Skip to content

Commit 06683cd

Browse files
committed
Add module alias lookup option enum
Pass the enum param to ASTContext::getRealModuleName
1 parent 710c6b8 commit 06683cd

File tree

4 files changed

+73
-8
lines changed

4 files changed

+73
-8
lines changed

include/swift/AST/ASTContext.h

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -483,9 +483,27 @@ class ASTContext final {
483483
/// are the real (physical) module names on disk.
484484
void setModuleAliases(const llvm::StringMap<StringRef> &aliasMap);
485485

486-
/// Retrieve the actual module name if a module alias is used via '-module-alias Foo=X', where Foo is
487-
/// a module alias and X is the real (physical) name. Returns \p key if no aliasing is used.
488-
Identifier getRealModuleName(Identifier key) const;
486+
/// Look up option used in \c getRealModuleName when module aliasing is applied.
487+
enum class ModuleAliasLookupOption {
488+
alwaysRealName,
489+
realNameFromAlias,
490+
aliasFromRealName
491+
};
492+
493+
/// Look up the module alias map by the given \p key and a lookup \p option.
494+
///
495+
/// \param key A module alias or real name to look up the map by.
496+
/// \param option A look up option \c ModuleAliasLookupOption. Defaults to alwaysRealName.
497+
///
498+
/// \return The real name or alias mapped to the key.
499+
/// If no aliasing is used, return \p key regardless of \p option.
500+
/// If \p option is alwaysRealName, return the real module name whether the \p key is an alias
501+
/// or a real name.
502+
/// If \p option is realNameFromAlias, only return a real name if \p key is an alias.
503+
/// If \p option is aliasFromRealName, only return an alias if \p key is a real name.
504+
/// Else return a real name or an alias mapped to the \p key.
505+
Identifier getRealModuleName(Identifier key,
506+
ModuleAliasLookupOption option = ModuleAliasLookupOption::alwaysRealName) const;
489507

490508
/// Decide how to interpret two precedence groups.
491509
Associativity associateInfixOperators(PrecedenceGroupDecl *left,

lib/AST/ASTContext.cpp

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1645,12 +1645,31 @@ void ASTContext::setModuleAliases(const llvm::StringMap<StringRef> &aliasMap) {
16451645
}
16461646
}
16471647

1648-
Identifier ASTContext::getRealModuleName(Identifier key) const {
1648+
Identifier ASTContext::getRealModuleName(Identifier key, ModuleAliasLookupOption option) const {
16491649
auto found = ModuleAliasMap.find(key);
1650-
if (found != ModuleAliasMap.end()) {
1651-
return found->second;
1650+
if (found == ModuleAliasMap.end())
1651+
return key; // No module aliasing was used, so just return the given key
1652+
1653+
// Found an entry
1654+
auto value = found->second;
1655+
1656+
// With the alwaysRealName option, look up the real name by treating
1657+
// the given key as an alias; if the key's not an alias, return the key
1658+
// itself since that's the real name.
1659+
if (option == ModuleAliasLookupOption::alwaysRealName) {
1660+
return value.second ? value.first : key;
16521661
}
1653-
return key;
1662+
1663+
// With realNameFromAlias or aliasFromRealName option, only return the value
1664+
// if the given key matches the description (whether it's an alias or real name)
1665+
// by looking up the value.second (true if keyed by an alias). If not matched,
1666+
// return an empty Identifier.
1667+
if ((option == ModuleAliasLookupOption::realNameFromAlias && !value.second) ||
1668+
(option == ModuleAliasLookupOption::aliasFromRealName && value.second))
1669+
return Identifier();
1670+
1671+
// Otherwise return the value found (whether the key is an alias or real name)
1672+
return value.first;
16541673
}
16551674

16561675
Optional<ModuleDependencies> ASTContext::getModuleDependencies(

lib/AST/UnqualifiedLookup.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -431,7 +431,21 @@ void UnqualifiedLookupFactory::lookForAModuleWithTheGivenName(
431431
#endif
432432
return;
433433
}
434-
ModuleDecl *desiredModule = Ctx.getLoadedModule(Name.getBaseIdentifier());
434+
435+
ModuleDecl *desiredModule = nullptr;
436+
auto givenName = Name.getBaseIdentifier();
437+
// Check if the given name appearing in the source file is a module
438+
// real name or alias; for example, if `-module-alias Foo=Bar` was
439+
// passed, the alias 'Foo' should appear in source files, not 'Bar'.
440+
// If the real name 'Bar' was used, looking up getRealModuleName with
441+
// the real name 'Bar' and realNameFromAlias option should return
442+
// an empty Identifier.
443+
if (!Ctx.getRealModuleName(givenName, ASTContext::ModuleAliasLookupOption::realNameFromAlias).empty()) {
444+
// Only load the module if the lookup value is not empty, i.e. given
445+
// name is a module alias, not a real module name.
446+
desiredModule = Ctx.getLoadedModule(givenName);
447+
}
448+
435449
if (!desiredModule && Name.getFullName() == Ctx.TheBuiltinModule->getName())
436450
desiredModule = Ctx.TheBuiltinModule;
437451
if (desiredModule) {

lib/Parse/ParseDecl.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4819,6 +4819,20 @@ ParserResult<ImportDecl> Parser::parseDeclImport(ParseDeclOptions Flags,
48194819
return nullptr;
48204820
}
48214821

4822+
// Look up if the imported module is being aliased via -module-alias,
4823+
// and check that the module alias appeared in source files instead of
4824+
// its corresponding real name
4825+
auto parsedModuleID = importPath.get().front().Item;
4826+
if (Context.getRealModuleName(parsedModuleID, ASTContext::ModuleAliasLookupOption::realNameFromAlias).empty()) {
4827+
// If reached here, it means the parsed module name is a real module name
4828+
// which appeared in the source file; only a module alias should be allowed
4829+
auto aliasName = Context.getRealModuleName(parsedModuleID, ASTContext::ModuleAliasLookupOption::aliasFromRealName);
4830+
diagnose(importPath.front().Loc, diag::expected_module_alias,
4831+
parsedModuleID, aliasName)
4832+
.fixItReplace(importPath.front().Loc, aliasName.str());
4833+
return nullptr;
4834+
}
4835+
48224836
auto *ID = ImportDecl::create(Context, CurDeclContext, ImportLoc, Kind,
48234837
KindLoc, importPath.get());
48244838
ID->getAttrs() = Attributes;

0 commit comments

Comments
 (0)