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