[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:
Xi Ge
2016-03-30 14:19:06 -07:00
parent c10a818d12
commit 37f5a0390a
10 changed files with 750 additions and 587 deletions

View File

@@ -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;
}