Skip to content

Commit 7811f53

Browse files
author
Nathan Hawes
authored
Merge pull request swiftlang#30521 from nathawes/cross-import-interface-gen
[SourceKit/InterfaceGen] Also print the cross-import overlays of a module in its interface.
2 parents 2ca8b15 + a355a56 commit 7811f53

22 files changed

+1016
-173
lines changed

include/swift/AST/Module.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,31 @@ class ModuleDecl : public DeclContext, public TypeDecl {
335335
void getDeclaredCrossImportBystanders(
336336
SmallVectorImpl<Identifier> &bystanderNames);
337337

338+
/// A lazily populated mapping from each declared cross import overlay this
339+
/// module transitively underlies to its bystander and immediate underlying
340+
/// module.
341+
llvm::SmallDenseMap<ModuleDecl *, std::pair<Identifier, ModuleDecl *>, 1>
342+
declaredCrossImportsTransitive;
343+
344+
/// Determines if the given \p overlay is a declarared cross-import overlay of
345+
/// this module, or an of its transitively declared overlay modules.
346+
///
347+
/// This is used by tooling to map overlays to their underlying modules, and t
348+
bool isUnderlyingModuleOfCrossImportOverlay(const ModuleDecl *overlay);
349+
350+
/// If \p overlay is a transitively declared cross-import overlay of this
351+
/// module, gets the list of bystander modules that need to be imported
352+
/// alongside this module for the overlay to be loaded.
353+
void getAllBystandersForCrossImportOverlay(
354+
ModuleDecl *overlay, SmallVectorImpl<Identifier> &bystanders);
355+
356+
/// Walks and loads the declared cross-import overlays of this module,
357+
/// transitively, to find all overlays this module underlies.
358+
///
359+
/// This is used by tooling to present these overlays as part of this module.
360+
void findDeclaredCrossImportOverlaysTransitive(
361+
SmallVectorImpl<ModuleDecl *> &overlays);
362+
338363
/// Convenience accessor for clients that know what kind of file they're
339364
/// dealing with.
340365
SourceFile &getMainSourceFile(SourceFileKind expectedKind) const;

include/swift/AST/PrintOptions.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,13 @@ struct PrintOptions {
432432
/// The information for converting archetypes to specialized types.
433433
llvm::Optional<TypeTransformContext> TransformContext;
434434

435+
/// Before printing the name of a ModuleDecl, this callback will be called and
436+
/// the name of the ModuleDecl it returns will be printed instead. This is
437+
/// currently used to present cross import overlays as if they were their
438+
/// underlying module.
439+
std::function<const ModuleDecl*(const ModuleDecl *)> mapModuleToUnderlying =
440+
[] (const ModuleDecl *D) { return D; };
441+
435442
bool PrintAsMember = false;
436443

437444
/// Whether to print parameter specifiers as 'let' and 'var'.

lib/AST/ASTPrinter.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3586,7 +3586,8 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
35863586
template <typename T>
35873587
void printModuleContext(T *Ty) {
35883588
FileUnit *File = cast<FileUnit>(Ty->getDecl()->getModuleScopeContext());
3589-
ModuleDecl *Mod = File->getParentModule();
3589+
const ModuleDecl *Mod =
3590+
Options.mapModuleToUnderlying(File->getParentModule());
35903591

35913592
Identifier Name = Mod->getName();
35923593
if (Options.UseExportedModuleNames)

lib/AST/Module.cpp

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1697,6 +1697,80 @@ void ModuleDecl::getDeclaredCrossImportBystanders(
16971697
otherModules.push_back(std::get<0>(pair));
16981698
}
16991699

1700+
using TransitiveOverlays =
1701+
llvm::SmallDenseMap<ModuleDecl *, std::pair<Identifier, ModuleDecl *>, 1>;
1702+
1703+
static void populateTransitiveCrossImports(ModuleDecl *base,
1704+
TransitiveOverlays &result) {
1705+
if (!result.empty() || !base->mightDeclareCrossImportOverlays())
1706+
return;
1707+
1708+
SmallVector<Identifier, 1> bystanders;
1709+
SmallVector<Identifier, 1> overlays;
1710+
SmallVector<ModuleDecl *, 1> worklist;
1711+
SourceLoc diagLoc; // ignored
1712+
1713+
worklist.push_back(base);
1714+
while (!worklist.empty()) {
1715+
ModuleDecl *current = worklist.back();
1716+
worklist.pop_back();
1717+
if (!current->mightDeclareCrossImportOverlays())
1718+
continue;
1719+
bystanders.clear();
1720+
current->getDeclaredCrossImportBystanders(bystanders);
1721+
for (Identifier bystander: bystanders) {
1722+
overlays.clear();
1723+
current->findDeclaredCrossImportOverlays(bystander, overlays, diagLoc);
1724+
for (Identifier overlay: overlays) {
1725+
if (!overlay.str().startswith("_"))
1726+
continue;
1727+
ModuleDecl *overlayMod =
1728+
base->getASTContext().getModuleByName(overlay.str());
1729+
if (!overlayMod)
1730+
continue;
1731+
if (result.insert({overlayMod, {bystander, current}}).second)
1732+
worklist.push_back(overlayMod);
1733+
}
1734+
}
1735+
}
1736+
}
1737+
1738+
bool ModuleDecl::isUnderlyingModuleOfCrossImportOverlay(
1739+
const ModuleDecl *overlay) {
1740+
if (!overlay->getNameStr().startswith("_"))
1741+
return false;
1742+
1743+
populateTransitiveCrossImports(this, declaredCrossImportsTransitive);
1744+
return declaredCrossImportsTransitive.find(overlay) !=
1745+
declaredCrossImportsTransitive.end();
1746+
}
1747+
1748+
void ModuleDecl::getAllBystandersForCrossImportOverlay(
1749+
ModuleDecl *overlay, SmallVectorImpl<Identifier> &bystanders) {
1750+
if (!overlay->getNameStr().startswith("_"))
1751+
return;
1752+
1753+
populateTransitiveCrossImports(this, declaredCrossImportsTransitive);
1754+
1755+
auto end = declaredCrossImportsTransitive.end();
1756+
for (auto i = declaredCrossImportsTransitive.find(overlay);
1757+
i != end;
1758+
i = declaredCrossImportsTransitive.find(i->second.second)) {
1759+
bystanders.push_back(i->second.first);
1760+
}
1761+
}
1762+
1763+
void ModuleDecl::findDeclaredCrossImportOverlaysTransitive(
1764+
SmallVectorImpl<ModuleDecl *> &overlayModules) {
1765+
populateTransitiveCrossImports(this, declaredCrossImportsTransitive);
1766+
std::transform(declaredCrossImportsTransitive.begin(),
1767+
declaredCrossImportsTransitive.end(),
1768+
std::back_inserter(overlayModules),
1769+
[](TransitiveOverlays::iterator::value_type &i) {
1770+
return i.first;
1771+
});
1772+
}
1773+
17001774
namespace {
17011775
struct OverlayFileContents {
17021776
struct Module {

0 commit comments

Comments
 (0)