From 5b5e0e1f85d935028a55b1ad3a475ced8f622356 Mon Sep 17 00:00:00 2001 From: Jon Parise Date: Fri, 3 Jan 2020 12:47:31 -0800 Subject: [PATCH 1/2] Support nested object type definitions We previously discovered nested object definitions but didn't generate code for them. This change implements that final bit of support. The main missing piece was a recursive operation to return all of the object roots defined within a schema. We were previously only looking at the schema's top-level object root during the file generation step. With this in place, the file generation loop now also operates over *all* object roots defined by a schema. --- .../Cocoa/Sources/Objective_C/Everything.m | 56 ++++- Examples/Cocoa/Sources/Objective_C/Nested.m | 207 ++++++++++++++++++ .../Sources/Objective_C/include/Everything.h | 4 + .../Sources/Objective_C/include/Nested.h | 40 ++++ Examples/JS/flow/EverythingType.js | 2 + Examples/JS/flow/NestedType.js | 18 ++ Examples/Java/Sources/Everything.java | 83 +++++-- Examples/Java/Sources/Nested.java | 193 ++++++++++++++++ Examples/PDK/everything.json | 7 + Sources/Core/FileGenerator.swift | 9 +- Sources/Core/Schema.swift | 19 +- 11 files changed, 613 insertions(+), 25 deletions(-) create mode 100644 Examples/Cocoa/Sources/Objective_C/Nested.m create mode 100644 Examples/Cocoa/Sources/Objective_C/include/Nested.h create mode 100644 Examples/JS/flow/NestedType.js create mode 100644 Examples/Java/Sources/Nested.java diff --git a/Examples/Cocoa/Sources/Objective_C/Everything.m b/Examples/Cocoa/Sources/Objective_C/Everything.m index 6c76abe7..818a7b88 100644 --- a/Examples/Cocoa/Sources/Objective_C/Everything.m +++ b/Examples/Cocoa/Sources/Objective_C/Everything.m @@ -10,6 +10,7 @@ #import "Everything.h" #import "Everything.h" #import "Image.h" +#import "Nested.h" #import "Pin.h" #import "User.h" @@ -598,6 +599,7 @@ - (void)encodeWithCoder:(NSCoder *)aCoder unsigned int EverythingDirtyPropertyMapWithObjectValues:1; unsigned int EverythingDirtyPropertyMapWithOtherModelValues:1; unsigned int EverythingDirtyPropertyMapWithPrimitiveValues:1; + unsigned int EverythingDirtyPropertyNestedObject:1; unsigned int EverythingDirtyPropertyNsintegerEnum:1; unsigned int EverythingDirtyPropertyNsuintegerEnum:1; unsigned int EverythingDirtyPropertyNumberProp:1; @@ -995,6 +997,15 @@ - (instancetype)initWithModelDictionary:(NS_VALID_UNTIL_END_OF_SCOPE NSDictionar self->_everythingDirtyProperties.EverythingDirtyPropertyMapWithPrimitiveValues = 1; } } + { + __unsafe_unretained id value = modelDictionary[@"nested_object"]; // Collection will retain. + if (value != nil) { + if (value != (id)kCFNull) { + self->_nestedObject = [Nested modelObjectWithDictionary:value]; + } + self->_everythingDirtyProperties.EverythingDirtyPropertyNestedObject = 1; + } + } { __unsafe_unretained id value = modelDictionary[@"nsinteger_enum"]; // Collection will retain. if (value != nil) { @@ -1245,6 +1256,7 @@ - (instancetype)initWithBuilder:(EverythingBuilder *)builder initType:(PlankMode _mapWithObjectValues = builder.mapWithObjectValues; _mapWithOtherModelValues = builder.mapWithOtherModelValues; _mapWithPrimitiveValues = builder.mapWithPrimitiveValues; + _nestedObject = builder.nestedObject; _nsintegerEnum = builder.nsintegerEnum; _nsuintegerEnum = builder.nsuintegerEnum; _numberProp = builder.numberProp; @@ -1272,7 +1284,7 @@ - (instancetype)initWithBuilder:(EverythingBuilder *)builder initType:(PlankMode - (NSString *)debugDescription { NSArray *parentDebugDescription = [[super debugDescription] componentsSeparatedByString:@"\n"]; - NSMutableArray *descriptionFields = [NSMutableArray arrayWithCapacity:36]; + NSMutableArray *descriptionFields = [NSMutableArray arrayWithCapacity:37]; [descriptionFields addObject:parentDebugDescription]; struct EverythingDirtyProperties props = _everythingDirtyProperties; if (props.EverythingDirtyPropertyArrayProp) { @@ -1329,6 +1341,9 @@ - (NSString *)debugDescription if (props.EverythingDirtyPropertyMapWithPrimitiveValues) { [descriptionFields addObject:[@"_mapWithPrimitiveValues = " stringByAppendingFormat:@"%@", _mapWithPrimitiveValues]]; } + if (props.EverythingDirtyPropertyNestedObject) { + [descriptionFields addObject:[@"_nestedObject = " stringByAppendingFormat:@"%@", _nestedObject]]; + } if (props.EverythingDirtyPropertyNsintegerEnum) { [descriptionFields addObject:[@"_nsintegerEnum = " stringByAppendingFormat:@"%@", @(_nsintegerEnum)]]; } @@ -1433,6 +1448,7 @@ - (BOOL)isEqualToEverything:(Everything *)anObject (_mapWithObjectValues == anObject.mapWithObjectValues || [_mapWithObjectValues isEqualToDictionary:anObject.mapWithObjectValues]) && (_mapWithOtherModelValues == anObject.mapWithOtherModelValues || [_mapWithOtherModelValues isEqualToDictionary:anObject.mapWithOtherModelValues]) && (_mapWithPrimitiveValues == anObject.mapWithPrimitiveValues || [_mapWithPrimitiveValues isEqualToDictionary:anObject.mapWithPrimitiveValues]) && + (_nestedObject == anObject.nestedObject || [_nestedObject isEqual:anObject.nestedObject]) && (_otherModelProp == anObject.otherModelProp || [_otherModelProp isEqual:anObject.otherModelProp]) && (_polymorphicProp == anObject.polymorphicProp || [_polymorphicProp isEqual:anObject.polymorphicProp]) && (_setProp == anObject.setProp || [_setProp isEqualToSet:anObject.setProp]) && @@ -1467,6 +1483,7 @@ - (NSUInteger)hash [_mapWithObjectValues hash], [_mapWithOtherModelValues hash], [_mapWithPrimitiveValues hash], + [_nestedObject hash], (NSUInteger)_nsintegerEnum, (NSUInteger)_nsuintegerEnum, [@(_numberProp) hash], @@ -1500,7 +1517,7 @@ - (instancetype)mergeWithModel:(Everything *)modelObject initType:(PlankModelIni } - (NSDictionary *)dictionaryObjectRepresentation { - NSMutableDictionary *dict = [[NSMutableDictionary alloc] initWithCapacity:36]; + NSMutableDictionary *dict = [[NSMutableDictionary alloc] initWithCapacity:37]; if (_everythingDirtyProperties.EverythingDirtyPropertyArrayProp) { if (_arrayProp != nil) { [dict setObject:_arrayProp forKey:@"array_prop"]; @@ -1691,6 +1708,13 @@ - (NSDictionary *)dictionaryObjectRepresentation [dict setObject:[NSNull null] forKey:@"map_with_primitive_values"]; } } + if (_everythingDirtyProperties.EverythingDirtyPropertyNestedObject) { + if (_nestedObject != nil) { + [dict setObject:[_nestedObject dictionaryObjectRepresentation] forKey:@"nested_object"]; + } else { + [dict setObject:[NSNull null] forKey:@"nested_object"]; + } + } if (_everythingDirtyProperties.EverythingDirtyPropertyNsintegerEnum) { [dict setObject:@(_nsintegerEnum) forKey:@"nsinteger_enum"]; } @@ -1874,6 +1898,10 @@ - (BOOL)isMapWithPrimitiveValuesSet { return _everythingDirtyProperties.EverythingDirtyPropertyMapWithPrimitiveValues == 1; } +- (BOOL)isNestedObjectSet +{ + return _everythingDirtyProperties.EverythingDirtyPropertyNestedObject == 1; +} - (BOOL)isNsintegerEnumSet { return _everythingDirtyProperties.EverythingDirtyPropertyNsintegerEnum == 1; @@ -1979,6 +2007,7 @@ - (instancetype)initWithCoder:(NSCoder *)aDecoder _mapWithObjectValues = [aDecoder decodeObjectOfClasses:[NSSet setWithArray:@[[NSDictionary class], [NSString class]]] forKey:@"map_with_object_values"]; _mapWithOtherModelValues = [aDecoder decodeObjectOfClasses:[NSSet setWithArray:@[[NSDictionary class], [User class]]] forKey:@"map_with_other_model_values"]; _mapWithPrimitiveValues = [aDecoder decodeObjectOfClasses:[NSSet setWithArray:@[[NSDictionary class], [NSNumber class]]] forKey:@"map_with_primitive_values"]; + _nestedObject = [aDecoder decodeObjectOfClass:[Nested class] forKey:@"nested_object"]; _nsintegerEnum = (EverythingNsintegerEnum)[aDecoder decodeIntegerForKey:@"nsinteger_enum"]; _nsuintegerEnum = (EverythingNsuintegerEnum)[aDecoder decodeIntegerForKey:@"nsuinteger_enum"]; _numberProp = [aDecoder decodeDoubleForKey:@"number_prop"]; @@ -2016,6 +2045,7 @@ - (instancetype)initWithCoder:(NSCoder *)aDecoder _everythingDirtyProperties.EverythingDirtyPropertyMapWithObjectValues = [aDecoder decodeIntForKey:@"map_with_object_values_dirty_property"] & 0x1; _everythingDirtyProperties.EverythingDirtyPropertyMapWithOtherModelValues = [aDecoder decodeIntForKey:@"map_with_other_model_values_dirty_property"] & 0x1; _everythingDirtyProperties.EverythingDirtyPropertyMapWithPrimitiveValues = [aDecoder decodeIntForKey:@"map_with_primitive_values_dirty_property"] & 0x1; + _everythingDirtyProperties.EverythingDirtyPropertyNestedObject = [aDecoder decodeIntForKey:@"nested_object_dirty_property"] & 0x1; _everythingDirtyProperties.EverythingDirtyPropertyNsintegerEnum = [aDecoder decodeIntForKey:@"nsinteger_enum_dirty_property"] & 0x1; _everythingDirtyProperties.EverythingDirtyPropertyNsuintegerEnum = [aDecoder decodeIntForKey:@"nsuinteger_enum_dirty_property"] & 0x1; _everythingDirtyProperties.EverythingDirtyPropertyNumberProp = [aDecoder decodeIntForKey:@"number_prop_dirty_property"] & 0x1; @@ -2059,6 +2089,7 @@ - (void)encodeWithCoder:(NSCoder *)aCoder [aCoder encodeObject:self.mapWithObjectValues forKey:@"map_with_object_values"]; [aCoder encodeObject:self.mapWithOtherModelValues forKey:@"map_with_other_model_values"]; [aCoder encodeObject:self.mapWithPrimitiveValues forKey:@"map_with_primitive_values"]; + [aCoder encodeObject:self.nestedObject forKey:@"nested_object"]; [aCoder encodeInteger:self.nsintegerEnum forKey:@"nsinteger_enum"]; [aCoder encodeInteger:self.nsuintegerEnum forKey:@"nsuinteger_enum"]; [aCoder encodeDouble:self.numberProp forKey:@"number_prop"]; @@ -2095,6 +2126,7 @@ - (void)encodeWithCoder:(NSCoder *)aCoder [aCoder encodeInt:_everythingDirtyProperties.EverythingDirtyPropertyMapWithObjectValues forKey:@"map_with_object_values_dirty_property"]; [aCoder encodeInt:_everythingDirtyProperties.EverythingDirtyPropertyMapWithOtherModelValues forKey:@"map_with_other_model_values_dirty_property"]; [aCoder encodeInt:_everythingDirtyProperties.EverythingDirtyPropertyMapWithPrimitiveValues forKey:@"map_with_primitive_values_dirty_property"]; + [aCoder encodeInt:_everythingDirtyProperties.EverythingDirtyPropertyNestedObject forKey:@"nested_object_dirty_property"]; [aCoder encodeInt:_everythingDirtyProperties.EverythingDirtyPropertyNsintegerEnum forKey:@"nsinteger_enum_dirty_property"]; [aCoder encodeInt:_everythingDirtyProperties.EverythingDirtyPropertyNsuintegerEnum forKey:@"nsuinteger_enum_dirty_property"]; [aCoder encodeInt:_everythingDirtyProperties.EverythingDirtyPropertyNumberProp forKey:@"number_prop_dirty_property"]; @@ -2180,6 +2212,9 @@ - (instancetype)initWithModel:(Everything *)modelObject if (everythingDirtyProperties.EverythingDirtyPropertyMapWithPrimitiveValues) { _mapWithPrimitiveValues = modelObject.mapWithPrimitiveValues; } + if (everythingDirtyProperties.EverythingDirtyPropertyNestedObject) { + _nestedObject = modelObject.nestedObject; + } if (everythingDirtyProperties.EverythingDirtyPropertyNsintegerEnum) { _nsintegerEnum = modelObject.nsintegerEnum; } @@ -2299,6 +2334,18 @@ - (void)mergeWithModel:(Everything *)modelObject if (modelObject.everythingDirtyProperties.EverythingDirtyPropertyMapWithPrimitiveValues) { builder.mapWithPrimitiveValues = modelObject.mapWithPrimitiveValues; } + if (modelObject.everythingDirtyProperties.EverythingDirtyPropertyNestedObject) { + id value = modelObject.nestedObject; + if (value != nil) { + if (builder.nestedObject) { + builder.nestedObject = [builder.nestedObject mergeWithModel:value initType:PlankModelInitTypeFromSubmerge]; + } else { + builder.nestedObject = value; + } + } else { + builder.nestedObject = nil; + } + } if (modelObject.everythingDirtyProperties.EverythingDirtyPropertyNsintegerEnum) { builder.nsintegerEnum = modelObject.nsintegerEnum; } @@ -2455,6 +2502,11 @@ - (void)setMapWithPrimitiveValues:(NSDictionary_identifier = [value integerValue]; + } + self->_nestedDirtyProperties.NestedDirtyPropertyIdentifier = 1; + } + } + if ([self class] == [Nested class]) { + [[NSNotificationCenter defaultCenter] postNotificationName:kPlankDidInitializeNotification object:self userInfo:@{ kPlankInitTypeKey : @(PlankModelInitTypeDefault) }]; + } + return self; +} +- (instancetype)initWithBuilder:(NestedBuilder *)builder +{ + NSParameterAssert(builder); + return [self initWithBuilder:builder initType:PlankModelInitTypeDefault]; +} +- (instancetype)initWithBuilder:(NestedBuilder *)builder initType:(PlankModelInitType)initType +{ + NSParameterAssert(builder); + if (!(self = [super init])) { + return self; + } + _identifier = builder.identifier; + _nestedDirtyProperties = builder.nestedDirtyProperties; + if ([self class] == [Nested class]) { + [[NSNotificationCenter defaultCenter] postNotificationName:kPlankDidInitializeNotification object:self userInfo:@{ kPlankInitTypeKey : @(initType) }]; + } + return self; +} +- (NSString *)debugDescription +{ + NSArray *parentDebugDescription = [[super debugDescription] componentsSeparatedByString:@"\n"]; + NSMutableArray *descriptionFields = [NSMutableArray arrayWithCapacity:1]; + [descriptionFields addObject:parentDebugDescription]; + struct NestedDirtyProperties props = _nestedDirtyProperties; + if (props.NestedDirtyPropertyIdentifier) { + [descriptionFields addObject:[@"_identifier = " stringByAppendingFormat:@"%@", @(_identifier)]]; + } + return [NSString stringWithFormat:@"Nested = {\n%@\n}", debugDescriptionForFields(descriptionFields)]; +} +- (instancetype)copyWithBlock:(PLANK_NOESCAPE void (^)(NestedBuilder *builder))block +{ + NSParameterAssert(block); + NestedBuilder *builder = [[NestedBuilder alloc] initWithModel:self]; + block(builder); + return [builder build]; +} +- (BOOL)isEqual:(id)anObject +{ + if (self == anObject) { + return YES; + } + if ([anObject isKindOfClass:[Nested class]] == NO) { + return NO; + } + return [self isEqualToNested:anObject]; +} +- (BOOL)isEqualToNested:(Nested *)anObject +{ + return ( + (anObject != nil) && + (_identifier == anObject.identifier) + ); +} +- (NSUInteger)hash +{ + NSUInteger subhashes[] = { + 17, + (NSUInteger)_identifier + }; + return PINIntegerArrayHash(subhashes, sizeof(subhashes) / sizeof(subhashes[0])); +} +- (instancetype)mergeWithModel:(Nested *)modelObject +{ + return [self mergeWithModel:modelObject initType:PlankModelInitTypeFromMerge]; +} +- (instancetype)mergeWithModel:(Nested *)modelObject initType:(PlankModelInitType)initType +{ + NSParameterAssert(modelObject); + NestedBuilder *builder = [[NestedBuilder alloc] initWithModel:self]; + [builder mergeWithModel:modelObject]; + return [[Nested alloc] initWithBuilder:builder initType:initType]; +} +- (NSDictionary *)dictionaryObjectRepresentation +{ + NSMutableDictionary *dict = [[NSMutableDictionary alloc] initWithCapacity:1]; + if (_nestedDirtyProperties.NestedDirtyPropertyIdentifier) { + [dict setObject:@(_identifier) forKey: @"id"]; + } + return dict; +} +- (BOOL)isIdentifierSet +{ + return _nestedDirtyProperties.NestedDirtyPropertyIdentifier == 1; +} +#pragma mark - NSCopying +- (id)copyWithZone:(NSZone *)zone +{ + return self; +} +#pragma mark - NSSecureCoding ++ (BOOL)supportsSecureCoding +{ + return YES; +} +- (instancetype)initWithCoder:(NSCoder *)aDecoder +{ + if (!(self = [super init])) { + return self; + } + _identifier = [aDecoder decodeIntegerForKey:@"id"]; + _nestedDirtyProperties.NestedDirtyPropertyIdentifier = [aDecoder decodeIntForKey:@"id_dirty_property"] & 0x1; + if ([self class] == [Nested class]) { + [[NSNotificationCenter defaultCenter] postNotificationName:kPlankDidInitializeNotification object:self userInfo:@{ kPlankInitTypeKey : @(PlankModelInitTypeDefault) }]; + } + return self; +} +- (void)encodeWithCoder:(NSCoder *)aCoder +{ + [aCoder encodeInteger:self.identifier forKey:@"id"]; + [aCoder encodeInt:_nestedDirtyProperties.NestedDirtyPropertyIdentifier forKey:@"id_dirty_property"]; +} +@end + +@implementation NestedBuilder +- (instancetype)initWithModel:(Nested *)modelObject +{ + NSParameterAssert(modelObject); + if (!(self = [super init])) { + return self; + } + struct NestedDirtyProperties nestedDirtyProperties = modelObject.nestedDirtyProperties; + if (nestedDirtyProperties.NestedDirtyPropertyIdentifier) { + _identifier = modelObject.identifier; + } + _nestedDirtyProperties = nestedDirtyProperties; + return self; +} +- (Nested *)build +{ + return [[Nested alloc] initWithBuilder:self]; +} +- (void)mergeWithModel:(Nested *)modelObject +{ + NSParameterAssert(modelObject); + NestedBuilder *builder = self; + if (modelObject.nestedDirtyProperties.NestedDirtyPropertyIdentifier) { + builder.identifier = modelObject.identifier; + } +} +- (void)setIdentifier:(NSInteger)identifier +{ + _identifier = identifier; + _nestedDirtyProperties.NestedDirtyPropertyIdentifier = 1; +} +@end diff --git a/Examples/Cocoa/Sources/Objective_C/include/Everything.h b/Examples/Cocoa/Sources/Objective_C/include/Everything.h index 3c7eecaa..cd16dfe3 100644 --- a/Examples/Cocoa/Sources/Objective_C/include/Everything.h +++ b/Examples/Cocoa/Sources/Objective_C/include/Everything.h @@ -12,6 +12,7 @@ @class Everything; @class EverythingBuilder; @class Image; +@class Nested; @class Pin; @class User; @@ -148,6 +149,7 @@ NS_ASSUME_NONNULL_BEGIN @property (nullable, nonatomic, strong, readonly) NSDictionary * mapWithObjectValues; @property (nullable, nonatomic, strong, readonly) NSDictionary * mapWithOtherModelValues; @property (nullable, nonatomic, strong, readonly) NSDictionary * mapWithPrimitiveValues; +@property (nullable, nonatomic, strong, readonly) Nested * nestedObject; @property (nonatomic, assign, readonly) EverythingNsintegerEnum nsintegerEnum; @property (nonatomic, assign, readonly) EverythingNsuintegerEnum nsuintegerEnum; @property (nonatomic, assign, readonly) double numberProp; @@ -196,6 +198,7 @@ NS_ASSUME_NONNULL_BEGIN - (BOOL)isMapWithObjectValuesSet; - (BOOL)isMapWithOtherModelValuesSet; - (BOOL)isMapWithPrimitiveValuesSet; +- (BOOL)isNestedObjectSet; - (BOOL)isNsintegerEnumSet; - (BOOL)isNsuintegerEnumSet; - (BOOL)isNumberPropSet; @@ -236,6 +239,7 @@ NS_ASSUME_NONNULL_BEGIN @property (nullable, nonatomic, strong, readwrite) NSDictionary * mapWithObjectValues; @property (nullable, nonatomic, strong, readwrite) NSDictionary * mapWithOtherModelValues; @property (nullable, nonatomic, strong, readwrite) NSDictionary * mapWithPrimitiveValues; +@property (nullable, nonatomic, strong, readwrite) Nested * nestedObject; @property (nonatomic, assign, readwrite) EverythingNsintegerEnum nsintegerEnum; @property (nonatomic, assign, readwrite) EverythingNsuintegerEnum nsuintegerEnum; @property (nonatomic, assign, readwrite) double numberProp; diff --git a/Examples/Cocoa/Sources/Objective_C/include/Nested.h b/Examples/Cocoa/Sources/Objective_C/include/Nested.h new file mode 100644 index 00000000..90ec15ef --- /dev/null +++ b/Examples/Cocoa/Sources/Objective_C/include/Nested.h @@ -0,0 +1,40 @@ +// +// Nested.h +// Autogenerated by Plank (https://pinterest.github.io/plank/) +// +// DO NOT EDIT - EDITS WILL BE OVERWRITTEN +// @generated +// + +#import +#import "PlankModelRuntime.h" +@class NestedBuilder; + +NS_ASSUME_NONNULL_BEGIN + +@interface Nested : NSObject +@property (nonatomic, assign, readonly) NSInteger identifier; + ++ (NSString *)className; ++ (NSString *)polymorphicTypeIdentifier; ++ (instancetype)modelObjectWithDictionary:(NSDictionary *)dictionary; +- (instancetype)initWithModelDictionary:(NS_VALID_UNTIL_END_OF_SCOPE NSDictionary *)modelDictionary; +- (instancetype)initWithBuilder:(NestedBuilder *)builder; +- (instancetype)initWithBuilder:(NestedBuilder *)builder initType:(PlankModelInitType)initType; +- (instancetype)copyWithBlock:(PLANK_NOESCAPE void (^)(NestedBuilder *builder))block; +- (BOOL)isEqualToNested:(Nested *)anObject; +- (instancetype)mergeWithModel:(Nested *)modelObject; +- (instancetype)mergeWithModel:(Nested *)modelObject initType:(PlankModelInitType)initType; +- (NSDictionary *)dictionaryObjectRepresentation; +- (BOOL)isIdentifierSet; +@end + +@interface NestedBuilder : NSObject +@property (nonatomic, assign, readwrite) NSInteger identifier; + +- (instancetype)initWithModel:(Nested *)modelObject; +- (Nested *)build; +- (void)mergeWithModel:(Nested *)modelObject; +@end + +NS_ASSUME_NONNULL_END diff --git a/Examples/JS/flow/EverythingType.js b/Examples/JS/flow/EverythingType.js index f67ebd20..f4e57cac 100644 --- a/Examples/JS/flow/EverythingType.js +++ b/Examples/JS/flow/EverythingType.js @@ -10,6 +10,7 @@ import type { PlankDate, PlankURI } from './runtime.flow.js'; import type { BoardType } from './BoardType.js'; import type { ImageType } from './ImageType.js'; +import type { Nested } from './Nested.js'; import type { PinType } from './PinType.js'; import type { UserType } from './UserType.js'; @@ -78,6 +79,7 @@ export type EverythingType = $Shape<{| +map_with_object_values: ?{ +[string]: string }, +map_with_other_model_values: ?{ +[string]: UserType }, +map_with_primitive_values: ?{ +[string]: number } /* Integer */, + +nested_object: ?NestedType, +nsinteger_enum: EverythingNsintegerEnum, +nsuinteger_enum: EverythingNsuintegerEnum, +number_prop: number, diff --git a/Examples/JS/flow/NestedType.js b/Examples/JS/flow/NestedType.js new file mode 100644 index 00000000..ae9cdba3 --- /dev/null +++ b/Examples/JS/flow/NestedType.js @@ -0,0 +1,18 @@ +// @flow +// +// NestedType.js +// Autogenerated by Plank (https://pinterest.github.io/plank/) +// +// DO NOT EDIT - EDITS WILL BE OVERWRITTEN +// @generated +// + +import type { PlankDate, PlankURI } from './runtime.flow.js'; + + +export type NestedType = $Shape<{| + +id: number, +|}> & { + id: string +}; + diff --git a/Examples/Java/Sources/Everything.java b/Examples/Java/Sources/Everything.java index 87d4825e..9831aff5 100644 --- a/Examples/Java/Sources/Everything.java +++ b/Examples/Java/Sources/Everything.java @@ -144,6 +144,7 @@ public int getValue() { @SerializedName("map_with_object_values") private @Nullable Map mapWithObjectValues; @SerializedName("map_with_other_model_values") private @Nullable Map mapWithOtherModelValues; @SerializedName("map_with_primitive_values") private @Nullable Map mapWithPrimitiveValues; + @SerializedName("nested_object") private @Nullable Nested nestedObject; @SerializedName("nsinteger_enum") private @Nullable EverythingNsintegerEnum nsintegerEnum; @SerializedName("nsuinteger_enum") private @Nullable EverythingNsuintegerEnum nsuintegerEnum; @SerializedName("number_prop") private @Nullable Double numberProp; @@ -181,23 +182,24 @@ public int getValue() { private static final int MAP_WITH_OBJECT_VALUES_INDEX = 16; private static final int MAP_WITH_OTHER_MODEL_VALUES_INDEX = 17; private static final int MAP_WITH_PRIMITIVE_VALUES_INDEX = 18; - private static final int NSINTEGER_ENUM_INDEX = 19; - private static final int NSUINTEGER_ENUM_INDEX = 20; - private static final int NUMBER_PROP_INDEX = 21; - private static final int OTHER_MODEL_PROP_INDEX = 22; - private static final int POLYMORPHIC_PROP_INDEX = 23; - private static final int SET_PROP_INDEX = 24; - private static final int SET_PROP_WITH_OTHER_MODEL_VALUES_INDEX = 25; - private static final int SET_PROP_WITH_PRIMITIVE_VALUES_INDEX = 26; - private static final int SET_PROP_WITH_VALUES_INDEX = 27; - private static final int SHORT_ENUM_INDEX = 28; - private static final int STRING_ENUM_INDEX = 29; - private static final int STRING_PROP_INDEX = 30; - private static final int TYPE_INDEX = 31; - private static final int UNSIGNED_CHAR_ENUM_INDEX = 32; - private static final int UNSIGNED_INT_ENUM_INDEX = 33; - private static final int UNSIGNED_SHORT_ENUM_INDEX = 34; - private static final int URI_PROP_INDEX = 35; + private static final int NESTED_OBJECT_INDEX = 19; + private static final int NSINTEGER_ENUM_INDEX = 20; + private static final int NSUINTEGER_ENUM_INDEX = 21; + private static final int NUMBER_PROP_INDEX = 22; + private static final int OTHER_MODEL_PROP_INDEX = 23; + private static final int POLYMORPHIC_PROP_INDEX = 24; + private static final int SET_PROP_INDEX = 25; + private static final int SET_PROP_WITH_OTHER_MODEL_VALUES_INDEX = 26; + private static final int SET_PROP_WITH_PRIMITIVE_VALUES_INDEX = 27; + private static final int SET_PROP_WITH_VALUES_INDEX = 28; + private static final int SHORT_ENUM_INDEX = 29; + private static final int STRING_ENUM_INDEX = 30; + private static final int STRING_PROP_INDEX = 31; + private static final int TYPE_INDEX = 32; + private static final int UNSIGNED_CHAR_ENUM_INDEX = 33; + private static final int UNSIGNED_INT_ENUM_INDEX = 34; + private static final int UNSIGNED_SHORT_ENUM_INDEX = 35; + private static final int URI_PROP_INDEX = 36; private boolean[] _bits; @@ -221,6 +223,7 @@ private Everything( @Nullable Map mapWithObjectValues, @Nullable Map mapWithOtherModelValues, @Nullable Map mapWithPrimitiveValues, + @Nullable Nested nestedObject, @Nullable EverythingNsintegerEnum nsintegerEnum, @Nullable EverythingNsuintegerEnum nsuintegerEnum, @Nullable Double numberProp, @@ -259,6 +262,7 @@ private Everything( this.mapWithObjectValues = mapWithObjectValues; this.mapWithOtherModelValues = mapWithOtherModelValues; this.mapWithPrimitiveValues = mapWithPrimitiveValues; + this.nestedObject = nestedObject; this.nsintegerEnum = nsintegerEnum; this.nsuintegerEnum = nsuintegerEnum; this.numberProp = numberProp; @@ -332,6 +336,7 @@ public boolean equals(Object o) { Objects.equals(this.mapWithObjectValues, that.mapWithObjectValues) && Objects.equals(this.mapWithOtherModelValues, that.mapWithOtherModelValues) && Objects.equals(this.mapWithPrimitiveValues, that.mapWithPrimitiveValues) && + Objects.equals(this.nestedObject, that.nestedObject) && Objects.equals(this.otherModelProp, that.otherModelProp) && Objects.equals(this.polymorphicProp, that.polymorphicProp) && Objects.equals(this.setProp, that.setProp) && @@ -364,6 +369,7 @@ public int hashCode() { mapWithObjectValues, mapWithOtherModelValues, mapWithPrimitiveValues, + nestedObject, nsintegerEnum, nsuintegerEnum, numberProp, @@ -461,6 +467,10 @@ public Integer getIntProp() { return this.mapWithPrimitiveValues; } + public @Nullable Nested getNestedObject() { + return this.nestedObject; + } + public @Nullable EverythingNsintegerEnum getNsintegerEnum() { return this.nsintegerEnum; } @@ -606,6 +616,10 @@ public boolean getMapWithPrimitiveValuesIsSet() { return this._bits.length > MAP_WITH_PRIMITIVE_VALUES_INDEX && this._bits[MAP_WITH_PRIMITIVE_VALUES_INDEX]; } + public boolean getNestedObjectIsSet() { + return this._bits.length > NESTED_OBJECT_INDEX && this._bits[NESTED_OBJECT_INDEX]; + } + public boolean getNsintegerEnumIsSet() { return this._bits.length > NSINTEGER_ENUM_INDEX && this._bits[NSINTEGER_ENUM_INDEX]; } @@ -695,6 +709,7 @@ public static class Builder { private @Nullable Map mapWithObjectValues; private @Nullable Map mapWithOtherModelValues; private @Nullable Map mapWithPrimitiveValues; + private @Nullable Nested nestedObject; private @Nullable EverythingNsintegerEnum nsintegerEnum; private @Nullable EverythingNsuintegerEnum nsuintegerEnum; private @Nullable Double numberProp; @@ -716,7 +731,7 @@ public static class Builder { private boolean[] _bits; private Builder() { - this._bits = new boolean[36]; + this._bits = new boolean[37]; } private Builder(@NonNull Everything model) { @@ -739,6 +754,7 @@ private Builder(@NonNull Everything model) { this.mapWithObjectValues = model.mapWithObjectValues; this.mapWithOtherModelValues = model.mapWithOtherModelValues; this.mapWithPrimitiveValues = model.mapWithPrimitiveValues; + this.nestedObject = model.nestedObject; this.nsintegerEnum = model.nsintegerEnum; this.nsuintegerEnum = model.nsuintegerEnum; this.numberProp = model.numberProp; @@ -930,6 +946,15 @@ public Builder setMapWithPrimitiveValues(@Nullable Map value) { return this; } + @NonNull + public Builder setNestedObject(@Nullable Nested value) { + this.nestedObject = value; + if (this._bits.length > NESTED_OBJECT_INDEX) { + this._bits[NESTED_OBJECT_INDEX] = true; + } + return this; + } + @NonNull public Builder setNsintegerEnum(@Nullable EverythingNsintegerEnum value) { this.nsintegerEnum = value; @@ -1159,6 +1184,10 @@ public Builder setUriProp(@Nullable String value) { return this.mapWithPrimitiveValues; } + public @Nullable Nested getNestedObject() { + return this.nestedObject; + } + public @Nullable EverythingNsintegerEnum getNsintegerEnum() { return this.nsintegerEnum; } @@ -1249,6 +1278,7 @@ public Everything build() { this.mapWithObjectValues, this.mapWithOtherModelValues, this.mapWithPrimitiveValues, + this.nestedObject, this.nsintegerEnum, this.nsuintegerEnum, this.numberProp, @@ -1347,6 +1377,10 @@ public void mergeFrom(@NonNull Everything model) { this.mapWithPrimitiveValues = model.mapWithPrimitiveValues; this._bits[MAP_WITH_PRIMITIVE_VALUES_INDEX] = true; } + if (model._bits.length > NESTED_OBJECT_INDEX && model._bits[NESTED_OBJECT_INDEX]) { + this.nestedObject = model.nestedObject; + this._bits[NESTED_OBJECT_INDEX] = true; + } if (model._bits.length > NSINTEGER_ENUM_INDEX && model._bits[NSINTEGER_ENUM_INDEX]) { this.nsintegerEnum = model.nsintegerEnum; this._bits[NSINTEGER_ENUM_INDEX] = true; @@ -1460,6 +1494,7 @@ private static class EverythingTypeAdapter extends TypeAdapter { private TypeAdapter> map_String__Object_TypeAdapter; private TypeAdapter> map_String__String_TypeAdapter; private TypeAdapter> map_String__User_TypeAdapter; + private TypeAdapter nestedTypeAdapter; private TypeAdapter> set_Integer_TypeAdapter; private TypeAdapter> set_Object_TypeAdapter; private TypeAdapter> set_String_TypeAdapter; @@ -1592,6 +1627,12 @@ public void write(@NonNull JsonWriter writer, Everything value) throws IOExcepti } this.map_String__Integer_TypeAdapter.write(writer.name("map_with_primitive_values"), value.mapWithPrimitiveValues); } + if (value._bits.length > NESTED_OBJECT_INDEX && value._bits[NESTED_OBJECT_INDEX]) { + if (this.nestedTypeAdapter == null) { + this.nestedTypeAdapter = this.gson.getAdapter(Nested.class).nullSafe(); + } + this.nestedTypeAdapter.write(writer.name("nested_object"), value.nestedObject); + } if (value._bits.length > NSINTEGER_ENUM_INDEX && value._bits[NSINTEGER_ENUM_INDEX]) { if (this.everythingNsintegerEnumTypeAdapter == null) { this.everythingNsintegerEnumTypeAdapter = this.gson.getAdapter(EverythingNsintegerEnum.class).nullSafe(); @@ -1823,6 +1864,12 @@ public Everything read(@NonNull JsonReader reader) throws IOException { } builder.setMapWithPrimitiveValues(this.map_String__Integer_TypeAdapter.read(reader)); break; + case ("nested_object"): + if (this.nestedTypeAdapter == null) { + this.nestedTypeAdapter = this.gson.getAdapter(Nested.class).nullSafe(); + } + builder.setNestedObject(this.nestedTypeAdapter.read(reader)); + break; case ("nsinteger_enum"): if (this.everythingNsintegerEnumTypeAdapter == null) { this.everythingNsintegerEnumTypeAdapter = this.gson.getAdapter(EverythingNsintegerEnum.class).nullSafe(); diff --git a/Examples/Java/Sources/Nested.java b/Examples/Java/Sources/Nested.java new file mode 100644 index 00000000..9f5f9a28 --- /dev/null +++ b/Examples/Java/Sources/Nested.java @@ -0,0 +1,193 @@ +// +// Nested.java +// Autogenerated by Plank (https://pinterest.github.io/plank/) +// +// DO NOT EDIT - EDITS WILL BE OVERWRITTEN +// @generated +// + +package com.pinterest.models; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import com.google.gson.Gson; +import com.google.gson.TypeAdapter; +import com.google.gson.TypeAdapterFactory; +import com.google.gson.annotations.SerializedName; +import com.google.gson.reflect.TypeToken; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonToken; +import com.google.gson.stream.JsonWriter; +import java.io.IOException; +import java.util.Objects; + +public class Nested { + + public static final String TYPE = "nested"; + + @SerializedName("id") private @Nullable Integer uid; + + private static final int ID_INDEX = 0; + + private boolean[] _bits; + + private Nested( + @Nullable Integer uid, + boolean[] _bits + ) { + this.uid = uid; + this._bits = _bits; + } + + @NonNull + public static Nested.Builder builder() { + return new Nested.Builder(); + } + + @NonNull + public Nested.Builder toBuilder() { + return new Nested.Builder(this); + } + + @NonNull + public Nested mergeFrom(@NonNull Nested model) { + Nested.Builder builder = this.toBuilder(); + builder.mergeFrom(model); + return builder.build(); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Nested that = (Nested) o; + return Objects.equals(this.uid, that.uid); + } + + @Override + public int hashCode() { + return Objects.hash(uid); + } + + @NonNull + public Integer getUid() { + return this.uid == null ? 0 : this.uid; + } + + public boolean getUidIsSet() { + return this._bits.length > ID_INDEX && this._bits[ID_INDEX]; + } + + public static class Builder { + + private @Nullable Integer uid; + + private boolean[] _bits; + + private Builder() { + this._bits = new boolean[1]; + } + + private Builder(@NonNull Nested model) { + this.uid = model.uid; + this._bits = model._bits; + } + + @NonNull + public Builder setUid(@Nullable Integer value) { + this.uid = value; + if (this._bits.length > ID_INDEX) { + this._bits[ID_INDEX] = true; + } + return this; + } + + public @Nullable Integer getUid() { + return this.uid; + } + + @NonNull + public Nested build() { + return new Nested( + this.uid, + this._bits + ); + } + + public void mergeFrom(@NonNull Nested model) { + if (model._bits.length > ID_INDEX && model._bits[ID_INDEX]) { + this.uid = model.uid; + this._bits[ID_INDEX] = true; + } + } + } + + public static class NestedTypeAdapterFactory implements TypeAdapterFactory { + + @Nullable + @Override + public TypeAdapter create(@NonNull Gson gson, @NonNull TypeToken typeToken) { + if (!Nested.class.isAssignableFrom(typeToken.getRawType())) { + return null; + } + return (TypeAdapter) new NestedTypeAdapter(gson); + } + } + + private static class NestedTypeAdapter extends TypeAdapter { + + private final Gson gson; + private TypeAdapter integerTypeAdapter; + + NestedTypeAdapter(Gson gson) { + this.gson = gson; + } + + @Override + public void write(@NonNull JsonWriter writer, Nested value) throws IOException { + if (value == null) { + writer.nullValue(); + return; + } + writer.beginObject(); + if (value._bits.length > ID_INDEX && value._bits[ID_INDEX]) { + if (this.integerTypeAdapter == null) { + this.integerTypeAdapter = this.gson.getAdapter(Integer.class).nullSafe(); + } + this.integerTypeAdapter.write(writer.name("id"), value.uid); + } + writer.endObject(); + } + + @Nullable + @Override + public Nested read(@NonNull JsonReader reader) throws IOException { + if (reader.peek() == JsonToken.NULL) { + reader.nextNull(); + return null; + } + Builder builder = Nested.builder(); + reader.beginObject(); + while (reader.hasNext()) { + String name = reader.nextName(); + switch (name) { + case ("id"): + if (this.integerTypeAdapter == null) { + this.integerTypeAdapter = this.gson.getAdapter(Integer.class).nullSafe(); + } + builder.setUid(this.integerTypeAdapter.read(reader)); + break; + default: + reader.skipValue(); + break; + } + } + reader.endObject(); + return builder.build(); + } + } +} diff --git a/Examples/PDK/everything.json b/Examples/PDK/everything.json index b15267ea..51e0218d 100644 --- a/Examples/PDK/everything.json +++ b/Examples/PDK/everything.json @@ -15,6 +15,13 @@ "set_prop": { "type": "array", "unique": "true" }, "array_prop": { "type": "array" }, "other_model_prop": { "$ref": "user.json" }, + "nested_object": { + "title": "nested", + "type": "object", + "properties": { + "id": {"type": "integer"} + } + }, "date_prop" : { "type": "string", "format": "date-time" diff --git a/Sources/Core/FileGenerator.swift b/Sources/Core/FileGenerator.swift index 26b5b0d6..8e082dac 100644 --- a/Sources/Core/FileGenerator.swift +++ b/Sources/Core/FileGenerator.swift @@ -509,15 +509,16 @@ public func generateFiles(urls: Set, outputDirectory: URL, generationParame return } processedSchemas.insert(url) - switch schema { - case let .object(rootObject): + + let objectRoots = schema.objectRoots() + assert(!objectRoots.isEmpty, "Incorrect Schema for root.") // TODO: Better error message. + + objectRoots.forEach { rootObject in fileGenerators.forEach { generator in generator.generateFile(rootObject, outputDirectory: outputDirectory, generationParameters: generationParameters) } - default: - assert(false, "Incorrect Schema for root.") // TODO: Better error message. } } } while diff --git a/Sources/Core/Schema.swift b/Sources/Core/Schema.swift index 77919bad..c3d10f87 100644 --- a/Sources/Core/Schema.swift +++ b/Sources/Core/Schema.swift @@ -131,7 +131,7 @@ extension Schema { } } -public struct SchemaObjectRoot: Equatable { +public struct SchemaObjectRoot: Hashable { let name: String let properties: [String: SchemaObjectProperty] let extends: URLSchemaReference? @@ -140,6 +140,10 @@ public struct SchemaObjectRoot: Equatable { var typeIdentifier: String { return algebraicTypeIdentifier ?? name } + + public func hash(into hasher: inout Hasher) { + hasher.combine(typeIdentifier) + } } public func == (lhs: SchemaObjectRoot, rhs: SchemaObjectRoot) -> Bool { @@ -257,6 +261,19 @@ extension Schema { return [ref.url] } } + + func objectRoots() -> Set { + switch self { + case let .object(rootObject): + return Set([rootObject]).union(rootObject.properties.values.flatMap { $0.schema.objectRoots() }) + case let .array(itemType: itemType), let .set(itemType: itemType): + return itemType?.objectRoots() ?? [] + case let .map(valueType: valueType): + return valueType?.objectRoots() ?? [] + default: + return [] + } + } } extension Schema { From 6f587636371c505158c840dad896dfe9fc8d0ab8 Mon Sep 17 00:00:00 2001 From: Jon Parise Date: Fri, 3 Jan 2020 13:11:19 -0800 Subject: [PATCH 2/2] Also support nested objects within oneOf --- .../Cocoa/Sources/Objective_C/Everything.m | 126 ++++++----- .../Cocoa/Sources/Objective_C/OneofObject.m | 207 ++++++++++++++++++ .../Sources/Objective_C/include/Everything.h | 17 +- .../Sources/Objective_C/include/OneofObject.h | 40 ++++ Examples/JS/flow/EverythingType.js | 3 +- Examples/JS/flow/OneofObjectType.js | 18 ++ Examples/Java/Sources/Everything.java | 46 ++-- Examples/Java/Sources/OneofObject.java | 193 ++++++++++++++++ Examples/PDK/everything.json | 1 + Sources/Core/Schema.swift | 2 + 10 files changed, 578 insertions(+), 75 deletions(-) create mode 100644 Examples/Cocoa/Sources/Objective_C/OneofObject.m create mode 100644 Examples/Cocoa/Sources/Objective_C/include/OneofObject.h create mode 100644 Examples/JS/flow/OneofObjectType.js create mode 100644 Examples/Java/Sources/OneofObject.java diff --git a/Examples/Cocoa/Sources/Objective_C/Everything.m b/Examples/Cocoa/Sources/Objective_C/Everything.m index 818a7b88..bb2891d6 100644 --- a/Examples/Cocoa/Sources/Objective_C/Everything.m +++ b/Examples/Cocoa/Sources/Objective_C/Everything.m @@ -11,6 +11,7 @@ #import "Everything.h" #import "Image.h" #import "Nested.h" +#import "OneofObject.h" #import "Pin.h" #import "User.h" @@ -253,12 +254,13 @@ @interface EverythingPolymorphicProp () @property (nonatomic, strong, readwrite) Image * value2; @property (nonatomic, strong, readwrite) Pin * value3; @property (nonatomic, strong, readwrite) Everything * value4; -@property (nonatomic, copy, readwrite) NSString * value5; -@property (nonatomic, assign, readwrite) BOOL value6; -@property (nonatomic, assign, readwrite) NSInteger value7; -@property (nonatomic, assign, readwrite) double value8; -@property (nonatomic, copy, readwrite) NSDate * value9; -@property (nonatomic, copy, readwrite) NSURL * value10; +@property (nonatomic, strong, readwrite) OneofObject * value5; +@property (nonatomic, copy, readwrite) NSString * value6; +@property (nonatomic, assign, readwrite) BOOL value7; +@property (nonatomic, assign, readwrite) NSInteger value8; +@property (nonatomic, assign, readwrite) double value9; +@property (nonatomic, copy, readwrite) NSDate * value10; +@property (nonatomic, copy, readwrite) NSURL * value11; @end @implementation EverythingPolymorphicProp @@ -297,49 +299,56 @@ + (instancetype)objectWithEverything:(Everything *)everything obj.internalType = EverythingPolymorphicPropInternalTypeEverything; return obj; } ++ (instancetype)objectWithOneofObject:(OneofObject *)oneofObject +{ + EverythingPolymorphicProp *obj = [[EverythingPolymorphicProp alloc] init]; + obj.value5 = oneofObject; + obj.internalType = EverythingPolymorphicPropInternalTypeOneofObject; + return obj; +} + (instancetype)objectWithString:(NSString *)string { EverythingPolymorphicProp *obj = [[EverythingPolymorphicProp alloc] init]; - obj.value5 = string; + obj.value6 = string; obj.internalType = EverythingPolymorphicPropInternalTypeString; return obj; } + (instancetype)objectWithBoolean:(BOOL)boolean { EverythingPolymorphicProp *obj = [[EverythingPolymorphicProp alloc] init]; - obj.value6 = boolean; + obj.value7 = boolean; obj.internalType = EverythingPolymorphicPropInternalTypeBoolean; return obj; } + (instancetype)objectWithInteger:(NSInteger)integer { EverythingPolymorphicProp *obj = [[EverythingPolymorphicProp alloc] init]; - obj.value7 = integer; + obj.value8 = integer; obj.internalType = EverythingPolymorphicPropInternalTypeInteger; return obj; } + (instancetype)objectWithFloat:(double)floatProperty { EverythingPolymorphicProp *obj = [[EverythingPolymorphicProp alloc] init]; - obj.value8 = floatProperty; + obj.value9 = floatProperty; obj.internalType = EverythingPolymorphicPropInternalTypeFloat; return obj; } + (instancetype)objectWithDate:(NSDate *)date { EverythingPolymorphicProp *obj = [[EverythingPolymorphicProp alloc] init]; - obj.value9 = date; + obj.value10 = date; obj.internalType = EverythingPolymorphicPropInternalTypeDate; return obj; } + (instancetype)objectWithURL:(NSURL *)uRL { EverythingPolymorphicProp *obj = [[EverythingPolymorphicProp alloc] init]; - obj.value10 = uRL; + obj.value11 = uRL; obj.internalType = EverythingPolymorphicPropInternalTypeURL; return obj; } -- (void)matchUser:(nullable PLANK_NOESCAPE void (^)(User * user))userMatchHandler orBoard:(nullable PLANK_NOESCAPE void (^)(Board * board))boardMatchHandler orImage:(nullable PLANK_NOESCAPE void (^)(Image * image))imageMatchHandler orPin:(nullable PLANK_NOESCAPE void (^)(Pin * pin))pinMatchHandler orEverything:(nullable PLANK_NOESCAPE void (^)(Everything * everything))everythingMatchHandler orString:(nullable PLANK_NOESCAPE void (^)(NSString * string))stringMatchHandler orBoolean:(nullable PLANK_NOESCAPE void (^)(BOOL boolean))booleanMatchHandler orInteger:(nullable PLANK_NOESCAPE void (^)(NSInteger integer))integerMatchHandler orFloat:(nullable PLANK_NOESCAPE void (^)(double floatProperty))floatPropertyMatchHandler orDate:(nullable PLANK_NOESCAPE void (^)(NSDate * date))dateMatchHandler orURL:(nullable PLANK_NOESCAPE void (^)(NSURL * uRL))uRLMatchHandler +- (void)matchUser:(nullable PLANK_NOESCAPE void (^)(User * user))userMatchHandler orBoard:(nullable PLANK_NOESCAPE void (^)(Board * board))boardMatchHandler orImage:(nullable PLANK_NOESCAPE void (^)(Image * image))imageMatchHandler orPin:(nullable PLANK_NOESCAPE void (^)(Pin * pin))pinMatchHandler orEverything:(nullable PLANK_NOESCAPE void (^)(Everything * everything))everythingMatchHandler orOneofObject:(nullable PLANK_NOESCAPE void (^)(OneofObject * oneofObject))oneofObjectMatchHandler orString:(nullable PLANK_NOESCAPE void (^)(NSString * string))stringMatchHandler orBoolean:(nullable PLANK_NOESCAPE void (^)(BOOL boolean))booleanMatchHandler orInteger:(nullable PLANK_NOESCAPE void (^)(NSInteger integer))integerMatchHandler orFloat:(nullable PLANK_NOESCAPE void (^)(double floatProperty))floatPropertyMatchHandler orDate:(nullable PLANK_NOESCAPE void (^)(NSDate * date))dateMatchHandler orURL:(nullable PLANK_NOESCAPE void (^)(NSURL * uRL))uRLMatchHandler { switch (self.internalType) { case EverythingPolymorphicPropInternalTypeUser: @@ -367,34 +376,39 @@ - (void)matchUser:(nullable PLANK_NOESCAPE void (^)(User * user))userMatchHandle everythingMatchHandler(self.value4); } break; + case EverythingPolymorphicPropInternalTypeOneofObject: + if (oneofObjectMatchHandler != NULL) { + oneofObjectMatchHandler(self.value5); + } + break; case EverythingPolymorphicPropInternalTypeString: if (stringMatchHandler != NULL) { - stringMatchHandler(self.value5); + stringMatchHandler(self.value6); } break; case EverythingPolymorphicPropInternalTypeBoolean: if (booleanMatchHandler != NULL) { - booleanMatchHandler(self.value6); + booleanMatchHandler(self.value7); } break; case EverythingPolymorphicPropInternalTypeInteger: if (integerMatchHandler != NULL) { - integerMatchHandler(self.value7); + integerMatchHandler(self.value8); } break; case EverythingPolymorphicPropInternalTypeFloat: if (floatPropertyMatchHandler != NULL) { - floatPropertyMatchHandler(self.value8); + floatPropertyMatchHandler(self.value9); } break; case EverythingPolymorphicPropInternalTypeDate: if (dateMatchHandler != NULL) { - dateMatchHandler(self.value9); + dateMatchHandler(self.value10); } break; case EverythingPolymorphicPropInternalTypeURL: if (uRLMatchHandler != NULL) { - uRLMatchHandler(self.value10); + uRLMatchHandler(self.value11); } break; } @@ -413,18 +427,19 @@ - (BOOL)isEqualToEverythingPolymorphicProp:(EverythingPolymorphicProp *)anObject { return ( (anObject != nil) && + (_value9 == anObject.value9) && (_value8 == anObject.value8) && (_value7 == anObject.value7) && - (_value6 == anObject.value6) && (_internalType == anObject.internalType) && (_value0 == anObject.value0 || [_value0 isEqual:anObject.value0]) && (_value1 == anObject.value1 || [_value1 isEqual:anObject.value1]) && - (_value10 == anObject.value10 || [_value10 isEqual:anObject.value10]) && + (_value10 == anObject.value10 || [_value10 isEqualToDate:anObject.value10]) && + (_value11 == anObject.value11 || [_value11 isEqual:anObject.value11]) && (_value2 == anObject.value2 || [_value2 isEqual:anObject.value2]) && (_value3 == anObject.value3 || [_value3 isEqual:anObject.value3]) && (_value4 == anObject.value4 || [_value4 isEqual:anObject.value4]) && - (_value5 == anObject.value5 || [_value5 isEqualToString:anObject.value5]) && - (_value9 == anObject.value9 || [_value9 isEqualToDate:anObject.value9]) + (_value5 == anObject.value5 || [_value5 isEqual:anObject.value5]) && + (_value6 == anObject.value6 || [_value6 isEqualToString:anObject.value6]) ); } - (NSUInteger)hash @@ -435,14 +450,15 @@ - (NSUInteger)hash [_value0 hash], [_value1 hash], [_value10 hash], + [_value11 hash], [_value2 hash], [_value3 hash], [_value4 hash], [_value5 hash], - (_value6 ? 1231 : 1237), - (NSUInteger)_value7, - [@(_value8) hash], - [_value9 hash] + [_value6 hash], + (_value7 ? 1231 : 1237), + (NSUInteger)_value8, + [@(_value9) hash] }; return PINIntegerArrayHash(subhashes, sizeof(subhashes) / sizeof(subhashes[0])); } @@ -484,51 +500,58 @@ - (id)dictionaryObjectRepresentation return resultDict[@"value4"]; } break; - case EverythingPolymorphicPropInternalTypeString: + case EverythingPolymorphicPropInternalTypeOneofObject: { NSMutableDictionary *resultDict = [[NSMutableDictionary alloc] init]; - [resultDict setObject:_value5 forKey:@"value5"]; + [resultDict setObject:[_value5 dictionaryObjectRepresentation] forKey:@"value5"]; return resultDict[@"value5"]; } break; - case EverythingPolymorphicPropInternalTypeBoolean: + case EverythingPolymorphicPropInternalTypeString: { NSMutableDictionary *resultDict = [[NSMutableDictionary alloc] init]; - [resultDict setObject:@(_value6) forKey: @"value6"]; + [resultDict setObject:_value6 forKey:@"value6"]; return resultDict[@"value6"]; } break; - case EverythingPolymorphicPropInternalTypeInteger: + case EverythingPolymorphicPropInternalTypeBoolean: { NSMutableDictionary *resultDict = [[NSMutableDictionary alloc] init]; [resultDict setObject:@(_value7) forKey: @"value7"]; return resultDict[@"value7"]; } break; - case EverythingPolymorphicPropInternalTypeFloat: + case EverythingPolymorphicPropInternalTypeInteger: { NSMutableDictionary *resultDict = [[NSMutableDictionary alloc] init]; [resultDict setObject:@(_value8) forKey: @"value8"]; return resultDict[@"value8"]; } break; + case EverythingPolymorphicPropInternalTypeFloat: + { + NSMutableDictionary *resultDict = [[NSMutableDictionary alloc] init]; + [resultDict setObject:@(_value9) forKey: @"value9"]; + return resultDict[@"value9"]; + } + break; case EverythingPolymorphicPropInternalTypeDate: { NSMutableDictionary *resultDict = [[NSMutableDictionary alloc] init]; NSValueTransformer *valueTransformer = [NSValueTransformer valueTransformerForName:kPlankDateValueTransformerKey]; if ([[valueTransformer class] allowsReverseTransformation]) { - [resultDict setObject:[valueTransformer reverseTransformedValue:_value9] forKey:@"value9"]; + [resultDict setObject:[valueTransformer reverseTransformedValue:_value10] forKey:@"value10"]; } else { - [resultDict setObject:[NSNull null] forKey:@"value9"]; + [resultDict setObject:[NSNull null] forKey:@"value10"]; } - return resultDict[@"value9"]; + return resultDict[@"value10"]; } break; case EverythingPolymorphicPropInternalTypeURL: { NSMutableDictionary *resultDict = [[NSMutableDictionary alloc] init]; - [resultDict setObject:[_value10 absoluteString] forKey:@"value10"]; - return resultDict[@"value10"]; + [resultDict setObject:[_value11 absoluteString] forKey:@"value11"]; + return resultDict[@"value11"]; } break; } @@ -551,15 +574,16 @@ - (instancetype)initWithCoder:(NSCoder *)aDecoder _internalType = (EverythingPolymorphicPropInternalType)[aDecoder decodeIntegerForKey:@"internal_type"]; _value0 = [aDecoder decodeObjectOfClass:[User class] forKey:@"value0"]; _value1 = [aDecoder decodeObjectOfClass:[Board class] forKey:@"value1"]; - _value10 = [aDecoder decodeObjectOfClass:[NSURL class] forKey:@"value10"]; + _value10 = [aDecoder decodeObjectOfClass:[NSDate class] forKey:@"value10"]; + _value11 = [aDecoder decodeObjectOfClass:[NSURL class] forKey:@"value11"]; _value2 = [aDecoder decodeObjectOfClass:[Image class] forKey:@"value2"]; _value3 = [aDecoder decodeObjectOfClass:[Pin class] forKey:@"value3"]; _value4 = [aDecoder decodeObjectOfClass:[Everything class] forKey:@"value4"]; - _value5 = [aDecoder decodeObjectOfClass:[NSString class] forKey:@"value5"]; - _value6 = [aDecoder decodeBoolForKey:@"value6"]; - _value7 = [aDecoder decodeIntegerForKey:@"value7"]; - _value8 = [aDecoder decodeDoubleForKey:@"value8"]; - _value9 = [aDecoder decodeObjectOfClass:[NSDate class] forKey:@"value9"]; + _value5 = [aDecoder decodeObjectOfClass:[OneofObject class] forKey:@"value5"]; + _value6 = [aDecoder decodeObjectOfClass:[NSString class] forKey:@"value6"]; + _value7 = [aDecoder decodeBoolForKey:@"value7"]; + _value8 = [aDecoder decodeIntegerForKey:@"value8"]; + _value9 = [aDecoder decodeDoubleForKey:@"value9"]; return self; } - (void)encodeWithCoder:(NSCoder *)aCoder @@ -568,14 +592,15 @@ - (void)encodeWithCoder:(NSCoder *)aCoder [aCoder encodeObject:self.value0 forKey:@"value0"]; [aCoder encodeObject:self.value1 forKey:@"value1"]; [aCoder encodeObject:self.value10 forKey:@"value10"]; + [aCoder encodeObject:self.value11 forKey:@"value11"]; [aCoder encodeObject:self.value2 forKey:@"value2"]; [aCoder encodeObject:self.value3 forKey:@"value3"]; [aCoder encodeObject:self.value4 forKey:@"value4"]; [aCoder encodeObject:self.value5 forKey:@"value5"]; - [aCoder encodeBool:self.value6 forKey:@"value6"]; - [aCoder encodeInteger:self.value7 forKey:@"value7"]; - [aCoder encodeDouble:self.value8 forKey:@"value8"]; - [aCoder encodeObject:self.value9 forKey:@"value9"]; + [aCoder encodeObject:self.value6 forKey:@"value6"]; + [aCoder encodeBool:self.value7 forKey:@"value7"]; + [aCoder encodeInteger:self.value8 forKey:@"value8"]; + [aCoder encodeDouble:self.value9 forKey:@"value9"]; } @end @@ -1061,6 +1086,9 @@ - (instancetype)initWithModelDictionary:(NS_VALID_UNTIL_END_OF_SCOPE NSDictionar if ([value isKindOfClass:[NSDictionary class]] && [value[@"type"] isEqualToString:@"everything"]) { self->_polymorphicProp = [EverythingPolymorphicProp objectWithEverything:[Everything modelObjectWithDictionary:value]]; } + if ([value isKindOfClass:[NSDictionary class]] && [value[@"type"] isEqualToString:@"oneof_object"]) { + self->_polymorphicProp = [EverythingPolymorphicProp objectWithOneofObject:[OneofObject modelObjectWithDictionary:value]]; + } if ([value isKindOfClass:[NSString class]]) { self->_polymorphicProp = [EverythingPolymorphicProp objectWithString:[value copy]]; } @@ -2012,7 +2040,7 @@ - (instancetype)initWithCoder:(NSCoder *)aDecoder _nsuintegerEnum = (EverythingNsuintegerEnum)[aDecoder decodeIntegerForKey:@"nsuinteger_enum"]; _numberProp = [aDecoder decodeDoubleForKey:@"number_prop"]; _otherModelProp = [aDecoder decodeObjectOfClass:[User class] forKey:@"other_model_prop"]; - _polymorphicProp = [aDecoder decodeObjectOfClasses:[NSSet setWithArray:@[[Board class], [Everything class], [Image class], [NSDate class], [NSNumber class], [NSString class], [NSURL class], [Pin class], [User class]]] forKey:@"polymorphic_prop"]; + _polymorphicProp = [aDecoder decodeObjectOfClasses:[NSSet setWithArray:@[[Board class], [Everything class], [Image class], [NSDate class], [NSNumber class], [NSString class], [NSURL class], [OneofObject class], [Pin class], [User class]]] forKey:@"polymorphic_prop"]; _setProp = [aDecoder decodeObjectOfClass:[NSSet class] forKey:@"set_prop"]; _setPropWithOtherModelValues = [aDecoder decodeObjectOfClasses:[NSSet setWithArray:@[[NSSet class], [User class]]] forKey:@"set_prop_with_other_model_values"]; _setPropWithPrimitiveValues = [aDecoder decodeObjectOfClasses:[NSSet setWithArray:@[[NSNumber class], [NSSet class]]] forKey:@"set_prop_with_primitive_values"]; diff --git a/Examples/Cocoa/Sources/Objective_C/OneofObject.m b/Examples/Cocoa/Sources/Objective_C/OneofObject.m new file mode 100644 index 00000000..aa6836f0 --- /dev/null +++ b/Examples/Cocoa/Sources/Objective_C/OneofObject.m @@ -0,0 +1,207 @@ +// +// OneofObject.m +// Autogenerated by Plank (https://pinterest.github.io/plank/) +// +// DO NOT EDIT - EDITS WILL BE OVERWRITTEN +// @generated +// + +#import "OneofObject.h" + +struct OneofObjectDirtyProperties { + unsigned int OneofObjectDirtyPropertyIdentifier:1; +}; + +@interface OneofObject () +@property (nonatomic, assign, readwrite) struct OneofObjectDirtyProperties oneofObjectDirtyProperties; +@end + +@interface OneofObjectBuilder () +@property (nonatomic, assign, readwrite) struct OneofObjectDirtyProperties oneofObjectDirtyProperties; +@end + +@implementation OneofObject ++ (NSString *)className +{ + return @"OneofObject"; +} ++ (NSString *)polymorphicTypeIdentifier +{ + return @"oneof_object"; +} ++ (instancetype)modelObjectWithDictionary:(NSDictionary *)dictionary +{ + return [[self alloc] initWithModelDictionary:dictionary]; +} +- (instancetype)init +{ + return [self initWithModelDictionary:@{}]; +} +- (instancetype)initWithModelDictionary:(NS_VALID_UNTIL_END_OF_SCOPE NSDictionary *)modelDictionary +{ + NSParameterAssert(modelDictionary); + if (!modelDictionary) { + return self; + } + if (!(self = [super init])) { + return self; + } + { + __unsafe_unretained id value = modelDictionary[@"id"]; // Collection will retain. + if (value != nil) { + if (value != (id)kCFNull) { + self->_identifier = [value integerValue]; + } + self->_oneofObjectDirtyProperties.OneofObjectDirtyPropertyIdentifier = 1; + } + } + if ([self class] == [OneofObject class]) { + [[NSNotificationCenter defaultCenter] postNotificationName:kPlankDidInitializeNotification object:self userInfo:@{ kPlankInitTypeKey : @(PlankModelInitTypeDefault) }]; + } + return self; +} +- (instancetype)initWithBuilder:(OneofObjectBuilder *)builder +{ + NSParameterAssert(builder); + return [self initWithBuilder:builder initType:PlankModelInitTypeDefault]; +} +- (instancetype)initWithBuilder:(OneofObjectBuilder *)builder initType:(PlankModelInitType)initType +{ + NSParameterAssert(builder); + if (!(self = [super init])) { + return self; + } + _identifier = builder.identifier; + _oneofObjectDirtyProperties = builder.oneofObjectDirtyProperties; + if ([self class] == [OneofObject class]) { + [[NSNotificationCenter defaultCenter] postNotificationName:kPlankDidInitializeNotification object:self userInfo:@{ kPlankInitTypeKey : @(initType) }]; + } + return self; +} +- (NSString *)debugDescription +{ + NSArray *parentDebugDescription = [[super debugDescription] componentsSeparatedByString:@"\n"]; + NSMutableArray *descriptionFields = [NSMutableArray arrayWithCapacity:1]; + [descriptionFields addObject:parentDebugDescription]; + struct OneofObjectDirtyProperties props = _oneofObjectDirtyProperties; + if (props.OneofObjectDirtyPropertyIdentifier) { + [descriptionFields addObject:[@"_identifier = " stringByAppendingFormat:@"%@", @(_identifier)]]; + } + return [NSString stringWithFormat:@"OneofObject = {\n%@\n}", debugDescriptionForFields(descriptionFields)]; +} +- (instancetype)copyWithBlock:(PLANK_NOESCAPE void (^)(OneofObjectBuilder *builder))block +{ + NSParameterAssert(block); + OneofObjectBuilder *builder = [[OneofObjectBuilder alloc] initWithModel:self]; + block(builder); + return [builder build]; +} +- (BOOL)isEqual:(id)anObject +{ + if (self == anObject) { + return YES; + } + if ([anObject isKindOfClass:[OneofObject class]] == NO) { + return NO; + } + return [self isEqualToOneofObject:anObject]; +} +- (BOOL)isEqualToOneofObject:(OneofObject *)anObject +{ + return ( + (anObject != nil) && + (_identifier == anObject.identifier) + ); +} +- (NSUInteger)hash +{ + NSUInteger subhashes[] = { + 17, + (NSUInteger)_identifier + }; + return PINIntegerArrayHash(subhashes, sizeof(subhashes) / sizeof(subhashes[0])); +} +- (instancetype)mergeWithModel:(OneofObject *)modelObject +{ + return [self mergeWithModel:modelObject initType:PlankModelInitTypeFromMerge]; +} +- (instancetype)mergeWithModel:(OneofObject *)modelObject initType:(PlankModelInitType)initType +{ + NSParameterAssert(modelObject); + OneofObjectBuilder *builder = [[OneofObjectBuilder alloc] initWithModel:self]; + [builder mergeWithModel:modelObject]; + return [[OneofObject alloc] initWithBuilder:builder initType:initType]; +} +- (NSDictionary *)dictionaryObjectRepresentation +{ + NSMutableDictionary *dict = [[NSMutableDictionary alloc] initWithCapacity:1]; + if (_oneofObjectDirtyProperties.OneofObjectDirtyPropertyIdentifier) { + [dict setObject:@(_identifier) forKey: @"id"]; + } + return dict; +} +- (BOOL)isIdentifierSet +{ + return _oneofObjectDirtyProperties.OneofObjectDirtyPropertyIdentifier == 1; +} +#pragma mark - NSCopying +- (id)copyWithZone:(NSZone *)zone +{ + return self; +} +#pragma mark - NSSecureCoding ++ (BOOL)supportsSecureCoding +{ + return YES; +} +- (instancetype)initWithCoder:(NSCoder *)aDecoder +{ + if (!(self = [super init])) { + return self; + } + _identifier = [aDecoder decodeIntegerForKey:@"id"]; + _oneofObjectDirtyProperties.OneofObjectDirtyPropertyIdentifier = [aDecoder decodeIntForKey:@"id_dirty_property"] & 0x1; + if ([self class] == [OneofObject class]) { + [[NSNotificationCenter defaultCenter] postNotificationName:kPlankDidInitializeNotification object:self userInfo:@{ kPlankInitTypeKey : @(PlankModelInitTypeDefault) }]; + } + return self; +} +- (void)encodeWithCoder:(NSCoder *)aCoder +{ + [aCoder encodeInteger:self.identifier forKey:@"id"]; + [aCoder encodeInt:_oneofObjectDirtyProperties.OneofObjectDirtyPropertyIdentifier forKey:@"id_dirty_property"]; +} +@end + +@implementation OneofObjectBuilder +- (instancetype)initWithModel:(OneofObject *)modelObject +{ + NSParameterAssert(modelObject); + if (!(self = [super init])) { + return self; + } + struct OneofObjectDirtyProperties oneofObjectDirtyProperties = modelObject.oneofObjectDirtyProperties; + if (oneofObjectDirtyProperties.OneofObjectDirtyPropertyIdentifier) { + _identifier = modelObject.identifier; + } + _oneofObjectDirtyProperties = oneofObjectDirtyProperties; + return self; +} +- (OneofObject *)build +{ + return [[OneofObject alloc] initWithBuilder:self]; +} +- (void)mergeWithModel:(OneofObject *)modelObject +{ + NSParameterAssert(modelObject); + OneofObjectBuilder *builder = self; + if (modelObject.oneofObjectDirtyProperties.OneofObjectDirtyPropertyIdentifier) { + builder.identifier = modelObject.identifier; + } +} +- (void)setIdentifier:(NSInteger)identifier +{ + _identifier = identifier; + _oneofObjectDirtyProperties.OneofObjectDirtyPropertyIdentifier = 1; +} +@end diff --git a/Examples/Cocoa/Sources/Objective_C/include/Everything.h b/Examples/Cocoa/Sources/Objective_C/include/Everything.h index cd16dfe3..3ce0fb10 100644 --- a/Examples/Cocoa/Sources/Objective_C/include/Everything.h +++ b/Examples/Cocoa/Sources/Objective_C/include/Everything.h @@ -13,6 +13,7 @@ @class EverythingBuilder; @class Image; @class Nested; +@class OneofObject; @class Pin; @class User; @@ -53,12 +54,13 @@ typedef NS_ENUM(unsigned char, EverythingPolymorphicPropInternalType) { EverythingPolymorphicPropInternalTypeImage = 3, EverythingPolymorphicPropInternalTypePin = 4, EverythingPolymorphicPropInternalTypeEverything = 5, - EverythingPolymorphicPropInternalTypeString = 6, - EverythingPolymorphicPropInternalTypeBoolean = 7, - EverythingPolymorphicPropInternalTypeInteger = 8, - EverythingPolymorphicPropInternalTypeFloat = 9, - EverythingPolymorphicPropInternalTypeDate = 10, - EverythingPolymorphicPropInternalTypeURL = 11 + EverythingPolymorphicPropInternalTypeOneofObject = 6, + EverythingPolymorphicPropInternalTypeString = 7, + EverythingPolymorphicPropInternalTypeBoolean = 8, + EverythingPolymorphicPropInternalTypeInteger = 9, + EverythingPolymorphicPropInternalTypeFloat = 10, + EverythingPolymorphicPropInternalTypeDate = 11, + EverythingPolymorphicPropInternalTypeURL = 12 }; @interface EverythingPolymorphicProp : NSObject @@ -69,13 +71,14 @@ typedef NS_ENUM(unsigned char, EverythingPolymorphicPropInternalType) { + (instancetype)objectWithImage:(Image *)image; + (instancetype)objectWithPin:(Pin *)pin; + (instancetype)objectWithEverything:(Everything *)everything; ++ (instancetype)objectWithOneofObject:(OneofObject *)oneofObject; + (instancetype)objectWithString:(NSString *)string; + (instancetype)objectWithBoolean:(BOOL)boolean; + (instancetype)objectWithInteger:(NSInteger)integer; + (instancetype)objectWithFloat:(double)floatProperty; + (instancetype)objectWithDate:(NSDate *)date; + (instancetype)objectWithURL:(NSURL *)uRL; -- (void)matchUser:(nullable PLANK_NOESCAPE void (^)(User * user))userMatchHandler orBoard:(nullable PLANK_NOESCAPE void (^)(Board * board))boardMatchHandler orImage:(nullable PLANK_NOESCAPE void (^)(Image * image))imageMatchHandler orPin:(nullable PLANK_NOESCAPE void (^)(Pin * pin))pinMatchHandler orEverything:(nullable PLANK_NOESCAPE void (^)(Everything * everything))everythingMatchHandler orString:(nullable PLANK_NOESCAPE void (^)(NSString * string))stringMatchHandler orBoolean:(nullable PLANK_NOESCAPE void (^)(BOOL boolean))booleanMatchHandler orInteger:(nullable PLANK_NOESCAPE void (^)(NSInteger integer))integerMatchHandler orFloat:(nullable PLANK_NOESCAPE void (^)(double floatProperty))floatPropertyMatchHandler orDate:(nullable PLANK_NOESCAPE void (^)(NSDate * date))dateMatchHandler orURL:(nullable PLANK_NOESCAPE void (^)(NSURL * uRL))uRLMatchHandler; +- (void)matchUser:(nullable PLANK_NOESCAPE void (^)(User * user))userMatchHandler orBoard:(nullable PLANK_NOESCAPE void (^)(Board * board))boardMatchHandler orImage:(nullable PLANK_NOESCAPE void (^)(Image * image))imageMatchHandler orPin:(nullable PLANK_NOESCAPE void (^)(Pin * pin))pinMatchHandler orEverything:(nullable PLANK_NOESCAPE void (^)(Everything * everything))everythingMatchHandler orOneofObject:(nullable PLANK_NOESCAPE void (^)(OneofObject * oneofObject))oneofObjectMatchHandler orString:(nullable PLANK_NOESCAPE void (^)(NSString * string))stringMatchHandler orBoolean:(nullable PLANK_NOESCAPE void (^)(BOOL boolean))booleanMatchHandler orInteger:(nullable PLANK_NOESCAPE void (^)(NSInteger integer))integerMatchHandler orFloat:(nullable PLANK_NOESCAPE void (^)(double floatProperty))floatPropertyMatchHandler orDate:(nullable PLANK_NOESCAPE void (^)(NSDate * date))dateMatchHandler orURL:(nullable PLANK_NOESCAPE void (^)(NSURL * uRL))uRLMatchHandler; - (BOOL)isEqualToEverythingPolymorphicProp:(EverythingPolymorphicProp *)anObject; - (id)dictionaryObjectRepresentation; @end diff --git a/Examples/Cocoa/Sources/Objective_C/include/OneofObject.h b/Examples/Cocoa/Sources/Objective_C/include/OneofObject.h new file mode 100644 index 00000000..10839602 --- /dev/null +++ b/Examples/Cocoa/Sources/Objective_C/include/OneofObject.h @@ -0,0 +1,40 @@ +// +// OneofObject.h +// Autogenerated by Plank (https://pinterest.github.io/plank/) +// +// DO NOT EDIT - EDITS WILL BE OVERWRITTEN +// @generated +// + +#import +#import "PlankModelRuntime.h" +@class OneofObjectBuilder; + +NS_ASSUME_NONNULL_BEGIN + +@interface OneofObject : NSObject +@property (nonatomic, assign, readonly) NSInteger identifier; + ++ (NSString *)className; ++ (NSString *)polymorphicTypeIdentifier; ++ (instancetype)modelObjectWithDictionary:(NSDictionary *)dictionary; +- (instancetype)initWithModelDictionary:(NS_VALID_UNTIL_END_OF_SCOPE NSDictionary *)modelDictionary; +- (instancetype)initWithBuilder:(OneofObjectBuilder *)builder; +- (instancetype)initWithBuilder:(OneofObjectBuilder *)builder initType:(PlankModelInitType)initType; +- (instancetype)copyWithBlock:(PLANK_NOESCAPE void (^)(OneofObjectBuilder *builder))block; +- (BOOL)isEqualToOneofObject:(OneofObject *)anObject; +- (instancetype)mergeWithModel:(OneofObject *)modelObject; +- (instancetype)mergeWithModel:(OneofObject *)modelObject initType:(PlankModelInitType)initType; +- (NSDictionary *)dictionaryObjectRepresentation; +- (BOOL)isIdentifierSet; +@end + +@interface OneofObjectBuilder : NSObject +@property (nonatomic, assign, readwrite) NSInteger identifier; + +- (instancetype)initWithModel:(OneofObject *)modelObject; +- (OneofObject *)build; +- (void)mergeWithModel:(OneofObject *)modelObject; +@end + +NS_ASSUME_NONNULL_END diff --git a/Examples/JS/flow/EverythingType.js b/Examples/JS/flow/EverythingType.js index f4e57cac..72c06778 100644 --- a/Examples/JS/flow/EverythingType.js +++ b/Examples/JS/flow/EverythingType.js @@ -11,12 +11,13 @@ import type { PlankDate, PlankURI } from './runtime.flow.js'; import type { BoardType } from './BoardType.js'; import type { ImageType } from './ImageType.js'; import type { Nested } from './Nested.js'; +import type { OneofObject } from './OneofObject.js'; import type { PinType } from './PinType.js'; import type { UserType } from './UserType.js'; export type EverythingMapPolymorphicValuesType = UserType | BoardType | ImageType | PinType | EverythingType | Array<*> | {}; -export type EverythingPolymorphicPropType = UserType | BoardType | ImageType | PinType | EverythingType | string | boolean | number | number | PlankDate | PlankURI; +export type EverythingPolymorphicPropType = UserType | BoardType | ImageType | PinType | EverythingType | OneofObjectType | string | boolean | number | number | PlankDate | PlankURI; export type EverythingCharEnum = | -1 /* char_case_1 */ diff --git a/Examples/JS/flow/OneofObjectType.js b/Examples/JS/flow/OneofObjectType.js new file mode 100644 index 00000000..9f7f18e3 --- /dev/null +++ b/Examples/JS/flow/OneofObjectType.js @@ -0,0 +1,18 @@ +// @flow +// +// OneofObjectType.js +// Autogenerated by Plank (https://pinterest.github.io/plank/) +// +// DO NOT EDIT - EDITS WILL BE OVERWRITTEN +// @generated +// + +import type { PlankDate, PlankURI } from './runtime.flow.js'; + + +export type OneofObjectType = $Shape<{| + +id: number, +|}> & { + id: string +}; + diff --git a/Examples/Java/Sources/Everything.java b/Examples/Java/Sources/Everything.java index 9831aff5..9a6858eb 100644 --- a/Examples/Java/Sources/Everything.java +++ b/Examples/Java/Sources/Everything.java @@ -2152,12 +2152,13 @@ public static final class EverythingPolymorphicProp { private @Nullable Image value2; private @Nullable Pin value3; private @Nullable Everything value4; - private @Nullable String value5; - private @Nullable Boolean value6; - private @Nullable Integer value7; - private @Nullable Double value8; - private @Nullable Date value9; - private @Nullable String value10; + private @Nullable OneofObject value5; + private @Nullable String value6; + private @Nullable Boolean value7; + private @Nullable Integer value8; + private @Nullable Double value9; + private @Nullable Date value10; + private @Nullable String value11; private EverythingPolymorphicProp() { } @@ -2182,30 +2183,34 @@ public EverythingPolymorphicProp(@NonNull Everything value) { this.value4 = value; } - public EverythingPolymorphicProp(@NonNull String value) { + public EverythingPolymorphicProp(@NonNull OneofObject value) { this.value5 = value; } - public EverythingPolymorphicProp(@NonNull Boolean value) { + public EverythingPolymorphicProp(@NonNull String value) { this.value6 = value; } - public EverythingPolymorphicProp(@NonNull Integer value) { + public EverythingPolymorphicProp(@NonNull Boolean value) { this.value7 = value; } - public EverythingPolymorphicProp(@NonNull Double value) { + public EverythingPolymorphicProp(@NonNull Integer value) { this.value8 = value; } - public EverythingPolymorphicProp(@NonNull Date value) { + public EverythingPolymorphicProp(@NonNull Double value) { this.value9 = value; } - public EverythingPolymorphicProp(@NonNull String value) { + public EverythingPolymorphicProp(@NonNull Date value) { this.value10 = value; } + public EverythingPolymorphicProp(@NonNull String value) { + this.value11 = value; + } + @Nullable public R matchEverythingPolymorphicProp(EverythingPolymorphicPropMatcher matcher) { if (value0 != null) { @@ -2241,6 +2246,9 @@ public R matchEverythingPolymorphicProp(EverythingPolymorphicPropMatcher if (value10 != null) { return matcher.match(value10); } + if (value11 != null) { + return matcher.match(value11); + } return null; } @@ -2264,6 +2272,7 @@ private static class EverythingPolymorphicPropTypeAdapter extends TypeAdapter imageTypeAdapter; private TypeAdapter pinTypeAdapter; private TypeAdapter everythingTypeAdapter; + private TypeAdapter oneofObjectTypeAdapter; private TypeAdapter stringTypeAdapter; private TypeAdapter booleanTypeAdapter; private TypeAdapter integerTypeAdapter; @@ -2339,12 +2348,13 @@ public interface EverythingPolymorphicPropMatcher { R match(@NonNull Image value2); R match(@NonNull Pin value3); R match(@NonNull Everything value4); - R match(@NonNull String value5); - R match(@NonNull Boolean value6); - R match(@NonNull Integer value7); - R match(@NonNull Double value8); - R match(@NonNull Date value9); - R match(@NonNull String value10); + R match(@NonNull OneofObject value5); + R match(@NonNull String value6); + R match(@NonNull Boolean value7); + R match(@NonNull Integer value8); + R match(@NonNull Double value9); + R match(@NonNull Date value10); + R match(@NonNull String value11); } } } diff --git a/Examples/Java/Sources/OneofObject.java b/Examples/Java/Sources/OneofObject.java new file mode 100644 index 00000000..ab45aac5 --- /dev/null +++ b/Examples/Java/Sources/OneofObject.java @@ -0,0 +1,193 @@ +// +// OneofObject.java +// Autogenerated by Plank (https://pinterest.github.io/plank/) +// +// DO NOT EDIT - EDITS WILL BE OVERWRITTEN +// @generated +// + +package com.pinterest.models; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import com.google.gson.Gson; +import com.google.gson.TypeAdapter; +import com.google.gson.TypeAdapterFactory; +import com.google.gson.annotations.SerializedName; +import com.google.gson.reflect.TypeToken; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonToken; +import com.google.gson.stream.JsonWriter; +import java.io.IOException; +import java.util.Objects; + +public class OneofObject { + + public static final String TYPE = "oneof_object"; + + @SerializedName("id") private @Nullable Integer uid; + + private static final int ID_INDEX = 0; + + private boolean[] _bits; + + private OneofObject( + @Nullable Integer uid, + boolean[] _bits + ) { + this.uid = uid; + this._bits = _bits; + } + + @NonNull + public static OneofObject.Builder builder() { + return new OneofObject.Builder(); + } + + @NonNull + public OneofObject.Builder toBuilder() { + return new OneofObject.Builder(this); + } + + @NonNull + public OneofObject mergeFrom(@NonNull OneofObject model) { + OneofObject.Builder builder = this.toBuilder(); + builder.mergeFrom(model); + return builder.build(); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + OneofObject that = (OneofObject) o; + return Objects.equals(this.uid, that.uid); + } + + @Override + public int hashCode() { + return Objects.hash(uid); + } + + @NonNull + public Integer getUid() { + return this.uid == null ? 0 : this.uid; + } + + public boolean getUidIsSet() { + return this._bits.length > ID_INDEX && this._bits[ID_INDEX]; + } + + public static class Builder { + + private @Nullable Integer uid; + + private boolean[] _bits; + + private Builder() { + this._bits = new boolean[1]; + } + + private Builder(@NonNull OneofObject model) { + this.uid = model.uid; + this._bits = model._bits; + } + + @NonNull + public Builder setUid(@Nullable Integer value) { + this.uid = value; + if (this._bits.length > ID_INDEX) { + this._bits[ID_INDEX] = true; + } + return this; + } + + public @Nullable Integer getUid() { + return this.uid; + } + + @NonNull + public OneofObject build() { + return new OneofObject( + this.uid, + this._bits + ); + } + + public void mergeFrom(@NonNull OneofObject model) { + if (model._bits.length > ID_INDEX && model._bits[ID_INDEX]) { + this.uid = model.uid; + this._bits[ID_INDEX] = true; + } + } + } + + public static class OneofObjectTypeAdapterFactory implements TypeAdapterFactory { + + @Nullable + @Override + public TypeAdapter create(@NonNull Gson gson, @NonNull TypeToken typeToken) { + if (!OneofObject.class.isAssignableFrom(typeToken.getRawType())) { + return null; + } + return (TypeAdapter) new OneofObjectTypeAdapter(gson); + } + } + + private static class OneofObjectTypeAdapter extends TypeAdapter { + + private final Gson gson; + private TypeAdapter integerTypeAdapter; + + OneofObjectTypeAdapter(Gson gson) { + this.gson = gson; + } + + @Override + public void write(@NonNull JsonWriter writer, OneofObject value) throws IOException { + if (value == null) { + writer.nullValue(); + return; + } + writer.beginObject(); + if (value._bits.length > ID_INDEX && value._bits[ID_INDEX]) { + if (this.integerTypeAdapter == null) { + this.integerTypeAdapter = this.gson.getAdapter(Integer.class).nullSafe(); + } + this.integerTypeAdapter.write(writer.name("id"), value.uid); + } + writer.endObject(); + } + + @Nullable + @Override + public OneofObject read(@NonNull JsonReader reader) throws IOException { + if (reader.peek() == JsonToken.NULL) { + reader.nextNull(); + return null; + } + Builder builder = OneofObject.builder(); + reader.beginObject(); + while (reader.hasNext()) { + String name = reader.nextName(); + switch (name) { + case ("id"): + if (this.integerTypeAdapter == null) { + this.integerTypeAdapter = this.gson.getAdapter(Integer.class).nullSafe(); + } + builder.setUid(this.integerTypeAdapter.read(reader)); + break; + default: + reader.skipValue(); + break; + } + } + reader.endObject(); + return builder.build(); + } + } +} diff --git a/Examples/PDK/everything.json b/Examples/PDK/everything.json index 51e0218d..ccdf4f48 100644 --- a/Examples/PDK/everything.json +++ b/Examples/PDK/everything.json @@ -162,6 +162,7 @@ { "$ref" : "image.json" }, { "$ref" : "pin.json" }, { "$ref" : "everything.json" }, + { "type" : "object", "title": "oneof_object", "properties": {"id": {"type": "integer"} } }, { "type" : "string" }, { "type" : "boolean" }, { "type" : "integer" }, diff --git a/Sources/Core/Schema.swift b/Sources/Core/Schema.swift index c3d10f87..30cea978 100644 --- a/Sources/Core/Schema.swift +++ b/Sources/Core/Schema.swift @@ -270,6 +270,8 @@ extension Schema { return itemType?.objectRoots() ?? [] case let .map(valueType: valueType): return valueType?.objectRoots() ?? [] + case let .oneOf(types: types): + return types.map { type in type.objectRoots() }.reduce([]) { $0.union($1) } default: return [] }