Skip to content

Commit 5c364e7

Browse files
committed
Working on property list serialization in OpenStep format.
1 parent 2c17859 commit 5c364e7

File tree

7 files changed

+623
-123
lines changed

7 files changed

+623
-123
lines changed

Example/Example.xcodeproj/project.pbxproj

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010
E22195B21B7C6EDA00F58D3F /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = E22195B11B7C6EDA00F58D3F /* main.swift */; };
1111
E262D4431B7E20DB0057CCEE /* project.pbxproj in CopyFiles */ = {isa = PBXBuildFile; fileRef = E262D4421B7E20CF0057CCEE /* project.pbxproj */; };
1212
E262D4451B7E21190057CCEE /* XCProjectFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = E262D4441B7E21190057CCEE /* XCProjectFile.swift */; };
13+
E292B9C71B9236D900D75DE2 /* Serialization.swift in Sources */ = {isa = PBXBuildFile; fileRef = E292B9C61B9236D900D75DE2 /* Serialization.swift */; settings = {ASSET_TAGS = (); }; };
14+
E292B9CE1B932F3200D75DE2 /* Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = E292B9CC1B932F3200D75DE2 /* Extensions.swift */; settings = {ASSET_TAGS = (); }; };
15+
E292B9CF1B932F3200D75DE2 /* PBXObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = E292B9CD1B932F3200D75DE2 /* PBXObject.swift */; settings = {ASSET_TAGS = (); }; };
1316
/* End PBXBuildFile section */
1417

1518
/* Begin PBXCopyFilesBuildPhase section */
@@ -30,6 +33,9 @@
3033
E22195B11B7C6EDA00F58D3F /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = "<group>"; };
3134
E262D4421B7E20CF0057CCEE /* project.pbxproj */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.pbxproject; path = project.pbxproj; sourceTree = "<group>"; };
3235
E262D4441B7E21190057CCEE /* XCProjectFile.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = XCProjectFile.swift; path = ../Xcode/Xcode/XCProjectFile.swift; sourceTree = "<group>"; };
36+
E292B9C61B9236D900D75DE2 /* Serialization.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Serialization.swift; path = ../Xcode/Xcode/Serialization.swift; sourceTree = "<group>"; };
37+
E292B9CC1B932F3200D75DE2 /* Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Extensions.swift; path = ../Xcode/Xcode/Extensions.swift; sourceTree = "<group>"; };
38+
E292B9CD1B932F3200D75DE2 /* PBXObject.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = PBXObject.swift; path = ../Xcode/Xcode/PBXObject.swift; sourceTree = "<group>"; };
3339
/* End PBXFileReference section */
3440

3541
/* Begin PBXFrameworksBuildPhase section */
@@ -80,6 +86,9 @@
8086
E262D4411B7E20AA0057CCEE /* Xcode.swift */ = {
8187
isa = PBXGroup;
8288
children = (
89+
E292B9CC1B932F3200D75DE2 /* Extensions.swift */,
90+
E292B9CD1B932F3200D75DE2 /* PBXObject.swift */,
91+
E292B9C61B9236D900D75DE2 /* Serialization.swift */,
8392
E262D4441B7E21190057CCEE /* XCProjectFile.swift */,
8493
);
8594
name = Xcode.swift;
@@ -142,8 +151,11 @@
142151
isa = PBXSourcesBuildPhase;
143152
buildActionMask = 2147483647;
144153
files = (
154+
E292B9CF1B932F3200D75DE2 /* PBXObject.swift in Sources */,
145155
E262D4451B7E21190057CCEE /* XCProjectFile.swift in Sources */,
156+
E292B9C71B9236D900D75DE2 /* Serialization.swift in Sources */,
146157
E22195B21B7C6EDA00F58D3F /* main.swift in Sources */,
158+
E292B9CE1B932F3200D75DE2 /* Extensions.swift in Sources */,
147159
);
148160
runOnlyForDeploymentPostprocessing = 0;
149161
};

Example/Example/main.swift

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,12 @@ import Foundation
1212
let xcodeproj = "Test.xcodeproj"
1313

1414

15-
// Parse JSON to XCProjectFile object
15+
// Load from a xcodeproj
1616
let proj = try! XCProjectFile(xcodeprojPath: xcodeproj)
1717

18+
// Write out a new pbxproj file
19+
try! proj.writeToXcodeproj("/Users/tom/Projects/Xcode.swift/Example/" + xcodeproj)
20+
1821
// Print paths for all files in Resources build phases
1922
for target in proj.project.targets {
2023
for resourcesBuildPhase in target.buildPhases.ofType(PBXResourcesBuildPhase.self) {
@@ -32,3 +35,13 @@ for target in proj.project.targets {
3235
}
3336
}
3437

38+
// Print shells
39+
for target in proj.project.targets {
40+
for buildPhase in target.buildPhases {
41+
print(buildPhase)
42+
if let shellScriptPhase = buildPhase as? PBXShellScriptBuildPhase {
43+
print(shellScriptPhase.shellScript)
44+
}
45+
}
46+
}
47+

Xcode/Xcode.xcodeproj/project.pbxproj

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@
1111
E21D91A61B7B1A5D00FD0374 /* Xcode.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E21D919A1B7B1A5D00FD0374 /* Xcode.framework */; };
1212
E21D91AD1B7B1A5D00FD0374 /* XcodeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E21D91AC1B7B1A5D00FD0374 /* XcodeTests.swift */; };
1313
E21D91B71B7B1A9000FD0374 /* XCProjectFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = E21D91B61B7B1A9000FD0374 /* XCProjectFile.swift */; };
14-
E28D3FDA1B7B1E00006BA061 /* XCProjectFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = E21D91B61B7B1A9000FD0374 /* XCProjectFile.swift */; };
14+
E292B9C51B9236B500D75DE2 /* Serialization.swift in Sources */ = {isa = PBXBuildFile; fileRef = E292B9C41B9236B500D75DE2 /* Serialization.swift */; settings = {ASSET_TAGS = (); }; };
15+
E292B9C91B92380300D75DE2 /* Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = E292B9C81B92380300D75DE2 /* Extensions.swift */; settings = {ASSET_TAGS = (); }; };
16+
E292B9CB1B92384B00D75DE2 /* PBXObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = E292B9CA1B92384B00D75DE2 /* PBXObject.swift */; settings = {ASSET_TAGS = (); }; };
1517
/* End PBXBuildFile section */
1618

1719
/* Begin PBXContainerItemProxy section */
@@ -32,6 +34,9 @@
3234
E21D91AB1B7B1A5D00FD0374 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
3335
E21D91AC1B7B1A5D00FD0374 /* XcodeTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XcodeTests.swift; sourceTree = "<group>"; };
3436
E21D91B61B7B1A9000FD0374 /* XCProjectFile.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = XCProjectFile.swift; sourceTree = "<group>"; };
37+
E292B9C41B9236B500D75DE2 /* Serialization.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Serialization.swift; sourceTree = "<group>"; };
38+
E292B9C81B92380300D75DE2 /* Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Extensions.swift; sourceTree = "<group>"; };
39+
E292B9CA1B92384B00D75DE2 /* PBXObject.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PBXObject.swift; sourceTree = "<group>"; };
3540
/* End PBXFileReference section */
3641

3742
/* Begin PBXFrameworksBuildPhase section */
@@ -74,6 +79,9 @@
7479
E21D919C1B7B1A5D00FD0374 /* Xcode */ = {
7580
isa = PBXGroup;
7681
children = (
82+
E292B9C81B92380300D75DE2 /* Extensions.swift */,
83+
E292B9CA1B92384B00D75DE2 /* PBXObject.swift */,
84+
E292B9C41B9236B500D75DE2 /* Serialization.swift */,
7785
E21D919D1B7B1A5D00FD0374 /* Supporting Files */,
7886
E21D91B61B7B1A9000FD0374 /* XCProjectFile.swift */,
7987
);
@@ -215,15 +223,17 @@
215223
isa = PBXSourcesBuildPhase;
216224
buildActionMask = 2147483647;
217225
files = (
226+
E292B9C51B9236B500D75DE2 /* Serialization.swift in Sources */,
227+
E292B9C91B92380300D75DE2 /* Extensions.swift in Sources */,
218228
E21D91B71B7B1A9000FD0374 /* XCProjectFile.swift in Sources */,
229+
E292B9CB1B92384B00D75DE2 /* PBXObject.swift in Sources */,
219230
);
220231
runOnlyForDeploymentPostprocessing = 0;
221232
};
222233
E21D91A11B7B1A5D00FD0374 /* Sources */ = {
223234
isa = PBXSourcesBuildPhase;
224235
buildActionMask = 2147483647;
225236
files = (
226-
E28D3FDA1B7B1E00006BA061 /* XCProjectFile.swift in Sources */,
227237
E21D91AD1B7B1A5D00FD0374 /* XcodeTests.swift in Sources */,
228238
);
229239
runOnlyForDeploymentPostprocessing = 0;

Xcode/Xcode/Extensions.swift

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
//
2+
// Extensions.swift
3+
// Xcode
4+
//
5+
// Created by Tom Lokhorst on 2015-08-29.
6+
// Copyright © 2015 nonstrict. All rights reserved.
7+
//
8+
9+
import Foundation
10+
11+
extension Array {
12+
func ofType<T>(type: T.Type) -> [T] {
13+
return self.filter { $0 is T }.map { $0 as! T }
14+
}
15+
16+
func any(pred: Element -> Bool) -> Bool {
17+
for elem in self {
18+
if pred(elem) {
19+
return true
20+
}
21+
}
22+
23+
return false
24+
}
25+
}
26+
27+
func += <KeyType, ValueType> (inout left: Dictionary<KeyType, ValueType>, right: Dictionary<KeyType, ValueType>) {
28+
for (k, v) in right {
29+
left.updateValue(v, forKey: k)
30+
}
31+
}

Xcode/Xcode/PBXObject.swift

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
//
2+
// PBXObject.swift
3+
// Xcode
4+
//
5+
// Created by Tom Lokhorst on 2015-08-29.
6+
// Copyright © 2015 nonstrict. All rights reserved.
7+
//
8+
9+
import Foundation
10+
11+
typealias JsonObject = [String: AnyObject]
12+
13+
public class AllObjects {
14+
var projectName: String
15+
var dict: [String: PBXObject] = [:]
16+
var fullFilePaths: [String: String] = [:]
17+
18+
init(projectName: String) {
19+
self.projectName = projectName
20+
}
21+
22+
subscript(key: String) -> PBXObject? {
23+
get { return dict[key] }
24+
}
25+
26+
func object<T : PBXObject>(key: String) -> T {
27+
let obj = dict[key]!
28+
if let t = obj as? T {
29+
return t
30+
}
31+
32+
return T(id: key, dict: obj.dict, allObjects: self)
33+
}
34+
}
35+
36+
public /* abstract */ class PBXObject {
37+
let id: String
38+
let dict: JsonObject
39+
let allObjects: AllObjects
40+
41+
public lazy var isa: String = self.string("isa")!
42+
43+
public required init(id: String, dict: AnyObject, allObjects: AllObjects) {
44+
self.id = id
45+
self.dict = dict as! JsonObject
46+
self.allObjects = allObjects
47+
}
48+
49+
func string(key: String) -> String? {
50+
return dict[key] as? String
51+
}
52+
53+
func object<T : PBXObject>(key: String) -> T {
54+
let objectKey = dict[key] as! String
55+
return allObjects.object(objectKey)
56+
}
57+
58+
func objects<T : PBXObject>(key: String) -> [T] {
59+
let objectKeys = dict[key] as! [String]
60+
return objectKeys.map(allObjects.object)
61+
}
62+
}
63+
64+
public /* abstract */ class PBXContainer : PBXObject {
65+
}
66+
67+
public class PBXProject : PBXContainer {
68+
public lazy var targets: [PBXNativeTarget] = self.objects("targets")
69+
public lazy var mainGroup: PBXGroup = self.object("mainGroup")
70+
public lazy var buildConfigurationList: XCConfigurationList = self.object("buildConfigurationList")
71+
}
72+
73+
public /* abstract */ class PBXContainerItem : PBXObject {
74+
}
75+
76+
public class PBXContainerItemProxy : PBXContainerItem {
77+
}
78+
79+
public /* abstract */ class PBXProjectItem : PBXContainerItem {
80+
}
81+
82+
public class PBXBuildFile : PBXProjectItem {
83+
public lazy var fileRef: PBXReference = self.object("fileRef")
84+
}
85+
86+
87+
public /* abstract */ class PBXBuildPhase : PBXProjectItem {
88+
public lazy var files: [PBXBuildFile] = self.objects("files")
89+
}
90+
91+
public class PBXCopyFilesBuildPhase : PBXBuildPhase {
92+
public lazy var name: String? = self.string("name")
93+
}
94+
95+
public class PBXFrameworksBuildPhase : PBXBuildPhase {
96+
}
97+
98+
public class PBXHeadersBuildPhase : PBXBuildPhase {
99+
}
100+
101+
public class PBXResourcesBuildPhase : PBXBuildPhase {
102+
}
103+
104+
public class PBXShellScriptBuildPhase : PBXBuildPhase {
105+
public lazy var name: String? = self.string("name")
106+
public lazy var shellScript: String = self.string("shellScript")!
107+
}
108+
109+
public class PBXSourcesBuildPhase : PBXBuildPhase {
110+
}
111+
112+
public class PBXBuildStyle : PBXProjectItem {
113+
}
114+
115+
public class XCBuildConfiguration : PBXBuildStyle {
116+
public lazy var name: String = self.string("name")!
117+
}
118+
119+
public /* abstract */ class PBXTarget : PBXProjectItem {
120+
public lazy var buildConfigurationList: XCConfigurationList = self.object("buildConfigurationList")
121+
public lazy var name: String = self.string("name")!
122+
public lazy var productName: String = self.string("productName")!
123+
public lazy var buildPhases: [PBXBuildPhase] = self.objects("buildPhases")
124+
}
125+
126+
public class PBXAggregateTarget : PBXTarget {
127+
}
128+
129+
public class PBXNativeTarget : PBXTarget {
130+
}
131+
132+
public class PBXTargetDependency : PBXProjectItem {
133+
}
134+
135+
public class XCConfigurationList : PBXProjectItem {
136+
}
137+
138+
public class PBXReference : PBXContainerItem {
139+
public lazy var name: String? = self.string("name")
140+
public lazy var path: String? = self.string("path")
141+
}
142+
143+
public class PBXFileReference : PBXReference {
144+
145+
// convenience accessor
146+
public lazy var fullPath: String = self.allObjects.fullFilePaths[self.id]!
147+
}
148+
149+
public class PBXGroup : PBXReference {
150+
public lazy var children: [PBXReference] = self.objects("children")
151+
152+
// convenience accessors
153+
public lazy var subGroups: [PBXGroup] = self.children.ofType(PBXGroup.self)
154+
public lazy var fileRefs: [PBXFileReference] = self.children.ofType(PBXFileReference)
155+
}
156+
157+
public class PBXVariantGroup : PBXGroup {
158+
}
159+
160+
public class XCVersionGroup : PBXReference {
161+
}

0 commit comments

Comments
 (0)