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