[CodeComplete] Filter override completions by function name

Summary:
We put only part of the signature starting with a function name into "typed text"
chunks now, previously the whole signature was "typed text".

This leads to meaningful fuzzy match scores, giving better signals to
compare with other completion items.

Ideally, we would not display the result type to the user, but that requires adding
a new kind of completion chunk.

Reviewers: kadircet

Reviewed By: kadircet

Subscribers: jkorous, arphaman, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D62298

llvm-svn: 361623
This commit is contained in:
Ilya Biryukov 2019-05-24 10:18:39 +00:00
parent 5f04f00282
commit cabab29af2
3 changed files with 45 additions and 28 deletions
clang-tools-extra/clangd/unittests
clang
lib/Sema
test/CodeCompletion

View File

@ -49,6 +49,9 @@ class IgnoreDiagnostics : public DiagnosticsConsumer {
// GMock helpers for matching completion items.
MATCHER_P(Named, Name, "") { return arg.Name == Name; }
MATCHER_P(NameStartsWith, Prefix, "") {
return llvm::StringRef(arg.Name).startswith(Prefix);
}
MATCHER_P(Scope, S, "") { return arg.Scope == S; }
MATCHER_P(Qualifier, Q, "") { return arg.RequiredQualifier == Q; }
MATCHER_P(Labeled, Label, "") {
@ -1946,10 +1949,13 @@ TEST(CompletionTest, SuggestOverrides) {
};
)cpp");
const auto Results = completions(Text);
EXPECT_THAT(Results.Completions,
AllOf(Contains(Labeled("void vfunc(bool param, int p) override")),
Contains(Labeled("void ttt(bool param) const override")),
Not(Contains(Labeled("void vfunc(bool param) override")))));
EXPECT_THAT(
Results.Completions,
AllOf(Contains(AllOf(Labeled("void vfunc(bool param, int p) override"),
NameStartsWith("vfunc"))),
Contains(AllOf(Labeled("void ttt(bool param) const override"),
NameStartsWith("ttt"))),
Not(Contains(Labeled("void vfunc(bool param) override")))));
}
TEST(CompletionTest, OverridesNonIdentName) {

View File

@ -37,6 +37,7 @@
#include "llvm/Support/Path.h"
#include <list>
#include <map>
#include <string>
#include <vector>
using namespace clang;
@ -1828,19 +1829,6 @@ static void AddStaticAssertResult(CodeCompletionBuilder &Builder,
Results.AddResult(CodeCompletionResult(Builder.TakeString()));
}
static void printOverrideString(llvm::raw_ostream &OS,
CodeCompletionString *CCS) {
for (const auto &C : *CCS) {
if (C.Kind == CodeCompletionString::CK_Optional)
printOverrideString(OS, C.Optional);
else
OS << C.Text;
// Add a space after return type.
if (C.Kind == CodeCompletionString::CK_ResultType)
OS << ' ';
}
}
static void AddOverrideResults(ResultBuilder &Results,
const CodeCompletionContext &CCContext,
CodeCompletionBuilder &Builder) {
@ -3162,19 +3150,42 @@ CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString(
PP, Ctx, Result, IncludeBriefComments, CCContext, Policy);
}
static void printOverrideString(const CodeCompletionString &CCS,
std::string &BeforeName,
std::string &NameAndSignature) {
bool SeenTypedChunk = false;
for (auto &Chunk : CCS) {
if (Chunk.Kind == CodeCompletionString::CK_Optional) {
assert(SeenTypedChunk && "optional parameter before name");
// Note that we put all chunks inside into NameAndSignature.
printOverrideString(*Chunk.Optional, NameAndSignature, NameAndSignature);
continue;
}
SeenTypedChunk |= Chunk.Kind == CodeCompletionString::CK_TypedText;
if (SeenTypedChunk)
NameAndSignature += Chunk.Text;
else
BeforeName += Chunk.Text;
}
}
CodeCompletionString *
CodeCompletionResult::createCodeCompletionStringForOverride(
Preprocessor &PP, ASTContext &Ctx, CodeCompletionBuilder &Result,
bool IncludeBriefComments, const CodeCompletionContext &CCContext,
PrintingPolicy &Policy) {
std::string OverrideSignature;
llvm::raw_string_ostream OS(OverrideSignature);
auto *CCS = createCodeCompletionStringForDecl(PP, Ctx, Result,
/*IncludeBriefComments=*/false,
CCContext, Policy);
printOverrideString(OS, CCS);
OS << " override";
Result.AddTypedTextChunk(Result.getAllocator().CopyString(OS.str()));
std::string BeforeName;
std::string NameAndSignature;
// For overrides all chunks go into the result, none are informative.
printOverrideString(*CCS, BeforeName, NameAndSignature);
NameAndSignature += " override";
Result.AddTextChunk(Result.getAllocator().CopyString(BeforeName));
Result.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Result.AddTypedTextChunk(Result.getAllocator().CopyString(NameAndSignature));
return Result.TakeString();
}

View File

@ -11,23 +11,23 @@ void vfunc(bool param, int p) override;
class C : public B {
public:
void vfunc(bool param) override;
void
vf
};
// Runs completion at ^void.
// Runs completion at ^vf
// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:14:3 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
// CHECK-CC1: COMPLETION: Pattern : int ttt(bool param, int x = 3) const override{{$}}
// CHECK-CC1: COMPLETION: Pattern : void vfunc(bool param, int p) override{{$}}
// CHECK-CC1-NOT: COMPLETION: Pattern : void vfunc(bool param) override{{$}}
//
// Runs completion at vo^id.
// Runs completion at vf^
// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:14:5 %s -o - | FileCheck -check-prefix=CHECK-CC2 %s
// CHECK-CC2: COMPLETION: Pattern : void vfunc(bool param, int p) override{{$}}
// CHECK-CC2-NOT: COMPLETION: Pattern : int ttt(bool param, int x = 3) const override{{$}}
// CHECK-CC2: COMPLETION: Pattern : void vfunc(bool param, int p) override{{$}}
// CHECK-CC2-NOT: COMPLETION: Pattern : void vfunc(bool param) override{{$}}
//
// Runs completion at void ^.
// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:14:8 %s -o - | FileCheck -check-prefix=CHECK-CC3 %s
// Runs completion at void ^ on line 13.
// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:13:8 %s -o - | FileCheck -check-prefix=CHECK-CC3 %s
// CHECK-CC3-NOT: COMPLETION: Pattern : int ttt(bool param, int x = 3) const override{{$}}
// CHECK-CC3-NOT: COMPLETION: Pattern : void vfunc(bool param, int p) override{{$}}
// CHECK-CC3-NOT: COMPLETION: Pattern : void vfunc(bool param) override{{$}}