diff options
author | Ivan Donchevskii <ivan.donchevskii@qt.io> | 2018-06-13 12:37:08 +0000 |
---|---|---|
committer | Ivan Donchevskii <ivan.donchevskii@qt.io> | 2018-06-13 12:37:08 +0000 |
commit | 85ffa9bd6b859e0aab115e6985678252669e8e65 (patch) | |
tree | 69d0eb253cfb78301c444d1bb7f6c8fec5424acd /tools | |
parent | 46c05521ad97b165353fa285cd56d51bcb4a1327 (diff) | |
download | clang-85ffa9bd6b859e0aab115e6985678252669e8e65.tar.gz |
[libclang] Optionally add code completion results for arrow instead of dot
Follow up for D41537 - libclang part.
Differential Revision: https://reviews.llvm.org/D46862
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334593 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'tools')
-rw-r--r-- | tools/c-index-test/c-index-test.c | 50 | ||||
-rw-r--r-- | tools/libclang/CIndex.cpp | 36 | ||||
-rw-r--r-- | tools/libclang/CIndexCodeCompletion.cpp | 57 | ||||
-rw-r--r-- | tools/libclang/libclang.exports | 27 |
4 files changed, 149 insertions, 21 deletions
diff --git a/tools/c-index-test/c-index-test.c b/tools/c-index-test/c-index-test.c index e86a20b55b..50fea5ba8b 100644 --- a/tools/c-index-test/c-index-test.c +++ b/tools/c-index-test/c-index-test.c @@ -2270,8 +2270,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; @@ -2339,7 +2364,20 @@ static void print_completion_result(CXCompletionResult *completion_result, fprintf(file, "(brief comment: %s)", BriefCommentCString); } clang_disposeString(BriefComment); - + + unsigned i; + 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"); } @@ -2438,6 +2476,8 @@ int perform_code_completion(int argc, const char **argv, int timing_only) { completionOptions |= CXCodeComplete_IncludeBriefComments; if (getenv("CINDEXTEST_COMPLETION_SKIP_PREAMBLE")) completionOptions |= CXCodeComplete_SkipPreamble; + if (getenv("CINDEXTEST_COMPLETION_INCLUDE_FIXITS")) + completionOptions |= CXCodeComplete_IncludeCompletionsWithFixIts; if (timing_only) input += strlen("-code-completion-timing="); @@ -2502,7 +2542,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) { @@ -4402,10 +4442,10 @@ static void printLocation(CXSourceLocation L) { CXFile File; CXString FileName; unsigned line, column, offset; - + clang_getExpansionLocation(L, &File, &line, &column, &offset); FileName = clang_getFileName(File); - + fprintf(stderr, "%s:%d:%d", clang_getCString(FileName), line, column); clang_disposeString(FileName); } diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index 32f6ca994b..1c291d7332 100644 --- a/tools/libclang/CIndex.cpp +++ b/tools/libclang/CIndex.cpp @@ -6652,6 +6652,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 NULL; + } + + ASTUnit *CXXUnit = cxtu::getASTUnit(TU); + if (!CXXUnit) + return NULL; + + SourceLocation Begin = cxloc::translateSourceLocation(Location); + if (Begin.isInvalid()) + return NULL; + SourceManager &SM = CXXUnit->getSourceManager(); + std::pair<FileID, unsigned> DecomposedEnd = SM.getDecomposedLoc(Begin); + DecomposedEnd.second += Lexer::MeasureTokenLength(Begin, SM, CXXUnit->getLangOpts()); + + SourceLocation End = SM.getComposedLoc(DecomposedEnd.first, DecomposedEnd.second); + + SmallVector<CXToken, 32> CXTokens; + getTokens(CXXUnit, SourceRange(Begin, End), CXTokens); + + if (CXTokens.empty()) + return NULL; + + CXTokens.resize(1); + CXToken *Token = static_cast<CXToken *>(llvm::safe_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 73f8da1e1b..f49f9763c3 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 { /// A string containing the Objective-C selector entered thus far for a /// message send. std::string Selector; + + /// Vector of fix-its for each completion result that *must* be applied + /// before that result for the corresponding completion item. + std::vector<std::vector<FixItHint>> 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<unsigned>(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<FixItHint> 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()); +} + /// 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; @@ -644,13 +692,13 @@ clang_codeCompleteAt_Impl(CXTranslationUnit TU, const char *complete_filename, unsigned options) { bool IncludeBriefComments = options & CXCodeComplete_IncludeBriefComments; bool SkipPreamble = options & CXCodeComplete_SkipPreamble; + 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)) { @@ -691,6 +739,7 @@ clang_codeCompleteAt_Impl(CXTranslationUnit TU, const char *complete_filename, CodeCompleteOptions Opts; Opts.IncludeBriefComments = IncludeBriefComments; Opts.LoadExternal = !SkipPreamble; + Opts.IncludeFixIts = IncludeFixIts; CaptureCompletionResults Capture(Opts, *Results, &TU); // Perform completion. @@ -964,7 +1013,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 222598dcd9..a185bc7845 100644 --- a/tools/libclang/libclang.exports +++ b/tools/libclang/libclang.exports @@ -168,12 +168,14 @@ clang_getClangVersion clang_getCompletionAnnotation clang_getCompletionAvailability clang_getCompletionBriefComment -clang_getCompletionChunkCompletionString -clang_getCompletionChunkKind -clang_getCompletionChunkText -clang_getCompletionNumAnnotations -clang_getCompletionParent -clang_getCompletionPriority +clang_getCompletionChunkCompletionString
+clang_getCompletionChunkKind
+clang_getCompletionChunkText
+clang_getCompletionNumFixIts
+clang_getCompletionFixIt
+clang_getCompletionNumAnnotations
+clang_getCompletionParent
+clang_getCompletionPriority
clang_getCursor clang_getCursorAvailability clang_getCursorCompletionString @@ -257,12 +259,13 @@ clang_getRemappingsFromFileList clang_getResultType clang_getSkippedRanges clang_getSpecializedCursorTemplate -clang_getSpellingLocation -clang_getTUResourceUsageName -clang_getTemplateCursorKind -clang_getTokenExtent -clang_getTokenKind -clang_getTokenLocation +clang_getSpellingLocation
+clang_getTUResourceUsageName
+clang_getTemplateCursorKind
+clang_getToken
+clang_getTokenExtent
+clang_getTokenKind
+clang_getTokenLocation
clang_getTokenSpelling clang_getTranslationUnitCursor clang_getTranslationUnitSpelling |