add support to getTopLevelDecls for clang submodules (#76401)

rdar://126031510
This commit is contained in:
QuietMisdreavus
2025-01-30 09:39:58 -07:00
committed by GitHub
parent b3275d9db3
commit ab26b8b9d7
23 changed files with 693 additions and 277 deletions

View File

@@ -17,6 +17,7 @@
#include "swift/AST/Module.h"
#include "swift/AST/NameLookup.h"
#include "swift/Sema/IDETypeChecking.h"
#include "clang/Basic/Module.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/JSON.h"
#include "llvm/Support/Path.h"
@@ -30,14 +31,16 @@ namespace {
int serializeSymbolGraph(SymbolGraph &SG,
const SymbolGraphOptions &Options) {
SmallString<256> FileName;
FileName.append(SG.M.getNameStr());
FileName.append(getFullModuleName(&SG.M));
if (SG.ExtendedModule.has_value()) {
FileName.push_back('@');
FileName.append(SG.ExtendedModule.value()->getNameStr());
// FileName.append(SG.ExtendedModule.value()->getNameStr());
FileName.append(getFullModuleName(SG.ExtendedModule.value()));
} else if (SG.DeclaringModule.has_value()) {
// Treat cross-import overlay modules as "extensions" of their declaring module
FileName.push_back('@');
FileName.append(SG.DeclaringModule.value()->getNameStr());
// FileName.append(SG.DeclaringModule.value()->getNameStr());
FileName.append(getFullModuleName(SG.DeclaringModule.value()));
}
FileName.append(".symbols.json");
@@ -62,18 +65,60 @@ int symbolgraphgen::emitSymbolGraphForModule(
ModuleDecl *M, const SymbolGraphOptions &Options) {
ModuleDecl::ImportCollector importCollector(Options.MinimumAccessLevel);
auto importFilter = [&Options](const ModuleDecl *module) {
if (!module)
return false;
SmallPtrSet<const clang::Module *, 2> ExportedClangModules = {};
SmallPtrSet<const clang::Module *, 2> WildcardExportClangModules = {};
if (const auto *ClangModule = M->findUnderlyingClangModule()) {
// Scan through the Clang module's exports and collect them for later
// handling
for (auto ClangExport : ClangModule->Exports) {
if (ClangExport.getInt()) {
// Blanket exports are represented as a true boolean tag
if (const auto *ExportParent = ClangExport.getPointer()) {
// If a pointer is present, this is a scoped blanket export, like
// `export Submodule.*`
WildcardExportClangModules.insert(ExportParent);
} else {
// Otherwise it represents a full blanket `export *`
WildcardExportClangModules.insert(ClangModule);
}
} else if (!ClangExport.getInt() && ClangExport.getPointer()) {
// This is an explicit `export Submodule`
ExportedClangModules.insert(ClangExport.getPointer());
}
}
if (ExportedClangModules.empty() && WildcardExportClangModules.empty()) {
// HACK: In the absence of an explicit export declaration, export all of the submodules.
WildcardExportClangModules.insert(ClangModule);
}
}
auto importFilter = [&Options, &WildcardExportClangModules,
&ExportedClangModules](const ModuleDecl *module) {
if (!module)
return false;
if (const auto *ClangModule = module->findUnderlyingClangModule()) {
if (ExportedClangModules.contains(ClangModule)) {
return true;
}
for (const auto *ClangParent : WildcardExportClangModules) {
if (ClangModule->isSubModuleOf(ClangParent))
return true;
}
}
if (Options.AllowedReexportedModules.has_value())
for (const auto &allowedModuleName : *Options.AllowedReexportedModules)
if (allowedModuleName == module->getNameStr())
return true;
return false;
};
return false;
};
if (Options.AllowedReexportedModules.has_value())
if (Options.AllowedReexportedModules.has_value() ||
!WildcardExportClangModules.empty() || !ExportedClangModules.empty())
importCollector.importFilter = std::move(importFilter);
SmallVector<Decl *, 64> ModuleDecls;