Skip to content

[5.9] Fix RelBase indexing with composite types #65536

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 37 additions & 5 deletions lib/Index/Index.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -878,6 +878,10 @@ class IndexSwiftASTWalker : public SourceEntityWalker {
auto AfterDollar = Loc.getAdvancedLoc(1);
reportRef(Wrapped, AfterDollar, Info, None);
}
} else if (auto *TAD = dyn_cast<TypeAliasDecl>(D)) {
TypeLoc TL(TAD->getUnderlyingTypeRepr(), TAD->getUnderlyingType());
if (!reportRelatedTypeRef(TL, (SymbolRoleSet)SymbolRole::Reference, D, /*isImplicit=*/true, Loc))
return false;
}

return true;
Expand Down Expand Up @@ -962,7 +966,18 @@ class IndexSwiftASTWalker : public SourceEntityWalker {
bool startEntityDecl(ValueDecl *D);

bool reportRelatedRef(ValueDecl *D, SourceLoc Loc, bool isImplicit, SymbolRoleSet Relations, Decl *Related);
bool reportRelatedTypeRef(const TypeLoc &Ty, SymbolRoleSet Relations, Decl *Related);

/// Report references for dependent types
///
/// NOTE: If the dependent type is a typealias, report the underlying types as well.
///
/// \param Ty The type being referenced.
/// \param Relations The relationship between the referenced type and the passed Decl.
/// \param Related The Decl that is referencing the type.
/// \param isImplicit Whether the reference is implicit, such as for a typealias' underlying type.
/// \param Loc The location of the reference, otherwise the location of the TypeLoc is used.
bool reportRelatedTypeRef(const TypeLoc &Ty, SymbolRoleSet Relations, Decl *Related,
bool isImplicit=false, SourceLoc Loc={});
bool reportInheritedTypeRefs(
ArrayRef<InheritedEntry> Inherited, Decl *Inheritee);
NominalTypeDecl *getTypeLocAsNominalTypeDecl(const TypeLoc &Ty);
Expand Down Expand Up @@ -1378,20 +1393,37 @@ bool IndexSwiftASTWalker::reportInheritedTypeRefs(ArrayRef<InheritedEntry> Inher
return true;
}

bool IndexSwiftASTWalker::reportRelatedTypeRef(const TypeLoc &Ty, SymbolRoleSet Relations, Decl *Related) {
if (auto *declRefTR = dyn_cast_or_null<DeclRefTypeRepr>(Ty.getTypeRepr())) {
SourceLoc IdLoc = declRefTR->getLoc();
bool IndexSwiftASTWalker::reportRelatedTypeRef(const TypeLoc &Ty, SymbolRoleSet Relations,
Decl *Related, bool Implicit, SourceLoc Loc) {
if (auto *composite = llvm::dyn_cast_or_null<CompositionTypeRepr>(Ty.getTypeRepr())) {
SourceLoc IdLoc = Loc.isValid() ? Loc : composite->getSourceLoc();
for (auto *Type : composite->getTypes()) {
if (!reportRelatedTypeRef(Type, Relations, Related, /*isImplicit=*/Implicit, IdLoc))
return false;
}

return true;
} else if (auto *declRefTR = dyn_cast_or_null<DeclRefTypeRepr>(Ty.getTypeRepr())) {
SourceLoc IdLoc = Loc.isValid() ? Loc : declRefTR->getLoc();
NominalTypeDecl *NTD = nullptr;
bool isImplicit = false;
bool isImplicit = Implicit;
if (auto *VD = declRefTR->getBoundDecl()) {
if (auto *TAD = dyn_cast<TypeAliasDecl>(VD)) {
IndexSymbol Info;
if (isImplicit)
Info.roles |= (unsigned)SymbolRole::Implicit;
if (!reportRef(TAD, IdLoc, Info, None))
return false;
if (auto Ty = TAD->getUnderlyingType()) {
NTD = Ty->getAnyNominal();
isImplicit = true;
}

if (isa_and_nonnull<CompositionTypeRepr>(TAD->getUnderlyingTypeRepr())) {
TypeLoc TL(TAD->getUnderlyingTypeRepr(), TAD->getUnderlyingType());
if (!reportRelatedTypeRef(TL, Relations, Related, /*isImplicit=*/true, IdLoc))
return false;
}
} else {
NTD = dyn_cast<NominalTypeDecl>(VD);
}
Expand Down
45 changes: 44 additions & 1 deletion test/Index/conformances.swift
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ protocol P3 {
func meth2() // CHECK: [[@LINE]]:8 | instance-method/Swift | meth2() | [[P3_meth2_USR:.*]] | Def
}

class BaseMultiConf {
class BaseMultiConf { // CHECK: [[@LINE]]:7 | class/Swift | BaseMultiConf | [[BaseMultiConf_USR:.*]] | Def
func meth2() {} // CHECK: [[@LINE]]:8 | instance-method/Swift | meth2() | [[BaseMultiConf_meth2_USR:.*]] | Def
}
extension SubMultiConf {
Expand All @@ -79,6 +79,49 @@ class SubMultiConf: BaseMultiConf,P2,P1,P3 { // CHECK: [[@LINE]]:7 | class/Swift
// CHECK-NOT: [[@LINE-13]]:7 | instance-method
}

class CompositionType: BaseMultiConf & P1 { // CHECK: [[@LINE]]:7 | class/Swift | CompositionType | [[CompositionType_USR:.*]] | Def
// CHECK: [[@LINE-1]]:24 | class/Swift | BaseMultiConf | [[BaseMultiConf_USR]] | Ref,RelBase | rel: 1
// CHECK: [[@LINE-2]]:24 | protocol/Swift | P1 | [[P1_USR]] | Ref,RelBase | rel: 1
func foo() {}
}

typealias CompositionTypeAlias = BaseMultiConf & P1 // CHECK: [[@LINE]]:11 | type-alias/Swift | CompositionTypeAlias | [[CompositionTypeAlias_USR:.*]] | Def
// CHECK: [[@LINE-1]]:34 | class/Swift | BaseMultiConf | [[BaseMultiConf_USR]] | Ref | rel: 0
// CHECK: [[@LINE-2]]:50 | protocol/Swift | P1 | [[P1_USR]] | Ref | rel: 0

class CompositionTypeViaAlias: CompositionTypeAlias { // CHECK: [[@LINE]]:7 | class/Swift | CompositionTypeViaAlias | [[CompositionTypeViaAlias_USR:.*]] | Def
// CHECK: [[@LINE-1]]:32 | type-alias/Swift | CompositionTypeAlias | [[CompositionTypeAlias_USR]] | Ref | rel: 0
// CHECK: [[@LINE-2]]:32 | class/Swift | BaseMultiConf | [[BaseMultiConf_USR]] | Ref,Impl,RelBase | rel: 1
// CHECK: [[@LINE-3]]:32 | protocol/Swift | P1 | [[P1_USR]] | Ref,Impl,RelBase | rel: 1
func foo() {}
}

typealias NestedCompositionTypeAlias = CompositionTypeAlias & P2 // CHECK: [[@LINE]]:11 | type-alias/Swift | NestedCompositionTypeAlias | [[NestedCompositionTypeAlias_USR:.*]] | Def
// CHECK: [[@LINE-1]]:40 | type-alias/Swift | CompositionTypeAlias | [[CompositionTypeAlias_USR]] | Ref | rel: 0
// CHECK: [[@LINE-2]]:40 | class/Swift | BaseMultiConf | [[BaseMultiConf_USR]] | Ref,Impl | rel: 1
// CHECK: [[@LINE-3]]:40 | protocol/Swift | P1 | [[P1_USR]] | Ref,Impl | rel: 1
// CHECK: [[@LINE-4]]:63 | protocol/Swift | P2 | [[P2_USR]] | Ref | rel: 0

class CompositionViaNestedAlias: NestedCompositionTypeAlias { // CHECK: [[@LINE]]:7 | class/Swift | CompositionViaNestedAlias | [[CompositionViaNestedAlias_USR:.*]] | Def
// CHECK: [[@LINE-1]]:34 | type-alias/Swift | NestedCompositionTypeAlias | [[NestedCompositionTypeAlias_USR]] | Ref | rel: 0
// CHECK: [[@LINE-2]]:34 | class/Swift | BaseMultiConf | [[BaseMultiConf_USR]] | Ref,Impl,RelBase | rel: 1
// CHECK: [[@LINE-3]]:34 | protocol/Swift | P1 | [[P1_USR]] | Ref,Impl,RelBase | rel: 1
// CHECK: [[@LINE-4]]:34 | protocol/Swift | P2 | [[P2_USR]] | Ref,Impl,RelBase | rel: 1
func foo() {}
}

typealias ProtocolsOnly = P1 & P2 // CHECK: [[@LINE]]:11 | type-alias/Swift | ProtocolsOnly | [[ProtocolsOnly_USR:.*]] | Def
// CHECK: [[@LINE-1]]:27 | protocol/Swift | P1 | [[P1_USR]] | Ref | rel: 0
// CHECK: [[@LINE-2]]:32 | protocol/Swift | P2 | [[P2_USR]] | Ref | rel: 0

class NoInherited {} // CHECK: [[@LINE]]:7 | class/Swift | NoInherited | [[NoInherited_USR:.*]] | Def
extension NoInherited: ProtocolsOnly {} // CHECK: [[@LINE]]:11 | class/Swift | NoInherited | [[NoInherited_USR:.*]] | Ref
// CHECK: [[@LINE-1]]:24 | type-alias/Swift | ProtocolsOnly | [[ProtocolsOnly_USR]] | Ref | rel: 0
// CHECK: [[@LINE-2]]:24 | protocol/Swift | P1 | [[P1_USR]] | Ref,Impl | rel: 1
// CHECK: [[@LINE-3]]:24 | protocol/Swift | P2 | [[P2_USR]] | Ref,Impl | rel: 1

struct WithCodable: Codable {} // CHECK: [[@LINE]]:21 | type-alias/Swift | Codable | [[Codable_USR:.*]] | Ref | rel: 0

protocol InheritingP: P1 { // CHECK: [[@LINE]]:10 | protocol/Swift | InheritingP | [[InheritingP_USR:.*]] | Def
func foo() // CHECK: [[@LINE]]:8 | instance-method/Swift | foo() | [[InheritingP_foo_USR:.*]] | Def,Dyn,RelChild,RelOver | rel: 2
// CHECK-NEXT: RelOver | instance-method/Swift | foo() | s:14swift_ide_test2P1P3fooyyF
Expand Down
7 changes: 7 additions & 0 deletions test/SourceKit/Indexing/index.swift.response
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,13 @@
key.usr: <usr>,
key.line: 50,
key.column: 19
},
{
key.kind: source.lang.swift.ref.class,
key.usr: <usr>,
key.line: 50,
key.column: 19,
key.is_implicit: 1
}
],
key.effective_access: source.decl.effective_access.internal
Expand Down