fix(estree): include decorators in FormalParameterRest spans (#26021)

Serialize `FormalParameterRest` with its outer span so its range includes parameter decorators. Regenerate the raw-transfer deserializers and remove `sourceMapValidationDecorators.ts` from the ESTree mismatch baseline.

Fixes #26011.
This commit is contained in:
camc314 committed 2026-08-23 18:32:30 +00:00
1 parent 70c3e35356
commit 8a9bdbd6d8
9 files changed
+54 -42

No files matched your search

+5 -5
View File
@@ -2389,12 +2389,12 @@ function deserializeFormalParameters(pos) {
});
rest.argument = deserializeBindingPattern(pos + 56);
rest.decorators = deserializeVecDecorator(pos + 16);
rest.decorators.length !== 0 && (start = rest.decorators[0].start);
rest.typeAnnotation = deserializeOptionBoxTSTypeAnnotation(pos + 72);
if (rest.typeAnnotation !== null) {
end = rest.typeAnnotation.end;
rest.end = end;
rest.range[1] = end;
}
rest.typeAnnotation !== null && (end = rest.typeAnnotation.end);
rest.start = start;
rest.end = end;
rest.range = [start, end];
params.push(rest);
parent = previousParent;
}
+11 -10
View File
@@ -281,6 +281,7 @@ impl ESTree for BindingPatternKindAndTsFields<'_, '_> {
raw_deser = "
const pattern = DESER[BindingPattern](POS_OFFSET.id);
if (IS_TS) {
let start, end;
const previousParent = parent;
if (PARENT) parent = pattern;
const typeAnnotation = DESER[Option<Box<TSTypeAnnotation>>](POS_OFFSET.type_annotation);
@@ -361,9 +362,9 @@ impl ESTree for CatchParameterConverter<'_, '_> {
if (int32[restFieldPos32] !== 0 && int32[restFieldPos32 + 1] !== 0) {
pos = int32[restFieldPos32];
let start, end;
const previousParent = parent;
const rest = parent = {
let start, end,
previousParent = parent,
rest = parent = {
type: 'RestElement',
...(IS_TS && { decorators: [] }),
argument: null,
@@ -380,14 +381,18 @@ impl ESTree for CatchParameterConverter<'_, '_> {
rest.argument = DESER[BindingPattern]( POS_OFFSET<FormalParameterRest>.rest.argument );
if (IS_TS) {
rest.decorators = DESER[Vec<Decorator>](POS_OFFSET<FormalParameterRest>.decorators);
if (rest.decorators.length !== 0) {
start = rest.decorators[0].start;
}
rest.typeAnnotation = DESER[Option<Box<TSTypeAnnotation>>](
POS_OFFSET<FormalParameterRest>.type_annotation
);
if (rest.typeAnnotation !== null) {
end = rest.typeAnnotation.end;
rest.end = end;
if (RANGE) rest.range[1] = end;
}
rest.start = start;
rest.end = end;
if (RANGE) rest.range = [start, end];
}
params.push(rest);
if (PARENT) parent = previousParent;
@@ -424,11 +429,7 @@ impl ESTree for FormalParameterRest<'_> {
state.serialize_ts_field("optional", &false);
state.serialize_ts_field("typeAnnotation", &rest.type_annotation);
state.serialize_ts_field("value", &Null(()));
state.serialize_span(
rest.type_annotation
.as_ref()
.map_or(rest.rest.span, |ta| rest.rest.span.merge(ta.span)),
);
state.serialize_span(rest.span);
state.end();
}
}
@@ -18,7 +18,16 @@ impl Utf8ToUtf16Converter<'_> {
// Span of `FormalParameters` itself does not appear in ESTree AST,
// and its span includes `TSThisParameter` in types like `Function`,
// which is converted before `FormalParameters`. So skip converting span.
walk_mut::walk_formal_parameters(self, params);
self.visit_formal_parameter_list(&mut params.items);
if let Some(rest) = &mut params.rest {
self.convert_offset(&mut rest.span.start);
self.visit_decorators(&mut rest.decorators);
self.visit_binding_rest_element(&mut rest.rest);
if let Some(type_annotation) = &mut rest.type_annotation {
self.visit_ts_type_annotation(type_annotation);
}
self.convert_offset(&mut rest.span.end);
}
}
pub(crate) fn convert_object_property(&mut self, prop: &mut ObjectProperty<'_>) {
+3 -1
View File
@@ -880,7 +880,9 @@ impl Gen for FormalParameterRest<'_> {
fn r#gen(&self, p: &mut Codegen, ctx: Context) {
p.add_source_mapping(self.span);
p.print_decorators(&self.decorators, ctx);
self.rest.print(p, ctx);
p.add_source_mapping(self.span);
p.print_ellipsis();
self.rest.argument.print(p, ctx);
if let Some(type_annotation) = &self.type_annotation {
p.print_colon();
p.print_soft_space();
@@ -1905,7 +1905,8 @@ function deserializeFormalParameters(pos) {
restFieldPos32 = (pos >> 2) + 10;
if (int32[restFieldPos32] !== 0 && int32[restFieldPos32 + 1] !== 0) {
pos = int32[restFieldPos32];
let end,
let start,
end,
rest = {
type: "RestElement",
decorators: [],
@@ -1913,16 +1914,16 @@ function deserializeFormalParameters(pos) {
optional: false,
typeAnnotation: null,
value: null,
start: deserializeI32(pos + 40),
start: (start = deserializeI32(pos + 40)),
end: (end = deserializeI32(pos + 44)),
};
rest.argument = deserializeBindingPattern(pos + 56);
rest.decorators = deserializeVecDecorator(pos + 16);
rest.decorators.length !== 0 && (start = rest.decorators[0].start);
rest.typeAnnotation = deserializeOptionBoxTSTypeAnnotation(pos + 72);
if (rest.typeAnnotation !== null) {
end = rest.typeAnnotation.end;
rest.end = end;
}
rest.typeAnnotation !== null && (end = rest.typeAnnotation.end);
rest.start = start;
rest.end = end;
params.push(rest);
}
return params;
@@ -2107,7 +2107,8 @@ function deserializeFormalParameters(pos) {
restFieldPos32 = (pos >> 2) + 10;
if (int32[restFieldPos32] !== 0 && int32[restFieldPos32 + 1] !== 0) {
pos = int32[restFieldPos32];
let end,
let start,
end,
previousParent = parent,
rest = (parent = {
type: "RestElement",
@@ -2116,17 +2117,17 @@ function deserializeFormalParameters(pos) {
optional: false,
typeAnnotation: null,
value: null,
start: deserializeI32(pos + 40),
start: (start = deserializeI32(pos + 40)),
end: (end = deserializeI32(pos + 44)),
parent: previousParent,
});
rest.argument = deserializeBindingPattern(pos + 56);
rest.decorators = deserializeVecDecorator(pos + 16);
rest.decorators.length !== 0 && (start = rest.decorators[0].start);
rest.typeAnnotation = deserializeOptionBoxTSTypeAnnotation(pos + 72);
if (rest.typeAnnotation !== null) {
end = rest.typeAnnotation.end;
rest.end = end;
}
rest.typeAnnotation !== null && (end = rest.typeAnnotation.end);
rest.start = start;
rest.end = end;
params.push(rest);
parent = previousParent;
}
@@ -2125,12 +2125,12 @@ function deserializeFormalParameters(pos) {
};
rest.argument = deserializeBindingPattern(pos + 56);
rest.decorators = deserializeVecDecorator(pos + 16);
rest.decorators.length !== 0 && (start = rest.decorators[0].start);
rest.typeAnnotation = deserializeOptionBoxTSTypeAnnotation(pos + 72);
if (rest.typeAnnotation !== null) {
end = rest.typeAnnotation.end;
rest.end = end;
rest.range[1] = end;
}
rest.typeAnnotation !== null && (end = rest.typeAnnotation.end);
rest.start = start;
rest.end = end;
rest.range = [start, end];
params.push(rest);
}
return params;
@@ -2328,12 +2328,12 @@ function deserializeFormalParameters(pos) {
});
rest.argument = deserializeBindingPattern(pos + 56);
rest.decorators = deserializeVecDecorator(pos + 16);
rest.decorators.length !== 0 && (start = rest.decorators[0].start);
rest.typeAnnotation = deserializeOptionBoxTSTypeAnnotation(pos + 72);
if (rest.typeAnnotation !== null) {
end = rest.typeAnnotation.end;
rest.end = end;
rest.range[1] = end;
}
rest.typeAnnotation !== null && (end = rest.typeAnnotation.end);
rest.start = start;
rest.end = end;
rest.range = [start, end];
params.push(rest);
parent = previousParent;
}
@@ -2,15 +2,13 @@ commit: b465fdbf
estree_typescript Summary:
AST Parsed : 9723/9723 (100.00%)
Positive Passed: 9706/9723 (99.83%)
Positive Passed: 9707/9723 (99.84%)
Mismatch: tasks/coverage/typescript/tests/cases/compiler/moduleDetectionIsolatedModulesCjsFileScope.ts
Mismatch: tasks/coverage/typescript/tests/cases/compiler/moduleNodeImportRequireEmit.ts
Mismatch: tasks/coverage/typescript/tests/cases/compiler/sideEffectImports2.ts
Mismatch: tasks/coverage/typescript/tests/cases/compiler/sourceMapValidationDecorators.ts
Mismatch: tasks/coverage/typescript/tests/cases/compiler/tripleSlashTypesReferenceWithMissingExports.ts
Mismatch: tasks/coverage/typescript/tests/cases/conformance/externalModules/moduleResolutionWithoutExtension7.ts