diff --git a/ets2panda/parser/ETSparser.cpp b/ets2panda/parser/ETSparser.cpp index 7847a5b8999cd2fe40f0282da0925000f4794c06..f08fe9a042e4dac3b271e6ec79306ed0282611eb 100644 --- a/ets2panda/parser/ETSparser.cpp +++ b/ets2panda/parser/ETSparser.cpp @@ -2132,6 +2132,8 @@ ir::AstNode *ETSParser::ParseAmbientSignature(const lexer::SourcePosition &start ir::DummyNodeFlag::INDEXER, typeAnno); ES2PANDA_ASSERT(dummyNode != nullptr); dummyNode->SetRange({startPos, Lexer()->GetToken().End()}); + Lexer()->NextToken(); // eat return type + ambientIndexerSeen_ = true; return dummyNode; } diff --git a/ets2panda/parser/ETSparser.h b/ets2panda/parser/ETSparser.h index bd8fcb7b1cf5b5fb2e3d2ae40926037f3d34e8af..c2db7ca3cfb1480f7a634aaf1879347d7726a26e 100644 --- a/ets2panda/parser/ETSparser.h +++ b/ets2panda/parser/ETSparser.h @@ -180,6 +180,7 @@ private: ArenaVector ParseTopLevelStatements(); ir::AstNode *HandleAmbientDeclaration(ir::ModifierFlags &memberModifiers, const std::function &parseClassMethod); + ir::Statement *CheckDuplicateAmbientIndex(bool ambientIndexerSeen, const lexer::SourcePosition &startPos); static bool IsClassMethodModifier(lexer::TokenType type) noexcept; #ifdef USE_FTW @@ -458,6 +459,7 @@ private: parser::Program *globalProgram_; std::vector insertingNodes_ {}; std::unique_ptr importPathManager_ {nullptr}; + bool ambientIndexerSeen_ {false}; }; class ExternalSourceParser { diff --git a/ets2panda/parser/ETSparserClasses.cpp b/ets2panda/parser/ETSparserClasses.cpp index 6341e82096dcc4f051cd8e729b45345b9088c7c8..03d4779e7b3bc254a934ddcbc635317cdb06b5e8 100644 --- a/ets2panda/parser/ETSparserClasses.cpp +++ b/ets2panda/parser/ETSparserClasses.cpp @@ -332,12 +332,24 @@ ir::AstNode *ETSParser::HandleAmbientDeclaration(ir::ModifierFlags &memberModifi return parseClassMethod(memberName); } } else { + if (auto *dup = CheckDuplicateAmbientIndex(ambientIndexerSeen_, startPosAmbient)) { + return dup; + } return ParseAmbientSignature(startPosAmbient); } } return nullptr; } +ir::Statement *ETSParser::CheckDuplicateAmbientIndex(bool ambientIndexerSeen, const lexer::SourcePosition &startPos) +{ + if (!ambientIndexerSeen) { + return nullptr; + } + LogError(diagnostic::DUPLICATE_INDEX_SIGNATURE, {}, startPos); + return AllocBrokenStatement(startPos); +} + // Helper method for ir::ModifierFlags ETSParser::ParseClassMethodModifiers(bool seenStatic) ir::ModifierFlags ETSParser::ParseClassMethodModifierFlag() { @@ -1056,6 +1068,7 @@ ir::AstNode *ETSParser::ParseInterfaceField() fieldModifiers |= ir::ModifierFlags::DECLARE; auto property = HandleAmbientDeclaration(fieldModifiers, parseClassMethod); if (property != nullptr) { + ambientIndexerSeen_ = true; return property; } } diff --git a/ets2panda/test/parser/ets/interface_mixed_literals.ets b/ets2panda/test/parser/ets/interface_mixed_literals.ets new file mode 100644 index 0000000000000000000000000000000000000000..675c6ab62b68594d107f0a6e514e75c20758ac86 --- /dev/null +++ b/ets2panda/test/parser/ets/interface_mixed_literals.ets @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2024-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. + */ + + declare interface Z { + [name: string]: string; + [456: number]: boolean; +} + +/* @@? 17:12 Error SyntaxError: Index type must be number in index signature. */ +/* @@? 18:5 Error TypeError: Duplicate index signature in interface */ +/* @@? 18:6 Error SyntaxError: Unexpected token, expected ','. */ +/* @@? 18:6 Error SyntaxError: Unexpected token, expected 'private' or identifier. */ +/* @@? 18:9 Error SyntaxError: Identifier expected. */ +/* @@? 18:9 Error SyntaxError: Unexpected token, expected ','. */ +/* @@? 18:9 Error SyntaxError: Unexpected token, expected 'private' or identifier. */ +/* @@? 18:17 Error SyntaxError: Interface fields must have type annotation. */ +/* @@? 18:18 Error SyntaxError: Invalid Type. */ +/* @@? 18:18 Error SyntaxError: Unexpected token, expected ','. */ +/* @@? 18:18 Error SyntaxError: Unexpected token, expected 'private' or identifier. */ +/* @@? 18:20 Error SyntaxError: Identifier expected. */ +/* @@? 18:20 Error SyntaxError: Unexpected token, expected ','. */ +/* @@? 18:20 Error SyntaxError: Unexpected token, expected 'private' or identifier. */ +/* @@? 18:27 Error SyntaxError: Identifier expected. */ \ No newline at end of file diff --git a/ets2panda/util/diagnostic/semantic.yaml b/ets2panda/util/diagnostic/semantic.yaml index cd59e9ec84e35644e64de3f533c63c5de23c3e9b..3be121909b5f05ade969c71ffdc29b341e09ab3a 100644 --- a/ets2panda/util/diagnostic/semantic.yaml +++ b/ets2panda/util/diagnostic/semantic.yaml @@ -395,6 +395,10 @@ semantic: id: 219 message: "Duplicate accessor definition" +- name: DUPLICATE_INDEX_SIGNATURE + id: 392 + message: "Duplicate index signature in interface" + - name: DUPLICATE_OVERLOADED_NAME id: 385 message: "Duplicate overloaded method." @@ -1601,7 +1605,6 @@ semantic: id: 347 message: "Wrong operand type for unary expression" - graveyard: - 8 - 29