Skip to content
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

Add ability to encode ProjectSpec to JSON #545

Merged
merged 8 commits into from
Apr 22, 2019
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
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## Next Version

#### Added

- Added ability to encode ProjectSpec to JSON [#545](https://github.com/yonaskolb/XcodeGen/pull/545) @ryohey

## 2.5.0

#### Added
Expand Down
13 changes: 13 additions & 0 deletions Sources/ProjectSpec/AggregateTarget.swift
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,19 @@ extension AggregateTarget: NamedJSONDictionaryConvertible {
}
}

extension AggregateTarget: JSONEncodable {
public func toJSONValue() -> Any {
return [
"settings": settings.toJSONValue(),
"targets": targets,
"configFiles": configFiles,
"attributes": attributes,
"buildScripts": buildScripts.map { $0.toJSONValue() },
"scheme": scheme?.toJSONValue()
] as [String: Any?]
}
}

extension AggregateTarget: PathContainer {

static var pathProperties: [PathProperty] {
Expand Down
26 changes: 26 additions & 0 deletions Sources/ProjectSpec/BuildRule.swift
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,29 @@ extension BuildRule: JSONObjectConvertible {
name = jsonDictionary.json(atKeyPath: "name")
}
}

extension BuildRule: JSONEncodable {
public func toJSONValue() -> Any {
var dict: [String: Any?] = [
"outputFiles": outputFiles,
"outputFilesCompilerFlags": outputFilesCompilerFlags,
"name": name
]

switch fileType {
case .pattern(let string):
dict["filePattern"] = string
case .type(let string):
dict["fileType"] = string
}

switch action {
case .compilerSpec(let string):
dict["compilerSpec"] = string
case .script(let string):
dict["script"] = string
}

return dict
}
}
36 changes: 32 additions & 4 deletions Sources/ProjectSpec/BuildScript.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import Foundation
import JSONUtilities

public struct BuildScript: Equatable {
public static let runOnlyWhenInstallingDefault = false
public static let showEnvVarsDefault = true

public var script: ScriptType
public var name: String?
Expand All @@ -26,8 +28,8 @@ public struct BuildScript: Equatable {
inputFileLists: [String] = [],
outputFileLists: [String] = [],
shell: String? = nil,
runOnlyWhenInstalling: Bool = false,
showEnvVars: Bool = true
runOnlyWhenInstalling: Bool = runOnlyWhenInstallingDefault,
showEnvVars: Bool = showEnvVarsDefault
) {
self.script = script
self.name = name
Expand Down Expand Up @@ -57,8 +59,34 @@ extension BuildScript: JSONObjectConvertible {
script = .path(path)
}
shell = jsonDictionary.json(atKeyPath: "shell")
runOnlyWhenInstalling = jsonDictionary.json(atKeyPath: "runOnlyWhenInstalling") ?? false
showEnvVars = jsonDictionary.json(atKeyPath: "showEnvVars") ?? true
runOnlyWhenInstalling = jsonDictionary.json(atKeyPath: "runOnlyWhenInstalling") ?? BuildScript.runOnlyWhenInstallingDefault
showEnvVars = jsonDictionary.json(atKeyPath: "showEnvVars") ?? BuildScript.showEnvVarsDefault
}
}
extension BuildScript: JSONEncodable {
public func toJSONValue() -> Any {
var dict: [String: Any?] = [
"inputFiles": inputFiles,
"inputFileLists": inputFileLists,
"outputFiles": outputFiles,
"outputFileLists": outputFileLists,
"runOnlyWhenInstalling": runOnlyWhenInstalling,
"name": name,
"shell": shell
]

if showEnvVars != BuildScript.showEnvVarsDefault {
dict["showEnvVars"] = showEnvVars
}

switch script {
case .path(let string):
dict["path"] = string
case .script(let string):
dict["script"] = string
}

return dict
}
}

Expand Down
49 changes: 44 additions & 5 deletions Sources/ProjectSpec/Dependency.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,27 @@ import Foundation
import JSONUtilities

public struct Dependency: Equatable {
public static let removeHeadersDefault = true
public static let implicitDefault = false
public static let weakLinkDefault = false

public var type: DependencyType
public var reference: String
public var embed: Bool?
public var codeSign: Bool?
public var removeHeaders: Bool = true
public var removeHeaders: Bool = removeHeadersDefault
public var link: Bool?
public var implicit: Bool = false
public var weakLink: Bool = false
public var implicit: Bool = implicitDefault
public var weakLink: Bool = weakLinkDefault

public init(
type: DependencyType,
reference: String,
embed: Bool? = nil,
codeSign: Bool? = nil,
link: Bool? = nil,
implicit: Bool = false,
weakLink: Bool = false
implicit: Bool = implicitDefault,
weakLink: Bool = weakLinkDefault
) {
self.type = type
self.reference = reference
Expand Down Expand Up @@ -81,6 +84,42 @@ extension Dependency: JSONObjectConvertible {
}
}

extension Dependency: JSONEncodable {
public func toJSONValue() -> Any {
var dict: [String: Any?] = [
"embed": embed,
"codeSign": codeSign,
"link": link
]

if removeHeaders != Dependency.removeHeadersDefault {
dict["removeHeaders"] = removeHeaders
}
if implicit != Dependency.implicitDefault {
dict["implicit"] = implicit
}
if weakLink != Dependency.weakLinkDefault {
dict["weak"] = weakLink
}

switch type {
case .target:
dict["target"] = reference
case .framework:
dict["framework"] = reference
case .carthage(let findFrameworks):
dict["carthage"] = reference
if let findFrameworks = findFrameworks {
dict["findFrameworks"] = findFrameworks
}
case .sdk:
dict["sdk"] = reference
}

return dict
}
}

extension Dependency: PathContainer {

static var pathProperties: [PathProperty] {
Expand Down
11 changes: 11 additions & 0 deletions Sources/ProjectSpec/DeploymentTarget.swift
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,14 @@ extension DeploymentTarget: JSONObjectConvertible {
macOS = try parseVersion("macOS")
}
}

extension DeploymentTarget: JSONEncodable {
public func toJSONValue() -> Any {
return [
"iOS": iOS?.string,
"tvOS": tvOS?.string,
"watchOS": watchOS?.string,
"macOS": macOS?.string,
]
}
}
7 changes: 7 additions & 0 deletions Sources/ProjectSpec/Encoding.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import Foundation
import JSONUtilities

public protocol JSONEncodable {
// returns JSONDictionary or JSONArray or JSONRawType or nil
func toJSONValue() -> Any
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure we need all these protocols as they aren't really used on their own. I think all the functions could just be the func toJSONValue() -> Any. Maybe just the top level spec would have a function that returned a dictionary.

}
9 changes: 9 additions & 0 deletions Sources/ProjectSpec/Plist.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,15 @@ extension Plist: JSONObjectConvertible {
}
}

extension Plist: JSONEncodable {
public func toJSONValue() -> Any {
return [
"path": path,
"properties": properties
]
}
}

extension Plist: PathContainer {

static var pathProperties: [PathProperty] {
Expand Down
28 changes: 28 additions & 0 deletions Sources/ProjectSpec/Project.swift
Original file line number Diff line number Diff line change
Expand Up @@ -230,3 +230,31 @@ extension BuildSettingsContainer {
return configFiles.values.map { Path($0) }
}
}

extension Project: JSONEncodable {
public func toJSONValue() -> Any {
return toJSONDictionary()
}

public func toJSONDictionary() -> JSONDictionary {
let targetPairs = targets.map { ($0.name, $0.toJSONValue()) }
let configsPairs = configs.map { ($0.name, $0.type?.rawValue) }
let aggregateTargetsPairs = aggregateTargets.map { ($0.name, $0.toJSONValue()) }
let schemesPairs = schemes.map { ($0.name, $0.toJSONValue()) }

return [
"name": name,
"options": options.toJSONValue(),
"settings": settings.toJSONValue(),
"fileGroups": fileGroups,
"configFiles": configFiles,
"include": include,
"attributes": attributes,
"targets": Dictionary(uniqueKeysWithValues: targetPairs),
"configs": Dictionary(uniqueKeysWithValues: configsPairs),
"aggregateTargets": Dictionary(uniqueKeysWithValues: aggregateTargetsPairs),
"schemes": Dictionary(uniqueKeysWithValues: schemesPairs),
"settingGroups": settingGroups.mapValues { $0.toJSONValue() }
]
}
}
Loading