[clang-tools-extra] r321065 - [clangd] Add unit tests for signature help. SigHelp/CodeComplete lit tests are smoke only.

Sam McCall via cfe-commits cfe-commits at lists.llvm.org
Tue Dec 19 02:29:27 PST 2017


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




More information about the cfe-commits mailing list