ModulePrinting: Merge synthesized extensions' bodies if they have the common constraints.

This commit is contained in:
Xi Ge
2016-03-10 17:43:39 -08:00
parent 74afb7800c
commit c22e9bcf53
5 changed files with 228 additions and 122 deletions

View File

@@ -31,6 +31,7 @@ class Type;
enum DeclAttrKind : unsigned; enum DeclAttrKind : unsigned;
class PrinterArchetypeTransformer; class PrinterArchetypeTransformer;
class SynthesizedExtensionAnalyzer; class SynthesizedExtensionAnalyzer;
struct PrintOptions;
/// Necessary information for archetype transformation during printing. /// Necessary information for archetype transformation during printing.
struct ArchetypeTransformContext { struct ArchetypeTransformContext {
@@ -47,29 +48,30 @@ struct ArchetypeTransformContext {
SynthesizedExtensionAnalyzer *Analyzer); SynthesizedExtensionAnalyzer *Analyzer);
Type transform(Type Input); Type transform(Type Input);
StringRef transform(StringRef Input); StringRef transform(StringRef Input);
bool shouldPrintRequirement(ExtensionDecl *ED, StringRef Req); bool shouldPrintRequirement(ExtensionDecl *ED, StringRef Req);
bool shouldOpenExtension;
bool shouldCloseExtension;
~ArchetypeTransformContext(); ~ArchetypeTransformContext();
private: private:
struct Implementation; struct Implementation;
Implementation &Impl; Implementation &Impl;
}; };
struct SynthesizedExtensionInfo {
ExtensionDecl *Ext = nullptr;
std::vector<StringRef> KnownSatisfiedRequirements;
operator bool() const { return Ext; }
};
class SynthesizedExtensionAnalyzer { class SynthesizedExtensionAnalyzer {
struct Implementation; struct Implementation;
Implementation &Impl; Implementation &Impl;
public: public:
SynthesizedExtensionAnalyzer(NominalTypeDecl *Target, SynthesizedExtensionAnalyzer(NominalTypeDecl *Target,
PrintOptions Options,
bool IncludeUnconditional = true); bool IncludeUnconditional = true);
~SynthesizedExtensionAnalyzer(); ~SynthesizedExtensionAnalyzer();
void forEachSynthesizedExtension( void forEachSynthesizedExtension(
llvm::function_ref<void(ExtensionDecl*)> Fn); llvm::function_ref<void(ExtensionDecl*)> Fn);
void forEachSynthesizedExtensionMergeGroup(
llvm::function_ref<void(ArrayRef<ExtensionDecl*>)> Fn);
bool isInSynthesizedExtension(const ValueDecl *VD); bool isInSynthesizedExtension(const ValueDecl *VD);
bool shouldPrintRequirement(ExtensionDecl *ED, StringRef Req); bool shouldPrintRequirement(ExtensionDecl *ED, StringRef Req);
}; };
@@ -259,7 +261,7 @@ struct PrintOptions {
/// \brief Print dependent types as references into this generic parameter /// \brief Print dependent types as references into this generic parameter
/// list. /// list.
GenericParamList *ContextGenericParams = nullptr; GenericParamList *ContextGenericParams = nullptr;
/// \brief Print types with alternative names from their canonical names. /// \brief Print types with alternative names from their canonical names.
llvm::DenseMap<CanType, Identifier> *AlternativeTypeNames = nullptr; llvm::DenseMap<CanType, Identifier> *AlternativeTypeNames = nullptr;

View File

@@ -98,14 +98,14 @@ public:
return Ty.transform([&](Type Ty) -> Type { return Ty.transform([&](Type Ty) -> Type {
if (Ty->getKind() != TypeKind::Archetype) if (Ty->getKind() != TypeKind::Archetype)
return Ty; return Ty;
// First, we try to find the map from cache. // First, we try to find the map from cache.
if (Cache.count(Ty.getPointer()) > 0) { if (Cache.count(Ty.getPointer()) > 0) {
return Cache[Ty.getPointer()]; return Cache[Ty.getPointer()];
} }
auto Id = cast<ArchetypeType>(Ty.getPointer())->getName().str(); auto Id = cast<ArchetypeType>(Ty.getPointer())->getName().str();
auto Result = Ty; auto Result = Ty;
// Iterate the IdMap to find the argument type of the given param name. // Iterate the IdMap to find the argument type of the given param name.
for (auto It = IdMap->begin(); It != IdMap->end(); ++ It) { for (auto It = IdMap->begin(); It != IdMap->end(); ++ It) {
if (Id == It->getFirst()) { if (Id == It->getFirst()) {
@@ -113,7 +113,7 @@ public:
break; break;
} }
} }
// Put the result into cache. // Put the result into cache.
Cache[Ty.getPointer()] = Result; Cache[Ty.getPointer()] = Result;
return Result; return Result;
@@ -206,20 +206,30 @@ public:
}; };
struct SynthesizedExtensionAnalyzer::Implementation { struct SynthesizedExtensionAnalyzer::Implementation {
struct SynthesizedExtensionInfo {
ExtensionDecl *Ext = nullptr;
std::vector<StringRef> KnownSatisfiedRequirements;
unsigned MergeGroup;
operator bool() const { return Ext; }
};
typedef llvm::MapVector<ExtensionDecl*, SynthesizedExtensionInfo> ExtMap; typedef llvm::MapVector<ExtensionDecl*, SynthesizedExtensionInfo> ExtMap;
NominalTypeDecl *Target; NominalTypeDecl *Target;
Type BaseType; Type BaseType;
DeclContext *DC; DeclContext *DC;
std::unique_ptr<ArchetypeSelfTransformer> pTransform; std::unique_ptr<ArchetypeSelfTransformer> pTransform;
bool IncludeUnconditional; bool IncludeUnconditional;
PrintOptions Options;
std::unique_ptr<ExtMap> Results; std::unique_ptr<ExtMap> Results;
Implementation(NominalTypeDecl *Target, bool IncludeUnconditional): Implementation(NominalTypeDecl *Target, bool IncludeUnconditional,
PrintOptions Options):
Target(Target), Target(Target),
BaseType(Target->getDeclaredTypeInContext()), BaseType(Target->getDeclaredTypeInContext()),
DC(Target), DC(Target),
pTransform(new ArchetypeSelfTransformer(Target)), pTransform(new ArchetypeSelfTransformer(Target)),
IncludeUnconditional(IncludeUnconditional), IncludeUnconditional(IncludeUnconditional),
Options(Options),
Results(collectSynthesizedExtensionInfo()) {} Results(collectSynthesizedExtensionInfo()) {}
Type checkElementType(StringRef Text) { Type checkElementType(StringRef Text) {
@@ -284,12 +294,46 @@ struct SynthesizedExtensionAnalyzer::Implementation {
return MType->getAs<AnyMetatypeType>()->getInstanceType(); return MType->getAs<AnyMetatypeType>()->getInstanceType();
} }
SynthesizedExtensionInfo isApplicable(ExtensionDecl *Ext) { struct ExtensionMergeInfo {
struct Requirement {
Type First;
Type Second;
RequirementReprKind Kind;
bool operator< (const Requirement& Rhs) const {
if (Kind != Rhs.Kind)
return Kind < Rhs.Kind;
else if (First.getPointer() != Rhs.First.getPointer())
return First.getPointer() < Rhs.First.getPointer();
else
return Second.getPointer() < Rhs.Second.getPointer();
}
bool operator== (const Requirement& Rhs) const {
return (!(*this < Rhs)) && (!(Rhs < *this));
}
};
bool HasDocComment;
std::set<Requirement> Requirements;
void addRequirement(Type First, Type Second, RequirementReprKind Kind) {
Requirements.insert({First, Second, Kind});
}
bool operator== (const ExtensionMergeInfo& Another) const {
// Trivially unmergable.
if (HasDocComment || Another.HasDocComment)
return false;
return Requirements == Another.Requirements;
}
};
std::pair<SynthesizedExtensionInfo, std::unique_ptr<ExtensionMergeInfo>>
isApplicable(ExtensionDecl *Ext) {
SynthesizedExtensionInfo Result; SynthesizedExtensionInfo Result;
std::unique_ptr<ExtensionMergeInfo> MergeInfo(new ExtensionMergeInfo());
MergeInfo->HasDocComment = false;
if (!Ext->isConstrainedExtension()) { if (!Ext->isConstrainedExtension()) {
if (IncludeUnconditional) if (IncludeUnconditional)
Result.Ext = Ext; Result.Ext = Ext;
return Result; return {Result, std::move(MergeInfo)};
} }
assert(Ext->getGenericParams() && "No generic params."); assert(Ext->getGenericParams() && "No generic params.");
for (auto Req : Ext->getGenericParams()->getRequirements()){ for (auto Req : Ext->getGenericParams()->getRequirements()){
@@ -308,30 +352,61 @@ struct SynthesizedExtensionAnalyzer::Implementation {
if (First && Second) { if (First && Second) {
First = First->getDesugaredType(); First = First->getDesugaredType();
Second = Second->getDesugaredType(); Second = Second->getDesugaredType();
auto Written = Req.getAsWrittenString();
switch (Kind) { switch (Kind) {
case RequirementReprKind::TypeConstraint: case RequirementReprKind::TypeConstraint:
if(!canPossiblyConvertTo(First, Second, *DC)) if(!canPossiblyConvertTo(First, Second, *DC))
return Result; return {Result, std::move(MergeInfo)};
else if (isConvertibleTo(First, Second, *DC)) else if (isConvertibleTo(First, Second, *DC))
Result.KnownSatisfiedRequirements.push_back(Req.getAsWrittenString()); Result.KnownSatisfiedRequirements.push_back(Written);
else
MergeInfo->addRequirement(First, Second, Kind);
break; break;
case RequirementReprKind::SameType: case RequirementReprKind::SameType:
if (!canPossiblyEqual(First, Second, *DC)) if (!canPossiblyEqual(First, Second, *DC))
return Result; return {Result, std::move(MergeInfo)};
else if (isEqual(First, Second, *DC)) else if (isEqual(First, Second, *DC))
Result.KnownSatisfiedRequirements.push_back(Req.getAsWrittenString()); Result.KnownSatisfiedRequirements.push_back(Written);
else
MergeInfo->addRequirement(First, Second, Kind);
break; break;
} }
} }
} }
Result.Ext = Ext; Result.Ext = Ext;
return Result; return {Result, std::move(MergeInfo)};
}
typedef llvm::MapVector<ExtensionDecl*, std::unique_ptr<ExtensionMergeInfo>>
ExtensionMergeInfoMap;
typedef llvm::MapVector<ExtensionDecl*, unsigned> ExtensionMergeGroupMap;
void calculateMergeGroup(ExtensionMergeInfoMap &MergeInfoMap,
ExtensionMergeGroupMap &MergeGroupMap) {
std::vector<std::pair<ExtensionMergeInfo*, unsigned>> KnownGroups;
unsigned NewGroupNum = 0;
for (auto &Pair : MergeInfoMap) {
auto Key = Pair.first;
auto Found = std::find_if(KnownGroups.begin(), KnownGroups.end(),
[&](std::pair<ExtensionMergeInfo*, unsigned> LHS) {
return (*LHS.first) == (*Pair.second);
});
if (Found != KnownGroups.end()) {
MergeGroupMap[Key] = (*Found).second;
continue;
}
MergeGroupMap[Key] = NewGroupNum;
KnownGroups.push_back({Pair.second.get(), NewGroupNum});
NewGroupNum ++;
}
} }
std::unique_ptr<ExtMap> collectSynthesizedExtensionInfo() { std::unique_ptr<ExtMap> collectSynthesizedExtensionInfo() {
std::unique_ptr<ExtMap> pMap(new ExtMap()); std::unique_ptr<ExtMap> pMap(new ExtMap());
if (Target->getKind() == DeclKind::Protocol) if (Target->getKind() == DeclKind::Protocol)
return pMap; return pMap;
ExtensionMergeInfoMap MergeInfoMap;
std::vector<NominalTypeDecl*> Unhandled; std::vector<NominalTypeDecl*> Unhandled;
auto addTypeLocNominal = [&](TypeLoc TL){ auto addTypeLocNominal = [&](TypeLoc TL){
if (TL.getType()) { if (TL.getType()) {
@@ -347,21 +422,32 @@ 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()) {
if (auto Info = isApplicable(E)) if (!shouldPrint(E, Options))
(*pMap)[E] = Info; continue;
auto Pair = isApplicable(E);
if (Pair.first) {
(*pMap)[E] = Pair.first;
MergeInfoMap[E] = std::move(Pair.second);
}
for (auto TL : Back->getInherited()) { for (auto TL : Back->getInherited()) {
addTypeLocNominal(TL); addTypeLocNominal(TL);
} }
} }
} }
ExtensionMergeGroupMap GroupMap;
calculateMergeGroup(MergeInfoMap, GroupMap);
for(auto It : *pMap) {
(*pMap)[It.first].MergeGroup = GroupMap[It.first];
}
return pMap; return pMap;
} }
}; };
SynthesizedExtensionAnalyzer:: SynthesizedExtensionAnalyzer::
SynthesizedExtensionAnalyzer(NominalTypeDecl *Target, SynthesizedExtensionAnalyzer(NominalTypeDecl *Target,
PrintOptions Options,
bool IncludeUnconditional): bool IncludeUnconditional):
Impl(*(new Implementation(Target, IncludeUnconditional))) {} Impl(*(new Implementation(Target, IncludeUnconditional, Options))) {}
SynthesizedExtensionAnalyzer::~SynthesizedExtensionAnalyzer() {delete &Impl;} SynthesizedExtensionAnalyzer::~SynthesizedExtensionAnalyzer() {delete &Impl;}
@@ -381,6 +467,21 @@ forEachSynthesizedExtension(llvm::function_ref<void(ExtensionDecl*)> Fn) {
} }
} }
void SynthesizedExtensionAnalyzer::
forEachSynthesizedExtensionMergeGroup(
llvm::function_ref<void(ArrayRef<ExtensionDecl*>)> Fn) {
llvm::DenseMap<unsigned, std::vector<ExtensionDecl*>> GroupBags;
for (auto It : *Impl.Results) {
unsigned Group = It.second.MergeGroup;
if (GroupBags.find(Group) == GroupBags.end())
GroupBags[Group] = std::vector<ExtensionDecl*>();
GroupBags[Group].push_back(It.first);
}
for (auto It : GroupBags) {
Fn(llvm::makeArrayRef(It.second));
}
}
bool SynthesizedExtensionAnalyzer:: bool SynthesizedExtensionAnalyzer::
shouldPrintRequirement(ExtensionDecl *ED, StringRef Req) { shouldPrintRequirement(ExtensionDecl *ED, StringRef Req) {
auto Found = Impl.Results->find(ED); auto Found = Impl.Results->find(ED);
@@ -547,7 +648,7 @@ void ASTPrinter::printIndent() {
llvm::SmallString<16> Str; llvm::SmallString<16> Str;
for (unsigned i = 0; i != CurrentIndentation; ++i) for (unsigned i = 0; i != CurrentIndentation; ++i)
Str += ' '; Str += ' ';
printText(Str); printText(Str);
} }
@@ -865,8 +966,10 @@ private:
bool shouldPrintPattern(const Pattern *P); bool shouldPrintPattern(const Pattern *P);
void printPatternType(const Pattern *P); void printPatternType(const Pattern *P);
void printAccessors(AbstractStorageDecl *ASD); void printAccessors(AbstractStorageDecl *ASD);
void printMembersOfDecl(Decl * NTD, bool needComma = false); void printMembersOfDecl(Decl * NTD, bool needComma = false,
void printMembers(ArrayRef<Decl *> members, bool needComma = false); bool openBracket = true, bool closeBracket = true);
void printMembers(ArrayRef<Decl *> members, bool needComma = false,
bool openBracket = true, bool closeBracket = true);
void printNominalDeclGenericParams(NominalTypeDecl *decl); void printNominalDeclGenericParams(NominalTypeDecl *decl);
void printInherited(const Decl *decl, void printInherited(const Decl *decl,
ArrayRef<TypeLoc> inherited, ArrayRef<TypeLoc> inherited,
@@ -1020,7 +1123,7 @@ void PrintAST::printPattern(const Pattern *pattern) {
const auto &Elt = Fields[i]; const auto &Elt = Fields[i];
if (i != 0) if (i != 0)
Printer << ", "; Printer << ", ";
printPattern(Elt.getPattern()); printPattern(Elt.getPattern());
} }
Printer << ")"; Printer << ")";
@@ -1485,7 +1588,7 @@ void PrintAST::printAccessors(AbstractStorageDecl *ASD) {
switch (storageKind) { switch (storageKind) {
case AbstractStorageDecl::Stored: case AbstractStorageDecl::Stored:
llvm_unreachable("filtered out above!"); llvm_unreachable("filtered out above!");
case AbstractStorageDecl::StoredWithTrivialAccessors: case AbstractStorageDecl::StoredWithTrivialAccessors:
case AbstractStorageDecl::Computed: case AbstractStorageDecl::Computed:
PrintAccessor(ASD->getGetter(), "get"); PrintAccessor(ASD->getGetter(), "get");
@@ -1522,7 +1625,9 @@ void PrintAST::printAccessors(AbstractStorageDecl *ASD) {
Printer << "}"; Printer << "}";
} }
void PrintAST::printMembersOfDecl(Decl *D, bool needComma) { void PrintAST::printMembersOfDecl(Decl *D, bool needComma,
bool openBracket,
bool closeBracket) {
llvm::SmallVector<Decl *, 3> Members; llvm::SmallVector<Decl *, 3> Members;
auto AddDeclFunc = [&](DeclRange Range) { auto AddDeclFunc = [&](DeclRange Range) {
for (auto RD : Range) for (auto RD : Range)
@@ -1538,11 +1643,13 @@ void PrintAST::printMembersOfDecl(Decl *D, bool needComma) {
AddDeclFunc(Ext->getMembers()); AddDeclFunc(Ext->getMembers());
} }
} }
printMembers(Members, needComma); printMembers(Members, needComma, openBracket, closeBracket);
} }
void PrintAST::printMembers(ArrayRef<Decl *> members, bool needComma) { void PrintAST::printMembers(ArrayRef<Decl *> members, bool needComma,
Printer << " {"; bool openBracket, bool closeBracket) {
if (openBracket)
Printer << " {";
Printer.printNewline(); Printer.printNewline();
{ {
IndentRAII indentMore(*this); IndentRAII indentMore(*this);
@@ -1565,7 +1672,8 @@ void PrintAST::printMembers(ArrayRef<Decl *> members, bool needComma) {
} }
} }
indent(); indent();
Printer << "}"; if (closeBracket)
Printer << "}";
} }
void PrintAST::printNominalDeclGenericParams(NominalTypeDecl *decl) { void PrintAST::printNominalDeclGenericParams(NominalTypeDecl *decl) {
@@ -1795,27 +1903,30 @@ static void printExtendedTypeName(Type ExtendedType, ASTPrinter &Printer,
void PrintAST:: void PrintAST::
printSynthesizedExtension(NominalTypeDecl* Decl, ExtensionDecl *ExtDecl) { printSynthesizedExtension(NominalTypeDecl* Decl, ExtensionDecl *ExtDecl) {
Printer << "/// Synthesized extension from " << if (Options.TransformContext->shouldOpenExtension) {
Printer << "/// Synthesized extension from " <<
ExtDecl->getExtendedType()->getAnyNominal()->getName().str() << "\n"; ExtDecl->getExtendedType()->getAnyNominal()->getName().str() << "\n";
printDocumentationComment(ExtDecl); printDocumentationComment(ExtDecl);
printAttributes(ExtDecl); printAttributes(ExtDecl);
Printer << tok::kw_extension << " "; Printer << tok::kw_extension << " ";
printExtendedTypeName(Decl->getDeclaredType(), Printer, Options); printExtendedTypeName(Decl->getDeclaredType(), Printer, Options);
printInherited(ExtDecl); printInherited(ExtDecl);
if (auto *GPs = ExtDecl->getGenericParams()) { if (auto *GPs = ExtDecl->getGenericParams()) {
std::vector<RequirementRepr> ReqsToPrint; std::vector<RequirementRepr> ReqsToPrint;
for (auto Req : GPs->getRequirements()) { for (auto Req : GPs->getRequirements()) {
if (Options.TransformContext->shouldPrintRequirement(ExtDecl, if (Options.TransformContext->shouldPrintRequirement(ExtDecl,
Req.getAsWrittenString())) Req.getAsWrittenString()))
ReqsToPrint.push_back(Req); ReqsToPrint.push_back(Req);
}
printWhereClause(ReqsToPrint);
} }
printWhereClause(ReqsToPrint);
} }
if (Options.TypeDefinitions) { if (Options.TypeDefinitions) {
printMembersOfDecl(ExtDecl); printMembersOfDecl(ExtDecl, false,
Options.TransformContext->shouldOpenExtension,
Options.TransformContext->shouldCloseExtension);
} }
} }
@@ -1879,7 +1990,7 @@ void PrintAST::visitPatternBindingDecl(PatternBindingDecl *decl) {
} else { } else {
Printer << "let "; Printer << "let ";
} }
bool isFirst = true; bool isFirst = true;
for (auto entry : decl->getPatternList()) { for (auto entry : decl->getPatternList()) {
if (!shouldPrintPattern(entry.getPattern())) if (!shouldPrintPattern(entry.getPattern()))
@@ -1888,7 +1999,7 @@ void PrintAST::visitPatternBindingDecl(PatternBindingDecl *decl) {
isFirst = false; isFirst = false;
else else
Printer << ", "; Printer << ", ";
printPattern(entry.getPattern()); printPattern(entry.getPattern());
// We also try to print type for named patterns, e.g. var Field = 10; // We also try to print type for named patterns, e.g. var Field = 10;
@@ -2198,17 +2309,17 @@ void PrintAST::printOneParameter(const ParamDecl *param, bool Curried,
Options.ExcludeAttrList.push_back(DAK_NoEscape); Options.ExcludeAttrList.push_back(DAK_NoEscape);
if (!hasAutoClosure) if (!hasAutoClosure)
Options.ExcludeAttrList.push_back(DAK_AutoClosure); Options.ExcludeAttrList.push_back(DAK_AutoClosure);
// If the parameter is variadic, we will print the "..." after it, but we have // If the parameter is variadic, we will print the "..." after it, but we have
// to strip off the added array type. // to strip off the added array type.
if (param->isVariadic() && TheTypeLoc.getType()) { if (param->isVariadic() && TheTypeLoc.getType()) {
if (auto *BGT = TheTypeLoc.getType()->getAs<BoundGenericType>()) if (auto *BGT = TheTypeLoc.getType()->getAs<BoundGenericType>())
TheTypeLoc.setType(BGT->getGenericArgs()[0]); TheTypeLoc.setType(BGT->getGenericArgs()[0]);
} }
printTypeLoc(TheTypeLoc); printTypeLoc(TheTypeLoc);
if (param->isVariadic()) if (param->isVariadic())
Printer << "..."; Printer << "...";
@@ -2217,8 +2328,8 @@ void PrintAST::printOneParameter(const ParamDecl *param, bool Curried,
RemoveFunc(DAK_NoEscape); RemoveFunc(DAK_NoEscape);
if (!hasAutoClosure) if (!hasAutoClosure)
RemoveFunc(DAK_AutoClosure); RemoveFunc(DAK_AutoClosure);
if (Options.PrintDefaultParameterPlaceholder && if (Options.PrintDefaultParameterPlaceholder &&
param->isDefaultArgument()) { param->isDefaultArgument()) {
Printer << " = "; Printer << " = ";
@@ -2237,7 +2348,7 @@ void PrintAST::printParameterList(ParameterList *PL, bool isCurried,
for (unsigned i = 0, e = PL->size(); i != e; ++i) { for (unsigned i = 0, e = PL->size(); i != e; ++i) {
if (i > 0) if (i > 0)
Printer << ", "; Printer << ", ";
printOneParameter(PL->get(i), isCurried, isAPINameByDefault(i)); printOneParameter(PL->get(i), isCurried, isAPINameByDefault(i));
} }
Printer << ")"; Printer << ")";
@@ -2503,7 +2614,7 @@ void PrintAST::visitConstructorDecl(ConstructorDecl *decl) {
} else if (decl->getInitKind() == CtorInitializerKind::Factory) { } else if (decl->getInitKind() == CtorInitializerKind::Factory) {
Printer << "/*not inherited*/ "; Printer << "/*not inherited*/ ";
} }
recordDeclLoc(decl, recordDeclLoc(decl,
[&]{ [&]{
Printer << "init"; Printer << "init";
@@ -2511,7 +2622,7 @@ void PrintAST::visitConstructorDecl(ConstructorDecl *decl) {
switch (decl->getFailability()) { switch (decl->getFailability()) {
case OTK_None: case OTK_None:
break; break;
case OTK_Optional: case OTK_Optional:
Printer << "?"; Printer << "?";
break; break;
@@ -2526,7 +2637,7 @@ void PrintAST::visitConstructorDecl(ConstructorDecl *decl) {
printFunctionParameters(decl); printFunctionParameters(decl);
}); });
if (!Options.FunctionDefinitions || !decl->getBody()) { if (!Options.FunctionDefinitions || !decl->getBody()) {
return; return;
} }
@@ -2877,7 +2988,7 @@ void Pattern::print(llvm::raw_ostream &OS, const PrintOptions &Options) const {
namespace { namespace {
class TypePrinter : public TypeVisitor<TypePrinter> { class TypePrinter : public TypeVisitor<TypePrinter> {
using super = TypeVisitor; using super = TypeVisitor;
ASTPrinter &Printer; ASTPrinter &Printer;
const PrintOptions &Options; const PrintOptions &Options;
Optional<std::vector<GenericParamList *>> UnwrappedGenericParams; Optional<std::vector<GenericParamList *>> UnwrappedGenericParams;
@@ -2917,7 +3028,7 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
case DeclContextKind::AbstractFunctionDecl: case DeclContextKind::AbstractFunctionDecl:
visit(cast<AbstractFunctionDecl>(DC)->getType()); visit(cast<AbstractFunctionDecl>(DC)->getType());
return; return;
case DeclContextKind::SubscriptDecl: case DeclContextKind::SubscriptDecl:
visit(cast<SubscriptDecl>(DC)->getType()); visit(cast<SubscriptDecl>(DC)->getType());
return; return;
@@ -3040,7 +3151,7 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
public: public:
TypePrinter(ASTPrinter &Printer, const PrintOptions &PO) TypePrinter(ASTPrinter &Printer, const PrintOptions &PO)
: Printer(Printer), Options(PO) {} : Printer(Printer), Options(PO) {}
void visit(Type T) { void visit(Type T) {
Printer.printTypePre(TypeLoc::withoutLoc(T)); Printer.printTypePre(TypeLoc::withoutLoc(T));
defer { Printer.printTypePost(TypeLoc::withoutLoc(T)); }; defer { Printer.printTypePost(TypeLoc::withoutLoc(T)); };
@@ -3082,7 +3193,7 @@ public:
void visitBuiltinBridgeObjectType(BuiltinBridgeObjectType *T) { void visitBuiltinBridgeObjectType(BuiltinBridgeObjectType *T) {
Printer << "Builtin.BridgeObject"; Printer << "Builtin.BridgeObject";
} }
void visitBuiltinUnsafeValueBufferType(BuiltinUnsafeValueBufferType *T) { void visitBuiltinUnsafeValueBufferType(BuiltinUnsafeValueBufferType *T) {
Printer << "Builtin.UnsafeValueBuffer"; Printer << "Builtin.UnsafeValueBuffer";
} }
@@ -3303,7 +3414,7 @@ public:
else if (info.isNoEscape() && !IsAttrExcluded(DAK_NoEscape)) else if (info.isNoEscape() && !IsAttrExcluded(DAK_NoEscape))
// autoclosure implies noescape. // autoclosure implies noescape.
Printer << "@noescape "; Printer << "@noescape ";
if (Options.PrintFunctionRepresentationAttrs) { if (Options.PrintFunctionRepresentationAttrs) {
// TODO: coalesce into a single convention attribute. // TODO: coalesce into a single convention attribute.
switch (info.getSILRepresentation()) { switch (info.getSILRepresentation()) {
@@ -3374,10 +3485,10 @@ public:
printFunctionExtInfo(T->getExtInfo()); printFunctionExtInfo(T->getExtInfo());
printWithParensIfNotSimple(T->getInput()); printWithParensIfNotSimple(T->getInput());
if (T->throws()) if (T->throws())
Printer << " " << tok::kw_throws; Printer << " " << tok::kw_throws;
Printer << " -> "; Printer << " -> ";
Printer.callPrintStructurePre(PrintStructureKind::FunctionReturnType); Printer.callPrintStructurePre(PrintStructureKind::FunctionReturnType);
@@ -3435,7 +3546,7 @@ public:
// Return the max valid depth of firstType and secondType. // Return the max valid depth of firstType and secondType.
unsigned firstDepth = getDepthOfType(req.getFirstType()); unsigned firstDepth = getDepthOfType(req.getFirstType());
unsigned secondDepth = getDepthOfType(req.getSecondType()); unsigned secondDepth = getDepthOfType(req.getSecondType());
unsigned maxDepth; unsigned maxDepth;
if (firstDepth == ErrorDepth && secondDepth != ErrorDepth) if (firstDepth == ErrorDepth && secondDepth != ErrorDepth)
maxDepth = secondDepth; maxDepth = secondDepth;
@@ -3443,7 +3554,7 @@ public:
maxDepth = firstDepth; maxDepth = firstDepth;
else else
maxDepth = std::max(firstDepth, secondDepth); maxDepth = std::max(firstDepth, secondDepth);
return maxDepth; return maxDepth;
} }
} }
@@ -3473,7 +3584,7 @@ public:
// Collect requirements for this level. // Collect requirements for this level.
// Because of same-type requirements, these aren't well-ordered. // Because of same-type requirements, these aren't well-ordered.
SmallVector<Requirement, 2> requirementsAtDepth; SmallVector<Requirement, 2> requirementsAtDepth;
for (auto reqt : requirements) { for (auto reqt : requirements) {
unsigned currentDepth = getDepthOfRequirement(reqt); unsigned currentDepth = getDepthOfRequirement(reqt);
// Collect requirements at the current depth. // Collect requirements at the current depth.
@@ -3487,7 +3598,7 @@ public:
printSingleDepthOfGenericSignature( printSingleDepthOfGenericSignature(
genericParams.slice(paramIdx, lastParamIdx - paramIdx), genericParams.slice(paramIdx, lastParamIdx - paramIdx),
requirementsAtDepth); requirementsAtDepth);
paramIdx = lastParamIdx; paramIdx = lastParamIdx;
} }
} }
@@ -3616,7 +3727,7 @@ public:
if (totalResults != 1) Printer << ")"; if (totalResults != 1) Printer << ")";
} }
void visitSILBlockStorageType(SILBlockStorageType *T) { void visitSILBlockStorageType(SILBlockStorageType *T) {
Printer << "@block_storage "; Printer << "@block_storage ";
printWithParensIfNotSimple(T->getCaptureType()); printWithParensIfNotSimple(T->getCaptureType());
@@ -3774,7 +3885,7 @@ public:
Printer << "$T" << T->getID(); Printer << "$T" << T->getID();
return; return;
} }
Printer << "_"; Printer << "_";
} }
}; };
@@ -3928,10 +4039,10 @@ void ProtocolConformance::printName(llvm::raw_ostream &os,
os << ' '; os << ' ';
} }
} }
getType()->print(os, PO); getType()->print(os, PO);
os << ": "; os << ": ";
switch (getKind()) { switch (getKind()) {
case ProtocolConformanceKind::Normal: { case ProtocolConformanceKind::Normal: {
auto normal = cast<NormalProtocolConformance>(this); auto normal = cast<NormalProtocolConformance>(this);

View File

@@ -479,15 +479,22 @@ void swift::ide::printSubmoduleInterface(
continue; continue;
// Print synthesized extensions. // Print synthesized extensions.
SynthesizedExtensionAnalyzer Analyzer(NTD); SynthesizedExtensionAnalyzer Analyzer(NTD, AdjustedOptions);
AdjustedOptions.initArchetypeTransformerForSynthesizedExtensions(NTD, AdjustedOptions.initArchetypeTransformerForSynthesizedExtensions(NTD,
&Analyzer); &Analyzer);
Analyzer.forEachSynthesizedExtension([&](ExtensionDecl *ET){ Analyzer.forEachSynthesizedExtensionMergeGroup(
if (!shouldPrint(ET, AdjustedOptions)) [&](ArrayRef<ExtensionDecl*> Decls){
return; for (auto ET : Decls) {
Printer << "\n"; AdjustedOptions.TransformContext->shouldOpenExtension =
ET->print(Printer, AdjustedOptions); Decls.front() == ET;
Printer << "\n"; AdjustedOptions.TransformContext->shouldCloseExtension =
Decls.back() == ET;
if (AdjustedOptions.TransformContext->shouldOpenExtension)
Printer << "\n";
ET->print(Printer, AdjustedOptions);
if (AdjustedOptions.TransformContext->shouldCloseExtension)
Printer << "\n";
}
}); });
AdjustedOptions.clearArchetypeTransformerForSynthesizedExtensions(); AdjustedOptions.clearArchetypeTransformerForSynthesizedExtensions();
} }

View File

@@ -123,68 +123,53 @@ public struct S10 : P1 {
} }
} }
// CHECK: <synthesized>/// Synthesized extension from P2 // CHECK: <synthesized>/// Synthesized extension from P2
// CHECK-NEXT: extension <ref:Struct>S1</ref> where T : P2 {
// CHECK-NEXT: <decl:Func>public func <loc>p2member()</loc></decl>
// CHECK-NEXT: }</synthesized>
// CHECK: <synthesized>/// Synthesized extension from P1
// CHECK-NEXT: extension <ref:Struct>S1</ref> where T == Int {
// CHECK-NEXT: <decl:Func>public func <loc>p1IntFunc(<decl:Param>i: <ref:Struct>Int</ref></decl>)</loc> -> <ref:Struct>Int</ref></decl>
// CHECK-NEXT: }</synthesized>
// CHECK: <synthesized>/// Synthesized extension from P1
// CHECK-NEXT: extension <ref:Struct>S1</ref> where T : P3 {
// CHECK-NEXT: <decl:Func>public func <loc>p3Func(<decl:Param>i: <ref:Struct>Int</ref></decl>)</loc> -> <ref:Struct>Int</ref></decl>
// CHECK-NEXT: }</synthesized>
// CHECK: <synthesized>/// Synthesized extension from P1
// CHECK-NEXT: extension <ref:Struct>S1</ref> where T : P2 { // CHECK-NEXT: extension <ref:Struct>S1</ref> where T : P2 {
// CHECK-NEXT: <decl:Func>public func <loc>p2member()</loc></decl></synthesized>
// CHECK-NEXT: <synthesized>
// CHECK-NEXT: <decl:Func>public func <loc>ef1(<decl:Param>t: T</decl>)</loc></decl> // CHECK-NEXT: <decl:Func>public func <loc>ef1(<decl:Param>t: T</decl>)</loc></decl>
// CHECK-NEXT: <decl:Func>public func <loc>ef2(<decl:Param>t: <ref:Struct>S2</ref></decl>)</loc></decl> // CHECK-NEXT: <decl:Func>public func <loc>ef2(<decl:Param>t: <ref:Struct>S2</ref></decl>)</loc></decl>
// CHECK-NEXT: }</synthesized> // CHECK-NEXT: }</synthesized>
// CHECK: <synthesized>/// Synthesized extension from P1 // CHECK: <synthesized>/// Synthesized extension from P1
// CHECK-NEXT: extension <ref:Struct>S1</ref> where T : P3 {
// CHECK-NEXT: <decl:Func>public func <loc>p3Func(<decl:Param>i: <ref:Struct>Int</ref></decl>)</loc> -> <ref:Struct>Int</ref></decl>
// CHECK-NEXT: }</synthesized>
// CHECK: <synthesized>/// Synthesized extension from P1
// CHECK-NEXT: extension <ref:Struct>S1</ref> where T == Int {
// CHECK-NEXT: <decl:Func>public func <loc>p1IntFunc(<decl:Param>i: <ref:Struct>Int</ref></decl>)</loc> -> <ref:Struct>Int</ref></decl>
// CHECK-NEXT: }</synthesized>
// CHECK: <synthesized>/// Synthesized extension from P1
// CHECK-NEXT: extension <ref:Struct>S1</ref> where T == S9<Int> { // CHECK-NEXT: extension <ref:Struct>S1</ref> where T == S9<Int> {
// CHECK-NEXT: <decl:Func>public func <loc>S9IntFunc()</loc></decl> // CHECK-NEXT: <decl:Func>public func <loc>S9IntFunc()</loc></decl>
// CHECK-NEXT: }</synthesized> // CHECK-NEXT: }</synthesized>
// CHECK: <synthesized>/// Synthesized extension from P1 // CHECK: <synthesized>/// Synthesized extension from P1
// CHECK-NEXT: extension <ref:Struct>S10</ref> {
// CHECK-NEXT: <decl:Func>public func <loc>p3Func(<decl:Param>i: <ref:Struct>Int</ref></decl>)</loc> -> <ref:Struct>Int</ref></decl>
// CHECK-NEXT: }</synthesized>
// CHECK: <synthesized>/// Synthesized extension from P1
// CHECK-NEXT: extension <ref:Struct>S10</ref> {
// CHECK-NEXT: <decl:Func>public func <loc>ef5(<decl:Param>t: <ref:Struct>S9</ref><<ref:Struct>Int</ref>></decl>)</loc></decl>
// CHECK-NEXT: }</synthesized>
// CHECK: <synthesized>/// Synthesized extension from P1
// CHECK-NEXT: extension <ref:Struct>S10</ref> { // CHECK-NEXT: extension <ref:Struct>S10</ref> {
// CHECK-NEXT: <decl:Func>public func <loc>p3Func(<decl:Param>i: <ref:Struct>Int</ref></decl>)</loc> -> <ref:Struct>Int</ref></decl></synthesized>
// CHECK-NEXT: <synthesized>
// CHECK-NEXT: <decl:Func>public func <loc>ef5(<decl:Param>t: <ref:Struct>S9</ref><<ref:Struct>Int</ref>></decl>)</loc></decl></synthesized>
// CHECK-NEXT: <synthesized>
// CHECK-NEXT: <decl:Func>public func <loc>S9IntFunc()</loc></decl> // CHECK-NEXT: <decl:Func>public func <loc>S9IntFunc()</loc></decl>
// CHECK-NEXT: }</synthesized> // CHECK-NEXT: }</synthesized>
// CHECK: <synthesized>/// Synthesized extension from P1 // CHECK: <synthesized>/// Synthesized extension from P1
// CHECK-NEXT: extension <ref:Struct>S4</ref> { // CHECK-NEXT: extension <ref:Struct>S4</ref> {
// CHECK-NEXT: <decl:Func>public func <loc>p1IntFunc(<decl:Param>i: <ref:Struct>Int</ref></decl>)</loc> -> <ref:Struct>Int</ref></decl> // CHECK-NEXT: <decl:Func>public func <loc>p1IntFunc(<decl:Param>i: <ref:Struct>Int</ref></decl>)</loc> -> <ref:Struct>Int</ref></decl>
// CHECK-NEXT: }</synthesized> // CHECK-NEXT: }</synthesized>
// CHECK: <synthesized>/// Synthesized extension from P1 // CHECK: <synthesized>/// Synthesized extension from P1
// CHECK-NEXT: extension <ref:Struct>S6</ref> {
// CHECK-NEXT: <decl:Func>public func <loc>p3Func(<decl:Param>i: <ref:Struct>Int</ref></decl>)</loc> -> <ref:Struct>Int</ref></decl>
// CHECK-NEXT: }</synthesized>
// CHECK: <synthesized>/// Synthesized extension from P1
// CHECK-NEXT: extension <ref:Struct>S6</ref> { // CHECK-NEXT: extension <ref:Struct>S6</ref> {
// CHECK-NEXT: <decl:Func>public func <loc>p3Func(<decl:Param>i: <ref:Struct>Int</ref></decl>)</loc> -> <ref:Struct>Int</ref></decl></synthesized>
// CHECK-NEXT: <synthesized>
// CHECK-NEXT: <decl:Func>public func <loc>ef5(<decl:Param>t: <ref:Struct>S5</ref></decl>)</loc></decl> // CHECK-NEXT: <decl:Func>public func <loc>ef5(<decl:Param>t: <ref:Struct>S5</ref></decl>)</loc></decl>
// CHECK-NEXT: }</synthesized> // CHECK-NEXT: }</synthesized>
// CHECK: <synthesized>/// Synthesized extension from P1 // CHECK: <synthesized>/// Synthesized extension from P1
// CHECK-NEXT: extension <ref:module>print_synthesized_extensions</ref>.<ref:Struct>S7</ref>.<ref:Struct>S8</ref> {
// CHECK-NEXT: <decl:Func>public func <loc>p3Func(<decl:Param>i: <ref:Struct>Int</ref></decl>)</loc> -> <ref:Struct>Int</ref></decl>
// CHECK-NEXT: }</synthesized>
// CHECK: <synthesized>/// Synthesized extension from P1
// CHECK-NEXT: extension <ref:module>print_synthesized_extensions</ref>.<ref:Struct>S7</ref>.<ref:Struct>S8</ref> { // CHECK-NEXT: extension <ref:module>print_synthesized_extensions</ref>.<ref:Struct>S7</ref>.<ref:Struct>S8</ref> {
// CHECK-NEXT: <decl:Func>public func <loc>p3Func(<decl:Param>i: <ref:Struct>Int</ref></decl>)</loc> -> <ref:Struct>Int</ref></decl></synthesized>
// CHECK-NEXT: <synthesized>
// CHECK-NEXT: <decl:Func>public func <loc>ef5(<decl:Param>t: <ref:Struct>S5</ref></decl>)</loc></decl> // CHECK-NEXT: <decl:Func>public func <loc>ef5(<decl:Param>t: <ref:Struct>S5</ref></decl>)</loc></decl>
// CHECK-NEXT: }</synthesized> // CHECK-NEXT: }</synthesized>

View File

@@ -594,7 +594,8 @@ static bool passCursorInfoForDecl(const ValueDecl *VD,
bool InSynthesizedExtension = false; bool InSynthesizedExtension = false;
if (BaseType) { if (BaseType) {
if(auto Target = BaseType->getAnyNominal()) { if(auto Target = BaseType->getAnyNominal()) {
SynthesizedExtensionAnalyzer Analyzer(Target); SynthesizedExtensionAnalyzer Analyzer(Target,
PrintOptions::printInterface());
InSynthesizedExtension = Analyzer.isInSynthesizedExtension(VD); InSynthesizedExtension = Analyzer.isInSynthesizedExtension(VD);
} }
} }