Added clang_getCompletionAnnotation and clang_getCompletionNumAnnotations to
retrieve annotations from completion string.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@141953 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h
index 3df1670..1320145 100644
--- a/include/clang-c/Index.h
+++ b/include/clang-c/Index.h
@@ -3281,8 +3281,7 @@
* \param chunk_number the 0-based index of the chunk in the completion string.
*
* \returns the completion string associated with the chunk at index
- * \c chunk_number, or NULL if that chunk is not represented by a completion
- * string.
+ * \c chunk_number.
*/
CINDEX_LINKAGE CXCompletionString
clang_getCompletionChunkCompletionString(CXCompletionString completion_string,
@@ -3321,6 +3320,33 @@
clang_getCompletionAvailability(CXCompletionString completion_string);
/**
+ * \brief Retrieve the number of annotations associated with the given
+ * completion string.
+ *
+ * \param completion_string the completion string to query.
+ *
+ * \returns the number of annotations associated with the given completion
+ * string.
+ */
+CINDEX_LINKAGE unsigned
+clang_getCompletionNumAnnotations(CXCompletionString completion_string);
+
+/**
+ * \brief Retrieve the annotation associated with the given completion string.
+ *
+ * \param completion_string the completion string to query.
+ *
+ * \param annotation_number the 0-based index of the annotation of the
+ * completion string.
+ *
+ * \returns annotation string associated with the completion at index
+ * \c annotation_number, or a NULL string if that annotation is not available.
+ */
+CINDEX_LINKAGE CXString
+clang_getCompletionAnnotation(CXCompletionString completion_string,
+ unsigned annotation_number);
+
+/**
* \brief Retrieve a completion string for an arbitrary declaration or macro
* definition cursor.
*
diff --git a/include/clang/Sema/CodeCompleteConsumer.h b/include/clang/Sema/CodeCompleteConsumer.h
index a20468e..9e2d60d 100644
--- a/include/clang/Sema/CodeCompleteConsumer.h
+++ b/include/clang/Sema/CodeCompleteConsumer.h
@@ -428,19 +428,23 @@
private:
/// \brief The number of chunks stored in this string.
- unsigned NumChunks;
+ unsigned NumChunks : 16;
+ /// \brief The number of annotations for this code-completion result.
+ unsigned NumAnnotations : 16;
+
/// \brief The priority of this code-completion string.
unsigned Priority : 30;
/// \brief The availability of this code-completion result.
unsigned Availability : 2;
-
+
CodeCompletionString(const CodeCompletionString &); // DO NOT IMPLEMENT
CodeCompletionString &operator=(const CodeCompletionString &); // DITTO
CodeCompletionString(const Chunk *Chunks, unsigned NumChunks,
- unsigned Priority, CXAvailabilityKind Availability);
+ unsigned Priority, CXAvailabilityKind Availability,
+ const char **Annotations, unsigned NumAnnotations);
~CodeCompletionString() { }
friend class CodeCompletionBuilder;
@@ -464,8 +468,14 @@
/// \brief Retrieve the priority of this code completion result.
unsigned getPriority() const { return Priority; }
- /// \brief Reteirve the availability of this code completion result.
+ /// \brief Retrieve the availability of this code completion result.
unsigned getAvailability() const { return Availability; }
+
+ /// \brief Retrieve the number of annotations for this code completion result.
+ unsigned getAnnotationCount() const;
+
+ /// \brief Retrieve the annotation string specified by \c AnnotationNr.
+ const char *getAnnotation(unsigned AnnotationNr) const;
/// \brief Retrieve a string representation of the code completion string,
/// which is mainly useful for debugging.
@@ -504,6 +514,8 @@
/// \brief The chunks stored in this string.
SmallVector<Chunk, 4> Chunks;
+
+ SmallVector<const char *, 2> Annotations;
public:
CodeCompletionBuilder(CodeCompletionAllocator &Allocator)
@@ -560,6 +572,8 @@
/// \brief Add a new chunk.
void AddChunk(Chunk C) { Chunks.push_back(C); }
+
+ void AddAnnotation(const char *A) { Annotations.push_back(A); }
};
/// \brief Captures a result of code completion.
diff --git a/lib/Sema/CodeCompleteConsumer.cpp b/lib/Sema/CodeCompleteConsumer.cpp
index ab69938..de87b80 100644
--- a/lib/Sema/CodeCompleteConsumer.cpp
+++ b/lib/Sema/CodeCompleteConsumer.cpp
@@ -190,14 +190,36 @@
CodeCompletionString::CodeCompletionString(const Chunk *Chunks,
unsigned NumChunks,
unsigned Priority,
- CXAvailabilityKind Availability)
- : NumChunks(NumChunks), Priority(Priority), Availability(Availability)
+ CXAvailabilityKind Availability,
+ const char **Annotations,
+ unsigned NumAnnotations)
+ : NumChunks(NumChunks), NumAnnotations(NumAnnotations)
+ , Priority(Priority), Availability(Availability)
{
+ assert(NumChunks <= 0xffff);
+ assert(NumAnnotations <= 0xffff);
+
Chunk *StoredChunks = reinterpret_cast<Chunk *>(this + 1);
for (unsigned I = 0; I != NumChunks; ++I)
StoredChunks[I] = Chunks[I];
+
+ const char **StoredAnnotations = reinterpret_cast<const char **>(StoredChunks + NumChunks);
+ for (unsigned I = 0; I != NumAnnotations; ++I)
+ StoredAnnotations[I] = Annotations[I];
}
+unsigned CodeCompletionString::getAnnotationCount() const {
+ return NumAnnotations;
+}
+
+const char *CodeCompletionString::getAnnotation(unsigned AnnotationNr) const {
+ if (AnnotationNr < NumAnnotations)
+ return reinterpret_cast<const char * const*>(end())[AnnotationNr];
+ else
+ return 0;
+}
+
+
std::string CodeCompletionString::getAsString() const {
std::string Result;
llvm::raw_string_ostream OS(Result);
@@ -244,11 +266,13 @@
CodeCompletionString *CodeCompletionBuilder::TakeString() {
void *Mem = Allocator.Allocate(
- sizeof(CodeCompletionString) + sizeof(Chunk) * Chunks.size(),
+ sizeof(CodeCompletionString) + sizeof(Chunk) * Chunks.size()
+ + sizeof(const char *) * Annotations.size(),
llvm::alignOf<CodeCompletionString>());
CodeCompletionString *Result
= new (Mem) CodeCompletionString(Chunks.data(), Chunks.size(),
- Priority, Availability);
+ Priority, Availability,
+ Annotations.data(), Annotations.size());
Chunks.clear();
return Result;
}
diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp
index 56b351c..405d626 100644
--- a/lib/Sema/SemaCodeComplete.cpp
+++ b/lib/Sema/SemaCodeComplete.cpp
@@ -2424,6 +2424,12 @@
Result.AddTextChunk("::");
return Result.TakeString();
}
+
+ for (Decl::attr_iterator i = ND->attr_begin(); i != ND->attr_end(); ++i) {
+ if (AnnotateAttr *Attr = dyn_cast_or_null<AnnotateAttr>(*i)) {
+ Result.AddAnnotation(Result.getAllocator().CopyString(Attr->getAnnotation()));
+ }
+ }
AddResultTypeChunk(S.Context, Policy, ND, Result);
diff --git a/test/Index/complete-with-annotations.cpp b/test/Index/complete-with-annotations.cpp
new file mode 100644
index 0000000..afa8d9e
--- /dev/null
+++ b/test/Index/complete-with-annotations.cpp
@@ -0,0 +1,23 @@
+class X {
+ void doSomething();
+
+ int field __attribute((annotate("one"), annotate("two"), annotate("three")));
+
+public __attribute__((annotate("some annotation"))):
+ void func2();
+ int member2 __attribute__((annotate("another annotation")));
+};
+
+void X::doSomething() {
+ // RUN: c-index-test -code-completion-at=%s:13:9 %s | FileCheck %s
+ this->;
+}
+
+// CHECK: CXXMethod:{ResultType void}{TypedText doSomething}{LeftParen (}{RightParen )} (34)
+// CHECK: FieldDecl:{ResultType int}{TypedText field} (35) ("three", "two", "one")
+// CHECK: CXXMethod:{ResultType void}{TypedText func2}{LeftParen (}{RightParen )} (34) ("some annotation")
+// CHECK: FieldDecl:{ResultType int}{TypedText member2} (35) ("another annotation", "some annotation")
+// CHECK: CXXMethod:{ResultType X &}{TypedText operator=}{LeftParen (}{Placeholder const X &}{RightParen )} (34)
+// CHECK: ClassDecl:{TypedText X}{Text ::} (75)
+// CHECK: CXXDestructor:{ResultType void}{TypedText ~X}{LeftParen (}{RightParen )} (34)
+
diff --git a/tools/c-index-test/c-index-test.c b/tools/c-index-test/c-index-test.c
index 063c4ad..2a3584b 100644
--- a/tools/c-index-test/c-index-test.c
+++ b/tools/c-index-test/c-index-test.c
@@ -1033,6 +1033,7 @@
CXClientData client_data) {
FILE *file = (FILE *)client_data;
CXString ks = clang_getCursorKindSpelling(completion_result->CursorKind);
+ unsigned annotationCount;
fprintf(file, "%s:", clang_getCString(ks));
clang_disposeString(ks);
@@ -1056,6 +1057,22 @@
fprintf(file, " (inaccessible)");
break;
}
+
+ annotationCount = clang_getCompletionNumAnnotations(
+ completion_result->CompletionString);
+ if (annotationCount) {
+ unsigned i;
+ fprintf(file, " (");
+ for (i = 0; i < annotationCount; ++i) {
+ if (i != 0)
+ fprintf(file, ", ");
+ fprintf(file, "\"%s\"",
+ clang_getCString(clang_getCompletionAnnotation(
+ completion_result->CompletionString, i)));
+ }
+ fprintf(file, ")");
+ }
+
fprintf(file, "\n");
}
diff --git a/tools/libclang/CIndexCodeCompletion.cpp b/tools/libclang/CIndexCodeCompletion.cpp
index 3ce0d24..c19b340 100644
--- a/tools/libclang/CIndexCodeCompletion.cpp
+++ b/tools/libclang/CIndexCodeCompletion.cpp
@@ -203,6 +203,20 @@
: CXAvailability_Available;
}
+unsigned clang_getCompletionNumAnnotations(CXCompletionString completion_string)
+{
+ CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;
+ return CCStr ? CCStr->getAnnotationCount() : 0;
+}
+
+CXString clang_getCompletionAnnotation(CXCompletionString completion_string,
+ unsigned annotation_number) {
+ CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;
+ return CCStr ? createCXString(CCStr->getAnnotation(annotation_number))
+ : createCXString((const char *) 0);
+}
+
+
/// \brief The CXCodeCompleteResults structure we allocate internally;
/// the client only sees the initial CXCodeCompleteResults structure.
struct AllocatedCXCodeCompleteResults : public CXCodeCompleteResults {
diff --git a/tools/libclang/libclang.exports b/tools/libclang/libclang.exports
index 68c0ad5..989ed83 100644
--- a/tools/libclang/libclang.exports
+++ b/tools/libclang/libclang.exports
@@ -54,9 +54,11 @@
clang_getCanonicalType
clang_getClangVersion
clang_getCompletionAvailability
+clang_getCompletionAnnotation
clang_getCompletionChunkCompletionString
clang_getCompletionChunkKind
clang_getCompletionChunkText
+clang_getCompletionNumAnnotations
clang_getCompletionPriority
clang_getCursor
clang_getCursorAvailability