libclang の Python binding を使用する 〜 詳細な型名の取得 〜

前回はカーソル位置の型名を取得する方法について書きました。
今回は詳細な型名を取得する方法について書きます。


さて、前回使用した方法では例えば以下のように typedef されている場合、typedef した型名を取得します。

typedef int hoge;
hoge h;
// h は hoge 型として取得する


今回は typedef した型名ではなくて typedef された型名を取得する方法についてのコードを書きます。

[ソース]

# -*- coding: utf-8 -*
import clang.cindex
from clang.cindex import Cursor
from clang.cindex import Config
from clang.cindex import _CXString
from clang.cindex import Type


# Clang 3.3 の python binding を使用した場合、
# lib に設定されていないので
# ユーザ側で設定しておく必要がある
conf = Config()
conf.lib.clang_getTypeSpelling.restype  = _CXString
conf.lib.clang_getTypeSpelling.argtypes = [Type]
conf.lib.clang_getTypeSpelling.errcheck = _CXString.from_result

def type_spelling(type):
    return conf.lib.clang_getTypeSpelling(type)


# source code
source = """
template<typename T>
struct X{};

int
main(){
    typedef int hoge;
    hoge h;
    h;
    
    typedef X<hoge> X_hoge;
    X_hoge x;
    x;
}
"""

index = clang.cindex.Index.create()

tu = index.parse("test.cpp", args = ["-std=c++11 "], unsaved_files = [ ("test.cpp", source)])

# Cursor の生成
def make_cursor(file, line, col):
    # location を定義
    location = tu.get_location(file, (line, col))
    
    # location からその位置の cursor を取得
    return Cursor.from_location(tu, location)

# Type の情報を出力
def print_type(type):
    print "kind : %s" % type.kind
    print "spelling : %s" % type_spelling(type)
    print "canonical_spelling : %s" % type_spelling(type.get_canonical())


cursor1 = make_cursor("test.cpp", 8, 5)
print_type(cursor1.type)

cursor2 = make_cursor("test.cpp", 12, 5)
print_type(cursor2.type)

[出力]

kind : TypeKind.TYPEDEF
spelling : hoge
canonical_spelling : int
kind : TypeKind.TYPEDEF
spelling : X_hoge
canonical_spelling : X<int>


元の型名を取得するには type.get_canonical() で取得する事ができます。
これは Type を返すので後は type_spelling() 等で型名を取得する事ができます。
C++ だとテンプレートがすごいことになっている型があるので詳細を調べたい場合は有効だと思います。

[Clang]

  • clang++ (LLVM) 3.3


[2014-03-01 22:33]