15
15
#include " swift/Basic/LLVMInitialize.h"
16
16
#include " swift/Basic/TargetInfo.h"
17
17
#include " swift/Basic/ColorUtils.h"
18
+ #include " swift/Basic/Defer.h"
18
19
#include " swift/DependencyScan/DependencyScanningTool.h"
19
20
#include " swift/DependencyScan/DependencyScanImpl.h"
20
21
#include " swift/DependencyScan/SerializedModuleDependencyCacheFormat.h"
@@ -131,15 +132,15 @@ void DepScanInMemoryDiagnosticCollector::addDiagnostic(
131
132
}
132
133
133
134
swiftscan_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 ();
137
138
swiftscan_diagnostic_set_t *diagnosticOutput = new swiftscan_diagnostic_set_t ;
138
139
diagnosticOutput->count = numDiagnostics;
139
140
diagnosticOutput->diagnostics =
140
141
new swiftscan_diagnostic_info_t [numDiagnostics];
141
142
for (size_t i = 0 ; i < numDiagnostics; ++i) {
142
- const auto &Diagnostic = collectedDiagnostics [i];
143
+ const auto &Diagnostic = diagnostics [i];
143
144
swiftscan_diagnostic_info_s *diagnosticInfo =
144
145
new swiftscan_diagnostic_info_s;
145
146
diagnosticInfo->message =
@@ -183,7 +184,8 @@ swiftscan_diagnostic_set_t *mapCollectedDiagnosticsForOutput(
183
184
// module dependnecies but captures the diagnostics emitted during the attempted
184
185
// scan query.
185
186
static swiftscan_dependency_graph_t generateHollowDiagnosticOutput (
186
- const DepScanInMemoryDiagnosticCollector &ScanDiagnosticConsumer) {
187
+ ArrayRef<DepScanInMemoryDiagnosticCollector::ScannerDiagnosticInfo>
188
+ diagnostics) {
187
189
// Create a dependency graph instance
188
190
swiftscan_dependency_graph_t hollowResult = new swiftscan_dependency_graph_s;
189
191
@@ -246,20 +248,21 @@ static swiftscan_dependency_graph_t generateHollowDiagnosticOutput(
246
248
247
249
// Populate the diagnostic info
248
250
hollowResult->diagnostics =
249
- mapCollectedDiagnosticsForOutput (&ScanDiagnosticConsumer );
251
+ mapCollectedDiagnosticsForOutput (diagnostics );
250
252
return hollowResult;
251
253
}
252
254
253
255
// Generate an instance of the `swiftscan_import_set_t` which contains no
254
256
// imports but captures the diagnostics emitted during the attempted
255
257
// scan query.
256
258
static swiftscan_import_set_t generateHollowDiagnosticOutputImportSet (
257
- const DepScanInMemoryDiagnosticCollector &ScanDiagnosticConsumer) {
259
+ ArrayRef<DepScanInMemoryDiagnosticCollector::ScannerDiagnosticInfo>
260
+ diagnostics) {
258
261
// Create an dependency graph instance
259
262
swiftscan_import_set_t hollowResult = new swiftscan_import_set_s;
260
263
hollowResult->imports = c_string_utils::create_empty_set ();
261
264
hollowResult->diagnostics =
262
- mapCollectedDiagnosticsForOutput (&ScanDiagnosticConsumer );
265
+ mapCollectedDiagnosticsForOutput (diagnostics );
263
266
return hollowResult;
264
267
}
265
268
@@ -270,55 +273,67 @@ DependencyScanningTool::DependencyScanningTool()
270
273
llvm::ErrorOr<swiftscan_dependency_graph_t >
271
274
DependencyScanningTool::getDependencies (ArrayRef<const char *> Command,
272
275
StringRef WorkingDirectory) {
276
+ // Diagnostics which may get collected during scanning instance
277
+ // initialization
278
+ std::vector<DepScanInMemoryDiagnosticCollector::ScannerDiagnosticInfo>
279
+ InitializationDiagnostics;
280
+
273
281
// 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 ();
279
287
280
288
// Local scan cache instance, wrapping the shared global cache.
281
289
ModuleDependenciesCache cache (
282
290
ScanInstance->getMainModule ()->getNameStr ().str (),
283
291
ScanInstance->getInvocation ().getModuleScanningHash ());
284
292
// Execute the scanning action, retrieving the in-memory result
285
293
auto DependenciesOrErr =
286
- performModuleScan (*ScanningService, cache, QueryContext);
294
+ performModuleScan (*ScanningService, cache, * QueryContext);
287
295
288
296
if (DependenciesOrErr.getError ())
289
297
return generateHollowDiagnosticOutput (
290
- * QueryContext. InMemoryDiagnosticCollector );
298
+ QueryContext-> InMemoryDiagnosticCollector -> getDiagnosticsRef () );
291
299
292
300
return std::move (*DependenciesOrErr);
293
301
}
294
302
295
303
llvm::ErrorOr<swiftscan_import_set_t >
296
304
DependencyScanningTool::getImports (ArrayRef<const char *> Command,
297
305
StringRef WorkingDirectory) {
306
+ // Diagnostics which may get collected during scanning instance
307
+ // initialization
308
+ std::vector<DepScanInMemoryDiagnosticCollector::ScannerDiagnosticInfo>
309
+ InitializationDiagnostics;
310
+
298
311
// 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 ();
304
317
305
318
// Local scan cache instance, wrapping the shared global cache.
306
319
ModuleDependenciesCache cache (
307
320
ScanInstance->getMainModule ()->getNameStr ().str (),
308
321
ScanInstance->getInvocation ().getModuleScanningHash ());
309
322
// Execute the pre-scanning action, retrieving the in-memory result
310
323
auto DependenciesOrErr =
311
- performModulePrescan (*ScanningService, cache, QueryContext);
324
+ performModulePrescan (*ScanningService, cache, * QueryContext);
312
325
313
326
if (DependenciesOrErr.getError ())
314
327
return generateHollowDiagnosticOutputImportSet (
315
- * QueryContext. InMemoryDiagnosticCollector );
328
+ QueryContext-> InMemoryDiagnosticCollector -> getDiagnosticsRef () );
316
329
317
330
return std::move (*DependenciesOrErr);
318
331
}
319
332
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) {
322
337
// The remainder of this method operates on shared state in the
323
338
// scanning service
324
339
llvm::sys::SmartScopedLock<true > Lock (DependencyScanningToolStateLock);
@@ -336,54 +351,58 @@ ScanQueryContext DependencyScanningTool::createScanQueryContext(
336
351
auto Instance = std::make_unique<CompilerInstance>();
337
352
Instance->addDiagnosticConsumer (ScannerDiagnosticsCollector.get ());
338
353
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
+ }
345
366
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);
350
371
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
+ }
372
392
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);
378
397
379
- Invocation.getFrontendOptions ().LLVMArgs .clear ();
398
+ Invocation.getFrontendOptions ().LLVMArgs .clear ();
380
399
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);
385
403
386
- (void )Instance->getMainModule ();
404
+ (void )Instance->getMainModule ();
405
+ }
387
406
388
407
auto SerializedDiagnosticsOutputPath =
389
408
Instance->getInvocation ()
0 commit comments