From 35f740fd6bb29be428c30783aa911891836217a8 Mon Sep 17 00:00:00 2001 From: David Sherret Date: Thu, 29 Aug 2024 15:59:24 -0400 Subject: [PATCH 1/2] fix(fast_check/dts): better handling of computed properties --- src/fast_check/transform_dts.rs | 78 +++++++++++++++++++ .../fast_check/class_properties_computed.txt | 77 ++++++++++++++++++ 2 files changed, 155 insertions(+) create mode 100644 tests/specs/graph/fast_check/class_properties_computed.txt diff --git a/src/fast_check/transform_dts.rs b/src/fast_check/transform_dts.rs index 6018abbe..a649a091 100644 --- a/src/fast_check/transform_dts.rs +++ b/src/fast_check/transform_dts.rs @@ -833,6 +833,12 @@ impl<'a> FastCheckDtsTransformer<'a> { Some(ClassMember::Constructor(class_constructor)) } ClassMember::Method(mut method) => { + if let Some(new_prop_name) = valid_prop_name(&method.key) { + method.key = new_prop_name; + } else { + return None; + } + method.function.body = None; if method.kind == MethodKind::Setter { method.function.return_type = None; @@ -840,6 +846,11 @@ impl<'a> FastCheckDtsTransformer<'a> { Some(ClassMember::Method(method)) } ClassMember::ClassProp(mut prop) => { + if let Some(new_prop_name) = valid_prop_name(&prop.key) { + prop.key = new_prop_name; + } else { + return None; + } if prop.type_ann.is_none() { if let Some(value) = prop.value { prop.type_ann = self @@ -899,6 +910,73 @@ impl<'a> FastCheckDtsTransformer<'a> { } } +fn valid_prop_name(prop_name: &PropName) -> Option { + fn prop_name_from_expr(expr: &Expr) -> Option { + match expr { + Expr::Lit(e) => match &e { + Lit::Str(e) => Some(PropName::Str(e.clone())), + Lit::Num(e) => Some(PropName::Num(e.clone())), + Lit::BigInt(e) => Some(PropName::BigInt(e.clone())), + Lit::Bool(_) | Lit::Null(_) | Lit::Regex(_) | Lit::JSXText(_) => None, + }, + Expr::Tpl(e) => { + if e.quasis.is_empty() && e.exprs.len() == 1 { + prop_name_from_expr(&e.exprs[0]) + } else { + None + } + } + Expr::Paren(e) => prop_name_from_expr(&e.expr), + Expr::TsTypeAssertion(e) => prop_name_from_expr(&e.expr), + Expr::TsConstAssertion(e) => prop_name_from_expr(&e.expr), + Expr::TsNonNull(e) => prop_name_from_expr(&e.expr), + Expr::TsAs(e) => prop_name_from_expr(&e.expr), + Expr::TsSatisfies(e) => prop_name_from_expr(&e.expr), + Expr::Ident(_) => Some(PropName::Computed(ComputedPropName { + span: deno_ast::swc::common::Spanned::span(&expr), + expr: Box::new(expr.clone()), + })), + Expr::TaggedTpl(_) + | Expr::This(_) + | Expr::Array(_) + | Expr::Object(_) + | Expr::Fn(_) + | Expr::Unary(_) + | Expr::Update(_) + | Expr::Bin(_) + | Expr::Assign(_) + | Expr::Member(_) + | Expr::SuperProp(_) + | Expr::Cond(_) + | Expr::Call(_) + | Expr::New(_) + | Expr::Seq(_) + | Expr::Arrow(_) + | Expr::Class(_) + | Expr::Yield(_) + | Expr::Await(_) + | Expr::MetaProp(_) + | Expr::JSXMember(_) + | Expr::JSXNamespacedName(_) + | Expr::JSXEmpty(_) + | Expr::JSXElement(_) + | Expr::JSXFragment(_) + | Expr::TsInstantiation(_) + | Expr::PrivateName(_) + | Expr::OptChain(_) + | Expr::Invalid(_) => None, + } + } + + match prop_name { + PropName::Ident(_) + | PropName::Str(_) + | PropName::Num(_) + | PropName::BigInt(_) => Some(prop_name.clone()), + PropName::Computed(computed) => prop_name_from_expr(&*computed.expr), + } +} + #[cfg(test)] mod tests { use std::collections::VecDeque; diff --git a/tests/specs/graph/fast_check/class_properties_computed.txt b/tests/specs/graph/fast_check/class_properties_computed.txt new file mode 100644 index 00000000..573a3554 --- /dev/null +++ b/tests/specs/graph/fast_check/class_properties_computed.txt @@ -0,0 +1,77 @@ +# https://jsr.io/@scope/a/meta.json +{"versions": { "1.0.0": {} } } + +# https://jsr.io/@scope/a/1.0.0_meta.json +{ "exports": { ".": "./mod.ts" } } + +# https://jsr.io/@scope/a/1.0.0/mod.ts +export class Test { + [Symbol.for("nodejs.util.inspect.custom")]() { + } + ["string"]: string; + ["string2" as string]: string; + [1 as number]: string; +} + +# mod.ts +import 'jsr:@scope/a' + +# output +{ + "roots": [ + "file:///mod.ts" + ], + "modules": [ + { + "kind": "esm", + "dependencies": [ + { + "specifier": "jsr:@scope/a", + "code": { + "specifier": "jsr:@scope/a", + "span": { + "start": { + "line": 0, + "character": 7 + }, + "end": { + "line": 0, + "character": 21 + } + } + } + } + ], + "size": 22, + "mediaType": "TypeScript", + "specifier": "file:///mod.ts" + }, + { + "kind": "esm", + "size": 155, + "mediaType": "TypeScript", + "specifier": "https://jsr.io/@scope/a/1.0.0/mod.ts" + } + ], + "redirects": { + "jsr:@scope/a": "https://jsr.io/@scope/a/1.0.0/mod.ts" + }, + "packages": { + "@scope/a@*": "@scope/a@1.0.0" + } +} + +Fast check https://jsr.io/@scope/a/1.0.0/mod.ts: + {} + export class Test { + [Symbol.for("nodejs.util.inspect.custom")](): void {} + declare ["string"]: string; + declare ["string2" as string]: string; + declare [1 as number]: string; + } + --- DTS --- + export declare class Test { + "string": string; + "string2": string; + 1: string; + } From 928e0027f8a760da41b1541777d55957d594db2a Mon Sep 17 00:00:00 2001 From: David Sherret Date: Thu, 29 Aug 2024 16:02:29 -0400 Subject: [PATCH 2/2] Update --- src/fast_check/transform_dts.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/fast_check/transform_dts.rs b/src/fast_check/transform_dts.rs index a649a091..ebab002b 100644 --- a/src/fast_check/transform_dts.rs +++ b/src/fast_check/transform_dts.rs @@ -933,6 +933,7 @@ fn valid_prop_name(prop_name: &PropName) -> Option { Expr::TsAs(e) => prop_name_from_expr(&e.expr), Expr::TsSatisfies(e) => prop_name_from_expr(&e.expr), Expr::Ident(_) => Some(PropName::Computed(ComputedPropName { + #[allow(clippy::disallowed_methods)] span: deno_ast::swc::common::Spanned::span(&expr), expr: Box::new(expr.clone()), })), @@ -973,7 +974,7 @@ fn valid_prop_name(prop_name: &PropName) -> Option { | PropName::Str(_) | PropName::Num(_) | PropName::BigInt(_) => Some(prop_name.clone()), - PropName::Computed(computed) => prop_name_from_expr(&*computed.expr), + PropName::Computed(computed) => prop_name_from_expr(&computed.expr), } }