@@ -140,6 +140,120 @@ 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+
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+ hollowDetails->swift_textual_details = {c_string_utils::create_null (),
223+ c_string_utils::create_empty_set (),
224+ c_string_utils::create_null (),
225+ c_string_utils::create_empty_set (),
226+ c_string_utils::create_empty_set (),
227+ c_string_utils::create_empty_set (),
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_null (),
232+ false ,
233+ c_string_utils::create_null (),
234+ c_string_utils::create_null (),
235+ c_string_utils::create_null ()};
236+ hollowMainModuleInfo->details = hollowDetails;
237+
238+ // Populate the diagnostic info
239+ hollowResult->diagnostics =
240+ mapCollectedDiagnosticsForOutput (&ScanDiagnosticConsumer);
241+ return hollowResult;
242+ }
243+
244+ // Generate an instance of the `swiftscan_import_set_t` which contains no
245+ // imports but captures the diagnostics emitted during the attempted
246+ // scan query.
247+ static swiftscan_import_set_t generateHollowDiagnosticOutputImportSet (
248+ const DependencyScanDiagnosticCollector &ScanDiagnosticConsumer) {
249+ // Create an dependency graph instance
250+ swiftscan_import_set_t hollowResult = new swiftscan_import_set_s;
251+ hollowResult->imports = c_string_utils::create_empty_set ();
252+ hollowResult->diagnostics =
253+ mapCollectedDiagnosticsForOutput (&ScanDiagnosticConsumer);
254+ return hollowResult;
255+ }
256+
143257DependencyScanningTool::DependencyScanningTool ()
144258 : ScanningService(std::make_unique<SwiftDependencyScanningService>()),
145259 VersionedPCMInstanceCacheCache (
@@ -148,12 +262,20 @@ DependencyScanningTool::DependencyScanningTool()
148262
149263llvm::ErrorOr<swiftscan_dependency_graph_t >
150264DependencyScanningTool::getDependencies (
151- ArrayRef<const char *> Command, const llvm::StringSet<> &PlaceholderModules,
265+ ArrayRef<const char *> Command,
266+ const llvm::StringSet<> &PlaceholderModules,
152267 StringRef WorkingDirectory) {
268+ // There may be errors as early as in instance initialization, so we must ensure
269+ // we can catch those.
270+ auto ScanDiagnosticConsumer = std::make_shared<DependencyScanDiagnosticCollector>();
271+
153272 // 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;
273+ auto QueryContextOrErr = initCompilerInstanceForScan (Command,
274+ WorkingDirectory,
275+ ScanDiagnosticConsumer);
276+ if (QueryContextOrErr.getError ())
277+ return generateHollowDiagnosticOutput (*ScanDiagnosticConsumer);
278+
157279 auto QueryContext = std::move (*QueryContextOrErr);
158280
159281 // Local scan cache instance, wrapping the shared global cache.
@@ -166,19 +288,24 @@ DependencyScanningTool::getDependencies(
166288 QueryContext.ScanDiagnostics .get (),
167289 cache);
168290 if (DependenciesOrErr.getError ())
169- return std::make_error_code (std::errc::not_supported);
170- auto Dependencies = std::move (*DependenciesOrErr);
291+ return generateHollowDiagnosticOutput (*ScanDiagnosticConsumer);
171292
172- return Dependencies ;
293+ return std::move (*DependenciesOrErr) ;
173294}
174295
175296llvm::ErrorOr<swiftscan_import_set_t >
176297DependencyScanningTool::getImports (ArrayRef<const char *> Command,
177298 StringRef WorkingDirectory) {
299+ // There may be errors as early as in instance initialization, so we must ensure
300+ // we can catch those
301+ auto ScanDiagnosticConsumer = std::make_shared<DependencyScanDiagnosticCollector>();
178302 // 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;
303+ auto QueryContextOrErr = initCompilerInstanceForScan (Command,
304+ WorkingDirectory,
305+ ScanDiagnosticConsumer);
306+ if (QueryContextOrErr.getError ())
307+ return generateHollowDiagnosticOutputImportSet (*ScanDiagnosticConsumer);
308+
182309 auto QueryContext = std::move (*QueryContextOrErr);
183310
184311 // Local scan cache instance, wrapping the shared global cache.
@@ -190,10 +317,9 @@ DependencyScanningTool::getImports(ArrayRef<const char *> Command,
190317 QueryContext.ScanDiagnostics .get (),
191318 cache);
192319 if (DependenciesOrErr.getError ())
193- return std::make_error_code (std::errc::not_supported);
194- auto Dependencies = std::move (*DependenciesOrErr);
320+ return generateHollowDiagnosticOutputImportSet (*ScanDiagnosticConsumer);
195321
196- return Dependencies ;
322+ return std::move (*DependenciesOrErr) ;
197323}
198324
199325std::vector<llvm::ErrorOr<swiftscan_dependency_graph_t >>
@@ -202,10 +328,14 @@ DependencyScanningTool::getDependencies(
202328 const std::vector<BatchScanInput> &BatchInput,
203329 const llvm::StringSet<> &PlaceholderModules, StringRef WorkingDirectory) {
204330 // The primary instance used to scan Swift modules
205- auto QueryContextOrErr = initScannerForAction (Command, WorkingDirectory);
331+ auto ScanDiagnosticConsumer = std::make_shared<DependencyScanDiagnosticCollector>();
332+ auto QueryContextOrErr = initCompilerInstanceForScan (Command,
333+ WorkingDirectory,
334+ ScanDiagnosticConsumer);
206335 if (std::error_code EC = QueryContextOrErr.getError ())
207336 return std::vector<llvm::ErrorOr<swiftscan_dependency_graph_t >>(
208337 BatchInput.size (), std::make_error_code (std::errc::invalid_argument));
338+
209339 auto QueryContext = std::move (*QueryContextOrErr);
210340
211341 // Local scan cache instance, wrapping the shared global cache.
@@ -264,26 +394,26 @@ void DependencyScanningTool::resetDiagnostics() {
264394}
265395
266396llvm::ErrorOr<ScanQueryInstance>
267- DependencyScanningTool::initScannerForAction (
268- ArrayRef<const char *> Command, StringRef WorkingDirectory) {
397+ DependencyScanningTool::initCompilerInstanceForScan (
398+ ArrayRef<const char *> CommandArgs,
399+ StringRef WorkingDir,
400+ std::shared_ptr<DependencyScanDiagnosticCollector> scannerDiagnosticsCollector) {
269401 // The remainder of this method operates on shared state in the
270402 // scanning service and global LLVM state with:
271403 // llvm::cl::ResetAllOptionOccurrences
272404 llvm::sys::SmartScopedLock<true > Lock (DependencyScanningToolStateLock);
273- return initCompilerInstanceForScan (Command, WorkingDirectory);
274- }
405+ // FIXME: Instead, target-info and supported-features queries must use
406+ // `DependencyScanningToolStateLock`, but this currently requires further
407+ // client-side API plumbing.
408+ llvm::sys::SmartScopedLock<true > TargetInfoLock (TargetInfoMutex);
275409
276- llvm::ErrorOr<ScanQueryInstance>
277- DependencyScanningTool::initCompilerInstanceForScan (
278- ArrayRef<const char *> CommandArgs, StringRef WorkingDir) {
279410 // State unique to an individual scan
280411 auto Instance = std::make_unique<CompilerInstance>();
281- auto ScanDiagnosticConsumer = std::make_unique<DependencyScanDiagnosticCollector>();
282412
283413 // FIXME: The shared CDC must be deprecated once all clients have switched
284414 // to using per-scan diagnostic output embedded in the `swiftscan_dependency_graph_s`
285415 Instance->addDiagnosticConsumer (&CDC);
286- Instance->addDiagnosticConsumer (ScanDiagnosticConsumer .get ());
416+ Instance->addDiagnosticConsumer (scannerDiagnosticsCollector .get ());
287417
288418 // Basic error checking on the arguments
289419 if (CommandArgs.empty ()) {
@@ -327,6 +457,7 @@ DependencyScanningTool::initCompilerInstanceForScan(
327457 if (Instance->setup (Invocation, InstanceSetupError)) {
328458 return std::make_error_code (std::errc::not_supported);
329459 }
460+ Invocation.getFrontendOptions ().LLVMArgs .clear ();
330461
331462 // Setup the caching service after the instance finishes setup.
332463 if (ScanningService->setupCachingDependencyScanningService (*Instance))
@@ -335,7 +466,7 @@ DependencyScanningTool::initCompilerInstanceForScan(
335466 (void )Instance->getMainModule ();
336467
337468 return ScanQueryInstance{std::move (Instance),
338- std::move (ScanDiagnosticConsumer) };
469+ scannerDiagnosticsCollector };
339470}
340471
341472} // namespace dependencies
0 commit comments