• 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_ETSANALYZER_H
17 #define ES2PANDA_CHECKER_ETSANALYZER_H
18 
19 #include "checker/SemanticAnalyzer.h"
20 #include "checker/ETSchecker.h"
21 #include "ETSAnalyzerHelpers.h"
22 
23 namespace ark::es2panda::checker {
24 
25 class ETSAnalyzer final : public SemanticAnalyzer {
26 public:
ETSAnalyzer(Checker * checker)27     explicit ETSAnalyzer(Checker *checker) : SemanticAnalyzer(checker) {};
28 
29 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
30 #define DECLARE_ETSANALYZER_CHECK_METHOD(_, nodeType) checker::Type *Check(ir::nodeType *node) const override;
31     AST_NODE_MAPPING(DECLARE_ETSANALYZER_CHECK_METHOD)
32 #undef DECLARE_ETSANALYZER_CHECK_METHOD
33 
34 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
35 #define DECLARE_ETSANALYZER_CHECK_METHOD(_, __, nodeType, ___) \
36     virtual checker::Type *Check(ir::nodeType *node) const override;
37     AST_NODE_REINTERPRET_MAPPING(DECLARE_ETSANALYZER_CHECK_METHOD)
38 #undef DECLARE_ETSANALYZER_CHECK_METHOD
39     checker::Type *PreferredType(ir::ObjectExpression *expr) const;
40     checker::Type *GetPreferredType(ir::ArrayExpression *expr) const;
41     void CheckObjectExprProps(const ir::ObjectExpression *expr, checker::PropertySearchFlags searchFlags) const;
42     std::tuple<Type *, ir::Expression *> CheckAssignmentExprOperatorType(ir::AssignmentExpression *expr,
43                                                                          Type *leftType) const;
44 
45 private:
46     ETSChecker *GetETSChecker() const;
47     void CheckInstantatedClass(ir::ETSNewClassInstanceExpression *expr, ETSObjectType *&calleeObj) const;
48     void CheckMethodModifiers(ir::MethodDefinition *node) const;
49     checker::Signature *ResolveSignature(ETSChecker *checker, ir::CallExpression *expr, checker::Type *calleeType,
50                                          bool isFunctionalInterface, bool isUnionTypeWithFunctionalInterface) const;
51     checker::Type *GetReturnType(ir::CallExpression *expr, checker::Type *calleeType) const;
52     checker::Type *GetFunctionReturnType(ir::ReturnStatement *st, ir::ScriptFunction *containingFunc) const;
53     checker::Type *SetAndAdjustType(ETSChecker *checker, ir::MemberExpression *expr, ETSObjectType *objectType) const;
54     checker::Type *UnwrapPromiseType(checker::Type *type) const;
55 
GetCalleeType(ETSChecker * checker,ir::ETSNewClassInstanceExpression * expr)56     checker::Type *GetCalleeType(ETSChecker *checker, ir::ETSNewClassInstanceExpression *expr) const
57     {
58         checker::Type *calleeType = expr->GetTypeRef()->Check(checker);
59 
60         if (!calleeType->IsETSObjectType()) {
61             checker->ThrowTypeError("This expression is not constructible.", expr->Start());
62         }
63 
64         return calleeType;
65     }
66 
CheckVoidTypeExpression(ETSChecker * checker,const ir::Expression * expr)67     void CheckVoidTypeExpression(ETSChecker *checker, const ir::Expression *expr) const
68     {
69         // Existing void expression inconsistency,refer to #17762
70         if (expr->TsType() == nullptr || !expr->TsType()->IsETSVoidType() || expr->Parent() == nullptr) {
71             return;
72         }
73         auto parent = expr->Parent();
74         while (parent->IsConditionalExpression()) {
75             parent = parent->Parent();
76             if (parent == nullptr) {
77                 return;
78             }
79         }
80         bool acceptVoid = parent->IsExpressionStatement() || parent->IsReturnStatement() ||
81                           parent->IsETSLaunchExpression() || parent->IsCallExpression();
82         if (!acceptVoid) {
83             checker->ThrowTypeError({"Cannot use type 'void' as value. "}, expr->Start());
84         }
85     }
86 };
87 
88 }  // namespace ark::es2panda::checker
89 
90 #endif  // ES2PANDA_CHECKER_ETSANALYZER_H
91