Index: include/clang/Parse/Parser.h =================================================================== --- include/clang/Parse/Parser.h +++ include/clang/Parse/Parser.h @@ -290,6 +290,8 @@ "Should consume special tokens with Consume*Token"); PrevTokLocation = Tok.getLocation(); PP.Lex(Tok); + if (Tok.is(tok::code_completion)) + Actions.setCodeCompletionFilter(Tok.getIdentifierInfo()); return PrevTokLocation; } Index: include/clang/Sema/CodeCompleteConsumer.h =================================================================== --- include/clang/Sema/CodeCompleteConsumer.h +++ include/clang/Sema/CodeCompleteConsumer.h @@ -912,6 +912,14 @@ /// \brief Deregisters and destroys this code-completion consumer. virtual ~CodeCompleteConsumer(); + /// \name Code-completion filtering + //@{ + /// \brief Check if the result should be filtered out. + virtual bool isResultFilteredOut(StringRef Filter, + CodeCompletionResult Results) { + return true; + } + /// \name Code-completion callbacks //@{ /// \brief Process the finalized code-completion results. @@ -965,6 +973,8 @@ OverloadCandidate *Candidates, unsigned NumCandidates) override; + bool isResultFilteredOut(StringRef Filter, CodeCompletionResult Results) override; + CodeCompletionAllocator &getAllocator() override { return CCTUInfo.getAllocator(); } Index: include/clang/Sema/Sema.h =================================================================== --- include/clang/Sema/Sema.h +++ include/clang/Sema/Sema.h @@ -305,6 +305,9 @@ /// \brief Code-completion consumer. CodeCompleteConsumer *CodeCompleter; + /// \brief Code-complete filter. + IdentifierInfo *CodeCompleteFilter; + /// CurContext - This is the current declaration context of parsing. DeclContext *CurContext; @@ -8962,6 +8965,15 @@ PCC_LocalDeclarationSpecifiers }; + void setCodeCompletionFilter(IdentifierInfo* filterII) { + CodeCompleteFilter = filterII; + } + StringRef getCodeCompletionFilter() { + if (CodeCompleteFilter) + return CodeCompleteFilter->getName(); + return StringRef(); + } + void CodeCompleteModuleImport(SourceLocation ImportLoc, ModuleIdPath Path); void CodeCompleteOrdinaryName(Scope *S, ParserCompletionContext CompletionContext); Index: lib/Lex/Lexer.cpp =================================================================== --- lib/Lex/Lexer.cpp +++ lib/Lex/Lexer.cpp @@ -1533,7 +1533,15 @@ // preprocessor, which may macro expand it or something. if (II->isHandleIdentifierCase()) return PP->HandleIdentifier(Result); - + + if (II->getTokenID() == tok::identifier && isCodeCompletionPoint(CurPtr) + && II->getPPKeywordID() == tok::pp_not_keyword + && II->getObjCKeywordID() == tok::objc_not_keyword) { + // Return the code-completion token. + Result.setKind(tok::code_completion); + cutOffLexing(); + return true; + } return true; } Index: lib/Sema/CodeCompleteConsumer.cpp =================================================================== --- lib/Sema/CodeCompleteConsumer.cpp +++ lib/Sema/CodeCompleteConsumer.cpp @@ -428,6 +428,28 @@ CodeCompleteConsumer::~CodeCompleteConsumer() { } +bool PrintingCodeCompleteConsumer::isResultFilteredOut(StringRef Filter, + CodeCompletionResult Result) { + switch (Result.Kind) { + case CodeCompletionResult::RK_Declaration: { + return !(Result.Declaration && + (*Result.Declaration).getIdentifier() && + (*Result.Declaration).getIdentifier()->getName().startswith(Filter)); + } + case CodeCompletionResult::RK_Keyword: { + return !(Result.Keyword && StringRef(&(*Result.Keyword)).startswith(Filter)); + } + case CodeCompletionResult::RK_Macro: { + return !(Result.Macro && Result.Macro->getName().startswith(Filter)); + } + case CodeCompletionResult::RK_Pattern: { + return !(Result.Pattern && + StringRef((Result.Pattern->getAsString())).startswith(Filter)); + } + } + return false; +} + void PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef, CodeCompletionContext Context, @@ -435,8 +457,12 @@ unsigned NumResults) { std::stable_sort(Results, Results + NumResults); + StringRef Filter = SemaRef.getCodeCompletionFilter(); + // Print the results. for (unsigned I = 0; I != NumResults; ++I) { + if(!Filter.empty() && isResultFilteredOut(Filter, Results[I])) + continue; OS << "COMPLETION: "; switch (Results[I].Kind) { case CodeCompletionResult::RK_Declaration: Index: lib/Sema/Sema.cpp =================================================================== --- lib/Sema/Sema.cpp +++ lib/Sema/Sema.cpp @@ -77,7 +77,7 @@ isMultiplexExternalSource(false), FPFeatures(pp.getLangOpts()), LangOpts(pp.getLangOpts()), PP(pp), Context(ctxt), Consumer(consumer), Diags(PP.getDiagnostics()), SourceMgr(PP.getSourceManager()), - CollectStats(false), CodeCompleter(CodeCompleter), + CollectStats(false), CodeCompleter(CodeCompleter), CodeCompleteFilter(0), CurContext(nullptr), OriginalLexicalContext(nullptr), PackContext(nullptr), MSStructPragmaOn(false), MSPointerToMemberRepresentationMethod( Index: test/CodeCompletion/objc-message.mm =================================================================== --- test/CodeCompletion/objc-message.mm +++ test/CodeCompletion/objc-message.mm @@ -38,9 +38,9 @@ [ptr instanceMethod1]; } -// RUN: %clang_cc1 -fsyntax-only -std=c++11 -code-completion-at=%s:33:7 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -code-completion-at=%s:33:8 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s // CHECK-CC1: categoryInstanceMethod : [#id#]categoryInstanceMethod // CHECK-CC1: instanceMethod1 : [#id#]instanceMethod1 // CHECK-CC1: protocolInstanceMethod : [#id#]protocolInstanceMethod -// RUN: %clang_cc1 -fsyntax-only -std=c++11 -code-completion-at=%s:38:7 %s -o - | FileCheck -check-prefix=CHECK-CC2 %s +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -code-completion-at=%s:38:8 %s -o - | FileCheck -check-prefix=CHECK-CC2 %s // CHECK-CC2: protocolInstanceMethod : [#id#]protocolInstanceMethod Index: test/Index/complete-method-decls.m =================================================================== --- test/Index/complete-method-decls.m +++ test/Index/complete-method-decls.m @@ -195,7 +195,7 @@ // CHECK-CCG: NotImplemented:{TypedText void} (50) // CHECK-CCG: NotImplemented:{TypedText volatile} (50) // RUN: c-index-test -code-completion-at=%s:60:24 %s | FileCheck -check-prefix=CHECK-CCF %s -// RUN: c-index-test -code-completion-at=%s:60:26 %s | FileCheck -check-prefix=CHECK-CCH %s +// RUN: c-index-test -code-completion-at=%s:60:27 %s | FileCheck -check-prefix=CHECK-CCH %s // CHECK-CCH: ObjCInterfaceDecl:{TypedText A} (50) // CHECK-CCH: ObjCInterfaceDecl:{TypedText B} (50) // CHECK-CCH: NotImplemented:{TypedText bycopy} (40) Index: test/Index/complete-objc-message-id.m =================================================================== --- test/Index/complete-objc-message-id.m +++ test/Index/complete-objc-message-id.m @@ -68,7 +68,7 @@ // CHECK-SELECTOR-PREF: ObjCClassMethodDecl:{ResultType id}{TypedText new} (35) // CHECK-SELECTOR-PREF: ObjCClassMethodDecl:{ResultType Class}{TypedText superclass} (35) -// RUN: c-index-test -code-completion-at=%s:46:7 %s | FileCheck -check-prefix=CHECK-INSTANCE-QUAL-ID %s -// RUN: c-index-test -code-completion-at=%s:47:7 %s | FileCheck -check-prefix=CHECK-INSTANCE-QUAL-ID %s +// RUN: c-index-test -code-completion-at=%s:46:8 %s | FileCheck -check-prefix=CHECK-INSTANCE-QUAL-ID %s +// RUN: c-index-test -code-completion-at=%s:47:8 %s | FileCheck -check-prefix=CHECK-INSTANCE-QUAL-ID %s // CHECK-INSTANCE-QUAL-ID: ObjCInstanceMethodDecl:{ResultType int}{TypedText P1_method1} (37) // CHECK-INSTANCE-QUAL-ID: ObjCInstanceMethodDecl:{ResultType int}{TypedText P2_method1} (35) Index: test/Index/complete-objc-message.m =================================================================== --- test/Index/complete-objc-message.m +++ test/Index/complete-objc-message.m @@ -218,13 +218,13 @@ // CHECK-CC2-NEXT: Container Kind: ObjCInterfaceDecl // CHECK-CC2-NEXT: Container is complete // CHECK-CC2-NEXT: Container USR: c:objc(cs)Foo -// RUN: c-index-test -code-completion-at=%s:61:16 %s | FileCheck -check-prefix=CHECK-CC3 %s +// RUN: c-index-test -code-completion-at=%s:61:17 %s | FileCheck -check-prefix=CHECK-CC3 %s // CHECK-CC3: ObjCClassMethodDecl:{ResultType int}{TypedText MyClassMethod:}{Placeholder (id)} // CHECK-CC3: ObjCClassMethodDecl:{ResultType int}{TypedText MyPrivateMethod} -// RUN: c-index-test -code-completion-at=%s:65:16 %s | FileCheck -check-prefix=CHECK-CC4 %s +// RUN: c-index-test -code-completion-at=%s:65:17 %s | FileCheck -check-prefix=CHECK-CC4 %s // CHECK-CC4: ObjCInstanceMethodDecl:{ResultType int}{TypedText MyInstMethod:}{Placeholder (id)}{HorizontalSpace }{TypedText second:}{Placeholder (id)} // CHECK-CC4: ObjCInstanceMethodDecl:{ResultType int}{TypedText MyPrivateInstMethod} -// RUN: c-index-test -code-completion-at=%s:74:9 %s | FileCheck -check-prefix=CHECK-CC5 %s +// RUN: c-index-test -code-completion-at=%s:74:10 %s | FileCheck -check-prefix=CHECK-CC5 %s // CHECK-CC5: ObjCInstanceMethodDecl:{ResultType int}{TypedText MyInstMethod:}{Placeholder (id)}{HorizontalSpace }{TypedText second:}{Placeholder (id)} // CHECK-CC5: ObjCInstanceMethodDecl:{ResultType int}{TypedText MySubInstMethod} // RUN: c-index-test -code-completion-at=%s:82:8 %s | FileCheck -check-prefix=CHECK-CC6 %s @@ -311,7 +311,7 @@ // CHECK-CCI: ObjCInstanceMethodDecl:{ResultType void}{TypedText method1} (37) // CHECK-CCI: ObjCInstanceMethodDecl:{ResultType void}{TypedText method2} (35) -// RUN: c-index-test -code-completion-at=%s:150:5 %s | FileCheck -check-prefix=CHECK-REDUNDANT %s +// RUN: c-index-test -code-completion-at=%s:150:6 %s | FileCheck -check-prefix=CHECK-REDUNDANT %s // CHECK-REDUNDANT: ObjCInstanceMethodDecl:{ResultType void}{TypedText method2} (35) // CHECK-REDUNDANT-NOT: ObjCInstanceMethodDecl:{ResultType void}{TypedText method2} // CHECK-REDUNDANT: ObjCInstanceMethodDecl:{ResultType void}{TypedText method3} (35) Index: test/Index/complete-recovery.m =================================================================== --- test/Index/complete-recovery.m +++ test/Index/complete-recovery.m @@ -26,7 +26,7 @@ // Test case for fix committed in r145441. // RUN: env CINDEXTEST_CODE_COMPLETE_PATTERNS=1 c-index-test -code-completion-at=%s:9:20 %s -fms-compatibility | FileCheck -check-prefix=CHECK-CC1 %s -// RUN: env CINDEXTEST_CODE_COMPLETE_PATTERNS=1 c-index-test -code-completion-at=%s:10:24 %s | FileCheck -check-prefix=CHECK-CC2 %s +// RUN: env CINDEXTEST_CODE_COMPLETE_PATTERNS=1 c-index-test -code-completion-at=%s:10:25 %s | FileCheck -check-prefix=CHECK-CC2 %s // CHECK-CC2: NotImplemented:{ResultType char[]}{TypedText @encode}{LeftParen (}{Placeholder type-name}{RightParen )} // CHECK-CC2: NotImplemented:{TypedText _Bool} // CHECK-CC2: VarDecl:{ResultType A *}{TypedText a} Index: test/Index/complete-super.m =================================================================== --- test/Index/complete-super.m +++ test/Index/complete-super.m @@ -60,7 +60,7 @@ // RUN: c-index-test -code-completion-at=%s:20:16 %s | FileCheck -check-prefix=CHECK-ADD-TO %s // CHECK-ADD-TO: ObjCInstanceMethodDecl:{ResultType void}{Informative add:}{TypedText to:}{Placeholder b} (20) -// RUN: c-index-test -code-completion-at=%s:24:28 %s | FileCheck -check-prefix=CHECK-SELECTOR-FIRST %s +// RUN: c-index-test -code-completion-at=%s:24:29 %s | FileCheck -check-prefix=CHECK-SELECTOR-FIRST %s // CHECK-SELECTOR-FIRST: ObjCClassMethodDecl:{ResultType void}{Informative select:}{TypedText first:}{Placeholder a}{HorizontalSpace }{Text second:}{Placeholder b} (20) // Check "super" completion at the third identifier @@ -69,7 +69,7 @@ // Check "super" completion with missing '['. // RUN: c-index-test -code-completion-at=%s:25:10 %s | FileCheck -check-prefix=CHECK-SELECTOR-SELECTOR %s -// RUN: c-index-test -code-completion-at=%s:25:28 %s | FileCheck -check-prefix=CHECK-SELECTOR-FIRST %s +// RUN: c-index-test -code-completion-at=%s:25:29 %s | FileCheck -check-prefix=CHECK-SELECTOR-FIRST %s // RUN: c-index-test -code-completion-at=%s:25:37 %s | FileCheck -check-prefix=CHECK-SELECTOR-SECOND %s // Check "super" completion for a method declared in a category.