diff options
Diffstat (limited to 'src/qml/compiler/qqmlirbuilder_p.h')
-rw-r--r-- | src/qml/compiler/qqmlirbuilder_p.h | 480 |
1 files changed, 395 insertions, 85 deletions
diff --git a/src/qml/compiler/qqmlirbuilder_p.h b/src/qml/compiler/qqmlirbuilder_p.h index 4279f5b768..ffd3ad72f7 100644 --- a/src/qml/compiler/qqmlirbuilder_p.h +++ b/src/qml/compiler/qqmlirbuilder_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 tools applications 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 QQMLIRBUILDER_P_H #define QQMLIRBUILDER_P_H @@ -158,6 +122,13 @@ struct PoolList } struct Iterator { + // turn Iterator into a proper iterator + using iterator_category = std::forward_iterator_tag; + using value_type = T; + using difference_type = ptrdiff_t; + using pointer = T *; + using reference = T &; + T *ptr; explicit Iterator(T *p) : ptr(p) {} @@ -178,8 +149,15 @@ struct PoolList return *ptr; } - void operator++() { + Iterator& operator++() { + ptr = ptr->next; + return *this; + } + + Iterator operator++(int) { + Iterator that {ptr}; ptr = ptr->next; + return that; } bool operator==(const Iterator &rhs) const { @@ -189,10 +167,15 @@ struct PoolList bool operator!=(const Iterator &rhs) const { return ptr != rhs.ptr; } + + operator T *() { return ptr; } + operator const T *() const { return ptr; } }; Iterator begin() { return Iterator(first); } Iterator end() { return Iterator(nullptr); } + + using iterator = Iterator; }; struct Object; @@ -220,13 +203,36 @@ struct Parameter : public QV4::CompiledData::Parameter { Parameter *next; - bool init(QV4::Compiler::JSUnitGenerator *stringGenerator, const QString ¶meterName, const QString &typeName); - static bool init(QV4::CompiledData::Parameter *param, const QV4::Compiler::JSUnitGenerator *stringGenerator, - int parameterNameIndex, int typeNameIndex); - static bool initType(QV4::CompiledData::ParameterType *paramType, - const QV4::Compiler::JSUnitGenerator *stringGenerator, int typeNameIndex); + template<typename IdGenerator> + static bool initType( + QV4::CompiledData::ParameterType *type, const IdGenerator &idGenerator, + const QQmlJS::AST::Type *annotation) + { + using Flag = QV4::CompiledData::ParameterType::Flag; + + if (!annotation) + return initType(type, QString(), idGenerator(QString()), Flag::NoFlag); + + const QString typeId = annotation->typeId->toString(); + const QString typeArgument = + annotation->typeArgument ? annotation->typeArgument->toString() : QString(); + + if (typeArgument.isEmpty()) + return initType(type, typeId, idGenerator(typeId), Flag::NoFlag); + + if (typeId == QLatin1String("list")) + return initType(type, typeArgument, idGenerator(typeArgument), Flag::List); - static QV4::CompiledData::BuiltinType stringToBuiltinType(const QString &typeName); + const QString annotationString = annotation->toString(); + return initType(type, annotationString, idGenerator(annotationString), Flag::NoFlag); + } + + static QV4::CompiledData::CommonType stringToBuiltinType(const QString &typeName); + +private: + static bool initType( + QV4::CompiledData::ParameterType *paramType, const QString &typeName, + int typeNameIndex, QV4::CompiledData::ParameterType::Flag listFlag); }; struct Signal @@ -259,11 +265,21 @@ struct Binding : public QV4::CompiledData::Binding Binding *next; }; +struct InlineComponent : public QV4::CompiledData::InlineComponent +{ + InlineComponent *next; +}; + struct Alias : public QV4::CompiledData::Alias { Alias *next; }; +struct RequiredPropertyExtraData : public QV4::CompiledData::RequiredPropertyExtraData +{ + RequiredPropertyExtraData *next; +}; + struct Function { QV4::CompiledData::Location location; @@ -280,7 +296,7 @@ struct Function Function *next; }; -struct Q_QMLCOMPILER_PRIVATE_EXPORT CompiledFunctionOrExpression +struct Q_QML_COMPILER_EXPORT CompiledFunctionOrExpression { CompiledFunctionOrExpression() {} @@ -291,7 +307,7 @@ struct Q_QMLCOMPILER_PRIVATE_EXPORT CompiledFunctionOrExpression CompiledFunctionOrExpression *next = nullptr; }; -struct Q_QMLCOMPILER_PRIVATE_EXPORT Object +struct Q_QML_COMPILER_EXPORT Object { Q_DECLARE_TR_FUNCTIONS(Object) public: @@ -317,6 +333,11 @@ public: int bindingCount() const { return bindings->count; } const Function *firstFunction() const { return functions->first; } int functionCount() const { return functions->count; } + const InlineComponent *inlineComponent() const { return inlineComponents->first; } + int inlineComponentCount() const { return inlineComponents->count; } + const RequiredPropertyExtraData *requiredPropertyExtraData() const {return requiredPropertyExtraDatas->first; } + int requiredPropertyExtraDataCount() const { return requiredPropertyExtraDatas->count; } + void simplifyRequiredProperties(); PoolList<Binding>::Iterator bindingsBegin() const { return bindings->begin(); } PoolList<Binding>::Iterator bindingsEnd() const { return bindings->end(); } @@ -330,18 +351,24 @@ public: PoolList<Signal>::Iterator signalsEnd() const { return qmlSignals->end(); } PoolList<Function>::Iterator functionsBegin() const { return functions->begin(); } PoolList<Function>::Iterator functionsEnd() const { return functions->end(); } + PoolList<InlineComponent>::Iterator inlineComponentsBegin() const { return inlineComponents->begin(); } + PoolList<InlineComponent>::Iterator inlineComponentsEnd() const { return inlineComponents->end(); } + PoolList<RequiredPropertyExtraData>::Iterator requiredPropertyExtraDataBegin() const {return requiredPropertyExtraDatas->begin(); } + PoolList<RequiredPropertyExtraData>::Iterator requiredPropertyExtraDataEnd() const {return requiredPropertyExtraDatas->end(); } // If set, then declarations for this object (and init bindings for these) should go into the // specified object. Used for declarations inside group properties. Object *declarationsOverride; - void init(QQmlJS::MemoryPool *pool, int typeNameIndex, int idIndex, const QQmlJS::AST::SourceLocation &location = QQmlJS::AST::SourceLocation()); + void init(QQmlJS::MemoryPool *pool, int typeNameIndex, int idIndex, const QV4::CompiledData::Location &location); QString appendEnum(Enum *enumeration); QString appendSignal(Signal *signal); - QString appendProperty(Property *prop, const QString &propertyName, bool isDefaultProperty, const QQmlJS::AST::SourceLocation &defaultToken, QQmlJS::AST::SourceLocation *errorLocation); - QString appendAlias(Alias *prop, const QString &aliasName, bool isDefaultProperty, const QQmlJS::AST::SourceLocation &defaultToken, QQmlJS::AST::SourceLocation *errorLocation); + QString appendProperty(Property *prop, const QString &propertyName, bool isDefaultProperty, const QQmlJS::SourceLocation &defaultToken, QQmlJS::SourceLocation *errorLocation); + QString appendAlias(Alias *prop, const QString &aliasName, bool isDefaultProperty, const QQmlJS::SourceLocation &defaultToken, QQmlJS::SourceLocation *errorLocation); void appendFunction(QmlIR::Function *f); + void appendInlineComponent(InlineComponent *ic); + void appendRequiredPropertyExtraData(RequiredPropertyExtraData *extraData); QString appendBinding(Binding *b, bool isListBinding); Binding *findBinding(quint32 nameIndex) const; @@ -356,6 +383,10 @@ public: int namedObjectsInComponentCount() const { return namedObjectsInComponent.size(); } const quint32 *namedObjectsInComponentTable() const { return namedObjectsInComponent.begin(); } + bool hasFlag(QV4::CompiledData::Object::Flag flag) const { return flags & flag; } + qint32 objectId() const { return id; } + bool hasAliasAsDefaultProperty() const { return defaultPropertyIsAlias; } + private: friend struct ::QQmlIRLoader; @@ -365,19 +396,72 @@ private: PoolList<Signal> *qmlSignals; PoolList<Binding> *bindings; PoolList<Function> *functions; + PoolList<InlineComponent> *inlineComponents; + PoolList<RequiredPropertyExtraData> *requiredPropertyExtraDatas; }; -struct Q_QMLCOMPILER_PRIVATE_EXPORT Pragma +struct Q_QML_COMPILER_EXPORT Pragma { - enum PragmaType { - PragmaSingleton = 0x1 + enum PragmaType + { + Singleton, + Strict, + ListPropertyAssignBehavior, + ComponentBehavior, + FunctionSignatureBehavior, + NativeMethodBehavior, + ValueTypeBehavior, + Translator, + }; + + enum ListPropertyAssignBehaviorValue + { + Append, + Replace, + ReplaceIfNotDefault, + }; + + enum ComponentBehaviorValue + { + Unbound, + Bound + }; + + enum FunctionSignatureBehaviorValue + { + Ignored, + Enforced + }; + + enum NativeMethodBehaviorValue + { + AcceptThisObject, + RejectThisObject + }; + + enum ValueTypeBehaviorValue + { + Copy = 0x1, + Addressable = 0x2, + Assertable = 0x4, + }; + Q_DECLARE_FLAGS(ValueTypeBehaviorValues, ValueTypeBehaviorValue); + + PragmaType type; + + union { + ListPropertyAssignBehaviorValue listPropertyAssignBehavior; + ComponentBehaviorValue componentBehavior; + FunctionSignatureBehaviorValue functionSignatureBehavior; + NativeMethodBehaviorValue nativeMethodBehavior; + ValueTypeBehaviorValues::Int valueTypeBehavior; + uint translationContextIndex; }; - quint32 type; QV4::CompiledData::Location location; }; -struct Q_QMLCOMPILER_PRIVATE_EXPORT Document +struct Q_QML_COMPILER_EXPORT Document { Document(bool debugMode); QString code; @@ -389,13 +473,22 @@ struct Q_QMLCOMPILER_PRIVATE_EXPORT Document QVector<Object*> objects; QV4::Compiler::JSUnitGenerator jsGenerator; - QV4::CompiledData::CompilationUnit javaScriptCompilationUnit; + QQmlRefPointer<QV4::CompiledData::CompilationUnit> javaScriptCompilationUnit; + + bool isSingleton() const { + return std::any_of(pragmas.constBegin(), pragmas.constEnd(), [](const Pragma *pragma) { + return pragma->type == Pragma::Singleton; + }); + } int registerString(const QString &str) { return jsGenerator.registerString(str); } QString stringAt(int index) const { return jsGenerator.stringForIndex(index); } + + int objectCount() const {return objects.size();} + Object* objectAt(int i) const {return objects.at(i);} }; -class Q_QMLCOMPILER_PRIVATE_EXPORT ScriptDirectivesCollector : public QQmlJS::Directives +class Q_QML_COMPILER_EXPORT ScriptDirectivesCollector : public QQmlJS::Directives { QmlIR::Document *document; QQmlJS::Engine *engine; @@ -409,15 +502,13 @@ public: void importModule(const QString &uri, const QString &version, const QString &module, int lineNumber, int column) override; }; -struct Q_QMLCOMPILER_PRIVATE_EXPORT IRBuilder : public QQmlJS::AST::Visitor +struct Q_QML_COMPILER_EXPORT IRBuilder : public QQmlJS::AST::Visitor { Q_DECLARE_TR_FUNCTIONS(QQmlCodeGenerator) public: IRBuilder(const QSet<QString> &illegalNames); bool generateFromQml(const QString &code, const QString &url, Document *output); - static bool isSignalPropertyName(const QString &name); - using QQmlJS::AST::Visitor::visit; using QQmlJS::AST::Visitor::endVisit; @@ -433,57 +524,71 @@ public: bool visit(QQmlJS::AST::UiArrayBinding *ast) override; bool visit(QQmlJS::AST::UiObjectBinding *ast) override; bool visit(QQmlJS::AST::UiObjectDefinition *ast) override; + bool visit(QQmlJS::AST::UiInlineComponent *ast) override; bool visit(QQmlJS::AST::UiEnumDeclaration *ast) override; bool visit(QQmlJS::AST::UiPublicMember *ast) override; bool visit(QQmlJS::AST::UiScriptBinding *ast) override; bool visit(QQmlJS::AST::UiSourceElement *ast) override; + bool visit(QQmlJS::AST::UiRequired *ast) override; void throwRecursionDepthError() override { - recordError(QQmlJS::AST::SourceLocation(), + recordError(QQmlJS::SourceLocation(), QStringLiteral("Maximum statement or expression depth exceeded")); } void accept(QQmlJS::AST::Node *node); // returns index in _objects - bool defineQMLObject(int *objectIndex, QQmlJS::AST::UiQualifiedId *qualifiedTypeNameId, const QQmlJS::AST::SourceLocation &location, QQmlJS::AST::UiObjectInitializer *initializer, Object *declarationsOverride = nullptr); - bool defineQMLObject(int *objectIndex, QQmlJS::AST::UiObjectDefinition *node, Object *declarationsOverride = nullptr) - { return defineQMLObject(objectIndex, node->qualifiedTypeNameId, node->qualifiedTypeNameId->firstSourceLocation(), node->initializer, declarationsOverride); } + bool defineQMLObject( + int *objectIndex, QQmlJS::AST::UiQualifiedId *qualifiedTypeNameId, + const QV4::CompiledData::Location &location, + QQmlJS::AST::UiObjectInitializer *initializer, Object *declarationsOverride = nullptr); + + bool defineQMLObject( + int *objectIndex, QQmlJS::AST::UiObjectDefinition *node, + Object *declarationsOverride = nullptr) + { + const QQmlJS::SourceLocation location = node->qualifiedTypeNameId->firstSourceLocation(); + return defineQMLObject( + objectIndex, node->qualifiedTypeNameId, + { location.startLine, location.startColumn }, node->initializer, + declarationsOverride); + } static QString asString(QQmlJS::AST::UiQualifiedId *node); - QStringRef asStringRef(QQmlJS::AST::Node *node); - static void extractVersion(const QStringRef &string, int *maj, int *min); - QStringRef textRefAt(const QQmlJS::AST::SourceLocation &loc) const - { return QStringRef(&sourceCode, loc.offset, loc.length); } - QStringRef textRefAt(const QQmlJS::AST::SourceLocation &first, - const QQmlJS::AST::SourceLocation &last) const; + QStringView asStringRef(QQmlJS::AST::Node *node); + static QTypeRevision extractVersion(QStringView string); + QStringView textRefAt(const QQmlJS::SourceLocation &loc) const + { return QStringView(sourceCode).mid(loc.offset, loc.length); } + QStringView textRefAt(const QQmlJS::SourceLocation &first, + const QQmlJS::SourceLocation &last) const; void setBindingValue(QV4::CompiledData::Binding *binding, QQmlJS::AST::Statement *statement, QQmlJS::AST::Node *parentNode); - void tryGeneratingTranslationBinding(const QStringRef &base, QQmlJS::AST::ArgumentList *args, QV4::CompiledData::Binding *binding); + void tryGeneratingTranslationBinding(QStringView base, QQmlJS::AST::ArgumentList *args, QV4::CompiledData::Binding *binding); void appendBinding(QQmlJS::AST::UiQualifiedId *name, QQmlJS::AST::Statement *value, QQmlJS::AST::Node *parentNode); void appendBinding(QQmlJS::AST::UiQualifiedId *name, int objectIndex, bool isOnAssignment = false); - void appendBinding(const QQmlJS::AST::SourceLocation &qualifiedNameLocation, - const QQmlJS::AST::SourceLocation &nameLocation, quint32 propertyNameIndex, + void appendBinding(const QQmlJS::SourceLocation &qualifiedNameLocation, + const QQmlJS::SourceLocation &nameLocation, quint32 propertyNameIndex, QQmlJS::AST::Statement *value, QQmlJS::AST::Node *parentNode); - void appendBinding(const QQmlJS::AST::SourceLocation &qualifiedNameLocation, - const QQmlJS::AST::SourceLocation &nameLocation, quint32 propertyNameIndex, + void appendBinding(const QQmlJS::SourceLocation &qualifiedNameLocation, + const QQmlJS::SourceLocation &nameLocation, quint32 propertyNameIndex, int objectIndex, bool isListItem = false, bool isOnAssignment = false); bool appendAlias(QQmlJS::AST::UiPublicMember *node); Object *bindingsTarget() const; - bool setId(const QQmlJS::AST::SourceLocation &idLocation, QQmlJS::AST::Statement *value); + bool setId(const QQmlJS::SourceLocation &idLocation, QQmlJS::AST::Statement *value); // resolves qualified name (font.pixelSize for example) and returns the last name along // with the object any right-hand-side of a binding should apply to. bool resolveQualifiedId(QQmlJS::AST::UiQualifiedId **nameToResolve, Object **object, bool onAssignment = false); - void recordError(const QQmlJS::AST::SourceLocation &location, const QString &description); + void recordError(const QQmlJS::SourceLocation &location, const QString &description); quint32 registerString(const QString &str) const { return jsGenerator->registerString(str); } template <typename _Tp> _Tp *New() { return pool->New<_Tp>(); } @@ -493,11 +598,12 @@ public: static bool isStatementNodeScript(QQmlJS::AST::Statement *statement); static bool isRedundantNullInitializerForPropertyDeclaration(Property *property, QQmlJS::AST::Statement *statement); - QString sanityCheckFunctionNames(Object *obj, const QSet<QString> &illegalNames, QQmlJS::AST::SourceLocation *errorLocation); + QString sanityCheckFunctionNames(Object *obj, const QSet<QString> &illegalNames, QQmlJS::SourceLocation *errorLocation); QList<QQmlJS::DiagnosticMessage> errors; QSet<QString> illegalNames; + QSet<QString> inlineComponentsNames; QList<const QV4::CompiledData::Import *> _imports; QList<Pragma*> _pragmas; @@ -511,9 +617,11 @@ public: QQmlJS::MemoryPool *pool; QString sourceCode; QV4::Compiler::JSUnitGenerator *jsGenerator; + + bool insideInlineComponent = false; }; -struct Q_QMLCOMPILER_PRIVATE_EXPORT QmlUnitGenerator +struct Q_QML_COMPILER_EXPORT QmlUnitGenerator { void generate(Document &output, const QV4::CompiledData::DependentTypesHasher &dependencyHasher = QV4::CompiledData::DependentTypesHasher()); @@ -522,21 +630,223 @@ private: char *writeBindings(char *bindingPtr, const Object *o, BindingFilter filter) const; }; -struct Q_QMLCOMPILER_PRIVATE_EXPORT JSCodeGen : public QV4::Compiler::Codegen +struct Q_QML_COMPILER_EXPORT JSCodeGen : public QV4::Compiler::Codegen { - JSCodeGen(Document *document, const QSet<QString> &globalNames); + JSCodeGen(Document *document, const QSet<QString> &globalNames, + QV4::Compiler::CodegenWarningInterface *iface = + QV4::Compiler::defaultCodegenWarningInterface(), + bool storeSourceLocations = false); // Returns mapping from input functions to index in IR::Module::functions / compiledData->runtimeFunctions - QVector<int> generateJSCodeForFunctionsAndBindings(const QList<CompiledFunctionOrExpression> &functions); + QVector<int> + generateJSCodeForFunctionsAndBindings(const QList<CompiledFunctionOrExpression> &functions); - bool generateCodeForComponents(const QVector<quint32> &componentRoots); - bool compileComponent(int contextObject); - bool compileJavaScriptCodeInObjectsRecursively(int objectIndex, int scopeObjectIndex); + bool generateRuntimeFunctions(QmlIR::Object *object); 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 RegisterMainString, + typename RegisterCommentString, + typename RegisterContextString, + typename FinalizeTranslationData> +void tryGeneratingTranslationBindingBase(QStringView base, QQmlJS::AST::ArgumentList *args, + RegisterMainString registerMainString, + RegisterCommentString registerCommentString, + RegisterContextString registerContextString, + FinalizeTranslationData finalizeTranslationData + ) +{ + if (base == QLatin1String("qsTr")) { + QV4::CompiledData::TranslationData translationData; + translationData.number = -1; + + // empty string + translationData.commentIndex = 0; + + // No context (not empty string) + translationData.contextIndex = QV4::CompiledData::TranslationData::NoContextIndex; + + 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; + + // empty string, but unused + translationData.commentIndex = 0; + + // No context (not empty string) + translationData.contextIndex = QV4::CompiledData::TranslationData::NoContextIndex; + + 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); + } else if (base == QLatin1String("qsTranslate")) { + QV4::CompiledData::TranslationData translationData; + translationData.number = -1; + translationData.commentIndex = 0; // empty string + + if (!args || !args->next) + return; // less than 2 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.contextIndex = registerContextString(translation); + + args = args->next; + Q_ASSERT(args); + + QQmlJS::AST::StringLiteral *arg2 + = QQmlJS::AST::cast<QQmlJS::AST::StringLiteral *>(args->expression); + if (!arg2) + return; // second argument is not a string, stop + translationData.stringIndex = registerMainString(arg2->value); + + args = args->next; + if (args) { + QQmlJS::AST::StringLiteral *arg3 + = QQmlJS::AST::cast<QQmlJS::AST::StringLiteral *>(args->expression); + if (!arg3) + return; // third argument is not a string, stop + translationData.commentIndex = registerCommentString(arg3->value); + + args = args->next; + if (args) { + if (QQmlJS::AST::NumericLiteral *arg4 + = QQmlJS::AST::cast<QQmlJS::AST::NumericLiteral *>(args->expression)) { + translationData.number = int(arg4->value); + args = args->next; + } else { + return; // fourth argument is not a translation number, stop + } + } + } + + if (args) + return; // too many arguments, stop + + finalizeTranslationData(QV4::CompiledData::Binding::Type_Translation, translationData); + } +} + } // namespace QmlIR QT_END_NAMESPACE |