• 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 #include "ETSchecker.h"
17 
18 #include "es2panda.h"
19 #include "ir/base/classDefinition.h"
20 #include "ir/expression.h"
21 #include "ir/expressions/callExpression.h"
22 #include "ir/ts/tsInterfaceDeclaration.h"
23 #include "ir/statements/blockStatement.h"
24 #include "varbinder/ETSBinder.h"
25 #include "parser/program/program.h"
26 #include "checker/ets/aliveAnalyzer.h"
27 #include "checker/ets/assignAnalyzer.h"
28 #include "checker/ets/etsWarningAnalyzer.h"
29 #include "checker/types/globalTypesHolder.h"
30 #include "ir/base/scriptFunction.h"
31 #include "util/helpers.h"
32 
33 namespace ark::es2panda::checker {
34 
InitBuiltin(ETSChecker * checker,std::string_view signature)35 static util::StringView InitBuiltin(ETSChecker *checker, std::string_view signature)
36 {
37     const auto varMap = checker->VarBinder()->TopScope()->Bindings();
38     const auto iterator = varMap.find(signature);
39     ASSERT(iterator != varMap.end());
40     auto *var = iterator->second;
41     Type *type {nullptr};
42     if (var->Declaration()->Node()->IsClassDefinition()) {
43         type = checker->BuildBasicClassProperties(var->Declaration()->Node()->AsClassDefinition());
44     } else {
45         ASSERT(var->Declaration()->Node()->IsTSInterfaceDeclaration());
46         type = checker->BuildBasicInterfaceProperties(var->Declaration()->Node()->AsTSInterfaceDeclaration());
47     }
48     checker->GetGlobalTypesHolder()->InitializeBuiltin(iterator->first, type);
49     return iterator->first;
50 }
51 
SetupFunctionalInterface(ETSObjectType * type)52 static void SetupFunctionalInterface(ETSObjectType *type)
53 {
54     type->AddObjectFlag(ETSObjectFlags::FUNCTIONAL);
55     auto *invoke = type->GetOwnProperty<PropertyType::INSTANCE_METHOD>(FUNCTIONAL_INTERFACE_INVOKE_METHOD_NAME);
56     auto *invokeType = invoke->TsType()->AsETSFunctionType();
57     ASSERT(invokeType->CallSignatures().size() == 1);
58     auto *signature = invokeType->CallSignatures()[0];
59     signature->AddSignatureFlag(SignatureFlags::FUNCTIONAL_INTERFACE_SIGNATURE);
60 }
61 
SetupBuiltinMember(varbinder::Variable * var)62 static void SetupBuiltinMember(varbinder::Variable *var)
63 {
64     auto *type = var->TsType();
65     if (type == nullptr || !type->IsETSObjectType()) {
66         return;
67     }
68 }
69 
70 // NOLINTNEXTLINE(modernize-avoid-c-arrays)
71 static constexpr std::string_view BUILTINS_TO_INIT[] = {
72     compiler::Signatures::BUILTIN_BOOLEAN_CLASS,    compiler::Signatures::BUILTIN_BYTE_CLASS,
73     compiler::Signatures::BUILTIN_CHAR_CLASS,       compiler::Signatures::BUILTIN_SHORT_CLASS,
74     compiler::Signatures::BUILTIN_INT_CLASS,        compiler::Signatures::BUILTIN_LONG_CLASS,
75     compiler::Signatures::BUILTIN_FLOAT_CLASS,      compiler::Signatures::BUILTIN_DOUBLE_CLASS,
76     compiler::Signatures::BUILTIN_FUNCTION0_CLASS,  compiler::Signatures::BUILTIN_FUNCTION1_CLASS,
77     compiler::Signatures::BUILTIN_FUNCTION2_CLASS,  compiler::Signatures::BUILTIN_FUNCTION3_CLASS,
78     compiler::Signatures::BUILTIN_FUNCTION4_CLASS,  compiler::Signatures::BUILTIN_FUNCTION5_CLASS,
79     compiler::Signatures::BUILTIN_FUNCTION6_CLASS,  compiler::Signatures::BUILTIN_FUNCTION7_CLASS,
80     compiler::Signatures::BUILTIN_FUNCTION8_CLASS,  compiler::Signatures::BUILTIN_FUNCTION9_CLASS,
81     compiler::Signatures::BUILTIN_FUNCTION10_CLASS, compiler::Signatures::BUILTIN_FUNCTION11_CLASS,
82     compiler::Signatures::BUILTIN_FUNCTION12_CLASS, compiler::Signatures::BUILTIN_FUNCTION13_CLASS,
83     compiler::Signatures::BUILTIN_FUNCTION14_CLASS, compiler::Signatures::BUILTIN_FUNCTION15_CLASS,
84     compiler::Signatures::BUILTIN_FUNCTION16_CLASS, compiler::Signatures::BUILTIN_FUNCTIONN_CLASS,
85 };
86 
InitializeBuiltins(varbinder::ETSBinder * varbinder)87 void ETSChecker::InitializeBuiltins(varbinder::ETSBinder *varbinder)
88 {
89     if (HasStatus(CheckerStatus::BUILTINS_INITIALIZED)) {
90         return;
91     }
92 
93     const auto varMap = varbinder->TopScope()->Bindings();
94 
95     auto const objectName = InitBuiltin(this, compiler::Signatures::BUILTIN_OBJECT_CLASS);
96 
97     for (auto sig : BUILTINS_TO_INIT) {
98         InitBuiltin(this, sig);
99     }
100 
101     for (size_t id = static_cast<size_t>(GlobalTypeId::ETS_FUNCTION0_CLASS), nargs = 0;
102          id <= static_cast<size_t>(GlobalTypeId::ETS_FUNCTIONN_CLASS); id++, nargs++) {
103         auto *type = GetGlobalTypesHolder()->GlobalFunctionBuiltinType(nargs)->AsETSObjectType();
104         SetupFunctionalInterface(type);
105     }
106 
107     for (const auto &[name, var] : varMap) {
108         (void)name;
109         SetupBuiltinMember(var);
110     }
111 
112     for (const auto &[name, var] : varMap) {
113         if (name == objectName) {
114             continue;
115         }
116 
117         if (var->HasFlag(varbinder::VariableFlags::BUILTIN_TYPE)) {
118             if (var->TsType() == nullptr) {
119                 InitializeBuiltin(var, name);
120             } else {
121                 GetGlobalTypesHolder()->InitializeBuiltin(name, var->TsType());
122             }
123         }
124     }
125 
126     AddStatus(CheckerStatus::BUILTINS_INITIALIZED);
127 }
128 
InitializeBuiltin(varbinder::Variable * var,const util::StringView & name)129 void ETSChecker::InitializeBuiltin(varbinder::Variable *var, const util::StringView &name)
130 {
131     Type *type {nullptr};
132     if (var->Declaration()->Node()->IsClassDefinition()) {
133         type = BuildBasicClassProperties(var->Declaration()->Node()->AsClassDefinition());
134     } else {
135         ASSERT(var->Declaration()->Node()->IsTSInterfaceDeclaration());
136         type = BuildBasicInterfaceProperties(var->Declaration()->Node()->AsTSInterfaceDeclaration());
137     }
138     GetGlobalTypesHolder()->InitializeBuiltin(name, type);
139 }
140 
StartChecker(varbinder::VarBinder * varbinder,const CompilerOptions & options)141 bool ETSChecker::StartChecker(varbinder::VarBinder *varbinder, const CompilerOptions &options)
142 {
143     Initialize(varbinder);
144 
145     if (options.parseOnly) {
146         return false;
147     }
148 
149     auto *etsBinder = varbinder->AsETSBinder();
150     InitializeBuiltins(etsBinder);
151 
152     for (auto &entry : etsBinder->DynamicImportVars()) {
153         auto &data = entry.second;
154         if (data.import->IsPureDynamic()) {
155             data.variable->SetTsType(GlobalBuiltinDynamicType(data.import->Language()));
156         }
157     }
158 
159     CheckProgram(Program(), true);
160     BuildDynamicImportClass();
161 
162 #ifndef NDEBUG
163     for (auto *func : varbinder->Functions()) {
164         ASSERT(!func->Node()->AsScriptFunction()->Scope()->InternalName().Empty());
165     }
166 #endif
167 
168     if (options.dumpCheckedAst) {
169         std::cout << Program()->Dump() << std::endl;
170     }
171 
172     if (options.etsHasWarnings) {
173         CheckWarnings(Program(), options);
174     }
175 
176     return !ErrorLogger()->IsAnyError();
177 }
178 
CheckProgram(parser::Program * program,bool runAnalysis)179 void ETSChecker::CheckProgram(parser::Program *program, bool runAnalysis)
180 {
181     auto *savedProgram = Program();
182     SetProgram(program);
183 
184     for (auto &[_, extPrograms] : program->ExternalSources()) {
185         (void)_;
186         for (auto *extProg : extPrograms) {
187             checker::SavedCheckerContext savedContext(this, Context().Status(), Context().ContainingClass());
188             AddStatus(checker::CheckerStatus::IN_EXTERNAL);
189             CheckProgram(extProg, VarBinder()->IsGenStdLib());
190         }
191     }
192 
193     ASSERT(Program()->Ast()->IsProgram());
194     Program()->Ast()->Check(this);
195 
196     if (ErrorLogger()->IsAnyError()) {
197         return;
198     }
199 
200     if (runAnalysis) {
201         AliveAnalyzer aliveAnalyzer(Program()->Ast(), this);
202         AssignAnalyzer(this).Analyze(Program()->Ast());
203     }
204 
205     ASSERT(VarBinder()->AsETSBinder()->GetExternalRecordTable().find(program)->second);
206 
207     SetProgram(savedProgram);
208 }
209 
CheckWarnings(parser::Program * program,const CompilerOptions & options)210 void ETSChecker::CheckWarnings(parser::Program *program, const CompilerOptions &options)
211 {
212     const auto etsWarningCollection = options.etsWarningCollection;
213     for (const auto warning : etsWarningCollection) {
214         ETSWarningAnalyzer(Program()->Ast(), program, warning, options.etsWerror);
215     }
216 }
217 
CheckTypeCached(ir::Expression * expr)218 Type *ETSChecker::CheckTypeCached(ir::Expression *expr)
219 {
220     if (expr->TsType() == nullptr) {
221         expr->SetTsType(expr->Check(this));
222     }
223 
224     return expr->TsType();
225 }
226 
227 template <typename... Args>
AsETSObjectType(Type * (GlobalTypesHolder::* typeFunctor)(Args...),Args...args) const228 ETSObjectType *ETSChecker::AsETSObjectType(Type *(GlobalTypesHolder::*typeFunctor)(Args...), Args... args) const
229 {
230     auto *ret = (GetGlobalTypesHolder()->*typeFunctor)(args...);
231     return ret != nullptr ? ret->AsETSObjectType() : nullptr;
232 }
233 
GlobalByteType() const234 Type *ETSChecker::GlobalByteType() const
235 {
236     return GetGlobalTypesHolder()->GlobalByteType();
237 }
238 
GlobalShortType() const239 Type *ETSChecker::GlobalShortType() const
240 {
241     return GetGlobalTypesHolder()->GlobalShortType();
242 }
243 
GlobalIntType() const244 Type *ETSChecker::GlobalIntType() const
245 {
246     return GetGlobalTypesHolder()->GlobalIntType();
247 }
248 
GlobalLongType() const249 Type *ETSChecker::GlobalLongType() const
250 {
251     return GetGlobalTypesHolder()->GlobalLongType();
252 }
253 
GlobalFloatType() const254 Type *ETSChecker::GlobalFloatType() const
255 {
256     return GetGlobalTypesHolder()->GlobalFloatType();
257 }
258 
GlobalDoubleType() const259 Type *ETSChecker::GlobalDoubleType() const
260 {
261     return GetGlobalTypesHolder()->GlobalDoubleType();
262 }
263 
GlobalCharType() const264 Type *ETSChecker::GlobalCharType() const
265 {
266     return GetGlobalTypesHolder()->GlobalCharType();
267 }
268 
GlobalETSBooleanType() const269 Type *ETSChecker::GlobalETSBooleanType() const
270 {
271     return GetGlobalTypesHolder()->GlobalETSBooleanType();
272 }
273 
GlobalVoidType() const274 Type *ETSChecker::GlobalVoidType() const
275 {
276     return GetGlobalTypesHolder()->GlobalETSVoidType();
277 }
278 
GlobalETSNullType() const279 Type *ETSChecker::GlobalETSNullType() const
280 {
281     return GetGlobalTypesHolder()->GlobalETSNullType();
282 }
283 
GlobalETSUndefinedType() const284 Type *ETSChecker::GlobalETSUndefinedType() const
285 {
286     return GetGlobalTypesHolder()->GlobalETSUndefinedType();
287 }
288 
GlobalETSStringLiteralType() const289 Type *ETSChecker::GlobalETSStringLiteralType() const
290 {
291     return GetGlobalTypesHolder()->GlobalETSStringLiteralType();
292 }
293 
GlobalETSBigIntType() const294 Type *ETSChecker::GlobalETSBigIntType() const
295 {
296     return GetGlobalTypesHolder()->GlobalETSBigIntBuiltinType();
297 }
298 
GlobalWildcardType() const299 Type *ETSChecker::GlobalWildcardType() const
300 {
301     return GetGlobalTypesHolder()->GlobalWildcardType();
302 }
303 
GlobalETSObjectType() const304 ETSObjectType *ETSChecker::GlobalETSObjectType() const
305 {
306     return AsETSObjectType(&GlobalTypesHolder::GlobalETSObjectType);
307 }
308 
GlobalETSNullishType() const309 ETSUnionType *ETSChecker::GlobalETSNullishType() const
310 {
311     auto *ret = (GetGlobalTypesHolder()->*&GlobalTypesHolder::GlobalETSNullishType)();
312     return ret != nullptr ? ret->AsETSUnionType() : nullptr;
313 }
314 
GlobalETSNullishObjectType() const315 ETSUnionType *ETSChecker::GlobalETSNullishObjectType() const
316 {
317     auto *ret = (GetGlobalTypesHolder()->*&GlobalTypesHolder::GlobalETSNullishObjectType)();
318     return ret != nullptr ? ret->AsETSUnionType() : nullptr;
319 }
320 
GlobalBuiltinETSStringType() const321 ETSObjectType *ETSChecker::GlobalBuiltinETSStringType() const
322 {
323     return AsETSObjectType(&GlobalTypesHolder::GlobalETSStringBuiltinType);
324 }
325 
GlobalBuiltinETSBigIntType() const326 ETSObjectType *ETSChecker::GlobalBuiltinETSBigIntType() const
327 {
328     return AsETSObjectType(&GlobalTypesHolder::GlobalETSBigIntBuiltinType);
329 }
330 
GlobalBuiltinTypeType() const331 ETSObjectType *ETSChecker::GlobalBuiltinTypeType() const
332 {
333     return AsETSObjectType(&GlobalTypesHolder::GlobalTypeBuiltinType);
334 }
335 
GlobalBuiltinExceptionType() const336 ETSObjectType *ETSChecker::GlobalBuiltinExceptionType() const
337 {
338     return AsETSObjectType(&GlobalTypesHolder::GlobalExceptionBuiltinType);
339 }
340 
GlobalBuiltinErrorType() const341 ETSObjectType *ETSChecker::GlobalBuiltinErrorType() const
342 {
343     return AsETSObjectType(&GlobalTypesHolder::GlobalErrorBuiltinType);
344 }
345 
GlobalStringBuilderBuiltinType() const346 ETSObjectType *ETSChecker::GlobalStringBuilderBuiltinType() const
347 {
348     return AsETSObjectType(&GlobalTypesHolder::GlobalStringBuilderBuiltinType);
349 }
350 
GlobalBuiltinPromiseType() const351 ETSObjectType *ETSChecker::GlobalBuiltinPromiseType() const
352 {
353     return AsETSObjectType(&GlobalTypesHolder::GlobalPromiseBuiltinType);
354 }
355 
GlobalBuiltinJSRuntimeType() const356 ETSObjectType *ETSChecker::GlobalBuiltinJSRuntimeType() const
357 {
358     return AsETSObjectType(&GlobalTypesHolder::GlobalJSRuntimeBuiltinType);
359 }
360 
GlobalBuiltinJSValueType() const361 ETSObjectType *ETSChecker::GlobalBuiltinJSValueType() const
362 {
363     return AsETSObjectType(&GlobalTypesHolder::GlobalJSValueBuiltinType);
364 }
365 
GlobalBuiltinFunctionType(size_t nargs) const366 ETSObjectType *ETSChecker::GlobalBuiltinFunctionType(size_t nargs) const
367 {
368     return AsETSObjectType(&GlobalTypesHolder::GlobalFunctionBuiltinType, nargs);
369 }
370 
GlobalBuiltinFunctionTypeVariadicThreshold() const371 size_t ETSChecker::GlobalBuiltinFunctionTypeVariadicThreshold() const
372 {
373     return GetGlobalTypesHolder()->VariadicFunctionTypeThreshold();
374 }
375 
GlobalBuiltinDynamicType(Language lang) const376 ETSObjectType *ETSChecker::GlobalBuiltinDynamicType(Language lang) const
377 {
378     if (lang.GetId() == Language::Id::JS) {
379         return GlobalBuiltinJSValueType();
380     }
381     return nullptr;
382 }
383 
GlobalBuiltinBoxType(Type * contents)384 ETSObjectType *ETSChecker::GlobalBuiltinBoxType(Type *contents)
385 {
386     switch (TypeKind(contents)) {
387         case TypeFlag::ETS_BOOLEAN:
388             return AsETSObjectType(&GlobalTypesHolder::GlobalBooleanBoxBuiltinType);
389         case TypeFlag::BYTE:
390             return AsETSObjectType(&GlobalTypesHolder::GlobalByteBoxBuiltinType);
391         case TypeFlag::CHAR:
392             return AsETSObjectType(&GlobalTypesHolder::GlobalCharBoxBuiltinType);
393         case TypeFlag::SHORT:
394             return AsETSObjectType(&GlobalTypesHolder::GlobalShortBoxBuiltinType);
395         case TypeFlag::INT:
396             return AsETSObjectType(&GlobalTypesHolder::GlobalIntBoxBuiltinType);
397         case TypeFlag::LONG:
398             return AsETSObjectType(&GlobalTypesHolder::GlobalLongBoxBuiltinType);
399         case TypeFlag::FLOAT:
400             return AsETSObjectType(&GlobalTypesHolder::GlobalFloatBoxBuiltinType);
401         case TypeFlag::DOUBLE:
402             return AsETSObjectType(&GlobalTypesHolder::GlobalDoubleBoxBuiltinType);
403         default: {
404             auto *base = AsETSObjectType(&GlobalTypesHolder::GlobalBoxBuiltinType);
405             auto *substitution = NewSubstitution();
406             substitution->emplace(base->TypeArguments()[0]->AsETSTypeParameter(), contents);
407             return base->Substitute(Relation(), substitution);
408         }
409     }
410 }
411 
PrimitiveWrapper() const412 const checker::WrapperDesc &ETSChecker::PrimitiveWrapper() const
413 {
414     return primitiveWrappers_.Wrappers();
415 }
416 
GlobalArrayTypes()417 GlobalArraySignatureMap &ETSChecker::GlobalArrayTypes()
418 {
419     return globalArraySignatures_;
420 }
421 
GlobalArrayTypes() const422 const GlobalArraySignatureMap &ETSChecker::GlobalArrayTypes() const
423 {
424     return globalArraySignatures_;
425 }
426 
GlobalTypeError() const427 Type *ETSChecker::GlobalTypeError() const
428 {
429     return GetGlobalTypesHolder()->GlobalTypeError();
430 }
431 
HandleUpdatedCallExpressionNode(ir::CallExpression * callExpr)432 void ETSChecker::HandleUpdatedCallExpressionNode(ir::CallExpression *callExpr)
433 {
434     VarBinder()->AsETSBinder()->HandleCustomNodes(callExpr);
435 }
436 
SelectGlobalIntegerTypeForNumeric(Type * type)437 Type *ETSChecker::SelectGlobalIntegerTypeForNumeric(Type *type)
438 {
439     switch (ETSType(type)) {
440         case checker::TypeFlag::FLOAT: {
441             return GlobalIntType();
442         }
443         case checker::TypeFlag::DOUBLE: {
444             return GlobalLongType();
445         }
446         default: {
447             return type;
448         }
449     }
450 }
451 
452 }  // namespace ark::es2panda::checker
453