fix(rslint_parser): Fix parsing of TS keywords
declare, abstract, namespace, type, enum, module, global, interface, private, protected, and public are typescript keywords but valid identifiers in JS.
This PR removes the TS parsing logic for now and ensures these identifiers are correctly parsed.
`compiler.js` no longer reports any errors.
MODIFY
crates/rslint_parser/src/ast.rs
crates/rslint_parser/src/ast.rs
@@ -617,8 +617,6 @@ mod tests {
// list([,3])
let list = build_list(vec![(None, Some(",")), (Some(3), None)]);
- dbg!(&list.syntax_list.node());
-
assert_eq!(list.len(), 2);
assert!(!list.is_empty());
assert_eq!(list.separators().count(), 1);

MODIFY
crates/rslint_parser/src/syntax/expr.rs
crates/rslint_parser/src/syntax/expr.rs
@@ -50,7 +50,7 @@ pub const ASSIGN_TOKENS: TokenSet = token_set![
T![**=],
];
-pub const STARTS_EXPR: TokenSet = token_set![
+const STARTS_EXPR: TokenSet = token_set![
T![!],
T!['('],
T!['['],
@@ -69,6 +69,7 @@ pub const STARTS_EXPR: TokenSet = token_set![
T![...],
T![this],
T![yield],
+ T![enum],
T![await],
T![function],
T![class],
@@ -959,6 +960,10 @@ pub(crate) fn parse_expression(p: &mut Parser) -> ParsedSyntax {
})
}
+pub(crate) fn is_at_expression(p: &Parser) -> bool {
+ p.at_ts(STARTS_EXPR) || p.at(T![<]) || (p.at(T![enum]) && !p.has_linebreak_before_n(0))
+}
+
/// A primary expression such as a literal, an object, an array, or `this`.
fn parse_primary_expression(p: &mut Parser) -> ParsedSyntax {
let parsed_literal_expression = parse_literal_expression(p);
@@ -995,7 +1000,7 @@ fn parse_primary_expression(p: &mut Parser) -> ParsedSyntax {
} else {
// `async a => {}` and `async (a) => {}`
if p.state.potential_arrow_start
- && token_set![T![ident], T![yield], T![await], T!['(']].contains(p.nth(1))
+ && (is_nth_at_identifier_name(p, 1) || p.nth(1) == T!['('])
{
// test async_arrow_expr
// let a = async foo => {}
@@ -1046,7 +1051,7 @@ fn parse_primary_expression(p: &mut Parser) -> ParsedSyntax {
parse_function_expression(p).unwrap()
}
- T![ident] | T![yield] | T![await] => {
+ T![ident] | T![yield] | T![await] | T![enum] => {
// test identifier_reference
// // SCRIPT
// foo;
@@ -1166,6 +1171,9 @@ fn parse_reference_identifier(p: &mut Parser) -> ParsedSyntax {
// await;
// async function test(await) {}
// function* test(yield) {}
+// enum;
+// implements;
+// interface;
/// Parses an identifier if it is valid in this context or returns `Invalid` if the context isn't valid in this context.
/// An identifier is invalid if:
@@ -1173,7 +1181,7 @@ fn parse_reference_identifier(p: &mut Parser) -> ParsedSyntax {
/// * It is named `yield` inside of a generator function or in strict mode
pub(super) fn parse_identifier(p: &mut Parser, kind: JsSyntaxKind) -> ParsedSyntax {
match p.cur() {
- T![yield] | T![await] | T![ident] => {
+ T![yield] | T![await] | T![ident] | T![enum] => {
let m = p.start();
let name = p.cur_src();
@@ -1190,18 +1198,23 @@ pub(super) fn parse_identifier(p: &mut Parser, kind: JsSyntaxKind) -> ParsedSynt
p.err_builder("Illegal use of `yield` as an identifier in generator function")
.primary(p.cur_tok().range, ""),
),
+
"yield" | "let" | "public" | "protected" | "private" | "package" | "implements"
| "interface" | "static"
if StrictMode.is_supported(p) =>
{
Some(
p.err_builder(&format!(
- "Illegal use of `{}` as an identifier in strict mode",
+ "Illegal use of reserved keyword `{}` as an identifier in strict mode",
name
))
.primary(p.cur_tok().range, ""),
)
}
+ _ if p.cur() == T![enum] => Some(
+ p.err_builder("Illegal use of reserved keyword `enum` as an identifier")
+ .primary(p.cur_tok().range, ""),
+ ),
_ => None,
};
@@ -1220,7 +1233,7 @@ pub(super) fn parse_identifier(p: &mut Parser, kind: JsSyntaxKind) -> ParsedSynt
}
pub(crate) fn is_at_identifier(p: &Parser) -> bool {
- matches!(p.cur(), T![ident] | T![await] | T![yield])
+ matches!(p.cur(), T![ident] | T![await] | T![yield] | T![enum])
}
/// A template literal such as "`abcd ${efg}`"
@@ -1528,5 +1541,9 @@ pub(super) fn parse_unary_expr(p: &mut Parser) -> ParsedSyntax {
}
pub(super) fn is_at_identifier_name(p: &Parser) -> bool {
- p.at(T![ident]) || p.cur().is_keyword()
+ is_nth_at_identifier_name(p, 0)
+}
+
+pub(super) fn is_nth_at_identifier_name(p: &Parser, offset: usize) -> bool {
+ p.nth_at(offset, T![ident]) || p.nth(offset).is_keyword()
}

MODIFY
crates/rslint_parser/src/syntax/stmt.rs
crates/rslint_parser/src/syntax/stmt.rs
//! See the [ECMAScript spec](https://www.ecma-international.org/ecma-262/5.1/#sec-12).
use super::binding::*;
-use super::expr::{parse_expression, STARTS_EXPR};
+use super::expr::parse_expression;
use super::program::export_decl;
use super::typescript::*;
use super::util::check_label_use;
@@ -12,7 +12,8 @@ use crate::parser::{RecoveryError, RecoveryResult};
use crate::syntax::assignment::{expression_to_assignment_pattern, AssignmentExprPrecedence};
use crate::syntax::class::{parse_class_declaration, parse_initializer_clause};
use crate::syntax::expr::{
- parse_expr_or_assignment, parse_expression_or_recover_to_next_statement, parse_identifier,
+ is_at_expression, is_at_identifier, is_nth_at_identifier_name, parse_expr_or_assignment,
+ parse_expression_or_recover_to_next_statement, parse_identifier,
};
use crate::syntax::function::{is_at_async_function, parse_function_declaration, LineBreak};
use crate::syntax::js_parse_error;
@@ -161,7 +162,9 @@ pub fn parse_statement(p: &mut Parser) -> ParsedSyntax {
T![if] => parse_if_statement(p), // It is only ever Err if there's no if
T![with] => parse_with_statement(p), // ever only Err if there's no with keyword
T![while] => parse_while_statement(p), // It is only ever Err if there's no while keyword
- t if (t == T![const] && p.nth_at(1, T![enum])) || t == T![enum] => {
+ t if (t == T![enum] && is_nth_at_identifier_name(p, 1))
+ || (t == T![const] && p.nth_at(1, T![enum]) && is_nth_at_identifier_name(p, 2)) =>
+ {
let mut res = ts_enum(p);
res.err_if_not_ts(p, "enums can only be declared in TypeScript files");
Present(res)
@@ -184,7 +187,13 @@ pub fn parse_statement(p: &mut Parser) -> ParsedSyntax {
variable_declaration_statement(p)
}
// TODO: handle `<T>() => {};` with less of a hack
- _ if p.at_ts(STARTS_EXPR) || p.at(T![<]) => parse_expression_statement(p),
+ _ if is_at_expression(p) => {
+ if is_at_identifier(p) && p.nth_at(1, T![:]) {
+ parse_labeled_statement(p)
+ } else {
+ parse_expression_statement(p)
+ }
+ }
_ => Absent,
}
}
@@ -195,56 +204,8 @@ pub fn parse_statement(p: &mut Parser) -> ParsedSyntax {
// label1: {}
// }
// }
-
-fn parse_expression_statement(p: &mut Parser) -> ParsedSyntax {
- let start = p.cur_tok().range.start;
- // this is *technically* wrong because it would be an expr stmt in js but for our purposes
- // we treat these as always being ts declarations since ambiguity is inefficient in this style of
- // parsing and it results in better errors usually
- if matches!(
- p.cur_src(),
- "declare" | "abstract" | "enum" | "interface" | "namespace" | "type"
- ) && !p.nth_at(1, T![:])
- && !p.nth_at(1, T![.])
- {
- if let Some(mut res) = try_parse_ts(p, ts_expr_stmt) {
- res.err_if_not_ts(
- p,
- "TypeScript declarations can only be used in TypeScript files",
- );
- return Present(res);
- }
- }
-
- // module and global are special because its used normally in js a lot so we cant assume its a ts module decl
- if p.cur_src() == "module" || (p.cur_src() == "global" && p.nth_at(1, T!['{'])) {
- if let Some(mut res) = try_parse_ts(p, ts_expr_stmt) {
- res.err_if_not_ts(
- p,
- "TypeScript declarations can only be used in TypeScript files",
- );
- return Present(res);
- }
- }
- if p.typescript()
- && matches!(p.cur_src(), "public" | "private" | "protected")
- && p.nth_src(1) == "interface"
- {
- let err = p
- .err_builder("interface declarations cannot have accessibility modifiers")
- .primary(p.cur_tok().range, "")
- .secondary(p.nth_tok(1).range, "");
-
- p.error(err);
- let m = p.start();
- p.bump_any();
- ts_interface(p);
- m.complete(p, JS_UNKNOWN);
- }
-
- // Labelled statement
- if p.nth_at(1, T![:]) {
- if let Present(identifier) = parse_identifier(p, JS_LABELED_STATEMENT) {
+fn parse_labeled_statement(p: &mut Parser) -> ParsedSyntax {
+ parse_identifier(p, JS_LABELED_STATEMENT).map(|identifier| {
if !identifier.kind().is_unknown() {
let range = identifier.range(p);
let label = p.source(range);
@@ -268,21 +229,34 @@ fn parse_expression_statement(p: &mut Parser) -> ParsedSyntax {
}
}
- let kind = if identifier.kind().is_unknown() {
- JS_UNKNOWN_STATEMENT
- } else {
- JS_LABELED_STATEMENT
- };
-
let labelled_statement = identifier.undo_completion(p);
p.bump_any();
parse_statement(p).or_add_diagnostic(p, expected_statement);
- return Present(labelled_statement.complete(p, kind));
- }
+ labelled_statement.complete(p, JS_LABELED_STATEMENT)
+ })
}
+// test ts_keyword_assignments
+// declare = 1;
+// abstract = 2;
+// namespace = 3;
+// type = 4;
+// module = 5;
+// global = 6;
+//
+// test ts_keywords_assignments_script
+// // SCRIPT
+// interface = 1;
+// private = 2;
+// protected = 3;
+// public = 4;
+// implements = 5;
+fn parse_expression_statement(p: &mut Parser) -> ParsedSyntax {
+ let start = p.cur_tok().range.start;
+
let expr = parse_expression_or_recover_to_next_statement(p, false);
+
if let Ok(expr) = expr {
let m = expr.precede(p);
semi(p, start..p.cur_tok().range.end);
@@ -336,7 +310,7 @@ pub fn parse_throw_statement(p: &mut Parser) -> ParsedSyntax {
)
.primary(p.cur_tok().range, "A linebreak is not allowed here");
- if p.at_ts(STARTS_EXPR) {
+ if is_at_expression(p) {
err = err.secondary(p.cur_tok().range, "Help: did you mean to throw this?");
}
@@ -450,8 +424,8 @@ pub fn parse_return_statement(p: &mut Parser) -> ParsedSyntax {
let m = p.start();
let start = p.cur_tok().range.start;
p.bump_any(); // return keyword
- if !p.has_linebreak_before_n(0) && p.at_ts(STARTS_EXPR) {
- parse_expression(p).unwrap();
+ if !p.has_linebreak_before_n(0) {
+ parse_expression(p).ok();
}
semi(p, start..p.cur_tok().range.end);

MODIFY
crates/rslint_parser/src/syntax/typescript.rs
crates/rslint_parser/src/syntax/typescript.rs
@@ -107,20 +107,6 @@ pub(crate) fn maybe_ts_type_annotation(p: &mut Parser) -> Option<Range<usize>> {
}
}
-pub(crate) fn ts_expr_stmt(p: &mut Parser) -> Option<CompletedMarker> {
- match p.cur_src() {
- "declare" => ts_declare(p),
- "global" => {
- if p.nth_at(1, T!['{']) {
- ts_ambient_external_module_decl(p, false)
- } else {
- None
- }
- }
- _ => ts_decl(p),
- }
-}
-
pub(crate) fn ts_declare(p: &mut Parser) -> Option<CompletedMarker> {
debug_assert_eq!(p.cur_src(), "declare");
let p = &mut *p.with_state(ParserState {

MODIFY
crates/rslint_parser/test_data/inline/err/identifier_err.js
crates/rslint_parser/test_data/inline/err/identifier_err.js
@@ -2,3 +2,6 @@ yield;
await;
async function test(await) {}
function* test(yield) {}
+enum;
+implements;
+interface;

ADD
crates/rslint_parser/test_data/inline/ok/ts_keyword_assignments.js
+declare = 1;
+abstract = 2;
+namespace = 3;
+type = 4;
+module = 5;
+global = 6;

ADD
crates/rslint_parser/test_data/inline/ok/ts_keyword_assignments.rast
+JsModule {
+ interpreter_token: missing (optional),
+ directives: JsDirectiveList [],
+ items: JsModuleItemList [
+ JsExpressionStatement {
+ expression: JsAssignmentExpression {
+ left: JsIdentifierAssignment {
+ name_token: IDENT@0..8 "declare" [] [Whitespace(" ")],
+ },
+ operator_token: EQ@8..10 "=" [] [Whitespace(" ")],
+ right: JsNumberLiteralExpression {
+ value_token: JS_NUMBER_LITERAL@10..11 "1" [] [],
+ },
+ },
+ semicolon_token: SEMICOLON@11..12 ";" [] [],
+ },
+ JsExpressionStatement {
+ expression: JsAssignmentExpression {
+ left: JsIdentifierAssignment {
+ name_token: IDENT@12..22 "abstract" [Whitespace("\n")] [Whitespace(" ")],
+ },
+ operator_token: EQ@22..24 "=" [] [Whitespace(" ")],
+ right: JsNumberLiteralExpression {
+ value_token: JS_NUMBER_LITERAL@24..25 "2" [] [],
+ },
+ },
+ semicolon_token: SEMICOLON@25..26 ";" [] [],
+ },
+ JsExpressionStatement {
+ expression: JsAssignmentExpression {
+ left: JsIdentifierAssignment {
+ name_token: IDENT@26..37 "namespace" [Whitespace("\n")] [Whitespace(" ")],
+ },
+ operator_token: EQ@37..39 "=" [] [Whitespace(" ")],
+ right: JsNumberLiteralExpression {
+ value_token: JS_NUMBER_LITERAL@39..40 "3" [] [],
+ },
+ },
+ semicolon_token: SEMICOLON@40..41 ";" [] [],
+ },
+ JsExpressionStatement {
+ expression: JsAssignmentExpression {
+ left: JsIdentifierAssignment {
+ name_token: IDENT@41..47 "type" [Whitespace("\n")] [Whitespace(" ")],
+ },
+ operator_token: EQ@47..49 "=" [] [Whitespace(" ")],
+ right: JsNumberLiteralExpression {
+ value_token: JS_NUMBER_LITERAL@49..50 "4" [] [],
+ },
+ },
+ semicolon_token: SEMICOLON@50..51 ";" [] [],
+ },
+ JsExpressionStatement {
+ expression: JsAssignmentExpression {
+ left: JsIdentifierAssignment {
+ name_token: IDENT@51..59 "module" [Whitespace("\n")] [Whitespace(" ")],
+ },
+ operator_token: EQ@59..61 "=" [] [Whitespace(" ")],
+ right: JsNumberLiteralExpression {
+ value_token: JS_NUMBER_LITERAL@61..62 "5" [] [],
+ },
+ },
+ semicolon_token: SEMICOLON@62..63 ";" [] [],
+ },
+ JsExpressionStatement {
+ expression: JsAssignmentExpression {
+ left: JsIdentifierAssignment {
+ name_token: IDENT@63..71 "global" [Whitespace("\n")] [Whitespace(" ")],
+ },
+ operator_token: EQ@71..73 "=" [] [Whitespace(" ")],
+ right: JsNumberLiteralExpression {
+ value_token: JS_NUMBER_LITERAL@73..74 "6" [] [],
+ },
+ },
+ semicolon_token: SEMICOLON@74..75 ";" [] [],
+ },
+ ],
+ eof_token: EOF@75..76 "" [Whitespace("\n")] [],
+}
+
+0: JS_MODULE@0..76
+ 0: (empty)
+ 1: JS_DIRECTIVE_LIST@0..0
+ 2: JS_MODULE_ITEM_LIST@0..75
+ 0: JS_EXPRESSION_STATEMENT@0..12
+ 0: JS_ASSIGNMENT_EXPRESSION@0..11
+ 0: JS_IDENTIFIER_ASSIGNMENT@0..8
+ 0: IDENT@0..8 "declare" [] [Whitespace(" ")]
+ 1: EQ@8..10 "=" [] [Whitespace(" ")]
+ 2: JS_NUMBER_LITERAL_EXPRESSION@10..11
+ 0: JS_NUMBER_LITERAL@10..11 "1" [] []
+ 1: SEMICOLON@11..12 ";" [] []
+ 1: JS_EXPRESSION_STATEMENT@12..26
+ 0: JS_ASSIGNMENT_EXPRESSION@12..25
+ 0: JS_IDENTIFIER_ASSIGNMENT@12..22
+ 0: IDENT@12..22 "abstract" [Whitespace("\n")] [Whitespace(" ")]
+ 1: EQ@22..24 "=" [] [Whitespace(" ")]
+ 2: JS_NUMBER_LITERAL_EXPRESSION@24..25
+ 0: JS_NUMBER_LITERAL@24..25 "2" [] []
+ 1: SEMICOLON@25..26 ";" [] []
+ 2: JS_EXPRESSION_STATEMENT@26..41
+ 0: JS_ASSIGNMENT_EXPRESSION@26..40
+ 0: JS_IDENTIFIER_ASSIGNMENT@26..37
+ 0: IDENT@26..37 "namespace" [Whitespace("\n")] [Whitespace(" ")]
+ 1: EQ@37..39 "=" [] [Whitespace(" ")]
+ 2: JS_NUMBER_LITERAL_EXPRESSION@39..40
+ 0: JS_NUMBER_LITERAL@39..40 "3" [] []
+ 1: SEMICOLON@40..41 ";" [] []
+ 3: JS_EXPRESSION_STATEMENT@41..51
+ 0: JS_ASSIGNMENT_EXPRESSION@41..50
+ 0: JS_IDENTIFIER_ASSIGNMENT@41..47
+ 0: IDENT@41..47 "type" [Whitespace("\n")] [Whitespace(" ")]
+ 1: EQ@47..49 "=" [] [Whitespace(" ")]
+ 2: JS_NUMBER_LITERAL_EXPRESSION@49..50
+ 0: JS_NUMBER_LITERAL@49..50 "4" [] []
+ 1: SEMICOLON@50..51 ";" [] []
+ 4: JS_EXPRESSION_STATEMENT@51..63
+ 0: JS_ASSIGNMENT_EXPRESSION@51..62
+ 0: JS_IDENTIFIER_ASSIGNMENT@51..59
+ 0: IDENT@51..59 "module" [Whitespace("\n")] [Whitespace(" ")]
+ 1: EQ@59..61 "=" [] [Whitespace(" ")]
+ 2: JS_NUMBER_LITERAL_EXPRESSION@61..62
+ 0: JS_NUMBER_LITERAL@61..62 "5" [] []
+ 1: SEMICOLON@62..63 ";" [] []
+ 5: JS_EXPRESSION_STATEMENT@63..75
+ 0: JS_ASSIGNMENT_EXPRESSION@63..74
+ 0: JS_IDENTIFIER_ASSIGNMENT@63..71
+ 0: IDENT@63..71 "global" [Whitespace("\n")] [Whitespace(" ")]
+ 1: EQ@71..73 "=" [] [Whitespace(" ")]
+ 2: JS_NUMBER_LITERAL_EXPRESSION@73..74
+ 0: JS_NUMBER_LITERAL@73..74 "6" [] []
+ 1: SEMICOLON@74..75 ";" [] []
+ 3: EOF@75..76 "" [Whitespace("\n")] []

ADD
crates/rslint_parser/test_data/inline/ok/ts_keywords_assignments_script.js
+// SCRIPT
+interface = 1;
+private = 2;
+protected = 3;
+public = 4;
+implements = 5;

ADD
crates/rslint_parser/test_data/inline/ok/ts_keywords_assignments_script.rast
+JsScript {
+ interpreter_token: missing (optional),
+ directives: JsDirectiveList [],
+ statements: JsStatementList [
+ JsExpressionStatement {
+ expression: JsAssignmentExpression {
+ left: JsIdentifierAssignment {
+ name_token: IDENT@0..20 "interface" [Comments("// SCRIPT"), Whitespace("\n")] [Whitespace(" ")],
+ },
+ operator_token: EQ@20..22 "=" [] [Whitespace(" ")],
+ right: JsNumberLiteralExpression {
+ value_token: JS_NUMBER_LITERAL@22..23 "1" [] [],
+ },
+ },
+ semicolon_token: SEMICOLON@23..24 ";" [] [],
+ },
+ JsExpressionStatement {
+ expression: JsAssignmentExpression {
+ left: JsIdentifierAssignment {
+ name_token: IDENT@24..33 "private" [Whitespace("\n")] [Whitespace(" ")],
+ },
+ operator_token: EQ@33..35 "=" [] [Whitespace(" ")],
+ right: JsNumberLiteralExpression {
+ value_token: JS_NUMBER_LITERAL@35..36 "2" [] [],
+ },
+ },
+ semicolon_token: SEMICOLON@36..37 ";" [] [],
+ },
+ JsExpressionStatement {
+ expression: JsAssignmentExpression {
+ left: JsIdentifierAssignment {
+ name_token: IDENT@37..48 "protected" [Whitespace("\n")] [Whitespace(" ")],
+ },
+ operator_token: EQ@48..50 "=" [] [Whitespace(" ")],
+ right: JsNumberLiteralExpression {
+ value_token: JS_NUMBER_LITERAL@50..51 "3" [] [],
+ },
+ },
+ semicolon_token: SEMICOLON@51..52 ";" [] [],
+ },
+ JsExpressionStatement {
+ expression: JsAssignmentExpression {
+ left: JsIdentifierAssignment {
+ name_token: IDENT@52..60 "public" [Whitespace("\n")] [Whitespace(" ")],
+ },
+ operator_token: EQ@60..62 "=" [] [Whitespace(" ")],
+ right: JsNumberLiteralExpression {
+ value_token: JS_NUMBER_LITERAL@62..63 "4" [] [],
+ },
+ },
+ semicolon_token: SEMICOLON@63..64 ";" [] [],
+ },
+ JsExpressionStatement {
+ expression: JsAssignmentExpression {
+ left: JsIdentifierAssignment {
+ name_token: IDENT@64..76 "implements" [Whitespace("\n")] [Whitespace(" ")],
+ },
+ operator_token: EQ@76..78 "=" [] [Whitespace(" ")],
+ right: JsNumberLiteralExpression {
+ value_token: JS_NUMBER_LITERAL@78..79 "5" [] [],
+ },
+ },
+ semicolon_token: SEMICOLON@79..80 ";" [] [],
+ },
+ ],
+ eof_token: EOF@80..81 "" [Whitespace("\n")] [],
+}
+
+0: JS_SCRIPT@0..81
+ 0: (empty)
+ 1: JS_DIRECTIVE_LIST@0..0
+ 2: JS_STATEMENT_LIST@0..80
+ 0: JS_EXPRESSION_STATEMENT@0..24
+ 0: JS_ASSIGNMENT_EXPRESSION@0..23
+ 0: JS_IDENTIFIER_ASSIGNMENT@0..20
+ 0: IDENT@0..20 "interface" [Comments("// SCRIPT"), Whitespace("\n")] [Whitespace(" ")]
+ 1: EQ@20..22 "=" [] [Whitespace(" ")]
+ 2: JS_NUMBER_LITERAL_EXPRESSION@22..23
+ 0: JS_NUMBER_LITERAL@22..23 "1" [] []
+ 1: SEMICOLON@23..24 ";" [] []
+ 1: JS_EXPRESSION_STATEMENT@24..37
+ 0: JS_ASSIGNMENT_EXPRESSION@24..36
+ 0: JS_IDENTIFIER_ASSIGNMENT@24..33
+ 0: IDENT@24..33 "private" [Whitespace("\n")] [Whitespace(" ")]
+ 1: EQ@33..35 "=" [] [Whitespace(" ")]
+ 2: JS_NUMBER_LITERAL_EXPRESSION@35..36
+ 0: JS_NUMBER_LITERAL@35..36 "2" [] []
+ 1: SEMICOLON@36..37 ";" [] []
+ 2: JS_EXPRESSION_STATEMENT@37..52
+ 0: JS_ASSIGNMENT_EXPRESSION@37..51
+ 0: JS_IDENTIFIER_ASSIGNMENT@37..48
+ 0: IDENT@37..48 "protected" [Whitespace("\n")] [Whitespace(" ")]
+ 1: EQ@48..50 "=" [] [Whitespace(" ")]
+ 2: JS_NUMBER_LITERAL_EXPRESSION@50..51
+ 0: JS_NUMBER_LITERAL@50..51 "3" [] []
+ 1: SEMICOLON@51..52 ";" [] []
+ 3: JS_EXPRESSION_STATEMENT@52..64
+ 0: JS_ASSIGNMENT_EXPRESSION@52..63
+ 0: JS_IDENTIFIER_ASSIGNMENT@52..60
+ 0: IDENT@52..60 "public" [Whitespace("\n")] [Whitespace(" ")]
+ 1: EQ@60..62 "=" [] [Whitespace(" ")]
+ 2: JS_NUMBER_LITERAL_EXPRESSION@62..63
+ 0: JS_NUMBER_LITERAL@62..63 "4" [] []
+ 1: SEMICOLON@63..64 ";" [] []
+ 4: JS_EXPRESSION_STATEMENT@64..80
+ 0: JS_ASSIGNMENT_EXPRESSION@64..79
+ 0: JS_IDENTIFIER_ASSIGNMENT@64..76
+ 0: IDENT@64..76 "implements" [Whitespace("\n")] [Whitespace(" ")]
+ 1: EQ@76..78 "=" [] [Whitespace(" ")]
+ 2: JS_NUMBER_LITERAL_EXPRESSION@78..79
+ 0: JS_NUMBER_LITERAL@78..79 "5" [] []
+ 1: SEMICOLON@79..80 ";" [] []
+ 3: EOF@80..81 "" [Whitespace("\n")] []

fix(rslint_parser): Fix parsing of TS keywords (#1896)

declare, abstract, namespace, type, enum, module, global, interface, private, protected, and public are typescript keywords but valid identifiers in JS.

This PR removes the TS parsing logic for now and ensures these identifiers are correctly parsed.

`compiler.js` no longer reports any errors.