@@ -42,17 +42,22 @@ public final class SwiftABICheckerToolSpec : GenericCommandLineToolSpec, SpecIde
42
42
/// The path to the serialized diagnostic output. Every clang task must provide this path.
43
43
let serializedDiagnosticsPath : Path
44
44
45
- init ( serializedDiagnosticsPath: Path ) {
45
+ let downgradeErrors : Bool
46
+
47
+ init ( serializedDiagnosticsPath: Path , downgradeErrors: Bool ) {
46
48
self . serializedDiagnosticsPath = serializedDiagnosticsPath
49
+ self . downgradeErrors = downgradeErrors
47
50
}
48
51
public func serialize< T: Serializer > ( to serializer: T ) {
49
- serializer. serializeAggregate ( 1 ) {
52
+ serializer. serializeAggregate ( 2 ) {
50
53
serializer. serialize ( serializedDiagnosticsPath)
54
+ serializer. serialize ( downgradeErrors)
51
55
}
52
56
}
53
57
public init ( from deserializer: any Deserializer ) throws {
54
- try deserializer. beginAggregate ( 1 )
58
+ try deserializer. beginAggregate ( 2 )
55
59
self . serializedDiagnosticsPath = try deserializer. deserialize ( )
60
+ self . downgradeErrors = try deserializer. deserialize ( )
56
61
}
57
62
}
58
63
@@ -67,7 +72,12 @@ public final class SwiftABICheckerToolSpec : GenericCommandLineToolSpec, SpecIde
67
72
68
73
// Override this func to ensure we can see these diagnostics in unit tests.
69
74
public override func customOutputParserType( for task: any ExecutableTask ) -> ( any TaskOutputParser . Type ) ? {
70
- return SerializedDiagnosticsOutputParser . self
75
+ let payload = task. payload! as! ABICheckerPayload
76
+ if payload. downgradeErrors {
77
+ return APIDigesterDowngradingSerializedDiagnosticsOutputParser . self
78
+ } else {
79
+ return SerializedDiagnosticsOutputParser . self
80
+ }
71
81
}
72
82
public func constructABICheckingTask( _ cbc: CommandBuildContext , _ delegate: any TaskGenerationDelegate , _ serializedDiagsPath: Path , _ baselinePath: Path ? , _ allowlistPath: Path ? ) async {
73
83
let toolSpecInfo : DiscoveredSwiftCompilerToolSpecInfo
@@ -86,6 +96,10 @@ public final class SwiftABICheckerToolSpec : GenericCommandLineToolSpec, SpecIde
86
96
if let allowlistPath {
87
97
commandLine += [ " -breakage-allowlist-path " , allowlistPath. normalize ( ) . str]
88
98
}
99
+ let downgradeErrors = cbc. scope. evaluate ( BuiltinMacros . SWIFT_ABI_CHECKER_DOWNGRADE_ERRORS)
100
+ if downgradeErrors {
101
+ commandLine += [ " -disable-fail-on-error " ]
102
+ }
89
103
let allInputs = cbc. inputs. map { delegate. createNode ( $0. absolutePath) } + [ baselinePath, allowlistPath] . compactMap { $0 } . map { delegate. createNode ( $0. normalize ( ) ) }
90
104
// Add import search paths
91
105
for searchPath in SwiftCompilerSpec . collectInputSearchPaths ( cbc, toolInfo: toolSpecInfo) {
@@ -95,7 +109,10 @@ public final class SwiftABICheckerToolSpec : GenericCommandLineToolSpec, SpecIde
95
109
commandLine += cbc. scope. evaluate ( BuiltinMacros . SWIFT_SYSTEM_INCLUDE_PATHS) . flatMap { [ " -I " , $0] }
96
110
commandLine += cbc. scope. evaluate ( BuiltinMacros . SYSTEM_FRAMEWORK_SEARCH_PATHS) . flatMap { [ " -F " , $0] }
97
111
delegate. createTask ( type: self ,
98
- payload: ABICheckerPayload ( serializedDiagnosticsPath: serializedDiagsPath) ,
112
+ payload: ABICheckerPayload (
113
+ serializedDiagnosticsPath: serializedDiagsPath,
114
+ downgradeErrors: downgradeErrors
115
+ ) ,
99
116
ruleInfo: defaultRuleInfo ( cbc, delegate) ,
100
117
commandLine: commandLine,
101
118
environment: environmentFromSpec ( cbc, delegate) ,
@@ -105,3 +122,40 @@ public final class SwiftABICheckerToolSpec : GenericCommandLineToolSpec, SpecIde
105
122
enableSandboxing: enableSandboxing)
106
123
}
107
124
}
125
+
126
+ public final class APIDigesterDowngradingSerializedDiagnosticsOutputParser : TaskOutputParser {
127
+ private let task : any ExecutableTask
128
+
129
+ public let workspaceContext : WorkspaceContext
130
+ public let buildRequestContext : BuildRequestContext
131
+ public let delegate : any TaskOutputParserDelegate
132
+
133
+ required public init ( for task: any ExecutableTask , workspaceContext: WorkspaceContext , buildRequestContext: BuildRequestContext , delegate: any TaskOutputParserDelegate , progressReporter: ( any SubtaskProgressReporter ) ? ) {
134
+ self . task = task
135
+ self . workspaceContext = workspaceContext
136
+ self . buildRequestContext = buildRequestContext
137
+ self . delegate = delegate
138
+ }
139
+
140
+ public func write( bytes: ByteString ) {
141
+ // Forward the unparsed bytes immediately (without line buffering).
142
+ delegate. emitOutput ( bytes)
143
+
144
+ // Disable diagnostic scraping, since we use serialized diagnostics.
145
+ }
146
+
147
+ public func close( result: TaskResult ? ) {
148
+ defer {
149
+ delegate. close ( )
150
+ }
151
+ // Don't try to read diagnostics if the process crashed or got cancelled as they were almost certainly not written in this case.
152
+ if result. shouldSkipParsingDiagnostics { return }
153
+
154
+ for path in task. type. serializedDiagnosticsPaths ( task, workspaceContext. fs) {
155
+ let diagnostics = delegate. readSerializedDiagnostics ( at: path, workingDirectory: task. workingDirectory, workspaceContext: workspaceContext)
156
+ for diagnostic in diagnostics {
157
+ delegate. diagnosticsEngine. emit ( diagnostic. with ( behavior: diagnostic. behavior == . error ? . warning : diagnostic. behavior) )
158
+ }
159
+ }
160
+ }
161
+ }
0 commit comments