From 70c233591ad2f77a01c8a318283ae03010c64c8f Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Thu, 9 Dec 2010 21:44:02 +0000 Subject: [PATCH] Don't walk the translation unit context to produce protocol names when global code completions are disabled (e.g., because they are cached). Also, make sure that forward-declared protocols are visited when we look for all visible names within a declaration context. Previously, we would end up with duplicate completions for protocols. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@121416 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaCodeComplete.cpp | 43 ++++++++++++++++++++------------- lib/Sema/SemaLookup.cpp | 16 ++++++++++-- test/Index/complete-protocols.m | 4 ++- 3 files changed, 43 insertions(+), 20 deletions(-) diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index 6d40fb8d29..727dd7929c 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -4950,20 +4950,25 @@ static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext, void Sema::CodeCompleteObjCProtocolReferences(IdentifierLocPair *Protocols, unsigned NumProtocols) { ResultBuilder Results(*this, CodeCompletionContext::CCC_ObjCProtocolName); - Results.EnterNewScope(); - // Tell the result set to ignore all of the protocols we have - // already seen. - for (unsigned I = 0; I != NumProtocols; ++I) - if (ObjCProtocolDecl *Protocol = LookupProtocol(Protocols[I].first, - Protocols[I].second)) - Results.Ignore(Protocol); - - // Add all protocols. - AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, false, - Results); + if (CodeCompleter && CodeCompleter->includeGlobals()) { + Results.EnterNewScope(); + + // Tell the result set to ignore all of the protocols we have + // already seen. + // FIXME: This doesn't work when caching code-completion results. + for (unsigned I = 0; I != NumProtocols; ++I) + if (ObjCProtocolDecl *Protocol = LookupProtocol(Protocols[I].first, + Protocols[I].second)) + Results.Ignore(Protocol); + + // Add all protocols. + AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, false, + Results); - Results.ExitScope(); + Results.ExitScope(); + } + HandleCodeCompleteResults(this, CodeCompleter, CodeCompletionContext::CCC_ObjCProtocolName, Results.data(),Results.size()); @@ -4971,13 +4976,17 @@ void Sema::CodeCompleteObjCProtocolReferences(IdentifierLocPair *Protocols, void Sema::CodeCompleteObjCProtocolDecl(Scope *) { ResultBuilder Results(*this, CodeCompletionContext::CCC_ObjCProtocolName); - Results.EnterNewScope(); - // Add all protocols. - AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, true, - Results); + if (CodeCompleter && CodeCompleter->includeGlobals()) { + Results.EnterNewScope(); + + // Add all protocols. + AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, true, + Results); - Results.ExitScope(); + Results.ExitScope(); + } + HandleCodeCompleteResults(this, CodeCompleter, CodeCompletionContext::CCC_ObjCProtocolName, Results.data(),Results.size()); diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index 16ca78f4dd..6ff9cc69f1 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -2463,12 +2463,24 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result, for (DeclContext::decl_iterator D = CurCtx->decls_begin(), DEnd = CurCtx->decls_end(); D != DEnd; ++D) { - if (NamedDecl *ND = dyn_cast(*D)) + if (NamedDecl *ND = dyn_cast(*D)) { if (Result.isAcceptableDecl(ND)) { Consumer.FoundDecl(ND, Visited.checkHidden(ND), InBaseClass); Visited.add(ND); } - + } else if (ObjCForwardProtocolDecl *ForwardProto + = dyn_cast(*D)) { + for (ObjCForwardProtocolDecl::protocol_iterator + P = ForwardProto->protocol_begin(), + PEnd = ForwardProto->protocol_end(); + P != PEnd; + ++P) { + if (Result.isAcceptableDecl(*P)) { + Consumer.FoundDecl(*P, Visited.checkHidden(*P), InBaseClass); + Visited.add(*P); + } + } + } // Visit transparent contexts and inline namespaces inside this context. if (DeclContext *InnerCtx = dyn_cast(*D)) { if (InnerCtx->isTransparentContext() || InnerCtx->isInlineNamespace()) diff --git a/test/Index/complete-protocols.m b/test/Index/complete-protocols.m index 89f61bcf9a..6af0198baa 100644 --- a/test/Index/complete-protocols.m +++ b/test/Index/complete-protocols.m @@ -16,10 +16,12 @@ void f(id); // RUN: c-index-test -code-completion-at=%s:9:11 %s | FileCheck -check-prefix=CHECK-CC1 %s // CHECK-CC1: ObjCProtocolDecl:{TypedText Protocol1} -// CHECK-CC1: ObjCProtocolDecl:{TypedText Protocol2} +// CHECK-CC1-NEXT: ObjCProtocolDecl:{TypedText Protocol2} // RUN: c-index-test -code-completion-at=%s:9:21 %s | FileCheck -check-prefix=CHECK-CC2 %s // CHECK-CC2-NOT: ObjCProtocolDecl:{TypedText Protocol1} // CHECK-CC2: ObjCProtocolDecl:{TypedText Protocol2} // RUN: c-index-test -code-completion-at=%s:12:11 %s | FileCheck -check-prefix=CHECK-CC3 %s // CHECK-CC3: ObjCProtocolDecl:{TypedText Protocol0} // CHECK-CC3-NEXT: ObjCProtocolDecl:{TypedText Protocol2} + +// RUN: env CINDEXTEST_EDITING=1 CINDEXTEST_COMPLETION_CACHING=1 c-index-test -code-completion-at=%s:9:11 %s | FileCheck -check-prefix=CHECK-CC1 %s -- 2.40.0