aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/qmldesigner/designercore
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/qmldesigner/designercore')
-rw-r--r--src/plugins/qmldesigner/designercore/generatedcomponentutils.cpp291
-rw-r--r--src/plugins/qmldesigner/designercore/generatedcomponentutils.h55
-rw-r--r--src/plugins/qmldesigner/designercore/imagecache/imagecachecollector.cpp2
-rw-r--r--src/plugins/qmldesigner/designercore/imagecache/imagecachecollector.h2
-rw-r--r--src/plugins/qmldesigner/designercore/imagecache/taskqueue.h41
-rw-r--r--src/plugins/qmldesigner/designercore/include/externaldependenciesinterface.h1
-rw-r--r--src/plugins/qmldesigner/designercore/include/itemlibraryentry.h13
-rw-r--r--src/plugins/qmldesigner/designercore/include/model.h19
-rw-r--r--src/plugins/qmldesigner/designercore/include/modelfwd.h2
-rw-r--r--src/plugins/qmldesigner/designercore/include/nodehints.h9
-rw-r--r--src/plugins/qmldesigner/designercore/include/nodemetainfo.h17
-rw-r--r--src/plugins/qmldesigner/designercore/include/projectstorageids.h8
-rw-r--r--src/plugins/qmldesigner/designercore/include/qmlitemnode.h1
-rw-r--r--src/plugins/qmldesigner/designercore/include/rewriterview.h13
-rw-r--r--src/plugins/qmldesigner/designercore/include/subcomponentmanager.h2
-rw-r--r--src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp92
-rw-r--r--src/plugins/qmldesigner/designercore/metainfo/itemlibraryentry.cpp23
-rw-r--r--src/plugins/qmldesigner/designercore/metainfo/metainforeader.cpp2
-rw-r--r--src/plugins/qmldesigner/designercore/metainfo/nodehints.cpp35
-rw-r--r--src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp1491
-rw-r--r--src/plugins/qmldesigner/designercore/metainfo/subcomponentmanager.cpp17
-rw-r--r--src/plugins/qmldesigner/designercore/model/abstractview.cpp6
-rw-r--r--src/plugins/qmldesigner/designercore/model/bindingproperty.cpp3
-rw-r--r--src/plugins/qmldesigner/designercore/model/model.cpp156
-rw-r--r--src/plugins/qmldesigner/designercore/model/model_p.h2
-rw-r--r--src/plugins/qmldesigner/designercore/model/modelresourcemanagement.cpp3
-rw-r--r--src/plugins/qmldesigner/designercore/model/modelutils.cpp18
-rw-r--r--src/plugins/qmldesigner/designercore/model/propertycontainer.cpp2
-rw-r--r--src/plugins/qmldesigner/designercore/model/propertyparser.cpp7
-rw-r--r--src/plugins/qmldesigner/designercore/model/qmlitemnode.cpp8
-rw-r--r--src/plugins/qmldesigner/designercore/model/qmlvisualnode.cpp27
-rw-r--r--src/plugins/qmldesigner/designercore/model/rewriteactioncompressor.cpp3
-rw-r--r--src/plugins/qmldesigner/designercore/model/rewriterview.cpp117
-rw-r--r--src/plugins/qmldesigner/designercore/model/stylesheetmerger.cpp16
-rw-r--r--src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp310
-rw-r--r--src/plugins/qmldesigner/designercore/model/texttomodelmerger.h6
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/commontypecache.h248
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/filestatus.h12
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/filesystem.cpp13
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/filesystem.h7
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/filesysteminterface.h1
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/projectstorage.cpp4892
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/projectstorage.h3817
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/projectstorageerrornotifier.cpp17
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/projectstorageerrornotifier.h25
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/projectstorageerrornotifierinterface.h27
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/projectstorageexceptions.cpp120
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/projectstorageexceptions.h33
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/projectstoragefwd.h1
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/projectstorageinfotypes.h221
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/projectstorageinterface.h28
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/projectstoragepathwatchertypes.h43
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/projectstoragetypes.h474
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.cpp758
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.h63
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparser.cpp49
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparser.h2
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/qmltypesparser.cpp115
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/qmltypesparser.h9
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/qmltypesparserinterface.h2
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/sourcepath.h11
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/sourcepathcachetypes.h2
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/storagecache.h2
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/typeannotationreader.cpp30
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/typeannotationreader.h4
-rw-r--r--src/plugins/qmldesigner/designercore/tracing/qmldesignertracing.cpp63
-rw-r--r--src/plugins/qmldesigner/designercore/tracing/qmldesignertracing.h34
-rw-r--r--src/plugins/qmldesigner/designercore/uniquename.cpp165
-rw-r--r--src/plugins/qmldesigner/designercore/uniquename.h17
69 files changed, 9599 insertions, 4526 deletions
diff --git a/src/plugins/qmldesigner/designercore/generatedcomponentutils.cpp b/src/plugins/qmldesigner/designercore/generatedcomponentutils.cpp
new file mode 100644
index 0000000000..da40c4d387
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/generatedcomponentutils.cpp
@@ -0,0 +1,291 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#include "generatedcomponentutils.h"
+#include <qmldesignerconstants.h>
+
+namespace QmlDesigner {
+
+bool couldBeProjectModule(const Utils::FilePath &path, const QString &projectName)
+{
+ if (!path.exists())
+ return false;
+
+ Utils::FilePath qmlDirPath = path.pathAppended("qmldir");
+ if (qmlDirPath.exists()) {
+ Utils::expected_str<QByteArray> qmldirContents = qmlDirPath.fileContents();
+ if (!qmldirContents.has_value())
+ return false;
+
+ const QString expectedLine = QLatin1String("module %1").arg(projectName);
+ QByteArray fileContents = *qmldirContents;
+ QTextStream stream(fileContents);
+ while (!stream.atEnd()) {
+ QString lineData = stream.readLine().trimmed();
+ if (lineData.startsWith(u"module "))
+ return lineData == expectedLine;
+ }
+ }
+ if (path.endsWith(projectName))
+ return true;
+
+ return false;
+}
+
+GeneratedComponentUtils::GeneratedComponentUtils(ExternalDependenciesInterface &externalDependencies)
+ : m_externalDependencies(externalDependencies)
+{
+}
+
+Utils::FilePath GeneratedComponentUtils::generatedComponentsPath() const
+{
+ Utils::FilePath projectPath = Utils::FilePath::fromString(m_externalDependencies.currentProjectDirPath());
+ if (projectPath.isEmpty())
+ return {};
+
+ Utils::FilePath assetImportsPath = projectPath.resolvePath(QLatin1String(Constants::OLD_ASSET_IMPORT_FOLDER));
+ if (assetImportsPath.exists())
+ return assetImportsPath;
+
+ Utils::FilePath componentsPath = projectPath.resolvePath(QLatin1String(Constants::GENERATED_COMPONENTS_FOLDER));
+ if (!componentsPath.exists())
+ componentsPath.createDir();
+
+ return componentsPath;
+}
+
+Utils::FilePath GeneratedComponentUtils::composedEffectsBasePath() const
+{
+ Utils::FilePath basePath = generatedComponentsPath();
+ if (basePath.isEmpty())
+ return {};
+
+ QString effectsImportPath;
+ if (basePath.endsWith(Constants::OLD_ASSET_IMPORT_FOLDER))
+ effectsImportPath = Constants::OLD_EFFECTS_FOLDER;
+ else
+ effectsImportPath = Constants::COMPOSED_EFFECTS_TYPE;
+
+ return basePath.resolvePath(effectsImportPath);
+}
+
+Utils::FilePath GeneratedComponentUtils::composedEffectPath(const QString &effectPath) const
+{
+ Utils::FilePath effectsBasePath = composedEffectsBasePath();
+
+ QString effectName = Utils::FilePath::fromString(effectPath).baseName();
+
+ return effectsBasePath.resolvePath(effectName + "/" + effectName + ".qml");
+}
+
+Utils::FilePath GeneratedComponentUtils::componentBundlesBasePath() const
+{
+ Utils::FilePath basePath = generatedComponentsPath();
+
+ if (basePath.isEmpty())
+ return {};
+
+ if (basePath.endsWith(Constants::GENERATED_COMPONENTS_FOLDER))
+ return basePath.resolvePath(QLatin1String(Constants::COMPONENT_BUNDLES_TYPE));
+
+ return basePath.resolvePath(QLatin1String(Constants::OLD_COMPONENT_BUNDLES_TYPE));
+}
+
+Utils::FilePath GeneratedComponentUtils::import3dBasePath() const
+{
+ Utils::FilePath basePath = generatedComponentsPath();
+
+ if (basePath.isEmpty())
+ return {};
+
+ Utils::FilePath import3dPath;
+ if (basePath.endsWith(Constants::OLD_ASSET_IMPORT_FOLDER))
+ return basePath.resolvePath(QLatin1String(Constants::OLD_QUICK_3D_ASSETS_FOLDER));
+
+ return basePath.resolvePath(QLatin1String(Constants::QUICK_3D_COMPONENTS_FOLDER));
+}
+
+Utils::FilePath GeneratedComponentUtils::materialBundlePath() const
+{
+ Utils::FilePath basePath = componentBundlesBasePath();
+
+ if (basePath.isEmpty())
+ return {};
+
+ if (basePath.endsWith(Constants::OLD_COMPONENT_BUNDLES_TYPE))
+ return basePath.resolvePath(QLatin1String(Constants::OLD_COMPONENT_BUNDLES_MATERIAL_BUNDLE_TYPE));
+
+ return basePath.resolvePath(QLatin1String(Constants::COMPONENT_BUNDLES_MATERIAL_BUNDLE_TYPE));
+}
+
+Utils::FilePath GeneratedComponentUtils::effectBundlePath() const
+{
+ Utils::FilePath basePath = componentBundlesBasePath();
+
+ if (basePath.isEmpty())
+ return {};
+
+ if (basePath.endsWith(Constants::OLD_COMPONENT_BUNDLES_TYPE))
+ return basePath.resolvePath(QLatin1String(Constants::OLD_COMPONENT_BUNDLES_EFFECT_BUNDLE_TYPE));
+
+ return basePath.resolvePath(QLatin1String(Constants::COMPONENT_BUNDLES_EFFECT_BUNDLE_TYPE));
+}
+
+Utils::FilePath GeneratedComponentUtils::projectModulePath(bool generateIfNotExists) const
+{
+ using Utils::FilePath;
+ FilePath projectPath = FilePath::fromString(m_externalDependencies.currentProjectDirPath());
+
+ if (projectPath.isEmpty())
+ return {};
+
+ const QString projectName = m_externalDependencies.projectName();
+
+ FilePath newImportDirectory = projectPath.pathAppended(projectName);
+ if (couldBeProjectModule(newImportDirectory, projectName))
+ return newImportDirectory;
+
+ FilePath oldImportDirectory = projectPath.resolvePath(QLatin1String("imports/") + projectName);
+ if (couldBeProjectModule(oldImportDirectory, projectName))
+ return oldImportDirectory;
+
+ for (const QString &path : m_externalDependencies.projectModulePaths()) {
+ FilePath dir = FilePath::fromString(path);
+ if (couldBeProjectModule(dir, projectName))
+ return dir;
+ }
+
+ if (generateIfNotExists)
+ newImportDirectory.createDir();
+
+ return newImportDirectory;
+}
+
+bool GeneratedComponentUtils::isImport3dPath(const QString &path) const
+{
+ return path.contains('/' + QLatin1String(Constants::OLD_QUICK_3D_ASSETS_FOLDER))
+ || path.contains(QLatin1String(Constants::GENERATED_COMPONENTS_FOLDER) + '/'
+ + QLatin1String(Constants::QUICK_3D_COMPONENTS_FOLDER));
+}
+
+bool GeneratedComponentUtils::isComposedEffectPath(const QString &path) const
+{
+ return path.contains(Constants::OLD_EFFECTS_IMPORT_FOLDER)
+ || path.contains(QLatin1String(Constants::GENERATED_COMPONENTS_FOLDER) + '/'
+ + QLatin1String(Constants::COMPOSED_EFFECTS_TYPE));
+}
+
+bool GeneratedComponentUtils::isBundlePath(const QString &path) const
+{
+ return path.contains(componentBundlesTypePrefix().replace('.', '/'));
+}
+
+bool GeneratedComponentUtils::isGeneratedPath(const QString &path) const
+{
+ return path.startsWith(generatedComponentsPath().toFSPathString());
+}
+
+
+QString GeneratedComponentUtils::generatedComponentTypePrefix() const
+{
+ Utils::FilePath basePath = generatedComponentsPath();
+ if (basePath.isEmpty() || basePath.endsWith(Constants::OLD_ASSET_IMPORT_FOLDER))
+ return {};
+
+ return Constants::GENERATED_COMPONENTS_FOLDER;
+}
+
+QString GeneratedComponentUtils::import3dTypePrefix() const
+{
+ QString basePrefix = generatedComponentTypePrefix();
+
+ if (basePrefix == Constants::GENERATED_COMPONENTS_FOLDER)
+ return basePrefix + '.' + QLatin1String(Constants::QUICK_3D_COMPONENTS_FOLDER);
+
+ return Constants::OLD_QUICK_3D_ASSETS_FOLDER;
+}
+
+QString GeneratedComponentUtils::import3dTypePath() const
+{
+ QString prefix = import3dTypePrefix();
+ prefix.replace('.', '/');
+ return prefix;
+}
+
+QString GeneratedComponentUtils::componentBundlesTypePrefix() const
+{
+ QString basePrefix = generatedComponentTypePrefix();
+
+ if (basePrefix.endsWith(Constants::GENERATED_COMPONENTS_FOLDER))
+ return basePrefix + '.' + QLatin1String(Constants::COMPONENT_BUNDLES_TYPE);
+
+ return Constants::OLD_COMPONENT_BUNDLES_TYPE;
+}
+
+QString GeneratedComponentUtils::composedEffectsTypePrefix() const
+{
+ QString basePrefix = generatedComponentTypePrefix();
+
+ if (basePrefix == Constants::GENERATED_COMPONENTS_FOLDER)
+ return basePrefix + '.' + QLatin1String(Constants::COMPOSED_EFFECTS_TYPE);
+
+ return Constants::OLD_EFFECTS_FOLDER;
+}
+
+QString GeneratedComponentUtils::materialsBundleId() const
+{
+ bool isNewImportDir = generatedComponentTypePrefix().endsWith(Constants::GENERATED_COMPONENTS_FOLDER);
+
+ return QLatin1String(isNewImportDir ? Constants::COMPONENT_BUNDLES_MATERIAL_BUNDLE_TYPE
+ : Constants::OLD_COMPONENT_BUNDLES_MATERIAL_BUNDLE_TYPE);
+}
+
+QString GeneratedComponentUtils::effectsBundleId() const
+{
+ bool isNewImportDir = generatedComponentTypePrefix().endsWith(Constants::GENERATED_COMPONENTS_FOLDER);
+
+ return QLatin1String(isNewImportDir ? Constants::COMPONENT_BUNDLES_EFFECT_BUNDLE_TYPE
+ : Constants::OLD_COMPONENT_BUNDLES_EFFECT_BUNDLE_TYPE);
+}
+
+QString GeneratedComponentUtils::userMaterialsBundleId() const
+{
+ return QLatin1String(Constants::COMPONENT_BUNDLES_USER_MATERIAL_BUNDLE_TYPE);
+}
+
+QString GeneratedComponentUtils::userEffectsBundleId() const
+{
+ return QLatin1String(Constants::COMPONENT_BUNDLES_USER_EFFECT_BUNDLE_TYPE);
+}
+
+QString GeneratedComponentUtils::user3DBundleId() const
+{
+ return QLatin1String(Constants::COMPONENT_BUNDLES_USER_3D_BUNDLE_TYPE);
+}
+
+QString GeneratedComponentUtils::materialsBundleType() const
+{
+ return componentBundlesTypePrefix() + '.' + materialsBundleId();
+}
+
+QString GeneratedComponentUtils::effectsBundleType() const
+{
+ return componentBundlesTypePrefix() + '.' + effectsBundleId();
+}
+
+QString GeneratedComponentUtils::userMaterialsBundleType() const
+{
+ return componentBundlesTypePrefix() + '.' + userMaterialsBundleId();
+}
+
+QString GeneratedComponentUtils::userEffectsBundleType() const
+{
+ return componentBundlesTypePrefix() + '.' + userEffectsBundleId();
+}
+
+QString GeneratedComponentUtils::user3DBundleType() const
+{
+ return componentBundlesTypePrefix() + '.' + user3DBundleId();
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/generatedcomponentutils.h b/src/plugins/qmldesigner/designercore/generatedcomponentutils.h
new file mode 100644
index 0000000000..ceddb405a3
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/generatedcomponentutils.h
@@ -0,0 +1,55 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#pragma once
+
+#include <externaldependenciesinterface.h>
+#include <qmldesignercorelib_exports.h>
+
+#include <utils/filepath.h>
+
+#include <QString>
+
+namespace QmlDesigner {
+
+class QMLDESIGNERCORE_EXPORT GeneratedComponentUtils {
+public:
+ GeneratedComponentUtils(ExternalDependenciesInterface &externalDependencies);
+
+ Utils::FilePath generatedComponentsPath() const;
+ Utils::FilePath composedEffectsBasePath() const;
+ Utils::FilePath composedEffectPath(const QString &effectPath) const;
+ Utils::FilePath componentBundlesBasePath() const;
+ Utils::FilePath import3dBasePath() const;
+ Utils::FilePath materialBundlePath() const;
+ Utils::FilePath effectBundlePath() const;
+ Utils::FilePath projectModulePath(bool generateIfNotExists = false) const;
+
+ bool isImport3dPath(const QString &path) const;
+ bool isComposedEffectPath(const QString &path) const;
+ bool isBundlePath(const QString &path) const;
+ bool isGeneratedPath(const QString &path) const;
+
+ QString generatedComponentTypePrefix() const;
+ QString import3dTypePrefix() const;
+ QString import3dTypePath() const;
+ QString componentBundlesTypePrefix() const;
+ QString composedEffectsTypePrefix() const;
+
+ QString materialsBundleId() const;
+ QString effectsBundleId() const;
+ QString userMaterialsBundleId() const;
+ QString userEffectsBundleId() const;
+ QString user3DBundleId() const;
+
+ QString materialsBundleType() const;
+ QString effectsBundleType() const;
+ QString userMaterialsBundleType() const;
+ QString userEffectsBundleType() const;
+ QString user3DBundleType() const;
+
+private:
+ ExternalDependenciesInterface &m_externalDependencies;
+};
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/imagecache/imagecachecollector.cpp b/src/plugins/qmldesigner/designercore/imagecache/imagecachecollector.cpp
index 955e676d3b..97148e664f 100644
--- a/src/plugins/qmldesigner/designercore/imagecache/imagecachecollector.cpp
+++ b/src/plugins/qmldesigner/designercore/imagecache/imagecachecollector.cpp
@@ -76,8 +76,10 @@ void ImageCacheCollector::start(Utils::SmallStringView name,
AbortCallback abortCallback,
ImageCache::TraceToken traceToken)
{
+#ifdef QDS_USE_PROJECTSTORAGE
if (!m_projectStorage || !m_pathCache)
return;
+#endif
using namespace NanotraceHR::Literals;
auto [collectorTraceToken, flowtoken] = traceToken.beginDurationWithFlow(
diff --git a/src/plugins/qmldesigner/designercore/imagecache/imagecachecollector.h b/src/plugins/qmldesigner/designercore/imagecache/imagecachecollector.h
index c2a912cc3a..fec68c2894 100644
--- a/src/plugins/qmldesigner/designercore/imagecache/imagecachecollector.h
+++ b/src/plugins/qmldesigner/designercore/imagecache/imagecachecollector.h
@@ -64,8 +64,10 @@ private:
QSize captureImageMaximumSize;
ExternalDependenciesInterface &m_externalDependencies;
ImageCacheCollectorNullImageHandling nullImageHandling{};
+#ifdef QDS_USE_PROJECTSTORAGE
ProjectStorageType *m_projectStorage = nullptr;
PathCacheType *m_pathCache = nullptr;
+#endif
};
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/imagecache/taskqueue.h b/src/plugins/qmldesigner/designercore/imagecache/taskqueue.h
index fac7e7d9bf..dc5ed3de23 100644
--- a/src/plugins/qmldesigner/designercore/imagecache/taskqueue.h
+++ b/src/plugins/qmldesigner/designercore/imagecache/taskqueue.h
@@ -31,7 +31,7 @@ public:
{
std::unique_lock lock{m_mutex};
- ensureThreadIsRunning(std::move(traceToken));
+ ensureThreadIsRunning(lock, std::move(traceToken));
m_tasks.emplace_back(std::forward<Arguments>(arguments)...);
}
@@ -54,6 +54,15 @@ public:
clearTasks(oldTasks);
}
+ void putThreadToSleep()
+ {
+ {
+ std::unique_lock lock{m_mutex};
+ m_sleeping = true;
+ }
+ m_condition.notify_all();
+ }
+
private:
void destroy()
{
@@ -66,19 +75,20 @@ private:
{
using namespace std::literals::chrono_literals;
std::unique_lock lock{m_mutex};
- if (m_finishing)
+
+ if (m_finishing || m_sleeping)
return {std::move(lock), true};
+
if (m_tasks.empty()) {
auto timedOutWithoutEntriesOrFinishing = !m_condition.wait_for(lock, 10min, [&] {
- return m_tasks.size() || m_finishing;
+ return m_tasks.size() || m_finishing || m_sleeping;
});
- if (timedOutWithoutEntriesOrFinishing || m_finishing) {
+ if (timedOutWithoutEntriesOrFinishing)
m_sleeping = true;
- return {std::move(lock), true};
- }
}
- return {std::move(lock), false};
+
+ return {std::move(lock), m_finishing || m_sleeping};
}
[[nodiscard]] std::optional<Task> getTask(std::unique_lock<std::mutex> lock)
@@ -94,29 +104,38 @@ private:
return {std::move(task)};
}
- template<typename TraceToken>
- void ensureThreadIsRunning(TraceToken traceToken)
+ template<typename Lock, typename TraceToken>
+ void ensureThreadIsRunning(Lock &lock, TraceToken traceToken)
{
using namespace NanotraceHR::Literals;
if (m_finishing || !m_sleeping)
return;
+ if (m_sleeping) {
+ lock.unlock();
+ joinThread();
+ lock.lock();
+
+ m_sleeping = false;
+ }
+
if (m_backgroundThread.joinable())
return;
- m_sleeping = false;
-
auto [threadCreateToken, flowToken] = traceToken.beginDurationWithFlow(
"thread is created in the task queue"_t);
m_backgroundThread = std::thread{[this](auto traceToken) {
auto duration = traceToken.beginDuration(
"thread is ready"_t);
+
while (true) {
auto [lock, abort] = waitForTasks();
duration.end();
+
if (abort)
return;
+
auto getTaskToken = duration.beginDuration(
"get task from queue"_t);
if (auto task = getTask(std::move(lock)); task) {
diff --git a/src/plugins/qmldesigner/designercore/include/externaldependenciesinterface.h b/src/plugins/qmldesigner/designercore/include/externaldependenciesinterface.h
index 71ddeb7dc1..9055f51b6a 100644
--- a/src/plugins/qmldesigner/designercore/include/externaldependenciesinterface.h
+++ b/src/plugins/qmldesigner/designercore/include/externaldependenciesinterface.h
@@ -28,6 +28,7 @@ public:
virtual QString qmlPuppetFallbackDirectory() const = 0;
virtual QString defaultPuppetToplevelBuildDirectory() const = 0;
virtual QUrl projectUrl() const = 0;
+ virtual QString projectName() const = 0;
virtual QString currentProjectDirPath() const = 0;
virtual QUrl currentResourcePath() const = 0;
virtual void parseItemLibraryDescriptions() = 0;
diff --git a/src/plugins/qmldesigner/designercore/include/itemlibraryentry.h b/src/plugins/qmldesigner/designercore/include/itemlibraryentry.h
index f88f9e35c6..2d0f2ef31e 100644
--- a/src/plugins/qmldesigner/designercore/include/itemlibraryentry.h
+++ b/src/plugins/qmldesigner/designercore/include/itemlibraryentry.h
@@ -42,13 +42,16 @@ class QMLDESIGNERCORE_EXPORT ItemLibraryEntry
public:
ItemLibraryEntry();
- explicit ItemLibraryEntry(const Storage::Info::ItemLibraryEntry &entry,
- const ProjectStorageType &projectStorage);
- ~ItemLibraryEntry() = default;
+ ItemLibraryEntry(const ItemLibraryEntry &) = default;
+ ItemLibraryEntry &operator=(const ItemLibraryEntry &) = default;
+ ItemLibraryEntry(ItemLibraryEntry &&) = default;
+ ItemLibraryEntry &operator=(ItemLibraryEntry &&) = default;
+ explicit ItemLibraryEntry(const Storage::Info::ItemLibraryEntry &entry);
+ ~ItemLibraryEntry();
QString name() const;
TypeName typeName() const;
- const NodeMetaInfo &metaInfo() const;
+ TypeId typeId() const;
QIcon typeIcon() const;
QString libraryEntryIconPath() const;
int majorVersion() const;
@@ -86,7 +89,7 @@ private:
using ItemLibraryEntries = QList<ItemLibraryEntry>;
QMLDESIGNERCORE_EXPORT QList<ItemLibraryEntry> toItemLibraryEntries(
- const Storage::Info::ItemLibraryEntries &entries, const ProjectStorageType &projectStorage);
+ const Storage::Info::ItemLibraryEntries &entries);
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/include/model.h b/src/plugins/qmldesigner/designercore/include/model.h
index b907e6c5d8..39b5cdaa81 100644
--- a/src/plugins/qmldesigner/designercore/include/model.h
+++ b/src/plugins/qmldesigner/designercore/include/model.h
@@ -137,7 +137,7 @@ public:
ModelPointer createModel(const TypeName &typeName,
std::unique_ptr<ModelResourceManagementInterface> resourceManagement = {});
- QUrl fileUrl() const;
+ const QUrl &fileUrl() const;
SourceId fileUrlSourceId() const;
void setFileUrl(const QUrl &url);
@@ -147,7 +147,7 @@ public:
void setMetaInfo(const MetaInfo &metaInfo);
#endif
- Module module(Utils::SmallStringView moduleName);
+ Module module(Utils::SmallStringView moduleName, Storage::ModuleKind moduleKind);
NodeMetaInfo metaInfo(const TypeName &typeName, int majorVersion = -1, int minorVersion = -1) const;
NodeMetaInfo metaInfo(Module module,
Utils::SmallStringView typeName,
@@ -166,6 +166,7 @@ public:
NodeMetaInfo qtQmlConnectionsMetaInfo() const;
NodeMetaInfo qtQmlModelsListModelMetaInfo() const;
NodeMetaInfo qtQmlModelsListElementMetaInfo() const;
+ NodeMetaInfo qtQmlXmlListModelXmlListModelRoleMetaInfo() const;
NodeMetaInfo qtQuick3DBakedLightmapMetaInfo() const;
NodeMetaInfo qtQuick3DDefaultMaterialMetaInfo() const;
NodeMetaInfo qtQuick3DDirectionalLightMetaInfo() const;
@@ -218,14 +219,17 @@ public:
// Imports:
const Imports &imports() const;
- const Imports &possibleImports() const;
- const Imports &usedImports() const;
+ Imports possibleImports() const;
+ Imports usedImports() const;
void changeImports(Imports importsToBeAdded, Imports importsToBeRemoved);
+#ifndef QDS_USE_PROJECTSTORAGE
void setPossibleImports(Imports possibleImports);
+#endif
+#ifndef QDS_USE_PROJECTSTORAGE
void setUsedImports(Imports usedImports);
+#endif
bool hasImport(const Import &import, bool ignoreAlias = true, bool allowHigherVersion = false) const;
bool isImportPossible(const Import &import, bool ignoreAlias = true, bool allowHigherVersion = false) const;
- QString pathForImport(const Import &import);
QStringList importPaths() const;
Import highestPossibleImport(const QString &importPath);
@@ -251,10 +255,7 @@ public:
bool hasId(const QString &id) const;
bool hasImport(const QString &importUrl) const;
- QString generateNewId(const QString &prefixName,
- const QString &fallbackPrefix = "element",
- std::optional<std::function<bool(const QString &)>> isDuplicate = {}) const;
- QString generateIdFromName(const QString &name, const QString &fallbackId = "element") const;
+ QString generateNewId(const QString &prefixName, const QString &fallbackPrefix = "element") const;
void startDrag(QMimeData *mimeData, const QPixmap &icon);
void endDrag();
diff --git a/src/plugins/qmldesigner/designercore/include/modelfwd.h b/src/plugins/qmldesigner/designercore/include/modelfwd.h
index 0a062289fd..91c533fe7b 100644
--- a/src/plugins/qmldesigner/designercore/include/modelfwd.h
+++ b/src/plugins/qmldesigner/designercore/include/modelfwd.h
@@ -77,7 +77,7 @@ constexpr bool useProjectStorage()
using ProjectStorageType = ProjectStorageInterface;
using PathCacheType = SourcePathCacheInterface;
#else
-using ProjectStorageType = ProjectStorage<Sqlite::Database>;
+using ProjectStorageType = ProjectStorage;
using PathCacheType = SourcePathCache<ProjectStorageType, NonLockingMutex>;
#endif
diff --git a/src/plugins/qmldesigner/designercore/include/nodehints.h b/src/plugins/qmldesigner/designercore/include/nodehints.h
index 9e67c2d99b..99470db65f 100644
--- a/src/plugins/qmldesigner/designercore/include/nodehints.h
+++ b/src/plugins/qmldesigner/designercore/include/nodehints.h
@@ -3,9 +3,11 @@
#pragma once
+#include "modelnode.h"
+#include "nodemetainfo.h"
+
#include <QList>
#include <QString>
-#include "modelnode.h"
#include "qmldesignercorelib_global.h"
#include "invalidmetainfoexception.h"
@@ -54,18 +56,19 @@ public:
QHash<QString, QString> hints() const;
static NodeHints fromModelNode(const ModelNode &modelNode);
- static NodeHints fromItemLibraryEntry(const ItemLibraryEntry &entry);
+ static NodeHints fromItemLibraryEntry(const ItemLibraryEntry &entry, Model *model);
private:
explicit NodeHints(const ModelNode &modelNode);
explicit NodeHints(const NodeMetaInfo &metaInfo);
- explicit NodeHints(const ItemLibraryEntry &entry);
+ explicit NodeHints(const ItemLibraryEntry &entry, Model *model);
const ModelNode &modelNode() const;
bool isValid() const;
Model *model() const;
bool evaluateBooleanExpression(const QString &hintName, bool defaultValue, const ModelNode potentialParent = ModelNode()) const;
ModelNode m_modelNode;
+ NodeMetaInfo m_metaInfo;
QHash<QString, QString> m_hints;
};
diff --git a/src/plugins/qmldesigner/designercore/include/nodemetainfo.h b/src/plugins/qmldesigner/designercore/include/nodemetainfo.h
index 53c755ddc8..fd3f2f9be8 100644
--- a/src/plugins/qmldesigner/designercore/include/nodemetainfo.h
+++ b/src/plugins/qmldesigner/designercore/include/nodemetainfo.h
@@ -27,9 +27,15 @@ QT_END_NAMESPACE
# define DEPRECATED_VERSION_NUMBER \
[[deprecated( \
"In most cases you don't need them anymore because the import is setting them!")]]
+# define DEPRECATED_COMPONENT_FILE_NAME [[deprecated("Use sourceId() instead.")]]
+# define DEPRECATED_IMPORT_DIRECTORY_PATH [[deprecated("Use allExportedTypeNames().")]]
+# define DEPRECATED_REQUIRED_IMPORT_STRING [[deprecated("Use allExportedTypeNames().")]]
#else
# define DEPRECATED_TYPENAME
# define DEPRECATED_VERSION_NUMBER
+# define DEPRECATED_COMPONENT_FILE_NAME
+# define DEPRECATED_IMPORT_DIRECTORY_PATH
+# define DEPRECATED_REQUIRED_IMPORT_STRING
#endif
namespace QmlDesigner {
@@ -116,7 +122,7 @@ public:
Storage::Info::ItemLibraryEntries itemLibrariesEntries() const;
SourceId sourceId() const;
- QString componentFileName() const;
+ DEPRECATED_COMPONENT_FILE_NAME QString componentFileName() const;
bool isBasedOn(const NodeMetaInfo &metaInfo) const;
bool isBasedOn(const NodeMetaInfo &metaInfo1, const NodeMetaInfo &metaInfo2) const;
@@ -167,6 +173,7 @@ public:
bool isQtMultimediaSoundEffect() const;
bool isQtObject() const;
bool isQtQmlConnections() const;
+ bool isQtQmlModelsListElement() const;
bool isQtQuick3DBakedLightmap() const;
bool isQtQuick3DBuffer() const;
bool isQtQuick3DCamera() const;
@@ -176,9 +183,9 @@ public:
bool isQtQuick3DInstanceList() const;
bool isQtQuick3DInstanceListEntry() const;
bool isQtQuick3DLight() const;
- bool isQtQuickListElement() const;
bool isQtQuickListModel() const;
bool isQtQuickListView() const;
+ bool isQtQuickGridView() const;
bool isQtQuick3DMaterial() const;
bool isQtQuick3DModel() const;
bool isQtQuick3DNode() const;
@@ -235,8 +242,8 @@ public:
bool usesCustomParser() const;
bool isEnumeration() const;
- QString importDirectoryPath() const;
- QString requiredImportString() const;
+ DEPRECATED_IMPORT_DIRECTORY_PATH QString importDirectoryPath() const;
+ DEPRECATED_REQUIRED_IMPORT_STRING QString requiredImportString() const;
friend bool operator==(const NodeMetaInfo &first, const NodeMetaInfo &second)
{
@@ -265,12 +272,14 @@ public:
private:
const Storage::Info::Type &typeData() const;
+ PropertyDeclarationId defaultPropertyDeclarationId() const;
bool isSubclassOf(const TypeName &type, int majorVersion = -1, int minorVersion = -1) const;
private:
TypeId m_typeId;
NotNullPointer<const ProjectStorageType> m_projectStorage = {};
mutable std::optional<Storage::Info::Type> m_typeData;
+ mutable std::optional<PropertyDeclarationId> m_defaultPropertyId;
std::shared_ptr<NodeMetaInfoPrivate> m_privateData;
};
diff --git a/src/plugins/qmldesigner/designercore/include/projectstorageids.h b/src/plugins/qmldesigner/designercore/include/projectstorageids.h
index bc66e0d2b2..7c2e8c4b25 100644
--- a/src/plugins/qmldesigner/designercore/include/projectstorageids.h
+++ b/src/plugins/qmldesigner/designercore/include/projectstorageids.h
@@ -7,6 +7,8 @@
#include <utils/span.h>
+#include <QVarLengthArray>
+
namespace QmlDesigner {
enum class BasicIdType {
@@ -29,6 +31,8 @@ enum class BasicIdType {
using TypeId = Sqlite::BasicId<BasicIdType::Type>;
using TypeIds = std::vector<TypeId>;
+template<std::size_t size>
+using SmallTypeIds = QVarLengthArray<TypeId, size>;
using PropertyDeclarationId = Sqlite::BasicId<BasicIdType::PropertyDeclaration>;
using PropertyDeclarationIds = std::vector<PropertyDeclarationId>;
@@ -44,9 +48,13 @@ using EnumerationDeclarationIds = std::vector<EnumerationDeclarationId>;
using SourceContextId = Sqlite::BasicId<BasicIdType::SourceContext, int>;
using SourceContextIds = std::vector<SourceContextId>;
+template<std::size_t size>
+using SmallSourceContextIds = QVarLengthArray<SourceContextId, size>;
using SourceId = Sqlite::BasicId<BasicIdType::Source, int>;
using SourceIds = std::vector<SourceId>;
+template<std::size_t size>
+using SmallSourceIds = QVarLengthArray<SourceId, size>;
using ModuleId = Sqlite::BasicId<BasicIdType::Module, int>;
using ModuleIds = std::vector<ModuleId>;
diff --git a/src/plugins/qmldesigner/designercore/include/qmlitemnode.h b/src/plugins/qmldesigner/designercore/include/qmlitemnode.h
index dde5515a5a..e11f201cdb 100644
--- a/src/plugins/qmldesigner/designercore/include/qmlitemnode.h
+++ b/src/plugins/qmldesigner/designercore/include/qmlitemnode.h
@@ -174,6 +174,7 @@ public:
ModelNode targetTransition() const;
void assignTargetFlowItem(const QmlFlowTargetNode &flowItem);
QmlFlowItemNode flowItemParent() const;
+private:
void destroyTarget();
};
diff --git a/src/plugins/qmldesigner/designercore/include/rewriterview.h b/src/plugins/qmldesigner/designercore/include/rewriterview.h
index 23841accda..92c79c7863 100644
--- a/src/plugins/qmldesigner/designercore/include/rewriterview.h
+++ b/src/plugins/qmldesigner/designercore/include/rewriterview.h
@@ -8,11 +8,11 @@
#include "documentmessage.h"
#include "rewritertransaction.h"
-#include <QScopedPointer>
#include <QTimer>
#include <QUrl>
#include <functional>
+#include <memory>
namespace QmlJS {
class Document;
@@ -123,7 +123,10 @@ public:
bool renameId(const QString& oldId, const QString& newId);
const QmlJS::Document *document() const;
+
+#ifndef QDS_USE_PROJECTSTORAGE
const QmlJS::ScopeChain *scopeChain() const;
+#endif
QString convertTypeToImportAlias(const QString &type) const;
@@ -135,8 +138,6 @@ public:
void setCheckLinkErrors(bool b) { m_checkLinkErrors = b; }
- QString pathForImport(const Import &import);
-
QStringList importDirectories() const;
QSet<QPair<QString, QString> > qrcMapping() const;
@@ -202,9 +203,9 @@ private: //variables
bool m_checkLinkErrors = true;
DifferenceHandling m_differenceHandling;
- QScopedPointer<Internal::ModelNodePositionStorage> m_positionStorage;
- QScopedPointer<Internal::ModelToTextMerger> m_modelToTextMerger;
- QScopedPointer<Internal::TextToModelMerger> m_textToModelMerger;
+ std::unique_ptr<Internal::ModelNodePositionStorage> m_positionStorage;
+ std::unique_ptr<Internal::ModelToTextMerger> m_modelToTextMerger;
+ std::unique_ptr<Internal::TextToModelMerger> m_textToModelMerger;
QList<DocumentMessage> m_errors;
QList<DocumentMessage> m_warnings;
RewriterTransaction m_removeDefaultPropertyTransaction;
diff --git a/src/plugins/qmldesigner/designercore/include/subcomponentmanager.h b/src/plugins/qmldesigner/designercore/include/subcomponentmanager.h
index 7fa2348854..a42164d1bd 100644
--- a/src/plugins/qmldesigner/designercore/include/subcomponentmanager.h
+++ b/src/plugins/qmldesigner/designercore/include/subcomponentmanager.h
@@ -7,6 +7,7 @@
# include "qmldesignercorelib_global.h"
+# include <generatedcomponentutils.h>
# include <import.h>
# include <QObject>
@@ -62,6 +63,7 @@ private: // variables
QDir m_filePathDir;
QPointer<Model> m_model;
ExternalDependenciesInterface &m_externalDependencies;
+ GeneratedComponentUtils m_componentUtils;
};
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp b/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp
index 33a100f7b2..484f18e42b 100644
--- a/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp
+++ b/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp
@@ -64,6 +64,8 @@
#include <qmlitemnode.h>
#include <rewriterview.h>
+#include <projectstorage/projectstorage.h>
+
#include <utils/hdrimage.h>
#include <coreplugin/messagemanager.h>
@@ -89,7 +91,6 @@
#include <QMultiHash>
#include <QPainter>
#include <QPicture>
-#include <QScopedPointer>
#include <QTimerEvent>
#include <QUrl>
@@ -205,22 +206,17 @@ NodeInstanceView::~NodeInstanceView()
static bool isSkippedRootNode(const ModelNode &node)
{
- static const PropertyNameList skipList({"Qt.ListModel", "QtQuick.ListModel", "Qt.ListModel", "QtQuick.ListModel"});
-
- if (skipList.contains(node.type()))
- return true;
-
- return false;
+ return node.metaInfo().isQtQuickListModel();
}
static bool isSkippedNode(const ModelNode &node)
{
- static const PropertyNameList skipList({"QtQuick.XmlRole", "Qt.XmlRole", "QtQuick.ListElement", "Qt.ListElement"});
+ auto model = node.model();
- if (skipList.contains(node.type()))
- return true;
+ auto listElement = model->qtQmlModelsListElementMetaInfo();
+ auto xmlRole = model->qtQmlXmlListModelXmlListModelRoleMetaInfo();
- return false;
+ return node.metaInfo().isBasedOn(listElement, xmlRole);
}
static bool parentTakesOverRendering(const ModelNode &modelNode)
@@ -644,7 +640,7 @@ void NodeInstanceView::auxiliaryDataChanged(const ModelNode &node,
TypeName(),
key.type};
m_nodeInstanceServer->changeAuxiliaryValues({{container}});
- };
+ }
break;
case AuxiliaryDataType::NodeInstanceAuxiliary:
@@ -656,7 +652,7 @@ void NodeInstanceView::auxiliaryDataChanged(const ModelNode &node,
TypeName(),
key.type};
m_nodeInstanceServer->changeAuxiliaryValues({{container}});
- };
+ }
break;
case AuxiliaryDataType::NodeInstancePropertyOverwrite:
@@ -991,6 +987,8 @@ QRectF NodeInstanceView::sceneRect() const
return {};
}
+namespace {
+
QList<ModelNode> filterNodesForSkipItems(const QList<ModelNode> &nodeList)
{
QList<ModelNode> filteredNodeList;
@@ -1003,14 +1001,12 @@ QList<ModelNode> filterNodesForSkipItems(const QList<ModelNode> &nodeList)
return filteredNodeList;
}
-namespace {
bool shouldSendAuxiliary(const AuxiliaryDataKey &key)
{
return key.type == AuxiliaryDataType::NodeInstancePropertyOverwrite
|| key.type == AuxiliaryDataType::NodeInstanceAuxiliary || key == invisibleProperty
|| key == lockedProperty;
}
-} // namespace
bool parentIsBehavior(ModelNode node)
{
@@ -1024,6 +1020,43 @@ bool parentIsBehavior(ModelNode node)
return false;
}
+TypeName createQualifiedTypeName(const ModelNode &node)
+{
+ if (!node)
+ return {};
+
+#ifdef QDS_USE_PROJECTSTORAGE
+ auto model = node.model();
+ auto exportedTypes = node.metaInfo().exportedTypeNamesForSourceId(model->fileUrlSourceId());
+ if (exportedTypes.size()) {
+ const auto &exportedType = exportedTypes.front();
+ using Storage::ModuleKind;
+ auto module = model->projectStorage()->module(exportedType.moduleId);
+ Utils::PathString typeName;
+ switch (module.kind) {
+ case ModuleKind::QmlLibrary:
+ typeName += module.name;
+ typeName += '/';
+ break;
+ case ModuleKind::PathLibrary:
+ break;
+ case ModuleKind::CppLibrary:
+ break;
+ }
+
+ typeName += exportedType.name;
+
+ return typeName.toQByteArray();
+ }
+
+ return {};
+#else
+ return node.type();
+#endif
+}
+
+} // namespace
+
CreateSceneCommand NodeInstanceView::createCreateSceneCommand()
{
QList<ModelNode> nodeList = allModelNodes();
@@ -1079,8 +1112,9 @@ CreateSceneCommand NodeInstanceView::createCreateSceneCommand()
nodeFlags |= InstanceContainer::ParentTakesOverRendering;
const auto modelNode = instance.modelNode();
+
InstanceContainer container(instance.instanceId(),
- modelNode.type(),
+ createQualifiedTypeName(modelNode),
modelNode.majorVersion(),
modelNode.minorVersion(),
ModelUtils::componentFilePath(modelNode),
@@ -1182,6 +1216,13 @@ CreateSceneCommand NodeInstanceView::createCreateSceneCommand()
if (stateNode.isValid() && stateNode.metaInfo().isQtQuickState())
stateInstanceId = stateNode.internalId();
+ QHash<QString, QVariantMap> sceneStates = m_edit3DToolStates[model()->fileUrl()];
+ QHash<QString, QVariantMap> projectStates = m_edit3DToolStates[
+ QUrl::fromLocalFile(m_externalDependencies.currentProjectDirPath())];
+ const QString ptsId = "@PTS";
+ if (projectStates.contains(ptsId))
+ sceneStates.insert(ptsId, projectStates[ptsId]);
+
return CreateSceneCommand(instanceContainerList,
reparentContainerList,
idContainerList,
@@ -1192,7 +1233,7 @@ CreateSceneCommand NodeInstanceView::createCreateSceneCommand()
mockupTypesVector,
model()->fileUrl(),
m_externalDependencies.currentResourcePath(),
- m_edit3DToolStates[model()->fileUrl()],
+ sceneStates,
lastUsedLanguage,
m_captureImageMinimumSize,
m_captureImageMaximumSize,
@@ -1243,7 +1284,7 @@ CreateInstancesCommand NodeInstanceView::createCreateInstancesCommand(const QLis
const auto modelNode = instance.modelNode();
InstanceContainer container(instance.instanceId(),
- modelNode.type(),
+ createQualifiedTypeName(modelNode),
modelNode.majorVersion(),
modelNode.minorVersion(),
ModelUtils::componentFilePath(modelNode),
@@ -1710,7 +1751,12 @@ void NodeInstanceView::handlePuppetToCreatorCommand(const PuppetToCreatorCommand
auto data = qvariant_cast<QVariantList>(command.data());
if (data.size() == 3) {
QString qmlId = data[0].toString();
- m_edit3DToolStates[model()->fileUrl()][qmlId].insert(data[1].toString(), data[2]);
+ QUrl mainKey;
+ if (qmlId == "@PTS") // Project tool state
+ mainKey = QUrl::fromLocalFile(m_externalDependencies.currentProjectDirPath());
+ else
+ mainKey = model()->fileUrl();
+ m_edit3DToolStates[mainKey][qmlId].insert(data[1].toString(), data[2]);
}
}
} else if (command.type() == PuppetToCreatorCommand::Render3DView) {
@@ -1824,7 +1870,7 @@ QVariant NodeInstanceView::modelNodePreviewImageDataToVariant(const ModelNodePre
placeHolder = {150, 150};
// Placeholder has transparency, but we don't want to show the checkerboard, so
// paint in the correct background color
- placeHolder.fill(Utils::creatorTheme()->color(Utils::Theme::BackgroundColorNormal));
+ placeHolder.fill(Utils::creatorColor(Utils::Theme::BackgroundColorNormal));
QPainter painter(&placeHolder);
painter.drawPixmap(0, 0, 150, 150, placeHolderSrc);
}
@@ -1850,7 +1896,7 @@ QVariant NodeInstanceView::previewImageDataForImageNode(const ModelNode &modelNo
ModelNodePreviewImageData imageData;
imageData.id = modelNode.id();
- imageData.type = QString::fromLatin1(modelNode.type());
+ imageData.type = QString::fromUtf8(createQualifiedTypeName(modelNode));
const double ratio = m_externalDependencies.formEditorDevicePixelRatio();
if (imageSource.isEmpty() && modelNode.metaInfo().isQtQuick3DTexture()) {
@@ -1923,7 +1969,7 @@ QVariant NodeInstanceView::previewImageDataForImageNode(const ModelNode &modelNo
imageData.pixmap = originalPixmap.scaled(dim, dim, Qt::KeepAspectRatio);
imageData.pixmap.setDevicePixelRatio(ratio);
imageData.time = modified;
- imageData.info = ImageUtils::imageInfo(imageSource);
+ imageData.info = ImageUtils::imageInfoString(imageSource);
m_imageDataMap.insert(imageData.id, imageData);
}
}
@@ -1958,7 +2004,7 @@ QVariant NodeInstanceView::previewImageDataForGenericNode(const ModelNode &model
if (m_imageDataMap.contains(id)) {
imageData = m_imageDataMap[id];
} else {
- imageData.type = QString::fromLatin1(modelNode.type());
+ imageData.type = QString::fromLatin1(createQualifiedTypeName(modelNode));
imageData.id = id;
m_imageDataMap.insert(id, imageData);
}
diff --git a/src/plugins/qmldesigner/designercore/metainfo/itemlibraryentry.cpp b/src/plugins/qmldesigner/designercore/metainfo/itemlibraryentry.cpp
index 806da7e7c4..2aec766002 100644
--- a/src/plugins/qmldesigner/designercore/metainfo/itemlibraryentry.cpp
+++ b/src/plugins/qmldesigner/designercore/metainfo/itemlibraryentry.cpp
@@ -22,7 +22,7 @@ class ItemLibraryEntryData
public:
QString name;
TypeName typeName;
- NodeMetaInfo metaInfo;
+ TypeId typeId;
QString category;
int majorVersion{-1};
int minorVersion{-1};
@@ -64,12 +64,12 @@ ItemLibraryEntry::ItemLibraryEntry()
: m_data(std::make_shared<Internal::ItemLibraryEntryData>())
{}
-ItemLibraryEntry::ItemLibraryEntry(const Storage::Info::ItemLibraryEntry &entry,
- const ProjectStorageType &projectStorage)
+ItemLibraryEntry::ItemLibraryEntry(const Storage::Info::ItemLibraryEntry &entry)
: ItemLibraryEntry{}
{
m_data->name = entry.name.toQString();
- m_data->metaInfo = {entry.typeId, &projectStorage};
+ m_data->typeId = entry.typeId;
+ m_data->typeName = entry.typeName.toQByteArray();
m_data->category = entry.category.toQString();
if (entry.iconPath.size())
m_data->libraryEntryIconPath = entry.iconPath.toQString();
@@ -87,6 +87,8 @@ ItemLibraryEntry::ItemLibraryEntry(const Storage::Info::ItemLibraryEntry &entry,
m_data->extraFilePaths.emplace_back(extraFilePath.toQString());
}
+ItemLibraryEntry::~ItemLibraryEntry() = default;
+
QString ItemLibraryEntry::name() const
{
return m_data->name;
@@ -97,9 +99,9 @@ TypeName ItemLibraryEntry::typeName() const
return m_data->typeName;
}
-const NodeMetaInfo &ItemLibraryEntry::metaInfo() const
+TypeId ItemLibraryEntry::typeId() const
{
- return m_data->metaInfo;
+ return m_data->typeId;
}
QString ItemLibraryEntry::qmlSource() const
@@ -245,6 +247,7 @@ QDataStream &operator<<(QDataStream &stream, const ItemLibraryEntry &itemLibrary
stream << itemLibraryEntry.m_data->qmlSource;
stream << itemLibraryEntry.m_data->customComponentSource;
stream << itemLibraryEntry.m_data->extraFilePaths;
+ stream << itemLibraryEntry.m_data->typeId.internalId();
return stream;
}
@@ -270,6 +273,9 @@ QDataStream &operator>>(QDataStream &stream, ItemLibraryEntry &itemLibraryEntry)
stream >> itemLibraryEntry.m_data->qmlSource;
stream >> itemLibraryEntry.m_data->customComponentSource;
stream >> itemLibraryEntry.m_data->extraFilePaths;
+ TypeId::DatabaseType internalTypeId;
+ stream >> internalTypeId;
+ itemLibraryEntry.m_data->typeId = TypeId::create(internalTypeId);
return stream;
}
@@ -295,11 +301,10 @@ QDebug operator<<(QDebug debug, const ItemLibraryEntry &itemLibraryEntry)
return debug.space();
}
-QList<ItemLibraryEntry> toItemLibraryEntries(const Storage::Info::ItemLibraryEntries &entries,
- const ProjectStorageType &projectStorage)
+QList<ItemLibraryEntry> toItemLibraryEntries(const Storage::Info::ItemLibraryEntries &entries)
{
return Utils::transform<QList<ItemLibraryEntry>>(entries, [&](const auto &entry) {
- return ItemLibraryEntry{entry, projectStorage};
+ return ItemLibraryEntry{entry};
});
}
diff --git a/src/plugins/qmldesigner/designercore/metainfo/metainforeader.cpp b/src/plugins/qmldesigner/designercore/metainfo/metainforeader.cpp
index af61ef6573..0addc6884d 100644
--- a/src/plugins/qmldesigner/designercore/metainfo/metainforeader.cpp
+++ b/src/plugins/qmldesigner/designercore/metainfo/metainforeader.cpp
@@ -272,7 +272,7 @@ inline QString deEscape(const QString &value)
inline QVariant deEscapeVariant(const QVariant &value)
{
- if (value.typeId() == QVariant::String)
+ if (value.typeId() == QMetaType::QString)
return deEscape(value.toString());
return value;
}
diff --git a/src/plugins/qmldesigner/designercore/metainfo/nodehints.cpp b/src/plugins/qmldesigner/designercore/metainfo/nodehints.cpp
index 32e68a3cdc..1f9a3e42bd 100644
--- a/src/plugins/qmldesigner/designercore/metainfo/nodehints.cpp
+++ b/src/plugins/qmldesigner/designercore/metainfo/nodehints.cpp
@@ -106,14 +106,15 @@ QmlDesigner::NodeHints::NodeHints(const ModelNode &node)
}
NodeHints::NodeHints(const NodeMetaInfo &metaInfo)
+ : m_metaInfo{metaInfo}
{
for (const auto &[name, expression] : metaInfo.typeHints())
m_hints.insert(name.toQString(), expression.toQString());
}
-NodeHints::NodeHints(const ItemLibraryEntry &entry)
+NodeHints::NodeHints(const ItemLibraryEntry &entry, [[maybe_unused]] Model *model)
#ifdef QDS_USE_PROJECTSTORAGE
- : NodeHints{entry.metaInfo()}
+ : NodeHints{NodeMetaInfo{entry.typeId(), model->projectStorage()}}
#endif
{
if constexpr (!useProjectStorage())
@@ -135,7 +136,7 @@ bool NodeHints::canBeContainerFor(const ModelNode &potenialChild) const
if (!isValid())
return true;
- auto flagIs = m_modelNode.metaInfo().canBeContainer();
+ auto flagIs = m_metaInfo.canBeContainer();
if (flagIs != FlagIs::Set)
return convert(flagIs);
@@ -151,7 +152,7 @@ bool NodeHints::forceClip() const
if (isSwipeView(modelNode()))
return true;
- auto flagIs = m_modelNode.metaInfo().forceClip();
+ auto flagIs = m_metaInfo.forceClip();
if (flagIs != FlagIs::Set)
return convert(flagIs);
@@ -167,7 +168,7 @@ bool NodeHints::doesLayoutChildren() const
if (isSwipeView(modelNode()))
return true;
- auto flagIs = m_modelNode.metaInfo().doesLayoutChildren();
+ auto flagIs = m_metaInfo.doesLayoutChildren();
if (flagIs != FlagIs::Set)
return convert(flagIs);
@@ -177,7 +178,7 @@ bool NodeHints::doesLayoutChildren() const
bool NodeHints::canBeDroppedInFormEditor() const
{
- auto flagIs = m_modelNode.metaInfo().canBeDroppedInFormEditor();
+ auto flagIs = m_metaInfo.canBeDroppedInFormEditor();
if (flagIs != FlagIs::Set)
return convert(flagIs);
@@ -187,7 +188,7 @@ bool NodeHints::canBeDroppedInFormEditor() const
bool NodeHints::canBeDroppedInNavigator() const
{
- auto flagIs = m_modelNode.metaInfo().canBeDroppedInNavigator();
+ auto flagIs = m_metaInfo.canBeDroppedInNavigator();
if (flagIs != FlagIs::Set)
return convert(flagIs);
@@ -197,7 +198,7 @@ bool NodeHints::canBeDroppedInNavigator() const
bool NodeHints::canBeDroppedInView3D() const
{
- auto flagIs = m_modelNode.metaInfo().canBeDroppedInView3D();
+ auto flagIs = m_metaInfo.canBeDroppedInView3D();
if (flagIs != FlagIs::Set)
return convert(flagIs);
@@ -210,7 +211,7 @@ bool NodeHints::isMovable() const
if (!isValid())
return true;
- auto flagIs = m_modelNode.metaInfo().isMovable();
+ auto flagIs = m_metaInfo.isMovable();
if (flagIs != FlagIs::Set)
return convert(flagIs);
@@ -223,7 +224,7 @@ bool NodeHints::isResizable() const
if (!isValid())
return true;
- auto flagIs = m_modelNode.metaInfo().isResizable();
+ auto flagIs = m_metaInfo.isResizable();
if (flagIs != FlagIs::Set)
return convert(flagIs);
@@ -236,7 +237,7 @@ bool NodeHints::hasFormEditorItem() const
if (!isValid())
return true;
- auto flagIs = m_modelNode.metaInfo().hasFormEditorItem();
+ auto flagIs = m_metaInfo.hasFormEditorItem();
if (flagIs != FlagIs::Set)
return convert(flagIs);
@@ -252,7 +253,7 @@ bool NodeHints::isStackedContainer() const
if (isSwipeView(modelNode()))
return true;
- auto flagIs = m_modelNode.metaInfo().isStackedContainer();
+ auto flagIs = m_metaInfo.isStackedContainer();
if (flagIs != FlagIs::Set)
return convert(flagIs);
@@ -299,7 +300,7 @@ bool NodeHints::takesOverRenderingOfChildren() const
if (!isValid())
return false;
- auto flagIs = m_modelNode.metaInfo().takesOverRenderingOfChildren();
+ auto flagIs = m_metaInfo.takesOverRenderingOfChildren();
if (flagIs != FlagIs::Set)
return convert(flagIs);
@@ -312,7 +313,7 @@ bool NodeHints::visibleInNavigator() const
if (!isValid())
return false;
- auto flagIs = m_modelNode.metaInfo().visibleInNavigator();
+ auto flagIs = m_metaInfo.visibleInNavigator();
if (flagIs != FlagIs::Set)
return convert(flagIs);
@@ -322,7 +323,7 @@ bool NodeHints::visibleInNavigator() const
bool NodeHints::visibleInLibrary() const
{
- auto flagIs = m_modelNode.metaInfo().visibleInLibrary();
+ auto flagIs = m_metaInfo.visibleInLibrary();
if (flagIs != FlagIs::Set)
return convert(flagIs);
@@ -391,9 +392,9 @@ NodeHints NodeHints::fromModelNode(const ModelNode &modelNode)
return NodeHints(modelNode);
}
-NodeHints NodeHints::fromItemLibraryEntry(const ItemLibraryEntry &entry)
+NodeHints NodeHints::fromItemLibraryEntry(const ItemLibraryEntry &entry, Model *model)
{
- return NodeHints(entry);
+ return NodeHints(entry, model);
}
const ModelNode &NodeHints::modelNode() const
diff --git a/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp b/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp
index 85f904666c..c656634272 100644
--- a/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp
+++ b/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp
@@ -53,6 +53,10 @@ NodeMetaInfo object will result in an InvalidMetaInfoException being thrown.
namespace {
+using Storage::ModuleKind;
+
+auto category = MetaInfoTracing::category;
+
struct TypeDescription
{
QString className;
@@ -919,8 +923,11 @@ const ObjectValue *NodeMetaInfoPrivate::getObjectValue() const
ContextPtr NodeMetaInfoPrivate::context() const
{
+#ifndef QDS_USE_PROJECTSTORAGE
if (m_model && m_model->rewriterView() && m_model->rewriterView()->scopeChain())
return m_model->rewriterView()->scopeChain()->context();
+#endif
+
return ContextPtr(nullptr);
}
@@ -1490,15 +1497,20 @@ MetaInfoType NodeMetaInfo::type() const
{
if constexpr (useProjectStorage()) {
if (isValid()) {
- switch (typeData().traits.kind) {
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get type"_t, category(), keyValue("type id", m_typeId)};
+ auto kind = typeData().traits.kind;
+ tracer.end(keyValue("type kind", kind));
+
+ switch (kind) {
case Storage::TypeTraitsKind::Reference:
return MetaInfoType::Reference;
case Storage::TypeTraitsKind::Value:
return MetaInfoType::Value;
case Storage::TypeTraitsKind::Sequence:
return MetaInfoType::Sequence;
- default:
- break;
+ case Storage::TypeTraitsKind::None:
+ return MetaInfoType::None;
}
}
}
@@ -1508,16 +1520,38 @@ MetaInfoType NodeMetaInfo::type() const
bool NodeMetaInfo::isFileComponent() const
{
- if constexpr (useProjectStorage())
- return isValid() && typeData().traits.isFileComponent;
- else
+ if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return {};
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is file component"_t, category(), keyValue("type id", m_typeId)};
+
+ auto isFileComponent = typeData().traits.isFileComponent;
+
+ tracer.end(keyValue("is file component", isFileComponent));
+
+ return isFileComponent;
+
+ } else {
return isValid() && m_privateData->isFileComponent();
+ }
}
bool NodeMetaInfo::isProjectComponent() const
{
if constexpr (useProjectStorage()) {
- return isValid() && typeData().traits.isProjectComponent;
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is project component"_t, category(), keyValue("type id", m_typeId)};
+
+ auto isProjectComponent = typeData().traits.isProjectComponent;
+
+ tracer.end(keyValue("is project component", isProjectComponent));
+
+ return isProjectComponent;
}
return false;
@@ -1526,7 +1560,17 @@ bool NodeMetaInfo::isProjectComponent() const
bool NodeMetaInfo::isInProjectModule() const
{
if constexpr (useProjectStorage()) {
- return isValid() && typeData().traits.isInProjectModule;
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is project module"_t, category(), keyValue("type id", m_typeId)};
+
+ auto isInProjectModule = typeData().traits.isInProjectModule;
+
+ tracer.end(keyValue("is project module", isInProjectModule));
+
+ return isInProjectModule;
}
return false;
@@ -1535,10 +1579,17 @@ bool NodeMetaInfo::isInProjectModule() const
FlagIs NodeMetaInfo::canBeContainer() const
{
if constexpr (useProjectStorage()) {
- if (isValid())
- return typeData().traits.canBeContainer;
+ if (!isValid())
+ return FlagIs::False;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"can be container"_t, category(), keyValue("type id", m_typeId)};
+
+ auto canBeContainer = typeData().traits.canBeContainer;
- return FlagIs::False;
+ tracer.end(keyValue("can be container", canBeContainer));
+
+ return canBeContainer;
}
return FlagIs::Set;
@@ -1547,10 +1598,17 @@ FlagIs NodeMetaInfo::canBeContainer() const
FlagIs NodeMetaInfo::forceClip() const
{
if constexpr (useProjectStorage()) {
- if (isValid())
- return typeData().traits.forceClip;
+ if (!isValid())
+ return FlagIs::False;
- return FlagIs::False;
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"force clip"_t, category(), keyValue("type id", m_typeId)};
+
+ auto forceClip = typeData().traits.forceClip;
+
+ tracer.end(keyValue("force clip", forceClip));
+
+ return forceClip;
}
return FlagIs::Set;
@@ -1559,10 +1617,17 @@ FlagIs NodeMetaInfo::forceClip() const
FlagIs NodeMetaInfo::doesLayoutChildren() const
{
if constexpr (useProjectStorage()) {
- if (isValid())
- return typeData().traits.doesLayoutChildren;
+ if (!isValid())
+ return FlagIs::False;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"does layout children"_t, category(), keyValue("type id", m_typeId)};
- return FlagIs::False;
+ auto doesLayoutChildren = typeData().traits.doesLayoutChildren;
+
+ tracer.end(keyValue("does layout children", doesLayoutChildren));
+
+ return doesLayoutChildren;
}
return FlagIs::Set;
@@ -1571,10 +1636,19 @@ FlagIs NodeMetaInfo::doesLayoutChildren() const
FlagIs NodeMetaInfo::canBeDroppedInFormEditor() const
{
if constexpr (useProjectStorage()) {
- if (isValid())
- return typeData().traits.canBeDroppedInFormEditor;
+ if (!isValid())
+ return FlagIs::False;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"can be dropped in form editor"_t,
+ category(),
+ keyValue("type id", m_typeId)};
- return FlagIs::False;
+ auto canBeDroppedInFormEditor = typeData().traits.canBeDroppedInFormEditor;
+
+ tracer.end(keyValue("can be dropped in form editor", canBeDroppedInFormEditor));
+
+ return canBeDroppedInFormEditor;
}
return FlagIs::Set;
@@ -1583,10 +1657,19 @@ FlagIs NodeMetaInfo::canBeDroppedInFormEditor() const
FlagIs NodeMetaInfo::canBeDroppedInNavigator() const
{
if constexpr (useProjectStorage()) {
- if (isValid())
- return typeData().traits.canBeDroppedInNavigator;
+ if (!isValid())
+ return FlagIs::False;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"can be dropped in navigator"_t,
+ category(),
+ keyValue("type id", m_typeId)};
+
+ auto canBeDroppedInNavigator = typeData().traits.canBeDroppedInNavigator;
- return FlagIs::False;
+ tracer.end(keyValue("can be dropped in navigator", canBeDroppedInNavigator));
+
+ return canBeDroppedInNavigator;
}
return FlagIs::Set;
@@ -1595,10 +1678,19 @@ FlagIs NodeMetaInfo::canBeDroppedInNavigator() const
FlagIs NodeMetaInfo::canBeDroppedInView3D() const
{
if constexpr (useProjectStorage()) {
- if (isValid())
- return typeData().traits.canBeDroppedInView3D;
+ if (!isValid())
+ return FlagIs::False;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"can be dropped in view3d"_t,
+ category(),
+ keyValue("type id", m_typeId)};
+
+ auto canBeDroppedInView3D = typeData().traits.canBeDroppedInView3D;
+
+ tracer.end(keyValue("can be dropped in view3d", canBeDroppedInView3D));
- return FlagIs::False;
+ return canBeDroppedInView3D;
}
return FlagIs::Set;
@@ -1607,10 +1699,17 @@ FlagIs NodeMetaInfo::canBeDroppedInView3D() const
FlagIs NodeMetaInfo::isMovable() const
{
if constexpr (useProjectStorage()) {
- if (isValid())
- return typeData().traits.isMovable;
+ if (!isValid())
+ return FlagIs::False;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is movable"_t, category(), keyValue("type id", m_typeId)};
- return FlagIs::False;
+ auto isMovable = typeData().traits.isMovable;
+
+ tracer.end(keyValue("is movable", isMovable));
+
+ return isMovable;
}
return FlagIs::Set;
@@ -1619,10 +1718,17 @@ FlagIs NodeMetaInfo::isMovable() const
FlagIs NodeMetaInfo::isResizable() const
{
if constexpr (useProjectStorage()) {
- if (isValid())
- return typeData().traits.isResizable;
+ if (!isValid())
+ return FlagIs::False;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is resizable"_t, category(), keyValue("type id", m_typeId)};
+
+ auto isResizable = typeData().traits.isResizable;
- return FlagIs::False;
+ tracer.end(keyValue("is resizable", isResizable));
+
+ return isResizable;
}
return FlagIs::Set;
@@ -1631,10 +1737,17 @@ FlagIs NodeMetaInfo::isResizable() const
FlagIs NodeMetaInfo::hasFormEditorItem() const
{
if constexpr (useProjectStorage()) {
- if (isValid())
- return typeData().traits.hasFormEditorItem;
+ if (!isValid())
+ return FlagIs::False;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"has form editor item"_t, category(), keyValue("type id", m_typeId)};
+
+ auto hasFormEditorItem = typeData().traits.hasFormEditorItem;
- return FlagIs::False;
+ tracer.end(keyValue("has form editor item", hasFormEditorItem));
+
+ return hasFormEditorItem;
}
return FlagIs::Set;
@@ -1643,10 +1756,17 @@ FlagIs NodeMetaInfo::hasFormEditorItem() const
FlagIs NodeMetaInfo::isStackedContainer() const
{
if constexpr (useProjectStorage()) {
- if (isValid())
- return typeData().traits.isStackedContainer;
+ if (!isValid())
+ return FlagIs::False;
- return FlagIs::False;
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is stacked container"_t, category(), keyValue("type id", m_typeId)};
+
+ auto isStackedContainer = typeData().traits.isStackedContainer;
+
+ tracer.end(keyValue("is stacked container", isStackedContainer));
+
+ return isStackedContainer;
}
return FlagIs::Set;
@@ -1655,10 +1775,19 @@ FlagIs NodeMetaInfo::isStackedContainer() const
FlagIs NodeMetaInfo::takesOverRenderingOfChildren() const
{
if constexpr (useProjectStorage()) {
- if (isValid())
- return typeData().traits.takesOverRenderingOfChildren;
+ if (!isValid())
+ return FlagIs::False;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"takes over rendering of children"_t,
+ category(),
+ keyValue("type id", m_typeId)};
- return FlagIs::False;
+ auto takesOverRenderingOfChildren = typeData().traits.takesOverRenderingOfChildren;
+
+ tracer.end(keyValue("takes over rendering of children", takesOverRenderingOfChildren));
+
+ return takesOverRenderingOfChildren;
}
return FlagIs::Set;
@@ -1667,10 +1796,17 @@ FlagIs NodeMetaInfo::takesOverRenderingOfChildren() const
FlagIs NodeMetaInfo::visibleInNavigator() const
{
if constexpr (useProjectStorage()) {
- if (isValid())
- return typeData().traits.visibleInNavigator;
+ if (!isValid())
+ return FlagIs::False;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"visible in navigator"_t, category(), keyValue("type id", m_typeId)};
+
+ auto visibleInNavigator = typeData().traits.visibleInNavigator;
- return FlagIs::False;
+ tracer.end(keyValue("visible in navigator", visibleInNavigator));
+
+ return visibleInNavigator;
}
return FlagIs::Set;
@@ -1679,10 +1815,17 @@ FlagIs NodeMetaInfo::visibleInNavigator() const
FlagIs NodeMetaInfo::visibleInLibrary() const
{
if constexpr (useProjectStorage()) {
- if (isValid())
- return typeData().traits.visibleInLibrary;
+ if (!isValid())
+ return FlagIs::False;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"visible in library"_t, category(), keyValue("type id", m_typeId)};
+
+ auto visibleInLibrary = typeData().traits.visibleInLibrary;
- return FlagIs::False;
+ tracer.end(keyValue("visible in library", visibleInLibrary));
+
+ return visibleInLibrary;
}
return FlagIs::Set;
@@ -1694,6 +1837,12 @@ namespace {
TypeId typeId,
Utils::SmallStringView propertyName)
{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get combound property id"_t,
+ category(),
+ keyValue("type id", typeId),
+ keyValue("property name", propertyName)};
+
auto begin = propertyName.begin();
const auto end = propertyName.end();
@@ -1709,11 +1858,17 @@ namespace {
if (propertyId && found != end) {
begin = std::next(found);
- return projectStorage.propertyDeclarationId(propertyTypeId, {begin, end});
+ auto id = projectStorage.propertyDeclarationId(propertyTypeId, {begin, end});
+
+ tracer.end(keyValue("property id", id));
+
+ return id;
}
}
}
+ tracer.end(keyValue("property id", propertyId));
+
return propertyId;
}
@@ -1721,10 +1876,24 @@ namespace {
bool NodeMetaInfo::hasProperty(Utils::SmallStringView propertyName) const
{
- if constexpr (useProjectStorage())
- return isValid() && bool(propertyId(*m_projectStorage, m_typeId, propertyName));
- else
+ if constexpr (useProjectStorage()) {
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"has property"_t,
+ category(),
+ keyValue("type id", m_typeId),
+ keyValue("property name", propertyName)};
+
+ if (!isValid())
+ return false;
+
+ auto hasPropertyId = bool(propertyId(*m_projectStorage, m_typeId, propertyName));
+
+ tracer.end(keyValue("has property", hasPropertyId));
+
+ return hasPropertyId;
+ } else {
return isValid() && m_privateData->properties().contains(QByteArrayView(propertyName));
+ }
}
PropertyMetaInfos NodeMetaInfo::properties() const
@@ -1733,12 +1902,14 @@ PropertyMetaInfos NodeMetaInfo::properties() const
return {};
if constexpr (useProjectStorage()) {
- if (isValid()) {
- return Utils::transform<PropertyMetaInfos>(
- m_projectStorage->propertyDeclarationIds(m_typeId), [&](auto id) {
- return PropertyMetaInfo{id, m_projectStorage};
- });
- }
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get properties"_t, category(), keyValue("type id", m_typeId)};
+
+ return Utils::transform<PropertyMetaInfos>(
+ m_projectStorage->propertyDeclarationIds(m_typeId), [&](auto id) {
+ return PropertyMetaInfo{id, m_projectStorage};
+ });
+
} else {
const auto &properties = m_privateData->properties();
@@ -1750,19 +1921,22 @@ PropertyMetaInfos NodeMetaInfo::properties() const
return propertyMetaInfos;
}
-
- return {};
}
PropertyMetaInfos NodeMetaInfo::localProperties() const
{
+ if (!isValid())
+ return {};
+
if constexpr (useProjectStorage()) {
- if (isValid()) {
- return Utils::transform<PropertyMetaInfos>(
- m_projectStorage->localPropertyDeclarationIds(m_typeId), [&](auto id) {
- return PropertyMetaInfo{id, m_projectStorage};
- });
- }
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get local properties"_t, category(), keyValue("type id", m_typeId)};
+
+ return Utils::transform<PropertyMetaInfos>(
+ m_projectStorage->localPropertyDeclarationIds(m_typeId), [&](auto id) {
+ return PropertyMetaInfo{id, m_projectStorage};
+ });
+
} else {
const auto &properties = m_privateData->localProperties();
@@ -1774,71 +1948,82 @@ PropertyMetaInfos NodeMetaInfo::localProperties() const
return propertyMetaInfos;
}
-
- return {};
}
PropertyMetaInfo NodeMetaInfo::property(const PropertyName &propertyName) const
{
+ if (!isValid())
+ return {};
+
if constexpr (useProjectStorage()) {
- if (isValid())
- return {propertyId(*m_projectStorage, m_typeId, propertyName), m_projectStorage};
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get property"_t,
+ category(),
+ keyValue("type id", m_typeId),
+ keyValue("property name", propertyName)};
+
+ return {propertyId(*m_projectStorage, m_typeId, propertyName), m_projectStorage};
} else {
if (hasProperty(propertyName)) {
return PropertyMetaInfo{m_privateData, propertyName};
}
+ return {};
}
-
- return {};
}
PropertyNameList NodeMetaInfo::signalNames() const
{
+ if (!isValid())
+ return {};
+
if constexpr (useProjectStorage()) {
- if (isValid()) {
- return Utils::transform<PropertyNameList>(m_projectStorage->signalDeclarationNames(
- m_typeId),
- [&](const auto &name) {
- return name.toQByteArray();
- });
- }
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get signal names"_t, category(), keyValue("type id", m_typeId)};
+
+ return Utils::transform<PropertyNameList>(m_projectStorage->signalDeclarationNames(m_typeId),
+ [&](const auto &name) {
+ return name.toQByteArray();
+ });
+
} else {
- if (isValid())
- return m_privateData->signalNames();
+ return m_privateData->signalNames();
}
-
- return {};
}
PropertyNameList NodeMetaInfo::slotNames() const
{
+ if (!isValid())
+ return {};
+
if constexpr (useProjectStorage()) {
- if (isValid()) {
- return Utils::transform<PropertyNameList>(m_projectStorage->functionDeclarationNames(
- m_typeId),
- [&](const auto &name) {
- return name.toQByteArray();
- });
- }
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get slot names"_t, category(), keyValue("type id", m_typeId)};
+ return Utils::transform<PropertyNameList>(m_projectStorage->functionDeclarationNames(m_typeId),
+ [&](const auto &name) {
+ return name.toQByteArray();
+ });
} else {
- if (isValid())
- return m_privateData->slotNames();
+ return m_privateData->slotNames();
}
-
- return {};
}
PropertyName NodeMetaInfo::defaultPropertyName() const
{
+ if (!isValid())
+ return {};
+
if constexpr (useProjectStorage()) {
- if (isValid()) {
- if (auto name = m_projectStorage->propertyName(typeData().defaultPropertyId)) {
- return name->toQByteArray();
- }
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get default property name"_t,
+ category(),
+ keyValue("type id", m_typeId)};
+ if (auto name = m_projectStorage->propertyName(defaultPropertyDeclarationId())) {
+ tracer.end(keyValue("default property name", name));
+ return name->toQByteArray();
}
+
} else {
- if (isValid())
- return m_privateData->defaultPropertyName();
+ return m_privateData->defaultPropertyName();
}
return {};
@@ -1846,88 +2031,128 @@ PropertyName NodeMetaInfo::defaultPropertyName() const
PropertyMetaInfo NodeMetaInfo::defaultProperty() const
{
+ if (!isValid())
+ return {};
+
if constexpr (useProjectStorage()) {
- if (isValid()) {
- return PropertyMetaInfo(typeData().defaultPropertyId, m_projectStorage);
- }
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get default property"_t, category(), keyValue("type id", m_typeId)};
+
+ auto id = defaultPropertyDeclarationId();
+
+ tracer.end(keyValue("default property id", id));
+
+ return PropertyMetaInfo(id, m_projectStorage);
} else {
return property(defaultPropertyName());
}
-
- return {};
}
bool NodeMetaInfo::hasDefaultProperty() const
{
- if constexpr (useProjectStorage())
- return isValid() && bool(typeData().defaultPropertyId);
- else
+ if (!isValid())
+ return false;
+
+ if constexpr (useProjectStorage()) {
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"has default property"_t, category(), keyValue("type id", m_typeId)};
+ auto hasDefaultProperty = bool(defaultPropertyDeclarationId());
+ tracer.end(keyValue("has default property", hasDefaultProperty));
+
+ return hasDefaultProperty;
+ } else {
return !defaultPropertyName().isEmpty();
+ }
}
std::vector<NodeMetaInfo> NodeMetaInfo::selfAndPrototypes() const
{
+ if (!isValid())
+ return {};
+
if constexpr (useProjectStorage()) {
- if (isValid()) {
- return Utils::transform<NodeMetaInfos>(
- m_projectStorage->prototypeAndSelfIds(m_typeId), [&](TypeId typeId) {
- return NodeMetaInfo{typeId, m_projectStorage};
- });
- }
- } else {
- if (isValid()) {
- NodeMetaInfos hierarchy = {*this};
- Model *model = m_privateData->model();
- for (const TypeDescription &type : m_privateData->prototypes()) {
- auto &last = hierarchy.emplace_back(model,
- type.className.toUtf8(),
- type.majorVersion,
- type.minorVersion);
- if (!last.isValid())
- hierarchy.pop_back();
- }
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get self and prototypes"_t,
+ category(),
+ keyValue("type id", m_typeId)};
- return hierarchy;
+ return Utils::transform<NodeMetaInfos>(m_projectStorage->prototypeAndSelfIds(m_typeId),
+ [&](TypeId typeId) {
+ return NodeMetaInfo{typeId, m_projectStorage};
+ });
+ } else {
+ NodeMetaInfos hierarchy = {*this};
+ Model *model = m_privateData->model();
+ for (const TypeDescription &type : m_privateData->prototypes()) {
+ auto &last = hierarchy.emplace_back(model,
+ type.className.toUtf8(),
+ type.majorVersion,
+ type.minorVersion);
+ if (!last.isValid())
+ hierarchy.pop_back();
}
- }
- return {};
+ return hierarchy;
+ }
}
NodeMetaInfos NodeMetaInfo::prototypes() const
{
+ if (!isValid())
+ return {};
+
if constexpr (useProjectStorage()) {
- if (isValid()) {
- return Utils::transform<NodeMetaInfos>(
- m_projectStorage->prototypeIds(m_typeId), [&](TypeId typeId) {
- return NodeMetaInfo{typeId, m_projectStorage};
- });
- }
- } else {
- if (isValid()) {
- NodeMetaInfos hierarchy;
- Model *model = m_privateData->model();
- for (const TypeDescription &type : m_privateData->prototypes()) {
- auto &last = hierarchy.emplace_back(model,
- type.className.toUtf8(),
- type.majorVersion,
- type.minorVersion);
- if (!last.isValid())
- hierarchy.pop_back();
- }
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get prototypes"_t, category(), keyValue("type id", m_typeId)};
+ return Utils::transform<NodeMetaInfos>(m_projectStorage->prototypeIds(m_typeId),
+ [&](TypeId typeId) {
+ return NodeMetaInfo{typeId, m_projectStorage};
+ });
- return hierarchy;
+ } else {
+ NodeMetaInfos hierarchy;
+ Model *model = m_privateData->model();
+ for (const TypeDescription &type : m_privateData->prototypes()) {
+ auto &last = hierarchy.emplace_back(model,
+ type.className.toUtf8(),
+ type.majorVersion,
+ type.minorVersion);
+ if (!last.isValid())
+ hierarchy.pop_back();
}
+
+ return hierarchy;
}
+}
- return {};
+namespace {
+template<const char *moduleName, const char *typeName, ModuleKind moduleKind = ModuleKind::QmlLibrary>
+bool isBasedOnCommonType(NotNullPointer<const ProjectStorageType> projectStorage, TypeId typeId)
+{
+ if (!typeId)
+ return false;
+
+ auto base = projectStorage->commonTypeId<moduleName, typeName, moduleKind>();
+
+ return projectStorage->isBasedOn(typeId, base);
}
+} // namespace
bool NodeMetaInfo::defaultPropertyIsComponent() const
{
- if (hasDefaultProperty())
- return defaultProperty().propertyType().isQmlComponent();
+ if (!isValid())
+ return false;
- return false;
+ if (useProjectStorage()) {
+ auto id = defaultPropertyDeclarationId();
+ auto propertyDeclaration = m_projectStorage->propertyDeclaration(id);
+
+ using namespace Storage::Info;
+ return isBasedOnCommonType<QML, Component>(m_projectStorage, propertyDeclaration->typeId);
+ } else {
+ if (hasDefaultProperty())
+ return defaultProperty().propertyType().isQmlComponent();
+ return false;
+ }
}
TypeName NodeMetaInfo::displayName() const
@@ -1973,10 +2198,16 @@ int NodeMetaInfo::minorVersion() const
Storage::Info::ExportedTypeNames NodeMetaInfo::allExportedTypeNames() const
{
+ if (!isValid())
+ return {};
+
if constexpr (useProjectStorage()) {
- if (isValid()) {
- return m_projectStorage->exportedTypeNames(m_typeId);
- }
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get all exported type names"_t,
+ category(),
+ keyValue("type id", m_typeId)};
+
+ return m_projectStorage->exportedTypeNames(m_typeId);
}
return {};
@@ -1984,10 +2215,17 @@ Storage::Info::ExportedTypeNames NodeMetaInfo::allExportedTypeNames() const
Storage::Info::ExportedTypeNames NodeMetaInfo::exportedTypeNamesForSourceId(SourceId sourceId) const
{
+ if (!isValid())
+ return {};
+
if constexpr (useProjectStorage()) {
- if (isValid()) {
- return m_projectStorage->exportedTypeNames(m_typeId, sourceId);
- }
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get exported type names for source id"_t,
+ category(),
+ keyValue("type id", m_typeId),
+ keyValue("source id", sourceId)};
+
+ return m_projectStorage->exportedTypeNames(m_typeId, sourceId);
}
return {};
@@ -1995,9 +2233,18 @@ Storage::Info::ExportedTypeNames NodeMetaInfo::exportedTypeNamesForSourceId(Sour
Storage::Info::TypeHints NodeMetaInfo::typeHints() const
{
+ if (!isValid())
+ return {};
+
if constexpr (useProjectStorage()) {
- if (isValid())
- return m_projectStorage->typeHints(m_typeId);
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get type hints"_t, category(), keyValue("type id", m_typeId)};
+
+ auto hints = m_projectStorage->typeHints(m_typeId);
+
+ tracer.end(keyValue("type hints", hints));
+
+ return hints;
}
return {};
@@ -2005,9 +2252,18 @@ Storage::Info::TypeHints NodeMetaInfo::typeHints() const
Utils::PathString NodeMetaInfo::iconPath() const
{
+ if (!isValid())
+ return {};
+
if constexpr (useProjectStorage()) {
- if (isValid())
- return m_projectStorage->typeIconPath(m_typeId);
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get icon path"_t, category(), keyValue("type id", m_typeId)};
+
+ auto iconPath = m_projectStorage->typeIconPath(m_typeId);
+
+ tracer.end(keyValue("icon path", iconPath));
+
+ return iconPath;
}
return {};
@@ -2015,9 +2271,20 @@ Utils::PathString NodeMetaInfo::iconPath() const
Storage::Info::ItemLibraryEntries NodeMetaInfo::itemLibrariesEntries() const
{
+ if (!isValid())
+ return {};
+
if constexpr (useProjectStorage()) {
- if (isValid())
- return m_projectStorage->itemLibraryEntries(m_typeId);
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get item library entries"_t,
+ category(),
+ keyValue("type id", m_typeId)};
+
+ auto entries = m_projectStorage->itemLibraryEntries(m_typeId);
+
+ tracer.end(keyValue("item library entries", entries));
+
+ return entries;
}
return {};
@@ -2025,10 +2292,18 @@ Storage::Info::ItemLibraryEntries NodeMetaInfo::itemLibrariesEntries() const
SourceId NodeMetaInfo::sourceId() const
{
+ if (!isValid())
+ return SourceId{};
+
if constexpr (useProjectStorage()) {
- if (isValid()) {
- return typeData().sourceId;
- }
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get source id"_t, category(), keyValue("type id", m_typeId)};
+
+ auto id = typeData().sourceId;
+
+ tracer.end(keyValue("source id", id));
+
+ return id;
}
return SourceId{};
@@ -2061,18 +2336,31 @@ QString NodeMetaInfo::requiredImportString() const
if (!isValid())
return {};
- Import imp = m_privateData->requiredImport();
- if (!imp.isEmpty())
- return imp.toImportString();
+ if constexpr (!useProjectStorage()) {
+ Import imp = m_privateData->requiredImport();
+ if (!imp.isEmpty())
+ return imp.toImportString();
+ }
return {};
}
SourceId NodeMetaInfo::propertyEditorPathId() const
{
+ if (!isValid())
+ return SourceId{};
+
if (useProjectStorage()) {
- if (isValid())
- return m_projectStorage->propertyEditorPathId(m_typeId);
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get property editor path id"_t,
+ category(),
+ keyValue("type id", m_typeId)};
+
+ auto id = m_projectStorage->propertyEditorPathId(m_typeId);
+
+ tracer.end(keyValue("property editor path id", id));
+
+ return id;
}
return SourceId{};
@@ -2086,6 +2374,14 @@ const Storage::Info::Type &NodeMetaInfo::typeData() const
return *m_typeData;
}
+PropertyDeclarationId NodeMetaInfo::defaultPropertyDeclarationId() const
+{
+ if (!m_defaultPropertyId)
+ m_defaultPropertyId.emplace(m_projectStorage->defaultPropertyDeclarationId(m_typeId));
+
+ return *m_defaultPropertyId;
+}
+
bool NodeMetaInfo::isSubclassOf(const TypeName &type, int majorVersion, int minorVersion) const
{
if (!isValid()) {
@@ -2122,9 +2418,13 @@ bool NodeMetaInfo::isSubclassOf(const TypeName &type, int majorVersion, int mino
bool NodeMetaInfo::isSuitableForMouseAreaFill() const
{
if constexpr (useProjectStorage()) {
- if (!isValid()) {
+ if (!isValid())
return false;
- }
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is suitable for mouse area fill"_t,
+ category(),
+ keyValue("type id", m_typeId)};
using namespace Storage::Info;
auto itemId = m_projectStorage->commonTypeId<QtQuick, Item>();
@@ -2132,11 +2432,16 @@ bool NodeMetaInfo::isSuitableForMouseAreaFill() const
auto controlsControlId = m_projectStorage->commonTypeId<QtQuick_Controls, Control>();
auto templatesControlId = m_projectStorage->commonTypeId<QtQuick_Templates, Control>();
- return m_projectStorage->isBasedOn(m_typeId,
- itemId,
- mouseAreaId,
- controlsControlId,
- templatesControlId);
+ auto isSuitableForMouseAreaFill = m_projectStorage->isBasedOn(m_typeId,
+ itemId,
+ mouseAreaId,
+ controlsControlId,
+ templatesControlId);
+
+ tracer.end(keyValue("is suitable for mouse area fill", isSuitableForMouseAreaFill));
+
+ return isSuitableForMouseAreaFill;
+
} else {
return isSubclassOf("QtQuick.Item") && !isSubclassOf("QtQuick.MouseArea")
&& !isSubclassOf("QtQuick.Controls.Control")
@@ -2147,6 +2452,15 @@ bool NodeMetaInfo::isSuitableForMouseAreaFill() const
bool NodeMetaInfo::isBasedOn(const NodeMetaInfo &metaInfo) const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is based on"_t,
+ category(),
+ keyValue("type id", m_typeId),
+ keyValue("meta info type id", metaInfo.m_typeId)};
+
return m_projectStorage->isBasedOn(m_typeId, metaInfo.m_typeId);
} else {
if (!isValid())
@@ -2160,6 +2474,12 @@ bool NodeMetaInfo::isBasedOn(const NodeMetaInfo &metaInfo) const
bool NodeMetaInfo::isBasedOn(const NodeMetaInfo &metaInfo1, const NodeMetaInfo &metaInfo2) const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is based on"_t, category(), keyValue("type id", m_typeId)};
+
return m_projectStorage->isBasedOn(m_typeId, metaInfo1.m_typeId, metaInfo2.m_typeId);
} else {
if (!isValid())
@@ -2178,6 +2498,12 @@ bool NodeMetaInfo::isBasedOn(const NodeMetaInfo &metaInfo1,
const NodeMetaInfo &metaInfo3) const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is based on"_t, category(), keyValue("type id", m_typeId)};
+
return m_projectStorage->isBasedOn(m_typeId,
metaInfo1.m_typeId,
metaInfo2.m_typeId,
@@ -2202,6 +2528,12 @@ bool NodeMetaInfo::isBasedOn(const NodeMetaInfo &metaInfo1,
const NodeMetaInfo &metaInfo4) const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is based on"_t, category(), keyValue("type id", m_typeId)};
+
return m_projectStorage->isBasedOn(m_typeId,
metaInfo1.m_typeId,
metaInfo2.m_typeId,
@@ -2229,6 +2561,12 @@ bool NodeMetaInfo::isBasedOn(const NodeMetaInfo &metaInfo1,
const NodeMetaInfo &metaInfo5) const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is based on"_t, category(), keyValue("type id", m_typeId)};
+
return m_projectStorage->isBasedOn(m_typeId,
metaInfo1.m_typeId,
metaInfo2.m_typeId,
@@ -2261,6 +2599,12 @@ bool NodeMetaInfo::isBasedOn(const NodeMetaInfo &metaInfo1,
const NodeMetaInfo &metaInfo6) const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is based on"_t, category(), keyValue("type id", m_typeId)};
+
return m_projectStorage->isBasedOn(m_typeId,
metaInfo1.m_typeId,
metaInfo2.m_typeId,
@@ -2298,6 +2642,12 @@ bool NodeMetaInfo::isBasedOn(const NodeMetaInfo &metaInfo1,
const NodeMetaInfo &metaInfo7) const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is based on"_t, category(), keyValue("type id", m_typeId)};
+
return m_projectStorage->isBasedOn(m_typeId,
metaInfo1.m_typeId,
metaInfo2.m_typeId,
@@ -2330,26 +2680,14 @@ bool NodeMetaInfo::isBasedOn(const NodeMetaInfo &metaInfo1,
}
}
-namespace {
-template<const char *moduleName, const char *typeName>
-bool isBasedOnCommonType(NotNullPointer<const ProjectStorageType> projectStorage, TypeId typeId)
-{
- if (!typeId) {
- return false;
- }
-
- auto base = projectStorage->commonTypeId<moduleName, typeName>();
-
- return projectStorage->isBasedOn(typeId, base);
-}
-} // namespace
-
bool NodeMetaInfo::isGraphicalItem() const
{
if constexpr (useProjectStorage()) {
- if (!isValid()) {
+ if (!isValid())
return false;
- }
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is graphical item"_t, category(), keyValue("type id", m_typeId)};
using namespace Storage::Info;
auto itemId = m_projectStorage->commonTypeId<QtQuick, Item>();
@@ -2369,6 +2707,12 @@ bool NodeMetaInfo::isGraphicalItem() const
bool NodeMetaInfo::isQtObject() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is Qt object"_t, category(), keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
return isBasedOnCommonType<QML, QtObject>(m_projectStorage, m_typeId);
} else {
@@ -2379,6 +2723,14 @@ bool NodeMetaInfo::isQtObject() const
bool NodeMetaInfo::isQtQmlConnections() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is Qt Qml connections"_t,
+ category(),
+ keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
return isBasedOnCommonType<QtQml, Connections>(m_projectStorage, m_typeId);
} else {
@@ -2389,9 +2741,11 @@ bool NodeMetaInfo::isQtQmlConnections() const
bool NodeMetaInfo::isLayoutable() const
{
if constexpr (useProjectStorage()) {
- if (!isValid()) {
+ if (!isValid())
return false;
- }
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is layoutable"_t, category(), keyValue("type id", m_typeId)};
using namespace Storage::Info;
auto positionerId = m_projectStorage->commonTypeId<QtQuick, Positioner>();
@@ -2410,6 +2764,14 @@ bool NodeMetaInfo::isLayoutable() const
bool NodeMetaInfo::isQtQuickLayoutsLayout() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is QtQuick.Layouts.Layout"_t,
+ category(),
+ keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
return isBasedOnCommonType<QtQuick_Layouts, Layout>(m_projectStorage, m_typeId);
} else {
@@ -2420,9 +2782,11 @@ bool NodeMetaInfo::isQtQuickLayoutsLayout() const
bool NodeMetaInfo::isView() const
{
if constexpr (useProjectStorage()) {
- if (!isValid()) {
+ if (!isValid())
return false;
- }
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is view"_t, category(), keyValue("type id", m_typeId)};
using namespace Storage::Info;
auto listViewId = m_projectStorage->commonTypeId<QtQuick, ListView>();
@@ -2439,17 +2803,20 @@ bool NodeMetaInfo::isView() const
bool NodeMetaInfo::usesCustomParser() const
{
if constexpr (useProjectStorage()) {
- return isValid() && typeData().traits.usesCustomParser;
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"uses custom parser"_t, category(), keyValue("type id", m_typeId)};
+
+ return typeData().traits.usesCustomParser;
} else {
if (!isValid())
return false;
- auto type = typeName();
- return type == "QtQuick.VisualItemModel" || type == "Qt.VisualItemModel"
- || type == "QtQuick.VisualDataModel" || type == "Qt.VisualDataModel"
- || type == "QtQuick.ListModel" || type == "Qt.ListModel"
- || type == "QtQml.Models.ListModel" || type == "QtQuick.XmlListModel"
- || type == "Qt.XmlListModel" || type == "QtQml.XmlListModel.XmlListModel";
+ auto type = simplifiedTypeName();
+ return type == "VisualItemModel" || type == "VisualDataModel" || type == "ListModel"
+ || type == "XmlListModel";
}
}
@@ -2468,8 +2835,14 @@ bool isTypeId(TypeId typeId, TypeIds... otherTypeIds)
bool NodeMetaInfo::isVector2D() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is vector2d"_t, category(), keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
- return isValid() && isTypeId(m_typeId, m_projectStorage->commonTypeId<QtQuick, vector2d>());
+ return isTypeId(m_typeId, m_projectStorage->commonTypeId<QtQuick, vector2d>());
} else {
if (!m_privateData)
return false;
@@ -2483,8 +2856,14 @@ bool NodeMetaInfo::isVector2D() const
bool NodeMetaInfo::isVector3D() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is vector3d"_t, category(), keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
- return isValid() && isTypeId(m_typeId, m_projectStorage->commonTypeId<QtQuick, vector3d>());
+ return isTypeId(m_typeId, m_projectStorage->commonTypeId<QtQuick, vector3d>());
} else {
if (!m_privateData)
return false;
@@ -2498,8 +2877,14 @@ bool NodeMetaInfo::isVector3D() const
bool NodeMetaInfo::isVector4D() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is vector4d"_t, category(), keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
- return isValid() && isTypeId(m_typeId, m_projectStorage->commonTypeId<QtQuick, vector4d>());
+ return isTypeId(m_typeId, m_projectStorage->commonTypeId<QtQuick, vector4d>());
} else {
if (!m_privateData)
return false;
@@ -2513,6 +2898,14 @@ bool NodeMetaInfo::isVector4D() const
bool NodeMetaInfo::isQtQuickPropertyChanges() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is QtQuick.PropertyChanges"_t,
+ category(),
+ keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
return isBasedOnCommonType<QtQuick, Storage::Info::PropertyChanges>(m_projectStorage,
m_typeId);
@@ -2524,6 +2917,14 @@ bool NodeMetaInfo::isQtQuickPropertyChanges() const
bool NodeMetaInfo::isQtSafeRendererSafeRendererPicture() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is Qt.SafeRenderer.SafeRendererPicture"_t,
+ category(),
+ keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
return isBasedOnCommonType<Qt_SafeRenderer, SafeRendererPicture>(m_projectStorage, m_typeId);
} else {
@@ -2534,6 +2935,14 @@ bool NodeMetaInfo::isQtSafeRendererSafeRendererPicture() const
bool NodeMetaInfo::isQtSafeRendererSafePicture() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is Qt.SafeRenderer.SafePicture"_t,
+ category(),
+ keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
return isBasedOnCommonType<Qt_SafeRenderer, SafePicture>(m_projectStorage, m_typeId);
} else {
@@ -2544,6 +2953,14 @@ bool NodeMetaInfo::isQtSafeRendererSafePicture() const
bool NodeMetaInfo::isQtQuickTimelineKeyframe() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is QtQuick.Timeline.Keyframe"_t,
+ category(),
+ keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
return isBasedOnCommonType<QtQuick_Timeline, Keyframe>(m_projectStorage, m_typeId);
@@ -2555,6 +2972,14 @@ bool NodeMetaInfo::isQtQuickTimelineKeyframe() const
bool NodeMetaInfo::isQtQuickTimelineTimelineAnimation() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is QtQuick.Timeline.TimelineAnimation"_t,
+ category(),
+ keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
return isBasedOnCommonType<QtQuick_Timeline, TimelineAnimation>(m_projectStorage, m_typeId);
} else {
@@ -2565,6 +2990,14 @@ bool NodeMetaInfo::isQtQuickTimelineTimelineAnimation() const
bool NodeMetaInfo::isQtQuickTimelineTimeline() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is QtQuick.Timeline.Timeline"_t,
+ category(),
+ keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
return isBasedOnCommonType<QtQuick_Timeline, Timeline>(m_projectStorage, m_typeId);
} else {
@@ -2575,6 +3008,14 @@ bool NodeMetaInfo::isQtQuickTimelineTimeline() const
bool NodeMetaInfo::isQtQuickTimelineKeyframeGroup() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is QtQuick.Timeline.KeyframeGroup"_t,
+ category(),
+ keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
return isBasedOnCommonType<QtQuick_Timeline, KeyframeGroup>(m_projectStorage, m_typeId);
} else {
@@ -2585,9 +3026,11 @@ bool NodeMetaInfo::isQtQuickTimelineKeyframeGroup() const
bool NodeMetaInfo::isListOrGridView() const
{
if constexpr (useProjectStorage()) {
- if (!isValid()) {
+ if (!isValid())
return false;
- }
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is list or grid view"_t, category(), keyValue("type id", m_typeId)};
using namespace Storage::Info;
auto listViewId = m_projectStorage->commonTypeId<QtQuick, ListView>();
@@ -2601,9 +3044,11 @@ bool NodeMetaInfo::isListOrGridView() const
bool NodeMetaInfo::isNumber() const
{
if constexpr (useProjectStorage()) {
- if (!isValid()) {
+ if (!isValid())
return false;
- }
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is number"_t, category(), keyValue("type id", m_typeId)};
using namespace Storage::Info;
auto intId = m_projectStorage->builtinTypeId<int>();
@@ -2624,6 +3069,14 @@ bool NodeMetaInfo::isNumber() const
bool NodeMetaInfo::isQtQuickExtrasPicture() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is QtQuick.Extras.Picture"_t,
+ category(),
+ keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
return isBasedOnCommonType<QtQuick_Extras, Picture>(m_projectStorage, m_typeId);
} else {
@@ -2634,6 +3087,12 @@ bool NodeMetaInfo::isQtQuickExtrasPicture() const
bool NodeMetaInfo::isQtQuickImage() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is QtQuick.Image"_t, category(), keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
return isBasedOnCommonType<QtQuick, Image>(m_projectStorage, m_typeId);
@@ -2645,6 +3104,14 @@ bool NodeMetaInfo::isQtQuickImage() const
bool NodeMetaInfo::isQtQuickBorderImage() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is QtQuick.BorderImage"_t,
+ category(),
+ keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
return isBasedOnCommonType<QtQuick, BorderImage>(m_projectStorage, m_typeId);
@@ -2656,7 +3123,13 @@ bool NodeMetaInfo::isQtQuickBorderImage() const
bool NodeMetaInfo::isAlias() const
{
if constexpr (useProjectStorage()) {
- return false; // there is no type alias
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is alias"_t, category(), keyValue("type id", m_typeId)};
+
+ return false; // all types are already resolved
} else {
return isValid() && m_privateData->qualfiedTypeName() == "alias";
}
@@ -2665,6 +3138,14 @@ bool NodeMetaInfo::isAlias() const
bool NodeMetaInfo::isQtQuickPositioner() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is QtQuick.Positioner"_t,
+ category(),
+ keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
return isBasedOnCommonType<QtQuick, Positioner>(m_projectStorage, m_typeId);
@@ -2676,6 +3157,14 @@ bool NodeMetaInfo::isQtQuickPositioner() const
bool NodeMetaInfo::isQtQuickPropertyAnimation() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is QtQuick.PropertyAnimation"_t,
+ category(),
+ keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
return isBasedOnCommonType<QtQuick, PropertyAnimation>(m_projectStorage, m_typeId);
} else {
@@ -2686,6 +3175,12 @@ bool NodeMetaInfo::isQtQuickPropertyAnimation() const
bool NodeMetaInfo::isQtQuickRepeater() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is QtQuick.Repeater"_t, category(), keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
return isBasedOnCommonType<QtQuick, Repeater>(m_projectStorage, m_typeId);
} else {
@@ -2696,6 +3191,14 @@ bool NodeMetaInfo::isQtQuickRepeater() const
bool NodeMetaInfo::isQtQuickControlsTabBar() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is QtQuick.Controls.TabBar"_t,
+ category(),
+ keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
return isBasedOnCommonType<QtQuick_Controls, TabBar>(m_projectStorage, m_typeId);
} else {
@@ -2706,6 +3209,14 @@ bool NodeMetaInfo::isQtQuickControlsTabBar() const
bool NodeMetaInfo::isQtQuickControlsSwipeView() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is QtQuick.Controls.SwipeView"_t,
+ category(),
+ keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
return isBasedOnCommonType<QtQuick_Controls, SwipeView>(m_projectStorage, m_typeId);
} else {
@@ -2716,6 +3227,12 @@ bool NodeMetaInfo::isQtQuickControlsSwipeView() const
bool NodeMetaInfo::isQtQuick3DCamera() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is QtQuick3D.Camera"_t, category(), keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
return isBasedOnCommonType<QtQuick3D, Camera>(m_projectStorage, m_typeId);
} else {
@@ -2726,6 +3243,14 @@ bool NodeMetaInfo::isQtQuick3DCamera() const
bool NodeMetaInfo::isQtQuick3DBakedLightmap() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is QtQuick3D.BakedLightmap"_t,
+ category(),
+ keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
return isBasedOnCommonType<QtQuick3D, BakedLightmap>(m_projectStorage, m_typeId);
} else {
@@ -2736,6 +3261,12 @@ bool NodeMetaInfo::isQtQuick3DBakedLightmap() const
bool NodeMetaInfo::isQtQuick3DBuffer() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is QtQuick3D.Buffer"_t, category(), keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
return isBasedOnCommonType<QtQuick3D, Buffer>(m_projectStorage, m_typeId);
} else {
@@ -2746,6 +3277,14 @@ bool NodeMetaInfo::isQtQuick3DBuffer() const
bool NodeMetaInfo::isQtQuick3DInstanceListEntry() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is QtQuick3D.InstanceListEntry"_t,
+ category(),
+ keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
return isBasedOnCommonType<QtQuick3D, InstanceListEntry>(m_projectStorage, m_typeId);
} else {
@@ -2756,6 +3295,12 @@ bool NodeMetaInfo::isQtQuick3DInstanceListEntry() const
bool NodeMetaInfo::isQtQuick3DLight() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is QtQuick3D.Light"_t, category(), keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
return isBasedOnCommonType<QtQuick3D, Light>(m_projectStorage, m_typeId);
} else {
@@ -2763,9 +3308,17 @@ bool NodeMetaInfo::isQtQuick3DLight() const
}
}
-bool NodeMetaInfo::isQtQuickListElement() const
+bool NodeMetaInfo::isQtQmlModelsListElement() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is QtQml.Models.ListElement"_t,
+ category(),
+ keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
return isBasedOnCommonType<QtQml_Models, ListElement>(m_projectStorage, m_typeId);
} else {
@@ -2776,6 +3329,12 @@ bool NodeMetaInfo::isQtQuickListElement() const
bool NodeMetaInfo::isQtQuickListModel() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is QtQuick.ListModel"_t, category(), keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
return isBasedOnCommonType<QtQml_Models, ListModel>(m_projectStorage, m_typeId);
} else {
@@ -2786,6 +3345,12 @@ bool NodeMetaInfo::isQtQuickListModel() const
bool NodeMetaInfo::isQtQuickListView() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is QtQuick.ListView"_t, category(), keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
return isBasedOnCommonType<QtQuick, ListView>(m_projectStorage, m_typeId);
} else {
@@ -2793,9 +3358,33 @@ bool NodeMetaInfo::isQtQuickListView() const
}
}
+bool QmlDesigner::NodeMetaInfo::isQtQuickGridView() const
+{
+ if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is QtQuick.GridView"_t, category(), keyValue("type id", m_typeId)};
+
+ using namespace Storage::Info;
+ return isBasedOnCommonType<QtQuick, GridView>(m_projectStorage, m_typeId);
+ } else {
+ return isValid() && (isSubclassOf("QtQuick.GridView"));
+ }
+}
+
bool NodeMetaInfo::isQtQuick3DInstanceList() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is QtQuick3D.InstanceList"_t,
+ category(),
+ keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
return isBasedOnCommonType<QtQuick3D, InstanceList>(m_projectStorage, m_typeId);
} else {
@@ -2806,6 +3395,14 @@ bool NodeMetaInfo::isQtQuick3DInstanceList() const
bool NodeMetaInfo::isQtQuick3DParticles3DParticle3D() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is QtQuick3D.Particles3D.Particle3D"_t,
+ category(),
+ keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
return isBasedOnCommonType<QtQuick3D_Particles3D, Particle3D>(m_projectStorage, m_typeId);
} else {
@@ -2816,6 +3413,14 @@ bool NodeMetaInfo::isQtQuick3DParticles3DParticle3D() const
bool NodeMetaInfo::isQtQuick3DParticles3DParticleEmitter3D() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is QtQuick3D.Particles3D.ParticleEmitter3D"_t,
+ category(),
+ keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
return isBasedOnCommonType<QtQuick3D_Particles3D, ParticleEmitter3D>(m_projectStorage,
m_typeId);
@@ -2827,6 +3432,14 @@ bool NodeMetaInfo::isQtQuick3DParticles3DParticleEmitter3D() const
bool NodeMetaInfo::isQtQuick3DParticles3DAttractor3D() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is QtQuick3D.Particles3D.Attractor3D"_t,
+ category(),
+ keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
return isBasedOnCommonType<QtQuick3D_Particles3D, Attractor3D>(m_projectStorage, m_typeId);
} else {
@@ -2837,8 +3450,16 @@ bool NodeMetaInfo::isQtQuick3DParticles3DAttractor3D() const
bool NodeMetaInfo::isQtQuick3DParticlesAbstractShape() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is QtQuick3D.Particles3D.AbstractShape"_t,
+ category(),
+ keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
- return isBasedOnCommonType<QtQuick3D_Particles3D_cppnative, QQuick3DParticleAbstractShape>(
+ return isBasedOnCommonType<QtQuick3D_Particles3D, QQuick3DParticleAbstractShape, ModuleKind::CppLibrary>(
m_projectStorage, m_typeId);
} else {
return isValid() && isSubclassOf("QQuick3DParticleAbstractShape");
@@ -2848,6 +3469,12 @@ bool NodeMetaInfo::isQtQuick3DParticlesAbstractShape() const
bool NodeMetaInfo::isQtQuickItem() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is QtQuick.Item"_t, category(), keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
return isBasedOnCommonType<QtQuick, Item>(m_projectStorage, m_typeId);
} else {
@@ -2858,6 +3485,12 @@ bool NodeMetaInfo::isQtQuickItem() const
bool NodeMetaInfo::isQtQuickPath() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is QtQuick.Path"_t, category(), keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
return isBasedOnCommonType<QtQuick, Path>(m_projectStorage, m_typeId);
} else {
@@ -2868,6 +3501,14 @@ bool NodeMetaInfo::isQtQuickPath() const
bool NodeMetaInfo::isQtQuickPauseAnimation() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is QtQuick.PauseAnimation"_t,
+ category(),
+ keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
return isBasedOnCommonType<QtQuick, PauseAnimation>(m_projectStorage, m_typeId);
} else {
@@ -2878,6 +3519,14 @@ bool NodeMetaInfo::isQtQuickPauseAnimation() const
bool NodeMetaInfo::isQtQuickTransition() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is QtQuick.Transition"_t,
+ category(),
+ keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
return isBasedOnCommonType<QtQuick, Transition>(m_projectStorage, m_typeId);
} else {
@@ -2888,6 +3537,14 @@ bool NodeMetaInfo::isQtQuickTransition() const
bool NodeMetaInfo::isQtQuickWindowWindow() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is QtQuick.Window.Window"_t,
+ category(),
+ keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
return isBasedOnCommonType<QtQuick_Window, Window>(m_projectStorage, m_typeId);
} else {
@@ -2898,6 +3555,12 @@ bool NodeMetaInfo::isQtQuickWindowWindow() const
bool NodeMetaInfo::isQtQuickLoader() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is QtQuick.Loader"_t, category(), keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
return isBasedOnCommonType<QtQuick, Loader>(m_projectStorage, m_typeId);
} else {
@@ -2908,6 +3571,12 @@ bool NodeMetaInfo::isQtQuickLoader() const
bool NodeMetaInfo::isQtQuickState() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is QtQuick.State"_t, category(), keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
return isBasedOnCommonType<QtQuick, State>(m_projectStorage, m_typeId);
} else {
@@ -2918,9 +3587,17 @@ bool NodeMetaInfo::isQtQuickState() const
bool NodeMetaInfo::isQtQuickStateOperation() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is QtQuick.StateOperation"_t,
+ category(),
+ keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
- return isBasedOnCommonType<QtQuick_cppnative, QQuickStateOperation>(m_projectStorage,
- m_typeId);
+ return isBasedOnCommonType<QtQuick, QQuickStateOperation, ModuleKind::CppLibrary>(m_projectStorage,
+ m_typeId);
} else {
return isValid() && isSubclassOf("<cpp>.QQuickStateOperation");
}
@@ -2929,6 +3606,12 @@ bool NodeMetaInfo::isQtQuickStateOperation() const
bool NodeMetaInfo::isQtQuickText() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is QtQuick.Text"_t, category(), keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
return isBasedOnCommonType<QtQuick, Text>(m_projectStorage, m_typeId);
} else {
@@ -2939,6 +3622,14 @@ bool NodeMetaInfo::isQtQuickText() const
bool NodeMetaInfo::isQtMultimediaSoundEffect() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is QtMultimedia.SoundEffect"_t,
+ category(),
+ keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
return isBasedOnCommonType<QtMultimedia, SoundEffect>(m_projectStorage, m_typeId);
} else {
@@ -2949,9 +3640,11 @@ bool NodeMetaInfo::isQtMultimediaSoundEffect() const
bool NodeMetaInfo::isFlowViewItem() const
{
if constexpr (useProjectStorage()) {
- if (!isValid()) {
+ if (!isValid())
return false;
- }
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is FlowView.ViewItem"_t, category(), keyValue("type id", m_typeId)};
using namespace Storage::Info;
auto flowItemId = m_projectStorage->commonTypeId<FlowView, FlowItem>();
@@ -2968,6 +3661,12 @@ bool NodeMetaInfo::isFlowViewItem() const
bool NodeMetaInfo::isFlowViewFlowItem() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is FlowView.FlowItem"_t, category(), keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
return isBasedOnCommonType<FlowView, FlowItem>(m_projectStorage, m_typeId);
} else {
@@ -2978,6 +3677,12 @@ bool NodeMetaInfo::isFlowViewFlowItem() const
bool NodeMetaInfo::isFlowViewFlowView() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is FlowView.FlowView"_t, category(), keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
return isBasedOnCommonType<FlowView, FlowView>(m_projectStorage, m_typeId);
} else {
@@ -2998,6 +3703,14 @@ bool NodeMetaInfo::isFlowViewFlowActionArea() const
bool NodeMetaInfo::isFlowViewFlowTransition() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is FlowView.FlowTransition"_t,
+ category(),
+ keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
return isBasedOnCommonType<FlowView, FlowTransition>(m_projectStorage, m_typeId);
} else {
@@ -3008,6 +3721,14 @@ bool NodeMetaInfo::isFlowViewFlowTransition() const
bool NodeMetaInfo::isFlowViewFlowDecision() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is FlowView.FlowDecision"_t,
+ category(),
+ keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
return isBasedOnCommonType<FlowView, FlowDecision>(m_projectStorage, m_typeId);
} else {
@@ -3018,6 +3739,14 @@ bool NodeMetaInfo::isFlowViewFlowDecision() const
bool NodeMetaInfo::isFlowViewFlowWildcard() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is FlowView.FlowWildcard"_t,
+ category(),
+ keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
return isBasedOnCommonType<FlowView, FlowWildcard>(m_projectStorage, m_typeId);
} else {
@@ -3028,6 +3757,14 @@ bool NodeMetaInfo::isFlowViewFlowWildcard() const
bool NodeMetaInfo::isQtQuickStudioComponentsGroupItem() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is QtQuick.Studio.Components.GroupItem"_t,
+ category(),
+ keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
return isBasedOnCommonType<QtQuick_Studio_Components, GroupItem>(m_projectStorage, m_typeId);
} else {
@@ -3038,6 +3775,14 @@ bool NodeMetaInfo::isQtQuickStudioComponentsGroupItem() const
bool NodeMetaInfo::isQtQuickStudioUtilsJsonListModel() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is QtQuick.Studio.Utils.JsonListModel"_t,
+ category(),
+ keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
return isBasedOnCommonType<QtQuick_Studio_Components, JsonListModel>(m_projectStorage,
m_typeId);
@@ -3049,6 +3794,12 @@ bool NodeMetaInfo::isQtQuickStudioUtilsJsonListModel() const
bool NodeMetaInfo::isQmlComponent() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is QML.Component"_t, category(), keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
return isBasedOnCommonType<QML, Component>(m_projectStorage, m_typeId);
} else {
@@ -3064,6 +3815,12 @@ bool NodeMetaInfo::isQmlComponent() const
bool NodeMetaInfo::isFont() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is font"_t, category(), keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
return isValid() && isTypeId(m_typeId, m_projectStorage->commonTypeId<QtQuick, font>());
} else {
@@ -3074,6 +3831,12 @@ bool NodeMetaInfo::isFont() const
bool NodeMetaInfo::isColor() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is color"_t, category(), keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
return isValid() && isTypeId(m_typeId, m_projectStorage->builtinTypeId<QColor>());
} else {
@@ -3089,6 +3852,12 @@ bool NodeMetaInfo::isColor() const
bool NodeMetaInfo::isBool() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is bool"_t, category(), keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
return isValid() && isTypeId(m_typeId, m_projectStorage->builtinTypeId<bool>());
} else {
@@ -3104,6 +3873,12 @@ bool NodeMetaInfo::isBool() const
bool NodeMetaInfo::isInteger() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is integer"_t, category(), keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
return isValid() && isTypeId(m_typeId, m_projectStorage->builtinTypeId<int>());
} else {
@@ -3119,9 +3894,11 @@ bool NodeMetaInfo::isInteger() const
bool NodeMetaInfo::isFloat() const
{
if constexpr (useProjectStorage()) {
- if (!isValid()) {
+ if (!isValid())
return false;
- }
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is float"_t, category(), keyValue("type id", m_typeId)};
using namespace Storage::Info;
auto floatId = m_projectStorage->builtinTypeId<float>();
@@ -3141,6 +3918,12 @@ bool NodeMetaInfo::isFloat() const
bool NodeMetaInfo::isVariant() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is variant"_t, category(), keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
return isValid() && isTypeId(m_typeId, m_projectStorage->builtinTypeId<QVariant>());
} else {
@@ -3156,6 +3939,12 @@ bool NodeMetaInfo::isVariant() const
bool NodeMetaInfo::isString() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is string"_t, category(), keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
return isValid() && isTypeId(m_typeId, m_projectStorage->builtinTypeId<QString>());
} else {
@@ -3171,6 +3960,12 @@ bool NodeMetaInfo::isString() const
bool NodeMetaInfo::isUrl() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is url"_t, category(), keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
return isValid() && isTypeId(m_typeId, m_projectStorage->builtinTypeId<QUrl>());
} else {
@@ -3186,6 +3981,12 @@ bool NodeMetaInfo::isUrl() const
bool NodeMetaInfo::isQtQuick3DTexture() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is QtQuick3D.Texture"_t, category(), keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
return isBasedOnCommonType<QtQuick3D, Texture>(m_projectStorage, m_typeId);
} else {
@@ -3197,6 +3998,12 @@ bool NodeMetaInfo::isQtQuick3DTexture() const
bool NodeMetaInfo::isQtQuick3DShader() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is QtQuick3D.Shader"_t, category(), keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
return isBasedOnCommonType<QtQuick3D, Shader>(m_projectStorage, m_typeId);
} else {
@@ -3207,6 +4014,12 @@ bool NodeMetaInfo::isQtQuick3DShader() const
bool NodeMetaInfo::isQtQuick3DPass() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is QtQuick3D.Pass"_t, category(), keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
return isBasedOnCommonType<QtQuick3D, Pass>(m_projectStorage, m_typeId);
} else {
@@ -3217,6 +4030,12 @@ bool NodeMetaInfo::isQtQuick3DPass() const
bool NodeMetaInfo::isQtQuick3DCommand() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is QtQuick3D.Command"_t, category(), keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
return isBasedOnCommonType<QtQuick3D, Command>(m_projectStorage, m_typeId);
} else {
@@ -3227,6 +4046,14 @@ bool NodeMetaInfo::isQtQuick3DCommand() const
bool NodeMetaInfo::isQtQuick3DDefaultMaterial() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is QtQuick3D.DefaultMaterial"_t,
+ category(),
+ keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
return isBasedOnCommonType<QtQuick3D, DefaultMaterial>(m_projectStorage, m_typeId);
} else {
@@ -3247,6 +4074,12 @@ bool NodeMetaInfo::isQtQuick3DMaterial() const
bool NodeMetaInfo::isQtQuick3DModel() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is QtQuick3D.Model"_t, category(), keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
return isBasedOnCommonType<QtQuick3D, Storage::Info::Model>(m_projectStorage, m_typeId);
} else {
@@ -3257,6 +4090,12 @@ bool NodeMetaInfo::isQtQuick3DModel() const
bool NodeMetaInfo::isQtQuick3DNode() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is QtQuick3D.Node"_t, category(), keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
return isBasedOnCommonType<QtQuick3D, Node>(m_projectStorage, m_typeId);
} else {
@@ -3267,6 +4106,14 @@ bool NodeMetaInfo::isQtQuick3DNode() const
bool NodeMetaInfo::isQtQuick3DParticles3DAffector3D() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is QtQuick3D.Particles3D.Affector3D"_t,
+ category(),
+ keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
return isBasedOnCommonType<QtQuick3D_Particles3D, Affector3D>(m_projectStorage, m_typeId);
} else {
@@ -3277,6 +4124,12 @@ bool NodeMetaInfo::isQtQuick3DParticles3DAffector3D() const
bool NodeMetaInfo::isQtQuick3DView3D() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is QtQuick3D.View3D"_t, category(), keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
return isBasedOnCommonType<QtQuick3D, View3D>(m_projectStorage, m_typeId);
} else {
@@ -3287,6 +4140,14 @@ bool NodeMetaInfo::isQtQuick3DView3D() const
bool NodeMetaInfo::isQtQuick3DPrincipledMaterial() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is QtQuick3D.PrincipledMaterial"_t,
+ category(),
+ keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
return isBasedOnCommonType<QtQuick3D, PrincipledMaterial>(m_projectStorage, m_typeId);
} else {
@@ -3297,6 +4158,14 @@ bool NodeMetaInfo::isQtQuick3DPrincipledMaterial() const
bool NodeMetaInfo::isQtQuick3DSpecularGlossyMaterial() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is QtQuick3D.SpecularGlossyMaterial"_t,
+ category(),
+ keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
return isBasedOnCommonType<QtQuick3D, SpecularGlossyMaterial>(m_projectStorage, m_typeId);
} else {
@@ -3307,6 +4176,14 @@ bool NodeMetaInfo::isQtQuick3DSpecularGlossyMaterial() const
bool NodeMetaInfo::isQtQuick3DParticles3DSpriteParticle3D() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is QtQuick3D.Particles3D.SpriteParticle3D"_t,
+ category(),
+ keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
return isBasedOnCommonType<QtQuick3D_Particles3D, SpriteParticle3D>(m_projectStorage,
m_typeId);
@@ -3318,6 +4195,14 @@ bool NodeMetaInfo::isQtQuick3DParticles3DSpriteParticle3D() const
bool NodeMetaInfo::isQtQuick3DTextureInput() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is QtQuick3D.TextureInput"_t,
+ category(),
+ keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
return isBasedOnCommonType<QtQuick3D, TextureInput>(m_projectStorage, m_typeId);
} else {
@@ -3328,6 +4213,14 @@ bool NodeMetaInfo::isQtQuick3DTextureInput() const
bool NodeMetaInfo::isQtQuick3DCubeMapTexture() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is QtQuick3D.CubeMapTexture"_t,
+ category(),
+ keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
return isBasedOnCommonType<QtQuick3D, CubeMapTexture>(m_projectStorage, m_typeId);
} else {
@@ -3340,6 +4233,14 @@ bool NodeMetaInfo::isQtQuick3DCubeMapTexture() const
bool NodeMetaInfo::isQtQuick3DSceneEnvironment() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is QtQuick3D.SceneEnvironment"_t,
+ category(),
+ keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
return isBasedOnCommonType<QtQuick3D, SceneEnvironment>(m_projectStorage, m_typeId);
} else {
@@ -3350,6 +4251,12 @@ bool NodeMetaInfo::isQtQuick3DSceneEnvironment() const
bool NodeMetaInfo::isQtQuick3DEffect() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is QtQuick3D.Effect"_t, category(), keyValue("type id", m_typeId)};
+
using namespace Storage::Info;
return isBasedOnCommonType<QtQuick3D, Effect>(m_projectStorage, m_typeId);
} else {
@@ -3359,8 +4266,15 @@ bool NodeMetaInfo::isQtQuick3DEffect() const
bool NodeMetaInfo::isEnumeration() const
{
- if constexpr (useProjectStorage())
- return isValid() && typeData().traits.isEnum;
+ if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is enumeration"_t, category(), keyValue("type id", m_typeId)};
+
+ return typeData().traits.isEnum;
+ }
return false;
}
@@ -3385,8 +4299,15 @@ PropertyMetaInfo::~PropertyMetaInfo() = default;
NodeMetaInfo PropertyMetaInfo::propertyType() const
{
if constexpr (useProjectStorage()) {
- if (isValid())
- return {propertyData().propertyTypeId, m_projectStorage};
+ if (!isValid())
+ return {};
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get property type"_t,
+ category(),
+ keyValue("property declaration id", m_id)};
+
+ return {propertyData().propertyTypeId, m_projectStorage};
} else {
if (isValid())
return NodeMetaInfo{nodeMetaInfoPrivateData()->model(),
@@ -3401,8 +4322,15 @@ NodeMetaInfo PropertyMetaInfo::propertyType() const
NodeMetaInfo PropertyMetaInfo::type() const
{
if constexpr (useProjectStorage()) {
- if (isValid())
- return NodeMetaInfo(propertyData().typeId, m_projectStorage);
+ if (!isValid())
+ return {};
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get property owner type "_t,
+ category(),
+ keyValue("property declaration id", m_id)};
+
+ return NodeMetaInfo(propertyData().typeId, m_projectStorage);
}
return {};
@@ -3410,59 +4338,121 @@ NodeMetaInfo PropertyMetaInfo::type() const
PropertyName PropertyMetaInfo::name() const
{
- if (isValid()) {
- if constexpr (useProjectStorage())
- return PropertyName(Utils::SmallStringView(propertyData().name));
- else
- return propertyName();
- }
+ if (!isValid())
+ return {};
- return {};
+ if constexpr (useProjectStorage()) {
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get property name"_t,
+ category(),
+ keyValue("property declaration id", m_id)};
+
+ return PropertyName(Utils::SmallStringView(propertyData().name));
+ } else {
+ return propertyName();
+ }
}
bool PropertyMetaInfo::isWritable() const
{
- if constexpr (useProjectStorage())
- return isValid() && !(propertyData().traits & Storage::PropertyDeclarationTraits::IsReadOnly);
- else
+ if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return {};
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is property writable"_t,
+ category(),
+ keyValue("property declaration id", m_id)};
+
+ return !(propertyData().traits & Storage::PropertyDeclarationTraits::IsReadOnly);
+ } else {
return isValid() && nodeMetaInfoPrivateData()->isPropertyWritable(propertyName());
+ }
}
bool PropertyMetaInfo::isReadOnly() const
{
- return !isWritable();
+ if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return {};
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is property read only"_t,
+ category(),
+ keyValue("property declaration id", m_id)};
+
+ return propertyData().traits & Storage::PropertyDeclarationTraits::IsReadOnly;
+ } else {
+ return !isWritable();
+ }
}
bool PropertyMetaInfo::isListProperty() const
{
- if constexpr (useProjectStorage())
- return isValid() && propertyData().traits & Storage::PropertyDeclarationTraits::IsList;
- else
+ if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return {};
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is list property"_t,
+ category(),
+ keyValue("property declaration id", m_id)};
+
+ return propertyData().traits & Storage::PropertyDeclarationTraits::IsList;
+ } else {
return isValid() && nodeMetaInfoPrivateData()->isPropertyList(propertyName());
+ }
}
bool PropertyMetaInfo::isEnumType() const
{
- if constexpr (useProjectStorage())
+ if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return {};
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is enum type"_t,
+ category(),
+ keyValue("property has enumeration type", m_id)};
+
return propertyType().isEnumeration();
- else
+ } else {
return isValid() && nodeMetaInfoPrivateData()->isPropertyEnum(propertyName());
+ }
}
bool PropertyMetaInfo::isPrivate() const
{
- if constexpr (useProjectStorage())
+ if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return {};
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is private property"_t,
+ category(),
+ keyValue("property declaration id", m_id)};
+
return isValid() && propertyData().name.startsWith("__");
- else
+ } else {
return isValid() && propertyName().startsWith("__");
+ }
}
bool PropertyMetaInfo::isPointer() const
{
- if constexpr (useProjectStorage())
+ if constexpr (useProjectStorage()) {
+ if (!isValid())
+ return {};
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is pointer property"_t,
+ category(),
+ keyValue("property declaration id", m_id)};
+
return isValid() && (propertyData().traits & Storage::PropertyDeclarationTraits::IsPointer);
- else
+ } else {
return isValid() && nodeMetaInfoPrivateData()->isPropertyPointer(propertyName());
+ }
}
namespace {
@@ -3479,6 +4469,11 @@ QVariant PropertyMetaInfo::castedValue(const QVariant &value) const
return {};
if constexpr (!useProjectStorage()) {
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"cast value"_t,
+ category(),
+ keyValue("property declaration id", m_id)};
+
const QVariant variant = value;
QVariant copyVariant = variant;
const TypeName &typeName = propertyTypeName();
@@ -3496,7 +4491,7 @@ QVariant PropertyMetaInfo::castedValue(const QVariant &value) const
return variant;
} else if (typeId == QVariant::UserType && typeName == "var") {
return variant;
- } else if (variant.typeId() == QVariant::List) {
+ } else if (variant.typeId() == QMetaType::QVariantList) {
// TODO: check the contents of the list
return variant;
} else if (typeName == "var" || typeName == "variant") {
diff --git a/src/plugins/qmldesigner/designercore/metainfo/subcomponentmanager.cpp b/src/plugins/qmldesigner/designercore/metainfo/subcomponentmanager.cpp
index 403731d1c4..29a093f199 100644
--- a/src/plugins/qmldesigner/designercore/metainfo/subcomponentmanager.cpp
+++ b/src/plugins/qmldesigner/designercore/metainfo/subcomponentmanager.cpp
@@ -44,6 +44,7 @@ SubComponentManager::SubComponentManager(Model *model,
ExternalDependenciesInterface &externalDependencies)
: m_model(model)
, m_externalDependencies{externalDependencies}
+ , m_componentUtils{externalDependencies}
{
connect(&m_watcher, &QFileSystemWatcher::directoryChanged,
this, [this](const QString &path) { parseDirectory(path); });
@@ -192,7 +193,7 @@ void SubComponentManager::parseDirectory(const QString &canonicalDirPath, bool a
if (!model() || !model()->rewriterView())
return;
- if (canonicalDirPath.endsWith(QLatin1String(Constants::QUICK_3D_ASSETS_FOLDER))) {
+ if (m_componentUtils.isImport3dPath(canonicalDirPath)) {
parseQuick3DAssetsDir(canonicalDirPath);
return;
}
@@ -344,11 +345,8 @@ void SubComponentManager::unregisterQmlFile(const QFileInfo &fileInfo, const QSt
void SubComponentManager::registerQmlFile(const QFileInfo &fileInfo, const QString &qualifier,
bool addToLibrary)
{
- if (!addToLibrary || !model()
- || fileInfo.path().contains(QLatin1String(Constants::QUICK_3D_ASSETS_FOLDER))
- || fileInfo.path().contains(QLatin1String(Constants::DEFAULT_EFFECTS_IMPORT_FOLDER))) {
+ if (!addToLibrary || !model() || m_componentUtils.isGeneratedPath(fileInfo.path()))
return;
- }
QString componentName = fileInfo.baseName();
const QString baseComponentName = componentName;
@@ -395,7 +393,7 @@ void SubComponentManager::parseQuick3DAssetsDir(const QString &quick3DAssetsPath
QDir quick3DAssetsDir(quick3DAssetsPath);
QStringList assets = quick3DAssetsDir.entryList(QDir::Dirs | QDir::NoDot | QDir::NoDotDot);
for (QString &asset : assets)
- asset.prepend(QString(Constants::QUICK_3D_ASSETS_FOLDER).mid(1) + '.');
+ asset.prepend(m_componentUtils.import3dTypePrefix() + '.');
// Create item library entries for Quick3D assets that are imported by document
for (auto &import : std::as_const(m_imports)) {
@@ -460,7 +458,8 @@ QStringList SubComponentManager::quick3DAssetPaths() const
const auto impPaths = importPaths();
QStringList retPaths;
for (const auto &impPath : impPaths) {
- const QString assetPath = impPath + QLatin1String(Constants::QUICK_3D_ASSETS_FOLDER);
+ QString path3d = m_componentUtils.import3dTypePath();
+ const QString assetPath = impPath + '/' + path3d;
if (QFileInfo::exists(assetPath))
retPaths << assetPath;
}
@@ -520,7 +519,7 @@ void SubComponentManager::update(const QUrl &filePath, const Imports &imports)
// Remove old watched asset paths
const QStringList watchPaths = m_watcher.directories();
- const QString &quick3DAssetFolder = QLatin1String(Constants::QUICK_3D_ASSETS_FOLDER);
+ const QString &quick3DAssetFolder = m_componentUtils.import3dTypePath();
for (const auto &watchPath : watchPaths) {
if (watchPath.endsWith(quick3DAssetFolder))
m_watcher.removePath(watchPath);
@@ -580,7 +579,7 @@ void SubComponentManager::addAndParseImport(const Import &import)
} else {
QString url = import.url();
- if (url.startsWith(QString(Constants::QUICK_3D_ASSETS_FOLDER).mid(1))) {
+ if (url.startsWith(m_componentUtils.import3dTypePrefix())) {
parseQuick3DAssetsItem(import.url());
return;
}
diff --git a/src/plugins/qmldesigner/designercore/model/abstractview.cpp b/src/plugins/qmldesigner/designercore/model/abstractview.cpp
index 061ab8ae2b..125c7195a8 100644
--- a/src/plugins/qmldesigner/designercore/model/abstractview.cpp
+++ b/src/plugins/qmldesigner/designercore/model/abstractview.cpp
@@ -567,8 +567,10 @@ void AbstractView::disableWidget()
void AbstractView::enableWidget()
{
- if (hasWidget() && widgetInfo().widgetFlags == DesignerWidgetFlags::DisableOnError)
- widgetInfo().widget->setEnabled(true);
+ if (hasWidget()) {
+ if (auto info = widgetInfo(); info.widgetFlags == DesignerWidgetFlags::DisableOnError)
+ info.widget->setEnabled(true);
+ }
}
QString AbstractView::contextHelpId() const
diff --git a/src/plugins/qmldesigner/designercore/model/bindingproperty.cpp b/src/plugins/qmldesigner/designercore/model/bindingproperty.cpp
index 141548047e..23c17dc61a 100644
--- a/src/plugins/qmldesigner/designercore/model/bindingproperty.cpp
+++ b/src/plugins/qmldesigner/designercore/model/bindingproperty.cpp
@@ -37,10 +37,11 @@ BindingProperty::BindingProperty(const PropertyName &propertyName, const Interna
void BindingProperty::setExpression(const QString &expression)
{
- Internal::WriteLocker locker(model());
if (!isValid())
return;
+ Internal::WriteLocker locker(model());
+
if (isDynamic())
qWarning() << "Calling BindingProperty::setExpression on dynamic property.";
diff --git a/src/plugins/qmldesigner/designercore/model/model.cpp b/src/plugins/qmldesigner/designercore/model/model.cpp
index a4cd31b2a8..d4eea26378 100644
--- a/src/plugins/qmldesigner/designercore/model/model.cpp
+++ b/src/plugins/qmldesigner/designercore/model/model.cpp
@@ -9,7 +9,6 @@
#include "../projectstorage/sourcepath.h"
#include "../projectstorage/sourcepathcache.h"
#include "abstractview.h"
-#include "auxiliarydataproperties.h"
#include "internalbindingproperty.h"
#include "internalnodeabstractproperty.h"
#include "internalnodelistproperty.h"
@@ -33,6 +32,8 @@
#include "signalhandlerproperty.h"
#include "variantproperty.h"
+#include <uniquename.h>
+
#include <projectstorage/projectstorage.h>
#include <qmljs/qmljsmodelmanagerinterface.h>
@@ -46,8 +47,6 @@
#include <QRegularExpression>
#include <qcompilerdetection.h>
-#include <string>
-
/*!
\defgroup CoreModel
*/
@@ -170,10 +169,10 @@ Storage::Imports createStorageImports(const Imports &imports,
SourceId fileId)
{
return Utils::transform<Storage::Imports>(imports, [&](const Import &import) {
- return Storage::Import{projectStorage.moduleId(Utils::SmallString{import.url()}),
- import.majorVersion(),
- import.minorVersion(),
- fileId};
+ using Storage::ModuleKind;
+ auto moduleKind = import.isLibraryImport() ? ModuleKind::QmlLibrary : ModuleKind::PathLibrary;
+ auto moduleId = projectStorage.moduleId(Utils::SmallString{import.url()}, moduleKind);
+ return Storage::Import{moduleId, import.majorVersion(), import.minorVersion(), fileId};
});
}
@@ -244,7 +243,7 @@ void ModelPrivate::notifyUsedImportsChanged(const Imports &usedImports)
}
}
-QUrl ModelPrivate::fileUrl() const
+const QUrl &ModelPrivate::fileUrl() const
{
return m_fileUrl;
}
@@ -390,7 +389,11 @@ ImportedTypeNameId ModelPrivate::importedTypeNameId(Utils::SmallStringView typeN
return import.alias() == aliasName;
});
if (found != m_imports.end()) {
- ModuleId moduleId = projectStorage->moduleId(Utils::PathString{found->url()});
+ using Storage::ModuleKind;
+ auto moduleKind = found->isLibraryImport() ? ModuleKind::QmlLibrary
+ : ModuleKind::PathLibrary;
+ ModuleId moduleId = projectStorage->moduleId(Utils::PathString{found->url()},
+ moduleKind);
ImportId importId = projectStorage->importId(
Storage::Import{moduleId, found->majorVersion(), found->minorVersion(), m_sourceId});
return projectStorage->importedTypeNameId(importId, shortTypeName);
@@ -1758,14 +1761,22 @@ Storage::Info::ExportedTypeName Model::exportedTypeNameForMetaInfo(const NodeMet
return {};
}
-const Imports &Model::possibleImports() const
+Imports Model::possibleImports() const
{
+#ifdef QDS_USE_PROJECTSTORAGE
+ return {};
+#else
return d->m_possibleImportList;
+#endif
}
-const Imports &Model::usedImports() const
+Imports Model::usedImports() const
{
+#ifdef QDS_USE_PROJECTSTORAGE
+ return {};
+#else
return d->m_usedImportList;
+#endif
}
void Model::changeImports(Imports importsToBeAdded, Imports importsToBeRemoved)
@@ -1773,6 +1784,7 @@ void Model::changeImports(Imports importsToBeAdded, Imports importsToBeRemoved)
d->changeImports(std::move(importsToBeAdded), std::move(importsToBeRemoved));
}
+#ifndef QDS_USE_PROJECTSTORAGE
void Model::setPossibleImports(Imports possibleImports)
{
auto tracer = d->traceToken.begin("possible imports"_t);
@@ -1784,7 +1796,9 @@ void Model::setPossibleImports(Imports possibleImports)
d->notifyPossibleImportsChanged(d->m_possibleImportList);
}
}
+#endif
+#ifndef QDS_USE_PROJECTSTORAGE
void Model::setUsedImports(Imports usedImports)
{
auto tracer = d->traceToken.begin("used imports"_t);
@@ -1796,6 +1810,7 @@ void Model::setUsedImports(Imports usedImports)
d->notifyUsedImportsChanged(d->m_usedImportList);
}
}
+#endif
static bool compareVersions(const Import &import1, const Import &import2, bool allowHigherVersion)
{
@@ -1848,89 +1863,18 @@ bool Model::hasImport(const QString &importUrl) const
});
}
-static QString firstCharToLower(const QString &string)
-{
- QString resultString = string;
-
- if (!resultString.isEmpty())
- resultString[0] = resultString.at(0).toLower();
-
- return resultString;
-}
-
-QString Model::generateNewId(const QString &prefixName,
- const QString &fallbackPrefix,
- std::optional<std::function<bool(const QString &)>> isDuplicate) const
+QString Model::generateNewId(const QString &prefixName, const QString &fallbackPrefix) const
{
- // First try just the prefixName without number as postfix, then continue with 2 and further
- // as postfix until id does not already exist.
- // Properties of the root node are not allowed for ids, because they are available in the
- // complete context without qualification.
-
- int counter = 0;
-
- QString newBaseId = QStringView(u"%1").arg(firstCharToLower(prefixName));
- newBaseId.remove(QRegularExpression(QStringLiteral("[^a-zA-Z0-9_]")));
-
- if (!newBaseId.isEmpty()) {
- QChar firstChar = newBaseId.at(0);
- if (firstChar.isDigit())
- newBaseId.prepend('_');
- } else {
- newBaseId = fallbackPrefix;
- }
-
- QString newId = newBaseId;
+ QString newId = prefixName;
- if (!isDuplicate.has_value())
- isDuplicate = std::bind(&Model::hasId, this, std::placeholders::_1);
+ if (newId.isEmpty())
+ newId = fallbackPrefix;
- while (!ModelNode::isValidId(newId) || isDuplicate.value()(newId)
- || d->rootNode()->property(newId.toUtf8())) {
- ++counter;
- newId = QStringView(u"%1%2").arg(firstCharToLower(newBaseId)).arg(counter);
- }
-
- return newId;
-}
-
-// Generate a unique camelCase id from a name
-// note: this methods does the same as generateNewId(). The 2 methods should be merged into one
-QString Model::generateIdFromName(const QString &name, const QString &fallbackId) const
-{
- QString newId;
- if (name.isEmpty()) {
- newId = fallbackId;
- } else {
- // convert to camel case
- QStringList nameWords = name.split(" ");
- nameWords[0] = nameWords[0].at(0).toLower() + nameWords[0].mid(1);
- for (int i = 1; i < nameWords.size(); ++i)
- nameWords[i] = nameWords[i].at(0).toUpper() + nameWords[i].mid(1);
- newId = nameWords.join("");
-
- // if id starts with a number prepend an underscore
- if (newId.at(0).isDigit())
- newId.prepend('_');
- }
-
- // If the new id is not valid (e.g. qml keyword match), try fixing it by prepending underscore
- if (!ModelNode::isValidId(newId))
- newId.prepend("_");
-
- QRegularExpression rgx("\\d+$"); // matches a number at the end of a string
- while (hasId(newId)) { // id exists
- QRegularExpressionMatch match = rgx.match(newId);
- if (match.hasMatch()) { // ends with a number, increment it
- QString numStr = match.captured();
- int num = numStr.toInt() + 1;
- newId = newId.mid(0, match.capturedStart()) + QString::number(num);
- } else {
- newId.append('1');
- }
- }
-
- return newId;
+ return UniqueName::generateId(prefixName, [&] (const QString &id) {
+ // Properties of the root node are not allowed for ids, because they are available in the
+ // complete context without qualification.
+ return hasId(id) || d->rootNode()->property(id.toUtf8());
+ });
}
void Model::startDrag(QMimeData *mimeData, const QPixmap &icon)
@@ -2021,14 +1965,6 @@ bool Model::isImportPossible(const Import &import, bool ignoreAlias, bool allowH
return false;
}
-QString Model::pathForImport(const Import &import)
-{
- if (!rewriterView())
- return QString();
-
- return rewriterView()->pathForImport(import);
-}
-
QStringList Model::importPaths() const
{
if (rewriterView())
@@ -2110,7 +2046,7 @@ void Model::clearMetaInfoCache()
\brief Returns the URL against which relative URLs within the model should be resolved.
\return The base URL.
*/
-QUrl Model::fileUrl() const
+const QUrl &Model::fileUrl() const
{
return d->fileUrl();
}
@@ -2205,6 +2141,16 @@ NodeMetaInfo Model::qtQmlModelsListElementMetaInfo() const
}
}
+NodeMetaInfo Model::qtQmlXmlListModelXmlListModelRoleMetaInfo() const
+{
+ if constexpr (useProjectStorage()) {
+ using namespace Storage::Info;
+ return createNodeMetaInfo<QtQml_XmlListModel, XmlListModelRole>();
+ } else {
+ return metaInfo("QtQml.XmlListModel.XmlListModelRole");
+ }
+}
+
NodeMetaInfo Model::qmlQtObjectMetaInfo() const
{
if constexpr (useProjectStorage()) {
@@ -2541,8 +2487,7 @@ QList<ItemLibraryEntry> Model::itemLibraryEntries() const
{
#ifdef QDS_USE_PROJECTSTORAGE
using namespace Storage::Info;
- return toItemLibraryEntries(d->projectStorage->itemLibraryEntries(d->m_sourceId),
- *d->projectStorage);
+ return toItemLibraryEntries(d->projectStorage->itemLibraryEntries(d->m_sourceId));
#else
return d->metaInfo().itemLibraryInfo()->entries();
#endif
@@ -2608,11 +2553,10 @@ MetaInfo Model::metaInfo()
}
#endif
-Module Model::module(Utils::SmallStringView moduleName)
+Module Model::module(Utils::SmallStringView moduleName, Storage::ModuleKind moduleKind)
{
- if constexpr (useProjectStorage()) {
- return Module(d->projectStorage->moduleId(moduleName), d->projectStorage);
- }
+ if constexpr (useProjectStorage())
+ return Module(d->projectStorage->moduleId(moduleName, moduleKind), d->projectStorage);
return {};
}
diff --git a/src/plugins/qmldesigner/designercore/model/model_p.h b/src/plugins/qmldesigner/designercore/model/model_p.h
index a3e972f329..cb082fd1d7 100644
--- a/src/plugins/qmldesigner/designercore/model/model_p.h
+++ b/src/plugins/qmldesigner/designercore/model/model_p.h
@@ -122,7 +122,7 @@ public:
ModelPrivate(const ModelPrivate &) = delete;
ModelPrivate &operator=(const ModelPrivate &) = delete;
- QUrl fileUrl() const;
+ const QUrl &fileUrl() const;
void setFileUrl(const QUrl &url);
InternalNodePointer createNode(const TypeName &typeName,
diff --git a/src/plugins/qmldesigner/designercore/model/modelresourcemanagement.cpp b/src/plugins/qmldesigner/designercore/model/modelresourcemanagement.cpp
index a61f1001f9..27ac2e67ab 100644
--- a/src/plugins/qmldesigner/designercore/model/modelresourcemanagement.cpp
+++ b/src/plugins/qmldesigner/designercore/model/modelresourcemanagement.cpp
@@ -515,8 +515,7 @@ struct BindingFilter
struct TargetFilter
{
TargetFilter(NodeDependencies &dependencies, Model *model)
- : flowViewFlowActionAreaMetaInfo{model->flowViewFlowActionAreaMetaInfo()}
- , flowViewFlowTransitionMetaInfo{model->flowViewFlowTransitionMetaInfo()}
+ : flowViewFlowTransitionMetaInfo{model->flowViewFlowTransitionMetaInfo()}
, qtQuickPropertyChangesMetaInfo{model->qtQuickPropertyChangesMetaInfo()}
, qtQuickTimelineKeyframeGroupMetaInfo{model->qtQuickTimelineKeyframeGroupMetaInfo()}
, qtQuickPropertyAnimationMetaInfo{model->qtQuickPropertyAnimationMetaInfo()}
diff --git a/src/plugins/qmldesigner/designercore/model/modelutils.cpp b/src/plugins/qmldesigner/designercore/model/modelutils.cpp
index cb3f482289..6c3e1ea50f 100644
--- a/src/plugins/qmldesigner/designercore/model/modelutils.cpp
+++ b/src/plugins/qmldesigner/designercore/model/modelutils.cpp
@@ -9,6 +9,8 @@
#include <projectstorage/projectstorage.h>
#include <projectstorage/sourcepathcache.h>
+#include <coreplugin/messagebox.h>
+
#include <utils/expected.h>
#include <utils/ranges.h>
@@ -107,19 +109,19 @@ PropertyMetaInfo metainfo(const ModelNode &node, const PropertyName &propertyNam
return node.metaInfo().property(propertyName);
}
-QString componentFilePath(const PathCacheType &pathCache, const NodeMetaInfo &metaInfo)
+QString componentFilePath([[maybe_unused]] const PathCacheType &pathCache, const NodeMetaInfo &metaInfo)
{
- if constexpr (useProjectStorage()) {
- auto typeSourceId = metaInfo.sourceId();
+#ifdef QDS_USE_PROJECTSTORAGE
+ auto typeSourceId = metaInfo.sourceId();
- if (typeSourceId && metaInfo.isFileComponent()) {
- return pathCache.sourcePath(typeSourceId).toQString();
- }
- } else {
- return metaInfo.componentFileName();
+ if (typeSourceId && metaInfo.isFileComponent()) {
+ return pathCache.sourcePath(typeSourceId).toQString();
}
return {};
+#else
+ return metaInfo.componentFileName();
+#endif
}
QString componentFilePath(const ModelNode &node)
diff --git a/src/plugins/qmldesigner/designercore/model/propertycontainer.cpp b/src/plugins/qmldesigner/designercore/model/propertycontainer.cpp
index cd7cebbb73..8eaa7947de 100644
--- a/src/plugins/qmldesigner/designercore/model/propertycontainer.cpp
+++ b/src/plugins/qmldesigner/designercore/model/propertycontainer.cpp
@@ -41,7 +41,7 @@ PropertyName PropertyContainer::name() const
QVariant PropertyContainer::value() const
{
- if (m_value.typeId() == QVariant::String)
+ if (m_value.typeId() == QMetaType::QString)
m_value = PropertyParser::read(m_type, m_value.toString());
return m_value;
}
diff --git a/src/plugins/qmldesigner/designercore/model/propertyparser.cpp b/src/plugins/qmldesigner/designercore/model/propertyparser.cpp
index 788530c291..264c944fea 100644
--- a/src/plugins/qmldesigner/designercore/model/propertyparser.cpp
+++ b/src/plugins/qmldesigner/designercore/model/propertyparser.cpp
@@ -201,7 +201,7 @@ QVariant read(const QString &typeStr, const QString &str, const MetaInfo &)
QVariant read(const QString &typeStr, const QString &str)
{
- int type = QMetaType::type(typeStr.toUtf8().constData());
+ int type = QMetaType::fromName(typeStr.toUtf8().constData()).id();
if (type == 0) {
if (typeStr != "binding"_L1 && typeStr != "enum"_L1) {
qWarning() << "Type " << typeStr
@@ -270,15 +270,14 @@ QVariant read(int variantType, const QString &str)
value = QVariant::fromValue<Enumeration>(enumerationFromString(str, &conversionOk));
} else {
value = QVariant(str);
- value.convert(static_cast<QVariant::Type>(variantType));
+ value.convert(QMetaType(variantType));
}
break;
}
}
if (!conversionOk) {
- qWarning() << "Could not convert" << str
- << "to" << QMetaType::typeName(variantType);
+ qWarning() << "Could not convert" << str << "to" << QMetaType(variantType).name();
value = QVariant(str);
}
diff --git a/src/plugins/qmldesigner/designercore/model/qmlitemnode.cpp b/src/plugins/qmldesigner/designercore/model/qmlitemnode.cpp
index 826856428b..6e3b739096 100644
--- a/src/plugins/qmldesigner/designercore/model/qmlitemnode.cpp
+++ b/src/plugins/qmldesigner/designercore/model/qmlitemnode.cpp
@@ -9,8 +9,9 @@
#include "bindingproperty.h"
#include "qmlanchors.h"
-#include <model.h>
#include <abstractview.h>
+#include <generatedcomponentutils.h>
+#include <model.h>
#include <coreplugin/icore.h>
@@ -196,7 +197,9 @@ QmlItemNode QmlItemNode::createQmlItemNodeForEffect(AbstractView *view,
auto createEffectNode = [=, &newQmlItemNode, &parentProperty]() {
const QString effectName = QFileInfo(effectPath).baseName();
- Import import = Import::createLibraryImport("Effects." + effectName, "1.0");
+ Import import = Import::createLibraryImport(GeneratedComponentUtils(view->externalDependencies())
+ .composedEffectsTypePrefix()
+ + '.' + effectName, "1.0");
try {
if (!view->model()->hasImport(import, true, true))
view->model()->changeImports({import}, {});
@@ -748,7 +751,6 @@ void QmlFlowActionAreaNode::assignTargetFlowItem(const QmlFlowTargetNode &flowIt
ModelNode transition = flowView.addTransition(flowParent.modelNode(),
flowItem.modelNode());
-
modelNode().bindingProperty("target").setExpression(transition.validId());
}
diff --git a/src/plugins/qmldesigner/designercore/model/qmlvisualnode.cpp b/src/plugins/qmldesigner/designercore/model/qmlvisualnode.cpp
index c84f234257..726d3d52af 100644
--- a/src/plugins/qmldesigner/designercore/model/qmlvisualnode.cpp
+++ b/src/plugins/qmldesigner/designercore/model/qmlvisualnode.cpp
@@ -24,6 +24,8 @@
#include <QDir>
#include <QRandomGenerator>
+#include <memory>
+
namespace QmlDesigner {
static char imagePlaceHolder[] = "qrc:/qtquickplugin/images/template_image.png";
@@ -182,8 +184,8 @@ void QmlVisualNode::scatter(const ModelNode &targetNode, const std::optional<int
if (!scatter)
return;
- if (offset.has_value()) { // offset
- double offsetValue = offset.value();
+ if (offset) { // offset
+ double offsetValue = *offset;
this->translate(QVector3D(offsetValue, offsetValue, offsetValue));
} else { // scatter in range
const double scatterRange = 20.;
@@ -250,8 +252,7 @@ QmlObjectNode QmlVisualNode::createQmlObjectNode(AbstractView *view,
NodeAbstractProperty parentProperty = parentQmlItemNode.defaultNodeAbstractProperty();
-
- NodeHints hints = NodeHints::fromItemLibraryEntry(itemLibraryEntry);
+ NodeHints hints = NodeHints::fromItemLibraryEntry(itemLibraryEntry, view->model());
const PropertyName forceNonDefaultProperty = hints.forceNonDefaultProperty().toUtf8();
QmlObjectNode newNode = QmlItemNode::createQmlObjectNode(view,
@@ -289,17 +290,17 @@ static QmlObjectNode createQmlObjectNodeFromSource(AbstractView *view,
textEdit.setPlainText(source);
NotIndentingTextEditModifier modifier(&textEdit);
- QScopedPointer<RewriterView> rewriterView(
- new RewriterView(view->externalDependencies(), RewriterView::Amend));
+ std::unique_ptr<RewriterView> rewriterView = std::make_unique<RewriterView>(
+ view->externalDependencies(), RewriterView::Amend);
rewriterView->setCheckSemanticErrors(false);
rewriterView->setTextModifier(&modifier);
rewriterView->setAllowComponentRoot(true);
rewriterView->setPossibleImportsEnabled(false);
- inputModel->setRewriterView(rewriterView.data());
+ inputModel->setRewriterView(rewriterView.get());
if (rewriterView->errors().isEmpty() && rewriterView->rootModelNode().isValid()) {
ModelNode rootModelNode = rewriterView->rootModelNode();
- inputModel->detachView(rewriterView.data());
+ inputModel->detachView(rewriterView.get());
QmlVisualNode(rootModelNode).setPosition(position);
ModelMerger merger(view);
return merger.insertModel(rootModelNode);
@@ -329,7 +330,7 @@ QmlObjectNode QmlVisualNode::createQmlObjectNode(AbstractView *view,
{
QmlObjectNode newQmlObjectNode;
- NodeHints hints = NodeHints::fromItemLibraryEntry(itemLibraryEntry);
+ NodeHints hints = NodeHints::fromItemLibraryEntry(itemLibraryEntry, view->model());
auto createNodeFunc = [=, &newQmlObjectNode, &parentProperty]() {
#ifndef QDS_USE_PROJECTSTORAGE
@@ -361,13 +362,17 @@ QmlObjectNode QmlVisualNode::createQmlObjectNode(AbstractView *view,
propertyPairList.append(position.propertyPairList());
ModelNode::NodeSourceType nodeSourceType = ModelNode::NodeWithoutSource;
- if (itemLibraryEntry.typeName() == "QtQml.Component")
- nodeSourceType = ModelNode::NodeWithComponentSource;
#ifdef QDS_USE_PROJECTSTORAGE
+ NodeMetaInfo metaInfo{itemLibraryEntry.typeId(), view->model()->projectStorage()};
+ if (metaInfo.isQmlComponent())
+ nodeSourceType = ModelNode::NodeWithComponentSource;
newQmlObjectNode = QmlObjectNode(view->createModelNode(
itemLibraryEntry.typeName(), propertyPairList, {}, {}, nodeSourceType));
#else
+ if (itemLibraryEntry.typeName() == "QtQml.Component")
+ nodeSourceType = ModelNode::NodeWithComponentSource;
+
newQmlObjectNode = QmlObjectNode(view->createModelNode(itemLibraryEntry.typeName(),
majorVersion,
minorVersion,
diff --git a/src/plugins/qmldesigner/designercore/model/rewriteactioncompressor.cpp b/src/plugins/qmldesigner/designercore/model/rewriteactioncompressor.cpp
index c4d96bb250..edee6840ef 100644
--- a/src/plugins/qmldesigner/designercore/model/rewriteactioncompressor.cpp
+++ b/src/plugins/qmldesigner/designercore/model/rewriteactioncompressor.cpp
@@ -58,7 +58,6 @@ void RewriteActionCompressor::compressImports(QList<RewriteAction *> &actions) c
actionsToRemove.append(action);
actionsToRemove.append(addImportAction);
addedImports.remove(import);
- delete addImportAction;
} else {
removedImports.insert(import, action);
}
@@ -67,13 +66,11 @@ void RewriteActionCompressor::compressImports(QList<RewriteAction *> &actions) c
if (RewriteAction *duplicateAction = addedImports.value(import, 0)) {
actionsToRemove.append(duplicateAction);
addedImports.remove(import);
- delete duplicateAction;
addedImports.insert(import, action);
} else if (RewriteAction *removeAction = removedImports.value(import, 0)) {
actionsToRemove.append(action);
actionsToRemove.append(removeAction);
removedImports.remove(import);
- delete removeAction;
} else {
addedImports.insert(import, action);
}
diff --git a/src/plugins/qmldesigner/designercore/model/rewriterview.cpp b/src/plugins/qmldesigner/designercore/model/rewriterview.cpp
index 4ae2261e60..3c481573d2 100644
--- a/src/plugins/qmldesigner/designercore/model/rewriterview.cpp
+++ b/src/plugins/qmldesigner/designercore/model/rewriterview.cpp
@@ -16,12 +16,14 @@
#include <filemanager/objectlengthcalculator.h>
#include <modelnode.h>
#include <modelnodepositionstorage.h>
+#include <nodemetainfo.h>
#include <nodeproperty.h>
+#include <projectstorage/projectstorage.h>
+#include <qmlobjectnode.h>
+#include <qmltimelinekeyframegroup.h>
#include <rewritingexception.h>
#include <signalhandlerproperty.h>
#include <variantproperty.h>
-#include <qmlobjectnode.h>
-#include <qmltimelinekeyframegroup.h>
#include <qmljs/parser/qmljsengine_p.h>
#include <qmljs/qmljsmodelmanagerinterface.h>
@@ -56,9 +58,9 @@ RewriterView::RewriterView(ExternalDependenciesInterface &externalDependencies,
DifferenceHandling differenceHandling)
: AbstractView{externalDependencies}
, m_differenceHandling(differenceHandling)
- , m_positionStorage(new ModelNodePositionStorage)
- , m_modelToTextMerger(new Internal::ModelToTextMerger(this))
- , m_textToModelMerger(new Internal::TextToModelMerger(this))
+ , m_positionStorage(std::make_unique<ModelNodePositionStorage>())
+ , m_modelToTextMerger(std::make_unique<Internal::ModelToTextMerger>(this))
+ , m_textToModelMerger(std::make_unique<Internal::TextToModelMerger>(this))
{
m_amendTimer.setSingleShot(true);
@@ -78,12 +80,12 @@ RewriterView::~RewriterView() = default;
Internal::ModelToTextMerger *RewriterView::modelToTextMerger() const
{
- return m_modelToTextMerger.data();
+ return m_modelToTextMerger.get();
}
Internal::TextToModelMerger *RewriterView::textToModelMerger() const
{
- return m_textToModelMerger.data();
+ return m_textToModelMerger.get();
}
void RewriterView::modelAttached(Model *model)
@@ -92,7 +94,7 @@ void RewriterView::modelAttached(Model *model)
AbstractView::modelAttached(model);
- ModelAmender differenceHandler(m_textToModelMerger.data());
+ ModelAmender differenceHandler(m_textToModelMerger.get());
const QString qmlSource = m_textModifier->text();
if (m_textToModelMerger->load(qmlSource, differenceHandler))
m_lastCorrectQmlSource = qmlSource;
@@ -104,6 +106,7 @@ void RewriterView::modelAttached(Model *model)
m_modelAttachPending = true;
QTimer::singleShot(1000, this, [this, model](){
modelAttached(model);
+ restoreAuxiliaryData();
});
}
}
@@ -492,7 +495,7 @@ void RewriterView::amendQmlText()
const QString newQmlText = m_textModifier->text();
- ModelAmender differenceHandler(m_textToModelMerger.data());
+ ModelAmender differenceHandler(m_textToModelMerger.get());
if (m_textToModelMerger->load(newQmlText, differenceHandler))
m_lastCorrectQmlSource = newQmlText;
emitCustomNotification(EndRewriterAmend);
@@ -593,7 +596,7 @@ QString RewriterView::auxiliaryDataAsQML() const
hasAuxData = true;
QString strValue = value.toString();
- auto metaType = static_cast<QMetaType::Type>(value.type());
+ const int metaType = value.typeId();
if (metaType == QMetaType::QString
|| metaType == QMetaType::QColor) {
@@ -698,7 +701,7 @@ void RewriterView::forceAmend()
Internal::ModelNodePositionStorage *RewriterView::positionStorage() const
{
- return m_positionStorage.data();
+ return m_positionStorage.get();
}
QList<DocumentMessage> RewriterView::warnings() const
@@ -755,7 +758,7 @@ void RewriterView::resetToLastCorrectQml()
{
m_textModifier->textDocument()->undo();
m_textModifier->textDocument()->clearUndoRedoStacks(QTextDocument::RedoStack);
- ModelAmender differenceHandler(m_textToModelMerger.data());
+ ModelAmender differenceHandler(m_textToModelMerger.get());
Internal::WriteLocker::unlock(model());
m_textToModelMerger->load(m_textModifier->text(), differenceHandler);
Internal::WriteLocker::lock(model());
@@ -933,10 +936,12 @@ bool RewriterView::renameId(const QString& oldId, const QString& newId)
return false;
}
+#ifndef QDS_USE_PROJECTSTORAGE
const QmlJS::ScopeChain *RewriterView::scopeChain() const
{
return textToModelMerger()->scopeChain();
}
+#endif
const QmlJS::Document *RewriterView::document() const
{
@@ -989,38 +994,74 @@ QString RewriterView::convertTypeToImportAlias(const QString &type) const
return result;
}
-QString RewriterView::pathForImport(const Import &import)
+QStringList RewriterView::importDirectories() const
{
- if (scopeChain() && scopeChain()->context() && document()) {
- const QString importStr = import.isFileImport() ? import.file() : import.url();
- const QmlJS::Imports *imports = scopeChain()->context()->imports(document());
+ const QList<Utils::FilePath> list(m_textToModelMerger->vContext().paths.begin(),
+ m_textToModelMerger->vContext().paths.end());
- QmlJS::ImportInfo importInfo;
+ return Utils::transform(list, [](const Utils::FilePath &p) { return p.toString(); });
+}
- for (const QmlJS::Import &qmljsImport : imports->all()) {
- if (qmljsImport.info.name() == importStr)
- importInfo = qmljsImport.info;
- }
- const QString importPath = importInfo.path();
- return importPath;
+QSet<QPair<QString, QString> > RewriterView::qrcMapping() const
+{
+ return m_textToModelMerger->qrcMapping();
+}
+
+namespace {
+#ifdef QDS_USE_PROJECTSTORAGE
+
+ModuleIds generateModuleIds(const ModelNodes &nodes)
+{
+ ModuleIds moduleIds;
+ moduleIds.reserve(Utils::usize(nodes));
+ for (const auto &node : nodes) {
+ auto exportedNames = node.metaInfo().allExportedTypeNames();
+ if (exportedNames.size())
+ moduleIds.push_back(exportedNames.front().moduleId);
}
- return QString();
+ std::sort(moduleIds.begin(), moduleIds.end());
+ moduleIds.erase(std::unique(moduleIds.begin(), moduleIds.end()), moduleIds.end());
+
+ return moduleIds;
}
-QStringList RewriterView::importDirectories() const
+QStringList generateImports(ModuleIds moduleIds, const ProjectStorageType &projectStorage)
{
- const QList<Utils::FilePath> list(m_textToModelMerger->vContext().paths.begin(),
- m_textToModelMerger->vContext().paths.end());
+ QStringList imports;
+ imports.reserve(std::ssize(moduleIds));
- return Utils::transform(list, [](const Utils::FilePath &p) { return p.toString(); });
+ for (auto moduleId : moduleIds) {
+ using Storage::ModuleKind;
+ auto module = projectStorage.module(moduleId);
+ switch (module.kind) {
+ case ModuleKind::QmlLibrary:
+ imports.push_back("import " + module.name.toQString());
+ break;
+ case ModuleKind::PathLibrary:
+ imports.push_back("import \"" + module.name.toQString() + "\"");
+ break;
+ case ModuleKind::CppLibrary:
+ break;
+ }
+ }
+
+ return imports;
}
-QSet<QPair<QString, QString> > RewriterView::qrcMapping() const
+QStringList generateImports(const ModelNodes &nodes)
{
- return m_textToModelMerger->qrcMapping();
+ if (nodes.empty())
+ return {};
+
+ auto moduleIds = generateModuleIds(nodes);
+
+ return generateImports(moduleIds, *nodes.front().model()->projectStorage());
}
+#endif
+} // namespace
+
void RewriterView::moveToComponent(const ModelNode &modelNode)
{
if (!modelNode.isValid())
@@ -1029,20 +1070,26 @@ void RewriterView::moveToComponent(const ModelNode &modelNode)
int offset = nodeOffset(modelNode);
const QList<ModelNode> nodes = modelNode.allSubModelNodesAndThisNode();
- QSet<QString> directPaths;
+#ifdef QDS_USE_PROJECTSTORAGE
+ auto directPaths = generateImports(nodes);
+#else
+ QSet<QString> directPathsSet;
// Always add QtQuick import
QString quickImport = model()->qtQuickItemMetaInfo().requiredImportString();
if (!quickImport.isEmpty())
- directPaths.insert(quickImport);
+ directPathsSet.insert(quickImport);
for (const ModelNode &partialNode : nodes) {
QString importStr = partialNode.metaInfo().requiredImportString();
if (importStr.size())
- directPaths << importStr;
+ directPathsSet << importStr;
}
- QString importData = Utils::sorted(directPaths.values()).join(QChar::LineFeed);
+ auto directPaths = directPathsSet.values();
+#endif
+
+ QString importData = Utils::sorted(directPaths).join(QChar::LineFeed);
if (importData.size())
importData.append(QString(2, QChar::LineFeed));
@@ -1108,7 +1155,7 @@ void RewriterView::qmlTextChanged()
switch (m_differenceHandling) {
case Validate: {
- ModelValidator differenceHandler(m_textToModelMerger.data());
+ ModelValidator differenceHandler(m_textToModelMerger.get());
if (m_textToModelMerger->load(newQmlText, differenceHandler))
m_lastCorrectQmlSource = newQmlText;
break;
diff --git a/src/plugins/qmldesigner/designercore/model/stylesheetmerger.cpp b/src/plugins/qmldesigner/designercore/model/stylesheetmerger.cpp
index 16877b61db..4f744d54e6 100644
--- a/src/plugins/qmldesigner/designercore/model/stylesheetmerger.cpp
+++ b/src/plugins/qmldesigner/designercore/model/stylesheetmerger.cpp
@@ -23,6 +23,8 @@
#include <QQueue>
#include <QRegularExpression>
+#include <memory>
+
namespace {
QPoint pointForModelNode(const QmlDesigner::ModelNode &node)
@@ -641,10 +643,10 @@ void StylesheetMerger::styleMerge(const QString &qmlTemplateString,
textEditTemplate.setPlainText(imports + qmlTemplateString);
NotIndentingTextEditModifier textModifierTemplate(&textEditTemplate);
- QScopedPointer<RewriterView> templateRewriterView(
- new RewriterView(externalDependencies, RewriterView::Amend));
+ std::unique_ptr<RewriterView> templateRewriterView = std::make_unique<RewriterView>(
+ externalDependencies, RewriterView::Amend);
templateRewriterView->setTextModifier(&textModifierTemplate);
- templateModel->attachView(templateRewriterView.data());
+ templateModel->attachView(templateRewriterView.get());
templateRewriterView->setCheckSemanticErrors(false);
templateRewriterView->setPossibleImportsEnabled(false);
@@ -665,12 +667,12 @@ void StylesheetMerger::styleMerge(const QString &qmlTemplateString,
textEditStyle.setPlainText(parentRewriterView->textModifierContent());
NotIndentingTextEditModifier textModifierStyle(&textEditStyle);
- QScopedPointer<RewriterView> styleRewriterView(
- new RewriterView(externalDependencies, RewriterView::Amend));
+ std::unique_ptr<RewriterView> styleRewriterView = std::make_unique<RewriterView>(
+ externalDependencies, RewriterView::Amend);
styleRewriterView->setTextModifier(&textModifierStyle);
- styleModel->attachView(styleRewriterView.data());
+ styleModel->attachView(styleRewriterView.get());
- StylesheetMerger merger(templateRewriterView.data(), styleRewriterView.data());
+ StylesheetMerger merger(templateRewriterView.get(), styleRewriterView.get());
try {
merger.merge();
diff --git a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp
index f7be6cf5e4..ded7fbc5ef 100644
--- a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp
+++ b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp
@@ -57,7 +57,7 @@ using namespace QmlJS;
using namespace Qt::StringLiterals;
static Q_LOGGING_CATEGORY(rewriterBenchmark, "qtc.rewriter.load", QtWarningMsg)
-static Q_LOGGING_CATEGORY(texttomodelMergerDebug, "qtc.texttomodelmerger.debug", QtDebugMsg)
+static Q_LOGGING_CATEGORY(texttomodelMergerLog, "qtc.texttomodelmerger", QtWarningMsg)
namespace {
@@ -67,17 +67,6 @@ bool isSupportedAttachedProperties(const QString &propertyName)
|| propertyName.startsWith(QLatin1String("InsightCategory."));
}
-bool isSupportedVersion(QmlDesigner::Version version)
-{
- if (version.major == 2)
- return version.minor <= 15;
-
- if (version.major == 6)
- return version.minor <= 6;
-
- return false;
-}
-
bool isGlobalQtEnums(QStringView value)
{
static constexpr auto list = Utils::to_array<std::u16string_view>(
@@ -95,6 +84,9 @@ bool isGlobalQtEnums(QStringView value)
u"TopToBottom", u"UpArrowCursor", u"Vertical", u"WaitCursor",
u"WhatsThisCursor", u"WheelFocus"});
+ if (value.toString().startsWith("Key_"))
+ return true;
+
return std::binary_search(std::begin(list),
std::end(list),
QmlDesigner::ModelUtils::toStdStringView(value));
@@ -102,32 +94,28 @@ bool isGlobalQtEnums(QStringView value)
bool isKnownEnumScopes(QStringView value)
{
- static constexpr auto list = Utils::to_array<std::u16string_view>({u"TextInput",
- u"TextEdit",
- u"Material",
- u"Universal",
- u"Font",
- u"Shape",
- u"ShapePath",
- u"AbstractButton",
- u"Text",
- u"ShaderEffectSource",
- u"Grid",
- u"ItemLayer",
- u"ImageLayer",
- u"SpriteLayer",
- u"Light"});
+ static constexpr auto list = Utils::to_array<std::u16string_view>(
+ {u"TextInput",
+ u"TextEdit",
+ u"Material",
+ u"Universal",
+ u"Font",
+ u"Shape",
+ u"ShapePath",
+ u"AbstractButton",
+ u"Text",
+ u"ShaderEffectSource",
+ u"Grid",
+ u"ItemLayer",
+ u"ImageLayer",
+ u"SpriteLayer",
+ u"Light",
+ u"ExtendedSceneEnvironment.GlowBlendMode"});
return std::find(std::begin(list), std::end(list), QmlDesigner::ModelUtils::toStdStringView(value))
!= std::end(list);
}
-bool supportedQtQuickVersion(const QmlDesigner::Import &import)
-{
- auto version = import.toVersion();
- return version.isEmpty() || isSupportedVersion(version);
-}
-
QString stripQuotes(const QString &str)
{
if ((str.startsWith(QLatin1Char('"')) && str.endsWith(QLatin1Char('"')))
@@ -431,14 +419,19 @@ namespace Internal {
class ReadingContext
{
public:
- ReadingContext(const Snapshot &snapshot, const Document::Ptr &doc,
- const ViewerContext &vContext, Model *model)
+ ReadingContext([[maybe_unused]] const Snapshot &snapshot,
+ [[maybe_unused]] const Document::Ptr &doc,
+ [[maybe_unused]] const ViewerContext &vContext,
+ Model *model)
: m_doc(doc)
+#ifndef QDS_USE_PROJECTSTORAGE
, m_context(
- Link(snapshot, vContext, ModelManagerInterface::instance()->builtins(doc))
- (doc, &m_diagnosticLinkMessages))
+ Link(snapshot,
+ vContext,
+ ModelManagerInterface::instance()->builtins(doc))(doc, &m_diagnosticLinkMessages))
, m_scopeChain(doc, m_context)
, m_scopeBuilder(&m_scopeChain)
+#endif
, m_model(model)
{
}
@@ -446,12 +439,19 @@ public:
~ReadingContext() = default;
Document::Ptr doc() const
- { return m_doc; }
+ {
+ return m_doc;
+ }
+#ifndef QDS_USE_PROJECTSTORAGE
void enterScope(AST::Node *node)
{ m_scopeBuilder.push(node); }
- void leaveScope() { m_scopeBuilder.pop(); }
+ void leaveScope()
+ {
+ m_scopeBuilder.pop();
+ }
+#endif
std::tuple<NodeMetaInfo, TypeName> lookup(AST::UiQualifiedId *astTypeNode)
{
@@ -481,113 +481,6 @@ public:
return node.metaInfo().hasProperty(propertyName.toUtf8());
}
- /// When something is changed here, also change Check::checkScopeObjectMember in
- /// qmljscheck.cpp
- /// ### Maybe put this into the context as a helper function.
- ///
- bool lookupProperty(const QString &prefix,
- const AST::UiQualifiedId *id,
- const Value **property = nullptr,
- const ObjectValue **parentObject = nullptr,
- QString *name = nullptr)
- {
- QList<const ObjectValue *> scopeObjects = m_scopeChain.qmlScopeObjects();
- if (scopeObjects.isEmpty())
- return false;
-
- if (!id)
- return false; // ### error?
-
- if (id->name.isEmpty()) // possible after error recovery
- return false;
-
- QString propertyName;
- if (prefix.isEmpty())
- propertyName = id->name.toString();
- else
- propertyName = prefix;
-
- if (name)
- *name = propertyName;
-
- if (propertyName == u"id" && !id->next)
- return false; // ### should probably be a special value
-
- // attached properties
- bool isAttachedProperty = false;
- if (! propertyName.isEmpty() && propertyName[0].isUpper()) {
- isAttachedProperty = true;
- if (const ObjectValue *qmlTypes = m_scopeChain.qmlTypes())
- scopeObjects += qmlTypes;
- }
-
- if (scopeObjects.isEmpty())
- return false;
-
- // global lookup for first part of id
- const ObjectValue *objectValue = nullptr;
- const Value *value = nullptr;
- for (int i = scopeObjects.size() - 1; i >= 0; --i) {
- objectValue = scopeObjects[i];
- value = objectValue->lookupMember(propertyName, m_context);
- if (value)
- break;
- }
- if (parentObject)
- *parentObject = objectValue;
- if (!value) {
- qCInfo(texttomodelMergerDebug) << Q_FUNC_INFO << "Skipping invalid property name" << propertyName;
- return false;
- }
-
- // can't look up members for attached properties
- if (isAttachedProperty)
- return false;
-
- // resolve references
- if (const Reference *ref = value->asReference())
- value = m_context->lookupReference(ref);
-
- // member lookup
- const AST::UiQualifiedId *idPart = id;
- if (prefix.isEmpty())
- idPart = idPart->next;
- for (; idPart; idPart = idPart->next) {
- objectValue = value_cast<ObjectValue>(value);
- if (! objectValue) {
-// if (idPart->name)
-// qDebug() << idPart->name->asString() << "has no property named"
-// << propertyName;
- return false;
- }
- if (parentObject)
- *parentObject = objectValue;
-
- if (idPart->name.isEmpty()) {
- // somebody typed "id." and error recovery still gave us a valid tree,
- // so just bail out here.
- return false;
- }
-
- propertyName = idPart->name.toString();
- if (name)
- *name = propertyName;
-
- value = objectValue->lookupMember(propertyName, m_context);
- if (! value) {
-// if (idPart->name)
-// qDebug() << "In" << idPart->name->asString() << ":"
-// << objectValue->className() << "has no property named"
-// << propertyName;
- return false;
- }
- }
-
- if (property)
- *property = value;
- return true;
- }
-
bool isArrayProperty(const AbstractProperty &property)
{
return ModelUtils::metainfo(property).isListProperty();
@@ -610,9 +503,9 @@ public:
if (!propertyMetaInfo.isValid()) {
const bool isAttached = !propertyName.isEmpty() && propertyName[0].isUpper();
// Only list elements might have unknown properties.
- if (!node.metaInfo().isQtQuickListElement() && !isAttached) {
- qCInfo(texttomodelMergerDebug)
- << Q_FUNC_INFO << "Unknown property"
+ if (!node.metaInfo().isQtQmlModelsListElement() && !isAttached) {
+ qCInfo(texttomodelMergerLog)
+ << Q_FUNC_INFO << "\nUnknown property"
<< propertyPrefix + QLatin1Char('.') + toString(propertyId) << "on line"
<< propertyId->identifierToken.startLine << "column"
<< propertyId->identifierToken.startColumn;
@@ -668,6 +561,11 @@ public:
//Check for known enum scopes used globally
if (isKnownEnumScopes(astValueList.constFirst()))
return QVariant::fromValue(Enumeration(astValue));
+ } else if (astValueList.size() == 3) {
+ QString enumName = astValueList.constFirst() + '.' + astValueList.at(1);
+ if (isKnownEnumScopes(enumName))
+ return QVariant::fromValue(
+ Enumeration(enumName.toUtf8(), astValueList.constLast().toUtf8()));
}
auto eStmt = AST::cast<AST::ExpressionStatement *>(rhs);
@@ -685,9 +583,12 @@ public:
return QVariant();
}
-
+#ifndef QDS_USE_PROJECTSTORAGE
const ScopeChain &scopeChain() const
- { return m_scopeChain; }
+ {
+ return m_scopeChain;
+ }
+#endif
QList<DiagnosticMessage> diagnosticLinkMessages() const
{ return m_diagnosticLinkMessages; }
@@ -695,9 +596,11 @@ public:
private:
Document::Ptr m_doc;
QList<DiagnosticMessage> m_diagnosticLinkMessages;
+#ifndef QDS_USE_PROJECTSTORAGE
ContextPtr m_context;
ScopeChain m_scopeChain;
ScopeBuilder m_scopeBuilder;
+#endif
Model *m_model;
};
@@ -841,6 +744,7 @@ constexpr auto skipModules = std::make_tuple(EndsWith(u".impl"),
Equals(u"QtQuick.Controls.NativeStyle"),
Equals(u"QtQuick.Controls.Universal"),
Equals(u"QtQuick.Controls.Windows"),
+ Equals(u"QtQuick3D.MaterialEditor"),
StartsWith(u"QtQuick.LocalStorage"),
StartsWith(u"QtQuick.NativeStyle"),
StartsWith(u"QtQuick.Pdf"),
@@ -866,6 +770,7 @@ constexpr auto skipModules = std::make_tuple(EndsWith(u".impl"),
StartsWith(u"QtWebSockets"),
StartsWith(u"QtWebView"));
+#ifndef QDS_USE_PROJECTSTORAGE
bool skipModule(QStringView moduleName)
{
return std::apply([=](const auto &...skipModule) { return (skipModule(moduleName) || ...); },
@@ -931,9 +836,11 @@ QmlDesigner::Imports createQt5Modules()
QmlDesigner::Import::createLibraryImport("QtQuick.Studio.MultiText", "1.0"),
QmlDesigner::Import::createLibraryImport("Qt.SafeRenderer", "2.0")};
}
+#endif
} // namespace
+#ifndef QDS_USE_PROJECTSTORAGE
void TextToModelMerger::setupPossibleImports()
{
if (!m_rewriterView->possibleImportsEnabled())
@@ -942,10 +849,10 @@ void TextToModelMerger::setupPossibleImports()
static QUrl lastProjectUrl;
auto &externalDependencies = m_rewriterView->externalDependencies();
auto projectUrl = externalDependencies.projectUrl();
+
auto allUsedImports = m_scopeChain->context()->imports(m_document.data())->all();
if (m_possibleModules.isEmpty() || projectUrl != lastProjectUrl) {
-
auto &externalDependencies = m_rewriterView->externalDependencies();
if (externalDependencies.isQt6Project()) {
ModuleScanner moduleScanner{[&](QStringView moduleName) {
@@ -975,7 +882,9 @@ void TextToModelMerger::setupPossibleImports()
if (m_rewriterView->isAttached())
m_rewriterView->model()->setPossibleImports(modules);
}
+#endif
+#ifndef QDS_USE_PROJECTSTORAGE
void TextToModelMerger::setupUsedImports()
{
const QmlJS::Imports *imports = m_scopeChain->context()->imports(m_document.data());
@@ -1010,6 +919,7 @@ void TextToModelMerger::setupUsedImports()
if (m_rewriterView->isAttached())
m_rewriterView->model()->setUsedImports(usedImports);
}
+#endif
Document::MutablePtr TextToModelMerger::createParsedDocument(const QUrl &url, const QString &data, QList<DocumentMessage> *errors)
{
@@ -1100,15 +1010,16 @@ bool TextToModelMerger::load(const QString &data, DifferenceHandler &differenceH
m_vContext = ModelManagerInterface::instance()->projectVContext(Dialect::Qml, m_document);
ReadingContext ctxt(snapshot, m_document, m_vContext, m_rewriterView->model());
- m_scopeChain = QSharedPointer<const ScopeChain>(
- new ScopeChain(ctxt.scopeChain()));
+
+#ifndef QDS_USE_PROJECTSTORAGE
+ m_scopeChain = QSharedPointer<const ScopeChain>(new ScopeChain(ctxt.scopeChain()));
if (view()->checkLinkErrors()) {
qCInfo(rewriterBenchmark) << "linked:" << time.elapsed();
collectLinkErrors(&errors, ctxt);
}
-
setupPossibleImports();
+#endif
qCInfo(rewriterBenchmark) << "possible imports:" << time.elapsed();
@@ -1142,7 +1053,9 @@ bool TextToModelMerger::load(const QString &data, DifferenceHandler &differenceH
qCInfo(rewriterBenchmark) << "synced nodes:" << time.elapsed();
+#ifndef QDS_USE_PROJECTSTORAGE
setupUsedImports();
+#endif
setActive(false);
@@ -1239,8 +1152,9 @@ void TextToModelMerger::syncNode(ModelNode &modelNode,
else if (!modelNode.nodeSource().isEmpty() || modelNode.nodeSourceType() != ModelNode::NodeWithoutSource)
clearImplicitComponentDelayed(modelNode, differenceHandler.isAmender());
-
+#ifndef QDS_USE_PROJECTSTORAGE
context->enterScope(astNode);
+#endif
QSet<PropertyName> modelPropertyNames = Utils::toSet(modelNode.propertyNames());
if (!modelNode.id().isEmpty())
@@ -1254,7 +1168,8 @@ void TextToModelMerger::syncNode(ModelNode &modelNode,
if (auto array = AST::cast<AST::UiArrayBinding *>(member)) {
const QString astPropertyName = toString(array->qualifiedId);
- if (isPropertyChangesType(typeName) || isConnectionsType(typeName) || context->lookupProperty(QString(), array->qualifiedId)) {
+ if (isPropertyChangesType(typeName) || isConnectionsType(typeName)
+ || modelNode.metaInfo().hasProperty(astPropertyName.toUtf8())) {
AbstractProperty modelProperty = modelNode.property(astPropertyName.toUtf8());
QList<AST::UiObjectMember *> arrayMembers;
for (AST::UiArrayMemberList *iter = array->members; iter; iter = iter->next)
@@ -1286,13 +1201,8 @@ void TextToModelMerger::syncNode(ModelNode &modelNode,
// Store Behaviours in the default property
defaultPropertyItems.append(member);
} else {
- const Value *propertyType = nullptr;
- const ObjectValue *containingObject = nullptr;
- if (context->lookupProperty({},
- binding->qualifiedId,
- &propertyType,
- &containingObject)
- || isPropertyChangesType(typeName) || isConnectionsType(typeName)) {
+ if (isPropertyChangesType(typeName) || isConnectionsType(typeName)
+ || modelNode.metaInfo().hasProperty(astPropertyName.toUtf8())) {
AbstractProperty modelProperty = modelNode.property(astPropertyName.toUtf8());
if (context->isArrayProperty(modelProperty))
syncArrayProperty(modelProperty, {member}, context, differenceHandler);
@@ -1396,7 +1306,9 @@ void TextToModelMerger::syncNode(ModelNode &modelNode,
differenceHandler.propertyAbsentFromQml(modelProperty);
}
+#ifndef QDS_USE_PROJECTSTORAGE
context->leaveScope();
+#endif
}
static QVariant parsePropertyExpression(AST::ExpressionNode *expressionNode)
@@ -1476,9 +1388,8 @@ QmlDesigner::PropertyName TextToModelMerger::syncScriptBinding(ModelNode &modelN
}
if (isLiteralValue(script)) {
- if (isPropertyChangesType(modelNode.type())
- || isConnectionsType(modelNode.type())
- || isListElementType(modelNode.type())) {
+ if (isPropertyChangesType(modelNode.type()) || isConnectionsType(modelNode.type())
+ || isListElementType(modelNode.type())) {
AbstractProperty modelProperty = modelNode.property(astPropertyName.toUtf8());
QVariant variantValue = parsePropertyScriptBinding(script);
if (!variantValue.isValid())
@@ -1512,15 +1423,14 @@ QmlDesigner::PropertyName TextToModelMerger::syncScriptBinding(ModelNode &modelN
syncVariantProperty(modelProperty, enumValue, TypeName(), differenceHandler); // TODO: parse type
return astPropertyName.toUtf8();
} else { // Not an enum, so:
- if (isPropertyChangesType(modelNode.type())
- || isConnectionsType(modelNode.type())
- || context->lookupProperty(prefix, script->qualifiedId)
- || isSupportedAttachedProperties(astPropertyName)) {
+ if (isPropertyChangesType(modelNode.type()) || isConnectionsType(modelNode.type())
+ || isSupportedAttachedProperties(astPropertyName)
+ || modelNode.metaInfo().hasProperty(astPropertyName.toUtf8())) {
AbstractProperty modelProperty = modelNode.property(astPropertyName.toUtf8());
syncExpressionProperty(modelProperty, astValue, TypeName(), differenceHandler); // TODO: parse type
return astPropertyName.toUtf8();
} else {
- qWarning() << Q_FUNC_INFO << "Skipping invalid expression property" << astPropertyName
+ qCInfo(texttomodelMergerLog) << Q_FUNC_INFO << "\nSkipping invalid expression property" << astPropertyName
<< "for node type" << modelNode.type();
return PropertyName();
}
@@ -1655,7 +1565,7 @@ void TextToModelMerger::syncVariantProperty(AbstractProperty &modelProperty,
const TypeName &astType,
DifferenceHandler &differenceHandler)
{
- if (astValue.canConvert(QMetaType::QString))
+ if (astValue.canConvert(QMetaType(QMetaType::QString)))
populateQrcMapping(astValue.toString());
if (modelProperty.isVariantProperty()) {
@@ -2232,42 +2142,31 @@ void TextToModelMerger::collectImportErrors(QList<DocumentMessage> *errors)
bool hasQtQuick = false;
for (const QmlDesigner::Import &import : m_rewriterView->model()->imports()) {
if (import.isLibraryImport() && import.url() == u"QtQuick") {
- if (supportedQtQuickVersion(import)) {
- hasQtQuick = true;
-
- auto &externalDependencies = m_rewriterView->externalDependencies();
- if (externalDependencies.hasStartupTarget()) {
- const bool qt6import = !import.hasVersion() || import.majorVersion() == 6;
-
- if (!externalDependencies.isQt6Import() && (m_hasVersionlessImport || qt6import)) {
- const QmlJS::DiagnosticMessage diagnosticMessage(
- QmlJS::Severity::Error,
- SourceLocation(0, 0, 0, 0),
- QCoreApplication::translate(
- "QmlDesigner::TextToModelMerger",
- "Qt Quick 6 is not supported with a Qt 5 kit."));
- errors->prepend(
- DocumentMessage(diagnosticMessage,
- QUrl::fromLocalFile(m_document->fileName().path())));
- }
- } else {
+ hasQtQuick = true;
+
+ auto &externalDependencies = m_rewriterView->externalDependencies();
+ if (externalDependencies.hasStartupTarget()) {
+ const bool qt6import = !import.hasVersion() || import.majorVersion() == 6;
+
+ if (!externalDependencies.isQt6Import() && (m_hasVersionlessImport || qt6import)) {
const QmlJS::DiagnosticMessage diagnosticMessage(
QmlJS::Severity::Error,
SourceLocation(0, 0, 0, 0),
- QCoreApplication::translate("QmlDesigner::TextToModelMerger",
- "The Design Mode requires a valid Qt kit."));
+ QCoreApplication::translate(
+ "QmlDesigner::TextToModelMerger",
+ "Qt Quick 6 is not supported with a Qt 5 kit."));
errors->prepend(
DocumentMessage(diagnosticMessage,
QUrl::fromLocalFile(m_document->fileName().path())));
}
} else {
- const QmlJS::DiagnosticMessage
- diagnosticMessage(QmlJS::Severity::Error,
- SourceLocation(0, 0, 0, 0),
- QCoreApplication::translate("QmlDesigner::TextToModelMerger",
- "Unsupported Qt Quick version."));
- errors->append(DocumentMessage(diagnosticMessage,
- QUrl::fromLocalFile(m_document->fileName().path())));
+ const QmlJS::DiagnosticMessage diagnosticMessage(
+ QmlJS::Severity::Error,
+ SourceLocation(0, 0, 0, 0),
+ QCoreApplication::translate("QmlDesigner::TextToModelMerger",
+ "The Design Mode requires a valid Qt kit."));
+ errors->prepend(DocumentMessage(diagnosticMessage,
+ QUrl::fromLocalFile(m_document->fileName().path())));
}
}
}
@@ -2276,8 +2175,10 @@ void TextToModelMerger::collectImportErrors(QList<DocumentMessage> *errors)
errors->append(DocumentMessage(QCoreApplication::translate("QmlDesigner::TextToModelMerger", "No import for Qt Quick found.")));
}
-void TextToModelMerger::collectSemanticErrorsAndWarnings(QList<DocumentMessage> *errors, QList<DocumentMessage> *warnings)
+void TextToModelMerger::collectSemanticErrorsAndWarnings(
+ [[maybe_unused]] QList<DocumentMessage> *errors, [[maybe_unused]] QList<DocumentMessage> *warnings)
{
+#ifndef QDS_USE_PROJECTSTORAGE
Check check(m_document, m_scopeChain->context());
check.disableMessage(StaticAnalysis::ErrPrototypeCycle);
check.disableMessage(StaticAnalysis::ErrCouldNotResolvePrototype);
@@ -2306,6 +2207,7 @@ void TextToModelMerger::collectSemanticErrorsAndWarnings(QList<DocumentMessage>
if (message.severity == Severity::Warning)
warnings->append(DocumentMessage(message.toDiagnosticMessage(), fileNameUrl));
}
+#endif
}
void TextToModelMerger::populateQrcMapping(const QString &filePath)
@@ -2410,6 +2312,9 @@ QSet<QPair<QString, QString> > TextToModelMerger::qrcMapping() const
QList<QmlTypeData> TextToModelMerger::getQMLSingletons() const
{
+#ifdef QDS_USE_PROJECTSTORAGE
+ return {};
+#else
QList<QmlTypeData> list;
if (!m_scopeChain || !m_scopeChain->document())
return list;
@@ -2440,6 +2345,7 @@ QList<QmlTypeData> TextToModelMerger::getQMLSingletons() const
}
}
return list;
+#endif
}
void TextToModelMerger::clearPossibleImportKeys()
diff --git a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.h b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.h
index f511906040..e22f747718 100644
--- a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.h
+++ b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.h
@@ -37,15 +37,19 @@ public:
bool isActive() const;
void setupImports(const QmlJS::Document::Ptr &doc, DifferenceHandler &differenceHandler);
+#ifndef QDS_USE_PROJECTSTORAGE
void setupPossibleImports();
+#endif
void setupUsedImports();
bool load(const QString &data, DifferenceHandler &differenceHandler);
RewriterView *view() const
{ return m_rewriterView; }
+#ifndef QDS_USE_PROJECTSTORAGE
const QmlJS::ScopeChain *scopeChain() const
{ return m_scopeChain.data(); }
+#endif
const QmlJS::Document *document() const
{ return m_document.data(); }
@@ -141,7 +145,9 @@ private:
private:
RewriterView *m_rewriterView;
bool m_isActive;
+#ifndef QDS_USE_PROJECTSTORAGE
QSharedPointer<const QmlJS::ScopeChain> m_scopeChain;
+#endif
QmlJS::Document::Ptr m_document;
QTimer m_setupTimer;
QSet<ModelNode> m_setupComponentList;
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/commontypecache.h b/src/plugins/qmldesigner/designercore/projectstorage/commontypecache.h
index 03c25dfac7..76305b1fbe 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/commontypecache.h
+++ b/src/plugins/qmldesigner/designercore/projectstorage/commontypecache.h
@@ -84,16 +84,15 @@ inline constexpr char PrincipledMaterial[] = "PrincipledMaterial";
inline constexpr char PropertyAnimation[] = "PropertyAnimation";
inline constexpr char PropertyChanges[] = "PropertyChanges";
inline constexpr char QML[] = "QML";
-inline constexpr char QML_cppnative[] = "QML-cppnative";
inline constexpr char QQuick3DParticleAbstractShape[] = "QQuick3DParticleAbstractShape";
inline constexpr char QQuickStateOperation[] = "QQuickStateOperation";
inline constexpr char QtMultimedia[] = "QtMultimedia";
inline constexpr char QtObject[] = "QtObject";
inline constexpr char QtQml[] = "QtQml";
inline constexpr char QtQml_Models[] = "QtQml.Models";
+inline constexpr char QtQml_XmlListModel[] = "QtQml.XmlListModel";
inline constexpr char QtQuick3D[] = "QtQuick3D";
inline constexpr char QtQuick3D_Particles3D[] = "QtQuick3D.Particles3D";
-inline constexpr char QtQuick3D_Particles3D_cppnative[] = "QtQuick3D.Particles3D-cppnative";
inline constexpr char QtQuick[] = "QtQuick";
inline constexpr char QtQuick_Controls[] = "QtQuick.Controls";
inline constexpr char QtQuick_Dialogs[] = "QtQuick.Dialogs";
@@ -103,7 +102,6 @@ inline constexpr char QtQuick_Studio_Components[] = "QtQuick.Studio.Components";
inline constexpr char QtQuick_Templates[] = "QtQuick.Templates";
inline constexpr char QtQuick_Timeline[] = "QtQuick.Timeline";
inline constexpr char QtQuick_Window[] = "QtQuick.Window";
-inline constexpr char QtQuick_cppnative[] = "QtQuick-cppnative";
inline constexpr char Qt_SafeRenderer[] = "Qt.SafeRenderer";
inline constexpr char Rectangle[] = "Rectangle";
inline constexpr char Repeater[] = "Repeater";
@@ -131,6 +129,7 @@ inline constexpr char Transition[] = "Transition";
inline constexpr char UIntType[] = "uint";
inline constexpr char View3D[] = "View3D";
inline constexpr char Window[] = "Window";
+inline constexpr char XmlListModelRole[] = "XmlListModelRole";
inline constexpr char color[] = "color";
inline constexpr char date[] = "date";
inline constexpr char font[] = "font";
@@ -147,7 +146,7 @@ struct BaseCacheType
QmlDesigner::TypeId typeId;
};
-template<const char *moduleName_, const char *typeName_>
+template<const char *moduleName_, ModuleKind moduleKind, const char *typeName_>
struct CacheType : public BaseCacheType
{
};
@@ -155,105 +154,107 @@ struct CacheType : public BaseCacheType
template<typename ProjectStorage>
class CommonTypeCache
{
- using CommonTypes = std::tuple<CacheType<FlowView, FlowActionArea>,
- CacheType<FlowView, FlowDecision>,
- CacheType<FlowView, FlowItem>,
- CacheType<FlowView, FlowTransition>,
- CacheType<FlowView, FlowView>,
- CacheType<FlowView, FlowWildcard>,
- CacheType<QML, BoolType>,
- CacheType<QML, Component>,
- CacheType<QML, DoubleType>,
- CacheType<QML, IntType>,
- CacheType<QML, QtObject>,
- CacheType<QML, date>,
- CacheType<QML, string>,
- CacheType<QML, url>,
- CacheType<QML, var>,
- CacheType<QML_cppnative, FloatType>,
- CacheType<QML_cppnative, UIntType>,
- CacheType<QtQml, Connections>,
- CacheType<QtMultimedia, SoundEffect>,
- CacheType<QtQml_Models, ListElement>,
- CacheType<QtQml_Models, ListModel>,
- CacheType<QtQuick, BorderImage>,
- CacheType<QtQuick, GridView>,
- CacheType<QtQuick, Image>,
- CacheType<QtQuick, Item>,
- CacheType<QtQuick, ListView>,
- CacheType<QtQuick, Loader>,
- CacheType<QtQuick, MouseArea>,
- CacheType<QtQuick, Path>,
- CacheType<QtQuick, PathView>,
- CacheType<QtQuick, PauseAnimation>,
- CacheType<QtQuick, Positioner>,
- CacheType<QtQuick, PropertyAnimation>,
- CacheType<QtQuick, PropertyChanges>,
- CacheType<QtQuick, Rectangle>,
- CacheType<QtQuick, Repeater>,
- CacheType<QtQuick, State>,
- CacheType<QtQuick, StateGroup>,
- CacheType<QtQuick, Text>,
- CacheType<QtQuick, TextEdit>,
- CacheType<QtQuick, Transition>,
- CacheType<QtQuick, color>,
- CacheType<QtQuick, font>,
- CacheType<QtQuick, vector2d>,
- CacheType<QtQuick, vector3d>,
- CacheType<QtQuick, vector4d>,
- CacheType<QtQuick3D, BakedLightmap>,
- CacheType<QtQuick3D, Buffer>,
- CacheType<QtQuick3D, Camera>,
- CacheType<QtQuick3D, Command>,
- CacheType<QtQuick3D, CubeMapTexture>,
- CacheType<QtQuick3D, DefaultMaterial>,
- CacheType<QtQuick3D, DirectionalLight>,
- CacheType<QtQuick3D, Effect>,
- CacheType<QtQuick3D, InstanceList>,
- CacheType<QtQuick3D, InstanceListEntry>,
- CacheType<QtQuick3D, Light>,
- CacheType<QtQuick3D, Material>,
- CacheType<QtQuick3D, Model>,
- CacheType<QtQuick3D, Node>,
- CacheType<QtQuick3D, OrthographicCamera>,
- CacheType<QtQuick3D, Pass>,
- CacheType<QtQuick3D, PerspectiveCamera>,
- CacheType<QtQuick3D, PointLight>,
- CacheType<QtQuick3D, PrincipledMaterial>,
- CacheType<QtQuick3D, SceneEnvironment>,
- CacheType<QtQuick3D, Shader>,
- CacheType<QtQuick3D, SpecularGlossyMaterial>,
- CacheType<QtQuick3D, SpotLight>,
- CacheType<QtQuick3D, Texture>,
- CacheType<QtQuick3D, TextureInput>,
- CacheType<QtQuick3D, View3D>,
- CacheType<QtQuick3D_Particles3D, Affector3D>,
- CacheType<QtQuick3D_Particles3D, Attractor3D>,
- CacheType<QtQuick3D_Particles3D, Model>,
- CacheType<QtQuick3D_Particles3D, Particle3D>,
- CacheType<QtQuick3D_Particles3D, ParticleEmitter3D>,
- CacheType<QtQuick3D_Particles3D, SpriteParticle3D>,
- CacheType<QtQuick3D_Particles3D_cppnative, QQuick3DParticleAbstractShape>,
- CacheType<QtQuick_Controls, Control>,
- CacheType<QtQuick_Controls, Popup>,
- CacheType<QtQuick_Controls, SplitView>,
- CacheType<QtQuick_Controls, SwipeView>,
- CacheType<QtQuick_Controls, TabBar>,
- CacheType<QtQuick_Controls, TextArea>,
- CacheType<QtQuick_Dialogs, Dialog>,
- CacheType<QtQuick_Extras, Picture>,
- CacheType<QtQuick_Layouts, Layout>,
- CacheType<QtQuick_Studio_Components, GroupItem>,
- CacheType<QtQuick_Studio_Components, JsonListModel>,
- CacheType<QtQuick_Templates, Control>,
- CacheType<QtQuick_Timeline, Keyframe>,
- CacheType<QtQuick_Timeline, KeyframeGroup>,
- CacheType<QtQuick_Timeline, Timeline>,
- CacheType<QtQuick_Timeline, TimelineAnimation>,
- CacheType<QtQuick_cppnative, QQuickStateOperation>,
- CacheType<Qt_SafeRenderer, SafePicture>,
- CacheType<Qt_SafeRenderer, SafeRendererPicture>,
- CacheType<QtQuick_Window, Window>>;
+ using CommonTypes = std::tuple<
+ CacheType<FlowView, ModuleKind::QmlLibrary, FlowActionArea>,
+ CacheType<FlowView, ModuleKind::QmlLibrary, FlowDecision>,
+ CacheType<FlowView, ModuleKind::QmlLibrary, FlowItem>,
+ CacheType<FlowView, ModuleKind::QmlLibrary, FlowTransition>,
+ CacheType<FlowView, ModuleKind::QmlLibrary, FlowView>,
+ CacheType<FlowView, ModuleKind::QmlLibrary, FlowWildcard>,
+ CacheType<QML, ModuleKind::QmlLibrary, BoolType>,
+ CacheType<QML, ModuleKind::QmlLibrary, Component>,
+ CacheType<QML, ModuleKind::QmlLibrary, DoubleType>,
+ CacheType<QML, ModuleKind::QmlLibrary, IntType>,
+ CacheType<QML, ModuleKind::QmlLibrary, QtObject>,
+ CacheType<QML, ModuleKind::QmlLibrary, date>,
+ CacheType<QML, ModuleKind::QmlLibrary, string>,
+ CacheType<QML, ModuleKind::QmlLibrary, url>,
+ CacheType<QML, ModuleKind::QmlLibrary, var>,
+ CacheType<QML, ModuleKind::CppLibrary, FloatType>,
+ CacheType<QML, ModuleKind::CppLibrary, UIntType>,
+ CacheType<QtQml, ModuleKind::QmlLibrary, Connections>,
+ CacheType<QtMultimedia, ModuleKind::QmlLibrary, SoundEffect>,
+ CacheType<QtQml_Models, ModuleKind::QmlLibrary, ListElement>,
+ CacheType<QtQml_Models, ModuleKind::QmlLibrary, ListModel>,
+ CacheType<QtQml_XmlListModel, ModuleKind::QmlLibrary, XmlListModelRole>,
+ CacheType<QtQuick, ModuleKind::QmlLibrary, BorderImage>,
+ CacheType<QtQuick, ModuleKind::QmlLibrary, GridView>,
+ CacheType<QtQuick, ModuleKind::QmlLibrary, Image>,
+ CacheType<QtQuick, ModuleKind::QmlLibrary, Item>,
+ CacheType<QtQuick, ModuleKind::QmlLibrary, ListView>,
+ CacheType<QtQuick, ModuleKind::QmlLibrary, Loader>,
+ CacheType<QtQuick, ModuleKind::QmlLibrary, MouseArea>,
+ CacheType<QtQuick, ModuleKind::QmlLibrary, Path>,
+ CacheType<QtQuick, ModuleKind::QmlLibrary, PathView>,
+ CacheType<QtQuick, ModuleKind::QmlLibrary, PauseAnimation>,
+ CacheType<QtQuick, ModuleKind::QmlLibrary, Positioner>,
+ CacheType<QtQuick, ModuleKind::QmlLibrary, PropertyAnimation>,
+ CacheType<QtQuick, ModuleKind::QmlLibrary, PropertyChanges>,
+ CacheType<QtQuick, ModuleKind::QmlLibrary, Rectangle>,
+ CacheType<QtQuick, ModuleKind::QmlLibrary, Repeater>,
+ CacheType<QtQuick, ModuleKind::QmlLibrary, State>,
+ CacheType<QtQuick, ModuleKind::QmlLibrary, StateGroup>,
+ CacheType<QtQuick, ModuleKind::QmlLibrary, Text>,
+ CacheType<QtQuick, ModuleKind::QmlLibrary, TextEdit>,
+ CacheType<QtQuick, ModuleKind::QmlLibrary, Transition>,
+ CacheType<QtQuick, ModuleKind::QmlLibrary, color>,
+ CacheType<QtQuick, ModuleKind::QmlLibrary, font>,
+ CacheType<QtQuick, ModuleKind::QmlLibrary, vector2d>,
+ CacheType<QtQuick, ModuleKind::QmlLibrary, vector3d>,
+ CacheType<QtQuick, ModuleKind::QmlLibrary, vector4d>,
+ CacheType<QtQuick3D, ModuleKind::QmlLibrary, BakedLightmap>,
+ CacheType<QtQuick3D, ModuleKind::QmlLibrary, Buffer>,
+ CacheType<QtQuick3D, ModuleKind::QmlLibrary, Camera>,
+ CacheType<QtQuick3D, ModuleKind::QmlLibrary, Command>,
+ CacheType<QtQuick3D, ModuleKind::QmlLibrary, CubeMapTexture>,
+ CacheType<QtQuick3D, ModuleKind::QmlLibrary, DefaultMaterial>,
+ CacheType<QtQuick3D, ModuleKind::QmlLibrary, DirectionalLight>,
+ CacheType<QtQuick3D, ModuleKind::QmlLibrary, Effect>,
+ CacheType<QtQuick3D, ModuleKind::QmlLibrary, InstanceList>,
+ CacheType<QtQuick3D, ModuleKind::QmlLibrary, InstanceListEntry>,
+ CacheType<QtQuick3D, ModuleKind::QmlLibrary, Light>,
+ CacheType<QtQuick3D, ModuleKind::QmlLibrary, Material>,
+ CacheType<QtQuick3D, ModuleKind::QmlLibrary, Model>,
+ CacheType<QtQuick3D, ModuleKind::QmlLibrary, Node>,
+ CacheType<QtQuick3D, ModuleKind::QmlLibrary, OrthographicCamera>,
+ CacheType<QtQuick3D, ModuleKind::QmlLibrary, Pass>,
+ CacheType<QtQuick3D, ModuleKind::QmlLibrary, PerspectiveCamera>,
+ CacheType<QtQuick3D, ModuleKind::QmlLibrary, PointLight>,
+ CacheType<QtQuick3D, ModuleKind::QmlLibrary, PrincipledMaterial>,
+ CacheType<QtQuick3D, ModuleKind::QmlLibrary, SceneEnvironment>,
+ CacheType<QtQuick3D, ModuleKind::QmlLibrary, Shader>,
+ CacheType<QtQuick3D, ModuleKind::QmlLibrary, SpecularGlossyMaterial>,
+ CacheType<QtQuick3D, ModuleKind::QmlLibrary, SpotLight>,
+ CacheType<QtQuick3D, ModuleKind::QmlLibrary, Texture>,
+ CacheType<QtQuick3D, ModuleKind::QmlLibrary, TextureInput>,
+ CacheType<QtQuick3D, ModuleKind::QmlLibrary, View3D>,
+ CacheType<QtQuick3D_Particles3D, ModuleKind::QmlLibrary, Affector3D>,
+ CacheType<QtQuick3D_Particles3D, ModuleKind::QmlLibrary, Attractor3D>,
+ CacheType<QtQuick3D_Particles3D, ModuleKind::QmlLibrary, Model>,
+ CacheType<QtQuick3D_Particles3D, ModuleKind::QmlLibrary, Particle3D>,
+ CacheType<QtQuick3D_Particles3D, ModuleKind::QmlLibrary, ParticleEmitter3D>,
+ CacheType<QtQuick3D_Particles3D, ModuleKind::QmlLibrary, SpriteParticle3D>,
+ CacheType<QtQuick3D_Particles3D, ModuleKind::CppLibrary, QQuick3DParticleAbstractShape>,
+ CacheType<QtQuick_Controls, ModuleKind::QmlLibrary, Control>,
+ CacheType<QtQuick_Controls, ModuleKind::QmlLibrary, Popup>,
+ CacheType<QtQuick_Controls, ModuleKind::QmlLibrary, SplitView>,
+ CacheType<QtQuick_Controls, ModuleKind::QmlLibrary, SwipeView>,
+ CacheType<QtQuick_Controls, ModuleKind::QmlLibrary, TabBar>,
+ CacheType<QtQuick_Controls, ModuleKind::QmlLibrary, TextArea>,
+ CacheType<QtQuick_Dialogs, ModuleKind::QmlLibrary, Dialog>,
+ CacheType<QtQuick_Extras, ModuleKind::QmlLibrary, Picture>,
+ CacheType<QtQuick_Layouts, ModuleKind::QmlLibrary, Layout>,
+ CacheType<QtQuick_Studio_Components, ModuleKind::QmlLibrary, GroupItem>,
+ CacheType<QtQuick_Studio_Components, ModuleKind::QmlLibrary, JsonListModel>,
+ CacheType<QtQuick_Templates, ModuleKind::QmlLibrary, Control>,
+ CacheType<QtQuick_Timeline, ModuleKind::QmlLibrary, Keyframe>,
+ CacheType<QtQuick_Timeline, ModuleKind::QmlLibrary, KeyframeGroup>,
+ CacheType<QtQuick_Timeline, ModuleKind::QmlLibrary, Timeline>,
+ CacheType<QtQuick_Timeline, ModuleKind::QmlLibrary, TimelineAnimation>,
+ CacheType<QtQuick, ModuleKind::CppLibrary, QQuickStateOperation>,
+ CacheType<Qt_SafeRenderer, ModuleKind::QmlLibrary, SafePicture>,
+ CacheType<Qt_SafeRenderer, ModuleKind::QmlLibrary, SafeRendererPicture>,
+ CacheType<QtQuick_Window, ModuleKind::QmlLibrary, Window>>;
public:
CommonTypeCache(const ProjectStorage &projectStorage)
@@ -280,14 +281,14 @@ public:
std::fill(std::begin(m_typesWithoutProperties), std ::end(m_typesWithoutProperties), TypeId{});
}
- template<const char *moduleName, const char *typeName>
+ template<const char *moduleName, const char *typeName, ModuleKind moduleKind = ModuleKind::QmlLibrary>
TypeId typeId() const
{
- auto &type = std::get<CacheType<moduleName, typeName>>(m_types);
+ auto &type = std::get<CacheType<moduleName, moduleKind, typeName>>(m_types);
if (type.typeId)
return type.typeId;
- return refreshTypedId(type, moduleName, typeName);
+ return refreshTypedId(type, moduleName, moduleKind, typeName);
}
template<const char *typeName>
@@ -304,11 +305,11 @@ public:
else if constexpr (std::is_same_v<Type, int>)
return typeId<QML, IntType>();
else if constexpr (std::is_same_v<Type, uint>)
- return typeId<QML_cppnative, UIntType>();
+ return typeId<QML, UIntType, ModuleKind::CppLibrary>();
else if constexpr (std::is_same_v<Type, bool>)
return typeId<QML, BoolType>();
else if constexpr (std::is_same_v<Type, float>)
- return typeId<QML_cppnative, FloatType>();
+ return typeId<QML, FloatType, ModuleKind::CppLibrary>();
else if constexpr (std::is_same_v<Type, QString>)
return typeId<QML, string>();
else if constexpr (std::is_same_v<Type, QDateTime>)
@@ -338,10 +339,11 @@ public:
private:
TypeId refreshTypedId(BaseCacheType &type,
::Utils::SmallStringView moduleName,
+ ModuleKind moduleKind,
::Utils::SmallStringView typeName) const
{
if (!type.moduleId)
- type.moduleId = m_projectStorage.moduleId(moduleName);
+ type.moduleId = m_projectStorage.moduleId(moduleName, moduleKind);
type.typeId = m_projectStorage.typeId(type.moduleId, typeName, Storage::Version{});
@@ -350,10 +352,11 @@ private:
TypeId refreshTypedIdWithoutTransaction(BaseCacheType &type,
::Utils::SmallStringView moduleName,
- ::Utils::SmallStringView typeName) const
+ ::Utils::SmallStringView typeName,
+ ModuleKind moduleKind) const
{
if (!type.moduleId)
- type.moduleId = m_projectStorage.fetchModuleIdUnguarded(moduleName);
+ type.moduleId = m_projectStorage.fetchModuleIdUnguarded(moduleName, moduleKind);
type.typeId = m_projectStorage.fetchTypeIdByModuleIdAndExportedName(type.moduleId, typeName);
@@ -368,26 +371,27 @@ private:
std::copy(std::begin(typeIds), std::end(typeIds), std::begin(m_typesWithoutProperties));
}
- template<const char *moduleName, const char *typeName>
+ template<const char *moduleName, const char *typeName, ModuleKind moduleKind = ModuleKind::QmlLibrary>
TypeId typeIdWithoutTransaction() const
{
- auto &type = std::get<CacheType<moduleName, typeName>>(m_types);
+ auto &type = std::get<CacheType<moduleName, moduleKind, typeName>>(m_types);
if (type.typeId)
return type.typeId;
- return refreshTypedIdWithoutTransaction(type, moduleName, typeName);
+ return refreshTypedIdWithoutTransaction(type, moduleName, typeName, moduleKind);
}
void updateTypeIdsWithoutProperties()
{
- setupTypeIdsWithoutProperties({typeIdWithoutTransaction<QML, BoolType>(),
- typeIdWithoutTransaction<QML, IntType>(),
- typeIdWithoutTransaction<QML_cppnative, UIntType>(),
- typeIdWithoutTransaction<QML, DoubleType>(),
- typeIdWithoutTransaction<QML_cppnative, FloatType>(),
- typeIdWithoutTransaction<QML, date>(),
- typeIdWithoutTransaction<QML, string>(),
- typeIdWithoutTransaction<QML, url>()});
+ setupTypeIdsWithoutProperties(
+ {typeIdWithoutTransaction<QML, BoolType>(),
+ typeIdWithoutTransaction<QML, IntType>(),
+ typeIdWithoutTransaction<QML, UIntType, ModuleKind::CppLibrary>(),
+ typeIdWithoutTransaction<QML, DoubleType>(),
+ typeIdWithoutTransaction<QML, FloatType, ModuleKind::CppLibrary>(),
+ typeIdWithoutTransaction<QML, date>(),
+ typeIdWithoutTransaction<QML, string>(),
+ typeIdWithoutTransaction<QML, url>()});
}
private:
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/filestatus.h b/src/plugins/qmldesigner/designercore/projectstorage/filestatus.h
index f3e275b8f3..48b3ba2700 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/filestatus.h
+++ b/src/plugins/qmldesigner/designercore/projectstorage/filestatus.h
@@ -50,6 +50,18 @@ public:
explicit operator bool() const { return isValid(); }
+ template<typename String>
+ friend void convertToString(String &string, const FileStatus &fileStatus)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("source id", fileStatus.sourceId),
+ keyValue("size", fileStatus.size),
+ keyValue("last modified", fileStatus.lastModified));
+
+ convertToString(string, dict);
+ }
+
public:
SourceId sourceId;
long long size = -1;
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/filesystem.cpp b/src/plugins/qmldesigner/designercore/projectstorage/filesystem.cpp
index 1376b2c3d9..d11190fdc7 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/filesystem.cpp
+++ b/src/plugins/qmldesigner/designercore/projectstorage/filesystem.cpp
@@ -11,6 +11,7 @@
#include <QDateTime>
#include <QDir>
+#include <QDirIterator>
#include <QFileInfo>
namespace QmlDesigner {
@@ -69,6 +70,18 @@ QString FileSystem::contentAsQString(const QString &filePath) const
return {};
}
+QStringList FileSystem::subdirectories(const QString &directoryPath) const
+{
+ QStringList directoryPaths;
+ directoryPaths.reserve(100);
+ QDirIterator directoryIterator{directoryPath, QDir::Dirs | QDir::NoDotAndDotDot};
+
+ while (directoryIterator.hasNext())
+ directoryPaths.push_back(directoryIterator.next());
+
+ return directoryPaths;
+}
+
void FileSystem::remove(const SourceIds &sourceIds)
{
for (SourceId sourceId : sourceIds)
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/filesystem.h b/src/plugins/qmldesigner/designercore/projectstorage/filesystem.h
index 078fd1ee98..1c881741c6 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/filesystem.h
+++ b/src/plugins/qmldesigner/designercore/projectstorage/filesystem.h
@@ -6,6 +6,7 @@
#include "filestatuscache.h"
#include "filesysteminterface.h"
#include "nonlockingmutex.h"
+#include "projectstoragefwd.h"
namespace Sqlite {
class Database;
@@ -16,12 +17,9 @@ namespace QmlDesigner {
template<typename ProjectStorage, typename Mutex>
class SourcePathCache;
-template<typename Database>
-class ProjectStorage;
-
class FileSystem : public FileSystemInterface
{
- using PathCache = SourcePathCache<ProjectStorage<Sqlite::Database>, NonLockingMutex>;
+ using PathCache = SourcePathCache<ProjectStorage, NonLockingMutex>;
public:
FileSystem(PathCache &sourcePathCache)
@@ -33,6 +31,7 @@ public:
long long lastModified(SourceId sourceId) const override;
FileStatus fileStatus(SourceId sourceId) const override;
QString contentAsQString(const QString &filePath) const override;
+ QStringList subdirectories(const QString &directoryPath) const override;
void remove(const SourceIds &sourceIds) override;
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/filesysteminterface.h b/src/plugins/qmldesigner/designercore/projectstorage/filesysteminterface.h
index 6a7c964fa6..ff7608c9a3 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/filesysteminterface.h
+++ b/src/plugins/qmldesigner/designercore/projectstorage/filesysteminterface.h
@@ -20,6 +20,7 @@ public:
virtual FileStatus fileStatus(SourceId sourceId) const = 0;
virtual void remove(const SourceIds &sourceIds) = 0;
virtual QString contentAsQString(const QString &filePath) const = 0;
+ virtual QStringList subdirectories(const QString &directoryPath) const = 0;
protected:
~FileSystemInterface() = default;
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstorage.cpp b/src/plugins/qmldesigner/designercore/projectstorage/projectstorage.cpp
index 3e493e8772..2283b64945 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/projectstorage.cpp
+++ b/src/plugins/qmldesigner/designercore/projectstorage/projectstorage.cpp
@@ -3,20 +3,4896 @@
#include "projectstorage.h"
-#include <tracing/qmldesignertracing.h>
-
#include <sqlitedatabase.h>
namespace QmlDesigner {
-NanotraceHR::StringViewCategory<projectStorageTracingStatus()> &projectStorageCategory()
+enum class SpecialIdState { Unresolved = -1 };
+
+constexpr TypeId unresolvedTypeId = TypeId::createSpecialState(SpecialIdState::Unresolved);
+
+class UnresolvedTypeId : public TypeId
+{
+public:
+ constexpr UnresolvedTypeId()
+ : TypeId{TypeId::createSpecialState(SpecialIdState::Unresolved)}
+ {}
+
+ static constexpr UnresolvedTypeId create(DatabaseType idNumber)
+ {
+ UnresolvedTypeId id;
+ id.id = idNumber;
+ return id;
+ }
+};
+
+struct ProjectStorage::Statements
{
- thread_local NanotraceHR::StringViewCategory<projectStorageTracingStatus()>
- projectStorageCategory_{"project storage"_t, Tracing::eventQueue(), projectStorageCategory};
+ Statements(Sqlite::Database &database)
+ : database{database}
+ {}
+
+ Sqlite::Database &database;
+ Sqlite::ReadWriteStatement<1, 2> insertTypeStatement{
+ "INSERT OR IGNORE INTO types(sourceId, name) VALUES(?1, ?2) RETURNING typeId", database};
+ Sqlite::WriteStatement<5> updatePrototypeAndExtensionStatement{
+ "UPDATE types "
+ "SET prototypeId=?2, prototypeNameId=?3, extensionId=?4, extensionNameId=?5 "
+ "WHERE typeId=?1 AND ( "
+ " prototypeId IS NOT ?2 "
+ " OR extensionId IS NOT ?3 "
+ " OR prototypeId IS NOT ?4 "
+ " OR extensionNameId IS NOT ?5)",
+ database};
+ mutable Sqlite::ReadStatement<1, 1> selectTypeIdByExportedNameStatement{
+ "SELECT typeId FROM exportedTypeNames WHERE name=?1", database};
+ mutable Sqlite::ReadStatement<1, 2> selectTypeIdByModuleIdAndExportedNameStatement{
+ "SELECT typeId FROM exportedTypeNames "
+ "WHERE moduleId=?1 AND name=?2 "
+ "ORDER BY majorVersion DESC, minorVersion DESC "
+ "LIMIT 1",
+ database};
+ mutable Sqlite::ReadStatement<1, 3> selectTypeIdByModuleIdAndExportedNameAndMajorVersionStatement{
+ "SELECT typeId FROM exportedTypeNames "
+ "WHERE moduleId=?1 AND name=?2 AND majorVersion=?3"
+ "ORDER BY minorVersion DESC "
+ "LIMIT 1",
+ database};
+ mutable Sqlite::ReadStatement<1, 4> selectTypeIdByModuleIdAndExportedNameAndVersionStatement{
+ "SELECT typeId FROM exportedTypeNames "
+ "WHERE moduleId=?1 AND name=?2 AND majorVersion=?3 AND minorVersion<=?4"
+ "ORDER BY minorVersion DESC "
+ "LIMIT 1",
+ database};
+ mutable Sqlite::ReadStatement<3, 1> selectPropertyDeclarationResultByPropertyDeclarationIdStatement{
+ "SELECT propertyTypeId, propertyDeclarationId, propertyTraits "
+ "FROM propertyDeclarations "
+ "WHERE propertyDeclarationId=?1 "
+ "LIMIT 1",
+ database};
+ mutable Sqlite::ReadStatement<1, 1> selectSourceContextIdFromSourceContextsBySourceContextPathStatement{
+ "SELECT sourceContextId FROM sourceContexts WHERE sourceContextPath = ?", database};
+ mutable Sqlite::ReadStatement<1, 1> selectSourceContextPathFromSourceContextsBySourceContextIdStatement{
+ "SELECT sourceContextPath FROM sourceContexts WHERE sourceContextId = ?", database};
+ mutable Sqlite::ReadStatement<2> selectAllSourceContextsStatement{
+ "SELECT sourceContextPath, sourceContextId FROM sourceContexts", database};
+ Sqlite::WriteStatement<1> insertIntoSourceContextsStatement{
+ "INSERT INTO sourceContexts(sourceContextPath) VALUES (?)", database};
+ mutable Sqlite::ReadStatement<1, 2> selectSourceIdFromSourcesBySourceContextIdAndSourceNameStatement{
+ "SELECT sourceId FROM sources WHERE sourceContextId = ? AND sourceName = ?", database};
+ mutable Sqlite::ReadStatement<2, 1> selectSourceNameAndSourceContextIdFromSourcesBySourceIdStatement{
+ "SELECT sourceName, sourceContextId FROM sources WHERE sourceId = ?", database};
+ mutable Sqlite::ReadStatement<1, 1> selectSourceContextIdFromSourcesBySourceIdStatement{
+ "SELECT sourceContextId FROM sources WHERE sourceId = ?", database};
+ Sqlite::WriteStatement<2> insertIntoSourcesStatement{
+ "INSERT INTO sources(sourceContextId, sourceName) VALUES (?,?)", database};
+ mutable Sqlite::ReadStatement<3> selectAllSourcesStatement{
+ "SELECT sourceName, sourceContextId, sourceId FROM sources", database};
+ mutable Sqlite::ReadStatement<8, 1> selectTypeByTypeIdStatement{
+ "SELECT sourceId, t.name, t.typeId, prototypeId, extensionId, traits, annotationTraits, "
+ "pd.name "
+ "FROM types AS t LEFT JOIN propertyDeclarations AS pd ON "
+ "defaultPropertyId=propertyDeclarationId "
+ "WHERE t.typeId=?",
+ database};
+ mutable Sqlite::ReadStatement<4, 1> selectExportedTypesByTypeIdStatement{
+ "SELECT moduleId, name, ifnull(majorVersion, -1), ifnull(minorVersion, -1) FROM "
+ "exportedTypeNames WHERE typeId=?",
+ database};
+ mutable Sqlite::ReadStatement<4, 2> selectExportedTypesByTypeIdAndSourceIdStatement{
+ "SELECT etn.moduleId, name, ifnull(etn.majorVersion, -1), ifnull(etn.minorVersion, -1) "
+ "FROM exportedTypeNames AS etn JOIN documentImports USING(moduleId) WHERE typeId=?1 AND "
+ "sourceId=?2",
+ database};
+ mutable Sqlite::ReadStatement<8> selectTypesStatement{
+ "SELECT sourceId, t.name, t.typeId, prototypeId, extensionId, traits, annotationTraits, "
+ "pd.name "
+ "FROM types AS t LEFT JOIN propertyDeclarations AS pd ON "
+ "defaultPropertyId=propertyDeclarationId",
+ database};
+ Sqlite::WriteStatement<2> updateTypeTraitStatement{
+ "UPDATE types SET traits = ?2 WHERE typeId=?1", database};
+ Sqlite::WriteStatement<2> updateTypeAnnotationTraitStatement{
+ "WITH RECURSIVE "
+ " typeSelection(typeId) AS ("
+ " VALUES(?1) "
+ " UNION ALL "
+ " SELECT t.typeId "
+ " FROM types AS t JOIN typeSelection AS ts "
+ " WHERE prototypeId=ts.typeId "
+ " AND t.typeId NOT IN (SELECT typeId FROM typeAnnotations)) "
+ "UPDATE types AS t "
+ "SET annotationTraits = ?2 "
+ "FROM typeSelection ts "
+ "WHERE t.typeId=ts.typeId",
+ database};
+ Sqlite::ReadStatement<1, 2> selectNotUpdatedTypesInSourcesStatement{
+ "SELECT DISTINCT typeId FROM types WHERE (sourceId IN carray(?1) AND typeId NOT IN "
+ "carray(?2))",
+ database};
+ Sqlite::WriteStatement<1> deleteTypeNamesByTypeIdStatement{
+ "DELETE FROM exportedTypeNames WHERE typeId=?", database};
+ Sqlite::WriteStatement<1> deleteEnumerationDeclarationByTypeIdStatement{
+ "DELETE FROM enumerationDeclarations WHERE typeId=?", database};
+ Sqlite::WriteStatement<1> deletePropertyDeclarationByTypeIdStatement{
+ "DELETE FROM propertyDeclarations WHERE typeId=?", database};
+ Sqlite::WriteStatement<1> deleteFunctionDeclarationByTypeIdStatement{
+ "DELETE FROM functionDeclarations WHERE typeId=?", database};
+ Sqlite::WriteStatement<1> deleteSignalDeclarationByTypeIdStatement{
+ "DELETE FROM signalDeclarations WHERE typeId=?", database};
+ Sqlite::WriteStatement<1> deleteTypeStatement{"DELETE FROM types WHERE typeId=?", database};
+ mutable Sqlite::ReadStatement<4, 1> selectPropertyDeclarationsByTypeIdStatement{
+ "SELECT name, propertyTypeId, propertyTraits, (SELECT name FROM "
+ "propertyDeclarations WHERE propertyDeclarationId=pd.aliasPropertyDeclarationId) FROM "
+ "propertyDeclarations AS pd WHERE typeId=?",
+ database};
+ Sqlite::ReadStatement<6, 1> selectPropertyDeclarationsForTypeIdStatement{
+ "SELECT name, propertyTraits, propertyTypeId, propertyImportedTypeNameId, "
+ "propertyDeclarationId, aliasPropertyDeclarationId FROM propertyDeclarations "
+ "WHERE typeId=? ORDER BY name",
+ database};
+ Sqlite::ReadWriteStatement<1, 5> insertPropertyDeclarationStatement{
+ "INSERT INTO propertyDeclarations(typeId, name, propertyTypeId, propertyTraits, "
+ "propertyImportedTypeNameId, aliasPropertyDeclarationId) VALUES(?1, ?2, ?3, ?4, ?5, NULL) "
+ "RETURNING propertyDeclarationId",
+ database};
+ Sqlite::WriteStatement<4> updatePropertyDeclarationStatement{
+ "UPDATE propertyDeclarations SET propertyTypeId=?2, propertyTraits=?3, "
+ "propertyImportedTypeNameId=?4, aliasPropertyDeclarationId=NULL WHERE "
+ "propertyDeclarationId=?1",
+ database};
+ Sqlite::WriteStatement<3> updatePropertyAliasDeclarationRecursivelyWithTypeAndTraitsStatement{
+ "WITH RECURSIVE "
+ " properties(aliasPropertyDeclarationId) AS ( "
+ " SELECT propertyDeclarationId FROM propertyDeclarations WHERE "
+ " aliasPropertyDeclarationId=?1 "
+ " UNION ALL "
+ " SELECT pd.propertyDeclarationId FROM "
+ " propertyDeclarations AS pd JOIN properties USING(aliasPropertyDeclarationId)) "
+ "UPDATE propertyDeclarations AS pd "
+ "SET propertyTypeId=?2, propertyTraits=?3 "
+ "FROM properties AS p "
+ "WHERE pd.propertyDeclarationId=p.aliasPropertyDeclarationId",
+ database};
+ Sqlite::WriteStatement<1> updatePropertyAliasDeclarationRecursivelyStatement{
+ "WITH RECURSIVE "
+ " propertyValues(propertyTypeId, propertyTraits) AS ("
+ " SELECT propertyTypeId, propertyTraits FROM propertyDeclarations "
+ " WHERE propertyDeclarationId=?1), "
+ " properties(aliasPropertyDeclarationId) AS ( "
+ " SELECT propertyDeclarationId FROM propertyDeclarations WHERE "
+ " aliasPropertyDeclarationId=?1 "
+ " UNION ALL "
+ " SELECT pd.propertyDeclarationId FROM "
+ " propertyDeclarations AS pd JOIN properties USING(aliasPropertyDeclarationId)) "
+ "UPDATE propertyDeclarations AS pd "
+ "SET propertyTypeId=pv.propertyTypeId, propertyTraits=pv.propertyTraits "
+ "FROM properties AS p, propertyValues AS pv "
+ "WHERE pd.propertyDeclarationId=p.aliasPropertyDeclarationId",
+ database};
+ Sqlite::WriteStatement<1> deletePropertyDeclarationStatement{
+ "DELETE FROM propertyDeclarations WHERE propertyDeclarationId=?", database};
+ Sqlite::ReadStatement<3, 1> selectPropertyDeclarationsWithAliasForTypeIdStatement{
+ "SELECT name, propertyDeclarationId, aliasPropertyDeclarationId FROM propertyDeclarations "
+ "WHERE typeId=? AND aliasPropertyDeclarationId IS NOT NULL ORDER BY name",
+ database};
+ Sqlite::WriteStatement<5> updatePropertyDeclarationWithAliasAndTypeStatement{
+ "UPDATE propertyDeclarations SET propertyTypeId=?2, propertyTraits=?3, "
+ "propertyImportedTypeNameId=?4, aliasPropertyDeclarationId=?5 WHERE "
+ "propertyDeclarationId=?1",
+ database};
+ Sqlite::ReadWriteStatement<1, 2> insertAliasPropertyDeclarationStatement{
+ "INSERT INTO propertyDeclarations(typeId, name) VALUES(?1, ?2) RETURNING "
+ "propertyDeclarationId",
+ database};
+ mutable Sqlite::ReadStatement<4, 1> selectFunctionDeclarationsForTypeIdStatement{
+ "SELECT name, returnTypeName, signature, functionDeclarationId FROM "
+ "functionDeclarations WHERE typeId=? ORDER BY name, signature",
+ database};
+ mutable Sqlite::ReadStatement<3, 1> selectFunctionDeclarationsForTypeIdWithoutSignatureStatement{
+ "SELECT name, returnTypeName, functionDeclarationId FROM "
+ "functionDeclarations WHERE typeId=? ORDER BY name",
+ database};
+ mutable Sqlite::ReadStatement<3, 1> selectFunctionParameterDeclarationsStatement{
+ "SELECT json_extract(json_each.value, '$.n'), json_extract(json_each.value, '$.tn'), "
+ "json_extract(json_each.value, '$.tr') FROM functionDeclarations, "
+ "json_each(functionDeclarations.signature) WHERE functionDeclarationId=?",
+ database};
+ Sqlite::WriteStatement<4> insertFunctionDeclarationStatement{
+ "INSERT INTO functionDeclarations(typeId, name, returnTypeName, signature) VALUES(?1, ?2, "
+ "?3, ?4)",
+ database};
+ Sqlite::WriteStatement<3> updateFunctionDeclarationStatement{
+ "UPDATE functionDeclarations "
+ "SET returnTypeName=?2, signature=?3 "
+ "WHERE functionDeclarationId=?1",
+ database};
+ Sqlite::WriteStatement<1> deleteFunctionDeclarationStatement{
+ "DELETE FROM functionDeclarations WHERE functionDeclarationId=?", database};
+ mutable Sqlite::ReadStatement<3, 1> selectSignalDeclarationsForTypeIdStatement{
+ "SELECT name, signature, signalDeclarationId FROM signalDeclarations WHERE typeId=? ORDER "
+ "BY name, signature",
+ database};
+ mutable Sqlite::ReadStatement<2, 1> selectSignalDeclarationsForTypeIdWithoutSignatureStatement{
+ "SELECT name, signalDeclarationId FROM signalDeclarations WHERE typeId=? ORDER BY name",
+ database};
+ mutable Sqlite::ReadStatement<3, 1> selectSignalParameterDeclarationsStatement{
+ "SELECT json_extract(json_each.value, '$.n'), json_extract(json_each.value, '$.tn'), "
+ "json_extract(json_each.value, '$.tr') FROM signalDeclarations, "
+ "json_each(signalDeclarations.signature) WHERE signalDeclarationId=?",
+ database};
+ Sqlite::WriteStatement<3> insertSignalDeclarationStatement{
+ "INSERT INTO signalDeclarations(typeId, name, signature) VALUES(?1, ?2, ?3)", database};
+ Sqlite::WriteStatement<2> updateSignalDeclarationStatement{
+ "UPDATE signalDeclarations SET signature=?2 WHERE signalDeclarationId=?1", database};
+ Sqlite::WriteStatement<1> deleteSignalDeclarationStatement{
+ "DELETE FROM signalDeclarations WHERE signalDeclarationId=?", database};
+ mutable Sqlite::ReadStatement<3, 1> selectEnumerationDeclarationsForTypeIdStatement{
+ "SELECT name, enumeratorDeclarations, enumerationDeclarationId FROM "
+ "enumerationDeclarations WHERE typeId=? ORDER BY name",
+ database};
+ mutable Sqlite::ReadStatement<2, 1> selectEnumerationDeclarationsForTypeIdWithoutEnumeratorDeclarationsStatement{
+ "SELECT name, enumerationDeclarationId FROM enumerationDeclarations WHERE typeId=? ORDER "
+ "BY name",
+ database};
+ mutable Sqlite::ReadStatement<3, 1> selectEnumeratorDeclarationStatement{
+ "SELECT json_each.key, json_each.value, json_each.type!='null' FROM "
+ "enumerationDeclarations, json_each(enumerationDeclarations.enumeratorDeclarations) WHERE "
+ "enumerationDeclarationId=?",
+ database};
+ Sqlite::WriteStatement<3> insertEnumerationDeclarationStatement{
+ "INSERT INTO enumerationDeclarations(typeId, name, enumeratorDeclarations) VALUES(?1, ?2, "
+ "?3)",
+ database};
+ Sqlite::WriteStatement<2> updateEnumerationDeclarationStatement{
+ "UPDATE enumerationDeclarations SET enumeratorDeclarations=?2 WHERE "
+ "enumerationDeclarationId=?1",
+ database};
+ Sqlite::WriteStatement<1> deleteEnumerationDeclarationStatement{
+ "DELETE FROM enumerationDeclarations WHERE enumerationDeclarationId=?", database};
+ mutable Sqlite::ReadStatement<1, 2> selectModuleIdByNameStatement{
+ "SELECT moduleId FROM modules WHERE kind=?1 AND name=?2 LIMIT 1", database};
+ mutable Sqlite::ReadWriteStatement<1, 2> insertModuleNameStatement{
+ "INSERT INTO modules(kind, name) VALUES(?1, ?2) RETURNING moduleId", database};
+ mutable Sqlite::ReadStatement<2, 1> selectModuleStatement{
+ "SELECT name, kind FROM modules WHERE moduleId =?1", database};
+ mutable Sqlite::ReadStatement<3> selectAllModulesStatement{
+ "SELECT name, kind, moduleId FROM modules", database};
+ mutable Sqlite::ReadStatement<1, 2> selectTypeIdBySourceIdAndNameStatement{
+ "SELECT typeId FROM types WHERE sourceId=?1 and name=?2", database};
+ mutable Sqlite::ReadStatement<1, 3> selectTypeIdByModuleIdsAndExportedNameStatement{
+ "SELECT typeId FROM exportedTypeNames WHERE moduleId IN carray(?1, ?2, 'int32') AND "
+ "name=?3",
+ database};
+ mutable Sqlite::ReadStatement<4> selectAllDocumentImportForSourceIdStatement{
+ "SELECT moduleId, majorVersion, minorVersion, sourceId "
+ "FROM documentImports ",
+ database};
+ mutable Sqlite::ReadStatement<5, 2> selectDocumentImportForSourceIdStatement{
+ "SELECT importId, sourceId, moduleId, majorVersion, minorVersion "
+ "FROM documentImports WHERE sourceId IN carray(?1) AND kind=?2 ORDER BY sourceId, "
+ "moduleId, majorVersion, minorVersion",
+ database};
+ Sqlite::ReadWriteStatement<1, 5> insertDocumentImportWithoutVersionStatement{
+ "INSERT INTO documentImports(sourceId, moduleId, sourceModuleId, kind, "
+ "parentImportId) VALUES (?1, ?2, ?3, ?4, ?5) RETURNING importId",
+ database};
+ Sqlite::ReadWriteStatement<1, 6> insertDocumentImportWithMajorVersionStatement{
+ "INSERT INTO documentImports(sourceId, moduleId, sourceModuleId, kind, majorVersion, "
+ "parentImportId) VALUES (?1, ?2, ?3, ?4, ?5, ?6) RETURNING importId",
+ database};
+ Sqlite::ReadWriteStatement<1, 7> insertDocumentImportWithVersionStatement{
+ "INSERT INTO documentImports(sourceId, moduleId, sourceModuleId, kind, majorVersion, "
+ "minorVersion, parentImportId) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7) RETURNING "
+ "importId",
+ database};
+ Sqlite::WriteStatement<1> deleteDocumentImportStatement{
+ "DELETE FROM documentImports WHERE importId=?1", database};
+ Sqlite::WriteStatement<2> deleteDocumentImportsWithParentImportIdStatement{
+ "DELETE FROM documentImports WHERE sourceId=?1 AND parentImportId=?2", database};
+ Sqlite::WriteStatement<1> deleteDocumentImportsWithSourceIdsStatement{
+ "DELETE FROM documentImports WHERE sourceId IN carray(?1)", database};
+ mutable Sqlite::ReadStatement<1, 2> selectPropertyDeclarationIdByTypeIdAndNameStatement{
+ "SELECT propertyDeclarationId "
+ "FROM propertyDeclarations "
+ "WHERE typeId=?1 AND name=?2 "
+ "LIMIT 1",
+ database};
+ Sqlite::WriteStatement<2> updateAliasIdPropertyDeclarationStatement{
+ "UPDATE propertyDeclarations SET aliasPropertyDeclarationId=?2 WHERE "
+ "aliasPropertyDeclarationId=?1",
+ database};
+ Sqlite::WriteStatement<2> updateAliasPropertyDeclarationByAliasPropertyDeclarationIdStatement{
+ "UPDATE propertyDeclarations SET propertyTypeId=new.propertyTypeId, "
+ "propertyTraits=new.propertyTraits, aliasPropertyDeclarationId=?1 FROM (SELECT "
+ "propertyTypeId, propertyTraits FROM propertyDeclarations WHERE propertyDeclarationId=?1) "
+ "AS new WHERE aliasPropertyDeclarationId=?2",
+ database};
+ Sqlite::WriteStatement<1> updateAliasPropertyDeclarationToNullStatement{
+ "UPDATE propertyDeclarations SET aliasPropertyDeclarationId=NULL, propertyTypeId=NULL, "
+ "propertyTraits=NULL WHERE propertyDeclarationId=? AND (aliasPropertyDeclarationId IS NOT "
+ "NULL OR propertyTypeId IS NOT NULL OR propertyTraits IS NOT NULL)",
+ database};
+ Sqlite::ReadStatement<5, 1> selectAliasPropertiesDeclarationForPropertiesWithTypeIdStatement{
+ "SELECT alias.typeId, alias.propertyDeclarationId, alias.propertyImportedTypeNameId, "
+ " alias.aliasPropertyDeclarationId, alias.aliasPropertyDeclarationTailId "
+ "FROM propertyDeclarations AS alias JOIN propertyDeclarations AS target "
+ " ON alias.aliasPropertyDeclarationId=target.propertyDeclarationId OR "
+ " alias.aliasPropertyDeclarationTailId=target.propertyDeclarationId "
+ "WHERE alias.propertyTypeId=?1 "
+ "UNION ALL "
+ "SELECT alias.typeId, alias.propertyDeclarationId, alias.propertyImportedTypeNameId, "
+ " alias.aliasPropertyDeclarationId, alias.aliasPropertyDeclarationTailId "
+ "FROM propertyDeclarations AS alias JOIN propertyDeclarations AS target "
+ " ON alias.aliasPropertyDeclarationId=target.propertyDeclarationId OR "
+ " alias.aliasPropertyDeclarationTailId=target.propertyDeclarationId "
+ "WHERE target.typeId=?1 "
+ "UNION ALL "
+ "SELECT alias.typeId, alias.propertyDeclarationId, alias.propertyImportedTypeNameId, "
+ " alias.aliasPropertyDeclarationId, alias.aliasPropertyDeclarationTailId "
+ "FROM propertyDeclarations AS alias JOIN propertyDeclarations AS target "
+ " ON alias.aliasPropertyDeclarationId=target.propertyDeclarationId OR "
+ " alias.aliasPropertyDeclarationTailId=target.propertyDeclarationId "
+ "WHERE alias.propertyImportedTypeNameId IN "
+ " (SELECT importedTypeNameId FROM exportedTypeNames JOIN importedTypeNames USING(name) "
+ " WHERE typeId=?1)",
+ database};
+ Sqlite::ReadStatement<3, 1> selectAliasPropertiesDeclarationForPropertiesWithAliasIdStatement{
+ "WITH RECURSIVE "
+ " properties(propertyDeclarationId, propertyImportedTypeNameId, typeId, "
+ " aliasPropertyDeclarationId) AS ("
+ " SELECT propertyDeclarationId, propertyImportedTypeNameId, typeId, "
+ " aliasPropertyDeclarationId FROM propertyDeclarations WHERE "
+ " aliasPropertyDeclarationId=?1"
+ " UNION ALL "
+ " SELECT pd.propertyDeclarationId, pd.propertyImportedTypeNameId, pd.typeId, "
+ " pd.aliasPropertyDeclarationId FROM propertyDeclarations AS pd JOIN properties AS "
+ " p ON pd.aliasPropertyDeclarationId=p.propertyDeclarationId)"
+ "SELECT propertyDeclarationId, propertyImportedTypeNameId, aliasPropertyDeclarationId "
+ " FROM properties",
+ database};
+ Sqlite::ReadWriteStatement<3, 1> updatesPropertyDeclarationPropertyTypeToNullStatement{
+ "UPDATE propertyDeclarations SET propertyTypeId=NULL WHERE propertyTypeId=?1 AND "
+ "aliasPropertyDeclarationId IS NULL RETURNING typeId, propertyDeclarationId, "
+ "propertyImportedTypeNameId",
+ database};
+ mutable Sqlite::ReadStatement<1, 1> selectPropertyNameStatement{
+ "SELECT name FROM propertyDeclarations WHERE propertyDeclarationId=?", database};
+ Sqlite::WriteStatement<2> updatePropertyDeclarationTypeStatement{
+ "UPDATE propertyDeclarations SET propertyTypeId=?2 WHERE propertyDeclarationId=?1", database};
+ Sqlite::ReadWriteStatement<2, 2> updatePrototypeIdToTypeIdStatement{
+ "UPDATE types "
+ "SET prototypeId=?2 "
+ "WHERE prototypeId=?1 "
+ "RETURNING typeId, prototypeNameId",
+ database};
+ Sqlite::ReadWriteStatement<2, 2> updateExtensionIdToTypeIdStatement{
+ "UPDATE types "
+ "SET extensionId=?2 "
+ "WHERE extensionId=?1 "
+ "RETURNING typeId, extensionNameId",
+ database};
+ Sqlite::ReadStatement<2, 2> selectTypeIdAndPrototypeNameIdForPrototypeIdAndTypeNameStatement{
+ "SELECT typeId, prototypeNameId "
+ "FROM types "
+ "WHERE prototypeNameId IN ( "
+ " SELECT importedTypeNameId "
+ " FROM "
+ " importedTypeNames WHERE name=?1) "
+ " AND prototypeId=?2",
+ database};
+ Sqlite::ReadStatement<2, 2> selectTypeIdAndPrototypeNameIdForPrototypeIdAndSourceIdStatement{
+ "SELECT typeId , prototypeNameId "
+ "FROM types "
+ "WHERE prototypeId=?1 AND sourceId=?2",
+ database};
+ Sqlite::ReadStatement<2, 2> selectTypeIdAndExtensionNameIdForExtensionIdAndSourceIdStatement{
+ "SELECT typeId, extensionNameId "
+ "FROM types "
+ "WHERE extensionId=?1 AND sourceId=?2",
+ database};
+ Sqlite::ReadWriteStatement<3, 3> updatePrototypeIdAndExtensionIdToTypeIdForSourceIdStatement{
+ "UPDATE types "
+ "SET prototypeId=?2, extensionId=?3 "
+ "WHERE sourceId=?1 "
+ "RETURNING typeId, prototypeNameId, extensionNameId",
+ database};
+ Sqlite::ReadStatement<2, 2> selectTypeIdForExtensionIdAndTypeNameStatement{
+ "SELECT typeId , prototypeNameId "
+ "FROM types "
+ "WHERE extensionNameId IN ( "
+ " SELECT importedTypeNameId "
+ " FROM importedTypeNames "
+ " WHERE name=?1) "
+ " AND extensionId=?2",
+ database};
+ Sqlite::WriteStatement<2> updateTypePrototypeStatement{
+ "UPDATE types SET prototypeId=?2 WHERE typeId=?1", database};
+ Sqlite::WriteStatement<2> updateTypeExtensionStatement{
+ "UPDATE types SET extensionId=?2 WHERE typeId=?1", database};
+ mutable Sqlite::ReadStatement<1, 1> selectPrototypeAndExtensionIdsStatement{
+ "WITH RECURSIVE "
+ " prototypes(typeId) AS ( "
+ " SELECT prototypeId FROM types WHERE typeId=?1 "
+ " UNION ALL "
+ " SELECT extensionId FROM types WHERE typeId=?1 "
+ " UNION ALL "
+ " SELECT prototypeId FROM types JOIN prototypes USING(typeId) "
+ " UNION ALL "
+ " SELECT extensionId FROM types JOIN prototypes USING(typeId)) "
+ "SELECT typeId FROM prototypes WHERE typeId IS NOT NULL",
+ database};
+ Sqlite::WriteStatement<3> updatePropertyDeclarationAliasIdAndTypeNameIdStatement{
+ "UPDATE propertyDeclarations SET aliasPropertyDeclarationId=?2, "
+ "propertyImportedTypeNameId=?3 WHERE propertyDeclarationId=?1 AND "
+ "(aliasPropertyDeclarationId IS NOT ?2 OR propertyImportedTypeNameId IS NOT ?3)",
+ database};
+ Sqlite::WriteStatement<1> updatetPropertiesDeclarationValuesOfAliasStatement{
+ "WITH RECURSIVE "
+ " properties(propertyDeclarationId, propertyTypeId, propertyTraits) AS ( "
+ " SELECT aliasPropertyDeclarationId, propertyTypeId, propertyTraits FROM "
+ " propertyDeclarations WHERE propertyDeclarationId=?1 "
+ " UNION ALL "
+ " SELECT pd.aliasPropertyDeclarationId, pd.propertyTypeId, pd.propertyTraits FROM "
+ " propertyDeclarations AS pd JOIN properties USING(propertyDeclarationId)) "
+ "UPDATE propertyDeclarations AS pd SET propertyTypeId=p.propertyTypeId, "
+ " propertyTraits=p.propertyTraits "
+ "FROM properties AS p "
+ "WHERE pd.propertyDeclarationId=?1 AND p.propertyDeclarationId IS NULL AND "
+ " (pd.propertyTypeId IS NOT p.propertyTypeId OR pd.propertyTraits IS NOT "
+ " p.propertyTraits)",
+ database};
+ Sqlite::WriteStatement<1> updatePropertyDeclarationAliasIdToNullStatement{
+ "UPDATE propertyDeclarations SET aliasPropertyDeclarationId=NULL WHERE "
+ "propertyDeclarationId=?1",
+ database};
+ mutable Sqlite::ReadStatement<1, 1> selectPropertyDeclarationIdsForAliasChainStatement{
+ "WITH RECURSIVE "
+ " properties(propertyDeclarationId) AS ( "
+ " SELECT aliasPropertyDeclarationId FROM propertyDeclarations WHERE "
+ " propertyDeclarationId=?1 "
+ " UNION ALL "
+ " SELECT aliasPropertyDeclarationId FROM propertyDeclarations JOIN properties "
+ " USING(propertyDeclarationId)) "
+ "SELECT propertyDeclarationId FROM properties",
+ database};
+ mutable Sqlite::ReadStatement<3> selectAllFileStatusesStatement{
+ "SELECT sourceId, size, lastModified FROM fileStatuses ORDER BY sourceId", database};
+ mutable Sqlite::ReadStatement<3, 1> selectFileStatusesForSourceIdsStatement{
+ "SELECT sourceId, size, lastModified FROM fileStatuses WHERE sourceId IN carray(?1) ORDER "
+ "BY sourceId",
+ database};
+ mutable Sqlite::ReadStatement<3, 1> selectFileStatusesForSourceIdStatement{
+ "SELECT sourceId, size, lastModified FROM fileStatuses WHERE sourceId=?1 ORDER BY sourceId",
+ database};
+ Sqlite::WriteStatement<3> insertFileStatusStatement{
+ "INSERT INTO fileStatuses(sourceId, size, lastModified) VALUES(?1, ?2, ?3)", database};
+ Sqlite::WriteStatement<1> deleteFileStatusStatement{
+ "DELETE FROM fileStatuses WHERE sourceId=?1", database};
+ Sqlite::WriteStatement<3> updateFileStatusStatement{
+ "UPDATE fileStatuses SET size=?2, lastModified=?3 WHERE sourceId=?1", database};
+ Sqlite::ReadStatement<1, 1> selectTypeIdBySourceIdStatement{
+ "SELECT typeId FROM types WHERE sourceId=?", database};
+ mutable Sqlite::ReadStatement<1, 3> selectImportedTypeNameIdStatement{
+ "SELECT importedTypeNameId FROM importedTypeNames WHERE kind=?1 AND importOrSourceId=?2 "
+ "AND name=?3 LIMIT 1",
+ database};
+ mutable Sqlite::ReadWriteStatement<1, 3> insertImportedTypeNameIdStatement{
+ "INSERT INTO importedTypeNames(kind, importOrSourceId, name) VALUES (?1, ?2, ?3) "
+ "RETURNING importedTypeNameId",
+ database};
+ mutable Sqlite::ReadStatement<1, 2> selectImportIdBySourceIdAndModuleIdStatement{
+ "SELECT importId FROM documentImports WHERE sourceId=?1 AND moduleId=?2 AND majorVersion "
+ "IS NULL AND minorVersion IS NULL LIMIT 1",
+ database};
+ mutable Sqlite::ReadStatement<1, 3> selectImportIdBySourceIdAndModuleIdAndMajorVersionStatement{
+ "SELECT importId FROM documentImports WHERE sourceId=?1 AND moduleId=?2 AND "
+ "majorVersion=?3 AND minorVersion IS NULL LIMIT 1",
+ database};
+ mutable Sqlite::ReadStatement<1, 4> selectImportIdBySourceIdAndModuleIdAndVersionStatement{
+ "SELECT importId FROM documentImports WHERE sourceId=?1 AND moduleId=?2 AND "
+ "majorVersion=?3 AND minorVersion=?4 LIMIT 1",
+ database};
+ mutable Sqlite::ReadStatement<1, 1> selectKindFromImportedTypeNamesStatement{
+ "SELECT kind FROM importedTypeNames WHERE importedTypeNameId=?1", database};
+ mutable Sqlite::ReadStatement<1, 1> selectNameFromImportedTypeNamesStatement{
+ "SELECT name FROM importedTypeNames WHERE importedTypeNameId=?1", database};
+ mutable Sqlite::ReadStatement<1, 1> selectTypeIdForQualifiedImportedTypeNameNamesStatement{
+ "SELECT typeId FROM importedTypeNames AS itn JOIN documentImports AS di ON "
+ "importOrSourceId=di.importId JOIN documentImports AS di2 ON di.sourceId=di2.sourceId AND "
+ "di.moduleId=di2.sourceModuleId "
+ "JOIN exportedTypeNames AS etn ON di2.moduleId=etn.moduleId WHERE "
+ "itn.kind=2 AND importedTypeNameId=?1 AND itn.name=etn.name AND "
+ "(di.majorVersion IS NULL OR (di.majorVersion=etn.majorVersion AND (di.minorVersion IS "
+ "NULL OR di.minorVersion>=etn.minorVersion))) ORDER BY etn.majorVersion DESC NULLS FIRST, "
+ "etn.minorVersion DESC NULLS FIRST LIMIT 1",
+ database};
+ mutable Sqlite::ReadStatement<1, 1> selectTypeIdForImportedTypeNameNamesStatement{
+ "WITH "
+ " importTypeNames(moduleId, name, kind, majorVersion, minorVersion) AS ( "
+ " SELECT moduleId, name, di.kind, majorVersion, minorVersion "
+ " FROM importedTypeNames AS itn JOIN documentImports AS di ON "
+ " importOrSourceId=sourceId "
+ " WHERE "
+ " importedTypeNameId=?1 AND itn.kind=1) "
+ "SELECT typeId FROM importTypeNames AS itn "
+ " JOIN exportedTypeNames AS etn USING(moduleId, name) "
+ "WHERE (itn.majorVersion IS NULL OR (itn.majorVersion=etn.majorVersion "
+ " AND (itn.minorVersion IS NULL OR itn.minorVersion>=etn.minorVersion))) "
+ "ORDER BY itn.kind, etn.majorVersion DESC NULLS FIRST, etn.minorVersion DESC NULLS FIRST "
+ "LIMIT 1",
+ database};
+ Sqlite::WriteStatement<0> deleteAllSourcesStatement{"DELETE FROM sources", database};
+ Sqlite::WriteStatement<0> deleteAllSourceContextsStatement{"DELETE FROM sourceContexts", database};
+ mutable Sqlite::ReadStatement<6, 1> selectExportedTypesForSourceIdsStatement{
+ "SELECT moduleId, name, ifnull(majorVersion, -1), ifnull(minorVersion, -1), typeId, "
+ "exportedTypeNameId FROM exportedTypeNames WHERE typeId in carray(?1) ORDER BY moduleId, "
+ "name, majorVersion, minorVersion",
+ database};
+ Sqlite::WriteStatement<5> insertExportedTypeNamesWithVersionStatement{
+ "INSERT INTO exportedTypeNames(moduleId, name, majorVersion, minorVersion, typeId) "
+ "VALUES(?1, ?2, ?3, ?4, ?5)",
+ database};
+ Sqlite::WriteStatement<4> insertExportedTypeNamesWithMajorVersionStatement{
+ "INSERT INTO exportedTypeNames(moduleId, name, majorVersion, typeId) "
+ "VALUES(?1, ?2, ?3, ?4)",
+ database};
+ Sqlite::WriteStatement<3> insertExportedTypeNamesWithoutVersionStatement{
+ "INSERT INTO exportedTypeNames(moduleId, name, typeId) VALUES(?1, ?2, ?3)", database};
+ Sqlite::WriteStatement<1> deleteExportedTypeNameStatement{
+ "DELETE FROM exportedTypeNames WHERE exportedTypeNameId=?", database};
+ Sqlite::WriteStatement<2> updateExportedTypeNameTypeIdStatement{
+ "UPDATE exportedTypeNames SET typeId=?2 WHERE exportedTypeNameId=?1", database};
+ mutable Sqlite::ReadStatement<4, 1> selectDirectoryInfosForSourceIdsStatement{
+ "SELECT directorySourceId, sourceId, moduleId, fileType FROM directoryInfos WHERE "
+ "directorySourceId IN carray(?1) ORDER BY directorySourceId, sourceId",
+ database};
+ Sqlite::WriteStatement<4> insertDirectoryInfoStatement{
+ "INSERT INTO directoryInfos(directorySourceId, sourceId, "
+ "moduleId, fileType) VALUES(?1, ?2, ?3, ?4)",
+ database};
+ Sqlite::WriteStatement<2> deleteDirectoryInfoStatement{
+ "DELETE FROM directoryInfos WHERE directorySourceId=?1 AND sourceId=?2", database};
+ Sqlite::WriteStatement<4> updateDirectoryInfoStatement{
+ "UPDATE directoryInfos SET moduleId=?3, fileType=?4 WHERE directorySourceId=?1 AND sourceId=?2",
+ database};
+ mutable Sqlite::ReadStatement<4, 1> selectDirectoryInfosForSourceIdStatement{
+ "SELECT directorySourceId, sourceId, moduleId, fileType FROM directoryInfos WHERE "
+ "directorySourceId=?1",
+ database};
+ mutable Sqlite::ReadStatement<4, 2> selectDirectoryInfosForSourceIdAndFileTypeStatement{
+ "SELECT directorySourceId, sourceId, moduleId, fileType FROM directoryInfos WHERE "
+ "directorySourceId=?1 AND fileType=?2",
+ database};
+ mutable Sqlite::ReadStatement<1, 2> selectDirectoryInfosSourceIdsForSourceIdAndFileTypeStatement{
+ "SELECT sourceId FROM directoryInfos WHERE directorySourceId=?1 AND fileType=?2", database};
+ mutable Sqlite::ReadStatement<4, 1> selectDirectoryInfoForSourceIdStatement{
+ "SELECT directorySourceId, sourceId, moduleId, fileType FROM directoryInfos WHERE "
+ "sourceId=?1 LIMIT 1",
+ database};
+ mutable Sqlite::ReadStatement<1, 1> selectTypeIdsForSourceIdsStatement{
+ "SELECT typeId FROM types WHERE sourceId IN carray(?1)", database};
+ mutable Sqlite::ReadStatement<6, 1> selectModuleExportedImportsForSourceIdStatement{
+ "SELECT moduleExportedImportId, moduleId, exportedModuleId, ifnull(majorVersion, -1), "
+ "ifnull(minorVersion, -1), isAutoVersion FROM moduleExportedImports WHERE moduleId IN "
+ "carray(?1) ORDER BY moduleId, exportedModuleId",
+ database};
+ Sqlite::WriteStatement<3> insertModuleExportedImportWithoutVersionStatement{
+ "INSERT INTO moduleExportedImports(moduleId, exportedModuleId, isAutoVersion) "
+ "VALUES (?1, ?2, ?3)",
+ database};
+ Sqlite::WriteStatement<4> insertModuleExportedImportWithMajorVersionStatement{
+ "INSERT INTO moduleExportedImports(moduleId, exportedModuleId, isAutoVersion, "
+ "majorVersion) VALUES (?1, ?2, ?3, ?4)",
+ database};
+ Sqlite::WriteStatement<5> insertModuleExportedImportWithVersionStatement{
+ "INSERT INTO moduleExportedImports(moduleId, exportedModuleId, isAutoVersion, "
+ "majorVersion, minorVersion) VALUES (?1, ?2, ?3, ?4, ?5)",
+ database};
+ Sqlite::WriteStatement<1> deleteModuleExportedImportStatement{
+ "DELETE FROM moduleExportedImports WHERE moduleExportedImportId=?1", database};
+ mutable Sqlite::ReadStatement<3, 3> selectModuleExportedImportsForModuleIdStatement{
+ "WITH RECURSIVE "
+ " imports(moduleId, majorVersion, minorVersion, moduleExportedImportId) AS ( "
+ " SELECT exportedModuleId, "
+ " iif(isAutoVersion=1, ?2, majorVersion), "
+ " iif(isAutoVersion=1, ?3, minorVersion), "
+ " moduleExportedImportId "
+ " FROM moduleExportedImports WHERE moduleId=?1 "
+ " UNION ALL "
+ " SELECT exportedModuleId, "
+ " iif(mei.isAutoVersion=1, i.majorVersion, mei.majorVersion), "
+ " iif(mei.isAutoVersion=1, i.minorVersion, mei.minorVersion), "
+ " mei.moduleExportedImportId "
+ " FROM moduleExportedImports AS mei JOIN imports AS i USING(moduleId)) "
+ "SELECT DISTINCT moduleId, ifnull(majorVersion, -1), ifnull(minorVersion, -1) "
+ "FROM imports",
+ database};
+ mutable Sqlite::ReadStatement<1, 1> selectLocalPropertyDeclarationIdsForTypeStatement{
+ "SELECT propertyDeclarationId "
+ "FROM propertyDeclarations "
+ "WHERE typeId=? "
+ "ORDER BY propertyDeclarationId",
+ database};
+ mutable Sqlite::ReadStatement<1, 2> selectLocalPropertyDeclarationIdForTypeAndPropertyNameStatement{
+ "SELECT propertyDeclarationId "
+ "FROM propertyDeclarations "
+ "WHERE typeId=?1 AND name=?2 LIMIT 1",
+ database};
+ mutable Sqlite::ReadStatement<4, 1> selectPropertyDeclarationForPropertyDeclarationIdStatement{
+ "SELECT typeId, name, propertyTraits, propertyTypeId "
+ "FROM propertyDeclarations "
+ "WHERE propertyDeclarationId=?1 LIMIT 1",
+ database};
+ mutable Sqlite::ReadStatement<1, 1> selectSignalDeclarationNamesForTypeStatement{
+ "WITH RECURSIVE "
+ " all_prototype_and_extension(typeId, prototypeId) AS ("
+ " SELECT typeId, prototypeId FROM types WHERE prototypeId IS NOT NULL"
+ " UNION ALL "
+ " SELECT typeId, extensionId FROM types WHERE extensionId IS NOT NULL),"
+ " typeChain(typeId) AS ("
+ " VALUES(?1)"
+ " UNION ALL "
+ " SELECT prototypeId FROM all_prototype_and_extension JOIN typeChain "
+ " USING(typeId)) "
+ "SELECT name FROM typeChain JOIN signalDeclarations "
+ " USING(typeId) ORDER BY name",
+ database};
+ mutable Sqlite::ReadStatement<1, 1> selectFuncionDeclarationNamesForTypeStatement{
+ "WITH RECURSIVE "
+ " all_prototype_and_extension(typeId, prototypeId) AS ("
+ " SELECT typeId, prototypeId FROM types WHERE prototypeId IS NOT NULL"
+ " UNION ALL "
+ " SELECT typeId, extensionId FROM types WHERE extensionId IS NOT NULL),"
+ " typeChain(typeId) AS ("
+ " VALUES(?1)"
+ " UNION ALL "
+ " SELECT prototypeId FROM all_prototype_and_extension JOIN typeChain "
+ " USING(typeId))"
+ "SELECT name FROM typeChain JOIN functionDeclarations "
+ " USING(typeId) ORDER BY name",
+ database};
+ mutable Sqlite::ReadStatement<2> selectTypesWithDefaultPropertyStatement{
+ "SELECT typeId, defaultPropertyId FROM types ORDER BY typeId", database};
+ Sqlite::WriteStatement<2> updateDefaultPropertyIdStatement{
+ "UPDATE types SET defaultPropertyId=?2 WHERE typeId=?1", database};
+ Sqlite::WriteStatement<1> updateDefaultPropertyIdToNullStatement{
+ "UPDATE types SET defaultPropertyId=NULL WHERE defaultPropertyId=?1", database};
+ mutable Sqlite::ReadStatement<3, 1> selectInfoTypeByTypeIdStatement{
+ "SELECT sourceId, traits, annotationTraits FROM types WHERE typeId=?", database};
+ mutable Sqlite::ReadStatement<1, 1> selectSourceIdByTypeIdStatement{
+ "SELECT sourceId FROM types WHERE typeId=?", database};
+ mutable Sqlite::ReadStatement<1, 1> selectPrototypeAnnotationTraitsByTypeIdStatement{
+ "SELECT annotationTraits "
+ "FROM types "
+ "WHERE typeId=(SELECT prototypeId FROM types WHERE typeId=?)",
+ database};
+ mutable Sqlite::ReadStatement<1, 1> selectDefaultPropertyDeclarationIdStatement{
+ "SELECT defaultPropertyId FROM types WHERE typeId=?", database};
+ mutable Sqlite::ReadStatement<1, 1> selectPrototypeIdsForTypeIdInOrderStatement{
+ "WITH RECURSIVE "
+ " all_prototype_and_extension(typeId, prototypeId) AS ("
+ " SELECT typeId, prototypeId FROM types WHERE prototypeId IS NOT NULL"
+ " UNION ALL "
+ " SELECT typeId, extensionId FROM types WHERE extensionId IS NOT NULL),"
+ " prototypes(typeId, level) AS ("
+ " SELECT prototypeId, 0 FROM all_prototype_and_extension WHERE typeId=?"
+ " UNION ALL "
+ " SELECT prototypeId, p.level+1 FROM all_prototype_and_extension JOIN "
+ " prototypes AS p USING(typeId)) "
+ "SELECT typeId FROM prototypes ORDER BY level",
+ database};
+ Sqlite::WriteStatement<2> upsertPropertyEditorPathIdStatement{
+ "INSERT INTO propertyEditorPaths(typeId, pathSourceId) VALUES(?1, ?2) ON CONFLICT DO "
+ "UPDATE SET pathSourceId=excluded.pathSourceId WHERE pathSourceId IS NOT "
+ "excluded.pathSourceId",
+ database};
+ mutable Sqlite::ReadStatement<1, 1> selectPropertyEditorPathIdStatement{
+ "SELECT pathSourceId FROM propertyEditorPaths WHERE typeId=?", database};
+ mutable Sqlite::ReadStatement<3, 1> selectPropertyEditorPathsForForSourceIdsStatement{
+ "SELECT typeId, pathSourceId, directoryId "
+ "FROM propertyEditorPaths "
+ "WHERE directoryId IN carray(?1) "
+ "ORDER BY typeId",
+ database};
+ Sqlite::WriteStatement<3> insertPropertyEditorPathStatement{
+ "INSERT INTO propertyEditorPaths(typeId, pathSourceId, directoryId) VALUES (?1, ?2, ?3)",
+ database};
+ Sqlite::WriteStatement<3> updatePropertyEditorPathsStatement{
+ "UPDATE propertyEditorPaths "
+ "SET pathSourceId=?2, directoryId=?3 "
+ "WHERE typeId=?1",
+ database};
+ Sqlite::WriteStatement<1> deletePropertyEditorPathStatement{
+ "DELETE FROM propertyEditorPaths WHERE typeId=?1", database};
+ mutable Sqlite::ReadStatement<5, 1> selectTypeAnnotationsForSourceIdsStatement{
+ "SELECT typeId, typeName, iconPath, itemLibrary, hints FROM typeAnnotations WHERE "
+ "sourceId IN carray(?1) ORDER BY typeId",
+ database};
+ Sqlite::WriteStatement<7> insertTypeAnnotationStatement{
+ "INSERT INTO "
+ " typeAnnotations(typeId, sourceId, directorySourceId, typeName, iconPath, itemLibrary, "
+ " hints) "
+ "VALUES(?1, ?2, ?3, ?4, ?5, ?6, ?7)",
+ database};
+ Sqlite::WriteStatement<5> updateTypeAnnotationStatement{
+ "UPDATE typeAnnotations "
+ "SET typeName=?2, iconPath=?3, itemLibrary=?4, hints=?5 "
+ "WHERE typeId=?1",
+ database};
+ Sqlite::WriteStatement<1> deleteTypeAnnotationStatement{
+ "DELETE FROM typeAnnotations WHERE typeId=?1", database};
+ mutable Sqlite::ReadStatement<1, 1> selectTypeIconPathStatement{
+ "SELECT iconPath FROM typeAnnotations WHERE typeId=?1", database};
+ mutable Sqlite::ReadStatement<2, 1> selectTypeHintsStatement{
+ "SELECT hints.key, hints.value "
+ "FROM typeAnnotations, json_each(typeAnnotations.hints) AS hints "
+ "WHERE typeId=?1 AND hints IS NOT NULL",
+ database};
+ mutable Sqlite::ReadStatement<1, 1> selectTypeAnnotationSourceIdsStatement{
+ "SELECT sourceId FROM typeAnnotations WHERE directorySourceId=?1 ORDER BY sourceId", database};
+ mutable Sqlite::ReadStatement<1, 0> selectTypeAnnotationDirectorySourceIdsStatement{
+ "SELECT DISTINCT directorySourceId FROM typeAnnotations ORDER BY directorySourceId", database};
+ mutable Sqlite::ReadStatement<10> selectItemLibraryEntriesStatement{
+ "SELECT typeId, typeName, i.value->>'$.name', i.value->>'$.iconPath', "
+ " i.value->>'$.category', i.value->>'$.import', i.value->>'$.toolTip', "
+ " i.value->>'$.properties', i.value->>'$.extraFilePaths', i.value->>'$.templatePath' "
+ "FROM typeAnnotations AS ta , json_each(ta.itemLibrary) AS i "
+ "WHERE ta.itemLibrary IS NOT NULL",
+ database};
+ mutable Sqlite::ReadStatement<10, 1> selectItemLibraryEntriesByTypeIdStatement{
+ "SELECT typeId, typeName, i.value->>'$.name', i.value->>'$.iconPath', "
+ " i.value->>'$.category', i.value->>'$.import', i.value->>'$.toolTip', "
+ " i.value->>'$.properties', i.value->>'$.extraFilePaths', i.value->>'$.templatePath' "
+ "FROM typeAnnotations AS ta, json_each(ta.itemLibrary) AS i "
+ "WHERE typeId=?1 AND ta.itemLibrary IS NOT NULL",
+ database};
+ mutable Sqlite::ReadStatement<10, 1> selectItemLibraryEntriesBySourceIdStatement{
+ "SELECT typeId, typeName, i.value->>'$.name', i.value->>'$.iconPath', "
+ "i.value->>'$.category', "
+ " i.value->>'$.import', i.value->>'$.toolTip', i.value->>'$.properties', "
+ " i.value->>'$.extraFilePaths', i.value->>'$.templatePath' "
+ "FROM typeAnnotations, json_each(typeAnnotations.itemLibrary) AS i "
+ "WHERE typeId IN (SELECT DISTINCT typeId "
+ " FROM documentImports AS di JOIN exportedTypeNames "
+ " USING(moduleId) "
+ " WHERE di.sourceId=?)",
+ database};
+ mutable Sqlite::ReadStatement<3, 1> selectItemLibraryPropertiesStatement{
+ "SELECT p.value->>0, p.value->>1, p.value->>2 FROM json_each(?1) AS p", database};
+ mutable Sqlite::ReadStatement<1, 1> selectItemLibraryExtraFilePathsStatement{
+ "SELECT p.value FROM json_each(?1) AS p", database};
+ mutable Sqlite::ReadStatement<1, 1> selectTypeIdsByModuleIdStatement{
+ "SELECT DISTINCT typeId FROM exportedTypeNames WHERE moduleId=?", database};
+ mutable Sqlite::ReadStatement<1, 1> selectHeirTypeIdsStatement{
+ "WITH RECURSIVE "
+ " typeSelection(typeId) AS ("
+ " SELECT typeId FROM types WHERE prototypeId=?1 OR extensionId=?1"
+ " UNION ALL "
+ " SELECT t.typeId "
+ " FROM types AS t JOIN typeSelection AS ts "
+ " WHERE prototypeId=ts.typeId OR extensionId=ts.typeId)"
+ "SELECT typeId FROM typeSelection",
+ database};
+};
+
+class ProjectStorage::Initializer
+{
+public:
+ Initializer(Database &database, bool isInitialized)
+ {
+ if (!isInitialized) {
+ auto moduleIdColumn = createModulesTable(database);
+ createSourceContextsTable(database);
+ createSourcesTable(database);
+ createTypesAndePropertyDeclarationsTables(database, moduleIdColumn);
+ createExportedTypeNamesTable(database, moduleIdColumn);
+ createImportedTypeNamesTable(database);
+ createEnumerationsTable(database);
+ createFunctionsTable(database);
+ createSignalsTable(database);
+ createModuleExportedImportsTable(database, moduleIdColumn);
+ createDocumentImportsTable(database, moduleIdColumn);
+ createFileStatusesTable(database);
+ createDirectoryInfosTable(database);
+ createPropertyEditorPathsTable(database);
+ createTypeAnnotionsTable(database);
+ }
+ database.setIsInitialized(true);
+ }
+
+ void createSourceContextsTable(Database &database)
+ {
+ Sqlite::Table table;
+ table.setUseIfNotExists(true);
+ table.setName("sourceContexts");
+ table.addColumn("sourceContextId", Sqlite::ColumnType::Integer, {Sqlite::PrimaryKey{}});
+ const Sqlite::Column &sourceContextPathColumn = table.addColumn("sourceContextPath");
+
+ table.addUniqueIndex({sourceContextPathColumn});
+
+ table.initialize(database);
+ }
+
+ void createSourcesTable(Database &database)
+ {
+ Sqlite::StrictTable table;
+ table.setUseIfNotExists(true);
+ table.setName("sources");
+ table.addColumn("sourceId", Sqlite::StrictColumnType::Integer, {Sqlite::PrimaryKey{}});
+ const auto &sourceContextIdColumn = table.addColumn(
+ "sourceContextId",
+ Sqlite::StrictColumnType::Integer,
+ {Sqlite::NotNull{},
+ Sqlite::ForeignKey{"sourceContexts",
+ "sourceContextId",
+ Sqlite::ForeignKeyAction::NoAction,
+ Sqlite::ForeignKeyAction::Cascade}});
+ const auto &sourceNameColumn = table.addColumn("sourceName", Sqlite::StrictColumnType::Text);
+ table.addUniqueIndex({sourceContextIdColumn, sourceNameColumn});
+
+ table.initialize(database);
+ }
+
+ void createTypesAndePropertyDeclarationsTables(
+ Database &database, [[maybe_unused]] const Sqlite::StrictColumn &foreignModuleIdColumn)
+ {
+ Sqlite::StrictTable typesTable;
+ typesTable.setUseIfNotExists(true);
+ typesTable.setName("types");
+ typesTable.addColumn("typeId", Sqlite::StrictColumnType::Integer, {Sqlite::PrimaryKey{}});
+ auto &sourceIdColumn = typesTable.addColumn("sourceId", Sqlite::StrictColumnType::Integer);
+ auto &typesNameColumn = typesTable.addColumn("name", Sqlite::StrictColumnType::Text);
+ typesTable.addColumn("traits", Sqlite::StrictColumnType::Integer);
+ auto &prototypeIdColumn = typesTable.addColumn("prototypeId",
+ Sqlite::StrictColumnType::Integer);
+ auto &prototypeNameIdColumn = typesTable.addColumn("prototypeNameId",
+ Sqlite::StrictColumnType::Integer);
+ auto &extensionIdColumn = typesTable.addColumn("extensionId",
+ Sqlite::StrictColumnType::Integer);
+ auto &extensionNameIdColumn = typesTable.addColumn("extensionNameId",
+ Sqlite::StrictColumnType::Integer);
+ auto &defaultPropertyIdColumn = typesTable.addColumn("defaultPropertyId",
+ Sqlite::StrictColumnType::Integer);
+ typesTable.addColumn("annotationTraits", Sqlite::StrictColumnType::Integer);
+ typesTable.addUniqueIndex({sourceIdColumn, typesNameColumn});
+ typesTable.addIndex({defaultPropertyIdColumn});
+ typesTable.addIndex({prototypeIdColumn, sourceIdColumn});
+ typesTable.addIndex({extensionIdColumn, sourceIdColumn});
+ typesTable.addIndex({prototypeNameIdColumn});
+ typesTable.addIndex({extensionNameIdColumn});
+
+ typesTable.initialize(database);
+
+ {
+ Sqlite::StrictTable propertyDeclarationTable;
+ propertyDeclarationTable.setUseIfNotExists(true);
+ propertyDeclarationTable.setName("propertyDeclarations");
+ propertyDeclarationTable.addColumn("propertyDeclarationId",
+ Sqlite::StrictColumnType::Integer,
+ {Sqlite::PrimaryKey{}});
+ auto &typeIdColumn = propertyDeclarationTable.addColumn("typeId");
+ auto &nameColumn = propertyDeclarationTable.addColumn("name");
+ auto &propertyTypeIdColumn = propertyDeclarationTable.addForeignKeyColumn(
+ "propertyTypeId",
+ typesTable,
+ Sqlite::ForeignKeyAction::NoAction,
+ Sqlite::ForeignKeyAction::Restrict);
+ propertyDeclarationTable.addColumn("propertyTraits", Sqlite::StrictColumnType::Integer);
+ propertyDeclarationTable.addColumn("propertyImportedTypeNameId",
+ Sqlite::StrictColumnType::Integer);
+ auto &aliasPropertyDeclarationIdColumn = propertyDeclarationTable.addForeignKeyColumn(
+ "aliasPropertyDeclarationId",
+ propertyDeclarationTable,
+ Sqlite::ForeignKeyAction::NoAction,
+ Sqlite::ForeignKeyAction::Restrict);
+ auto &aliasPropertyDeclarationTailIdColumn = propertyDeclarationTable.addForeignKeyColumn(
+ "aliasPropertyDeclarationTailId",
+ propertyDeclarationTable,
+ Sqlite::ForeignKeyAction::NoAction,
+ Sqlite::ForeignKeyAction::Restrict);
+
+ propertyDeclarationTable.addUniqueIndex({typeIdColumn, nameColumn});
+ propertyDeclarationTable.addIndex({propertyTypeIdColumn});
+ propertyDeclarationTable.addIndex({aliasPropertyDeclarationIdColumn},
+ "aliasPropertyDeclarationId IS NOT NULL");
+ propertyDeclarationTable.addIndex({aliasPropertyDeclarationTailIdColumn},
+ "aliasPropertyDeclarationTailId IS NOT NULL");
+
+ propertyDeclarationTable.initialize(database);
+ }
+ }
+
+ void createExportedTypeNamesTable(Database &database,
+ const Sqlite::StrictColumn &foreignModuleIdColumn)
+ {
+ Sqlite::StrictTable table;
+ table.setUseIfNotExists(true);
+ table.setName("exportedTypeNames");
+ table.addColumn("exportedTypeNameId",
+ Sqlite::StrictColumnType::Integer,
+ {Sqlite::PrimaryKey{}});
+ auto &moduleIdColumn = table.addForeignKeyColumn("moduleId",
+ foreignModuleIdColumn,
+ Sqlite::ForeignKeyAction::NoAction,
+ Sqlite::ForeignKeyAction::NoAction);
+ auto &nameColumn = table.addColumn("name", Sqlite::StrictColumnType::Text);
+ auto &typeIdColumn = table.addColumn("typeId", Sqlite::StrictColumnType::Integer);
+ auto &majorVersionColumn = table.addColumn("majorVersion", Sqlite::StrictColumnType::Integer);
+ auto &minorVersionColumn = table.addColumn("minorVersion", Sqlite::StrictColumnType::Integer);
+
+ table.addUniqueIndex({moduleIdColumn, nameColumn},
+ "majorVersion IS NULL AND minorVersion IS NULL");
+ table.addUniqueIndex({moduleIdColumn, nameColumn, majorVersionColumn},
+ "majorVersion IS NOT NULL AND minorVersion IS NULL");
+ table.addUniqueIndex({moduleIdColumn, nameColumn, majorVersionColumn, minorVersionColumn},
+ "majorVersion IS NOT NULL AND minorVersion IS NOT NULL");
+
+ table.addIndex({typeIdColumn});
+ table.addIndex({moduleIdColumn, nameColumn});
+
+ table.initialize(database);
+ }
+
+ void createImportedTypeNamesTable(Database &database)
+ {
+ Sqlite::StrictTable table;
+ table.setUseIfNotExists(true);
+ table.setName("importedTypeNames");
+ table.addColumn("importedTypeNameId",
+ Sqlite::StrictColumnType::Integer,
+ {Sqlite::PrimaryKey{}});
+ auto &importOrSourceIdColumn = table.addColumn("importOrSourceId");
+ auto &nameColumn = table.addColumn("name", Sqlite::StrictColumnType::Text);
+ auto &kindColumn = table.addColumn("kind", Sqlite::StrictColumnType::Integer);
+
+ table.addUniqueIndex({kindColumn, importOrSourceIdColumn, nameColumn});
+ table.addIndex({nameColumn});
+
+ table.initialize(database);
+ }
+
+ void createEnumerationsTable(Database &database)
+ {
+ Sqlite::StrictTable table;
+ table.setUseIfNotExists(true);
+ table.setName("enumerationDeclarations");
+ table.addColumn("enumerationDeclarationId",
+ Sqlite::StrictColumnType::Integer,
+ {Sqlite::PrimaryKey{}});
+ auto &typeIdColumn = table.addColumn("typeId", Sqlite::StrictColumnType::Integer);
+ auto &nameColumn = table.addColumn("name", Sqlite::StrictColumnType::Text);
+ table.addColumn("enumeratorDeclarations", Sqlite::StrictColumnType::Text);
+
+ table.addUniqueIndex({typeIdColumn, nameColumn});
+
+ table.initialize(database);
+ }
+
+ void createFunctionsTable(Database &database)
+ {
+ Sqlite::StrictTable table;
+ table.setUseIfNotExists(true);
+ table.setName("functionDeclarations");
+ table.addColumn("functionDeclarationId",
+ Sqlite::StrictColumnType::Integer,
+ {Sqlite::PrimaryKey{}});
+ auto &typeIdColumn = table.addColumn("typeId", Sqlite::StrictColumnType::Integer);
+ auto &nameColumn = table.addColumn("name", Sqlite::StrictColumnType::Text);
+ auto &signatureColumn = table.addColumn("signature", Sqlite::StrictColumnType::Text);
+ table.addColumn("returnTypeName");
+
+ table.addUniqueIndex({typeIdColumn, nameColumn, signatureColumn});
+
+ table.initialize(database);
+ }
+
+ void createSignalsTable(Database &database)
+ {
+ Sqlite::StrictTable table;
+ table.setUseIfNotExists(true);
+ table.setName("signalDeclarations");
+ table.addColumn("signalDeclarationId",
+ Sqlite::StrictColumnType::Integer,
+ {Sqlite::PrimaryKey{}});
+ auto &typeIdColumn = table.addColumn("typeId", Sqlite::StrictColumnType::Integer);
+ auto &nameColumn = table.addColumn("name", Sqlite::StrictColumnType::Text);
+ auto &signatureColumn = table.addColumn("signature", Sqlite::StrictColumnType::Text);
+
+ table.addUniqueIndex({typeIdColumn, nameColumn, signatureColumn});
+
+ table.initialize(database);
+ }
+
+ Sqlite::StrictColumn createModulesTable(Database &database)
+ {
+ Sqlite::StrictTable table;
+ table.setUseIfNotExists(true);
+ table.setName("modules");
+ auto &modelIdColumn = table.addColumn("moduleId",
+ Sqlite::StrictColumnType::Integer,
+ {Sqlite::PrimaryKey{}});
+ auto &kindColumn = table.addColumn("kind", Sqlite::StrictColumnType::Integer);
+ auto &nameColumn = table.addColumn("name", Sqlite::StrictColumnType::Text);
+
+ table.addUniqueIndex({kindColumn, nameColumn});
- return projectStorageCategory_;
+ table.initialize(database);
+
+ return std::move(modelIdColumn);
+ }
+
+ void createModuleExportedImportsTable(Database &database,
+ const Sqlite::StrictColumn &foreignModuleIdColumn)
+ {
+ Sqlite::StrictTable table;
+ table.setUseIfNotExists(true);
+ table.setName("moduleExportedImports");
+ table.addColumn("moduleExportedImportId",
+ Sqlite::StrictColumnType::Integer,
+ {Sqlite::PrimaryKey{}});
+ auto &moduleIdColumn = table.addForeignKeyColumn("moduleId",
+ foreignModuleIdColumn,
+ Sqlite::ForeignKeyAction::NoAction,
+ Sqlite::ForeignKeyAction::Cascade,
+ Sqlite::Enforment::Immediate);
+ auto &sourceIdColumn = table.addColumn("exportedModuleId", Sqlite::StrictColumnType::Integer);
+ table.addColumn("isAutoVersion", Sqlite::StrictColumnType::Integer);
+ table.addColumn("majorVersion", Sqlite::StrictColumnType::Integer);
+ table.addColumn("minorVersion", Sqlite::StrictColumnType::Integer);
+
+ table.addUniqueIndex({sourceIdColumn, moduleIdColumn});
+
+ table.initialize(database);
+ }
+
+ void createDocumentImportsTable(Database &database,
+ const Sqlite::StrictColumn &foreignModuleIdColumn)
+ {
+ Sqlite::StrictTable table;
+ table.setUseIfNotExists(true);
+ table.setName("documentImports");
+ table.addColumn("importId", Sqlite::StrictColumnType::Integer, {Sqlite::PrimaryKey{}});
+ auto &sourceIdColumn = table.addColumn("sourceId", Sqlite::StrictColumnType::Integer);
+ auto &moduleIdColumn = table.addForeignKeyColumn("moduleId",
+ foreignModuleIdColumn,
+ Sqlite::ForeignKeyAction::NoAction,
+ Sqlite::ForeignKeyAction::Cascade,
+ Sqlite::Enforment::Immediate);
+ auto &sourceModuleIdColumn = table.addForeignKeyColumn("sourceModuleId",
+ foreignModuleIdColumn,
+ Sqlite::ForeignKeyAction::NoAction,
+ Sqlite::ForeignKeyAction::Cascade,
+ Sqlite::Enforment::Immediate);
+ auto &kindColumn = table.addColumn("kind", Sqlite::StrictColumnType::Integer);
+ auto &majorVersionColumn = table.addColumn("majorVersion", Sqlite::StrictColumnType::Integer);
+ auto &minorVersionColumn = table.addColumn("minorVersion", Sqlite::StrictColumnType::Integer);
+ auto &parentImportIdColumn = table.addColumn("parentImportId",
+ Sqlite::StrictColumnType::Integer);
+
+ table.addUniqueIndex(
+ {sourceIdColumn, moduleIdColumn, kindColumn, sourceModuleIdColumn, parentImportIdColumn},
+ "majorVersion IS NULL AND minorVersion IS NULL");
+ table.addUniqueIndex({sourceIdColumn,
+ moduleIdColumn,
+ kindColumn,
+ sourceModuleIdColumn,
+ majorVersionColumn,
+ parentImportIdColumn},
+ "majorVersion IS NOT NULL AND minorVersion IS NULL");
+ table.addUniqueIndex({sourceIdColumn,
+ moduleIdColumn,
+ kindColumn,
+ sourceModuleIdColumn,
+ majorVersionColumn,
+ minorVersionColumn,
+ parentImportIdColumn},
+ "majorVersion IS NOT NULL AND minorVersion IS NOT NULL");
+
+ table.addIndex({sourceIdColumn, kindColumn});
+
+ table.initialize(database);
+ }
+
+ void createFileStatusesTable(Database &database)
+ {
+ Sqlite::StrictTable table;
+ table.setUseIfNotExists(true);
+ table.setName("fileStatuses");
+ table.addColumn("sourceId",
+ Sqlite::StrictColumnType::Integer,
+ {Sqlite::PrimaryKey{},
+ Sqlite::ForeignKey{"sources",
+ "sourceId",
+ Sqlite::ForeignKeyAction::NoAction,
+ Sqlite::ForeignKeyAction::Cascade}});
+ table.addColumn("size", Sqlite::StrictColumnType::Integer);
+ table.addColumn("lastModified", Sqlite::StrictColumnType::Integer);
+
+ table.initialize(database);
+ }
+
+ void createDirectoryInfosTable(Database &database)
+ {
+ Sqlite::StrictTable table;
+ table.setUseIfNotExists(true);
+ table.setUseWithoutRowId(true);
+ table.setName("directoryInfos");
+ auto &directorySourceIdColumn = table.addColumn("directorySourceId",
+ Sqlite::StrictColumnType::Integer);
+ auto &sourceIdColumn = table.addColumn("sourceId", Sqlite::StrictColumnType::Integer);
+ table.addColumn("moduleId", Sqlite::StrictColumnType::Integer);
+ auto &fileTypeColumn = table.addColumn("fileType", Sqlite::StrictColumnType::Integer);
+
+ table.addPrimaryKeyContraint({directorySourceIdColumn, sourceIdColumn});
+ table.addUniqueIndex({sourceIdColumn});
+ table.addIndex({directorySourceIdColumn, fileTypeColumn});
+
+ table.initialize(database);
+ }
+
+ void createPropertyEditorPathsTable(Database &database)
+ {
+ Sqlite::StrictTable table;
+ table.setUseIfNotExists(true);
+ table.setUseWithoutRowId(true);
+ table.setName("propertyEditorPaths");
+ table.addColumn("typeId", Sqlite::StrictColumnType::Integer, {Sqlite::PrimaryKey{}});
+ table.addColumn("pathSourceId", Sqlite::StrictColumnType::Integer);
+ auto &directoryIdColumn = table.addColumn("directoryId", Sqlite::StrictColumnType::Integer);
+
+ table.addIndex({directoryIdColumn});
+
+ table.initialize(database);
+ }
+
+ void createTypeAnnotionsTable(Database &database)
+ {
+ Sqlite::StrictTable table;
+ table.setUseIfNotExists(true);
+ table.setUseWithoutRowId(true);
+ table.setName("typeAnnotations");
+ auto &typeIdColumn = table.addColumn("typeId",
+ Sqlite::StrictColumnType::Integer,
+ {Sqlite::PrimaryKey{}});
+ auto &sourceIdColumn = table.addColumn("sourceId", Sqlite::StrictColumnType::Integer);
+ auto &directorySourceIdColumn = table.addColumn("directorySourceId",
+ Sqlite::StrictColumnType::Integer);
+ table.addColumn("typeName", Sqlite::StrictColumnType::Text);
+ table.addColumn("iconPath", Sqlite::StrictColumnType::Text);
+ table.addColumn("itemLibrary", Sqlite::StrictColumnType::Text);
+ table.addColumn("hints", Sqlite::StrictColumnType::Text);
+
+ table.addUniqueIndex({sourceIdColumn, typeIdColumn});
+ table.addIndex({directorySourceIdColumn});
+
+ table.initialize(database);
+ }
+};
+
+ProjectStorage::ProjectStorage(Database &database,
+ ProjectStorageErrorNotifierInterface &errorNotifier,
+ bool isInitialized)
+ : database{database}
+ , errorNotifier{&errorNotifier}
+ , exclusiveTransaction{database}
+ , initializer{std::make_unique<ProjectStorage::Initializer>(database, isInitialized)}
+ , moduleCache{ModuleStorageAdapter{*this}}
+ , s{std::make_unique<ProjectStorage::Statements>(database)}
+{
+ NanotraceHR::Tracer tracer{"initialize"_t, projectStorageCategory()};
+
+ exclusiveTransaction.commit();
+
+ database.walCheckpointFull();
+
+ moduleCache.populate();
}
-} // namespace QmlDesigner
+ProjectStorage::~ProjectStorage() = default;
+
+void ProjectStorage::synchronize(Storage::Synchronization::SynchronizationPackage package)
+{
+ NanotraceHR::Tracer tracer{"synchronize"_t, projectStorageCategory()};
+
+ TypeIds deletedTypeIds;
+ Sqlite::withImmediateTransaction(database, [&] {
+ AliasPropertyDeclarations insertedAliasPropertyDeclarations;
+ AliasPropertyDeclarations updatedAliasPropertyDeclarations;
+
+ AliasPropertyDeclarations relinkableAliasPropertyDeclarations;
+ PropertyDeclarations relinkablePropertyDeclarations;
+ Prototypes relinkablePrototypes;
+ Prototypes relinkableExtensions;
+
+ TypeIds updatedTypeIds;
+ updatedTypeIds.reserve(package.types.size());
+
+ TypeIds typeIdsToBeDeleted;
+
+ std::sort(package.updatedSourceIds.begin(), package.updatedSourceIds.end());
+
+ synchronizeFileStatuses(package.fileStatuses, package.updatedFileStatusSourceIds);
+ synchronizeImports(package.imports,
+ package.updatedSourceIds,
+ package.moduleDependencies,
+ package.updatedModuleDependencySourceIds,
+ package.moduleExportedImports,
+ package.updatedModuleIds,
+ relinkablePrototypes,
+ relinkableExtensions);
+ synchronizeTypes(package.types,
+ updatedTypeIds,
+ insertedAliasPropertyDeclarations,
+ updatedAliasPropertyDeclarations,
+ relinkableAliasPropertyDeclarations,
+ relinkablePropertyDeclarations,
+ relinkablePrototypes,
+ relinkableExtensions,
+ package.updatedSourceIds);
+ synchronizeTypeAnnotations(package.typeAnnotations, package.updatedTypeAnnotationSourceIds);
+ synchronizePropertyEditorQmlPaths(package.propertyEditorQmlPaths,
+ package.updatedPropertyEditorQmlPathSourceIds);
+
+ deleteNotUpdatedTypes(updatedTypeIds,
+ package.updatedSourceIds,
+ typeIdsToBeDeleted,
+ relinkableAliasPropertyDeclarations,
+ relinkablePropertyDeclarations,
+ relinkablePrototypes,
+ relinkableExtensions,
+ deletedTypeIds);
+
+ relink(relinkableAliasPropertyDeclarations,
+ relinkablePropertyDeclarations,
+ relinkablePrototypes,
+ relinkableExtensions,
+ deletedTypeIds);
+
+ linkAliases(insertedAliasPropertyDeclarations, updatedAliasPropertyDeclarations);
+
+ synchronizeDirectoryInfos(package.directoryInfos, package.updatedDirectoryInfoSourceIds);
+
+ commonTypeCache_.resetTypeIds();
+ });
+
+ callRefreshMetaInfoCallback(deletedTypeIds);
+}
+
+void ProjectStorage::synchronizeDocumentImports(Storage::Imports imports, SourceId sourceId)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"synchronize document imports"_t,
+ projectStorageCategory(),
+ keyValue("imports", imports),
+ keyValue("source id", sourceId)};
+
+ Sqlite::withImmediateTransaction(database, [&] {
+ AliasPropertyDeclarations relinkableAliasPropertyDeclarations;
+ PropertyDeclarations relinkablePropertyDeclarations;
+ Prototypes relinkablePrototypes;
+ Prototypes relinkableExtensions;
+ TypeIds deletedTypeIds;
+
+ synchronizeDocumentImports(imports,
+ {sourceId},
+ Storage::Synchronization::ImportKind::Import,
+ Relink::Yes,
+ relinkablePrototypes,
+ relinkableExtensions);
+
+ relink(relinkableAliasPropertyDeclarations,
+ relinkablePropertyDeclarations,
+ relinkablePrototypes,
+ relinkableExtensions,
+ deletedTypeIds);
+ });
+}
+
+void ProjectStorage::addObserver(ProjectStorageObserver *observer)
+{
+ NanotraceHR::Tracer tracer{"add observer"_t, projectStorageCategory()};
+ observers.push_back(observer);
+}
+
+void ProjectStorage::removeObserver(ProjectStorageObserver *observer)
+{
+ NanotraceHR::Tracer tracer{"remove observer"_t, projectStorageCategory()};
+ observers.removeOne(observer);
+}
+
+ModuleId ProjectStorage::moduleId(Utils::SmallStringView moduleName, Storage::ModuleKind kind) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get module id"_t,
+ projectStorageCategory(),
+ keyValue("module name", moduleName)};
+
+ auto moduleId = moduleCache.id({moduleName, kind});
+
+ tracer.end(keyValue("module id", moduleId));
+
+ return moduleId;
+}
+
+Storage::Module ProjectStorage::module(ModuleId moduleId) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get module name"_t,
+ projectStorageCategory(),
+ keyValue("module id", moduleId)};
+
+ if (!moduleId)
+ throw ModuleDoesNotExists{};
+
+ auto module = moduleCache.value(moduleId);
+
+ tracer.end(keyValue("module name", module.name));
+ tracer.end(keyValue("module kind", module.kind));
+
+ return {module.name, module.kind};
+}
+
+TypeId ProjectStorage::typeId(ModuleId moduleId,
+ Utils::SmallStringView exportedTypeName,
+ Storage::Version version) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get type id by exported name"_t,
+ projectStorageCategory(),
+ keyValue("module id", moduleId),
+ keyValue("exported type name", exportedTypeName),
+ keyValue("version", version)};
+
+ TypeId typeId;
+
+ if (version.minor) {
+ typeId = s->selectTypeIdByModuleIdAndExportedNameAndVersionStatement.valueWithTransaction<TypeId>(
+ moduleId, exportedTypeName, version.major.value, version.minor.value);
+
+ } else if (version.major) {
+ typeId = s->selectTypeIdByModuleIdAndExportedNameAndMajorVersionStatement
+ .valueWithTransaction<TypeId>(moduleId, exportedTypeName, version.major.value);
+
+ } else {
+ typeId = s->selectTypeIdByModuleIdAndExportedNameStatement
+ .valueWithTransaction<TypeId>(moduleId, exportedTypeName);
+ }
+
+ tracer.end(keyValue("type id", typeId));
+
+ return typeId;
+}
+
+TypeId ProjectStorage::typeId(ImportedTypeNameId typeNameId) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get type id by imported type name"_t,
+ projectStorageCategory(),
+ keyValue("imported type name id", typeNameId)};
+
+ auto typeId = Sqlite::withDeferredTransaction(database, [&] { return fetchTypeId(typeNameId); });
+
+ tracer.end(keyValue("type id", typeId));
+
+ return typeId;
+}
+
+QVarLengthArray<TypeId, 256> ProjectStorage::typeIds(ModuleId moduleId) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get type ids by module id"_t,
+ projectStorageCategory(),
+ keyValue("module id", moduleId)};
+
+ auto typeIds = s->selectTypeIdsByModuleIdStatement
+ .valuesWithTransaction<QVarLengthArray<TypeId, 256>>(moduleId);
+
+ tracer.end(keyValue("type ids", typeIds));
+
+ return typeIds;
+}
+
+Storage::Info::ExportedTypeNames ProjectStorage::exportedTypeNames(TypeId typeId) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get exported type names by type id"_t,
+ projectStorageCategory(),
+ keyValue("type id", typeId)};
+
+ auto exportedTypenames = s->selectExportedTypesByTypeIdStatement
+ .valuesWithTransaction<Storage::Info::ExportedTypeName, 4>(typeId);
+
+ tracer.end(keyValue("exported type names", exportedTypenames));
+
+ return exportedTypenames;
+}
+
+Storage::Info::ExportedTypeNames ProjectStorage::exportedTypeNames(TypeId typeId, SourceId sourceId) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get exported type names by source id"_t,
+ projectStorageCategory(),
+ keyValue("type id", typeId),
+ keyValue("source id", sourceId)};
+
+ auto exportedTypenames = s->selectExportedTypesByTypeIdAndSourceIdStatement
+ .valuesWithTransaction<Storage::Info::ExportedTypeName, 4>(typeId,
+ sourceId);
+
+ tracer.end(keyValue("exported type names", exportedTypenames));
+
+ return exportedTypenames;
+}
+
+ImportId ProjectStorage::importId(const Storage::Import &import) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get import id by import"_t,
+ projectStorageCategory(),
+ keyValue("import", import)};
+
+ auto importId = Sqlite::withDeferredTransaction(database, [&] {
+ return fetchImportId(import.sourceId, import);
+ });
+
+ tracer.end(keyValue("import id", importId));
+
+ return importId;
+}
+
+ImportedTypeNameId ProjectStorage::importedTypeNameId(ImportId importId,
+ Utils::SmallStringView typeName)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get imported type name id by import id"_t,
+ projectStorageCategory(),
+ keyValue("import id", importId),
+ keyValue("imported type name", typeName)};
+
+ auto importedTypeNameId = Sqlite::withDeferredTransaction(database, [&] {
+ return fetchImportedTypeNameId(Storage::Synchronization::TypeNameKind::QualifiedExported,
+ importId,
+ typeName);
+ });
+
+ tracer.end(keyValue("imported type name id", importedTypeNameId));
+
+ return importedTypeNameId;
+}
+
+ImportedTypeNameId ProjectStorage::importedTypeNameId(SourceId sourceId,
+ Utils::SmallStringView typeName)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get imported type name id by source id"_t,
+ projectStorageCategory(),
+ keyValue("source id", sourceId),
+ keyValue("imported type name", typeName)};
+
+ auto importedTypeNameId = Sqlite::withDeferredTransaction(database, [&] {
+ return fetchImportedTypeNameId(Storage::Synchronization::TypeNameKind::Exported,
+ sourceId,
+ typeName);
+ });
+
+ tracer.end(keyValue("imported type name id", importedTypeNameId));
+
+ return importedTypeNameId;
+}
+
+QVarLengthArray<PropertyDeclarationId, 128> ProjectStorage::propertyDeclarationIds(TypeId typeId) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get property declaration ids"_t,
+ projectStorageCategory(),
+ keyValue("type id", typeId)};
+
+ auto propertyDeclarationIds = Sqlite::withDeferredTransaction(database, [&] {
+ return fetchPropertyDeclarationIds(typeId);
+ });
+
+ std::sort(propertyDeclarationIds.begin(), propertyDeclarationIds.end());
+
+ tracer.end(keyValue("property declaration ids", propertyDeclarationIds));
+
+ return propertyDeclarationIds;
+}
+
+QVarLengthArray<PropertyDeclarationId, 128> ProjectStorage::localPropertyDeclarationIds(TypeId typeId) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get local property declaration ids"_t,
+ projectStorageCategory(),
+ keyValue("type id", typeId)};
+
+ auto propertyDeclarationIds = s->selectLocalPropertyDeclarationIdsForTypeStatement
+ .valuesWithTransaction<QVarLengthArray<PropertyDeclarationId, 128>>(
+ typeId);
+
+ tracer.end(keyValue("property declaration ids", propertyDeclarationIds));
+
+ return propertyDeclarationIds;
+}
+
+PropertyDeclarationId ProjectStorage::propertyDeclarationId(TypeId typeId,
+ Utils::SmallStringView propertyName) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get property declaration id"_t,
+ projectStorageCategory(),
+ keyValue("type id", typeId),
+ keyValue("property name", propertyName)};
+
+ auto propertyDeclarationId = Sqlite::withDeferredTransaction(database, [&] {
+ return fetchPropertyDeclarationId(typeId, propertyName);
+ });
+
+ tracer.end(keyValue("property declaration id", propertyDeclarationId));
+
+ return propertyDeclarationId;
+}
+
+PropertyDeclarationId ProjectStorage::localPropertyDeclarationId(TypeId typeId,
+ Utils::SmallStringView propertyName) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get local property declaration id"_t,
+ projectStorageCategory(),
+ keyValue("type id", typeId),
+ keyValue("property name", propertyName)};
+
+ auto propertyDeclarationId = s->selectLocalPropertyDeclarationIdForTypeAndPropertyNameStatement
+ .valueWithTransaction<PropertyDeclarationId>(typeId,
+ propertyName);
+
+ tracer.end(keyValue("property declaration id", propertyDeclarationId));
+
+ return propertyDeclarationId;
+}
+
+PropertyDeclarationId ProjectStorage::defaultPropertyDeclarationId(TypeId typeId) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get default property declaration id"_t,
+ projectStorageCategory(),
+ keyValue("type id", typeId)};
+
+ auto propertyDeclarationId = Sqlite::withDeferredTransaction(database, [&] {
+ return fetchDefaultPropertyDeclarationId(typeId);
+ });
+
+ tracer.end(keyValue("property declaration id", propertyDeclarationId));
+
+ return propertyDeclarationId;
+}
+
+std::optional<Storage::Info::PropertyDeclaration> ProjectStorage::propertyDeclaration(
+ PropertyDeclarationId propertyDeclarationId) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get property declaration"_t,
+ projectStorageCategory(),
+ keyValue("property declaration id", propertyDeclarationId)};
+
+ auto propertyDeclaration = s->selectPropertyDeclarationForPropertyDeclarationIdStatement
+ .optionalValueWithTransaction<Storage::Info::PropertyDeclaration>(
+ propertyDeclarationId);
+
+ tracer.end(keyValue("property declaration", propertyDeclaration));
+
+ return propertyDeclaration;
+}
+
+std::optional<Storage::Info::Type> ProjectStorage::type(TypeId typeId) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get type"_t, projectStorageCategory(), keyValue("type id", typeId)};
+
+ auto type = s->selectInfoTypeByTypeIdStatement.optionalValueWithTransaction<Storage::Info::Type>(
+ typeId);
+
+ tracer.end(keyValue("type", type));
+
+ return type;
+}
+
+Utils::PathString ProjectStorage::typeIconPath(TypeId typeId) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get type icon path"_t,
+ projectStorageCategory(),
+ keyValue("type id", typeId)};
+
+ auto typeIconPath = s->selectTypeIconPathStatement.valueWithTransaction<Utils::PathString>(typeId);
+
+ tracer.end(keyValue("type icon path", typeIconPath));
+
+ return typeIconPath;
+}
+
+Storage::Info::TypeHints ProjectStorage::typeHints(TypeId typeId) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get type hints"_t,
+ projectStorageCategory(),
+ keyValue("type id", typeId)};
+
+ auto typeHints = s->selectTypeHintsStatement.valuesWithTransaction<Storage::Info::TypeHints, 4>(
+ typeId);
+
+ tracer.end(keyValue("type hints", typeHints));
+
+ return typeHints;
+}
+
+SmallSourceIds<4> ProjectStorage::typeAnnotationSourceIds(SourceId directoryId) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get type annotaion source ids"_t,
+ projectStorageCategory(),
+ keyValue("source id", directoryId)};
+
+ auto sourceIds = s->selectTypeAnnotationSourceIdsStatement.valuesWithTransaction<SmallSourceIds<4>>(
+ directoryId);
+
+ tracer.end(keyValue("source ids", sourceIds));
+
+ return sourceIds;
+}
+
+SmallSourceIds<64> ProjectStorage::typeAnnotationDirectorySourceIds() const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get type annotaion source ids"_t, projectStorageCategory()};
+
+ auto sourceIds = s->selectTypeAnnotationDirectorySourceIdsStatement
+ .valuesWithTransaction<SmallSourceIds<64>>();
+
+ tracer.end(keyValue("source ids", sourceIds));
+
+ return sourceIds;
+}
+
+Storage::Info::ItemLibraryEntries ProjectStorage::itemLibraryEntries(TypeId typeId) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get item library entries by type id"_t,
+ projectStorageCategory(),
+ keyValue("type id", typeId)};
+
+ using Storage::Info::ItemLibraryProperties;
+ Storage::Info::ItemLibraryEntries entries;
+
+ auto callback = [&](TypeId typeId_,
+ Utils::SmallStringView typeName,
+ Utils::SmallStringView name,
+ Utils::SmallStringView iconPath,
+ Utils::SmallStringView category,
+ Utils::SmallStringView import,
+ Utils::SmallStringView toolTip,
+ Utils::SmallStringView properties,
+ Utils::SmallStringView extraFilePaths,
+ Utils::SmallStringView templatePath) {
+ auto &last = entries.emplace_back(
+ typeId_, typeName, name, iconPath, category, import, toolTip, templatePath);
+ if (properties.size())
+ s->selectItemLibraryPropertiesStatement.readTo(last.properties, properties);
+ if (extraFilePaths.size())
+ s->selectItemLibraryExtraFilePathsStatement.readTo(last.extraFilePaths, extraFilePaths);
+ };
+
+ s->selectItemLibraryEntriesByTypeIdStatement.readCallbackWithTransaction(callback, typeId);
+
+ tracer.end(keyValue("item library entries", entries));
+
+ return entries;
+}
+
+Storage::Info::ItemLibraryEntries ProjectStorage::itemLibraryEntries(ImportId importId) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get item library entries by import id"_t,
+ projectStorageCategory(),
+ keyValue("import id", importId)};
+
+ using Storage::Info::ItemLibraryProperties;
+ Storage::Info::ItemLibraryEntries entries;
+
+ auto callback = [&](TypeId typeId_,
+ Utils::SmallStringView typeName,
+ Utils::SmallStringView name,
+ Utils::SmallStringView iconPath,
+ Utils::SmallStringView category,
+ Utils::SmallStringView import,
+ Utils::SmallStringView toolTip,
+ Utils::SmallStringView properties,
+ Utils::SmallStringView extraFilePaths,
+ Utils::SmallStringView templatePath) {
+ auto &last = entries.emplace_back(
+ typeId_, typeName, name, iconPath, category, import, toolTip, templatePath);
+ if (properties.size())
+ s->selectItemLibraryPropertiesStatement.readTo(last.properties, properties);
+ if (extraFilePaths.size())
+ s->selectItemLibraryExtraFilePathsStatement.readTo(last.extraFilePaths, extraFilePaths);
+ };
+
+ s->selectItemLibraryEntriesByTypeIdStatement.readCallbackWithTransaction(callback, importId);
+
+ tracer.end(keyValue("item library entries", entries));
+
+ return entries;
+}
+
+Storage::Info::ItemLibraryEntries ProjectStorage::itemLibraryEntries(SourceId sourceId) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get item library entries by source id"_t,
+ projectStorageCategory(),
+ keyValue("source id", sourceId)};
+
+ using Storage::Info::ItemLibraryProperties;
+ Storage::Info::ItemLibraryEntries entries;
+
+ auto callback = [&](TypeId typeId,
+ Utils::SmallStringView typeName,
+ Utils::SmallStringView name,
+ Utils::SmallStringView iconPath,
+ Utils::SmallStringView category,
+ Utils::SmallStringView import,
+ Utils::SmallStringView toolTip,
+ Utils::SmallStringView properties,
+ Utils::SmallStringView extraFilePaths,
+ Utils::SmallStringView templatePath) {
+ auto &last = entries.emplace_back(
+ typeId, typeName, name, iconPath, category, import, toolTip, templatePath);
+ if (properties.size())
+ s->selectItemLibraryPropertiesStatement.readTo(last.properties, properties);
+ if (extraFilePaths.size())
+ s->selectItemLibraryExtraFilePathsStatement.readTo(last.extraFilePaths, extraFilePaths);
+ };
+
+ s->selectItemLibraryEntriesBySourceIdStatement.readCallbackWithTransaction(callback, sourceId);
+
+ tracer.end(keyValue("item library entries", entries));
+
+ return entries;
+}
+
+Storage::Info::ItemLibraryEntries ProjectStorage::allItemLibraryEntries() const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get all item library entries"_t, projectStorageCategory()};
+
+ using Storage::Info::ItemLibraryProperties;
+ Storage::Info::ItemLibraryEntries entries;
+
+ auto callback = [&](TypeId typeId,
+ Utils::SmallStringView typeName,
+ Utils::SmallStringView name,
+ Utils::SmallStringView iconPath,
+ Utils::SmallStringView category,
+ Utils::SmallStringView import,
+ Utils::SmallStringView toolTip,
+ Utils::SmallStringView properties,
+ Utils::SmallStringView extraFilePaths,
+ Utils::SmallStringView templatePath) {
+ auto &last = entries.emplace_back(
+ typeId, typeName, name, iconPath, category, import, toolTip, templatePath);
+ if (properties.size())
+ s->selectItemLibraryPropertiesStatement.readTo(last.properties, properties);
+ if (extraFilePaths.size())
+ s->selectItemLibraryExtraFilePathsStatement.readTo(last.extraFilePaths, extraFilePaths);
+ };
+
+ s->selectItemLibraryEntriesStatement.readCallbackWithTransaction(callback);
+
+ tracer.end(keyValue("item library entries", entries));
+
+ return entries;
+}
+
+std::vector<Utils::SmallString> ProjectStorage::signalDeclarationNames(TypeId typeId) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get signal names"_t,
+ projectStorageCategory(),
+ keyValue("type id", typeId)};
+
+ auto signalDeclarationNames = s->selectSignalDeclarationNamesForTypeStatement
+ .valuesWithTransaction<Utils::SmallString, 32>(typeId);
+
+ tracer.end(keyValue("signal names", signalDeclarationNames));
+
+ return signalDeclarationNames;
+}
+
+std::vector<Utils::SmallString> ProjectStorage::functionDeclarationNames(TypeId typeId) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get function names"_t,
+ projectStorageCategory(),
+ keyValue("type id", typeId)};
+
+ auto functionDeclarationNames = s->selectFuncionDeclarationNamesForTypeStatement
+ .valuesWithTransaction<Utils::SmallString, 32>(typeId);
+
+ tracer.end(keyValue("function names", functionDeclarationNames));
+
+ return functionDeclarationNames;
+}
+
+std::optional<Utils::SmallString> ProjectStorage::propertyName(
+ PropertyDeclarationId propertyDeclarationId) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get property name"_t,
+ projectStorageCategory(),
+ keyValue("property declaration id", propertyDeclarationId)};
+
+ auto propertyName = s->selectPropertyNameStatement.optionalValueWithTransaction<Utils::SmallString>(
+ propertyDeclarationId);
+
+ tracer.end(keyValue("property name", propertyName));
+
+ return propertyName;
+}
+
+SmallTypeIds<16> ProjectStorage::prototypeIds(TypeId type) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get prototypes"_t, projectStorageCategory(), keyValue("type id", type)};
+
+ auto prototypeIds = s->selectPrototypeAndExtensionIdsStatement
+ .valuesWithTransaction<SmallTypeIds<16>>(type);
+
+ tracer.end(keyValue("type ids", prototypeIds));
+
+ return prototypeIds;
+}
+
+SmallTypeIds<16> ProjectStorage::prototypeAndSelfIds(TypeId typeId) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get prototypes and self"_t, projectStorageCategory()};
+
+ SmallTypeIds<16> prototypeAndSelfIds;
+ prototypeAndSelfIds.push_back(typeId);
+
+ s->selectPrototypeAndExtensionIdsStatement.readToWithTransaction(prototypeAndSelfIds, typeId);
+
+ tracer.end(keyValue("type ids", prototypeAndSelfIds));
+
+ return prototypeAndSelfIds;
+}
+
+SmallTypeIds<64> ProjectStorage::heirIds(TypeId typeId) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get heirs"_t, projectStorageCategory()};
+
+ auto heirIds = s->selectHeirTypeIdsStatement.valuesWithTransaction<SmallTypeIds<64>>(typeId);
+
+ tracer.end(keyValue("type ids", heirIds));
+
+ return heirIds;
+}
+
+bool ProjectStorage::isBasedOn(TypeId) const
+{
+ return false;
+}
+
+bool ProjectStorage::isBasedOn(TypeId typeId, TypeId id1) const
+{
+ return isBasedOn_(typeId, id1);
+}
+
+bool ProjectStorage::isBasedOn(TypeId typeId, TypeId id1, TypeId id2) const
+{
+ return isBasedOn_(typeId, id1, id2);
+}
+
+bool ProjectStorage::isBasedOn(TypeId typeId, TypeId id1, TypeId id2, TypeId id3) const
+{
+ return isBasedOn_(typeId, id1, id2, id3);
+}
+
+bool ProjectStorage::isBasedOn(TypeId typeId, TypeId id1, TypeId id2, TypeId id3, TypeId id4) const
+{
+ return isBasedOn_(typeId, id1, id2, id3, id4);
+}
+
+bool ProjectStorage::isBasedOn(TypeId typeId, TypeId id1, TypeId id2, TypeId id3, TypeId id4, TypeId id5) const
+{
+ return isBasedOn_(typeId, id1, id2, id3, id4, id5);
+}
+
+bool ProjectStorage::isBasedOn(
+ TypeId typeId, TypeId id1, TypeId id2, TypeId id3, TypeId id4, TypeId id5, TypeId id6) const
+{
+ return isBasedOn_(typeId, id1, id2, id3, id4, id5, id6);
+}
+
+bool ProjectStorage::isBasedOn(
+ TypeId typeId, TypeId id1, TypeId id2, TypeId id3, TypeId id4, TypeId id5, TypeId id6, TypeId id7) const
+{
+ return isBasedOn_(typeId, id1, id2, id3, id4, id5, id6, id7);
+}
+
+TypeId ProjectStorage::fetchTypeIdByExportedName(Utils::SmallStringView name) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is based on"_t,
+ projectStorageCategory(),
+ keyValue("exported type name", name)};
+
+ auto typeId = s->selectTypeIdByExportedNameStatement.valueWithTransaction<TypeId>(name);
+
+ tracer.end(keyValue("type id", typeId));
+
+ return typeId;
+}
+
+TypeId ProjectStorage::fetchTypeIdByModuleIdsAndExportedName(ModuleIds moduleIds,
+ Utils::SmallStringView name) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch type id by module ids and exported name"_t,
+ projectStorageCategory(),
+ keyValue("module ids", NanotraceHR::array(moduleIds)),
+ keyValue("exported type name", name)};
+ auto typeId = s->selectTypeIdByModuleIdsAndExportedNameStatement.valueWithTransaction<TypeId>(
+ static_cast<void *>(moduleIds.data()), static_cast<long long>(moduleIds.size()), name);
+
+ tracer.end(keyValue("type id", typeId));
+
+ return typeId;
+}
+
+TypeId ProjectStorage::fetchTypeIdByName(SourceId sourceId, Utils::SmallStringView name)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch type id by name"_t,
+ projectStorageCategory(),
+ keyValue("source id", sourceId),
+ keyValue("internal type name", name)};
+
+ auto typeId = s->selectTypeIdBySourceIdAndNameStatement.valueWithTransaction<TypeId>(sourceId,
+ name);
+
+ tracer.end(keyValue("type id", typeId));
+
+ return typeId;
+}
+
+Storage::Synchronization::Type ProjectStorage::fetchTypeByTypeId(TypeId typeId)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch type by type id"_t,
+ projectStorageCategory(),
+ keyValue("type id", typeId)};
+
+ auto type = Sqlite::withDeferredTransaction(database, [&] {
+ auto type = s->selectTypeByTypeIdStatement.value<Storage::Synchronization::Type>(typeId);
+
+ type.exportedTypes = fetchExportedTypes(typeId);
+ type.propertyDeclarations = fetchPropertyDeclarations(type.typeId);
+ type.functionDeclarations = fetchFunctionDeclarations(type.typeId);
+ type.signalDeclarations = fetchSignalDeclarations(type.typeId);
+ type.enumerationDeclarations = fetchEnumerationDeclarations(type.typeId);
+
+ return type;
+ });
+
+ tracer.end(keyValue("type", type));
+
+ return type;
+}
+
+Storage::Synchronization::Types ProjectStorage::fetchTypes()
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch types"_t, projectStorageCategory()};
+
+ auto types = Sqlite::withDeferredTransaction(database, [&] {
+ auto types = s->selectTypesStatement.values<Storage::Synchronization::Type, 64>();
+
+ for (Storage::Synchronization::Type &type : types) {
+ type.exportedTypes = fetchExportedTypes(type.typeId);
+ type.propertyDeclarations = fetchPropertyDeclarations(type.typeId);
+ type.functionDeclarations = fetchFunctionDeclarations(type.typeId);
+ type.signalDeclarations = fetchSignalDeclarations(type.typeId);
+ type.enumerationDeclarations = fetchEnumerationDeclarations(type.typeId);
+ }
+
+ return types;
+ });
+
+ tracer.end(keyValue("type", types));
+
+ return types;
+}
+
+SourceContextId ProjectStorage::fetchSourceContextIdUnguarded(Utils::SmallStringView sourceContextPath)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch source context id unguarded"_t, projectStorageCategory()};
+
+ auto sourceContextId = readSourceContextId(sourceContextPath);
+
+ return sourceContextId ? sourceContextId : writeSourceContextId(sourceContextPath);
+}
+
+SourceContextId ProjectStorage::fetchSourceContextId(Utils::SmallStringView sourceContextPath)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch source context id"_t,
+ projectStorageCategory(),
+ keyValue("source context path", sourceContextPath)};
+
+ SourceContextId sourceContextId;
+ try {
+ sourceContextId = Sqlite::withDeferredTransaction(database, [&] {
+ return fetchSourceContextIdUnguarded(sourceContextPath);
+ });
+ } catch (const Sqlite::ConstraintPreventsModification &) {
+ sourceContextId = fetchSourceContextId(sourceContextPath);
+ }
+
+ tracer.end(keyValue("source context id", sourceContextId));
+
+ return sourceContextId;
+}
+
+Utils::PathString ProjectStorage::fetchSourceContextPath(SourceContextId sourceContextId) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch source context path"_t,
+ projectStorageCategory(),
+ keyValue("source context id", sourceContextId)};
+
+ auto path = Sqlite::withDeferredTransaction(database, [&] {
+ auto optionalSourceContextPath = s->selectSourceContextPathFromSourceContextsBySourceContextIdStatement
+ .optionalValue<Utils::PathString>(sourceContextId);
+
+ if (!optionalSourceContextPath)
+ throw SourceContextIdDoesNotExists();
+
+ return std::move(*optionalSourceContextPath);
+ });
+
+ tracer.end(keyValue("source context path", path));
+
+ return path;
+}
+
+Cache::SourceContexts ProjectStorage::fetchAllSourceContexts() const
+{
+ NanotraceHR::Tracer tracer{"fetch all source contexts"_t, projectStorageCategory()};
+
+ return s->selectAllSourceContextsStatement.valuesWithTransaction<Cache::SourceContext, 128>();
+}
+
+SourceId ProjectStorage::fetchSourceId(SourceContextId sourceContextId,
+ Utils::SmallStringView sourceName)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch source id"_t,
+ projectStorageCategory(),
+ keyValue("source context id", sourceContextId),
+ keyValue("source name", sourceName)};
+
+ auto sourceId = Sqlite::withDeferredTransaction(database, [&] {
+ return fetchSourceIdUnguarded(sourceContextId, sourceName);
+ });
+
+ tracer.end(keyValue("source id", sourceId));
+
+ return sourceId;
+}
+
+Cache::SourceNameAndSourceContextId ProjectStorage::fetchSourceNameAndSourceContextId(SourceId sourceId) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch source name and source context id"_t,
+ projectStorageCategory(),
+ keyValue("source id", sourceId)};
+
+ auto value = s->selectSourceNameAndSourceContextIdFromSourcesBySourceIdStatement
+ .valueWithTransaction<Cache::SourceNameAndSourceContextId>(sourceId);
+
+ if (!value.sourceContextId)
+ throw SourceIdDoesNotExists();
+
+ tracer.end(keyValue("source name", value.sourceName),
+ keyValue("source context id", value.sourceContextId));
+
+ return value;
+}
+
+void ProjectStorage::clearSources()
+{
+ Sqlite::withImmediateTransaction(database, [&] {
+ s->deleteAllSourceContextsStatement.execute();
+ s->deleteAllSourcesStatement.execute();
+ });
+}
+
+SourceContextId ProjectStorage::fetchSourceContextId(SourceId sourceId) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch source context id"_t,
+ projectStorageCategory(),
+ keyValue("source id", sourceId)};
+
+ auto sourceContextId = s->selectSourceContextIdFromSourcesBySourceIdStatement
+ .valueWithTransaction<SourceContextId>(sourceId);
+
+ if (!sourceContextId)
+ throw SourceIdDoesNotExists();
+
+ tracer.end(keyValue("source context id", sourceContextId));
+
+ return sourceContextId;
+}
+
+Cache::Sources ProjectStorage::fetchAllSources() const
+{
+ NanotraceHR::Tracer tracer{"fetch all sources"_t, projectStorageCategory()};
+
+ return s->selectAllSourcesStatement.valuesWithTransaction<Cache::Source, 1024>();
+}
+
+SourceId ProjectStorage::fetchSourceIdUnguarded(SourceContextId sourceContextId,
+ Utils::SmallStringView sourceName)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch source id unguarded"_t,
+ projectStorageCategory(),
+ keyValue("source context id", sourceContextId),
+ keyValue("source name", sourceName)};
+
+ auto sourceId = readSourceId(sourceContextId, sourceName);
+
+ if (!sourceId)
+ sourceId = writeSourceId(sourceContextId, sourceName);
+
+ tracer.end(keyValue("source id", sourceId));
+
+ return sourceId;
+}
+
+FileStatuses ProjectStorage::fetchAllFileStatuses() const
+{
+ NanotraceHR::Tracer tracer{"fetch all file statuses"_t, projectStorageCategory()};
+
+ return s->selectAllFileStatusesStatement.valuesWithTransaction<FileStatus>();
+}
+
+FileStatus ProjectStorage::fetchFileStatus(SourceId sourceId) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch file status"_t,
+ projectStorageCategory(),
+ keyValue("source id", sourceId)};
+
+ auto fileStatus = s->selectFileStatusesForSourceIdStatement.valueWithTransaction<FileStatus>(
+ sourceId);
+
+ tracer.end(keyValue("file status", fileStatus));
+
+ return fileStatus;
+}
+
+std::optional<Storage::Synchronization::DirectoryInfo> ProjectStorage::fetchDirectoryInfo(SourceId sourceId) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch directory info"_t,
+ projectStorageCategory(),
+ keyValue("source id", sourceId)};
+
+ auto directoryInfo = s->selectDirectoryInfoForSourceIdStatement
+ .optionalValueWithTransaction<Storage::Synchronization::DirectoryInfo>(
+ sourceId);
+
+ tracer.end(keyValue("directory info", directoryInfo));
+
+ return directoryInfo;
+}
+
+Storage::Synchronization::DirectoryInfos ProjectStorage::fetchDirectoryInfos(SourceId directorySourceId) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch directory infos by source id"_t,
+ projectStorageCategory(),
+ keyValue("source id", directorySourceId)};
+
+ auto directoryInfos = s->selectDirectoryInfosForSourceIdStatement
+ .valuesWithTransaction<Storage::Synchronization::DirectoryInfo, 1024>(
+ directorySourceId);
+
+ tracer.end(keyValue("directory infos", directoryInfos));
+
+ return directoryInfos;
+}
+
+Storage::Synchronization::DirectoryInfos ProjectStorage::fetchDirectoryInfos(
+ SourceId directorySourceId, Storage::Synchronization::FileType fileType) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch directory infos by source id and file type"_t,
+ projectStorageCategory(),
+ keyValue("source id", directorySourceId),
+ keyValue("file type", fileType)};
+
+ auto directoryInfos = s->selectDirectoryInfosForSourceIdAndFileTypeStatement
+ .valuesWithTransaction<Storage::Synchronization::DirectoryInfo, 16>(
+ directorySourceId, fileType);
+
+ tracer.end(keyValue("directory infos", directoryInfos));
+
+ return directoryInfos;
+}
+
+Storage::Synchronization::DirectoryInfos ProjectStorage::fetchDirectoryInfos(
+ const SourceIds &directorySourceIds) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch directory infos by source ids"_t,
+ projectStorageCategory(),
+ keyValue("source ids", directorySourceIds)};
+
+ auto directoryInfos = s->selectDirectoryInfosForSourceIdsStatement
+ .valuesWithTransaction<Storage::Synchronization::DirectoryInfo, 64>(
+ toIntegers(directorySourceIds));
+
+ tracer.end(keyValue("directory infos", directoryInfos));
+
+ return directoryInfos;
+}
+
+SmallSourceIds<32> ProjectStorage::fetchSubdirectorySourceIds(SourceId directorySourceId) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch subdirectory source ids"_t,
+ projectStorageCategory(),
+ keyValue("source id", directorySourceId)};
+
+ auto sourceIds = s->selectDirectoryInfosSourceIdsForSourceIdAndFileTypeStatement
+ .valuesWithTransaction<SmallSourceIds<32>>(
+ directorySourceId, Storage::Synchronization::FileType::Directory);
+
+ tracer.end(keyValue("source ids", sourceIds));
+
+ return sourceIds;
+}
+
+void ProjectStorage::setPropertyEditorPathId(TypeId typeId, SourceId pathId)
+{
+ Sqlite::ImmediateSessionTransaction transaction{database};
+
+ s->upsertPropertyEditorPathIdStatement.write(typeId, pathId);
+
+ transaction.commit();
+}
+
+SourceId ProjectStorage::propertyEditorPathId(TypeId typeId) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"property editor path id"_t,
+ projectStorageCategory(),
+ keyValue("type id", typeId)};
+
+ auto sourceId = s->selectPropertyEditorPathIdStatement.valueWithTransaction<SourceId>(typeId);
+
+ tracer.end(keyValue("source id", sourceId));
+
+ return sourceId;
+}
+
+Storage::Imports ProjectStorage::fetchDocumentImports() const
+{
+ NanotraceHR::Tracer tracer{"fetch document imports"_t, projectStorageCategory()};
+
+ return s->selectAllDocumentImportForSourceIdStatement.valuesWithTransaction<Storage::Imports>();
+}
+
+void ProjectStorage::resetForTestsOnly()
+{
+ database.clearAllTablesForTestsOnly();
+ commonTypeCache_.clearForTestsOnly();
+ moduleCache.clearForTestOnly();
+}
+
+ModuleId ProjectStorage::fetchModuleId(Utils::SmallStringView moduleName,
+ Storage::ModuleKind moduleKind)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch module id"_t,
+ projectStorageCategory(),
+ keyValue("module name", moduleName),
+ keyValue("module kind", moduleKind)};
+
+ auto moduleId = Sqlite::withDeferredTransaction(database, [&] {
+ return fetchModuleIdUnguarded(moduleName, moduleKind);
+ });
+
+ tracer.end(keyValue("module id", moduleId));
+
+ return moduleId;
+}
+
+Storage::Module ProjectStorage::fetchModule(ModuleId id)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch module name"_t,
+ projectStorageCategory(),
+ keyValue("module id", id)};
+
+ auto module = Sqlite::withDeferredTransaction(database, [&] { return fetchModuleUnguarded(id); });
+
+ tracer.end(keyValue("module name", module.name));
+ tracer.end(keyValue("module name", module.kind));
+
+ return module;
+}
+
+ProjectStorage::ModuleCacheEntries ProjectStorage::fetchAllModules() const
+{
+ NanotraceHR::Tracer tracer{"fetch all modules"_t, projectStorageCategory()};
+
+ return s->selectAllModulesStatement.valuesWithTransaction<ModuleCacheEntry, 128>();
+}
+
+void ProjectStorage::callRefreshMetaInfoCallback(const TypeIds &deletedTypeIds)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"call refresh meta info callback"_t,
+ projectStorageCategory(),
+ keyValue("type ids", deletedTypeIds)};
+
+ if (deletedTypeIds.size()) {
+ for (ProjectStorageObserver *observer : observers)
+ observer->removedTypeIds(deletedTypeIds);
+ }
+}
+
+SourceIds ProjectStorage::filterSourceIdsWithoutType(const SourceIds &updatedSourceIds,
+ SourceIds &sourceIdsOfTypes)
+{
+ std::sort(sourceIdsOfTypes.begin(), sourceIdsOfTypes.end());
+
+ SourceIds sourceIdsWithoutTypeSourceIds;
+ sourceIdsWithoutTypeSourceIds.reserve(updatedSourceIds.size());
+ std::set_difference(updatedSourceIds.begin(),
+ updatedSourceIds.end(),
+ sourceIdsOfTypes.begin(),
+ sourceIdsOfTypes.end(),
+ std::back_inserter(sourceIdsWithoutTypeSourceIds));
+
+ return sourceIdsWithoutTypeSourceIds;
+}
+
+TypeIds ProjectStorage::fetchTypeIds(const SourceIds &sourceIds)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch type ids"_t,
+ projectStorageCategory(),
+ keyValue("source ids", sourceIds)};
+
+ return s->selectTypeIdsForSourceIdsStatement.values<TypeId, 128>(toIntegers(sourceIds));
+}
+
+void ProjectStorage::unique(SourceIds &sourceIds)
+{
+ std::sort(sourceIds.begin(), sourceIds.end());
+ auto newEnd = std::unique(sourceIds.begin(), sourceIds.end());
+ sourceIds.erase(newEnd, sourceIds.end());
+}
+
+void ProjectStorage::synchronizeTypeTraits(TypeId typeId, Storage::TypeTraits traits)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"synchronize type traits"_t,
+ projectStorageCategory(),
+ keyValue("type id", typeId),
+ keyValue("type traits", traits)};
+
+ s->updateTypeAnnotationTraitStatement.write(typeId, traits.annotation);
+}
+
+void ProjectStorage::updateTypeIdInTypeAnnotations(Storage::Synchronization::TypeAnnotations &typeAnnotations)
+{
+ NanotraceHR::Tracer tracer{"update type id in type annotations"_t, projectStorageCategory()};
+
+ for (auto &annotation : typeAnnotations) {
+ annotation.typeId = fetchTypeIdByModuleIdAndExportedName(annotation.moduleId,
+ annotation.typeName);
+ }
+
+ typeAnnotations.erase(std::remove_if(typeAnnotations.begin(),
+ typeAnnotations.end(),
+ [](const auto &annotation) { return !annotation.typeId; }),
+ typeAnnotations.end());
+}
+
+void ProjectStorage::synchronizeTypeAnnotations(Storage::Synchronization::TypeAnnotations &typeAnnotations,
+ const SourceIds &updatedTypeAnnotationSourceIds)
+{
+ NanotraceHR::Tracer tracer{"synchronize type annotations"_t, projectStorageCategory()};
+
+ using Storage::Synchronization::TypeAnnotation;
+
+ updateTypeIdInTypeAnnotations(typeAnnotations);
+
+ auto compareKey = [](auto &&first, auto &&second) { return first.typeId - second.typeId; };
+
+ std::sort(typeAnnotations.begin(), typeAnnotations.end(), [&](auto &&first, auto &&second) {
+ return first.typeId < second.typeId;
+ });
+
+ auto range = s->selectTypeAnnotationsForSourceIdsStatement.range<TypeAnnotationView>(
+ toIntegers(updatedTypeAnnotationSourceIds));
+
+ auto insert = [&](const TypeAnnotation &annotation) {
+ if (!annotation.sourceId)
+ throw TypeAnnotationHasInvalidSourceId{};
+
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"insert type annotations"_t,
+ projectStorageCategory(),
+ keyValue("type annotation", annotation)};
+
+ s->insertTypeAnnotationStatement.write(annotation.typeId,
+ annotation.sourceId,
+ annotation.directorySourceId,
+ annotation.typeName,
+ annotation.iconPath,
+ createEmptyAsNull(annotation.itemLibraryJson),
+ createEmptyAsNull(annotation.hintsJson));
+
+ synchronizeTypeTraits(annotation.typeId, annotation.traits);
+ };
+
+ auto update = [&](const TypeAnnotationView &annotationFromDatabase,
+ const TypeAnnotation &annotation) {
+
+ if (annotationFromDatabase.typeName != annotation.typeName
+ || annotationFromDatabase.iconPath != annotation.iconPath
+ || annotationFromDatabase.itemLibraryJson != annotation.itemLibraryJson
+ || annotationFromDatabase.hintsJson != annotation.hintsJson) {
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"update type annotations"_t,
+ projectStorageCategory(),
+ keyValue("type annotation from database",
+ annotationFromDatabase),
+ keyValue("type annotation", annotation)};
+
+ s->updateTypeAnnotationStatement.write(annotation.typeId,
+ annotation.typeName,
+ annotation.iconPath,
+ createEmptyAsNull(annotation.itemLibraryJson),
+ createEmptyAsNull(annotation.hintsJson));
+
+ synchronizeTypeTraits(annotation.typeId, annotation.traits);
+
+ return Sqlite::UpdateChange::Update;
+ }
+
+ synchronizeTypeTraits(annotation.typeId, annotation.traits);
+
+ return Sqlite::UpdateChange::No;
+ };
+
+ auto remove = [&](const TypeAnnotationView &annotationFromDatabase) {
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"remove type annotations"_t,
+ projectStorageCategory(),
+ keyValue("type annotation", annotationFromDatabase)};
+
+ auto prototypeAnnotationTraits = s->selectPrototypeAnnotationTraitsByTypeIdStatement
+ .value<long long>(annotationFromDatabase.typeId);
+ s->deleteTypeAnnotationStatement.write(annotationFromDatabase.typeId);
+
+ s->updateTypeAnnotationTraitStatement.write(annotationFromDatabase.typeId,
+ prototypeAnnotationTraits);
+ };
+
+ Sqlite::insertUpdateDelete(range, typeAnnotations, compareKey, insert, update, remove);
+}
+
+void ProjectStorage::synchronizeTypeTrait(const Storage::Synchronization::Type &type)
+{
+ s->updateTypeTraitStatement.write(type.typeId, type.traits.type);
+}
+
+void ProjectStorage::synchronizeTypes(Storage::Synchronization::Types &types,
+ TypeIds &updatedTypeIds,
+ AliasPropertyDeclarations &insertedAliasPropertyDeclarations,
+ AliasPropertyDeclarations &updatedAliasPropertyDeclarations,
+ AliasPropertyDeclarations &relinkableAliasPropertyDeclarations,
+ PropertyDeclarations &relinkablePropertyDeclarations,
+ Prototypes &relinkablePrototypes,
+ Prototypes &relinkableExtensions,
+ const SourceIds &updatedSourceIds)
+{
+ NanotraceHR::Tracer tracer{"synchronize types"_t, projectStorageCategory()};
+
+ Storage::Synchronization::ExportedTypes exportedTypes;
+ exportedTypes.reserve(types.size() * 3);
+ SourceIds sourceIdsOfTypes;
+ sourceIdsOfTypes.reserve(updatedSourceIds.size());
+ SourceIds notUpdatedExportedSourceIds;
+ notUpdatedExportedSourceIds.reserve(updatedSourceIds.size());
+ SourceIds exportedSourceIds;
+ exportedSourceIds.reserve(types.size());
+
+ for (auto &type : types) {
+ if (!type.sourceId)
+ throw TypeHasInvalidSourceId{};
+
+ TypeId typeId = declareType(type);
+ synchronizeTypeTrait(type);
+ sourceIdsOfTypes.push_back(type.sourceId);
+ updatedTypeIds.push_back(typeId);
+ if (type.changeLevel != Storage::Synchronization::ChangeLevel::ExcludeExportedTypes) {
+ exportedSourceIds.push_back(type.sourceId);
+ extractExportedTypes(typeId, type, exportedTypes);
+ }
+ }
+
+ std::sort(types.begin(), types.end(), [](const auto &first, const auto &second) {
+ return first.typeId < second.typeId;
+ });
+
+ unique(exportedSourceIds);
+
+ SourceIds sourceIdsWithoutType = filterSourceIdsWithoutType(updatedSourceIds, sourceIdsOfTypes);
+ exportedSourceIds.insert(exportedSourceIds.end(),
+ sourceIdsWithoutType.begin(),
+ sourceIdsWithoutType.end());
+ TypeIds exportedTypeIds = fetchTypeIds(exportedSourceIds);
+ synchronizeExportedTypes(exportedTypeIds,
+ exportedTypes,
+ relinkableAliasPropertyDeclarations,
+ relinkablePropertyDeclarations,
+ relinkablePrototypes,
+ relinkableExtensions);
+
+ syncPrototypesAndExtensions(types, relinkablePrototypes, relinkableExtensions);
+ resetDefaultPropertiesIfChanged(types);
+ resetRemovedAliasPropertyDeclarationsToNull(types, relinkableAliasPropertyDeclarations);
+ syncDeclarations(types,
+ insertedAliasPropertyDeclarations,
+ updatedAliasPropertyDeclarations,
+ relinkablePropertyDeclarations);
+ syncDefaultProperties(types);
+}
+
+void ProjectStorage::synchronizeDirectoryInfos(Storage::Synchronization::DirectoryInfos &directoryInfos,
+ const SourceIds &updatedDirectoryInfoSourceIds)
+{
+ NanotraceHR::Tracer tracer{"synchronize directory infos"_t, projectStorageCategory()};
+
+ auto compareKey = [](auto &&first, auto &&second) {
+ auto directorySourceIdDifference = first.directorySourceId - second.directorySourceId;
+ if (directorySourceIdDifference != 0)
+ return directorySourceIdDifference;
+
+ return first.sourceId - second.sourceId;
+ };
+
+ std::sort(directoryInfos.begin(), directoryInfos.end(), [&](auto &&first, auto &&second) {
+ return std::tie(first.directorySourceId, first.sourceId)
+ < std::tie(second.directorySourceId, second.sourceId);
+ });
+
+ auto range = s->selectDirectoryInfosForSourceIdsStatement.range<Storage::Synchronization::DirectoryInfo>(
+ toIntegers(updatedDirectoryInfoSourceIds));
+
+ auto insert = [&](const Storage::Synchronization::DirectoryInfo &directoryInfo) {
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"insert directory info"_t,
+ projectStorageCategory(),
+ keyValue("directory info", directoryInfo)};
+
+ if (!directoryInfo.directorySourceId)
+ throw DirectoryInfoHasInvalidProjectSourceId{};
+ if (!directoryInfo.sourceId)
+ throw DirectoryInfoHasInvalidSourceId{};
+
+ s->insertDirectoryInfoStatement.write(directoryInfo.directorySourceId,
+ directoryInfo.sourceId,
+ directoryInfo.moduleId,
+ directoryInfo.fileType);
+ };
+
+ auto update = [&](const Storage::Synchronization::DirectoryInfo &directoryInfoFromDatabase,
+ const Storage::Synchronization::DirectoryInfo &directoryInfo) {
+ if (directoryInfoFromDatabase.fileType != directoryInfo.fileType
+ || !compareInvalidAreTrue(directoryInfoFromDatabase.moduleId, directoryInfo.moduleId)) {
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"update directory info"_t,
+ projectStorageCategory(),
+ keyValue("directory info", directoryInfo),
+ keyValue("directory info from database",
+ directoryInfoFromDatabase)};
+
+ s->updateDirectoryInfoStatement.write(directoryInfo.directorySourceId,
+ directoryInfo.sourceId,
+ directoryInfo.moduleId,
+ directoryInfo.fileType);
+ return Sqlite::UpdateChange::Update;
+ }
+
+ return Sqlite::UpdateChange::No;
+ };
+
+ auto remove = [&](const Storage::Synchronization::DirectoryInfo &directoryInfo) {
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"remove directory info"_t,
+ projectStorageCategory(),
+ keyValue("directory info", directoryInfo)};
+
+ s->deleteDirectoryInfoStatement.write(directoryInfo.directorySourceId, directoryInfo.sourceId);
+ };
+
+ Sqlite::insertUpdateDelete(range, directoryInfos, compareKey, insert, update, remove);
+}
+
+void ProjectStorage::synchronizeFileStatuses(FileStatuses &fileStatuses,
+ const SourceIds &updatedSourceIds)
+{
+ NanotraceHR::Tracer tracer{"synchronize file statuses"_t, projectStorageCategory()};
+
+ auto compareKey = [](auto &&first, auto &&second) { return first.sourceId - second.sourceId; };
+
+ std::sort(fileStatuses.begin(), fileStatuses.end(), [&](auto &&first, auto &&second) {
+ return first.sourceId < second.sourceId;
+ });
+
+ auto range = s->selectFileStatusesForSourceIdsStatement.range<FileStatus>(
+ toIntegers(updatedSourceIds));
+
+ auto insert = [&](const FileStatus &fileStatus) {
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"insert file status"_t,
+ projectStorageCategory(),
+ keyValue("file status", fileStatus)};
+
+ if (!fileStatus.sourceId)
+ throw FileStatusHasInvalidSourceId{};
+ s->insertFileStatusStatement.write(fileStatus.sourceId,
+ fileStatus.size,
+ fileStatus.lastModified);
+ };
+
+ auto update = [&](const FileStatus &fileStatusFromDatabase, const FileStatus &fileStatus) {
+ if (fileStatusFromDatabase.lastModified != fileStatus.lastModified
+ || fileStatusFromDatabase.size != fileStatus.size) {
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"update file status"_t,
+ projectStorageCategory(),
+ keyValue("file status", fileStatus),
+ keyValue("file status from database", fileStatusFromDatabase)};
+
+ s->updateFileStatusStatement.write(fileStatus.sourceId,
+ fileStatus.size,
+ fileStatus.lastModified);
+ return Sqlite::UpdateChange::Update;
+ }
+
+ return Sqlite::UpdateChange::No;
+ };
+
+ auto remove = [&](const FileStatus &fileStatus) {
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"remove file status"_t,
+ projectStorageCategory(),
+ keyValue("file status", fileStatus)};
+
+ s->deleteFileStatusStatement.write(fileStatus.sourceId);
+ };
+
+ Sqlite::insertUpdateDelete(range, fileStatuses, compareKey, insert, update, remove);
+}
+
+void ProjectStorage::synchronizeImports(Storage::Imports &imports,
+ const SourceIds &updatedSourceIds,
+ Storage::Imports &moduleDependencies,
+ const SourceIds &updatedModuleDependencySourceIds,
+ Storage::Synchronization::ModuleExportedImports &moduleExportedImports,
+ const ModuleIds &updatedModuleIds,
+ Prototypes &relinkablePrototypes,
+ Prototypes &relinkableExtensions)
+{
+ NanotraceHR::Tracer tracer{"synchronize imports"_t, projectStorageCategory()};
+
+ synchromizeModuleExportedImports(moduleExportedImports, updatedModuleIds);
+ NanotraceHR::Tracer importTracer{"synchronize qml document imports"_t, projectStorageCategory()};
+ synchronizeDocumentImports(imports,
+ updatedSourceIds,
+ Storage::Synchronization::ImportKind::Import,
+ Relink::No,
+ relinkablePrototypes,
+ relinkableExtensions);
+ importTracer.end();
+ NanotraceHR::Tracer moduleDependenciesTracer{"synchronize module depdencies"_t,
+ projectStorageCategory()};
+ synchronizeDocumentImports(moduleDependencies,
+ updatedModuleDependencySourceIds,
+ Storage::Synchronization::ImportKind::ModuleDependency,
+ Relink::Yes,
+ relinkablePrototypes,
+ relinkableExtensions);
+ moduleDependenciesTracer.end();
+}
+
+void ProjectStorage::synchromizeModuleExportedImports(
+ Storage::Synchronization::ModuleExportedImports &moduleExportedImports,
+ const ModuleIds &updatedModuleIds)
+{
+ NanotraceHR::Tracer tracer{"synchronize module exported imports"_t, projectStorageCategory()};
+ std::sort(moduleExportedImports.begin(),
+ moduleExportedImports.end(),
+ [](auto &&first, auto &&second) {
+ return std::tie(first.moduleId, first.exportedModuleId)
+ < std::tie(second.moduleId, second.exportedModuleId);
+ });
+
+ auto range = s->selectModuleExportedImportsForSourceIdStatement
+ .range<Storage::Synchronization::ModuleExportedImportView>(
+ toIntegers(updatedModuleIds));
+
+ auto compareKey = [](const Storage::Synchronization::ModuleExportedImportView &view,
+ const Storage::Synchronization::ModuleExportedImport &import) -> long long {
+ auto moduleIdDifference = view.moduleId - import.moduleId;
+ if (moduleIdDifference != 0)
+ return moduleIdDifference;
+
+ return view.exportedModuleId - import.exportedModuleId;
+ };
+
+ auto insert = [&](const Storage::Synchronization::ModuleExportedImport &import) {
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"insert module exported import"_t,
+ projectStorageCategory(),
+ keyValue("module exported import", import),
+ keyValue("module id", import.moduleId)};
+ tracer.tick("exported module"_t, keyValue("module id", import.exportedModuleId));
+
+ if (import.version.minor) {
+ s->insertModuleExportedImportWithVersionStatement.write(import.moduleId,
+ import.exportedModuleId,
+ import.isAutoVersion,
+ import.version.major.value,
+ import.version.minor.value);
+ } else if (import.version.major) {
+ s->insertModuleExportedImportWithMajorVersionStatement.write(import.moduleId,
+ import.exportedModuleId,
+ import.isAutoVersion,
+ import.version.major.value);
+ } else {
+ s->insertModuleExportedImportWithoutVersionStatement.write(import.moduleId,
+ import.exportedModuleId,
+ import.isAutoVersion);
+ }
+ };
+
+ auto update = [](const Storage::Synchronization::ModuleExportedImportView &,
+ const Storage::Synchronization::ModuleExportedImport &) {
+ return Sqlite::UpdateChange::No;
+ };
-template class QmlDesigner::ProjectStorage<Sqlite::Database>;
+ auto remove = [&](const Storage::Synchronization::ModuleExportedImportView &view) {
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"remove module exported import"_t,
+ projectStorageCategory(),
+ keyValue("module exported import view", view),
+ keyValue("module id", view.moduleId)};
+ tracer.tick("exported module"_t, keyValue("module id", view.exportedModuleId));
+
+ s->deleteModuleExportedImportStatement.write(view.moduleExportedImportId);
+ };
+
+ Sqlite::insertUpdateDelete(range, moduleExportedImports, compareKey, insert, update, remove);
+}
+
+ModuleId ProjectStorage::fetchModuleIdUnguarded(Utils::SmallStringView name,
+ Storage::ModuleKind kind) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch module id ungarded"_t,
+ projectStorageCategory(),
+ keyValue("module name", name),
+ keyValue("module kind", kind)};
+
+ auto moduleId = s->selectModuleIdByNameStatement.value<ModuleId>(kind, name);
+
+ if (!moduleId)
+ moduleId = s->insertModuleNameStatement.value<ModuleId>(kind, name);
+
+ tracer.end(keyValue("module id", moduleId));
+
+ return moduleId;
+}
+
+Storage::Module ProjectStorage::fetchModuleUnguarded(ModuleId id) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch module ungarded"_t,
+ projectStorageCategory(),
+ keyValue("module id", id)};
+
+ auto module = s->selectModuleStatement.value<Storage::Module>(id);
+
+ if (!module)
+ throw ModuleDoesNotExists{};
+
+ tracer.end(keyValue("module name", module.name));
+ tracer.end(keyValue("module name", module.kind));
+
+ return module;
+}
+
+void ProjectStorage::handleAliasPropertyDeclarationsWithPropertyType(
+ TypeId typeId, AliasPropertyDeclarations &relinkableAliasPropertyDeclarations)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"handle alias property declarations with property type"_t,
+ projectStorageCategory(),
+ keyValue("type id", typeId),
+ keyValue("relinkable alias property declarations",
+ relinkableAliasPropertyDeclarations)};
+
+ auto callback = [&](TypeId typeId_,
+ PropertyDeclarationId propertyDeclarationId,
+ ImportedTypeNameId propertyImportedTypeNameId,
+ PropertyDeclarationId aliasPropertyDeclarationId,
+ PropertyDeclarationId aliasPropertyDeclarationTailId) {
+ auto aliasPropertyName = s->selectPropertyNameStatement.value<Utils::SmallString>(
+ aliasPropertyDeclarationId);
+ Utils::SmallString aliasPropertyNameTail;
+ if (aliasPropertyDeclarationTailId)
+ aliasPropertyNameTail = s->selectPropertyNameStatement.value<Utils::SmallString>(
+ aliasPropertyDeclarationTailId);
+
+ relinkableAliasPropertyDeclarations.emplace_back(TypeId{typeId_},
+ PropertyDeclarationId{propertyDeclarationId},
+ ImportedTypeNameId{propertyImportedTypeNameId},
+ std::move(aliasPropertyName),
+ std::move(aliasPropertyNameTail));
+
+ s->updateAliasPropertyDeclarationToNullStatement.write(propertyDeclarationId);
+ };
+
+ s->selectAliasPropertiesDeclarationForPropertiesWithTypeIdStatement.readCallback(callback, typeId);
+}
+
+void ProjectStorage::handlePropertyDeclarationWithPropertyType(
+ TypeId typeId, PropertyDeclarations &relinkablePropertyDeclarations)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"handle property declarations with property type"_t,
+ projectStorageCategory(),
+ keyValue("type id", typeId),
+ keyValue("relinkable property declarations",
+ relinkablePropertyDeclarations)};
+
+ s->updatesPropertyDeclarationPropertyTypeToNullStatement.readTo(relinkablePropertyDeclarations,
+ typeId);
+}
+
+void ProjectStorage::handlePrototypes(TypeId prototypeId, Prototypes &relinkablePrototypes)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"handle prototypes"_t,
+ projectStorageCategory(),
+ keyValue("type id", prototypeId),
+ keyValue("relinkable prototypes", relinkablePrototypes)};
+
+ auto callback = [&](TypeId typeId, ImportedTypeNameId prototypeNameId) {
+ if (prototypeNameId)
+ relinkablePrototypes.emplace_back(typeId, prototypeNameId);
+ };
+
+ s->updatePrototypeIdToTypeIdStatement.readCallback(callback, prototypeId, unresolvedTypeId);
+}
+
+void ProjectStorage::handlePrototypesWithExportedTypeNameAndTypeId(
+ Utils::SmallStringView exportedTypeName, TypeId typeId, Prototypes &relinkablePrototypes)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"handle invalid prototypes"_t,
+ projectStorageCategory(),
+ keyValue("type id", exportedTypeName),
+ keyValue("relinkable prototypes", relinkablePrototypes)};
+
+ auto callback = [&](TypeId typeId, ImportedTypeNameId prototypeNameId) {
+ relinkablePrototypes.emplace_back(typeId, prototypeNameId);
+ };
+
+ s->selectTypeIdAndPrototypeNameIdForPrototypeIdAndTypeNameStatement.readCallback(callback,
+ exportedTypeName,
+ typeId);
+}
+
+void ProjectStorage::handleExtensions(TypeId extensionId, Prototypes &relinkableExtensions)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"handle extension"_t,
+ projectStorageCategory(),
+ keyValue("type id", extensionId),
+ keyValue("relinkable extensions", relinkableExtensions)};
+
+ auto callback = [&](TypeId typeId, ImportedTypeNameId extensionNameId) {
+ if (extensionNameId)
+ relinkableExtensions.emplace_back(typeId, extensionNameId);
+ };
+
+ s->updateExtensionIdToTypeIdStatement.readCallback(callback, extensionId, unresolvedTypeId);
+}
+
+void ProjectStorage::handleExtensionsWithExportedTypeNameAndTypeId(
+ Utils::SmallStringView exportedTypeName, TypeId typeId, Prototypes &relinkableExtensions)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"handle invalid extensions"_t,
+ projectStorageCategory(),
+ keyValue("type id", exportedTypeName),
+ keyValue("relinkable extensions", relinkableExtensions)};
+
+ auto callback = [&](TypeId typeId, ImportedTypeNameId extensionNameId) {
+ relinkableExtensions.emplace_back(typeId, extensionNameId);
+ };
+
+ s->selectTypeIdForExtensionIdAndTypeNameStatement.readCallback(callback, exportedTypeName, typeId);
+}
+
+void ProjectStorage::deleteType(TypeId typeId,
+ AliasPropertyDeclarations &relinkableAliasPropertyDeclarations,
+ PropertyDeclarations &relinkablePropertyDeclarations,
+ Prototypes &relinkablePrototypes,
+ Prototypes &relinkableExtensions)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"delete type"_t, projectStorageCategory(), keyValue("type id", typeId)};
+
+ handlePropertyDeclarationWithPropertyType(typeId, relinkablePropertyDeclarations);
+ handleAliasPropertyDeclarationsWithPropertyType(typeId, relinkableAliasPropertyDeclarations);
+ handlePrototypes(typeId, relinkablePrototypes);
+ handleExtensions(typeId, relinkableExtensions);
+ s->deleteTypeNamesByTypeIdStatement.write(typeId);
+ s->deleteEnumerationDeclarationByTypeIdStatement.write(typeId);
+ s->deletePropertyDeclarationByTypeIdStatement.write(typeId);
+ s->deleteFunctionDeclarationByTypeIdStatement.write(typeId);
+ s->deleteSignalDeclarationByTypeIdStatement.write(typeId);
+ s->deleteTypeStatement.write(typeId);
+}
+
+void ProjectStorage::relinkAliasPropertyDeclarations(AliasPropertyDeclarations &aliasPropertyDeclarations,
+ const TypeIds &deletedTypeIds)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"relink alias properties"_t,
+ projectStorageCategory(),
+ keyValue("alias property declarations", aliasPropertyDeclarations),
+ keyValue("deleted type ids", deletedTypeIds)};
+
+ std::sort(aliasPropertyDeclarations.begin(), aliasPropertyDeclarations.end());
+
+ Utils::set_greedy_difference(
+ aliasPropertyDeclarations.cbegin(),
+ aliasPropertyDeclarations.cend(),
+ deletedTypeIds.begin(),
+ deletedTypeIds.end(),
+ [&](const AliasPropertyDeclaration &alias) {
+ auto typeId = fetchTypeId(alias.aliasImportedTypeNameId);
+
+ if (!typeId)
+ throw TypeNameDoesNotExists{fetchImportedTypeName(alias.aliasImportedTypeNameId)};
+
+ auto [propertyTypeId, aliasId, propertyTraits] = fetchPropertyDeclarationByTypeIdAndNameUngarded(
+ typeId, alias.aliasPropertyName);
+
+ s->updatePropertyDeclarationWithAliasAndTypeStatement.write(alias.propertyDeclarationId,
+ propertyTypeId,
+ propertyTraits,
+ alias.aliasImportedTypeNameId,
+ aliasId);
+ },
+ TypeCompare<AliasPropertyDeclaration>{});
+}
+
+void ProjectStorage::relinkPropertyDeclarations(PropertyDeclarations &relinkablePropertyDeclaration,
+ const TypeIds &deletedTypeIds)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"relink property declarations"_t,
+ projectStorageCategory(),
+ keyValue("relinkable property declarations",
+ relinkablePropertyDeclaration),
+ keyValue("deleted type ids", deletedTypeIds)};
+
+ std::sort(relinkablePropertyDeclaration.begin(), relinkablePropertyDeclaration.end());
+
+ Utils::set_greedy_difference(
+ relinkablePropertyDeclaration.cbegin(),
+ relinkablePropertyDeclaration.cend(),
+ deletedTypeIds.begin(),
+ deletedTypeIds.end(),
+ [&](const PropertyDeclaration &property) {
+ TypeId propertyTypeId = fetchTypeId(property.importedTypeNameId);
+
+ if (!propertyTypeId)
+ throw TypeNameDoesNotExists{fetchImportedTypeName(property.importedTypeNameId)};
+
+ s->updatePropertyDeclarationTypeStatement.write(property.propertyDeclarationId,
+ propertyTypeId);
+ },
+ TypeCompare<PropertyDeclaration>{});
+}
+
+template<typename Callable>
+void ProjectStorage::relinkPrototypes(Prototypes &relinkablePrototypes,
+ const TypeIds &deletedTypeIds,
+ Callable updateStatement)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"relink prototypes"_t,
+ projectStorageCategory(),
+ keyValue("relinkable prototypes", relinkablePrototypes),
+ keyValue("deleted type ids", deletedTypeIds)};
+
+ std::sort(relinkablePrototypes.begin(), relinkablePrototypes.end());
+ relinkablePrototypes.erase(std::unique(relinkablePrototypes.begin(), relinkablePrototypes.end()),
+ relinkablePrototypes.end());
+
+ Utils::set_greedy_difference(
+ relinkablePrototypes.cbegin(),
+ relinkablePrototypes.cend(),
+ deletedTypeIds.begin(),
+ deletedTypeIds.end(),
+ [&](const Prototype &prototype) {
+ TypeId prototypeId = fetchTypeId(prototype.prototypeNameId);
+
+ if (!prototypeId)
+ errorNotifier->typeNameCannotBeResolved(fetchImportedTypeName(prototype.prototypeNameId),
+ fetchTypeSourceId(prototype.typeId));
+
+ updateStatement(prototype.typeId, prototypeId);
+ checkForPrototypeChainCycle(prototype.typeId);
+ },
+ TypeCompare<Prototype>{});
+}
+
+void ProjectStorage::deleteNotUpdatedTypes(const TypeIds &updatedTypeIds,
+ const SourceIds &updatedSourceIds,
+ const TypeIds &typeIdsToBeDeleted,
+ AliasPropertyDeclarations &relinkableAliasPropertyDeclarations,
+ PropertyDeclarations &relinkablePropertyDeclarations,
+ Prototypes &relinkablePrototypes,
+ Prototypes &relinkableExtensions,
+ TypeIds &deletedTypeIds)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"delete not updated types"_t,
+ projectStorageCategory(),
+ keyValue("updated type ids", updatedTypeIds),
+ keyValue("updated source ids", updatedSourceIds),
+ keyValue("type ids to be deleted", typeIdsToBeDeleted)};
+
+ auto callback = [&](TypeId typeId) {
+ deletedTypeIds.push_back(typeId);
+ deleteType(typeId,
+ relinkableAliasPropertyDeclarations,
+ relinkablePropertyDeclarations,
+ relinkablePrototypes,
+ relinkableExtensions);
+ };
+
+ s->selectNotUpdatedTypesInSourcesStatement.readCallback(callback,
+ toIntegers(updatedSourceIds),
+ toIntegers(updatedTypeIds));
+ for (TypeId typeIdToBeDeleted : typeIdsToBeDeleted)
+ callback(typeIdToBeDeleted);
+}
+
+void ProjectStorage::relink(AliasPropertyDeclarations &relinkableAliasPropertyDeclarations,
+ PropertyDeclarations &relinkablePropertyDeclarations,
+ Prototypes &relinkablePrototypes,
+ Prototypes &relinkableExtensions,
+ TypeIds &deletedTypeIds)
+{
+ NanotraceHR::Tracer tracer{"relink"_t, projectStorageCategory()};
+
+ std::sort(deletedTypeIds.begin(), deletedTypeIds.end());
+
+ relinkPrototypes(relinkablePrototypes, deletedTypeIds, [&](TypeId typeId, TypeId prototypeId) {
+ s->updateTypePrototypeStatement.write(typeId, prototypeId);
+ });
+ relinkPrototypes(relinkableExtensions, deletedTypeIds, [&](TypeId typeId, TypeId prototypeId) {
+ s->updateTypeExtensionStatement.write(typeId, prototypeId);
+ });
+ relinkPropertyDeclarations(relinkablePropertyDeclarations, deletedTypeIds);
+ relinkAliasPropertyDeclarations(relinkableAliasPropertyDeclarations, deletedTypeIds);
+}
+
+PropertyDeclarationId ProjectStorage::fetchAliasId(TypeId aliasTypeId,
+ Utils::SmallStringView aliasPropertyName,
+ Utils::SmallStringView aliasPropertyNameTail)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch alias id"_t,
+ projectStorageCategory(),
+ keyValue("alias type id", aliasTypeId),
+ keyValue("alias property name", aliasPropertyName),
+ keyValue("alias property name tail", aliasPropertyNameTail)};
+
+ if (aliasPropertyNameTail.empty())
+ return fetchPropertyDeclarationIdByTypeIdAndNameUngarded(aliasTypeId, aliasPropertyName);
+
+ auto stemAlias = fetchPropertyDeclarationByTypeIdAndNameUngarded(aliasTypeId, aliasPropertyName);
+
+ return fetchPropertyDeclarationIdByTypeIdAndNameUngarded(stemAlias.propertyTypeId,
+ aliasPropertyNameTail);
+}
+
+void ProjectStorage::linkAliasPropertyDeclarationAliasIds(const AliasPropertyDeclarations &aliasDeclarations)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"link alias property declarations alias ids"_t,
+ projectStorageCategory(),
+ keyValue("alias property declarations", aliasDeclarations)};
+
+ for (const auto &aliasDeclaration : aliasDeclarations) {
+ auto aliasTypeId = fetchTypeId(aliasDeclaration.aliasImportedTypeNameId);
+
+ if (!aliasTypeId) {
+ throw TypeNameDoesNotExists{
+ fetchImportedTypeName(aliasDeclaration.aliasImportedTypeNameId)};
+ }
+
+ auto aliasId = fetchAliasId(aliasTypeId,
+ aliasDeclaration.aliasPropertyName,
+ aliasDeclaration.aliasPropertyNameTail);
+
+ s->updatePropertyDeclarationAliasIdAndTypeNameIdStatement.write(
+ aliasDeclaration.propertyDeclarationId, aliasId, aliasDeclaration.aliasImportedTypeNameId);
+ }
+}
+
+void ProjectStorage::updateAliasPropertyDeclarationValues(const AliasPropertyDeclarations &aliasDeclarations)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"update alias property declarations"_t,
+ projectStorageCategory(),
+ keyValue("alias property declarations", aliasDeclarations)};
+
+ for (const auto &aliasDeclaration : aliasDeclarations) {
+ s->updatetPropertiesDeclarationValuesOfAliasStatement.write(
+ aliasDeclaration.propertyDeclarationId);
+ s->updatePropertyAliasDeclarationRecursivelyStatement.write(
+ aliasDeclaration.propertyDeclarationId);
+ }
+}
+
+void ProjectStorage::checkAliasPropertyDeclarationCycles(const AliasPropertyDeclarations &aliasDeclarations)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"check alias property declarations cycles"_t,
+ projectStorageCategory(),
+ keyValue("alias property declarations", aliasDeclarations)};
+ for (const auto &aliasDeclaration : aliasDeclarations)
+ checkForAliasChainCycle(aliasDeclaration.propertyDeclarationId);
+}
+
+void ProjectStorage::linkAliases(const AliasPropertyDeclarations &insertedAliasPropertyDeclarations,
+ const AliasPropertyDeclarations &updatedAliasPropertyDeclarations)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"link aliases"_t, projectStorageCategory()};
+
+ linkAliasPropertyDeclarationAliasIds(insertedAliasPropertyDeclarations);
+ linkAliasPropertyDeclarationAliasIds(updatedAliasPropertyDeclarations);
+
+ checkAliasPropertyDeclarationCycles(insertedAliasPropertyDeclarations);
+ checkAliasPropertyDeclarationCycles(updatedAliasPropertyDeclarations);
+
+ updateAliasPropertyDeclarationValues(insertedAliasPropertyDeclarations);
+ updateAliasPropertyDeclarationValues(updatedAliasPropertyDeclarations);
+}
+
+void ProjectStorage::synchronizeExportedTypes(const TypeIds &updatedTypeIds,
+ Storage::Synchronization::ExportedTypes &exportedTypes,
+ AliasPropertyDeclarations &relinkableAliasPropertyDeclarations,
+ PropertyDeclarations &relinkablePropertyDeclarations,
+ Prototypes &relinkablePrototypes,
+ Prototypes &relinkableExtensions)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"synchronize exported types"_t, projectStorageCategory()};
+
+ std::sort(exportedTypes.begin(), exportedTypes.end(), [](auto &&first, auto &&second) {
+ if (first.moduleId < second.moduleId)
+ return true;
+ else if (first.moduleId > second.moduleId)
+ return false;
+
+ auto nameCompare = Sqlite::compare(first.name, second.name);
+
+ if (nameCompare < 0)
+ return true;
+ else if (nameCompare > 0)
+ return false;
+
+ return first.version < second.version;
+ });
+
+ auto range = s->selectExportedTypesForSourceIdsStatement
+ .range<Storage::Synchronization::ExportedTypeView>(toIntegers(updatedTypeIds));
+
+ auto compareKey = [](const Storage::Synchronization::ExportedTypeView &view,
+ const Storage::Synchronization::ExportedType &type) -> long long {
+ auto moduleIdDifference = view.moduleId - type.moduleId;
+ if (moduleIdDifference != 0)
+ return moduleIdDifference;
+
+ auto nameDifference = Sqlite::compare(view.name, type.name);
+ if (nameDifference != 0)
+ return nameDifference;
+
+ auto versionDifference = view.version.major.value - type.version.major.value;
+ if (versionDifference != 0)
+ return versionDifference;
+
+ return view.version.minor.value - type.version.minor.value;
+ };
+
+ auto insert = [&](const Storage::Synchronization::ExportedType &type) {
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"insert exported type"_t,
+ projectStorageCategory(),
+ keyValue("exported type", type),
+ keyValue("type id", type.typeId),
+ keyValue("module id", type.moduleId)};
+ if (!type.moduleId)
+ throw QmlDesigner::ModuleDoesNotExists{};
+
+ try {
+ if (type.version) {
+ s->insertExportedTypeNamesWithVersionStatement.write(type.moduleId,
+ type.name,
+ type.version.major.value,
+ type.version.minor.value,
+ type.typeId);
+
+ } else if (type.version.major) {
+ s->insertExportedTypeNamesWithMajorVersionStatement.write(type.moduleId,
+ type.name,
+ type.version.major.value,
+ type.typeId);
+ } else {
+ s->insertExportedTypeNamesWithoutVersionStatement.write(type.moduleId,
+ type.name,
+ type.typeId);
+ }
+ } catch (const Sqlite::ConstraintPreventsModification &) {
+ throw QmlDesigner::ExportedTypeCannotBeInserted{type.name};
+ }
+
+ handlePrototypesWithExportedTypeNameAndTypeId(type.name, unresolvedTypeId, relinkablePrototypes);
+ handleExtensionsWithExportedTypeNameAndTypeId(type.name, unresolvedTypeId, relinkableExtensions);
+ };
+
+ auto update = [&](const Storage::Synchronization::ExportedTypeView &view,
+ const Storage::Synchronization::ExportedType &type) {
+ if (view.typeId != type.typeId) {
+ NanotraceHR::Tracer tracer{"update exported type"_t,
+ projectStorageCategory(),
+ keyValue("exported type", type),
+ keyValue("exported type view", view),
+ keyValue("type id", type.typeId),
+ keyValue("module id", type.typeId)};
+
+ handlePropertyDeclarationWithPropertyType(view.typeId, relinkablePropertyDeclarations);
+ handleAliasPropertyDeclarationsWithPropertyType(view.typeId,
+ relinkableAliasPropertyDeclarations);
+ handlePrototypes(view.typeId, relinkablePrototypes);
+ handleExtensions(view.typeId, relinkableExtensions);
+ s->updateExportedTypeNameTypeIdStatement.write(view.exportedTypeNameId, type.typeId);
+ return Sqlite::UpdateChange::Update;
+ }
+ return Sqlite::UpdateChange::No;
+ };
+
+ auto remove = [&](const Storage::Synchronization::ExportedTypeView &view) {
+ NanotraceHR::Tracer tracer{"remove exported type"_t,
+ projectStorageCategory(),
+ keyValue("exported type", view),
+ keyValue("type id", view.typeId),
+ keyValue("module id", view.moduleId)};
+
+ handlePropertyDeclarationWithPropertyType(view.typeId, relinkablePropertyDeclarations);
+ handleAliasPropertyDeclarationsWithPropertyType(view.typeId,
+ relinkableAliasPropertyDeclarations);
+ handlePrototypes(view.typeId, relinkablePrototypes);
+ handleExtensions(view.typeId, relinkableExtensions);
+
+ s->deleteExportedTypeNameStatement.write(view.exportedTypeNameId);
+ };
+
+ Sqlite::insertUpdateDelete(range, exportedTypes, compareKey, insert, update, remove);
+}
+
+void ProjectStorage::synchronizePropertyDeclarationsInsertAlias(
+ AliasPropertyDeclarations &insertedAliasPropertyDeclarations,
+ const Storage::Synchronization::PropertyDeclaration &value,
+ SourceId sourceId,
+ TypeId typeId)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"insert property declaration to alias"_t,
+ projectStorageCategory(),
+ keyValue("property declaration", value)};
+
+ auto callback = [&](PropertyDeclarationId propertyDeclarationId) {
+ insertedAliasPropertyDeclarations.emplace_back(typeId,
+ propertyDeclarationId,
+ fetchImportedTypeNameId(value.typeName,
+ sourceId),
+ value.aliasPropertyName,
+ value.aliasPropertyNameTail);
+ return Sqlite::CallbackControl::Abort;
+ };
+
+ s->insertAliasPropertyDeclarationStatement.readCallback(callback, typeId, value.name);
+}
+
+QVarLengthArray<PropertyDeclarationId, 128> ProjectStorage::fetchPropertyDeclarationIds(
+ TypeId baseTypeId) const
+{
+ QVarLengthArray<PropertyDeclarationId, 128> propertyDeclarationIds;
+
+ s->selectLocalPropertyDeclarationIdsForTypeStatement.readTo(propertyDeclarationIds, baseTypeId);
+
+ auto range = s->selectPrototypeAndExtensionIdsStatement.range<TypeId>(baseTypeId);
+
+ for (TypeId prototype : range) {
+ s->selectLocalPropertyDeclarationIdsForTypeStatement.readTo(propertyDeclarationIds, prototype);
+ }
+
+ return propertyDeclarationIds;
+}
+
+PropertyDeclarationId ProjectStorage::fetchNextPropertyDeclarationId(
+ TypeId baseTypeId, Utils::SmallStringView propertyName) const
+{
+ auto range = s->selectPrototypeAndExtensionIdsStatement.range<TypeId>(baseTypeId);
+
+ for (TypeId prototype : range) {
+ auto propertyDeclarationId = s->selectPropertyDeclarationIdByTypeIdAndNameStatement
+ .value<PropertyDeclarationId>(prototype, propertyName);
+
+ if (propertyDeclarationId)
+ return propertyDeclarationId;
+ }
+
+ return PropertyDeclarationId{};
+}
+
+PropertyDeclarationId ProjectStorage::fetchPropertyDeclarationId(TypeId typeId,
+ Utils::SmallStringView propertyName) const
+{
+ auto propertyDeclarationId = s->selectPropertyDeclarationIdByTypeIdAndNameStatement
+ .value<PropertyDeclarationId>(typeId, propertyName);
+
+ if (propertyDeclarationId)
+ return propertyDeclarationId;
+
+ return fetchNextPropertyDeclarationId(typeId, propertyName);
+}
+
+PropertyDeclarationId ProjectStorage::fetchNextDefaultPropertyDeclarationId(TypeId baseTypeId) const
+{
+ auto range = s->selectPrototypeAndExtensionIdsStatement.range<TypeId>(baseTypeId);
+
+ for (TypeId prototype : range) {
+ auto propertyDeclarationId = s->selectDefaultPropertyDeclarationIdStatement
+ .value<PropertyDeclarationId>(prototype);
+
+ if (propertyDeclarationId)
+ return propertyDeclarationId;
+ }
+
+ return PropertyDeclarationId{};
+}
+
+PropertyDeclarationId ProjectStorage::fetchDefaultPropertyDeclarationId(TypeId typeId) const
+{
+ auto propertyDeclarationId = s->selectDefaultPropertyDeclarationIdStatement
+ .value<PropertyDeclarationId>(typeId);
+
+ if (propertyDeclarationId)
+ return propertyDeclarationId;
+
+ return fetchNextDefaultPropertyDeclarationId(typeId);
+}
+
+void ProjectStorage::synchronizePropertyDeclarationsInsertProperty(
+ const Storage::Synchronization::PropertyDeclaration &value, SourceId sourceId, TypeId typeId)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"insert property declaration"_t,
+ projectStorageCategory(),
+ keyValue("property declaration", value)};
+
+ auto propertyImportedTypeNameId = fetchImportedTypeNameId(value.typeName, sourceId);
+ auto propertyTypeId = fetchTypeId(propertyImportedTypeNameId);
+
+ if (!propertyTypeId)
+ throw TypeNameDoesNotExists{fetchImportedTypeName(propertyImportedTypeNameId), sourceId};
+
+ auto propertyDeclarationId = s->insertPropertyDeclarationStatement.value<PropertyDeclarationId>(
+ typeId, value.name, propertyTypeId, value.traits, propertyImportedTypeNameId);
+
+ auto nextPropertyDeclarationId = fetchNextPropertyDeclarationId(typeId, value.name);
+ if (nextPropertyDeclarationId) {
+ s->updateAliasIdPropertyDeclarationStatement.write(nextPropertyDeclarationId,
+ propertyDeclarationId);
+ s->updatePropertyAliasDeclarationRecursivelyWithTypeAndTraitsStatement
+ .write(propertyDeclarationId, propertyTypeId, value.traits);
+ }
+}
+
+void ProjectStorage::synchronizePropertyDeclarationsUpdateAlias(
+ AliasPropertyDeclarations &updatedAliasPropertyDeclarations,
+ const Storage::Synchronization::PropertyDeclarationView &view,
+ const Storage::Synchronization::PropertyDeclaration &value,
+ SourceId sourceId)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"update property declaration to alias"_t,
+ projectStorageCategory(),
+ keyValue("property declaration", value),
+ keyValue("property declaration view", view)};
+
+ updatedAliasPropertyDeclarations.emplace_back(view.typeId,
+ view.id,
+ fetchImportedTypeNameId(value.typeName, sourceId),
+ value.aliasPropertyName,
+ value.aliasPropertyNameTail,
+ view.aliasId);
+}
+
+Sqlite::UpdateChange ProjectStorage::synchronizePropertyDeclarationsUpdateProperty(
+ const Storage::Synchronization::PropertyDeclarationView &view,
+ const Storage::Synchronization::PropertyDeclaration &value,
+ SourceId sourceId,
+ PropertyDeclarationIds &propertyDeclarationIds)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"update property declaration"_t,
+ projectStorageCategory(),
+ keyValue("property declaration", value),
+ keyValue("property declaration view", view)};
+
+ auto propertyImportedTypeNameId = fetchImportedTypeNameId(value.typeName, sourceId);
+
+ auto propertyTypeId = fetchTypeId(propertyImportedTypeNameId);
+
+ if (!propertyTypeId)
+ throw TypeNameDoesNotExists{fetchImportedTypeName(propertyImportedTypeNameId), sourceId};
+
+ if (view.traits == value.traits && propertyTypeId == view.typeId
+ && propertyImportedTypeNameId == view.typeNameId)
+ return Sqlite::UpdateChange::No;
+
+ s->updatePropertyDeclarationStatement.write(view.id,
+ propertyTypeId,
+ value.traits,
+ propertyImportedTypeNameId);
+ s->updatePropertyAliasDeclarationRecursivelyWithTypeAndTraitsStatement.write(view.id,
+ propertyTypeId,
+ value.traits);
+ propertyDeclarationIds.push_back(view.id);
+
+ tracer.end(keyValue("updated", "yes"));
+
+ return Sqlite::UpdateChange::Update;
+}
+
+void ProjectStorage::synchronizePropertyDeclarations(
+ TypeId typeId,
+ Storage::Synchronization::PropertyDeclarations &propertyDeclarations,
+ SourceId sourceId,
+ AliasPropertyDeclarations &insertedAliasPropertyDeclarations,
+ AliasPropertyDeclarations &updatedAliasPropertyDeclarations,
+ PropertyDeclarationIds &propertyDeclarationIds)
+{
+ NanotraceHR::Tracer tracer{"synchronize property declaration"_t, projectStorageCategory()};
+
+ std::sort(propertyDeclarations.begin(), propertyDeclarations.end(), [](auto &&first, auto &&second) {
+ return Sqlite::compare(first.name, second.name) < 0;
+ });
+
+ auto range = s->selectPropertyDeclarationsForTypeIdStatement
+ .range<Storage::Synchronization::PropertyDeclarationView>(typeId);
+
+ auto compareKey = [](const Storage::Synchronization::PropertyDeclarationView &view,
+ const Storage::Synchronization::PropertyDeclaration &value) {
+ return Sqlite::compare(view.name, value.name);
+ };
+
+ auto insert = [&](const Storage::Synchronization::PropertyDeclaration &value) {
+ if (value.kind == Storage::Synchronization::PropertyKind::Alias) {
+ synchronizePropertyDeclarationsInsertAlias(insertedAliasPropertyDeclarations,
+ value,
+ sourceId,
+ typeId);
+ } else {
+ synchronizePropertyDeclarationsInsertProperty(value, sourceId, typeId);
+ }
+ };
+
+ auto update = [&](const Storage::Synchronization::PropertyDeclarationView &view,
+ const Storage::Synchronization::PropertyDeclaration &value) {
+ if (value.kind == Storage::Synchronization::PropertyKind::Alias) {
+ synchronizePropertyDeclarationsUpdateAlias(updatedAliasPropertyDeclarations,
+ view,
+ value,
+ sourceId);
+ propertyDeclarationIds.push_back(view.id);
+ } else {
+ return synchronizePropertyDeclarationsUpdateProperty(view,
+ value,
+ sourceId,
+ propertyDeclarationIds);
+ }
+
+ return Sqlite::UpdateChange::No;
+ };
+
+ auto remove = [&](const Storage::Synchronization::PropertyDeclarationView &view) {
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"remove property declaration"_t,
+ projectStorageCategory(),
+ keyValue("property declaratio viewn", view)};
+
+ auto nextPropertyDeclarationId = fetchNextPropertyDeclarationId(typeId, view.name);
+
+ if (nextPropertyDeclarationId) {
+ s->updateAliasPropertyDeclarationByAliasPropertyDeclarationIdStatement
+ .write(nextPropertyDeclarationId, view.id);
+ }
+
+ s->updateDefaultPropertyIdToNullStatement.write(view.id);
+ s->deletePropertyDeclarationStatement.write(view.id);
+ propertyDeclarationIds.push_back(view.id);
+ };
+
+ Sqlite::insertUpdateDelete(range, propertyDeclarations, compareKey, insert, update, remove);
+}
+
+void ProjectStorage::resetRemovedAliasPropertyDeclarationsToNull(
+ Storage::Synchronization::Type &type, PropertyDeclarationIds &propertyDeclarationIds)
+{
+ NanotraceHR::Tracer tracer{"reset removed alias property declaration to null"_t,
+ projectStorageCategory()};
+
+ if (type.changeLevel == Storage::Synchronization::ChangeLevel::Minimal)
+ return;
+
+ Storage::Synchronization::PropertyDeclarations &aliasDeclarations = type.propertyDeclarations;
+
+ std::sort(aliasDeclarations.begin(), aliasDeclarations.end(), [](auto &&first, auto &&second) {
+ return Sqlite::compare(first.name, second.name) < 0;
+ });
+
+ auto range = s->selectPropertyDeclarationsWithAliasForTypeIdStatement
+ .range<AliasPropertyDeclarationView>(type.typeId);
+
+ auto compareKey = [](const AliasPropertyDeclarationView &view,
+ const Storage::Synchronization::PropertyDeclaration &value) {
+ return Sqlite::compare(view.name, value.name);
+ };
+
+ auto insert = [&](const Storage::Synchronization::PropertyDeclaration &) {};
+
+ auto update = [&](const AliasPropertyDeclarationView &,
+ const Storage::Synchronization::PropertyDeclaration &) {
+ return Sqlite::UpdateChange::No;
+ };
+
+ auto remove = [&](const AliasPropertyDeclarationView &view) {
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"reset removed alias property declaration to null"_t,
+ projectStorageCategory(),
+ keyValue("alias property declaration view", view)};
+
+ s->updatePropertyDeclarationAliasIdToNullStatement.write(view.id);
+ propertyDeclarationIds.push_back(view.id);
+ };
+
+ Sqlite::insertUpdateDelete(range, aliasDeclarations, compareKey, insert, update, remove);
+}
+
+void ProjectStorage::resetRemovedAliasPropertyDeclarationsToNull(
+ Storage::Synchronization::Types &types,
+ AliasPropertyDeclarations &relinkableAliasPropertyDeclarations)
+{
+ NanotraceHR::Tracer tracer{"reset removed alias properties to null"_t, projectStorageCategory()};
+
+ PropertyDeclarationIds propertyDeclarationIds;
+ propertyDeclarationIds.reserve(types.size());
+
+ for (auto &&type : types)
+ resetRemovedAliasPropertyDeclarationsToNull(type, propertyDeclarationIds);
+
+ removeRelinkableEntries(relinkableAliasPropertyDeclarations,
+ propertyDeclarationIds,
+ PropertyCompare<AliasPropertyDeclaration>{});
+}
+
+void ProjectStorage::handlePrototypesWithSourceIdAndPrototypeId(SourceId sourceId,
+ TypeId prototypeId,
+ Prototypes &relinkablePrototypes)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"handle prototypes with source id and prototype id"_t,
+ projectStorageCategory(),
+ keyValue("source id", sourceId),
+ keyValue("type id", prototypeId)};
+
+ auto callback = [&](TypeId typeId, ImportedTypeNameId prototypeNameId) {
+ if (prototypeNameId)
+ relinkablePrototypes.emplace_back(typeId, prototypeNameId);
+ };
+
+ s->selectTypeIdAndPrototypeNameIdForPrototypeIdAndSourceIdStatement.readCallback(callback,
+ prototypeId,
+ sourceId);
+}
+
+void ProjectStorage::handlePrototypesAndExtensionsWithSourceId(SourceId sourceId,
+ TypeId prototypeId,
+ TypeId extensionId,
+ Prototypes &relinkablePrototypes,
+ Prototypes &relinkableExtensions)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"handle prototypes with source id"_t,
+ projectStorageCategory(),
+ keyValue("source id", sourceId),
+ keyValue("prototype id", prototypeId),
+ keyValue("extension id", extensionId)};
+
+ auto callback =
+ [&](TypeId typeId, ImportedTypeNameId prototypeNameId, ImportedTypeNameId extensionNameId) {
+ if (prototypeNameId)
+ relinkablePrototypes.emplace_back(typeId, prototypeNameId);
+ if (extensionNameId)
+ relinkableExtensions.emplace_back(typeId, extensionNameId);
+ };
+
+ s->updatePrototypeIdAndExtensionIdToTypeIdForSourceIdStatement.readCallback(callback,
+ sourceId,
+ prototypeId,
+ extensionId);
+}
+
+void ProjectStorage::handleExtensionsWithSourceIdAndExtensionId(SourceId sourceId,
+ TypeId extensionId,
+ Prototypes &relinkableExtensions)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"handle prototypes with source id and prototype id"_t,
+ projectStorageCategory(),
+ keyValue("source id", sourceId),
+ keyValue("type id", extensionId)};
+
+ auto callback = [&](TypeId typeId, ImportedTypeNameId extensionNameId) {
+ if (extensionNameId)
+ relinkableExtensions.emplace_back(typeId, extensionNameId);
+ };
+
+ s->selectTypeIdAndExtensionNameIdForExtensionIdAndSourceIdStatement.readCallback(callback,
+ extensionId,
+ sourceId);
+}
+
+ImportId ProjectStorage::insertDocumentImport(const Storage::Import &import,
+ Storage::Synchronization::ImportKind importKind,
+ ModuleId sourceModuleId,
+ ImportId parentImportId,
+ Relink relink,
+ Prototypes &relinkablePrototypes,
+ Prototypes &relinkableExtensions)
+{
+ if (relink == Relink::Yes) {
+ handlePrototypesWithSourceIdAndPrototypeId(import.sourceId,
+ unresolvedTypeId,
+ relinkablePrototypes);
+ handleExtensionsWithSourceIdAndExtensionId(import.sourceId,
+ unresolvedTypeId,
+ relinkableExtensions);
+ }
+
+ if (import.version.minor) {
+ return s->insertDocumentImportWithVersionStatement.value<ImportId>(import.sourceId,
+ import.moduleId,
+ sourceModuleId,
+ importKind,
+ import.version.major.value,
+ import.version.minor.value,
+ parentImportId);
+ } else if (import.version.major) {
+ return s->insertDocumentImportWithMajorVersionStatement.value<ImportId>(import.sourceId,
+ import.moduleId,
+ sourceModuleId,
+ importKind,
+ import.version.major.value,
+ parentImportId);
+ } else {
+ return s->insertDocumentImportWithoutVersionStatement.value<ImportId>(import.sourceId,
+ import.moduleId,
+ sourceModuleId,
+ importKind,
+ parentImportId);
+ }
+}
+
+void ProjectStorage::synchronizeDocumentImports(Storage::Imports &imports,
+ const SourceIds &updatedSourceIds,
+ Storage::Synchronization::ImportKind importKind,
+ Relink relink,
+ Prototypes &relinkablePrototypes,
+ Prototypes &relinkableExtensions)
+{
+ std::sort(imports.begin(), imports.end(), [](auto &&first, auto &&second) {
+ return std::tie(first.sourceId, first.moduleId, first.version)
+ < std::tie(second.sourceId, second.moduleId, second.version);
+ });
+
+ auto range = s->selectDocumentImportForSourceIdStatement
+ .range<Storage::Synchronization::ImportView>(toIntegers(updatedSourceIds),
+ importKind);
+
+ auto compareKey = [](const Storage::Synchronization::ImportView &view,
+ const Storage::Import &import) -> long long {
+ auto sourceIdDifference = view.sourceId - import.sourceId;
+ if (sourceIdDifference != 0)
+ return sourceIdDifference;
+
+ auto moduleIdDifference = view.moduleId - import.moduleId;
+ if (moduleIdDifference != 0)
+ return moduleIdDifference;
+
+ auto versionDifference = view.version.major.value - import.version.major.value;
+ if (versionDifference != 0)
+ return versionDifference;
+
+ return view.version.minor.value - import.version.minor.value;
+ };
+
+ auto insert = [&](const Storage::Import &import) {
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"insert import"_t,
+ projectStorageCategory(),
+ keyValue("import", import),
+ keyValue("import kind", importKind),
+ keyValue("source id", import.sourceId),
+ keyValue("module id", import.moduleId)};
+
+ auto importId = insertDocumentImport(import,
+ importKind,
+ import.moduleId,
+ ImportId{},
+ relink,
+ relinkablePrototypes,
+ relinkableExtensions);
+ auto callback = [&](ModuleId exportedModuleId, int majorVersion, int minorVersion) {
+ Storage::Import additionImport{exportedModuleId,
+ Storage::Version{majorVersion, minorVersion},
+ import.sourceId};
+
+ auto exportedImportKind = importKind == Storage::Synchronization::ImportKind::Import
+ ? Storage::Synchronization::ImportKind::ModuleExportedImport
+ : Storage::Synchronization::ImportKind::ModuleExportedModuleDependency;
+
+ NanotraceHR::Tracer tracer{"insert indirect import"_t,
+ projectStorageCategory(),
+ keyValue("import", import),
+ keyValue("import kind", exportedImportKind),
+ keyValue("source id", import.sourceId),
+ keyValue("module id", import.moduleId)};
+
+ auto indirectImportId = insertDocumentImport(additionImport,
+ exportedImportKind,
+ import.moduleId,
+ importId,
+ relink,
+ relinkablePrototypes,
+ relinkableExtensions);
+
+ tracer.end(keyValue("import id", indirectImportId));
+ };
+
+ s->selectModuleExportedImportsForModuleIdStatement.readCallback(callback,
+ import.moduleId,
+ import.version.major.value,
+ import.version.minor.value);
+ tracer.end(keyValue("import id", importId));
+ };
+
+ auto update = [](const Storage::Synchronization::ImportView &, const Storage::Import &) {
+ return Sqlite::UpdateChange::No;
+ };
+
+ auto remove = [&](const Storage::Synchronization::ImportView &view) {
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"remove import"_t,
+ projectStorageCategory(),
+ keyValue("import", view),
+ keyValue("import id", view.importId),
+ keyValue("source id", view.sourceId),
+ keyValue("module id", view.moduleId)};
+
+ s->deleteDocumentImportStatement.write(view.importId);
+ s->deleteDocumentImportsWithParentImportIdStatement.write(view.sourceId, view.importId);
+ if (relink == Relink::Yes) {
+ handlePrototypesAndExtensionsWithSourceId(view.sourceId,
+ unresolvedTypeId,
+ unresolvedTypeId,
+ relinkablePrototypes,
+ relinkableExtensions);
+ }
+ };
+
+ Sqlite::insertUpdateDelete(range, imports, compareKey, insert, update, remove);
+}
+
+Utils::PathString ProjectStorage::createJson(const Storage::Synchronization::ParameterDeclarations &parameters)
+{
+ NanotraceHR::Tracer tracer{"create json from parameter declarations"_t, projectStorageCategory()};
+
+ Utils::PathString json;
+ json.append("[");
+
+ Utils::SmallStringView comma{""};
+
+ for (const auto &parameter : parameters) {
+ json.append(comma);
+ comma = ",";
+ json.append(R"({"n":")");
+ json.append(parameter.name);
+ json.append(R"(","tn":")");
+ json.append(parameter.typeName);
+ if (parameter.traits == Storage::PropertyDeclarationTraits::None) {
+ json.append("\"}");
+ } else {
+ json.append(R"(","tr":)");
+ json.append(Utils::SmallString::number(Utils::to_underlying(parameter.traits)));
+ json.append("}");
+ }
+ }
+
+ json.append("]");
+
+ return json;
+}
+
+TypeId ProjectStorage::fetchTypeIdByModuleIdAndExportedName(ModuleId moduleId,
+ Utils::SmallStringView name) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch type id by module id and exported name"_t,
+ projectStorageCategory(),
+ keyValue("module id", moduleId),
+ keyValue("exported name", name)};
+
+ return s->selectTypeIdByModuleIdAndExportedNameStatement.value<TypeId>(moduleId, name);
+}
+
+void ProjectStorage::addTypeIdToPropertyEditorQmlPaths(
+ Storage::Synchronization::PropertyEditorQmlPaths &paths)
+{
+ NanotraceHR::Tracer tracer{"add type id to property editor qml paths"_t, projectStorageCategory()};
+
+ for (auto &path : paths)
+ path.typeId = fetchTypeIdByModuleIdAndExportedName(path.moduleId, path.typeName);
+}
+
+void ProjectStorage::synchronizePropertyEditorPaths(Storage::Synchronization::PropertyEditorQmlPaths &paths,
+ SourceIds updatedPropertyEditorQmlPathsSourceIds)
+{
+ using Storage::Synchronization::PropertyEditorQmlPath;
+ std::sort(paths.begin(), paths.end(), [](auto &&first, auto &&second) {
+ return first.typeId < second.typeId;
+ });
+
+ auto range = s->selectPropertyEditorPathsForForSourceIdsStatement.range<PropertyEditorQmlPathView>(
+ toIntegers(updatedPropertyEditorQmlPathsSourceIds));
+
+ auto compareKey = [](const PropertyEditorQmlPathView &view,
+ const PropertyEditorQmlPath &value) -> long long {
+ return view.typeId - value.typeId;
+ };
+
+ auto insert = [&](const PropertyEditorQmlPath &path) {
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"insert property editor paths"_t,
+ projectStorageCategory(),
+ keyValue("property editor qml path", path)};
+
+ if (path.typeId)
+ s->insertPropertyEditorPathStatement.write(path.typeId, path.pathId, path.directoryId);
+ };
+
+ auto update = [&](const PropertyEditorQmlPathView &view, const PropertyEditorQmlPath &value) {
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"update property editor paths"_t,
+ projectStorageCategory(),
+ keyValue("property editor qml path", value),
+ keyValue("property editor qml path view", view)};
+
+ if (value.pathId != view.pathId || value.directoryId != view.directoryId) {
+ s->updatePropertyEditorPathsStatement.write(value.typeId, value.pathId, value.directoryId);
+
+ tracer.end(keyValue("updated", "yes"));
+
+ return Sqlite::UpdateChange::Update;
+ }
+ return Sqlite::UpdateChange::No;
+ };
+
+ auto remove = [&](const PropertyEditorQmlPathView &view) {
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"remove property editor paths"_t,
+ projectStorageCategory(),
+ keyValue("property editor qml path view", view)};
+
+ s->deletePropertyEditorPathStatement.write(view.typeId);
+ };
+
+ Sqlite::insertUpdateDelete(range, paths, compareKey, insert, update, remove);
+}
+
+void ProjectStorage::synchronizePropertyEditorQmlPaths(
+ Storage::Synchronization::PropertyEditorQmlPaths &paths,
+ SourceIds updatedPropertyEditorQmlPathsSourceIds)
+{
+ NanotraceHR::Tracer tracer{"synchronize property editor qml paths"_t, projectStorageCategory()};
+
+ addTypeIdToPropertyEditorQmlPaths(paths);
+ synchronizePropertyEditorPaths(paths, updatedPropertyEditorQmlPathsSourceIds);
+}
+
+void ProjectStorage::synchronizeFunctionDeclarations(
+ TypeId typeId, Storage::Synchronization::FunctionDeclarations &functionsDeclarations)
+{
+ NanotraceHR::Tracer tracer{"synchronize function declaration"_t, projectStorageCategory()};
+
+ std::sort(functionsDeclarations.begin(),
+ functionsDeclarations.end(),
+ [](auto &&first, auto &&second) {
+ auto compare = Sqlite::compare(first.name, second.name);
+
+ if (compare == 0) {
+ Utils::PathString firstSignature{createJson(first.parameters)};
+ Utils::PathString secondSignature{createJson(second.parameters)};
+
+ return Sqlite::compare(firstSignature, secondSignature) < 0;
+ }
+
+ return compare < 0;
+ });
+
+ auto range = s->selectFunctionDeclarationsForTypeIdStatement
+ .range<Storage::Synchronization::FunctionDeclarationView>(typeId);
+
+ auto compareKey = [](const Storage::Synchronization::FunctionDeclarationView &view,
+ const Storage::Synchronization::FunctionDeclaration &value) {
+ auto nameKey = Sqlite::compare(view.name, value.name);
+ if (nameKey != 0)
+ return nameKey;
+
+ Utils::PathString valueSignature{createJson(value.parameters)};
+
+ return Sqlite::compare(view.signature, valueSignature);
+ };
+
+ auto insert = [&](const Storage::Synchronization::FunctionDeclaration &value) {
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"insert function declaration"_t,
+ projectStorageCategory(),
+ keyValue("function declaration", value)};
+
+ Utils::PathString signature{createJson(value.parameters)};
+
+ s->insertFunctionDeclarationStatement.write(typeId, value.name, value.returnTypeName, signature);
+ };
+
+ auto update = [&](const Storage::Synchronization::FunctionDeclarationView &view,
+ const Storage::Synchronization::FunctionDeclaration &value) {
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"update function declaration"_t,
+ projectStorageCategory(),
+ keyValue("function declaration", value),
+ keyValue("function declaration view", view)};
+
+ Utils::PathString signature{createJson(value.parameters)};
+
+ if (value.returnTypeName == view.returnTypeName && signature == view.signature)
+ return Sqlite::UpdateChange::No;
+
+ s->updateFunctionDeclarationStatement.write(view.id, value.returnTypeName, signature);
+
+ tracer.end(keyValue("updated", "yes"));
+
+ return Sqlite::UpdateChange::Update;
+ };
+
+ auto remove = [&](const Storage::Synchronization::FunctionDeclarationView &view) {
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"remove function declaration"_t,
+ projectStorageCategory(),
+ keyValue("function declaration view", view)};
+
+ s->deleteFunctionDeclarationStatement.write(view.id);
+ };
+
+ Sqlite::insertUpdateDelete(range, functionsDeclarations, compareKey, insert, update, remove);
+}
+
+void ProjectStorage::synchronizeSignalDeclarations(
+ TypeId typeId, Storage::Synchronization::SignalDeclarations &signalDeclarations)
+{
+ NanotraceHR::Tracer tracer{"synchronize signal declaration"_t, projectStorageCategory()};
+
+ std::sort(signalDeclarations.begin(), signalDeclarations.end(), [](auto &&first, auto &&second) {
+ auto compare = Sqlite::compare(first.name, second.name);
+
+ if (compare == 0) {
+ Utils::PathString firstSignature{createJson(first.parameters)};
+ Utils::PathString secondSignature{createJson(second.parameters)};
+
+ return Sqlite::compare(firstSignature, secondSignature) < 0;
+ }
+
+ return compare < 0;
+ });
+
+ auto range = s->selectSignalDeclarationsForTypeIdStatement
+ .range<Storage::Synchronization::SignalDeclarationView>(typeId);
+
+ auto compareKey = [](const Storage::Synchronization::SignalDeclarationView &view,
+ const Storage::Synchronization::SignalDeclaration &value) {
+ auto nameKey = Sqlite::compare(view.name, value.name);
+ if (nameKey != 0)
+ return nameKey;
+
+ Utils::PathString valueSignature{createJson(value.parameters)};
+
+ return Sqlite::compare(view.signature, valueSignature);
+ };
+
+ auto insert = [&](const Storage::Synchronization::SignalDeclaration &value) {
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"insert signal declaration"_t,
+ projectStorageCategory(),
+ keyValue("signal declaration", value)};
+
+ Utils::PathString signature{createJson(value.parameters)};
+
+ s->insertSignalDeclarationStatement.write(typeId, value.name, signature);
+ };
+
+ auto update = [&]([[maybe_unused]] const Storage::Synchronization::SignalDeclarationView &view,
+ [[maybe_unused]] const Storage::Synchronization::SignalDeclaration &value) {
+ return Sqlite::UpdateChange::No;
+ };
+
+ auto remove = [&](const Storage::Synchronization::SignalDeclarationView &view) {
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"remove signal declaration"_t,
+ projectStorageCategory(),
+ keyValue("signal declaration view", view)};
+
+ s->deleteSignalDeclarationStatement.write(view.id);
+ };
+
+ Sqlite::insertUpdateDelete(range, signalDeclarations, compareKey, insert, update, remove);
+}
+
+Utils::PathString ProjectStorage::createJson(
+ const Storage::Synchronization::EnumeratorDeclarations &enumeratorDeclarations)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"create json from enumerator declarations"_t, projectStorageCategory()};
+
+ Utils::PathString json;
+ json.append("{");
+
+ Utils::SmallStringView comma{"\""};
+
+ for (const auto &enumerator : enumeratorDeclarations) {
+ json.append(comma);
+ comma = ",\"";
+ json.append(enumerator.name);
+ if (enumerator.hasValue) {
+ json.append("\":\"");
+ json.append(Utils::SmallString::number(enumerator.value));
+ json.append("\"");
+ } else {
+ json.append("\":null");
+ }
+ }
+
+ json.append("}");
+
+ return json;
+}
+
+void ProjectStorage::synchronizeEnumerationDeclarations(
+ TypeId typeId, Storage::Synchronization::EnumerationDeclarations &enumerationDeclarations)
+{
+ NanotraceHR::Tracer tracer{"synchronize enumeration declaration"_t, projectStorageCategory()};
+
+ std::sort(enumerationDeclarations.begin(),
+ enumerationDeclarations.end(),
+ [](auto &&first, auto &&second) {
+ return Sqlite::compare(first.name, second.name) < 0;
+ });
+
+ auto range = s->selectEnumerationDeclarationsForTypeIdStatement
+ .range<Storage::Synchronization::EnumerationDeclarationView>(typeId);
+
+ auto compareKey = [](const Storage::Synchronization::EnumerationDeclarationView &view,
+ const Storage::Synchronization::EnumerationDeclaration &value) {
+ return Sqlite::compare(view.name, value.name);
+ };
+
+ auto insert = [&](const Storage::Synchronization::EnumerationDeclaration &value) {
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"insert enumeration declaration"_t,
+ projectStorageCategory(),
+ keyValue("enumeration declaration", value)};
+
+ Utils::PathString signature{createJson(value.enumeratorDeclarations)};
+
+ s->insertEnumerationDeclarationStatement.write(typeId, value.name, signature);
+ };
+
+ auto update = [&](const Storage::Synchronization::EnumerationDeclarationView &view,
+ const Storage::Synchronization::EnumerationDeclaration &value) {
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"update enumeration declaration"_t,
+ projectStorageCategory(),
+ keyValue("enumeration declaration", value),
+ keyValue("enumeration declaration view", view)};
+
+ Utils::PathString enumeratorDeclarations{createJson(value.enumeratorDeclarations)};
+
+ if (enumeratorDeclarations == view.enumeratorDeclarations)
+ return Sqlite::UpdateChange::No;
+
+ s->updateEnumerationDeclarationStatement.write(view.id, enumeratorDeclarations);
+
+ tracer.end(keyValue("updated", "yes"));
+
+ return Sqlite::UpdateChange::Update;
+ };
+
+ auto remove = [&](const Storage::Synchronization::EnumerationDeclarationView &view) {
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"remove enumeration declaration"_t,
+ projectStorageCategory(),
+ keyValue("enumeration declaration view", view)};
+
+ s->deleteEnumerationDeclarationStatement.write(view.id);
+ };
+
+ Sqlite::insertUpdateDelete(range, enumerationDeclarations, compareKey, insert, update, remove);
+}
+
+void ProjectStorage::extractExportedTypes(TypeId typeId,
+ const Storage::Synchronization::Type &type,
+ Storage::Synchronization::ExportedTypes &exportedTypes)
+{
+ for (const auto &exportedType : type.exportedTypes)
+ exportedTypes.emplace_back(exportedType.name, exportedType.version, typeId, exportedType.moduleId);
+}
+
+TypeId ProjectStorage::declareType(Storage::Synchronization::Type &type)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"declare type"_t,
+ projectStorageCategory(),
+ keyValue("source id", type.sourceId),
+ keyValue("type name", type.typeName)};
+
+ if (type.typeName.isEmpty()) {
+ type.typeId = s->selectTypeIdBySourceIdStatement.value<TypeId>(type.sourceId);
+
+ tracer.end(keyValue("type id", type.typeId));
+
+ return type.typeId;
+ }
+
+ type.typeId = s->insertTypeStatement.value<TypeId>(type.sourceId, type.typeName);
+
+ if (!type.typeId)
+ type.typeId = s->selectTypeIdBySourceIdAndNameStatement.value<TypeId>(type.sourceId,
+ type.typeName);
+
+ tracer.end(keyValue("type id", type.typeId));
+
+ return type.typeId;
+}
+
+void ProjectStorage::syncDeclarations(Storage::Synchronization::Type &type,
+ AliasPropertyDeclarations &insertedAliasPropertyDeclarations,
+ AliasPropertyDeclarations &updatedAliasPropertyDeclarations,
+ PropertyDeclarationIds &propertyDeclarationIds)
+{
+ NanotraceHR::Tracer tracer{"synchronize declaration per type"_t, projectStorageCategory()};
+
+ if (type.changeLevel == Storage::Synchronization::ChangeLevel::Minimal)
+ return;
+
+ synchronizePropertyDeclarations(type.typeId,
+ type.propertyDeclarations,
+ type.sourceId,
+ insertedAliasPropertyDeclarations,
+ updatedAliasPropertyDeclarations,
+ propertyDeclarationIds);
+ synchronizeFunctionDeclarations(type.typeId, type.functionDeclarations);
+ synchronizeSignalDeclarations(type.typeId, type.signalDeclarations);
+ synchronizeEnumerationDeclarations(type.typeId, type.enumerationDeclarations);
+}
+
+void ProjectStorage::syncDeclarations(Storage::Synchronization::Types &types,
+ AliasPropertyDeclarations &insertedAliasPropertyDeclarations,
+ AliasPropertyDeclarations &updatedAliasPropertyDeclarations,
+ PropertyDeclarations &relinkablePropertyDeclarations)
+{
+ NanotraceHR::Tracer tracer{"synchronize declaration"_t, projectStorageCategory()};
+
+ PropertyDeclarationIds propertyDeclarationIds;
+ propertyDeclarationIds.reserve(types.size() * 10);
+
+ for (auto &&type : types)
+ syncDeclarations(type,
+ insertedAliasPropertyDeclarations,
+ updatedAliasPropertyDeclarations,
+ propertyDeclarationIds);
+
+ removeRelinkableEntries(relinkablePropertyDeclarations,
+ propertyDeclarationIds,
+ PropertyCompare<PropertyDeclaration>{});
+}
+
+void ProjectStorage::syncDefaultProperties(Storage::Synchronization::Types &types)
+{
+ NanotraceHR::Tracer tracer{"synchronize default properties"_t, projectStorageCategory()};
+
+ auto range = s->selectTypesWithDefaultPropertyStatement.range<TypeWithDefaultPropertyView>();
+
+ auto compareKey = [](const TypeWithDefaultPropertyView &view,
+ const Storage::Synchronization::Type &value) {
+ return view.typeId - value.typeId;
+ };
+
+ auto insert = [&](const Storage::Synchronization::Type &) {
+
+ };
+
+ auto update = [&](const TypeWithDefaultPropertyView &view,
+ const Storage::Synchronization::Type &value) {
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"synchronize default properties by update"_t,
+ projectStorageCategory(),
+ keyValue("type id", value.typeId),
+ keyValue("value", value),
+ keyValue("view", view)};
+
+ PropertyDeclarationId valueDefaultPropertyId;
+ if (value.defaultPropertyName.size())
+ valueDefaultPropertyId = fetchPropertyDeclarationByTypeIdAndNameUngarded(value.typeId,
+ value.defaultPropertyName)
+ .propertyDeclarationId;
+
+ if (compareInvalidAreTrue(valueDefaultPropertyId, view.defaultPropertyId))
+ return Sqlite::UpdateChange::No;
+
+ s->updateDefaultPropertyIdStatement.write(value.typeId, valueDefaultPropertyId);
+
+ tracer.end(keyValue("updated", "yes"),
+ keyValue("default property id", valueDefaultPropertyId));
+
+ return Sqlite::UpdateChange::Update;
+ };
+
+ auto remove = [&](const TypeWithDefaultPropertyView &) {};
+
+ Sqlite::insertUpdateDelete(range, types, compareKey, insert, update, remove);
+}
+
+void ProjectStorage::resetDefaultPropertiesIfChanged(Storage::Synchronization::Types &types)
+{
+ NanotraceHR::Tracer tracer{"reset changed default properties"_t, projectStorageCategory()};
+
+ auto range = s->selectTypesWithDefaultPropertyStatement.range<TypeWithDefaultPropertyView>();
+
+ auto compareKey = [](const TypeWithDefaultPropertyView &view,
+ const Storage::Synchronization::Type &value) {
+ return view.typeId - value.typeId;
+ };
+
+ auto insert = [&](const Storage::Synchronization::Type &) {
+
+ };
+
+ auto update = [&](const TypeWithDefaultPropertyView &view,
+ const Storage::Synchronization::Type &value) {
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"reset changed default properties by update"_t,
+ projectStorageCategory(),
+ keyValue("type id", value.typeId),
+ keyValue("value", value),
+ keyValue("view", view)};
+
+ PropertyDeclarationId valueDefaultPropertyId;
+ if (value.defaultPropertyName.size()) {
+ auto optionalValueDefaultPropertyId = fetchOptionalPropertyDeclarationByTypeIdAndNameUngarded(
+ value.typeId, value.defaultPropertyName);
+ if (optionalValueDefaultPropertyId)
+ valueDefaultPropertyId = optionalValueDefaultPropertyId->propertyDeclarationId;
+ }
+
+ if (compareInvalidAreTrue(valueDefaultPropertyId, view.defaultPropertyId))
+ return Sqlite::UpdateChange::No;
+
+ s->updateDefaultPropertyIdStatement.write(value.typeId, Sqlite::NullValue{});
+
+ tracer.end(keyValue("updated", "yes"));
+
+ return Sqlite::UpdateChange::Update;
+ };
+
+ auto remove = [&](const TypeWithDefaultPropertyView &) {};
+
+ Sqlite::insertUpdateDelete(range, types, compareKey, insert, update, remove);
+}
+
+void ProjectStorage::checkForPrototypeChainCycle(TypeId typeId) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"check for prototype chain cycle"_t,
+ projectStorageCategory(),
+ keyValue("type id", typeId)};
+
+ auto callback = [=](TypeId currentTypeId) {
+ if (typeId == currentTypeId)
+ throw PrototypeChainCycle{};
+ };
+
+ s->selectPrototypeAndExtensionIdsStatement.readCallback(callback, typeId);
+}
+
+void ProjectStorage::checkForAliasChainCycle(PropertyDeclarationId propertyDeclarationId) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"check for alias chain cycle"_t,
+ projectStorageCategory(),
+ keyValue("property declaration id", propertyDeclarationId)};
+ auto callback = [=](PropertyDeclarationId currentPropertyDeclarationId) {
+ if (propertyDeclarationId == currentPropertyDeclarationId)
+ throw AliasChainCycle{};
+ };
+
+ s->selectPropertyDeclarationIdsForAliasChainStatement.readCallback(callback,
+ propertyDeclarationId);
+}
+
+std::pair<TypeId, ImportedTypeNameId> ProjectStorage::fetchImportedTypeNameIdAndTypeId(
+ const Storage::Synchronization::ImportedTypeName &importedTypeName, SourceId sourceId)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch imported type name id and type id"_t,
+ projectStorageCategory(),
+ keyValue("imported type name", importedTypeName),
+ keyValue("source id", sourceId)};
+
+ TypeId typeId;
+ ImportedTypeNameId typeNameId;
+ auto typeName = std::visit([](auto &&importedTypeName) { return importedTypeName.name; },
+ importedTypeName);
+ if (!typeName.empty()) {
+ typeNameId = fetchImportedTypeNameId(importedTypeName, sourceId);
+
+ typeId = fetchTypeId(typeNameId);
+
+ tracer.end(keyValue("type id", typeId), keyValue("type name id", typeNameId));
+
+ if (!typeId) {
+ errorNotifier->typeNameCannotBeResolved(typeName, sourceId);
+ return {unresolvedTypeId, typeNameId};
+ }
+ }
+
+ return {typeId, typeNameId};
+}
+
+void ProjectStorage::syncPrototypeAndExtension(Storage::Synchronization::Type &type, TypeIds &typeIds)
+{
+ if (type.changeLevel == Storage::Synchronization::ChangeLevel::Minimal)
+ return;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"synchronize prototype and extension"_t,
+ projectStorageCategory(),
+ keyValue("prototype", type.prototype),
+ keyValue("extension", type.extension),
+ keyValue("type id", type.typeId),
+ keyValue("source id", type.sourceId)};
+
+ auto [prototypeId, prototypeTypeNameId] = fetchImportedTypeNameIdAndTypeId(type.prototype,
+ type.sourceId);
+ auto [extensionId, extensionTypeNameId] = fetchImportedTypeNameIdAndTypeId(type.extension,
+ type.sourceId);
+
+ s->updatePrototypeAndExtensionStatement.write(type.typeId,
+ prototypeId,
+ prototypeTypeNameId,
+ extensionId,
+ extensionTypeNameId);
+
+ if (prototypeId || extensionId)
+ checkForPrototypeChainCycle(type.typeId);
+
+ typeIds.push_back(type.typeId);
+
+ tracer.end(keyValue("prototype id", prototypeId),
+ keyValue("prototype type name id", prototypeTypeNameId),
+ keyValue("extension id", extensionId),
+ keyValue("extension type name id", extensionTypeNameId));
+}
+
+void ProjectStorage::syncPrototypesAndExtensions(Storage::Synchronization::Types &types,
+ Prototypes &relinkablePrototypes,
+ Prototypes &relinkableExtensions)
+{
+ NanotraceHR::Tracer tracer{"synchronize prototypes and extensions"_t, projectStorageCategory()};
+
+ TypeIds typeIds;
+ typeIds.reserve(types.size());
+
+ for (auto &type : types)
+ syncPrototypeAndExtension(type, typeIds);
+
+ removeRelinkableEntries(relinkablePrototypes, typeIds, TypeCompare<Prototype>{});
+ removeRelinkableEntries(relinkableExtensions, typeIds, TypeCompare<Prototype>{});
+}
+
+ImportId ProjectStorage::fetchImportId(SourceId sourceId, const Storage::Import &import) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch imported type name id"_t,
+ projectStorageCategory(),
+ keyValue("import", import),
+ keyValue("source id", sourceId)};
+
+ ImportId importId;
+ if (import.version) {
+ importId = s->selectImportIdBySourceIdAndModuleIdAndVersionStatement.value<ImportId>(
+ sourceId, import.moduleId, import.version.major.value, import.version.minor.value);
+ } else if (import.version.major) {
+ importId = s->selectImportIdBySourceIdAndModuleIdAndMajorVersionStatement
+ .value<ImportId>(sourceId, import.moduleId, import.version.major.value);
+ } else {
+ importId = s->selectImportIdBySourceIdAndModuleIdStatement.value<ImportId>(sourceId,
+ import.moduleId);
+ }
+
+ tracer.end(keyValue("import id", importId));
+
+ return importId;
+}
+
+ImportedTypeNameId ProjectStorage::fetchImportedTypeNameId(
+ const Storage::Synchronization::ImportedTypeName &name, SourceId sourceId)
+{
+ struct Inspect
+ {
+ auto operator()(const Storage::Synchronization::ImportedType &importedType)
+ {
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch imported type name id"_t,
+ projectStorageCategory(),
+ keyValue("imported type name", importedType.name),
+ keyValue("source id", sourceId),
+ keyValue("type name kind", "exported"sv)};
+
+ return storage.fetchImportedTypeNameId(Storage::Synchronization::TypeNameKind::Exported,
+ sourceId,
+ importedType.name);
+ }
+
+ auto operator()(const Storage::Synchronization::QualifiedImportedType &importedType)
+ {
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch imported type name id"_t,
+ projectStorageCategory(),
+ keyValue("imported type name", importedType.name),
+ keyValue("import", importedType.import),
+ keyValue("type name kind", "qualified exported"sv)};
+
+ ImportId importId = storage.fetchImportId(sourceId, importedType.import);
+
+ auto importedTypeNameId = storage.fetchImportedTypeNameId(
+ Storage::Synchronization::TypeNameKind::QualifiedExported, importId, importedType.name);
+
+ tracer.end(keyValue("import id", importId), keyValue("source id", sourceId));
+
+ return importedTypeNameId;
+ }
+
+ ProjectStorage &storage;
+ SourceId sourceId;
+ };
+
+ return std::visit(Inspect{*this, sourceId}, name);
+}
+
+TypeId ProjectStorage::fetchTypeId(ImportedTypeNameId typeNameId) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch type id with type name kind"_t,
+ projectStorageCategory(),
+ keyValue("type name id", typeNameId)};
+
+ auto kind = s->selectKindFromImportedTypeNamesStatement.value<Storage::Synchronization::TypeNameKind>(
+ typeNameId);
+
+ auto typeId = fetchTypeId(typeNameId, kind);
+
+ tracer.end(keyValue("type id", typeId), keyValue("type name kind", kind));
+
+ return typeId;
+}
+
+Utils::SmallString ProjectStorage::fetchImportedTypeName(ImportedTypeNameId typeNameId) const
+{
+ return s->selectNameFromImportedTypeNamesStatement.value<Utils::SmallString>(typeNameId);
+}
+
+SourceId ProjectStorage::fetchTypeSourceId(TypeId typeId) const
+{
+ return s->selectSourceIdByTypeIdStatement.value<SourceId>(typeId);
+}
+
+TypeId ProjectStorage::fetchTypeId(ImportedTypeNameId typeNameId,
+ Storage::Synchronization::TypeNameKind kind) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch type id"_t,
+ projectStorageCategory(),
+ keyValue("type name id", typeNameId),
+ keyValue("type name kind", kind)};
+
+ TypeId typeId;
+ if (kind == Storage::Synchronization::TypeNameKind::Exported) {
+ typeId = s->selectTypeIdForImportedTypeNameNamesStatement.value<UnresolvedTypeId>(typeNameId);
+ } else {
+ typeId = s->selectTypeIdForQualifiedImportedTypeNameNamesStatement.value<UnresolvedTypeId>(
+ typeNameId);
+ }
+
+ tracer.end(keyValue("type id", typeId));
+
+ return typeId;
+}
+
+std::optional<ProjectStorage::FetchPropertyDeclarationResult>
+ProjectStorage::fetchOptionalPropertyDeclarationByTypeIdAndNameUngarded(TypeId typeId,
+ Utils::SmallStringView name)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch optional property declaration by type id and name ungarded"_t,
+ projectStorageCategory(),
+ keyValue("type id", typeId),
+ keyValue("property name", name)};
+
+ auto propertyDeclarationId = fetchPropertyDeclarationId(typeId, name);
+ auto propertyDeclaration = s->selectPropertyDeclarationResultByPropertyDeclarationIdStatement
+ .optionalValue<FetchPropertyDeclarationResult>(
+ propertyDeclarationId);
+
+ tracer.end(keyValue("property declaration", propertyDeclaration));
+
+ return propertyDeclaration;
+}
+
+ProjectStorage::FetchPropertyDeclarationResult ProjectStorage::fetchPropertyDeclarationByTypeIdAndNameUngarded(
+ TypeId typeId, Utils::SmallStringView name)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch property declaration by type id and name ungarded"_t,
+ projectStorageCategory(),
+ keyValue("type id", typeId),
+ keyValue("property name", name)};
+
+ auto propertyDeclaration = fetchOptionalPropertyDeclarationByTypeIdAndNameUngarded(typeId, name);
+ tracer.end(keyValue("property declaration", propertyDeclaration));
+
+ if (propertyDeclaration)
+ return *propertyDeclaration;
+
+ throw PropertyNameDoesNotExists{};
+}
+
+PropertyDeclarationId ProjectStorage::fetchPropertyDeclarationIdByTypeIdAndNameUngarded(
+ TypeId typeId, Utils::SmallStringView name)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch property declaration id by type id and name ungarded"_t,
+ projectStorageCategory(),
+ keyValue("type id", typeId),
+ keyValue("property name", name)};
+
+ auto propertyDeclarationId = fetchPropertyDeclarationId(typeId, name);
+
+ tracer.end(keyValue("property declaration id", propertyDeclarationId));
+
+ if (propertyDeclarationId)
+ return propertyDeclarationId;
+
+ throw PropertyNameDoesNotExists{};
+}
+
+SourceContextId ProjectStorage::readSourceContextId(Utils::SmallStringView sourceContextPath)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"read source context id"_t,
+ projectStorageCategory(),
+ keyValue("source context path", sourceContextPath)};
+
+ auto sourceContextId = s->selectSourceContextIdFromSourceContextsBySourceContextPathStatement
+ .value<SourceContextId>(sourceContextPath);
+
+ tracer.end(keyValue("source context id", sourceContextId));
+
+ return sourceContextId;
+}
+
+SourceContextId ProjectStorage::writeSourceContextId(Utils::SmallStringView sourceContextPath)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"write source context id"_t,
+ projectStorageCategory(),
+ keyValue("source context path", sourceContextPath)};
+
+ s->insertIntoSourceContextsStatement.write(sourceContextPath);
+
+ auto sourceContextId = SourceContextId::create(static_cast<int>(database.lastInsertedRowId()));
+
+ tracer.end(keyValue("source context id", sourceContextId));
+
+ return sourceContextId;
+}
+
+SourceId ProjectStorage::writeSourceId(SourceContextId sourceContextId,
+ Utils::SmallStringView sourceName)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"write source id"_t,
+ projectStorageCategory(),
+ keyValue("source context id", sourceContextId),
+ keyValue("source name", sourceName)};
+
+ s->insertIntoSourcesStatement.write(sourceContextId, sourceName);
+
+ auto sourceId = SourceId::create(static_cast<int>(database.lastInsertedRowId()));
+
+ tracer.end(keyValue("source id", sourceId));
+
+ return sourceId;
+}
+
+SourceId ProjectStorage::readSourceId(SourceContextId sourceContextId,
+ Utils::SmallStringView sourceName)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"read source id"_t,
+ projectStorageCategory(),
+ keyValue("source context id", sourceContextId),
+ keyValue("source name", sourceName)};
+
+ auto sourceId = s->selectSourceIdFromSourcesBySourceContextIdAndSourceNameStatement
+ .value<SourceId>(sourceContextId, sourceName);
+
+ tracer.end(keyValue("source id", sourceId));
+
+ return sourceId;
+}
+
+Storage::Synchronization::ExportedTypes ProjectStorage::fetchExportedTypes(TypeId typeId)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch exported type"_t,
+ projectStorageCategory(),
+ keyValue("type id", typeId)};
+
+ auto exportedTypes = s->selectExportedTypesByTypeIdStatement
+ .values<Storage::Synchronization::ExportedType, 12>(typeId);
+
+ tracer.end(keyValue("exported types", exportedTypes));
+
+ return exportedTypes;
+}
+
+Storage::Synchronization::PropertyDeclarations ProjectStorage::fetchPropertyDeclarations(TypeId typeId)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch property declarations"_t,
+ projectStorageCategory(),
+ keyValue("type id", typeId)};
+
+ auto propertyDeclarations = s->selectPropertyDeclarationsByTypeIdStatement
+ .values<Storage::Synchronization::PropertyDeclaration, 24>(typeId);
+
+ tracer.end(keyValue("property declarations", propertyDeclarations));
+
+ return propertyDeclarations;
+}
+
+Storage::Synchronization::FunctionDeclarations ProjectStorage::fetchFunctionDeclarations(TypeId typeId)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch signal declarations"_t,
+ projectStorageCategory(),
+ keyValue("type id", typeId)};
+
+ Storage::Synchronization::FunctionDeclarations functionDeclarations;
+
+ auto callback = [&](Utils::SmallStringView name,
+ Utils::SmallStringView returnType,
+ FunctionDeclarationId functionDeclarationId) {
+ auto &functionDeclaration = functionDeclarations.emplace_back(name, returnType);
+ functionDeclaration.parameters = s->selectFunctionParameterDeclarationsStatement
+ .values<Storage::Synchronization::ParameterDeclaration, 8>(
+ functionDeclarationId);
+ };
+
+ s->selectFunctionDeclarationsForTypeIdWithoutSignatureStatement.readCallback(callback, typeId);
+
+ tracer.end(keyValue("function declarations", functionDeclarations));
+
+ return functionDeclarations;
+}
+
+Storage::Synchronization::SignalDeclarations ProjectStorage::fetchSignalDeclarations(TypeId typeId)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch signal declarations"_t,
+ projectStorageCategory(),
+ keyValue("type id", typeId)};
+
+ Storage::Synchronization::SignalDeclarations signalDeclarations;
+
+ auto callback = [&](Utils::SmallStringView name, SignalDeclarationId signalDeclarationId) {
+ auto &signalDeclaration = signalDeclarations.emplace_back(name);
+ signalDeclaration.parameters = s->selectSignalParameterDeclarationsStatement
+ .values<Storage::Synchronization::ParameterDeclaration, 8>(
+ signalDeclarationId);
+ };
+
+ s->selectSignalDeclarationsForTypeIdWithoutSignatureStatement.readCallback(callback, typeId);
+
+ tracer.end(keyValue("signal declarations", signalDeclarations));
+
+ return signalDeclarations;
+}
+
+Storage::Synchronization::EnumerationDeclarations ProjectStorage::fetchEnumerationDeclarations(TypeId typeId)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch enumeration declarations"_t,
+ projectStorageCategory(),
+ keyValue("type id", typeId)};
+
+ Storage::Synchronization::EnumerationDeclarations enumerationDeclarations;
+
+ auto callback = [&](Utils::SmallStringView name,
+ EnumerationDeclarationId enumerationDeclarationId) {
+ enumerationDeclarations.emplace_back(
+ name,
+ s->selectEnumeratorDeclarationStatement
+ .values<Storage::Synchronization::EnumeratorDeclaration, 8>(enumerationDeclarationId));
+ };
+
+ s->selectEnumerationDeclarationsForTypeIdWithoutEnumeratorDeclarationsStatement
+ .readCallback(callback, typeId);
+
+ tracer.end(keyValue("enumeration declarations", enumerationDeclarations));
+
+ return enumerationDeclarations;
+}
+
+template<typename... TypeIds>
+bool ProjectStorage::isBasedOn_(TypeId typeId, TypeIds... baseTypeIds) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is based on"_t,
+ projectStorageCategory(),
+ keyValue("type id", typeId),
+ keyValue("base type ids", NanotraceHR::array(baseTypeIds...))};
+
+ static_assert(((std::is_same_v<TypeId, TypeIds>) &&...), "Parameter must be a TypeId!");
+
+ if (((typeId == baseTypeIds) || ...)) {
+ tracer.end(keyValue("is based on", true));
+ return true;
+ }
+
+ auto range = s->selectPrototypeAndExtensionIdsStatement.rangeWithTransaction<TypeId>(typeId);
+
+ auto isBasedOn = std::any_of(range.begin(), range.end(), [&](TypeId currentTypeId) {
+ return ((currentTypeId == baseTypeIds) || ...);
+ });
+
+ tracer.end(keyValue("is based on", isBasedOn));
+
+ return isBasedOn;
+}
+
+template<typename Id>
+ImportedTypeNameId ProjectStorage::fetchImportedTypeNameId(Storage::Synchronization::TypeNameKind kind,
+ Id id,
+ Utils::SmallStringView typeName)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch imported type name id"_t,
+ projectStorageCategory(),
+ keyValue("imported type name", typeName),
+ keyValue("kind", kind)};
+
+ auto importedTypeNameId = s->selectImportedTypeNameIdStatement.value<ImportedTypeNameId>(kind,
+ id,
+ typeName);
+
+ if (!importedTypeNameId)
+ importedTypeNameId = s->insertImportedTypeNameIdStatement.value<ImportedTypeNameId>(kind,
+ id,
+ typeName);
+
+ tracer.end(keyValue("imported type name id", importedTypeNameId));
+
+ return importedTypeNameId;
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstorage.h b/src/plugins/qmldesigner/designercore/projectstorage/projectstorage.h
index a770577a65..54d9101596 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/projectstorage.h
+++ b/src/plugins/qmldesigner/designercore/projectstorage/projectstorage.h
@@ -4,11 +4,15 @@
#pragma once
#include "commontypecache.h"
+#include "projectstorageerrornotifier.h"
#include "projectstorageexceptions.h"
#include "projectstorageinterface.h"
+#include "projectstoragetypes.h"
#include "sourcepathcachetypes.h"
#include "storagecache.h"
+#include <tracing/qmldesignertracing.h>
+
#include <sqlitealgorithms.h>
#include <sqlitedatabase.h>
#include <sqlitetable.h>
@@ -28,516 +32,167 @@ namespace QmlDesigner {
using namespace NanotraceHR::Literals;
-constexpr NanotraceHR::Tracing projectStorageTracingStatus()
-{
-#ifdef ENABLE_PROJECT_STORAGE_TRACING
- return NanotraceHR::Tracing::IsEnabled;
-#else
- return NanotraceHR::Tracing::IsDisabled;
-#endif
-}
-
-[[gnu::pure]] NanotraceHR::StringViewCategory<projectStorageTracingStatus()> &projectStorageCategory();
+using ProjectStorageTracing::projectStorageCategory;
-template<typename Database>
class ProjectStorage final : public ProjectStorageInterface
{
- friend Storage::Info::CommonTypeCache<Database>;
-
-public:
- template<int ResultCount, int BindParameterCount = 0>
- using ReadStatement = typename Database::template ReadStatement<ResultCount, BindParameterCount>;
- template<int ResultCount, int BindParameterCount = 0>
- using ReadWriteStatement = typename Database::template ReadWriteStatement<ResultCount, BindParameterCount>;
- template<int BindParameterCount>
- using WriteStatement = typename Database::template WriteStatement<BindParameterCount>;
-
- ProjectStorage(Database &database, bool isInitialized)
- : database{database}
- , exclusiveTransaction{database}
- , initializer{database, isInitialized}
- {
- NanotraceHR::Tracer tracer{"initialize"_t, projectStorageCategory()};
+ using Database = Sqlite::Database;
+ friend Storage::Info::CommonTypeCache<ProjectStorageType>;
- exclusiveTransaction.commit();
+ enum class Relink { No, Yes };
- database.walCheckpointFull();
-
- moduleCache.populate();
- }
-
- void synchronize(Storage::Synchronization::SynchronizationPackage package) override
- {
- NanotraceHR::Tracer tracer{"synchronize"_t, projectStorageCategory()};
-
- TypeIds deletedTypeIds;
- Sqlite::withImmediateTransaction(database, [&] {
- AliasPropertyDeclarations insertedAliasPropertyDeclarations;
- AliasPropertyDeclarations updatedAliasPropertyDeclarations;
-
- AliasPropertyDeclarations relinkableAliasPropertyDeclarations;
- PropertyDeclarations relinkablePropertyDeclarations;
- Prototypes relinkablePrototypes;
- Prototypes relinkableExtensions;
-
- TypeIds updatedTypeIds;
- updatedTypeIds.reserve(package.types.size());
-
- TypeIds typeIdsToBeDeleted;
-
- std::sort(package.updatedSourceIds.begin(), package.updatedSourceIds.end());
-
- synchronizeFileStatuses(package.fileStatuses, package.updatedFileStatusSourceIds);
- synchronizeImports(package.imports,
- package.updatedSourceIds,
- package.moduleDependencies,
- package.updatedModuleDependencySourceIds,
- package.moduleExportedImports,
- package.updatedModuleIds);
- synchronizeTypes(package.types,
- updatedTypeIds,
- insertedAliasPropertyDeclarations,
- updatedAliasPropertyDeclarations,
- relinkableAliasPropertyDeclarations,
- relinkablePropertyDeclarations,
- relinkablePrototypes,
- relinkableExtensions,
- package.updatedSourceIds);
- synchronizeTypeAnnotations(package.typeAnnotations,
- package.updatedTypeAnnotationSourceIds);
- synchronizePropertyEditorQmlPaths(package.propertyEditorQmlPaths,
- package.updatedPropertyEditorQmlPathSourceIds);
-
- deleteNotUpdatedTypes(updatedTypeIds,
- package.updatedSourceIds,
- typeIdsToBeDeleted,
- relinkableAliasPropertyDeclarations,
- relinkablePropertyDeclarations,
- relinkablePrototypes,
- relinkableExtensions,
- deletedTypeIds);
-
- relink(relinkableAliasPropertyDeclarations,
- relinkablePropertyDeclarations,
- relinkablePrototypes,
- relinkableExtensions,
- deletedTypeIds);
-
- linkAliases(insertedAliasPropertyDeclarations, updatedAliasPropertyDeclarations);
-
- synchronizeProjectDatas(package.projectDatas, package.updatedProjectSourceIds);
-
- commonTypeCache_.resetTypeIds();
- });
-
- callRefreshMetaInfoCallback(deletedTypeIds);
- }
+public:
+ ProjectStorage(Database &database,
+ ProjectStorageErrorNotifierInterface &errorNotifier,
+ bool isInitialized);
+ ~ProjectStorage();
- void synchronizeDocumentImports(Storage::Imports imports, SourceId sourceId) override
- {
- NanotraceHR::Tracer tracer{"synchronize document imports"_t, projectStorageCategory()};
+ void synchronize(Storage::Synchronization::SynchronizationPackage package) override;
- Sqlite::withImmediateTransaction(database, [&] {
- synchronizeDocumentImports(imports,
- {sourceId},
- Storage::Synchronization::ImportKind::Import);
- });
- }
+ void synchronizeDocumentImports(Storage::Imports imports, SourceId sourceId) override;
- void addObserver(ProjectStorageObserver *observer) override { observers.push_back(observer); }
-
- void removeObserver(ProjectStorageObserver *observer) override
+ void setErrorNotifier(ProjectStorageErrorNotifierInterface &errorNotifier)
{
- observers.removeOne(observer);
+ this->errorNotifier = &errorNotifier;
}
- ModuleId moduleId(Utils::SmallStringView moduleName) const override
- {
- NanotraceHR::Tracer tracer{"get module id"_t, projectStorageCategory()};
-
- return moduleCache.id(moduleName);
- }
+ void addObserver(ProjectStorageObserver *observer) override;
- Utils::SmallString moduleName(ModuleId moduleId) const
- {
- NanotraceHR::Tracer tracer{"get module name"_t, projectStorageCategory()};
+ void removeObserver(ProjectStorageObserver *observer) override;
- if (!moduleId)
- throw ModuleDoesNotExists{};
+ ModuleId moduleId(Utils::SmallStringView moduleName, Storage::ModuleKind kind) const override;
- return moduleCache.value(moduleId);
- }
+ Storage::Module module(ModuleId moduleId) const override;
TypeId typeId(ModuleId moduleId,
Utils::SmallStringView exportedTypeName,
- Storage::Version version) const override
- {
- NanotraceHR::Tracer tracer{"get type id by exported name"_t, projectStorageCategory()};
+ Storage::Version version) const override;
- if (version.minor)
- return selectTypeIdByModuleIdAndExportedNameAndVersionStatement
- .template valueWithTransaction<TypeId>(moduleId,
- exportedTypeName,
- version.major.value,
- version.minor.value);
+ TypeId typeId(ImportedTypeNameId typeNameId) const override;
- if (version.major)
- return selectTypeIdByModuleIdAndExportedNameAndMajorVersionStatement
- .template valueWithTransaction<TypeId>(moduleId, exportedTypeName, version.major.value);
+ QVarLengthArray<TypeId, 256> typeIds(ModuleId moduleId) const override;
- return selectTypeIdByModuleIdAndExportedNameStatement
- .template valueWithTransaction<TypeId>(moduleId, exportedTypeName);
- }
-
- TypeId typeId(ImportedTypeNameId typeNameId) const override
- {
- NanotraceHR::Tracer tracer{"get type id by imported type name"_t, projectStorageCategory()};
-
- return Sqlite::withDeferredTransaction(database, [&] { return fetchTypeId(typeNameId); });
- }
-
- QVarLengthArray<TypeId, 256> typeIds(ModuleId moduleId) const override
- {
- NanotraceHR::Tracer tracer{"get type ids by module id"_t, projectStorageCategory()};
-
- return selectTypeIdsByModuleIdStatement
- .template valuesWithTransaction<QVarLengthArray<TypeId, 256>>(moduleId);
- }
-
- Storage::Info::ExportedTypeNames exportedTypeNames(TypeId typeId) const override
- {
- NanotraceHR::Tracer tracer{"get exported type names by type id"_t, projectStorageCategory()};
+ Storage::Info::ExportedTypeNames exportedTypeNames(TypeId typeId) const override;
- return selectExportedTypesByTypeIdStatement
- .template valuesWithTransaction<Storage::Info::ExportedTypeName, 4>(typeId);
- }
+ Storage::Info::ExportedTypeNames exportedTypeNames(TypeId typeId, SourceId sourceId) const override;
- Storage::Info::ExportedTypeNames exportedTypeNames(TypeId typeId,
- SourceId sourceId) const override
- {
- NanotraceHR::Tracer tracer{"get exported type names by source id"_t, projectStorageCategory()};
-
- return selectExportedTypesByTypeIdAndSourceIdStatement
- .template valuesWithTransaction<Storage::Info::ExportedTypeName, 4>(typeId, sourceId);
- }
+ ImportId importId(const Storage::Import &import) const override;
- ImportId importId(const Storage::Import &import) const override
- {
- NanotraceHR::Tracer tracer{"get import id by import"_t, projectStorageCategory()};
+ ImportedTypeNameId importedTypeNameId(ImportId importId, Utils::SmallStringView typeName) override;
- return Sqlite::withDeferredTransaction(database, [&] {
- return fetchImportId(import.sourceId, import);
- });
- }
+ ImportedTypeNameId importedTypeNameId(SourceId sourceId, Utils::SmallStringView typeName) override;
- ImportedTypeNameId importedTypeNameId(ImportId importId,
- Utils::SmallStringView typeName) override
- {
- NanotraceHR::Tracer tracer{"get imported type name id by import id"_t,
- projectStorageCategory()};
+ QVarLengthArray<PropertyDeclarationId, 128> propertyDeclarationIds(TypeId typeId) const override;
- return Sqlite::withDeferredTransaction(database, [&] {
- return fetchImportedTypeNameId(Storage::Synchronization::TypeNameKind::QualifiedExported,
- importId,
- typeName);
- });
- }
-
- ImportedTypeNameId importedTypeNameId(SourceId sourceId,
- Utils::SmallStringView typeName) override
- {
- NanotraceHR::Tracer tracer{"get imported type name id by source id"_t,
- projectStorageCategory()};
-
- return Sqlite::withDeferredTransaction(database, [&] {
- return fetchImportedTypeNameId(Storage::Synchronization::TypeNameKind::Exported,
- sourceId,
- typeName);
- });
- }
-
- QVarLengthArray<PropertyDeclarationId, 128> propertyDeclarationIds(TypeId typeId) const override
- {
- NanotraceHR::Tracer tracer{"get property declaration ids"_t, projectStorageCategory()};
-
- return selectPropertyDeclarationIdsForTypeStatement
- .template valuesWithTransaction<QVarLengthArray<PropertyDeclarationId, 128>>(typeId);
- }
-
- QVarLengthArray<PropertyDeclarationId, 128> localPropertyDeclarationIds(TypeId typeId) const override
- {
- NanotraceHR::Tracer tracer{"get local property declaration ids"_t, projectStorageCategory()};
-
- return selectLocalPropertyDeclarationIdsForTypeStatement
- .template valuesWithTransaction<QVarLengthArray<PropertyDeclarationId, 128>>(typeId);
- }
+ QVarLengthArray<PropertyDeclarationId, 128> localPropertyDeclarationIds(TypeId typeId) const override;
PropertyDeclarationId propertyDeclarationId(TypeId typeId,
- Utils::SmallStringView propertyName) const override
- {
- NanotraceHR::Tracer tracer{"get property declaration id"_t, projectStorageCategory()};
-
- return selectPropertyDeclarationIdForTypeAndPropertyNameStatement
- .template valueWithTransaction<PropertyDeclarationId>(typeId, propertyName);
- }
+ Utils::SmallStringView propertyName) const override;
PropertyDeclarationId localPropertyDeclarationId(TypeId typeId,
- Utils::SmallStringView propertyName) const
- {
- NanotraceHR::Tracer tracer{"get local property declaration id"_t, projectStorageCategory()};
+ Utils::SmallStringView propertyName) const;
- return selectLocalPropertyDeclarationIdForTypeAndPropertyNameStatement
- .template valueWithTransaction<PropertyDeclarationId>(typeId, propertyName);
- }
+ PropertyDeclarationId defaultPropertyDeclarationId(TypeId typeId) const override;
std::optional<Storage::Info::PropertyDeclaration> propertyDeclaration(
- PropertyDeclarationId propertyDeclarationId) const override
- {
- NanotraceHR::Tracer tracer{"get property declaration"_t, projectStorageCategory()};
-
- return selectPropertyDeclarationForPropertyDeclarationIdStatement
- .template optionalValueWithTransaction<Storage::Info::PropertyDeclaration>(
- propertyDeclarationId);
- }
-
- std::optional<Storage::Info::Type> type(TypeId typeId) const override
- {
- NanotraceHR::Tracer tracer{"get type"_t, projectStorageCategory()};
-
- return selectInfoTypeByTypeIdStatement.template optionalValueWithTransaction<Storage::Info::Type>(
- typeId);
- }
+ PropertyDeclarationId propertyDeclarationId) const override;
- Utils::PathString typeIconPath(TypeId typeId) const override
- {
- NanotraceHR::Tracer tracer{"get type icon path"_t, projectStorageCategory()};
-
- return selectTypeIconPathStatement.template valueWithTransaction<Utils::PathString>(typeId);
- }
-
- Storage::Info::TypeHints typeHints(TypeId typeId) const override
- {
- NanotraceHR::Tracer tracer{"get type hints"_t, projectStorageCategory()};
+ std::optional<Storage::Info::Type> type(TypeId typeId) const override;
- return selectTypeHintsStatement.template valuesWithTransaction<Storage::Info::TypeHints, 4>(
- typeId);
- }
+ Utils::PathString typeIconPath(TypeId typeId) const override;
- Storage::Info::ItemLibraryEntries itemLibraryEntries(TypeId typeId) const override
- {
- NanotraceHR::Tracer tracer{"get item library entries by type id"_t, projectStorageCategory()};
-
- using Storage::Info::ItemLibraryProperties;
- Storage::Info::ItemLibraryEntries entries;
-
- auto callback = [&](TypeId typeId_,
- Utils::SmallStringView name,
- Utils::SmallStringView iconPath,
- Utils::SmallStringView category,
- Utils::SmallStringView import,
- Utils::SmallStringView toolTip,
- Utils::SmallStringView properties,
- Utils::SmallStringView extraFilePaths,
- Utils::SmallStringView templatePath) {
- auto &last = entries.emplace_back(
- typeId_, name, iconPath, category, import, toolTip, templatePath);
- if (properties.size())
- selectItemLibraryPropertiesStatement.readTo(last.properties, properties);
- if (extraFilePaths.size())
- selectItemLibraryExtraFilePathsStatement.readTo(last.extraFilePaths, extraFilePaths);
- };
-
- selectItemLibraryEntriesByTypeIdStatement.readCallbackWithTransaction(callback, typeId);
-
- return entries;
- }
+ Storage::Info::TypeHints typeHints(TypeId typeId) const override;
- Storage::Info::ItemLibraryEntries itemLibraryEntries(SourceId sourceId) const override
- {
- NanotraceHR::Tracer tracer{"get item library entries by source id"_t,
- projectStorageCategory()};
+ SmallSourceIds<4> typeAnnotationSourceIds(SourceId directoryId) const override;
- using Storage::Info::ItemLibraryProperties;
- Storage::Info::ItemLibraryEntries entries;
-
- auto callback = [&](TypeId typeId,
- Utils::SmallStringView name,
- Utils::SmallStringView iconPath,
- Utils::SmallStringView category,
- Utils::SmallStringView import,
- Utils::SmallStringView toolTip,
- Utils::SmallStringView properties,
- Utils::SmallStringView extraFilePaths,
- Utils::SmallStringView templatePath) {
- auto &last = entries.emplace_back(
- typeId, name, iconPath, category, import, toolTip, templatePath);
- if (properties.size())
- selectItemLibraryPropertiesStatement.readTo(last.properties, properties);
- if (extraFilePaths.size())
- selectItemLibraryExtraFilePathsStatement.readTo(last.extraFilePaths, extraFilePaths);
- };
-
- selectItemLibraryEntriesBySourceIdStatement.readCallbackWithTransaction(callback, sourceId);
-
- return entries;
- }
+ SmallSourceIds<64> typeAnnotationDirectorySourceIds() const override;
- Storage::Info::ItemLibraryEntries allItemLibraryEntries() const override
- {
- NanotraceHR::Tracer tracer{"get all item library entries"_t, projectStorageCategory()};
-
- using Storage::Info::ItemLibraryProperties;
- Storage::Info::ItemLibraryEntries entries;
-
- auto callback = [&](TypeId typeId,
- Utils::SmallStringView name,
- Utils::SmallStringView iconPath,
- Utils::SmallStringView category,
- Utils::SmallStringView import,
- Utils::SmallStringView toolTip,
- Utils::SmallStringView properties,
- Utils::SmallStringView extraFilePaths,
- Utils::SmallStringView templatePath) {
- auto &last = entries.emplace_back(
- typeId, name, iconPath, category, import, toolTip, templatePath);
- if (properties.size())
- selectItemLibraryPropertiesStatement.readTo(last.properties, properties);
- if (extraFilePaths.size())
- selectItemLibraryExtraFilePathsStatement.readTo(last.extraFilePaths, extraFilePaths);
- };
-
- selectItemLibraryEntriesStatement.readCallbackWithTransaction(callback);
-
- return entries;
- }
+ Storage::Info::ItemLibraryEntries itemLibraryEntries(TypeId typeId) const override;
- std::vector<Utils::SmallString> signalDeclarationNames(TypeId typeId) const override
- {
- NanotraceHR::Tracer tracer{"get signal names"_t, projectStorageCategory()};
+ Storage::Info::ItemLibraryEntries itemLibraryEntries(ImportId importId) const;
- return selectSignalDeclarationNamesForTypeStatement
- .template valuesWithTransaction<Utils::SmallString, 32>(typeId);
- }
+ Storage::Info::ItemLibraryEntries itemLibraryEntries(SourceId sourceId) const override;
- std::vector<Utils::SmallString> functionDeclarationNames(TypeId typeId) const override
- {
- NanotraceHR::Tracer tracer{"get function names"_t, projectStorageCategory()};
+ Storage::Info::ItemLibraryEntries allItemLibraryEntries() const override;
- return selectFuncionDeclarationNamesForTypeStatement
- .template valuesWithTransaction<Utils::SmallString, 32>(typeId);
- }
+ std::vector<Utils::SmallString> signalDeclarationNames(TypeId typeId) const override;
- std::optional<Utils::SmallString> propertyName(PropertyDeclarationId propertyDeclarationId) const override
- {
- NanotraceHR::Tracer tracer{"get property name"_t, projectStorageCategory()};
+ std::vector<Utils::SmallString> functionDeclarationNames(TypeId typeId) const override;
- return selectPropertyNameStatement.template optionalValueWithTransaction<Utils::SmallString>(
- propertyDeclarationId);
- }
+ std::optional<Utils::SmallString> propertyName(PropertyDeclarationId propertyDeclarationId) const override;
- const Storage::Info::CommonTypeCache<ProjectStorageInterface> &commonTypeCache() const override
+ const Storage::Info::CommonTypeCache<ProjectStorageType> &commonTypeCache() const override
{
return commonTypeCache_;
}
- template<const char *moduleName, const char *typeName>
+ template<const char *moduleName, const char *typeName, Storage::ModuleKind moduleKind = Storage::ModuleKind::QmlLibrary>
TypeId commonTypeId() const
{
- NanotraceHR::Tracer tracer{"get type id from common type cache"_t, projectStorageCategory()};
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get type id from common type cache"_t,
+ projectStorageCategory(),
+ keyValue("module name", std::string_view{moduleName}),
+ keyValue("type name", std::string_view{typeName})};
+
+ auto typeId = commonTypeCache_.typeId<moduleName, typeName, moduleKind>();
+
+ tracer.end(keyValue("type id", typeId));
- return commonTypeCache_.template typeId<moduleName, typeName>();
+ return typeId;
}
template<typename BuiltinType>
TypeId builtinTypeId() const
{
+ using NanotraceHR::keyValue;
NanotraceHR::Tracer tracer{"get builtin type id from common type cache"_t,
projectStorageCategory()};
- return commonTypeCache_.template builtinTypeId<BuiltinType>();
+ auto typeId = commonTypeCache_.builtinTypeId<BuiltinType>();
+
+ tracer.end(keyValue("type id", typeId));
+
+ return typeId;
}
template<const char *builtinType>
TypeId builtinTypeId() const
{
+ using NanotraceHR::keyValue;
NanotraceHR::Tracer tracer{"get builtin type id from common type cache"_t,
projectStorageCategory()};
- return commonTypeCache_.template builtinTypeId<builtinType>();
- }
+ auto typeId = commonTypeCache_.builtinTypeId<builtinType>();
- TypeIds prototypeIds(TypeId type) const override
- {
- NanotraceHR::Tracer tracer{"get prototypes"_t, projectStorageCategory()};
+ tracer.end(keyValue("type id", typeId));
- return selectPrototypeIdsForTypeIdInOrderStatement.template valuesWithTransaction<TypeId, 16>(
- type);
+ return typeId;
}
- TypeIds prototypeAndSelfIds(TypeId type) const override
- {
- NanotraceHR::Tracer tracer{"get prototypes and self"_t, projectStorageCategory()};
+ SmallTypeIds<16> prototypeIds(TypeId type) const override;
- return selectPrototypeAndSelfIdsForTypeIdInOrderStatement
- .template valuesWithTransaction<TypeId, 16>(type);
- }
+ SmallTypeIds<16> prototypeAndSelfIds(TypeId typeId) const override;
- TypeIds heirIds(TypeId typeId) const override
- {
- NanotraceHR::Tracer tracer{"get heirs"_t, projectStorageCategory()};
-
- return selectHeirTypeIdsStatement.template valuesWithTransaction<TypeId, 64>(typeId);
- }
+ SmallTypeIds<64> heirIds(TypeId typeId) const override;
template<typename... TypeIds>
- bool isBasedOn_(TypeId typeId, TypeIds... baseTypeIds) const
- {
- NanotraceHR::Tracer tracer{"is based on"_t, projectStorageCategory()};
+ bool isBasedOn_(TypeId typeId, TypeIds... baseTypeIds) const;
- static_assert(((std::is_same_v<TypeId, TypeIds>) &&...), "Parameter must be a TypeId!");
+ bool isBasedOn(TypeId) const;
- if (((typeId == baseTypeIds) || ...))
- return true;
+ bool isBasedOn(TypeId typeId, TypeId id1) const override;
- auto range = selectPrototypeIdsStatement.template rangeWithTransaction<TypeId>(typeId);
+ bool isBasedOn(TypeId typeId, TypeId id1, TypeId id2) const override;
- for ([[maybe_unused]] TypeId currentTypeId : range) {
- if (((currentTypeId == baseTypeIds) || ...))
- return true;
- }
-
- return false;
- }
+ bool isBasedOn(TypeId typeId, TypeId id1, TypeId id2, TypeId id3) const override;
- bool isBasedOn(TypeId typeId) const { return isBasedOn_(typeId); }
+ bool isBasedOn(TypeId typeId, TypeId id1, TypeId id2, TypeId id3, TypeId id4) const override;
- bool isBasedOn(TypeId typeId, TypeId id1) const override { return isBasedOn_(typeId, id1); }
+ bool isBasedOn(TypeId typeId, TypeId id1, TypeId id2, TypeId id3, TypeId id4, TypeId id5) const override;
- bool isBasedOn(TypeId typeId, TypeId id1, TypeId id2) const override
- {
- return isBasedOn_(typeId, id1, id2);
- }
-
- bool isBasedOn(TypeId typeId, TypeId id1, TypeId id2, TypeId id3) const override
- {
- return isBasedOn_(typeId, id1, id2, id3);
- }
-
- bool isBasedOn(TypeId typeId, TypeId id1, TypeId id2, TypeId id3, TypeId id4) const override
- {
- return isBasedOn_(typeId, id1, id2, id3, id4);
- }
-
- bool isBasedOn(TypeId typeId, TypeId id1, TypeId id2, TypeId id3, TypeId id4, TypeId id5) const override
- {
- return isBasedOn_(typeId, id1, id2, id3, id4, id5);
- }
-
- bool isBasedOn(
- TypeId typeId, TypeId id1, TypeId id2, TypeId id3, TypeId id4, TypeId id5, TypeId id6) const override
- {
- return isBasedOn_(typeId, id1, id2, id3, id4, id5, id6);
- }
+ bool isBasedOn(TypeId typeId, TypeId id1, TypeId id2, TypeId id3, TypeId id4, TypeId id5, TypeId id6)
+ const override;
bool isBasedOn(TypeId typeId,
TypeId id1,
@@ -546,316 +201,147 @@ public:
TypeId id4,
TypeId id5,
TypeId id6,
- TypeId id7) const override
- {
- return isBasedOn_(typeId, id1, id2, id3, id4, id5, id6, id7);
- }
+ TypeId id7) const override;
- TypeId fetchTypeIdByExportedName(Utils::SmallStringView name) const
- {
- NanotraceHR::Tracer tracer{"is based on"_t, projectStorageCategory()};
+ TypeId fetchTypeIdByExportedName(Utils::SmallStringView name) const;
- return selectTypeIdByExportedNameStatement.template valueWithTransaction<TypeId>(name);
- }
+ TypeId fetchTypeIdByModuleIdsAndExportedName(ModuleIds moduleIds,
+ Utils::SmallStringView name) const;
- TypeId fetchTypeIdByModuleIdsAndExportedName(ModuleIds moduleIds, Utils::SmallStringView name) const
- {
- return selectTypeIdByModuleIdsAndExportedNameStatement.template valueWithTransaction<TypeId>(
- static_cast<void *>(moduleIds.data()), static_cast<long long>(moduleIds.size()), name);
- }
+ TypeId fetchTypeIdByName(SourceId sourceId, Utils::SmallStringView name);
- TypeId fetchTypeIdByName(SourceId sourceId, Utils::SmallStringView name)
- {
- return selectTypeIdBySourceIdAndNameStatement.template valueWithTransaction<TypeId>(sourceId,
- name);
- }
+ Storage::Synchronization::Type fetchTypeByTypeId(TypeId typeId);
- Storage::Synchronization::Type fetchTypeByTypeId(TypeId typeId)
- {
- return Sqlite::withDeferredTransaction(database, [&] {
- auto type = selectTypeByTypeIdStatement.template value<Storage::Synchronization::Type>(
- typeId);
-
- type.exportedTypes = fetchExportedTypes(typeId);
- type.propertyDeclarations = fetchPropertyDeclarations(type.typeId);
- type.functionDeclarations = fetchFunctionDeclarations(type.typeId);
- type.signalDeclarations = fetchSignalDeclarations(type.typeId);
- type.enumerationDeclarations = fetchEnumerationDeclarations(type.typeId);
-
- return type;
- });
- }
-
- Storage::Synchronization::Types fetchTypes()
- {
- return Sqlite::withDeferredTransaction(database, [&] {
- auto types = selectTypesStatement.template values<Storage::Synchronization::Type, 64>();
-
- for (Storage::Synchronization::Type &type : types) {
- type.exportedTypes = fetchExportedTypes(type.typeId);
- type.propertyDeclarations = fetchPropertyDeclarations(type.typeId);
- type.functionDeclarations = fetchFunctionDeclarations(type.typeId);
- type.signalDeclarations = fetchSignalDeclarations(type.typeId);
- type.enumerationDeclarations = fetchEnumerationDeclarations(type.typeId);
- }
-
- return types;
- });
- }
-
- bool fetchIsProtype(TypeId type, TypeId prototype)
- {
- return bool(selectPrototypeIdStatement.template valueWithTransaction<TypeId>(type, prototype));
- }
-
- auto fetchPrototypes(TypeId type)
- {
- return selectPrototypeIdsInOrderStatement.template rangeWithTransaction<TypeId>(type);
- }
-
- SourceContextId fetchSourceContextIdUnguarded(Utils::SmallStringView sourceContextPath)
- {
- NanotraceHR::Tracer tracer{"fetch source context id unguarded"_t, projectStorageCategory()};
-
- auto sourceContextId = readSourceContextId(sourceContextPath);
-
- return sourceContextId ? sourceContextId : writeSourceContextId(sourceContextPath);
- }
-
- SourceContextId fetchSourceContextId(Utils::SmallStringView sourceContextPath)
- {
- NanotraceHR::Tracer tracer{"fetch source context id"_t, projectStorageCategory()};
-
- try {
- return Sqlite::withDeferredTransaction(database, [&] {
- return fetchSourceContextIdUnguarded(sourceContextPath);
- });
- } catch (const Sqlite::ConstraintPreventsModification &) {
- return fetchSourceContextId(sourceContextPath);
- }
- }
+ Storage::Synchronization::Types fetchTypes();
- Utils::PathString fetchSourceContextPath(SourceContextId sourceContextId) const
- {
- NanotraceHR::Tracer tracer{"fetch source context path"_t, projectStorageCategory()};
-
- return Sqlite::withDeferredTransaction(database, [&] {
- auto optionalSourceContextPath = selectSourceContextPathFromSourceContextsBySourceContextIdStatement
- .template optionalValue<Utils::PathString>(
- sourceContextId);
-
- if (!optionalSourceContextPath)
- throw SourceContextIdDoesNotExists();
-
- return std::move(*optionalSourceContextPath);
- });
- }
+ SourceContextId fetchSourceContextIdUnguarded(Utils::SmallStringView sourceContextPath);
- auto fetchAllSourceContexts() const
- {
- NanotraceHR::Tracer tracer{"fetch all source contexts"_t, projectStorageCategory()};
+ SourceContextId fetchSourceContextId(Utils::SmallStringView sourceContextPath);
- return selectAllSourceContextsStatement
- .template valuesWithTransaction<Cache::SourceContext, 128>();
- }
+ Utils::PathString fetchSourceContextPath(SourceContextId sourceContextId) const;
- SourceId fetchSourceId(SourceContextId sourceContextId, Utils::SmallStringView sourceName)
- {
- NanotraceHR::Tracer tracer{"fetch source id"_t, projectStorageCategory()};
-
- return Sqlite::withDeferredTransaction(database, [&] {
- return fetchSourceIdUnguarded(sourceContextId, sourceName);
- });
- }
+ Cache::SourceContexts fetchAllSourceContexts() const;
- auto fetchSourceNameAndSourceContextId(SourceId sourceId) const
- {
- NanotraceHR::Tracer tracer{"fetch source name and source context id"_t,
- projectStorageCategory()};
+ SourceId fetchSourceId(SourceContextId sourceContextId, Utils::SmallStringView sourceName);
- auto value = selectSourceNameAndSourceContextIdFromSourcesBySourceIdStatement
- .template valueWithTransaction<Cache::SourceNameAndSourceContextId>(sourceId);
+ Cache::SourceNameAndSourceContextId fetchSourceNameAndSourceContextId(SourceId sourceId) const;
- if (!value.sourceContextId)
- throw SourceIdDoesNotExists();
+ void clearSources();
- return value;
- }
+ SourceContextId fetchSourceContextId(SourceId sourceId) const;
- void clearSources()
- {
- Sqlite::withImmediateTransaction(database, [&] {
- deleteAllSourceContextsStatement.execute();
- deleteAllSourcesStatement.execute();
- });
- }
+ Cache::Sources fetchAllSources() const;
- SourceContextId fetchSourceContextId(SourceId sourceId) const
- {
- NanotraceHR::Tracer tracer{"fetch source context id"_t, projectStorageCategory()};
+ SourceId fetchSourceIdUnguarded(SourceContextId sourceContextId,
+ Utils::SmallStringView sourceName);
- auto sourceContextId = selectSourceContextIdFromSourcesBySourceIdStatement
- .template valueWithTransaction<SourceContextId>(sourceId);
+ FileStatuses fetchAllFileStatuses() const;
- if (!sourceContextId)
- throw SourceIdDoesNotExists();
+ FileStatus fetchFileStatus(SourceId sourceId) const override;
- return sourceContextId;
- }
+ std::optional<Storage::Synchronization::DirectoryInfo> fetchDirectoryInfo(SourceId sourceId) const override;
- auto fetchAllSources() const
- {
- NanotraceHR::Tracer tracer{"fetch all sources"_t, projectStorageCategory()};
+ Storage::Synchronization::DirectoryInfos fetchDirectoryInfos(SourceId directorySourceId) const override;
+ Storage::Synchronization::DirectoryInfos fetchDirectoryInfos(
+ SourceId directorySourceId, Storage::Synchronization::FileType fileType) const override;
+ Storage::Synchronization::DirectoryInfos fetchDirectoryInfos(const SourceIds &directorySourceIds) const;
+ SmallSourceIds<32> fetchSubdirectorySourceIds(SourceId directorySourceId) const override;
- return selectAllSourcesStatement.template valuesWithTransaction<Cache::Source, 1024>();
- }
+ void setPropertyEditorPathId(TypeId typeId, SourceId pathId);
- SourceId fetchSourceIdUnguarded(SourceContextId sourceContextId, Utils::SmallStringView sourceName)
- {
- NanotraceHR::Tracer tracer{"fetch source id unguarded"_t, projectStorageCategory()};
+ SourceId propertyEditorPathId(TypeId typeId) const override;
- auto sourceId = readSourceId(sourceContextId, sourceName);
+ Storage::Imports fetchDocumentImports() const;
- if (sourceId)
- return sourceId;
+ void resetForTestsOnly();
- return writeSourceId(sourceContextId, sourceName);
- }
-
- auto fetchAllFileStatuses() const
- {
- NanotraceHR::Tracer tracer{"fetch all file statuses"_t, projectStorageCategory()};
-
- return selectAllFileStatusesStatement.template rangeWithTransaction<FileStatus>();
- }
-
- FileStatus fetchFileStatus(SourceId sourceId) const override
- {
- NanotraceHR::Tracer tracer{"fetch file status"_t, projectStorageCategory()};
-
- return selectFileStatusesForSourceIdStatement.template valueWithTransaction<FileStatus>(
- sourceId);
- }
-
- std::optional<Storage::Synchronization::ProjectData> fetchProjectData(SourceId sourceId) const override
- {
- NanotraceHR::Tracer tracer{"fetch project data"_t, projectStorageCategory()};
-
- return selectProjectDataForSourceIdStatement
- .template optionalValueWithTransaction<Storage::Synchronization::ProjectData>(sourceId);
- }
-
- Storage::Synchronization::ProjectDatas fetchProjectDatas(SourceId projectSourceId) const override
- {
- NanotraceHR::Tracer tracer{"fetch project datas by source id"_t, projectStorageCategory()};
-
- return selectProjectDatasForSourceIdStatement
- .template valuesWithTransaction<Storage::Synchronization::ProjectData, 1024>(
- projectSourceId);
- }
-
- Storage::Synchronization::ProjectDatas fetchProjectDatas(const SourceIds &projectSourceIds) const
- {
- NanotraceHR::Tracer tracer{"fetch project datas by source ids"_t, projectStorageCategory()};
-
- return selectProjectDatasForSourceIdsStatement
- .template valuesWithTransaction<Storage::Synchronization::ProjectData, 64>(
- toIntegers(projectSourceIds));
- }
-
- void setPropertyEditorPathId(TypeId typeId, SourceId pathId)
+private:
+ struct ModuleView
{
- Sqlite::ImmediateSessionTransaction transaction{database};
+ ModuleView() = default;
- upsertPropertyEditorPathIdStatement.write(typeId, pathId);
+ ModuleView(Utils::SmallStringView name, Storage::ModuleKind kind)
+ : name{name}
+ , kind{kind}
+ {}
- transaction.commit();
- }
+ ModuleView(const Storage::Module &module)
+ : name{module.name}
+ , kind{module.kind}
+ {}
- SourceId propertyEditorPathId(TypeId typeId) const override
- {
- return selectPropertyEditorPathIdStatement.template valueWithTransaction<SourceId>(typeId);
- }
+ Utils::SmallStringView name;
+ Storage::ModuleKind kind;
- Storage::Imports fetchDocumentImports() const
- {
- NanotraceHR::Tracer tracer{"fetch document imports"_t, projectStorageCategory()};
+ friend bool operator<(ModuleView first, ModuleView second)
+ {
+ return std::tie(first.kind, first.name) < std::tie(second.kind, second.name);
+ }
- return selectAllDocumentImportForSourceIdStatement
- .template valuesWithTransaction<Storage::Imports>();
- }
+ friend bool operator==(const Storage::Module &first, ModuleView second)
+ {
+ return first.name == second.name && first.kind == second.kind;
+ }
- void resetForTestsOnly()
- {
- database.clearAllTablesForTestsOnly();
- commonTypeCache_.clearForTestsOnly();
- moduleCache.clearForTestOnly();
- }
+ friend bool operator==(ModuleView first, const Storage::Module &second)
+ {
+ return second == first;
+ }
+ };
-private:
class ModuleStorageAdapter
{
public:
- auto fetchId(const Utils::SmallStringView name) { return storage.fetchModuleId(name); }
+ auto fetchId(ModuleView module) { return storage.fetchModuleId(module.name, module.kind); }
- auto fetchValue(ModuleId id) { return storage.fetchModuleName(id); }
+ auto fetchValue(ModuleId id) { return storage.fetchModule(id); }
auto fetchAll() { return storage.fetchAllModules(); }
ProjectStorage &storage;
};
- class Module : public StorageCacheEntry<Utils::PathString, Utils::SmallStringView, ModuleId>
+ friend ModuleStorageAdapter;
+
+ static bool moduleNameLess(ModuleView first, ModuleView second) noexcept
+ {
+ return first < second;
+ }
+
+ class ModuleCacheEntry : public StorageCacheEntry<Storage::Module, ModuleView, ModuleId>
{
- using Base = StorageCacheEntry<Utils::PathString, Utils::SmallStringView, ModuleId>;
+ using Base = StorageCacheEntry<Storage::Module, ModuleView, ModuleId>;
public:
using Base::Base;
- friend bool operator==(const Module &first, const Module &second)
+ ModuleCacheEntry(Utils::SmallStringView name, Storage::ModuleKind kind, ModuleId moduleId)
+ : Base{{name, kind}, moduleId}
+ {}
+
+ friend bool operator==(const ModuleCacheEntry &first, const ModuleCacheEntry &second)
{
return &first == &second && first.value == second.value;
}
- };
- friend ModuleStorageAdapter;
+ friend bool operator==(const ModuleCacheEntry &first, ModuleView second)
+ {
+ return first.value.name == second.name && first.value.kind == second.kind;
+ }
+ };
- static bool moduleNameLess(Utils::SmallStringView first, Utils::SmallStringView second) noexcept
- {
- return first < second;
- }
+ using ModuleCacheEntries = std::vector<ModuleCacheEntry>;
- using ModuleCache = StorageCache<Utils::PathString,
- Utils::SmallStringView,
- ModuleId,
- ModuleStorageAdapter,
- NonLockingMutex,
- moduleNameLess,
- Module>;
+ using ModuleCache
+ = StorageCache<Storage::Module, ModuleView, ModuleId, ModuleStorageAdapter, NonLockingMutex, moduleNameLess, ModuleCacheEntry>;
- ModuleId fetchModuleId(Utils::SmallStringView moduleName)
- {
- return Sqlite::withDeferredTransaction(database,
- [&] { return fetchModuleIdUnguarded(moduleName); });
- }
+ ModuleId fetchModuleId(Utils::SmallStringView moduleName, Storage::ModuleKind moduleKind);
- auto fetchModuleName(ModuleId id)
- {
- return Sqlite::withDeferredTransaction(database, [&] { return fetchModuleNameUnguarded(id); });
- }
+ Storage::Module fetchModule(ModuleId id);
- auto fetchAllModules() const
- {
- return selectAllModulesStatement.template valuesWithTransaction<Module, 128>();
- }
+ ModuleCacheEntries fetchAllModules() const;
- void callRefreshMetaInfoCallback(const TypeIds &deletedTypeIds)
- {
- if (deletedTypeIds.size()) {
- for (ProjectStorageObserver *observer : observers)
- observer->removedTypeIds(deletedTypeIds);
- }
- }
+ void callRefreshMetaInfoCallback(const TypeIds &deletedTypeIds);
class AliasPropertyDeclaration
{
@@ -882,6 +368,25 @@ private:
< std::tie(second.typeId, second.propertyDeclarationId);
}
+ template<typename String>
+ friend void convertToString(String &string,
+ const AliasPropertyDeclaration &aliasPropertyDeclaration)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(
+ keyValue("type id", aliasPropertyDeclaration.typeId),
+ keyValue("property declaration id", aliasPropertyDeclaration.propertyDeclarationId),
+ keyValue("alias imported type name id",
+ aliasPropertyDeclaration.aliasImportedTypeNameId),
+ keyValue("alias property name", aliasPropertyDeclaration.aliasPropertyName),
+ keyValue("alias property name tail", aliasPropertyDeclaration.aliasPropertyNameTail),
+ keyValue("alias property declaration id",
+ aliasPropertyDeclaration.aliasPropertyDeclarationId));
+
+ convertToString(string, dict);
+ }
+
public:
TypeId typeId;
PropertyDeclarationId propertyDeclarationId;
@@ -910,6 +415,20 @@ private:
< std::tie(second.typeId, second.propertyDeclarationId);
}
+ template<typename String>
+ friend void convertToString(String &string, const PropertyDeclaration &propertyDeclaration)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("type id", propertyDeclaration.typeId),
+ keyValue("property declaration id",
+ propertyDeclaration.propertyDeclarationId),
+ keyValue("imported type name id",
+ propertyDeclaration.importedTypeNameId));
+
+ convertToString(string, dict);
+ }
+
public:
TypeId typeId;
PropertyDeclarationId propertyDeclarationId;
@@ -931,6 +450,22 @@ private:
return first.typeId < second.typeId;
}
+ friend bool operator==(Prototype first, Prototype second)
+ {
+ return first.typeId == second.typeId;
+ }
+
+ template<typename String>
+ friend void convertToString(String &string, const Prototype &prototype)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("type id", prototype.typeId),
+ keyValue("prototype name id", prototype.prototypeNameId));
+
+ convertToString(string, dict);
+ }
+
public:
TypeId typeId;
ImportedTypeNameId prototypeNameId;
@@ -970,127 +505,67 @@ private:
}
};
- SourceIds filterSourceIdsWithoutType(const SourceIds &updatedSourceIds, SourceIds &sourceIdsOfTypes)
- {
- std::sort(sourceIdsOfTypes.begin(), sourceIdsOfTypes.end());
+ SourceIds filterSourceIdsWithoutType(const SourceIds &updatedSourceIds,
+ SourceIds &sourceIdsOfTypes);
- SourceIds sourceIdsWithoutTypeSourceIds;
- sourceIdsWithoutTypeSourceIds.reserve(updatedSourceIds.size());
- std::set_difference(updatedSourceIds.begin(),
- updatedSourceIds.end(),
- sourceIdsOfTypes.begin(),
- sourceIdsOfTypes.end(),
- std::back_inserter(sourceIdsWithoutTypeSourceIds));
+ TypeIds fetchTypeIds(const SourceIds &sourceIds);
- return sourceIdsWithoutTypeSourceIds;
- }
-
- TypeIds fetchTypeIds(const SourceIds &sourceIds)
- {
- return selectTypeIdsForSourceIdsStatement.template values<TypeId, 128>(toIntegers(sourceIds));
- }
-
- void unique(SourceIds &sourceIds)
- {
- std::sort(sourceIds.begin(), sourceIds.end());
- auto newEnd = std::unique(sourceIds.begin(), sourceIds.end());
- sourceIds.erase(newEnd, sourceIds.end());
- }
+ void unique(SourceIds &sourceIds);
- void synchronizeTypeTraits(TypeId typeId, Storage::TypeTraits traits)
- {
- updateTypeAnnotationTraitStatement.write(typeId, traits.annotation);
- }
+ void synchronizeTypeTraits(TypeId typeId, Storage::TypeTraits traits);
class TypeAnnotationView
{
public:
TypeAnnotationView(TypeId typeId,
+ Utils::SmallStringView typeName,
Utils::SmallStringView iconPath,
Utils::SmallStringView itemLibraryJson,
Utils::SmallStringView hintsJson)
: typeId{typeId}
+ , typeName{typeName}
, iconPath{iconPath}
, itemLibraryJson{itemLibraryJson}
, hintsJson{hintsJson}
{}
+ template<typename String>
+ friend void convertToString(String &string, const TypeAnnotationView &typeAnnotationView)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("type id", typeAnnotationView.typeId),
+ keyValue("type name", typeAnnotationView.typeName),
+ keyValue("icon path", typeAnnotationView.iconPath),
+ keyValue("item library json", typeAnnotationView.itemLibraryJson),
+ keyValue("hints json", typeAnnotationView.hintsJson));
+
+ convertToString(string, dict);
+ }
+
public:
TypeId typeId;
+ Utils::SmallStringView typeName;
Utils::SmallStringView iconPath;
Utils::SmallStringView itemLibraryJson;
Utils::PathString hintsJson;
};
- void updateTypeIdInTypeAnnotations(Storage::Synchronization::TypeAnnotations &typeAnnotations)
- {
- for (auto &annotation : typeAnnotations) {
- annotation.typeId = fetchTypeIdByModuleIdAndExportedName(annotation.moduleId,
- annotation.typeName);
- }
- }
+ void updateTypeIdInTypeAnnotations(Storage::Synchronization::TypeAnnotations &typeAnnotations);
- void synchronizeTypeAnnotations(Storage::Synchronization::TypeAnnotations &typeAnnotations,
- const SourceIds &updatedTypeAnnotationSourceIds)
+ template<typename Value>
+ static Sqlite::ValueView createEmptyAsNull(const Value &value)
{
- NanotraceHR::Tracer tracer{"synchronize type annotations"_t, projectStorageCategory()};
-
- using Storage::Synchronization::TypeAnnotation;
-
- updateTypeIdInTypeAnnotations(typeAnnotations);
-
- auto compareKey = [](auto &&first, auto &&second) { return first.typeId - second.typeId; };
+ if (value.size())
+ return Sqlite::ValueView::create(value);
- std::sort(typeAnnotations.begin(), typeAnnotations.end(), [&](auto &&first, auto &&second) {
- return first.typeId < second.typeId;
- });
-
- auto range = selectTypeAnnotationsForSourceIdsStatement.template range<TypeAnnotationView>(
- toIntegers(updatedTypeAnnotationSourceIds));
-
- auto insert = [&](const TypeAnnotation &annotation) {
- if (!annotation.sourceId)
- throw TypeAnnotationHasInvalidSourceId{};
-
- synchronizeTypeTraits(annotation.typeId, annotation.traits);
-
- insertTypeAnnotationStatement.write(annotation.typeId,
- annotation.sourceId,
- annotation.iconPath,
- annotation.itemLibraryJson,
- annotation.hintsJson);
- };
-
- auto update = [&](const TypeAnnotationView &annotationFromDatabase,
- const TypeAnnotation &annotation) {
- synchronizeTypeTraits(annotation.typeId, annotation.traits);
-
- if (annotationFromDatabase.iconPath != annotation.iconPath
- || annotationFromDatabase.itemLibraryJson != annotation.itemLibraryJson
- || annotationFromDatabase.hintsJson != annotation.hintsJson) {
- updateTypeAnnotationStatement.write(annotation.typeId,
- annotation.iconPath,
- annotation.itemLibraryJson,
- annotation.hintsJson);
- return Sqlite::UpdateChange::Update;
- }
-
- return Sqlite::UpdateChange::No;
- };
-
- auto remove = [&](const TypeAnnotationView &annotationFromDatabase) {
- synchronizeTypeTraits(annotationFromDatabase.typeId, Storage::TypeTraits{});
-
- deleteTypeAnnotationStatement.write(annotationFromDatabase.typeId);
- };
-
- Sqlite::insertUpdateDelete(range, typeAnnotations, compareKey, insert, update, remove);
+ return Sqlite::ValueView{};
}
- void synchronizeTypeTrait(const Storage::Synchronization::Type &type)
- {
- updateTypeTraitStatement.write(type.typeId, type.traits.type);
- }
+ void synchronizeTypeAnnotations(Storage::Synchronization::TypeAnnotations &typeAnnotations,
+ const SourceIds &updatedTypeAnnotationSourceIds);
+
+ void synchronizeTypeTrait(const Storage::Synchronization::Type &type);
void synchronizeTypes(Storage::Synchronization::Types &types,
TypeIds &updatedTypeIds,
@@ -1100,403 +575,62 @@ private:
PropertyDeclarations &relinkablePropertyDeclarations,
Prototypes &relinkablePrototypes,
Prototypes &relinkableExtensions,
- const SourceIds &updatedSourceIds)
- {
- NanotraceHR::Tracer tracer{"synchronize types"_t, projectStorageCategory()};
-
- Storage::Synchronization::ExportedTypes exportedTypes;
- exportedTypes.reserve(types.size() * 3);
- SourceIds sourceIdsOfTypes;
- sourceIdsOfTypes.reserve(updatedSourceIds.size());
- SourceIds notUpdatedExportedSourceIds;
- notUpdatedExportedSourceIds.reserve(updatedSourceIds.size());
- SourceIds exportedSourceIds;
- exportedSourceIds.reserve(types.size());
-
- for (auto &type : types) {
- if (!type.sourceId)
- throw TypeHasInvalidSourceId{};
-
- TypeId typeId = declareType(type);
- synchronizeTypeTrait(type);
- sourceIdsOfTypes.push_back(type.sourceId);
- updatedTypeIds.push_back(typeId);
- if (type.changeLevel != Storage::Synchronization::ChangeLevel::ExcludeExportedTypes) {
- exportedSourceIds.push_back(type.sourceId);
- extractExportedTypes(typeId, type, exportedTypes);
- }
- }
-
- std::sort(types.begin(), types.end(), [](const auto &first, const auto &second) {
- return first.typeId < second.typeId;
- });
-
- unique(exportedSourceIds);
-
- SourceIds sourceIdsWithoutType = filterSourceIdsWithoutType(updatedSourceIds,
- sourceIdsOfTypes);
- exportedSourceIds.insert(exportedSourceIds.end(),
- sourceIdsWithoutType.begin(),
- sourceIdsWithoutType.end());
- TypeIds exportedTypeIds = fetchTypeIds(exportedSourceIds);
- synchronizeExportedTypes(exportedTypeIds,
- exportedTypes,
- relinkableAliasPropertyDeclarations,
- relinkablePropertyDeclarations,
- relinkablePrototypes,
- relinkableExtensions);
-
- syncPrototypesAndExtensions(types, relinkablePrototypes, relinkableExtensions);
- resetDefaultPropertiesIfChanged(types);
- resetRemovedAliasPropertyDeclarationsToNull(types, relinkableAliasPropertyDeclarations);
- syncDeclarations(types,
- insertedAliasPropertyDeclarations,
- updatedAliasPropertyDeclarations,
- relinkablePropertyDeclarations);
- syncDefaultProperties(types);
- }
+ const SourceIds &updatedSourceIds);
- void synchronizeProjectDatas(Storage::Synchronization::ProjectDatas &projectDatas,
- const SourceIds &updatedProjectSourceIds)
- {
- NanotraceHR::Tracer tracer{"synchronize project datas"_t, projectStorageCategory()};
-
- auto compareKey = [](auto &&first, auto &&second) {
- auto projectSourceIdDifference = first.projectSourceId - second.projectSourceId;
- if (projectSourceIdDifference != 0)
- return projectSourceIdDifference;
-
- return first.sourceId - second.sourceId;
- };
-
- std::sort(projectDatas.begin(), projectDatas.end(), [&](auto &&first, auto &&second) {
- return std::tie(first.projectSourceId, first.sourceId)
- < std::tie(second.projectSourceId, second.sourceId);
- });
-
- auto range = selectProjectDatasForSourceIdsStatement
- .template range<Storage::Synchronization::ProjectData>(
- toIntegers(updatedProjectSourceIds));
-
- auto insert = [&](const Storage::Synchronization::ProjectData &projectData) {
- if (!projectData.projectSourceId)
- throw ProjectDataHasInvalidProjectSourceId{};
- if (!projectData.sourceId)
- throw ProjectDataHasInvalidSourceId{};
-
- insertProjectDataStatement.write(projectData.projectSourceId,
- projectData.sourceId,
- projectData.moduleId,
- projectData.fileType);
- };
-
- auto update = [&](const Storage::Synchronization::ProjectData &projectDataFromDatabase,
- const Storage::Synchronization::ProjectData &projectData) {
- if (projectDataFromDatabase.fileType != projectData.fileType
- || !compareInvalidAreTrue(projectDataFromDatabase.moduleId, projectData.moduleId)) {
- updateProjectDataStatement.write(projectData.projectSourceId,
- projectData.sourceId,
- projectData.moduleId,
- projectData.fileType);
- return Sqlite::UpdateChange::Update;
- }
-
- return Sqlite::UpdateChange::No;
- };
-
- auto remove = [&](const Storage::Synchronization::ProjectData &projectData) {
- deleteProjectDataStatement.write(projectData.projectSourceId, projectData.sourceId);
- };
-
- Sqlite::insertUpdateDelete(range, projectDatas, compareKey, insert, update, remove);
- }
+ void synchronizeDirectoryInfos(Storage::Synchronization::DirectoryInfos &directoryInfos,
+ const SourceIds &updatedDirectoryInfoSourceIds);
- void synchronizeFileStatuses(FileStatuses &fileStatuses, const SourceIds &updatedSourceIds)
- {
- NanotraceHR::Tracer tracer{"synchronize file statuses"_t, projectStorageCategory()};
-
- auto compareKey = [](auto &&first, auto &&second) {
- return first.sourceId - second.sourceId;
- };
-
- std::sort(fileStatuses.begin(), fileStatuses.end(), [&](auto &&first, auto &&second) {
- return first.sourceId < second.sourceId;
- });
-
- auto range = selectFileStatusesForSourceIdsStatement.template range<FileStatus>(
- toIntegers(updatedSourceIds));
-
- auto insert = [&](const FileStatus &fileStatus) {
- if (!fileStatus.sourceId)
- throw FileStatusHasInvalidSourceId{};
- insertFileStatusStatement.write(fileStatus.sourceId,
- fileStatus.size,
- fileStatus.lastModified);
- };
-
- auto update = [&](const FileStatus &fileStatusFromDatabase, const FileStatus &fileStatus) {
- if (fileStatusFromDatabase.lastModified != fileStatus.lastModified
- || fileStatusFromDatabase.size != fileStatus.size) {
- updateFileStatusStatement.write(fileStatus.sourceId,
- fileStatus.size,
- fileStatus.lastModified);
- return Sqlite::UpdateChange::Update;
- }
-
- return Sqlite::UpdateChange::No;
- };
-
- auto remove = [&](const FileStatus &fileStatus) {
- deleteFileStatusStatement.write(fileStatus.sourceId);
- };
-
- Sqlite::insertUpdateDelete(range, fileStatuses, compareKey, insert, update, remove);
- }
+ void synchronizeFileStatuses(FileStatuses &fileStatuses, const SourceIds &updatedSourceIds);
void synchronizeImports(Storage::Imports &imports,
const SourceIds &updatedSourceIds,
Storage::Imports &moduleDependencies,
const SourceIds &updatedModuleDependencySourceIds,
Storage::Synchronization::ModuleExportedImports &moduleExportedImports,
- const ModuleIds &updatedModuleIds)
- {
- NanotraceHR::Tracer tracer{"synchronize imports"_t, projectStorageCategory()};
-
- synchromizeModuleExportedImports(moduleExportedImports, updatedModuleIds);
- synchronizeDocumentImports(imports,
- updatedSourceIds,
- Storage::Synchronization::ImportKind::Import);
- synchronizeDocumentImports(moduleDependencies,
- updatedModuleDependencySourceIds,
- Storage::Synchronization::ImportKind::ModuleDependency);
- }
+ const ModuleIds &updatedModuleIds,
+ Prototypes &relinkablePrototypes,
+ Prototypes &relinkableExtensions);
void synchromizeModuleExportedImports(
Storage::Synchronization::ModuleExportedImports &moduleExportedImports,
- const ModuleIds &updatedModuleIds)
- {
- std::sort(moduleExportedImports.begin(),
- moduleExportedImports.end(),
- [](auto &&first, auto &&second) {
- return std::tie(first.moduleId, first.exportedModuleId)
- < std::tie(second.moduleId, second.exportedModuleId);
- });
-
- auto range = selectModuleExportedImportsForSourceIdStatement
- .template range<Storage::Synchronization::ModuleExportedImportView>(
- toIntegers(updatedModuleIds));
-
- auto compareKey = [](const Storage::Synchronization::ModuleExportedImportView &view,
- const Storage::Synchronization::ModuleExportedImport &import) -> long long {
- auto moduleIdDifference = view.moduleId - import.moduleId;
- if (moduleIdDifference != 0)
- return moduleIdDifference;
-
- return view.exportedModuleId - import.exportedModuleId;
- };
-
- auto insert = [&](const Storage::Synchronization::ModuleExportedImport &import) {
- if (import.version.minor) {
- insertModuleExportedImportWithVersionStatement.write(import.moduleId,
- import.exportedModuleId,
- import.isAutoVersion,
- import.version.major.value,
- import.version.minor.value);
- } else if (import.version.major) {
- insertModuleExportedImportWithMajorVersionStatement.write(import.moduleId,
- import.exportedModuleId,
- import.isAutoVersion,
- import.version.major.value);
- } else {
- insertModuleExportedImportWithoutVersionStatement.write(import.moduleId,
- import.exportedModuleId,
- import.isAutoVersion);
- }
- };
-
- auto update = [](const Storage::Synchronization::ModuleExportedImportView &,
- const Storage::Synchronization::ModuleExportedImport &) {
- return Sqlite::UpdateChange::No;
- };
-
- auto remove = [&](const Storage::Synchronization::ModuleExportedImportView &view) {
- deleteModuleExportedImportStatement.write(view.moduleExportedImportId);
- };
-
- Sqlite::insertUpdateDelete(range, moduleExportedImports, compareKey, insert, update, remove);
- }
-
- ModuleId fetchModuleIdUnguarded(Utils::SmallStringView name) const override
- {
- auto moduleId = selectModuleIdByNameStatement.template value<ModuleId>(name);
+ const ModuleIds &updatedModuleIds);
- if (moduleId)
- return moduleId;
+ ModuleId fetchModuleIdUnguarded(Utils::SmallStringView name,
+ Storage::ModuleKind moduleKind) const override;
- return insertModuleNameStatement.template value<ModuleId>(name);
- }
-
- auto fetchModuleNameUnguarded(ModuleId id) const
- {
- auto moduleName = selectModuleNameStatement.template value<Utils::PathString>(id);
-
- if (moduleName.empty())
- throw ModuleDoesNotExists{};
-
- return moduleName;
- }
+ Storage::Module fetchModuleUnguarded(ModuleId id) const;
void handleAliasPropertyDeclarationsWithPropertyType(
- TypeId typeId, AliasPropertyDeclarations &relinkableAliasPropertyDeclarations)
- {
- auto callback = [&](TypeId typeId_,
- PropertyDeclarationId propertyDeclarationId,
- ImportedTypeNameId propertyImportedTypeNameId,
- PropertyDeclarationId aliasPropertyDeclarationId,
- PropertyDeclarationId aliasPropertyDeclarationTailId) {
- auto aliasPropertyName = selectPropertyNameStatement.template value<Utils::SmallString>(
- aliasPropertyDeclarationId);
- Utils::SmallString aliasPropertyNameTail;
- if (aliasPropertyDeclarationTailId)
- aliasPropertyNameTail = selectPropertyNameStatement.template value<Utils::SmallString>(
- aliasPropertyDeclarationTailId);
-
- relinkableAliasPropertyDeclarations
- .emplace_back(TypeId{typeId_},
- PropertyDeclarationId{propertyDeclarationId},
- ImportedTypeNameId{propertyImportedTypeNameId},
- std::move(aliasPropertyName),
- std::move(aliasPropertyNameTail));
-
- updateAliasPropertyDeclarationToNullStatement.write(propertyDeclarationId);
- };
-
- selectAliasPropertiesDeclarationForPropertiesWithTypeIdStatement.readCallback(callback,
- typeId);
- }
+ TypeId typeId, AliasPropertyDeclarations &relinkableAliasPropertyDeclarations);
void handlePropertyDeclarationWithPropertyType(TypeId typeId,
- PropertyDeclarations &relinkablePropertyDeclarations)
- {
- updatesPropertyDeclarationPropertyTypeToNullStatement.readTo(relinkablePropertyDeclarations,
- typeId);
- }
+ PropertyDeclarations &relinkablePropertyDeclarations);
- void handlePrototypes(TypeId prototypeId, Prototypes &relinkablePrototypes)
- {
- auto callback = [&](TypeId typeId, ImportedTypeNameId prototypeNameId) {
- relinkablePrototypes.emplace_back(typeId, prototypeNameId);
- };
-
- updatePrototypeIdToNullStatement.readCallback(callback, prototypeId);
- }
-
- void handleExtensions(TypeId extensionId, Prototypes &relinkableExtensions)
- {
- auto callback = [&](TypeId typeId, ImportedTypeNameId extensionNameId) {
- relinkableExtensions.emplace_back(typeId, extensionNameId);
- };
-
- updateExtensionIdToNullStatement.readCallback(callback, extensionId);
- }
+ void handlePrototypes(TypeId prototypeId, Prototypes &relinkablePrototypes);
+ void handlePrototypesWithExportedTypeNameAndTypeId(Utils::SmallStringView exportedTypeName,
+ TypeId typeId,
+ Prototypes &relinkablePrototypes);
+ void handleExtensions(TypeId extensionId, Prototypes &relinkableExtensions);
+ void handleExtensionsWithExportedTypeNameAndTypeId(Utils::SmallStringView exportedTypeName,
+ TypeId typeId,
+ Prototypes &relinkableExtensions);
void deleteType(TypeId typeId,
AliasPropertyDeclarations &relinkableAliasPropertyDeclarations,
PropertyDeclarations &relinkablePropertyDeclarations,
Prototypes &relinkablePrototypes,
- Prototypes &relinkableExtensions)
- {
- handlePropertyDeclarationWithPropertyType(typeId, relinkablePropertyDeclarations);
- handleAliasPropertyDeclarationsWithPropertyType(typeId, relinkableAliasPropertyDeclarations);
- handlePrototypes(typeId, relinkablePrototypes);
- handleExtensions(typeId, relinkableExtensions);
- deleteTypeNamesByTypeIdStatement.write(typeId);
- deleteEnumerationDeclarationByTypeIdStatement.write(typeId);
- deletePropertyDeclarationByTypeIdStatement.write(typeId);
- deleteFunctionDeclarationByTypeIdStatement.write(typeId);
- deleteSignalDeclarationByTypeIdStatement.write(typeId);
- deleteTypeStatement.write(typeId);
- }
+ Prototypes &relinkableExtensions);
void relinkAliasPropertyDeclarations(AliasPropertyDeclarations &aliasPropertyDeclarations,
- const TypeIds &deletedTypeIds)
- {
- NanotraceHR::Tracer tracer{"relink alias properties"_t, projectStorageCategory()};
-
- std::sort(aliasPropertyDeclarations.begin(), aliasPropertyDeclarations.end());
-
- Utils::set_greedy_difference(
- aliasPropertyDeclarations.cbegin(),
- aliasPropertyDeclarations.cend(),
- deletedTypeIds.begin(),
- deletedTypeIds.end(),
- [&](const AliasPropertyDeclaration &alias) {
- auto typeId = fetchTypeId(alias.aliasImportedTypeNameId);
-
- if (!typeId)
- throw TypeNameDoesNotExists{fetchImportedTypeName(alias.aliasImportedTypeNameId)};
-
- auto [propertyTypeId, aliasId, propertyTraits] = fetchPropertyDeclarationByTypeIdAndNameUngarded(
- typeId, alias.aliasPropertyName);
-
- updatePropertyDeclarationWithAliasAndTypeStatement.write(alias.propertyDeclarationId,
- propertyTypeId,
- propertyTraits,
- alias.aliasImportedTypeNameId,
- aliasId);
- },
- TypeCompare<AliasPropertyDeclaration>{});
- }
+ const TypeIds &deletedTypeIds);
void relinkPropertyDeclarations(PropertyDeclarations &relinkablePropertyDeclaration,
- const TypeIds &deletedTypeIds)
- {
- NanotraceHR::Tracer tracer{"relink properties"_t, projectStorageCategory()};
-
- std::sort(relinkablePropertyDeclaration.begin(), relinkablePropertyDeclaration.end());
-
- Utils::set_greedy_difference(
- relinkablePropertyDeclaration.cbegin(),
- relinkablePropertyDeclaration.cend(),
- deletedTypeIds.begin(),
- deletedTypeIds.end(),
- [&](const PropertyDeclaration &property) {
- TypeId propertyTypeId = fetchTypeId(property.importedTypeNameId);
-
- if (!propertyTypeId)
- throw TypeNameDoesNotExists{fetchImportedTypeName(property.importedTypeNameId)};
-
- updatePropertyDeclarationTypeStatement.write(property.propertyDeclarationId,
- propertyTypeId);
- },
- TypeCompare<PropertyDeclaration>{});
- }
+ const TypeIds &deletedTypeIds);
template<typename Callable>
void relinkPrototypes(Prototypes &relinkablePrototypes,
const TypeIds &deletedTypeIds,
- Callable updateStatement)
- {
- NanotraceHR::Tracer tracer{"relink prototypes"_t, projectStorageCategory()};
-
- std::sort(relinkablePrototypes.begin(), relinkablePrototypes.end());
-
- Utils::set_greedy_difference(
- relinkablePrototypes.cbegin(),
- relinkablePrototypes.cend(),
- deletedTypeIds.begin(),
- deletedTypeIds.end(),
- [&](const Prototype &prototype) {
- TypeId prototypeId = fetchTypeId(prototype.prototypeNameId);
-
- if (!prototypeId)
- throw TypeNameDoesNotExists{fetchImportedTypeName(prototype.prototypeNameId)};
-
- updateStatement(prototype.typeId, prototypeId);
- checkForPrototypeChainCycle(prototype.typeId);
- },
- TypeCompare<Prototype>{});
- }
+ Callable updateStatement);
void deleteNotUpdatedTypes(const TypeIds &updatedTypeIds,
const SourceIds &updatedSourceIds,
@@ -1505,295 +639,66 @@ private:
PropertyDeclarations &relinkablePropertyDeclarations,
Prototypes &relinkablePrototypes,
Prototypes &relinkableExtensions,
- TypeIds &deletedTypeIds)
- {
- NanotraceHR::Tracer tracer{"delete not updated types"_t, projectStorageCategory()};
-
- auto callback = [&](TypeId typeId) {
- deletedTypeIds.push_back(typeId);
- deleteType(typeId,
- relinkableAliasPropertyDeclarations,
- relinkablePropertyDeclarations,
- relinkablePrototypes,
- relinkableExtensions);
- };
-
- selectNotUpdatedTypesInSourcesStatement.readCallback(callback,
- toIntegers(updatedSourceIds),
- toIntegers(updatedTypeIds));
- for (TypeId typeIdToBeDeleted : typeIdsToBeDeleted)
- callback(typeIdToBeDeleted);
- }
+ TypeIds &deletedTypeIds);
void relink(AliasPropertyDeclarations &relinkableAliasPropertyDeclarations,
PropertyDeclarations &relinkablePropertyDeclarations,
Prototypes &relinkablePrototypes,
Prototypes &relinkableExtensions,
- TypeIds &deletedTypeIds)
- {
- NanotraceHR::Tracer tracer{"relink"_t, projectStorageCategory()};
-
- std::sort(deletedTypeIds.begin(), deletedTypeIds.end());
-
- relinkPrototypes(relinkablePrototypes, deletedTypeIds, [&](TypeId typeId, TypeId prototypeId) {
- updateTypePrototypeStatement.write(typeId, prototypeId);
- });
- relinkPrototypes(relinkableExtensions, deletedTypeIds, [&](TypeId typeId, TypeId prototypeId) {
- updateTypeExtensionStatement.write(typeId, prototypeId);
- });
- relinkPropertyDeclarations(relinkablePropertyDeclarations, deletedTypeIds);
- relinkAliasPropertyDeclarations(relinkableAliasPropertyDeclarations, deletedTypeIds);
- }
+ TypeIds &deletedTypeIds);
PropertyDeclarationId fetchAliasId(TypeId aliasTypeId,
Utils::SmallStringView aliasPropertyName,
- Utils::SmallStringView aliasPropertyNameTail)
- {
- if (aliasPropertyNameTail.empty())
- return fetchPropertyDeclarationIdByTypeIdAndNameUngarded(aliasTypeId, aliasPropertyName);
+ Utils::SmallStringView aliasPropertyNameTail);
- auto stemAlias = fetchPropertyDeclarationByTypeIdAndNameUngarded(aliasTypeId,
- aliasPropertyName);
+ void linkAliasPropertyDeclarationAliasIds(const AliasPropertyDeclarations &aliasDeclarations);
- return fetchPropertyDeclarationIdByTypeIdAndNameUngarded(stemAlias.propertyTypeId,
- aliasPropertyNameTail);
- }
+ void updateAliasPropertyDeclarationValues(const AliasPropertyDeclarations &aliasDeclarations);
- void linkAliasPropertyDeclarationAliasIds(const AliasPropertyDeclarations &aliasDeclarations)
- {
- for (const auto &aliasDeclaration : aliasDeclarations) {
- auto aliasTypeId = fetchTypeId(aliasDeclaration.aliasImportedTypeNameId);
-
- if (!aliasTypeId) {
- throw TypeNameDoesNotExists{
- fetchImportedTypeName(aliasDeclaration.aliasImportedTypeNameId)};
- }
-
- auto aliasId = fetchAliasId(aliasTypeId,
- aliasDeclaration.aliasPropertyName,
- aliasDeclaration.aliasPropertyNameTail);
-
- updatePropertyDeclarationAliasIdAndTypeNameIdStatement
- .write(aliasDeclaration.propertyDeclarationId,
- aliasId,
- aliasDeclaration.aliasImportedTypeNameId);
- }
- }
-
- void updateAliasPropertyDeclarationValues(const AliasPropertyDeclarations &aliasDeclarations)
- {
- for (const auto &aliasDeclaration : aliasDeclarations) {
- updatetPropertiesDeclarationValuesOfAliasStatement.write(
- aliasDeclaration.propertyDeclarationId);
- updatePropertyAliasDeclarationRecursivelyStatement.write(
- aliasDeclaration.propertyDeclarationId);
- }
- }
-
- void checkAliasPropertyDeclarationCycles(const AliasPropertyDeclarations &aliasDeclarations)
- {
- for (const auto &aliasDeclaration : aliasDeclarations)
- checkForAliasChainCycle(aliasDeclaration.propertyDeclarationId);
- }
+ void checkAliasPropertyDeclarationCycles(const AliasPropertyDeclarations &aliasDeclarations);
void linkAliases(const AliasPropertyDeclarations &insertedAliasPropertyDeclarations,
- const AliasPropertyDeclarations &updatedAliasPropertyDeclarations)
- {
- NanotraceHR::Tracer tracer{"link aliases"_t, projectStorageCategory()};
-
- linkAliasPropertyDeclarationAliasIds(insertedAliasPropertyDeclarations);
- linkAliasPropertyDeclarationAliasIds(updatedAliasPropertyDeclarations);
-
- checkAliasPropertyDeclarationCycles(insertedAliasPropertyDeclarations);
- checkAliasPropertyDeclarationCycles(updatedAliasPropertyDeclarations);
-
- updateAliasPropertyDeclarationValues(insertedAliasPropertyDeclarations);
- updateAliasPropertyDeclarationValues(updatedAliasPropertyDeclarations);
- }
+ const AliasPropertyDeclarations &updatedAliasPropertyDeclarations);
void synchronizeExportedTypes(const TypeIds &updatedTypeIds,
Storage::Synchronization::ExportedTypes &exportedTypes,
AliasPropertyDeclarations &relinkableAliasPropertyDeclarations,
PropertyDeclarations &relinkablePropertyDeclarations,
Prototypes &relinkablePrototypes,
- Prototypes &relinkableExtensions)
- {
- NanotraceHR::Tracer tracer{"synchronize exported types"_t, projectStorageCategory()};
-
- std::sort(exportedTypes.begin(), exportedTypes.end(), [](auto &&first, auto &&second) {
- if (first.moduleId < second.moduleId)
- return true;
- else if (first.moduleId > second.moduleId)
- return false;
-
- auto nameCompare = Sqlite::compare(first.name, second.name);
-
- if (nameCompare < 0)
- return true;
- else if (nameCompare > 0)
- return false;
-
- return first.version < second.version;
- });
-
- auto range = selectExportedTypesForSourceIdsStatement
- .template range<Storage::Synchronization::ExportedTypeView>(
- toIntegers(updatedTypeIds));
-
- auto compareKey = [](const Storage::Synchronization::ExportedTypeView &view,
- const Storage::Synchronization::ExportedType &type) -> long long {
- auto moduleIdDifference = view.moduleId - type.moduleId;
- if (moduleIdDifference != 0)
- return moduleIdDifference;
-
- auto nameDifference = Sqlite::compare(view.name, type.name);
- if (nameDifference != 0)
- return nameDifference;
-
- auto versionDifference = view.version.major.value - type.version.major.value;
- if (versionDifference != 0)
- return versionDifference;
-
- return view.version.minor.value - type.version.minor.value;
- };
-
- auto insert = [&](const Storage::Synchronization::ExportedType &type) {
- if (!type.moduleId)
- throw QmlDesigner::ModuleDoesNotExists{};
-
- try {
- if (type.version) {
- insertExportedTypeNamesWithVersionStatement.write(type.moduleId,
- type.name,
- type.version.major.value,
- type.version.minor.value,
- type.typeId);
-
- } else if (type.version.major) {
- insertExportedTypeNamesWithMajorVersionStatement.write(type.moduleId,
- type.name,
- type.version.major.value,
- type.typeId);
- } else {
- insertExportedTypeNamesWithoutVersionStatement.write(type.moduleId,
- type.name,
- type.typeId);
- }
- } catch (const Sqlite::ConstraintPreventsModification &) {
- throw QmlDesigner::ExportedTypeCannotBeInserted{type.name};
- }
- };
-
- auto update = [&](const Storage::Synchronization::ExportedTypeView &view,
- const Storage::Synchronization::ExportedType &type) {
- if (view.typeId != type.typeId) {
- handlePropertyDeclarationWithPropertyType(view.typeId, relinkablePropertyDeclarations);
- handleAliasPropertyDeclarationsWithPropertyType(view.typeId,
- relinkableAliasPropertyDeclarations);
- handlePrototypes(view.typeId, relinkablePrototypes);
- handleExtensions(view.typeId, relinkableExtensions);
- updateExportedTypeNameTypeIdStatement.write(view.exportedTypeNameId, type.typeId);
- return Sqlite::UpdateChange::Update;
- }
- return Sqlite::UpdateChange::No;
- };
-
- auto remove = [&](const Storage::Synchronization::ExportedTypeView &view) {
- handlePropertyDeclarationWithPropertyType(view.typeId, relinkablePropertyDeclarations);
- handleAliasPropertyDeclarationsWithPropertyType(view.typeId,
- relinkableAliasPropertyDeclarations);
- handlePrototypes(view.typeId, relinkablePrototypes);
- handleExtensions(view.typeId, relinkableExtensions);
- deleteExportedTypeNameStatement.write(view.exportedTypeNameId);
- };
-
- Sqlite::insertUpdateDelete(range, exportedTypes, compareKey, insert, update, remove);
- }
+ Prototypes &relinkableExtensions);
void synchronizePropertyDeclarationsInsertAlias(
AliasPropertyDeclarations &insertedAliasPropertyDeclarations,
const Storage::Synchronization::PropertyDeclaration &value,
SourceId sourceId,
- TypeId typeId)
- {
- auto callback = [&](PropertyDeclarationId propertyDeclarationId) {
- insertedAliasPropertyDeclarations.emplace_back(typeId,
- propertyDeclarationId,
- fetchImportedTypeNameId(value.typeName,
- sourceId),
- value.aliasPropertyName,
- value.aliasPropertyNameTail);
- return Sqlite::CallbackControl::Abort;
- };
-
- insertAliasPropertyDeclarationStatement.readCallback(callback, typeId, value.name);
- }
+ TypeId typeId);
+
+ QVarLengthArray<PropertyDeclarationId, 128> fetchPropertyDeclarationIds(TypeId baseTypeId) const;
+
+ PropertyDeclarationId fetchNextPropertyDeclarationId(TypeId baseTypeId,
+ Utils::SmallStringView propertyName) const;
+
+ PropertyDeclarationId fetchPropertyDeclarationId(TypeId typeId,
+ Utils::SmallStringView propertyName) const;
+
+ PropertyDeclarationId fetchNextDefaultPropertyDeclarationId(TypeId baseTypeId) const;
+
+ PropertyDeclarationId fetchDefaultPropertyDeclarationId(TypeId typeId) const;
void synchronizePropertyDeclarationsInsertProperty(
- const Storage::Synchronization::PropertyDeclaration &value, SourceId sourceId, TypeId typeId)
- {
- auto propertyImportedTypeNameId = fetchImportedTypeNameId(value.typeName, sourceId);
- auto propertyTypeId = fetchTypeId(propertyImportedTypeNameId);
-
- if (!propertyTypeId)
- throw TypeNameDoesNotExists{fetchImportedTypeName(propertyImportedTypeNameId)};
-
- auto propertyDeclarationId = insertPropertyDeclarationStatement.template value<PropertyDeclarationId>(
- typeId, value.name, propertyTypeId, value.traits, propertyImportedTypeNameId);
-
- auto nextPropertyDeclarationId = selectPropertyDeclarationIdPrototypeChainDownStatement
- .template value<PropertyDeclarationId>(typeId,
- value.name);
- if (nextPropertyDeclarationId) {
- updateAliasIdPropertyDeclarationStatement.write(nextPropertyDeclarationId,
- propertyDeclarationId);
- updatePropertyAliasDeclarationRecursivelyWithTypeAndTraitsStatement
- .write(propertyDeclarationId, propertyTypeId, value.traits);
- }
- }
+ const Storage::Synchronization::PropertyDeclaration &value, SourceId sourceId, TypeId typeId);
void synchronizePropertyDeclarationsUpdateAlias(
AliasPropertyDeclarations &updatedAliasPropertyDeclarations,
const Storage::Synchronization::PropertyDeclarationView &view,
const Storage::Synchronization::PropertyDeclaration &value,
- SourceId sourceId)
- {
- auto last = updatedAliasPropertyDeclarations.emplace_back(view.typeId,
- view.id,
- fetchImportedTypeNameId(value.typeName,
- sourceId),
- value.aliasPropertyName,
- value.aliasPropertyNameTail,
- view.aliasId);
- }
+ SourceId sourceId);
- auto synchronizePropertyDeclarationsUpdateProperty(
+ Sqlite::UpdateChange synchronizePropertyDeclarationsUpdateProperty(
const Storage::Synchronization::PropertyDeclarationView &view,
const Storage::Synchronization::PropertyDeclaration &value,
SourceId sourceId,
- PropertyDeclarationIds &propertyDeclarationIds)
- {
- auto propertyImportedTypeNameId = fetchImportedTypeNameId(value.typeName, sourceId);
-
- auto propertyTypeId = fetchTypeId(propertyImportedTypeNameId);
-
- if (!propertyTypeId)
- throw TypeNameDoesNotExists{fetchImportedTypeName(propertyImportedTypeNameId)};
-
- if (view.traits == value.traits && propertyTypeId == view.typeId
- && propertyImportedTypeNameId == view.typeNameId)
- return Sqlite::UpdateChange::No;
-
- updatePropertyDeclarationStatement.write(view.id,
- propertyTypeId,
- value.traits,
- propertyImportedTypeNameId);
- updatePropertyAliasDeclarationRecursivelyWithTypeAndTraitsStatement.write(view.id,
- propertyTypeId,
- value.traits);
- propertyDeclarationIds.push_back(view.id);
- return Sqlite::UpdateChange::Update;
- }
+ PropertyDeclarationIds &propertyDeclarationIds);
void synchronizePropertyDeclarations(
TypeId typeId,
@@ -1801,270 +706,78 @@ private:
SourceId sourceId,
AliasPropertyDeclarations &insertedAliasPropertyDeclarations,
AliasPropertyDeclarations &updatedAliasPropertyDeclarations,
- PropertyDeclarationIds &propertyDeclarationIds)
- {
- NanotraceHR::Tracer tracer{"synchronize property declaration"_t, projectStorageCategory()};
-
- std::sort(propertyDeclarations.begin(),
- propertyDeclarations.end(),
- [](auto &&first, auto &&second) {
- return Sqlite::compare(first.name, second.name) < 0;
- });
-
- auto range = selectPropertyDeclarationsForTypeIdStatement
- .template range<Storage::Synchronization::PropertyDeclarationView>(typeId);
-
- auto compareKey = [](const Storage::Synchronization::PropertyDeclarationView &view,
- const Storage::Synchronization::PropertyDeclaration &value) {
- return Sqlite::compare(view.name, value.name);
- };
-
- auto insert = [&](const Storage::Synchronization::PropertyDeclaration &value) {
- if (value.kind == Storage::Synchronization::PropertyKind::Alias) {
- synchronizePropertyDeclarationsInsertAlias(insertedAliasPropertyDeclarations,
- value,
- sourceId,
- typeId);
- } else {
- synchronizePropertyDeclarationsInsertProperty(value, sourceId, typeId);
- }
- };
-
- auto update = [&](const Storage::Synchronization::PropertyDeclarationView &view,
- const Storage::Synchronization::PropertyDeclaration &value) {
- if (value.kind == Storage::Synchronization::PropertyKind::Alias) {
- synchronizePropertyDeclarationsUpdateAlias(updatedAliasPropertyDeclarations,
- view,
- value,
- sourceId);
- propertyDeclarationIds.push_back(view.id);
- } else {
- return synchronizePropertyDeclarationsUpdateProperty(view,
- value,
- sourceId,
- propertyDeclarationIds);
- }
-
- return Sqlite::UpdateChange::No;
- };
-
- auto remove = [&](const Storage::Synchronization::PropertyDeclarationView &view) {
- auto nextPropertyDeclarationId = selectPropertyDeclarationIdPrototypeChainDownStatement
- .template value<PropertyDeclarationId>(typeId,
- view.name);
- if (nextPropertyDeclarationId) {
- updateAliasPropertyDeclarationByAliasPropertyDeclarationIdStatement
- .write(nextPropertyDeclarationId, view.id);
- }
-
- updateDefaultPropertyIdToNullStatement.write(view.id);
- deletePropertyDeclarationStatement.write(view.id);
- propertyDeclarationIds.push_back(view.id);
- };
-
- Sqlite::insertUpdateDelete(range, propertyDeclarations, compareKey, insert, update, remove);
- }
+ PropertyDeclarationIds &propertyDeclarationIds);
- void resetRemovedAliasPropertyDeclarationsToNull(Storage::Synchronization::Type &type,
- PropertyDeclarationIds &propertyDeclarationIds)
+ class AliasPropertyDeclarationView
{
- if (type.changeLevel == Storage::Synchronization::ChangeLevel::Minimal)
- return;
-
- Storage::Synchronization::PropertyDeclarations &aliasDeclarations = type.propertyDeclarations;
+ public:
+ explicit AliasPropertyDeclarationView(Utils::SmallStringView name,
+ PropertyDeclarationId id,
+ PropertyDeclarationId aliasId)
+ : name{name}
+ , id{id}
+ , aliasId{aliasId}
+ {}
- class AliasPropertyDeclarationView
+ template<typename String>
+ friend void convertToString(String &string,
+ const AliasPropertyDeclarationView &aliasPropertyDeclarationView)
{
- public:
- explicit AliasPropertyDeclarationView(Utils::SmallStringView name,
- PropertyDeclarationId id,
- PropertyDeclarationId aliasId)
- : name{name}
- , id{id}
- , aliasId{aliasId}
- {}
-
- public:
- Utils::SmallStringView name;
- PropertyDeclarationId id;
- PropertyDeclarationId aliasId;
- };
-
- std::sort(aliasDeclarations.begin(), aliasDeclarations.end(), [](auto &&first, auto &&second) {
- return Sqlite::compare(first.name, second.name) < 0;
- });
-
- auto range = selectPropertyDeclarationsWithAliasForTypeIdStatement
- .template range<AliasPropertyDeclarationView>(type.typeId);
-
- auto compareKey = [](const AliasPropertyDeclarationView &view,
- const Storage::Synchronization::PropertyDeclaration &value) {
- return Sqlite::compare(view.name, value.name);
- };
-
- auto insert = [&](const Storage::Synchronization::PropertyDeclaration &) {};
-
- auto update = [&](const AliasPropertyDeclarationView &,
- const Storage::Synchronization::PropertyDeclaration &) {
- return Sqlite::UpdateChange::No;
- };
-
- auto remove = [&](const AliasPropertyDeclarationView &view) {
- updatePropertyDeclarationAliasIdToNullStatement.write(view.id);
- propertyDeclarationIds.push_back(view.id);
- };
-
- Sqlite::insertUpdateDelete(range, aliasDeclarations, compareKey, insert, update, remove);
- }
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("name", aliasPropertyDeclarationView.name),
+ keyValue("id", aliasPropertyDeclarationView.id),
+ keyValue("alias id", aliasPropertyDeclarationView.aliasId));
- void resetRemovedAliasPropertyDeclarationsToNull(
- Storage::Synchronization::Types &types,
- AliasPropertyDeclarations &relinkableAliasPropertyDeclarations)
- {
- NanotraceHR::Tracer tracer{"reset removed alias properties to null"_t,
- projectStorageCategory()};
+ convertToString(string, dict);
+ }
- PropertyDeclarationIds propertyDeclarationIds;
- propertyDeclarationIds.reserve(types.size());
+ public:
+ Utils::SmallStringView name;
+ PropertyDeclarationId id;
+ PropertyDeclarationId aliasId;
+ };
- for (auto &&type : types)
- resetRemovedAliasPropertyDeclarationsToNull(type, propertyDeclarationIds);
+ void resetRemovedAliasPropertyDeclarationsToNull(Storage::Synchronization::Type &type,
+ PropertyDeclarationIds &propertyDeclarationIds);
- removeRelinkableEntries(relinkableAliasPropertyDeclarations,
- propertyDeclarationIds,
- PropertyCompare<AliasPropertyDeclaration>{});
- }
+ void resetRemovedAliasPropertyDeclarationsToNull(
+ Storage::Synchronization::Types &types,
+ AliasPropertyDeclarations &relinkableAliasPropertyDeclarations);
+
+ void handlePrototypesWithSourceIdAndPrototypeId(SourceId sourceId,
+ TypeId prototypeId,
+ Prototypes &relinkablePrototypes);
+ void handlePrototypesAndExtensionsWithSourceId(SourceId sourceId,
+ TypeId prototypeId,
+ TypeId extensionId,
+ Prototypes &relinkablePrototypes,
+ Prototypes &relinkableExtensions);
+ void handleExtensionsWithSourceIdAndExtensionId(SourceId sourceId,
+ TypeId extensionId,
+ Prototypes &relinkableExtensions);
ImportId insertDocumentImport(const Storage::Import &import,
Storage::Synchronization::ImportKind importKind,
ModuleId sourceModuleId,
- ImportId parentImportId)
- {
- if (import.version.minor) {
- return insertDocumentImportWithVersionStatement
- .template value<ImportId>(import.sourceId,
- import.moduleId,
- sourceModuleId,
- importKind,
- import.version.major.value,
- import.version.minor.value,
- parentImportId);
- } else if (import.version.major) {
- return insertDocumentImportWithMajorVersionStatement
- .template value<ImportId>(import.sourceId,
- import.moduleId,
- sourceModuleId,
- importKind,
- import.version.major.value,
- parentImportId);
- } else {
- return insertDocumentImportWithoutVersionStatement.template value<ImportId>(
- import.sourceId, import.moduleId, sourceModuleId, importKind, parentImportId);
- }
- }
+ ImportId parentImportId,
+ Relink forceRelink,
+ Prototypes &relinkablePrototypes,
+ Prototypes &relinkableExtensions);
void synchronizeDocumentImports(Storage::Imports &imports,
const SourceIds &updatedSourceIds,
- Storage::Synchronization::ImportKind importKind)
- {
- std::sort(imports.begin(), imports.end(), [](auto &&first, auto &&second) {
- return std::tie(first.sourceId, first.moduleId, first.version)
- < std::tie(second.sourceId, second.moduleId, second.version);
- });
-
- auto range = selectDocumentImportForSourceIdStatement
- .template range<Storage::Synchronization::ImportView>(toIntegers(
- updatedSourceIds),
- importKind);
-
- auto compareKey = [](const Storage::Synchronization::ImportView &view,
- const Storage::Import &import) -> long long {
- auto sourceIdDifference = view.sourceId - import.sourceId;
- if (sourceIdDifference != 0)
- return sourceIdDifference;
-
- auto moduleIdDifference = view.moduleId - import.moduleId;
- if (moduleIdDifference != 0)
- return moduleIdDifference;
-
- auto versionDifference = view.version.major.value - import.version.major.value;
- if (versionDifference != 0)
- return versionDifference;
-
- return view.version.minor.value - import.version.minor.value;
- };
-
- auto insert = [&](const Storage::Import &import) {
- auto importId = insertDocumentImport(import, importKind, import.moduleId, ImportId{});
- auto callback = [&](ModuleId exportedModuleId, int majorVersion, int minorVersion) {
- Storage::Import additionImport{exportedModuleId,
- Storage::Version{majorVersion, minorVersion},
- import.sourceId};
-
- auto exportedImportKind = importKind == Storage::Synchronization::ImportKind::Import
- ? Storage::Synchronization::ImportKind::ModuleExportedImport
- : Storage::Synchronization::ImportKind::ModuleExportedModuleDependency;
-
- insertDocumentImport(additionImport, exportedImportKind, import.moduleId, importId);
- };
-
- selectModuleExportedImportsForModuleIdStatement.readCallback(callback,
- import.moduleId,
- import.version.major.value,
- import.version.minor.value);
- };
-
- auto update = [](const Storage::Synchronization::ImportView &, const Storage::Import &) {
- return Sqlite::UpdateChange::No;
- };
-
- auto remove = [&](const Storage::Synchronization::ImportView &view) {
- deleteDocumentImportStatement.write(view.importId);
- deleteDocumentImportsWithParentImportIdStatement.write(view.sourceId, view.importId);
- };
-
- Sqlite::insertUpdateDelete(range, imports, compareKey, insert, update, remove);
- }
-
- static Utils::PathString createJson(const Storage::Synchronization::ParameterDeclarations &parameters)
- {
- Utils::PathString json;
- json.append("[");
-
- Utils::SmallStringView comma{""};
-
- for (const auto &parameter : parameters) {
- json.append(comma);
- comma = ",";
- json.append(R"({"n":")");
- json.append(parameter.name);
- json.append(R"(","tn":")");
- json.append(parameter.typeName);
- if (parameter.traits == Storage::PropertyDeclarationTraits::None) {
- json.append("\"}");
- } else {
- json.append(R"(","tr":)");
- json.append(Utils::SmallString::number(to_underlying(parameter.traits)));
- json.append("}");
- }
- }
+ Storage::Synchronization::ImportKind importKind,
+ Relink forceRelink,
+ Prototypes &relinkablePrototypes,
+ Prototypes &relinkableExtensions);
- json.append("]");
-
- return json;
- }
+ static Utils::PathString createJson(const Storage::Synchronization::ParameterDeclarations &parameters);
TypeId fetchTypeIdByModuleIdAndExportedName(ModuleId moduleId,
- Utils::SmallStringView name) const override
- {
- return selectTypeIdByModuleIdAndExportedNameStatement.template value<TypeId>(moduleId, name);
- }
+ Utils::SmallStringView name) const override;
- void addTypeIdToPropertyEditorQmlPaths(Storage::Synchronization::PropertyEditorQmlPaths &paths)
- {
- for (auto &path : paths)
- path.typeId = fetchTypeIdByModuleIdAndExportedName(path.moduleId, path.typeName);
- }
+ void addTypeIdToPropertyEditorQmlPaths(Storage::Synchronization::PropertyEditorQmlPaths &paths);
class PropertyEditorQmlPathView
{
@@ -2075,6 +788,19 @@ private:
, directoryId{directoryId}
{}
+ template<typename String>
+ friend void convertToString(String &string,
+ const PropertyEditorQmlPathView &propertyEditorQmlPathView)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("type id", propertyEditorQmlPathView.typeId),
+ keyValue("source id", propertyEditorQmlPathView.pathId),
+ keyValue("directory id", propertyEditorQmlPathView.directoryId));
+
+ convertToString(string, dict);
+ }
+
public:
TypeId typeId;
SourceId pathId;
@@ -2082,279 +808,33 @@ private:
};
void synchronizePropertyEditorPaths(Storage::Synchronization::PropertyEditorQmlPaths &paths,
- SourceIds updatedPropertyEditorQmlPathsSourceIds)
- {
- using Storage::Synchronization::PropertyEditorQmlPath;
- std::sort(paths.begin(), paths.end(), [](auto &&first, auto &&second) {
- return first.typeId < second.typeId;
- });
-
- auto range = selectPropertyEditorPathsForForSourceIdsStatement
- .template range<PropertyEditorQmlPathView>(
- toIntegers(updatedPropertyEditorQmlPathsSourceIds));
-
- auto compareKey = [](const PropertyEditorQmlPathView &view,
- const PropertyEditorQmlPath &value) -> long long {
- return view.typeId - value.typeId;
- };
-
- auto insert = [&](const PropertyEditorQmlPath &path) {
- if (path.typeId)
- insertPropertyEditorPathStatement.write(path.typeId, path.pathId, path.directoryId);
- };
-
- auto update = [&](const PropertyEditorQmlPathView &view, const PropertyEditorQmlPath &value) {
- if (value.pathId != view.pathId || value.directoryId != view.directoryId) {
- updatePropertyEditorPathsStatement.write(value.typeId, value.pathId, value.directoryId);
- return Sqlite::UpdateChange::Update;
- }
- return Sqlite::UpdateChange::No;
- };
-
- auto remove = [&](const PropertyEditorQmlPathView &view) {
- deletePropertyEditorPathStatement.write(view.typeId);
- };
-
- Sqlite::insertUpdateDelete(range, paths, compareKey, insert, update, remove);
- }
+ SourceIds updatedPropertyEditorQmlPathsSourceIds);
void synchronizePropertyEditorQmlPaths(Storage::Synchronization::PropertyEditorQmlPaths &paths,
- SourceIds updatedPropertyEditorQmlPathsSourceIds)
- {
- NanotraceHR::Tracer tracer{"synchronize property editor qml paths"_t,
- projectStorageCategory()};
-
- addTypeIdToPropertyEditorQmlPaths(paths);
- synchronizePropertyEditorPaths(paths, updatedPropertyEditorQmlPathsSourceIds);
- }
+ SourceIds updatedPropertyEditorQmlPathsSourceIds);
void synchronizeFunctionDeclarations(
- TypeId typeId, Storage::Synchronization::FunctionDeclarations &functionsDeclarations)
- {
- NanotraceHR::Tracer tracer{"synchronize function declaration"_t, projectStorageCategory()};
-
- std::sort(functionsDeclarations.begin(),
- functionsDeclarations.end(),
- [](auto &&first, auto &&second) {
- auto compare = Sqlite::compare(first.name, second.name);
-
- if (compare == 0) {
- Utils::PathString firstSignature{createJson(first.parameters)};
- Utils::PathString secondSignature{createJson(second.parameters)};
-
- return Sqlite::compare(firstSignature, secondSignature) < 0;
- }
-
- return compare < 0;
- });
-
- auto range = selectFunctionDeclarationsForTypeIdStatement
- .template range<Storage::Synchronization::FunctionDeclarationView>(typeId);
-
- auto compareKey = [](const Storage::Synchronization::FunctionDeclarationView &view,
- const Storage::Synchronization::FunctionDeclaration &value) {
- auto nameKey = Sqlite::compare(view.name, value.name);
- if (nameKey != 0)
- return nameKey;
-
- Utils::PathString valueSignature{createJson(value.parameters)};
-
- return Sqlite::compare(view.signature, valueSignature);
- };
-
- auto insert = [&](const Storage::Synchronization::FunctionDeclaration &value) {
- Utils::PathString signature{createJson(value.parameters)};
-
- insertFunctionDeclarationStatement.write(typeId, value.name, value.returnTypeName, signature);
- };
-
- auto update = [&](const Storage::Synchronization::FunctionDeclarationView &view,
- const Storage::Synchronization::FunctionDeclaration &value) {
- Utils::PathString signature{createJson(value.parameters)};
-
- if (value.returnTypeName == view.returnTypeName)
- return Sqlite::UpdateChange::No;
-
- updateFunctionDeclarationStatement.write(view.id, value.returnTypeName);
-
- return Sqlite::UpdateChange::Update;
- };
-
- auto remove = [&](const Storage::Synchronization::FunctionDeclarationView &view) {
- deleteFunctionDeclarationStatement.write(view.id);
- };
-
- Sqlite::insertUpdateDelete(range, functionsDeclarations, compareKey, insert, update, remove);
- }
+ TypeId typeId, Storage::Synchronization::FunctionDeclarations &functionsDeclarations);
void synchronizeSignalDeclarations(TypeId typeId,
- Storage::Synchronization::SignalDeclarations &signalDeclarations)
- {
- NanotraceHR::Tracer tracer{"synchronize signal declaration"_t, projectStorageCategory()};
-
- std::sort(signalDeclarations.begin(), signalDeclarations.end(), [](auto &&first, auto &&second) {
- auto compare = Sqlite::compare(first.name, second.name);
-
- if (compare == 0) {
- Utils::PathString firstSignature{createJson(first.parameters)};
- Utils::PathString secondSignature{createJson(second.parameters)};
-
- return Sqlite::compare(firstSignature, secondSignature) < 0;
- }
-
- return compare < 0;
- });
-
- auto range = selectSignalDeclarationsForTypeIdStatement
- .template range<Storage::Synchronization::SignalDeclarationView>(typeId);
-
- auto compareKey = [](const Storage::Synchronization::SignalDeclarationView &view,
- const Storage::Synchronization::SignalDeclaration &value) {
- auto nameKey = Sqlite::compare(view.name, value.name);
- if (nameKey != 0)
- return nameKey;
-
- Utils::PathString valueSignature{createJson(value.parameters)};
-
- return Sqlite::compare(view.signature, valueSignature);
- };
-
- auto insert = [&](const Storage::Synchronization::SignalDeclaration &value) {
- Utils::PathString signature{createJson(value.parameters)};
-
- insertSignalDeclarationStatement.write(typeId, value.name, signature);
- };
-
- auto update = [&]([[maybe_unused]] const Storage::Synchronization::SignalDeclarationView &view,
- [[maybe_unused]] const Storage::Synchronization::SignalDeclaration &value) {
- return Sqlite::UpdateChange::No;
- };
-
- auto remove = [&](const Storage::Synchronization::SignalDeclarationView &view) {
- deleteSignalDeclarationStatement.write(view.id);
- };
-
- Sqlite::insertUpdateDelete(range, signalDeclarations, compareKey, insert, update, remove);
- }
+ Storage::Synchronization::SignalDeclarations &signalDeclarations);
static Utils::PathString createJson(
- const Storage::Synchronization::EnumeratorDeclarations &enumeratorDeclarations)
- {
- Utils::PathString json;
- json.append("{");
-
- Utils::SmallStringView comma{"\""};
-
- for (const auto &enumerator : enumeratorDeclarations) {
- json.append(comma);
- comma = ",\"";
- json.append(enumerator.name);
- if (enumerator.hasValue) {
- json.append("\":\"");
- json.append(Utils::SmallString::number(enumerator.value));
- json.append("\"");
- } else {
- json.append("\":null");
- }
- }
-
- json.append("}");
-
- return json;
- }
+ const Storage::Synchronization::EnumeratorDeclarations &enumeratorDeclarations);
void synchronizeEnumerationDeclarations(
- TypeId typeId, Storage::Synchronization::EnumerationDeclarations &enumerationDeclarations)
- {
- NanotraceHR::Tracer tracer{"synchronize enumeation declaration"_t, projectStorageCategory()};
-
- std::sort(enumerationDeclarations.begin(),
- enumerationDeclarations.end(),
- [](auto &&first, auto &&second) {
- return Sqlite::compare(first.name, second.name) < 0;
- });
-
- auto range = selectEnumerationDeclarationsForTypeIdStatement
- .template range<Storage::Synchronization::EnumerationDeclarationView>(typeId);
-
- auto compareKey = [](const Storage::Synchronization::EnumerationDeclarationView &view,
- const Storage::Synchronization::EnumerationDeclaration &value) {
- return Sqlite::compare(view.name, value.name);
- };
-
- auto insert = [&](const Storage::Synchronization::EnumerationDeclaration &value) {
- Utils::PathString signature{createJson(value.enumeratorDeclarations)};
-
- insertEnumerationDeclarationStatement.write(typeId, value.name, signature);
- };
-
- auto update = [&](const Storage::Synchronization::EnumerationDeclarationView &view,
- const Storage::Synchronization::EnumerationDeclaration &value) {
- Utils::PathString enumeratorDeclarations{createJson(value.enumeratorDeclarations)};
-
- if (enumeratorDeclarations == view.enumeratorDeclarations)
- return Sqlite::UpdateChange::No;
-
- updateEnumerationDeclarationStatement.write(view.id, enumeratorDeclarations);
-
- return Sqlite::UpdateChange::Update;
- };
-
- auto remove = [&](const Storage::Synchronization::EnumerationDeclarationView &view) {
- deleteEnumerationDeclarationStatement.write(view.id);
- };
-
- Sqlite::insertUpdateDelete(range, enumerationDeclarations, compareKey, insert, update, remove);
- }
+ TypeId typeId, Storage::Synchronization::EnumerationDeclarations &enumerationDeclarations);
void extractExportedTypes(TypeId typeId,
const Storage::Synchronization::Type &type,
- Storage::Synchronization::ExportedTypes &exportedTypes)
- {
- for (const auto &exportedType : type.exportedTypes)
- exportedTypes.emplace_back(exportedType.name,
- exportedType.version,
- typeId,
- exportedType.moduleId);
- }
-
- TypeId declareType(Storage::Synchronization::Type &type)
- {
- if (type.typeName.isEmpty()) {
- type.typeId = selectTypeIdBySourceIdStatement.template value<TypeId>(type.sourceId);
-
- return type.typeId;
- }
+ Storage::Synchronization::ExportedTypes &exportedTypes);
- type.typeId = insertTypeStatement.template value<TypeId>(type.sourceId, type.typeName);
-
- if (!type.typeId)
- type.typeId = selectTypeIdBySourceIdAndNameStatement.template value<TypeId>(type.sourceId,
- type.typeName);
-
- return type.typeId;
- }
+ TypeId declareType(Storage::Synchronization::Type &type);
void syncDeclarations(Storage::Synchronization::Type &type,
AliasPropertyDeclarations &insertedAliasPropertyDeclarations,
AliasPropertyDeclarations &updatedAliasPropertyDeclarations,
- PropertyDeclarationIds &propertyDeclarationIds)
- {
- NanotraceHR::Tracer tracer{"synchronize declaration per type"_t, projectStorageCategory()};
-
- if (type.changeLevel == Storage::Synchronization::ChangeLevel::Minimal)
- return;
-
- synchronizePropertyDeclarations(type.typeId,
- type.propertyDeclarations,
- type.sourceId,
- insertedAliasPropertyDeclarations,
- updatedAliasPropertyDeclarations,
- propertyDeclarationIds);
- synchronizeFunctionDeclarations(type.typeId, type.functionDeclarations);
- synchronizeSignalDeclarations(type.typeId, type.signalDeclarations);
- synchronizeEnumerationDeclarations(type.typeId, type.enumerationDeclarations);
- }
+ PropertyDeclarationIds &propertyDeclarationIds);
template<typename Relinkable, typename Ids, typename Compare>
void removeRelinkableEntries(std::vector<Relinkable> &relinkables, Ids &ids, Compare compare)
@@ -2381,23 +861,7 @@ private:
void syncDeclarations(Storage::Synchronization::Types &types,
AliasPropertyDeclarations &insertedAliasPropertyDeclarations,
AliasPropertyDeclarations &updatedAliasPropertyDeclarations,
- PropertyDeclarations &relinkablePropertyDeclarations)
- {
- NanotraceHR::Tracer tracer{"synchronize declaration"_t, projectStorageCategory()};
-
- PropertyDeclarationIds propertyDeclarationIds;
- propertyDeclarationIds.reserve(types.size() * 10);
-
- for (auto &&type : types)
- syncDeclarations(type,
- insertedAliasPropertyDeclarations,
- updatedAliasPropertyDeclarations,
- propertyDeclarationIds);
-
- removeRelinkableEntries(relinkablePropertyDeclarations,
- propertyDeclarationIds,
- PropertyCompare<PropertyDeclaration>{});
- }
+ PropertyDeclarations &relinkablePropertyDeclarations);
class TypeWithDefaultPropertyView
{
@@ -2407,240 +871,55 @@ private:
, defaultPropertyId{defaultPropertyId}
{}
+ template<typename String>
+ friend void convertToString(String &string, const TypeWithDefaultPropertyView &view)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("type id", view.typeId),
+ keyValue("property id", view.defaultPropertyId));
+
+ convertToString(string, dict);
+ }
+
TypeId typeId;
PropertyDeclarationId defaultPropertyId;
};
- void syncDefaultProperties(Storage::Synchronization::Types &types)
- {
- NanotraceHR::Tracer tracer{"synchronize default properties"_t, projectStorageCategory()};
-
- auto range = selectTypesWithDefaultPropertyStatement.template range<TypeWithDefaultPropertyView>();
-
- auto compareKey = [](const TypeWithDefaultPropertyView &view,
- const Storage::Synchronization::Type &value) {
- return view.typeId - value.typeId;
- };
-
- auto insert = [&](const Storage::Synchronization::Type &) {
-
- };
-
- auto update = [&](const TypeWithDefaultPropertyView &view,
- const Storage::Synchronization::Type &value) {
- PropertyDeclarationId valueDefaultPropertyId;
- if (value.defaultPropertyName.size())
- valueDefaultPropertyId = fetchPropertyDeclarationByTypeIdAndNameUngarded(
- value.typeId, value.defaultPropertyName)
- .propertyDeclarationId;
+ void syncDefaultProperties(Storage::Synchronization::Types &types);
- if (compareInvalidAreTrue(valueDefaultPropertyId, view.defaultPropertyId))
- return Sqlite::UpdateChange::No;
+ void resetDefaultPropertiesIfChanged(Storage::Synchronization::Types &types);
- updateDefaultPropertyIdStatement.write(value.typeId, valueDefaultPropertyId);
+ void checkForPrototypeChainCycle(TypeId typeId) const;
- return Sqlite::UpdateChange::Update;
- };
-
- auto remove = [&](const TypeWithDefaultPropertyView &) {};
-
- Sqlite::insertUpdateDelete(range, types, compareKey, insert, update, remove);
- }
-
- void resetDefaultPropertiesIfChanged(Storage::Synchronization::Types &types)
- {
- NanotraceHR::Tracer tracer{"reset changed default properties"_t, projectStorageCategory()};
-
- auto range = selectTypesWithDefaultPropertyStatement.template range<TypeWithDefaultPropertyView>();
-
- auto compareKey = [](const TypeWithDefaultPropertyView &view,
- const Storage::Synchronization::Type &value) {
- return view.typeId - value.typeId;
- };
-
- auto insert = [&](const Storage::Synchronization::Type &) {
-
- };
-
- auto update = [&](const TypeWithDefaultPropertyView &view,
- const Storage::Synchronization::Type &value) {
- PropertyDeclarationId valueDefaultPropertyId;
- if (value.defaultPropertyName.size()) {
- auto optionalValueDefaultPropertyId = fetchOptionalPropertyDeclarationByTypeIdAndNameUngarded(
- value.typeId, value.defaultPropertyName);
- if (optionalValueDefaultPropertyId)
- valueDefaultPropertyId = optionalValueDefaultPropertyId->propertyDeclarationId;
- }
-
- if (compareInvalidAreTrue(valueDefaultPropertyId, view.defaultPropertyId))
- return Sqlite::UpdateChange::No;
-
- updateDefaultPropertyIdStatement.write(value.typeId, Sqlite::NullValue{});
-
- return Sqlite::UpdateChange::Update;
- };
-
- auto remove = [&](const TypeWithDefaultPropertyView &) {};
-
- Sqlite::insertUpdateDelete(range, types, compareKey, insert, update, remove);
- }
-
- void checkForPrototypeChainCycle(TypeId typeId) const
- {
- auto callback = [=](TypeId currentTypeId) {
- if (typeId == currentTypeId)
- throw PrototypeChainCycle{};
- };
-
- selectTypeIdsForPrototypeChainIdStatement.readCallback(callback, typeId);
- }
-
- void checkForAliasChainCycle(PropertyDeclarationId propertyDeclarationId) const
- {
- auto callback = [=](PropertyDeclarationId currentPropertyDeclarationId) {
- if (propertyDeclarationId == currentPropertyDeclarationId)
- throw AliasChainCycle{};
- };
-
- selectPropertyDeclarationIdsForAliasChainStatement.readCallback(callback,
- propertyDeclarationId);
- }
+ void checkForAliasChainCycle(PropertyDeclarationId propertyDeclarationId) const;
std::pair<TypeId, ImportedTypeNameId> fetchImportedTypeNameIdAndTypeId(
- const Storage::Synchronization::ImportedTypeName &typeName, SourceId sourceId)
- {
- TypeId typeId;
- ImportedTypeNameId typeNameId;
- if (!std::visit([](auto &&typeName_) -> bool { return typeName_.name.isEmpty(); }, typeName)) {
- typeNameId = fetchImportedTypeNameId(typeName, sourceId);
-
- typeId = fetchTypeId(typeNameId);
-
- if (!typeId)
- throw TypeNameDoesNotExists{fetchImportedTypeName(typeNameId)};
- }
-
- return {typeId, typeNameId};
- }
+ const Storage::Synchronization::ImportedTypeName &typeName, SourceId sourceId);
- void syncPrototypeAndExtension(Storage::Synchronization::Type &type, TypeIds &typeIds)
- {
- if (type.changeLevel == Storage::Synchronization::ChangeLevel::Minimal)
- return;
-
- auto [prototypeId, prototypeTypeNameId] = fetchImportedTypeNameIdAndTypeId(type.prototype,
- type.sourceId);
- auto [extensionId, extensionTypeNameId] = fetchImportedTypeNameIdAndTypeId(type.extension,
- type.sourceId);
-
- updatePrototypeAndExtensionStatement.write(type.typeId,
- prototypeId,
- prototypeTypeNameId,
- extensionId,
- extensionTypeNameId);
-
- if (prototypeId || extensionId)
- checkForPrototypeChainCycle(type.typeId);
-
- typeIds.push_back(type.typeId);
- }
+ void syncPrototypeAndExtension(Storage::Synchronization::Type &type, TypeIds &typeIds);
void syncPrototypesAndExtensions(Storage::Synchronization::Types &types,
Prototypes &relinkablePrototypes,
- Prototypes &relinkableExtensions)
- {
- NanotraceHR::Tracer tracer{"synchronize prototypes"_t, projectStorageCategory()};
-
- TypeIds typeIds;
- typeIds.reserve(types.size());
+ Prototypes &relinkableExtensions);
- for (auto &type : types)
- syncPrototypeAndExtension(type, typeIds);
-
- removeRelinkableEntries(relinkablePrototypes, typeIds, TypeCompare<Prototype>{});
- removeRelinkableEntries(relinkableExtensions, typeIds, TypeCompare<Prototype>{});
- }
-
- ImportId fetchImportId(SourceId sourceId, const Storage::Import &import) const
- {
- if (import.version) {
- return selectImportIdBySourceIdAndModuleIdAndVersionStatement.template value<ImportId>(
- sourceId, import.moduleId, import.version.major.value, import.version.minor.value);
- }
-
- if (import.version.major) {
- return selectImportIdBySourceIdAndModuleIdAndMajorVersionStatement
- .template value<ImportId>(sourceId, import.moduleId, import.version.major.value);
- }
-
- return selectImportIdBySourceIdAndModuleIdStatement.template value<ImportId>(sourceId,
- import.moduleId);
- }
+ ImportId fetchImportId(SourceId sourceId, const Storage::Import &import) const;
ImportedTypeNameId fetchImportedTypeNameId(const Storage::Synchronization::ImportedTypeName &name,
- SourceId sourceId)
- {
- struct Inspect
- {
- auto operator()(const Storage::Synchronization::ImportedType &importedType)
- {
- return storage.fetchImportedTypeNameId(Storage::Synchronization::TypeNameKind::Exported,
- sourceId,
- importedType.name);
- }
-
- auto operator()(const Storage::Synchronization::QualifiedImportedType &importedType)
- {
- ImportId importId = storage.fetchImportId(sourceId, importedType.import);
-
- return storage.fetchImportedTypeNameId(Storage::Synchronization::TypeNameKind::QualifiedExported,
- importId,
- importedType.name);
- }
-
- ProjectStorage &storage;
- SourceId sourceId;
- };
-
- return std::visit(Inspect{*this, sourceId}, name);
- }
+ SourceId sourceId);
template<typename Id>
ImportedTypeNameId fetchImportedTypeNameId(Storage::Synchronization::TypeNameKind kind,
Id id,
- Utils::SmallStringView typeName)
- {
- auto importedTypeNameId = selectImportedTypeNameIdStatement
- .template value<ImportedTypeNameId>(kind, id, typeName);
-
- if (importedTypeNameId)
- return importedTypeNameId;
-
- return insertImportedTypeNameIdStatement.template value<ImportedTypeNameId>(kind, id, typeName);
- }
-
- TypeId fetchTypeId(ImportedTypeNameId typeNameId) const
- {
- auto kind = selectKindFromImportedTypeNamesStatement
- .template value<Storage::Synchronization::TypeNameKind>(typeNameId);
-
- return fetchTypeId(typeNameId, kind);
- }
+ Utils::SmallStringView typeName);
- Utils::SmallString fetchImportedTypeName(ImportedTypeNameId typeNameId) const
- {
- return selectNameFromImportedTypeNamesStatement.template value<Utils::SmallString>(typeNameId);
- }
+ TypeId fetchTypeId(ImportedTypeNameId typeNameId) const;
- TypeId fetchTypeId(ImportedTypeNameId typeNameId, Storage::Synchronization::TypeNameKind kind) const
- {
- if (kind == Storage::Synchronization::TypeNameKind::QualifiedExported) {
- return selectTypeIdForQualifiedImportedTypeNameNamesStatement.template value<TypeId>(
- typeNameId);
- }
+ Utils::SmallString fetchImportedTypeName(ImportedTypeNameId typeNameId) const;
+ SourceId fetchTypeSourceId(TypeId typeId) const;
- return selectTypeIdForImportedTypeNameNamesStatement.template value<TypeId>(typeNameId);
- }
+ TypeId fetchTypeId(ImportedTypeNameId typeNameId,
+ Storage::Synchronization::TypeNameKind kind) const;
class FetchPropertyDeclarationResult
{
@@ -2653,1303 +932,65 @@ private:
, propertyTraits{propertyTraits}
{}
+ template<typename String>
+ friend void convertToString(String &string, const FetchPropertyDeclarationResult &result)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("property type id", result.propertyTypeId),
+ keyValue("property declaration id", result.propertyDeclarationId),
+ keyValue("property traits", result.propertyTraits));
+
+ convertToString(string, dict);
+ }
+
public:
TypeId propertyTypeId;
PropertyDeclarationId propertyDeclarationId;
Storage::PropertyDeclarationTraits propertyTraits;
};
- auto fetchOptionalPropertyDeclarationByTypeIdAndNameUngarded(TypeId typeId,
- Utils::SmallStringView name)
- {
- return selectPropertyDeclarationByTypeIdAndNameStatement
- .template optionalValue<FetchPropertyDeclarationResult>(typeId, name);
- }
+ std::optional<FetchPropertyDeclarationResult> fetchOptionalPropertyDeclarationByTypeIdAndNameUngarded(
+ TypeId typeId, Utils::SmallStringView name);
FetchPropertyDeclarationResult fetchPropertyDeclarationByTypeIdAndNameUngarded(
- TypeId typeId, Utils::SmallStringView name)
- {
- auto propertyDeclaration = fetchOptionalPropertyDeclarationByTypeIdAndNameUngarded(typeId,
- name);
-
- if (propertyDeclaration)
- return *propertyDeclaration;
-
- throw PropertyNameDoesNotExists{};
- }
+ TypeId typeId, Utils::SmallStringView name);
PropertyDeclarationId fetchPropertyDeclarationIdByTypeIdAndNameUngarded(TypeId typeId,
- Utils::SmallStringView name)
- {
- auto propertyDeclarationId = selectPropertyDeclarationIdByTypeIdAndNameStatement
- .template value<PropertyDeclarationId>(typeId, name);
+ Utils::SmallStringView name);
- if (propertyDeclarationId)
- return propertyDeclarationId;
+ SourceContextId readSourceContextId(Utils::SmallStringView sourceContextPath);
- throw PropertyNameDoesNotExists{};
- }
+ SourceContextId writeSourceContextId(Utils::SmallStringView sourceContextPath);
- SourceContextId readSourceContextId(Utils::SmallStringView sourceContextPath)
- {
- return selectSourceContextIdFromSourceContextsBySourceContextPathStatement
- .template value<SourceContextId>(sourceContextPath);
- }
+ SourceId writeSourceId(SourceContextId sourceContextId, Utils::SmallStringView sourceName);
- SourceContextId writeSourceContextId(Utils::SmallStringView sourceContextPath)
- {
- insertIntoSourceContextsStatement.write(sourceContextPath);
+ SourceId readSourceId(SourceContextId sourceContextId, Utils::SmallStringView sourceName);
- return SourceContextId::create(database.lastInsertedRowId());
- }
+ Storage::Synchronization::ExportedTypes fetchExportedTypes(TypeId typeId);
- SourceId writeSourceId(SourceContextId sourceContextId, Utils::SmallStringView sourceName)
- {
- insertIntoSourcesStatement.write(sourceContextId, sourceName);
+ Storage::Synchronization::PropertyDeclarations fetchPropertyDeclarations(TypeId typeId);
- return SourceId::create(database.lastInsertedRowId());
- }
-
- SourceId readSourceId(SourceContextId sourceContextId, Utils::SmallStringView sourceName)
- {
- return selectSourceIdFromSourcesBySourceContextIdAndSourceNameStatement
- .template value<SourceId>(sourceContextId, sourceName);
- }
-
- auto fetchExportedTypes(TypeId typeId)
- {
- return selectExportedTypesByTypeIdStatement
- .template values<Storage::Synchronization::ExportedType, 12>(typeId);
- }
-
- auto fetchPropertyDeclarations(TypeId typeId)
- {
- return selectPropertyDeclarationsByTypeIdStatement
- .template values<Storage::Synchronization::PropertyDeclaration, 24>(typeId);
- }
-
- auto fetchFunctionDeclarations(TypeId typeId)
- {
- Storage::Synchronization::FunctionDeclarations functionDeclarations;
-
- auto callback = [&](Utils::SmallStringView name,
- Utils::SmallStringView returnType,
- FunctionDeclarationId functionDeclarationId) {
- auto &functionDeclaration = functionDeclarations.emplace_back(name, returnType);
- functionDeclaration.parameters = selectFunctionParameterDeclarationsStatement
- .template values<Storage::Synchronization::ParameterDeclaration,
- 8>(functionDeclarationId);
- };
-
- selectFunctionDeclarationsForTypeIdWithoutSignatureStatement.readCallback(callback, typeId);
-
- return functionDeclarations;
- }
-
- auto fetchSignalDeclarations(TypeId typeId)
- {
- Storage::Synchronization::SignalDeclarations signalDeclarations;
-
- auto callback = [&](Utils::SmallStringView name, SignalDeclarationId signalDeclarationId) {
- auto &signalDeclaration = signalDeclarations.emplace_back(name);
- signalDeclaration.parameters = selectSignalParameterDeclarationsStatement
- .template values<Storage::Synchronization::ParameterDeclaration,
- 8>(signalDeclarationId);
- };
-
- selectSignalDeclarationsForTypeIdWithoutSignatureStatement.readCallback(callback, typeId);
-
- return signalDeclarations;
- }
-
- auto fetchEnumerationDeclarations(TypeId typeId)
- {
- Storage::Synchronization::EnumerationDeclarations enumerationDeclarations;
-
- auto callback = [&](Utils::SmallStringView name,
- EnumerationDeclarationId enumerationDeclarationId) {
- enumerationDeclarations.emplace_back(
- name,
- selectEnumeratorDeclarationStatement
- .template values<Storage::Synchronization::EnumeratorDeclaration, 8>(
- enumerationDeclarationId));
- };
-
- selectEnumerationDeclarationsForTypeIdWithoutEnumeratorDeclarationsStatement
- .readCallback(callback, typeId);
-
- return enumerationDeclarations;
- }
-
- class Initializer
- {
- public:
- Initializer(Database &database, bool isInitialized)
- {
- if (!isInitialized) {
- auto moduleIdColumn = createModulesTable(database);
- createSourceContextsTable(database);
- createSourcesTable(database);
- createTypesAndePropertyDeclarationsTables(database, moduleIdColumn);
- createExportedTypeNamesTable(database, moduleIdColumn);
- createImportedTypeNamesTable(database);
- createEnumerationsTable(database);
- createFunctionsTable(database);
- createSignalsTable(database);
- createModuleExportedImportsTable(database, moduleIdColumn);
- createDocumentImportsTable(database, moduleIdColumn);
- createFileStatusesTable(database);
- createProjectDatasTable(database);
- createPropertyEditorPathsTable(database);
- createTypeAnnotionsTable(database);
- }
- database.setIsInitialized(true);
- }
-
- void createSourceContextsTable(Database &database)
- {
- Sqlite::Table table;
- table.setUseIfNotExists(true);
- table.setName("sourceContexts");
- table.addColumn("sourceContextId", Sqlite::ColumnType::Integer, {Sqlite::PrimaryKey{}});
- const Sqlite::Column &sourceContextPathColumn = table.addColumn("sourceContextPath");
-
- table.addUniqueIndex({sourceContextPathColumn});
-
- table.initialize(database);
- }
-
- void createSourcesTable(Database &database)
- {
- Sqlite::StrictTable table;
- table.setUseIfNotExists(true);
- table.setName("sources");
- table.addColumn("sourceId", Sqlite::StrictColumnType::Integer, {Sqlite::PrimaryKey{}});
- const auto &sourceContextIdColumn = table.addColumn(
- "sourceContextId",
- Sqlite::StrictColumnType::Integer,
- {Sqlite::NotNull{},
- Sqlite::ForeignKey{"sourceContexts",
- "sourceContextId",
- Sqlite::ForeignKeyAction::NoAction,
- Sqlite::ForeignKeyAction::Cascade}});
- const auto &sourceNameColumn = table.addColumn("sourceName",
- Sqlite::StrictColumnType::Text);
- table.addUniqueIndex({sourceContextIdColumn, sourceNameColumn});
-
- table.initialize(database);
- }
-
- void createTypesAndePropertyDeclarationsTables(
- Database &database, [[maybe_unused]] const Sqlite::StrictColumn &foreignModuleIdColumn)
- {
- Sqlite::StrictTable typesTable;
- typesTable.setUseIfNotExists(true);
- typesTable.setName("types");
- typesTable.addColumn("typeId", Sqlite::StrictColumnType::Integer, {Sqlite::PrimaryKey{}});
- auto &sourceIdColumn = typesTable.addColumn("sourceId", Sqlite::StrictColumnType::Integer);
- auto &typesNameColumn = typesTable.addColumn("name", Sqlite::StrictColumnType::Text);
- typesTable.addColumn("traits", Sqlite::StrictColumnType::Integer);
- auto &prototypeIdColumn = typesTable.addForeignKeyColumn("prototypeId",
- typesTable,
- Sqlite::ForeignKeyAction::NoAction,
- Sqlite::ForeignKeyAction::Restrict);
- typesTable.addColumn("prototypeNameId", Sqlite::StrictColumnType::Integer);
- auto &extensionIdColumn = typesTable.addForeignKeyColumn("extensionId",
- typesTable,
- Sqlite::ForeignKeyAction::NoAction,
- Sqlite::ForeignKeyAction::Restrict);
- typesTable.addColumn("extensionNameId", Sqlite::StrictColumnType::Integer);
- auto &defaultPropertyIdColumn = typesTable.addColumn("defaultPropertyId",
- Sqlite::StrictColumnType::Integer);
- typesTable.addColumn("annotationTraits", Sqlite::StrictColumnType::Integer);
- typesTable.addUniqueIndex({sourceIdColumn, typesNameColumn});
- typesTable.addIndex({defaultPropertyIdColumn});
- typesTable.addIndex({prototypeIdColumn});
- typesTable.addIndex({extensionIdColumn});
-
- typesTable.initialize(database);
-
- {
- Sqlite::StrictTable propertyDeclarationTable;
- propertyDeclarationTable.setUseIfNotExists(true);
- propertyDeclarationTable.setName("propertyDeclarations");
- propertyDeclarationTable.addColumn("propertyDeclarationId",
- Sqlite::StrictColumnType::Integer,
- {Sqlite::PrimaryKey{}});
- auto &typeIdColumn = propertyDeclarationTable.addColumn("typeId");
- auto &nameColumn = propertyDeclarationTable.addColumn("name");
- propertyDeclarationTable.addForeignKeyColumn("propertyTypeId",
- typesTable,
- Sqlite::ForeignKeyAction::NoAction,
- Sqlite::ForeignKeyAction::Restrict);
- propertyDeclarationTable.addColumn("propertyTraits",
- Sqlite::StrictColumnType::Integer);
- propertyDeclarationTable.addColumn("propertyImportedTypeNameId",
- Sqlite::StrictColumnType::Integer);
- auto &aliasPropertyDeclarationIdColumn = propertyDeclarationTable.addForeignKeyColumn(
- "aliasPropertyDeclarationId",
- propertyDeclarationTable,
- Sqlite::ForeignKeyAction::NoAction,
- Sqlite::ForeignKeyAction::Restrict);
- auto &aliasPropertyDeclarationTailIdColumn = propertyDeclarationTable.addForeignKeyColumn(
- "aliasPropertyDeclarationTailId",
- propertyDeclarationTable,
- Sqlite::ForeignKeyAction::NoAction,
- Sqlite::ForeignKeyAction::Restrict);
-
- propertyDeclarationTable.addUniqueIndex({typeIdColumn, nameColumn});
- propertyDeclarationTable.addIndex({aliasPropertyDeclarationIdColumn},
- "aliasPropertyDeclarationId IS NOT NULL");
- propertyDeclarationTable.addIndex({aliasPropertyDeclarationTailIdColumn},
- "aliasPropertyDeclarationTailId IS NOT NULL");
-
- propertyDeclarationTable.initialize(database);
- }
- }
-
- void createExportedTypeNamesTable(Database &database,
- const Sqlite::StrictColumn &foreignModuleIdColumn)
- {
- Sqlite::StrictTable table;
- table.setUseIfNotExists(true);
- table.setName("exportedTypeNames");
- table.addColumn("exportedTypeNameId",
- Sqlite::StrictColumnType::Integer,
- {Sqlite::PrimaryKey{}});
- auto &moduleIdColumn = table.addForeignKeyColumn("moduleId",
- foreignModuleIdColumn,
- Sqlite::ForeignKeyAction::NoAction,
- Sqlite::ForeignKeyAction::NoAction);
- auto &nameColumn = table.addColumn("name", Sqlite::StrictColumnType::Text);
- auto &typeIdColumn = table.addColumn("typeId", Sqlite::StrictColumnType::Integer);
- auto &majorVersionColumn = table.addColumn("majorVersion",
- Sqlite::StrictColumnType::Integer);
- auto &minorVersionColumn = table.addColumn("minorVersion",
- Sqlite::StrictColumnType::Integer);
-
- table.addUniqueIndex({moduleIdColumn, nameColumn},
- "majorVersion IS NULL AND minorVersion IS NULL");
- table.addUniqueIndex({moduleIdColumn, nameColumn, majorVersionColumn},
- "majorVersion IS NOT NULL AND minorVersion IS NULL");
- table.addUniqueIndex({moduleIdColumn, nameColumn, majorVersionColumn, minorVersionColumn},
- "majorVersion IS NOT NULL AND minorVersion IS NOT NULL");
-
- table.addIndex({typeIdColumn});
-
- table.initialize(database);
- }
-
- void createImportedTypeNamesTable(Database &database)
- {
- Sqlite::StrictTable table;
- table.setUseIfNotExists(true);
- table.setName("importedTypeNames");
- table.addColumn("importedTypeNameId",
- Sqlite::StrictColumnType::Integer,
- {Sqlite::PrimaryKey{}});
- auto &importOrSourceIdColumn = table.addColumn("importOrSourceId");
- auto &nameColumn = table.addColumn("name", Sqlite::StrictColumnType::Text);
- auto &kindColumn = table.addColumn("kind", Sqlite::StrictColumnType::Integer);
-
- table.addUniqueIndex({kindColumn, importOrSourceIdColumn, nameColumn});
-
- table.initialize(database);
- }
-
- void createEnumerationsTable(Database &database)
- {
- Sqlite::StrictTable table;
- table.setUseIfNotExists(true);
- table.setName("enumerationDeclarations");
- table.addColumn("enumerationDeclarationId",
- Sqlite::StrictColumnType::Integer,
- {Sqlite::PrimaryKey{}});
- auto &typeIdColumn = table.addColumn("typeId", Sqlite::StrictColumnType::Integer);
- auto &nameColumn = table.addColumn("name", Sqlite::StrictColumnType::Text);
- table.addColumn("enumeratorDeclarations", Sqlite::StrictColumnType::Text);
-
- table.addUniqueIndex({typeIdColumn, nameColumn});
-
- table.initialize(database);
- }
-
- void createFunctionsTable(Database &database)
- {
- Sqlite::StrictTable table;
- table.setUseIfNotExists(true);
- table.setName("functionDeclarations");
- table.addColumn("functionDeclarationId",
- Sqlite::StrictColumnType::Integer,
- {Sqlite::PrimaryKey{}});
- auto &typeIdColumn = table.addColumn("typeId", Sqlite::StrictColumnType::Integer);
- auto &nameColumn = table.addColumn("name", Sqlite::StrictColumnType::Text);
- auto &signatureColumn = table.addColumn("signature", Sqlite::StrictColumnType::Text);
- table.addColumn("returnTypeName");
-
- table.addUniqueIndex({typeIdColumn, nameColumn, signatureColumn});
-
- table.initialize(database);
- }
-
- void createSignalsTable(Database &database)
- {
- Sqlite::StrictTable table;
- table.setUseIfNotExists(true);
- table.setName("signalDeclarations");
- table.addColumn("signalDeclarationId",
- Sqlite::StrictColumnType::Integer,
- {Sqlite::PrimaryKey{}});
- auto &typeIdColumn = table.addColumn("typeId", Sqlite::StrictColumnType::Integer);
- auto &nameColumn = table.addColumn("name", Sqlite::StrictColumnType::Text);
- auto &signatureColumn = table.addColumn("signature", Sqlite::StrictColumnType::Text);
-
- table.addUniqueIndex({typeIdColumn, nameColumn, signatureColumn});
-
- table.initialize(database);
- }
-
- Sqlite::StrictColumn createModulesTable(Database &database)
- {
- Sqlite::StrictTable table;
- table.setUseIfNotExists(true);
- table.setName("modules");
- auto &modelIdColumn = table.addColumn("moduleId",
- Sqlite::StrictColumnType::Integer,
- {Sqlite::PrimaryKey{}});
- auto &nameColumn = table.addColumn("name", Sqlite::StrictColumnType::Text);
-
- table.addUniqueIndex({nameColumn});
-
- table.initialize(database);
-
- return std::move(modelIdColumn);
- }
-
- void createModuleExportedImportsTable(Database &database,
- const Sqlite::StrictColumn &foreignModuleIdColumn)
- {
- Sqlite::StrictTable table;
- table.setUseIfNotExists(true);
- table.setName("moduleExportedImports");
- table.addColumn("moduleExportedImportId",
- Sqlite::StrictColumnType::Integer,
- {Sqlite::PrimaryKey{}});
- auto &moduleIdColumn = table.addForeignKeyColumn("moduleId",
- foreignModuleIdColumn,
- Sqlite::ForeignKeyAction::NoAction,
- Sqlite::ForeignKeyAction::Cascade,
- Sqlite::Enforment::Immediate);
- auto &sourceIdColumn = table.addColumn("exportedModuleId",
- Sqlite::StrictColumnType::Integer);
- table.addColumn("isAutoVersion", Sqlite::StrictColumnType::Integer);
- table.addColumn("majorVersion", Sqlite::StrictColumnType::Integer);
- table.addColumn("minorVersion", Sqlite::StrictColumnType::Integer);
-
- table.addUniqueIndex({sourceIdColumn, moduleIdColumn});
-
- table.initialize(database);
- }
-
- void createDocumentImportsTable(Database &database,
- const Sqlite::StrictColumn &foreignModuleIdColumn)
- {
- Sqlite::StrictTable table;
- table.setUseIfNotExists(true);
- table.setName("documentImports");
- table.addColumn("importId", Sqlite::StrictColumnType::Integer, {Sqlite::PrimaryKey{}});
- auto &sourceIdColumn = table.addColumn("sourceId", Sqlite::StrictColumnType::Integer);
- auto &moduleIdColumn = table.addForeignKeyColumn("moduleId",
- foreignModuleIdColumn,
- Sqlite::ForeignKeyAction::NoAction,
- Sqlite::ForeignKeyAction::Cascade,
- Sqlite::Enforment::Immediate);
- auto &sourceModuleIdColumn = table.addForeignKeyColumn("sourceModuleId",
- foreignModuleIdColumn,
- Sqlite::ForeignKeyAction::NoAction,
- Sqlite::ForeignKeyAction::Cascade,
- Sqlite::Enforment::Immediate);
- auto &kindColumn = table.addColumn("kind", Sqlite::StrictColumnType::Integer);
- auto &majorVersionColumn = table.addColumn("majorVersion",
- Sqlite::StrictColumnType::Integer);
- auto &minorVersionColumn = table.addColumn("minorVersion",
- Sqlite::StrictColumnType::Integer);
- auto &parentImportIdColumn = table.addColumn("parentImportId",
- Sqlite::StrictColumnType::Integer);
-
- table.addUniqueIndex({sourceIdColumn,
- moduleIdColumn,
- kindColumn,
- sourceModuleIdColumn,
- parentImportIdColumn},
- "majorVersion IS NULL AND minorVersion IS NULL");
- table.addUniqueIndex({sourceIdColumn,
- moduleIdColumn,
- kindColumn,
- sourceModuleIdColumn,
- majorVersionColumn,
- parentImportIdColumn},
- "majorVersion IS NOT NULL AND minorVersion IS NULL");
- table.addUniqueIndex({sourceIdColumn,
- moduleIdColumn,
- kindColumn,
- sourceModuleIdColumn,
- majorVersionColumn,
- minorVersionColumn,
- parentImportIdColumn},
- "majorVersion IS NOT NULL AND minorVersion IS NOT NULL");
-
- table.initialize(database);
- }
+ Storage::Synchronization::FunctionDeclarations fetchFunctionDeclarations(TypeId typeId);
- void createFileStatusesTable(Database &database)
- {
- Sqlite::StrictTable table;
- table.setUseIfNotExists(true);
- table.setName("fileStatuses");
- table.addColumn("sourceId",
- Sqlite::StrictColumnType::Integer,
- {Sqlite::PrimaryKey{},
- Sqlite::ForeignKey{"sources",
- "sourceId",
- Sqlite::ForeignKeyAction::NoAction,
- Sqlite::ForeignKeyAction::Cascade}});
- table.addColumn("size", Sqlite::StrictColumnType::Integer);
- table.addColumn("lastModified", Sqlite::StrictColumnType::Integer);
-
- table.initialize(database);
- }
+ Storage::Synchronization::SignalDeclarations fetchSignalDeclarations(TypeId typeId);
- void createProjectDatasTable(Database &database)
- {
- Sqlite::StrictTable table;
- table.setUseIfNotExists(true);
- table.setUseWithoutRowId(true);
- table.setName("projectDatas");
- auto &projectSourceIdColumn = table.addColumn("projectSourceId",
- Sqlite::StrictColumnType::Integer);
- auto &sourceIdColumn = table.addColumn("sourceId", Sqlite::StrictColumnType::Integer);
- table.addColumn("moduleId", Sqlite::StrictColumnType::Integer);
- table.addColumn("fileType", Sqlite::StrictColumnType::Integer);
-
- table.addPrimaryKeyContraint({projectSourceIdColumn, sourceIdColumn});
- table.addUniqueIndex({sourceIdColumn});
-
- table.initialize(database);
- }
+ Storage::Synchronization::EnumerationDeclarations fetchEnumerationDeclarations(TypeId typeId);
- void createPropertyEditorPathsTable(Database &database)
- {
- Sqlite::StrictTable table;
- table.setUseIfNotExists(true);
- table.setUseWithoutRowId(true);
- table.setName("propertyEditorPaths");
- table.addColumn("typeId", Sqlite::StrictColumnType::Integer, {Sqlite::PrimaryKey{}});
- table.addColumn("pathSourceId", Sqlite::StrictColumnType::Integer);
- auto &directoryIdColumn = table.addColumn("directoryId",
- Sqlite::StrictColumnType::Integer);
-
- table.addIndex({directoryIdColumn});
-
- table.initialize(database);
- }
+ class Initializer;
- void createTypeAnnotionsTable(Database &database)
- {
- Sqlite::StrictTable table;
- table.setUseIfNotExists(true);
- table.setUseWithoutRowId(true);
- table.setName("typeAnnotations");
- auto &typeIdColumn = table.addColumn("typeId",
- Sqlite::StrictColumnType::Integer,
- {Sqlite::PrimaryKey{}});
- auto &sourceIdColumn = table.addColumn("sourceId", Sqlite::StrictColumnType::Integer);
- table.addColumn("iconPath", Sqlite::StrictColumnType::Text);
- table.addColumn("itemLibrary", Sqlite::StrictColumnType::Text);
- table.addColumn("hints", Sqlite::StrictColumnType::Text);
-
- table.addUniqueIndex({sourceIdColumn, typeIdColumn});
-
- table.initialize(database);
- }
- };
+ struct Statements;
public:
Database &database;
+ ProjectStorageErrorNotifierInterface *errorNotifier = nullptr; // cannot be null
Sqlite::ExclusiveNonThrowingDestructorTransaction<Database> exclusiveTransaction;
- Initializer initializer;
+ std::unique_ptr<Initializer> initializer;
mutable ModuleCache moduleCache{ModuleStorageAdapter{*this}};
- Storage::Info::CommonTypeCache<ProjectStorageInterface> commonTypeCache_{*this};
+ Storage::Info::CommonTypeCache<ProjectStorageType> commonTypeCache_{*this};
QVarLengthArray<ProjectStorageObserver *, 24> observers;
- ReadWriteStatement<1, 2> insertTypeStatement{
- "INSERT OR IGNORE INTO types(sourceId, name) VALUES(?1, ?2) RETURNING typeId", database};
- WriteStatement<5> updatePrototypeAndExtensionStatement{
- "UPDATE types SET prototypeId=?2, prototypeNameId=?3, extensionId=?4, extensionNameId=?5 "
- "WHERE typeId=?1 AND (prototypeId IS NOT ?2 OR extensionId IS NOT ?3 AND prototypeId "
- "IS NOT ?4 OR extensionNameId IS NOT ?5)",
- database};
- mutable ReadStatement<1, 1> selectTypeIdByExportedNameStatement{
- "SELECT typeId FROM exportedTypeNames WHERE name=?1", database};
- mutable ReadStatement<1, 2> selectTypeIdByModuleIdAndExportedNameStatement{
- "SELECT typeId FROM exportedTypeNames "
- "WHERE moduleId=?1 AND name=?2 "
- "ORDER BY majorVersion DESC, minorVersion DESC "
- "LIMIT 1",
- database};
- mutable ReadStatement<1, 3> selectTypeIdByModuleIdAndExportedNameAndMajorVersionStatement{
- "SELECT typeId FROM exportedTypeNames "
- "WHERE moduleId=?1 AND name=?2 AND majorVersion=?3"
- "ORDER BY minorVersion DESC "
- "LIMIT 1",
- database};
- mutable ReadStatement<1, 4> selectTypeIdByModuleIdAndExportedNameAndVersionStatement{
- "SELECT typeId FROM exportedTypeNames "
- "WHERE moduleId=?1 AND name=?2 AND majorVersion=?3 AND minorVersion<=?4"
- "ORDER BY minorVersion DESC "
- "LIMIT 1",
- database};
- mutable ReadStatement<1, 2> selectPrototypeIdStatement{
- "WITH RECURSIVE "
- " all_prototype_and_extension(typeId, prototypeId) AS ("
- " SELECT typeId, prototypeId FROM types WHERE prototypeId IS NOT NULL"
- " UNION ALL "
- " SELECT typeId, extensionId FROM types WHERE extensionId IS NOT NULL),"
- " typeSelection(typeId) AS ("
- " VALUES(?1) "
- " UNION ALL "
- " SELECT prototypeId FROM all_prototype_and_extension JOIN typeSelection "
- " USING(typeId))"
- "SELECT typeId FROM typeSelection WHERE typeId=?2 LIMIT 1",
- database};
- mutable ReadStatement<1, 2> selectPropertyDeclarationIdByTypeIdAndNameStatement{
- "WITH RECURSIVE "
- " all_prototype_and_extension(typeId, prototypeId) AS ("
- " SELECT typeId, prototypeId FROM types WHERE prototypeId IS NOT NULL"
- " UNION ALL "
- " SELECT typeId, extensionId FROM types WHERE extensionId IS NOT NULL),"
- " typeSelection(typeId, level) AS ("
- " VALUES(?1, 0) "
- " UNION ALL "
- " SELECT prototypeId, typeSelection.level+1 FROM all_prototype_and_extension JOIN "
- " typeSelection USING(typeId)) "
- "SELECT propertyDeclarationId FROM propertyDeclarations JOIN typeSelection USING(typeId) "
- " WHERE name=?2 ORDER BY level LIMIT 1",
- database};
- mutable ReadStatement<3, 2> selectPropertyDeclarationByTypeIdAndNameStatement{
- "WITH RECURSIVE "
- " all_prototype_and_extension(typeId, prototypeId) AS ("
- " SELECT typeId, prototypeId FROM types WHERE prototypeId IS NOT NULL"
- " UNION ALL "
- " SELECT typeId, extensionId FROM types WHERE extensionId IS NOT NULL),"
- " typeSelection(typeId, level) AS ("
- " VALUES(?1, 0) "
- " UNION ALL "
- " SELECT prototypeId, typeSelection.level+1 FROM all_prototype_and_extension JOIN "
- " typeSelection USING(typeId))"
- "SELECT propertyTypeId, propertyDeclarationId, propertyTraits "
- " FROM propertyDeclarations JOIN typeSelection USING(typeId) "
- " WHERE name=?2 ORDER BY level LIMIT 1",
- database};
- mutable ReadStatement<1, 1> selectPrototypeIdsInOrderStatement{
- "WITH RECURSIVE "
- " all_prototype_and_extension(typeId, prototypeId) AS ("
- " SELECT typeId, prototypeId FROM types WHERE prototypeId IS NOT NULL"
- " UNION ALL "
- " SELECT typeId, extensionId FROM types WHERE extensionId IS NOT NULL),"
- " typeSelection(typeId, level) AS ("
- " VALUES(?1, 0) "
- " UNION ALL "
- " SELECT prototypeId, typeSelection.level+1 FROM all_prototype_and_extension JOIN "
- " typeSelection USING(typeId) WHERE prototypeId IS NOT NULL) "
- "SELECT typeId FROM typeSelection ORDER BY level DESC",
- database};
- mutable ReadStatement<1, 1> selectSourceContextIdFromSourceContextsBySourceContextPathStatement{
- "SELECT sourceContextId FROM sourceContexts WHERE sourceContextPath = ?", database};
- mutable ReadStatement<1, 1> selectSourceContextPathFromSourceContextsBySourceContextIdStatement{
- "SELECT sourceContextPath FROM sourceContexts WHERE sourceContextId = ?", database};
- mutable ReadStatement<2> selectAllSourceContextsStatement{
- "SELECT sourceContextPath, sourceContextId FROM sourceContexts", database};
- WriteStatement<1> insertIntoSourceContextsStatement{
- "INSERT INTO sourceContexts(sourceContextPath) VALUES (?)", database};
- mutable ReadStatement<1, 2> selectSourceIdFromSourcesBySourceContextIdAndSourceNameStatement{
- "SELECT sourceId FROM sources WHERE sourceContextId = ? AND sourceName = ?", database};
- mutable ReadStatement<2, 1> selectSourceNameAndSourceContextIdFromSourcesBySourceIdStatement{
- "SELECT sourceName, sourceContextId FROM sources WHERE sourceId = ?", database};
- mutable ReadStatement<1, 1> selectSourceContextIdFromSourcesBySourceIdStatement{
- "SELECT sourceContextId FROM sources WHERE sourceId = ?", database};
- WriteStatement<2> insertIntoSourcesStatement{
- "INSERT INTO sources(sourceContextId, sourceName) VALUES (?,?)", database};
- mutable ReadStatement<3> selectAllSourcesStatement{
- "SELECT sourceName, sourceContextId, sourceId FROM sources", database};
- mutable ReadStatement<8, 1> selectTypeByTypeIdStatement{
- "SELECT sourceId, t.name, t.typeId, prototypeId, extensionId, traits, annotationTraits, "
- "pd.name "
- "FROM types AS t LEFT JOIN propertyDeclarations AS pd ON "
- "defaultPropertyId=propertyDeclarationId "
- "WHERE t.typeId=?",
- database};
- mutable ReadStatement<4, 1> selectExportedTypesByTypeIdStatement{
- "SELECT moduleId, name, ifnull(majorVersion, -1), ifnull(minorVersion, -1) FROM "
- "exportedTypeNames WHERE typeId=?",
- database};
- mutable ReadStatement<4, 2> selectExportedTypesByTypeIdAndSourceIdStatement{
- "SELECT etn.moduleId, name, ifnull(etn.majorVersion, -1), ifnull(etn.minorVersion, -1) "
- "FROM exportedTypeNames AS etn JOIN documentImports USING(moduleId) WHERE typeId=?1 AND "
- "sourceId=?2",
- database};
- mutable ReadStatement<8> selectTypesStatement{
- "SELECT sourceId, t.name, t.typeId, prototypeId, extensionId, traits, annotationTraits, "
- "pd.name "
- "FROM types AS t LEFT JOIN propertyDeclarations AS pd ON "
- "defaultPropertyId=propertyDeclarationId",
- database};
- WriteStatement<2> updateTypeTraitStatement{"UPDATE types SET traits = ?2 WHERE typeId=?1",
- database};
- WriteStatement<2> updateTypeAnnotationTraitStatement{
- "UPDATE types SET annotationTraits = ?2 WHERE typeId=?1", database};
- ReadStatement<1, 2> selectNotUpdatedTypesInSourcesStatement{
- "SELECT DISTINCT typeId FROM types WHERE (sourceId IN carray(?1) AND typeId NOT IN "
- "carray(?2))",
- database};
- WriteStatement<1> deleteTypeNamesByTypeIdStatement{
- "DELETE FROM exportedTypeNames WHERE typeId=?", database};
- WriteStatement<1> deleteEnumerationDeclarationByTypeIdStatement{
- "DELETE FROM enumerationDeclarations WHERE typeId=?", database};
- WriteStatement<1> deletePropertyDeclarationByTypeIdStatement{
- "DELETE FROM propertyDeclarations WHERE typeId=?", database};
- WriteStatement<1> deleteFunctionDeclarationByTypeIdStatement{
- "DELETE FROM functionDeclarations WHERE typeId=?", database};
- WriteStatement<1> deleteSignalDeclarationByTypeIdStatement{
- "DELETE FROM signalDeclarations WHERE typeId=?", database};
- WriteStatement<1> deleteTypeStatement{"DELETE FROM types WHERE typeId=?", database};
- mutable ReadStatement<4, 1> selectPropertyDeclarationsByTypeIdStatement{
- "SELECT name, propertyTypeId, propertyTraits, (SELECT name FROM "
- "propertyDeclarations WHERE propertyDeclarationId=pd.aliasPropertyDeclarationId) FROM "
- "propertyDeclarations AS pd WHERE typeId=?",
- database};
- ReadStatement<6, 1> selectPropertyDeclarationsForTypeIdStatement{
- "SELECT name, propertyTraits, propertyTypeId, propertyImportedTypeNameId, "
- "propertyDeclarationId, aliasPropertyDeclarationId FROM propertyDeclarations "
- "WHERE typeId=? ORDER BY name",
- database};
- ReadWriteStatement<1, 5> insertPropertyDeclarationStatement{
- "INSERT INTO propertyDeclarations(typeId, name, propertyTypeId, propertyTraits, "
- "propertyImportedTypeNameId, aliasPropertyDeclarationId) VALUES(?1, ?2, ?3, ?4, ?5, NULL) "
- "RETURNING propertyDeclarationId",
- database};
- WriteStatement<4> updatePropertyDeclarationStatement{
- "UPDATE propertyDeclarations SET propertyTypeId=?2, propertyTraits=?3, "
- "propertyImportedTypeNameId=?4, aliasPropertyDeclarationId=NULL WHERE "
- "propertyDeclarationId=?1",
- database};
- WriteStatement<3> updatePropertyAliasDeclarationRecursivelyWithTypeAndTraitsStatement{
- "WITH RECURSIVE "
- " properties(aliasPropertyDeclarationId) AS ( "
- " SELECT propertyDeclarationId FROM propertyDeclarations WHERE "
- " aliasPropertyDeclarationId=?1 "
- " UNION ALL "
- " SELECT pd.propertyDeclarationId FROM "
- " propertyDeclarations AS pd JOIN properties USING(aliasPropertyDeclarationId)) "
- "UPDATE propertyDeclarations AS pd "
- "SET propertyTypeId=?2, propertyTraits=?3 "
- "FROM properties AS p "
- "WHERE pd.propertyDeclarationId=p.aliasPropertyDeclarationId",
- database};
- WriteStatement<1> updatePropertyAliasDeclarationRecursivelyStatement{
- "WITH RECURSIVE "
- " propertyValues(propertyTypeId, propertyTraits) AS ("
- " SELECT propertyTypeId, propertyTraits FROM propertyDeclarations "
- " WHERE propertyDeclarationId=?1), "
- " properties(aliasPropertyDeclarationId) AS ( "
- " SELECT propertyDeclarationId FROM propertyDeclarations WHERE "
- " aliasPropertyDeclarationId=?1 "
- " UNION ALL "
- " SELECT pd.propertyDeclarationId FROM "
- " propertyDeclarations AS pd JOIN properties USING(aliasPropertyDeclarationId)) "
- "UPDATE propertyDeclarations AS pd "
- "SET propertyTypeId=pv.propertyTypeId, propertyTraits=pv.propertyTraits "
- "FROM properties AS p, propertyValues AS pv "
- "WHERE pd.propertyDeclarationId=p.aliasPropertyDeclarationId",
- database};
- WriteStatement<1> deletePropertyDeclarationStatement{
- "DELETE FROM propertyDeclarations WHERE propertyDeclarationId=?", database};
- ReadStatement<3, 1> selectPropertyDeclarationsWithAliasForTypeIdStatement{
- "SELECT name, propertyDeclarationId, aliasPropertyDeclarationId FROM propertyDeclarations "
- "WHERE typeId=? AND aliasPropertyDeclarationId IS NOT NULL ORDER BY name",
- database};
- WriteStatement<5> updatePropertyDeclarationWithAliasAndTypeStatement{
- "UPDATE propertyDeclarations SET propertyTypeId=?2, propertyTraits=?3, "
- "propertyImportedTypeNameId=?4, aliasPropertyDeclarationId=?5 WHERE "
- "propertyDeclarationId=?1",
- database};
- ReadWriteStatement<1, 2> insertAliasPropertyDeclarationStatement{
- "INSERT INTO propertyDeclarations(typeId, name) VALUES(?1, ?2) RETURNING "
- "propertyDeclarationId",
- database};
- mutable ReadStatement<4, 1> selectFunctionDeclarationsForTypeIdStatement{
- "SELECT name, returnTypeName, signature, functionDeclarationId FROM "
- "functionDeclarations WHERE typeId=? ORDER BY name, signature",
- database};
- mutable ReadStatement<3, 1> selectFunctionDeclarationsForTypeIdWithoutSignatureStatement{
- "SELECT name, returnTypeName, functionDeclarationId FROM "
- "functionDeclarations WHERE typeId=? ORDER BY name",
- database};
- mutable ReadStatement<3, 1> selectFunctionParameterDeclarationsStatement{
- "SELECT json_extract(json_each.value, '$.n'), json_extract(json_each.value, '$.tn'), "
- "json_extract(json_each.value, '$.tr') FROM functionDeclarations, "
- "json_each(functionDeclarations.signature) WHERE functionDeclarationId=?",
- database};
- WriteStatement<4> insertFunctionDeclarationStatement{
- "INSERT INTO functionDeclarations(typeId, name, returnTypeName, signature) VALUES(?1, ?2, "
- "?3, ?4)",
- database};
- WriteStatement<2> updateFunctionDeclarationStatement{
- "UPDATE functionDeclarations SET returnTypeName=?2 WHERE functionDeclarationId=?1", database};
- WriteStatement<1> deleteFunctionDeclarationStatement{
- "DELETE FROM functionDeclarations WHERE functionDeclarationId=?", database};
- mutable ReadStatement<3, 1> selectSignalDeclarationsForTypeIdStatement{
- "SELECT name, signature, signalDeclarationId FROM signalDeclarations WHERE typeId=? ORDER "
- "BY name, signature",
- database};
- mutable ReadStatement<2, 1> selectSignalDeclarationsForTypeIdWithoutSignatureStatement{
- "SELECT name, signalDeclarationId FROM signalDeclarations WHERE typeId=? ORDER BY name",
- database};
- mutable ReadStatement<3, 1> selectSignalParameterDeclarationsStatement{
- "SELECT json_extract(json_each.value, '$.n'), json_extract(json_each.value, '$.tn'), "
- "json_extract(json_each.value, '$.tr') FROM signalDeclarations, "
- "json_each(signalDeclarations.signature) WHERE signalDeclarationId=?",
- database};
- WriteStatement<3> insertSignalDeclarationStatement{
- "INSERT INTO signalDeclarations(typeId, name, signature) VALUES(?1, ?2, ?3)", database};
- WriteStatement<2> updateSignalDeclarationStatement{
- "UPDATE signalDeclarations SET signature=?2 WHERE signalDeclarationId=?1", database};
- WriteStatement<1> deleteSignalDeclarationStatement{
- "DELETE FROM signalDeclarations WHERE signalDeclarationId=?", database};
- mutable ReadStatement<3, 1> selectEnumerationDeclarationsForTypeIdStatement{
- "SELECT name, enumeratorDeclarations, enumerationDeclarationId FROM "
- "enumerationDeclarations WHERE typeId=? ORDER BY name",
- database};
- mutable ReadStatement<2, 1> selectEnumerationDeclarationsForTypeIdWithoutEnumeratorDeclarationsStatement{
- "SELECT name, enumerationDeclarationId FROM enumerationDeclarations WHERE typeId=? ORDER "
- "BY name",
- database};
- mutable ReadStatement<3, 1> selectEnumeratorDeclarationStatement{
- "SELECT json_each.key, json_each.value, json_each.type!='null' FROM "
- "enumerationDeclarations, json_each(enumerationDeclarations.enumeratorDeclarations) WHERE "
- "enumerationDeclarationId=?",
- database};
- WriteStatement<3> insertEnumerationDeclarationStatement{
- "INSERT INTO enumerationDeclarations(typeId, name, enumeratorDeclarations) VALUES(?1, ?2, "
- "?3)",
- database};
- WriteStatement<2> updateEnumerationDeclarationStatement{
- "UPDATE enumerationDeclarations SET enumeratorDeclarations=?2 WHERE "
- "enumerationDeclarationId=?1",
- database};
- WriteStatement<1> deleteEnumerationDeclarationStatement{
- "DELETE FROM enumerationDeclarations WHERE enumerationDeclarationId=?", database};
- mutable ReadStatement<1, 1> selectModuleIdByNameStatement{
- "SELECT moduleId FROM modules WHERE name=? LIMIT 1", database};
- mutable ReadWriteStatement<1, 1> insertModuleNameStatement{
- "INSERT INTO modules(name) VALUES(?1) RETURNING moduleId", database};
- mutable ReadStatement<1, 1> selectModuleNameStatement{
- "SELECT name FROM modules WHERE moduleId =?1", database};
- mutable ReadStatement<2> selectAllModulesStatement{"SELECT name, moduleId FROM modules", database};
- mutable ReadStatement<1, 2> selectTypeIdBySourceIdAndNameStatement{
- "SELECT typeId FROM types WHERE sourceId=?1 and name=?2", database};
- mutable ReadStatement<1, 3> selectTypeIdByModuleIdsAndExportedNameStatement{
- "SELECT typeId FROM exportedTypeNames WHERE moduleId IN carray(?1, ?2, 'int32') AND "
- "name=?3",
- database};
- mutable ReadStatement<4> selectAllDocumentImportForSourceIdStatement{
- "SELECT moduleId, majorVersion, minorVersion, sourceId "
- "FROM documentImports ",
- database};
- mutable ReadStatement<5, 2> selectDocumentImportForSourceIdStatement{
- "SELECT importId, sourceId, moduleId, majorVersion, minorVersion "
- "FROM documentImports WHERE sourceId IN carray(?1) AND kind=?2 ORDER BY sourceId, "
- "moduleId, majorVersion, minorVersion",
- database};
- ReadWriteStatement<1, 5> insertDocumentImportWithoutVersionStatement{
- "INSERT INTO documentImports(sourceId, moduleId, sourceModuleId, kind, "
- "parentImportId) VALUES (?1, ?2, ?3, ?4, ?5) RETURNING importId",
- database};
- ReadWriteStatement<1, 6> insertDocumentImportWithMajorVersionStatement{
- "INSERT INTO documentImports(sourceId, moduleId, sourceModuleId, kind, majorVersion, "
- "parentImportId) VALUES (?1, ?2, ?3, ?4, ?5, ?6) RETURNING importId",
- database};
- ReadWriteStatement<1, 7> insertDocumentImportWithVersionStatement{
- "INSERT INTO documentImports(sourceId, moduleId, sourceModuleId, kind, majorVersion, "
- "minorVersion, parentImportId) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7) RETURNING "
- "importId",
- database};
- WriteStatement<1> deleteDocumentImportStatement{"DELETE FROM documentImports WHERE importId=?1",
- database};
- WriteStatement<2> deleteDocumentImportsWithParentImportIdStatement{
- "DELETE FROM documentImports WHERE sourceId=?1 AND parentImportId=?2", database};
- WriteStatement<1> deleteDocumentImportsWithSourceIdsStatement{
- "DELETE FROM documentImports WHERE sourceId IN carray(?1)", database};
- ReadStatement<1, 2> selectPropertyDeclarationIdPrototypeChainDownStatement{
- "WITH RECURSIVE "
- " all_prototype_and_extension(typeId, prototypeId) AS ("
- " SELECT typeId, prototypeId FROM types WHERE prototypeId IS NOT NULL"
- " UNION ALL "
- " SELECT typeId, extensionId FROM types WHERE extensionId IS NOT NULL),"
- " typeSelection(typeId, level) AS ("
- " SELECT prototypeId, 0 FROM types WHERE typeId=?1 AND prototypeId IS NOT NULL"
- " UNION ALL "
- " SELECT prototypeId, typeSelection.level+1 FROM all_prototype_and_extension JOIN "
- " typeSelection USING(typeId))"
- "SELECT propertyDeclarationId FROM typeSelection JOIN propertyDeclarations "
- " USING(typeId) WHERE name=?2 ORDER BY level LIMIT 1",
- database};
- WriteStatement<2> updateAliasIdPropertyDeclarationStatement{
- "UPDATE propertyDeclarations SET aliasPropertyDeclarationId=?2 WHERE "
- "aliasPropertyDeclarationId=?1",
- database};
- WriteStatement<2> updateAliasPropertyDeclarationByAliasPropertyDeclarationIdStatement{
- "UPDATE propertyDeclarations SET propertyTypeId=new.propertyTypeId, "
- "propertyTraits=new.propertyTraits, aliasPropertyDeclarationId=?1 FROM (SELECT "
- "propertyTypeId, propertyTraits FROM propertyDeclarations WHERE propertyDeclarationId=?1) "
- "AS new WHERE aliasPropertyDeclarationId=?2",
- database};
- WriteStatement<1> updateAliasPropertyDeclarationToNullStatement{
- "UPDATE propertyDeclarations SET aliasPropertyDeclarationId=NULL, propertyTypeId=NULL, "
- "propertyTraits=NULL WHERE propertyDeclarationId=? AND (aliasPropertyDeclarationId IS NOT "
- "NULL OR propertyTypeId IS NOT NULL OR propertyTraits IS NOT NULL)",
- database};
- ReadStatement<5, 1> selectAliasPropertiesDeclarationForPropertiesWithTypeIdStatement{
- "SELECT alias.typeId, alias.propertyDeclarationId, alias.propertyImportedTypeNameId, "
- "alias.aliasPropertyDeclarationId, alias.aliasPropertyDeclarationTailId FROM "
- "propertyDeclarations AS alias JOIN propertyDeclarations AS target ON "
- "alias.aliasPropertyDeclarationId=target.propertyDeclarationId OR "
- "alias.aliasPropertyDeclarationTailId=target.propertyDeclarationId WHERE "
- "alias.propertyTypeId=?1 OR target.typeId=?1 OR alias.propertyImportedTypeNameId IN "
- "(SELECT importedTypeNameId FROM exportedTypeNames JOIN importedTypeNames USING(name) "
- "WHERE typeId=?1)",
- database};
- ReadStatement<3, 1> selectAliasPropertiesDeclarationForPropertiesWithAliasIdStatement{
- "WITH RECURSIVE "
- " properties(propertyDeclarationId, propertyImportedTypeNameId, typeId, "
- " aliasPropertyDeclarationId) AS ("
- " SELECT propertyDeclarationId, propertyImportedTypeNameId, typeId, "
- " aliasPropertyDeclarationId FROM propertyDeclarations WHERE "
- " aliasPropertyDeclarationId=?1"
- " UNION ALL "
- " SELECT pd.propertyDeclarationId, pd.propertyImportedTypeNameId, pd.typeId, "
- " pd.aliasPropertyDeclarationId FROM propertyDeclarations AS pd JOIN properties AS "
- " p ON pd.aliasPropertyDeclarationId=p.propertyDeclarationId)"
- "SELECT propertyDeclarationId, propertyImportedTypeNameId, aliasPropertyDeclarationId "
- " FROM properties",
- database};
- ReadWriteStatement<3, 1> updatesPropertyDeclarationPropertyTypeToNullStatement{
- "UPDATE propertyDeclarations SET propertyTypeId=NULL WHERE propertyTypeId=?1 AND "
- "aliasPropertyDeclarationId IS NULL RETURNING typeId, propertyDeclarationId, "
- "propertyImportedTypeNameId",
- database};
- mutable ReadStatement<1, 1> selectPropertyNameStatement{
- "SELECT name FROM propertyDeclarations WHERE propertyDeclarationId=?", database};
- WriteStatement<2> updatePropertyDeclarationTypeStatement{
- "UPDATE propertyDeclarations SET propertyTypeId=?2 WHERE propertyDeclarationId=?1", database};
- ReadWriteStatement<2, 1> updatePrototypeIdToNullStatement{
- "UPDATE types SET prototypeId=NULL WHERE prototypeId=?1 RETURNING "
- "typeId, prototypeNameId",
- database};
- ReadWriteStatement<2, 1> updateExtensionIdToNullStatement{
- "UPDATE types SET extensionId=NULL WHERE extensionId=?1 RETURNING "
- "typeId, extensionNameId",
- database};
- WriteStatement<2> updateTypePrototypeStatement{
- "UPDATE types SET prototypeId=?2 WHERE typeId=?1", database};
- WriteStatement<2> updateTypeExtensionStatement{
- "UPDATE types SET extensionId=?2 WHERE typeId=?1", database};
- mutable ReadStatement<1, 1> selectTypeIdsForPrototypeChainIdStatement{
- "WITH RECURSIVE "
- " all_prototype_and_extension(typeId, prototypeId) AS ("
- " SELECT typeId, prototypeId FROM types WHERE prototypeId IS NOT NULL"
- " UNION ALL "
- " SELECT typeId, extensionId FROM types WHERE extensionId IS NOT NULL),"
- " prototypes(typeId) AS ("
- " SELECT prototypeId FROM all_prototype_and_extension WHERE typeId=?"
- " UNION ALL "
- " SELECT prototypeId FROM all_prototype_and_extension JOIN "
- " prototypes USING(typeId)) "
- "SELECT typeId FROM prototypes",
- database};
- WriteStatement<3> updatePropertyDeclarationAliasIdAndTypeNameIdStatement{
- "UPDATE propertyDeclarations SET aliasPropertyDeclarationId=?2, "
- "propertyImportedTypeNameId=?3 WHERE propertyDeclarationId=?1 AND "
- "(aliasPropertyDeclarationId IS NOT ?2 OR propertyImportedTypeNameId IS NOT ?3)",
- database};
- WriteStatement<1> updatetPropertiesDeclarationValuesOfAliasStatement{
- "WITH RECURSIVE "
- " properties(propertyDeclarationId, propertyTypeId, propertyTraits) AS ( "
- " SELECT aliasPropertyDeclarationId, propertyTypeId, propertyTraits FROM "
- " propertyDeclarations WHERE propertyDeclarationId=?1 "
- " UNION ALL "
- " SELECT pd.aliasPropertyDeclarationId, pd.propertyTypeId, pd.propertyTraits FROM "
- " propertyDeclarations AS pd JOIN properties USING(propertyDeclarationId)) "
- "UPDATE propertyDeclarations AS pd SET propertyTypeId=p.propertyTypeId, "
- " propertyTraits=p.propertyTraits "
- "FROM properties AS p "
- "WHERE pd.propertyDeclarationId=?1 AND p.propertyDeclarationId IS NULL AND "
- " (pd.propertyTypeId IS NOT p.propertyTypeId OR pd.propertyTraits IS NOT "
- " p.propertyTraits)",
- database};
- WriteStatement<1> updatePropertyDeclarationAliasIdToNullStatement{
- "UPDATE propertyDeclarations SET aliasPropertyDeclarationId=NULL WHERE "
- "propertyDeclarationId=?1",
- database};
- mutable ReadStatement<1, 1> selectPropertyDeclarationIdsForAliasChainStatement{
- "WITH RECURSIVE "
- " properties(propertyDeclarationId) AS ( "
- " SELECT aliasPropertyDeclarationId FROM propertyDeclarations WHERE "
- " propertyDeclarationId=?1 "
- " UNION ALL "
- " SELECT aliasPropertyDeclarationId FROM propertyDeclarations JOIN properties "
- " USING(propertyDeclarationId)) "
- "SELECT propertyDeclarationId FROM properties",
- database};
- mutable ReadStatement<3> selectAllFileStatusesStatement{
- "SELECT sourceId, size, lastModified FROM fileStatuses ORDER BY sourceId", database};
- mutable ReadStatement<3, 1> selectFileStatusesForSourceIdsStatement{
- "SELECT sourceId, size, lastModified FROM fileStatuses WHERE sourceId IN carray(?1) ORDER "
- "BY sourceId",
- database};
- mutable ReadStatement<3, 1> selectFileStatusesForSourceIdStatement{
- "SELECT sourceId, size, lastModified FROM fileStatuses WHERE sourceId=?1 ORDER BY sourceId",
- database};
- WriteStatement<3> insertFileStatusStatement{
- "INSERT INTO fileStatuses(sourceId, size, lastModified) VALUES(?1, ?2, ?3)", database};
- WriteStatement<1> deleteFileStatusStatement{"DELETE FROM fileStatuses WHERE sourceId=?1",
- database};
- WriteStatement<3> updateFileStatusStatement{
- "UPDATE fileStatuses SET size=?2, lastModified=?3 WHERE sourceId=?1", database};
- ReadStatement<1, 1> selectTypeIdBySourceIdStatement{"SELECT typeId FROM types WHERE sourceId=?",
- database};
- mutable ReadStatement<1, 3> selectImportedTypeNameIdStatement{
- "SELECT importedTypeNameId FROM importedTypeNames WHERE kind=?1 AND importOrSourceId=?2 "
- "AND name=?3 LIMIT 1",
- database};
- mutable ReadWriteStatement<1, 3> insertImportedTypeNameIdStatement{
- "INSERT INTO importedTypeNames(kind, importOrSourceId, name) VALUES (?1, ?2, ?3) "
- "RETURNING importedTypeNameId",
- database};
- mutable ReadStatement<1, 2> selectImportIdBySourceIdAndModuleIdStatement{
- "SELECT importId FROM documentImports WHERE sourceId=?1 AND moduleId=?2 AND majorVersion "
- "IS NULL AND minorVersion IS NULL LIMIT 1",
- database};
- mutable ReadStatement<1, 3> selectImportIdBySourceIdAndModuleIdAndMajorVersionStatement{
- "SELECT importId FROM documentImports WHERE sourceId=?1 AND moduleId=?2 AND "
- "majorVersion=?3 AND minorVersion IS NULL LIMIT 1",
- database};
- mutable ReadStatement<1, 4> selectImportIdBySourceIdAndModuleIdAndVersionStatement{
- "SELECT importId FROM documentImports WHERE sourceId=?1 AND moduleId=?2 AND "
- "majorVersion=?3 AND minorVersion=?4 LIMIT 1",
- database};
- mutable ReadStatement<1, 1> selectKindFromImportedTypeNamesStatement{
- "SELECT kind FROM importedTypeNames WHERE importedTypeNameId=?1", database};
- mutable ReadStatement<1, 1> selectNameFromImportedTypeNamesStatement{
- "SELECT name FROM importedTypeNames WHERE importedTypeNameId=?1", database};
- mutable ReadStatement<1, 1> selectTypeIdForQualifiedImportedTypeNameNamesStatement{
- "SELECT typeId FROM importedTypeNames AS itn JOIN documentImports AS di ON "
- "importOrSourceId=di.importId JOIN documentImports AS di2 ON di.sourceId=di2.sourceId AND "
- "di.moduleId=di2.sourceModuleId "
- "JOIN exportedTypeNames AS etn ON di2.moduleId=etn.moduleId WHERE "
- "itn.kind=2 AND importedTypeNameId=?1 AND itn.name=etn.name AND "
- "(di.majorVersion IS NULL OR (di.majorVersion=etn.majorVersion AND (di.minorVersion IS "
- "NULL OR di.minorVersion>=etn.minorVersion))) ORDER BY etn.majorVersion DESC NULLS FIRST, "
- "etn.minorVersion DESC NULLS FIRST LIMIT 1",
- database};
- mutable ReadStatement<1, 1> selectTypeIdForImportedTypeNameNamesStatement{
- "SELECT typeId FROM importedTypeNames AS itn JOIN documentImports AS di ON "
- "importOrSourceId=sourceId JOIN exportedTypeNames AS etn USING(moduleId) WHERE "
- "itn.kind=1 AND importedTypeNameId=?1 AND itn.name=etn.name AND "
- "(di.majorVersion IS NULL OR (di.majorVersion=etn.majorVersion AND (di.minorVersion IS "
- "NULL OR di.minorVersion>=etn.minorVersion))) ORDER BY di.kind, etn.majorVersion DESC "
- "NULLS FIRST, etn.minorVersion DESC NULLS FIRST LIMIT 1",
- database};
- WriteStatement<0> deleteAllSourcesStatement{"DELETE FROM sources", database};
- WriteStatement<0> deleteAllSourceContextsStatement{"DELETE FROM sourceContexts", database};
- mutable ReadStatement<6, 1> selectExportedTypesForSourceIdsStatement{
- "SELECT moduleId, name, ifnull(majorVersion, -1), ifnull(minorVersion, -1), typeId, "
- "exportedTypeNameId FROM exportedTypeNames WHERE typeId in carray(?1) ORDER BY moduleId, "
- "name, majorVersion, minorVersion",
- database};
- WriteStatement<5> insertExportedTypeNamesWithVersionStatement{
- "INSERT INTO exportedTypeNames(moduleId, name, majorVersion, minorVersion, typeId) "
- "VALUES(?1, ?2, ?3, ?4, ?5)",
- database};
- WriteStatement<4> insertExportedTypeNamesWithMajorVersionStatement{
- "INSERT INTO exportedTypeNames(moduleId, name, majorVersion, typeId) "
- "VALUES(?1, ?2, ?3, ?4)",
- database};
- WriteStatement<3> insertExportedTypeNamesWithoutVersionStatement{
- "INSERT INTO exportedTypeNames(moduleId, name, typeId) VALUES(?1, ?2, ?3)", database};
- WriteStatement<1> deleteExportedTypeNameStatement{
- "DELETE FROM exportedTypeNames WHERE exportedTypeNameId=?", database};
- WriteStatement<2> updateExportedTypeNameTypeIdStatement{
- "UPDATE exportedTypeNames SET typeId=?2 WHERE exportedTypeNameId=?1", database};
- mutable ReadStatement<4, 1> selectProjectDatasForSourceIdsStatement{
- "SELECT projectSourceId, sourceId, moduleId, fileType FROM projectDatas WHERE "
- "projectSourceId IN carray(?1) ORDER BY projectSourceId, sourceId",
- database};
- WriteStatement<4> insertProjectDataStatement{
- "INSERT INTO projectDatas(projectSourceId, sourceId, "
- "moduleId, fileType) VALUES(?1, ?2, ?3, ?4)",
- database};
- WriteStatement<2> deleteProjectDataStatement{
- "DELETE FROM projectDatas WHERE projectSourceId=?1 AND sourceId=?2", database};
- WriteStatement<4> updateProjectDataStatement{
- "UPDATE projectDatas SET moduleId=?3, fileType=?4 WHERE projectSourceId=?1 AND sourceId=?2",
- database};
- mutable ReadStatement<4, 1> selectProjectDatasForSourceIdStatement{
- "SELECT projectSourceId, sourceId, moduleId, fileType FROM projectDatas WHERE "
- "projectSourceId=?1",
- database};
- mutable ReadStatement<4, 1> selectProjectDataForSourceIdStatement{
- "SELECT projectSourceId, sourceId, moduleId, fileType FROM projectDatas WHERE "
- "sourceId=?1 LIMIT 1",
- database};
- mutable ReadStatement<1, 1> selectTypeIdsForSourceIdsStatement{
- "SELECT typeId FROM types WHERE sourceId IN carray(?1)", database};
- mutable ReadStatement<6, 1> selectModuleExportedImportsForSourceIdStatement{
- "SELECT moduleExportedImportId, moduleId, exportedModuleId, ifnull(majorVersion, -1), "
- "ifnull(minorVersion, -1), isAutoVersion FROM moduleExportedImports WHERE moduleId IN "
- "carray(?1) ORDER BY moduleId, exportedModuleId",
- database};
- WriteStatement<3> insertModuleExportedImportWithoutVersionStatement{
- "INSERT INTO moduleExportedImports(moduleId, exportedModuleId, isAutoVersion) "
- "VALUES (?1, ?2, ?3)",
- database};
- WriteStatement<4> insertModuleExportedImportWithMajorVersionStatement{
- "INSERT INTO moduleExportedImports(moduleId, exportedModuleId, isAutoVersion, "
- "majorVersion) VALUES (?1, ?2, ?3, ?4)",
- database};
- WriteStatement<5> insertModuleExportedImportWithVersionStatement{
- "INSERT INTO moduleExportedImports(moduleId, exportedModuleId, isAutoVersion, "
- "majorVersion, minorVersion) VALUES (?1, ?2, ?3, ?4, ?5)",
- database};
- WriteStatement<1> deleteModuleExportedImportStatement{
- "DELETE FROM moduleExportedImports WHERE moduleExportedImportId=?1", database};
- mutable ReadStatement<3, 3> selectModuleExportedImportsForModuleIdStatement{
- "WITH RECURSIVE "
- " imports(moduleId, majorVersion, minorVersion, moduleExportedImportId) AS ( "
- " SELECT exportedModuleId, "
- " iif(isAutoVersion=1, ?2, majorVersion), "
- " iif(isAutoVersion=1, ?3, minorVersion), "
- " moduleExportedImportId "
- " FROM moduleExportedImports WHERE moduleId=?1 "
- " UNION ALL "
- " SELECT exportedModuleId, "
- " iif(mei.isAutoVersion=1, i.majorVersion, mei.majorVersion), "
- " iif(mei.isAutoVersion=1, i.minorVersion, mei.minorVersion), "
- " mei.moduleExportedImportId "
- " FROM moduleExportedImports AS mei JOIN imports AS i USING(moduleId)) "
- "SELECT DISTINCT moduleId, ifnull(majorVersion, -1), ifnull(minorVersion, -1) "
- "FROM imports",
- database};
- mutable ReadStatement<1, 1> selectPropertyDeclarationIdsForTypeStatement{
- "WITH RECURSIVE "
- " all_prototype_and_extension(typeId, prototypeId) AS ("
- " SELECT typeId, prototypeId FROM types WHERE prototypeId IS NOT NULL"
- " UNION ALL "
- " SELECT typeId, extensionId FROM types WHERE extensionId IS NOT NULL),"
- " typeChain(typeId) AS ("
- " VALUES(?1)"
- " UNION ALL "
- " SELECT prototypeId FROM all_prototype_and_extension JOIN typeChain "
- " USING(typeId))"
- "SELECT propertyDeclarationId FROM typeChain JOIN propertyDeclarations "
- " USING(typeId) ORDER BY propertyDeclarationId",
- database};
- mutable ReadStatement<1, 1> selectLocalPropertyDeclarationIdsForTypeStatement{
- "SELECT propertyDeclarationId "
- "FROM propertyDeclarations "
- "WHERE typeId=? "
- "ORDER BY propertyDeclarationId",
- database};
- mutable ReadStatement<1, 2> selectPropertyDeclarationIdForTypeAndPropertyNameStatement{
- "WITH RECURSIVE "
- " all_prototype_and_extension(typeId, prototypeId) AS ("
- " SELECT typeId, prototypeId FROM types WHERE prototypeId IS NOT NULL"
- " UNION ALL "
- " SELECT typeId, extensionId FROM types WHERE extensionId IS NOT NULL),"
- " typeChain(typeId, level) AS ("
- " VALUES(?1, 0)"
- " UNION ALL "
- " SELECT prototypeId, typeChain.level + 1 FROM all_prototype_and_extension JOIN "
- " typeChain USING(typeId))"
- "SELECT propertyDeclarationId FROM typeChain JOIN propertyDeclarations "
- " USING(typeId) WHERE name=?2 ORDER BY level LIMIT 1",
- database};
- mutable ReadStatement<1, 2> selectLocalPropertyDeclarationIdForTypeAndPropertyNameStatement{
- "SELECT propertyDeclarationId "
- "FROM propertyDeclarations "
- "WHERE typeId=?1 AND name=?2 LIMIT 1",
- database};
- mutable ReadStatement<4, 1> selectPropertyDeclarationForPropertyDeclarationIdStatement{
- "SELECT typeId, name, propertyTraits, propertyTypeId "
- "FROM propertyDeclarations "
- "WHERE propertyDeclarationId=?1 LIMIT 1",
- database};
- mutable ReadStatement<1, 1> selectSignalDeclarationNamesForTypeStatement{
- "WITH RECURSIVE "
- " all_prototype_and_extension(typeId, prototypeId) AS ("
- " SELECT typeId, prototypeId FROM types WHERE prototypeId IS NOT NULL"
- " UNION ALL "
- " SELECT typeId, extensionId FROM types WHERE extensionId IS NOT NULL),"
- " typeChain(typeId) AS ("
- " VALUES(?1)"
- " UNION ALL "
- " SELECT prototypeId FROM all_prototype_and_extension JOIN typeChain "
- " USING(typeId)) "
- "SELECT name FROM typeChain JOIN signalDeclarations "
- " USING(typeId) ORDER BY name",
- database};
- mutable ReadStatement<1, 1> selectFuncionDeclarationNamesForTypeStatement{
- "WITH RECURSIVE "
- " all_prototype_and_extension(typeId, prototypeId) AS ("
- " SELECT typeId, prototypeId FROM types WHERE prototypeId IS NOT NULL"
- " UNION ALL "
- " SELECT typeId, extensionId FROM types WHERE extensionId IS NOT NULL),"
- " typeChain(typeId) AS ("
- " VALUES(?1)"
- " UNION ALL "
- " SELECT prototypeId FROM all_prototype_and_extension JOIN typeChain "
- " USING(typeId))"
- "SELECT name FROM typeChain JOIN functionDeclarations "
- " USING(typeId) ORDER BY name",
- database};
- mutable ReadStatement<2> selectTypesWithDefaultPropertyStatement{
- "SELECT typeId, defaultPropertyId FROM types ORDER BY typeId", database};
- WriteStatement<2> updateDefaultPropertyIdStatement{
- "UPDATE types SET defaultPropertyId=?2 WHERE typeId=?1", database};
- WriteStatement<1> updateDefaultPropertyIdToNullStatement{
- "UPDATE types SET defaultPropertyId=NULL WHERE defaultPropertyId=?1", database};
- mutable ReadStatement<4, 1> selectInfoTypeByTypeIdStatement{
- "SELECT defaultPropertyId, sourceId, traits, annotationTraits FROM types WHERE typeId=?",
- database};
- mutable ReadStatement<1, 1> selectPrototypeIdsForTypeIdInOrderStatement{
- "WITH RECURSIVE "
- " all_prototype_and_extension(typeId, prototypeId) AS ("
- " SELECT typeId, prototypeId FROM types WHERE prototypeId IS NOT NULL"
- " UNION ALL "
- " SELECT typeId, extensionId FROM types WHERE extensionId IS NOT NULL),"
- " prototypes(typeId, level) AS ("
- " SELECT prototypeId, 0 FROM all_prototype_and_extension WHERE typeId=?"
- " UNION ALL "
- " SELECT prototypeId, p.level+1 FROM all_prototype_and_extension JOIN "
- " prototypes AS p USING(typeId)) "
- "SELECT typeId FROM prototypes ORDER BY level",
- database};
- mutable ReadStatement<1, 1> selectPrototypeAndSelfIdsForTypeIdInOrderStatement{
- "WITH RECURSIVE "
- " all_prototype_and_extension(typeId, prototypeId) AS ("
- " SELECT typeId, prototypeId FROM types WHERE prototypeId IS NOT NULL"
- " UNION ALL "
- " SELECT typeId, extensionId FROM types WHERE extensionId IS NOT NULL),"
- " typeChain(typeId, level) AS ("
- " VALUES(?1, 0)"
- " UNION ALL "
- " SELECT prototypeId, tc.level+1 FROM all_prototype_and_extension JOIN "
- " typeChain AS tc USING(typeId)) "
- "SELECT typeId FROM typeChain ORDER BY level",
- database};
- mutable ReadStatement<1, 1> selectPrototypeIdsStatement{
- "WITH RECURSIVE "
- " all_prototype_and_extension(typeId, prototypeId) AS ("
- " SELECT typeId, prototypeId FROM types WHERE prototypeId IS NOT NULL"
- " UNION ALL "
- " SELECT typeId, extensionId FROM types WHERE extensionId IS NOT NULL),"
- " typeSelection(typeId) AS ("
- " SELECT prototypeId FROM all_prototype_and_extension WHERE typeId=?1 "
- " UNION ALL "
- " SELECT prototypeId FROM all_prototype_and_extension JOIN typeSelection "
- " USING(typeId))"
- "SELECT typeId FROM typeSelection",
- database};
- WriteStatement<2> upsertPropertyEditorPathIdStatement{
- "INSERT INTO propertyEditorPaths(typeId, pathSourceId) VALUES(?1, ?2) ON CONFLICT DO "
- "UPDATE SET pathSourceId=excluded.pathSourceId WHERE pathSourceId IS NOT "
- "excluded.pathSourceId",
- database};
- mutable ReadStatement<1, 1> selectPropertyEditorPathIdStatement{
- "SELECT pathSourceId FROM propertyEditorPaths WHERE typeId=?", database};
- mutable ReadStatement<3, 1> selectPropertyEditorPathsForForSourceIdsStatement{
- "SELECT typeId, pathSourceId, directoryId "
- "FROM propertyEditorPaths "
- "WHERE directoryId IN carray(?1) "
- "ORDER BY typeId",
- database};
- WriteStatement<3> insertPropertyEditorPathStatement{
- "INSERT INTO propertyEditorPaths(typeId, pathSourceId, directoryId) VALUES (?1, ?2, ?3)",
- database};
- WriteStatement<3> updatePropertyEditorPathsStatement{"UPDATE propertyEditorPaths "
- "SET pathSourceId=?2, directoryId=?3 "
- "WHERE typeId=?1",
- database};
- WriteStatement<1> deletePropertyEditorPathStatement{
- "DELETE FROM propertyEditorPaths WHERE typeId=?1", database};
- mutable ReadStatement<4, 1> selectTypeAnnotationsForSourceIdsStatement{
- "SELECT typeId, iconPath, itemLibrary, hints FROM typeAnnotations WHERE "
- "sourceId IN carray(?1) ORDER BY typeId",
- database};
- WriteStatement<5> insertTypeAnnotationStatement{
- "INSERT INTO typeAnnotations(typeId, sourceId, iconPath, itemLibrary, hints) VALUES(?1, "
- "?2, ?3, ?4, ?5)",
- database};
- WriteStatement<4> updateTypeAnnotationStatement{
- "UPDATE typeAnnotations SET iconPath=?2, itemLibrary=?3, hints=?4 WHERE typeId=?1", database};
- WriteStatement<1> deleteTypeAnnotationStatement{"DELETE FROM typeAnnotations WHERE typeId=?1",
- database};
- mutable ReadStatement<1, 1> selectTypeIconPathStatement{
- "SELECT iconPath FROM typeAnnotations WHERE typeId=?1", database};
- mutable ReadStatement<2, 1> selectTypeHintsStatement{
- "SELECT hints.key, hints.value "
- "FROM typeAnnotations, json_each(typeAnnotations.hints) AS hints "
- "WHERE typeId=?1",
- database};
- mutable ReadStatement<9> selectItemLibraryEntriesStatement{
- "SELECT typeId, i.value->>'$.name', i.value->>'$.iconPath', i.value->>'$.category', "
- " i.value->>'$.import', i.value->>'$.toolTip', i.value->>'$.properties', "
- " i.value->>'$.extraFilePaths', i.value->>'$.templatePath' "
- "FROM typeAnnotations, json_each(typeAnnotations.itemLibrary) AS i",
- database};
- mutable ReadStatement<9, 1> selectItemLibraryEntriesByTypeIdStatement{
- "SELECT typeId, i.value->>'$.name', i.value->>'$.iconPath', i.value->>'$.category', "
- " i.value->>'$.import', i.value->>'$.toolTip', i.value->>'$.properties', "
- " i.value->>'$.extraFilePaths', i.value->>'$.templatePath' "
- "FROM typeAnnotations, json_each(typeAnnotations.itemLibrary) AS i "
- "WHERE typeId=?1",
- database};
- mutable ReadStatement<9, 1> selectItemLibraryEntriesBySourceIdStatement{
- "SELECT typeId, i.value->>'$.name', i.value->>'$.iconPath', i.value->>'$.category', "
- " i.value->>'$.import', i.value->>'$.toolTip', i.value->>'$.properties', "
- " i.value->>'$.extraFilePaths', i.value->>'$.templatePath' "
- "FROM typeAnnotations, json_each(typeAnnotations.itemLibrary) AS i "
- "WHERE typeId IN (SELECT DISTINCT typeId "
- " FROM documentImports AS di JOIN exportedTypeNames USING(moduleId) "
- " WHERE di.sourceId=?)",
- database};
- mutable ReadStatement<3, 1> selectItemLibraryPropertiesStatement{
- "SELECT p.value->>0, p.value->>1, p.value->>2 FROM json_each(?1) AS p", database};
- mutable ReadStatement<1, 1> selectItemLibraryExtraFilePathsStatement{
- "SELECT p.value FROM json_each(?1) AS p", database};
- mutable ReadStatement<1, 1> selectTypeIdsByModuleIdStatement{
- "SELECT DISTINCT typeId FROM exportedTypeNames WHERE moduleId=?", database};
- mutable ReadStatement<1, 1> selectHeirTypeIdsStatement{
- "WITH RECURSIVE "
- " typeSelection(typeId) AS ("
- " SELECT typeId FROM types WHERE prototypeId=?1 OR extensionId=?1"
- " UNION ALL "
- " SELECT t.typeId "
- " FROM types AS t JOIN typeSelection AS ts "
- " WHERE prototypeId=ts.typeId OR extensionId=ts.typeId)"
- "SELECT typeId FROM typeSelection",
- database};
+ std::unique_ptr<Statements> s;
};
-extern template class ProjectStorage<Sqlite::Database>;
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageerrornotifier.cpp b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageerrornotifier.cpp
new file mode 100644
index 0000000000..a4705f5eec
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageerrornotifier.cpp
@@ -0,0 +1,17 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#include "projectstorageerrornotifier.h"
+
+#include "sourcepathcache.h"
+
+namespace QmlDesigner {
+
+void ProjectStorageErrorNotifier::typeNameCannotBeResolved(Utils::SmallStringView typeName,
+ SourceId sourceId)
+{
+ qDebug() << "Missing type name: " << typeName
+ << " in file: " << m_pathCache.sourcePath(sourceId).toStringView();
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageerrornotifier.h b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageerrornotifier.h
new file mode 100644
index 0000000000..2695e93019
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageerrornotifier.h
@@ -0,0 +1,25 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#pragma once
+
+#include "projectstorageerrornotifierinterface.h"
+
+#include <modelfwd.h>
+
+namespace QmlDesigner {
+
+class ProjectStorageErrorNotifier final : public ProjectStorageErrorNotifierInterface
+{
+public:
+ ProjectStorageErrorNotifier(PathCacheType &pathCache)
+ : m_pathCache{pathCache}
+ {}
+
+ void typeNameCannotBeResolved(Utils::SmallStringView typeName, SourceId souceId) override;
+
+private:
+ PathCacheType &m_pathCache;
+};
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageerrornotifierinterface.h b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageerrornotifierinterface.h
new file mode 100644
index 0000000000..8136c9d599
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageerrornotifierinterface.h
@@ -0,0 +1,27 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#pragma once
+
+#include "projectstorageids.h"
+
+#include <utils/smallstringview.h>
+
+namespace QmlDesigner {
+
+class ProjectStorageErrorNotifierInterface
+{
+public:
+ ProjectStorageErrorNotifierInterface() = default;
+ ProjectStorageErrorNotifierInterface(ProjectStorageErrorNotifierInterface &&) = default;
+ ProjectStorageErrorNotifierInterface &operator=(ProjectStorageErrorNotifierInterface &&) = default;
+ ProjectStorageErrorNotifierInterface(const ProjectStorageErrorNotifierInterface &) = delete;
+ ProjectStorageErrorNotifierInterface &operator=(const ProjectStorageErrorNotifierInterface &) = delete;
+
+ virtual void typeNameCannotBeResolved(Utils::SmallStringView typeName, SourceId souceId) = 0;
+
+protected:
+ ~ProjectStorageErrorNotifierInterface() = default;
+};
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageexceptions.cpp b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageexceptions.cpp
index efe9bc58f5..a86b78a785 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageexceptions.cpp
+++ b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageexceptions.cpp
@@ -3,87 +3,186 @@
#include "projectstorageexceptions.h"
+#include <tracing/qmldesignertracing.h>
+
namespace QmlDesigner {
+using namespace NanotraceHR::Literals;
+using NanotraceHR::keyValue;
+
+namespace {
+auto &category()
+{
+ return ProjectStorageTracing::projectStorageCategory();
+}
+} // namespace
+
+NoSourcePathForInvalidSourceId::NoSourcePathForInvalidSourceId()
+{
+ category().threadEvent("NoSourcePathForInvalidSourceId"_t);
+}
+
const char *NoSourcePathForInvalidSourceId::what() const noexcept
{
return "You cannot get a file path for an invalid file path id!";
}
+NoSourceContextPathForInvalidSourceContextId::NoSourceContextPathForInvalidSourceContextId()
+{
+ category().threadEvent("NoSourceContextPathForInvalidSourceContextId"_t);
+}
+
const char *NoSourceContextPathForInvalidSourceContextId::what() const noexcept
{
return "You cannot get a directory path for an invalid directory path id!";
}
+SourceContextIdDoesNotExists::SourceContextIdDoesNotExists()
+{
+ category().threadEvent("SourceContextIdDoesNotExists"_t);
+}
+
const char *SourceContextIdDoesNotExists::what() const noexcept
{
return "The source context id does not exist in the database!";
}
+SourceIdDoesNotExists::SourceIdDoesNotExists()
+{
+ category().threadEvent("SourceIdDoesNotExists"_t);
+}
+
const char *SourceIdDoesNotExists::what() const noexcept
{
return "The source id does not exist in the database!";
}
+TypeHasInvalidSourceId::TypeHasInvalidSourceId()
+{
+ category().threadEvent("TypeHasInvalidSourceId"_t);
+}
+
const char *TypeHasInvalidSourceId::what() const noexcept
{
return "The source id is invalid!";
}
+ModuleDoesNotExists::ModuleDoesNotExists()
+{
+ category().threadEvent("ModuleDoesNotExists"_t);
+}
+
const char *ModuleDoesNotExists::what() const noexcept
{
return "The module does not exist!";
}
+ModuleAlreadyExists::ModuleAlreadyExists()
+{
+ category().threadEvent("ModuleAlreadyExists"_t);
+}
+
const char *ModuleAlreadyExists::what() const noexcept
{
return "The module does already exist!";
}
-TypeNameDoesNotExists::TypeNameDoesNotExists(std::string_view errorMessage)
- : ProjectStorageErrorWithMessage{"TypeNameDoesNotExists"sv, errorMessage}
-{}
+TypeNameDoesNotExists::TypeNameDoesNotExists(std::string_view typeName, SourceId sourceId)
+ : ProjectStorageErrorWithMessage{
+ "TypeNameDoesNotExists"sv,
+ Utils::SmallString::join(
+ {"type: ", typeName, ", source id: ", Utils::SmallString::number(sourceId.internalId())})}
+{
+ category().threadEvent("TypeNameDoesNotExists"_t,
+ keyValue("type name", typeName),
+ keyValue("source id", sourceId));
+}
+
+PropertyNameDoesNotExists::PropertyNameDoesNotExists()
+{
+ category().threadEvent("PropertyNameDoesNotExists"_t);
+}
const char *PropertyNameDoesNotExists::what() const noexcept
{
return "The property name does not exist!";
}
+PrototypeChainCycle::PrototypeChainCycle()
+{
+ category().threadEvent("PrototypeChainCycle"_t);
+}
+
const char *PrototypeChainCycle::what() const noexcept
{
return "There is a prototype chain cycle!";
}
+AliasChainCycle::AliasChainCycle()
+{
+ category().threadEvent("AliasChainCycle"_t);
+}
+
const char *AliasChainCycle::what() const noexcept
{
return "There is a prototype chain cycle!";
}
+CannotParseQmlTypesFile::CannotParseQmlTypesFile()
+{
+ category().threadEvent("CannotParseQmlTypesFile"_t);
+}
+
const char *CannotParseQmlTypesFile::what() const noexcept
{
return "Cannot parse qml types file!";
}
+CannotParseQmlDocumentFile::CannotParseQmlDocumentFile()
+{
+ category().threadEvent("CannotParseQmlDocumentFile"_t);
+}
+
const char *CannotParseQmlDocumentFile::what() const noexcept
{
return "Cannot parse qml types file!";
}
-const char *ProjectDataHasInvalidProjectSourceId::what() const noexcept
+DirectoryInfoHasInvalidProjectSourceId::DirectoryInfoHasInvalidProjectSourceId()
+{
+ category().threadEvent("DirectoryInfoHasInvalidProjectSourceId"_t);
+}
+
+const char *DirectoryInfoHasInvalidProjectSourceId::what() const noexcept
{
return "The project source id is invalid!";
}
-const char *ProjectDataHasInvalidSourceId::what() const noexcept
+DirectoryInfoHasInvalidSourceId::DirectoryInfoHasInvalidSourceId()
+{
+ category().threadEvent("DirectoryInfoHasInvalidSourceId"_t);
+}
+
+const char *DirectoryInfoHasInvalidSourceId::what() const noexcept
{
return "The source id is invalid!";
}
-const char *ProjectDataHasInvalidModuleId::what() const noexcept
+DirectoryInfoHasInvalidModuleId::DirectoryInfoHasInvalidModuleId()
+{
+ category().threadEvent("DirectoryInfoHasInvalidModuleId"_t);
+}
+
+const char *DirectoryInfoHasInvalidModuleId::what() const noexcept
{
return "The module id is invalid!";
}
+FileStatusHasInvalidSourceId::FileStatusHasInvalidSourceId()
+{
+ category().threadEvent("FileStatusHasInvalidSourceId"_t);
+}
+
const char *FileStatusHasInvalidSourceId::what() const noexcept
{
return "The source id in file status is invalid!";
@@ -110,7 +209,14 @@ const char *ProjectStorageErrorWithMessage::what() const noexcept
ExportedTypeCannotBeInserted::ExportedTypeCannotBeInserted(std::string_view errorMessage)
: ProjectStorageErrorWithMessage{"ExportedTypeCannotBeInserted"sv, errorMessage}
-{}
+{
+ category().threadEvent("ExportedTypeCannotBeInserted"_t, keyValue("error message", errorMessage));
+}
+
+TypeAnnotationHasInvalidSourceId::TypeAnnotationHasInvalidSourceId()
+{
+ category().threadEvent("TypeAnnotationHasInvalidSourceId"_t);
+}
const char *TypeAnnotationHasInvalidSourceId::what() const noexcept
{
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageexceptions.h b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageexceptions.h
index 412dd4a9ff..f4f78f714b 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageexceptions.h
+++ b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageexceptions.h
@@ -5,6 +5,8 @@
#include "../include/qmldesignercorelib_global.h"
+#include "projectstorageids.h"
+
#include <exception>
namespace QmlDesigner {
@@ -13,15 +15,19 @@ using namespace std::literals::string_view_literals;
class QMLDESIGNERCORE_EXPORT ProjectStorageError : public std::exception
{
+protected:
+ ProjectStorageError() = default;
+
public:
const char *what() const noexcept override;
};
class ProjectStorageErrorWithMessage : public ProjectStorageError
{
-public:
+protected:
ProjectStorageErrorWithMessage(std::string_view error, std::string_view errorMessage);
+public:
const char *what() const noexcept override;
public:
@@ -31,42 +37,49 @@ public:
class QMLDESIGNERCORE_EXPORT NoSourcePathForInvalidSourceId : public ProjectStorageError
{
public:
+ NoSourcePathForInvalidSourceId();
const char *what() const noexcept override;
};
class QMLDESIGNERCORE_EXPORT NoSourceContextPathForInvalidSourceContextId : public ProjectStorageError
{
public:
+ NoSourceContextPathForInvalidSourceContextId();
const char *what() const noexcept override;
};
class QMLDESIGNERCORE_EXPORT SourceContextIdDoesNotExists : public ProjectStorageError
{
public:
+ SourceContextIdDoesNotExists();
const char *what() const noexcept override;
};
class QMLDESIGNERCORE_EXPORT SourceIdDoesNotExists : public ProjectStorageError
{
public:
+ SourceIdDoesNotExists();
const char *what() const noexcept override;
};
class QMLDESIGNERCORE_EXPORT TypeHasInvalidSourceId : public ProjectStorageError
{
public:
+ TypeHasInvalidSourceId();
const char *what() const noexcept override;
};
class QMLDESIGNERCORE_EXPORT ModuleDoesNotExists : public ProjectStorageError
{
public:
+ ModuleDoesNotExists();
const char *what() const noexcept override;
};
class QMLDESIGNERCORE_EXPORT ModuleAlreadyExists : public ProjectStorageError
{
public:
+ ModuleAlreadyExists();
const char *what() const noexcept override;
};
@@ -79,66 +92,76 @@ public:
class QMLDESIGNERCORE_EXPORT TypeNameDoesNotExists : public ProjectStorageErrorWithMessage
{
public:
- TypeNameDoesNotExists(std::string_view errorMessage);
+ TypeNameDoesNotExists(std::string_view typeName, SourceId sourceId = SourceId{});
};
class QMLDESIGNERCORE_EXPORT PropertyNameDoesNotExists : public ProjectStorageError
{
public:
+ PropertyNameDoesNotExists();
const char *what() const noexcept override;
};
class QMLDESIGNERCORE_EXPORT PrototypeChainCycle : public ProjectStorageError
{
public:
+ PrototypeChainCycle();
const char *what() const noexcept override;
};
class QMLDESIGNERCORE_EXPORT AliasChainCycle : public ProjectStorageError
{
public:
+ AliasChainCycle();
const char *what() const noexcept override;
};
class QMLDESIGNERCORE_EXPORT CannotParseQmlTypesFile : public ProjectStorageError
{
public:
+ CannotParseQmlTypesFile();
const char *what() const noexcept override;
};
class QMLDESIGNERCORE_EXPORT CannotParseQmlDocumentFile : public ProjectStorageError
{
public:
+ CannotParseQmlDocumentFile();
const char *what() const noexcept override;
};
-class QMLDESIGNERCORE_EXPORT ProjectDataHasInvalidProjectSourceId : public ProjectStorageError
+class QMLDESIGNERCORE_EXPORT DirectoryInfoHasInvalidProjectSourceId : public ProjectStorageError
{
public:
+ DirectoryInfoHasInvalidProjectSourceId();
const char *what() const noexcept override;
};
-class QMLDESIGNERCORE_EXPORT ProjectDataHasInvalidSourceId : public ProjectStorageError
+class QMLDESIGNERCORE_EXPORT DirectoryInfoHasInvalidSourceId : public ProjectStorageError
{
public:
+ DirectoryInfoHasInvalidSourceId();
const char *what() const noexcept override;
};
-class QMLDESIGNERCORE_EXPORT ProjectDataHasInvalidModuleId : public ProjectStorageError
+class QMLDESIGNERCORE_EXPORT DirectoryInfoHasInvalidModuleId : public ProjectStorageError
{
public:
+ DirectoryInfoHasInvalidModuleId();
const char *what() const noexcept override;
};
class QMLDESIGNERCORE_EXPORT FileStatusHasInvalidSourceId : public ProjectStorageError
{
public:
+ FileStatusHasInvalidSourceId();
const char *what() const noexcept override;
};
class QMLDESIGNERCORE_EXPORT TypeAnnotationHasInvalidSourceId : public ProjectStorageError
{
public:
+ TypeAnnotationHasInvalidSourceId();
const char *what() const noexcept override;
};
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstoragefwd.h b/src/plugins/qmldesigner/designercore/projectstorage/projectstoragefwd.h
index b33c609509..cbb7d4265a 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/projectstoragefwd.h
+++ b/src/plugins/qmldesigner/designercore/projectstorage/projectstoragefwd.h
@@ -11,7 +11,6 @@ namespace QmlDesigner {
class ProjectStorageInterface;
class SourcePathCacheInterface;
-template<typename Database>
class ProjectStorage;
template<typename Type>
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageinfotypes.h b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageinfotypes.h
index 427c0ff8d6..1d630344ae 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageinfotypes.h
+++ b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageinfotypes.h
@@ -7,6 +7,9 @@
#include <sqlite/sqlitevalue.h>
#include <utils/smallstring.h>
+#include <utils/utility.h>
+
+#include <QVarLengthArray>
#include <array>
#include <tuple>
@@ -15,19 +18,57 @@
namespace QmlDesigner {
-template<typename Enumeration>
-constexpr std::underlying_type_t<Enumeration> to_underlying(Enumeration enumeration) noexcept
-{
- static_assert(std::is_enum_v<Enumeration>, "to_underlying expect an enumeration");
- return static_cast<std::underlying_type_t<Enumeration>>(enumeration);
-}
+template<std::size_t size>
+using SmallPathStrings = QVarLengthArray<Utils::PathString, size>;
enum class FlagIs : unsigned int { False, Set, True };
+template<typename String>
+void convertToString(String &string, const FlagIs &flagIs)
+{
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+
+ if (flagIs == FlagIs::False)
+ convertToString(string, false);
+ else if (flagIs == FlagIs::True)
+ convertToString(string, true);
+ else
+ convertToString(string, "is set");
+}
+
} // namespace QmlDesigner
namespace QmlDesigner::Storage {
+enum class ModuleKind { QmlLibrary, CppLibrary, PathLibrary };
+
+struct Module
+{
+ Module() = default;
+
+ Module(Utils::SmallStringView name, Storage::ModuleKind kind)
+ : name{name}
+ , kind{kind}
+ {}
+
+ template<typename ModuleType>
+ Module(const ModuleType &module)
+ : name{module.name}
+ , kind{module.kind}
+ {}
+
+ Utils::PathString name;
+ Storage::ModuleKind kind = Storage::ModuleKind::QmlLibrary;
+
+ friend bool operator==(const Module &first, const Module &second)
+ {
+ return first.name == second.name && first.kind == second.kind;
+ }
+
+ explicit operator bool() const { return name.size(); }
+};
+
enum class PropertyDeclarationTraits : int {
None = 0,
IsReadOnly = 1 << 0,
@@ -46,6 +87,18 @@ constexpr bool operator&(PropertyDeclarationTraits first, PropertyDeclarationTra
return static_cast<int>(first) & static_cast<int>(second);
}
+template<typename String>
+void convertToString(String &string, const PropertyDeclarationTraits &traits)
+{
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("is read only", traits & PropertyDeclarationTraits::IsReadOnly),
+ keyValue("is pointer", traits & PropertyDeclarationTraits::IsPointer),
+ keyValue("is list", traits & PropertyDeclarationTraits::IsList));
+
+ convertToString(string, dict);
+}
+
enum class TypeTraitsKind : unsigned int {
None,
Reference,
@@ -53,6 +106,25 @@ enum class TypeTraitsKind : unsigned int {
Sequence,
};
+template<typename String>
+void convertToString(String &string, const TypeTraitsKind &kind)
+{
+ switch (kind) {
+ case TypeTraitsKind::None:
+ convertToString(string, "None");
+ break;
+ case TypeTraitsKind::Reference:
+ convertToString(string, "Reference");
+ break;
+ case TypeTraitsKind::Value:
+ convertToString(string, "Value");
+ break;
+ case TypeTraitsKind::Sequence:
+ convertToString(string, "Sequence");
+ break;
+ }
+}
+
struct TypeTraits
{
constexpr TypeTraits()
@@ -100,6 +172,35 @@ struct TypeTraits
return first.type == second.type && first.annotation == second.annotation;
}
+ template<typename String>
+ friend void convertToString(String &string, const TypeTraits &typeTraits)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(
+ keyValue("kind", typeTraits.kind),
+ keyValue("is enum", typeTraits.isEnum),
+ keyValue("is file component", typeTraits.isFileComponent),
+ keyValue("is project component", typeTraits.isProjectComponent),
+ keyValue("is in project module", typeTraits.isInProjectModule),
+ keyValue("uses custom parser", typeTraits.usesCustomParser),
+ keyValue("can be container", typeTraits.canBeContainer),
+ keyValue("force clip", typeTraits.forceClip),
+ keyValue("does layout children", typeTraits.doesLayoutChildren),
+ keyValue("can be dropped in form editor", typeTraits.canBeDroppedInFormEditor),
+ keyValue("can be dropped in navigator", typeTraits.canBeDroppedInNavigator),
+ keyValue("can be dropped in view 3D", typeTraits.canBeDroppedInView3D),
+ keyValue("is movable", typeTraits.isMovable),
+ keyValue("is resizable", typeTraits.isResizable),
+ keyValue("has form editor item", typeTraits.hasFormEditorItem),
+ keyValue("is stacked container", typeTraits.isStackedContainer),
+ keyValue("takes over rendering of children", typeTraits.takesOverRenderingOfChildren),
+ keyValue("visible in navigator", typeTraits.visibleInNavigator),
+ keyValue("visible in library", typeTraits.visibleInLibrary));
+
+ convertToString(string, dict);
+ }
+
union {
struct
{
@@ -202,10 +303,22 @@ public:
explicit operator bool() const { return major && minor; }
+ template<typename String>
+ friend void convertToString(String &string, const Version &version)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("major version", version.major.value),
+ keyValue("minor version", version.minor.value));
+
+ convertToString(string, dict);
+ }
+
public:
VersionNumber major;
VersionNumber minor;
};
+
} // namespace QmlDesigner::Storage
namespace QmlDesigner::Storage::Info {
@@ -217,6 +330,17 @@ struct TypeHint
, expression{expression}
{}
+ template<typename String>
+ friend void convertToString(String &string, const TypeHint &typeHint)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("name", typeHint.name),
+ keyValue("expression", typeHint.expression));
+
+ convertToString(string, dict);
+ }
+
Utils::SmallString name;
Utils::PathString expression;
};
@@ -231,6 +355,18 @@ struct ItemLibraryProperty
, value{value}
{}
+ template<typename String>
+ friend void convertToString(String &string, const ItemLibraryProperty &property)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("name", property.name),
+ keyValue("type", property.type),
+ keyValue("value", property.value));
+
+ convertToString(string, dict);
+ }
+
Utils::SmallString name;
Utils::SmallString type;
Sqlite::Value value;
@@ -243,6 +379,7 @@ using ToolTipString = Utils::BasicSmallString<94>;
struct ItemLibraryEntry
{
ItemLibraryEntry(TypeId typeId,
+ Utils::SmallStringView typeName,
Utils::SmallStringView name,
Utils::SmallStringView iconPath,
Utils::SmallStringView category,
@@ -250,6 +387,7 @@ struct ItemLibraryEntry
Utils::SmallStringView toolTip,
Utils::SmallStringView templatePath)
: typeId{typeId}
+ , typeName{typeName}
, name{name}
, iconPath{iconPath}
, category{category}
@@ -259,6 +397,7 @@ struct ItemLibraryEntry
{}
ItemLibraryEntry(TypeId typeId,
+ Utils::SmallStringView typeName,
Utils::SmallStringView name,
Utils::SmallStringView iconPath,
Utils::SmallStringView category,
@@ -266,6 +405,7 @@ struct ItemLibraryEntry
Utils::SmallStringView toolTip,
ItemLibraryProperties properties)
: typeId{typeId}
+ , typeName{typeName}
, name{name}
, iconPath{iconPath}
, category{category}
@@ -274,7 +414,27 @@ struct ItemLibraryEntry
, properties{std::move(properties)}
{}
+ template<typename String>
+ friend void convertToString(String &string, const ItemLibraryEntry &entry)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("type id", entry.typeId),
+ keyValue("type name", entry.typeName),
+ keyValue("name", entry.name),
+ keyValue("icon path", entry.iconPath),
+ keyValue("category", entry.category),
+ keyValue("import", entry.import),
+ keyValue("tool tip", entry.toolTip),
+ keyValue("template path", entry.templatePath),
+ keyValue("properties", entry.properties),
+ keyValue("extra file paths", entry.extraFilePaths));
+
+ convertToString(string, dict);
+ }
+
TypeId typeId;
+ Utils::SmallString typeName;
Utils::SmallString name;
Utils::PathString iconPath;
Utils::SmallString category;
@@ -321,6 +481,18 @@ public:
< std::tie(second.moduleId, second.name, second.version);
}
+ template<typename String>
+ friend void convertToString(String &string, const ExportedTypeName &exportedTypeName)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("name", exportedTypeName.name),
+ keyValue("version", exportedTypeName.version),
+ keyValue("module id", exportedTypeName.moduleId));
+
+ convertToString(string, dict);
+ }
+
public:
::Utils::SmallString name;
Storage::Version version;
@@ -342,6 +514,19 @@ public:
, propertyTypeId{propertyTypeId}
{}
+ template<typename String>
+ friend void convertToString(String &string, const PropertyDeclaration &propertyDeclaration)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("type id", propertyDeclaration.typeId),
+ keyValue("name", propertyDeclaration.name),
+ keyValue("traits", propertyDeclaration.traits),
+ keyValue("property type id", propertyDeclaration.propertyTypeId));
+
+ convertToString(string, dict);
+ }
+
TypeId typeId;
::Utils::SmallString name;
PropertyDeclarationTraits traits;
@@ -351,22 +536,26 @@ public:
class Type
{
public:
- Type(PropertyDeclarationId defaultPropertyId,
- SourceId sourceId,
- long long typeTraits,
- long long typeAnnotationTraits)
- : defaultPropertyId{defaultPropertyId}
- , sourceId{sourceId}
+ Type(SourceId sourceId, long long typeTraits, long long typeAnnotationTraits)
+ : sourceId{sourceId}
, traits{typeTraits, typeAnnotationTraits}
{}
- Type(PropertyDeclarationId defaultPropertyId, SourceId sourceId, TypeTraits traits)
- : defaultPropertyId{defaultPropertyId}
- , sourceId{sourceId}
+ Type(SourceId sourceId, TypeTraits traits)
+ : sourceId{sourceId}
, traits{traits}
{}
- PropertyDeclarationId defaultPropertyId;
+ template<typename String>
+ friend void convertToString(String &string, const Type &type)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("source id", type.sourceId), keyValue("traits", type.traits));
+
+ convertToString(string, dict);
+ }
+
SourceId sourceId;
TypeTraits traits;
};
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageinterface.h b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageinterface.h
index 266c6ee7ca..4d840d2a5c 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageinterface.h
+++ b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageinterface.h
@@ -31,7 +31,8 @@ public:
virtual void addObserver(ProjectStorageObserver *observer) = 0;
virtual void removeObserver(ProjectStorageObserver *observer) = 0;
- virtual ModuleId moduleId(::Utils::SmallStringView name) const = 0;
+ virtual ModuleId moduleId(::Utils::SmallStringView name, Storage::ModuleKind kind) const = 0;
+ virtual QmlDesigner::Storage::Module module(ModuleId moduleId) const = 0;
virtual std::optional<Storage::Info::PropertyDeclaration>
propertyDeclaration(PropertyDeclarationId propertyDeclarationId) const = 0;
virtual TypeId typeId(ModuleId moduleId,
@@ -54,7 +55,10 @@ public:
virtual PropertyDeclarationId propertyDeclarationId(TypeId typeId,
::Utils::SmallStringView propertyName) const
= 0;
+ virtual PropertyDeclarationId defaultPropertyDeclarationId(TypeId typeId) const = 0;
virtual std::optional<Storage::Info::Type> type(TypeId typeId) const = 0;
+ virtual SmallSourceIds<4> typeAnnotationSourceIds(SourceId directoryId) const = 0;
+ virtual SmallSourceIds<64> typeAnnotationDirectorySourceIds() const = 0;
virtual Utils::PathString typeIconPath(TypeId typeId) const = 0;
virtual Storage::Info::TypeHints typeHints(TypeId typeId) const = 0;
virtual Storage::Info::ItemLibraryEntries itemLibraryEntries(TypeId typeId) const = 0;
@@ -64,9 +68,9 @@ public:
virtual std::vector<::Utils::SmallString> functionDeclarationNames(TypeId typeId) const = 0;
virtual std::optional<::Utils::SmallString>
propertyName(PropertyDeclarationId propertyDeclarationId) const = 0;
- virtual TypeIds prototypeAndSelfIds(TypeId type) const = 0;
- virtual TypeIds prototypeIds(TypeId type) const = 0;
- virtual TypeIds heirIds(TypeId typeId) const = 0;
+ virtual SmallTypeIds<16> prototypeAndSelfIds(TypeId type) const = 0;
+ virtual SmallTypeIds<16> prototypeIds(TypeId type) const = 0;
+ virtual SmallTypeIds<64> heirIds(TypeId typeId) const = 0;
virtual bool isBasedOn(TypeId, TypeId) const = 0;
virtual bool isBasedOn(TypeId, TypeId, TypeId) const = 0;
virtual bool isBasedOn(TypeId, TypeId, TypeId, TypeId) const = 0;
@@ -76,16 +80,20 @@ public:
virtual bool isBasedOn(TypeId, TypeId, TypeId, TypeId, TypeId, TypeId, TypeId, TypeId) const = 0;
virtual FileStatus fetchFileStatus(SourceId sourceId) const = 0;
- virtual Storage::Synchronization::ProjectDatas fetchProjectDatas(SourceId sourceId) const = 0;
- virtual std::optional<Storage::Synchronization::ProjectData> fetchProjectData(SourceId sourceId) const = 0;
+ virtual Storage::Synchronization::DirectoryInfos fetchDirectoryInfos(SourceId sourceId) const = 0;
+ virtual Storage::Synchronization::DirectoryInfos fetchDirectoryInfos(
+ SourceId directorySourceId, Storage::Synchronization::FileType) const
+ = 0;
+ virtual std::optional<Storage::Synchronization::DirectoryInfo> fetchDirectoryInfo(SourceId sourceId) const = 0;
+ virtual SmallSourceIds<32> fetchSubdirectorySourceIds(SourceId directorySourceId) const = 0;
virtual SourceId propertyEditorPathId(TypeId typeId) const = 0;
- virtual const Storage::Info::CommonTypeCache<ProjectStorageInterface> &commonTypeCache() const = 0;
+ virtual const Storage::Info::CommonTypeCache<ProjectStorageType> &commonTypeCache() const = 0;
- template<const char *moduleName, const char *typeName>
+ template<const char *moduleName, const char *typeName, Storage::ModuleKind moduleKind = Storage::ModuleKind::QmlLibrary>
TypeId commonTypeId() const
{
- return commonTypeCache().template typeId<moduleName, typeName>();
+ return commonTypeCache().template typeId<moduleName, typeName, moduleKind>();
}
template<typename BuiltinType>
@@ -104,7 +112,7 @@ protected:
ProjectStorageInterface() = default;
~ProjectStorageInterface() = default;
- virtual ModuleId fetchModuleIdUnguarded(Utils::SmallStringView name) const = 0;
+ virtual ModuleId fetchModuleIdUnguarded(Utils::SmallStringView name, Storage::ModuleKind moduleKind) const = 0;
virtual TypeId fetchTypeIdByModuleIdAndExportedName(ModuleId moduleId, Utils::SmallStringView name) const = 0;
};
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstoragepathwatchertypes.h b/src/plugins/qmldesigner/designercore/projectstorage/projectstoragepathwatchertypes.h
index a9185d91e8..04f11096bd 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/projectstoragepathwatchertypes.h
+++ b/src/plugins/qmldesigner/designercore/projectstorage/projectstoragepathwatchertypes.h
@@ -12,6 +12,28 @@ namespace QmlDesigner {
enum class SourceType : int { Qml, QmlUi, QmlTypes, QmlDir, Directory };
+template<typename String>
+void convertToString(String &string, SourceType sourceType)
+{
+ switch (sourceType) {
+ case SourceType::Qml:
+ convertToString(string, "Qml");
+ break;
+ case SourceType::QmlUi:
+ convertToString(string, "QmlUi");
+ break;
+ case SourceType::QmlTypes:
+ convertToString(string, "QmlTypes");
+ break;
+ case SourceType::QmlDir:
+ convertToString(string, "QmlDir");
+ break;
+ case SourceType::Directory:
+ convertToString(string, "Directory");
+ break;
+ }
+}
+
class ProjectChunkId
{
public:
@@ -46,6 +68,17 @@ public:
friend bool operator<(ProjectChunkId first, ProjectPartId second) { return first.id < second; }
friend bool operator<(ProjectPartId first, ProjectChunkId second) { return first < second.id; }
+
+ template<typename String>
+ friend void convertToString(String &string, const ProjectChunkId &id)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("project part id", id.id),
+ keyValue("source type", id.sourceType));
+
+ convertToString(string, dict);
+ }
};
using ProjectChunkIds = std::vector<ProjectChunkId>;
@@ -67,6 +100,16 @@ public:
return first.id == second.id && first.sourceIds == second.sourceIds;
}
+ template<typename String>
+ friend void convertToString(String &string, const IdPaths &idPaths)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("id", idPaths.id), keyValue("source ids", idPaths.sourceIds));
+
+ convertToString(string, dict);
+ }
+
public:
ProjectChunkId id;
SourceIds sourceIds;
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstoragetypes.h b/src/plugins/qmldesigner/designercore/projectstorage/projectstoragetypes.h
index 18c3931249..1592628af5 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/projectstoragetypes.h
+++ b/src/plugins/qmldesigner/designercore/projectstorage/projectstoragetypes.h
@@ -7,8 +7,10 @@
#include "projectstorageids.h"
#include "projectstorageinfotypes.h"
+#include <nanotrace/nanotracehr.h>
#include <sqlite/sqlitevalue.h>
#include <utils/smallstring.h>
+#include <utils/utility.h>
#include <tuple>
#include <variant>
@@ -45,6 +47,17 @@ public:
< std::tie(second.sourceId, second.moduleId, second.version);
}
+ template<typename String>
+ friend void convertToString(String &string, const Import &import)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("module id", import.moduleId),
+ keyValue("source id", import.sourceId),
+ keyValue("version", import.version));
+ convertToString(string, dict);
+ }
+
public:
Storage::Version version;
ModuleId moduleId;
@@ -57,11 +70,53 @@ namespace Synchronization {
enum class TypeNameKind { Exported = 1, QualifiedExported = 2 };
-enum class FileType : char { QmlTypes, QmlDocument };
+template<typename String>
+void convertToString(String &string, const TypeNameKind &kind)
+{
+ switch (kind) {
+ case TypeNameKind::Exported:
+ convertToString(string, "Exported");
+ break;
+ case TypeNameKind::QualifiedExported:
+ convertToString(string, "QualifiedExported");
+ break;
+ }
+}
+
+enum class FileType : char { QmlTypes, QmlDocument, Directory };
+
+template<typename String>
+void convertToString(String &string, const FileType &type)
+{
+ switch (type) {
+ case FileType::QmlTypes:
+ convertToString(string, "QmlTypes");
+ break;
+ case FileType::QmlDocument:
+ convertToString(string, "QmlDocument");
+ break;
+ case FileType::Directory:
+ convertToString(string, "Directory");
+ break;
+ }
+}
enum class IsQualified : int { No, Yes };
-inline int operator-(IsQualified first, IsQualified second)
+template<typename String>
+void convertToString(String &string, const IsQualified &isQualified)
+{
+ switch (isQualified) {
+ case IsQualified::No:
+ convertToString(string, "No");
+ break;
+ case IsQualified::Yes:
+ convertToString(string, "Yes");
+ break;
+ }
+}
+
+inline int operator-(IsQualified first, const IsQualified &second)
{
return static_cast<int>(first) - static_cast<int>(second);
}
@@ -78,6 +133,25 @@ enum class ImportKind : char {
ModuleExportedModuleDependency
};
+template<typename String>
+void convertToString(String &string, const ImportKind &kind)
+{
+ switch (kind) {
+ case ImportKind::Import:
+ convertToString(string, "Import");
+ break;
+ case ImportKind::ModuleDependency:
+ convertToString(string, "ModuleDependency");
+ break;
+ case ImportKind::ModuleExportedImport:
+ convertToString(string, "ModuleExportedImport");
+ break;
+ case ImportKind::ModuleExportedModuleDependency:
+ convertToString(string, "ModuleExportedModuleDependency");
+ break;
+ }
+}
+
class ImportView
{
public:
@@ -97,6 +171,19 @@ public:
&& first.version == second.version;
}
+ template<typename String>
+ friend void convertToString(String &string, const ImportView &import)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("import id", import.importId),
+ keyValue("source id", import.sourceId),
+ keyValue("module id", import.moduleId),
+ keyValue("version", import.version));
+
+ convertToString(string, dict);
+ }
+
public:
ImportId importId;
SourceId sourceId;
@@ -106,9 +193,22 @@ public:
enum class IsAutoVersion : char { No, Yes };
+template<typename String>
+void convertToString(String &string, const IsAutoVersion &isAutoVersion)
+{
+ switch (isAutoVersion) {
+ case IsAutoVersion::No:
+ convertToString(string, "No");
+ break;
+ case IsAutoVersion::Yes:
+ convertToString(string, "Yes");
+ break;
+ }
+}
+
constexpr bool operator<(IsAutoVersion first, IsAutoVersion second)
{
- return to_underlying(first) < to_underlying(second);
+ return Utils::to_underlying(first) < Utils::to_underlying(second);
}
class ModuleExportedImport
@@ -137,6 +237,19 @@ public:
< std::tie(second.moduleId, second.exportedModuleId, second.isAutoVersion, second.version);
}
+ template<typename String>
+ friend void convertToString(String &string, const ModuleExportedImport &import)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("module id", import.moduleId),
+ keyValue("exported module id", import.exportedModuleId),
+ keyValue("version", import.version),
+ keyValue("is auto version", import.isAutoVersion));
+
+ convertToString(string, dict);
+ }
+
public:
Storage::Version version;
ModuleId moduleId;
@@ -171,6 +284,20 @@ public:
&& first.version == second.version && first.isAutoVersion == second.isAutoVersion;
}
+ template<typename String>
+ friend void convertToString(String &string, const ModuleExportedImportView &import)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("module exported import id", import.moduleExportedImportId),
+ keyValue("module id", import.moduleId),
+ keyValue("exported module id", import.exportedModuleId),
+ keyValue("version", import.version),
+ keyValue("is auto version", import.isAutoVersion));
+
+ convertToString(string, dict);
+ }
+
public:
ModuleExportedImportId moduleExportedImportId;
Storage::Version version;
@@ -192,6 +319,16 @@ public:
return first.name == second.name;
}
+ template<typename String>
+ friend void convertToString(String &string, const ImportedType &importedType)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("name", importedType.name));
+
+ convertToString(string, dict);
+ }
+
public:
TypeNameString name;
};
@@ -210,6 +347,17 @@ public:
return first.name == second.name && first.import == second.import;
}
+ template<typename String>
+ friend void convertToString(String &string, const QualifiedImportedType &importedType)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("name", importedType.name),
+ keyValue("import", importedType.import));
+
+ convertToString(string, dict);
+ }
+
public:
TypeNameString name;
Import import;
@@ -264,6 +412,19 @@ public:
< std::tie(second.moduleId, second.name, second.version);
}
+ template<typename String>
+ friend void convertToString(String &string, const ExportedType &exportedType)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("name", exportedType.name),
+ keyValue("module id", exportedType.moduleId),
+ keyValue("type id", exportedType.typeId),
+ keyValue("version", exportedType.version));
+
+ convertToString(string, dict);
+ }
+
public:
::Utils::SmallString name;
Storage::Version version;
@@ -295,6 +456,20 @@ public:
, exportedTypeNameId{exportedTypeNameId}
{}
+ template<typename String>
+ friend void convertToString(String &string, const ExportedTypeView &exportedType)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("name", exportedType.name),
+ keyValue("module id", exportedType.moduleId),
+ keyValue("type id", exportedType.typeId),
+ keyValue("version", exportedType.version),
+ keyValue("version", exportedType.exportedTypeNameId));
+
+ convertToString(string, dict);
+ }
+
public:
::Utils::SmallStringView name;
Storage::Version version;
@@ -305,6 +480,43 @@ public:
using ImportedTypeName = std::variant<ImportedType, QualifiedImportedType>;
+template<typename String>
+void convertToString(String &string, const ImportedTypeName &typeName)
+{
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+
+ struct Dispatcher
+ {
+ static const QmlDesigner::Storage::Import &nullImport()
+ {
+ static QmlDesigner::Storage::Import import;
+
+ return import;
+ }
+
+ void operator()(const QmlDesigner::Storage::Synchronization::ImportedType &importedType) const
+ {
+ auto dict = dictonary(keyValue("name", importedType.name));
+
+ convertToString(string, dict);
+ }
+
+ void operator()(
+ const QmlDesigner::Storage::Synchronization::QualifiedImportedType &qualifiedImportedType) const
+ {
+ auto dict = dictonary(keyValue("name", qualifiedImportedType.name),
+ keyValue("import", qualifiedImportedType.import));
+
+ convertToString(string, dict);
+ }
+
+ String &string;
+ };
+
+ std::visit(Dispatcher{string}, typeName);
+}
+
class EnumeratorDeclaration
{
public:
@@ -325,6 +537,18 @@ public:
&& first.hasValue == second.hasValue;
}
+ template<typename String>
+ friend void convertToString(String &string, const EnumeratorDeclaration &enumeratorDeclaration)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("name", enumeratorDeclaration.name),
+ keyValue("value", enumeratorDeclaration.value),
+ keyValue("has value", enumeratorDeclaration.hasValue));
+
+ convertToString(string, dict);
+ }
+
public:
::Utils::SmallString name;
long long value = 0;
@@ -349,6 +573,18 @@ public:
&& first.enumeratorDeclarations == second.enumeratorDeclarations;
}
+ template<typename String>
+ friend void convertToString(String &string, const EnumerationDeclaration &enumerationDeclaration)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("name", enumerationDeclaration.name),
+ keyValue("enumerator declarations",
+ enumerationDeclaration.enumeratorDeclarations));
+
+ convertToString(string, dict);
+ }
+
public:
TypeNameString name;
EnumeratorDeclarations enumeratorDeclarations;
@@ -368,6 +604,20 @@ public:
, id{id}
{}
+ template<typename String>
+ friend void convertToString(String &string,
+ const EnumerationDeclarationView &enumerationDeclaration)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("name", enumerationDeclaration.name),
+ keyValue("enumerator declarations",
+ enumerationDeclaration.enumeratorDeclarations),
+ keyValue("id", enumerationDeclaration.id));
+
+ convertToString(string, dict);
+ }
+
public:
::Utils::SmallStringView name;
::Utils::SmallStringView enumeratorDeclarations;
@@ -392,6 +642,18 @@ public:
&& first.traits == second.traits;
}
+ template<typename String>
+ friend void convertToString(String &string, const ParameterDeclaration &parameterDeclaration)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("name", parameterDeclaration.name),
+ keyValue("type name", parameterDeclaration.typeName),
+ keyValue("traits", parameterDeclaration.traits));
+
+ convertToString(string, dict);
+ }
+
public:
::Utils::SmallString name;
TypeNameString typeName;
@@ -418,6 +680,17 @@ public:
return first.name == second.name && first.parameters == second.parameters;
}
+ template<typename String>
+ friend void convertToString(String &string, const SignalDeclaration &signalDeclaration)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("name", signalDeclaration.name),
+ keyValue("parameters", signalDeclaration.parameters));
+
+ convertToString(string, dict);
+ }
+
public:
::Utils::SmallString name;
ParameterDeclarations parameters;
@@ -437,6 +710,18 @@ public:
, id{id}
{}
+ template<typename String>
+ friend void convertToString(String &string, const SignalDeclarationView &signalDeclaration)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("name", signalDeclaration.name),
+ keyValue("signature", signalDeclaration.signature),
+ keyValue("id", signalDeclaration.id));
+
+ convertToString(string, dict);
+ }
+
public:
::Utils::SmallStringView name;
::Utils::SmallStringView signature;
@@ -467,6 +752,18 @@ public:
&& first.parameters == second.parameters;
}
+ template<typename String>
+ friend void convertToString(String &string, const FunctionDeclaration &functionDeclaration)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("name", functionDeclaration.name),
+ keyValue("return type name", functionDeclaration.returnTypeName),
+ keyValue("parameters", functionDeclaration.parameters));
+
+ convertToString(string, dict);
+ }
+
public:
::Utils::SmallString name;
TypeNameString returnTypeName;
@@ -489,6 +786,19 @@ public:
, id{id}
{}
+ template<typename String>
+ friend void convertToString(String &string, const FunctionDeclarationView &functionDeclaration)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("name", functionDeclaration.name),
+ keyValue("return type name", functionDeclaration.returnTypeName),
+ keyValue("signature", functionDeclaration.signature),
+ keyValue("id", functionDeclaration.id));
+
+ convertToString(string, dict);
+ }
+
public:
::Utils::SmallStringView name;
::Utils::SmallStringView returnTypeName;
@@ -498,6 +808,19 @@ public:
enum class PropertyKind { Property, Alias };
+template<typename String>
+void convertToString(String &string, const PropertyKind &kind)
+{
+ switch (kind) {
+ case PropertyKind::Property:
+ convertToString(string, "Property");
+ break;
+ case PropertyKind::Alias:
+ convertToString(string, "Alias");
+ break;
+ }
+}
+
class PropertyDeclaration
{
public:
@@ -567,6 +890,24 @@ public:
&& first.traits == second.traits && first.kind == second.kind;
}
+ template<typename String>
+ friend void convertToString(String &string, const PropertyDeclaration &propertyDeclaration)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("name", propertyDeclaration.name),
+ keyValue("type name", propertyDeclaration.typeName),
+ keyValue("alias property name", propertyDeclaration.aliasPropertyName),
+ keyValue("alias property name tail",
+ propertyDeclaration.aliasPropertyNameTail),
+ keyValue("traits", propertyDeclaration.traits),
+ keyValue("type id", propertyDeclaration.typeId),
+ keyValue("property type id", propertyDeclaration.propertyTypeId),
+ keyValue("kind", propertyDeclaration.kind));
+
+ convertToString(string, dict);
+ }
+
public:
::Utils::SmallString name;
ImportedTypeName typeName;
@@ -597,6 +938,21 @@ public:
, aliasId{aliasId}
{}
+ template<typename String>
+ friend void convertToString(String &string, const PropertyDeclarationView &propertyDeclaration)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("name", propertyDeclaration.name),
+ keyValue("traits", propertyDeclaration.traits),
+ keyValue("type id", propertyDeclaration.typeId),
+ keyValue("type name id", propertyDeclaration.typeNameId),
+ keyValue("id", propertyDeclaration.id),
+ keyValue("alias id", propertyDeclaration.aliasId));
+
+ convertToString(string, dict);
+ }
+
public:
::Utils::SmallStringView name;
PropertyDeclarationTraits traits = {};
@@ -608,6 +964,22 @@ public:
enum class ChangeLevel : char { Full, Minimal, ExcludeExportedTypes };
+template<typename String>
+void convertToString(String &string, const ChangeLevel &changeLevel)
+{
+ switch (changeLevel) {
+ case ChangeLevel::Full:
+ convertToString(string, "Full");
+ break;
+ case ChangeLevel::Minimal:
+ convertToString(string, "Minimal");
+ break;
+ case ChangeLevel::ExcludeExportedTypes:
+ convertToString(string, "ExcludeExportedTypes");
+ break;
+ }
+}
+
class Type
{
public:
@@ -717,6 +1089,27 @@ public:
&& first.sourceId == second.sourceId;
}
+ template<typename String>
+ friend void convertToString(String &string, const Type &type)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("type name", type.typeName),
+ keyValue("prototype", type.prototype),
+ keyValue("extension", type.extension),
+ keyValue("exported types", type.exportedTypes),
+ keyValue("property declarations", type.propertyDeclarations),
+ keyValue("function declarations", type.functionDeclarations),
+ keyValue("signal declarations", type.signalDeclarations),
+ keyValue("enumeration declarations", type.enumerationDeclarations),
+ keyValue("traits", type.traits),
+ keyValue("source id", type.sourceId),
+ keyValue("change level", type.changeLevel),
+ keyValue("default property name", type.defaultPropertyName));
+
+ convertToString(string, dict);
+ }
+
public:
TypeNameString typeName;
::Utils::SmallString defaultPropertyName;
@@ -747,6 +1140,20 @@ public:
, moduleId{moduleId}
{}
+ template<typename String>
+ friend void convertToString(String &string, const PropertyEditorQmlPath &propertyEditorQmlPath)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("type name", propertyEditorQmlPath.typeName),
+ keyValue("type id", propertyEditorQmlPath.typeId),
+ keyValue("path id", propertyEditorQmlPath.pathId),
+ keyValue("directory id", propertyEditorQmlPath.directoryId),
+ keyValue("module id", propertyEditorQmlPath.moduleId));
+
+ convertToString(string, dict);
+ }
+
public:
TypeNameString typeName;
TypeId typeId;
@@ -757,39 +1164,55 @@ public:
using PropertyEditorQmlPaths = std::vector<class PropertyEditorQmlPath>;
-class ProjectData
+class DirectoryInfo
{
public:
- ProjectData(SourceId projectSourceId, SourceId sourceId, ModuleId moduleId, FileType fileType)
- : projectSourceId{projectSourceId}
+ DirectoryInfo(SourceId directorySourceId, SourceId sourceId, ModuleId moduleId, FileType fileType)
+ : directorySourceId{directorySourceId}
, sourceId{sourceId}
, moduleId{moduleId}
, fileType{fileType}
{}
- friend bool operator==(const ProjectData &first, const ProjectData &second)
+ friend bool operator==(const DirectoryInfo &first, const DirectoryInfo &second)
{
- return first.projectSourceId == second.projectSourceId && first.sourceId == second.sourceId
+ return first.directorySourceId == second.directorySourceId && first.sourceId == second.sourceId
&& first.moduleId.internalId() == second.moduleId.internalId()
&& first.fileType == second.fileType;
}
+ template<typename String>
+ friend void convertToString(String &string, const DirectoryInfo &directoryInfo)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("project source id", directoryInfo.directorySourceId),
+ keyValue("source id", directoryInfo.sourceId),
+ keyValue("module id", directoryInfo.moduleId),
+ keyValue("file type", directoryInfo.fileType));
+
+ convertToString(string, dict);
+ }
+
public:
- SourceId projectSourceId;
+ SourceId directorySourceId;
SourceId sourceId;
ModuleId moduleId;
FileType fileType;
};
-using ProjectDatas = std::vector<ProjectData>;
+using DirectoryInfos = std::vector<DirectoryInfo>;
class TypeAnnotation
{
public:
- TypeAnnotation(SourceId sourceId)
+ TypeAnnotation(SourceId sourceId, SourceId directorySourceId)
: sourceId{sourceId}
+ , directorySourceId{directorySourceId}
{}
+
TypeAnnotation(SourceId sourceId,
+ SourceId directorySourceId,
Utils::SmallStringView typeName,
ModuleId moduleId,
Utils::SmallStringView iconPath,
@@ -803,8 +1226,26 @@ public:
, sourceId{sourceId}
, moduleId{moduleId}
, traits{traits}
+ , directorySourceId{directorySourceId}
{}
+ template<typename String>
+ friend void convertToString(String &string, const TypeAnnotation &typeAnnotation)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("type name", typeAnnotation.typeName),
+ keyValue("icon path", typeAnnotation.iconPath),
+ keyValue("item library json", typeAnnotation.itemLibraryJson),
+ keyValue("hints json", typeAnnotation.hintsJson),
+ keyValue("type id", typeAnnotation.typeId),
+ keyValue("source id", typeAnnotation.sourceId),
+ keyValue("module id", typeAnnotation.moduleId),
+ keyValue("traits", typeAnnotation.traits));
+
+ convertToString(string, dict);
+ }
+
public:
TypeNameString typeName;
Utils::PathString iconPath;
@@ -814,6 +1255,7 @@ public:
SourceId sourceId;
ModuleId moduleId;
TypeTraits traits;
+ SourceId directorySourceId;
};
using TypeAnnotations = std::vector<TypeAnnotation>;
@@ -853,9 +1295,9 @@ public:
, fileStatuses(std::move(fileStatuses))
{}
- SynchronizationPackage(SourceIds updatedProjectSourceIds, ProjectDatas projectDatas)
- : projectDatas(std::move(projectDatas))
- , updatedProjectSourceIds(std::move(updatedProjectSourceIds))
+ SynchronizationPackage(SourceIds updatedDirectoryInfoSourceIds, DirectoryInfos directoryInfos)
+ : directoryInfos(std::move(directoryInfos))
+ , updatedDirectoryInfoSourceIds(std::move(updatedDirectoryInfoSourceIds))
{}
public:
@@ -864,8 +1306,8 @@ public:
SourceIds updatedSourceIds;
SourceIds updatedFileStatusSourceIds;
FileStatuses fileStatuses;
- ProjectDatas projectDatas;
- SourceIds updatedProjectSourceIds;
+ DirectoryInfos directoryInfos;
+ SourceIds updatedDirectoryInfoSourceIds;
Imports moduleDependencies;
SourceIds updatedModuleDependencySourceIds;
ModuleExportedImports moduleExportedImports;
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.cpp b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.cpp
index 62fcf310f6..a0e7bba3c5 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.cpp
+++ b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.cpp
@@ -11,8 +11,11 @@
#include "qmltypesparserinterface.h"
#include "sourcepath.h"
#include "sourcepathcache.h"
+#include "typeannotationreader.h"
#include <sqlitedatabase.h>
+#include <tracing/qmldesignertracing.h>
+#include <utils/set_algorithm.h>
#include <QDirIterator>
#include <QRegularExpression>
@@ -21,6 +24,26 @@
#include <functional>
namespace QmlDesigner {
+constexpr auto category = ProjectStorageTracing::projectStorageUpdaterCategory;
+using NanotraceHR::keyValue;
+using Tracer = ProjectStorageTracing::Category::TracerType;
+
+template<typename String>
+void convertToString(String &string, const ProjectStorageUpdater::FileState &state)
+{
+ switch (state) {
+ case ProjectStorageUpdater::FileState::Changed:
+ convertToString(string, "Changed");
+ break;
+ case ProjectStorageUpdater::FileState::NotChanged:
+ convertToString(string, "NotChanged");
+ break;
+ case ProjectStorageUpdater::FileState::NotExists:
+ convertToString(string, "NotExists");
+ break;
+ }
+}
+
namespace {
QStringList filterMultipleEntries(QStringList qmlTypes)
@@ -79,6 +102,8 @@ ProjectStorageUpdater::Components createComponents(
}
for (const QmlDirParser::Component &qmlDirParserComponent : qmlDirParserComponents) {
+ if (qmlDirParserComponent.fileName.contains('/'))
+ continue;
components.push_back(ProjectStorageUpdater::Component{qmlDirParserComponent.fileName,
qmlDirParserComponent.typeName,
moduleId,
@@ -110,10 +135,15 @@ SourceIds filterNotUpdatedSourceIds(SourceIds updatedSourceIds, SourceIds notUpd
return filteredUpdatedSourceIds;
}
-void addSourceIds(SourceIds &sourceIds, const Storage::Synchronization::ProjectDatas &projectDatas)
+void addSourceIds(SourceIds &sourceIds,
+ const Storage::Synchronization::DirectoryInfos &directoryInfos,
+ TracerLiteral message,
+ Tracer &tracer)
{
- for (const auto &projectData : projectDatas)
- sourceIds.push_back(projectData.sourceId);
+ for (const auto &directoryInfo : directoryInfos) {
+ tracer.tick(message, keyValue("source id", directoryInfo.sourceId));
+ sourceIds.push_back(directoryInfo.sourceId);
+ }
}
Storage::Version convertVersion(LanguageUtils::ComponentVersion version)
@@ -131,34 +161,84 @@ Storage::Synchronization::IsAutoVersion convertToIsAutoVersion(QmlDirParser::Imp
void addDependencies(Storage::Imports &dependencies,
SourceId sourceId,
const QList<QmlDirParser::Import> &qmldirDependencies,
- ProjectStorageInterface &projectStorage)
+ ProjectStorageInterface &projectStorage,
+ TracerLiteral message,
+ Tracer &tracer)
{
for (const QmlDirParser::Import &qmldirDependency : qmldirDependencies) {
- ModuleId moduleId = projectStorage.moduleId(Utils::PathString{qmldirDependency.module}
- + "-cppnative");
- dependencies.emplace_back(moduleId, Storage::Version{}, sourceId);
+ ModuleId moduleId = projectStorage.moduleId(Utils::PathString{qmldirDependency.module},
+ Storage::ModuleKind::CppLibrary);
+ auto &import = dependencies.emplace_back(moduleId, Storage::Version{}, sourceId);
+ tracer.tick(message, keyValue("import", import));
}
}
+void addModuleExportedImport(Storage::Synchronization::ModuleExportedImports &imports,
+ ModuleId moduleId,
+ ModuleId exportedModuleId,
+ Storage::Version version,
+ Storage::Synchronization::IsAutoVersion isAutoVersion,
+ std::string_view moduleName,
+ Storage::ModuleKind moduleKind,
+ std::string_view exportedModuleName)
+{
+ NanotraceHR::Tracer tracer{"add module exported imports"_t,
+ category(),
+ keyValue("module id", moduleId),
+ keyValue("exported module id", exportedModuleId),
+ keyValue("version", version),
+ keyValue("is auto version", isAutoVersion),
+ keyValue("module name", moduleName),
+ keyValue("module kind", moduleKind),
+ keyValue("exported module name", exportedModuleName)};
+
+ imports.emplace_back(moduleId, exportedModuleId, version, isAutoVersion);
+}
+
+bool isOptionalImport(QmlDirParser::Import::Flags flags)
+{
+ return flags & QmlDirParser::Import::Optional && !(flags & QmlDirParser::Import::OptionalDefault);
+}
+
void addModuleExportedImports(Storage::Synchronization::ModuleExportedImports &imports,
ModuleId moduleId,
ModuleId cppModuleId,
+ std::string_view moduleName,
const QList<QmlDirParser::Import> &qmldirImports,
ProjectStorageInterface &projectStorage)
{
+ NanotraceHR::Tracer tracer{"add module exported imports"_t,
+ category(),
+ keyValue("cpp module id", cppModuleId),
+ keyValue("module id", moduleId)};
+
for (const QmlDirParser::Import &qmldirImport : qmldirImports) {
- ModuleId exportedModuleId = projectStorage.moduleId(Utils::PathString{qmldirImport.module});
- imports.emplace_back(moduleId,
- exportedModuleId,
- convertVersion(qmldirImport.version),
- convertToIsAutoVersion(qmldirImport.flags));
+ if (isOptionalImport(qmldirImport.flags))
+ continue;
- ModuleId exportedCppModuleId = projectStorage.moduleId(
- Utils::PathString{qmldirImport.module} + "-cppnative");
- imports.emplace_back(cppModuleId,
- exportedCppModuleId,
- Storage::Version{},
- Storage::Synchronization::IsAutoVersion::No);
+ Utils::PathString exportedModuleName{qmldirImport.module};
+ using Storage::ModuleKind;
+ ModuleId exportedModuleId = projectStorage.moduleId(exportedModuleName,
+ ModuleKind::QmlLibrary);
+ addModuleExportedImport(imports,
+ moduleId,
+ exportedModuleId,
+ convertVersion(qmldirImport.version),
+ convertToIsAutoVersion(qmldirImport.flags),
+ moduleName,
+ ModuleKind::QmlLibrary,
+ exportedModuleName);
+
+ ModuleId exportedCppModuleId = projectStorage.moduleId(exportedModuleName,
+ ModuleKind::CppLibrary);
+ addModuleExportedImport(imports,
+ cppModuleId,
+ exportedCppModuleId,
+ Storage::Version{},
+ Storage::Synchronization::IsAutoVersion::No,
+ moduleName,
+ ModuleKind::CppLibrary,
+ exportedModuleName);
}
}
@@ -182,8 +262,14 @@ std::vector<IdPaths> createIdPaths(ProjectStorageUpdater::WatchedSourceIdsIds wa
void ProjectStorageUpdater::update(QStringList directories,
QStringList qmlTypesPaths,
- const QString &propertyEditorResourcesPath)
+ const QString &propertyEditorResourcesPath,
+ const QStringList &typeAnnotationPaths)
{
+ NanotraceHR::Tracer tracer{"update"_t,
+ category(),
+ keyValue("directories", directories),
+ keyValue("qml types paths", qmlTypesPaths)};
+
Storage::Synchronization::SynchronizationPackage package;
WatchedSourceIdsIds watchedSourceIds{Utils::span{directories}.size()};
NotUpdatedSourceIds notUpdatedSourceIds{Utils::span{directories}.size()};
@@ -191,6 +277,7 @@ void ProjectStorageUpdater::update(QStringList directories,
updateDirectories(directories, package, notUpdatedSourceIds, watchedSourceIds);
updateQmlTypes(qmlTypesPaths, package, notUpdatedSourceIds, watchedSourceIds);
updatePropertyEditorPaths(propertyEditorResourcesPath, package, notUpdatedSourceIds);
+ updateTypeAnnotations(typeAnnotationPaths, package, notUpdatedSourceIds);
package.updatedSourceIds = filterNotUpdatedSourceIds(std::move(package.updatedSourceIds),
std::move(notUpdatedSourceIds.sourceIds));
@@ -198,7 +285,13 @@ void ProjectStorageUpdater::update(QStringList directories,
std::move(package.updatedFileStatusSourceIds),
std::move(notUpdatedSourceIds.fileStatusSourceIds));
- m_projectStorage.synchronize(std::move(package));
+ try {
+ m_projectStorage.synchronize(std::move(package));
+ } catch (const TypeNameDoesNotExists &exception) {
+ qDebug() << "missing type: " << exception.what();
+ } catch (...) {
+ qWarning() << "Project storage could not been updated!";
+ }
m_pathWatcher.updateIdPaths(createIdPaths(watchedSourceIds, m_projectPartId));
}
@@ -211,25 +304,30 @@ void ProjectStorageUpdater::updateQmlTypes(const QStringList &qmlTypesPaths,
if (qmlTypesPaths.empty())
return;
- ModuleId moduleId = m_projectStorage.moduleId("QML-cppnative");
+ NanotraceHR::Tracer tracer{"update qmltypes file"_t, category()};
+
+ ModuleId moduleId = m_projectStorage.moduleId("QML", Storage::ModuleKind::CppLibrary);
for (const QString &qmlTypesPath : qmlTypesPaths) {
SourceId sourceId = m_pathCache.sourceId(SourcePath{qmlTypesPath});
watchedSourceIdsIds.qmltypesSourceIds.push_back(sourceId);
+ tracer.tick("append watched qml types source id"_t,
+ keyValue("source id", sourceId),
+ keyValue("qml types path", qmlTypesPath));
- Storage::Synchronization::ProjectData projectData{sourceId,
- sourceId,
- moduleId,
- Storage::Synchronization::FileType::QmlTypes};
+ Storage::Synchronization::DirectoryInfo directoryInfo{
+ sourceId, sourceId, moduleId, Storage::Synchronization::FileType::QmlTypes};
- FileState state = parseTypeInfo(projectData,
+ FileState state = parseTypeInfo(directoryInfo,
Utils::PathString{qmlTypesPath},
package,
notUpdatedSourceIds);
if (state == FileState::Changed) {
- package.projectDatas.push_back(std::move(projectData));
- package.updatedProjectSourceIds.push_back(sourceId);
+ tracer.tick("append project data"_t, keyValue("project data", directoryInfo));
+ package.directoryInfos.push_back(std::move(directoryInfo));
+ tracer.tick("append updated project source ids"_t, keyValue("source id", sourceId));
+ package.updatedDirectoryInfoSourceIds.push_back(sourceId);
}
}
}
@@ -246,24 +344,199 @@ ProjectStorageUpdater::FileState combineState(FileStates... fileStates)
return ProjectStorageUpdater::FileState::NotExists;
}
+
} // namespace
+void ProjectStorageUpdater::updateDirectoryChanged(std::string_view directoryPath,
+ FileState qmldirState,
+ SourcePath qmldirSourcePath,
+ SourceId qmldirSourceId,
+ SourceId directorySourceId,
+ SourceContextId directoryId,
+ Storage::Synchronization::SynchronizationPackage &package,
+ NotUpdatedSourceIds &notUpdatedSourceIds,
+ WatchedSourceIdsIds &watchedSourceIdsIds,
+ Tracer &tracer)
+{
+ QmlDirParser parser;
+ if (qmldirState != FileState::NotExists)
+ parser.parse(m_fileSystem.contentAsQString(QString{qmldirSourcePath}));
+
+ if (qmldirState != FileState::NotChanged) {
+ tracer.tick("append updated source id"_t, keyValue("module id", qmldirSourceId));
+ package.updatedSourceIds.push_back(qmldirSourceId);
+ }
+
+ using Storage::ModuleKind;
+ Utils::PathString moduleName{parser.typeNamespace()};
+ ModuleId moduleId = m_projectStorage.moduleId(moduleName, ModuleKind::QmlLibrary);
+ ModuleId cppModuleId = m_projectStorage.moduleId(moduleName, ModuleKind::CppLibrary);
+ ModuleId pathModuleId = m_projectStorage.moduleId(directoryPath, ModuleKind::PathLibrary);
+
+ auto imports = filterMultipleEntries(parser.imports());
+
+ addModuleExportedImports(package.moduleExportedImports,
+ moduleId,
+ cppModuleId,
+ moduleName,
+ imports,
+ m_projectStorage);
+ tracer.tick("append updated module id"_t, keyValue("module id", moduleId));
+ package.updatedModuleIds.push_back(moduleId);
+
+ const auto qmlDirectoryInfos = m_projectStorage.fetchDirectoryInfos(directorySourceId);
+ addSourceIds(package.updatedSourceIds, qmlDirectoryInfos, "append updated source id"_t, tracer);
+ addSourceIds(package.updatedFileStatusSourceIds,
+ qmlDirectoryInfos,
+ "append updated file status source id"_t,
+ tracer);
+
+ auto qmlTypes = filterMultipleEntries(parser.typeInfos());
+
+ if (!qmlTypes.isEmpty()) {
+ parseTypeInfos(qmlTypes,
+ filterMultipleEntries(parser.dependencies()),
+ imports,
+ directorySourceId,
+ directoryPath,
+ cppModuleId,
+ package,
+ notUpdatedSourceIds,
+ watchedSourceIdsIds);
+ }
+ parseQmlComponents(
+ createComponents(parser.components(), moduleId, pathModuleId, m_fileSystem, directoryPath),
+ directorySourceId,
+ directoryId,
+ package,
+ notUpdatedSourceIds,
+ watchedSourceIdsIds,
+ qmldirState);
+ tracer.tick("append updated project source id"_t, keyValue("module id", moduleId));
+ package.updatedDirectoryInfoSourceIds.push_back(directorySourceId);
+}
+
void ProjectStorageUpdater::updateDirectories(const QStringList &directories,
Storage::Synchronization::SynchronizationPackage &package,
NotUpdatedSourceIds &notUpdatedSourceIds,
WatchedSourceIdsIds &watchedSourceIdsIds)
{
+ NanotraceHR::Tracer tracer{"update directories"_t, category()};
+
for (const QString &directory : directories)
- updateDirectory({directory}, package, notUpdatedSourceIds, watchedSourceIdsIds);
+ updateDirectory({directory}, {}, package, notUpdatedSourceIds, watchedSourceIdsIds);
+}
+
+void ProjectStorageUpdater::updateSubdirectories(const Utils::PathString &directoryPath,
+ SourceId directorySourceId,
+ FileState directoryState,
+ const SourceContextIds &subdirectoriesToIgnore,
+ Storage::Synchronization::SynchronizationPackage &package,
+ NotUpdatedSourceIds &notUpdatedSourceIds,
+ WatchedSourceIdsIds &watchedSourceIdsIds)
+{
+ struct Directory
+ {
+ Directory(Utils::SmallStringView path, SourceContextId sourceContextId, SourceId sourceId)
+ : path{path}
+ , sourceContextId{sourceContextId}
+ , sourceId{sourceId}
+ {}
+
+ bool operator<(const Directory &other) const
+ {
+ return sourceContextId < other.sourceContextId;
+ }
+
+ bool operator==(const Directory &other) const
+ {
+ return sourceContextId == other.sourceContextId;
+ }
+
+ Utils::PathString path;
+ SourceContextId sourceContextId;
+ SourceId sourceId;
+ };
+
+ struct Compare
+ {
+ bool operator()(const Directory &first, const Directory &second) const
+ {
+ return first.sourceContextId < second.sourceContextId;
+ }
+
+ bool operator()(const Directory &first, SourceContextId second) const
+ {
+ return first.sourceContextId < second;
+ }
+
+ bool operator()(SourceContextId first, const Directory &second) const
+ {
+ return first < second.sourceContextId;
+ }
+ };
+
+ using Directories = QVarLengthArray<Directory, 32>;
+
+ auto subdirectorySourceIds = m_projectStorage.fetchSubdirectorySourceIds(directorySourceId);
+ auto subdirectories = Utils::transform<Directories>(
+ subdirectorySourceIds, [&](SourceId sourceId) -> Directory {
+ auto sourceContextId = m_pathCache.sourceContextId(sourceId);
+ auto subdirectoryPath = m_pathCache.sourceContextPath(sourceContextId);
+ return {subdirectoryPath, sourceContextId, sourceId};
+ });
+
+ auto exisitingSubdirectoryPaths = m_fileSystem.subdirectories(directoryPath.toQString());
+ Directories existingSubdirecories;
+ for (const QString &subdirectory : exisitingSubdirectoryPaths) {
+ if (subdirectory.endsWith("/designer") || subdirectory.endsWith("/QtQuick/Scene2D")
+ || subdirectory.endsWith("/QtQuick/Scene3D"))
+ continue;
+ Utils::PathString subdirectoryPath = subdirectory;
+ auto [sourceContextId, sourceId] = m_pathCache.sourceContextAndSourceId(
+ SourcePath{subdirectoryPath + "/."});
+ subdirectories.emplace_back(subdirectoryPath, sourceContextId, sourceId);
+ existingSubdirecories.emplace_back(subdirectoryPath, sourceContextId, sourceId);
+ }
+
+ std::sort(subdirectories.begin(), subdirectories.end());
+ subdirectories.erase(std::unique(subdirectories.begin(), subdirectories.end()),
+ subdirectories.end());
+
+ std::set_difference(subdirectories.begin(),
+ subdirectories.end(),
+ subdirectoriesToIgnore.begin(),
+ subdirectoriesToIgnore.end(),
+ Utils::make_iterator([&](const Directory &subdirectory) {
+ updateDirectory(subdirectory.path,
+ subdirectoriesToIgnore,
+ package,
+ notUpdatedSourceIds,
+ watchedSourceIdsIds);
+ }),
+ Compare{});
+
+ if (directoryState == FileState::Changed) {
+ for (const auto &[subdirectoryPath, sourceContextId, subdirectorySourceId] :
+ existingSubdirecories) {
+ package.directoryInfos.emplace_back(directorySourceId,
+ subdirectorySourceId,
+ ModuleId{},
+ Storage::Synchronization::FileType::Directory);
+ }
+ }
}
void ProjectStorageUpdater::updateDirectory(const Utils::PathString &directoryPath,
+ const SourceContextIds &subdirectoriesToIgnore,
Storage::Synchronization::SynchronizationPackage &package,
NotUpdatedSourceIds &notUpdatedSourceIds,
WatchedSourceIdsIds &watchedSourceIdsIds)
{
+ NanotraceHR::Tracer tracer{"update directory"_t, category(), keyValue("directory", directoryPath)};
+
SourcePath qmldirSourcePath{directoryPath + "/qmldir"};
- auto [directoryId, qmlDirSourceId] = m_pathCache.sourceContextAndSourceId(qmldirSourcePath);
+ auto [directoryId, qmldirSourceId] = m_pathCache.sourceContextAndSourceId(qmldirSourcePath);
SourcePath directorySourcePath{directoryPath + "/."};
auto directorySourceId = m_pathCache.sourceId(directorySourcePath);
@@ -271,82 +544,69 @@ void ProjectStorageUpdater::updateDirectory(const Utils::PathString &directoryPa
if (directoryState != FileState::NotExists)
watchedSourceIdsIds.directorySourceIds.push_back(directorySourceId);
- auto qmldirState = fileState(qmlDirSourceId, package, notUpdatedSourceIds);
+ auto qmldirState = fileState(qmldirSourceId, package, notUpdatedSourceIds);
if (qmldirState != FileState::NotExists)
- watchedSourceIdsIds.qmldirSourceIds.push_back(qmlDirSourceId);
+ watchedSourceIdsIds.qmldirSourceIds.push_back(qmldirSourceId);
switch (combineState(directoryState, qmldirState)) {
case FileState::Changed: {
- QmlDirParser parser;
- if (qmldirState != FileState::NotExists)
- parser.parse(m_fileSystem.contentAsQString(QString{qmldirSourcePath}));
-
- if (qmldirState != FileState::NotChanged)
- package.updatedSourceIds.push_back(qmlDirSourceId);
-
- Utils::PathString moduleName{parser.typeNamespace()};
- ModuleId moduleId = m_projectStorage.moduleId(moduleName);
- ModuleId cppModuleId = m_projectStorage.moduleId(moduleName + "-cppnative");
- ModuleId pathModuleId = m_projectStorage.moduleId(directoryPath);
-
- auto imports = filterMultipleEntries(parser.imports());
-
- addModuleExportedImports(package.moduleExportedImports,
- moduleId,
- cppModuleId,
- imports,
- m_projectStorage);
- package.updatedModuleIds.push_back(moduleId);
-
- const auto qmlProjectDatas = m_projectStorage.fetchProjectDatas(directorySourceId);
- addSourceIds(package.updatedSourceIds, qmlProjectDatas);
- addSourceIds(package.updatedFileStatusSourceIds, qmlProjectDatas);
-
- auto qmlTypes = filterMultipleEntries(parser.typeInfos());
-
- if (!qmlTypes.isEmpty()) {
- parseTypeInfos(qmlTypes,
- filterMultipleEntries(parser.dependencies()),
- imports,
- directorySourceId,
- directoryPath,
- cppModuleId,
- package,
- notUpdatedSourceIds,
- watchedSourceIdsIds);
- }
- parseQmlComponents(
- createComponents(parser.components(), moduleId, pathModuleId, m_fileSystem, directoryPath),
- directorySourceId,
- directoryId,
- package,
- notUpdatedSourceIds,
- watchedSourceIdsIds,
- qmldirState);
- package.updatedProjectSourceIds.push_back(directorySourceId);
+ tracer.tick("update directory changed"_t);
+ updateDirectoryChanged(directoryPath,
+ qmldirState,
+ qmldirSourcePath,
+ qmldirSourceId,
+ directorySourceId,
+ directoryId,
+ package,
+ notUpdatedSourceIds,
+ watchedSourceIdsIds,
+ tracer);
break;
}
case FileState::NotChanged: {
- parseProjectDatas(m_projectStorage.fetchProjectDatas(directorySourceId),
- package,
- notUpdatedSourceIds,
- watchedSourceIdsIds);
+ tracer.tick("update directory not changed"_t);
+
+ parseDirectoryInfos(m_projectStorage.fetchDirectoryInfos(directorySourceId),
+ package,
+ notUpdatedSourceIds,
+ watchedSourceIdsIds);
break;
}
case FileState::NotExists: {
+ tracer.tick("update directory don't exits"_t);
+
package.updatedFileStatusSourceIds.push_back(directorySourceId);
- package.updatedFileStatusSourceIds.push_back(qmlDirSourceId);
- package.updatedProjectSourceIds.push_back(directorySourceId);
- package.updatedSourceIds.push_back(qmlDirSourceId);
- auto qmlProjectDatas = m_projectStorage.fetchProjectDatas(directorySourceId);
- for (const Storage::Synchronization::ProjectData &projectData : qmlProjectDatas) {
- package.updatedSourceIds.push_back(projectData.sourceId);
- package.updatedFileStatusSourceIds.push_back(projectData.sourceId);
+ package.updatedFileStatusSourceIds.push_back(qmldirSourceId);
+ package.updatedDirectoryInfoSourceIds.push_back(directorySourceId);
+ package.updatedSourceIds.push_back(qmldirSourceId);
+ auto qmlDirectoryInfos = m_projectStorage.fetchDirectoryInfos(directorySourceId);
+ for (const Storage::Synchronization::DirectoryInfo &directoryInfo : qmlDirectoryInfos) {
+ tracer.tick("append updated source id"_t, keyValue("source id", directoryInfo.sourceId));
+ package.updatedSourceIds.push_back(directoryInfo.sourceId);
+ tracer.tick("append updated file status source id"_t,
+ keyValue("source id", directoryInfo.sourceId));
+ package.updatedFileStatusSourceIds.push_back(directoryInfo.sourceId);
}
break;
}
}
+
+ updateSubdirectories(directoryPath,
+ directorySourceId,
+ directoryState,
+ subdirectoriesToIgnore,
+ package,
+ notUpdatedSourceIds,
+ watchedSourceIdsIds);
+
+ tracer.end(keyValue("qmldir source path", qmldirSourcePath),
+ keyValue("directory source path", directorySourcePath),
+ keyValue("directory id", directoryId),
+ keyValue("qmldir source id", qmldirSourceId),
+ keyValue("directory source source id", directorySourceId),
+ keyValue("qmldir state", qmldirState),
+ keyValue("directory state", directoryState));
}
void ProjectStorageUpdater::updatePropertyEditorPaths(
@@ -354,6 +614,10 @@ void ProjectStorageUpdater::updatePropertyEditorPaths(
Storage::Synchronization::SynchronizationPackage &package,
NotUpdatedSourceIds &notUpdatedSourceIds)
{
+ NanotraceHR::Tracer tracer{"update property editor paths"_t,
+ category(),
+ keyValue("property editor resources path", propertyEditorResourcesPath)};
+
if (propertyEditorResourcesPath.isEmpty())
return;
@@ -368,49 +632,196 @@ void ProjectStorageUpdater::updatePropertyEditorPaths(
auto state = fileState(directorySourceId, package, notUpdatedSourceIds);
- if (state == FileState::Changed)
- updatePropertyEditorPath(pathInfo.filePath(), package, directorySourceId);
+ if (state == FileState::Changed) {
+ updatePropertyEditorPath(pathInfo.filePath(),
+ package,
+ directorySourceId,
+ propertyEditorResourcesPath.size() + 1);
+ }
}
}
+namespace {
+
+template<typename SourceIds1, typename SourceIds2>
+SmallSourceIds<16> mergedSourceIds(const SourceIds1 &sourceIds1, const SourceIds2 &sourceIds2)
+{
+ SmallSourceIds<16> mergedSourceIds;
+
+ std::set_union(sourceIds1.begin(),
+ sourceIds1.end(),
+ sourceIds2.begin(),
+ sourceIds2.end(),
+ std::back_inserter(mergedSourceIds));
+
+ return mergedSourceIds;
+}
+} // namespace
+
+void ProjectStorageUpdater::updateTypeAnnotations(const QStringList &directoryPaths,
+ Storage::Synchronization::SynchronizationPackage &package,
+ NotUpdatedSourceIds &notUpdatedSourceIds)
+{
+ NanotraceHR::Tracer tracer("update type annotations"_t, category());
+
+ std::map<SourceId, SmallSourceIds<16>> updatedSourceIdsDictonary;
+
+ for (SourceId directoryId : m_projectStorage.typeAnnotationDirectorySourceIds())
+ updatedSourceIdsDictonary[directoryId] = {};
+
+ for (const auto &directoryPath : directoryPaths)
+ updateTypeAnnotations(directoryPath, package, notUpdatedSourceIds, updatedSourceIdsDictonary);
+
+ updateTypeAnnotationDirectories(package, notUpdatedSourceIds, updatedSourceIdsDictonary);
+}
+
void ProjectStorageUpdater::updateTypeAnnotations(
- const QString & /*propertyEditorResourcesPath*/,
- Storage::Synchronization::SynchronizationPackage & /*package*/,
- NotUpdatedSourceIds & /*notUpdatedSourceIds*/)
+ const QString &rootDirectoryPath,
+ Storage::Synchronization::SynchronizationPackage &package,
+ NotUpdatedSourceIds &notUpdatedSourceIds,
+ std::map<SourceId, SmallSourceIds<16>> &updatedSourceIdsDictonary)
+{
+ NanotraceHR::Tracer tracer("update type annotation directory"_t,
+ category(),
+ keyValue("path", rootDirectoryPath));
+
+ if (rootDirectoryPath.isEmpty())
+ return;
+
+ QDirIterator directoryIterator{rootDirectoryPath,
+ {"*.metainfo"},
+ QDir::NoDotAndDotDot | QDir::Files,
+ QDirIterator::Subdirectories};
+
+ while (directoryIterator.hasNext()) {
+ auto fileInfo = directoryIterator.nextFileInfo();
+ auto filePath = fileInfo.filePath();
+ SourceId sourceId = m_pathCache.sourceId(SourcePath{filePath});
+
+ auto directoryPath = fileInfo.canonicalPath();
+
+ SourceId directorySourceId = m_pathCache.sourceId(SourcePath{directoryPath + "/."});
+
+ auto state = fileState(sourceId, package, notUpdatedSourceIds);
+ if (state == FileState::Changed)
+ updateTypeAnnotation(directoryPath, fileInfo.filePath(), sourceId, directorySourceId, package);
+
+ if (state != FileState::NotChanged)
+ updatedSourceIdsDictonary[directorySourceId].push_back(sourceId);
+ }
+}
+
+void ProjectStorageUpdater::updateTypeAnnotationDirectories(
+ Storage::Synchronization::SynchronizationPackage &package,
+ NotUpdatedSourceIds &notUpdatedSourceIds,
+ std::map<SourceId, SmallSourceIds<16>> &updatedSourceIdsDictonary)
+{
+ for (auto &[directorySourceId, updatedSourceIds] : updatedSourceIdsDictonary) {
+ auto directoryState = fileState(directorySourceId, package, notUpdatedSourceIds);
+
+ if (directoryState != FileState::NotChanged) {
+ auto existingTypeAnnotationSourceIds = m_projectStorage.typeAnnotationSourceIds(
+ directorySourceId);
+
+ std::sort(updatedSourceIds.begin(), updatedSourceIds.end());
+
+ auto changedSourceIds = mergedSourceIds(existingTypeAnnotationSourceIds, updatedSourceIds);
+ package.updatedTypeAnnotationSourceIds.insert(package.updatedTypeAnnotationSourceIds.end(),
+ changedSourceIds.begin(),
+ changedSourceIds.end());
+ } else {
+ package.updatedTypeAnnotationSourceIds.insert(package.updatedTypeAnnotationSourceIds.end(),
+ updatedSourceIds.begin(),
+ updatedSourceIds.end());
+ }
+ }
+}
+
+namespace {
+QString contentFromFile(const QString &path)
{
- // const auto typeAnnotations = dir.entryInfoList({"*.metainfo"}, QDir::Files);
+ QFile file{path};
+ if (file.open(QIODevice::ReadOnly))
+ return QString::fromUtf8(file.readAll());
+
+ return {};
+}
+} // namespace
+
+void ProjectStorageUpdater::updateTypeAnnotation(const QString &directoryPath,
+ const QString &filePath,
+ SourceId sourceId,
+ SourceId directorySourceId,
+ Storage::Synchronization::SynchronizationPackage &package)
+{
+ NanotraceHR::Tracer tracer{"update type annotation path"_t,
+ category(),
+ keyValue("path", filePath),
+ keyValue("directory path", directoryPath)};
+
+ Storage::TypeAnnotationReader reader{m_projectStorage};
+
+ auto annotations = reader.parseTypeAnnotation(contentFromFile(filePath),
+ directoryPath,
+ sourceId,
+ directorySourceId);
+ auto &typeAnnotations = package.typeAnnotations;
+ package.typeAnnotations.insert(typeAnnotations.end(),
+ std::make_move_iterator(annotations.begin()),
+ std::make_move_iterator(annotations.end()));
}
void ProjectStorageUpdater::updatePropertyEditorPath(
const QString &directoryPath,
Storage::Synchronization::SynchronizationPackage &package,
- SourceId directorySourceId)
+ SourceId directorySourceId,
+ long long pathOffset)
{
+ NanotraceHR::Tracer tracer{"update property editor path"_t,
+ category(),
+ keyValue("directory path", directoryPath),
+ keyValue("directory source id", directorySourceId)};
+
+ tracer.tick("append updated property editor qml path source id"_t,
+ keyValue("source id", directorySourceId));
package.updatedPropertyEditorQmlPathSourceIds.push_back(directorySourceId);
auto dir = QDir{directoryPath};
const auto fileInfos = dir.entryInfoList({"*Pane.qml", "*Specifics.qml"}, QDir::Files);
for (const auto &fileInfo : fileInfos)
- updatePropertyEditorFilePath(fileInfo.filePath(), package, directorySourceId);
+ updatePropertyEditorFilePath(fileInfo.filePath(), package, directorySourceId, pathOffset);
}
void ProjectStorageUpdater::updatePropertyEditorFilePath(
const QString &path,
Storage::Synchronization::SynchronizationPackage &package,
- SourceId directorySourceId)
+ SourceId directorySourceId,
+ long long pathOffset)
{
- QRegularExpression regex{R"xo(.+\/(\w+)\/(\w+)(Specifics|Pane).qml)xo"};
- auto match = regex.match(path);
+ NanotraceHR::Tracer tracer{"update property editor file path"_t,
+ category(),
+ keyValue("directory path", path),
+ keyValue("directory source id", directorySourceId)};
+
+ QRegularExpression regex{R"xo((.+)\/(\w+)(Specifics|Pane).qml)xo"};
+ auto match = regex.match(QStringView{path}.mid(pathOffset));
QString oldModuleName;
ModuleId moduleId;
if (match.hasMatch()) {
- auto moduleName = match.capturedView(1);
+ auto moduleName = match.capturedView(1).toString();
+ moduleName.replace('/', '.');
if (oldModuleName != moduleName) {
- oldModuleName = moduleName.toString();
- moduleId = m_projectStorage.moduleId(Utils::SmallString{moduleName});
+ oldModuleName = moduleName;
+ moduleId = m_projectStorage.moduleId(Utils::SmallString{moduleName},
+ Storage::ModuleKind::QmlLibrary);
}
Storage::TypeNameString typeName{match.capturedView(2)};
SourceId pathId = m_pathCache.sourceId(SourcePath{path});
- package.propertyEditorQmlPaths.emplace_back(moduleId, typeName, pathId, directorySourceId);
+ const auto &paths = package.propertyEditorQmlPaths.emplace_back(moduleId,
+ typeName,
+ pathId,
+ directorySourceId);
+ tracer.tick("append property editor qml paths"_t,
+ keyValue("property editor qml paths", paths));
}
}
@@ -447,6 +858,10 @@ bool contains(const Container &container, Id id)
void ProjectStorageUpdater::pathsWithIdsChanged(const std::vector<IdPaths> &changedIdPaths)
{
+ NanotraceHR::Tracer tracer{"paths with ids changed"_t,
+ category(),
+ keyValue("id paths", changedIdPaths)};
+
m_changedIdPaths.insert(m_changedIdPaths.end(), changedIdPaths.begin(), changedIdPaths.end());
Storage::Synchronization::SynchronizationPackage package;
@@ -486,7 +901,11 @@ void ProjectStorageUpdater::pathsWithIdsChanged(const std::vector<IdPaths> &chan
for (auto sourceContextId : directorySourceContextIds) {
Utils::PathString directory = m_pathCache.sourceContextPath(sourceContextId);
- updateDirectory(directory, package, notUpdatedSourceIds, watchedSourceIds);
+ updateDirectory(directory,
+ directorySourceContextIds,
+ package,
+ notUpdatedSourceIds,
+ watchedSourceIds);
}
for (SourceId sourceId : filterUniqueSourceIds(qmlDocumentSourceIds)) {
@@ -498,9 +917,9 @@ void ProjectStorageUpdater::pathsWithIdsChanged(const std::vector<IdPaths> &chan
for (SourceId sourceId : filterUniqueSourceIds(std::move(qmltypesSourceIds))) {
if (!contains(directorySourceContextIds, m_pathCache.sourceContextId(sourceId))) {
auto qmltypesPath = m_pathCache.sourcePath(sourceId);
- auto projectData = m_projectStorage.fetchProjectData(sourceId);
- if (projectData)
- parseTypeInfo(*projectData, qmltypesPath, package, notUpdatedSourceIds);
+ auto directoryInfo = m_projectStorage.fetchDirectoryInfo(sourceId);
+ if (directoryInfo)
+ parseTypeInfo(*directoryInfo, qmltypesPath, package, notUpdatedSourceIds);
}
}
} catch (const QmlDesigner::CannotParseQmlTypesFile &) {
@@ -539,72 +958,99 @@ void ProjectStorageUpdater::parseTypeInfos(const QStringList &typeInfos,
NotUpdatedSourceIds &notUpdatedSourceIds,
WatchedSourceIdsIds &watchedSourceIds)
{
+ NanotraceHR::Tracer tracer{"parse type infos"_t,
+ category(),
+ keyValue("directory source id", directorySourceId),
+ keyValue("directory path", directoryPath),
+ keyValue("module id", moduleId)};
+
for (const QString &typeInfo : typeInfos) {
+ NanotraceHR::Tracer tracer{"parse type info"_t, category(), keyValue("type info", typeInfo)};
+
Utils::PathString qmltypesPath = Utils::PathString::join(
{directoryPath, "/", Utils::SmallString{typeInfo}});
SourceId sourceId = m_pathCache.sourceId(SourcePathView{qmltypesPath});
+ tracer.tick("append qmltypes source id"_t, keyValue("source id", sourceId));
watchedSourceIds.qmltypesSourceIds.push_back(sourceId);
addDependencies(package.moduleDependencies,
sourceId,
joinImports(qmldirDependencies, qmldirImports),
- m_projectStorage);
+ m_projectStorage,
+ "append module dependency"_t,
+ tracer);
+
+ tracer.tick("append module dependenct source source id"_t, keyValue("source id", sourceId));
package.updatedModuleDependencySourceIds.push_back(sourceId);
- auto projectData = package.projectDatas.emplace_back(
+ const auto &directoryInfo = package.directoryInfos.emplace_back(
directorySourceId, sourceId, moduleId, Storage::Synchronization::FileType::QmlTypes);
+ tracer.tick("append project data"_t, keyValue("source id", sourceId));
- parseTypeInfo(projectData, qmltypesPath, package, notUpdatedSourceIds);
+ parseTypeInfo(directoryInfo, qmltypesPath, package, notUpdatedSourceIds);
}
}
-void ProjectStorageUpdater::parseProjectDatas(const Storage::Synchronization::ProjectDatas &projectDatas,
- Storage::Synchronization::SynchronizationPackage &package,
- NotUpdatedSourceIds &notUpdatedSourceIds,
- WatchedSourceIdsIds &watchedSourceIds)
+void ProjectStorageUpdater::parseDirectoryInfos(
+ const Storage::Synchronization::DirectoryInfos &directoryInfos,
+ Storage::Synchronization::SynchronizationPackage &package,
+ NotUpdatedSourceIds &notUpdatedSourceIds,
+ WatchedSourceIdsIds &watchedSourceIds)
{
- for (const Storage::Synchronization::ProjectData &projectData : projectDatas) {
- switch (projectData.fileType) {
+ NanotraceHR::Tracer tracer{"parse project datas"_t, category()};
+
+ for (const Storage::Synchronization::DirectoryInfo &directoryInfo : directoryInfos) {
+ switch (directoryInfo.fileType) {
case Storage::Synchronization::FileType::QmlTypes: {
- watchedSourceIds.qmltypesSourceIds.push_back(projectData.sourceId);
+ watchedSourceIds.qmltypesSourceIds.push_back(directoryInfo.sourceId);
- auto qmltypesPath = m_pathCache.sourcePath(projectData.sourceId);
- parseTypeInfo(projectData, qmltypesPath, package, notUpdatedSourceIds);
+ auto qmltypesPath = m_pathCache.sourcePath(directoryInfo.sourceId);
+ parseTypeInfo(directoryInfo, qmltypesPath, package, notUpdatedSourceIds);
break;
}
case Storage::Synchronization::FileType::QmlDocument: {
- watchedSourceIds.qmlSourceIds.push_back(projectData.sourceId);
+ watchedSourceIds.qmlSourceIds.push_back(directoryInfo.sourceId);
- parseQmlComponent(projectData.sourceId, package, notUpdatedSourceIds);
+ parseQmlComponent(directoryInfo.sourceId, package, notUpdatedSourceIds);
+ break;
}
+ case Storage::Synchronization::FileType::Directory:
+ break;
}
}
}
-auto ProjectStorageUpdater::parseTypeInfo(const Storage::Synchronization::ProjectData &projectData,
+auto ProjectStorageUpdater::parseTypeInfo(const Storage::Synchronization::DirectoryInfo &directoryInfo,
Utils::SmallStringView qmltypesPath,
Storage::Synchronization::SynchronizationPackage &package,
NotUpdatedSourceIds &notUpdatedSourceIds) -> FileState
{
- auto state = fileState(projectData.sourceId, package, notUpdatedSourceIds);
+ NanotraceHR::Tracer tracer{"parse type info"_t,
+ category(),
+ keyValue("qmltypes path", qmltypesPath)};
+
+ auto state = fileState(directoryInfo.sourceId, package, notUpdatedSourceIds);
switch (state) {
case FileState::Changed: {
- package.updatedSourceIds.push_back(projectData.sourceId);
+ tracer.tick("append updated source ids"_t, keyValue("source id", directoryInfo.sourceId));
+ package.updatedSourceIds.push_back(directoryInfo.sourceId);
const auto content = m_fileSystem.contentAsQString(QString{qmltypesPath});
- m_qmlTypesParser.parse(content, package.imports, package.types, projectData);
+ m_qmlTypesParser.parse(content, package.imports, package.types, directoryInfo);
break;
}
case FileState::NotChanged: {
- notUpdatedSourceIds.sourceIds.push_back(projectData.sourceId);
+ tracer.tick("append not updated source ids"_t, keyValue("source id", directoryInfo.sourceId));
+ notUpdatedSourceIds.sourceIds.push_back(directoryInfo.sourceId);
break;
}
case FileState::NotExists:
throw CannotParseQmlTypesFile{};
- break;
}
+ tracer.end(keyValue("state", state));
+
return state;
}
@@ -617,6 +1063,14 @@ void ProjectStorageUpdater::parseQmlComponent(Utils::SmallStringView relativeFil
WatchedSourceIdsIds &watchedSourceIds,
FileState qmldirState)
{
+ NanotraceHR::Tracer tracer{"parse qml component"_t,
+ category(),
+ keyValue("relative file path", relativeFilePath),
+ keyValue("directory path", directoryPath),
+ keyValue("exported types", exportedTypes),
+ keyValue("directory source id", directorySourceId),
+ keyValue("qmldir state", qmldirState)};
+
if (std::find(relativeFilePath.begin(), relativeFilePath.end(), '+') != relativeFilePath.end())
return;
@@ -626,16 +1080,18 @@ void ProjectStorageUpdater::parseQmlComponent(Utils::SmallStringView relativeFil
Storage::Synchronization::Type type;
auto state = fileState(sourceId, package, notUpdatedSourceIds);
+ tracer.tick("append watched qml source id"_t, keyValue("source id", sourceId));
watchedSourceIds.qmlSourceIds.push_back(sourceId);
switch (state) {
case FileState::NotChanged:
if (qmldirState == FileState::NotExists) {
+ tracer.tick("append not updated source id"_t, keyValue("source id", sourceId));
notUpdatedSourceIds.sourceIds.emplace_back(sourceId);
- package.projectDatas.emplace_back(directorySourceId,
- sourceId,
- ModuleId{},
- Storage::Synchronization::FileType::QmlDocument);
+
+ const auto &directoryInfo = package.directoryInfos.emplace_back(
+ directorySourceId, sourceId, ModuleId{}, Storage::Synchronization::FileType::QmlDocument);
+ tracer.tick("append project data"_t, keyValue("project data", directoryInfo));
return;
}
@@ -649,11 +1105,11 @@ void ProjectStorageUpdater::parseQmlComponent(Utils::SmallStringView relativeFil
break;
}
- package.projectDatas.emplace_back(directorySourceId,
- sourceId,
- ModuleId{},
- Storage::Synchronization::FileType::QmlDocument);
+ const auto &directoryInfo = package.directoryInfos.emplace_back(
+ directorySourceId, sourceId, ModuleId{}, Storage::Synchronization::FileType::QmlDocument);
+ tracer.tick("append project data"_t, keyValue("project data", directoryInfo));
+ tracer.tick("append updated source id"_t, keyValue("source id", sourceId));
package.updatedSourceIds.push_back(sourceId);
type.typeName = SourcePath{qmlFilePath}.name();
@@ -661,6 +1117,8 @@ void ProjectStorageUpdater::parseQmlComponent(Utils::SmallStringView relativeFil
type.sourceId = sourceId;
type.exportedTypes = std::move(exportedTypes);
+ tracer.end(keyValue("type", type));
+
package.types.push_back(std::move(type));
}
@@ -668,10 +1126,13 @@ void ProjectStorageUpdater::parseQmlComponent(SourceId sourceId,
Storage::Synchronization::SynchronizationPackage &package,
NotUpdatedSourceIds &notUpdatedSourceIds)
{
+ NanotraceHR::Tracer tracer{"parse qml component"_t, category(), keyValue("source id", sourceId)};
+
auto state = fileState(sourceId, package, notUpdatedSourceIds);
if (state == FileState::NotChanged)
return;
+ tracer.tick("append updated source id"_t, keyValue("source id", sourceId));
package.updatedSourceIds.push_back(sourceId);
if (state == FileState::NotExists)
@@ -687,6 +1148,8 @@ void ProjectStorageUpdater::parseQmlComponent(SourceId sourceId,
type.sourceId = sourceId;
type.changeLevel = Storage::Synchronization::ChangeLevel::ExcludeExportedTypes;
+ tracer.end(keyValue("type", type));
+
package.types.push_back(std::move(type));
}
@@ -733,6 +1196,12 @@ void ProjectStorageUpdater::parseQmlComponents(Components components,
WatchedSourceIdsIds &watchedSourceIdsIds,
FileState qmldirState)
{
+ NanotraceHR::Tracer tracer{"parse qml components"_t,
+ category(),
+ keyValue("directory source id", directorySourceId),
+ keyValue("directory id", directoryId),
+ keyValue("qmldir state", qmldirState)};
+
std::sort(components.begin(), components.end(), [](auto &&first, auto &&second) {
return first.fileName < second.fileName;
});
@@ -760,22 +1229,37 @@ ProjectStorageUpdater::FileState ProjectStorageUpdater::fileState(
Storage::Synchronization::SynchronizationPackage &package,
NotUpdatedSourceIds &notUpdatedSourceIds) const
{
+ NanotraceHR::Tracer tracer{"update property editor paths"_t,
+ category(),
+ keyValue("source id", sourceId)};
+
auto currentFileStatus = m_fileStatusCache.find(sourceId);
if (!currentFileStatus.isValid()) {
+ tracer.tick("append updated file status source id"_t, keyValue("source id", sourceId));
package.updatedFileStatusSourceIds.push_back(sourceId);
+
+ tracer.end(keyValue("state", FileState::NotExists));
return FileState::NotExists;
}
auto projectStorageFileStatus = m_projectStorage.fetchFileStatus(sourceId);
if (!projectStorageFileStatus.isValid() || projectStorageFileStatus != currentFileStatus) {
+ tracer.tick("append file status"_t, keyValue("file status", sourceId));
package.fileStatuses.push_back(currentFileStatus);
+
+ tracer.tick("append updated file status source id"_t, keyValue("source id", sourceId));
package.updatedFileStatusSourceIds.push_back(sourceId);
+
+ tracer.end(keyValue("state", FileState::Changed));
return FileState::Changed;
}
+ tracer.tick("append not updated file status source id"_t, keyValue("source id", sourceId));
notUpdatedSourceIds.fileStatusSourceIds.push_back(sourceId);
+
+ tracer.end(keyValue("state", FileState::NotChanged));
return FileState::NotChanged;
}
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.h b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.h
index 187a2219d0..baecbd6b11 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.h
+++ b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.h
@@ -11,10 +11,15 @@
#include "projectstoragetypes.h"
#include "sourcepath.h"
+#include <modelfwd.h>
+
+#include <tracing/qmldesignertracing.h>
+
#include <qmljs/parser/qmldirparser_p.h>
#include <QStringList>
+#include <map>
#include <vector>
namespace Sqlite {
@@ -27,7 +32,6 @@ class ProjectStorageInterface;
template<typename ProjectStorage, typename Mutex>
class SourcePathCache;
class FileStatusCache;
-template<typename Database>
class ProjectStorage;
class QmlDocumentParserInterface;
class QmlTypesParserInterface;
@@ -35,10 +39,10 @@ class QmlTypesParserInterface;
class ProjectStorageUpdater final : public ProjectStoragePathWatcherNotifierInterface
{
public:
- using PathCache = SourcePathCache<ProjectStorage<Sqlite::Database>, NonLockingMutex>;
+ using PathCache = SourcePathCache<ProjectStorage, NonLockingMutex>;
ProjectStorageUpdater(FileSystemInterface &fileSystem,
- ProjectStorageInterface &projectStorage,
+ ProjectStorageType &projectStorage,
FileStatusCache &fileStatusCache,
PathCache &pathCache,
QmlDocumentParserInterface &qmlDocumentParser,
@@ -57,7 +61,8 @@ public:
void update(QStringList directories,
QStringList qmlTypesPaths,
- const QString &propertyEditorResourcesPath);
+ const QString &propertyEditorResourcesPath,
+ const QStringList &typeAnnotationPaths);
void pathsWithIdsChanged(const std::vector<IdPaths> &idPaths) override;
void pathsChanged(const SourceIds &filePathIds) override;
@@ -138,22 +143,54 @@ private:
WatchedSourceIdsIds &watchedSourceIdsIds);
void updateDirectory(const Utils::PathString &directory,
+ const SourceContextIds &subdirecoriesToIgnore,
Storage::Synchronization::SynchronizationPackage &package,
NotUpdatedSourceIds &notUpdatedSourceIds,
WatchedSourceIdsIds &watchedSourceIdsIds);
+ void updateSubdirectories(const Utils::PathString &directory,
+ SourceId directorySourceId,
+ FileState directoryFileState,
+ const SourceContextIds &subdirecoriesToIgnore,
+ Storage::Synchronization::SynchronizationPackage &package,
+ NotUpdatedSourceIds &notUpdatedSourceIds,
+ WatchedSourceIdsIds &watchedSourceIdsIds);
+ void updateDirectoryChanged(std::string_view directoryPath,
+ FileState qmldirState,
+ SourcePath qmldirSourcePath,
+ SourceId qmldirSourceId,
+ SourceId directorySourceId,
+ SourceContextId directoryId,
+ Storage::Synchronization::SynchronizationPackage &package,
+ NotUpdatedSourceIds &notUpdatedSourceIds,
+ WatchedSourceIdsIds &watchedSourceIdsIds,
+ ProjectStorageTracing::Category::TracerType &tracer);
void updatePropertyEditorPaths(const QString &propertyEditorResourcesPath,
Storage::Synchronization::SynchronizationPackage &package,
NotUpdatedSourceIds &notUpdatedSourceIds);
- void updateTypeAnnotations(const QString &propertyEditorResourcesPath,
+ void updateTypeAnnotations(const QString &directoryPath,
+ Storage::Synchronization::SynchronizationPackage &package,
+ NotUpdatedSourceIds &notUpdatedSourceIds,
+ std::map<SourceId, SmallSourceIds<16>> &updatedSourceIdsDictonary);
+ void updateTypeAnnotationDirectories(Storage::Synchronization::SynchronizationPackage &package,
+ NotUpdatedSourceIds &notUpdatedSourceIds,
+ std::map<SourceId, SmallSourceIds<16>> &updatedSourceIdsDictonary);
+ void updateTypeAnnotations(const QStringList &directoryPath,
Storage::Synchronization::SynchronizationPackage &package,
NotUpdatedSourceIds &notUpdatedSourceIds);
+ void updateTypeAnnotation(const QString &directoryPath,
+ const QString &filePath,
+ SourceId sourceId,
+ SourceId directorySourceId,
+ Storage::Synchronization::SynchronizationPackage &package);
void updatePropertyEditorPath(const QString &path,
Storage::Synchronization::SynchronizationPackage &package,
- SourceId directorySourceId);
+ SourceId directorySourceId,
+ long long pathOffset);
void updatePropertyEditorFilePath(const QString &filePath,
Storage::Synchronization::SynchronizationPackage &package,
- SourceId directorySourceId);
+ SourceId directorySourceId,
+ long long pathOffset);
void parseTypeInfos(const QStringList &typeInfos,
const QList<QmlDirParser::Import> &qmldirDependencies,
const QList<QmlDirParser::Import> &qmldirImports,
@@ -163,11 +200,11 @@ private:
Storage::Synchronization::SynchronizationPackage &package,
NotUpdatedSourceIds &notUpdatedSourceIds,
WatchedSourceIdsIds &watchedSourceIdsIds);
- void parseProjectDatas(const Storage::Synchronization::ProjectDatas &projectDatas,
- Storage::Synchronization::SynchronizationPackage &package,
- NotUpdatedSourceIds &notUpdatedSourceIds,
- WatchedSourceIdsIds &watchedSourceIdsIds);
- FileState parseTypeInfo(const Storage::Synchronization::ProjectData &projectData,
+ void parseDirectoryInfos(const Storage::Synchronization::DirectoryInfos &directoryInfos,
+ Storage::Synchronization::SynchronizationPackage &package,
+ NotUpdatedSourceIds &notUpdatedSourceIds,
+ WatchedSourceIdsIds &watchedSourceIdsIds);
+ FileState parseTypeInfo(const Storage::Synchronization::DirectoryInfo &directoryInfo,
Utils::SmallStringView qmltypesPath,
Storage::Synchronization::SynchronizationPackage &package,
NotUpdatedSourceIds &notUpdatedSourceIds);
@@ -197,7 +234,7 @@ private:
private:
std::vector<IdPaths> m_changedIdPaths;
FileSystemInterface &m_fileSystem;
- ProjectStorageInterface &m_projectStorage;
+ ProjectStorageType &m_projectStorage;
FileStatusCache &m_fileStatusCache;
PathCache &m_pathCache;
QmlDocumentParserInterface &m_qmlDocumentParser;
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparser.cpp b/src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparser.cpp
index f9eb8080f7..4338da62ce 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparser.cpp
+++ b/src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparser.cpp
@@ -10,6 +10,8 @@
#include <sqlitedatabase.h>
+#include <tracing/qmldesignertracing.h>
+
#ifdef QDS_BUILD_QMLPARSER
#include <private/qqmldomtop_p.h>
#endif
@@ -21,6 +23,10 @@ namespace QmlDesigner {
#ifdef QDS_BUILD_QMLPARSER
+constexpr auto category = ProjectStorageTracing::projectStorageUpdaterCategory;
+using NanotraceHR::keyValue;
+using Tracer = ProjectStorageTracing::Category::TracerType;
+
namespace QmlDom = QQmlJS::Dom;
namespace Synchronization = Storage::Synchronization;
@@ -60,23 +66,32 @@ Storage::Import createImport(const QmlDom::Import &qmlImport,
Utils::SmallStringView directoryPath,
QmlDocumentParser::ProjectStorage &storage)
{
+ using Storage::ModuleKind;
using QmlUriKind = QQmlJS::Dom::QmlUri::Kind;
auto &&uri = qmlImport.uri;
- if (uri.kind() == QmlUriKind::RelativePath) {
+ switch (uri.kind()) {
+ case QmlUriKind::AbsolutePath:
+ case QmlUriKind::DirectoryUrl: {
+ auto moduleId = storage.moduleId(Utils::PathString{uri.toString()}, ModuleKind::PathLibrary);
+ return Storage::Import(moduleId, convertVersion(qmlImport.version), sourceId);
+ }
+ case QmlUriKind::RelativePath: {
auto path = createNormalizedPath(directoryPath, uri.localPath());
- auto moduleId = storage.moduleId(createNormalizedPath(directoryPath, uri.localPath()));
+ auto moduleId = storage.moduleId(createNormalizedPath(directoryPath, uri.localPath()),
+ ModuleKind::PathLibrary);
return Storage::Import(moduleId, Storage::Version{}, sourceId);
}
-
- if (uri.kind() == QmlUriKind::ModuleUri) {
- auto moduleId = storage.moduleId(Utils::PathString{uri.moduleUri()});
+ case QmlUriKind::ModuleUri: {
+ auto moduleId = storage.moduleId(Utils::PathString{uri.moduleUri()}, ModuleKind::QmlLibrary);
return Storage::Import(moduleId, convertVersion(qmlImport.version), sourceId);
}
+ case QmlUriKind::Invalid:
+ return Storage::Import{};
+ }
- auto moduleId = storage.moduleId(Utils::PathString{uri.toString()});
- return Storage::Import(moduleId, convertVersion(qmlImport.version), sourceId);
+ return Storage::Import{};
}
QualifiedImports createQualifiedImports(const QList<QmlDom::Import> &qmlImports,
@@ -84,6 +99,11 @@ QualifiedImports createQualifiedImports(const QList<QmlDom::Import> &qmlImports,
Utils::SmallStringView directoryPath,
QmlDocumentParser::ProjectStorage &storage)
{
+ NanotraceHR::Tracer tracer{"create qualified imports"_t,
+ category(),
+ keyValue("sourceId", sourceId),
+ keyValue("directoryPath", directoryPath)};
+
QualifiedImports qualifiedImports;
for (const QmlDom::Import &qmlImport : qmlImports) {
@@ -92,6 +112,8 @@ QualifiedImports createQualifiedImports(const QList<QmlDom::Import> &qmlImports,
createImport(qmlImport, sourceId, directoryPath, storage));
}
+ tracer.end(keyValue("qualified imports", qualifiedImports));
+
return qualifiedImports;
}
@@ -109,11 +131,13 @@ void addImports(Storage::Imports &imports,
}
}
- auto localDirectoryModuleId = storage.moduleId(directoryPath);
+ using Storage::ModuleKind;
+
+ auto localDirectoryModuleId = storage.moduleId(directoryPath, ModuleKind::PathLibrary);
imports.emplace_back(localDirectoryModuleId, Storage::Version{}, sourceId);
++importCount;
- auto qmlModuleId = storage.moduleId("QML");
+ auto qmlModuleId = storage.moduleId("QML", ModuleKind::QmlLibrary);
imports.emplace_back(qmlModuleId, Storage::Version{}, sourceId);
++importCount;
@@ -280,6 +304,11 @@ Storage::Synchronization::Type QmlDocumentParser::parse(const QString &sourceCon
SourceId sourceId,
Utils::SmallStringView directoryPath)
{
+ NanotraceHR::Tracer tracer{"qml document parser parse"_t,
+ category(),
+ keyValue("sourceId", sourceId),
+ keyValue("directoryPath", directoryPath)};
+
Storage::Synchronization::Type type;
using Option = QmlDom::DomEnvironment::Option;
@@ -335,7 +364,7 @@ Storage::Synchronization::Type QmlDocumentParser::parse(const QString &sourceCon
m_storage);
type.prototype = createImportedTypeName(qmlObject.name(), qualifiedImports);
-
+ type.defaultPropertyName = qmlObject.localDefaultPropertyName();
addImports(imports, qmlFile->imports(), sourceId, directoryPath, m_storage);
addPropertyDeclarations(type, qmlObject, qualifiedImports, file);
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparser.h b/src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparser.h
index b8ab4ec4b1..1b494a2f69 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparser.h
+++ b/src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparser.h
@@ -15,7 +15,7 @@ class SourcePathCache;
class QmlDocumentParser final : public QmlDocumentParserInterface
{
public:
- using ProjectStorage = QmlDesigner::ProjectStorage<Sqlite::Database>;
+ using ProjectStorage = QmlDesigner::ProjectStorage;
using PathCache = QmlDesigner::SourcePathCache<ProjectStorage, NonLockingMutex>;
#ifdef QDS_BUILD_QMLPARSER
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/qmltypesparser.cpp b/src/plugins/qmldesigner/designercore/projectstorage/qmltypesparser.cpp
index 3768535299..b3ec4f0024 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/qmltypesparser.cpp
+++ b/src/plugins/qmldesigner/designercore/projectstorage/qmltypesparser.cpp
@@ -5,8 +5,12 @@
#include "projectstorage.h"
+#include <tracing/qmldesignertracing.h>
+
#include <sqlitedatabase.h>
+#include <utils/span.h>
+
#ifdef QDS_BUILD_QMLPARSER
#include <private/qqmldomtop_p.h>
#include <private/qqmljstypedescriptionreader_p.h>
@@ -21,6 +25,10 @@ namespace QmlDesigner {
#ifdef QDS_BUILD_QMLPARSER
+constexpr auto category = ProjectStorageTracing::projectStorageUpdaterCategory;
+using NanotraceHR::keyValue;
+using Tracer = ProjectStorageTracing::Category::TracerType;
+using Storage::ModuleKind;
namespace QmlDom = QQmlJS::Dom;
namespace {
@@ -31,6 +39,8 @@ using Storage::TypeNameString;
ComponentWithoutNamespaces createComponentNameWithoutNamespaces(const QList<QQmlJSExportedScope> &objects)
{
+ NanotraceHR::Tracer tracer{"parse qmltypes file"_t, category()};
+
ComponentWithoutNamespaces componentWithoutNamespaces;
for (const auto &object : objects) {
@@ -46,23 +56,24 @@ ComponentWithoutNamespaces createComponentNameWithoutNamespaces(const QList<QQml
name);
}
+ tracer.end(keyValue("components without namespace", componentWithoutNamespaces));
+
return componentWithoutNamespaces;
}
-void appendImports(Storage::Imports &imports,
- const QString &dependency,
- SourceId sourceId,
- QmlTypesParser::ProjectStorage &storage)
+const Storage::Import &appendImports(Storage::Imports &imports,
+ const QString &dependency,
+ SourceId sourceId,
+ QmlTypesParser::ProjectStorage &storage)
{
auto spaceFound = std::find_if(dependency.begin(), dependency.end(), [](QChar c) {
return c.isSpace();
});
Utils::PathString moduleName{QStringView(dependency.begin(), spaceFound)};
- moduleName.append("-cppnative");
- ModuleId cppModuleId = storage.moduleId(moduleName);
+ ModuleId cppModuleId = storage.moduleId(moduleName, ModuleKind::CppLibrary);
- imports.emplace_back(cppModuleId, Storage::Version{}, sourceId);
+ return imports.emplace_back(cppModuleId, Storage::Version{}, sourceId);
}
void addImports(Storage::Imports &imports,
@@ -71,13 +82,26 @@ void addImports(Storage::Imports &imports,
QmlTypesParser::ProjectStorage &storage,
ModuleId cppModuleId)
{
- for (const QString &dependency : dependencies)
- appendImports(imports, dependency, sourceId, storage);
+ NanotraceHR::Tracer tracer{
+ "add imports"_t,
+ category(),
+ keyValue("source id", sourceId),
+ keyValue("module id", cppModuleId),
+ };
+
+ for (const QString &dependency : dependencies) {
+ const auto &import = appendImports(imports, dependency, sourceId, storage);
+ tracer.tick("append import"_t, keyValue("import", import), keyValue("dependency", dependency));
+ }
- imports.emplace_back(cppModuleId, Storage::Version{}, sourceId);
+ const auto &import = imports.emplace_back(cppModuleId, Storage::Version{}, sourceId);
+ tracer.tick("append import"_t, keyValue("import", import));
- if (ModuleId qmlCppModuleId = storage.moduleId("QML-cppnative"); cppModuleId != qmlCppModuleId)
- imports.emplace_back(qmlCppModuleId, Storage::Version{}, sourceId);
+ if (ModuleId qmlCppModuleId = storage.moduleId("QML", ModuleKind::CppLibrary);
+ cppModuleId != qmlCppModuleId) {
+ const auto &import = imports.emplace_back(qmlCppModuleId, Storage::Version{}, sourceId);
+ tracer.tick("append import"_t, keyValue("import", import));
+ }
}
Storage::TypeTraits createAccessTypeTraits(QQmlJSScope::AccessSemantics accessSematics)
@@ -121,7 +145,8 @@ Storage::Synchronization::ExportedTypes createExports(const QList<QQmlJSScope::E
for (const QQmlJSScope::Export &qmlExport : qmlExports) {
TypeNameString exportedTypeName{qmlExport.type()};
- exportedTypes.emplace_back(storage.moduleId(Utils::SmallString{qmlExport.package()}),
+ exportedTypes.emplace_back(storage.moduleId(Utils::SmallString{qmlExport.package()},
+ ModuleKind::QmlLibrary),
std::move(exportedTypeName),
createVersion(qmlExport.version()));
}
@@ -412,6 +437,11 @@ void addType(Storage::Synchronization::Types &types,
QmlTypesParser::ProjectStorage &storage,
const ComponentWithoutNamespaces &componentNameWithoutNamespace)
{
+ NanotraceHR::Tracer tracer{"add type"_t,
+ category(),
+ keyValue("source id", sourceId),
+ keyValue("module id", cppModuleId)};
+
const auto &component = *exportScope.scope;
auto [functionsDeclarations, signalDeclarations] = createFunctionAndSignals(
@@ -421,7 +451,7 @@ void addType(Storage::Synchronization::Types &types,
auto exports = exportScope.exports;
auto enumerationTypes = addEnumerationTypes(types, typeName, sourceId, cppModuleId, enumerations);
- types.emplace_back(
+ const auto &type = types.emplace_back(
Utils::SmallStringView{typeName},
Storage::Synchronization::ImportedType{TypeNameString{component.baseTypeName()}},
Storage::Synchronization::ImportedType{TypeNameString{component.extensionTypeName()}},
@@ -431,24 +461,61 @@ void addType(Storage::Synchronization::Types &types,
createProperties(component.ownProperties(), enumerationTypes, componentNameWithoutNamespace),
std::move(functionsDeclarations),
std::move(signalDeclarations),
- createEnumeration(enumerations));
+ createEnumeration(enumerations),
+ Storage::Synchronization::ChangeLevel::Full,
+ Utils::SmallString{component.ownDefaultPropertyName()});
+ tracer.end(keyValue("type", type));
+}
+
+using namespace Qt::StringLiterals;
+
+constexpr auto skipLists = std::make_tuple(
+ std::pair{std::pair{"QtQuick.Templates"_sv, ModuleKind::CppLibrary}, std::array{"QQuickItem"_L1}});
+
+Utils::span<const QLatin1StringView> getSkipList(const Storage::Module &module)
+{
+ static constexpr Utils::span<const QLatin1StringView> emptySkipList;
+ auto currentSkipList = emptySkipList;
+
+ std::apply(
+ [&](const auto &entry) {
+ if (entry.first.first == module.name && entry.first.second == module.kind)
+ currentSkipList = entry.second;
+ },
+ skipLists);
+
+ return currentSkipList;
+}
+
+bool skipType(const QQmlJSExportedScope &object, Utils::span<const QLatin1StringView> skipList)
+{
+ return std::any_of(skipList.begin(), skipList.end(), [&](const QLatin1StringView skip) {
+ return object.scope->internalName() == skip;
+ });
}
void addTypes(Storage::Synchronization::Types &types,
- const Storage::Synchronization::ProjectData &projectData,
+ const Storage::Synchronization::DirectoryInfo &directoryInfo,
const QList<QQmlJSExportedScope> &objects,
QmlTypesParser::ProjectStorage &storage,
const ComponentWithoutNamespaces &componentNameWithoutNamespaces)
{
+ NanotraceHR::Tracer tracer{"add types"_t, category()};
types.reserve(Utils::usize(objects) + types.size());
- for (const auto &object : objects)
+ const auto skipList = getSkipList(storage.module(directoryInfo.moduleId));
+
+ for (const auto &object : objects) {
+ if (skipType(object, skipList))
+ continue;
+
addType(types,
- projectData.sourceId,
- projectData.moduleId,
+ directoryInfo.sourceId,
+ directoryInfo.moduleId,
object,
storage,
componentNameWithoutNamespaces);
+ }
}
} // namespace
@@ -456,8 +523,10 @@ void addTypes(Storage::Synchronization::Types &types,
void QmlTypesParser::parse(const QString &sourceContent,
Storage::Imports &imports,
Storage::Synchronization::Types &types,
- const Storage::Synchronization::ProjectData &projectData)
+ const Storage::Synchronization::DirectoryInfo &directoryInfo)
{
+ NanotraceHR::Tracer tracer{"qmltypes parser parse"_t, category()};
+
QQmlJSTypeDescriptionReader reader({}, sourceContent);
QList<QQmlJSExportedScope> components;
QStringList dependencies;
@@ -467,8 +536,8 @@ void QmlTypesParser::parse(const QString &sourceContent,
auto componentNameWithoutNamespaces = createComponentNameWithoutNamespaces(components);
- addImports(imports, projectData.sourceId, dependencies, m_storage, projectData.moduleId);
- addTypes(types, projectData, components, m_storage, componentNameWithoutNamespaces);
+ addImports(imports, directoryInfo.sourceId, dependencies, m_storage, directoryInfo.moduleId);
+ addTypes(types, directoryInfo, components, m_storage, componentNameWithoutNamespaces);
}
#else
@@ -476,7 +545,7 @@ void QmlTypesParser::parse(const QString &sourceContent,
void QmlTypesParser::parse([[maybe_unused]] const QString &sourceContent,
[[maybe_unused]] Storage::Imports &imports,
[[maybe_unused]] Storage::Synchronization::Types &types,
- [[maybe_unused]] const Storage::Synchronization::ProjectData &projectData)
+ [[maybe_unused]] const Storage::Synchronization::DirectoryInfo &directoryInfo)
{}
#endif
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/qmltypesparser.h b/src/plugins/qmldesigner/designercore/projectstorage/qmltypesparser.h
index 7c41925f30..c73a429f91 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/qmltypesparser.h
+++ b/src/plugins/qmldesigner/designercore/projectstorage/qmltypesparser.h
@@ -4,6 +4,7 @@
#pragma once
#include "nonlockingmutex.h"
+#include "projectstoragefwd.h"
#include "qmltypesparserinterface.h"
namespace Sqlite {
@@ -12,17 +13,13 @@ class Database;
namespace QmlDesigner {
-template<typename Database>
-class ProjectStorage;
-
template<typename ProjectStorage, typename Mutex>
class SourcePathCache;
class QmlTypesParser final : public QmlTypesParserInterface
{
public:
- using ProjectStorage = QmlDesigner::ProjectStorage<Sqlite::Database>;
-
+ using ProjectStorage = QmlDesigner::ProjectStorage;
#ifdef QDS_BUILD_QMLPARSER
QmlTypesParser(ProjectStorage &storage)
: m_storage{storage}
@@ -34,7 +31,7 @@ public:
void parse(const QString &sourceContent,
Storage::Imports &imports,
Storage::Synchronization::Types &types,
- const Storage::Synchronization::ProjectData &projectData) override;
+ const Storage::Synchronization::DirectoryInfo &directoryInfo) override;
private:
#ifdef QDS_BUILD_QMLPARSER
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/qmltypesparserinterface.h b/src/plugins/qmldesigner/designercore/projectstorage/qmltypesparserinterface.h
index cdc7cd54d7..c0880cf5c6 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/qmltypesparserinterface.h
+++ b/src/plugins/qmldesigner/designercore/projectstorage/qmltypesparserinterface.h
@@ -15,7 +15,7 @@ public:
virtual void parse(const QString &sourceContent,
Storage::Imports &imports,
Storage::Synchronization::Types &types,
- const Storage::Synchronization::ProjectData &projectData)
+ const Storage::Synchronization::DirectoryInfo &directoryInfo)
= 0;
protected:
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/sourcepath.h b/src/plugins/qmldesigner/designercore/projectstorage/sourcepath.h
index 837e58d48a..fa550a4d52 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/sourcepath.h
+++ b/src/plugins/qmldesigner/designercore/projectstorage/sourcepath.h
@@ -7,6 +7,8 @@
#include <utils/smallstring.h>
+#include <QVarLengthArray>
+
namespace QmlDesigner {
class SourcePath : public Utils::PathString
@@ -117,10 +119,17 @@ public:
std::ptrdiff_t slashIndex() const { return m_slashIndex; }
+ template<typename String>
+ friend void convertToString(String &string, const SourcePath &path)
+ {
+ convertToString(string, path.toStringView());
+ }
+
private:
std::ptrdiff_t m_slashIndex = -1;
};
using SourcePaths = std::vector<SourcePath>;
-
+template<std::size_t size>
+using SmallSourcePaths = QVarLengthArray<SourcePath, size>;
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/sourcepathcachetypes.h b/src/plugins/qmldesigner/designercore/projectstorage/sourcepathcachetypes.h
index 5feaf30d00..1ef8ba7f21 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/sourcepathcachetypes.h
+++ b/src/plugins/qmldesigner/designercore/projectstorage/sourcepathcachetypes.h
@@ -125,4 +125,6 @@ public:
SourceContextId sourceContextId;
};
+using SourceNameAndSourceContextIds = std::vector<SourceNameAndSourceContextId>;
+
} // namespace QmlDesigner::Cache
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/storagecache.h b/src/plugins/qmldesigner/designercore/projectstorage/storagecache.h
index 85c6147d2c..32ecb1c3f7 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/storagecache.h
+++ b/src/plugins/qmldesigner/designercore/projectstorage/storagecache.h
@@ -313,7 +313,7 @@ private:
return entries.end();
}
- auto value = *found;
+ const auto &value = *found;
if (value == view) {
return found;
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/typeannotationreader.cpp b/src/plugins/qmldesigner/designercore/projectstorage/typeannotationreader.cpp
index b829e9db36..71eba94966 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/typeannotationreader.cpp
+++ b/src/plugins/qmldesigner/designercore/projectstorage/typeannotationreader.cpp
@@ -27,11 +27,11 @@ constexpr auto propertyElementName = "Property"_L1;
constexpr auto extraFileElementName = "ExtraFile"_L1;
} // namespace
-Synchronization::TypeAnnotations TypeAnnotationReader::parseTypeAnnotation(const QString &content,
- const QString &directoryPath,
- SourceId sourceId)
+Synchronization::TypeAnnotations TypeAnnotationReader::parseTypeAnnotation(
+ const QString &content, const QString &directoryPath, SourceId sourceId, SourceId directorySourceId)
{
m_sourceId = sourceId;
+ m_directorySourceId = directorySourceId;
m_directoryPath = directoryPath;
m_parserState = ParsingDocument;
if (!SimpleAbstractStreamReader::readFromSource(content)) {
@@ -178,8 +178,15 @@ TypeAnnotationReader::ParserSate TypeAnnotationReader::readDocument(const QStrin
TypeAnnotationReader::ParserSate TypeAnnotationReader::readMetaInfoRootElement(const QString &name)
{
if (name == typeElementName) {
- m_typeAnnotations.emplace_back(m_sourceId);
+ auto &annotation = m_typeAnnotations.emplace_back(m_sourceId, m_directorySourceId);
+ annotation.traits.canBeDroppedInFormEditor = FlagIs::True;
+ annotation.traits.canBeDroppedInNavigator = FlagIs::True;
+ annotation.traits.isMovable = FlagIs::True;
+ annotation.traits.isResizable = FlagIs::True;
+ annotation.traits.hasFormEditorItem = FlagIs::True;
+ annotation.traits.visibleInLibrary = FlagIs::True;
m_itemLibraryEntries = json::array();
+
return ParsingType;
} else {
addErrorInvalidType(name);
@@ -258,7 +265,8 @@ void TypeAnnotationReader::readTypeProperty(QStringView name, const QVariant &va
auto [moduleName, typeName] = decomposeTypePath(fullTypeName);
m_typeAnnotations.back().typeName = typeName;
- m_typeAnnotations.back().moduleId = m_projectStorage.moduleId(moduleName);
+ m_typeAnnotations.back().moduleId = m_projectStorage.moduleId(moduleName,
+ ModuleKind::QmlLibrary);
} else if (name == "icon"_L1) {
m_typeAnnotations.back().iconPath = absoluteFilePathForDocument(value.toString());
@@ -277,7 +285,7 @@ void TypeAnnotationReader::readItemLibraryEntryProperty(QStringView name, const
} else if (name == "category"_L1) {
m_itemLibraryEntries.back()["category"] = value;
} else if (name == "libraryIcon"_L1) {
- m_itemLibraryEntries.back()["iconPath"] = value;
+ m_itemLibraryEntries.back()["iconPath"] = absoluteFilePathForDocument(variant.toString());
} else if (name == "version"_L1) {
// setVersion(value.toString());
} else if (name == "requiredImport"_L1) {
@@ -304,7 +312,7 @@ QString deEscape(const QString &value)
QVariant deEscapeVariant(const QVariant &value)
{
- if (value.typeId() == QVariant::String)
+ if (value.typeId() == QMetaType::QString)
return deEscape(value.toString());
return value;
}
@@ -427,8 +435,8 @@ void TypeAnnotationReader::setVersion(const QString &versionNumber)
int minor = 0;
if (!versionNumber.isEmpty()) {
- int val;
- bool ok;
+ int val = -1;
+ bool ok = false;
if (versionNumber.contains('.'_L1)) {
val = versionNumber.split('.'_L1).constFirst().toInt(&ok);
major = ok ? val : major;
@@ -459,9 +467,9 @@ using json = nlohmann::json;
out = json::array({});
out.push_back(property.name);
out.push_back(property.type);
- if (property.value.type() == QVariant::String)
+ if (property.value.typeId() == QMetaType::QString)
out.push_back(Utils::PathString{property.value.toString()});
- else if (property.value.type() == QVariant::Int || property.value.type() == QVariant::LongLong)
+ else if (property.value.typeId() == QMetaType::Int || property.value.typeId() == QMetaType::LongLong)
out.push_back(property.value.toLongLong());
else
out.push_back(property.value.toDouble());
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/typeannotationreader.h b/src/plugins/qmldesigner/designercore/projectstorage/typeannotationreader.h
index 9332d5bed9..a320493ee2 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/typeannotationreader.h
+++ b/src/plugins/qmldesigner/designercore/projectstorage/typeannotationreader.h
@@ -49,7 +49,8 @@ public:
Synchronization::TypeAnnotations parseTypeAnnotation(const QString &content,
const QString &directoryPath,
- SourceId sourceId);
+ SourceId sourceId,
+ SourceId directorySourceId);
QStringList errors();
@@ -124,6 +125,7 @@ private:
json m_itemLibraryEntries;
Property m_currentProperty;
SourceId m_sourceId;
+ SourceId m_directorySourceId;
};
} // namespace QmlDesigner::Storage
diff --git a/src/plugins/qmldesigner/designercore/tracing/qmldesignertracing.cpp b/src/plugins/qmldesigner/designercore/tracing/qmldesignertracing.cpp
index d49c6156a6..cbe7b0ec38 100644
--- a/src/plugins/qmldesigner/designercore/tracing/qmldesignertracing.cpp
+++ b/src/plugins/qmldesigner/designercore/tracing/qmldesignertracing.cpp
@@ -3,40 +3,48 @@
#include "qmldesignertracing.h"
+#include <sqlitebasestatement.h>
+
namespace QmlDesigner {
+
+using namespace NanotraceHR::Literals;
+
namespace Tracing {
namespace {
using TraceFile = NanotraceHR::TraceFile<tracingStatus()>;
-TraceFile &traceFile()
+auto &traceFile()
{
- static TraceFile traceFile{"qml_designer.json"};
- return traceFile;
+ if constexpr (std::is_same_v<Sqlite::TraceFile, TraceFile>) {
+ return Sqlite::traceFile();
+ } else {
+ static TraceFile traceFile{"tracing.json"};
+ return traceFile;
+ }
}
} // namespace
EventQueue &eventQueue()
{
- thread_local NanotraceHR::EventQueueData<NanotraceHR::StringViewTraceEvent, 10000, tracingStatus()>
- stringViewEventQueueData(traceFile());
+ thread_local NanotraceHR::EventQueue<NanotraceHR::StringViewTraceEvent, tracingStatus()>
+ stringViewEventQueue(traceFile());
- return stringViewEventQueueData;
+ return stringViewEventQueue;
}
EventQueueWithStringArguments &eventQueueWithStringArguments()
{
- thread_local NanotraceHR::
- EventQueueData<NanotraceHR::StringViewWithStringArgumentsTraceEvent, 1000, tracingStatus()>
- stringViewWithStringArgumentsEventQueueData(traceFile());
+ thread_local NanotraceHR::EventQueue<NanotraceHR::StringViewWithStringArgumentsTraceEvent, tracingStatus()>
+ stringViewWithStringArgumentsEventQueue(traceFile());
- return stringViewWithStringArgumentsEventQueueData;
+ return stringViewWithStringArgumentsEventQueue;
}
StringEventQueue &stringEventQueue()
{
- thread_local NanotraceHR::EventQueueData<NanotraceHR::StringTraceEvent, 1000, tracingStatus()> eventQueue(
+ thread_local NanotraceHR::EventQueue<NanotraceHR::StringTraceEvent, tracingStatus()> eventQueue(
traceFile());
return eventQueue;
@@ -46,7 +54,6 @@ StringEventQueue &stringEventQueue()
namespace ModelTracing {
namespace {
-using namespace NanotraceHR::Literals;
thread_local Category category_{"model"_t, Tracing::stringEventQueue(), category};
@@ -58,4 +65,36 @@ Category &category()
}
} // namespace ModelTracing
+
+namespace ProjectStorageTracing {
+
+Category &projectStorageCategory()
+{
+ thread_local Category category{"project storage"_t,
+ Tracing::eventQueueWithStringArguments(),
+ projectStorageCategory};
+
+ return category;
+}
+
+Category &projectStorageUpdaterCategory()
+{
+ thread_local Category category{"project storage updater"_t,
+ Tracing::eventQueueWithStringArguments(),
+ projectStorageCategory};
+
+ return category;
+}
+
+} // namespace ProjectStorageTracing
+
+namespace MetaInfoTracing {
+Category &category()
+{
+ thread_local Category category_{"meta info"_t, Tracing::eventQueueWithStringArguments(), category};
+
+ return category_;
+}
+} // namespace MetaInfoTracing
+
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/tracing/qmldesignertracing.h b/src/plugins/qmldesigner/designercore/tracing/qmldesignertracing.h
index 31058260d6..899ceb6cd2 100644
--- a/src/plugins/qmldesigner/designercore/tracing/qmldesignertracing.h
+++ b/src/plugins/qmldesigner/designercore/tracing/qmldesignertracing.h
@@ -44,4 +44,38 @@ using AsynchronousToken = Category::AsynchronousTokenType;
[[gnu::pure]] QMLDESIGNERCORE_EXPORT Category &category();
} // namespace ModelTracing
+
+namespace ProjectStorageTracing {
+constexpr NanotraceHR::Tracing projectStorageTracingStatus()
+{
+#ifdef ENABLE_PROJECT_STORAGE_TRACING
+ return NanotraceHR::Tracing::IsEnabled;
+#else
+ return NanotraceHR::Tracing::IsDisabled;
+#endif
+}
+
+using Category = NanotraceHR::StringViewWithStringArgumentsCategory<projectStorageTracingStatus()>;
+
+[[gnu::pure]] Category &projectStorageCategory();
+
+[[gnu::pure]] Category &projectStorageUpdaterCategory();
+
+} // namespace ProjectStorageTracing
+
+namespace MetaInfoTracing {
+constexpr NanotraceHR::Tracing tracingStatus()
+{
+#ifdef ENABLE_METAINFO_TRACING
+ return NanotraceHR::Tracing::IsEnabled;
+#else
+ return NanotraceHR::Tracing::IsDisabled;
+#endif
+}
+
+using Category = NanotraceHR::StringViewWithStringArgumentsCategory<tracingStatus()>;
+
+[[gnu::pure]] Category &category();
+
+} // namespace MetaInfoTracing
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/uniquename.cpp b/src/plugins/qmldesigner/designercore/uniquename.cpp
new file mode 100644
index 0000000000..d7506164db
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/uniquename.cpp
@@ -0,0 +1,165 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#include "uniquename.h"
+
+#include <utils/span.h>
+
+#include <QFileInfo>
+#include <QRegularExpression>
+
+namespace QmlDesigner::UniqueName {
+
+using namespace Qt::Literals;
+
+constexpr QLatin1StringView keywords[] {
+ "anchors"_L1, "as"_L1, "baseState"_L1,
+ "border"_L1, "bottom"_L1, "break"_L1,
+ "case"_L1, "catch"_L1, "clip"_L1,
+ "color"_L1, "continue"_L1, "data"_L1,
+ "debugger"_L1, "default"_L1, "delete"_L1,
+ "do"_L1, "else"_L1, "enabled"_L1,
+ "finally"_L1, "flow"_L1, "focus"_L1,
+ "font"_L1, "for"_L1, "function"_L1,
+ "height"_L1, "if"_L1, "import"_L1,
+ "in"_L1, "instanceof"_L1, "item"_L1,
+ "layer"_L1, "left"_L1, "margin"_L1,
+ "new"_L1, "opacity"_L1, "padding"_L1,
+ "parent"_L1, "print"_L1, "rect"_L1,
+ "return"_L1, "right"_L1, "scale"_L1,
+ "shaderInfo"_L1, "source"_L1, "sprite"_L1,
+ "spriteSequence"_L1, "state"_L1, "switch"_L1,
+ "text"_L1, "this"_L1, "throw"_L1,
+ "top"_L1, "try"_L1, "typeof"_L1,
+ "var"_L1, "visible"_L1, "void"_L1,
+ "while"_L1, "with"_L1, "x"_L1,
+ "y"_L1
+};
+
+namespace {
+
+QString toCamelCase(const QString &input)
+{
+ QString result = input.at(0).toLower();
+ bool capitalizeNext = false;
+
+ for (const QChar &c : Utils::span{input}.subspan(1)) {
+ bool isValidChar = c.isLetterOrNumber() || c == '_';
+ if (isValidChar)
+ result += capitalizeNext ? c.toUpper() : c;
+
+ capitalizeNext = !isValidChar;
+ }
+
+ return result;
+}
+
+} // namespace
+
+/**
+ * @brief Generates a unique name based on the provided name.
+ *
+ * This method iteratively generates a name by appending suffixes until a unique name is found.
+ * The uniqueness of the generated name is determined by the provided predicate function.
+ *
+ * @param name The original name to be made unique.
+ * @param predicate A function that checks if a name exists. Returns true if the name exists,
+ * false if name is unique.
+ * @return A unique name derived from the provided name.
+ */
+QString generate(const QString &name, std::function<bool(const QString &)> predicate)
+{
+ if (!predicate(name))
+ return name;
+
+ // match prefix and number (including zero padding) parts
+ static QRegularExpression rgx("(\\D*?)(\\d+)$");
+ QRegularExpressionMatch match = rgx.match(name);
+
+ QString prefix;
+ int number = 0;
+ int padding = 0;
+
+ if (match.hasMatch()) {
+ // Split the name into prefix and number
+ prefix = match.captured(1);
+ QString numberStr = match.captured(2);
+ number = numberStr.toInt();
+ padding = numberStr.size();
+ } else {
+ prefix = name;
+ }
+
+ QString nameTemplate = "%1%2";
+ QString newName;
+ do {
+ newName = nameTemplate.arg(prefix).arg(++number, padding, 10, QChar('0'));
+ } while (predicate(newName));
+
+ return newName;
+}
+
+/**
+ * @brief Generates a unique path based on the provided path. If the path belongs to a file, the
+ * filename or if it's a directory, the directory name will be adjusted to ensure uniqueness.
+ *
+ * This method appends a numerical suffix (or increment it if it exists) to the filename or
+ * directory name if necessary to make it unique.
+ *
+ * @param path The original path to be made unique.
+ * @return A unique path derived from the provided path.
+ */
+QString generatePath(const QString &path)
+{
+ // Remove the trailing slash if it exists (otherwise QFileInfo::path() returns empty)
+ QString adjustedPath = path;
+ if (adjustedPath.endsWith('/'))
+ adjustedPath.chop(1);
+
+ QFileInfo fileInfo = QFileInfo(adjustedPath);
+ QString baseName = fileInfo.baseName();
+ QString suffix = fileInfo.completeSuffix();
+ if (!suffix.isEmpty())
+ suffix.prepend('.');
+
+ QString parentDir = fileInfo.path();
+ QString pathTemplate = parentDir + "/%1" + suffix;
+
+ QString uniqueBaseName = UniqueName::generate(baseName, [&] (const QString &currName) {
+ return QFileInfo::exists(pathTemplate.arg(currName));
+ });
+
+ return pathTemplate.arg(uniqueBaseName);
+}
+
+/**
+ * @brief Generates a unique ID based on the provided id
+ *
+ * This works similar to get() with additional restrictions:
+ * - Removes non-Latin1 characters
+ * - Removes spaces
+ * - Ensures the first letter is lowercase
+ * - Converts spaces to camel case
+ * - Prepends an underscore if id starts with a number or is a reserved word
+ *
+ * @param id The original id to be made unique.
+ * @return A unique Id (when predicate() returns false)
+ */
+QString generateId(const QString &id, std::function<bool(const QString &)> predicate)
+{
+ // remove non word (non A-Z, a-z, 0-9) or space characters
+ QString newId = id.trimmed();
+
+ newId = toCamelCase(newId);
+
+ // prepend _ if starts with a digit or invalid id (such as reserved words)
+ if (newId.at(0).isDigit() || std::binary_search(std::begin(keywords), std::end(keywords), newId))
+ newId.prepend('_');
+
+ if (!predicate)
+ return newId;
+
+ return UniqueName::generate(newId, predicate);
+}
+
+} // namespace QmlDesigner::UniqueName
diff --git a/src/plugins/qmldesigner/designercore/uniquename.h b/src/plugins/qmldesigner/designercore/uniquename.h
new file mode 100644
index 0000000000..85927c4514
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/uniquename.h
@@ -0,0 +1,17 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#pragma once
+
+#include <qmldesignercorelib_exports.h>
+
+#include <QString>
+
+namespace QmlDesigner::UniqueName {
+
+QString generate(const QString &name, std::function<bool(const QString &)> predicate);
+QString generatePath(const QString &path);
+QMLDESIGNERCORE_EXPORT QString generateId(const QString &id,
+ std::function<bool(const QString &)> predicate = {});
+
+} // namespace QmlDesigner::UniqueName