refactor(napi-derive): make typegen easier to read (#2956)

This commit is contained in:
LongYinan 2025-10-11 14:46:38 +08:00 committed by GitHub
parent 7a9397cb43
commit 656bdca927
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 767 additions and 360 deletions

View File

@ -71,6 +71,7 @@ jobs:
yarn tsc -p examples/napi/tsconfig.json --noEmit --skipLibCheck
yarn test:macro
cargo test -p napi-cargo-test --features noop
cargo test -p napi-derive-backend --features type-def
toolchain: stable
- host: ubuntu-latest
target: x86_64-unknown-linux-gnu
@ -90,6 +91,7 @@ jobs:
yarn tsc -p examples/napi/tsconfig.json --noEmit --skipLibCheck
RUSTFLAGS="-C link-args=-Wl,-undefined,dynamic_lookup,-no_fixup_chains"
cargo test -p napi-cargo-test --features noop
cargo test -p napi-derive-backend --features type-def
toolchain: stable
- host: windows-latest
target: x86_64-pc-windows-msvc
@ -100,6 +102,7 @@ jobs:
yarn tsc -p examples/napi/tsconfig.json --noEmit --skipLibCheck
yarn test:macro
cargo test -p napi-cargo-test --features noop
cargo test -p napi-derive-backend --features type-def
toolchain: stable
- host: windows-11-arm
target: aarch64-pc-windows-msvc

File diff suppressed because it is too large Load Diff

View File

@ -2,11 +2,9 @@ use std::collections::HashMap;
use std::vec::Vec;
use std::{cell::RefCell, iter};
use super::{add_alias, ToTypeDef, TypeDef};
use super::{add_alias, format_js_property_name, ty_to_ts_type, ToTypeDef, TypeDef};
use crate::typegen::JSDoc;
use crate::{
format_js_property_name, ty_to_ts_type, NapiImpl, NapiStruct, NapiStructField, NapiStructKind,
};
use crate::{NapiImpl, NapiStruct, NapiStructField, NapiStructKind};
thread_local! {
pub(crate) static TASK_STRUCTS: RefCell<HashMap<String, String>> = Default::default();

View File

@ -973,6 +973,37 @@ Generated by [AVA](https://avajs.dev).
export declare function promiseRawReturnClassInstance(): Promise<ClassReturnInPromise>
export interface PropertyNameDigitTest {␊
/** Property names starting with digits should be quoted */␊
'0invalid': string␊
'123': string␊
}␊
export interface PropertyNameSpecialCharsTest {␊
/** Special characters should be quoted */␊
'kebab-case': string␊
'with space': string␊
'dot.notation': string␊
'xml:lang': string␊
/** Dollar sign should be quoted for backward compatibility */␊
'$var': string␊
}␊
export interface PropertyNameUnicodeTest {␊
/** Unicode characters should NOT be quoted */␊
café: string␊
日本語: string␊
Ελληνικά: string␊
}␊
export interface PropertyNameValidTest {␊
/** Valid identifiers should NOT be quoted */␊
camelCase: string␊
pascalCase: string␊
private: string␊
with123Numbers: string␊
}␊
/** napi = { version = 2, features = ["serde-json"] } */␊
export declare function readFile(callback: (arg0: Error | undefined, arg1?: string | undefined | null) => void): void␊

View File

@ -0,0 +1,64 @@
import test from 'ava'
import type {
PropertyNameDigitTest,
PropertyNameSpecialCharsTest,
PropertyNameUnicodeTest,
PropertyNameValidTest,
} from '../index.cjs'
test('Unicode property names should be unquoted', (t) => {
// These should compile without quotes
const obj: PropertyNameUnicodeTest = {
café: 'coffee',
: 'japanese',
Ελληνικά: 'greek',
}
t.is(obj.café, 'coffee')
t.is(obj., 'japanese')
t.is(obj.Ελληνικά, 'greek')
})
test('Special character property names should be quoted', (t) => {
// These require quotes in the type definition
const obj: PropertyNameSpecialCharsTest = {
'kebab-case': 'value1',
'with space': 'value2',
'dot.notation': 'value3',
'xml:lang': 'value4',
$var: 'value5',
}
t.is(obj['kebab-case'], 'value1')
t.is(obj['with space'], 'value2')
t.is(obj['dot.notation'], 'value3')
t.is(obj['xml:lang'], 'value4')
t.is(obj['$var'], 'value5')
})
test('Digit-starting property names should be quoted', (t) => {
// These require quotes because they start with digits
const obj: PropertyNameDigitTest = {
'0invalid': 'value1',
'123': 'value2',
}
t.is(obj['0invalid'], 'value1')
t.is(obj['123'], 'value2')
})
test('Valid identifier property names should be unquoted', (t) => {
// These should compile without quotes
const obj: PropertyNameValidTest = {
camelCase: 'value1',
pascalCase: 'value2',
private: 'value3',
with123Numbers: 'value4',
}
t.is(obj.camelCase, 'value1')
t.is(obj.pascalCase, 'value2')
t.is(obj.private, 'value3')
t.is(obj.with123Numbers, 'value4')
})

View File

@ -934,6 +934,37 @@ export declare function promiseInEither(input: number | Promise<number>): Promis
export declare function promiseRawReturnClassInstance(): Promise<ClassReturnInPromise>
export interface PropertyNameDigitTest {
/** Property names starting with digits should be quoted */
'0invalid': string
'123': string
}
export interface PropertyNameSpecialCharsTest {
/** Special characters should be quoted */
'kebab-case': string
'with space': string
'dot.notation': string
'xml:lang': string
/** Dollar sign should be quoted for backward compatibility */
'$var': string
}
export interface PropertyNameUnicodeTest {
/** Unicode characters should NOT be quoted */
café: string
日本語: string
Ελληνικά: string
}
export interface PropertyNameValidTest {
/** Valid identifiers should NOT be quoted */
camelCase: string
pascalCase: string
private: string
with123Numbers: string
}
/** napi = { version = 2, features = ["serde-json"] } */
export declare function readFile(callback: (arg0: Error | undefined, arg1?: string | undefined | null) => void): void

View File

@ -3,6 +3,7 @@
#![allow(clippy::disallowed_names)]
#![allow(clippy::uninlined_format_args)]
#![allow(clippy::new_without_default)]
#![allow(non_snake_case)]
#![allow(deprecated)]
#[cfg(not(target_family = "wasm"))]

View File

@ -46,3 +46,52 @@ pub type ExternalLinterLoadPluginCb =
#[allow(unused_parens)]
pub type ExternalLinterLoadPluginCb2 =
Arc<ThreadsafeFunction<(String), PluginLoadResult, (String), Status, false>>;
// Test fixtures for format_js_property_name function
// These test that property names are correctly quoted/unquoted in TypeScript definitions
#[napi(object)]
pub struct PropertyNameUnicodeTest {
/// Unicode characters should NOT be quoted
#[napi(js_name = "café")]
pub cafe: String,
#[napi(js_name = "日本語")]
pub japanese: String,
#[napi(js_name = "Ελληνικά")]
pub greek: String,
}
#[napi(object)]
pub struct PropertyNameSpecialCharsTest {
/// Special characters should be quoted
#[napi(js_name = "kebab-case")]
pub kebab_case: String,
#[napi(js_name = "with space")]
pub with_space: String,
#[napi(js_name = "dot.notation")]
pub dot_notation: String,
#[napi(js_name = "xml:lang")]
pub xml_lang: String,
/// Dollar sign should be quoted for backward compatibility
#[napi(js_name = "$var")]
pub dollar_var: String,
}
#[napi(object)]
pub struct PropertyNameValidTest {
/// Valid identifiers should NOT be quoted
pub camelCase: String,
#[allow(non_snake_case)]
pub PascalCase: String,
pub _private: String,
pub with123numbers: String,
}
#[napi(object)]
pub struct PropertyNameDigitTest {
/// Property names starting with digits should be quoted
#[napi(js_name = "0invalid")]
pub zero_invalid: String,
#[napi(js_name = "123")]
pub one_two_three: String,
}