feat(napi-derive): add optional enum_string case conversion (#1995)
This commit is contained in:
parent
d962e34d3a
commit
6b1058a268
8 changed files with 91 additions and 19 deletions
|
@ -71,7 +71,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)),
|
||||
(string_enum, StringEnum(Span, Option<(String, Span)>)),
|
||||
(use_nullable, UseNullable(Span, Option<bool>), false),
|
||||
|
||||
// impl later
|
||||
|
@ -132,6 +132,21 @@ macro_rules! methods {
|
|||
}
|
||||
};
|
||||
|
||||
(@method $name:ident, $variant:ident(Span, Option<(String, Span)>)) => {
|
||||
pub fn $name(&self) -> Option<Option<&(String, Span)>> {
|
||||
self.attrs
|
||||
.iter()
|
||||
.filter_map(|a| match &a.1 {
|
||||
BindgenAttr::$variant(_, s) => {
|
||||
a.0.set(true);
|
||||
Some(s.as_ref())
|
||||
}
|
||||
_ => None,
|
||||
})
|
||||
.next()
|
||||
}
|
||||
};
|
||||
|
||||
(@method $name:ident, $variant:ident(Span, Option<bool>), $default_value:literal) => {
|
||||
pub fn $name(&self) -> bool {
|
||||
self.attrs
|
||||
|
@ -396,6 +411,21 @@ impl Parse for BindgenAttr {
|
|||
return Ok(BindgenAttr::$variant(attr_span, val, span))
|
||||
});
|
||||
|
||||
(@parser $variant:ident(Span, Option<(String, Span)>)) => ({
|
||||
if let Ok(_) = input.parse::<Token![=]>() {
|
||||
let val = match input.parse::<syn::LitStr>() {
|
||||
Ok(str) => Some((str.value(), str.span())),
|
||||
Err(_) => {
|
||||
let ident = input.parse::<AnyIdent>()?.0;
|
||||
Some((ident.to_string(), ident.span()))
|
||||
}
|
||||
};
|
||||
return Ok(BindgenAttr::$variant(attr_span, val))
|
||||
} else {
|
||||
return Ok(BindgenAttr::$variant(attr_span, None))
|
||||
}
|
||||
});
|
||||
|
||||
(@parser $variant:ident(Span, Option<bool>), $default_value:literal) => ({
|
||||
if let Ok(_) = input.parse::<Token![=]>() {
|
||||
let (val, _) = match input.parse::<syn::LitBool>() {
|
||||
|
|
|
@ -1062,26 +1062,48 @@ impl ConvertToAST for syn::ItemEnum {
|
|||
.map_or_else(|| self.ident.to_string(), |(s, _)| s.to_string());
|
||||
|
||||
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]")
|
||||
Some(case) => {
|
||||
let case = case.map(|c| Ok::<Case, Diagnostic>(match c.0.as_str() {
|
||||
"lowercase" => Case::Flat,
|
||||
"UPPERCASE" => Case::UpperFlat,
|
||||
"PascalCase" => Case::Pascal,
|
||||
"camelCase" => Case::Camel,
|
||||
"snake_case" => Case::Snake,
|
||||
"SCREAMING_SNAKE_CASE" => Case::UpperSnake,
|
||||
"kebab-case" => Case::Kebab,
|
||||
"SCREAMING-KEBAB-CASE" => Case::UpperKebab,
|
||||
_ => {
|
||||
bail_span!(self, "Unknown string enum case. Possible values are \"lowercase\", \"UPPERCASE\", \"PascalCase\", \"camelCase\", \"snake_case\", \"SCREAMING_SNAKE_CASE\", \"kebab-case\", or \"SCREAMING-KEBAB-CASE\"")
|
||||
}
|
||||
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),
|
||||
})).transpose()?;
|
||||
|
||||
self
|
||||
.variants
|
||||
.iter()
|
||||
.map(|v| {
|
||||
if !matches!(v.fields, syn::Fields::Unit) {
|
||||
bail_span!(v.fields, "Structured enum is not supported in #[napi]")
|
||||
}
|
||||
if matches!(&v.discriminant, Some((_, _))) {
|
||||
bail_span!(
|
||||
v.fields,
|
||||
"Literal values are not supported with string enum in #[napi]"
|
||||
)
|
||||
}
|
||||
|
||||
let mut val = v.ident.to_string();
|
||||
if let Some(case) = case {
|
||||
val = val.to_case(case)
|
||||
};
|
||||
|
||||
Ok(NapiEnumVariant {
|
||||
name: v.ident.clone(),
|
||||
val: NapiEnumValue::String(val),
|
||||
comments: extract_doc_comments(&v.attrs),
|
||||
})
|
||||
})
|
||||
})
|
||||
.collect::<BindgenResult<Vec<NapiEnumVariant>>>()?,
|
||||
.collect::<BindgenResult<Vec<NapiEnumVariant>>>()?
|
||||
}
|
||||
None => {
|
||||
let mut last_variant_val: i32 = -1;
|
||||
|
||||
|
|
|
@ -617,6 +617,12 @@ Generated by [AVA](https://avajs.dev).
|
|||
name: string␊
|
||||
}␊
|
||||
␊
|
||||
export const enum StringEnum {␊
|
||||
VariantOne = 'variantone',␊
|
||||
VariantTwo = 'varianttwo',␊
|
||||
VariantThree = 'variantthree'␊
|
||||
}␊
|
||||
␊
|
||||
export function sumBtreeMapping(nums: Record<string, number>): number␊
|
||||
␊
|
||||
export function sumIndexMapping(nums: Record<string, number>): number␊
|
||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -509,6 +509,7 @@ module.exports.roundtripStr = nativeBinding.roundtripStr
|
|||
module.exports.runScript = nativeBinding.runScript
|
||||
module.exports.setSymbolInObj = nativeBinding.setSymbolInObj
|
||||
module.exports.Status = nativeBinding.Status
|
||||
module.exports.StringEnum = nativeBinding.StringEnum
|
||||
module.exports.sumBtreeMapping = nativeBinding.sumBtreeMapping
|
||||
module.exports.sumIndexMapping = nativeBinding.sumIndexMapping
|
||||
module.exports.sumMapping = nativeBinding.sumMapping
|
||||
|
|
|
@ -607,6 +607,12 @@ export interface StrictObject {
|
|||
name: string
|
||||
}
|
||||
|
||||
export const enum StringEnum {
|
||||
VariantOne = 'variantone',
|
||||
VariantTwo = 'varianttwo',
|
||||
VariantThree = 'variantthree'
|
||||
}
|
||||
|
||||
export function sumBtreeMapping(nums: Record<string, number>): number
|
||||
|
||||
export function sumIndexMapping(nums: Record<string, number>): number
|
||||
|
|
|
@ -19,6 +19,13 @@ pub enum Status {
|
|||
Ready,
|
||||
}
|
||||
|
||||
#[napi(string_enum = "lowercase")]
|
||||
pub enum StringEnum {
|
||||
VariantOne,
|
||||
VariantTwo,
|
||||
VariantThree,
|
||||
}
|
||||
|
||||
/// You could break the step and for an new continuous value.
|
||||
#[napi]
|
||||
pub enum CustomNumEnum {
|
||||
|
|
Loading…
Reference in a new issue