diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-09-22 23:15:58 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-09-22 23:15:58 +0000 |
commit | 0563c2677cfc20c9450342ddc53aa96971671c71 (patch) | |
tree | e138bc16b594890110ace09d87ee7c53870c8178 /lib/Sema/SemaCodeComplete.cpp | |
parent | 16d81b8db39593b5f1a38b077757272a09c12da8 (diff) |
Tweak the code-completion results ranking and formation, so that
members found in base classes have the same ranking as members found
in derived classes. However, we will introduce an informative note for
members found in base classes, showing (as a nested-name-specifier)
the qualification to name the base class, to make it clear which
members are from bases.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@82586 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaCodeComplete.cpp')
-rw-r--r-- | lib/Sema/SemaCodeComplete.cpp | 63 |
1 files changed, 40 insertions, 23 deletions
diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index b19fda216d..f57480e13e 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -197,8 +197,8 @@ void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) { // Look through using declarations. if (UsingDecl *Using = dyn_cast<UsingDecl>(R.Declaration)) - return MaybeAddResult(Result(Using->getTargetDecl(), R.Rank, R.Qualifier), - CurContext); + MaybeAddResult(Result(Using->getTargetDecl(), R.Rank, R.Qualifier), + CurContext); // Handle each declaration in an overload set separately. if (OverloadedFunctionDecl *Ovl @@ -281,6 +281,7 @@ void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) { I->second.first)) { // Note that this result was hidden. R.Hidden = true; + R.QualifierIsInformative = false; if (!R.Qualifier) R.Qualifier = getRequiredQualification(SemaRef.Context, @@ -300,6 +301,18 @@ void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) { if (!AllDeclsFound.insert(CanonDecl)) return; + // If this result is supposed to have an informative qualifier, add one. + if (R.QualifierIsInformative && !R.Qualifier) { + DeclContext *Ctx = R.Declaration->getDeclContext(); + if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx)) + R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, Namespace); + else if (TagDecl *Tag = dyn_cast<TagDecl>(Ctx)) + R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, false, + SemaRef.Context.getTypeDeclType(Tag).getTypePtr()); + else + R.QualifierIsInformative = false; + } + // Insert this result into the set of results and into the current shadow // map. SMap.insert(std::make_pair(R.Declaration->getDeclName(), @@ -398,9 +411,7 @@ static DeclContext *findOuterContext(Scope *S) { /// /// \param Ctx the declaration context from which we will gather results. /// -/// \param InitialRank the initial rank given to results in this declaration -/// context. Larger rank values will be used for, e.g., members found in -/// base classes. +/// \param Rank the rank given to results in this declaration context. /// /// \param Visited the set of declaration contexts that have already been /// visited. Declaration contexts will only be visited once. @@ -408,18 +419,22 @@ static DeclContext *findOuterContext(Scope *S) { /// \param Results the result set that will be extended with any results /// found within this declaration context (and, for a C++ class, its bases). /// +/// \param InBaseClass whether we are in a base class. +/// /// \returns the next higher rank value, after considering all of the /// names within this declaration context. static unsigned CollectMemberLookupResults(DeclContext *Ctx, - unsigned InitialRank, + unsigned Rank, DeclContext *CurContext, llvm::SmallPtrSet<DeclContext *, 16> &Visited, - ResultBuilder &Results) { + ResultBuilder &Results, + bool InBaseClass = false) { // Make sure we don't visit the same context twice. if (!Visited.insert(Ctx->getPrimaryContext())) - return InitialRank; + return Rank; // Enumerate all of the results in this context. + typedef CodeCompleteConsumer::Result Result; Results.EnterNewScope(); for (DeclContext *CurCtx = Ctx->getPrimaryContext(); CurCtx; CurCtx = CurCtx->getNextContext()) { @@ -427,13 +442,11 @@ static unsigned CollectMemberLookupResults(DeclContext *Ctx, DEnd = CurCtx->decls_end(); D != DEnd; ++D) { if (NamedDecl *ND = dyn_cast<NamedDecl>(*D)) - Results.MaybeAddResult(CodeCompleteConsumer::Result(ND, InitialRank), - CurContext); + Results.MaybeAddResult(Result(ND, Rank, 0, InBaseClass), CurContext); } } // Traverse the contexts of inherited classes. - unsigned NextRank = InitialRank; if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Ctx)) { for (CXXRecordDecl::base_class_iterator B = Record->bases_begin(), BEnd = Record->bases_end(); @@ -468,19 +481,15 @@ static unsigned CollectMemberLookupResults(DeclContext *Ctx, // c->A::member // Collect results from this base class (and its bases). - NextRank = std::max(NextRank, - CollectMemberLookupResults(Record->getDecl(), - InitialRank + 1, - CurContext, - Visited, - Results)); + CollectMemberLookupResults(Record->getDecl(), Rank, CurContext, Visited, + Results, /*InBaseClass=*/true); } } // FIXME: Look into base classes in Objective-C! Results.ExitScope(); - return NextRank; + return Rank + 1; } /// \brief Collect the results of searching for members within the given @@ -735,6 +744,7 @@ static void AddTemplateParameterChunks(ASTContext &Context, /// provided nested-name-specifier is non-NULL. void AddQualifierToCompletionString(CodeCompletionString *Result, NestedNameSpecifier *Qualifier, + bool QualifierIsInformative, ASTContext &Context) { if (!Qualifier) return; @@ -744,7 +754,10 @@ void AddQualifierToCompletionString(CodeCompletionString *Result, llvm::raw_string_ostream OS(PrintedNNS); Qualifier->print(OS, Context.PrintingPolicy); } - Result->AddTextChunk(PrintedNNS.c_str()); + if (QualifierIsInformative) + Result->AddInformativeChunk(PrintedNNS.c_str()); + else + Result->AddTextChunk(PrintedNNS.c_str()); } /// \brief If possible, create a new code completion string for the given @@ -762,7 +775,8 @@ CodeCompleteConsumer::Result::CreateCodeCompletionString(Sema &S) { if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) { CodeCompletionString *Result = new CodeCompletionString; - AddQualifierToCompletionString(Result, Qualifier, S.Context); + AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative, + S.Context); Result->AddTextChunk(Function->getNameAsString().c_str()); Result->AddTextChunk("("); AddFunctionParameterChunks(S.Context, Function, Result); @@ -772,7 +786,8 @@ CodeCompleteConsumer::Result::CreateCodeCompletionString(Sema &S) { if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND)) { CodeCompletionString *Result = new CodeCompletionString; - AddQualifierToCompletionString(Result, Qualifier, S.Context); + AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative, + S.Context); FunctionDecl *Function = FunTmpl->getTemplatedDecl(); Result->AddTextChunk(Function->getNameAsString().c_str()); @@ -825,7 +840,8 @@ CodeCompleteConsumer::Result::CreateCodeCompletionString(Sema &S) { if (TemplateDecl *Template = dyn_cast<TemplateDecl>(ND)) { CodeCompletionString *Result = new CodeCompletionString; - AddQualifierToCompletionString(Result, Qualifier, S.Context); + AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative, + S.Context); Result->AddTextChunk(Template->getNameAsString().c_str()); Result->AddTextChunk("<"); AddTemplateParameterChunks(S.Context, Template, Result); @@ -835,7 +851,8 @@ CodeCompleteConsumer::Result::CreateCodeCompletionString(Sema &S) { if (Qualifier) { CodeCompletionString *Result = new CodeCompletionString; - AddQualifierToCompletionString(Result, Qualifier, S.Context); + AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative, + S.Context); Result->AddTextChunk(ND->getNameAsString().c_str()); return Result; } |