aboutsummaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorIvan Donchevskii <ivan.donchevskii@qt.io>2018-06-13 12:37:08 +0000
committerIvan Donchevskii <ivan.donchevskii@qt.io>2018-06-13 12:37:08 +0000
commit85ffa9bd6b859e0aab115e6985678252669e8e65 (patch)
tree69d0eb253cfb78301c444d1bb7f6c8fec5424acd /tools
parent46c05521ad97b165353fa285cd56d51bcb4a1327 (diff)
downloadclang-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.c50
-rw-r--r--tools/libclang/CIndex.cpp36
-rw-r--r--tools/libclang/CIndexCodeCompletion.cpp57
-rw-r--r--tools/libclang/libclang.exports27
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