microproduct/dem-sentiral/ISCEApp/site-packages/stone/backends/swift.py

197 lines
5.6 KiB
Python

from __future__ import absolute_import, division, print_function, unicode_literals
from contextlib import contextmanager
from stone.ir import (
Boolean,
Bytes,
DataType,
Float32,
Float64,
Int32,
Int64,
List,
String,
Timestamp,
UInt32,
UInt64,
Void,
is_list_type,
is_timestamp_type,
is_union_type,
is_user_defined_type,
unwrap_nullable,
)
from stone.backend import CodeBackend
from stone.backends.swift_helpers import (
fmt_class,
fmt_func,
fmt_obj,
fmt_type,
fmt_var,
)
_serial_type_table = {
Boolean: 'BoolSerializer',
Bytes: 'NSDataSerializer',
Float32: 'FloatSerializer',
Float64: 'DoubleSerializer',
Int32: 'Int32Serializer',
Int64: 'Int64Serializer',
List: 'ArraySerializer',
String: 'StringSerializer',
Timestamp: 'NSDateSerializer',
UInt32: 'UInt32Serializer',
UInt64: 'UInt64Serializer',
Void: 'VoidSerializer',
}
stone_warning = """\
///
/// Copyright (c) 2016 Dropbox, Inc. All rights reserved.
///
/// Auto-generated by Stone, do not modify.
///
"""
# This will be at the top of the generated file.
base = """\
{}\
import Foundation
""".format(stone_warning)
undocumented = '(no description)'
class SwiftBaseBackend(CodeBackend):
"""Wrapper class over Stone generator for Swift logic."""
# pylint: disable=abstract-method
@contextmanager
def function_block(self, func, args, return_type=None):
signature = '{}({})'.format(func, args)
if return_type:
signature += ' -> {}'.format(return_type)
with self.block(signature):
yield
def _func_args(self, args_list, newlines=False, force_first=False, not_init=False):
out = []
first = True
for k, v in args_list:
# this is a temporary hack -- injected client-side args
# do not have a separate field for default value. Right now,
# default values are stored along with the type, e.g.
# `Bool = True` is a type, hence this check.
if first and force_first and '=' not in v:
k = "{0} {0}".format(k)
if first and v is not None and not_init:
out.append('{}'.format(v))
elif v is not None:
out.append('{}: {}'.format(k, v))
first = False
sep = ', '
if newlines:
sep += '\n' + self.make_indent()
return sep.join(out)
@contextmanager
def class_block(self, thing, protocols=None):
protocols = protocols or []
extensions = []
if isinstance(thing, DataType):
name = fmt_class(thing.name)
if thing.parent_type:
extensions.append(fmt_type(thing.parent_type))
else:
name = thing
extensions.extend(protocols)
extend_suffix = ': {}'.format(', '.join(extensions)) if extensions else ''
with self.block('open class {}{}'.format(name, extend_suffix)):
yield
def _struct_init_args(self, data_type, namespace=None): # pylint: disable=unused-argument
args = []
for field in data_type.all_fields:
name = fmt_var(field.name)
value = fmt_type(field.data_type)
data_type, nullable = unwrap_nullable(field.data_type)
if field.has_default:
if is_union_type(data_type):
default = '.{}'.format(fmt_var(field.default.tag_name))
else:
default = fmt_obj(field.default)
value += ' = {}'.format(default)
elif nullable:
value += ' = nil'
arg = (name, value)
args.append(arg)
return args
def _docf(self, tag, val):
if tag == 'route':
if ':' in val:
val, version = val.split(':', 1)
version = int(version)
else:
version = 1
return fmt_func(val, version)
elif tag == 'field':
if '.' in val:
cls, field = val.split('.')
return ('{} in {}'.format(fmt_var(field),
fmt_class(cls)))
else:
return fmt_var(val)
elif tag in ('type', 'val', 'link'):
return val
else:
import pdb
pdb.set_trace()
return val
def fmt_serial_type(data_type):
data_type, nullable = unwrap_nullable(data_type)
if is_user_defined_type(data_type):
result = '{}.{}Serializer'
result = result.format(fmt_class(data_type.namespace.name),
fmt_class(data_type.name))
else:
result = _serial_type_table.get(data_type.__class__, fmt_class(data_type.name))
if is_list_type(data_type):
result = result + '<{}>'.format(fmt_serial_type(data_type.data_type))
return result if not nullable else 'NullableSerializer'
def fmt_serial_obj(data_type):
data_type, nullable = unwrap_nullable(data_type)
if is_user_defined_type(data_type):
result = '{}.{}Serializer()'
result = result.format(fmt_class(data_type.namespace.name),
fmt_class(data_type.name))
else:
result = _serial_type_table.get(data_type.__class__, fmt_class(data_type.name))
if is_list_type(data_type):
result = result + '({})'.format(fmt_serial_obj(data_type.data_type))
elif is_timestamp_type(data_type):
result = result + '("{}")'.format(data_type.format)
else:
result = 'Serialization._{}'.format(result)
return result if not nullable else 'NullableSerializer({})'.format(result)