diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp index 2dab6ada7a2f..3e8f749a054a 100644 --- a/clang/lib/Sema/SemaCodeComplete.cpp +++ b/clang/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(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(R.Declaration) && + cast(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(Ctx)) + R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, Namespace); + else if (TagDecl *Tag = dyn_cast(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(ND)) + return true; + return ND->getIdentifierNamespace() & IDNS; } @@ -609,6 +668,23 @@ bool ResultBuilder::IsMember(NamedDecl *ND) const { isa(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/clang/test/Index/complete-at-exprstmt.m b/clang/test/Index/complete-at-exprstmt.m index 4a2f1527f9c7..e8efc3cf46f1 100644 --- a/clang/test/Index/complete-at-exprstmt.m +++ b/clang/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}