Lines Matching +full:checker +full:-
2 * Copyright (c) 2021-2025 Huawei Device Co., Ltd.
7 * http://www.apache.org/licenses/LICENSE-2.0
18 #include "checker/TSchecker.h"
19 #include "checker/ets/castingContext.h"
20 #include "checker/types/ets/etsTupleType.h"
30 …object_ = other.object_ != nullptr ? other.object_->Clone(allocator, this)->AsExpression() : nullp… in MemberExpression()
31 …property_ = other.property_ != nullptr ? other.property_->Clone(allocator, this)->AsExpression() :… in MemberExpression()
36 return property_->IsIdentifier() && property_->AsIdentifier()->IsPrivateIdent(); in IsPrivateReference()
42 object_->SetTransformedNode(transformationName, transformedNode); in TransformChildren()
43 object_ = transformedNode->AsExpression(); in TransformChildren()
47 property_->SetTransformedNode(transformationName, transformedNode); in TransformChildren()
48 property_ = transformedNode->AsExpression(); in TransformChildren()
60 dumper->Add({{"type", "MemberExpression"}, in Dump()
72 object_->Dump(dumper); in Dump()
74 dumper->Add("?"); in Dump()
76 dumper->Add("."); in Dump()
80 dumper->Add("["); in Dump()
81 property_->Dump(dumper); in Dump()
82 dumper->Add("]"); in Dump()
84 dumper->Add("."); in Dump()
85 property_->Dump(dumper); in Dump()
87 if ((parent_ != nullptr) && (parent_->IsBlockStatement() || parent_->IsBlockExpression())) { in Dump()
88 dumper->Add(";"); in Dump()
89 dumper->Endl(); in Dump()
96 bool isSuper = object_->IsSuperExpression(); in LoadRhs()
97 compiler::Operand prop = pg->ToPropertyKey(property_, computed_, isSuper); in LoadRhs()
100 pg->LoadSuperProperty(this, prop); in LoadRhs()
102 const auto &name = property_->AsIdentifier()->Name(); in LoadRhs()
103 compiler::VReg objReg = pg->AllocReg(); in LoadRhs()
104 pg->StoreAccumulator(this, objReg); in LoadRhs()
105 compiler::VReg ctor = pg->AllocReg(); in LoadRhs()
107 pg->ClassPrivateFieldGet(this, ctor, objReg, name); in LoadRhs()
109 pg->LoadObjProperty(this, prop); in LoadRhs()
115 object_->Compile(pg); in CompileToRegs()
116 pg->StoreAccumulator(this, object); in CompileToRegs()
118 pg->OptionalChainCheck(IsOptional(), object); in CompileToRegs()
121 pg->LoadAccumulatorString(this, property_->AsIdentifier()->Name()); in CompileToRegs()
123 property_->Compile(pg); in CompileToRegs()
126 pg->StoreAccumulator(this, property); in CompileToRegs()
131 pg->GetAstCompiler()->Compile(this); in Compile()
136 object_->Compile(pg); in CompileToReg()
137 pg->StoreAccumulator(this, objReg); in CompileToReg()
138 pg->OptionalChainCheck(IsOptional(), objReg); in CompileToReg()
144 etsg->GetAstCompiler()->Compile(this); in Compile()
147 checker::Type *MemberExpression::Check(checker::TSChecker *checker) in Check() argument
149 return checker->GetAnalyzer()->Check(this); in Check()
152 std::pair<checker::Type *, varbinder::LocalVariable *> MemberExpression::ResolveObjectMember( in ResolveObjectMember()
153 checker::ETSChecker *checker) const in ResolveObjectMember()
155 auto resolveRes = checker->ResolveMemberReference(this, objType_); in ResolveObjectMember()
162 if (resolveRes[0]->Kind() == checker::ResolvedKind::PROPERTY) { in ResolveObjectMember()
163 auto var = resolveRes[0]->Variable()->AsLocalVariable(); in ResolveObjectMember()
164 checker->ValidatePropertyAccess(var, objType_, property_->Start()); in ResolveObjectMember()
165 return {checker->GetTypeOfVariable(var), var}; in ResolveObjectMember()
168 if (resolveRes[0]->Kind() == checker::ResolvedKind::EXTENSION_ACCESSOR) { in ResolveObjectMember()
169 auto *callee = const_cast<ir::Expression *>(this->AsExpression()); in ResolveObjectMember()
170 … callee->AsMemberExpression()->AddMemberKind(ir::MemberExpressionKind::EXTENSION_ACCESSOR); in ResolveObjectMember()
171 return {resolveRes[0]->Variable()->TsType(), nullptr}; in ResolveObjectMember()
174 return {checker->GetTypeOfVariable(resolveRes[0]->Variable()), nullptr}; in ResolveObjectMember()
177 auto classMethodType = checker->GetTypeOfVariable(resolveRes[1]->Variable()); in ResolveObjectMember()
178 auto extensionMethodType = checker->GetTypeOfVariable(resolveRes[0]->Variable()); in ResolveObjectMember()
180 if (classMethodType->IsETSFunctionType()) { in ResolveObjectMember()
181 ES2PANDA_ASSERT(extensionMethodType->IsETSFunctionType()); in ResolveObjectMember()
182 … resolvedType = checker->CreateETSExtensionFuncHelperType(classMethodType->AsETSFunctionType(), in ResolveObjectMember()
183 … extensionMethodType->AsETSFunctionType()); in ResolveObjectMember()
193 checker::Type *MemberExpression::TraverseUnionMember(checker::ETSChecker *checker, checker::ETSUnio… in TraverseUnionMember() argument
196 checker::Type *commonPropType = nullptr; in TraverseUnionMember()
198 auto const addPropType = [this, checker, &commonPropType](checker::Type *memberType) { in TraverseUnionMember()
205 checker->LogError(diagnostic::MEMBER_TYPE_MISMATCH_ACROSS_UNION, {}, Start()); in TraverseUnionMember()
209 if (!commonPropType->IsETSMethodType() && !memberType->IsETSMethodType()) { in TraverseUnionMember()
210 if (!checker->IsTypeIdenticalTo(commonPropType, memberType)) { in TraverseUnionMember()
211 checker->LogError(diagnostic::MEMBER_TYPE_MISMATCH_ACROSS_UNION, {}, Start()); in TraverseUnionMember()
217 …checker->IntersectSignatureSets(commonPropType->AsETSFunctionType(), memberType->AsETSFunctionType… in TraverseUnionMember()
218 if (newType->AsETSFunctionType()->CallSignatures().empty()) { in TraverseUnionMember()
219 checker->LogError(diagnostic::MEMBER_TYPE_MISMATCH_ACROSS_UNION, {}, Start()); in TraverseUnionMember()
225 for (auto *const type : unionType->ConstituentTypes()) { in TraverseUnionMember()
226 auto *const apparent = checker->GetApparentType(type); in TraverseUnionMember()
228 if (apparent->IsETSObjectType()) { in TraverseUnionMember()
229 SetObjectType(apparent->AsETSObjectType()); in TraverseUnionMember()
230 auto *memberType = ResolveObjectMember(checker).first; in TraverseUnionMember()
231 if (memberType != nullptr && memberType->IsTypeError()) { in TraverseUnionMember()
232 return checker->GlobalTypeError(); in TraverseUnionMember()
237 checker->LogError(diagnostic::UNION_MEMBER_ILLEGAL_TYPE, {unionType}, Start()); in TraverseUnionMember()
243 checker::Type *MemberExpression::CheckUnionMember(checker::ETSChecker *checker, checker::Type *base… in CheckUnionMember() argument
245 auto *const unionType = baseType->AsETSUnionType(); in CheckUnionMember()
246 if (object_->Variable() != nullptr && object_->Variable()->Declaration() != nullptr && in CheckUnionMember()
247 object_->Variable()->Declaration()->IsTypeAliasDecl()) { in CheckUnionMember()
248 checker->LogError(diagnostic::STATIC_UNION, {}, Start()); in CheckUnionMember()
249 return checker->GlobalTypeError(); in CheckUnionMember()
251 auto *const commonPropType = TraverseUnionMember(checker, unionType); in CheckUnionMember()
252 SetObjectType(checker->GlobalETSObjectType()); in CheckUnionMember()
256 static checker::Type *AdjustRecordReturnType(checker::Type *type, checker::Type *objType) in AdjustRecordReturnType()
258 auto *recordKeyType = objType->AsETSObjectType()->TypeArguments()[0]; in AdjustRecordReturnType()
259 auto *recordValueType = objType->AsETSObjectType()->TypeArguments()[1]; in AdjustRecordReturnType()
261 auto const isStringLiteralOrConstantUnion = [](checker::Type *recordKey) { in AdjustRecordReturnType()
262 if (recordKey->IsETSStringType() && recordKey->IsConstantType()) { in AdjustRecordReturnType()
265 if (!recordKey->IsETSUnionType()) { in AdjustRecordReturnType()
268 auto constituentTypes = recordKey->AsETSUnionType()->ConstituentTypes(); in AdjustRecordReturnType()
270 [](auto *it) { return it->IsETSStringType() && it->IsConstantType(); }); in AdjustRecordReturnType()
273 if (type->IsETSUnionType()) { in AdjustRecordReturnType()
277 …if (type->IsETSFunctionType() && type->AsETSFunctionType()->Name().Is(compiler::Signatures::GET_IN… in AdjustRecordReturnType()
278 type->AsETSFunctionType()->CallSignatures()[0]->SetReturnType(recordValueType); in AdjustRecordReturnType()
285 checker::Type *MemberExpression::AdjustType(checker::ETSChecker *checker, checker::Type *type) in AdjustType() argument
287 auto *const objType = checker->GetApparentType(Object()->TsType()); in AdjustType()
289 if (type != nullptr && objType->IsETSObjectType() && in AdjustType()
290 objType->ToAssemblerName().str() == compiler::Signatures::BUILTIN_RECORD) { in AdjustType()
295 uncheckedType_ = checker->GuaranteedTypeForUncheckedPropertyAccess(PropVar()); in AdjustType()
296 } else if (IsComputed() && objType->IsETSArrayType()) { // access erased array or tuple type in AdjustType()
297 …uncheckedType_ = checker->GuaranteedTypeForUncheckedCast(objType->AsETSArrayType()->ElementType(),… in AdjustType()
298 } else if (IsComputed() && objType->IsETSTupleType()) { in AdjustType()
299 if (!checker->ValidateTupleIndex(objType->AsETSTupleType(), this, false)) { in AdjustType()
301 return checker->InvalidateType(this); in AdjustType()
303 …uncheckedType_ = checker->GetApparentType(checker->MaybeBoxType(GetTypeOfTupleElement(checker, obj… in AdjustType()
304 } else if (objType->IsETSUnionType()) { in AdjustType()
305 … uncheckedType_ = checker->GuaranteedTypeForUnionFieldAccess(this, objType->AsETSUnionType()); in AdjustType()
306 } else if (checker->IsExtensionAccessorFunctionType(type)) { in AdjustType()
308 checker::Type *accessorReturnType = checker->GetExtensionAccessorReturnType(this); in AdjustType()
309 SetTsType(accessorReturnType == nullptr ? checker->GlobalTypeError() : accessorReturnType); in AdjustType()
312 SetTsType(type == nullptr ? checker->GlobalTypeError() : type); in AdjustType()
316 checker::Type *MemberExpression::SetAndAdjustType(checker::ETSChecker *checker, checker::ETSObjectT… in SetAndAdjustType() argument
319 auto [resType, resVar] = ResolveObjectMember(checker); in SetAndAdjustType()
321 return checker->InvalidateType(this); in SetAndAdjustType()
324 return AdjustType(checker, resType); in SetAndAdjustType()
329 auto *propType = property_->TsType(); in GetTupleIndexValue()
330 if (object_->TsType() == nullptr || !object_->TsType()->IsETSTupleType() || in GetTupleIndexValue()
331 …!propType->HasTypeFlag(checker::TypeFlag::CONSTANT | checker::TypeFlag::ETS_CONVERTIBLE_TO_NUMERIC… in GetTupleIndexValue()
335 if (propType->IsByteType()) { in GetTupleIndexValue()
336 return propType->AsByteType()->GetValue(); in GetTupleIndexValue()
339 if (propType->IsShortType()) { in GetTupleIndexValue()
340 return propType->AsShortType()->GetValue(); in GetTupleIndexValue()
343 if (propType->IsIntType()) { in GetTupleIndexValue()
344 return propType->AsIntType()->GetValue(); in GetTupleIndexValue()
347 if (propType->IsLongType()) { in GetTupleIndexValue()
348 if (auto val = propType->AsLongType()->GetValue(); in GetTupleIndexValue()
358 bool MemberExpression::CheckArrayIndexValue(checker::ETSChecker *checker) const in CheckArrayIndexValue()
362 auto const &number = property_->AsNumberLiteral()->Number(); in CheckArrayIndexValue()
367 checker->LogError(diagnostic::NEGATIVE_INDEX, {}, property_->Start()); in CheckArrayIndexValue()
377 checker->LogError(diagnostic::INDEX_NEGATIVE_OR_FRACTIONAL, {}, property_->Start()); in CheckArrayIndexValue()
383 if (object_->IsArrayExpression() && object_->AsArrayExpression()->Elements().size() <= index) { in CheckArrayIndexValue()
384 checker->LogError(diagnostic::INDEX_OOB, {}, property_->Start()); in CheckArrayIndexValue()
391 checker::Type *MemberExpression::ResolveReturnTypeFromSignature(checker::ETSChecker *checker, bool … in ResolveReturnTypeFromSignature() argument
393 … ArenaVector<checker::Signature *> &signatures, in ResolveReturnTypeFromSignature()
396 auto flags = checker::TypeRelationFlag::NONE; in ResolveReturnTypeFromSignature()
397 checker::Signature *signature = in ResolveReturnTypeFromSignature()
398 checker->ValidateSignatures(signatures, nullptr, arguments, Start(), "indexing", flags); in ResolveReturnTypeFromSignature()
401 Parent()->AsAssignmentExpression()->Right()->SetParent(Parent()); in ResolveReturnTypeFromSignature()
403 checker->LogError(diagnostic::MISSING_INDEX_ACCESSOR_WITH_SIG, {}, Property()->Start()); in ResolveReturnTypeFromSignature()
406 checker->ValidateSignatureAccessibility(objType_, signature, Start()); in ResolveReturnTypeFromSignature()
408 ES2PANDA_ASSERT(signature->Function() != nullptr); in ResolveReturnTypeFromSignature()
411 if (checker->IsClassStaticMethod(objType_, signature)) { in ResolveReturnTypeFromSignature()
412 …checker->LogError(diagnostic::PROP_IS_STATIC, {methodName, objType_->Name()}, Property()->Start()); in ResolveReturnTypeFromSignature()
415 Parent()->AsAssignmentExpression()->Right()->SetParent(Parent()); in ResolveReturnTypeFromSignature()
416 return signature->Params()[1]->TsType(); in ResolveReturnTypeFromSignature()
420 if (!signature->Owner()->IsETSEnumType() && checker->IsClassStaticMethod(objType_, signature)) { in ResolveReturnTypeFromSignature()
421 …checker->LogError(diagnostic::PROP_IS_STATIC, {methodName, objType_->Name()}, Property()->Start()); in ResolveReturnTypeFromSignature()
424 return signature->ReturnType(); in ResolveReturnTypeFromSignature()
427 checker::Type *MemberExpression::CheckIndexAccessMethod(checker::ETSChecker *checker) in CheckIndexAccessMethod() argument
429 checker::PropertySearchFlags searchFlag = checker::PropertySearchFlags::SEARCH_METHOD; in CheckIndexAccessMethod()
430 …searchFlag |= checker::PropertySearchFlags::SEARCH_IN_BASE | checker::PropertySearchFlags::SEARCH_… in CheckIndexAccessMethod()
431 …// NOTE(DZ) maybe we need to exclude static methods: search_flag &= ~(checker::PropertySearchFlags… in CheckIndexAccessMethod()
433 if (objType_->HasTypeFlag(checker::TypeFlag::GENERIC)) { in CheckIndexAccessMethod()
434 searchFlag |= checker::PropertySearchFlags::SEARCH_ALL; in CheckIndexAccessMethod()
437 …bool const isSetter = Parent()->IsAssignmentExpression() && Parent()->AsAssignmentExpression()->Le… in CheckIndexAccessMethod()
440 auto *const method = objType_->GetProperty(methodName, searchFlag); in CheckIndexAccessMethod()
441 if (method == nullptr || !method->HasFlag(varbinder::VariableFlags::METHOD)) { in CheckIndexAccessMethod()
442 checker->LogError(diagnostic::ERROR_ARKTS_NO_PROPERTIES_BY_INDEX, {}, Start()); in CheckIndexAccessMethod()
446 ArenaVector<Expression *> arguments {checker->ProgramAllocator()->Adapter()}; in CheckIndexAccessMethod()
451 auto *value = Parent()->AsAssignmentExpression()->Right(); in CheckIndexAccessMethod()
452 value->SetParent(this); in CheckIndexAccessMethod()
455 auto &signatures = checker->GetTypeOfVariable(method)->AsETSFunctionType()->CallSignatures(); in CheckIndexAccessMethod()
457 return ResolveReturnTypeFromSignature(checker, isSetter, arguments, signatures, methodName); in CheckIndexAccessMethod()
460 checker::Type *MemberExpression::GetTypeOfTupleElement(checker::ETSChecker *checker, checker::Type … in GetTypeOfTupleElement() argument
462 ES2PANDA_ASSERT(baseType->IsETSTupleType()); in GetTypeOfTupleElement()
463 checker::Type *type = nullptr; in GetTypeOfTupleElement()
464 if (Property()->HasBoxingUnboxingFlags(ir::BoxingUnboxingFlags::UNBOXING_FLAG)) { in GetTypeOfTupleElement()
465 ES2PANDA_ASSERT(Property()->Variable()->Declaration()->Node()->AsClassElement()->Value()); in GetTypeOfTupleElement()
466 type = Property()->Variable()->Declaration()->Node()->AsClassElement()->Value()->TsType(); in GetTypeOfTupleElement()
468 type = Property()->TsType(); in GetTypeOfTupleElement()
471 auto idxIfAny = checker->GetTupleElementAccessValue(type); in GetTypeOfTupleElement()
476 return baseType->AsETSTupleType()->GetTypeAtIndex(*idxIfAny); in GetTypeOfTupleElement()
479 static void CastTupleElementFromClassMemberType(checker::ETSChecker *checker, in CastTupleElementFromClassMemberType() argument
480 … ir::MemberExpression *tupleElementAccessor, checker::Type *baseType) in CastTupleElementFromClassMemberType()
482 auto *typeOfTuple = tupleElementAccessor->GetTypeOfTupleElement(checker, baseType); in CastTupleElementFromClassMemberType()
483 auto *storedTupleType = checker->MaybeBoxType(typeOfTuple); in CastTupleElementFromClassMemberType()
485 const checker::CastingContext tupleCast( in CastTupleElementFromClassMemberType()
486 checker->Relation(), diagnostic::CAST_FAIL_UNREACHABLE, {}, in CastTupleElementFromClassMemberType()
487 … checker::CastingContext::ConstructorData {tupleElementAccessor, storedTupleType, typeOfTuple, in CastTupleElementFromClassMemberType()
488 … tupleElementAccessor->Start(), checker::TypeRelationFlag::NO_THROW}); in CastTupleElementFromClassMemberType()
491 checker::Type *MemberExpression::CheckComputed(checker::ETSChecker *checker, checker::Type *baseTyp… in CheckComputed() argument
493 if (baseType->IsETSDynamicType()) { in CheckComputed()
494 if (!property_->Check(checker)->IsETSStringType()) { in CheckComputed()
495 checker->ValidateArrayIndex(property_); in CheckComputed()
497 return checker->GlobalBuiltinDynamicType(baseType->AsETSDynamicType()->Language()); in CheckComputed()
500 if (baseType->IsETSArrayType()) { in CheckComputed()
501 auto *dflt = baseType->AsETSArrayType()->ElementType(); in CheckComputed()
502 if (!checker->ValidateArrayIndex(property_)) { in CheckComputed()
508 if (property_->IsNumberLiteral() && !CheckArrayIndexValue(checker)) { in CheckComputed()
516 if (baseType->IsETSTupleType()) { in CheckComputed()
517 if (!checker->ValidateTupleIndex(baseType->AsETSTupleType(), this)) { in CheckComputed()
522 … if (Parent()->IsAssignmentExpression() && Parent()->AsAssignmentExpression()->Left() == this) { in CheckComputed()
525 auto *typeOfTuple = GetTypeOfTupleElement(checker, baseType); in CheckComputed()
526 auto *storedTupleType = checker->MaybeBoxType(typeOfTuple); in CheckComputed()
530 CastTupleElementFromClassMemberType(checker, this, baseType); in CheckComputed()
533 auto *res = GetTypeOfTupleElement(checker, baseType); in CheckComputed()
537 if (baseType->IsETSObjectType()) { in CheckComputed()
538 SetObjectType(baseType->AsETSObjectType()); in CheckComputed()
539 return CheckIndexAccessMethod(checker); in CheckComputed()
541 checker->LogError(diagnostic::INDEX_ON_INVALID_TYPE, {}, Object()->Start()); in CheckComputed()
545 checker::VerifiedType MemberExpression::Check(checker::ETSChecker *checker) in Check() argument
547 return {this, checker->GetAnalyzer()->Check(this)}; in Check()
552 auto *const clone = allocator->New<MemberExpression>(Tag {}, *this, allocator); in Clone()
555 clone->SetParent(parent); in Clone()
558 clone->SetRange(Range()); in Clone()
564 auto str1 = object_ != nullptr ? object_->ToString() : std::string {INVALID_EXPRESSION}; in ToString()
569 auto str2 = property_ != nullptr ? property_->ToString() : std::string {INVALID_EXPRESSION}; in ToString()