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
4#ifndef QQMLJSAST_P_H
5#define QQMLJSAST_P_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API. It exists purely as an
12// implementation detail. This header file may change from version to
13// version without notice, or even be removed.
14//
15// We mean it.
16//
17
19#include "qqmljsglobal_p.h"
20
21#include <private/qqmljsmemorypool_p.h>
22
23#include <QtCore/qtaggedpointer.h>
24#include <QtCore/qversionnumber.h>
25
26#include <type_traits>
27
28QT_BEGIN_NAMESPACE
29
30class QString;
31
32namespace QQmlJS {
33 class Parser;
34}
35
36#define QQMLJS_DECLARE_AST_NODE(name)
37 enum { K = Kind_##name };
38
86
87namespace QQmlJS {
88
89namespace AST {
90
91enum class VariableScope {
92 NoScope,
93 Var,
94 Let,
95 Const
96};
97
98template <typename T1, typename T2>
99T1 cast(T2 *ast)
100{
101 if (ast && ast->kind == std::remove_pointer_t<T1>::K)
102 return static_cast<T1>(ast);
103
104 return nullptr;
105}
106
107FunctionExpression *asAnonymousFunctionDefinition(AST::Node *n);
108ClassExpression *asAnonymousClassDefinition(AST::Node *n);
109
111{
112public:
113 enum Kind {
115
217
242 };
243
244 inline Node() {}
245
246 // NOTE: node destructors are never called,
247 // instead we block free the memory
248 // (see the NodePool class)
249 virtual ~Node() {}
250
253 virtual Statement *statementCast();
256 virtual Pattern *patternCast();
257 // implements the IsFunctionDefinition rules in the spec
260
261 bool ignoreRecursionDepth() const;
262
264 {
266
267 // Stack overflow is uncommon, ignoreRecursionDepth() only returns true if
268 // QV4_CRASH_ON_STACKOVERFLOW is set, and ignoreRecursionDepth() needs to be out of line.
269 // Therefore, check for ignoreRecursionDepth() _after_ calling the inline recursionCheck().
271 if (visitor->preVisit(this))
273 visitor->postVisit(this);
274 } else {
276 }
277 }
278
279 inline static void accept(Node *node, BaseVisitor *visitor)
280 {
281 if (node)
283 }
284
285 virtual void accept0(BaseVisitor *visitor) = 0;
288
289// attributes
291};
292
293template<typename T>
295{
296 auto current = head;
297 while (current->next)
298 current = current->next;
299 return current;
300}
301
303{
304public:
306
308 : next(this), name(name)
309 { kind = K; }
310
312 : name(name)
313 {
314 kind = K;
315 next = previous->next;
316 previous->next = this;
317 }
318
320 {
322 next = nullptr;
323 return head;
324 }
325
327
330
335
337
339 {
342 return result;
343 }
344
345 void toString(QString *out) const
346 {
347 for (const UiQualifiedId *it = this; it; it = it->next) {
348 out->append(it->name);
349 if (it->next)
350 out->append(QLatin1Char('.'));
351 }
352 }
353
354// attributes
359};
360
386
419
424
426{
427public:
429
431};
432
459
460
479
498
519
538
557
576
595
596
617
647
668
696
718
730
758
786
788{
789public:
791
793 next (this) { kind = K; }
794
796 {
797 kind = K;
798 next = previous->next;
799 previous->next = this;
800 }
801
803
806
809
810 inline Elision *finish ()
811 {
812 Elision *front = next;
813 next = nullptr;
814 return front;
815 }
816
817// attributes
820};
821
840
859
861{
862 int indexOf(const QString &name, int from = 0) const
863 {
864 auto found = std::find_if(constBegin() + from, constEnd(),
865 [name](const BoundName &it) { return it.id == name; });
866 if (found == constEnd())
867 return -1;
868 return found - constBegin();
869 }
870
871 bool contains(const QString &name) const
872 {
873 return indexOf(name) != -1;
874 }
875};
876
877/*!
878\internal
879This class is needed to pass the information about the equalToken in the parser, and is only needed
880during AST construction. It behaves exactly like the expression it contains: that avoids changing
881all the usages in qqmljs.g from ExpressionNode to InitializerExpression for every rule expecting a
882InitializerOpt_In or InitializerOpt.
883*/
909
911{
912public:
914
915 enum Type {
916 // object literal types
921
922 // used by both bindings and literals
925
926 // binding types
928 };
929
930private:
931 /*!
932 \internal
933 Hide InitializerExpression from the AST. InitializerExpression is only needed during parsing for
934 the AST construction, and it is not possible for the parser to directly embed the location of
935 equal tokens inside the PatternElement without the InitializerExpression.
936 */
937 void unwrapInitializer()
938 {
942 }
943 }
944public:
945
947 : initializer(i), type(t)
948 {
949 kind = K;
951 }
952
961
969
972
975
978
983
986
987 virtual void boundNames(BoundNames *names);
988
989// attributes
997 // when used in a VariableDeclarationList
1000 bool isForDeclaration = false;
1002};
1003
1043
1078
1079
1117
1119{
1120public:
1122
1125
1127
1128 QString asString() const override { return id.toString(); }
1129
1130// attributes
1132};
1133
1149
1151{
1152public:
1154
1156 id (n) { kind = K; }
1157
1159
1160 QString asString() const override;
1161
1162// attributes
1163 double id;
1164};
1165
1188
1189
1214
1239
1261
1286
1307
1332
1334{
1335public:
1337
1339 expression (e), next (this)
1340 { kind = K; }
1341
1343 expression (e)
1344 {
1345 kind = K;
1346 next = previous->next;
1347 previous->next = this;
1348 }
1349
1351
1354
1356 {
1357 if (next)
1358 return next->lastSourceLocation();
1360 }
1361
1363 {
1365 next = nullptr;
1366 return front;
1367 }
1368
1369// attributes
1373 bool isSpreadElement = false;
1374};
1375
1396
1417
1438
1459
1480
1501
1522
1543
1564
1585
1606
1632
1657
1679
1701
1703{
1704public:
1706
1707 // ### This should be a Statement, but FunctionDeclaration currently doesn't inherit it.
1709 : statement(stmt), next (this)
1710 { kind = K; }
1711
1713 n->next = next;
1714 next = n;
1715 return n;
1716 }
1717
1719
1722
1727
1729 {
1731 next = nullptr;
1732 return front;
1733 }
1734
1735// attributes
1736 Node *statement = nullptr;
1738};
1739
1785
1807
1826
1847
1879
1906
1931
1966
1967enum class ForEachType {
1968 In,
1969 Of
1970};
1971
2006
2029
2052
2074
2096
2121
2146
2171
2195
2197{
2198public:
2200
2202 clause (c), next (this)
2203 { kind = K; }
2204
2206 clause (c)
2207 {
2208 kind = K;
2209 next = previous->next;
2210 previous->next = this;
2211 }
2212
2214
2217
2222
2224 {
2226 next = nullptr;
2227 return front;
2228 }
2229
2230//attributes
2233};
2234
2257
2281
2303
2329
2351
2390
2427
2439
2441{
2442public:
2444
2446 : element(e)
2447 {
2448 kind = K;
2449 if (previous) {
2450 next = previous->next;
2451 previous->next = this;
2452 } else {
2453 next = this;
2454 }
2455 }
2456
2458 n->next = next;
2459 next = n;
2460 return n;
2461 }
2462
2464 {
2466 while (formals) {
2468 if (e && e->type == PatternElement::RestElement)
2469 return false;
2470 if (e && (e->initializer || e->bindingTarget))
2471 return false;
2472 formals = formals->next;
2473 }
2474 return true;
2475 }
2476
2478 {
2479 // the length property of Function objects
2480 int l = 0;
2482 while (formals) {
2484 if (!e || e->initializer)
2485 break;
2487 break;
2488 ++l;
2489 formals = formals->next;
2490 }
2491 return l;
2492 }
2493
2494 bool containsName(const QString &name) const {
2495 for (const FormalParameterList *it = this; it; it = it->next) {
2497 // ### handle binding patterns
2498 if (b && b->bindingIdentifier == name)
2499 return true;
2500 }
2501 return false;
2502 }
2503
2504 BoundNames formals() const;
2505
2506 BoundNames boundNames() const;
2507
2509
2512
2517
2519
2520// attributes
2523};
2524
2553
2565
2566
2568{
2569public:
2571
2574 {
2575 kind = K;
2576 next = this;
2577 }
2578
2580 n->next = next;
2581 next = n;
2582 return n;
2583 }
2584
2586
2589
2591 {
2592 if (next)
2593 return next->lastSourceLocation();
2594 return property->lastSourceLocation();
2595 }
2596
2598
2602};
2603
2624
2655
2657{
2658public:
2660
2667
2670 {
2671 kind = K;
2672 if (previous) {
2673 next = previous->next;
2674 previous->next = this;
2675 } else {
2676 next = this;
2677 }
2678 }
2679
2681 {
2683 next = nullptr;
2684 return head;
2685 }
2686
2688
2691
2696
2697// attributes
2701};
2702
2731
2755
2757{
2758public:
2760
2766
2772
2778
2785
2792
2794
2799
2800// attributes
2805};
2806
2831
2864
2895
2897{
2898public:
2900
2907
2910 {
2911 kind = K;
2912 if (previous) {
2913 next = previous->next;
2914 previous->next = this;
2915 } else {
2916 next = this;
2917 }
2918 }
2919
2921 {
2923 next = nullptr;
2924 return head;
2925 }
2926
2928
2933
2934// attributes
2937};
2938
2967
3017
3019{
3020public:
3022
3024 : body(body)
3025 {
3026 kind = K;
3027 }
3028
3030
3033
3036
3037// attributes
3039};
3040
3061
3094
3106
3143
3145{
3146public:
3148
3150 : value(value)
3151 , next(this)
3152 {
3153 kind = K;
3154 }
3155
3157 : value(value)
3158 {
3159 kind = K;
3160 next = previous->next;
3161 previous->next = this;
3162 }
3163
3165
3168
3171
3173 {
3175 next = nullptr;
3176 return head;
3177 }
3178
3182};
3183
3209
3231
3233{
3234public:
3236
3240
3244
3247 {
3248 kind = K;
3249 next = previous->next;
3250 previous->next = this;
3251 }
3252
3255 {
3256 kind = K;
3257 next = previous->next;
3258 previous->next = this;
3259 }
3260
3262 {
3264 next = nullptr;
3265 return head;
3266 }
3267
3269
3272
3275
3276// attributes
3279};
3280
3282{
3283public:
3285
3289
3291
3293 {
3294 if (headers)
3295 return headers->firstSourceLocation();
3296 else if (members)
3297 return members->firstSourceLocation();
3298 return SourceLocation();
3299 }
3300
3302 {
3303 if (members)
3304 return members->lastSourceLocation();
3305 else if (headers)
3306 return headers->lastSourceLocation();
3307 return SourceLocation();
3308 }
3309
3310// attributes
3313};
3314
3352
3375
3425
3427{
3429public:
3431
3433 bool isDefaultMember() const { return defaultToken().isValid(); }
3435 bool isRequired() const { return requiredToken().isValid(); }
3437 bool isReadonly() const { return readonlyToken().isValid(); }
3438
3440
3441 template <bool InvalidIsLargest = true>
3443 {
3444 if (lhs->isValid() && rhs->isValid())
3445 return lhs->begin() < rhs->begin();
3446 else if (lhs->isValid())
3447 return InvalidIsLargest;
3448 else
3449 return !InvalidIsLargest;
3450 }
3451
3452 void accept0(BaseVisitor *) override {} // intentionally do nothing
3453
3455
3457
3458private:
3459 friend class QQmlJS::Parser;
3464};
3465
3467{
3468public:
3470
3475
3481
3483
3485 {
3486 if (hasAttributes)
3488 else
3489 return m_propertyToken;
3490 }
3491
3493 {
3494 if (binding)
3495 return binding->lastSourceLocation();
3496 if (statement)
3497 return statement->lastSourceLocation();
3498
3499 return semicolonToken;
3500 }
3501
3506 bool isDefaultMember() const { return defaultToken().isValid(); }
3507
3512 bool isRequired() const { return requiredToken().isValid(); }
3513
3518 bool isReadonly() const { return readonlyToken().isValid(); }
3519
3525
3530
3532 {
3534 hasAttributes = false;
3535 }
3536
3537// attributes
3538 enum : bool { Signal, Property } type;
3539 bool hasAttributes = false;
3543 Statement *statement; // initialized with a JS expression
3544 UiObjectMember *binding; // initialized with a QML object or array.
3546 // TODO: merge source locations
3554private:
3555 union {
3558 };
3559};
3560
3583
3607
3643
3679
3704
3731
3733{
3735public:
3737 : next(this), member(member), value(v)
3738 { kind = K; }
3739
3741 : member(member)
3742 {
3743 kind = K;
3744 next = previous->next;
3745 previous->next = this;
3746 value = previous->value + 1;
3747 }
3748
3750 : member(member), value(v)
3751 {
3752 kind = K;
3753 next = previous->next;
3754 previous->next = this;
3755 }
3756
3759
3761 {
3762 auto last = lastListElement(this);
3764 }
3765
3767
3769 {
3771 next = nullptr;
3772 return head;
3773 }
3774
3775// attributes
3778 double value;
3781};
3782
3810
3833
3870
3871} } // namespace AST
3872
3873
3874QT_END_NAMESPACE
3875
3876#endif
friend size_t qHash(const SourceLocation &location, size_t seed=0)
SourceLocation startZeroLengthLocation() const
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(quint32 offset=0, quint32 length=0, quint32 line=0, quint32 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:19
T lastListElement(T head)
T1 cast(T2 *ast)
Definition qqmljsast_p.h:99
ClassExpression * asAnonymousClassDefinition(Node *n)
Definition qqmljsast.cpp:29
@ InplaceRightShift
Definition qqmljsast_p.h:73
@ InplaceURightShift
Definition qqmljsast_p.h:78
#define QQMLJS_DECLARE_AST_NODE(name)
Definition qqmljsast_p.h:36
#define QML_PARSER_EXPORT
bool contains(const QString &name) const
int indexOf(const QString &name, int from=0) const