13af6ab5fSopenharmony_ci/* 23af6ab5fSopenharmony_ci * Copyright (c) 2021-2024 Huawei Device Co., Ltd. 33af6ab5fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 43af6ab5fSopenharmony_ci * you may not use this file except in compliance with the License. 53af6ab5fSopenharmony_ci * You may obtain a copy of the License at 63af6ab5fSopenharmony_ci * 73af6ab5fSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 83af6ab5fSopenharmony_ci * 93af6ab5fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 103af6ab5fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 113af6ab5fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 123af6ab5fSopenharmony_ci * See the License for the specific language governing permissions and 133af6ab5fSopenharmony_ci * limitations under the License. 143af6ab5fSopenharmony_ci */ 153af6ab5fSopenharmony_ci 163af6ab5fSopenharmony_ci#include "TSAnalyzer.h" 173af6ab5fSopenharmony_ci 183af6ab5fSopenharmony_ci#include "checker/TSchecker.h" 193af6ab5fSopenharmony_ci#include "checker/ts/destructuringContext.h" 203af6ab5fSopenharmony_ci 213af6ab5fSopenharmony_cinamespace ark::es2panda::checker { 223af6ab5fSopenharmony_ci 233af6ab5fSopenharmony_ciTSChecker *TSAnalyzer::GetTSChecker() const 243af6ab5fSopenharmony_ci{ 253af6ab5fSopenharmony_ci return static_cast<TSChecker *>(GetChecker()); 263af6ab5fSopenharmony_ci} 273af6ab5fSopenharmony_ci 283af6ab5fSopenharmony_ci// from base folder 293af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check(ir::CatchClause *st) const 303af6ab5fSopenharmony_ci{ 313af6ab5fSopenharmony_ci TSChecker *checker = GetTSChecker(); 323af6ab5fSopenharmony_ci ir::Expression *typeAnnotation = st->Param()->AsAnnotatedExpression()->TypeAnnotation(); 333af6ab5fSopenharmony_ci 343af6ab5fSopenharmony_ci if (typeAnnotation != nullptr) { 353af6ab5fSopenharmony_ci checker::Type *catchParamType = typeAnnotation->Check(checker); 363af6ab5fSopenharmony_ci 373af6ab5fSopenharmony_ci if (!catchParamType->HasTypeFlag(checker::TypeFlag::ANY_OR_UNKNOWN)) { 383af6ab5fSopenharmony_ci checker->ThrowTypeError("Catch clause variable type annotation must be 'any' or 'unknown' if specified", 393af6ab5fSopenharmony_ci st->Start()); 403af6ab5fSopenharmony_ci } 413af6ab5fSopenharmony_ci } 423af6ab5fSopenharmony_ci 433af6ab5fSopenharmony_ci st->Body()->Check(checker); 443af6ab5fSopenharmony_ci 453af6ab5fSopenharmony_ci return nullptr; 463af6ab5fSopenharmony_ci} 473af6ab5fSopenharmony_ci 483af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check([[maybe_unused]] ir::ClassDefinition *node) const 493af6ab5fSopenharmony_ci{ 503af6ab5fSopenharmony_ci TSChecker *checker = GetTSChecker(); 513af6ab5fSopenharmony_ci // NOTE: aszilagyi. 523af6ab5fSopenharmony_ci return checker->GlobalAnyType(); 533af6ab5fSopenharmony_ci} 543af6ab5fSopenharmony_ci 553af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check([[maybe_unused]] ir::MetaProperty *expr) const 563af6ab5fSopenharmony_ci{ 573af6ab5fSopenharmony_ci TSChecker *checker = GetTSChecker(); 583af6ab5fSopenharmony_ci // NOTE: aszilagyi. 593af6ab5fSopenharmony_ci return checker->GlobalAnyType(); 603af6ab5fSopenharmony_ci} 613af6ab5fSopenharmony_ci 623af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check(ir::TSIndexSignature *node) const 633af6ab5fSopenharmony_ci{ 643af6ab5fSopenharmony_ci TSChecker *checker = GetTSChecker(); 653af6ab5fSopenharmony_ci if (node->TsType() != nullptr) { 663af6ab5fSopenharmony_ci return node->TsType(); 673af6ab5fSopenharmony_ci } 683af6ab5fSopenharmony_ci 693af6ab5fSopenharmony_ci const util::StringView ¶mName = node->Param()->AsIdentifier()->Name(); 703af6ab5fSopenharmony_ci node->typeAnnotation_->Check(checker); 713af6ab5fSopenharmony_ci checker::Type *indexType = node->typeAnnotation_->GetType(checker); 723af6ab5fSopenharmony_ci checker::IndexInfo *info = 733af6ab5fSopenharmony_ci checker->Allocator()->New<checker::IndexInfo>(indexType, paramName, node->Readonly(), node->Start()); 743af6ab5fSopenharmony_ci checker::ObjectDescriptor *desc = checker->Allocator()->New<checker::ObjectDescriptor>(checker->Allocator()); 753af6ab5fSopenharmony_ci checker::ObjectType *placeholder = checker->Allocator()->New<checker::ObjectLiteralType>(desc); 763af6ab5fSopenharmony_ci 773af6ab5fSopenharmony_ci if (node->Kind() == ir::TSIndexSignature::TSIndexSignatureKind::NUMBER) { 783af6ab5fSopenharmony_ci placeholder->Desc()->numberIndexInfo = info; 793af6ab5fSopenharmony_ci } else { 803af6ab5fSopenharmony_ci placeholder->Desc()->stringIndexInfo = info; 813af6ab5fSopenharmony_ci } 823af6ab5fSopenharmony_ci 833af6ab5fSopenharmony_ci node->SetTsType(placeholder); 843af6ab5fSopenharmony_ci return placeholder; 853af6ab5fSopenharmony_ci} 863af6ab5fSopenharmony_ci 873af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check(ir::TSMethodSignature *node) const 883af6ab5fSopenharmony_ci{ 893af6ab5fSopenharmony_ci TSChecker *checker = GetTSChecker(); 903af6ab5fSopenharmony_ci if (node->Computed()) { 913af6ab5fSopenharmony_ci checker->CheckComputedPropertyName(node->Key()); 923af6ab5fSopenharmony_ci } 933af6ab5fSopenharmony_ci 943af6ab5fSopenharmony_ci checker::ScopeContext scopeCtx(checker, node->Scope()); 953af6ab5fSopenharmony_ci 963af6ab5fSopenharmony_ci auto *signatureInfo = checker->Allocator()->New<checker::SignatureInfo>(checker->Allocator()); 973af6ab5fSopenharmony_ci checker->CheckFunctionParameterDeclarations(node->Params(), signatureInfo); 983af6ab5fSopenharmony_ci 993af6ab5fSopenharmony_ci auto *callSignature = checker->Allocator()->New<checker::Signature>(signatureInfo, checker->GlobalAnyType()); 1003af6ab5fSopenharmony_ci node->Variable()->SetTsType(checker->CreateFunctionTypeWithSignature(callSignature)); 1013af6ab5fSopenharmony_ci 1023af6ab5fSopenharmony_ci auto returnType = node->ReturnTypeAnnotation(); 1033af6ab5fSopenharmony_ci if (returnType == nullptr) { 1043af6ab5fSopenharmony_ci checker->ThrowTypeError( 1053af6ab5fSopenharmony_ci "Method signature, which lacks return-type annotation, implicitly has an 'any' return type.", 1063af6ab5fSopenharmony_ci node->Start()); 1073af6ab5fSopenharmony_ci } 1083af6ab5fSopenharmony_ci 1093af6ab5fSopenharmony_ci returnType->Check(checker); 1103af6ab5fSopenharmony_ci callSignature->SetReturnType(returnType->GetType(checker)); 1113af6ab5fSopenharmony_ci 1123af6ab5fSopenharmony_ci return nullptr; 1133af6ab5fSopenharmony_ci} 1143af6ab5fSopenharmony_ci 1153af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check(ir::TSPropertySignature *node) const 1163af6ab5fSopenharmony_ci{ 1173af6ab5fSopenharmony_ci TSChecker *checker = GetTSChecker(); 1183af6ab5fSopenharmony_ci if (node->TypeAnnotation() != nullptr) { 1193af6ab5fSopenharmony_ci node->TypeAnnotation()->Check(checker); 1203af6ab5fSopenharmony_ci } 1213af6ab5fSopenharmony_ci 1223af6ab5fSopenharmony_ci if (node->Computed()) { 1233af6ab5fSopenharmony_ci checker->CheckComputedPropertyName(node->Key()); 1243af6ab5fSopenharmony_ci } 1253af6ab5fSopenharmony_ci 1263af6ab5fSopenharmony_ci if (node->TypeAnnotation() != nullptr) { 1273af6ab5fSopenharmony_ci node->Variable()->SetTsType(node->TypeAnnotation()->GetType(checker)); 1283af6ab5fSopenharmony_ci return nullptr; 1293af6ab5fSopenharmony_ci } 1303af6ab5fSopenharmony_ci 1313af6ab5fSopenharmony_ci checker->ThrowTypeError("Property implicitly has an 'any' type.", node->Start()); 1323af6ab5fSopenharmony_ci return nullptr; 1333af6ab5fSopenharmony_ci} 1343af6ab5fSopenharmony_ci 1353af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check(ir::TSSignatureDeclaration *node) const 1363af6ab5fSopenharmony_ci{ 1373af6ab5fSopenharmony_ci TSChecker *checker = GetTSChecker(); 1383af6ab5fSopenharmony_ci if (node->TsType() != nullptr) { 1393af6ab5fSopenharmony_ci return node->TsType(); 1403af6ab5fSopenharmony_ci } 1413af6ab5fSopenharmony_ci 1423af6ab5fSopenharmony_ci checker::ScopeContext scopeCtx(checker, node->Scope()); 1433af6ab5fSopenharmony_ci 1443af6ab5fSopenharmony_ci auto *signatureInfo = checker->Allocator()->New<checker::SignatureInfo>(checker->Allocator()); 1453af6ab5fSopenharmony_ci checker->CheckFunctionParameterDeclarations(node->Params(), signatureInfo); 1463af6ab5fSopenharmony_ci 1473af6ab5fSopenharmony_ci bool isCallSignature = (node->Kind() == ir::TSSignatureDeclaration::TSSignatureDeclarationKind::CALL_SIGNATURE); 1483af6ab5fSopenharmony_ci 1493af6ab5fSopenharmony_ci if (node->ReturnTypeAnnotation() == nullptr) { 1503af6ab5fSopenharmony_ci if (isCallSignature) { 1513af6ab5fSopenharmony_ci checker->ThrowTypeError( 1523af6ab5fSopenharmony_ci "Call signature, which lacks return-type annotation, implicitly has an 'any' return type.", 1533af6ab5fSopenharmony_ci node->Start()); 1543af6ab5fSopenharmony_ci } 1553af6ab5fSopenharmony_ci 1563af6ab5fSopenharmony_ci checker->ThrowTypeError( 1573af6ab5fSopenharmony_ci "Construct signature, which lacks return-type annotation, implicitly has an 'any' return type.", 1583af6ab5fSopenharmony_ci node->Start()); 1593af6ab5fSopenharmony_ci } 1603af6ab5fSopenharmony_ci 1613af6ab5fSopenharmony_ci node->ReturnTypeAnnotation()->Check(checker); 1623af6ab5fSopenharmony_ci checker::Type *returnType = node->ReturnTypeAnnotation()->GetType(checker); 1633af6ab5fSopenharmony_ci 1643af6ab5fSopenharmony_ci auto *signature = checker->Allocator()->New<checker::Signature>(signatureInfo, returnType); 1653af6ab5fSopenharmony_ci 1663af6ab5fSopenharmony_ci checker::Type *placeholderObj = nullptr; 1673af6ab5fSopenharmony_ci 1683af6ab5fSopenharmony_ci if (isCallSignature) { 1693af6ab5fSopenharmony_ci placeholderObj = checker->CreateObjectTypeWithCallSignature(signature); 1703af6ab5fSopenharmony_ci } else { 1713af6ab5fSopenharmony_ci placeholderObj = checker->CreateObjectTypeWithConstructSignature(signature); 1723af6ab5fSopenharmony_ci } 1733af6ab5fSopenharmony_ci 1743af6ab5fSopenharmony_ci node->SetTsType(placeholderObj); 1753af6ab5fSopenharmony_ci return placeholderObj; 1763af6ab5fSopenharmony_ci} 1773af6ab5fSopenharmony_ci 1783af6ab5fSopenharmony_cistatic void GetSpreadElementType(checker::TSChecker *checker, checker::Type *spreadType, 1793af6ab5fSopenharmony_ci ArenaVector<checker::Type *> &elementTypes, const lexer::SourcePosition &loc) 1803af6ab5fSopenharmony_ci{ 1813af6ab5fSopenharmony_ci bool inConstContext = checker->HasStatus(checker::CheckerStatus::IN_CONST_CONTEXT); 1823af6ab5fSopenharmony_ci 1833af6ab5fSopenharmony_ci if (spreadType->IsObjectType() && spreadType->AsObjectType()->IsTupleType()) { 1843af6ab5fSopenharmony_ci ArenaVector<checker::Type *> tupleElementTypes(checker->Allocator()->Adapter()); 1853af6ab5fSopenharmony_ci checker::TupleType *spreadTuple = spreadType->AsObjectType()->AsTupleType(); 1863af6ab5fSopenharmony_ci 1873af6ab5fSopenharmony_ci for (auto *it : spreadTuple->Properties()) { 1883af6ab5fSopenharmony_ci if (inConstContext) { 1893af6ab5fSopenharmony_ci elementTypes.push_back(it->TsType()); 1903af6ab5fSopenharmony_ci continue; 1913af6ab5fSopenharmony_ci } 1923af6ab5fSopenharmony_ci 1933af6ab5fSopenharmony_ci tupleElementTypes.push_back(it->TsType()); 1943af6ab5fSopenharmony_ci } 1953af6ab5fSopenharmony_ci 1963af6ab5fSopenharmony_ci if (inConstContext) { 1973af6ab5fSopenharmony_ci return; 1983af6ab5fSopenharmony_ci } 1993af6ab5fSopenharmony_ci 2003af6ab5fSopenharmony_ci elementTypes.push_back(checker->CreateUnionType(std::move(tupleElementTypes))); 2013af6ab5fSopenharmony_ci return; 2023af6ab5fSopenharmony_ci } 2033af6ab5fSopenharmony_ci 2043af6ab5fSopenharmony_ci if (!spreadType->IsUnionType()) { 2053af6ab5fSopenharmony_ci checker->ThrowTypeError( 2063af6ab5fSopenharmony_ci {"Type '", spreadType, "' must have a '[Symbol.iterator]()' method that returns an iterator."}, loc); 2073af6ab5fSopenharmony_ci return; 2083af6ab5fSopenharmony_ci } 2093af6ab5fSopenharmony_ci 2103af6ab5fSopenharmony_ci ArenaVector<checker::Type *> spreadTypes(checker->Allocator()->Adapter()); 2113af6ab5fSopenharmony_ci bool throwError = false; 2123af6ab5fSopenharmony_ci 2133af6ab5fSopenharmony_ci for (auto *type : spreadType->AsUnionType()->ConstituentTypes()) { 2143af6ab5fSopenharmony_ci if (type->IsArrayType()) { 2153af6ab5fSopenharmony_ci spreadTypes.push_back(type->AsArrayType()->ElementType()); 2163af6ab5fSopenharmony_ci continue; 2173af6ab5fSopenharmony_ci } 2183af6ab5fSopenharmony_ci 2193af6ab5fSopenharmony_ci if (type->IsObjectType() && type->AsObjectType()->IsTupleType()) { 2203af6ab5fSopenharmony_ci checker::TupleType *tuple = type->AsObjectType()->AsTupleType(); 2213af6ab5fSopenharmony_ci 2223af6ab5fSopenharmony_ci for (auto *it : tuple->Properties()) { 2233af6ab5fSopenharmony_ci spreadTypes.push_back(it->TsType()); 2243af6ab5fSopenharmony_ci } 2253af6ab5fSopenharmony_ci 2263af6ab5fSopenharmony_ci continue; 2273af6ab5fSopenharmony_ci } 2283af6ab5fSopenharmony_ci 2293af6ab5fSopenharmony_ci throwError = true; 2303af6ab5fSopenharmony_ci break; 2313af6ab5fSopenharmony_ci } 2323af6ab5fSopenharmony_ci 2333af6ab5fSopenharmony_ci if (!throwError) { 2343af6ab5fSopenharmony_ci elementTypes.push_back(checker->CreateUnionType(std::move(spreadTypes))); 2353af6ab5fSopenharmony_ci return; 2363af6ab5fSopenharmony_ci } 2373af6ab5fSopenharmony_ci 2383af6ab5fSopenharmony_ci checker->ThrowTypeError( 2393af6ab5fSopenharmony_ci {"Type '", spreadType, "' must have a '[Symbol.iterator]()' method that returns an iterator."}, loc); 2403af6ab5fSopenharmony_ci} 2413af6ab5fSopenharmony_ci 2423af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check(ir::ArrayExpression *expr) const 2433af6ab5fSopenharmony_ci{ 2443af6ab5fSopenharmony_ci TSChecker *checker = GetTSChecker(); 2453af6ab5fSopenharmony_ci ArenaVector<checker::Type *> elementTypes(checker->Allocator()->Adapter()); 2463af6ab5fSopenharmony_ci ArenaVector<checker::ElementFlags> elementFlags(checker->Allocator()->Adapter()); 2473af6ab5fSopenharmony_ci bool inConstContext = checker->HasStatus(checker::CheckerStatus::IN_CONST_CONTEXT); 2483af6ab5fSopenharmony_ci bool createTuple = checker->HasStatus(checker::CheckerStatus::FORCE_TUPLE); 2493af6ab5fSopenharmony_ci 2503af6ab5fSopenharmony_ci for (auto *it : expr->Elements()) { 2513af6ab5fSopenharmony_ci if (it->IsSpreadElement()) { 2523af6ab5fSopenharmony_ci checker::Type *spreadType = it->AsSpreadElement()->Argument()->Check(checker); 2533af6ab5fSopenharmony_ci 2543af6ab5fSopenharmony_ci if (spreadType->IsArrayType()) { 2553af6ab5fSopenharmony_ci elementTypes.push_back(inConstContext ? spreadType : spreadType->AsArrayType()->ElementType()); 2563af6ab5fSopenharmony_ci elementFlags.push_back(checker::ElementFlags::VARIADIC); 2573af6ab5fSopenharmony_ci continue; 2583af6ab5fSopenharmony_ci } 2593af6ab5fSopenharmony_ci 2603af6ab5fSopenharmony_ci GetSpreadElementType(checker, spreadType, elementTypes, it->Start()); 2613af6ab5fSopenharmony_ci elementFlags.push_back(checker::ElementFlags::REST); 2623af6ab5fSopenharmony_ci continue; 2633af6ab5fSopenharmony_ci } 2643af6ab5fSopenharmony_ci 2653af6ab5fSopenharmony_ci checker::Type *elementType = it->Check(checker); 2663af6ab5fSopenharmony_ci 2673af6ab5fSopenharmony_ci if (!inConstContext) { 2683af6ab5fSopenharmony_ci elementType = checker->GetBaseTypeOfLiteralType(elementType); 2693af6ab5fSopenharmony_ci } 2703af6ab5fSopenharmony_ci 2713af6ab5fSopenharmony_ci elementFlags.push_back(checker::ElementFlags::REQUIRED); 2723af6ab5fSopenharmony_ci elementTypes.push_back(elementType); 2733af6ab5fSopenharmony_ci } 2743af6ab5fSopenharmony_ci 2753af6ab5fSopenharmony_ci if (inConstContext || createTuple) { 2763af6ab5fSopenharmony_ci checker::ObjectDescriptor *desc = checker->Allocator()->New<checker::ObjectDescriptor>(checker->Allocator()); 2773af6ab5fSopenharmony_ci uint32_t index = 0; 2783af6ab5fSopenharmony_ci 2793af6ab5fSopenharmony_ci for (auto it = elementTypes.begin(); it != elementTypes.end(); it++, index++) { 2803af6ab5fSopenharmony_ci util::StringView memberIndex = util::Helpers::ToStringView(checker->Allocator(), index); 2813af6ab5fSopenharmony_ci varbinder::LocalVariable *tupleMember = varbinder::Scope::CreateVar( 2823af6ab5fSopenharmony_ci checker->Allocator(), memberIndex, varbinder::VariableFlags::PROPERTY, nullptr); 2833af6ab5fSopenharmony_ci 2843af6ab5fSopenharmony_ci if (inConstContext) { 2853af6ab5fSopenharmony_ci tupleMember->AddFlag(varbinder::VariableFlags::READONLY); 2863af6ab5fSopenharmony_ci } 2873af6ab5fSopenharmony_ci 2883af6ab5fSopenharmony_ci tupleMember->SetTsType(*it); 2893af6ab5fSopenharmony_ci desc->properties.push_back(tupleMember); 2903af6ab5fSopenharmony_ci } 2913af6ab5fSopenharmony_ci 2923af6ab5fSopenharmony_ci const checker::TupleTypeInfo tupleTypeInfo = {ElementFlags::REQUIRED, index, index, inConstContext}; 2933af6ab5fSopenharmony_ci return checker->CreateTupleType(desc, std::move(elementFlags), tupleTypeInfo); 2943af6ab5fSopenharmony_ci } 2953af6ab5fSopenharmony_ci 2963af6ab5fSopenharmony_ci checker::Type *arrayElementType = nullptr; 2973af6ab5fSopenharmony_ci if (elementTypes.empty()) { 2983af6ab5fSopenharmony_ci arrayElementType = checker->GlobalAnyType(); 2993af6ab5fSopenharmony_ci } else { 3003af6ab5fSopenharmony_ci arrayElementType = checker->CreateUnionType(std::move(elementTypes)); 3013af6ab5fSopenharmony_ci } 3023af6ab5fSopenharmony_ci 3033af6ab5fSopenharmony_ci return checker->Allocator()->New<checker::ArrayType>(arrayElementType); 3043af6ab5fSopenharmony_ci} 3053af6ab5fSopenharmony_ci 3063af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check(ir::ArrowFunctionExpression *expr) const 3073af6ab5fSopenharmony_ci{ 3083af6ab5fSopenharmony_ci TSChecker *checker = GetTSChecker(); 3093af6ab5fSopenharmony_ci varbinder::Variable *funcVar = nullptr; 3103af6ab5fSopenharmony_ci 3113af6ab5fSopenharmony_ci if (expr->Function()->Parent()->Parent() != nullptr && 3123af6ab5fSopenharmony_ci expr->Function()->Parent()->Parent()->IsVariableDeclarator() && 3133af6ab5fSopenharmony_ci expr->Function()->Parent()->Parent()->AsVariableDeclarator()->Id()->IsIdentifier()) { 3143af6ab5fSopenharmony_ci funcVar = expr->Function()->Parent()->Parent()->AsVariableDeclarator()->Id()->AsIdentifier()->Variable(); 3153af6ab5fSopenharmony_ci } 3163af6ab5fSopenharmony_ci 3173af6ab5fSopenharmony_ci checker::ScopeContext scopeCtx(checker, expr->Function()->Scope()); 3183af6ab5fSopenharmony_ci 3193af6ab5fSopenharmony_ci auto *signatureInfo = checker->Allocator()->New<checker::SignatureInfo>(checker->Allocator()); 3203af6ab5fSopenharmony_ci checker->CheckFunctionParameterDeclarations(expr->Function()->Params(), signatureInfo); 3213af6ab5fSopenharmony_ci 3223af6ab5fSopenharmony_ci auto *signature = checker->Allocator()->New<checker::Signature>(signatureInfo, checker->GlobalResolvingReturnType(), 3233af6ab5fSopenharmony_ci expr->Function()); 3243af6ab5fSopenharmony_ci checker::Type *funcType = checker->CreateFunctionTypeWithSignature(signature); 3253af6ab5fSopenharmony_ci 3263af6ab5fSopenharmony_ci if (funcVar != nullptr && funcVar->TsType() == nullptr) { 3273af6ab5fSopenharmony_ci funcVar->SetTsType(funcType); 3283af6ab5fSopenharmony_ci } 3293af6ab5fSopenharmony_ci 3303af6ab5fSopenharmony_ci signature->SetReturnType(checker->HandleFunctionReturn(expr->Function())); 3313af6ab5fSopenharmony_ci 3323af6ab5fSopenharmony_ci if (!expr->Function()->Body()->IsExpression()) { 3333af6ab5fSopenharmony_ci expr->Function()->Body()->Check(checker); 3343af6ab5fSopenharmony_ci } 3353af6ab5fSopenharmony_ci 3363af6ab5fSopenharmony_ci return funcType; 3373af6ab5fSopenharmony_ci} 3383af6ab5fSopenharmony_ci 3393af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::CheckAssignmentExprOperatorType(ir::AssignmentExpression *expr, checker::Type *leftType, 3403af6ab5fSopenharmony_ci checker::Type *rightType) const 3413af6ab5fSopenharmony_ci{ 3423af6ab5fSopenharmony_ci TSChecker *checker = GetTSChecker(); 3433af6ab5fSopenharmony_ci ExpressionTypeInfo leftRightType {}; 3443af6ab5fSopenharmony_ci leftRightType.leftType = leftType; 3453af6ab5fSopenharmony_ci leftRightType.rightType = rightType; 3463af6ab5fSopenharmony_ci switch (expr->OperatorType()) { 3473af6ab5fSopenharmony_ci case lexer::TokenType::PUNCTUATOR_MULTIPLY_EQUAL: 3483af6ab5fSopenharmony_ci case lexer::TokenType::PUNCTUATOR_EXPONENTIATION_EQUAL: 3493af6ab5fSopenharmony_ci case lexer::TokenType::PUNCTUATOR_DIVIDE_EQUAL: 3503af6ab5fSopenharmony_ci case lexer::TokenType::PUNCTUATOR_MOD_EQUAL: 3513af6ab5fSopenharmony_ci case lexer::TokenType::PUNCTUATOR_MINUS_EQUAL: 3523af6ab5fSopenharmony_ci case lexer::TokenType::PUNCTUATOR_LEFT_SHIFT_EQUAL: 3533af6ab5fSopenharmony_ci case lexer::TokenType::PUNCTUATOR_RIGHT_SHIFT_EQUAL: 3543af6ab5fSopenharmony_ci case lexer::TokenType::PUNCTUATOR_UNSIGNED_RIGHT_SHIFT_EQUAL: 3553af6ab5fSopenharmony_ci case lexer::TokenType::PUNCTUATOR_BITWISE_AND_EQUAL: 3563af6ab5fSopenharmony_ci case lexer::TokenType::PUNCTUATOR_BITWISE_XOR_EQUAL: 3573af6ab5fSopenharmony_ci case lexer::TokenType::PUNCTUATOR_BITWISE_OR_EQUAL: { 3583af6ab5fSopenharmony_ci return checker->CheckBinaryOperator(&leftRightType, expr->Left(), expr->Right(), expr, 3593af6ab5fSopenharmony_ci expr->OperatorType()); 3603af6ab5fSopenharmony_ci } 3613af6ab5fSopenharmony_ci case lexer::TokenType::PUNCTUATOR_PLUS_EQUAL: { 3623af6ab5fSopenharmony_ci return checker->CheckPlusOperator(&leftRightType, expr->Left(), expr->Right(), expr, expr->OperatorType()); 3633af6ab5fSopenharmony_ci } 3643af6ab5fSopenharmony_ci case lexer::TokenType::PUNCTUATOR_SUBSTITUTION: { 3653af6ab5fSopenharmony_ci checker->CheckAssignmentOperator(expr->OperatorType(), expr->Left(), leftType, rightType); 3663af6ab5fSopenharmony_ci return rightType; 3673af6ab5fSopenharmony_ci } 3683af6ab5fSopenharmony_ci default: { 3693af6ab5fSopenharmony_ci UNREACHABLE(); 3703af6ab5fSopenharmony_ci break; 3713af6ab5fSopenharmony_ci } 3723af6ab5fSopenharmony_ci } 3733af6ab5fSopenharmony_ci 3743af6ab5fSopenharmony_ci return nullptr; 3753af6ab5fSopenharmony_ci} 3763af6ab5fSopenharmony_ci 3773af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check(ir::AssignmentExpression *expr) const 3783af6ab5fSopenharmony_ci{ 3793af6ab5fSopenharmony_ci TSChecker *checker = GetTSChecker(); 3803af6ab5fSopenharmony_ci if (expr->Left()->IsArrayPattern()) { 3813af6ab5fSopenharmony_ci auto savedContext = checker::SavedCheckerContext(checker, checker::CheckerStatus::FORCE_TUPLE); 3823af6ab5fSopenharmony_ci auto destructuringContext = 3833af6ab5fSopenharmony_ci checker::ArrayDestructuringContext({checker, expr->Left(), true, true, nullptr, expr->Right()}); 3843af6ab5fSopenharmony_ci destructuringContext.Start(); 3853af6ab5fSopenharmony_ci return destructuringContext.InferredType(); 3863af6ab5fSopenharmony_ci } 3873af6ab5fSopenharmony_ci 3883af6ab5fSopenharmony_ci if (expr->Left()->IsObjectPattern()) { 3893af6ab5fSopenharmony_ci auto savedContext = checker::SavedCheckerContext(checker, checker::CheckerStatus::FORCE_TUPLE); 3903af6ab5fSopenharmony_ci auto destructuringContext = 3913af6ab5fSopenharmony_ci checker::ObjectDestructuringContext({checker, expr->Left(), true, true, nullptr, expr->Right()}); 3923af6ab5fSopenharmony_ci destructuringContext.Start(); 3933af6ab5fSopenharmony_ci return destructuringContext.InferredType(); 3943af6ab5fSopenharmony_ci } 3953af6ab5fSopenharmony_ci 3963af6ab5fSopenharmony_ci if (expr->Left()->IsIdentifier() && expr->Left()->AsIdentifier()->Variable() != nullptr && 3973af6ab5fSopenharmony_ci expr->Left()->AsIdentifier()->Variable()->Declaration()->IsConstDecl()) { 3983af6ab5fSopenharmony_ci checker->ThrowTypeError( 3993af6ab5fSopenharmony_ci {"Cannot assign to ", expr->Left()->AsIdentifier()->Name(), " because it is a constant."}, 4003af6ab5fSopenharmony_ci expr->Left()->Start()); 4013af6ab5fSopenharmony_ci } 4023af6ab5fSopenharmony_ci 4033af6ab5fSopenharmony_ci auto *leftType = expr->Left()->Check(checker); 4043af6ab5fSopenharmony_ci 4053af6ab5fSopenharmony_ci if (leftType->HasTypeFlag(checker::TypeFlag::READONLY)) { 4063af6ab5fSopenharmony_ci checker->ThrowTypeError("Cannot assign to this property because it is readonly.", expr->Left()->Start()); 4073af6ab5fSopenharmony_ci } 4083af6ab5fSopenharmony_ci 4093af6ab5fSopenharmony_ci if (expr->OperatorType() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) { 4103af6ab5fSopenharmony_ci checker->ElaborateElementwise(leftType, expr->Right(), expr->Left()->Start()); 4113af6ab5fSopenharmony_ci return checker->CheckTypeCached(expr->Right()); 4123af6ab5fSopenharmony_ci } 4133af6ab5fSopenharmony_ci 4143af6ab5fSopenharmony_ci auto *rightType = expr->Right()->Check(checker); 4153af6ab5fSopenharmony_ci 4163af6ab5fSopenharmony_ci return CheckAssignmentExprOperatorType(expr, leftType, rightType); 4173af6ab5fSopenharmony_ci} 4183af6ab5fSopenharmony_ci 4193af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check([[maybe_unused]] ir::AwaitExpression *expr) const 4203af6ab5fSopenharmony_ci{ 4213af6ab5fSopenharmony_ci TSChecker *checker = GetTSChecker(); 4223af6ab5fSopenharmony_ci // NOTE(aszilagyi) 4233af6ab5fSopenharmony_ci return checker->GlobalAnyType(); 4243af6ab5fSopenharmony_ci} 4253af6ab5fSopenharmony_ci 4263af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::CheckBinaryExprArithmLogical(ir::BinaryExpression *expr, ExpressionTypeInfo *leftRightType, 4273af6ab5fSopenharmony_ci TSChecker *checker) const 4283af6ab5fSopenharmony_ci{ 4293af6ab5fSopenharmony_ci switch (expr->OperatorType()) { 4303af6ab5fSopenharmony_ci case lexer::TokenType::PUNCTUATOR_MULTIPLY: 4313af6ab5fSopenharmony_ci case lexer::TokenType::PUNCTUATOR_EXPONENTIATION: 4323af6ab5fSopenharmony_ci case lexer::TokenType::PUNCTUATOR_DIVIDE: 4333af6ab5fSopenharmony_ci case lexer::TokenType::PUNCTUATOR_MOD: 4343af6ab5fSopenharmony_ci case lexer::TokenType::PUNCTUATOR_MINUS: 4353af6ab5fSopenharmony_ci case lexer::TokenType::PUNCTUATOR_LEFT_SHIFT: 4363af6ab5fSopenharmony_ci case lexer::TokenType::PUNCTUATOR_RIGHT_SHIFT: 4373af6ab5fSopenharmony_ci case lexer::TokenType::PUNCTUATOR_UNSIGNED_RIGHT_SHIFT: 4383af6ab5fSopenharmony_ci case lexer::TokenType::PUNCTUATOR_BITWISE_AND: 4393af6ab5fSopenharmony_ci case lexer::TokenType::PUNCTUATOR_BITWISE_XOR: 4403af6ab5fSopenharmony_ci case lexer::TokenType::PUNCTUATOR_BITWISE_OR: { 4413af6ab5fSopenharmony_ci return checker->CheckBinaryOperator(leftRightType, expr->Left(), expr->Right(), expr, expr->OperatorType()); 4423af6ab5fSopenharmony_ci } 4433af6ab5fSopenharmony_ci case lexer::TokenType::PUNCTUATOR_PLUS: { 4443af6ab5fSopenharmony_ci return checker->CheckPlusOperator(leftRightType, expr->Left(), expr->Right(), expr, expr->OperatorType()); 4453af6ab5fSopenharmony_ci } 4463af6ab5fSopenharmony_ci case lexer::TokenType::PUNCTUATOR_LOGICAL_AND: { 4473af6ab5fSopenharmony_ci return checker->CheckAndOperator(leftRightType->leftType, leftRightType->rightType, expr->Left()); 4483af6ab5fSopenharmony_ci } 4493af6ab5fSopenharmony_ci case lexer::TokenType::PUNCTUATOR_LOGICAL_OR: { 4503af6ab5fSopenharmony_ci return checker->CheckOrOperator(leftRightType->leftType, leftRightType->rightType, expr->Left()); 4513af6ab5fSopenharmony_ci } 4523af6ab5fSopenharmony_ci default: { 4533af6ab5fSopenharmony_ci return nullptr; 4543af6ab5fSopenharmony_ci } 4553af6ab5fSopenharmony_ci } 4563af6ab5fSopenharmony_ci} 4573af6ab5fSopenharmony_ci 4583af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check(ir::BinaryExpression *expr) const 4593af6ab5fSopenharmony_ci{ 4603af6ab5fSopenharmony_ci TSChecker *checker = GetTSChecker(); 4613af6ab5fSopenharmony_ci ExpressionTypeInfo leftRightType {}; 4623af6ab5fSopenharmony_ci leftRightType.leftType = expr->Left()->Check(checker); 4633af6ab5fSopenharmony_ci leftRightType.rightType = expr->Right()->Check(checker); 4643af6ab5fSopenharmony_ci 4653af6ab5fSopenharmony_ci auto *checkBinaryExprPunctuator = CheckBinaryExprArithmLogical(expr, &leftRightType, checker); 4663af6ab5fSopenharmony_ci if (checkBinaryExprPunctuator != nullptr) { 4673af6ab5fSopenharmony_ci return checkBinaryExprPunctuator; 4683af6ab5fSopenharmony_ci } 4693af6ab5fSopenharmony_ci 4703af6ab5fSopenharmony_ci switch (expr->OperatorType()) { 4713af6ab5fSopenharmony_ci case lexer::TokenType::PUNCTUATOR_LESS_THAN: 4723af6ab5fSopenharmony_ci case lexer::TokenType::PUNCTUATOR_GREATER_THAN: { 4733af6ab5fSopenharmony_ci return checker->CheckCompareOperator(&leftRightType, expr->Left(), expr->Right(), expr, 4743af6ab5fSopenharmony_ci expr->OperatorType()); 4753af6ab5fSopenharmony_ci } 4763af6ab5fSopenharmony_ci case lexer::TokenType::PUNCTUATOR_EQUAL: 4773af6ab5fSopenharmony_ci case lexer::TokenType::PUNCTUATOR_NOT_EQUAL: 4783af6ab5fSopenharmony_ci case lexer::TokenType::PUNCTUATOR_STRICT_EQUAL: 4793af6ab5fSopenharmony_ci case lexer::TokenType::PUNCTUATOR_NOT_STRICT_EQUAL: { 4803af6ab5fSopenharmony_ci if (checker->IsTypeEqualityComparableTo(leftRightType.leftType, leftRightType.rightType) || 4813af6ab5fSopenharmony_ci checker->IsTypeEqualityComparableTo(leftRightType.rightType, leftRightType.leftType)) { 4823af6ab5fSopenharmony_ci return checker->GlobalBooleanType(); 4833af6ab5fSopenharmony_ci } 4843af6ab5fSopenharmony_ci 4853af6ab5fSopenharmony_ci checker->ThrowBinaryLikeError(expr->OperatorType(), leftRightType.leftType, leftRightType.rightType, 4863af6ab5fSopenharmony_ci expr->Start()); 4873af6ab5fSopenharmony_ci } 4883af6ab5fSopenharmony_ci case lexer::TokenType::PUNCTUATOR_NULLISH_COALESCING: { 4893af6ab5fSopenharmony_ci // NOTE: Csaba Repasi. Implement checker for nullish coalescing 4903af6ab5fSopenharmony_ci return checker->GlobalAnyType(); 4913af6ab5fSopenharmony_ci } 4923af6ab5fSopenharmony_ci case lexer::TokenType::PUNCTUATOR_SUBSTITUTION: { 4933af6ab5fSopenharmony_ci checker->CheckAssignmentOperator(expr->OperatorType(), expr->Left(), leftRightType.leftType, 4943af6ab5fSopenharmony_ci leftRightType.rightType); 4953af6ab5fSopenharmony_ci return leftRightType.rightType; 4963af6ab5fSopenharmony_ci } 4973af6ab5fSopenharmony_ci case lexer::TokenType::KEYW_INSTANCEOF: { 4983af6ab5fSopenharmony_ci return checker->CheckInstanceofExpression(leftRightType.leftType, leftRightType.rightType, expr->Right(), 4993af6ab5fSopenharmony_ci expr); 5003af6ab5fSopenharmony_ci } 5013af6ab5fSopenharmony_ci case lexer::TokenType::KEYW_IN: { 5023af6ab5fSopenharmony_ci return checker->CheckInExpression(leftRightType.leftType, leftRightType.rightType, expr->Left(), 5033af6ab5fSopenharmony_ci expr->Right(), expr); 5043af6ab5fSopenharmony_ci } 5053af6ab5fSopenharmony_ci default: { 5063af6ab5fSopenharmony_ci UNREACHABLE(); 5073af6ab5fSopenharmony_ci break; 5083af6ab5fSopenharmony_ci } 5093af6ab5fSopenharmony_ci } 5103af6ab5fSopenharmony_ci 5113af6ab5fSopenharmony_ci return nullptr; 5123af6ab5fSopenharmony_ci} 5133af6ab5fSopenharmony_ci 5143af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check(ir::CallExpression *expr) const 5153af6ab5fSopenharmony_ci{ 5163af6ab5fSopenharmony_ci TSChecker *checker = GetTSChecker(); 5173af6ab5fSopenharmony_ci checker::Type *calleeType = expr->callee_->Check(checker); 5183af6ab5fSopenharmony_ci 5193af6ab5fSopenharmony_ci // NOTE: aszilagyi. handle optional chain 5203af6ab5fSopenharmony_ci if (calleeType->IsObjectType()) { 5213af6ab5fSopenharmony_ci checker::ObjectType *calleeObj = calleeType->AsObjectType(); 5223af6ab5fSopenharmony_ci return checker->ResolveCallOrNewExpression(calleeObj->CallSignatures(), expr->Arguments(), expr->Start()); 5233af6ab5fSopenharmony_ci } 5243af6ab5fSopenharmony_ci 5253af6ab5fSopenharmony_ci checker->ThrowTypeError("This expression is not callable.", expr->Start()); 5263af6ab5fSopenharmony_ci return nullptr; 5273af6ab5fSopenharmony_ci} 5283af6ab5fSopenharmony_ci 5293af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check(ir::ChainExpression *expr) const 5303af6ab5fSopenharmony_ci{ 5313af6ab5fSopenharmony_ci TSChecker *checker = GetTSChecker(); 5323af6ab5fSopenharmony_ci return expr->expression_->Check(checker); 5333af6ab5fSopenharmony_ci} 5343af6ab5fSopenharmony_ci 5353af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check(ir::ConditionalExpression *expr) const 5363af6ab5fSopenharmony_ci{ 5373af6ab5fSopenharmony_ci TSChecker *checker = GetTSChecker(); 5383af6ab5fSopenharmony_ci checker::Type *testType = expr->Test()->Check(checker); 5393af6ab5fSopenharmony_ci 5403af6ab5fSopenharmony_ci checker->CheckTruthinessOfType(testType, expr->Test()->Start()); 5413af6ab5fSopenharmony_ci checker->CheckTestingKnownTruthyCallableOrAwaitableType(expr->Test(), testType, expr->Consequent()); 5423af6ab5fSopenharmony_ci 5433af6ab5fSopenharmony_ci checker::Type *consequentType = expr->Consequent()->Check(checker); 5443af6ab5fSopenharmony_ci checker::Type *alternateType = expr->Alternate()->Check(checker); 5453af6ab5fSopenharmony_ci 5463af6ab5fSopenharmony_ci return checker->CreateUnionType({consequentType, alternateType}); 5473af6ab5fSopenharmony_ci} 5483af6ab5fSopenharmony_ci 5493af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check(ir::FunctionExpression *expr) const 5503af6ab5fSopenharmony_ci{ 5513af6ab5fSopenharmony_ci TSChecker *checker = GetTSChecker(); 5523af6ab5fSopenharmony_ci varbinder::Variable *funcVar = nullptr; 5533af6ab5fSopenharmony_ci 5543af6ab5fSopenharmony_ci if (expr->Function()->Parent()->Parent() != nullptr && 5553af6ab5fSopenharmony_ci expr->Function()->Parent()->Parent()->IsVariableDeclarator() && 5563af6ab5fSopenharmony_ci expr->Function()->Parent()->Parent()->AsVariableDeclarator()->Id()->IsIdentifier()) { 5573af6ab5fSopenharmony_ci funcVar = expr->Function()->Parent()->Parent()->AsVariableDeclarator()->Id()->AsIdentifier()->Variable(); 5583af6ab5fSopenharmony_ci } 5593af6ab5fSopenharmony_ci 5603af6ab5fSopenharmony_ci checker::ScopeContext scopeCtx(checker, expr->Function()->Scope()); 5613af6ab5fSopenharmony_ci 5623af6ab5fSopenharmony_ci auto *signatureInfo = checker->Allocator()->New<checker::SignatureInfo>(checker->Allocator()); 5633af6ab5fSopenharmony_ci checker->CheckFunctionParameterDeclarations(expr->Function()->Params(), signatureInfo); 5643af6ab5fSopenharmony_ci 5653af6ab5fSopenharmony_ci auto *signature = checker->Allocator()->New<checker::Signature>(signatureInfo, checker->GlobalResolvingReturnType(), 5663af6ab5fSopenharmony_ci expr->Function()); 5673af6ab5fSopenharmony_ci checker::Type *funcType = checker->CreateFunctionTypeWithSignature(signature); 5683af6ab5fSopenharmony_ci 5693af6ab5fSopenharmony_ci if (funcVar != nullptr && funcVar->TsType() == nullptr) { 5703af6ab5fSopenharmony_ci funcVar->SetTsType(funcType); 5713af6ab5fSopenharmony_ci } 5723af6ab5fSopenharmony_ci 5733af6ab5fSopenharmony_ci signature->SetReturnType(checker->HandleFunctionReturn(expr->Function())); 5743af6ab5fSopenharmony_ci 5753af6ab5fSopenharmony_ci expr->Function()->Body()->Check(checker); 5763af6ab5fSopenharmony_ci 5773af6ab5fSopenharmony_ci return funcType; 5783af6ab5fSopenharmony_ci} 5793af6ab5fSopenharmony_ci 5803af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check(ir::Identifier *expr) const 5813af6ab5fSopenharmony_ci{ 5823af6ab5fSopenharmony_ci TSChecker *checker = GetTSChecker(); 5833af6ab5fSopenharmony_ci if (expr->Variable() == nullptr) { 5843af6ab5fSopenharmony_ci if (expr->Name().Is("undefined")) { 5853af6ab5fSopenharmony_ci return checker->GlobalUndefinedType(); 5863af6ab5fSopenharmony_ci } 5873af6ab5fSopenharmony_ci 5883af6ab5fSopenharmony_ci checker->ThrowTypeError({"Cannot find name ", expr->Name()}, expr->Start()); 5893af6ab5fSopenharmony_ci } 5903af6ab5fSopenharmony_ci 5913af6ab5fSopenharmony_ci const varbinder::Decl *decl = expr->Variable()->Declaration(); 5923af6ab5fSopenharmony_ci 5933af6ab5fSopenharmony_ci if (decl->IsTypeAliasDecl() || decl->IsInterfaceDecl()) { 5943af6ab5fSopenharmony_ci checker->ThrowTypeError({expr->Name(), " only refers to a type, but is being used as a value here."}, 5953af6ab5fSopenharmony_ci expr->Start()); 5963af6ab5fSopenharmony_ci } 5973af6ab5fSopenharmony_ci 5983af6ab5fSopenharmony_ci expr->SetTsType(checker->GetTypeOfVariable(expr->Variable())); 5993af6ab5fSopenharmony_ci return expr->TsType(); 6003af6ab5fSopenharmony_ci} 6013af6ab5fSopenharmony_ci 6023af6ab5fSopenharmony_civoid TSAnalyzer::CheckComputed(ir::MemberExpression *expr, checker::Type *indexType) const 6033af6ab5fSopenharmony_ci{ 6043af6ab5fSopenharmony_ci TSChecker *checker = GetTSChecker(); 6053af6ab5fSopenharmony_ci if (!indexType->HasTypeFlag(checker::TypeFlag::STRING_LIKE | checker::TypeFlag::NUMBER_LIKE)) { 6063af6ab5fSopenharmony_ci checker->ThrowTypeError({"Type ", indexType, " cannot be used as index type"}, expr->Property()->Start()); 6073af6ab5fSopenharmony_ci } 6083af6ab5fSopenharmony_ci 6093af6ab5fSopenharmony_ci if (indexType->IsNumberType()) { 6103af6ab5fSopenharmony_ci checker->ThrowTypeError("No index signature with a parameter of type 'string' was found on type this type", 6113af6ab5fSopenharmony_ci expr->Start()); 6123af6ab5fSopenharmony_ci } 6133af6ab5fSopenharmony_ci 6143af6ab5fSopenharmony_ci if (indexType->IsStringType()) { 6153af6ab5fSopenharmony_ci checker->ThrowTypeError("No index signature with a parameter of type 'number' was found on type this type", 6163af6ab5fSopenharmony_ci expr->Start()); 6173af6ab5fSopenharmony_ci } 6183af6ab5fSopenharmony_ci 6193af6ab5fSopenharmony_ci switch (expr->Property()->Type()) { 6203af6ab5fSopenharmony_ci case ir::AstNodeType::IDENTIFIER: { 6213af6ab5fSopenharmony_ci checker->ThrowTypeError( 6223af6ab5fSopenharmony_ci {"Property ", expr->Property()->AsIdentifier()->Name(), " does not exist on this type."}, 6233af6ab5fSopenharmony_ci expr->Property()->Start()); 6243af6ab5fSopenharmony_ci } 6253af6ab5fSopenharmony_ci case ir::AstNodeType::NUMBER_LITERAL: { 6263af6ab5fSopenharmony_ci checker->ThrowTypeError( 6273af6ab5fSopenharmony_ci {"Property ", expr->Property()->AsNumberLiteral()->Str(), " does not exist on this type."}, 6283af6ab5fSopenharmony_ci expr->Property()->Start()); 6293af6ab5fSopenharmony_ci } 6303af6ab5fSopenharmony_ci case ir::AstNodeType::STRING_LITERAL: { 6313af6ab5fSopenharmony_ci checker->ThrowTypeError( 6323af6ab5fSopenharmony_ci {"Property ", expr->Property()->AsStringLiteral()->Str(), " does not exist on this type."}, 6333af6ab5fSopenharmony_ci expr->Property()->Start()); 6343af6ab5fSopenharmony_ci } 6353af6ab5fSopenharmony_ci default: { 6363af6ab5fSopenharmony_ci UNREACHABLE(); 6373af6ab5fSopenharmony_ci } 6383af6ab5fSopenharmony_ci } 6393af6ab5fSopenharmony_ci} 6403af6ab5fSopenharmony_ci 6413af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check(ir::MemberExpression *expr) const 6423af6ab5fSopenharmony_ci{ 6433af6ab5fSopenharmony_ci TSChecker *checker = GetTSChecker(); 6443af6ab5fSopenharmony_ci checker::Type *baseType = checker->CheckNonNullType(expr->Object()->Check(checker), expr->Object()->Start()); 6453af6ab5fSopenharmony_ci 6463af6ab5fSopenharmony_ci if (expr->IsComputed()) { 6473af6ab5fSopenharmony_ci checker::Type *indexType = expr->Property()->Check(checker); 6483af6ab5fSopenharmony_ci checker::Type *indexedAccessType = checker->GetPropertyTypeForIndexType(baseType, indexType); 6493af6ab5fSopenharmony_ci 6503af6ab5fSopenharmony_ci if (indexedAccessType != nullptr) { 6513af6ab5fSopenharmony_ci return indexedAccessType; 6523af6ab5fSopenharmony_ci } 6533af6ab5fSopenharmony_ci CheckComputed(expr, indexType); 6543af6ab5fSopenharmony_ci } 6553af6ab5fSopenharmony_ci 6563af6ab5fSopenharmony_ci varbinder::Variable *prop = checker->GetPropertyOfType(baseType, expr->Property()->AsIdentifier()->Name()); 6573af6ab5fSopenharmony_ci 6583af6ab5fSopenharmony_ci if (prop != nullptr) { 6593af6ab5fSopenharmony_ci checker::Type *propType = checker->GetTypeOfVariable(prop); 6603af6ab5fSopenharmony_ci if (prop->HasFlag(varbinder::VariableFlags::READONLY)) { 6613af6ab5fSopenharmony_ci propType->AddTypeFlag(checker::TypeFlag::READONLY); 6623af6ab5fSopenharmony_ci } 6633af6ab5fSopenharmony_ci 6643af6ab5fSopenharmony_ci return propType; 6653af6ab5fSopenharmony_ci } 6663af6ab5fSopenharmony_ci 6673af6ab5fSopenharmony_ci if (baseType->IsObjectType()) { 6683af6ab5fSopenharmony_ci checker::ObjectType *objType = baseType->AsObjectType(); 6693af6ab5fSopenharmony_ci 6703af6ab5fSopenharmony_ci if (objType->StringIndexInfo() != nullptr) { 6713af6ab5fSopenharmony_ci checker::Type *indexType = objType->StringIndexInfo()->GetType(); 6723af6ab5fSopenharmony_ci if (objType->StringIndexInfo()->Readonly()) { 6733af6ab5fSopenharmony_ci indexType->AddTypeFlag(checker::TypeFlag::READONLY); 6743af6ab5fSopenharmony_ci } 6753af6ab5fSopenharmony_ci 6763af6ab5fSopenharmony_ci return indexType; 6773af6ab5fSopenharmony_ci } 6783af6ab5fSopenharmony_ci } 6793af6ab5fSopenharmony_ci 6803af6ab5fSopenharmony_ci checker->ThrowTypeError({"Property ", expr->Property()->AsIdentifier()->Name(), " does not exist on this type."}, 6813af6ab5fSopenharmony_ci expr->Property()->Start()); 6823af6ab5fSopenharmony_ci return nullptr; 6833af6ab5fSopenharmony_ci} 6843af6ab5fSopenharmony_ci 6853af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check(ir::NewExpression *expr) const 6863af6ab5fSopenharmony_ci{ 6873af6ab5fSopenharmony_ci TSChecker *checker = GetTSChecker(); 6883af6ab5fSopenharmony_ci checker::Type *calleeType = expr->callee_->Check(checker); 6893af6ab5fSopenharmony_ci 6903af6ab5fSopenharmony_ci if (calleeType->IsObjectType()) { 6913af6ab5fSopenharmony_ci checker::ObjectType *calleeObj = calleeType->AsObjectType(); 6923af6ab5fSopenharmony_ci return checker->ResolveCallOrNewExpression(calleeObj->ConstructSignatures(), expr->Arguments(), expr->Start()); 6933af6ab5fSopenharmony_ci } 6943af6ab5fSopenharmony_ci 6953af6ab5fSopenharmony_ci checker->ThrowTypeError("This expression is not callable.", expr->Start()); 6963af6ab5fSopenharmony_ci return nullptr; 6973af6ab5fSopenharmony_ci} 6983af6ab5fSopenharmony_cistatic const util::StringView &GetPropertyName(const ir::Expression *key) 6993af6ab5fSopenharmony_ci{ 7003af6ab5fSopenharmony_ci if (key->IsIdentifier()) { 7013af6ab5fSopenharmony_ci return key->AsIdentifier()->Name(); 7023af6ab5fSopenharmony_ci } 7033af6ab5fSopenharmony_ci 7043af6ab5fSopenharmony_ci if (key->IsStringLiteral()) { 7053af6ab5fSopenharmony_ci return key->AsStringLiteral()->Str(); 7063af6ab5fSopenharmony_ci } 7073af6ab5fSopenharmony_ci 7083af6ab5fSopenharmony_ci ASSERT(key->IsNumberLiteral()); 7093af6ab5fSopenharmony_ci return key->AsNumberLiteral()->Str(); 7103af6ab5fSopenharmony_ci} 7113af6ab5fSopenharmony_ci 7123af6ab5fSopenharmony_cistatic varbinder::VariableFlags GetFlagsForProperty(const ir::Property *prop) 7133af6ab5fSopenharmony_ci{ 7143af6ab5fSopenharmony_ci if (!prop->IsMethod()) { 7153af6ab5fSopenharmony_ci return varbinder::VariableFlags::PROPERTY; 7163af6ab5fSopenharmony_ci } 7173af6ab5fSopenharmony_ci 7183af6ab5fSopenharmony_ci varbinder::VariableFlags propFlags = varbinder::VariableFlags::METHOD; 7193af6ab5fSopenharmony_ci 7203af6ab5fSopenharmony_ci if (prop->IsAccessor() && prop->Kind() == ir::PropertyKind::GET) { 7213af6ab5fSopenharmony_ci propFlags |= varbinder::VariableFlags::READONLY; 7223af6ab5fSopenharmony_ci } 7233af6ab5fSopenharmony_ci 7243af6ab5fSopenharmony_ci return propFlags; 7253af6ab5fSopenharmony_ci} 7263af6ab5fSopenharmony_ci 7273af6ab5fSopenharmony_cistatic checker::Type *GetTypeForProperty(ir::Property *prop, checker::TSChecker *checker) 7283af6ab5fSopenharmony_ci{ 7293af6ab5fSopenharmony_ci if (prop->IsAccessor()) { 7303af6ab5fSopenharmony_ci checker::Type *funcType = prop->Value()->Check(checker); 7313af6ab5fSopenharmony_ci 7323af6ab5fSopenharmony_ci if (prop->Kind() == ir::PropertyKind::SET) { 7333af6ab5fSopenharmony_ci return checker->GlobalAnyType(); 7343af6ab5fSopenharmony_ci } 7353af6ab5fSopenharmony_ci 7363af6ab5fSopenharmony_ci ASSERT(funcType->IsObjectType() && funcType->AsObjectType()->IsFunctionType()); 7373af6ab5fSopenharmony_ci return funcType->AsObjectType()->CallSignatures()[0]->ReturnType(); 7383af6ab5fSopenharmony_ci } 7393af6ab5fSopenharmony_ci 7403af6ab5fSopenharmony_ci if (prop->IsShorthand()) { 7413af6ab5fSopenharmony_ci return prop->Key()->Check(checker); 7423af6ab5fSopenharmony_ci } 7433af6ab5fSopenharmony_ci 7443af6ab5fSopenharmony_ci return prop->Value()->Check(checker); 7453af6ab5fSopenharmony_ci} 7463af6ab5fSopenharmony_ci 7473af6ab5fSopenharmony_civoid TSAnalyzer::CheckSpread(std::unordered_map<util::StringView, lexer::SourcePosition> &allPropertiesMap, 7483af6ab5fSopenharmony_ci checker::ObjectDescriptor *desc, ir::Expression *it) const 7493af6ab5fSopenharmony_ci{ 7503af6ab5fSopenharmony_ci TSChecker *checker = GetTSChecker(); 7513af6ab5fSopenharmony_ci ASSERT(it->IsSpreadElement()); 7523af6ab5fSopenharmony_ci 7533af6ab5fSopenharmony_ci checker::Type *const spreadType = it->AsSpreadElement()->Argument()->Check(checker); 7543af6ab5fSopenharmony_ci 7553af6ab5fSopenharmony_ci // NOTE: aszilagyi. handle union of object types 7563af6ab5fSopenharmony_ci if (!spreadType->IsObjectType()) { 7573af6ab5fSopenharmony_ci checker->ThrowTypeError("Spread types may only be created from object types.", it->Start()); 7583af6ab5fSopenharmony_ci } 7593af6ab5fSopenharmony_ci 7603af6ab5fSopenharmony_ci for (auto *spreadProp : spreadType->AsObjectType()->Properties()) { 7613af6ab5fSopenharmony_ci auto found = allPropertiesMap.find(spreadProp->Name()); 7623af6ab5fSopenharmony_ci if (found != allPropertiesMap.end()) { 7633af6ab5fSopenharmony_ci checker->ThrowTypeError({found->first, " is specified more than once, so this usage will be overwritten."}, 7643af6ab5fSopenharmony_ci found->second); 7653af6ab5fSopenharmony_ci } 7663af6ab5fSopenharmony_ci 7673af6ab5fSopenharmony_ci varbinder::LocalVariable *foundMember = desc->FindProperty(spreadProp->Name()); 7683af6ab5fSopenharmony_ci 7693af6ab5fSopenharmony_ci if (foundMember != nullptr) { 7703af6ab5fSopenharmony_ci foundMember->SetTsType(spreadProp->TsType()); 7713af6ab5fSopenharmony_ci continue; 7723af6ab5fSopenharmony_ci } 7733af6ab5fSopenharmony_ci 7743af6ab5fSopenharmony_ci desc->properties.push_back(spreadProp); 7753af6ab5fSopenharmony_ci } 7763af6ab5fSopenharmony_ci} 7773af6ab5fSopenharmony_ci 7783af6ab5fSopenharmony_civoid TSAnalyzer::CheckNonComputed(checker::ObjectDescriptor *desc, ir::Expression *it, 7793af6ab5fSopenharmony_ci std::unordered_map<util::StringView, lexer::SourcePosition> &allPropertiesMap, 7803af6ab5fSopenharmony_ci bool inConstContext) const 7813af6ab5fSopenharmony_ci{ 7823af6ab5fSopenharmony_ci TSChecker *checker = GetTSChecker(); 7833af6ab5fSopenharmony_ci auto *prop = it->AsProperty(); 7843af6ab5fSopenharmony_ci checker::Type *propType = GetTypeForProperty(prop, checker); 7853af6ab5fSopenharmony_ci varbinder::VariableFlags flags = GetFlagsForProperty(prop); 7863af6ab5fSopenharmony_ci const util::StringView &propName = GetPropertyName(prop->Key()); 7873af6ab5fSopenharmony_ci 7883af6ab5fSopenharmony_ci auto *memberVar = varbinder::Scope::CreateVar(checker->Allocator(), propName, flags, it); 7893af6ab5fSopenharmony_ci 7903af6ab5fSopenharmony_ci if (inConstContext) { 7913af6ab5fSopenharmony_ci memberVar->AddFlag(varbinder::VariableFlags::READONLY); 7923af6ab5fSopenharmony_ci } else { 7933af6ab5fSopenharmony_ci propType = checker->GetBaseTypeOfLiteralType(propType); 7943af6ab5fSopenharmony_ci } 7953af6ab5fSopenharmony_ci 7963af6ab5fSopenharmony_ci memberVar->SetTsType(propType); 7973af6ab5fSopenharmony_ci 7983af6ab5fSopenharmony_ci if (prop->Key()->IsNumberLiteral()) { 7993af6ab5fSopenharmony_ci memberVar->AddFlag(varbinder::VariableFlags::NUMERIC_NAME); 8003af6ab5fSopenharmony_ci } 8013af6ab5fSopenharmony_ci 8023af6ab5fSopenharmony_ci varbinder::LocalVariable *foundMember = desc->FindProperty(propName); 8033af6ab5fSopenharmony_ci allPropertiesMap.insert({propName, it->Start()}); 8043af6ab5fSopenharmony_ci 8053af6ab5fSopenharmony_ci if (foundMember != nullptr) { 8063af6ab5fSopenharmony_ci foundMember->SetTsType(propType); 8073af6ab5fSopenharmony_ci return; 8083af6ab5fSopenharmony_ci } 8093af6ab5fSopenharmony_ci 8103af6ab5fSopenharmony_ci desc->properties.push_back(memberVar); 8113af6ab5fSopenharmony_ci} 8123af6ab5fSopenharmony_ci 8133af6ab5fSopenharmony_cichecker::IndexInfo *TSAnalyzer::CreateUnionTypeHelper(ArenaVector<checker::Type *> &computedPropTypes, 8143af6ab5fSopenharmony_ci bool inConstContext) const 8153af6ab5fSopenharmony_ci{ 8163af6ab5fSopenharmony_ci TSChecker *checker = GetTSChecker(); 8173af6ab5fSopenharmony_ci 8183af6ab5fSopenharmony_ci return checker->Allocator()->New<checker::IndexInfo>(checker->CreateUnionType(std::move(computedPropTypes)), "x", 8193af6ab5fSopenharmony_ci inConstContext); 8203af6ab5fSopenharmony_ci} 8213af6ab5fSopenharmony_ci 8223af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check(ir::ObjectExpression *expr) const 8233af6ab5fSopenharmony_ci{ 8243af6ab5fSopenharmony_ci TSChecker *checker = GetTSChecker(); 8253af6ab5fSopenharmony_ci 8263af6ab5fSopenharmony_ci checker::ObjectDescriptor *desc = checker->Allocator()->New<checker::ObjectDescriptor>(checker->Allocator()); 8273af6ab5fSopenharmony_ci std::unordered_map<util::StringView, lexer::SourcePosition> allPropertiesMap; 8283af6ab5fSopenharmony_ci bool inConstContext = checker->HasStatus(checker::CheckerStatus::IN_CONST_CONTEXT); 8293af6ab5fSopenharmony_ci ArenaVector<checker::Type *> computedNumberPropTypes(checker->Allocator()->Adapter()); 8303af6ab5fSopenharmony_ci ArenaVector<checker::Type *> computedStringPropTypes(checker->Allocator()->Adapter()); 8313af6ab5fSopenharmony_ci bool hasComputedNumberProperty = false; 8323af6ab5fSopenharmony_ci bool hasComputedStringProperty = false; 8333af6ab5fSopenharmony_ci bool seenSpread = false; 8343af6ab5fSopenharmony_ci 8353af6ab5fSopenharmony_ci for (auto *it : expr->Properties()) { 8363af6ab5fSopenharmony_ci if (it->IsProperty()) { 8373af6ab5fSopenharmony_ci auto *prop = it->AsProperty(); 8383af6ab5fSopenharmony_ci 8393af6ab5fSopenharmony_ci if (prop->IsComputed() && checker->CheckComputedPropertyName(prop->Key())->IsNumberType()) { 8403af6ab5fSopenharmony_ci hasComputedNumberProperty = true; 8413af6ab5fSopenharmony_ci computedNumberPropTypes.push_back(prop->Value()->Check(checker)); 8423af6ab5fSopenharmony_ci continue; 8433af6ab5fSopenharmony_ci } 8443af6ab5fSopenharmony_ci 8453af6ab5fSopenharmony_ci if (prop->IsComputed() && checker->CheckComputedPropertyName(prop->Key())->IsStringType()) { 8463af6ab5fSopenharmony_ci hasComputedStringProperty = true; 8473af6ab5fSopenharmony_ci computedStringPropTypes.push_back(prop->Value()->Check(checker)); 8483af6ab5fSopenharmony_ci continue; 8493af6ab5fSopenharmony_ci } 8503af6ab5fSopenharmony_ci 8513af6ab5fSopenharmony_ci CheckNonComputed(desc, it, allPropertiesMap, inConstContext); 8523af6ab5fSopenharmony_ci } 8533af6ab5fSopenharmony_ci 8543af6ab5fSopenharmony_ci if (it->IsSpreadElement()) { 8553af6ab5fSopenharmony_ci CheckSpread(allPropertiesMap, desc, it); 8563af6ab5fSopenharmony_ci seenSpread = true; 8573af6ab5fSopenharmony_ci } 8583af6ab5fSopenharmony_ci } 8593af6ab5fSopenharmony_ci 8603af6ab5fSopenharmony_ci if (!seenSpread && (hasComputedNumberProperty || hasComputedStringProperty)) { 8613af6ab5fSopenharmony_ci for (auto *it : desc->properties) { 8623af6ab5fSopenharmony_ci computedStringPropTypes.push_back(it->TsType()); 8633af6ab5fSopenharmony_ci 8643af6ab5fSopenharmony_ci if (hasComputedNumberProperty && it->HasFlag(varbinder::VariableFlags::NUMERIC_NAME)) { 8653af6ab5fSopenharmony_ci computedNumberPropTypes.push_back(it->TsType()); 8663af6ab5fSopenharmony_ci } 8673af6ab5fSopenharmony_ci } 8683af6ab5fSopenharmony_ci 8693af6ab5fSopenharmony_ci if (hasComputedNumberProperty) { 8703af6ab5fSopenharmony_ci desc->numberIndexInfo = CreateUnionTypeHelper(computedNumberPropTypes, inConstContext); 8713af6ab5fSopenharmony_ci } 8723af6ab5fSopenharmony_ci 8733af6ab5fSopenharmony_ci if (hasComputedStringProperty) { 8743af6ab5fSopenharmony_ci desc->stringIndexInfo = CreateUnionTypeHelper(computedStringPropTypes, inConstContext); 8753af6ab5fSopenharmony_ci } 8763af6ab5fSopenharmony_ci } 8773af6ab5fSopenharmony_ci 8783af6ab5fSopenharmony_ci checker::Type *returnType = checker->Allocator()->New<checker::ObjectLiteralType>(desc); 8793af6ab5fSopenharmony_ci returnType->AsObjectType()->AddObjectFlag(checker::ObjectFlags::RESOLVED_MEMBERS | 8803af6ab5fSopenharmony_ci checker::ObjectFlags::CHECK_EXCESS_PROPS); 8813af6ab5fSopenharmony_ci return returnType; 8823af6ab5fSopenharmony_ci} 8833af6ab5fSopenharmony_ci 8843af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check([[maybe_unused]] ir::OmittedExpression *expr) const 8853af6ab5fSopenharmony_ci{ 8863af6ab5fSopenharmony_ci TSChecker *checker = GetTSChecker(); 8873af6ab5fSopenharmony_ci return checker->GlobalUndefinedType(); 8883af6ab5fSopenharmony_ci} 8893af6ab5fSopenharmony_ci 8903af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check([[maybe_unused]] ir::OpaqueTypeNode *expr) const 8913af6ab5fSopenharmony_ci{ 8923af6ab5fSopenharmony_ci return expr->TsType(); 8933af6ab5fSopenharmony_ci} 8943af6ab5fSopenharmony_ci 8953af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check([[maybe_unused]] ir::SequenceExpression *expr) const 8963af6ab5fSopenharmony_ci{ 8973af6ab5fSopenharmony_ci TSChecker *checker = GetTSChecker(); 8983af6ab5fSopenharmony_ci // NOTE: aszilagyi. 8993af6ab5fSopenharmony_ci return checker->GlobalAnyType(); 9003af6ab5fSopenharmony_ci} 9013af6ab5fSopenharmony_ci 9023af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check([[maybe_unused]] ir::SuperExpression *expr) const 9033af6ab5fSopenharmony_ci{ 9043af6ab5fSopenharmony_ci TSChecker *checker = GetTSChecker(); 9053af6ab5fSopenharmony_ci // NOTE: aszilagyi. 9063af6ab5fSopenharmony_ci return checker->GlobalAnyType(); 9073af6ab5fSopenharmony_ci} 9083af6ab5fSopenharmony_ci 9093af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check([[maybe_unused]] ir::TaggedTemplateExpression *expr) const 9103af6ab5fSopenharmony_ci{ 9113af6ab5fSopenharmony_ci TSChecker *checker = GetTSChecker(); 9123af6ab5fSopenharmony_ci // NOTE: aszilagyi. 9133af6ab5fSopenharmony_ci return checker->GlobalAnyType(); 9143af6ab5fSopenharmony_ci} 9153af6ab5fSopenharmony_ci 9163af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check([[maybe_unused]] ir::TemplateLiteral *expr) const 9173af6ab5fSopenharmony_ci{ 9183af6ab5fSopenharmony_ci TSChecker *checker = GetTSChecker(); 9193af6ab5fSopenharmony_ci // NOTE(aszilagyi) 9203af6ab5fSopenharmony_ci return checker->GlobalAnyType(); 9213af6ab5fSopenharmony_ci} 9223af6ab5fSopenharmony_ci 9233af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check([[maybe_unused]] ir::ThisExpression *expr) const 9243af6ab5fSopenharmony_ci{ 9253af6ab5fSopenharmony_ci TSChecker *checker = GetTSChecker(); 9263af6ab5fSopenharmony_ci // NOTE: aszilagyi 9273af6ab5fSopenharmony_ci return checker->GlobalAnyType(); 9283af6ab5fSopenharmony_ci} 9293af6ab5fSopenharmony_ci 9303af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check([[maybe_unused]] ir::TypeofExpression *expr) const 9313af6ab5fSopenharmony_ci{ 9323af6ab5fSopenharmony_ci TSChecker *checker = GetTSChecker(); 9333af6ab5fSopenharmony_ci return checker->GlobalStringType(); 9343af6ab5fSopenharmony_ci} 9353af6ab5fSopenharmony_ci 9363af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::CheckDeleteKeyword([[maybe_unused]] checker::TSChecker *checker, 9373af6ab5fSopenharmony_ci ir::UnaryExpression *expr) const 9383af6ab5fSopenharmony_ci{ 9393af6ab5fSopenharmony_ci checker::Type *propType = expr->argument_->Check(checker); 9403af6ab5fSopenharmony_ci if (!expr->Argument()->IsMemberExpression()) { 9413af6ab5fSopenharmony_ci checker->ThrowTypeError("The operand of a delete operator must be a property reference.", 9423af6ab5fSopenharmony_ci expr->Argument()->Start()); 9433af6ab5fSopenharmony_ci } 9443af6ab5fSopenharmony_ci if (propType->Variable()->HasFlag(varbinder::VariableFlags::READONLY)) { 9453af6ab5fSopenharmony_ci checker->ThrowTypeError("The operand of a delete operator cannot be a readonly property.", 9463af6ab5fSopenharmony_ci expr->Argument()->Start()); 9473af6ab5fSopenharmony_ci } 9483af6ab5fSopenharmony_ci if (!propType->Variable()->HasFlag(varbinder::VariableFlags::OPTIONAL)) { 9493af6ab5fSopenharmony_ci checker->ThrowTypeError("The operand of a delete operator must be a optional.", expr->Argument()->Start()); 9503af6ab5fSopenharmony_ci } 9513af6ab5fSopenharmony_ci return checker->GlobalBooleanType(); 9523af6ab5fSopenharmony_ci} 9533af6ab5fSopenharmony_ci 9543af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::CheckLiteral([[maybe_unused]] checker::TSChecker *checker, ir::UnaryExpression *expr) const 9553af6ab5fSopenharmony_ci{ 9563af6ab5fSopenharmony_ci if (!expr->Argument()->IsLiteral()) { 9573af6ab5fSopenharmony_ci return nullptr; 9583af6ab5fSopenharmony_ci } 9593af6ab5fSopenharmony_ci 9603af6ab5fSopenharmony_ci const ir::Literal *lit = expr->Argument()->AsLiteral(); 9613af6ab5fSopenharmony_ci if (lit->IsNumberLiteral()) { 9623af6ab5fSopenharmony_ci auto numberValue = lit->AsNumberLiteral()->Number().GetDouble(); 9633af6ab5fSopenharmony_ci if (expr->OperatorType() == lexer::TokenType::PUNCTUATOR_PLUS) { 9643af6ab5fSopenharmony_ci return checker->CreateNumberLiteralType(numberValue); 9653af6ab5fSopenharmony_ci } 9663af6ab5fSopenharmony_ci if (expr->OperatorType() == lexer::TokenType::PUNCTUATOR_MINUS) { 9673af6ab5fSopenharmony_ci return checker->CreateNumberLiteralType(-numberValue); 9683af6ab5fSopenharmony_ci } 9693af6ab5fSopenharmony_ci } else if (lit->IsBigIntLiteral() && expr->OperatorType() == lexer::TokenType::PUNCTUATOR_MINUS) { 9703af6ab5fSopenharmony_ci return checker->CreateBigintLiteralType(lit->AsBigIntLiteral()->Str(), true); 9713af6ab5fSopenharmony_ci } 9723af6ab5fSopenharmony_ci 9733af6ab5fSopenharmony_ci return nullptr; 9743af6ab5fSopenharmony_ci} 9753af6ab5fSopenharmony_ci 9763af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check(ir::UnaryExpression *expr) const 9773af6ab5fSopenharmony_ci{ 9783af6ab5fSopenharmony_ci TSChecker *checker = GetTSChecker(); 9793af6ab5fSopenharmony_ci checker::Type *operandType = expr->argument_->Check(checker); 9803af6ab5fSopenharmony_ci 9813af6ab5fSopenharmony_ci if (expr->operator_ == lexer::TokenType::KEYW_TYPEOF) { 9823af6ab5fSopenharmony_ci return operandType; 9833af6ab5fSopenharmony_ci } 9843af6ab5fSopenharmony_ci 9853af6ab5fSopenharmony_ci if (expr->operator_ == lexer::TokenType::KEYW_DELETE) { 9863af6ab5fSopenharmony_ci return CheckDeleteKeyword(checker, expr); 9873af6ab5fSopenharmony_ci } 9883af6ab5fSopenharmony_ci 9893af6ab5fSopenharmony_ci auto *res = CheckLiteral(checker, expr); 9903af6ab5fSopenharmony_ci if (res != nullptr) { 9913af6ab5fSopenharmony_ci return res; 9923af6ab5fSopenharmony_ci } 9933af6ab5fSopenharmony_ci 9943af6ab5fSopenharmony_ci switch (expr->operator_) { 9953af6ab5fSopenharmony_ci case lexer::TokenType::PUNCTUATOR_PLUS: 9963af6ab5fSopenharmony_ci case lexer::TokenType::PUNCTUATOR_MINUS: 9973af6ab5fSopenharmony_ci case lexer::TokenType::PUNCTUATOR_TILDE: { 9983af6ab5fSopenharmony_ci checker->CheckNonNullType(operandType, expr->Start()); 9993af6ab5fSopenharmony_ci // NOTE: aszilagyi. check Symbol like types 10003af6ab5fSopenharmony_ci 10013af6ab5fSopenharmony_ci if (expr->operator_ == lexer::TokenType::PUNCTUATOR_PLUS) { 10023af6ab5fSopenharmony_ci if (checker::TSChecker::MaybeTypeOfKind(operandType, checker::TypeFlag::BIGINT_LIKE)) { 10033af6ab5fSopenharmony_ci checker->ThrowTypeError({"Operator '+' cannot be applied to type '", operandType, "'"}, 10043af6ab5fSopenharmony_ci expr->Start()); 10053af6ab5fSopenharmony_ci } 10063af6ab5fSopenharmony_ci 10073af6ab5fSopenharmony_ci return checker->GlobalNumberType(); 10083af6ab5fSopenharmony_ci } 10093af6ab5fSopenharmony_ci 10103af6ab5fSopenharmony_ci return checker->GetUnaryResultType(operandType); 10113af6ab5fSopenharmony_ci } 10123af6ab5fSopenharmony_ci case lexer::TokenType::PUNCTUATOR_EXCLAMATION_MARK: { 10133af6ab5fSopenharmony_ci checker->CheckTruthinessOfType(operandType, expr->Start()); 10143af6ab5fSopenharmony_ci auto facts = operandType->GetTypeFacts(); 10153af6ab5fSopenharmony_ci if ((facts & checker::TypeFacts::TRUTHY) != 0) { 10163af6ab5fSopenharmony_ci return checker->GlobalFalseType(); 10173af6ab5fSopenharmony_ci } 10183af6ab5fSopenharmony_ci 10193af6ab5fSopenharmony_ci if ((facts & checker::TypeFacts::FALSY) != 0) { 10203af6ab5fSopenharmony_ci return checker->GlobalTrueType(); 10213af6ab5fSopenharmony_ci } 10223af6ab5fSopenharmony_ci 10233af6ab5fSopenharmony_ci return checker->GlobalBooleanType(); 10243af6ab5fSopenharmony_ci } 10253af6ab5fSopenharmony_ci default: { 10263af6ab5fSopenharmony_ci UNREACHABLE(); 10273af6ab5fSopenharmony_ci } 10283af6ab5fSopenharmony_ci } 10293af6ab5fSopenharmony_ci 10303af6ab5fSopenharmony_ci return nullptr; 10313af6ab5fSopenharmony_ci} 10323af6ab5fSopenharmony_ci 10333af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check(ir::UpdateExpression *expr) const 10343af6ab5fSopenharmony_ci{ 10353af6ab5fSopenharmony_ci TSChecker *checker = GetTSChecker(); 10363af6ab5fSopenharmony_ci checker::Type *operandType = expr->argument_->Check(checker); 10373af6ab5fSopenharmony_ci checker->CheckNonNullType(operandType, expr->Start()); 10383af6ab5fSopenharmony_ci 10393af6ab5fSopenharmony_ci if (!operandType->HasTypeFlag(checker::TypeFlag::VALID_ARITHMETIC_TYPE)) { 10403af6ab5fSopenharmony_ci checker->ThrowTypeError("An arithmetic operand must be of type 'any', 'number', 'bigint' or an enum type.", 10413af6ab5fSopenharmony_ci expr->Start()); 10423af6ab5fSopenharmony_ci } 10433af6ab5fSopenharmony_ci 10443af6ab5fSopenharmony_ci checker->CheckReferenceExpression( 10453af6ab5fSopenharmony_ci expr->argument_, "The operand of an increment or decrement operator must be a variable or a property access", 10463af6ab5fSopenharmony_ci "The operand of an increment or decrement operator may not be an optional property access"); 10473af6ab5fSopenharmony_ci 10483af6ab5fSopenharmony_ci return checker->GetUnaryResultType(operandType); 10493af6ab5fSopenharmony_ci} 10503af6ab5fSopenharmony_ci 10513af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check([[maybe_unused]] ir::YieldExpression *expr) const 10523af6ab5fSopenharmony_ci{ 10533af6ab5fSopenharmony_ci TSChecker *checker = GetTSChecker(); 10543af6ab5fSopenharmony_ci // NOTE: aszilagyi. 10553af6ab5fSopenharmony_ci return checker->GlobalAnyType(); 10563af6ab5fSopenharmony_ci} 10573af6ab5fSopenharmony_ci// compile methods for LITERAL EXPRESSIONS in alphabetical order 10583af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check(ir::BigIntLiteral *expr) const 10593af6ab5fSopenharmony_ci{ 10603af6ab5fSopenharmony_ci TSChecker *checker = GetTSChecker(); 10613af6ab5fSopenharmony_ci auto search = checker->BigintLiteralMap().find(expr->Str()); 10623af6ab5fSopenharmony_ci if (search != checker->BigintLiteralMap().end()) { 10633af6ab5fSopenharmony_ci return search->second; 10643af6ab5fSopenharmony_ci } 10653af6ab5fSopenharmony_ci 10663af6ab5fSopenharmony_ci auto *newBigintLiteralType = checker->Allocator()->New<checker::BigintLiteralType>(expr->Str(), false); 10673af6ab5fSopenharmony_ci checker->BigintLiteralMap().insert({expr->Str(), newBigintLiteralType}); 10683af6ab5fSopenharmony_ci return newBigintLiteralType; 10693af6ab5fSopenharmony_ci} 10703af6ab5fSopenharmony_ci 10713af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check(ir::BooleanLiteral *expr) const 10723af6ab5fSopenharmony_ci{ 10733af6ab5fSopenharmony_ci TSChecker *checker = GetTSChecker(); 10743af6ab5fSopenharmony_ci return expr->Value() ? checker->GlobalTrueType() : checker->GlobalFalseType(); 10753af6ab5fSopenharmony_ci} 10763af6ab5fSopenharmony_ci 10773af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check([[maybe_unused]] ir::NullLiteral *expr) const 10783af6ab5fSopenharmony_ci{ 10793af6ab5fSopenharmony_ci TSChecker *checker = GetTSChecker(); 10803af6ab5fSopenharmony_ci return checker->GlobalNullType(); 10813af6ab5fSopenharmony_ci} 10823af6ab5fSopenharmony_ci 10833af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check(ir::NumberLiteral *expr) const 10843af6ab5fSopenharmony_ci{ 10853af6ab5fSopenharmony_ci TSChecker *checker = GetTSChecker(); 10863af6ab5fSopenharmony_ci auto search = checker->NumberLiteralMap().find(expr->Number().GetDouble()); 10873af6ab5fSopenharmony_ci if (search != checker->NumberLiteralMap().end()) { 10883af6ab5fSopenharmony_ci return search->second; 10893af6ab5fSopenharmony_ci } 10903af6ab5fSopenharmony_ci 10913af6ab5fSopenharmony_ci auto *newNumLiteralType = checker->Allocator()->New<checker::NumberLiteralType>(expr->Number().GetDouble()); 10923af6ab5fSopenharmony_ci checker->NumberLiteralMap().insert({expr->Number().GetDouble(), newNumLiteralType}); 10933af6ab5fSopenharmony_ci return newNumLiteralType; 10943af6ab5fSopenharmony_ci} 10953af6ab5fSopenharmony_ci 10963af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check([[maybe_unused]] ir::RegExpLiteral *expr) const 10973af6ab5fSopenharmony_ci{ 10983af6ab5fSopenharmony_ci TSChecker *checker = GetTSChecker(); 10993af6ab5fSopenharmony_ci // NOTE: aszilagyi 11003af6ab5fSopenharmony_ci return checker->GlobalAnyType(); 11013af6ab5fSopenharmony_ci} 11023af6ab5fSopenharmony_ci 11033af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check(ir::StringLiteral *expr) const 11043af6ab5fSopenharmony_ci{ 11053af6ab5fSopenharmony_ci TSChecker *checker = GetTSChecker(); 11063af6ab5fSopenharmony_ci auto search = checker->StringLiteralMap().find(expr->Str()); 11073af6ab5fSopenharmony_ci if (search != checker->StringLiteralMap().end()) { 11083af6ab5fSopenharmony_ci return search->second; 11093af6ab5fSopenharmony_ci } 11103af6ab5fSopenharmony_ci 11113af6ab5fSopenharmony_ci auto *newStrLiteralType = checker->Allocator()->New<checker::StringLiteralType>(expr->Str()); 11123af6ab5fSopenharmony_ci checker->StringLiteralMap().insert({expr->Str(), newStrLiteralType}); 11133af6ab5fSopenharmony_ci 11143af6ab5fSopenharmony_ci return newStrLiteralType; 11153af6ab5fSopenharmony_ci} 11163af6ab5fSopenharmony_ci 11173af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check(ir::BlockStatement *st) const 11183af6ab5fSopenharmony_ci{ 11193af6ab5fSopenharmony_ci TSChecker *checker = GetTSChecker(); 11203af6ab5fSopenharmony_ci checker::ScopeContext scopeCtx(checker, st->Scope()); 11213af6ab5fSopenharmony_ci 11223af6ab5fSopenharmony_ci for (auto *it : st->Statements()) { 11233af6ab5fSopenharmony_ci it->Check(checker); 11243af6ab5fSopenharmony_ci } 11253af6ab5fSopenharmony_ci 11263af6ab5fSopenharmony_ci return nullptr; 11273af6ab5fSopenharmony_ci} 11283af6ab5fSopenharmony_ci 11293af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check([[maybe_unused]] ir::BreakStatement *st) const 11303af6ab5fSopenharmony_ci{ 11313af6ab5fSopenharmony_ci return nullptr; 11323af6ab5fSopenharmony_ci} 11333af6ab5fSopenharmony_ci 11343af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check(ir::DoWhileStatement *st) const 11353af6ab5fSopenharmony_ci{ 11363af6ab5fSopenharmony_ci TSChecker *checker = GetTSChecker(); 11373af6ab5fSopenharmony_ci checker::ScopeContext scopeCtx(checker, st->Scope()); 11383af6ab5fSopenharmony_ci 11393af6ab5fSopenharmony_ci checker::Type *testType = st->Test()->Check(checker); 11403af6ab5fSopenharmony_ci checker->CheckTruthinessOfType(testType, st->Test()->Start()); 11413af6ab5fSopenharmony_ci st->Body()->Check(checker); 11423af6ab5fSopenharmony_ci 11433af6ab5fSopenharmony_ci return nullptr; 11443af6ab5fSopenharmony_ci} 11453af6ab5fSopenharmony_ci 11463af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check([[maybe_unused]] ir::EmptyStatement *st) const 11473af6ab5fSopenharmony_ci{ 11483af6ab5fSopenharmony_ci return nullptr; 11493af6ab5fSopenharmony_ci} 11503af6ab5fSopenharmony_ci 11513af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check(ir::ExpressionStatement *st) const 11523af6ab5fSopenharmony_ci{ 11533af6ab5fSopenharmony_ci TSChecker *checker = GetTSChecker(); 11543af6ab5fSopenharmony_ci return st->GetExpression()->Check(checker); 11553af6ab5fSopenharmony_ci} 11563af6ab5fSopenharmony_ci 11573af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check(ir::ForUpdateStatement *st) const 11583af6ab5fSopenharmony_ci{ 11593af6ab5fSopenharmony_ci TSChecker *checker = GetTSChecker(); 11603af6ab5fSopenharmony_ci checker::ScopeContext scopeCtx(checker, st->Scope()); 11613af6ab5fSopenharmony_ci 11623af6ab5fSopenharmony_ci if (st->Init() != nullptr) { 11633af6ab5fSopenharmony_ci st->Init()->Check(checker); 11643af6ab5fSopenharmony_ci } 11653af6ab5fSopenharmony_ci 11663af6ab5fSopenharmony_ci if (st->Test() != nullptr) { 11673af6ab5fSopenharmony_ci checker::Type *testType = st->Test()->Check(checker); 11683af6ab5fSopenharmony_ci checker->CheckTruthinessOfType(testType, st->Start()); 11693af6ab5fSopenharmony_ci } 11703af6ab5fSopenharmony_ci 11713af6ab5fSopenharmony_ci if (st->Update() != nullptr) { 11723af6ab5fSopenharmony_ci st->Update()->Check(checker); 11733af6ab5fSopenharmony_ci } 11743af6ab5fSopenharmony_ci 11753af6ab5fSopenharmony_ci st->Body()->Check(checker); 11763af6ab5fSopenharmony_ci 11773af6ab5fSopenharmony_ci return nullptr; 11783af6ab5fSopenharmony_ci} 11793af6ab5fSopenharmony_ci 11803af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check(ir::FunctionDeclaration *st) const 11813af6ab5fSopenharmony_ci{ 11823af6ab5fSopenharmony_ci TSChecker *checker = GetTSChecker(); 11833af6ab5fSopenharmony_ci if (st->Function()->IsOverload()) { 11843af6ab5fSopenharmony_ci return nullptr; 11853af6ab5fSopenharmony_ci } 11863af6ab5fSopenharmony_ci 11873af6ab5fSopenharmony_ci const util::StringView &funcName = st->Function()->Id()->Name(); 11883af6ab5fSopenharmony_ci auto result = checker->Scope()->Find(funcName); 11893af6ab5fSopenharmony_ci ASSERT(result.variable); 11903af6ab5fSopenharmony_ci 11913af6ab5fSopenharmony_ci checker::ScopeContext scopeCtx(checker, st->Function()->Scope()); 11923af6ab5fSopenharmony_ci 11933af6ab5fSopenharmony_ci if (result.variable->TsType() == nullptr) { 11943af6ab5fSopenharmony_ci checker->InferFunctionDeclarationType(result.variable->Declaration()->AsFunctionDecl(), result.variable); 11953af6ab5fSopenharmony_ci } 11963af6ab5fSopenharmony_ci 11973af6ab5fSopenharmony_ci st->Function()->Body()->Check(checker); 11983af6ab5fSopenharmony_ci 11993af6ab5fSopenharmony_ci return nullptr; 12003af6ab5fSopenharmony_ci} 12013af6ab5fSopenharmony_ci 12023af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check(ir::IfStatement *st) const 12033af6ab5fSopenharmony_ci{ 12043af6ab5fSopenharmony_ci TSChecker *checker = GetTSChecker(); 12053af6ab5fSopenharmony_ci checker::Type *testType = st->Test()->Check(checker); 12063af6ab5fSopenharmony_ci checker->CheckTruthinessOfType(testType, st->Start()); 12073af6ab5fSopenharmony_ci checker->CheckTestingKnownTruthyCallableOrAwaitableType(st->Test(), testType, st->Consequent()); 12083af6ab5fSopenharmony_ci 12093af6ab5fSopenharmony_ci st->Consequent()->Check(checker); 12103af6ab5fSopenharmony_ci 12113af6ab5fSopenharmony_ci if (st->Alternate() != nullptr) { 12123af6ab5fSopenharmony_ci st->Alternate()->Check(checker); 12133af6ab5fSopenharmony_ci } 12143af6ab5fSopenharmony_ci 12153af6ab5fSopenharmony_ci return nullptr; 12163af6ab5fSopenharmony_ci} 12173af6ab5fSopenharmony_ci 12183af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check(ir::ReturnStatement *st) const 12193af6ab5fSopenharmony_ci{ 12203af6ab5fSopenharmony_ci TSChecker *checker = GetTSChecker(); 12213af6ab5fSopenharmony_ci ir::AstNode *ancestor = util::Helpers::FindAncestorGivenByType(st, ir::AstNodeType::SCRIPT_FUNCTION); 12223af6ab5fSopenharmony_ci ASSERT(ancestor && ancestor->IsScriptFunction()); 12233af6ab5fSopenharmony_ci auto *containingFunc = ancestor->AsScriptFunction(); 12243af6ab5fSopenharmony_ci 12253af6ab5fSopenharmony_ci if (containingFunc->Parent()->Parent()->IsMethodDefinition()) { 12263af6ab5fSopenharmony_ci const ir::MethodDefinition *containingClassMethod = containingFunc->Parent()->Parent()->AsMethodDefinition(); 12273af6ab5fSopenharmony_ci if (containingClassMethod->Kind() == ir::MethodDefinitionKind::SET) { 12283af6ab5fSopenharmony_ci checker->ThrowTypeError("Setters cannot return a value", st->Start()); 12293af6ab5fSopenharmony_ci } 12303af6ab5fSopenharmony_ci } 12313af6ab5fSopenharmony_ci 12323af6ab5fSopenharmony_ci if (containingFunc->ReturnTypeAnnotation() != nullptr) { 12333af6ab5fSopenharmony_ci checker::Type *returnType = checker->GlobalUndefinedType(); 12343af6ab5fSopenharmony_ci checker::Type *funcReturnType = containingFunc->ReturnTypeAnnotation()->GetType(checker); 12353af6ab5fSopenharmony_ci 12363af6ab5fSopenharmony_ci if (st->Argument() != nullptr) { 12373af6ab5fSopenharmony_ci checker->ElaborateElementwise(funcReturnType, st->Argument(), st->Start()); 12383af6ab5fSopenharmony_ci returnType = checker->CheckTypeCached(st->Argument()); 12393af6ab5fSopenharmony_ci } 12403af6ab5fSopenharmony_ci 12413af6ab5fSopenharmony_ci checker->IsTypeAssignableTo(returnType, funcReturnType, 12423af6ab5fSopenharmony_ci {"Type '", returnType, "' is not assignable to type '", funcReturnType, "'."}, 12433af6ab5fSopenharmony_ci st->Start()); 12443af6ab5fSopenharmony_ci } 12453af6ab5fSopenharmony_ci 12463af6ab5fSopenharmony_ci return nullptr; 12473af6ab5fSopenharmony_ci} 12483af6ab5fSopenharmony_ci 12493af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check(ir::SwitchStatement *st) const 12503af6ab5fSopenharmony_ci{ 12513af6ab5fSopenharmony_ci TSChecker *checker = GetTSChecker(); 12523af6ab5fSopenharmony_ci checker::ScopeContext scopeCtx(checker, st->Scope()); 12533af6ab5fSopenharmony_ci 12543af6ab5fSopenharmony_ci checker::Type *exprType = st->Discriminant()->Check(checker); 12553af6ab5fSopenharmony_ci bool exprIsLiteral = checker::TSChecker::IsLiteralType(exprType); 12563af6ab5fSopenharmony_ci 12573af6ab5fSopenharmony_ci for (auto *it : st->Cases()) { 12583af6ab5fSopenharmony_ci if (it->Test() != nullptr) { 12593af6ab5fSopenharmony_ci checker::Type *caseType = it->Test()->Check(checker); 12603af6ab5fSopenharmony_ci bool caseIsLiteral = checker::TSChecker::IsLiteralType(caseType); 12613af6ab5fSopenharmony_ci checker::Type *comparedExprType = exprType; 12623af6ab5fSopenharmony_ci 12633af6ab5fSopenharmony_ci if (!caseIsLiteral || !exprIsLiteral) { 12643af6ab5fSopenharmony_ci caseType = caseIsLiteral ? checker->GetBaseTypeOfLiteralType(caseType) : caseType; 12653af6ab5fSopenharmony_ci comparedExprType = checker->GetBaseTypeOfLiteralType(exprType); 12663af6ab5fSopenharmony_ci } 12673af6ab5fSopenharmony_ci 12683af6ab5fSopenharmony_ci if (!checker->IsTypeEqualityComparableTo(comparedExprType, caseType) && 12693af6ab5fSopenharmony_ci !checker->IsTypeComparableTo(caseType, comparedExprType)) { 12703af6ab5fSopenharmony_ci checker->ThrowTypeError({"Type ", caseType, " is not comparable to type ", comparedExprType}, 12713af6ab5fSopenharmony_ci it->Test()->Start()); 12723af6ab5fSopenharmony_ci } 12733af6ab5fSopenharmony_ci } 12743af6ab5fSopenharmony_ci 12753af6ab5fSopenharmony_ci for (auto *caseStmt : it->Consequent()) { 12763af6ab5fSopenharmony_ci caseStmt->Check(checker); 12773af6ab5fSopenharmony_ci } 12783af6ab5fSopenharmony_ci } 12793af6ab5fSopenharmony_ci 12803af6ab5fSopenharmony_ci return nullptr; 12813af6ab5fSopenharmony_ci} 12823af6ab5fSopenharmony_ci 12833af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check(ir::TryStatement *st) const 12843af6ab5fSopenharmony_ci{ 12853af6ab5fSopenharmony_ci TSChecker *checker = GetTSChecker(); 12863af6ab5fSopenharmony_ci st->Block()->Check(checker); 12873af6ab5fSopenharmony_ci 12883af6ab5fSopenharmony_ci for (auto *catchClause : st->CatchClauses()) { 12893af6ab5fSopenharmony_ci if (catchClause != nullptr) { 12903af6ab5fSopenharmony_ci catchClause->Check(checker); 12913af6ab5fSopenharmony_ci } 12923af6ab5fSopenharmony_ci } 12933af6ab5fSopenharmony_ci 12943af6ab5fSopenharmony_ci if (st->HasFinalizer()) { 12953af6ab5fSopenharmony_ci st->finalizer_->Check(checker); 12963af6ab5fSopenharmony_ci } 12973af6ab5fSopenharmony_ci 12983af6ab5fSopenharmony_ci return nullptr; 12993af6ab5fSopenharmony_ci} 13003af6ab5fSopenharmony_ci 13013af6ab5fSopenharmony_cistatic void CheckSimpleVariableDeclaration(checker::TSChecker *checker, ir::VariableDeclarator *declarator) 13023af6ab5fSopenharmony_ci{ 13033af6ab5fSopenharmony_ci varbinder::Variable *const bindingVar = declarator->Id()->AsIdentifier()->Variable(); 13043af6ab5fSopenharmony_ci checker::Type *previousType = bindingVar->TsType(); 13053af6ab5fSopenharmony_ci auto *const typeAnnotation = declarator->Id()->AsIdentifier()->TypeAnnotation(); 13063af6ab5fSopenharmony_ci auto *const initializer = declarator->Init(); 13073af6ab5fSopenharmony_ci const bool isConst = declarator->Parent()->AsVariableDeclaration()->Kind() == 13083af6ab5fSopenharmony_ci ir::VariableDeclaration::VariableDeclarationKind::CONST; 13093af6ab5fSopenharmony_ci 13103af6ab5fSopenharmony_ci if (isConst) { 13113af6ab5fSopenharmony_ci checker->AddStatus(checker::CheckerStatus::IN_CONST_CONTEXT); 13123af6ab5fSopenharmony_ci } 13133af6ab5fSopenharmony_ci 13143af6ab5fSopenharmony_ci if (typeAnnotation != nullptr) { 13153af6ab5fSopenharmony_ci typeAnnotation->Check(checker); 13163af6ab5fSopenharmony_ci } 13173af6ab5fSopenharmony_ci 13183af6ab5fSopenharmony_ci if (typeAnnotation != nullptr && initializer != nullptr) { 13193af6ab5fSopenharmony_ci checker::Type *const annotationType = typeAnnotation->GetType(checker); 13203af6ab5fSopenharmony_ci checker->ElaborateElementwise(annotationType, initializer, declarator->Id()->Start()); 13213af6ab5fSopenharmony_ci bindingVar->SetTsType(annotationType); 13223af6ab5fSopenharmony_ci } else if (typeAnnotation != nullptr) { 13233af6ab5fSopenharmony_ci bindingVar->SetTsType(typeAnnotation->GetType(checker)); 13243af6ab5fSopenharmony_ci } else if (initializer != nullptr) { 13253af6ab5fSopenharmony_ci checker::Type *initializerType = checker->CheckTypeCached(initializer); 13263af6ab5fSopenharmony_ci 13273af6ab5fSopenharmony_ci if (!isConst) { 13283af6ab5fSopenharmony_ci initializerType = checker->GetBaseTypeOfLiteralType(initializerType); 13293af6ab5fSopenharmony_ci } 13303af6ab5fSopenharmony_ci 13313af6ab5fSopenharmony_ci if (initializerType->IsNullType()) { 13323af6ab5fSopenharmony_ci checker->ThrowTypeError( 13333af6ab5fSopenharmony_ci {"Cannot infer type for variable '", declarator->Id()->AsIdentifier()->Name(), "'."}, 13343af6ab5fSopenharmony_ci declarator->Id()->Start()); 13353af6ab5fSopenharmony_ci } 13363af6ab5fSopenharmony_ci 13373af6ab5fSopenharmony_ci bindingVar->SetTsType(initializerType); 13383af6ab5fSopenharmony_ci } else { 13393af6ab5fSopenharmony_ci checker->ThrowTypeError({"Variable ", declarator->Id()->AsIdentifier()->Name(), " implicitly has an any type."}, 13403af6ab5fSopenharmony_ci declarator->Id()->Start()); 13413af6ab5fSopenharmony_ci } 13423af6ab5fSopenharmony_ci 13433af6ab5fSopenharmony_ci if (previousType != nullptr) { 13443af6ab5fSopenharmony_ci checker->IsTypeIdenticalTo(bindingVar->TsType(), previousType, 13453af6ab5fSopenharmony_ci {"Subsequent variable declaration must have the same type. Variable '", 13463af6ab5fSopenharmony_ci bindingVar->Name(), "' must be of type '", previousType, "', but here has type '", 13473af6ab5fSopenharmony_ci bindingVar->TsType(), "'."}, 13483af6ab5fSopenharmony_ci declarator->Id()->Start()); 13493af6ab5fSopenharmony_ci } 13503af6ab5fSopenharmony_ci 13513af6ab5fSopenharmony_ci checker->RemoveStatus(checker::CheckerStatus::IN_CONST_CONTEXT); 13523af6ab5fSopenharmony_ci} 13533af6ab5fSopenharmony_ci 13543af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check(ir::VariableDeclarator *st) const 13553af6ab5fSopenharmony_ci{ 13563af6ab5fSopenharmony_ci TSChecker *checker = GetTSChecker(); 13573af6ab5fSopenharmony_ci 13583af6ab5fSopenharmony_ci if (st->TsType() == st->CHECKED) { 13593af6ab5fSopenharmony_ci return nullptr; 13603af6ab5fSopenharmony_ci } 13613af6ab5fSopenharmony_ci 13623af6ab5fSopenharmony_ci if (st->Id()->IsIdentifier()) { 13633af6ab5fSopenharmony_ci CheckSimpleVariableDeclaration(checker, st); 13643af6ab5fSopenharmony_ci st->SetTsType(st->CHECKED); 13653af6ab5fSopenharmony_ci return nullptr; 13663af6ab5fSopenharmony_ci } 13673af6ab5fSopenharmony_ci 13683af6ab5fSopenharmony_ci if (st->Id()->IsArrayPattern()) { 13693af6ab5fSopenharmony_ci auto context = checker::SavedCheckerContext(checker, checker::CheckerStatus::FORCE_TUPLE); 13703af6ab5fSopenharmony_ci checker::ArrayDestructuringContext({checker, st->Id(), false, 13713af6ab5fSopenharmony_ci st->Id()->AsArrayPattern()->TypeAnnotation() == nullptr, 13723af6ab5fSopenharmony_ci st->Id()->AsArrayPattern()->TypeAnnotation(), st->Init()}) 13733af6ab5fSopenharmony_ci .Start(); 13743af6ab5fSopenharmony_ci 13753af6ab5fSopenharmony_ci st->SetTsType(st->CHECKED); 13763af6ab5fSopenharmony_ci return nullptr; 13773af6ab5fSopenharmony_ci } 13783af6ab5fSopenharmony_ci 13793af6ab5fSopenharmony_ci ASSERT(st->Id()->IsObjectPattern()); 13803af6ab5fSopenharmony_ci auto context = checker::SavedCheckerContext(checker, checker::CheckerStatus::FORCE_TUPLE); 13813af6ab5fSopenharmony_ci checker::ObjectDestructuringContext({checker, st->Id(), false, 13823af6ab5fSopenharmony_ci st->Id()->AsObjectPattern()->TypeAnnotation() == nullptr, 13833af6ab5fSopenharmony_ci st->Id()->AsObjectPattern()->TypeAnnotation(), st->Init()}) 13843af6ab5fSopenharmony_ci .Start(); 13853af6ab5fSopenharmony_ci 13863af6ab5fSopenharmony_ci st->SetTsType(st->CHECKED); 13873af6ab5fSopenharmony_ci return nullptr; 13883af6ab5fSopenharmony_ci} 13893af6ab5fSopenharmony_ci 13903af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check(ir::VariableDeclaration *st) const 13913af6ab5fSopenharmony_ci{ 13923af6ab5fSopenharmony_ci TSChecker *checker = GetTSChecker(); 13933af6ab5fSopenharmony_ci for (auto *it : st->Declarators()) { 13943af6ab5fSopenharmony_ci it->Check(checker); 13953af6ab5fSopenharmony_ci } 13963af6ab5fSopenharmony_ci 13973af6ab5fSopenharmony_ci return nullptr; 13983af6ab5fSopenharmony_ci} 13993af6ab5fSopenharmony_ci 14003af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check(ir::WhileStatement *st) const 14013af6ab5fSopenharmony_ci{ 14023af6ab5fSopenharmony_ci TSChecker *checker = GetTSChecker(); 14033af6ab5fSopenharmony_ci checker::ScopeContext scopeCtx(checker, st->Scope()); 14043af6ab5fSopenharmony_ci 14053af6ab5fSopenharmony_ci checker::Type *testType = st->Test()->Check(checker); 14063af6ab5fSopenharmony_ci checker->CheckTruthinessOfType(testType, st->Test()->Start()); 14073af6ab5fSopenharmony_ci 14083af6ab5fSopenharmony_ci st->Body()->Check(checker); 14093af6ab5fSopenharmony_ci return nullptr; 14103af6ab5fSopenharmony_ci} 14113af6ab5fSopenharmony_ci// from ts folder 14123af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check([[maybe_unused]] ir::TSAnyKeyword *node) const 14133af6ab5fSopenharmony_ci{ 14143af6ab5fSopenharmony_ci return nullptr; 14153af6ab5fSopenharmony_ci} 14163af6ab5fSopenharmony_ci 14173af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check(ir::TSArrayType *node) const 14183af6ab5fSopenharmony_ci{ 14193af6ab5fSopenharmony_ci TSChecker *checker = GetTSChecker(); 14203af6ab5fSopenharmony_ci node->elementType_->Check(checker); 14213af6ab5fSopenharmony_ci return nullptr; 14223af6ab5fSopenharmony_ci} 14233af6ab5fSopenharmony_ci 14243af6ab5fSopenharmony_cistatic bool IsValidConstAssertionArgument(checker::Checker *checker, const ir::AstNode *arg) 14253af6ab5fSopenharmony_ci{ 14263af6ab5fSopenharmony_ci switch (arg->Type()) { 14273af6ab5fSopenharmony_ci case ir::AstNodeType::NUMBER_LITERAL: 14283af6ab5fSopenharmony_ci case ir::AstNodeType::STRING_LITERAL: 14293af6ab5fSopenharmony_ci case ir::AstNodeType::BIGINT_LITERAL: 14303af6ab5fSopenharmony_ci case ir::AstNodeType::BOOLEAN_LITERAL: 14313af6ab5fSopenharmony_ci case ir::AstNodeType::ARRAY_EXPRESSION: 14323af6ab5fSopenharmony_ci case ir::AstNodeType::OBJECT_EXPRESSION: 14333af6ab5fSopenharmony_ci case ir::AstNodeType::TEMPLATE_LITERAL: { 14343af6ab5fSopenharmony_ci return true; 14353af6ab5fSopenharmony_ci } 14363af6ab5fSopenharmony_ci case ir::AstNodeType::UNARY_EXPRESSION: { 14373af6ab5fSopenharmony_ci const ir::UnaryExpression *unaryExpr = arg->AsUnaryExpression(); 14383af6ab5fSopenharmony_ci lexer::TokenType op = unaryExpr->OperatorType(); 14393af6ab5fSopenharmony_ci const ir::Expression *unaryArg = unaryExpr->Argument(); 14403af6ab5fSopenharmony_ci return (op == lexer::TokenType::PUNCTUATOR_MINUS && unaryArg->IsLiteral() && 14413af6ab5fSopenharmony_ci (unaryArg->AsLiteral()->IsNumberLiteral() || unaryArg->AsLiteral()->IsBigIntLiteral())) || 14423af6ab5fSopenharmony_ci (op == lexer::TokenType::PUNCTUATOR_PLUS && unaryArg->IsLiteral() && 14433af6ab5fSopenharmony_ci unaryArg->AsLiteral()->IsNumberLiteral()); 14443af6ab5fSopenharmony_ci } 14453af6ab5fSopenharmony_ci case ir::AstNodeType::MEMBER_EXPRESSION: { 14463af6ab5fSopenharmony_ci const ir::MemberExpression *memberExpr = arg->AsMemberExpression(); 14473af6ab5fSopenharmony_ci if (memberExpr->Object()->IsIdentifier()) { 14483af6ab5fSopenharmony_ci auto result = checker->Scope()->Find(memberExpr->Object()->AsIdentifier()->Name()); 14493af6ab5fSopenharmony_ci constexpr auto ENUM_LITERAL_TYPE = checker::EnumLiteralType::EnumLiteralTypeKind::LITERAL; 14503af6ab5fSopenharmony_ci if (result.variable != nullptr && 14513af6ab5fSopenharmony_ci result.variable->TsType()->HasTypeFlag(checker::TypeFlag::ENUM_LITERAL) && 14523af6ab5fSopenharmony_ci result.variable->TsType()->AsEnumLiteralType()->Kind() == ENUM_LITERAL_TYPE) { 14533af6ab5fSopenharmony_ci return true; 14543af6ab5fSopenharmony_ci } 14553af6ab5fSopenharmony_ci } 14563af6ab5fSopenharmony_ci return false; 14573af6ab5fSopenharmony_ci } 14583af6ab5fSopenharmony_ci default: 14593af6ab5fSopenharmony_ci return false; 14603af6ab5fSopenharmony_ci } 14613af6ab5fSopenharmony_ci} 14623af6ab5fSopenharmony_ci 14633af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check(ir::TSAsExpression *expr) const 14643af6ab5fSopenharmony_ci{ 14653af6ab5fSopenharmony_ci TSChecker *checker = GetTSChecker(); 14663af6ab5fSopenharmony_ci if (expr->IsConst()) { 14673af6ab5fSopenharmony_ci auto context = checker::SavedCheckerContext(checker, checker::CheckerStatus::IN_CONST_CONTEXT); 14683af6ab5fSopenharmony_ci checker::Type *exprType = expr->Expr()->Check(checker); 14693af6ab5fSopenharmony_ci 14703af6ab5fSopenharmony_ci if (!IsValidConstAssertionArgument(checker, expr->Expr())) { 14713af6ab5fSopenharmony_ci checker->ThrowTypeError( 14723af6ab5fSopenharmony_ci "A 'const' assertions can only be applied to references to enum members, or string, number, " 14733af6ab5fSopenharmony_ci "boolean, array, or object literals.", 14743af6ab5fSopenharmony_ci expr->Expr()->Start()); 14753af6ab5fSopenharmony_ci } 14763af6ab5fSopenharmony_ci 14773af6ab5fSopenharmony_ci return exprType; 14783af6ab5fSopenharmony_ci } 14793af6ab5fSopenharmony_ci 14803af6ab5fSopenharmony_ci auto context = checker::SavedCheckerContext(checker, checker::CheckerStatus::NO_OPTS); 14813af6ab5fSopenharmony_ci 14823af6ab5fSopenharmony_ci expr->TypeAnnotation()->Check(checker); 14833af6ab5fSopenharmony_ci checker::Type *exprType = checker->GetBaseTypeOfLiteralType(expr->Expr()->Check(checker)); 14843af6ab5fSopenharmony_ci checker::Type *targetType = expr->TypeAnnotation()->GetType(checker); 14853af6ab5fSopenharmony_ci 14863af6ab5fSopenharmony_ci checker->IsTypeComparableTo( 14873af6ab5fSopenharmony_ci targetType, exprType, 14883af6ab5fSopenharmony_ci {"Conversion of type '", exprType, "' to type '", targetType, 14893af6ab5fSopenharmony_ci "' may be a mistake because neither type sufficiently overlaps with the other. If this was ", 14903af6ab5fSopenharmony_ci "intentional, convert the expression to 'unknown' first."}, 14913af6ab5fSopenharmony_ci expr->Start()); 14923af6ab5fSopenharmony_ci 14933af6ab5fSopenharmony_ci return targetType; 14943af6ab5fSopenharmony_ci} 14953af6ab5fSopenharmony_ci 14963af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check([[maybe_unused]] ir::TSBigintKeyword *node) const 14973af6ab5fSopenharmony_ci{ 14983af6ab5fSopenharmony_ci return nullptr; 14993af6ab5fSopenharmony_ci} 15003af6ab5fSopenharmony_ci 15013af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check([[maybe_unused]] ir::TSBooleanKeyword *node) const 15023af6ab5fSopenharmony_ci{ 15033af6ab5fSopenharmony_ci return nullptr; 15043af6ab5fSopenharmony_ci} 15053af6ab5fSopenharmony_ci 15063af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check(ir::TSConstructorType *node) const 15073af6ab5fSopenharmony_ci{ 15083af6ab5fSopenharmony_ci TSChecker *checker = GetTSChecker(); 15093af6ab5fSopenharmony_ci checker::ScopeContext scopeCtx(checker, node->Scope()); 15103af6ab5fSopenharmony_ci 15113af6ab5fSopenharmony_ci auto *signatureInfo = checker->Allocator()->New<checker::SignatureInfo>(checker->Allocator()); 15123af6ab5fSopenharmony_ci checker->CheckFunctionParameterDeclarations(node->Params(), signatureInfo); 15133af6ab5fSopenharmony_ci node->ReturnType()->Check(checker); 15143af6ab5fSopenharmony_ci auto *constructSignature = 15153af6ab5fSopenharmony_ci checker->Allocator()->New<checker::Signature>(signatureInfo, node->ReturnType()->GetType(checker)); 15163af6ab5fSopenharmony_ci 15173af6ab5fSopenharmony_ci return checker->CreateConstructorTypeWithSignature(constructSignature); 15183af6ab5fSopenharmony_ci} 15193af6ab5fSopenharmony_ci 15203af6ab5fSopenharmony_cistatic varbinder::EnumMemberResult EvaluateIdentifier(checker::TSChecker *checker, varbinder::EnumVariable *enumVar, 15213af6ab5fSopenharmony_ci const ir::Identifier *expr) 15223af6ab5fSopenharmony_ci{ 15233af6ab5fSopenharmony_ci if (expr->Name() == "NaN") { 15243af6ab5fSopenharmony_ci return std::nan(""); 15253af6ab5fSopenharmony_ci } 15263af6ab5fSopenharmony_ci if (expr->Name() == "Infinity") { 15273af6ab5fSopenharmony_ci return std::numeric_limits<double>::infinity(); 15283af6ab5fSopenharmony_ci } 15293af6ab5fSopenharmony_ci 15303af6ab5fSopenharmony_ci varbinder::Variable *enumMember = expr->AsIdentifier()->Variable(); 15313af6ab5fSopenharmony_ci 15323af6ab5fSopenharmony_ci if (enumMember == nullptr) { 15333af6ab5fSopenharmony_ci checker->ThrowTypeError({"Cannot find name ", expr->AsIdentifier()->Name()}, 15343af6ab5fSopenharmony_ci enumVar->Declaration()->Node()->Start()); 15353af6ab5fSopenharmony_ci } 15363af6ab5fSopenharmony_ci 15373af6ab5fSopenharmony_ci if (enumMember->IsEnumVariable()) { 15383af6ab5fSopenharmony_ci varbinder::EnumVariable *exprEnumVar = enumMember->AsEnumVariable(); 15393af6ab5fSopenharmony_ci if (std::holds_alternative<bool>(exprEnumVar->Value())) { 15403af6ab5fSopenharmony_ci checker->ThrowTypeError( 15413af6ab5fSopenharmony_ci "A member initializer in a enum declaration cannot reference members declared after it, " 15423af6ab5fSopenharmony_ci "including " 15433af6ab5fSopenharmony_ci "members defined in other enums.", 15443af6ab5fSopenharmony_ci enumVar->Declaration()->Node()->Start()); 15453af6ab5fSopenharmony_ci } 15463af6ab5fSopenharmony_ci 15473af6ab5fSopenharmony_ci return exprEnumVar->Value(); 15483af6ab5fSopenharmony_ci } 15493af6ab5fSopenharmony_ci 15503af6ab5fSopenharmony_ci return false; 15513af6ab5fSopenharmony_ci} 15523af6ab5fSopenharmony_ci 15533af6ab5fSopenharmony_cistatic int32_t ToInt(double num) 15543af6ab5fSopenharmony_ci{ 15553af6ab5fSopenharmony_ci if (num >= std::numeric_limits<int32_t>::min() && num <= std::numeric_limits<int32_t>::max()) { 15563af6ab5fSopenharmony_ci return static_cast<int32_t>(num); 15573af6ab5fSopenharmony_ci } 15583af6ab5fSopenharmony_ci 15593af6ab5fSopenharmony_ci // NOTE (aszilagyi): Perform ECMA defined toInt conversion 15603af6ab5fSopenharmony_ci 15613af6ab5fSopenharmony_ci return 0; 15623af6ab5fSopenharmony_ci} 15633af6ab5fSopenharmony_ci 15643af6ab5fSopenharmony_cistatic uint32_t ToUInt(double num) 15653af6ab5fSopenharmony_ci{ 15663af6ab5fSopenharmony_ci if (num >= std::numeric_limits<uint32_t>::min() && num <= std::numeric_limits<uint32_t>::max()) { 15673af6ab5fSopenharmony_ci return static_cast<int32_t>(num); 15683af6ab5fSopenharmony_ci } 15693af6ab5fSopenharmony_ci 15703af6ab5fSopenharmony_ci // NOTE (aszilagyi): Perform ECMA defined toInt conversion 15713af6ab5fSopenharmony_ci 15723af6ab5fSopenharmony_ci return 0; 15733af6ab5fSopenharmony_ci} 15743af6ab5fSopenharmony_ci 15753af6ab5fSopenharmony_civarbinder::EnumMemberResult GetOperationResulForDouble(lexer::TokenType type, varbinder::EnumMemberResult left, 15763af6ab5fSopenharmony_ci varbinder::EnumMemberResult right) 15773af6ab5fSopenharmony_ci{ 15783af6ab5fSopenharmony_ci switch (type) { 15793af6ab5fSopenharmony_ci case lexer::TokenType::PUNCTUATOR_BITWISE_OR: { 15803af6ab5fSopenharmony_ci return static_cast<double>(ToUInt(std::get<double>(left)) | ToUInt(std::get<double>(right))); 15813af6ab5fSopenharmony_ci } 15823af6ab5fSopenharmony_ci case lexer::TokenType::PUNCTUATOR_BITWISE_AND: { 15833af6ab5fSopenharmony_ci return static_cast<double>(ToUInt(std::get<double>(left)) & ToUInt(std::get<double>(right))); 15843af6ab5fSopenharmony_ci } 15853af6ab5fSopenharmony_ci case lexer::TokenType::PUNCTUATOR_BITWISE_XOR: { 15863af6ab5fSopenharmony_ci return static_cast<double>(ToUInt(std::get<double>(left)) ^ ToUInt(std::get<double>(right))); 15873af6ab5fSopenharmony_ci } 15883af6ab5fSopenharmony_ci case lexer::TokenType::PUNCTUATOR_LEFT_SHIFT: { // NOLINTNEXTLINE(hicpp-signed-bitwise) 15893af6ab5fSopenharmony_ci return static_cast<double>(ToInt(std::get<double>(left)) << ToUInt(std::get<double>(right))); 15903af6ab5fSopenharmony_ci } 15913af6ab5fSopenharmony_ci case lexer::TokenType::PUNCTUATOR_RIGHT_SHIFT: { // NOLINTNEXTLINE(hicpp-signed-bitwise) 15923af6ab5fSopenharmony_ci return static_cast<double>(ToInt(std::get<double>(left)) >> ToUInt(std::get<double>(right))); 15933af6ab5fSopenharmony_ci } 15943af6ab5fSopenharmony_ci case lexer::TokenType::PUNCTUATOR_UNSIGNED_RIGHT_SHIFT: { 15953af6ab5fSopenharmony_ci return static_cast<double>(ToUInt(std::get<double>(left)) >> ToUInt(std::get<double>(right))); 15963af6ab5fSopenharmony_ci } 15973af6ab5fSopenharmony_ci case lexer::TokenType::PUNCTUATOR_PLUS: { 15983af6ab5fSopenharmony_ci return std::get<double>(left) + std::get<double>(right); 15993af6ab5fSopenharmony_ci } 16003af6ab5fSopenharmony_ci case lexer::TokenType::PUNCTUATOR_MINUS: { 16013af6ab5fSopenharmony_ci return std::get<double>(left) - std::get<double>(right); 16023af6ab5fSopenharmony_ci } 16033af6ab5fSopenharmony_ci case lexer::TokenType::PUNCTUATOR_MULTIPLY: { 16043af6ab5fSopenharmony_ci return std::get<double>(left) * std::get<double>(right); 16053af6ab5fSopenharmony_ci } 16063af6ab5fSopenharmony_ci case lexer::TokenType::PUNCTUATOR_DIVIDE: { 16073af6ab5fSopenharmony_ci return std::get<double>(left) / std::get<double>(right); 16083af6ab5fSopenharmony_ci } 16093af6ab5fSopenharmony_ci case lexer::TokenType::PUNCTUATOR_MOD: { 16103af6ab5fSopenharmony_ci return std::fmod(std::get<double>(left), std::get<double>(right)); 16113af6ab5fSopenharmony_ci } 16123af6ab5fSopenharmony_ci case lexer::TokenType::PUNCTUATOR_EXPONENTIATION: { 16133af6ab5fSopenharmony_ci return std::pow(std::get<double>(left), std::get<double>(right)); 16143af6ab5fSopenharmony_ci } 16153af6ab5fSopenharmony_ci default: { 16163af6ab5fSopenharmony_ci return false; 16173af6ab5fSopenharmony_ci } 16183af6ab5fSopenharmony_ci } 16193af6ab5fSopenharmony_ci} 16203af6ab5fSopenharmony_ci 16213af6ab5fSopenharmony_civarbinder::EnumMemberResult TSAnalyzer::EvaluateBinaryExpression(checker::TSChecker *checker, 16223af6ab5fSopenharmony_ci varbinder::EnumVariable *enumVar, 16233af6ab5fSopenharmony_ci const ir::BinaryExpression *expr) const 16243af6ab5fSopenharmony_ci{ 16253af6ab5fSopenharmony_ci varbinder::EnumMemberResult left = EvaluateEnumMember(checker, enumVar, expr->AsBinaryExpression()->Left()); 16263af6ab5fSopenharmony_ci varbinder::EnumMemberResult right = EvaluateEnumMember(checker, enumVar, expr->AsBinaryExpression()->Right()); 16273af6ab5fSopenharmony_ci if (std::holds_alternative<double>(left) && std::holds_alternative<double>(right)) { 16283af6ab5fSopenharmony_ci GetOperationResulForDouble(expr->AsBinaryExpression()->OperatorType(), left, right); 16293af6ab5fSopenharmony_ci } 16303af6ab5fSopenharmony_ci 16313af6ab5fSopenharmony_ci if (std::holds_alternative<util::StringView>(left) && std::holds_alternative<util::StringView>(right) && 16323af6ab5fSopenharmony_ci expr->AsBinaryExpression()->OperatorType() == lexer::TokenType::PUNCTUATOR_PLUS) { 16333af6ab5fSopenharmony_ci std::stringstream ss; 16343af6ab5fSopenharmony_ci ss << std::get<util::StringView>(left) << std::get<util::StringView>(right); 16353af6ab5fSopenharmony_ci 16363af6ab5fSopenharmony_ci util::UString res(ss.str(), checker->Allocator()); 16373af6ab5fSopenharmony_ci return res.View(); 16383af6ab5fSopenharmony_ci } 16393af6ab5fSopenharmony_ci 16403af6ab5fSopenharmony_ci return false; 16413af6ab5fSopenharmony_ci} 16423af6ab5fSopenharmony_ci 16433af6ab5fSopenharmony_civarbinder::EnumMemberResult TSAnalyzer::EvaluateUnaryExpression(checker::TSChecker *checker, 16443af6ab5fSopenharmony_ci varbinder::EnumVariable *enumVar, 16453af6ab5fSopenharmony_ci const ir::UnaryExpression *expr) const 16463af6ab5fSopenharmony_ci{ 16473af6ab5fSopenharmony_ci varbinder::EnumMemberResult value = EvaluateEnumMember(checker, enumVar, expr->Argument()); 16483af6ab5fSopenharmony_ci if (!std::holds_alternative<double>(value)) { 16493af6ab5fSopenharmony_ci return false; 16503af6ab5fSopenharmony_ci } 16513af6ab5fSopenharmony_ci 16523af6ab5fSopenharmony_ci switch (expr->OperatorType()) { 16533af6ab5fSopenharmony_ci case lexer::TokenType::PUNCTUATOR_PLUS: { 16543af6ab5fSopenharmony_ci return std::get<double>(value); 16553af6ab5fSopenharmony_ci } 16563af6ab5fSopenharmony_ci case lexer::TokenType::PUNCTUATOR_MINUS: { 16573af6ab5fSopenharmony_ci return -std::get<double>(value); 16583af6ab5fSopenharmony_ci } 16593af6ab5fSopenharmony_ci case lexer::TokenType::PUNCTUATOR_TILDE: { 16603af6ab5fSopenharmony_ci return static_cast<double>(~ToInt(std::get<double>(value))); // NOLINT(hicpp-signed-bitwise) 16613af6ab5fSopenharmony_ci } 16623af6ab5fSopenharmony_ci default: { 16633af6ab5fSopenharmony_ci break; 16643af6ab5fSopenharmony_ci } 16653af6ab5fSopenharmony_ci } 16663af6ab5fSopenharmony_ci 16673af6ab5fSopenharmony_ci return false; 16683af6ab5fSopenharmony_ci} 16693af6ab5fSopenharmony_ci 16703af6ab5fSopenharmony_civarbinder::EnumMemberResult TSAnalyzer::EvaluateEnumMember(checker::TSChecker *checker, 16713af6ab5fSopenharmony_ci varbinder::EnumVariable *enumVar, 16723af6ab5fSopenharmony_ci const ir::AstNode *expr) const 16733af6ab5fSopenharmony_ci{ 16743af6ab5fSopenharmony_ci switch (expr->Type()) { 16753af6ab5fSopenharmony_ci case ir::AstNodeType::UNARY_EXPRESSION: { 16763af6ab5fSopenharmony_ci return EvaluateUnaryExpression(checker, enumVar, expr->AsUnaryExpression()); 16773af6ab5fSopenharmony_ci } 16783af6ab5fSopenharmony_ci case ir::AstNodeType::BINARY_EXPRESSION: { 16793af6ab5fSopenharmony_ci return EvaluateBinaryExpression(checker, enumVar, expr->AsBinaryExpression()); 16803af6ab5fSopenharmony_ci } 16813af6ab5fSopenharmony_ci case ir::AstNodeType::NUMBER_LITERAL: { 16823af6ab5fSopenharmony_ci return expr->AsNumberLiteral()->Number().GetDouble(); 16833af6ab5fSopenharmony_ci } 16843af6ab5fSopenharmony_ci case ir::AstNodeType::STRING_LITERAL: { 16853af6ab5fSopenharmony_ci return expr->AsStringLiteral()->Str(); 16863af6ab5fSopenharmony_ci } 16873af6ab5fSopenharmony_ci case ir::AstNodeType::IDENTIFIER: { 16883af6ab5fSopenharmony_ci return EvaluateIdentifier(checker, enumVar, expr->AsIdentifier()); 16893af6ab5fSopenharmony_ci } 16903af6ab5fSopenharmony_ci case ir::AstNodeType::MEMBER_EXPRESSION: { 16913af6ab5fSopenharmony_ci return EvaluateEnumMember(checker, enumVar, expr->AsMemberExpression()); 16923af6ab5fSopenharmony_ci } 16933af6ab5fSopenharmony_ci default: 16943af6ab5fSopenharmony_ci break; 16953af6ab5fSopenharmony_ci } 16963af6ab5fSopenharmony_ci 16973af6ab5fSopenharmony_ci return false; 16983af6ab5fSopenharmony_ci} 16993af6ab5fSopenharmony_ci 17003af6ab5fSopenharmony_cistatic bool IsComputedEnumMember(const ir::Expression *init) 17013af6ab5fSopenharmony_ci{ 17023af6ab5fSopenharmony_ci if (init->IsLiteral()) { 17033af6ab5fSopenharmony_ci return !init->AsLiteral()->IsStringLiteral() && !init->AsLiteral()->IsNumberLiteral(); 17043af6ab5fSopenharmony_ci } 17053af6ab5fSopenharmony_ci 17063af6ab5fSopenharmony_ci if (init->IsTemplateLiteral()) { 17073af6ab5fSopenharmony_ci return !init->AsTemplateLiteral()->Quasis().empty(); 17083af6ab5fSopenharmony_ci } 17093af6ab5fSopenharmony_ci 17103af6ab5fSopenharmony_ci return true; 17113af6ab5fSopenharmony_ci} 17123af6ab5fSopenharmony_ci 17133af6ab5fSopenharmony_cistatic void AddEnumValueDeclaration(checker::TSChecker *checker, double number, varbinder::EnumVariable *variable) 17143af6ab5fSopenharmony_ci{ 17153af6ab5fSopenharmony_ci variable->SetTsType(checker->GlobalNumberType()); 17163af6ab5fSopenharmony_ci 17173af6ab5fSopenharmony_ci util::StringView memberStr = util::Helpers::ToStringView(checker->Allocator(), number); 17183af6ab5fSopenharmony_ci 17193af6ab5fSopenharmony_ci varbinder::LocalScope *enumScope = checker->Scope()->AsLocalScope(); 17203af6ab5fSopenharmony_ci varbinder::Variable *res = enumScope->FindLocal(memberStr, varbinder::ResolveBindingOptions::BINDINGS); 17213af6ab5fSopenharmony_ci varbinder::EnumVariable *enumVar = nullptr; 17223af6ab5fSopenharmony_ci 17233af6ab5fSopenharmony_ci if (res == nullptr) { 17243af6ab5fSopenharmony_ci auto *decl = checker->Allocator()->New<varbinder::EnumDecl>(memberStr); 17253af6ab5fSopenharmony_ci decl->BindNode(variable->Declaration()->Node()); 17263af6ab5fSopenharmony_ci enumScope->AddDecl(checker->Allocator(), decl, ScriptExtension::TS); 17273af6ab5fSopenharmony_ci res = enumScope->FindLocal(memberStr, varbinder::ResolveBindingOptions::BINDINGS); 17283af6ab5fSopenharmony_ci ASSERT(res && res->IsEnumVariable()); 17293af6ab5fSopenharmony_ci enumVar = res->AsEnumVariable(); 17303af6ab5fSopenharmony_ci enumVar->AsEnumVariable()->SetBackReference(); 17313af6ab5fSopenharmony_ci enumVar->SetTsType(checker->GlobalStringType()); 17323af6ab5fSopenharmony_ci } else { 17333af6ab5fSopenharmony_ci ASSERT(res->IsEnumVariable()); 17343af6ab5fSopenharmony_ci enumVar = res->AsEnumVariable(); 17353af6ab5fSopenharmony_ci auto *decl = checker->Allocator()->New<varbinder::EnumDecl>(memberStr); 17363af6ab5fSopenharmony_ci decl->BindNode(variable->Declaration()->Node()); 17373af6ab5fSopenharmony_ci enumVar->ResetDecl(decl); 17383af6ab5fSopenharmony_ci } 17393af6ab5fSopenharmony_ci 17403af6ab5fSopenharmony_ci enumVar->SetValue(variable->Declaration()->Name()); 17413af6ab5fSopenharmony_ci} 17423af6ab5fSopenharmony_ci 17433af6ab5fSopenharmony_ci// NOLINTBEGIN(modernize-avoid-c-arrays) 17443af6ab5fSopenharmony_cistatic constexpr char const INVALID_COMPUTED_WITH_STRING[] = 17453af6ab5fSopenharmony_ci "Computed values are not permitted in an enum with string valued members."; 17463af6ab5fSopenharmony_cistatic constexpr char const INVALID_CONST_MEMBER[] = 17473af6ab5fSopenharmony_ci "'const' enum member initializers can only contain literal values and other computed enum values."; 17483af6ab5fSopenharmony_cistatic constexpr char const INVALID_CONST_NAN[] = 17493af6ab5fSopenharmony_ci "'const' enum member initializer was evaluated to disallowed value 'NaN'."; 17503af6ab5fSopenharmony_cistatic constexpr char const INVALID_CONST_INF[] = 17513af6ab5fSopenharmony_ci "'const' enum member initializer was evaluated to a non-finite value."; 17523af6ab5fSopenharmony_ci// NOLINTEND(modernize-avoid-c-arrays) 17533af6ab5fSopenharmony_ci 17543af6ab5fSopenharmony_civoid TSAnalyzer::InferEnumVariableType(varbinder::EnumVariable *variable, double *value, bool *initNext, 17553af6ab5fSopenharmony_ci bool *isLiteralEnum, bool isConstEnum) const 17563af6ab5fSopenharmony_ci{ 17573af6ab5fSopenharmony_ci TSChecker *checker = GetTSChecker(); 17583af6ab5fSopenharmony_ci const ir::Expression *init = variable->Declaration()->Node()->AsTSEnumMember()->Init(); 17593af6ab5fSopenharmony_ci 17603af6ab5fSopenharmony_ci if (init == nullptr && *initNext) { 17613af6ab5fSopenharmony_ci checker->ThrowTypeError("Enum member must have initializer.", variable->Declaration()->Node()->Start()); 17623af6ab5fSopenharmony_ci } 17633af6ab5fSopenharmony_ci 17643af6ab5fSopenharmony_ci if (init == nullptr && !*initNext) { 17653af6ab5fSopenharmony_ci variable->SetValue(++(*value)); 17663af6ab5fSopenharmony_ci AddEnumValueDeclaration(checker, *value, variable); 17673af6ab5fSopenharmony_ci return; 17683af6ab5fSopenharmony_ci } 17693af6ab5fSopenharmony_ci 17703af6ab5fSopenharmony_ci ASSERT(init); 17713af6ab5fSopenharmony_ci if (IsComputedEnumMember(init) && *isLiteralEnum) { 17723af6ab5fSopenharmony_ci checker->ThrowTypeError(INVALID_COMPUTED_WITH_STRING, init->Start()); 17733af6ab5fSopenharmony_ci } 17743af6ab5fSopenharmony_ci 17753af6ab5fSopenharmony_ci varbinder::EnumMemberResult res = EvaluateEnumMember(checker, variable, init); 17763af6ab5fSopenharmony_ci if (std::holds_alternative<util::StringView>(res)) { 17773af6ab5fSopenharmony_ci *isLiteralEnum = true; 17783af6ab5fSopenharmony_ci variable->SetTsType(checker->GlobalStringType()); 17793af6ab5fSopenharmony_ci *initNext = true; 17803af6ab5fSopenharmony_ci return; 17813af6ab5fSopenharmony_ci } 17823af6ab5fSopenharmony_ci 17833af6ab5fSopenharmony_ci if (std::holds_alternative<bool>(res)) { 17843af6ab5fSopenharmony_ci if (isConstEnum) { 17853af6ab5fSopenharmony_ci checker->ThrowTypeError(INVALID_CONST_MEMBER, init->Start()); 17863af6ab5fSopenharmony_ci } 17873af6ab5fSopenharmony_ci 17883af6ab5fSopenharmony_ci *initNext = true; 17893af6ab5fSopenharmony_ci return; 17903af6ab5fSopenharmony_ci } 17913af6ab5fSopenharmony_ci 17923af6ab5fSopenharmony_ci ASSERT(std::holds_alternative<double>(res)); 17933af6ab5fSopenharmony_ci variable->SetValue(res); 17943af6ab5fSopenharmony_ci 17953af6ab5fSopenharmony_ci *value = std::get<double>(res); 17963af6ab5fSopenharmony_ci if (isConstEnum && std::isnan(*value)) { 17973af6ab5fSopenharmony_ci checker->ThrowTypeError(INVALID_CONST_NAN, init->Start()); 17983af6ab5fSopenharmony_ci } 17993af6ab5fSopenharmony_ci 18003af6ab5fSopenharmony_ci if (isConstEnum && std::isinf(*value)) { 18013af6ab5fSopenharmony_ci checker->ThrowTypeError(INVALID_CONST_INF, init->Start()); 18023af6ab5fSopenharmony_ci } 18033af6ab5fSopenharmony_ci 18043af6ab5fSopenharmony_ci *initNext = false; 18053af6ab5fSopenharmony_ci AddEnumValueDeclaration(checker, *value, variable); 18063af6ab5fSopenharmony_ci} 18073af6ab5fSopenharmony_ci 18083af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::InferType(checker::TSChecker *checker, bool isConst, ir::TSEnumDeclaration *st) const 18093af6ab5fSopenharmony_ci{ 18103af6ab5fSopenharmony_ci double value = -1.0; 18113af6ab5fSopenharmony_ci 18123af6ab5fSopenharmony_ci varbinder::LocalScope *enumScope = checker->Scope()->AsLocalScope(); 18133af6ab5fSopenharmony_ci 18143af6ab5fSopenharmony_ci bool initNext = false; 18153af6ab5fSopenharmony_ci bool isLiteralEnum = false; 18163af6ab5fSopenharmony_ci size_t localsSize = enumScope->Decls().size(); 18173af6ab5fSopenharmony_ci 18183af6ab5fSopenharmony_ci for (size_t i = 0; i < localsSize; i++) { 18193af6ab5fSopenharmony_ci const util::StringView ¤tName = enumScope->Decls()[i]->Name(); 18203af6ab5fSopenharmony_ci varbinder::Variable *currentVar = enumScope->FindLocal(currentName, varbinder::ResolveBindingOptions::BINDINGS); 18213af6ab5fSopenharmony_ci ASSERT(currentVar && currentVar->IsEnumVariable()); 18223af6ab5fSopenharmony_ci InferEnumVariableType(currentVar->AsEnumVariable(), &value, &initNext, &isLiteralEnum, isConst); 18233af6ab5fSopenharmony_ci } 18243af6ab5fSopenharmony_ci 18253af6ab5fSopenharmony_ci checker::Type *enumType = checker->Allocator()->New<checker::EnumLiteralType>( 18263af6ab5fSopenharmony_ci st->Key()->Name(), checker->Scope(), 18273af6ab5fSopenharmony_ci isLiteralEnum ? checker::EnumLiteralType::EnumLiteralTypeKind::LITERAL 18283af6ab5fSopenharmony_ci : checker::EnumLiteralType::EnumLiteralTypeKind::NUMERIC); 18293af6ab5fSopenharmony_ci 18303af6ab5fSopenharmony_ci return enumType; 18313af6ab5fSopenharmony_ci} 18323af6ab5fSopenharmony_ci 18333af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check(ir::TSEnumDeclaration *st) const 18343af6ab5fSopenharmony_ci{ 18353af6ab5fSopenharmony_ci TSChecker *checker = GetTSChecker(); 18363af6ab5fSopenharmony_ci varbinder::Variable *enumVar = st->Key()->Variable(); 18373af6ab5fSopenharmony_ci ASSERT(enumVar); 18383af6ab5fSopenharmony_ci 18393af6ab5fSopenharmony_ci if (enumVar->TsType() == nullptr) { 18403af6ab5fSopenharmony_ci checker::ScopeContext scopeCtx(checker, st->Scope()); 18413af6ab5fSopenharmony_ci checker::Type *enumType = InferType(checker, st->IsConst(), st); 18423af6ab5fSopenharmony_ci enumType->SetVariable(enumVar); 18433af6ab5fSopenharmony_ci enumVar->SetTsType(enumType); 18443af6ab5fSopenharmony_ci } 18453af6ab5fSopenharmony_ci 18463af6ab5fSopenharmony_ci return nullptr; 18473af6ab5fSopenharmony_ci} 18483af6ab5fSopenharmony_ci 18493af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check(ir::TSFunctionType *node) const 18503af6ab5fSopenharmony_ci{ 18513af6ab5fSopenharmony_ci TSChecker *checker = GetTSChecker(); 18523af6ab5fSopenharmony_ci checker::ScopeContext scopeCtx(checker, node->Scope()); 18533af6ab5fSopenharmony_ci 18543af6ab5fSopenharmony_ci auto *signatureInfo = checker->Allocator()->New<checker::SignatureInfo>(checker->Allocator()); 18553af6ab5fSopenharmony_ci checker->CheckFunctionParameterDeclarations(node->Params(), signatureInfo); 18563af6ab5fSopenharmony_ci node->ReturnType()->Check(checker); 18573af6ab5fSopenharmony_ci auto *callSignature = 18583af6ab5fSopenharmony_ci checker->Allocator()->New<checker::Signature>(signatureInfo, node->ReturnType()->GetType(checker)); 18593af6ab5fSopenharmony_ci 18603af6ab5fSopenharmony_ci return checker->CreateFunctionTypeWithSignature(callSignature); 18613af6ab5fSopenharmony_ci} 18623af6ab5fSopenharmony_ci 18633af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check(ir::TSIndexedAccessType *node) const 18643af6ab5fSopenharmony_ci{ 18653af6ab5fSopenharmony_ci TSChecker *checker = GetTSChecker(); 18663af6ab5fSopenharmony_ci node->objectType_->Check(checker); 18673af6ab5fSopenharmony_ci node->indexType_->Check(checker); 18683af6ab5fSopenharmony_ci checker::Type *resolved = node->GetType(checker); 18693af6ab5fSopenharmony_ci 18703af6ab5fSopenharmony_ci if (resolved != nullptr) { 18713af6ab5fSopenharmony_ci return nullptr; 18723af6ab5fSopenharmony_ci } 18733af6ab5fSopenharmony_ci 18743af6ab5fSopenharmony_ci checker::Type *indexType = checker->CheckTypeCached(node->indexType_); 18753af6ab5fSopenharmony_ci 18763af6ab5fSopenharmony_ci if (!indexType->HasTypeFlag(checker::TypeFlag::STRING_LIKE | checker::TypeFlag::NUMBER_LIKE)) { 18773af6ab5fSopenharmony_ci checker->ThrowTypeError({"Type ", indexType, " cannot be used as index type"}, node->IndexType()->Start()); 18783af6ab5fSopenharmony_ci } 18793af6ab5fSopenharmony_ci 18803af6ab5fSopenharmony_ci if (indexType->IsNumberType()) { 18813af6ab5fSopenharmony_ci checker->ThrowTypeError("Type has no matching signature for type 'number'", node->Start()); 18823af6ab5fSopenharmony_ci } 18833af6ab5fSopenharmony_ci 18843af6ab5fSopenharmony_ci checker->ThrowTypeError("Type has no matching signature for type 'string'", node->Start()); 18853af6ab5fSopenharmony_ci return nullptr; 18863af6ab5fSopenharmony_ci} 18873af6ab5fSopenharmony_ci 18883af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check(ir::TSInterfaceBody *expr) const 18893af6ab5fSopenharmony_ci{ 18903af6ab5fSopenharmony_ci TSChecker *checker = GetTSChecker(); 18913af6ab5fSopenharmony_ci for (auto *it : expr->Body()) { 18923af6ab5fSopenharmony_ci it->Check(checker); 18933af6ab5fSopenharmony_ci } 18943af6ab5fSopenharmony_ci 18953af6ab5fSopenharmony_ci return nullptr; 18963af6ab5fSopenharmony_ci} 18973af6ab5fSopenharmony_ci 18983af6ab5fSopenharmony_cistatic void CheckInheritedPropertiesAreIdentical(checker::TSChecker *checker, checker::InterfaceType *type, 18993af6ab5fSopenharmony_ci const lexer::SourcePosition &locInfo) 19003af6ab5fSopenharmony_ci{ 19013af6ab5fSopenharmony_ci checker->GetBaseTypes(type); 19023af6ab5fSopenharmony_ci 19033af6ab5fSopenharmony_ci size_t constexpr BASE_SIZE_LIMIT = 2; 19043af6ab5fSopenharmony_ci if (type->Bases().size() < BASE_SIZE_LIMIT) { 19053af6ab5fSopenharmony_ci return; 19063af6ab5fSopenharmony_ci } 19073af6ab5fSopenharmony_ci 19083af6ab5fSopenharmony_ci checker->ResolveDeclaredMembers(type); 19093af6ab5fSopenharmony_ci 19103af6ab5fSopenharmony_ci checker::InterfacePropertyMap properties; 19113af6ab5fSopenharmony_ci 19123af6ab5fSopenharmony_ci for (auto *it : type->Properties()) { 19133af6ab5fSopenharmony_ci properties.insert({it->Name(), {it, type}}); 19143af6ab5fSopenharmony_ci } 19153af6ab5fSopenharmony_ci 19163af6ab5fSopenharmony_ci for (auto *base : type->Bases()) { 19173af6ab5fSopenharmony_ci checker->ResolveStructuredTypeMembers(base); 19183af6ab5fSopenharmony_ci ArenaVector<varbinder::LocalVariable *> inheritedProperties(checker->Allocator()->Adapter()); 19193af6ab5fSopenharmony_ci base->AsInterfaceType()->CollectProperties(&inheritedProperties); 19203af6ab5fSopenharmony_ci 19213af6ab5fSopenharmony_ci for (auto *inheritedProp : inheritedProperties) { 19223af6ab5fSopenharmony_ci auto res = properties.find(inheritedProp->Name()); 19233af6ab5fSopenharmony_ci if (res == properties.end()) { 19243af6ab5fSopenharmony_ci properties.insert({inheritedProp->Name(), {inheritedProp, base->AsInterfaceType()}}); 19253af6ab5fSopenharmony_ci } else if (res->second.second != type) { 19263af6ab5fSopenharmony_ci checker::Type *sourceType = checker->GetTypeOfVariable(inheritedProp); 19273af6ab5fSopenharmony_ci checker::Type *targetType = checker->GetTypeOfVariable(res->second.first); 19283af6ab5fSopenharmony_ci checker->IsTypeIdenticalTo(sourceType, targetType, 19293af6ab5fSopenharmony_ci {"Interface '", type, "' cannot simultaneously extend types '", 19303af6ab5fSopenharmony_ci res->second.second, "' and '", base->AsInterfaceType(), "'."}, 19313af6ab5fSopenharmony_ci locInfo); 19323af6ab5fSopenharmony_ci } 19333af6ab5fSopenharmony_ci } 19343af6ab5fSopenharmony_ci } 19353af6ab5fSopenharmony_ci} 19363af6ab5fSopenharmony_ci 19373af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check(ir::TSInterfaceDeclaration *st) const 19383af6ab5fSopenharmony_ci{ 19393af6ab5fSopenharmony_ci TSChecker *checker = GetTSChecker(); 19403af6ab5fSopenharmony_ci varbinder::Variable *var = st->Id()->Variable(); 19413af6ab5fSopenharmony_ci ASSERT(var->Declaration()->Node() && var->Declaration()->Node()->IsTSInterfaceDeclaration()); 19423af6ab5fSopenharmony_ci 19433af6ab5fSopenharmony_ci if (st == var->Declaration()->Node()) { 19443af6ab5fSopenharmony_ci checker::Type *resolvedType = var->TsType(); 19453af6ab5fSopenharmony_ci 19463af6ab5fSopenharmony_ci if (resolvedType == nullptr) { 19473af6ab5fSopenharmony_ci checker::ObjectDescriptor *desc = 19483af6ab5fSopenharmony_ci checker->Allocator()->New<checker::ObjectDescriptor>(checker->Allocator()); 19493af6ab5fSopenharmony_ci resolvedType = 19503af6ab5fSopenharmony_ci checker->Allocator()->New<checker::InterfaceType>(checker->Allocator(), st->Id()->Name(), desc); 19513af6ab5fSopenharmony_ci resolvedType->SetVariable(var); 19523af6ab5fSopenharmony_ci var->SetTsType(resolvedType); 19533af6ab5fSopenharmony_ci } 19543af6ab5fSopenharmony_ci 19553af6ab5fSopenharmony_ci checker::InterfaceType *resolvedInterface = resolvedType->AsObjectType()->AsInterfaceType(); 19563af6ab5fSopenharmony_ci CheckInheritedPropertiesAreIdentical(checker, resolvedInterface, st->Id()->Start()); 19573af6ab5fSopenharmony_ci 19583af6ab5fSopenharmony_ci for (auto *base : resolvedInterface->Bases()) { 19593af6ab5fSopenharmony_ci checker->IsTypeAssignableTo( 19603af6ab5fSopenharmony_ci resolvedInterface, base, 19613af6ab5fSopenharmony_ci {"Interface '", st->Id()->Name(), "' incorrectly extends interface '", base, "'"}, st->Id()->Start()); 19623af6ab5fSopenharmony_ci } 19633af6ab5fSopenharmony_ci 19643af6ab5fSopenharmony_ci checker->CheckIndexConstraints(resolvedInterface); 19653af6ab5fSopenharmony_ci } 19663af6ab5fSopenharmony_ci 19673af6ab5fSopenharmony_ci st->Body()->Check(checker); 19683af6ab5fSopenharmony_ci 19693af6ab5fSopenharmony_ci return nullptr; 19703af6ab5fSopenharmony_ci} 19713af6ab5fSopenharmony_ci 19723af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check(ir::TSLiteralType *node) const 19733af6ab5fSopenharmony_ci{ 19743af6ab5fSopenharmony_ci TSChecker *checker = GetTSChecker(); 19753af6ab5fSopenharmony_ci node->GetType(checker); 19763af6ab5fSopenharmony_ci return nullptr; 19773af6ab5fSopenharmony_ci} 19783af6ab5fSopenharmony_ci 19793af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check(ir::TSNamedTupleMember *node) const 19803af6ab5fSopenharmony_ci{ 19813af6ab5fSopenharmony_ci TSChecker *checker = GetTSChecker(); 19823af6ab5fSopenharmony_ci node->ElementType()->Check(checker); 19833af6ab5fSopenharmony_ci return nullptr; 19843af6ab5fSopenharmony_ci} 19853af6ab5fSopenharmony_ci 19863af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check([[maybe_unused]] ir::TSNeverKeyword *node) const 19873af6ab5fSopenharmony_ci{ 19883af6ab5fSopenharmony_ci return nullptr; 19893af6ab5fSopenharmony_ci} 19903af6ab5fSopenharmony_ci 19913af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check([[maybe_unused]] ir::TSNullKeyword *node) const 19923af6ab5fSopenharmony_ci{ 19933af6ab5fSopenharmony_ci return nullptr; 19943af6ab5fSopenharmony_ci} 19953af6ab5fSopenharmony_ci 19963af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check([[maybe_unused]] ir::TSNumberKeyword *node) const 19973af6ab5fSopenharmony_ci{ 19983af6ab5fSopenharmony_ci return nullptr; 19993af6ab5fSopenharmony_ci} 20003af6ab5fSopenharmony_ci 20013af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check(ir::TSParenthesizedType *node) const 20023af6ab5fSopenharmony_ci{ 20033af6ab5fSopenharmony_ci TSChecker *checker = GetTSChecker(); 20043af6ab5fSopenharmony_ci node->type_->Check(checker); 20053af6ab5fSopenharmony_ci return nullptr; 20063af6ab5fSopenharmony_ci} 20073af6ab5fSopenharmony_ci 20083af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check(ir::TSQualifiedName *expr) const 20093af6ab5fSopenharmony_ci{ 20103af6ab5fSopenharmony_ci TSChecker *checker = GetTSChecker(); 20113af6ab5fSopenharmony_ci checker::Type *baseType = checker->CheckNonNullType(expr->Left()->Check(checker), expr->Left()->Start()); 20123af6ab5fSopenharmony_ci varbinder::Variable *prop = checker->GetPropertyOfType(baseType, expr->Right()->Name()); 20133af6ab5fSopenharmony_ci 20143af6ab5fSopenharmony_ci if (prop != nullptr) { 20153af6ab5fSopenharmony_ci return checker->GetTypeOfVariable(prop); 20163af6ab5fSopenharmony_ci } 20173af6ab5fSopenharmony_ci 20183af6ab5fSopenharmony_ci if (baseType->IsObjectType()) { 20193af6ab5fSopenharmony_ci checker::ObjectType *objType = baseType->AsObjectType(); 20203af6ab5fSopenharmony_ci 20213af6ab5fSopenharmony_ci if (objType->StringIndexInfo() != nullptr) { 20223af6ab5fSopenharmony_ci return objType->StringIndexInfo()->GetType(); 20233af6ab5fSopenharmony_ci } 20243af6ab5fSopenharmony_ci } 20253af6ab5fSopenharmony_ci 20263af6ab5fSopenharmony_ci checker->ThrowTypeError({"Property ", expr->Right()->Name(), " does not exist on this type."}, 20273af6ab5fSopenharmony_ci expr->Right()->Start()); 20283af6ab5fSopenharmony_ci return nullptr; 20293af6ab5fSopenharmony_ci} 20303af6ab5fSopenharmony_ci 20313af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check([[maybe_unused]] ir::TSStringKeyword *node) const 20323af6ab5fSopenharmony_ci{ 20333af6ab5fSopenharmony_ci return nullptr; 20343af6ab5fSopenharmony_ci} 20353af6ab5fSopenharmony_ci 20363af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check(ir::TSTupleType *node) const 20373af6ab5fSopenharmony_ci{ 20383af6ab5fSopenharmony_ci TSChecker *checker = GetTSChecker(); 20393af6ab5fSopenharmony_ci for (auto *it : node->ElementType()) { 20403af6ab5fSopenharmony_ci it->Check(checker); 20413af6ab5fSopenharmony_ci } 20423af6ab5fSopenharmony_ci 20433af6ab5fSopenharmony_ci node->GetType(checker); 20443af6ab5fSopenharmony_ci return nullptr; 20453af6ab5fSopenharmony_ci} 20463af6ab5fSopenharmony_ci 20473af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check(ir::TSTypeAliasDeclaration *st) const 20483af6ab5fSopenharmony_ci{ 20493af6ab5fSopenharmony_ci TSChecker *checker = GetTSChecker(); 20503af6ab5fSopenharmony_ci st->TypeAnnotation()->Check(checker); 20513af6ab5fSopenharmony_ci return nullptr; 20523af6ab5fSopenharmony_ci} 20533af6ab5fSopenharmony_ci 20543af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check(ir::TSTypeLiteral *node) const 20553af6ab5fSopenharmony_ci{ 20563af6ab5fSopenharmony_ci TSChecker *checker = GetTSChecker(); 20573af6ab5fSopenharmony_ci 20583af6ab5fSopenharmony_ci for (auto *it : node->Members()) { 20593af6ab5fSopenharmony_ci it->Check(checker); 20603af6ab5fSopenharmony_ci } 20613af6ab5fSopenharmony_ci 20623af6ab5fSopenharmony_ci checker::Type *type = node->GetType(checker); 20633af6ab5fSopenharmony_ci checker->CheckIndexConstraints(type); 20643af6ab5fSopenharmony_ci 20653af6ab5fSopenharmony_ci return nullptr; 20663af6ab5fSopenharmony_ci} 20673af6ab5fSopenharmony_ci 20683af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check(ir::TSTypeQuery *node) const 20693af6ab5fSopenharmony_ci{ 20703af6ab5fSopenharmony_ci TSChecker *checker = GetTSChecker(); 20713af6ab5fSopenharmony_ci if (node->TsType() != nullptr) { 20723af6ab5fSopenharmony_ci return node->TsType(); 20733af6ab5fSopenharmony_ci } 20743af6ab5fSopenharmony_ci 20753af6ab5fSopenharmony_ci node->SetTsType(node->exprName_->Check(checker)); 20763af6ab5fSopenharmony_ci return node->TsType(); 20773af6ab5fSopenharmony_ci} 20783af6ab5fSopenharmony_ci 20793af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check(ir::TSTypeReference *node) const 20803af6ab5fSopenharmony_ci{ 20813af6ab5fSopenharmony_ci TSChecker *checker = GetTSChecker(); 20823af6ab5fSopenharmony_ci node->GetType(checker); 20833af6ab5fSopenharmony_ci return nullptr; 20843af6ab5fSopenharmony_ci} 20853af6ab5fSopenharmony_ci 20863af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check([[maybe_unused]] ir::TSUndefinedKeyword *node) const 20873af6ab5fSopenharmony_ci{ 20883af6ab5fSopenharmony_ci return nullptr; 20893af6ab5fSopenharmony_ci} 20903af6ab5fSopenharmony_ci 20913af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check(ir::TSUnionType *node) const 20923af6ab5fSopenharmony_ci{ 20933af6ab5fSopenharmony_ci TSChecker *checker = GetTSChecker(); 20943af6ab5fSopenharmony_ci for (auto *it : node->Types()) { 20953af6ab5fSopenharmony_ci it->Check(checker); 20963af6ab5fSopenharmony_ci } 20973af6ab5fSopenharmony_ci 20983af6ab5fSopenharmony_ci node->GetType(checker); 20993af6ab5fSopenharmony_ci return nullptr; 21003af6ab5fSopenharmony_ci} 21013af6ab5fSopenharmony_ci 21023af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check([[maybe_unused]] ir::TSUnknownKeyword *node) const 21033af6ab5fSopenharmony_ci{ 21043af6ab5fSopenharmony_ci return nullptr; 21053af6ab5fSopenharmony_ci} 21063af6ab5fSopenharmony_ci 21073af6ab5fSopenharmony_cichecker::Type *TSAnalyzer::Check([[maybe_unused]] ir::TSVoidKeyword *node) const 21083af6ab5fSopenharmony_ci{ 21093af6ab5fSopenharmony_ci return nullptr; 21103af6ab5fSopenharmony_ci} 21113af6ab5fSopenharmony_ci} // namespace ark::es2panda::checker 2112