19
19
#include " swift/AST/Expr.h"
20
20
#include " swift/AST/Module.h"
21
21
#include " swift/AST/ParameterList.h"
22
+ #include " swift/AST/ProtocolConformance.h"
22
23
#include " swift/AST/Types.h"
23
24
#include " swift/AST/USRGeneration.h"
24
25
#include " swift/Basic/SourceManager.h"
@@ -78,6 +79,13 @@ static bool isMemberwiseInit(swift::ValueDecl *D) {
78
79
return false ;
79
80
}
80
81
82
+ static SourceLoc getLocForExtension (ExtensionDecl *D) {
83
+ // Use the 'End' token of the range, in case it is a compound name, e.g.
84
+ // extension A.B {}
85
+ // we want the location of 'B' token.
86
+ return D->getExtendedTypeLoc ().getSourceRange ().End ;
87
+ }
88
+
81
89
namespace {
82
90
// Adapter providing a common interface for a SourceFile/Module.
83
91
class SourceFileOrModule {
@@ -121,6 +129,11 @@ class SourceFileOrModule {
121
129
}
122
130
};
123
131
132
+ struct ValueWitness {
133
+ ValueDecl *Member;
134
+ ValueDecl *Requirement;
135
+ };
136
+
124
137
class IndexSwiftASTWalker : public SourceEntityWalker {
125
138
IndexDataConsumer &IdxConsumer;
126
139
SourceManager &SrcMgr;
@@ -133,6 +146,7 @@ class IndexSwiftASTWalker : public SourceEntityWalker {
133
146
Decl *D;
134
147
SymbolInfo SymInfo;
135
148
SymbolRoleSet Roles;
149
+ SmallVector<ValueWitness, 6 > ExplicitValueWitnesses;
136
150
SmallVector<SourceLoc, 6 > RefsToSuppress;
137
151
};
138
152
SmallVector<Entity, 6 > EntitiesStack;
@@ -319,7 +333,7 @@ class IndexSwiftASTWalker : public SourceEntityWalker {
319
333
IndexSymbol Info;
320
334
if (initIndexSymbol (Prop, *LabelIt++, /* IsRef=*/ true , Info))
321
335
continue ;
322
- if (startEntity (Prop, Info))
336
+ if (startEntity (Prop, Info, /* IsRef= */ true ))
323
337
finishCurrentEntity ();
324
338
}
325
339
}
@@ -398,8 +412,10 @@ class IndexSwiftASTWalker : public SourceEntityWalker {
398
412
bool reportExtension (ExtensionDecl *D);
399
413
bool reportRef (ValueDecl *D, SourceLoc Loc, IndexSymbol &Info,
400
414
Optional<AccessKind> AccKind);
415
+ bool reportImplicitValueConformance (ValueDecl *witness, ValueDecl *requirement,
416
+ Decl *container);
401
417
402
- bool startEntity (Decl *D, IndexSymbol &Info);
418
+ bool startEntity (Decl *D, IndexSymbol &Info, bool IsRef );
403
419
bool startEntityDecl (ValueDecl *D);
404
420
405
421
bool reportRelatedRef (ValueDecl *D, SourceLoc Loc, bool isImplicit, SymbolRoleSet Relations, Decl *Related);
@@ -459,6 +475,14 @@ class IndexSwiftASTWalker : public SourceEntityWalker {
459
475
return true ;
460
476
}
461
477
478
+ // / Reports all implicit member value decl conformances that \p D introduces
479
+ // / as implicit overrides at the source location of \p D, and returns the
480
+ // / explicit ones so we can check against them later on when visiting them as
481
+ // / members.
482
+ // /
483
+ // / \returns false if AST visitation should stop.
484
+ bool handleValueWitnesses (Decl *D, SmallVectorImpl<ValueWitness> &explicitValueWitnesses);
485
+
462
486
void getModuleHash (SourceFileOrModule SFOrMod, llvm::raw_ostream &OS);
463
487
llvm::hash_code hashModule (llvm::hash_code code, SourceFileOrModule SFOrMod);
464
488
llvm::hash_code hashFileReference (llvm::hash_code code,
@@ -612,16 +636,53 @@ bool IndexSwiftASTWalker::visitImports(
612
636
return true ;
613
637
}
614
638
615
- bool IndexSwiftASTWalker::startEntity (Decl *D, IndexSymbol &Info) {
639
+ bool IndexSwiftASTWalker::handleValueWitnesses (Decl *D, SmallVectorImpl<ValueWitness> &explicitValueWitnesses) {
640
+ auto DC = dyn_cast<DeclContext>(D);
641
+ if (!DC)
642
+ return true ;
643
+
644
+ for (auto *conf : DC->getLocalConformances ()) {
645
+ if (conf->isInvalid ())
646
+ continue ;
647
+
648
+ auto normal = conf->getRootNormalConformance ();
649
+ normal->forEachValueWitness (nullptr ,
650
+ [&](ValueDecl *req, Witness witness) {
651
+ if (Cancelled)
652
+ return ;
653
+
654
+ auto *decl = witness.getDecl ();
655
+ if (decl->getDeclContext () == DC) {
656
+ explicitValueWitnesses.push_back (ValueWitness{decl, req});
657
+ } else {
658
+ // Report the implicit conformance.
659
+ reportImplicitValueConformance (decl, req, D);
660
+ }
661
+ });
662
+ }
663
+
664
+ if (Cancelled)
665
+ return false ;
666
+
667
+ return true ;
668
+ }
669
+
670
+ bool IndexSwiftASTWalker::startEntity (Decl *D, IndexSymbol &Info, bool IsRef) {
616
671
switch (IdxConsumer.startSourceEntity (Info)) {
617
672
case swift::index::IndexDataConsumer::Abort:
618
673
Cancelled = true ;
619
674
LLVM_FALLTHROUGH;
620
675
case swift::index::IndexDataConsumer::Skip:
621
676
return false ;
622
- case swift::index::IndexDataConsumer::Continue:
623
- EntitiesStack.push_back ({D, Info.symInfo , Info.roles , {}});
677
+ case swift::index::IndexDataConsumer::Continue: {
678
+ SmallVector<ValueWitness, 6 > explicitValueWitnesses;
679
+ if (!IsRef) {
680
+ if (!handleValueWitnesses (D, explicitValueWitnesses))
681
+ return false ;
682
+ }
683
+ EntitiesStack.push_back ({D, Info.symInfo , Info.roles , std::move (explicitValueWitnesses), {}});
624
684
return true ;
685
+ }
625
686
}
626
687
627
688
llvm_unreachable (" Unhandled IndexDataConsumer in switch." );
@@ -649,12 +710,15 @@ bool IndexSwiftASTWalker::startEntityDecl(ValueDecl *D) {
649
710
return false ;
650
711
}
651
712
652
- for (auto Overriden: getOverriddenDecls (D, /* IncludeProtocolReqs=*/ !isSystemModule)) {
653
- if (addRelation (Info, (SymbolRoleSet) SymbolRole::RelationOverrideOf, Overriden))
654
- return false ;
713
+ for (auto Overriden: getOverriddenDecls (D, /* IncludeProtocolReqs=*/ false )) {
714
+ addRelation (Info, (SymbolRoleSet) SymbolRole::RelationOverrideOf, Overriden);
655
715
}
656
716
657
717
if (auto Parent = getParentDecl ()) {
718
+ for (const ValueWitness &witness : EntitiesStack.back ().ExplicitValueWitnesses ) {
719
+ if (witness.Member == D)
720
+ addRelation (Info, (SymbolRoleSet) SymbolRole::RelationOverrideOf, witness.Requirement );
721
+ }
658
722
if (auto ParentVD = dyn_cast<ValueDecl>(Parent)) {
659
723
SymbolRoleSet RelationsToParent = (SymbolRoleSet)SymbolRole::RelationChildOf;
660
724
if (Info.symInfo .SubKind == SymbolSubKind::AccessorGetter ||
@@ -673,7 +737,7 @@ bool IndexSwiftASTWalker::startEntityDecl(ValueDecl *D) {
673
737
}
674
738
}
675
739
676
- return startEntity (D, Info);
740
+ return startEntity (D, Info, /* IsRef= */ false );
677
741
}
678
742
679
743
bool IndexSwiftASTWalker::reportRelatedRef (ValueDecl *D, SourceLoc Loc, bool isImplicit,
@@ -836,10 +900,7 @@ IndexSwiftASTWalker::getTypeLocAsNominalTypeDecl(const TypeLoc &Ty) {
836
900
}
837
901
838
902
bool IndexSwiftASTWalker::reportExtension (ExtensionDecl *D) {
839
- // Use the 'End' token of the range, in case it is a compound name, e.g.
840
- // extension A.B {}
841
- // we want the location of 'B' token.
842
- SourceLoc Loc = D->getExtendedTypeLoc ().getSourceRange ().End ;
903
+ SourceLoc Loc = getLocForExtension (D);
843
904
NominalTypeDecl *NTD = D->getExtendedNominal ();
844
905
if (!NTD)
845
906
return true ;
@@ -850,7 +911,7 @@ bool IndexSwiftASTWalker::reportExtension(ExtensionDecl *D) {
850
911
if (initIndexSymbol (D, NTD, Loc, Info))
851
912
return true ;
852
913
853
- if (!startEntity (D, Info))
914
+ if (!startEntity (D, Info, /* IsRef= */ false ))
854
915
return false ;
855
916
856
917
if (!reportRelatedRef (NTD, Loc, /* isImplicit=*/ false ,
@@ -940,7 +1001,7 @@ bool IndexSwiftASTWalker::reportRef(ValueDecl *D, SourceLoc Loc,
940
1001
if (isSystemModule && !hasUsefulRoleInSystemModule (Info.roles ))
941
1002
return true ;
942
1003
943
- if (!startEntity (D, Info))
1004
+ if (!startEntity (D, Info, /* IsRef= */ true ))
944
1005
return true ;
945
1006
946
1007
// Report the accessors that were utilized.
@@ -961,6 +1022,34 @@ bool IndexSwiftASTWalker::reportRef(ValueDecl *D, SourceLoc Loc,
961
1022
return finishCurrentEntity ();
962
1023
}
963
1024
1025
+ bool IndexSwiftASTWalker::reportImplicitValueConformance (ValueDecl *witness, ValueDecl *requirement,
1026
+ Decl *container) {
1027
+ if (!shouldIndex (witness, /* IsRef=*/ true ))
1028
+ return true ; // keep walking
1029
+
1030
+ SourceLoc loc;
1031
+ if (auto *extD = dyn_cast<ExtensionDecl>(container))
1032
+ loc = getLocForExtension (extD);
1033
+ else
1034
+ loc = container->getLoc ();
1035
+
1036
+ IndexSymbol info;
1037
+ if (initIndexSymbol (witness, loc, /* IsRef=*/ true , info))
1038
+ return true ;
1039
+ if (addRelation (info, (SymbolRoleSet) SymbolRole::RelationOverrideOf, requirement))
1040
+ return true ;
1041
+ if (addRelation (info, (SymbolRoleSet) SymbolRole::RelationContainedBy, container))
1042
+ return true ;
1043
+ // Remove the 'ref' role that \c initIndexSymbol introduces. This isn't
1044
+ // actually a 'reference', but an 'implicit' override.
1045
+ info.roles &= ~(SymbolRoleSet)SymbolRole::Reference;
1046
+ info.roles |= (SymbolRoleSet)SymbolRole::Implicit;
1047
+
1048
+ if (!startEntity (witness, info, /* IsRef=*/ true ))
1049
+ return true ;
1050
+ return finishCurrentEntity ();
1051
+ }
1052
+
964
1053
bool IndexSwiftASTWalker::initIndexSymbol (ValueDecl *D, SourceLoc Loc,
965
1054
bool IsRef, IndexSymbol &Info) {
966
1055
assert (D);
0 commit comments