From 037f72429e408e0c8b194fbe4e818f4d9722b78a Mon Sep 17 00:00:00 2001 From: Geng Chen Date: Tue, 8 Jul 2025 16:03:49 +0800 Subject: [PATCH 1/3] lazy checker --- ets2panda/BUILD.gn | 1 + ets2panda/CMakeLists.txt | 1 + ets2panda/checker/ETSAnalyzer.cpp | 336 +++++++++--------- ets2panda/checker/ETSchecker.cpp | 136 ++++++- ets2panda/checker/ETSchecker.h | 18 +- ets2panda/checker/ets/helpers.cpp | 2 +- ets2panda/checker/ets/object.cpp | 95 ++--- ets2panda/checker/ets/typeCheckingHelpers.cpp | 39 +- ets2panda/compiler/core/ETSemitter.cpp | 53 ++- .../compiler/lowering/ets/ambientLowering.cpp | 5 +- .../lowering/ets/asyncMethodLowering.cpp | 6 +- .../compiler/lowering/ets/bigintLowering.cpp | 5 +- .../compiler/lowering/ets/boxingForLocals.cpp | 10 +- .../compiler/lowering/ets/cfgBuilderPhase.cpp | 4 + .../lowering/ets/declareOverloadLowering.cpp | 9 +- ...defaultParametersInConstructorLowering.cpp | 2 +- .../lowering/ets/enumPostCheckLowering.cpp | 5 + .../compiler/lowering/ets/expandBrackets.cpp | 3 + .../lowering/ets/expressionLambdaLowering.cpp | 9 +- .../ets/extensionAccessorLowering.cpp | 7 +- .../lowering/ets/genericBridgesLowering.cpp | 3 + .../ets/interfaceObjectLiteralLowering.cpp | 18 +- .../ets/interfaceObjectLiteralLowering.h | 4 + .../compiler/lowering/ets/lambdaLowering.cpp | 31 +- .../lowering/ets/objectIndexAccess.cpp | 11 +- .../compiler/lowering/ets/objectIterator.cpp | 3 + .../lowering/ets/objectLiteralLowering.cpp | 10 +- .../compiler/lowering/ets/opAssignment.cpp | 12 +- .../ets/optionalArgumentsLowering.cpp | 12 +- .../lowering/ets/partialExportClassGen.cpp | 5 +- .../compiler/lowering/ets/recordLowering.cpp | 3 + .../compiler/lowering/ets/spreadLowering.cpp | 5 +- .../lowering/ets/stringComparison.cpp | 3 + .../ets/stringConstructorLowering.cpp | 5 +- .../compiler/lowering/ets/unionLowering.cpp | 10 +- ets2panda/compiler/lowering/phase.cpp | 60 ++++ ets2panda/compiler/lowering/phase.h | 49 ++- ets2panda/ir/astNodeFlags.h | 1 + ets2panda/ir/base/classProperty.cpp | 2 +- ets2panda/ir/ets/etsTypeReference.cpp | 4 +- ets2panda/ir/expressions/identifier.cpp | 2 +- ets2panda/ir/typed.cpp | 92 +++++ ets2panda/ir/typed.h | 15 +- ets2panda/util/generateBin.cpp | 2 + ets2panda/varbinder/ETSBinder.cpp | 7 + ets2panda/varbinder/scope.h | 2 + ets2panda/varbinder/variable.cpp | 126 ++++++- ets2panda/varbinder/variable.h | 17 +- ets2panda/varbinder/variableFlags.h | 1 + 49 files changed, 980 insertions(+), 281 deletions(-) create mode 100644 ets2panda/ir/typed.cpp diff --git a/ets2panda/BUILD.gn b/ets2panda/BUILD.gn index 60c32ea888..0f2c9231bc 100644 --- a/ets2panda/BUILD.gn +++ b/ets2panda/BUILD.gn @@ -465,6 +465,7 @@ libes2panda_sources = [ "ir/ts/tsUnknownKeyword.cpp", "ir/ts/tsVoidKeyword.cpp", "ir/typeNode.cpp", + "ir/typed.cpp", "lexer/ASLexer.cpp", "lexer/ETSLexer.cpp", "lexer/TSLexer.cpp", diff --git a/ets2panda/CMakeLists.txt b/ets2panda/CMakeLists.txt index 73d465ae36..8c7f217c1e 100644 --- a/ets2panda/CMakeLists.txt +++ b/ets2panda/CMakeLists.txt @@ -333,6 +333,7 @@ set(ES2PANDA_LIB_SRC ir/astNodeHistory.cpp ir/irnode.cpp ir/typeNode.cpp + ir/typed.cpp ir/opaqueTypeNode.cpp ir/brokenTypeNode.cpp ir/base/catchClause.cpp diff --git a/ets2panda/checker/ETSAnalyzer.cpp b/ets2panda/checker/ETSAnalyzer.cpp index 25c2af4b66..6293538b96 100644 --- a/ets2panda/checker/ETSAnalyzer.cpp +++ b/ets2panda/checker/ETSAnalyzer.cpp @@ -85,7 +85,7 @@ checker::Type *ETSAnalyzer::Check(ir::ClassDefinition *node) const { ETSChecker *checker = GetETSChecker(); - if (node->TsType() == nullptr) { + if (node->TsTypeChecker() == nullptr) { checker->BuildBasicClassProperties(node); } @@ -93,13 +93,13 @@ checker::Type *ETSAnalyzer::Check(ir::ClassDefinition *node) const checker->CheckClassDefinition(node); } - return node->TsType(); + return node->TsTypeChecker(); } checker::Type *ETSAnalyzer::Check(ir::ClassProperty *st) const { - if (st->TsType() != nullptr) { - return st->TsType(); + if (st->TsTypeChecker() != nullptr) { + return st->TsTypeChecker(); } ES2PANDA_ASSERT(st->Id() != nullptr); @@ -130,7 +130,7 @@ checker::Type *ETSAnalyzer::Check(ir::ClassProperty *st) const propertyType = propertyType != nullptr ? propertyType : checker->GlobalTypeError(); st->SetTsType(propertyType); - if (st->IsDefinite() && st->TsType()->PossiblyETSNullish()) { + if (st->IsDefinite() && st->TsTypeChecker()->PossiblyETSNullish()) { checker->LogError(diagnostic::LATE_INITIALIZATION_FIELD_HAS_INVALID_TYPE, st->TypeAnnotation()->Start()); } @@ -144,7 +144,7 @@ checker::Type *ETSAnalyzer::Check(ir::ClassStaticBlock *st) const if (checker->HasStatus(checker::CheckerStatus::INNER_CLASS)) { checker->LogError(diagnostic::STATIC_INIT_IN_NESTED_CLASS, {}, st->Start()); st->SetTsType(checker->GlobalTypeError()); - return st->TsType(); + return st->TsTypeChecker(); } auto *func = st->Function(); @@ -160,7 +160,7 @@ checker::Type *ETSAnalyzer::Check(ir::ClassStaticBlock *st) const checker->Context().ContainingClass()); checker->AddStatus(checker::CheckerStatus::IN_STATIC_BLOCK | checker::CheckerStatus::IN_STATIC_CONTEXT); func->Body()->Check(checker); - return st->TsType(); + return st->TsTypeChecker(); } // Satisfy the Chinese code checker @@ -189,14 +189,14 @@ static checker::Type *CheckMethodDefinitionHelper(ETSChecker *checker, ir::Metho // NOTE(gogabr): temporary, until we have proper bridges, see #16485 // Don't check overriding for synthetic functional classes. if ((node->Parent()->Modifiers() & ir::ModifierFlags::FUNCTIONAL) == 0) { - checker->CheckOverride(node->TsType()->AsETSFunctionType()->FindSignature(node->Function())); + checker->CheckOverride(node->TsTypeChecker()->AsETSFunctionType()->FindSignature(node->Function())); } for (auto *overload : node->Overloads()) { overload->Check(checker); } - return node->TsType(); + return node->TsTypeChecker(); } static bool IsInitializerBlockTransfer(std::string_view str) @@ -213,7 +213,7 @@ checker::Type *ETSAnalyzer::Check(ir::MethodDefinition *node) const // CC-OFFNXT(G.FMT.14-CPP) project code style auto const returnErrorType = [checker, node]() -> checker::Type * { node->SetTsType(checker->GlobalTypeError()); - return node->TsType(); + return node->TsTypeChecker(); }; checker->CheckAnnotations(scriptFunc->Annotations()); @@ -242,7 +242,7 @@ checker::Type *ETSAnalyzer::Check(ir::MethodDefinition *node) const return returnErrorType(); } - if (node->TsType() == nullptr) { + if (node->TsTypeChecker() == nullptr) { node->SetTsType(checker->BuildMethodSignature(node)); } @@ -254,8 +254,8 @@ checker::Type *ETSAnalyzer::Check(ir::MethodDefinition *node) const HandleNativeAndAsyncMethods(checker, node); DoBodyTypeChecking(checker, node, scriptFunc); CheckPredefinedMethodReturnType(checker, scriptFunc); - if (node->TsType()->IsTypeError()) { - return node->TsType(); + if (node->TsTypeChecker()->IsTypeError()) { + return node->TsTypeChecker(); } return CheckMethodDefinitionHelper(checker, node); @@ -372,8 +372,8 @@ checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::Property *expr) const checker::Type *ETSAnalyzer::Check(ir::SpreadElement *expr) const { - if (expr->TsType() != nullptr) { - return expr->TsType(); + if (expr->TsTypeChecker() != nullptr) { + return expr->TsTypeChecker(); } ETSChecker *checker = GetETSChecker(); @@ -403,7 +403,7 @@ checker::Type *ETSAnalyzer::Check(ir::TemplateElement *expr) const { ETSChecker *checker = GetETSChecker(); expr->SetTsType(checker->CreateETSStringLiteralType(expr->Raw())); - return expr->TsType(); + return expr->TsTypeChecker(); } checker::Type *ETSAnalyzer::Check(ir::ETSClassLiteral *expr) const @@ -413,13 +413,13 @@ checker::Type *ETSAnalyzer::Check(ir::ETSClassLiteral *expr) const checker->LogError(diagnostic::UNSUPPORTED_CLASS_LITERAL, {}, literal->Start()); expr->SetTsType(checker->GlobalTypeError()); - return expr->TsType(); + return expr->TsTypeChecker(); auto exprType = literal->Check(checker); if (exprType->IsETSVoidType()) { checker->LogError(diagnostic::INVALID_DOT_CLASS, {}, literal->Start()); expr->SetTsType(checker->GlobalTypeError()); - return expr->TsType(); + return expr->TsTypeChecker(); } ArenaVector typeArgTypes(checker->ProgramAllocator()->Adapter()); @@ -429,13 +429,13 @@ checker::Type *ETSAnalyzer::Check(ir::ETSClassLiteral *expr) const expr->Range().start); expr->SetTsType(ctx.Result()); - return expr->TsType(); + return expr->TsTypeChecker(); } checker::Type *ETSAnalyzer::Check(ir::ETSFunctionType *node) const { - if (node->TsType() != nullptr) { - return node->TsType(); + if (node->TsTypeChecker() != nullptr) { + return node->TsTypeChecker(); } ETSChecker *checker = GetETSChecker(); checker->CheckAnnotations(node->Annotations()); @@ -444,7 +444,7 @@ checker::Type *ETSAnalyzer::Check(ir::ETSFunctionType *node) const auto *signatureInfo = checker->ComposeSignatureInfo(node->TypeParams(), node->Params()); ES2PANDA_ASSERT(signatureInfo != nullptr); auto *returnType = node->IsExtensionFunction() && node->ReturnType()->IsTSThisType() - ? signatureInfo->params.front()->TsType() + ? signatureInfo->params.front()->TsTypeChecker() : checker->ComposeReturnType(node->ReturnType(), node->IsAsync()); auto *const signature = @@ -507,8 +507,8 @@ static bool NeedCreateETSResizableArrayType(ETSChecker *checker, Type *type) checker::Type *ETSAnalyzer::Check(ir::ETSNewArrayInstanceExpression *expr) const { - if (expr->TsType() != nullptr) { - return expr->TsType(); + if (expr->TsTypeChecker() != nullptr) { + return expr->TsTypeChecker(); } ETSChecker *checker = GetETSChecker(); @@ -526,11 +526,11 @@ checker::Type *ETSAnalyzer::Check(ir::ETSNewArrayInstanceExpression *expr) const } else { expr->SetTsType(checker->CreateETSArrayType(elementType)); } - if (expr->TsType()->IsETSArrayType()) { - checker->CreateBuiltinArraySignature(expr->TsType()->AsETSArrayType(), 1); + if (expr->TsTypeChecker()->IsETSArrayType()) { + checker->CreateBuiltinArraySignature(expr->TsTypeChecker()->AsETSArrayType(), 1); } - return expr->TsType(); + return expr->TsTypeChecker(); } static checker::Type *CheckInstantiatedNewType(ETSChecker *checker, ir::ETSNewClassInstanceExpression *expr) @@ -572,8 +572,8 @@ static checker::Type *CheckInstantiatedNewType(ETSChecker *checker, ir::ETSNewCl checker::Type *ETSAnalyzer::Check(ir::ETSNewClassInstanceExpression *expr) const { - if (expr->TsType() != nullptr) { - return expr->TsType(); + if (expr->TsTypeChecker() != nullptr) { + return expr->TsTypeChecker(); } ETSChecker *checker = GetETSChecker(); auto *calleeType = CheckInstantiatedNewType(checker, expr); @@ -595,13 +595,13 @@ checker::Type *ETSAnalyzer::Check(ir::ETSNewClassInstanceExpression *expr) const expr->SetSignature(signature); - return expr->TsType(); + return expr->TsTypeChecker(); } checker::Type *ETSAnalyzer::Check(ir::ETSNewMultiDimArrayInstanceExpression *expr) const { - if (expr->TsType() != nullptr) { - return expr->TsType(); + if (expr->TsTypeChecker() != nullptr) { + return expr->TsTypeChecker(); } ETSChecker *checker = GetETSChecker(); @@ -622,12 +622,12 @@ checker::Type *ETSAnalyzer::Check(ir::ETSNewMultiDimArrayInstanceExpression *exp expr->SetTsType(fixedArrayType); } - if (expr->TsType()->IsETSArrayType()) { + if (expr->TsTypeChecker()->IsETSArrayType()) { expr->SetSignature( - checker->CreateBuiltinArraySignature(expr->TsType()->AsETSArrayType(), expr->Dimensions().size())); + checker->CreateBuiltinArraySignature(expr->TsTypeChecker()->AsETSArrayType(), expr->Dimensions().size())); } - return expr->TsType(); + return expr->TsTypeChecker(); } checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::ETSPackageDeclaration *st) const @@ -638,21 +638,21 @@ checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::ETSPackageDeclaration *st checker::Type *ETSAnalyzer::Check(ir::ETSParameterExpression *expr) const { ETSChecker *checker = GetETSChecker(); - if (expr->TsType() != nullptr) { - return expr->TsType(); + if (expr->TsTypeChecker() != nullptr) { + return expr->TsTypeChecker(); } ASSERT_PRINT(expr->Initializer() == nullptr, "default parameter was not lowered"); - if (expr->Ident()->TsType() != nullptr) { - expr->SetTsType(expr->Ident()->TsType()); + if (expr->Ident()->TsTypeChecker() != nullptr) { + expr->SetTsType(expr->Ident()->TsTypeChecker()); } else if (expr->IsRestParameter()) { expr->SetTsType(expr->RestParameter()->Check(checker)); } else { expr->SetTsType(expr->Ident()->Check(checker)); } ES2PANDA_ASSERT(!expr->IsOptional() || - checker->Relation()->IsSupertypeOf(expr->TsType(), checker->GlobalETSUndefinedType())); - return expr->TsType(); + checker->Relation()->IsSupertypeOf(expr->TsTypeChecker(), checker->GlobalETSUndefinedType())); + return expr->TsTypeChecker(); } checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::ETSPrimitiveType *node) const @@ -683,8 +683,8 @@ checker::Type *ETSAnalyzer::Check(ir::ETSTypeReferencePart *node) const checker::Type *ETSAnalyzer::Check(ir::ETSNonNullishTypeNode *node) const { - if (node->TsType() != nullptr) { - return node->TsType(); + if (node->TsTypeChecker() != nullptr) { + return node->TsTypeChecker(); } ETSChecker *checker = GetETSChecker(); return node->SetTsType(checker->GetNonNullishType(node->GetTypeNode()->Check(checker))); @@ -735,7 +735,7 @@ static void AddSpreadElementTypes(ETSChecker *checker, ir::SpreadElement *const return; } - Type *const spreadArgumentType = element->Argument()->TsType()->MaybeBaseTypeOfGradualType(); + Type *const spreadArgumentType = element->Argument()->TsTypeChecker()->MaybeBaseTypeOfGradualType(); if (spreadArgumentType->IsETSTupleType()) { for (Type *type : spreadArgumentType->AsETSTupleType()->GetTupleTypesList()) { @@ -939,8 +939,8 @@ static Type *GetAppropriatePreferredType(Type *originalType, std::functionTsType() != nullptr) { - return expr->TsType(); + if (expr->TsTypeChecker() != nullptr) { + return expr->TsTypeChecker(); } auto *preferredType = GetAppropriatePreferredType(expr->PreferredType(), [](Type *tp) -> bool { @@ -975,7 +975,7 @@ checker::Type *ETSAnalyzer::Check(ir::ArrayExpression *expr) const const auto *const arrayType = preferredType->AsETSArrayType(); checker->CreateBuiltinArraySignature(arrayType, arrayType->Rank()); } - return expr->TsType(); + return expr->TsTypeChecker(); } void TryInferPreferredType(ir::ArrowFunctionExpression *expr, checker::Type *preferredType, ETSChecker *checker) @@ -1005,8 +1005,8 @@ checker::Type *ETSAnalyzer::Check(ir::ArrowFunctionExpression *expr) const { ETSChecker *checker = GetETSChecker(); checker->CheckAnnotations(expr->Annotations()); - if (expr->TsType() != nullptr) { - return expr->TsType(); + if (expr->TsTypeChecker() != nullptr) { + return expr->TsTypeChecker(); } checker::ScopeContext scopeCtx(checker, expr->Function()->Scope()); @@ -1026,7 +1026,7 @@ checker::Type *ETSAnalyzer::Check(ir::ArrowFunctionExpression *expr) const here the enclosing class of arrow function should be Class A */ checker->Context().SetContainingClass( - checker->Scope()->Find(varbinder::VarBinder::MANDATORY_PARAM_THIS).variable->TsType()->AsETSObjectType()); + checker->Scope()->Find(varbinder::VarBinder::MANDATORY_PARAM_THIS).variable->TsTypeChecker()->AsETSObjectType()); } auto lambdaSavedSmartCasts = checker->Context().CloneSmartCasts(); @@ -1069,11 +1069,11 @@ checker::Type *ETSAnalyzer::Check(ir::ArrowFunctionExpression *expr) const retType->AsETSObjectType()->GetOriginalBaseType() != checker->GlobalBuiltinPromiseType()) { checker->LogError(diagnostic::ASYNC_DOESNT_PROMISE, {}, expr->Function()->Start()); expr->SetTsType(checker->GlobalTypeError()); - return expr->TsType(); + return expr->TsTypeChecker(); } } expr->SetTsType(funcType); - return expr->TsType(); + return expr->TsTypeChecker(); } static bool IsInvalidArrayMemberAssignment(const ir::AssignmentExpression *const expr, ETSChecker *checker) @@ -1083,15 +1083,15 @@ static bool IsInvalidArrayMemberAssignment(const ir::AssignmentExpression *const } const auto *const leftExpr = expr->Left()->AsMemberExpression(); - if (leftExpr->Object()->TsType()->IsETSArrayType() || leftExpr->Object()->TsType()->IsETSTupleType() || - leftExpr->Object()->TsType()->IsETSResizableArrayType()) { - if (leftExpr->Object()->TsType()->IsETSArrayType() && leftExpr->Property()->IsIdentifier() && + if (leftExpr->Object()->TsTypeChecker()->IsETSArrayType() || leftExpr->Object()->TsTypeChecker()->IsETSTupleType() || + leftExpr->Object()->TsTypeChecker()->IsETSResizableArrayType()) { + if (leftExpr->Object()->TsTypeChecker()->IsETSArrayType() && leftExpr->Property()->IsIdentifier() && leftExpr->Property()->AsIdentifier()->Name().Is("length")) { checker->LogError(diagnostic::ARRAY_LENGTH_MODIFICATION, {}, expr->Left()->Start()); return true; } - if (leftExpr->Object()->TsType()->HasTypeFlag(TypeFlag::READONLY)) { + if (leftExpr->Object()->TsTypeChecker()->HasTypeFlag(TypeFlag::READONLY)) { checker->LogError(diagnostic::READONLY_ARRAYLIKE_MODIFICATION, {}, expr->Left()->Start()); return true; } @@ -1162,8 +1162,8 @@ static bool IsInvalidMethodAssignment(const ir::AssignmentExpression *const expr checker::Type *ETSAnalyzer::Check(ir::AssignmentExpression *const expr) const { - if (expr->TsType() != nullptr) { - return expr->TsType(); + if (expr->TsTypeChecker() != nullptr) { + return expr->TsTypeChecker(); } ETSChecker *checker = GetETSChecker(); @@ -1176,21 +1176,21 @@ checker::Type *ETSAnalyzer::Check(ir::AssignmentExpression *const expr) const if (IsInvalidArrayMemberAssignment(expr, checker) || IsInvalidMethodAssignment(expr, checker)) { expr->SetTsType(checker->GlobalTypeError()); - return expr->TsType(); + return expr->TsTypeChecker(); } if (expr->Left()->IsIdentifier()) { expr->target_ = expr->Left()->AsIdentifier()->Variable(); } else if (expr->Left()->IsMemberExpression()) { if (!expr->IsIgnoreConstAssign() && - expr->Left()->AsMemberExpression()->Object()->TsType()->HasTypeFlag(TypeFlag::READONLY)) { + expr->Left()->AsMemberExpression()->Object()->TsTypeChecker()->HasTypeFlag(TypeFlag::READONLY)) { checker->LogError(diagnostic::READONLY_PROPERTY_REASSIGN, {}, expr->Left()->Start()); } expr->target_ = expr->Left()->AsMemberExpression()->PropVar(); } else { checker->LogError(diagnostic::ASSIGNMENT_INVALID_LHS, {}, expr->Left()->Start()); expr->SetTsType(checker->GlobalTypeError()); - return expr->TsType(); + return expr->TsTypeChecker(); } if (expr->target_ != nullptr && !expr->IsIgnoreConstAssign()) { @@ -1294,8 +1294,8 @@ static bool IsPromiseType(checker::Type *type, ETSChecker *checker) checker::Type *ETSAnalyzer::Check(ir::AwaitExpression *expr) const { ETSChecker *checker = GetETSChecker(); - if (expr->TsType() != nullptr) { - return expr->TsType(); + if (expr->TsTypeChecker() != nullptr) { + return expr->TsTypeChecker(); } checker::Type *argType = checker->GetApparentType(expr->argument_->Check(checker)); @@ -1320,7 +1320,7 @@ checker::Type *ETSAnalyzer::Check(ir::AwaitExpression *expr) const } expr->SetTsType(argType->IsETSUnionType() ? checker->CreateETSUnionType(std::move(awaitedTypes)) : awaitedTypes[0]); - return expr->TsType(); + return expr->TsTypeChecker(); } checker::Type *ETSAnalyzer::UnwrapPromiseType(checker::Type *type) const @@ -1354,8 +1354,8 @@ checker::Type *ETSAnalyzer::UnwrapPromiseType(checker::Type *type) const checker::Type *ETSAnalyzer::Check(ir::BinaryExpression *expr) const { - if (expr->TsType() != nullptr) { - return expr->TsType(); + if (expr->TsTypeChecker() != nullptr) { + return expr->TsTypeChecker(); } ETSChecker *checker = GetETSChecker(); @@ -1390,13 +1390,13 @@ checker::Type *ETSAnalyzer::Check(ir::BinaryExpression *expr) const checker->Context().ExitTestExpression(); } - return expr->TsType(); + return expr->TsTypeChecker(); } checker::Type *ETSAnalyzer::Check(ir::BlockExpression *st) const { - if (st->TsType() != nullptr) { - return st->TsType(); + if (st->TsTypeChecker() != nullptr) { + return st->TsTypeChecker(); } ETSChecker *checker = GetETSChecker(); @@ -1409,8 +1409,8 @@ checker::Type *ETSAnalyzer::Check(ir::BlockExpression *st) const auto lastStmt = st->Statements().back(); ES2PANDA_ASSERT(lastStmt->IsExpressionStatement()); - st->SetTsType(lastStmt->AsExpressionStatement()->GetExpression()->TsType()); - return st->TsType(); + st->SetTsType(lastStmt->AsExpressionStatement()->GetExpression()->TsTypeChecker()); + return st->TsTypeChecker(); } static bool LambdaIsField(ir::CallExpression *expr) @@ -1520,7 +1520,7 @@ Type *ETSAnalyzer::GetReturnType(ir::CallExpression *expr, Type *calleeType) con // #22951: this type should not be encoded as a signature flag if (signature->HasSignatureFlag(SignatureFlags::THIS_RETURN_TYPE)) { return signature->HasSignatureFlag(SignatureFlags::EXTENSION_FUNCTION) - ? expr->Arguments()[0]->TsType() + ? expr->Arguments()[0]->TsTypeChecker() : GetCallExpressionCalleeObject(checker, expr, calleeType); } return signature->ReturnType(); @@ -1549,7 +1549,7 @@ static void CheckCallee(ETSChecker *checker, ir::CallExpression *expr) if (memberExpr->Object() == nullptr) { return; } - auto baseType = memberExpr->Object()->TsType()->MaybeBaseTypeOfGradualType(); + auto baseType = memberExpr->Object()->TsTypeChecker()->MaybeBaseTypeOfGradualType(); if (baseType->IsETSObjectType() && baseType->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::READONLY)) { checker->LogError(diagnostic::READONLY_CALL, {}, expr->Start()); expr->SetTsType(checker->GlobalTypeError()); @@ -1584,8 +1584,8 @@ checker::Type *ETSAnalyzer::GetCallExpressionReturnType(ir::CallExpression *expr } auto *const signature = expr->Signature(); - if (signature->RestVar() != nullptr && signature->RestVar()->TsType()->IsETSArrayType()) { - auto *elementType = signature->RestVar()->TsType()->AsETSArrayType()->ElementType(); + if (signature->RestVar() != nullptr && signature->RestVar()->TsTypeChecker()->IsETSArrayType()) { + auto *elementType = signature->RestVar()->TsTypeChecker()->AsETSArrayType()->ElementType(); auto *const arrayType = checker->CreateETSArrayType(elementType)->AsETSArrayType(); checker->CreateBuiltinArraySignature(arrayType, arrayType->Rank()); } @@ -1627,8 +1627,8 @@ checker::Type *ETSAnalyzer::GetCallExpressionReturnType(ir::CallExpression *expr checker::Type *ETSAnalyzer::Check(ir::CallExpression *expr) const { ETSChecker *checker = GetETSChecker(); - if (expr->TsType() != nullptr) { - return expr->TsType(); + if (expr->TsTypeChecker() != nullptr) { + return expr->TsTypeChecker(); } ES2PANDA_ASSERT(!expr->IsOptional()); @@ -1671,12 +1671,12 @@ checker::Type *ETSAnalyzer::Check(ir::CallExpression *expr) const if (returnType->IsTypeError()) { expr->SetTsType(returnType); - return expr->TsType(); + return expr->TsTypeChecker(); } CheckVoidTypeExpression(checker, expr); CheckAbstractCall(checker, expr); - return expr->TsType(); + return expr->TsTypeChecker(); } static bool IsNumericType(ETSChecker *checker, Type *type) @@ -1720,8 +1720,8 @@ static Type *BiggerNumericType(ETSChecker *checker, Type *t1, Type *t2) checker::Type *ETSAnalyzer::Check(ir::ConditionalExpression *expr) const { - if (expr->TsType() != nullptr) { - return expr->TsType(); + if (expr->TsTypeChecker() != nullptr) { + return expr->TsTypeChecker(); } ETSChecker *const checker = GetETSChecker(); @@ -1764,7 +1764,7 @@ checker::Type *ETSAnalyzer::Check(ir::ConditionalExpression *expr) const // Restore smart casts to initial state. checker->Context().RestoreSmartCasts(smartCasts); - return expr->TsType(); + return expr->TsTypeChecker(); } // Convert method references to Arrow type if method is used as value @@ -1821,16 +1821,16 @@ static Type *TransformTypeForMethodReference(ETSChecker *checker, ir::Expression checker::Type *ETSAnalyzer::Check(ir::Identifier *expr) const { - if (expr->TsType() != nullptr) { - return expr->TsType(); + if (expr->TsTypeChecker() != nullptr) { + return expr->TsTypeChecker(); } ETSChecker *checker = GetETSChecker(); auto *identType = TransformTypeForMethodReference(checker, expr, checker->ResolveIdentifier(expr)); - if (expr->TsType() != nullptr && expr->TsType()->IsTypeError()) { - return expr->TsType(); + if (expr->TsTypeChecker() != nullptr && expr->TsTypeChecker()->IsTypeError()) { + return expr->TsTypeChecker(); } ES2PANDA_ASSERT(expr->Variable() != nullptr); if (expr->Parent() == nullptr || !expr->Parent()->IsAssignmentExpression() || @@ -1846,7 +1846,7 @@ checker::Type *ETSAnalyzer::Check(ir::Identifier *expr) const if (!identType->IsTypeError()) { checker->Context().CheckIdentifierSmartCastCondition(expr); } - return expr->TsType(); + return expr->TsTypeChecker(); } std::pair SearchReExportsType(ETSObjectType *baseType, ir::MemberExpression *expr, @@ -1944,13 +1944,13 @@ checker::Type *ETSAnalyzer::ResolveMemberExpressionByBaseType(ETSChecker *checke } TypeErrorOnMissingProperty(expr, baseType, checker); - return expr->TsType(); + return expr->TsTypeChecker(); } checker::Type *ETSAnalyzer::Check(ir::MemberExpression *expr) const { - if (expr->TsType() != nullptr) { - return expr->TsType(); + if (expr->TsTypeChecker() != nullptr) { + return expr->TsTypeChecker(); } ES2PANDA_ASSERT(!expr->IsOptional()); ETSChecker *checker = GetETSChecker(); @@ -1959,7 +1959,7 @@ checker::Type *ETSAnalyzer::Check(ir::MemberExpression *expr) const // Such situation should be correctly resolved in the subsequent lowering. ES2PANDA_ASSERT(baseType != nullptr); if (baseType->DefinitelyETSNullish() && expr->Object()->IsIdentifier()) { - baseType = expr->Object()->AsIdentifier()->Variable()->TsType(); + baseType = expr->Object()->AsIdentifier()->Variable()->TsTypeChecker(); } if (baseType->IsETSObjectType() && !baseType->AsETSObjectType()->ReExports().empty() && @@ -1995,7 +1995,7 @@ checker::Type *ETSAnalyzer::CheckDynamic(ir::ObjectExpression *expr) const ir::Property *prop = propExpr->AsProperty(); ir::Expression *value = prop->Value(); value->Check(checker); - ES2PANDA_ASSERT(value->TsType()); + ES2PANDA_ASSERT(value->TsTypeChecker()); } expr->SetTsType(expr->PreferredType()); @@ -2394,19 +2394,19 @@ static checker::Type *HandleRecordOrMapType(ETSChecker *checker, ir::ObjectExpre checker::Type *ETSAnalyzer::Check(ir::ObjectExpression *expr) const { ETSChecker *checker = GetETSChecker(); - if (expr->TsType() != nullptr) { - return expr->TsType(); + if (expr->TsTypeChecker() != nullptr) { + return expr->TsTypeChecker(); } if (expr->PreferredType() == nullptr) { checker->LogError(diagnostic::CLASS_COMPOSITE_UNKNOWN_TYPE, {}, expr->Start()); expr->SetTsType(checker->GlobalTypeError()); - return expr->TsType(); + return expr->TsTypeChecker(); } if (!expr->PreferredType()->IsETSUnionType() && !ValidatePreferredType(checker, expr)) { expr->SetTsType(checker->GlobalTypeError()); - return expr->TsType(); + return expr->TsTypeChecker(); } checker::ETSObjectType *objType = ResolveObjectTypeFromPreferredType(checker, expr); @@ -2416,7 +2416,7 @@ checker::Type *ETSAnalyzer::Check(ir::ObjectExpression *expr) const checker->LogError(diagnostic::CLASS_COMPOSITE_INVALID_TARGET, {expr->PreferredType()}, expr->Start()); } expr->SetTsType(checker->GlobalTypeError()); - return expr->TsType(); + return expr->TsTypeChecker(); } if (objType->HasObjectFlag(checker::ETSObjectFlags::INTERFACE)) { @@ -2433,7 +2433,7 @@ checker::Type *ETSAnalyzer::Check(ir::ObjectExpression *expr) const // If we reach here, objType is a class. It must have a parameterless constructor if (!HasParameterlessConstructor(objType, checker, expr->Start())) { expr->SetTsType(checker->TypeError(expr, diagnostic::NO_PARAMLESS_CTOR, {objType->Name()}, expr->Start())); - return expr->TsType(); + return expr->TsTypeChecker(); } CheckObjectExprProps(expr, objType, @@ -2491,8 +2491,8 @@ void ETSAnalyzer::CheckObjectExprProps(const ir::ObjectExpression *expr, key->SetTsType(propType); value->SetTsType(value->Check(checker)); - checker::AssignmentContext(checker->Relation(), value, value->TsType(), propType, value->Start(), - {{diagnostic::PROP_INCOMPAT, {value->TsType(), propType, pname}}}); + checker::AssignmentContext(checker->Relation(), value, value->TsTypeChecker(), propType, value->Start(), + {{diagnostic::PROP_INCOMPAT, {value->TsTypeChecker(), propType, pname}}}); } if (objType->HasObjectFlag(ETSObjectFlags::REQUIRED)) { @@ -2502,7 +2502,7 @@ void ETSAnalyzer::CheckObjectExprProps(const ir::ObjectExpression *expr, checker::Type *ETSAnalyzer::Check(ir::OpaqueTypeNode *expr) const { - return expr->TsType(); + return expr->TsTypeChecker(); } checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::BrokenTypeNode *expr) const @@ -2513,27 +2513,27 @@ checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::BrokenTypeNode *expr) con checker::Type *ETSAnalyzer::Check(ir::SequenceExpression *expr) const { ETSChecker *checker = GetETSChecker(); - if (expr->TsType() != nullptr) { - return expr->TsType(); + if (expr->TsTypeChecker() != nullptr) { + return expr->TsTypeChecker(); } for (auto *it : expr->Sequence()) { it->Check(checker); } ES2PANDA_ASSERT(!expr->Sequence().empty()); - expr->SetTsType(expr->Sequence().back()->TsType()); - return expr->TsType(); + expr->SetTsType(expr->Sequence().back()->TsTypeChecker()); + return expr->TsTypeChecker(); } checker::Type *ETSAnalyzer::Check(ir::SuperExpression *expr) const { ETSChecker *checker = GetETSChecker(); - if (expr->TsType() != nullptr) { - return expr->TsType(); + if (expr->TsTypeChecker() != nullptr) { + return expr->TsTypeChecker(); } expr->SetTsType(checker->CheckThisOrSuperAccess(expr, checker->Context().ContainingClass()->SuperType(), "super")); - return expr->TsType(); + return expr->TsTypeChecker(); } checker::Type *ETSAnalyzer::Check(ir::TemplateLiteral *expr) const @@ -2544,14 +2544,14 @@ checker::Type *ETSAnalyzer::Check(ir::TemplateLiteral *expr) const it->Check(checker); } - if (expr->TsType() != nullptr) { - return expr->TsType(); + if (expr->TsTypeChecker() != nullptr) { + return expr->TsTypeChecker(); } if (expr->Quasis().size() != expr->Expressions().size() + 1U) { checker->LogError(diagnostic::TEMPLATE_COUNT_MISMATCH, {}, expr->Start()); expr->SetTsType(checker->GlobalTypeError()); - return expr->TsType(); + return expr->TsTypeChecker(); } for (auto *it : expr->Quasis()) { @@ -2559,14 +2559,14 @@ checker::Type *ETSAnalyzer::Check(ir::TemplateLiteral *expr) const } expr->SetTsType(checker->CreateETSStringLiteralType(expr->GetMultilineString())); - return expr->TsType(); + return expr->TsTypeChecker(); } checker::Type *ETSAnalyzer::Check(ir::ThisExpression *expr) const { ETSChecker *checker = GetETSChecker(); - if (expr->TsType() != nullptr) { - return expr->TsType(); + if (expr->TsTypeChecker() != nullptr) { + return expr->TsTypeChecker(); } /* @@ -2593,12 +2593,12 @@ checker::Type *ETSAnalyzer::Check(ir::ThisExpression *expr) const auto *variable = checker->AsETSChecker()->Scope()->Find(varbinder::VarBinder::MANDATORY_PARAM_THIS).variable; if (checker->HasStatus(checker::CheckerStatus::IN_EXTENSION_METHOD)) { ES2PANDA_ASSERT(variable != nullptr); - expr->SetTsType(variable->TsType()); + expr->SetTsType(variable->TsTypeChecker()); } else { expr->SetTsType(checker->CheckThisOrSuperAccess(expr, checker->Context().ContainingClass(), "this")); } - return expr->TsType(); + return expr->TsTypeChecker(); } // Get string literal type as potential typeof result type with respect to spec p.7.17 @@ -2664,21 +2664,21 @@ static checker::Type *ComputeTypeOfType(ETSChecker *checker, checker::Type *argT checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::TypeofExpression *expr) const { ETSChecker *checker = GetETSChecker(); - if (expr->TsType() != nullptr) { - return expr->TsType(); + if (expr->TsTypeChecker() != nullptr) { + return expr->TsTypeChecker(); } expr->Argument()->Check(checker); - expr->SetTsType(ComputeTypeOfType(checker, expr->Argument()->TsType())); - return expr->TsType(); + expr->SetTsType(ComputeTypeOfType(checker, expr->Argument()->TsTypeChecker())); + return expr->TsTypeChecker(); } checker::Type *ETSAnalyzer::Check(ir::UnaryExpression *expr) const { ETSChecker *checker = GetETSChecker(); - if (expr->TsType() != nullptr) { - return expr->TsType(); + if (expr->TsTypeChecker() != nullptr) { + return expr->TsTypeChecker(); } auto argType = expr->argument_->Check(checker); @@ -2694,7 +2694,7 @@ checker::Type *ETSAnalyzer::Check(ir::UnaryExpression *expr) const type->RemoveTypeFlag(checker::TypeFlag::CONSTANT); expr->argument_->SetTsType(type); expr->SetTsType(type); - return expr->TsType(); + return expr->TsTypeChecker(); } default: // Handled below @@ -2709,7 +2709,7 @@ checker::Type *ETSAnalyzer::Check(ir::UnaryExpression *expr) const case lexer::TokenType::PUNCTUATOR_PLUS: case lexer::TokenType::PUNCTUATOR_TILDE: { expr->SetTsType(argType); - return expr->TsType(); + return expr->TsTypeChecker(); } default: break; @@ -2720,14 +2720,14 @@ checker::Type *ETSAnalyzer::Check(ir::UnaryExpression *expr) const checker->Context().CheckUnarySmartCastCondition(expr); - return expr->TsType(); + return expr->TsTypeChecker(); } checker::Type *ETSAnalyzer::Check(ir::UpdateExpression *expr) const { ETSChecker *checker = GetETSChecker(); - if (expr->TsType() != nullptr) { - return expr->TsType(); + if (expr->TsTypeChecker() != nullptr) { + return expr->TsTypeChecker(); } checker::Type *operandType = expr->argument_->Check(checker); @@ -2775,38 +2775,38 @@ checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::BigIntLiteral *expr) cons { ETSChecker *checker = GetETSChecker(); expr->SetTsType(checker->CreateETSBigIntLiteralType(expr->Str())); - return expr->TsType(); + return expr->TsTypeChecker(); } checker::Type *ETSAnalyzer::Check(ir::BooleanLiteral *expr) const { ETSChecker *checker = GetETSChecker(); - if (expr->TsType() == nullptr) { + if (expr->TsTypeChecker() == nullptr) { auto type = checker->GlobalETSBooleanBuiltinType()->Clone(GetChecker()); type->AddTypeFlag(TypeFlag::CONSTANT); expr->SetTsType(type); } - return expr->TsType(); + return expr->TsTypeChecker(); } checker::Type *ETSAnalyzer::Check(ir::CharLiteral *expr) const { ETSChecker *checker = GetETSChecker(); - if (expr->TsType() == nullptr) { + if (expr->TsTypeChecker() == nullptr) { auto type = checker->GlobalCharBuiltinType()->Clone(GetChecker()); type->AddTypeFlag(TypeFlag::CONSTANT); expr->SetTsType(type); } - return expr->TsType(); + return expr->TsTypeChecker(); } checker::Type *ETSAnalyzer::Check(ir::NullLiteral *expr) const { ETSChecker *checker = GetETSChecker(); - if (expr->TsType() == nullptr) { + if (expr->TsTypeChecker() == nullptr) { expr->SetTsType(checker->GlobalETSNullType()); } - return expr->TsType(); + return expr->TsTypeChecker(); } static bool CheckIfLiteralValueIsAppropriate(ETSChecker *checker, Type *type, ir::NumberLiteral *expr) @@ -2839,8 +2839,8 @@ static bool CheckIfLiteralValueIsAppropriate(ETSChecker *checker, Type *type, ir checker::Type *ETSAnalyzer::Check(ir::NumberLiteral *expr) const { - if (expr->TsType() != nullptr) { - return expr->TsType(); + if (expr->TsTypeChecker() != nullptr) { + return expr->TsTypeChecker(); } ETSChecker *checker = GetETSChecker(); @@ -2874,10 +2874,10 @@ checker::Type *ETSAnalyzer::Check(ir::NumberLiteral *expr) const checker::Type *ETSAnalyzer::Check(ir::StringLiteral *expr) const { ETSChecker *checker = GetETSChecker(); - if (expr->TsType() == nullptr) { + if (expr->TsTypeChecker() == nullptr) { expr->SetTsType(checker->CreateETSStringLiteralType(expr->Str())); } - return expr->TsType(); + return expr->TsTypeChecker(); } checker::Type *ETSAnalyzer::Check(ir::ETSIntrinsicNode *node) const @@ -2919,8 +2919,8 @@ checker::Type *ETSAnalyzer::Check(ir::ImportNamespaceSpecifier *st) const return ReturnTypeForStatement(st); } - if (st->Local()->AsIdentifier()->TsType() != nullptr) { - return st->Local()->TsType(); + if (st->Local()->AsIdentifier()->TsTypeChecker() != nullptr) { + return st->Local()->TsTypeChecker(); } ir::ETSImportDeclaration *importDecl = nullptr; @@ -3019,12 +3019,19 @@ checker::Type *ETSAnalyzer::Check(ir::ClassDeclaration *st) const { ETSChecker *checker = GetETSChecker(); st->Definition()->Check(checker); + + // Set CHECKED flag and propagate it to all child nodes + st->AddAstNodeFlags(ir::AstNodeFlags::CHECKED); + st->IterateRecursively([](ir::AstNode *node) -> void { + node->AddAstNodeFlags(ir::AstNodeFlags::CHECKED); + }); + return ReturnTypeForStatement(st); } checker::Type *ETSAnalyzer::Check(ir::AnnotationDeclaration *st) const { - if (st->Expr()->TsType() != nullptr) { + if (st->Expr()->TsTypeChecker() != nullptr) { return ReturnTypeForStatement(st); } ETSChecker *checker = GetETSChecker(); @@ -3068,7 +3075,7 @@ static void ProcessRequiredFields(ArenaUnorderedMapExpr()->TsType() != nullptr) { + if (st->Expr()->TsTypeChecker() != nullptr) { return ReturnTypeForStatement(st); } ETSChecker *checker = GetETSChecker(); @@ -3176,7 +3183,7 @@ static bool ValidateAndProcessIteratorType(ETSChecker *checker, Type *elemType, const auto variable = ident->Variable(); if (variable != nullptr) { // Set smart type for variable of 'for-of' statement - const auto smartType = checker->ResolveSmartType(elemType, variable->TsType()); + const auto smartType = checker->ResolveSmartType(elemType, variable->TsTypeChecker()); checker->Context().SetSmartCast(variable, smartType); } @@ -3564,8 +3571,8 @@ checker::Type *ETSAnalyzer::Check(ir::TryStatement *st) const checker::Type *ETSAnalyzer::Check(ir::VariableDeclarator *st) const { - if (st->TsType() != nullptr) { - return st->TsType(); + if (st->TsTypeChecker() != nullptr) { + return st->TsTypeChecker(); } ETSChecker *checker = GetETSChecker(); @@ -3591,7 +3598,7 @@ checker::Type *ETSAnalyzer::Check(ir::VariableDeclarator *st) const // Now try to define the actual type of Identifier so that smart cast can be used in further checker processing // NOTE: T_S and K_o_t_l_i_n don't act in such way, but we can try - why not? :) auto *smartType = variableType; - if (auto *const initType = st->Init() != nullptr ? st->Init()->TsType() : nullptr; initType != nullptr) { + if (auto *const initType = st->Init() != nullptr ? st->Init()->TsTypeChecker() : nullptr; initType != nullptr) { auto const value = st->Init()->IsNumberLiteral() ? std::make_optional(st->Init()->AsNumberLiteral()->Number().GetDouble()) : std::nullopt; @@ -3654,17 +3661,17 @@ checker::Type *ETSAnalyzer::Check(ir::TSArrayType *node) const node->elementType_->Check(checker); node->SetTsType(node->GetType(checker)); - const auto *arrayType = node->TsType()->AsETSArrayType(); + const auto *arrayType = node->TsTypeChecker()->AsETSArrayType(); checker->CreateBuiltinArraySignature(arrayType, arrayType->Rank()); - return node->TsType(); + return node->TsTypeChecker(); } checker::Type *ETSAnalyzer::Check(ir::TSAsExpression *expr) const { ETSChecker *checker = GetETSChecker(); - if (expr->TsType() != nullptr) { - return expr->TsType(); + if (expr->TsTypeChecker() != nullptr) { + return expr->TsTypeChecker(); } checker->CheckAnnotations(expr->TypeAnnotation()->Annotations()); @@ -3717,8 +3724,8 @@ checker::Type *ETSAnalyzer::Check(ir::TSEnumDeclaration *st) const checker::Type *ETSAnalyzer::Check(ir::TSInterfaceDeclaration *st) const { - if (st->TsType() != nullptr) { - return st->TsType(); + if (st->TsTypeChecker() != nullptr) { + return st->TsTypeChecker(); } ETSChecker *checker = GetETSChecker(); @@ -3744,13 +3751,20 @@ checker::Type *ETSAnalyzer::Check(ir::TSInterfaceDeclaration *st) const for (auto *it : st->Body()->Body()) { it->Check(checker); } - return st->TsType(); + + // Set CHECKED flag and propagate it to all child nodes + st->AddAstNodeFlags(ir::AstNodeFlags::CHECKED); + st->IterateRecursively([](ir::AstNode *node) -> void { + node->AddAstNodeFlags(ir::AstNodeFlags::CHECKED); + }); + + return st->TsTypeChecker(); } checker::Type *ETSAnalyzer::Check(ir::TSNonNullExpression *expr) const { - if (expr->TsType() != nullptr) { - return expr->TsType(); + if (expr->TsTypeChecker() != nullptr) { + return expr->TsTypeChecker(); } ETSChecker *checker = GetETSChecker(); auto exprType = expr->expr_->Check(checker); @@ -3761,18 +3775,18 @@ checker::Type *ETSAnalyzer::Check(ir::TSNonNullExpression *expr) const if (expr->expr_->IsIdentifier()) { ES2PANDA_ASSERT(expr->expr_->AsIdentifier()->Variable() != nullptr); - auto originalType = expr->expr_->AsIdentifier()->Variable()->TsType(); + auto originalType = expr->expr_->AsIdentifier()->Variable()->TsTypeChecker(); if (originalType != nullptr) { expr->SetTsType(checker->GetNonNullishType(originalType)); } } } - if (expr->TsType() == nullptr) { + if (expr->TsTypeChecker() == nullptr) { expr->SetTsType(checker->GetNonNullishType(exprType)); } - expr->SetOriginalType(expr->TsType()); - return expr->TsType(); + expr->SetOriginalType(expr->TsTypeChecker()); + return expr->TsTypeChecker(); } static varbinder::Variable *FindNameForImportNamespace(ETSChecker *checker, util::StringView &searchName, @@ -3871,7 +3885,7 @@ checker::Type *ETSAnalyzer::Check(ir::TSTypeAliasDeclaration *st) const const checker::SavedTypeRelationFlagsContext savedFlagsCtx( checker->Relation(), checker::TypeRelationFlag::NO_THROW_GENERIC_TYPEALIAS); - if (st->TypeAnnotation()->TsType() == nullptr) { + if (st->TypeAnnotation()->TsTypeChecker() == nullptr) { st->TypeAnnotation()->Check(checker); } @@ -3889,7 +3903,7 @@ checker::Type *ETSAnalyzer::Check(ir::TSTypeAliasDeclaration *st) const const checker::SavedTypeRelationFlagsContext savedFlagsCtx(checker->Relation(), checker::TypeRelationFlag::NO_THROW_GENERIC_TYPEALIAS); - if (st->TypeAnnotation()->TsType() == nullptr) { + if (st->TypeAnnotation()->TsTypeChecker() == nullptr) { st->TypeAnnotation()->Check(checker); } diff --git a/ets2panda/checker/ETSchecker.cpp b/ets2panda/checker/ETSchecker.cpp index 7ca0134c52..ab78a38629 100644 --- a/ets2panda/checker/ETSchecker.cpp +++ b/ets2panda/checker/ETSchecker.cpp @@ -320,6 +320,8 @@ bool ETSChecker::StartChecker(varbinder::VarBinder *varbinder, const util::Optio return false; } + // 第一次调用CheckProgram时,设置当前program为主文件 + mainFileProgram_ = Program(); auto *etsBinder = varbinder->AsETSBinder(); InitializeBuiltins(etsBinder); @@ -348,6 +350,10 @@ bool ETSChecker::StartChecker(varbinder::VarBinder *varbinder, const util::Optio CheckWarnings(Program(), options); + // Lazy checker: 在checker阶段末尾处理所有搜集的classDef + ProcessPendingClassDefs(); + ClearPendingClassDefs(); + return !IsAnyError(); } @@ -371,24 +377,6 @@ void ETSChecker::CheckProgram(parser::Program *program, bool runAnalysis) auto *savedProgram = Program(); SetProgram(program); - for (auto &[_, extPrograms] : program->ExternalSources()) { - (void)_; - for (auto *extProg : extPrograms) { - if (!extProg->IsASTLowered()) { - extProg->PushChecker(this); - auto *savedProgram2 = VarBinder()->AsETSBinder()->Program(); - varbinder::RecordTableContext recordTableCtx(VarBinder()->AsETSBinder(), extProg); - VarBinder()->AsETSBinder()->SetProgram(extProg); - VarBinder()->AsETSBinder()->ResetTopScope(extProg->GlobalScope()); - checker::SavedCheckerContext savedContext(this, Context().Status(), Context().ContainingClass()); - AddStatus(checker::CheckerStatus::IN_EXTERNAL); - CheckProgram(extProg, VarBinder()->IsGenStdLib() || extProg->IsGenAbcForExternal()); - VarBinder()->AsETSBinder()->SetProgram(savedProgram2); - VarBinder()->AsETSBinder()->ResetTopScope(savedProgram2->GlobalScope()); - } - } - } - ES2PANDA_ASSERT(Program()->Ast()->IsProgram()); Program()->Ast()->Check(this); @@ -403,6 +391,118 @@ void ETSChecker::CheckProgram(parser::Program *program, bool runAnalysis) SetProgram(savedProgram); } +// Lazy checker: 管理搜集的classDef的方法实现 +void ETSChecker::AddPendingClassDef(ir::ClassDefinition *classDef, CheckerStatus status) +{ + if (classDef != nullptr) { + pendingClassDefs_.emplace_back(classDef, status); + } +} + +void ETSChecker::ProcessPendingClassDefs() +{ + for (auto &[classDef, savedStatus] : pendingClassDefs_) { + if (classDef != nullptr && classDef->Parent() != nullptr && + classDef->Parent()->IsClassDeclaration()) { + auto *classDecl = classDef->Parent()->AsClassDeclaration(); + + // 检查是否已经被标记为CHECKED + if (!classDecl->HasAstNodeFlags(ir::AstNodeFlags::CHECKED)) { + // 直接使用搜集时保存的CheckerStatus + checker::SavedCheckerContext savedContext(this, savedStatus); + checker::ScopeContext scopeCtx(this, classDef->Scope()); + + // 执行完整的类检查 + classDecl->Check(this); + + // 设置CHECKED标志并传播到所有子节点 + classDecl->AddAstNodeFlags(ir::AstNodeFlags::CHECKED); + classDecl->IterateRecursively([](ir::AstNode *node) -> void { + node->AddAstNodeFlags(ir::AstNodeFlags::CHECKED); + }); + } + } + } +} + +void ETSChecker::ClearPendingClassDefs() +{ + pendingClassDefs_.clear(); +} + +// // Lazy checker: 按需检查外部符号 +// void ETSChecker::CheckExternalSymbolOnDemand(ir::AstNode *symbolNode) +// { +// if (symbolNode == nullptr) { +// return; +// } + +// parser::Program *declProgram = nullptr; + +// // 获取符号所在的程序并检查是否已被标记 +// if (symbolNode->IsClassDeclaration()) { +// auto *classDecl = symbolNode->AsClassDeclaration(); +// if (classDecl->HasAstNodeFlags(ir::AstNodeFlags::CHECKED)) { +// return; // 已被检查过 +// } + +// // 安全获取程序 +// auto *topStatement = classDecl->GetTopStatement(); +// if (topStatement == nullptr || !topStatement->IsETSModule()) { +// return; // 无法获取程序 +// } +// declProgram = topStatement->AsETSModule()->Program(); +// } else if (symbolNode->IsTSInterfaceDeclaration()) { +// auto *interfaceDecl = symbolNode->AsTSInterfaceDeclaration(); +// if (interfaceDecl->HasAstNodeFlags(ir::AstNodeFlags::CHECKED)) { +// return; // 已被检查过 +// } + +// // 安全获取程序 +// auto *topStatement = interfaceDecl->GetTopStatement(); +// if (topStatement == nullptr || !topStatement->IsETSModule()) { +// return; // 无法获取程序 +// } +// declProgram = topStatement->AsETSModule()->Program(); +// } + +// if (declProgram == nullptr) { +// return; // 无法获取程序信息 +// } + +// auto *currentProgram = VarBinder()->Program(); +// if (currentProgram == declProgram) { +// return; // 不是外部符号 +// } + +// // 检查外部符号时,设置适当的上下文并调用完整的Check方法 +// // Check方法内部会处理所有必要的步骤: +// // 1. 基本属性构建 (BuildBasicClassProperties/BuildBasicInterfaceProperties) +// // 2. 依赖关系建立 (GetInterfaces, GetSuperType) +// // 3. 成员解析 (ResolveDeclaredMembersOfObject) +// // 4. 方法签名构建 (BuildFunctionSignature) +// // 5. 完整检查和验证 + +// auto *savedProgram = Program(); +// SetProgram(declProgram); + +// // 设置外部检查上下文,避免无限递归 +// checker::SavedCheckerContext savedContext(this, Context().Status(), Context().ContainingClass()); +// AddStatus(checker::CheckerStatus::IN_EXTERNAL); + +// try { +// // 调用完整的Check方法,让其内部处理所有依赖关系建立 +// symbolNode->Check(this); +// } catch (...) { +// // 如果检查失败,至少标记为已检查,避免重复尝试 +// symbolNode->AddAstNodeFlags(ir::AstNodeFlags::CHECKED); +// SetProgram(savedProgram); +// throw; +// } + +// SetProgram(savedProgram); +// } + void ETSChecker::CheckWarnings(parser::Program *program, const util::Options &options) { const auto &etsWarningCollection = options.GetEtsWarningCollection(); diff --git a/ets2panda/checker/ETSchecker.h b/ets2panda/checker/ETSchecker.h index b79f790e69..9aa9fdbb52 100644 --- a/ets2panda/checker/ETSchecker.h +++ b/ets2panda/checker/ETSchecker.h @@ -104,7 +104,8 @@ public: dynamicCallNames_ { {DynamicCallNamesMap(Allocator()->Adapter()), DynamicCallNamesMap(Allocator()->Adapter())}}, overloadSigContainer_(Allocator()->Adapter()), - readdedChecker_(Allocator()->Adapter()) + readdedChecker_(Allocator()->Adapter()), + pendingClassDefs_(Allocator()->Adapter()) { } @@ -891,6 +892,14 @@ public: void SetDebugInfoPlugin(evaluate::ScopedDebugInfoPlugin *debugInfo); + // Lazy checker: 管理搜集的classDef + void AddPendingClassDef(ir::ClassDefinition *classDef, CheckerStatus status); + void ProcessPendingClassDefs(); + void ClearPendingClassDefs(); + + // 获取主文件program,用于IsExternal判断 + parser::Program *GetMainFileProgram() const noexcept { return mainFileProgram_; } + using ClassBuilder = std::function *)>; using ClassInitializerBuilder = std::function *, ArenaVector *)>; @@ -967,6 +976,7 @@ public: } elementStack_.clear(); overloadSigContainer_.clear(); + pendingClassDefs_.clear(); } // This helper finds the intersection of two callSignatures sets @@ -1123,6 +1133,12 @@ private: std::unordered_set elementStack_; ArenaVector overloadSigContainer_; ArenaSet readdedChecker_; + + // Lazy checker: 搜集经过BuildBasicClassProperties的classDef和对应的CheckerStatus + ArenaVector> pendingClassDefs_; + + // 存储当前主文件对应的program,用于IsExternal判断 + parser::Program *mainFileProgram_ {nullptr}; }; } // namespace ark::es2panda::checker diff --git a/ets2panda/checker/ets/helpers.cpp b/ets2panda/checker/ets/helpers.cpp index d7eb47097e..f85d057827 100644 --- a/ets2panda/checker/ets/helpers.cpp +++ b/ets2panda/checker/ets/helpers.cpp @@ -1801,7 +1801,7 @@ void ETSChecker::SetPropertiesForModuleObject(checker::ETSObjectType *moduleObjT if (!program->IsASTChecked()) { // NOTE: helps to avoid endless loop in case of recursive imports that uses all bindings program->SetASTChecked(); - program->Ast()->Check(this); + //program->Ast()->Check(this); //TODO_Geng: do we need this? lazy checker } if (program->IsDeclForDynamicStaticInterop()) { BindingsModuleObjectAddProperty( diff --git a/ets2panda/checker/ets/object.cpp b/ets2panda/checker/ets/object.cpp index 82f486c79e..b89a73d605 100644 --- a/ets2panda/checker/ets/object.cpp +++ b/ets2panda/checker/ets/object.cpp @@ -55,11 +55,11 @@ namespace ark::es2panda::checker { static bool CheckGetterSetterDecl(varbinder::LocalVariable const *child, varbinder::LocalVariable const *parent) { auto readonlyCheck = [](varbinder::LocalVariable const *var, bool isParent, bool isReadonly) { - if (!var->TsType()->IsETSMethodType()) { + if (!var->TsTypeChecker()->IsETSMethodType()) { return true; } - auto *functionType = var->TsType()->AsETSFunctionType(); + auto *functionType = var->TsTypeChecker()->AsETSFunctionType(); auto getter = functionType->FindGetter(); if (getter == nullptr) { return false; @@ -79,7 +79,7 @@ static bool CheckGetterSetterDecl(varbinder::LocalVariable const *child, varbind bool checkChild = readonlyCheck(child, false, parent->Declaration()->Type() == varbinder::DeclType::READONLY); bool checkParent = readonlyCheck(parent, true, child->Declaration()->Type() == varbinder::DeclType::READONLY); - return checkChild && checkParent && (child->TsType()->IsETSFunctionType() || parent->TsType()->IsETSFunctionType()); + return checkChild && checkParent && (child->TsTypeChecker()->IsETSFunctionType() || parent->TsTypeChecker()->IsETSFunctionType()); } static bool CheckOverloadDecl(varbinder::LocalVariable *child, varbinder::LocalVariable *parent) @@ -112,12 +112,12 @@ static bool CheckFunctionDecl(varbinder::LocalVariable *child, varbinder::LocalV return false; } ES2PANDA_ASSERT(child->Declaration()->Type() == parent->Declaration()->Type()); - if (!child->TsType()->IsETSMethodType() || !parent->TsType()->IsETSMethodType()) { + if (!child->TsTypeChecker()->IsETSMethodType() || !parent->TsTypeChecker()->IsETSMethodType()) { return true; } - const auto *childType = child->TsType()->AsETSFunctionType(); - const auto *parentType = parent->TsType()->AsETSFunctionType(); + const auto *childType = child->TsTypeChecker()->AsETSFunctionType(); + const auto *parentType = parent->TsTypeChecker()->AsETSFunctionType(); bool childIsField = (childType->FindGetter() != nullptr) || (childType->FindSetter() != nullptr); bool parentIsField = (parentType->FindGetter() != nullptr) || (parentType->FindSetter() != nullptr); return childIsField == parentIsField; @@ -237,7 +237,7 @@ void ETSChecker::ValidateImplementedInterface(ETSObjectType *type, Type *interfa GetInterfaces(interface->AsETSObjectType()); auto *declNode = interface->AsETSObjectType()->GetDeclNode()->AsTSInterfaceDeclaration(); - if (declNode->TsType() != nullptr && declNode->TsType()->IsTypeError()) { + if (declNode->TsTypeChecker() != nullptr && declNode->TsTypeChecker()->IsTypeError()) { return; } type->AddInterface(interface->AsETSObjectType()); @@ -392,7 +392,7 @@ bool ETSChecker::CheckTypeParameterConstraint(ir::TSTypeParameter *param, Type2T void ETSChecker::SetUpTypeParameterConstraint(ir::TSTypeParameter *const param) { - ETSTypeParameter *const paramType = param->Name()->Variable()->TsType()->AsETSTypeParameter(); + ETSTypeParameter *const paramType = param->Name()->Variable()->TsTypeChecker()->AsETSTypeParameter(); auto const traverseReferenced = [this, scope = param->Parent()->AsTSTypeParameterDeclaration()->Scope()](ir::TypeNode *typeNode) { if (!typeNode->IsETSTypeReference()) { @@ -424,8 +424,8 @@ ETSTypeParameter *ETSChecker::SetUpParameterType(ir::TSTypeParameter *const para auto *const var = param->Name()->Variable(); ES2PANDA_ASSERT(var != nullptr); - if (var->TsType() != nullptr) { - return var->TsType()->AsETSTypeParameter(); + if (var->TsTypeChecker() != nullptr) { + return var->TsTypeChecker()->AsETSTypeParameter(); } auto *const paramType = CreateTypeParameter(); @@ -476,7 +476,7 @@ Type *ETSChecker::BuildBasicInterfaceProperties(ir::TSInterfaceDeclaration *inte checker::ETSObjectType *interfaceType {}; checker::Type *type {}; - if (var->TsType() == nullptr) { + if (var->TsTypeChecker() == nullptr) { interfaceType = CreateETSObjectTypeOrBuiltin(interfaceDecl, checker::ETSObjectFlags::INTERFACE); interfaceType->SetVariable(var); type = MaybeGradualType(interfaceDecl, interfaceType); @@ -518,6 +518,7 @@ Type *ETSChecker::BuildBasicInterfaceProperties(ir::TSInterfaceDeclaration *inte Type *ETSChecker::BuildBasicClassProperties(ir::ClassDefinition *classDef) { + if (classDef->IsFinal() && classDef->IsAbstract()) { LogError(diagnostic::ABSTRACT_IS_FINAL, {}, classDef->Start()); } @@ -530,7 +531,7 @@ Type *ETSChecker::BuildBasicClassProperties(ir::ClassDefinition *classDef) checker::ETSObjectType *classType {}; checker::Type *type {}; - if (var->TsType() == nullptr) { + if (var->TsTypeChecker() == nullptr) { classType = CreateETSObjectTypeOrBuiltin(classDef, checker::ETSObjectFlags::CLASS); type = MaybeGradualType(classDef, classType); classType->SetVariable(var); @@ -558,6 +559,10 @@ Type *ETSChecker::BuildBasicClassProperties(ir::ClassDefinition *classDef) classType->SetEnclosingType(enclosingClass); CheckerStatus newStatus = CheckerStatus::IN_CLASS; + if (classDef->IsAbstract()) { + newStatus |= CheckerStatus::IN_ABSTRACT; + } + if (classDef->IsInner()) { newStatus |= CheckerStatus::INNER_CLASS; classType->AddObjectFlag(checker::ETSObjectFlags::INNER); @@ -570,6 +575,8 @@ Type *ETSChecker::BuildBasicClassProperties(ir::ClassDefinition *classDef) GetInterfaces(classType); } ctScope.TryCheckConstraints(); + AddPendingClassDef(classDef, newStatus); + return type; } @@ -773,11 +780,11 @@ std::vector ETSChecker::CollectAbstractSignaturesFromObject(const E GetTypeOfVariable(prop); - if (!prop->TsType()->IsETSFunctionType()) { + if (!prop->TsTypeChecker()->IsETSFunctionType()) { continue; } - for (auto *sig : prop->TsType()->AsETSFunctionType()->CallSignatures()) { + for (auto *sig : prop->TsTypeChecker()->AsETSFunctionType()->CallSignatures()) { if (sig->HasSignatureFlag(SignatureFlags::ABSTRACT) && !sig->HasSignatureFlag(SignatureFlags::PRIVATE)) { abstracts.push_back(sig); } @@ -978,10 +985,10 @@ void ETSChecker::CheckInterfaceFunctions(ETSObjectType *classType) } ir::MethodDefinition *node = prop->Declaration()->Node()->AsMethodDefinition(); - if (prop->TsType()->IsTypeError()) { + if (prop->TsTypeChecker()->IsTypeError()) { continue; } - auto *funcType = prop->TsType()->AsETSFunctionType(); + auto *funcType = prop->TsTypeChecker()->AsETSFunctionType(); CallRedeclarationCheckForCorrectSignature(node, funcType, similarSignatures, classType, this); for (auto *const &overload : node->Overloads()) { CallRedeclarationCheckForCorrectSignature(overload, funcType, similarSignatures, classType, this); @@ -1225,11 +1232,11 @@ void ETSChecker::ValidateOverriding(ETSObjectType *classType, const lexer::Sourc void ETSChecker::AddImplementedSignature(std::vector *implementedSignatures, varbinder::LocalVariable *function, ETSFunctionType *it) { - if (!function->TsType()->IsETSFunctionType()) { + if (!function->TsTypeChecker()->IsETSFunctionType()) { return; } - for (auto signature : function->TsType()->AsETSFunctionType()->CallSignatures()) { + for (auto signature : function->TsTypeChecker()->AsETSFunctionType()->CallSignatures()) { if (signature->Function()->IsAbstract() || signature->Function()->IsStatic()) { continue; } @@ -1263,16 +1270,16 @@ void ETSChecker::CheckClassDefinition(ir::ClassDefinition *classDef) { classDef->SetClassDefinitionChecked(); - if (classDef->TsType() == nullptr) { + if (classDef->TsTypeChecker() == nullptr) { ES2PANDA_ASSERT(IsAnyError()); classDef->SetTsType(GlobalTypeError()); } - if (classDef->TsType()->IsTypeError()) { + if (classDef->TsTypeChecker()->IsTypeError()) { return; } - auto *classType = classDef->TsType()->MaybeBaseTypeOfGradualType()->AsETSObjectType(); + auto *classType = classDef->TsTypeChecker()->MaybeBaseTypeOfGradualType()->AsETSObjectType(); if (classType->SuperType() != nullptr) { classType->SuperType()->GetDeclNode()->Check(this); } @@ -1538,11 +1545,11 @@ void ETSChecker::CheckConstFieldInitialized(const ETSObjectType *classType, varb { const bool classVarStatic = classVar->Declaration()->Node()->AsClassProperty()->IsStatic(); for (const auto &prop : classType->Methods()) { - if (!prop->TsType()->IsETSFunctionType()) { + if (!prop->TsTypeChecker()->IsETSFunctionType()) { continue; } - const auto &callSigs = prop->TsType()->AsETSFunctionType()->CallSignatures(); + const auto &callSigs = prop->TsTypeChecker()->AsETSFunctionType()->CallSignatures(); for (const auto *signature : callSigs) { if ((signature->Function()->IsConstructor() && !classVarStatic) || (signature->Function()->IsStaticBlock() && classVarStatic)) { @@ -1745,7 +1752,7 @@ bool ETSChecker::ValidateTupleIndexFromEtsObject(const ETSTupleType *const tuple LogError(diagnostic::TUPLE_INDEX_NONCONST, {}, expr->Property()->Start()); return false; } - auto *exprType = value->TsType(); + auto *exprType = value->TsTypeChecker(); ES2PANDA_ASSERT(exprType != nullptr); if (!exprType->HasTypeFlag(TypeFlag::CONSTANT)) { LogError(diagnostic::TUPLE_INDEX_NONCONST, {}, expr->Property()->Start()); @@ -1830,7 +1837,7 @@ void ETSChecker::CheckCyclicConstructorCall(Signature *signature) ->Callee() ->IsThisExpression()) { auto *constructorCall = funcBody->Statements()[0]->AsExpressionStatement()->GetExpression()->AsCallExpression(); - if (constructorCall->TsType() == nullptr || constructorCall->TsType()->HasTypeFlag(TypeFlag::TYPE_ERROR)) { + if (constructorCall->TsTypeChecker() == nullptr || constructorCall->TsTypeChecker()->HasTypeFlag(TypeFlag::TYPE_ERROR)) { LogError(diagnostic::NO_SUCH_CTOR_SIG, {}, constructorCall->Start()); return; } @@ -1870,9 +1877,9 @@ void ETSChecker::ValidateNamespaceProperty(varbinder::Variable *property, const const ir::Identifier *ident) { ir::AstNode *parent = nullptr; - if (property->TsType() != nullptr && !property->TsType()->IsTypeError()) { - if (property->TsType()->IsETSMethodType()) { - auto funcType = property->TsType()->AsETSFunctionType(); + if (property->TsTypeChecker() != nullptr && !property->TsType()->IsTypeError()) { + if (property->TsTypeChecker()->IsETSMethodType()) { + auto funcType = property->TsTypeChecker()->AsETSFunctionType(); property = funcType->CallSignatures()[0]->OwnerVar(); ES2PANDA_ASSERT(property != nullptr); } else { @@ -1966,7 +1973,7 @@ varbinder::Variable *ETSChecker::GetExtensionFuncVarInGlobalField(const ir::Memb { auto propertyName = memberExpr->Property()->AsIdentifier()->Name(); auto *globalFieldVar = Scope()->FindInGlobal(propertyName, VO::STATIC_VARIABLES).variable; - if (globalFieldVar == nullptr || !IsExtensionETSFunctionType(globalFieldVar->TsType())) { + if (globalFieldVar == nullptr || !IsExtensionETSFunctionType(globalFieldVar->TsTypeChecker())) { return nullptr; } @@ -1977,7 +1984,7 @@ varbinder::Variable *ETSChecker::GetExtensionFuncVarInFunctionScope(const ir::Me { auto propertyName = memberExpr->Property()->AsIdentifier()->Name(); auto *funcScopeVar = Scope()->FindInFunctionScope(propertyName, VO::ALL).variable; - if (funcScopeVar == nullptr || !IsExtensionETSFunctionType(funcScopeVar->TsType())) { + if (funcScopeVar == nullptr || !IsExtensionETSFunctionType(funcScopeVar->TsTypeChecker())) { return nullptr; } return funcScopeVar; @@ -2054,7 +2061,7 @@ static bool ShouldRemoveStaticSearchFlag(const ir::MemberExpression *const membe const varbinder::Variable *targetRef) { if ((targetRef != nullptr && targetRef->Declaration() != nullptr && targetRef->Declaration()->IsLetOrConstDecl()) || - !memberExpr->Object()->TsType()->IsETSEnumType()) { + !memberExpr->Object()->TsTypeChecker()->IsETSEnumType()) { auto object = memberExpr->Object(); if (object->IsMemberExpression()) { object = object->AsMemberExpression()->Property(); @@ -2083,10 +2090,10 @@ PropertySearchFlags ETSChecker::GetSearchFlags(const ir::MemberExpression *const if (targetRef != nullptr && (targetRef->HasFlag(varbinder::VariableFlags::CLASS_OR_INTERFACE_OR_ENUM) || - // NOTE (DZ): need to investigate when and why `targetRef->TsType()->Variable()` can be `nullptr` + // NOTE (DZ): need to investigate when and why `targetRef->TsTypeChecker()->Variable()` can be `nullptr` // (see ast/parser/ets/union_static_method.ets) - (targetRef->HasFlag(varbinder::VariableFlags::TYPE_ALIAS) && targetRef->TsType()->Variable() != nullptr && - targetRef->TsType()->Variable()->HasFlag(varbinder::VariableFlags::CLASS_OR_INTERFACE)))) { + (targetRef->HasFlag(varbinder::VariableFlags::TYPE_ALIAS) && targetRef->TsTypeChecker()->Variable() != nullptr && + targetRef->TsTypeChecker()->Variable()->HasFlag(varbinder::VariableFlags::CLASS_OR_INTERFACE)))) { searchFlag &= ~PropertySearchFlags::SEARCH_INSTANCE; } else if (ShouldRemoveStaticSearchFlag(memberExpr, targetRef)) { searchFlag &= ~PropertySearchFlags::SEARCH_STATIC; @@ -2189,8 +2196,8 @@ std::vector ETSChecker::ValidateAccessor(ir::MemberExpression * varbinder::Variable *const eAcc, PropertySearchFlags searchFlag) { - auto *funcType = eAcc != nullptr ? eAcc->TsType()->AsETSFunctionType() : nullptr; - auto *propType = oAcc != nullptr ? oAcc->TsType()->AsETSFunctionType() : nullptr; + auto *funcType = eAcc != nullptr ? eAcc->TsTypeChecker()->AsETSFunctionType() : nullptr; + auto *propType = oAcc != nullptr ? oAcc->TsTypeChecker()->AsETSFunctionType() : nullptr; searchFlag = memberExpr->Parent()->IsUpdateExpression() ? searchFlag | PropertySearchFlags::IS_SETTER : searchFlag; // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) ETSFunctionType *finalRes = ResolveAccessorTypeByFlag(memberExpr, propType, funcType, searchFlag); @@ -2326,7 +2333,7 @@ std::vector ETSChecker::ResolveMemberReference(const ir::Member } if (globalFunctionVar != nullptr) { - ResolvedKind resolvedKind = DecideResolvedKind(globalFunctionVar->TsType()); + ResolvedKind resolvedKind = DecideResolvedKind(globalFunctionVar->TsTypeChecker()); if (IsExtensionAccessorCallUse(this, memberExpr, resolvedKind)) { LogError(diagnostic::EXTENSION_ACCESSOR_INVALID_CALL, {}, memberExpr->Start()); return resolveRes; @@ -2386,8 +2393,8 @@ void ETSChecker::CheckValidInheritance(ETSObjectType *classType, ir::ClassDefini for (auto *it : allProps) { auto *node = it->Declaration()->Node(); - if (node->IsClassProperty() && node->AsClassProperty()->TsType() != nullptr && - node->AsClassProperty()->TsType()->IsTypeError()) { + if (node->IsClassProperty() && node->AsClassProperty()->TsTypeChecker() != nullptr && + node->AsClassProperty()->TsTypeChecker()->IsTypeError()) { continue; } @@ -2423,7 +2430,7 @@ void ETSChecker::CheckValidInheritance(ETSObjectType *classType, ir::ClassDefini void ETSChecker::CheckProperties(ETSObjectType *classType, ir::ClassDefinition *classDef, varbinder::LocalVariable *it, varbinder::LocalVariable *found, ETSObjectType *interfaceFound) { - if (found->TsType() == nullptr) { + if (found->TsTypeChecker() == nullptr) { GetTypeOfVariable(found); } @@ -2495,12 +2502,12 @@ void ETSChecker::CheckReadonlyClassPropertyInImplementedInterface(ETSObjectType continue; } - ES2PANDA_ASSERT(propertyFound->TsType() != nullptr); - if (!propertyFound->TsType()->IsETSFunctionType()) { + ES2PANDA_ASSERT(propertyFound->TsTypeChecker() != nullptr); + if (!propertyFound->TsTypeChecker()->IsETSFunctionType()) { continue; } - auto setter = propertyFound->TsType()->AsETSFunctionType()->FindSetter(); + auto setter = propertyFound->TsTypeChecker()->AsETSFunctionType()->FindSetter(); if (setter != nullptr) { LogError(diagnostic::INTERFACE_PROPERTY_REQUIRES_SETTER, {interface->Name(), field->Name()}, field->Declaration()->Node()->Start()); @@ -2549,7 +2556,7 @@ void ETSChecker::TransformProperties(ETSObjectType *classType) void ETSChecker::CheckGetterSetterProperties(ETSObjectType *classType) { auto const checkGetterSetter = [this](varbinder::LocalVariable *var, util::StringView name) { - auto const *type = var->TsType()->AsETSFunctionType(); + auto const *type = var->TsTypeChecker()->AsETSFunctionType(); auto const *sigGetter = type->FindGetter(); auto const *sigSetter = type->FindSetter(); diff --git a/ets2panda/checker/ets/typeCheckingHelpers.cpp b/ets2panda/checker/ets/typeCheckingHelpers.cpp index 6496cdb8ce..116a150bdf 100644 --- a/ets2panda/checker/ets/typeCheckingHelpers.cpp +++ b/ets2panda/checker/ets/typeCheckingHelpers.cpp @@ -576,6 +576,23 @@ Type *ETSChecker::GetTypeFromVariableDeclaration(varbinder::Variable *const var) auto *classDef = var->Declaration()->Node()->AsClassDefinition(); BuildBasicClassProperties(classDef); variableType = classDef->TsType(); + + // Lazy checker: 如果是外部符号且没有被检查过,进行完整检查 + if (var->IsExternal(this->GetMainFileProgram()) && classDef->Parent()->IsClassDeclaration()) { + auto *classDecl = classDef->Parent()->AsClassDeclaration(); + if (!classDecl->HasAstNodeFlags(ir::AstNodeFlags::CHECKED)) { + // 为外部类检查设置正确的上下文,使用classDef直接判断状态 + CheckerStatus const status = CheckerStatus::IN_CLASS | + (classDef->IsAbstract() ? CheckerStatus::IN_ABSTRACT : CheckerStatus::NO_OPTS) | + (classDef->IsInner() ? CheckerStatus::INNER_CLASS : CheckerStatus::NO_OPTS); + + checker::SavedCheckerContext savedContext(this, status); + checker::ScopeContext scopeCtx(this, classDef->Scope()); + classDecl->Check(this); + } + // 设置变量为已检查状态 + var->SetChecked(true); + } break; } case varbinder::DeclType::CONST: @@ -599,9 +616,22 @@ Type *ETSChecker::GetTypeFromVariableDeclaration(varbinder::Variable *const var) variableType = GetTypeFromTypeAliasReference(var); break; - case varbinder::DeclType::INTERFACE: - variableType = BuildBasicInterfaceProperties(var->Declaration()->Node()->AsTSInterfaceDeclaration()); + case varbinder::DeclType::INTERFACE: { + auto *interfaceDecl = var->Declaration()->Node()->AsTSInterfaceDeclaration(); + variableType = BuildBasicInterfaceProperties(interfaceDecl); + + // Lazy checker: 如果是外部符号且没有被检查过,进行完整检查 + if (var->IsExternal(this->GetMainFileProgram()) && !interfaceDecl->HasAstNodeFlags(ir::AstNodeFlags::CHECKED)) { + // 为外部接口检查设置正确的上下文 + CheckerStatus const status = CheckerStatus::IN_INTERFACE; + checker::SavedCheckerContext savedContext(this, status); + checker::ScopeContext scopeCtx(this, interfaceDecl->Scope()); + interfaceDecl->Check(this); + } + // 设置变量为已检查状态 + var->SetChecked(true); break; + } case varbinder::DeclType::ANNOTATIONUSAGE: [[fallthrough]]; @@ -626,6 +656,11 @@ Type *ETSChecker::GetTypeOfVariable(varbinder::Variable *const var) return GetTypeOfSetterGetter(var); } + // Lazy checker: 对于外部符号,在 GetTypeFromVariableDeclaration 内部处理 + if (var->IsExternal(this->GetMainFileProgram()) && !var->IsChecked()) { + GetTypeFromVariableDeclaration(var); + } + if (var->TsType() != nullptr) { return var->TsType(); } diff --git a/ets2panda/compiler/core/ETSemitter.cpp b/ets2panda/compiler/core/ETSemitter.cpp index 71855bef27..dee87567c5 100644 --- a/ets2panda/compiler/core/ETSemitter.cpp +++ b/ets2panda/compiler/core/ETSemitter.cpp @@ -263,6 +263,10 @@ void ETSEmitter::GenAnnotation() } for (auto *classDecl : globalRecordTable->ClassDefinitions()) { + std::string className = classDecl->InternalName().Mutf8(); + if (className == "escompat.Position") { + std::cout << 101112 << std::endl; + } GenClassRecord(classDecl, classDecl->IsDeclare()); } @@ -317,20 +321,30 @@ void ETSEmitter::GenExternalRecord(varbinder::RecordTable *recordTable, const pa !recordTable->Program()->VarBinder()->IsGenStdLib() && !recordTable->Program()->IsGenAbcForExternal(); const auto *varbinder = static_cast(Context()->parserProgram->VarBinder()); auto baseName = varbinder->GetRecordTable()->RecordName().Mutf8(); + for (auto *annoDecl : recordTable->AnnotationDeclarations()) { - auto newBaseName = GenerateMangledName(baseName, annoDecl->GetBaseName()->Name().Mutf8()); - GenCustomAnnotationRecord(annoDecl, newBaseName, isExternalFromCompile || annoDecl->IsDeclare()); + if (annoDecl->HasAstNodeFlags(ir::AstNodeFlags::CHECKED)) { + auto newBaseName = GenerateMangledName(baseName, annoDecl->GetBaseName()->Name().Mutf8()); + GenCustomAnnotationRecord(annoDecl, newBaseName, isExternalFromCompile || annoDecl->IsDeclare()); + } } for (auto *classDecl : recordTable->ClassDefinitions()) { - GenClassRecord(classDecl, isExternalFromCompile || classDecl->IsDeclare()); + if (classDecl->HasAstNodeFlags(ir::AstNodeFlags::CHECKED)) { + GenClassRecord(classDecl, isExternalFromCompile || classDecl->IsDeclare()); + } } for (auto *interfaceDecl : recordTable->InterfaceDeclarations()) { - GenInterfaceRecord(interfaceDecl, isExternalFromCompile || interfaceDecl->IsDeclare()); + if (interfaceDecl->HasAstNodeFlags(ir::AstNodeFlags::CHECKED)) { + GenInterfaceRecord(interfaceDecl, isExternalFromCompile || interfaceDecl->IsDeclare()); + } } for (auto *signature : recordTable->Signatures()) { + if (!signature->Node()->HasAstNodeFlags(ir::AstNodeFlags::CHECKED)) { + continue; + } auto scriptFunc = signature->Node()->AsScriptFunction(); auto func = GenScriptFunction(scriptFunc, this); @@ -503,7 +517,7 @@ void ETSEmitter::GenGlobalArrayRecord(const checker::ETSArrayType *arrayType, ch void ETSEmitter::GenInterfaceRecord(const ir::TSInterfaceDeclaration *interfaceDecl, bool external) { - auto *baseType = interfaceDecl->TsType()->IsGradualType() + auto *baseType = interfaceDecl->TsTypeChecker()->IsGradualType() ? interfaceDecl->TsType()->AsGradualType()->GetBaseType()->AsETSObjectType() : interfaceDecl->TsType()->AsETSObjectType(); auto interfaceRecord = pandasm::Record(interfaceDecl->InternalName().Mutf8(), Program()->lang); @@ -521,6 +535,10 @@ void ETSEmitter::GenInterfaceRecord(const ir::TSInterfaceDeclaration *interfaceD GenClassInheritedFields(baseType, interfaceRecord); for (const auto *prop : interfaceDecl->Body()->Body()) { + // We don't need this because if the interface is checked, the body is also checked. + //if (!prop->HasAstNodeFlags(ir::AstNodeFlags::CHECKED)) { + // continue; + //} if (prop->IsClassProperty()) { GenClassField(prop->AsClassProperty(), interfaceRecord, external); } else if (prop->IsMethodDefinition()) { @@ -577,6 +595,11 @@ std::vector ETSEmitter::GenAnnotations(const ir::ClassD parent = parent->Parent(); } + std::string className = classDef->InternalName().Mutf8(); + if (className.find("escompat.Position") != std::string::npos) { + std::cout << "in GenAnnotations:" << className << std::endl; + } + auto classIdent = classDef->Ident()->Name().Mutf8(); bool isConstruct = classIdent == Signatures::JSNEW_CLASS; if (isConstruct || classIdent == Signatures::JSCALL_CLASS) { @@ -610,6 +633,10 @@ static uint32_t GetAccessFlags(const ir::ClassDefinition *classDef) void ETSEmitter::GenClassRecord(const ir::ClassDefinition *classDef, bool external) { + std::string className = classDef->InternalName().Mutf8(); + if (className.find("escompat.Position") != std::string::npos) { + std::cout << "in GenClassRecord:" << className << std::endl; + } auto classRecord = pandasm::Record(classDef->InternalName().Mutf8(), Program()->lang); uint32_t accessFlags = GetAccessFlags(classDef); classRecord.metadata->SetAccessFlags(accessFlags); @@ -953,6 +980,12 @@ pandasm::AnnotationData ETSEmitter::GenAnnotationModule(const ir::ClassDefinitio { std::vector exportedClasses {}; + std::string className = classDef->InternalName().Mutf8(); + if (className.find("escompat.Position") != std::string::npos) { + std::cout << "in GenAnnotationModule:" << className << std::endl; + } + + for (auto cls : classDef->ExportedClasses()) { exportedClasses.emplace_back(pandasm::ScalarValue::Create( pandasm::Type::FromName(cls->Definition()->InternalName().Utf8(), true))); @@ -998,6 +1031,11 @@ pandasm::AnnotationData ETSEmitter::GenAnnotationSignature(const ir::ClassDefini std::vector parts {}; const auto &typeParams = classDef->TypeParams()->Params(); + std::string className = classDef->InternalName().Mutf8(); + if (className.find("escompat.Position") != std::string::npos) { + std::cout << "in GenAnnotationSignature:" << className << std::endl; + } + auto const addStringValue = [&parts](std::string_view str) { parts.emplace_back(pandasm::ScalarValue::Create(str)); }; @@ -1078,6 +1116,11 @@ pandasm::AnnotationData ETSEmitter::GenAnnotationEnclosingClass(std::string_view pandasm::AnnotationData ETSEmitter::GenAnnotationInnerClass(const ir::ClassDefinition *classDef, const ir::AstNode *parent) { + std::string className = classDef->InternalName().Mutf8(); + if (className.find("escompat.Position") != std::string::npos) { + std::cout << "in GenAnnotationInnerClass:" << className << std::endl; + } + GenAnnotationRecord(Signatures::ETS_ANNOTATION_INNER_CLASS); pandasm::AnnotationData innerClass(Signatures::ETS_ANNOTATION_INNER_CLASS); const bool isAnonymous = (classDef->Modifiers() & ir::ClassDefinitionModifiers::ANONYMOUS) != 0; diff --git a/ets2panda/compiler/lowering/ets/ambientLowering.cpp b/ets2panda/compiler/lowering/ets/ambientLowering.cpp index 5e88122100..6981e54dae 100644 --- a/ets2panda/compiler/lowering/ets/ambientLowering.cpp +++ b/ets2panda/compiler/lowering/ets/ambientLowering.cpp @@ -29,8 +29,9 @@ std::string_view AmbientLowering::Name() const bool AmbientLowering::PostconditionForModule([[maybe_unused]] public_lib::Context *ctx, const parser::Program *program) { - return !program->Ast()->IsAnyChild( - [](const ir::AstNode *node) -> bool { return node->IsDummyNode() && node->AsDummyNode()->IsDeclareIndexer(); }); + return !program->Ast()->IsAnyChild([](const ir::AstNode *node) -> bool { + return node->IsDummyNode() && node->AsDummyNode()->IsDeclareIndexer(); + }); } bool AmbientLowering::PerformForModule(public_lib::Context *ctx, parser::Program *program) diff --git a/ets2panda/compiler/lowering/ets/asyncMethodLowering.cpp b/ets2panda/compiler/lowering/ets/asyncMethodLowering.cpp index 1affd68bbf..266d324943 100644 --- a/ets2panda/compiler/lowering/ets/asyncMethodLowering.cpp +++ b/ets2panda/compiler/lowering/ets/asyncMethodLowering.cpp @@ -206,7 +206,11 @@ bool AsyncMethodLowering::PerformForModule(public_lib::Context *ctx, parser::Pro { checker::ETSChecker *const checker = ctx->GetChecker()->AsETSChecker(); - ir::NodeTransformer handleClassAsyncMethod = [checker](ir::AstNode *const ast) { + ir::NodeTransformer handleClassAsyncMethod = [checker, this](ir::AstNode *const ast) { + if (!Phase::ShouldProcessNode(ast)) { + return ast; + } + if (ast->IsClassDefinition()) { UpdateClassDefintion(checker, ast->AsClassDefinition()); } diff --git a/ets2panda/compiler/lowering/ets/bigintLowering.cpp b/ets2panda/compiler/lowering/ets/bigintLowering.cpp index 46fced80e7..0c5f2f1360 100644 --- a/ets2panda/compiler/lowering/ets/bigintLowering.cpp +++ b/ets2panda/compiler/lowering/ets/bigintLowering.cpp @@ -165,7 +165,10 @@ bool BigIntLowering::PerformForModule(public_lib::Context *const ctx, parser::Pr program->Ast()->TransformChildrenRecursivelyPostorder( // CC-OFFNXT(G.FMT.14-CPP) project code style - [ctx, checker](ir::AstNode *ast) -> ir::AstNode * { + [ctx, checker, this](ir::AstNode *ast) -> ir::AstNode * { + if (!this->ShouldProcessNode(ast)) { + return ast; + } if (ast->IsBigIntLiteral() && ast->Parent() != nullptr && ast->Parent()->IsClassProperty()) { return CreateBigInt(ctx, ast->AsBigIntLiteral()); } diff --git a/ets2panda/compiler/lowering/ets/boxingForLocals.cpp b/ets2panda/compiler/lowering/ets/boxingForLocals.cpp index 0277b45394..2398b532f4 100644 --- a/ets2panda/compiler/lowering/ets/boxingForLocals.cpp +++ b/ets2panda/compiler/lowering/ets/boxingForLocals.cpp @@ -362,6 +362,9 @@ bool BoxingForLocals::PerformForModule(public_lib::Context *ctx, parser::Program parser::SavedFormattingFileName savedFormattingName(ctx->parser->AsETSParser(), "boxing-for-lambdas"); std::function searchForFunctions = [&](ir::AstNode *ast) { + if (!Phase::ShouldProcessNode(ast)) { + return; + } if (ast->IsScriptFunction()) { HandleScriptFunction(ctx, ast->AsScriptFunction()); // no recursion RefineSourceRanges(ast); @@ -375,7 +378,12 @@ bool BoxingForLocals::PerformForModule(public_lib::Context *ctx, parser::Program bool BoxingForLocals::PostconditionForModule([[maybe_unused]] public_lib::Context *ctx, parser::Program const *program) { - return !program->Ast()->IsAnyChild([](const ir::AstNode *node) { + return !program->Ast()->IsAnyChild([this](const ir::AstNode *node) { + // 跳过没有CHECKED标记的节点 + if (!Phase::ShouldProcessNode(node)) { + return false; + } + if (node->IsAssignmentExpression() && node->AsAssignmentExpression()->Left()->IsIdentifier()) { auto asExpr = node->AsAssignmentExpression(); auto var = asExpr->Left()->AsIdentifier()->Variable(); diff --git a/ets2panda/compiler/lowering/ets/cfgBuilderPhase.cpp b/ets2panda/compiler/lowering/ets/cfgBuilderPhase.cpp index 2bffe0888e..dbeeda850d 100644 --- a/ets2panda/compiler/lowering/ets/cfgBuilderPhase.cpp +++ b/ets2panda/compiler/lowering/ets/cfgBuilderPhase.cpp @@ -37,6 +37,10 @@ bool CFGBuilderPhase::Perform(public_lib::Context *ctx, parser::Program *program compiler::CFG *cfg = program->GetCFG(); program->Ast()->IterateRecursively([&](ir::AstNode *node) -> void { + if (!Phase::ShouldProcessNode(node)) { + return; + } + if (node->IsScriptFunction()) { cfg->Build(node->AsScriptFunction()); } diff --git a/ets2panda/compiler/lowering/ets/declareOverloadLowering.cpp b/ets2panda/compiler/lowering/ets/declareOverloadLowering.cpp index c65dccccc6..e1fe9c74ef 100644 --- a/ets2panda/compiler/lowering/ets/declareOverloadLowering.cpp +++ b/ets2panda/compiler/lowering/ets/declareOverloadLowering.cpp @@ -117,7 +117,10 @@ void UpdateCallSignature(public_lib::Context *ctx, ir::CallExpression *expr) bool DeclareOverloadLowering::PerformForModule(public_lib::Context *ctx, parser::Program *program) { // Note: Generate helper overload method - auto const transformMethodDef = [ctx](ir::AstNode *ast) { + auto const transformMethodDef = [ctx, this](ir::AstNode *ast) { + if (!Phase::ShouldProcessNode(ast)) { + return ast; + } if (ast->IsMethodDefinition() && ast->AsMethodDefinition()->GetOverloadInfo().needHelperOverload) { BuildOverloadHelperFunction(ctx, ast->AsMethodDefinition()); } @@ -125,8 +128,8 @@ bool DeclareOverloadLowering::PerformForModule(public_lib::Context *ctx, parser: }; // Note: Update signature for call expression - auto const transformCallExpr = [ctx](ir::AstNode *ast) { - if (!ast->IsCallExpression() || ast->AsCallExpression()->Signature() == nullptr) { + auto const transformCallExpr = [ctx, this](ir::AstNode *ast) { + if (!ast->IsCallExpression() || ast->AsCallExpression()->Signature() == nullptr || !Phase::ShouldProcessNode(ast)) { return ast; } if (ast->AsCallExpression()->Signature()->HasSignatureFlag(checker::SignatureFlags::DUPLICATE_ASM)) { diff --git a/ets2panda/compiler/lowering/ets/defaultParametersInConstructorLowering.cpp b/ets2panda/compiler/lowering/ets/defaultParametersInConstructorLowering.cpp index 3b7466ef9f..61c3017736 100644 --- a/ets2panda/compiler/lowering/ets/defaultParametersInConstructorLowering.cpp +++ b/ets2panda/compiler/lowering/ets/defaultParametersInConstructorLowering.cpp @@ -310,7 +310,7 @@ bool DefaultParametersInConstructorLowering::PerformForModule(public_lib::Contex bool DefaultParametersInConstructorLowering::PostconditionForModule([[maybe_unused]] public_lib::Context *ctx, parser::Program const *program) { - return !program->Ast()->IsAnyChild([](ir::AstNode const *node) { + return !program->Ast()->IsAnyChild([](ir::AstNode const *node) { if (!node->IsMethodDefinition() || !node->AsMethodDefinition()->IsConstructor()) { return false; } diff --git a/ets2panda/compiler/lowering/ets/enumPostCheckLowering.cpp b/ets2panda/compiler/lowering/ets/enumPostCheckLowering.cpp index abd8401d58..0da8d399b8 100644 --- a/ets2panda/compiler/lowering/ets/enumPostCheckLowering.cpp +++ b/ets2panda/compiler/lowering/ets/enumPostCheckLowering.cpp @@ -396,6 +396,11 @@ bool EnumPostCheckLoweringPhase::PerformForModule(public_lib::Context *ctx, pars program->Ast()->TransformChildrenRecursivelyPostorder( // clang-format off [this](ir::AstNode *const node) -> ir::AstNode* { + // 使用统一的节点处理检查 + if (!this->ShouldProcessNode(node)) { + return node; + } + if (node->HasAstNodeFlags(ir::AstNodeFlags::RECHECK)) { if (node->IsExpression()) { node->AsExpression()->SetTsType(nullptr); // force recheck diff --git a/ets2panda/compiler/lowering/ets/expandBrackets.cpp b/ets2panda/compiler/lowering/ets/expandBrackets.cpp index 2f865dca1e..265f5077bd 100644 --- a/ets2panda/compiler/lowering/ets/expandBrackets.cpp +++ b/ets2panda/compiler/lowering/ets/expandBrackets.cpp @@ -155,6 +155,9 @@ bool ExpandBracketsPhase::PerformForModule(public_lib::Context *ctx, parser::Pro { program->Ast()->TransformChildrenRecursively( [this, ctx](checker::AstNodePtr const ast) -> checker::AstNodePtr { + if (!Phase::ShouldProcessNode(ast)) { + return ast; + } if (ast->IsETSNewArrayInstanceExpression()) { return ProcessNewArrayInstanceExpression(ctx, ast->AsETSNewArrayInstanceExpression()); } diff --git a/ets2panda/compiler/lowering/ets/expressionLambdaLowering.cpp b/ets2panda/compiler/lowering/ets/expressionLambdaLowering.cpp index e09b2b2af2..fe6fec9da6 100644 --- a/ets2panda/compiler/lowering/ets/expressionLambdaLowering.cpp +++ b/ets2panda/compiler/lowering/ets/expressionLambdaLowering.cpp @@ -68,8 +68,13 @@ bool ExpressionLambdaConstructionPhase::PostconditionForModule([[maybe_unused]] const parser::Program *program) { return !program->Ast()->IsAnyChild([](const ir::AstNode *node) { - return node->IsArrowFunctionExpression() && - node->AsArrowFunctionExpression()->Function()->Body()->IsExpression(); + bool isArrowFunction = node->IsArrowFunctionExpression() && + node->AsArrowFunctionExpression()->Function()->Body()->IsExpression(); + + if (isArrowFunction) { + std::cout << "isArrowFunction" << node->DumpEtsSrc() << std::endl; + } + return isArrowFunction; }); } diff --git a/ets2panda/compiler/lowering/ets/extensionAccessorLowering.cpp b/ets2panda/compiler/lowering/ets/extensionAccessorLowering.cpp index 0ec34677b1..358ea2d5ba 100644 --- a/ets2panda/compiler/lowering/ets/extensionAccessorLowering.cpp +++ b/ets2panda/compiler/lowering/ets/extensionAccessorLowering.cpp @@ -133,7 +133,12 @@ bool ExtensionAccessorPhase::PerformForModule(public_lib::Context *ctx, parser:: checker::ETSChecker *const checker = ctx->GetChecker()->AsETSChecker(); program->Ast()->TransformChildrenRecursively( - [&checker](ir::AstNode *const node) -> AstNodePtr { return CheckAndReturnNode(checker, node); }, Name()); + [&checker, this](ir::AstNode *const node) -> AstNodePtr { + if (!Phase::ShouldProcessNode(node)) { + return node; + } + return CheckAndReturnNode(checker, node); + }, Name()); return true; } diff --git a/ets2panda/compiler/lowering/ets/genericBridgesLowering.cpp b/ets2panda/compiler/lowering/ets/genericBridgesLowering.cpp index e74ea9ce95..332d3678bb 100644 --- a/ets2panda/compiler/lowering/ets/genericBridgesLowering.cpp +++ b/ets2panda/compiler/lowering/ets/genericBridgesLowering.cpp @@ -349,6 +349,9 @@ bool GenericBridgesPhase::PerformForModule(public_lib::Context *ctx, parser::Pro program->Ast()->TransformChildrenRecursively( // CC-OFFNXT(G.FMT.14-CPP) project code style [this](ir::AstNode *ast) -> ir::AstNode * { + if (!Phase::ShouldProcessNode(ast)) { + return ast; + } if (ast->IsClassDefinition()) { return ProcessClassDefinition(ast->AsClassDefinition()); } diff --git a/ets2panda/compiler/lowering/ets/interfaceObjectLiteralLowering.cpp b/ets2panda/compiler/lowering/ets/interfaceObjectLiteralLowering.cpp index 4998efb733..b817bb6898 100644 --- a/ets2panda/compiler/lowering/ets/interfaceObjectLiteralLowering.cpp +++ b/ets2panda/compiler/lowering/ets/interfaceObjectLiteralLowering.cpp @@ -421,9 +421,12 @@ static bool CheckAbstractClassShouldGenerateAnonClass(ir::ClassDefinition *class return true; } -static void TransfromInterfaceDecl(public_lib::Context *ctx, parser::Program *program) +void InterfaceObjectLiteralLowering::TransfromInterfaceDecl(public_lib::Context *ctx, parser::Program *program) { - program->Ast()->IterateRecursivelyPostorder([ctx, program](ir::AstNode *ast) -> void { + program->Ast()->IterateRecursivelyPostorder([this, ctx, program](ir::AstNode *ast) -> void { + if (!this->ShouldProcessNode(ast)) { + return; + } if (ast->IsTSInterfaceDeclaration() && CheckInterfaceShouldGenerateAnonClass(ast->AsTSInterfaceDeclaration())) { GenerateAnonClassTypeFromInterface(ctx, ast->AsTSInterfaceDeclaration()); } else if (ast->IsClassDefinition() && ast != program->GlobalClass() && @@ -434,10 +437,11 @@ static void TransfromInterfaceDecl(public_lib::Context *ctx, parser::Program *pr }); } -static void TransfromInterfaceLiteral(public_lib::Context *ctx, parser::Program *program) +// 将静态函数改为成员函数 +void InterfaceObjectLiteralLowering::TransfromInterfaceLiteral(public_lib::Context *ctx, parser::Program *program) { - program->Ast()->IterateRecursivelyPostorder([ctx](ir::AstNode *ast) -> void { - if (!ast->IsObjectExpression()) { + program->Ast()->IterateRecursivelyPostorder([this, ctx](ir::AstNode *ast) -> void { + if (!ast->IsObjectExpression() || !this->ShouldProcessNode(ast)) { return; } auto objExpr = ast->AsObjectExpression(); @@ -463,14 +467,14 @@ bool InterfaceObjectLiteralLowering::Perform(public_lib::Context *ctx, parser::P varbinder->ResetTopScope(extProg->GlobalScope()); varbinder->SetRecordTable(varbinder->GetExternalRecordTable().at(extProg)); varbinder->SetProgram(extProg); - TransfromInterfaceDecl(ctx, extProg); + TransfromInterfaceDecl(ctx, extProg); // 改为成员函数调用 varbinder->SetProgram(savedProgram); varbinder->SetRecordTable(savedRecordTable); varbinder->ResetTopScope(savedTopScope); } } - TransfromInterfaceDecl(ctx, program); + TransfromInterfaceDecl(ctx, program); // 改为成员函数调用 for (auto &[_, extPrograms] : program->ExternalSources()) { (void)_; diff --git a/ets2panda/compiler/lowering/ets/interfaceObjectLiteralLowering.h b/ets2panda/compiler/lowering/ets/interfaceObjectLiteralLowering.h index 055e3a64b3..1b277313fa 100644 --- a/ets2panda/compiler/lowering/ets/interfaceObjectLiteralLowering.h +++ b/ets2panda/compiler/lowering/ets/interfaceObjectLiteralLowering.h @@ -24,6 +24,10 @@ class InterfaceObjectLiteralLowering : public Phase { public: std::string_view Name() const override; bool Perform(public_lib::Context *ctx, parser::Program *program) override; + +private: + void TransfromInterfaceDecl(public_lib::Context *ctx, parser::Program *program); + void TransfromInterfaceLiteral(public_lib::Context *ctx, parser::Program *program); }; } // namespace ark::es2panda::compiler diff --git a/ets2panda/compiler/lowering/ets/lambdaLowering.cpp b/ets2panda/compiler/lowering/ets/lambdaLowering.cpp index e4bd77c6fd..8a6f430fd3 100644 --- a/ets2panda/compiler/lowering/ets/lambdaLowering.cpp +++ b/ets2panda/compiler/lowering/ets/lambdaLowering.cpp @@ -1499,12 +1499,28 @@ bool LambdaConversionPhase::PerformForModule(public_lib::Context *ctx, parser::P } program->Ast()->TransformChildrenRecursivelyPostorder( - [ctx](ir::AstNode *node) { return BuildLambdaClassWhenNeeded(ctx, node); }, Name()); + [ctx, this](ir::AstNode *node) { + // 使用统一的节点处理检查 + if (!Phase::ShouldProcessNode(node)) { + return node; + } + return BuildLambdaClassWhenNeeded(ctx, node); + }, Name()); program->Ast()->TransformChildrenRecursivelyPreorder( - [ctx](ir::AstNode *node) { return LowerTypeNodeIfNeeded(ctx, node); }, Name()); + [ctx, this](ir::AstNode *node) { + // 使用统一的节点处理检查 + if (!Phase::ShouldProcessNode(node)) { + return node; + } + return LowerTypeNodeIfNeeded(ctx, node); + }, Name()); - auto insertInvokeIfNeeded = [ctx](ir::AstNode *node) { + auto insertInvokeIfNeeded = [ctx, this](ir::AstNode *node) { + // 使用统一的节点处理检查 + if (!Phase::ShouldProcessNode(node)) { + return node; + } if (node->IsCallExpression() && !IsFunctionOrMethodCall(ctx->GetChecker()->AsETSChecker(), node->AsCallExpression()) && !IsRedirectingConstructorCall(node->AsCallExpression())) { @@ -1522,7 +1538,14 @@ bool LambdaConversionPhase::PerformForModule(public_lib::Context *ctx, parser::P bool LambdaConversionPhase::PostconditionForModule([[maybe_unused]] public_lib::Context *ctx, parser::Program const *program) { - return !program->Ast()->IsAnyChild([](ir::AstNode const *node) { return node->IsArrowFunctionExpression(); }); + return !program->Ast()->IsAnyChild([this](ir::AstNode const *node) { + // 使用统一的节点处理检查 + if (!this->ShouldProcessNode(const_cast(node))) { + return false; + } + + return node->IsArrowFunctionExpression(); + }); } } // namespace ark::es2panda::compiler diff --git a/ets2panda/compiler/lowering/ets/objectIndexAccess.cpp b/ets2panda/compiler/lowering/ets/objectIndexAccess.cpp index c57d29aa9c..4427b4c57f 100644 --- a/ets2panda/compiler/lowering/ets/objectIndexAccess.cpp +++ b/ets2panda/compiler/lowering/ets/objectIndexAccess.cpp @@ -112,6 +112,9 @@ bool ObjectIndexLowering::PerformForModule(public_lib::Context *ctx, parser::Pro program->Ast()->TransformChildrenRecursively( // CC-OFFNXT(G.FMT.14-CPP) project code style [this, parser, checker](ir::AstNode *const ast) -> ir::AstNode * { + if (!Phase::ShouldProcessNode(ast)) { + return ast; + } if (ast->IsAssignmentExpression() && ast->AsAssignmentExpression()->Left()->IsMemberExpression()) { auto memberExpr = ast->AsAssignmentExpression()->Left()->AsMemberExpression(); if (memberExpr->Kind() == ir::MemberExpressionKind::ELEMENT_ACCESS && @@ -127,6 +130,9 @@ bool ObjectIndexLowering::PerformForModule(public_lib::Context *ctx, parser::Pro program->Ast()->TransformChildrenRecursively( // CC-OFFNXT(G.FMT.14-CPP) project code style [this, parser, checker](ir::AstNode *const ast) -> ir::AstNode * { + if (!Phase::ShouldProcessNode(ast)) { + return ast; + } if (ast->IsMemberExpression()) { auto memberExpr = ast->AsMemberExpression(); if (memberExpr->Kind() == ir::MemberExpressionKind::ELEMENT_ACCESS && @@ -144,7 +150,10 @@ bool ObjectIndexLowering::PerformForModule(public_lib::Context *ctx, parser::Pro bool ObjectIndexLowering::PostconditionForModule([[maybe_unused]] public_lib::Context *ctx, const parser::Program *program) { - return !program->Ast()->IsAnyChild([](const ir::AstNode *ast) { + return !program->Ast()->IsAnyChild([this](const ir::AstNode *ast) { + if (!Phase::ShouldProcessNode(ast)) { + return false; + } if (ast->IsMemberExpression()) { auto memberExpr = ast->AsMemberExpression(); if (memberExpr->Kind() == ir::MemberExpressionKind::ELEMENT_ACCESS && memberExpr->ObjType() != nullptr && diff --git a/ets2panda/compiler/lowering/ets/objectIterator.cpp b/ets2panda/compiler/lowering/ets/objectIterator.cpp index 94293d0079..a879bff021 100644 --- a/ets2panda/compiler/lowering/ets/objectIterator.cpp +++ b/ets2panda/compiler/lowering/ets/objectIterator.cpp @@ -200,6 +200,9 @@ bool ObjectIteratorLowering::PerformForModule(public_lib::Context *ctx, parser:: // clang-format off [this, ctx, &hasIterator](ir::AstNode *ast) -> ir::AstNode* { // clang-format on + if (!ast->HasAstNodeFlags(ir::AstNodeFlags::CHECKED)) { + return ast; + } if (ast->IsForOfStatement()) { if (auto const *const exprType = ast->AsForOfStatement()->Right()->TsType(); hasIterator(exprType) || (exprType != nullptr && exprType->IsETSUnionType() && diff --git a/ets2panda/compiler/lowering/ets/objectLiteralLowering.cpp b/ets2panda/compiler/lowering/ets/objectLiteralLowering.cpp index 0a17664868..5fd1f2379a 100644 --- a/ets2panda/compiler/lowering/ets/objectLiteralLowering.cpp +++ b/ets2panda/compiler/lowering/ets/objectLiteralLowering.cpp @@ -338,7 +338,10 @@ bool ObjectLiteralLowering::PerformForModule(public_lib::Context *ctx, parser::P { program->Ast()->TransformChildrenRecursively( // CC-OFFNXT(G.FMT.14-CPP) project code style - [ctx](ir::AstNode *ast) -> ir::AstNode * { + [ctx, this](ir::AstNode *ast) -> ir::AstNode * { + if (!Phase::ShouldProcessNode(ast)) { + return ast; + } // Skip processing invalid and dynamic objects if (ast->IsObjectExpression()) { auto *exprType = ast->AsObjectExpression()->TsType(); @@ -362,7 +365,10 @@ bool ObjectLiteralLowering::PostconditionForModule([[maybe_unused]] public_lib:: const parser::Program *program) { // In all object literal contexts (except dynamic) a substitution should take place - return !program->Ast()->IsAnyChild([](const ir::AstNode *ast) -> bool { + return !program->Ast()->IsAnyChild([this](const ir::AstNode *ast) -> bool { + if (!Phase::ShouldProcessNode(ast)) { + return false; + } return ast->IsObjectExpression() && ast->AsObjectExpression()->TsType()->IsETSObjectType(); }); } diff --git a/ets2panda/compiler/lowering/ets/opAssignment.cpp b/ets2panda/compiler/lowering/ets/opAssignment.cpp index d323d0006f..9146ee546b 100644 --- a/ets2panda/compiler/lowering/ets/opAssignment.cpp +++ b/ets2panda/compiler/lowering/ets/opAssignment.cpp @@ -428,7 +428,10 @@ static ir::AstNode *HandleUpdate(public_lib::Context *ctx, ir::UpdateExpression bool OpAssignmentLowering::PerformForModule(public_lib::Context *ctx, parser::Program *program) { program->Ast()->TransformChildrenRecursively( - [ctx](ir::AstNode *ast) { + [ctx, this](ir::AstNode *ast) { + if (!Phase::ShouldProcessNode(ast)) { + return ast; + } if (ast->IsAssignmentExpression() && ast->AsAssignmentExpression()->OperatorType() != lexer::TokenType::PUNCTUATOR_SUBSTITUTION) { return HandleOpAssignment(ctx, ast->AsAssignmentExpression()); @@ -448,7 +451,12 @@ bool OpAssignmentLowering::PerformForModule(public_lib::Context *ctx, parser::Pr bool OpAssignmentLowering::PostconditionForModule([[maybe_unused]] public_lib::Context *ctx, const parser::Program *program) { - return !program->Ast()->IsAnyChild([](const ir::AstNode *ast) { + return !program->Ast()->IsAnyChild([this](const ir::AstNode *ast) { + // 跳过没有CHECKED标记的节点 + if (!Phase::ShouldProcessNode(ast)) { + return false; + } + return (ast->IsAssignmentExpression() && ast->AsAssignmentExpression()->TsType() != nullptr && ast->AsAssignmentExpression()->OperatorType() != lexer::TokenType::PUNCTUATOR_SUBSTITUTION) || ast->IsUpdateExpression(); diff --git a/ets2panda/compiler/lowering/ets/optionalArgumentsLowering.cpp b/ets2panda/compiler/lowering/ets/optionalArgumentsLowering.cpp index c58a3b93f3..f271b1ec2a 100644 --- a/ets2panda/compiler/lowering/ets/optionalArgumentsLowering.cpp +++ b/ets2panda/compiler/lowering/ets/optionalArgumentsLowering.cpp @@ -63,7 +63,10 @@ bool OptionalArgumentsLowering::PerformForModule(public_lib::Context *ctx, parse { program->Ast()->TransformChildrenRecursivelyPreorder( // CC-OFFNXT(G.FMT.14-CPP) project code style - [ctx](ir::AstNode *const node) -> ir::AstNode * { + [ctx, this](ir::AstNode *const node) -> ir::AstNode * { + if (!Phase::ShouldProcessNode(node)) { + return node; + } if (node->IsCallExpression()) { auto callExpr = node->AsCallExpression(); if (callExpr->Signature() == nullptr) { @@ -88,7 +91,12 @@ bool OptionalArgumentsLowering::PerformForModule(public_lib::Context *ctx, parse bool OptionalArgumentsLowering::PostconditionForModule([[maybe_unused]] public_lib::Context *ctx, parser::Program const *program) { - return !program->Ast()->IsAnyChild([](ir::AstNode const *node) { + return !program->Ast()->IsAnyChild([this](ir::AstNode const *node) { + // 跳过没有CHECKED标记的节点 + if (!Phase::ShouldProcessNode(node)) { + return false; + } + if (!node->IsScriptFunction()) { return false; } diff --git a/ets2panda/compiler/lowering/ets/partialExportClassGen.cpp b/ets2panda/compiler/lowering/ets/partialExportClassGen.cpp index a0814250f8..1f8c760389 100644 --- a/ets2panda/compiler/lowering/ets/partialExportClassGen.cpp +++ b/ets2panda/compiler/lowering/ets/partialExportClassGen.cpp @@ -34,7 +34,10 @@ static void GeneratePartialDeclForExported(const public_lib::Context *const ctx, bool PartialExportClassGen::PerformForModule(public_lib::Context *const ctx, parser::Program *const program) { program->Ast()->TransformChildrenRecursively( - [ctx, program](ir::AstNode *const ast) { + [ctx, program, this](ir::AstNode *const ast) { + if (!Phase::ShouldProcessNode(ast)) { + return ast; + } if ((ast->IsClassDeclaration() || ast->IsTSInterfaceDeclaration()) && (ast->IsExported() || ast->IsDefaultExported())) { auto *const savedProg = ctx->GetChecker()->VarBinder()->AsETSBinder()->Program(); diff --git a/ets2panda/compiler/lowering/ets/recordLowering.cpp b/ets2panda/compiler/lowering/ets/recordLowering.cpp index 8c13718bc0..8812bc4880 100644 --- a/ets2panda/compiler/lowering/ets/recordLowering.cpp +++ b/ets2panda/compiler/lowering/ets/recordLowering.cpp @@ -69,6 +69,9 @@ bool RecordLowering::PerformForModule(public_lib::Context *ctx, parser::Program program->Ast()->TransformChildrenRecursively( // CC-OFFNXT(G.FMT.14-CPP) project code style [this, ctx](ir::AstNode *ast) -> ir::AstNode * { + if (!Phase::ShouldProcessNode(ast)) { + return ast; + } if (ast->IsObjectExpression()) { return UpdateObjectExpression(ast->AsObjectExpression(), ctx); } diff --git a/ets2panda/compiler/lowering/ets/spreadLowering.cpp b/ets2panda/compiler/lowering/ets/spreadLowering.cpp index fe71baaaf6..d7557ca008 100644 --- a/ets2panda/compiler/lowering/ets/spreadLowering.cpp +++ b/ets2panda/compiler/lowering/ets/spreadLowering.cpp @@ -369,7 +369,10 @@ bool SpreadConstructionPhase::PerformForModule(public_lib::Context *ctx, parser: varbinder::ETSBinder *const varbinder = checker->VarBinder()->AsETSBinder(); program->Ast()->TransformChildrenRecursively( - [&checker, &varbinder, &ctx](ir::AstNode *const node) -> AstNodePtr { + [&checker, &varbinder, &ctx, this](ir::AstNode *const node) -> AstNodePtr { + if (!this->ShouldProcessNode(node)) { + return node; + } if (node->IsArrayExpression() && std::any_of(node->AsArrayExpression()->Elements().begin(), node->AsArrayExpression()->Elements().end(), [](const auto *param) { return param->Type() == ir::AstNodeType::SPREAD_ELEMENT; })) { diff --git a/ets2panda/compiler/lowering/ets/stringComparison.cpp b/ets2panda/compiler/lowering/ets/stringComparison.cpp index 68d18c745e..583f862050 100644 --- a/ets2panda/compiler/lowering/ets/stringComparison.cpp +++ b/ets2panda/compiler/lowering/ets/stringComparison.cpp @@ -114,6 +114,9 @@ bool StringComparisonLowering::PerformForModule(public_lib::Context *ctx, parser [[maybe_unused]] ArenaVector foundNodes(checker->Allocator()->Adapter()); // CC-OFFNXT(G.FMT.14-CPP) project code style program->Ast()->IterateRecursively([&foundNodes, this](ir::AstNode *ast) -> ir::AstNode * { + if (!Phase::ShouldProcessNode(ast)) { + return ast; + } if (IsStringComparison(ast)) { foundNodes.push_back(ast->AsBinaryExpression()); } diff --git a/ets2panda/compiler/lowering/ets/stringConstructorLowering.cpp b/ets2panda/compiler/lowering/ets/stringConstructorLowering.cpp index 19429df0d3..b09e8b8d26 100644 --- a/ets2panda/compiler/lowering/ets/stringConstructorLowering.cpp +++ b/ets2panda/compiler/lowering/ets/stringConstructorLowering.cpp @@ -120,7 +120,10 @@ bool StringConstructorLowering::PerformForModule(public_lib::Context *const ctx, { program->Ast()->TransformChildrenRecursively( // CC-OFFNXT(G.FMT.14-CPP) project code style - [ctx](ir::AstNode *ast) -> ir::AstNode * { + [ctx, this](ir::AstNode *ast) -> ir::AstNode * { + if (!Phase::ShouldProcessNode(ast)) { + return ast; + } if (ast->IsETSNewClassInstanceExpression()) { return ReplaceStringConstructor(ctx, ast->AsETSNewClassInstanceExpression()); } diff --git a/ets2panda/compiler/lowering/ets/unionLowering.cpp b/ets2panda/compiler/lowering/ets/unionLowering.cpp index 1710ce3ed4..d205f392d0 100644 --- a/ets2panda/compiler/lowering/ets/unionLowering.cpp +++ b/ets2panda/compiler/lowering/ets/unionLowering.cpp @@ -215,7 +215,10 @@ bool UnionLowering::PerformForModule(public_lib::Context *ctx, parser::Program * checker::ETSChecker *checker = ctx->GetChecker()->AsETSChecker(); program->Ast()->TransformChildrenRecursively( - [ctx, checker](checker::AstNodePtr ast) -> checker::AstNodePtr { + [this, ctx, checker](checker::AstNodePtr ast) -> checker::AstNodePtr { + if (!Phase::ShouldProcessNode(ast)) { + return ast; + } if (ast->IsMemberExpression() && ast->AsMemberExpression()->Object()->TsType() != nullptr) { auto *objType = checker->GetApparentType(checker->GetNonNullishType(ast->AsMemberExpression()->Object()->TsType())); @@ -235,7 +238,10 @@ bool UnionLowering::PerformForModule(public_lib::Context *ctx, parser::Program * bool UnionLowering::PostconditionForModule(public_lib::Context *ctx, const parser::Program *program) { auto *checker = ctx->GetChecker()->AsETSChecker(); - bool current = !program->Ast()->IsAnyChild([checker](ir::AstNode *ast) { + bool current = !program->Ast()->IsAnyChild([this, checker](ir::AstNode *ast) { + if (!Phase::ShouldProcessNode(ast)) { + return false; + } if (!ast->IsMemberExpression() || ast->AsMemberExpression()->Object()->TsType() == nullptr) { return false; } diff --git a/ets2panda/compiler/lowering/phase.cpp b/ets2panda/compiler/lowering/phase.cpp index bc06d4dca0..85d296dcc0 100644 --- a/ets2panda/compiler/lowering/phase.cpp +++ b/ets2panda/compiler/lowering/phase.cpp @@ -428,6 +428,7 @@ void PhaseManager::InitializePhases() } int id = 0; + checkerPhaseId_ = -1; // 重置 checkerPhaseId for (auto phase : phases_) { // js side UI plugin needs an extra phaseID, which is different from c++ side plugin phase if (phase->Name() == std::string(g_pluginsAfterParse)) { @@ -442,6 +443,11 @@ void PhaseManager::InitializePhases() if (phase->Name() == std::string(g_pluginsAfterLowering)) { jsPluginAfterLower_ = id++; } + // 记录 CheckerPhase 的位置 + if (phase->Name() == CheckerPhase::NAME) { + checkerPhaseId_ = id; + } + phase->id_ = id++; } } @@ -487,4 +493,58 @@ int32_t PhaseManager::GetCurrentMinor() const return curr_.minor; } +bool PhaseManager::IsAfterOrEqualCheckerPhase() const +{ + return checkerPhaseId_ != -1 && curr_.minor > checkerPhaseId_; +} + +bool PhaseManager::IsAfterCheckerPhase() const +{ + // 如果找到了 CheckerPhase,并且当前阶段在它之后 + return checkerPhaseId_ != -1 && curr_.minor > checkerPhaseId_; +} + +bool Phase::ShouldProcessNode(const ir::AstNode *node) const +{ + if (node == nullptr) { + return false; + } + + // 获取当前阶段管理器 + PhaseManager *phaseManager = GetPhaseManager(); + + // 如果当前在 CheckerPhase 之前,总是处理所有节点 + if (!phaseManager->IsAfterCheckerPhase()) { + return true; + } + + // 如果在 CheckerPhase 之后,只处理带有 CHECKED 标志的节点 + return node->HasAstNodeFlags(ir::AstNodeFlags::CHECKED); +} +// TODO: 这个函数可以优化,只check顶层的class declaration和interface declaration +bool Phase::HasCheckedStatements(const parser::Program *program) const +{ + if (program->Ast() == nullptr) { + return false; + } + + // 获取当前阶段管理器 + PhaseManager *phaseManager = GetPhaseManager(); + + // 如果当前在 CheckerPhase 之前,总是处理所有语句 + // 因为CHECKED标志是在CheckerPhase中设置的 + if (!phaseManager->IsAfterCheckerPhase()) { + return true; + } + + // 如果在 CheckerPhase 之后,只有当存在CHECKED标志的语句时才处理 + for (auto *stmt : program->Ast()->Statements()) { + if (stmt->HasAstNodeFlags(ir::AstNodeFlags::CHECKED)) { + return true; + } + } + + return false; +} + } // namespace ark::es2panda::compiler diff --git a/ets2panda/compiler/lowering/phase.h b/ets2panda/compiler/lowering/phase.h index 63c3e493f4..fd87751d7c 100644 --- a/ets2panda/compiler/lowering/phase.h +++ b/ets2panda/compiler/lowering/phase.h @@ -21,6 +21,41 @@ #include "public/public.h" #include "phase_id.h" +// 便于使用的宏:在阶段的 perform 函数中检查节点是否应该被处理 +// +// 使用说明: +// 1. CheckerPhase 之前的阶段:总是处理所有节点,不需要检查 +// 2. CheckerPhase 之后的阶段:只处理带有 CHECKED 标志的节点 +// +// 用法示例: +// 在循环中使用 SKIP_IF_NOT_CHECKED: +// for (auto* node : nodes) { +// SKIP_IF_NOT_CHECKED(node); +// // 处理节点的代码... +// } +// +// 在 TransformChildrenRecursively 回调中使用 RETURN_IF_NOT_CHECKED: +// program->Ast()->TransformChildrenRecursively([this](ir::AstNode* node) { +// RETURN_IF_NOT_CHECKED(node); +// // 转换节点的代码... +// return node; +// }); +// +#define SKIP_IF_NOT_CHECKED(node) \ + do { \ + if (!this->ShouldProcessNode(node)) { \ + continue; \ + } \ + } while (0) + +// 用于返回的版本:如果节点不应该被处理则返回原节点 +#define RETURN_IF_NOT_CHECKED(node) \ + do { \ + if (!this->ShouldProcessNode(node)) { \ + return (node); \ + } \ + } while (0) + namespace ark::es2panda::compiler { class Phase { @@ -45,11 +80,19 @@ public: } virtual bool Perform(public_lib::Context *ctx, parser::Program *program) = 0; virtual bool Postcondition([[maybe_unused]] public_lib::Context *ctx, - [[maybe_unused]] const parser::Program *program) + [[maybe_unused]] const parser::Program *program) { return true; } + // 辅助方法:检查 AST 节点是否应该被处理 + // CheckerPhase 之前的阶段总是处理所有节点 + // CheckerPhase 之后的阶段只处理带有 CHECKED 标志的节点 + bool ShouldProcessNode(const ir::AstNode *node) const; + + // 辅助方法:检查程序中是否有被标记为CHECKED的语句 + bool HasCheckedStatements(const parser::Program *program) const; + private: friend class PhaseManager; int32_t id_ {INVALID_PHASE_ID}; @@ -193,6 +236,9 @@ public: int32_t GetCurrentMinor() const; std::vector GetSubPhases(const std::vector &phaseNames); + // 检查当前阶段是否在 CheckerPhase 之后 + bool IsAfterCheckerPhase() const; + bool IsAfterOrEqualCheckerPhase() const; private: void InitializePhases(); @@ -203,6 +249,7 @@ private: int32_t jsPluginAfterBind_ {0}; int32_t jsPluginAfterCheck_ {0}; int32_t jsPluginAfterLower_ {0}; + int32_t checkerPhaseId_ {-1}; // CheckerPhase 在阶段列表中的位置 ArenaAllocator *allocator_ {nullptr}; public_lib::Context *context_ {nullptr}; diff --git a/ets2panda/ir/astNodeFlags.h b/ets2panda/ir/astNodeFlags.h index 2f8281d0a0..4df5209e45 100644 --- a/ets2panda/ir/astNodeFlags.h +++ b/ets2panda/ir/astNodeFlags.h @@ -37,6 +37,7 @@ enum class AstNodeFlags : uint16_t { TMP_CONVERT_PRIMITIVE_CAST_METHOD_CALL = 1U << 8U, // Moved out of the ir::Expression IS_GROUPED = 1U << 9U, + CHECKED = 1U << 10U, // node has been checked /* do not introduce new flags. all the existing to be removed */ }; diff --git a/ets2panda/ir/base/classProperty.cpp b/ets2panda/ir/base/classProperty.cpp index 9fb04ee715..47487dc7af 100644 --- a/ets2panda/ir/base/classProperty.cpp +++ b/ets2panda/ir/base/classProperty.cpp @@ -305,7 +305,7 @@ ClassProperty *ClassProperty::Clone(ArenaAllocator *const allocator, AstNode *co value->SetParent(clone); } if (typeAnnotation != nullptr) { - typeAnnotation->SetTsType(typeAnnotation->TsType()); + typeAnnotation->SetTsType(typeAnnotation->TsTypeChecker()); typeAnnotation->SetParent(clone); } diff --git a/ets2panda/ir/ets/etsTypeReference.cpp b/ets2panda/ir/ets/etsTypeReference.cpp index 5ad9abc912..4a05fbdecb 100644 --- a/ets2panda/ir/ets/etsTypeReference.cpp +++ b/ets2panda/ir/ets/etsTypeReference.cpp @@ -114,8 +114,8 @@ checker::VerifiedType ETSTypeReference::Check(checker::ETSChecker *checker) } checker::Type *ETSTypeReference::GetType(checker::ETSChecker *checker) { - if (TsType() != nullptr) { - return TsType(); + if (TsTypeChecker() != nullptr) { + return TsTypeChecker(); } auto *type = Part()->GetType(checker); if (IsReadonlyType()) { diff --git a/ets2panda/ir/expressions/identifier.cpp b/ets2panda/ir/expressions/identifier.cpp index 57419e8539..05642168d4 100644 --- a/ets2panda/ir/expressions/identifier.cpp +++ b/ets2panda/ir/expressions/identifier.cpp @@ -68,7 +68,7 @@ Identifier *Identifier::Clone(ArenaAllocator *const allocator, AstNode *const pa auto *const clone = allocator->New(Tag {}, *this, allocator); ES2PANDA_ASSERT(clone != nullptr); - clone->SetTsType(TsType()); + clone->SetTsType(TsTypeChecker()); if (parent != nullptr) { clone->SetParent(parent); } diff --git a/ets2panda/ir/typed.cpp b/ets2panda/ir/typed.cpp new file mode 100644 index 0000000000..de54b96eca --- /dev/null +++ b/ets2panda/ir/typed.cpp @@ -0,0 +1,92 @@ +/** + * 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. + */ + +#include "ir/typed.h" +#include "checker/ETSchecker.h" +#include "ir/base/classDefinition.h" +#include "ir/statements/classDeclaration.h" +#include "ir/ts/tsInterfaceDeclaration.h" +#include "compiler/lowering/phase.h" +#include "public/public.h" + +namespace ark::es2panda::ir { + +template +checker::Type *Typed::TsType() +{ + auto *typedNode = AstNode::GetHistoryNodeAs>(); + if (typedNode->tsType_ != nullptr) { + return typedNode->tsType_; + } + + if (this->HasAstNodeFlags(ir::AstNodeFlags::CHECKED)) { + return nullptr; + } + + if (!compiler::GetPhaseManager()->IsAfterOrEqualCheckerPhase()) { + return nullptr; + } + + ir::AstNode *current = static_cast(this); + while (current != nullptr) { + if (current->IsClassDeclaration() || current->IsTSInterfaceDeclaration()) { + break; + } + current = current->Parent(); + } + + ES2PANDA_ASSERT(current != nullptr && (current->IsClassDeclaration() || current->IsTSInterfaceDeclaration())); + + auto *etsChecker = compiler::GetPhaseManager()->Context()->GetChecker()->AsETSChecker(); + if (etsChecker == nullptr) { + return nullptr; + } + + checker::CheckerStatus status = checker::CheckerStatus::NO_OPTS; + + if (current->IsClassDeclaration()) { + auto *classDecl = current->AsClassDeclaration(); + status = checker::CheckerStatus::IN_CLASS; + if (classDecl->Definition()->IsAbstract()) { + status |= checker::CheckerStatus::IN_ABSTRACT; + } + if (classDecl->Definition()->IsInner()) { + status |= checker::CheckerStatus::INNER_CLASS; + } + } else { + status = checker::CheckerStatus::IN_INTERFACE; + } + + checker::SavedCheckerContext savedContext(etsChecker, status); + varbinder::Scope *scope = current->IsClassDeclaration() ? current->AsClassDeclaration()->Definition()->Scope() + : current->AsTSInterfaceDeclaration()->Scope(); + checker::ScopeContext scopeCtx(etsChecker, scope); + + (void)current->Check(etsChecker); + + current->AddAstNodeFlags(ir::AstNodeFlags::CHECKED); + current->IterateRecursively( + [](ir::AstNode *node) -> void { node->AddAstNodeFlags(ir::AstNodeFlags::CHECKED); }); + + return AstNode::GetHistoryNodeAs>()->tsType_; +} + +template class Typed; +template class Typed>; +template class Typed; +template class Typed>; +template class Typed; + +} // namespace ark::es2panda::ir \ No newline at end of file diff --git a/ets2panda/ir/typed.h b/ets2panda/ir/typed.h index d5170eeb1d..8a58ced980 100644 --- a/ets2panda/ir/typed.h +++ b/ets2panda/ir/typed.h @@ -22,9 +22,14 @@ namespace ark::es2panda::checker { // NOLINTBEGIN(readability-redundant-declaration) bool IsTypeError(Type const *tp); +class ETSChecker; // NOLINTEND(readability-redundant-declaration) } // namespace ark::es2panda::checker +namespace ark::es2panda::varbinder { +class Scope; +} // namespace ark::es2panda::varbinder + namespace ark::es2panda::ir { template @@ -41,11 +46,19 @@ public: return AstNode::GetHistoryNodeAs>()->tsType_; } - [[nodiscard]] checker::Type *TsType() + [[nodiscard]] checker ::Type * TsTypeChecker() + { + return AstNode::GetHistoryNodeAs>()->tsType_; + } + + [[nodiscard]] checker ::Type * TsTypeChecker() const { return AstNode::GetHistoryNodeAs>()->tsType_; } + // 带checker参数的懒加载检查方法 + [[nodiscard]] checker::Type *TsType(); + checker::Type *SetTsType(checker::Type *tsType) noexcept { auto nowNode = AstNode::GetHistoryNodeAs>(); diff --git a/ets2panda/util/generateBin.cpp b/ets2panda/util/generateBin.cpp index 134b2c9511..0f8c52a2b7 100644 --- a/ets2panda/util/generateBin.cpp +++ b/ets2panda/util/generateBin.cpp @@ -44,6 +44,7 @@ static int OptimizeBytecode(ark::pandasm::Program *prog, const util::Options &op { if (options.GetOptLevel() != 0) { InitializeLogging(options); + reporter(diagnostic::EMIT_FAILED, {ark::pandasm::AsmEmitter::GetLastError()}); if (!ark::pandasm::AsmEmitter::Emit(options.GetOutput(), *prog, statp, mapsp, true)) { reporter(diagnostic::EMIT_FAILED, {ark::pandasm::AsmEmitter::GetLastError()}); return 1; @@ -51,6 +52,7 @@ static int OptimizeBytecode(ark::pandasm::Program *prog, const util::Options &op ark::bytecodeopt::g_options.SetOptLevel(options.GetOptLevel()); // Set default value instead of maximum set in ark::bytecodeopt::SetCompilerOptions() + return 1; ark::compiler::CompilerLogger::Init({"all"}); ark::compiler::g_options.SetCompilerMaxBytecodeSize(ark::compiler::g_options.GetCompilerMaxBytecodeSize()); ark::bytecodeopt::OptimizeBytecode(prog, mapsp, options.GetOutput(), options.IsDynamic(), true); diff --git a/ets2panda/varbinder/ETSBinder.cpp b/ets2panda/varbinder/ETSBinder.cpp index ff783ab436..4ad3b6cd74 100644 --- a/ets2panda/varbinder/ETSBinder.cpp +++ b/ets2panda/varbinder/ETSBinder.cpp @@ -649,6 +649,7 @@ void ETSBinder::ImportAllForeignBindings(const varbinder::Scope::VariableMap &gl (var->AsLocalVariable()->Declaration()->Node()->IsExported())) { auto variable = Program()->GlobalClassScope()->FindLocal(bindingName, ResolveBindingOptions::ALL); if (variable == nullptr || var == variable) { + var->AddFlag(VariableFlags::EXTERNAL); InsertForeignBinding(bindingName, var); continue; } @@ -660,6 +661,7 @@ void ETSBinder::ImportAllForeignBindings(const varbinder::Scope::VariableMap &gl // It will be a redeclaration error, but the imported element has not been placed among the bindings yet if (TopScope()->FindLocal(bindingName, ResolveBindingOptions::ALL) == nullptr) { + var->AddFlag(VariableFlags::EXTERNAL); InsertForeignBinding(bindingName, var); } @@ -675,12 +677,14 @@ void ETSBinder::ImportAllForeignBindings(const varbinder::Scope::VariableMap &gl for (const auto [bindingName, var] : importProgram->GlobalClassScope()->StaticMethodScope()->Bindings()) { if (!var->Declaration()->Node()->IsDefaultExported()) { + var->AddFlag(VariableFlags::EXTERNAL); InsertForeignBinding(bindingName, var); } } for (const auto [bindingName, var] : importProgram->GlobalClassScope()->StaticFieldScope()->Bindings()) { if (!var->Declaration()->Node()->IsDefaultExported()) { + var->AddFlag(VariableFlags::EXTERNAL); InsertForeignBinding(bindingName, var); } } @@ -1028,6 +1032,7 @@ bool ETSBinder::AddImportSpecifiersToTopBindings(Span re ThrowError(importSpecifier->Start(), diagnostic::IMPORT_NOT_FOUND, {imported}); return false; } + var->AddFlag(VariableFlags::EXTERNAL); InsertOrAssignForeignBinding(localName, var); return true; @@ -1052,6 +1057,7 @@ void ETSBinder::AddImportDefaultSpecifiersToTopBindings(SpanAddFlag(VariableFlags::EXTERNAL); importDefaultSpecifier->Local()->SetVariable(var); InsertOrAssignForeignBinding(importDefaultSpecifier->Local()->Name(), var); return; @@ -1059,6 +1065,7 @@ void ETSBinder::AddImportDefaultSpecifiersToTopBindings(SpanSource()); var != nullptr) { + var->AddFlag(VariableFlags::EXTERNAL); importDefaultSpecifier->Local()->SetVariable(var); InsertForeignBinding(importDefaultSpecifier->Local()->Name(), var); return; diff --git a/ets2panda/varbinder/scope.h b/ets2panda/varbinder/scope.h index 0ed9b12968..dbf9dd3625 100644 --- a/ets2panda/varbinder/scope.h +++ b/ets2panda/varbinder/scope.h @@ -41,6 +41,8 @@ namespace ark::es2panda::varbinder { SCOPE_TYPES(DECLARE_CLASSES) #undef DECLARE_CLASSES +class VariableScope; + template && std::is_base_of_v>, bool> = true> diff --git a/ets2panda/varbinder/variable.cpp b/ets2panda/varbinder/variable.cpp index 66885f4f0c..bab5775b80 100644 --- a/ets2panda/varbinder/variable.cpp +++ b/ets2panda/varbinder/variable.cpp @@ -13,23 +13,64 @@ * limitations under the License. */ -#include "variable.h" +#include "varbinder/variable.h" +#include "checker/ETSchecker.h" #include "checker/types/type.h" +#include "ir/base/classDefinition.h" +#include "ir/expressions/identifier.h" +#include "ir/statements/blockStatement.h" +#include "ir/statements/classDeclaration.h" +#include "ir/ets/etsModule.h" +#include "ir/ts/tsInterfaceDeclaration.h" +#include "parser/program/program.h" #include "varbinder/scope.h" +#include "compiler/lowering/phase.h" +#include "public/public.h" #include namespace ark::es2panda::varbinder { -LocalVariable::LocalVariable(Decl *decl, VariableFlags flags) : Variable(decl, flags) +bool Variable::IsExternal([[maybe_unused]] const parser::Program *mainFileProgram) const noexcept { - if (decl->IsConstDecl() || decl->IsReadonlyDecl()) { - flags_ |= VariableFlags::READONLY; + if (decl_ == nullptr) { + return false; } -} -LocalVariable::LocalVariable(VariableFlags flags) : Variable(flags) {} + if (decl_->IsImportDecl()) { + return true; + } + + if (HasFlag(VariableFlags::EXTERNAL)) { + return true; + } + + // 使用传入的主文件程序进行比较 + /* if (mainFileProgram != nullptr) { + auto mainFilePath = mainFileProgram->AbsoluteName(); + + // 获取变量声明所在文件路径 + auto *declNode = decl_->Node(); + if (declNode != nullptr) { + auto *declTopStatement = declNode->GetTopStatement(); + if (declTopStatement != nullptr && declTopStatement->IsETSModule()) { + auto *declEtsModule = declTopStatement->AsETSModule(); + auto *declProgram = declEtsModule->Program(); + if (declProgram != nullptr) { + auto declFilePath = declProgram->AbsoluteName(); + + // 如果变量声明文件与主文件不同,则认为是external + if (mainFilePath != declFilePath) { + return true; + } + } + } + } + } + */ + return false; +} const util::StringView &Variable::Name() const { @@ -38,6 +79,78 @@ const util::StringView &Variable::Name() const return decl_->Name(); } +checker::Type *Variable::TsType() const +{ + if (tsType_ != nullptr) { + return tsType_; + } + + ir::AstNode *declNode = decl_->Node(); + if (declNode == nullptr) { + return nullptr; + } + + if (declNode->HasAstNodeFlags(ir::AstNodeFlags::CHECKED)) { + return nullptr; + } + + if (!compiler::GetPhaseManager()->IsAfterOrEqualCheckerPhase()) { + return nullptr; + } + + auto *etsChecker = compiler::GetPhaseManager()->Context()->GetChecker()->AsETSChecker(); + if (etsChecker == nullptr) { + return nullptr; + } + + ir::AstNode *current = declNode; + while (current != nullptr) { + if (current->IsClassDeclaration() || current->IsTSInterfaceDeclaration()) { + break; + } + current = current->Parent(); + } + + ES2PANDA_ASSERT(current != nullptr && (current->IsClassDeclaration() || current->IsTSInterfaceDeclaration())); + + checker::CheckerStatus status = checker::CheckerStatus::NO_OPTS; + + if (current->IsClassDeclaration()) { + auto *classDecl = current->AsClassDeclaration(); + status = checker::CheckerStatus::IN_CLASS; + if (classDecl->Definition()->IsAbstract()) { + status |= checker::CheckerStatus::IN_ABSTRACT; + } + if (classDecl->Definition()->IsInner()) { + status |= checker::CheckerStatus::INNER_CLASS; + } + } else { + status = checker::CheckerStatus::IN_INTERFACE; + } + + checker::SavedCheckerContext savedContext(etsChecker, status); + varbinder::Scope *scope = current->IsClassDeclaration() ? current->AsClassDeclaration()->Definition()->Scope() + : current->AsTSInterfaceDeclaration()->Scope(); + checker::ScopeContext scopeCtx(etsChecker, scope); + + (void)current->Check(etsChecker); + + current->AddAstNodeFlags(ir::AstNodeFlags::CHECKED); + current->IterateRecursively( + [](ir::AstNode *node) -> void { node->AddAstNodeFlags(ir::AstNodeFlags::CHECKED); }); + + return const_cast(this)->tsType_; +} + +LocalVariable::LocalVariable(Decl *decl, VariableFlags flags) : Variable(decl, flags) +{ + if (decl->IsConstDecl() || decl->IsReadonlyDecl()) { + flags_ |= VariableFlags::READONLY; + } +} + +LocalVariable::LocalVariable(VariableFlags flags) : Variable(flags) {} + LocalVariable *LocalVariable::Copy(ArenaAllocator *allocator, Decl *decl) const { auto *var = allocator->New(decl, flags_); @@ -65,4 +178,5 @@ void EnumVariable::ResetDecl(Decl *decl) { decl_ = decl; } + } // namespace ark::es2panda::varbinder diff --git a/ets2panda/varbinder/variable.h b/ets2panda/varbinder/variable.h index be95eb82d3..24f8043afd 100644 --- a/ets2panda/varbinder/variable.h +++ b/ets2panda/varbinder/variable.h @@ -18,11 +18,13 @@ #include "varbinder/enumMemberResult.h" #include "varbinder/variableFlags.h" +#include "varbinder/declaration.h" #include "ir/irnode.h" namespace ark::es2panda::checker { class Type; enum class PropertyType; +class ETSChecker; // NOLINTBEGIN(readability-redundant-declaration) bool IsTypeError(Type const *tp); // NOLINTEND(readability-redundant-declaration) @@ -86,11 +88,14 @@ public: return flags_; } - [[nodiscard]] checker::Type *TsType() const + [[nodiscard]] checker::Type *TsTypeChecker() const { return tsType_; } + // 带checker参数的懒加载检查方法 + [[nodiscard]] checker::Type *TsType() const; + [[nodiscard]] Scope *GetScope() const noexcept { return scope_; @@ -131,7 +136,14 @@ public: { return HasFlag(VariableFlags::LEXICAL_BOUND); } - + [[nodiscard]] bool IsChecked() const noexcept + { + return isChecked_.load(std::memory_order_seq_cst); + } + void SetChecked(bool checked) { + isChecked_.store(checked, std::memory_order_seq_cst); + } + [[nodiscard]] bool IsExternal([[maybe_unused]] const parser::Program *mainFileProgram) const noexcept; [[nodiscard]] const util::StringView &Name() const; virtual void SetLexical(Scope *scope) = 0; @@ -147,6 +159,7 @@ protected: private: checker::Type *tsType_ {}; Scope *scope_ {}; + std::atomic isChecked_ {false}; //should be atomic in multithreading case }; class LocalVariable : public Variable { diff --git a/ets2panda/varbinder/variableFlags.h b/ets2panda/varbinder/variableFlags.h index 12d8b6ff8c..7c11ee0c89 100644 --- a/ets2panda/varbinder/variableFlags.h +++ b/ets2panda/varbinder/variableFlags.h @@ -168,6 +168,7 @@ enum class VariableFlags : uint64_t { DYNAMIC = 1ULL << 37ULL, OVERLOAD = 1ULL << 38ULL, + EXTERNAL = 1ULL << 39ULL, HOIST_VAR = HOIST | VAR, CLASS_OR_INTERFACE = CLASS | INTERFACE, CLASS_OR_INTERFACE_OR_ENUM = CLASS_OR_INTERFACE | ENUM_LITERAL, -- Gitee From b61b0ac8ab1be7af01b23061d207bc245953b150 Mon Sep 17 00:00:00 2001 From: Geng Chen Date: Fri, 18 Jul 2025 16:52:03 +0800 Subject: [PATCH 2/3] use the tstypecheck instead of tstype in the "will check" cases --- ets2panda/ast_verifier/helpers.cpp | 8 ++++---- .../invariants/sequenceExpressionHasLastType.cpp | 4 ++-- ets2panda/checker/ETSAnalyzerHelpers.cpp | 2 +- ets2panda/checker/ETSchecker.cpp | 8 ++++---- ets2panda/checker/TSAnalyzer.cpp | 14 +++++++------- ets2panda/checker/TSchecker.cpp | 2 +- ets2panda/checker/checkerContext.cpp | 2 +- ets2panda/checker/ets/function.cpp | 16 ++++++++-------- ets2panda/checker/ets/helpers.cpp | 14 +++++++------- ets2panda/checker/ets/typeCheckingHelpers.cpp | 14 +++++++------- ets2panda/checker/ets/utilityTypeHandlers.cpp | 4 ++-- ets2panda/checker/ts/destructuringContext.cpp | 2 +- ets2panda/checker/ts/function.cpp | 2 +- ets2panda/checker/ts/helpers.cpp | 2 +- ets2panda/checker/ts/object.cpp | 2 +- ets2panda/checker/types/ets/etsObjectType.cpp | 2 +- ets2panda/checker/types/ts/objectLiteralType.cpp | 2 +- ets2panda/checker/types/type.cpp | 2 +- ets2panda/compiler/base/condition.cpp | 2 +- ets2panda/compiler/core/ETSCompiler.cpp | 4 ++-- ets2panda/compiler/core/ETSfunction.cpp | 2 +- ets2panda/compiler/core/emitter.cpp | 2 +- .../lowering/ets/arrayLiteralLowering.cpp | 2 +- .../compiler/lowering/ets/bigintLowering.cpp | 6 +++--- .../lowering/ets/enumPostCheckLowering.cpp | 4 ++-- .../lowering/ets/genericBridgesLowering.cpp | 2 +- .../lowering/ets/gradualTypeNarrowing.cpp | 6 +++--- .../ets/interfaceObjectLiteralLowering.cpp | 4 ++-- .../compiler/lowering/ets/lambdaLowering.cpp | 10 +++++----- .../lowering/ets/objectLiteralLowering.cpp | 2 +- ets2panda/compiler/lowering/ets/opAssignment.cpp | 4 ++-- .../compiler/lowering/ets/setterLowering.cpp | 2 +- .../compiler/lowering/ets/spreadLowering.cpp | 2 +- .../compiler/lowering/ets/stringComparison.cpp | 2 +- .../compiler/lowering/ets/unboxLowering.cpp | 8 ++++---- .../compiler/lowering/ets/unionLowering.cpp | 6 +++--- ets2panda/declgen_ets2ts/declgenEts2Ts.cpp | 10 +++++----- ets2panda/ir/ets/etsTypeReferencePart.cpp | 4 ++-- ets2panda/ir/ets/etsUnionType.cpp | 4 ++-- ets2panda/ir/expressions/memberExpression.cpp | 4 ++-- replace_tstype.sh | 16 ++++++++++++++++ 41 files changed, 113 insertions(+), 97 deletions(-) create mode 100644 replace_tstype.sh diff --git a/ets2panda/ast_verifier/helpers.cpp b/ets2panda/ast_verifier/helpers.cpp index a2179fc411..c02d5d07cf 100644 --- a/ets2panda/ast_verifier/helpers.cpp +++ b/ets2panda/ast_verifier/helpers.cpp @@ -51,7 +51,7 @@ bool IsBooleanType(const ir::AstNode *ast) } auto typedAst = static_cast(ast); - if (typedAst->TsType() == nullptr) { + if (typedAst->TsTypeChecker() == nullptr) { return false; } @@ -75,7 +75,7 @@ bool IsValidTypeForBinaryOp(const ir::AstNode *ast, bool isBitwise) } auto typedAst = static_cast(ast); - if (typedAst->TsType() == nullptr) { + if (typedAst->TsTypeChecker() == nullptr) { return false; } @@ -111,7 +111,7 @@ bool IsStringType(const ir::AstNode *ast) } auto typedAst = static_cast(ast); - if (typedAst->TsType() == nullptr) { + if (typedAst->TsTypeChecker() == nullptr) { return false; } @@ -307,7 +307,7 @@ bool ValidateMethodAccess(const ir::MemberExpression *memberExpression, const ir { // NOTE: need to refactor: type of member expression object can be obtained via // me->ObjType() or me->Object()->TsType() and they may differ!!!! - if (memberExpression->Object()->TsType() != nullptr) { + if (memberExpression->Object()->TsTypeChecker() != nullptr) { // When calling enum methods member expression // object has ETSEnumType instead of ETSObjectType. const auto *const type = memberExpression->Object()->TsType(); diff --git a/ets2panda/ast_verifier/invariants/sequenceExpressionHasLastType.cpp b/ets2panda/ast_verifier/invariants/sequenceExpressionHasLastType.cpp index 07413cf7be..6654db3c2d 100644 --- a/ets2panda/ast_verifier/invariants/sequenceExpressionHasLastType.cpp +++ b/ets2panda/ast_verifier/invariants/sequenceExpressionHasLastType.cpp @@ -31,11 +31,11 @@ namespace ark::es2panda::compiler::ast_verifier { } const auto *expr = ast->AsSequenceExpression(); const auto *last = expr->Sequence().back(); - if (expr->TsType() == nullptr) { + if (expr->TsTypeChecker() == nullptr) { AddCheckMessage("Sequence expression type is null", *expr); return {CheckDecision::INCORRECT, CheckAction::CONTINUE}; } - if (last->TsType() == nullptr) { + if (last->TsTypeChecker() == nullptr) { AddCheckMessage("Sequence expression last type is null", *last); return {CheckDecision::INCORRECT, CheckAction::CONTINUE}; } diff --git a/ets2panda/checker/ETSAnalyzerHelpers.cpp b/ets2panda/checker/ETSAnalyzerHelpers.cpp index d6f3174596..0ca021713e 100644 --- a/ets2panda/checker/ETSAnalyzerHelpers.cpp +++ b/ets2panda/checker/ETSAnalyzerHelpers.cpp @@ -555,7 +555,7 @@ checker::Type *GetIteratorType(ETSChecker *checker, checker::Type *elemType, ir: // Just to avoid extra nested level(s) // CC-OFFNXT(G.FMT.14-CPP) project code style auto const getIterType = [checker, elemType](ir::VariableDeclarator *const declarator) -> checker::Type * { - if (declarator->TsType() == nullptr) { + if (declarator->TsTypeChecker() == nullptr) { if (auto *resolved = checker->FindVariableInFunctionScope(declarator->Id()->AsIdentifier()->Name()); resolved != nullptr) { resolved->SetTsType(elemType); diff --git a/ets2panda/checker/ETSchecker.cpp b/ets2panda/checker/ETSchecker.cpp index ab78a38629..72ec1f1f36 100644 --- a/ets2panda/checker/ETSchecker.cpp +++ b/ets2panda/checker/ETSchecker.cpp @@ -291,10 +291,10 @@ void ETSChecker::InitializeBuiltins(varbinder::ETSBinder *varbinder) } if (var->HasFlag(varbinder::VariableFlags::BUILTIN_TYPE)) { - if (var->TsType() == nullptr) { + if (var->TsTypeChecker() == nullptr) { InitializeBuiltin(var, name); } else { - GetGlobalTypesHolder()->InitializeBuiltin(name, var->TsType()); + GetGlobalTypesHolder()->InitializeBuiltin(name, var->TsTypeChecker()); } } } @@ -513,11 +513,11 @@ void ETSChecker::CheckWarnings(parser::Program *program, const util::Options &op Type *ETSChecker::CheckTypeCached(ir::Expression *expr) { - if (expr->TsType() == nullptr) { + if (expr->TsTypeChecker() == nullptr) { expr->SetTsType(expr->Check(this)); } - return expr->TsType(); + return expr->TsTypeChecker(); } bool ETSChecker::IsClassStaticMethod(checker::ETSObjectType *objType, checker::Signature *signature) diff --git a/ets2panda/checker/TSAnalyzer.cpp b/ets2panda/checker/TSAnalyzer.cpp index 655c154d5f..61d0107e5e 100644 --- a/ets2panda/checker/TSAnalyzer.cpp +++ b/ets2panda/checker/TSAnalyzer.cpp @@ -62,7 +62,7 @@ checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::MetaProperty *expr) const checker::Type *TSAnalyzer::Check(ir::TSIndexSignature *node) const { TSChecker *checker = GetTSChecker(); - if (node->TsType() != nullptr) { + if (node->TsTypeChecker() != nullptr) { return node->TsType(); } @@ -137,7 +137,7 @@ checker::Type *TSAnalyzer::Check(ir::TSPropertySignature *node) const checker::Type *TSAnalyzer::Check(ir::TSSignatureDeclaration *node) const { TSChecker *checker = GetTSChecker(); - if (node->TsType() != nullptr) { + if (node->TsTypeChecker() != nullptr) { return node->TsType(); } @@ -326,7 +326,7 @@ checker::Type *TSAnalyzer::Check(ir::ArrowFunctionExpression *expr) const expr->Function()); checker::Type *funcType = checker->CreateFunctionTypeWithSignature(signature); - if (funcVar != nullptr && funcVar->TsType() == nullptr) { + if (funcVar != nullptr && funcVar->TsTypeChecker() == nullptr) { funcVar->SetTsType(funcType); } ES2PANDA_ASSERT(signature != nullptr); @@ -569,7 +569,7 @@ checker::Type *TSAnalyzer::Check(ir::FunctionExpression *expr) const expr->Function()); checker::Type *funcType = checker->CreateFunctionTypeWithSignature(signature); - if (funcVar != nullptr && funcVar->TsType() == nullptr) { + if (funcVar != nullptr && funcVar->TsTypeChecker() == nullptr) { funcVar->SetTsType(funcType); } ES2PANDA_ASSERT(signature != nullptr); @@ -1210,7 +1210,7 @@ checker::Type *TSAnalyzer::Check(ir::FunctionDeclaration *st) const checker::ScopeContext scopeCtx(checker, st->Function()->Scope()); - if (result.variable->TsType() == nullptr) { + if (result.variable->TsTypeChecker() == nullptr) { checker->InferFunctionDeclarationType(result.variable->Declaration()->AsFunctionDecl(), result.variable); } @@ -1852,7 +1852,7 @@ checker::Type *TSAnalyzer::Check(ir::TSEnumDeclaration *st) const varbinder::Variable *enumVar = st->Key()->Variable(); ES2PANDA_ASSERT(enumVar); - if (enumVar->TsType() == nullptr) { + if (enumVar->TsTypeChecker() == nullptr) { checker::ScopeContext scopeCtx(checker, st->Scope()); checker::Type *enumType = InferType(checker, st->IsConst(), st); ES2PANDA_ASSERT(enumType != nullptr); @@ -2083,7 +2083,7 @@ checker::Type *TSAnalyzer::Check(ir::TSTypeLiteral *node) const checker::Type *TSAnalyzer::Check(ir::TSTypeQuery *node) const { TSChecker *checker = GetTSChecker(); - if (node->TsType() != nullptr) { + if (node->TsTypeChecker() != nullptr) { return node->TsType(); } diff --git a/ets2panda/checker/TSchecker.cpp b/ets2panda/checker/TSchecker.cpp index 4fe4acde54..efc95015b5 100644 --- a/ets2panda/checker/TSchecker.cpp +++ b/ets2panda/checker/TSchecker.cpp @@ -46,7 +46,7 @@ bool TSChecker::StartChecker([[maybe_unused]] varbinder::VarBinder *varbinder, c Type *TSChecker::CheckTypeCached(ir::Expression *expr) { - if (expr->TsType() == nullptr) { + if (expr->TsTypeChecker() == nullptr) { expr->SetTsType(expr->Check(this)); } diff --git a/ets2panda/checker/checkerContext.cpp b/ets2panda/checker/checkerContext.cpp index b8da863c9b..369dfd7386 100644 --- a/ets2panda/checker/checkerContext.cpp +++ b/ets2panda/checker/checkerContext.cpp @@ -350,7 +350,7 @@ void CheckerContext::CheckBinarySmartCastCondition(ir::BinaryExpression *const b if (auto const operatorType = binaryExpression->OperatorType(); operatorType == lexer::TokenType::KEYW_INSTANCEOF) { if (binaryExpression->Left()->IsIdentifier()) { - if (binaryExpression->Right()->TsType() == nullptr) { + if (binaryExpression->Right()->TsTypeChecker() == nullptr) { return; } // NOTE(pantos) Issue with generics diff --git a/ets2panda/checker/ets/function.cpp b/ets2panda/checker/ets/function.cpp index 53741e08a3..4097ac6451 100644 --- a/ets2panda/checker/ets/function.cpp +++ b/ets2panda/checker/ets/function.cpp @@ -216,10 +216,10 @@ static void RemoveInvalidTypeMarkers(ir::AstNode *node) noexcept { std::function doNode = [&](ir::AstNode *nn) { if (nn->IsTyped() && !(nn->IsExpression() && nn->AsExpression()->IsTypeNode()) && - nn->AsTyped()->TsType() != nullptr && nn->AsTyped()->TsType()->IsTypeError()) { + nn->AsTyped()->TsTypeChecker() != nullptr && nn->AsTyped()->TsType()->IsTypeError()) { nn->AsTyped()->SetTsType(nullptr); } - if (nn->IsIdentifier() && nn->AsIdentifier()->TsType() != nullptr && + if (nn->IsIdentifier() && nn->AsIdentifier()->TsTypeChecker() != nullptr && nn->AsIdentifier()->TsType()->IsTypeError()) { nn->AsIdentifier()->SetVariable(nullptr); } @@ -1443,12 +1443,12 @@ static bool CollectOverload(checker::ETSChecker *checker, ir::MethodDefinition * return false; } - auto *const overloadType = currentFunc->TsType() != nullptr ? currentFunc->TsType()->AsETSFunctionType() + auto *const overloadType = currentFunc->TsTypeChecker() != nullptr ? currentFunc->TsType()->AsETSFunctionType() : checker->BuildMethodType(currentFunc->Function()); ldInfo.needHelperOverload |= checker->CheckIdenticalOverloads(funcType, overloadType, currentFunc, ldInfo.isDeclare); - if (currentFunc->TsType() == nullptr) { + if (currentFunc->TsTypeChecker() == nullptr) { currentFunc->SetTsType(overloadType); } @@ -1481,7 +1481,7 @@ static bool CollectOverload(checker::ETSChecker *checker, ir::MethodDefinition * checker::Type *ETSChecker::BuildMethodSignature(ir::MethodDefinition *method) { - if (method->TsType() != nullptr) { + if (method->TsTypeChecker() != nullptr) { return method->TsType()->AsETSFunctionType(); } auto *methodId = method->Id(); @@ -1596,7 +1596,7 @@ static bool AppendSignatureInfoParam(ETSChecker *checker, SignatureInfo *sigInfo auto type = param->TypeAnnotation()->GetType(checker); return param->IsOptional() ? checker->CreateETSUnionType({type, checker->GlobalETSUndefinedType()}) : type; } - if (param->Ident()->TsType() != nullptr) { + if (param->Ident()->TsTypeChecker() != nullptr) { return param->Ident()->TsType(); } @@ -1649,7 +1649,7 @@ SignatureInfo *ETSChecker::ComposeSignatureInfo(ir::TSTypeParameterDeclaration * checker::Type *restParamType = nullptr; if (param->TypeAnnotation() != nullptr) { restParamType = param->RestParameter()->TypeAnnotation()->GetType(this); - } else if (param->Ident()->TsType() != nullptr) { + } else if (param->Ident()->TsTypeChecker() != nullptr) { restParamType = param->Ident()->TsType(); } else { ES2PANDA_ASSERT(IsAnyError()); // #23134 @@ -1953,7 +1953,7 @@ bool ETSChecker::CheckOverride(Signature *signature, ETSObjectType *site) auto *target = site->GetProperty(signature->Function()->Id()->Name(), flags); bool isOverridingAnySignature = false; - if (target == nullptr || target->TsType() == nullptr || target->TsType()->IsTypeError()) { + if (target == nullptr || target->TsTypeChecker() == nullptr || target->TsType()->IsTypeError()) { return isOverridingAnySignature; } diff --git a/ets2panda/checker/ets/helpers.cpp b/ets2panda/checker/ets/helpers.cpp index f85d057827..e5d2bf57e4 100644 --- a/ets2panda/checker/ets/helpers.cpp +++ b/ets2panda/checker/ets/helpers.cpp @@ -74,7 +74,7 @@ bool ETSChecker::IsVariableStatic(const varbinder::Variable *var) bool ETSChecker::IsVariableGetterSetter(const varbinder::Variable *var) { - return var != nullptr && var->TsType() != nullptr && var->TsType()->HasTypeFlag(TypeFlag::GETTER_SETTER); + return var != nullptr && var->TsTypeChecker() != nullptr && var->TsType()->HasTypeFlag(TypeFlag::GETTER_SETTER); } bool ETSChecker::IsVariableOverloadDeclaration(const varbinder::Variable *var) @@ -85,7 +85,7 @@ bool ETSChecker::IsVariableOverloadDeclaration(const varbinder::Variable *var) bool ETSChecker::IsVariableExtensionAccessor(const varbinder::Variable *var) { - return var != nullptr && var->TsType() != nullptr && var->TsType()->IsETSFunctionType() && + return var != nullptr && var->TsTypeChecker() != nullptr && var->TsType()->IsETSFunctionType() && var->TsType()->AsETSFunctionType()->IsExtensionAccessorType(); } @@ -153,7 +153,7 @@ void ETSChecker::WrongContextErrorClassifyByType(ir::Identifier *ident) void ETSChecker::NotResolvedError(ir::Identifier *const ident, const varbinder::Variable *classVar, const ETSObjectType *classType) { - if (classVar == nullptr || (classVar->TsType() != nullptr && classVar->TsType()->IsTypeError())) { + if (classVar == nullptr || (classVar->TsTypeChecker() != nullptr && classVar->TsType()->IsTypeError())) { LogUnresolvedReferenceError(ident); return; } @@ -627,7 +627,7 @@ checker::Type *ETSChecker::FixOptionalVariableType(varbinder::Variable *const bi { if ((flags & ir::ModifierFlags::OPTIONAL) != 0) { ES2PANDA_ASSERT(bindingVar != nullptr); - auto *variableType = bindingVar->TsType() != nullptr ? bindingVar->TsType() : GlobalTypeError(); + auto *variableType = bindingVar->TsTypeChecker() != nullptr ? bindingVar->TsType() : GlobalTypeError(); bindingVar->SetTsType( !variableType->IsTypeError() ? CreateETSUnionType({GlobalETSUndefinedType(), variableType}) : variableType); } @@ -982,7 +982,7 @@ static checker::Type *ResolveGetter(checker::ETSChecker *checker, ir::MemberExpr auto objType = expr->ObjType(); auto searchName = objType->GetReExportAliasValue(expr->Property()->AsIdentifier()->Name()); auto *prop = objType->GetProperty(searchName, flags); - if (prop == nullptr || prop->TsType() == nullptr || + if (prop == nullptr || prop->TsTypeChecker() == nullptr || !prop->TsType()->HasTypeFlag(checker::TypeFlag::GETTER_SETTER)) { return nullptr; } @@ -1871,7 +1871,7 @@ Type *ETSChecker::GetReferencedTypeBase(ir::Expression *name) auto *const var = name->AsIdentifier()->Variable(); ES2PANDA_ASSERT(var != nullptr); - if (var->TsType() != nullptr && var->TsType()->IsTypeError()) { + if (var->TsTypeChecker() != nullptr && var->TsType()->IsTypeError()) { return name->SetTsType(GlobalTypeError()); } @@ -2773,7 +2773,7 @@ void ETSChecker::GenerateGetterSetterBody(ArenaVector &stmts, A memberExpression->SetTsType(field->TsType()); memberExpression->SetPropVar(field->Key()->Variable()->AsLocalVariable()); memberExpression->SetRange(classDef->Range()); - if (memberExpression->ObjType() == nullptr && classDef->TsType() != nullptr) { + if (memberExpression->ObjType() == nullptr && classDef->TsTypeChecker() != nullptr) { memberExpression->SetObjectType(classDef->TsType()->AsETSObjectType()); } diff --git a/ets2panda/checker/ets/typeCheckingHelpers.cpp b/ets2panda/checker/ets/typeCheckingHelpers.cpp index 116a150bdf..6036478e1a 100644 --- a/ets2panda/checker/ets/typeCheckingHelpers.cpp +++ b/ets2panda/checker/ets/typeCheckingHelpers.cpp @@ -527,7 +527,7 @@ void ETSChecker::IterateInVariableContext(varbinder::Variable *const var) auto *classDef = iter->AsClassDefinition(); Type *containingClass {}; - if (classDef->TsType() == nullptr) { + if (classDef->TsTypeChecker() == nullptr) { containingClass = BuildBasicClassProperties(classDef)->MaybeBaseTypeOfGradualType(); ResolveDeclaredMembersOfObject(containingClass); } else { @@ -546,7 +546,7 @@ void ETSChecker::IterateInVariableContext(varbinder::Variable *const var) static Type *GetTypeFromVarLikeVariableDeclaration(ETSChecker *checker, varbinder::Variable *const var) { - if (var->TsType() != nullptr) { + if (var->TsTypeChecker() != nullptr) { return var->TsType(); } @@ -661,7 +661,7 @@ Type *ETSChecker::GetTypeOfVariable(varbinder::Variable *const var) GetTypeFromVariableDeclaration(var); } - if (var->TsType() != nullptr) { + if (var->TsTypeChecker() != nullptr) { return var->TsType(); } @@ -693,7 +693,7 @@ Type *ETSChecker::GuaranteedTypeForUncheckedPropertyAccess(varbinder::Variable * return nullptr; } - if (prop->TsType() != nullptr && prop->TsType()->IsTypeError()) { + if (prop->TsTypeChecker() != nullptr && prop->TsType()->IsTypeError()) { return nullptr; } @@ -832,7 +832,7 @@ bool ETSChecker::IsAllowedTypeAliasRecursion(const ir::TSTypeAliasDeclaration *t Type *ETSChecker::GetTypeFromTypeAliasReference(varbinder::Variable *var) { - if (var->TsType() != nullptr) { + if (var->TsTypeChecker() != nullptr) { return var->TsType(); } @@ -875,7 +875,7 @@ Type *ETSChecker::GetTypeFromTypeAliasReference(varbinder::Variable *var) Type *ETSChecker::GetTypeFromInterfaceReference(varbinder::Variable *var) { - if (var->TsType() != nullptr) { + if (var->TsTypeChecker() != nullptr) { return var->TsType(); } @@ -892,7 +892,7 @@ Type *ETSChecker::GetTypeFromInterfaceReference(varbinder::Variable *var) Type *ETSChecker::GetTypeFromClassReference(varbinder::Variable *var) { - if (var->TsType() != nullptr) { + if (var->TsTypeChecker() != nullptr) { return var->TsType(); } diff --git a/ets2panda/checker/ets/utilityTypeHandlers.cpp b/ets2panda/checker/ets/utilityTypeHandlers.cpp index 3bc3261558..cf6d892dca 100644 --- a/ets2panda/checker/ets/utilityTypeHandlers.cpp +++ b/ets2panda/checker/ets/utilityTypeHandlers.cpp @@ -263,7 +263,7 @@ ir::ClassProperty *ETSChecker::CreateNullishPropertyFromAccessor(ir::MethodDefin return CreateNullishProperty(prop, newClassDefinition); } - if (accessor->TsType() == nullptr) { + if (accessor->TsTypeChecker() == nullptr) { accessor->Parent()->Check(this); } @@ -846,7 +846,7 @@ varbinder::Variable *ETSChecker::SearchNamesInMultiplePrograms(const std::setTsType() == nullptr) { + if (var->TsTypeChecker() == nullptr) { var->Declaration()->Node()->Check(this); } diff --git a/ets2panda/checker/ts/destructuringContext.cpp b/ets2panda/checker/ts/destructuringContext.cpp index 7fcbc2e9d9..8cf424bf61 100644 --- a/ets2panda/checker/ts/destructuringContext.cpp +++ b/ets2panda/checker/ts/destructuringContext.cpp @@ -79,7 +79,7 @@ void DestructuringContext::SetInferredTypeForVariable(varbinder::Variable *var, inferredType = checker_->GetBaseTypeOfLiteralType(inferredType); } - if (var->TsType() != nullptr) { + if (var->TsTypeChecker() != nullptr) { checker_->IsTypeIdenticalTo(var->TsType(), inferredType, diagnostic::DIFFERENT_SUBSEQ_DECL, {var->Name(), var->TsType(), inferredType}, loc); return; diff --git a/ets2panda/checker/ts/function.cpp b/ets2panda/checker/ts/function.cpp index 7b0634260a..ce801ffa0f 100644 --- a/ets2panda/checker/ts/function.cpp +++ b/ets2panda/checker/ts/function.cpp @@ -356,7 +356,7 @@ std::tuple TSCheck ir::Expression *param, SignatureInfo *signatureInfo) { std::tuple result; - if (param->TsType() != nullptr) { + if (param->TsTypeChecker() != nullptr) { ES2PANDA_ASSERT(param->TsType()->Variable()); varbinder::Variable *var = param->TsType()->Variable(); result = {var->AsLocalVariable(), nullptr, var->HasFlag(varbinder::VariableFlags::OPTIONAL)}; diff --git a/ets2panda/checker/ts/helpers.cpp b/ets2panda/checker/ts/helpers.cpp index 9b5abf6d29..2b8beb071d 100644 --- a/ets2panda/checker/ts/helpers.cpp +++ b/ets2panda/checker/ts/helpers.cpp @@ -478,7 +478,7 @@ Type *TSChecker::GetDeclTsType(varbinder::Variable *var, varbinder::Decl *decl) Type *TSChecker::GetTypeOfVariable(varbinder::Variable *var) { - if (var->TsType() != nullptr) { + if (var->TsTypeChecker() != nullptr) { return var->TsType(); } diff --git a/ets2panda/checker/ts/object.cpp b/ets2panda/checker/ts/object.cpp index 0c9e3c25c3..9d9d3bc718 100644 --- a/ets2panda/checker/ts/object.cpp +++ b/ets2panda/checker/ts/object.cpp @@ -343,7 +343,7 @@ varbinder::Variable *TSChecker::GetPropertyOfUnionType(UnionType *type, const ut Type *TSChecker::CheckComputedPropertyName(ir::Expression *key) { - if (key->TsType() != nullptr) { + if (key->TsTypeChecker() != nullptr) { return key->TsType(); } diff --git a/ets2panda/checker/types/ets/etsObjectType.cpp b/ets2panda/checker/types/ets/etsObjectType.cpp index 177a0c679a..8944f6252d 100644 --- a/ets2panda/checker/types/ets/etsObjectType.cpp +++ b/ets2panda/checker/types/ets/etsObjectType.cpp @@ -729,7 +729,7 @@ ETSFunctionType *ETSObjectType::GetFunctionalInterfaceInvokeType() const std::string invokeName = checker->FunctionalInterfaceInvokeName(foundArity, hasRest); auto *invoke = GetProperty(util::StringView(invokeName), PropertySearchFlags::SEARCH_INSTANCE_METHOD | PropertySearchFlags::SEARCH_IN_INTERFACES); - ES2PANDA_ASSERT(invoke != nullptr && invoke->TsType() != nullptr && invoke->TsType()->IsETSFunctionType()); + ES2PANDA_ASSERT(invoke != nullptr && invoke->TsTypeChecker() != nullptr && invoke->TsType()->IsETSFunctionType()); return invoke->TsType()->AsETSFunctionType(); } diff --git a/ets2panda/checker/types/ts/objectLiteralType.cpp b/ets2panda/checker/types/ts/objectLiteralType.cpp index 7071e84332..f92a794e2c 100644 --- a/ets2panda/checker/types/ts/objectLiteralType.cpp +++ b/ets2panda/checker/types/ts/objectLiteralType.cpp @@ -60,7 +60,7 @@ void ObjectLiteralType::ToString(std::stringstream &ss, [[maybe_unused]] bool pr ss << ": "; } - if (it->TsType() != nullptr) { + if (it->TsTypeChecker() != nullptr) { it->TsType()->ToString(ss); } else { ss << "any"; diff --git a/ets2panda/checker/types/type.cpp b/ets2panda/checker/types/type.cpp index 61a6b8568e..01c37e1eaa 100644 --- a/ets2panda/checker/types/type.cpp +++ b/ets2panda/checker/types/type.cpp @@ -61,7 +61,7 @@ bool Type::IsLambdaObject() const AsETSObjectType()->HasObjectFlag(checker::ETSObjectFlags::CLASS))) { auto *invoke = AsETSObjectType()->GetOwnProperty( compiler::Signatures::STATIC_INVOKE_METHOD); - if (invoke != nullptr && invoke->TsType() != nullptr && invoke->TsType()->IsETSFunctionType()) { + if (invoke != nullptr && invoke->TsTypeChecker() != nullptr && invoke->TsType()->IsETSFunctionType()) { return true; } } diff --git a/ets2panda/compiler/base/condition.cpp b/ets2panda/compiler/base/condition.cpp index e0ebfb209d..d01e98f66e 100644 --- a/ets2panda/compiler/base/condition.cpp +++ b/ets2panda/compiler/base/condition.cpp @@ -102,7 +102,7 @@ void Condition::Compile(PandaGen *pg, const ir::Expression *expr, Label *falseLa bool Condition::CompileBinaryExprForBigInt(ETSGen *etsg, const ir::BinaryExpression *expr, Label *falseLabel) { - if ((expr->Left()->TsType() == nullptr) || (expr->Right()->TsType() == nullptr)) { + if ((expr->Left()->TsTypeChecker() == nullptr) || (expr->Right()->TsTypeChecker() == nullptr)) { return false; } diff --git a/ets2panda/compiler/core/ETSCompiler.cpp b/ets2panda/compiler/core/ETSCompiler.cpp index 75fd7d3de5..069d2fbd28 100644 --- a/ets2panda/compiler/core/ETSCompiler.cpp +++ b/ets2panda/compiler/core/ETSCompiler.cpp @@ -546,7 +546,7 @@ std::map &GetBigintSignatures() static bool CompileBigInt(compiler::ETSGen *etsg, const ir::BinaryExpression *expr) { - if ((expr->Left()->TsType() == nullptr) || (expr->Right()->TsType() == nullptr)) { + if ((expr->Left()->TsTypeChecker() == nullptr) || (expr->Right()->TsTypeChecker() == nullptr)) { return false; } @@ -938,7 +938,7 @@ void ETSCompiler::Compile(const ir::MemberExpression *expr) const etsg->StoreAccumulator(expr, objReg); auto ttctx = compiler::TargetTypeContext(etsg, expr->TsType()); - ES2PANDA_ASSERT(expr->PropVar()->TsType() != nullptr); + ES2PANDA_ASSERT(expr->PropVar()->TsTypeChecker() != nullptr); const checker::Type *const variableType = expr->PropVar()->TsType(); ES2PANDA_ASSERT(variableType != nullptr); if (variableType->HasTypeFlag(checker::TypeFlag::GETTER_SETTER)) { diff --git a/ets2panda/compiler/core/ETSfunction.cpp b/ets2panda/compiler/core/ETSfunction.cpp index 672f29e5f6..3a7bf9b600 100644 --- a/ets2panda/compiler/core/ETSfunction.cpp +++ b/ets2panda/compiler/core/ETSfunction.cpp @@ -98,7 +98,7 @@ void ETSFunction::ExtendWithDefaultReturn(ETSGen *etsg, const ir::AstNode *node, return; } - if (scriptFunc->ReturnTypeAnnotation() != nullptr && scriptFunc->ReturnTypeAnnotation()->TsType() != nullptr && + if (scriptFunc->ReturnTypeAnnotation() != nullptr && scriptFunc->ReturnTypeAnnotation()->TsTypeChecker() != nullptr && scriptFunc->ReturnTypeAnnotation()->TsType()->IsETSAsyncFuncReturnType()) { etsg->LoadDefaultValue(node, scriptFunc->ReturnTypeAnnotation()->TsType()); } else { diff --git a/ets2panda/compiler/core/emitter.cpp b/ets2panda/compiler/core/emitter.cpp index 6586372749..918ad9e3bc 100644 --- a/ets2panda/compiler/core/emitter.cpp +++ b/ets2panda/compiler/core/emitter.cpp @@ -286,7 +286,7 @@ static void GenLocalVariableInfo(pandasm::debuginfo::LocalVariable &variableDebu variableDebug.signature = "any"; variableDebug.signatureType = "any"; } else { - ES2PANDA_ASSERT(var->AsLocalVariable()->TsType() != nullptr); + ES2PANDA_ASSERT(var->AsLocalVariable()->TsTypeChecker() != nullptr); std::stringstream ss; var->AsLocalVariable()->TsType()->ToDebugInfoType(ss); variableDebug.signature = ss.str(); diff --git a/ets2panda/compiler/lowering/ets/arrayLiteralLowering.cpp b/ets2panda/compiler/lowering/ets/arrayLiteralLowering.cpp index 3d4f3e5b15..ac96aae7b6 100644 --- a/ets2panda/compiler/lowering/ets/arrayLiteralLowering.cpp +++ b/ets2panda/compiler/lowering/ets/arrayLiteralLowering.cpp @@ -80,7 +80,7 @@ static bool IsInAnnotationContext(ir::AstNode *node) ir::AstNode *ArrayLiteralLowering::TryTransformLiteralArrayToRefArray(ir::ArrayExpression *literalArray) { - auto literalArrayType = literalArray->TsType() != nullptr ? literalArray->TsType() : literalArray->PreferredType(); + auto literalArrayType = literalArray->TsTypeChecker() != nullptr ? literalArray->TsType() : literalArray->PreferredType(); if (literalArrayType->IsETSArrayType() || literalArrayType->IsETSTupleType() || !literalArrayType->IsETSResizableArrayType() || IsInAnnotationContext(literalArray)) { return literalArray; diff --git a/ets2panda/compiler/lowering/ets/bigintLowering.cpp b/ets2panda/compiler/lowering/ets/bigintLowering.cpp index 0c5f2f1360..9d5a1ab4ea 100644 --- a/ets2panda/compiler/lowering/ets/bigintLowering.cpp +++ b/ets2panda/compiler/lowering/ets/bigintLowering.cpp @@ -41,7 +41,7 @@ static bool IsFloatingPoint(ir::Expression *expr, public_lib::Context *ctx) auto number = expr->AsNumberLiteral()->Number(); return number.IsFloat() || number.IsDouble(); } - if (expr->TsType() != nullptr) { + if (expr->TsTypeChecker() != nullptr) { auto checker = ctx->GetChecker()->AsETSChecker(); return checker->CheckIfFloatingPoint(expr->TsType()); } @@ -101,8 +101,8 @@ bool ConvertNumericExpressionToBigInt(public_lib::Context *ctx, ir::BinaryExpres auto *left = expr->Left(); auto *right = expr->Right(); - bool leftIsBigInt = (left->TsType() != nullptr && left->TsType()->IsETSBigIntType()) || left->IsBigIntLiteral(); - bool rightIsBigInt = (right->TsType() != nullptr && right->TsType()->IsETSBigIntType()) || right->IsBigIntLiteral(); + bool leftIsBigInt = (left->TsTypeChecker() != nullptr && left->TsType()->IsETSBigIntType()) || left->IsBigIntLiteral(); + bool rightIsBigInt = (right->TsTypeChecker() != nullptr && right->TsType()->IsETSBigIntType()) || right->IsBigIntLiteral(); // Convert when one operand is BigInt and the other is numeric (including literals and expressions) if (leftIsBigInt && !rightIsBigInt && IsNumericType(ctx, right->TsType())) { ir::Expression *newRight = CreateBigIntFromNumericExpression(ctx, right); diff --git a/ets2panda/compiler/lowering/ets/enumPostCheckLowering.cpp b/ets2panda/compiler/lowering/ets/enumPostCheckLowering.cpp index 0da8d399b8..6e935a9755 100644 --- a/ets2panda/compiler/lowering/ets/enumPostCheckLowering.cpp +++ b/ets2panda/compiler/lowering/ets/enumPostCheckLowering.cpp @@ -410,7 +410,7 @@ bool EnumPostCheckLoweringPhase::PerformForModule(public_lib::Context *ctx, pars parentClass->AsClassDefinition()->TsType()->AsETSObjectType()); node->RemoveAstNodeFlags(ir::AstNodeFlags::RECHECK); node->Check(checker_); - if (node->IsExpression() && node->AsExpression()->TsType() != nullptr && + if (node->IsExpression() && node->AsExpression()->TsTypeChecker() != nullptr && !node->AsExpression()->TsType()->IsETSIntEnumType()) { node->RemoveAstNodeFlags(ir::AstNodeFlags::GENERATE_VALUE_OF); } @@ -425,7 +425,7 @@ bool EnumPostCheckLoweringPhase::PerformForModule(public_lib::Context *ctx, pars } return GenerateEnumCasting(node->AsTSAsExpression(), castFlag); } - if (node->IsSwitchStatement() && (node->AsSwitchStatement()->Discriminant()->TsType() != nullptr) && + if (node->IsSwitchStatement() && (node->AsSwitchStatement()->Discriminant()->TsTypeChecker() != nullptr) && node->AsSwitchStatement()->Discriminant()->TsType()->IsETSEnumType()) { return GenerateGetOrdinalCallForSwitch(node->AsSwitchStatement()); } diff --git a/ets2panda/compiler/lowering/ets/genericBridgesLowering.cpp b/ets2panda/compiler/lowering/ets/genericBridgesLowering.cpp index 332d3678bb..3ef2c3130c 100644 --- a/ets2panda/compiler/lowering/ets/genericBridgesLowering.cpp +++ b/ets2panda/compiler/lowering/ets/genericBridgesLowering.cpp @@ -317,7 +317,7 @@ ir::ClassDefinition *GenericBridgesPhase::ProcessClassDefinition(ir::ClassDefini ProcessInterfaces(classDefinition, classDefinition->TsType()->AsETSObjectType()->Interfaces()); // Check if the base class is a generic class. - if (classDefinition->Super() == nullptr || classDefinition->Super()->TsType() == nullptr || + if (classDefinition->Super() == nullptr || classDefinition->Super()->TsTypeChecker() == nullptr || !classDefinition->Super()->TsType()->IsETSObjectType()) { return classDefinition; } diff --git a/ets2panda/compiler/lowering/ets/gradualTypeNarrowing.cpp b/ets2panda/compiler/lowering/ets/gradualTypeNarrowing.cpp index e2d6d9405d..06abba3092 100644 --- a/ets2panda/compiler/lowering/ets/gradualTypeNarrowing.cpp +++ b/ets2panda/compiler/lowering/ets/gradualTypeNarrowing.cpp @@ -79,14 +79,14 @@ void GradualTypeNarrowing::NarrowGradualType(ir::AstNode *node) auto typedNode = node->AsTyped(); auto typeTransformFunc = [this](checker::Type *type) -> checker::TypePtr { if (type->IsGradualType() || (type->IsETSObjectType() && type->AsETSObjectType()->GetDeclNode() != nullptr && - type->AsETSObjectType()->GetDeclNode()->AsTyped()->TsType() != nullptr && + type->AsETSObjectType()->GetDeclNode()->AsTyped()->TsTypeChecker() != nullptr && type->AsETSObjectType()->GetDeclNode()->AsTyped()->TsType()->IsGradualType())) { return this->checker_->GlobalETSRelaxedAnyType(); } return type; }; - if (typedNode->TsType() != nullptr) { + if (typedNode->TsTypeChecker() != nullptr) { typedNode->SetTsType(TransformType(typedNode->TsType(), typeTransformFunc)); } if (typedNode->IsBinaryExpression()) { @@ -95,7 +95,7 @@ void GradualTypeNarrowing::NarrowGradualType(ir::AstNode *node) } auto var = node->Variable(); - if (var != nullptr && var->TsType() != nullptr) { + if (var != nullptr && var->TsTypeChecker() != nullptr) { var->SetTsType(TransformType(var->TsType(), typeTransformFunc)); } } diff --git a/ets2panda/compiler/lowering/ets/interfaceObjectLiteralLowering.cpp b/ets2panda/compiler/lowering/ets/interfaceObjectLiteralLowering.cpp index b817bb6898..a1ce208bdd 100644 --- a/ets2panda/compiler/lowering/ets/interfaceObjectLiteralLowering.cpp +++ b/ets2panda/compiler/lowering/ets/interfaceObjectLiteralLowering.cpp @@ -223,7 +223,7 @@ static void GenerateAnonClassTypeFromInterface(public_lib::Context *ctx, ir::TSI } auto classBodyBuilder = [ctx, checker, ifaceNode](ArenaVector *classBody) { - if (ifaceNode->TsType() == nullptr) { + if (ifaceNode->TsTypeChecker() == nullptr) { ifaceNode->Check(checker); } ArenaVector readonlyFields(ctx->Allocator()->Adapter()); @@ -386,7 +386,7 @@ static void HandleInterfaceLowering(public_lib::Context *ctx, ir::ObjectExpressi static bool CheckInterfaceShouldGenerateAnonClass(ir::TSInterfaceDeclaration *interfaceDecl) { - if (interfaceDecl->TsType() != nullptr && interfaceDecl->TsType()->IsGradualType()) { + if (interfaceDecl->TsTypeChecker() != nullptr && interfaceDecl->TsType()->IsGradualType()) { return false; } for (auto it : interfaceDecl->Body()->Body()) { diff --git a/ets2panda/compiler/lowering/ets/lambdaLowering.cpp b/ets2panda/compiler/lowering/ets/lambdaLowering.cpp index 8a6f430fd3..b55f5f9172 100644 --- a/ets2panda/compiler/lowering/ets/lambdaLowering.cpp +++ b/ets2panda/compiler/lowering/ets/lambdaLowering.cpp @@ -250,7 +250,7 @@ static void ProcessCalleeMethodBody(ir::AstNode *body, checker::ETSChecker *chec if (substitution == nullptr) { return; } - if (node->IsTyped() && node->AsTyped()->TsType() != nullptr) { + if (node->IsTyped() && node->AsTyped()->TsTypeChecker() != nullptr) { node->AsTyped()->SetTsType(node->AsTyped()->TsType()->Substitute(checker->Relation(), substitution)); if (node->IsTSNonNullExpression()) { auto expr = node->AsTSNonNullExpression(); @@ -1309,7 +1309,7 @@ static bool IsVariableOriginalAccessor(const varbinder::Variable *var) static bool IsFunctionOrMethodCall(checker::ETSChecker *checker, ir::CallExpression const *node) { auto const *callee = node->Callee(); - if (callee->TsType() != nullptr && callee->TsType()->IsETSExtensionFuncHelperType()) { + if (callee->TsTypeChecker() != nullptr && callee->TsType()->IsETSExtensionFuncHelperType()) { return true; } @@ -1318,7 +1318,7 @@ static bool IsFunctionOrMethodCall(checker::ETSChecker *checker, ir::CallExpress if (callee->IsMemberExpression()) { auto me = callee->AsMemberExpression(); ES2PANDA_ASSERT(me->TsType()); - if (me->Object()->TsType() != nullptr && checker->GetApparentType(me->Object()->TsType())->IsETSUnionType() && + if (me->Object()->TsTypeChecker() != nullptr && checker->GetApparentType(me->Object()->TsType())->IsETSUnionType() && me->TsType()->IsETSMethodType()) { return true; } @@ -1441,7 +1441,7 @@ static ir::AstNode *BuildLambdaClassWhenNeeded(public_lib::Context *ctx, ir::Ast auto *var = id->Variable(); // We are running this lowering only for ETS files // so it is correct to pass ETS extension here to isReference() - if (id->IsReference(ScriptExtension::ETS) && id->TsType() != nullptr && id->TsType()->IsETSFunctionType() && + if (id->IsReference(ScriptExtension::ETS) && id->TsTypeChecker() != nullptr && id->TsType()->IsETSFunctionType() && !IsInCalleePosition(id) && !IsEnumFunctionCall(id) && IsValidFunctionDeclVar(var) && !id->Variable()->HasFlag(varbinder::VariableFlags::DYNAMIC) && !IsOverloadedName(id)) { return ConvertFunctionReference(ctx, id); @@ -1449,7 +1449,7 @@ static ir::AstNode *BuildLambdaClassWhenNeeded(public_lib::Context *ctx, ir::Ast } if (node->IsMemberExpression()) { auto *mexpr = node->AsMemberExpression(); - if (mexpr->Kind() == ir::MemberExpressionKind::PROPERTY_ACCESS && mexpr->TsType() != nullptr && + if (mexpr->Kind() == ir::MemberExpressionKind::PROPERTY_ACCESS && mexpr->TsTypeChecker() != nullptr && mexpr->TsType()->IsETSFunctionType() && mexpr->Object()->TsType()->IsETSObjectType()) { ES2PANDA_ASSERT(mexpr->Property()->IsIdentifier()); auto *var = mexpr->Object()->TsType()->AsETSObjectType()->GetProperty( diff --git a/ets2panda/compiler/lowering/ets/objectLiteralLowering.cpp b/ets2panda/compiler/lowering/ets/objectLiteralLowering.cpp index 5fd1f2379a..0e4b2165ed 100644 --- a/ets2panda/compiler/lowering/ets/objectLiteralLowering.cpp +++ b/ets2panda/compiler/lowering/ets/objectLiteralLowering.cpp @@ -257,7 +257,7 @@ static ir::AstNode *HandleObjectLiteralLowering(public_lib::Context *ctx, ir::Ob * }) */ - if (objExpr->TsType() == nullptr) { + if (objExpr->TsTypeChecker() == nullptr) { return objExpr; } diff --git a/ets2panda/compiler/lowering/ets/opAssignment.cpp b/ets2panda/compiler/lowering/ets/opAssignment.cpp index 9146ee546b..4b50441f39 100644 --- a/ets2panda/compiler/lowering/ets/opAssignment.cpp +++ b/ets2panda/compiler/lowering/ets/opAssignment.cpp @@ -272,7 +272,7 @@ ir::AstNode *HandleOpAssignment(public_lib::Context *ctx, ir::AssignmentExpressi { auto *checker = ctx->GetChecker()->AsETSChecker(); - if (assignment->TsType() == nullptr) { // hasn't been through checker + if (assignment->TsTypeChecker() == nullptr) { // hasn't been through checker return assignment; } @@ -457,7 +457,7 @@ bool OpAssignmentLowering::PostconditionForModule([[maybe_unused]] public_lib::C return false; } - return (ast->IsAssignmentExpression() && ast->AsAssignmentExpression()->TsType() != nullptr && + return (ast->IsAssignmentExpression() && ast->AsAssignmentExpression()->TsTypeChecker() != nullptr && ast->AsAssignmentExpression()->OperatorType() != lexer::TokenType::PUNCTUATOR_SUBSTITUTION) || ast->IsUpdateExpression(); }); diff --git a/ets2panda/compiler/lowering/ets/setterLowering.cpp b/ets2panda/compiler/lowering/ets/setterLowering.cpp index 902fbbc667..b89c1a9fac 100644 --- a/ets2panda/compiler/lowering/ets/setterLowering.cpp +++ b/ets2panda/compiler/lowering/ets/setterLowering.cpp @@ -49,7 +49,7 @@ static bool IsSetterCall(const ir::Expression *const expr) return false; } - ES2PANDA_ASSERT(variable != nullptr && variable->TsType() != nullptr); + ES2PANDA_ASSERT(variable != nullptr && variable->TsTypeChecker() != nullptr); return variable->TsType()->HasTypeFlag(checker::TypeFlag::SETTER); } diff --git a/ets2panda/compiler/lowering/ets/spreadLowering.cpp b/ets2panda/compiler/lowering/ets/spreadLowering.cpp index d7557ca008..3f98eacd67 100644 --- a/ets2panda/compiler/lowering/ets/spreadLowering.cpp +++ b/ets2panda/compiler/lowering/ets/spreadLowering.cpp @@ -65,7 +65,7 @@ ir::Identifier *CreateNewArrayLengthStatement(public_lib::Context *ctx, ir::Arra const size_t normalElementCount = array->Elements().size() - spreadArrayIds.size(); lengthString << "let @@I" << (argumentCount++) << " : int = " << normalElementCount << " + "; for (auto *const spaId : spreadArrayIds) { - if (spaId->TsType() != nullptr && spaId->TsType()->IsETSTupleType()) { + if (spaId->TsTypeChecker() != nullptr && spaId->TsType()->IsETSTupleType()) { lengthString << "(" << spaId->TsType()->AsETSTupleType()->GetTupleSize() << ") + "; } else { lengthString << "(@@I" << (argumentCount++) << ".length.toInt()) + "; diff --git a/ets2panda/compiler/lowering/ets/stringComparison.cpp b/ets2panda/compiler/lowering/ets/stringComparison.cpp index 583f862050..a3324a68a9 100644 --- a/ets2panda/compiler/lowering/ets/stringComparison.cpp +++ b/ets2panda/compiler/lowering/ets/stringComparison.cpp @@ -59,7 +59,7 @@ bool StringComparisonLowering::IsStringComparison(ir::AstNode *node) return false; } - if ((expr->Left()->TsType() == nullptr) || (expr->Right()->TsType() == nullptr)) { + if ((expr->Left()->TsTypeChecker() == nullptr) || (expr->Right()->TsTypeChecker() == nullptr)) { return false; } diff --git a/ets2panda/compiler/lowering/ets/unboxLowering.cpp b/ets2panda/compiler/lowering/ets/unboxLowering.cpp index 0e5299b822..a1c53216cf 100644 --- a/ets2panda/compiler/lowering/ets/unboxLowering.cpp +++ b/ets2panda/compiler/lowering/ets/unboxLowering.cpp @@ -256,7 +256,7 @@ static void NormalizeAllTypes(UnboxContext *uctx, ir::AstNode *ast) } if (child->IsTyped()) { child->AsTyped()->SetTsType(NormalizeType(uctx, child->AsTyped()->TsType())); - if (child->Variable() != nullptr && child->Variable()->TsType() != nullptr) { + if (child->Variable() != nullptr && child->Variable()->TsTypeChecker() != nullptr) { child->Variable()->SetTsType(NormalizeType(uctx, child->Variable()->TsType())); } } @@ -1160,7 +1160,7 @@ struct UnboxVisitor : public ir::visitor::EmptyAstVisitor { !mexpr->Object()->TsType()->IsETSAnyType()) { HandleDeclarationNode(uctx_, mexpr->Property()->Variable()->Declaration()->Node()); propType = mexpr->Property()->Variable()->Declaration()->Node()->AsTyped()->TsType(); - } else if (mexpr->Property()->Variable()->TsType() != nullptr) { + } else if (mexpr->Property()->Variable()->TsTypeChecker() != nullptr) { propType = mexpr->Property()->Variable()->TsType(); } else { propType = mexpr->Property()->TsType(); @@ -1290,7 +1290,7 @@ struct UnboxVisitor : public ir::visitor::EmptyAstVisitor { void HandleLiteral(ir::Literal *lit) { - if (lit->TsType() == nullptr) { + if (lit->TsTypeChecker() == nullptr) { return; } lit->SetTsType(uctx_->checker->MaybeUnboxType(lit->TsType())); @@ -1312,7 +1312,7 @@ struct UnboxVisitor : public ir::visitor::EmptyAstVisitor { void HandleVariableRef(ir::Expression *expr) { auto *var = expr->Variable(); - if (var == nullptr || var->TsType() == nullptr || expr->TsType() == nullptr || + if (var == nullptr || var->TsTypeChecker() == nullptr || expr->TsTypeChecker() == nullptr || var->Declaration() == nullptr) { // lambda invoke function return; } diff --git a/ets2panda/compiler/lowering/ets/unionLowering.cpp b/ets2panda/compiler/lowering/ets/unionLowering.cpp index d205f392d0..f92dbab223 100644 --- a/ets2panda/compiler/lowering/ets/unionLowering.cpp +++ b/ets2panda/compiler/lowering/ets/unionLowering.cpp @@ -127,7 +127,7 @@ static std::tuple CreateNamedA auto boundCtx = varbinder::BoundContext(varbinder->AsETSBinder()->GetRecordTable(), accessClass, true); CheckLoweredNode(varbinder->AsETSBinder(), checker, method); } - ES2PANDA_ASSERT(method->Id() != nullptr && method->TsType() != nullptr); + ES2PANDA_ASSERT(method->Id() != nullptr && method->TsTypeChecker() != nullptr); return {method->Id()->Variable()->AsLocalVariable(), method->TsType()->AsETSFunctionType()->CallSignatures().front()}; } @@ -219,7 +219,7 @@ bool UnionLowering::PerformForModule(public_lib::Context *ctx, parser::Program * if (!Phase::ShouldProcessNode(ast)) { return ast; } - if (ast->IsMemberExpression() && ast->AsMemberExpression()->Object()->TsType() != nullptr) { + if (ast->IsMemberExpression() && ast->AsMemberExpression()->Object()->TsTypeChecker() != nullptr) { auto *objType = checker->GetApparentType(checker->GetNonNullishType(ast->AsMemberExpression()->Object()->TsType())); if (objType->IsETSUnionType()) { @@ -242,7 +242,7 @@ bool UnionLowering::PostconditionForModule(public_lib::Context *ctx, const parse if (!Phase::ShouldProcessNode(ast)) { return false; } - if (!ast->IsMemberExpression() || ast->AsMemberExpression()->Object()->TsType() == nullptr) { + if (!ast->IsMemberExpression() || ast->AsMemberExpression()->Object()->TsTypeChecker() == nullptr) { return false; } auto *objType = diff --git a/ets2panda/declgen_ets2ts/declgenEts2Ts.cpp b/ets2panda/declgen_ets2ts/declgenEts2Ts.cpp index f1a78d5555..6a1074d28d 100644 --- a/ets2panda/declgen_ets2ts/declgenEts2Ts.cpp +++ b/ets2panda/declgen_ets2ts/declgenEts2Ts.cpp @@ -155,7 +155,7 @@ void TSDeclGen::ProcessClassDependencies(const ir::ClassDeclaration *classDecl) if (state_.super != nullptr) { AddSuperType(state_.super); } - if (classDef->TsType() != nullptr && classDef->TsType()->IsETSObjectType()) { + if (classDef->TsTypeChecker() != nullptr && classDef->TsType()->IsETSObjectType()) { ProcessInterfacesDependencies(classDef->TsType()->AsETSObjectType()->Interfaces()); } @@ -216,7 +216,7 @@ void TSDeclGen::ProcessClassMethodDependencies(const ir::MethodDefinition *metho void TSDeclGen::AddSuperType(const ir::Expression *super) { - if (super->TsType() == nullptr) { + if (super->TsTypeChecker() == nullptr) { return; } const auto superType = checker::ETSChecker::ETSType(super->TsType()); @@ -1799,7 +1799,7 @@ void TSDeclGen::HandleClassDeclarationTypeInfo(const ir::ClassDefinition *classD HandleClassInherit(super); } - if (classDef->TsType() != nullptr && classDef->TsType()->IsETSObjectType() && + if (classDef->TsTypeChecker() != nullptr && classDef->TsType()->IsETSObjectType() && !classDef->TsType()->AsETSObjectType()->Interfaces().empty()) { OutDts(" implements "); const auto &interfaces = classDef->TsType()->AsETSObjectType()->Interfaces(); @@ -1897,7 +1897,7 @@ void TSDeclGen::ProcessClassBody(const ir::ClassDefinition *classDef) GenClassDeclaration(prop->AsClassDeclaration()); } } - if (classDef->TsType() != nullptr && classDef->TsType()->IsETSObjectType()) { + if (classDef->TsTypeChecker() != nullptr && classDef->TsType()->IsETSObjectType()) { ProcessMethodsFromInterfaces(processedMethods, classDef->TsType()->AsETSObjectType()->Interfaces()); } } @@ -2080,7 +2080,7 @@ void TSDeclGen::GenMethodSignature(const ir::MethodDefinition *methodDef, const DebugPrint(" GenMethodDeclaration: " + methodName); OutDts(methodName); - if (methodDef->TsType() == nullptr) { + if (methodDef->TsTypeChecker() == nullptr) { LogWarning(diagnostic::UNTYPED_METHOD, {methodName}, methodIdent->Start()); OutDts(": ESObject"); return; diff --git a/ets2panda/ir/ets/etsTypeReferencePart.cpp b/ets2panda/ir/ets/etsTypeReferencePart.cpp index 95812f806b..3b9f4712f3 100644 --- a/ets2panda/ir/ets/etsTypeReferencePart.cpp +++ b/ets2panda/ir/ets/etsTypeReferencePart.cpp @@ -208,7 +208,7 @@ checker::Type *ETSTypeReferencePart::HandleInternalTypes(checker::ETSChecker *co variable = ident->Variable(); } else { if (name->AsTSQualifiedName()->Left()->Variable() != nullptr && - name->AsTSQualifiedName()->Left()->Variable()->TsType() != nullptr && + name->AsTSQualifiedName()->Left()->Variable()->TsTypeChecker() != nullptr && name->AsTSQualifiedName()->Left()->Variable()->TsType()->IsETSObjectType()) { variable = name->AsTSQualifiedName()->Left()->Variable()->TsType()->AsETSObjectType()->GetProperty( ident->Name(), checker::PropertySearchFlags::SEARCH_DECL); @@ -265,7 +265,7 @@ checker::Type *ETSTypeReferencePart::GetType(checker::ETSChecker *checker) SetTsType(HandleInternalTypes(checker)); } - if (TsType() == nullptr) { + if (TsTypeChecker() == nullptr) { checker::Type *baseType = checker->GetReferencedTypeBase(name); ES2PANDA_ASSERT(baseType != nullptr); SetTsType(HandlerResultType(checker, baseType)); diff --git a/ets2panda/ir/ets/etsUnionType.cpp b/ets2panda/ir/ets/etsUnionType.cpp index 0a74affb97..cde5716c8f 100644 --- a/ets2panda/ir/ets/etsUnionType.cpp +++ b/ets2panda/ir/ets/etsUnionType.cpp @@ -90,8 +90,8 @@ static bool CheckConstituentTypesValid(ArenaVector const &const checker::Type *ETSUnionType::GetType(checker::ETSChecker *checker) { - if (TsType() != nullptr) { - return TsType(); + if (TsTypeChecker() != nullptr) { + return TsTypeChecker(); } checker->CheckAnnotations(Annotations()); diff --git a/ets2panda/ir/expressions/memberExpression.cpp b/ets2panda/ir/expressions/memberExpression.cpp index 6c0bc3f2ef..273da47e6d 100644 --- a/ets2panda/ir/expressions/memberExpression.cpp +++ b/ets2panda/ir/expressions/memberExpression.cpp @@ -327,7 +327,7 @@ checker::Type *MemberExpression::SetAndAdjustType(checker::ETSChecker *checker, std::optional MemberExpression::GetTupleIndexValue() const { - if (object_->TsType() == nullptr || !object_->TsType()->IsETSTupleType() || !property_->IsNumberLiteral()) { + if (object_->TsTypeChecker() == nullptr || !object_->TsType()->IsETSTupleType() || !property_->IsNumberLiteral()) { return std::nullopt; } return property_->AsNumberLiteral()->Number().GetValueAndCastTo(); @@ -485,7 +485,7 @@ checker::Type *MemberExpression::HandleComputedInGradualType(checker::ETSChecker checker::Type *MemberExpression::CheckComputed(checker::ETSChecker *checker, checker::Type *baseType) { if (baseType->IsETSObjectType() && baseType->AsETSObjectType()->GetDeclNode() != nullptr && - baseType->AsETSObjectType()->GetDeclNode()->AsTyped()->TsType() != nullptr && + baseType->AsETSObjectType()->GetDeclNode()->AsTyped()->TsTypeChecker() != nullptr && baseType->AsETSObjectType()->GetDeclNode()->AsTyped()->TsType()->IsGradualType()) { SetObjectType(baseType->AsETSObjectType()); return HandleComputedInGradualType(checker, baseType); diff --git a/replace_tstype.sh b/replace_tstype.sh new file mode 100644 index 0000000000..0fc4a959fe --- /dev/null +++ b/replace_tstype.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +# 批量替换TsType()调用为TsTypeChecker() +# 只替换与nullptr比较的情况 + +echo "开始批量替换TsType()调用..." + +# 替换 TsType() == nullptr +find /home/polyhedron/arkcompiler/ets_frontend -name "*.cpp" -exec sed -i 's/\([[:alnum:]_]*\)->TsType() == nullptr/\1->TsTypeChecker() == nullptr/g' {} \; +find /home/polyhedron/arkcompiler/ets_frontend -name "*.cpp" -exec sed -i 's/\([[:alnum:]_]*\)\.TsType() == nullptr/\1.TsTypeChecker() == nullptr/g' {} \; + +# 替换 TsType() != nullptr +find /home/polyhedron/arkcompiler/ets_frontend -name "*.cpp" -exec sed -i 's/\([[:alnum:]_]*\)->TsType() != nullptr/\1->TsTypeChecker() != nullptr/g' {} \; +find /home/polyhedron/arkcompiler/ets_frontend -name "*.cpp" -exec sed -i 's/\([[:alnum:]_]*\)\.TsType() != nullptr/\1.TsTypeChecker() != nullptr/g' {} \; + +echo "批量替换完成!" -- Gitee From e5cf9b849de13c5426b41617385ec550ecd7e8b7 Mon Sep 17 00:00:00 2001 From: Geng Chen Date: Sat, 19 Jul 2025 17:17:00 +0800 Subject: [PATCH 3/3] fixed a tstype to tstypechecker --- ets2panda/checker/ets/typeCheckingHelpers.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ets2panda/checker/ets/typeCheckingHelpers.cpp b/ets2panda/checker/ets/typeCheckingHelpers.cpp index 6036478e1a..552549e668 100644 --- a/ets2panda/checker/ets/typeCheckingHelpers.cpp +++ b/ets2panda/checker/ets/typeCheckingHelpers.cpp @@ -1195,7 +1195,7 @@ void ETSChecker::HandleAnnotationRetention(ir::AnnotationUsage *anno, ir::Annota void ETSChecker::CheckStandardAnnotation(ir::AnnotationUsage *anno) { - if (anno->GetBaseName()->Variable() == nullptr || IsTypeError(anno->GetBaseName()->TsType())) { + if (anno->GetBaseName()->Variable() == nullptr || IsTypeError(anno->GetBaseName()->TsTypeChecker())) { return; } ES2PANDA_ASSERT(anno->GetBaseName()->Variable()->Declaration()->Node()->AsAnnotationDeclaration() != nullptr); -- Gitee