clang-tools  10.0.0git
SemanticSelectionTests.cpp
Go to the documentation of this file.
1 //===-- SemanticSelectionTests.cpp ----------------*- C++ -*--------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "Annotations.h"
10 #include "ClangdServer.h"
11 #include "Matchers.h"
12 #include "Protocol.h"
13 #include "SemanticSelection.h"
14 #include "SourceCode.h"
15 #include "SyncAPI.h"
16 #include "TestFS.h"
17 #include "TestTU.h"
18 #include "clang/Basic/SourceLocation.h"
19 #include "clang/Basic/SourceManager.h"
20 #include "llvm/Support/Error.h"
21 #include "gmock/gmock.h"
22 #include "gtest/gtest.h"
23 #include <vector>
24 namespace clang {
25 namespace clangd {
26 namespace {
27 using ::testing::ElementsAreArray;
28 
29 class IgnoreDiagnostics : public DiagnosticsConsumer {
31  std::vector<Diag> Diagnostics) override {}
32 };
33 
34 TEST(SemanticSelection, All) {
35  const char *Tests[] = {
36  R"cpp( // Single statement in a function body.
37  [[void func() [[{
38  [[[[int v = [[1^00]]]];]]
39  }]]]]
40  )cpp",
41  R"cpp( // Expression
42  [[void func() [[{
43  int a = 1;
44  // int v = (10 + 2) * (a + a);
45  [[[[int v = [[[[([[[[10^]] + 2]])]] * (a + a)]]]];]]
46  }]]]]
47  )cpp",
48  R"cpp( // Function call.
49  int add(int x, int y) { return x + y; }
50  [[void callee() [[{
51  // int res = add(11, 22);
52  [[[[int res = [[add([[1^1]], 22)]]]];]]
53  }]]]]
54  )cpp",
55  R"cpp( // Tricky macros.
56  #define MUL ) * (
57  [[void func() [[{
58  // int var = (4 + 15 MUL 6 + 10);
59  [[[[int var = [[[[([[4 + [[1^5]]]] MUL]] 6 + 10)]]]];]]
60  }]]]]
61  )cpp",
62  R"cpp( // Cursor inside a macro.
63  #define HASH(x) ((x) % 10)
64  [[void func() [[{
65  [[[[int a = [[HASH([[[[2^3]] + 34]])]]]];]]
66  }]]]]
67  )cpp",
68  R"cpp( // Cursor on a macro.
69  #define HASH(x) ((x) % 10)
70  [[void func() [[{
71  [[[[int a = [[HA^SH(23)]]]];]]
72  }]]]]
73  )cpp",
74  R"cpp( // Multiple declaration.
75  [[void func() [[{
76  [[[[int var1, var^2]], var3;]]
77  }]]]]
78  )cpp",
79  R"cpp( // Before comment.
80  [[void func() [[{
81  int var1 = 1;
82  [[[[int var2 = [[[[var1]]^ /*some comment*/ + 41]]]];]]
83  }]]]]
84  )cpp",
85  // Empty file.
86  "^",
87  // FIXME: We should get the whole DeclStmt as a range.
88  R"cpp( // Single statement in TU.
89  [[int v = [[1^00]]]];
90  )cpp",
91  R"cpp( // Cursor at end of VarDecl.
92  [[int v = [[100]]^]];
93  )cpp",
94  // FIXME: No node found associated to the position.
95  R"cpp( // Cursor in between spaces.
96  void func() {
97  int v = 100 + ^ 100;
98  }
99  )cpp",
100  // Structs.
101  R"cpp(
102  struct AAA { struct BBB { static int ccc(); };};
103  [[void func() [[{
104  // int x = AAA::BBB::ccc();
105  [[[[int x = [[[[AAA::BBB::c^cc]]()]]]];]]
106  }]]]]
107  )cpp",
108  R"cpp(
109  struct AAA { struct BBB { static int ccc(); };};
110  [[void func() [[{
111  // int x = AAA::BBB::ccc();
112  [[[[int x = [[[[[[[[[[AA^A]]::]]BBB::]]ccc]]()]]]];]]
113  }]]]]
114  )cpp",
115  R"cpp( // Inside struct.
116  struct A { static int a(); };
117  [[struct B {
118  [[static int b() [[{
119  [[return [[[[1^1]] + 2]]]];
120  }]]]]
121  }]];
122  )cpp",
123  // Namespaces.
124  R"cpp(
125  [[namespace nsa {
126  [[namespace nsb {
127  static int ccc();
128  [[void func() [[{
129  // int x = nsa::nsb::ccc();
130  [[[[int x = [[[[nsa::nsb::cc^c]]()]]]];]]
131  }]]]]
132  }]]
133  }]]
134  )cpp",
135 
136  };
137 
138  for (const char *Test : Tests) {
139  auto T = Annotations(Test);
140  auto AST = TestTU::withCode(T.code()).build();
141  EXPECT_THAT(llvm::cantFail(getSemanticRanges(AST, T.point())),
142  ElementsAreArray(T.ranges()))
143  << Test;
144  }
145 }
146 
147 TEST(SemanticSelection, RunViaClangDServer) {
148  MockFSProvider FS;
149  IgnoreDiagnostics DiagConsumer;
150  MockCompilationDatabase CDB;
151  ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
152 
153  auto FooH = testPath("foo.h");
154  FS.Files[FooH] = R"cpp(
155  int foo(int x);
156  #define HASH(x) ((x) % 10)
157  )cpp";
158 
159  auto FooCpp = testPath("Foo.cpp");
160  const char *SourceContents = R"cpp(
161  #include "foo.h"
162  [[void bar(int& inp) [[{
163  // inp = HASH(foo(inp));
164  [[inp = [[HASH([[foo([[in^p]])]])]]]];
165  }]]]]
166  )cpp";
167  Annotations SourceAnnotations(SourceContents);
168  FS.Files[FooCpp] = SourceAnnotations.code();
169  Server.addDocument(FooCpp, SourceAnnotations.code());
170 
171  auto Ranges = runSemanticRanges(Server, FooCpp, SourceAnnotations.point());
172  ASSERT_TRUE(bool(Ranges))
173  << "getSemanticRange returned an error: " << Ranges.takeError();
174  EXPECT_THAT(*Ranges, ElementsAreArray(SourceAnnotations.ranges()));
175 }
176 } // namespace
177 } // namespace clangd
178 } // namespace clang
llvm::Expected< std::vector< Range > > runSemanticRanges(ClangdServer &Server, PathRef File, Position Pos)
Definition: SyncAPI.cpp:148
llvm::StringRef PathRef
A typedef to represent a ref to file path.
Definition: Path.h:23
MockFSProvider FS
static Options optsForTest()
TEST(BackgroundQueueTest, Priority)
std::string testPath(PathRef File)
Definition: TestFS.cpp:82
virtual void onDiagnosticsReady(PathRef File, std::vector< Diag > Diagnostics)=0
Called by ClangdServer when Diagnostics for File are ready.
llvm::Expected< std::vector< Range > > getSemanticRanges(ParsedAST &AST, Position Pos)
Returns the list of all interesting ranges around the Position Pos.
static TestTU withCode(llvm::StringRef Code)
Definition: TestTU.h:33
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
ClangdServer Server
IgnoreDiagnostics DiagConsumer