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/qqmljsdiagnosticmessage_p.h>
23#include <private/qqmljsmemorypool_p.h>
24
25#include <QtCore/qtaggedpointer.h>
26#include <QtCore/qtyperevision.h>
27
28#include <type_traits>
29
30QT_BEGIN_NAMESPACE
31
32class QString;
33
34namespace QQmlJS {
35 class Parser;
36}
37
38#define QQMLJS_DECLARE_AST_NODE(name)
39 enum { K = Kind_##name };
40
88
89namespace QQmlJS {
90
91namespace AST {
92
99
100template <typename T1, typename T2>
101T1 cast(T2 *ast)
102{
103 if (ast && ast->kind == std::remove_pointer_t<T1>::K)
104 return static_cast<T1>(ast);
105
106 return nullptr;
107}
108
109FunctionExpression *asAnonymousFunctionDefinition(AST::Node *n);
110ClassExpression *asAnonymousClassDefinition(AST::Node *n);
111
113{
114public:
115 enum Kind {
117
219
244 };
245
246 inline Node() {}
247
248 // NOTE: node destructors are never called,
249 // instead we block free the memory
250 // (see the NodePool class)
251 virtual ~Node() {}
252
255 virtual Statement *statementCast();
258 virtual Pattern *patternCast();
259 // implements the IsFunctionDefinition rules in the spec
262
263 bool ignoreRecursionDepth() const;
264
266 {
268
269 // Stack overflow is uncommon, ignoreRecursionDepth() only returns true if
270 // QV4_CRASH_ON_STACKOVERFLOW is set, and ignoreRecursionDepth() needs to be out of line.
271 // Therefore, check for ignoreRecursionDepth() _after_ calling the inline recursionCheck().
273 if (visitor->preVisit(this))
275 visitor->postVisit(this);
276 } else {
278 }
279 }
280
281 inline static void accept(Node *node, BaseVisitor *visitor)
282 {
283 if (node)
285 }
286
287 virtual void accept0(BaseVisitor *visitor) = 0;
290
291// attributes
293};
294
295template<typename T>
297{
298 auto current = head;
299 while (current->next)
300 current = current->next;
301 return current;
302}
303
305{
306public:
308
310 : next(this), name(name)
311 { kind = K; }
312
314 : name(name)
315 {
316 kind = K;
317 next = previous->next;
318 previous->next = this;
319 }
320
322 {
324 next = nullptr;
325 return head;
326 }
327
329
332
337
339
341 {
344 return result;
345 }
346
347 void toString(QString *out) const
348 {
349 for (const UiQualifiedId *it = this; it; it = it->next) {
350 out->append(it->name);
351 if (it->next)
352 out->append(QLatin1Char('.'));
353 }
354 }
355
356// attributes
361};
362
392
425
430
432{
433public:
435
437};
438
465
466
485
504
525
544
563
582
601
602
623
653
674
702
724
737
766
795
797{
798public:
800
802 next (this) { kind = K; }
803
805 {
806 kind = K;
807 next = previous->next;
808 previous->next = this;
809 }
810
812
815
818
819 inline Elision *finish ()
820 {
821 Elision *front = next;
822 next = nullptr;
823 return front;
824 }
825
826// attributes
829};
830
849
868
869struct BoundNames : public QList<BoundName>
870{
871 int indexOf(const QString &name, int from = 0) const
872 {
873 auto found = std::find_if(constBegin() + from, constEnd(),
874 [&name](const BoundName &it) { return it.id == name; });
875 if (found == constEnd())
876 return -1;
877 return found - constBegin();
878 }
879
880 bool contains(const QString &name) const
881 {
882 return indexOf(name) != -1;
883 }
884};
885
886/*!
887\internal
888This class is needed to pass the information about the equalToken in the parser, and is only needed
889during AST construction. It behaves exactly like the expression it contains: that avoids changing
890all the usages in qqmljs.g from ExpressionNode to InitializerExpression for every rule expecting a
891InitializerOpt_In or InitializerOpt.
892*/
918
920{
921public:
923
924 enum Type {
925 // object literal types
930
931 // used by both bindings and literals
934
935 // binding types
937 };
938
939private:
940 /*!
941 \internal
942 Hide InitializerExpression from the AST. InitializerExpression is only needed during parsing for
943 the AST construction, and it is not possible for the parser to directly embed the location of
944 equal tokens inside the PatternElement without the InitializerExpression.
945 */
946 void unwrapInitializer()
947 {
951 }
952 }
953public:
954
956 : initializer(i), type(t)
957 {
958 kind = K;
960 }
961
970
978
982
985
988
993
996
997 virtual void boundNames(BoundNames *names);
998
999// attributes
1007 // when used in a VariableDeclarationList
1010 bool isForDeclaration = false;
1012};
1013
1057
1093
1094
1132
1134{
1135public:
1137
1140
1142
1143 QString asString() const override { return id.toString(); }
1144
1145// attributes
1147};
1148
1164
1166{
1167public:
1169
1171 id (n) { kind = K; }
1172
1174
1175 QString asString() const override;
1176
1177// attributes
1178 double id;
1179};
1180
1203
1204
1230
1255
1277
1302
1323
1349
1351{
1352public:
1354
1356 expression (e), next (this)
1357 { kind = K; }
1358
1360 expression (e)
1361 {
1362 kind = K;
1363 next = previous->next;
1364 previous->next = this;
1365 }
1366
1368
1371
1373 {
1374 if (next)
1375 return next->lastSourceLocation();
1377 }
1378
1380 {
1382 next = nullptr;
1383 return front;
1384 }
1385
1386// attributes
1391};
1392
1413
1434
1455
1476
1497
1518
1539
1560
1581
1602
1623
1649
1674
1696
1718
1720{
1721public:
1723
1724 // ### This should be a Statement, but FunctionDeclaration currently doesn't inherit it.
1726 : statement(stmt), next (this)
1727 { kind = K; }
1728
1730 n->next = next;
1731 next = n;
1732 return n;
1733 }
1734
1736
1739
1744
1746 {
1748 next = nullptr;
1749 return front;
1750 }
1751
1752// attributes
1753 Node *statement = nullptr;
1755};
1756
1802
1824
1843
1864
1896
1923
1948
1983
1984enum class ForEachType {
1987};
1988
2023
2046
2069
2091
2113
2138
2163
2188
2212
2214{
2215public:
2217
2219 clause (c), next (this)
2220 { kind = K; }
2221
2223 clause (c)
2224 {
2225 kind = K;
2226 next = previous->next;
2227 previous->next = this;
2228 }
2229
2231
2234
2239
2241 {
2243 next = nullptr;
2244 return front;
2245 }
2246
2247//attributes
2250};
2251
2274
2298
2320
2346
2368
2407
2444
2456
2458{
2459public:
2461
2463 : element(e)
2464 {
2465 kind = K;
2466 if (previous) {
2467 next = previous->next;
2468 previous->next = this;
2469 } else {
2470 next = this;
2471 }
2472 }
2473
2475 n->next = next;
2476 next = n;
2477 return n;
2478 }
2479
2481 {
2483 while (formals) {
2485 if (e && e->type == PatternElement::RestElement)
2486 return false;
2487 if (e && (e->initializer || e->bindingTarget))
2488 return false;
2489 formals = formals->next;
2490 }
2491 return true;
2492 }
2493
2495 {
2496 // the length property of Function objects
2497 int l = 0;
2499 while (formals) {
2501 if (!e || e->initializer)
2502 break;
2504 break;
2505 ++l;
2506 formals = formals->next;
2507 }
2508 return l;
2509 }
2510
2511 bool containsName(const QString &name) const {
2512 for (const FormalParameterList *it = this; it; it = it->next) {
2514 // ### handle binding patterns
2515 if (b && b->bindingIdentifier == name)
2516 return true;
2517 }
2518 return false;
2519 }
2520
2521 BoundNames formals() const;
2522
2523 BoundNames boundNames() const;
2524
2526
2529
2534
2536
2537// attributes
2541};
2542
2571
2583
2584
2586{
2587public:
2589
2592 {
2593 kind = K;
2594 next = this;
2595 }
2596
2598 n->next = next;
2599 next = n;
2600 return n;
2601 }
2602
2604
2607
2609 {
2610 if (next)
2611 return next->lastSourceLocation();
2612 return property->lastSourceLocation();
2613 }
2614
2616
2620};
2621
2642
2673
2675{
2676public:
2678
2685
2688 {
2689 kind = K;
2690 if (previous) {
2691 next = previous->next;
2692 previous->next = this;
2693 } else {
2694 next = this;
2695 }
2696 }
2697
2699 {
2701 next = nullptr;
2702 return head;
2703 }
2704
2706
2709
2714
2715// attributes
2719};
2720
2749
2773
2775{
2776public:
2778
2784
2790
2796
2803
2810
2812
2817
2818// attributes
2823};
2824
2849
2882
2913
2915{
2916public:
2918
2925
2928 {
2929 kind = K;
2930 if (previous) {
2931 next = previous->next;
2932 previous->next = this;
2933 } else {
2934 next = this;
2935 }
2936 }
2937
2939 {
2941 next = nullptr;
2942 return head;
2943 }
2944
2946
2951
2952// attributes
2955};
2956
2985
3035
3037{
3038public:
3040
3042 : body(body)
3043 {
3044 kind = K;
3045 }
3046
3048
3051
3054
3055// attributes
3057};
3058
3079
3112
3124
3161
3163{
3164public:
3166
3168 : value(value)
3169 , next(this)
3170 {
3171 kind = K;
3172 }
3173
3175 : value(value)
3176 {
3177 kind = K;
3178 next = previous->next;
3179 previous->next = this;
3180 }
3181
3183
3186
3189
3191 {
3193 next = nullptr;
3194 return head;
3195 }
3196
3200};
3201
3227
3249
3251{
3252public:
3254
3258
3262
3265 {
3266 kind = K;
3267 next = previous->next;
3268 previous->next = this;
3269 }
3270
3273 {
3274 kind = K;
3275 next = previous->next;
3276 previous->next = this;
3277 }
3278
3280 {
3282 next = nullptr;
3283 return head;
3284 }
3285
3287
3290
3293
3294// attributes
3297};
3298
3300{
3301public:
3303
3307
3309
3311 {
3312 if (headers)
3313 return headers->firstSourceLocation();
3314 else if (members)
3315 return members->firstSourceLocation();
3316 return SourceLocation();
3317 }
3318
3320 {
3321 if (members)
3322 return members->lastSourceLocation();
3323 else if (headers)
3324 return headers->lastSourceLocation();
3325 return SourceLocation();
3326 }
3327
3328// attributes
3331};
3332
3370
3393
3443
3445{
3447public:
3449
3451 bool isDefaultMember() const { return defaultToken().isValid(); }
3453 bool isRequired() const { return requiredToken().isValid(); }
3455 bool isReadonly() const { return readonlyToken().isValid(); }
3457 bool isFinal() const { return finalToken().isValid(); }
3459 bool isVirtual() const { return virtualToken().isValid(); }
3461 bool isOverride() const { return overrideToken().isValid(); }
3462
3464
3465 template <bool InvalidIsLargest = true>
3466 static bool compareLocationsByBegin(const SourceLocation * const &lhs,
3467 const SourceLocation * const &rhs)
3468 {
3469 if (lhs->isValid() && rhs->isValid())
3470 return lhs->begin() < rhs->begin();
3471 else if (lhs->isValid())
3472 return InvalidIsLargest;
3473 else
3474 return !InvalidIsLargest;
3475 }
3476
3477 void accept0(BaseVisitor *) override {} // intentionally do nothing
3478
3480
3482
3483private:
3484 friend class QQmlJS::Parser;
3492};
3493
3495{
3496public:
3498
3503
3509
3511
3513 {
3514 if (hasAttributes)
3516 else
3517 return m_propertyToken;
3518 }
3519
3521 {
3522 if (binding)
3523 return binding->lastSourceLocation();
3524 if (statement)
3525 return statement->lastSourceLocation();
3526
3527 return semicolonToken;
3528 }
3529
3534 bool isDefaultMember() const { return defaultToken().isValid(); }
3535
3540 bool isRequired() const { return requiredToken().isValid(); }
3541
3546 bool isReadonly() const { return readonlyToken().isValid(); }
3547
3549 {
3551 }
3552 bool isFinal() const { return finalToken().isValid(); }
3553
3558 bool isOverride() const { return overrideToken().isValid(); }
3559
3564 bool isVirtual() const { return virtualToken().isValid(); }
3565
3571
3576
3578 {
3580 hasAttributes = false;
3581 }
3582
3583// attributes
3584 enum : bool { Signal, Property } type;
3585 bool hasAttributes = false;
3589 Statement *statement; // initialized with a JS expression
3590 UiObjectMember *binding; // initialized with a QML object or array.
3592 // TODO: merge source locations
3600private:
3601 union {
3604 };
3605};
3606
3629
3653
3689
3725
3750
3777
3830
3858
3881
3918
3919} } // namespace AST
3920
3921
3922QT_END_NAMESPACE
3923
3924#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:21
T lastListElement(T head)
T1 cast(T2 *ast)
ClassExpression * asAnonymousClassDefinition(Node *n)
Definition qqmljsast.cpp:31
static constexpr SourceLocation s_documentOrigin(0, 0, 1, 1)
@ InplaceRightShift
Definition qqmljsast_p.h:75
@ InplaceURightShift
Definition qqmljsast_p.h:80
Combined button and popup list for selecting options.
#define QQMLJS_DECLARE_AST_NODE(name)
Definition qqmljsast_p.h:38
Q_DECLARE_TYPEINFO(QQmlJS::DiagnosticMessage, Q_RELOCATABLE_TYPE)
#define QML_PARSER_EXPORT
bool contains(const QString &name) const
int indexOf(const QString &name, int from=0) const