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/qversionnumber.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
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
1049
1084
1085
1123
1125{
1126public:
1128
1131
1133
1134 QString asString() const override { return id.toString(); }
1135
1136// attributes
1138};
1139
1155
1157{
1158public:
1160
1162 id (n) { kind = K; }
1163
1165
1166 QString asString() const override;
1167
1168// attributes
1169 double id;
1170};
1171
1194
1195
1221
1246
1268
1293
1314
1340
1342{
1343public:
1345
1347 expression (e), next (this)
1348 { kind = K; }
1349
1351 expression (e)
1352 {
1353 kind = K;
1354 next = previous->next;
1355 previous->next = this;
1356 }
1357
1359
1362
1364 {
1365 if (next)
1366 return next->lastSourceLocation();
1368 }
1369
1371 {
1373 next = nullptr;
1374 return front;
1375 }
1376
1377// attributes
1381 bool isSpreadElement = false;
1382};
1383
1404
1425
1446
1467
1488
1509
1530
1551
1572
1593
1614
1640
1665
1687
1709
1711{
1712public:
1714
1715 // ### This should be a Statement, but FunctionDeclaration currently doesn't inherit it.
1717 : statement(stmt), next (this)
1718 { kind = K; }
1719
1721 n->next = next;
1722 next = n;
1723 return n;
1724 }
1725
1727
1730
1735
1737 {
1739 next = nullptr;
1740 return front;
1741 }
1742
1743// attributes
1744 Node *statement = nullptr;
1746};
1747
1793
1815
1834
1855
1887
1914
1939
1974
1975enum class ForEachType {
1978};
1979
2014
2037
2060
2082
2104
2129
2154
2179
2203
2205{
2206public:
2208
2210 clause (c), next (this)
2211 { kind = K; }
2212
2214 clause (c)
2215 {
2216 kind = K;
2217 next = previous->next;
2218 previous->next = this;
2219 }
2220
2222
2225
2230
2232 {
2234 next = nullptr;
2235 return front;
2236 }
2237
2238//attributes
2241};
2242
2265
2289
2311
2337
2359
2398
2435
2447
2449{
2450public:
2452
2454 : element(e)
2455 {
2456 kind = K;
2457 if (previous) {
2458 next = previous->next;
2459 previous->next = this;
2460 } else {
2461 next = this;
2462 }
2463 }
2464
2466 n->next = next;
2467 next = n;
2468 return n;
2469 }
2470
2472 {
2474 while (formals) {
2476 if (e && e->type == PatternElement::RestElement)
2477 return false;
2478 if (e && (e->initializer || e->bindingTarget))
2479 return false;
2480 formals = formals->next;
2481 }
2482 return true;
2483 }
2484
2486 {
2487 // the length property of Function objects
2488 int l = 0;
2490 while (formals) {
2492 if (!e || e->initializer)
2493 break;
2495 break;
2496 ++l;
2497 formals = formals->next;
2498 }
2499 return l;
2500 }
2501
2502 bool containsName(const QString &name) const {
2503 for (const FormalParameterList *it = this; it; it = it->next) {
2505 // ### handle binding patterns
2506 if (b && b->bindingIdentifier == name)
2507 return true;
2508 }
2509 return false;
2510 }
2511
2512 BoundNames formals() const;
2513
2514 BoundNames boundNames() const;
2515
2517
2520
2525
2527
2528// attributes
2532};
2533
2562
2574
2575
2577{
2578public:
2580
2583 {
2584 kind = K;
2585 next = this;
2586 }
2587
2589 n->next = next;
2590 next = n;
2591 return n;
2592 }
2593
2595
2598
2600 {
2601 if (next)
2602 return next->lastSourceLocation();
2603 return property->lastSourceLocation();
2604 }
2605
2607
2611};
2612
2633
2664
2666{
2667public:
2669
2676
2679 {
2680 kind = K;
2681 if (previous) {
2682 next = previous->next;
2683 previous->next = this;
2684 } else {
2685 next = this;
2686 }
2687 }
2688
2690 {
2692 next = nullptr;
2693 return head;
2694 }
2695
2697
2700
2705
2706// attributes
2710};
2711
2740
2764
2766{
2767public:
2769
2775
2781
2787
2794
2801
2803
2808
2809// attributes
2814};
2815
2840
2873
2904
2906{
2907public:
2909
2916
2919 {
2920 kind = K;
2921 if (previous) {
2922 next = previous->next;
2923 previous->next = this;
2924 } else {
2925 next = this;
2926 }
2927 }
2928
2930 {
2932 next = nullptr;
2933 return head;
2934 }
2935
2937
2942
2943// attributes
2946};
2947
2976
3026
3028{
3029public:
3031
3033 : body(body)
3034 {
3035 kind = K;
3036 }
3037
3039
3042
3045
3046// attributes
3048};
3049
3070
3103
3115
3152
3154{
3155public:
3157
3159 : value(value)
3160 , next(this)
3161 {
3162 kind = K;
3163 }
3164
3166 : value(value)
3167 {
3168 kind = K;
3169 next = previous->next;
3170 previous->next = this;
3171 }
3172
3174
3177
3180
3182 {
3184 next = nullptr;
3185 return head;
3186 }
3187
3191};
3192
3218
3240
3242{
3243public:
3245
3249
3253
3256 {
3257 kind = K;
3258 next = previous->next;
3259 previous->next = this;
3260 }
3261
3264 {
3265 kind = K;
3266 next = previous->next;
3267 previous->next = this;
3268 }
3269
3271 {
3273 next = nullptr;
3274 return head;
3275 }
3276
3278
3281
3284
3285// attributes
3288};
3289
3291{
3292public:
3294
3298
3300
3302 {
3303 if (headers)
3304 return headers->firstSourceLocation();
3305 else if (members)
3306 return members->firstSourceLocation();
3307 return SourceLocation();
3308 }
3309
3311 {
3312 if (members)
3313 return members->lastSourceLocation();
3314 else if (headers)
3315 return headers->lastSourceLocation();
3316 return SourceLocation();
3317 }
3318
3319// attributes
3322};
3323
3361
3384
3434
3436{
3438public:
3440
3442 bool isDefaultMember() const { return defaultToken().isValid(); }
3444 bool isRequired() const { return requiredToken().isValid(); }
3446 bool isReadonly() const { return readonlyToken().isValid(); }
3448 bool isFinal() const { return finalToken().isValid(); }
3449
3451
3452 template <bool InvalidIsLargest = true>
3453 static bool compareLocationsByBegin(const SourceLocation * const &lhs,
3454 const SourceLocation * const &rhs)
3455 {
3456 if (lhs->isValid() && rhs->isValid())
3457 return lhs->begin() < rhs->begin();
3458 else if (lhs->isValid())
3459 return InvalidIsLargest;
3460 else
3461 return !InvalidIsLargest;
3462 }
3463
3464 void accept0(BaseVisitor *) override {} // intentionally do nothing
3465
3467
3469
3470private:
3471 friend class QQmlJS::Parser;
3477};
3478
3480{
3481public:
3483
3488
3494
3496
3498 {
3499 if (hasAttributes)
3501 else
3502 return m_propertyToken;
3503 }
3504
3506 {
3507 if (binding)
3508 return binding->lastSourceLocation();
3509 if (statement)
3510 return statement->lastSourceLocation();
3511
3512 return semicolonToken;
3513 }
3514
3519 bool isDefaultMember() const { return defaultToken().isValid(); }
3520
3525 bool isRequired() const { return requiredToken().isValid(); }
3526
3531 bool isReadonly() const { return readonlyToken().isValid(); }
3532
3534 {
3536 }
3537 bool isFinal() const { return finalToken().isValid(); }
3538
3544
3549
3551 {
3553 hasAttributes = false;
3554 }
3555
3556// attributes
3557 enum : bool { Signal, Property } type;
3558 bool hasAttributes = false;
3562 Statement *statement; // initialized with a JS expression
3563 UiObjectMember *binding; // initialized with a QML object or array.
3565 // TODO: merge source locations
3573private:
3574 union {
3577 };
3578};
3579
3602
3626
3662
3698
3723
3750
3803
3831
3854
3891
3892} } // namespace AST
3893
3894
3895QT_END_NAMESPACE
3896
3897#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:20
T lastListElement(T head)
T1 cast(T2 *ast)
ClassExpression * asAnonymousClassDefinition(Node *n)
Definition qqmljsast.cpp:30
@ 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