Author: sammccall Date: Tue Dec 19 02:29:27 2017 New Revision: 321065 URL: http://llvm.org/viewvc/llvm-project?rev=321065&view=rev Log: [clangd] Add unit tests for signature help. SigHelp/CodeComplete lit tests are smoke only.
Modified: clang-tools-extra/trunk/test/clangd/completion.test clang-tools-extra/trunk/test/clangd/signature-help.test clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp Modified: clang-tools-extra/trunk/test/clangd/completion.test URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clangd/completion.test?rev=321065&r1=321064&r2=321065&view=diff ============================================================================== --- clang-tools-extra/trunk/test/clangd/completion.test (original) +++ clang-tools-extra/trunk/test/clangd/completion.test Tue Dec 19 02:29:27 2017 @@ -6,13 +6,13 @@ Content-Length: 125 {"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}} -Content-Length: 246 +Content-Length: 186 -{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///main.cpp","languageId":"cpp","version":1,"text":"struct fake { int a, bb, ccc; int f(int i, const float f) const; };\nint main() {\n fake f;\n f.\n}\n"}}} +{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///main.cpp","languageId":"cpp","version":1,"text":"struct S { int a; };\nint main() {\nS().\n}"}}} Content-Length: 148 -{"jsonrpc":"2.0","id":1,"method":"textDocument/completion","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":3,"character":5}}} +{"jsonrpc":"2.0","id":1,"method":"textDocument/completion","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":2,"character":4}}} # CHECK: "id": 1 # CHECK-NEXT: "jsonrpc": "2.0", # CHECK-NEXT: "result": { @@ -27,157 +27,31 @@ Content-Length: 148 # CHECK-NEXT: "label": "a", # CHECK-NEXT: "sortText": "{{.*}}a" # CHECK-NEXT: }, -# CHECK-NEXT: { -# CHECK-NEXT: "detail": "int", -# CHECK-NEXT: "filterText": "bb", -# CHECK-NEXT: "insertText": "bb", -# CHECK-NEXT: "insertTextFormat": 1, -# CHECK-NEXT: "kind": 5, -# CHECK-NEXT: "label": "bb", -# CHECK-NEXT: "sortText": "{{.*}}bb" -# CHECK-NEXT: }, -# CHECK-NEXT: { -# CHECK-NEXT: "detail": "int", -# CHECK-NEXT: "filterText": "ccc", -# CHECK-NEXT: "insertText": "ccc", -# CHECK-NEXT: "insertTextFormat": 1, -# CHECK-NEXT: "kind": 5, -# CHECK-NEXT: "label": "ccc", -# CHECK-NEXT: "sortText": "{{.*}}ccc" -# CHECK-NEXT: }, -# CHECK-NEXT: { -# CHECK-NEXT: "detail": "int", -# CHECK-NEXT: "filterText": "f", -# CHECK-NEXT: "insertText": "f", -# CHECK-NEXT: "insertTextFormat": 1, -# CHECK-NEXT: "kind": 2, -# CHECK-NEXT: "label": "f(int i, const float f) const", -# CHECK-NEXT: "sortText": "{{.*}}f" -# CHECK-NEXT: }, -# CHECK-NEXT: { -# CHECK-NEXT: "filterText": "fake", -# CHECK-NEXT: "insertText": "fake", -# CHECK-NEXT: "insertTextFormat": 1, -# CHECK-NEXT: "kind": 7, -# CHECK-NEXT: "label": "fake::", -# CHECK-NEXT: "sortText": "{{.*}}fake" -# CHECK-NEXT: }, -# FIXME: Why do buildbots show different operator=s here? -# CHECK: { -# CHECK: "detail": "void", -# CHECK-NEXT: "filterText": "~fake", -# CHECK-NEXT: "insertText": "~fake", -# CHECK-NEXT: "insertTextFormat": 1, -# CHECK-NEXT: "kind": 4, -# CHECK-NEXT: "label": "~fake()", -# CHECK-NEXT: "sortText": "{{.*}}~fake" -# CHECK-NEXT: } -# CHECK-NEXT: ] -Content-Length: 148 - -{"jsonrpc":"2.0","id":2,"method":"textDocument/completion","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":3,"character":5}}} -# CHECK: "id": 2 -# CHECK-NEXT: "jsonrpc": "2.0", -# CHECK-NEXT: "result": { -# CHECK-NEXT: "isIncomplete": false, -# CHECK-NEXT: "items": [ -# CHECK-NEXT: { -# CHECK-NEXT: "detail": "int", -# CHECK-NEXT: "filterText": "a", -# CHECK-NEXT: "insertText": "a", -# CHECK-NEXT: "insertTextFormat": 1, -# CHECK-NEXT: "kind": 5, -# CHECK-NEXT: "label": "a", -# CHECK-NEXT: "sortText": "{{.*}}" -# CHECK-NEXT: }, -# CHECK-NEXT: { -# CHECK-NEXT: "detail": "int", -# CHECK-NEXT: "filterText": "bb", -# CHECK-NEXT: "insertText": "bb", -# CHECK-NEXT: "insertTextFormat": 1, -# CHECK-NEXT: "kind": 5, -# CHECK-NEXT: "label": "bb", -# CHECK-NEXT: "sortText": "{{.*}}" -# CHECK-NEXT: }, -# CHECK-NEXT: { -# CHECK-NEXT: "detail": "int", -# CHECK-NEXT: "filterText": "ccc", -# CHECK-NEXT: "insertText": "ccc", -# CHECK-NEXT: "insertTextFormat": 1, -# CHECK-NEXT: "kind": 5, -# CHECK-NEXT: "label": "ccc", -# CHECK-NEXT: "sortText": "{{.*}}" -# CHECK-NEXT: }, -# CHECK-NEXT: { -# CHECK-NEXT: "detail": "int", -# CHECK-NEXT: "filterText": "f", -# CHECK-NEXT: "insertText": "f", -# CHECK-NEXT: "insertTextFormat": 1, -# CHECK-NEXT: "kind": 2, -# CHECK-NEXT: "label": "f(int i, const float f) const", -# CHECK-NEXT: "sortText": "{{.*}}" -# CHECK-NEXT: }, -# CHECK-NEXT: { -# CHECK-NEXT: "filterText": "fake", -# CHECK-NEXT: "insertText": "fake", -# CHECK-NEXT: "insertTextFormat": 1, -# CHECK-NEXT: "kind": 7, -# CHECK-NEXT: "label": "fake::", -# CHECK-NEXT: "sortText": "{{.*}}" -# CHECK-NEXT: }, -# CHECK: { -# CHECK: "detail": "void", -# CHECK-NEXT: "filterText": "~fake", -# CHECK-NEXT: "insertText": "~fake", -# CHECK-NEXT: "insertTextFormat": 1, -# CHECK-NEXT: "kind": 4, -# CHECK-NEXT: "label": "~fake()", -# CHECK-NEXT: "sortText": "{{.*}}" -# CHECK-NEXT: } -# CHECK-NEXT: ] +# CHECK: ] # Update the source file and check for completions again. -Content-Length: 226 +Content-Length: 190 -{"jsonrpc":"2.0","method":"textDocument/didChange","params":{"textDocument":{"uri":"file:///main.cpp","version":2},"contentChanges":[{"text":"struct fancy { int (*func())(int, int); };\nint main() {\n fancy f;\n f.\n}\n"}]}} +{"jsonrpc":"2.0","method":"textDocument/didChange","params":{"textDocument":{"uri":"file:///main.cpp","version":2},"contentChanges":[{"text":"struct S { int b; };\nint main() {\nS().\n}"}]}} Content-Length: 148 -{"jsonrpc":"2.0","id":3,"method":"textDocument/completion","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":3,"character":5}}} -# CHECK: "id": 3, +{"jsonrpc":"2.0","id":3,"method":"textDocument/completion","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":2,"character":4}}} +# CHECK: "id": 3, # CHECK-NEXT: "jsonrpc": "2.0", # CHECK-NEXT: "result": { # CHECK-NEXT: "isIncomplete": false, # CHECK-NEXT: "items": [ # CHECK-NEXT: { -# CHECK-NEXT: "detail": "int (*)(int, int)", -# CHECK-NEXT: "filterText": "func", -# CHECK-NEXT: "insertText": "func", -# CHECK-NEXT: "insertTextFormat": 1, -# CHECK-NEXT: "kind": 2, -# CHECK-NEXT: "label": "func()", -# CHECK-NEXT: "sortText": "{{.*}}" -# CHECK-NEXT: }, -# CHECK-NEXT: { -# CHECK-NEXT: "filterText": "fancy", -# CHECK-NEXT: "insertText": "fancy", +# CHECK-NEXT: "detail": "int", +# CHECK-NEXT: "filterText": "b", +# CHECK-NEXT: "insertText": "b", # CHECK-NEXT: "insertTextFormat": 1, -# CHECK-NEXT: "kind": 7, -# CHECK-NEXT: "label": "fancy::", -# CHECK-NEXT: "sortText": "{{.*}}" +# CHECK-NEXT: "kind": 5, +# CHECK-NEXT: "label": "b", +# CHECK-NEXT: "sortText": "{{.*}}b" # CHECK-NEXT: }, -# CHECK: { -# CHECK: "detail": "void", -# CHECK-NEXT: "filterText": "~fancy", -# CHECK-NEXT: "insertText": "~fancy", -# CHECK-NEXT: "insertTextFormat": 1, -# CHECK-NEXT: "kind": 4, -# CHECK-NEXT: "label": "~fancy()", -# CHECK-NEXT: "sortText": "{{.*}}" -# CHECK-NEXT: } -# CHECK-NEXT: ] +# CHECK: ] Content-Length: 44 {"jsonrpc":"2.0","id":4,"method":"shutdown"} -Content-Length: 33 -{"jsonrpc":"2.0":"method":"exit"} Modified: clang-tools-extra/trunk/test/clangd/signature-help.test URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clangd/signature-help.test?rev=321065&r1=321064&r2=321065&view=diff ============================================================================== --- clang-tools-extra/trunk/test/clangd/signature-help.test (original) +++ clang-tools-extra/trunk/test/clangd/signature-help.test Tue Dec 19 02:29:27 2017 @@ -1,4 +1,4 @@ -# RUN: clangd -run-synchronously < %s | FileCheck %s +# RUN: clangd -pretty -run-synchronously < %s | FileCheck -strict-whitespace %s # It is absolutely vital that this file has CRLF line endings. # Start a session. @@ -6,45 +6,32 @@ Content-Length: 125 {"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}} -# Modify the document. -Content-Length: 333 +Content-Length: 172 -{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///main.cpp","languageId":"cpp","version":1,"text":"void foo(int x, int y);\nvoid foo(int x, float y);\nvoid foo(float x, int y);\nvoid foo(float x, float y);\nvoid bar(int x, int y = 0);\nvoid bar(float x = 0, int y = 42);\nint main() { foo("}}} +{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///main.cpp","languageId":"cpp","version":1,"text":"void x(int);\nint main(){\nx("}}} -# Ask for signature help. Content-Length: 151 -{"jsonrpc":"2.0","id":1,"method":"textDocument/signatureHelp","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":8,"character":9}}} -# CHECK: {"id":1,"jsonrpc":"2.0","result":{"activeParameter":0,"activeSignature":0,"signatures":[ -# CHECK-DAG: {"label":"foo(float x, float y) -> void","parameters":[{"label":"float x"},{"label":"float y"}]} -# CHECK-DAG: {"label":"foo(float x, int y) -> void","parameters":[{"label":"float x"},{"label":"int y"}]} -# CHECK-DAG: {"label":"foo(int x, float y) -> void","parameters":[{"label":"int x"},{"label":"float y"}]} -# CHECK-DAG: {"label":"foo(int x, int y) -> void","parameters":[{"label":"int x"},{"label":"int y"}]} -# CHECK-SAME: ]} - -# Modify the document -Content-Length: 333 - -{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///main.cpp","languageId":"cpp","version":2,"text":"void foo(int x, int y);\nvoid foo(int x, float y);\nvoid foo(float x, int y);\nvoid foo(float x, float y);\nvoid bar(int x, int y = 0);\nvoid bar(float x = 0, int y = 42);\nint main() { bar("}}} - -# Ask for signature help (this checks default argument handling). -Content-Length: 151 - -{"jsonrpc":"2.0","id":2,"method":"textDocument/signatureHelp","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":8,"character":9}}} -# CHECK: {"id":2,"jsonrpc":"2.0","result":{"activeParameter":0,"activeSignature":0,"signatures":[ -# CHECK-DAG: {"label":"bar(int x, int y = 0) -> void","parameters":[{"label":"int x"},{"label":"int y = 0"}]} -# CHECK-DAG: {"label":"bar(float x = 0, int y = 42) -> void","parameters":[{"label":"float x = 0"},{"label":"int y = 42"}]} -# CHECK-SAME: ]} - -Content-Length: 159 - -{"jsonrpc":"2.0","id":3,"method":"textDocument/signatureHelp","params":{"textDocument":{"uri":"file:///doesnotexist.cpp"},"position":{"line":8,"character":9}}} -# CHECK: {"error":{"code":-32602,"message":"signatureHelp is called for non-added document"},"id":3,"jsonrpc":"2.0"} +{"jsonrpc":"2.0","id":1,"method":"textDocument/signatureHelp","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":2,"character":2}}} +# CHECK: "id": 1, +# CHECK-NEXT: "jsonrpc": "2.0", +# CHECK-NEXT: "result": { +# CHECK-NEXT: "activeParameter": 0, +# CHECK-NEXT: "activeSignature": 0, +# CHECK-NEXT: "signatures": [ +# CHECK-NEXT: { +# CHECK-NEXT: "label": "x(int) -> void", +# CHECK-NEXT: "parameters": [ +# CHECK-NEXT: { +# CHECK-NEXT: "label": "int" +# CHECK-NEXT: } +# CHECK-NEXT: ] +# CHECK-NEXT: } +# CHECK-NEXT: ] +# CHECK-NEXT: } # Shutdown. Content-Length: 49 {"jsonrpc":"2.0","id":100000,"method":"shutdown"} Content-Length: 33 - -{"jsonrpc":"2.0":"method":"exit"} Modified: clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp?rev=321065&r1=321064&r2=321065&view=diff ============================================================================== --- clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp (original) +++ clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp Tue Dec 19 02:29:27 2017 @@ -17,7 +17,7 @@ namespace clang { namespace clangd { -// Let GMock print completion items. +// Let GMock print completion items and signature help. void PrintTo(const CompletionItem &I, std::ostream *O) { llvm::raw_os_ostream OS(*O); OS << I.label << " - " << toJSON(I); @@ -31,6 +31,19 @@ void PrintTo(const std::vector<Completio } *O << "}"; } +void PrintTo(const SignatureInformation &I, std::ostream *O) { + llvm::raw_os_ostream OS(*O); + OS << I.label << " - " << toJSON(I); +} +void PrintTo(const std::vector<SignatureInformation> &V, std::ostream *O) { + *O << "{\n"; + for (const auto &I : V) { + *O << "\t"; + PrintTo(I, O); + *O << "\n"; + } + *O << "}"; +} namespace { using namespace llvm; @@ -368,6 +381,81 @@ TEST(CompletionTest, Kinds) { EXPECT_THAT(Results.items, Has("namespace", CompletionItemKind::Snippet)); } +SignatureHelp signatures(StringRef Text) { + MockFSProvider FS; + MockCompilationDatabase CDB; + IgnoreDiagnostics DiagConsumer; + ClangdServer Server(CDB, DiagConsumer, FS, getDefaultAsyncThreadsCount(), + /*StorePreamblesInMemory=*/true); + auto File = getVirtualTestFilePath("foo.cpp"); + auto Test = parseTextMarker(Text); + Server.addDocument(Context::empty(), File, Test.Text); + auto R = Server.signatureHelp(Context::empty(), File, Test.MarkerPos); + assert(R); + return R.get().Value; +} + +MATCHER_P(ParamsAre, P, "") { + if (P.size() != arg.parameters.size()) + return false; + for (unsigned I = 0; I < P.size(); ++I) + if (P[I] != arg.parameters[I].label) + return false; + return true; +} + +Matcher<SignatureInformation> Sig(std::string Label, + std::vector<std::string> Params) { + return AllOf(Labeled(Label), ParamsAre(Params)); +} + +TEST(SignatureHelpTest, Overloads) { + auto Results = signatures(R"cpp( + void foo(int x, int y); + void foo(int x, float y); + void foo(float x, int y); + void foo(float x, float y); + void bar(int x, int y = 0); + int main() { foo(^); } + )cpp"); + EXPECT_THAT(Results.signatures, + UnorderedElementsAre( + Sig("foo(float x, float y) -> void", {"float x", "float y"}), + Sig("foo(float x, int y) -> void", {"float x", "int y"}), + Sig("foo(int x, float y) -> void", {"int x", "float y"}), + Sig("foo(int x, int y) -> void", {"int x", "int y"}))); + // We always prefer the first signature. + EXPECT_EQ(0, Results.activeSignature); + EXPECT_EQ(0, Results.activeParameter); +} + +TEST(SignatureHelpTest, DefaultArgs) { + auto Results = signatures(R"cpp( + void bar(int x, int y = 0); + void bar(float x = 0, int y = 42); + int main() { bar(^ + )cpp"); + EXPECT_THAT(Results.signatures, + UnorderedElementsAre( + Sig("bar(int x, int y = 0) -> void", {"int x", "int y = 0"}), + Sig("bar(float x = 0, int y = 42) -> void", + {"float x = 0", "int y = 42"}))); + EXPECT_EQ(0, Results.activeSignature); + EXPECT_EQ(0, Results.activeParameter); +} + +TEST(SignatureHelpTest, ActiveArg) { + auto Results = signatures(R"cpp( + int baz(int a, int b, int c); + int main() { baz(baz(1,2,3), ^); } + )cpp"); + EXPECT_THAT(Results.signatures, + ElementsAre(Sig("baz(int a, int b, int c) -> int", + {"int a", "int b", "int c"}))); + EXPECT_EQ(0, Results.activeSignature); + EXPECT_EQ(1, Results.activeParameter); +} + } // namespace } // namespace clangd } // namespace clang _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits