From eb9099074bd57f609f962ee3c8955fb1ebe9576e Mon Sep 17 00:00:00 2001 From: yanpeng51 Date: Fri, 27 Jun 2025 15:46:46 +0800 Subject: [PATCH] "set all Mandatory attribute" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Issue:[新需求]:https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICIB78 Signed-off-by: yanpeng51 --- ets2panda/checker/ETSAnalyzer.cpp | 47 +++++++++++++++++++ ets2panda/checker/ETSAnalyzer.h | 4 ++ .../required_attribute_init.ets | 26 ++++++++++ .../test/runtime/ets/objectLiteral-2.ets | 2 +- ets2panda/util/diagnostic/semantic.yaml | 4 ++ 5 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 ets2panda/test/ast/compiler/ets/required_attribute_init/required_attribute_init.ets diff --git a/ets2panda/checker/ETSAnalyzer.cpp b/ets2panda/checker/ETSAnalyzer.cpp index 951f221722..438beebcbf 100644 --- a/ets2panda/checker/ETSAnalyzer.cpp +++ b/ets2panda/checker/ETSAnalyzer.cpp @@ -2346,6 +2346,12 @@ void ETSAnalyzer::CheckObjectExprProps(const ir::ObjectExpression *expr, ETSChecker *checker = GetETSChecker(); checker::ETSObjectType *objType = objectTypeForProperties; + std::string requiredName = ""; + if (!CheckRequiredAttributeInit(expr, objectTypeForProperties, requiredName)) { + checker->LogError(diagnostic::MANDATORY_ATTRIBUTE_MISS, {requiredName}, expr->Start()); + return; + } + for (ir::Expression *propExpr : expr->Properties()) { if (!propExpr->IsProperty()) { checker->LogError(diagnostic::OBJECT_LITERAL_NOT_KV, {}, expr->Start()); @@ -2393,6 +2399,47 @@ void ETSAnalyzer::CheckObjectExprProps(const ir::ObjectExpression *expr, } } +bool ETSAnalyzer::CheckRequiredAttributeInit(const ir::ObjectExpression *expr, + checker::ETSObjectType *objectTypeForProperties, + std::string &requiredName) const +{ + if (expr->Properties().empty()) { + return true; + } + + ETSChecker *checker = GetETSChecker(); + checker::ETSObjectType *objType = objectTypeForProperties; + + auto allProperties = objType->GetAllProperties(); + std::unordered_set literalProperties; + + for (ir::Expression *propExpr : expr->Properties()) { + if (propExpr->IsProperty()) { + ir::Expression *key = propExpr->AsProperty()->Key(); + if (auto optPname = GetPropertyNameFromKey(key); optPname.has_value()) { + literalProperties.insert(std::string(optPname.value().Utf8())); + } + } + } + + for (auto *property : allProperties) { + if (!checker->GetTypeOfVariable(property)->IsETSMethodType()) { + std::string propName(property->Name().Utf8()); + auto *propertyType = checker->GetTypeOfVariable(property); + bool isInLiteral = literalProperties.find(propName) != literalProperties.end(); + if (!isInLiteral) { + bool isOptional = IsPropertyOptional(property, propertyType); + bool hasDefaultValue = HasPropertyDefaultValue(property); + if (!isOptional && !hasDefaultValue) { + requiredName = propName; + return false; // 必需属性未提供且无默认值 + } + } + } + } + return true; +} + checker::Type *ETSAnalyzer::Check(ir::OpaqueTypeNode *expr) const { return expr->TsType(); diff --git a/ets2panda/checker/ETSAnalyzer.h b/ets2panda/checker/ETSAnalyzer.h index c4a0d46ba6..88d90ec898 100644 --- a/ets2panda/checker/ETSAnalyzer.h +++ b/ets2panda/checker/ETSAnalyzer.h @@ -83,6 +83,10 @@ private: checker->LogError(diagnostic::VOID_VALUE, {}, expr->Start()); } } + + bool CheckRequiredAttributeInit(const ir::ObjectExpression *expr, + checker::ETSObjectType *objectTypeForProperties, std::string &requiredName) const; + mutable std::vector catchParamStack_ {}; }; diff --git a/ets2panda/test/ast/compiler/ets/required_attribute_init/required_attribute_init.ets b/ets2panda/test/ast/compiler/ets/required_attribute_init/required_attribute_init.ets new file mode 100644 index 0000000000..bdddf2579c --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/required_attribute_init/required_attribute_init.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. + */ + +interface Person { + age :number; + sex?:string; +} + +let a:Person = {sex:"男"} as Person + +function main () +{ + console.log(a.sex); +} diff --git a/ets2panda/test/runtime/ets/objectLiteral-2.ets b/ets2panda/test/runtime/ets/objectLiteral-2.ets index f11bc578c6..4ecb173c69 100644 --- a/ets2panda/test/runtime/ets/objectLiteral-2.ets +++ b/ets2panda/test/runtime/ets/objectLiteral-2.ets @@ -54,7 +54,7 @@ function main(): int { test(c, 5, 6) test({ // function argument - x: 3, + x: 3, iv: {v: 0} }, 3, 0) test(returnC(), 99, 77) diff --git a/ets2panda/util/diagnostic/semantic.yaml b/ets2panda/util/diagnostic/semantic.yaml index 4c4ae2e28e..35164d73c8 100644 --- a/ets2panda/util/diagnostic/semantic.yaml +++ b/ets2panda/util/diagnostic/semantic.yaml @@ -1514,3 +1514,7 @@ semantic: - name: DYMANIC_INIT_WITH_OBJEXPR id: 382 message: "Dymanic Type {} cannot be initialize with an object expression" + +- name: MANDATORY_ATTRIBUTE_MISS + id: 383 + message: "The name '{}' attribute is mandatory, lacks explicit initialization, and has no default value." -- Gitee