Skip to content

Commit

Permalink
Handle mapping struct fields with subtypes to Objective-C
Browse files Browse the repository at this point in the history
  • Loading branch information
julianlocke committed Feb 6, 2024
1 parent e5d9907 commit 54c75f0
Show file tree
Hide file tree
Showing 2 changed files with 99 additions and 3 deletions.
32 changes: 31 additions & 1 deletion stone/backends/swift_rsrc/ObjcTypes.jinja
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,37 @@ public class DBX{{ namespace_class_name }}{{ data_type_class_name }}: {{ 'NSObje
{% for field in data_type.fields %}
{{ struct_field_doc(field, ' ') }}
@objc
public var {{ fmt_var(field.name) }}: {{ fmt_objc_type(field.data_type) }} { {{ objc_return_field_value(data_type, field) }} }
{% if objc_return_field_value_specified_in_jinja(field) %}
public var {{ fmt_var(field.name) }}: {{ fmt_objc_type(field.data_type) }} {
{% if (field_is_user_defined(field)) or (field_is_user_defined_optional(field)) %}
switch {{ swift_var_name }}.{{ fmt_var(field.name) }} {
{% for tuple in objc_return_field_value_type_tuples(field) %}
case let {{ tuple[0] }} as {{ tuple[1] }}:
return {{ tuple[2] }}(swift: {{ tuple[0] }})
{% endfor %}
default:
{% if field_is_user_defined_optional(field) %}
return {{ swift_var_name }}.{{ fmt_var(field.name) }}.flatMap { {{ fmt_objc_type(field.data_type, False) }}(swift: $0) }
{% else %}
return {{ fmt_objc_type(field.data_type) }}(swift: {{ swift_var_name }}.{{ fmt_var(field.name) }})
{% endif %}
}
{% elif (field_is_user_defined_map(field)) or (field_is_user_defined_list(field)) %}
{{ swift_var_name }}.{{ fmt_var(field.name) }}.{{ 'mapValues' if field_is_user_defined_map(field) else 'map' }} {
switch $0 {
{% for tuple in objc_return_field_value_type_tuples(field) %} {#extract this snippet?#}
case let {{ tuple[0] }} as {{ tuple[1] }}:
return {{ tuple[2] }}(swift: {{ tuple[0] }})
{% endfor %}
default:
return {{ fmt_objc_type(field.data_type.data_type) }}(swift: $0)
}
}
{% endif %}
}
{% else %}
public var {{ fmt_var(field.name) }}: {{ fmt_objc_type(field.data_type) }} { {{ objc_return_field_value_oneliner(data_type, field) }} }
{% endif %}
{% endfor %}
{% if data_type.fields %}

Expand Down
70 changes: 68 additions & 2 deletions stone/backends/swift_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,13 @@ def generate(self, api):
template_globals['data_objc_type_doc'] = self._data_objc_type_doc
template_globals['objc_init_args'] = self._objc_init_args
template_globals['fmt_objc_type'] = fmt_objc_type
template_globals['objc_return_field_value'] = self._objc_return_field_value
template_globals['objc_return_field_value_oneliner'] = self._objc_return_field_value_oneliner
template_globals['field_is_user_defined'] = self._field_is_user_defined
template_globals['field_is_user_defined_optional'] = self._field_is_user_defined_optional
template_globals['field_is_user_defined_list'] = self._field_is_user_defined_list
template_globals['field_is_user_defined_map'] = self._field_is_user_defined_map
template_globals['objc_return_field_value_specified_in_jinja'] = self._objc_return_field_value_specified_in_jinja
template_globals['objc_return_field_value_type_tuples'] = self._objc_return_field_value_type_tuples

Check warning on line 185 in stone/backends/swift_types.py

View check run for this annotation

Codecov / codecov/patch

stone/backends/swift_types.py#L179-L185

Added lines #L179 - L185 were not covered by tests
template_globals['objc_init_args_to_swift'] = self._objc_init_args_to_swift
template_globals['objc_union_arg'] = self._objc_union_arg
template_globals['objc_swift_var_name'] = self._objc_swift_var_name
Expand Down Expand Up @@ -334,7 +340,67 @@ def _route_schema_attrs(self, route_schema, route):
result = ',\n '.join(attrs)
return result

def _objc_return_field_value(self, parent_type, field):
# List[typing.Tuple[let_name: str, swift_type: str, objc_type: str]]
def _objc_return_field_value_type_tuples(self, field):
data_type = field.data_type
ret = []

Check warning on line 346 in stone/backends/swift_types.py

View check run for this annotation

Codecov / codecov/patch

stone/backends/swift_types.py#L344-L346

Added lines #L344 - L346 were not covered by tests

# if list type get the data type of the item
if is_list_type(data_type):
data_type = data_type.data_type

Check warning on line 350 in stone/backends/swift_types.py

View check run for this annotation

Codecov / codecov/patch

stone/backends/swift_types.py#L350

Added line #L350 was not covered by tests

# if map type get the data type of the value
if is_map_type(data_type):
data_type = data_type.value_data_type

Check warning on line 354 in stone/backends/swift_types.py

View check run for this annotation

Codecov / codecov/patch

stone/backends/swift_types.py#L354

Added line #L354 was not covered by tests

# if data_type is a struct type and has subtypes, process them into labels and types
if is_struct_type(data_type) and data_type.has_enumerated_subtypes():
all_subtypes = data_type.get_all_subtypes_with_tags()

Check warning on line 358 in stone/backends/swift_types.py

View check run for this annotation

Codecov / codecov/patch

stone/backends/swift_types.py#L358

Added line #L358 was not covered by tests

for subtype in all_subtypes:
# subtype[0] is the tag name and subtype[1] is the subtype struct itself
struct = subtype[1]
case_let_name = fmt_var(struct.name)
swift_type = fmt_type(struct)
objc_type = fmt_objc_type(struct)
ret.append((case_let_name, swift_type, objc_type))

Check warning on line 366 in stone/backends/swift_types.py

View check run for this annotation

Codecov / codecov/patch

stone/backends/swift_types.py#L362-L366

Added lines #L362 - L366 were not covered by tests

return ret

Check warning on line 368 in stone/backends/swift_types.py

View check run for this annotation

Codecov / codecov/patch

stone/backends/swift_types.py#L368

Added line #L368 was not covered by tests

def _field_is_user_defined(self, field):
data_type, nullable = unwrap_nullable(field.data_type)
return is_user_defined_type(data_type) and not nullable

Check warning on line 372 in stone/backends/swift_types.py

View check run for this annotation

Codecov / codecov/patch

stone/backends/swift_types.py#L370-L372

Added lines #L370 - L372 were not covered by tests

def _field_is_user_defined_optional(self, field):
data_type, nullable = unwrap_nullable(field.data_type)
return is_user_defined_type(data_type) and nullable

Check warning on line 376 in stone/backends/swift_types.py

View check run for this annotation

Codecov / codecov/patch

stone/backends/swift_types.py#L374-L376

Added lines #L374 - L376 were not covered by tests

def _field_is_user_defined_map(self, field):
data_type, _ = unwrap_nullable(field.data_type)
return is_map_type(data_type) and is_user_defined_type(data_type.value_data_type)

Check warning on line 380 in stone/backends/swift_types.py

View check run for this annotation

Codecov / codecov/patch

stone/backends/swift_types.py#L378-L380

Added lines #L378 - L380 were not covered by tests

def _field_is_user_defined_list(self, field):
data_type, _ = unwrap_nullable(field.data_type)

Check warning on line 383 in stone/backends/swift_types.py

View check run for this annotation

Codecov / codecov/patch

stone/backends/swift_types.py#L382-L383

Added lines #L382 - L383 were not covered by tests
if is_list_type(data_type):
list_data_type, _ = unwrap_nullable(data_type.data_type)
return is_user_defined_type(list_data_type)

Check warning on line 386 in stone/backends/swift_types.py

View check run for this annotation

Codecov / codecov/patch

stone/backends/swift_types.py#L385-L386

Added lines #L385 - L386 were not covered by tests
else:
return False

Check warning on line 388 in stone/backends/swift_types.py

View check run for this annotation

Codecov / codecov/patch

stone/backends/swift_types.py#L388

Added line #L388 was not covered by tests

def _objc_return_field_value_specified_in_jinja(self, field) -> bool:
eligible_kind = self._field_is_user_defined(field) or \

Check warning on line 391 in stone/backends/swift_types.py

View check run for this annotation

Codecov / codecov/patch

stone/backends/swift_types.py#L390-L391

Added lines #L390 - L391 were not covered by tests
self._field_is_user_defined_optional(field) or \
self._field_is_user_defined_map(field) or \
self._field_is_user_defined_list(field)

if not eligible_kind:
return False

Check warning on line 397 in stone/backends/swift_types.py

View check run for this annotation

Codecov / codecov/patch

stone/backends/swift_types.py#L397

Added line #L397 was not covered by tests

requires_iterating_over_subtypes = len(self._objc_return_field_value_type_tuples(field)) > 0

Check warning on line 399 in stone/backends/swift_types.py

View check run for this annotation

Codecov / codecov/patch

stone/backends/swift_types.py#L399

Added line #L399 was not covered by tests

return requires_iterating_over_subtypes

Check warning on line 401 in stone/backends/swift_types.py

View check run for this annotation

Codecov / codecov/patch

stone/backends/swift_types.py#L401

Added line #L401 was not covered by tests

def _objc_return_field_value_oneliner(self, parent_type, field):

Check warning on line 403 in stone/backends/swift_types.py

View check run for this annotation

Codecov / codecov/patch

stone/backends/swift_types.py#L403

Added line #L403 was not covered by tests
data_type, nullable = unwrap_nullable(field.data_type)
swift_var_name = self._objc_swift_var_name(parent_type)

Expand Down

0 comments on commit 54c75f0

Please sign in to comment.