void findExtensionsFromConformingProtocols(Decl *D, llvm::SmallPtrSetImpl<ExtensionDecl*> &Results) { NominalTypeDecl* NTD = dyn_cast<NominalTypeDecl>(D); if (!NTD || NTD->getKind() == DeclKind::Protocol) return; std::vector<NominalTypeDecl*> Unhandled; auto addTypeLocNominal = [&](TypeLoc TL){ if (TL.getType()) { if (auto D = TL.getType()->getAnyNominal()) { Unhandled.push_back(D); } } }; for (auto TL : NTD->getInherited()) { addTypeLocNominal(TL); } while(!Unhandled.empty()) { NominalTypeDecl* Back = Unhandled.back(); Unhandled.pop_back(); for (ExtensionDecl *E : Back->getExtensions()) { if(E->isConstrainedExtension()) Results.insert(E); for (auto TL : Back->getInherited()) { addTypeLocNominal(TL); } } } }
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; }