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);
      }
    }
  }
}
Esempio n. 2
0
 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;
 }
Esempio n. 3
0
  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;
  }