9

libclang でコード補完を行う方法を理解しようとしています。「Thinking beyond the compiler」を見て、c-index-test を調べたところ、簡単なサンプル プログラムが見つかりました

私はそのプログラムをコンパイルし、このサンプル ファイルで実行しました。このサンプル ファイルは、ビデオのものと似ています。

struct List {
    int Data;
    struct List *Next;
};

int sumListNode(struct List *Node) {
    int result = 0;
    for (; Node; Node = Node->Next)
        result = result + Node->
}

void test() {
    sumLi
}

Node-> の後の最初の不完全なスペースでプログラムをポイントすると、いくつかの C キーワードが吐き出されますが、ビデオで言うように Next や Data は吐き出されません。

sumLi の後のスペースを指すと、同じ C キーワードが出力されます。sumLi に「s」が含まれる列を指定すると、sumListNode を出力できますが、それでも他のキーワードと同じ優先度値として割り当てられるため、実際にはすべてを出力するだけです。カーソルの下にあるものを読んで知的な推測をしようとする代わりに、そこに置くことができます。フラグメントの最後ではなく最初にカーソルを置くと、とにかく役立つことを期待して、ストローをつかんでいました。

libclang が提供できるデータの種類と、doxygen からの操作方法、および c-index-test をいじることから、多くのことを学びましたが、それを関連性のあるものにする方法を学んでいません。私が何かを扱うことができるようにデータ。

4

1 に答える 1

9

エラーが発生すると、clang がコード内で失われる可能性があるため、最初に、翻訳ユニットによる出力を印刷してみCXDiagnosticてください (これは、言及した非常に単純なケースではほとんどありません)。

第 2 に、libclang は行番号と列番号をこれまでとは異なる方法で定義している可能性があることに注意してください (つまり、テキスト エディターから行/列の情報を取得している場合は、列番号に 1 を追加する必要があるかもしれません)。 clang の定義と同期します)。

3 番目に、clang コンパイラ自体を使用して、コンパイル オプションと行/列情報の有効性をテストできます。このようにして、libclang ベースのコードに起因する不確実性を排除します。たとえば、次のコマンドラインを使用できます。

clang++ -cc1 -fsyntax-only -code-completion-at FILENAME:LINE:COL CLANG_ARGS

また、clang_codeCompleteAtはトークンの先頭でのみ呼び出されることを意図しており、すべての可能なトークンのリストを生成します。クライアントは、テキスト エディターに既に入力されている可能性のある部分トークンを使用して結果をフィルター処理します。

ドキュメントから(強調は私のものです):

翻訳単位の特定の場所でコード補完を実行します。

この関数は、ソース コード内の特定のファイル、行、および列でコード補完を実行し、補完のコンテキストに基づいて潜在的なコード スニペットを示唆する結果を提供します。コード補完の基本モデルは、Clang が完全なソース ファイルを解析し、コード補完が要求された場所まで構文チェックを実行することです。その時点で、特別なコード補完トークンがパーサーに渡されます。パーサーはこのトークンを認識し、C/Objective-C/C++ 文法の現在の位置と意味解析の状態に基づいて、どの補完を提供するかを決定します。これらの補完は、新しい CXCodeCompleteResults 構造を介して返されます。

コード補完自体は、ユーザーが句読点または空白を入力したときにクライアントによってトリガーされることを意図しており、その時点でコード補完の場所はカーソルと一致します。たとえば、p がポインターの場合、コード補完は p-> の "-" の後にトリガーされ、次に ">" の後にトリガーされる可能性があります。コード補完の場所が ">" の後ろにある場合、補完結果は、たとえば、"p" が指す構造体のメンバーを提供します。クライアントは、現在入力されているトークンの先頭にカーソルを置き、トークンの内容に基づいて結果をフィルタリングする責任があります. たとえば、式 p->get のコード補完を行う場合、クライアントは ">" の直後 (たとえば、"g" を指す) の場所をこのコード補完フックに提供する必要があります。次に、クライアントは現在のトークン テキスト ("get") に基づいて結果をフィルター処理し、"get" で始まる結果のみを表示できます。このインターフェイスの目的は、コード補完結果の比較的高いレイテンシーの取得を、より低いレイテンシーが必要な文字ごとの結果のフィルタリングから分離することです。

修正した 2 番目の例を取り上げます。

int main (int argc, char **argv) {
  int i = sumLi
  //      ^
}

コード補完は、マークされた位置 (つまり、トークンの先頭) で呼び出す必要があります。次に、Clang は、次のような結果の長いリストを提供できます。

  • argc
  • sumListNode(<# struct List *Node #>)

sumLi部分的に入力されたトークンに基づいてこのリストをフィルタリングし、関連する補完のみを保持するのはあなた次第です: sumListNode.

elisp を理解している場合、clang のソースには Emacs 用のオートコンプリート ライブラリが含まれています。これは、この 2 レベルの実装の良い例です。

trunk/utils/clang-completion-mode.el

于 2013-04-08T12:15:42.887 に答える