/**************************************************************************** ** ** Copyright (C) 2020 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtQml module 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$ **/ #ifndef DOMTOP_H #define DOMTOP_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 "qqmldomitem_p.h" #include "qqmldomexternalitems_p.h" #include #include #include #include #include #include QT_BEGIN_NAMESPACE namespace QQmlJS { namespace Dom { class QMLDOM_EXPORT ParsingTask { Q_GADGET public: QCborMap toCbor() const { return QCborMap( {{ QString::fromUtf16(Fields::requestedAt), QCborValue(requestedAt)}, { QString::fromUtf16(Fields::loadOptions), int(loadOptions)}, { QString::fromUtf16(Fields::kind), int(kind)}, { QString::fromUtf16(Fields::canonicalPath), canonicalPath}, { QString::fromUtf16(Fields::logicalPath), logicalPath}, { QString::fromUtf16(Fields::contents), contents}, { QString::fromUtf16(Fields::contentsDate), QCborValue(contentsDate)}, { QString::fromUtf16(Fields::hasCallback), bool(callback)}}); } QDateTime requestedAt; LoadOptions loadOptions; DomType kind; QString canonicalPath; QString logicalPath; QString contents; QDateTime contentsDate; std::weak_ptr requestingUniverse; // make it a shared_ptr? function callback; }; class QMLDOM_EXPORT ExternalItemPairBase: public OwningItem { // all access should have the lock of the DomUniverse containing this Q_DECLARE_TR_FUNCTIONS(ExternalItemPairBase); public: constexpr static DomType kindValue = DomType::ExternalItemPair; DomType kind() const override { return kindValue; } ExternalItemPairBase(QDateTime validExposedAt = QDateTime::fromMSecsSinceEpoch(0), QDateTime currentExposedAt = QDateTime::fromMSecsSinceEpoch(0), int derivedFrom=0, QDateTime lastDataUpdateAt = QDateTime::fromMSecsSinceEpoch(0)): OwningItem(derivedFrom, lastDataUpdateAt), validExposedAt(validExposedAt), currentExposedAt(currentExposedAt) {} ExternalItemPairBase(const ExternalItemPairBase &o): OwningItem(o), validExposedAt(o.validExposedAt), currentExposedAt(o.currentExposedAt) {} virtual std::shared_ptr validItem() const = 0; virtual std::shared_ptr currentItem() const = 0; QString canonicalFilePath(const DomItem &) const override; Path pathFromOwner(const DomItem &self) const override; Path canonicalPath(const DomItem &self) const override; bool iterateDirectSubpaths(DomItem &self, function) override; bool currentIsValid() const; std::shared_ptr makeCopy(const DomItem &self) { return std::static_pointer_cast(doCopy(self)); } QDateTime lastDataUpdateAt() const override { if (currentItem()) return currentItem()->lastDataUpdateAt(); return ExternalItemPairBase::lastDataUpdateAt(); } void refreshedDataAt(QDateTime tNew) override { return OwningItem::refreshedDataAt(tNew); if (currentItem()) currentItem()->refreshedDataAt(tNew); } friend class DomUniverse; QDateTime validExposedAt; QDateTime currentExposedAt; }; template class QMLDOM_EXPORT ExternalItemPair: public ExternalItemPairBase { // all access should have the lock of the DomUniverse containing this protected: std::shared_ptr doCopy(const DomItem &) override { return std::make_shared(*this); } public: friend class DomUniverse; ExternalItemPair(std::shared_ptr valid = {}, std::shared_ptr current = {}, QDateTime validExposedAt = QDateTime::fromMSecsSinceEpoch(0), QDateTime currentExposedAt = QDateTime::fromMSecsSinceEpoch(0), int derivedFrom = 0, QDateTime lastDataUpdateAt = QDateTime::fromMSecsSinceEpoch(0)): ExternalItemPairBase(validExposedAt, currentExposedAt, derivedFrom, lastDataUpdateAt), valid(valid), current(current) {} ExternalItemPair(const ExternalItemPair &o): ExternalItemPairBase(o), valid(o.valid), current(o.current) { QMutexLocker l(mutex()); } std::shared_ptr validItem() const override { return valid; } std::shared_ptr currentItem() const override { return current; } std::shared_ptr makeCopy(const DomItem &self) { return std::static_pointer_cast(doCopy(self)); } std::shared_ptr valid; std::shared_ptr current; }; class QMLDOM_EXPORT DomTop: public OwningItem { public: DomTop(QMap> extraOwningItems = {}, int derivedFrom=0): OwningItem(derivedFrom), m_extraOwningItems(extraOwningItems) {} DomTop(const DomTop &o): OwningItem(o) { QMap> items = o.extraOwningItems(); { QMutexLocker l(mutex()); m_extraOwningItems = items; } } using Callback = DomItem::Callback; virtual Path canonicalPath() const = 0; Path pathFromOwner(const DomItem &) const override; Path canonicalPath(const DomItem &) const override; DomItem containingObject(const DomItem&) const override; bool iterateDirectSubpaths(DomItem &self, function) override; void setExtraOwningItem(QString fieldName, std::shared_ptr item); void clearExtraOwningItems(); QMap> extraOwningItems() const; private: QMap> m_extraOwningItems; }; class QMLDOM_EXPORT DomUniverse: public DomTop { Q_DECLARE_TR_FUNCTIONS(DomUniverse); protected: std::shared_ptr doCopy(const DomItem &self) override; public: enum class Option{ Default, SingleThreaded }; Q_DECLARE_FLAGS(Options, Option); constexpr static DomType kindValue = DomType::DomUniverse; DomType kind() const override { return kindValue; } static ErrorGroups myErrors(); DomUniverse(QString universeName, Options options = Option::SingleThreaded); DomUniverse(const DomUniverse &) = delete; Path canonicalPath() const override; bool iterateDirectSubpaths(DomItem &self, function) override; std::shared_ptr makeCopy(const DomItem &self) { return std::static_pointer_cast(doCopy(self)); } void loadFile(const DomItem &self, QString filePath, QString logicalPath, Callback callback, LoadOptions loadOptions); void loadFile(const DomItem &self, QString canonicalFilePath, QString logicalPath, QString code, QDateTime codeDate, Callback callback, LoadOptions loadOptions); void execQueue(); QString name() const { return m_name; } Options options() const { return m_options; } QQueue queue() const { QMutexLocker l(mutex()); return m_queue; } private: QString m_name; Options m_options; QQueue m_queue; }; Q_DECLARE_OPERATORS_FOR_FLAGS(DomUniverse::Options) class QMLDOM_EXPORT ExternalItemInfoBase: public OwningItem { Q_DECLARE_TR_FUNCTIONS(ExternalItemInfoBase); public: constexpr static DomType kindValue = DomType::ExternalItemInfo; DomType kind() const override { return kindValue; } ExternalItemInfoBase(QDateTime currentExposedAt = QDateTime::fromMSecsSinceEpoch(0), int derivedFrom=0, QDateTime lastDataUpdateAt = QDateTime::fromMSecsSinceEpoch(0)): OwningItem(derivedFrom, lastDataUpdateAt), m_currentExposedAt(currentExposedAt) {} ExternalItemInfoBase(const ExternalItemInfoBase &o): OwningItem(o), m_currentExposedAt(o.currentExposedAt()), m_logicalFilePaths(o.logicalFilePaths()) {} virtual std::shared_ptr currentItem() const = 0; QString canonicalFilePath(const DomItem &) const override; Path canonicalPath(const DomItem &) const override; Path pathFromOwner(const DomItem &self) const override; bool iterateDirectSubpaths(DomItem &self, function) override; int currentRevision(const DomItem &self) const; int lastRevision(const DomItem &self) const; int lastValidRevision(const DomItem &self) const; std::shared_ptr makeCopy(const DomItem &self) { return std::static_pointer_cast(doCopy(self)); } QDateTime lastDataUpdateAt() const override { if (currentItem()) return currentItem()->lastDataUpdateAt(); return OwningItem::lastDataUpdateAt(); } void refreshedDataAt(QDateTime tNew) override { return OwningItem::refreshedDataAt(tNew); if (currentItem()) currentItem()->refreshedDataAt(tNew); } void ensureLogicalFilePath(QString path) { QMutexLocker l(mutex()); if (!m_logicalFilePaths.contains(path)) m_logicalFilePaths.append(path); } QDateTime currentExposedAt() const { QMutexLocker l(mutex()); // should not be needed, as it should not change... return m_currentExposedAt; } void setCurrentExposedAt(QDateTime d) { QMutexLocker l(mutex()); // should not be needed, as it should not change... m_currentExposedAt = d; } QStringList logicalFilePaths() const { QMutexLocker l(mutex()); return m_logicalFilePaths; } private: friend class DomEnvironment; QDateTime m_currentExposedAt; QStringList m_logicalFilePaths; }; template class ExternalItemInfo: public ExternalItemInfoBase { protected: std::shared_ptr doCopy(const DomItem &) override { return std::make_shared(*this); } public: ExternalItemInfo(std::shared_ptr current = std::shared_ptr(), QDateTime currentExposedAt = QDateTime::fromMSecsSinceEpoch(0), int derivedFrom = 0, QDateTime lastDataUpdateAt = QDateTime::fromMSecsSinceEpoch(0)): ExternalItemInfoBase(currentExposedAt, derivedFrom, lastDataUpdateAt), current(current) {} ExternalItemInfo(QString canonicalPath): current(std::make_shared(canonicalPath)) {} ExternalItemInfo(const ExternalItemInfo &o): ExternalItemInfoBase(o), current(o.current) { QMutexLocker l(mutex()); } std::shared_ptr makeCopy(const DomItem &self) { return std::static_pointer_cast(doCopy(self)); } std::shared_ptr currentItem() const override { return current; } std::shared_ptr current; }; enum class EnvLookup { Normal, NoBase, BaseOnly }; enum class Changeable { ReadOnly, Writable }; class QMLDOM_EXPORT DomEnvironment: public DomTop { Q_DECLARE_TR_FUNCTIONS(DomEnvironment); protected: std::shared_ptr doCopy(const DomItem &self) override; public: enum class Option { Default = 0x0, KeepValid = 0x1, // if there is a previous valid version, use that instead of the latest Exported = 0x2, // the current environment is accessible by multiple threads, one should only modify whole OwningItems, and in general load and do other operations in other (Child) environments NoReload = 0x4, // never reload something that was already loaded by the parent environment WeakLoad = 0x8, // load only the names of the available types, not the types (qml files) themselves SingleThreaded = 0x10, // do all operations in a single thread NoDependencies = 0x20 // will not load dependencies (useful when editing) }; Q_DECLARE_FLAGS(Options, Option); static ErrorGroups myErrors(); constexpr static DomType kindValue = DomType::DomEnvironment; DomType kind() const override { return kindValue; } Path canonicalPath() const override; bool iterateDirectSubpaths(DomItem &self, function) override; std::shared_ptr makeCopy(const DomItem &self) { return std::static_pointer_cast(doCopy(self)); } std::shared_ptr universe() const; DomEnvironment(std::shared_ptr universe, QStringList loadPaths, Options options = Option::SingleThreaded); DomEnvironment(std::shared_ptr parent, QStringList loadPaths, Options options = Option::SingleThreaded); DomEnvironment(const DomEnvironment &o) = delete; std::shared_ptr> addQmlFile(std::shared_ptr file); void commitToBase(const DomItem &self); Options options() const { return m_options; } std::shared_ptr base() const { return m_base; } QStringList loadPaths() const { QMutexLocker l(mutex()); return m_loadPaths; } private: const Options m_options; const std::shared_ptr m_base; const std::shared_ptr m_universe; QStringList m_loadPaths; // paths for qml bool m_singleThreadedLoadInProgress = false; QQueue m_loadsWithWork; QQueue m_inProgress; QList m_allLoadedCallback; }; Q_DECLARE_OPERATORS_FOR_FLAGS(DomEnvironment::Options) } // end namespace Dom } // end namespace QQmlJS QT_END_NAMESPACE #endif // DOMTOP_H