diff --git a/include/swift-c/DependencyScan/DependencyScan.h b/include/swift-c/DependencyScan/DependencyScan.h index 93a9ec2bdc31b..223816b363661 100644 --- a/include/swift-c/DependencyScan/DependencyScan.h +++ b/include/swift-c/DependencyScan/DependencyScan.h @@ -25,7 +25,7 @@ /// SWIFTSCAN_VERSION_MINOR should increase when there are API additions. /// SWIFTSCAN_VERSION_MAJOR is intended for "major" source/ABI breaking changes. #define SWIFTSCAN_VERSION_MAJOR 2 -#define SWIFTSCAN_VERSION_MINOR 1 +#define SWIFTSCAN_VERSION_MINOR 2 SWIFTSCAN_BEGIN_DECLS @@ -49,6 +49,9 @@ typedef struct swiftscan_dependency_info_s *swiftscan_dependency_info_t; /// Opaque container to a link library info. typedef struct swiftscan_link_library_info_s *swiftscan_link_library_info_t; +/// Opaque container to an import info. +typedef struct swiftscan_import_info_s *swiftscan_import_info_t; + /// Opaque container to a macro dependency. typedef struct swiftscan_macro_dependency_s *swiftscan_macro_dependency_t; @@ -76,6 +79,18 @@ typedef struct { size_t count; } swiftscan_link_library_set_t; +/// Set of details about source imports +typedef struct { + swiftscan_import_info_t *imports; + size_t count; +} swiftscan_import_info_set_t; + +/// Set of source location infos +typedef struct { + swiftscan_source_location_t *source_locations; + size_t count; +} swiftscan_source_location_set_t; + /// Set of macro dependency typedef struct { swiftscan_macro_dependency_t *macro_dependencies; @@ -89,6 +104,15 @@ typedef enum { SWIFTSCAN_DIAGNOSTIC_SEVERITY_REMARK = 3 } swiftscan_diagnostic_severity_t; +// Must maintain consistency with swift::AccessLevel +typedef enum { + SWIFTSCAN_ACCESS_LEVEL_PRIVATE = 0, + SWIFTSCAN_ACCESS_LEVEL_FILEPRIVATE = 1, + SWIFTSCAN_ACCESS_LEVEL_INTERNAL = 2, + SWIFTSCAN_ACCESS_LEVEL_PACKAGE = 3, + SWIFTSCAN_ACCESS_LEVEL_PUBLIC = 4 +} swiftscan_access_level_t; + typedef struct { swiftscan_diagnostic_info_t *diagnostics; size_t count; @@ -148,10 +172,23 @@ swiftscan_module_info_get_direct_dependencies(swiftscan_dependency_info_t info); SWIFTSCAN_PUBLIC swiftscan_link_library_set_t * swiftscan_module_info_get_link_libraries(swiftscan_dependency_info_t info); +SWIFTSCAN_PUBLIC swiftscan_import_info_set_t * +swiftscan_module_info_get_imports(swiftscan_dependency_info_t info); + SWIFTSCAN_PUBLIC swiftscan_module_details_t swiftscan_module_info_get_details(swiftscan_dependency_info_t info); -//=== Link Library Info Functions ------------------------------------===// +//=== Import Details Functions -------------------------------------------===// +SWIFTSCAN_PUBLIC swiftscan_source_location_set_t * +swiftscan_import_info_get_source_locations(swiftscan_import_info_t info); + +SWIFTSCAN_PUBLIC swiftscan_string_ref_t +swiftscan_import_info_get_identifier(swiftscan_import_info_t info); + +SWIFTSCAN_PUBLIC swiftscan_access_level_t +swiftscan_import_info_get_access_level(swiftscan_import_info_t info); + +//=== Link Library Info Functions ----------------------------------------===// SWIFTSCAN_PUBLIC swiftscan_string_ref_t swiftscan_link_library_info_get_link_name( swiftscan_link_library_info_t info); diff --git a/include/swift/AST/ModuleDependencies.h b/include/swift/AST/ModuleDependencies.h index e6d0581dab5a4..4846c4bcca735 100644 --- a/include/swift/AST/ModuleDependencies.h +++ b/include/swift/AST/ModuleDependencies.h @@ -156,30 +156,35 @@ struct ScannerImportStatementInfo { uint32_t columnNumber; }; - ScannerImportStatementInfo(std::string importIdentifier, bool isExported) - : importLocations(), importIdentifier(importIdentifier), - isExported(isExported) {} + ScannerImportStatementInfo(std::string importIdentifier, bool isExported, + AccessLevel accessLevel) + : importIdentifier(importIdentifier), importLocations(), + isExported(isExported), accessLevel(accessLevel) {} ScannerImportStatementInfo(std::string importIdentifier, bool isExported, + AccessLevel accessLevel, ImportDiagnosticLocationInfo location) - : importLocations({location}), importIdentifier(importIdentifier), - isExported(isExported) {} + : importIdentifier(importIdentifier), importLocations({location}), + isExported(isExported), accessLevel(accessLevel) {} ScannerImportStatementInfo(std::string importIdentifier, bool isExported, + AccessLevel accessLevel, SmallVector locations) - : importLocations(locations), importIdentifier(importIdentifier), - isExported(isExported) {} + : importIdentifier(importIdentifier), importLocations(locations), + isExported(isExported), accessLevel(accessLevel) {} void addImportLocation(ImportDiagnosticLocationInfo location) { importLocations.push_back(location); } - /// Buffer, line & column number of the import statement - SmallVector importLocations; /// Imported module string. e.g. "Foo.Bar" in 'import Foo.Bar' std::string importIdentifier; + /// Buffer, line & column number of the import statement + SmallVector importLocations; /// Is this an @_exported import bool isExported; + /// Access level of this dependency + AccessLevel accessLevel; }; /// Base class for the variant storage of ModuleDependencyInfo. @@ -942,6 +947,7 @@ class ModuleDependencyInfo { /// Add a dependency on the given module, if it was not already in the set. void addOptionalModuleImport(StringRef module, bool isExported, + AccessLevel accessLevel, llvm::StringSet<> *alreadyAddedModules = nullptr); /// Add all of the module imports in the given source @@ -952,12 +958,14 @@ class ModuleDependencyInfo { /// Add a dependency on the given module, if it was not already in the set. void addModuleImport(ImportPath::Module module, bool isExported, + AccessLevel accessLevel, llvm::StringSet<> *alreadyAddedModules = nullptr, const SourceManager *sourceManager = nullptr, SourceLoc sourceLocation = SourceLoc()); /// Add a dependency on the given module, if it was not already in the set. void addModuleImport(StringRef module, bool isExported, + AccessLevel accessLevel, llvm::StringSet<> *alreadyAddedModules = nullptr, const SourceManager *sourceManager = nullptr, SourceLoc sourceLocation = SourceLoc()); diff --git a/include/swift/DependencyScan/DependencyScanImpl.h b/include/swift/DependencyScan/DependencyScanImpl.h index 66f95615269b6..ec70611550fcc 100644 --- a/include/swift/DependencyScan/DependencyScanImpl.h +++ b/include/swift/DependencyScan/DependencyScanImpl.h @@ -63,6 +63,9 @@ struct swiftscan_dependency_info_s { /// The list of link libraries for this module. swiftscan_link_library_set_t *link_libraries; + /// The list of source import infos. + swiftscan_import_info_set_t *imports; + /// Specific details of a particular kind of module. swiftscan_module_details_t details; }; @@ -74,10 +77,16 @@ struct swiftscan_link_library_info_s { bool forceLoad; }; +struct swiftscan_import_info_s { + swiftscan_string_ref_t import_identifier; + swiftscan_source_location_set_t *source_locations; + swiftscan_access_level_t access_level; +}; + struct swiftscan_macro_dependency_s { - swiftscan_string_ref_t moduleName; - swiftscan_string_ref_t libraryPath; - swiftscan_string_ref_t executablePath; + swiftscan_string_ref_t module_name; + swiftscan_string_ref_t library_path; + swiftscan_string_ref_t executable_path; }; /// Swift modules to be built from a module interface, may have a bridging diff --git a/include/swift/DependencyScan/SerializedModuleDependencyCacheFormat.h b/include/swift/DependencyScan/SerializedModuleDependencyCacheFormat.h index 8a5c4d074cd90..f48f0e4e1ec64 100644 --- a/include/swift/DependencyScan/SerializedModuleDependencyCacheFormat.h +++ b/include/swift/DependencyScan/SerializedModuleDependencyCacheFormat.h @@ -67,6 +67,9 @@ using IsExportedImport = BCFixed<1>; using LineNumberField = BCFixed<32>; using ColumnNumberField = BCFixed<32>; +/// Access level of an import +using AccessLevelField = BCFixed<8>; + /// Arrays of various identifiers, distinguished for readability using IdentifierIDArryField = llvm::BCArray; using ModuleIDArryField = llvm::BCArray; @@ -192,7 +195,8 @@ using ImportStatementLayout = LineNumberField, // lineNumber ColumnNumberField, // columnNumber IsOptionalImport, // isOptional - IsExportedImport // isExported + IsExportedImport, // isExported + AccessLevelField // accessLevel >; using ImportStatementArrayLayout = BCRecordLayout; diff --git a/include/swift/Serialization/SerializedModuleLoader.h b/include/swift/Serialization/SerializedModuleLoader.h index 137a9dcd24783..3ae80b98b3193 100644 --- a/include/swift/Serialization/SerializedModuleLoader.h +++ b/include/swift/Serialization/SerializedModuleLoader.h @@ -170,8 +170,7 @@ class SerializedModuleLoaderBase : public ModuleLoader { bool isTestableImport, bool isCandidateForTextualModule); struct BinaryModuleImports { - llvm::StringSet<> moduleImports; - llvm::StringSet<> exportedModules; + std::vector moduleImports; std::string headerImport; }; diff --git a/lib/AST/ModuleDependencies.cpp b/lib/AST/ModuleDependencies.cpp index 07d08f4b9005c..4d9bc233a9639 100644 --- a/lib/AST/ModuleDependencies.cpp +++ b/lib/AST/ModuleDependencies.cpp @@ -116,14 +116,34 @@ bool ModuleDependencyInfo::isTestableImport(StringRef moduleName) const { } void ModuleDependencyInfo::addOptionalModuleImport( - StringRef module, bool isExported, llvm::StringSet<> *alreadyAddedModules) { - if (!alreadyAddedModules || alreadyAddedModules->insert(module).second) - storage->optionalModuleImports.push_back({module.str(), isExported}); + StringRef module, bool isExported, AccessLevel accessLevel, + llvm::StringSet<> *alreadyAddedModules) { + + if (alreadyAddedModules && alreadyAddedModules->contains(module)) { + // Find a prior import of this module and add import location + // and adjust whether or not this module is ever imported as exported + // as well as the access level + for (auto &existingImport : storage->optionalModuleImports) { + if (existingImport.importIdentifier == module) { + existingImport.isExported |= isExported; + existingImport.accessLevel = std::max(existingImport.accessLevel, + accessLevel); + break; + } + } + } else { + if (alreadyAddedModules) + alreadyAddedModules->insert(module); + + storage->optionalModuleImports.push_back( + {module.str(), isExported, accessLevel}); + } } void ModuleDependencyInfo::addModuleImport( - StringRef module, bool isExported, llvm::StringSet<> *alreadyAddedModules, - const SourceManager *sourceManager, SourceLoc sourceLocation) { + StringRef module, bool isExported, AccessLevel accessLevel, + llvm::StringSet<> *alreadyAddedModules, const SourceManager *sourceManager, + SourceLoc sourceLocation) { auto scannerImportLocToDiagnosticLocInfo = [&sourceManager](SourceLoc sourceLocation) { auto lineAndColumnNumbers = @@ -138,13 +158,16 @@ void ModuleDependencyInfo::addModuleImport( if (alreadyAddedModules && alreadyAddedModules->contains(module)) { // Find a prior import of this module and add import location // and adjust whether or not this module is ever imported as exported + // as well as the access level for (auto &existingImport : storage->moduleImports) { if (existingImport.importIdentifier == module) { if (validSourceLocation) { existingImport.addImportLocation( - scannerImportLocToDiagnosticLocInfo(sourceLocation)); + scannerImportLocToDiagnosticLocInfo(sourceLocation)); } existingImport.isExported |= isExported; + existingImport.accessLevel = std::max(existingImport.accessLevel, + accessLevel); break; } } @@ -154,16 +177,18 @@ void ModuleDependencyInfo::addModuleImport( if (validSourceLocation) storage->moduleImports.push_back(ScannerImportStatementInfo( - module.str(), isExported, scannerImportLocToDiagnosticLocInfo(sourceLocation))); + module.str(), isExported, accessLevel, + scannerImportLocToDiagnosticLocInfo(sourceLocation))); else storage->moduleImports.push_back( - ScannerImportStatementInfo(module.str(), isExported)); + ScannerImportStatementInfo(module.str(), isExported, accessLevel)); } } void ModuleDependencyInfo::addModuleImport( - ImportPath::Module module, bool isExported, llvm::StringSet<> *alreadyAddedModules, - const SourceManager *sourceManager, SourceLoc sourceLocation) { + ImportPath::Module module, bool isExported, AccessLevel accessLevel, + llvm::StringSet<> *alreadyAddedModules, const SourceManager *sourceManager, + SourceLoc sourceLocation) { std::string ImportedModuleName = module.front().Item.str().str(); auto submodulePath = module.getSubmodulePath(); if (submodulePath.size() > 0 && !submodulePath[0].Item.empty()) { @@ -172,11 +197,12 @@ void ModuleDependencyInfo::addModuleImport( // module named "Foo_Private". ClangImporter has special support for this. if (submoduleComponent.Item.str() == "Private") addOptionalModuleImport(ImportedModuleName + "_Private", + isExported, accessLevel, alreadyAddedModules); } - addModuleImport(ImportedModuleName, isExported, alreadyAddedModules, - sourceManager, sourceLocation); + addModuleImport(ImportedModuleName, isExported, accessLevel, + alreadyAddedModules, sourceManager, sourceLocation); } void ModuleDependencyInfo::addModuleImports( @@ -205,6 +231,7 @@ void ModuleDependencyInfo::addModuleImports( continue; addModuleImport(realPath, importDecl->isExported(), + importDecl->getAccessLevel(), &alreadyAddedModules, sourceManager, importDecl->getLoc()); diff --git a/lib/ClangImporter/ClangModuleDependencyScanner.cpp b/lib/ClangImporter/ClangModuleDependencyScanner.cpp index ad24cbaa02586..53d07866a629d 100644 --- a/lib/ClangImporter/ClangModuleDependencyScanner.cpp +++ b/lib/ClangImporter/ClangModuleDependencyScanner.cpp @@ -192,7 +192,8 @@ ModuleDependencyVector ClangImporter::bridgeClangModuleDependencies( // FIXME: This assumes, conservatively, that all Clang module imports // are exported. We need to fix this once the clang scanner gains the appropriate // API to query this. - dependencies.addModuleImport(moduleName.ModuleName, /* isExported */ true, &alreadyAddedModules); + dependencies.addModuleImport(moduleName.ModuleName, /* isExported */ true, + AccessLevel::Public, &alreadyAddedModules); // It is safe to assume that all dependencies of a Clang module are Clang modules. directDependencyIDs.push_back({moduleName.ModuleName, ModuleDependencyKind::Clang}); } diff --git a/lib/DependencyScan/DependencyScanJSON.cpp b/lib/DependencyScan/DependencyScanJSON.cpp index b41efc6883cca..f847bf572465e 100644 --- a/lib/DependencyScan/DependencyScanJSON.cpp +++ b/lib/DependencyScan/DependencyScanJSON.cpp @@ -77,6 +77,11 @@ void writeJSONValue(llvm::raw_ostream &out, bool value, unsigned indentLevel) { out.write_escaped(value ? "true" : "false"); } +/// Write a boolean value as JSON. +void writeJSONValue(llvm::raw_ostream &out, uint32_t value, unsigned indentLevel) { + out.write_escaped(std::to_string(value)); +} + /// Write a JSON array. template void writeJSONValue(llvm::raw_ostream &out, ArrayRef values, @@ -226,6 +231,90 @@ void writeLinkLibraries(llvm::raw_ostream &out, out << "\n"; } +void writeImportInfos(llvm::raw_ostream &out, + const swiftscan_import_info_set_t *imports, + unsigned indentLevel, bool trailingComma) { + out.indent(indentLevel * 2); + out << "\"imports\": "; + out << "[\n"; + + for (size_t i = 0; i < imports->count; ++i) { + const auto &iInfo = *imports->imports[i]; + out.indent((indentLevel + 1) * 2); + out << "{\n"; + auto entryIndentLevel = ((indentLevel + 2) * 2); + out.indent(entryIndentLevel); + out << "\"identifier\": "; + writeJSONValue(out, iInfo.import_identifier, indentLevel); + out << ",\n"; + out.indent(entryIndentLevel); + out << "\"accessLevel\": "; + switch (iInfo.access_level) { + case SWIFTSCAN_ACCESS_LEVEL_PRIVATE: + writeJSONValue(out, StringRef("private"), entryIndentLevel); + break; + case SWIFTSCAN_ACCESS_LEVEL_FILEPRIVATE: + writeJSONValue(out, StringRef("fileprivate"), entryIndentLevel); + break; + case SWIFTSCAN_ACCESS_LEVEL_INTERNAL: + writeJSONValue(out, StringRef("internal"), entryIndentLevel); + break; + case SWIFTSCAN_ACCESS_LEVEL_PACKAGE: + writeJSONValue(out, StringRef("package"), entryIndentLevel); + break; + case SWIFTSCAN_ACCESS_LEVEL_PUBLIC: + writeJSONValue(out, StringRef("public"), entryIndentLevel); + break; + } + + if (iInfo.source_locations->count) { + out << ",\n"; + out.indent(entryIndentLevel); + out << "\"importLocations\": "; + out << "[\n"; + auto slIndentLevel = ((entryIndentLevel + 4)); + for (size_t i = 0; i < iInfo.source_locations->count; ++i) { + out.indent(entryIndentLevel + 2); + out << "{\n"; + const auto &sl = *iInfo.source_locations->source_locations[i]; + out.indent(slIndentLevel); + out << "\"bufferIdentifier\": "; + writeJSONValue(out, sl.buffer_identifier, indentLevel); + out << ",\n"; + out.indent(slIndentLevel); + out << "\"linuNumber\": "; + writeJSONValue(out, sl.line_number, indentLevel); + out << ",\n"; + out.indent(slIndentLevel); + out << "\"columnNumber\": "; + writeJSONValue(out, sl.column_number, indentLevel); + out << "\n"; + out.indent(entryIndentLevel + 2); + out << "}"; + if (i != iInfo.source_locations->count - 1) + out << ","; + out << "\n"; + } + out.indent(entryIndentLevel); + out << "]\n"; + } else { + out << "\n"; + } + out.indent((indentLevel + 1) * 2); + out << "}"; + if (i != imports->count - 1) + out << ","; + out << "\n"; + } + + out.indent(indentLevel * 2); + out << "]"; + + if (trailingComma) + out << ","; + out << "\n"; +} + static void writeMacroDependencies(llvm::raw_ostream &out, const swiftscan_macro_dependency_set_t *macro_deps, @@ -243,15 +332,15 @@ writeMacroDependencies(llvm::raw_ostream &out, auto entryIndentLevel = ((indentLevel + 2) * 2); out.indent(entryIndentLevel); out << "\"moduleName\": "; - writeJSONValue(out, macroInfo.moduleName, indentLevel); + writeJSONValue(out, macroInfo.module_name, indentLevel); out << ",\n"; out.indent(entryIndentLevel); out << "\"libraryPath\": "; - writeJSONValue(out, macroInfo.libraryPath, entryIndentLevel); + writeJSONValue(out, macroInfo.library_path, entryIndentLevel); out << ",\n"; out.indent(entryIndentLevel); out << "\"executablePath\": "; - writeJSONValue(out, macroInfo.executablePath, entryIndentLevel); + writeJSONValue(out, macroInfo.executable_path, entryIndentLevel); out << "\n"; out.indent((indentLevel + 1) * 2); out << "}"; @@ -368,6 +457,8 @@ void writeJSON(llvm::raw_ostream &out, /*trailingComma=*/true); writeLinkLibraries(out, moduleInfo.link_libraries, 3, /*trailingComma=*/true); + writeImportInfos(out, moduleInfo.imports, + 3, /*trailingComma=*/true); } // Swift and Clang-specific details. out.indent(3 * 2); diff --git a/lib/DependencyScan/DependencyScanningTool.cpp b/lib/DependencyScan/DependencyScanningTool.cpp index e2651976c16da..157cefec7da64 100644 --- a/lib/DependencyScan/DependencyScanningTool.cpp +++ b/lib/DependencyScan/DependencyScanningTool.cpp @@ -238,6 +238,13 @@ static swiftscan_dependency_graph_t generateHollowDiagnosticOutput( hollowLinkLibrarySet->link_libraries = nullptr; hollowMainModuleInfo->link_libraries = hollowLinkLibrarySet; + // Empty Import set + swiftscan_import_info_set_t *hollowImportInfoSet = + new swiftscan_import_info_set_t; + hollowImportInfoSet->count = 0; + hollowImportInfoSet->imports = nullptr; + hollowMainModuleInfo->imports = hollowImportInfoSet; + // Populate the diagnostic info hollowResult->diagnostics = mapCollectedDiagnosticsForOutput(&ScanDiagnosticConsumer); diff --git a/lib/DependencyScan/ModuleDependencyCacheSerialization.cpp b/lib/DependencyScan/ModuleDependencyCacheSerialization.cpp index 1ca3d8e444ad2..d5817397c0902 100644 --- a/lib/DependencyScan/ModuleDependencyCacheSerialization.cpp +++ b/lib/DependencyScan/ModuleDependencyCacheSerialization.cpp @@ -415,9 +415,11 @@ bool ModuleDependenciesCacheDeserializer::readGraph( unsigned importIdentifierID, bufferIdentifierID; unsigned lineNumber, columnNumber; bool isOptional, isExported; + uint8_t rawAccessLevel; ImportStatementLayout::readRecord(Scratch, importIdentifierID, bufferIdentifierID, lineNumber, - columnNumber, isOptional, isExported); + columnNumber, isOptional, isExported, + rawAccessLevel); auto importIdentifier = getIdentifier(importIdentifierID); if (!importIdentifier) llvm::report_fatal_error("Bad import statement info: no import name"); @@ -428,10 +430,10 @@ bool ModuleDependenciesCacheDeserializer::readGraph( "Bad import statement info: no buffer identifier"); if (bufferIdentifier->empty()) ImportStatements.push_back(ScannerImportStatementInfo( - *importIdentifier, isExported)); + *importIdentifier, isExported, AccessLevel(rawAccessLevel))); else ImportStatements.push_back(ScannerImportStatementInfo( - *importIdentifier, isExported, + *importIdentifier, isExported, AccessLevel(rawAccessLevel), ScannerImportStatementInfo::ImportDiagnosticLocationInfo( *bufferIdentifier, lineNumber, columnNumber))); break; @@ -1527,7 +1529,8 @@ unsigned ModuleDependenciesCacheSerializer::writeImportStatementInfos( ImportStatementLayout::emitRecord( Out, ScratchRecord, AbbrCodes[ImportStatementLayout::Code], getIdentifier(importInfo.importIdentifier), - 0, 0, 0, isOptional, importInfo.isExported); + 0, 0, 0, isOptional, importInfo.isExported, + static_cast::type>(importInfo.accessLevel)); count++; } else { for (auto &importLoc : importInfo.importLocations) { @@ -1535,7 +1538,8 @@ unsigned ModuleDependenciesCacheSerializer::writeImportStatementInfos( Out, ScratchRecord, AbbrCodes[ImportStatementLayout::Code], getIdentifier(importInfo.importIdentifier), getIdentifier(importLoc.bufferIdentifier), importLoc.lineNumber, - importLoc.columnNumber, isOptional, importInfo.isExported); + importLoc.columnNumber, isOptional, importInfo.isExported, + static_cast::type>(importInfo.accessLevel)); count++; } } diff --git a/lib/DependencyScan/ModuleDependencyScanner.cpp b/lib/DependencyScan/ModuleDependencyScanner.cpp index fadd930d05c2d..b759c4369a365 100644 --- a/lib/DependencyScan/ModuleDependencyScanner.cpp +++ b/lib/DependencyScan/ModuleDependencyScanner.cpp @@ -544,6 +544,7 @@ ModuleDependencyScanner::getMainModuleDependencyInfo(ModuleDecl *mainModule) { case ImplicitStdlibKind::Stdlib: mainDependencies.addModuleImport("Swift", /* isExported */false, + AccessLevel::Public, &alreadyAddedModules); break; } @@ -552,6 +553,7 @@ ModuleDependencyScanner::getMainModuleDependencyInfo(ModuleDecl *mainModule) { for (const auto &import : importInfo.AdditionalUnloadedImports) { mainDependencies.addModuleImport(import.module.getModulePath(), import.options.contains(ImportFlags::Exported), + import.accessLevel, &alreadyAddedModules, &ScanASTContext.SourceMgr); } @@ -561,6 +563,7 @@ ModuleDependencyScanner::getMainModuleDependencyInfo(ModuleDecl *mainModule) { mainDependencies.addModuleImport( import.module.importedModule->getNameStr(), import.options.contains(ImportFlags::Exported), + import.accessLevel, &alreadyAddedModules); } @@ -574,6 +577,7 @@ ModuleDependencyScanner::getMainModuleDependencyInfo(ModuleDecl *mainModule) { if (importInfo.ShouldImportUnderlyingModule) { mainDependencies.addModuleImport(mainModule->getName().str(), /* isExported */ true, + AccessLevel::Public, &alreadyAddedModules); } @@ -584,6 +588,7 @@ ModuleDependencyScanner::getMainModuleDependencyInfo(ModuleDecl *mainModule) { ScanCompilerInvocation.getTBDGenOptions().embedSymbolsFromModules) { mainDependencies.addModuleImport(tbdSymbolModule, /* isExported */ false, + AccessLevel::Public, &alreadyAddedModules); } } @@ -948,7 +953,8 @@ void ModuleDependencyScanner::resolveAllClangModuleDependencies( if (importInfo.importIdentifier == ScanASTContext.Id_CxxStdlib.str()) { auto canonicalImportInfo = ScannerImportStatementInfo( - "std", importInfo.isExported, importInfo.importLocations); + "std", importInfo.isExported, importInfo.accessLevel, + importInfo.importLocations); unresolvedImports.push_back(canonicalImportInfo); unresolvedImportIdentifiers.insert( canonicalImportInfo.importIdentifier); @@ -1475,7 +1481,9 @@ void ModuleDependencyScanner::resolveCrossImportOverlayDependencies( std::for_each(newOverlays.begin(), newOverlays.end(), [&](Identifier modName) { dummyMainDependencies.addModuleImport(modName.str(), - /* isExported */ false); + /* isExported */ false, + // TODO: What is the right access level for a cross-import overlay? + AccessLevel::Public); }); // Record the dummy main module's direct dependencies. The dummy main module diff --git a/lib/DependencyScan/ScanDependencies.cpp b/lib/DependencyScan/ScanDependencies.cpp index 054b237ba82cd..42526995457da 100644 --- a/lib/DependencyScan/ScanDependencies.cpp +++ b/lib/DependencyScan/ScanDependencies.cpp @@ -747,10 +747,10 @@ static swiftscan_macro_dependency_set_t *createMacroDependencySet( unsigned SI = 0; for (auto &entry : macroDeps) { set->macro_dependencies[SI] = new swiftscan_macro_dependency_s; - set->macro_dependencies[SI]->moduleName = create_clone(entry.first.c_str()); - set->macro_dependencies[SI]->libraryPath = + set->macro_dependencies[SI]->module_name = create_clone(entry.first.c_str()); + set->macro_dependencies[SI]->library_path = create_clone(entry.second.LibraryPath.c_str()); - set->macro_dependencies[SI]->executablePath = + set->macro_dependencies[SI]->executable_path = create_clone(entry.second.ExecutablePath.c_str()); ++ SI; } @@ -976,6 +976,37 @@ generateFullDependencyGraph(const CompilerInstance &instance, linkLibrarySet->link_libraries[i] = llInfo; } moduleInfo->link_libraries = linkLibrarySet; + + // Create source import infos set for this module + auto imports = moduleDependencyInfo.getModuleImports(); + swiftscan_import_info_set_t *importInfoSet = + new swiftscan_import_info_set_t; + importInfoSet->count = imports.size(); + importInfoSet->imports = new swiftscan_import_info_t[importInfoSet->count]; + for (size_t i = 0; i < imports.size(); ++i) { + const auto &ii = imports[i]; + swiftscan_import_info_s *iInfo = new swiftscan_import_info_s; + iInfo->import_identifier = create_clone(ii.importIdentifier.c_str()); + iInfo->access_level = static_cast(ii.accessLevel); + + const auto &sourceLocations = ii.importLocations; + swiftscan_source_location_set_t *sourceLocSet = + new swiftscan_source_location_set_t; + sourceLocSet->count = sourceLocations.size(); + sourceLocSet->source_locations = + new swiftscan_source_location_t[sourceLocSet->count]; + for (size_t j = 0; j < sourceLocations.size(); ++j) { + const auto &sl = sourceLocations[j]; + swiftscan_source_location_s *slInfo = new swiftscan_source_location_s; + slInfo->buffer_identifier = create_clone(sl.bufferIdentifier.c_str()); + slInfo->line_number = sl.lineNumber; + slInfo->column_number = sl.columnNumber; + sourceLocSet->source_locations[j] = slInfo; + } + iInfo->source_locations = sourceLocSet; + importInfoSet->imports[i] = iInfo; + } + moduleInfo->imports = importInfoSet; } swiftscan_dependency_graph_t result = new swiftscan_dependency_graph_s; diff --git a/lib/Serialization/ScanningLoaders.cpp b/lib/Serialization/ScanningLoaders.cpp index 2b90236952336..28dbb3315d53e 100644 --- a/lib/Serialization/ScanningLoaders.cpp +++ b/lib/Serialization/ScanningLoaders.cpp @@ -242,6 +242,7 @@ SwiftModuleScanner::scanInterfaceFile(Twine moduleInterfacePath, for (auto import : imInfo.AdditionalUnloadedImports) { Result->addModuleImport(import.module.getModulePath(), import.options.contains(ImportFlags::Exported), + import.accessLevel, &alreadyAddedModules, &Ctx.SourceMgr); } @@ -270,6 +271,7 @@ SwiftModuleScanner::scanInterfaceFile(Twine moduleInterfacePath, if (!alreadyAddedModules.contains(requiredImport.importIdentifier)) Result->addModuleImport(requiredImport.importIdentifier, requiredImport.isExported, + requiredImport.accessLevel, &alreadyAddedModules); } } diff --git a/lib/Serialization/SerializedModuleLoader.cpp b/lib/Serialization/SerializedModuleLoader.cpp index 4f7df4ce7fb37..a72140158bb45 100644 --- a/lib/Serialization/SerializedModuleLoader.cpp +++ b/lib/Serialization/SerializedModuleLoader.cpp @@ -373,7 +373,8 @@ SerializedModuleLoaderBase::getMatchingPackageOnlyImportsOfModule( if (dotPos != std::string::npos) moduleName = moduleName.slice(0, dotPos); - importedModuleNames.push_back({moduleName.str(), dependency.isExported()}); + importedModuleNames.push_back({moduleName.str(), dependency.isExported(), + dependency.isInternalOrBelow() ? AccessLevel::Internal : AccessLevel::Public}); } return importedModuleNames; @@ -478,8 +479,7 @@ SerializedModuleLoaderBase::getImportsOfModule( const ModuleFileSharedCore &loadedModuleFile, ModuleLoadingBehavior transitiveBehavior, StringRef packageName, bool isTestableImport) { - llvm::StringSet<> importedModuleNames; - llvm::StringSet<> importedExportedModuleNames; + std::vector moduleImports; std::string importedHeader = ""; for (const auto &dependency : loadedModuleFile.getDependencies()) { if (dependency.isHeader()) { @@ -513,13 +513,13 @@ SerializedModuleLoaderBase::getImportsOfModule( if (moduleName == Ctx.Id_CxxStdlib.str()) moduleName = "std"; - importedModuleNames.insert(moduleName); - if (dependency.isExported()) - importedExportedModuleNames.insert(moduleName); + moduleImports.push_back(ScannerImportStatementInfo( + moduleName.str(), dependency.isExported(), + dependency.isInternalOrBelow() ? AccessLevel::Internal + : AccessLevel::Public)); } - return SerializedModuleLoaderBase::BinaryModuleImports{importedModuleNames, - importedExportedModuleNames, + return SerializedModuleLoaderBase::BinaryModuleImports{moduleImports, importedHeader}; } @@ -601,51 +601,33 @@ SerializedModuleLoaderBase::scanModuleFile(Twine modulePath, bool isFramework, getImportsOfModule(*loadedModuleFile, ModuleLoadingBehavior::Optional, Ctx.LangOpts.PackageName, isTestableImport); - auto importedModuleSet = binaryModuleImports->moduleImports; - std::vector moduleImports; - moduleImports.reserve(importedModuleSet.size()); - llvm::transform(importedModuleSet.keys(), std::back_inserter(moduleImports), - [&binaryModuleImports](llvm::StringRef N) { - return ScannerImportStatementInfo( - N.str(), - binaryModuleImports->exportedModules.contains(N)); - }); - - auto importedHeader = binaryModuleImports->headerImport; - auto &importedOptionalModuleSet = binaryModuleOptionalImports->moduleImports; - auto &importedExportedOptionalModuleSet = - binaryModuleOptionalImports->exportedModules; - std::vector optionalModuleImports; - for (const auto optionalImportedModule : importedOptionalModuleSet.keys()) - if (!importedModuleSet.contains(optionalImportedModule)) - optionalModuleImports.push_back( - {optionalImportedModule.str(), - importedExportedOptionalModuleSet.contains(optionalImportedModule)}); - std::vector linkLibraries; { linkLibraries.reserve(loadedModuleFile->getLinkLibraries().size()); llvm::copy(loadedModuleFile->getLinkLibraries(), std::back_inserter(linkLibraries)); if (loadedModuleFile->isFramework()) - linkLibraries.emplace_back( - loadedModuleFile->getName(), LibraryKind::Framework, - loadedModuleFile->isStaticLibrary()); + linkLibraries.emplace_back(loadedModuleFile->getName(), + LibraryKind::Framework, + loadedModuleFile->isStaticLibrary()); } // Attempt to resolve the module's defining .swiftinterface path std::string definingModulePath = - loadedModuleFile->resolveModuleDefiningFilePath(Ctx.SearchPathOpts.getSDKPath()); + loadedModuleFile->resolveModuleDefiningFilePath( + Ctx.SearchPathOpts.getSDKPath()); - std::string userModuleVer = loadedModuleFile->getUserModuleVersion().getAsString(); + std::string userModuleVer = + loadedModuleFile->getUserModuleVersion().getAsString(); std::vector serializedSearchPaths; llvm::copy(loadedModuleFile->getSearchPaths(), std::back_inserter(serializedSearchPaths)); - + // Map the set of dependencies over to the "module dependencies". auto dependencies = ModuleDependencyInfo::forSwiftBinaryModule( - modulePath.str(), moduleDocPath, sourceInfoPath, moduleImports, - optionalModuleImports, linkLibraries, serializedSearchPaths, - importedHeader, definingModulePath, isFramework, + modulePath.str(), moduleDocPath, sourceInfoPath, + binaryModuleImports->moduleImports, + binaryModuleOptionalImports->moduleImports, linkLibraries, serializedSearchPaths, + binaryModuleImports->headerImport, definingModulePath, isFramework, loadedModuleFile->isStaticLibrary(), /*module-cache-key*/ "", userModuleVer); diff --git a/lib/Tooling/libSwiftScan/libSwiftScan.cpp b/lib/Tooling/libSwiftScan/libSwiftScan.cpp index e51f8191b8c41..e3c672fdd3cc7 100644 --- a/lib/Tooling/libSwiftScan/libSwiftScan.cpp +++ b/lib/Tooling/libSwiftScan/libSwiftScan.cpp @@ -35,9 +35,9 @@ void swiftscan_macro_dependency_dispose( return; for (unsigned i = 0; i < macro->count; ++i) { - swiftscan_string_dispose(macro->macro_dependencies[i]->moduleName); - swiftscan_string_dispose(macro->macro_dependencies[i]->libraryPath); - swiftscan_string_dispose(macro->macro_dependencies[i]->executablePath); + swiftscan_string_dispose(macro->macro_dependencies[i]->module_name); + swiftscan_string_dispose(macro->macro_dependencies[i]->library_path); + swiftscan_string_dispose(macro->macro_dependencies[i]->executable_path); delete macro->macro_dependencies[i]; } delete[] macro->macro_dependencies; @@ -240,12 +240,17 @@ swiftscan_link_library_set_t *swiftscan_module_info_get_link_libraries( return info->link_libraries; } +swiftscan_import_info_set_t *swiftscan_module_info_get_imports( + swiftscan_dependency_info_t info) { + return info->imports; +} + swiftscan_module_details_t swiftscan_module_info_get_details(swiftscan_dependency_info_t info) { return info->details; } -//=== Link Library Info query APIs -----------------------------------===// +//=== Link Library Info query APIs ---------------------------------------===// swiftscan_string_ref_t swiftscan_link_library_info_get_link_name(swiftscan_link_library_info_t info) { @@ -267,7 +272,23 @@ swiftscan_link_library_info_get_should_force_load(swiftscan_link_library_info_t return info->forceLoad; } -//=== Swift Textual Module Details query APIs -----------------------------===// +//=== Import Details Query APIs ------------------------------------------===// +swiftscan_source_location_set_t * +swiftscan_import_info_get_source_locations(swiftscan_import_info_t info) { + return info->source_locations; +} + +swiftscan_string_ref_t +swiftscan_import_info_get_identifier(swiftscan_import_info_t info) { + return info->import_identifier; +} + +swiftscan_access_level_t +swiftscan_import_info_get_access_level(swiftscan_import_info_t info) { + return info->access_level; +} + +//=== Swift Textual Module Details query APIs ----------------------------===// swiftscan_dependency_info_kind_t swiftscan_module_detail_get_kind(swiftscan_module_details_t details) { diff --git a/lib/Tooling/libSwiftScan/libSwiftScan.exports b/lib/Tooling/libSwiftScan/libSwiftScan.exports index 540c0d723baf7..9eb60935f12fc 100644 --- a/lib/Tooling/libSwiftScan/libSwiftScan.exports +++ b/lib/Tooling/libSwiftScan/libSwiftScan.exports @@ -5,11 +5,15 @@ swiftscan_link_library_info_get_link_name swiftscan_link_library_info_get_is_static swiftscan_link_library_info_get_is_framework swiftscan_link_library_info_get_should_force_load +swiftscan_import_info_get_source_locations +swiftscan_import_info_get_identifier +swiftscan_import_info_get_access_level swiftscan_module_info_get_module_name swiftscan_module_info_get_module_path swiftscan_module_info_get_source_files swiftscan_module_info_get_direct_dependencies swiftscan_module_info_get_link_libraries +swiftscan_module_info_get_imports swiftscan_module_info_get_details swiftscan_module_detail_get_kind swiftscan_swift_textual_detail_get_module_interface_path diff --git a/test/ScanDependencies/eliminate_unused_vfs.swift b/test/ScanDependencies/eliminate_unused_vfs.swift index 854d6d290139e..d59fb245b28d5 100644 --- a/test/ScanDependencies/eliminate_unused_vfs.swift +++ b/test/ScanDependencies/eliminate_unused_vfs.swift @@ -75,7 +75,8 @@ import F /// Check that the dependency swift module hashes are identical when the vfs overlays are ignored. // MOD-HASH: "mainModuleName": "deps", // MOD-HASH: "linkLibraries": [], -// MOD-HASH-NEXT: "details": { +// MOD-HASH: "imports": [ +// MOD-HASH: "details": { // MOD-HASH-NEXT: "swift": { // MOD-HASH-NEXT: "moduleInterfacePath": "{{.*}}{{/|\\}}F.swiftinterface", // MOD-HASH: "commandLine": [ @@ -86,6 +87,7 @@ import F // MOD-HASH: ], // MOD-HASH: "mainModuleName": "deps1", // MOD-HASH: "linkLibraries": [], +// MOD-HASH: "imports": [ // MOD-HASH: "details": { // MOD-HASH-NEXT: "swift": { // MOD-HASH-NEXT: "moduleInterfacePath": "{{.*}}{{/|\\}}F.swiftinterface", @@ -97,6 +99,7 @@ import F // MOD-HASH: ], // MOD-HASH: "mainModuleName": "deps2", // MOD-HASH: "linkLibraries": [], +// MOD-HASH: "imports": [ // MOD-HASH: "details": { // MOD-HASH-NEXT: "swift": { // MOD-HASH-NEXT: "moduleInterfacePath": "{{.*}}{{/|\\}}F.swiftinterface", diff --git a/test/ScanDependencies/import_infos.swift b/test/ScanDependencies/import_infos.swift new file mode 100644 index 0000000000000..021fd84783943 --- /dev/null +++ b/test/ScanDependencies/import_infos.swift @@ -0,0 +1,72 @@ +// RUN: %empty-directory(%t) +// RUN: %empty-directory(%t/module-cache) + +// RUN: %target-swift-frontend -scan-dependencies -module-cache-path %t/module-cache %s -o %t/deps.json -I %S/Inputs/CHeaders -I %S/Inputs/Swift -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import +// RUN: %validate-json %t/deps.json | %FileCheck %s + +// CHECK: "mainModuleName": "deps" +// CHECK: "swift": "deps" +// CHECK: "modulePath": "deps.swiftmodule" + +// CHECK: "imports": [ +// CHECK-NEXT: { +// CHECK-NEXT: "identifier": "Swift" +// CHECK-NEXT: "accessLevel": "public" +// CHECK-NEXT: } +// CHECK-NEXT: { +// CHECK-NEXT: "identifier": "SwiftOnoneSupport" +// CHECK-NEXT: "accessLevel": "public" +// CHECK-NEXT: } +// CHECK-NEXT: { +// CHECK-NEXT: "identifier": "C" +// CHECK-NEXT: "accessLevel": "internal" +// CHECK-NEXT: "importLocations": [ +// CHECK-NEXT: { +// CHECK-NEXT: "bufferIdentifier": "{{.*}}import_infos.swift" +// CHECK-NEXT: "linuNumber": 65 +// CHECK-NEXT: "columnNumber": 17 +// CHECK-NEXT: } +// CHECK-NEXT: { +// CHECK-NEXT: "bufferIdentifier": "{{.*}}import_infos.swift" +// CHECK-NEXT: "linuNumber": 72 +// CHECK-NEXT: "columnNumber": 16 +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: { +// CHECK-NEXT: "identifier": "E" +// CHECK-NEXT: "accessLevel": "public" +// CHECK-NEXT: "importLocations": [ +// CHECK-NEXT: { +// CHECK-NEXT: "bufferIdentifier": "{{.*}}import_infos.swift" +// CHECK-NEXT: "linuNumber": 67 +// CHECK-NEXT: "columnNumber": 15 +// CHECK-NEXT: } +// CHECK-NEXT: { +// CHECK-NEXT: "bufferIdentifier": "{{.*}}import_infos.swift" +// CHECK-NEXT: "linuNumber": 68 +// CHECK-NEXT: "columnNumber": 8 +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: { +// CHECK-NEXT: "identifier": "G" +// CHECK-NEXT: "accessLevel": "fileprivate" +// CHECK-NEXT: "importLocations": [ +// CHECK-NEXT: { +// CHECK-NEXT: "bufferIdentifier": "{{.*}}import_infos.swift" +// CHECK-NEXT: "linuNumber": 70 +// CHECK-NEXT: "columnNumber": 20 +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] + +internal import C + +public import E +import E + +fileprivate import G + +private import C diff --git a/test/ScanDependencies/module_deps_cache_reuse.swift b/test/ScanDependencies/module_deps_cache_reuse.swift index fc11cfadb2660..2d2d8eba9a45a 100644 --- a/test/ScanDependencies/module_deps_cache_reuse.swift +++ b/test/ScanDependencies/module_deps_cache_reuse.swift @@ -128,7 +128,7 @@ import SubE // CHECK: ], // CHECK-NEXT: "linkLibraries": [ // CHECK-NEXT: ], -// CHECK-NEXT: "details": { +// CHECK: "details": { // CHECK: "commandLine": [ // CHECK: "-compile-module-from-interface" diff --git a/test/ScanDependencies/module_deps_different_paths_no_reuse.swift b/test/ScanDependencies/module_deps_different_paths_no_reuse.swift index f0d76411b46d0..a535a68619e47 100644 --- a/test/ScanDependencies/module_deps_different_paths_no_reuse.swift +++ b/test/ScanDependencies/module_deps_different_paths_no_reuse.swift @@ -29,7 +29,7 @@ import A // CHECK-INITIAL-SCAN: ], // CHECK-INITIAL-SCAN-NEXT: "linkLibraries": [ // CHECK-INITIAL-SCAN-NEXT: ], -// CHECK-INITIAL-SCAN-NEXT: "details": { +// CHECK-INITIAL-SCAN: "details": { // CHECK-INITIAL-SCAN-NEXT: "swift": { // CHECK-INITIAL-SCAN-NEXT: "moduleInterfacePath": "{{.*}}/Swift/A.swiftinterface", @@ -43,6 +43,6 @@ import A // CHECK-DIFFERENT: ], // CHECK-DIFFERENT-NEXT: "linkLibraries": [ // CHECK-DIFFERENT-NEXT: ], -// CHECK-DIFFERENT-NEXT: "details": { +// CHECK-DIFFERENT: "details": { // CHECK-DIFFERENT-NEXT: "swift": { // CHECK-DIFFERENT-NEXT: "moduleInterfacePath": "{{.*}}/SwiftDifferent/A.swiftinterface",