mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[index] Improvements on how conformances are recorded (#19043)
Query for the local conformances of a DeclContext and record conformances of functions that are defined in other types as 'implicit' overrides, with the type that introduces the conformance as container symbol. This allows more accurate index data, and avoids needing to query for all protocol requirements, which is expensive to calculate.
This commit is contained in:
committed by
GitHub
parent
b3a3220e38
commit
3bd80e5e31
@@ -19,6 +19,7 @@
|
|||||||
#include "swift/AST/Expr.h"
|
#include "swift/AST/Expr.h"
|
||||||
#include "swift/AST/Module.h"
|
#include "swift/AST/Module.h"
|
||||||
#include "swift/AST/ParameterList.h"
|
#include "swift/AST/ParameterList.h"
|
||||||
|
#include "swift/AST/ProtocolConformance.h"
|
||||||
#include "swift/AST/Types.h"
|
#include "swift/AST/Types.h"
|
||||||
#include "swift/AST/USRGeneration.h"
|
#include "swift/AST/USRGeneration.h"
|
||||||
#include "swift/Basic/SourceManager.h"
|
#include "swift/Basic/SourceManager.h"
|
||||||
@@ -78,6 +79,13 @@ static bool isMemberwiseInit(swift::ValueDecl *D) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static SourceLoc getLocForExtension(ExtensionDecl *D) {
|
||||||
|
// Use the 'End' token of the range, in case it is a compound name, e.g.
|
||||||
|
// extension A.B {}
|
||||||
|
// we want the location of 'B' token.
|
||||||
|
return D->getExtendedTypeLoc().getSourceRange().End;
|
||||||
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
// Adapter providing a common interface for a SourceFile/Module.
|
// Adapter providing a common interface for a SourceFile/Module.
|
||||||
class SourceFileOrModule {
|
class SourceFileOrModule {
|
||||||
@@ -121,6 +129,11 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ValueWitness {
|
||||||
|
ValueDecl *Member;
|
||||||
|
ValueDecl *Requirement;
|
||||||
|
};
|
||||||
|
|
||||||
class IndexSwiftASTWalker : public SourceEntityWalker {
|
class IndexSwiftASTWalker : public SourceEntityWalker {
|
||||||
IndexDataConsumer &IdxConsumer;
|
IndexDataConsumer &IdxConsumer;
|
||||||
SourceManager &SrcMgr;
|
SourceManager &SrcMgr;
|
||||||
@@ -133,6 +146,7 @@ class IndexSwiftASTWalker : public SourceEntityWalker {
|
|||||||
Decl *D;
|
Decl *D;
|
||||||
SymbolInfo SymInfo;
|
SymbolInfo SymInfo;
|
||||||
SymbolRoleSet Roles;
|
SymbolRoleSet Roles;
|
||||||
|
SmallVector<ValueWitness, 6> ExplicitValueWitnesses;
|
||||||
SmallVector<SourceLoc, 6> RefsToSuppress;
|
SmallVector<SourceLoc, 6> RefsToSuppress;
|
||||||
};
|
};
|
||||||
SmallVector<Entity, 6> EntitiesStack;
|
SmallVector<Entity, 6> EntitiesStack;
|
||||||
@@ -319,7 +333,7 @@ private:
|
|||||||
IndexSymbol Info;
|
IndexSymbol Info;
|
||||||
if (initIndexSymbol(Prop, *LabelIt++, /*IsRef=*/true, Info))
|
if (initIndexSymbol(Prop, *LabelIt++, /*IsRef=*/true, Info))
|
||||||
continue;
|
continue;
|
||||||
if (startEntity(Prop, Info))
|
if (startEntity(Prop, Info, /*IsRef=*/true))
|
||||||
finishCurrentEntity();
|
finishCurrentEntity();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -398,8 +412,10 @@ private:
|
|||||||
bool reportExtension(ExtensionDecl *D);
|
bool reportExtension(ExtensionDecl *D);
|
||||||
bool reportRef(ValueDecl *D, SourceLoc Loc, IndexSymbol &Info,
|
bool reportRef(ValueDecl *D, SourceLoc Loc, IndexSymbol &Info,
|
||||||
Optional<AccessKind> AccKind);
|
Optional<AccessKind> AccKind);
|
||||||
|
bool reportImplicitValueConformance(ValueDecl *witness, ValueDecl *requirement,
|
||||||
|
Decl *container);
|
||||||
|
|
||||||
bool startEntity(Decl *D, IndexSymbol &Info);
|
bool startEntity(Decl *D, IndexSymbol &Info, bool IsRef);
|
||||||
bool startEntityDecl(ValueDecl *D);
|
bool startEntityDecl(ValueDecl *D);
|
||||||
|
|
||||||
bool reportRelatedRef(ValueDecl *D, SourceLoc Loc, bool isImplicit, SymbolRoleSet Relations, Decl *Related);
|
bool reportRelatedRef(ValueDecl *D, SourceLoc Loc, bool isImplicit, SymbolRoleSet Relations, Decl *Related);
|
||||||
@@ -459,6 +475,14 @@ private:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Reports all implicit member value decl conformances that \p D introduces
|
||||||
|
/// as implicit overrides at the source location of \p D, and returns the
|
||||||
|
/// explicit ones so we can check against them later on when visiting them as
|
||||||
|
/// members.
|
||||||
|
///
|
||||||
|
/// \returns false if AST visitation should stop.
|
||||||
|
bool handleValueWitnesses(Decl *D, SmallVectorImpl<ValueWitness> &explicitValueWitnesses);
|
||||||
|
|
||||||
void getModuleHash(SourceFileOrModule SFOrMod, llvm::raw_ostream &OS);
|
void getModuleHash(SourceFileOrModule SFOrMod, llvm::raw_ostream &OS);
|
||||||
llvm::hash_code hashModule(llvm::hash_code code, SourceFileOrModule SFOrMod);
|
llvm::hash_code hashModule(llvm::hash_code code, SourceFileOrModule SFOrMod);
|
||||||
llvm::hash_code hashFileReference(llvm::hash_code code,
|
llvm::hash_code hashFileReference(llvm::hash_code code,
|
||||||
@@ -612,16 +636,53 @@ bool IndexSwiftASTWalker::visitImports(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IndexSwiftASTWalker::startEntity(Decl *D, IndexSymbol &Info) {
|
bool IndexSwiftASTWalker::handleValueWitnesses(Decl *D, SmallVectorImpl<ValueWitness> &explicitValueWitnesses) {
|
||||||
|
auto DC = dyn_cast<DeclContext>(D);
|
||||||
|
if (!DC)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
for (auto *conf : DC->getLocalConformances()) {
|
||||||
|
if (conf->isInvalid())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
auto normal = conf->getRootNormalConformance();
|
||||||
|
normal->forEachValueWitness(nullptr,
|
||||||
|
[&](ValueDecl *req, Witness witness) {
|
||||||
|
if (Cancelled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto *decl = witness.getDecl();
|
||||||
|
if (decl->getDeclContext() == DC) {
|
||||||
|
explicitValueWitnesses.push_back(ValueWitness{decl, req});
|
||||||
|
} else {
|
||||||
|
// Report the implicit conformance.
|
||||||
|
reportImplicitValueConformance(decl, req, D);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Cancelled)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IndexSwiftASTWalker::startEntity(Decl *D, IndexSymbol &Info, bool IsRef) {
|
||||||
switch (IdxConsumer.startSourceEntity(Info)) {
|
switch (IdxConsumer.startSourceEntity(Info)) {
|
||||||
case swift::index::IndexDataConsumer::Abort:
|
case swift::index::IndexDataConsumer::Abort:
|
||||||
Cancelled = true;
|
Cancelled = true;
|
||||||
LLVM_FALLTHROUGH;
|
LLVM_FALLTHROUGH;
|
||||||
case swift::index::IndexDataConsumer::Skip:
|
case swift::index::IndexDataConsumer::Skip:
|
||||||
return false;
|
return false;
|
||||||
case swift::index::IndexDataConsumer::Continue:
|
case swift::index::IndexDataConsumer::Continue: {
|
||||||
EntitiesStack.push_back({D, Info.symInfo, Info.roles, {}});
|
SmallVector<ValueWitness, 6> explicitValueWitnesses;
|
||||||
|
if (!IsRef) {
|
||||||
|
if (!handleValueWitnesses(D, explicitValueWitnesses))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
EntitiesStack.push_back({D, Info.symInfo, Info.roles, std::move(explicitValueWitnesses), {}});
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
llvm_unreachable("Unhandled IndexDataConsumer in switch.");
|
llvm_unreachable("Unhandled IndexDataConsumer in switch.");
|
||||||
@@ -649,12 +710,15 @@ bool IndexSwiftASTWalker::startEntityDecl(ValueDecl *D) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto Overriden: getOverriddenDecls(D, /*IncludeProtocolReqs=*/!isSystemModule)) {
|
for (auto Overriden: getOverriddenDecls(D, /*IncludeProtocolReqs=*/false)) {
|
||||||
if (addRelation(Info, (SymbolRoleSet) SymbolRole::RelationOverrideOf, Overriden))
|
addRelation(Info, (SymbolRoleSet) SymbolRole::RelationOverrideOf, Overriden);
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auto Parent = getParentDecl()) {
|
if (auto Parent = getParentDecl()) {
|
||||||
|
for (const ValueWitness &witness : EntitiesStack.back().ExplicitValueWitnesses) {
|
||||||
|
if (witness.Member == D)
|
||||||
|
addRelation(Info, (SymbolRoleSet) SymbolRole::RelationOverrideOf, witness.Requirement);
|
||||||
|
}
|
||||||
if (auto ParentVD = dyn_cast<ValueDecl>(Parent)) {
|
if (auto ParentVD = dyn_cast<ValueDecl>(Parent)) {
|
||||||
SymbolRoleSet RelationsToParent = (SymbolRoleSet)SymbolRole::RelationChildOf;
|
SymbolRoleSet RelationsToParent = (SymbolRoleSet)SymbolRole::RelationChildOf;
|
||||||
if (Info.symInfo.SubKind == SymbolSubKind::AccessorGetter ||
|
if (Info.symInfo.SubKind == SymbolSubKind::AccessorGetter ||
|
||||||
@@ -673,7 +737,7 @@ bool IndexSwiftASTWalker::startEntityDecl(ValueDecl *D) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return startEntity(D, Info);
|
return startEntity(D, Info, /*IsRef=*/false);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IndexSwiftASTWalker::reportRelatedRef(ValueDecl *D, SourceLoc Loc, bool isImplicit,
|
bool IndexSwiftASTWalker::reportRelatedRef(ValueDecl *D, SourceLoc Loc, bool isImplicit,
|
||||||
@@ -836,10 +900,7 @@ IndexSwiftASTWalker::getTypeLocAsNominalTypeDecl(const TypeLoc &Ty) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool IndexSwiftASTWalker::reportExtension(ExtensionDecl *D) {
|
bool IndexSwiftASTWalker::reportExtension(ExtensionDecl *D) {
|
||||||
// Use the 'End' token of the range, in case it is a compound name, e.g.
|
SourceLoc Loc = getLocForExtension(D);
|
||||||
// extension A.B {}
|
|
||||||
// we want the location of 'B' token.
|
|
||||||
SourceLoc Loc = D->getExtendedTypeLoc().getSourceRange().End;
|
|
||||||
NominalTypeDecl *NTD = D->getExtendedNominal();
|
NominalTypeDecl *NTD = D->getExtendedNominal();
|
||||||
if (!NTD)
|
if (!NTD)
|
||||||
return true;
|
return true;
|
||||||
@@ -850,7 +911,7 @@ bool IndexSwiftASTWalker::reportExtension(ExtensionDecl *D) {
|
|||||||
if (initIndexSymbol(D, NTD, Loc, Info))
|
if (initIndexSymbol(D, NTD, Loc, Info))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (!startEntity(D, Info))
|
if (!startEntity(D, Info, /*IsRef=*/false))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!reportRelatedRef(NTD, Loc, /*isImplicit=*/false,
|
if (!reportRelatedRef(NTD, Loc, /*isImplicit=*/false,
|
||||||
@@ -940,7 +1001,7 @@ bool IndexSwiftASTWalker::reportRef(ValueDecl *D, SourceLoc Loc,
|
|||||||
if (isSystemModule && !hasUsefulRoleInSystemModule(Info.roles))
|
if (isSystemModule && !hasUsefulRoleInSystemModule(Info.roles))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (!startEntity(D, Info))
|
if (!startEntity(D, Info, /*IsRef=*/true))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// Report the accessors that were utilized.
|
// Report the accessors that were utilized.
|
||||||
@@ -961,6 +1022,34 @@ bool IndexSwiftASTWalker::reportRef(ValueDecl *D, SourceLoc Loc,
|
|||||||
return finishCurrentEntity();
|
return finishCurrentEntity();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IndexSwiftASTWalker::reportImplicitValueConformance(ValueDecl *witness, ValueDecl *requirement,
|
||||||
|
Decl *container) {
|
||||||
|
if (!shouldIndex(witness, /*IsRef=*/true))
|
||||||
|
return true; // keep walking
|
||||||
|
|
||||||
|
SourceLoc loc;
|
||||||
|
if (auto *extD = dyn_cast<ExtensionDecl>(container))
|
||||||
|
loc = getLocForExtension(extD);
|
||||||
|
else
|
||||||
|
loc = container->getLoc();
|
||||||
|
|
||||||
|
IndexSymbol info;
|
||||||
|
if (initIndexSymbol(witness, loc, /*IsRef=*/true, info))
|
||||||
|
return true;
|
||||||
|
if (addRelation(info, (SymbolRoleSet) SymbolRole::RelationOverrideOf, requirement))
|
||||||
|
return true;
|
||||||
|
if (addRelation(info, (SymbolRoleSet) SymbolRole::RelationContainedBy, container))
|
||||||
|
return true;
|
||||||
|
// Remove the 'ref' role that \c initIndexSymbol introduces. This isn't
|
||||||
|
// actually a 'reference', but an 'implicit' override.
|
||||||
|
info.roles &= ~(SymbolRoleSet)SymbolRole::Reference;
|
||||||
|
info.roles |= (SymbolRoleSet)SymbolRole::Implicit;
|
||||||
|
|
||||||
|
if (!startEntity(witness, info, /*IsRef=*/true))
|
||||||
|
return true;
|
||||||
|
return finishCurrentEntity();
|
||||||
|
}
|
||||||
|
|
||||||
bool IndexSwiftASTWalker::initIndexSymbol(ValueDecl *D, SourceLoc Loc,
|
bool IndexSwiftASTWalker::initIndexSymbol(ValueDecl *D, SourceLoc Loc,
|
||||||
bool IsRef, IndexSymbol &Info) {
|
bool IsRef, IndexSymbol &Info) {
|
||||||
assert(D);
|
assert(D);
|
||||||
|
|||||||
102
test/Index/conformances.swift
Normal file
102
test/Index/conformances.swift
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
// RUN: %target-swift-ide-test -print-indexed-symbols -source-filename %s | %FileCheck %s
|
||||||
|
|
||||||
|
protocol P1 { // CHECK: [[@LINE]]:10 | protocol/Swift | P1 | [[P1_USR:.*]] | Def |
|
||||||
|
func foo() // CHECK: [[@LINE]]:8 | instance-method/Swift | foo() | [[P1_foo_USR:.*]] | Def
|
||||||
|
}
|
||||||
|
|
||||||
|
struct DirectConf: P1 { // CHECK: [[@LINE]]:8 | struct/Swift | DirectConf | [[DirectConf_USR:.*]] | Def
|
||||||
|
func foo() {} // CHECK: [[@LINE]]:8 | instance-method/Swift | foo() | [[DirectConf_foo_USR:.*]] | Def,RelChild,RelOver | rel: 2
|
||||||
|
// CHECK-NEXT: RelOver | instance-method/Swift | foo() | [[P1_foo_USR]]
|
||||||
|
// CHECK-NEXT: RelChild | struct/Swift | DirectConf | [[DirectConf_USR]]
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ConfFromExtension {}
|
||||||
|
extension ConfFromExtension: P1 { // CHECK: [[@LINE]]:11 | extension/ext-struct/Swift | ConfFromExtension | [[ConfFromExtension_ext_USR:.*]] | Def
|
||||||
|
func foo() {} // CHECK: [[@LINE]]:8 | instance-method/Swift | foo() | [[ConfFromExtension_ext_foo_USR:.*]] | Def,RelChild,RelOver | rel: 2
|
||||||
|
// CHECK-NEXT: RelOver | instance-method/Swift | foo() | [[P1_foo_USR]]
|
||||||
|
// CHECK-NEXT: RelChild | extension/ext-struct/Swift | ConfFromExtension | [[ConfFromExtension_ext_USR]]
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ImplicitConfFromExtension { // CHECK: [[@LINE]]:8 | struct/Swift | ImplicitConfFromExtension | [[ImplicitConfFromExtension_USR:.*]] | Def
|
||||||
|
func foo() {} // CHECK: [[@LINE]]:8 | instance-method/Swift | foo() | [[ImplicitConfFromExtension_foo_USR:.*]] | Def,RelChild | rel: 1
|
||||||
|
// CHECK-NEXT: RelChild | struct/Swift | ImplicitConfFromExtension | [[ImplicitConfFromExtension_USR]]
|
||||||
|
}
|
||||||
|
extension ImplicitConfFromExtension: P1 { // CHECK: [[@LINE]]:11 | extension/ext-struct/Swift | ImplicitConfFromExtension | [[ImplicitConfFromExtension_USR:.*]] | Def
|
||||||
|
// CHECK: [[@LINE-1]]:11 | instance-method/Swift | foo() | [[ImplicitConfFromExtension_foo_USR]] | Impl,RelOver,RelCont | rel: 2
|
||||||
|
// CHECK-NEXT: RelOver | instance-method/Swift | foo() | [[P1_foo_USR]]
|
||||||
|
// CHECK-NEXT: RelCont | extension/ext-struct/Swift | ImplicitConfFromExtension | [[ImplicitConfFromExtension_USR]]
|
||||||
|
}
|
||||||
|
|
||||||
|
class BaseConfFromBase { // CHECK: [[@LINE]]:7 | class/Swift | BaseConfFromBase | [[BaseConfFromBase_USR:.*]] | Def
|
||||||
|
func foo() {} // CHECK: [[@LINE]]:8 | instance-method/Swift | foo() | [[BaseConfFromBase_foo_USR:.*]] | Def,Dyn,RelChild | rel: 1
|
||||||
|
// CHECK-NEXT: RelChild | class/Swift | BaseConfFromBase | [[BaseConfFromBase_USR]]
|
||||||
|
}
|
||||||
|
class SubConfFromBase: BaseConfFromBase, P1 { // CHECK: [[@LINE]]:7 | class/Swift | SubConfFromBase | [[SubConfFromBase_USR:.*]] | Def
|
||||||
|
// CHECK: [[@LINE-1]]:7 | instance-method/Swift | foo() | [[BaseConfFromBase_foo_USR]] | Impl,RelOver,RelCont | rel: 2
|
||||||
|
// CHECK-NEXT: RelOver | instance-method/Swift | foo() | [[P1_foo_USR]]
|
||||||
|
// CHECK-NEXT: RelCont | class/Swift | SubConfFromBase | [[SubConfFromBase_USR]]
|
||||||
|
}
|
||||||
|
|
||||||
|
protocol P2 { // CHECK: [[@LINE]]:10 | protocol/Swift | P2 | [[P2_USR:.*]] | Def |
|
||||||
|
func foo() // CHECK: [[@LINE]]:8 | instance-method/Swift | foo() | [[P2_foo_USR:.*]] | Def
|
||||||
|
}
|
||||||
|
extension P2 { // CHECK: [[@LINE]]:11 | extension/ext-protocol/Swift | P2 | [[P2_ext_USR:.*]] | Def
|
||||||
|
func foo() {} // CHECK: [[@LINE]]:8 | instance-method/Swift | foo() | [[P2_ext_foo_USR:.*]] | Def,Dyn,RelChild,RelOver | rel: 2
|
||||||
|
// CHECK-NEXT: RelOver | instance-method/Swift | foo() | [[P2_foo_USR]]
|
||||||
|
// CHECK-NEXT: RelChild | extension/ext-protocol/Swift | P2 | [[P2_ext_USR]]
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ConfFromDefaultImpl: P2 { // CHECK: [[@LINE]]:8 | struct/Swift | ConfFromDefaultImpl | [[ConfFromDefaultImpl_USR:.*]] | Def
|
||||||
|
// CHECK: [[@LINE-1]]:8 | instance-method/Swift | foo() | [[P2_ext_foo_USR]] | Impl,RelOver,RelCont | rel: 2
|
||||||
|
// CHECK-NEXT: RelOver | instance-method/Swift | foo() | [[P2_foo_USR]]
|
||||||
|
// CHECK-NEXT: RelCont | struct/Swift | ConfFromDefaultImpl | [[ConfFromDefaultImpl_USR]]
|
||||||
|
}
|
||||||
|
|
||||||
|
protocol P3 {
|
||||||
|
func meth1() // CHECK: [[@LINE]]:8 | instance-method/Swift | meth1() | [[P3_meth1_USR:.*]] | Def
|
||||||
|
func meth2() // CHECK: [[@LINE]]:8 | instance-method/Swift | meth2() | [[P3_meth2_USR:.*]] | Def
|
||||||
|
}
|
||||||
|
|
||||||
|
class BaseMultiConf {
|
||||||
|
func meth2() {} // CHECK: [[@LINE]]:8 | instance-method/Swift | meth2() | [[BaseMultiConf_meth2_USR:.*]] | Def
|
||||||
|
}
|
||||||
|
extension SubMultiConf {
|
||||||
|
func meth1() {} // CHECK: [[@LINE]]:8 | instance-method/Swift | meth1() | [[SubMultiConf_ext_meth1_USR:.*]] | Def
|
||||||
|
}
|
||||||
|
class SubMultiConf: BaseMultiConf,P2,P1,P3 { // CHECK: [[@LINE]]:7 | class/Swift | SubMultiConf | [[SubMultiConf_USR:.*]] | Def
|
||||||
|
// CHECK: [[@LINE-1]]:7 | instance-method/Swift | foo() | [[P2_ext_foo_USR]] | Impl,RelOver,RelCont | rel: 2
|
||||||
|
// CHECK-NEXT RelOver | instance-method/Swift | foo() | [[P2_foo_USR]]
|
||||||
|
// CHECK-NEXT RelCont | class/Swift | SubMultiConf | [[SubMultiConf_USR]]
|
||||||
|
// CHECK: [[@LINE-4]]:7 | instance-method/Swift | foo() | [[P2_ext_foo_USR]] | Impl,RelOver,RelCont | rel: 2
|
||||||
|
// CHECK-NEXT RelOver | instance-method/Swift | foo() | [[P1_foo_USR]]
|
||||||
|
// CHECK-NEXT RelCont | class/Swift | SubMultiConf | [[SubMultiConf_USR]]
|
||||||
|
// CHECK: [[@LINE-7]]:7 | instance-method/Swift | meth1() | [[SubMultiConf_ext_meth1_USR]] | Impl,RelOver,RelCont | rel: 2
|
||||||
|
// CHECK-NEXT RelOver | instance-method/Swift | meth1() | [[P3_meth1_USR]]
|
||||||
|
// CHECK-NEXT RelCont | class/Swift | SubMultiConf | [[SubMultiConf_USR]]
|
||||||
|
// CHECK: [[@LINE-10]]:7 | instance-method/Swift | meth2() | [[BaseMultiConf_meth2_USR]] | Impl,RelOver,RelCont | rel: 2
|
||||||
|
// CHECK-NEXT RelOver | instance-method/Swift | meth2() | [[P3_meth2_USR]]
|
||||||
|
// CHECK-NEXT RelCont | class/Swift | SubMultiConf | [[SubMultiConf_USR]]
|
||||||
|
// CHECK-NOT: [[@LINE-13]]:7 | instance-method
|
||||||
|
}
|
||||||
|
|
||||||
|
protocol InheritingP: P1 { // CHECK: [[@LINE]]:10 | protocol/Swift | InheritingP | [[InheritingP_USR:.*]] | Def
|
||||||
|
// FIXME: Should have override relation with P1.foo()
|
||||||
|
func foo() // CHECK: [[@LINE]]:8 | instance-method/Swift | foo() | [[InheritingP_foo_USR:.*]] | Def,Dyn,RelChild | rel: 1
|
||||||
|
// CHECK-NEXT: RelChild | protocol/Swift | InheritingP | [[InheritingP_USR]]
|
||||||
|
}
|
||||||
|
|
||||||
|
struct DirectConf2: InheritingP { // CHECK: [[@LINE]]:8 | struct/Swift | DirectConf2 | [[DirectConf2_USR:.*]] | Def
|
||||||
|
// FIXME: Should only override InheritingP.foo()
|
||||||
|
func foo() {} // CHECK: [[@LINE]]:8 | instance-method/Swift | foo() | [[DirectConf2_foo_USR:.*]] | Def,RelChild,RelOver | rel: 3
|
||||||
|
// CHECK-NEXT: RelOver | instance-method/Swift | foo() | [[InheritingP_foo_USR]]
|
||||||
|
// CHECK-NEXT: RelOver | instance-method/Swift | foo() | [[P1_foo_USR]]
|
||||||
|
// CHECK-NEXT: RelChild | struct/Swift | DirectConf2 | [[DirectConf2_USR]]
|
||||||
|
}
|
||||||
|
|
||||||
|
extension InheritingP { // CHECK: [[@LINE]]:11 | extension/ext-protocol/Swift | InheritingP | [[InheritingP_USR:.*]] | Def
|
||||||
|
// FIXME: Should only override InheritingP.foo()
|
||||||
|
func foo() {} // CHECK: [[@LINE]]:8 | instance-method/Swift | foo() | [[InheritingP_ext_foo_USR:.*]] | Def,Dyn,RelChild,RelOver | rel: 3
|
||||||
|
// CHECK-NEXT: RelOver | instance-method/Swift | foo() | [[InheritingP_foo_USR]]
|
||||||
|
// CHECK-NEXT: RelOver | instance-method/Swift | foo() | [[P1_foo_USR]]
|
||||||
|
// CHECK-NEXT: RelChild | extension/ext-protocol/Swift | InheritingP | [[InheritingP_USR]]
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user