Commit fdb5371f authored by mpcomplete@google.com's avatar mpcomplete@google.com

Support default values for complex objects in mojom.

BUG=320082
R=darin@chromium.org

Review URL: https://codereview.chromium.org/139613005

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@248579 0039d316-1c4b-4281-b951-d872f2087c98
parent abc08b6c
...@@ -98,6 +98,19 @@ define([ ...@@ -98,6 +98,19 @@ define([
expect(foo.data[0]).toBe(1); expect(foo.data[0]).toBe(1);
expect(foo.data[1]).toBe(2); expect(foo.data[1]).toBe(2);
expect(foo.data[2]).toBe(3); expect(foo.data[2]).toBe(3);
var inner = new sample.DefaultsTestInner();
expect(inner.names.length).toBe(1);
expect(inner.names[0]).toBe("Jim");
expect(inner.height).toBe(6*12);
var full = new sample.DefaultsTest();
expect(full.people.length).toBe(1);
expect(full.people[0].age).toBe(32);
expect(full.people[0].names.length).toBe(2);
expect(full.people[0].names[0]).toBe("Bob");
expect(full.people[0].names[1]).toBe("Bobby");
expect(full.people[0].height).toBe(6*12);
} }
function ServiceImpl() { function ServiceImpl() {
......
...@@ -6,32 +6,55 @@ ...@@ -6,32 +6,55 @@
{%- set _ = dtor_name.append("NULL") %} {%- set _ = dtor_name.append("NULL") %}
{%- endif %} {%- endif %}
{%- macro set_default(field) -%} {%- macro set_default(kind, value, depth) -%}
{%- if field.kind|is_string_kind -%} {#--- Strings ---#}
set_{{field.name}}(mojo::String({{field.default}})); {%- if kind|is_string_kind -%}
{%- elif field.kind|is_array_kind -%} {{caller("mojo::String(" ~ value ~ ")")}}
{#--- Arrays ---#}
{%- elif kind|is_array_kind %}
{%- set _ = value|verify_token_type("ARRAY") %}
{ {
{{field.kind|cpp_wrapper_type}}::Builder tmp({{field.default|length}}); {{kind|cpp_wrapper_type}}::Builder tmp{{depth}}({{value[1]|length}});
{%- for element in field.default %} {%- for element in value[1] %}
tmp[{{loop.index0}}] = {{element}}; {%- filter indent(2) %}
{%- endfor %} {%- call(result) set_default(kind.kind, element, depth+1) %}
set_{{field.name}}(tmp.Finish()); tmp{{depth}}[{{loop.index0}}] = {{result}};
{%- endcall %}
{%- endfilter %}
{%- endfor -%}
{{caller("tmp" ~ depth ~ ".Finish()")|indent(2)}}
} }
{%- elif field.kind|is_object_kind -%} {#--- Objects ---#}
{%- elif kind|is_object_kind %}
{%- set _ = value|verify_token_type("OBJECT") %}
{ {
{{field.kind|cpp_wrapper_type}}::Builder tmp; {{kind|cpp_wrapper_type}}::Builder tmp{{depth}};
// TODO {%- set struct = structs|struct_by_name(kind.name) %}
set_{{field.name}}(tmp.Finish()); {%- for element in value[1] %}
{#- Use struct.packed_fields to order struct values by ordinal number #}
{%- set subfield = struct.fields[loop.index0] %}
{%- filter indent(2) %}
{%- call(result) set_default(subfield.kind, element, depth+1) %}
tmp{{depth}}.set_{{subfield.name}}({{result}});
{%- endcall %}
{%- endfilter %}
{%- endfor -%}
{{caller("tmp" ~ depth ~ ".Finish()")|indent(2)}}
} }
{#--- POD types ---#}
{%- else -%} {%- else -%}
set_{{field.name}}({{field.default}}); {{caller(value)}}
{%- endif %} {%- endif %}
{%- endmacro %} {%- endmacro %}
{{class_name}}::Builder::Builder(mojo::Buffer* buf) {{class_name}}::Builder::Builder(mojo::Buffer* buf)
: data_(Data::New(buf, {{dtor_name[0]}})) { : data_(Data::New(buf, {{dtor_name[0]}})) {
{%- for pf in struct.packed.packed_fields if pf.field.default %} {%- for pf in struct.packed.packed_fields if pf.field.default %}
{{set_default(pf.field)|indent(2)}} {%- filter indent(2) %}
{%- call(result) set_default(pf.field.kind, pf.field.default, 0) %}
set_{{pf.field.name}}({{result}});
{%- endcall %}
{%- endfilter %}
{%- endfor %} {%- endfor %}
} }
......
{%- macro set_default(kind, value, depth) -%}
{#--- Strings ---#}
{%- if kind|is_string_kind -%}
{{caller(value)}}
{#--- Arrays ---#}
{%- elif kind|is_array_kind %}
{%- set _ = value|verify_token_type("ARRAY") %}
{
var tmp{{depth}} = [];
{%- for element in value[1] %}
{%- filter indent(2) %}
{%- call(result) set_default(kind.kind, element, depth+1) %}
tmp{{depth}}[{{loop.index0}}] = {{result}};
{%- endcall %}
{%- endfilter %}
{%- endfor -%}
{{caller("tmp" ~ depth)|indent(2)}}
}
{#--- Objects ---#}
{%- elif kind|is_object_kind %}
{%- set _ = value|verify_token_type("OBJECT") %}
{
var tmp{{depth}} = new {{kind.name}}();
{%- set struct = structs|struct_by_name(kind.name) %}
{%- for element in value[1] %}
{#- Use struct.packed_fields to order struct values by ordinal number #}
{%- set subfield = struct.fields[loop.index0] %}
{%- filter indent(2) %}
{%- call(result) set_default(subfield.kind, element, depth+1) %}
tmp{{depth}}.{{subfield.name}} = {{result}};
{%- endcall %}
{%- endfilter %}
{%- endfor -%}
{{caller("tmp" ~ depth)|indent(2)}}
}
{#--- POD types ---#}
{%- else -%}
{{caller(value)}}
{%- endif %}
{%- endmacro %}
function {{struct.name}}() { function {{struct.name}}() {
{%- for packed_field in struct.packed.packed_fields %} {%- for packed_field in struct.packed.packed_fields %}
{%- if packed_field.field.default %}
{%- filter indent(4) %}
{%- call(result) set_default(packed_field.field.kind, packed_field.field.default, 0) %}
this.{{packed_field.field.name}} = {{result}};
{%- endcall %}
{%- endfilter %}
{%- else %}
this.{{packed_field.field.name}} = {{packed_field.field|default_value}}; this.{{packed_field.field.name}} = {{packed_field.field|default_value}};
{%- endif %}
{%- endfor %} {%- endfor %}
} }
......
...@@ -111,7 +111,9 @@ class Generator(mojom_generator.Generator): ...@@ -111,7 +111,9 @@ class Generator(mojom_generator.Generator):
"is_struct_with_handles": IsStructWithHandles, "is_struct_with_handles": IsStructWithHandles,
"struct_size": lambda ps: ps.GetTotalSize() + _HEADER_SIZE, "struct_size": lambda ps: ps.GetTotalSize() + _HEADER_SIZE,
"struct_from_method": mojom_generator.GetStructFromMethod, "struct_from_method": mojom_generator.GetStructFromMethod,
"struct_by_name": mojom_generator.GetStructByName,
"stylize_method": mojom_generator.StudlyCapsToCamel, "stylize_method": mojom_generator.StudlyCapsToCamel,
"verify_token_type": mojom_generator.VerifyTokenType,
} }
@UseJinja("cpp_templates/module.h.tmpl", filters=cpp_filters) @UseJinja("cpp_templates/module.h.tmpl", filters=cpp_filters)
......
...@@ -33,12 +33,7 @@ _kind_to_javascript_default_value = { ...@@ -33,12 +33,7 @@ _kind_to_javascript_default_value = {
def JavaScriptDefaultValue(field): def JavaScriptDefaultValue(field):
if field.default: if field.default:
if isinstance(field.default, list): raise Exception("Default values should've been handled in jinja.")
# TODO(mpcomplete): This will need to be more sophisticated to support
# arrays of objects/arrays.
return "[" + ", ".join(field.default) + "]"
else:
return field.default
if field.kind in mojom.PRIMITIVES: if field.kind in mojom.PRIMITIVES:
return _kind_to_javascript_default_value[field.kind] return _kind_to_javascript_default_value[field.kind]
if isinstance(field.kind, mojom.Struct): if isinstance(field.kind, mojom.Struct):
...@@ -152,7 +147,12 @@ class Generator(mojom_generator.Generator): ...@@ -152,7 +147,12 @@ class Generator(mojom_generator.Generator):
"payload_size": JavaScriptPayloadSize, "payload_size": JavaScriptPayloadSize,
"decode_snippet": JavaScriptDecodeSnippet, "decode_snippet": JavaScriptDecodeSnippet,
"encode_snippet": JavaScriptEncodeSnippet, "encode_snippet": JavaScriptEncodeSnippet,
"is_object_kind": mojom_generator.IsObjectKind,
"is_string_kind": mojom_generator.IsStringKind,
"is_array_kind": lambda kind: isinstance(kind, mojom.Array),
"struct_by_name": mojom_generator.GetStructByName,
"stylize_method": mojom_generator.StudlyCapsToCamel, "stylize_method": mojom_generator.StudlyCapsToCamel,
"verify_token_type": mojom_generator.VerifyTokenType,
} }
@UseJinja("js_templates/module.js.tmpl", filters=js_filters) @UseJinja("js_templates/module.js.tmpl", filters=js_filters)
......
...@@ -25,6 +25,12 @@ def GetStructInfo(exported, struct): ...@@ -25,6 +25,12 @@ def GetStructInfo(exported, struct):
struct.exported = exported struct.exported = exported
return struct return struct
def GetStructByName(structs, name):
for struct in structs:
if struct.name == name:
return struct
return None
def IsStringKind(kind): def IsStringKind(kind):
return kind.spec == 's' return kind.spec == 's'
...@@ -41,6 +47,18 @@ def CamelToUnderscores(camel): ...@@ -41,6 +47,18 @@ def CamelToUnderscores(camel):
def StudlyCapsToCamel(studly): def StudlyCapsToCamel(studly):
return studly[0].lower() + studly[1:] return studly[0].lower() + studly[1:]
def VerifyTokenType(token, expected):
"""Used to check that arrays and objects are used correctly as default
values. Arrays are tokens that look like ('ARRAY', element0, element1...).
See mojom_parser.py for their representation.
"""
if not isinstance(token, tuple):
raise Exception("Expected token type '%s'. Invalid token '%s'." %
(expected, token))
if token[0] != expected:
raise Exception("Expected token type '%s'. Got '%s'." %
(expected, token[0]))
class Generator(object): class Generator(object):
# Pass |output_dir| to emit files to disk. Omit |output_dir| to echo all # Pass |output_dir| to emit files to disk. Omit |output_dir| to echo all
# files to stdout. # files to stdout.
......
...@@ -100,7 +100,7 @@ class Parser(object): ...@@ -100,7 +100,7 @@ class Parser(object):
def p_default(self, p): def p_default(self, p):
"""default : EQUALS expression """default : EQUALS expression
| EQUALS expression_array | EQUALS expression_object
| """ | """
if len(p) > 2: if len(p) > 2:
p[0] = p[2] p[0] = p[2]
...@@ -190,17 +190,34 @@ class Parser(object): ...@@ -190,17 +190,34 @@ class Parser(object):
### Expressions ### ### Expressions ###
def p_expression_object(self, p):
"""expression_object : expression_array
| LBRACE expression_object_elements RBRACE """
if len(p) < 3:
p[0] = p[1]
else:
p[0] = ('OBJECT', p[2])
def p_expression_object_elements(self, p):
"""expression_object_elements : expression_object
| expression_object COMMA expression_object_elements
| """
if len(p) == 2:
p[0] = ListFromConcat(p[1])
elif len(p) > 3:
p[0] = ListFromConcat(p[1], p[3])
def p_expression_array(self, p): def p_expression_array(self, p):
"""expression_array : expression """expression_array : expression
| LBRACKET expression_array_elements RBRACKET """ | LBRACKET expression_array_elements RBRACKET """
if len(p) < 3: if len(p) < 3:
p[0] = p[1] p[0] = p[1]
else: else:
p[0] = p[2] p[0] = ('ARRAY', p[2])
def p_expression_array_elements(self, p): def p_expression_array_elements(self, p):
"""expression_array_elements : expression """expression_array_elements : expression_object
| expression COMMA expression_array_elements | expression_object COMMA expression_array_elements
| """ | """
if len(p) == 2: if len(p) == 2:
p[0] = ListFromConcat(p[1]) p[0] = ListFromConcat(p[1])
......
...@@ -34,6 +34,17 @@ struct Foo { ...@@ -34,6 +34,17 @@ struct Foo {
handle<data_pipe_producer>[] output_streams @11; handle<data_pipe_producer>[] output_streams @11;
}; };
struct DefaultsTestInner {
int32 age @2;
string[] names = ["Jim"] @1;
int32 height = 6*12 @3;
};
struct DefaultsTest {
DefaultsTestInner[] people = [{32, ["Bob", "Bobby"]}] @1;
uint8[] data = [1, 2, 3] @2;
};
[Peer=ServiceClient] [Peer=ServiceClient]
interface Service { interface Service {
enum BazOptions { enum BazOptions {
......
...@@ -326,6 +326,19 @@ TEST(BindingsSampleTest, DefaultValues) { ...@@ -326,6 +326,19 @@ TEST(BindingsSampleTest, DefaultValues) {
EXPECT_EQ(1, foo.data()[0]); EXPECT_EQ(1, foo.data()[0]);
EXPECT_EQ(2, foo.data()[1]); EXPECT_EQ(2, foo.data()[1]);
EXPECT_EQ(3, foo.data()[2]); EXPECT_EQ(3, foo.data()[2]);
DefaultsTestInner inner = DefaultsTestInner::Builder().Finish();
EXPECT_EQ(1u, inner.names().size());
EXPECT_EQ("Jim", inner.names()[0].To<std::string>());
EXPECT_EQ(6*12, inner.height());
DefaultsTest full = DefaultsTest::Builder().Finish();
EXPECT_EQ(1u, full.people().size());
EXPECT_EQ(32, full.people()[0].age());
EXPECT_EQ(2u, full.people()[0].names().size());
EXPECT_EQ("Bob", full.people()[0].names()[0].To<std::string>());
EXPECT_EQ("Bobby", full.people()[0].names()[1].To<std::string>());
EXPECT_EQ(6*12, full.people()[0].height());
} }
} // namespace sample } // namespace sample
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment