From a3246523a3e79e6f456f0c04fc196ae717f9b427 Mon Sep 17 00:00:00 2001 From: xucheng46 Date: Wed, 12 Oct 2022 11:46:21 +0800 Subject: [PATCH] Fix arrow functiontype and type assertion parse 1. An arrow function variable may have arrow function type, we should support this case. 2. We parser < as arrow function first, but we may throw error when we parser. So we should add try catch here. Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/I5VAG1 Test: parser tests, compier tests, test262 Signed-off-by: xucheng46 Change-Id: I1693ef99eb14c9362caa41b25f8d059a4acac7ff --- es2panda/parser/expressionParser.cpp | 7 +- es2panda/parser/parserImpl.cpp | 71 +++- es2panda/parser/parserImpl.h | 1 + .../ts/test-arrow-function1-expected.txt | 175 ++++++++ .../test/parser/ts/test-arrow-function1.ts | 17 + .../ts/test-arrow-function2-expected.txt | 378 ++++++++++++++++++ .../test/parser/ts/test-arrow-function2.ts | 21 + es2panda/test/test_tsc_ignore_list.txt | 7 - 8 files changed, 650 insertions(+), 27 deletions(-) create mode 100644 es2panda/test/parser/ts/test-arrow-function1-expected.txt create mode 100644 es2panda/test/parser/ts/test-arrow-function1.ts create mode 100644 es2panda/test/parser/ts/test-arrow-function2-expected.txt create mode 100644 es2panda/test/parser/ts/test-arrow-function2.ts diff --git a/es2panda/parser/expressionParser.cpp b/es2panda/parser/expressionParser.cpp index b772127022..bcd2a0f2c9 100644 --- a/es2panda/parser/expressionParser.cpp +++ b/es2panda/parser/expressionParser.cpp @@ -165,7 +165,12 @@ ir::Expression *ParserImpl::ParseExpression(ExpressionParseFlags flags) const auto startPos = lexer_->Save(); // TODO(rsipka): ParseTsGenericArrowFunction and ParseTsTypeAssertion might be in a common function - ir::Expression *expr = ParseTsGenericArrowFunction(); + ir::Expression *expr = nullptr; + try { + expr = ParseTsGenericArrowFunction(); + } catch ([[maybe_unused]] const class Error &e) { + expr = nullptr; + } if (expr != nullptr) { return expr; } diff --git a/es2panda/parser/parserImpl.cpp b/es2panda/parser/parserImpl.cpp index 09a79b3c26..b9e18288d4 100644 --- a/es2panda/parser/parserImpl.cpp +++ b/es2panda/parser/parserImpl.cpp @@ -1606,6 +1606,54 @@ ir::TSIntersectionType *ParserImpl::ParseTsIntersectionType(ir::Expression *type return intersectionType; } +bool ParserImpl::IsTsFunctionType() +{ + ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS); + const auto startPos = lexer_->Save(); + lexer_->NextToken(); // eat '(' + if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS || + lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD) { + lexer_->Rewind(startPos); + return true; + } + + try { + ParseModifiers(); + if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT || + (Extension() == ScriptExtension::TS && lexer_->GetToken().Type() == lexer::TokenType::KEYW_THIS)) { + lexer_->NextToken(); + } else if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET) { + ParseArrayExpression(ExpressionParseFlags::MUST_BE_PATTERN); + } else if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE) { + ParseObjectExpression(ExpressionParseFlags::MUST_BE_PATTERN | ExpressionParseFlags::OBJECT_PATTERN); + } else { + lexer_->Rewind(startPos); + return false; + } + } catch ([[maybe_unused]] const class Error &e) { + lexer_->Rewind(startPos); + return false; + } + + if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA || + lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_QUESTION_MARK || + lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON || + lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_EQUAL) { + lexer_->Rewind(startPos); + return true; + } + + if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) { + lexer_->NextToken(); // eat ')' + if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_ARROW) { + lexer_->Rewind(startPos); + return true; + } + } + lexer_->Rewind(startPos); + return false; +} + ir::Expression *ParserImpl::ParseTsParenthesizedOrFunctionType(ir::Expression *typeAnnotation, bool throwError) { if (typeAnnotation) { @@ -1635,25 +1683,16 @@ ir::Expression *ParserImpl::ParseTsParenthesizedOrFunctionType(ir::Expression *t return ParseTsFunctionType(typeStart, isConstructionType, throwError, abstractConstructor); } - const auto startPos = lexer_->Save(); + if (IsTsFunctionType()) { + return ParseTsFunctionType(typeStart, false, throwError); + } + ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS); lexer_->NextToken(); // eat '(' TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::NO_OPTS; ir::Expression *type = ParseTsTypeAnnotation(&options); - if (!type) { - lexer_->Rewind(startPos); - return ParseTsFunctionType(typeStart, false, throwError); - } - - if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA || - lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_QUESTION_MARK || - lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) { - lexer_->Rewind(startPos); - return ParseTsFunctionType(typeStart, false, throwError); - } - if (throwError && lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) { ThrowSyntaxError("')' expected"); } @@ -1661,12 +1700,6 @@ ir::Expression *ParserImpl::ParseTsParenthesizedOrFunctionType(ir::Expression *t lexer::SourcePosition endLoc = lexer_->GetToken().End(); lexer_->NextToken(); // eat ')' - if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_ARROW) { - lexer_->Rewind(startPos); - - return ParseTsFunctionType(typeStart, false, throwError); - } - auto *result = AllocNode(type); result->SetRange({typeStart, endLoc}); diff --git a/es2panda/parser/parserImpl.h b/es2panda/parser/parserImpl.h index 16d2929ce9..d1e663a1e3 100644 --- a/es2panda/parser/parserImpl.h +++ b/es2panda/parser/parserImpl.h @@ -243,6 +243,7 @@ private: ir::TSUnionType *ParseTsUnionType(ir::Expression *type, bool restrictExtends); ir::Expression *ParseTsParenthesizedOrFunctionType(ir::Expression *typeAnnotation, bool throwError); ir::TSArrayType *ParseTsArrayType(ir::Expression *elementType); + bool IsTsFunctionType(); ir::Expression *ParseTsFunctionType(lexer::SourcePosition startLoc, bool isConstructionType, bool throwError, bool abstractConstructor = false); ir::TSTypeParameter *ParseTsMappedTypeParameter(); diff --git a/es2panda/test/parser/ts/test-arrow-function1-expected.txt b/es2panda/test/parser/ts/test-arrow-function1-expected.txt new file mode 100644 index 0000000000..b853bf6b3d --- /dev/null +++ b/es2panda/test/parser/ts/test-arrow-function1-expected.txt @@ -0,0 +1,175 @@ +{ + "type": "Program", + "statements": [ + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "f", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 7 + }, + "end": { + "line": 17, + "column": 8 + } + } + }, + "init": { + "type": "ArrowFunctionExpression", + "function": { + "type": "ScriptFunction", + "id": null, + "generator": false, + "async": false, + "expression": true, + "params": [], + "returnType": { + "type": "TSParenthesizedType", + "typeAnnotation": { + "type": "TSFunctionType", + "params": [], + "returnType": { + "type": "TSNumberKeyword", + "loc": { + "start": { + "line": 17, + "column": 22 + }, + "end": { + "line": 17, + "column": 28 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 16 + }, + "end": { + "line": 17, + "column": 28 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 15 + }, + "end": { + "line": 17, + "column": 29 + } + } + }, + "body": { + "type": "ArrowFunctionExpression", + "function": { + "type": "ScriptFunction", + "id": null, + "generator": false, + "async": false, + "expression": true, + "params": [], + "body": { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 17, + "column": 39 + }, + "end": { + "line": 17, + "column": 40 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 33 + }, + "end": { + "line": 17, + "column": 40 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 33 + }, + "end": { + "line": 17, + "column": 40 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 11 + }, + "end": { + "line": 17, + "column": 40 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 11 + }, + "end": { + "line": 17, + "column": 40 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 7 + }, + "end": { + "line": 17, + "column": 40 + } + } + } + ], + "kind": "const", + "loc": { + "start": { + "line": 17, + "column": 1 + }, + "end": { + "line": 17, + "column": 41 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 18, + "column": 1 + } + } +} diff --git a/es2panda/test/parser/ts/test-arrow-function1.ts b/es2panda/test/parser/ts/test-arrow-function1.ts new file mode 100644 index 0000000000..36780a4d9a --- /dev/null +++ b/es2panda/test/parser/ts/test-arrow-function1.ts @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2022 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. + */ + + +const f = (): (() => number) => () => 1; diff --git a/es2panda/test/parser/ts/test-arrow-function2-expected.txt b/es2panda/test/parser/ts/test-arrow-function2-expected.txt new file mode 100644 index 0000000000..d1b0f26a3f --- /dev/null +++ b/es2panda/test/parser/ts/test-arrow-function2-expected.txt @@ -0,0 +1,378 @@ +{ + "type": "Program", + "statements": [ + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "C", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 7 + }, + "end": { + "line": 17, + "column": 8 + } + } + }, + "superClass": null, + "implements": [], + "constructor": { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": null, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 1 + }, + "end": { + "line": 19, + "column": 2 + } + } + }, + "body": [ + { + "type": "ClassProperty", + "key": { + "type": "Identifier", + "name": "a", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 5 + }, + "end": { + "line": 18, + "column": 6 + } + } + }, + "value": { + "type": "NumberLiteral", + "value": 0, + "loc": { + "start": { + "line": 18, + "column": 18 + }, + "end": { + "line": 18, + "column": 19 + } + } + }, + "static": false, + "readonly": false, + "declare": false, + "optional": false, + "computed": false, + "typeAnnotation": { + "type": "TSNumberKeyword", + "loc": { + "start": { + "line": 18, + "column": 9 + }, + "end": { + "line": 18, + "column": 15 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 5 + }, + "end": { + "line": 18, + "column": 19 + } + } + } + ], + "indexSignatures": [], + "loc": { + "start": { + "line": 17, + "column": 9 + }, + "end": { + "line": 19, + "column": 2 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 1 + }, + "end": { + "line": 19, + "column": 2 + } + } + }, + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "b", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 5 + }, + "end": { + "line": 20, + "column": 6 + } + } + }, + "init": { + "type": "ArrowFunctionExpression", + "function": { + "type": "ScriptFunction", + "id": null, + "generator": false, + "async": false, + "expression": true, + "params": [], + "body": { + "type": "TSTypeAssertion", + "typeAnnotation": { + "type": "TSTypeReference", + "typeName": { + "type": "Identifier", + "name": "C", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 18 + }, + "end": { + "line": 20, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 18 + }, + "end": { + "line": 20, + "column": 19 + } + } + }, + "expression": { + "type": "ObjectExpression", + "properties": [ + { + "type": "Property", + "method": false, + "shorthand": false, + "computed": false, + "key": { + "type": "Identifier", + "name": "a", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 23 + }, + "end": { + "line": 20, + "column": 24 + } + } + }, + "value": { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 20, + "column": 26 + }, + "end": { + "line": 20, + "column": 27 + } + } + }, + "kind": "init", + "loc": { + "start": { + "line": 20, + "column": 23 + }, + "end": { + "line": 20, + "column": 27 + } + } + } + ], + "loc": { + "start": { + "line": 20, + "column": 20 + }, + "end": { + "line": 20, + "column": 30 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 15 + }, + "end": { + "line": 20, + "column": 32 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 9 + }, + "end": { + "line": 20, + "column": 32 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 9 + }, + "end": { + "line": 20, + "column": 32 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 5 + }, + "end": { + "line": 20, + "column": 32 + } + } + } + ], + "kind": "var", + "loc": { + "start": { + "line": 20, + "column": 1 + }, + "end": { + "line": 20, + "column": 33 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 22, + "column": 1 + } + } +} diff --git a/es2panda/test/parser/ts/test-arrow-function2.ts b/es2panda/test/parser/ts/test-arrow-function2.ts new file mode 100644 index 0000000000..d74b837286 --- /dev/null +++ b/es2panda/test/parser/ts/test-arrow-function2.ts @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2022 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. + */ + + +class C { + a : number = 0; +} +var b = () => ((({ a: 1 }))); + diff --git a/es2panda/test/test_tsc_ignore_list.txt b/es2panda/test/test_tsc_ignore_list.txt index ec89e64c81..850a0347d4 100644 --- a/es2panda/test/test_tsc_ignore_list.txt +++ b/es2panda/test/test_tsc_ignore_list.txt @@ -1,9 +1,6 @@ es2panda/test/TypeScript/tests/cases/compiler/ambientClassOverloadForFunction.ts -es2panda/test/TypeScript/tests/cases/compiler/arrowFunctionWithObjectLiteralBody5.ts -es2panda/test/TypeScript/tests/cases/compiler/arrowFunctionWithObjectLiteralBody6.ts es2panda/test/TypeScript/tests/cases/compiler/assertionFunctionsCanNarrowByDiscriminant.ts es2panda/test/TypeScript/tests/cases/compiler/bom-utf16be.ts -es2panda/test/TypeScript/tests/cases/compiler/castTest.ts es2panda/test/TypeScript/tests/cases/compiler/classFunctionMerging.ts es2panda/test/TypeScript/tests/cases/compiler/collisionArgumentsInType.ts es2panda/test/TypeScript/tests/cases/compiler/collisionArgumentsInterfaceMembers.ts @@ -24,7 +21,6 @@ es2panda/test/TypeScript/tests/cases/compiler/exportRedeclarationTypeAliases.ts es2panda/test/TypeScript/tests/cases/compiler/exportSpecifierAndExportedMemberDeclaration.ts es2panda/test/TypeScript/tests/cases/compiler/fileWithNextLine2.ts es2panda/test/TypeScript/tests/cases/compiler/genericRecursiveImplicitConstructorErrors2.ts -es2panda/test/TypeScript/tests/cases/compiler/getterSetterNonAccessor.ts es2panda/test/TypeScript/tests/cases/compiler/globalIsContextualKeyword.ts es2panda/test/TypeScript/tests/cases/compiler/implementsInClassExpression.ts es2panda/test/TypeScript/tests/cases/compiler/inferenceErasedSignatures.ts @@ -36,11 +32,8 @@ es2panda/test/TypeScript/tests/cases/compiler/letInVarDeclOfForIn_ES6.ts es2panda/test/TypeScript/tests/cases/compiler/letInVarDeclOfForOf_ES5.ts es2panda/test/TypeScript/tests/cases/compiler/letInVarDeclOfForOf_ES6.ts es2panda/test/TypeScript/tests/cases/compiler/mutuallyRecursiveInterfaceDeclaration.ts -es2panda/test/TypeScript/tests/cases/compiler/objectLitGetterSetter.ts -es2panda/test/TypeScript/tests/cases/compiler/overloadResolutionOverNonCTObjectLit.ts es2panda/test/TypeScript/tests/cases/compiler/overloadedConstructorFixesInferencesAppropriately.ts es2panda/test/TypeScript/tests/cases/compiler/parameterInitializerBeforeDestructuringEmit.ts -es2panda/test/TypeScript/tests/cases/compiler/parseArrowFunctionWithFunctionReturnType.ts es2panda/test/TypeScript/tests/cases/compiler/parseEntityNameWithReservedWord.ts es2panda/test/TypeScript/tests/cases/compiler/shebang.ts es2panda/test/TypeScript/tests/cases/compiler/sigantureIsSubTypeIfTheyAreIdentical.ts -- Gitee