diff --git a/ecmascript/parser/Cargo.toml b/ecmascript/parser/Cargo.toml index 868736024df..22e692ec24f 100644 --- a/ecmascript/parser/Cargo.toml +++ b/ecmascript/parser/Cargo.toml @@ -7,7 +7,7 @@ include = ["Cargo.toml", "src/**/*.rs", "examples/**/*.rs"] license = "Apache-2.0/MIT" name = "swc_ecma_parser" repository = "https://github.com/swc-project/swc.git" -version = "0.57.2" +version = "0.57.3" [features] default = [] diff --git a/ecmascript/parser/src/parser/class_and_fn.rs b/ecmascript/parser/src/parser/class_and_fn.rs index 7aacbc857a8..d30c0c3117e 100644 --- a/ecmascript/parser/src/parser/class_and_fn.rs +++ b/ecmascript/parser/src/parser/class_and_fn.rs @@ -316,7 +316,7 @@ impl<'a, I: Tokens> Parser { // Allow `private declare`. let declare = declare || self.syntax().typescript() && eat!(self, "declare"); - if declare { + let declare_token = if declare { // Handle declare(){} if self.is_class_method()? { let key = Either::Right(PropName::Ident(Ident::new( @@ -360,8 +360,12 @@ impl<'a, I: Tokens> Parser { false, false, ); + } else { + Some(span!(self, start)) } - } + } else { + None + }; let static_token = { let start = cur_pos!(self); @@ -423,7 +427,7 @@ impl<'a, I: Tokens> Parser { self.parse_class_member_with_is_static( start, - declare, + declare_token, accessibility, static_token, decorators, @@ -434,7 +438,7 @@ impl<'a, I: Tokens> Parser { fn parse_class_member_with_is_static( &mut self, start: BytePos, - declare: bool, + declare_token: Option, accessibility: Option, static_token: Option, decorators: Vec, @@ -445,6 +449,7 @@ impl<'a, I: Tokens> Parser { let mut is_override = false; let mut readonly = None; let mut modifier_span = None; + let declare = declare_token.is_some(); while let Some(modifier) = self.parse_ts_modifier(&["abstract", "readonly", "override", "static"])? { @@ -578,6 +583,11 @@ impl<'a, I: Tokens> Parser { trace_cur!(self, parse_class_member_with_is_static__normal_class_method); + match declare_token { + Some(token) => self.emit_err(token, SyntaxError::TS1031), + None => {} + } + if readonly.is_some() { syntax_error!(self, span!(self, start), SyntaxError::ReadOnlyMethod); } diff --git a/ecmascript/parser/tests/typescript-errors/class/declare-class-method/input.ts b/ecmascript/parser/tests/typescript-errors/class/declare-class-method/input.ts new file mode 100644 index 00000000000..273f0e7525e --- /dev/null +++ b/ecmascript/parser/tests/typescript-errors/class/declare-class-method/input.ts @@ -0,0 +1,3 @@ +class T { + declare m1(): string; +} diff --git a/ecmascript/parser/tests/typescript-errors/class/declare-class-method/input.ts.stderr b/ecmascript/parser/tests/typescript-errors/class/declare-class-method/input.ts.stderr new file mode 100644 index 00000000000..f594861f9c3 --- /dev/null +++ b/ecmascript/parser/tests/typescript-errors/class/declare-class-method/input.ts.stderr @@ -0,0 +1,6 @@ +error: `declare` modifier cannot appear on a class element + --> $DIR/tests/typescript-errors/class/declare-class-method/input.ts:2:5 + | +2 | declare m1(): string; + | ^^^^^^^ + diff --git a/ecmascript/parser/tests/typescript-errors/class/override-with-declare/input.ts.stderr b/ecmascript/parser/tests/typescript-errors/class/override-with-declare/input.ts.stderr index 1f229ff09ae..015418bbd68 100644 --- a/ecmascript/parser/tests/typescript-errors/class/override-with-declare/input.ts.stderr +++ b/ecmascript/parser/tests/typescript-errors/class/override-with-declare/input.ts.stderr @@ -4,3 +4,9 @@ error: 'override' modifier cannot be used with 'declare' modifier. 2 | declare override m1(): any | ^^^^^^^^ +error: `declare` modifier cannot appear on a class element + --> $DIR/tests/typescript-errors/class/override-with-declare/input.ts:2:3 + | +2 | declare override m1(): any + | ^^^^^^^ + diff --git a/ecmascript/parser/tests/typescript/class/property-declare/input.ts b/ecmascript/parser/tests/typescript/class/property-declare/input.ts new file mode 100644 index 00000000000..5651779093d --- /dev/null +++ b/ecmascript/parser/tests/typescript/class/property-declare/input.ts @@ -0,0 +1,8 @@ +class MyClass { + declare hoge: string; + declare foo: number; + + constructor() { + this.hoge = "test"; + } +} diff --git a/ecmascript/parser/tests/typescript/class/property-declare/input.ts.json b/ecmascript/parser/tests/typescript/class/property-declare/input.ts.json new file mode 100644 index 00000000000..3f49570baa8 --- /dev/null +++ b/ecmascript/parser/tests/typescript/class/property-declare/input.ts.json @@ -0,0 +1,219 @@ +{ + "type": "Script", + "span": { + "start": 0, + "end": 123, + "ctxt": 0 + }, + "body": [ + { + "type": "ClassDeclaration", + "identifier": { + "type": "Identifier", + "span": { + "start": 6, + "end": 13, + "ctxt": 0 + }, + "value": "MyClass", + "optional": false + }, + "declare": false, + "span": { + "start": 0, + "end": 123, + "ctxt": 0 + }, + "decorators": [], + "body": [ + { + "type": "ClassProperty", + "span": { + "start": 20, + "end": 41, + "ctxt": 0 + }, + "key": { + "type": "Identifier", + "span": { + "start": 28, + "end": 32, + "ctxt": 0 + }, + "value": "hoge", + "optional": false + }, + "value": null, + "typeAnnotation": { + "type": "TsTypeAnnotation", + "span": { + "start": 32, + "end": 40, + "ctxt": 0 + }, + "typeAnnotation": { + "type": "TsKeywordType", + "span": { + "start": 34, + "end": 40, + "ctxt": 0 + }, + "kind": "string" + } + }, + "isStatic": false, + "decorators": [], + "computed": false, + "accessibility": null, + "isAbstract": false, + "isOptional": false, + "isOverride": false, + "readonly": false, + "declare": true, + "definite": false + }, + { + "type": "ClassProperty", + "span": { + "start": 46, + "end": 66, + "ctxt": 0 + }, + "key": { + "type": "Identifier", + "span": { + "start": 54, + "end": 57, + "ctxt": 0 + }, + "value": "foo", + "optional": false + }, + "value": null, + "typeAnnotation": { + "type": "TsTypeAnnotation", + "span": { + "start": 57, + "end": 65, + "ctxt": 0 + }, + "typeAnnotation": { + "type": "TsKeywordType", + "span": { + "start": 59, + "end": 65, + "ctxt": 0 + }, + "kind": "number" + } + }, + "isStatic": false, + "decorators": [], + "computed": false, + "accessibility": null, + "isAbstract": false, + "isOptional": false, + "isOverride": false, + "readonly": false, + "declare": true, + "definite": false + }, + { + "type": "Constructor", + "span": { + "start": 72, + "end": 121, + "ctxt": 0 + }, + "key": { + "type": "Identifier", + "span": { + "start": 72, + "end": 83, + "ctxt": 0 + }, + "value": "constructor", + "optional": false + }, + "params": [], + "body": { + "type": "BlockStatement", + "span": { + "start": 86, + "end": 121, + "ctxt": 0 + }, + "stmts": [ + { + "type": "ExpressionStatement", + "span": { + "start": 96, + "end": 115, + "ctxt": 0 + }, + "expression": { + "type": "AssignmentExpression", + "span": { + "start": 96, + "end": 114, + "ctxt": 0 + }, + "operator": "=", + "left": { + "type": "MemberExpression", + "span": { + "start": 96, + "end": 105, + "ctxt": 0 + }, + "object": { + "type": "ThisExpression", + "span": { + "start": 96, + "end": 100, + "ctxt": 0 + } + }, + "property": { + "type": "Identifier", + "span": { + "start": 101, + "end": 105, + "ctxt": 0 + }, + "value": "hoge", + "optional": false + }, + "computed": false + }, + "right": { + "type": "StringLiteral", + "span": { + "start": 108, + "end": 114, + "ctxt": 0 + }, + "value": "test", + "hasEscape": false, + "kind": { + "type": "normal", + "containsQuote": true + } + } + } + } + ] + }, + "accessibility": null, + "isOptional": false + } + ], + "superClass": null, + "isAbstract": false, + "typeParams": null, + "superTypeParams": null, + "implements": [] + } + ], + "interpreter": null +}