aboutsummaryrefslogtreecommitdiffstats
path: root/src/qmldom/qqmldomtop_p.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/qmldom/qqmldomtop_p.h')
-rw-r--r--src/qmldom/qqmldomtop_p.h730
1 files changed, 528 insertions, 202 deletions
diff --git a/src/qmldom/qqmldomtop_p.h b/src/qmldom/qqmldomtop_p.h
index f73a973906..afdea6b311 100644
--- a/src/qmldom/qqmldomtop_p.h
+++ b/src/qmldom/qqmldomtop_p.h
@@ -31,43 +31,21 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::Literals::StringLiterals;
+
namespace QQmlJS {
namespace Dom {
-class QMLDOM_EXPORT ParsingTask {
-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<DomUniverse> requestingUniverse; // make it a shared_ptr?
- function<void(Path, DomItem &, DomItem &)> 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 final override { return kindValue; }
- ExternalItemPairBase(QDateTime validExposedAt = QDateTime::fromMSecsSinceEpoch(0, QTimeZone::UTC),
- QDateTime currentExposedAt = QDateTime::fromMSecsSinceEpoch(0, QTimeZone::UTC),
- int derivedFrom = 0,
- QDateTime lastDataUpdateAt = QDateTime::fromMSecsSinceEpoch(0, QTimeZone::UTC))
+ ExternalItemPairBase(
+ const QDateTime &validExposedAt = QDateTime::fromMSecsSinceEpoch(0, QTimeZone::UTC),
+ const QDateTime &currentExposedAt = QDateTime::fromMSecsSinceEpoch(0, QTimeZone::UTC),
+ int derivedFrom = 0,
+ const QDateTime &lastDataUpdateAt = QDateTime::fromMSecsSinceEpoch(0, QTimeZone::UTC))
: OwningItem(derivedFrom, lastDataUpdateAt),
validExposedAt(validExposedAt),
currentExposedAt(currentExposedAt)
@@ -76,21 +54,21 @@ public:
OwningItem(o), validExposedAt(o.validExposedAt), currentExposedAt(o.currentExposedAt)
{}
virtual std::shared_ptr<ExternalOwningItem> validItem() const = 0;
- virtual DomItem validItem(DomItem &self) const = 0;
+ virtual DomItem validItem(const DomItem &self) const = 0;
virtual std::shared_ptr<ExternalOwningItem> currentItem() const = 0;
- virtual DomItem currentItem(DomItem &self) const = 0;
+ virtual DomItem currentItem(const DomItem &self) const = 0;
- QString canonicalFilePath(DomItem &) const final override;
- Path canonicalPath(DomItem &self) const final override;
- bool iterateDirectSubpaths(DomItem &self, DirectVisitor) final override;
- DomItem field(DomItem &self, QStringView name) const final override
+ QString canonicalFilePath(const DomItem &) const final override;
+ Path canonicalPath(const DomItem &self) const final override;
+ bool iterateDirectSubpaths(const DomItem &self, DirectVisitor) const final override;
+ DomItem field(const DomItem &self, QStringView name) const final override
{
return OwningItem::field(self, name);
}
bool currentIsValid() const;
- std::shared_ptr<ExternalItemPairBase> makeCopy(DomItem &self) const
+ std::shared_ptr<ExternalItemPairBase> makeCopy(const DomItem &self) const
{
return std::static_pointer_cast<ExternalItemPairBase>(doCopy(self));
}
@@ -104,9 +82,9 @@ public:
void refreshedDataAt(QDateTime tNew) final override
{
- return OwningItem::refreshedDataAt(tNew);
if (currentItem())
currentItem()->refreshedDataAt(tNew);
+ return OwningItem::refreshedDataAt(tNew);
}
friend class DomUniverse;
@@ -119,7 +97,7 @@ template<class T>
class QMLDOM_EXPORT ExternalItemPair final : public ExternalItemPairBase
{ // all access should have the lock of the DomUniverse containing this
protected:
- std::shared_ptr<OwningItem> doCopy(DomItem &) const override
+ std::shared_ptr<OwningItem> doCopy(const DomItem &) const override
{
return std::make_shared<ExternalItemPair>(*this);
}
@@ -127,11 +105,12 @@ protected:
public:
constexpr static DomType kindValue = DomType::ExternalItemPair;
friend class DomUniverse;
- ExternalItemPair(std::shared_ptr<T> valid = {}, std::shared_ptr<T> current = {},
- QDateTime validExposedAt = QDateTime::fromMSecsSinceEpoch(0, QTimeZone::UTC),
- QDateTime currentExposedAt = QDateTime::fromMSecsSinceEpoch(0, QTimeZone::UTC),
- int derivedFrom = 0,
- QDateTime lastDataUpdateAt = QDateTime::fromMSecsSinceEpoch(0, QTimeZone::UTC))
+ ExternalItemPair(
+ const std::shared_ptr<T> &valid = {}, const std::shared_ptr<T> &current = {},
+ const QDateTime &validExposedAt = QDateTime::fromMSecsSinceEpoch(0, QTimeZone::UTC),
+ const QDateTime &currentExposedAt = QDateTime::fromMSecsSinceEpoch(0, QTimeZone::UTC),
+ int derivedFrom = 0,
+ const QDateTime &lastDataUpdateAt = QDateTime::fromMSecsSinceEpoch(0, QTimeZone::UTC))
: ExternalItemPairBase(validExposedAt, currentExposedAt, derivedFrom, lastDataUpdateAt),
valid(valid),
current(current)
@@ -141,10 +120,10 @@ public:
{
}
std::shared_ptr<ExternalOwningItem> validItem() const override { return valid; }
- DomItem validItem(DomItem &self) const override { return self.copy(valid); }
+ DomItem validItem(const DomItem &self) const override { return self.copy(valid); }
std::shared_ptr<ExternalOwningItem> currentItem() const override { return current; }
- DomItem currentItem(DomItem &self) const override { return self.copy(current); }
- std::shared_ptr<ExternalItemPair> makeCopy(DomItem &self) const
+ DomItem currentItem(const DomItem &self) const override { return self.copy(current); }
+ std::shared_ptr<ExternalItemPair> makeCopy(const DomItem &self) const
{
return std::static_pointer_cast<ExternalItemPair>(doCopy(self));
}
@@ -171,11 +150,11 @@ public:
virtual Path canonicalPath() const = 0;
- Path canonicalPath(DomItem &) const override;
- DomItem containingObject(DomItem &) const override;
- bool iterateDirectSubpaths(DomItem &self, DirectVisitor) override;
+ Path canonicalPath(const DomItem &) const override;
+ DomItem containingObject(const DomItem &) const override;
+ bool iterateDirectSubpaths(const DomItem &self, DirectVisitor) const override;
template<typename T>
- void setExtraOwningItem(QString fieldName, std::shared_ptr<T> item)
+ void setExtraOwningItem(const QString &fieldName, const std::shared_ptr<T> &item)
{
QMutexLocker l(mutex());
if (!item)
@@ -191,55 +170,55 @@ private:
QMap<QString, OwnerT> m_extraOwningItems;
};
-class QMLDOM_EXPORT DomUniverse final : public DomTop
+class QMLDOM_EXPORT DomUniverse final : public DomTop,
+ public std::enable_shared_from_this<DomUniverse>
{
Q_GADGET
Q_DECLARE_TR_FUNCTIONS(DomUniverse);
protected:
- std::shared_ptr<OwningItem> doCopy(DomItem &self) const override;
+ std::shared_ptr<OwningItem> doCopy(const DomItem &self) const override;
public:
- enum class Option{
- Default,
- SingleThreaded
- };
- Q_ENUM(Option)
- 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 QString &universeName);
DomUniverse(const DomUniverse &) = delete;
- static std::shared_ptr<DomUniverse> guaranteeUniverse(std::shared_ptr<DomUniverse> univ);
- static DomItem create(QString universeName, Options options = Option::SingleThreaded);
+ static std::shared_ptr<DomUniverse> guaranteeUniverse(const std::shared_ptr<DomUniverse> &univ);
+ static DomItem create(const QString &universeName);
Path canonicalPath() const override;
using DomTop::canonicalPath;
- bool iterateDirectSubpaths(DomItem &self, DirectVisitor) override;
- std::shared_ptr<DomUniverse> makeCopy(DomItem &self) const
+ bool iterateDirectSubpaths(const DomItem &self, DirectVisitor) const override;
+ std::shared_ptr<DomUniverse> makeCopy(const DomItem &self) const
{
return std::static_pointer_cast<DomUniverse>(doCopy(self));
}
- void loadFile(DomItem &self, QString filePath, QString logicalPath, Callback callback,
- LoadOptions loadOptions,
- std::optional<DomType> fileType = std::optional<DomType>());
- void loadFile(DomItem &self, QString canonicalFilePath, QString logicalPath, QString code,
- QDateTime codeDate, Callback callback, LoadOptions loadOptions,
- std::optional<DomType> fileType = std::optional<DomType>());
- void execQueue();
+ // Helper structure reflecting the change in the map once loading && parsing is completed
+ // formerItem - DomItem representing value (ExternalItemPair) existing in the map before the
+ // loading && parsing. Might be empty (if didn't exist / failure) or equal to currentItem
+ // currentItem - DomItem representing current map value
+ struct LoadResult
+ {
+ DomItem formerItem;
+ DomItem currentItem;
+ };
+
+ LoadResult loadFile(const FileToLoad &file, DomType fileType,
+ DomCreationOptions creationOptions = {});
void removePath(const QString &dir);
- std::shared_ptr<ExternalItemPair<GlobalScope>> globalScopeWithName(QString name) const
+ std::shared_ptr<ExternalItemPair<GlobalScope>> globalScopeWithName(const QString &name) const
{
QMutexLocker l(mutex());
return m_globalScopeWithName.value(name);
}
- std::shared_ptr<ExternalItemPair<GlobalScope>> ensureGlobalScopeWithName(QString name)
+ std::shared_ptr<ExternalItemPair<GlobalScope>> ensureGlobalScopeWithName(const QString &name)
{
if (auto current = globalScopeWithName(name))
return current;
@@ -263,7 +242,7 @@ public:
return QSet<QString>(map.keyBegin(), map.keyEnd());
}
- std::shared_ptr<ExternalItemPair<QmlDirectory>> qmlDirectoryWithPath(QString path) const
+ std::shared_ptr<ExternalItemPair<QmlDirectory>> qmlDirectoryWithPath(const QString &path) const
{
QMutexLocker l(mutex());
return m_qmlDirectoryWithPath.value(path);
@@ -278,7 +257,7 @@ public:
return QSet<QString>(map.keyBegin(), map.keyEnd());
}
- std::shared_ptr<ExternalItemPair<QmldirFile>> qmldirFileWithPath(QString path) const
+ std::shared_ptr<ExternalItemPair<QmldirFile>> qmldirFileWithPath(const QString &path) const
{
QMutexLocker l(mutex());
return m_qmldirFileWithPath.value(path);
@@ -293,7 +272,7 @@ public:
return QSet<QString>(map.keyBegin(), map.keyEnd());
}
- std::shared_ptr<ExternalItemPair<QmlFile>> qmlFileWithPath(QString path) const
+ std::shared_ptr<ExternalItemPair<QmlFile>> qmlFileWithPath(const QString &path) const
{
QMutexLocker l(mutex());
return m_qmlFileWithPath.value(path);
@@ -308,7 +287,7 @@ public:
return QSet<QString>(map.keyBegin(), map.keyEnd());
}
- std::shared_ptr<ExternalItemPair<JsFile>> jsFileWithPath(QString path) const
+ std::shared_ptr<ExternalItemPair<JsFile>> jsFileWithPath(const QString &path) const
{
QMutexLocker l(mutex());
return m_jsFileWithPath.value(path);
@@ -323,7 +302,7 @@ public:
return QSet<QString>(map.keyBegin(), map.keyEnd());
}
- std::shared_ptr<ExternalItemPair<QmltypesFile>> qmltypesFileWithPath(QString path) const
+ std::shared_ptr<ExternalItemPair<QmltypesFile>> qmltypesFileWithPath(const QString &path) const
{
QMutexLocker l(mutex());
return m_qmltypesFileWithPath.value(path);
@@ -341,37 +320,145 @@ public:
QString name() const {
return m_name;
}
- Options options() const {
- return m_options;
+
+private:
+ struct ContentWithDate
+ {
+ QString content;
+ QDateTime date;
+ };
+ // contains either Content with the timestamp when it was read or an Error
+ using ReadResult = std::variant<ContentWithDate, ErrorMessage>;
+ ReadResult readFileContent(const QString &canonicalPath) const;
+
+ LoadResult load(const ContentWithDate &codeWithDate, const FileToLoad &file, DomType fType,
+ DomCreationOptions creationOptions = {});
+
+ // contains either Content to be parsed or LoadResult if loading / parsing is not needed
+ using PreloadResult = std::variant<ContentWithDate, LoadResult>;
+ PreloadResult preload(const DomItem &univ, const FileToLoad &file, DomType fType) const;
+
+ std::shared_ptr<QmlFile> parseQmlFile(const QString &code, const FileToLoad &file,
+ const QDateTime &contentDate,
+ DomCreationOptions creationOptions);
+ std::shared_ptr<JsFile> parseJsFile(const QString &code, const FileToLoad &file,
+ const QDateTime &contentDate);
+ std::shared_ptr<ExternalItemPairBase> getPathValueOrNull(DomType fType,
+ const QString &path) const;
+ std::optional<DomItem> getItemIfMostRecent(const DomItem &univ, DomType fType,
+ const QString &path) const;
+ std::optional<DomItem> getItemIfHasSameCode(const DomItem &univ, DomType fType,
+ const QString &canonicalPath,
+ const ContentWithDate &codeWithDate) const;
+ static bool valueHasMostRecentItem(const ExternalItemPairBase *value,
+ const QDateTime &lastModified);
+ static bool valueHasSameContent(const ExternalItemPairBase *value, const QString &content);
+
+ // TODO better name / consider proper public get/set
+ template <typename T>
+ QMap<QString, std::shared_ptr<ExternalItemPair<T>>> &getMutableRefToMap()
+ {
+ Q_ASSERT(!mutex()->tryLock());
+ if constexpr (std::is_same_v<T, QmlDirectory>) {
+ return m_qmlDirectoryWithPath;
+ }
+ if constexpr (std::is_same_v<T, QmldirFile>) {
+ return m_qmldirFileWithPath;
+ }
+ if constexpr (std::is_same_v<T, QmlFile>) {
+ return m_qmlFileWithPath;
+ }
+ if constexpr (std::is_same_v<T, JsFile>) {
+ return m_jsFileWithPath;
+ }
+ if constexpr (std::is_same_v<T, QmltypesFile>) {
+ return m_qmltypesFileWithPath;
+ }
+ if constexpr (std::is_same_v<T, GlobalScope>) {
+ return m_globalScopeWithName;
+ }
+ Q_UNREACHABLE();
}
- QQueue<ParsingTask> queue() const {
- QMutexLocker l(mutex());
- return m_queue;
+
+ // Inserts or updates an entry reflecting ExternalItem in the corresponding map
+ // Returns a pair of:
+ // - current ExternalItemPair, current value in the map (might be empty, or equal to curValue)
+ // - new current ExternalItemPair, value in the map after after the execution of this function
+ template <typename T>
+ QPair<std::shared_ptr<ExternalItemPair<T>>, std::shared_ptr<ExternalItemPair<T>>>
+ insertOrUpdateEntry(std::shared_ptr<T> newItem)
+ {
+ std::shared_ptr<ExternalItemPair<T>> curValue;
+ std::shared_ptr<ExternalItemPair<T>> newCurValue;
+ QString canonicalPath = newItem->canonicalFilePath();
+ QDateTime now = QDateTime::currentDateTimeUtc();
+ {
+ QMutexLocker l(mutex());
+ auto &map = getMutableRefToMap<T>();
+ auto it = map.find(canonicalPath);
+ if (it != map.cend() && (*it) && (*it)->current) {
+ curValue = *it;
+ if (valueHasSameContent(curValue.get(), newItem->code())) {
+ // value in the map has same content as newItem, a.k.a. most recent
+ newCurValue = curValue;
+ if (newCurValue->current->lastDataUpdateAt() < newItem->lastDataUpdateAt()) {
+ // update timestamp in the current, as if its content was refreshed by
+ // NewItem
+ newCurValue->current->refreshedDataAt(newItem->lastDataUpdateAt());
+ }
+ } else if (curValue->current->lastDataUpdateAt() > newItem->lastDataUpdateAt()) {
+ // value in the map is more recent than newItem, nothing to update
+ newCurValue = curValue;
+ } else {
+ // perform update with newItem
+ curValue->current = std::move(newItem);
+ curValue->currentExposedAt = now;
+ if (curValue->current->isValid()) {
+ curValue->valid = curValue->current;
+ curValue->validExposedAt = std::move(now);
+ }
+ newCurValue = curValue;
+ }
+ } else {
+ // not found / invalid, just insert
+ newCurValue = std::make_shared<ExternalItemPair<T>>(
+ (newItem->isValid() ? newItem : std::shared_ptr<T>()), newItem, now, now);
+ map.insert(canonicalPath, newCurValue);
+ }
+ }
+ return qMakePair(curValue, newCurValue);
+ }
+
+ // Inserts or updates an entry reflecting ExternalItem in the corresponding map
+ // returns LoadResult reflecting the change made to the map
+ template <typename T>
+ LoadResult insertOrUpdateExternalItem(std::shared_ptr<T> extItem)
+ {
+ auto change = insertOrUpdateEntry<T>(std::move(extItem));
+ DomItem univ(shared_from_this());
+ return { univ.copy(change.first), univ.copy(change.second) };
}
private:
QString m_name;
- Options m_options;
QMap<QString, std::shared_ptr<ExternalItemPair<GlobalScope>>> m_globalScopeWithName;
QMap<QString, std::shared_ptr<ExternalItemPair<QmlDirectory>>> m_qmlDirectoryWithPath;
QMap<QString, std::shared_ptr<ExternalItemPair<QmldirFile>>> m_qmldirFileWithPath;
QMap<QString, std::shared_ptr<ExternalItemPair<QmlFile>>> m_qmlFileWithPath;
QMap<QString, std::shared_ptr<ExternalItemPair<JsFile>>> m_jsFileWithPath;
QMap<QString, std::shared_ptr<ExternalItemPair<QmltypesFile>>> m_qmltypesFileWithPath;
- QQueue<ParsingTask> 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 final override { return kindValue; }
- ExternalItemInfoBase(Path canonicalPath,
- QDateTime currentExposedAt = QDateTime::fromMSecsSinceEpoch(0, QTimeZone::UTC),
- int derivedFrom = 0,
- QDateTime lastDataUpdateAt = QDateTime::fromMSecsSinceEpoch(0, QTimeZone::UTC))
+ ExternalItemInfoBase(
+ const Path &canonicalPath,
+ const QDateTime &currentExposedAt = QDateTime::fromMSecsSinceEpoch(0, QTimeZone::UTC),
+ int derivedFrom = 0,
+ const QDateTime &lastDataUpdateAt = QDateTime::fromMSecsSinceEpoch(0, QTimeZone::UTC))
: OwningItem(derivedFrom, lastDataUpdateAt),
m_canonicalPath(canonicalPath),
m_currentExposedAt(currentExposedAt)
@@ -379,22 +466,22 @@ public:
ExternalItemInfoBase(const ExternalItemInfoBase &o) = default;
virtual std::shared_ptr<ExternalOwningItem> currentItem() const = 0;
- virtual DomItem currentItem(DomItem &) const = 0;
+ virtual DomItem currentItem(const DomItem &) const = 0;
- QString canonicalFilePath(DomItem &) const final override;
+ QString canonicalFilePath(const DomItem &) const final override;
Path canonicalPath() const { return m_canonicalPath; }
- Path canonicalPath(DomItem &) const final override { return canonicalPath(); }
- bool iterateDirectSubpaths(DomItem &self, DirectVisitor) final override;
- DomItem field(DomItem &self, QStringView name) const final override
+ Path canonicalPath(const DomItem &) const final override { return canonicalPath(); }
+ bool iterateDirectSubpaths(const DomItem &self, DirectVisitor) const final override;
+ DomItem field(const DomItem &self, QStringView name) const final override
{
return OwningItem::field(self, name);
}
- int currentRevision(DomItem &self) const;
- int lastRevision(DomItem &self) const;
- int lastValidRevision(DomItem &self) const;
+ int currentRevision(const DomItem &self) const;
+ int lastRevision(const DomItem &self) const;
+ int lastValidRevision(const DomItem &self) const;
- std::shared_ptr<ExternalItemInfoBase> makeCopy(DomItem &self) const
+ std::shared_ptr<ExternalItemInfoBase> makeCopy(const DomItem &self) const
{
return std::static_pointer_cast<ExternalItemInfoBase>(doCopy(self));
}
@@ -408,12 +495,12 @@ public:
void refreshedDataAt(QDateTime tNew) final override
{
- return OwningItem::refreshedDataAt(tNew);
if (currentItem())
currentItem()->refreshedDataAt(tNew);
+ return OwningItem::refreshedDataAt(tNew);
}
- void ensureLogicalFilePath(QString path) {
+ void ensureLogicalFilePath(const QString &path) {
QMutexLocker l(mutex());
if (!m_logicalFilePaths.contains(path))
m_logicalFilePaths.append(path);
@@ -446,28 +533,29 @@ template<typename T>
class ExternalItemInfo final : public ExternalItemInfoBase
{
protected:
- std::shared_ptr<OwningItem> doCopy(DomItem &) const override
+ std::shared_ptr<OwningItem> doCopy(const DomItem &) const override
{
return std::make_shared<ExternalItemInfo>(*this);
}
public:
constexpr static DomType kindValue = DomType::ExternalItemInfo;
- ExternalItemInfo(std::shared_ptr<T> current = std::shared_ptr<T>(),
- QDateTime currentExposedAt = QDateTime::fromMSecsSinceEpoch(0, QTimeZone::UTC),
- int derivedFrom = 0,
- QDateTime lastDataUpdateAt = QDateTime::fromMSecsSinceEpoch(0, QTimeZone::UTC))
+ ExternalItemInfo(
+ const std::shared_ptr<T> &current = std::shared_ptr<T>(),
+ const QDateTime &currentExposedAt = QDateTime::fromMSecsSinceEpoch(0, QTimeZone::UTC),
+ int derivedFrom = 0,
+ const QDateTime &lastDataUpdateAt = QDateTime::fromMSecsSinceEpoch(0, QTimeZone::UTC))
: ExternalItemInfoBase(current->canonicalPath().dropTail(), currentExposedAt, derivedFrom,
lastDataUpdateAt),
current(current)
{}
- ExternalItemInfo(QString canonicalPath) : current(new T(canonicalPath)) { }
+ ExternalItemInfo(const QString &canonicalPath) : current(new T(canonicalPath)) { }
ExternalItemInfo(const ExternalItemInfo &o):
ExternalItemInfoBase(o), current(o.current)
{
}
- std::shared_ptr<ExternalItemInfo> makeCopy(DomItem &self) const
+ std::shared_ptr<ExternalItemInfo> makeCopy(const DomItem &self) const
{
return std::static_pointer_cast<ExternalItemInfo>(doCopy(self));
}
@@ -475,7 +563,7 @@ public:
std::shared_ptr<ExternalOwningItem> currentItem() const override {
return current;
}
- DomItem currentItem(DomItem &self) const override { return self.copy(current); }
+ DomItem currentItem(const DomItem &self) const override { return self.copy(current); }
std::shared_ptr<T> current;
};
@@ -499,7 +587,7 @@ class QMLDOM_EXPORT LoadInfo final : public OwningItem
Q_DECLARE_TR_FUNCTIONS(LoadInfo);
protected:
- std::shared_ptr<OwningItem> doCopy(DomItem &self) const override;
+ std::shared_ptr<OwningItem> doCopy(const DomItem &self) const override;
public:
constexpr static DomType kindValue = DomType::LoadInfo;
@@ -513,9 +601,9 @@ public:
Done // fully loaded
};
- LoadInfo(Path elPath = Path(), Status status = Status::NotStarted, int nLoaded = 0,
+ LoadInfo(const Path &elPath = Path(), Status status = Status::NotStarted, int nLoaded = 0,
int derivedFrom = 0,
- QDateTime lastDataUpdateAt = QDateTime::fromMSecsSinceEpoch(0, QTimeZone::UTC))
+ const QDateTime &lastDataUpdateAt = QDateTime::fromMSecsSinceEpoch(0, QTimeZone::UTC))
: OwningItem(derivedFrom, lastDataUpdateAt),
m_elementCanonicalPath(elPath),
m_status(status),
@@ -534,23 +622,23 @@ public:
}
}
- Path canonicalPath(DomItem &self) const override;
+ Path canonicalPath(const DomItem &self) const override;
- bool iterateDirectSubpaths(DomItem &self, DirectVisitor) override;
- std::shared_ptr<LoadInfo> makeCopy(DomItem &self) const
+ bool iterateDirectSubpaths(const DomItem &self, DirectVisitor) const override;
+ std::shared_ptr<LoadInfo> makeCopy(const DomItem &self) const
{
return std::static_pointer_cast<LoadInfo>(doCopy(self));
}
- void addError(DomItem &self, ErrorMessage msg) override
+ void addError(const DomItem &self, ErrorMessage &&msg) override
{
- self.path(elementCanonicalPath()).addError(msg);
+ self.path(elementCanonicalPath()).addError(std::move(msg));
}
- void addEndCallback(DomItem &self, std::function<void(Path, DomItem &, DomItem &)> callback);
+ void addEndCallback(const DomItem &self, std::function<void(Path, const DomItem &, const DomItem &)> callback);
- void advanceLoad(DomItem &self);
- void finishedLoadingDep(DomItem &self, const Dependency &d);
- void execEnd(DomItem &self);
+ void advanceLoad(const DomItem &self);
+ void finishedLoadingDep(const DomItem &self, const Dependency &d);
+ void execEnd(const DomItem &self);
Status status() const
{
@@ -595,15 +683,15 @@ public:
}
private:
- void doAddDependencies(DomItem &self);
- void addDependency(DomItem &self, const Dependency &dep);
+ void doAddDependencies(const DomItem &self);
+ void addDependency(const DomItem &self, const Dependency &dep);
Path m_elementCanonicalPath;
Status m_status;
int m_nLoaded;
QQueue<Dependency> m_toDo;
QList<Dependency> m_inProgress;
- QList<std::function<void(Path, DomItem &, DomItem &)>> m_endCallbacks;
+ QList<std::function<void(Path, const DomItem &, const DomItem &)>> m_endCallbacks;
};
enum class EnvLookup { Normal, NoBase, BaseOnly };
@@ -617,21 +705,31 @@ public:
enum class Cached { None, First, All };
Q_ENUM(Cached)
- static RefCacheEntry forPath(DomItem &el, Path canonicalPath);
- static bool addForPath(DomItem &el, Path canonicalPath, const RefCacheEntry &entry,
+ static RefCacheEntry forPath(const DomItem &el, const Path &canonicalPath);
+ static bool addForPath(const DomItem &el, const Path &canonicalPath, const RefCacheEntry &entry,
AddOption addOption = AddOption::KeepExisting);
Cached cached = Cached::None;
QList<Path> canonicalPaths;
};
-class QMLDOM_EXPORT DomEnvironment final : public DomTop
+class QMLDOM_EXPORT DomEnvironment final : public DomTop,
+ public std::enable_shared_from_this<DomEnvironment>
{
Q_GADGET
Q_DECLARE_TR_FUNCTIONS(DomEnvironment);
protected:
- std::shared_ptr<OwningItem> doCopy(DomItem &self) const override;
+ std::shared_ptr<OwningItem> doCopy(const DomItem &self) const override;
+private:
+ struct TypeReader
+ {
+ std::weak_ptr<DomEnvironment> m_env;
+
+ QList<QQmlJS::DiagnosticMessage>
+ operator()(QQmlJSImporter *importer, const QString &filePath,
+ const QSharedPointer<QQmlJSScope> &scopeToPopulate);
+ };
public:
enum class Option {
Default = 0x0,
@@ -651,121 +749,336 @@ public:
Path canonicalPath() const override;
using DomTop::canonicalPath;
- bool iterateDirectSubpaths(DomItem &self, DirectVisitor) override;
- DomItem field(DomItem &self, QStringView name) const final override;
+ bool iterateDirectSubpaths(const DomItem &self, DirectVisitor) const override;
+ DomItem field(const DomItem &self, QStringView name) const final override;
- std::shared_ptr<DomEnvironment> makeCopy(DomItem &self) const;
+ std::shared_ptr<DomEnvironment> makeCopy(const DomItem &self) const;
- void loadFile(DomItem &self, QString filePath, QString logicalPath, Callback loadCallback,
- Callback directDepsCallback, Callback endCallback, LoadOptions loadOptions,
+ void loadFile(const FileToLoad &file, const Callback &callback,
std::optional<DomType> fileType = std::optional<DomType>(),
- ErrorHandler h = nullptr);
- void loadFile(DomItem &self, QString canonicalFilePath, QString logicalPath, QString code,
- QDateTime codeDate, Callback loadCallback, Callback directDepsCallback,
- Callback endCallback, LoadOptions loadOptions,
- std::optional<DomType> fileType = std::optional<DomType>(),
- ErrorHandler h = nullptr);
- void loadModuleDependency(DomItem &self, QString uri, Version v,
- Callback loadCallback = nullptr, Callback endCallback = nullptr,
- ErrorHandler = nullptr);
- void loadBuiltins(DomItem &self, Callback callback = nullptr, ErrorHandler h = nullptr);
+ const ErrorHandler &h = nullptr /* used only in loadPendingDependencies*/);
+ void loadBuiltins(const Callback &callback = nullptr, const ErrorHandler &h = nullptr);
+ void loadModuleDependency(const QString &uri, Version v, const Callback &callback = nullptr,
+ const ErrorHandler & = nullptr);
+
void removePath(const QString &path);
std::shared_ptr<DomUniverse> universe() const;
- QSet<QString> moduleIndexUris(DomItem &self, EnvLookup lookup = EnvLookup::Normal) const;
- QSet<int> moduleIndexMajorVersions(DomItem &self, QString uri,
+ QSet<QString> moduleIndexUris(const DomItem &self, EnvLookup lookup = EnvLookup::Normal) const;
+ QSet<int> moduleIndexMajorVersions(const DomItem &self, const QString &uri,
EnvLookup lookup = EnvLookup::Normal) const;
- std::shared_ptr<ModuleIndex> moduleIndexWithUri(DomItem &self, QString uri, int majorVersion,
+ std::shared_ptr<ModuleIndex> moduleIndexWithUri(const DomItem &self, const QString &uri, int majorVersion,
EnvLookup lookup, Changeable changeable,
- ErrorHandler errorHandler = nullptr);
- std::shared_ptr<ModuleIndex> moduleIndexWithUri(DomItem &self, QString uri, int majorVersion,
+ const ErrorHandler &errorHandler = nullptr);
+ std::shared_ptr<ModuleIndex> moduleIndexWithUri(const DomItem &self, const QString &uri, int majorVersion,
EnvLookup lookup = EnvLookup::Normal) const;
std::shared_ptr<ExternalItemInfo<QmlDirectory>>
- qmlDirectoryWithPath(DomItem &self, QString path, EnvLookup options = EnvLookup::Normal) const;
- QSet<QString> qmlDirectoryPaths(DomItem &self, EnvLookup options = EnvLookup::Normal) const;
+ qmlDirectoryWithPath(const DomItem &self, const QString &path, EnvLookup options = EnvLookup::Normal) const;
+ QSet<QString> qmlDirectoryPaths(const DomItem &self, EnvLookup options = EnvLookup::Normal) const;
std::shared_ptr<ExternalItemInfo<QmldirFile>>
- qmldirFileWithPath(DomItem &self, QString path, EnvLookup options = EnvLookup::Normal) const;
- QSet<QString> qmldirFilePaths(DomItem &self, EnvLookup options = EnvLookup::Normal) const;
+ qmldirFileWithPath(const DomItem &self, const QString &path, EnvLookup options = EnvLookup::Normal) const;
+ QSet<QString> qmldirFilePaths(const DomItem &self, EnvLookup options = EnvLookup::Normal) const;
std::shared_ptr<ExternalItemInfoBase>
- qmlDirWithPath(DomItem &self, QString path, EnvLookup options = EnvLookup::Normal) const;
- QSet<QString> qmlDirPaths(DomItem &self, EnvLookup options = EnvLookup::Normal) const;
+ qmlDirWithPath(const DomItem &self, const QString &path, EnvLookup options = EnvLookup::Normal) const;
+ QSet<QString> qmlDirPaths(const DomItem &self, EnvLookup options = EnvLookup::Normal) const;
std::shared_ptr<ExternalItemInfo<QmlFile>>
- qmlFileWithPath(DomItem &self, QString path, EnvLookup options = EnvLookup::Normal) const;
- QSet<QString> qmlFilePaths(DomItem &self, EnvLookup lookup = EnvLookup::Normal) const;
+ qmlFileWithPath(const DomItem &self, const QString &path, EnvLookup options = EnvLookup::Normal) const;
+ QSet<QString> qmlFilePaths(const DomItem &self, EnvLookup lookup = EnvLookup::Normal) const;
std::shared_ptr<ExternalItemInfo<JsFile>>
- jsFileWithPath(DomItem &self, QString path, EnvLookup options = EnvLookup::Normal) const;
- QSet<QString> jsFilePaths(DomItem &self, EnvLookup lookup = EnvLookup::Normal) const;
+ jsFileWithPath(const DomItem &self, const QString &path, EnvLookup options = EnvLookup::Normal) const;
+ QSet<QString> jsFilePaths(const DomItem &self, EnvLookup lookup = EnvLookup::Normal) const;
std::shared_ptr<ExternalItemInfo<QmltypesFile>>
- qmltypesFileWithPath(DomItem &self, QString path, EnvLookup options = EnvLookup::Normal) const;
- QSet<QString> qmltypesFilePaths(DomItem &self, EnvLookup lookup = EnvLookup::Normal) const;
+ qmltypesFileWithPath(const DomItem &self, const QString &path, EnvLookup options = EnvLookup::Normal) const;
+ QSet<QString> qmltypesFilePaths(const DomItem &self, EnvLookup lookup = EnvLookup::Normal) const;
std::shared_ptr<ExternalItemInfo<GlobalScope>>
- globalScopeWithName(DomItem &self, QString name, EnvLookup lookup = EnvLookup::Normal) const;
+ globalScopeWithName(const DomItem &self, const QString &name, EnvLookup lookup = EnvLookup::Normal) const;
std::shared_ptr<ExternalItemInfo<GlobalScope>>
- ensureGlobalScopeWithName(DomItem &self, QString name, EnvLookup lookup = EnvLookup::Normal);
- QSet<QString> globalScopeNames(DomItem &self, EnvLookup lookup = EnvLookup::Normal) const;
-
- explicit DomEnvironment(QStringList loadPaths, Options options = Option::SingleThreaded,
- std::shared_ptr<DomUniverse> universe = nullptr);
- explicit DomEnvironment(std::shared_ptr<DomEnvironment> parent, QStringList loadPaths,
- Options options = Option::SingleThreaded);
+ ensureGlobalScopeWithName(const DomItem &self, const QString &name, EnvLookup lookup = EnvLookup::Normal);
+ QSet<QString> globalScopeNames(const DomItem &self, EnvLookup lookup = EnvLookup::Normal) const;
+
+ explicit DomEnvironment(const QStringList &loadPaths, Options options = Option::SingleThreaded,
+ DomCreationOptions domCreationOptions = None,
+ const std::shared_ptr<DomUniverse> &universe = nullptr);
+ explicit DomEnvironment(const std::shared_ptr<DomEnvironment> &parent,
+ const QStringList &loadPaths, Options options = Option::SingleThreaded,
+ DomCreationOptions domCreationOptions = None);
DomEnvironment(const DomEnvironment &o) = delete;
- static DomItem create(QStringList loadPaths, Options options = Option::SingleThreaded,
- DomItem &universe = DomItem::empty);
-
- std::shared_ptr<ExternalItemInfo<QmlFile>>
- addQmlFile(std::shared_ptr<QmlFile> file, AddOption option = AddOption::KeepExisting);
- std::shared_ptr<ExternalItemInfo<QmlDirectory>>
- addQmlDirectory(std::shared_ptr<QmlDirectory> file, AddOption option = AddOption::KeepExisting);
- std::shared_ptr<ExternalItemInfo<QmldirFile>>
- addQmldirFile(std::shared_ptr<QmldirFile> file, AddOption option = AddOption::KeepExisting);
- std::shared_ptr<ExternalItemInfo<QmltypesFile>>
- addQmltypesFile(std::shared_ptr<QmltypesFile> file, AddOption option = AddOption::KeepExisting);
- std::shared_ptr<ExternalItemInfo<JsFile>> addJsFile(std::shared_ptr<JsFile> file,
- AddOption option = AddOption::KeepExisting);
- std::shared_ptr<ExternalItemInfo<GlobalScope>>
- addGlobalScope(std::shared_ptr<GlobalScope> file, AddOption option = AddOption::KeepExisting);
-
- bool commitToBase(DomItem &self, std::shared_ptr<DomEnvironment> validEnv = nullptr);
-
- void addLoadInfo(DomItem &self, std::shared_ptr<LoadInfo> loadInfo);
- std::shared_ptr<LoadInfo> loadInfo(Path path) const;
+ static std::shared_ptr<DomEnvironment>
+ create(const QStringList &loadPaths, Options options = Option::SingleThreaded,
+ DomCreationOptions creationOptions = DomCreationOption::None,
+ const DomItem &universe = DomItem::empty);
+
+ // TODO AddOption can easily be removed later. KeepExisting option only used in one
+ // place which will be removed in https://codereview.qt-project.org/c/qt/qtdeclarative/+/523217
+ void addQmlFile(const std::shared_ptr<QmlFile> &file,
+ AddOption option = AddOption::KeepExisting);
+ void addQmlDirectory(const std::shared_ptr<QmlDirectory> &file,
+ AddOption option = AddOption::KeepExisting);
+ void addQmldirFile(const std::shared_ptr<QmldirFile> &file,
+ AddOption option = AddOption::KeepExisting);
+ void addQmltypesFile(const std::shared_ptr<QmltypesFile> &file,
+ AddOption option = AddOption::KeepExisting);
+ void addJsFile(const std::shared_ptr<JsFile> &file, AddOption option = AddOption::KeepExisting);
+ void addGlobalScope(const std::shared_ptr<GlobalScope> &file,
+ AddOption option = AddOption::KeepExisting);
+
+ bool commitToBase(
+ const DomItem &self, const std::shared_ptr<DomEnvironment> &validEnv = nullptr);
+
+ void addDependenciesToLoad(const Path &path);
+ void addLoadInfo(
+ const DomItem &self, const std::shared_ptr<LoadInfo> &loadInfo);
+ std::shared_ptr<LoadInfo> loadInfo(const Path &path) const;
QList<Path> loadInfoPaths() const;
QHash<Path, std::shared_ptr<LoadInfo>> loadInfos() const;
- void loadPendingDependencies(DomItem &self);
- bool finishLoadingDependencies(DomItem &self, int waitMSec = 30000);
- void addWorkForLoadInfo(Path elementCanonicalPath);
+ void loadPendingDependencies();
+ bool finishLoadingDependencies(int waitMSec = 30000);
+ void addWorkForLoadInfo(const Path &elementCanonicalPath);
Options options() const;
std::shared_ptr<DomEnvironment> base() const;
QStringList loadPaths() const;
+ QStringList qmldirFiles() const;
QString globalScopeName() const;
static QList<Import> defaultImplicitImports();
QList<Import> implicitImports() const;
- void addAllLoadedCallback(DomItem &self, Callback c);
+ void addAllLoadedCallback(const DomItem &self, Callback c);
void clearReferenceCache();
void setLoadPaths(const QStringList &v);
+ // Helper structure reflecting the change in the map once loading / fetching is completed
+ // formerItem - DomItem representing value (ExternalItemInfo) existing in the map before the
+ // loading && parsing. Might be empty (if didn't exist / failure) or equal to currentItem
+ // currentItem - DomItem representing current map value
+ struct LoadResult
+ {
+ DomItem formerItem;
+ DomItem currentItem;
+ };
+ // TODO(QTBUG-121171)
+ template <typename T>
+ LoadResult insertOrUpdateExternalItemInfo(const QString &path, std::shared_ptr<T> extItem)
+ {
+ // maybe in the next revision this all can be just substituted by the addExternalItem
+ DomItem env(shared_from_this());
+ // try to fetch from the current env.
+ if (auto curValue = lookup<T>(path, EnvLookup::NoBase)) {
+ // found in the "initial" env
+ return { env.copy(curValue), env.copy(curValue) };
+ }
+ std::shared_ptr<ExternalItemInfo<T>> newCurValue;
+ // try to fetch from the base env
+ auto valueInBase = lookup<T>(path, EnvLookup::BaseOnly);
+ if (!valueInBase) {
+ // Nothing found. Just create an externalItemInfo which will be inserted
+ newCurValue = std::make_shared<ExternalItemInfo<T>>(std::move(extItem),
+ QDateTime::currentDateTimeUtc());
+ } else {
+ // prepare updated value as a copy of the value from the Base to be inserted
+ newCurValue = valueInBase->makeCopy(env);
+ if (newCurValue->current != extItem) {
+ newCurValue->current = std::move(extItem);
+ newCurValue->setCurrentExposedAt(QDateTime::currentDateTimeUtc());
+ }
+ }
+ // Before inserting new or updated value, check one more time, if ItemInfo is already
+ // present
+ // lookup<> can't be used here because of the data-race
+ {
+ QMutexLocker l(mutex());
+ auto &map = getMutableRefToMap<T>();
+ const auto &it = map.find(path);
+ if (it != map.end())
+ return { env.copy(*it), env.copy(*it) };
+ // otherwise insert
+ map.insert(path, newCurValue);
+ }
+ return { env.copy(valueInBase), env.copy(newCurValue) };
+ }
+
+ template <typename T>
+ void addExternalItemInfo(const DomItem &newExtItem, const Callback &loadCallback,
+ const Callback &endCallback)
+ {
+ // get either Valid "file" from the ExternalItemPair or the current (wip) "file"
+ std::shared_ptr<T> newItemPtr;
+ if (options() & DomEnvironment::Option::KeepValid)
+ newItemPtr = newExtItem.field(Fields::validItem).ownerAs<T>();
+ if (!newItemPtr)
+ newItemPtr = newExtItem.field(Fields::currentItem).ownerAs<T>();
+ Q_ASSERT(newItemPtr && "envCallbackForFile reached without current file");
+
+ auto loadResult = insertOrUpdateExternalItemInfo(newExtItem.canonicalFilePath(),
+ std::move(newItemPtr));
+ Path p = loadResult.currentItem.canonicalPath();
+ {
+ auto depLoad = qScopeGuard([p, this, endCallback] {
+ addDependenciesToLoad(p);
+ // add EndCallback to the queue, which should be called once all dependencies are
+ // loaded
+ if (endCallback) {
+ DomItem env = DomItem(shared_from_this());
+ addAllLoadedCallback(
+ env, [p, endCallback](Path, const DomItem &, const DomItem &env) {
+ DomItem el = env.path(p);
+ endCallback(p, el, el);
+ });
+ }
+ });
+ // call loadCallback
+ if (loadCallback) {
+ loadCallback(p, loadResult.formerItem, loadResult.currentItem);
+ }
+ }
+ }
+ void populateFromQmlFile(MutableDomItem &&qmlFile);
+ DomCreationOptions domCreationOptions() const { return m_domCreationOptions; }
+
private:
friend class RefCacheEntry;
- template<typename T>
+
+ void loadFile(const FileToLoad &file, const Callback &loadCallback, const Callback &endCallback,
+ std::optional<DomType> fileType = std::optional<DomType>(),
+ const ErrorHandler &h = nullptr);
+
+ void loadModuleDependency(const DomItem &self, const QString &uri, Version v,
+ Callback loadCallback = nullptr, Callback endCallback = nullptr,
+ const ErrorHandler & = nullptr);
+
+ template <typename T>
QSet<QString> getStrings(function_ref<QSet<QString>()> getBase, const QMap<QString, T> &selfMap,
EnvLookup lookup) const;
- Callback callbackForQmlDirectory(DomItem &self, Callback loadCallback,
- Callback directDepsCallback, Callback endCallback);
- Callback callbackForQmlFile(DomItem &self, Callback loadCallback, Callback directDepsCallback,
- Callback endCallback);
- Callback callbackForQmltypesFile(DomItem &self, Callback loadCallback,
- Callback directDepsCallback, Callback endCallback);
- Callback callbackForQmldirFile(DomItem &self, Callback loadCallback,
- Callback directDepsCallback, Callback endCallback);
+ template <typename T>
+ const QMap<QString, std::shared_ptr<ExternalItemInfo<T>>> &getConstRefToMap() const
+ {
+ Q_ASSERT(!mutex()->tryLock());
+ if constexpr (std::is_same_v<T, GlobalScope>) {
+ return m_globalScopeWithName;
+ }
+ if constexpr (std::is_same_v<T, QmlDirectory>) {
+ return m_qmlDirectoryWithPath;
+ }
+ if constexpr (std::is_same_v<T, QmldirFile>) {
+ return m_qmldirFileWithPath;
+ }
+ if constexpr (std::is_same_v<T, QmlFile>) {
+ return m_qmlFileWithPath;
+ }
+ if constexpr (std::is_same_v<T, JsFile>) {
+ return m_jsFileWithPath;
+ }
+ if constexpr (std::is_same_v<T, QmltypesFile>) {
+ return m_qmltypesFileWithPath;
+ }
+ Q_UNREACHABLE();
+ }
+
+ template <typename T>
+ std::shared_ptr<ExternalItemInfo<T>> lookup(const QString &path, EnvLookup options) const
+ {
+ if (options != EnvLookup::BaseOnly) {
+ QMutexLocker l(mutex());
+ const auto &map = getConstRefToMap<T>();
+ const auto &it = map.find(path);
+ if (it != map.end())
+ return *it;
+ }
+ if (options != EnvLookup::NoBase && m_base)
+ return m_base->lookup<T>(path, options);
+ return {};
+ }
+
+ template <typename T>
+ QMap<QString, std::shared_ptr<ExternalItemInfo<T>>> &getMutableRefToMap()
+ {
+ Q_ASSERT(!mutex()->tryLock());
+ if constexpr (std::is_same_v<T, QmlDirectory>) {
+ return m_qmlDirectoryWithPath;
+ }
+ if constexpr (std::is_same_v<T, QmldirFile>) {
+ return m_qmldirFileWithPath;
+ }
+ if constexpr (std::is_same_v<T, QmlFile>) {
+ return m_qmlFileWithPath;
+ }
+ if constexpr (std::is_same_v<T, JsFile>) {
+ return m_jsFileWithPath;
+ }
+ if constexpr (std::is_same_v<T, QmltypesFile>) {
+ return m_qmltypesFileWithPath;
+ }
+ if constexpr (std::is_same_v<T, GlobalScope>) {
+ return m_globalScopeWithName;
+ }
+ Q_UNREACHABLE();
+ }
+
+ template <typename T>
+ void addExternalItem(std::shared_ptr<T> file, QString key, AddOption option)
+ {
+ if (!file)
+ return;
+
+ auto eInfo = std::make_shared<ExternalItemInfo<T>>(file, QDateTime::currentDateTimeUtc());
+ // Lookup helper can't be used here, because it introduces data-race otherwise
+ // (other modifications might happen between the lookup and the insert)
+ QMutexLocker l(mutex());
+ auto &map = getMutableRefToMap<T>();
+ const auto &it = map.find(key);
+ if (it != map.end() && option == AddOption::KeepExisting)
+ return;
+ map.insert(key, eInfo);
+ }
+
+ using FetchResult =
+ QPair<std::shared_ptr<ExternalItemInfoBase>, std::shared_ptr<ExternalItemInfoBase>>;
+ // This function tries to get an Info object about the ExternalItem from the current env
+ // and depending on the result and options tries to fetch it from the Parent env,
+ // saving a copy with an updated timestamp
+ template <typename T>
+ FetchResult fetchFileFromEnvs(const FileToLoad &file)
+ {
+ const auto &path = file.canonicalPath();
+ // lookup only in the current env
+ if (auto value = lookup<T>(path, EnvLookup::NoBase)) {
+ return qMakePair(value, value);
+ }
+ // try to find the file in the base(parent) Env and insert if found
+ if (options() & Option::NoReload) {
+ if (auto baseV = lookup<T>(path, EnvLookup::BaseOnly)) {
+ // Watch out! QTBUG-121171
+ // It's possible between the lookup and creation of curVal, baseV && baseV->current
+ // might have changed
+ // Prepare a value to be inserted as copy of the value from Base
+ auto curV = std::make_shared<ExternalItemInfo<T>>(
+ baseV->current, QDateTime::currentDateTimeUtc(), baseV->revision(),
+ baseV->lastDataUpdateAt());
+ // Lookup one more time if the value was already inserted to the current env
+ // Lookup can't be used here because of the data-race
+ {
+ QMutexLocker l(mutex());
+ auto &map = getMutableRefToMap<T>();
+ const auto &it = map.find(path);
+ if (it != map.end())
+ return qMakePair(*it, *it);
+ // otherwise insert
+ map.insert(path, curV);
+ }
+ return qMakePair(baseV, curV);
+ }
+ }
+ return qMakePair(nullptr, nullptr);
+ }
+
+ Callback getLoadCallbackFor(DomType fileType, const Callback &loadCallback);
std::shared_ptr<ModuleIndex> lookupModuleInEnv(const QString &uri, int majorVersion) const;
// ModuleLookupResult contains the ModuleIndex pointer, and an indicator whether it was found
@@ -776,11 +1089,12 @@ private:
Origin fromBase = FromGlobal;
};
// helper function used by the moduleIndexWithUri methods
- ModuleLookupResult moduleIndexWithUriHelper(DomItem &self, QString uri, int majorVersion,
+ ModuleLookupResult moduleIndexWithUriHelper(const DomItem &self, const QString &uri, int majorVersion,
EnvLookup lookup = EnvLookup::Normal) const;
const Options m_options;
const std::shared_ptr<DomEnvironment> m_base;
+ std::shared_ptr<DomEnvironment> m_lastValidBase;
const std::shared_ptr<DomUniverse> m_universe;
QStringList m_loadPaths; // paths for qml
QString m_globalScopeName;
@@ -797,6 +1111,18 @@ private:
QList<Import> m_implicitImports;
QList<Callback> m_allLoadedCallback;
QHash<Path, RefCacheEntry> m_referenceCache;
+ DomCreationOptions m_domCreationOptions;
+
+ struct SemanticAnalysis
+ {
+ SemanticAnalysis(const QStringList &loadPaths);
+ void setLoadPaths(const QStringList &loadPaths);
+
+ std::shared_ptr<QQmlJSResourceFileMapper> m_mapper;
+ std::shared_ptr<QQmlJSImporter> m_importer;
+ };
+ std::optional<SemanticAnalysis> m_semanticAnalysis;
+ SemanticAnalysis &semanticAnalysis();
};
Q_DECLARE_OPERATORS_FOR_FLAGS(DomEnvironment::Options)