mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[SourceKit] DocInfo: Add a new entry to indicate the default implementation of a protocol member in its extensions. rdar://25032869
This commit is contained in:
@@ -58,21 +58,29 @@ struct TextRange {
|
||||
struct TextEntity {
|
||||
const Decl *Dcl = nullptr;
|
||||
const Decl *SynthesizeTarget = nullptr;
|
||||
const Decl *DefaultImplementationOf = nullptr;
|
||||
StringRef Argument;
|
||||
TextRange Range;
|
||||
unsigned LocOffset = 0;
|
||||
std::vector<TextEntity> SubEntities;
|
||||
|
||||
TextEntity(const Decl *D, const Decl *SynthesizeTarget, unsigned StartOffset)
|
||||
: Dcl(D), SynthesizeTarget(SynthesizeTarget), Range{StartOffset, 0} {}
|
||||
TextEntity(const Decl *D, const Decl *SynthesizeTarget,
|
||||
const Decl* DefaultImplementationOf,
|
||||
unsigned StartOffset)
|
||||
: Dcl(D), SynthesizeTarget(SynthesizeTarget),
|
||||
DefaultImplementationOf(DefaultImplementationOf), Range{StartOffset, 0} {}
|
||||
|
||||
TextEntity(const Decl *D, const Decl *SynthesizeTarget, TextRange TR,
|
||||
TextEntity(const Decl *D, const Decl *SynthesizeTarget,
|
||||
const Decl* DefaultImplementationOf, TextRange TR,
|
||||
unsigned LocOffset) : Dcl(D), SynthesizeTarget(SynthesizeTarget),
|
||||
DefaultImplementationOf(DefaultImplementationOf),
|
||||
Range(TR), LocOffset(LocOffset) {}
|
||||
|
||||
TextEntity(const Decl *D, const Decl *SynthesizeTarget, StringRef Arg,
|
||||
TextEntity(const Decl *D, const Decl *SynthesizeTarget,
|
||||
const Decl* DefaultImplementationOf, StringRef Arg,
|
||||
TextRange TR, unsigned LocOffset)
|
||||
: Dcl(D), SynthesizeTarget(SynthesizeTarget), Argument(Arg), Range(TR),
|
||||
: Dcl(D), SynthesizeTarget(SynthesizeTarget),
|
||||
DefaultImplementationOf(DefaultImplementationOf), Argument(Arg), Range(TR),
|
||||
LocOffset(LocOffset) {}
|
||||
};
|
||||
|
||||
@@ -88,6 +96,45 @@ struct TextReference {
|
||||
class AnnotatingPrinter : public StreamPrinter {
|
||||
const NominalTypeDecl *SynthesizeTarget = nullptr;
|
||||
|
||||
typedef llvm::SmallDenseMap<ValueDecl*, ValueDecl*> DefaultImplementMap;
|
||||
llvm::SmallDenseMap<ProtocolDecl*, DefaultImplementMap> AllDefaultMaps;
|
||||
DefaultImplementMap *DefaultMapToUse = nullptr;
|
||||
|
||||
void initDefaultMapToUse(const Decl *D) {
|
||||
const ExtensionDecl *ED = dyn_cast<ExtensionDecl>(D);
|
||||
if (!ED)
|
||||
return;
|
||||
if (ED->getExtendedType()) {
|
||||
if (auto NTD = ED->getExtendedType()->getAnyNominal()) {
|
||||
if (ProtocolDecl *PD = dyn_cast<ProtocolDecl>(NTD)) {
|
||||
auto Pair = AllDefaultMaps.insert({PD, DefaultImplementMap()});
|
||||
DefaultMapToUse = &Pair.first->getSecond();
|
||||
if (Pair.second) {
|
||||
swift::collectDefaultImplementationForProtocolMembers(PD,
|
||||
Pair.first->getSecond());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void deinitDefaultMapToUse(const Decl*D) {
|
||||
if (D->getKind() == DeclKind::Extension) {
|
||||
DefaultMapToUse = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
ValueDecl *getDefaultImplementation(const Decl *D) {
|
||||
if (!DefaultMapToUse)
|
||||
return nullptr;
|
||||
ValueDecl *VD = const_cast<ValueDecl*>(dyn_cast<ValueDecl>(D));
|
||||
auto Found = DefaultMapToUse->find(VD);
|
||||
if (Found != DefaultMapToUse->end()) {
|
||||
return Found->second;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
public:
|
||||
std::vector<TextEntity> TopEntities;
|
||||
std::vector<TextEntity> EntitiesStack;
|
||||
@@ -125,7 +172,7 @@ public:
|
||||
if (!shouldContinuePre(ED, Bracket))
|
||||
return;
|
||||
unsigned StartOffset = OS.tell();
|
||||
EntitiesStack.emplace_back(ED, SynthesizeTarget, StartOffset);
|
||||
EntitiesStack.emplace_back(ED, SynthesizeTarget, nullptr, StartOffset);
|
||||
}
|
||||
|
||||
void printSynthesizedExtensionPost(const ExtensionDecl *ED,
|
||||
@@ -151,7 +198,9 @@ public:
|
||||
if (!shouldContinuePre(D, Bracket))
|
||||
return;
|
||||
unsigned StartOffset = OS.tell();
|
||||
EntitiesStack.emplace_back(D, SynthesizeTarget, StartOffset);
|
||||
initDefaultMapToUse(D);
|
||||
EntitiesStack.emplace_back(D, SynthesizeTarget, getDefaultImplementation(D),
|
||||
StartOffset);
|
||||
}
|
||||
|
||||
void printDeclLoc(const Decl *D) override {
|
||||
@@ -175,6 +224,7 @@ public:
|
||||
TopEntities.push_back(std::move(Entity));
|
||||
else
|
||||
EntitiesStack.back().SubEntities.push_back(std::move(Entity));
|
||||
deinitDefaultMapToUse(D);
|
||||
}
|
||||
|
||||
void printTypeRef(Type T, const TypeDecl *TD, Identifier Name) override {
|
||||
@@ -227,6 +277,7 @@ static void initDocGenericParams(const Decl *D, DocEntityInfo &Info) {
|
||||
}
|
||||
|
||||
static bool initDocEntityInfo(const Decl *D, const Decl *SynthesizedTarget,
|
||||
const Decl *DefaultImplementationOf,
|
||||
bool IsRef, DocEntityInfo &Info,
|
||||
StringRef Arg = StringRef()) {
|
||||
if (!D || isa<ParamDecl>(D) ||
|
||||
@@ -265,6 +316,11 @@ static bool initDocEntityInfo(const Decl *D, const Decl *SynthesizedTarget,
|
||||
}
|
||||
}
|
||||
|
||||
if (DefaultImplementationOf) {
|
||||
llvm::raw_svector_ostream OS(Info.ProvideImplementationOfUSR);
|
||||
SwiftLangSupport::printUSR((ValueDecl*)DefaultImplementationOf, OS);
|
||||
}
|
||||
|
||||
Info.IsUnavailable = AvailableAttr::isUnavailable(D);
|
||||
Info.IsDeprecated = D->getAttrs().getDeprecated(D->getASTContext()) != nullptr;
|
||||
|
||||
@@ -286,6 +342,7 @@ static bool initDocEntityInfo(const Decl *D, const Decl *SynthesizedTarget,
|
||||
static bool initDocEntityInfo(const TextEntity &Entity,
|
||||
DocEntityInfo &Info) {
|
||||
if (initDocEntityInfo(Entity.Dcl, Entity.SynthesizeTarget,
|
||||
Entity.DefaultImplementationOf,
|
||||
/*IsRef=*/false, Info, Entity.Argument))
|
||||
return true;
|
||||
Info.Offset = Entity.Range.Offset;
|
||||
@@ -301,13 +358,13 @@ static const TypeDecl *getTypeDeclFromType(Type Ty) {
|
||||
|
||||
static void passInherits(const ValueDecl *D, DocInfoConsumer &Consumer) {
|
||||
DocEntityInfo EntInfo;
|
||||
if (initDocEntityInfo(D, nullptr, /*IsRef=*/true, EntInfo))
|
||||
if (initDocEntityInfo(D, nullptr, nullptr, /*IsRef=*/true, EntInfo))
|
||||
return;
|
||||
Consumer.handleInheritsEntity(EntInfo);
|
||||
}
|
||||
static void passConforms(const ValueDecl *D, DocInfoConsumer &Consumer) {
|
||||
DocEntityInfo EntInfo;
|
||||
if (initDocEntityInfo(D, nullptr, /*IsRef=*/true, EntInfo))
|
||||
if (initDocEntityInfo(D, nullptr, nullptr, /*IsRef=*/true, EntInfo))
|
||||
return;
|
||||
Consumer.handleConformsToEntity(EntInfo);
|
||||
}
|
||||
@@ -343,7 +400,7 @@ static void passConforms(ArrayRef<ValueDecl *> Dcls,
|
||||
}
|
||||
static void passExtends(const ValueDecl *D, DocInfoConsumer &Consumer) {
|
||||
DocEntityInfo EntInfo;
|
||||
if (initDocEntityInfo(D, nullptr, /*IsRef=*/true, EntInfo))
|
||||
if (initDocEntityInfo(D, nullptr, nullptr, /*IsRef=*/true, EntInfo))
|
||||
return;
|
||||
Consumer.handleExtendsEntity(EntInfo);
|
||||
}
|
||||
@@ -550,7 +607,7 @@ private:
|
||||
const TextReference &Ref = References.front();
|
||||
References = References.slice(1);
|
||||
DocEntityInfo Info;
|
||||
if (initDocEntityInfo(Ref.Dcl, nullptr, /*IsRef=*/true, Info))
|
||||
if (initDocEntityInfo(Ref.Dcl, nullptr, nullptr, /*IsRef=*/true, Info))
|
||||
continue;
|
||||
Info.Offset = Ref.Range.Offset;
|
||||
Info.Length = Ref.Range.Length;
|
||||
@@ -614,7 +671,7 @@ static void addParameters(ArrayRef<Identifier> &ArgNames,
|
||||
SM.getLocOffsetInBuffer(Lexer::getLocForEndOfToken(SM, TypeRange.End),
|
||||
BufferID);
|
||||
TextRange TR{ StartOffs, EndOffs-StartOffs };
|
||||
TextEntity Param(param, nullptr, Arg, TR, StartOffs);
|
||||
TextEntity Param(param, nullptr, nullptr, Arg, TR, StartOffs);
|
||||
Ent.SubEntities.push_back(std::move(Param));
|
||||
}
|
||||
}
|
||||
@@ -808,7 +865,7 @@ public:
|
||||
return true;
|
||||
TextRange TR = getTextRange(D->getSourceRange());
|
||||
unsigned LocOffset = getOffset(Range.getStart());
|
||||
EntitiesStack.emplace_back(D, nullptr, TR, LocOffset);
|
||||
EntitiesStack.emplace_back(D, nullptr, nullptr, TR, LocOffset);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user