From 62271a4e3b4646cbf8209dac34e97f572ff43ef9 Mon Sep 17 00:00:00 2001 From: songqi Date: Thu, 5 Jan 2023 16:25:30 +0800 Subject: [PATCH] Fix parser of ArrayExpression and ObjectExpression with TypeAnnotation Issue: I6RVS9 Tests: parse/compile/tsc/test262 Signed-off-by: songqi Change-Id: I60dc3d041607bba32878a38f882b9f703da28ba0 --- es2panda/parser/expressionParser.cpp | 53 ++- es2panda/parser/parserImpl.cpp | 7 + es2panda/parser/parserImpl.h | 2 + .../ts/test-arrow-function4-expected.txt | 1 + .../test/parser/ts/test-arrow-function4.ts | 17 + .../ts/test-arrow-function5-expected.txt | 1 + .../test/parser/ts/test-arrow-function5.ts | 17 + .../ts/test-object-expression-expected.txt | 361 ++++++++++++++++++ .../test/parser/ts/test-object-expression.ts | 20 + .../ts/test-object-expression2-expected.txt | 1 + .../test/parser/ts/test-object-expression2.ts | 19 + 11 files changed, 497 insertions(+), 2 deletions(-) create mode 100644 es2panda/test/parser/ts/test-arrow-function4-expected.txt create mode 100644 es2panda/test/parser/ts/test-arrow-function4.ts create mode 100644 es2panda/test/parser/ts/test-arrow-function5-expected.txt create mode 100644 es2panda/test/parser/ts/test-arrow-function5.ts create mode 100644 es2panda/test/parser/ts/test-object-expression-expected.txt create mode 100644 es2panda/test/parser/ts/test-object-expression.ts create mode 100644 es2panda/test/parser/ts/test-object-expression2-expected.txt create mode 100644 es2panda/test/parser/ts/test-object-expression2.ts diff --git a/es2panda/parser/expressionParser.cpp b/es2panda/parser/expressionParser.cpp index 1e2bb8c8d0..00c2459076 100644 --- a/es2panda/parser/expressionParser.cpp +++ b/es2panda/parser/expressionParser.cpp @@ -699,6 +699,49 @@ void ParserImpl::ValidateParenthesizedExpression(ir::Expression *lhsExpression) } } +void ParserImpl::ValidateParenthesizedExpressionWithoutArrow(ir::Expression *lhsExpression) +{ + switch (lhsExpression->Type()) { + case ir::AstNodeType::IDENTIFIER: { + if (lhsExpression->AsIdentifier()->TypeAnnotation() != nullptr) { + ThrowSyntaxError("'=>' expected."); + } + break; + } + case ir::AstNodeType::ARRAY_EXPRESSION: { + if (lhsExpression->AsArrayExpression()->TypeAnnotation() != nullptr) { + ThrowSyntaxError("'=>' expected."); + } + break; + } + case ir::AstNodeType::OBJECT_EXPRESSION: { + if (lhsExpression->AsObjectExpression()->TypeAnnotation() != nullptr) { + ThrowSyntaxError("'=>' expected."); + } + break; + } + case ir::AstNodeType::ASSIGNMENT_EXPRESSION: { + ValidateParenthesizedExpressionWithoutArrow(lhsExpression->AsAssignmentExpression()->Left()); + break; + } + case ir::AstNodeType::SPREAD_ELEMENT: { + if (lhsExpression->AsSpreadElement()->TypeAnnotation() != nullptr) { + ThrowSyntaxError("'=>' expected."); + } + break; + } + case ir::AstNodeType::REST_ELEMENT: { + if (lhsExpression->AsRestElement()->TypeAnnotation() != nullptr) { + ThrowSyntaxError("'=>' expected."); + } + break; + } + default: { + break; + } + } +} + ir::Expression *ParserImpl::ParseAssignmentExpression(ir::Expression *lhsExpression, ExpressionParseFlags flags) { lexer::TokenType tokenType = lexer_->GetToken().Type(); @@ -706,9 +749,15 @@ ir::Expression *ParserImpl::ParseAssignmentExpression(ir::Expression *lhsExpress if (lhsExpression->IsSequenceExpression()) { for (auto *seq : lhsExpression->AsSequenceExpression()->Sequence()) { ValidateParenthesizedExpression(seq); + if (tokenType != lexer::TokenType::PUNCTUATOR_ARROW) { + ValidateParenthesizedExpressionWithoutArrow(seq); + } } } else { ValidateParenthesizedExpression(lhsExpression); + if (tokenType != lexer::TokenType::PUNCTUATOR_ARROW) { + ValidateParenthesizedExpressionWithoutArrow(lhsExpression); + } } } @@ -1059,13 +1108,13 @@ ir::Expression *ParserImpl::ParsePrimaryExpression(ExpressionParseFlags flags) return regexpNode; } case lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET: { - return ParseArrayExpression(CarryPatternFlags(flags)); + return ParseArrayExpression(CarryAllowTsParamAndPatternFlags(flags)); } case lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS: { return ParseCoverParenthesizedExpressionAndArrowParameterList(); } case lexer::TokenType::PUNCTUATOR_LEFT_BRACE: { - return ParseObjectExpression(CarryPatternFlags(flags)); + return ParseObjectExpression(CarryAllowTsParamAndPatternFlags(flags)); } case lexer::TokenType::KEYW_FUNCTION: { return ParseFunctionExpression(); diff --git a/es2panda/parser/parserImpl.cpp b/es2panda/parser/parserImpl.cpp index 4092e21fb4..ee0c636bfa 100644 --- a/es2panda/parser/parserImpl.cpp +++ b/es2panda/parser/parserImpl.cpp @@ -252,6 +252,13 @@ ExpressionParseFlags ParserImpl::CarryPatternFlags(ExpressionParseFlags flags) ExpressionParseFlags::OBJECT_PATTERN); } +ExpressionParseFlags ParserImpl::CarryAllowTsParamAndPatternFlags(ExpressionParseFlags flags) +{ + return CarryExpressionParserFlag(flags, ExpressionParseFlags::ALLOW_TS_PARAM_TOKEN | + ExpressionParseFlags::POTENTIALLY_IN_PATTERN | + ExpressionParseFlags::OBJECT_PATTERN); +} + bool ParserImpl::CurrentLiteralIsBasicType() { ASSERT(lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT || diff --git a/es2panda/parser/parserImpl.h b/es2panda/parser/parserImpl.h index 626be76fa2..284f8755a0 100644 --- a/es2panda/parser/parserImpl.h +++ b/es2panda/parser/parserImpl.h @@ -234,6 +234,7 @@ private: bool CheckTopStatementsForRequiredDeclare(const ArenaVector &statements); static ExpressionParseFlags CarryExpressionParserFlag(ExpressionParseFlags origin, ExpressionParseFlags carry); static ExpressionParseFlags CarryPatternFlags(ExpressionParseFlags flags); + static ExpressionParseFlags CarryAllowTsParamAndPatternFlags(ExpressionParseFlags flags); bool CurrentIsBasicType(); bool CurrentLiteralIsBasicType(); static bool CheckTypeNameIsReserved(const util::StringView ¶mName); @@ -387,6 +388,7 @@ private: ir::MetaProperty *ParsePotentialNewTarget(); void CheckInvalidDestructuring(const ir::AstNode *object) const; void ValidateParenthesizedExpression(ir::Expression *lhsExpression); + void ValidateParenthesizedExpressionWithoutArrow(ir::Expression *lhsExpression); ir::Expression *ParseAssignmentExpression(ir::Expression *lhsExpression, ExpressionParseFlags flags = ExpressionParseFlags::NO_OPTS); ir::Expression *ParsePrimaryExpression(ExpressionParseFlags flags = ExpressionParseFlags::NO_OPTS); diff --git a/es2panda/test/parser/ts/test-arrow-function4-expected.txt b/es2panda/test/parser/ts/test-arrow-function4-expected.txt new file mode 100644 index 0000000000..0d9c961a14 --- /dev/null +++ b/es2panda/test/parser/ts/test-arrow-function4-expected.txt @@ -0,0 +1 @@ +SyntaxError: '=>' expected. [test-arrow-function4.ts:17:15] diff --git a/es2panda/test/parser/ts/test-arrow-function4.ts b/es2panda/test/parser/ts/test-arrow-function4.ts new file mode 100644 index 0000000000..f4dbd19b6c --- /dev/null +++ b/es2panda/test/parser/ts/test-arrow-function4.ts @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +(a:number = 1) \ No newline at end of file diff --git a/es2panda/test/parser/ts/test-arrow-function5-expected.txt b/es2panda/test/parser/ts/test-arrow-function5-expected.txt new file mode 100644 index 0000000000..8307073a82 --- /dev/null +++ b/es2panda/test/parser/ts/test-arrow-function5-expected.txt @@ -0,0 +1 @@ +SyntaxError: '=>' expected. [test-arrow-function5.ts:18:1] diff --git a/es2panda/test/parser/ts/test-arrow-function5.ts b/es2panda/test/parser/ts/test-arrow-function5.ts new file mode 100644 index 0000000000..975d958bf3 --- /dev/null +++ b/es2panda/test/parser/ts/test-arrow-function5.ts @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +(a1, ...a2:number[]) diff --git a/es2panda/test/parser/ts/test-object-expression-expected.txt b/es2panda/test/parser/ts/test-object-expression-expected.txt new file mode 100644 index 0000000000..a028b15217 --- /dev/null +++ b/es2panda/test/parser/ts/test-object-expression-expected.txt @@ -0,0 +1,361 @@ +{ + "type": "Program", + "statements": [ + { + "type": "TSInterfaceDeclaration", + "body": { + "type": "TSInterfaceBody", + "body": [ + { + "type": "TSPropertySignature", + "computed": false, + "optional": false, + "readonly": false, + "key": { + "type": "Identifier", + "name": "a", + "loc": { + "start": { + "line": 17, + "column": 15 + }, + "end": { + "line": 17, + "column": 16 + } + } + }, + "typeAnnotation": { + "type": "TSNumberKeyword", + "loc": { + "start": { + "line": 17, + "column": 18 + }, + "end": { + "line": 17, + "column": 24 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 15 + }, + "end": { + "line": 17, + "column": 26 + } + } + } + ], + "loc": { + "start": { + "line": 17, + "column": 13 + }, + "end": { + "line": 17, + "column": 26 + } + } + }, + "id": { + "type": "Identifier", + "name": "I", + "loc": { + "start": { + "line": 17, + "column": 11 + }, + "end": { + "line": 17, + "column": 12 + } + } + }, + "extends": [], + "loc": { + "start": { + "line": 17, + "column": 1 + }, + "end": { + "line": 17, + "column": 26 + } + } + }, + { + "type": "ExpressionStatement", + "expression": { + "type": "ArrowFunctionExpression", + "function": { + "type": "ScriptFunction", + "id": null, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "ObjectPattern", + "properties": [ + { + "type": "Property", + "method": false, + "shorthand": true, + "computed": false, + "key": { + "type": "Identifier", + "name": "a", + "loc": { + "start": { + "line": 19, + "column": 3 + }, + "end": { + "line": 19, + "column": 4 + } + } + }, + "value": { + "type": "Identifier", + "name": "a", + "loc": { + "start": { + "line": 19, + "column": 3 + }, + "end": { + "line": 19, + "column": 4 + } + } + }, + "kind": "init", + "loc": { + "start": { + "line": 19, + "column": 3 + }, + "end": { + "line": 19, + "column": 4 + } + } + } + ], + "typeAnnotation": { + "type": "TSTypeReference", + "typeName": { + "type": "Identifier", + "name": "I", + "loc": { + "start": { + "line": 19, + "column": 7 + }, + "end": { + "line": 19, + "column": 8 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 7 + }, + "end": { + "line": 19, + "column": 8 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 1 + }, + "end": { + "line": 19, + "column": 9 + } + } + } + ], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 19, + "column": 13 + }, + "end": { + "line": 19, + "column": 15 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 1 + }, + "end": { + "line": 19, + "column": 15 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 1 + }, + "end": { + "line": 19, + "column": 15 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 1 + }, + "end": { + "line": 19, + "column": 15 + } + } + }, + { + "type": "ExpressionStatement", + "expression": { + "type": "ArrowFunctionExpression", + "function": { + "type": "ScriptFunction", + "id": null, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "ArrayPattern", + "elements": [ + { + "type": "Identifier", + "name": "b", + "loc": { + "start": { + "line": 20, + "column": 3 + }, + "end": { + "line": 20, + "column": 4 + } + } + } + ], + "typeAnnotation": { + "type": "TSArrayType", + "elementType": { + "type": "TSNumberKeyword", + "loc": { + "start": { + "line": 20, + "column": 6 + }, + "end": { + "line": 20, + "column": 12 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 6 + }, + "end": { + "line": 20, + "column": 14 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 1 + }, + "end": { + "line": 20, + "column": 15 + } + } + } + ], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 20, + "column": 19 + }, + "end": { + "line": 20, + "column": 21 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 1 + }, + "end": { + "line": 20, + "column": 21 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 1 + }, + "end": { + "line": 20, + "column": 21 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 1 + }, + "end": { + "line": 20, + "column": 21 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 21, + "column": 1 + } + } +} diff --git a/es2panda/test/parser/ts/test-object-expression.ts b/es2panda/test/parser/ts/test-object-expression.ts new file mode 100644 index 0000000000..9649a88608 --- /dev/null +++ b/es2panda/test/parser/ts/test-object-expression.ts @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +interface I { a: number } + +({a}: I) => {} +([b]:number[]) => {} diff --git a/es2panda/test/parser/ts/test-object-expression2-expected.txt b/es2panda/test/parser/ts/test-object-expression2-expected.txt new file mode 100644 index 0000000000..e9787b480e --- /dev/null +++ b/es2panda/test/parser/ts/test-object-expression2-expected.txt @@ -0,0 +1 @@ +SyntaxError: '=>' expected. [test-object-expression2.ts:20:1] diff --git a/es2panda/test/parser/ts/test-object-expression2.ts b/es2panda/test/parser/ts/test-object-expression2.ts new file mode 100644 index 0000000000..3a918c9a90 --- /dev/null +++ b/es2panda/test/parser/ts/test-object-expression2.ts @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +interface I { a: number } + +({a}:I) -- Gitee