[clang-tools-extra] r320148 - [clangd] Convert lit code completion tests to unit-tests. NFC

Sam McCall via cfe-commits cfe-commits at lists.llvm.org
Fri Dec 8 07:00:59 PST 2017


Author: sammccall
Date: Fri Dec  8 07:00:59 2017
New Revision: 320148

URL: http://llvm.org/viewvc/llvm-project?rev=320148&view=rev
Log:
[clangd] Convert lit code completion tests to unit-tests. NFC

Summary: This improves readability of tests and error messages.

Reviewers: ioeric

Subscribers: klimek, ilya-biryukov, cfe-commits

Differential Revision: https://reviews.llvm.org/D40952

Added:
    clang-tools-extra/trunk/unittests/clangd/Matchers.h
Removed:
    clang-tools-extra/trunk/test/clangd/completion-items-kinds.test
    clang-tools-extra/trunk/test/clangd/completion-priorities.test
    clang-tools-extra/trunk/test/clangd/completion-qualifiers.test
    clang-tools-extra/trunk/test/clangd/completion-snippet.test
Modified:
    clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp

Removed: clang-tools-extra/trunk/test/clangd/completion-items-kinds.test
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clangd/completion-items-kinds.test?rev=320147&view=auto
==============================================================================
--- clang-tools-extra/trunk/test/clangd/completion-items-kinds.test (original)
+++ clang-tools-extra/trunk/test/clangd/completion-items-kinds.test (removed)
@@ -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}

Removed: clang-tools-extra/trunk/test/clangd/completion-priorities.test
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clangd/completion-priorities.test?rev=320147&view=auto
==============================================================================
--- clang-tools-extra/trunk/test/clangd/completion-priorities.test (original)
+++ clang-tools-extra/trunk/test/clangd/completion-priorities.test (removed)
@@ -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"}

Removed: clang-tools-extra/trunk/test/clangd/completion-qualifiers.test
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clangd/completion-qualifiers.test?rev=320147&view=auto
==============================================================================
--- clang-tools-extra/trunk/test/clangd/completion-qualifiers.test (original)
+++ clang-tools-extra/trunk/test/clangd/completion-qualifiers.test (removed)
@@ -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"}

Removed: clang-tools-extra/trunk/test/clangd/completion-snippet.test
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clangd/completion-snippet.test?rev=320147&view=auto
==============================================================================
--- clang-tools-extra/trunk/test/clangd/completion-snippet.test (original)
+++ clang-tools-extra/trunk/test/clangd/completion-snippet.test (removed)
@@ -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"}

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=320148&r1=320147&r2=320148&view=diff
==============================================================================
--- clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp (original)
+++ clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp Fri Dec  8 07:00:59 2017
@@ -8,6 +8,7 @@
 //===----------------------------------------------------------------------===//
 #include "ClangdServer.h"
 #include "Compiler.h"
+#include "Matchers.h"
 #include "Protocol.h"
 #include "TestFS.h"
 #include "gmock/gmock.h"
@@ -18,7 +19,16 @@ namespace clangd {
 // 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 {
@@ -26,7 +36,6 @@ 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 @@ StringWithPos parseTextMarker(StringRef
 
 // 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 = {}) {
@@ -133,93 +145,97 @@ TEST(CompletionTest, Filter) {
 }
 
 void TestAfterDotCompletion(clangd::CodeCompleteOptions Opts) {
-  auto Results = completions(R"cpp(
-#define MACRO X
+  auto Results = completions(
+      R"cpp(
+      #define MACRO X
 
-int global_var;
+      int global_var;
 
-int global_func();
+      int global_func();
 
-struct GlobalClass {};
+      struct GlobalClass {};
 
-struct ClassWithMembers {
-  /// Doc for method.
-  int method();
+      struct ClassWithMembers {
+        /// Doc for method.
+        int method();
 
-  int field;
-private:
-  int private_field;
-};
+        int field;
+      private:
+        int private_field;
+      };
 
-int test() {
-  struct LocalClass {};
+      int test() {
+        struct LocalClass {};
 
-  /// Doc for local_var.
-  int local_var;
+        /// Doc for local_var.
+        int local_var;
 
-  ClassWithMembers().^
-}
-)cpp",
-                             Opts)
-                     .items;
+        ClassWithMembers().^
+      }
+      )cpp",
+      Opts);
 
   // Class members. The only items that must be present in after-dot
   // completion.
-  EXPECT_THAT(Results, AllOf(Has(Opts.EnableSnippets ? "method()" : "method"),
-                             Has("field")));
-  EXPECT_IFF(Opts.IncludeIneligibleResults, Results, Has("private_field"));
+  EXPECT_THAT(
+      Results.items,
+      AllOf(Has(Opts.EnableSnippets ? "method()" : "method"), Has("field")));
+  EXPECT_IFF(Opts.IncludeIneligibleResults, Results.items,
+             Has("private_field"));
   // Global items.
-  EXPECT_THAT(Results, Not(AnyOf(Has("global_var"), Has("global_func"),
-                                 Has("global_func()"), Has("GlobalClass"),
-                                 Has("MACRO"), Has("LocalClass"))));
+  EXPECT_THAT(Results.items, Not(AnyOf(Has("global_var"), Has("global_func"),
+                                       Has("global_func()"), Has("GlobalClass"),
+                                       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.items, Not(Contains(Kind(CompletionItemKind::Snippet))));
   // Check documentation.
-  EXPECT_IFF(Opts.IncludeBriefComments, Results, Contains(IsDocumented()));
+  EXPECT_IFF(Opts.IncludeBriefComments, Results.items,
+             Contains(IsDocumented()));
 }
 
 void TestGlobalScopeCompletion(clangd::CodeCompleteOptions Opts) {
-  auto Results = completions(R"cpp(
-#define MACRO X
+  auto Results = completions(
+      R"cpp(
+      #define MACRO X
 
-int global_var;
-int global_func();
+      int global_var;
+      int global_func();
 
-struct GlobalClass {};
+      struct GlobalClass {};
 
-struct ClassWithMembers {
-  /// Doc for method.
-  int method();
-};
+      struct ClassWithMembers {
+        /// Doc for method.
+        int method();
+      };
 
-int test() {
-  struct LocalClass {};
+      int test() {
+        struct LocalClass {};
 
-  /// Doc for local_var.
-  int local_var;
+        /// Doc for local_var.
+        int local_var;
 
-  ^
-}
-)cpp",
-                             Opts)
-                     .items;
+        ^
+      }
+      )cpp",
+      Opts);
 
   // Class members. Should never be present in global completions.
-  EXPECT_THAT(Results,
+  EXPECT_THAT(Results.items,
               Not(AnyOf(Has("method"), Has("method()"), Has("field"))));
   // Global items.
-  EXPECT_IFF(Opts.IncludeGlobals, Results,
+  EXPECT_IFF(Opts.IncludeGlobals, Results.items,
              AllOf(Has("global_var"),
                    Has(Opts.EnableSnippets ? "global_func()" : "global_func"),
                    Has("GlobalClass")));
   // A macro.
-  EXPECT_IFF(Opts.IncludeMacros, Results, Has("MACRO"));
+  EXPECT_IFF(Opts.IncludeMacros, Results.items, Has("MACRO"));
   // Local items. Must be present always.
-  EXPECT_THAT(Results, AllOf(Has("local_var"), Has("LocalClass"),
-                             Contains(IsSnippet())));
+  EXPECT_THAT(Results.items, AllOf(Has("local_var"), Has("LocalClass"),
+                             Contains(Kind(CompletionItemKind::Snippet))));
   // Check documentation.
-  EXPECT_IFF(Opts.IncludeBriefComments, Results, Contains(IsDocumented()));
+  EXPECT_IFF(Opts.IncludeBriefComments, Results.items,
+             Contains(IsDocumented()));
 }
 
 TEST(CompletionTest, CompletionOptions) {
@@ -267,6 +283,90 @@ TEST(CompletionTest, CheckContentsOverri
   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

Added: clang-tools-extra/trunk/unittests/clangd/Matchers.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/clangd/Matchers.h?rev=320148&view=auto
==============================================================================
--- clang-tools-extra/trunk/unittests/clangd/Matchers.h (added)
+++ clang-tools-extra/trunk/unittests/clangd/Matchers.h Fri Dec  8 07:00:59 2017
@@ -0,0 +1,112 @@
+//===-- 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.
+//
+// SubsequenceMatcher implements this once the type of vector is known.
+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 override {
+    *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 override {
+    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;
+  }
+};
+
+// PolySubsequenceMatcher implements a "polymorphic" SubsequenceMatcher.
+// It captures the types of the element matchers, and can be converted to
+// Matcher<vector<T>> if each matcher can be converted to Matcher<T>.
+// This allows HasSubsequence() to accept polymorphic matchers like Not().
+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)...};
+  }
+};
+
+// HasSubsequence(m1, m2, ...) matches a vector containing elements that match
+// m1, m2 ... in that order.
+// The real implementation is in SubsequenceMatcher.
+template <typename... Args>
+PolySubsequenceMatcher<Args...> HasSubsequence(Args &&... M) {
+  return PolySubsequenceMatcher<Args...>(std::forward<Args>(M)...);
+}
+
+} // namespace clangd
+} // namespace clang
+#endif




More information about the cfe-commits mailing list