diff --git a/es2panda/parser/expressionParser.cpp b/es2panda/parser/expressionParser.cpp index b772127022a3471c8b77aa53c0caf72430813be3..bcd2a0f2c9e13ebf2cbf7d619dbaa29ae97b52c5 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 09a79b3c26effb24a1eabadad2768182b09abe90..b9e18288d40e5dd7499f296f24c970a287cb4092 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 16d2929ce91b2b3749cdb27b10cfcb10e9f4d99d..d1e663a1e397a3530815dbe95119e24cf399232c 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 0000000000000000000000000000000000000000..b853bf6b3dcd83e767ebe4066f3e9ce3f26763cb --- /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 0000000000000000000000000000000000000000..36780a4d9a151fb38eb1741da7795e623de566af --- /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 0000000000000000000000000000000000000000..d1b0f26a3fca162969100cc61219404c6b2d0009 --- /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 0000000000000000000000000000000000000000..d74b83728600dca478cdc507d1bde9905cca9807 --- /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 ec89e64c815b7db9ddbfb7968fe7909836f71fc1..850a0347d4643148516e712c27b475af4b8cb41f 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