sammccall created this revision.
Herald added subscribers: cfe-commits, ilya-biryukov, klimek.

This improves readability of tests and error messages.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D40952

Files:
  test/clangd/completion-items-kinds.test
  test/clangd/completion-priorities.test
  test/clangd/completion-qualifiers.test
  test/clangd/completion-snippet.test
  unittests/clangd/CodeCompleteTests.cpp
  unittests/clangd/Matchers.h

Index: unittests/clangd/Matchers.h
===================================================================
--- /dev/null
+++ unittests/clangd/Matchers.h
@@ -0,0 +1,103 @@
+//===-- Matchers.h ----------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// GMock matchers that aren't specific to particular tests.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_UNITTESTS_CLANGD_MATCHERS_H
+#define LLVM_CLANG_TOOLS_EXTRA_UNITTESTS_CLANGD_MATCHERS_H
+#include "gmock/gmock.h"
+
+namespace clang {
+namespace clangd {
+using ::testing::Matcher;
+
+// EXPECT_IFF expects matcher if condition is true, and Not(matcher) if false.
+// This is hard to write as a function, because matchers may be polymorphic.
+#define EXPECT_IFF(condition, value, matcher)                                  \
+  do {                                                                         \
+    if (condition)                                                             \
+      EXPECT_THAT(value, matcher);                                             \
+    else                                                                       \
+      EXPECT_THAT(value, ::testing::Not(matcher));                             \
+  } while (0)
+
+// HasSubsequence(m1, m2, ...) matches a vector containing elements that match
+// m1, m2 ... in that order.
+template <typename T>
+class SubsequenceMatcher
+    : public ::testing::MatcherInterface<const std::vector<T> &> {
+  std::vector<Matcher<T>> Matchers;
+
+public:
+  SubsequenceMatcher(std::vector<Matcher<T>> M) : Matchers(M) {}
+
+  void DescribeTo(std::ostream *OS) const {
+    *OS << "Contains the subsequence [";
+    const char *Sep = "";
+    for (const auto &M : Matchers) {
+      *OS << Sep;
+      M.DescribeTo(OS);
+      Sep = ", ";
+    }
+    *OS << "]";
+  }
+
+  bool MatchAndExplain(const std::vector<T> &V,
+                       ::testing::MatchResultListener *L) const {
+    std::vector<int> Matches(Matchers.size());
+    size_t I = 0;
+    for (size_t J = 0; I < Matchers.size() && J < V.size(); ++J)
+      if (Matchers[I].Matches(V[J]))
+        Matches[I++] = J;
+    if (I == Matchers.size()) // We exhausted all matchers.
+      return true;
+    if (L->IsInterested()) {
+      *L << "\n  Matched:";
+      for (size_t K = 0; K < I; ++K) {
+        *L << "\n\t";
+        Matchers[K].DescribeTo(L->stream());
+        *L << " ==> " << ::testing::PrintToString(V[Matches[K]]);
+      }
+      *L << "\n\t";
+      Matchers[I].DescribeTo(L->stream());
+      *L << " ==> no subsequent match";
+    }
+    return false;
+  }
+};
+
+template <typename... M> class PolySubsequenceMatcher {
+  std::tuple<M...> Matchers;
+
+public:
+  PolySubsequenceMatcher(M &&... Args)
+      : Matchers(std::make_tuple(std::forward<M>(Args)...)) {}
+
+  template <typename T> operator Matcher<const std::vector<T> &>() const {
+    return ::testing::MakeMatcher(new SubsequenceMatcher<T>(
+        TypedMatchers<T>(llvm::index_sequence_for<M...>{})));
+  }
+
+private:
+  template <typename T, size_t... I>
+  std::vector<Matcher<T>> TypedMatchers(llvm::index_sequence<I...>) const {
+    return {std::get<I>(Matchers)...};
+  }
+};
+
+template <typename... Args>
+PolySubsequenceMatcher<Args...> HasSubsequence(Args &&... M) {
+  return PolySubsequenceMatcher<Args...>(std::forward<Args>(M)...);
+}
+
+} // namespace clangd
+} // namespace clang
+#endif
Index: unittests/clangd/CodeCompleteTests.cpp
===================================================================
--- unittests/clangd/CodeCompleteTests.cpp
+++ unittests/clangd/CodeCompleteTests.cpp
@@ -8,6 +8,7 @@
 //===----------------------------------------------------------------------===//
 #include "ClangdServer.h"
 #include "Compiler.h"
+#include "Matchers.h"
 #include "Protocol.h"
 #include "TestFS.h"
 #include "gmock/gmock.h"
@@ -18,15 +19,23 @@
 // Let GMock print completion items.
 void PrintTo(const CompletionItem &I, std::ostream *O) {
   llvm::raw_os_ostream OS(*O);
-  OS << toJSON(I);
+  OS << I.label << " - " << toJSON(I);
+}
+void PrintTo(const std::vector<CompletionItem> &V, std::ostream *O) {
+  *O << "{\n";
+  for (const auto &I : V) {
+    *O << "\t";
+    PrintTo(I, O);
+    *O << "\n";
+  }
+  *O << "}";
 }
 
 namespace {
 using namespace llvm;
 using ::testing::AllOf;
 using ::testing::Contains;
 using ::testing::ElementsAre;
-using ::testing::Matcher;
 using ::testing::Not;
 
 class IgnoreDiagnostics : public DiagnosticsConsumer {
@@ -57,22 +66,25 @@
 
 // GMock helpers for matching completion items.
 MATCHER_P(Named, Name, "") { return arg.insertText == Name; }
+MATCHER_P(Labeled, Label, "") { return arg.label == Label; }
+MATCHER_P(Kind, K, "") { return arg.kind == K; }
+MATCHER_P(PlainText, Text, "") {
+  return arg.insertTextFormat == clangd::InsertTextFormat::PlainText &&
+         arg.insertText == Text;
+}
+MATCHER_P(Snippet, Text, "") {
+  return arg.insertTextFormat == clangd::InsertTextFormat::Snippet &&
+         arg.insertText == Text;
+}
 // Shorthand for Contains(Named(Name)).
 Matcher<const std::vector<CompletionItem> &> Has(std::string Name) {
   return Contains(Named(std::move(Name)));
 }
-MATCHER(IsDocumented, "") { return !arg.documentation.empty(); }
-MATCHER(IsSnippet, "") {
-  return arg.kind == clangd::CompletionItemKind::Snippet;
+Matcher<const std::vector<CompletionItem> &> Has(std::string Name,
+                                                 CompletionItemKind K) {
+  return Contains(AllOf(Named(std::move(Name)), Kind(K)));
 }
-// This is hard to write as a function, because matchers may be polymorphic.
-#define EXPECT_IFF(condition, value, matcher)                                  \
-  do {                                                                         \
-    if (condition)                                                             \
-      EXPECT_THAT(value, matcher);                                             \
-    else                                                                       \
-      EXPECT_THAT(value, ::testing::Not(matcher));                             \
-  } while (0)
+MATCHER(IsDocumented, "") { return !arg.documentation.empty(); }
 
 CompletionList completions(StringRef Text,
                            clangd::CodeCompleteOptions Opts = {}) {
@@ -174,7 +186,7 @@
                                  Has("MACRO"), Has("LocalClass"))));
   // There should be no code patterns (aka snippets) in after-dot
   // completion. At least there aren't any we're aware of.
-  EXPECT_THAT(Results, Not(Contains(IsSnippet())));
+  EXPECT_THAT(Results, Not(Contains(Kind(CompletionItemKind::Snippet))));
   // Check documentation.
   EXPECT_IFF(Opts.IncludeBriefComments, Results, Contains(IsDocumented()));
 }
@@ -217,7 +229,7 @@
   EXPECT_IFF(Opts.IncludeMacros, Results, Has("MACRO"));
   // Local items. Must be present always.
   EXPECT_THAT(Results, AllOf(Has("local_var"), Has("LocalClass"),
-                             Contains(IsSnippet())));
+                             Contains(Kind(CompletionItemKind::Snippet))));
   // Check documentation.
   EXPECT_IFF(Opts.IncludeBriefComments, Results, Contains(IsDocumented()));
 }
@@ -267,6 +279,86 @@
   EXPECT_THAT(Results.items, Contains(Named("cbc")));
 }
 
+TEST(CompletionTest, Priorities) {
+  auto Internal = completions(R"cpp(
+    class Foo {
+      public: void pub();
+      protected: void prot();
+      private: void priv();
+    };
+    void Foo::pub() { this->^ }
+  )cpp");
+  EXPECT_THAT(Internal.items,
+              HasSubsequence(Named("priv"), Named("prot"), Named("pub")));
+
+  auto External = completions(R"cpp(
+    class Foo {
+      public: void pub();
+      protected: void prot();
+      private: void priv();
+    };
+    void test() {
+      Foo F;
+      F.^
+    }
+  )cpp");
+  EXPECT_THAT(External.items,
+              AllOf(Has("pub"), Not(Has("prot")), Not(Has("priv"))));
+}
+
+TEST(CompletionTest, Qualifiers) {
+  auto Results = completions(R"cpp(
+    class Foo {
+      public: int foo() const;
+      int bar() const;
+    };
+    class Bar : public Foo {
+      int foo() const;
+    };
+    void test() { Bar().^ }
+  )cpp");
+  EXPECT_THAT(Results.items, HasSubsequence(Labeled("bar() const"),
+                                            Labeled("Foo::foo() const")));
+  EXPECT_THAT(Results.items, Not(Contains(Labeled("foo() const")))); // private
+}
+
+TEST(CompletionTest, Snippets) {
+  clangd::CodeCompleteOptions Opts;
+  Opts.EnableSnippets = true;
+  auto Results = completions(R"cpp(
+    struct fake {
+      int a;
+      int f(int i, const float f) const;
+    };
+    int main() { fake f; f.^ }
+  )cpp",
+                             Opts);
+  EXPECT_THAT(Results.items,
+              HasSubsequence(PlainText("a"),
+                             Snippet("f(${1:int i}, ${2:const float f})")));
+}
+
+TEST(CompletionTest, Kinds) {
+  auto Results = completions(R"cpp(
+    #define MACRO X
+    int variable;
+    struct Struct {};
+    int function();
+    int X = ^
+  )cpp");
+  EXPECT_THAT(Results.items, Has("function", CompletionItemKind::Function));
+  EXPECT_THAT(Results.items, Has("variable", CompletionItemKind::Variable));
+  EXPECT_THAT(Results.items, Has("int", CompletionItemKind::Keyword));
+  EXPECT_THAT(Results.items, Has("Struct", CompletionItemKind::Class));
+  EXPECT_THAT(Results.items, Has("MACRO", CompletionItemKind::Text));
+
+  clangd::CodeCompleteOptions Opts;
+  Opts.EnableSnippets = true; // Needed for code patterns.
+
+  Results = completions("nam^");
+  EXPECT_THAT(Results.items, Has("namespace", CompletionItemKind::Snippet));
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: test/clangd/completion-snippet.test
===================================================================
--- test/clangd/completion-snippet.test
+++ /dev/null
@@ -1,102 +0,0 @@
-# RUN: clangd -pretty -run-synchronously -enable-snippets < %s | FileCheck -strict-whitespace %s
-# It is absolutely vital that this file has CRLF line endings.
-#
-Content-Length: 125
-
-{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}}
-
-Content-Length: 246
-
-{"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"}}}
-
-Content-Length: 148
-
-{"jsonrpc":"2.0","id":1,"method":"textDocument/completion","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":3,"character":5}}}
-#      CHECK:  "id": 1,
-# 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": "{{.*}}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(${1:int i}, ${2:const float f})",
-# CHECK-NEXT:        "insertTextFormat": 2,
-# 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:      },
-#      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:    ]
-# CHECK-NEXT:  }
-# Update the source file and check for completions again.
-Content-Length: 226
-
-{"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"}]}}
-
-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,
-# 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": "{{.*}}func"
-# CHECK-NEXT:      },
-Content-Length: 44
-
-{"jsonrpc":"2.0","id":4,"method":"shutdown"}
-Content-Length: 33
-
-{"jsonrpc":"2.0":"method":"exit"}
Index: test/clangd/completion-qualifiers.test
===================================================================
--- test/clangd/completion-qualifiers.test
+++ /dev/null
@@ -1,43 +0,0 @@
-# RUN: clangd -pretty -run-synchronously < %s | FileCheck -strict-whitespace %s
-Content-Length: 125
-
-{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}}
-Content-Length: 297
-
-{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///main.cpp","languageId":"cpp","version":1,"text":"class Foo {\n  public:\n    int foo() const;\n    int bar() const;\n};\n\nclass Bar : public Foo {\n  int foo() const;\n};\n\nvoid test() {\n  Bar().\n}"}}}
-Content-Length: 151
-
-{"jsonrpc":"2.0","id":2,"method":"textDocument/completion","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":11,"character":8}}}
-#      CHECK:  "id": 2,
-# CHECK-NEXT:  "jsonrpc": "2.0",
-# CHECK-NEXT:  "result": {
-# CHECK-NEXT:    "isIncomplete": false,
-# CHECK-NEXT:    "items": [
-# Eligible functions are at the top of the list.
-# CHECK-NEXT:      {
-# CHECK-NEXT:        "detail": "int",
-# CHECK-NEXT:        "filterText": "bar",
-# CHECK-NEXT:        "insertText": "bar",
-# CHECK-NEXT:        "insertTextFormat": 1,
-# CHECK-NEXT:        "kind": 2,
-# CHECK-NEXT:        "label": "bar() const",
-# CHECK-NEXT:        "sortText": "{{.*}}bar"
-# CHECK-NEXT:      },
-# CHECK-NEXT:      {
-# CHECK-NEXT:        "detail": "int",
-# CHECK-NEXT:        "filterText": "foo",
-# CHECK-NEXT:        "insertText": "foo",
-# CHECK-NEXT:        "insertTextFormat": 1,
-# CHECK-NEXT:        "kind": 2,
-# CHECK-NEXT:        "label": "Foo::foo() const",
-# CHECK-NEXT:        "sortText": "{{.*}}foo"
-# CHECK-NEXT:      },
-# Ineligible private functions are not present.
-#  CHECK-NOT:        "label": "foo() const",
-#      CHECK:    ]
-Content-Length: 44
-
-{"jsonrpc":"2.0","id":4,"method":"shutdown"}
-Content-Length: 33
-
-{"jsonrpc":"2.0":"method":"exit"}
Index: test/clangd/completion-priorities.test
===================================================================
--- test/clangd/completion-priorities.test
+++ /dev/null
@@ -1,73 +0,0 @@
-# RUN: clangd -pretty -run-synchronously < %s | FileCheck -strict-whitespace %s
-# It is absolutely vital that this file has CRLF line endings.
-#
-
-Content-Length: 127
-
-{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}}
-
-Content-Length: 312
-
-{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///main.cpp","languageId":"cpp","version":1,"text":"class Foo {\npublic:\n  void pub();\n\nprotected:\n  void prot();\n\nprivate:\n  void priv();\n};\n\nvoid Foo::pub() {\n  this->\n}\n\nvoid test() {\n  Foo f;\n  f.\n}"}}}
-
-Content-Length: 151
-
-{"jsonrpc":"2.0","id":2,"method":"textDocument/completion","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":12,"character":8}}}
-#      CHECK:  "id": 2,
-# CHECK-NEXT:  "jsonrpc": "2.0",
-# CHECK-NEXT:  "result": {
-# CHECK-NEXT:    "isIncomplete": false,
-# CHECK-NEXT:    "items": [
-# CHECK-NEXT:      {
-# CHECK-NEXT:        "detail": "void",
-# CHECK-NEXT:        "filterText": "priv",
-# CHECK-NEXT:        "insertText": "priv",
-# CHECK-NEXT:        "insertTextFormat": 1,
-# CHECK-NEXT:        "kind": 2,
-# CHECK-NEXT:        "label": "priv()",
-# CHECK-NEXT:        "sortText": "{{.*}}priv"
-# CHECK-NEXT:      },
-# CHECK-NEXT:      {
-# CHECK-NEXT:        "detail": "void",
-# CHECK-NEXT:        "filterText": "prot",
-# CHECK-NEXT:        "insertText": "prot",
-# CHECK-NEXT:        "insertTextFormat": 1,
-# CHECK-NEXT:        "kind": 2,
-# CHECK-NEXT:        "label": "prot()",
-# CHECK-NEXT:        "sortText": "{{.*}}prot"
-# CHECK-NEXT:      },
-# CHECK-NEXT:      {
-# CHECK-NEXT:        "detail": "void",
-# CHECK-NEXT:        "filterText": "pub",
-# CHECK-NEXT:        "insertText": "pub",
-# CHECK-NEXT:        "insertTextFormat": 1,
-# CHECK-NEXT:        "kind": 2,
-# CHECK-NEXT:        "label": "pub()",
-# CHECK-NEXT:        "sortText": "{{.*}}pub"
-# CHECK-NEXT:      },
-Content-Length: 151
-
-{"jsonrpc":"2.0","id":3,"method":"textDocument/completion","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":17,"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": "void",
-# CHECK-NEXT:        "filterText": "pub",
-# CHECK-NEXT:        "insertText": "pub",
-# CHECK-NEXT:        "insertTextFormat": 1,
-# CHECK-NEXT:        "kind": 2,
-# CHECK-NEXT:        "label": "pub()",
-# CHECK-NEXT:        "sortText": "{{.*}}pub"
-# CHECK-NEXT:      }
-#  CHECK-NOT:        "label": "priv()",
-#  CHECK-NOT:        "label": "prot()",
-#      CHECK:    ]
-Content-Length: 58
-
-{"jsonrpc":"2.0","id":4,"method":"shutdown","params":null}
-Content-Length: 33
-
-{"jsonrpc":"2.0":"method":"exit"}
Index: test/clangd/completion-items-kinds.test
===================================================================
--- test/clangd/completion-items-kinds.test
+++ /dev/null
@@ -1,42 +0,0 @@
-# RUN: clangd -enable-snippets -run-synchronously < %s | FileCheck %s
-# It is absolutely vital that this file has CRLF line endings.
-#
-Content-Length: 125
-
-{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}}
-Content-Length: 220
-
-{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///main.cpp","languageId":"cpp","version":1,"text":"#define MACRO X\nint variable;\nstruct Struct {};\n int function();\nint X = "}}}
-Content-Length: 148
-
-{"jsonrpc":"2.0","id":1,"method":"textDocument/completion","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":4,"character":7}}}
-# CHECK: {"id":1,"jsonrpc":"2.0","result":{"isIncomplete":false,"items":
-#
-# Function
-# CHECK: {"detail":"int","filterText":"function","insertText":"function()","insertTextFormat":1,"kind":3,"label":"function()","sortText":"{{.*}}function"}
-#
-# Variable
-# CHECK: {"detail":"int","filterText":"variable","insertText":"variable","insertTextFormat":1,"kind":6,"label":"variable","sortText":"{{.*}}variable"}
-#
-# Keyword
-# CHECK: {"filterText":"int","insertText":"int","insertTextFormat":1,"kind":14,"label":"int","sortText":"{{.*}}int"}
-#
-# Struct
-# CHECK: {"filterText":"Struct","insertText":"Struct","insertTextFormat":1,"kind":7,"label":"Struct","sortText":"{{.*}}Struct"}
-#
-# Macro
-# CHECK: {"filterText":"MACRO","insertText":"MACRO","insertTextFormat":1,"kind":1,"label":"MACRO","sortText":"{{.*}}MACRO"}
-#
-# CHECK-SAME: ]}}
-Content-Length: 146
-
-{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///main.cpp","languageId":"cpp","version":1,"text":"nam"}}}
-Content-Length: 148
-
-{"jsonrpc":"2.0","id":2,"method":"textDocument/completion","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":1,"character":3}}}
-# Code pattern (unfortunately there are none in expression context)
-# CHECK-DAG: {"filterText":"namespace","insertText":"namespace ${1:identifier}{${2:declarations}\n}","insertTextFormat":2,"kind":15,"label":"namespace identifier{declarations}","sortText":"{{.*}}namespace"}
-#
-Content-Length: 58
-
-{"jsonrpc":"2.0","id":3,"method":"shutdown","params":null}
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to