CrisCristescu updated this revision to Diff 51404. CrisCristescu added a comment.
The code_completion token now stores the information, if there is one, about the identifier that it is lexing. During the parsing there is a common entry point which is ConsumerToken where we can set the information necessary for filtering in the Sema in the case of a code_completion token. The information is retrieved when doing the actual filtering. This introduces a change in functionality which means that some tests had to be modified(6 tests for ObjC) due to the fact that if you press tab at the end of a word which could be a language specific keyword, you will get the possible completions of this identifier, not what could be written after the space. This is in accordance with the behaviour of IDEs, for instance XCode. As an example: const<TAB> will only give completions for variables like constVar, and if you have const<SPACE><TAB> the you get the possible completions: const double, const int etc. Repository: rL LLVM http://reviews.llvm.org/D17820 Files: include/clang/Parse/Parser.h include/clang/Sema/CodeCompleteConsumer.h include/clang/Sema/Sema.h lib/Lex/Lexer.cpp lib/Sema/CodeCompleteConsumer.cpp lib/Sema/Sema.cpp test/CodeCompletion/objc-message.mm test/Index/complete-method-decls.m test/Index/complete-objc-message-id.m test/Index/complete-objc-message.m test/Index/complete-recovery.m test/Index/complete-super.m
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. 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-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-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-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/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: 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: 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/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: 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: 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/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; }
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits