aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2023-02-16 11:28:33 +0100
committerUlf Hermann <ulf.hermann@qt.io>2023-02-22 11:00:19 +0100
commitbdb2bb561054ad7e95ced2f4b79533d13000172b (patch)
tree8cf445d89c335bd13ca21720c87aa5bc69271ece /src
parent763dad999dc5bf6109158283c9dc6b396a4e75f6 (diff)
QML: Allow pragmas with multiple values
This will be needed in follow-up changes. Task-number: QTBUG-94807 Change-Id: I6243ea31290251c30dd0aceaae878568bc1c0525 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Diffstat (limited to 'src')
-rw-r--r--src/qml/compiler/qqmlirbuilder.cpp123
-rw-r--r--src/qml/compiler/qv4codegen.cpp5
-rw-r--r--src/qml/compiler/qv4codegen_p.h1
-rw-r--r--src/qml/parser/qqmljs.g27
-rw-r--r--src/qml/parser/qqmljsast.cpp9
-rw-r--r--src/qml/parser/qqmljsast_p.h47
-rw-r--r--src/qml/parser/qqmljsastfwd_p.h1
-rw-r--r--src/qml/parser/qqmljsastvisitor_p.h4
-rw-r--r--src/qmlcompiler/qqmljsimportvisitor.cpp77
-rw-r--r--src/qmldom/qqmldomastdumper.cpp8
-rw-r--r--src/qmldom/qqmldomcomments.cpp3
-rw-r--r--src/qmldom/qqmldomreformatter.cpp10
12 files changed, 233 insertions, 82 deletions
diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp
index 6b2f795daf..e85c0fe310 100644
--- a/src/qml/compiler/qqmlirbuilder.cpp
+++ b/src/qml/compiler/qqmlirbuilder.cpp
@@ -767,10 +767,10 @@ struct PragmaParser
pragma->type = type();
- if (!assign(pragma, node->value)) {
+ if (QQmlJS::AST::UiPragmaValueList *bad = assign(pragma, node->values)) {
builder->recordError(
node->pragmaToken, QCoreApplication::translate(
- "QQmlParser", "Unknown %1 '%2' in pragma").arg(name(), node->value));
+ "QQmlParser", "Unknown %1 '%2' in pragma").arg(name(), bad->value));
return false;
}
@@ -795,63 +795,90 @@ private:
Q_UNREACHABLE_RETURN(Pragma::PragmaType(-1));
}
- static bool assign(Pragma *pragma, QStringView value)
+ template<typename F>
+ static QQmlJS::AST::UiPragmaValueList *iterateValues(
+ QQmlJS::AST::UiPragmaValueList *input, F &&process)
+ {
+ for (QQmlJS::AST::UiPragmaValueList *i = input; i; i = i->next) {
+ if (!process(i->value))
+ return i;
+ }
+ return nullptr;
+ }
+
+ static QQmlJS::AST::UiPragmaValueList *assign(
+ Pragma *pragma, QQmlJS::AST::UiPragmaValueList *values)
{
// We could use QMetaEnum here to make the code more compact,
// but it's probably more expensive.
if constexpr (std::is_same_v<Argument, Pragma::ComponentBehaviorValue>) {
- if (value == "Unbound"_L1) {
- pragma->componentBehavior = Pragma::Unbound;
- return true;
- }
- if (value == "Bound"_L1) {
- pragma->componentBehavior = Pragma::Bound;
- return true;
- }
+ return iterateValues(values, [pragma](QStringView value) {
+ if (value == "Unbound"_L1) {
+ pragma->componentBehavior = Pragma::Unbound;
+ return true;
+ }
+ if (value == "Bound"_L1) {
+ pragma->componentBehavior = Pragma::Bound;
+ return true;
+ }
+ return false;
+ });
} else if constexpr (std::is_same_v<Argument, Pragma::ListPropertyAssignBehaviorValue>) {
- if (value == "Append"_L1) {
- pragma->listPropertyAssignBehavior = Pragma::Append;
- return true;
- }
- if (value == "Replace"_L1) {
- pragma->listPropertyAssignBehavior = Pragma::Replace;
- return true;
- }
- if (value == "ReplaceIfNotDefault"_L1) {
- pragma->listPropertyAssignBehavior = Pragma::ReplaceIfNotDefault;
- return true;
- }
+ return iterateValues(values, [pragma](QStringView value) {
+ if (value == "Append"_L1) {
+ pragma->listPropertyAssignBehavior = Pragma::Append;
+ return true;
+ }
+ if (value == "Replace"_L1) {
+ pragma->listPropertyAssignBehavior = Pragma::Replace;
+ return true;
+ }
+ if (value == "ReplaceIfNotDefault"_L1) {
+ pragma->listPropertyAssignBehavior = Pragma::ReplaceIfNotDefault;
+ return true;
+ }
+ return false;
+ });
} else if constexpr (std::is_same_v<Argument, Pragma::FunctionSignatureBehaviorValue>) {
- if (value == "Ignored"_L1) {
- pragma->functionSignatureBehavior = Pragma::Ignored;
- return true;
- }
- if (value == "Enforced"_L1) {
- pragma->functionSignatureBehavior = Pragma::Enforced;
- return true;
- }
+ return iterateValues(values, [pragma](QStringView value) {
+ if (value == "Ignored"_L1) {
+ pragma->functionSignatureBehavior = Pragma::Ignored;
+ return true;
+ }
+ if (value == "Enforced"_L1) {
+ pragma->functionSignatureBehavior = Pragma::Enforced;
+ return true;
+ }
+ return false;
+ });
} else if constexpr (std::is_same_v<Argument, Pragma::NativeMethodBehaviorValue>) {
- if (value == "AcceptThisObject"_L1) {
- pragma->nativeMethodBehavior = Pragma::AcceptThisObject;
- return true;
- }
- if (value == "RejectThisObject"_L1) {
- pragma->nativeMethodBehavior = Pragma::RejectThisObject;
- return true;
- }
+ return iterateValues(values, [pragma](QStringView value) {
+ if (value == "AcceptThisObject"_L1) {
+ pragma->nativeMethodBehavior = Pragma::AcceptThisObject;
+ return true;
+ }
+ if (value == "RejectThisObject"_L1) {
+ pragma->nativeMethodBehavior = Pragma::RejectThisObject;
+ return true;
+ }
+ return false;
+ });
} else if constexpr (std::is_same_v<Argument, Pragma::ValueTypeBehaviorValue>) {
- if (value == "Reference"_L1) {
- pragma->valueTypeBehavior = Pragma::Reference;
- return true;
- }
- if (value == "Copy"_L1) {
- pragma->valueTypeBehavior = Pragma::Copy;
- return true;
- }
+ return iterateValues(values, [pragma](QStringView value) {
+ if (value == "Reference"_L1) {
+ pragma->valueTypeBehavior = Pragma::Reference;
+ return true;
+ }
+ if (value == "Copy"_L1) {
+ pragma->valueTypeBehavior = Pragma::Copy;
+ return true;
+ }
+ return false;
+ });
}
- return false;
+ Q_UNREACHABLE_RETURN(nullptr);
}
static bool isUnique(IRBuilder *builder)
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp
index 5df9b3fa4c..3b0dac0766 100644
--- a/src/qml/compiler/qv4codegen.cpp
+++ b/src/qml/compiler/qv4codegen.cpp
@@ -905,6 +905,11 @@ bool Codegen::visit(UiHeaderItemList *)
Q_UNREACHABLE_RETURN(false);
}
+bool Codegen::visit(UiPragmaValueList *)
+{
+ Q_UNREACHABLE_RETURN(false);
+}
+
bool Codegen::visit(UiPragma *)
{
Q_UNREACHABLE_RETURN(false);
diff --git a/src/qml/compiler/qv4codegen_p.h b/src/qml/compiler/qv4codegen_p.h
index fddbcc7d31..e1f17dc89b 100644
--- a/src/qml/compiler/qv4codegen_p.h
+++ b/src/qml/compiler/qv4codegen_p.h
@@ -595,6 +595,7 @@ protected:
bool visit(QQmlJS::AST::UiArrayMemberList *ast) override;
bool visit(QQmlJS::AST::UiImport *ast) override;
bool visit(QQmlJS::AST::UiHeaderItemList *ast) override;
+ bool visit(QQmlJS::AST::UiPragmaValueList *ast) override;
bool visit(QQmlJS::AST::UiPragma *ast) override;
bool visit(QQmlJS::AST::UiObjectInitializer *ast) override;
bool visit(QQmlJS::AST::UiObjectMemberList *ast) override;
diff --git a/src/qml/parser/qqmljs.g b/src/qml/parser/qqmljs.g
index 394edf0fed..13c54d387b 100644
--- a/src/qml/parser/qqmljs.g
+++ b/src/qml/parser/qqmljs.g
@@ -217,6 +217,7 @@ public:
AST::UiProgram *UiProgram;
AST::UiHeaderItemList *UiHeaderItemList;
+ AST::UiPragmaValueList *UiPragmaValueList;
AST::UiPragma *UiPragma;
AST::UiImport *UiImport;
AST::UiParameterList *UiParameterList;
@@ -717,10 +718,31 @@ UiHeaderItemList: UiHeaderItemList UiImport;
./
PragmaId: JsIdentifier;
+PragmaValue: JsIdentifier;
Semicolon: T_AUTOMATIC_SEMICOLON;
Semicolon: T_SEMICOLON;
+UiPragmaValueList: PragmaValue;
+/.
+ case $rule_number: {
+ AST::UiPragmaValueList *list
+ = new (pool) AST::UiPragmaValueList(stringRef(1));
+ list->location = loc(1);
+ sym(1).Node = list;
+ } break;
+./
+
+UiPragmaValueList: UiPragmaValueList T_COMMA PragmaValue;
+/.
+ case $rule_number: {
+ AST::UiPragmaValueList *list
+ = new (pool) AST::UiPragmaValueList(sym(1).UiPragmaValueList, stringRef(3));
+ list->location = loc(3);
+ sym(1).Node = list;
+ } break;
+./
+
UiPragma: T_PRAGMA PragmaId Semicolon;
/.
case $rule_number: {
@@ -731,10 +753,11 @@ UiPragma: T_PRAGMA PragmaId Semicolon;
} break;
./
-UiPragma: T_PRAGMA PragmaId T_COLON JsIdentifier Semicolon;
+UiPragma: T_PRAGMA PragmaId T_COLON UiPragmaValueList Semicolon;
/.
case $rule_number: {
- AST::UiPragma *pragma = new (pool) AST::UiPragma(stringRef(2), stringRef(4));
+ AST::UiPragma *pragma = new (pool) AST::UiPragma(
+ stringRef(2), sym(4).UiPragmaValueList->finish());
pragma->pragmaToken = loc(1);
pragma->semicolonToken = loc(5);
sym(1).Node = pragma;
diff --git a/src/qml/parser/qqmljsast.cpp b/src/qml/parser/qqmljsast.cpp
index 5408f29900..e3ed876473 100644
--- a/src/qml/parser/qqmljsast.cpp
+++ b/src/qml/parser/qqmljsast.cpp
@@ -1336,6 +1336,15 @@ void UiImport::accept0(BaseVisitor *visitor)
visitor->endVisit(this);
}
+void UiPragmaValueList::accept0(BaseVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+
+ visitor->endVisit(this);
+}
+
+
void UiPragma::accept0(BaseVisitor *visitor)
{
if (visitor->visit(this)) {
diff --git a/src/qml/parser/qqmljsast_p.h b/src/qml/parser/qqmljsast_p.h
index 77af38aaca..e7052f324e 100644
--- a/src/qml/parser/qqmljsast_p.h
+++ b/src/qml/parser/qqmljsast_p.h
@@ -222,6 +222,7 @@ public:
Kind_UiObjectInitializer,
Kind_UiObjectMemberList,
Kind_UiArrayMemberList,
+ Kind_UiPragmaValueList,
Kind_UiPragma,
Kind_UiProgram,
Kind_UiParameterList,
@@ -3074,13 +3075,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, QStringView value = {})
- : name(name), value(value)
+ UiPragma(QStringView name, UiPragmaValueList *values = nullptr)
+ : name(name), values(values)
{ kind = K; }
void accept0(BaseVisitor *visitor) override;
@@ -3093,7 +3134,7 @@ public:
// attributes
QStringView name;
- QStringView value;
+ UiPragmaValueList *values;
SourceLocation pragmaToken;
SourceLocation semicolonToken;
};
diff --git a/src/qml/parser/qqmljsastfwd_p.h b/src/qml/parser/qqmljsastfwd_p.h
index e06da8b4c1..ab807386c2 100644
--- a/src/qml/parser/qqmljsastfwd_p.h
+++ b/src/qml/parser/qqmljsastfwd_p.h
@@ -128,6 +128,7 @@ class TypeAnnotation;
// ui elements
class UiProgram;
+class UiPragmaValueList;
class UiPragma;
class UiImport;
class UiPublicMember;
diff --git a/src/qml/parser/qqmljsastvisitor_p.h b/src/qml/parser/qqmljsastvisitor_p.h
index 450cfaad40..b4ee47ef0d 100644
--- a/src/qml/parser/qqmljsastvisitor_p.h
+++ b/src/qml/parser/qqmljsastvisitor_p.h
@@ -60,6 +60,7 @@ public:
// Ui
virtual bool visit(UiProgram *) = 0;
virtual bool visit(UiHeaderItemList *) = 0;
+ virtual bool visit(UiPragmaValueList *) = 0;
virtual bool visit(UiPragma *) = 0;
virtual bool visit(UiImport *) = 0;
virtual bool visit(UiPublicMember *) = 0;
@@ -84,6 +85,7 @@ public:
virtual void endVisit(UiProgram *) = 0;
virtual void endVisit(UiImport *) = 0;
virtual void endVisit(UiHeaderItemList *) = 0;
+ virtual void endVisit(UiPragmaValueList *) = 0;
virtual void endVisit(UiPragma *) = 0;
virtual void endVisit(UiPublicMember *) = 0;
virtual void endVisit(UiSourceElement *) = 0;
@@ -404,6 +406,7 @@ public:
// Ui
bool visit(UiProgram *) override { return true; }
bool visit(UiHeaderItemList *) override { return true; }
+ bool visit(UiPragmaValueList *) override { return true; }
bool visit(UiPragma *) override { return true; }
bool visit(UiImport *) override { return true; }
bool visit(UiPublicMember *) override { return true; }
@@ -428,6 +431,7 @@ public:
void endVisit(UiProgram *) override {}
void endVisit(UiImport *) override {}
void endVisit(UiHeaderItemList *) override {}
+ void endVisit(UiPragmaValueList *) override {}
void endVisit(UiPragma *) override {}
void endVisit(UiPublicMember *) override {}
void endVisit(UiSourceElement *) override {}
diff --git a/src/qmlcompiler/qqmljsimportvisitor.cpp b/src/qmlcompiler/qqmljsimportvisitor.cpp
index 380520595a..2f0e4f3321 100644
--- a/src/qmlcompiler/qqmljsimportvisitor.cpp
+++ b/src/qmlcompiler/qqmljsimportvisitor.cpp
@@ -2233,6 +2233,21 @@ bool QQmlJSImportVisitor::visit(QQmlJS::AST::UiImport *import)
return true;
}
+#if QT_VERSION >= QT_VERSION_CHECK(6, 6, 0)
+template<typename F>
+void handlePragmaValues(QQmlJS::AST::UiPragma *pragma, F &&assign)
+{
+ for (const QQmlJS::AST::UiPragmaValueList *v = pragma->values; v; v = v->next)
+ assign(v->value);
+}
+#else
+template<typename F>
+void handlePragmaValues(QQmlJS::AST::UiPragma *pragma, F &&assign)
+{
+ assign(pragma->value);
+}
+#endif
+
bool QQmlJSImportVisitor::visit(QQmlJS::AST::UiPragma *pragma)
{
if (pragma->name == u"Strict"_s) {
@@ -2248,37 +2263,41 @@ bool QQmlJSImportVisitor::visit(QQmlJS::AST::UiPragma *pragma)
} else if (pragma->name == u"Singleton") {
m_rootIsSingleton = true;
} else if (pragma->name == u"ComponentBehavior") {
- if (pragma->value == u"Bound") {
- m_scopesById.setComponentsAreBound(true);
- } else if (pragma->value == u"Unbound") {
- m_scopesById.setComponentsAreBound(false);
- } else {
- m_logger->log(
- u"Unkonwn argument \"%s\" to pragma ComponentBehavior"_s.arg(pragma->value),
- qmlSyntax, pragma->firstSourceLocation());
- }
+ handlePragmaValues(pragma, [this, pragma](QStringView value) {
+ if (value == u"Bound") {
+ m_scopesById.setComponentsAreBound(true);
+ } else if (value == u"Unbound") {
+ m_scopesById.setComponentsAreBound(false);
+ } else {
+ m_logger->log(
+ u"Unkonwn argument \"%s\" to pragma ComponentBehavior"_s.arg(value),
+ qmlSyntax, pragma->firstSourceLocation());
+ }
+ });
} else if (pragma->name == u"FunctionSignatureBehavior") {
- if (pragma->value == u"Enforced") {
- m_scopesById.setSignaturesAreEnforced(true);
- } else if (pragma->value == u"Ignored") {
- m_scopesById.setSignaturesAreEnforced(false);
- } else {
- m_logger->log(
- u"Unkonwn argument \"%s\" to pragma FunctionSignatureBehavior"_s
- .arg(pragma->value),
- qmlSyntax, pragma->firstSourceLocation());
- }
+ handlePragmaValues(pragma, [this, pragma](QStringView value) {
+ if (value == u"Enforced") {
+ m_scopesById.setSignaturesAreEnforced(true);
+ } else if (value == u"Ignored") {
+ m_scopesById.setSignaturesAreEnforced(false);
+ } else {
+ m_logger->log(
+ u"Unkonwn argument \"%s\" to pragma FunctionSignatureBehavior"_s.arg(value),
+ qmlSyntax, pragma->firstSourceLocation());
+ }
+ });
} else if (pragma->name == u"ValueTypeBehavior") {
- if (pragma->value == u"Copy") {
- m_scopesById.setValueTypesAreCopied(true);
- } else if (pragma->value == u"Reference") {
- m_scopesById.setValueTypesAreCopied(false);
- } else {
- m_logger->log(
- u"Unkonwn argument \"%s\" to pragma ValueTypeBehavior"_s
- .arg(pragma->value),
- qmlSyntax, pragma->firstSourceLocation());
- }
+ handlePragmaValues(pragma, [this, pragma](QStringView value) {
+ if (value == u"Copy") {
+ m_scopesById.setValueTypesAreCopied(true);
+ } else if (value == u"Reference") {
+ m_scopesById.setValueTypesAreCopied(false);
+ } else {
+ m_logger->log(
+ u"Unkonwn argument \"%s\" to pragma ValueTypeBehavior"_s.arg(value),
+ qmlSyntax, pragma->firstSourceLocation());
+ }
+ });
}
return true;
diff --git a/src/qmldom/qqmldomastdumper.cpp b/src/qmldom/qqmldomastdumper.cpp
index ffb776cf2d..9ae88a6dc9 100644
--- a/src/qmldom/qqmldomastdumper.cpp
+++ b/src/qmldom/qqmldomastdumper.cpp
@@ -132,6 +132,14 @@ public:
bool visit(UiHeaderItemList *) override { start(u"UiHeaderItemList"); return true; }
void endVisit(AST::UiHeaderItemList *) override { stop(u"UiHeaderItemList"); }
+#if QT_VERSION >= QT_VERSION_CHECK(6, 6, 0)
+ bool visit(UiPragmaValueList *el) override {
+ start(QLatin1String("UiPragmaValueList value=%1").arg(el->value));
+ return true;
+ }
+ void endVisit(AST::UiPragmaValueList *) override { stop(u"UiPragmaValueList"); }
+#endif
+
bool visit(UiPragma *el) override {
start(QLatin1String("UiPragma name=%1 pragmaToken=%2%3")
.arg(quotedString(el->name), loc(el->pragmaToken),
diff --git a/src/qmldom/qqmldomcomments.cpp b/src/qmldom/qqmldomcomments.cpp
index 3eee7adb28..559f7c0d73 100644
--- a/src/qmldom/qqmldomcomments.cpp
+++ b/src/qmldom/qqmldomcomments.cpp
@@ -331,6 +331,9 @@ QSet<int> VisitAll::uiKinds()
AST::Node::Kind_UiArrayBinding, AST::Node::Kind_UiImport,
AST::Node::Kind_UiObjectBinding, AST::Node::Kind_UiObjectDefinition,
AST::Node::Kind_UiInlineComponent, AST::Node::Kind_UiObjectInitializer,
+#if QT_VERSION >= QT_VERSION_CHECK(6, 6, 0)
+ AST::Node::Kind_UiPragmaValueList,
+#endif
AST::Node::Kind_UiPragma, AST::Node::Kind_UiProgram,
AST::Node::Kind_UiPublicMember, AST::Node::Kind_UiQualifiedId,
AST::Node::Kind_UiScriptBinding, AST::Node::Kind_UiSourceElement,
diff --git a/src/qmldom/qqmldomreformatter.cpp b/src/qmldom/qqmldomreformatter.cpp
index 9114f39c3e..c41b51b147 100644
--- a/src/qmldom/qqmldomreformatter.cpp
+++ b/src/qmldom/qqmldomreformatter.cpp
@@ -92,7 +92,14 @@ protected:
}
}
+#if QT_VERSION >= QT_VERSION_CHECK(6, 6, 0)
// we are not supposed to handle the ui
+ bool visit(UiPragmaValueList *) override
+ {
+ Q_ASSERT(false);
+ return false;
+ }
+#endif
bool visit(UiPragma *) override
{
Q_ASSERT(false);
@@ -1059,6 +1066,9 @@ protected:
void endVisit(UiProgram *) override { }
void endVisit(UiImport *) override { }
void endVisit(UiHeaderItemList *) override { }
+#if QT_VERSION >= QT_VERSION_CHECK(6, 6, 0)
+ void endVisit(UiPragmaValueList *) override { }
+#endif
void endVisit(UiPragma *) override { }
void endVisit(UiPublicMember *) override { }
void endVisit(UiSourceElement *) override { }