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
213
238 };
239
240 inline Node() {}
241
242 // NOTE: node destructors are never called,
243 // instead we block free the memory
244 // (see the NodePool class)
245 virtual ~Node() {}
246
249 virtual Statement *statementCast();
252 virtual Pattern *patternCast();
253 // implements the IsFunctionDefinition rules in the spec
256
257 bool ignoreRecursionDepth() const;
258
260 {
262
263 // Stack overflow is uncommon, ignoreRecursionDepth() only returns true if
264 // QV4_CRASH_ON_STACKOVERFLOW is set, and ignoreRecursionDepth() needs to be out of line.
265 // Therefore, check for ignoreRecursionDepth() _after_ calling the inline recursionCheck().
267 if (visitor->preVisit(this))
269 visitor->postVisit(this);
270 } else {
272 }
273 }
274
275 inline static void accept(Node *node, BaseVisitor *visitor)
276 {
277 if (node)
279 }
280
281 virtual void accept0(BaseVisitor *visitor) = 0;
284
285// attributes
287};
288
289template<typename T>
291{
292 auto current = head;
293 while (current->next)
294 current = current->next;
295 return current;
296}
297
299{
300public:
302
304 : next(this), name(name)
305 { kind = K; }
306
308 : name(name)
309 {
310 kind = K;
311 next = previous->next;
312 previous->next = this;
313 }
314
316 {
318 next = nullptr;
319 return head;
320 }
321
323
326
331
333
335 {
338 return result;
339 }
340
341 void toString(QString *out) const
342 {
343 for (const UiQualifiedId *it = this; it; it = it->next) {
344 out->append(it->name);
345 if (it->next)
346 out->append(QLatin1Char('.'));
347 }
348 }
349
350// attributes
355};
356
386
419
424
426{
427public:
429
431};
432
459
460
479
498
519
538
557
576
595
596
617
647
668
696
718
731
760
789
791{
792public:
794
796 next (this) { kind = K; }
797
799 {
800 kind = K;
801 next = previous->next;
802 previous->next = this;
803 }
804
806
809
812
813 inline Elision *finish ()
814 {
815 Elision *front = next;
816 next = nullptr;
817 return front;
818 }
819
820// attributes
823};
824
843
862
863struct BoundNames : public QList<BoundName>
864{
865 int indexOf(const QString &name, int from = 0) const
866 {
867 auto found = std::find_if(constBegin() + from, constEnd(),
868 [&name](const BoundName &it) { return it.id == name; });
869 if (found == constEnd())
870 return -1;
871 return found - constBegin();
872 }
873
874 bool contains(const QString &name) const
875 {
876 return indexOf(name) != -1;
877 }
878};
879
880/*!
881\internal
882This class is needed to pass the information about the equalToken in the parser, and is only needed
883during AST construction. It behaves exactly like the expression it contains: that avoids changing
884all the usages in qqmljs.g from ExpressionNode to InitializerExpression for every rule expecting a
885InitializerOpt_In or InitializerOpt.
886*/
912
914{
915public:
917
918 enum Type {
919 // object literal types
924
925 // used by both bindings and literals
928
929 // binding types
931 };
932
933private:
934 /*!
935 \internal
936 Hide InitializerExpression from the AST. InitializerExpression is only needed during parsing for
937 the AST construction, and it is not possible for the parser to directly embed the location of
938 equal tokens inside the PatternElement without the InitializerExpression.
939 */
940 void unwrapInitializer()
941 {
945 }
946 }
947public:
948
950 : initializer(i), type(t)
951 {
952 kind = K;
954 }
955
964
972
976
979
982
987
990
991 virtual void boundNames(BoundNames *names);
992
993// attributes
1001 // when used in a VariableDeclarationList
1004 bool isForDeclaration = false;
1006};
1007
1051
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
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: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