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