@@ -43,6 +43,7 @@ extension Xcode.Project {
4343}
4444
4545extension Xcode . Project : PropertyListSerializable {
46+ fileprivate var xcodeClassName : String { " PBXProject " }
4647
4748 /// Generates and returns the contents of a `project.pbxproj` plist. Does
4849 /// not generate any ancillary files, such as a set of schemes.
@@ -77,7 +78,7 @@ extension Xcode.Project: PropertyListSerializable {
7778 // by Xcode when it opens the project and notices that they are missing.
7879 // Note: we also skip schemes, since they are not in the project plist.
7980 var dict = [ String: PropertyList] ( )
80- dict [ " isa " ] = . string( " PBXProject " )
81+ dict [ " isa " ] = . string( xcodeClassName )
8182 // Since the project file is generated, we opt out of upgrade-checking.
8283 // FIXME: Should we really? Why would we not want to get upgraded?
8384 dict [ " attributes " ] = . dictionary( [ " LastUpgradeCheck " : . string( " 9999 " ) ,
@@ -108,26 +109,35 @@ extension Xcode.Project: PropertyListSerializable {
108109}
109110
110111extension Xcode . Reference : PropertyListSerializable {
111- fileprivate dynamic func serialize(
112+ fileprivate var xcodeClassName : String {
113+ switch self {
114+ case is Xcode . Group :
115+ " PBXGroup "
116+ case let fileRef as Xcode . FileReference :
117+ fileRef. isBuildableFolder ? " PBXFileSystemSynchronizedRootGroup "
118+ : " PBXFileReference "
119+ default :
120+ fatalError ( " Unhandled subclass " )
121+ }
122+ }
123+
124+ fileprivate func serialize(
112125 to serializer: PropertyListSerializer
113126 ) throws -> [ String : PropertyList ] {
114127 var dict = [ String: PropertyList] ( )
128+ dict [ " isa " ] = . string( xcodeClassName)
115129 dict [ " path " ] = . string( path)
116130 if let name = name {
117131 dict [ " name " ] = . string( name)
118132 }
119133 dict [ " sourceTree " ] = . string( pathBase. rawValue)
120134
121- let xcodeClassName : String
122135 switch self {
123136 case let group as Xcode . Group :
124- xcodeClassName = " PBXGroup "
125137 dict [ " children " ] = try . array( group. subitems. map ( { reference in
126138 try . identifier( serializer. serialize ( object: reference) )
127139 } ) )
128140 case let fileRef as Xcode . FileReference :
129- xcodeClassName = fileRef. isBuildableFolder
130- ? " PBXFileSystemSynchronizedRootGroup " : " PBXFileReference "
131141 if let fileType = fileRef. fileType {
132142 dict [ " explicitFileType " ] = . string( fileType)
133143 }
@@ -138,19 +148,21 @@ extension Xcode.Reference: PropertyListSerializable {
138148 default :
139149 fatalError ( " Unhandled subclass " )
140150 }
141- dict [ " isa " ] = . string( xcodeClassName)
142151 return dict
143152 }
144153}
145154
146155extension Xcode . Target : PropertyListSerializable {
156+ fileprivate var xcodeClassName : String {
157+ productType == nil ? " PBXAggregateTarget " : " PBXNativeTarget "
158+ }
147159
148160 /// Called by the Serializer to serialize the Target.
149161 fileprivate func serialize( to serializer: PropertyListSerializer ) throws -> [ String : PropertyList ] {
150162 // Create either a `PBXNativeTarget` or an `PBXAggregateTarget` plist
151163 // dictionary (depending on whether or not we have a product type).
152164 var dict = [ String: PropertyList] ( )
153- dict [ " isa " ] = . string( productType == nil ? " PBXAggregateTarget " : " PBXNativeTarget " )
165+ dict [ " isa " ] = . string( xcodeClassName )
154166 dict [ " name " ] = . string( name)
155167 // Build settings are a bit tricky; in Xcode, each is stored in a named
156168 // XCBuildConfiguration object, and the list of build configurations is
@@ -169,14 +181,16 @@ extension Xcode.Target: PropertyListSerializable {
169181 /// glue between our value-based settings structures and the Xcode
170182 /// project model's identity-based TargetDependency objects.
171183 class TargetDependency : PropertyListSerializable {
184+ var xcodeClassName : String { " PBXTargetDependency " }
185+
172186 var target : Xcode . Target
173187 init ( target: Xcode . Target ) {
174188 self . target = target
175189 }
176190 func serialize( to serializer: PropertyListSerializer ) -> [ String : PropertyList ] {
177191 // Create a `PBXTargetDependency` plist dictionary.
178192 var dict = [ String: PropertyList] ( )
179- dict [ " isa " ] = . string( " PBXTargetDependency " )
193+ dict [ " isa " ] = . string( xcodeClassName )
180194 dict [ " target " ] = . identifier( serializer. id ( of: target) )
181195 return dict
182196 }
@@ -202,91 +216,60 @@ extension Xcode.Target: PropertyListSerializable {
202216 }
203217}
204218
205- /// Private helper function that constructs and returns a partial property list
206- /// dictionary for build phases. The caller can add to the returned dictionary.
207- /// FIXME: It would be nicer to be able to use inheritance to serialize the
208- /// attributes inherited from BuildPhase, but but in Swift 3.0 we get an error
209- /// that "declarations in extensions cannot override yet".
210- fileprivate func makeBuildPhaseDict(
211- buildPhase: Xcode . BuildPhase ,
212- serializer: PropertyListSerializer ,
213- xcodeClassName: String
214- ) throws -> [ String : PropertyList ] {
215- var dict = [ String: PropertyList] ( )
216- dict [ " isa " ] = . string( xcodeClassName)
217- dict [ " files " ] = try . array( buildPhase. files. map ( { file in
218- try . identifier( serializer. serialize ( object: file) )
219- } ) )
220- return dict
219+ extension PropertyListSerializable where Self: Xcode . BuildPhase {
220+ /// Helper function that constructs and returns the base property list
221+ /// dictionary for build phases.
222+ fileprivate func makeBuildPhaseDict(
223+ serializer: PropertyListSerializer
224+ ) throws -> [ String : PropertyList ] {
225+ var dict = [ String: PropertyList] ( )
226+ dict [ " isa " ] = . string( xcodeClassName)
227+ dict [ " files " ] = try . array( files. map ( { file in
228+ try . identifier( serializer. serialize ( object: file) )
229+ } ) )
230+ return dict
231+ }
232+
233+ /// Default serialization implementation.
234+ fileprivate func serialize(
235+ to serializer: PropertyListSerializer
236+ ) throws -> [ String : PropertyList ] {
237+ try makeBuildPhaseDict ( serializer: serializer)
238+ }
221239}
222240
223241extension Xcode . HeadersBuildPhase : PropertyListSerializable {
224-
225- /// Called by the Serializer to serialize the HeadersBuildPhase.
226- fileprivate func serialize( to serializer: PropertyListSerializer ) throws -> [ String : PropertyList ] {
227- // Create a `PBXHeadersBuildPhase` plist dictionary.
228- // FIXME: It would be nicer to be able to use inheritance for the code
229- // inherited from BuildPhase, but but in Swift 3.0 we get an error that
230- // "declarations in extensions cannot override yet".
231- return try makeBuildPhaseDict ( buildPhase: self , serializer: serializer, xcodeClassName: " PBXHeadersBuildPhase " )
232- }
242+ fileprivate var xcodeClassName : String { " PBXHeadersBuildPhase " }
233243}
234244
235245extension Xcode . SourcesBuildPhase : PropertyListSerializable {
236-
237- /// Called by the Serializer to serialize the SourcesBuildPhase.
238- fileprivate func serialize( to serializer: PropertyListSerializer ) throws -> [ String : PropertyList ] {
239- // Create a `PBXSourcesBuildPhase` plist dictionary.
240- // FIXME: It would be nicer to be able to use inheritance for the code
241- // inherited from BuildPhase, but but in Swift 3.0 we get an error that
242- // "declarations in extensions cannot override yet".
243- return try makeBuildPhaseDict ( buildPhase: self , serializer: serializer, xcodeClassName: " PBXSourcesBuildPhase " )
244- }
246+ fileprivate var xcodeClassName : String { " PBXSourcesBuildPhase " }
245247}
246248
247249extension Xcode . FrameworksBuildPhase : PropertyListSerializable {
248-
249- /// Called by the Serializer to serialize the FrameworksBuildPhase.
250- fileprivate func serialize( to serializer: PropertyListSerializer ) throws -> [ String : PropertyList ] {
251- // Create a `PBXFrameworksBuildPhase` plist dictionary.
252- // FIXME: It would be nicer to be able to use inheritance for the code
253- // inherited from BuildPhase, but but in Swift 3.0 we get an error that
254- // "declarations in extensions cannot override yet".
255- return try makeBuildPhaseDict ( buildPhase: self , serializer: serializer, xcodeClassName: " PBXFrameworksBuildPhase " )
256- }
250+ fileprivate var xcodeClassName : String { " PBXFrameworksBuildPhase " }
257251}
258252
259253extension Xcode . CopyFilesBuildPhase : PropertyListSerializable {
254+ fileprivate var xcodeClassName : String { " PBXCopyFilesBuildPhase " }
260255
261- /// Called by the Serializer to serialize the FrameworksBuildPhase.
262- fileprivate func serialize( to serializer: PropertyListSerializer ) throws -> [ String : PropertyList ] {
263- // Create a `PBXCopyFilesBuildPhase` plist dictionary.
264- // FIXME: It would be nicer to be able to use inheritance for the code
265- // inherited from BuildPhase, but but in Swift 3.0 we get an error that
266- // "declarations in extensions cannot override yet".
267- var dict = try makeBuildPhaseDict (
268- buildPhase: self ,
269- serializer: serializer,
270- xcodeClassName: " PBXCopyFilesBuildPhase "
271- )
256+ fileprivate func serialize(
257+ to serializer: PropertyListSerializer
258+ ) throws -> [ String : PropertyList ] {
259+ var dict = try makeBuildPhaseDict ( serializer: serializer)
272260 dict [ " dstPath " ] = . string( " " ) // FIXME: needs to be real
273261 dict [ " dstSubfolderSpec " ] = . string( " " ) // FIXME: needs to be real
274262 return dict
275263 }
276264}
277265
278266extension Xcode . ShellScriptBuildPhase : PropertyListSerializable {
267+ fileprivate var xcodeClassName : String { " PBXShellScriptBuildPhase " }
279268
280- /// Called by the Serializer to serialize the ShellScriptBuildPhase.
281- fileprivate func serialize( to serializer: PropertyListSerializer ) throws -> [ String : PropertyList ] {
282- // Create a `PBXShellScriptBuildPhase` plist dictionary.
283- // FIXME: It would be nicer to be able to use inheritance for the code
284- // inherited from BuildPhase, but but in Swift 3.0 we get an error that
285- // "declarations in extensions cannot override yet".
286- var dict = try makeBuildPhaseDict (
287- buildPhase: self ,
288- serializer: serializer,
289- xcodeClassName: " PBXShellScriptBuildPhase " )
269+ fileprivate func serialize(
270+ to serializer: PropertyListSerializer
271+ ) throws -> [ String : PropertyList ] {
272+ var dict = try makeBuildPhaseDict ( serializer: serializer)
290273 dict [ " shellPath " ] = . string( " /bin/sh " ) // FIXME: should be settable
291274 dict [ " shellScript " ] = . string( script)
292275 dict [ " inputPaths " ] = . array( inputs. map { . string( $0) } )
@@ -297,12 +280,13 @@ extension Xcode.ShellScriptBuildPhase: PropertyListSerializable {
297280}
298281
299282extension Xcode . BuildFile : PropertyListSerializable {
283+ fileprivate var xcodeClassName : String { " PBXBuildFile " }
300284
301285 /// Called by the Serializer to serialize the BuildFile.
302286 fileprivate func serialize( to serializer: PropertyListSerializer ) throws -> [ String : PropertyList ] {
303287 // Create a `PBXBuildFile` plist dictionary.
304288 var dict = [ String: PropertyList] ( )
305- dict [ " isa " ] = . string( " PBXBuildFile " )
289+ dict [ " isa " ] = . string( xcodeClassName )
306290 if let fileRef = fileRef {
307291 dict [ " fileRef " ] = . identifier( serializer. id ( of: fileRef) )
308292 }
@@ -317,6 +301,7 @@ extension Xcode.BuildFile: PropertyListSerializable {
317301}
318302
319303extension Xcode . BuildSettingsTable : PropertyListSerializable {
304+ fileprivate var xcodeClassName : String { " XCConfigurationList " }
320305
321306 /// Called by the Serializer to serialize the BuildFile. It is serialized
322307 /// as an XCBuildConfigurationList and two additional XCBuildConfiguration
@@ -331,6 +316,8 @@ extension Xcode.BuildSettingsTable: PropertyListSerializable {
331316 var overlaySettings : BuildSettings
332317 let xcconfigFileRef : Xcode . FileReference ?
333318
319+ var xcodeClassName : String { " XCBuildConfiguration " }
320+
334321 init (
335322 name: String ,
336323 baseSettings: BuildSettings ,
@@ -346,7 +333,7 @@ extension Xcode.BuildSettingsTable: PropertyListSerializable {
346333 func serialize( to serializer: PropertyListSerializer ) throws -> [ String : PropertyList ] {
347334 // Create a `XCBuildConfiguration` plist dictionary.
348335 var dict = [ String: PropertyList] ( )
349- dict [ " isa " ] = . string( " XCBuildConfiguration " )
336+ dict [ " isa " ] = . string( xcodeClassName )
350337 dict [ " name " ] = . string( name)
351338 // Combine the base settings and the overlay settings.
352339 dict [ " buildSettings " ] = try combineBuildSettingsPropertyLists (
@@ -363,7 +350,7 @@ extension Xcode.BuildSettingsTable: PropertyListSerializable {
363350
364351 // Create a `XCConfigurationList` plist dictionary.
365352 var dict = [ String: PropertyList] ( )
366- dict [ " isa " ] = . string( " XCConfigurationList " )
353+ dict [ " isa " ] = . string( xcodeClassName )
367354 dict [ " buildConfigurations " ] = . array( [
368355 // We use a private wrapper to "objectify" our two build settings
369356 // structures (which, being structs, are value types).
@@ -535,6 +522,9 @@ fileprivate protocol PropertyListSerializable: AnyObject {
535522 /// matters. So this is acceptable for now in the interest of getting it
536523 /// done.
537524
525+ /// The ID for the `isa` field of the object.
526+ var xcodeClassName : String { get }
527+
538528 /// A custom ID to use for the instance, if enabled.
539529 ///
540530 /// This ID must be unique across the entire serialized graph.
0 commit comments