diff --git a/include/swift-c/DependencyScan/DependencyScan.h b/include/swift-c/DependencyScan/DependencyScan.h index c8e48b1ace62f..8320435945672 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 0 -#define SWIFTSCAN_VERSION_MINOR 8 +#define SWIFTSCAN_VERSION_MINOR 9 SWIFTSCAN_BEGIN_DECLS @@ -55,6 +55,9 @@ typedef struct swiftscan_import_set_s *swiftscan_import_set_t; /// Opaque container to contain the info of a diagnostics emitted by the scanner. typedef struct swiftscan_diagnostic_info_s *swiftscan_diagnostic_info_t; +/// Opaque container to contain the info of a source location. +typedef struct swiftscan_source_location_s *swiftscan_source_location_t; + /// Full Dependency Graph (Result) typedef struct { swiftscan_dependency_info_t *modules; @@ -419,9 +422,22 @@ swiftscan_diagnostic_get_message(swiftscan_diagnostic_info_t diagnostic); SWIFTSCAN_PUBLIC swiftscan_diagnostic_severity_t swiftscan_diagnostic_get_severity(swiftscan_diagnostic_info_t diagnostic); +SWIFTSCAN_PUBLIC swiftscan_source_location_t +swiftscan_diagnostic_get_source_location(swiftscan_diagnostic_info_t diagnostic); + SWIFTSCAN_PUBLIC void swiftscan_diagnostics_set_dispose(swiftscan_diagnostic_set_t* diagnostics); +//=== Source Location -----------------------------------------------------===// +SWIFTSCAN_PUBLIC swiftscan_string_ref_t +swiftscan_source_location_get_buffer_identifier(swiftscan_source_location_t source_location); + +SWIFTSCAN_PUBLIC int64_t +swiftscan_source_location_get_line_number(swiftscan_source_location_t source_location); + +SWIFTSCAN_PUBLIC int64_t +swiftscan_source_location_get_column_number(swiftscan_source_location_t source_location); + //=== Scanner Cache Operations --------------------------------------------===// // The following operations expose an implementation detail of the dependency // scanner: its module dependencies cache. This is done in order diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index 9d6ff5e972266..9252d1e91eb81 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -2206,6 +2206,8 @@ ERROR(alignment_not_power_of_two,none, // Dependency Scanning ERROR(dependency_scan_module_not_found, none, "Unable to find module dependency: '%0'", (StringRef)) +NOTE(unresolved_import_location,none, + "also imported here", ()) NOTE(dependency_as_imported_by_main_module,none, "a dependency of main module '%0'", (StringRef)) NOTE(dependency_as_imported_by, none, diff --git a/include/swift/AST/ModuleDependencies.h b/include/swift/AST/ModuleDependencies.h index a952243fb9e1d..edcf07d957cc5 100644 --- a/include/swift/AST/ModuleDependencies.h +++ b/include/swift/AST/ModuleDependencies.h @@ -129,6 +129,39 @@ namespace dependencies { bool); } +struct ScannerImportStatementInfo { + struct ImportDiagnosticLocationInfo { + ImportDiagnosticLocationInfo() = delete; + ImportDiagnosticLocationInfo(std::string bufferIdentifier, + uint32_t lineNumber, + uint32_t columnNumber) + : bufferIdentifier(bufferIdentifier), + lineNumber(lineNumber), + columnNumber(columnNumber) {} + std::string bufferIdentifier; + uint32_t lineNumber; + uint32_t columnNumber; + }; + + ScannerImportStatementInfo(std::string importIdentifier) + : importLocations(), + importIdentifier(importIdentifier) {} + + ScannerImportStatementInfo(std::string importIdentifier, + ImportDiagnosticLocationInfo location) + : importLocations({location}), + importIdentifier(importIdentifier) {} + + 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; +}; + /// Base class for the variant storage of ModuleDependencyInfo. /// /// This class is mostly an implementation detail for \c ModuleDependencyInfo. @@ -141,25 +174,27 @@ class ModuleDependencyInfoStorageBase { : dependencyKind(dependencyKind), moduleCacheKey(moduleCacheKey.str()), resolved(false), finalized(false) {} - ModuleDependencyInfoStorageBase(ModuleDependencyKind dependencyKind, - const std::vector &moduleImports, - const std::vector &optionalModuleImports, - StringRef moduleCacheKey = "") + ModuleDependencyInfoStorageBase( + ModuleDependencyKind dependencyKind, + const std::vector &moduleImports, + const std::vector &optionalModuleImports, + StringRef moduleCacheKey = "") : dependencyKind(dependencyKind), moduleImports(moduleImports), optionalModuleImports(optionalModuleImports), - moduleCacheKey(moduleCacheKey.str()), resolved(false), finalized(false) {} + moduleCacheKey(moduleCacheKey.str()), resolved(false), + finalized(false) {} virtual ModuleDependencyInfoStorageBase *clone() const = 0; virtual ~ModuleDependencyInfoStorageBase(); /// The set of modules on which this module depends. - std::vector moduleImports; + std::vector moduleImports; /// The set of modules which constitute optional module /// dependencies for this module, such as `@_implementationOnly` /// or `internal` imports. - std::vector optionalModuleImports; + std::vector optionalModuleImports; /// The set of modules on which this module depends, resolved /// to Module IDs, qualified by module kind: Swift, Clang, etc. @@ -320,21 +355,23 @@ class SwiftSourceModuleDependenciesStorage : } }; -/// Describes the dependencies of a pre-built Swift module (with no .swiftinterface). +/// Describes the dependencies of a pre-built Swift module (with no +/// .swiftinterface). /// /// This class is mostly an implementation detail for \c ModuleDependencyInfo. -class SwiftBinaryModuleDependencyStorage : public ModuleDependencyInfoStorageBase { +class SwiftBinaryModuleDependencyStorage + : public ModuleDependencyInfoStorageBase { public: - SwiftBinaryModuleDependencyStorage(const std::string &compiledModulePath, - const std::string &moduleDocPath, - const std::string &sourceInfoPath, - const std::vector &moduleImports, - const std::vector &optionalModuleImports, - const std::string &headerImport, - const bool isFramework, - const std::string &moduleCacheKey) + SwiftBinaryModuleDependencyStorage( + const std::string &compiledModulePath, const std::string &moduleDocPath, + const std::string &sourceInfoPath, + const std::vector &moduleImports, + const std::vector &optionalModuleImports, + const std::string &headerImport, const bool isFramework, + const std::string &moduleCacheKey) : ModuleDependencyInfoStorageBase(ModuleDependencyKind::SwiftBinary, - moduleImports, optionalModuleImports, moduleCacheKey), + moduleImports, optionalModuleImports, + moduleCacheKey), compiledModulePath(compiledModulePath), moduleDocPath(moduleDocPath), sourceInfoPath(sourceInfoPath), headerImport(headerImport), isFramework(isFramework) {} @@ -520,8 +557,8 @@ class ModuleDependencyInfo { const std::string &compiledModulePath, const std::string &moduleDocPath, const std::string &sourceInfoPath, - const std::vector &moduleImports, - const std::vector &optionalModuleImports, + const std::vector &moduleImports, + const std::vector &optionalModuleImports, const std::string &headerImport, bool isFramework, const std::string &moduleCacheKey) { return ModuleDependencyInfo( @@ -572,12 +609,12 @@ class ModuleDependencyInfo { } /// Retrieve the module-level imports. - ArrayRef getModuleImports() const { + ArrayRef getModuleImports() const { return storage->moduleImports; } /// Retrieve the module-level optional imports. - ArrayRef getOptionalModuleImports() const { + ArrayRef getOptionalModuleImports() const { return storage->optionalModuleImports; } @@ -754,31 +791,24 @@ class ModuleDependencyInfo { void addOptionalModuleImport(StringRef module, llvm::StringSet<> *alreadyAddedModules = nullptr); + /// Add all of the module imports in the given source + /// file to the set of module imports. + void addModuleImports(const SourceFile &sourceFile, + llvm::StringSet<> &alreadyAddedModules, + const SourceManager *sourceManager); /// Add a dependency on the given module, if it was not already in the set. - void addModuleImport(StringRef module, - llvm::StringSet<> *alreadyAddedModules = nullptr); + void addModuleImport(ImportPath::Module module, + 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(ImportPath::Module module, - llvm::StringSet<> *alreadyAddedModules = nullptr) { - std::string ImportedModuleName = module.front().Item.str().str(); - auto submodulePath = module.getSubmodulePath(); - if (submodulePath.size() > 0 && !submodulePath[0].Item.empty()) { - auto submoduleComponent = submodulePath[0]; - // Special case: a submodule named "Foo.Private" can be moved to a top-level - // module named "Foo_Private". ClangImporter has special support for this. - if (submoduleComponent.Item.str() == "Private") - addOptionalModuleImport(ImportedModuleName + "_Private", alreadyAddedModules); - } - - addModuleImport(ImportedModuleName, alreadyAddedModules); - } + void addModuleImport(StringRef module, + llvm::StringSet<> *alreadyAddedModules = nullptr, + const SourceManager *sourceManager = nullptr, + SourceLoc sourceLocation = SourceLoc()); - /// Add all of the module imports in the given source - /// file to the set of module imports. - void addModuleImport(const SourceFile &sf, - llvm::StringSet<> &alreadyAddedModules); /// Add a kind-qualified module dependency ID to the set of /// module dependencies. void addModuleDependency(ModuleDependencyID dependencyID); diff --git a/include/swift/DependencyScan/DependencyScanImpl.h b/include/swift/DependencyScan/DependencyScanImpl.h index 857501548cab6..a00dff1d6749a 100644 --- a/include/swift/DependencyScan/DependencyScanImpl.h +++ b/include/swift/DependencyScan/DependencyScanImpl.h @@ -21,7 +21,7 @@ namespace swift { namespace dependencies { class DependencyScanningTool; -} +} // namespace dependencies } // namespace swift struct swiftscan_dependency_graph_s { @@ -212,7 +212,13 @@ struct swiftscan_scan_invocation_s { struct swiftscan_diagnostic_info_s { swiftscan_string_ref_t message; swiftscan_diagnostic_severity_t severity; - // TODO: SourceLoc + swiftscan_source_location_t source_location; +}; + +struct swiftscan_source_location_s { + swiftscan_string_ref_t buffer_identifier; + uint32_t line_number; + uint32_t column_number; }; #endif // SWIFT_C_DEPENDENCY_SCAN_IMPL_H diff --git a/include/swift/DependencyScan/DependencyScanningTool.h b/include/swift/DependencyScan/DependencyScanningTool.h index 1709365ba46b9..6ec5b1f75170e 100644 --- a/include/swift/DependencyScan/DependencyScanningTool.h +++ b/include/swift/DependencyScan/DependencyScanningTool.h @@ -37,10 +37,11 @@ class DependencyScanDiagnosticCollector : public DiagnosticConsumer { struct ScannerDiagnosticInfo { std::string Message; llvm::SourceMgr::DiagKind Severity; + std::optional ImportLocation; }; + std::vector Diagnostics; void handleDiagnostic(SourceManager &SM, const DiagnosticInfo &Info) override; - std::vector Diagnostics; protected: virtual void addDiagnostic(SourceManager &SM, const DiagnosticInfo &Info); diff --git a/lib/AST/ModuleDependencies.cpp b/lib/AST/ModuleDependencies.cpp index eeee5b0f92eeb..03284d448fbd6 100644 --- a/lib/AST/ModuleDependencies.cpp +++ b/lib/AST/ModuleDependencies.cpp @@ -121,16 +121,67 @@ void ModuleDependencyInfo::addOptionalModuleImport( } void ModuleDependencyInfo::addModuleImport( - StringRef module, llvm::StringSet<> *alreadyAddedModules) { - if (!alreadyAddedModules || alreadyAddedModules->insert(module).second) - storage->moduleImports.push_back(module.str()); + StringRef module, llvm::StringSet<> *alreadyAddedModules, + const SourceManager *sourceManager, SourceLoc sourceLocation) { + auto scannerImportLocToDiagnosticLocInfo = + [&sourceManager](SourceLoc sourceLocation) { + auto lineAndColumnNumbers = + sourceManager->getLineAndColumnInBuffer(sourceLocation); + return ScannerImportStatementInfo::ImportDiagnosticLocationInfo( + sourceManager->getDisplayNameForLoc(sourceLocation).str(), + lineAndColumnNumbers.first, lineAndColumnNumbers.second); + }; + bool validSourceLocation = sourceManager && sourceLocation.isValid() && + sourceManager->isOwning(sourceLocation); + + if (alreadyAddedModules && alreadyAddedModules->contains(module)) { + if (validSourceLocation) { + // Find a prior import of this module and add import location + for (auto &existingImport : storage->moduleImports) { + if (existingImport.importIdentifier == module) { + existingImport.addImportLocation( + scannerImportLocToDiagnosticLocInfo(sourceLocation)); + break; + } + } + } + } else { + if (alreadyAddedModules) + alreadyAddedModules->insert(module); + + if (validSourceLocation) + storage->moduleImports.push_back(ScannerImportStatementInfo( + module.str(), scannerImportLocToDiagnosticLocInfo(sourceLocation))); + else + storage->moduleImports.push_back( + ScannerImportStatementInfo(module.str())); + } } void ModuleDependencyInfo::addModuleImport( - const SourceFile &sf, llvm::StringSet<> &alreadyAddedModules) { + ImportPath::Module module, 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()) { + auto submoduleComponent = submodulePath[0]; + // Special case: a submodule named "Foo.Private" can be moved to a top-level + // module named "Foo_Private". ClangImporter has special support for this. + if (submoduleComponent.Item.str() == "Private") + addOptionalModuleImport(ImportedModuleName + "_Private", + alreadyAddedModules); + } + + addModuleImport(ImportedModuleName, alreadyAddedModules, + sourceManager, sourceLocation); +} + +void ModuleDependencyInfo::addModuleImports( + const SourceFile &sourceFile, llvm::StringSet<> &alreadyAddedModules, + const SourceManager *sourceManager) { // Add all of the module dependencies. SmallVector decls; - sf.getTopLevelDecls(decls); + sourceFile.getTopLevelDecls(decls); for (auto decl : decls) { auto importDecl = dyn_cast(decl); if (!importDecl) @@ -149,10 +200,12 @@ void ModuleDependencyInfo::addModuleImport( // Ignore/diagnose tautological imports akin to import resolution if (!swift::dependencies::checkImportNotTautological( - realPath, importDecl->getLoc(), sf, importDecl->isExported())) + realPath, importDecl->getLoc(), sourceFile, + importDecl->isExported())) continue; - addModuleImport(realPath, &alreadyAddedModules); + addModuleImport(realPath, &alreadyAddedModules, + sourceManager, importDecl->getLoc()); // Additionally, keep track of which dependencies of a Source // module are `@Testable`. @@ -161,7 +214,7 @@ void ModuleDependencyInfo::addModuleImport( addTestableImport(realPath); } - auto fileName = sf.getFilename(); + auto fileName = sourceFile.getFilename(); if (fileName.empty()) return; diff --git a/lib/DependencyScan/DependencyScanningTool.cpp b/lib/DependencyScan/DependencyScanningTool.cpp index 04f6fbce34f52..10cb1359cb6cd 100644 --- a/lib/DependencyScan/DependencyScanningTool.cpp +++ b/lib/DependencyScan/DependencyScanningTool.cpp @@ -10,14 +10,15 @@ // //===----------------------------------------------------------------------===// -#include "swift/DependencyScan/DependencyScanningTool.h" -#include "swift/DependencyScan/SerializedModuleDependencyCacheFormat.h" -#include "swift/DependencyScan/StringUtils.h" #include "swift/AST/DiagnosticEngine.h" #include "swift/AST/DiagnosticsFrontend.h" #include "swift/Basic/LLVMInitialize.h" #include "swift/Basic/TargetInfo.h" +#include "swift/Basic/ColorUtils.h" +#include "swift/DependencyScan/DependencyScanningTool.h" #include "swift/DependencyScan/DependencyScanImpl.h" +#include "swift/DependencyScan/SerializedModuleDependencyCacheFormat.h" +#include "swift/DependencyScan/StringUtils.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/VirtualOutputBackends.h" @@ -94,25 +95,43 @@ void DependencyScanDiagnosticCollector::addDiagnostic( SMKind = llvm::SourceMgr::DK_Remark; break; } + // Translate ranges. SmallVector Ranges; for (auto R : Info.Ranges) Ranges.push_back(getRawRange(SM, R)); + // Translate fix-its. SmallVector FixIts; for (DiagnosticInfo::FixIt F : Info.FixIts) FixIts.push_back(getRawFixIt(SM, F)); - std::string ResultingMessage; - llvm::raw_string_ostream Stream(ResultingMessage); - + // Display the diagnostic. + std::string FormattedMessage; + llvm::raw_string_ostream Stream(FormattedMessage); // Actually substitute the diagnostic arguments into the diagnostic text. llvm::SmallString<256> Text; - llvm::raw_svector_ostream Out(Text); - DiagnosticEngine::formatDiagnosticText(Out, Info.FormatString, - Info.FormatArgs); - auto Msg = SM.GetMessage(Info.Loc, SMKind, Text, Ranges, FixIts); - Diagnostics.push_back(ScannerDiagnosticInfo{Msg.getMessage().str(), SMKind}); + { + llvm::raw_svector_ostream Out(Text); + DiagnosticEngine::formatDiagnosticText(Out, Info.FormatString, + Info.FormatArgs); + auto Msg = SM.GetMessage(Info.Loc, SMKind, Text, Ranges, FixIts, true); + Msg.print(nullptr, Stream, false, false, false); + Stream.flush(); + } + + if (Info.Loc && Info.Loc.isValid()) { + auto bufferIdentifier = SM.getDisplayNameForLoc(Info.Loc); + auto lineAndColumnNumbers = SM.getLineAndColumnInBuffer(Info.Loc); + auto importLocation = ScannerImportStatementInfo::ImportDiagnosticLocationInfo( + bufferIdentifier.str(), lineAndColumnNumbers.first, + lineAndColumnNumbers.second); + Diagnostics.push_back( + ScannerDiagnosticInfo{FormattedMessage, SMKind, importLocation}); + } else { + Diagnostics.push_back( + ScannerDiagnosticInfo{FormattedMessage, SMKind, std::nullopt}); + } } void LockingDependencyScanDiagnosticCollector::addDiagnostic( diff --git a/lib/DependencyScan/ModuleDependencyCacheSerialization.cpp b/lib/DependencyScan/ModuleDependencyCacheSerialization.cpp index aa3801c9344d1..3783957c3099c 100644 --- a/lib/DependencyScan/ModuleDependencyCacheSerialization.cpp +++ b/lib/DependencyScan/ModuleDependencyCacheSerialization.cpp @@ -155,9 +155,9 @@ bool ModuleDependenciesCacheDeserializer::readGraph(SwiftDependencyScanningServi bool hasCurrentModule = false; std::string currentModuleName; unsigned currentContextHashID; - std::optional> currentModuleImports; - std::optional> currentOptionalModuleImports; - std::optional> currentModuleDependencyIDs; + std::vector currentModuleImports; + std::vector currentOptionalModuleImports; + std::vector currentModuleDependencyIDs; auto getContextHash = [&]() { assert(currentContextHashID && @@ -225,15 +225,22 @@ bool ModuleDependenciesCacheDeserializer::readGraph(SwiftDependencyScanningServi llvm::report_fatal_error("Bad module name"); currentModuleName = *moduleName; currentContextHashID = contextHashID; - currentModuleImports = getStringArray(moduleImportsArrayID); - currentOptionalModuleImports = getStringArray(optionalModuleImportsArrayID); - currentModuleDependencyIDs = getModuleDependencyIDArray(moduleDependencyIDArrayID); - if (!currentModuleImports) - llvm::report_fatal_error("Bad direct dependencies: no imports"); - if (!currentOptionalModuleImports) - llvm::report_fatal_error("Bad direct dependencies: no optional imports"); - if (!currentModuleDependencyIDs) + auto importStrings = getStringArray(moduleImportsArrayID); + auto optionalImportStrings = getStringArray(optionalModuleImportsArrayID); + if (importStrings.has_value()) { + for (const auto &is : importStrings.value()) + currentModuleImports.push_back(is); + } + + if (optionalImportStrings.has_value()) { + for (const auto &ois : optionalImportStrings.value()) + currentOptionalModuleImports.push_back(ois); + } + + auto optionalCurrentModuleDependencyIDs = getModuleDependencyIDArray(moduleDependencyIDArrayID); + if (!optionalCurrentModuleDependencyIDs) llvm::report_fatal_error("Bad direct dependencies: no qualified dependencies"); + currentModuleDependencyIDs = optionalCurrentModuleDependencyIDs.value(); break; } @@ -301,14 +308,14 @@ bool ModuleDependenciesCacheDeserializer::readGraph(SwiftDependencyScanningServi *contextHash, isFramework, *rootFileSystemID, *moduleCacheKey); // Add imports of this module - for (const auto &moduleName : *currentModuleImports) - moduleDep.addModuleImport(moduleName); + for (const auto &moduleName : currentModuleImports) + moduleDep.addModuleImport(moduleName.importIdentifier); // Add optional imports of this module - for (const auto &moduleName : *currentOptionalModuleImports) - moduleDep.addOptionalModuleImport(moduleName); + for (const auto &moduleName : currentOptionalModuleImports) + moduleDep.addOptionalModuleImport(moduleName.importIdentifier); // Add qualified dependencies of this module - moduleDep.resolveDirectDependencies(*currentModuleDependencyIDs); + moduleDep.resolveDirectDependencies(currentModuleDependencyIDs); // Add bridging header file path if (bridgingHeaderFileID != 0) { @@ -412,11 +419,11 @@ bool ModuleDependenciesCacheDeserializer::readGraph(SwiftDependencyScanningServi extraPCMRefs); // Add dependencies of this module - for (const auto &moduleName : *currentModuleImports) - moduleDep.addModuleImport(moduleName); + for (const auto &moduleName : currentModuleImports) + moduleDep.addModuleImport(moduleName.importIdentifier); // Add optional imports of this module - for (const auto &moduleName : *currentOptionalModuleImports) - moduleDep.addOptionalModuleImport(moduleName); + for (const auto &moduleName : currentOptionalModuleImports) + moduleDep.addOptionalModuleImport(moduleName.importIdentifier); // Add bridging header file path if (bridgingHeaderFileID != 0) { @@ -504,7 +511,7 @@ bool ModuleDependenciesCacheDeserializer::readGraph(SwiftDependencyScanningServi // Form the dependencies storage object auto moduleDep = ModuleDependencyInfo::forSwiftBinaryModule( *compiledModulePath, *moduleDocPath, *moduleSourceInfoPath, - *currentModuleImports, *currentOptionalModuleImports, + currentModuleImports, currentOptionalModuleImports, *headerImport, isFramework, *moduleCacheKey); auto headerModuleDependencies = getStringArray(headerModuleDependenciesArrayID); @@ -555,12 +562,13 @@ bool ModuleDependenciesCacheDeserializer::readGraph(SwiftDependencyScanningServi // Form the dependencies storage object auto moduleDep = ModuleDependencyInfo::forPlaceholderSwiftModuleStub( *compiledModulePath, *moduleDocPath, *moduleSourceInfoPath); + // Add dependencies of this module - for (const auto &moduleName : *currentModuleImports) - moduleDep.addModuleImport(moduleName); + for (const auto &moduleName : currentModuleImports) + moduleDep.addModuleImport(moduleName.importIdentifier); // Add optional imports of this module - for (const auto &moduleName : *currentOptionalModuleImports) - moduleDep.addOptionalModuleImport(moduleName); + for (const auto &moduleName : currentOptionalModuleImports) + moduleDep.addOptionalModuleImport(moduleName.importIdentifier); cache.recordDependency(currentModuleName, std::move(moduleDep), getContextHash()); @@ -618,11 +626,11 @@ bool ModuleDependenciesCacheDeserializer::readGraph(SwiftDependencyScanningServi *rootFileSystemID, *clangIncludeTreeRoot, *moduleCacheKey, isSystem); // Add dependencies of this module - for (const auto &moduleName : *currentModuleImports) - moduleDep.addModuleImport(moduleName); + for (const auto &moduleName : currentModuleImports) + moduleDep.addModuleImport(moduleName.importIdentifier); // Add optional imports of this module - for (const auto &moduleName : *currentOptionalModuleImports) - moduleDep.addOptionalModuleImport(moduleName); + for (const auto &moduleName : currentOptionalModuleImports) + moduleDep.addOptionalModuleImport(moduleName.importIdentifier); cache.recordDependency(currentModuleName, std::move(moduleDep), getContextHash()); @@ -1162,11 +1170,27 @@ void ModuleDependenciesCacheSerializer::collectStringsAndArrays( auto dependencyInfo = optionalDependencyInfo.value(); // Add the module's name addIdentifier(moduleID.ModuleName); + + // Map import infos to their respective module identifiers + auto importInfoArrayToIdentifier = + [](const auto &importInfo) -> std::string { + return importInfo.importIdentifier; + }; + // Add the module's dependencies + std::vector importIdentifiers; + llvm::transform(dependencyInfo->getModuleImports(), + std::back_inserter(importIdentifiers), + importInfoArrayToIdentifier); + std::vector optionalImportIdentifiers; + llvm::transform(dependencyInfo->getOptionalModuleImports(), + std::back_inserter(optionalImportIdentifiers), + importInfoArrayToIdentifier); + addStringArray(moduleID, ModuleIdentifierArrayKind::DependencyImports, - dependencyInfo->getModuleImports()); + importIdentifiers); addStringArray(moduleID, ModuleIdentifierArrayKind::OptionalDependencyImports, - dependencyInfo->getOptionalModuleImports()); + optionalImportIdentifiers); addDependencyIDArray( moduleID, ModuleIdentifierArrayKind::QualifiedModuleDependencyIDs, dependencyInfo->getDirectModuleDependencies()); diff --git a/lib/DependencyScan/ModuleDependencyScanner.cpp b/lib/DependencyScan/ModuleDependencyScanner.cpp index 19454b3972e7c..179bbceb91d13 100644 --- a/lib/DependencyScan/ModuleDependencyScanner.cpp +++ b/lib/DependencyScan/ModuleDependencyScanner.cpp @@ -54,14 +54,15 @@ static void findPath_dfs(ModuleDependencyID X, ModuleDependencyID Y, std::optional lookupKind = std::nullopt; // Underlying Clang module needs an explicit lookup to avoid confusing it // with the parent Swift module. - if ((dep == X.ModuleName && node->isSwiftModule()) || node->isClangModule()) + if ((dep.importIdentifier == X.ModuleName && node->isSwiftModule()) || + node->isClangModule()) lookupKind = ModuleDependencyKind::Clang; - auto optionalDepNode = cache.findDependency(dep, lookupKind); + auto optionalDepNode = cache.findDependency(dep.importIdentifier, lookupKind); if (!optionalDepNode.has_value()) continue; auto depNode = optionalDepNode.value(); - auto depID = ModuleDependencyID{dep, depNode->getKind()}; + auto depID = ModuleDependencyID{dep.importIdentifier, depNode->getKind()}; if (!visited.count(depID)) { findPath_dfs(depID, Y, visited, stack, result, cache); } @@ -89,11 +90,20 @@ findPathToDependency(ModuleDependencyID dependency, // Diagnose scanner failure and attempt to reconstruct the dependency // path from the main module to the missing dependency. static void -diagnoseScannerFailure(StringRef moduleName, DiagnosticEngine &Diags, +diagnoseScannerFailure(const ScannerImportStatementInfo &moduleImport, + DiagnosticEngine &Diags, const ModuleDependenciesCache &cache, std::optional dependencyOf) { - Diags.diagnose(SourceLoc(), diag::dependency_scan_module_not_found, - moduleName); + SourceLoc importLoc = SourceLoc(); + if (!moduleImport.importLocations.empty()) { + auto locInfo = moduleImport.importLocations[0]; + importLoc = Diags.SourceMgr.getLocFromExternalSource(locInfo.bufferIdentifier, + locInfo.lineNumber, + locInfo.columnNumber); + } + + Diags.diagnose(importLoc, diag::dependency_scan_module_not_found, + moduleImport.importIdentifier); if (dependencyOf.has_value()) { auto path = findPathToDependency(dependencyOf.value(), cache); // We may fail to construct a path in some cases, such as a Swift overlay of @@ -110,7 +120,7 @@ diagnoseScannerFailure(StringRef moduleName, DiagnosticEngine &Diags, bool isClang = false; switch (entryNode->getKind()) { case swift::ModuleDependencyKind::SwiftSource: - Diags.diagnose(SourceLoc(), diag::dependency_as_imported_by_main_module, + Diags.diagnose(importLoc, diag::dependency_as_imported_by_main_module, entry.ModuleName); continue; case swift::ModuleDependencyKind::SwiftInterface: @@ -133,13 +143,20 @@ diagnoseScannerFailure(StringRef moduleName, DiagnosticEngine &Diags, llvm_unreachable("Unexpected dependency kind"); } - // TODO: Consider turning the module file (interface or modulemap) into - // the SourceLoc of this diagnostic instead. Ideally with the location of - // the `import` statement that this dependency originates from. - Diags.diagnose(SourceLoc(), diag::dependency_as_imported_by, + Diags.diagnose(importLoc, diag::dependency_as_imported_by, entry.ModuleName, moduleFilePath, isClang); } } + + if (moduleImport.importLocations.size() > 1) { + for (size_t i = 1; i < moduleImport.importLocations.size(); ++i) { + auto locInfo = moduleImport.importLocations[i]; + auto importLoc = Diags.SourceMgr.getLocFromExternalSource(locInfo.bufferIdentifier, + locInfo.lineNumber, + locInfo.columnNumber); + Diags.diagnose(importLoc, diag::unresolved_import_location); + } + } } ModuleDependencyScanningWorker::ModuleDependencyScanningWorker( @@ -391,13 +408,15 @@ ModuleDependencyScanner::getMainModuleDependencyInfo(ModuleDecl *mainModule) { // Add any implicit module names. for (const auto &import : importInfo.AdditionalUnloadedImports) { mainDependencies.addModuleImport(import.module.getModulePath(), - &alreadyAddedModules); + &alreadyAddedModules, + &ScanASTContext.SourceMgr); } // Already-loaded, implicitly imported module names. for (const auto &import : importInfo.AdditionalImports) { mainDependencies.addModuleImport( - import.module.importedModule->getNameStr(), &alreadyAddedModules); + import.module.importedModule->getNameStr(), + &alreadyAddedModules); } // Add the bridging header. @@ -417,18 +436,21 @@ ModuleDependencyScanner::getMainModuleDependencyInfo(ModuleDecl *mainModule) { // to be impored in the source. for (const auto &tbdSymbolModule : ScanCompilerInvocation.getTBDGenOptions().embedSymbolsFromModules) { - mainDependencies.addModuleImport(tbdSymbolModule, &alreadyAddedModules); + mainDependencies.addModuleImport(tbdSymbolModule, + &alreadyAddedModules); } } // Add source-specified `import` dependencies { for (auto fileUnit : mainModule->getFiles()) { - auto sf = dyn_cast(fileUnit); - if (!sf) + auto sourceFile = dyn_cast(fileUnit); + if (!sourceFile) continue; - mainDependencies.addModuleImport(*sf, alreadyAddedModules); + mainDependencies.addModuleImports(*sourceFile, + alreadyAddedModules, + &ScanASTContext.SourceMgr); } // Add all the successful canImport checks from the ASTContext as part of @@ -437,8 +459,9 @@ ModuleDependencyScanner::getMainModuleDependencyInfo(ModuleDecl *mainModule) { // SourceFiles. for (auto &Module : mainModule->getASTContext().getSuccessfulCanImportCheckNames()) - mainDependencies.addModuleImport(Module.first(), &alreadyAddedModules); - } + mainDependencies.addModuleImport(Module.first(), + &alreadyAddedModules); + } return mainDependencies; } @@ -558,8 +581,9 @@ void ModuleDependencyScanner::resolveImportDependencies( auto moduleDependencyInfo = optionalModuleDependencyInfo.value(); llvm::StringMap> moduleLookupResult; + // ACTDOO: Import refactor for (const auto &dependsOn : moduleDependencyInfo->getModuleImports()) - moduleLookupResult.insert(std::make_pair(dependsOn, std::nullopt)); + moduleLookupResult.insert(std::make_pair(dependsOn.importIdentifier, std::nullopt)); // A scanning task to query a module by-name. If the module already exists // in the cache, do nothing and return. @@ -588,51 +612,55 @@ void ModuleDependencyScanner::resolveImportDependencies( moduleLookupResult.insert_or_assign(moduleName, moduleDependencies); }; + // ACTDOO: Import refactor // Enque asynchronous lookup tasks for (const auto &dependsOn : moduleDependencyInfo->getModuleImports()) { - bool underlyingClangModuleLookup = moduleID.ModuleName == dependsOn; - bool isTestable = moduleDependencyInfo->isTestableImport(dependsOn); - ScanningThreadPool.async(scanForModuleDependency, getModuleImportIdentifier(dependsOn), + bool underlyingClangModuleLookup = moduleID.ModuleName == dependsOn.importIdentifier; + bool isTestable = moduleDependencyInfo->isTestableImport(dependsOn.importIdentifier); + ScanningThreadPool.async(scanForModuleDependency, getModuleImportIdentifier(dependsOn.importIdentifier), underlyingClangModuleLookup, isTestable); } for (const auto &dependsOn : moduleDependencyInfo->getOptionalModuleImports()) { - bool underlyingClangModuleLookup = moduleID.ModuleName == dependsOn; - bool isTestable = moduleDependencyInfo->isTestableImport(dependsOn); - ScanningThreadPool.async(scanForModuleDependency, getModuleImportIdentifier(dependsOn), + bool underlyingClangModuleLookup = moduleID.ModuleName == dependsOn.importIdentifier; + bool isTestable = moduleDependencyInfo->isTestableImport(dependsOn.importIdentifier); + ScanningThreadPool.async(scanForModuleDependency, getModuleImportIdentifier(dependsOn.importIdentifier), underlyingClangModuleLookup, isTestable); } ScanningThreadPool.wait(); - std::vector unresolvedImports; + std::vector unresolvedImports; // Aggregate both previously-cached and freshly-scanned module results auto recordResolvedModuleImport = [&cache, &moduleLookupResult, &unresolvedImports, &directDependencies, - moduleID](const std::string &moduleName, bool optionalImport) { - bool underlyingClangModule = moduleID.ModuleName == moduleName; - auto lookupResult = moduleLookupResult[moduleName]; + moduleID](const ScannerImportStatementInfo &moduleImport, bool optionalImport) { + bool underlyingClangModule = moduleID.ModuleName == moduleImport.importIdentifier; + auto lookupResult = moduleLookupResult[moduleImport.importIdentifier]; // The imported module was found in the cache if (lookupResult == std::nullopt) { const ModuleDependencyInfo *cachedInfo; if (underlyingClangModule) cachedInfo = - cache.findDependency(moduleName, ModuleDependencyKind::Clang) - .value(); + cache.findDependency(moduleImport.importIdentifier, + ModuleDependencyKind::Clang).value(); else - cachedInfo = cache.findDependency(moduleName).value(); + cachedInfo = + cache.findDependency(moduleImport.importIdentifier).value(); assert(cachedInfo && "Expected cached dependency info"); - directDependencies.insert({moduleName, cachedInfo->getKind()}); + directDependencies.insert({moduleImport.importIdentifier, + cachedInfo->getKind()}); } else { // Cache discovered module dependencies. if (!lookupResult.value().empty()) { cache.recordDependencies(lookupResult.value()); directDependencies.insert( - {moduleName, lookupResult.value()[0].first.Kind}); + {moduleImport.importIdentifier, + lookupResult.value()[0].first.Kind}); } else if (!optionalImport) { // Otherwise, we failed to resolve this dependency. We will try // again using the cache after all other imports have been resolved. // If that fails too, a scanning failure will be diagnosed. - unresolvedImports.push_back(moduleName); + unresolvedImports.push_back(moduleImport); } } }; @@ -665,14 +693,16 @@ void ModuleDependencyScanner::resolveImportDependencies( // transitive dependencies to the cache, and then attempt to re-query imports // for which resolution originally failed from the cache. If this fails, then // the scanner genuinely failed to resolve this dependency. - for (const auto &moduleName : unresolvedImports) { + for (const auto &moduleImport : unresolvedImports) { auto optionalCachedModuleInfo = - cache.findDependency({moduleName, ModuleDependencyKind::Clang}); + cache.findDependency({moduleImport.importIdentifier, + ModuleDependencyKind::Clang}); if (optionalCachedModuleInfo.has_value()) directDependencies.insert( - {moduleName, optionalCachedModuleInfo.value()->getKind()}); + {moduleImport.importIdentifier, + optionalCachedModuleInfo.value()->getKind()}); else - diagnoseScannerFailure(moduleName, Diagnostics, cache, moduleID); + diagnoseScannerFailure(moduleImport, Diagnostics, cache, moduleID); } } diff --git a/lib/DependencyScan/ScanDependencies.cpp b/lib/DependencyScan/ScanDependencies.cpp index f8f6c3c0f082e..3e361dfee5c83 100644 --- a/lib/DependencyScan/ScanDependencies.cpp +++ b/lib/DependencyScan/ScanDependencies.cpp @@ -1109,6 +1109,7 @@ static void bridgeDependencyIDs(const ArrayRef dependencies, } static swiftscan_diagnostic_set_t *mapCollectedDiagnosticsForOutput( + const SourceManager &SM, const DependencyScanDiagnosticCollector *diagnosticCollector) { auto collectedDiagnostics = diagnosticCollector->getDiagnostics(); auto numDiagnostics = collectedDiagnostics.size(); @@ -1136,6 +1137,22 @@ static swiftscan_diagnostic_set_t *mapCollectedDiagnosticsForOutput( diagnosticInfo->severity = SWIFTSCAN_DIAGNOSTIC_SEVERITY_REMARK; break; } + + if (Diagnostic.ImportLocation.has_value()) { + auto importLocation = Diagnostic.ImportLocation.value(); + swiftscan_source_location_s *sourceLoc = new swiftscan_source_location_s; + if (importLocation.bufferIdentifier.empty()) + sourceLoc->buffer_identifier = swift::c_string_utils::create_null(); + else + sourceLoc->buffer_identifier = swift::c_string_utils::create_clone( + importLocation.bufferIdentifier.c_str()); + sourceLoc->line_number = importLocation.lineNumber; + sourceLoc->column_number = importLocation.columnNumber; + diagnosticInfo->source_location = sourceLoc; + } else { + diagnosticInfo->source_location = nullptr; + } + diagnosticOutput->diagnostics[i] = diagnosticInfo; } return diagnosticOutput; @@ -1322,9 +1339,10 @@ generateFullDependencyGraph(const CompilerInstance &instance, result->main_module_name = create_clone(mainModuleName.c_str()); result->dependencies = dependencySet; result->diagnostics = - diagnosticCollector - ? mapCollectedDiagnosticsForOutput(diagnosticCollector) - : nullptr; + diagnosticCollector + ? mapCollectedDiagnosticsForOutput(instance.getSourceMgr(), + diagnosticCollector) + : nullptr; return result; } @@ -1984,10 +2002,24 @@ swift::dependencies::performModulePrescan(CompilerInstance &instance, if (!mainDependencies) return mainDependencies.getError(); auto *importSet = new swiftscan_import_set_s; - importSet->imports = create_set(mainDependencies->getModuleImports()); + + std::vector importIdentifiers; + importIdentifiers.reserve(mainDependencies->getModuleImports().size()); + llvm::transform(mainDependencies->getModuleImports(), + std::back_inserter(importIdentifiers), + [](const auto &importInfo) -> std::string { + return importInfo.importIdentifier; + }); + importSet->imports = create_set(importIdentifiers); + importSet->diagnostics = + diagnosticCollector + ? mapCollectedDiagnosticsForOutput(instance.getSourceMgr(), + diagnosticCollector) + : nullptr; importSet->diagnostics = diagnosticCollector - ? mapCollectedDiagnosticsForOutput(diagnosticCollector) + ? mapCollectedDiagnosticsForOutput(instance.getSourceMgr(), + diagnosticCollector) : nullptr; return importSet; } diff --git a/lib/Serialization/ScanningLoaders.cpp b/lib/Serialization/ScanningLoaders.cpp index 0bb53171a8c37..1293acb794ca1 100644 --- a/lib/Serialization/ScanningLoaders.cpp +++ b/lib/Serialization/ScanningLoaders.cpp @@ -240,14 +240,15 @@ SwiftModuleScanner::scanInterfaceFile(Twine moduleInterfacePath, // Walk the source file to find the import declarations. llvm::StringSet<> alreadyAddedModules; - Result->addModuleImport(*sourceFile, alreadyAddedModules); + Result->addModuleImports(*sourceFile, alreadyAddedModules, + &Ctx.SourceMgr); // Collect implicitly imported modules in case they are not explicitly // printed in the interface file, e.g. SwiftOnoneSupport. auto &imInfo = mainMod->getImplicitImportInfo(); for (auto import : imInfo.AdditionalUnloadedImports) { Result->addModuleImport(import.module.getModulePath(), - &alreadyAddedModules); + &alreadyAddedModules, &Ctx.SourceMgr); } return std::error_code(); diff --git a/lib/Serialization/SerializedModuleLoader.cpp b/lib/Serialization/SerializedModuleLoader.cpp index 62d0de51da0f7..1461b30f17567 100644 --- a/lib/Serialization/SerializedModuleLoader.cpp +++ b/lib/Serialization/SerializedModuleLoader.cpp @@ -479,26 +479,25 @@ SerializedModuleLoaderBase::scanModuleFile(Twine modulePath, bool isFramework, Ctx.LangOpts.PackageName, isTestableImport); auto importedModuleSet = binaryModuleImports->moduleImports; - std::vector importedModuleNames; - importedModuleNames.reserve(importedModuleSet.size()); - llvm::transform(importedModuleSet.keys(), - std::back_inserter(importedModuleNames), - [](llvm::StringRef N) { - return N.str(); - }); + std::vector moduleImports; + moduleImports.reserve(importedModuleSet.size()); + llvm::transform( + importedModuleSet.keys(), std::back_inserter(moduleImports), + [](llvm::StringRef N) { return ScannerImportStatementInfo(N.str()); }); auto importedHeader = binaryModuleImports->headerImport; auto &importedOptionalModuleSet = binaryModuleOptionalImports->moduleImports; - std::vector importedOptionalModuleNames; + std::vector optionalModuleImports; for (const auto optionalImportedModule : importedOptionalModuleSet.keys()) if (!importedModuleSet.contains(optionalImportedModule)) - importedOptionalModuleNames.push_back(optionalImportedModule.str()); + optionalModuleImports.push_back( + ScannerImportStatementInfo(optionalImportedModule.str())); // Map the set of dependencies over to the "module dependencies". auto dependencies = ModuleDependencyInfo::forSwiftBinaryModule( - modulePath.str(), moduleDocPath, sourceInfoPath, - importedModuleNames, importedOptionalModuleNames, - importedHeader, isFramework, /*module-cache-key*/ ""); + modulePath.str(), moduleDocPath, sourceInfoPath, moduleImports, + optionalModuleImports, importedHeader, isFramework, + /*module-cache-key*/ ""); return std::move(dependencies); } diff --git a/test/ScanDependencies/error_path.swift b/test/ScanDependencies/error_path.swift index f8301f00353b6..0e128e2cea40b 100644 --- a/test/ScanDependencies/error_path.swift +++ b/test/ScanDependencies/error_path.swift @@ -1,14 +1,17 @@ -// expected-error@-1 {{Unable to find module dependency: 'missing_module'}} // RUN: %empty-directory(%t) // RUN: mkdir -p %t/clang-module-cache // REQUIRES: objc_interop - // RUN: %target-swift-frontend -scan-dependencies -module-cache-path %t/clang-module-cache %s -o %t/deps.json -I %S/Inputs/CHeaders -I %S/Inputs/Swift -emit-dependencies -emit-dependencies-path %t/deps.d -import-objc-header %S/Inputs/CHeaders/Bridging.h -swift-version 4 2>&1 | %FileCheck %s import P -// CHECK: :0: error: Unable to find module dependency: 'missing_module' -// CHECK: :0: note: a dependency of Swift module 'Z': '{{.*}}/Inputs/Swift/Z.swiftinterface' -// CHECK: :0: note: a dependency of Swift module 'Y': '{{.*}}/Inputs/Swift/Y.swiftinterface' -// CHECK: :0: note: a dependency of Swift module 'P': '{{.*}}/Inputs/Swift/P.swiftinterface' -// CHECK: :0: note: a dependency of main module 'deps' +// CHECK: {{.*}}{{/|\\}}Z.swiftinterface:3:8: error: Unable to find module dependency: 'missing_module' +// CHECK-NEXT: 1 | // swift-interface-format-version: 1.0 +// CHECK-NEXT: 2 | // swift-module-flags: -module-name Z +// CHECK-NEXT: 3 | import missing_module +// CHECK-NEXT: | |- error: Unable to find module dependency: 'missing_module' +// CHECK-NEXT: | |- note: a dependency of Swift module 'Z': '{{.*}}{{/|\\}}Z.swiftinterface' +// CHECK-NEXT: | |- note: a dependency of Swift module 'Y': '{{.*}}{{/|\\}}Y.swiftinterface' +// CHECK-NEXT: | |- note: a dependency of Swift module 'P': '{{.*}}{{/|\\}}P.swiftinterface' +// CHECK-NEXT: | `- note: a dependency of main module 'deps' +// CHECK-NEXT: 4 | public func funcZ() { } diff --git a/test/ScanDependencies/error_source_locations.swift b/test/ScanDependencies/error_source_locations.swift new file mode 100644 index 0000000000000..be4392a02795e --- /dev/null +++ b/test/ScanDependencies/error_source_locations.swift @@ -0,0 +1,27 @@ +// RUN: %empty-directory(%t) +// RUN: mkdir -p %t/clang-module-cache +// REQUIRES: objc_interop +// RUN: %target-swift-frontend -scan-dependencies -module-cache-path %t/clang-module-cache %s -o %t/deps.json -I %S/Inputs/CHeaders -I %S/Inputs/Swift -emit-dependencies -emit-dependencies-path %t/deps.d -import-objc-header %S/Inputs/CHeaders/Bridging.h -swift-version 4 2>&1 | %FileCheck %s + +import P +import FooBar + +// CHECK: {{.*}}{{/|\\}}error_source_locations.swift:7:8: error: Unable to find module dependency: 'FooBar' +// CHECK-NEXT: 5 | +// CHECK-NEXT: 6 | import P +// CHECK-NEXT: 7 | import FooBar +// CHECK-NEXT: | |- error: Unable to find module dependency: 'FooBar' +// CHECK-NEXT: | `- note: a dependency of main module 'deps' +// CHECK-NEXT: 8 | +// CHECK-NEXT: 9 | + +// CHECK: {{.*}}{{/|\\}}Z.swiftinterface:3:8: error: Unable to find module dependency: 'missing_module' +// CHECK-NEXT: 1 | // swift-interface-format-version: 1.0 +// CHECK-NEXT: 2 | // swift-module-flags: -module-name Z +// CHECK-NEXT: 3 | import missing_module +// CHECK-NEXT: | |- error: Unable to find module dependency: 'missing_module' +// CHECK-NEXT: | |- note: a dependency of Swift module 'Z': '{{.*}}{{/|\\}}Z.swiftinterface' +// CHECK-NEXT: | |- note: a dependency of Swift module 'Y': '{{.*}}{{/|\\}}Y.swiftinterface' +// CHECK-NEXT: | |- note: a dependency of Swift module 'P': '{{.*}}{{/|\\}}P.swiftinterface' +// CHECK-NEXT: | `- note: a dependency of main module 'deps' +// CHECK-NEXT: 4 | public func funcZ() { } diff --git a/tools/libSwiftScan/libSwiftScan.cpp b/tools/libSwiftScan/libSwiftScan.cpp index 1838d8bc5fb07..9121ecd925ce1 100644 --- a/tools/libSwiftScan/libSwiftScan.cpp +++ b/tools/libSwiftScan/libSwiftScan.cpp @@ -14,6 +14,7 @@ // //===----------------------------------------------------------------------===// +#include "swift-c/DependencyScan/DependencyScan.h" #include "swift/Basic/LLVMInitialize.h" #include "swift/Basic/InitializeSwiftModules.h" #include "swift/DependencyScan/DependencyScanImpl.h" @@ -505,7 +506,7 @@ void swiftscan_scan_invocation_set_working_directory( invocation->working_directory = swift::c_string_utils::create_clone(working_directory); } -SWIFTSCAN_PUBLIC void +void swiftscan_scan_invocation_set_argv(swiftscan_scan_invocation_t invocation, int argc, const char **argv) { invocation->argv = swift::c_string_utils::create_set(argc, argv); @@ -662,6 +663,9 @@ swiftscan_scanner_diagnostics_query(swiftscan_scanner_t scanner) { DiagnosticInfo->severity = SWIFTSCAN_DIAGNOSTIC_SEVERITY_REMARK; break; } + // swiftscan_scanner_diagnostics_query is deprecated, + // so it does not support source locations. + DiagnosticInfo->source_location = nullptr; Result->diagnostics[i] = DiagnosticInfo; } @@ -684,8 +688,17 @@ swiftscan_diagnostic_get_severity(swiftscan_diagnostic_info_t diagnostic) { return diagnostic->severity; } +swiftscan_source_location_t +swiftscan_diagnostic_get_source_location(swiftscan_diagnostic_info_t diagnostic) { + return diagnostic->source_location; +} + void swiftscan_diagnostic_dispose(swiftscan_diagnostic_info_t diagnostic) { swiftscan_string_dispose(diagnostic->message); + if (diagnostic->source_location) { + swiftscan_string_dispose(diagnostic->source_location->buffer_identifier); + delete diagnostic->source_location; + } delete diagnostic; } @@ -698,6 +711,23 @@ swiftscan_diagnostics_set_dispose(swiftscan_diagnostic_set_t* diagnostics){ delete diagnostics; } +//=== Source Location -----------------------------------------------------===// + +swiftscan_string_ref_t +swiftscan_source_location_get_buffer_identifier(swiftscan_source_location_t source_location) { + return source_location->buffer_identifier; +} + +int64_t +swiftscan_source_location_get_line_number(swiftscan_source_location_t source_location) { + return source_location->line_number; +} + +int64_t +swiftscan_source_location_get_column_number(swiftscan_source_location_t source_location) { + return source_location->column_number; +} + //=== Experimental Compiler Invocation Functions ------------------------===// int invoke_swift_compiler(int argc, const char **argv) { diff --git a/tools/libSwiftScan/libSwiftScan.exports b/tools/libSwiftScan/libSwiftScan.exports index af002619c7de5..2232eb027a6c8 100644 --- a/tools/libSwiftScan/libSwiftScan.exports +++ b/tools/libSwiftScan/libSwiftScan.exports @@ -78,7 +78,11 @@ swiftscan_scanner_diagnostics_query swiftscan_scanner_diagnostics_reset swiftscan_diagnostic_get_message swiftscan_diagnostic_get_severity +swiftscan_diagnostic_get_source_location swiftscan_diagnostics_set_dispose +swiftscan_source_location_get_buffer_identifier +swiftscan_source_location_get_line_number +swiftscan_source_location_get_column_number swiftscan_cas_create_from_options swiftscan_cas_get_ondisk_size swiftscan_cas_set_ondisk_size_limit