From 032861c5bcbf563d98814ad0223a5b4b851361ac Mon Sep 17 00:00:00 2001 From: forehalo Date: Fri, 24 Sep 2021 09:15:48 +0800 Subject: [PATCH] support typegen for Result --- crates/backend/src/typegen.rs | 29 ++++++++++++++++---- examples/napi/__test__/typegen.spec.ts.md | 1 + examples/napi/__test__/typegen.spec.ts.snap | Bin 549 -> 578 bytes examples/napi/__test__/values.spec.ts | 6 ++++ examples/napi/index.d.ts | 1 + examples/napi/src/callback.rs | 15 ++++++++++ 6 files changed, 46 insertions(+), 6 deletions(-) diff --git a/crates/backend/src/typegen.rs b/crates/backend/src/typegen.rs index 350fb9c9..81f9fdf0 100644 --- a/crates/backend/src/typegen.rs +++ b/crates/backend/src/typegen.rs @@ -2,6 +2,8 @@ mod r#enum; mod r#fn; mod r#struct; +use std::collections::HashMap; + use once_cell::sync::Lazy; use quote::ToTokens; use regex::Regex; @@ -27,8 +29,16 @@ pub trait ToTypeDef { fn to_type_def(&self) -> TypeDef; } -pub static VEC_REGEX: Lazy = Lazy::new(|| Regex::new(r"^Vec < (.*) >$").unwrap()); -pub static OPTION_REGEX: Lazy = Lazy::new(|| Regex::new(r"^Option < (.*) >").unwrap()); +pub static TYPE_REGEXES: Lazy> = Lazy::new(|| { + let mut map = HashMap::default(); + map.extend([ + ("Vec", Regex::new(r"^Vec < (.*) >$").unwrap()), + ("Option", Regex::new(r"^Option < (.*) >").unwrap()), + ("Result", Regex::new(r"^Result < (.*) >").unwrap()), + ]); + + map +}); pub fn ty_to_ts_type(ty: &Type) -> String { match ty { @@ -54,6 +64,7 @@ pub fn ty_to_ts_type(ty: &Type) -> String { pub fn str_to_ts_type(ty: &str) -> String { match ty { + "()" => "null".to_owned(), "i8" | "i16" | "i32" | "i64" | "u8" | "u16" | "u32" => "number".to_owned(), "i128" | "isize" | "u64" | "u128" | "usize" => "BigInt".to_owned(), "bool" => "boolean".to_owned(), @@ -61,18 +72,24 @@ pub fn str_to_ts_type(ty: &str) -> String { "Object" => "object".to_owned(), // nothing but `& 'lifetime str` could ends with ` str` s if s.ends_with(" str") => "string".to_owned(), - s if s.starts_with("Vec") && VEC_REGEX.is_match(s) => { - let captures = VEC_REGEX.captures(s).unwrap(); + s if s.starts_with("Vec") && TYPE_REGEXES["Vec"].is_match(s) => { + let captures = TYPE_REGEXES["Vec"].captures(s).unwrap(); let inner = captures.get(1).unwrap().as_str(); format!("Array<{}>", str_to_ts_type(inner)) } - s if s.starts_with("Option") && OPTION_REGEX.is_match(s) => { - let captures = OPTION_REGEX.captures(s).unwrap(); + s if s.starts_with("Option") && TYPE_REGEXES["Option"].is_match(s) => { + let captures = TYPE_REGEXES["Option"].captures(s).unwrap(); let inner = captures.get(1).unwrap().as_str(); format!("{} | undefined", str_to_ts_type(inner)) } + s if s.starts_with("Result") && TYPE_REGEXES["Result"].is_match(s) => { + let captures = TYPE_REGEXES["Result"].captures(s).unwrap(); + let inner = captures.get(1).unwrap().as_str(); + + format!("Error | {}", str_to_ts_type(inner)) + } s => s.to_owned(), } } diff --git a/examples/napi/__test__/typegen.spec.ts.md b/examples/napi/__test__/typegen.spec.ts.md index 24d4b7e7..b17746ee 100644 --- a/examples/napi/__test__/typegen.spec.ts.md +++ b/examples/napi/__test__/typegen.spec.ts.md @@ -12,6 +12,7 @@ Generated by [AVA](https://avajs.dev). export function getNums(): Array␊ export function sumNums(nums: Array): number␊ export function getCwd(callback: (arg0: string) => void): void␊ + export function readFile(callback: (arg0: Error | null, arg1: string | undefined) => void): void␊ export enum Kind { Dog = 0, Cat = 1, Duck = 2 }␊ export enum CustomNumEnum { One = 1, Two = 2, Three = 3, Four = 4, Six = 6, Eight = 8, Nine = 9, Ten = 10 }␊ export function enumToI32(e: CustomNumEnum): number␊ diff --git a/examples/napi/__test__/typegen.spec.ts.snap b/examples/napi/__test__/typegen.spec.ts.snap index 1251228628800e5ff37e7eb52d80fab3293027f6..81dd14dd3ad083fcb9deac1aa813bc5f96f453e1 100644 GIT binary patch literal 578 zcmV-I0=@k~RzVF00000000Ap zlRt0MKp4gyT7;C1iS->Xl82;)0v4@QrKyBkHA9LJ-)Dajllmt z?FPY4@Fdrb$HCJ_A9wl9R2v7wOfe_4f)RJ`wMi^#MR05koxicp2sJutZXqwSbPZHl z8go+xZIKZBlMEugP>!C%g_$5D(8_qF{HPIYEbJr7|ZZcrSA&=aGvPk0r=g~+|H(ZZE) z(q3gPAKr&v>bLuQgh!j<_2-?^X@BY!xu&wDHcn()vC@Vn385t!LR`xF;Gu}MqKpZm z9)_i`t{-2W@wp{BzKQ@ZoVf>QmEk-%j!r+Vg{R7B<)~1WSbPJFms1gf!y(~rIeHPq zT1!sVwhoNCfion{++fX6h#LN#8+Hx|ei^wKl%BO!jq#j1p*r4KsKNF)CaJY>tVBvB zESivi8(PUZOmL2)e44SUXu5o6Tw(<3j5%${iVHWe7IM~MHUq_H^;q;T9r4*%(^Qbv QChwYm0qH@R*0BTt0E+Pxc>n+a literal 549 zcmV+=0^0pSRzVznxFQSHI)8sB%uDu2XNzna59@`}HlDvzTWY3}#-LpW1Tqk0iSEN)O7 zgm5adkxzIX!i6ZkZ_vV}AJScBEgsE>UaEKddxS^p;mxn3pp(JGD{@Wqnu5>ZWXgva zns&BrZj7O6N@z`nkkqm{cqkGjDPw}jhv8fpJ4mk1`OFZNTt$Ev&g_F#VwzLS(do-n zc{Uj(EfvxbgI|F0x(OjzEC#oWW<-!Em2)b$O<>fZ;xX+H3p8QC}W9)HMwi$ONEf&v=ON>D6m{poA nxo{2ZAZILQGmw1Rj79&_5uc6}Ed*H}^0xgKBi!tqPy_$~Gk*R9 diff --git a/examples/napi/__test__/values.spec.ts b/examples/napi/__test__/values.spec.ts index f2aed855..f87f1144 100644 --- a/examples/napi/__test__/values.spec.ts +++ b/examples/napi/__test__/values.spec.ts @@ -18,6 +18,7 @@ import { listObjKeys, createObj, mapOption, + readFile, } from '../' test('number', (t) => { @@ -78,6 +79,11 @@ test('callback', (t) => { null, 'Expect value to be Function, but received Undefined', ) + + readFile((err, content) => { + t.is(err, null) + t.is(content, 'hello world') + }) }) test('object', (t) => { diff --git a/examples/napi/index.d.ts b/examples/napi/index.d.ts index a869439a..7cdb1527 100644 --- a/examples/napi/index.d.ts +++ b/examples/napi/index.d.ts @@ -2,6 +2,7 @@ export function getWords(): Array export function getNums(): Array export function sumNums(nums: Array): number export function getCwd(callback: (arg0: string) => void): void +export function readFile(callback: (arg0: Error | null, arg1: string | undefined) => void): void export enum Kind { Dog = 0, Cat = 1, Duck = 2 } export enum CustomNumEnum { One = 1, Two = 2, Three = 3, Four = 4, Six = 6, Eight = 8, Nine = 9, Ten = 10 } export function enumToI32(e: CustomNumEnum): number diff --git a/examples/napi/src/callback.rs b/examples/napi/src/callback.rs index ceff82b4..2fe4c926 100644 --- a/examples/napi/src/callback.rs +++ b/examples/napi/src/callback.rs @@ -5,3 +5,18 @@ use std::env; fn get_cwd Result<()>>(callback: T) { callback(env::current_dir().unwrap().to_string_lossy().to_string()).unwrap(); } + +/// napi = { version = 2, features = ["serde-json"] } +#[napi] +fn read_file, Option) -> Result<()>>(callback: T) { + match read_file_content() { + Ok(s) => callback(Ok(()), Some(s)), + Err(e) => callback(Err(e), None), + } + .unwrap(); +} + +fn read_file_content() -> Result { + // serde_json::from_str(&s)?; + Ok("hello world".to_string()) +}