diff --git a/webapi_gen/emit/interface_emitter.mbt b/webapi_gen/emit/interface_emitter.mbt index 349d61d..359be9c 100644 --- a/webapi_gen/emit/interface_emitter.mbt +++ b/webapi_gen/emit/interface_emitter.mbt @@ -217,9 +217,45 @@ pub impl Emitter for InterfaceEmitter with emit( interface_methods.push(trait_method) continue rest } - [Attribute(attr), .. rest] if attr.static_ => - // Static attributes are not yet handled + [Attribute(attr), .. rest] if attr.static_ => { + if attr.is_readonly && !attr.is_inherit { + // only static readonly attributes are supported for now + // TODO: log this + continue rest + } + let (attr_type, attr_emits) = arg_mbt_type( + attr.type_, + interface.name, + attr.name, + "", + self.type_registry, + ) + emits.push_iter(attr_emits.iter()) + if attr_type is ArgMbtType::Union(union_type_name, has_undefined) { + emits + ..push(Emit::External(union_type_name)) + ..push(Emit::IntoMethod(union_type_name)) + if has_undefined { + emits.push(Emit::IsUndefinedMethod(union_type_name)) + } + emits.push( + Emit::UnionArgTraitImpl( + TypeName(union_type_name), + TraitName("T\{union_type_name}"), + ), + ) + } + emits.push_iter(attr_emits.iter()) + + // Static Attribute Get method + let static_attr_getter_method = StaticAttributeGetMethodEmit::{ + interface_name: interface.name, + original_name: attr.name, + return_type: attr_type.name(), + } + interface_methods.push(static_attr_getter_method) continue rest + } [Attribute(attr), .. rest] => { let (attr_type, attr_emits) = arg_mbt_type( attr.type_, diff --git a/webapi_gen/emit/interface_method_emit.mbt b/webapi_gen/emit/interface_method_emit.mbt index 652c9a2..2901030 100644 --- a/webapi_gen/emit/interface_method_emit.mbt +++ b/webapi_gen/emit/interface_method_emit.mbt @@ -198,6 +198,48 @@ impl InterfaceMethodEmit for AttributeSetMethodEmit with impl_emit( Code(code.to_string()) } +//============================ Attribute Set Method Emit ====================== + +///| +struct StaticAttributeGetMethodEmit { + interface_name : String // Name of the interface this method belongs to, eg. Document + original_name : String // Original attribute name from IDL, eg "title" + return_type : String +} derive(Show, ToJson) + +///| +impl InterfaceMethodEmit for StaticAttributeGetMethodEmit with decl_emit( + _self : StaticAttributeGetMethodEmit, +) -> Code { + Code("") // Static attributes are not included in trait declarations +} + +///| +impl InterfaceMethodEmit for StaticAttributeGetMethodEmit with impl_emit( + self : StaticAttributeGetMethodEmit, +) -> Code { + // Emit FFI function + let ret_type_str = self.return_type + let trait_name = self.interface_name + let ffi_name = "\{snake_case(trait_name)}_\{snake_case(self.original_name)}_ffi" + let code = StringBuilder::new() + code + ..write_string( + "extern \"js\" fn \{ffi_name}() -> \{ret_type_str} = \"() => \{trait_name}.\{self.original_name}\"", + ) + ..write_string("\n\n") + + // Emit static attribute getter implementation + let method_name = safe_identifier(self.original_name) + code + ..write_string( + "pub fn \{trait_name}::\{method_name}() -> \{ret_type_str} {\n", + ) + ..write_string(" \{ffi_name}()\n") + ..write_string("}") + Code(code.to_string()) +} + //============================ Method Emit Helpers ============================ ///|