clang-tools 19.0.0git
SymbolInfoTests.cpp
Go to the documentation of this file.
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"
14#include <optional>
15
16namespace clang {
17namespace clangd {
18namespace {
19
20using ::testing::UnorderedElementsAreArray;
21
22// Partial SymbolDetails with the rest filled in at testing time.
23struct ExpectedSymbolDetails {
24 std::string Name;
25 std::string Container;
26 std::string USR;
27 const char *DeclMarker = nullptr;
28 const char *DefMarker = nullptr;
29};
30
31TEST(SymbolInfoTests, All) {
32 std::pair<const char *, std::vector<ExpectedSymbolDetails>>
33 TestInputExpectedOutput[] = {
34 {
35 R"cpp( // Simple function reference - declaration
36 void $decl[[foo]]();
37 int bar() {
38 fo^o();
39 }
40 )cpp",
41 {ExpectedSymbolDetails{"foo", "", "c:@F@foo#", "decl"}}},
42 {
43 R"cpp( // Simple function reference - definition
44 void $def[[foo]]() {}
45 int bar() {
46 fo^o();
47 }
48 )cpp",
49 {ExpectedSymbolDetails{"foo", "", "c:@F@foo#", "def", "def"}}},
50 {
51 R"cpp( // Simple function reference - decl and def
52 void $decl[[foo]]();
53 void $def[[foo]]() {}
54 int bar() {
55 fo^o();
56 }
57 )cpp",
58 {ExpectedSymbolDetails{"foo", "", "c:@F@foo#", "decl", "def"}}},
59 {
60 R"cpp( // Simple class reference - decl and def
61 @interface $decl[[Foo]]
62 @end
63 @implementation $def[[Foo]]
64 @end
65 void doSomething(F^oo *obj) {}
66 )cpp",
67 {ExpectedSymbolDetails{"Foo", "", "c:objc(cs)Foo", "decl",
68 "def"}}},
69 {
70 R"cpp( // Simple method reference - decl and def
71 @interface Foo
72 - (void)$decl[[foo]];
73 @end
74 @implementation Foo
75 - (void)$def[[fo^o]] {}
76 @end
77 )cpp",
78 {ExpectedSymbolDetails{"foo", "Foo::", "c:objc(cs)Foo(im)foo",
79 "decl", "def"}}},
80 {
81 R"cpp( // Function in namespace reference
82 namespace bar {
83 void $decl[[foo]]();
84 int baz() {
85 fo^o();
86 }
87 }
88 )cpp",
89 {ExpectedSymbolDetails{"foo", "bar::", "c:@N@bar@F@foo#",
90 "decl"}}},
91 {
92 R"cpp( // Function in different namespace reference
93 namespace bar {
94 void $decl[[foo]]();
95 }
96 namespace barbar {
97 int baz() {
98 bar::fo^o();
99 }
100 }
101 )cpp",
102 {ExpectedSymbolDetails{"foo", "bar::", "c:@N@bar@F@foo#",
103 "decl"}}},
104 {
105 R"cpp( // Function in global namespace reference
106 void $decl[[foo]]();
107 namespace Nbar {
108 namespace Nbaz {
109 int baz() {
110 ::fo^o();
111 }
112 }
113 }
114 )cpp",
115 {ExpectedSymbolDetails{"foo", "", "c:@F@foo#", "decl"}}},
116 {
117 R"cpp( // Function in anonymous namespace reference
118 namespace {
119 void $decl[[foo]]();
120 }
121 namespace barbar {
122 int baz() {
123 fo^o();
124 }
125 }
126 )cpp",
127 {ExpectedSymbolDetails{"foo", "(anonymous)",
128 "c:TestTU.cpp@aN@F@foo#", "decl"}}},
129 {
130 R"cpp( // Function reference - ADL
131 namespace bar {
132 struct BarType {};
133 void $decl[[foo]](const BarType&);
134 }
135 namespace barbar {
136 int baz() {
137 bar::BarType b;
138 fo^o(b);
139 }
140 }
141 )cpp",
142 {ExpectedSymbolDetails{
143 "foo", "bar::", "c:@N@bar@F@foo#&1$@N@bar@S@BarType#",
144 "decl"}}},
145 {
146 R"cpp( // Global value reference
147 int $def[[value]];
148 void foo(int) { }
149 void bar() {
150 foo(val^ue);
151 }
152 )cpp",
153 {ExpectedSymbolDetails{"value", "", "c:@value", "def", "def"}}},
154 {
155 R"cpp( // Local value reference
156 void foo() { int $def[[aaa]]; int bbb = aa^a; }
157 )cpp",
158 {ExpectedSymbolDetails{"aaa", "foo", "c:TestTU.cpp@49@F@foo#@aaa",
159 "def", "def"}}},
160 {
161 R"cpp( // Function param
162 void bar(int $def[[aaa]]) {
163 int bbb = a^aa;
164 }
165 )cpp",
166 {ExpectedSymbolDetails{
167 "aaa", "bar", "c:TestTU.cpp@38@F@bar#I#@aaa", "def", "def"}}},
168 {
169 R"cpp( // Lambda capture
170 void foo() {
171 int $def[[ii]];
172 auto lam = [ii]() {
173 return i^i;
174 };
175 }
176 )cpp",
177 {ExpectedSymbolDetails{"ii", "foo", "c:TestTU.cpp@54@F@foo#@ii",
178 "def", "def"}}},
179 {
180 R"cpp( // Macro reference
181 #define MACRO 5\nint i = MAC^RO;
182 )cpp",
183 {ExpectedSymbolDetails{"MACRO", "",
184 "c:TestTU.cpp@38@macro@MACRO"}}},
185 {
186 R"cpp( // Macro reference
187 #define MACRO 5\nint i = MACRO^;
188 )cpp",
189 {ExpectedSymbolDetails{"MACRO", "",
190 "c:TestTU.cpp@38@macro@MACRO"}}},
191 {
192 R"cpp( // Multiple symbols returned - using overloaded function name
193 void $def[[foo]]() {}
194 void $def_bool[[foo]](bool) {}
195 void $def_int[[foo]](int) {}
196 namespace bar {
197 using ::$decl[[fo^o]];
198 }
199 )cpp",
200 {ExpectedSymbolDetails{"foo", "", "c:@F@foo#", "def", "def"},
201 ExpectedSymbolDetails{"foo", "", "c:@F@foo#b#", "def_bool",
202 "def_bool"},
203 ExpectedSymbolDetails{"foo", "", "c:@F@foo#I#", "def_int",
204 "def_int"},
205 ExpectedSymbolDetails{"foo", "bar::", "c:@N@bar@UD@foo",
206 "decl"}}},
207 {
208 R"cpp( // Multiple symbols returned - implicit conversion
209 struct foo {};
210 struct bar {
211 bar(const foo&) {}
212 };
213 void func_baz1(bar) {}
214 void func_baz2() {
215 foo $def[[ff]];
216 func_baz1(f^f);
217 }
218 )cpp",
219 {ExpectedSymbolDetails{"ff", "func_baz2",
220 "c:TestTU.cpp@218@F@func_baz2#@ff", "def",
221 "def"}}},
222 {
223 R"cpp( // Type reference - declaration
224 struct $decl[[foo]];
225 void bar(fo^o*);
226 )cpp",
227 {ExpectedSymbolDetails{"foo", "", "c:@S@foo", "decl"}}},
228 {
229 R"cpp( // Type reference - definition
230 struct $def[[foo]] {};
231 void bar(fo^o*);
232 )cpp",
233 {ExpectedSymbolDetails{"foo", "", "c:@S@foo", "def", "def"}}},
234 {
235 R"cpp( // Type Reference - template argument
236 struct $def[[foo]] {};
237 template<class T> struct bar {};
238 void baz() {
239 bar<fo^o> b;
240 }
241 )cpp",
242 {ExpectedSymbolDetails{"foo", "", "c:@S@foo", "def", "def"}}},
243 {
244 R"cpp( // Template parameter reference - type param
245 template<class $def[[TT]]> struct bar {
246 T^T t;
247 };
248 )cpp",
249 {ExpectedSymbolDetails{"TT", "bar::", "c:TestTU.cpp@65", "def",
250 "def"}}},
251 {
252 R"cpp( // Template parameter reference - type param
253 template<int $def[[NN]]> struct bar {
254 int a = N^N;
255 };
256 )cpp",
257 {ExpectedSymbolDetails{"NN", "bar::", "c:TestTU.cpp@65", "def",
258 "def"}}},
259 {
260 R"cpp( // Class member reference - objec
261 struct foo {
262 int $def[[aa]];
263 };
264 void bar() {
265 foo f;
266 f.a^a;
267 }
268 )cpp",
269 {ExpectedSymbolDetails{"aa", "foo::", "c:@S@foo@FI@aa", "def",
270 "def"}}},
271 {
272 R"cpp( // Class member reference - pointer
273 struct foo {
274 int $def[[aa]];
275 };
276 void bar() {
277 &foo::a^a;
278 }
279 )cpp",
280 {ExpectedSymbolDetails{"aa", "foo::", "c:@S@foo@FI@aa", "def",
281 "def"}}},
282 {
283 R"cpp( // Class method reference - objec
284 struct foo {
285 void $def[[aa]]() {}
286 };
287 void bar() {
288 foo f;
289 f.a^a();
290 }
291 )cpp",
292 {ExpectedSymbolDetails{"aa", "foo::", "c:@S@foo@F@aa#", "def",
293 "def"}}},
294 {
295 R"cpp( // Class method reference - pointer
296 struct foo {
297 void $def[[aa]]() {}
298 };
299 void bar() {
300 &foo::a^a;
301 }
302 )cpp",
303 {ExpectedSymbolDetails{"aa", "foo::", "c:@S@foo@F@aa#", "def",
304 "def"}}},
305 {
306 R"cpp( // Typedef
307 typedef int $decl[[foo]];
308 void bar() {
309 fo^o a;
310 }
311 )cpp",
312 {ExpectedSymbolDetails{"foo", "", "c:TestTU.cpp@T@foo", "decl"}}},
313 {
314 R"cpp( // Type alias
315 using $decl[[foo]] = int;
316 void bar() {
317 fo^o a;
318 }
319 )cpp",
320 {ExpectedSymbolDetails{"foo", "", "c:@foo", "decl"}}},
321 {
322 R"cpp( // Namespace reference
323 namespace $decl[[foo]] {}
324 using namespace fo^o;
325 )cpp",
326 {ExpectedSymbolDetails{"foo", "", "c:@N@foo", "decl"}}},
327 {
328 R"cpp( // Enum value reference
329 enum foo { $def[[bar]], baz };
330 void f() {
331 foo fff = ba^r;
332 }
333 )cpp",
334 {ExpectedSymbolDetails{"bar", "foo", "c:@E@foo@bar", "def",
335 "def"}}},
336 {
337 R"cpp( // Enum class value reference
338 enum class foo { $def[[bar]], baz };
339 void f() {
340 foo fff = foo::ba^r;
341 }
342 )cpp",
343 {ExpectedSymbolDetails{"bar", "foo::", "c:@E@foo@bar", "def",
344 "def"}}},
345 {
346 R"cpp( // Parameters in declarations
347 void foo(int $def[[ba^r]]);
348 )cpp",
349 {ExpectedSymbolDetails{
350 "bar", "foo", "c:TestTU.cpp@50@F@foo#I#@bar", "def", "def"}}},
351 {
352 R"cpp( // Type inference with auto keyword
353 struct foo {};
354 foo getfoo() { return foo{}; }
355 void f() {
356 au^to a = getfoo();
357 }
358 )cpp",
359 {/* not implemented */}},
360 {
361 R"cpp( // decltype
362 struct foo {};
363 void f() {
364 foo f;
365 declt^ype(f);
366 }
367 )cpp",
368 {/* not implemented */}},
369 };
370
371 for (const auto &T : TestInputExpectedOutput) {
372 Annotations TestInput(T.first);
373 TestTU TU;
374 TU.Code = std::string(TestInput.code());
375 TU.ExtraArgs.push_back("-xobjective-c++");
376 auto AST = TU.build();
377
378 std::vector<SymbolDetails> Expected;
379 for (const auto &Sym : T.second) {
380 std::optional<Location> Decl, Def;
381 if (Sym.DeclMarker)
383 TestInput.range(Sym.DeclMarker)};
384 if (Sym.DefMarker)
385 Def = Location{URIForFile::canonicalize(testPath(TU.Filename), ""),
386 TestInput.range(Sym.DefMarker)};
387 Expected.push_back(
388 {Sym.Name, Sym.Container, Sym.USR, SymbolID(Sym.USR), Decl, Def});
389 }
390
391 EXPECT_THAT(getSymbolInfo(AST, TestInput.point()),
392 UnorderedElementsAreArray(Expected))
393 << T.first;
394 }
395}
396
397} // namespace
398} // namespace clangd
399} // namespace clang
const FunctionDecl * Decl
llvm::SmallString< 256U > Name
std::vector< const char * > Expected
std::string Container
const char * DefMarker
std::string USR
const char * DeclMarker
std::vector< SymbolDetails > getSymbolInfo(ParsedAST &AST, Position Pos)
Get info about symbols at Pos.
Definition: XRefs.cpp:1592
std::string testPath(PathRef File, llvm::sys::path::Style Style)
Definition: TestFS.cpp:93
TEST(BackgroundQueueTest, Priority)
std::array< uint8_t, 20 > SymbolID
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
static URIForFile canonicalize(llvm::StringRef AbsPath, llvm::StringRef TUPath)
Canonicalizes AbsPath via URI.
Definition: Protocol.cpp:46