Skip to content

Commit 73ce0af

Browse files
authored
Merge pull request #85775 from hamishknight/related-fix-6.3
[6.3] [Index] Handle implicit reference relations for type sugar
2 parents 2c1a6dd + 8742a30 commit 73ce0af

File tree

3 files changed

+172
-63
lines changed

3 files changed

+172
-63
lines changed

lib/Index/Index.cpp

Lines changed: 69 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -103,12 +103,8 @@ static bool isMemberwiseInit(swift::ValueDecl *D) {
103103
}
104104

105105
static SourceLoc getLocForExtension(ExtensionDecl *D) {
106-
// Use the 'End' token of the range, in case it is a compound name, e.g.
107-
// extension A.B {}
108-
// we want the location of 'B' token.
109-
if (auto *repr = D->getExtendedTypeRepr()) {
110-
return repr->getSourceRange().End;
111-
}
106+
if (auto *repr = D->getExtendedTypeRepr())
107+
return repr->getLoc();
112108
return SourceLoc();
113109
}
114110

@@ -1037,21 +1033,23 @@ class IndexSwiftASTWalker : public SourceEntityWalker {
10371033

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

1040-
/// Report a related type relation for a given TypeRepr.
1036+
/// Report a related type relation for a given TypeLoc. Don't call this
1037+
/// directly, use \c reportRelatedTypeRef instead.
10411038
///
10421039
/// NOTE: If the dependent type is a typealias, report the underlying types as
10431040
/// well.
10441041
///
1045-
/// \param TR The type being referenced.
1042+
/// \param TL The type being referenced.
10461043
/// \param Relations The relationship between the referenced type and the
10471044
/// passed Decl.
10481045
/// \param Related The Decl that is referencing the type.
10491046
/// \param Implicit Whether the reference is implicit, such as for a
10501047
/// typealias' underlying type.
10511048
/// \param ParentLoc The parent location of the reference that should be used
10521049
/// for implicit references.
1053-
bool reportRelatedTypeRepr(const TypeRepr *TR, SymbolRoleSet Relations,
1054-
Decl *Related, bool Implicit, SourceLoc ParentLoc);
1050+
bool reportRelatedTypeRefImpl(const TypeLoc &TL, SymbolRoleSet Relations,
1051+
Decl *Related, bool Implicit,
1052+
SourceLoc ParentLoc);
10551053

10561054
/// Report a related type relation for a Type at a given location.
10571055
///
@@ -1531,66 +1529,85 @@ bool IndexSwiftASTWalker::reportInheritedTypeRefs(InheritedTypes Inherited,
15311529
return true;
15321530
}
15331531

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;
1532+
bool IndexSwiftASTWalker::reportRelatedTypeRefImpl(const TypeLoc &TL,
1533+
SymbolRoleSet Relations,
1534+
Decl *Related, bool Implicit,
1535+
SourceLoc ParentLoc) {
1536+
auto *TR = TL.getTypeRepr();
1537+
if (TR) {
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;
1551+
}
1552+
break;
15511553
}
1552-
break;
1553-
}
1554-
// NOTE: We don't yet handle InverseTypeRepr since we don't have an inverse
1555-
// relation for inheritance.
1554+
// NOTE: We don't yet handle InverseTypeRepr since we don't have an inverse
1555+
// relation for inheritance.
15561556

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

15691591
auto *VD = declRefTR->getBoundDecl();
15701592
if (!VD)
15711593
return true;
15721594

1573-
SourceLoc IdLoc = ParentLoc.isValid() ? ParentLoc : declRefTR->getLoc();
15741595
if (auto *TAD = dyn_cast<TypeAliasDecl>(VD)) {
15751596
IndexSymbol Info;
15761597
if (Implicit)
15771598
Info.roles |= (unsigned)SymbolRole::Implicit;
1578-
if (!reportRef(TAD, IdLoc, Info, std::nullopt))
1599+
if (!reportRef(TAD, Loc, Info, std::nullopt))
15791600
return false;
15801601

15811602
// Recurse into the underlying type and report any found references as
15821603
// 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);
1604+
TypeLoc UnderlyingTL(TAD->getUnderlyingTypeRepr(),
1605+
TAD->getUnderlyingType());
1606+
return reportRelatedTypeRefImpl(UnderlyingTL, Relations, Related,
1607+
/*Implicit*/ true, /*ParentLoc*/ Loc);
15911608
}
15921609
if (auto *NTD = dyn_cast<NominalTypeDecl>(VD)) {
1593-
if (!reportRelatedRef(NTD, IdLoc, Implicit, Relations, Related))
1610+
if (!reportRelatedRef(NTD, Loc, Implicit, Relations, Related))
15941611
return false;
15951612
}
15961613
return true;
@@ -1618,19 +1635,8 @@ bool IndexSwiftASTWalker::reportRelatedType(Type Ty, SymbolRoleSet Relations,
16181635
bool IndexSwiftASTWalker::reportRelatedTypeRef(const TypeLoc &TL,
16191636
SymbolRoleSet Relations,
16201637
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;
1638+
return reportRelatedTypeRefImpl(TL, Relations, Related, /*Implicit*/ false,
1639+
/*ParentLoc*/ SourceLoc());
16341640
}
16351641

16361642
bool IndexSwiftASTWalker::reportPseudoAccessor(AbstractStorageDecl *D,

test/Index/index_imported.swift

Lines changed: 58 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,19 @@ 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+
extension ArrayOf<Int> {
96+
// CHECK: [[@LINE-1]]:11 | extension/ext-struct/Swift | Array | s:e:s:Sa14swift_ide_testSiRszlE4bishyyF | Def | rel: 0
97+
// CHECK-NEXT: [[@LINE-2]]:11 | type-alias/Swift | ArrayOf | s:3Lib7ArrayOfa | Ref | rel: 0
98+
// CHECK-NEXT: [[@LINE-3]]:11 | struct/Swift | Array | s:Sa | Ref,Impl,RelExt | rel: 1
99+
// CHECK-NEXT: RelExt | extension/ext-struct/Swift | Array | s:e:s:Sa14swift_ide_testSiRszlE4bishyyF
100+
func bish() {}
101+
}

test/Index/roles.swift

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

0 commit comments

Comments
 (0)