diff options
author | Douglas Gregor <dgregor@apple.com> | 2010-01-14 01:09:38 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2010-01-14 01:09:38 +0000 |
commit | 1ca6ae865cc632e9f626faacd4937e666eb05f6b (patch) | |
tree | 3aea0e9df199ff5fc5303f57422d6000bca18c91 /lib/Sema/SemaCodeComplete.cpp | |
parent | e81e15ed0c31f828104b339ceb66648d1c815a8b (diff) |
Switch code-completion for ordinary names over to the new(ish)
LookupVisibleDecls, unifying the name lookup mechanisms used by code
completion and typo correction. Aside from the software-engineering
improvements, this makes code-completion see through using directives
and see ivars when performing unqualified name lookup in an
Objective-C instance method.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@93397 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaCodeComplete.cpp')
-rw-r--r-- | lib/Sema/SemaCodeComplete.cpp | 84 |
1 files changed, 80 insertions, 4 deletions
diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index 2dab6ada7a..3e8f749a05 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -11,6 +11,7 @@ // //===----------------------------------------------------------------------===// #include "Sema.h" +#include "Lookup.h" #include "clang/Sema/CodeCompleteConsumer.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" @@ -150,11 +151,21 @@ namespace { /// of the shadow maps), or replace an existing result (for, e.g., a /// redeclaration). /// - /// \param R the result to add (if it is unique). + /// \param CurContext the result to add (if it is unique). /// /// \param R the context in which this result will be named. void MaybeAddResult(Result R, DeclContext *CurContext = 0); + /// \brief Add a new result to this result set, where we already know + /// the hiding declation (if any). + /// + /// \param R the result to add (if it is unique). + /// + /// \param CurContext the context in which this result will be named. + /// + /// \param Hiding the declaration that hides the result. + void AddResult(Result R, DeclContext *CurContext, NamedDecl *Hiding); + /// \brief Enter into a new scope. void EnterNewScope(); @@ -505,6 +516,52 @@ void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) { Results.push_back(R); } +void ResultBuilder::AddResult(Result R, DeclContext *CurContext, + NamedDecl *Hiding) { + assert(R.Kind == Result::RK_Declaration && + "Only declaration results are supported"); + + // Look through using declarations. + if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) { + AddResult(Result(Using->getTargetDecl(), R.Qualifier), CurContext, Hiding); + return; + } + + if (!isInterestingDecl(R.Declaration)) + return; + + if (Hiding && CheckHiddenResult(R, CurContext, Hiding)) + return; + + // Make sure that any given declaration only shows up in the result set once. + if (!AllDeclsFound.insert(R.Declaration->getCanonicalDecl())) + return; + + // If the filter is for nested-name-specifiers, then this result starts a + // nested-name-specifier. + if ((Filter == &ResultBuilder::IsNestedNameSpecifier) || + (Filter == &ResultBuilder::IsMember && + isa<CXXRecordDecl>(R.Declaration) && + cast<CXXRecordDecl>(R.Declaration)->isInjectedClassName())) + R.StartsNestedNameSpecifier = true; + + // If this result is supposed to have an informative qualifier, add one. + if (R.QualifierIsInformative && !R.Qualifier && + !R.StartsNestedNameSpecifier) { + 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. + Results.push_back(R); +} + /// \brief Enter into a new scope. void ResultBuilder::EnterNewScope() { ShadowMaps.push_back(ShadowMap()); @@ -527,7 +584,9 @@ bool ResultBuilder::IsOrdinaryName(NamedDecl *ND) const { unsigned IDNS = Decl::IDNS_Ordinary; if (SemaRef.getLangOptions().CPlusPlus) IDNS |= Decl::IDNS_Tag; - + else if (SemaRef.getLangOptions().ObjC1 && isa<ObjCIvarDecl>(ND)) + return true; + return ND->getIdentifierNamespace() & IDNS; } @@ -609,6 +668,23 @@ bool ResultBuilder::IsMember(NamedDecl *ND) const { isa<ObjCPropertyDecl>(ND); } +namespace { + /// \brief Visible declaration consumer that adds a code-completion result + /// for each visible declaration. + class CodeCompletionDeclConsumer : public VisibleDeclConsumer { + ResultBuilder &Results; + DeclContext *CurContext; + + public: + CodeCompletionDeclConsumer(ResultBuilder &Results, DeclContext *CurContext) + : Results(Results), CurContext(CurContext) { } + + virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding) { + Results.AddResult(ND, CurContext, Hiding); + } + }; +} + // Find the next outer declaration context corresponding to this scope. static DeclContext *findOuterContext(Scope *S) { for (S = S->getParent(); S; S = S->getParent()) @@ -1970,8 +2046,8 @@ void Sema::CodeCompleteOrdinaryName(Scope *S, break; } - CollectLookupResults(S, Context.getTranslationUnitDecl(), CurContext, - Results); + CodeCompletionDeclConsumer Consumer(Results, CurContext); + LookupVisibleDecls(S, LookupOrdinaryName, Consumer); Results.EnterNewScope(); AddOrdinaryNameResults(CompletionContext, S, *this, Results); |