aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/parser/qqmljsast_p.h
diff options
context:
space:
mode:
authorFabian Kosmale <fabian.kosmale@qt.io>2021-11-15 16:16:16 +0100
committerFabian Kosmale <fabian.kosmale@qt.io>2021-11-17 20:59:23 +0100
commitc9380aa42805cf55736dc87c87149d912282c0ae (patch)
treea1b824fcdf3768ed4e6d4477ef180649e239bd0d /src/qml/parser/qqmljsast_p.h
parentf9bddfa12d233d9ef01299869f4d491d62a0828e (diff)
Clean up property attributes (2/2)
This commit introduces a new AST node for property attributes (currently required, default and readonly). That node is not integrated into our visitors, as it is only meant as an internal implementaion detail of UiPublicMember. All information stored in it is meant to be accessed by UiPublicMember's methods (see also the note below). We use an union of SourceLocation and a node pointer to only pay the overhead of the new node for properties; signals simply store the signal token. The grammar is rewritten with a new UiPropertyAttributes rule, which avoids quite a bit of duplication in various rules, which had to deal with the combinatorial explosion of attributes. Some parse errors are now turned into semantic errors instead (readonly without initializer, required with initializer). By centralizing the handling of attributes in the grammar, we now can easily support e.g. default properties with a list initializer. As part of this restructuring, UiPublicMember's firstSourceLocation is fixed to ensure that we actually return the first source location, independent of the order in which the attributes are written. Note: In theory, we would not need to make UiPropertyAttributes an AST node. It could be a simple data class. However, the parser currently assumes that every pointer in its parser stack is an AST node, and touching that part would be a larger undertaking. As we use a pool allocator, the cost is not that high (though we use more memory from the pool then we would strictly need to). Change-Id: Ia1d9fd7a6553d443cc57bc3d773f5be0aebe0e0e Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Diffstat (limited to 'src/qml/parser/qqmljsast_p.h')
-rw-r--r--src/qml/parser/qqmljsast_p.h103
1 files changed, 84 insertions, 19 deletions
diff --git a/src/qml/parser/qqmljsast_p.h b/src/qml/parser/qqmljsast_p.h
index 6e51a906bb..f9e62c79fd 100644
--- a/src/qml/parser/qqmljsast_p.h
+++ b/src/qml/parser/qqmljsast_p.h
@@ -56,11 +56,12 @@
#include <private/qqmljsmemorypool_p.h>
-#include <QtCore/qstring.h>
#include <QtCore/qversionnumber.h>
QT_BEGIN_NAMESPACE
+class QString;
+
namespace QQmlJS {
class Parser;
}
@@ -257,6 +258,7 @@ public:
Kind_UiPragma,
Kind_UiProgram,
Kind_UiParameterList,
+ Kind_UiPropertyAttributes,
Kind_UiPublicMember,
Kind_UiQualifiedId,
Kind_UiScriptBinding,
@@ -3369,6 +3371,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:
@@ -3389,15 +3431,10 @@ public:
SourceLocation firstSourceLocation() const override
{
- // ### FIXME: return the first(!) modifier token
- 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
@@ -3410,15 +3447,44 @@ public:
return semicolonToken;
}
- SourceLocation defaultToken() const { return m_defaultToken; }
+ SourceLocation defaultToken() const
+ {
+ return hasAttributes ? m_attributes->defaultToken() : SourceLocation {};
+ }
bool isDefaultMember() const { return defaultToken().isValid(); }
- SourceLocation requiredToken() const { return m_requiredToken; }
+
+ SourceLocation requiredToken() const
+ {
+ return hasAttributes ? m_attributes->requiredToken() : SourceLocation {};
+ }
bool isRequired() const { return requiredToken().isValid(); }
- SourceLocation readonlyToken() const { return m_readonlyToken; }
+
+ 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;
@@ -3426,17 +3492,16 @@ public:
UiObjectMember *binding; // initialized with a QML object or array.
UiParameterList *parameters;
// TODO: merge source locations
- SourceLocation propertyToken;
SourceLocation typeModifierToken;
SourceLocation typeToken;
SourceLocation identifierToken;
SourceLocation colonToken;
SourceLocation semicolonToken;
private:
- friend class QQmlJS::Parser;
- SourceLocation m_defaultToken;
- SourceLocation m_readonlyToken;
- SourceLocation m_requiredToken;
+ union {
+ SourceLocation m_propertyToken = SourceLocation {};
+ UiPropertyAttributes *m_attributes;
+ };
};
class QML_PARSER_EXPORT UiObjectDefinition: public UiObjectMember