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 "Compiler.h"
10 #include "Matchers.h"
11 #include "ParsedAST.h"
12 #include "SyncAPI.h"
13 #include "TestFS.h"
14 #include "TestTU.h"
15 #include "XRefs.h"
16 #include "index/FileIndex.h"
17 #include "index/SymbolCollector.h"
18 #include "clang/Index/IndexingAction.h"
19 #include "llvm/Support/Path.h"
20 #include "gmock/gmock.h"
21 #include "gtest/gtest.h"
22
23 namespace clang {
24 namespace clangd {
25 namespace {
26
27 using ::testing::UnorderedElementsAreArray;
28
29 auto CreateExpectedSymbolDetails = [](const std::string &name,
30 const std::string &container,
__anon6ff7cb020202(const std::string &name, const std::string &container, const std::string &USR) 31 const std::string &USR) {
32 return SymbolDetails{name, container, USR, SymbolID(USR)};
33 };
34
TEST(SymbolInfoTests,All)35 TEST(SymbolInfoTests, All) {
36 std::pair<const char *, std::vector<SymbolDetails>>
37 TestInputExpectedOutput[] = {
38 {
39 R"cpp( // Simple function reference - declaration
40 void foo();
41 int bar() {
42 fo^o();
43 }
44 )cpp",
45 {CreateExpectedSymbolDetails("foo", "", "c:@F@foo#")}},
46 {
47 R"cpp( // Simple function reference - definition
48 void foo() {}
49 int bar() {
50 fo^o();
51 }
52 )cpp",
53 {CreateExpectedSymbolDetails("foo", "", "c:@F@foo#")}},
54 {
55 R"cpp( // Function in namespace reference
56 namespace bar {
57 void foo();
58 int baz() {
59 fo^o();
60 }
61 }
62 )cpp",
63 {CreateExpectedSymbolDetails("foo", "bar::", "c:@N@bar@F@foo#")}},
64 {
65 R"cpp( // Function in different namespace reference
66 namespace bar {
67 void foo();
68 }
69 namespace barbar {
70 int baz() {
71 bar::fo^o();
72 }
73 }
74 )cpp",
75 {CreateExpectedSymbolDetails("foo", "bar::", "c:@N@bar@F@foo#")}},
76 {
77 R"cpp( // Function in global namespace reference
78 void foo();
79 namespace Nbar {
80 namespace Nbaz {
81 int baz() {
82 ::fo^o();
83 }
84 }
85 }
86 )cpp",
87 {CreateExpectedSymbolDetails("foo", "", "c:@F@foo#")}},
88 {
89 R"cpp( // Function in anonymous namespace reference
90 namespace {
91 void foo();
92 }
93 namespace barbar {
94 int baz() {
95 fo^o();
96 }
97 }
98 )cpp",
99 {CreateExpectedSymbolDetails("foo", "(anonymous)",
100 "c:TestTU.cpp@aN@F@foo#")}},
101 {
102 R"cpp( // Function reference - ADL
103 namespace bar {
104 struct BarType {};
105 void foo(const BarType&);
106 }
107 namespace barbar {
108 int baz() {
109 bar::BarType b;
110 fo^o(b);
111 }
112 }
113 )cpp",
114 {CreateExpectedSymbolDetails(
115 "foo", "bar::", "c:@N@bar@F@foo#&1$@N@bar@S@BarType#")}},
116 {
117 R"cpp( // Global value reference
118 int value;
119 void foo(int) { }
120 void bar() {
121 foo(val^ue);
122 }
123 )cpp",
124 {CreateExpectedSymbolDetails("value", "", "c:@value")}},
125 {
126 R"cpp( // Local value reference
127 void foo() { int aaa; int bbb = aa^a; }
128 )cpp",
129 {CreateExpectedSymbolDetails("aaa", "foo",
130 "c:TestTU.cpp@49@F@foo#@aaa")}},
131 {
132 R"cpp( // Function param
133 void bar(int aaa) {
134 int bbb = a^aa;
135 }
136 )cpp",
137 {CreateExpectedSymbolDetails("aaa", "bar",
138 "c:TestTU.cpp@38@F@bar#I#@aaa")}},
139 {
140 R"cpp( // Lambda capture
141 void foo() {
142 int ii;
143 auto lam = [ii]() {
144 return i^i;
145 };
146 }
147 )cpp",
148 {CreateExpectedSymbolDetails("ii", "foo",
149 "c:TestTU.cpp@54@F@foo#@ii")}},
150 {
151 R"cpp( // Macro reference
152 #define MACRO 5\nint i = MAC^RO;
153 )cpp",
154 {CreateExpectedSymbolDetails("MACRO", "",
155 "c:TestTU.cpp@38@macro@MACRO")}},
156 {
157 R"cpp( // Macro reference
158 #define MACRO 5\nint i = MACRO^;
159 )cpp",
160 {CreateExpectedSymbolDetails("MACRO", "",
161 "c:TestTU.cpp@38@macro@MACRO")}},
162 {
163 R"cpp( // Multiple symbols returned - using overloaded function name
164 void foo() {}
165 void foo(bool) {}
166 void foo(int) {}
167 namespace bar {
168 using ::fo^o;
169 }
170 )cpp",
171 {CreateExpectedSymbolDetails("foo", "", "c:@F@foo#"),
172 CreateExpectedSymbolDetails("foo", "", "c:@F@foo#b#"),
173 CreateExpectedSymbolDetails("foo", "", "c:@F@foo#I#"),
174 CreateExpectedSymbolDetails("foo", "bar::", "c:@N@bar@UD@foo")}},
175 {
176 R"cpp( // Multiple symbols returned - implicit conversion
177 struct foo {};
178 struct bar {
179 bar(const foo&) {}
180 };
181 void func_baz1(bar) {}
182 void func_baz2() {
183 foo ff;
184 func_baz1(f^f);
185 }
186 )cpp",
187 {CreateExpectedSymbolDetails(
188 "ff", "func_baz2", "c:TestTU.cpp@218@F@func_baz2#@ff")}},
189 {
190 R"cpp( // Type reference - declaration
191 struct foo;
192 void bar(fo^o*);
193 )cpp",
194 {CreateExpectedSymbolDetails("foo", "", "c:@S@foo")}},
195 {
196 R"cpp( // Type reference - definition
197 struct foo {};
198 void bar(fo^o*);
199 )cpp",
200 {CreateExpectedSymbolDetails("foo", "", "c:@S@foo")}},
201 {
202 R"cpp( // Type Reference - template argument
203 struct foo {};
204 template<class T> struct bar {};
205 void baz() {
206 bar<fo^o> b;
207 }
208 )cpp",
209 {CreateExpectedSymbolDetails("foo", "", "c:@S@foo")}},
210 {
211 R"cpp( // Template parameter reference - type param
212 template<class TT> struct bar {
213 T^T t;
214 };
215 )cpp",
216 {CreateExpectedSymbolDetails("TT", "bar::", "c:TestTU.cpp@65")}},
217 {
218 R"cpp( // Template parameter reference - type param
219 template<int NN> struct bar {
220 int a = N^N;
221 };
222 )cpp",
223 {CreateExpectedSymbolDetails("NN", "bar::", "c:TestTU.cpp@65")}},
224 {
225 R"cpp( // Class member reference - objec
226 struct foo {
227 int aa;
228 };
229 void bar() {
230 foo f;
231 f.a^a;
232 }
233 )cpp",
234 {CreateExpectedSymbolDetails("aa", "foo::", "c:@S@foo@FI@aa")}},
235 {
236 R"cpp( // Class member reference - pointer
237 struct foo {
238 int aa;
239 };
240 void bar() {
241 &foo::a^a;
242 }
243 )cpp",
244 {CreateExpectedSymbolDetails("aa", "foo::", "c:@S@foo@FI@aa")}},
245 {
246 R"cpp( // Class method reference - objec
247 struct foo {
248 void aa() {}
249 };
250 void bar() {
251 foo f;
252 f.a^a();
253 }
254 )cpp",
255 {CreateExpectedSymbolDetails("aa", "foo::", "c:@S@foo@F@aa#")}},
256 {
257 R"cpp( // Class method reference - pointer
258 struct foo {
259 void aa() {}
260 };
261 void bar() {
262 &foo::a^a;
263 }
264 )cpp",
265 {CreateExpectedSymbolDetails("aa", "foo::", "c:@S@foo@F@aa#")}},
266 {
267 R"cpp( // Typedef
268 typedef int foo;
269 void bar() {
270 fo^o a;
271 }
272 )cpp",
273 {CreateExpectedSymbolDetails("foo", "", "c:TestTU.cpp@T@foo")}},
274 {
275 R"cpp( // Type alias
276 using foo = int;
277 void bar() {
278 fo^o a;
279 }
280 )cpp",
281 {CreateExpectedSymbolDetails("foo", "", "c:@foo")}},
282 {
283 R"cpp( // Namespace reference
284 namespace foo {}
285 using namespace fo^o;
286 )cpp",
287 {CreateExpectedSymbolDetails("foo", "", "c:@N@foo")}},
288 {
289 R"cpp( // Enum value reference
290 enum foo { bar, baz };
291 void f() {
292 foo fff = ba^r;
293 }
294 )cpp",
295 {CreateExpectedSymbolDetails("bar", "foo", "c:@E@foo@bar")}},
296 {
297 R"cpp( // Enum class value reference
298 enum class foo { bar, baz };
299 void f() {
300 foo fff = foo::ba^r;
301 }
302 )cpp",
303 {CreateExpectedSymbolDetails("bar", "foo::", "c:@E@foo@bar")}},
304 {
305 R"cpp( // Parameters in declarations
306 void foo(int ba^r);
307 )cpp",
308 {CreateExpectedSymbolDetails("bar", "foo",
309 "c:TestTU.cpp@50@F@foo#I#@bar")}},
310 {
311 R"cpp( // Type inference with auto keyword
312 struct foo {};
313 foo getfoo() { return foo{}; }
314 void f() {
315 au^to a = getfoo();
316 }
317 )cpp",
318 {/* not implemented */}},
319 {
320 R"cpp( // decltype
321 struct foo {};
322 void f() {
323 foo f;
324 declt^ype(f);
325 }
326 )cpp",
327 {/* not implemented */}},
328 };
329
330 for (const auto &T : TestInputExpectedOutput) {
331 Annotations TestInput(T.first);
332 auto AST = TestTU::withCode(TestInput.code()).build();
333
334 EXPECT_THAT(getSymbolInfo(AST, TestInput.point()),
335 UnorderedElementsAreArray(T.second))
336 << T.first;
337 }
338 }
339
340 } // namespace
341 } // namespace clangd
342 } // namespace clang
343