aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/parser/qqmljsast_p.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/parser/qqmljsast_p.h')
-rw-r--r--src/qml/parser/qqmljsast_p.h383
1 files changed, 260 insertions, 123 deletions
diff --git a/src/qml/parser/qqmljsast_p.h b/src/qml/parser/qqmljsast_p.h
index cb6d5fa3ee..2bb9b3f001 100644
--- a/src/qml/parser/qqmljsast_p.h
+++ b/src/qml/parser/qqmljsast_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QQMLJSAST_P_H
#define QQMLJSAST_P_H
@@ -56,11 +20,19 @@
#include <private/qqmljsmemorypool_p.h>
-#include <QtCore/qstring.h>
+#include <QtCore/qtaggedpointer.h>
#include <QtCore/qversionnumber.h>
+#include <type_traits>
+
QT_BEGIN_NAMESPACE
+class QString;
+
+namespace QQmlJS {
+ class Parser;
+}
+
#define QQMLJS_DECLARE_AST_NODE(name) \
enum { K = Kind_##name };
@@ -126,10 +98,10 @@ enum class VariableScope {
template <typename T1, typename T2>
T1 cast(T2 *ast)
{
- if (ast && ast->kind == static_cast<T1>(0)->K)
+ if (ast && ast->kind == std::remove_pointer_t<T1>::K)
return static_cast<T1>(ast);
- return 0;
+ return nullptr;
}
FunctionExpression *asAnonymousFunctionDefinition(AST::Node *n);
@@ -177,6 +149,7 @@ public:
Kind_ClassDeclaration,
Kind_IdentifierExpression,
Kind_IdentifierPropertyName,
+ Kind_InitializerExpression,
Kind_ComputedPropertyName,
Kind_IfStatement,
Kind_LabelledStatement,
@@ -239,7 +212,7 @@ public:
Kind_PatternProperty,
Kind_PatternPropertyList,
Kind_Type,
- Kind_TypeArgumentList,
+ Kind_TypeArgument,
Kind_TypeAnnotation,
Kind_UiArrayBinding,
@@ -250,9 +223,11 @@ public:
Kind_UiObjectInitializer,
Kind_UiObjectMemberList,
Kind_UiArrayMemberList,
+ Kind_UiPragmaValueList,
Kind_UiPragma,
Kind_UiProgram,
Kind_UiParameterList,
+ Kind_UiPropertyAttributes,
Kind_UiPublicMember,
Kind_UiQualifiedId,
Kind_UiScriptBinding,
@@ -307,12 +282,6 @@ public:
node->accept(visitor);
}
- // ### Remove when we can. This is part of the qmldevtools library, though.
- inline static void acceptChild(Node *node, BaseVisitor *visitor)
- {
- return accept(node, visitor);
- }
-
virtual void accept0(BaseVisitor *visitor) = 0;
virtual SourceLocation firstSourceLocation() const = 0;
virtual SourceLocation lastSourceLocation() const = 0;
@@ -360,12 +329,33 @@ public:
{ return identifierToken; }
SourceLocation lastSourceLocation() const override
- { return lastListElement(this)->identifierToken; }
+ {
+ return lastListElement(this)->lastOwnSourceLocation();
+ }
+
+ SourceLocation lastOwnSourceLocation() const { return identifierToken; }
+
+ QString toString() const
+ {
+ QString result;
+ toString(&result);
+ return result;
+ }
+
+ void toString(QString *out) const
+ {
+ for (const UiQualifiedId *it = this; it; it = it->next) {
+ out->append(it->name);
+ if (it->next)
+ out->append(QLatin1Char('.'));
+ }
+ }
// attributes
UiQualifiedId *next;
QStringView name;
SourceLocation identifierToken;
+ SourceLocation dotToken;
};
class QML_PARSER_EXPORT Type: public Node
@@ -373,9 +363,9 @@ class QML_PARSER_EXPORT Type: public Node
public:
QQMLJS_DECLARE_AST_NODE(Type)
- Type(UiQualifiedId *typeId, Node *typeArguments = nullptr)
+ Type(UiQualifiedId *typeId, Type *typeArgument = nullptr)
: typeId(typeId)
- , typeArguments(typeArguments)
+ , typeArgument(typeArgument ? typeArgument->typeId : nullptr)
{ kind = K; }
void accept0(BaseVisitor *visitor) override;
@@ -384,53 +374,14 @@ public:
{ return typeId->firstSourceLocation(); }
SourceLocation lastSourceLocation() const override
- { return typeArguments ? typeArguments->lastSourceLocation() : typeId->lastSourceLocation(); }
+ { return typeArgument ? typeArgument->lastSourceLocation() : typeId->lastSourceLocation(); }
QString toString() const;
void toString(QString *out) const;
// attributes
UiQualifiedId *typeId;
- Node *typeArguments; // TypeArgumentList
-};
-
-
-class QML_PARSER_EXPORT TypeArgumentList: public Node
-{
-public:
- QQMLJS_DECLARE_AST_NODE(TypeArgumentList)
-
- TypeArgumentList(Type *typeId)
- : typeId(typeId)
- , next(nullptr)
- { kind = K; }
-
- TypeArgumentList(TypeArgumentList *previous, Type *typeId)
- : typeId(typeId)
- {
- kind = K;
- next = previous->next;
- previous->next = this;
- }
-
- void accept0(BaseVisitor *visitor) override;
-
- SourceLocation firstSourceLocation() const override
- { return typeId->firstSourceLocation(); }
-
- SourceLocation lastSourceLocation() const override
- { return lastListElement(this)->typeId->lastSourceLocation(); }
-
- inline TypeArgumentList *finish()
- {
- TypeArgumentList *front = next;
- next = nullptr;
- return front;
- }
-
-// attributes
- Type *typeId;
- TypeArgumentList *next;
+ UiQualifiedId *typeArgument;
};
class QML_PARSER_EXPORT TypeAnnotation: public Node
@@ -460,6 +411,7 @@ public:
ExpressionNode() {}
ExpressionNode *expressionCast() override;
+ bool containsOptionalChain() const;
AST::FormalParameterList *reparseAsFormalParameterList(MemoryPool *pool);
@@ -734,6 +686,7 @@ public:
void accept0(BaseVisitor *visitor) override;
+ bool hasNoSubstitution = false;
QStringView value;
QStringView rawValue;
ExpressionNode *expression;
@@ -893,12 +846,14 @@ struct QML_PARSER_EXPORT BoundName
};
QString id;
+ QQmlJS::SourceLocation location;
QTaggedPointer<TypeAnnotation, Type> typeAnnotation;
- BoundName(const QString &id, TypeAnnotation *typeAnnotation, Type type = Declared)
- : id(id), typeAnnotation(typeAnnotation, type)
+ BoundName(const QString &id, const QQmlJS::SourceLocation &location,
+ TypeAnnotation *typeAnnotation, Type type = Declared)
+ : id(id), location(location), typeAnnotation(typeAnnotation, type)
{}
BoundName() = default;
- QString typeName() const { return typeAnnotation ? typeAnnotation->type->toString() : QString(); }
+
bool isInjected() const { return typeAnnotation.tag() == Injected; }
};
@@ -919,6 +874,39 @@ struct BoundNames : public QVector<BoundName>
}
};
+/*!
+\internal
+This class is needed to pass the information about the equalToken in the parser, and is only needed
+during AST construction. It behaves exactly like the expression it contains: that avoids changing
+all the usages in qqmljs.g from ExpressionNode to InitializerExpression for every rule expecting a
+InitializerOpt_In or InitializerOpt.
+*/
+class QML_PARSER_EXPORT InitializerExpression : public ExpressionNode
+{
+public:
+ QQMLJS_DECLARE_AST_NODE(InitializerExpression)
+
+ InitializerExpression(ExpressionNode *e) : expression(e) { kind = K; }
+
+ void accept0(BaseVisitor *visitor) override;
+
+ SourceLocation firstSourceLocation() const override
+ { return equalToken; }
+
+ SourceLocation lastSourceLocation() const override { return expression->lastSourceLocation(); }
+
+ FunctionExpression *asFunctionDefinition() override
+ {
+ return expression->asFunctionDefinition();
+ }
+
+ ClassExpression *asClassDefinition() override { return expression->asClassDefinition(); }
+
+ // attributes
+ ExpressionNode *expression;
+ SourceLocation equalToken;
+};
+
class QML_PARSER_EXPORT PatternElement : public Node
{
public:
@@ -939,9 +927,28 @@ public:
Binding,
};
+private:
+ /*!
+ \internal
+ Hide InitializerExpression from the AST. InitializerExpression is only needed during parsing for
+ the AST construction, and it is not possible for the parser to directly embed the location of
+ equal tokens inside the PatternElement without the InitializerExpression.
+ */
+ void unwrapInitializer()
+ {
+ if (auto unwrapped = AST::cast<InitializerExpression *>(initializer)) {
+ equalToken = unwrapped->equalToken;
+ initializer = unwrapped->expression;
+ }
+ }
+public:
+
PatternElement(ExpressionNode *i = nullptr, Type t = Literal)
: initializer(i), type(t)
- { kind = K; }
+ {
+ kind = K;
+ unwrapInitializer();
+ }
PatternElement(QStringView n, TypeAnnotation *typeAnnotation = nullptr, ExpressionNode *i = nullptr, Type t = Binding)
: bindingIdentifier(n), initializer(i), type(t)
@@ -949,6 +956,7 @@ public:
{
Q_ASSERT(t >= RestElement);
kind = K;
+ unwrapInitializer();
}
PatternElement(Pattern *pattern, ExpressionNode *i = nullptr, Type t = Binding)
@@ -956,6 +964,7 @@ public:
{
Q_ASSERT(t >= RestElement);
kind = K;
+ unwrapInitializer();
}
void accept0(BaseVisitor *visitor) override;
@@ -979,6 +988,7 @@ public:
// attributes
SourceLocation identifierToken;
+ SourceLocation equalToken;
QStringView bindingIdentifier;
ExpressionNode *bindingTarget = nullptr;
ExpressionNode *initializer = nullptr;
@@ -1198,6 +1208,7 @@ public:
ExpressionNode *expression;
SourceLocation lbracketToken;
SourceLocation rbracketToken;
+ bool isOptional = false;
};
class QML_PARSER_EXPORT FieldMemberExpression: public LeftHandSideExpression
@@ -1222,6 +1233,7 @@ public:
QStringView name;
SourceLocation dotToken;
SourceLocation identifierToken;
+ bool isOptional = false;
};
class QML_PARSER_EXPORT TaggedTemplate : public LeftHandSideExpression
@@ -1314,6 +1326,7 @@ public:
ArgumentList *arguments;
SourceLocation lparenToken;
SourceLocation rparenToken;
+ bool isOptional = false;
};
class QML_PARSER_EXPORT ArgumentList: public Node
@@ -2957,7 +2970,6 @@ public:
ExportDeclaration(FromClause *fromClause)
: fromClause(fromClause)
{
- exportAll = true;
kind = K;
}
@@ -2980,6 +2992,11 @@ public:
kind = K;
}
+ bool exportsAll() const
+ {
+ return fromClause && !exportClause;
+ }
+
void accept0(BaseVisitor *visitor) override;
SourceLocation firstSourceLocation() const override
@@ -2989,7 +3006,6 @@ public:
// attributes
SourceLocation exportToken;
- bool exportAll = false;
ExportClause *exportClause = nullptr;
FromClause *fromClause = nullptr;
Node *variableStatementOrDeclaration = nullptr;
@@ -3122,13 +3138,53 @@ public:
UiObjectMember *member;
};
+class QML_PARSER_EXPORT UiPragmaValueList: public Node
+{
+public:
+ QQMLJS_DECLARE_AST_NODE(UiPragmaValueList)
+
+ UiPragmaValueList(QStringView value)
+ : value(value)
+ , next(this)
+ {
+ kind = K;
+ }
+
+ UiPragmaValueList(UiPragmaValueList *previous, QStringView value)
+ : value(value)
+ {
+ kind = K;
+ next = previous->next;
+ previous->next = this;
+ }
+
+ void accept0(BaseVisitor *visitor) override;
+
+ SourceLocation firstSourceLocation() const override
+ { return location; }
+
+ SourceLocation lastSourceLocation() const override
+ { return lastListElement(this)->location; }
+
+ UiPragmaValueList *finish()
+ {
+ UiPragmaValueList *head = next;
+ next = nullptr;
+ return head;
+ }
+
+ QStringView value;
+ UiPragmaValueList *next;
+ SourceLocation location;
+};
+
class QML_PARSER_EXPORT UiPragma: public Node
{
public:
QQMLJS_DECLARE_AST_NODE(UiPragma)
- UiPragma(QStringView name)
- : name(name)
+ UiPragma(QStringView name, UiPragmaValueList *values = nullptr)
+ : name(name), values(values)
{ kind = K; }
void accept0(BaseVisitor *visitor) override;
@@ -3141,7 +3197,10 @@ public:
// attributes
QStringView name;
+ UiPragmaValueList *values;
SourceLocation pragmaToken;
+ SourceLocation pragmaIdToken;
+ SourceLocation colonToken;
SourceLocation semicolonToken;
};
@@ -3316,11 +3375,11 @@ class QML_PARSER_EXPORT UiParameterList: public Node
public:
QQMLJS_DECLARE_AST_NODE(UiParameterList)
- UiParameterList(UiQualifiedId *t, QStringView n):
+ UiParameterList(Type *t, QStringView n):
type (t), name (n), next (this)
{ kind = K; }
- UiParameterList(UiParameterList *previous, UiQualifiedId *t, QStringView n):
+ UiParameterList(UiParameterList *previous, Type *t, QStringView n):
type (t), name (n)
{
kind = K;
@@ -3336,7 +3395,12 @@ public:
SourceLocation lastSourceLocation() const override
{
auto last = lastListElement(this);
- return (last->colonToken.isValid() ? last->propertyTypeToken : last->identifierToken);
+ return last->lastOwnSourceLocation();
+ }
+
+ SourceLocation lastOwnSourceLocation() const
+ {
+ return (colonToken.isValid() ? propertyTypeToken : identifierToken);
}
inline UiParameterList *finish ()
@@ -3347,7 +3411,7 @@ public:
}
// attributes
- UiQualifiedId *type;
+ Type *type;
QStringView name;
UiParameterList *next;
SourceLocation commaToken;
@@ -3356,6 +3420,46 @@ public:
SourceLocation colonToken;
};
+class QML_PARSER_EXPORT UiPropertyAttributes : public Node
+{
+ QQMLJS_DECLARE_AST_NODE(UiPropertyAttributes)
+public:
+ UiPropertyAttributes() { kind = K; }
+
+ SourceLocation defaultToken() const { return m_defaultToken; }
+ bool isDefaultMember() const { return defaultToken().isValid(); }
+ SourceLocation requiredToken() const { return m_requiredToken; }
+ bool isRequired() const { return requiredToken().isValid(); }
+ SourceLocation readonlyToken() const { return m_readonlyToken; }
+ bool isReadonly() const { return readonlyToken().isValid(); }
+
+ SourceLocation propertyToken() const { return m_propertyToken; }
+
+ template <bool InvalidIsLargest = true>
+ static bool compareLocationsByBegin(const SourceLocation *& lhs, const SourceLocation *& rhs)
+ {
+ if (lhs->isValid() && rhs->isValid())
+ return lhs->begin() < rhs->begin();
+ else if (lhs->isValid())
+ return InvalidIsLargest;
+ else
+ return !InvalidIsLargest;
+ }
+
+ void accept0(BaseVisitor *) override {} // intentionally do nothing
+
+ SourceLocation firstSourceLocation() const override;
+
+ SourceLocation lastSourceLocation() const override;
+
+private:
+ friend class QQmlJS::Parser;
+ SourceLocation m_defaultToken;
+ SourceLocation m_readonlyToken;
+ SourceLocation m_requiredToken;
+ SourceLocation m_propertyToken;
+};
+
class QML_PARSER_EXPORT UiPublicMember: public UiObjectMember
{
public:
@@ -3363,27 +3467,23 @@ public:
UiPublicMember(UiQualifiedId *memberType,
QStringView name)
- : type(Property), memberType(memberType), name(name), statement(nullptr), binding(nullptr), isDefaultMember(false), isReadonlyMember(false), parameters(nullptr)
+ : type(Property), memberType(memberType), name(name), statement(nullptr), binding(nullptr), parameters(nullptr)
{ kind = K; }
UiPublicMember(UiQualifiedId *memberType,
QStringView name,
Statement *statement)
- : type(Property), memberType(memberType), name(name), statement(statement), binding(nullptr), isDefaultMember(false), isReadonlyMember(false), parameters(nullptr)
+ : type(Property), memberType(memberType), name(name), statement(statement), binding(nullptr), parameters(nullptr)
{ kind = K; }
void accept0(BaseVisitor *visitor) override;
SourceLocation firstSourceLocation() const override
{
- if (defaultToken.isValid())
- return defaultToken;
- else if (readonlyToken.isValid())
- return readonlyToken;
- else if (requiredToken.isValid())
- return requiredToken;
-
- return propertyToken;
+ if (hasAttributes)
+ return m_attributes->firstSourceLocation();
+ else
+ return m_propertyToken;
}
SourceLocation lastSourceLocation() const override
@@ -3396,27 +3496,61 @@ public:
return semicolonToken;
}
+ SourceLocation defaultToken() const
+ {
+ return hasAttributes ? m_attributes->defaultToken() : SourceLocation {};
+ }
+ bool isDefaultMember() const { return defaultToken().isValid(); }
+
+ SourceLocation requiredToken() const
+ {
+ return hasAttributes ? m_attributes->requiredToken() : SourceLocation {};
+ }
+ bool isRequired() const { return requiredToken().isValid(); }
+
+ SourceLocation readonlyToken() const
+ {
+ return hasAttributes ? m_attributes->readonlyToken() : SourceLocation {};
+ }
+ bool isReadonly() const { return readonlyToken().isValid(); }
+
+ void setAttributes(UiPropertyAttributes *attributes)
+ {
+ m_attributes = attributes;
+ hasAttributes = true;
+ }
+
+ SourceLocation propertyToken() const
+ {
+ return hasAttributes ? m_attributes->propertyToken() : m_propertyToken;
+ }
+
+ void setPropertyToken(SourceLocation token)
+ {
+ m_propertyToken = token;
+ hasAttributes = false;
+ }
+
// attributes
- enum { Signal, Property } type;
+ enum : bool { Signal, Property } type;
+ bool hasAttributes = false;
QStringView typeModifier;
UiQualifiedId *memberType;
QStringView name;
Statement *statement; // initialized with a JS expression
UiObjectMember *binding; // initialized with a QML object or array.
- bool isDefaultMember;
- bool isReadonlyMember;
- bool isRequired = false;
UiParameterList *parameters;
// TODO: merge source locations
- SourceLocation defaultToken;
- SourceLocation readonlyToken;
- SourceLocation propertyToken;
- SourceLocation requiredToken;
SourceLocation typeModifierToken;
SourceLocation typeToken;
SourceLocation identifierToken;
SourceLocation colonToken;
SourceLocation semicolonToken;
+private:
+ union {
+ SourceLocation m_propertyToken = SourceLocation {};
+ UiPropertyAttributes *m_attributes;
+ };
};
class QML_PARSER_EXPORT UiObjectDefinition: public UiObjectMember
@@ -3463,6 +3597,7 @@ public:
QStringView name;
UiObjectDefinition* component;
SourceLocation componentToken;
+ SourceLocation identifierToken;
};
class QML_PARSER_EXPORT UiSourceElement: public UiObjectMember
@@ -3574,7 +3709,7 @@ public:
{ kind = K; }
SourceLocation firstSourceLocation() const override
- { return qualifiedId->identifierToken; }
+ { Q_ASSERT(qualifiedId); return qualifiedId->identifierToken; }
SourceLocation lastSourceLocation() const override
{ return rbracketToken; }
@@ -3661,6 +3796,8 @@ public:
// attributes
SourceLocation enumToken;
+ SourceLocation identifierToken;
+ SourceLocation lbraceToken;
SourceLocation rbraceToken;
QStringView name;
UiEnumMemberList *members;