Index: include/clang-c/Index.h =================================================================== --- include/clang-c/Index.h +++ include/clang-c/Index.h @@ -4626,6 +4626,19 @@ } CXCodeCompleteResults; /** + * \brief Retrieve a cursor corresponding to the completion result at the given index. + * + * \param result The results in which to look for the cursor. + * \param index The index into the CXCompletionResult array in CXCodeCompleteResults. + * + * \returns The cursor that represents the completion result at the given index, + * or a null cursor when the result does not represent a cursor. This + * will happen e.g. for language keywords. + */ +CINDEX_LINKAGE CXCursor +clang_getCompletionCursor(CXCodeCompleteResults *Results, int Index); + +/** * \brief Flags that can be passed to \c clang_codeCompleteAt() to * modify its behavior. * Index: tools/libclang/CIndexCodeCompletion.cpp =================================================================== --- tools/libclang/CIndexCodeCompletion.cpp +++ tools/libclang/CIndexCodeCompletion.cpp @@ -308,6 +308,9 @@ /// \brief A string containing the Objective-C selector entered thus far for a /// message send. std::string Selector; + + /// \brief the list of cursors for the results + SmallVector Cursors; }; } // end anonymous namespace @@ -540,16 +543,36 @@ CodeCompletionResult *Results, unsigned NumResults) override { StoredResults.reserve(StoredResults.size() + NumResults); + AllocatedResults.Cursors.reserve(AllocatedResults.Cursors.size() + NumResults); for (unsigned I = 0; I != NumResults; ++I) { + auto& Result = Results[I]; CodeCompletionString *StoredCompletion - = Results[I].CreateCodeCompletionString(S, Context, getAllocator(), + = Result.CreateCodeCompletionString(S, Context, getAllocator(), getCodeCompletionTUInfo(), includeBriefComments()); CXCompletionResult R; - R.CursorKind = Results[I].CursorKind; + R.CursorKind = Result.CursorKind; R.CompletionString = StoredCompletion; StoredResults.push_back(R); + + CXCursor cursor = clang_getNullCursor(); + switch (Result.Kind) { + case CodeCompletionResult::RK_Pattern: + case CodeCompletionResult::RK_Declaration: + if (auto Declaration = Result.Declaration) + cursor = cxcursor::MakeCXCursor(Declaration, *TU); + break; + case CodeCompletionResult::RK_Macro: + // TODO: build the CXCursor that represents the Resul.Macro + // I have no idea how to get the MacroDefinitionRecord + // corresponding to the IdentifierInfo + break; + case CodeCompletionResult::RK_Keyword: + // not representable by a cursor + break; + } + AllocatedResults.Cursors.push_back(cursor); } enum CodeCompletionContext::Kind contextKind = Context.getKind(); @@ -616,9 +639,11 @@ OverloadCandidate *Candidates, unsigned NumCandidates) override { StoredResults.reserve(StoredResults.size() + NumCandidates); + AllocatedResults.Cursors.reserve(AllocatedResults.Cursors.size() + NumCandidates); for (unsigned I = 0; I != NumCandidates; ++I) { + const auto& Candidate = Candidates[I]; CodeCompletionString *StoredCompletion - = Candidates[I].CreateSignatureString(CurrentArg, S, getAllocator(), + = Candidate.CreateSignatureString(CurrentArg, S, getAllocator(), getCodeCompletionTUInfo(), includeBriefComments()); @@ -626,6 +651,10 @@ R.CursorKind = CXCursor_OverloadCandidate; R.CompletionString = StoredCompletion; StoredResults.push_back(R); + + auto FunctionDecl = Candidate.getFunction(); + CXCursor cursor = FunctionDecl ? cxcursor::MakeCXCursor(FunctionDecl, *TU) : clang_getNullCursor(); + AllocatedResults.Cursors.push_back(cursor); } } @@ -995,4 +1024,15 @@ unsigned NumResults) { std::stable_sort(Results, Results + NumResults, OrderCompletionResults()); } + + CXCursor clang_getCompletionCursor(CXCodeCompleteResults *ResultsIn, int Index) + { + if (!ResultsIn || Index >= ResultsIn->NumResults) + return clang_getNullCursor(); + + AllocatedCXCodeCompleteResults *Results + = static_cast(ResultsIn); + + return Results->Cursors[Index]; + } } Index: tools/libclang/libclang.exports =================================================================== --- tools/libclang/libclang.exports +++ tools/libclang/libclang.exports @@ -314,3 +314,4 @@ clang_VirtualFileOverlay_dispose clang_VirtualFileOverlay_setCaseSensitivity clang_VirtualFileOverlay_writeToBuffer +clang_getCompletionCursor \ No newline at end of file