1 /*
2 * Copyright (c) 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 "identifierHasVariable.h"
17 #include "ir/expressions/memberExpression.h"
18 #include "ir/ts/tsEnumDeclaration.h"
19
20 namespace ark::es2panda::compiler::ast_verifier {
21
operator ()(CheckContext & ctx,const ir::AstNode * ast)22 CheckResult IdentifierHasVariable::operator()(CheckContext &ctx, const ir::AstNode *ast)
23 {
24 if (!ast->IsIdentifier()) {
25 return {CheckDecision::CORRECT, CheckAction::CONTINUE};
26 }
27
28 if (ast->AsIdentifier()->Variable() != nullptr) {
29 return {CheckDecision::CORRECT, CheckAction::CONTINUE};
30 }
31
32 const auto *id = ast->AsIdentifier();
33 if (CheckAstExceptions(id)) {
34 return {CheckDecision::CORRECT, CheckAction::CONTINUE};
35 }
36
37 // Another function with exceptions to reduce function size
38 if (CheckMoreAstExceptions(id)) {
39 return {CheckDecision::CORRECT, CheckAction::CONTINUE};
40 }
41
42 ctx.AddCheckMessage("NULL_VARIABLE", *id, id->Start());
43 return {CheckDecision::INCORRECT, CheckAction::CONTINUE};
44 }
45
CheckMoreAstExceptions(const ir::Identifier * ast) const46 bool IdentifierHasVariable::CheckMoreAstExceptions(const ir::Identifier *ast) const
47 {
48 // NOTE(kkonkuznetsov): object expressions
49 const auto *parent = ast->Parent();
50 while (parent != nullptr) {
51 if (parent->IsObjectExpression()) {
52 return true;
53 }
54
55 parent = parent->Parent();
56 }
57
58 // NOTE(kkonkuznetsov): some identifiers have empty names
59 if (ast->Name().Empty()) {
60 return true;
61 }
62
63 // NOTE(mmartin): find a better solution to handle utility type resolution
64 if (ast->Name().Is(Signatures::PARTIAL_TYPE_NAME) || ast->Name().Is(Signatures::REQUIRED_TYPE_NAME) ||
65 ast->Name().Is(Signatures::READONLY_TYPE_NAME)) {
66 return true;
67 }
68
69 return false;
70 }
71
CheckAstExceptions(const ir::Identifier * ast) const72 bool IdentifierHasVariable::CheckAstExceptions(const ir::Identifier *ast) const
73 {
74 // NOTE(kkonkuznetsov): skip length property
75 if (ast->Parent()->IsMemberExpression() && ast->Name().Is("length")) {
76 return true;
77 }
78
79 // NOTE(kkonkuznetsov): skip package declarations
80 const auto *parent = ast->Parent();
81 while (parent != nullptr) {
82 if (parent->IsETSPackageDeclaration()) {
83 return true;
84 }
85 parent = parent->Parent();
86 }
87
88 return false;
89 }
90
91 } // namespace ark::es2panda::compiler::ast_verifier
92