Skip to content

Commit 582462e

Browse files
committed
[Index] Handle implicit reference relations for type sugar
I missed handling this case in my previous patch, make sure we can fallback to retrieving the nominal from type sugar such as `Array` for `[Int]`. rdar://161036418
1 parent a69dbb3 commit 582462e

File tree

3 files changed

+173
-57
lines changed

3 files changed

+173
-57
lines changed

lib/Index/Index.cpp

Lines changed: 67 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1037,21 +1037,23 @@ class IndexSwiftASTWalker : public SourceEntityWalker {
10371037

10381038
bool reportRelatedRef(ValueDecl *D, SourceLoc Loc, bool isImplicit, SymbolRoleSet Relations, Decl *Related);
10391039

1040-
/// Report a related type relation for a given TypeRepr.
1040+
/// Report a related type relation for a given TypeLoc. Don't call this
1041+
/// directly, use \c reportRelatedTypeRef instead.
10411042
///
10421043
/// NOTE: If the dependent type is a typealias, report the underlying types as
10431044
/// well.
10441045
///
1045-
/// \param TR The type being referenced.
1046+
/// \param TL The type being referenced.
10461047
/// \param Relations The relationship between the referenced type and the
10471048
/// passed Decl.
10481049
/// \param Related The Decl that is referencing the type.
10491050
/// \param Implicit Whether the reference is implicit, such as for a
10501051
/// typealias' underlying type.
10511052
/// \param ParentLoc The parent location of the reference that should be used
10521053
/// for implicit references.
1053-
bool reportRelatedTypeRepr(const TypeRepr *TR, SymbolRoleSet Relations,
1054-
Decl *Related, bool Implicit, SourceLoc ParentLoc);
1054+
bool reportRelatedTypeRefImpl(const TypeLoc &TL, SymbolRoleSet Relations,
1055+
Decl *Related, bool Implicit,
1056+
SourceLoc ParentLoc);
10551057

10561058
/// Report a related type relation for a Type at a given location.
10571059
///
@@ -1531,66 +1533,85 @@ bool IndexSwiftASTWalker::reportInheritedTypeRefs(InheritedTypes Inherited,
15311533
return true;
15321534
}
15331535

1534-
bool IndexSwiftASTWalker::reportRelatedTypeRepr(const TypeRepr *TR,
1535-
SymbolRoleSet Relations,
1536-
Decl *Related, bool Implicit,
1537-
SourceLoc ParentLoc) {
1538-
// Look through parens/specifiers/attributes.
1539-
while (true) {
1540-
if (TR->isParenType()) {
1541-
TR = TR->getWithoutParens();
1542-
continue;
1543-
}
1544-
if (auto *SPR = dyn_cast<SpecifierTypeRepr>(TR)) {
1545-
TR = SPR->getBase();
1546-
continue;
1547-
}
1548-
if (auto *ATR = dyn_cast<AttributedTypeRepr>(TR)) {
1549-
TR = ATR->getTypeRepr();
1550-
continue;
1536+
bool IndexSwiftASTWalker::reportRelatedTypeRefImpl(const TypeLoc &TL,
1537+
SymbolRoleSet Relations,
1538+
Decl *Related, bool Implicit,
1539+
SourceLoc ParentLoc) {
1540+
auto *TR = TL.getTypeRepr();
1541+
if (TR) {
1542+
// Look through parens/specifiers/attributes.
1543+
while (true) {
1544+
if (TR->isParenType()) {
1545+
TR = TR->getWithoutParens();
1546+
continue;
1547+
}
1548+
if (auto *SPR = dyn_cast<SpecifierTypeRepr>(TR)) {
1549+
TR = SPR->getBase();
1550+
continue;
1551+
}
1552+
if (auto *ATR = dyn_cast<AttributedTypeRepr>(TR)) {
1553+
TR = ATR->getTypeRepr();
1554+
continue;
1555+
}
1556+
break;
15511557
}
1552-
break;
1553-
}
1554-
// NOTE: We don't yet handle InverseTypeRepr since we don't have an inverse
1555-
// relation for inheritance.
1558+
// NOTE: We don't yet handle InverseTypeRepr since we don't have an inverse
1559+
// relation for inheritance.
15561560

1557-
if (auto *composite = dyn_cast<CompositionTypeRepr>(TR)) {
1558-
for (auto *Type : composite->getTypes()) {
1559-
if (!reportRelatedTypeRepr(Type, Relations, Related, Implicit,
1560-
ParentLoc)) {
1561-
return false;
1561+
if (auto *composite = dyn_cast<CompositionTypeRepr>(TR)) {
1562+
for (auto *Type : composite->getTypes()) {
1563+
// Note this doesn't handle type sugar cases where the decl is only
1564+
// available on the semantic type. This isn't currently something that
1565+
// happens for type compositions though.
1566+
if (!reportRelatedTypeRefImpl(Type, Relations, Related, Implicit,
1567+
ParentLoc)) {
1568+
return false;
1569+
}
15621570
}
1571+
return true;
15631572
}
15641573
}
1565-
auto *declRefTR = dyn_cast<DeclRefTypeRepr>(TR);
1566-
if (!declRefTR)
1567-
return true;
1574+
SourceLoc Loc = [&]() {
1575+
if (ParentLoc)
1576+
return ParentLoc;
1577+
if (TR)
1578+
return TR->getLoc();
1579+
return SourceLoc();
1580+
}();
1581+
1582+
auto *declRefTR = dyn_cast_or_null<DeclRefTypeRepr>(TR);
1583+
if (!declRefTR) {
1584+
if (!TL.getType())
1585+
return true;
1586+
1587+
// If we don't have a TypeRepr, we're e.g indexing a Swift module, so want
1588+
// to look at the Type instead. If we have a TypeRepr but have no explicit
1589+
// decl reference, fall back to indexing an implicit reference to handle
1590+
// type sugar e.g Array for `[Int]`.
1591+
return reportRelatedType(TL.getType(), Relations, Related,
1592+
Implicit || TR, Loc);
1593+
}
15681594

15691595
auto *VD = declRefTR->getBoundDecl();
15701596
if (!VD)
15711597
return true;
15721598

1573-
SourceLoc IdLoc = ParentLoc.isValid() ? ParentLoc : declRefTR->getLoc();
15741599
if (auto *TAD = dyn_cast<TypeAliasDecl>(VD)) {
15751600
IndexSymbol Info;
15761601
if (Implicit)
15771602
Info.roles |= (unsigned)SymbolRole::Implicit;
1578-
if (!reportRef(TAD, IdLoc, Info, std::nullopt))
1603+
if (!reportRef(TAD, Loc, Info, std::nullopt))
15791604
return false;
15801605

15811606
// Recurse into the underlying type and report any found references as
15821607
// implicit references at the location of the typealias reference.
1583-
if (auto *UTR = TAD->getUnderlyingTypeRepr()) {
1584-
return reportRelatedTypeRepr(UTR, Relations, Related,
1585-
/*Implicit*/ true, /*ParentLoc*/ IdLoc);
1586-
}
1587-
// If we don't have a TypeRepr available, this is a typealias in another
1588-
// module, consult the computed underlying type.
1589-
return reportRelatedType(TAD->getUnderlyingType(), Relations, Related,
1590-
/*Implicit*/ true, /*ParentLoc*/ IdLoc);
1608+
TypeLoc UnderlyingTL(TAD->getUnderlyingTypeRepr(),
1609+
TAD->getUnderlyingType());
1610+
return reportRelatedTypeRefImpl(UnderlyingTL, Relations, Related,
1611+
/*Implicit*/ true, /*ParentLoc*/ Loc);
15911612
}
15921613
if (auto *NTD = dyn_cast<NominalTypeDecl>(VD)) {
1593-
if (!reportRelatedRef(NTD, IdLoc, Implicit, Relations, Related))
1614+
if (!reportRelatedRef(NTD, Loc, Implicit, Relations, Related))
15941615
return false;
15951616
}
15961617
return true;
@@ -1618,19 +1639,8 @@ bool IndexSwiftASTWalker::reportRelatedType(Type Ty, SymbolRoleSet Relations,
16181639
bool IndexSwiftASTWalker::reportRelatedTypeRef(const TypeLoc &TL,
16191640
SymbolRoleSet Relations,
16201641
Decl *Related) {
1621-
// If we have a TypeRepr, prefer that since it lets us match up source
1622-
// locations with the code the user wrote.
1623-
if (auto *TR = TL.getTypeRepr()) {
1624-
return reportRelatedTypeRepr(TR, Relations, Related, /*Implicit*/ false,
1625-
/*ParentLoc*/ SourceLoc());
1626-
}
1627-
// Otherwise fall back to reporting the Type, this is necessary when indexing
1628-
// swiftmodules.
1629-
if (auto Ty = TL.getType()) {
1630-
return reportRelatedType(Ty, Relations, Related,
1631-
/*Implicit*/ false, SourceLoc());
1632-
}
1633-
return true;
1642+
return reportRelatedTypeRefImpl(TL, Relations, Related, /*Implicit*/ false,
1643+
/*ParentLoc*/ SourceLoc());
16341644
}
16351645

16361646
bool IndexSwiftASTWalker::reportPseudoAccessor(AbstractStorageDecl *D,

test/Index/index_imported.swift

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,48 @@ public struct NonCopyable: NonCopyableProto & ~Copyable {}
2929
// We don't currently have a relation for Copyable.
3030
// LIB-NOT: s:s8CopyableP
3131

32+
extension [Int] {
33+
public func foo() {}
34+
}
35+
// LIB: 0:0 | extension/ext-struct/Swift | Array | s:e:s:Sa3LibSiRszlE3fooyyF | Def | rel: 0
36+
// LIB-NEXT: 0:0 | struct/Swift | Array | s:Sa | Ref,RelExt | rel: 1
37+
// LIB-NEXT: RelExt | extension/ext-struct/Swift | Array | s:e:s:Sa3LibSiRszlE3fooyyF
38+
39+
extension Array where Element == Int {
40+
public func bar() {}
41+
}
42+
// LIB: 0:0 | extension/ext-struct/Swift | Array | s:e:s:Sa3LibSiRszlE3baryyF | Def | rel: 0
43+
// LIB-NEXT: 0:0 | struct/Swift | Array | s:Sa | Ref,RelExt | rel: 1
44+
// LIB-NEXT: RelExt | extension/ext-struct/Swift | Array | s:e:s:Sa3LibSiRszlE3baryyF
45+
46+
extension Int? {
47+
public func baz() {}
48+
}
49+
// LIB: 0:0 | extension/ext-enum/Swift | Optional | s:e:s:Sq3LibSiRszlE3bazyyF | Def | rel: 0
50+
// LIB-NEXT: 0:0 | enum/Swift | Optional | s:Sq | Ref,RelExt | rel: 1
51+
// LIB-NEXT: RelExt | extension/ext-enum/Swift | Optional | s:e:s:Sq3LibSiRszlE3bazyyF
52+
53+
public typealias IntArray = [Int]
54+
public typealias ArrayOf<T> = [T]
55+
56+
extension IntArray {
57+
public func qux() {}
58+
}
59+
// We don't currently report references to typealiases in imported modules, so
60+
// this is just an extension of Array.
61+
// LIB: 0:0 | extension/ext-struct/Swift | Array | s:e:s:Sa3LibSiRszlE3quxyyF | Def | rel: 0
62+
// LIB-NEXT: 0:0 | struct/Swift | Array | s:Sa | Ref,RelExt | rel: 1
63+
// LIB-NEXT: RelExt | extension/ext-struct/Swift | Array | s:e:s:Sa3LibSiRszlE3quxyyF
64+
65+
extension ArrayOf<Int> {
66+
public func flim() {}
67+
}
68+
// We don't currently report references to typealiases in imported modules, so
69+
// this is just an extension of Array.
70+
// LIB: 0:0 | extension/ext-struct/Swift | Array | s:e:s:Sa3LibSiRszlE4flimyyF | Def | rel: 0
71+
// LIB-NEXT: 0:0 | struct/Swift | Array | s:Sa | Ref,RelExt | rel: 1
72+
// LIB-NEXT: RelExt | extension/ext-struct/Swift | Array | s:e:s:Sa3LibSiRszlE4flimyyF
73+
3274
//--- main.swift
3375

3476
import Lib
@@ -41,3 +83,20 @@ struct K: P & X {}
4183
// CHECK-NEXT: RelBase | struct/Swift | K | s:14swift_ide_test1KV
4284
// CHECK-NEXT: [[@LINE-6]]:15 | protocol/Swift | R | s:3Lib1RP | Ref,Impl,RelBase | rel: 1
4385
// CHECK-NEXT: RelBase | struct/Swift | K | s:14swift_ide_test1KV
86+
87+
extension IntArray {
88+
// CHECK: [[@LINE-1]]:11 | extension/ext-struct/Swift | Array | s:e:s:Sa14swift_ide_testSiRszlE4flamyyF | Def | rel: 0
89+
// CHECK-NEXT: [[@LINE-2]]:11 | type-alias/Swift | IntArray | s:3Lib8IntArraya | Ref | rel: 0
90+
// CHECK-NEXT: [[@LINE-3]]:11 | struct/Swift | Array | s:Sa | Ref,Impl,RelExt | rel: 1
91+
// CHECK-NEXT: RelExt | extension/ext-struct/Swift | Array | s:e:s:Sa14swift_ide_testSiRszlE4flamyyF
92+
func flam() {}
93+
}
94+
95+
// FIXME: Column 22 here is wrong...
96+
extension ArrayOf<Int> {
97+
// CHECK: [[@LINE-1]]:22 | extension/ext-struct/Swift | Array | s:e:s:Sa14swift_ide_testSiRszlE4bishyyF | Def | rel: 0
98+
// CHECK-NEXT: [[@LINE-2]]:11 | type-alias/Swift | ArrayOf | s:3Lib7ArrayOfa | Ref | rel: 0
99+
// CHECK-NEXT: [[@LINE-3]]:11 | struct/Swift | Array | s:Sa | Ref,Impl,RelExt | rel: 1
100+
// CHECK-NEXT: RelExt | extension/ext-struct/Swift | Array | s:e:s:Sa14swift_ide_testSiRszlE4bishyyF
101+
func bish() {}
102+
}

test/Index/roles.swift

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -564,3 +564,50 @@ class Subclass: BaseClass {
564564
// CHECK-NEXT: RelChild,RelAcc | instance-property/Swift | x | s:14swift_ide_test8SubclassC1xSivp
565565
}
566566
}
567+
568+
// FIXME: Column 15 here is wrong...
569+
extension [Int] {
570+
// CHECK: [[@LINE-1]]:15 | extension/ext-struct/Swift | Array | s:e:s:Sa14swift_ide_testSiRszlE3fooyyF | Def | rel: 0
571+
// CHECK-NEXT: [[@LINE-2]]:11 | struct/Swift | Array | s:Sa | Ref,Impl,RelExt | rel: 1
572+
// CHECK-NEXT: RelExt | extension/ext-struct/Swift | Array | s:e:s:Sa14swift_ide_testSiRszlE3fooyyF
573+
// CHECK-NEXT: [[@LINE-4]]:12 | struct/Swift | Int | s:Si | Ref | rel: 0
574+
func foo() {}
575+
}
576+
577+
extension Array where Element == Int {
578+
// CHECK: [[@LINE-1]]:11 | extension/ext-struct/Swift | Array | s:e:s:Sa14swift_ide_testSiRszlE3baryyF | Def | rel: 0
579+
// CHECK-NEXT: [[@LINE-2]]:11 | struct/Swift | Array | s:Sa | Ref,RelExt | rel: 1
580+
// CHECK-NEXT: RelExt | extension/ext-struct/Swift | Array | s:e:s:Sa14swift_ide_testSiRszlE3baryyF
581+
// CHECK-NEXT: [[@LINE-4]]:23 | type-alias/generic-type-param/Swift | Element | s:Sa7Elementxmfp | Ref | rel: 0
582+
// CHECK-NEXT: [[@LINE-5]]:34 | struct/Swift | Int | s:Si | Ref | rel: 0
583+
func bar() {}
584+
}
585+
586+
extension Int? {
587+
// CHECK: [[@LINE-1]]:14 | extension/ext-enum/Swift | Optional | s:e:s:Sq14swift_ide_testSiRszlE3bazyyF | Def | rel: 0
588+
// CHECK-NEXT: [[@LINE-2]]:14 | enum/Swift | Optional | s:Sq | Ref,Impl,RelExt | rel: 1
589+
// CHECK-NEXT: RelExt | extension/ext-enum/Swift | Optional | s:e:s:Sq14swift_ide_testSiRszlE3bazyyF
590+
// CHECK-NEXT: [[@LINE-4]]:11 | struct/Swift | Int | s:Si | Ref | rel: 0
591+
func baz() {}
592+
}
593+
594+
typealias IntArray = [Int]
595+
typealias ArrayOf<T> = [T]
596+
597+
extension IntArray {
598+
// CHECK: [[@LINE-1]]:11 | extension/ext-struct/Swift | Array | s:e:s:Sa14swift_ide_testSiRszlE4flamyyF | Def | rel: 0
599+
// CHECK-NEXT: [[@LINE-2]]:11 | type-alias/Swift | IntArray | s:14swift_ide_test8IntArraya | Ref | rel: 0
600+
// CHECK-NEXT: [[@LINE-3]]:11 | struct/Swift | Array | s:Sa | Ref,Impl,RelExt | rel: 1
601+
// CHECK-NEXT: RelExt | extension/ext-struct/Swift | Array | s:e:s:Sa14swift_ide_testSiRszlE4flamyyF
602+
func flam() {}
603+
}
604+
605+
// FIXME: Column 22 here is wrong...
606+
extension ArrayOf<Int> {
607+
// CHECK: [[@LINE-1]]:22 | extension/ext-struct/Swift | Array | s:e:s:Sa14swift_ide_testSiRszlE4bishyyF | Def | rel: 0
608+
// CHECK-NEXT: [[@LINE-2]]:11 | type-alias/Swift | ArrayOf | s:14swift_ide_test7ArrayOfa | Ref | rel: 0
609+
// CHECK-NEXT: [[@LINE-3]]:11 | struct/Swift | Array | s:Sa | Ref,Impl,RelExt | rel: 1
610+
// CHECK-NEXT: RelExt | extension/ext-struct/Swift | Array | s:e:s:Sa14swift_ide_testSiRszlE4bishyyF
611+
func bish() {}
612+
}
613+

0 commit comments

Comments
 (0)