diff options
Diffstat (limited to 'src/qmlcompiler/qqmljsimporter_p.h')
-rw-r--r-- | src/qmlcompiler/qqmljsimporter_p.h | 207 |
1 files changed, 151 insertions, 56 deletions
diff --git a/src/qmlcompiler/qqmljsimporter_p.h b/src/qmlcompiler/qqmljsimporter_p.h index 02da8b7b46..290ea71605 100644 --- a/src/qmlcompiler/qqmljsimporter_p.h +++ b/src/qmlcompiler/qqmljsimporter_p.h @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2020 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:GPL-EXCEPT$ -** 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 General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** 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-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2020 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #ifndef QQMLJSIMPORTER_P_H #define QQMLJSIMPORTER_P_H @@ -39,34 +14,82 @@ // // We mean it. +#include <qtqmlcompilerexports.h> + +#include "qqmljscontextualtypes_p.h" #include "qqmljsscope_p.h" #include "qqmljsresourcefilemapper_p.h" #include <QtQml/private/qqmldirparser_p.h> +#include <QtQml/private/qqmljsast_p.h> + +#include <memory> QT_BEGIN_NAMESPACE -class QQmlJSImporter +namespace QQmlJS { +class Import { public: - using ImportedTypes = QHash<QString, QQmlJSScope::ConstPtr>; + Import() = default; + Import(QString prefix, QString name, QTypeRevision version, bool isFile, bool isDependency); + + bool isValid() const; - QQmlJSImporter(const QStringList &importPaths, QQmlJSResourceFileMapper *mapper) - : m_importPaths(importPaths) - , m_builtins({}) - , m_mapper(mapper) - {} + QString prefix() const { return m_prefix; } + QString name() const { return m_name; } + QTypeRevision version() const { return m_version; } + bool isFile() const { return m_isFile; } + bool isDependency() const { return m_isDependency; } + +private: + QString m_prefix; + QString m_name; + QTypeRevision m_version; + bool m_isFile = false; + bool m_isDependency = false; - QQmlJSResourceFileMapper *resourceFileMapper() { return m_mapper; } + friend inline size_t qHash(const Import &key, size_t seed = 0) noexcept + { + return qHashMulti(seed, key.m_prefix, key.m_name, key.m_version, + key.m_isFile, key.m_isDependency); + } + + friend inline bool operator==(const Import &a, const Import &b) + { + return a.m_prefix == b.m_prefix && a.m_name == b.m_name && a.m_version == b.m_version + && a.m_isFile == b.m_isFile && a.m_isDependency == b.m_isDependency; + } +}; +} + +class QQmlJSImportVisitor; +class QQmlJSLogger; +class Q_QMLCOMPILER_EXPORT QQmlJSImporter +{ +public: + using ImportedTypes = QQmlJS::ContextualTypes; + + QQmlJSImporter(const QStringList &importPaths, QQmlJSResourceFileMapper *mapper, + bool useOptionalImports = false); + + QQmlJSResourceFileMapper *resourceFileMapper() const { return m_mapper; } + void setResourceFileMapper(QQmlJSResourceFileMapper *mapper) { m_mapper = mapper; } + + QQmlJSResourceFileMapper *metaDataMapper() const { return m_metaDataMapper; } + void setMetaDataMapper(QQmlJSResourceFileMapper *mapper) { m_metaDataMapper = mapper; } ImportedTypes importBuiltins(); - ImportedTypes importQmltypes(const QStringList &qmltypesFiles); + void importQmldirs(const QStringList &qmltypesFiles); QQmlJSScope::Ptr importFile(const QString &file); ImportedTypes importDirectory(const QString &directory, const QString &prefix = QString()); - ImportedTypes importModule( - const QString &module, const QString &prefix = QString(), - QTypeRevision version = QTypeRevision()); + // ### qmltc needs this. once re-written, we no longer need to expose this + QHash<QString, QQmlJSScope::Ptr> importedFiles() const { return m_importedFiles; } + + ImportedTypes importModule(const QString &module, const QString &prefix = QString(), + QTypeRevision version = QTypeRevision(), + QStringList *staticModuleList = nullptr); ImportedTypes builtinInternalNames(); @@ -77,50 +100,122 @@ public: return result; } + QList<QQmlJS::DiagnosticMessage> takeGlobalWarnings() + { + const auto result = std::move(m_globalWarnings); + m_globalWarnings.clear(); + return result; + } + + QStringList importPaths() const { return m_importPaths; } + void setImportPaths(const QStringList &importPaths); + + void clearCache(); + + QQmlJSScope::ConstPtr jsGlobalObject() const; + + struct ImportVisitorPrerequisites + { + ImportVisitorPrerequisites(QQmlJSScope::Ptr target, QQmlJSLogger *logger, + const QString &implicitImportDirectory = {}, + const QStringList &qmldirFiles = {}) + : m_target(target), + m_logger(logger), + m_implicitImportDirectory(implicitImportDirectory), + m_qmldirFiles(qmldirFiles) + { + Q_ASSERT(target && logger); + } + + QQmlJSScope::Ptr m_target; + QQmlJSLogger *m_logger; + QString m_implicitImportDirectory; + QStringList m_qmldirFiles; + }; + void runImportVisitor(QQmlJS::AST::Node *rootNode, + const ImportVisitorPrerequisites &prerequisites); + + /*! + \internal + When a qml file gets lazily loaded, it will be lexed and parsed and finally be constructed + via an ImportVisitor. By default, this is done via the QQmlJSImportVisitor, but can also be done + via other import visitors like QmltcVisitor, which is used by qmltc to compile a QML file, or + QQmlDomAstCreatorWithQQmlJSScope, which is used to construct the Dom of lazily loaded QML files. + */ + using ImportVisitor = std::function<void(QQmlJS::AST::Node *rootNode, QQmlJSImporter *self, + const ImportVisitorPrerequisites &prerequisites)>; + + void setImportVisitor(ImportVisitor visitor) { m_importVisitor = visitor; } + private: friend class QDeferredFactory<QQmlJSScope>; struct AvailableTypes { - AvailableTypes(QHash<QString, QQmlJSScope::ConstPtr> builtins) + AvailableTypes(ImportedTypes builtins) : cppNames(std::move(builtins)) - {} + , qmlNames(QQmlJS::ContextualTypes::QML, {}, cppNames.arrayType()) + { + } // C++ names used in qmltypes files for non-composite types - QHash<QString, QQmlJSScope::ConstPtr> cppNames; + ImportedTypes cppNames; // Names the importing component sees, including any prefixes - QHash<QString, QQmlJSScope::ConstPtr> qmlNames; + ImportedTypes qmlNames; + + // Static modules included here + QStringList staticModules; + + // Whether a system module has been imported + bool hasSystemModule = false; }; struct Import { - QHash<QString, QQmlJSScope::Ptr> objects; - QHash<QString, QQmlJSScope::Ptr> scripts; + QString name; + bool isStaticModule = false; + bool isSystemModule = false; + + QList<QQmlJSExportedScope> objects; + QHash<QString, QQmlJSExportedScope> scripts; QList<QQmlDirParser::Import> imports; QList<QQmlDirParser::Import> dependencies; }; AvailableTypes builtinImportHelper(); - void importHelper(const QString &module, AvailableTypes *types, - const QString &prefix = QString(), - QTypeRevision version = QTypeRevision()); - void processImport(const Import &import, AvailableTypes *types, - const QString &prefix = QString()); - void importDependencies(const QQmlJSImporter::Import &import, - AvailableTypes *types, + bool importHelper(const QString &module, AvailableTypes *types, + const QString &prefix = QString(), QTypeRevision version = QTypeRevision(), + bool isDependency = false, bool isFile = false); + void processImport(const QQmlJS::Import &importDescription, const Import &import, + AvailableTypes *types); + void importDependencies(const QQmlJSImporter::Import &import, AvailableTypes *types, const QString &prefix = QString(), - QTypeRevision version = QTypeRevision()); - void readQmltypes(const QString &filename, QHash<QString, QQmlJSScope::Ptr> *objects, + QTypeRevision version = QTypeRevision(), bool isDependency = false); + QQmlDirParser createQmldirParserForFile(const QString &filename); + void readQmltypes(const QString &filename, QList<QQmlJSExportedScope> *objects, QList<QQmlDirParser::Import> *dependencies); Import readQmldir(const QString &dirname); + Import readDirectory(const QString &directory); + QQmlJSScope::Ptr localFile2ScopeTree(const QString &filePath); + static void setQualifiedNamesOn(const Import &import); QStringList m_importPaths; - QHash<QPair<QString, QTypeRevision>, Import> m_seenImports; + + QHash<QPair<QString, QTypeRevision>, QString> m_seenImports; + QHash<QQmlJS::Import, QSharedPointer<AvailableTypes>> m_cachedImportTypes; + QHash<QString, Import> m_seenQmldirFiles; + QHash<QString, QQmlJSScope::Ptr> m_importedFiles; + QList<QQmlJS::DiagnosticMessage> m_globalWarnings; QList<QQmlJS::DiagnosticMessage> m_warnings; - AvailableTypes m_builtins; + std::optional<AvailableTypes> m_builtins; + QQmlJSResourceFileMapper *m_mapper = nullptr; + QQmlJSResourceFileMapper *m_metaDataMapper = nullptr; + bool m_useOptionalImports; + + ImportVisitor m_importVisitor; }; QT_END_NAMESPACE |