From fa278a99c769e99727176f4faae081cc2d219342 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Thu, 16 Apr 2015 21:22:12 +0200 Subject: [PATCH] fix(CLI): request value parsing compiles and inits Therefore, you can now actually make the call and the program will not crash due to uninitialized Options. Fixes #64 --- src/mako/cli/lib/engine.mako | 56 +++++++++++++++++++++++++++++------- 1 file changed, 46 insertions(+), 10 deletions(-) diff --git a/src/mako/cli/lib/engine.mako b/src/mako/cli/lib/engine.mako index b4d3769821..9ff2e61519 100644 --- a/src/mako/cli/lib/engine.mako +++ b/src/mako/cli/lib/engine.mako @@ -1,7 +1,7 @@ <%namespace name="util" file="../../lib/util.mako"/>\ <%! from util import (hub_type, mangle_ident, indent_all_but_first_by, activity_rust_type, setter_fn_name, ADD_PARAM_FN, - upload_action_fn, is_schema_with_optionals, schema_markers) + upload_action_fn, is_schema_with_optionals, schema_markers, indent_by) from cli import (mangle_subcommand, new_method_context, PARAM_FLAG, STRUCT_FLAG, UPLOAD_FLAG, OUTPUT_FLAG, VALUE_ARG, CONFIG_DIR, SCOPE_FLAG, is_request_value_property, FIELD_SEP, docopt_mode, FILE_ARG, MIME_ARG, OUT_ARG, cmd_ident, call_method_ident, arg_ident, POD_TYPES, flag_ident, ident, JSON_TYPE_VALUE_MAP, @@ -148,6 +148,8 @@ self.opt.${cmd_ident(method)} { handle_props = optional_props or parameters is not UNDEFINED if mc.request_value: request_cli_schema = to_cli_schema(c, mc.request_value) + + request_prop_type = None %>\ ## REQUIRED PARAMETERS % for p in mc.required_props: @@ -157,6 +159,7 @@ self.opt.${cmd_ident(method)} { opt_ident = to_opt_arg_ident(p) %>\ % if is_request_value_property(mc, p): + <% request_prop_type = prop_type %>\ let mut ${prop_name}: api::${prop_type} = Default::default(); % elif p.type != 'string': let ${prop_name}: ${prop_type} = arg_from_str(&${opt_ident}, err, "<${mangle_subcommand(p.name)}>", "${p.type}"); @@ -240,27 +243,48 @@ ${value_unwrap}\ <% allow_optionals_fn = lambda s: is_schema_with_optionals(schema_markers(s, c, transitive=False)) - def flatten_schema_fields(schema, res, cur=list()): + def flatten_schema_fields(schema, res, init_fn_map, cur=list(), init_call=None): if len(cur) == 0: + init_call = '' cur = list() opt_access = '.as_mut().unwrap()' - if not allow_optionals_fn(schema): + allow_optionals = allow_optionals_fn(schema) + parent_init_call = init_call + if not allow_optionals: opt_access = '' for fn, f in schema.fields.iteritems(): - cur.append(['%s%s' % (mangle_ident(fn), opt_access), fn]) if isinstance(f, SchemaEntry): cur[-1][0] = mangle_ident(fn) - res.append((schema, f, list(cur))) + res.append((init_call, schema, f, list(cur))) else: - flatten_schema_fields(f, res, cur) + if allow_optionals: + init_fn_name = 'request_%s_init' % '_'.join(mangle_ident(t[1]) for t in cur) + init_call = init_fn_name + '(&mut request);' + struct_field = 'request.' + '.'.join('%s%s' % (mangle_ident(t[1]), opt_access) for t in cur[:-1]) + if len(cur) > 1: + struct_field += '.' + struct_field += mangle_ident(cur[-1][1]) + init_fn = "fn %s(request: &mut api::%s) {\n" % (init_fn_name, request_prop_type) + if parent_init_call: + pcall = parent_init_call[:parent_init_call.index('(')] + "(request)" + init_fn += " %s;\n" % pcall + init_fn += " if %s.is_none() {\n" % struct_field + init_fn += " %s = Some(Default::default());\n" % struct_field + init_fn += " }\n" + init_fn += "}\n" + + init_fn_map[init_fn_name] = init_fn + # end handle init + flatten_schema_fields(f, res, init_fn_map, cur, init_call) cur.pop() # endfor # end utility schema_fields = list() - flatten_schema_fields(request_cli_schema, schema_fields) + init_fn_map = dict() + flatten_schema_fields(request_cli_schema, schema_fields, init_fn_map) %>\ let mut field_name: FieldCursor = Default::default(); for kvarg in ${SOPT + arg_ident(KEY_VALUE_ARG)}.iter() { @@ -268,8 +292,11 @@ for kvarg in ${SOPT + arg_ident(KEY_VALUE_ARG)}.iter() { if let Err(field_err) = field_name.set(&*key) { err.issues.push(field_err); } + % for name in sorted(init_fn_map.keys()): +${init_fn_map[name] | indent_by(4)} + % endfor match &field_name.to_string()[..] { - % for schema, fe, f in schema_fields: + % for init_call, schema, fe, f in schema_fields: <% # TODO: Deduplicate ! ptype = fe.actual_property.type @@ -281,16 +308,25 @@ for kvarg in ${SOPT + arg_ident(KEY_VALUE_ARG)}.iter() { allow_optionals = True opt_prefix = 'Some(' opt_suffix = ')' + opt_access = '.as_mut().unwrap()' if not allow_optionals_fn(schema): - opt_prefix = opt_suffix = '' + opt_prefix = opt_suffix = opt_access = '' struct_field = 'request.' + '.'.join(t[0] for t in f) %>\ "${pname}" => { + % if init_call: + ${init_call} + % endif % if fe.container_type == CTYPE_POD: ${struct_field} = ${opt_prefix}\ % else: - ${struct_field}.push(\ + % if opt_prefix: + if ${struct_field}.is_none() { + ${struct_field} = Some(Default::default()); + } + % endif + ${struct_field}${opt_access}.push(\ % endif % if ptype != 'string': arg_from_str(${value_unwrap}, err, "${pname}", "${ptype}")\