@@ -140,6 +140,55 @@ 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
+
143
192
DependencyScanningTool::DependencyScanningTool ()
144
193
: ScanningService(std::make_unique<SwiftDependencyScanningService>()),
145
194
VersionedPCMInstanceCacheCache (
@@ -148,12 +197,25 @@ DependencyScanningTool::DependencyScanningTool()
148
197
149
198
llvm::ErrorOr<swiftscan_dependency_graph_t >
150
199
DependencyScanningTool::getDependencies (
151
- ArrayRef<const char *> Command, const llvm::StringSet<> &PlaceholderModules,
200
+ ArrayRef<const char *> Command,
201
+ const llvm::StringSet<> &PlaceholderModules,
152
202
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
+
153
212
// 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
+
157
219
auto QueryContext = std::move (*QueryContextOrErr);
158
220
159
221
// Local scan cache instance, wrapping the shared global cache.
@@ -166,19 +228,26 @@ DependencyScanningTool::getDependencies(
166
228
QueryContext.ScanDiagnostics .get (),
167
229
cache);
168
230
if (DependenciesOrErr.getError ())
169
- return std::make_error_code (std::errc::not_supported);
170
- auto Dependencies = std::move (*DependenciesOrErr);
231
+ return produceDiagnosticStateOnFailure ();
171
232
172
- return Dependencies ;
233
+ return std::move (*DependenciesOrErr); ;
173
234
}
174
235
175
236
llvm::ErrorOr<swiftscan_import_set_t >
176
237
DependencyScanningTool::getImports (ArrayRef<const char *> Command,
177
238
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>();
178
242
// 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
+ }
182
251
auto QueryContext = std::move (*QueryContextOrErr);
183
252
184
253
// Local scan cache instance, wrapping the shared global cache.
@@ -202,10 +271,14 @@ DependencyScanningTool::getDependencies(
202
271
const std::vector<BatchScanInput> &BatchInput,
203
272
const llvm::StringSet<> &PlaceholderModules, StringRef WorkingDirectory) {
204
273
// 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);
206
278
if (std::error_code EC = QueryContextOrErr.getError ())
207
279
return std::vector<llvm::ErrorOr<swiftscan_dependency_graph_t >>(
208
280
BatchInput.size (), std::make_error_code (std::errc::invalid_argument));
281
+
209
282
auto QueryContext = std::move (*QueryContextOrErr);
210
283
211
284
// Local scan cache instance, wrapping the shared global cache.
@@ -264,26 +337,26 @@ void DependencyScanningTool::resetDiagnostics() {
264
337
}
265
338
266
339
llvm::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) {
269
344
// The remainder of this method operates on shared state in the
270
345
// scanning service and global LLVM state with:
271
346
// llvm::cl::ResetAllOptionOccurrences
272
347
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);
275
352
276
- llvm::ErrorOr<ScanQueryInstance>
277
- DependencyScanningTool::initCompilerInstanceForScan (
278
- ArrayRef<const char *> CommandArgs, StringRef WorkingDir) {
279
353
// State unique to an individual scan
280
354
auto Instance = std::make_unique<CompilerInstance>();
281
- auto ScanDiagnosticConsumer = std::make_unique<DependencyScanDiagnosticCollector>();
282
355
283
356
// FIXME: The shared CDC must be deprecated once all clients have switched
284
357
// to using per-scan diagnostic output embedded in the `swiftscan_dependency_graph_s`
285
358
Instance->addDiagnosticConsumer (&CDC);
286
- Instance->addDiagnosticConsumer (ScanDiagnosticConsumer .get ());
359
+ Instance->addDiagnosticConsumer (scannerDiagnosticsCollector .get ());
287
360
288
361
// Basic error checking on the arguments
289
362
if (CommandArgs.empty ()) {
@@ -327,6 +400,7 @@ DependencyScanningTool::initCompilerInstanceForScan(
327
400
if (Instance->setup (Invocation, InstanceSetupError)) {
328
401
return std::make_error_code (std::errc::not_supported);
329
402
}
403
+ Invocation.getFrontendOptions ().LLVMArgs .clear ();
330
404
331
405
// Setup the caching service after the instance finishes setup.
332
406
if (ScanningService->setupCachingDependencyScanningService (*Instance))
@@ -335,7 +409,7 @@ DependencyScanningTool::initCompilerInstanceForScan(
335
409
(void )Instance->getMainModule ();
336
410
337
411
return ScanQueryInstance{std::move (Instance),
338
- std::move (ScanDiagnosticConsumer) };
412
+ scannerDiagnosticsCollector };
339
413
}
340
414
341
415
} // namespace dependencies
0 commit comments