diff --git a/ets2panda/checker/ETSchecker.h b/ets2panda/checker/ETSchecker.h index de4af4f3f8039f0d8eadd6f3c2efb41e56965eed..67ab7afd77226602a07514a1fa00f9febb6a8a93 100644 --- a/ets2panda/checker/ETSchecker.h +++ b/ets2panda/checker/ETSchecker.h @@ -275,6 +275,10 @@ public: ArenaVector *target); void CheckCyclicConstructorCall(Signature *signature); void CheckAnnotationReference(const ir::MemberExpression *memberExpr, const varbinder::LocalVariable *prop); + std::vector HandlePropertyResolution(varbinder::LocalVariable *const prop, + ir::MemberExpression *const memberExpr, + varbinder::Variable *const globalFunctionVar, + PropertySearchFlags searchFlag); std::vector ResolveMemberReference(const ir::MemberExpression *memberExpr, const ETSObjectType *target); varbinder::LocalVariable *ResolveOverloadReference(const ir::Identifier *ident, ETSObjectType *objType, diff --git a/ets2panda/checker/ets/object.cpp b/ets2panda/checker/ets/object.cpp index 03ff57a90ca1cd324ba4205f0098534959b64592..f0869bbb568a3387e1809b3878506e8c004c1cf4 100644 --- a/ets2panda/checker/ets/object.cpp +++ b/ets2panda/checker/ets/object.cpp @@ -2351,12 +2351,28 @@ void ETSChecker::CheckAnnotationReference(const ir::MemberExpression *memberExpr } } +std::vector ETSChecker::HandlePropertyResolution(varbinder::LocalVariable *const prop, + ir::MemberExpression *const memberExpr, + varbinder::Variable *const globalFunctionVar, + PropertySearchFlags searchFlag) +{ + std::vector resolveRes {}; + + if (prop != nullptr && IsVariableGetterSetter(prop) && + ((searchFlag & PropertySearchFlags::IS_GETTER) != 0 || (searchFlag & PropertySearchFlags::IS_SETTER) != 0)) { + // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) + return ValidateAccessor(memberExpr, prop, globalFunctionVar, searchFlag); + } + if (prop != nullptr) { + resolveRes.emplace_back(ProgramAllocator()->New(prop, ResolvedKind::PROPERTY)); + } + return resolveRes; +} + // NOLINTNEXTLINE(readability-function-size) std::vector ETSChecker::ResolveMemberReference(const ir::MemberExpression *const memberExpr, const ETSObjectType *const target) { - std::vector resolveRes {}; - if (target->GetDeclNode() != nullptr && target->GetDeclNode()->IsClassDefinition() && !target->GetDeclNode()->AsClassDefinition()->IsClassDefinitionChecked()) { // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) @@ -2376,10 +2392,9 @@ std::vector ETSChecker::ResolveMemberReference(const ir::Member if (targetRef != nullptr && targetRef->HasFlag(varbinder::VariableFlags::CLASS_OR_INTERFACE)) { // Note: extension function only for instance. ValidateResolvedProperty(&prop, target, memberExpr->Property()->AsIdentifier(), searchFlag); - if (prop != nullptr) { - resolveRes.emplace_back(ProgramAllocator()->New(prop, ResolvedKind::PROPERTY)); - } - return resolveRes; + // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) + return HandlePropertyResolution(prop, const_cast(memberExpr), globalFunctionVar, + searchFlag); } if (HasStatus(CheckerStatus::IN_GETTER)) { @@ -2393,6 +2408,7 @@ std::vector ETSChecker::ResolveMemberReference(const ir::Member return ValidateAccessor(const_cast(memberExpr), prop, globalFunctionVar, searchFlag); } + std::vector resolveRes {}; if (globalFunctionVar != nullptr) { ResolvedKind resolvedKind = DecideResolvedKind(globalFunctionVar->TsType()); if (IsExtensionAccessorCallUse(this, memberExpr, resolvedKind)) { diff --git a/ets2panda/test/ast/compiler/ets/missing_CTE_access_private.ets b/ets2panda/test/ast/compiler/ets/missing_CTE_access_private.ets new file mode 100644 index 0000000000000000000000000000000000000000..d37040e3380b5cb6f0b29678d209f0b1a020e71c --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/missing_CTE_access_private.ets @@ -0,0 +1,30 @@ +/* + * 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 A { + private static _val: number = 0; + private static get val(): number { return A._val; } + private static set val(i: number) { + A._val = i + } +} + +function main(): void { + let j: number = A.val + A.val = 1 +} + +/* @@? 25:23 Error TypeError: Signature val(): Double is not visible here. */ +/* @@? 26:7 Error TypeError: Signature val(i: Double): void is not visible here. */ diff --git a/ets2panda/test/ast/compiler/ets/missing_CTE_access_protected.ets b/ets2panda/test/ast/compiler/ets/missing_CTE_access_protected.ets new file mode 100644 index 0000000000000000000000000000000000000000..fb1fd6164735e48aad35f2fcaf14f8823c2493cd --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/missing_CTE_access_protected.ets @@ -0,0 +1,30 @@ +/* + * 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 A { + protected static _val: number = 0; + protected static get val(): number { return A._val; } + protected static set val(i: number) { + A._val = i + } +} + +function main(): void { + let j: number = A.val + A.val = 1 +} + +/* @@? 25:23 Error TypeError: Signature val(): Double is not visible here. */ +/* @@? 26:7 Error TypeError: Signature val(i: Double): void is not visible here. */