From 53cbdeaf7472d71a5b28d3feed086d3305a6d3a6 Mon Sep 17 00:00:00 2001 From: feldspar Date: Fri, 27 Feb 2026 13:50:06 +0300 Subject: [PATCH] Nested types fix commit_hash:e1fb78090d0820084061470a69d2bc8fe6685d6a --- .mapping.json | 5 + .../generators/swift/generator.py | 8 +- .../generators/swift/swift_entities.py | 6 +- .../not_templates_swift/Entity.swift | 3 +- .../not_templates_swift/EntityWithArray.swift | 2 +- .../EntityWithArrayOfNestedItems.swift | 4 +- .../EntityWithComplexProperty.swift | 2 +- .../EnumWithDefaultType.swift | 3 +- .../tests/references/swift/Entity.swift | 3 +- .../references/swift/EntityTemplate.swift | 2 +- .../references/swift/EntityWithArray.swift | 2 +- .../swift/EntityWithArrayOfNestedItems.swift | 4 +- .../swift/EntityWithComplexProperty.swift | 2 +- .../swift/EnumWithDefaultType.swift | 3 +- .../swift/EnumWithDefaultTypeTemplate.swift | 2 +- .../DivData/DivDataExtensions.swift | 46 +-- .../UntypedDivTemplateResolver.swift | 265 ++++++++---------- client/ios/DivKit/generated_sources/Div.swift | 3 +- .../DivActionArrayInsertValue.swift | 2 +- .../DivActionArraySetValue.swift | 2 +- .../DivActionCopyToClipboard.swift | 2 +- .../DivActionCopyToClipboardContent.swift | 3 +- ...ActionCopyToClipboardContentTemplate.swift | 2 +- .../DivActionScrollDestination.swift | 3 +- .../DivActionScrollDestinationTemplate.swift | 2 +- .../generated_sources/DivActionScrollTo.swift | 2 +- .../DivActionSetStoredValue.swift | 2 +- .../DivActionSetVariable.swift | 2 +- .../generated_sources/DivActionSubmit.swift | 2 +- .../generated_sources/DivActionTyped.swift | 3 +- .../DivActionTypedTemplate.swift | 2 +- .../DivActionUpdateStructure.swift | 2 +- .../generated_sources/DivAnimator.swift | 3 +- .../DivAnimatorTemplate.swift | 2 +- .../DivAppearanceSetTransition.swift | 2 +- .../DivAppearanceTransition.swift | 3 +- .../DivAppearanceTransitionTemplate.swift | 2 +- .../generated_sources/DivBackground.swift | 3 +- .../DivBackgroundTemplate.swift | 2 +- .../DivChangeSetTransition.swift | 2 +- .../DivChangeTransition.swift | 3 +- .../DivChangeTransitionTemplate.swift | 2 +- .../DivCollectionItemBuilder.swift | 4 +- .../generated_sources/DivContainer.swift | 2 +- .../DivKit/generated_sources/DivCount.swift | 3 +- .../generated_sources/DivCountTemplate.swift | 2 +- .../DivKit/generated_sources/DivData.swift | 4 +- .../generated_sources/DivDrawable.swift | 3 +- .../DivDrawableTemplate.swift | 2 +- .../DivKit/generated_sources/DivFilter.swift | 3 +- .../generated_sources/DivFilterTemplate.swift | 2 +- .../DivFixedLengthInputMask.swift | 2 +- .../generated_sources/DivFunction.swift | 2 +- .../DivIndicatorItemPlacement.swift | 3 +- .../DivIndicatorItemPlacementTemplate.swift | 2 +- .../generated_sources/DivInputFilter.swift | 3 +- .../DivInputFilterTemplate.swift | 2 +- .../generated_sources/DivInputMask.swift | 3 +- .../DivInputMaskTemplate.swift | 2 +- .../generated_sources/DivInputValidator.swift | 3 +- .../DivInputValidatorTemplate.swift | 2 +- .../DivNeighbourPageSize.swift | 2 +- .../DivNinePatchBackground.swift | 2 +- .../generated_sources/DivPageSize.swift | 2 +- .../DivPageTransformation.swift | 3 +- .../DivPageTransformationTemplate.swift | 2 +- .../DivKit/generated_sources/DivPager.swift | 2 +- .../DivPagerLayoutMode.swift | 3 +- .../DivPagerLayoutModeTemplate.swift | 2 +- .../DivKit/generated_sources/DivPatch.swift | 2 +- .../DivKit/generated_sources/DivPivot.swift | 3 +- .../generated_sources/DivPivotTemplate.swift | 2 +- .../DivKit/generated_sources/DivPoint.swift | 4 +- .../DivRadialGradientCenter.swift | 3 +- .../DivRadialGradientCenterTemplate.swift | 2 +- .../DivRadialGradientRadius.swift | 3 +- .../DivRadialGradientRadiusTemplate.swift | 2 +- .../DivKit/generated_sources/DivSelect.swift | 2 +- .../DivKit/generated_sources/DivShadow.swift | 2 +- .../DivKit/generated_sources/DivShape.swift | 3 +- .../generated_sources/DivShapeDrawable.swift | 2 +- .../generated_sources/DivShapeTemplate.swift | 2 +- .../DivKit/generated_sources/DivSize.swift | 3 +- .../generated_sources/DivSizeTemplate.swift | 2 +- .../DivKit/generated_sources/DivSlider.swift | 6 +- .../DivKit/generated_sources/DivState.swift | 2 +- .../generated_sources/DivStrokeStyle.swift | 3 +- .../DivStrokeStyleTemplate.swift | 2 +- .../DivKit/generated_sources/DivTabs.swift | 4 +- .../generated_sources/DivTemplate.swift | 2 +- .../generated_sources/DivTextGradient.swift | 3 +- .../DivTextGradientTemplate.swift | 2 +- .../DivTextRangeBackground.swift | 3 +- .../DivTextRangeBackgroundTemplate.swift | 2 +- .../generated_sources/DivTextRangeMask.swift | 3 +- .../DivTextRangeMaskTemplate.swift | 2 +- .../DivKit/generated_sources/DivTooltip.swift | 2 +- .../generated_sources/DivTooltipMode.swift | 3 +- .../DivTooltipModeTemplate.swift | 2 +- .../generated_sources/DivTransformation.swift | 3 +- .../DivTransformationTemplate.swift | 2 +- .../generated_sources/DivTranslation.swift | 3 +- .../DivTranslationTemplate.swift | 2 +- .../DivKit/generated_sources/DivTrigger.swift | 2 +- .../generated_sources/DivTypedValue.swift | 3 +- .../DivTypedValueTemplate.swift | 2 +- .../generated_sources/DivVariable.swift | 3 +- .../DivVariableTemplate.swift | 2 +- .../DivKit/generated_sources/DivVideo.swift | 2 +- .../Entities/generated_sources/Entity.swift | 3 +- .../generated_sources/EntityTemplate.swift | 2 +- .../generated_sources/EntityWithArray.swift | 2 +- .../EntityWithArrayOfNestedItems.swift | 4 +- .../EntityWithComplexProperty.swift | 2 +- .../EnumWithDefaultType.swift | 3 +- .../EnumWithDefaultTypeTemplate.swift | 2 +- client/ios/Serialization/Deserializable.swift | 15 +- .../Dictionary+Serialization.swift | 156 ++++++++++- .../cross_level_link_resolution_in_items.json | 57 ++++ .../templates/deeply_nested_card.json | 48 ++++ .../templates/nested_template_usage.json | 54 ++++ ...ate_name_collision_in_nested_property.json | 40 +++ ..._single_level_link_in_nested_template.json | 52 ++++ 123 files changed, 701 insertions(+), 328 deletions(-) create mode 100644 test_data/parsing_test_data/templates/cross_level_link_resolution_in_items.json create mode 100644 test_data/parsing_test_data/templates/deeply_nested_card.json create mode 100644 test_data/parsing_test_data/templates/nested_template_usage.json create mode 100644 test_data/parsing_test_data/templates/template_name_collision_in_nested_property.json create mode 100644 test_data/parsing_test_data/templates/with_single_level_link_in_nested_template.json diff --git a/.mapping.json b/.mapping.json index d1d689490..7586dbaca 100644 --- a/.mapping.json +++ b/.mapping.json @@ -24691,12 +24691,16 @@ "test_data/parsing_test_data/invalid_value_replaced_with_default_value.json":"divkit/public/test_data/parsing_test_data/invalid_value_replaced_with_default_value.json", "test_data/parsing_test_data/required_property_value_is_missing.json":"divkit/public/test_data/parsing_test_data/required_property_value_is_missing.json", "test_data/parsing_test_data/simple_values.json":"divkit/public/test_data/parsing_test_data/simple_values.json", + "test_data/parsing_test_data/templates/cross_level_link_resolution_in_items.json":"divkit/public/test_data/parsing_test_data/templates/cross_level_link_resolution_in_items.json", + "test_data/parsing_test_data/templates/deeply_nested_card.json":"divkit/public/test_data/parsing_test_data/templates/deeply_nested_card.json", "test_data/parsing_test_data/templates/direct_value_overrides_link.json":"divkit/public/test_data/parsing_test_data/templates/direct_value_overrides_link.json", "test_data/parsing_test_data/templates/invalid_value_replaced_with_default_value_in_div_text.json":"divkit/public/test_data/parsing_test_data/templates/invalid_value_replaced_with_default_value_in_div_text.json", "test_data/parsing_test_data/templates/link_is_overridden_in_derived_template.json":"divkit/public/test_data/parsing_test_data/templates/link_is_overridden_in_derived_template.json", + "test_data/parsing_test_data/templates/nested_template_usage.json":"divkit/public/test_data/parsing_test_data/templates/nested_template_usage.json", "test_data/parsing_test_data/templates/same_link_used_in_two_places.json":"divkit/public/test_data/parsing_test_data/templates/same_link_used_in_two_places.json", "test_data/parsing_test_data/templates/simple.json":"divkit/public/test_data/parsing_test_data/templates/simple.json", "test_data/parsing_test_data/templates/template_chain.json":"divkit/public/test_data/parsing_test_data/templates/template_chain.json", + "test_data/parsing_test_data/templates/template_name_collision_in_nested_property.json":"divkit/public/test_data/parsing_test_data/templates/template_name_collision_in_nested_property.json", "test_data/parsing_test_data/templates/transitive_template_dependencies_in_items.json":"divkit/public/test_data/parsing_test_data/templates/transitive_template_dependencies_in_items.json", "test_data/parsing_test_data/templates/unresolved_link_for_optional_field.json":"divkit/public/test_data/parsing_test_data/templates/unresolved_link_for_optional_field.json", "test_data/parsing_test_data/templates/with_array_link.json":"divkit/public/test_data/parsing_test_data/templates/with_array_link.json", @@ -24705,6 +24709,7 @@ "test_data/parsing_test_data/templates/with_nested_object.json":"divkit/public/test_data/parsing_test_data/templates/with_nested_object.json", "test_data/parsing_test_data/templates/with_override.json":"divkit/public/test_data/parsing_test_data/templates/with_override.json", "test_data/parsing_test_data/templates/with_parent_template_with_link.json":"divkit/public/test_data/parsing_test_data/templates/with_parent_template_with_link.json", + "test_data/parsing_test_data/templates/with_single_level_link_in_nested_template.json":"divkit/public/test_data/parsing_test_data/templates/with_single_level_link_in_nested_template.json", "test_data/perf_test_data/expressions.json":"divkit/public/test_data/perf_test_data/expressions.json", "test_data/perf_test_data/prototypes.json":"divkit/public/test_data/perf_test_data/prototypes.json", "test_data/perf_test_data/scroll_default.json":"divkit/public/test_data/perf_test_data/scroll_default.json", diff --git a/api_generator/api_generator/generators/swift/generator.py b/api_generator/api_generator/generators/swift/generator.py index b6a216d3d..64efeed8c 100644 --- a/api_generator/api_generator/generators/swift/generator.py +++ b/api_generator/api_generator/generators/swift/generator.py @@ -159,8 +159,11 @@ class SwiftGenerator(Generator): if entity_enumeration.mode.is_template: body += 'let receivedType = try dictionary.getField("type") as String' body += 'let blockType = templateToType[receivedType] ?? receivedType' + dict_var = 'dictionary' else: + body += 'let dictionary = context.templateResolver?(dictionary) ?? dictionary' body += 'let blockType = try dictionary.getField("type") as String' + dict_var = 'dictionary' body += 'switch blockType {' entity_names = entity_enumeration.entity_names for entity, name in zip(entity_enumeration.entities, entity_names): @@ -169,10 +172,9 @@ class SwiftGenerator(Generator): args = swift_template_deserializable_args(entity_enumeration.mode) context_param = '' if entity_enumeration.mode.is_template else ', context: context' body += f'case {obj_t}.type:' - body += f' self = .{low_name}(try {obj_t}(dictionary: dictionary{args}{context_param}))' + body += f' self = .{low_name}(try {obj_t}(dictionary: {dict_var}{args}{context_param}))' body += 'default:' - args = f'field: "{entity_enumeration.name}", representation: dictionary' - body += f' throw DeserializationError.invalidFieldRepresentation({args})' + body += ' throw DeserializationError.requiredFieldIsMissing(field: "type")' body += '}' deserializable_extension += body.indented(level=2) deserializable_extension += ' }' diff --git a/api_generator/api_generator/generators/swift/swift_entities.py b/api_generator/api_generator/generators/swift/swift_entities.py index 4caab2a85..b2dd672db 100644 --- a/api_generator/api_generator/generators/swift/swift_entities.py +++ b/api_generator/api_generator/generators/swift/swift_entities.py @@ -603,6 +603,8 @@ class SwiftProperty(Property): validator_arg_string = self.validator_arg(entity_name='Self', mode=mode) declaration_mode = SwiftProperty.SwiftMode(value=mode, use_expressions=False) + context_suffix = ', context: context' if not self.parsed_value_is_optional else '' + if isinstance(self.property_type, Array): item_type = cast(SwiftPropertyType, self.property_type.property_type).prefixed_declaration( declaration_mode @@ -611,7 +613,7 @@ class SwiftProperty(Property): expr = ( f'"{self.dict_field}", transform: ' f'{{ (dict: [String: Any]) in try? {item_type}(dictionary: dict, context: context) }}' - f'{validator_arg_string}' + f'{validator_arg_string}{context_suffix}' ) return f'get{optional_suffix}Array({expr})' @@ -622,7 +624,7 @@ class SwiftProperty(Property): expr = ( f'"{self.dict_field}", transform: ' f'{{ (dict: [String: Any]) in try {value_type}(dictionary: dict, context: context) }}' - f'{validator_arg_string}' + f'{validator_arg_string}{context_suffix}' ) return f'get{optional_suffix}Field({expr})' diff --git a/api_generator/tests/references/not_templates_swift/Entity.swift b/api_generator/tests/references/not_templates_swift/Entity.swift index 41c161223..27810dba0 100644 --- a/api_generator/tests/references/not_templates_swift/Entity.swift +++ b/api_generator/tests/references/not_templates_swift/Entity.swift @@ -72,6 +72,7 @@ public enum Entity: Sendable { extension Entity { public init(dictionary: [String: Any], context: ParsingContext) throws { + let dictionary = context.templateResolver?(dictionary) ?? dictionary let blockType = try dictionary.getField("type") as String switch blockType { case EntityWithArray.type: @@ -113,7 +114,7 @@ extension Entity { case EntityWithoutProperties.type: self = .entityWithoutProperties(try EntityWithoutProperties(dictionary: dictionary, context: context)) default: - throw DeserializationError.invalidFieldRepresentation(field: "entity", representation: dictionary) + throw DeserializationError.requiredFieldIsMissing(field: "type") } } } diff --git a/api_generator/tests/references/not_templates_swift/EntityWithArray.swift b/api_generator/tests/references/not_templates_swift/EntityWithArray.swift index 0d5376df9..e5484a26e 100644 --- a/api_generator/tests/references/not_templates_swift/EntityWithArray.swift +++ b/api_generator/tests/references/not_templates_swift/EntityWithArray.swift @@ -13,7 +13,7 @@ public final class EntityWithArray: Sendable { public convenience init(dictionary: [String: Any], context: ParsingContext) throws { self.init( - array: try dictionary.getArray("array", transform: { (dict: [String: Any]) in try? Entity(dictionary: dict, context: context) }, validator: Self.arrayValidator) + array: try dictionary.getArray("array", transform: { (dict: [String: Any]) in try? Entity(dictionary: dict, context: context) }, validator: Self.arrayValidator, context: context) ) } diff --git a/api_generator/tests/references/not_templates_swift/EntityWithArrayOfNestedItems.swift b/api_generator/tests/references/not_templates_swift/EntityWithArrayOfNestedItems.swift index 2edd1e5fc..6075e67d8 100644 --- a/api_generator/tests/references/not_templates_swift/EntityWithArrayOfNestedItems.swift +++ b/api_generator/tests/references/not_templates_swift/EntityWithArrayOfNestedItems.swift @@ -15,7 +15,7 @@ public final class EntityWithArrayOfNestedItems: Sendable { public convenience init(dictionary: [String: Any], context: ParsingContext) throws { self.init( - entity: try dictionary.getField("entity", transform: { (dict: [String: Any]) in try Entity(dictionary: dict, context: context) }), + entity: try dictionary.getField("entity", transform: { (dict: [String: Any]) in try Entity(dictionary: dict, context: context) }, context: context), property: try dictionary.getExpressionField("property", context: context) ) } @@ -37,7 +37,7 @@ public final class EntityWithArrayOfNestedItems: Sendable { public convenience init(dictionary: [String: Any], context: ParsingContext) throws { self.init( - items: try dictionary.getArray("items", transform: { (dict: [String: Any]) in try? EntityWithArrayOfNestedItems.Item(dictionary: dict, context: context) }, validator: Self.itemsValidator) + items: try dictionary.getArray("items", transform: { (dict: [String: Any]) in try? EntityWithArrayOfNestedItems.Item(dictionary: dict, context: context) }, validator: Self.itemsValidator, context: context) ) } diff --git a/api_generator/tests/references/not_templates_swift/EntityWithComplexProperty.swift b/api_generator/tests/references/not_templates_swift/EntityWithComplexProperty.swift index d7e0b31da..9542c6b65 100644 --- a/api_generator/tests/references/not_templates_swift/EntityWithComplexProperty.swift +++ b/api_generator/tests/references/not_templates_swift/EntityWithComplexProperty.swift @@ -30,7 +30,7 @@ public final class EntityWithComplexProperty: Sendable { public convenience init(dictionary: [String: Any], context: ParsingContext) throws { self.init( - property: try dictionary.getField("property", transform: { (dict: [String: Any]) in try EntityWithComplexProperty.Property(dictionary: dict, context: context) }) + property: try dictionary.getField("property", transform: { (dict: [String: Any]) in try EntityWithComplexProperty.Property(dictionary: dict, context: context) }, context: context) ) } diff --git a/api_generator/tests/references/not_templates_swift/EnumWithDefaultType.swift b/api_generator/tests/references/not_templates_swift/EnumWithDefaultType.swift index 0805b08b0..ce3e54603 100644 --- a/api_generator/tests/references/not_templates_swift/EnumWithDefaultType.swift +++ b/api_generator/tests/references/not_templates_swift/EnumWithDefaultType.swift @@ -21,6 +21,7 @@ public enum EnumWithDefaultType: Sendable { extension EnumWithDefaultType { public init(dictionary: [String: Any], context: ParsingContext) throws { + let dictionary = context.templateResolver?(dictionary) ?? dictionary let blockType = try dictionary.getField("type") as String switch blockType { case WithDefault.type: @@ -28,7 +29,7 @@ extension EnumWithDefaultType { case WithoutDefault.type: self = .withoutDefault(try WithoutDefault(dictionary: dictionary, context: context)) default: - throw DeserializationError.invalidFieldRepresentation(field: "enum_with_default_type", representation: dictionary) + throw DeserializationError.requiredFieldIsMissing(field: "type") } } } diff --git a/api_generator/tests/references/swift/Entity.swift b/api_generator/tests/references/swift/Entity.swift index 41c161223..27810dba0 100644 --- a/api_generator/tests/references/swift/Entity.swift +++ b/api_generator/tests/references/swift/Entity.swift @@ -72,6 +72,7 @@ public enum Entity: Sendable { extension Entity { public init(dictionary: [String: Any], context: ParsingContext) throws { + let dictionary = context.templateResolver?(dictionary) ?? dictionary let blockType = try dictionary.getField("type") as String switch blockType { case EntityWithArray.type: @@ -113,7 +114,7 @@ extension Entity { case EntityWithoutProperties.type: self = .entityWithoutProperties(try EntityWithoutProperties(dictionary: dictionary, context: context)) default: - throw DeserializationError.invalidFieldRepresentation(field: "entity", representation: dictionary) + throw DeserializationError.requiredFieldIsMissing(field: "type") } } } diff --git a/api_generator/tests/references/swift/EntityTemplate.swift b/api_generator/tests/references/swift/EntityTemplate.swift index 2f64a3b89..9ed4ec012 100644 --- a/api_generator/tests/references/swift/EntityTemplate.swift +++ b/api_generator/tests/references/swift/EntityTemplate.swift @@ -485,7 +485,7 @@ extension EntityTemplate { case EntityWithoutPropertiesTemplate.type: self = .entityWithoutPropertiesTemplate(try EntityWithoutPropertiesTemplate(dictionary: dictionary, templateToType: templateToType)) default: - throw DeserializationError.invalidFieldRepresentation(field: "entity_template", representation: dictionary) + throw DeserializationError.requiredFieldIsMissing(field: "type") } } } diff --git a/api_generator/tests/references/swift/EntityWithArray.swift b/api_generator/tests/references/swift/EntityWithArray.swift index 0d5376df9..e5484a26e 100644 --- a/api_generator/tests/references/swift/EntityWithArray.swift +++ b/api_generator/tests/references/swift/EntityWithArray.swift @@ -13,7 +13,7 @@ public final class EntityWithArray: Sendable { public convenience init(dictionary: [String: Any], context: ParsingContext) throws { self.init( - array: try dictionary.getArray("array", transform: { (dict: [String: Any]) in try? Entity(dictionary: dict, context: context) }, validator: Self.arrayValidator) + array: try dictionary.getArray("array", transform: { (dict: [String: Any]) in try? Entity(dictionary: dict, context: context) }, validator: Self.arrayValidator, context: context) ) } diff --git a/api_generator/tests/references/swift/EntityWithArrayOfNestedItems.swift b/api_generator/tests/references/swift/EntityWithArrayOfNestedItems.swift index 2edd1e5fc..6075e67d8 100644 --- a/api_generator/tests/references/swift/EntityWithArrayOfNestedItems.swift +++ b/api_generator/tests/references/swift/EntityWithArrayOfNestedItems.swift @@ -15,7 +15,7 @@ public final class EntityWithArrayOfNestedItems: Sendable { public convenience init(dictionary: [String: Any], context: ParsingContext) throws { self.init( - entity: try dictionary.getField("entity", transform: { (dict: [String: Any]) in try Entity(dictionary: dict, context: context) }), + entity: try dictionary.getField("entity", transform: { (dict: [String: Any]) in try Entity(dictionary: dict, context: context) }, context: context), property: try dictionary.getExpressionField("property", context: context) ) } @@ -37,7 +37,7 @@ public final class EntityWithArrayOfNestedItems: Sendable { public convenience init(dictionary: [String: Any], context: ParsingContext) throws { self.init( - items: try dictionary.getArray("items", transform: { (dict: [String: Any]) in try? EntityWithArrayOfNestedItems.Item(dictionary: dict, context: context) }, validator: Self.itemsValidator) + items: try dictionary.getArray("items", transform: { (dict: [String: Any]) in try? EntityWithArrayOfNestedItems.Item(dictionary: dict, context: context) }, validator: Self.itemsValidator, context: context) ) } diff --git a/api_generator/tests/references/swift/EntityWithComplexProperty.swift b/api_generator/tests/references/swift/EntityWithComplexProperty.swift index d7e0b31da..9542c6b65 100644 --- a/api_generator/tests/references/swift/EntityWithComplexProperty.swift +++ b/api_generator/tests/references/swift/EntityWithComplexProperty.swift @@ -30,7 +30,7 @@ public final class EntityWithComplexProperty: Sendable { public convenience init(dictionary: [String: Any], context: ParsingContext) throws { self.init( - property: try dictionary.getField("property", transform: { (dict: [String: Any]) in try EntityWithComplexProperty.Property(dictionary: dict, context: context) }) + property: try dictionary.getField("property", transform: { (dict: [String: Any]) in try EntityWithComplexProperty.Property(dictionary: dict, context: context) }, context: context) ) } diff --git a/api_generator/tests/references/swift/EnumWithDefaultType.swift b/api_generator/tests/references/swift/EnumWithDefaultType.swift index 0805b08b0..ce3e54603 100644 --- a/api_generator/tests/references/swift/EnumWithDefaultType.swift +++ b/api_generator/tests/references/swift/EnumWithDefaultType.swift @@ -21,6 +21,7 @@ public enum EnumWithDefaultType: Sendable { extension EnumWithDefaultType { public init(dictionary: [String: Any], context: ParsingContext) throws { + let dictionary = context.templateResolver?(dictionary) ?? dictionary let blockType = try dictionary.getField("type") as String switch blockType { case WithDefault.type: @@ -28,7 +29,7 @@ extension EnumWithDefaultType { case WithoutDefault.type: self = .withoutDefault(try WithoutDefault(dictionary: dictionary, context: context)) default: - throw DeserializationError.invalidFieldRepresentation(field: "enum_with_default_type", representation: dictionary) + throw DeserializationError.requiredFieldIsMissing(field: "type") } } } diff --git a/api_generator/tests/references/swift/EnumWithDefaultTypeTemplate.swift b/api_generator/tests/references/swift/EnumWithDefaultTypeTemplate.swift index f56d73f82..115413dee 100644 --- a/api_generator/tests/references/swift/EnumWithDefaultTypeTemplate.swift +++ b/api_generator/tests/references/swift/EnumWithDefaultTypeTemplate.swift @@ -93,7 +93,7 @@ extension EnumWithDefaultTypeTemplate { case WithoutDefaultTemplate.type: self = .withoutDefaultTemplate(try WithoutDefaultTemplate(dictionary: dictionary, templateToType: templateToType)) default: - throw DeserializationError.invalidFieldRepresentation(field: "enum_with_default_type_template", representation: dictionary) + throw DeserializationError.requiredFieldIsMissing(field: "type") } } } diff --git a/client/ios/DivKit/Extensions/DivData/DivDataExtensions.swift b/client/ios/DivKit/Extensions/DivData/DivDataExtensions.swift index bef38f722..244c35d51 100644 --- a/client/ios/DivKit/Extensions/DivData/DivDataExtensions.swift +++ b/client/ios/DivKit/Extensions/DivData/DivDataExtensions.swift @@ -99,50 +99,30 @@ extension DivData { flagsInfo: DivFlagsInfo = .default ) -> DeserializationResult { if flagsInfo.useUntypedTemplateResolver { - var resolver = UntypedDivTemplateResolver(templates: templatesDict) - let resolvedCardResult = resolver.resolve(card: cardDict) - let parsingContext = ParsingContext() - - guard let resolvedCard = resolvedCardResult.value else { - return .failure(resolvedCardResult.errorsOrWarnings ?? NonEmptyArray(.generic)) - } + let resolver = UntypedDivTemplateResolver(templates: templatesDict) + let parsingContext = ParsingContext( + templateResolver: { resolver.resolveFlat($0) } + ) let divDataResult: DeserializationResult do { - divDataResult = try .success(DivData(dictionary: resolvedCard, context: parsingContext)) - } catch let error as DeserializationError { - divDataResult = .failure(NonEmptyArray(error)) + divDataResult = try .success(DivData(dictionary: cardDict, context: parsingContext)) } catch { - divDataResult = - .failure(NonEmptyArray(.unexpectedError(message: String(describing: error)))) + divDataResult = .noValue } - let contextWarnings: NonEmptyArray? = NonEmptyArray(parsingContext - .warnings - ) - let contextErrors: NonEmptyArray? = NonEmptyArray(parsingContext.errors) - let resolverWarnings = resolvedCardResult.warnings - - let allIssues: NonEmptyArray? = NonEmptyArray( - mergeErrors(contextWarnings, contextErrors, resolverWarnings) - ) + let contextErrors = parsingContext.errors + let contextWarnings = parsingContext.warnings switch divDataResult { - case let .success(value): - if let warnings = allIssues { + case .success(let value), .partialSuccess(let value, _): + if let warnings = NonEmptyArray(contextErrors + contextWarnings) { return .partialSuccess(value, warnings: warnings) } return .success(value) - case let .partialSuccess(value, warnings): - if let mergedWarnings = NonEmptyArray(mergeErrors(warnings, allIssues)) { - return .partialSuccess(value, warnings: mergedWarnings) - } - return .success(value) - case let .failure(errors): - return .failure(NonEmptyArray(mergeErrors(errors, allIssues))!) - case .noValue: - if let warnings = allIssues { - return .failure(warnings) + default: + if let errors = NonEmptyArray(contextErrors) { + return .failure(errors) } return .failure(NonEmptyArray(.generic)) } diff --git a/client/ios/DivKit/Templates/UntypedDivTemplateResolver.swift b/client/ios/DivKit/Templates/UntypedDivTemplateResolver.swift index b25b2b704..7e9c23f4a 100644 --- a/client/ios/DivKit/Templates/UntypedDivTemplateResolver.swift +++ b/client/ios/DivKit/Templates/UntypedDivTemplateResolver.swift @@ -2,17 +2,7 @@ import Foundation import Serialization import VGSL -struct UntypedDivTemplateResolver { - private enum Origin { - case instance - case template - } - - private struct OriginValue { - let value: Any - let origin: Origin - } - +final class UntypedDivTemplateResolver { private let templates: [TemplateName: Any] private let templateToType: [TemplateName: String] private var resolvedTemplateCache: [TemplateName: [String: Any]] = [:] @@ -24,131 +14,27 @@ struct UntypedDivTemplateResolver { templateToType = calculateTemplateToType(in: templates) } - mutating func resolve(card: [String: Any]) -> DeserializationResult<[String: Any]> { - resolveDictionary( - card, - linkSource: card, - origin: .instance - ) + func resolveFlat(_ dictionary: [String: Any]) -> [String: Any] { + guard let templateName = dictionary["type"] as? String, + templates[templateName] != nil else { + return dictionary + } + + let resolvedTemplate = resolveTemplate(named: templateName) + guard let templateValue = resolvedTemplate.value else { + return dictionary + } + + var merged = templateValue + for (key, value) in dictionary { + merged[key] = value + } + merged["type"] = templateToType[templateName] ?? templateName + + return resolveLinks(in: merged, linkSource: dictionary) } - private mutating func resolveDictionary( - _ dictionary: [String: Any], - linkSource: [String: Any], - origin: Origin - ) -> DeserializationResult<[String: Any]> { - var values: [String: OriginValue] = [:] - - if let templateName = dictionary["type"] as? String, templates[templateName] != nil { - let resolvedTemplate = resolveTemplate(named: templateName) - guard let templateValue = resolvedTemplate.value else { - return .failure(normalizedErrors(from: resolvedTemplate.errorsOrWarnings)) - } - - values = templateValue.mapValues { OriginValue(value: $0, origin: .template) } - for (key, value) in dictionary { - values[key] = OriginValue(value: value, origin: .instance) - } - values["type"] = OriginValue( - value: templateToType[templateName] ?? templateName, - origin: .template - ) - } else { - values = dictionary.mapValues { OriginValue(value: $0, origin: origin) } - } - - let currentLinkSource = origin == .instance ? dictionary : linkSource - substituteLinks(values: &values, linkSource: currentLinkSource) - - var resolved: [String: Any] = [:] - var errors: [DeserializationError] = [] - - for (key, value) in values { - guard !key.hasPrefix("$") else { continue } - - let childResult = resolveAny( - value.value, - linkSource: currentLinkSource, - origin: value.origin - ) - if let resolvedChild = childResult.value { - resolved[key] = resolvedChild - } - if let childErrors = childResult.errorsOrWarnings { - errors.append(contentsOf: childErrors.map { .nestedObjectError(field: key, error: $0) }) - } - } - - if let warnings = NonEmptyArray(errors) { - return .partialSuccess(resolved, warnings: warnings) - } - return .success(resolved) - } - - private mutating func resolveArray( - _ array: [Any], - linkSource: [String: Any], - origin: Origin - ) -> DeserializationResult<[Any]> { - var result: [Any] = [] - var errors: [DeserializationError] = [] - result.reserveCapacity(array.count) - - for index in array.indices { - let child = array[index] - let childResult: DeserializationResult - if let dictionary = child as? [String: Any] { - let childLinkSource = origin == .instance ? dictionary : linkSource - childResult = resolveDictionary( - dictionary, - linkSource: childLinkSource, - origin: origin == .instance ? .instance : .template - ).map { $0 as Any } - } else if let nestedArray = child as? [Any] { - childResult = resolveArray( - nestedArray, - linkSource: linkSource, - origin: origin - ).map { $0 as Any } - } else { - childResult = .success(child) - } - - if let value = childResult.value { - result.append(value) - } - if let childErrors = childResult.errorsOrWarnings { - errors - .append(contentsOf: childErrors.map { .nestedObjectError(field: "\(index)", error: $0) }) - } - } - - if let warnings = NonEmptyArray(errors) { - return .partialSuccess(result, warnings: warnings) - } - return .success(result) - } - - private mutating func resolveAny( - _ value: Any, - linkSource: [String: Any], - origin: Origin - ) -> DeserializationResult { - if let dictionary = value as? [String: Any] { - let childLinkSource = origin == .instance ? dictionary : linkSource - return resolveDictionary( - dictionary, - linkSource: childLinkSource, - origin: origin == .instance ? .instance : .template - ).map { $0 as Any } - } - if let array = value as? [Any] { - return resolveArray(array, linkSource: linkSource, origin: origin).map { $0 as Any } - } - return .success(value) - } - - private mutating func resolveTemplate(named templateName: TemplateName) + private func resolveTemplate(named templateName: TemplateName) -> DeserializationResult<[String: Any]> { if let cached = resolvedTemplateCache[templateName] { return .success(cached) @@ -185,15 +71,99 @@ struct UntypedDivTemplateResolver { return .success(result) } - private func substituteLinks(values: inout [String: OriginValue], linkSource: [String: Any]) { - let linkValues = values.filter { $0.key.hasPrefix("$") } - for (linkKey, linkValue) in linkValues { + private func resolveLinks( + in dictionary: [String: Any], + linkSource: [String: Any] + ) -> [String: Any] { + var dict = dictionary + let linkKeys = dict.keys.filter { $0.hasPrefix("$") } + for linkKey in linkKeys { let key = String(linkKey.dropFirst()) - guard values[key] == nil else { continue } - guard let linkName = linkValue.value as? String else { continue } + guard dict[key] == nil else { continue } + guard let linkName = dict[linkKey] as? String else { continue } guard let value = linkSource[linkName] else { continue } - values[key] = OriginValue(value: value, origin: .instance) + dict[key] = value } + + var result: [String: Any] = [:] + for (key, value) in dict { + guard !key.hasPrefix("$") else { continue } + result[key] = resolveLinksInValue(value, linkSource: linkSource) + } + return result + } + + private func resolveLinksInValue( + _ value: Any, + linkSource: [String: Any] + ) -> Any { + if let dict = value as? [String: Any] { + if let type = dict["type"] as? String, + let resolvedTemplate = resolveTemplate(named: type).value { + let parameterNames = collectParameterNames(from: resolvedTemplate) + return resolveInstanceLinks( + in: dict, + linkSource: linkSource, + parameterNames: parameterNames + ) + } + return resolveLinks(in: dict, linkSource: linkSource) + } + if let array = value as? [Any] { + return array.map { resolveLinksInValue($0, linkSource: linkSource) } + } + return value + } + + private func resolveInstanceLinks( + in dictionary: [String: Any], + linkSource: [String: Any], + parameterNames: Set + ) -> [String: Any] { + var dict = dictionary + let linkKeys = dict.keys.filter { $0.hasPrefix("$") } + for linkKey in linkKeys { + let key = String(linkKey.dropFirst()) + guard dict[key] == nil else { continue } + guard !parameterNames.contains(key) else { continue } + guard let linkName = dict[linkKey] as? String else { continue } + guard let value = linkSource[linkName] else { continue } + dict[key] = value + } + + var result: [String: Any] = [:] + for (key, value) in dict { + guard !key.hasPrefix("$") else { continue } + result[key] = value + } + + for paramName in parameterNames { + if result[paramName] == nil, let value = linkSource[paramName] { + result[paramName] = value + } + } + + return result + } + + private func collectParameterNames(from dict: [String: Any]) -> Set { + var names = Set() + for (key, value) in dict { + if key.hasPrefix("$"), let name = value as? String { + names.insert(name) + } + if let nestedDict = value as? [String: Any] { + names.formUnion(collectParameterNames(from: nestedDict)) + } + if let array = value as? [Any] { + for element in array { + if let elementDict = element as? [String: Any] { + names.formUnion(collectParameterNames(from: elementDict)) + } + } + } + } + return names } } @@ -202,18 +172,3 @@ private func normalizedErrors( ) -> NonEmptyArray { errors ?? NonEmptyArray(.generic) } - -extension DeserializationResult { - fileprivate func map(_ transform: (T) -> U) -> DeserializationResult { - switch self { - case let .success(value): - .success(transform(value)) - case let .partialSuccess(value, warnings): - .partialSuccess(transform(value), warnings: warnings) - case let .failure(errors): - .failure(errors) - case .noValue: - .noValue - } - } -} diff --git a/client/ios/DivKit/generated_sources/Div.swift b/client/ios/DivKit/generated_sources/Div.swift index 9fe652f03..8e4cd3fa2 100644 --- a/client/ios/DivKit/generated_sources/Div.swift +++ b/client/ios/DivKit/generated_sources/Div.swift @@ -105,6 +105,7 @@ public enum Div: Sendable { extension Div { public init(dictionary: [String: Any], context: ParsingContext) throws { + let dictionary = context.templateResolver?(dictionary) ?? dictionary let blockType = try dictionary.getField("type") as String switch blockType { case DivImage.type: @@ -142,7 +143,7 @@ extension Div { case DivVideo.type: self = .divVideo(try DivVideo(dictionary: dictionary, context: context)) default: - throw DeserializationError.invalidFieldRepresentation(field: "div", representation: dictionary) + throw DeserializationError.requiredFieldIsMissing(field: "type") } } } diff --git a/client/ios/DivKit/generated_sources/DivActionArrayInsertValue.swift b/client/ios/DivKit/generated_sources/DivActionArrayInsertValue.swift index 148343530..7c92f6066 100644 --- a/client/ios/DivKit/generated_sources/DivActionArrayInsertValue.swift +++ b/client/ios/DivKit/generated_sources/DivActionArrayInsertValue.swift @@ -21,7 +21,7 @@ public final class DivActionArrayInsertValue: Sendable { public convenience init(dictionary: [String: Any], context: ParsingContext) throws { self.init( index: try dictionary.getOptionalExpressionField("index", context: context), - value: try dictionary.getField("value", transform: { (dict: [String: Any]) in try DivTypedValue(dictionary: dict, context: context) }), + value: try dictionary.getField("value", transform: { (dict: [String: Any]) in try DivTypedValue(dictionary: dict, context: context) }, context: context), variableName: try dictionary.getExpressionField("variable_name", context: context) ) } diff --git a/client/ios/DivKit/generated_sources/DivActionArraySetValue.swift b/client/ios/DivKit/generated_sources/DivActionArraySetValue.swift index d7c48b7b4..d9f58e63a 100644 --- a/client/ios/DivKit/generated_sources/DivActionArraySetValue.swift +++ b/client/ios/DivKit/generated_sources/DivActionArraySetValue.swift @@ -21,7 +21,7 @@ public final class DivActionArraySetValue: Sendable { public convenience init(dictionary: [String: Any], context: ParsingContext) throws { self.init( index: try dictionary.getExpressionField("index", context: context), - value: try dictionary.getField("value", transform: { (dict: [String: Any]) in try DivTypedValue(dictionary: dict, context: context) }), + value: try dictionary.getField("value", transform: { (dict: [String: Any]) in try DivTypedValue(dictionary: dict, context: context) }, context: context), variableName: try dictionary.getExpressionField("variable_name", context: context) ) } diff --git a/client/ios/DivKit/generated_sources/DivActionCopyToClipboard.swift b/client/ios/DivKit/generated_sources/DivActionCopyToClipboard.swift index 50503e212..5880c876b 100644 --- a/client/ios/DivKit/generated_sources/DivActionCopyToClipboard.swift +++ b/client/ios/DivKit/generated_sources/DivActionCopyToClipboard.swift @@ -10,7 +10,7 @@ public final class DivActionCopyToClipboard: Sendable { public convenience init(dictionary: [String: Any], context: ParsingContext) throws { self.init( - content: try dictionary.getField("content", transform: { (dict: [String: Any]) in try DivActionCopyToClipboardContent(dictionary: dict, context: context) }) + content: try dictionary.getField("content", transform: { (dict: [String: Any]) in try DivActionCopyToClipboardContent(dictionary: dict, context: context) }, context: context) ) } diff --git a/client/ios/DivKit/generated_sources/DivActionCopyToClipboardContent.swift b/client/ios/DivKit/generated_sources/DivActionCopyToClipboardContent.swift index 4566f14c8..cd3dabc3e 100644 --- a/client/ios/DivKit/generated_sources/DivActionCopyToClipboardContent.swift +++ b/client/ios/DivKit/generated_sources/DivActionCopyToClipboardContent.swift @@ -21,6 +21,7 @@ public enum DivActionCopyToClipboardContent: Sendable { extension DivActionCopyToClipboardContent { public init(dictionary: [String: Any], context: ParsingContext) throws { + let dictionary = context.templateResolver?(dictionary) ?? dictionary let blockType = try dictionary.getField("type") as String switch blockType { case ContentText.type: @@ -28,7 +29,7 @@ extension DivActionCopyToClipboardContent { case ContentUrl.type: self = .contentUrl(try ContentUrl(dictionary: dictionary, context: context)) default: - throw DeserializationError.invalidFieldRepresentation(field: "div-action-copy-to-clipboard-content", representation: dictionary) + throw DeserializationError.requiredFieldIsMissing(field: "type") } } } diff --git a/client/ios/DivKit/generated_sources/DivActionCopyToClipboardContentTemplate.swift b/client/ios/DivKit/generated_sources/DivActionCopyToClipboardContentTemplate.swift index f3b4129ff..4c028a6c4 100644 --- a/client/ios/DivKit/generated_sources/DivActionCopyToClipboardContentTemplate.swift +++ b/client/ios/DivKit/generated_sources/DivActionCopyToClipboardContentTemplate.swift @@ -94,7 +94,7 @@ extension DivActionCopyToClipboardContentTemplate { case ContentUrlTemplate.type: self = .contentUrlTemplate(try ContentUrlTemplate(dictionary: dictionary, templateToType: templateToType)) default: - throw DeserializationError.invalidFieldRepresentation(field: "div-action-copy-to-clipboard-content_template", representation: dictionary) + throw DeserializationError.requiredFieldIsMissing(field: "type") } } } diff --git a/client/ios/DivKit/generated_sources/DivActionScrollDestination.swift b/client/ios/DivKit/generated_sources/DivActionScrollDestination.swift index 94dbb0d46..0a7ea8a5b 100644 --- a/client/ios/DivKit/generated_sources/DivActionScrollDestination.swift +++ b/client/ios/DivKit/generated_sources/DivActionScrollDestination.swift @@ -27,6 +27,7 @@ public enum DivActionScrollDestination: Sendable { extension DivActionScrollDestination { public init(dictionary: [String: Any], context: ParsingContext) throws { + let dictionary = context.templateResolver?(dictionary) ?? dictionary let blockType = try dictionary.getField("type") as String switch blockType { case OffsetDestination.type: @@ -38,7 +39,7 @@ extension DivActionScrollDestination { case EndDestination.type: self = .endDestination(try EndDestination(dictionary: dictionary, context: context)) default: - throw DeserializationError.invalidFieldRepresentation(field: "div-action-scroll-destination", representation: dictionary) + throw DeserializationError.requiredFieldIsMissing(field: "type") } } } diff --git a/client/ios/DivKit/generated_sources/DivActionScrollDestinationTemplate.swift b/client/ios/DivKit/generated_sources/DivActionScrollDestinationTemplate.swift index a30e7802e..2bd9f6ff5 100644 --- a/client/ios/DivKit/generated_sources/DivActionScrollDestinationTemplate.swift +++ b/client/ios/DivKit/generated_sources/DivActionScrollDestinationTemplate.swift @@ -140,7 +140,7 @@ extension DivActionScrollDestinationTemplate { case EndDestinationTemplate.type: self = .endDestinationTemplate(try EndDestinationTemplate(dictionary: dictionary, templateToType: templateToType)) default: - throw DeserializationError.invalidFieldRepresentation(field: "div-action-scroll-destination_template", representation: dictionary) + throw DeserializationError.requiredFieldIsMissing(field: "type") } } } diff --git a/client/ios/DivKit/generated_sources/DivActionScrollTo.swift b/client/ios/DivKit/generated_sources/DivActionScrollTo.swift index d3632f32b..e44f7029d 100644 --- a/client/ios/DivKit/generated_sources/DivActionScrollTo.swift +++ b/client/ios/DivKit/generated_sources/DivActionScrollTo.swift @@ -21,7 +21,7 @@ public final class DivActionScrollTo: Sendable { public convenience init(dictionary: [String: Any], context: ParsingContext) throws { self.init( animated: try dictionary.getOptionalExpressionField("animated", context: context), - destination: try dictionary.getField("destination", transform: { (dict: [String: Any]) in try DivActionScrollDestination(dictionary: dict, context: context) }), + destination: try dictionary.getField("destination", transform: { (dict: [String: Any]) in try DivActionScrollDestination(dictionary: dict, context: context) }, context: context), id: try dictionary.getExpressionField("id", context: context) ) } diff --git a/client/ios/DivKit/generated_sources/DivActionSetStoredValue.swift b/client/ios/DivKit/generated_sources/DivActionSetStoredValue.swift index 130f711b1..f504be1e4 100644 --- a/client/ios/DivKit/generated_sources/DivActionSetStoredValue.swift +++ b/client/ios/DivKit/generated_sources/DivActionSetStoredValue.swift @@ -22,7 +22,7 @@ public final class DivActionSetStoredValue: Sendable { self.init( lifetime: try dictionary.getExpressionField("lifetime", context: context), name: try dictionary.getExpressionField("name", context: context), - value: try dictionary.getField("value", transform: { (dict: [String: Any]) in try DivTypedValue(dictionary: dict, context: context) }) + value: try dictionary.getField("value", transform: { (dict: [String: Any]) in try DivTypedValue(dictionary: dict, context: context) }, context: context) ) } diff --git a/client/ios/DivKit/generated_sources/DivActionSetVariable.swift b/client/ios/DivKit/generated_sources/DivActionSetVariable.swift index 550d3dd1b..1c202719d 100644 --- a/client/ios/DivKit/generated_sources/DivActionSetVariable.swift +++ b/client/ios/DivKit/generated_sources/DivActionSetVariable.swift @@ -15,7 +15,7 @@ public final class DivActionSetVariable: Sendable { public convenience init(dictionary: [String: Any], context: ParsingContext) throws { self.init( - value: try dictionary.getField("value", transform: { (dict: [String: Any]) in try DivTypedValue(dictionary: dict, context: context) }), + value: try dictionary.getField("value", transform: { (dict: [String: Any]) in try DivTypedValue(dictionary: dict, context: context) }, context: context), variableName: try dictionary.getExpressionField("variable_name", context: context) ) } diff --git a/client/ios/DivKit/generated_sources/DivActionSubmit.swift b/client/ios/DivKit/generated_sources/DivActionSubmit.swift index 90404f0f2..39961901b 100644 --- a/client/ios/DivKit/generated_sources/DivActionSubmit.swift +++ b/client/ios/DivKit/generated_sources/DivActionSubmit.swift @@ -91,7 +91,7 @@ public final class DivActionSubmit: Sendable { containerId: try dictionary.getExpressionField("container_id", context: context), onFailActions: try dictionary.getOptionalArray("on_fail_actions", transform: { (dict: [String: Any]) in try? DivAction(dictionary: dict, context: context) }), onSuccessActions: try dictionary.getOptionalArray("on_success_actions", transform: { (dict: [String: Any]) in try? DivAction(dictionary: dict, context: context) }), - request: try dictionary.getField("request", transform: { (dict: [String: Any]) in try DivActionSubmit.Request(dictionary: dict, context: context) }) + request: try dictionary.getField("request", transform: { (dict: [String: Any]) in try DivActionSubmit.Request(dictionary: dict, context: context) }, context: context) ) } diff --git a/client/ios/DivKit/generated_sources/DivActionTyped.swift b/client/ios/DivKit/generated_sources/DivActionTyped.swift index 1b40c687b..81e1b729f 100644 --- a/client/ios/DivKit/generated_sources/DivActionTyped.swift +++ b/client/ios/DivKit/generated_sources/DivActionTyped.swift @@ -81,6 +81,7 @@ public enum DivActionTyped: Sendable { extension DivActionTyped { public init(dictionary: [String: Any], context: ParsingContext) throws { + let dictionary = context.templateResolver?(dictionary) ?? dictionary let blockType = try dictionary.getField("type") as String switch blockType { case DivActionAnimatorStart.type: @@ -128,7 +129,7 @@ extension DivActionTyped { case DivActionCustom.type: self = .divActionCustom(try DivActionCustom(dictionary: dictionary, context: context)) default: - throw DeserializationError.invalidFieldRepresentation(field: "div-action-typed", representation: dictionary) + throw DeserializationError.requiredFieldIsMissing(field: "type") } } } diff --git a/client/ios/DivKit/generated_sources/DivActionTypedTemplate.swift b/client/ios/DivKit/generated_sources/DivActionTypedTemplate.swift index 59bb8203f..8bda478ae 100644 --- a/client/ios/DivKit/generated_sources/DivActionTypedTemplate.swift +++ b/client/ios/DivKit/generated_sources/DivActionTypedTemplate.swift @@ -554,7 +554,7 @@ extension DivActionTypedTemplate { case DivActionCustomTemplate.type: self = .divActionCustomTemplate(try DivActionCustomTemplate(dictionary: dictionary, templateToType: templateToType)) default: - throw DeserializationError.invalidFieldRepresentation(field: "div-action-typed_template", representation: dictionary) + throw DeserializationError.requiredFieldIsMissing(field: "type") } } } diff --git a/client/ios/DivKit/generated_sources/DivActionUpdateStructure.swift b/client/ios/DivKit/generated_sources/DivActionUpdateStructure.swift index d97341e2d..931dddf68 100644 --- a/client/ios/DivKit/generated_sources/DivActionUpdateStructure.swift +++ b/client/ios/DivKit/generated_sources/DivActionUpdateStructure.swift @@ -24,7 +24,7 @@ public final class DivActionUpdateStructure: Sendable { public convenience init(dictionary: [String: Any], context: ParsingContext) throws { self.init( path: try dictionary.getExpressionField("path", validator: Self.pathValidator, context: context), - value: try dictionary.getField("value", transform: { (dict: [String: Any]) in try DivTypedValue(dictionary: dict, context: context) }), + value: try dictionary.getField("value", transform: { (dict: [String: Any]) in try DivTypedValue(dictionary: dict, context: context) }, context: context), variableName: try dictionary.getExpressionField("variable_name", context: context) ) } diff --git a/client/ios/DivKit/generated_sources/DivAnimator.swift b/client/ios/DivKit/generated_sources/DivAnimator.swift index b9b31aa93..a9faf3db3 100644 --- a/client/ios/DivKit/generated_sources/DivAnimator.swift +++ b/client/ios/DivKit/generated_sources/DivAnimator.swift @@ -30,6 +30,7 @@ public enum DivAnimator: Sendable { extension DivAnimator { public init(dictionary: [String: Any], context: ParsingContext) throws { + let dictionary = context.templateResolver?(dictionary) ?? dictionary let blockType = try dictionary.getField("type") as String switch blockType { case DivColorAnimator.type: @@ -37,7 +38,7 @@ extension DivAnimator { case DivNumberAnimator.type: self = .divNumberAnimator(try DivNumberAnimator(dictionary: dictionary, context: context)) default: - throw DeserializationError.invalidFieldRepresentation(field: "div-animator", representation: dictionary) + throw DeserializationError.requiredFieldIsMissing(field: "type") } } } diff --git a/client/ios/DivKit/generated_sources/DivAnimatorTemplate.swift b/client/ios/DivKit/generated_sources/DivAnimatorTemplate.swift index 506099693..f5041c3e5 100644 --- a/client/ios/DivKit/generated_sources/DivAnimatorTemplate.swift +++ b/client/ios/DivKit/generated_sources/DivAnimatorTemplate.swift @@ -94,7 +94,7 @@ extension DivAnimatorTemplate { case DivNumberAnimatorTemplate.type: self = .divNumberAnimatorTemplate(try DivNumberAnimatorTemplate(dictionary: dictionary, templateToType: templateToType)) default: - throw DeserializationError.invalidFieldRepresentation(field: "div-animator_template", representation: dictionary) + throw DeserializationError.requiredFieldIsMissing(field: "type") } } } diff --git a/client/ios/DivKit/generated_sources/DivAppearanceSetTransition.swift b/client/ios/DivKit/generated_sources/DivAppearanceSetTransition.swift index a0af64226..7b2284361 100644 --- a/client/ios/DivKit/generated_sources/DivAppearanceSetTransition.swift +++ b/client/ios/DivKit/generated_sources/DivAppearanceSetTransition.swift @@ -13,7 +13,7 @@ public final class DivAppearanceSetTransition: Sendable { public convenience init(dictionary: [String: Any], context: ParsingContext) throws { self.init( - items: try dictionary.getArray("items", transform: { (dict: [String: Any]) in try? DivAppearanceTransition(dictionary: dict, context: context) }, validator: Self.itemsValidator) + items: try dictionary.getArray("items", transform: { (dict: [String: Any]) in try? DivAppearanceTransition(dictionary: dict, context: context) }, validator: Self.itemsValidator, context: context) ) } diff --git a/client/ios/DivKit/generated_sources/DivAppearanceTransition.swift b/client/ios/DivKit/generated_sources/DivAppearanceTransition.swift index 725357ab3..1ce9a4789 100644 --- a/client/ios/DivKit/generated_sources/DivAppearanceTransition.swift +++ b/client/ios/DivKit/generated_sources/DivAppearanceTransition.swift @@ -27,6 +27,7 @@ public enum DivAppearanceTransition: Sendable { extension DivAppearanceTransition { public init(dictionary: [String: Any], context: ParsingContext) throws { + let dictionary = context.templateResolver?(dictionary) ?? dictionary let blockType = try dictionary.getField("type") as String switch blockType { case DivAppearanceSetTransition.type: @@ -38,7 +39,7 @@ extension DivAppearanceTransition { case DivSlideTransition.type: self = .divSlideTransition(try DivSlideTransition(dictionary: dictionary, context: context)) default: - throw DeserializationError.invalidFieldRepresentation(field: "div-appearance-transition", representation: dictionary) + throw DeserializationError.requiredFieldIsMissing(field: "type") } } } diff --git a/client/ios/DivKit/generated_sources/DivAppearanceTransitionTemplate.swift b/client/ios/DivKit/generated_sources/DivAppearanceTransitionTemplate.swift index d110ce0d0..b0c95c9de 100644 --- a/client/ios/DivKit/generated_sources/DivAppearanceTransitionTemplate.swift +++ b/client/ios/DivKit/generated_sources/DivAppearanceTransitionTemplate.swift @@ -140,7 +140,7 @@ extension DivAppearanceTransitionTemplate { case DivSlideTransitionTemplate.type: self = .divSlideTransitionTemplate(try DivSlideTransitionTemplate(dictionary: dictionary, templateToType: templateToType)) default: - throw DeserializationError.invalidFieldRepresentation(field: "div-appearance-transition_template", representation: dictionary) + throw DeserializationError.requiredFieldIsMissing(field: "type") } } } diff --git a/client/ios/DivKit/generated_sources/DivBackground.swift b/client/ios/DivKit/generated_sources/DivBackground.swift index 4527e76c4..872550a8d 100644 --- a/client/ios/DivKit/generated_sources/DivBackground.swift +++ b/client/ios/DivKit/generated_sources/DivBackground.swift @@ -30,6 +30,7 @@ public enum DivBackground: Sendable { extension DivBackground { public init(dictionary: [String: Any], context: ParsingContext) throws { + let dictionary = context.templateResolver?(dictionary) ?? dictionary let blockType = try dictionary.getField("type") as String switch blockType { case DivLinearGradient.type: @@ -43,7 +44,7 @@ extension DivBackground { case DivNinePatchBackground.type: self = .divNinePatchBackground(try DivNinePatchBackground(dictionary: dictionary, context: context)) default: - throw DeserializationError.invalidFieldRepresentation(field: "div-background", representation: dictionary) + throw DeserializationError.requiredFieldIsMissing(field: "type") } } } diff --git a/client/ios/DivKit/generated_sources/DivBackgroundTemplate.swift b/client/ios/DivKit/generated_sources/DivBackgroundTemplate.swift index 0bb087146..e72c697b4 100644 --- a/client/ios/DivKit/generated_sources/DivBackgroundTemplate.swift +++ b/client/ios/DivKit/generated_sources/DivBackgroundTemplate.swift @@ -163,7 +163,7 @@ extension DivBackgroundTemplate { case DivNinePatchBackgroundTemplate.type: self = .divNinePatchBackgroundTemplate(try DivNinePatchBackgroundTemplate(dictionary: dictionary, templateToType: templateToType)) default: - throw DeserializationError.invalidFieldRepresentation(field: "div-background_template", representation: dictionary) + throw DeserializationError.requiredFieldIsMissing(field: "type") } } } diff --git a/client/ios/DivKit/generated_sources/DivChangeSetTransition.swift b/client/ios/DivKit/generated_sources/DivChangeSetTransition.swift index 322e3c54b..3fe6c60cc 100644 --- a/client/ios/DivKit/generated_sources/DivChangeSetTransition.swift +++ b/client/ios/DivKit/generated_sources/DivChangeSetTransition.swift @@ -13,7 +13,7 @@ public final class DivChangeSetTransition: Sendable { public convenience init(dictionary: [String: Any], context: ParsingContext) throws { self.init( - items: try dictionary.getArray("items", transform: { (dict: [String: Any]) in try? DivChangeTransition(dictionary: dict, context: context) }, validator: Self.itemsValidator) + items: try dictionary.getArray("items", transform: { (dict: [String: Any]) in try? DivChangeTransition(dictionary: dict, context: context) }, validator: Self.itemsValidator, context: context) ) } diff --git a/client/ios/DivKit/generated_sources/DivChangeTransition.swift b/client/ios/DivKit/generated_sources/DivChangeTransition.swift index a6cb5d43e..2363d8931 100644 --- a/client/ios/DivKit/generated_sources/DivChangeTransition.swift +++ b/client/ios/DivKit/generated_sources/DivChangeTransition.swift @@ -21,6 +21,7 @@ public enum DivChangeTransition: Sendable { extension DivChangeTransition { public init(dictionary: [String: Any], context: ParsingContext) throws { + let dictionary = context.templateResolver?(dictionary) ?? dictionary let blockType = try dictionary.getField("type") as String switch blockType { case DivChangeSetTransition.type: @@ -28,7 +29,7 @@ extension DivChangeTransition { case DivChangeBoundsTransition.type: self = .divChangeBoundsTransition(try DivChangeBoundsTransition(dictionary: dictionary, context: context)) default: - throw DeserializationError.invalidFieldRepresentation(field: "div-change-transition", representation: dictionary) + throw DeserializationError.requiredFieldIsMissing(field: "type") } } } diff --git a/client/ios/DivKit/generated_sources/DivChangeTransitionTemplate.swift b/client/ios/DivKit/generated_sources/DivChangeTransitionTemplate.swift index bc747c86b..389711bbc 100644 --- a/client/ios/DivKit/generated_sources/DivChangeTransitionTemplate.swift +++ b/client/ios/DivKit/generated_sources/DivChangeTransitionTemplate.swift @@ -94,7 +94,7 @@ extension DivChangeTransitionTemplate { case DivChangeBoundsTransitionTemplate.type: self = .divChangeBoundsTransitionTemplate(try DivChangeBoundsTransitionTemplate(dictionary: dictionary, templateToType: templateToType)) default: - throw DeserializationError.invalidFieldRepresentation(field: "div-change-transition_template", representation: dictionary) + throw DeserializationError.requiredFieldIsMissing(field: "type") } } } diff --git a/client/ios/DivKit/generated_sources/DivCollectionItemBuilder.swift b/client/ios/DivKit/generated_sources/DivCollectionItemBuilder.swift index b5c2a0822..3f13d922e 100644 --- a/client/ios/DivKit/generated_sources/DivCollectionItemBuilder.swift +++ b/client/ios/DivKit/generated_sources/DivCollectionItemBuilder.swift @@ -20,7 +20,7 @@ public final class DivCollectionItemBuilder: @unchecked Sendable { public convenience init(dictionary: [String: Any], context: ParsingContext) throws { self.init( - div: try dictionary.getField("div", transform: { (dict: [String: Any]) in try Div(dictionary: dict, context: context) }), + div: try dictionary.getField("div", transform: { (dict: [String: Any]) in try Div(dictionary: dict, context: context) }, context: context), id: try dictionary.getOptionalExpressionField("id", context: context), selector: try dictionary.getOptionalExpressionField("selector", context: context) ) @@ -52,7 +52,7 @@ public final class DivCollectionItemBuilder: @unchecked Sendable { self.init( data: try dictionary.getExpressionField("data", context: context), dataElementName: try dictionary.getOptionalField("data_element_name", context: context), - prototypes: try dictionary.getArray("prototypes", transform: { (dict: [String: Any]) in try? DivCollectionItemBuilder.Prototype(dictionary: dict, context: context) }, validator: Self.prototypesValidator) + prototypes: try dictionary.getArray("prototypes", transform: { (dict: [String: Any]) in try? DivCollectionItemBuilder.Prototype(dictionary: dict, context: context) }, validator: Self.prototypesValidator, context: context) ) } diff --git a/client/ios/DivKit/generated_sources/DivContainer.swift b/client/ios/DivKit/generated_sources/DivContainer.swift index bd26fb5fd..9d62cf5ad 100644 --- a/client/ios/DivKit/generated_sources/DivContainer.swift +++ b/client/ios/DivKit/generated_sources/DivContainer.swift @@ -43,7 +43,7 @@ public final class DivContainer: DivBase, Sendable { showAtEnd: try dictionary.getOptionalExpressionField("show_at_end", context: context), showAtStart: try dictionary.getOptionalExpressionField("show_at_start", context: context), showBetween: try dictionary.getOptionalExpressionField("show_between", context: context), - style: try dictionary.getField("style", transform: { (dict: [String: Any]) in try DivDrawable(dictionary: dict, context: context) }) + style: try dictionary.getField("style", transform: { (dict: [String: Any]) in try DivDrawable(dictionary: dict, context: context) }, context: context) ) } diff --git a/client/ios/DivKit/generated_sources/DivCount.swift b/client/ios/DivKit/generated_sources/DivCount.swift index c446ccd59..d5509c2dc 100644 --- a/client/ios/DivKit/generated_sources/DivCount.swift +++ b/client/ios/DivKit/generated_sources/DivCount.swift @@ -21,6 +21,7 @@ public enum DivCount: Sendable { extension DivCount { public init(dictionary: [String: Any], context: ParsingContext) throws { + let dictionary = context.templateResolver?(dictionary) ?? dictionary let blockType = try dictionary.getField("type") as String switch blockType { case DivInfinityCount.type: @@ -28,7 +29,7 @@ extension DivCount { case DivFixedCount.type: self = .divFixedCount(try DivFixedCount(dictionary: dictionary, context: context)) default: - throw DeserializationError.invalidFieldRepresentation(field: "div-count", representation: dictionary) + throw DeserializationError.requiredFieldIsMissing(field: "type") } } } diff --git a/client/ios/DivKit/generated_sources/DivCountTemplate.swift b/client/ios/DivKit/generated_sources/DivCountTemplate.swift index 9c03c5121..3336e489b 100644 --- a/client/ios/DivKit/generated_sources/DivCountTemplate.swift +++ b/client/ios/DivKit/generated_sources/DivCountTemplate.swift @@ -94,7 +94,7 @@ extension DivCountTemplate { case DivFixedCountTemplate.type: self = .divFixedCountTemplate(try DivFixedCountTemplate(dictionary: dictionary, templateToType: templateToType)) default: - throw DeserializationError.invalidFieldRepresentation(field: "div-count_template", representation: dictionary) + throw DeserializationError.requiredFieldIsMissing(field: "type") } } } diff --git a/client/ios/DivKit/generated_sources/DivData.swift b/client/ios/DivKit/generated_sources/DivData.swift index c540ff98f..42805f090 100644 --- a/client/ios/DivKit/generated_sources/DivData.swift +++ b/client/ios/DivKit/generated_sources/DivData.swift @@ -11,7 +11,7 @@ public final class DivData: Sendable { public convenience init(dictionary: [String: Any], context: ParsingContext) throws { self.init( - div: try dictionary.getField("div", transform: { (dict: [String: Any]) in try Div(dictionary: dict, context: context) }), + div: try dictionary.getField("div", transform: { (dict: [String: Any]) in try Div(dictionary: dict, context: context) }, context: context), stateId: try dictionary.getField("state_id", context: context) ) } @@ -44,7 +44,7 @@ public final class DivData: Sendable { self.init( functions: try dictionary.getOptionalArray("functions", transform: { (dict: [String: Any]) in try? DivFunction(dictionary: dict, context: context) }), logId: try dictionary.getField("log_id", context: context), - states: try dictionary.getArray("states", transform: { (dict: [String: Any]) in try? DivData.State(dictionary: dict, context: context) }, validator: Self.statesValidator), + states: try dictionary.getArray("states", transform: { (dict: [String: Any]) in try? DivData.State(dictionary: dict, context: context) }, validator: Self.statesValidator, context: context), timers: try dictionary.getOptionalArray("timers", transform: { (dict: [String: Any]) in try? DivTimer(dictionary: dict, context: context) }), transitionAnimationSelector: try dictionary.getOptionalExpressionField("transition_animation_selector", context: context), variableTriggers: try dictionary.getOptionalArray("variable_triggers", transform: { (dict: [String: Any]) in try? DivTrigger(dictionary: dict, context: context) }), diff --git a/client/ios/DivKit/generated_sources/DivDrawable.swift b/client/ios/DivKit/generated_sources/DivDrawable.swift index 1a6f6db58..bccab0617 100644 --- a/client/ios/DivKit/generated_sources/DivDrawable.swift +++ b/client/ios/DivKit/generated_sources/DivDrawable.swift @@ -18,12 +18,13 @@ public enum DivDrawable: Sendable { extension DivDrawable { public init(dictionary: [String: Any], context: ParsingContext) throws { + let dictionary = context.templateResolver?(dictionary) ?? dictionary let blockType = try dictionary.getField("type") as String switch blockType { case DivShapeDrawable.type: self = .divShapeDrawable(try DivShapeDrawable(dictionary: dictionary, context: context)) default: - throw DeserializationError.invalidFieldRepresentation(field: "div-drawable", representation: dictionary) + throw DeserializationError.requiredFieldIsMissing(field: "type") } } } diff --git a/client/ios/DivKit/generated_sources/DivDrawableTemplate.swift b/client/ios/DivKit/generated_sources/DivDrawableTemplate.swift index 5f506efce..68fcbd4c4 100644 --- a/client/ios/DivKit/generated_sources/DivDrawableTemplate.swift +++ b/client/ios/DivKit/generated_sources/DivDrawableTemplate.swift @@ -71,7 +71,7 @@ extension DivDrawableTemplate { case DivShapeDrawableTemplate.type: self = .divShapeDrawableTemplate(try DivShapeDrawableTemplate(dictionary: dictionary, templateToType: templateToType)) default: - throw DeserializationError.invalidFieldRepresentation(field: "div-drawable_template", representation: dictionary) + throw DeserializationError.requiredFieldIsMissing(field: "type") } } } diff --git a/client/ios/DivKit/generated_sources/DivFilter.swift b/client/ios/DivKit/generated_sources/DivFilter.swift index 4021e43ef..f107df82e 100644 --- a/client/ios/DivKit/generated_sources/DivFilter.swift +++ b/client/ios/DivKit/generated_sources/DivFilter.swift @@ -21,6 +21,7 @@ public enum DivFilter: Sendable { extension DivFilter { public init(dictionary: [String: Any], context: ParsingContext) throws { + let dictionary = context.templateResolver?(dictionary) ?? dictionary let blockType = try dictionary.getField("type") as String switch blockType { case DivBlur.type: @@ -28,7 +29,7 @@ extension DivFilter { case DivFilterRtlMirror.type: self = .divFilterRtlMirror(try DivFilterRtlMirror(dictionary: dictionary, context: context)) default: - throw DeserializationError.invalidFieldRepresentation(field: "div-filter", representation: dictionary) + throw DeserializationError.requiredFieldIsMissing(field: "type") } } } diff --git a/client/ios/DivKit/generated_sources/DivFilterTemplate.swift b/client/ios/DivKit/generated_sources/DivFilterTemplate.swift index 4cc1eb75f..4cb5fc75e 100644 --- a/client/ios/DivKit/generated_sources/DivFilterTemplate.swift +++ b/client/ios/DivKit/generated_sources/DivFilterTemplate.swift @@ -94,7 +94,7 @@ extension DivFilterTemplate { case DivFilterRtlMirrorTemplate.type: self = .divFilterRtlMirrorTemplate(try DivFilterRtlMirrorTemplate(dictionary: dictionary, templateToType: templateToType)) default: - throw DeserializationError.invalidFieldRepresentation(field: "div-filter_template", representation: dictionary) + throw DeserializationError.requiredFieldIsMissing(field: "type") } } } diff --git a/client/ios/DivKit/generated_sources/DivFixedLengthInputMask.swift b/client/ios/DivKit/generated_sources/DivFixedLengthInputMask.swift index 30ae76084..a7c2d0ca1 100644 --- a/client/ios/DivKit/generated_sources/DivFixedLengthInputMask.swift +++ b/client/ios/DivKit/generated_sources/DivFixedLengthInputMask.swift @@ -68,7 +68,7 @@ public final class DivFixedLengthInputMask: DivInputMaskBase, Sendable { self.init( alwaysVisible: try dictionary.getOptionalExpressionField("always_visible", context: context), pattern: try dictionary.getExpressionField("pattern", context: context), - patternElements: try dictionary.getArray("pattern_elements", transform: { (dict: [String: Any]) in try? DivFixedLengthInputMask.PatternElement(dictionary: dict, context: context) }, validator: Self.patternElementsValidator), + patternElements: try dictionary.getArray("pattern_elements", transform: { (dict: [String: Any]) in try? DivFixedLengthInputMask.PatternElement(dictionary: dict, context: context) }, validator: Self.patternElementsValidator, context: context), rawTextVariable: try dictionary.getField("raw_text_variable", context: context) ) } diff --git a/client/ios/DivKit/generated_sources/DivFunction.swift b/client/ios/DivKit/generated_sources/DivFunction.swift index 19b4a6112..f05b471b2 100644 --- a/client/ios/DivKit/generated_sources/DivFunction.swift +++ b/client/ios/DivKit/generated_sources/DivFunction.swift @@ -15,7 +15,7 @@ public final class DivFunction: Sendable { public convenience init(dictionary: [String: Any], context: ParsingContext) throws { self.init( - arguments: try dictionary.getArray("arguments", transform: { (dict: [String: Any]) in try? DivFunctionArgument(dictionary: dict, context: context) }), + arguments: try dictionary.getArray("arguments", transform: { (dict: [String: Any]) in try? DivFunctionArgument(dictionary: dict, context: context) }, context: context), body: try dictionary.getField("body", context: context), name: try dictionary.getField("name", validator: Self.nameValidator, context: context), returnType: try dictionary.getField("return_type", context: context) diff --git a/client/ios/DivKit/generated_sources/DivIndicatorItemPlacement.swift b/client/ios/DivKit/generated_sources/DivIndicatorItemPlacement.swift index 13026d7a1..5824b300b 100644 --- a/client/ios/DivKit/generated_sources/DivIndicatorItemPlacement.swift +++ b/client/ios/DivKit/generated_sources/DivIndicatorItemPlacement.swift @@ -21,6 +21,7 @@ public enum DivIndicatorItemPlacement: Sendable { extension DivIndicatorItemPlacement { public init(dictionary: [String: Any], context: ParsingContext) throws { + let dictionary = context.templateResolver?(dictionary) ?? dictionary let blockType = try dictionary.getField("type") as String switch blockType { case DivDefaultIndicatorItemPlacement.type: @@ -28,7 +29,7 @@ extension DivIndicatorItemPlacement { case DivStretchIndicatorItemPlacement.type: self = .divStretchIndicatorItemPlacement(try DivStretchIndicatorItemPlacement(dictionary: dictionary, context: context)) default: - throw DeserializationError.invalidFieldRepresentation(field: "div-indicator-item-placement", representation: dictionary) + throw DeserializationError.requiredFieldIsMissing(field: "type") } } } diff --git a/client/ios/DivKit/generated_sources/DivIndicatorItemPlacementTemplate.swift b/client/ios/DivKit/generated_sources/DivIndicatorItemPlacementTemplate.swift index 1d6e97bea..5f32584f3 100644 --- a/client/ios/DivKit/generated_sources/DivIndicatorItemPlacementTemplate.swift +++ b/client/ios/DivKit/generated_sources/DivIndicatorItemPlacementTemplate.swift @@ -94,7 +94,7 @@ extension DivIndicatorItemPlacementTemplate { case DivStretchIndicatorItemPlacementTemplate.type: self = .divStretchIndicatorItemPlacementTemplate(try DivStretchIndicatorItemPlacementTemplate(dictionary: dictionary, templateToType: templateToType)) default: - throw DeserializationError.invalidFieldRepresentation(field: "div-indicator-item-placement_template", representation: dictionary) + throw DeserializationError.requiredFieldIsMissing(field: "type") } } } diff --git a/client/ios/DivKit/generated_sources/DivInputFilter.swift b/client/ios/DivKit/generated_sources/DivInputFilter.swift index d36581af9..e7aeeeff3 100644 --- a/client/ios/DivKit/generated_sources/DivInputFilter.swift +++ b/client/ios/DivKit/generated_sources/DivInputFilter.swift @@ -21,6 +21,7 @@ public enum DivInputFilter: Sendable { extension DivInputFilter { public init(dictionary: [String: Any], context: ParsingContext) throws { + let dictionary = context.templateResolver?(dictionary) ?? dictionary let blockType = try dictionary.getField("type") as String switch blockType { case DivInputFilterRegex.type: @@ -28,7 +29,7 @@ extension DivInputFilter { case DivInputFilterExpression.type: self = .divInputFilterExpression(try DivInputFilterExpression(dictionary: dictionary, context: context)) default: - throw DeserializationError.invalidFieldRepresentation(field: "div-input-filter", representation: dictionary) + throw DeserializationError.requiredFieldIsMissing(field: "type") } } } diff --git a/client/ios/DivKit/generated_sources/DivInputFilterTemplate.swift b/client/ios/DivKit/generated_sources/DivInputFilterTemplate.swift index 041d2d14e..0a1c835e5 100644 --- a/client/ios/DivKit/generated_sources/DivInputFilterTemplate.swift +++ b/client/ios/DivKit/generated_sources/DivInputFilterTemplate.swift @@ -94,7 +94,7 @@ extension DivInputFilterTemplate { case DivInputFilterExpressionTemplate.type: self = .divInputFilterExpressionTemplate(try DivInputFilterExpressionTemplate(dictionary: dictionary, templateToType: templateToType)) default: - throw DeserializationError.invalidFieldRepresentation(field: "div-input-filter_template", representation: dictionary) + throw DeserializationError.requiredFieldIsMissing(field: "type") } } } diff --git a/client/ios/DivKit/generated_sources/DivInputMask.swift b/client/ios/DivKit/generated_sources/DivInputMask.swift index e77baffed..97b8e33c7 100644 --- a/client/ios/DivKit/generated_sources/DivInputMask.swift +++ b/client/ios/DivKit/generated_sources/DivInputMask.swift @@ -24,6 +24,7 @@ public enum DivInputMask: Sendable { extension DivInputMask { public init(dictionary: [String: Any], context: ParsingContext) throws { + let dictionary = context.templateResolver?(dictionary) ?? dictionary let blockType = try dictionary.getField("type") as String switch blockType { case DivFixedLengthInputMask.type: @@ -33,7 +34,7 @@ extension DivInputMask { case DivPhoneInputMask.type: self = .divPhoneInputMask(try DivPhoneInputMask(dictionary: dictionary, context: context)) default: - throw DeserializationError.invalidFieldRepresentation(field: "div-input-mask", representation: dictionary) + throw DeserializationError.requiredFieldIsMissing(field: "type") } } } diff --git a/client/ios/DivKit/generated_sources/DivInputMaskTemplate.swift b/client/ios/DivKit/generated_sources/DivInputMaskTemplate.swift index e193d608b..cbadb3274 100644 --- a/client/ios/DivKit/generated_sources/DivInputMaskTemplate.swift +++ b/client/ios/DivKit/generated_sources/DivInputMaskTemplate.swift @@ -117,7 +117,7 @@ extension DivInputMaskTemplate { case DivPhoneInputMaskTemplate.type: self = .divPhoneInputMaskTemplate(try DivPhoneInputMaskTemplate(dictionary: dictionary, templateToType: templateToType)) default: - throw DeserializationError.invalidFieldRepresentation(field: "div-input-mask_template", representation: dictionary) + throw DeserializationError.requiredFieldIsMissing(field: "type") } } } diff --git a/client/ios/DivKit/generated_sources/DivInputValidator.swift b/client/ios/DivKit/generated_sources/DivInputValidator.swift index 407703b7c..0fb116ab6 100644 --- a/client/ios/DivKit/generated_sources/DivInputValidator.swift +++ b/client/ios/DivKit/generated_sources/DivInputValidator.swift @@ -21,6 +21,7 @@ public enum DivInputValidator: Sendable { extension DivInputValidator { public init(dictionary: [String: Any], context: ParsingContext) throws { + let dictionary = context.templateResolver?(dictionary) ?? dictionary let blockType = try dictionary.getField("type") as String switch blockType { case DivInputValidatorRegex.type: @@ -28,7 +29,7 @@ extension DivInputValidator { case DivInputValidatorExpression.type: self = .divInputValidatorExpression(try DivInputValidatorExpression(dictionary: dictionary, context: context)) default: - throw DeserializationError.invalidFieldRepresentation(field: "div-input-validator", representation: dictionary) + throw DeserializationError.requiredFieldIsMissing(field: "type") } } } diff --git a/client/ios/DivKit/generated_sources/DivInputValidatorTemplate.swift b/client/ios/DivKit/generated_sources/DivInputValidatorTemplate.swift index 55bde3655..f64c308c4 100644 --- a/client/ios/DivKit/generated_sources/DivInputValidatorTemplate.swift +++ b/client/ios/DivKit/generated_sources/DivInputValidatorTemplate.swift @@ -94,7 +94,7 @@ extension DivInputValidatorTemplate { case DivInputValidatorExpressionTemplate.type: self = .divInputValidatorExpressionTemplate(try DivInputValidatorExpressionTemplate(dictionary: dictionary, templateToType: templateToType)) default: - throw DeserializationError.invalidFieldRepresentation(field: "div-input-validator_template", representation: dictionary) + throw DeserializationError.requiredFieldIsMissing(field: "type") } } } diff --git a/client/ios/DivKit/generated_sources/DivNeighbourPageSize.swift b/client/ios/DivKit/generated_sources/DivNeighbourPageSize.swift index 3a5f8525f..487f338d4 100644 --- a/client/ios/DivKit/generated_sources/DivNeighbourPageSize.swift +++ b/client/ios/DivKit/generated_sources/DivNeighbourPageSize.swift @@ -10,7 +10,7 @@ public final class DivNeighbourPageSize: Sendable { public convenience init(dictionary: [String: Any], context: ParsingContext) throws { self.init( - neighbourPageWidth: try dictionary.getField("neighbour_page_width", transform: { (dict: [String: Any]) in try DivFixedSize(dictionary: dict, context: context) }) + neighbourPageWidth: try dictionary.getField("neighbour_page_width", transform: { (dict: [String: Any]) in try DivFixedSize(dictionary: dict, context: context) }, context: context) ) } diff --git a/client/ios/DivKit/generated_sources/DivNinePatchBackground.swift b/client/ios/DivKit/generated_sources/DivNinePatchBackground.swift index 9db3cecc7..48d0fb371 100644 --- a/client/ios/DivKit/generated_sources/DivNinePatchBackground.swift +++ b/client/ios/DivKit/generated_sources/DivNinePatchBackground.swift @@ -16,7 +16,7 @@ public final class DivNinePatchBackground: Sendable { public convenience init(dictionary: [String: Any], context: ParsingContext) throws { self.init( imageUrl: try dictionary.getExpressionField("image_url", transform: URL.makeFromNonEncodedString, context: context), - insets: try dictionary.getField("insets", transform: { (dict: [String: Any]) in try DivAbsoluteEdgeInsets(dictionary: dict, context: context) }) + insets: try dictionary.getField("insets", transform: { (dict: [String: Any]) in try DivAbsoluteEdgeInsets(dictionary: dict, context: context) }, context: context) ) } diff --git a/client/ios/DivKit/generated_sources/DivPageSize.swift b/client/ios/DivKit/generated_sources/DivPageSize.swift index 3c46dfb5d..93f83986e 100644 --- a/client/ios/DivKit/generated_sources/DivPageSize.swift +++ b/client/ios/DivKit/generated_sources/DivPageSize.swift @@ -10,7 +10,7 @@ public final class DivPageSize: Sendable { public convenience init(dictionary: [String: Any], context: ParsingContext) throws { self.init( - pageWidth: try dictionary.getField("page_width", transform: { (dict: [String: Any]) in try DivPercentageSize(dictionary: dict, context: context) }) + pageWidth: try dictionary.getField("page_width", transform: { (dict: [String: Any]) in try DivPercentageSize(dictionary: dict, context: context) }, context: context) ) } diff --git a/client/ios/DivKit/generated_sources/DivPageTransformation.swift b/client/ios/DivKit/generated_sources/DivPageTransformation.swift index 4dabc3d6a..ad6fc9812 100644 --- a/client/ios/DivKit/generated_sources/DivPageTransformation.swift +++ b/client/ios/DivKit/generated_sources/DivPageTransformation.swift @@ -21,6 +21,7 @@ public enum DivPageTransformation: Sendable { extension DivPageTransformation { public init(dictionary: [String: Any], context: ParsingContext) throws { + let dictionary = context.templateResolver?(dictionary) ?? dictionary let blockType = try dictionary.getField("type") as String switch blockType { case DivPageTransformationSlide.type: @@ -28,7 +29,7 @@ extension DivPageTransformation { case DivPageTransformationOverlap.type: self = .divPageTransformationOverlap(try DivPageTransformationOverlap(dictionary: dictionary, context: context)) default: - throw DeserializationError.invalidFieldRepresentation(field: "div-page-transformation", representation: dictionary) + throw DeserializationError.requiredFieldIsMissing(field: "type") } } } diff --git a/client/ios/DivKit/generated_sources/DivPageTransformationTemplate.swift b/client/ios/DivKit/generated_sources/DivPageTransformationTemplate.swift index a6e337948..c781ac66a 100644 --- a/client/ios/DivKit/generated_sources/DivPageTransformationTemplate.swift +++ b/client/ios/DivKit/generated_sources/DivPageTransformationTemplate.swift @@ -94,7 +94,7 @@ extension DivPageTransformationTemplate { case DivPageTransformationOverlapTemplate.type: self = .divPageTransformationOverlapTemplate(try DivPageTransformationOverlapTemplate(dictionary: dictionary, templateToType: templateToType)) default: - throw DeserializationError.invalidFieldRepresentation(field: "div-page-transformation_template", representation: dictionary) + throw DeserializationError.requiredFieldIsMissing(field: "type") } } } diff --git a/client/ios/DivKit/generated_sources/DivPager.swift b/client/ios/DivKit/generated_sources/DivPager.swift index 0b1a4e57b..969e7ce2d 100644 --- a/client/ios/DivKit/generated_sources/DivPager.swift +++ b/client/ios/DivKit/generated_sources/DivPager.swift @@ -153,7 +153,7 @@ public final class DivPager: DivBase, Sendable { itemBuilder: try dictionary.getOptionalField("item_builder", transform: { (dict: [String: Any]) in try DivCollectionItemBuilder(dictionary: dict, context: context) }), itemSpacing: try dictionary.getOptionalField("item_spacing", transform: { (dict: [String: Any]) in try DivFixedSize(dictionary: dict, context: context) }), items: try dictionary.getOptionalArray("items", transform: { (dict: [String: Any]) in try? Div(dictionary: dict, context: context) }), - layoutMode: try dictionary.getField("layout_mode", transform: { (dict: [String: Any]) in try DivPagerLayoutMode(dictionary: dict, context: context) }), + layoutMode: try dictionary.getField("layout_mode", transform: { (dict: [String: Any]) in try DivPagerLayoutMode(dictionary: dict, context: context) }, context: context), layoutProvider: try dictionary.getOptionalField("layout_provider", transform: { (dict: [String: Any]) in try DivLayoutProvider(dictionary: dict, context: context) }), margins: try dictionary.getOptionalField("margins", transform: { (dict: [String: Any]) in try DivEdgeInsets(dictionary: dict, context: context) }), orientation: try dictionary.getOptionalExpressionField("orientation", context: context), diff --git a/client/ios/DivKit/generated_sources/DivPagerLayoutMode.swift b/client/ios/DivKit/generated_sources/DivPagerLayoutMode.swift index bd7f80143..23014257f 100644 --- a/client/ios/DivKit/generated_sources/DivPagerLayoutMode.swift +++ b/client/ios/DivKit/generated_sources/DivPagerLayoutMode.swift @@ -24,6 +24,7 @@ public enum DivPagerLayoutMode: Sendable { extension DivPagerLayoutMode { public init(dictionary: [String: Any], context: ParsingContext) throws { + let dictionary = context.templateResolver?(dictionary) ?? dictionary let blockType = try dictionary.getField("type") as String switch blockType { case DivPageSize.type: @@ -33,7 +34,7 @@ extension DivPagerLayoutMode { case DivPageContentSize.type: self = .divPageContentSize(try DivPageContentSize(dictionary: dictionary, context: context)) default: - throw DeserializationError.invalidFieldRepresentation(field: "div-pager-layout-mode", representation: dictionary) + throw DeserializationError.requiredFieldIsMissing(field: "type") } } } diff --git a/client/ios/DivKit/generated_sources/DivPagerLayoutModeTemplate.swift b/client/ios/DivKit/generated_sources/DivPagerLayoutModeTemplate.swift index f3e1bd9fd..f8ff7429b 100644 --- a/client/ios/DivKit/generated_sources/DivPagerLayoutModeTemplate.swift +++ b/client/ios/DivKit/generated_sources/DivPagerLayoutModeTemplate.swift @@ -117,7 +117,7 @@ extension DivPagerLayoutModeTemplate { case DivPageContentSizeTemplate.type: self = .divPageContentSizeTemplate(try DivPageContentSizeTemplate(dictionary: dictionary, templateToType: templateToType)) default: - throw DeserializationError.invalidFieldRepresentation(field: "div-pager-layout-mode_template", representation: dictionary) + throw DeserializationError.requiredFieldIsMissing(field: "type") } } } diff --git a/client/ios/DivKit/generated_sources/DivPatch.swift b/client/ios/DivKit/generated_sources/DivPatch.swift index 7d3f59dcd..0f8799753 100644 --- a/client/ios/DivKit/generated_sources/DivPatch.swift +++ b/client/ios/DivKit/generated_sources/DivPatch.swift @@ -45,7 +45,7 @@ public final class DivPatch: Sendable { public convenience init(dictionary: [String: Any], context: ParsingContext) throws { self.init( - changes: try dictionary.getArray("changes", transform: { (dict: [String: Any]) in try? DivPatch.Change(dictionary: dict, context: context) }, validator: Self.changesValidator), + changes: try dictionary.getArray("changes", transform: { (dict: [String: Any]) in try? DivPatch.Change(dictionary: dict, context: context) }, validator: Self.changesValidator, context: context), mode: try dictionary.getOptionalExpressionField("mode", context: context), onAppliedActions: try dictionary.getOptionalArray("on_applied_actions", transform: { (dict: [String: Any]) in try? DivAction(dictionary: dict, context: context) }), onFailedActions: try dictionary.getOptionalArray("on_failed_actions", transform: { (dict: [String: Any]) in try? DivAction(dictionary: dict, context: context) }) diff --git a/client/ios/DivKit/generated_sources/DivPivot.swift b/client/ios/DivKit/generated_sources/DivPivot.swift index 11273abe7..3e9890893 100644 --- a/client/ios/DivKit/generated_sources/DivPivot.swift +++ b/client/ios/DivKit/generated_sources/DivPivot.swift @@ -21,6 +21,7 @@ public enum DivPivot: Sendable { extension DivPivot { public init(dictionary: [String: Any], context: ParsingContext) throws { + let dictionary = context.templateResolver?(dictionary) ?? dictionary let blockType = try dictionary.getField("type") as String switch blockType { case DivPivotFixed.type: @@ -28,7 +29,7 @@ extension DivPivot { case DivPivotPercentage.type: self = .divPivotPercentage(try DivPivotPercentage(dictionary: dictionary, context: context)) default: - throw DeserializationError.invalidFieldRepresentation(field: "div-pivot", representation: dictionary) + throw DeserializationError.requiredFieldIsMissing(field: "type") } } } diff --git a/client/ios/DivKit/generated_sources/DivPivotTemplate.swift b/client/ios/DivKit/generated_sources/DivPivotTemplate.swift index 08c6be7dc..c51e47b30 100644 --- a/client/ios/DivKit/generated_sources/DivPivotTemplate.swift +++ b/client/ios/DivKit/generated_sources/DivPivotTemplate.swift @@ -93,7 +93,7 @@ extension DivPivotTemplate { case DivPivotPercentageTemplate.type: self = .divPivotPercentageTemplate(try DivPivotPercentageTemplate(dictionary: dictionary, templateToType: templateToType)) default: - throw DeserializationError.invalidFieldRepresentation(field: "div-pivot_template", representation: dictionary) + throw DeserializationError.requiredFieldIsMissing(field: "type") } } } diff --git a/client/ios/DivKit/generated_sources/DivPoint.swift b/client/ios/DivKit/generated_sources/DivPoint.swift index 77aa17a72..3ab12bedb 100644 --- a/client/ios/DivKit/generated_sources/DivPoint.swift +++ b/client/ios/DivKit/generated_sources/DivPoint.swift @@ -10,8 +10,8 @@ public final class DivPoint: Sendable { public convenience init(dictionary: [String: Any], context: ParsingContext) throws { self.init( - x: try dictionary.getField("x", transform: { (dict: [String: Any]) in try DivDimension(dictionary: dict, context: context) }), - y: try dictionary.getField("y", transform: { (dict: [String: Any]) in try DivDimension(dictionary: dict, context: context) }) + x: try dictionary.getField("x", transform: { (dict: [String: Any]) in try DivDimension(dictionary: dict, context: context) }, context: context), + y: try dictionary.getField("y", transform: { (dict: [String: Any]) in try DivDimension(dictionary: dict, context: context) }, context: context) ) } diff --git a/client/ios/DivKit/generated_sources/DivRadialGradientCenter.swift b/client/ios/DivKit/generated_sources/DivRadialGradientCenter.swift index 2c95865bd..be72f8c6b 100644 --- a/client/ios/DivKit/generated_sources/DivRadialGradientCenter.swift +++ b/client/ios/DivKit/generated_sources/DivRadialGradientCenter.swift @@ -21,6 +21,7 @@ public enum DivRadialGradientCenter: Sendable { extension DivRadialGradientCenter { public init(dictionary: [String: Any], context: ParsingContext) throws { + let dictionary = context.templateResolver?(dictionary) ?? dictionary let blockType = try dictionary.getField("type") as String switch blockType { case DivRadialGradientFixedCenter.type: @@ -28,7 +29,7 @@ extension DivRadialGradientCenter { case DivRadialGradientRelativeCenter.type: self = .divRadialGradientRelativeCenter(try DivRadialGradientRelativeCenter(dictionary: dictionary, context: context)) default: - throw DeserializationError.invalidFieldRepresentation(field: "div-radial-gradient-center", representation: dictionary) + throw DeserializationError.requiredFieldIsMissing(field: "type") } } } diff --git a/client/ios/DivKit/generated_sources/DivRadialGradientCenterTemplate.swift b/client/ios/DivKit/generated_sources/DivRadialGradientCenterTemplate.swift index b7ab6e859..1e2008af9 100644 --- a/client/ios/DivKit/generated_sources/DivRadialGradientCenterTemplate.swift +++ b/client/ios/DivKit/generated_sources/DivRadialGradientCenterTemplate.swift @@ -94,7 +94,7 @@ extension DivRadialGradientCenterTemplate { case DivRadialGradientRelativeCenterTemplate.type: self = .divRadialGradientRelativeCenterTemplate(try DivRadialGradientRelativeCenterTemplate(dictionary: dictionary, templateToType: templateToType)) default: - throw DeserializationError.invalidFieldRepresentation(field: "div-radial-gradient-center_template", representation: dictionary) + throw DeserializationError.requiredFieldIsMissing(field: "type") } } } diff --git a/client/ios/DivKit/generated_sources/DivRadialGradientRadius.swift b/client/ios/DivKit/generated_sources/DivRadialGradientRadius.swift index affa48442..a4474378f 100644 --- a/client/ios/DivKit/generated_sources/DivRadialGradientRadius.swift +++ b/client/ios/DivKit/generated_sources/DivRadialGradientRadius.swift @@ -21,6 +21,7 @@ public enum DivRadialGradientRadius: Sendable { extension DivRadialGradientRadius { public init(dictionary: [String: Any], context: ParsingContext) throws { + let dictionary = context.templateResolver?(dictionary) ?? dictionary let blockType = try dictionary.getField("type") as String switch blockType { case DivFixedSize.type: @@ -28,7 +29,7 @@ extension DivRadialGradientRadius { case DivRadialGradientRelativeRadius.type: self = .divRadialGradientRelativeRadius(try DivRadialGradientRelativeRadius(dictionary: dictionary, context: context)) default: - throw DeserializationError.invalidFieldRepresentation(field: "div-radial-gradient-radius", representation: dictionary) + throw DeserializationError.requiredFieldIsMissing(field: "type") } } } diff --git a/client/ios/DivKit/generated_sources/DivRadialGradientRadiusTemplate.swift b/client/ios/DivKit/generated_sources/DivRadialGradientRadiusTemplate.swift index 2d55a67e5..48b0d95c3 100644 --- a/client/ios/DivKit/generated_sources/DivRadialGradientRadiusTemplate.swift +++ b/client/ios/DivKit/generated_sources/DivRadialGradientRadiusTemplate.swift @@ -94,7 +94,7 @@ extension DivRadialGradientRadiusTemplate { case DivRadialGradientRelativeRadiusTemplate.type: self = .divRadialGradientRelativeRadiusTemplate(try DivRadialGradientRelativeRadiusTemplate(dictionary: dictionary, templateToType: templateToType)) default: - throw DeserializationError.invalidFieldRepresentation(field: "div-radial-gradient-radius_template", representation: dictionary) + throw DeserializationError.requiredFieldIsMissing(field: "type") } } } diff --git a/client/ios/DivKit/generated_sources/DivSelect.swift b/client/ios/DivKit/generated_sources/DivSelect.swift index 714382218..ede918cf7 100644 --- a/client/ios/DivKit/generated_sources/DivSelect.swift +++ b/client/ios/DivKit/generated_sources/DivSelect.swift @@ -205,7 +205,7 @@ public final class DivSelect: DivBase, @unchecked Sendable { letterSpacing: try dictionary.getOptionalExpressionField("letter_spacing", context: context), lineHeight: try dictionary.getOptionalExpressionField("line_height", validator: Self.lineHeightValidator, context: context), margins: try dictionary.getOptionalField("margins", transform: { (dict: [String: Any]) in try DivEdgeInsets(dictionary: dict, context: context) }), - options: try dictionary.getArray("options", transform: { (dict: [String: Any]) in try? DivSelect.Option(dictionary: dict, context: context) }, validator: Self.optionsValidator), + options: try dictionary.getArray("options", transform: { (dict: [String: Any]) in try? DivSelect.Option(dictionary: dict, context: context) }, validator: Self.optionsValidator, context: context), paddings: try dictionary.getOptionalField("paddings", transform: { (dict: [String: Any]) in try DivEdgeInsets(dictionary: dict, context: context) }), reuseId: try dictionary.getOptionalExpressionField("reuse_id", context: context), rowSpan: try dictionary.getOptionalExpressionField("row_span", validator: Self.rowSpanValidator, context: context), diff --git a/client/ios/DivKit/generated_sources/DivShadow.swift b/client/ios/DivKit/generated_sources/DivShadow.swift index dbb9c0cfe..9e735d9e6 100644 --- a/client/ios/DivKit/generated_sources/DivShadow.swift +++ b/client/ios/DivKit/generated_sources/DivShadow.swift @@ -33,7 +33,7 @@ public final class DivShadow: Sendable { alpha: try dictionary.getOptionalExpressionField("alpha", validator: Self.alphaValidator, context: context), blur: try dictionary.getOptionalExpressionField("blur", validator: Self.blurValidator, context: context), color: try dictionary.getOptionalExpressionField("color", transform: Color.color(withHexString:), context: context), - offset: try dictionary.getField("offset", transform: { (dict: [String: Any]) in try DivPoint(dictionary: dict, context: context) }) + offset: try dictionary.getField("offset", transform: { (dict: [String: Any]) in try DivPoint(dictionary: dict, context: context) }, context: context) ) } diff --git a/client/ios/DivKit/generated_sources/DivShape.swift b/client/ios/DivKit/generated_sources/DivShape.swift index c45f87abd..1aa1de146 100644 --- a/client/ios/DivKit/generated_sources/DivShape.swift +++ b/client/ios/DivKit/generated_sources/DivShape.swift @@ -21,6 +21,7 @@ public enum DivShape: Sendable { extension DivShape { public init(dictionary: [String: Any], context: ParsingContext) throws { + let dictionary = context.templateResolver?(dictionary) ?? dictionary let blockType = try dictionary.getField("type") as String switch blockType { case DivRoundedRectangleShape.type: @@ -28,7 +29,7 @@ extension DivShape { case DivCircleShape.type: self = .divCircleShape(try DivCircleShape(dictionary: dictionary, context: context)) default: - throw DeserializationError.invalidFieldRepresentation(field: "div-shape", representation: dictionary) + throw DeserializationError.requiredFieldIsMissing(field: "type") } } } diff --git a/client/ios/DivKit/generated_sources/DivShapeDrawable.swift b/client/ios/DivKit/generated_sources/DivShapeDrawable.swift index a8b0a3501..10881ad91 100644 --- a/client/ios/DivKit/generated_sources/DivShapeDrawable.swift +++ b/client/ios/DivKit/generated_sources/DivShapeDrawable.swift @@ -17,7 +17,7 @@ public final class DivShapeDrawable: Sendable { public convenience init(dictionary: [String: Any], context: ParsingContext) throws { self.init( color: try dictionary.getExpressionField("color", transform: Color.color(withHexString:), context: context), - shape: try dictionary.getField("shape", transform: { (dict: [String: Any]) in try DivShape(dictionary: dict, context: context) }), + shape: try dictionary.getField("shape", transform: { (dict: [String: Any]) in try DivShape(dictionary: dict, context: context) }, context: context), stroke: try dictionary.getOptionalField("stroke", transform: { (dict: [String: Any]) in try DivStroke(dictionary: dict, context: context) }) ) } diff --git a/client/ios/DivKit/generated_sources/DivShapeTemplate.swift b/client/ios/DivKit/generated_sources/DivShapeTemplate.swift index ec98c7164..e21edcb83 100644 --- a/client/ios/DivKit/generated_sources/DivShapeTemplate.swift +++ b/client/ios/DivKit/generated_sources/DivShapeTemplate.swift @@ -94,7 +94,7 @@ extension DivShapeTemplate { case DivCircleShapeTemplate.type: self = .divCircleShapeTemplate(try DivCircleShapeTemplate(dictionary: dictionary, templateToType: templateToType)) default: - throw DeserializationError.invalidFieldRepresentation(field: "div-shape_template", representation: dictionary) + throw DeserializationError.requiredFieldIsMissing(field: "type") } } } diff --git a/client/ios/DivKit/generated_sources/DivSize.swift b/client/ios/DivKit/generated_sources/DivSize.swift index 36b53d2df..8ca7a488e 100644 --- a/client/ios/DivKit/generated_sources/DivSize.swift +++ b/client/ios/DivKit/generated_sources/DivSize.swift @@ -24,6 +24,7 @@ public enum DivSize: Sendable { extension DivSize { public init(dictionary: [String: Any], context: ParsingContext) throws { + let dictionary = context.templateResolver?(dictionary) ?? dictionary let blockType = try dictionary.getField("type") as String switch blockType { case DivFixedSize.type: @@ -33,7 +34,7 @@ extension DivSize { case DivWrapContentSize.type: self = .divWrapContentSize(try DivWrapContentSize(dictionary: dictionary, context: context)) default: - throw DeserializationError.invalidFieldRepresentation(field: "div-size", representation: dictionary) + throw DeserializationError.requiredFieldIsMissing(field: "type") } } } diff --git a/client/ios/DivKit/generated_sources/DivSizeTemplate.swift b/client/ios/DivKit/generated_sources/DivSizeTemplate.swift index 115b470cc..435d853a7 100644 --- a/client/ios/DivKit/generated_sources/DivSizeTemplate.swift +++ b/client/ios/DivKit/generated_sources/DivSizeTemplate.swift @@ -117,7 +117,7 @@ extension DivSizeTemplate { case DivWrapContentSizeTemplate.type: self = .divWrapContentSizeTemplate(try DivWrapContentSizeTemplate(dictionary: dictionary, templateToType: templateToType)) default: - throw DeserializationError.invalidFieldRepresentation(field: "div-size_template", representation: dictionary) + throw DeserializationError.requiredFieldIsMissing(field: "type") } } } diff --git a/client/ios/DivKit/generated_sources/DivSlider.swift b/client/ios/DivKit/generated_sources/DivSlider.swift index 4e21620d3..ef4bf338b 100644 --- a/client/ios/DivKit/generated_sources/DivSlider.swift +++ b/client/ios/DivKit/generated_sources/DivSlider.swift @@ -263,14 +263,14 @@ public final class DivSlider: DivBase, Sendable { thumbSecondaryStyle: try dictionary.getOptionalField("thumb_secondary_style", transform: { (dict: [String: Any]) in try DivDrawable(dictionary: dict, context: context) }), thumbSecondaryTextStyle: try dictionary.getOptionalField("thumb_secondary_text_style", transform: { (dict: [String: Any]) in try DivSlider.TextStyle(dictionary: dict, context: context) }), thumbSecondaryValueVariable: try dictionary.getOptionalField("thumb_secondary_value_variable", context: context), - thumbStyle: try dictionary.getField("thumb_style", transform: { (dict: [String: Any]) in try DivDrawable(dictionary: dict, context: context) }), + thumbStyle: try dictionary.getField("thumb_style", transform: { (dict: [String: Any]) in try DivDrawable(dictionary: dict, context: context) }, context: context), thumbTextStyle: try dictionary.getOptionalField("thumb_text_style", transform: { (dict: [String: Any]) in try DivSlider.TextStyle(dictionary: dict, context: context) }), thumbValueVariable: try dictionary.getOptionalField("thumb_value_variable", context: context), tickMarkActiveStyle: try dictionary.getOptionalField("tick_mark_active_style", transform: { (dict: [String: Any]) in try DivDrawable(dictionary: dict, context: context) }), tickMarkInactiveStyle: try dictionary.getOptionalField("tick_mark_inactive_style", transform: { (dict: [String: Any]) in try DivDrawable(dictionary: dict, context: context) }), tooltips: try dictionary.getOptionalArray("tooltips", transform: { (dict: [String: Any]) in try? DivTooltip(dictionary: dict, context: context) }), - trackActiveStyle: try dictionary.getField("track_active_style", transform: { (dict: [String: Any]) in try DivDrawable(dictionary: dict, context: context) }), - trackInactiveStyle: try dictionary.getField("track_inactive_style", transform: { (dict: [String: Any]) in try DivDrawable(dictionary: dict, context: context) }), + trackActiveStyle: try dictionary.getField("track_active_style", transform: { (dict: [String: Any]) in try DivDrawable(dictionary: dict, context: context) }, context: context), + trackInactiveStyle: try dictionary.getField("track_inactive_style", transform: { (dict: [String: Any]) in try DivDrawable(dictionary: dict, context: context) }, context: context), transform: try dictionary.getOptionalField("transform", transform: { (dict: [String: Any]) in try DivTransform(dictionary: dict, context: context) }), transformations: try dictionary.getOptionalArray("transformations", transform: { (dict: [String: Any]) in try? DivTransformation(dictionary: dict, context: context) }), transitionChange: try dictionary.getOptionalField("transition_change", transform: { (dict: [String: Any]) in try DivChangeTransition(dictionary: dict, context: context) }), diff --git a/client/ios/DivKit/generated_sources/DivState.swift b/client/ios/DivKit/generated_sources/DivState.swift index ed8c3d3c1..6346972c7 100644 --- a/client/ios/DivKit/generated_sources/DivState.swift +++ b/client/ios/DivKit/generated_sources/DivState.swift @@ -183,7 +183,7 @@ public final class DivState: DivBase, Sendable { rowSpan: try dictionary.getOptionalExpressionField("row_span", validator: Self.rowSpanValidator, context: context), selectedActions: try dictionary.getOptionalArray("selected_actions", transform: { (dict: [String: Any]) in try? DivAction(dictionary: dict, context: context) }), stateIdVariable: try dictionary.getOptionalField("state_id_variable", context: context), - states: try dictionary.getArray("states", transform: { (dict: [String: Any]) in try? DivState.State(dictionary: dict, context: context) }, validator: Self.statesValidator), + states: try dictionary.getArray("states", transform: { (dict: [String: Any]) in try? DivState.State(dictionary: dict, context: context) }, validator: Self.statesValidator, context: context), tooltips: try dictionary.getOptionalArray("tooltips", transform: { (dict: [String: Any]) in try? DivTooltip(dictionary: dict, context: context) }), transform: try dictionary.getOptionalField("transform", transform: { (dict: [String: Any]) in try DivTransform(dictionary: dict, context: context) }), transformations: try dictionary.getOptionalArray("transformations", transform: { (dict: [String: Any]) in try? DivTransformation(dictionary: dict, context: context) }), diff --git a/client/ios/DivKit/generated_sources/DivStrokeStyle.swift b/client/ios/DivKit/generated_sources/DivStrokeStyle.swift index 4a461a632..f4a54739d 100644 --- a/client/ios/DivKit/generated_sources/DivStrokeStyle.swift +++ b/client/ios/DivKit/generated_sources/DivStrokeStyle.swift @@ -21,6 +21,7 @@ public enum DivStrokeStyle: Sendable { extension DivStrokeStyle { public init(dictionary: [String: Any], context: ParsingContext) throws { + let dictionary = context.templateResolver?(dictionary) ?? dictionary let blockType = try dictionary.getField("type") as String switch blockType { case DivStrokeStyleSolid.type: @@ -28,7 +29,7 @@ extension DivStrokeStyle { case DivStrokeStyleDashed.type: self = .divStrokeStyleDashed(try DivStrokeStyleDashed(dictionary: dictionary, context: context)) default: - throw DeserializationError.invalidFieldRepresentation(field: "div-stroke-style", representation: dictionary) + throw DeserializationError.requiredFieldIsMissing(field: "type") } } } diff --git a/client/ios/DivKit/generated_sources/DivStrokeStyleTemplate.swift b/client/ios/DivKit/generated_sources/DivStrokeStyleTemplate.swift index 5551e1f49..2fbcc3c9e 100644 --- a/client/ios/DivKit/generated_sources/DivStrokeStyleTemplate.swift +++ b/client/ios/DivKit/generated_sources/DivStrokeStyleTemplate.swift @@ -94,7 +94,7 @@ extension DivStrokeStyleTemplate { case DivStrokeStyleDashedTemplate.type: self = .divStrokeStyleDashedTemplate(try DivStrokeStyleDashedTemplate(dictionary: dictionary, templateToType: templateToType)) default: - throw DeserializationError.invalidFieldRepresentation(field: "div-stroke-style_template", representation: dictionary) + throw DeserializationError.requiredFieldIsMissing(field: "type") } } } diff --git a/client/ios/DivKit/generated_sources/DivTabs.swift b/client/ios/DivKit/generated_sources/DivTabs.swift index 8f14e4c06..2f35d7cd1 100644 --- a/client/ios/DivKit/generated_sources/DivTabs.swift +++ b/client/ios/DivKit/generated_sources/DivTabs.swift @@ -16,7 +16,7 @@ public final class DivTabs: DivBase, Sendable { public convenience init(dictionary: [String: Any], context: ParsingContext) throws { self.init( - div: try dictionary.getField("div", transform: { (dict: [String: Any]) in try Div(dictionary: dict, context: context) }), + div: try dictionary.getField("div", transform: { (dict: [String: Any]) in try Div(dictionary: dict, context: context) }, context: context), title: try dictionary.getExpressionField("title", context: context), titleClickAction: try dictionary.getOptionalField("title_click_action", transform: { (dict: [String: Any]) in try DivAction(dictionary: dict, context: context) }) ) @@ -381,7 +381,7 @@ public final class DivTabs: DivBase, Sendable { hasSeparator: try dictionary.getOptionalExpressionField("has_separator", context: context), height: try dictionary.getOptionalField("height", transform: { (dict: [String: Any]) in try DivSize(dictionary: dict, context: context) }), id: try dictionary.getOptionalField("id", context: context), - items: try dictionary.getArray("items", transform: { (dict: [String: Any]) in try? DivTabs.Item(dictionary: dict, context: context) }, validator: Self.itemsValidator), + items: try dictionary.getArray("items", transform: { (dict: [String: Any]) in try? DivTabs.Item(dictionary: dict, context: context) }, validator: Self.itemsValidator, context: context), layoutProvider: try dictionary.getOptionalField("layout_provider", transform: { (dict: [String: Any]) in try DivLayoutProvider(dictionary: dict, context: context) }), margins: try dictionary.getOptionalField("margins", transform: { (dict: [String: Any]) in try DivEdgeInsets(dictionary: dict, context: context) }), paddings: try dictionary.getOptionalField("paddings", transform: { (dict: [String: Any]) in try DivEdgeInsets(dictionary: dict, context: context) }), diff --git a/client/ios/DivKit/generated_sources/DivTemplate.swift b/client/ios/DivKit/generated_sources/DivTemplate.swift index 95f8e9323..5256edb7e 100644 --- a/client/ios/DivKit/generated_sources/DivTemplate.swift +++ b/client/ios/DivKit/generated_sources/DivTemplate.swift @@ -439,7 +439,7 @@ extension DivTemplate { case DivVideoTemplate.type: self = .divVideoTemplate(try DivVideoTemplate(dictionary: dictionary, templateToType: templateToType)) default: - throw DeserializationError.invalidFieldRepresentation(field: "div_template", representation: dictionary) + throw DeserializationError.requiredFieldIsMissing(field: "type") } } } diff --git a/client/ios/DivKit/generated_sources/DivTextGradient.swift b/client/ios/DivKit/generated_sources/DivTextGradient.swift index 1d5ebf1db..5d7950a6b 100644 --- a/client/ios/DivKit/generated_sources/DivTextGradient.swift +++ b/client/ios/DivKit/generated_sources/DivTextGradient.swift @@ -21,6 +21,7 @@ public enum DivTextGradient: Sendable { extension DivTextGradient { public init(dictionary: [String: Any], context: ParsingContext) throws { + let dictionary = context.templateResolver?(dictionary) ?? dictionary let blockType = try dictionary.getField("type") as String switch blockType { case DivLinearGradient.type: @@ -28,7 +29,7 @@ extension DivTextGradient { case DivRadialGradient.type: self = .divRadialGradient(try DivRadialGradient(dictionary: dictionary, context: context)) default: - throw DeserializationError.invalidFieldRepresentation(field: "div-text-gradient", representation: dictionary) + throw DeserializationError.requiredFieldIsMissing(field: "type") } } } diff --git a/client/ios/DivKit/generated_sources/DivTextGradientTemplate.swift b/client/ios/DivKit/generated_sources/DivTextGradientTemplate.swift index 25eb8064a..9d1108d26 100644 --- a/client/ios/DivKit/generated_sources/DivTextGradientTemplate.swift +++ b/client/ios/DivKit/generated_sources/DivTextGradientTemplate.swift @@ -94,7 +94,7 @@ extension DivTextGradientTemplate { case DivRadialGradientTemplate.type: self = .divRadialGradientTemplate(try DivRadialGradientTemplate(dictionary: dictionary, templateToType: templateToType)) default: - throw DeserializationError.invalidFieldRepresentation(field: "div-text-gradient_template", representation: dictionary) + throw DeserializationError.requiredFieldIsMissing(field: "type") } } } diff --git a/client/ios/DivKit/generated_sources/DivTextRangeBackground.swift b/client/ios/DivKit/generated_sources/DivTextRangeBackground.swift index 08e59d66c..56c087109 100644 --- a/client/ios/DivKit/generated_sources/DivTextRangeBackground.swift +++ b/client/ios/DivKit/generated_sources/DivTextRangeBackground.swift @@ -21,6 +21,7 @@ public enum DivTextRangeBackground: Sendable { extension DivTextRangeBackground { public init(dictionary: [String: Any], context: ParsingContext) throws { + let dictionary = context.templateResolver?(dictionary) ?? dictionary let blockType = try dictionary.getField("type") as String switch blockType { case DivSolidBackground.type: @@ -28,7 +29,7 @@ extension DivTextRangeBackground { case DivCloudBackground.type: self = .divCloudBackground(try DivCloudBackground(dictionary: dictionary, context: context)) default: - throw DeserializationError.invalidFieldRepresentation(field: "div-text-range-background", representation: dictionary) + throw DeserializationError.requiredFieldIsMissing(field: "type") } } } diff --git a/client/ios/DivKit/generated_sources/DivTextRangeBackgroundTemplate.swift b/client/ios/DivKit/generated_sources/DivTextRangeBackgroundTemplate.swift index 89a0a59f5..f2f90bcc1 100644 --- a/client/ios/DivKit/generated_sources/DivTextRangeBackgroundTemplate.swift +++ b/client/ios/DivKit/generated_sources/DivTextRangeBackgroundTemplate.swift @@ -94,7 +94,7 @@ extension DivTextRangeBackgroundTemplate { case DivCloudBackgroundTemplate.type: self = .divCloudBackgroundTemplate(try DivCloudBackgroundTemplate(dictionary: dictionary, templateToType: templateToType)) default: - throw DeserializationError.invalidFieldRepresentation(field: "div-text-range-background_template", representation: dictionary) + throw DeserializationError.requiredFieldIsMissing(field: "type") } } } diff --git a/client/ios/DivKit/generated_sources/DivTextRangeMask.swift b/client/ios/DivKit/generated_sources/DivTextRangeMask.swift index aa99b0de2..7a17a4d08 100644 --- a/client/ios/DivKit/generated_sources/DivTextRangeMask.swift +++ b/client/ios/DivKit/generated_sources/DivTextRangeMask.swift @@ -21,6 +21,7 @@ public enum DivTextRangeMask: Sendable { extension DivTextRangeMask { public init(dictionary: [String: Any], context: ParsingContext) throws { + let dictionary = context.templateResolver?(dictionary) ?? dictionary let blockType = try dictionary.getField("type") as String switch blockType { case DivTextRangeMaskParticles.type: @@ -28,7 +29,7 @@ extension DivTextRangeMask { case DivTextRangeMaskSolid.type: self = .divTextRangeMaskSolid(try DivTextRangeMaskSolid(dictionary: dictionary, context: context)) default: - throw DeserializationError.invalidFieldRepresentation(field: "div-text-range-mask", representation: dictionary) + throw DeserializationError.requiredFieldIsMissing(field: "type") } } } diff --git a/client/ios/DivKit/generated_sources/DivTextRangeMaskTemplate.swift b/client/ios/DivKit/generated_sources/DivTextRangeMaskTemplate.swift index 4e239bf70..4d3ced9f8 100644 --- a/client/ios/DivKit/generated_sources/DivTextRangeMaskTemplate.swift +++ b/client/ios/DivKit/generated_sources/DivTextRangeMaskTemplate.swift @@ -94,7 +94,7 @@ extension DivTextRangeMaskTemplate { case DivTextRangeMaskSolidTemplate.type: self = .divTextRangeMaskSolidTemplate(try DivTextRangeMaskSolidTemplate(dictionary: dictionary, templateToType: templateToType)) default: - throw DeserializationError.invalidFieldRepresentation(field: "div-text-range-mask_template", representation: dictionary) + throw DeserializationError.requiredFieldIsMissing(field: "type") } } } diff --git a/client/ios/DivKit/generated_sources/DivTooltip.swift b/client/ios/DivKit/generated_sources/DivTooltip.swift index 3d289a4f1..be9e8c931 100644 --- a/client/ios/DivKit/generated_sources/DivTooltip.swift +++ b/client/ios/DivKit/generated_sources/DivTooltip.swift @@ -58,7 +58,7 @@ public final class DivTooltip: Sendable { backgroundAccessibilityDescription: try dictionary.getOptionalExpressionField("background_accessibility_description", context: context), bringToTopId: try dictionary.getOptionalField("bring_to_top_id", context: context), closeByTapOutside: try dictionary.getOptionalExpressionField("close_by_tap_outside", context: context), - div: try dictionary.getField("div", transform: { (dict: [String: Any]) in try Div(dictionary: dict, context: context) }), + div: try dictionary.getField("div", transform: { (dict: [String: Any]) in try Div(dictionary: dict, context: context) }, context: context), duration: try dictionary.getOptionalExpressionField("duration", validator: Self.durationValidator, context: context), id: try dictionary.getField("id", context: context), mode: try dictionary.getOptionalField("mode", transform: { (dict: [String: Any]) in try DivTooltipMode(dictionary: dict, context: context) }), diff --git a/client/ios/DivKit/generated_sources/DivTooltipMode.swift b/client/ios/DivKit/generated_sources/DivTooltipMode.swift index f902749db..eb2e8b5d2 100644 --- a/client/ios/DivKit/generated_sources/DivTooltipMode.swift +++ b/client/ios/DivKit/generated_sources/DivTooltipMode.swift @@ -21,6 +21,7 @@ public enum DivTooltipMode: Sendable { extension DivTooltipMode { public init(dictionary: [String: Any], context: ParsingContext) throws { + let dictionary = context.templateResolver?(dictionary) ?? dictionary let blockType = try dictionary.getField("type") as String switch blockType { case DivTooltipModeNonModal.type: @@ -28,7 +29,7 @@ extension DivTooltipMode { case DivTooltipModeModal.type: self = .divTooltipModeModal(try DivTooltipModeModal(dictionary: dictionary, context: context)) default: - throw DeserializationError.invalidFieldRepresentation(field: "div-tooltip-mode", representation: dictionary) + throw DeserializationError.requiredFieldIsMissing(field: "type") } } } diff --git a/client/ios/DivKit/generated_sources/DivTooltipModeTemplate.swift b/client/ios/DivKit/generated_sources/DivTooltipModeTemplate.swift index 36e7c9985..94572de19 100644 --- a/client/ios/DivKit/generated_sources/DivTooltipModeTemplate.swift +++ b/client/ios/DivKit/generated_sources/DivTooltipModeTemplate.swift @@ -94,7 +94,7 @@ extension DivTooltipModeTemplate { case DivTooltipModeModalTemplate.type: self = .divTooltipModeModalTemplate(try DivTooltipModeModalTemplate(dictionary: dictionary, templateToType: templateToType)) default: - throw DeserializationError.invalidFieldRepresentation(field: "div-tooltip-mode_template", representation: dictionary) + throw DeserializationError.requiredFieldIsMissing(field: "type") } } } diff --git a/client/ios/DivKit/generated_sources/DivTransformation.swift b/client/ios/DivKit/generated_sources/DivTransformation.swift index 8bd1929ea..e6d01c43e 100644 --- a/client/ios/DivKit/generated_sources/DivTransformation.swift +++ b/client/ios/DivKit/generated_sources/DivTransformation.swift @@ -21,6 +21,7 @@ public enum DivTransformation: Sendable { extension DivTransformation { public init(dictionary: [String: Any], context: ParsingContext) throws { + let dictionary = context.templateResolver?(dictionary) ?? dictionary let blockType = try dictionary.getField("type") as String switch blockType { case DivRotationTransformation.type: @@ -28,7 +29,7 @@ extension DivTransformation { case DivTranslationTransformation.type: self = .divTranslationTransformation(try DivTranslationTransformation(dictionary: dictionary, context: context)) default: - throw DeserializationError.invalidFieldRepresentation(field: "div-transformation", representation: dictionary) + throw DeserializationError.requiredFieldIsMissing(field: "type") } } } diff --git a/client/ios/DivKit/generated_sources/DivTransformationTemplate.swift b/client/ios/DivKit/generated_sources/DivTransformationTemplate.swift index 9f8d216fd..f284a2ce9 100644 --- a/client/ios/DivKit/generated_sources/DivTransformationTemplate.swift +++ b/client/ios/DivKit/generated_sources/DivTransformationTemplate.swift @@ -94,7 +94,7 @@ extension DivTransformationTemplate { case DivTranslationTransformationTemplate.type: self = .divTranslationTransformationTemplate(try DivTranslationTransformationTemplate(dictionary: dictionary, templateToType: templateToType)) default: - throw DeserializationError.invalidFieldRepresentation(field: "div-transformation_template", representation: dictionary) + throw DeserializationError.requiredFieldIsMissing(field: "type") } } } diff --git a/client/ios/DivKit/generated_sources/DivTranslation.swift b/client/ios/DivKit/generated_sources/DivTranslation.swift index 4a1e1d201..288ae0542 100644 --- a/client/ios/DivKit/generated_sources/DivTranslation.swift +++ b/client/ios/DivKit/generated_sources/DivTranslation.swift @@ -21,6 +21,7 @@ public enum DivTranslation: Sendable { extension DivTranslation { public init(dictionary: [String: Any], context: ParsingContext) throws { + let dictionary = context.templateResolver?(dictionary) ?? dictionary let blockType = try dictionary.getField("type") as String switch blockType { case DivFixedTranslation.type: @@ -28,7 +29,7 @@ extension DivTranslation { case DivPercentageTranslation.type: self = .divPercentageTranslation(try DivPercentageTranslation(dictionary: dictionary, context: context)) default: - throw DeserializationError.invalidFieldRepresentation(field: "div-translation", representation: dictionary) + throw DeserializationError.requiredFieldIsMissing(field: "type") } } } diff --git a/client/ios/DivKit/generated_sources/DivTranslationTemplate.swift b/client/ios/DivKit/generated_sources/DivTranslationTemplate.swift index 2c7032790..a766e3cab 100644 --- a/client/ios/DivKit/generated_sources/DivTranslationTemplate.swift +++ b/client/ios/DivKit/generated_sources/DivTranslationTemplate.swift @@ -94,7 +94,7 @@ extension DivTranslationTemplate { case DivPercentageTranslationTemplate.type: self = .divPercentageTranslationTemplate(try DivPercentageTranslationTemplate(dictionary: dictionary, templateToType: templateToType)) default: - throw DeserializationError.invalidFieldRepresentation(field: "div-translation_template", representation: dictionary) + throw DeserializationError.requiredFieldIsMissing(field: "type") } } } diff --git a/client/ios/DivKit/generated_sources/DivTrigger.swift b/client/ios/DivKit/generated_sources/DivTrigger.swift index 2d4b92200..0c5487055 100644 --- a/client/ios/DivKit/generated_sources/DivTrigger.swift +++ b/client/ios/DivKit/generated_sources/DivTrigger.swift @@ -28,7 +28,7 @@ public final class DivTrigger: Sendable { public convenience init(dictionary: [String: Any], context: ParsingContext) throws { self.init( - actions: try dictionary.getArray("actions", transform: { (dict: [String: Any]) in try? DivAction(dictionary: dict, context: context) }, validator: Self.actionsValidator), + actions: try dictionary.getArray("actions", transform: { (dict: [String: Any]) in try? DivAction(dictionary: dict, context: context) }, validator: Self.actionsValidator, context: context), condition: try dictionary.getExpressionField("condition", context: context), mode: try dictionary.getOptionalExpressionField("mode", context: context) ) diff --git a/client/ios/DivKit/generated_sources/DivTypedValue.swift b/client/ios/DivKit/generated_sources/DivTypedValue.swift index 4069dbc73..84ad71637 100644 --- a/client/ios/DivKit/generated_sources/DivTypedValue.swift +++ b/client/ios/DivKit/generated_sources/DivTypedValue.swift @@ -39,6 +39,7 @@ public enum DivTypedValue: Sendable { extension DivTypedValue { public init(dictionary: [String: Any], context: ParsingContext) throws { + let dictionary = context.templateResolver?(dictionary) ?? dictionary let blockType = try dictionary.getField("type") as String switch blockType { case StringValue.type: @@ -58,7 +59,7 @@ extension DivTypedValue { case ArrayValue.type: self = .arrayValue(try ArrayValue(dictionary: dictionary, context: context)) default: - throw DeserializationError.invalidFieldRepresentation(field: "div-typed-value", representation: dictionary) + throw DeserializationError.requiredFieldIsMissing(field: "type") } } } diff --git a/client/ios/DivKit/generated_sources/DivTypedValueTemplate.swift b/client/ios/DivKit/generated_sources/DivTypedValueTemplate.swift index c92d895f3..5495058fb 100644 --- a/client/ios/DivKit/generated_sources/DivTypedValueTemplate.swift +++ b/client/ios/DivKit/generated_sources/DivTypedValueTemplate.swift @@ -232,7 +232,7 @@ extension DivTypedValueTemplate { case ArrayValueTemplate.type: self = .arrayValueTemplate(try ArrayValueTemplate(dictionary: dictionary, templateToType: templateToType)) default: - throw DeserializationError.invalidFieldRepresentation(field: "div-typed-value_template", representation: dictionary) + throw DeserializationError.requiredFieldIsMissing(field: "type") } } } diff --git a/client/ios/DivKit/generated_sources/DivVariable.swift b/client/ios/DivKit/generated_sources/DivVariable.swift index 7f70f464e..65e295169 100644 --- a/client/ios/DivKit/generated_sources/DivVariable.swift +++ b/client/ios/DivKit/generated_sources/DivVariable.swift @@ -42,6 +42,7 @@ public enum DivVariable: Sendable { extension DivVariable { public init(dictionary: [String: Any], context: ParsingContext) throws { + let dictionary = context.templateResolver?(dictionary) ?? dictionary let blockType = try dictionary.getField("type") as String switch blockType { case StringVariable.type: @@ -63,7 +64,7 @@ extension DivVariable { case PropertyVariable.type: self = .propertyVariable(try PropertyVariable(dictionary: dictionary, context: context)) default: - throw DeserializationError.invalidFieldRepresentation(field: "div-variable", representation: dictionary) + throw DeserializationError.requiredFieldIsMissing(field: "type") } } } diff --git a/client/ios/DivKit/generated_sources/DivVariableTemplate.swift b/client/ios/DivKit/generated_sources/DivVariableTemplate.swift index 3817f2557..d65fa0d7c 100644 --- a/client/ios/DivKit/generated_sources/DivVariableTemplate.swift +++ b/client/ios/DivKit/generated_sources/DivVariableTemplate.swift @@ -255,7 +255,7 @@ extension DivVariableTemplate { case PropertyVariableTemplate.type: self = .propertyVariableTemplate(try PropertyVariableTemplate(dictionary: dictionary, templateToType: templateToType)) default: - throw DeserializationError.invalidFieldRepresentation(field: "div-variable_template", representation: dictionary) + throw DeserializationError.requiredFieldIsMissing(field: "type") } } } diff --git a/client/ios/DivKit/generated_sources/DivVideo.swift b/client/ios/DivKit/generated_sources/DivVideo.swift index 343cad792..10de2b0a1 100644 --- a/client/ios/DivKit/generated_sources/DivVideo.swift +++ b/client/ios/DivKit/generated_sources/DivVideo.swift @@ -167,7 +167,7 @@ public final class DivVideo: DivBase, @unchecked Sendable { transitionTriggers: try dictionary.getOptionalArray("transition_triggers", validator: Self.transitionTriggersValidator, context: context), variableTriggers: try dictionary.getOptionalArray("variable_triggers", transform: { (dict: [String: Any]) in try? DivTrigger(dictionary: dict, context: context) }), variables: try dictionary.getOptionalArray("variables", transform: { (dict: [String: Any]) in try? DivVariable(dictionary: dict, context: context) }), - videoSources: try dictionary.getArray("video_sources", transform: { (dict: [String: Any]) in try? DivVideoSource(dictionary: dict, context: context) }, validator: Self.videoSourcesValidator), + videoSources: try dictionary.getArray("video_sources", transform: { (dict: [String: Any]) in try? DivVideoSource(dictionary: dict, context: context) }, validator: Self.videoSourcesValidator, context: context), visibility: try dictionary.getOptionalExpressionField("visibility", context: context), visibilityAction: try dictionary.getOptionalField("visibility_action", transform: { (dict: [String: Any]) in try DivVisibilityAction(dictionary: dict, context: context) }), visibilityActions: try dictionary.getOptionalArray("visibility_actions", transform: { (dict: [String: Any]) in try? DivVisibilityAction(dictionary: dict, context: context) }), diff --git a/client/ios/DivKitTests/Entities/generated_sources/Entity.swift b/client/ios/DivKitTests/Entities/generated_sources/Entity.swift index 8da83c70f..ffce50ced 100644 --- a/client/ios/DivKitTests/Entities/generated_sources/Entity.swift +++ b/client/ios/DivKitTests/Entities/generated_sources/Entity.swift @@ -75,6 +75,7 @@ public enum Entity: Sendable { extension Entity { public init(dictionary: [String: Any], context: ParsingContext) throws { + let dictionary = context.templateResolver?(dictionary) ?? dictionary let blockType = try dictionary.getField("type") as String switch blockType { case EntityWithArray.type: @@ -116,7 +117,7 @@ extension Entity { case EntityWithoutProperties.type: self = .entityWithoutProperties(try EntityWithoutProperties(dictionary: dictionary, context: context)) default: - throw DeserializationError.invalidFieldRepresentation(field: "entity", representation: dictionary) + throw DeserializationError.requiredFieldIsMissing(field: "type") } } } diff --git a/client/ios/DivKitTests/Entities/generated_sources/EntityTemplate.swift b/client/ios/DivKitTests/Entities/generated_sources/EntityTemplate.swift index fe1c651da..e98399455 100644 --- a/client/ios/DivKitTests/Entities/generated_sources/EntityTemplate.swift +++ b/client/ios/DivKitTests/Entities/generated_sources/EntityTemplate.swift @@ -488,7 +488,7 @@ extension EntityTemplate { case EntityWithoutPropertiesTemplate.type: self = .entityWithoutPropertiesTemplate(try EntityWithoutPropertiesTemplate(dictionary: dictionary, templateToType: templateToType)) default: - throw DeserializationError.invalidFieldRepresentation(field: "entity_template", representation: dictionary) + throw DeserializationError.requiredFieldIsMissing(field: "type") } } } diff --git a/client/ios/DivKitTests/Entities/generated_sources/EntityWithArray.swift b/client/ios/DivKitTests/Entities/generated_sources/EntityWithArray.swift index 80050f67c..04512acea 100644 --- a/client/ios/DivKitTests/Entities/generated_sources/EntityWithArray.swift +++ b/client/ios/DivKitTests/Entities/generated_sources/EntityWithArray.swift @@ -16,7 +16,7 @@ public final class EntityWithArray: Sendable { public convenience init(dictionary: [String: Any], context: ParsingContext) throws { self.init( - array: try dictionary.getArray("array", transform: { (dict: [String: Any]) in try? Entity(dictionary: dict, context: context) }, validator: Self.arrayValidator) + array: try dictionary.getArray("array", transform: { (dict: [String: Any]) in try? Entity(dictionary: dict, context: context) }, validator: Self.arrayValidator, context: context) ) } diff --git a/client/ios/DivKitTests/Entities/generated_sources/EntityWithArrayOfNestedItems.swift b/client/ios/DivKitTests/Entities/generated_sources/EntityWithArrayOfNestedItems.swift index 8ba93b118..7b6d28cb4 100644 --- a/client/ios/DivKitTests/Entities/generated_sources/EntityWithArrayOfNestedItems.swift +++ b/client/ios/DivKitTests/Entities/generated_sources/EntityWithArrayOfNestedItems.swift @@ -18,7 +18,7 @@ public final class EntityWithArrayOfNestedItems: Sendable { public convenience init(dictionary: [String: Any], context: ParsingContext) throws { self.init( - entity: try dictionary.getField("entity", transform: { (dict: [String: Any]) in try Entity(dictionary: dict, context: context) }), + entity: try dictionary.getField("entity", transform: { (dict: [String: Any]) in try Entity(dictionary: dict, context: context) }, context: context), property: try dictionary.getExpressionField("property", context: context) ) } @@ -40,7 +40,7 @@ public final class EntityWithArrayOfNestedItems: Sendable { public convenience init(dictionary: [String: Any], context: ParsingContext) throws { self.init( - items: try dictionary.getArray("items", transform: { (dict: [String: Any]) in try? EntityWithArrayOfNestedItems.Item(dictionary: dict, context: context) }, validator: Self.itemsValidator) + items: try dictionary.getArray("items", transform: { (dict: [String: Any]) in try? EntityWithArrayOfNestedItems.Item(dictionary: dict, context: context) }, validator: Self.itemsValidator, context: context) ) } diff --git a/client/ios/DivKitTests/Entities/generated_sources/EntityWithComplexProperty.swift b/client/ios/DivKitTests/Entities/generated_sources/EntityWithComplexProperty.swift index 22bbe9ac1..01f2d2b60 100644 --- a/client/ios/DivKitTests/Entities/generated_sources/EntityWithComplexProperty.swift +++ b/client/ios/DivKitTests/Entities/generated_sources/EntityWithComplexProperty.swift @@ -33,7 +33,7 @@ public final class EntityWithComplexProperty: Sendable { public convenience init(dictionary: [String: Any], context: ParsingContext) throws { self.init( - property: try dictionary.getField("property", transform: { (dict: [String: Any]) in try EntityWithComplexProperty.Property(dictionary: dict, context: context) }) + property: try dictionary.getField("property", transform: { (dict: [String: Any]) in try EntityWithComplexProperty.Property(dictionary: dict, context: context) }, context: context) ) } diff --git a/client/ios/DivKitTests/Entities/generated_sources/EnumWithDefaultType.swift b/client/ios/DivKitTests/Entities/generated_sources/EnumWithDefaultType.swift index 39e9866f3..1dcafdc59 100644 --- a/client/ios/DivKitTests/Entities/generated_sources/EnumWithDefaultType.swift +++ b/client/ios/DivKitTests/Entities/generated_sources/EnumWithDefaultType.swift @@ -24,6 +24,7 @@ public enum EnumWithDefaultType: Sendable { extension EnumWithDefaultType { public init(dictionary: [String: Any], context: ParsingContext) throws { + let dictionary = context.templateResolver?(dictionary) ?? dictionary let blockType = try dictionary.getField("type") as String switch blockType { case WithDefault.type: @@ -31,7 +32,7 @@ extension EnumWithDefaultType { case WithoutDefault.type: self = .withoutDefault(try WithoutDefault(dictionary: dictionary, context: context)) default: - throw DeserializationError.invalidFieldRepresentation(field: "enum_with_default_type", representation: dictionary) + throw DeserializationError.requiredFieldIsMissing(field: "type") } } } diff --git a/client/ios/DivKitTests/Entities/generated_sources/EnumWithDefaultTypeTemplate.swift b/client/ios/DivKitTests/Entities/generated_sources/EnumWithDefaultTypeTemplate.swift index 5e543432c..e415f80fd 100644 --- a/client/ios/DivKitTests/Entities/generated_sources/EnumWithDefaultTypeTemplate.swift +++ b/client/ios/DivKitTests/Entities/generated_sources/EnumWithDefaultTypeTemplate.swift @@ -96,7 +96,7 @@ extension EnumWithDefaultTypeTemplate { case WithoutDefaultTemplate.type: self = .withoutDefaultTemplate(try WithoutDefaultTemplate(dictionary: dictionary, templateToType: templateToType)) default: - throw DeserializationError.invalidFieldRepresentation(field: "enum_with_default_type_template", representation: dictionary) + throw DeserializationError.requiredFieldIsMissing(field: "type") } } } diff --git a/client/ios/Serialization/Deserializable.swift b/client/ios/Serialization/Deserializable.swift index 46b5089d3..7a620929b 100644 --- a/client/ios/Serialization/Deserializable.swift +++ b/client/ios/Serialization/Deserializable.swift @@ -1,11 +1,16 @@ import Foundation +public typealias TemplateResolver = ([String: Any]) -> [String: Any] + public final class ParsingContext: @unchecked Sendable { public private(set) var warnings: [DeserializationError] = [] public private(set) var errors: [DeserializationError] = [] public private(set) var path: [String] = [] + public let templateResolver: TemplateResolver? - public init() {} + public init(templateResolver: TemplateResolver? = nil) { + self.templateResolver = templateResolver + } public func appendWarning(_ warning: DeserializationError) { warnings.append(warning) @@ -32,6 +37,14 @@ public final class ParsingContext: @unchecked Sendable { } } + public func captureErrors(_ body: () -> Void) -> [DeserializationError] { + let countBefore = errors.count + body() + let captured = Array(errors[countBefore...]) + errors.removeSubrange(countBefore...) + return captured + } + @discardableResult public func withPath(_ component: String, _ body: () throws -> T) rethrows -> T { path.append(component) diff --git a/client/ios/Serialization/Dictionary+Serialization.swift b/client/ios/Serialization/Dictionary+Serialization.swift index dd2660e4a..33644c739 100644 --- a/client/ios/Serialization/Dictionary+Serialization.swift +++ b/client/ios/Serialization/Dictionary+Serialization.swift @@ -55,10 +55,13 @@ func rawRepresentableValue( @usableFromInline func castValidSerializationValue( _ value: Any, - key: [some Any] + key _: [some Any] ) throws -> T { guard let transformed = value as? T else { - throw invalidFieldErrorForKey(key, representation: value) + throw DeserializationError.typeMismatch( + expected: String(describing: T.self), + representation: value + ) } return transformed } @@ -86,6 +89,29 @@ extension Dictionary where Key == String { // MARK: Required values (private interface) extension Dictionary where Key == String { + @usableFromInline + func getFieldPreservingError( + _ key: [Key], + transform: (T) throws -> U, + validator: AnyValueValidator? + ) throws -> U { + let dict = try enclosedDictForKeySequence(key) + guard let valueBeforeConversion = dict[key.last!] else { + throw DeserializationError.noData + } + guard let typedValue = valueBeforeConversion as? T else { + throw DeserializationError.typeMismatch( + expected: String(describing: T.self), + representation: valueBeforeConversion + ) + } + let transformed = try transform(typedValue) + guard validator?.isValid(transformed) != false else { + throw DeserializationError.invalidValue(result: transformed, value: valueBeforeConversion) + } + return transformed + } + @usableFromInline func getField( _ key: [Key], @@ -370,11 +396,27 @@ extension Dictionary where Key == String { validator: AnyValueValidator? = nil, context: ParsingContext ) throws -> U { - let result: DeserializationResult = getResult { - try getField(key, transform: transform, validator: validator) + let fieldName = key.last! + do { + return try getFieldPreservingError(key, transform: transform, validator: validator) + } catch let error as DeserializationError { + let wrappedError: DeserializationError = switch error { + case .noData: + .requiredFieldIsMissing(field: fieldName) + case .typeMismatch, .invalidFieldRepresentation: + .nestedObjectError(field: fieldName, error: error) + default: + .nestedObjectError( + field: fieldName, + error: .composite( + error: .invalidValue(result: nil, from: nil), + causes: NonEmptyArray(error) + ) + ) + } + context.appendError(wrappedError) + throw wrappedError } - context.append(result: result) - return try result.unwrap() } @usableFromInline @@ -384,11 +426,79 @@ extension Dictionary where Key == String { validator: AnyArrayValueValidator? = nil, context: ParsingContext ) throws -> [U] { - let result: DeserializationResult<[U]> = getResult { - try getArray(key, transform: transform, validator: validator) + let fieldName = key.last! + + let dict: [String: Any] + do { + dict = try enclosedDictForKeySequence(key) + } catch { + let err = DeserializationError.requiredFieldIsMissing(field: fieldName) + context.appendError(err) + throw err } - context.append(result: result) - return try result.unwrap() + + guard let value = dict[fieldName] else { + let err = DeserializationError.requiredFieldIsMissing(field: fieldName) + context.appendError(err) + throw err + } + + guard let array = value as? NSArray else { + let err = DeserializationError.nestedObjectError( + field: fieldName, + error: .typeMismatch(expected: "NSArray", representation: value) + ) + context.appendError(err) + throw err + } + + var result: [U] = [] + var elementCauses: [DeserializationError] = [] + result.reserveCapacity(array.count) + + for index in 0..