[docs] Add LICENSE.txt to the root of the mono-repo
[llvm-project.git] / clang-tools-extra / clangd / unittests / SymbolInfoTests.cpp
blobf68f87fef1560f5a5374d3c4ce3aa0cd5d37ca9c
1 //===-- SymbolInfoTests.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 #include "Annotations.h"
9 #include "ParsedAST.h"
10 #include "TestTU.h"
11 #include "XRefs.h"
12 #include "gmock/gmock.h"
13 #include "gtest/gtest.h"
15 namespace clang {
16 namespace clangd {
17 namespace {
19 using ::testing::UnorderedElementsAreArray;
21 // Partial SymbolDetails with the rest filled in at testing time.
22 struct ExpectedSymbolDetails {
23 std::string Name;
24 std::string Container;
25 std::string USR;
26 const char *DeclMarker = nullptr;
27 const char *DefMarker = nullptr;
30 TEST(SymbolInfoTests, All) {
31 std::pair<const char *, std::vector<ExpectedSymbolDetails>>
32 TestInputExpectedOutput[] = {
34 R"cpp( // Simple function reference - declaration
35 void $decl[[foo]]();
36 int bar() {
37 fo^o();
39 )cpp",
40 {ExpectedSymbolDetails{"foo", "", "c:@F@foo#", "decl"}}},
42 R"cpp( // Simple function reference - definition
43 void $def[[foo]]() {}
44 int bar() {
45 fo^o();
47 )cpp",
48 {ExpectedSymbolDetails{"foo", "", "c:@F@foo#", "def", "def"}}},
50 R"cpp( // Simple function reference - decl and def
51 void $decl[[foo]]();
52 void $def[[foo]]() {}
53 int bar() {
54 fo^o();
56 )cpp",
57 {ExpectedSymbolDetails{"foo", "", "c:@F@foo#", "decl", "def"}}},
59 R"cpp( // Simple class reference - decl and def
60 @interface $decl[[Foo]]
61 @end
62 @implementation $def[[Foo]]
63 @end
64 void doSomething(F^oo *obj) {}
65 )cpp",
66 {ExpectedSymbolDetails{"Foo", "", "c:objc(cs)Foo", "decl",
67 "def"}}},
69 R"cpp( // Simple method reference - decl and def
70 @interface Foo
71 - (void)$decl[[foo]];
72 @end
73 @implementation Foo
74 - (void)$def[[fo^o]] {}
75 @end
76 )cpp",
77 {ExpectedSymbolDetails{"foo", "Foo::", "c:objc(cs)Foo(im)foo",
78 "decl", "def"}}},
80 R"cpp( // Function in namespace reference
81 namespace bar {
82 void $decl[[foo]]();
83 int baz() {
84 fo^o();
87 )cpp",
88 {ExpectedSymbolDetails{"foo", "bar::", "c:@N@bar@F@foo#",
89 "decl"}}},
91 R"cpp( // Function in different namespace reference
92 namespace bar {
93 void $decl[[foo]]();
95 namespace barbar {
96 int baz() {
97 bar::fo^o();
100 )cpp",
101 {ExpectedSymbolDetails{"foo", "bar::", "c:@N@bar@F@foo#",
102 "decl"}}},
104 R"cpp( // Function in global namespace reference
105 void $decl[[foo]]();
106 namespace Nbar {
107 namespace Nbaz {
108 int baz() {
109 ::fo^o();
113 )cpp",
114 {ExpectedSymbolDetails{"foo", "", "c:@F@foo#", "decl"}}},
116 R"cpp( // Function in anonymous namespace reference
117 namespace {
118 void $decl[[foo]]();
120 namespace barbar {
121 int baz() {
122 fo^o();
125 )cpp",
126 {ExpectedSymbolDetails{"foo", "(anonymous)",
127 "c:TestTU.cpp@aN@F@foo#", "decl"}}},
129 R"cpp( // Function reference - ADL
130 namespace bar {
131 struct BarType {};
132 void $decl[[foo]](const BarType&);
134 namespace barbar {
135 int baz() {
136 bar::BarType b;
137 fo^o(b);
140 )cpp",
141 {ExpectedSymbolDetails{
142 "foo", "bar::", "c:@N@bar@F@foo#&1$@N@bar@S@BarType#",
143 "decl"}}},
145 R"cpp( // Global value reference
146 int $def[[value]];
147 void foo(int) { }
148 void bar() {
149 foo(val^ue);
151 )cpp",
152 {ExpectedSymbolDetails{"value", "", "c:@value", "def", "def"}}},
154 R"cpp( // Local value reference
155 void foo() { int $def[[aaa]]; int bbb = aa^a; }
156 )cpp",
157 {ExpectedSymbolDetails{"aaa", "foo", "c:TestTU.cpp@49@F@foo#@aaa",
158 "def", "def"}}},
160 R"cpp( // Function param
161 void bar(int $def[[aaa]]) {
162 int bbb = a^aa;
164 )cpp",
165 {ExpectedSymbolDetails{
166 "aaa", "bar", "c:TestTU.cpp@38@F@bar#I#@aaa", "def", "def"}}},
168 R"cpp( // Lambda capture
169 void foo() {
170 int $def[[ii]];
171 auto lam = [ii]() {
172 return i^i;
175 )cpp",
176 {ExpectedSymbolDetails{"ii", "foo", "c:TestTU.cpp@54@F@foo#@ii",
177 "def", "def"}}},
179 R"cpp( // Macro reference
180 #define MACRO 5\nint i = MAC^RO;
181 )cpp",
182 {ExpectedSymbolDetails{"MACRO", "",
183 "c:TestTU.cpp@38@macro@MACRO"}}},
185 R"cpp( // Macro reference
186 #define MACRO 5\nint i = MACRO^;
187 )cpp",
188 {ExpectedSymbolDetails{"MACRO", "",
189 "c:TestTU.cpp@38@macro@MACRO"}}},
191 R"cpp( // Multiple symbols returned - using overloaded function name
192 void $def[[foo]]() {}
193 void $def_bool[[foo]](bool) {}
194 void $def_int[[foo]](int) {}
195 namespace bar {
196 using ::$decl[[fo^o]];
198 )cpp",
199 {ExpectedSymbolDetails{"foo", "", "c:@F@foo#", "def", "def"},
200 ExpectedSymbolDetails{"foo", "", "c:@F@foo#b#", "def_bool",
201 "def_bool"},
202 ExpectedSymbolDetails{"foo", "", "c:@F@foo#I#", "def_int",
203 "def_int"},
204 ExpectedSymbolDetails{"foo", "bar::", "c:@N@bar@UD@foo",
205 "decl"}}},
207 R"cpp( // Multiple symbols returned - implicit conversion
208 struct foo {};
209 struct bar {
210 bar(const foo&) {}
212 void func_baz1(bar) {}
213 void func_baz2() {
214 foo $def[[ff]];
215 func_baz1(f^f);
217 )cpp",
218 {ExpectedSymbolDetails{"ff", "func_baz2",
219 "c:TestTU.cpp@218@F@func_baz2#@ff", "def",
220 "def"}}},
222 R"cpp( // Type reference - declaration
223 struct $decl[[foo]];
224 void bar(fo^o*);
225 )cpp",
226 {ExpectedSymbolDetails{"foo", "", "c:@S@foo", "decl"}}},
228 R"cpp( // Type reference - definition
229 struct $def[[foo]] {};
230 void bar(fo^o*);
231 )cpp",
232 {ExpectedSymbolDetails{"foo", "", "c:@S@foo", "def", "def"}}},
234 R"cpp( // Type Reference - template argument
235 struct $def[[foo]] {};
236 template<class T> struct bar {};
237 void baz() {
238 bar<fo^o> b;
240 )cpp",
241 {ExpectedSymbolDetails{"foo", "", "c:@S@foo", "def", "def"}}},
243 R"cpp( // Template parameter reference - type param
244 template<class $def[[TT]]> struct bar {
245 T^T t;
247 )cpp",
248 {ExpectedSymbolDetails{"TT", "bar::", "c:TestTU.cpp@65", "def",
249 "def"}}},
251 R"cpp( // Template parameter reference - type param
252 template<int $def[[NN]]> struct bar {
253 int a = N^N;
255 )cpp",
256 {ExpectedSymbolDetails{"NN", "bar::", "c:TestTU.cpp@65", "def",
257 "def"}}},
259 R"cpp( // Class member reference - objec
260 struct foo {
261 int $def[[aa]];
263 void bar() {
264 foo f;
265 f.a^a;
267 )cpp",
268 {ExpectedSymbolDetails{"aa", "foo::", "c:@S@foo@FI@aa", "def",
269 "def"}}},
271 R"cpp( // Class member reference - pointer
272 struct foo {
273 int $def[[aa]];
275 void bar() {
276 &foo::a^a;
278 )cpp",
279 {ExpectedSymbolDetails{"aa", "foo::", "c:@S@foo@FI@aa", "def",
280 "def"}}},
282 R"cpp( // Class method reference - objec
283 struct foo {
284 void $def[[aa]]() {}
286 void bar() {
287 foo f;
288 f.a^a();
290 )cpp",
291 {ExpectedSymbolDetails{"aa", "foo::", "c:@S@foo@F@aa#", "def",
292 "def"}}},
294 R"cpp( // Class method reference - pointer
295 struct foo {
296 void $def[[aa]]() {}
298 void bar() {
299 &foo::a^a;
301 )cpp",
302 {ExpectedSymbolDetails{"aa", "foo::", "c:@S@foo@F@aa#", "def",
303 "def"}}},
305 R"cpp( // Typedef
306 typedef int $decl[[foo]];
307 void bar() {
308 fo^o a;
310 )cpp",
311 {ExpectedSymbolDetails{"foo", "", "c:TestTU.cpp@T@foo", "decl"}}},
313 R"cpp( // Type alias
314 using $decl[[foo]] = int;
315 void bar() {
316 fo^o a;
318 )cpp",
319 {ExpectedSymbolDetails{"foo", "", "c:@foo", "decl"}}},
321 R"cpp( // Namespace reference
322 namespace $decl[[foo]] {}
323 using namespace fo^o;
324 )cpp",
325 {ExpectedSymbolDetails{"foo", "", "c:@N@foo", "decl"}}},
327 R"cpp( // Enum value reference
328 enum foo { $def[[bar]], baz };
329 void f() {
330 foo fff = ba^r;
332 )cpp",
333 {ExpectedSymbolDetails{"bar", "foo", "c:@E@foo@bar", "def",
334 "def"}}},
336 R"cpp( // Enum class value reference
337 enum class foo { $def[[bar]], baz };
338 void f() {
339 foo fff = foo::ba^r;
341 )cpp",
342 {ExpectedSymbolDetails{"bar", "foo::", "c:@E@foo@bar", "def",
343 "def"}}},
345 R"cpp( // Parameters in declarations
346 void foo(int $def[[ba^r]]);
347 )cpp",
348 {ExpectedSymbolDetails{
349 "bar", "foo", "c:TestTU.cpp@50@F@foo#I#@bar", "def", "def"}}},
351 R"cpp( // Type inference with auto keyword
352 struct foo {};
353 foo getfoo() { return foo{}; }
354 void f() {
355 au^to a = getfoo();
357 )cpp",
358 {/* not implemented */}},
360 R"cpp( // decltype
361 struct foo {};
362 void f() {
363 foo f;
364 declt^ype(f);
366 )cpp",
367 {/* not implemented */}},
370 for (const auto &T : TestInputExpectedOutput) {
371 Annotations TestInput(T.first);
372 TestTU TU;
373 TU.Code = std::string(TestInput.code());
374 TU.ExtraArgs.push_back("-xobjective-c++");
375 auto AST = TU.build();
377 std::vector<SymbolDetails> Expected;
378 for (const auto &Sym : T.second) {
379 llvm::Optional<Location> Decl, Def;
380 if (Sym.DeclMarker)
381 Decl = Location{URIForFile::canonicalize(testPath(TU.Filename), ""),
382 TestInput.range(Sym.DeclMarker)};
383 if (Sym.DefMarker)
384 Def = Location{URIForFile::canonicalize(testPath(TU.Filename), ""),
385 TestInput.range(Sym.DefMarker)};
386 Expected.push_back(
387 {Sym.Name, Sym.Container, Sym.USR, SymbolID(Sym.USR), Decl, Def});
390 EXPECT_THAT(getSymbolInfo(AST, TestInput.point()),
391 UnorderedElementsAreArray(Expected))
392 << T.first;
396 } // namespace
397 } // namespace clangd
398 } // namespace clang