// 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 QQMLTYPECOMPILER_P_H #define QQMLTYPECOMPILER_P_H // // W A R N I N G // ------------- // // This file is not part of the Qt API. It exists purely as an // implementation detail. This header file may change from version to // version without notice, or even be removed. // // We mean it. // #include #include #include #include #include #include QT_BEGIN_NAMESPACE class QQmlEnginePrivate; class QQmlError; class QQmlTypeData; class QQmlImports; namespace QmlIR { struct Document; } namespace QV4 { namespace CompiledData { struct QmlUnit; struct Location; } } struct QQmlTypeCompiler { Q_DECLARE_TR_FUNCTIONS(QQmlTypeCompiler) public: QQmlTypeCompiler(QQmlEnginePrivate *engine, QQmlTypeData *typeData, QmlIR::Document *document, QV4::CompiledData::ResolvedTypeReferenceMap *resolvedTypeCache, const QV4::CompiledData::DependentTypesHasher &dependencyHasher); // --- interface used by QQmlPropertyCacheCreator typedef QmlIR::Object CompiledObject; typedef QmlIR::Binding CompiledBinding; using ListPropertyAssignBehavior = QmlIR::Pragma::ListPropertyAssignBehaviorValue; // Deliberate choice of map over hash here to ensure stable generated output. using IdToObjectMap = QMap; const QmlIR::Object *objectAt(int index) const { return document->objects.at(index); } QmlIR::Object *objectAt(int index) { return document->objects.at(index); } int objectCount() const { return document->objects.size(); } QString stringAt(int idx) const; QmlIR::PoolList::Iterator objectFunctionsBegin(const QmlIR::Object *object) const { return object->functionsBegin(); } QmlIR::PoolList::Iterator objectFunctionsEnd(const QmlIR::Object *object) const { return object->functionsEnd(); } QV4::CompiledData::ResolvedTypeReferenceMap *resolvedTypes = nullptr; ListPropertyAssignBehavior listPropertyAssignBehavior() const { for (const QmlIR::Pragma *pragma: document->pragmas) { if (pragma->type == QmlIR::Pragma::ListPropertyAssignBehavior) return pragma->listPropertyAssignBehavior; } return ListPropertyAssignBehavior::Append; } // --- QQmlRefPointer compile(); QList compilationErrors() const { return errors; } void recordError(const QV4::CompiledData::Location &location, const QString &description); void recordError(const QQmlJS::DiagnosticMessage &message); void recordError(const QQmlError &e); int registerString(const QString &str); int registerConstant(QV4::ReturnedValue v); const QV4::CompiledData::Unit *qmlUnit() const; QUrl url() const { return typeData->finalUrl(); } QQmlEnginePrivate *enginePrivate() const { return engine; } const QQmlImports *imports() const; QVector *qmlObjects() const; QQmlPropertyCacheVector *propertyCaches(); const QQmlPropertyCacheVector *propertyCaches() const; QQmlJS::MemoryPool *memoryPool(); QStringView newStringRef(const QString &string); const QV4::Compiler::StringTableGenerator *stringPool() const; const QHash &customParserCache() const { return customParsers; } QString bindingAsString(const QmlIR::Object *object, int scriptIndex) const; void addImport(const QString &module, const QString &qualifier, QTypeRevision version); QV4::ResolvedTypeReference *resolvedType(int id) const { return resolvedTypes->value(id); } QV4::ResolvedTypeReference *resolvedType(QMetaType type) const { for (QV4::ResolvedTypeReference *ref : std::as_const(*resolvedTypes)) { if (ref->type().typeId() == type) return ref; } return nullptr; } QQmlType qmlTypeForComponent(const QString &inlineComponentName = QString()) const; private: QList errors; QQmlEnginePrivate *engine; const QV4::CompiledData::DependentTypesHasher &dependencyHasher; QmlIR::Document *document; // index is string index of type name (use obj->inheritedTypeNameIndex) QHash customParsers; // index in first hash is component index, vector inside contains object indices of objects with id property QQmlPropertyCacheVector m_propertyCaches; QQmlTypeData *typeData; }; struct QQmlCompilePass { QQmlCompilePass(QQmlTypeCompiler *typeCompiler); QString stringAt(int idx) const { return compiler->stringAt(idx); } protected: void recordError(const QV4::CompiledData::Location &location, const QString &description) const { compiler->recordError(location, description); } QV4::ResolvedTypeReference *resolvedType(int id) const { return compiler->resolvedType(id); } QQmlTypeCompiler *compiler; }; // Resolves signal handlers. Updates the QV4::CompiledData::Binding objects to // set the property name to the final signal name (onTextChanged -> textChanged) // and sets the IsSignalExpression flag. struct SignalHandlerResolver : public QQmlCompilePass { Q_DECLARE_TR_FUNCTIONS(SignalHandlerResolver) public: SignalHandlerResolver(QQmlTypeCompiler *typeCompiler); bool resolveSignalHandlerExpressions(); private: bool resolveSignalHandlerExpressions(const QmlIR::Object *obj, const QString &typeName, const QQmlPropertyCache::ConstPtr &propertyCache); QQmlEnginePrivate *enginePrivate; const QVector &qmlObjects; const QQmlImports *imports; const QHash &customParsers; const QSet &illegalNames; const QQmlPropertyCacheVector * const propertyCaches; }; // ### This will go away when the codegen resolves all enums to constant expressions // and we replace the constant expression with a literal binding instead of using // a script. class QQmlEnumTypeResolver : public QQmlCompilePass { Q_DECLARE_TR_FUNCTIONS(QQmlEnumTypeResolver) public: QQmlEnumTypeResolver(QQmlTypeCompiler *typeCompiler); bool resolveEnumBindings(); private: bool assignEnumToBinding(QmlIR::Binding *binding, QStringView enumName, int enumValue, bool isQtObject); bool assignEnumToBinding(QmlIR::Binding *binding, const QString &enumName, int enumValue, bool isQtObject) { return assignEnumToBinding(binding, QStringView(enumName), enumValue, isQtObject); } bool tryQualifiedEnumAssignment( const QmlIR::Object *obj, const QQmlPropertyCache::ConstPtr &propertyCache, const QQmlPropertyData *prop, QmlIR::Binding *binding); int evaluateEnum(const QString &scope, QStringView enumName, QStringView enumValue, bool *ok) const; const QVector &qmlObjects; const QQmlPropertyCacheVector * const propertyCaches; const QQmlImports *imports; }; class QQmlCustomParserScriptIndexer: public QQmlCompilePass { public: QQmlCustomParserScriptIndexer(QQmlTypeCompiler *typeCompiler); void annotateBindingsWithScriptStrings(); private: void scanObjectRecursively(int objectIndex, bool annotateScriptBindings = false); const QVector &qmlObjects; const QHash &customParsers; }; // Annotate properties bound to aliases with a flag class QQmlAliasAnnotator : public QQmlCompilePass { public: QQmlAliasAnnotator(QQmlTypeCompiler *typeCompiler); void annotateBindingsToAliases(); private: const QVector &qmlObjects; const QQmlPropertyCacheVector * const propertyCaches; }; class QQmlScriptStringScanner : public QQmlCompilePass { public: QQmlScriptStringScanner(QQmlTypeCompiler *typeCompiler); void scan(); private: const QVector &qmlObjects; const QQmlPropertyCacheVector * const propertyCaches; }; class QQmlDeferredAndCustomParserBindingScanner : public QQmlCompilePass { Q_DECLARE_TR_FUNCTIONS(QQmlDeferredAndCustomParserBindingScanner) public: QQmlDeferredAndCustomParserBindingScanner(QQmlTypeCompiler *typeCompiler); bool scanObject(); private: enum class ScopeDeferred { False, True }; bool scanObject(int objectIndex, ScopeDeferred scopeDeferred); QVector *qmlObjects; const QQmlPropertyCacheVector * const propertyCaches; const QHash &customParsers; bool _seenObjectWithId; }; class QQmlDefaultPropertyMerger : public QQmlCompilePass { public: QQmlDefaultPropertyMerger(QQmlTypeCompiler *typeCompiler); void mergeDefaultProperties(); private: void mergeDefaultProperties(int objectIndex); const QVector &qmlObjects; const QQmlPropertyCacheVector * const propertyCaches; }; QT_END_NAMESPACE #endif // QQMLTYPECOMPILER_P_H