Skip to content

Commit fdde347

Browse files
authored
Merge pull request #204 from rabc/handle_json_format
Update to handle the new JSON format introduced in Xcode 15.3
2 parents e536e30 + 64a5516 commit fdde347

12 files changed

+152
-2
lines changed

Sources/XCLogParser/activityparser/ActivityParser.swift

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ public class ActivityParser {
110110
uniqueIdentifier: try parseAsString(token: iterator.next()),
111111
localizedResultString: try parseAsString(token: iterator.next()),
112112
xcbuildSignature: try parseAsString(token: iterator.next()),
113+
attachments: try parseIDEActivityLogSectionAttachments(iterator: &iterator),
113114
unknown: isCommandLineLog ? Int(try parseAsInt(token: iterator.next())) : 0)
114115
}
115116

@@ -133,6 +134,7 @@ public class ActivityParser {
133134
uniqueIdentifier: try parseAsString(token: iterator.next()),
134135
localizedResultString: try parseAsString(token: iterator.next()),
135136
xcbuildSignature: try parseAsString(token: iterator.next()),
137+
attachments: try parseIDEActivityLogSectionAttachments(iterator: &iterator),
136138
unknown: isCommandLineLog ? Int(try parseAsInt(token: iterator.next())) : 0,
137139
testsPassedString: try parseAsString(token: iterator.next()),
138140
durationString: try parseAsString(token: iterator.next()),
@@ -163,6 +165,8 @@ public class ActivityParser {
163165
localizedResultString: try parseAsString(token: iterator.next()),
164166
xcbuildSignature: try parseAsString(token: iterator.next()),
165167
// swiftlint:disable:next line_length
168+
attachments: try parseIDEActivityLogSectionAttachments(iterator: &iterator),
169+
// swiftlint:disable:next line_length
166170
unknown: isCommandLineLog ? Int(try parseAsInt(token: iterator.next())) : 0,
167171
logConsoleItems: try parseIDEConsoleItems(iterator: &iterator)
168172
)
@@ -361,6 +365,25 @@ public class ActivityParser {
361365
throw XCLogParserError.parseError("Unexpected className found parsing IDEActivityLogMessage \(className)")
362366
}
363367

368+
private func parseLogSectionAttachment(iterator: inout IndexingIterator<[Token]>)
369+
throws -> IDEActivityLogSectionAttachment {
370+
let classRefToken = try getClassRefToken(iterator: &iterator)
371+
guard case Token.classNameRef(let className) = classRefToken else {
372+
throw XCLogParserError.parseError("Unexpected token found parsing " +
373+
"IDEActivityLogSectionAttachment \(classRefToken)")
374+
}
375+
376+
if className == "IDEFoundation.\(String(describing: IDEActivityLogSectionAttachment.self))" {
377+
let jsonType = IDEActivityLogSectionAttachment.BuildOperationTaskMetrics.self
378+
return try IDEActivityLogSectionAttachment(identifier: try parseAsString(token: iterator.next()),
379+
majorVersion: try parseAsInt(token: iterator.next()),
380+
minorVersion: try parseAsInt(token: iterator.next()),
381+
metrics: try parseAsJson(token: iterator.next(),
382+
type: jsonType))
383+
}
384+
throw XCLogParserError.parseError("Unexpected className found parsing IDEConsoleItem \(className)")
385+
}
386+
364387
private func parseLogSection(iterator: inout IndexingIterator<[Token]>)
365388
throws -> IDEActivityLogSection {
366389
var classRefToken = try getClassRefToken(iterator: &iterator)
@@ -433,6 +456,27 @@ public class ActivityParser {
433456
}
434457
}
435458

459+
private func parseIDEActivityLogSectionAttachments(iterator: inout IndexingIterator<[Token]>)
460+
throws -> [IDEActivityLogSectionAttachment] {
461+
guard let listToken = iterator.next() else {
462+
throw XCLogParserError.parseError("Unexpected EOF parsing array of IDEActivityLogSectionAttachment")
463+
}
464+
switch listToken {
465+
case .null:
466+
return []
467+
case .list(let count):
468+
var sections = [IDEActivityLogSectionAttachment]()
469+
for _ in 0..<count {
470+
let section = try parseLogSectionAttachment(iterator: &iterator)
471+
sections.append(section)
472+
}
473+
return sections
474+
default:
475+
throw XCLogParserError.parseError("Unexpected token parsing array of " +
476+
"IDEActivityLogSectionAttachment: \(listToken)")
477+
}
478+
}
479+
436480
private func parseIDEConsoleItem(iterator: inout IndexingIterator<[Token]>)
437481
throws -> IDEConsoleItem? {
438482
let classRefToken = try getClassRefToken(iterator: &iterator)
@@ -555,6 +599,23 @@ public class ActivityParser {
555599
}
556600
}
557601

602+
private func parseAsJson<T: Decodable>(token: Token?, type: T.Type) throws -> T? {
603+
guard let token = token else {
604+
throw XCLogParserError.parseError("Unexpected EOF parsing JSON String")
605+
}
606+
switch token {
607+
case .json(let string):
608+
guard let data = string.data(using: .utf8) else {
609+
throw XCLogParserError.parseError("Unexpected JSON string \(string)")
610+
}
611+
return try JSONDecoder().decode(type, from: data)
612+
case .null:
613+
return nil
614+
default:
615+
throw XCLogParserError.parseError("Unexpected token parsing JSON String: \(token)")
616+
}
617+
}
618+
558619
private func parseAsInt(token: Token?) throws -> UInt64 {
559620
guard let token = token else {
560621
throw XCLogParserError.parseError("Unexpected EOF parsing Int")

Sources/XCLogParser/activityparser/IDEActivityModel.swift

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ public class IDEActivityLogSection: Encodable {
4949
public let uniqueIdentifier: String
5050
public let localizedResultString: String
5151
public let xcbuildSignature: String
52+
public let attachments: [IDEActivityLogSectionAttachment]
5253
public let unknown: Int
5354

5455
public init(sectionType: Int8,
@@ -69,6 +70,7 @@ public class IDEActivityLogSection: Encodable {
6970
uniqueIdentifier: String,
7071
localizedResultString: String,
7172
xcbuildSignature: String,
73+
attachments: [IDEActivityLogSectionAttachment],
7274
unknown: Int) {
7375
self.sectionType = sectionType
7476
self.domainType = domainType
@@ -88,6 +90,7 @@ public class IDEActivityLogSection: Encodable {
8890
self.uniqueIdentifier = uniqueIdentifier
8991
self.localizedResultString = localizedResultString
9092
self.xcbuildSignature = xcbuildSignature
93+
self.attachments = attachments
9194
self.unknown = unknown
9295
}
9396

@@ -119,6 +122,7 @@ public class IDEActivityLogUnitTestSection: IDEActivityLogSection {
119122
uniqueIdentifier: String,
120123
localizedResultString: String,
121124
xcbuildSignature: String,
125+
attachments: [IDEActivityLogSectionAttachment],
122126
unknown: Int,
123127
testsPassedString: String,
124128
durationString: String,
@@ -151,6 +155,7 @@ public class IDEActivityLogUnitTestSection: IDEActivityLogSection {
151155
uniqueIdentifier: uniqueIdentifier,
152156
localizedResultString: localizedResultString,
153157
xcbuildSignature: xcbuildSignature,
158+
attachments: attachments,
154159
unknown: unknown)
155160
}
156161

@@ -421,6 +426,7 @@ public class DBGConsoleLog: IDEActivityLogSection {
421426
uniqueIdentifier: String,
422427
localizedResultString: String,
423428
xcbuildSignature: String,
429+
attachments: [IDEActivityLogSectionAttachment],
424430
unknown: Int,
425431
logConsoleItems: [IDEConsoleItem]) {
426432
self.logConsoleItems = logConsoleItems
@@ -442,6 +448,7 @@ public class DBGConsoleLog: IDEActivityLogSection {
442448
uniqueIdentifier: uniqueIdentifier,
443449
localizedResultString: localizedResultString,
444450
xcbuildSignature: xcbuildSignature,
451+
attachments: attachments,
445452
unknown: unknown)
446453
}
447454

@@ -635,3 +642,32 @@ public class DVTMemberDocumentLocation: DVTDocumentLocation, Equatable {
635642
}
636643

637644
}
645+
646+
// MARK: Added in Xcode 15.3
647+
648+
public class IDEActivityLogSectionAttachment: Encodable {
649+
public struct BuildOperationTaskMetrics: Codable {
650+
public let utime: UInt64
651+
public let stime: UInt64
652+
public let maxRSS: UInt64
653+
public let wcStartTime: UInt64
654+
public let wcDuration: UInt64
655+
}
656+
657+
public let identifier: String
658+
public let majorVersion: UInt64
659+
public let minorVersion: UInt64
660+
public let metrics: BuildOperationTaskMetrics?
661+
662+
public init(
663+
identifier: String,
664+
majorVersion: UInt64,
665+
minorVersion: UInt64,
666+
metrics: BuildOperationTaskMetrics?
667+
) throws {
668+
self.identifier = identifier
669+
self.majorVersion = majorVersion
670+
self.minorVersion = minorVersion
671+
self.metrics = metrics
672+
}
673+
}

Sources/XCLogParser/lexer/Lexer.swift

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,11 @@ public final class Lexer {
163163
return .null
164164
case .list:
165165
return handleListTokenTypeCase(payload: payload)
166+
case .json:
167+
return handleJSONTokenTypeCase(scanner: scanner,
168+
payload: payload,
169+
redacted: redacted,
170+
withoutBuildSpecificInformation: withoutBuildSpecificInformation)
166171
}
167172
}
168173

@@ -213,6 +218,20 @@ public final class Lexer {
213218
return .string(content)
214219
}
215220

221+
private func handleJSONTokenTypeCase(scanner: Scanner,
222+
payload: String,
223+
redacted: Bool,
224+
withoutBuildSpecificInformation: Bool) -> Token? {
225+
guard let content = scanString(length: payload,
226+
scanner: scanner,
227+
redacted: redacted,
228+
withoutBuildSpecificInformation: withoutBuildSpecificInformation) else {
229+
print("error parsing string")
230+
return nil
231+
}
232+
return .json(content)
233+
}
234+
216235
private func handleDoubleTokenTypeCase(payload: String) -> Token? {
217236
guard let double = hexToInt(payload) else {
218237
print("error parsing double")

Sources/XCLogParser/lexer/LexerModel.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ public enum TokenType: String, CaseIterable {
2727
case double = "^"
2828
case null = "-"
2929
case list = "("
30+
case json = "*"
3031

3132
static func all() -> String {
3233
return TokenType.allCases.reduce(String()) {
@@ -43,6 +44,7 @@ public enum Token: CustomDebugStringConvertible, Equatable {
4344
case double(Double)
4445
case null
4546
case list(Int)
47+
case json(String)
4648
}
4749

4850
extension Token {
@@ -62,6 +64,8 @@ extension Token {
6264
return "[type: nil]"
6365
case .list(let count):
6466
return "[type: list, count: \(count)]"
67+
case .json(let json):
68+
return "[type: json, value: \(json)]"
6569
}
6670
}
6771
}

Sources/XCLogParser/parser/IDEActivityLogSection+Builders.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ extension IDEActivityLogSection {
4040
uniqueIdentifier: self.uniqueIdentifier,
4141
localizedResultString: self.localizedResultString,
4242
xcbuildSignature: self.xcbuildSignature,
43+
attachments: self.attachments,
4344
unknown: self.unknown)
4445
}
4546

Sources/XCLogParser/parser/IDEActivityLogSection+Parsing.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ extension IDEActivityLogSection {
156156
uniqueIdentifier: "",
157157
localizedResultString: "",
158158
xcbuildSignature: "",
159+
attachments: section.attachments,
159160
unknown: 0)
160161
}
161162

Tests/XCLogParserTests/ActivityParserTests.swift

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,12 @@ class ActivityParserTests: XCTestCase {
9797
Token.string("501796C4-6BE4-4F80-9F9D-3269617ECC17"),
9898
Token.string("localizedResultString"),
9999
Token.string("xcbuildSignature"),
100+
Token.list(1),
101+
Token.classNameRef("IDEFoundation.IDEActivityLogSectionAttachment"),
102+
Token.string("com.apple.dt.ActivityLogSectionAttachment.TaskMetrics"),
103+
Token.int(1),
104+
Token.int(0),
105+
Token.json("{\"wcStartTime\":1,\"maxRSS\":1,\"utime\":1,\"wcDuration\":1,\"stime\":1}"),
100106
Token.int(0)
101107
]
102108
return startTokens + logMessageTokens + endTokens
@@ -129,7 +135,13 @@ class ActivityParserTests: XCTestCase {
129135
Token.string("79D9C1DE-F736-4743-A7C6-B08ED42A1DFE"),
130136
Token.null,
131137
Token.null,
132-
Token.list(1)
138+
Token.list(1),
139+
Token.classNameRef("IDEFoundation.IDEActivityLogSectionAttachment"),
140+
Token.string("com.apple.dt.ActivityLogSectionAttachment.TaskMetrics"),
141+
Token.int(1),
142+
Token.int(0),
143+
Token.json("{\"wcStartTime\":1,\"maxRSS\":1,\"utime\":1,\"wcDuration\":1,\"stime\":1}"),
144+
Token.list(1),
133145
]
134146
return startTokens + IDEConsoleItemTokens
135147
}()

Tests/XCLogParserTests/ClangCompilerParserTests.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ class ClangCompilerParserTests: XCTestCase {
9595
uniqueIdentifier: "",
9696
localizedResultString: "",
9797
xcbuildSignature: "",
98+
attachments: [],
9899
unknown: 0)
99100
}
100101
}

Tests/XCLogParserTests/LogManifestTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ class LogManifestTests: XCTestCase {
2828
<plist version="1.0">
2929
<dict>
3030
<key>logFormatVersion</key>
31-
<integer>10</integer>
31+
<integer>11</integer>
3232
<key>logs</key>
3333
<dict>
3434
<key>E8557234-04E4-40E7-A6D6-920AC64BCF21</key>

Tests/XCLogParserTests/ParserTests.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ class ParserTests: XCTestCase {
6464
uniqueIdentifier: uniqueIdentifier,
6565
localizedResultString: "",
6666
xcbuildSignature: "",
67+
attachments: [],
6768
unknown: 0)
6869
let fakeActivityLog = IDEActivityLog(version: 10, mainSection: fakeMainSection)
6970
let buildStep = try parser.parse(activityLog: fakeActivityLog)
@@ -260,6 +261,7 @@ note: use 'updatedDoSomething' instead\r doSomething()\r ^~~~~~~~~~~\r
260261
uniqueIdentifier: "ABC",
261262
localizedResultString: "",
262263
xcbuildSignature: "",
264+
attachments: [],
263265
unknown: 0)
264266

265267
let parsedTarget = fakeSection.getTargetFromCommand()
@@ -310,6 +312,7 @@ note: use 'updatedDoSomething' instead\r doSomething()\r ^~~~~~~~~~~\r
310312
uniqueIdentifier: "uniqueIdentifier",
311313
localizedResultString: "",
312314
xcbuildSignature: "",
315+
attachments: [],
313316
unknown: 0)
314317
return IDEActivityLog(version: 10, mainSection: fakeMainStep)
315318
}
@@ -555,6 +558,7 @@ CompileSwift normal x86_64 (in target 'Alamofire' from project 'Pods')
555558
uniqueIdentifier: "uniqueIdentifier",
556559
localizedResultString: "",
557560
xcbuildSignature: "",
561+
attachments: [],
558562
unknown: 0)
559563
}()
560564
}

0 commit comments

Comments
 (0)