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 | |
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
-rw-r--r-- | lib/Sema/SemaCodeComplete.cpp | 84 | ||||
-rw-r--r-- | test/Index/complete-at-exprstmt.m | 3 |
2 files changed, 82 insertions, 5 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); diff --git a/test/Index/complete-at-exprstmt.m b/test/Index/complete-at-exprstmt.m index 4a2f1527f9..e8efc3cf46 100644 --- a/test/Index/complete-at-exprstmt.m +++ b/test/Index/complete-at-exprstmt.m @@ -1,6 +1,6 @@ /* The run lines are below, because this test is line- and column-number sensitive. */ -@interface MyClass { } +@interface MyClass { int ivar; } - (int)myMethod:(int)arg; @end @@ -31,6 +31,7 @@ // CHECK-CC3: ParmDecl:{ResultType int}{TypedText arg} // CHECK-CC3: TypedefDecl:{TypedText Class} // CHECK-CC3: TypedefDecl:{TypedText id} +// CHECK-CC3: ObjCIvarDecl:{ResultType int}{TypedText ivar} // CHECK-CC3: ObjCInterfaceDecl:{TypedText MyClass} // CHECK-CC3: TypedefDecl:{TypedText SEL} // CHECK-CC3: NotImplemented:{ResultType MyClass *}{TypedText self} |