void populateMergeGroup(ExtensionInfoMap &InfoMap, ExtensionMergeInfoMap &MergeInfoMap, MergeGroupVector &Results, bool AllowMergeWithDefBody) { for (auto &Pair : InfoMap) { ExtensionDecl *ED = Pair.first; ExtensionMergeInfo &MergeInfo = MergeInfoMap[ED]; SynthesizedExtensionInfo &ExtInfo = InfoMap[ED]; auto Found = std::find_if(Results.begin(), Results.end(), [&](ExtensionMergeGroup &Group) { return MergeInfo == MergeInfoMap[Group.Members.front()->Ext]; }); if (Found == Results.end()) { Results.push_back({&ExtInfo, (unsigned)MergeInfo.Requirements.size(), MergeInfo.InheritsCount, AllowMergeWithDefBody && MergeInfo.isMergeableWithTypeDef()}); } else { Found->Members.push_back(&ExtInfo); } } }
std::unique_ptr<ExtensionInfoMap> collectSynthesizedExtensionInfoForProtocol(MergeGroupVector &AllGroups) { std::unique_ptr<ExtensionInfoMap> InfoMap(new ExtensionInfoMap()); ExtensionMergeInfoMap MergeInfoMap; for (auto *E : Target->getExtensions()) { if (!Options.shouldPrint(E)) continue; auto Pair = isApplicable(E, /*Synthesized*/false); if (Pair.first) { InfoMap->insert({E, Pair.first}); MergeInfoMap.insert({E, Pair.second}); } } populateMergeGroup(*InfoMap, MergeInfoMap, AllGroups, /*AllowMergeWithDefBody*/false); std::sort(AllGroups.begin(), AllGroups.end()); for (auto &Group : AllGroups) { Group.sortMembers(); } return InfoMap; }
std::unique_ptr<ExtensionInfoMap> collectSynthesizedExtensionInfo(MergeGroupVector &AllGroups) { if (isa<ProtocolDecl>(Target)) { return collectSynthesizedExtensionInfoForProtocol(AllGroups); } std::unique_ptr<ExtensionInfoMap> InfoMap(new ExtensionInfoMap()); ExtensionMergeInfoMap MergeInfoMap; std::vector<NominalTypeDecl*> Unhandled; auto handleExtension = [&](ExtensionDecl *E, bool Synthesized, ExtensionDecl *EnablingE, NormalProtocolConformance *Conf) { if (Options.shouldPrint(E)) { auto Pair = isApplicable(E, Synthesized, EnablingE, Conf); if (Pair.first) { InfoMap->insert({E, Pair.first}); MergeInfoMap.insert({E, Pair.second}); } } }; for (auto *Conf : Target->getLocalConformances()) { Unhandled.push_back(Conf->getProtocol()); } if (auto *CD = dyn_cast<ClassDecl>(Target)) { if (auto Super = CD->getSuperclassDecl()) Unhandled.push_back(Super); } while (!Unhandled.empty()) { NominalTypeDecl* Back = Unhandled.back(); Unhandled.pop_back(); for (ExtensionDecl *E : Back->getExtensions()) { handleExtension(E, true, nullptr, nullptr); } for (auto *Conf : Back->getLocalConformances()) { Unhandled.push_back(Conf->getProtocol()); } if (auto *CD = dyn_cast<ClassDecl>(Back)) { if (auto Super = CD->getSuperclass()) Unhandled.push_back(Super->getAnyNominal()); } } // Merge with actual extensions. for (auto *EnablingE : Target->getExtensions()) { handleExtension(EnablingE, false, nullptr, nullptr); for (auto *Conf : EnablingE->getLocalConformances()) { for (auto E : Conf->getProtocol()->getExtensions()) handleExtension(E, true, EnablingE, Conf->getRootNormalConformance()); } } populateMergeGroup(*InfoMap, MergeInfoMap, AllGroups, /*AllowMergeWithDefBody*/true); std::sort(AllGroups.begin(), AllGroups.end()); for (auto &Group : AllGroups) { Group.removeUnfavored(Target); Group.sortMembers(); } AllGroups.erase(std::remove_if(AllGroups.begin(), AllGroups.end(), [](ExtensionMergeGroup &Group) { return Group.Members.empty(); }), AllGroups.end()); return InfoMap; }