Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 21 additions & 6 deletions Sources/XCLogParser/activityparser/ActivityParser.swift
Original file line number Diff line number Diff line change
Expand Up @@ -380,12 +380,27 @@ public class ActivityParser {
}

if className == "IDEFoundation.\(String(describing: IDEActivityLogSectionAttachment.self))" {
let jsonType = IDEActivityLogSectionAttachment.BuildOperationTaskMetrics.self
return try IDEActivityLogSectionAttachment(identifier: try parseAsString(token: iterator.next()),
majorVersion: try parseAsInt(token: iterator.next()),
minorVersion: try parseAsInt(token: iterator.next()),
metrics: try parseAsJson(token: iterator.next(),
type: jsonType))
let identifier = try parseAsString(token: iterator.next())
switch identifier.components(separatedBy: "ActivityLogSectionAttachment.").last {
case .some("TaskMetrics"):
let jsonType = IDEActivityLogSectionAttachment.BuildOperationTaskMetrics.self
return try IDEActivityLogSectionAttachment(identifier: identifier,
majorVersion: try parseAsInt(token: iterator.next()),
minorVersion: try parseAsInt(token: iterator.next()),
metrics: try parseAsJson(token: iterator.next(),
type: jsonType),
backtrace: nil)
case .some("TaskBacktrace"):
let jsonType = IDEActivityLogSectionAttachment.BuildOperationTaskBacktrace.self
return try IDEActivityLogSectionAttachment(identifier: identifier,
majorVersion: try parseAsInt(token: iterator.next()),
minorVersion: try parseAsInt(token: iterator.next()),
metrics: nil,
backtrace: try parseAsJson(token: iterator.next(),
type: jsonType))
default:
throw XCLogParserError.parseError("Unexpected attachment identifier \(identifier)")
}
}
throw XCLogParserError.parseError("Unexpected className found parsing IDEConsoleItem \(className)")
}
Expand Down
101 changes: 100 additions & 1 deletion Sources/XCLogParser/activityparser/IDEActivityModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -658,16 +658,115 @@ public class IDEActivityLogSectionAttachment: Encodable {
public let majorVersion: UInt64
public let minorVersion: UInt64
public let metrics: BuildOperationTaskMetrics?
public let backtrace: BuildOperationTaskBacktrace?

public init(
identifier: String,
majorVersion: UInt64,
minorVersion: UInt64,
metrics: BuildOperationTaskMetrics?
metrics: BuildOperationTaskMetrics?,
backtrace: BuildOperationTaskBacktrace?
) throws {
self.identifier = identifier
self.majorVersion = majorVersion
self.minorVersion = minorVersion
self.metrics = metrics
self.backtrace = backtrace
}

public struct BuildOperationTaskBacktrace: Codable {
public let frames: [BuildOperationTaskBacktraceFrame]

public init(from decoder: any Decoder) throws {
let container = try decoder.singleValueContainer()
self.frames = try container.decode([BuildOperationTaskBacktraceFrame].self)
}

public func encode(to encoder: any Encoder) throws {
var container = encoder.singleValueContainer()
try container.encode(frames)
}
}

public struct BuildOperationTaskBacktraceFrame: Codable {
public let category: BuildOperationTaskBacktraceCategory
public let description: String
}

public enum BuildOperationTaskBacktraceCategory: String, Codable {
case ruleHadInvalidValue
case ruleSignatureChanged
case ruleNeverBuilt
case ruleInputRebuilt
case ruleForced
case dynamicTaskRegistration
case dynamicTaskRequest
case none

public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: BuildOperationTaskBacktraceCategoryCodingKeys.self)

if container.contains(.ruleHadInvalidValue) {
self = .ruleHadInvalidValue
} else if container.contains(.ruleSignatureChanged) {
self = .ruleSignatureChanged
} else if container.contains(.ruleNeverBuilt) {
self = .ruleNeverBuilt
} else if container.contains(.ruleInputRebuilt) {
self = .ruleInputRebuilt
} else if container.contains(.ruleForced) {
self = .ruleForced
} else if container.contains(.dynamicTaskRegistration) {
self = .dynamicTaskRegistration
} else if container.contains(.dynamicTaskRequest) {
self = .dynamicTaskRequest
} else if container.contains(.none) {
self = .none
} else {
throw DecodingError.dataCorrupted(
DecodingError.Context(
codingPath: decoder.codingPath,
debugDescription: "Unknown task backtrace category"
)
)
}
}

public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: BuildOperationTaskBacktraceCategoryCodingKeys.self)
switch self {
case .ruleHadInvalidValue:
try container.encode(EmptyObject(), forKey: .ruleHadInvalidValue)
case .ruleSignatureChanged:
try container.encode(EmptyObject(), forKey: .ruleSignatureChanged)
case .ruleNeverBuilt:
try container.encode(EmptyObject(), forKey: .ruleNeverBuilt)
case .ruleInputRebuilt:
try container.encode(EmptyObject(), forKey: .ruleInputRebuilt)
case .ruleForced:
try container.encode(EmptyObject(), forKey: .ruleForced)
case .dynamicTaskRegistration:
try container.encode(EmptyObject(), forKey: .dynamicTaskRegistration)
case .dynamicTaskRequest:
try container.encode(EmptyObject(), forKey: .dynamicTaskRequest)
case .none:
try container.encode(EmptyObject(), forKey: .none)
}
}
}

private enum BuildOperationTaskBacktraceCategoryCodingKeys: String, CodingKey {
case ruleHadInvalidValue
case ruleSignatureChanged
case ruleNeverBuilt
case ruleInputRebuilt
case ruleForced
case dynamicTaskRegistration
case dynamicTaskRequest
case none
}

private struct EmptyObject: Codable {
// Empty struct for objects with no properties
}
}
2 changes: 1 addition & 1 deletion Sources/XCLogParser/logmanifest/LogManifest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public struct LogManifest {

public init() {}

public func getWithLogOptions(_ logOptions: LogOptions) throws -> [LogManifestEntry] {
public func getWithLogOptions(_ logOptions: LogOptions) throws -> [LogManifestEntry] {
let logFinder = LogFinder()
let logManifestURL = try logFinder.findLogManifestWithLogOptions(logOptions)
let logManifestDictionary = try getDictionaryFromURL(logManifestURL)
Expand Down
12 changes: 10 additions & 2 deletions Tests/XCLogParserTests/ActivityParserTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,13 @@ class ActivityParserTests: XCTestCase {
Token.string("501796C4-6BE4-4F80-9F9D-3269617ECC17"),
Token.string("localizedResultString"),
Token.string("xcbuildSignature"),
Token.list(1),
Token.list(2),
Token.classNameRef("IDEFoundation.IDEActivityLogSectionAttachment"),
Token.string("com.apple.dt.ActivityLogSectionAttachment.TaskBacktrace"),
Token.int(1),
Token.int(0),
// swiftlint:disable:next line_length
Token.json(#"[{"description":"'Planning Swift module ConcurrencyExtras (arm64)' had never run","category":{"ruleNeverBuilt":{}},"identifier":{"storage":{"task":{"_0":[0,80,50,58,116,97,114,103,101,116,45,67,111,110,99,117,114,114,101,110,99,121,69,120,116,114,97,115,45,101,102,52,50,51,48,52,53,57,52,98,102,56,53,50,102,52,51,56,101,102,55,99,51,97,49,51,54,98,50,99,57,48,100,102,56,55,49,56,97,102,50,98,57,100,51,97,97,99,48,100,48,100,99,97,50,50,98,52,99,50,57,99,50,45,58,66,101,116,97,32,68,101,98,117,103,58,51,99,57,97,99,57,53,50,98,52,99,56,49,100,57,99,99,49,55,100,49,97,102,52,55,49,97,48,52,53,101,56]}}},"frameKind":{"genericTask":{}}}]"#),
Token.classNameRef("IDEFoundation.IDEActivityLogSectionAttachment"),
Token.string("com.apple.dt.ActivityLogSectionAttachment.TaskMetrics"),
Token.int(1),
Expand Down Expand Up @@ -339,7 +345,9 @@ class ActivityParserTests: XCTestCase {
XCTAssertEqual("501796C4-6BE4-4F80-9F9D-3269617ECC17", logSection.uniqueIdentifier)
XCTAssertEqual("localizedResultString", logSection.localizedResultString)
XCTAssertEqual("xcbuildSignature", logSection.xcbuildSignature)
XCTAssertEqual(1, logSection.attachments.count)
XCTAssertEqual(2, logSection.attachments.count)
XCTAssertEqual(logSection.attachments[0].backtrace?.frames.first?.category, .ruleNeverBuilt)
XCTAssertEqual(logSection.attachments[1].metrics?.wcDuration, 1)
XCTAssertEqual(0, logSection.unknown)
}

Expand Down