From 7c4dc2a2bddec8f66f8c4f77b9a52b9bdacb153a Mon Sep 17 00:00:00 2001 From: Francesco Benedetto Date: Mon, 3 Apr 2023 08:10:58 +0200 Subject: [PATCH] feat(napi-derive-backend, napi-derive): add support for string enums (#1551) --- crates/backend/src/ast.rs | 19 ++- crates/backend/src/codegen/enum.rs | 16 ++- crates/backend/src/typegen/enum.rs | 13 +- crates/macro/src/parser/attrs.rs | 3 +- crates/macro/src/parser/mod.rs | 136 ++++++++++++-------- examples/napi/__test__/typegen.spec.ts.md | 5 + examples/napi/__test__/typegen.spec.ts.snap | Bin 3900 -> 3945 bytes examples/napi/index.d.ts | 5 + examples/napi/src/enum.rs | 7 + 9 files changed, 132 insertions(+), 72 deletions(-) diff --git a/crates/backend/src/ast.rs b/crates/backend/src/ast.rs index b907775e..a1ee4424 100644 --- a/crates/backend/src/ast.rs +++ b/crates/backend/src/ast.rs @@ -1,4 +1,4 @@ -use proc_macro2::Ident; +use proc_macro2::{Ident, Literal}; use syn::{Attribute, Expr, Type}; #[derive(Debug, Clone)] @@ -133,10 +133,25 @@ pub struct NapiEnum { pub skip_typescript: bool, } +#[derive(Debug, Clone)] +pub enum NapiEnumValue { + String(String), + Number(i32), +} + +impl Into for &NapiEnumValue { + fn into(self) -> Literal { + match self { + NapiEnumValue::String(string) => Literal::string(string), + NapiEnumValue::Number(number) => Literal::i32_unsuffixed(number.to_owned()), + } + } +} + #[derive(Debug, Clone)] pub struct NapiEnumVariant { pub name: Ident, - pub val: i32, + pub val: NapiEnumValue, pub comments: Vec, } diff --git a/crates/backend/src/codegen/enum.rs b/crates/backend/src/codegen/enum.rs index 27dd3346..0a7137c2 100644 --- a/crates/backend/src/codegen/enum.rs +++ b/crates/backend/src/codegen/enum.rs @@ -29,7 +29,7 @@ impl NapiEnum { let mut to_napi_branches = vec![]; self.variants.iter().for_each(|v| { - let val = Literal::i32_unsuffixed(v.val); + let val: Literal = (&v.val).into(); let v_name = &v.name; from_napi_branches.push(quote! { #val => Ok(#name::#v_name) }); @@ -62,7 +62,7 @@ impl NapiEnum { env: napi::bindgen_prelude::sys::napi_env, napi_val: napi::bindgen_prelude::sys::napi_value ) -> napi::bindgen_prelude::Result { - let val = i32::from_napi_value(env, napi_val).map_err(|e| { + let val = FromNapiValue::from_napi_value(env, napi_val).map_err(|e| { napi::bindgen_prelude::error!( e.status, "Failed to convert napi value into enum `{}`. {}", @@ -76,7 +76,7 @@ impl NapiEnum { _ => { Err(napi::bindgen_prelude::error!( napi::bindgen_prelude::Status::InvalidArg, - "value `{}` does not match any variant of enum `{}`", + "value `{:?}` does not match any variant of enum `{}`", val, #name_str )) @@ -94,7 +94,7 @@ impl NapiEnum { #(#to_napi_branches,)* }; - i32::to_napi_value(env, val) + ToNapiValue::to_napi_value(env, val) } } } @@ -109,13 +109,17 @@ impl NapiEnum { for variant in self.variants.iter() { let name_lit = Literal::string(&format!("{}\0", variant.name)); - let val_lit = Literal::i32_unsuffixed(variant.val); + let val_lit: Literal = (&variant.val).into(); define_properties.push(quote! { { let name = std::ffi::CStr::from_bytes_with_nul_unchecked(#name_lit.as_bytes()); napi::bindgen_prelude::check_status!( - napi::bindgen_prelude::sys::napi_set_named_property(env, obj_ptr, name.as_ptr(), i32::to_napi_value(env, #val_lit)?), + napi::bindgen_prelude::sys::napi_set_named_property( + env, + obj_ptr, name.as_ptr(), + ToNapiValue::to_napi_value(env, #val_lit)? + ), "Failed to defined enum `{}`", #js_name_lit )?; diff --git a/crates/backend/src/typegen/enum.rs b/crates/backend/src/typegen/enum.rs index 6f3c1efe..cdd03780 100644 --- a/crates/backend/src/typegen/enum.rs +++ b/crates/backend/src/typegen/enum.rs @@ -1,5 +1,5 @@ use super::{add_alias, ToTypeDef, TypeDef}; -use crate::{js_doc_from_comments, NapiEnum}; +use crate::{js_doc_from_comments, NapiEnum, NapiEnumValue}; impl ToTypeDef for NapiEnum { fn to_type_def(&self) -> Option { @@ -26,12 +26,11 @@ impl NapiEnum { .variants .iter() .map(|v| { - format!( - "{}{} = {}", - js_doc_from_comments(&v.comments), - v.name, - v.val, - ) + let val = match &v.val { + NapiEnumValue::Number(num) => format!("{}", num), + NapiEnumValue::String(string) => format!("'{}'", string), + }; + format!("{}{} = {}", js_doc_from_comments(&v.comments), v.name, val) }) .collect::>() .join(",\n ") diff --git a/crates/macro/src/parser/attrs.rs b/crates/macro/src/parser/attrs.rs index a0fcdd94..19b4a110 100644 --- a/crates/macro/src/parser/attrs.rs +++ b/crates/macro/src/parser/attrs.rs @@ -38,7 +38,7 @@ pub struct BindgenAttrs { } // NOTE: borrowed from wasm-bindgen -// some of them may useless is #[napi] macro +// some of them may useless in #[napi] macro macro_rules! attrgen { ($mac:ident) => { $mac! { @@ -65,6 +65,7 @@ macro_rules! attrgen { (ts_return_type, TsReturnType(Span, String, Span)), (ts_type, TsType(Span, String, Span)), (ts_generic_types, TsGenericTypes(Span, String, Span)), + (string_enum, StringEnum(Span)), // impl later // (inspectable, Inspectable(Span)), diff --git a/crates/macro/src/parser/mod.rs b/crates/macro/src/parser/mod.rs index f4b1a2b6..86afc1f0 100644 --- a/crates/macro/src/parser/mod.rs +++ b/crates/macro/src/parser/mod.rs @@ -9,7 +9,7 @@ use attrs::{BindgenAttr, BindgenAttrs}; use convert_case::{Case, Casing}; use napi_derive_backend::{ - BindgenResult, CallbackArg, Diagnostic, FnKind, FnSelf, Napi, NapiConst, NapiEnum, + BindgenResult, CallbackArg, Diagnostic, FnKind, FnSelf, Napi, NapiConst, NapiEnum, NapiEnumValue, NapiEnumVariant, NapiFn, NapiFnArg, NapiFnArgKind, NapiImpl, NapiItem, NapiStruct, NapiStructField, NapiStructKind, }; @@ -1124,63 +1124,87 @@ impl ConvertToAST for syn::ItemEnum { .js_name() .map_or_else(|| self.ident.to_string(), |(s, _)| s.to_string()); - let mut last_variant_val: i32 = -1; - let variants = self - .variants - .iter() - .map(|v| { - match v.fields { - syn::Fields::Unit => {} - _ => bail_span!(v.fields, "Structured enum is not supported in #[napi]"), - }; - - let val = match &v.discriminant { - Some((_, expr)) => { - let mut symbol = 1; - let mut inner_expr = get_expr(expr); - if let syn::Expr::Unary(syn::ExprUnary { - attrs: _, - op: syn::UnOp::Neg(_), - expr, - }) = inner_expr - { - symbol = -1; - inner_expr = expr; - } - - match inner_expr { - syn::Expr::Lit(syn::ExprLit { - attrs: _, - lit: syn::Lit::Int(int_lit), - }) => match int_lit.base10_digits().parse::() { - Ok(v) => symbol * v, - Err(_) => { - bail_span!( - int_lit, - "enums with #[wasm_bindgen] can only support \ - numbers that can be represented as i32", - ); - } - }, - _ => bail_span!( - expr, - "enums with #[wasm_bindgen] may only have \ - number literal values", - ), - } + let variants = match opts.string_enum() { + Some(_) => self + .variants + .iter() + .map(|v| { + if !matches!(v.fields, syn::Fields::Unit) { + bail_span!(v.fields, "Structured enum is not supported in #[napi]") } - None => last_variant_val + 1, - }; - - last_variant_val = val; - - Ok(NapiEnumVariant { - name: v.ident.clone(), - val, - comments: extract_doc_comments(&v.attrs), + if matches!(&v.discriminant, Some((_, _))) { + bail_span!( + v.fields, + "Literal values are not supported with string enum in #[napi]" + ) + } + Ok(NapiEnumVariant { + name: v.ident.clone(), + val: NapiEnumValue::String(v.ident.to_string()), + comments: extract_doc_comments(&v.attrs), + }) }) - }) - .collect::>>()?; + .collect::>>()?, + None => { + let mut last_variant_val: i32 = -1; + + self + .variants + .iter() + .map(|v| { + if !matches!(v.fields, syn::Fields::Unit) { + bail_span!(v.fields, "Structured enum is not supported in #[napi]") + } + + let val = match &v.discriminant { + Some((_, expr)) => { + let mut symbol = 1; + let mut inner_expr = get_expr(expr); + if let syn::Expr::Unary(syn::ExprUnary { + attrs: _, + op: syn::UnOp::Neg(_), + expr, + }) = inner_expr + { + symbol = -1; + inner_expr = expr; + } + + match inner_expr { + syn::Expr::Lit(syn::ExprLit { + attrs: _, + lit: syn::Lit::Int(int_lit), + }) => match int_lit.base10_digits().parse::() { + Ok(v) => symbol * v, + Err(_) => { + bail_span!( + int_lit, + "enums with #[wasm_bindgen] can only support \ + numbers that can be represented as i32", + ); + } + }, + _ => bail_span!( + expr, + "enums with #[wasm_bindgen] may only have \ + number literal values", + ), + } + } + None => last_variant_val + 1, + }; + + last_variant_val = val; + + Ok(NapiEnumVariant { + name: v.ident.clone(), + val: NapiEnumValue::Number(val), + comments: extract_doc_comments(&v.attrs), + }) + }) + .collect::>>()? + } + }; Ok(Napi { item: NapiItem::Enum(NapiEnum { diff --git a/examples/napi/__test__/typegen.spec.ts.md b/examples/napi/__test__/typegen.spec.ts.md index 8c68405a..e978724c 100644 --- a/examples/napi/__test__/typegen.spec.ts.md +++ b/examples/napi/__test__/typegen.spec.ts.md @@ -98,6 +98,11 @@ Generated by [AVA](https://avajs.dev). export const enum Empty {␊ ␊ }␊ + export const enum Status {␊ + Pristine = 'Pristine',␊ + Loading = 'Loading',␊ + Ready = 'Ready'␊ + }␊ /** You could break the step and for an new continuous value. */␊ export const enum CustomNumEnum {␊ One = 1,␊ diff --git a/examples/napi/__test__/typegen.spec.ts.snap b/examples/napi/__test__/typegen.spec.ts.snap index e249977761fba91f3025d912d8f4150993cd4b85..abcd4363458879ff7b100a57a89ba234541083f0 100644 GIT binary patch literal 3945 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 DP9d=( literal 3900 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 Ku-A{iIRF6Eg`LU( diff --git a/examples/napi/index.d.ts b/examples/napi/index.d.ts index 2ad678be..aba4722f 100644 --- a/examples/napi/index.d.ts +++ b/examples/napi/index.d.ts @@ -87,6 +87,11 @@ export const enum Kind { } export const enum Empty { +} +export const enum Status { + Pristine = 'Pristine', + Loading = 'Loading', + Ready = 'Ready' } /** You could break the step and for an new continuous value. */ export const enum CustomNumEnum { diff --git a/examples/napi/src/enum.rs b/examples/napi/src/enum.rs index 58e1cd12..a2e72a18 100644 --- a/examples/napi/src/enum.rs +++ b/examples/napi/src/enum.rs @@ -14,6 +14,13 @@ pub enum Kind { #[napi] pub enum Empty {} +#[napi(string_enum)] +pub enum Status { + Pristine, + Loading, + Ready, +} + /// You could break the step and for an new continuous value. #[napi] pub enum CustomNumEnum {