Skip to content

Commit b5b285e

Browse files
committed
Reuse compute module aliases function
Update tests
1 parent 1e5160b commit b5b285e

File tree

6 files changed

+117
-115
lines changed

6 files changed

+117
-115
lines changed

include/swift/Frontend/Frontend.h

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -309,10 +309,14 @@ class CompilerInvocation {
309309
return FrontendOpts.ModuleName;
310310
}
311311

312-
/// Sets module alias map with string args passed in via `-module-alias`. This assumes
313-
/// the args are valid strings; full validation of input args for module aliasing is done at
314-
/// \c ArgsToFrontendOptionsConverter::computeModulealiases.
315-
void setModuleAliasMap(std::vector<std::string> args);
312+
/// Sets the module alias map with string args passed in via `-module-alias`.
313+
/// \param args The arguments to `-module-alias`. If input has `-module-alias Foo=Bar
314+
/// -module-alias Baz=Qux`, the args are ['Foo=Bar', 'Baz=Qux']. The name
315+
/// Foo is the name that appears in source files, while it maps to Bar, the name
316+
/// of the binary on disk, /path/to/Bar.swiftmodule(interface), under the hood.
317+
/// \param diags Used to print diagnostics in case validation of the string args fails.
318+
/// See \c ModuleAliasesConverter::computeModuleAliases on validation details.
319+
void setModuleAliasMap(std::vector<std::string> args, DiagnosticEngine &diags);
316320

317321
std::string getOutputFilename() const {
318322
return FrontendOpts.InputsAndOutputs.getSingleOutputFilename();

lib/Frontend/ArgsToFrontendOptionsConverter.cpp

Lines changed: 65 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -253,8 +253,9 @@ bool ArgsToFrontendOptionsConverter::convert(
253253
Opts.ModuleLinkName = A->getValue();
254254

255255
// This must be called after computing module name, module abi name,
256-
// and module link name.
257-
if (computeModuleAliases())
256+
// and module link name. If computing module aliases is unsuccessful,
257+
// return early.
258+
if (!computeModuleAliases())
258259
return true;
259260

260261
if (const Arg *A = Args.getLastArg(OPT_access_notes_path))
@@ -515,62 +516,7 @@ bool ArgsToFrontendOptionsConverter::setUpImmediateArgs() {
515516

516517
bool ArgsToFrontendOptionsConverter::computeModuleAliases() {
517518
auto list = Args.getAllArgValues(options::OPT_module_alias);
518-
if (!list.empty()) {
519-
// ModuleAliasMap should initially be empty as setting
520-
// it should be called only once
521-
Opts.ModuleAliasMap.clear();
522-
523-
auto validate = [this](StringRef value, bool allowModuleName) -> bool
524-
{
525-
if (!allowModuleName) {
526-
if (value == Opts.ModuleName ||
527-
value == Opts.ModuleABIName ||
528-
value == Opts.ModuleLinkName) {
529-
Diags.diagnose(SourceLoc(), diag::error_module_alias_forbidden_name, value);
530-
return false;
531-
}
532-
}
533-
if (value == STDLIB_NAME) {
534-
Diags.diagnose(SourceLoc(), diag::error_module_alias_forbidden_name, value);
535-
return false;
536-
}
537-
if (!Lexer::isIdentifier(value)) {
538-
Diags.diagnose(SourceLoc(), diag::error_bad_module_name, value, false);
539-
return false;
540-
}
541-
return true;
542-
};
543-
544-
for (auto item: list) {
545-
auto str = StringRef(item);
546-
// splits to an alias and the underlying name
547-
auto pair = str.split('=');
548-
auto lhs = pair.first;
549-
auto rhs = pair.second;
550-
551-
if (rhs.empty()) { // '=' is missing
552-
Diags.diagnose(SourceLoc(), diag::error_module_alias_invalid_format, str);
553-
return true;
554-
}
555-
if (!validate(lhs, false) || !validate(rhs, true)) {
556-
return true;
557-
}
558-
559-
// First, add the underlying name as a key to prevent it from being
560-
// used as an alias
561-
if (!Opts.ModuleAliasMap.insert({rhs, StringRef()}).second) {
562-
Diags.diagnose(SourceLoc(), diag::error_module_alias_duplicate, rhs);
563-
return true;
564-
}
565-
// Next, add the alias as a key and the underlying name as a value to the map
566-
auto underlyingName = Opts.ModuleAliasMap.find(rhs)->first();
567-
if (!Opts.ModuleAliasMap.insert({lhs, underlyingName}).second) {
568-
Diags.diagnose(SourceLoc(), diag::error_module_alias_duplicate, lhs);
569-
return true;
570-
}
571-
}
572-
}
573-
return false;
519+
return ModuleAliasesConverter::computeModuleAliases(list, Opts, Diags);
574520
}
575521

576522
bool ArgsToFrontendOptionsConverter::computeModuleName() {
@@ -748,3 +694,64 @@ void ArgsToFrontendOptionsConverter::computeLLVMArgs() {
748694
Opts.LLVMArgs.push_back(A->getValue());
749695
}
750696
}
697+
698+
bool ModuleAliasesConverter::computeModuleAliases(std::vector<std::string> args,
699+
FrontendOptions &options,
700+
DiagnosticEngine &diags) {
701+
if (!args.empty()) {
702+
// ModuleAliasMap should initially be empty as setting
703+
// it should be called only once
704+
options.ModuleAliasMap.clear();
705+
706+
auto validate = [&options, &diags](StringRef value, bool allowModuleName) -> bool
707+
{
708+
if (!allowModuleName) {
709+
if (value == options.ModuleName ||
710+
value == options.ModuleABIName ||
711+
value == options.ModuleLinkName) {
712+
diags.diagnose(SourceLoc(), diag::error_module_alias_forbidden_name, value);
713+
return false;
714+
}
715+
}
716+
if (value == STDLIB_NAME) {
717+
diags.diagnose(SourceLoc(), diag::error_module_alias_forbidden_name, value);
718+
return false;
719+
}
720+
if (!Lexer::isIdentifier(value)) {
721+
diags.diagnose(SourceLoc(), diag::error_bad_module_name, value, false);
722+
return false;
723+
}
724+
return true;
725+
};
726+
727+
for (auto item: args) {
728+
auto str = StringRef(item);
729+
// splits to an alias and the underlying name
730+
auto pair = str.split('=');
731+
auto lhs = pair.first;
732+
auto rhs = pair.second;
733+
734+
if (rhs.empty()) { // '=' is missing
735+
diags.diagnose(SourceLoc(), diag::error_module_alias_invalid_format, str);
736+
return false;
737+
}
738+
if (!validate(lhs, false) || !validate(rhs, true)) {
739+
return false;
740+
}
741+
742+
// First, add the underlying name as a key to prevent it from being
743+
// used as an alias
744+
if (!options.ModuleAliasMap.insert({rhs, StringRef()}).second) {
745+
diags.diagnose(SourceLoc(), diag::error_module_alias_duplicate, rhs);
746+
return false;
747+
}
748+
// Next, add the alias as a key and the underlying name as a value to the map
749+
auto underlyingName = options.ModuleAliasMap.find(rhs)->first();
750+
if (!options.ModuleAliasMap.insert({lhs, underlyingName}).second) {
751+
diags.diagnose(SourceLoc(), diag::error_module_alias_duplicate, lhs);
752+
return false;
753+
}
754+
}
755+
}
756+
return true;
757+
}

lib/Frontend/ArgsToFrontendOptionsConverter.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,22 @@ class ArgsToFrontendOptionsConverter {
7373
determineRequestedAction(const llvm::opt::ArgList &);
7474
};
7575

76+
class ModuleAliasesConverter {
77+
public:
78+
/// Sets the \c ModuleAliasMap in the \c FrontendOptions with args passed via `-module-alias`.
79+
///
80+
/// \param args The arguments to `-module-alias`. If input has `-module-alias Foo=Bar
81+
/// -module-alias Baz=Qux`, the args are ['Foo=Bar', 'Baz=Qux']. The name
82+
/// Foo is the name that appears in source files, while it maps to Bar, the name
83+
/// of the binary on disk, /path/to/Bar.swiftmodule(interface), under the hood.
84+
/// \param options FrontendOptions containings the module alias map to set args to.
85+
/// \param diags Used to print diagnostics in case validation of the args fails.
86+
/// \return Whether the validation passed and successfully set the module alias map
87+
static bool computeModuleAliases(std::vector<std::string> args,
88+
FrontendOptions &options,
89+
DiagnosticEngine &diags);
90+
};
91+
7692
} // namespace swift
7793

7894
#endif /* SWIFT_FRONTEND_ARGSTOFRONTENDOPTIONSCONVERTER_H */

lib/Frontend/CompilerInvocation.cpp

Lines changed: 3 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -262,28 +262,9 @@ void CompilerInvocation::setSDKPath(const std::string &Path) {
262262
updateRuntimeLibraryPaths(SearchPathOpts, LangOpts.Target);
263263
}
264264

265-
void CompilerInvocation::setModuleAliasMap(std::vector<std::string> args) {
266-
// ModuleAliasMap should initially be empty as setting
267-
// it should be called only once
268-
FrontendOpts.ModuleAliasMap.clear();
269-
for (auto item: args) {
270-
auto str = StringRef(item);
271-
// splits to an alias and the underlying name
272-
auto pair = str.split('=');
273-
auto lhs = pair.first;
274-
auto rhs = pair.second;
275-
if (rhs.empty()) // bad format, so skip to the next
276-
continue;
277-
if (!FrontendOpts.ModuleAliasMap.insert({rhs, StringRef()}).second) {
278-
// the underlying name was already added, so skip
279-
continue;
280-
}
281-
auto underlyingName = FrontendOpts.ModuleAliasMap.find(rhs)->first();
282-
if (!FrontendOpts.ModuleAliasMap.insert({lhs, underlyingName}).second) {
283-
// the alias was already added, so skip
284-
continue;
285-
}
286-
}
265+
void CompilerInvocation::setModuleAliasMap(std::vector<std::string> args,
266+
DiagnosticEngine &diags) {
267+
ModuleAliasesConverter::computeModuleAliases(args, FrontendOpts, diags);
287268
}
288269

289270
static bool ParseFrontendArgs(

test/IDE/module-aliasing-code-complete.swift

Lines changed: 20 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -11,51 +11,41 @@
1111
// RUN: %target-swift-frontend %t/FileLogging.swift -module-name AppleLogging -module-alias XLogging=AppleLogging -emit-module -o %t/AppleLogging.swiftmodule
1212

1313
// RUN: %target-swift-ide-test -code-completion -code-completion-token=MODULE_NAME -source-filename %t/FileLib1.swift -module-alias XLogging=AppleLogging -I %t > %t/result1.txt
14-
// RUN: %FileCheck %s -check-prefix CHECK1 < %t/result1.txt
15-
16-
// CHECK1-NOT: AppleLogging
17-
// CHECK1: found code completion token MODULE_NAME
18-
// CHECK1: Begin completions
19-
// CHECK1: Decl[Module]/None: XLogging[#Module#]; name=XLogging
20-
// CHECK1: Decl[Protocol]/OtherModule[XLogging]: Logging[#Logging#]; name=Logging
21-
// CHECK1: Decl[Struct]/OtherModule[XLogging]: Logger[#Logger#]; name=Logger
22-
// CHECK1: End completions
23-
14+
// RUN: %FileCheck %s -check-prefix CHECK12 < %t/result1.txt
2415

2516
// RUN: %target-swift-ide-test -code-completion -code-completion-token=MODULE_NAME -source-filename %t/FileLib2.swift -module-alias XLogging=AppleLogging -I %t > %t/result2.txt
26-
// RUN: %FileCheck %s -check-prefix CHECK2 < %t/result2.txt
27-
28-
// CHECK2-NOT: AppleLogging
29-
// CHECK2: found code completion token MODULE_NAME
30-
// CHECK2: Begin completions
31-
// CHECK2: Decl[Module]/None: XLogging[#Module#]; name=XLogging
32-
// CHECK2: Decl[Protocol]/OtherModule[XLogging]: Logging[#Logging#]; name=Logging
33-
// CHECK2: Decl[Struct]/OtherModule[XLogging]: Logger[#Logger#]; name=Logger
34-
// CHECK2: End completions
17+
// RUN: %FileCheck %s -check-prefix CHECK12 < %t/result2.txt
3518

19+
// CHECK12: found code completion token MODULE_NAME
20+
// CHECK12: Begin completions
21+
// CHECK12-NOT: AppleLogging
22+
// CHECK12-DAG: Decl[Module]/None: XLogging[#Module#]; name=XLogging
23+
// CHECK12-DAG: Decl[Protocol]/OtherModule[XLogging]: Logging[#Logging#]; name=Logging
24+
// CHECK12-DAG: Decl[Struct]/OtherModule[XLogging]: Logger[#Logger#]; name=Logger
25+
// CHECK12: End completions
3626

3727
// RUN: %target-swift-ide-test -code-completion -code-completion-token=MODULE_NAME -source-filename %t/FileLib3.swift -module-alias XLogging=AppleLogging -I %t > %t/result3.txt
3828
// RUN: %FileCheck %s -check-prefix CHECK3 < %t/result3.txt
3929

40-
// CHECK3-NOT: AppleLogging
4130
// CHECK3: found code completion token MODULE_NAME
4231
// CHECK3: Begin completions
43-
// CHECK3: Decl[Module]/None: XLogging[#Module#]; name=XLogging
44-
// CHECK3: Decl[Protocol]/OtherModule[XLogging]/Flair[RareType]: Logging[#Logging#]; name=Logging
45-
// CHECK3: Decl[Struct]/OtherModule[XLogging]: Logger[#Logger#]; name=Logger
46-
// CHECK3: Decl[FreeFunction]/OtherModule[XLogging]: setupLogger()[#Logger?#]; name=setupLogger()
32+
// CHECK3-NOT: AppleLogging
33+
// CHECK3-DAG: Decl[Module]/None: XLogging[#Module#]; name=XLogging
34+
// CHECK3-DAG: Decl[Protocol]/OtherModule[XLogging]/Flair[RareType]: Logging[#Logging#]; name=Logging
35+
// CHECK3-DAG: Decl[Struct]/OtherModule[XLogging]: Logger[#Logger#]; name=Logger
36+
// CHECK3-DAG: Decl[FreeFunction]/OtherModule[XLogging]: setupLogger()[#Logger?#]; name=setupLogger()
4737
// CHECK3: End completions
4838

4939

5040
// RUN: %target-swift-ide-test -code-completion -code-completion-token=MODULE_NAME -source-filename %t/FileLib4.swift -module-alias XLogging=AppleLogging -I %t > %t/result4.txt
5141
// RUN: %FileCheck %s -check-prefix CHECK4 < %t/result4.txt
5242

53-
// CHECK4-NOT: AppleLogging
5443
// CHECK4: found code completion token MODULE_NAME
5544
// CHECK4: Begin completions
56-
// CHECK4: Decl[Protocol]/OtherModule[XLogging]/Flair[RareType]: Logging[#Logging#]; name=Logging
57-
// CHECK4: Decl[Struct]/OtherModule[XLogging]: Logger[#Logger#]; name=Logger
58-
// CHECK4: Decl[FreeFunction]/OtherModule[XLogging]: setupLogger()[#Logger?#]; name=setupLogger()
45+
// CHECK4-NOT: AppleLogging
46+
// CHECK4-DAG: Decl[Protocol]/OtherModule[XLogging]/Flair[RareType]: Logging[#Logging#]; name=Logging
47+
// CHECK4-DAG: Decl[Struct]/OtherModule[XLogging]: Logger[#Logger#]; name=Logger
48+
// CHECK4-DAG: Decl[FreeFunction]/OtherModule[XLogging]: setupLogger()[#Logger?#]; name=setupLogger()
5949
// CHECK4: End completions
6050

6151
/// In the following, the module alias name should be shown as a module that can be imported instead of the real name
@@ -65,9 +55,9 @@
6555

6656
/// In search paths, only AppleLogging.swiftmodule exists, but when `-module-alias XLogging=AppleLogging` is passed,
6757
/// we want to only show XLogging as an option to import, not AppleLogging
68-
// CHECK5-NOT: AppleLogging
6958
// CHECK5: found code completion token MODULE_NAME
7059
// CHECK5: Begin completions
60+
// CHECK5-NOT: AppleLogging
7161
// CHECK5: Decl[Module]/None: XLogging[#Module#]; name=XLogging
7262
// CHECK5: End completions
7363

@@ -77,9 +67,9 @@
7767

7868
/// In search paths, only AppleLogging.swiftmodule exists, and no module aliasing option is passed, so
7969
/// just show AppleLogging as one of the modules that can be imported
80-
// CHECK6-NOT: XLogging
8170
// CHECK6: found code completion token MODULE_NAME
8271
// CHECK6: Begin completions
72+
// CHECK6-NOT: XLogging
8373
// CHECK6: Decl[Module]/None: AppleLogging[#Module#]; name=AppleLogging
8474
// CHECK6: End completions
8575

tools/swift-ide-test/swift-ide-test.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4238,7 +4238,11 @@ int main(int argc, char *argv[]) {
42384238
}
42394239

42404240
if (!options::ModuleAliases.empty()) {
4241-
InitInvok.setModuleAliasMap(options::ModuleAliases);
4241+
PrintingDiagnosticConsumer PDC;
4242+
SourceManager SM;
4243+
DiagnosticEngine Diags(SM);
4244+
Diags.addConsumer(PDC);
4245+
InitInvok.setModuleAliasMap(options::ModuleAliases, Diags);
42424246
}
42434247

42444248
// Process the clang arguments last and allow them to override previously

0 commit comments

Comments
 (0)