Skip to content
This repository has been archived by the owner on Aug 31, 2023. It is now read-only.

Commit

Permalink
feat(rome_js_parser): EcmaScript @decorators #4252
Browse files Browse the repository at this point in the history
  • Loading branch information
denbezrukov committed Apr 25, 2023
1 parent 9c8570c commit 6d509e7
Show file tree
Hide file tree
Showing 23 changed files with 246 additions and 410 deletions.
5 changes: 2 additions & 3 deletions crates/rome_js_parser/src/syntax/auxiliary.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::prelude::*;
use crate::syntax::class::{parse_class_declaration, parse_decorators};
use crate::syntax::function::parse_function_declaration;
use crate::syntax::js_parse_error::decorators_not_allowed;
use crate::syntax::module::parse_import_or_import_equals_declaration;
use crate::syntax::stmt::{
is_nth_at_variable_declarations, parse_variable_declaration, semi, StatementContext,
Expand Down Expand Up @@ -101,9 +102,7 @@ pub(crate) fn parse_declaration_clause(p: &mut JsParser, stmt_start_pos: TextSiz
// @decorator1 @decorator2
// export function Foo() { }
decorator_list
.add_diagnostic_if_present(p, |p, range| {
p.err_builder("Decorators are not valid here.", range)
})
.add_diagnostic_if_present(p, decorators_not_allowed)
.map(|mut marker| {
marker.change_kind(p, JS_BOGUS_STATEMENT);
marker
Expand Down
7 changes: 0 additions & 7 deletions crates/rome_js_parser/src/syntax/class.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2497,13 +2497,6 @@ fn parse_decorator(p: &mut JsParser) -> ParsedSyntax {
Present(m.complete(p, JS_DECORATOR))
}

// test ts ts_class_decorator
// function test() {}
// @test
// class Test {}
// @test.a?.c @test @test
// class Test2{}

/// Skips over any TypeScript decorator syntax.
pub(crate) fn skip_ts_decorators(p: &mut JsParser) {
if !p.at(T![@]) {
Expand Down
8 changes: 3 additions & 5 deletions crates/rome_js_parser/src/syntax/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use crate::syntax::function::{
is_at_async_function, parse_arrow_function_expression, parse_function_expression, LineBreak,
};
use crate::syntax::js_parse_error;
use crate::syntax::js_parse_error::expected_simple_assignment_target;
use crate::syntax::js_parse_error::{decorators_not_allowed, expected_simple_assignment_target};
use crate::syntax::js_parse_error::{
expected_expression, expected_identifier, invalid_assignment_error,
private_names_only_allowed_on_left_side_of_in_expression,
Expand Down Expand Up @@ -1292,12 +1292,10 @@ fn parse_primary_expression(p: &mut JsParser, context: ExpressionContext) -> Par
_ => {
// test_err decorator_expression_class
// let a = @decorator () => {};
// let b = @first @second function foo {}
// let b = @first @second function foo() {}
// let a = @decorator ( () => {} )
decorator_list
.add_diagnostic_if_present(p, |p, range| {
p.err_builder("Decorators are not valid here.", range)
})
.add_diagnostic_if_present(p, decorators_not_allowed)
.map(|mut marker| {
marker.change_kind(p, JS_BOGUS_EXPRESSION);
marker
Expand Down
6 changes: 6 additions & 0 deletions crates/rome_js_parser/src/syntax/js_parse_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -282,3 +282,9 @@ pub(crate) fn invalid_decorator_error(p: &JsParser, range: TextRange) -> ParseDi
range,
)
}

pub(crate) fn decorators_not_allowed(p: &JsParser, range: TextRange) -> ParseDiagnostic {
p.err_builder("Decorators are not valid here", range).hint(
"Decorators are only valid on class declarations, class expressions, and class methods",
)
}
18 changes: 7 additions & 11 deletions crates/rome_js_parser/src/syntax/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ use crate::syntax::expr::{
};
use crate::syntax::function::{parse_function_export_default_declaration, LineBreak};
use crate::syntax::js_parse_error::{
duplicate_assertion_keys_error, expected_binding, expected_declaration, expected_export_clause,
expected_export_default_declaration, expected_export_name_specifier, expected_expression,
expected_identifier, expected_literal_export_name, expected_module_source,
decorators_not_allowed, duplicate_assertion_keys_error, expected_binding, expected_declaration,
expected_export_clause, expected_export_default_declaration, expected_export_name_specifier,
expected_expression, expected_identifier, expected_literal_export_name, expected_module_source,
expected_named_import, expected_named_import_specifier, expected_statement,
};
use crate::syntax::stmt::{parse_statement, semi, StatementContext, STMT_RECOVERY_SET};
Expand Down Expand Up @@ -193,9 +193,7 @@ fn parse_module_item(p: &mut JsParser) -> ParsedSyntax {
// @decorator1 @decorator2
// function Foo() { }
decorator_list
.add_diagnostic_if_present(p, |p, range| {
p.err_builder("Decorators are not valid here.", range)
})
.add_diagnostic_if_present(p, decorators_not_allowed)
.map(|mut marker| {
marker.change_kind(p, JS_BOGUS_STATEMENT);
marker
Expand Down Expand Up @@ -1203,9 +1201,7 @@ fn parse_export_default_clause(p: &mut JsParser) -> ParsedSyntax {
}
_ => {
decorator_list
.add_diagnostic_if_present(p, |p, range| {
p.err_builder("Decorators are not valid here.", range)
})
.add_diagnostic_if_present(p, decorators_not_allowed)
.map(|mut marker| {
marker.change_kind(p, JS_BOGUS_STATEMENT);
marker
Expand All @@ -1214,11 +1210,11 @@ fn parse_export_default_clause(p: &mut JsParser) -> ParsedSyntax {
match p.cur() {
// test_err ts decorator_function_export_default_declaration_clause
// @decorator
// export default function foo { }
// export default function foo() { }
T![function] => parse_function_export_default_declaration_clause(p, m),
// test_err ts decorator_async_function_export_default_declaration_clause
// @decorator
// export default async function foo { }
// export default async function foo() { }
T![async] if p.nth_at(1, T![function]) => {
parse_function_export_default_declaration_clause(p, m)
}
Expand Down
6 changes: 2 additions & 4 deletions crates/rome_js_parser/src/syntax/stmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use crate::syntax::expr::{
};
use crate::syntax::function::{is_at_async_function, parse_function_declaration, LineBreak};
use crate::syntax::js_parse_error;
use crate::syntax::js_parse_error::{expected_binding, expected_statement};
use crate::syntax::js_parse_error::{decorators_not_allowed, expected_binding, expected_statement};
use crate::syntax::module::parse_import_or_import_equals_declaration;
use crate::syntax::typescript::ts_parse_error::{expected_ts_type, ts_only_syntax_error};

Expand Down Expand Up @@ -270,9 +270,7 @@ pub(crate) fn parse_statement(p: &mut JsParser, context: StatementContext) -> Pa
// function Foo() { }
// }
decorator_list
.add_diagnostic_if_present(p, |p, range| {
p.err_builder("Decorators are not valid here.", range)
})
.add_diagnostic_if_present(p, decorators_not_allowed)
.map(|mut marker| {
marker.change_kind(p, JS_BOGUS_STATEMENT);
marker
Expand Down
48 changes: 36 additions & 12 deletions crates/rome_js_parser/test_data/inline/err/decorator.rast
Original file line number Diff line number Diff line change
Expand Up @@ -1153,7 +1153,7 @@ decorator.ts:3:2 parse ━━━━━━━━━━━━━━━━━━━
--
decorator.ts:3:1 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

× Decorators are not valid here.
× Decorators are not valid here

1 │ @'dsads' class MyClass {}
2 │ @1 class MyClass {}
Expand All @@ -1162,6 +1162,8 @@ decorator.ts:3:1 parse ━━━━━━━━━━━━━━━━━━━
4 │ @[] in 1 class MyClass {}
5 │ @[] class MyClass {}

i Decorators are only valid on class declarations, class expressions, and class methods

--
decorator.ts:3:4 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Expand Down Expand Up @@ -1221,7 +1223,7 @@ decorator.ts:4:2 parse ━━━━━━━━━━━━━━━━━━━
--
decorator.ts:4:1 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

× Decorators are not valid here.
× Decorators are not valid here

2 │ @1 class MyClass {}
3 │ @++1 class MyClass {}
Expand All @@ -1230,6 +1232,8 @@ decorator.ts:4:1 parse ━━━━━━━━━━━━━━━━━━━
5 │ @[] class MyClass {}
6 │ @() => {} class MyClass {}

i Decorators are only valid on class declarations, class expressions, and class methods

--
decorator.ts:4:5 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Expand Down Expand Up @@ -1280,7 +1284,7 @@ decorator.ts:6:3 parse ━━━━━━━━━━━━━━━━━━━
--
decorator.ts:6:1 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

× Decorators are not valid here.
× Decorators are not valid here

4 │ @[] in 1 class MyClass {}
5 │ @[] class MyClass {}
Expand All @@ -1289,6 +1293,8 @@ decorator.ts:6:1 parse ━━━━━━━━━━━━━━━━━━━
7 │ @1 == 2 ? true : false class MyClass {}
8 │ @await fn class MyClass {}

i Decorators are only valid on class declarations, class expressions, and class methods

--
decorator.ts:6:5 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Expand Down Expand Up @@ -1325,7 +1331,7 @@ decorator.ts:7:2 parse ━━━━━━━━━━━━━━━━━━━
--
decorator.ts:7:1 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

× Decorators are not valid here.
× Decorators are not valid here

5 │ @[] class MyClass {}
6 │ @() => {} class MyClass {}
Expand All @@ -1334,6 +1340,8 @@ decorator.ts:7:1 parse ━━━━━━━━━━━━━━━━━━━
8 │ @await fn class MyClass {}
9 │ @function(){} class MyClass {}

i Decorators are only valid on class declarations, class expressions, and class methods

--
decorator.ts:7:4 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Expand Down Expand Up @@ -1370,7 +1378,7 @@ decorator.ts:8:2 parse ━━━━━━━━━━━━━━━━━━━
--
decorator.ts:8:1 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

× Decorators are not valid here.
× Decorators are not valid here

6 │ @() => {} class MyClass {}
7 │ @1 == 2 ? true : false class MyClass {}
Expand All @@ -1379,6 +1387,8 @@ decorator.ts:8:1 parse ━━━━━━━━━━━━━━━━━━━
9 │ @function(){} class MyClass {}
10 │ @obj instanceof Object class MyClass {}

i Decorators are only valid on class declarations, class expressions, and class methods

--
decorator.ts:8:11 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Expand Down Expand Up @@ -1424,7 +1434,7 @@ decorator.ts:9:2 parse ━━━━━━━━━━━━━━━━━━━
--
decorator.ts:10:1 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

× Decorators are not valid here.
× Decorators are not valid here

8 │ @await fn class MyClass {}
9 │ @function(){} class MyClass {}
Expand All @@ -1433,6 +1443,8 @@ decorator.ts:10:1 parse ━━━━━━━━━━━━━━━━━━
11 │ @1 === 2 class MyClass {}
12 │ @new Object() class MyClass {}

i Decorators are only valid on class declarations, class expressions, and class methods

--
decorator.ts:10:6 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Expand Down Expand Up @@ -1469,7 +1481,7 @@ decorator.ts:11:2 parse ━━━━━━━━━━━━━━━━━━
--
decorator.ts:11:1 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

× Decorators are not valid here.
× Decorators are not valid here

9 │ @function(){} class MyClass {}
10 │ @obj instanceof Object class MyClass {}
Expand All @@ -1478,6 +1490,8 @@ decorator.ts:11:1 parse ━━━━━━━━━━━━━━━━━━
12 │ @new Object() class MyClass {}
13 │ @{} class MyClass {}

i Decorators are only valid on class declarations, class expressions, and class methods

--
decorator.ts:11:4 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Expand Down Expand Up @@ -1526,7 +1540,7 @@ decorator.ts:13:2 parse ━━━━━━━━━━━━━━━━━━
--
decorator.ts:14:1 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

× Decorators are not valid here.
× Decorators are not valid here

12 │ @new Object() class MyClass {}
13 │ @{} class MyClass {}
Expand All @@ -1535,6 +1549,8 @@ decorator.ts:14:1 parse ━━━━━━━━━━━━━━━━━━
15 │ @a,b class MyClass {}
16 │ @`${d}foo` class MyClass {}

i Decorators are only valid on class declarations, class expressions, and class methods

--
decorator.ts:14:6 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Expand All @@ -1552,7 +1568,7 @@ decorator.ts:14:6 parse ━━━━━━━━━━━━━━━━━━
--
decorator.ts:15:1 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

× Decorators are not valid here.
× Decorators are not valid here

13 │ @{} class MyClass {}
14 │ @a++ class MyClass {}
Expand All @@ -1561,6 +1577,8 @@ decorator.ts:15:1 parse ━━━━━━━━━━━━━━━━━━
16 │ @`${d}foo` class MyClass {}
17 │ @obj as MyType class MyClass {}

i Decorators are only valid on class declarations, class expressions, and class methods

--
decorator.ts:15:3 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Expand Down Expand Up @@ -1597,7 +1615,7 @@ decorator.ts:16:2 parse ━━━━━━━━━━━━━━━━━━
--
decorator.ts:17:1 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

× Decorators are not valid here.
× Decorators are not valid here

15 │ @a,b class MyClass {}
16 │ @`${d}foo` class MyClass {}
Expand All @@ -1606,6 +1624,8 @@ decorator.ts:17:1 parse ━━━━━━━━━━━━━━━━━━
18 │ @<MyType>obj class MyClass {}
19 │ @obj satisfies MyType class MyClass {}

i Decorators are only valid on class declarations, class expressions, and class methods

--
decorator.ts:17:9 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Expand Down Expand Up @@ -1690,7 +1710,7 @@ decorator.ts:18:2 parse ━━━━━━━━━━━━━━━━━━
--
decorator.ts:18:1 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

× Decorators are not valid here.
× Decorators are not valid here

16 │ @`${d}foo` class MyClass {}
17 │ @obj as MyType class MyClass {}
Expand All @@ -1699,6 +1719,8 @@ decorator.ts:18:1 parse ━━━━━━━━━━━━━━━━━━
19 │ @obj satisfies MyType class MyClass {}
20 │ @obj! class MyClass {}

i Decorators are only valid on class declarations, class expressions, and class methods

--
decorator.ts:18:14 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Expand Down Expand Up @@ -1732,7 +1754,7 @@ decorator.ts:18:14 parse ━━━━━━━━━━━━━━━━━━
--
decorator.ts:19:1 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

× Decorators are not valid here.
× Decorators are not valid here

17 │ @obj as MyType class MyClass {}
18 │ @<MyType>obj class MyClass {}
Expand All @@ -1741,6 +1763,8 @@ decorator.ts:19:1 parse ━━━━━━━━━━━━━━━━━━
20 │ @obj! class MyClass {}
21 │

i Decorators are only valid on class declarations, class expressions, and class methods

--
decorator.ts:19:16 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Expand Down
Loading

0 comments on commit 6d509e7

Please sign in to comment.