Skip to content

Commit 8a5618c

Browse files
committed
Move XCBuildMessage to its own file
1 parent 07bb3cf commit 8a5618c

File tree

3 files changed

+352
-338
lines changed

3 files changed

+352
-338
lines changed

Sources/XCBuildSupport/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ add_library(XCBuildSupport
1010
PIF.swift
1111
PIFBuilder.swift
1212
XCBuildDelegate.swift
13+
XCBuildMessage.swift
1314
XCBuildOutputParser.swift
1415
XcodeBuildSystem.swift
1516
)
Lines changed: 351 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,351 @@
1+
/*
2+
This source file is part of the Swift.org open source project
3+
4+
Copyright (c) 2020 Apple Inc. and the Swift project authors
5+
Licensed under Apache License v2.0 with Runtime Library Exception
6+
7+
See http://swift.org/LICENSE.txt for license information
8+
See http://swift.org/CONTRIBUTORS.txt for Swift project authors
9+
*/
10+
11+
import Foundation
12+
import TSCBasic
13+
import TSCUtility
14+
15+
/// Represents a message output by xcbuild.
16+
public enum XCBuildMessage {
17+
public struct BuildDiagnosticInfo {
18+
public let message: String
19+
}
20+
21+
public struct BuildCompletedInfo {
22+
public enum Result: String {
23+
case ok
24+
case failed
25+
case cancelled
26+
case aborted
27+
}
28+
29+
public let result: Result
30+
}
31+
32+
public struct BuildOutputInfo {
33+
let data: String
34+
}
35+
36+
public struct DidUpdateProgressInfo {
37+
public let message: String
38+
public let percentComplete: Double
39+
public let showInLog: Bool
40+
}
41+
42+
public struct TargetUpToDateInfo {
43+
public let guid: PIF.GUID
44+
}
45+
46+
public struct TargetStartedInfo {
47+
public enum Kind: String {
48+
case native = "Native"
49+
case aggregate = "Aggregate"
50+
case external = "External"
51+
case packageProduct = "Package Product"
52+
}
53+
54+
public let targetID: Int
55+
public let targetGUID: PIF.GUID
56+
public let targetName: String
57+
public let type: Kind
58+
}
59+
60+
public struct TargetCompleteInfo {
61+
public let targetID: Int
62+
}
63+
64+
public struct TaskUpToDateInfo {
65+
let targetID: Int?
66+
let taskSignature: String
67+
let parentTaskID: Int?
68+
}
69+
70+
public struct TaskStartedInfo {
71+
let taskID: Int
72+
let targetID: Int?
73+
let taskSignature: String
74+
let parentTaskID: Int?
75+
let ruleInfo: String
76+
let interestingPath: AbsolutePath?
77+
let commandLineDisplayString: String?
78+
let executionDescription: String
79+
}
80+
81+
public struct TaskDiagnosticInfo {
82+
let taskID: Int
83+
let targetID: Int?
84+
let message: String
85+
}
86+
87+
public struct TaskOutputInfo {
88+
let taskID: Int
89+
let data: String
90+
}
91+
92+
public struct TaskCompleteInfo {
93+
public enum Result: String {
94+
case success
95+
case failed
96+
case cancelled
97+
}
98+
99+
let taskID: Int
100+
let result: Result
101+
let signalled: Bool
102+
}
103+
104+
public struct TargetDiagnosticInfo {
105+
let targetID: Int
106+
let message: String
107+
}
108+
109+
case buildStarted
110+
case buildDiagnostic(BuildDiagnosticInfo)
111+
case buildCompleted(BuildCompletedInfo)
112+
case buildOutput(BuildOutputInfo)
113+
case preparationComplete
114+
case didUpdateProgress(DidUpdateProgressInfo)
115+
case targetUpToDate(TargetUpToDateInfo)
116+
case targetStarted(TargetStartedInfo)
117+
case targetComplete(TargetCompleteInfo)
118+
case taskUpToDate(TaskUpToDateInfo)
119+
case taskStarted(TaskStartedInfo)
120+
case taskDiagnostic(TaskDiagnosticInfo)
121+
case taskOutput(TaskOutputInfo)
122+
case taskComplete(TaskCompleteInfo)
123+
case targetDiagnostic(TargetDiagnosticInfo)
124+
}
125+
126+
extension XCBuildMessage.BuildDiagnosticInfo: Decodable, Equatable {}
127+
extension XCBuildMessage.BuildCompletedInfo.Result: Decodable, Equatable {}
128+
extension XCBuildMessage.BuildCompletedInfo: Decodable, Equatable {}
129+
extension XCBuildMessage.BuildOutputInfo: Decodable, Equatable {}
130+
extension XCBuildMessage.TargetUpToDateInfo: Decodable, Equatable {}
131+
extension XCBuildMessage.TaskDiagnosticInfo: Decodable, Equatable {}
132+
extension XCBuildMessage.TargetDiagnosticInfo: Decodable, Equatable {}
133+
134+
extension XCBuildMessage.DidUpdateProgressInfo: Decodable, Equatable {
135+
enum CodingKeys: String, CodingKey {
136+
case message
137+
case percentComplete
138+
case showInLog
139+
}
140+
141+
public init(from decoder: Decoder) throws {
142+
let container = try decoder.container(keyedBy: CodingKeys.self)
143+
message = try container.decode(String.self, forKey: .message)
144+
percentComplete = try container.decodeDoubleOrString(forKey: .percentComplete)
145+
showInLog = try container.decodeBoolOrString(forKey: .showInLog)
146+
}
147+
}
148+
149+
extension XCBuildMessage.TargetStartedInfo.Kind: Decodable, Equatable {}
150+
extension XCBuildMessage.TargetStartedInfo: Decodable, Equatable {
151+
enum CodingKeys: String, CodingKey {
152+
case targetID = "id"
153+
case targetGUID = "guid"
154+
case targetName = "name"
155+
case type
156+
}
157+
158+
public init(from decoder: Decoder) throws {
159+
let container = try decoder.container(keyedBy: CodingKeys.self)
160+
targetID = try container.decodeIntOrString(forKey: .targetID)
161+
targetGUID = try container.decode(PIF.GUID.self, forKey: .targetGUID)
162+
targetName = try container.decode(String.self, forKey: .targetName)
163+
type = try container.decode(Kind.self, forKey: .type)
164+
}
165+
}
166+
167+
extension XCBuildMessage.TargetCompleteInfo: Decodable, Equatable {
168+
enum CodingKeys: String, CodingKey {
169+
case targetID = "id"
170+
}
171+
172+
public init(from decoder: Decoder) throws {
173+
let container = try decoder.container(keyedBy: CodingKeys.self)
174+
targetID = try container.decodeIntOrString(forKey: .targetID)
175+
}
176+
}
177+
178+
extension XCBuildMessage.TaskUpToDateInfo: Decodable, Equatable {
179+
enum CodingKeys: String, CodingKey {
180+
case targetID
181+
case taskSignature = "signature"
182+
case parentTaskID = "parentID"
183+
}
184+
185+
public init(from decoder: Decoder) throws {
186+
let container = try decoder.container(keyedBy: CodingKeys.self)
187+
targetID = try container.decodeIntOrStringIfPresent(forKey: .targetID)
188+
taskSignature = try container.decode(String.self, forKey: .taskSignature)
189+
parentTaskID = try container.decodeIntOrStringIfPresent(forKey: .parentTaskID)
190+
}
191+
}
192+
193+
extension XCBuildMessage.TaskStartedInfo: Decodable, Equatable {
194+
enum CodingKeys: String, CodingKey {
195+
case taskID = "id"
196+
case targetID
197+
case taskSignature = "signature"
198+
case parentTaskID = "parentID"
199+
case ruleInfo
200+
case interestingPath
201+
case commandLineDisplayString
202+
case executionDescription
203+
}
204+
205+
public init(from decoder: Decoder) throws {
206+
let container = try decoder.container(keyedBy: CodingKeys.self)
207+
taskID = try container.decodeIntOrString(forKey: .taskID)
208+
targetID = try container.decodeIntOrStringIfPresent(forKey: .targetID)
209+
taskSignature = try container.decode(String.self, forKey: .taskSignature)
210+
parentTaskID = try container.decodeIntOrStringIfPresent(forKey: .parentTaskID)
211+
ruleInfo = try container.decode(String.self, forKey: .ruleInfo)
212+
interestingPath = try AbsolutePath(validatingOrNilIfEmpty: container.decodeIfPresent(String.self, forKey: .interestingPath))
213+
commandLineDisplayString = try container.decode(String.self, forKey: .commandLineDisplayString)
214+
executionDescription = try container.decode(String.self, forKey: .executionDescription)
215+
}
216+
}
217+
218+
extension XCBuildMessage.TaskOutputInfo: Decodable, Equatable {
219+
enum CodingKeys: String, CodingKey {
220+
case taskID
221+
case data
222+
}
223+
224+
public init(from decoder: Decoder) throws {
225+
let container = try decoder.container(keyedBy: CodingKeys.self)
226+
taskID = try container.decodeIntOrString(forKey: .taskID)
227+
data = try container.decode(String.self, forKey: .data)
228+
}
229+
}
230+
231+
extension XCBuildMessage.TaskCompleteInfo.Result: Decodable, Equatable {}
232+
extension XCBuildMessage.TaskCompleteInfo: Decodable, Equatable {
233+
enum CodingKeys: String, CodingKey {
234+
case taskID = "id"
235+
case result
236+
case signalled
237+
}
238+
239+
public init(from decoder: Decoder) throws {
240+
let container = try decoder.container(keyedBy: CodingKeys.self)
241+
taskID = try container.decodeIntOrString(forKey: .taskID)
242+
result = try container.decode(Result.self, forKey: .result)
243+
signalled = try container.decode(Bool.self, forKey: .signalled)
244+
}
245+
}
246+
247+
extension XCBuildMessage: Decodable, Equatable {
248+
enum CodingKeys: CodingKey {
249+
case kind
250+
}
251+
252+
public init(from decoder: Decoder) throws {
253+
let container = try decoder.container(keyedBy: CodingKeys.self)
254+
let kind = try container.decode(String.self, forKey: .kind)
255+
switch kind {
256+
case "buildStarted":
257+
self = .buildStarted
258+
case "buildDiagnostic":
259+
self = try .buildDiagnostic(BuildDiagnosticInfo(from: decoder))
260+
case "buildCompleted":
261+
self = try .buildCompleted(BuildCompletedInfo(from: decoder))
262+
case "buildOutput":
263+
self = try .buildOutput(BuildOutputInfo(from: decoder))
264+
case "preparationComplete":
265+
self = .preparationComplete
266+
case "didUpdateProgress":
267+
self = try .didUpdateProgress(DidUpdateProgressInfo(from: decoder))
268+
case "targetUpToDate":
269+
self = try .targetUpToDate(TargetUpToDateInfo(from: decoder))
270+
case "targetStarted":
271+
self = try .targetStarted(TargetStartedInfo(from: decoder))
272+
case "targetComplete":
273+
self = try .targetComplete(TargetCompleteInfo(from: decoder))
274+
case "taskUpToDate":
275+
self = try .taskUpToDate(TaskUpToDateInfo(from: decoder))
276+
case "taskStarted":
277+
self = try .taskStarted(TaskStartedInfo(from: decoder))
278+
case "taskDiagnostic":
279+
self = try .taskDiagnostic(TaskDiagnosticInfo(from: decoder))
280+
case "taskOutput":
281+
self = try .taskOutput(TaskOutputInfo(from: decoder))
282+
case "taskComplete":
283+
self = try .taskComplete(TaskCompleteInfo(from: decoder))
284+
case "targetDiagnostic":
285+
self = try .targetDiagnostic(TargetDiagnosticInfo(from: decoder))
286+
default:
287+
throw DecodingError.dataCorruptedError(forKey: .kind, in: container, debugDescription: "invalid kind \(kind)")
288+
}
289+
}
290+
}
291+
292+
fileprivate extension KeyedDecodingContainer {
293+
func decodeBoolOrString(forKey key: Key) throws -> Bool {
294+
do {
295+
return try decode(Bool.self, forKey: key)
296+
} catch {
297+
let string = try decode(String.self, forKey: key)
298+
guard let value = Bool(string) else {
299+
throw DecodingError.dataCorruptedError(forKey: key, in: self, debugDescription: "Could not parse '\(string)' as Bool for key \(key)")
300+
}
301+
return value
302+
}
303+
}
304+
305+
func decodeDoubleOrString(forKey key: Key) throws -> Double {
306+
do {
307+
return try decode(Double.self, forKey: key)
308+
} catch {
309+
let string = try decode(String.self, forKey: key)
310+
guard let value = Double(string) else {
311+
throw DecodingError.dataCorruptedError(forKey: key, in: self, debugDescription: "Could not parse '\(string)' as Double for key \(key)")
312+
}
313+
return value
314+
}
315+
}
316+
317+
func decodeIntOrString(forKey key: Key) throws -> Int {
318+
do {
319+
return try decode(Int.self, forKey: key)
320+
} catch {
321+
let string = try decode(String.self, forKey: key)
322+
guard let value = Int(string) else {
323+
throw DecodingError.dataCorruptedError(forKey: key, in: self, debugDescription: "Could not parse '\(string)' as Int for key \(key)")
324+
}
325+
return value
326+
}
327+
}
328+
329+
func decodeIntOrStringIfPresent(forKey key: Key) throws -> Int? {
330+
do {
331+
return try decodeIfPresent(Int.self, forKey: key)
332+
} catch {
333+
guard let string = try decodeIfPresent(String.self, forKey: key), !string.isEmpty else {
334+
return nil
335+
}
336+
guard let value = Int(string) else {
337+
throw DecodingError.dataCorruptedError(forKey: key, in: self, debugDescription: "Could not parse '\(string)' as Int for key \(key)")
338+
}
339+
return value
340+
}
341+
}
342+
}
343+
344+
fileprivate extension AbsolutePath {
345+
init?(validatingOrNilIfEmpty path: String?) throws {
346+
guard let path = path, !path.isEmpty else {
347+
return nil
348+
}
349+
try self.init(validating: path)
350+
}
351+
}

0 commit comments

Comments
 (0)