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_COMPILER_SCOPES_DECLARATION_H
17#define ES2PANDA_COMPILER_SCOPES_DECLARATION_H
18
19#include "varbinder/variableFlags.h"
20#include "macros.h"
21#include "util/ustring.h"
22
23namespace ark::es2panda::ir {
24class AstNode;
25class ScriptFunction;
26class TSInterfaceDeclaration;
27class ImportDeclaration;
28class ETSImportDeclaration;
29}  // namespace ark::es2panda::ir
30
31namespace ark::es2panda::varbinder {
32class Scope;
33class LocalScope;
34
35// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
36#define DECLARE_CLASSES(decl_kind, className) class className;
37DECLARATION_KINDS(DECLARE_CLASSES)
38#undef DECLARE_CLASSES
39
40class Decl {
41public:
42    virtual ~Decl() = default;
43    NO_COPY_SEMANTIC(Decl);
44    NO_MOVE_SEMANTIC(Decl);
45
46    virtual DeclType Type() const = 0;
47
48    const util::StringView &Name() const
49    {
50        return name_;
51    }
52
53    ir::AstNode *Node()
54    {
55        return node_;
56    }
57
58    const ir::AstNode *Node() const
59    {
60        return node_;
61    }
62
63// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
64#define DECLARE_CHECKS_CASTS(declKind, className)         \
65    bool Is##className() const                            \
66    {                                                     \
67        return Type() == DeclType::declKind;              \
68    }                                                     \
69    className *As##className()                            \
70    {                                                     \
71        ASSERT(Is##className());                          \
72        return reinterpret_cast<className *>(this);       \
73    }                                                     \
74    const className *As##className() const                \
75    {                                                     \
76        ASSERT(Is##className());                          \
77        return reinterpret_cast<const className *>(this); \
78    }
79    DECLARATION_KINDS(DECLARE_CHECKS_CASTS)
80#undef DECLARE_CHECKS_CASTS
81
82    void BindNode(ir::AstNode *node)
83    {
84        node_ = node;
85    }
86
87    bool IsLetOrConstDecl() const
88    {
89        return IsLetDecl() || IsConstDecl();
90    }
91
92    bool PossibleTDZ() const
93    {
94        return IsLetOrConstDecl() || IsParameterDecl();
95    }
96
97protected:
98    explicit Decl(util::StringView name) : name_(name) {}
99    explicit Decl(util::StringView name, ir::AstNode *declNode) : name_(name), node_(declNode) {}
100
101    // NOLINTBEGIN(misc-non-private-member-variables-in-classes)
102    util::StringView name_;
103    ir::AstNode *node_ {};
104    // NOLINTEND(misc-non-private-member-variables-in-classes)
105};
106
107template <typename T>
108class MultiDecl : public Decl {
109public:
110    explicit MultiDecl(ArenaAllocator *allocator, util::StringView name)
111        : Decl(name), declarations_(allocator->Adapter())
112    {
113    }
114
115    explicit MultiDecl(ArenaAllocator *allocator, util::StringView name, ir::AstNode *declNode)
116        : Decl(name, declNode), declarations_(allocator->Adapter())
117    {
118    }
119
120    const ArenaVector<T *> &Decls() const
121    {
122        return declarations_;
123    }
124
125    void Add(T *decl)
126    {
127        declarations_.push_back(decl);
128    }
129
130private:
131    ArenaVector<T *> declarations_;
132};
133
134class EnumLiteralDecl : public Decl {
135public:
136    explicit EnumLiteralDecl(util::StringView name, bool isConst) : Decl(name), isConst_(isConst) {}
137    explicit EnumLiteralDecl(util::StringView name, ir::AstNode *declNode, bool isConst)
138        : Decl(name, declNode), isConst_(isConst)
139    {
140    }
141
142    DeclType Type() const override
143    {
144        return DeclType::ENUM_LITERAL;
145    }
146
147    bool IsConst() const
148    {
149        return isConst_;
150    }
151
152    void BindScope(LocalScope *scope)
153    {
154        scope_ = scope;
155    }
156
157    LocalScope *Scope()
158    {
159        return scope_;
160    }
161
162private:
163    LocalScope *scope_ {};
164    bool isConst_ {};
165};
166
167class InterfaceDecl : public MultiDecl<ir::TSInterfaceDeclaration> {
168public:
169    explicit InterfaceDecl(ArenaAllocator *allocator, util::StringView name) : MultiDecl(allocator, name) {}
170    explicit InterfaceDecl(ArenaAllocator *allocator, util::StringView name, ir::AstNode *declNode)
171        : MultiDecl(allocator, name, declNode)
172    {
173    }
174
175    DeclType Type() const override
176    {
177        return DeclType::INTERFACE;
178    }
179};
180
181class ClassDecl : public Decl {
182public:
183    explicit ClassDecl(util::StringView name) : Decl(name) {}
184    explicit ClassDecl(util::StringView name, ir::AstNode *node) : Decl(name, node) {}
185
186    DeclType Type() const override
187    {
188        return DeclType::CLASS;
189    }
190};
191
192class FunctionDecl : public MultiDecl<ir::ScriptFunction> {
193public:
194    explicit FunctionDecl(ArenaAllocator *allocator, util::StringView name, ir::AstNode *node)
195        : MultiDecl(allocator, name)
196    {
197        node_ = node;
198    }
199
200    DeclType Type() const override
201    {
202        return DeclType::FUNC;
203    }
204};
205
206class TypeParameterDecl : public Decl {
207public:
208    explicit TypeParameterDecl(util::StringView name) : Decl(name) {}
209
210    DeclType Type() const override
211    {
212        return DeclType::TYPE_PARAMETER;
213    }
214};
215
216class PropertyDecl : public Decl {
217public:
218    explicit PropertyDecl(util::StringView name) : Decl(name) {}
219
220    DeclType Type() const override
221    {
222        return DeclType::PROPERTY;
223    }
224};
225
226class MethodDecl : public Decl {
227public:
228    explicit MethodDecl(util::StringView name) : Decl(name) {}
229
230    DeclType Type() const override
231    {
232        return DeclType::METHOD;
233    }
234};
235
236class EnumDecl : public Decl {
237public:
238    explicit EnumDecl(util::StringView name) : Decl(name) {}
239
240    DeclType Type() const override
241    {
242        return DeclType::ENUM;
243    }
244};
245
246class TypeAliasDecl : public Decl {
247public:
248    explicit TypeAliasDecl(util::StringView name) : Decl(name) {}
249    explicit TypeAliasDecl(util::StringView name, ir::AstNode *node) : Decl(name, node) {}
250
251    DeclType Type() const override
252    {
253        return DeclType::TYPE_ALIAS;
254    }
255};
256
257class NameSpaceDecl : public Decl {
258public:
259    explicit NameSpaceDecl(util::StringView name) : Decl(name) {}
260
261    DeclType Type() const override
262    {
263        return DeclType::NAMESPACE;
264    }
265};
266
267class VarDecl : public Decl {
268public:
269    explicit VarDecl(util::StringView name) : Decl(name) {}
270
271    DeclType Type() const override
272    {
273        return DeclType::VAR;
274    }
275};
276
277class LetDecl : public Decl {
278public:
279    explicit LetDecl(util::StringView name) : Decl(name) {}
280    explicit LetDecl(util::StringView name, ir::AstNode *declNode) : Decl(name, declNode) {}
281
282    DeclType Type() const override
283    {
284        return DeclType::LET;
285    }
286};
287
288class ConstDecl : public Decl {
289public:
290    explicit ConstDecl(util::StringView name) : Decl(name) {}
291    explicit ConstDecl(util::StringView name, ir::AstNode *declNode) : Decl(name, declNode) {}
292
293    DeclType Type() const override
294    {
295        return DeclType::CONST;
296    }
297};
298
299class LabelDecl : public Decl {
300public:
301    explicit LabelDecl(util::StringView name) : Decl(name) {}
302    explicit LabelDecl(util::StringView name, ir::AstNode *declNode) : Decl(name, declNode) {}
303
304    DeclType Type() const override
305    {
306        return DeclType::LABEL;
307    }
308};
309
310class ReadonlyDecl : public Decl {
311public:
312    explicit ReadonlyDecl(util::StringView name) : Decl(name) {}
313    explicit ReadonlyDecl(util::StringView name, ir::AstNode *declNode) : Decl(name, declNode) {}
314
315    DeclType Type() const override
316    {
317        return DeclType::READONLY;
318    }
319};
320
321class ParameterDecl : public Decl {
322public:
323    explicit ParameterDecl(util::StringView name) : Decl(name) {}
324
325    DeclType Type() const override
326    {
327        return DeclType::PARAM;
328    }
329};
330
331class ImportDecl : public Decl {
332public:
333    explicit ImportDecl(util::StringView importName, util::StringView localName)
334        : Decl(localName), importName_(importName)
335    {
336    }
337
338    explicit ImportDecl(util::StringView importName, util::StringView localName, ir::AstNode *node)
339        : Decl(localName), importName_(importName)
340    {
341        BindNode(node);
342    }
343
344    const util::StringView &ImportName() const
345    {
346        return importName_;
347    }
348
349    const util::StringView &LocalName() const
350    {
351        return name_;
352    }
353
354    DeclType Type() const override
355    {
356        return DeclType::IMPORT;
357    }
358
359private:
360    util::StringView importName_;
361};
362
363class ExportDecl : public Decl {
364public:
365    explicit ExportDecl(util::StringView exportName, util::StringView localName)
366        : Decl(localName), exportName_(exportName)
367    {
368    }
369
370    explicit ExportDecl(util::StringView exportName, util::StringView localName, ir::AstNode *node)
371        : Decl(localName), exportName_(exportName)
372    {
373        BindNode(node);
374    }
375
376    const util::StringView &ExportName() const
377    {
378        return exportName_;
379    }
380
381    const util::StringView &LocalName() const
382    {
383        return name_;
384    }
385
386    DeclType Type() const override
387    {
388        return DeclType::EXPORT;
389    }
390
391private:
392    util::StringView exportName_;
393};
394}  // namespace ark::es2panda::varbinder
395
396#endif
397