Skip to content

Commit a48b515

Browse files
authored
feat: support decorators before or after export (#5871)
* feat: support decorators before or after export * refactor convert_item_list * adjust code for better readability
1 parent 17824d9 commit a48b515

File tree

17 files changed

+306
-78
lines changed

17 files changed

+306
-78
lines changed

rust/parse_ast/src/ast_nodes/block_statement.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -21,20 +21,20 @@ impl AstConverter<'_> {
2121
let mut keep_checking_directives = check_directive;
2222
self.convert_item_list_with_state(
2323
&block_statement.stmts,
24-
&mut keep_checking_directives,
2524
end_position + BLOCK_STATEMENT_BODY_OFFSET,
25+
&mut keep_checking_directives,
2626
|ast_converter, statement, can_be_directive| {
2727
if *can_be_directive {
2828
if let Stmt::Expr(expression) = statement {
2929
if let Expr::Lit(Lit::Str(string)) = &*expression.expr {
3030
ast_converter.store_directive(expression, &string.value);
31-
return true;
31+
return (true, None);
3232
}
3333
}
3434
}
3535
*can_be_directive = false;
3636
ast_converter.convert_statement(statement);
37-
true
37+
(true, None)
3838
},
3939
);
4040
// end

rust/parse_ast/src/ast_nodes/class_declaration.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,16 @@ use crate::convert_ast::converter::ast_constants::TYPE_CLASS_DECLARATION;
44
use crate::convert_ast::converter::AstConverter;
55

66
impl AstConverter<'_> {
7-
pub(crate) fn store_class_declaration(&mut self, class_declaration: &ClassDecl) {
7+
pub(crate) fn store_class_declaration(
8+
&mut self,
9+
class_declaration: &ClassDecl,
10+
outside_class_span_decorators_insert_position: Option<u32>,
11+
) {
812
self.store_class_node(
913
&TYPE_CLASS_DECLARATION,
1014
Some(&class_declaration.ident),
1115
&class_declaration.class,
16+
outside_class_span_decorators_insert_position,
1217
);
1318
}
1419
}

rust/parse_ast/src/ast_nodes/class_expression.rs

+2
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,13 @@ impl AstConverter<'_> {
77
&mut self,
88
class_expression: &ClassExpr,
99
node_type: &[u8; 4],
10+
outside_class_span_decorators_insert_position: Option<u32>,
1011
) {
1112
self.store_class_node(
1213
node_type,
1314
class_expression.ident.as_ref(),
1415
&class_expression.class,
16+
outside_class_span_decorators_insert_position,
1517
);
1618
}
1719
}

rust/parse_ast/src/ast_nodes/export_default_declaration.rs

+40-2
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,37 @@ use crate::convert_ast::converter::ast_constants::{
55
EXPORT_DEFAULT_DECLARATION_DECLARATION_OFFSET, EXPORT_DEFAULT_DECLARATION_RESERVED_BYTES,
66
TYPE_CLASS_DECLARATION, TYPE_EXPORT_DEFAULT_DECLARATION, TYPE_FUNCTION_DECLARATION,
77
};
8-
use crate::convert_ast::converter::AstConverter;
8+
9+
use crate::convert_ast::converter::{get_outside_class_span_decorators_info, AstConverter};
910

1011
impl AstConverter<'_> {
1112
pub(crate) fn store_export_default_declaration(
1213
&mut self,
1314
span: &Span,
1415
expression: StoredDefaultExportExpression,
16+
module_item_insert_position: &mut u32,
1517
) {
18+
let (
19+
mut outside_class_span_decorators_insert_position,
20+
are_decorators_before_export,
21+
are_decorators_after_export,
22+
outside_class_span_decorators,
23+
) = get_outside_class_span_decorators_info(
24+
span,
25+
match expression {
26+
StoredDefaultExportExpression::Class(class_expression) => Some(&class_expression.class),
27+
_ => None,
28+
},
29+
);
30+
31+
if are_decorators_before_export {
32+
self.store_outside_class_span_decorators(
33+
outside_class_span_decorators,
34+
&mut outside_class_span_decorators_insert_position,
35+
);
36+
*module_item_insert_position = (self.buffer.len() as u32) >> 2;
37+
}
38+
1639
let end_position = self.add_type_and_start(
1740
&TYPE_EXPORT_DEFAULT_DECLARATION,
1841
span,
@@ -23,14 +46,25 @@ impl AstConverter<'_> {
2346
| StoredDefaultExportExpression::Function(_)
2447
),
2548
);
49+
50+
if are_decorators_after_export {
51+
self.store_outside_class_span_decorators(
52+
outside_class_span_decorators,
53+
&mut outside_class_span_decorators_insert_position,
54+
);
55+
}
2656
// declaration
2757
self.update_reference_position(end_position + EXPORT_DEFAULT_DECLARATION_DECLARATION_OFFSET);
2858
match expression {
2959
StoredDefaultExportExpression::Expression(expression) => {
3060
self.convert_expression(expression);
3161
}
3262
StoredDefaultExportExpression::Class(class_expression) => {
33-
self.store_class_expression(class_expression, &TYPE_CLASS_DECLARATION)
63+
self.store_class_expression(
64+
class_expression,
65+
&TYPE_CLASS_DECLARATION,
66+
outside_class_span_decorators_insert_position,
67+
);
3468
}
3569
StoredDefaultExportExpression::Function(function_expression) => self.convert_function(
3670
&function_expression.function,
@@ -45,6 +79,7 @@ impl AstConverter<'_> {
4579
pub(crate) fn convert_export_default_declaration(
4680
&mut self,
4781
export_default_declaration: &ExportDefaultDecl,
82+
module_item_insert_position: &mut u32,
4883
) {
4984
self.store_export_default_declaration(
5085
&export_default_declaration.span,
@@ -59,16 +94,19 @@ impl AstConverter<'_> {
5994
unimplemented!("Cannot convert ExportDefaultDeclaration with TsInterfaceDecl")
6095
}
6196
},
97+
module_item_insert_position,
6298
);
6399
}
64100

65101
pub(crate) fn convert_export_default_expression(
66102
&mut self,
67103
export_default_expression: &ExportDefaultExpr,
104+
module_item_insert_position: &mut u32,
68105
) {
69106
self.store_export_default_declaration(
70107
&export_default_expression.span,
71108
StoredDefaultExportExpression::Expression(&export_default_expression.expr),
109+
module_item_insert_position,
72110
);
73111
}
74112
}

rust/parse_ast/src/ast_nodes/export_named_declaration.rs

+41-3
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ use crate::convert_ast::converter::ast_constants::{
66
EXPORT_NAMED_DECLARATION_RESERVED_BYTES, EXPORT_NAMED_DECLARATION_SOURCE_OFFSET,
77
EXPORT_NAMED_DECLARATION_SPECIFIERS_OFFSET, TYPE_EXPORT_NAMED_DECLARATION,
88
};
9-
use crate::convert_ast::converter::AstConverter;
9+
10+
use crate::convert_ast::converter::{get_outside_class_span_decorators_info, AstConverter};
1011

1112
impl AstConverter<'_> {
1213
pub(crate) fn store_export_named_declaration(
@@ -16,7 +17,31 @@ impl AstConverter<'_> {
1617
src: Option<&Str>,
1718
declaration: Option<&Decl>,
1819
with: &Option<Box<ObjectLit>>,
20+
module_item_insert_position: Option<&mut u32>,
1921
) {
22+
let (
23+
mut outside_class_span_decorators_insert_position,
24+
are_decorators_before_export,
25+
are_decorators_after_export,
26+
outside_class_span_decorators,
27+
) = get_outside_class_span_decorators_info(
28+
span,
29+
match declaration {
30+
Some(Decl::Class(class_declaration)) => Some(&class_declaration.class),
31+
_ => None,
32+
},
33+
);
34+
35+
if are_decorators_before_export {
36+
self.store_outside_class_span_decorators(
37+
outside_class_span_decorators,
38+
&mut outside_class_span_decorators_insert_position,
39+
);
40+
if let Some(module_item_insert_position) = module_item_insert_position {
41+
*module_item_insert_position = (self.buffer.len() as u32) >> 2;
42+
}
43+
}
44+
2045
let end_position = self.add_type_and_start(
2146
&TYPE_EXPORT_NAMED_DECLARATION,
2247
span,
@@ -27,6 +52,14 @@ impl AstConverter<'_> {
2752
_ => false,
2853
},
2954
);
55+
56+
if are_decorators_after_export {
57+
self.store_outside_class_span_decorators(
58+
outside_class_span_decorators,
59+
&mut outside_class_span_decorators_insert_position,
60+
);
61+
}
62+
3063
// specifiers
3164
self.convert_item_list(
3265
specifiers,
@@ -39,7 +72,7 @@ impl AstConverter<'_> {
3972
// declaration
4073
if let Some(declaration) = declaration {
4174
self.update_reference_position(end_position + EXPORT_NAMED_DECLARATION_DECLARATION_OFFSET);
42-
self.convert_declaration(declaration);
75+
self.convert_declaration(declaration, outside_class_span_decorators_insert_position);
4376
}
4477
// source
4578
if let Some(src) = src {
@@ -55,13 +88,18 @@ impl AstConverter<'_> {
5588
self.add_end(end_position, span);
5689
}
5790

58-
pub(crate) fn convert_export_declaration(&mut self, export_declaration: &ExportDecl) {
91+
pub(crate) fn convert_export_declaration(
92+
&mut self,
93+
export_declaration: &ExportDecl,
94+
module_item_insert_position: &mut u32,
95+
) {
5996
self.store_export_named_declaration(
6097
&export_declaration.span,
6198
&[],
6299
None,
63100
Some(&export_declaration.decl),
64101
&None,
102+
Some(module_item_insert_position),
65103
);
66104
}
67105
}

rust/parse_ast/src/ast_nodes/jsx_opening_element.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,12 @@ impl AstConverter<'_> {
2929
let mut previous_element_end = jsx_opening_element.name.span().hi.0;
3030
self.convert_item_list_with_state(
3131
&jsx_opening_element.attrs,
32-
&mut previous_element_end,
3332
end_position + JSX_OPENING_ELEMENT_ATTRIBUTES_OFFSET,
33+
&mut previous_element_end,
3434
|ast_converter, jsx_attribute, previous_end| {
3535
ast_converter.convert_jsx_attribute_or_spread(jsx_attribute, *previous_end);
3636
*previous_end = jsx_attribute.span().hi.0;
37-
true
37+
(true, None)
3838
},
3939
);
4040
// end

rust/parse_ast/src/ast_nodes/program.rs

+11-9
Original file line numberDiff line numberDiff line change
@@ -15,40 +15,42 @@ impl AstConverter<'_> {
1515
ModuleItemsOrStatements::ModuleItems(module_items) => {
1616
self.convert_item_list_with_state(
1717
module_items,
18-
&mut keep_checking_directives,
1918
end_position + PROGRAM_BODY_OFFSET,
19+
&mut keep_checking_directives,
2020
|ast_converter, module_item, can_be_directive| {
2121
if *can_be_directive {
2222
if let ModuleItem::Stmt(Stmt::Expr(expression)) = module_item {
2323
if let Expr::Lit(Lit::Str(string)) = &*expression.expr {
2424
ast_converter.store_directive(expression, &string.value);
25-
return true;
25+
return (true, None);
2626
}
2727
};
28+
*can_be_directive = false;
2829
}
29-
*can_be_directive = false;
30-
ast_converter.convert_module_item(module_item);
31-
true
30+
31+
let mut module_item_insert_position = ast_converter.buffer.len() as u32 >> 2;
32+
ast_converter.convert_module_item(module_item, &mut module_item_insert_position);
33+
(true, Some(module_item_insert_position))
3234
},
3335
);
3436
}
3537
ModuleItemsOrStatements::Statements(statements) => {
3638
self.convert_item_list_with_state(
3739
statements,
38-
&mut keep_checking_directives,
3940
end_position + PROGRAM_BODY_OFFSET,
41+
&mut keep_checking_directives,
4042
|ast_converter, statement, can_be_directive| {
4143
if *can_be_directive {
4244
if let Stmt::Expr(expression) = statement {
4345
if let Expr::Lit(Lit::Str(string)) = &*expression.expr {
4446
ast_converter.store_directive(expression, &string.value);
45-
return true;
47+
return (true, None);
4648
}
4749
};
50+
*can_be_directive = false;
4851
}
49-
*can_be_directive = false;
5052
ast_converter.convert_statement(statement);
51-
true
53+
(true, None)
5254
},
5355
);
5456
}

rust/parse_ast/src/ast_nodes/shared/class_node.rs

+18-8
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ impl AstConverter<'_> {
1414
node_type: &[u8; 4],
1515
identifier: Option<&Ident>,
1616
class: &Class,
17+
outside_class_span_decorators_insert_position: Option<u32>,
1718
) {
1819
let end_position = self.add_type_and_start(
1920
node_type,
@@ -23,14 +24,23 @@ impl AstConverter<'_> {
2324
);
2425
let mut body_start_search = class.span.lo.0 - 1;
2526
// decorators
26-
self.convert_item_list(
27-
&class.decorators,
28-
end_position + CLASS_DECLARATION_DECORATORS_OFFSET,
29-
|ast_converter, decorator| {
30-
ast_converter.store_decorator(decorator);
31-
true
32-
},
33-
);
27+
if let Some(outside_class_span_decorators_insert_position) =
28+
outside_class_span_decorators_insert_position
29+
{
30+
self.buffer[end_position + CLASS_DECLARATION_DECORATORS_OFFSET
31+
..end_position + CLASS_DECLARATION_DECORATORS_OFFSET + 4]
32+
.copy_from_slice(&outside_class_span_decorators_insert_position.to_ne_bytes());
33+
} else {
34+
self.convert_item_list(
35+
&class.decorators,
36+
end_position + CLASS_DECLARATION_DECORATORS_OFFSET,
37+
|ast_converter, decorator| {
38+
ast_converter.store_decorator(decorator);
39+
true
40+
},
41+
);
42+
}
43+
3444
if !class.decorators.is_empty() {
3545
body_start_search = class.decorators.last().unwrap().span.hi.0 - 1;
3646
}

0 commit comments

Comments
 (0)