Add frontend flag -import-module <name>.

This implicitly adds the named module as an import of every source file
in the module being compiled. This is not intended to be used generally,
but will be useful for playgrounds.

rdar://problem/19605934

Swift SVN r24905
This commit is contained in:
Jordan Rose
2015-02-02 22:20:13 +00:00
parent 7fd2ca6fc9
commit c97c949fcf
5 changed files with 37 additions and 4 deletions

View File

@@ -72,6 +72,9 @@ public:
/// by the frontend. /// by the frontend.
std::string OutputFilename; std::string OutputFilename;
/// An arbitrary module to import and make implicitly visible.
std::string ImplicitImportModuleName;
/// An Objective-C header to import and make implicitly visible. /// An Objective-C header to import and make implicitly visible.
std::string ImplicitObjCHeaderPath; std::string ImplicitObjCHeaderPath;

View File

@@ -184,6 +184,9 @@ def enable_union_import :
def enable_source_import : Flag<["-"], "enable-source-import">, def enable_source_import : Flag<["-"], "enable-source-import">,
HelpText<"Enable importing of Swift source files">; HelpText<"Enable importing of Swift source files">;
def import_module : Separate<["-"], "import-module">,
HelpText<"Implicitly import the specified module">;
def print_stats : Flag<["-"], "print-stats">, def print_stats : Flag<["-"], "print-stats">,
HelpText<"Print various statistics">; HelpText<"Print various statistics">;

View File

@@ -535,6 +535,9 @@ static bool ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
!Opts.PrimaryInput && !Opts.ModuleOutputPath.empty(); !Opts.PrimaryInput && !Opts.ModuleOutputPath.empty();
} }
if (const Arg *A = Args.getLastArg(OPT_import_module))
Opts.ImplicitImportModuleName = A->getValue();
for (const Arg *A : make_range(Args.filtered_begin(OPT_Xllvm), for (const Arg *A : make_range(Args.filtered_begin(OPT_Xllvm),
Args.filtered_end())) { Args.filtered_end())) {
Opts.LLVMArgs.push_back(A->getValue()); Opts.LLVMArgs.push_back(A->getValue());

View File

@@ -222,6 +222,7 @@ Module *CompilerInstance::getMainModule() {
} }
void CompilerInstance::performSema() { void CompilerInstance::performSema() {
const FrontendOptions &options = Invocation.getFrontendOptions();
const SourceFileKind Kind = Invocation.getInputKind(); const SourceFileKind Kind = Invocation.getInputKind();
Module *MainModule = getMainModule(); Module *MainModule = getMainModule();
Context->LoadedModules[MainModule->Name] = MainModule; Context->LoadedModules[MainModule->Name] = MainModule;
@@ -254,7 +255,7 @@ void CompilerInstance::performSema() {
static_cast<ClangImporter *>(Context->getClangModuleLoader()); static_cast<ClangImporter *>(Context->getClangModuleLoader());
Module *underlying = nullptr; Module *underlying = nullptr;
if (Invocation.getFrontendOptions().ImportUnderlyingModule) { if (options.ImportUnderlyingModule) {
underlying = clangImporter->loadModule(SourceLoc(), underlying = clangImporter->loadModule(SourceLoc(),
std::make_pair(MainModule->Name, std::make_pair(MainModule->Name,
SourceLoc())); SourceLoc()));
@@ -265,16 +266,26 @@ void CompilerInstance::performSema() {
} }
Module *importedHeaderModule = nullptr; Module *importedHeaderModule = nullptr;
StringRef implicitHeaderPath = StringRef implicitHeaderPath = options.ImplicitObjCHeaderPath;
Invocation.getFrontendOptions().ImplicitObjCHeaderPath;
if (!implicitHeaderPath.empty()) { if (!implicitHeaderPath.empty()) {
clangImporter->importBridgingHeader(implicitHeaderPath, MainModule); clangImporter->importBridgingHeader(implicitHeaderPath, MainModule);
importedHeaderModule = clangImporter->getImportedHeaderModule(); importedHeaderModule = clangImporter->getImportedHeaderModule();
assert(importedHeaderModule); assert(importedHeaderModule);
} }
Module *importModule = nullptr;
if (!options.ImplicitImportModuleName.empty()) {
if (Lexer::isIdentifier(options.ImplicitImportModuleName)) {
auto moduleID = Context->getIdentifier(options.ImplicitImportModuleName);
importModule = Context->getModule(std::make_pair(moduleID, SourceLoc()));
} else {
Diagnostics.diagnose(SourceLoc(), diag::error_bad_module_name,
options.ImplicitImportModuleName, false);
}
}
auto addAdditionalInitialImports = [&](SourceFile *SF) { auto addAdditionalInitialImports = [&](SourceFile *SF) {
if (!underlying && !importedHeaderModule) if (!underlying && !importedHeaderModule && !importModule)
return; return;
auto initialImports = SF->getImports(/*allowUnparsed=*/true); auto initialImports = SF->getImports(/*allowUnparsed=*/true);
@@ -289,6 +300,10 @@ void CompilerInstance::performSema() {
if (importedHeaderModule) if (importedHeaderModule)
initialImportsBuf.push_back({ { /*accessPath=*/{}, importedHeaderModule }, initialImportsBuf.push_back({ { /*accessPath=*/{}, importedHeaderModule },
/*exported=*/true }); /*exported=*/true });
if (importModule)
initialImportsBuf.push_back({ { /*accessPath=*/{}, importModule },
/*exported=*/false });
SF->setImports(Context->AllocateCopy(initialImportsBuf)); SF->setImports(Context->AllocateCopy(initialImportsBuf));
}; };

View File

@@ -0,0 +1,9 @@
// RUN: %target-swift-frontend -parse %s -enable-source-import -I %S/Inputs -sdk "" -verify
// RUN: %target-swift-frontend -parse %s -enable-source-import -I %S/Inputs -sdk "" -import-module abcde
// RUN: not %target-swift-frontend -parse %s -enable-source-import -I %S/Inputs -sdk "" -import-module 3333 2>&1 | FileCheck -check-prefix=NON-IDENT %s
// NON-IDENT: error: module name "3333" is not a valid identifier
var a: A? // expected-error {{use of undeclared type 'A'}}
var qA: abcde.A? // expected-error {{use of undeclared type 'abcde'}}