@@ -57,6 +57,28 @@ public enum DependencyScanningError: Error, DiagnosticData {
5757 }
5858}
5959
60+ @_spi ( Testing) public struct ScannerDiagnosticPayload {
61+ @_spi ( Testing) public let severity : Diagnostic . Behavior
62+ @_spi ( Testing) public let message : String
63+ }
64+
65+ internal extension swiftscan_diagnostic_severity_t {
66+ func toDiagnosticBehavior( ) -> Diagnostic . Behavior {
67+ switch self {
68+ case SWIFTSCAN_DIAGNOSTIC_SEVERITY_ERROR:
69+ return Diagnostic . Behavior. error
70+ case SWIFTSCAN_DIAGNOSTIC_SEVERITY_WARNING:
71+ return Diagnostic . Behavior. warning
72+ case SWIFTSCAN_DIAGNOSTIC_SEVERITY_NOTE:
73+ return Diagnostic . Behavior. note
74+ case SWIFTSCAN_DIAGNOSTIC_SEVERITY_REMARK:
75+ return Diagnostic . Behavior. remark
76+ default :
77+ return Diagnostic . Behavior. error
78+ }
79+ }
80+ }
81+
6082/// Wrapper for libSwiftScan, taking care of initialization, shutdown, and dispatching dependency scanning queries.
6183internal final class SwiftScan {
6284 /// The path to the libSwiftScan dylib.
@@ -235,6 +257,41 @@ internal final class SwiftScan {
235257 func resetScannerCache( ) {
236258 api. swiftscan_scanner_cache_reset ( scanner)
237259 }
260+
261+ @_spi ( Testing) public func supportsScannerDiagnostics( ) -> Bool {
262+ return api. swiftscan_scanner_diagnostics_query != nil &&
263+ api. swiftscan_scanner_diagnostics_reset != nil &&
264+ api. swiftscan_diagnostic_get_message != nil &&
265+ api. swiftscan_diagnostic_get_severity != nil &&
266+ api. swiftscan_diagnostics_set_dispose != nil
267+ }
268+
269+ @_spi ( Testing) public func queryScannerDiagnostics( ) throws -> [ ScannerDiagnosticPayload ] {
270+ var result : [ ScannerDiagnosticPayload ] = [ ]
271+ let diagnosticSetRefOrNull = api. swiftscan_scanner_diagnostics_query ( scanner)
272+ guard let diagnosticSetRef = diagnosticSetRefOrNull else {
273+ // Seems heavy-handed to fail here
274+ // throw DependencyScanningError.dependencyScanFailed
275+ return [ ]
276+ }
277+ defer { api. swiftscan_diagnostics_set_dispose ( diagnosticSetRef) }
278+ let diagnosticRefArray = Array ( UnsafeBufferPointer ( start: diagnosticSetRef. pointee. diagnostics,
279+ count: Int ( diagnosticSetRef. pointee. count) ) )
280+
281+ for diagnosticRefOrNull in diagnosticRefArray {
282+ guard let diagnosticRef = diagnosticRefOrNull else {
283+ throw DependencyScanningError . dependencyScanFailed
284+ }
285+ let message = try toSwiftString ( api. swiftscan_diagnostic_get_message ( diagnosticRef) )
286+ let severity = api. swiftscan_diagnostic_get_severity ( diagnosticRef)
287+ result. append ( ScannerDiagnosticPayload ( severity: severity. toDiagnosticBehavior ( ) , message: message) )
288+ }
289+ return result
290+ }
291+
292+ @_spi ( Testing) public func resetScannerDiagnostics( ) throws {
293+ api. swiftscan_scanner_diagnostics_reset ( scanner)
294+ }
238295
239296 @_spi ( Testing) public func canQuerySupportedArguments( ) -> Bool {
240297 return api. swiftscan_compiler_supported_arguments_query != nil &&
@@ -300,6 +357,18 @@ private extension swiftscan_functions_t {
300357 // Clang dependency captured PCM args
301358 self . swiftscan_clang_detail_get_captured_pcm_args =
302359 try loadOptional ( " swiftscan_clang_detail_get_captured_pcm_args " )
360+
361+ // Scanner diagnostic emission query
362+ self . swiftscan_scanner_diagnostics_query =
363+ try loadOptional ( " swiftscan_scanner_diagnostics_query " )
364+ self . swiftscan_scanner_diagnostics_reset =
365+ try loadOptional ( " swiftscan_scanner_diagnostics_reset " )
366+ self . swiftscan_diagnostic_get_message =
367+ try loadOptional ( " swiftscan_diagnostic_get_message " )
368+ self . swiftscan_diagnostic_get_severity =
369+ try loadOptional ( " swiftscan_diagnostic_get_severity " )
370+ self . swiftscan_diagnostics_set_dispose =
371+ try loadOptional ( " swiftscan_diagnostics_set_dispose " )
303372
304373 // MARK: Required Methods
305374 func loadRequired< T> ( _ symbol: String ) throws -> T {
0 commit comments