mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[IDE] Teach type checker about conditional conformance extensions.
Before conditional conformances, the archetypes in conformance extensions (i.e. extension Foo: SomeProtocol) were equivalent to those in the type decl, with the same protocol bounds and so on. The code for printing "synthesized" members relied on this fact. This commit teaches that code to deal with archetypes in the conditional conformance extension when required. Fixes rdar://problem/36553066 and SR-6930.
This commit is contained in:
@@ -174,10 +174,6 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
class SILLayout; // From SIL
|
class SILLayout; // From SIL
|
||||||
/// \brief Describes either a nominal type declaration or an extension
|
|
||||||
/// declaration.
|
|
||||||
typedef llvm::PointerUnion<NominalTypeDecl *, ExtensionDecl *>
|
|
||||||
TypeOrExtensionDecl;
|
|
||||||
|
|
||||||
/// ASTContext - This object creates and owns the AST objects.
|
/// ASTContext - This object creates and owns the AST objects.
|
||||||
/// However, this class does more than just maintain context within an AST.
|
/// However, this class does more than just maintain context within an AST.
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ enum class PrintStructureKind {
|
|||||||
class ASTPrinter {
|
class ASTPrinter {
|
||||||
unsigned CurrentIndentation = 0;
|
unsigned CurrentIndentation = 0;
|
||||||
unsigned PendingNewlines = 0;
|
unsigned PendingNewlines = 0;
|
||||||
const NominalTypeDecl *SynthesizeTarget = nullptr;
|
TypeOrExtensionDecl SynthesizeTarget;
|
||||||
|
|
||||||
void printTextImpl(StringRef Text);
|
void printTextImpl(StringRef Text);
|
||||||
|
|
||||||
@@ -136,13 +136,14 @@ public:
|
|||||||
|
|
||||||
/// Called before printing a synthesized extension.
|
/// Called before printing a synthesized extension.
|
||||||
virtual void printSynthesizedExtensionPre(const ExtensionDecl *ED,
|
virtual void printSynthesizedExtensionPre(const ExtensionDecl *ED,
|
||||||
const NominalTypeDecl *NTD,
|
TypeOrExtensionDecl NTD,
|
||||||
Optional<BracketOptions> Bracket) {}
|
Optional<BracketOptions> Bracket) {}
|
||||||
|
|
||||||
/// Called after printing a synthesized extension.
|
/// Called after printing a synthesized extension.
|
||||||
virtual void printSynthesizedExtensionPost(const ExtensionDecl *ED,
|
virtual void printSynthesizedExtensionPost(const ExtensionDecl *ED,
|
||||||
const NominalTypeDecl *NTD,
|
TypeOrExtensionDecl TargetDecl,
|
||||||
Optional<BracketOptions> Bracket) {}
|
Optional<BracketOptions> Bracket) {
|
||||||
|
}
|
||||||
|
|
||||||
/// Called before printing a structured entity.
|
/// Called before printing a structured entity.
|
||||||
///
|
///
|
||||||
@@ -213,7 +214,7 @@ public:
|
|||||||
CurrentIndentation = NumSpaces;
|
CurrentIndentation = NumSpaces;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setSynthesizedTarget(NominalTypeDecl *Target) {
|
void setSynthesizedTarget(TypeOrExtensionDecl Target) {
|
||||||
assert((!SynthesizeTarget || !Target || Target == SynthesizeTarget) &&
|
assert((!SynthesizeTarget || !Target || Target == SynthesizeTarget) &&
|
||||||
"unexpected change of setSynthesizedTarget");
|
"unexpected change of setSynthesizedTarget");
|
||||||
// FIXME: this can overwrite the original target with nullptr.
|
// FIXME: this can overwrite the original target with nullptr.
|
||||||
|
|||||||
@@ -36,16 +36,45 @@ enum DeclAttrKind : unsigned;
|
|||||||
class SynthesizedExtensionAnalyzer;
|
class SynthesizedExtensionAnalyzer;
|
||||||
struct PrintOptions;
|
struct PrintOptions;
|
||||||
|
|
||||||
|
/// \brief Describes either a nominal type declaration or an extension
|
||||||
|
/// declaration.
|
||||||
|
struct TypeOrExtensionDecl {
|
||||||
|
llvm::PointerUnion<NominalTypeDecl *, ExtensionDecl *> Decl;
|
||||||
|
|
||||||
|
TypeOrExtensionDecl() = default;
|
||||||
|
|
||||||
|
TypeOrExtensionDecl(NominalTypeDecl *D);
|
||||||
|
TypeOrExtensionDecl(ExtensionDecl *D);
|
||||||
|
|
||||||
|
/// \brief Return the contained *Decl as the Decl superclass.
|
||||||
|
class Decl *getAsDecl() const;
|
||||||
|
/// \brief Return the contained *Decl as the DeclContext superclass.
|
||||||
|
DeclContext *getAsDeclContext() const;
|
||||||
|
/// \brief Return the contained NominalTypeDecl or that of the extended type
|
||||||
|
/// in the ExtensionDecl.
|
||||||
|
NominalTypeDecl *getBaseNominal() const;
|
||||||
|
|
||||||
|
/// \brief Is the contained pointer null?
|
||||||
|
bool isNull() const;
|
||||||
|
explicit operator bool() const { return !isNull(); }
|
||||||
|
|
||||||
|
bool operator==(TypeOrExtensionDecl rhs) { return Decl == rhs.Decl; }
|
||||||
|
bool operator!=(TypeOrExtensionDecl rhs) { return Decl != rhs.Decl; }
|
||||||
|
bool operator<(TypeOrExtensionDecl rhs) { return Decl < rhs.Decl; }
|
||||||
|
};
|
||||||
|
|
||||||
/// Necessary information for archetype transformation during printing.
|
/// Necessary information for archetype transformation during printing.
|
||||||
struct TypeTransformContext {
|
struct TypeTransformContext {
|
||||||
TypeBase *BaseType;
|
TypeBase *BaseType;
|
||||||
NominalTypeDecl *Nominal = nullptr;
|
TypeOrExtensionDecl Decl;
|
||||||
|
|
||||||
explicit TypeTransformContext(Type T);
|
explicit TypeTransformContext(Type T);
|
||||||
explicit TypeTransformContext(NominalTypeDecl* NTD);
|
explicit TypeTransformContext(TypeOrExtensionDecl D);
|
||||||
|
|
||||||
Type getBaseType() const;
|
Type getBaseType() const;
|
||||||
NominalTypeDecl *getNominal() const;
|
TypeOrExtensionDecl getDecl() const;
|
||||||
|
|
||||||
|
DeclContext *getDeclContext() const;
|
||||||
|
|
||||||
bool isPrintingSynthesizedExtension() const;
|
bool isPrintingSynthesizedExtension() const;
|
||||||
};
|
};
|
||||||
@@ -421,7 +450,7 @@ struct PrintOptions {
|
|||||||
|
|
||||||
void setBaseType(Type T);
|
void setBaseType(Type T);
|
||||||
|
|
||||||
void initForSynthesizedExtension(NominalTypeDecl *D);
|
void initForSynthesizedExtension(TypeOrExtensionDecl D);
|
||||||
|
|
||||||
void clearSynthesizedExtension();
|
void clearSynthesizedExtension();
|
||||||
|
|
||||||
|
|||||||
@@ -137,10 +137,18 @@ namespace swift {
|
|||||||
/// Creates a lazy type resolver for use in lookups.
|
/// Creates a lazy type resolver for use in lookups.
|
||||||
OwnedResolver createLazyResolver(ASTContext &Ctx);
|
OwnedResolver createLazyResolver(ASTContext &Ctx);
|
||||||
|
|
||||||
typedef std::pair<ExtensionDecl*, bool> ExtensionAndIsSynthesized;
|
struct ExtensionInfo {
|
||||||
|
// The extension with the declarations to apply.
|
||||||
|
ExtensionDecl *Ext;
|
||||||
|
// The extension that enables the former to apply, if any (i.e. a
|
||||||
|
// conditional
|
||||||
|
// conformance to Foo enables 'extension Foo').
|
||||||
|
ExtensionDecl *EnablingExt;
|
||||||
|
bool IsSynthesized;
|
||||||
|
};
|
||||||
|
|
||||||
typedef llvm::function_ref<void(ArrayRef<ExtensionAndIsSynthesized>)>
|
typedef llvm::function_ref<void(ArrayRef<ExtensionInfo>)>
|
||||||
ExtensionGroupOperation;
|
ExtensionGroupOperation;
|
||||||
|
|
||||||
class SynthesizedExtensionAnalyzer {
|
class SynthesizedExtensionAnalyzer {
|
||||||
struct Implementation;
|
struct Implementation;
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ void PrintOptions::setBaseType(Type T) {
|
|||||||
TransformContext = TypeTransformContext(T);
|
TransformContext = TypeTransformContext(T);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrintOptions::initForSynthesizedExtension(NominalTypeDecl *D) {
|
void PrintOptions::initForSynthesizedExtension(TypeOrExtensionDecl D) {
|
||||||
TransformContext = TypeTransformContext(D);
|
TransformContext = TypeTransformContext(D);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,16 +63,40 @@ void PrintOptions::clearSynthesizedExtension() {
|
|||||||
TransformContext.reset();
|
TransformContext.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TypeOrExtensionDecl::TypeOrExtensionDecl(NominalTypeDecl *D) : Decl(D) {}
|
||||||
|
TypeOrExtensionDecl::TypeOrExtensionDecl(ExtensionDecl *D) : Decl(D) {}
|
||||||
|
|
||||||
|
Decl *TypeOrExtensionDecl::getAsDecl() const {
|
||||||
|
if (auto NTD = Decl.dyn_cast<NominalTypeDecl *>())
|
||||||
|
return NTD;
|
||||||
|
|
||||||
|
return Decl.get<ExtensionDecl *>();
|
||||||
|
}
|
||||||
|
DeclContext *TypeOrExtensionDecl::getAsDeclContext() const {
|
||||||
|
return getAsDecl()->getInnermostDeclContext();
|
||||||
|
}
|
||||||
|
NominalTypeDecl *TypeOrExtensionDecl::getBaseNominal() const {
|
||||||
|
return getAsDeclContext()->getAsNominalTypeOrNominalTypeExtensionContext();
|
||||||
|
}
|
||||||
|
bool TypeOrExtensionDecl::isNull() const { return Decl.isNull(); }
|
||||||
|
|
||||||
TypeTransformContext::TypeTransformContext(Type T)
|
TypeTransformContext::TypeTransformContext(Type T)
|
||||||
: BaseType(T.getPointer()) {
|
: BaseType(T.getPointer()) {
|
||||||
assert(T->mayHaveMembers());
|
assert(T->mayHaveMembers());
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeTransformContext::TypeTransformContext(NominalTypeDecl *NTD)
|
TypeTransformContext::TypeTransformContext(TypeOrExtensionDecl D)
|
||||||
: BaseType(NTD->getDeclaredTypeInContext().getPointer()), Nominal(NTD) {}
|
: BaseType(nullptr), Decl(D) {
|
||||||
|
if (auto NTD = Decl.Decl.dyn_cast<NominalTypeDecl *>())
|
||||||
|
BaseType = NTD->getDeclaredTypeInContext().getPointer();
|
||||||
|
else
|
||||||
|
BaseType = Decl.Decl.get<ExtensionDecl *>()->getExtendedType().getPointer();
|
||||||
|
}
|
||||||
|
|
||||||
NominalTypeDecl *TypeTransformContext::getNominal() const {
|
TypeOrExtensionDecl TypeTransformContext::getDecl() const { return Decl; }
|
||||||
return Nominal;
|
|
||||||
|
DeclContext *TypeTransformContext::getDeclContext() const {
|
||||||
|
return Decl.getAsDecl()->getDeclContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
Type TypeTransformContext::getBaseType() const {
|
Type TypeTransformContext::getBaseType() const {
|
||||||
@@ -80,7 +104,7 @@ Type TypeTransformContext::getBaseType() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool TypeTransformContext::isPrintingSynthesizedExtension() const {
|
bool TypeTransformContext::isPrintingSynthesizedExtension() const {
|
||||||
return Nominal != nullptr;
|
return !Decl.isNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ASTPrinter::sanitizeUtf8(StringRef Text) {
|
std::string ASTPrinter::sanitizeUtf8(StringRef Text) {
|
||||||
@@ -631,8 +655,7 @@ private:
|
|||||||
#define STMT(Name, Parent) void visit##Name##Stmt(Name##Stmt *stmt);
|
#define STMT(Name, Parent) void visit##Name##Stmt(Name##Stmt *stmt);
|
||||||
#include "swift/AST/StmtNodes.def"
|
#include "swift/AST/StmtNodes.def"
|
||||||
|
|
||||||
void printSynthesizedExtension(NominalTypeDecl* Decl,
|
void printSynthesizedExtension(Type ExtendedType, ExtensionDecl *ExtDecl);
|
||||||
ExtensionDecl* ExtDecl);
|
|
||||||
|
|
||||||
void printExtension(ExtensionDecl* ExtDecl);
|
void printExtension(ExtensionDecl* ExtDecl);
|
||||||
|
|
||||||
@@ -668,8 +691,9 @@ public:
|
|||||||
Options.TransformContext &&
|
Options.TransformContext &&
|
||||||
Options.TransformContext->isPrintingSynthesizedExtension() &&
|
Options.TransformContext->isPrintingSynthesizedExtension() &&
|
||||||
isa<ExtensionDecl>(D);
|
isa<ExtensionDecl>(D);
|
||||||
if (Synthesize)
|
if (Synthesize) {
|
||||||
Printer.setSynthesizedTarget(Options.TransformContext->getNominal());
|
Printer.setSynthesizedTarget(Options.TransformContext->getDecl());
|
||||||
|
}
|
||||||
|
|
||||||
// We want to print a newline before doc comments. Swift code already
|
// We want to print a newline before doc comments. Swift code already
|
||||||
// handles this, but we need to insert it for clang doc comments when not
|
// handles this, but we need to insert it for clang doc comments when not
|
||||||
@@ -692,10 +716,10 @@ public:
|
|||||||
ASTVisitor::visit(D);
|
ASTVisitor::visit(D);
|
||||||
|
|
||||||
if (Synthesize) {
|
if (Synthesize) {
|
||||||
Printer.setSynthesizedTarget(nullptr);
|
Printer.setSynthesizedTarget({});
|
||||||
Printer.printSynthesizedExtensionPost(
|
Printer.printSynthesizedExtensionPost(cast<ExtensionDecl>(D),
|
||||||
cast<ExtensionDecl>(D), Options.TransformContext->getNominal(),
|
Options.TransformContext->getDecl(),
|
||||||
Options.BracketOptions);
|
Options.BracketOptions);
|
||||||
} else {
|
} else {
|
||||||
Printer.callPrintDeclPost(D, Options.BracketOptions);
|
Printer.callPrintDeclPost(D, Options.BracketOptions);
|
||||||
}
|
}
|
||||||
@@ -1775,14 +1799,14 @@ static void printExtendedTypeName(Type ExtendedType, ASTPrinter &Printer,
|
|||||||
Printer.printTypeRef(ExtendedType, Nominal, Nominal->getName());
|
Printer.printTypeRef(ExtendedType, Nominal, Nominal->getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrintAST::
|
void PrintAST::printSynthesizedExtension(Type ExtendedType,
|
||||||
printSynthesizedExtension(NominalTypeDecl* Decl, ExtensionDecl *ExtDecl) {
|
ExtensionDecl *ExtDecl) {
|
||||||
if (Options.BracketOptions.shouldOpenExtension(ExtDecl)) {
|
if (Options.BracketOptions.shouldOpenExtension(ExtDecl)) {
|
||||||
printDocumentationComment(ExtDecl);
|
printDocumentationComment(ExtDecl);
|
||||||
printAttributes(ExtDecl);
|
printAttributes(ExtDecl);
|
||||||
Printer << tok::kw_extension << " ";
|
Printer << tok::kw_extension << " ";
|
||||||
|
|
||||||
printExtendedTypeName(Decl->getDeclaredType(), Printer, Options);
|
printExtendedTypeName(ExtendedType, Printer, Options);
|
||||||
printInherited(ExtDecl);
|
printInherited(ExtDecl);
|
||||||
|
|
||||||
if (ExtDecl->getGenericParams())
|
if (ExtDecl->getGenericParams())
|
||||||
@@ -1832,9 +1856,11 @@ void PrintAST::printExtension(ExtensionDecl *decl) {
|
|||||||
|
|
||||||
void PrintAST::visitExtensionDecl(ExtensionDecl *decl) {
|
void PrintAST::visitExtensionDecl(ExtensionDecl *decl) {
|
||||||
if (Options.TransformContext &&
|
if (Options.TransformContext &&
|
||||||
Options.TransformContext->isPrintingSynthesizedExtension())
|
Options.TransformContext->isPrintingSynthesizedExtension()) {
|
||||||
printSynthesizedExtension(Options.TransformContext->getNominal(), decl);
|
auto extendedType =
|
||||||
else
|
Options.TransformContext->getBaseType()->mapTypeOutOfContext();
|
||||||
|
printSynthesizedExtension(extendedType, decl);
|
||||||
|
} else
|
||||||
printExtension(decl);
|
printExtension(decl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,14 +31,13 @@ static bool shouldPrintAsFavorable(const Decl *D, PrintOptions &Options) {
|
|||||||
!D->getDeclContext()->isExtensionContext() ||
|
!D->getDeclContext()->isExtensionContext() ||
|
||||||
!Options.TransformContext->isPrintingSynthesizedExtension())
|
!Options.TransformContext->isPrintingSynthesizedExtension())
|
||||||
return true;
|
return true;
|
||||||
NominalTypeDecl *Target = Options.TransformContext->getNominal();
|
auto DC = Options.TransformContext->getDeclContext();
|
||||||
Type BaseTy = Target->getDeclaredTypeInContext();
|
auto BaseTy = Options.TransformContext->getBaseType();
|
||||||
const auto *FD = dyn_cast<FuncDecl>(D);
|
const auto *FD = dyn_cast<FuncDecl>(D);
|
||||||
if (!FD)
|
if (!FD)
|
||||||
return true;
|
return true;
|
||||||
ResolvedMemberResult Result =
|
ResolvedMemberResult Result =
|
||||||
resolveValueMember(*Target->getDeclContext(), BaseTy,
|
resolveValueMember(*DC, BaseTy, FD->getEffectiveFullName());
|
||||||
FD->getEffectiveFullName());
|
|
||||||
return !(Result.hasBestOverload() && Result.getBestOverload() != D);
|
return !(Result.hasBestOverload() && Result.getBestOverload() != D);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,9 +121,11 @@ struct SynthesizedExtensionAnalyzer::Implementation {
|
|||||||
struct SynthesizedExtensionInfo {
|
struct SynthesizedExtensionInfo {
|
||||||
ExtensionDecl *Ext = nullptr;
|
ExtensionDecl *Ext = nullptr;
|
||||||
bool IsSynthesized;
|
bool IsSynthesized;
|
||||||
|
ExtensionDecl *EnablingExt = nullptr;
|
||||||
operator bool() const { return Ext; }
|
operator bool() const { return Ext; }
|
||||||
SynthesizedExtensionInfo(bool IsSynthesized = true) :
|
SynthesizedExtensionInfo(bool IsSynthesized = false,
|
||||||
IsSynthesized(IsSynthesized) {}
|
ExtensionDecl *EnablingExt = nullptr)
|
||||||
|
: IsSynthesized(IsSynthesized), EnablingExt(EnablingExt) {}
|
||||||
bool operator< (const SynthesizedExtensionInfo& Rhs) const {
|
bool operator< (const SynthesizedExtensionInfo& Rhs) const {
|
||||||
|
|
||||||
// Synthesized are always after actual ones.
|
// Synthesized are always after actual ones.
|
||||||
@@ -146,6 +147,7 @@ struct SynthesizedExtensionAnalyzer::Implementation {
|
|||||||
return LeftOrder.getValue() < RightOrder.getValue();
|
return LeftOrder.getValue() < RightOrder.getValue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -269,62 +271,65 @@ struct SynthesizedExtensionAnalyzer::Implementation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::pair<SynthesizedExtensionInfo, ExtensionMergeInfo>
|
std::pair<SynthesizedExtensionInfo, ExtensionMergeInfo>
|
||||||
isApplicable(ExtensionDecl *Ext, bool IsSynthesized) {
|
isApplicable(ExtensionDecl *Ext, bool IsSynthesized,
|
||||||
SynthesizedExtensionInfo Result(IsSynthesized);
|
ExtensionDecl *EnablingExt, NormalProtocolConformance *Conf) {
|
||||||
|
SynthesizedExtensionInfo Result(IsSynthesized, EnablingExt);
|
||||||
ExtensionMergeInfo MergeInfo;
|
ExtensionMergeInfo MergeInfo;
|
||||||
MergeInfo.HasDocComment = !Ext->getRawComment().isEmpty();
|
MergeInfo.HasDocComment = !Ext->getRawComment().isEmpty();
|
||||||
MergeInfo.InheritsCount = countInherits(Ext);
|
MergeInfo.InheritsCount = countInherits(Ext);
|
||||||
if (!Ext->isConstrainedExtension()) {
|
|
||||||
|
// There's (up to) two extensions here: the extension with the items that we
|
||||||
|
// might be merging, plus the "enabling extension", which is the route
|
||||||
|
// through which \c Ext itself applies, e.g. extension SomeProtocol {}
|
||||||
|
// extension SomeType: SomeProtocol where T: SomeProtocol {}. The former is
|
||||||
|
// Ext and the latter is EnablingExt/Conf. Either of these can be
|
||||||
|
// conditional in ways that need to be considered when merging.
|
||||||
|
auto conformanceIsConditional =
|
||||||
|
Conf && !Conf->getConditionalRequirements().empty();
|
||||||
|
if (!Ext->isConstrainedExtension() && !conformanceIsConditional) {
|
||||||
if (IncludeUnconditional)
|
if (IncludeUnconditional)
|
||||||
Result.Ext = Ext;
|
Result.Ext = Ext;
|
||||||
return {Result, MergeInfo};
|
return {Result, MergeInfo};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the substitutions from the generic signature of
|
auto handleRequirements = [&](SubstitutionMap subMap,
|
||||||
// the extension to the interface types of the base type's
|
GenericSignature *GenericSig,
|
||||||
// declaration.
|
ArrayRef<Requirement> Reqs) {
|
||||||
auto *M = DC->getParentModule();
|
for (auto Req : Reqs) {
|
||||||
SubstitutionMap subMap;
|
auto Kind = Req.getKind();
|
||||||
if (!BaseType->isExistentialType())
|
|
||||||
subMap = BaseType->getContextSubstitutionMap(M, Ext);
|
|
||||||
|
|
||||||
assert(Ext->getGenericSignature() && "No generic signature.");
|
// FIXME: Could do something here
|
||||||
auto GenericSig = Ext->getGenericSignature();
|
if (Kind == RequirementKind::Layout)
|
||||||
for (auto Req : GenericSig->getRequirements()) {
|
continue;
|
||||||
auto Kind = Req.getKind();
|
|
||||||
|
|
||||||
// FIXME: Could do something here
|
auto First = Req.getFirstType();
|
||||||
if (Kind == RequirementKind::Layout)
|
auto Second = Req.getSecondType();
|
||||||
continue;
|
if (!BaseType->isExistentialType()) {
|
||||||
|
First = First.subst(subMap);
|
||||||
|
Second = Second.subst(subMap);
|
||||||
|
|
||||||
auto First = Req.getFirstType();
|
if (!First || !Second) {
|
||||||
auto Second = Req.getSecondType();
|
// Substitution with interface type bases can only fail
|
||||||
if (!BaseType->isExistentialType()) {
|
// if a concrete type fails to conform to a protocol.
|
||||||
First = First.subst(subMap);
|
// In this case, just give up on the extension altogether.
|
||||||
Second = Second.subst(subMap);
|
return true;
|
||||||
|
}
|
||||||
if (!First || !Second) {
|
|
||||||
// Substitution with interface type bases can only fail
|
|
||||||
// if a concrete type fails to conform to a protocol.
|
|
||||||
// In this case, just give up on the extension altogether.
|
|
||||||
return {Result, MergeInfo};
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
switch (Kind) {
|
switch (Kind) {
|
||||||
case RequirementKind::Conformance:
|
case RequirementKind::Conformance:
|
||||||
case RequirementKind::Superclass:
|
case RequirementKind::Superclass:
|
||||||
// FIXME: This could be more accurate; check
|
// FIXME: This could be more accurate; check
|
||||||
// conformance instead of subtyping
|
// conformance instead of subtyping
|
||||||
if (!canPossiblyConvertTo(First, Second, *DC))
|
if (!canPossiblyConvertTo(First, Second, *DC))
|
||||||
return {Result, MergeInfo};
|
return true;
|
||||||
else if (!isConvertibleTo(First, Second, *DC))
|
else if (!isConvertibleTo(First, Second, *DC))
|
||||||
MergeInfo.addRequirement(GenericSig, First, Second, Kind);
|
MergeInfo.addRequirement(GenericSig, First, Second, Kind);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RequirementKind::SameType:
|
case RequirementKind::SameType:
|
||||||
if (!canPossiblyEqual(First, Second, *DC)) {
|
if (!canPossiblyEqual(First, Second, *DC)) {
|
||||||
return {Result, MergeInfo};
|
return true;
|
||||||
} else if (!First->isEqual(Second)) {
|
} else if (!First->isEqual(Second)) {
|
||||||
MergeInfo.addRequirement(GenericSig, First, Second, Kind);
|
MergeInfo.addRequirement(GenericSig, First, Second, Kind);
|
||||||
}
|
}
|
||||||
@@ -332,8 +337,31 @@ struct SynthesizedExtensionAnalyzer::Implementation {
|
|||||||
|
|
||||||
case RequirementKind::Layout:
|
case RequirementKind::Layout:
|
||||||
llvm_unreachable("Handled above");
|
llvm_unreachable("Handled above");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
auto *M = DC->getParentModule();
|
||||||
|
if (Ext->isConstrainedExtension()) {
|
||||||
|
// Get the substitutions from the generic signature of
|
||||||
|
// the extension to the interface types of the base type's
|
||||||
|
// declaration.
|
||||||
|
SubstitutionMap subMap;
|
||||||
|
if (!BaseType->isExistentialType())
|
||||||
|
subMap = BaseType->getContextSubstitutionMap(M, Ext);
|
||||||
|
|
||||||
|
assert(Ext->getGenericSignature() && "No generic signature.");
|
||||||
|
auto GenericSig = Ext->getGenericSignature();
|
||||||
|
if (handleRequirements(subMap, GenericSig, GenericSig->getRequirements()))
|
||||||
|
return {Result, MergeInfo};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Conf && handleRequirements(Conf->getSubstitutions(M),
|
||||||
|
Conf->getGenericSignature(),
|
||||||
|
Conf->getConditionalRequirements()))
|
||||||
|
return {Result, MergeInfo};
|
||||||
|
|
||||||
Result.Ext = Ext;
|
Result.Ext = Ext;
|
||||||
return {Result, MergeInfo};
|
return {Result, MergeInfo};
|
||||||
}
|
}
|
||||||
@@ -368,7 +396,9 @@ struct SynthesizedExtensionAnalyzer::Implementation {
|
|||||||
for (auto *E : Target->getExtensions()) {
|
for (auto *E : Target->getExtensions()) {
|
||||||
if (!Options.shouldPrint(E))
|
if (!Options.shouldPrint(E))
|
||||||
continue;
|
continue;
|
||||||
auto Pair = isApplicable(E, /*Synthesized*/false);
|
auto Pair = isApplicable(E, /*Synthesized*/ false,
|
||||||
|
/*EnablingExt*/ nullptr,
|
||||||
|
/*Conf*/ nullptr);
|
||||||
if (Pair.first) {
|
if (Pair.first) {
|
||||||
InfoMap->insert({E, Pair.first});
|
InfoMap->insert({E, Pair.first});
|
||||||
MergeInfoMap.insert({E, Pair.second});
|
MergeInfoMap.insert({E, Pair.second});
|
||||||
@@ -400,9 +430,11 @@ struct SynthesizedExtensionAnalyzer::Implementation {
|
|||||||
ExtensionMergeInfoMap MergeInfoMap;
|
ExtensionMergeInfoMap MergeInfoMap;
|
||||||
std::vector<NominalTypeDecl*> Unhandled;
|
std::vector<NominalTypeDecl*> Unhandled;
|
||||||
|
|
||||||
auto handleExtension = [&](ExtensionDecl *E, bool Synthesized) {
|
auto handleExtension = [&](ExtensionDecl *E, bool Synthesized,
|
||||||
|
ExtensionDecl *EnablingE,
|
||||||
|
NormalProtocolConformance *Conf) {
|
||||||
if (Options.shouldPrint(E)) {
|
if (Options.shouldPrint(E)) {
|
||||||
auto Pair = isApplicable(E, Synthesized);
|
auto Pair = isApplicable(E, Synthesized, EnablingE, Conf);
|
||||||
if (Pair.first) {
|
if (Pair.first) {
|
||||||
InfoMap->insert({E, Pair.first});
|
InfoMap->insert({E, Pair.first});
|
||||||
MergeInfoMap.insert({E, Pair.second});
|
MergeInfoMap.insert({E, Pair.second});
|
||||||
@@ -421,7 +453,7 @@ struct SynthesizedExtensionAnalyzer::Implementation {
|
|||||||
NominalTypeDecl* Back = Unhandled.back();
|
NominalTypeDecl* Back = Unhandled.back();
|
||||||
Unhandled.pop_back();
|
Unhandled.pop_back();
|
||||||
for (ExtensionDecl *E : Back->getExtensions()) {
|
for (ExtensionDecl *E : Back->getExtensions()) {
|
||||||
handleExtension(E, true);
|
handleExtension(E, true, nullptr, nullptr);
|
||||||
}
|
}
|
||||||
for (auto *Conf : Back->getLocalConformances()) {
|
for (auto *Conf : Back->getLocalConformances()) {
|
||||||
Unhandled.push_back(Conf->getProtocol());
|
Unhandled.push_back(Conf->getProtocol());
|
||||||
@@ -433,11 +465,11 @@ struct SynthesizedExtensionAnalyzer::Implementation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Merge with actual extensions.
|
// Merge with actual extensions.
|
||||||
for (auto *E : Target->getExtensions()) {
|
for (auto *EnablingE : Target->getExtensions()) {
|
||||||
handleExtension(E, false);
|
handleExtension(EnablingE, false, nullptr, nullptr);
|
||||||
for (auto *Conf : E->getLocalConformances()) {
|
for (auto *Conf : EnablingE->getLocalConformances()) {
|
||||||
for (auto E : Conf->getProtocol()->getExtensions())
|
for (auto E : Conf->getProtocol()->getExtensions())
|
||||||
handleExtension(E, true);
|
handleExtension(E, true, EnablingE, Conf->getRootNormalConformance());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -482,9 +514,10 @@ forEachExtensionMergeGroup(MergeGroupKind Kind, ExtensionGroupOperation Fn) {
|
|||||||
if (Kind != Group.Kind)
|
if (Kind != Group.Kind)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
std::vector<ExtensionAndIsSynthesized> GroupContent;
|
std::vector<ExtensionInfo> GroupContent;
|
||||||
for (auto &Member : Group.Members) {
|
for (auto &Member : Group.Members) {
|
||||||
GroupContent.push_back({Member->Ext, Member->IsSynthesized});
|
GroupContent.push_back(
|
||||||
|
{Member->Ext, Member->EnablingExt, Member->IsSynthesized});
|
||||||
}
|
}
|
||||||
Fn(llvm::makeArrayRef(GroupContent));
|
Fn(llvm::makeArrayRef(GroupContent));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,15 +81,16 @@ private:
|
|||||||
return OtherPrinter.printModuleRef(Mod, Name);
|
return OtherPrinter.printModuleRef(Mod, Name);
|
||||||
}
|
}
|
||||||
void printSynthesizedExtensionPre(const ExtensionDecl *ED,
|
void printSynthesizedExtensionPre(const ExtensionDecl *ED,
|
||||||
const NominalTypeDecl *NTD,
|
TypeOrExtensionDecl Target,
|
||||||
Optional<BracketOptions> Bracket) override {
|
Optional<BracketOptions> Bracket) override {
|
||||||
return OtherPrinter.printSynthesizedExtensionPre(ED, NTD, Bracket);
|
return OtherPrinter.printSynthesizedExtensionPre(ED, Target, Bracket);
|
||||||
}
|
}
|
||||||
|
|
||||||
void printSynthesizedExtensionPost(const ExtensionDecl *ED,
|
void
|
||||||
const NominalTypeDecl *NTD,
|
printSynthesizedExtensionPost(const ExtensionDecl *ED,
|
||||||
Optional<BracketOptions> Bracket) override {
|
TypeOrExtensionDecl Target,
|
||||||
return OtherPrinter.printSynthesizedExtensionPost(ED, NTD, Bracket);
|
Optional<BracketOptions> Bracket) override {
|
||||||
|
return OtherPrinter.printSynthesizedExtensionPost(ED, Target, Bracket);
|
||||||
}
|
}
|
||||||
|
|
||||||
void printStructurePre(PrintStructureKind Kind, const Decl *D) override {
|
void printStructurePre(PrintStructureKind Kind, const Decl *D) override {
|
||||||
@@ -589,20 +590,22 @@ void swift::ide::printSubmoduleInterface(
|
|||||||
if (IsTopLevelDecl) {
|
if (IsTopLevelDecl) {
|
||||||
// Print the part that should be merged with the type decl.
|
// Print the part that should be merged with the type decl.
|
||||||
pAnalyzer->forEachExtensionMergeGroup(
|
pAnalyzer->forEachExtensionMergeGroup(
|
||||||
SynthesizedExtensionAnalyzer::MergeGroupKind::MergeableWithTypeDef,
|
SynthesizedExtensionAnalyzer::MergeGroupKind::
|
||||||
[&](ArrayRef<ExtensionAndIsSynthesized> Decls){
|
MergeableWithTypeDef,
|
||||||
for (auto ET : Decls) {
|
[&](ArrayRef<ExtensionInfo> Decls) {
|
||||||
AdjustedOptions.BracketOptions = {ET.first, false,
|
for (auto ET : Decls) {
|
||||||
Decls.back().first == ET.first, true};
|
AdjustedOptions.BracketOptions = {
|
||||||
if (ET.second)
|
ET.Ext, false, Decls.back().Ext == ET.Ext, true};
|
||||||
AdjustedOptions.initForSynthesizedExtension(NTD);
|
if (ET.IsSynthesized)
|
||||||
ET.first->print(Printer, AdjustedOptions);
|
AdjustedOptions.initForSynthesizedExtension(NTD);
|
||||||
if (ET.second)
|
ET.Ext->print(Printer, AdjustedOptions);
|
||||||
AdjustedOptions.clearSynthesizedExtension();
|
if (ET.IsSynthesized)
|
||||||
if (AdjustedOptions.BracketOptions.shouldCloseExtension(ET.first))
|
AdjustedOptions.clearSynthesizedExtension();
|
||||||
Printer << "\n";
|
if (AdjustedOptions.BracketOptions.shouldCloseExtension(
|
||||||
}
|
ET.Ext))
|
||||||
});
|
Printer << "\n";
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the printed Decl is not the top-level one, reset analyzer.
|
// If the printed Decl is not the top-level one, reset analyzer.
|
||||||
@@ -611,28 +614,36 @@ void swift::ide::printSubmoduleInterface(
|
|||||||
|
|
||||||
// Print the rest as synthesized extensions.
|
// Print the rest as synthesized extensions.
|
||||||
pAnalyzer->forEachExtensionMergeGroup(
|
pAnalyzer->forEachExtensionMergeGroup(
|
||||||
// For top-level decls, only constraint extensions are to print;
|
// For top-level decls, only constraint extensions need to be
|
||||||
// Since the rest are merged into the main body.
|
// printed, since the rest are merged into the main body.
|
||||||
IsTopLevelDecl ?
|
IsTopLevelDecl ? SynthesizedExtensionAnalyzer::MergeGroupKind::
|
||||||
SynthesizedExtensionAnalyzer::MergeGroupKind::UnmergeableWithTypeDef :
|
UnmergeableWithTypeDef
|
||||||
// For sub-decls, all extensions should be printed.
|
:
|
||||||
SynthesizedExtensionAnalyzer::MergeGroupKind::All,
|
// For sub-decls, all extensions should be printed.
|
||||||
[&](ArrayRef<ExtensionAndIsSynthesized> Decls){
|
SynthesizedExtensionAnalyzer::MergeGroupKind::All,
|
||||||
for (auto ET : Decls) {
|
[&](ArrayRef<ExtensionInfo> Decls) {
|
||||||
AdjustedOptions.BracketOptions = {ET.first,
|
for (auto ET : Decls) {
|
||||||
Decls.front().first == ET.first,
|
AdjustedOptions.BracketOptions = {
|
||||||
Decls.back().first == ET.first, true};
|
ET.Ext, Decls.front().Ext == ET.Ext,
|
||||||
if (AdjustedOptions.BracketOptions.shouldOpenExtension(ET.first))
|
Decls.back().Ext == ET.Ext, true};
|
||||||
Printer << "\n";
|
if (AdjustedOptions.BracketOptions.shouldOpenExtension(
|
||||||
if (ET.second)
|
ET.Ext))
|
||||||
AdjustedOptions.initForSynthesizedExtension(NTD);
|
Printer << "\n";
|
||||||
ET.first->print(Printer, AdjustedOptions);
|
if (ET.IsSynthesized) {
|
||||||
if (ET.second)
|
if (ET.EnablingExt)
|
||||||
AdjustedOptions.clearSynthesizedExtension();
|
AdjustedOptions.initForSynthesizedExtension(
|
||||||
if (AdjustedOptions.BracketOptions.shouldCloseExtension(ET.first))
|
ET.EnablingExt);
|
||||||
Printer << "\n";
|
else
|
||||||
}
|
AdjustedOptions.initForSynthesizedExtension(NTD);
|
||||||
});
|
}
|
||||||
|
ET.Ext->print(Printer, AdjustedOptions);
|
||||||
|
if (ET.IsSynthesized)
|
||||||
|
AdjustedOptions.clearSynthesizedExtension();
|
||||||
|
if (AdjustedOptions.BracketOptions.shouldCloseExtension(
|
||||||
|
ET.Ext))
|
||||||
|
Printer << "\n";
|
||||||
|
}
|
||||||
|
});
|
||||||
AdjustedOptions.BracketOptions = BracketOptions();
|
AdjustedOptions.BracketOptions = BracketOptions();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,3 +83,17 @@ extension C1 : P4 {
|
|||||||
public func C1S1foo(a : P4) {}
|
public func C1S1foo(a : P4) {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// rdar://problem/36553066
|
||||||
|
|
||||||
|
public protocol P5 {
|
||||||
|
associatedtype Element
|
||||||
|
}
|
||||||
|
public protocol P6: P5 {}
|
||||||
|
extension P6 {
|
||||||
|
public var null: Element? { return nil }
|
||||||
|
}
|
||||||
|
public struct S3<Wrapped: P5>: P5 {
|
||||||
|
public typealias Element = Wrapped.Element
|
||||||
|
}
|
||||||
|
extension S3: P6 where Wrapped: P6 {}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -62,7 +62,7 @@ struct TextRange {
|
|||||||
|
|
||||||
struct TextEntity {
|
struct TextEntity {
|
||||||
const Decl *Dcl = nullptr;
|
const Decl *Dcl = nullptr;
|
||||||
const Decl *SynthesizeTarget = nullptr;
|
TypeOrExtensionDecl SynthesizeTarget;
|
||||||
const Decl *DefaultImplementationOf = nullptr;
|
const Decl *DefaultImplementationOf = nullptr;
|
||||||
StringRef Argument;
|
StringRef Argument;
|
||||||
TextRange Range;
|
TextRange Range;
|
||||||
@@ -70,26 +70,26 @@ struct TextEntity {
|
|||||||
std::vector<TextEntity> SubEntities;
|
std::vector<TextEntity> SubEntities;
|
||||||
const bool IsSynthesizedExtension;
|
const bool IsSynthesizedExtension;
|
||||||
|
|
||||||
TextEntity(const Decl *D, const Decl *SynthesizeTarget,
|
TextEntity(const Decl *D, TypeOrExtensionDecl SynthesizeTarget,
|
||||||
const Decl* DefaultImplementationOf,
|
const Decl *DefaultImplementationOf, unsigned StartOffset,
|
||||||
unsigned StartOffset, bool IsSynthesizedExtension)
|
bool IsSynthesizedExtension)
|
||||||
: Dcl(D), SynthesizeTarget(SynthesizeTarget),
|
: Dcl(D), SynthesizeTarget(SynthesizeTarget),
|
||||||
DefaultImplementationOf(DefaultImplementationOf), Range{StartOffset, 0},
|
DefaultImplementationOf(DefaultImplementationOf), Range{StartOffset, 0},
|
||||||
IsSynthesizedExtension(IsSynthesizedExtension) {}
|
IsSynthesizedExtension(IsSynthesizedExtension) {}
|
||||||
|
|
||||||
TextEntity(const Decl *D, const Decl *SynthesizeTarget,
|
TextEntity(const Decl *D, TypeOrExtensionDecl SynthesizeTarget,
|
||||||
const Decl* DefaultImplementationOf, TextRange TR,
|
const Decl *DefaultImplementationOf, TextRange TR,
|
||||||
unsigned LocOffset, bool IsSynthesizedExtension) : Dcl(D),
|
unsigned LocOffset, bool IsSynthesizedExtension)
|
||||||
DefaultImplementationOf(DefaultImplementationOf), Range(TR),
|
: Dcl(D), DefaultImplementationOf(DefaultImplementationOf), Range(TR),
|
||||||
LocOffset(LocOffset),
|
LocOffset(LocOffset), IsSynthesizedExtension(IsSynthesizedExtension) {}
|
||||||
IsSynthesizedExtension(IsSynthesizedExtension) {}
|
|
||||||
|
|
||||||
TextEntity(const Decl *D, const Decl *SynthesizeTarget,
|
TextEntity(const Decl *D, TypeOrExtensionDecl SynthesizeTarget,
|
||||||
const Decl* DefaultImplementationOf, StringRef Arg,
|
const Decl *DefaultImplementationOf, StringRef Arg, TextRange TR,
|
||||||
TextRange TR, unsigned LocOffset, bool IsSynthesizedExtension)
|
unsigned LocOffset, bool IsSynthesizedExtension)
|
||||||
: Dcl(D), SynthesizeTarget(SynthesizeTarget),
|
: Dcl(D), SynthesizeTarget(SynthesizeTarget),
|
||||||
DefaultImplementationOf(DefaultImplementationOf), Argument(Arg), Range(TR),
|
DefaultImplementationOf(DefaultImplementationOf), Argument(Arg),
|
||||||
LocOffset(LocOffset), IsSynthesizedExtension(IsSynthesizedExtension) {}
|
Range(TR), LocOffset(LocOffset),
|
||||||
|
IsSynthesizedExtension(IsSynthesizedExtension) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TextReference {
|
struct TextReference {
|
||||||
@@ -103,8 +103,8 @@ struct TextReference {
|
|||||||
|
|
||||||
class AnnotatingPrinter : public StreamPrinter {
|
class AnnotatingPrinter : public StreamPrinter {
|
||||||
|
|
||||||
std::pair<const ExtensionDecl *, const NominalTypeDecl *>
|
std::pair<const ExtensionDecl *, TypeOrExtensionDecl>
|
||||||
SynthesizedExtensionInfo = {nullptr, nullptr};
|
SynthesizedExtensionInfo = {nullptr, {}};
|
||||||
|
|
||||||
typedef llvm::SmallDenseMap<ValueDecl*, ValueDecl*> DefaultImplementMap;
|
typedef llvm::SmallDenseMap<ValueDecl*, ValueDecl*> DefaultImplementMap;
|
||||||
llvm::SmallDenseMap<ProtocolDecl*, DefaultImplementMap> AllDefaultMaps;
|
llvm::SmallDenseMap<ProtocolDecl*, DefaultImplementMap> AllDefaultMaps;
|
||||||
@@ -175,22 +175,22 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void printSynthesizedExtensionPre(const ExtensionDecl *ED,
|
void printSynthesizedExtensionPre(const ExtensionDecl *ED,
|
||||||
const NominalTypeDecl *NTD,
|
TypeOrExtensionDecl Target,
|
||||||
Optional<BracketOptions> Bracket) override {
|
Optional<BracketOptions> Bracket) override {
|
||||||
assert(!SynthesizedExtensionInfo.first);
|
assert(!SynthesizedExtensionInfo.first);
|
||||||
SynthesizedExtensionInfo = {ED, NTD};
|
SynthesizedExtensionInfo = {ED, Target};
|
||||||
if (!shouldContinuePre(ED, Bracket))
|
if (!shouldContinuePre(ED, Bracket))
|
||||||
return;
|
return;
|
||||||
unsigned StartOffset = OS.tell();
|
unsigned StartOffset = OS.tell();
|
||||||
EntitiesStack.emplace_back(ED, SynthesizedExtensionInfo.second, nullptr,
|
EntitiesStack.emplace_back(ED, Target, nullptr, StartOffset, true);
|
||||||
StartOffset, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void printSynthesizedExtensionPost(const ExtensionDecl *ED,
|
void
|
||||||
const NominalTypeDecl *NTD,
|
printSynthesizedExtensionPost(const ExtensionDecl *ED,
|
||||||
Optional<BracketOptions> Bracket) override {
|
TypeOrExtensionDecl Target,
|
||||||
|
Optional<BracketOptions> Bracket) override {
|
||||||
assert(SynthesizedExtensionInfo.first);
|
assert(SynthesizedExtensionInfo.first);
|
||||||
SynthesizedExtensionInfo = {nullptr, nullptr};
|
SynthesizedExtensionInfo = {nullptr, {}};
|
||||||
if (!shouldContinuePost(ED, Bracket))
|
if (!shouldContinuePost(ED, Bracket))
|
||||||
return;
|
return;
|
||||||
TextEntity Entity = std::move(EntitiesStack.back());
|
TextEntity Entity = std::move(EntitiesStack.back());
|
||||||
@@ -207,8 +207,8 @@ public:
|
|||||||
return;
|
return;
|
||||||
unsigned StartOffset = OS.tell();
|
unsigned StartOffset = OS.tell();
|
||||||
initDefaultMapToUse(D);
|
initDefaultMapToUse(D);
|
||||||
const NominalTypeDecl *SynthesizedTarget = nullptr;
|
|
||||||
// If D is declared in the extension, then the synthesized target is valid.
|
// If D is declared in the extension, then the synthesized target is valid.
|
||||||
|
TypeOrExtensionDecl SynthesizedTarget;
|
||||||
if (D->getDeclContext() == SynthesizedExtensionInfo.first)
|
if (D->getDeclContext() == SynthesizedExtensionInfo.first)
|
||||||
SynthesizedTarget = SynthesizedExtensionInfo.second;
|
SynthesizedTarget = SynthesizedExtensionInfo.second;
|
||||||
EntitiesStack.emplace_back(D, SynthesizedTarget,
|
EntitiesStack.emplace_back(D, SynthesizedTarget,
|
||||||
@@ -297,10 +297,10 @@ static void initDocGenericParams(const Decl *D, DocEntityInfo &Info) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool initDocEntityInfo(const Decl *D, const Decl *SynthesizedTarget,
|
static bool initDocEntityInfo(const Decl *D,
|
||||||
const Decl *DefaultImplementationOf,
|
TypeOrExtensionDecl SynthesizedTarget,
|
||||||
bool IsRef, bool IsSynthesizedExtension,
|
const Decl *DefaultImplementationOf, bool IsRef,
|
||||||
DocEntityInfo &Info,
|
bool IsSynthesizedExtension, DocEntityInfo &Info,
|
||||||
StringRef Arg = StringRef()) {
|
StringRef Arg = StringRef()) {
|
||||||
if (!IsRef && D->isImplicit())
|
if (!IsRef && D->isImplicit())
|
||||||
return true;
|
return true;
|
||||||
@@ -320,9 +320,13 @@ static bool initDocEntityInfo(const Decl *D, const Decl *SynthesizedTarget,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsSynthesizedExtension)
|
auto SynthesizedTargetNTD =
|
||||||
Info.Kind = SwiftLangSupport::getUIDForExtensionOfDecl(SynthesizedTarget);
|
SynthesizedTarget ? SynthesizedTarget.getBaseNominal() : nullptr;
|
||||||
else
|
|
||||||
|
if (IsSynthesizedExtension) {
|
||||||
|
Info.Kind =
|
||||||
|
SwiftLangSupport::getUIDForExtensionOfDecl(SynthesizedTargetNTD);
|
||||||
|
} else
|
||||||
Info.Kind = SwiftLangSupport::getUIDForDecl(D, IsRef);
|
Info.Kind = SwiftLangSupport::getUIDForDecl(D, IsRef);
|
||||||
|
|
||||||
if (Info.Kind.isInvalid())
|
if (Info.Kind.isInvalid())
|
||||||
@@ -335,7 +339,7 @@ static bool initDocEntityInfo(const Decl *D, const Decl *SynthesizedTarget,
|
|||||||
SwiftLangSupport::printUSR(VD, OS);
|
SwiftLangSupport::printUSR(VD, OS);
|
||||||
if (SynthesizedTarget) {
|
if (SynthesizedTarget) {
|
||||||
OS << SwiftLangSupport::SynthesizedUSRSeparator;
|
OS << SwiftLangSupport::SynthesizedUSRSeparator;
|
||||||
SwiftLangSupport::printUSR(dyn_cast<ValueDecl>(SynthesizedTarget), OS);
|
SwiftLangSupport::printUSR(SynthesizedTargetNTD, OS);
|
||||||
{
|
{
|
||||||
llvm::raw_svector_ostream OS(Info.OriginalUSR);
|
llvm::raw_svector_ostream OS(Info.OriginalUSR);
|
||||||
SwiftLangSupport::printUSR(VD, OS);
|
SwiftLangSupport::printUSR(VD, OS);
|
||||||
@@ -375,8 +379,7 @@ static bool initDocEntityInfo(const Decl *D, const Decl *SynthesizedTarget,
|
|||||||
SecondPart = SecondPart.substr(ExtendedName.size());
|
SecondPart = SecondPart.substr(ExtendedName.size());
|
||||||
llvm::SmallString<128> UpdatedDocBuffer;
|
llvm::SmallString<128> UpdatedDocBuffer;
|
||||||
UpdatedDocBuffer.append(FirstPart);
|
UpdatedDocBuffer.append(FirstPart);
|
||||||
UpdatedDocBuffer.append(((const NominalTypeDecl*)SynthesizedTarget)->getName().
|
UpdatedDocBuffer.append(SynthesizedTargetNTD->getName().str());
|
||||||
str());
|
|
||||||
UpdatedDocBuffer.append(SecondPart);
|
UpdatedDocBuffer.append(SecondPart);
|
||||||
OS << UpdatedDocBuffer;
|
OS << UpdatedDocBuffer;
|
||||||
} else
|
} else
|
||||||
@@ -392,9 +395,7 @@ static bool initDocEntityInfo(const Decl *D, const Decl *SynthesizedTarget,
|
|||||||
llvm::raw_svector_ostream OS(Info.FullyAnnotatedDecl);
|
llvm::raw_svector_ostream OS(Info.FullyAnnotatedDecl);
|
||||||
if (SynthesizedTarget)
|
if (SynthesizedTarget)
|
||||||
SwiftLangSupport::printFullyAnnotatedSynthesizedDeclaration(
|
SwiftLangSupport::printFullyAnnotatedSynthesizedDeclaration(
|
||||||
VD, const_cast<NominalTypeDecl *>(
|
VD, SynthesizedTarget, OS);
|
||||||
static_cast<const NominalTypeDecl *>(SynthesizedTarget)),
|
|
||||||
OS);
|
|
||||||
else
|
else
|
||||||
SwiftLangSupport::printFullyAnnotatedDeclaration(VD, Type(), OS);
|
SwiftLangSupport::printFullyAnnotatedDeclaration(VD, Type(), OS);
|
||||||
}
|
}
|
||||||
@@ -461,13 +462,13 @@ static const TypeDecl *getTypeDeclFromType(Type Ty) {
|
|||||||
|
|
||||||
static void passInherits(const ValueDecl *D, DocInfoConsumer &Consumer) {
|
static void passInherits(const ValueDecl *D, DocInfoConsumer &Consumer) {
|
||||||
DocEntityInfo EntInfo;
|
DocEntityInfo EntInfo;
|
||||||
if (initDocEntityInfo(D, nullptr, nullptr, /*IsRef=*/true, false, EntInfo))
|
if (initDocEntityInfo(D, {}, nullptr, /*IsRef=*/true, false, EntInfo))
|
||||||
return;
|
return;
|
||||||
Consumer.handleInheritsEntity(EntInfo);
|
Consumer.handleInheritsEntity(EntInfo);
|
||||||
}
|
}
|
||||||
static void passConforms(const ValueDecl *D, DocInfoConsumer &Consumer) {
|
static void passConforms(const ValueDecl *D, DocInfoConsumer &Consumer) {
|
||||||
DocEntityInfo EntInfo;
|
DocEntityInfo EntInfo;
|
||||||
if (initDocEntityInfo(D, nullptr, nullptr, /*IsRef=*/true, false, EntInfo))
|
if (initDocEntityInfo(D, {}, nullptr, /*IsRef=*/true, false, EntInfo))
|
||||||
return;
|
return;
|
||||||
Consumer.handleConformsToEntity(EntInfo);
|
Consumer.handleConformsToEntity(EntInfo);
|
||||||
}
|
}
|
||||||
@@ -503,7 +504,7 @@ static void passConforms(ArrayRef<ValueDecl *> Dcls,
|
|||||||
}
|
}
|
||||||
static void passExtends(const ValueDecl *D, DocInfoConsumer &Consumer) {
|
static void passExtends(const ValueDecl *D, DocInfoConsumer &Consumer) {
|
||||||
DocEntityInfo EntInfo;
|
DocEntityInfo EntInfo;
|
||||||
if (initDocEntityInfo(D, nullptr, nullptr, /*IsRef=*/true, false, EntInfo))
|
if (initDocEntityInfo(D, {}, nullptr, /*IsRef=*/true, false, EntInfo))
|
||||||
return;
|
return;
|
||||||
Consumer.handleExtendsEntity(EntInfo);
|
Consumer.handleExtendsEntity(EntInfo);
|
||||||
}
|
}
|
||||||
@@ -516,15 +517,15 @@ static void passInheritsAndConformancesForValueDecl(const ValueDecl *VD,
|
|||||||
Consumer);
|
Consumer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void reportRelated(ASTContext &Ctx,
|
static void reportRelated(ASTContext &Ctx, const Decl *D,
|
||||||
const Decl *D,
|
TypeOrExtensionDecl SynthesizedTarget,
|
||||||
const Decl* SynthesizedTarget,
|
|
||||||
DocInfoConsumer &Consumer) {
|
DocInfoConsumer &Consumer) {
|
||||||
if (!D || isa<ParamDecl>(D))
|
if (!D || isa<ParamDecl>(D))
|
||||||
return;
|
return;
|
||||||
if (const auto *ED = dyn_cast<ExtensionDecl>(D)) {
|
if (const auto *ED = dyn_cast<ExtensionDecl>(D)) {
|
||||||
if (SynthesizedTarget) {
|
if (SynthesizedTarget) {
|
||||||
passExtends((const ValueDecl*)SynthesizedTarget, Consumer);
|
auto Extends = SynthesizedTarget.getBaseNominal();
|
||||||
|
passExtends(Extends, Consumer);
|
||||||
} else if (Type T = ED->getExtendedType()) {
|
} else if (Type T = ED->getExtendedType()) {
|
||||||
if (auto TD = getTypeDeclFromType(T))
|
if (auto TD = getTypeDeclFromType(T))
|
||||||
passExtends(TD, Consumer);
|
passExtends(TD, Consumer);
|
||||||
@@ -645,7 +646,8 @@ static void reportDocEntities(ASTContext &Ctx,
|
|||||||
continue;
|
continue;
|
||||||
Consumer.startSourceEntity(EntInfo);
|
Consumer.startSourceEntity(EntInfo);
|
||||||
reportRelated(Ctx, Entity.Dcl,
|
reportRelated(Ctx, Entity.Dcl,
|
||||||
Entity.IsSynthesizedExtension ? Entity.SynthesizeTarget : nullptr,
|
Entity.IsSynthesizedExtension ? Entity.SynthesizeTarget
|
||||||
|
: TypeOrExtensionDecl(),
|
||||||
Consumer);
|
Consumer);
|
||||||
reportDocEntities(Ctx, Entity.SubEntities, Consumer);
|
reportDocEntities(Ctx, Entity.SubEntities, Consumer);
|
||||||
reportAttributes(Ctx, Entity.Dcl, Consumer);
|
reportAttributes(Ctx, Entity.Dcl, Consumer);
|
||||||
@@ -759,8 +761,7 @@ private:
|
|||||||
const TextReference &Ref = References.front();
|
const TextReference &Ref = References.front();
|
||||||
References = References.slice(1);
|
References = References.slice(1);
|
||||||
DocEntityInfo Info;
|
DocEntityInfo Info;
|
||||||
if (initDocEntityInfo(Ref.Dcl, nullptr, nullptr, /*IsRef=*/true, false,
|
if (initDocEntityInfo(Ref.Dcl, {}, nullptr, /*IsRef=*/true, false, Info))
|
||||||
Info))
|
|
||||||
continue;
|
continue;
|
||||||
Info.Offset = Ref.Range.Offset;
|
Info.Offset = Ref.Range.Offset;
|
||||||
Info.Length = Ref.Range.Length;
|
Info.Length = Ref.Range.Length;
|
||||||
@@ -826,7 +827,7 @@ static void addParameters(ArrayRef<Identifier> &ArgNames,
|
|||||||
SM.getLocOffsetInBuffer(Lexer::getLocForEndOfToken(SM, TypeRange.End),
|
SM.getLocOffsetInBuffer(Lexer::getLocForEndOfToken(SM, TypeRange.End),
|
||||||
BufferID);
|
BufferID);
|
||||||
TextRange TR{ StartOffs, EndOffs-StartOffs };
|
TextRange TR{ StartOffs, EndOffs-StartOffs };
|
||||||
TextEntity Param(param, nullptr, nullptr, Arg, TR, StartOffs, false);
|
TextEntity Param(param, {}, nullptr, Arg, TR, StartOffs, false);
|
||||||
Ent.SubEntities.push_back(std::move(Param));
|
Ent.SubEntities.push_back(std::move(Param));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1020,7 +1021,8 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
TextRange TR = getTextRange(D->getSourceRange());
|
TextRange TR = getTextRange(D->getSourceRange());
|
||||||
unsigned LocOffset = getOffset(Range.getStart());
|
unsigned LocOffset = getOffset(Range.getStart());
|
||||||
EntitiesStack.emplace_back(D, nullptr, nullptr, TR, LocOffset, false);
|
EntitiesStack.emplace_back(D, TypeOrExtensionDecl(), nullptr, TR, LocOffset,
|
||||||
|
false);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -129,21 +129,22 @@ public:
|
|||||||
assert(DeclUSRs.empty() && "unmatched printDeclLoc call ?");
|
assert(DeclUSRs.empty() && "unmatched printDeclLoc call ?");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void printSynthesizedExtensionPre(const ExtensionDecl *ED,
|
void printSynthesizedExtensionPre(const ExtensionDecl *ED,
|
||||||
const NominalTypeDecl *Target,
|
TypeOrExtensionDecl Target,
|
||||||
Optional<BracketOptions> Bracket) override {
|
Optional<BracketOptions> Bracket) override {
|
||||||
// When we start print a synthesized extension, record the target's USR.
|
// When we start print a synthesized extension, record the target's USR.
|
||||||
llvm::SmallString<64> Buf;
|
llvm::SmallString<64> Buf;
|
||||||
llvm::raw_svector_ostream OS(Buf);
|
llvm::raw_svector_ostream OS(Buf);
|
||||||
if (!SwiftLangSupport::printUSR(Target, OS)) {
|
auto TargetNTD = Target.getBaseNominal();
|
||||||
|
if (!SwiftLangSupport::printUSR(TargetNTD, OS)) {
|
||||||
TargetUSR = OS.str();
|
TargetUSR = OS.str();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void printSynthesizedExtensionPost(const ExtensionDecl *ED,
|
void
|
||||||
const NominalTypeDecl *Target,
|
printSynthesizedExtensionPost(const ExtensionDecl *ED,
|
||||||
Optional<BracketOptions> Bracket) override {
|
TypeOrExtensionDecl Target,
|
||||||
|
Optional<BracketOptions> Bracket) override {
|
||||||
// When we leave a synthesized extension, clear target's USR.
|
// When we leave a synthesized extension, clear target's USR.
|
||||||
TargetUSR = "";
|
TargetUSR = "";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -354,9 +354,9 @@ public:
|
|||||||
swift::Type BaseTy,
|
swift::Type BaseTy,
|
||||||
llvm::raw_ostream &OS);
|
llvm::raw_ostream &OS);
|
||||||
|
|
||||||
static void printFullyAnnotatedSynthesizedDeclaration(
|
static void
|
||||||
const swift::ValueDecl *VD,
|
printFullyAnnotatedSynthesizedDeclaration(const swift::ValueDecl *VD,
|
||||||
swift::NominalTypeDecl *Target,
|
swift::TypeOrExtensionDecl Target,
|
||||||
llvm::raw_ostream &OS);
|
llvm::raw_ostream &OS);
|
||||||
|
|
||||||
/// Tries to resolve the path to the real file-system path. If it fails it
|
/// Tries to resolve the path to the real file-system path. If it fails it
|
||||||
|
|||||||
@@ -433,19 +433,20 @@ void SwiftLangSupport::printFullyAnnotatedDeclaration(const ValueDecl *VD,
|
|||||||
VD->print(Printer, PO);
|
VD->print(Printer, PO);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SwiftLangSupport::
|
void SwiftLangSupport::printFullyAnnotatedSynthesizedDeclaration(
|
||||||
printFullyAnnotatedSynthesizedDeclaration(const swift::ValueDecl *VD,
|
const swift::ValueDecl *VD, TypeOrExtensionDecl Target,
|
||||||
swift::NominalTypeDecl *Target,
|
llvm::raw_ostream &OS) {
|
||||||
llvm::raw_ostream &OS) {
|
|
||||||
// FIXME: Mutable global variable - gross!
|
// FIXME: Mutable global variable - gross!
|
||||||
static llvm::SmallDenseMap<swift::ValueDecl*,
|
static llvm::SmallDenseMap<swift::ValueDecl*,
|
||||||
std::unique_ptr<swift::SynthesizedExtensionAnalyzer>> TargetToAnalyzerMap;
|
std::unique_ptr<swift::SynthesizedExtensionAnalyzer>> TargetToAnalyzerMap;
|
||||||
FullyAnnotatedDeclarationPrinter Printer(OS);
|
FullyAnnotatedDeclarationPrinter Printer(OS);
|
||||||
PrintOptions PO = PrintOptions::printQuickHelpDeclaration();
|
PrintOptions PO = PrintOptions::printQuickHelpDeclaration();
|
||||||
if (TargetToAnalyzerMap.count(Target) == 0) {
|
NominalTypeDecl *TargetNTD = Target.getBaseNominal();
|
||||||
|
|
||||||
|
if (TargetToAnalyzerMap.count(TargetNTD) == 0) {
|
||||||
std::unique_ptr<SynthesizedExtensionAnalyzer> Analyzer(
|
std::unique_ptr<SynthesizedExtensionAnalyzer> Analyzer(
|
||||||
new SynthesizedExtensionAnalyzer(Target, PO));
|
new SynthesizedExtensionAnalyzer(TargetNTD, PO));
|
||||||
TargetToAnalyzerMap.insert({Target, std::move(Analyzer)});
|
TargetToAnalyzerMap.insert({TargetNTD, std::move(Analyzer)});
|
||||||
}
|
}
|
||||||
PO.initForSynthesizedExtension(Target);
|
PO.initForSynthesizedExtension(Target);
|
||||||
PO.PrintAsMember = true;
|
PO.PrintAsMember = true;
|
||||||
|
|||||||
@@ -1700,18 +1700,18 @@ public:
|
|||||||
printDeclPost(D, None);
|
printDeclPost(D, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void printSynthesizedExtensionPre(const ExtensionDecl *ED,
|
void printSynthesizedExtensionPre(const ExtensionDecl *ED,
|
||||||
const NominalTypeDecl *NTD,
|
TypeOrExtensionDecl Target,
|
||||||
Optional<BracketOptions> Bracket) override {
|
Optional<BracketOptions> Bracket) override {
|
||||||
if (Bracket.hasValue() && !Bracket.getValue().shouldOpenExtension(ED))
|
if (Bracket.hasValue() && !Bracket.getValue().shouldOpenExtension(ED))
|
||||||
return;
|
return;
|
||||||
OS << "<synthesized>";
|
OS << "<synthesized>";
|
||||||
}
|
}
|
||||||
|
|
||||||
void printSynthesizedExtensionPost(const ExtensionDecl *ED,
|
void
|
||||||
const NominalTypeDecl *NTD,
|
printSynthesizedExtensionPost(const ExtensionDecl *ED,
|
||||||
Optional<BracketOptions> Bracket) override {
|
TypeOrExtensionDecl Target,
|
||||||
|
Optional<BracketOptions> Bracket) override {
|
||||||
if (Bracket.hasValue() && !Bracket.getValue().shouldCloseExtension(ED))
|
if (Bracket.hasValue() && !Bracket.getValue().shouldCloseExtension(ED))
|
||||||
return;
|
return;
|
||||||
OS << "</synthesized>";
|
OS << "</synthesized>";
|
||||||
|
|||||||
Reference in New Issue
Block a user