• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef ES2PANDA_CHECKER_ETS_CHECKER_H
17 #define ES2PANDA_CHECKER_ETS_CHECKER_H
18 
19 #include <mutex>
20 
21 #include "checker/checker.h"
22 
23 #include "checker/types/ets/types.h"
24 #include "checker/ets/primitiveWrappers.h"
25 #include "checker/resolveResult.h"
26 #include "util/helpers.h"
27 
28 namespace ark::es2panda::varbinder {
29 class VarBinder;
30 class Decl;
31 class EnumVariable;
32 class FunctionDecl;
33 class LocalVariable;
34 class Scope;
35 class Variable;
36 class ETSBinder;
37 class RecordTable;
38 class FunctionParamScope;
39 }  // namespace ark::es2panda::varbinder
40 
41 namespace ark::es2panda::checker {
42 
43 struct Accessor {
44     bool isGetter {false};
45     bool isSetter {false};
46     bool isExternal {false};
47 };
48 
49 using ComputedAbstracts =
50     ArenaUnorderedMap<ETSObjectType *, std::pair<ArenaVector<ETSFunctionType *>, std::unordered_set<ETSObjectType *>>>;
51 using ArrayMap = ArenaUnorderedMap<Type *, ETSArrayType *>;
52 using GlobalArraySignatureMap = ArenaUnorderedMap<ETSArrayType *, Signature *>;
53 using DynamicCallIntrinsicsMap = ArenaUnorderedMap<Language, ArenaUnorderedMap<util::StringView, ir::ScriptFunction *>>;
54 using DynamicClassIntrinsicsMap = ArenaUnorderedMap<Language, ir::ClassDeclaration *>;
55 using DynamicLambdaObjectSignatureMap = ArenaUnorderedMap<std::string, Signature *>;
56 using FunctionalInterfaceMap = ArenaUnorderedMap<util::StringView, ETSObjectType *>;
57 using TypeMapping = ArenaUnorderedMap<Type const *, Type *>;
58 using DynamicCallNamesMap = ArenaMap<const ArenaVector<util::StringView>, uint32_t>;
59 using ConstraintCheckRecord = std::tuple<const ArenaVector<Type *> *, const Substitution *, lexer::SourcePosition>;
60 
61 class ETSChecker final : public Checker {
62 public:
ETSChecker()63     explicit ETSChecker()
64         // NOLINTNEXTLINE(readability-redundant-member-init)
65         : Checker(),
66           arrayTypes_(Allocator()->Adapter()),
67           pendingConstraintCheckRecords_(Allocator()->Adapter()),
68           globalArraySignatures_(Allocator()->Adapter()),
69           primitiveWrappers_(Allocator()),
70           cachedComputedAbstracts_(Allocator()->Adapter()),
71           dynamicIntrinsics_ {DynamicCallIntrinsicsMap {Allocator()->Adapter()},
72                               DynamicCallIntrinsicsMap {Allocator()->Adapter()}},
73           dynamicClasses_ {DynamicClassIntrinsicsMap(Allocator()->Adapter()),
74                            DynamicClassIntrinsicsMap(Allocator()->Adapter())},
75           dynamicLambdaSignatureCache_(Allocator()->Adapter()),
76           functionalInterfaceCache_(Allocator()->Adapter()),
77           apparentTypes_(Allocator()->Adapter()),
78           dynamicCallNames_ {{DynamicCallNamesMap(Allocator()->Adapter()), DynamicCallNamesMap(Allocator()->Adapter())}}
79     {
80     }
81 
82     ~ETSChecker() override = default;
83 
84     NO_COPY_SEMANTIC(ETSChecker);
85     NO_MOVE_SEMANTIC(ETSChecker);
86 
ETSType(const Type * const type)87     [[nodiscard]] static inline TypeFlag ETSType(const Type *const type) noexcept
88     {
89         return static_cast<TypeFlag>(type->TypeFlags() & TypeFlag::ETS_TYPE);
90     }
91 
TypeKind(const Type * const type)92     [[nodiscard]] static inline TypeFlag TypeKind(const Type *const type) noexcept
93     {
94         return static_cast<checker::TypeFlag>(type->TypeFlags() & checker::TypeFlag::ETS_TYPE);
95     }
96 
97     Type *GlobalByteType() const;
98     Type *GlobalShortType() const;
99     Type *GlobalIntType() const;
100     Type *GlobalLongType() const;
101     Type *GlobalFloatType() const;
102     Type *GlobalDoubleType() const;
103     Type *GlobalCharType() const;
104     Type *GlobalETSBooleanType() const;
105     Type *GlobalVoidType() const;
106     Type *GlobalETSNullType() const;
107     Type *GlobalETSUndefinedType() const;
108     Type *GlobalETSStringLiteralType() const;
109     Type *GlobalETSBigIntType() const;
110     Type *GlobalWildcardType() const;
111 
112     ETSObjectType *GlobalETSObjectType() const;
113     ETSUnionType *GlobalETSNullishType() const;
114     ETSUnionType *GlobalETSNullishObjectType() const;
115     ETSObjectType *GlobalBuiltinETSStringType() const;
116     ETSObjectType *GlobalBuiltinETSBigIntType() const;
117     ETSObjectType *GlobalBuiltinTypeType() const;
118     ETSObjectType *GlobalBuiltinExceptionType() const;
119     ETSObjectType *GlobalBuiltinErrorType() const;
120     ETSObjectType *GlobalStringBuilderBuiltinType() const;
121     ETSObjectType *GlobalBuiltinPromiseType() const;
122     ETSObjectType *GlobalBuiltinJSRuntimeType() const;
123     ETSObjectType *GlobalBuiltinJSValueType() const;
124     ETSObjectType *GlobalBuiltinBoxType(Type *contents);
125 
126     ETSObjectType *GlobalBuiltinFunctionType(size_t nargs) const;
127     size_t GlobalBuiltinFunctionTypeVariadicThreshold() const;
128 
129     ETSObjectType *GlobalBuiltinDynamicType(Language lang) const;
130 
131     const checker::WrapperDesc &PrimitiveWrapper() const;
132 
133     GlobalArraySignatureMap &GlobalArrayTypes();
134     const GlobalArraySignatureMap &GlobalArrayTypes() const;
135 
136     Type *GlobalTypeError() const;
137 
138     void InitializeBuiltins(varbinder::ETSBinder *varbinder);
139     void InitializeBuiltin(varbinder::Variable *var, const util::StringView &name);
140     bool StartChecker([[maybe_unused]] varbinder::VarBinder *varbinder, const CompilerOptions &options) override;
141     Type *CheckTypeCached(ir::Expression *expr) override;
ResolveStructuredTypeMembers(Type * type)142     void ResolveStructuredTypeMembers([[maybe_unused]] Type *type) override {}
143     Type *GetTypeOfVariable([[maybe_unused]] varbinder::Variable *var) override;
144     Type *GuaranteedTypeForUncheckedCast(Type *base, Type *substituted);
145     Type *GuaranteedTypeForUncheckedCallReturn(Signature *sig);
146     Type *GuaranteedTypeForUncheckedPropertyAccess(varbinder::Variable *prop);
147 
IsETSChecker()148     [[nodiscard]] bool IsETSChecker() const noexcept override
149     {
150         return true;
151     }
152 
153     // Object
154     ETSObjectType *BuildBasicClassProperties(ir::ClassDefinition *classDef);
155     ETSObjectType *BuildAnonymousClassProperties(ir::ClassDefinition *classDef, ETSObjectType *superType);
156     ETSObjectType *BuildBasicInterfaceProperties(ir::TSInterfaceDeclaration *interfaceDecl);
157     ETSObjectType *GetSuperType(ETSObjectType *type);
158     ArenaVector<ETSObjectType *> GetInterfaces(ETSObjectType *type);
159     ArenaVector<ETSObjectType *> GetInterfacesOfClass(ETSObjectType *type);
160     ArenaVector<ETSObjectType *> GetInterfacesOfInterface(ETSObjectType *type);
161     void ValidateImplementedInterface(ETSObjectType *type, Type *interface, std::unordered_set<Type *> *extendsSet,
162                                       const lexer::SourcePosition &pos);
163     void ResolveDeclaredMembersOfObject(const ETSObjectType *type);
164     std::optional<int32_t> GetTupleElementAccessValue(const Type *type, const lexer::SourcePosition &pos);
165     bool ValidateArrayIndex(ir::Expression *expr, bool relaxed = false);
166     bool ValidateTupleIndex(const ETSTupleType *tuple, ir::MemberExpression *expr);
167     ETSObjectType *CheckThisOrSuperAccess(ir::Expression *node, ETSObjectType *classType, std::string_view msg);
168     void CreateTypeForClassOrInterfaceTypeParameters(ETSObjectType *type);
169     ETSTypeParameter *SetUpParameterType(ir::TSTypeParameter *param);
170     void CheckIfOverrideIsValidInInterface(const ETSObjectType *classType, Signature *sig, ir::ScriptFunction *func);
171     void CheckFunctionRedeclarationInInterface(const ETSObjectType *classType,
172                                                ArenaVector<Signature *> &similarSignatures, ir::ScriptFunction *func);
173     void ValidateAbstractMethodsToBeImplemented(ArenaVector<ETSFunctionType *> &abstractsToBeImplemented,
174                                                 ETSObjectType *classType,
175                                                 const std::vector<Signature *> &implementedSignatures);
176     void ApplyModifiersAndRemoveImplementedAbstracts(ArenaVector<ETSFunctionType *>::iterator &it,
177                                                      ArenaVector<ETSFunctionType *> &abstractsToBeImplemented,
178                                                      ETSObjectType *classType, bool &functionOverridden,
179                                                      const Accessor &isGetSetExternal);
180     void ValidateAbstractSignature(ArenaVector<ETSFunctionType *>::iterator &it,
181                                    ArenaVector<ETSFunctionType *> &abstractsToBeImplemented,
182                                    const std::vector<Signature *> &implementedSignatures, bool &functionOverridden,
183                                    Accessor &isGetSetExternal);
184     void ValidateNonOverriddenFunction(ETSObjectType *classType, ArenaVector<ETSFunctionType *>::iterator &it,
185                                        ArenaVector<ETSFunctionType *> &abstractsToBeImplemented,
186                                        bool &functionOverridden, const Accessor &isGetSet);
187     void MaybeReportErrorsForOverridingValidation(ArenaVector<ETSFunctionType *> &abstractsToBeImplemented,
188                                                   ETSObjectType *classType, const lexer::SourcePosition &pos,
189                                                   bool reportError);
190     void ValidateOverriding(ETSObjectType *classType, const lexer::SourcePosition &pos);
191     void CheckInterfaceFunctions(ETSObjectType *classType);
192     void CollectImplementedMethodsFromInterfaces(ETSObjectType *classType,
193                                                  std::vector<Signature *> *implementedSignatures,
194                                                  const ArenaVector<ETSFunctionType *> &abstractsToBeImplemented);
195     void AddImplementedSignature(std::vector<Signature *> *implementedSignatures, varbinder::LocalVariable *function,
196                                  ETSFunctionType *it);
197     void CheckInnerClassMembers(const ETSObjectType *classType);
198     void CheckLocalClass(ir::ClassDefinition *classDef, CheckerStatus &checkerStatus);
199     void CheckClassDefinition(ir::ClassDefinition *classDef);
200     void CheckConstructors(ir::ClassDefinition *classDef, ETSObjectType *classType);
201     void FindAssignment(const ir::AstNode *node, const varbinder::LocalVariable *classVar, bool &initialized);
202     void FindAssignments(const ir::AstNode *node, const varbinder::LocalVariable *classVar, bool &initialized);
203     void CheckConstFields(const ETSObjectType *classType);
204     void CheckConstFieldInitialized(const ETSObjectType *classType, varbinder::LocalVariable *classVar);
205     void CheckConstFieldInitialized(const Signature *signature, varbinder::LocalVariable *classVar);
206     void ComputeAbstractsFromInterface(ETSObjectType *interfaceType);
207     ArenaVector<ETSFunctionType *> &GetAbstractsForClass(ETSObjectType *classType);
208     std::vector<Signature *> CollectAbstractSignaturesFromObject(const ETSObjectType *objType);
209     void CreateFunctionTypesFromAbstracts(const std::vector<Signature *> &abstracts,
210                                           ArenaVector<ETSFunctionType *> *target);
211     void CheckCyclicConstructorCall(Signature *signature);
212     std::vector<ResolveResult *> ResolveMemberReference(const ir::MemberExpression *memberExpr,
213                                                         const ETSObjectType *target);
214     varbinder::Variable *ResolveInstanceExtension(const ir::MemberExpression *memberExpr);
215     void CheckImplicitSuper(ETSObjectType *classType, Signature *ctorSig);
216     void CheckThisOrSuperCallInConstructor(ETSObjectType *classType, Signature *ctorSig);
217     void CheckExpressionsInConstructor(const ArenaVector<const ir::Expression *> &arguments);
218     ArenaVector<const ir::Expression *> CheckMemberOrCallOrObjectExpressionInConstructor(const ir::Expression *arg);
219     void CheckValidInheritance(ETSObjectType *classType, ir::ClassDefinition *classDef);
220     void CheckProperties(ETSObjectType *classType, ir::ClassDefinition *classDef, varbinder::LocalVariable *it,
221                          varbinder::LocalVariable *found, ETSObjectType *interfaceFound);
222     void TransformProperties(ETSObjectType *classType);
223     void CheckGetterSetterProperties(ETSObjectType *classType);
224     void AddElementsToModuleObject(ETSObjectType *moduleObj, const util::StringView &str);
ComputeApparentType(Type * type)225     void ComputeApparentType(Type *type)
226     {
227         [[maybe_unused]] auto x = GetApparentType(type);
228     }
229     [[nodiscard]] Type *GetApparentType(Type *type);
230     [[nodiscard]] Type const *GetApparentType(Type const *type) const;
231     ETSObjectType *GetClosestCommonAncestor(ETSObjectType *source, ETSObjectType *target);
232     bool HasETSFunctionType(ir::TypeNode *typeAnnotation);
233 
234     // Type creation
235     ByteType *CreateByteType(int8_t value);
236     ETSBooleanType *CreateETSBooleanType(bool value);
237     DoubleType *CreateDoubleType(double value);
238     FloatType *CreateFloatType(float value);
239     IntType *CreateIntType(int32_t value);
240     LongType *CreateLongType(int64_t value);
241     ShortType *CreateShortType(int16_t value);
242     CharType *CreateCharType(char16_t value);
243     ETSBigIntType *CreateETSBigIntLiteralType(util::StringView value);
244     ETSStringType *CreateETSStringLiteralType(util::StringView value);
245     ETSArrayType *CreateETSArrayType(Type *elementType);
246     ETSIntEnumType *CreateEnumIntTypeFromEnumDeclaration(ir::TSEnumDeclaration const *const enumDecl);
247     ETSStringEnumType *CreateEnumStringTypeFromEnumDeclaration(ir::TSEnumDeclaration const *const enumDecl);
248 
249     Type *CreateETSUnionType(Span<Type *const> constituentTypes);
250     template <size_t N>
CreateETSUnionType(Type * const (& arr)[N])251     Type *CreateETSUnionType(Type *const (&arr)[N])  // NOLINT(modernize-avoid-c-arrays)
252     {
253         return CreateETSUnionType(Span(arr));
254     }
CreateETSUnionType(ArenaVector<Type * > && constituentTypes)255     Type *CreateETSUnionType(ArenaVector<Type *> &&constituentTypes)
256     {
257         return CreateETSUnionType(Span<Type *const>(constituentTypes));
258     }
259     ETSFunctionType *CreateETSFunctionType(Signature *signature);
260     ETSFunctionType *CreateETSFunctionType(Signature *signature, util::StringView name);
261     ETSFunctionType *CreateETSFunctionType(ir::ScriptFunction *func, Signature *signature, util::StringView name);
262     ETSFunctionType *CreateETSFunctionType(util::StringView name);
263     ETSFunctionType *CreateETSFunctionType(ArenaVector<Signature *> &signatures);
264     ETSExtensionFuncHelperType *CreateETSExtensionFuncHelperType(ETSFunctionType *classMethodType,
265                                                                  ETSFunctionType *extensionFunctionType);
266     ETSObjectType *FunctionTypeToFunctionalInterfaceType(Signature *signature);
267     ETSTypeParameter *CreateTypeParameter();
268     ETSObjectType *CreateETSObjectType(util::StringView name, ir::AstNode *declNode, ETSObjectFlags flags);
269     std::tuple<util::StringView, SignatureInfo *> CreateBuiltinArraySignatureInfo(ETSArrayType *arrayType, size_t dim);
270     Signature *CreateBuiltinArraySignature(ETSArrayType *arrayType, size_t dim);
271     IntType *CreateIntTypeFromType(Type *type);
272     std::tuple<Language, bool> CheckForDynamicLang(ir::AstNode *declNode, util::StringView assemblerName);
273     ETSObjectType *CreateNewETSObjectType(util::StringView name, ir::AstNode *declNode, ETSObjectFlags flags);
274 
275     Signature *CreateSignature(SignatureInfo *info, Type *returnType, ir::ScriptFunction *func);
276     Signature *CreateSignature(SignatureInfo *info, Type *returnType, util::StringView internalName);
277     SignatureInfo *CreateSignatureInfo();
278 
279     // Arithmetic
280     Type *NegateNumericType(Type *type, ir::Expression *node);
281     Type *BitwiseNegateNumericType(Type *type, ir::Expression *node);
282     bool CheckBinaryOperatorForBigInt(Type *left, Type *right, lexer::TokenType op);
283     [[nodiscard]] bool CheckBinaryPlusMultDivOperandsForUnionType(const Type *leftType, const Type *rightType,
284                                                                   const ir::Expression *left,
285                                                                   const ir::Expression *right);
286     std::tuple<Type *, Type *> CheckBinaryOperator(ir::Expression *left, ir::Expression *right, ir::Expression *expr,
287                                                    lexer::TokenType operationType, lexer::SourcePosition pos,
288                                                    bool forcePromotion = false);
289     checker::Type *CheckBinaryOperatorMulDivMod(
290         std::tuple<ir::Expression *, ir::Expression *, lexer::TokenType, lexer::SourcePosition> op, bool isEqualOp,
291         std::tuple<checker::Type *, checker::Type *, Type *, Type *> types);
292     checker::Type *CheckBinaryOperatorPlusForEnums(const checker::Type *const leftType,
293                                                    const checker::Type *const rightType);
294     checker::Type *CheckBinaryOperatorPlus(
295         std::tuple<ir::Expression *, ir::Expression *, lexer::TokenType, lexer::SourcePosition> op, bool isEqualOp,
296         std::tuple<checker::Type *, checker::Type *, Type *, Type *> types);
297     checker::Type *CheckBinaryOperatorShift(
298         std::tuple<ir::Expression *, ir::Expression *, lexer::TokenType, lexer::SourcePosition> op, bool isEqualOp,
299         std::tuple<checker::Type *, checker::Type *, Type *, Type *> types);
300     checker::Type *CheckBinaryOperatorBitwise(
301         std::tuple<ir::Expression *, ir::Expression *, lexer::TokenType, lexer::SourcePosition> op, bool isEqualOp,
302         std::tuple<checker::Type *, checker::Type *, Type *, Type *> types);
303     checker::Type *CheckBinaryOperatorLogical(ir::Expression *left, ir::Expression *right, ir::Expression *expr,
304                                               lexer::SourcePosition pos, checker::Type *leftType,
305                                               checker::Type *rightType, Type *unboxedL, Type *unboxedR);
306     std::tuple<Type *, Type *> CheckBinaryOperatorStrictEqual(ir::Expression *left, lexer::TokenType operationType,
307                                                               lexer::SourcePosition pos, checker::Type *leftType,
308                                                               checker::Type *rightType);
309     std::optional<std::tuple<Type *, Type *>> CheckBinaryOperatorEqualError(checker::Type *const leftType,
310                                                                             checker::Type *const rightType,
311                                                                             checker::Type *tsType,
312                                                                             lexer::SourcePosition pos);
313     std::tuple<Type *, Type *> CheckBinaryOperatorEqual(ir::Expression *left, ir::Expression *right,
314                                                         lexer::TokenType operationType, lexer::SourcePosition pos,
315                                                         checker::Type *leftType, checker::Type *rightType,
316                                                         Type *unboxedL, Type *unboxedR);
317     std::tuple<Type *, Type *> CheckBinaryOperatorEqualDynamic(ir::Expression *left, ir::Expression *right,
318                                                                lexer::SourcePosition pos);
319     std::tuple<Type *, Type *> CheckBinaryOperatorLessGreater(ir::Expression *left, ir::Expression *right,
320                                                               lexer::TokenType operationType, lexer::SourcePosition pos,
321                                                               bool isEqualOp, checker::Type *leftType,
322                                                               checker::Type *rightType, Type *unboxedL, Type *unboxedR);
323     std::tuple<Type *, Type *> CheckBinaryOperatorInstanceOf(lexer::SourcePosition pos, checker::Type *leftType,
324                                                              checker::Type *rightType);
325     checker::Type *CheckBinaryOperatorNullishCoalescing(ir::Expression *left, ir::Expression *right,
326                                                         lexer::SourcePosition pos);
327     bool AdjustNumberLiteralType(ir::NumberLiteral *literal, Type *literalType, Type *otherType);
328 
329     Type *HandleArithmeticOperationOnTypes(Type *left, Type *right, lexer::TokenType operationType);
330     Type *HandleBitwiseOperationOnTypes(Type *left, Type *right, lexer::TokenType operationType);
331     void FlagExpressionWithUnboxing(Type *type, Type *unboxedType, ir::Expression *typeExpression);
332     template <typename ValueType>
333     Type *PerformArithmeticOperationOnTypes(Type *left, Type *right, lexer::TokenType operationType);
334 
335     Type *HandleRelationOperationOnTypes(Type *left, Type *right, lexer::TokenType operationType);
336     template <typename TargetType>
337     Type *PerformRelationOperationOnTypes(Type *left, Type *right, lexer::TokenType operationType);
338 
339     // Function
340     bool NeedTypeInference(const ir::ScriptFunction *lambda);
341     std::vector<bool> FindTypeInferenceArguments(const ArenaVector<ir::Expression *> &arguments);
342     void InferTypesForLambda(ir::ScriptFunction *lambda, ir::ETSFunctionType *calleeType);
343     bool TypeInference(Signature *signature, const ArenaVector<ir::Expression *> &arguments,
344                        TypeRelationFlag flags = TypeRelationFlag::NONE);
345     bool CheckLambdaTypeAnnotation(ir::AstNode *typeAnnotation, ir::ArrowFunctionExpression *arrowFuncExpr,
346                                    Type *parameterType, TypeRelationFlag flags);
347     bool CheckLambdaInvocable(ir::AstNode *typeAnnotation, ir::ArrowFunctionExpression *arrowFuncExpr,
348                               Type *parameterType, TypeRelationFlag flags);
349     bool CheckLambdaAssignable(ir::Expression *param, ir::ScriptFunction *lambda);
350     bool CheckLambdaAssignableUnion(ir::AstNode *typeAnn, ir::ScriptFunction *lambda);
351     bool IsCompatibleTypeArgument(ETSTypeParameter *typeParam, Type *typeArgument, const Substitution *substitution);
NewSubstitution()352     Substitution *NewSubstitution()
353     {
354         return Allocator()->New<Substitution>(Allocator()->Adapter());
355     }
CopySubstitution(const Substitution * src)356     Substitution *CopySubstitution(const Substitution *src)
357     {
358         return Allocator()->New<Substitution>(*src);
359     }
360     static void EmplaceSubstituted(Substitution *substitution, ETSTypeParameter *tparam, Type *typeArg);
361     [[nodiscard]] bool EnhanceSubstitutionForType(const ArenaVector<Type *> &typeParams, Type *paramType,
362                                                   Type *argumentType, Substitution *substitution);
363     [[nodiscard]] bool EnhanceSubstitutionForReadonly(const ArenaVector<Type *> &typeParams, ETSReadonlyType *paramType,
364                                                       Type *argumentType, Substitution *substitution);
365     [[nodiscard]] bool EnhanceSubstitutionForObject(const ArenaVector<Type *> &typeParams, ETSObjectType *paramType,
366                                                     Type *argumentType, Substitution *substitution);
367     [[nodiscard]] bool EnhanceSubstitutionForUnion(const ArenaVector<Type *> &typeParams, ETSUnionType *paramUn,
368                                                    Type *argumentType, Substitution *substitution);
369     [[nodiscard]] bool EnhanceSubstitutionForArray(const ArenaVector<Type *> &typeParams, ETSArrayType *paramType,
370                                                    Type *argumentType, Substitution *substitution);
371     [[nodiscard]] bool EnhanceSubstitutionForGenericType(const ArenaVector<Type *> &typeParams, const Type *argType,
372                                                          const Type *paramType, Substitution *substitution);
373     [[nodiscard]] static bool HasTypeArgsOfObject(Type *argType, Type *paramType);
374     [[nodiscard]] bool InsertTypeIntoSubstitution(const ArenaVector<Type *> &typeParams, const Type *typeParam,
375                                                   const size_t index, Substitution *substitution, Type *objectParam);
376     std::pair<ArenaVector<Type *>, bool> CreateUnconstrainedTypeParameters(
377         ir::TSTypeParameterDeclaration const *typeParams);
378     void AssignTypeParameterConstraints(ir::TSTypeParameterDeclaration const *typeParams);
379     Signature *ValidateParameterlessConstructor(Signature *signature, const lexer::SourcePosition &pos,
380                                                 TypeRelationFlag flags);
381     Signature *CollectParameterlessConstructor(ArenaVector<Signature *> &signatures, const lexer::SourcePosition &pos,
382                                                TypeRelationFlag resolveFlags = TypeRelationFlag::NONE);
383     Signature *ValidateSignature(
384         std::tuple<Signature *, const ir::TSTypeParameterInstantiation *, TypeRelationFlag> info,
385         const ArenaVector<ir::Expression *> &arguments, const lexer::SourcePosition &pos,
386         const std::vector<bool> &argTypeInferenceRequired);
387     void MaybeSubstituteLambdaArgumentsInFunctionCall(ir::CallExpression *callExpr);
388     void MaybeSubstituteLambdaArgumentsInFunctionCallHelper(ir::CallExpression *callExpr, ir::Identifier *ident);
389     void MaybeSubstituteLambdaArguments(const ArenaVector<ir::Expression *> &params, ir::CallExpression *callExpr);
390     bool ValidateSignatureRequiredParams(Signature *substitutedSig, const ArenaVector<ir::Expression *> &arguments,
391                                          TypeRelationFlag flags, const std::vector<bool> &argTypeInferenceRequired,
392                                          bool throwError);
393     bool ValidateSignatureInvocationContext(Signature *substitutedSig, ir::Expression *argument, const Type *targetType,
394                                             std::size_t index, TypeRelationFlag flags);
395     bool CheckInvokable(Signature *substitutedSig, ir::Expression *argument, std::size_t index, TypeRelationFlag flags);
396     bool CheckOptionalLambdaFunction(ir::Expression *argument, Signature *substitutedSig, std::size_t index);
397     bool ValidateArgumentAsIdentifier(const ir::Identifier *identifier);
398     bool ValidateSignatureRestParams(Signature *substitutedSig, const ArenaVector<ir::Expression *> &arguments,
399                                      TypeRelationFlag flags, bool throwError);
400     Signature *ValidateSignatures(ArenaVector<Signature *> &signatures,
401                                   const ir::TSTypeParameterInstantiation *typeArguments,
402                                   const ArenaVector<ir::Expression *> &arguments, const lexer::SourcePosition &pos,
403                                   std::string_view signatureKind,
404                                   TypeRelationFlag resolveFlags = TypeRelationFlag::NONE);
405     Signature *FindMostSpecificSignature(const ArenaVector<Signature *> &signatures,
406                                          const ArenaMultiMap<size_t, Signature *> &bestSignaturesForParameter,
407                                          size_t paramCount);
408     void SearchAmongMostSpecificTypes(
409         Type *&mostSpecificType, Signature *&prevSig,
410         std::tuple<const lexer::SourcePosition &, size_t, size_t, size_t, Signature *> info, bool lookForClassType);
411     ArenaMultiMap<size_t, Signature *> GetSuitableSignaturesForParameter(
412         const std::vector<bool> &argTypeInferenceRequired, size_t paramCount, ArenaVector<Signature *> &signatures,
413         const lexer::SourcePosition &pos, size_t argumentsSize);
414     Signature *ChooseMostSpecificSignature(ArenaVector<Signature *> &signatures,
415                                            const std::vector<bool> &argTypeInferenceRequired,
416                                            const lexer::SourcePosition &pos, size_t argumentsSize = ULONG_MAX);
417     Signature *ResolveCallExpressionAndTrailingLambda(ArenaVector<Signature *> &signatures,
418                                                       ir::CallExpression *callExpr, const lexer::SourcePosition &pos,
419                                                       TypeRelationFlag throwFlag = TypeRelationFlag::NONE);
420     Signature *ResolveConstructExpression(ETSObjectType *type, const ArenaVector<ir::Expression *> &arguments,
421                                           const lexer::SourcePosition &pos);
422     void CheckObjectLiteralArguments(Signature *sig, ArenaVector<ir::Expression *> const &arguments);
423     Signature *ComposeSignature(ir::ScriptFunction *func, SignatureInfo *signatureInfo, Type *returnType,
424                                 varbinder::Variable *nameVar);
425     Type *ComposeReturnType(ir::ScriptFunction *func);
426     SignatureInfo *ComposeSignatureInfo(ir::ScriptFunction *func);
427     ArenaVector<SignatureInfo *> ComposeSignatureInfosForArrowFunction(ir::ArrowFunctionExpression *arrowFuncExpr);
428     void SetParamForSignatureInfoOfArrowFunction(SignatureInfo *signatureInfo, ir::ETSParameterExpression *param);
429     void ValidateMainSignature(ir::ScriptFunction *func);
430     checker::ETSFunctionType *BuildFunctionSignature(ir::ScriptFunction *func, bool isConstructSig = false);
431     checker::ETSFunctionType *BuildMethodSignature(ir::MethodDefinition *method);
432     Signature *CheckEveryAbstractSignatureIsOverridden(ETSFunctionType *target, ETSFunctionType *source);
433     static Signature *GetSignatureFromMethodDefinition(const ir::MethodDefinition *methodDef);
434     void CheckIdenticalOverloads(ETSFunctionType *func, ETSFunctionType *overload,
435                                  const ir::MethodDefinition *currentFunc);
436     Signature *AdjustForTypeParameters(Signature *source, Signature *target);
437     void ThrowOverrideError(Signature *signature, Signature *overriddenSignature, const OverrideErrorCode &errorCode);
438     void CheckOverride(Signature *signature);
439     bool CheckOverride(Signature *signature, ETSObjectType *site);
440     OverrideErrorCode CheckOverride(Signature *signature, Signature *other);
441     bool IsMethodOverridesOther(Signature *base, Signature *derived);
442     bool IsOverridableIn(Signature *signature);
443     [[nodiscard]] bool AreOverrideEquivalent(Signature *s1, Signature *s2);
444     [[nodiscard]] bool IsReturnTypeSubstitutable(Signature *s1, Signature *s2);
445     void CheckThrowMarkers(Signature *source, Signature *target);
446     void ValidateSignatureAccessibility(ETSObjectType *callee, const ir::CallExpression *callExpr, Signature *signature,
447                                         const lexer::SourcePosition &pos, char const *errorMessage = nullptr);
448     void CheckCapturedVariables();
449     void CheckCapturedVariableInSubnodes(ir::AstNode *node, varbinder::Variable *var);
450     void CheckCapturedVariable(ir::AstNode *node, varbinder::Variable *var);
451     void CreateAsyncProxyMethods(ir::ClassDefinition *classDef);
452     ir::MethodDefinition *CreateAsyncImplMethod(ir::MethodDefinition *asyncMethod, ir::ClassDefinition *classDef);
453     ir::MethodDefinition *CreateAsyncProxy(ir::MethodDefinition *asyncMethod, ir::ClassDefinition *classDef,
454                                            bool createDecl = true);
455     ir::MethodDefinition *CreateMethod(const util::StringView &name, ir::ModifierFlags modifiers,
456                                        ir::ScriptFunctionFlags flags, ArenaVector<ir::Expression *> &&params,
457                                        varbinder::FunctionParamScope *paramScope, ir::TypeNode *returnType,
458                                        ir::AstNode *body);
459     varbinder::FunctionParamScope *CopyParams(const ArenaVector<ir::Expression *> &params,
460                                               ArenaVector<ir::Expression *> &outParams);
461     void ReplaceScope(ir::AstNode *root, ir::AstNode *oldNode, varbinder::Scope *newScope);
462 
463     // Helpers
464     size_t ComputeProxyMethods(ir::ClassDefinition *klass);
465     ir::ModifierFlags GetFlagsForProxyLambda(bool isStatic);
466     ir::ScriptFunction *CreateProxyFunc(ir::ArrowFunctionExpression *lambda, ArenaVector<ir::AstNode *> &captured,
467                                         bool isStatic);
468     ir::AstNode *GetProxyMethodBody(ir::ArrowFunctionExpression *lambda, varbinder::FunctionScope *scope);
469     static std::string GetAsyncImplName(const util::StringView &name);
470     static std::string GetAsyncImplName(ir::MethodDefinition *asyncMethod);
471     static bool IsAsyncImplMethod(ir::MethodDefinition const *method);
472     std::vector<util::StringView> GetNameForSynteticObjectType(const util::StringView &source);
473     template <checker::PropertyType TYPE>
474     void BindingsModuleObjectAddProperty(checker::ETSObjectType *moduleObjType, ir::ETSImportDeclaration *importDecl,
475                                          const varbinder::Scope::VariableMap &bindings);
476     util::StringView FindPropNameForNamespaceImport(const util::StringView &originalName);
477     void SetPropertiesForModuleObject(checker::ETSObjectType *moduleObjType, const util::StringView &importPath,
478                                       ir::ETSImportDeclaration *importDecl = nullptr);
479     void SetrModuleObjectTsType(ir::Identifier *local, checker::ETSObjectType *moduleObjType);
480     Type *GetReferencedTypeFromBase(Type *baseType, ir::Expression *name);
481     Type *GetReferencedTypeBase(ir::Expression *name);
482     Type *GetTypeFromInterfaceReference(varbinder::Variable *var);
483     Type *GetTypeFromTypeAliasReference(varbinder::Variable *var);
484     Type *GetTypeFromClassReference(varbinder::Variable *var);
485     void ValidateGenericTypeAliasForClonedNode(ir::TSTypeAliasDeclaration *typeAliasNode,
486                                                const ir::TSTypeParameterInstantiation *exactTypeParams);
487     Type *HandleTypeAlias(ir::Expression *name, const ir::TSTypeParameterInstantiation *typeParams);
488     Type *GetTypeFromEnumReference(varbinder::Variable *var);
489     Type *GetTypeFromTypeParameterReference(varbinder::LocalVariable *var, const lexer::SourcePosition &pos);
490     Type *GetNonConstantTypeFromPrimitiveType(Type *type) const;
491     bool IsNullLikeOrVoidExpression(const ir::Expression *expr) const;
492     bool IsConstantExpression(ir::Expression *expr, Type *type);
493     void ValidateUnaryOperatorOperand(varbinder::Variable *variable);
494     void InferAliasLambdaType(ir::TypeNode *localTypeAnnotation, ir::ArrowFunctionExpression *init);
495     bool TestUnionType(Type *type, TypeFlag test);
496     std::tuple<Type *, bool> ApplyBinaryOperatorPromotion(Type *left, Type *right, TypeFlag test,
497                                                           bool doPromotion = true);
498     checker::Type *ApplyConditionalOperatorPromotion(checker::ETSChecker *checker, checker::Type *unboxedL,
499                                                      checker::Type *unboxedR);
500     Type *ApplyUnaryOperatorPromotion(Type *type, bool createConst = true, bool doPromotion = true,
501                                       bool isCondExpr = false);
502     Type *HandleBooleanLogicalOperators(Type *leftType, Type *rightType, lexer::TokenType tokenType);
503     Type *HandleBooleanLogicalOperatorsExtended(Type *leftType, Type *rightType, ir::BinaryExpression *expr);
504 
505     checker::Type *FixOptionalVariableType(varbinder::Variable *const bindingVar, ir::ModifierFlags flags);
506     void CheckEnumType(ir::Expression *init, checker::Type *initType, const util::StringView &varName);
507     checker::Type *CheckVariableDeclaration(ir::Identifier *ident, ir::TypeNode *typeAnnotation, ir::Expression *init,
508                                             ir::ModifierFlags flags);
509     void CheckAnnotationTypeForVariableDeclaration(checker::Type *annotationType, bool isUnionFunction,
510                                                    ir::Expression *init, checker::Type *initType);
511     void CheckTruthinessOfType(ir::Expression *expr);
512 
513     void CheckNonNullish(ir::Expression const *expr);
514     Type *GetNonNullishType(Type *type);
515     Type *RemoveNullType(Type *type);
516     Type *RemoveUndefinedType(Type *type);
517     std::pair<Type *, Type *> RemoveNullishTypes(Type *type);
518 
519     void ConcatConstantString(util::UString &target, Type *type);
520     Type *HandleStringConcatenation(Type *leftType, Type *rightType);
521     Type *ResolveIdentifier(ir::Identifier *ident);
522     ETSFunctionType *FindFunctionInVectorGivenByName(util::StringView name, ArenaVector<ETSFunctionType *> &list);
523     void MergeComputedAbstracts(ArenaVector<ETSFunctionType *> &merged, ArenaVector<ETSFunctionType *> &current);
524     void MergeSignatures(ETSFunctionType *target, ETSFunctionType *source);
525     ir::AstNode *FindAncestorGivenByType(ir::AstNode *node, ir::AstNodeType type, const ir::AstNode *endNode = nullptr);
526     util::StringView GetContainingObjectNameFromSignature(Signature *signature);
527     bool IsFunctionContainsSignature(ETSFunctionType *funcType, Signature *signature);
528     void CheckFunctionContainsClashingSignature(const ETSFunctionType *funcType, Signature *signature);
529     bool IsTypeBuiltinType(const Type *type) const;
IsReferenceType(const Type * type)530     static bool IsReferenceType(const Type *type)
531     {
532         return type->IsETSReferenceType();
533     }
534     const ir::AstNode *FindJumpTarget(ir::AstNode *node);
535     void ValidatePropertyAccess(varbinder::Variable *var, ETSObjectType *obj, const lexer::SourcePosition &pos);
536     varbinder::VariableFlags GetAccessFlagFromNode(const ir::AstNode *node);
537     Type *CheckSwitchDiscriminant(ir::Expression *discriminant);
538     Type *ETSBuiltinTypeAsPrimitiveType(Type *objectType);
539     Type *ETSBuiltinTypeAsConditionalType(Type *objectType);
540     Type *PrimitiveTypeAsETSBuiltinType(Type *objectType);
541     void AddBoxingUnboxingFlagsToNode(ir::AstNode *node, Type *boxingUnboxingType);
542     ir::BoxingUnboxingFlags GetBoxingFlag(Type *boxingType);
543     ir::BoxingUnboxingFlags GetUnboxingFlag(Type const *unboxingType) const;
544     util::StringView TypeToName(Type *type) const;
545     Type *MaybeBoxExpression(ir::Expression *expr);
546     Type *MaybeUnboxExpression(ir::Expression *expr);
547     Type *MaybePromotedBuiltinType(Type *type) const;
548     Type const *MaybePromotedBuiltinType(Type const *type) const;
549     Type *MaybePrimitiveBuiltinType(Type *type) const;
550     void CheckForSameSwitchCases(ArenaVector<ir::SwitchCaseStatement *> const &cases);
551     std::string GetStringFromIdentifierValue(checker::Type *caseType) const;
552     bool CompareIdentifiersValuesAreDifferent(ir::Expression *compareValue, const std::string &caseValue);
553     void CheckIdentifierSwitchCase(ir::Expression *currentCase, ir::Expression *compareCase,
554                                    const lexer::SourcePosition &pos);
555     std::string GetStringFromLiteral(ir::Expression *caseTest) const;
556     varbinder::Variable *FindVariableInFunctionScope(util::StringView name,
557                                                      const varbinder::ResolveBindingOptions options);
558     std::pair<const varbinder::Variable *, const ETSObjectType *> FindVariableInClassOrEnclosing(
559         util::StringView name, const ETSObjectType *classType);
560     varbinder::Variable *FindVariableInGlobal(const ir::Identifier *identifier,
561                                               const varbinder::ResolveBindingOptions options);
562     void ExtraCheckForResolvedError(ir::Identifier *ident);
563     void ValidateResolvedIdentifier(ir::Identifier *ident, varbinder::Variable *resolved);
564     static bool IsVariableStatic(const varbinder::Variable *var);
565     static bool IsVariableGetterSetter(const varbinder::Variable *var);
566     bool IsSameDeclarationType(varbinder::LocalVariable *target, varbinder::LocalVariable *compare);
567     void SaveCapturedVariable(varbinder::Variable *var, ir::Identifier *ident);
568     bool SaveCapturedVariableInLocalClass(varbinder::Variable *var, ir::Identifier *ident);
569     void AddBoxingFlagToPrimitiveType(TypeRelation *relation, Type *target);
570     void AddUnboxingFlagToPrimitiveType(TypeRelation *relation, Type *source, Type *self);
571     void CheckUnboxedTypeWidenable(TypeRelation *relation, Type *target, Type *self);
572     void CheckUnboxedTypesAssignable(TypeRelation *relation, Type *source, Type *target);
573     void CheckBoxedSourceTypeAssignable(TypeRelation *relation, Type *source, Type *target);
574     void CheckUnboxedSourceTypeWithWideningAssignable(TypeRelation *relation, Type *source, Type *target);
575     void CheckValidGenericTypeParameter(Type *argType, const lexer::SourcePosition &pos);
576     void ValidateResolvedProperty(varbinder::LocalVariable **property, const ETSObjectType *target,
577                                   const ir::Identifier *ident, PropertySearchFlags flags);
578     bool IsValidSetterLeftSide(const ir::MemberExpression *member);
579     bool CheckRethrowingParams(const ir::AstNode *ancestorFunction, const ir::AstNode *node);
580     void CheckThrowingStatements(ir::AstNode *node);
581     bool CheckThrowingPlacement(ir::AstNode *node, const ir::AstNode *ancestorFunction);
582     void CheckNumberOfTypeArguments(ETSObjectType *type, ir::TSTypeParameterInstantiation *typeArgs,
583                                     const lexer::SourcePosition &pos);
584     ir::BlockStatement *FindFinalizerOfTryStatement(ir::AstNode *startFrom, const ir::AstNode *p);
585     void CheckExceptionClauseType(const std::vector<checker::ETSObjectType *> &exceptions, ir::CatchClause *catchClause,
586                                   checker::Type *clauseType);
587     void CheckRethrowingFunction(ir::ScriptFunction *func);
588     ETSObjectType *GetRelevantArgumentedTypeFromChild(ETSObjectType *child, ETSObjectType *target);
589     util::StringView GetHashFromTypeArguments(const ArenaVector<Type *> &typeArgTypes);
590     util::StringView GetHashFromSubstitution(const Substitution *substitution);
591     util::StringView GetHashFromFunctionType(ir::ETSFunctionType *type);
592     static ETSObjectType *GetOriginalBaseType(Type *object);
593     void SetArrayPreferredTypeForNestedMemberExpressions(ir::MemberExpression *expr, Type *annotationType);
594     bool ExtensionETSFunctionType(checker::Type *type);
595     void ValidateTupleMinElementSize(ir::ArrayExpression *arrayExpr, ETSTupleType *tuple);
596     void ModifyPreferredType(ir::ArrayExpression *arrayExpr, Type *newPreferredType);
597     Type *SelectGlobalIntegerTypeForNumeric(Type *type);
598     Type *TryGettingFunctionTypeFromInvokeFunction(Type *type);
599     ir::ClassProperty *ClassPropToImplementationProp(ir::ClassProperty *classProp, varbinder::ClassScope *scope);
600     ir::Expression *GenerateImplicitInstantiateArg(varbinder::LocalVariable *instantiateMethod,
601                                                    const std::string &className);
602     void GenerateGetterSetterBody(ArenaVector<ir::Statement *> &stmts, ArenaVector<ir::Expression *> &params,
603                                   ir::ClassProperty *field, varbinder::FunctionParamScope *paramScope, bool isSetter);
604     static ir::MethodDefinition *GenerateDefaultGetterSetter(ir::ClassProperty *property, ir::ClassProperty *field,
605                                                              varbinder::ClassScope *scope, bool isSetter,
606                                                              ETSChecker *checker);
607     void GenerateGetterSetterPropertyAndMethod(ir::ClassProperty *originalProp, ETSObjectType *classType);
608     ETSObjectType *GetImportSpecifierObjectType(ir::ETSImportDeclaration *importDecl, ir::Identifier *ident);
609     void ImportNamespaceObjectTypeAddReExportType(ir::ETSImportDeclaration *importDecl,
610                                                   checker::ETSObjectType *lastObjectType, ir::Identifier *ident);
611     checker::ETSObjectType *CreateSyntheticType(util::StringView const &syntheticName,
612                                                 checker::ETSObjectType *lastObjectType, ir::Identifier *id);
613     bool CheckValidUnionEqual(checker::Type *const leftType, checker::Type *const rightType);
614     bool CheckValidEqualReferenceType(checker::Type *const leftType, checker::Type *const rightType);
615     void CheckVoidAnnotation(const ir::ETSPrimitiveType *typeAnnotation);
616 
617     // Utility type handler functions
618     ir::TypeNode *GetUtilityTypeTypeParamNode(const ir::TSTypeParameterInstantiation *typeParams,
619                                               const std::string_view &utilityTypeName);
620     Type *HandleUtilityTypeParameterNode(const ir::TSTypeParameterInstantiation *typeParams,
621                                          const std::string_view &utilityType);
622     // Partial
623     Type *HandlePartialType(Type *typeToBePartial);
624     Type *HandlePartialTypeNode(ir::TypeNode *typeParamNode);
625     ir::ClassProperty *CreateNullishProperty(ir::ClassProperty *prop, ir::ClassDefinition *newClassDefinition);
626     ir::ClassDefinition *CreatePartialClassDeclaration(ir::ClassDefinition *newClassDefinition,
627                                                        const ir::ClassDefinition *classDef);
628     void CreateConstructorForPartialType(ir::ClassDefinition *partialClassDef, checker::ETSObjectType *partialType,
629                                          varbinder::RecordTable *recordTable);
630     ir::ClassDefinition *CreateClassPrototype(util::StringView name, parser::Program *classDeclProgram);
631     varbinder::Variable *SearchNamesInMultiplePrograms(const std::set<const parser::Program *> &programs,
632                                                        const std::set<util::StringView> &classNamesToFind);
633     util::StringView GetQualifiedClassName(const parser::Program *classDefProgram, util::StringView className);
634     Type *HandleUnionForPartialType(ETSUnionType *typeToBePartial);
635     Type *CreatePartialTypeClassDef(ir::ClassDefinition *partialClassDef, ir::ClassDefinition *classDef,
636                                     const Type *typeToBePartial, varbinder::RecordTable *recordTableToUse);
637     std::pair<ir::ScriptFunction *, ir::Identifier *> CreateScriptFunctionForConstructor(
638         varbinder::FunctionScope *scope);
639     ir::MethodDefinition *CreateNonStaticClassInitializer(varbinder::ClassScope *classScope,
640                                                           varbinder::RecordTable *recordTable);
641     // Readonly
642     Type *HandleReadonlyType(const ir::TSTypeParameterInstantiation *typeParams);
643     Type *GetReadonlyType(Type *type);
644     void MakePropertiesReadonly(ETSObjectType *classType);
645     // Required
646     Type *HandleRequiredType(Type *typeToBeRequired);
647     Type *HandleRequiredTypeNode(ir::TypeNode *typeParamNode);
648     void MakePropertiesNonNullish(ETSObjectType *classType);
649     template <PropertyType PROP_TYPE>
650     void MakePropertyNonNullish(ETSObjectType *classType, varbinder::LocalVariable *prop);
651     void ValidateObjectLiteralForRequiredType(const ETSObjectType *requiredType,
652                                               const ir::ObjectExpression *initObjExpr);
653 
654     // Smart cast support
655     [[nodiscard]] checker::Type *ResolveSmartType(checker::Type *sourceType, checker::Type *targetType);
656     [[nodiscard]] std::pair<Type *, Type *> CheckTestNullishCondition(Type *testedType, Type *actualType, bool strict);
657     [[nodiscard]] std::pair<Type *, Type *> CheckTestObjectCondition(ETSObjectType *testedType, Type *actualType,
658                                                                      bool strict);
659     [[nodiscard]] std::pair<Type *, Type *> CheckTestObjectCondition(ETSArrayType *testedType, Type *actualType);
660 
661     void ApplySmartCast(varbinder::Variable const *variable, checker::Type *smartType) noexcept;
662 
663     bool IsInLocalClass(const ir::AstNode *node) const;
664     // Exception
665     ETSObjectType *CheckExceptionOrErrorType(checker::Type *type, lexer::SourcePosition pos);
666 
667     static Type *TryToInstantiate(Type *type, ArenaAllocator *allocator, TypeRelation *relation,
668                                   GlobalTypesHolder *globalTypes);
669 
670     // Dynamic interop
671     template <typename T>
672     Signature *ResolveDynamicCallExpression(ir::Expression *callee, const ArenaVector<T *> &arguments, Language lang,
673                                             bool isConstruct);
674     ir::ClassProperty *CreateStaticReadonlyField(const char *name);
675     void BuildDynamicImportClass();
676     void BuildLambdaObjectClass(ETSObjectType *functionalInterface, ir::TypeNode *retTypeAnnotation);
677     // Trailing lambda
678     void EnsureValidCurlyBrace(ir::CallExpression *callExpr);
679 
680     // Extension function
681     void HandleUpdatedCallExpressionNode(ir::CallExpression *callExpr);
682 
683     // Static invoke
684     void CheckInvokeMethodsLegitimacy(ETSObjectType *classType);
685     checker::Type *CheckArrayElements(ir::ArrayExpression *init);
686     void ResolveReturnStatement(checker::Type *funcReturnType, checker::Type *argumentType,
687                                 ir::ScriptFunction *containingFunc, ir::ReturnStatement *st);
688 
DynamicCallNames(bool isConstruct)689     auto *DynamicCallNames(bool isConstruct)
690     {
691         return &dynamicCallNames_[static_cast<uint32_t>(isConstruct)];
692     }
693 
DynamicCallNames(bool isConstruct)694     const auto *DynamicCallNames(bool isConstruct) const
695     {
696         return &dynamicCallNames_[static_cast<uint32_t>(isConstruct)];
697     }
698 
Mutex()699     std::recursive_mutex *Mutex()
700     {
701         return &mtx_;
702     }
703 
704     template <typename T, typename... Args>
AllocNode(Args &&...args)705     T *AllocNode(Args &&...args)
706     {
707         // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
708         return util::NodeAllocator::ForceSetParent<T>(Allocator(), std::forward<Args>(args)...);
709     }
710 
711     ArenaVector<ConstraintCheckRecord> &PendingConstraintCheckRecords();
712     size_t &ConstraintCheckScopesCount();
713 
714     ETSObjectType *GetCachedFunctionalInterface(ir::ETSFunctionType *type);
715     void CacheFunctionalInterface(ir::ETSFunctionType *type, ETSObjectType *ifaceType);
716     void CollectReturnStatements(ir::AstNode *parent);
717     ir::ETSParameterExpression *AddParam(util::StringView name, ir::TypeNode *type);
718 
719     [[nodiscard]] ir::ScriptFunction *FindFunction(ir::TSEnumDeclaration const *const enumDecl,
720                                                    const std::string_view &name);
721 
722     using ClassBuilder = std::function<void(ArenaVector<ir::AstNode *> *)>;
723     using ClassInitializerBuilder =
724         std::function<void(ArenaVector<ir::Statement *> *, ArenaVector<ir::Expression *> *)>;
725     using MethodBuilder = std::function<void(ArenaVector<ir::Statement *> *, ArenaVector<ir::Expression *> *, Type **)>;
726 
727     ir::ClassStaticBlock *CreateClassStaticInitializer(const ClassInitializerBuilder &builder,
728                                                        ETSObjectType *type = nullptr);
729     ir::MethodDefinition *CreateClassInstanceInitializer(const ClassInitializerBuilder &builder,
730                                                          ETSObjectType *type = nullptr);
731     ir::MethodDefinition *CreateClassMethod(std::string_view name, ir::ScriptFunctionFlags funcFlags,
732                                             ir::ModifierFlags modifierFlags, const MethodBuilder &builder);
733     ir::ClassDeclaration *BuildClass(util::StringView name, const ClassBuilder &builder);
734 
735 private:
736     ETSEnumType::Method MakeMethod(ir::TSEnumDeclaration const *const enumDecl, const std::string_view &name,
737                                    bool buildPorxyParam, Type *returnType, bool buildProxy = true);
738 
739     std::pair<const ir::Identifier *, ir::TypeNode *> GetTargetIdentifierAndType(ir::Identifier *ident);
740     [[noreturn]] void ThrowError(ir::Identifier *ident);
741     void LogOperatorCannotBeApplied(lexer::TokenType operationType, checker::Type *const leftType,
742                                     checker::Type *const rightType, lexer::SourcePosition pos);
743     void WrongContextErrorClassifyByType(ir::Identifier *ident, varbinder::Variable *resolved);
744     void CheckEtsFunctionType(ir::Identifier *ident, ir::Identifier const *id, ir::TypeNode const *annotation);
745     [[noreturn]] void NotResolvedError(ir::Identifier *const ident, const varbinder::Variable *classVar,
746                                        const ETSObjectType *classType);
747     void ValidateCallExpressionIdentifier(ir::Identifier *const ident, varbinder::Variable *const resolved,
748                                           Type *const type);
749     void ValidateNewClassInstanceIdentifier(ir::Identifier *const ident, varbinder::Variable *const resolved);
750     void ValidateMemberIdentifier(ir::Identifier *const ident, varbinder::Variable *const resolved, Type *const type);
751     void ValidatePropertyOrDeclaratorIdentifier(ir::Identifier *const ident, varbinder::Variable *const resolved);
752     void ValidateAssignmentIdentifier(ir::Identifier *const ident, varbinder::Variable *const resolved,
753                                       Type *const type);
754     bool ValidateBinaryExpressionIdentifier(ir::Identifier *const ident, Type *const type);
755     void ValidateGetterSetter(const ir::MemberExpression *const memberExpr, const varbinder::LocalVariable *const prop,
756                               PropertySearchFlags searchFlag);
757     ir::ClassProperty *FindClassProperty(const ETSObjectType *objectType, const ETSFunctionType *propType);
758     bool IsInitializedProperty(const ir::ClassDefinition *classDefinition, const ir::ClassProperty *prop);
759     bool FindPropertyInAssignment(const ir::AstNode *it, const std::string &targetName);
760     void ValidateReadonlyProperty(const ir::MemberExpression *memberExpr, const ETSFunctionType *propType,
761                                   lexer::SourcePosition sourcePos);
762     void ValidateVarDeclaratorOrClassProperty(const ir::MemberExpression *memberExpr, varbinder::LocalVariable *prop);
763     void ResolveMemberReferenceValidate(varbinder::LocalVariable *prop, PropertySearchFlags searchFlag,
764                                         const ir::MemberExpression *const memberExpr);
765     std::tuple<bool, bool> IsResolvedAndValue(const ir::Expression *expr, Type *type) const;
766     PropertySearchFlags GetSearchFlags(const ir::MemberExpression *memberExpr, const varbinder::Variable *targetRef);
767     PropertySearchFlags GetInitialSearchFlags(const ir::MemberExpression *memberExpr);
768     const varbinder::Variable *GetTargetRef(const ir::MemberExpression *memberExpr);
769     Type *GetTypeOfSetterGetter([[maybe_unused]] varbinder::Variable *var);
770     void IterateInVariableContext([[maybe_unused]] varbinder::Variable *const var);
771     void CheckInit(ir::Identifier *ident, ir::TypeNode *typeAnnotation, ir::Expression *init,
772                    checker::Type *annotationType, varbinder::Variable *const bindingVar);
773 
774     template <typename EnumType>
775     EnumType *CreateEnumTypeFromEnumDeclaration(ir::TSEnumDeclaration const *const enumDecl);
776 
777     std::pair<ir::ScriptFunction *, ir::Identifier *> CreateStaticScriptFunction(
778         ClassInitializerBuilder const &builder);
779     std::pair<ir::ScriptFunction *, ir::Identifier *> CreateScriptFunction(ClassInitializerBuilder const &builder);
780 
781     template <typename T>
782     ir::MethodDefinition *CreateDynamicCallIntrinsic(ir::Expression *callee, const ArenaVector<T *> &arguments,
783                                                      Language lang);
784     ir::ClassStaticBlock *CreateDynamicCallClassInitializer(Language lang, bool isConstruct);
785     ir::ClassStaticBlock *CreateDynamicModuleClassInitializer(const std::vector<ir::ETSImportDeclaration *> &imports);
786     ir::MethodDefinition *CreateDynamicModuleClassInitMethod();
787 
788     ir::MethodDefinition *CreateLambdaObjectClassInitializer(ETSObjectType *functionalInterface);
789 
790     ir::MethodDefinition *CreateLambdaObjectClassInvokeMethod(Signature *invokeSignature,
791                                                               ir::TypeNode *retTypeAnnotation);
792 
793     void ClassInitializerFromImport(ir::ETSImportDeclaration *import, ArenaVector<ir::Statement *> *statements);
794     void EmitDynamicModuleClassInitCall();
DynamicCallIntrinsics(bool isConstruct)795     DynamicCallIntrinsicsMap *DynamicCallIntrinsics(bool isConstruct)
796     {
797         return &dynamicIntrinsics_[static_cast<size_t>(isConstruct)];
798     }
799 
800     ir::ClassDeclaration *GetDynamicClass(Language lang, bool isConstruct);
801 
802     using Type2TypeMap = std::unordered_map<varbinder::Variable *, varbinder::Variable *>;
803     using TypeSet = std::unordered_set<varbinder::Variable *>;
804     bool CheckTypeParameterConstraint(ir::TSTypeParameter *param, Type2TypeMap &extends);
805     bool CheckDefaultTypeParameter(const ir::TSTypeParameter *param, TypeSet &typeParameterDecls);
806 
807     void SetUpTypeParameterConstraint(ir::TSTypeParameter *param);
808     ETSObjectType *UpdateGlobalType(ETSObjectType *objType, util::StringView name);
809     ETSObjectType *UpdateBoxedGlobalType(ETSObjectType *objType, util::StringView name);
810     ETSObjectType *CreateETSObjectTypeCheckBuiltins(util::StringView name, ir::AstNode *declNode, ETSObjectFlags flags);
811     void CheckProgram(parser::Program *program, bool runAnalysis = false);
812     void CheckWarnings(parser::Program *program, const CompilerOptions &options);
813 
814     template <typename UType>
815     UType HandleModulo(UType leftValue, UType rightValue);
816 
817     template <typename FloatOrIntegerType, typename IntegerType = FloatOrIntegerType>
818     Type *HandleBitWiseArithmetic(Type *leftValue, Type *rightValue, lexer::TokenType operationType);
819 
820     template <typename TargetType>
821     typename TargetType::UType GetOperand(Type *type);
822 
823     template <typename... Args>
824     ETSObjectType *AsETSObjectType(Type *(GlobalTypesHolder::*typeFunctor)(Args...), Args... args) const;
825     Signature *GetMostSpecificSignature(ArenaVector<Signature *> &compatibleSignatures,
826                                         const ArenaVector<ir::Expression *> &arguments,
827                                         const lexer::SourcePosition &pos, TypeRelationFlag resolveFlags);
828     ArenaVector<Signature *> CollectSignatures(ArenaVector<Signature *> &signatures,
829                                                const ir::TSTypeParameterInstantiation *typeArguments,
830                                                const ArenaVector<ir::Expression *> &arguments,
831                                                const lexer::SourcePosition &pos, TypeRelationFlag resolveFlags);
832     // Trailing lambda
833     void MoveTrailingBlockToEnclosingBlockStatement(ir::CallExpression *callExpr);
834     void TransformTraillingLambda(ir::CallExpression *callExpr);
835     ArenaVector<ir::Expression *> ExtendArgumentsWithFakeLamda(ir::CallExpression *callExpr);
836 
837     // Static invoke
838     bool TryTransformingToStaticInvoke(ir::Identifier *ident, const Type *resolvedType);
839 
840     ArrayMap arrayTypes_;
841     ArenaVector<ConstraintCheckRecord> pendingConstraintCheckRecords_;
842     size_t constraintCheckScopesCount_ {0};
843     GlobalArraySignatureMap globalArraySignatures_;
844     PrimitiveWrappers primitiveWrappers_;
845     ComputedAbstracts cachedComputedAbstracts_;
846     // NOTE(aleksisch): Extract dynamic from checker to separate class
847     std::array<DynamicCallIntrinsicsMap, 2U> dynamicIntrinsics_;
848     std::array<DynamicClassIntrinsicsMap, 2U> dynamicClasses_;
849     DynamicLambdaObjectSignatureMap dynamicLambdaSignatureCache_;
850     FunctionalInterfaceMap functionalInterfaceCache_;
851     TypeMapping apparentTypes_;
852     std::array<DynamicCallNamesMap, 2U> dynamicCallNames_;
853     std::recursive_mutex mtx_;
854 };
855 
856 }  // namespace ark::es2panda::checker
857 
858 #endif /* CHECKER_H */
859