mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Merge exported modules with the same public name in generated interface
If a module has the same `public-module-name` as the module being generated and its import is exported, merge it into the same generated interface. Fix various always-imported modules from being printed while here and update all the tests that checked for them. Resolves rdar://137887712.
This commit is contained in:
@@ -304,6 +304,34 @@ static bool compareSwiftDecls(Decl *LHS, Decl *RHS) {
|
||||
return LHS->getKind() < RHS->getKind();
|
||||
}
|
||||
|
||||
static bool shouldPrintImport(ImportDecl *ImportD, ModuleDecl *OrigMod,
|
||||
const clang::Module *OrigClangMod) {
|
||||
if (ImportD->getAttrs().hasAttribute<ImplementationOnlyAttr>())
|
||||
return false;
|
||||
|
||||
auto *ImportedMod = ImportD->getModule();
|
||||
if (ImportedMod) {
|
||||
if (ImportedMod == OrigMod)
|
||||
return false;
|
||||
if (ImportedMod->isOnoneSupportModule())
|
||||
return false;
|
||||
if (ImportedMod->getName().hasUnderscoredNaming())
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!OrigClangMod)
|
||||
return true;
|
||||
|
||||
auto ImportedClangMod = ImportD->getClangModule();
|
||||
if (!ImportedClangMod)
|
||||
return true;
|
||||
if (!ImportedClangMod->isSubModule())
|
||||
return true;
|
||||
if (ImportedClangMod == OrigClangMod)
|
||||
return false;
|
||||
return ImportedClangMod->isSubModuleOf(OrigClangMod);
|
||||
}
|
||||
|
||||
static std::pair<ArrayRef<Decl*>, ArrayRef<Decl*>>
|
||||
getDeclsFromCrossImportOverlay(ModuleDecl *Overlay, ModuleDecl *Declaring,
|
||||
SmallVectorImpl<Decl *> &Decls,
|
||||
@@ -329,7 +357,8 @@ getDeclsFromCrossImportOverlay(ModuleDecl *Overlay, ModuleDecl *Declaring,
|
||||
|
||||
// Ignore imports of the underlying module, or any cross-import
|
||||
// that would map back to it.
|
||||
if (Imported == Declaring || Imported->isCrossImportOverlayOf(Declaring))
|
||||
if (!shouldPrintImport(ID, Declaring, nullptr) ||
|
||||
Imported->isCrossImportOverlayOf(Declaring))
|
||||
return false;
|
||||
|
||||
// Ignore an imports of modules also imported by the underlying module.
|
||||
@@ -457,19 +486,40 @@ void swift::ide::printModuleInterface(
|
||||
auto AdjustedOptions = Options;
|
||||
adjustPrintOptions(AdjustedOptions);
|
||||
|
||||
llvm::DenseSet<const void *> SeenImportedDecls;
|
||||
SmallVector<ModuleDecl *, 1> ModuleList;
|
||||
ModuleList.push_back(TargetMod);
|
||||
SeenImportedDecls.insert(TargetMod);
|
||||
|
||||
SmallVector<ImportDecl *, 1> ImportDecls;
|
||||
llvm::DenseSet<const clang::Module *> ClangModulesForImports;
|
||||
SmallVector<Decl *, 1> SwiftDecls;
|
||||
SmallVector<ImportDecl *, 0> ImportDecls;
|
||||
SmallVector<Decl *, 0> SwiftDecls;
|
||||
llvm::DenseMap<const clang::Module *,
|
||||
SmallVector<std::pair<Decl *, clang::SourceLocation>, 1>>
|
||||
ClangDecls;
|
||||
SmallVector<std::pair<Decl *, clang::SourceLocation>, 0>>
|
||||
ClangDecls;
|
||||
|
||||
// Add exported modules that have the same public module name as this module
|
||||
// (excluding the underlying clang module if there is one).
|
||||
if (TraversalOptions & ModuleTraversal::VisitMatchingExported) {
|
||||
SmallVector<ImportedModule> Imports;
|
||||
TargetMod->getImportedModules(Imports,
|
||||
ModuleDecl::ImportFilterKind::Exported);
|
||||
for (ImportedModule Import : Imports) {
|
||||
if (Import.importedModule->getPublicModuleName(
|
||||
/*onlyIfImported=*/false) != TargetMod->getName())
|
||||
continue;
|
||||
|
||||
if (TargetClangMod != nullptr &&
|
||||
Import.importedModule->findUnderlyingClangModule() == TargetClangMod)
|
||||
continue;
|
||||
|
||||
ModuleList.push_back(Import.importedModule);
|
||||
SeenImportedDecls.insert(Import.importedModule);
|
||||
}
|
||||
}
|
||||
|
||||
// If we're printing recursively, find all of the submodules to print.
|
||||
if (TargetClangMod) {
|
||||
if (TraversalOptions) {
|
||||
// Add clang submodules if they're being visited
|
||||
if (TraversalOptions & ModuleTraversal::VisitSubmodules) {
|
||||
SmallVector<const clang::Module *, 8> Worklist;
|
||||
SmallPtrSet<const clang::Module *, 8> Visited;
|
||||
Worklist.push_back(TargetClangMod);
|
||||
@@ -482,16 +532,15 @@ void swift::ide::printModuleInterface(
|
||||
|
||||
ClangDecls.insert({ CM, {} });
|
||||
|
||||
if (CM != TargetClangMod)
|
||||
if (auto *OwningModule = Importer.getWrapperForModule(CM))
|
||||
if (CM != TargetClangMod) {
|
||||
if (auto *OwningModule = Importer.getWrapperForModule(CM)) {
|
||||
ModuleList.push_back(OwningModule);
|
||||
}
|
||||
}
|
||||
|
||||
// If we're supposed to visit submodules, add them now.
|
||||
if (TraversalOptions & ModuleTraversal::VisitSubmodules) {
|
||||
for (clang::Module * submodule: CM->submodules()) {
|
||||
if (Visited.insert(submodule).second) {
|
||||
Worklist.push_back(submodule);
|
||||
}
|
||||
for (clang::Module *submodule : CM->submodules()) {
|
||||
if (Visited.insert(submodule).second) {
|
||||
Worklist.push_back(submodule);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -500,8 +549,7 @@ void swift::ide::printModuleInterface(
|
||||
}
|
||||
}
|
||||
|
||||
SmallVector<Decl *, 1> Decls;
|
||||
|
||||
SmallVector<Decl *, 0> Decls;
|
||||
for (ModuleDecl *M : ModuleList) {
|
||||
swift::getTopLevelDeclsForDisplay(M, Decls);
|
||||
}
|
||||
@@ -527,42 +575,38 @@ void swift::ide::printModuleInterface(
|
||||
continue;
|
||||
}
|
||||
|
||||
auto ShouldPrintImport = [&](ImportDecl *ImportD) -> bool {
|
||||
if (ImportD->getAttrs().hasAttribute<ImplementationOnlyAttr>())
|
||||
return false;
|
||||
|
||||
if (!TargetClangMod)
|
||||
return true;
|
||||
if (ImportD->getModule() == TargetMod)
|
||||
return false;
|
||||
|
||||
auto ImportedMod = ImportD->getClangModule();
|
||||
if (!ImportedMod)
|
||||
return true;
|
||||
if (!ImportedMod->isSubModule())
|
||||
return true;
|
||||
if (ImportedMod == TargetClangMod)
|
||||
return false;
|
||||
return ImportedMod->isSubModuleOf(TargetClangMod);
|
||||
};
|
||||
|
||||
if (auto ID = dyn_cast<ImportDecl>(D)) {
|
||||
if (ShouldPrintImport(ID)) {
|
||||
if (ID->getClangModule())
|
||||
// Erase those submodules that are not missing.
|
||||
NoImportSubModules.erase(ID->getClangModule());
|
||||
if (ID->getImportKind() == ImportKind::Module) {
|
||||
// Make sure we don't print duplicate imports, due to getting imports
|
||||
// for both a clang module and its overlay.
|
||||
if (auto *ClangMod = getUnderlyingClangModuleForImport(ID)) {
|
||||
auto P = ClangModulesForImports.insert(ClangMod);
|
||||
bool IsNew = P.second;
|
||||
if (!IsNew)
|
||||
continue;
|
||||
}
|
||||
if (!shouldPrintImport(ID, TargetMod, TargetClangMod))
|
||||
continue;
|
||||
|
||||
// Erase submodules that are not missing
|
||||
if (ID->getClangModule())
|
||||
NoImportSubModules.erase(ID->getClangModule());
|
||||
|
||||
if (ID->getImportKind() == ImportKind::Module) {
|
||||
// Could have a duplicate import from a clang module's overlay or
|
||||
// because we're merging modules. Skip them.
|
||||
|
||||
if (auto *ClangMod = getUnderlyingClangModuleForImport(ID)) {
|
||||
if (!SeenImportedDecls.insert(ClangMod).second)
|
||||
continue;
|
||||
}
|
||||
ImportDecls.push_back(ID);
|
||||
|
||||
if (auto *ImportedMod = ID->getModule()) {
|
||||
if (!SeenImportedDecls.insert(ImportedMod).second)
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
bool AnyNewDecls = false;
|
||||
for (auto *ImportedDecl : ID->getDecls()) {
|
||||
AnyNewDecls |= SeenImportedDecls.insert(ImportedDecl).second;
|
||||
}
|
||||
if (!AnyNewDecls)
|
||||
continue;
|
||||
}
|
||||
|
||||
ImportDecls.push_back(ID);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -684,9 +728,12 @@ void swift::ide::printModuleInterface(
|
||||
|
||||
// Imports from the stdlib are internal details that don't need to be exposed.
|
||||
if (!TargetMod->isStdlibModule()) {
|
||||
for (auto *D : ImportDecls)
|
||||
for (auto *D : ImportDecls) {
|
||||
PrintDecl(D);
|
||||
Printer.printNewline();
|
||||
}
|
||||
if (!ImportDecls.empty()) {
|
||||
Printer.printNewline();
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user