diff --git a/example/demo_gen/demo/index.mjs b/example/demo_gen/demo/index.mjs index 40071ac6a..cf6a6a460 100644 --- a/example/demo_gen/demo/index.mjs +++ b/example/demo_gen/demo/index.mjs @@ -16,23 +16,27 @@ let termini = Object.assign({ { name: "Locale Name", - type: "string" + type: "string", + typeUse: "string" }, { name: "ICU4X Fixed Decimal Grouping Strategy", - type: "FixedDecimalGroupingStrategy" + type: "FixedDecimalGroupingStrategy", + typeUse: "enumerator" }, { name: "Useless Config (Ignore)", type: "boolean", + typeUse: "boolean", defaultValue: "true" }, { name: "ICU4XFixedDecimal Value", type: "number", + typeUse: "number", defaultValue: "1000" } @@ -48,6 +52,7 @@ let termini = Object.assign({ { name: "ICU4XFixedDecimal Value", type: "number", + typeUse: "number", defaultValue: "1000" } diff --git a/example/demo_gen/demo/rendering/rendering.mjs b/example/demo_gen/demo/rendering/rendering.mjs index f57bf012d..aca286f1f 100644 --- a/example/demo_gen/demo/rendering/rendering.mjs +++ b/example/demo_gen/demo/rendering/rendering.mjs @@ -142,10 +142,8 @@ class EnumTemplate extends ParameterTemplate { let options = clone.querySelector("*[data-options]"); if (this.default === null) { - this.default = enumType.values.values().next().value; - - for (let value of enumType.values) { - options.append(...(new EnumOption(value[0])).children); + for (let entry of enumType.getAllEntries()) { + options.append(...(new EnumOption(entry[0])).children); } } } @@ -171,7 +169,7 @@ class TerminusParams extends HTMLElement { var newChild; - switch (param.type) { + switch (param.typeUse) { case "string": newChild = new StringTemplate(param); this.#params[i] = ""; @@ -188,17 +186,18 @@ class TerminusParams extends HTMLElement { newChild = new StringArrayTemplate(param); this.#params[i] = []; break; + case "enumerator": + newChild = new EnumTemplate(param, library[param.type]); + this.#params[i] = newChild.default + break; + case "external": + let updateParamEvent = (value) => { + this.#params[i] = value; + }; + evaluateExternal(param, updateParamEvent); + break; default: - if (param.type in library && "values" in library[param.type]) { - newChild = new EnumTemplate(param, library[param.type]); - this.#params[i] = newChild.default - } else { - let updateParamEvent = (value) => { - this.#params[i] = value; - }; - evaluateExternal(param, updateParamEvent); - continue; - } + console.error("Unrecognized parameter: ", param); break; } diff --git a/example/js/lib/api/FixedDecimalGroupingStrategy.mjs b/example/js/lib/api/FixedDecimalGroupingStrategy.mjs index 74c4fc8c1..ba673bd3a 100644 --- a/example/js/lib/api/FixedDecimalGroupingStrategy.mjs +++ b/example/js/lib/api/FixedDecimalGroupingStrategy.mjs @@ -13,6 +13,10 @@ export class FixedDecimalGroupingStrategy { ["Min2", 3] ]); + static getAllEntries() { + return FixedDecimalGroupingStrategy.#values.entries(); + } + constructor(value) { if (arguments.length > 1 && arguments[0] === diplomatRuntime.internalConstructor) { // We pass in two internalConstructor arguments to create *new* diff --git a/feature_tests/demo_gen/demo/index.mjs b/feature_tests/demo_gen/demo/index.mjs index a8c9c2b2c..80a354642 100644 --- a/feature_tests/demo_gen/demo/index.mjs +++ b/feature_tests/demo_gen/demo/index.mjs @@ -21,7 +21,8 @@ let termini = Object.assign({ { name: "DiplomatStr", - type: "string" + type: "string", + typeUse: "string" } ] @@ -35,7 +36,8 @@ let termini = Object.assign({ { name: "V", - type: "Array" + type: "Array", + typeUse: "Array" } ] @@ -49,7 +51,8 @@ let termini = Object.assign({ { name: "V", - type: "string" + type: "string", + typeUse: "string" } ] @@ -63,7 +66,8 @@ let termini = Object.assign({ { name: "Foo", - type: "string" + type: "string", + typeUse: "string" } ] @@ -86,7 +90,8 @@ let termini = Object.assign({ { name: "Input", - type: "string" + type: "string", + typeUse: "string" } ] diff --git a/feature_tests/demo_gen/demo/rendering/rendering.mjs b/feature_tests/demo_gen/demo/rendering/rendering.mjs index f57bf012d..aca286f1f 100644 --- a/feature_tests/demo_gen/demo/rendering/rendering.mjs +++ b/feature_tests/demo_gen/demo/rendering/rendering.mjs @@ -142,10 +142,8 @@ class EnumTemplate extends ParameterTemplate { let options = clone.querySelector("*[data-options]"); if (this.default === null) { - this.default = enumType.values.values().next().value; - - for (let value of enumType.values) { - options.append(...(new EnumOption(value[0])).children); + for (let entry of enumType.getAllEntries()) { + options.append(...(new EnumOption(entry[0])).children); } } } @@ -171,7 +169,7 @@ class TerminusParams extends HTMLElement { var newChild; - switch (param.type) { + switch (param.typeUse) { case "string": newChild = new StringTemplate(param); this.#params[i] = ""; @@ -188,17 +186,18 @@ class TerminusParams extends HTMLElement { newChild = new StringArrayTemplate(param); this.#params[i] = []; break; + case "enumerator": + newChild = new EnumTemplate(param, library[param.type]); + this.#params[i] = newChild.default + break; + case "external": + let updateParamEvent = (value) => { + this.#params[i] = value; + }; + evaluateExternal(param, updateParamEvent); + break; default: - if (param.type in library && "values" in library[param.type]) { - newChild = new EnumTemplate(param, library[param.type]); - this.#params[i] = newChild.default - } else { - let updateParamEvent = (value) => { - this.#params[i] = value; - }; - evaluateExternal(param, updateParamEvent); - continue; - } + console.error("Unrecognized parameter: ", param); break; } diff --git a/feature_tests/js/api/ContiguousEnum.mjs b/feature_tests/js/api/ContiguousEnum.mjs index cb2cd533e..77aeb5bd1 100644 --- a/feature_tests/js/api/ContiguousEnum.mjs +++ b/feature_tests/js/api/ContiguousEnum.mjs @@ -13,6 +13,10 @@ export class ContiguousEnum { ["F", 3] ]); + static getAllEntries() { + return ContiguousEnum.#values.entries(); + } + constructor(value) { if (arguments.length > 1 && arguments[0] === diplomatRuntime.internalConstructor) { // We pass in two internalConstructor arguments to create *new* diff --git a/feature_tests/js/api/ErrorEnum.mjs b/feature_tests/js/api/ErrorEnum.mjs index efde8bd0b..cedaf53d2 100644 --- a/feature_tests/js/api/ErrorEnum.mjs +++ b/feature_tests/js/api/ErrorEnum.mjs @@ -11,6 +11,10 @@ export class ErrorEnum { ["Bar", 1] ]); + static getAllEntries() { + return ErrorEnum.#values.entries(); + } + constructor(value) { if (arguments.length > 1 && arguments[0] === diplomatRuntime.internalConstructor) { // We pass in two internalConstructor arguments to create *new* diff --git a/feature_tests/js/api/MyEnum.mjs b/feature_tests/js/api/MyEnum.mjs index 2f66512e8..788f7a045 100644 --- a/feature_tests/js/api/MyEnum.mjs +++ b/feature_tests/js/api/MyEnum.mjs @@ -15,6 +15,10 @@ export class MyEnum { ["F", 3] ]); + static getAllEntries() { + return MyEnum.#values.entries(); + } + constructor(value) { if (arguments.length > 1 && arguments[0] === diplomatRuntime.internalConstructor) { // We pass in two internalConstructor arguments to create *new* diff --git a/feature_tests/js/api/OptionEnum.mjs b/feature_tests/js/api/OptionEnum.mjs index a0e362534..57907e448 100644 --- a/feature_tests/js/api/OptionEnum.mjs +++ b/feature_tests/js/api/OptionEnum.mjs @@ -11,6 +11,10 @@ export class OptionEnum { ["Bar", 1] ]); + static getAllEntries() { + return OptionEnum.#values.entries(); + } + constructor(value) { if (arguments.length > 1 && arguments[0] === diplomatRuntime.internalConstructor) { // We pass in two internalConstructor arguments to create *new* diff --git a/feature_tests/js/api/RenamedAttrEnum.mjs b/feature_tests/js/api/RenamedAttrEnum.mjs index c4f46edd4..be4c09515 100644 --- a/feature_tests/js/api/RenamedAttrEnum.mjs +++ b/feature_tests/js/api/RenamedAttrEnum.mjs @@ -12,6 +12,10 @@ export class RenamedAttrEnum { ["Renamed", 2] ]); + static getAllEntries() { + return RenamedAttrEnum.#values.entries(); + } + constructor(value) { if (arguments.length > 1 && arguments[0] === diplomatRuntime.internalConstructor) { // We pass in two internalConstructor arguments to create *new* diff --git a/feature_tests/js/api/UnimportedEnum.mjs b/feature_tests/js/api/UnimportedEnum.mjs index 56ba7abc4..273e06e5e 100644 --- a/feature_tests/js/api/UnimportedEnum.mjs +++ b/feature_tests/js/api/UnimportedEnum.mjs @@ -12,6 +12,10 @@ export class UnimportedEnum { ["C", 2] ]); + static getAllEntries() { + return UnimportedEnum.#values.entries(); + } + constructor(value) { if (arguments.length > 1 && arguments[0] === diplomatRuntime.internalConstructor) { // We pass in two internalConstructor arguments to create *new* diff --git a/tool/src/demo_gen/terminus.rs b/tool/src/demo_gen/terminus.rs index f9a425886..8514d5819 100644 --- a/tool/src/demo_gen/terminus.rs +++ b/tool/src/demo_gen/terminus.rs @@ -20,8 +20,10 @@ pub struct OutParam { /// Full string name of the param. pub label: String, pub default_value: String, - /// For typescript and RenderInfo output. Type that this parameter is. + /// For typescript and RenderInfo output. Type that this parameter is. We get this directly from Rust. pub type_name: String, + /// Also for typescript and RenderInfo output. This is used for types where we might want to know more information, like if it's an enumerator, or a custom type to be set by the default renderer. + pub type_use: String, } /// Represents a function that we'll be using when constructing the ultimate output of a RenderTerminus function. See [`TerminusInfo`] for full output. @@ -177,10 +179,10 @@ impl<'ctx, 'tcx> RenderTerminusContext<'ctx, 'tcx> { /// Helper function for quickly passing a parameter to both our node and the render terminus. /// Appends to [TerminusInfo::out_params] - fn append_out_param( + fn append_out_param>( &mut self, param_name: String, - type_name: String, + type_info: &Type

, node: &mut MethodDependency, attrs: Option, ) { @@ -194,10 +196,37 @@ impl<'ctx, 'tcx> RenderTerminusContext<'ctx, 'tcx> { let default_value = attrs_default.input_cfg.default_value; + let type_name = match type_info { + Type::Primitive(p) => self.formatter.fmt_primitive_as_ffi(*p).to_string(), + Type::Enum(e) => self.formatter.fmt_type_name(e.tcx_id.into()).to_string(), + Type::Slice(hir::Slice::Str(..)) => self.formatter.fmt_string().to_string(), + Type::Slice(hir::Slice::Primitive(.., p)) => { + self.formatter.fmt_primitive_list_type(*p).to_string() + } + Type::Slice(hir::Slice::Strs(..)) => "Array".to_string(), + _ => { + if let Some(i) = type_info.id() { + self.formatter.fmt_type_name(i).to_string() + } else { + panic!("Type {type_info:?} not recognized."); + } + } + }; + + let type_use = if attrs_default.external { + "external".into() + } else { + match type_info { + Type::Enum(..) => "enumerator".into(), + _ => type_name.clone(), + } + }; + let out_param = OutParam { param_name, label, type_name: type_name.clone(), + type_use, default_value, }; @@ -226,13 +255,8 @@ impl<'ctx, 'tcx> RenderTerminusContext<'ctx, 'tcx> { // TODO: I think we need to check for struct and opaque types as to whether or not these have attributes that label them as provided as a parameter. match param_type { // Types we can easily coerce into out parameters (i.e., get easy user input from): - Type::Primitive(p) => { - self.append_out_param( - param_name, - self.formatter.fmt_primitive_as_ffi(*p).to_string(), - node, - Some(param_attrs), - ); + Type::Primitive(..) => { + self.append_out_param(param_name, param_type, node, Some(param_attrs)); } Type::Enum(e) => { let type_name = self.formatter.fmt_type_name(e.tcx_id.into()).to_string(); @@ -242,31 +266,10 @@ impl<'ctx, 'tcx> RenderTerminusContext<'ctx, 'tcx> { .push_error(format!("Found usage of disabled type {type_name}")) } - self.append_out_param(param_name, type_name, node, Some(param_attrs)); - } - Type::Slice(hir::Slice::Str(..)) => { - self.append_out_param( - param_name, - self.formatter.fmt_string().to_string(), - node, - Some(param_attrs), - ); - } - Type::Slice(hir::Slice::Primitive(_, p)) => { - self.append_out_param( - param_name, - self.formatter.fmt_primitive_list_type(*p).to_string(), - node, - Some(param_attrs), - ); + self.append_out_param(param_name, param_type, node, Some(param_attrs)); } - Type::Slice(hir::Slice::Strs(..)) => { - self.append_out_param( - param_name, - "Array".to_string(), - node, - Some(param_attrs), - ); + Type::Slice(..) => { + self.append_out_param(param_name, param_type, node, Some(param_attrs)); } // Types we can't easily coerce into out parameters: Type::Opaque(o) => { @@ -280,7 +283,7 @@ impl<'ctx, 'tcx> RenderTerminusContext<'ctx, 'tcx> { } if all_attrs.demo_attrs.external { - self.append_out_param(param_name, type_name.into(), node, Some(param_attrs)); + self.append_out_param(param_name, param_type, node, Some(param_attrs)); return; } diff --git a/tool/templates/demo_gen/default_renderer/rendering.mjs b/tool/templates/demo_gen/default_renderer/rendering.mjs index f57bf012d..aca286f1f 100644 --- a/tool/templates/demo_gen/default_renderer/rendering.mjs +++ b/tool/templates/demo_gen/default_renderer/rendering.mjs @@ -142,10 +142,8 @@ class EnumTemplate extends ParameterTemplate { let options = clone.querySelector("*[data-options]"); if (this.default === null) { - this.default = enumType.values.values().next().value; - - for (let value of enumType.values) { - options.append(...(new EnumOption(value[0])).children); + for (let entry of enumType.getAllEntries()) { + options.append(...(new EnumOption(entry[0])).children); } } } @@ -171,7 +169,7 @@ class TerminusParams extends HTMLElement { var newChild; - switch (param.type) { + switch (param.typeUse) { case "string": newChild = new StringTemplate(param); this.#params[i] = ""; @@ -188,17 +186,18 @@ class TerminusParams extends HTMLElement { newChild = new StringArrayTemplate(param); this.#params[i] = []; break; + case "enumerator": + newChild = new EnumTemplate(param, library[param.type]); + this.#params[i] = newChild.default + break; + case "external": + let updateParamEvent = (value) => { + this.#params[i] = value; + }; + evaluateExternal(param, updateParamEvent); + break; default: - if (param.type in library && "values" in library[param.type]) { - newChild = new EnumTemplate(param, library[param.type]); - this.#params[i] = newChild.default - } else { - let updateParamEvent = (value) => { - this.#params[i] = value; - }; - evaluateExternal(param, updateParamEvent); - continue; - } + console.error("Unrecognized parameter: ", param); break; } diff --git a/tool/templates/demo_gen/index.js.jinja b/tool/templates/demo_gen/index.js.jinja index bdd2fed5c..2cb731953 100644 --- a/tool/templates/demo_gen/index.js.jinja +++ b/tool/templates/demo_gen/index.js.jinja @@ -17,7 +17,8 @@ let termini = Object.assign({ {% for param in terminus.out_params %} { name: "{{param.label}}", - type: "{{param.type_name}}" + type: "{{param.type_name}}", + typeUse: "{{param.type_use}}" {%- if !param.default_value.is_empty() -%} , defaultValue: "{{ param.default_value }}" diff --git a/tool/templates/js/enum.js.jinja b/tool/templates/js/enum.js.jinja index 233ae962f..9878a5057 100644 --- a/tool/templates/js/enum.js.jinja +++ b/tool/templates/js/enum.js.jinja @@ -13,6 +13,10 @@ export class {{type_name}} { {%- endfor %} ]); + static getAllEntries() { + return {{type_name}}.#values.entries(); + } + {# TODO: I think it's possible to allow for constructors, but we just need to check if a constructor will be generated. -#} constructor(value) {