@@ -54,6 +54,28 @@ public enum DependencyScanningError: Error, DiagnosticData {
5454 }
5555}
5656
57+ @_spi ( Testing) public struct ScannerDiagnosticPayload {
58+ @_spi ( Testing) public let severity : Diagnostic . Behavior
59+ @_spi ( Testing) public let message : String
60+ }
61+
62+ internal extension swiftscan_diagnostic_severity_t {
63+ func toDiagnosticBehavior( ) -> Diagnostic . Behavior {
64+ switch self {
65+ case SWIFTSCAN_DIAGNOSTIC_SEVERITY_ERROR:
66+ return Diagnostic . Behavior. error
67+ case SWIFTSCAN_DIAGNOSTIC_SEVERITY_WARNING:
68+ return Diagnostic . Behavior. warning
69+ case SWIFTSCAN_DIAGNOSTIC_SEVERITY_NOTE:
70+ return Diagnostic . Behavior. note
71+ case SWIFTSCAN_DIAGNOSTIC_SEVERITY_REMARK:
72+ return Diagnostic . Behavior. remark
73+ default :
74+ return Diagnostic . Behavior. error
75+ }
76+ }
77+ }
78+
5779/// Wrapper for libSwiftScan, taking care of initialization, shutdown, and dispatching dependency scanning queries.
5880internal final class SwiftScan {
5981 /// The path to the libSwiftScan dylib.
@@ -232,6 +254,41 @@ internal final class SwiftScan {
232254 func resetScannerCache( ) {
233255 api. swiftscan_scanner_cache_reset ( scanner)
234256 }
257+
258+ @_spi ( Testing) public func supportsScannerDiagnostics( ) -> Bool {
259+ return api. swiftscan_scanner_diagnostics_query != nil &&
260+ api. swiftscan_scanner_diagnostics_reset != nil &&
261+ api. swiftscan_diagnostic_get_message != nil &&
262+ api. swiftscan_diagnostic_get_severity != nil &&
263+ api. swiftscan_diagnostics_set_dispose != nil
264+ }
265+
266+ @_spi ( Testing) public func queryScannerDiagnostics( ) throws -> [ ScannerDiagnosticPayload ] {
267+ var result : [ ScannerDiagnosticPayload ] = [ ]
268+ let diagnosticSetRefOrNull = api. swiftscan_scanner_diagnostics_query ( scanner)
269+ guard let diagnosticSetRef = diagnosticSetRefOrNull else {
270+ // Seems heavy-handed to fail here
271+ // throw DependencyScanningError.dependencyScanFailed
272+ return [ ]
273+ }
274+ defer { api. swiftscan_diagnostics_set_dispose ( diagnosticSetRef) }
275+ let diagnosticRefArray = Array ( UnsafeBufferPointer ( start: diagnosticSetRef. pointee. diagnostics,
276+ count: Int ( diagnosticSetRef. pointee. count) ) )
277+
278+ for diagnosticRefOrNull in diagnosticRefArray {
279+ guard let diagnosticRef = diagnosticRefOrNull else {
280+ throw DependencyScanningError . dependencyScanFailed
281+ }
282+ let message = try toSwiftString ( api. swiftscan_diagnostic_get_message ( diagnosticRef) )
283+ let severity = api. swiftscan_diagnostic_get_severity ( diagnosticRef)
284+ result. append ( ScannerDiagnosticPayload ( severity: severity. toDiagnosticBehavior ( ) , message: message) )
285+ }
286+ return result
287+ }
288+
289+ @_spi ( Testing) public func resetScannerDiagnostics( ) throws {
290+ api. swiftscan_scanner_diagnostics_reset ( scanner)
291+ }
235292
236293 @_spi ( Testing) public func canQuerySupportedArguments( ) -> Bool {
237294 return api. swiftscan_compiler_supported_arguments_query != nil &&
@@ -297,6 +354,18 @@ private extension swiftscan_functions_t {
297354 // Clang dependency captured PCM args
298355 self . swiftscan_clang_detail_get_captured_pcm_args =
299356 try loadOptional ( " swiftscan_clang_detail_get_captured_pcm_args " )
357+
358+ // Scanner diagnostic emission query
359+ self . swiftscan_scanner_diagnostics_query =
360+ try loadOptional ( " swiftscan_scanner_diagnostics_query " )
361+ self . swiftscan_scanner_diagnostics_reset =
362+ try loadOptional ( " swiftscan_scanner_diagnostics_reset " )
363+ self . swiftscan_diagnostic_get_message =
364+ try loadOptional ( " swiftscan_diagnostic_get_message " )
365+ self . swiftscan_diagnostic_get_severity =
366+ try loadOptional ( " swiftscan_diagnostic_get_severity " )
367+ self . swiftscan_diagnostics_set_dispose =
368+ try loadOptional ( " swiftscan_diagnostics_set_dispose " )
300369
301370 // MARK: Required Methods
302371 func loadRequired< T> ( _ symbol: String ) throws -> T {
0 commit comments