@@ -409,17 +409,21 @@ TEST(TypeHierarchy, RecursiveHierarchyUnbounded) {
409
409
ASSERT_TRUE (!AST.getDiagnostics ().empty ());
410
410
411
411
// Make sure getTypeHierarchy() doesn't get into an infinite recursion.
412
- // FIXME(nridge): It would be preferable if the type hierarchy gave us type
413
- // names (e.g. "S<0>" for the child and "S<1>" for the parent) rather than
414
- // template names (e.g. "S") .
412
+ // The parent is reported as "S" because "S<0>" is an invalid instantiation.
413
+ // We then iterate once more and find "S" again before detecting the
414
+ // recursion .
415
415
llvm::Optional<TypeHierarchyItem> Result = getTypeHierarchy (
416
416
AST, Source.points ()[0 ], 0 , TypeHierarchyDirection::Parents);
417
417
ASSERT_TRUE (bool (Result));
418
418
EXPECT_THAT (
419
419
*Result,
420
- AllOf (WithName (" S" ), WithKind (SymbolKind::Struct),
421
- Parents (AllOf (WithName (" S" ), WithKind (SymbolKind::Struct),
422
- SelectionRangeIs (Source.range (" SDef" )), Parents ()))));
420
+ AllOf (WithName (" S<0>" ), WithKind (SymbolKind::Struct),
421
+ Parents (
422
+ AllOf (WithName (" S" ), WithKind (SymbolKind::Struct),
423
+ SelectionRangeIs (Source.range (" SDef" )),
424
+ Parents (AllOf (WithName (" S" ), WithKind (SymbolKind::Struct),
425
+ SelectionRangeIs (Source.range (" SDef" )),
426
+ Parents ()))))));
423
427
}
424
428
425
429
TEST (TypeHierarchy, RecursiveHierarchyBounded) {
@@ -449,9 +453,12 @@ TEST(TypeHierarchy, RecursiveHierarchyBounded) {
449
453
ASSERT_TRUE (bool (Result));
450
454
EXPECT_THAT (
451
455
*Result,
452
- AllOf (WithName (" S" ), WithKind (SymbolKind::Struct),
453
- Parents (AllOf (WithName (" S" ), WithKind (SymbolKind::Struct),
454
- SelectionRangeIs (Source.range (" SDef" )), Parents ()))));
456
+ AllOf (WithName (" S<2>" ), WithKind (SymbolKind::Struct),
457
+ Parents (AllOf (
458
+ WithName (" S<1>" ), WithKind (SymbolKind::Struct),
459
+ SelectionRangeIs (Source.range (" SDef" )),
460
+ Parents (AllOf (WithName (" S<0>" ), WithKind (SymbolKind::Struct),
461
+ Parents ()))))));
455
462
Result = getTypeHierarchy (AST, Source.point (" SRefDependent" ), 0 ,
456
463
TypeHierarchyDirection::Parents);
457
464
ASSERT_TRUE (bool (Result));
@@ -462,6 +469,83 @@ TEST(TypeHierarchy, RecursiveHierarchyBounded) {
462
469
SelectionRangeIs (Source.range (" SDef" )), Parents ()))));
463
470
}
464
471
472
+ TEST (TypeHierarchy, DeriveFromImplicitSpec) {
473
+ Annotations Source (R"cpp(
474
+ template <typename T>
475
+ struct Parent {};
476
+
477
+ struct Child : Parent<int> {};
478
+
479
+ Parent<int> Fo^o;
480
+ )cpp" );
481
+
482
+ TestTU TU = TestTU::withCode (Source.code ());
483
+ auto AST = TU.build ();
484
+ auto Index = TU.index ();
485
+ ASSERT_TRUE (AST.getDiagnostics ().empty ());
486
+
487
+ llvm::Optional<TypeHierarchyItem> Result = getTypeHierarchy (
488
+ AST, Source.points ()[0 ], 2 , TypeHierarchyDirection::Children, Index.get (),
489
+ testPath (TU.Filename ));
490
+ ASSERT_TRUE (bool (Result));
491
+ EXPECT_THAT (*Result,
492
+ AllOf (WithName (" Parent<int>" ), WithKind (SymbolKind::Struct),
493
+ Children (AllOf (WithName (" Child" ),
494
+ WithKind (SymbolKind::Struct), Children ()))));
495
+ }
496
+
497
+ TEST (TypeHierarchy, DeriveFromPartialSpec) {
498
+ Annotations Source (R"cpp(
499
+ template <typename T> struct Parent {};
500
+ template <typename T> struct Parent<T*> {};
501
+
502
+ struct Child : Parent<int*> {};
503
+
504
+ Parent<int> Fo^o;
505
+ )cpp" );
506
+
507
+ TestTU TU = TestTU::withCode (Source.code ());
508
+ auto AST = TU.build ();
509
+ auto Index = TU.index ();
510
+ ASSERT_TRUE (AST.getDiagnostics ().empty ());
511
+
512
+ llvm::Optional<TypeHierarchyItem> Result = getTypeHierarchy (
513
+ AST, Source.points ()[0 ], 2 , TypeHierarchyDirection::Children, Index.get (),
514
+ testPath (TU.Filename ));
515
+ ASSERT_TRUE (bool (Result));
516
+ EXPECT_THAT (*Result, AllOf (WithName (" Parent<int>" ),
517
+ WithKind (SymbolKind::Struct), Children ()));
518
+ }
519
+
520
+ TEST (TypeHierarchy, DeriveFromTemplate) {
521
+ Annotations Source (R"cpp(
522
+ template <typename T>
523
+ struct Parent {};
524
+
525
+ template <typename T>
526
+ struct Child : Parent<T> {};
527
+
528
+ Parent<int> Fo^o;
529
+ )cpp" );
530
+
531
+ TestTU TU = TestTU::withCode (Source.code ());
532
+ auto AST = TU.build ();
533
+ auto Index = TU.index ();
534
+ ASSERT_TRUE (AST.getDiagnostics ().empty ());
535
+
536
+ // FIXME: We'd like this to return the implicit specialization Child<int>,
537
+ // but currently libIndex does not expose relationships between
538
+ // implicit specializations.
539
+ llvm::Optional<TypeHierarchyItem> Result = getTypeHierarchy (
540
+ AST, Source.points ()[0 ], 2 , TypeHierarchyDirection::Children, Index.get (),
541
+ testPath (TU.Filename ));
542
+ ASSERT_TRUE (bool (Result));
543
+ EXPECT_THAT (*Result,
544
+ AllOf (WithName (" Parent<int>" ), WithKind (SymbolKind::Struct),
545
+ Children (AllOf (WithName (" Child" ),
546
+ WithKind (SymbolKind::Struct), Children ()))));
547
+ }
548
+
465
549
SymbolID findSymbolIDByName (SymbolIndex *Index, llvm::StringRef Name,
466
550
llvm::StringRef TemplateArgs = " " ) {
467
551
SymbolID Result;
0 commit comments