fix(ast/estree): fix Function.this_param (#9913)

`Function.this_param` is included in `Function.params` as an `Identifier` with `name: "this"`

https://ast-explorer.dev/#eNolykEKwzAMRNGrmFm10F7AB+lKG2MU6uAoJlICwfjuUchiNu9PR0XEnI6keSvN8EFzsLPxA1/WWuT27D7tkq2sEqaX/YvG0Mfb53X12klCIHBe0o839R8hOtRkrEYgGRgXircmAw==
This commit is contained in:
hi-ogawa committed 2025-03-21 07:25:42 +00:00
1 parent 5631ebd2ec
commit 8228b74af2
9 files changed
+88 -530

No files matched your search

+3 -1
View File
@@ -1658,7 +1658,7 @@ pub struct BindingRestElement<'a> {
add_fields(expression = False),
field_order(
r#type, span, id, expression, generator, r#async, params, body,
declare, type_parameters, this_param, return_type,
declare, type_parameters, return_type,
),
)]
pub struct Function<'a> {
@@ -1695,10 +1695,12 @@ pub struct Function<'a> {
/// });
/// ```
#[ts]
#[estree(skip)]
pub this_param: Option<Box<'a, TSThisParameter<'a>>>,
/// Function parameters.
///
/// Does not include `this` parameters used by some TypeScript functions.
#[estree(via = FunctionFormalParameters)]
pub params: Box<'a, FormalParameters<'a>>,
/// The TypeScript return type annotation.
#[ts]
+4
View File
@@ -31,6 +31,10 @@ use super::{inherit_variants, js::*, literal::*};
#[ast(visit)]
#[derive(Debug)]
#[generate_derive(CloneIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
#[estree(
rename = "Identifier",
add_fields(decorators = TsEmptyArray, optional = TsFalse, name = This)
)]
pub struct TSThisParameter<'a> {
pub span: Span,
#[estree(skip)]
@@ -1345,11 +1345,10 @@ impl ESTree for Function<'_> {
state.serialize_field("expression", &crate::serialize::False(self));
state.serialize_field("generator", &self.generator);
state.serialize_field("async", &self.r#async);
state.serialize_field("params", &self.params);
state.serialize_field("params", &crate::serialize::FunctionFormalParameters(self));
state.serialize_field("body", &self.body);
state.serialize_ts_field("declare", &self.declare);
state.serialize_ts_field("typeParameters", &self.type_parameters);
state.serialize_ts_field("thisParam", &self.this_param);
state.serialize_ts_field("returnType", &self.return_type);
state.end();
}
@@ -2278,10 +2277,13 @@ impl ESTree for JSXText<'_> {
impl ESTree for TSThisParameter<'_> {
fn serialize<S: Serializer>(&self, serializer: S) {
let mut state = serializer.serialize_struct();
state.serialize_field("type", &JsonSafeString("TSThisParameter"));
state.serialize_field("type", &JsonSafeString("Identifier"));
state.serialize_field("start", &self.span.start);
state.serialize_field("end", &self.span.end);
state.serialize_field("typeAnnotation", &self.type_annotation);
state.serialize_field("name", &crate::serialize::This(self));
state.serialize_ts_field("decorators", &crate::serialize::TsEmptyArray(self));
state.serialize_ts_field("optional", &crate::serialize::TsFalse(self));
state.end();
}
}
+47
View File
@@ -150,6 +150,17 @@ impl<T> ESTree for Init<'_, T> {
}
}
/// Serialized as `"this"`.
#[ast_meta]
#[estree(ts_type = "'this'", raw_deser = "'this'")]
pub struct This<'b, T>(#[expect(dead_code)] pub &'b T);
impl<T> ESTree for This<'_, T> {
fn serialize<S: Serializer>(&self, serializer: S) {
JsonSafeString("this").serialize(serializer);
}
}
#[ast_meta]
#[estree(ts_type = "[]", raw_deser = "[]")]
#[ts]
@@ -642,6 +653,42 @@ impl ESTree for ExpressionStatementDirective<'_, '_> {
}
}
#[ast_meta]
#[estree(
ts_type = "ParamPattern[]",
raw_deser = "
const params = DESER[Box<FormalParameters>](POS_OFFSET.params);
/* IF_TS */
const thisParam = DESER[Option<Box<TSThisParameter>>](POS_OFFSET.this_param)
if (thisParam !== null) {
params.unshift(thisParam);
}
/* END_IF_TS */
params
"
)]
pub struct FunctionFormalParameters<'a, 'b>(pub &'b Function<'a>);
impl ESTree for FunctionFormalParameters<'_, '_> {
fn serialize<S: Serializer>(&self, serializer: S) {
let mut seq = serializer.serialize_sequence();
if let Some(this_param) = &self.0.this_param {
seq.serialize_ts_element(this_param);
}
for item in &self.0.params.items {
seq.serialize_element(item);
}
if let Some(rest) = &self.0.params.rest {
seq.serialize_element(&FormalParametersRest(rest));
}
seq.end();
}
}
// --------------------
// Comments
// --------------------
@@ -4,6 +4,7 @@ use super::{Config, ESTree, ESTreeSerializer, Formatter, Serializer, SerializerP
pub trait SequenceSerializer {
/// Serialize sequence entry.
fn serialize_element<T: ESTree + ?Sized>(&mut self, value: &T);
fn serialize_ts_element<T: ESTree + ?Sized>(&mut self, value: &T);
/// Finish serializing sequence.
fn end(self);
@@ -43,6 +44,12 @@ impl<C: Config, F: Formatter> SequenceSerializer for ESTreeSequenceSerializer<'_
value.serialize(&mut *self.serializer);
}
fn serialize_ts_element<T: ESTree + ?Sized>(&mut self, value: &T) {
if C::INCLUDE_TS_FIELDS {
self.serialize_element(value);
}
}
/// Finish serializing sequence.
fn end(mut self) {
let (buffer, formatter) = self.serializer.buffer_and_formatter_mut();
+4 -2
View File
@@ -749,6 +749,7 @@ function deserializeBindingRestElement(pos) {
}
function deserializeFunction(pos) {
const params = deserializeBoxFormalParameters(pos + 72);
return {
type: deserializeFunctionType(pos + 8),
start: deserializeU32(pos),
@@ -757,7 +758,7 @@ function deserializeFunction(pos) {
expression: false,
generator: deserializeBool(pos + 48),
async: deserializeBool(pos + 49),
params: deserializeBoxFormalParameters(pos + 72),
params,
body: deserializeOptionBoxFunctionBody(pos + 88),
};
}
@@ -1262,10 +1263,11 @@ function deserializeJSXText(pos) {
function deserializeTSThisParameter(pos) {
return {
type: 'TSThisParameter',
type: 'Identifier',
start: deserializeU32(pos),
end: deserializeU32(pos + 4),
typeAnnotation: deserializeOptionBoxTSTypeAnnotation(pos + 16),
name: 'this',
};
}
+10 -3
View File
@@ -768,6 +768,11 @@ function deserializeBindingRestElement(pos) {
}
function deserializeFunction(pos) {
const params = deserializeBoxFormalParameters(pos + 72);
const thisParam = deserializeOptionBoxTSThisParameter(pos + 64);
if (thisParam !== null) {
params.unshift(thisParam);
}
return {
type: deserializeFunctionType(pos + 8),
start: deserializeU32(pos),
@@ -776,11 +781,10 @@ function deserializeFunction(pos) {
expression: false,
generator: deserializeBool(pos + 48),
async: deserializeBool(pos + 49),
params: deserializeBoxFormalParameters(pos + 72),
params,
body: deserializeOptionBoxFunctionBody(pos + 88),
declare: deserializeBool(pos + 50),
typeParameters: deserializeOptionBoxTSTypeParameterDeclaration(pos + 56),
thisParam: deserializeOptionBoxTSThisParameter(pos + 64),
returnType: deserializeOptionBoxTSTypeAnnotation(pos + 80),
};
}
@@ -1326,10 +1330,13 @@ function deserializeJSXText(pos) {
function deserializeTSThisParameter(pos) {
return {
type: 'TSThisParameter',
type: 'Identifier',
start: deserializeU32(pos),
end: deserializeU32(pos + 4),
typeAnnotation: deserializeOptionBoxTSTypeAnnotation(pos + 16),
name: 'this',
decorators: [],
optional: false,
};
}
+4 -2
View File
@@ -553,7 +553,6 @@ export interface Function extends Span {
body: FunctionBody | null;
declare?: boolean;
typeParameters?: TSTypeParameterDeclaration | null;
thisParam?: TSThisParameter | null;
returnType?: TSTypeAnnotation | null;
}
@@ -918,8 +917,11 @@ export interface JSXText extends Span {
}
export interface TSThisParameter extends Span {
type: 'TSThisParameter';
type: 'Identifier';
typeAnnotation: TSTypeAnnotation | null;
name: 'this';
decorators?: [];
optional?: false;
}
export interface TSEnumDeclaration extends Span {
File diff suppressed because it is too large. Load diff