diff options
author | Douglas Gregor <dgregor@apple.com> | 2012-03-27 23:34:16 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2012-03-27 23:34:16 +0000 |
commit | ba1030698dbc276db86b11c5329a1edee8a1805e (patch) | |
tree | 05795b249632407ea75e576411c56c9078255b80 /lib | |
parent | 2259286fc5c1514089b17ec93e26ca56ba8ac2b6 (diff) |
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
<rdar://problem/11121951>.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@153545 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/AST/Decl.cpp | 2 | ||||
-rw-r--r-- | lib/Sema/CodeCompleteConsumer.cpp | 89 | ||||
-rw-r--r-- | lib/Sema/SemaCodeComplete.cpp | 56 |
3 files changed, 103 insertions, 44 deletions
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 3b7113d354..e476bfb6f1 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -845,7 +845,7 @@ static LinkageInfo getLVForDecl(const NamedDecl *D, LVFlags Flags) { } std::string NamedDecl::getQualifiedNameAsString() const { - return getQualifiedNameAsString(getASTContext().getLangOpts()); + return getQualifiedNameAsString(getASTContext().getPrintingPolicy()); } std::string NamedDecl::getQualifiedNameAsString(const PrintingPolicy &P) const { 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<NamedDecl>(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<DeclContext *, 2> Contexts; + while (DC && !DC->isFunctionOrMethod()) { + if (NamedDecl *ND = dyn_cast<NamedDecl>(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<ObjCCategoryImplDecl>(CurDC)) + CurDC = CatImpl->getCategoryDecl(); + + if (ObjCCategoryDecl *Cat = dyn_cast<ObjCCategoryDecl>(CurDC)) { + ObjCInterfaceDecl *Interface = Cat->getClassInterface(); + if (!Interface) + return; + + OS << Interface->getName() << '(' << Cat->getName() << ')'; + } else { + OS << cast<NamedDecl>(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) diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index b33c1697bf..3fd66ec042 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -2454,6 +2454,13 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx, if (Kind == RK_Pattern) { Pattern->Priority = Priority; Pattern->Availability = Availability; + + if (Declaration) { + Result.addParentContext(Declaration->getDeclContext()); + Pattern->ParentKind = Result.getParentKind(); + Pattern->ParentName = Result.getParentName(); + } + return Pattern; } @@ -2509,7 +2516,8 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx, assert(Kind == RK_Declaration && "Missed a result kind?"); NamedDecl *ND = Declaration; - + Result.addParentContext(ND->getDeclContext()); + if (StartsNestedNameSpecifier) { Result.AddTypedTextChunk( Result.getAllocator().CopyString(ND->getNameAsString())); @@ -3023,7 +3031,9 @@ static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext, Builder.AddChunk(CodeCompletionString::CK_RightParen); Results.AddResult(CodeCompletionResult(Builder.TakeString(), CCP_SuperCompletion, - CXCursor_CXXMethod)); + CXCursor_CXXMethod, + CXAvailability_Available, + Overridden)); Results.Ignore(Overridden); } } @@ -3342,28 +3352,8 @@ static void AddObjCProperties(ObjCContainerDecl *Container, Builder.AddTypedTextChunk( Results.getAllocator().CopyString(Name->getName())); - CXAvailabilityKind Availability = CXAvailability_Available; - switch (M->getAvailability()) { - case AR_Available: - case AR_NotYetIntroduced: - Availability = CXAvailability_Available; - break; - - case AR_Deprecated: - Availability = CXAvailability_Deprecated; - break; - - case AR_Unavailable: - Availability = CXAvailability_NotAvailable; - break; - } - - Results.MaybeAddResult(Result(Builder.TakeString(), - CCP_MemberDeclaration + CCD_MethodAsProperty, - M->isInstanceMethod() - ? CXCursor_ObjCInstanceMethodDecl - : CXCursor_ObjCClassMethodDecl, - Availability), + Results.MaybeAddResult(Result(Builder.TakeString(), *M, + CCP_MemberDeclaration + CCD_MethodAsProperty), CurContext); } } @@ -4028,7 +4018,8 @@ void Sema::CodeCompleteNamespaceDecl(Scope *S) { // namespace to the list of results. Results.EnterNewScope(); for (std::map<NamespaceDecl *, NamespaceDecl *>::iterator - NS = OrigToLatest.begin(), NSEnd = OrigToLatest.end(); + NS = OrigToLatest.begin(), + NSEnd = OrigToLatest.end(); NS != NSEnd; ++NS) Results.AddResult(CodeCompletionResult(NS->second, 0), CurContext, 0, false); @@ -4188,7 +4179,9 @@ void Sema::CodeCompleteConstructorInitializer(Decl *ConstructorD, Results.AddResult(CodeCompletionResult(Builder.TakeString(), SawLastInitializer? CCP_NextInitializer : CCP_MemberDeclaration, - CXCursor_MemberRef)); + CXCursor_MemberRef, + CXAvailability_Available, + *Field)); SawLastInitializer = false; } Results.ExitScope(); @@ -5057,10 +5050,8 @@ static ObjCMethodDecl *AddSuperSendCompletion(Sema &S, bool NeedSuperKeyword, } } - Results.AddResult(CodeCompletionResult(Builder.TakeString(), CCP_SuperCompletion, - SuperMethod->isInstanceMethod() - ? CXCursor_ObjCInstanceMethodDecl - : CXCursor_ObjCClassMethodDecl)); + Results.AddResult(CodeCompletionResult(Builder.TakeString(), SuperMethod, + CCP_SuperCompletion)); return SuperMethod; } @@ -6747,10 +6738,7 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, if (!M->second.second) Priority += CCD_InBaseClass; - Results.AddResult(Result(Builder.TakeString(), Priority, - Method->isInstanceMethod() - ? CXCursor_ObjCInstanceMethodDecl - : CXCursor_ObjCClassMethodDecl)); + Results.AddResult(Result(Builder.TakeString(), Method, Priority)); } // Add Key-Value-Coding and Key-Value-Observing accessor methods for all of |