zyounan updated this revision to Diff 543277.
zyounan added a comment.
Don't change the CCR. Handle these in CreateCodeCompletionString. Emit template
arguments if possible.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D155370/new/
https://reviews.llvm.org/D155370
Files:
clang-tools-extra/clangd/CodeComplete.cpp
clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
clang/lib/Sema/SemaCodeComplete.cpp
clang/test/CodeCompletion/member-access.cpp
clang/test/Index/complete-qualified.cpp
clang/unittests/Sema/CodeCompleteTest.cpp
Index: clang/unittests/Sema/CodeCompleteTest.cpp
===================================================================
--- clang/unittests/Sema/CodeCompleteTest.cpp
+++ clang/unittests/Sema/CodeCompleteTest.cpp
@@ -60,7 +60,10 @@
for (unsigned I = 0; I < NumResults; ++I) {
auto R = Results[I];
if (R.Kind == CodeCompletionResult::RK_Declaration) {
- if (const auto *FD = llvm::dyn_cast<FunctionDecl>(R.getDeclaration())) {
+ auto *ND = R.getDeclaration();
+ if (auto *Template = llvm::dyn_cast<FunctionTemplateDecl>(ND))
+ ND = Template->getTemplatedDecl();
+ if (const auto *FD = llvm::dyn_cast<FunctionDecl>(ND)) {
CompletedFunctionDecl D;
D.Name = FD->getNameAsString();
D.CanBeCall = R.FunctionCanBeCall;
@@ -191,6 +194,10 @@
struct Foo {
static int staticMethod();
int method() const;
+ template <typename T, int U>
+ void generic(T);
+ template <typename T, int U = 3>
+ static T staticGeneric();
Foo() {
this->$canBeCall^
$canBeCall^
@@ -223,12 +230,16 @@
auto Results = CollectCompletedFunctions(Code.code(), P);
EXPECT_THAT(Results, Contains(AllOf(named("method"), isStatic(false),
canBeCall(true))));
+ EXPECT_THAT(Results, Contains(AllOf(named("generic"), isStatic(false),
+ canBeCall(true))));
}
for (const auto &P : Code.points("cannotBeCall")) {
auto Results = CollectCompletedFunctions(Code.code(), P);
EXPECT_THAT(Results, Contains(AllOf(named("method"), isStatic(false),
canBeCall(false))));
+ EXPECT_THAT(Results, Contains(AllOf(named("generic"), isStatic(false),
+ canBeCall(false))));
}
// static method can always be a call
@@ -236,6 +247,8 @@
auto Results = CollectCompletedFunctions(Code.code(), P);
EXPECT_THAT(Results, Contains(AllOf(named("staticMethod"), isStatic(true),
canBeCall(true))));
+ EXPECT_THAT(Results, Contains(AllOf(named("staticGeneric"), isStatic(true),
+ canBeCall(true))));
}
}
Index: clang/test/Index/complete-qualified.cpp
===================================================================
--- clang/test/Index/complete-qualified.cpp
+++ clang/test/Index/complete-qualified.cpp
@@ -16,5 +16,5 @@
// RUN: c-index-test -code-completion-at=%s:14:8 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
// CHECK-CC1: FieldDecl:{ResultType C<Foo, class Bar>}{TypedText c} (35)
// CHECK-CC1: ClassDecl:{TypedText Foo} (35)
-// CHECK-CC1: CXXMethod:{ResultType Foo &}{TypedText operator=}{LeftParen (}{Placeholder const Foo &}{RightParen )}
-// CHECK-CC1: CXXDestructor:{ResultType void}{TypedText ~Foo}{LeftParen (}{RightParen )} (80)
+// CHECK-CC1: CXXMethod:{ResultType Foo &}{TypedText operator=}
+// CHECK-CC1: CXXDestructor:{ResultType void}{TypedText ~Foo} (80)
Index: clang/test/CodeCompletion/member-access.cpp
===================================================================
--- clang/test/CodeCompletion/member-access.cpp
+++ clang/test/CodeCompletion/member-access.cpp
@@ -171,7 +171,7 @@
template<typename T>
void dependentColonColonCompletion() {
Template<T>::staticFn();
-// CHECK-CC7: function : [#void#]function()
+// CHECK-CC7: function : [#void#]function
// CHECK-CC7: Nested : Nested
// CHECK-CC7: o1 : [#BaseTemplate<int>#]o1
// CHECK-CC7: o2 : [#BaseTemplate<T>#]o2
Index: clang/lib/Sema/SemaCodeComplete.cpp
===================================================================
--- clang/lib/Sema/SemaCodeComplete.cpp
+++ clang/lib/Sema/SemaCodeComplete.cpp
@@ -1384,7 +1384,11 @@
// dot/arrow member access) and we're not inside that class' scope,
// it can't be a call.
if (CompletionContext.getKind() == clang::CodeCompletionContext::CCC_Symbol) {
- const auto *Method = dyn_cast<CXXMethodDecl>(R.getDeclaration());
+ const NamedDecl *ND = R.getDeclaration();
+ if (const auto *FuncTmpl = dyn_cast<FunctionTemplateDecl>(ND)) {
+ ND = FuncTmpl->getTemplatedDecl();
+ }
+ const auto *Method = dyn_cast<CXXMethodDecl>(ND);
if (Method && !Method->isStatic()) {
// Find the class scope that we're currently in.
// We could e.g. be inside a lambda, so walk up the DeclContext until we
@@ -3494,6 +3498,9 @@
AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Ctx, Policy);
AddTypedNameChunk(Ctx, Policy, ND, Result);
+ // We don't emit parameters (and qualifiers) for context where it can't be a call.
+ if (!FunctionCanBeCall)
+ return;
Result.AddChunk(CodeCompletionString::CK_LeftParen);
AddFunctionParameterChunks(PP, Policy, Function, Result);
Result.AddChunk(CodeCompletionString::CK_RightParen);
@@ -3550,6 +3557,15 @@
}
}
+ if (!FunctionCanBeCall) {
+ // If this isn't a call, emit all the template arguments
+ // to disambiguate the (potential) overloads.
+ Result.AddChunk(CodeCompletionString::CK_LeftAngle);
+ AddTemplateParameterChunks(Ctx, Policy, FunTmpl, Result);
+ Result.AddChunk(CodeCompletionString::CK_RightAngle);
+ return Result.TakeString();
+ }
+
if (LastDeducibleArgument) {
// Some of the function template arguments cannot be deduced from a
// function call, so we introduce an explicit template argument list
Index: clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
===================================================================
--- clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -532,45 +532,57 @@
struct Foo {
static int staticMethod();
int method() const;
+ template <typename T, int U>
+ void generic(T);
+ template <typename T, int U = 3>
+ static T staticGeneric();
Foo() {
- this->$keepSnippet^
- $keepSnippet^
- Foo::$keepSnippet^
+ this->$canBeCall^
+ $canBeCall^
+ Foo::$canBeCall^
}
};
struct Derived : Foo {
Derived() {
- Foo::$keepSnippet^
+ Foo::$canBeCall^
}
};
struct OtherClass {
OtherClass() {
Foo f;
- f.$keepSnippet^
- &Foo::$noSnippet^
+ f.$canBeCall^
+ &Foo::$canNotBeCall^
}
};
int main() {
Foo f;
- f.$keepSnippet^
- &Foo::$noSnippet^
+ f.$canBeCall^
+ &Foo::$canNotBeCall^
}
)cpp");
auto TU = TestTU::withCode(Code.code());
- for (const auto &P : Code.points("noSnippet")) {
+ for (const auto &P : Code.points("canNotBeCall")) {
auto Results = completions(TU, P, /*IndexSymbols*/ {}, Opts);
EXPECT_THAT(Results.Completions,
Contains(AllOf(named("method"), snippetSuffix(""))));
+ EXPECT_THAT(
+ Results.Completions,
+ Contains(AllOf(named("generic"), signature("<typename T, int U>"),
+ snippetSuffix("<${1:typename T}, ${2:int U}>"))));
}
- for (const auto &P : Code.points("keepSnippet")) {
+ for (const auto &P : Code.points("canBeCall")) {
auto Results = completions(TU, P, /*IndexSymbols*/ {}, Opts);
EXPECT_THAT(Results.Completions,
Contains(AllOf(named("method"), snippetSuffix("()"))));
+ EXPECT_THAT(
+ Results.Completions,
+ Contains(AllOf(named("generic"), signature("<typename T, int U>(T)"),
+ snippetSuffix("<${1:typename T}, ${2:int U}>(${3:T})"))));
}
// static method will always keep the snippet
@@ -578,6 +590,9 @@
auto Results = completions(TU, P, /*IndexSymbols*/ {}, Opts);
EXPECT_THAT(Results.Completions,
Contains(AllOf(named("staticMethod"), snippetSuffix("()"))));
+ EXPECT_THAT(Results.Completions, Contains(AllOf(named("staticGeneric"),
+ signature("<typename T>()"),
+ snippetSuffix("<${1:typename T}>()"))));
}
}
Index: clang-tools-extra/clangd/CodeComplete.cpp
===================================================================
--- clang-tools-extra/clangd/CodeComplete.cpp
+++ clang-tools-extra/clangd/CodeComplete.cpp
@@ -438,8 +438,6 @@
if (C.SemaResult) {
getSignature(*SemaCCS, &S.Signature, &S.SnippetSuffix, C.SemaResult->Kind,
C.SemaResult->CursorKind, &Completion.RequiredQualifier);
- if (!C.SemaResult->FunctionCanBeCall)
- S.SnippetSuffix.clear();
S.ReturnType = getReturnType(*SemaCCS);
} else if (C.IndexResult) {
S.Signature = std::string(C.IndexResult->Signature);
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits