From ba1030698dbc276db86b11c5329a1edee8a1805e Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Tue, 27 Mar 2012 23:34:16 +0000 Subject: Introduce a new libclang API to determine the parent context of a code completion item. For example, if the code completion itself represents a declaration in a namespace (say, std::vector), then this API retrieves the cursor kind and name of the namespace (std). Implements . git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@153545 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/CodeCompleteConsumer.cpp | 89 +++++++++++++++++++++++++++++++++++---- 1 file changed, 80 insertions(+), 9 deletions(-) (limited to 'lib/Sema/CodeCompleteConsumer.cpp') diff --git a/lib/Sema/CodeCompleteConsumer.cpp b/lib/Sema/CodeCompleteConsumer.cpp index caebe3a221..dbc9b0080a 100644 --- a/lib/Sema/CodeCompleteConsumer.cpp +++ b/lib/Sema/CodeCompleteConsumer.cpp @@ -192,9 +192,12 @@ CodeCompletionString::CodeCompletionString(const Chunk *Chunks, unsigned Priority, CXAvailabilityKind Availability, const char **Annotations, - unsigned NumAnnotations) - : NumChunks(NumChunks), NumAnnotations(NumAnnotations) - , Priority(Priority), Availability(Availability) + unsigned NumAnnotations, + CXCursorKind ParentKind, + StringRef ParentName) + : NumChunks(NumChunks), NumAnnotations(NumAnnotations), + Priority(Priority), Availability(Availability), ParentKind(ParentKind), + ParentName(ParentName) { assert(NumChunks <= 0xffff); assert(NumAnnotations <= 0xffff); @@ -272,7 +275,8 @@ CodeCompletionString *CodeCompletionBuilder::TakeString() { CodeCompletionString *Result = new (Mem) CodeCompletionString(Chunks.data(), Chunks.size(), Priority, Availability, - Annotations.data(), Annotations.size()); + Annotations.data(), Annotations.size(), + ParentKind, ParentName); Chunks.clear(); return Result; } @@ -311,6 +315,70 @@ void CodeCompletionBuilder::AddChunk(CodeCompletionString::ChunkKind CK, Chunks.push_back(Chunk(CK, Text)); } +void CodeCompletionBuilder::addParentContext(DeclContext *DC) { + if (DC->isTranslationUnit()) { + ParentKind = CXCursor_TranslationUnit; + return; + } + + if (DC->isFunctionOrMethod()) + return; + + NamedDecl *ND = dyn_cast(DC); + if (!ND) + return; + + ParentKind = getCursorKindForDecl(ND); + + // Check whether we've already cached the parent name. + StringRef &CachedParentName = Allocator.getParentNames()[DC]; + if (!CachedParentName.empty()) { + ParentName = CachedParentName; + return; + } + + // Find the interesting names. + llvm::SmallVector Contexts; + while (DC && !DC->isFunctionOrMethod()) { + if (NamedDecl *ND = dyn_cast(DC)) { + if (ND->getIdentifier()) + Contexts.push_back(DC); + } + + DC = DC->getParent(); + } + + { + llvm::SmallString<128> S; + llvm::raw_svector_ostream OS(S); + bool First = true; + for (unsigned I = Contexts.size(); I != 0; --I) { + if (First) + First = false; + else { + OS << "::"; + } + + DeclContext *CurDC = Contexts[I-1]; + if (ObjCCategoryImplDecl *CatImpl = dyn_cast(CurDC)) + CurDC = CatImpl->getCategoryDecl(); + + if (ObjCCategoryDecl *Cat = dyn_cast(CurDC)) { + ObjCInterfaceDecl *Interface = Cat->getClassInterface(); + if (!Interface) + return; + + OS << Interface->getName() << '(' << Cat->getName() << ')'; + } else { + OS << cast(CurDC)->getName(); + } + } + + ParentName = Allocator.CopyString(OS.str()); + CachedParentName = ParentName; + } +} + unsigned CodeCompletionResult::getPriorityFromDecl(NamedDecl *ND) { if (!ND) return CCP_Unlikely; @@ -444,6 +512,13 @@ static AvailabilityResult getDeclAvailability(Decl *D) { void CodeCompletionResult::computeCursorKindAndAvailability(bool Accessible) { switch (Kind) { + case RK_Pattern: + if (!Declaration) { + // Do nothing: Patterns can come with cursor kinds! + break; + } + // Fall through + case RK_Declaration: { // Set the availability based on attributes. switch (getDeclAvailability(Declaration)) { @@ -488,11 +563,7 @@ void CodeCompletionResult::computeCursorKindAndAvailability(bool Accessible) { case RK_Keyword: Availability = CXAvailability_Available; CursorKind = CXCursor_NotImplemented; - break; - - case RK_Pattern: - // Do nothing: Patterns can come with cursor kinds! - break; + break; } if (!Accessible) -- cgit v1.2.3-18-g5258