18 #include "clang/AST/DeclCXX.h"
19 #include "clang/AST/DeclTemplate.h"
20 #include "clang/Index/IndexingAction.h"
21 #include "llvm/Support/Path.h"
22 #include "llvm/Support/ScopedPrinter.h"
23 #include "gmock/gmock.h"
24 #include "gtest/gtest.h"
30 using ::testing::AllOf;
31 using ::testing::ElementsAre;
33 using ::testing::Field;
34 using ::testing::IsEmpty;
35 using ::testing::Matcher;
36 using ::testing::Pointee;
37 using ::testing::UnorderedElementsAre;
40 MATCHER_P(WithName, N,
"") {
return arg.name == N; }
42 MATCHER_P(SelectionRangeIs, R,
"") {
return arg.selectionRange == R; }
43 template <
class... ParentMatchers>
44 ::testing::Matcher<TypeHierarchyItem>
Parents(ParentMatchers... ParentsM) {
46 HasValue(UnorderedElementsAre(ParentsM...)));
48 template <
class... ChildMatchers>
49 ::testing::Matcher<TypeHierarchyItem>
Children(ChildMatchers... ChildrenM) {
51 HasValue(UnorderedElementsAre(ChildrenM...)));
54 MATCHER(ParentsNotResolved,
"") {
return !arg.parents; }
55 MATCHER(ChildrenNotResolved,
"") {
return !arg.children; }
57 TEST(FindRecordTypeAt, TypeOrVariable) {
58 Annotations Source(R
"cpp(
63 using A^lias = Child2;
72 auto AST = TU.
build();
74 for (Position Pt : Source.points()) {
76 EXPECT_EQ(&
findDecl(AST,
"Child2"), static_cast<const NamedDecl *>(RD));
80 TEST(FindRecordTypeAt, Method) {
81 Annotations Source(R
"cpp(
94 auto AST = TU.
build();
96 for (Position Pt : Source.points()) {
98 EXPECT_EQ(&
findDecl(AST,
"Child2"), static_cast<const NamedDecl *>(RD));
102 TEST(FindRecordTypeAt, Field) {
103 Annotations Source(R
"cpp(
115 auto AST = TU.
build();
117 for (Position Pt : Source.points()) {
122 EXPECT_EQ(
nullptr, RD);
126 TEST(TypeParents, SimpleInheritance) {
127 Annotations Source(R
"cpp(
132 struct Child1 : Parent {
136 struct Child2 : Child1 {
142 auto AST = TU.
build();
144 const CXXRecordDecl *
Parent =
145 dyn_cast<CXXRecordDecl>(&
findDecl(AST,
"Parent"));
146 const CXXRecordDecl *Child1 =
147 dyn_cast<CXXRecordDecl>(&
findDecl(AST,
"Child1"));
148 const CXXRecordDecl *Child2 =
149 dyn_cast<CXXRecordDecl>(&
findDecl(AST,
"Child2"));
153 EXPECT_THAT(
typeParents(Child2), ElementsAre(Child1));
156 TEST(TypeParents, MultipleInheritance) {
157 Annotations Source(R
"cpp(
166 struct Parent3 : Parent2 {
170 struct Child : Parent1, Parent3 {
176 auto AST = TU.
build();
178 const CXXRecordDecl *Parent1 =
179 dyn_cast<CXXRecordDecl>(&
findDecl(AST,
"Parent1"));
180 const CXXRecordDecl *Parent2 =
181 dyn_cast<CXXRecordDecl>(&
findDecl(AST,
"Parent2"));
182 const CXXRecordDecl *Parent3 =
183 dyn_cast<CXXRecordDecl>(&
findDecl(AST,
"Parent3"));
184 const CXXRecordDecl *Child = dyn_cast<CXXRecordDecl>(&
findDecl(AST,
"Child"));
188 EXPECT_THAT(
typeParents(Parent3), ElementsAre(Parent2));
189 EXPECT_THAT(
typeParents(Child), ElementsAre(Parent1, Parent3));
192 TEST(TypeParents, ClassTemplate) {
193 Annotations Source(R
"cpp(
196 template <typename T>
197 struct Child : Parent {};
201 auto AST = TU.
build();
203 const CXXRecordDecl *
Parent =
204 dyn_cast<CXXRecordDecl>(&
findDecl(AST,
"Parent"));
205 const CXXRecordDecl *Child =
206 dyn_cast<ClassTemplateDecl>(&
findDecl(AST,
"Child"))->getTemplatedDecl();
211 MATCHER_P(ImplicitSpecOf, ClassTemplate,
"") {
212 const ClassTemplateSpecializationDecl *CTS =
213 dyn_cast<ClassTemplateSpecializationDecl>(arg);
215 CTS->getSpecializedTemplate()->getTemplatedDecl() == ClassTemplate &&
216 CTS->getSpecializationKind() == TSK_ImplicitInstantiation;
221 const NamedDecl &findDeclWithTemplateArgs(ParsedAST &AST,
222 llvm::StringRef Query) {
223 return findDecl(AST, [&Query](
const NamedDecl &ND) {
225 llvm::raw_string_ostream
OS(QName);
226 PrintingPolicy Policy(ND.getASTContext().getLangOpts());
229 ND.getNameForDiagnostic(
OS, Policy,
true);
231 return QName == Query;
235 TEST(TypeParents, TemplateSpec1) {
236 Annotations Source(R
"cpp(
237 template <typename T>
241 struct Parent<int> {};
243 struct Child1 : Parent<float> {};
245 struct Child2 : Parent<int> {};
249 auto AST = TU.
build();
251 const CXXRecordDecl *
Parent =
252 dyn_cast<ClassTemplateDecl>(&
findDecl(AST,
"Parent"))->getTemplatedDecl();
253 const CXXRecordDecl *ParentSpec =
254 dyn_cast<CXXRecordDecl>(&findDeclWithTemplateArgs(AST,
"Parent<int>"));
255 const CXXRecordDecl *Child1 =
256 dyn_cast<CXXRecordDecl>(&
findDecl(AST,
"Child1"));
257 const CXXRecordDecl *Child2 =
258 dyn_cast<CXXRecordDecl>(&
findDecl(AST,
"Child2"));
261 EXPECT_THAT(
typeParents(Child2), ElementsAre(ParentSpec));
264 TEST(TypeParents, TemplateSpec2) {
265 Annotations Source(R
"cpp(
268 template <typename T>
272 struct Child<int> : Parent {};
276 auto AST = TU.
build();
278 const CXXRecordDecl *
Parent =
279 dyn_cast<CXXRecordDecl>(&
findDecl(AST,
"Parent"));
280 const CXXRecordDecl *Child =
281 dyn_cast<ClassTemplateDecl>(&
findDecl(AST,
"Child"))->getTemplatedDecl();
282 const CXXRecordDecl *ChildSpec =
283 dyn_cast<CXXRecordDecl>(&findDeclWithTemplateArgs(AST,
"Child<int>"));
289 TEST(TypeParents, DependentBase) {
290 Annotations Source(R
"cpp(
291 template <typename T>
294 template <typename T>
295 struct Child1 : Parent<T> {};
297 template <typename T>
298 struct Child2 : Parent<T>::Type {};
300 template <typename T>
301 struct Child3 : T {};
305 auto AST = TU.
build();
307 const CXXRecordDecl *
Parent =
308 dyn_cast<ClassTemplateDecl>(&
findDecl(AST,
"Parent"))->getTemplatedDecl();
309 const CXXRecordDecl *Child1 =
310 dyn_cast<ClassTemplateDecl>(&
findDecl(AST,
"Child1"))->getTemplatedDecl();
311 const CXXRecordDecl *Child2 =
312 dyn_cast<ClassTemplateDecl>(&
findDecl(AST,
"Child2"))->getTemplatedDecl();
313 const CXXRecordDecl *Child3 =
314 dyn_cast<ClassTemplateDecl>(&
findDecl(AST,
"Child3"))->getTemplatedDecl();
327 TEST(TypeHierarchy, Parents) {
328 Annotations Source(R
"cpp(
329 struct $Parent1Def[[Parent1]] {
333 struct $Parent2Def[[Parent2]] {
337 struct $Parent3Def[[Parent3]] : Parent2 {
341 struct Ch^ild : Parent1, Parent3 {
353 auto AST = TU.
build();
355 for (Position Pt : Source.points()) {
360 ASSERT_TRUE(
bool(Result));
366 SelectionRangeIs(Source.range(
"Parent1Def")),
369 SelectionRangeIs(Source.range(
"Parent3Def")),
372 SelectionRangeIs(Source.range(
"Parent2Def")),
377 TEST(TypeHierarchy, RecursiveHierarchyUnbounded) {
378 Annotations Source(R
"cpp(
380 struct $SDef[[S]] : S<N + 1> {};
386 TU.ExtraArgs.push_back("-ftemplate-depth=10");
387 auto AST = TU.
build();
399 ASSERT_TRUE(
bool(Result));
405 SelectionRangeIs(Source.range(
"SDef")),
407 SelectionRangeIs(Source.range(
"SDef")),
411 TEST(TypeHierarchy, RecursiveHierarchyBounded) {
412 Annotations Source(R
"cpp(
414 struct $SDef[[S]] : S<N - 1> {};
419 S$SRefConcrete^<2> s;
423 S$SRefDependent^<N> s;
427 auto AST = TU.
build();
433 ASSERT_TRUE(
bool(Result));
439 SelectionRangeIs(Source.range(
"SDef")),
444 ASSERT_TRUE(
bool(Result));
449 SelectionRangeIs(Source.range(
"SDef")),
Parents()))));
452 TEST(TypeHierarchy, DeriveFromImplicitSpec) {
453 Annotations Source(R
"cpp(
454 template <typename T>
457 struct Child : Parent<int> {};
463 auto AST = TU.
build();
464 auto Index = TU.index();
469 ASSERT_TRUE(
bool(Result));
476 TEST(TypeHierarchy, DeriveFromPartialSpec) {
477 Annotations Source(R
"cpp(
478 template <typename T> struct Parent {};
479 template <typename T> struct Parent<T*> {};
481 struct Child : Parent<int*> {};
487 auto AST = TU.
build();
488 auto Index = TU.index();
493 ASSERT_TRUE(
bool(Result));
494 EXPECT_THAT(*Result, AllOf(WithName(
"Parent<int>"),
498 TEST(TypeHierarchy, DeriveFromTemplate) {
499 Annotations Source(R
"cpp(
500 template <typename T>
503 template <typename T>
504 struct Child : Parent<T> {};
510 auto AST = TU.
build();
511 auto Index = TU.index();
519 ASSERT_TRUE(
bool(Result));
527 llvm::StringRef TemplateArgs =
"") {
529 FuzzyFindRequest Request;
530 Request.Query = std::string(
Name);
531 Request.AnyScope =
true;
532 bool GotResult =
false;
534 if (TemplateArgs == S.TemplateSpecializationArgs) {
535 EXPECT_FALSE(GotResult);
540 EXPECT_TRUE(GotResult);
544 std::vector<SymbolID> collectSubtypes(
SymbolID Subject, SymbolIndex *
Index) {
545 std::vector<SymbolID> Result;
546 RelationsRequest Req;
547 Req.Subjects.insert(Subject);
550 [&Result](
const SymbolID &Subject,
const Symbol &Object) {
551 Result.push_back(
Object.ID);
556 TEST(Subtypes, SimpleInheritance) {
557 Annotations Source(R
"cpp(
559 struct Child1a : Parent {};
560 struct Child1b : Parent {};
561 struct Child2 : Child1a {};
565 auto Index = TU.index();
568 SymbolID Child1a = findSymbolIDByName(
Index.get(),
"Child1a");
569 SymbolID Child1b = findSymbolIDByName(
Index.get(),
"Child1b");
573 UnorderedElementsAre(Child1a, Child1b));
574 EXPECT_THAT(collectSubtypes(Child1a,
Index.get()), ElementsAre(Child2));
577 TEST(Subtypes, MultipleInheritance) {
578 Annotations Source(R
"cpp(
581 struct Parent3 : Parent2 {};
582 struct Child : Parent1, Parent3 {};
586 auto Index = TU.index();
588 SymbolID Parent1 = findSymbolIDByName(
Index.get(),
"Parent1");
589 SymbolID Parent2 = findSymbolIDByName(
Index.get(),
"Parent2");
590 SymbolID Parent3 = findSymbolIDByName(
Index.get(),
"Parent3");
593 EXPECT_THAT(collectSubtypes(Parent1,
Index.get()), ElementsAre(Child));
594 EXPECT_THAT(collectSubtypes(Parent2,
Index.get()), ElementsAre(Parent3));
595 EXPECT_THAT(collectSubtypes(Parent3,
Index.get()), ElementsAre(Child));
598 TEST(Subtypes, ClassTemplate) {
599 Annotations Source(R
"cpp(
602 template <typename T>
603 struct Child : Parent {};
607 auto Index = TU.index();
612 EXPECT_THAT(collectSubtypes(
Parent,
Index.get()), ElementsAre(Child));
615 TEST(Subtypes, TemplateSpec1) {
616 Annotations Source(R
"cpp(
617 template <typename T>
621 struct Parent<int> {};
623 struct Child1 : Parent<float> {};
625 struct Child2 : Parent<int> {};
629 auto Index = TU.index();
632 SymbolID ParentSpec = findSymbolIDByName(
Index.get(),
"Parent",
"<int>");
636 EXPECT_THAT(collectSubtypes(
Parent,
Index.get()), ElementsAre(Child1));
637 EXPECT_THAT(collectSubtypes(ParentSpec,
Index.get()), ElementsAre(Child2));
640 TEST(Subtypes, TemplateSpec2) {
641 Annotations Source(R
"cpp(
644 template <typename T>
648 struct Child<int> : Parent {};
652 auto Index = TU.index();
655 SymbolID ChildSpec = findSymbolIDByName(
Index.get(),
"Child",
"<int>");
657 EXPECT_THAT(collectSubtypes(
Parent,
Index.get()), ElementsAre(ChildSpec));
660 TEST(Subtypes, DependentBase) {
661 Annotations Source(R
"cpp(
662 template <typename T>
665 template <typename T>
666 struct Child : Parent<T> {};
670 auto Index = TU.index();
675 EXPECT_THAT(collectSubtypes(
Parent,
Index.get()), ElementsAre(Child));
678 TEST(Subtypes, LazyResolution) {
679 Annotations Source(R
"cpp(
681 struct Child1 : Parent {};
682 struct Child2a : Child1 {};
683 struct Child2b : Child1 {};
687 auto AST = TU.
build();
688 auto Index = TU.index();
691 AST, Source.point(), 1,
693 ASSERT_TRUE(
bool(Result));
697 ParentsNotResolved(),
699 ParentsNotResolved(), ChildrenNotResolved()))));
705 (*Result->children)[0],
707 ParentsNotResolved(),
709 ParentsNotResolved(), ChildrenNotResolved()),
711 ParentsNotResolved(), ChildrenNotResolved()))));