14 #include "clang/AST/DeclCXX.h"
15 #include "clang/AST/DeclTemplate.h"
16 #include "llvm/Support/Path.h"
17 #include "gmock/gmock.h"
18 #include "gtest/gtest.h"
24 using ::testing::AllOf;
25 using ::testing::ElementsAre;
27 using ::testing::IsEmpty;
28 using ::testing::Matcher;
29 using ::testing::UnorderedElementsAre;
32 MATCHER_P(withName, N,
"") {
return arg.name == N; }
34 MATCHER_P(selectionRangeIs, R,
"") {
return arg.selectionRange == R; }
35 template <
class... ParentMatchers>
36 ::testing::Matcher<TypeHierarchyItem> parents(ParentMatchers... ParentsM) {
38 HasValue(UnorderedElementsAre(ParentsM...)));
40 template <
class... ChildMatchers>
41 ::testing::Matcher<TypeHierarchyItem> children(ChildMatchers... ChildrenM) {
43 HasValue(UnorderedElementsAre(ChildrenM...)));
46 MATCHER(parentsNotResolved,
"") {
return !arg.parents; }
47 MATCHER(childrenNotResolved,
"") {
return !arg.children; }
49 TEST(FindRecordTypeAt, TypeOrVariable) {
50 Annotations Source(R
"cpp(
55 using A^lias = Child2;
64 auto AST = TU.
build();
66 for (Position Pt : Source.points()) {
68 EXPECT_EQ(&
findDecl(AST,
"Child2"),
static_cast<const NamedDecl *
>(RD));
72 TEST(FindRecordTypeAt, Method) {
73 Annotations Source(R
"cpp(
86 auto AST = TU.
build();
88 for (Position Pt : Source.points()) {
90 EXPECT_EQ(&
findDecl(AST,
"Child2"),
static_cast<const NamedDecl *
>(RD));
94 TEST(FindRecordTypeAt, Field) {
95 Annotations Source(R
"cpp(
107 auto AST = TU.
build();
109 for (Position Pt : Source.points()) {
114 EXPECT_EQ(
nullptr, RD);
118 TEST(TypeParents, SimpleInheritance) {
119 Annotations Source(R
"cpp(
124 struct Child1 : Parent {
128 struct Child2 : Child1 {
134 auto AST = TU.
build();
136 const CXXRecordDecl *
Parent =
137 dyn_cast<CXXRecordDecl>(&
findDecl(AST,
"Parent"));
138 const CXXRecordDecl *Child1 =
139 dyn_cast<CXXRecordDecl>(&
findDecl(AST,
"Child1"));
140 const CXXRecordDecl *Child2 =
141 dyn_cast<CXXRecordDecl>(&
findDecl(AST,
"Child2"));
145 EXPECT_THAT(
typeParents(Child2), ElementsAre(Child1));
148 TEST(TypeParents, MultipleInheritance) {
149 Annotations Source(R
"cpp(
158 struct Parent3 : Parent2 {
162 struct Child : Parent1, Parent3 {
168 auto AST = TU.
build();
170 const CXXRecordDecl *Parent1 =
171 dyn_cast<CXXRecordDecl>(&
findDecl(AST,
"Parent1"));
172 const CXXRecordDecl *Parent2 =
173 dyn_cast<CXXRecordDecl>(&
findDecl(AST,
"Parent2"));
174 const CXXRecordDecl *Parent3 =
175 dyn_cast<CXXRecordDecl>(&
findDecl(AST,
"Parent3"));
176 const CXXRecordDecl *Child = dyn_cast<CXXRecordDecl>(&
findDecl(AST,
"Child"));
180 EXPECT_THAT(
typeParents(Parent3), ElementsAre(Parent2));
181 EXPECT_THAT(
typeParents(Child), ElementsAre(Parent1, Parent3));
184 TEST(TypeParents, ClassTemplate) {
185 Annotations Source(R
"cpp(
188 template <typename T>
189 struct Child : Parent {};
193 auto AST = TU.
build();
195 const CXXRecordDecl *
Parent =
196 dyn_cast<CXXRecordDecl>(&
findDecl(AST,
"Parent"));
197 const CXXRecordDecl *Child =
198 dyn_cast<ClassTemplateDecl>(&
findDecl(AST,
"Child"))->getTemplatedDecl();
203 MATCHER_P(implicitSpecOf, ClassTemplate,
"") {
204 const ClassTemplateSpecializationDecl *CTS =
205 dyn_cast<ClassTemplateSpecializationDecl>(arg);
207 CTS->getSpecializedTemplate()->getTemplatedDecl() == ClassTemplate &&
208 CTS->getSpecializationKind() == TSK_ImplicitInstantiation;
213 const NamedDecl &findDeclWithTemplateArgs(ParsedAST &AST,
214 llvm::StringRef Query) {
215 return findDecl(AST, [&Query](
const NamedDecl &ND) {
217 llvm::raw_string_ostream
OS(QName);
218 PrintingPolicy Policy(ND.getASTContext().getLangOpts());
221 ND.getNameForDiagnostic(
OS, Policy,
true);
223 return QName == Query;
227 TEST(TypeParents, TemplateSpec1) {
228 Annotations Source(R
"cpp(
229 template <typename T>
233 struct Parent<int> {};
235 struct Child1 : Parent<float> {};
237 struct Child2 : Parent<int> {};
241 auto AST = TU.
build();
243 const CXXRecordDecl *
Parent =
244 dyn_cast<ClassTemplateDecl>(&
findDecl(AST,
"Parent"))->getTemplatedDecl();
245 const CXXRecordDecl *ParentSpec =
246 dyn_cast<CXXRecordDecl>(&findDeclWithTemplateArgs(AST,
"Parent<int>"));
247 const CXXRecordDecl *Child1 =
248 dyn_cast<CXXRecordDecl>(&
findDecl(AST,
"Child1"));
249 const CXXRecordDecl *Child2 =
250 dyn_cast<CXXRecordDecl>(&
findDecl(AST,
"Child2"));
253 EXPECT_THAT(
typeParents(Child2), ElementsAre(ParentSpec));
256 TEST(TypeParents, TemplateSpec2) {
257 Annotations Source(R
"cpp(
260 template <typename T>
264 struct Child<int> : Parent {};
268 auto AST = TU.
build();
270 const CXXRecordDecl *
Parent =
271 dyn_cast<CXXRecordDecl>(&
findDecl(AST,
"Parent"));
272 const CXXRecordDecl *Child =
273 dyn_cast<ClassTemplateDecl>(&
findDecl(AST,
"Child"))->getTemplatedDecl();
274 const CXXRecordDecl *ChildSpec =
275 dyn_cast<CXXRecordDecl>(&findDeclWithTemplateArgs(AST,
"Child<int>"));
281 TEST(TypeParents, DependentBase) {
282 Annotations Source(R
"cpp(
283 template <typename T>
286 template <typename T>
287 struct Child1 : Parent<T> {};
289 template <typename T>
290 struct Child2 : Parent<T>::Type {};
292 template <typename T>
293 struct Child3 : T {};
297 auto AST = TU.
build();
299 const CXXRecordDecl *
Parent =
300 dyn_cast<ClassTemplateDecl>(&
findDecl(AST,
"Parent"))->getTemplatedDecl();
301 const CXXRecordDecl *Child1 =
302 dyn_cast<ClassTemplateDecl>(&
findDecl(AST,
"Child1"))->getTemplatedDecl();
303 const CXXRecordDecl *Child2 =
304 dyn_cast<ClassTemplateDecl>(&
findDecl(AST,
"Child2"))->getTemplatedDecl();
305 const CXXRecordDecl *Child3 =
306 dyn_cast<ClassTemplateDecl>(&
findDecl(AST,
"Child3"))->getTemplatedDecl();
316 TEST(TypeParents, IncompleteClass) {
317 Annotations Source(R
"cpp(
321 auto AST = TU.
build();
323 const CXXRecordDecl *Incomplete =
324 dyn_cast<CXXRecordDecl>(&
findDecl(AST,
"Incomplete"));
331 TEST(TypeHierarchy, Parents) {
332 Annotations Source(R
"cpp(
333 struct $Parent1Def[[Parent1]] {
337 struct $Parent2Def[[Parent2]] {
341 struct $Parent3Def[[Parent3]] : Parent2 {
345 struct Ch^ild : Parent1, Parent3 {
357 auto AST = TU.
build();
359 for (Position Pt : Source.points()) {
364 ASSERT_TRUE(
bool(Result));
370 selectionRangeIs(Source.range(
"Parent1Def")),
373 selectionRangeIs(Source.range(
"Parent3Def")),
376 selectionRangeIs(Source.range(
"Parent2Def")),
381 TEST(TypeHierarchy, RecursiveHierarchyUnbounded) {
382 Annotations Source(R
"cpp(
384 struct $SDef[[S]] : S<N + 1> {};
390 TU.ExtraArgs.push_back("-ftemplate-depth=10");
391 auto AST = TU.
build();
403 ASSERT_TRUE(
bool(Result));
409 selectionRangeIs(Source.range(
"SDef")),
411 selectionRangeIs(Source.range(
"SDef")),
415 TEST(TypeHierarchy, RecursiveHierarchyBounded) {
416 Annotations Source(R
"cpp(
418 struct $SDef[[S]] : S<N - 1> {};
423 S$SRefConcrete^<2> s;
427 S$SRefDependent^<N> s;
431 auto AST = TU.
build();
437 ASSERT_TRUE(
bool(Result));
443 selectionRangeIs(Source.range(
"SDef")),
448 ASSERT_TRUE(
bool(Result));
453 selectionRangeIs(Source.range(
"SDef")), parents()))));
456 TEST(TypeHierarchy, DeriveFromImplicitSpec) {
457 Annotations Source(R
"cpp(
458 template <typename T>
461 struct Child1 : Parent<int> {};
463 struct Child2 : Parent<char> {};
469 auto AST = TU.
build();
470 auto Index = TU.index();
475 ASSERT_TRUE(
bool(Result));
478 children(AllOf(withName(
"Child1"),
480 AllOf(withName(
"Child2"),
484 TEST(TypeHierarchy, DeriveFromPartialSpec) {
485 Annotations Source(R
"cpp(
486 template <typename T> struct Parent {};
487 template <typename T> struct Parent<T*> {};
489 struct Child : Parent<int*> {};
495 auto AST = TU.
build();
496 auto Index = TU.index();
501 ASSERT_TRUE(
bool(Result));
506 TEST(TypeHierarchy, DeriveFromTemplate) {
507 Annotations Source(R
"cpp(
508 template <typename T>
511 template <typename T>
512 struct Child : Parent<T> {};
518 auto AST = TU.
build();
519 auto Index = TU.index();
527 ASSERT_TRUE(
bool(Result));
530 children(AllOf(withName(
"Child"),
534 TEST(TypeHierarchy, Preamble) {
535 Annotations SourceAnnotations(R
"cpp(
536 struct Ch^ild : Parent {
540 Annotations HeaderInPreambleAnnotations(R"cpp(
546 TU.HeaderCode = HeaderInPreambleAnnotations.code().str();
547 auto AST = TU.
build();
555 AllOf(withName(
"Child"),
556 parents(AllOf(withName(
"Parent"),
557 selectionRangeIs(HeaderInPreambleAnnotations.range()),
562 llvm::StringRef TemplateArgs =
"") {
564 FuzzyFindRequest Request;
565 Request.Query = std::string(
Name);
566 Request.AnyScope =
true;
567 bool GotResult =
false;
569 if (TemplateArgs == S.TemplateSpecializationArgs) {
570 EXPECT_FALSE(GotResult);
575 EXPECT_TRUE(GotResult);
579 std::vector<SymbolID> collectSubtypes(
SymbolID Subject, SymbolIndex *
Index) {
580 std::vector<SymbolID> Result;
581 RelationsRequest Req;
582 Req.Subjects.insert(Subject);
585 [&Result](
const SymbolID &Subject,
const Symbol &Object) {
586 Result.push_back(
Object.ID);
591 TEST(Subtypes, SimpleInheritance) {
592 Annotations Source(R
"cpp(
594 struct Child1a : Parent {};
595 struct Child1b : Parent {};
596 struct Child2 : Child1a {};
600 auto Index = TU.index();
603 SymbolID Child1a = findSymbolIDByName(
Index.get(),
"Child1a");
604 SymbolID Child1b = findSymbolIDByName(
Index.get(),
"Child1b");
608 UnorderedElementsAre(Child1a, Child1b));
609 EXPECT_THAT(collectSubtypes(Child1a,
Index.get()), ElementsAre(Child2));
612 TEST(Subtypes, MultipleInheritance) {
613 Annotations Source(R
"cpp(
616 struct Parent3 : Parent2 {};
617 struct Child : Parent1, Parent3 {};
621 auto Index = TU.index();
623 SymbolID Parent1 = findSymbolIDByName(
Index.get(),
"Parent1");
624 SymbolID Parent2 = findSymbolIDByName(
Index.get(),
"Parent2");
625 SymbolID Parent3 = findSymbolIDByName(
Index.get(),
"Parent3");
628 EXPECT_THAT(collectSubtypes(Parent1,
Index.get()), ElementsAre(Child));
629 EXPECT_THAT(collectSubtypes(Parent2,
Index.get()), ElementsAre(Parent3));
630 EXPECT_THAT(collectSubtypes(Parent3,
Index.get()), ElementsAre(Child));
633 TEST(Subtypes, ClassTemplate) {
634 Annotations Source(R
"cpp(
637 template <typename T>
638 struct Child : Parent {};
642 auto Index = TU.index();
647 EXPECT_THAT(collectSubtypes(
Parent,
Index.get()), ElementsAre(Child));
650 TEST(Subtypes, TemplateSpec1) {
651 Annotations Source(R
"cpp(
652 template <typename T>
656 struct Parent<int> {};
658 struct Child1 : Parent<float> {};
660 struct Child2 : Parent<int> {};
664 auto Index = TU.index();
667 SymbolID ParentSpec = findSymbolIDByName(
Index.get(),
"Parent",
"<int>");
671 EXPECT_THAT(collectSubtypes(
Parent,
Index.get()), ElementsAre(Child1));
672 EXPECT_THAT(collectSubtypes(ParentSpec,
Index.get()), ElementsAre(Child2));
675 TEST(Subtypes, TemplateSpec2) {
676 Annotations Source(R
"cpp(
679 template <typename T>
683 struct Child<int> : Parent {};
687 auto Index = TU.index();
690 SymbolID ChildSpec = findSymbolIDByName(
Index.get(),
"Child",
"<int>");
692 EXPECT_THAT(collectSubtypes(
Parent,
Index.get()), ElementsAre(ChildSpec));
695 TEST(Subtypes, DependentBase) {
696 Annotations Source(R
"cpp(
697 template <typename T>
700 template <typename T>
701 struct Child : Parent<T> {};
705 auto Index = TU.index();
710 EXPECT_THAT(collectSubtypes(
Parent,
Index.get()), ElementsAre(Child));
713 TEST(Subtypes, LazyResolution) {
714 Annotations Source(R
"cpp(
716 struct Child1 : Parent {};
717 struct Child2a : Child1 {};
718 struct Child2b : Child1 {};
722 auto AST = TU.
build();
723 auto Index = TU.index();
726 AST, Source.point(), 1,
728 ASSERT_TRUE(
bool(Result));
732 parentsNotResolved(),
734 parentsNotResolved(), childrenNotResolved()))));
740 (*Result->children)[0],
742 parentsNotResolved(),
744 parentsNotResolved(), childrenNotResolved()),
746 parentsNotResolved(), childrenNotResolved()))));