From: Erik Verbruggen Date: Fri, 14 Oct 2011 15:31:08 +0000 (+0000) Subject: Added clang_getCompletionAnnotation and clang_getCompletionNumAnnotations to X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6164ea1d75385b6fc3c19e5ab9bb686298436a5a;p=clang 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 3df1670f10..1320145a89 100644 --- a/include/clang-c/Index.h +++ b/include/clang-c/Index.h @@ -3281,8 +3281,7 @@ clang_getCompletionChunkText(CXCompletionString completion_string, * \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, @@ -3320,6 +3319,33 @@ clang_getCompletionPriority(CXCompletionString completion_string); CINDEX_LINKAGE enum CXAvailabilityKind 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 a20468e20b..9e2d60d3e0 100644 --- a/include/clang/Sema/CodeCompleteConsumer.h +++ b/include/clang/Sema/CodeCompleteConsumer.h @@ -428,19 +428,23 @@ public: 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 @@ public: /// \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 @@ private: /// \brief The chunks stored in this string. SmallVector Chunks; + + SmallVector Annotations; public: CodeCompletionBuilder(CodeCompletionAllocator &Allocator) @@ -560,6 +572,8 @@ public: /// \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 ab699382e6..de87b80ff4 100644 --- a/lib/Sema/CodeCompleteConsumer.cpp +++ b/lib/Sema/CodeCompleteConsumer.cpp @@ -190,14 +190,36 @@ CodeCompletionString::Chunk::CreateCurrentParameter( 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(this + 1); for (unsigned I = 0; I != NumChunks; ++I) StoredChunks[I] = Chunks[I]; + + const char **StoredAnnotations = reinterpret_cast(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(end())[AnnotationNr]; + else + return 0; +} + + std::string CodeCompletionString::getAsString() const { std::string Result; llvm::raw_string_ostream OS(Result); @@ -244,11 +266,13 @@ const char *CodeCompletionAllocator::CopyString(Twine String) { 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 *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 56b351c4cf..405d626ae9 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -2424,6 +2424,12 @@ CodeCompletionResult::CreateCodeCompletionString(Sema &S, 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(*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 0000000000..afa8d9ed66 --- /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 063c4adc90..2a3584b892 100644 --- a/tools/c-index-test/c-index-test.c +++ b/tools/c-index-test/c-index-test.c @@ -1033,6 +1033,7 @@ void print_completion_result(CXCompletionResult *completion_result, 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 @@ void print_completion_result(CXCompletionResult *completion_result, 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 3ce0d245cf..c19b340492 100644 --- a/tools/libclang/CIndexCodeCompletion.cpp +++ b/tools/libclang/CIndexCodeCompletion.cpp @@ -203,6 +203,20 @@ clang_getCompletionAvailability(CXCompletionString completion_string) { : 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 68c0ad5c27..989ed837ea 100644 --- a/tools/libclang/libclang.exports +++ b/tools/libclang/libclang.exports @@ -54,9 +54,11 @@ clang_getCanonicalCursor clang_getCanonicalType clang_getClangVersion clang_getCompletionAvailability +clang_getCompletionAnnotation clang_getCompletionChunkCompletionString clang_getCompletionChunkKind clang_getCompletionChunkText +clang_getCompletionNumAnnotations clang_getCompletionPriority clang_getCursor clang_getCursorAvailability