@@ -140,6 +140,132 @@ void LockingDependencyScanDiagnosticCollector::addDiagnostic(
140
140
DependencyScanDiagnosticCollector::addDiagnostic (SM, Info);
141
141
}
142
142
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
+
192
+ // Generate an instance of the `swiftscan_dependency_graph_s` which contains no
193
+ // module dependnecies but captures the diagnostics emitted during the attempted
194
+ // scan query.
195
+ static swiftscan_dependency_graph_t generateHollowDiagnosticOutput (
196
+ const DependencyScanDiagnosticCollector &ScanDiagnosticConsumer) {
197
+ // Create a dependency graph instance
198
+ swiftscan_dependency_graph_t hollowResult = new swiftscan_dependency_graph_s;
199
+
200
+ // Populate the `modules` with a single info for the main module
201
+ // containing no dependencies
202
+ swiftscan_dependency_set_t *dependencySet = new swiftscan_dependency_set_t ;
203
+ dependencySet->count = 1 ;
204
+ dependencySet->modules = new swiftscan_dependency_info_t [1 ];
205
+ swiftscan_dependency_info_s *hollowMainModuleInfo =
206
+ new swiftscan_dependency_info_s;
207
+ dependencySet->modules [0 ] = hollowMainModuleInfo;
208
+ hollowResult->dependencies = dependencySet;
209
+
210
+ // Other main module details empty
211
+ hollowMainModuleInfo->direct_dependencies =
212
+ c_string_utils::create_empty_set ();
213
+ hollowMainModuleInfo->source_files = c_string_utils::create_empty_set ();
214
+ hollowMainModuleInfo->module_path = c_string_utils::create_null ();
215
+ hollowResult->main_module_name = c_string_utils::create_clone (" unknown" );
216
+ hollowMainModuleInfo->module_name =
217
+ c_string_utils::create_clone (" swiftTextual:unknown" );
218
+
219
+ // Hollow info details
220
+ swiftscan_module_details_s *hollowDetails = new swiftscan_module_details_s;
221
+ hollowDetails->kind = SWIFTSCAN_DEPENDENCY_INFO_SWIFT_TEXTUAL;
222
+ swiftscan_macro_dependency_set_t *hollowMacroSet = new swiftscan_macro_dependency_set_t ;
223
+ hollowMacroSet->count = 0 ;
224
+ hollowMacroSet->macro_dependencies = nullptr ;
225
+ hollowDetails->swift_textual_details = {c_string_utils::create_null (),
226
+ c_string_utils::create_empty_set (),
227
+ c_string_utils::create_null (),
228
+ c_string_utils::create_empty_set (),
229
+ c_string_utils::create_empty_set (),
230
+ c_string_utils::create_empty_set (),
231
+ c_string_utils::create_empty_set (),
232
+ c_string_utils::create_empty_set (),
233
+ c_string_utils::create_empty_set (),
234
+ c_string_utils::create_null (),
235
+ false ,
236
+ false ,
237
+ c_string_utils::create_null (),
238
+ c_string_utils::create_null (),
239
+ c_string_utils::create_null (),
240
+ hollowMacroSet};
241
+ hollowMainModuleInfo->details = hollowDetails;
242
+
243
+ // Empty Link Library set
244
+ swiftscan_link_library_set_t *hollowLinkLibrarySet =
245
+ new swiftscan_link_library_set_t ;
246
+ hollowLinkLibrarySet->count = 0 ;
247
+ hollowLinkLibrarySet->link_libraries = nullptr ;
248
+ hollowMainModuleInfo->link_libraries = hollowLinkLibrarySet;
249
+
250
+ // Populate the diagnostic info
251
+ hollowResult->diagnostics =
252
+ mapCollectedDiagnosticsForOutput (&ScanDiagnosticConsumer);
253
+ return hollowResult;
254
+ }
255
+
256
+ // Generate an instance of the `swiftscan_import_set_t` which contains no
257
+ // imports but captures the diagnostics emitted during the attempted
258
+ // scan query.
259
+ static swiftscan_import_set_t generateHollowDiagnosticOutputImportSet (
260
+ const DependencyScanDiagnosticCollector &ScanDiagnosticConsumer) {
261
+ // Create an dependency graph instance
262
+ swiftscan_import_set_t hollowResult = new swiftscan_import_set_s;
263
+ hollowResult->imports = c_string_utils::create_empty_set ();
264
+ hollowResult->diagnostics =
265
+ mapCollectedDiagnosticsForOutput (&ScanDiagnosticConsumer);
266
+ return hollowResult;
267
+ }
268
+
143
269
DependencyScanningTool::DependencyScanningTool ()
144
270
: ScanningService(std::make_unique<SwiftDependencyScanningService>()),
145
271
VersionedPCMInstanceCacheCache (
@@ -148,12 +274,20 @@ DependencyScanningTool::DependencyScanningTool()
148
274
149
275
llvm::ErrorOr<swiftscan_dependency_graph_t >
150
276
DependencyScanningTool::getDependencies (
151
- ArrayRef<const char *> Command, const llvm::StringSet<> &PlaceholderModules,
277
+ ArrayRef<const char *> Command,
278
+ const llvm::StringSet<> &PlaceholderModules,
152
279
StringRef WorkingDirectory) {
280
+ // There may be errors as early as in instance initialization, so we must ensure
281
+ // we can catch those.
282
+ auto ScanDiagnosticConsumer = std::make_shared<DependencyScanDiagnosticCollector>();
283
+
153
284
// 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;
285
+ auto QueryContextOrErr = initCompilerInstanceForScan (Command,
286
+ WorkingDirectory,
287
+ ScanDiagnosticConsumer);
288
+ if (QueryContextOrErr.getError ())
289
+ return generateHollowDiagnosticOutput (*ScanDiagnosticConsumer);
290
+
157
291
auto QueryContext = std::move (*QueryContextOrErr);
158
292
159
293
// Local scan cache instance, wrapping the shared global cache.
@@ -166,19 +300,24 @@ DependencyScanningTool::getDependencies(
166
300
QueryContext.ScanDiagnostics .get (),
167
301
cache);
168
302
if (DependenciesOrErr.getError ())
169
- return std::make_error_code (std::errc::not_supported);
170
- auto Dependencies = std::move (*DependenciesOrErr);
303
+ return generateHollowDiagnosticOutput (*ScanDiagnosticConsumer);
171
304
172
- return Dependencies ;
305
+ return std::move (*DependenciesOrErr) ;
173
306
}
174
307
175
308
llvm::ErrorOr<swiftscan_import_set_t >
176
309
DependencyScanningTool::getImports (ArrayRef<const char *> Command,
177
310
StringRef WorkingDirectory) {
311
+ // There may be errors as early as in instance initialization, so we must ensure
312
+ // we can catch those
313
+ auto ScanDiagnosticConsumer = std::make_shared<DependencyScanDiagnosticCollector>();
178
314
// 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;
315
+ auto QueryContextOrErr = initCompilerInstanceForScan (Command,
316
+ WorkingDirectory,
317
+ ScanDiagnosticConsumer);
318
+ if (QueryContextOrErr.getError ())
319
+ return generateHollowDiagnosticOutputImportSet (*ScanDiagnosticConsumer);
320
+
182
321
auto QueryContext = std::move (*QueryContextOrErr);
183
322
184
323
// Local scan cache instance, wrapping the shared global cache.
@@ -190,10 +329,9 @@ DependencyScanningTool::getImports(ArrayRef<const char *> Command,
190
329
QueryContext.ScanDiagnostics .get (),
191
330
cache);
192
331
if (DependenciesOrErr.getError ())
193
- return std::make_error_code (std::errc::not_supported);
194
- auto Dependencies = std::move (*DependenciesOrErr);
332
+ return generateHollowDiagnosticOutputImportSet (*ScanDiagnosticConsumer);
195
333
196
- return Dependencies ;
334
+ return std::move (*DependenciesOrErr) ;
197
335
}
198
336
199
337
std::vector<llvm::ErrorOr<swiftscan_dependency_graph_t >>
@@ -202,10 +340,14 @@ DependencyScanningTool::getDependencies(
202
340
const std::vector<BatchScanInput> &BatchInput,
203
341
const llvm::StringSet<> &PlaceholderModules, StringRef WorkingDirectory) {
204
342
// The primary instance used to scan Swift modules
205
- auto QueryContextOrErr = initScannerForAction (Command, WorkingDirectory);
343
+ auto ScanDiagnosticConsumer = std::make_shared<DependencyScanDiagnosticCollector>();
344
+ auto QueryContextOrErr = initCompilerInstanceForScan (Command,
345
+ WorkingDirectory,
346
+ ScanDiagnosticConsumer);
206
347
if (std::error_code EC = QueryContextOrErr.getError ())
207
348
return std::vector<llvm::ErrorOr<swiftscan_dependency_graph_t >>(
208
349
BatchInput.size (), std::make_error_code (std::errc::invalid_argument));
350
+
209
351
auto QueryContext = std::move (*QueryContextOrErr);
210
352
211
353
// Local scan cache instance, wrapping the shared global cache.
@@ -264,26 +406,26 @@ void DependencyScanningTool::resetDiagnostics() {
264
406
}
265
407
266
408
llvm::ErrorOr<ScanQueryInstance>
267
- DependencyScanningTool::initScannerForAction (
268
- ArrayRef<const char *> Command, StringRef WorkingDirectory) {
409
+ DependencyScanningTool::initCompilerInstanceForScan (
410
+ ArrayRef<const char *> CommandArgs,
411
+ StringRef WorkingDir,
412
+ std::shared_ptr<DependencyScanDiagnosticCollector> scannerDiagnosticsCollector) {
269
413
// The remainder of this method operates on shared state in the
270
414
// scanning service and global LLVM state with:
271
415
// llvm::cl::ResetAllOptionOccurrences
272
416
llvm::sys::SmartScopedLock<true > Lock (DependencyScanningToolStateLock);
273
- return initCompilerInstanceForScan (Command, WorkingDirectory);
274
- }
417
+ // FIXME: Instead, target-info and supported-features queries must use
418
+ // `DependencyScanningToolStateLock`, but this currently requires further
419
+ // client-side API plumbing.
420
+ llvm::sys::SmartScopedLock<true > TargetInfoLock (TargetInfoMutex);
275
421
276
- llvm::ErrorOr<ScanQueryInstance>
277
- DependencyScanningTool::initCompilerInstanceForScan (
278
- ArrayRef<const char *> CommandArgs, StringRef WorkingDir) {
279
422
// State unique to an individual scan
280
423
auto Instance = std::make_unique<CompilerInstance>();
281
- auto ScanDiagnosticConsumer = std::make_unique<DependencyScanDiagnosticCollector>();
282
424
283
425
// FIXME: The shared CDC must be deprecated once all clients have switched
284
426
// to using per-scan diagnostic output embedded in the `swiftscan_dependency_graph_s`
285
427
Instance->addDiagnosticConsumer (&CDC);
286
- Instance->addDiagnosticConsumer (ScanDiagnosticConsumer .get ());
428
+ Instance->addDiagnosticConsumer (scannerDiagnosticsCollector .get ());
287
429
288
430
// Basic error checking on the arguments
289
431
if (CommandArgs.empty ()) {
@@ -327,6 +469,7 @@ DependencyScanningTool::initCompilerInstanceForScan(
327
469
if (Instance->setup (Invocation, InstanceSetupError)) {
328
470
return std::make_error_code (std::errc::not_supported);
329
471
}
472
+ Invocation.getFrontendOptions ().LLVMArgs .clear ();
330
473
331
474
// Setup the caching service after the instance finishes setup.
332
475
if (ScanningService->setupCachingDependencyScanningService (*Instance))
@@ -335,7 +478,7 @@ DependencyScanningTool::initCompilerInstanceForScan(
335
478
(void )Instance->getMainModule ();
336
479
337
480
return ScanQueryInstance{std::move (Instance),
338
- std::move (ScanDiagnosticConsumer) };
481
+ scannerDiagnosticsCollector };
339
482
}
340
483
341
484
} // namespace dependencies
0 commit comments