libclang の Python binding を使用する 〜 unsave_files 編〜

前回は Index に関する記事を書きました。
今回は存在しないファイルをパースする方法について書きます。
Vim などを使用しているとわかりやすいんですが、ファイルは存在していないけど編集中のソースファイルをパースしたい、という事はあると思います。
そんな時は unsave_files を利用することで指定した文字列をファイルとして認識させてパースを行うことができます。

[ソース]

import sys
import clang.cindex


source = """\
#include <tuple>

int
main(){
    X x;
    x.value = 10;

    X2 x2;
    x2.value = 3.14f;
}
"""


index = clang.cindex.Index.create()

tu = index.parse("test.cpp",
    unsaved_files = [ ("test.cpp", source) ]
)

for file in tu.get_includes():
    print file.source.name
    print file.include.name

[出力]

test.cpp
c:/MinGW/lib/gcc/mingw32/4.6.2/include/c++\tuple
c:/MinGW/lib/gcc/mingw32/4.6.2/include/c++\tuple
c:/MinGW/lib/gcc/mingw32/4.6.2/include/c++\bits/c++0x_warning.h


上記のように unsaved_files に対してファイル名とそのファイルの文字列をタプルのリストで渡します。
あとはファイルを直接パースした時と同じようにそのファイル名で結果が返ってきます。


[複数のファイルを設定する]

次のようにしてヘッダーファイルも unsaved_files に設定することもできます。

[ソース]

import sys
import clang.cindex


source = """\
#include "test.h"

int
main(){
    X x;
    x.value = 10;

    X2 x2;
    x2.value = 3.14f;
}
"""


header = """
#include <tuple>

struct X{
    int value;
};

"""


index = clang.cindex.Index.create()

tu = index.parse("test.cpp",
    unsaved_files = [ ("test.cpp", source), ("./test.h", header) ]
)

for file in tu.get_includes():
    print file.source.name
    print file.include.name

[出力]

test.cpp
./test.h
./test.h
c:/MinGW/lib/gcc/mingw32/4.6.2/include/c++\tuple
c:/MinGW/lib/gcc/mingw32/4.6.2/include/c++\tuple
c:/MinGW/lib/gcc/mingw32/4.6.2/include/c++\bits/c++0x_warning.h


次は diagnostics について書く予定です。

[Clang]

  • clang++ (LLVM) 3.3