-
Notifications
You must be signed in to change notification settings - Fork 35
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Parse dump-pif
result and reduce XCBuildSupport dependency
#183
base: main
Are you sure you want to change the base?
Changes from all commits
865d4c6
949481a
f584cf3
62e795a
4381b35
7ffcef9
7e03709
39ffcdb
952c75e
8677de9
c3f0bfb
05298a7
d04f901
abc835a
8231a99
5ea4586
0d46ad2
5a4bb8f
af89aa9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
import Foundation | ||
import SwiftyJSON | ||
|
||
/// A build configuration for a target. | ||
package struct BuildConfiguration: Codable, Equatable, JSONConvertible { | ||
Comment on lines
+4
to
+5
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you please add the reference to its doc comments? |
||
package enum MacroExpressionValue: Sendable, Codable, Equatable { | ||
case bool(Bool) | ||
case string(String) | ||
case stringList([String]) | ||
} | ||
|
||
package struct ImpartedBuildProperties: Sendable, Codable, Equatable { | ||
package var buildSettings: [String: MacroExpressionValue] | ||
|
||
package init(buildSettings: [String: MacroExpressionValue]) { | ||
self.buildSettings = buildSettings | ||
} | ||
} | ||
|
||
package var name: String | ||
package var buildSettings: [String: MacroExpressionValue] | ||
package var baseConfigurationFileReferenceGUID: String? | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is this? |
||
package var impartedBuildProperties: ImpartedBuildProperties | ||
} | ||
|
||
extension BuildConfiguration.MacroExpressionValue { | ||
package enum DecodingError: Error { | ||
case unknownBuildSettingsValue | ||
} | ||
|
||
package func encode(to encoder: any Encoder) throws { | ||
var container = encoder.singleValueContainer() | ||
switch self { | ||
case .bool(let value): | ||
try container.encode(value ? "YES" : "NO") | ||
case .string(let value): | ||
try container.encode(value) | ||
case .stringList(let value): | ||
try container.encode(value) | ||
} | ||
} | ||
|
||
package init(from decoder: any Decoder) throws { | ||
let container = try decoder.singleValueContainer() | ||
|
||
if let stringValue = try? container.decode(String.self) { | ||
if stringValue == "YES" { | ||
self = .bool(true) | ||
} else if stringValue == "NO" { | ||
self = .bool(false) | ||
} else { | ||
self = .string(stringValue) | ||
} | ||
} else if let arrayValue = try? container.decode([String].self) { | ||
self = .stringList(arrayValue) | ||
} else { | ||
throw DecodingError.unknownBuildSettingsValue | ||
} | ||
} | ||
} | ||
|
||
extension BuildConfiguration.MacroExpressionValue: ExpressibleByStringLiteral { | ||
package init(stringLiteral value: String) { | ||
self = .string(value) | ||
} | ||
} | ||
|
||
extension BuildConfiguration.MacroExpressionValue: ExpressibleByBooleanLiteral { | ||
package init(booleanLiteral value: Bool) { | ||
self = .bool(value) | ||
} | ||
} | ||
|
||
extension BuildConfiguration.MacroExpressionValue: ExpressibleByArrayLiteral { | ||
package init(arrayLiteral elements: String...) { | ||
self = .stringList(elements) | ||
} | ||
} | ||
|
||
extension BuildConfiguration.MacroExpressionValue? { | ||
package mutating func append(_ appendingValues: [String]) { | ||
self = .stringList(self.values + appendingValues) | ||
} | ||
|
||
package mutating func append(_ appendingValue: String) { | ||
append([appendingValue]) | ||
} | ||
|
||
private var values: [String] { | ||
switch self { | ||
case .bool(let value): | ||
return [value ? "YES" : "NO"] | ||
case .string(let value): | ||
return [value] | ||
case .stringList(let value): | ||
return value | ||
case .none: | ||
return ["$(inherited)"] | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import Foundation | ||
import SwiftyJSON | ||
|
||
package protocol JSONConvertible: Codable { } | ||
|
||
extension JSONConvertible { | ||
init(from json: JSON) throws { | ||
let decoder = JSONDecoder() | ||
let data = try json.rawData() | ||
self = try decoder.decode(Self.self, from: data) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,50 @@ | ||||||||||||||
import Foundation | ||||||||||||||
import SwiftyJSON | ||||||||||||||
|
||||||||||||||
/// Manipulates PIF JSON data | ||||||||||||||
package class PIFManipulator { | ||||||||||||||
private var topLevelObject: JSON | ||||||||||||||
|
||||||||||||||
/// Initialize PIFManipulator with JSON data | ||||||||||||||
/// - Parameters jsonData: JSON data | ||||||||||||||
package init(jsonData: Data) throws { | ||||||||||||||
self.topLevelObject = try JSON(data: jsonData) | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
/// Update targets in PIF JSON data | ||||||||||||||
/// - Parameters modifier: Closure to modify Target | ||||||||||||||
package func updateTargets(_ modifier: (inout Target) -> Void) { | ||||||||||||||
for index in 0..<topLevelObject.arrayValue.count { | ||||||||||||||
guard topLevelObject[index]["type"].stringValue == "target", var target = try? Target(from: topLevelObject[index]["contents"]) else { | ||||||||||||||
continue | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
modifier(&target) | ||||||||||||||
apply(target, to: &topLevelObject[index]) | ||||||||||||||
} | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
/// Dump manipulating JSON data | ||||||||||||||
/// - Returns: JSON data | ||||||||||||||
package func dump() throws -> Data { | ||||||||||||||
try topLevelObject.rawData(options: [.prettyPrinted]) | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
/// Apply target to JSON object | ||||||||||||||
/// Currently, Target is a subset of an actual PIF target. So, we have to apply only the properties that are present in the Target. | ||||||||||||||
/// - Parameters target: Target to apply | ||||||||||||||
/// - Parameters pifObject: JSON object to apply the target to | ||||||||||||||
private func apply(_ target: Target, to pifObject: inout JSON) { | ||||||||||||||
pifObject["contents"]["name"].string = target.name | ||||||||||||||
pifObject["contents"]["productTypeIdentifier"].string = target.productType?.rawValue | ||||||||||||||
pifObject["contents"]["buildConfigurations"].arrayObject = target.buildConfigurations.compactMap { try? $0.toJSON() } | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
Comment on lines
+40
to
+42
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would be better to reuse a single JSONEncoder I think.
Suggested change
|
||||||||||||||
} | ||||||||||||||
|
||||||||||||||
extension BuildConfiguration { | ||||||||||||||
fileprivate func toJSON(using encoder: JSONEncoder = JSONEncoder()) throws -> JSON { | ||||||||||||||
let data = try encoder.encode(self) | ||||||||||||||
return try JSON(data: data) | ||||||||||||||
} | ||||||||||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import Foundation | ||
import SwiftyJSON | ||
|
||
package struct Target: Sendable, Codable, Equatable, JSONConvertible { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you please add the reference to its doc comments? |
||
package enum ProductType: String, Codable, Equatable, Sendable { | ||
case application = "com.apple.product-type.application" | ||
case staticArchive = "com.apple.product-type.library.static" | ||
case objectFile = "com.apple.product-type.objfile" | ||
case dynamicLibrary = "com.apple.product-type.library.dynamic" | ||
case framework = "com.apple.product-type.framework" | ||
case executable = "com.apple.product-type.tool" | ||
case unitTest = "com.apple.product-type.bundle.unit-test" | ||
case bundle = "com.apple.product-type.bundle" | ||
case packageProduct = "packageProduct" | ||
} | ||
|
||
package var name: String | ||
package var buildConfigurations: [BuildConfiguration] | ||
package var productType: ProductType? | ||
|
||
enum CodingKeys: String, CodingKey { | ||
case name | ||
case buildConfigurations | ||
case productType = "productTypeIdentifier" | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.