aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/compiler
diff options
context:
space:
mode:
authorFabian Kosmale <fabian.kosmale@qt.io>2021-12-06 22:07:41 +0100
committerFabian Kosmale <fabian.kosmale@qt.io>2021-12-08 14:38:21 +0100
commitd7119d327cacf08b1b2ce678a002a760226b3d0b (patch)
treee3419fcb561df820b8cfa1884b103ee7dcf4858f /src/qml/compiler
parentfa2569262faeaa67a0b040e72ac5897f10980286 (diff)
qmllint: Initial translation binding support
We will need to distinguish between script and translation bindings in the future (to correctly assign script binding indices). Moreover, the NOOP translation functions actually produce string literal bindings, not translation bindings. To unify the classification of translation bindings, the code from the IRBuilder has been converted into a template taking a few callbacks. This change does not add validation for translation bindings yet, but a failing autotest for a case where it would be necesseray is already provided. Change-Id: Icccba98edbdcd15068188807e8622c1bd513725c Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Diffstat (limited to 'src/qml/compiler')
-rw-r--r--src/qml/compiler/qqmlirbuilder.cpp122
-rw-r--r--src/qml/compiler/qqmlirbuilder_p.h136
2 files changed, 146 insertions, 112 deletions
diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp
index fc0da9db1b..7b24154701 100644
--- a/src/qml/compiler/qqmlirbuilder.cpp
+++ b/src/qml/compiler/qqmlirbuilder.cpp
@@ -1209,119 +1209,17 @@ void IRBuilder::setBindingValue(QV4::CompiledData::Binding *binding, QQmlJS::AST
void IRBuilder::tryGeneratingTranslationBinding(QStringView base, AST::ArgumentList *args, QV4::CompiledData::Binding *binding)
{
- if (base == QLatin1String("qsTr")) {
- QV4::CompiledData::TranslationData translationData;
- translationData.number = -1;
- translationData.commentIndex = 0; // empty string
- translationData.padding = 0;
-
- if (!args || !args->expression)
- return; // no arguments, stop
-
- QStringView translation;
- if (QQmlJS::AST::StringLiteral *arg1 = QQmlJS::AST::cast<QQmlJS::AST::StringLiteral *>(args->expression)) {
- translation = arg1->value;
- } else {
- return; // first argument is not a string, stop
- }
- translationData.stringIndex = jsGenerator->registerString(translation.toString());
-
- args = args->next;
-
- if (args) {
- QQmlJS::AST::StringLiteral *arg2 = QQmlJS::AST::cast<QQmlJS::AST::StringLiteral *>(args->expression);
- if (!arg2)
- return; // second argument is not a string, stop
- translationData.commentIndex = jsGenerator->registerString(arg2->value.toString());
-
- args = args->next;
- if (args) {
- if (QQmlJS::AST::NumericLiteral *arg3 = QQmlJS::AST::cast<QQmlJS::AST::NumericLiteral *>(args->expression)) {
- translationData.number = int(arg3->value);
- args = args->next;
- } else {
- return; // third argument is not a translation number, stop
- }
- }
- }
-
- if (args)
- return; // too many arguments, stop
-
- binding->type = QV4::CompiledData::Binding::Type_Translation;
- binding->value.translationDataIndex = jsGenerator->registerTranslation(translationData);
- } else if (base == QLatin1String("qsTrId")) {
- QV4::CompiledData::TranslationData translationData;
- translationData.number = -1;
- translationData.commentIndex = 0; // empty string, but unused
- translationData.padding = 0;
-
- if (!args || !args->expression)
- return; // no arguments, stop
-
- QStringView id;
- if (QQmlJS::AST::StringLiteral *arg1 = QQmlJS::AST::cast<QQmlJS::AST::StringLiteral *>(args->expression)) {
- id = arg1->value;
- } else {
- return; // first argument is not a string, stop
- }
- translationData.stringIndex = jsGenerator->registerString(id.toString());
-
- args = args->next;
-
- if (args) {
- if (QQmlJS::AST::NumericLiteral *arg3 = QQmlJS::AST::cast<QQmlJS::AST::NumericLiteral *>(args->expression)) {
- translationData.number = int(arg3->value);
- args = args->next;
- } else {
- return; // third argument is not a translation number, stop
- }
- }
-
- if (args)
- return; // too many arguments, stop
-
- binding->type = QV4::CompiledData::Binding::Type_TranslationById;
- binding->value.translationDataIndex = jsGenerator->registerTranslation(translationData);
- } else if (base == QLatin1String("QT_TR_NOOP") || base == QLatin1String("QT_TRID_NOOP")) {
- if (!args || !args->expression)
- return; // no arguments, stop
-
- QStringView str;
- if (QQmlJS::AST::StringLiteral *arg1 = QQmlJS::AST::cast<QQmlJS::AST::StringLiteral *>(args->expression)) {
- str = arg1->value;
- } else {
- return; // first argument is not a string, stop
- }
-
- args = args->next;
- if (args)
- return; // too many arguments, stop
-
- binding->type = QV4::CompiledData::Binding::Type_String;
- binding->stringIndex = jsGenerator->registerString(str.toString());
- } else if (base == QLatin1String("QT_TRANSLATE_NOOP")) {
- if (!args || !args->expression)
- return; // no arguments, stop
-
- args = args->next;
- if (!args || !args->expression)
- return; // no second arguments, stop
-
- QStringView str;
- if (QQmlJS::AST::StringLiteral *arg2 = QQmlJS::AST::cast<QQmlJS::AST::StringLiteral *>(args->expression)) {
- str = arg2->value;
- } else {
- return; // first argument is not a string, stop
- }
-
- args = args->next;
- if (args)
- return; // too many arguments, stop
+ auto registerMainString = [&](QStringView mainString) { return jsGenerator->registerString(mainString.toString()) ; };
+ auto registerCommentString = [&](QStringView commentString) { return jsGenerator->registerString(commentString.toString()); };
+ auto finalizeTranslationData = [&](QV4::CompiledData::Binding::ValueType type, QV4::CompiledData::TranslationData translationData) {
+ binding->type = type;
+ if (type == QV4::CompiledData::Binding::Type_Translation || type == QV4::CompiledData::Binding::Type_TranslationById)
+ binding->value.translationDataIndex = jsGenerator->registerTranslation(translationData);
+ else if (type == QV4::CompiledData::Binding::Type_String)
+ binding->stringIndex = translationData.number;
+ };
- binding->type = QV4::CompiledData::Binding::Type_String;
- binding->stringIndex = jsGenerator->registerString(str.toString());
- }
+ tryGeneratingTranslationBindingBase(base, args, registerMainString, registerCommentString, finalizeTranslationData);
}
void IRBuilder::appendBinding(QQmlJS::AST::UiQualifiedId *name, QQmlJS::AST::Statement *value, QQmlJS::AST::Node *parentNode)
diff --git a/src/qml/compiler/qqmlirbuilder_p.h b/src/qml/compiler/qqmlirbuilder_p.h
index 8555aedaca..213d43134a 100644
--- a/src/qml/compiler/qqmlirbuilder_p.h
+++ b/src/qml/compiler/qqmlirbuilder_p.h
@@ -615,6 +615,142 @@ private:
Document *document;
};
+// RegisterStringN ~= std::function<int(QStringView)>
+// FinalizeTranlationData ~= std::function<void(QV4::CompiledData::Binding::ValueType, QV4::CompiledData::TranslationData)>
+/*
+ \internal
+ \a base: name of the potential translation function
+ \a args: arguments to the function call
+ \a registerMainString: Takes the first argument passed to the translation function, and it's
+ result will be stored in a TranslationData's stringIndex for translation bindings and in numbeIndex
+ for string bindings.
+ \a registerCommentString: Takes the comment argument passed to some of the translation functions.
+ Result will be stored in a TranslationData's commentIndex
+ \a finalizeTranslationData: Takes the type of the binding and the previously set up TranslationData
+ */
+template<typename RegisterString1, typename RegisterString2, typename FinalizeTranslationData>
+void tryGeneratingTranslationBindingBase(QStringView base, QQmlJS::AST::ArgumentList *args,
+ RegisterString1 registerMainString,
+ RegisterString2 registerCommentString,
+ FinalizeTranslationData finalizeTranslationData
+ )
+{
+ if (base == QLatin1String("qsTr")) {
+ QV4::CompiledData::TranslationData translationData;
+ translationData.number = -1;
+ translationData.commentIndex = 0; // empty string
+ translationData.padding = 0;
+
+ if (!args || !args->expression)
+ return; // no arguments, stop
+
+ QStringView translation;
+ if (QQmlJS::AST::StringLiteral *arg1 = QQmlJS::AST::cast<QQmlJS::AST::StringLiteral *>(args->expression)) {
+ translation = arg1->value;
+ } else {
+ return; // first argument is not a string, stop
+ }
+
+ translationData.stringIndex = registerMainString(translation);
+
+ args = args->next;
+
+ if (args) {
+ QQmlJS::AST::StringLiteral *arg2 = QQmlJS::AST::cast<QQmlJS::AST::StringLiteral *>(args->expression);
+ if (!arg2)
+ return; // second argument is not a string, stop
+ translationData.commentIndex = registerCommentString(arg2->value);
+
+ args = args->next;
+ if (args) {
+ if (QQmlJS::AST::NumericLiteral *arg3 = QQmlJS::AST::cast<QQmlJS::AST::NumericLiteral *>(args->expression)) {
+ translationData.number = int(arg3->value);
+ args = args->next;
+ } else {
+ return; // third argument is not a translation number, stop
+ }
+ }
+ }
+
+ if (args)
+ return; // too many arguments, stop
+
+ finalizeTranslationData(QV4::CompiledData::Binding::Type_Translation, translationData);
+ } else if (base == QLatin1String("qsTrId")) {
+ QV4::CompiledData::TranslationData translationData;
+ translationData.number = -1;
+ translationData.commentIndex = 0; // empty string, but unused
+ translationData.padding = 0;
+
+ if (!args || !args->expression)
+ return; // no arguments, stop
+
+ QStringView id;
+ if (QQmlJS::AST::StringLiteral *arg1 = QQmlJS::AST::cast<QQmlJS::AST::StringLiteral *>(args->expression)) {
+ id = arg1->value;
+ } else {
+ return; // first argument is not a string, stop
+ }
+ translationData.stringIndex = registerMainString(id);
+
+ args = args->next;
+
+ if (args) {
+ if (QQmlJS::AST::NumericLiteral *arg3 = QQmlJS::AST::cast<QQmlJS::AST::NumericLiteral *>(args->expression)) {
+ translationData.number = int(arg3->value);
+ args = args->next;
+ } else {
+ return; // third argument is not a translation number, stop
+ }
+ }
+
+ if (args)
+ return; // too many arguments, stop
+
+ finalizeTranslationData(QV4::CompiledData::Binding::Type_TranslationById, translationData);
+ } else if (base == QLatin1String("QT_TR_NOOP") || base == QLatin1String("QT_TRID_NOOP")) {
+ if (!args || !args->expression)
+ return; // no arguments, stop
+
+ QStringView str;
+ if (QQmlJS::AST::StringLiteral *arg1 = QQmlJS::AST::cast<QQmlJS::AST::StringLiteral *>(args->expression)) {
+ str = arg1->value;
+ } else {
+ return; // first argument is not a string, stop
+ }
+
+ args = args->next;
+ if (args)
+ return; // too many arguments, stop
+
+ QV4::CompiledData::TranslationData translationData;
+ translationData.number = registerMainString(str);
+ finalizeTranslationData(QV4::CompiledData::Binding::Type_String, translationData);
+ } else if (base == QLatin1String("QT_TRANSLATE_NOOP")) {
+ if (!args || !args->expression)
+ return; // no arguments, stop
+
+ args = args->next;
+ if (!args || !args->expression)
+ return; // no second arguments, stop
+
+ QStringView str;
+ if (QQmlJS::AST::StringLiteral *arg2 = QQmlJS::AST::cast<QQmlJS::AST::StringLiteral *>(args->expression)) {
+ str = arg2->value;
+ } else {
+ return; // first argument is not a string, stop
+ }
+
+ args = args->next;
+ if (args)
+ return; // too many arguments, stop
+
+ QV4::CompiledData::TranslationData fakeTranslationData;
+ fakeTranslationData.number = registerMainString(str);
+ finalizeTranslationData(QV4::CompiledData::Binding::Type_String, fakeTranslationData);
+ }
+}
+
} // namespace QmlIR
QT_END_NAMESPACE