14 #include "llvm/Support/Path.h"
15 #include "gmock/gmock.h"
16 #include "gtest/gtest.h"
28 Stream <<
"{ from: " << Call.
from <<
", ranges: [";
33 return Stream <<
"] }";
38 using ::testing::AllOf;
39 using ::testing::ElementsAre;
41 using ::testing::IsEmpty;
42 using ::testing::Matcher;
43 using ::testing::UnorderedElementsAre;
46 MATCHER_P(withName, N,
"") {
return arg.name == N; }
47 MATCHER_P(withSelectionRange, R,
"") {
return arg.selectionRange == R; }
49 template <
class ItemMatcher>
50 ::testing::Matcher<CallHierarchyIncomingCall> from(ItemMatcher
M) {
53 template <
class... RangeMatchers>
54 ::testing::Matcher<CallHierarchyIncomingCall> fromRanges(RangeMatchers...
M) {
56 UnorderedElementsAre(
M...));
59 TEST(CallHierarchy, IncomingOneFileCpp) {
60 Annotations Source(R
"cpp(
63 $Callee[[callee]](42);
66 $Caller1A[[caller1]]();
67 $Caller1B[[caller1]]();
70 $Caller1C[[caller1]]();
71 $Caller2[[caller2]]();
75 auto AST = TU.
build();
76 auto Index = TU.index();
78 std::vector<CallHierarchyItem> Items =
80 ASSERT_THAT(Items, ElementsAre(withName(
"callee")));
82 ASSERT_THAT(IncomingLevel1,
83 ElementsAre(AllOf(from(withName(
"caller1")),
84 fromRanges(Source.range(
"Callee")))));
86 ASSERT_THAT(IncomingLevel2,
87 ElementsAre(AllOf(from(withName(
"caller2")),
88 fromRanges(Source.range(
"Caller1A"),
89 Source.range(
"Caller1B"))),
90 AllOf(from(withName(
"caller3")),
91 fromRanges(Source.range(
"Caller1C")))));
94 ASSERT_THAT(IncomingLevel3,
95 ElementsAre(AllOf(from(withName(
"caller3")),
96 fromRanges(Source.range(
"Caller2")))));
99 EXPECT_THAT(IncomingLevel4, IsEmpty());
102 TEST(CallHierarchy, IncomingOneFileObjC) {
103 Annotations Source(R
"objc(
104 @implementation MyClass {}
107 [MyClass $Callee[[callee]]];
110 [MyClass $Caller1A[[caller1]]];
111 [MyClass $Caller1B[[caller1]]];
114 [MyClass $Caller1C[[caller1]]];
115 [MyClass $Caller2[[caller2]]];
120 TU.Filename = "TestTU.m";
121 auto AST = TU.
build();
122 auto Index = TU.index();
123 std::vector<CallHierarchyItem> Items =
125 ASSERT_THAT(Items, ElementsAre(withName(
"callee")));
127 ASSERT_THAT(IncomingLevel1,
128 ElementsAre(AllOf(from(withName(
"caller1")),
129 fromRanges(Source.range(
"Callee")))));
131 ASSERT_THAT(IncomingLevel2,
132 ElementsAre(AllOf(from(withName(
"caller2")),
133 fromRanges(Source.range(
"Caller1A"),
134 Source.range(
"Caller1B"))),
135 AllOf(from(withName(
"caller3")),
136 fromRanges(Source.range(
"Caller1C")))));
139 ASSERT_THAT(IncomingLevel3,
140 ElementsAre(AllOf(from(withName(
"caller3")),
141 fromRanges(Source.range(
"Caller2")))));
144 EXPECT_THAT(IncomingLevel4, IsEmpty());
147 TEST(CallHierarchy, MainFileOnlyRef) {
151 Annotations Source(R
"cpp(
155 $Callee[[callee]](42);
159 $Caller1[[caller1]]();
163 auto AST = TU.
build();
164 auto Index = TU.index();
166 std::vector<CallHierarchyItem> Items =
168 ASSERT_THAT(Items, ElementsAre(withName(
"callee")));
170 ASSERT_THAT(IncomingLevel1,
171 ElementsAre(AllOf(from(withName(
"caller1")),
172 fromRanges(Source.range(
"Callee")))));
175 EXPECT_THAT(IncomingLevel2,
176 ElementsAre(AllOf(from(withName(
"caller2")),
177 fromRanges(Source.range(
"Caller1")))));
180 TEST(CallHierarchy, IncomingQualified) {
181 Annotations Source(R
"cpp(
186 void Waldo::find() {}
187 void caller1(Waldo &W) {
188 W.$Caller1[[f^ind]]();
190 void caller2(Waldo &W) {
191 W.$Caller2[[find]]();
196 auto AST = TU.
build();
197 auto Index = TU.index();
199 std::vector<CallHierarchyItem> Items =
201 ASSERT_THAT(Items, ElementsAre(withName(
"Waldo::find")));
203 EXPECT_THAT(Incoming,
204 ElementsAre(AllOf(from(withName(
"caller1")),
205 fromRanges(Source.range(
"Caller1"))),
206 AllOf(from(withName(
"caller2")),
207 fromRanges(Source.range(
"Caller2")))));
210 TEST(CallHierarchy, IncomingMultiFileCpp) {
216 Annotations CalleeH(R
"cpp(
219 Annotations CalleeC(R"cpp(
223 Annotations Caller1H(R"cpp(
226 Annotations Caller1C(R"cpp(
228 #include "caller1.hh"
233 Annotations Caller2H(R"cpp(
236 Annotations Caller2C(R"cpp(
237 #include "caller1.hh"
238 #include "caller2.hh"
244 Annotations Caller3C(R"cpp(
245 #include "caller1.hh"
246 #include "caller2.hh"
248 $Caller1[[caller1]]();
249 $Caller2[[caller2]]();
253 TestWorkspace Workspace;
254 Workspace.addSource("callee.hh", CalleeH.code());
255 Workspace.addSource(
"caller1.hh", Caller1H.code());
256 Workspace.addSource(
"caller2.hh", Caller2H.code());
257 Workspace.addMainFile(
"callee.cc", CalleeC.code());
258 Workspace.addMainFile(
"caller1.cc", Caller1C.code());
259 Workspace.addMainFile(
"caller2.cc", Caller2C.code());
260 Workspace.addMainFile(
"caller3.cc", Caller3C.code());
262 auto Index = Workspace.index();
264 auto CheckCallHierarchy = [&](ParsedAST &AST, Position
Pos,
PathRef TUPath) {
265 std::vector<CallHierarchyItem> Items =
267 ASSERT_THAT(Items, ElementsAre(withName(
"callee")));
269 ASSERT_THAT(IncomingLevel1,
270 ElementsAre(AllOf(from(withName(
"caller1")),
271 fromRanges(Caller1C.range()))));
276 ElementsAre(AllOf(from(withName(
"caller2")),
277 fromRanges(Caller2C.range(
"A"), Caller2C.range(
"B"))),
278 AllOf(from(withName(
"caller3")),
279 fromRanges(Caller3C.range(
"Caller1")))));
282 ASSERT_THAT(IncomingLevel3,
283 ElementsAre(AllOf(from(withName(
"caller3")),
284 fromRanges(Caller3C.range(
"Caller2")))));
287 EXPECT_THAT(IncomingLevel4, IsEmpty());
291 auto AST = Workspace.openFile(
"caller1.cc");
292 ASSERT_TRUE(
bool(AST));
293 CheckCallHierarchy(*AST, Caller1C.point(),
testPath(
"caller1.cc"));
296 AST = Workspace.openFile(
"callee.hh");
297 ASSERT_TRUE(
bool(AST));
298 CheckCallHierarchy(*AST, CalleeH.point(),
testPath(
"callee.hh"));
301 AST = Workspace.openFile(
"callee.cc");
302 ASSERT_TRUE(
bool(AST));
303 CheckCallHierarchy(*AST, CalleeC.point(),
testPath(
"callee.cc"));
306 TEST(CallHierarchy, IncomingMultiFileObjC) {
312 Annotations CalleeH(R
"objc(
313 @interface CalleeClass
317 Annotations CalleeC(R"objc(
319 @implementation CalleeClass {}
323 Annotations Caller1H(R"objc(
324 @interface Caller1Class
328 Annotations Caller1C(R"objc(
331 @implementation Caller1Class {}
333 [CalleeClass [[calle^e]]];
337 Annotations Caller2H(R"objc(
338 @interface Caller2Class
342 Annotations Caller2C(R"objc(
345 @implementation Caller2Class {}
347 [Caller1Class $A[[caller1]]];
348 [Caller1Class $B[[caller1]]];
352 Annotations Caller3C(R"objc(
355 @implementation Caller3Class {}
357 [Caller1Class $Caller1[[caller1]]];
358 [Caller2Class $Caller2[[caller2]]];
363 TestWorkspace Workspace;
364 Workspace.addSource("callee.mi", CalleeH.code());
365 Workspace.addSource(
"caller1.mi", Caller1H.code());
366 Workspace.addSource(
"caller2.mi", Caller2H.code());
367 Workspace.addMainFile(
"callee.m", CalleeC.code());
368 Workspace.addMainFile(
"caller1.m", Caller1C.code());
369 Workspace.addMainFile(
"caller2.m", Caller2C.code());
370 Workspace.addMainFile(
"caller3.m", Caller3C.code());
371 auto Index = Workspace.index();
373 auto CheckCallHierarchy = [&](ParsedAST &AST, Position
Pos,
PathRef TUPath) {
374 std::vector<CallHierarchyItem> Items =
376 ASSERT_THAT(Items, ElementsAre(withName(
"callee")));
378 ASSERT_THAT(IncomingLevel1,
379 ElementsAre(AllOf(from(withName(
"caller1")),
380 fromRanges(Caller1C.range()))));
385 ElementsAre(AllOf(from(withName(
"caller2")),
386 fromRanges(Caller2C.range(
"A"), Caller2C.range(
"B"))),
387 AllOf(from(withName(
"caller3")),
388 fromRanges(Caller3C.range(
"Caller1")))));
391 ASSERT_THAT(IncomingLevel3,
392 ElementsAre(AllOf(from(withName(
"caller3")),
393 fromRanges(Caller3C.range(
"Caller2")))));
396 EXPECT_THAT(IncomingLevel4, IsEmpty());
400 auto AST = Workspace.openFile(
"caller1.m");
401 ASSERT_TRUE(
bool(AST));
402 CheckCallHierarchy(*AST, Caller1C.point(),
testPath(
"caller1.m"));
405 AST = Workspace.openFile(
"callee.mi");
406 ASSERT_TRUE(
bool(AST));
407 CheckCallHierarchy(*AST, CalleeH.point(),
testPath(
"callee.mi"));
410 AST = Workspace.openFile(
"callee.m");
411 ASSERT_TRUE(
bool(AST));
412 CheckCallHierarchy(*AST, CalleeC.point(),
testPath(
"callee.m"));
415 TEST(CallHierarchy, CallInLocalVarDecl) {
422 Annotations Source(R
"cpp(
428 int localVar = $call2[[callee]]();
430 int caller3 = $call3[[callee]]();
433 auto AST = TU.
build();
434 auto Index = TU.index();
436 std::vector<CallHierarchyItem> Items =
438 ASSERT_THAT(Items, ElementsAre(withName(
"callee")));
444 AllOf(from(withName(
"caller1")), fromRanges(Source.range(
"call1"))),
445 AllOf(from(withName(
"caller2")), fromRanges(Source.range(
"call2"))),
446 AllOf(from(withName(
"caller3")), fromRanges(Source.range(
"call3")))));