feat(napi-derive): support const export
This commit is contained in:
parent
6bfaaebadc
commit
47da28adb4
12 changed files with 113 additions and 5 deletions
|
@ -1,5 +1,5 @@
|
|||
use proc_macro2::Ident;
|
||||
use syn::{Attribute, Type};
|
||||
use syn::{Attribute, Expr, Type};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct NapiFn {
|
||||
|
@ -93,3 +93,11 @@ pub struct NapiEnumVariant {
|
|||
pub val: i32,
|
||||
pub comments: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct NapiConst {
|
||||
pub name: Ident,
|
||||
pub js_name: String,
|
||||
pub type_name: Type,
|
||||
pub value: Expr,
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ use proc_macro2::{Ident, Span, TokenStream};
|
|||
|
||||
use crate::BindgenResult;
|
||||
|
||||
mod r#const;
|
||||
mod r#enum;
|
||||
mod r#fn;
|
||||
mod r#struct;
|
||||
|
|
41
crates/backend/src/codegen/const.rs
Normal file
41
crates/backend/src/codegen/const.rs
Normal file
|
@ -0,0 +1,41 @@
|
|||
use proc_macro2::{Literal, TokenStream};
|
||||
use quote::ToTokens;
|
||||
|
||||
use crate::{codegen::get_register_ident, BindgenResult, NapiConst, TryToTokens};
|
||||
|
||||
impl TryToTokens for NapiConst {
|
||||
fn try_to_tokens(&self, tokens: &mut TokenStream) -> BindgenResult<()> {
|
||||
let register = self.gen_module_register();
|
||||
(quote! {
|
||||
#register
|
||||
})
|
||||
.to_tokens(tokens);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl NapiConst {
|
||||
fn gen_module_register(&self) -> TokenStream {
|
||||
let name_str = self.name.to_string();
|
||||
let name_ident = self.name.clone();
|
||||
let js_name_lit = Literal::string(&self.js_name);
|
||||
let register_name = get_register_ident(&name_str);
|
||||
let type_name = &self.type_name;
|
||||
quote! {
|
||||
#[allow(non_snake_case)]
|
||||
#[allow(clippy::all)]
|
||||
#[napi::bindgen_prelude::ctor]
|
||||
fn #register_name() {
|
||||
use std::ffi::CString;
|
||||
use std::ptr;
|
||||
|
||||
unsafe fn cb(env: napi::sys::napi_env) -> napi::Result<napi::sys::napi_value> {
|
||||
<#type_name as napi::bindgen_prelude::ToNapiValue>::to_napi_value(env, #name_ident)
|
||||
}
|
||||
|
||||
napi::bindgen_prelude::register_module_export(#js_name_lit, cb);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -53,4 +53,5 @@ napi_ast_impl! {
|
|||
(Struct, NapiStruct),
|
||||
(Impl, NapiImpl),
|
||||
(Enum, NapiEnum),
|
||||
(Const, NapiConst),
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
mod r#const;
|
||||
mod r#enum;
|
||||
mod r#fn;
|
||||
pub(crate) mod r#struct;
|
||||
|
|
17
crates/backend/src/typegen/const.rs
Normal file
17
crates/backend/src/typegen/const.rs
Normal file
|
@ -0,0 +1,17 @@
|
|||
use super::{ToTypeDef, TypeDef};
|
||||
|
||||
use crate::{ty_to_ts_type, NapiConst};
|
||||
|
||||
impl ToTypeDef for NapiConst {
|
||||
fn to_type_def(&self) -> TypeDef {
|
||||
TypeDef {
|
||||
kind: "const".to_owned(),
|
||||
name: self.js_name.to_owned(),
|
||||
def: format!(
|
||||
"export const {}: {}",
|
||||
&self.js_name,
|
||||
ty_to_ts_type(&self.type_name, false).0
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
|
@ -9,8 +9,9 @@ use attrs::{BindgenAttr, BindgenAttrs};
|
|||
|
||||
use convert_case::{Case, Casing};
|
||||
use napi_derive_backend::{
|
||||
BindgenResult, CallbackArg, Diagnostic, FnKind, FnSelf, Napi, NapiEnum, NapiEnumVariant, NapiFn,
|
||||
NapiFnArgKind, NapiImpl, NapiItem, NapiStruct, NapiStructField, NapiStructKind,
|
||||
BindgenResult, CallbackArg, Diagnostic, FnKind, FnSelf, Napi, NapiConst, NapiEnum,
|
||||
NapiEnumVariant, NapiFn, NapiFnArgKind, NapiImpl, NapiItem, NapiStruct, NapiStructField,
|
||||
NapiStructKind,
|
||||
};
|
||||
use proc_macro2::{Ident, TokenStream, TokenTree};
|
||||
use quote::ToTokens;
|
||||
|
@ -296,7 +297,7 @@ fn extract_doc_comments(attrs: &[syn::Attribute]) -> Vec<String> {
|
|||
})
|
||||
}
|
||||
|
||||
// Unescapes a quoted string. char::escape_debug() was used to escape the text.
|
||||
// Unescaped a quoted string. char::escape_debug() was used to escape the text.
|
||||
fn try_unescape(s: &str) -> Option<String> {
|
||||
if s.is_empty() {
|
||||
return Some(String::new());
|
||||
|
@ -584,6 +585,7 @@ impl ParseNapi for syn::Item {
|
|||
syn::Item::Struct(s) => s.parse_napi(tokens, opts),
|
||||
syn::Item::Impl(i) => i.parse_napi(tokens, opts),
|
||||
syn::Item::Enum(e) => e.parse_napi(tokens, opts),
|
||||
syn::Item::Const(c) => c.parse_napi(tokens, opts),
|
||||
_ => bail_span!(
|
||||
self,
|
||||
"#[napi] can only be applied to a function, struct, enum or impl."
|
||||
|
@ -625,6 +627,14 @@ impl ParseNapi for syn::ItemEnum {
|
|||
}
|
||||
}
|
||||
|
||||
impl ParseNapi for syn::ItemConst {
|
||||
fn parse_napi(&mut self, tokens: &mut TokenStream, opts: BindgenAttrs) -> BindgenResult<Napi> {
|
||||
let napi = self.convert_to_ast(opts);
|
||||
self.to_tokens(tokens);
|
||||
napi
|
||||
}
|
||||
}
|
||||
|
||||
fn fn_kind(opts: &BindgenAttrs) -> FnKind {
|
||||
let mut kind = FnKind::Normal;
|
||||
|
||||
|
@ -910,3 +920,22 @@ impl ConvertToAST for syn::ItemEnum {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl ConvertToAST for syn::ItemConst {
|
||||
fn convert_to_ast(&mut self, opts: BindgenAttrs) -> BindgenResult<Napi> {
|
||||
match self.vis {
|
||||
Visibility::Public(_) => Ok(Napi {
|
||||
comments: vec![],
|
||||
item: NapiItem::Const(NapiConst {
|
||||
name: self.ident.clone(),
|
||||
js_name: opts
|
||||
.js_name()
|
||||
.map_or_else(|| self.ident.to_string(), |(s, _)| s.to_string()),
|
||||
type_name: *self.ty.clone(),
|
||||
value: *self.expr.clone(),
|
||||
}),
|
||||
}),
|
||||
_ => bail_span!(self, "only public const allowed"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,8 @@ Generated by [AVA](https://avajs.dev).
|
|||
|
||||
> Snapshot 1
|
||||
|
||||
`export function getWords(): Array<string>␊
|
||||
`export const DEFAULT_COST: number␊
|
||||
export function getWords(): Array<string>␊
|
||||
export function getNums(): Array<number>␊
|
||||
export function sumNums(nums: Array<number>): number␊
|
||||
export function readFileAsync(path: string): Promise<Buffer>␊
|
||||
|
|
Binary file not shown.
|
@ -3,6 +3,7 @@ import { join } from 'path'
|
|||
import test from 'ava'
|
||||
|
||||
import {
|
||||
DEFAULT_COST,
|
||||
add,
|
||||
fibonacci,
|
||||
contains,
|
||||
|
@ -48,6 +49,10 @@ import {
|
|||
createSymbol,
|
||||
} from '../'
|
||||
|
||||
test('export const', (t) => {
|
||||
t.is(DEFAULT_COST, 12)
|
||||
})
|
||||
|
||||
test('number', (t) => {
|
||||
t.is(add(1, 2), 3)
|
||||
t.is(fibonacci(5), 5)
|
||||
|
|
1
examples/napi/index.d.ts
vendored
1
examples/napi/index.d.ts
vendored
|
@ -1,3 +1,4 @@
|
|||
export const DEFAULT_COST: number
|
||||
export function getWords(): Array<string>
|
||||
export function getNums(): Array<number>
|
||||
export function sumNums(nums: Array<number>): number
|
||||
|
|
|
@ -3,6 +3,9 @@ extern crate napi_derive;
|
|||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
|
||||
#[napi]
|
||||
pub const DEFAULT_COST: u32 = 12;
|
||||
|
||||
mod array;
|
||||
mod r#async;
|
||||
mod bigint;
|
||||
|
|
Loading…
Reference in a new issue