diff --git a/ets2panda/checker/ETSchecker.h b/ets2panda/checker/ETSchecker.h index 8e7db4fb3ccc3aa5041cca4dcb9f7e5533bad6e9..6f141a39ffa061a42a9cfd95b796116efe1bd678 100644 --- a/ets2panda/checker/ETSchecker.h +++ b/ets2panda/checker/ETSchecker.h @@ -1019,7 +1019,7 @@ private: PropertySearchFlags GetInitialSearchFlags(const ir::MemberExpression *memberExpr); Type *GetTypeOfSetterGetter([[maybe_unused]] varbinder::Variable *var); ETSFunctionType *CreateSyntheticTypeFromOverload(varbinder::Variable *const var); - void IterateInVariableContext([[maybe_unused]] varbinder::Variable *const var); + SavedCheckerContext CreateSavedCheckerContext(varbinder::Variable *const var); bool CheckInit(ir::Identifier *ident, ir::TypeNode *typeAnnotation, ir::Expression *init, checker::Type *annotationType, varbinder::Variable *const bindingVar); void CheckItemCasesConstant(ArenaVector const &cases); diff --git a/ets2panda/checker/ets/helpers.cpp b/ets2panda/checker/ets/helpers.cpp index 66b876183569d8533df241ea89e09c9b3215bacb..5d71f86ed918f2061c5a7e5506f764bf6669fca8 100644 --- a/ets2panda/checker/ets/helpers.cpp +++ b/ets2panda/checker/ets/helpers.cpp @@ -3016,7 +3016,7 @@ void ETSChecker::GenerateGetterSetterPropertyAndMethod(ir::ClassProperty *origin const auto &name = getter->Key()->AsIdentifier()->Name(); ir::MethodDefinition *setter = - !classProp->IsConst() + !classProp->IsConst() && !classProp->IsReadonly() // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) ? GenerateDefaultGetterSetter(interfaceProp, classProp, Scope()->AsClassScope(), true, this) : nullptr; diff --git a/ets2panda/checker/ets/typeCheckingHelpers.cpp b/ets2panda/checker/ets/typeCheckingHelpers.cpp index 6496cdb8ce75eb3a25d6fc59349a8ce4840f40fc..efc0117053a74d79ea0882c430de40032966c0c4 100644 --- a/ets2panda/checker/ets/typeCheckingHelpers.cpp +++ b/ets2panda/checker/ets/typeCheckingHelpers.cpp @@ -14,6 +14,7 @@ */ #include "checker/checker.h" +#include "checker/checkerContext.h" #include "checker/ets/wideningConverter.h" #include "checker/types/globalTypesHolder.h" #include "checker/types/gradualType.h" @@ -510,38 +511,36 @@ ETSFunctionType *ETSChecker::CreateSyntheticTypeFromOverload(varbinder::Variable return syntheticFunctionType; } -void ETSChecker::IterateInVariableContext(varbinder::Variable *const var) +SavedCheckerContext ETSChecker::CreateSavedCheckerContext(varbinder::Variable *const var) { // Before computing the given variables type, we have to make a new checker context frame so that the checking is // done in the proper context, and have to enter the scope where the given variable is declared, so reference // resolution works properly - auto *iter = var->Declaration()->Node()->Parent(); - while (iter != nullptr) { + auto constexpr STATUS = CheckerStatus::NO_OPTS; + for (auto *iter = var->Declaration()->Node()->Parent(); iter != nullptr; iter = iter->Parent()) { if (iter->IsMethodDefinition()) { auto *methodDef = iter->AsMethodDefinition(); ES2PANDA_ASSERT(methodDef->TsType()); auto *func = methodDef->Function(); ES2PANDA_ASSERT(func != nullptr); - Context().SetContainingSignature(func->Signature()); - } else if (iter->IsClassDefinition()) { + return SavedCheckerContext(this, STATUS, nullptr, func->Signature()); + } + if (iter->IsClassDefinition()) { auto *classDef = iter->AsClassDefinition(); Type *containingClass {}; - if (classDef->TsType() == nullptr) { containingClass = BuildBasicClassProperties(classDef)->MaybeBaseTypeOfGradualType(); ResolveDeclaredMembersOfObject(containingClass); } else { containingClass = classDef->TsType()->MaybeBaseTypeOfGradualType()->AsETSObjectType(); } - ES2PANDA_ASSERT(classDef->TsType()); if (!containingClass->IsTypeError()) { - Context().SetContainingClass(containingClass->AsETSObjectType()); + return SavedCheckerContext(this, STATUS, containingClass->AsETSObjectType()); } } - - iter = iter->Parent(); } + return SavedCheckerContext(this, STATUS); } static Type *GetTypeFromVarLikeVariableDeclaration(ETSChecker *checker, varbinder::Variable *const var) @@ -630,9 +629,8 @@ Type *ETSChecker::GetTypeOfVariable(varbinder::Variable *const var) return var->TsType(); } - checker::SavedCheckerContext savedContext(this, CheckerStatus::NO_OPTS); + checker::SavedCheckerContext savedContext = CreateSavedCheckerContext(var); checker::ScopeContext scopeCtx(this, var->GetScope()); - IterateInVariableContext(var); return GetTypeFromVariableDeclaration(var); } diff --git a/ets2panda/test/runtime/ets/namespace_tests/namespace_this_in_field.ets b/ets2panda/test/runtime/ets/namespace_tests/namespace_this_in_field.ets new file mode 100644 index 0000000000000000000000000000000000000000..de04c4d9197d6f5127439fa61f9aa314feaae963 --- /dev/null +++ b/ets2panda/test/runtime/ets/namespace_tests/namespace_this_in_field.ets @@ -0,0 +1,32 @@ +/* + * 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. + */ + +namespace NS { + export interface I { + readonly p: boolean + } + + export class C implements I { + readonly p: boolean = this.getP() + getP(): boolean { + return true + } + } +} + +function main() { + const c = new NS.C as NS.I + arktest.assertTrue(c.p) +}