@@ -140,6 +140,55 @@ void LockingDependencyScanDiagnosticCollector::addDiagnostic(
140140 DependencyScanDiagnosticCollector::addDiagnostic (SM, Info);
141141}
142142
143+ swiftscan_diagnostic_set_t *mapCollectedDiagnosticsForOutput (
144+ const DependencyScanDiagnosticCollector *diagnosticCollector) {
145+ auto collectedDiagnostics = diagnosticCollector->getDiagnostics ();
146+ auto numDiagnostics = collectedDiagnostics.size ();
147+ swiftscan_diagnostic_set_t *diagnosticOutput = new swiftscan_diagnostic_set_t ;
148+ diagnosticOutput->count = numDiagnostics;
149+ diagnosticOutput->diagnostics =
150+ new swiftscan_diagnostic_info_t [numDiagnostics];
151+ for (size_t i = 0 ; i < numDiagnostics; ++i) {
152+ const auto &Diagnostic = collectedDiagnostics[i];
153+ swiftscan_diagnostic_info_s *diagnosticInfo =
154+ new swiftscan_diagnostic_info_s;
155+ diagnosticInfo->message =
156+ swift::c_string_utils::create_clone (Diagnostic.Message .c_str ());
157+ switch (Diagnostic.Severity ) {
158+ case llvm::SourceMgr::DK_Error:
159+ diagnosticInfo->severity = SWIFTSCAN_DIAGNOSTIC_SEVERITY_ERROR;
160+ break ;
161+ case llvm::SourceMgr::DK_Warning:
162+ diagnosticInfo->severity = SWIFTSCAN_DIAGNOSTIC_SEVERITY_WARNING;
163+ break ;
164+ case llvm::SourceMgr::DK_Note:
165+ diagnosticInfo->severity = SWIFTSCAN_DIAGNOSTIC_SEVERITY_NOTE;
166+ break ;
167+ case llvm::SourceMgr::DK_Remark:
168+ diagnosticInfo->severity = SWIFTSCAN_DIAGNOSTIC_SEVERITY_REMARK;
169+ break ;
170+ }
171+
172+ if (Diagnostic.ImportLocation .has_value ()) {
173+ auto importLocation = Diagnostic.ImportLocation .value ();
174+ swiftscan_source_location_s *sourceLoc = new swiftscan_source_location_s;
175+ if (importLocation.bufferIdentifier .empty ())
176+ sourceLoc->buffer_identifier = swift::c_string_utils::create_null ();
177+ else
178+ sourceLoc->buffer_identifier = swift::c_string_utils::create_clone (
179+ importLocation.bufferIdentifier .c_str ());
180+ sourceLoc->line_number = importLocation.lineNumber ;
181+ sourceLoc->column_number = importLocation.columnNumber ;
182+ diagnosticInfo->source_location = sourceLoc;
183+ } else {
184+ diagnosticInfo->source_location = nullptr ;
185+ }
186+
187+ diagnosticOutput->diagnostics [i] = diagnosticInfo;
188+ }
189+ return diagnosticOutput;
190+ }
191+
143192DependencyScanningTool::DependencyScanningTool ()
144193 : ScanningService(std::make_unique<SwiftDependencyScanningService>()),
145194 VersionedPCMInstanceCacheCache (
@@ -148,12 +197,25 @@ DependencyScanningTool::DependencyScanningTool()
148197
149198llvm::ErrorOr<swiftscan_dependency_graph_t >
150199DependencyScanningTool::getDependencies (
151- ArrayRef<const char *> Command, const llvm::StringSet<> &PlaceholderModules,
200+ ArrayRef<const char *> Command,
201+ const llvm::StringSet<> &PlaceholderModules,
152202 StringRef WorkingDirectory) {
203+ // There may be errors as early as in instance initialization, so we must ensure
204+ // we can catch those.
205+ auto ScanDiagnosticConsumer = std::make_shared<DependencyScanDiagnosticCollector>();
206+ auto produceDiagnosticStateOnFailure = [&ScanDiagnosticConsumer]() {
207+ swiftscan_dependency_graph_t result = new swiftscan_dependency_graph_s;
208+ result->diagnostics = mapCollectedDiagnosticsForOutput (ScanDiagnosticConsumer.get ());
209+ return result;
210+ };
211+
153212 // The primary instance used to scan the query Swift source-code
154- auto QueryContextOrErr = initScannerForAction (Command, WorkingDirectory);
155- if (std::error_code EC = QueryContextOrErr.getError ())
156- return EC;
213+ auto QueryContextOrErr = initCompilerInstanceForScan (Command,
214+ WorkingDirectory,
215+ ScanDiagnosticConsumer);
216+ if (QueryContextOrErr.getError ())
217+ return produceDiagnosticStateOnFailure ();
218+
157219 auto QueryContext = std::move (*QueryContextOrErr);
158220
159221 // Local scan cache instance, wrapping the shared global cache.
@@ -166,19 +228,26 @@ DependencyScanningTool::getDependencies(
166228 QueryContext.ScanDiagnostics .get (),
167229 cache);
168230 if (DependenciesOrErr.getError ())
169- return std::make_error_code (std::errc::not_supported);
170- auto Dependencies = std::move (*DependenciesOrErr);
231+ return produceDiagnosticStateOnFailure ();
171232
172- return Dependencies ;
233+ return std::move (*DependenciesOrErr); ;
173234}
174235
175236llvm::ErrorOr<swiftscan_import_set_t >
176237DependencyScanningTool::getImports (ArrayRef<const char *> Command,
177238 StringRef WorkingDirectory) {
239+ // There may be errors as early as in instance initialization, so we must ensure
240+ // we can catch those
241+ auto ScanDiagnosticConsumer = std::make_shared<DependencyScanDiagnosticCollector>();
178242 // The primary instance used to scan the query Swift source-code
179- auto QueryContextOrErr = initScannerForAction (Command, WorkingDirectory);
180- if (std::error_code EC = QueryContextOrErr.getError ())
181- return EC;
243+ auto QueryContextOrErr = initCompilerInstanceForScan (Command,
244+ WorkingDirectory,
245+ ScanDiagnosticConsumer);
246+ if (QueryContextOrErr.getError ()) {
247+ swiftscan_import_set_t result = new swiftscan_import_set_s;
248+ result->diagnostics = mapCollectedDiagnosticsForOutput (ScanDiagnosticConsumer.get ());
249+ return result;
250+ }
182251 auto QueryContext = std::move (*QueryContextOrErr);
183252
184253 // Local scan cache instance, wrapping the shared global cache.
@@ -202,10 +271,14 @@ DependencyScanningTool::getDependencies(
202271 const std::vector<BatchScanInput> &BatchInput,
203272 const llvm::StringSet<> &PlaceholderModules, StringRef WorkingDirectory) {
204273 // The primary instance used to scan Swift modules
205- auto QueryContextOrErr = initScannerForAction (Command, WorkingDirectory);
274+ auto ScanDiagnosticConsumer = std::make_shared<DependencyScanDiagnosticCollector>();
275+ auto QueryContextOrErr = initCompilerInstanceForScan (Command,
276+ WorkingDirectory,
277+ ScanDiagnosticConsumer);
206278 if (std::error_code EC = QueryContextOrErr.getError ())
207279 return std::vector<llvm::ErrorOr<swiftscan_dependency_graph_t >>(
208280 BatchInput.size (), std::make_error_code (std::errc::invalid_argument));
281+
209282 auto QueryContext = std::move (*QueryContextOrErr);
210283
211284 // Local scan cache instance, wrapping the shared global cache.
@@ -264,26 +337,26 @@ void DependencyScanningTool::resetDiagnostics() {
264337}
265338
266339llvm::ErrorOr<ScanQueryInstance>
267- DependencyScanningTool::initScannerForAction (
268- ArrayRef<const char *> Command, StringRef WorkingDirectory) {
340+ DependencyScanningTool::initCompilerInstanceForScan (
341+ ArrayRef<const char *> CommandArgs,
342+ StringRef WorkingDir,
343+ std::shared_ptr<DependencyScanDiagnosticCollector> scannerDiagnosticsCollector) {
269344 // The remainder of this method operates on shared state in the
270345 // scanning service and global LLVM state with:
271346 // llvm::cl::ResetAllOptionOccurrences
272347 llvm::sys::SmartScopedLock<true > Lock (DependencyScanningToolStateLock);
273- return initCompilerInstanceForScan (Command, WorkingDirectory);
274- }
348+ // FIXME: Instead, target-info and supported-features queries must use
349+ // `DependencyScanningToolStateLock`, but this currently requires further
350+ // client-side API plumbing.
351+ llvm::sys::SmartScopedLock<true > TargetInfoLock (TargetInfoMutex);
275352
276- llvm::ErrorOr<ScanQueryInstance>
277- DependencyScanningTool::initCompilerInstanceForScan (
278- ArrayRef<const char *> CommandArgs, StringRef WorkingDir) {
279353 // State unique to an individual scan
280354 auto Instance = std::make_unique<CompilerInstance>();
281- auto ScanDiagnosticConsumer = std::make_unique<DependencyScanDiagnosticCollector>();
282355
283356 // FIXME: The shared CDC must be deprecated once all clients have switched
284357 // to using per-scan diagnostic output embedded in the `swiftscan_dependency_graph_s`
285358 Instance->addDiagnosticConsumer (&CDC);
286- Instance->addDiagnosticConsumer (ScanDiagnosticConsumer .get ());
359+ Instance->addDiagnosticConsumer (scannerDiagnosticsCollector .get ());
287360
288361 // Basic error checking on the arguments
289362 if (CommandArgs.empty ()) {
@@ -327,6 +400,7 @@ DependencyScanningTool::initCompilerInstanceForScan(
327400 if (Instance->setup (Invocation, InstanceSetupError)) {
328401 return std::make_error_code (std::errc::not_supported);
329402 }
403+ Invocation.getFrontendOptions ().LLVMArgs .clear ();
330404
331405 // Setup the caching service after the instance finishes setup.
332406 if (ScanningService->setupCachingDependencyScanningService (*Instance))
@@ -335,7 +409,7 @@ DependencyScanningTool::initCompilerInstanceForScan(
335409 (void )Instance->getMainModule ();
336410
337411 return ScanQueryInstance{std::move (Instance),
338- std::move (ScanDiagnosticConsumer) };
412+ scannerDiagnosticsCollector };
339413}
340414
341415} // namespace dependencies
0 commit comments