From e775457c4ede090c31de56fe20e5c59b6fe46b95 Mon Sep 17 00:00:00 2001 From: Ivan Donchevskii Date: Thu, 17 May 2018 11:50:03 +0200 Subject: [backported/clang-7][libclang] Optionally add code completion results for arrow instead of dot -------------------------------------------------------------------------- * https://reviews.llvm.org/D46862 -------------------------------------------------------------------------- Follow up for https://reviews.llvm.org/D41537 - libclang part is extracted into this review Change-Id: Ib166eb7b8675be605c81330df0c5f342942815ce Reviewed-by: Ivan Donchevskii --- include/clang-c/Index.h | 87 ++++++++++++++++++++++++++++++- include/clang/Basic/SourceManager.h | 12 +++++ include/clang/Sema/CodeCompleteConsumer.h | 50 +++++++++--------- test/Index/complete-arrow-dot.cpp | 54 +++++++++++++++++++ tools/c-index-test/c-index-test.c | 46 ++++++++++++++-- tools/libclang/CIndex.cpp | 36 +++++++++++++ tools/libclang/CIndexCodeCompletion.cpp | 57 ++++++++++++++++++-- tools/libclang/libclang.exports | 3 ++ 8 files changed, 313 insertions(+), 32 deletions(-) create mode 100644 test/Index/complete-arrow-dot.cpp diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h index d06c82a4db..41534f68e6 100644 --- a/include/clang-c/Index.h +++ b/include/clang-c/Index.h @@ -36,6 +36,7 @@ #define CINDEX_VERSION_HAS_ISINVALIDECL_BACKPORTED #define CINDEX_VERSION_HAS_PRETTYDECL_BACKPORTED #define CINDEX_VERSION_HAS_LIMITSKIPFUNCTIONBODIESTOPREAMBLE_BACKPORTED +#define CINDEX_VERSION_HAS_COMPLETION_FIXITS_BACKPORTED #define CINDEX_VERSION_ENCODE(major, minor) ( \ ((major) * 10000) \ @@ -4737,6 +4738,20 @@ typedef struct { void *ptr_data; } CXToken; +/** + * \brief Get the raw lexical token starting with the given location. + * + * \param TU the translation unit whose text is being tokenized. + * + * \param Location the source location with which the token starts. + * + * \returns The token starting with the given location or NULL if no such tokens + * exist. The returned pointer must be freed with clang_disposeTokens before the + * translation unit is destroyed. + */ +CINDEX_LINKAGE CXToken *clang_getToken(CXTranslationUnit TU, + CXSourceLocation Location); + /** * \brief Determine the kind of the given token. */ @@ -5232,6 +5247,70 @@ typedef struct { unsigned NumResults; } CXCodeCompleteResults; +/** + * \brief Retrieve the number of fix-its for the given completion string. + * + * Calling this makes sense only if CXCodeComplete_IncludeCompletionsWithFixIts + * option was set. + * + * \param results The structure keeping all completion results + * + * \param completion_index The index of the completion + * + * \return The number of fix-its which must be applied before the completion at + * completion_index can be applied + */ +CINDEX_LINKAGE unsigned +clang_getCompletionNumFixIts(CXCodeCompleteResults *results, + unsigned completion_index); + +/** + * \brief Fix-its that *must* be applied before inserting the text for the + * corresponding completion. + * + * By default, clang_codeCompleteAt() only returns completions with empty + * fix-its. Extra completions with non-empty fix-its should be explicitly + * requested by setting CXCodeComplete_IncludeCompletionsWithFixIts. + * + * For the clients to be able to compute position of the cursor after applying + * fix-its, the following conditions are guaranteed to hold for + * replacement_range of the stored fix-its: + * - Ranges in the fix-its are guaranteed to never contain the completion + * point (or identifier under completion point, if any) inside them, except + * at the start or at the end of the range. + * - If a fix-it range starts or ends with completion point (or starts or + * ends after the identifier under completion point), it will contain at + * least one character. It allows to unambiguously recompute completion + * point after applying the fix-it. + * + * The intuition is that provided fix-its change code around the identifier we + * complete, but are not allowed to touch the identifier itself or the + * completion point. One example of completions with corrections are the ones + * replacing '.' with '->' and vice versa: + * + * std::unique_ptr> vec_ptr; + * In 'vec_ptr.^', one of the completions is 'push_back', it requires + * replacing '.' with '->'. + * In 'vec_ptr->^', one of the completions is 'release', it requires + * replacing '->' with '.'. + * + * \param results The structure keeping all completion results + * + * \param completion_index The index of the completion + * + * \param fixit_index The index of the fix-it for the completion at + * completion_index + * + * \param replacement_range The fix-it range that must be replaced before the + * completion at completion_index can be applied + * + * \returns The fix-it string that must replace the code at replacement_range + * before the completion at completion_index can be applied + */ +CINDEX_LINKAGE CXString clang_getCompletionFixIt( + CXCodeCompleteResults *results, unsigned completion_index, + unsigned fixit_index, CXSourceRange *replacement_range); + /** * \brief Flags that can be passed to \c clang_codeCompleteAt() to * modify its behavior. @@ -5256,7 +5335,13 @@ enum CXCodeComplete_Flags { * \brief Whether to include brief documentation within the set of code * completions returned. */ - CXCodeComplete_IncludeBriefComments = 0x04 + CXCodeComplete_IncludeBriefComments = 0x04, + + /** + * \brief Whether to include completions with small + * fix-its, e.g. change '.' to '->' on member access, etc. + */ + CXCodeComplete_IncludeCompletionsWithFixIts = 0x10 }; /** diff --git a/include/clang/Basic/SourceManager.h b/include/clang/Basic/SourceManager.h index 397ad2e77f..80e277384c 100644 --- a/include/clang/Basic/SourceManager.h +++ b/include/clang/Basic/SourceManager.h @@ -1137,6 +1137,18 @@ public: /// be used by clients. SourceLocation getImmediateSpellingLoc(SourceLocation Loc) const; + /// Form a SourceLocation from a FileID and Offset pair. + SourceLocation getComposedLoc(FileID FID, unsigned Offset) const { + bool Invalid = false; + const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &Invalid); + if (Invalid) + return SourceLocation(); + + unsigned GlobalOffset = Entry.getOffset() + Offset; + return Entry.isFile() ? SourceLocation::getFileLoc(GlobalOffset) + : SourceLocation::getMacroLoc(GlobalOffset); + } + /// \brief Decompose the specified location into a raw FileID + Offset pair. /// /// The first element is the FileID, the second is the offset from the diff --git a/include/clang/Sema/CodeCompleteConsumer.h b/include/clang/Sema/CodeCompleteConsumer.h index 720a150f51..002f93ade2 100644 --- a/include/clang/Sema/CodeCompleteConsumer.h +++ b/include/clang/Sema/CodeCompleteConsumer.h @@ -680,30 +680,33 @@ public: /// \brief The availability of this result. CXAvailabilityKind Availability; - /// \brief FixIts that *must* be applied before inserting the text for the - /// corresponding completion item. + ///\brief Fix-its that *must* be applied before inserting the text for the + /// corresponding completion. /// - /// Completion items with non-empty fixits will not be returned by default, - /// they should be explicitly requested by setting - /// CompletionOptions::IncludeFixIts. For the editors to be able to - /// compute position of the cursor for the completion item itself, the - /// following conditions are guaranteed to hold for RemoveRange of the stored - /// fixits: - /// - Ranges in the fixits are guaranteed to never contain the completion + /// By default, CodeCompletionBuilder only returns completions with empty + /// fix-its. Extra completions with non-empty fix-its should be explicitly + /// requested by setting CompletionOptions::IncludeFixIts. + /// + /// For the clients to be able to compute position of the cursor after + /// applying fix-its, the following conditions are guaranteed to hold for + /// RemoveRange of the stored fix-its: + /// - Ranges in the fix-its are guaranteed to never contain the completion /// point (or identifier under completion point, if any) inside them, except /// at the start or at the end of the range. - /// - If a fixit range starts or ends with completion point (or starts or + /// - If a fix-it range starts or ends with completion point (or starts or /// ends after the identifier under completion point), it will contain at /// least one character. It allows to unambiguously recompute completion - /// point after applying the fixit. - /// The intuition is that provided fixits change code around the identifier we - /// complete, but are not allowed to touch the identifier itself or the - /// completion point. One example of completion items with corrections are the - /// ones replacing '.' with '->' and vice versa: + /// point after applying the fix-it. + /// + /// The intuition is that provided fix-its change code around the identifier + /// we complete, but are not allowed to touch the identifier itself or the + /// completion point. One example of completions with corrections are the ones + /// replacing '.' with '->' and vice versa: + /// /// std::unique_ptr> vec_ptr; - /// In 'vec_ptr.^', one of completion items is 'push_back', it requires + /// In 'vec_ptr.^', one of the completions is 'push_back', it requires /// replacing '.' with '->'. - /// In 'vec_ptr->^', one of completion items is 'release', it requires + /// In 'vec_ptr->^', one of the completions is 'release', it requires /// replacing '->' with '.'. std::vector FixIts; @@ -736,13 +739,12 @@ public: bool QualifierIsInformative = false, bool Accessible = true, std::vector FixIts = std::vector()) - : Declaration(Declaration), Priority(Priority), - StartParameter(0), Kind(RK_Declaration), - Availability(CXAvailability_Available), Hidden(false), - QualifierIsInformative(QualifierIsInformative), - StartsNestedNameSpecifier(false), AllParametersAreInformative(false), - DeclaringEntity(false), Qualifier(Qualifier), - FixIts(std::move(FixIts)) { + : Declaration(Declaration), Priority(Priority), StartParameter(0), + Kind(RK_Declaration), Availability(CXAvailability_Available), + FixIts(std::move(FixIts)), Hidden(false), + QualifierIsInformative(QualifierIsInformative), + StartsNestedNameSpecifier(false), AllParametersAreInformative(false), + DeclaringEntity(false), Qualifier(Qualifier) { //FIXME: Add assert to check FixIts range requirements. computeCursorKindAndAvailability(Accessible); } diff --git a/test/Index/complete-arrow-dot.cpp b/test/Index/complete-arrow-dot.cpp new file mode 100644 index 0000000000..fb5efbe6e6 --- /dev/null +++ b/test/Index/complete-arrow-dot.cpp @@ -0,0 +1,54 @@ +struct X { + void doSomething(); + + int field; +}; + +void X::doSomething() { + // RUN: c-index-test -code-completion-at=%s:10:8 %s | FileCheck %s + // RUN: env CINDEXTEST_COMPLETION_INCLUDE_FIXITS=1 c-index-test -code-completion-at=%s:10:8 %s | FileCheck -check-prefix=CHECK-WITH-CORRECTION %s + this.; +} + +void doSomething() { + // RUN: c-index-test -code-completion-at=%s:17:6 %s | FileCheck -check-prefix=CHECK-ARROW-TO-DOT %s + // RUN: env CINDEXTEST_COMPLETION_INCLUDE_FIXITS=1 c-index-test -code-completion-at=%s:17:6 %s | FileCheck -check-prefix=CHECK-ARROW-TO-DOT-WITH-CORRECTION %s + X x; + x-> +} + +// CHECK-NOT: CXXMethod:{ResultType void}{TypedText doSomething}{LeftParen (}{RightParen )} (34) (requires fix-it:{{.*}} +// CHECK-NOT: FieldDecl:{ResultType int}{TypedText field} (35) (requires fix-it:{{.*}} +// CHECK-NOT: CXXMethod:{ResultType X &}{TypedText operator=}{LeftParen (}{Placeholder const X &}{RightParen )} (79) (requires fix-it:{{.*}} +// CHECK-NOT: CXXMethod:{ResultType X &}{TypedText operator=}{LeftParen (}{Placeholder X &&}{RightParen )} (79) (requires fix-it:{{.*}} +// CHECK-NOT: StructDecl:{TypedText X}{Text ::} (75) (requires fix-it:{{.*}} +// CHECK-NOT: CXXDestructor:{ResultType void}{TypedText ~X}{LeftParen (}{RightParen )} (79) (requires fix-it:{{.*}} +// CHECK: Completion contexts: +// CHECK-NEXT: Dot member access + +// CHECK-WITH-CORRECTION: CXXMethod:{ResultType void}{TypedText doSomething}{LeftParen (}{RightParen )} (34) (requires fix-it:{{.*}} +// CHECK-WITH-CORRECTION-NEXT: FieldDecl:{ResultType int}{TypedText field} (35) (requires fix-it:{{.*}} +// CHECK-WITH-CORRECTION-NEXT: CXXMethod:{ResultType X &}{TypedText operator=}{LeftParen (}{Placeholder const X &}{RightParen )} (79) (requires fix-it:{{.*}} +// CHECK-WITH-CORRECTION-NEXT: CXXMethod:{ResultType X &}{TypedText operator=}{LeftParen (}{Placeholder X &&}{RightParen )} (79) (requires fix-it:{{.*}} +// CHECK-WITH-CORRECTION-NEXT: StructDecl:{TypedText X}{Text ::} (75) (requires fix-it:{{.*}} +// CHECK-WITH-CORRECTION-NEXT: CXXDestructor:{ResultType void}{TypedText ~X}{LeftParen (}{RightParen )} (79) (requires fix-it:{{.*}} +// CHECK-WITH-CORRECTION-NEXT: Completion contexts: +// CHECK-WITH-CORRECTION-NEXT: Dot member access + +// CHECK-ARROW-TO-DOT-NOT: CXXMethod:{ResultType void}{TypedText doSomething}{LeftParen (}{RightParen )} (34) (requires fix-it:{{.*}} +// CHECK-ARROW-TO-DOT-NOT: FieldDecl:{ResultType int}{TypedText field} (35) (requires fix-it:{{.*}} +// CHECK-ARROW-TO-DOT-NOT: CXXMethod:{ResultType X &}{TypedText operator=}{LeftParen (}{Placeholder const X &}{RightParen )} (79) (requires fix-it:{{.*}} +// CHECK-ARROW-TO-DOT-NOT: CXXMethod:{ResultType X &}{TypedText operator=}{LeftParen (}{Placeholder X &&}{RightParen )} (79) (requires fix-it:{{.*}} +// CHECK-ARROW-TO-DOT-NOT: StructDecl:{TypedText X}{Text ::} (75) (requires fix-it:{{.*}} +// CHECK-ARROW-TO-DOT-NOT: CXXDestructor:{ResultType void}{TypedText ~X}{LeftParen (}{RightParen )} (79) (requires fix-it:{{.*}} +// CHECK-ARROW-TO-DOT: Completion contexts: +// CHECK-ARROW-TO-DOT-NEXT: Unknown + +// CHECK-ARROW-TO-DOT-WITH-CORRECTION: CXXMethod:{ResultType void}{TypedText doSomething}{LeftParen (}{RightParen )} (34) (requires fix-it:{{.*}} +// CHECK-ARROW-TO-DOT-WITH-CORRECTION-NEXT: FieldDecl:{ResultType int}{TypedText field} (35) (requires fix-it:{{.*}} +// CHECK-ARROW-TO-DOT-WITH-CORRECTION-NEXT: CXXMethod:{ResultType X &}{TypedText operator=}{LeftParen (}{Placeholder const X &}{RightParen )} (79) (requires fix-it:{{.*}} +// CHECK-ARROW-TO-DOT-WITH-CORRECTION-NEXT: CXXMethod:{ResultType X &}{TypedText operator=}{LeftParen (}{Placeholder X &&}{RightParen )} (79) (requires fix-it:{{.*}} +// CHECK-ARROW-TO-DOT-WITH-CORRECTION-NEXT: StructDecl:{TypedText X}{Text ::} (75) (requires fix-it:{{.*}} +// CHECK-ARROW-TO-DOT-WITH-CORRECTION-NEXT: CXXDestructor:{ResultType void}{TypedText ~X}{LeftParen (}{RightParen )} (79) (requires fix-it:{{.*}} +// CHECK-ARROW-TO-DOT-WITH-CORRECTION-NEXT: Completion contexts: +// CHECK-ARROW-TO-DOT-WITH-CORRECTION-NEXT: Arrow member access diff --git a/tools/c-index-test/c-index-test.c b/tools/c-index-test/c-index-test.c index bcc42ad994..45348a21c4 100644 --- a/tools/c-index-test/c-index-test.c +++ b/tools/c-index-test/c-index-test.c @@ -2254,8 +2254,33 @@ static void print_completion_string(CXCompletionString completion_string, } -static void print_completion_result(CXCompletionResult *completion_result, +static void print_line_column(CXSourceLocation location, FILE *file) { + unsigned line, column; + clang_getExpansionLocation(location, NULL, &line, &column, NULL); + fprintf(file, "%d:%d", line, column); +} + +static void print_token_range(CXTranslationUnit translation_unit, + CXSourceLocation start, FILE *file) { + CXToken *token = clang_getToken(translation_unit, start); + + fprintf(file, "{"); + if (token != NULL) { + CXSourceRange token_range = clang_getTokenExtent(translation_unit, *token); + print_line_column(clang_getRangeStart(token_range), file); + fprintf(file, "-"); + print_line_column(clang_getRangeEnd(token_range), file); + clang_disposeTokens(translation_unit, token, 1); + } + + fprintf(file, "}"); +} + +static void print_completion_result(CXTranslationUnit translation_unit, + CXCodeCompleteResults *completion_results, + unsigned index, FILE *file) { + CXCompletionResult *completion_result = completion_results->Results + index; CXString ks = clang_getCursorKindSpelling(completion_result->CursorKind); unsigned annotationCount; enum CXCursorKind ParentKind; @@ -2263,6 +2288,7 @@ static void print_completion_result(CXCompletionResult *completion_result, CXString BriefComment; CXString Annotation; const char *BriefCommentCString; + unsigned i; fprintf(file, "%s:", clang_getCString(ks)); clang_disposeString(ks); @@ -2323,7 +2349,19 @@ static void print_completion_result(CXCompletionResult *completion_result, fprintf(file, "(brief comment: %s)", BriefCommentCString); } clang_disposeString(BriefComment); - + + for (i = 0; i < clang_getCompletionNumFixIts(completion_results, index); + ++i) { + CXSourceRange correction_range; + CXString FixIt = clang_getCompletionFixIt(completion_results, index, i, + &correction_range); + fprintf(file, " (requires fix-it: "); + print_token_range(translation_unit, clang_getRangeStart(correction_range), + file); + fprintf(file, " to \"%s\")", clang_getCString(FixIt)); + clang_disposeString(FixIt); + } + fprintf(file, "\n"); } @@ -2420,6 +2458,8 @@ int perform_code_completion(int argc, const char **argv, int timing_only) { completionOptions |= CXCodeComplete_IncludeCodePatterns; if (getenv("CINDEXTEST_COMPLETION_BRIEF_COMMENTS")) completionOptions |= CXCodeComplete_IncludeBriefComments; + if (getenv("CINDEXTEST_COMPLETION_INCLUDE_FIXITS")) + completionOptions |= CXCodeComplete_IncludeCompletionsWithFixIts; if (timing_only) input += strlen("-code-completion-timing="); @@ -2484,7 +2524,7 @@ int perform_code_completion(int argc, const char **argv, int timing_only) { clang_sortCodeCompletionResults(results->Results, results->NumResults); for (i = 0; i != n; ++i) - print_completion_result(results->Results + i, stdout); + print_completion_result(TU, results, i, stdout); } n = clang_codeCompleteGetNumDiagnostics(results); for (i = 0; i != n; ++i) { diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index 884206d9d1..c44c72e2ed 100644 --- a/tools/libclang/CIndex.cpp +++ b/tools/libclang/CIndex.cpp @@ -6642,6 +6642,42 @@ static void getTokens(ASTUnit *CXXUnit, SourceRange Range, } while (Lex.getBufferLocation() < EffectiveBufferEnd); } +CXToken *clang_getToken(CXTranslationUnit TU, CXSourceLocation Location) { + LOG_FUNC_SECTION { + *Log << TU << ' ' << Location; + } + + if (isNotUsableTU(TU)) { + LOG_BAD_TU(TU); + return nullptr; + } + + ASTUnit *CXXUnit = cxtu::getASTUnit(TU); + if (!CXXUnit) + return nullptr; + + SourceLocation Begin = cxloc::translateSourceLocation(Location); + if (Begin.isInvalid()) + return nullptr; + SourceManager &SM = CXXUnit->getSourceManager(); + std::pair DecomposedEnd = SM.getDecomposedLoc(Begin); + DecomposedEnd.second += Lexer::MeasureTokenLength(Begin, SM, CXXUnit->getLangOpts()); + + SourceLocation End = SM.getComposedLoc(DecomposedEnd.first, DecomposedEnd.second); + + SmallVector CXTokens; + getTokens(CXXUnit, SourceRange(Begin, End), CXTokens); + + if (CXTokens.empty()) + return nullptr; + + CXTokens.resize(1); + CXToken *Token = (CXToken *)malloc(sizeof(CXToken)); + + memmove(Token, CXTokens.data(), sizeof(CXToken)); + return Token; +} + void clang_tokenize(CXTranslationUnit TU, CXSourceRange Range, CXToken **Tokens, unsigned *NumTokens) { LOG_FUNC_SECTION { diff --git a/tools/libclang/CIndexCodeCompletion.cpp b/tools/libclang/CIndexCodeCompletion.cpp index d4af0870c0..32fc7325f0 100644 --- a/tools/libclang/CIndexCodeCompletion.cpp +++ b/tools/libclang/CIndexCodeCompletion.cpp @@ -16,6 +16,7 @@ #include "CIndexDiagnostic.h" #include "CLog.h" #include "CXCursor.h" +#include "CXSourceLocation.h" #include "CXString.h" #include "CXTranslationUnit.h" #include "clang/AST/Decl.h" @@ -302,10 +303,53 @@ struct AllocatedCXCodeCompleteResults : public CXCodeCompleteResults { /// \brief A string containing the Objective-C selector entered thus far for a /// message send. std::string Selector; + + /// \brief Vector of fix-its for each completion result that *must* be applied + /// before that result for the corresponding completion item. + std::vector> FixItsVector; }; } // end anonymous namespace +unsigned clang_getCompletionNumFixIts(CXCodeCompleteResults *results, + unsigned completion_index) { + AllocatedCXCodeCompleteResults *allocated_results = (AllocatedCXCodeCompleteResults *)results; + + if (!allocated_results || allocated_results->FixItsVector.size() <= completion_index) + return 0; + + return static_cast(allocated_results->FixItsVector[completion_index].size()); +} + +CXString clang_getCompletionFixIt(CXCodeCompleteResults *results, + unsigned completion_index, + unsigned fixit_index, + CXSourceRange *replacement_range) { + AllocatedCXCodeCompleteResults *allocated_results = (AllocatedCXCodeCompleteResults *)results; + + if (!allocated_results || allocated_results->FixItsVector.size() <= completion_index) { + if (replacement_range) + *replacement_range = clang_getNullRange(); + return cxstring::createNull(); + } + + ArrayRef FixIts = allocated_results->FixItsVector[completion_index]; + if (FixIts.size() <= fixit_index) { + if (replacement_range) + *replacement_range = clang_getNullRange(); + return cxstring::createNull(); + } + + const FixItHint &FixIt = FixIts[fixit_index]; + if (replacement_range) { + *replacement_range = cxloc::translateSourceRange( + *allocated_results->SourceMgr, allocated_results->LangOpts, + FixIt.RemoveRange); + } + + return cxstring::createRef(FixIt.CodeToInsert.c_str()); +} + /// \brief Tracks the number of code-completion result objects that are /// currently active. /// @@ -531,8 +575,10 @@ namespace { CodeCompletionResult *Results, unsigned NumResults) override { StoredResults.reserve(StoredResults.size() + NumResults); + if (includeFixIts()) + AllocatedResults.FixItsVector.reserve(NumResults); for (unsigned I = 0; I != NumResults; ++I) { - CodeCompletionString *StoredCompletion + CodeCompletionString *StoredCompletion = Results[I].CreateCodeCompletionString(S, Context, getAllocator(), getCodeCompletionTUInfo(), includeBriefComments()); @@ -541,8 +587,10 @@ namespace { R.CursorKind = Results[I].CursorKind; R.CompletionString = StoredCompletion; StoredResults.push_back(R); + if (includeFixIts()) + AllocatedResults.FixItsVector.emplace_back(std::move(Results[I].FixIts)); } - + enum CodeCompletionContext::Kind contextKind = Context.getKind(); AllocatedResults.ContextKind = contextKind; @@ -643,13 +691,13 @@ clang_codeCompleteAt_Impl(CXTranslationUnit TU, const char *complete_filename, ArrayRef unsaved_files, unsigned options) { bool IncludeBriefComments = options & CXCodeComplete_IncludeBriefComments; + bool IncludeFixIts = options & CXCodeComplete_IncludeCompletionsWithFixIts; #ifdef UDP_CODE_COMPLETION_LOGGER #ifdef UDP_CODE_COMPLETION_LOGGER_PORT const llvm::TimeRecord &StartTime = llvm::TimeRecord::getCurrentTime(); #endif #endif - bool EnableLogging = getenv("LIBCLANG_CODE_COMPLETION_LOGGING") != nullptr; if (cxtu::isNotUsableTU(TU)) { @@ -689,6 +737,7 @@ clang_codeCompleteAt_Impl(CXTranslationUnit TU, const char *complete_filename, // Create a code-completion consumer to capture the results. CodeCompleteOptions Opts; Opts.IncludeBriefComments = IncludeBriefComments; + Opts.IncludeFixIts = IncludeFixIts; CaptureCompletionResults Capture(Opts, *Results, &TU); // Perform completion. @@ -962,7 +1011,7 @@ namespace { = (CodeCompletionString *)XR.CompletionString; CodeCompletionString *Y = (CodeCompletionString *)YR.CompletionString; - + SmallString<256> XBuffer; StringRef XText = GetTypedName(X, XBuffer); SmallString<256> YBuffer; diff --git a/tools/libclang/libclang.exports b/tools/libclang/libclang.exports index 67e4b4334b..8deca1cb50 100644 --- a/tools/libclang/libclang.exports +++ b/tools/libclang/libclang.exports @@ -170,6 +170,8 @@ clang_getCompletionBriefComment clang_getCompletionChunkCompletionString clang_getCompletionChunkKind clang_getCompletionChunkText +clang_getCompletionNumFixIts +clang_getCompletionFixIt clang_getCompletionNumAnnotations clang_getCompletionParent clang_getCompletionPriority @@ -259,6 +261,7 @@ clang_getSpecializedCursorTemplate clang_getSpellingLocation clang_getTUResourceUsageName clang_getTemplateCursorKind +clang_getToken clang_getTokenExtent clang_getTokenKind clang_getTokenLocation -- cgit v1.2.3