From e42db901e36fc65c3cf3e1088d52d3531533b22e Mon Sep 17 00:00:00 2001 From: matejovic Date: Wed, 24 May 2017 16:38:10 +0200 Subject: [PATCH 1/2] Initial dictionary representation --- Examples/Cocoa/Sources/objc/Board.m | 85 ++++++++ Examples/Cocoa/Sources/objc/Image.m | 21 ++ Examples/Cocoa/Sources/objc/Pin.m | 136 ++++++++++++ Examples/Cocoa/Sources/objc/User.m | 85 ++++++++ Examples/Cocoa/Sources/objc/include/Board.h | 1 + Examples/Cocoa/Sources/objc/include/Image.h | 1 + Examples/Cocoa/Sources/objc/include/Pin.h | 1 + Examples/Cocoa/Sources/objc/include/User.h | 1 + Sources/Core/ObjCADTRenderer.swift | 67 +++++- Sources/Core/ObjCModelRenderer.swift | 4 +- .../Core/ObjectiveCDictionaryExtension.swift | 202 ++++++++++++++++++ plank.xcodeproj/project.pbxproj | 8 +- 12 files changed, 608 insertions(+), 4 deletions(-) create mode 100644 Sources/Core/ObjectiveCDictionaryExtension.swift diff --git a/Examples/Cocoa/Sources/objc/Board.m b/Examples/Cocoa/Sources/objc/Board.m index f8a79245..a147eaf2 100644 --- a/Examples/Cocoa/Sources/objc/Board.m +++ b/Examples/Cocoa/Sources/objc/Board.m @@ -249,6 +249,91 @@ - (instancetype)mergeWithModel:(Board *)modelObject initType:(PlankModelInitType [builder mergeWithModel:modelObject]; return [[Board alloc] initWithBuilder:builder initType:initType]; } +- (NSDictionary *)dictionaryRepresentation +{ + NSMutableDictionary *dict = [[NSMutableDictionary alloc] initWithCapacity:8]; + if (_boardDirtyProperties.BoardDirtyPropertyName) { + { + if (_name != nil) { + [dict setObject:_name forKey:@"name"]; + } + else { + [dict setObject:[NSNull null] forKey:@"name"]; + } + } + } + if (_boardDirtyProperties.BoardDirtyPropertyIdentifier) { + { + if (_identifier != nil) { + [dict setObject:_identifier forKey:@"id"]; + } + else { + [dict setObject:[NSNull null] forKey:@"id"]; + } + } + } + if (_boardDirtyProperties.BoardDirtyPropertyImage) { + { + if (_image != nil) { + [dict setObject:[_image dictionaryRepresentation] forKey:@"image"]; + } + else { + [dict setObject:[NSNull null] forKey:@"image"]; + } + } + } + if (_boardDirtyProperties.BoardDirtyPropertyCounts) { + { + if (_counts != nil) { + [dict setObject:_counts forKey:@"counts"]; + } + else { + [dict setObject:[NSNull null] forKey:@"counts"]; + } + } + } + if (_boardDirtyProperties.BoardDirtyPropertyCreatedAt) { + { + if (_createdAt != nil && [NSValueTransformer allowsReverseTransformation]) { + [dict setObject:[[NSValueTransformer valueTransformerForName:kPlankDateValueTransformerKey] reverseTransformedValue:_createdAt] forKey:@"created_at"]; + } + else { + [dict setObject:[NSNull null] forKey:@"created_at"]; + } + } + } + if (_boardDirtyProperties.BoardDirtyPropertyDescriptionText) { + { + if (_descriptionText != nil) { + [dict setObject:_descriptionText forKey:@"description"]; + } + else { + [dict setObject:[NSNull null] forKey:@"description"]; + } + } + } + if (_boardDirtyProperties.BoardDirtyPropertyCreator) { + { + if (_creator != nil) { + [dict setObject:_creator forKey:@"creator"]; + } + else { + [dict setObject:[NSNull null] forKey:@"creator"]; + } + } + } + if (_boardDirtyProperties.BoardDirtyPropertyUrl) { + { + if (_url != nil) { + [dict setObject:[_url absoluteString] forKey:@"url"]; + } + else { + [dict setObject:[NSNull null] forKey:@"url"]; + } + } + } + return dict; +} #pragma mark - NSCopying - (id)copyWithZone:(NSZone *)zone { diff --git a/Examples/Cocoa/Sources/objc/Image.m b/Examples/Cocoa/Sources/objc/Image.m index 1797853a..ffde2ed9 100644 --- a/Examples/Cocoa/Sources/objc/Image.m +++ b/Examples/Cocoa/Sources/objc/Image.m @@ -161,6 +161,27 @@ - (instancetype)mergeWithModel:(Image *)modelObject initType:(PlankModelInitType [builder mergeWithModel:modelObject]; return [[Image alloc] initWithBuilder:builder initType:initType]; } +- (NSDictionary *)dictionaryRepresentation +{ + NSMutableDictionary *dict = [[NSMutableDictionary alloc] initWithCapacity:3]; + if (_imageDirtyProperties.ImageDirtyPropertyHeight) { + [dict setObject:@(_height) forKey: @"height" ]; + } + if (_imageDirtyProperties.ImageDirtyPropertyUrl) { + { + if (_url != nil) { + [dict setObject:[_url absoluteString] forKey:@"url"]; + } + else { + [dict setObject:[NSNull null] forKey:@"url"]; + } + } + } + if (_imageDirtyProperties.ImageDirtyPropertyWidth) { + [dict setObject:@(_width) forKey: @"width" ]; + } + return dict; +} #pragma mark - NSCopying - (id)copyWithZone:(NSZone *)zone { diff --git a/Examples/Cocoa/Sources/objc/Pin.m b/Examples/Cocoa/Sources/objc/Pin.m index 824c239b..b2b7dc8e 100644 --- a/Examples/Cocoa/Sources/objc/Pin.m +++ b/Examples/Cocoa/Sources/objc/Pin.m @@ -345,6 +345,142 @@ - (instancetype)mergeWithModel:(Pin *)modelObject initType:(PlankModelInitType)i [builder mergeWithModel:modelObject]; return [[Pin alloc] initWithBuilder:builder initType:initType]; } +- (NSDictionary *)dictionaryRepresentation +{ + NSMutableDictionary *dict = [[NSMutableDictionary alloc] initWithCapacity:13]; + if (_pinDirtyProperties.PinDirtyPropertyNote) { + { + if (_note != nil) { + [dict setObject:_note forKey:@"note"]; + } + else { + [dict setObject:[NSNull null] forKey:@"note"]; + } + } + } + if (_pinDirtyProperties.PinDirtyPropertyMedia) { + { + if (_media != nil) { + [dict setObject:_media forKey:@"media"]; + } + else { + [dict setObject:[NSNull null] forKey:@"media"]; + } + } + } + if (_pinDirtyProperties.PinDirtyPropertyCounts) { + { + if (_counts != nil) { + [dict setObject:_counts forKey:@"counts"]; + } + else { + [dict setObject:[NSNull null] forKey:@"counts"]; + } + } + } + if (_pinDirtyProperties.PinDirtyPropertyDescriptionText) { + { + if (_descriptionText != nil) { + [dict setObject:_descriptionText forKey:@"description"]; + } + else { + [dict setObject:[NSNull null] forKey:@"description"]; + } + } + } + if (_pinDirtyProperties.PinDirtyPropertyCreator) { + { + NSMutableDictionary *items0 = [NSMutableDictionary new]; + for (id key in _creator) { + if ([_creator objectForKey:key] != (id)kCFNull) { + [items0 setObject:[[_creator objectForKey:key] dictionaryRepresentation] forKey:key]; + } + } + [dict setObject:items0 forKey: @"_creator" ]; + } + } + if (_pinDirtyProperties.PinDirtyPropertyAttribution) { + { + if (_attribution != nil) { + [dict setObject:_attribution forKey:@"attribution"]; + } + else { + [dict setObject:[NSNull null] forKey:@"attribution"]; + } + } + } + if (_pinDirtyProperties.PinDirtyPropertyBoard) { + { + if (_board != nil) { + [dict setObject:[_board dictionaryRepresentation] forKey:@"board"]; + } + else { + [dict setObject:[NSNull null] forKey:@"board"]; + } + } + } + if (_pinDirtyProperties.PinDirtyPropertyColor) { + { + if (_color != nil) { + [dict setObject:_color forKey:@"color"]; + } + else { + [dict setObject:[NSNull null] forKey:@"color"]; + } + } + } + if (_pinDirtyProperties.PinDirtyPropertyLink) { + { + if (_link != nil) { + [dict setObject:[_link absoluteString] forKey:@"link"]; + } + else { + [dict setObject:[NSNull null] forKey:@"link"]; + } + } + } + if (_pinDirtyProperties.PinDirtyPropertyIdentifier) { + { + if (_identifier != nil) { + [dict setObject:_identifier forKey:@"id"]; + } + else { + [dict setObject:[NSNull null] forKey:@"id"]; + } + } + } + if (_pinDirtyProperties.PinDirtyPropertyImage) { + { + if (_image != nil) { + [dict setObject:[_image dictionaryRepresentation] forKey:@"image"]; + } + else { + [dict setObject:[NSNull null] forKey:@"image"]; + } + } + } + if (_pinDirtyProperties.PinDirtyPropertyCreatedAt) { + { + if (_createdAt != nil && [NSValueTransformer allowsReverseTransformation]) { + [dict setObject:[[NSValueTransformer valueTransformerForName:kPlankDateValueTransformerKey] reverseTransformedValue:_createdAt] forKey:@"created_at"]; + } + else { + [dict setObject:[NSNull null] forKey:@"created_at"]; + } + } + } + if (_pinDirtyProperties.PinDirtyPropertyUrl) { + { + if (_url != nil) { + [dict setObject:[_url absoluteString] forKey:@"url"]; + } + else { + [dict setObject:[NSNull null] forKey:@"url"]; + } + } + } + return dict; +} #pragma mark - NSCopying - (id)copyWithZone:(NSZone *)zone { diff --git a/Examples/Cocoa/Sources/objc/User.m b/Examples/Cocoa/Sources/objc/User.m index ce346fbb..8ffd6d27 100644 --- a/Examples/Cocoa/Sources/objc/User.m +++ b/Examples/Cocoa/Sources/objc/User.m @@ -242,6 +242,91 @@ - (instancetype)mergeWithModel:(User *)modelObject initType:(PlankModelInitType) [builder mergeWithModel:modelObject]; return [[User alloc] initWithBuilder:builder initType:initType]; } +- (NSDictionary *)dictionaryRepresentation +{ + NSMutableDictionary *dict = [[NSMutableDictionary alloc] initWithCapacity:8]; + if (_userDirtyProperties.UserDirtyPropertyLastName) { + { + if (_lastName != nil) { + [dict setObject:_lastName forKey:@"last_name"]; + } + else { + [dict setObject:[NSNull null] forKey:@"last_name"]; + } + } + } + if (_userDirtyProperties.UserDirtyPropertyIdentifier) { + { + if (_identifier != nil) { + [dict setObject:_identifier forKey:@"id"]; + } + else { + [dict setObject:[NSNull null] forKey:@"id"]; + } + } + } + if (_userDirtyProperties.UserDirtyPropertyFirstName) { + { + if (_firstName != nil) { + [dict setObject:_firstName forKey:@"first_name"]; + } + else { + [dict setObject:[NSNull null] forKey:@"first_name"]; + } + } + } + if (_userDirtyProperties.UserDirtyPropertyImage) { + { + if (_image != nil) { + [dict setObject:[_image dictionaryRepresentation] forKey:@"image"]; + } + else { + [dict setObject:[NSNull null] forKey:@"image"]; + } + } + } + if (_userDirtyProperties.UserDirtyPropertyCounts) { + { + if (_counts != nil) { + [dict setObject:_counts forKey:@"counts"]; + } + else { + [dict setObject:[NSNull null] forKey:@"counts"]; + } + } + } + if (_userDirtyProperties.UserDirtyPropertyCreatedAt) { + { + if (_createdAt != nil && [NSValueTransformer allowsReverseTransformation]) { + [dict setObject:[[NSValueTransformer valueTransformerForName:kPlankDateValueTransformerKey] reverseTransformedValue:_createdAt] forKey:@"created_at"]; + } + else { + [dict setObject:[NSNull null] forKey:@"created_at"]; + } + } + } + if (_userDirtyProperties.UserDirtyPropertyUsername) { + { + if (_username != nil) { + [dict setObject:_username forKey:@"username"]; + } + else { + [dict setObject:[NSNull null] forKey:@"username"]; + } + } + } + if (_userDirtyProperties.UserDirtyPropertyBio) { + { + if (_bio != nil) { + [dict setObject:_bio forKey:@"bio"]; + } + else { + [dict setObject:[NSNull null] forKey:@"bio"]; + } + } + } + return dict; +} #pragma mark - NSCopying - (id)copyWithZone:(NSZone *)zone { diff --git a/Examples/Cocoa/Sources/objc/include/Board.h b/Examples/Cocoa/Sources/objc/include/Board.h index 5899af3a..7cd63ee5 100644 --- a/Examples/Cocoa/Sources/objc/include/Board.h +++ b/Examples/Cocoa/Sources/objc/include/Board.h @@ -32,6 +32,7 @@ NS_ASSUME_NONNULL_BEGIN - (BOOL)isEqualToBoard:(Board *)anObject; - (instancetype)mergeWithModel:(Board *)modelObject; - (instancetype)mergeWithModel:(Board *)modelObject initType:(PlankModelInitType)initType; +- (NSDictionary *)dictionaryRepresentation; @end @interface BoardBuilder : NSObject diff --git a/Examples/Cocoa/Sources/objc/include/Image.h b/Examples/Cocoa/Sources/objc/include/Image.h index 9c0e2259..ca2d67e6 100644 --- a/Examples/Cocoa/Sources/objc/include/Image.h +++ b/Examples/Cocoa/Sources/objc/include/Image.h @@ -26,6 +26,7 @@ NS_ASSUME_NONNULL_BEGIN - (BOOL)isEqualToImage:(Image *)anObject; - (instancetype)mergeWithModel:(Image *)modelObject; - (instancetype)mergeWithModel:(Image *)modelObject initType:(PlankModelInitType)initType; +- (NSDictionary *)dictionaryRepresentation; @end @interface ImageBuilder : NSObject diff --git a/Examples/Cocoa/Sources/objc/include/Pin.h b/Examples/Cocoa/Sources/objc/include/Pin.h index 18ca18b4..1c51e7a1 100644 --- a/Examples/Cocoa/Sources/objc/include/Pin.h +++ b/Examples/Cocoa/Sources/objc/include/Pin.h @@ -39,6 +39,7 @@ NS_ASSUME_NONNULL_BEGIN - (BOOL)isEqualToPin:(Pin *)anObject; - (instancetype)mergeWithModel:(Pin *)modelObject; - (instancetype)mergeWithModel:(Pin *)modelObject initType:(PlankModelInitType)initType; +- (NSDictionary *)dictionaryRepresentation; @end @interface PinBuilder : NSObject diff --git a/Examples/Cocoa/Sources/objc/include/User.h b/Examples/Cocoa/Sources/objc/include/User.h index caa9d939..c7e2e4b1 100644 --- a/Examples/Cocoa/Sources/objc/include/User.h +++ b/Examples/Cocoa/Sources/objc/include/User.h @@ -32,6 +32,7 @@ NS_ASSUME_NONNULL_BEGIN - (BOOL)isEqualToUser:(User *)anObject; - (instancetype)mergeWithModel:(User *)modelObject; - (instancetype)mergeWithModel:(User *)modelObject initType:(PlankModelInitType)initType; +- (NSDictionary *)dictionaryRepresentation; @end @interface UserBuilder : NSObject diff --git a/Sources/Core/ObjCADTRenderer.swift b/Sources/Core/ObjCADTRenderer.swift index 2fb87d6c..fd38e42f 100644 --- a/Sources/Core/ObjCADTRenderer.swift +++ b/Sources/Core/ObjCADTRenderer.swift @@ -102,6 +102,70 @@ struct ObjCADTRenderer: ObjCFileRenderer { } } + func renderDictionaryRepresentation() -> ObjCIR.Method { + return ObjCIR.method("- (id)dictionaryRepresentation") { + [ + ObjCIR.switchStmt("self.internalType") { + self.dataTypes.enumerated().map { (index, schema) -> ObjCIR.SwitchCase in + switch schema { + case .object: + return ObjCIR.caseStmt(self.internalTypeEnumName + ObjCADTRenderer.objectName(schema)) {[ + ObjCIR.stmt("return [[NSDictionary alloc]initWithDictionary:[self.value\(index) dictionaryRepresentation]]") + ]} + case .reference: + return ObjCIR.caseStmt(self.internalTypeEnumName + ObjCADTRenderer.objectName(schema)) {[ + ObjCIR.stmt("return [[NSDictionary alloc]initWithDictionary:[self.value\(index) dictionaryRepresentation]]") + ]} + case .float: + return ObjCIR.caseStmt(self.internalTypeEnumName + ObjCADTRenderer.objectName(schema)) {[ + ObjCIR.stmt("return [NSNumber numberWithFloat:self.value\(index)]") + ]} + case .integer: + return ObjCIR.caseStmt(self.internalTypeEnumName + ObjCADTRenderer.objectName(schema)) {[ + ObjCIR.stmt("return [NSNumber numberWithInteger:self.value\(index)]") + ]} + case .enumT(.integer): + return ObjCIR.caseStmt(self.internalTypeEnumName + ObjCADTRenderer.objectName(schema)) {[ + ObjCIR.stmt("return [NSNumber numberWithInteger:self.value\(index)]") + ]} + case .boolean: + return ObjCIR.caseStmt(self.internalTypeEnumName + ObjCADTRenderer.objectName(schema)) {[ + ObjCIR.stmt("return [NSNumber numberWithBool:self.value\(index)]") + ]} + case .array(itemType: _): + return ObjCIR.caseStmt(self.internalTypeEnumName + ObjCADTRenderer.objectName(schema)) {[ + ObjCIR.stmt("return [[NSDictionary alloc]initWithDictionary:[self.value\(index) dictionaryRepresentation]]") + ]} + case .map(valueType: _): + return ObjCIR.caseStmt(self.internalTypeEnumName + ObjCADTRenderer.objectName(schema)) {[ + ObjCIR.stmt("return [[NSDictionary alloc]initWithDictionary:[self.value\(index) absoluteString] ]") + ]} + case .string(.some(.uri)): + return ObjCIR.caseStmt(self.internalTypeEnumName + ObjCADTRenderer.objectName(schema)) {[ + ObjCIR.stmt("return [self.value\(index) absoluteString]") + ]} + case .string(.some(.dateTime)): + return ObjCIR.caseStmt(self.internalTypeEnumName + ObjCADTRenderer.objectName(schema)) {[ + ObjCIR.stmt("return [[NSValueTransformer valueTransformerForName:\(dateValueTransformerKey)] reverseTransformedValue:self.value\(index)]") + ]} + case .string(.some), .string(.none): + return ObjCIR.caseStmt(self.internalTypeEnumName + ObjCADTRenderer.objectName(schema)) {[ + ObjCIR.stmt("return self.value\(index)") + ]} + case .enumT(.string): + return ObjCIR.caseStmt(self.internalTypeEnumName + ObjCADTRenderer.objectName(schema)) {[ + ObjCIR.stmt("return "+enumToStringMethodName(propertyName: self.internalTypeEnumName, className: self.className)) + ]} + case .oneOf(types:_): + //error + fatalError("Nested oneOf types are unsupported at this time. Please file an issue if you require this. \(schema)") + } + } + } + ] + } + } + func renderMatchFunction() -> ObjCIR.Method { let signatureComponents = self.dataTypes.enumerated().map { (index, schema) -> String in let name = ObjCADTRenderer.objectName(schema) @@ -155,7 +219,8 @@ struct ObjCADTRenderer: ObjCFileRenderer { (.publicM, self.renderMatchFunction()), (.privateM, self.renderIsEqual()), (.publicM, self.renderIsEqualToClass()), - (.privateM, self.renderHash()) + (.privateM, self.renderHash()), + (.publicM, self.renderDictionaryRepresentation()) ], properties: [], protocols: protocols), diff --git a/Sources/Core/ObjCModelRenderer.swift b/Sources/Core/ObjCModelRenderer.swift index d22c276e..b0d86e57 100644 --- a/Sources/Core/ObjCModelRenderer.swift +++ b/Sources/Core/ObjCModelRenderer.swift @@ -197,7 +197,9 @@ public struct ObjCModelRenderer: ObjCFileRenderer { (.publicM, self.renderIsEqualToClass()), (.privateM, self.renderHash()), (.publicM, self.renderMergeWithModel()), - (.publicM, self.renderMergeWithModelWithInitType()) + (.publicM, self.renderMergeWithModelWithInitType()), + (.publicM, self.renderGenerateDictionary()) + ], properties: properties.map { param, schema in (param, objcClassFromSchema(param, schema), schema, .readonly) }, protocols: protocols diff --git a/Sources/Core/ObjectiveCDictionaryExtension.swift b/Sources/Core/ObjectiveCDictionaryExtension.swift new file mode 100644 index 00000000..36dc3c25 --- /dev/null +++ b/Sources/Core/ObjectiveCDictionaryExtension.swift @@ -0,0 +1,202 @@ +// +// ObjectiveCDictionaryExtension.swift +// plank +// +// Created by Martin Matejovic on 18/05/2017. +// +// + +import Foundation + +extension ObjCModelRenderer { + func renderGenerateDictionary() -> ObjCIR.Method { + let dictionary = "dict" + let props = self.properties.map { (param, schema) -> String in + ObjCIR.ifStmt("_"+"\(self.dirtyPropertiesIVarName).\(dirtyPropertyOption(propertyName: param, className: self.className))") { + [renderAddObjectStatement(param, schema, dictionary)] + } + }.joined(separator: "\n") + return ObjCIR.method("- (NSDictionary *)dictionaryRepresentation") {[ + "NSMutableDictionary *\(dictionary) = [[NSMutableDictionary alloc] initWithCapacity:\(self.properties.count)];", + props, + "return \(dictionary);" + ]} + } +} + +extension ObjCFileRenderer { + fileprivate func renderAddObjectStatement(_ param: String, _ schema: Schema, _ dictionary: String, counter: Int = 0) -> String { + var propIVarName = "_\(param.snakeCaseToPropertyName())" + switch schema { + case .boolean, .float, .integer: + return "[\(dictionary) setObject:@(\(propIVarName)) forKey: @\"\(param)\" ];" + case .object: + return ObjCIR.scope {[ + // TODO: After nullability PR landed we should revisit this and don't have to check for nil if + // the ivar is nonnull + ObjCIR.ifStmt("\(propIVarName) != nil") {[ + "[\(dictionary) setObject:[\(propIVarName) dictionaryRepresentation] forKey:@\"\(param)\"];" + ]}, + ObjCIR.elseStmt({[ + "[\(dictionary) setObject:[NSNull null] forKey:@\"\(param)\"];" + ] + }) + ]} + case .string(format: .none), + .string(format: .some(.email)), + .string(format: .some(.hostname)), + .string(format: .some(.ipv4)), + .string(format: .some(.ipv6)): + return ObjCIR.scope {[ + ObjCIR.ifStmt("\(propIVarName) != nil") {[ + "[\(dictionary) setObject:\(propIVarName) forKey:@\"\(param)\"];" + ]}, + ObjCIR.elseStmt({[ + "[\(dictionary) setObject:[NSNull null] forKey:@\"\(param)\"];" + ] + }) + ]} + case .string(format: .some(.uri)): + return ObjCIR.scope {[ + ObjCIR.ifStmt("\(propIVarName) != nil") {[ + "[\(dictionary) setObject:[\(propIVarName) absoluteString] forKey:@\"\(param)\"];" + ]}, + ObjCIR.elseStmt({[ + "[\(dictionary) setObject:[NSNull null] forKey:@\"\(param)\"];" + ] + }) + ]} + case .string(format: .some(.dateTime)): + return ObjCIR.scope {[ + ObjCIR.ifStmt("\(propIVarName) != nil && [NSValueTransformer allowsReverseTransformation]") {[ + "[\(dictionary) setObject:[[NSValueTransformer valueTransformerForName:\(dateValueTransformerKey)] reverseTransformedValue:\(propIVarName)] forKey:@\"\(param)\"];" + ]}, + ObjCIR.elseStmt({[ + "[\(dictionary) setObject:[NSNull null] forKey:@\"\(param)\"];" + ] + }) + ]} + case .enumT(.integer): + return "[\(dictionary) setObject:@(\(propIVarName)) forKey:@\"\(param)\"];" + case .enumT(.string): + return "[\(dictionary) setObject:"+enumToStringMethodName(propertyName: param, className: self.className) + "(\(propIVarName))" + " forKey:@\"\(param)\"];" + case .array(itemType: let itemType?): + func createArray(destArray: String, processObject: String, arraySchema: Schema, arrayCounter: Int = 0) -> String { + switch arraySchema { + case .reference, .object: + return "[\(destArray) addObject:[\(processObject) dictionaryRepresentation]];" + case .array(itemType: let type): + let currentResult = "result\(arrayCounter)" + let parentResult = "result\(arrayCounter-1)" + let currentObj = "obj\(arrayCounter)" + return ObjCIR.scope {[ + "NSArray *items\(arrayCounter) = \(processObject);", + "NSMutableArray *\(currentResult) = [NSMutableArray arrayWithCapacity:items\(arrayCounter).count];", + ObjCIR.forStmt("id \(currentObj) in items\(arrayCounter)") { [ + ObjCIR.ifStmt("\(currentObj) != (id)kCFNull") { [ + ObjCIR.stmt(createArray(destArray: currentResult, processObject: currentObj, arraySchema: type!, arrayCounter: arrayCounter+1)) + ]} + ]}, + "[\(parentResult) addObject:\(currentResult)];" + ]} + case .map(valueType: let type): + return self.renderAddObjectStatement(processObject, type!, processObject) + case .integer, .float, .boolean: + return "[\(destArray) addObject:@(\(processObject))] ];" + case .string(format: .none), + .string(format: .some(.email)), + .string(format: .some(.hostname)), + .string(format: .some(.ipv4)), + .string(format: .some(.ipv6)): + return "[\(destArray) addObject:\(processObject) ];" + case .string(format: .some(.uri)): + return "[\(destArray) addObject:[\(processObject) absoluteString] ];" + case .string(format: .some(.dateTime)): + return ObjCIR.scope {[ + ObjCIR.ifStmt("\(propIVarName) != nil && [NSValueTransformer allowsReverseTransformation]") {[ + "[\(destArray) addObject: [[NSValueTransformer valueTransformerForName:\(dateValueTransformerKey)] reverseTransformedValue:\(propIVarName)]];" + ]}, + ObjCIR.elseStmt({[ + "[\(destArray) addObject:[NSNull null]];" + ] + }) + ]} + case .enumT(.integer): + return "[\(destArray) addObject:@(\(processObject))];" + case .enumT(.string): + return "[\(destArray) addObject:"+enumToStringMethodName(propertyName: param, className: self.className) + "(\(propIVarName))];" + default: + assert(false, "Array of oneOf is not possible") + return "" + } + } + let currentResult = "result\(counter)" + let currentObj = "obj\(counter)" + return ObjCIR.scope {[ + "NSArray *items\(counter) = \(propIVarName);", + "NSMutableArray *\(currentResult) = [NSMutableArray arrayWithCapacity:items\(counter).count];", + ObjCIR.forStmt("id \(currentObj) in items\(counter)") { [ + ObjCIR.ifStmt("\(currentObj) != (id)kCFNull") { [ + ObjCIR.stmt(createArray(destArray: currentResult, processObject: currentObj, arraySchema: itemType, arrayCounter: counter+1)) + ]} + ]}, + "[\(dictionary) setObject:\(currentResult) forKey:@\"\(param)\"];" + ]} + case .map(valueType: let type): + switch type.unsafelyUnwrapped { + case .map, .object, .array: + return ObjCIR.scope {[ + ObjCIR.ifStmt("\(propIVarName) != nil") {[ + renderAddObjectStatement(param, type!, dictionary) + ]}, + ObjCIR.elseStmt({ + ["[\(dictionary) setObject:[NSNull null] forKey:@\"\(param)\"];"] + }) + ]} + case .reference(with: _): + return ObjCIR.scope {[ + "NSMutableDictionary *items\(counter) = [NSMutableDictionary new];", + ObjCIR.forStmt("id key in \(propIVarName)") { [ + ObjCIR.ifStmt("[\(propIVarName) objectForKey:key] != (id)kCFNull") { [ + "[items\(counter) setObject:[[\(propIVarName) objectForKey:key] dictionaryRepresentation] forKey:key];" + ]} + ]}, + "[\(dictionary) setObject:items\(counter) forKey: @\"\(propIVarName)\" ];" + ]} + default: + return ObjCIR.scope {[ + ObjCIR.ifStmt("\(propIVarName) != nil") { + ["[\(dictionary) setObject:\(propIVarName) forKey:@\"\(param)\"];"] + }, + ObjCIR.elseStmt({ + ["[\(dictionary) setObject:[NSNull null] forKey:@\"\(param)\"];"] + }) + ]} + } + case .oneOf(types: let avTypes): + return ObjCIR.scope {[ + ObjCIR.ifStmt("\(propIVarName) != nil") {[ + ObjCIR.switchStmt("\(propIVarName).internalType") { + avTypes.enumerated().map { (_, schema) -> ObjCIR.SwitchCase in + return ObjCIR.caseStmt(self.className+propIVarName.snakeCaseToCamelCase()+"InternalType"+ObjCADTRenderer.objectName(schema)) {[ + "[\(dictionary) setObject:[\(propIVarName) dictionaryRepresentation] forKey:@\"\(param)\"];" + ]} + } + } + ]}, + ObjCIR.elseStmt({ + ["[\(dictionary) setObject:[NSNull null] forKey:@\"\(param)\"];"] + }) + ]} + case .reference(with: let ref): + return ref.force().map { + renderAddObjectStatement(param, $0, dictionary) + } ?? { + assert(false, "TODO: Forward optional across methods") + return "" + }() + default: + return "" + } + } +} diff --git a/plank.xcodeproj/project.pbxproj b/plank.xcodeproj/project.pbxproj index ff9693b6..28bec9fc 100644 --- a/plank.xcodeproj/project.pbxproj +++ b/plank.xcodeproj/project.pbxproj @@ -7,13 +7,13 @@ objects = { /* Begin PBXBuildFile section */ + 691F9DFF1EF41CD10002CE40 /* StringExtensionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 691F9DFE1EF41CD10002CE40 /* StringExtensionsTests.swift */; }; 692EA6121EAFF3A9000D9A19 /* JSRuntimeFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 692EA6111EAFF3A9000D9A19 /* JSRuntimeFile.swift */; }; 6948DB2C1EB6A98C00EA902D /* JSIR.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6948DB2B1EB6A98C00EA902D /* JSIR.swift */; }; 6948DB301EB6AA5900EA902D /* JSModelRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6948DB2F1EB6AA5900EA902D /* JSModelRenderer.swift */; }; 6948DB321EB6AB2C00EA902D /* JSFileRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6948DB311EB6AB2C00EA902D /* JSFileRenderer.swift */; }; 6948DB341EB6C41700EA902D /* JSADTExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6948DB331EB6C41700EA902D /* JSADTExtension.swift */; }; 696C6E811EA928030039B52F /* JSFileGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 696C6E801EA928030039B52F /* JSFileGenerator.swift */; }; - 691F9DFF1EF41CD10002CE40 /* StringExtensionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 691F9DFE1EF41CD10002CE40 /* StringExtensionsTests.swift */; }; 812A69D01E53D2A1006A510E /* ObjectiveCEqualityExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 812A69CF1E53D2A1006A510E /* ObjectiveCEqualityExtension.swift */; }; 812A69D21E53D30F006A510E /* ObjectiveCInitExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 812A69D11E53D30F006A510E /* ObjectiveCInitExtension.swift */; }; 812A69D41E53D35F006A510E /* ObjectiveCBuilderExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 812A69D31E53D35F006A510E /* ObjectiveCBuilderExtension.swift */; }; @@ -23,6 +23,7 @@ 815A011C1E55100E00017AFB /* MockSchemaLoader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 815A011B1E55100E00017AFB /* MockSchemaLoader.swift */; }; 8193AF2E1E66A7E600DEBD13 /* ObjectiveCDebugExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8193AF2D1E66A7E600DEBD13 /* ObjectiveCDebugExtension.swift */; }; 8193AF301E66A87300DEBD13 /* ObjCFileRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8193AF2F1E66A87300DEBD13 /* ObjCFileRenderer.swift */; }; + EE11EB4E1ECDEF1400DD6A00 /* ObjectiveCDictionaryExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE11EB4D1ECDEF1400DD6A00 /* ObjectiveCDictionaryExtension.swift */; }; OBJ_33 /* FileGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_9 /* FileGenerator.swift */; }; OBJ_34 /* ObjCModelRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_10 /* ObjCModelRenderer.swift */; }; OBJ_35 /* ObjectiveCFileGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_11 /* ObjectiveCFileGenerator.swift */; }; @@ -56,13 +57,13 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + 691F9DFE1EF41CD10002CE40 /* StringExtensionsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StringExtensionsTests.swift; sourceTree = ""; }; 692EA6111EAFF3A9000D9A19 /* JSRuntimeFile.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JSRuntimeFile.swift; sourceTree = ""; }; 6948DB2B1EB6A98C00EA902D /* JSIR.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JSIR.swift; sourceTree = ""; }; 6948DB2F1EB6AA5900EA902D /* JSModelRenderer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JSModelRenderer.swift; sourceTree = ""; }; 6948DB311EB6AB2C00EA902D /* JSFileRenderer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JSFileRenderer.swift; sourceTree = ""; }; 6948DB331EB6C41700EA902D /* JSADTExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JSADTExtension.swift; sourceTree = ""; }; 696C6E801EA928030039B52F /* JSFileGenerator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JSFileGenerator.swift; sourceTree = ""; }; - 691F9DFE1EF41CD10002CE40 /* StringExtensionsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StringExtensionsTests.swift; sourceTree = ""; }; 812A69CF1E53D2A1006A510E /* ObjectiveCEqualityExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ObjectiveCEqualityExtension.swift; sourceTree = ""; }; 812A69D11E53D30F006A510E /* ObjectiveCInitExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ObjectiveCInitExtension.swift; sourceTree = ""; }; 812A69D31E53D35F006A510E /* ObjectiveCBuilderExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ObjectiveCBuilderExtension.swift; sourceTree = ""; }; @@ -72,6 +73,7 @@ 815A011B1E55100E00017AFB /* MockSchemaLoader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MockSchemaLoader.swift; sourceTree = ""; }; 8193AF2D1E66A7E600DEBD13 /* ObjectiveCDebugExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ObjectiveCDebugExtension.swift; sourceTree = ""; }; 8193AF2F1E66A87300DEBD13 /* ObjCFileRenderer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ObjCFileRenderer.swift; sourceTree = ""; }; + EE11EB4D1ECDEF1400DD6A00 /* ObjectiveCDictionaryExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ObjectiveCDictionaryExtension.swift; sourceTree = ""; }; OBJ_10 /* ObjCModelRenderer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = ObjCModelRenderer.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; OBJ_11 /* ObjectiveCFileGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = ObjectiveCFileGenerator.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; OBJ_12 /* ObjectiveCIR.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = ObjectiveCIR.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; @@ -194,6 +196,7 @@ OBJ_10 /* ObjCModelRenderer.swift */, 812A69D31E53D35F006A510E /* ObjectiveCBuilderExtension.swift */, 8193AF2D1E66A7E600DEBD13 /* ObjectiveCDebugExtension.swift */, + EE11EB4D1ECDEF1400DD6A00 /* ObjectiveCDictionaryExtension.swift */, 812A69CF1E53D2A1006A510E /* ObjectiveCEqualityExtension.swift */, OBJ_11 /* ObjectiveCFileGenerator.swift */, 812A69D11E53D30F006A510E /* ObjectiveCInitExtension.swift */, @@ -311,6 +314,7 @@ files = ( OBJ_33 /* FileGenerator.swift in Sources */, 812A69D21E53D30F006A510E /* ObjectiveCInitExtension.swift in Sources */, + EE11EB4E1ECDEF1400DD6A00 /* ObjectiveCDictionaryExtension.swift in Sources */, OBJ_34 /* ObjCModelRenderer.swift in Sources */, 692EA6121EAFF3A9000D9A19 /* JSRuntimeFile.swift in Sources */, OBJ_35 /* ObjectiveCFileGenerator.swift in Sources */, From 3c39a33b246c618dd1ac545680ebb3eb7383b371 Mon Sep 17 00:00:00 2001 From: Michael Schneider Date: Tue, 25 Jul 2017 09:39:01 -0700 Subject: [PATCH 2/2] Some code cleanup --- Examples/Cocoa/Sources/objc/Board.m | 96 +++++------ Examples/Cocoa/Sources/objc/Image.m | 12 +- Examples/Cocoa/Sources/objc/Pin.m | 156 ++++++++---------- Examples/Cocoa/Sources/objc/User.m | 96 +++++------ .../Core/ObjectiveCDictionaryExtension.swift | 71 ++++---- 5 files changed, 183 insertions(+), 248 deletions(-) diff --git a/Examples/Cocoa/Sources/objc/Board.m b/Examples/Cocoa/Sources/objc/Board.m index a147eaf2..eb65e43b 100644 --- a/Examples/Cocoa/Sources/objc/Board.m +++ b/Examples/Cocoa/Sources/objc/Board.m @@ -253,83 +253,67 @@ - (NSDictionary *)dictionaryRepresentation { NSMutableDictionary *dict = [[NSMutableDictionary alloc] initWithCapacity:8]; if (_boardDirtyProperties.BoardDirtyPropertyName) { - { - if (_name != nil) { - [dict setObject:_name forKey:@"name"]; - } - else { - [dict setObject:[NSNull null] forKey:@"name"]; - } + if (_name != nil) { + [dict setObject:_name forKey:@"name"]; + } + else { + [dict setObject:[NSNull null] forKey:@"name"]; } } if (_boardDirtyProperties.BoardDirtyPropertyIdentifier) { - { - if (_identifier != nil) { - [dict setObject:_identifier forKey:@"id"]; - } - else { - [dict setObject:[NSNull null] forKey:@"id"]; - } + if (_identifier != nil) { + [dict setObject:_identifier forKey:@"id"]; + } + else { + [dict setObject:[NSNull null] forKey:@"id"]; } } if (_boardDirtyProperties.BoardDirtyPropertyImage) { - { - if (_image != nil) { - [dict setObject:[_image dictionaryRepresentation] forKey:@"image"]; - } - else { - [dict setObject:[NSNull null] forKey:@"image"]; - } + if (_image != nil) { + [dict setObject:[_image dictionaryRepresentation] forKey:@"image"]; + } + else { + [dict setObject:[NSNull null] forKey:@"image"]; } } if (_boardDirtyProperties.BoardDirtyPropertyCounts) { - { - if (_counts != nil) { - [dict setObject:_counts forKey:@"counts"]; - } - else { - [dict setObject:[NSNull null] forKey:@"counts"]; - } + if (_counts != nil) { + [dict setObject:_counts forKey:@"counts"]; + } + else { + [dict setObject:[NSNull null] forKey:@"counts"]; } } if (_boardDirtyProperties.BoardDirtyPropertyCreatedAt) { - { - if (_createdAt != nil && [NSValueTransformer allowsReverseTransformation]) { - [dict setObject:[[NSValueTransformer valueTransformerForName:kPlankDateValueTransformerKey] reverseTransformedValue:_createdAt] forKey:@"created_at"]; - } - else { - [dict setObject:[NSNull null] forKey:@"created_at"]; - } + if (_createdAt != nil && [NSValueTransformer allowsReverseTransformation]) { + [dict setObject:[[NSValueTransformer valueTransformerForName:kPlankDateValueTransformerKey] reverseTransformedValue:_createdAt] forKey:@"created_at"]; + } + else { + [dict setObject:[NSNull null] forKey:@"created_at"]; } } if (_boardDirtyProperties.BoardDirtyPropertyDescriptionText) { - { - if (_descriptionText != nil) { - [dict setObject:_descriptionText forKey:@"description"]; - } - else { - [dict setObject:[NSNull null] forKey:@"description"]; - } + if (_descriptionText != nil) { + [dict setObject:_descriptionText forKey:@"description"]; + } + else { + [dict setObject:[NSNull null] forKey:@"description"]; } } if (_boardDirtyProperties.BoardDirtyPropertyCreator) { - { - if (_creator != nil) { - [dict setObject:_creator forKey:@"creator"]; - } - else { - [dict setObject:[NSNull null] forKey:@"creator"]; - } + if (_creator != nil) { + [dict setObject:_creator forKey:@"creator"]; + } + else { + [dict setObject:[NSNull null] forKey:@"creator"]; } } if (_boardDirtyProperties.BoardDirtyPropertyUrl) { - { - if (_url != nil) { - [dict setObject:[_url absoluteString] forKey:@"url"]; - } - else { - [dict setObject:[NSNull null] forKey:@"url"]; - } + if (_url != nil) { + [dict setObject:[_url absoluteString] forKey:@"url"]; + } + else { + [dict setObject:[NSNull null] forKey:@"url"]; } } return dict; diff --git a/Examples/Cocoa/Sources/objc/Image.m b/Examples/Cocoa/Sources/objc/Image.m index ffde2ed9..3ccea959 100644 --- a/Examples/Cocoa/Sources/objc/Image.m +++ b/Examples/Cocoa/Sources/objc/Image.m @@ -168,13 +168,11 @@ - (NSDictionary *)dictionaryRepresentation [dict setObject:@(_height) forKey: @"height" ]; } if (_imageDirtyProperties.ImageDirtyPropertyUrl) { - { - if (_url != nil) { - [dict setObject:[_url absoluteString] forKey:@"url"]; - } - else { - [dict setObject:[NSNull null] forKey:@"url"]; - } + if (_url != nil) { + [dict setObject:[_url absoluteString] forKey:@"url"]; + } + else { + [dict setObject:[NSNull null] forKey:@"url"]; } } if (_imageDirtyProperties.ImageDirtyPropertyWidth) { diff --git a/Examples/Cocoa/Sources/objc/Pin.m b/Examples/Cocoa/Sources/objc/Pin.m index b2b7dc8e..f3e89e78 100644 --- a/Examples/Cocoa/Sources/objc/Pin.m +++ b/Examples/Cocoa/Sources/objc/Pin.m @@ -349,134 +349,108 @@ - (NSDictionary *)dictionaryRepresentation { NSMutableDictionary *dict = [[NSMutableDictionary alloc] initWithCapacity:13]; if (_pinDirtyProperties.PinDirtyPropertyNote) { - { - if (_note != nil) { - [dict setObject:_note forKey:@"note"]; - } - else { - [dict setObject:[NSNull null] forKey:@"note"]; - } + if (_note != nil) { + [dict setObject:_note forKey:@"note"]; + } + else { + [dict setObject:[NSNull null] forKey:@"note"]; } } if (_pinDirtyProperties.PinDirtyPropertyMedia) { - { - if (_media != nil) { - [dict setObject:_media forKey:@"media"]; - } - else { - [dict setObject:[NSNull null] forKey:@"media"]; - } + if (_media != nil) { + [dict setObject:_media forKey:@"media"]; + } + else { + [dict setObject:[NSNull null] forKey:@"media"]; } } if (_pinDirtyProperties.PinDirtyPropertyCounts) { - { - if (_counts != nil) { - [dict setObject:_counts forKey:@"counts"]; - } - else { - [dict setObject:[NSNull null] forKey:@"counts"]; - } + if (_counts != nil) { + [dict setObject:_counts forKey:@"counts"]; + } + else { + [dict setObject:[NSNull null] forKey:@"counts"]; } } if (_pinDirtyProperties.PinDirtyPropertyDescriptionText) { - { - if (_descriptionText != nil) { - [dict setObject:_descriptionText forKey:@"description"]; - } - else { - [dict setObject:[NSNull null] forKey:@"description"]; - } + if (_descriptionText != nil) { + [dict setObject:_descriptionText forKey:@"description"]; + } + else { + [dict setObject:[NSNull null] forKey:@"description"]; } } if (_pinDirtyProperties.PinDirtyPropertyCreator) { - { - NSMutableDictionary *items0 = [NSMutableDictionary new]; - for (id key in _creator) { - if ([_creator objectForKey:key] != (id)kCFNull) { - [items0 setObject:[[_creator objectForKey:key] dictionaryRepresentation] forKey:key]; - } + NSMutableDictionary *items0 = [NSMutableDictionary new]; + for (id key in _creator) { + if ([_creator objectForKey:key] != (id)kCFNull) { + [items0 setObject:[[_creator objectForKey:key] dictionaryRepresentation] forKey:key]; } - [dict setObject:items0 forKey: @"_creator" ]; } + [dict setObject:items0 forKey: @"_creator" ]; } if (_pinDirtyProperties.PinDirtyPropertyAttribution) { - { - if (_attribution != nil) { - [dict setObject:_attribution forKey:@"attribution"]; - } - else { - [dict setObject:[NSNull null] forKey:@"attribution"]; - } + if (_attribution != nil) { + [dict setObject:_attribution forKey:@"attribution"]; + } + else { + [dict setObject:[NSNull null] forKey:@"attribution"]; } } if (_pinDirtyProperties.PinDirtyPropertyBoard) { - { - if (_board != nil) { - [dict setObject:[_board dictionaryRepresentation] forKey:@"board"]; - } - else { - [dict setObject:[NSNull null] forKey:@"board"]; - } + if (_board != nil) { + [dict setObject:[_board dictionaryRepresentation] forKey:@"board"]; + } + else { + [dict setObject:[NSNull null] forKey:@"board"]; } } if (_pinDirtyProperties.PinDirtyPropertyColor) { - { - if (_color != nil) { - [dict setObject:_color forKey:@"color"]; - } - else { - [dict setObject:[NSNull null] forKey:@"color"]; - } + if (_color != nil) { + [dict setObject:_color forKey:@"color"]; + } + else { + [dict setObject:[NSNull null] forKey:@"color"]; } } if (_pinDirtyProperties.PinDirtyPropertyLink) { - { - if (_link != nil) { - [dict setObject:[_link absoluteString] forKey:@"link"]; - } - else { - [dict setObject:[NSNull null] forKey:@"link"]; - } + if (_link != nil) { + [dict setObject:[_link absoluteString] forKey:@"link"]; + } + else { + [dict setObject:[NSNull null] forKey:@"link"]; } } if (_pinDirtyProperties.PinDirtyPropertyIdentifier) { - { - if (_identifier != nil) { - [dict setObject:_identifier forKey:@"id"]; - } - else { - [dict setObject:[NSNull null] forKey:@"id"]; - } + if (_identifier != nil) { + [dict setObject:_identifier forKey:@"id"]; + } + else { + [dict setObject:[NSNull null] forKey:@"id"]; } } if (_pinDirtyProperties.PinDirtyPropertyImage) { - { - if (_image != nil) { - [dict setObject:[_image dictionaryRepresentation] forKey:@"image"]; - } - else { - [dict setObject:[NSNull null] forKey:@"image"]; - } + if (_image != nil) { + [dict setObject:[_image dictionaryRepresentation] forKey:@"image"]; + } + else { + [dict setObject:[NSNull null] forKey:@"image"]; } } if (_pinDirtyProperties.PinDirtyPropertyCreatedAt) { - { - if (_createdAt != nil && [NSValueTransformer allowsReverseTransformation]) { - [dict setObject:[[NSValueTransformer valueTransformerForName:kPlankDateValueTransformerKey] reverseTransformedValue:_createdAt] forKey:@"created_at"]; - } - else { - [dict setObject:[NSNull null] forKey:@"created_at"]; - } + if (_createdAt != nil && [NSValueTransformer allowsReverseTransformation]) { + [dict setObject:[[NSValueTransformer valueTransformerForName:kPlankDateValueTransformerKey] reverseTransformedValue:_createdAt] forKey:@"created_at"]; + } + else { + [dict setObject:[NSNull null] forKey:@"created_at"]; } } if (_pinDirtyProperties.PinDirtyPropertyUrl) { - { - if (_url != nil) { - [dict setObject:[_url absoluteString] forKey:@"url"]; - } - else { - [dict setObject:[NSNull null] forKey:@"url"]; - } + if (_url != nil) { + [dict setObject:[_url absoluteString] forKey:@"url"]; + } + else { + [dict setObject:[NSNull null] forKey:@"url"]; } } return dict; diff --git a/Examples/Cocoa/Sources/objc/User.m b/Examples/Cocoa/Sources/objc/User.m index 8ffd6d27..429ffa9a 100644 --- a/Examples/Cocoa/Sources/objc/User.m +++ b/Examples/Cocoa/Sources/objc/User.m @@ -246,83 +246,67 @@ - (NSDictionary *)dictionaryRepresentation { NSMutableDictionary *dict = [[NSMutableDictionary alloc] initWithCapacity:8]; if (_userDirtyProperties.UserDirtyPropertyLastName) { - { - if (_lastName != nil) { - [dict setObject:_lastName forKey:@"last_name"]; - } - else { - [dict setObject:[NSNull null] forKey:@"last_name"]; - } + if (_lastName != nil) { + [dict setObject:_lastName forKey:@"last_name"]; + } + else { + [dict setObject:[NSNull null] forKey:@"last_name"]; } } if (_userDirtyProperties.UserDirtyPropertyIdentifier) { - { - if (_identifier != nil) { - [dict setObject:_identifier forKey:@"id"]; - } - else { - [dict setObject:[NSNull null] forKey:@"id"]; - } + if (_identifier != nil) { + [dict setObject:_identifier forKey:@"id"]; + } + else { + [dict setObject:[NSNull null] forKey:@"id"]; } } if (_userDirtyProperties.UserDirtyPropertyFirstName) { - { - if (_firstName != nil) { - [dict setObject:_firstName forKey:@"first_name"]; - } - else { - [dict setObject:[NSNull null] forKey:@"first_name"]; - } + if (_firstName != nil) { + [dict setObject:_firstName forKey:@"first_name"]; + } + else { + [dict setObject:[NSNull null] forKey:@"first_name"]; } } if (_userDirtyProperties.UserDirtyPropertyImage) { - { - if (_image != nil) { - [dict setObject:[_image dictionaryRepresentation] forKey:@"image"]; - } - else { - [dict setObject:[NSNull null] forKey:@"image"]; - } + if (_image != nil) { + [dict setObject:[_image dictionaryRepresentation] forKey:@"image"]; + } + else { + [dict setObject:[NSNull null] forKey:@"image"]; } } if (_userDirtyProperties.UserDirtyPropertyCounts) { - { - if (_counts != nil) { - [dict setObject:_counts forKey:@"counts"]; - } - else { - [dict setObject:[NSNull null] forKey:@"counts"]; - } + if (_counts != nil) { + [dict setObject:_counts forKey:@"counts"]; + } + else { + [dict setObject:[NSNull null] forKey:@"counts"]; } } if (_userDirtyProperties.UserDirtyPropertyCreatedAt) { - { - if (_createdAt != nil && [NSValueTransformer allowsReverseTransformation]) { - [dict setObject:[[NSValueTransformer valueTransformerForName:kPlankDateValueTransformerKey] reverseTransformedValue:_createdAt] forKey:@"created_at"]; - } - else { - [dict setObject:[NSNull null] forKey:@"created_at"]; - } + if (_createdAt != nil && [NSValueTransformer allowsReverseTransformation]) { + [dict setObject:[[NSValueTransformer valueTransformerForName:kPlankDateValueTransformerKey] reverseTransformedValue:_createdAt] forKey:@"created_at"]; + } + else { + [dict setObject:[NSNull null] forKey:@"created_at"]; } } if (_userDirtyProperties.UserDirtyPropertyUsername) { - { - if (_username != nil) { - [dict setObject:_username forKey:@"username"]; - } - else { - [dict setObject:[NSNull null] forKey:@"username"]; - } + if (_username != nil) { + [dict setObject:_username forKey:@"username"]; + } + else { + [dict setObject:[NSNull null] forKey:@"username"]; } } if (_userDirtyProperties.UserDirtyPropertyBio) { - { - if (_bio != nil) { - [dict setObject:_bio forKey:@"bio"]; - } - else { - [dict setObject:[NSNull null] forKey:@"bio"]; - } + if (_bio != nil) { + [dict setObject:_bio forKey:@"bio"]; + } + else { + [dict setObject:[NSNull null] forKey:@"bio"]; } } return dict; diff --git a/Sources/Core/ObjectiveCDictionaryExtension.swift b/Sources/Core/ObjectiveCDictionaryExtension.swift index 36dc3c25..a0847ff5 100644 --- a/Sources/Core/ObjectiveCDictionaryExtension.swift +++ b/Sources/Core/ObjectiveCDictionaryExtension.swift @@ -28,54 +28,50 @@ extension ObjCFileRenderer { fileprivate func renderAddObjectStatement(_ param: String, _ schema: Schema, _ dictionary: String, counter: Int = 0) -> String { var propIVarName = "_\(param.snakeCaseToPropertyName())" switch schema { + // TODO: After nullability PR landed we should revisit this and don't check for nil if + // the ivar is nonnull in all of this cases case .boolean, .float, .integer: return "[\(dictionary) setObject:@(\(propIVarName)) forKey: @\"\(param)\" ];" case .object: - return ObjCIR.scope {[ - // TODO: After nullability PR landed we should revisit this and don't have to check for nil if - // the ivar is nonnull + return [ ObjCIR.ifStmt("\(propIVarName) != nil") {[ "[\(dictionary) setObject:[\(propIVarName) dictionaryRepresentation] forKey:@\"\(param)\"];" ]}, ObjCIR.elseStmt({[ "[\(dictionary) setObject:[NSNull null] forKey:@\"\(param)\"];" - ] - }) - ]} + ]}) + ].joined(separator: "\n") case .string(format: .none), .string(format: .some(.email)), .string(format: .some(.hostname)), .string(format: .some(.ipv4)), .string(format: .some(.ipv6)): - return ObjCIR.scope {[ + return [ ObjCIR.ifStmt("\(propIVarName) != nil") {[ "[\(dictionary) setObject:\(propIVarName) forKey:@\"\(param)\"];" - ]}, + ]}, ObjCIR.elseStmt({[ "[\(dictionary) setObject:[NSNull null] forKey:@\"\(param)\"];" - ] - }) - ]} + ]}) + ].joined(separator: "\n") case .string(format: .some(.uri)): - return ObjCIR.scope {[ + return [ ObjCIR.ifStmt("\(propIVarName) != nil") {[ "[\(dictionary) setObject:[\(propIVarName) absoluteString] forKey:@\"\(param)\"];" - ]}, + ]}, ObjCIR.elseStmt({[ "[\(dictionary) setObject:[NSNull null] forKey:@\"\(param)\"];" - ] - }) - ]} + ]}) + ].joined(separator: "\n") case .string(format: .some(.dateTime)): - return ObjCIR.scope {[ + return [ ObjCIR.ifStmt("\(propIVarName) != nil && [NSValueTransformer allowsReverseTransformation]") {[ "[\(dictionary) setObject:[[NSValueTransformer valueTransformerForName:\(dateValueTransformerKey)] reverseTransformedValue:\(propIVarName)] forKey:@\"\(param)\"];" - ]}, + ]}, ObjCIR.elseStmt({[ "[\(dictionary) setObject:[NSNull null] forKey:@\"\(param)\"];" - ] - }) - ]} + ]}) + ].joined(separator: "\n") case .enumT(.integer): return "[\(dictionary) setObject:@(\(propIVarName)) forKey:@\"\(param)\"];" case .enumT(.string): @@ -89,7 +85,7 @@ extension ObjCFileRenderer { let currentResult = "result\(arrayCounter)" let parentResult = "result\(arrayCounter-1)" let currentObj = "obj\(arrayCounter)" - return ObjCIR.scope {[ + return [ "NSArray *items\(arrayCounter) = \(processObject);", "NSMutableArray *\(currentResult) = [NSMutableArray arrayWithCapacity:items\(arrayCounter).count];", ObjCIR.forStmt("id \(currentObj) in items\(arrayCounter)") { [ @@ -98,7 +94,7 @@ extension ObjCFileRenderer { ]} ]}, "[\(parentResult) addObject:\(currentResult)];" - ]} + ].joined(separator: "\n") case .map(valueType: let type): return self.renderAddObjectStatement(processObject, type!, processObject) case .integer, .float, .boolean: @@ -112,15 +108,14 @@ extension ObjCFileRenderer { case .string(format: .some(.uri)): return "[\(destArray) addObject:[\(processObject) absoluteString] ];" case .string(format: .some(.dateTime)): - return ObjCIR.scope {[ + return [ ObjCIR.ifStmt("\(propIVarName) != nil && [NSValueTransformer allowsReverseTransformation]") {[ "[\(destArray) addObject: [[NSValueTransformer valueTransformerForName:\(dateValueTransformerKey)] reverseTransformedValue:\(propIVarName)]];" - ]}, + ]}, ObjCIR.elseStmt({[ "[\(destArray) addObject:[NSNull null]];" - ] - }) - ]} + ]}) + ].joined(separator: "\n") case .enumT(.integer): return "[\(destArray) addObject:@(\(processObject))];" case .enumT(.string): @@ -132,7 +127,7 @@ extension ObjCFileRenderer { } let currentResult = "result\(counter)" let currentObj = "obj\(counter)" - return ObjCIR.scope {[ + return [ "NSArray *items\(counter) = \(propIVarName);", "NSMutableArray *\(currentResult) = [NSMutableArray arrayWithCapacity:items\(counter).count];", ObjCIR.forStmt("id \(currentObj) in items\(counter)") { [ @@ -141,20 +136,20 @@ extension ObjCFileRenderer { ]} ]}, "[\(dictionary) setObject:\(currentResult) forKey:@\"\(param)\"];" - ]} + ].joined(separator: "\n") case .map(valueType: let type): switch type.unsafelyUnwrapped { case .map, .object, .array: - return ObjCIR.scope {[ + return [ ObjCIR.ifStmt("\(propIVarName) != nil") {[ renderAddObjectStatement(param, type!, dictionary) ]}, ObjCIR.elseStmt({ ["[\(dictionary) setObject:[NSNull null] forKey:@\"\(param)\"];"] }) - ]} + ].joined(separator: "\n") case .reference(with: _): - return ObjCIR.scope {[ + return [ "NSMutableDictionary *items\(counter) = [NSMutableDictionary new];", ObjCIR.forStmt("id key in \(propIVarName)") { [ ObjCIR.ifStmt("[\(propIVarName) objectForKey:key] != (id)kCFNull") { [ @@ -162,19 +157,19 @@ extension ObjCFileRenderer { ]} ]}, "[\(dictionary) setObject:items\(counter) forKey: @\"\(propIVarName)\" ];" - ]} + ].joined(separator: "\n") default: - return ObjCIR.scope {[ + return [ ObjCIR.ifStmt("\(propIVarName) != nil") { ["[\(dictionary) setObject:\(propIVarName) forKey:@\"\(param)\"];"] }, ObjCIR.elseStmt({ ["[\(dictionary) setObject:[NSNull null] forKey:@\"\(param)\"];"] }) - ]} + ].joined(separator: "\n") } case .oneOf(types: let avTypes): - return ObjCIR.scope {[ + return [ ObjCIR.ifStmt("\(propIVarName) != nil") {[ ObjCIR.switchStmt("\(propIVarName).internalType") { avTypes.enumerated().map { (_, schema) -> ObjCIR.SwitchCase in @@ -187,7 +182,7 @@ extension ObjCFileRenderer { ObjCIR.elseStmt({ ["[\(dictionary) setObject:[NSNull null] forKey:@\"\(param)\"];"] }) - ]} + ].joined(separator: "\n") case .reference(with: let ref): return ref.force().map { renderAddObjectStatement(param, $0, dictionary)