From: Douglas Gregor Date: Wed, 25 Aug 2010 18:41:16 +0000 (+0000) Subject: When combining the code-completion results from Sema long with the X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=721f359a350059a81945baa08f63b2e5feceb044;p=clang When combining the code-completion results from Sema long with the code-completion results cached by ASTUnit, sort the resulting result set. This makes testing far, far easier, so this commit also includes tests for the previous few fixes. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@112070 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Sema/CodeCompleteConsumer.h b/include/clang/Sema/CodeCompleteConsumer.h index 13d16e357d..d290d39a93 100644 --- a/include/clang/Sema/CodeCompleteConsumer.h +++ b/include/clang/Sema/CodeCompleteConsumer.h @@ -182,6 +182,9 @@ public: CCC_MacroNameUse, /// \brief Code completion occurred within a preprocessor expression. CCC_PreprocessorExpression, + /// \brief Code completion occurred where a preprocessor directive is + /// expected. + CCC_PreprocessorDirective, /// \brief Code completion occurred in a context where natural language is /// expected, e.g., a comment or string literal. /// @@ -580,6 +583,24 @@ private: void computeCursorKindAndAvailability(); }; +bool operator<(const CodeCompletionResult &X, const CodeCompletionResult &Y); + +inline bool operator>(const CodeCompletionResult &X, + const CodeCompletionResult &Y) { + return Y < X; +} + +inline bool operator<=(const CodeCompletionResult &X, + const CodeCompletionResult &Y) { + return !(Y < X); +} + +inline bool operator>=(const CodeCompletionResult &X, + const CodeCompletionResult &Y) { + return !(X < Y); +} + + llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const CodeCompletionString &CCS); diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp index 31e42a3c36..452803acd2 100644 --- a/lib/Frontend/ASTUnit.cpp +++ b/lib/Frontend/ASTUnit.cpp @@ -1552,8 +1552,10 @@ void CalculateHiddenNames(const CodeCompletionContext &Context, case CodeCompletionContext::CCC_MacroName: case CodeCompletionContext::CCC_MacroNameUse: case CodeCompletionContext::CCC_PreprocessorExpression: + case CodeCompletionContext::CCC_PreprocessorDirective: case CodeCompletionContext::CCC_NaturalLanguage: - // If we're just looking for protocol or macro names, nothing can hide them. + // We're looking for nothing, or we're looking for names that cannot + // be hidden. return; } @@ -1676,7 +1678,9 @@ void AugmentedCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &S, Next.ProcessCodeCompleteResults(S, Context, Results, NumResults); return; } - + + // Sort the completion results before passing them on to the actual consumer. + std::stable_sort(AllResults.begin(), AllResults.end()); Next.ProcessCodeCompleteResults(S, Context, AllResults.data(), AllResults.size()); diff --git a/lib/Sema/CodeCompleteConsumer.cpp b/lib/Sema/CodeCompleteConsumer.cpp index 303647bbc1..4345123558 100644 --- a/lib/Sema/CodeCompleteConsumer.cpp +++ b/lib/Sema/CodeCompleteConsumer.cpp @@ -615,6 +615,62 @@ void CodeCompletionResult::computeCursorKindAndAvailability() { } } +/// \brief Retrieve the name that should be used to order a result. +/// +/// If the name needs to be constructed as a string, that string will be +/// saved into Saved and the returned StringRef will refer to it. +static llvm::StringRef getOrderedName(const CodeCompletionResult &R, + std::string &Saved) { + switch (R.Kind) { + case CodeCompletionResult::RK_Keyword: + return R.Keyword; + + case CodeCompletionResult::RK_Pattern: + return R.Pattern->getTypedText(); + + case CodeCompletionResult::RK_Macro: + return R.Macro->getName(); + + case CodeCompletionResult::RK_Declaration: + // Handle declarations below. + break; + } + + DeclarationName Name = R.Declaration->getDeclName(); + + // If the name is a simple identifier (by far the common case), or a + // zero-argument selector, just return a reference to that identifier. + if (IdentifierInfo *Id = Name.getAsIdentifierInfo()) + return Id->getName(); + if (Name.isObjCZeroArgSelector()) + if (IdentifierInfo *Id + = Name.getObjCSelector().getIdentifierInfoForSlot(0)) + return Id->getName(); + + Saved = Name.getAsString(); + return Saved; +} + +bool clang::operator<(const CodeCompletionResult &X, + const CodeCompletionResult &Y) { + std::string XSaved, YSaved; + llvm::StringRef XStr = getOrderedName(X, XSaved); + llvm::StringRef YStr = getOrderedName(Y, YSaved); + int cmp = XStr.compare_lower(YStr); + if (cmp) + return cmp < 0; + + // Non-hidden names precede hidden names. + if (X.Hidden != Y.Hidden) + return !X.Hidden; + + // Non-nested-name-specifiers precede nested-name-specifiers. + if (X.StartsNestedNameSpecifier != Y.StartsNestedNameSpecifier) + return !X.StartsNestedNameSpecifier; + + return false; +} + void CIndexCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef, CodeCompletionContext Context, diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index 6d91b465de..f8bb9b5a75 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -2231,67 +2231,6 @@ CodeCompleteConsumer::OverloadCandidate::CreateSignatureString( return Result; } -namespace { - struct SortCodeCompleteResult { - typedef CodeCompletionResult Result; - - /// \brief Retrieve the name that should be used to order a result. - /// - /// If the name needs to be constructed as a string, that string will be - /// saved into Saved and the returned StringRef will refer to it. - static llvm::StringRef getOrderedName(const Result &R, - std::string &Saved) { - switch (R.Kind) { - case Result::RK_Keyword: - return R.Keyword; - - case Result::RK_Pattern: - return R.Pattern->getTypedText(); - - case Result::RK_Macro: - return R.Macro->getName(); - - case Result::RK_Declaration: - // Handle declarations below. - break; - } - - DeclarationName Name = R.Declaration->getDeclName(); - - // If the name is a simple identifier (by far the common case), or a - // zero-argument selector, just return a reference to that identifier. - if (IdentifierInfo *Id = Name.getAsIdentifierInfo()) - return Id->getName(); - if (Name.isObjCZeroArgSelector()) - if (IdentifierInfo *Id - = Name.getObjCSelector().getIdentifierInfoForSlot(0)) - return Id->getName(); - - Saved = Name.getAsString(); - return Saved; - } - - bool operator()(const Result &X, const Result &Y) const { - std::string XSaved, YSaved; - llvm::StringRef XStr = getOrderedName(X, XSaved); - llvm::StringRef YStr = getOrderedName(Y, YSaved); - int cmp = XStr.compare_lower(YStr); - if (cmp) - return cmp < 0; - - // Non-hidden names precede hidden names. - if (X.Hidden != Y.Hidden) - return !X.Hidden; - - // Non-nested-name-specifiers precede nested-name-specifiers. - if (X.StartsNestedNameSpecifier != Y.StartsNestedNameSpecifier) - return !X.StartsNestedNameSpecifier; - - return false; - } - }; -} - unsigned clang::getMacroUsagePriority(llvm::StringRef MacroName, bool PreferredTypeIsPointer) { unsigned Priority = CCP_Macro; @@ -2338,7 +2277,7 @@ static void HandleCodeCompleteResults(Sema *S, CodeCompletionContext Context, CodeCompletionResult *Results, unsigned NumResults) { - std::stable_sort(Results, Results + NumResults, SortCodeCompleteResult()); + std::stable_sort(Results, Results + NumResults); if (CodeCompleter) CodeCompleter->ProcessCodeCompleteResults(*S, Context, Results, NumResults); @@ -4804,9 +4743,8 @@ void Sema::CodeCompletePreprocessorDirective(bool InConditional) { // FIXME: we don't support #assert or #unassert, so don't suggest them. Results.ExitScope(); - // FIXME: Create a new code-completion context for this? HandleCodeCompleteResults(this, CodeCompleter, - CodeCompletionContext::CCC_Other, + CodeCompletionContext::CCC_PreprocessorDirective, Results.data(), Results.size()); } diff --git a/test/Index/complete-exprs.c b/test/Index/complete-exprs.c index aed825e045..35fe40405e 100644 --- a/test/Index/complete-exprs.c +++ b/test/Index/complete-exprs.c @@ -26,12 +26,7 @@ void f4(const char* str) { // CHECK-CC1-NOT: NotImplemented:{TypedText float} (65) // CHECK-CC1: ParmDecl:{ResultType int}{TypedText j} (2) // CHECK-CC1: NotImplemented:{TypedText sizeof}{LeftParen (}{Placeholder expression-or-type}{RightParen )} (30) -// RUN: env CINDEXTEST_EDITING=1 CINDEXTEST_COMPLETION_CACHING=1 c-index-test -code-completion-at=%s:7:9 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC1a %s -// CHECK-CC1a: NotImplemented:{TypedText __PRETTY_FUNCTION__} (60) -// CHECK-CC1a: ParmDecl:{ResultType int}{TypedText j} (2) -// CHECK-CC1a: NotImplemented:{TypedText sizeof}{LeftParen (}{Placeholder expression-or-type}{RightParen )} (30) -// CHECK-CC1a: FunctionDecl:{ResultType int}{TypedText f}{LeftParen (}{Placeholder int}{RightParen )} (12) -// CHECK-CC1a: macro definition:{TypedText __VERSION__} (70) +// RUN: env CINDEXTEST_EDITING=1 CINDEXTEST_COMPLETION_CACHING=1 c-index-test -code-completion-at=%s:7:9 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC1 %s // RUN: c-index-test -code-completion-at=%s:7:14 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC3 %s // RUN: env CINDEXTEST_EDITING=1 c-index-test -code-completion-at=%s:7:14 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC3 %s // CHECK-CC3: macro definition:{TypedText __VERSION__} (70) diff --git a/test/Index/complete-preprocessor.m b/test/Index/complete-preprocessor.m index 6ca7214fa2..1873dad6f3 100644 --- a/test/Index/complete-preprocessor.m +++ b/test/Index/complete-preprocessor.m @@ -71,3 +71,10 @@ FOO(in,t) value; // CHECK-CC5: NotImplemented:{TypedText inline} (30) // CHECK-CC5: NotImplemented:{TypedText int} (65) // CHECK-CC5: NotImplemented:{TypedText long} (65) + +// Same tests as above, but with completion caching. +// RUN: env CINDEXTEST_EDITING=1 CINDEXTEST_COMPLETION_CACHING=1 c-index-test -code-completion-at=%s:4:2 %s | FileCheck -check-prefix=CHECK-CC1 %s +// RUN: env CINDEXTEST_EDITING=1 CINDEXTEST_COMPLETION_CACHING=1 c-index-test -code-completion-at=%s:5:2 %s | FileCheck -check-prefix=CHECK-CC2 %s +// RUN: env CINDEXTEST_EDITING=1 CINDEXTEST_COMPLETION_CACHING=1 c-index-test -code-completion-at=%s:9:8 %s | FileCheck -check-prefix=CHECK-CC3 %s +// RUN: env CINDEXTEST_EDITING=1 CINDEXTEST_COMPLETION_CACHING=1 c-index-test -code-completion-at=%s:11:5 %s | FileCheck -check-prefix=CHECK-CC4 %s +// RUN: env CINDEXTEST_EDITING=1 CINDEXTEST_COMPLETION_CACHING=1 c-index-test -code-completion-at=%s:14:5 %s | FileCheck -check-prefix=CHECK-CC5 %s