@@ -140,6 +140,132 @@ 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+ 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+
143269DependencyScanningTool::DependencyScanningTool ()
144270 : ScanningService(std::make_unique<SwiftDependencyScanningService>()),
145271 VersionedPCMInstanceCacheCache (
@@ -148,12 +274,20 @@ DependencyScanningTool::DependencyScanningTool()
148274
149275llvm::ErrorOr<swiftscan_dependency_graph_t >
150276DependencyScanningTool::getDependencies (
151- ArrayRef<const char *> Command, const llvm::StringSet<> &PlaceholderModules,
277+ ArrayRef<const char *> Command,
278+ const llvm::StringSet<> &PlaceholderModules,
152279 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+
153284 // 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+
157291 auto QueryContext = std::move (*QueryContextOrErr);
158292
159293 // Local scan cache instance, wrapping the shared global cache.
@@ -166,19 +300,24 @@ DependencyScanningTool::getDependencies(
166300 QueryContext.ScanDiagnostics .get (),
167301 cache);
168302 if (DependenciesOrErr.getError ())
169- return std::make_error_code (std::errc::not_supported);
170- auto Dependencies = std::move (*DependenciesOrErr);
303+ return generateHollowDiagnosticOutput (*ScanDiagnosticConsumer);
171304
172- return Dependencies ;
305+ return std::move (*DependenciesOrErr) ;
173306}
174307
175308llvm::ErrorOr<swiftscan_import_set_t >
176309DependencyScanningTool::getImports (ArrayRef<const char *> Command,
177310 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>();
178314 // 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+
182321 auto QueryContext = std::move (*QueryContextOrErr);
183322
184323 // Local scan cache instance, wrapping the shared global cache.
@@ -190,10 +329,9 @@ DependencyScanningTool::getImports(ArrayRef<const char *> Command,
190329 QueryContext.ScanDiagnostics .get (),
191330 cache);
192331 if (DependenciesOrErr.getError ())
193- return std::make_error_code (std::errc::not_supported);
194- auto Dependencies = std::move (*DependenciesOrErr);
332+ return generateHollowDiagnosticOutputImportSet (*ScanDiagnosticConsumer);
195333
196- return Dependencies ;
334+ return std::move (*DependenciesOrErr) ;
197335}
198336
199337std::vector<llvm::ErrorOr<swiftscan_dependency_graph_t >>
@@ -202,10 +340,14 @@ DependencyScanningTool::getDependencies(
202340 const std::vector<BatchScanInput> &BatchInput,
203341 const llvm::StringSet<> &PlaceholderModules, StringRef WorkingDirectory) {
204342 // 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);
206347 if (std::error_code EC = QueryContextOrErr.getError ())
207348 return std::vector<llvm::ErrorOr<swiftscan_dependency_graph_t >>(
208349 BatchInput.size (), std::make_error_code (std::errc::invalid_argument));
350+
209351 auto QueryContext = std::move (*QueryContextOrErr);
210352
211353 // Local scan cache instance, wrapping the shared global cache.
@@ -264,26 +406,26 @@ void DependencyScanningTool::resetDiagnostics() {
264406}
265407
266408llvm::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) {
269413 // The remainder of this method operates on shared state in the
270414 // scanning service and global LLVM state with:
271415 // llvm::cl::ResetAllOptionOccurrences
272416 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);
275421
276- llvm::ErrorOr<ScanQueryInstance>
277- DependencyScanningTool::initCompilerInstanceForScan (
278- ArrayRef<const char *> CommandArgs, StringRef WorkingDir) {
279422 // State unique to an individual scan
280423 auto Instance = std::make_unique<CompilerInstance>();
281- auto ScanDiagnosticConsumer = std::make_unique<DependencyScanDiagnosticCollector>();
282424
283425 // FIXME: The shared CDC must be deprecated once all clients have switched
284426 // to using per-scan diagnostic output embedded in the `swiftscan_dependency_graph_s`
285427 Instance->addDiagnosticConsumer (&CDC);
286- Instance->addDiagnosticConsumer (ScanDiagnosticConsumer .get ());
428+ Instance->addDiagnosticConsumer (scannerDiagnosticsCollector .get ());
287429
288430 // Basic error checking on the arguments
289431 if (CommandArgs.empty ()) {
@@ -327,6 +469,7 @@ DependencyScanningTool::initCompilerInstanceForScan(
327469 if (Instance->setup (Invocation, InstanceSetupError)) {
328470 return std::make_error_code (std::errc::not_supported);
329471 }
472+ Invocation.getFrontendOptions ().LLVMArgs .clear ();
330473
331474 // Setup the caching service after the instance finishes setup.
332475 if (ScanningService->setupCachingDependencyScanningService (*Instance))
@@ -335,7 +478,7 @@ DependencyScanningTool::initCompilerInstanceForScan(
335478 (void )Instance->getMainModule ();
336479
337480 return ScanQueryInstance{std::move (Instance),
338- std::move (ScanDiagnosticConsumer) };
481+ scannerDiagnosticsCollector };
339482}
340483
341484} // namespace dependencies
0 commit comments