Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qqmljsast_p.h
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant
4
5#ifndef QQMLJSAST_P_H
6#define QQMLJSAST_P_H
7
8//
9// W A R N I N G
10// -------------
11//
12// This file is not part of the Qt API. It exists purely as an
13// implementation detail. This header file may change from version to
14// version without notice, or even be removed.
15//
16// We mean it.
17//
18
20#include "qqmljsglobal_p.h"
21
22#include <private/qqmljsmemorypool_p.h>
23
24#include <QtCore/qtaggedpointer.h>
25#include <QtCore/qtyperevision.h>
26
27#include <type_traits>
28
29QT_BEGIN_NAMESPACE
30
31class QString;
32
33namespace QQmlJS {
34 class Parser;
35}
36
37#define QQMLJS_DECLARE_AST_NODE(name)
38 enum { K = Kind_##name };
39
87
88namespace QQmlJS {
89
90namespace AST {
91
98
99template <typename T1, typename T2>
100T1 cast(T2 *ast)
101{
102 if (ast && ast->kind == std::remove_pointer_t<T1>::K)
103 return static_cast<T1>(ast);
104
105 return nullptr;
106}
107
108FunctionExpression *asAnonymousFunctionDefinition(AST::Node *n);
109ClassExpression *asAnonymousClassDefinition(AST::Node *n);
110
112{
113public:
114 enum Kind {
116
218
243 };
244
245 inline Node() {}
246
247 // NOTE: node destructors are never called,
248 // instead we block free the memory
249 // (see the NodePool class)
250 virtual ~Node() {}
251
254 virtual Statement *statementCast();
257 virtual Pattern *patternCast();
258 // implements the IsFunctionDefinition rules in the spec
261
262 bool ignoreRecursionDepth() const;
263
265 {
267
268 // Stack overflow is uncommon, ignoreRecursionDepth() only returns true if
269 // QV4_CRASH_ON_STACKOVERFLOW is set, and ignoreRecursionDepth() needs to be out of line.
270 // Therefore, check for ignoreRecursionDepth() _after_ calling the inline recursionCheck().
272 if (visitor->preVisit(this))
274 visitor->postVisit(this);
275 } else {
277 }
278 }
279
280 inline static void accept(Node *node, BaseVisitor *visitor)
281 {
282 if (node)
284 }
285
286 virtual void accept0(BaseVisitor *visitor) = 0;
289
290// attributes
292};
293
294template<typename T>
296{
297 auto current = head;
298 while (current->next)
299 current = current->next;
300 return current;
301}
302
304{
305public:
307
309 : next(this), name(name)
310 { kind = K; }
311
313 : name(name)
314 {
315 kind = K;
316 next = previous->next;
317 previous->next = this;
318 }
319
321 {
323 next = nullptr;
324 return head;
325 }
326
328
331
336
338
340 {
343 return result;
344 }
345
346 void toString(QString *out) const
347 {
348 for (const UiQualifiedId *it = this; it; it = it->next) {
349 out->append(it->name);
350 if (it->next)
351 out->append(QLatin1Char('.'));
352 }
353 }
354
355// attributes
360};
361
391
424
429
431{
432public:
434
436};
437
464
465
484
503
524
543
562
581
600
601
622
652
673
701
723
735
763
791
793{
794public:
796
798 next (this) { kind = K; }
799
801 {
802 kind = K;
803 next = previous->next;
804 previous->next = this;
805 }
806
808
811
814
815 inline Elision *finish ()
816 {
817 Elision *front = next;
818 next = nullptr;
819 return front;
820 }
821
822// attributes
825};
826
845
864
865struct BoundNames : public QList<BoundName>
866{
867 int indexOf(const QString &name, int from = 0) const
868 {
869 auto found = std::find_if(constBegin() + from, constEnd(),
870 [name](const BoundName &it) { return it.id == name; });
871 if (found == constEnd())
872 return -1;
873 return found - constBegin();
874 }
875
876 bool contains(const QString &name) const
877 {
878 return indexOf(name) != -1;
879 }
880};
881
882/*!
883\internal
884This class is needed to pass the information about the equalToken in the parser, and is only needed
885during AST construction. It behaves exactly like the expression it contains: that avoids changing
886all the usages in qqmljs.g from ExpressionNode to InitializerExpression for every rule expecting a
887InitializerOpt_In or InitializerOpt.
888*/
914
916{
917public:
919
920 enum Type {
921 // object literal types
926
927 // used by both bindings and literals
930
931 // binding types
933 };
934
935private:
936 /*!
937 \internal
938 Hide InitializerExpression from the AST. InitializerExpression is only needed during parsing for
939 the AST construction, and it is not possible for the parser to directly embed the location of
940 equal tokens inside the PatternElement without the InitializerExpression.
941 */
942 void unwrapInitializer()
943 {
947 }
948 }
949public:
950
952 : initializer(i), type(t)
953 {
954 kind = K;
956 }
957
966
974
977
980
983
988
991
992 virtual void boundNames(BoundNames *names);
993
994// attributes
1002 // when used in a VariableDeclarationList
1005 bool isForDeclaration = false;
1007};
1008
1052
1087
1088
1126
1128{
1129public:
1131
1134
1136
1137 QString asString() const override { return id.toString(); }
1138
1139// attributes
1141};
1142
1158
1160{
1161public:
1163
1165 id (n) { kind = K; }
1166
1168
1169 QString asString() const override;
1170
1171// attributes
1172 double id;
1173};
1174
1197
1198
1224
1249
1271
1296
1317
1343
1345{
1346public:
1348
1350 expression (e), next (this)
1351 { kind = K; }
1352
1354 expression (e)
1355 {
1356 kind = K;
1357 next = previous->next;
1358 previous->next = this;
1359 }
1360
1362
1365
1367 {
1368 if (next)
1369 return next->lastSourceLocation();
1371 }
1372
1374 {
1376 next = nullptr;
1377 return front;
1378 }
1379
1380// attributes
1384 bool isSpreadElement = false;
1385};
1386
1407
1428
1449
1470
1491
1512
1533
1554
1575
1596
1617
1643
1668
1690
1712
1714{
1715public:
1717
1718 // ### This should be a Statement, but FunctionDeclaration currently doesn't inherit it.
1720 : statement(stmt), next (this)
1721 { kind = K; }
1722
1724 n->next = next;
1725 next = n;
1726 return n;
1727 }
1728
1730
1733
1738
1740 {
1742 next = nullptr;
1743 return front;
1744 }
1745
1746// attributes
1747 Node *statement = nullptr;
1749};
1750
1796
1818
1837
1858
1890
1917
1942
1977
1978enum class ForEachType {
1981};
1982
2017
2040
2063
2085
2107
2132
2157
2182
2206
2208{
2209public:
2211
2213 clause (c), next (this)
2214 { kind = K; }
2215
2217 clause (c)
2218 {
2219 kind = K;
2220 next = previous->next;
2221 previous->next = this;
2222 }
2223
2225
2228
2233
2235 {
2237 next = nullptr;
2238 return front;
2239 }
2240
2241//attributes
2244};
2245
2268
2292
2314
2340
2362
2401
2438
2450
2452{
2453public:
2455
2457 : element(e)
2458 {
2459 kind = K;
2460 if (previous) {
2461 next = previous->next;
2462 previous->next = this;
2463 } else {
2464 next = this;
2465 }
2466 }
2467
2469 n->next = next;
2470 next = n;
2471 return n;
2472 }
2473
2475 {
2477 while (formals) {
2479 if (e && e->type == PatternElement::RestElement)
2480 return false;
2481 if (e && (e->initializer || e->bindingTarget))
2482 return false;
2483 formals = formals->next;
2484 }
2485 return true;
2486 }
2487
2489 {
2490 // the length property of Function objects
2491 int l = 0;
2493 while (formals) {
2495 if (!e || e->initializer)
2496 break;
2498 break;
2499 ++l;
2500 formals = formals->next;
2501 }
2502 return l;
2503 }
2504
2505 bool containsName(const QString &name) const {
2506 for (const FormalParameterList *it = this; it; it = it->next) {
2508 // ### handle binding patterns
2509 if (b && b->bindingIdentifier == name)
2510 return true;
2511 }
2512 return false;
2513 }
2514
2515 BoundNames formals() const;
2516
2517 BoundNames boundNames() const;
2518
2520
2523
2528
2530
2531// attributes
2535};
2536
2565
2577
2578
2580{
2581public:
2583
2586 {
2587 kind = K;
2588 next = this;
2589 }
2590
2592 n->next = next;
2593 next = n;
2594 return n;
2595 }
2596
2598
2601
2603 {
2604 if (next)
2605 return next->lastSourceLocation();
2606 return property->lastSourceLocation();
2607 }
2608
2610
2614};
2615
2636
2667
2669{
2670public:
2672
2679
2682 {
2683 kind = K;
2684 if (previous) {
2685 next = previous->next;
2686 previous->next = this;
2687 } else {
2688 next = this;
2689 }
2690 }
2691
2693 {
2695 next = nullptr;
2696 return head;
2697 }
2698
2700
2703
2708
2709// attributes
2713};
2714
2743
2767
2769{
2770public:
2772
2778
2784
2790
2797
2804
2806
2811
2812// attributes
2817};
2818
2843
2876
2907
2909{
2910public:
2912
2919
2922 {
2923 kind = K;
2924 if (previous) {
2925 next = previous->next;
2926 previous->next = this;
2927 } else {
2928 next = this;
2929 }
2930 }
2931
2933 {
2935 next = nullptr;
2936 return head;
2937 }
2938
2940
2945
2946// attributes
2949};
2950
2979
3029
3031{
3032public:
3034
3036 : body(body)
3037 {
3038 kind = K;
3039 }
3040
3042
3045
3048
3049// attributes
3051};
3052
3073
3106
3118
3155
3157{
3158public:
3160
3162 : value(value)
3163 , next(this)
3164 {
3165 kind = K;
3166 }
3167
3169 : value(value)
3170 {
3171 kind = K;
3172 next = previous->next;
3173 previous->next = this;
3174 }
3175
3177
3180
3183
3185 {
3187 next = nullptr;
3188 return head;
3189 }
3190
3194};
3195
3221
3243
3245{
3246public:
3248
3252
3256
3259 {
3260 kind = K;
3261 next = previous->next;
3262 previous->next = this;
3263 }
3264
3267 {
3268 kind = K;
3269 next = previous->next;
3270 previous->next = this;
3271 }
3272
3274 {
3276 next = nullptr;
3277 return head;
3278 }
3279
3281
3284
3287
3288// attributes
3291};
3292
3294{
3295public:
3297
3301
3303
3305 {
3306 if (headers)
3307 return headers->firstSourceLocation();
3308 else if (members)
3309 return members->firstSourceLocation();
3310 return SourceLocation();
3311 }
3312
3314 {
3315 if (members)
3316 return members->lastSourceLocation();
3317 else if (headers)
3318 return headers->lastSourceLocation();
3319 return SourceLocation();
3320 }
3321
3322// attributes
3325};
3326
3364
3387
3437
3439{
3441public:
3443
3445 bool isDefaultMember() const { return defaultToken().isValid(); }
3447 bool isRequired() const { return requiredToken().isValid(); }
3449 bool isReadonly() const { return readonlyToken().isValid(); }
3451 bool isFinal() const { return finalToken().isValid(); }
3453 bool isVirtual() const { return virtualToken().isValid(); }
3455 bool isOverride() const { return overrideToken().isValid(); }
3456
3458
3459 template <bool InvalidIsLargest = true>
3460 static bool compareLocationsByBegin(const SourceLocation * const &lhs,
3461 const SourceLocation * const &rhs)
3462 {
3463 if (lhs->isValid() && rhs->isValid())
3464 return lhs->begin() < rhs->begin();
3465 else if (lhs->isValid())
3466 return InvalidIsLargest;
3467 else
3468 return !InvalidIsLargest;
3469 }
3470
3471 void accept0(BaseVisitor *) override {} // intentionally do nothing
3472
3474
3476
3477private:
3478 friend class QQmlJS::Parser;
3486};
3487
3489{
3490public:
3492
3497
3503
3505
3507 {
3508 if (hasAttributes)
3510 else
3511 return m_propertyToken;
3512 }
3513
3515 {
3516 if (binding)
3517 return binding->lastSourceLocation();
3518 if (statement)
3519 return statement->lastSourceLocation();
3520
3521 return semicolonToken;
3522 }
3523
3528 bool isDefaultMember() const { return defaultToken().isValid(); }
3529
3534 bool isRequired() const { return requiredToken().isValid(); }
3535
3540 bool isReadonly() const { return readonlyToken().isValid(); }
3541
3543 {
3545 }
3546 bool isFinal() const { return finalToken().isValid(); }
3547
3552 bool isOverride() const { return overrideToken().isValid(); }
3553
3558 bool isVirtual() const { return virtualToken().isValid(); }
3559
3565
3570
3572 {
3574 hasAttributes = false;
3575 }
3576
3577// attributes
3578 enum : bool { Signal, Property } type;
3579 bool hasAttributes = false;
3583 Statement *statement; // initialized with a JS expression
3584 UiObjectMember *binding; // initialized with a QML object or array.
3586 // TODO: merge source locations
3594private:
3595 union {
3598 };
3599};
3600
3623
3647
3683
3719
3744
3771
3824
3852
3875
3912
3913} } // namespace AST
3914
3915
3916QT_END_NAMESPACE
3917
3918#endif
friend size_t qHash(const SourceLocation &location, size_t seed=0)
SourceLocation startZeroLengthLocation() const
constexpr SourceLocation(quint32 offset=0, quint32 length=0, quint32 line=0, quint32 column=0)
friend bool operator!=(const SourceLocation &a, const SourceLocation &b)
static quint32 offsetFrom(QStringView text, quint32 line, quint32 column, const SourceLocation &startHint=SourceLocation{})
friend SourceLocation combine(const SourceLocation &l1, const SourceLocation &l2)
static SourceLocation fromQSizeType(qsizetype offset, qsizetype length=0, qsizetype line=0, qsizetype column=0)
SourceLocation endZeroLengthLocation(QStringView text) const
friend bool operator==(const SourceLocation &a, const SourceLocation &b)
static std::pair< quint32, quint32 > rowAndColumnFrom(QStringView text, quint32 offset, const SourceLocation &startHint=SourceLocation{})
FunctionExpression * asAnonymousFunctionDefinition(Node *n)
Definition qqmljsast.cpp:20
T lastListElement(T head)
T1 cast(T2 *ast)
ClassExpression * asAnonymousClassDefinition(Node *n)
Definition qqmljsast.cpp:30
static constexpr SourceLocation s_documentOrigin(0, 0, 1, 1)
@ InplaceRightShift
Definition qqmljsast_p.h:74
@ InplaceURightShift
Definition qqmljsast_p.h:79
#define QQMLJS_DECLARE_AST_NODE(name)
Definition qqmljsast_p.h:37
#define QML_PARSER_EXPORT
bool contains(const QString &name) const
int indexOf(const QString &name, int from=0) const