diff --git a/ets2panda/parser/ETSparser.h b/ets2panda/parser/ETSparser.h index 738bc9f53f929088ad83aeee77a2e4335543c760..01cca2560c3e5b933800b7c2fb03d74ccd3fc0fb 100644 --- a/ets2panda/parser/ETSparser.h +++ b/ets2panda/parser/ETSparser.h @@ -440,6 +440,7 @@ private: // NOLINTNEXTLINE(google-default-arguments) ir::Expression *ParseExpression(ExpressionParseFlags flags = ExpressionParseFlags::NO_OPTS) override; ir::Expression *ParseExpressionOrTypeAnnotation(lexer::TokenType type, ExpressionParseFlags flags) override; + void ValidateKeywordIn(); ir::Expression *ParsePotentialExpressionSequence(ir::Expression *expr, ExpressionParseFlags flags) override; ir::Expression *ParseGenericLambdaOrTypeAssertion(); ir::ModifierFlags ParseTypeVarianceModifier(TypeAnnotationParsingOptions *const options); diff --git a/ets2panda/parser/ETSparserExpressions.cpp b/ets2panda/parser/ETSparserExpressions.cpp index 8d990614716770414f54c64351825353890d6cd5..938d3be96065bd069018e891191296cfab13d786 100644 --- a/ets2panda/parser/ETSparserExpressions.cpp +++ b/ets2panda/parser/ETSparserExpressions.cpp @@ -839,6 +839,21 @@ ir::Expression *ETSParser::ParseGenericLambdaOrTypeAssertion() return AllocBrokenExpression(lexer::SourceRange {start, Lexer()->GetToken().End()}); } +void ETSParser::ValidateKeywordIn() +{ + if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_IN) { + LogError(diagnostic::ERROR_ARKTS_NO_IN_OPERATOR); + Lexer()->NextToken(); // eat 'in' + if (auto const tokenType = Lexer()->GetToken().Type(); tokenType == lexer::TokenType::PUNCTUATOR_LEFT_BRACE) { + ParseObjectExpression(); + } else if (tokenType == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET) { + ParseArrayExpression(ExpressionParseFlags::NO_OPTS); + } else { + Lexer()->NextToken(); + } + } +} + // NOLINTNEXTLINE(google-default-arguments) ir::Expression *ETSParser::ParseExpression(ExpressionParseFlags flags) { @@ -866,6 +881,7 @@ ir::Expression *ETSParser::ParseExpression(ExpressionParseFlags flags) } ir::Expression *unaryExpressionNode = ParseUnaryOrPrefixUpdateExpression(flags); + ValidateKeywordIn(); if ((flags & ExpressionParseFlags::INSTANCEOF) != 0) { ValidateInstanceOfExpression(unaryExpressionNode); } @@ -873,12 +889,9 @@ ir::Expression *ETSParser::ParseExpression(ExpressionParseFlags flags) ir::Expression *assignmentExpression = ParseAssignmentExpression(unaryExpressionNode, flags); ApplyAnnotationsToNode(assignmentExpression, std::move(annotations), start); - if (Lexer()->GetToken().NewLine()) { - return assignmentExpression; - } - - if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA && - (flags & ExpressionParseFlags::ACCEPT_COMMA) != 0U && (flags & ExpressionParseFlags::IN_FOR) != 0U) { + if (!Lexer()->GetToken().NewLine() && + (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA && + (flags & ExpressionParseFlags::ACCEPT_COMMA) != 0U && (flags & ExpressionParseFlags::IN_FOR) != 0U)) { return ParseSequenceExpression(assignmentExpression, (flags & ExpressionParseFlags::ACCEPT_REST) != 0U); } diff --git a/ets2panda/test/ast/compiler/ets/noInOperator.ets b/ets2panda/test/ast/compiler/ets/noInOperator.ets new file mode 100644 index 0000000000000000000000000000000000000000..27aa68a1ccfc0200e99df36f86cc1f831246ce6c --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/noInOperator.ets @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2025 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 Person { + name: string = "" +} +let p = new Person() +let b = "name" /* @@ label1 */in p +let c = "name" /* @@ label2 */in {name: 1, some: 2} +let d = 2 /* @@ label3 */in [44, 55] + +/* @@@ label1 Error SyntaxError: 'in' operator is not supported. Use 'instanceof' operator to check whether an object is the instance of a class that contains the necessary class member. */ +/* @@@ label2 Error SyntaxError: 'in' operator is not supported. Use 'instanceof' operator to check whether an object is the instance of a class that contains the necessary class member. */ +/* @@@ label3 Error SyntaxError: 'in' operator is not supported. Use 'instanceof' operator to check whether an object is the instance of a class that contains the necessary class member. */ diff --git a/ets2panda/test/ast/parser/ets/FixedArray/InvalidStatements3.ets b/ets2panda/test/ast/parser/ets/FixedArray/InvalidStatements3.ets index ef5fb160524f486bcf001ae132a3c0868e648940..a285e8f19e9c99873b23b759129755562c577065 100644 --- a/ets2panda/test/ast/parser/ets/FixedArray/InvalidStatements3.ets +++ b/ets2panda/test/ast/parser/ets/FixedArray/InvalidStatements3.ets @@ -59,5 +59,6 @@ for (let i = 1 in [0, 1, 2]) {} /* @@? 38:5 Error SyntaxError: Unexpected token 'private'. */ /* @@? 38:13 Error SyntaxError: Unexpected token '@'. */ /* @@? 38:14 Error TypeError: Cannot find type 'annotate'. */ -/* @@? 42:16 Error SyntaxError: for-in loop variable declaration may not have an initializer. */ -/* @@? 42:16 Error SyntaxError: 'for ... in' loop is not supported, please use regular 'for' or 'for ... of ...' loop to iterate through arrays and iterable objects. */ +/* @@? 42:16 Error SyntaxError: 'in' operator is not supported. Use 'instanceof' operator to check whether an object is the instance of a class that contains the necessary class member. */ +/* @@? 42:28 Error SyntaxError: Expected ';', got ')'. */ +/* @@? 42:28 Error SyntaxError: Invalid left-hand side in 'For[In/Of]Statement'. */ diff --git a/ets2panda/test/ast/parser/ets/InvalidStatements3.ets b/ets2panda/test/ast/parser/ets/InvalidStatements3.ets index 308ab7542c9dc3dca8077fb5dfc665065e625eba..b22649104ee05fa1d0b541ad3ae1108aaef69abd 100644 --- a/ets2panda/test/ast/parser/ets/InvalidStatements3.ets +++ b/ets2panda/test/ast/parser/ets/InvalidStatements3.ets @@ -59,5 +59,6 @@ for (let i = 1 in [0, 1, 2]) {} /* @@? 38:5 Error SyntaxError: Unexpected token 'private'. */ /* @@? 38:13 Error SyntaxError: Unexpected token '@'. */ /* @@? 38:14 Error TypeError: Cannot find type 'annotate'. */ -/* @@? 42:16 Error SyntaxError: for-in loop variable declaration may not have an initializer. */ -/* @@? 42:16 Error SyntaxError: 'for ... in' loop is not supported, please use regular 'for' or 'for ... of ...' loop to iterate through arrays and iterable objects. */ +/* @@? 42:16 Error SyntaxError: 'in' operator is not supported. Use 'instanceof' operator to check whether an object is the instance of a class that contains the necessary class member. */ +/* @@? 42:28 Error SyntaxError: Expected ';', got ')'. */ +/* @@? 42:28 Error SyntaxError: Invalid left-hand side in 'For[In/Of]Statement'. */ diff --git a/ets2panda/util/diagnostic/syntax.yaml b/ets2panda/util/diagnostic/syntax.yaml index 6665016a2ed312d820e61ea8c4e508069c15ce8b..3f964a674677cedc1d1b730152e919f91407ae41 100644 --- a/ets2panda/util/diagnostic/syntax.yaml +++ b/ets2panda/util/diagnostic/syntax.yaml @@ -242,6 +242,11 @@ syntax: id: 81515 message: "Constructor signatures are not supported in interfaces, use methods instead!" +- name: ERROR_ARKTS_NO_IN_OPERATOR + id: 105822 + message: "'in' operator is not supported. Use 'instanceof' operator to check whether an object is the instance of a class + that contains the necessary class member." + - name: ERROR_ARKTS_NO_OBJ_LITERAL_TO_DECL_TYPE id: 177354 message: "Using object literals to declare types in place is not supported. Please declare types and interfaces explicitly!"