1515#include " swift/Basic/LLVMInitialize.h"
1616#include " swift/Basic/TargetInfo.h"
1717#include " swift/Basic/ColorUtils.h"
18+ #include " swift/Basic/Defer.h"
1819#include " swift/DependencyScan/DependencyScanningTool.h"
1920#include " swift/DependencyScan/DependencyScanImpl.h"
2021#include " swift/DependencyScan/SerializedModuleDependencyCacheFormat.h"
@@ -131,15 +132,15 @@ void DepScanInMemoryDiagnosticCollector::addDiagnostic(
131132}
132133
133134swiftscan_diagnostic_set_t *mapCollectedDiagnosticsForOutput (
134- const DepScanInMemoryDiagnosticCollector *diagnosticCollector) {
135- auto collectedDiagnostics = diagnosticCollector-> getDiagnostics ();
136- auto numDiagnostics = collectedDiagnostics .size ();
135+ ArrayRef< DepScanInMemoryDiagnosticCollector::ScannerDiagnosticInfo>
136+ diagnostics) {
137+ auto numDiagnostics = diagnostics .size ();
137138 swiftscan_diagnostic_set_t *diagnosticOutput = new swiftscan_diagnostic_set_t ;
138139 diagnosticOutput->count = numDiagnostics;
139140 diagnosticOutput->diagnostics =
140141 new swiftscan_diagnostic_info_t [numDiagnostics];
141142 for (size_t i = 0 ; i < numDiagnostics; ++i) {
142- const auto &Diagnostic = collectedDiagnostics [i];
143+ const auto &Diagnostic = diagnostics [i];
143144 swiftscan_diagnostic_info_s *diagnosticInfo =
144145 new swiftscan_diagnostic_info_s;
145146 diagnosticInfo->message =
@@ -183,7 +184,8 @@ swiftscan_diagnostic_set_t *mapCollectedDiagnosticsForOutput(
183184// module dependnecies but captures the diagnostics emitted during the attempted
184185// scan query.
185186static swiftscan_dependency_graph_t generateHollowDiagnosticOutput (
186- const DepScanInMemoryDiagnosticCollector &ScanDiagnosticConsumer) {
187+ ArrayRef<DepScanInMemoryDiagnosticCollector::ScannerDiagnosticInfo>
188+ diagnostics) {
187189 // Create a dependency graph instance
188190 swiftscan_dependency_graph_t hollowResult = new swiftscan_dependency_graph_s;
189191
@@ -246,20 +248,21 @@ static swiftscan_dependency_graph_t generateHollowDiagnosticOutput(
246248
247249 // Populate the diagnostic info
248250 hollowResult->diagnostics =
249- mapCollectedDiagnosticsForOutput (&ScanDiagnosticConsumer );
251+ mapCollectedDiagnosticsForOutput (diagnostics );
250252 return hollowResult;
251253}
252254
253255// Generate an instance of the `swiftscan_import_set_t` which contains no
254256// imports but captures the diagnostics emitted during the attempted
255257// scan query.
256258static swiftscan_import_set_t generateHollowDiagnosticOutputImportSet (
257- const DepScanInMemoryDiagnosticCollector &ScanDiagnosticConsumer) {
259+ ArrayRef<DepScanInMemoryDiagnosticCollector::ScannerDiagnosticInfo>
260+ diagnostics) {
258261 // Create an dependency graph instance
259262 swiftscan_import_set_t hollowResult = new swiftscan_import_set_s;
260263 hollowResult->imports = c_string_utils::create_empty_set ();
261264 hollowResult->diagnostics =
262- mapCollectedDiagnosticsForOutput (&ScanDiagnosticConsumer );
265+ mapCollectedDiagnosticsForOutput (diagnostics );
263266 return hollowResult;
264267}
265268
@@ -270,55 +273,67 @@ DependencyScanningTool::DependencyScanningTool()
270273llvm::ErrorOr<swiftscan_dependency_graph_t >
271274DependencyScanningTool::getDependencies (ArrayRef<const char *> Command,
272275 StringRef WorkingDirectory) {
276+ // Diagnostics which may get collected during scanning instance
277+ // initialization
278+ std::vector<DepScanInMemoryDiagnosticCollector::ScannerDiagnosticInfo>
279+ InitializationDiagnostics;
280+
273281 // The primary instance used to scan the query Swift source-code
274- auto QueryContext = createScanQueryContext (Command, WorkingDirectory);
275- if (QueryContext. ScanInstance . getError ())
276- return generateHollowDiagnosticOutput (
277- *QueryContext. InMemoryDiagnosticCollector );
278- auto ScanInstance = QueryContext. ScanInstance -> get ();
282+ auto QueryContext = createScanQueryContext (Command, WorkingDirectory,
283+ InitializationDiagnostics);
284+ if (QueryContext. getError ())
285+ return generateHollowDiagnosticOutput (InitializationDiagnostics );
286+ auto ScanInstance = QueryContext-> ScanInstance . get ();
279287
280288 // Local scan cache instance, wrapping the shared global cache.
281289 ModuleDependenciesCache cache (
282290 ScanInstance->getMainModule ()->getNameStr ().str (),
283291 ScanInstance->getInvocation ().getModuleScanningHash ());
284292 // Execute the scanning action, retrieving the in-memory result
285293 auto DependenciesOrErr =
286- performModuleScan (*ScanningService, cache, QueryContext);
294+ performModuleScan (*ScanningService, cache, * QueryContext);
287295
288296 if (DependenciesOrErr.getError ())
289297 return generateHollowDiagnosticOutput (
290- * QueryContext. InMemoryDiagnosticCollector );
298+ QueryContext-> InMemoryDiagnosticCollector -> getDiagnosticsRef () );
291299
292300 return std::move (*DependenciesOrErr);
293301}
294302
295303llvm::ErrorOr<swiftscan_import_set_t >
296304DependencyScanningTool::getImports (ArrayRef<const char *> Command,
297305 StringRef WorkingDirectory) {
306+ // Diagnostics which may get collected during scanning instance
307+ // initialization
308+ std::vector<DepScanInMemoryDiagnosticCollector::ScannerDiagnosticInfo>
309+ InitializationDiagnostics;
310+
298311 // The primary instance used to scan the query Swift source-code
299- auto QueryContext = createScanQueryContext (Command, WorkingDirectory);
300- if (QueryContext. ScanInstance . getError ())
301- return generateHollowDiagnosticOutputImportSet (
302- *QueryContext. InMemoryDiagnosticCollector );
303- auto ScanInstance = QueryContext. ScanInstance -> get ();
312+ auto QueryContext = createScanQueryContext (Command, WorkingDirectory,
313+ InitializationDiagnostics);
314+ if (QueryContext. getError ())
315+ return generateHollowDiagnosticOutputImportSet (InitializationDiagnostics );
316+ auto ScanInstance = QueryContext-> ScanInstance . get ();
304317
305318 // Local scan cache instance, wrapping the shared global cache.
306319 ModuleDependenciesCache cache (
307320 ScanInstance->getMainModule ()->getNameStr ().str (),
308321 ScanInstance->getInvocation ().getModuleScanningHash ());
309322 // Execute the pre-scanning action, retrieving the in-memory result
310323 auto DependenciesOrErr =
311- performModulePrescan (*ScanningService, cache, QueryContext);
324+ performModulePrescan (*ScanningService, cache, * QueryContext);
312325
313326 if (DependenciesOrErr.getError ())
314327 return generateHollowDiagnosticOutputImportSet (
315- * QueryContext. InMemoryDiagnosticCollector );
328+ QueryContext-> InMemoryDiagnosticCollector -> getDiagnosticsRef () );
316329
317330 return std::move (*DependenciesOrErr);
318331}
319332
320- ScanQueryContext DependencyScanningTool::createScanQueryContext (
321- ArrayRef<const char *> CommandArgs, StringRef WorkingDir) {
333+ llvm::ErrorOr<ScanQueryContext> DependencyScanningTool::createScanQueryContext (
334+ ArrayRef<const char *> CommandArgs, StringRef WorkingDir,
335+ std::vector<DepScanInMemoryDiagnosticCollector::ScannerDiagnosticInfo>
336+ &InitializationDiagnostics) {
322337 // The remainder of this method operates on shared state in the
323338 // scanning service
324339 llvm::sys::SmartScopedLock<true > Lock (DependencyScanningToolStateLock);
@@ -336,54 +351,58 @@ ScanQueryContext DependencyScanningTool::createScanQueryContext(
336351 auto Instance = std::make_unique<CompilerInstance>();
337352 Instance->addDiagnosticConsumer (ScannerDiagnosticsCollector.get ());
338353
339- // Basic error checking on the arguments
340- if (CommandArgs.empty ()) {
341- Instance->getDiags ().diagnose (SourceLoc (), diag::error_no_frontend_args);
342- return ScanQueryContext{std::make_error_code (std::errc::invalid_argument),
343- std::move (ScannerDiagnosticsCollector), nullptr };
344- }
354+ {
355+ // In case we exit with an error, ensure the client gets the
356+ // diagnostics collected so-far.
357+ SWIFT_DEFER {
358+ InitializationDiagnostics = ScannerDiagnosticsCollector->getDiagnostics ();
359+ };
360+
361+ // Basic error checking on the arguments
362+ if (CommandArgs.empty ()) {
363+ Instance->getDiags ().diagnose (SourceLoc (), diag::error_no_frontend_args);
364+ return std::make_error_code (std::errc::invalid_argument);
365+ }
345366
346- CompilerInvocation Invocation;
347- SmallString<128 > WorkingDirectory (WorkingDir);
348- if (WorkingDirectory.empty ())
349- llvm::sys::fs::current_path (WorkingDirectory);
367+ CompilerInvocation Invocation;
368+ SmallString<128 > WorkingDirectory (WorkingDir);
369+ if (WorkingDirectory.empty ())
370+ llvm::sys::fs::current_path (WorkingDirectory);
350371
351- // Parse/tokenize arguments.
352- std::string CommandString;
353- for (const auto *c : CommandArgs) {
354- CommandString.append (c);
355- CommandString.append (" " );
356- }
357- SmallVector<const char *, 4 > Args;
358- llvm::BumpPtrAllocator Alloc;
359- llvm::StringSaver Saver (Alloc);
360- // Ensure that we use the Windows command line parsing on Windows as we need
361- // to ensure that we properly handle paths.
362- if (llvm::Triple (llvm::sys::getProcessTriple ()).isOSWindows ())
363- llvm::cl::TokenizeWindowsCommandLine (CommandString, Saver, Args);
364- else
365- llvm::cl::TokenizeGNUCommandLine (CommandString, Saver, Args);
366-
367- if (Invocation.parseArgs (Args, Instance->getDiags (),
368- nullptr , WorkingDirectory, " /tmp/foo" )) {
369- return ScanQueryContext{std::make_error_code (std::errc::invalid_argument),
370- std::move (ScannerDiagnosticsCollector), nullptr };
371- }
372+ // Parse/tokenize arguments.
373+ std::string CommandString;
374+ for (const auto *c : CommandArgs) {
375+ CommandString.append (c);
376+ CommandString.append (" " );
377+ }
378+ SmallVector<const char *, 4 > Args;
379+ llvm::BumpPtrAllocator Alloc;
380+ llvm::StringSaver Saver (Alloc);
381+ // Ensure that we use the Windows command line parsing on Windows as we need
382+ // to ensure that we properly handle paths.
383+ if (llvm::Triple (llvm::sys::getProcessTriple ()).isOSWindows ())
384+ llvm::cl::TokenizeWindowsCommandLine (CommandString, Saver, Args);
385+ else
386+ llvm::cl::TokenizeGNUCommandLine (CommandString, Saver, Args);
387+
388+ if (Invocation.parseArgs (Args, Instance->getDiags (),
389+ nullptr , WorkingDirectory, " /tmp/foo" )) {
390+ return std::make_error_code (std::errc::invalid_argument);
391+ }
372392
373- // Setup the instance
374- std::string InstanceSetupError;
375- if (Instance->setup (Invocation, InstanceSetupError))
376- return ScanQueryContext{std::make_error_code (std::errc::not_supported),
377- std::move (ScannerDiagnosticsCollector), nullptr };
393+ // Setup the instance
394+ std::string InstanceSetupError;
395+ if (Instance->setup (Invocation, InstanceSetupError))
396+ return std::make_error_code (std::errc::not_supported);
378397
379- Invocation.getFrontendOptions ().LLVMArgs .clear ();
398+ Invocation.getFrontendOptions ().LLVMArgs .clear ();
380399
381- // Setup the caching service after the instance finishes setup.
382- if (ScanningService->setupCachingDependencyScanningService (*Instance))
383- return ScanQueryContext{std::make_error_code (std::errc::invalid_argument),
384- std::move (ScannerDiagnosticsCollector), nullptr };
400+ // Setup the caching service after the instance finishes setup.
401+ if (ScanningService->setupCachingDependencyScanningService (*Instance))
402+ return std::make_error_code (std::errc::invalid_argument);
385403
386- (void )Instance->getMainModule ();
404+ (void )Instance->getMainModule ();
405+ }
387406
388407 auto SerializedDiagnosticsOutputPath =
389408 Instance->getInvocation ()
0 commit comments