Skip to content

Commit

Permalink
fix(fast_check/dts): remove initializers in class methods/ctors (#521)
Browse files Browse the repository at this point in the history
  • Loading branch information
dsherret committed Aug 30, 2024
1 parent 61cfb50 commit 92eac49
Show file tree
Hide file tree
Showing 2 changed files with 226 additions and 60 deletions.
177 changes: 117 additions & 60 deletions src/fast_check/transform_dts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -504,66 +504,7 @@ impl<'a> FastCheckDtsTransformer<'a> {
fn_decl.function.body = None;
fn_decl.declare = is_declare;

for param in &mut fn_decl.function.params {
match &mut param.pat {
Pat::Ident(ident) => {
if ident.type_ann.is_none() {
self.mark_diagnostic_any_fallback(ident.range());
ident.type_ann = Some(any_type_ann());
}
}
Pat::Assign(assign_pat) => {
match &mut *assign_pat.left {
Pat::Ident(ident) => {
if ident.type_ann.is_none() {
ident.type_ann = self.infer_expr_fallback_any(
*assign_pat.right.clone(),
false,
false,
);
}

ident.optional = true;
param.pat = Pat::Ident(ident.clone());
}
Pat::Array(arr_pat) => {
if arr_pat.type_ann.is_none() {
arr_pat.type_ann = self.infer_expr_fallback_any(
*assign_pat.right.clone(),
false,
false,
);
}

arr_pat.optional = true;
param.pat = Pat::Array(arr_pat.clone());
}
Pat::Object(obj_pat) => {
if obj_pat.type_ann.is_none() {
obj_pat.type_ann = self.infer_expr_fallback_any(
*assign_pat.right.clone(),
false,
false,
);
}

obj_pat.optional = true;
param.pat = Pat::Object(obj_pat.clone());
}
Pat::Rest(_)
| Pat::Assign(_)
| Pat::Expr(_)
| Pat::Invalid(_) => {}
};
}
Pat::Array(_)
| Pat::Rest(_)
| Pat::Object(_)
| Pat::Invalid(_)
| Pat::Expr(_) => {}
}
}

self.handle_func_params(&mut fn_decl.function.params);
Some(Decl::Fn(fn_decl))
}
Decl::Var(mut var_decl) => {
Expand Down Expand Up @@ -830,13 +771,15 @@ impl<'a> FastCheckDtsTransformer<'a> {
.filter_map(|member| match member {
ClassMember::Constructor(mut class_constructor) => {
class_constructor.body = None;
self.handle_ts_param_props(&mut class_constructor.params);
Some(ClassMember::Constructor(class_constructor))
}
ClassMember::Method(mut method) => {
method.function.body = None;
if method.kind == MethodKind::Setter {
method.function.return_type = None;
}
self.handle_func_params(&mut method.function.params);
Some(ClassMember::Method(method))
}
ClassMember::ClassProp(mut prop) => {
Expand Down Expand Up @@ -868,6 +811,120 @@ impl<'a> FastCheckDtsTransformer<'a> {
.collect()
}

fn handle_ts_param_props(
&mut self,
param_props: &mut Vec<ParamOrTsParamProp>,
) {
for param in param_props {
match param {
ParamOrTsParamProp::TsParamProp(param) => {
match &mut param.param {
TsParamPropParam::Ident(ident) => {
self.handle_func_param_ident(ident);
}
TsParamPropParam::Assign(assign) => {
if let Some(new_pat) = self.handle_func_param_assign(assign) {
match new_pat {
Pat::Ident(new_ident) => {
param.param = TsParamPropParam::Ident(new_ident)
}
Pat::Assign(new_assign) => {
param.param = TsParamPropParam::Assign(new_assign)
}
Pat::Rest(_)
| Pat::Object(_)
| Pat::Array(_)
| Pat::Invalid(_)
| Pat::Expr(_) => {
// should never happen for parameter properties
unreachable!();
}
}
}
}
}
}
ParamOrTsParamProp::Param(param) => self.handle_func_param(param),
}
}
}

fn handle_func_params(&mut self, params: &mut Vec<Param>) {
for param in params {
self.handle_func_param(param);
}
}

fn handle_func_param(&mut self, param: &mut Param) {
match &mut param.pat {
Pat::Ident(ident) => {
self.handle_func_param_ident(ident);
}
Pat::Assign(assign_pat) => {
if let Some(new_pat) = self.handle_func_param_assign(assign_pat) {
param.pat = new_pat;
}
}
Pat::Array(_)
| Pat::Rest(_)
| Pat::Object(_)
| Pat::Invalid(_)
| Pat::Expr(_) => {}
}
}

fn handle_func_param_ident(&mut self, ident: &mut BindingIdent) {
if ident.type_ann.is_none() {
self.mark_diagnostic_any_fallback(ident.range());
ident.type_ann = Some(any_type_ann());
}
}

fn handle_func_param_assign(
&mut self,
assign_pat: &mut AssignPat,
) -> Option<Pat> {
match &mut *assign_pat.left {
Pat::Ident(ident) => {
if ident.type_ann.is_none() {
ident.type_ann = self.infer_expr_fallback_any(
*assign_pat.right.clone(),
false,
false,
);
}

ident.optional = true;
Some(Pat::Ident(ident.clone()))
}
Pat::Array(arr_pat) => {
if arr_pat.type_ann.is_none() {
arr_pat.type_ann = self.infer_expr_fallback_any(
*assign_pat.right.clone(),
false,
false,
);
}

arr_pat.optional = true;
Some(Pat::Array(arr_pat.clone()))
}
Pat::Object(obj_pat) => {
if obj_pat.type_ann.is_none() {
obj_pat.type_ann = self.infer_expr_fallback_any(
*assign_pat.right.clone(),
false,
false,
);
}

obj_pat.optional = true;
Some(Pat::Object(obj_pat.clone()))
}
Pat::Rest(_) | Pat::Assign(_) | Pat::Expr(_) | Pat::Invalid(_) => None,
}
}

fn pat_to_ts_fn_param(&mut self, pat: Pat) -> Option<TsFnParam> {
match pat {
Pat::Ident(binding_id) => Some(TsFnParam::Ident(binding_id)),
Expand Down
109 changes: 109 additions & 0 deletions tests/specs/graph/fast_check/class_params_initializers.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
# 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 Object {
constructor(
values: {},
{
a,
b,
}: {
a?: A;
b?: B;
} = {},
) {
}

method(
values: {},
{
a,
b,
}: {
a?: A;
b?: B;
} = {},
value = 1,
) {
}
}

# 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": 259,
"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 Object {
constructor(values: {
}, {}: {
a?: A;
b?: B;
} = {} as never){}
method(values: {
}, {}: {
a?: A;
b?: B;
} = {} as never, value?: number): void {}
}
--- DTS ---
export declare class Object {
constructor(values: {
}, {}?: {
a?: A;
b?: B;
});
method(values: {
}, {}?: {
a?: A;
b?: B;
}, value?: number): void;
}

0 comments on commit 92eac49

Please sign in to comment.