mirror of
https://github.com/intel/llvm.git
synced 2026-01-21 12:19:23 +08:00
[clang][CodeComplete] skip explicit obj param when creating signature string (#146649)
Fixes clangd/clangd#2284
This commit is contained in:
committed by
GitHub
parent
7410f6d31d
commit
3466cdb769
@@ -3267,6 +3267,56 @@ TEST(SignatureHelpTest, VariadicType) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST(SignatureHelpTest, SkipExplicitObjectParameter) {
|
||||
Annotations Code(R"cpp(
|
||||
struct A {
|
||||
void foo(this auto&& self, int arg);
|
||||
void bar(this A self, int arg);
|
||||
};
|
||||
int main() {
|
||||
A a {};
|
||||
a.foo($c1^);
|
||||
(&A::bar)($c2^);
|
||||
(&A::foo)($c3^);
|
||||
}
|
||||
)cpp");
|
||||
|
||||
auto TU = TestTU::withCode(Code.code());
|
||||
TU.ExtraArgs = {"-std=c++23"};
|
||||
|
||||
MockFS FS;
|
||||
auto Inputs = TU.inputs(FS);
|
||||
|
||||
auto Preamble = TU.preamble();
|
||||
ASSERT_TRUE(Preamble);
|
||||
|
||||
{
|
||||
const auto Result = signatureHelp(testPath(TU.Filename), Code.point("c1"),
|
||||
*Preamble, Inputs, MarkupKind::PlainText);
|
||||
|
||||
EXPECT_EQ(1U, Result.signatures.size());
|
||||
|
||||
EXPECT_THAT(Result.signatures[0], AllOf(sig("foo([[int arg]]) -> void")));
|
||||
}
|
||||
{
|
||||
const auto Result = signatureHelp(testPath(TU.Filename), Code.point("c2"),
|
||||
*Preamble, Inputs, MarkupKind::PlainText);
|
||||
|
||||
EXPECT_EQ(1U, Result.signatures.size());
|
||||
|
||||
EXPECT_THAT(Result.signatures[0], AllOf(sig("([[A]], [[int]]) -> void")));
|
||||
}
|
||||
{
|
||||
// TODO: llvm/llvm-project/146649
|
||||
const auto Result = signatureHelp(testPath(TU.Filename), Code.point("c3"),
|
||||
*Preamble, Inputs, MarkupKind::PlainText);
|
||||
// TODO: We expect 1 signature here, with this signature
|
||||
EXPECT_EQ(0U, Result.signatures.size());
|
||||
// EXPECT_THAT(Result.signatures[0], AllOf(sig("([[auto&&]], [[int]]) ->
|
||||
// void")));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(CompletionTest, IncludedCompletionKinds) {
|
||||
Annotations Test(R"cpp(#include "^)cpp");
|
||||
auto TU = TestTU::withCode(Test.code());
|
||||
@@ -4369,14 +4419,24 @@ TEST(CompletionTest, SkipExplicitObjectParameter) {
|
||||
Annotations Code(R"cpp(
|
||||
struct A {
|
||||
void foo(this auto&& self, int arg);
|
||||
void bar(this A self, int arg);
|
||||
};
|
||||
|
||||
int main() {
|
||||
A a {};
|
||||
a.^
|
||||
a.$c1^;
|
||||
(&A::fo$c2^;
|
||||
(&A::ba$c3^;
|
||||
}
|
||||
)cpp");
|
||||
|
||||
// TODO: llvm/llvm-project/146649
|
||||
// This is incorrect behavior. Correct Result should be a variant of,
|
||||
// c2: signature = (auto&& self, int arg)
|
||||
// snippet = (${1: auto&& self}, ${2: int arg})
|
||||
// c3: signature = (A self, int arg)
|
||||
// snippet = (${1: A self}, ${2: int arg})
|
||||
|
||||
auto TU = TestTU::withCode(Code.code());
|
||||
TU.ExtraArgs = {"-std=c++23"};
|
||||
|
||||
@@ -4387,12 +4447,31 @@ TEST(CompletionTest, SkipExplicitObjectParameter) {
|
||||
|
||||
MockFS FS;
|
||||
auto Inputs = TU.inputs(FS);
|
||||
auto Result = codeComplete(testPath(TU.Filename), Code.point(),
|
||||
Preamble.get(), Inputs, Opts);
|
||||
{
|
||||
auto Result = codeComplete(testPath(TU.Filename), Code.point("c1"),
|
||||
Preamble.get(), Inputs, Opts);
|
||||
|
||||
EXPECT_THAT(Result.Completions,
|
||||
ElementsAre(AllOf(named("foo"), signature("(int arg)"),
|
||||
snippetSuffix("(${1:int arg})"))));
|
||||
EXPECT_THAT(Result.Completions,
|
||||
UnorderedElementsAre(AllOf(named("foo"), signature("(int arg)"),
|
||||
snippetSuffix("(${1:int arg})")),
|
||||
AllOf(named("bar"), signature("(int arg)"),
|
||||
snippetSuffix("(${1:int arg})"))));
|
||||
}
|
||||
{
|
||||
auto Result = codeComplete(testPath(TU.Filename), Code.point("c2"),
|
||||
Preamble.get(), Inputs, Opts);
|
||||
EXPECT_THAT(
|
||||
Result.Completions,
|
||||
ElementsAre(AllOf(named("foo"), signature("<class self:auto>(int arg)"),
|
||||
snippetSuffix("<${1:class self:auto}>"))));
|
||||
}
|
||||
{
|
||||
auto Result = codeComplete(testPath(TU.Filename), Code.point("c3"),
|
||||
Preamble.get(), Inputs, Opts);
|
||||
EXPECT_THAT(Result.Completions,
|
||||
ElementsAre(AllOf(named("bar"), signature("(int arg)"),
|
||||
snippetSuffix(""))));
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
} // namespace clangd
|
||||
|
||||
@@ -4034,6 +4034,14 @@ static void AddOverloadParameterChunks(
|
||||
return;
|
||||
}
|
||||
|
||||
// C++23 introduces an explicit object parameter, a.k.a. "deducing this"
|
||||
// Skip it for autocomplete and treat the next parameter as the first
|
||||
// parameter
|
||||
if (Function && FirstParameter &&
|
||||
Function->getParamDecl(P)->isExplicitObjectParameter()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (FirstParameter)
|
||||
FirstParameter = false;
|
||||
else
|
||||
|
||||
@@ -1,14 +1,48 @@
|
||||
struct A {
|
||||
void foo(this A self, int arg);
|
||||
void foo(this auto&& self, int arg);
|
||||
void bar(this A self, int arg);
|
||||
};
|
||||
|
||||
int main() {
|
||||
int func1() {
|
||||
A a {};
|
||||
a.
|
||||
}
|
||||
// RUN: %clang_cc1 -cc1 -fsyntax-only -code-completion-at=%s:%(line-2):5 -std=c++23 %s | FileCheck %s
|
||||
// CHECK: COMPLETION: A : A::
|
||||
// CHECK-NEXT: COMPLETION: foo : [#void#]foo(<#int arg#>)
|
||||
// CHECK-NEXT: COMPLETION: operator= : [#A &#]operator=(<#const A &#>)
|
||||
// CHECK-NEXT: COMPLETION: operator= : [#A &#]operator=(<#A &&#>)
|
||||
// CHECK-NEXT: COMPLETION: ~A : [#void#]~A()
|
||||
// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:%(line-2):5 -std=c++23 %s | FileCheck -check-prefix=CHECK-CC1 %s
|
||||
// CHECK-CC1: COMPLETION: A : A::
|
||||
// CHECK-NEXT-CC1: COMPLETION: bar : [#void#]bar(<#int arg#>)
|
||||
// CHECK-NEXT-CC1: COMPLETION: foo : [#void#]foo(<#int arg#>)
|
||||
// CHECK-NEXT-CC1: COMPLETION: operator= : [#A &#]operator=(<#const A &#>)
|
||||
// CHECK-NEXT-CC1: COMPLETION: operator= : [#A &#]operator=(<#A &&#>)
|
||||
// CHECK-NEXT-CC1: COMPLETION: ~A : [#void#]~A()
|
||||
|
||||
struct B {
|
||||
template <typename T>
|
||||
void foo(this T&& self, int arg);
|
||||
};
|
||||
|
||||
int func2() {
|
||||
B b {};
|
||||
b.foo();
|
||||
}
|
||||
// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:%(line-2):9 -std=c++23 %s | FileCheck -check-prefix=CHECK-CC2 %s
|
||||
// CHECK-CC2: OVERLOAD: [#void#]foo(int arg)
|
||||
|
||||
// TODO: llvm/llvm-project/146649
|
||||
// This is incorrect behavior. Correct Result should be a variant of,
|
||||
// CC3: should be something like [#void#]foo(<#A self#>, <#int arg#>)
|
||||
// CC4: should be something like [#void#]bar(<#A self#>, <#int arg#>)
|
||||
int func3() {
|
||||
(&A::foo)
|
||||
(&A::bar)
|
||||
}
|
||||
// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:%(line-3):10 -std=c++23 %s | FileCheck -check-prefix=CHECK-CC3 %s
|
||||
// CHECK-CC3: COMPLETION: foo : [#void#]foo<<#class self:auto#>>(<#int arg#>)
|
||||
// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:%(line-4):10 -std=c++23 %s | FileCheck -check-prefix=CHECK-CC4 %s
|
||||
// CHECK-CC4: COMPLETION: bar : [#void#]bar(<#int arg#>)
|
||||
|
||||
int func4() {
|
||||
// TODO (&A::foo)(
|
||||
(&A::bar)(
|
||||
}
|
||||
// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:%(line-2):13 -std=c++23 %s | FileCheck -check-prefix=CHECK-CC5 %s
|
||||
// CHECK-CC5: OVERLOAD: [#void#](<#A#>, int)
|
||||
|
||||
Reference in New Issue
Block a user