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/include/import.h4
-rw-r--r--src/plugins/qmldesigner/designercore/include/projectstorageids.h2
-rw-r--r--src/plugins/qmldesigner/designercore/include/rewriterview.h2
-rw-r--r--src/plugins/qmldesigner/designercore/metainfo/metainforeader.cpp3
-rw-r--r--src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp2
-rw-r--r--src/plugins/qmldesigner/designercore/model/import.cpp2
-rw-r--r--src/plugins/qmldesigner/designercore/model/qmlobjectnode.cpp2
-rw-r--r--src/plugins/qmldesigner/designercore/model/qmltimelinekeyframegroup.cpp2
-rw-r--r--src/plugins/qmldesigner/designercore/model/rewriterview.cpp33
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/projectstorage.h873
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/projectstorageexceptions.h6
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/projectstorageinterface.h11
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/projectstoragetypes.h166
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.cpp86
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.h24
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparser.cpp197
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparser.h63
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/qmltypesparser.cpp307
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/qmltypesparser.h63
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/qmltypesparserinterface.h2
20 files changed, 1325 insertions, 525 deletions
diff --git a/src/plugins/qmldesigner/designercore/include/import.h b/src/plugins/qmldesigner/designercore/include/import.h
index 99612fa2ad..c797a19ae4 100644
--- a/src/plugins/qmldesigner/designercore/include/import.h
+++ b/src/plugins/qmldesigner/designercore/include/import.h
@@ -25,6 +25,8 @@
#pragma once
+#include <utils/porting.h>
+
#include <QString>
#include <QStringList>
#include <QMetaType>
@@ -74,7 +76,7 @@ private:
QStringList m_importPathList;
};
-QMLDESIGNERCORE_EXPORT uint qHash(const Import &import);
+QMLDESIGNERCORE_EXPORT Utils::QHashValueType qHash(const Import &import);
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/include/projectstorageids.h b/src/plugins/qmldesigner/designercore/include/projectstorageids.h
index 76f547eeb1..765f2c9c65 100644
--- a/src/plugins/qmldesigner/designercore/include/projectstorageids.h
+++ b/src/plugins/qmldesigner/designercore/include/projectstorageids.h
@@ -37,7 +37,7 @@ public:
constexpr explicit BasicId() = default;
- BasicId(const char *) = delete;
+ constexpr BasicId(const char *) = delete;
constexpr explicit BasicId(InternalIntergerType id)
: id{id}
diff --git a/src/plugins/qmldesigner/designercore/include/rewriterview.h b/src/plugins/qmldesigner/designercore/include/rewriterview.h
index ac251ef064..44e804f25d 100644
--- a/src/plugins/qmldesigner/designercore/include/rewriterview.h
+++ b/src/plugins/qmldesigner/designercore/include/rewriterview.h
@@ -177,6 +177,8 @@ public:
ModelNode getNodeForCanonicalIndex(int index);
+ void sanitizeModel();
+
signals:
void modelInterfaceProjectUpdated();
diff --git a/src/plugins/qmldesigner/designercore/metainfo/metainforeader.cpp b/src/plugins/qmldesigner/designercore/metainfo/metainforeader.cpp
index 28d8e02826..46ad1270e7 100644
--- a/src/plugins/qmldesigner/designercore/metainfo/metainforeader.cpp
+++ b/src/plugins/qmldesigner/designercore/metainfo/metainforeader.cpp
@@ -89,6 +89,7 @@ void MetaInfoReader::setQualifcation(const TypeName &qualification)
void MetaInfoReader::elementStart(const QString &name, const QmlJS::SourceLocation &nameLocation)
{
+ Q_UNUSED(nameLocation)
switch (parserState()) {
case ParsingDocument: setParserState(readDocument(name)); break;
case ParsingMetaInfo: setParserState(readMetaInfoRootElement(name)); break;
@@ -133,6 +134,8 @@ void MetaInfoReader::propertyDefinition(const QString &name,
const QVariant &value,
const QmlJS::SourceLocation &valueLocation)
{
+ Q_UNUSED(nameLocation)
+ Q_UNUSED(valueLocation)
switch (parserState()) {
case ParsingType: readTypeProperty(name, value); break;
case ParsingImports: readImportsProperty(name, value); break;
diff --git a/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp b/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp
index 33693210a9..97ff30850f 100644
--- a/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp
+++ b/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp
@@ -1505,6 +1505,8 @@ QVariant NodeMetaInfo::propertyCastedValue(const PropertyName &propertyName, con
return variant.toFloat();
} else if (typeName == "<cpp>.int") {
return variant.toInt();
+ } else if (typeName == "<cpp>.bool") {
+ return variant.toBool();
} else if (copyVariant.convert(typeId)) {
return copyVariant;
}
diff --git a/src/plugins/qmldesigner/designercore/model/import.cpp b/src/plugins/qmldesigner/designercore/model/import.cpp
index d895b07764..1c217bf47b 100644
--- a/src/plugins/qmldesigner/designercore/model/import.cpp
+++ b/src/plugins/qmldesigner/designercore/model/import.cpp
@@ -109,7 +109,7 @@ int Import::majorFromVersion(const QString &version)
return version.split('.').first().toInt();
}
-uint qHash(const Import &import)
+Utils::QHashValueType qHash(const Import &import)
{
return ::qHash(import.url()) ^ ::qHash(import.file()) ^ ::qHash(import.version()) ^ ::qHash(import.alias());
}
diff --git a/src/plugins/qmldesigner/designercore/model/qmlobjectnode.cpp b/src/plugins/qmldesigner/designercore/model/qmlobjectnode.cpp
index 55305c72d1..2445042fbb 100644
--- a/src/plugins/qmldesigner/designercore/model/qmlobjectnode.cpp
+++ b/src/plugins/qmldesigner/designercore/model/qmlobjectnode.cpp
@@ -332,7 +332,7 @@ static void removeStateOperationsForChildren(const QmlObjectNode &node)
stateOperation.modelNode().destroy(); //remove of belonging StatesOperations
}
- for (const QmlObjectNode &childNode : node.modelNode().directSubModelNodes()) {
+ for (const QmlObjectNode childNode : node.modelNode().directSubModelNodes()) {
removeStateOperationsForChildren(childNode);
}
}
diff --git a/src/plugins/qmldesigner/designercore/model/qmltimelinekeyframegroup.cpp b/src/plugins/qmldesigner/designercore/model/qmltimelinekeyframegroup.cpp
index 85eb51de44..924a4e0ee6 100644
--- a/src/plugins/qmldesigner/designercore/model/qmltimelinekeyframegroup.cpp
+++ b/src/plugins/qmldesigner/designercore/model/qmltimelinekeyframegroup.cpp
@@ -310,7 +310,7 @@ QList<QmlTimelineKeyframeGroup> QmlTimelineKeyframeGroup::allInvalidTimelineKeyf
QTC_ASSERT(view->rootModelNode().isValid(), return ret);
const auto groups = view->rootModelNode().subModelNodesOfType("QtQuick.Timeline.KeyframeGroup");
- for (const QmlTimelineKeyframeGroup &group : groups) {
+ for (const QmlTimelineKeyframeGroup group : groups) {
if (group.isDangling())
ret.append(group);
}
diff --git a/src/plugins/qmldesigner/designercore/model/rewriterview.cpp b/src/plugins/qmldesigner/designercore/model/rewriterview.cpp
index af066b81c2..e33c82b124 100644
--- a/src/plugins/qmldesigner/designercore/model/rewriterview.cpp
+++ b/src/plugins/qmldesigner/designercore/model/rewriterview.cpp
@@ -39,6 +39,8 @@
#include <modelnodepositionstorage.h>
#include <modelnode.h>
#include <nodeproperty.h>
+#include <qmlobjectnode.h>
+#include <qmltimelinekeyframegroup.h>
#ifndef QMLDESIGNER_TEST
#include <qmldesignerplugin.h>
@@ -57,6 +59,7 @@
#include <utility>
#include <vector>
+#include <algorithm>
using namespace QmlDesigner::Internal;
@@ -658,6 +661,36 @@ ModelNode RewriterView::getNodeForCanonicalIndex(int index)
return m_canonicalIntModelNode.value(index);
}
+void RewriterView::sanitizeModel()
+{
+ if (inErrorState())
+ return;
+
+ QmlObjectNode root = rootModelNode();
+
+ QTC_ASSERT(root.isValid(), return);
+
+ QList<ModelNode> danglingNodes;
+
+ const auto danglingStates = root.allInvalidStateOperations();
+ const auto danglingKeyframeGroups = QmlTimelineKeyframeGroup::allInvalidTimelineKeyframeGroups(this);
+
+ std::transform(danglingStates.begin(),
+ danglingStates.end(),
+ std::back_inserter(danglingNodes),
+ [](const auto &node) { return node.modelNode(); });
+
+ std::transform(danglingKeyframeGroups.begin(),
+ danglingKeyframeGroups.end(),
+ std::back_inserter(danglingNodes),
+ [](const auto &node) { return node.modelNode(); });
+
+ executeInTransaction("RewriterView::sanitizeModel", [&]() {
+ for (auto node : std::as_const(danglingNodes))
+ node.destroy();
+ });
+}
+
Internal::ModelNodePositionStorage *RewriterView::positionStorage() const
{
return m_positionStorage.data();
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstorage.h b/src/plugins/qmldesigner/designercore/projectstorage/projectstorage.h
index 2a428c6533..5df23b7385 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/projectstorage.h
+++ b/src/plugins/qmldesigner/designercore/projectstorage/projectstorage.h
@@ -28,6 +28,7 @@
#include "projectstorageexceptions.h"
#include "projectstorageinterface.h"
#include "sourcepathcachetypes.h"
+#include "storagecache.h"
#include <sqlitealgorithms.h>
#include <sqlitetable.h>
@@ -35,7 +36,9 @@
#include <utils/algorithm.h>
#include <utils/optional.h>
+#include <utils/set_algorithm.h>
+#include <algorithm>
#include <tuple>
namespace QmlDesigner {
@@ -53,65 +56,73 @@ public:
ProjectStorage(Database &database, bool isInitialized)
: database{database}
, initializer{database, isInitialized}
- {}
+ {
+ moduleCache.populate();
+ }
- void synchronize(Storage::Modules modules,
- Storage::Imports imports,
- Storage::Types types,
- SourceIds sourceIds,
- FileStatuses fileStatuses) override
+ void synchronize(Storage::SynchronizationPackage package) override
{
Sqlite::ImmediateTransaction transaction{database};
- std::vector<AliasPropertyDeclaration> insertedAliasPropertyDeclarations;
- std::vector<AliasPropertyDeclaration> updatedAliasPropertyDeclarations;
+ AliasPropertyDeclarations insertedAliasPropertyDeclarations;
+ AliasPropertyDeclarations updatedAliasPropertyDeclarations;
+
+ AliasPropertyDeclarations relinkableAliasPropertyDeclarations;
+ PropertyDeclarations relinkablePropertyDeclarations;
+ Prototypes relinkablePrototypes;
+ TypeIds deletedTypeIds;
TypeIds updatedTypeIds;
- updatedTypeIds.reserve(types.size());
+ updatedTypeIds.reserve(package.types.size());
TypeIds typeIdsToBeDeleted;
- auto sourceIdValues = Utils::transform<std::vector>(sourceIds, [](SourceId sourceId) {
+ auto sourceIdValues = Utils::transform<std::vector>(package.sourceIds, [](SourceId sourceId) {
return &sourceId;
});
std::sort(sourceIdValues.begin(), sourceIdValues.end());
- synchronizeFileStatuses(fileStatuses, sourceIdValues);
- synchronizeModules(modules, typeIdsToBeDeleted, sourceIdValues);
- synchronizeImports(imports, sourceIdValues);
- synchronizeTypes(types,
+ synchronizeFileStatuses(package.fileStatuses, sourceIdValues);
+ synchronizeImports(package.imports, sourceIdValues);
+ synchronizeTypes(package.types,
updatedTypeIds,
insertedAliasPropertyDeclarations,
- updatedAliasPropertyDeclarations);
-
- deleteNotUpdatedTypes(updatedTypeIds, sourceIdValues, typeIdsToBeDeleted);
+ updatedAliasPropertyDeclarations,
+ relinkableAliasPropertyDeclarations,
+ relinkablePropertyDeclarations,
+ relinkablePrototypes,
+ sourceIdValues);
+
+ deleteNotUpdatedTypes(updatedTypeIds,
+ sourceIdValues,
+ typeIdsToBeDeleted,
+ relinkableAliasPropertyDeclarations,
+ relinkablePropertyDeclarations,
+ relinkablePrototypes,
+ deletedTypeIds);
+
+ relink(relinkableAliasPropertyDeclarations,
+ relinkablePropertyDeclarations,
+ relinkablePrototypes,
+ deletedTypeIds);
linkAliases(insertedAliasPropertyDeclarations, updatedAliasPropertyDeclarations);
transaction.commit();
}
- ModuleId fetchModuleId(Utils::SmallStringView moduleName)
+ ModuleId moduleId(Utils::SmallStringView moduleName) override
{
- Sqlite::DeferredTransaction transaction{database};
-
- ModuleId moduleId = fetchModuleIdUnguarded(moduleName);
-
- transaction.commit();
-
- return moduleId;
+ return moduleCache.id(moduleName);
}
- ModuleIds fetchModuleIds(const Storage::Modules &modules)
+ Utils::SmallString moduleName(ModuleId moduleId)
{
- Sqlite::DeferredTransaction transaction{database};
-
- ModuleIds moduleIds = fetchModuleIdsUnguarded(modules);
-
- transaction.commit();
+ if (!moduleId)
+ throw ModuleDoesNotExists{};
- return moduleIds;
+ return moduleCache.value(moduleId);
}
PropertyDeclarationId fetchPropertyDeclarationByTypeIdAndName(TypeId typeId,
@@ -132,9 +143,9 @@ public:
static_cast<void *>(moduleIds.data()), static_cast<long long>(moduleIds.size()), name);
}
- TypeId fetchTypeIdByName(ModuleId moduleId, Utils::SmallStringView name)
+ TypeId fetchTypeIdByName(SourceId sourceId, Utils::SmallStringView name)
{
- return selectTypeIdByModuleIdAndNameStatement.template valueWithTransaction<TypeId>(&moduleId,
+ return selectTypeIdBySourceIdAndNameStatement.template valueWithTransaction<TypeId>(&sourceId,
name);
}
@@ -283,11 +294,6 @@ public:
return writeSourceId(sourceContextId, sourceName);
}
- auto fetchAllModules() const
- {
- return selectAllModulesStatement.template valuesWithTransaction<Storage::Module>(128);
- }
-
auto fetchAllFileStatuses() const
{
return selectAllFileStatusesStatement.template rangeWithTransaction<FileStatus>();
@@ -299,9 +305,79 @@ public:
&sourceId);
}
- SourceIds fetchSourceDependencieIds(SourceId sourceId) const override { return {}; }
+ Storage::ProjectDatas fetchProjectDatas(SourceId sourceId) const override
+ {
+ return Storage::ProjectDatas{};
+ }
private:
+ class ModuleStorageAdapter
+ {
+ public:
+ auto fetchId(const Utils::SmallStringView name) { return storage.fetchModuleId(name); }
+
+ auto fetchValue(ModuleId id) { return storage.fetchModuleName(id); }
+
+ auto fetchAll() { return storage.fetchAllModules(); }
+
+ ProjectStorage &storage;
+ };
+
+ class Module : public StorageCacheEntry<Utils::PathString, Utils::SmallStringView, ModuleId>
+ {
+ using Base = StorageCacheEntry<Utils::PathString, Utils::SmallStringView, ModuleId>;
+
+ public:
+ using Base::Base;
+
+ friend bool operator==(const Module &first, const Module &second)
+ {
+ return first.id == second.id && first.value == second.value;
+ }
+ };
+
+ friend ModuleStorageAdapter;
+
+ static bool moduleNameLess(Utils::SmallStringView first, Utils::SmallStringView second) noexcept
+ {
+ return Utils::reverseCompare(first, second) < 0;
+ }
+
+ using ModuleCache = StorageCache<Utils::PathString,
+ Utils::SmallStringView,
+ ModuleId,
+ ModuleStorageAdapter,
+ NonLockingMutex,
+ moduleNameLess,
+ Module>;
+
+ ModuleId fetchModuleId(Utils::SmallStringView moduleName)
+ {
+ Sqlite::DeferredTransaction transaction{database};
+
+ ModuleId moduleId = fetchModuleIdUnguarded(moduleName);
+
+ transaction.commit();
+
+ return moduleId;
+ }
+
+ auto fetchModuleName(ModuleId id)
+ {
+ Sqlite::DeferredTransaction transaction{database};
+
+ auto moduleName = fetchModuleNameUnguarded(id);
+
+ transaction.commit();
+
+ return moduleName;
+ }
+
+ auto fetchAllModules() const
+ {
+ return selectAllModulesStatement.template valuesWithTransaction<Module>(128);
+ }
+
class AliasPropertyDeclaration
{
public:
@@ -318,6 +394,13 @@ private:
, aliasPropertyDeclarationId{aliasPropertyDeclarationId}
{}
+ friend bool operator<(const AliasPropertyDeclaration &first,
+ const AliasPropertyDeclaration &second)
+ {
+ return std::tie(first.typeId, first.propertyDeclarationId)
+ < std::tie(second.typeId, second.propertyDeclarationId);
+ }
+
public:
TypeId typeId;
PropertyDeclarationId propertyDeclarationId;
@@ -326,6 +409,8 @@ private:
PropertyDeclarationId aliasPropertyDeclarationId;
};
+ using AliasPropertyDeclarations = std::vector<AliasPropertyDeclaration>;
+
class PropertyDeclaration
{
public:
@@ -345,12 +430,20 @@ private:
, importedTypeNameId{importedTypeNameId}
{}
+ friend bool operator<(const PropertyDeclaration &first, const PropertyDeclaration &second)
+ {
+ return std::tie(first.typeId, first.propertyDeclarationId)
+ < std::tie(second.typeId, second.propertyDeclarationId);
+ }
+
public:
TypeId typeId;
PropertyDeclarationId propertyDeclarationId;
ImportedTypeNameId importedTypeNameId;
};
+ using PropertyDeclarations = std::vector<PropertyDeclaration>;
+
class Prototype
{
public:
@@ -359,15 +452,58 @@ private:
, prototypeNameId{std::move(prototypeNameId)}
{}
+ friend bool operator<(Prototype first, Prototype second)
+ {
+ return first.typeId < second.typeId;
+ }
+
public:
TypeId typeId;
ImportedTypeNameId prototypeNameId;
};
+ using Prototypes = std::vector<Prototype>;
+
+ template<typename Type>
+ struct TypeCompare
+ {
+ bool operator()(const Type &type, TypeId typeId) { return type.typeId < typeId; };
+
+ bool operator()(TypeId typeId, const Type &type) { return typeId < type.typeId; };
+
+ bool operator()(const Type &first, const Type &second)
+ {
+ return first.typeId < second.typeId;
+ };
+ };
+
+ template<typename Property>
+ struct PropertyCompare
+ {
+ bool operator()(const Property &property, PropertyDeclarationId id)
+ {
+ return property.propertyDeclarationId < id;
+ };
+
+ bool operator()(PropertyDeclarationId id, const Property &property)
+ {
+ return id < property.propertyDeclarationId;
+ };
+
+ bool operator()(const Property &first, const Property &second)
+ {
+ return first.propertyDeclarationId < second.propertyDeclarationId;
+ };
+ };
+
void synchronizeTypes(Storage::Types &types,
TypeIds &updatedTypeIds,
- std::vector<AliasPropertyDeclaration> &insertedAliasPropertyDeclarations,
- std::vector<AliasPropertyDeclaration> &updatedAliasPropertyDeclarations)
+ AliasPropertyDeclarations &insertedAliasPropertyDeclarations,
+ AliasPropertyDeclarations &updatedAliasPropertyDeclarations,
+ AliasPropertyDeclarations &relinkableAliasPropertyDeclarations,
+ PropertyDeclarations &relinkablePropertyDeclarations,
+ Prototypes &relinkablePrototypes,
+ const std::vector<int> &sourceIdValues)
{
Storage::ExportedTypes exportedTypes;
exportedTypes.reserve(types.size() * 3);
@@ -381,16 +517,19 @@ private:
extractExportedTypes(typeId, type, exportedTypes);
}
- synchronizeExportedTypes(updatedTypeIds, exportedTypes);
+ synchronizeExportedTypes(sourceIdValues,
+ updatedTypeIds,
+ exportedTypes,
+ relinkableAliasPropertyDeclarations,
+ relinkablePropertyDeclarations,
+ relinkablePrototypes);
- for (auto &&type : types)
- syncPrototypes(type);
-
- for (auto &&type : types)
- resetRemovedAliasPropertyDeclarationsToNull(type.typeId, type.propertyDeclarations);
-
- for (auto &&type : types)
- syncDeclarations(type, insertedAliasPropertyDeclarations, updatedAliasPropertyDeclarations);
+ syncPrototypes(types, relinkablePrototypes);
+ resetRemovedAliasPropertyDeclarationsToNull(types, relinkableAliasPropertyDeclarations);
+ syncDeclarations(types,
+ insertedAliasPropertyDeclarations,
+ updatedAliasPropertyDeclarations,
+ relinkablePropertyDeclarations);
}
void synchronizeFileStatuses(FileStatuses &fileStatuses, const std::vector<int> &sourceIdValues)
@@ -428,43 +567,10 @@ private:
Sqlite::insertUpdateDelete(range, fileStatuses, compareKey, insert, update, remove);
}
- void synchronizeModules(Storage::Modules &modules,
- TypeIds &typeIdsToBeDeleted,
- const std::vector<int> &moduleIdValues)
- {
- auto compareKey = [](auto &&first, auto &&second) {
- return first.sourceId.id - second.sourceId.id;
- };
-
- std::sort(modules.begin(), modules.end(), [&](auto &&first, auto &&second) {
- return compareKey(first, second) < 0;
- });
-
- auto range = selectModulesForIdsStatement.template range<Storage::ModuleView>(
- Utils::span(moduleIdValues));
-
- auto insert = [&](Storage::Module &module) {
- insertModuleStatement.write(module.name, &module.sourceId);
- };
-
- auto update = [&](const Storage::ModuleView &moduleView, Storage::Module &module) {
- if (moduleView.name != module.name)
- updateModuleStatement.write(&moduleView.sourceId, module.name);
- };
-
- auto remove = [&](const Storage::ModuleView &moduleView) {
- deleteModuleStatement.write(&moduleView.sourceId);
- selectTypeIdsForModuleIdStatement.readTo(typeIdsToBeDeleted, &moduleView.sourceId);
- };
-
- Sqlite::insertUpdateDelete(range, modules, compareKey, insert, update, remove);
- }
-
void synchronizeImports(Storage::Imports &imports, std::vector<int> &sourceIdValues)
{
deleteDocumentImportsForDeletedDocuments(imports, sourceIdValues);
- addModuleIdToImports(imports);
synchronizeDocumentImports(imports, sourceIdValues);
}
@@ -487,50 +593,28 @@ private:
deleteDocumentImportsWithSourceIdsStatement.write(Utils::span{documentSourceIdsToBeDeleted});
}
- void synchronizeModulesAndUpdatesModuleIds(Storage::Modules &modules,
- TypeIds &typeIdsToBeDeleted,
- const std::vector<int> &moduleIds)
+ ModuleId fetchModuleIdUnguarded(Utils::SmallStringView name) const
{
- auto compareKey = [](auto &&first, auto &&second) {
- return first.sourceId.id - second.sourceId.id;
- };
-
- std::sort(modules.begin(), modules.end(), [&](auto &&first, auto &&second) {
- return compareKey(first, second) < 0;
- });
-
- auto range = selectModulesForIdsStatement.template range<Storage::ModuleView>(
- Utils::span(moduleIds));
-
- auto insert = [&](Storage::Module &module) {
- insertModuleStatement.write(module.name, &module.sourceId);
- };
-
- auto update = [&](const Storage::ModuleView &moduleView, Storage::Module &module) {
- if (moduleView.name != module.name)
- updateModuleStatement.write(&moduleView.sourceId, module.name);
- };
+ auto moduleId = selectModuleIdByNameStatement.template value<ModuleId>(name);
- auto remove = [&](const Storage::ModuleView &moduleView) {
- deleteModuleStatement.write(&moduleView.sourceId);
- selectTypeIdsForModuleIdStatement.readTo(typeIdsToBeDeleted, &moduleView.sourceId);
- };
+ if (moduleId)
+ return moduleId;
- Sqlite::insertUpdateDelete(range, modules, compareKey, insert, update, remove);
+ return insertModuleNameStatement.template value<ModuleId>(name);
}
- ModuleId fetchModuleIdUnguarded(const Storage::Module &module) const
+ auto fetchModuleNameUnguarded(ModuleId id) const
{
- return fetchModuleIdUnguarded(module.name);
- }
+ auto moduleName = selectModuleNameStatement.template value<Utils::PathString>(&id);
- ModuleId fetchModuleIdUnguarded(Utils::SmallStringView name) const
- {
- return selectModuleIdByNameStatement.template value<ModuleId>(name);
+ if (moduleName.empty())
+ throw ModuleDoesNotExists{};
+
+ return moduleName;
}
void handleAliasPropertyDeclarationsWithPropertyType(
- TypeId typeId, std::vector<AliasPropertyDeclaration> &relinkableAliasPropertyDeclarations)
+ TypeId typeId, AliasPropertyDeclarations &relinkableAliasPropertyDeclarations)
{
auto callback = [&](long long typeId,
long long propertyDeclarationId,
@@ -555,8 +639,7 @@ private:
}
void prepareLinkingOfAliasPropertiesDeclarationsWithAliasId(
- PropertyDeclarationId aliasId,
- std::vector<AliasPropertyDeclaration> &relinkableAliasPropertyDeclarations)
+ PropertyDeclarationId aliasId, AliasPropertyDeclarations &relinkableAliasPropertyDeclarations)
{
auto callback = [&](long long propertyDeclarationId,
long long propertyImportedTypeNameId,
@@ -578,14 +661,14 @@ private:
&aliasId);
}
- void handlePropertyDeclarationWithPropertyType(
- TypeId typeId, std::vector<PropertyDeclaration> &relinkablePropertyDeclarations)
+ void handlePropertyDeclarationWithPropertyType(TypeId typeId,
+ PropertyDeclarations &relinkablePropertyDeclarations)
{
updatesPropertyDeclarationPropertyTypeToNullStatement.readTo(relinkablePropertyDeclarations,
&typeId);
}
- void handlePrototypes(TypeId prototypeId, std::vector<Prototype> &relinkablePrototypes)
+ void handlePrototypes(TypeId prototypeId, Prototypes &relinkablePrototypes)
{
auto callback = [&](long long typeId, long long prototypeNameId) {
relinkablePrototypes.emplace_back(TypeId{typeId}, ImportedTypeNameId{prototypeNameId});
@@ -597,9 +680,9 @@ private:
}
void deleteType(TypeId typeId,
- std::vector<AliasPropertyDeclaration> &relinkableAliasPropertyDeclarations,
- std::vector<PropertyDeclaration> &relinkablePropertyDeclarations,
- std::vector<Prototype> &relinkablePrototypes)
+ AliasPropertyDeclarations &relinkableAliasPropertyDeclarations,
+ PropertyDeclarations &relinkablePropertyDeclarations,
+ Prototypes &relinkablePrototypes)
{
handlePropertyDeclarationWithPropertyType(typeId, relinkablePropertyDeclarations);
handleAliasPropertyDeclarationsWithPropertyType(typeId, relinkableAliasPropertyDeclarations);
@@ -612,72 +695,85 @@ private:
deleteTypeStatement.write(&typeId);
}
- void relinkAliasPropertyDeclarations(
- const std::vector<AliasPropertyDeclaration> &aliasPropertyDeclarations,
- const TypeIds &deletedTypeIds)
+ void relinkAliasPropertyDeclarations(AliasPropertyDeclarations &aliasPropertyDeclarations,
+ const TypeIds &deletedTypeIds)
{
- for (const AliasPropertyDeclaration &alias : aliasPropertyDeclarations) {
- if (std::binary_search(deletedTypeIds.begin(), deletedTypeIds.end(), alias.typeId))
- continue;
+ std::sort(aliasPropertyDeclarations.begin(), aliasPropertyDeclarations.end());
- auto typeId = fetchTypeId(alias.aliasImportedTypeNameId);
+ Utils::set_greedy_difference(
+ aliasPropertyDeclarations.cbegin(),
+ aliasPropertyDeclarations.cend(),
+ deletedTypeIds.begin(),
+ deletedTypeIds.end(),
+ [&](const AliasPropertyDeclaration &alias) {
+ auto typeId = fetchTypeId(alias.aliasImportedTypeNameId);
- if (!typeId)
- throw TypeNameDoesNotExists{};
+ if (!typeId)
+ throw TypeNameDoesNotExists{};
- auto [propertyTypeId, aliasId, propertyTraits] = fetchPropertyDeclarationByTypeIdAndNameUngarded(
- typeId, alias.aliasPropertyName);
+ auto [propertyTypeId, aliasId, propertyTraits] = fetchPropertyDeclarationByTypeIdAndNameUngarded(
+ typeId, alias.aliasPropertyName);
- updatePropertyDeclarationWithAliasAndTypeStatement.write(&alias.propertyDeclarationId,
- &propertyTypeId,
- propertyTraits,
- &alias.aliasImportedTypeNameId,
- &aliasId);
- }
+ updatePropertyDeclarationWithAliasAndTypeStatement.write(&alias.propertyDeclarationId,
+ &propertyTypeId,
+ propertyTraits,
+ &alias.aliasImportedTypeNameId,
+ &aliasId);
+ },
+ TypeCompare<AliasPropertyDeclaration>{});
}
- void relinkPropertyDeclarations(const std::vector<PropertyDeclaration> &relinkablePropertyDeclaration,
+ void relinkPropertyDeclarations(PropertyDeclarations &relinkablePropertyDeclaration,
const TypeIds &deletedTypeIds)
{
- for (const PropertyDeclaration &property : relinkablePropertyDeclaration) {
- if (std::binary_search(deletedTypeIds.begin(), deletedTypeIds.end(), property.typeId))
- continue;
+ std::sort(relinkablePropertyDeclaration.begin(), relinkablePropertyDeclaration.end());
- TypeId propertyTypeId = fetchTypeId(property.importedTypeNameId);
+ Utils::set_greedy_difference(
+ relinkablePropertyDeclaration.cbegin(),
+ relinkablePropertyDeclaration.cend(),
+ deletedTypeIds.begin(),
+ deletedTypeIds.end(),
+ [&](const PropertyDeclaration &property) {
+ TypeId propertyTypeId = fetchTypeId(property.importedTypeNameId);
- if (!propertyTypeId)
- throw TypeNameDoesNotExists{};
+ if (!propertyTypeId)
+ throw TypeNameDoesNotExists{};
- updatePropertyDeclarationTypeStatement.write(&property.propertyDeclarationId,
- &propertyTypeId);
- }
+ updatePropertyDeclarationTypeStatement.write(&property.propertyDeclarationId,
+ &propertyTypeId);
+ },
+ TypeCompare<PropertyDeclaration>{});
}
- void relinkPrototypes(std::vector<Prototype> relinkablePrototypes, const TypeIds &deletedTypeIds)
+ void relinkPrototypes(Prototypes &relinkablePrototypes, const TypeIds &deletedTypeIds)
{
- for (const Prototype &prototype : relinkablePrototypes) {
- if (std::binary_search(deletedTypeIds.begin(), deletedTypeIds.end(), prototype.typeId))
- continue;
+ std::sort(relinkablePrototypes.begin(), relinkablePrototypes.end());
- TypeId prototypeId = fetchTypeId(prototype.prototypeNameId);
+ Utils::set_greedy_difference(
+ relinkablePrototypes.cbegin(),
+ relinkablePrototypes.cend(),
+ deletedTypeIds.begin(),
+ deletedTypeIds.end(),
+ [&](const Prototype &prototype) {
+ TypeId prototypeId = fetchTypeId(prototype.prototypeNameId);
- if (!prototypeId)
- throw TypeNameDoesNotExists{};
+ if (!prototypeId)
+ throw TypeNameDoesNotExists{};
- updateTypePrototypeStatement.write(&prototype.typeId, &prototypeId);
- checkForPrototypeChainCycle(prototype.typeId);
- }
+ updateTypePrototypeStatement.write(&prototype.typeId, &prototypeId);
+ checkForPrototypeChainCycle(prototype.typeId);
+ },
+ TypeCompare<Prototype>{});
}
void deleteNotUpdatedTypes(const TypeIds &updatedTypeIds,
const std::vector<int> &sourceIdValues,
- const TypeIds &typeIdsToBeDeleted)
+ const TypeIds &typeIdsToBeDeleted,
+ AliasPropertyDeclarations &relinkableAliasPropertyDeclarations,
+ PropertyDeclarations &relinkablePropertyDeclarations,
+ Prototypes &relinkablePrototypes,
+ TypeIds &deletedTypeIds)
{
- std::vector<AliasPropertyDeclaration> relinkableAliasPropertyDeclarations;
- std::vector<PropertyDeclaration> relinkablePropertyDeclarations;
- std::vector<Prototype> relinkablePrototypes;
- TypeIds deletedTypeIds;
-
auto updatedTypeIdValues = Utils::transform<std::vector>(updatedTypeIds, [](TypeId typeId) {
return &typeId;
});
@@ -696,7 +792,13 @@ private:
Utils::span(updatedTypeIdValues));
for (TypeId typeIdToBeDeleted : typeIdsToBeDeleted)
callback(&typeIdToBeDeleted);
+ }
+ void relink(AliasPropertyDeclarations &relinkableAliasPropertyDeclarations,
+ PropertyDeclarations &relinkablePropertyDeclarations,
+ Prototypes &relinkablePrototypes,
+ TypeIds &deletedTypeIds)
+ {
std::sort(deletedTypeIds.begin(), deletedTypeIds.end());
relinkPrototypes(relinkablePrototypes, deletedTypeIds);
@@ -704,7 +806,7 @@ private:
relinkAliasPropertyDeclarations(relinkableAliasPropertyDeclarations, deletedTypeIds);
}
- void linkAliasPropertyDeclarationAliasIds(const std::vector<AliasPropertyDeclaration> &aliasDeclarations)
+ void linkAliasPropertyDeclarationAliasIds(const AliasPropertyDeclarations &aliasDeclarations)
{
for (const auto &aliasDeclaration : aliasDeclarations) {
auto aliasTypeId = fetchTypeId(aliasDeclaration.aliasImportedTypeNameId);
@@ -722,7 +824,7 @@ private:
}
}
- void updateAliasPropertyDeclarationValues(const std::vector<AliasPropertyDeclaration> &aliasDeclarations)
+ void updateAliasPropertyDeclarationValues(const AliasPropertyDeclarations &aliasDeclarations)
{
for (const auto &aliasDeclaration : aliasDeclarations) {
updatetPropertiesDeclarationValuesOfAliasStatement.write(
@@ -732,14 +834,14 @@ private:
}
}
- void checkAliasPropertyDeclarationCycles(const std::vector<AliasPropertyDeclaration> &aliasDeclarations)
+ void checkAliasPropertyDeclarationCycles(const AliasPropertyDeclarations &aliasDeclarations)
{
for (const auto &aliasDeclaration : aliasDeclarations)
checkForAliasChainCycle(aliasDeclaration.propertyDeclarationId);
}
- void linkAliases(const std::vector<AliasPropertyDeclaration> &insertedAliasPropertyDeclarations,
- const std::vector<AliasPropertyDeclaration> &updatedAliasPropertyDeclarations)
+ void linkAliases(const AliasPropertyDeclarations &insertedAliasPropertyDeclarations,
+ const AliasPropertyDeclarations &updatedAliasPropertyDeclarations)
{
linkAliasPropertyDeclarationAliasIds(insertedAliasPropertyDeclarations);
linkAliasPropertyDeclarationAliasIds(updatedAliasPropertyDeclarations);
@@ -751,16 +853,25 @@ private:
updateAliasPropertyDeclarationValues(updatedAliasPropertyDeclarations);
}
- void synchronizeExportedTypes(const TypeIds &typeIds, Storage::ExportedTypes &exportedTypes)
+ void synchronizeExportedTypes(const std::vector<int> &sourceIdValues,
+ const TypeIds &updatedTypeIds,
+ Storage::ExportedTypes &exportedTypes,
+ AliasPropertyDeclarations &relinkableAliasPropertyDeclarations,
+ PropertyDeclarations &relinkablePropertyDeclarations,
+ Prototypes &relinkablePrototypes)
{
std::sort(exportedTypes.begin(), exportedTypes.end(), [](auto &&first, auto &&second) {
return std::tie(first.moduleId, first.name, first.version)
< std::tie(second.moduleId, second.name, second.version);
});
- auto range = selectExportedTypesForTypeIdStatement.template range<Storage::ExportedTypeView>(
- const_cast<void *>(static_cast<const void *>(typeIds.data())),
- static_cast<long long>(typeIds.size()));
+ Utils::span typeIdValues{static_cast<const TypeIds::value_type::DatabaseType *>(
+ &updatedTypeIds.data()->id),
+ updatedTypeIds.size()};
+
+ auto range = selectExportedTypesForSourceIdsStatement
+ .template range<Storage::ExportedTypeView>(Utils::span{sourceIdValues},
+ typeIdValues);
auto compareKey = [](const Storage::ExportedTypeView &view,
const Storage::ExportedType &type) -> long long {
@@ -780,53 +891,55 @@ private:
};
auto insert = [&](const Storage::ExportedType &type) {
- if (type.version) {
- upsertExportedTypeNamesWithVersionStatement.write(&type.moduleId,
- type.name,
- static_cast<long long>(
- Storage::TypeNameKind::Exported),
- type.version.major.value,
- type.version.minor.value,
- &type.typeId);
-
- } else if (type.version.major) {
- upsertExportedTypeNamesWithMajorVersionStatement
- .write(&type.moduleId,
- type.name,
- static_cast<long long>(Storage::TypeNameKind::Exported),
- type.version.major.value,
- &type.typeId);
- } else {
- upsertExportedTypeNamesWithoutVersionStatement
- .write(&type.moduleId,
- type.name,
- static_cast<long long>(Storage::TypeNameKind::Exported),
- &type.typeId);
+ 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::ModuleDoesNotExists{};
}
};
auto update = [&](const Storage::ExportedTypeView &view, const Storage::ExportedType &type) {
- if (view.typeId != type.typeId)
+ if (view.typeId != type.typeId) {
+ handlePropertyDeclarationWithPropertyType(view.typeId, relinkablePropertyDeclarations);
+ handleAliasPropertyDeclarationsWithPropertyType(view.typeId,
+ relinkableAliasPropertyDeclarations);
+ handlePrototypes(view.typeId, relinkablePrototypes);
updateExportedTypeNameTypeIdStatement.write(&view.exportedTypeNameId, &type.typeId);
+ }
};
auto remove = [&](const Storage::ExportedTypeView &view) {
+ handlePropertyDeclarationWithPropertyType(view.typeId, relinkablePropertyDeclarations);
+ handleAliasPropertyDeclarationsWithPropertyType(view.typeId,
+ relinkableAliasPropertyDeclarations);
+ handlePrototypes(view.typeId, relinkablePrototypes);
deleteExportedTypeNameStatement.write(&view.exportedTypeNameId);
};
Sqlite::insertUpdateDelete(range, exportedTypes, compareKey, insert, update, remove);
}
- void upsertNativeType(ModuleId moduleId, Utils::SmallStringView name, TypeId typeId)
- {
- upsertExportedTypeNameStatement.write(&moduleId,
- name,
- static_cast<long long>(Storage::TypeNameKind::Native),
- &typeId);
- }
-
void synchronizePropertyDeclarationsInsertAlias(
- std::vector<AliasPropertyDeclaration> &insertedAliasPropertyDeclarations,
+ AliasPropertyDeclarations &insertedAliasPropertyDeclarations,
const Storage::PropertyDeclaration &value,
SourceId sourceId,
TypeId typeId)
@@ -872,7 +985,7 @@ private:
}
void synchronizePropertyDeclarationsUpdateAlias(
- std::vector<AliasPropertyDeclaration> &updatedAliasPropertyDeclarations,
+ AliasPropertyDeclarations &updatedAliasPropertyDeclarations,
const Storage::PropertyDeclarationView &view,
const Storage::PropertyDeclaration &value,
SourceId sourceId)
@@ -887,7 +1000,8 @@ private:
void synchronizePropertyDeclarationsUpdateProperty(const Storage::PropertyDeclarationView &view,
const Storage::PropertyDeclaration &value,
- SourceId sourceId)
+ SourceId sourceId,
+ PropertyDeclarationIds &propertyDeclarationIds)
{
auto propertyImportedTypeNameId = fetchImportedTypeNameId(value.typeName, sourceId);
@@ -906,14 +1020,15 @@ private:
&propertyImportedTypeNameId);
updatePropertyAliasDeclarationRecursivelyWithTypeAndTraitsStatement
.write(&view.id, &propertyTypeId, static_cast<int>(value.traits));
+ propertyDeclarationIds.push_back(view.id);
}
- void synchronizePropertyDeclarations(
- TypeId typeId,
- Storage::PropertyDeclarations &propertyDeclarations,
- SourceId sourceId,
- std::vector<AliasPropertyDeclaration> &insertedAliasPropertyDeclarations,
- std::vector<AliasPropertyDeclaration> &updatedAliasPropertyDeclarations)
+ void synchronizePropertyDeclarations(TypeId typeId,
+ Storage::PropertyDeclarations &propertyDeclarations,
+ SourceId sourceId,
+ AliasPropertyDeclarations &insertedAliasPropertyDeclarations,
+ AliasPropertyDeclarations &updatedAliasPropertyDeclarations,
+ PropertyDeclarationIds &propertyDeclarationIds)
{
std::sort(propertyDeclarations.begin(),
propertyDeclarations.end(),
@@ -947,8 +1062,12 @@ private:
view,
value,
sourceId);
+ propertyDeclarationIds.push_back(view.id);
} else {
- synchronizePropertyDeclarationsUpdateProperty(view, value, sourceId);
+ synchronizePropertyDeclarationsUpdateProperty(view,
+ value,
+ sourceId,
+ propertyDeclarationIds);
}
};
@@ -962,14 +1081,20 @@ private:
}
deletePropertyDeclarationStatement.write(&view.id);
+ propertyDeclarationIds.push_back(view.id);
};
Sqlite::insertUpdateDelete(range, propertyDeclarations, compareKey, insert, update, remove);
}
- void resetRemovedAliasPropertyDeclarationsToNull(TypeId typeId,
- Storage::PropertyDeclarations &aliasDeclarations)
+ void resetRemovedAliasPropertyDeclarationsToNull(Storage::Type &type,
+ PropertyDeclarationIds &propertyDeclarationIds)
{
+ if (type.changeLevel == Storage::ChangeLevel::Minimal)
+ return;
+
+ Storage::PropertyDeclarations &aliasDeclarations = type.propertyDeclarations;
+
class AliasPropertyDeclarationView
{
public:
@@ -992,7 +1117,7 @@ private:
});
auto range = selectPropertyDeclarationsWithAliasForTypeIdStatement
- .template range<AliasPropertyDeclarationView>(&typeId);
+ .template range<AliasPropertyDeclarationView>(&type.typeId);
auto compareKey = [](const AliasPropertyDeclarationView &view,
const Storage::PropertyDeclaration &value) {
@@ -1006,29 +1131,24 @@ private:
auto remove = [&](const AliasPropertyDeclarationView &view) {
updatePropertyDeclarationAliasIdToNullStatement.write(&view.id);
+ propertyDeclarationIds.push_back(view.id);
};
Sqlite::insertUpdateDelete(range, aliasDeclarations, compareKey, insert, update, remove);
}
- ModuleIds fetchModuleIdsUnguarded(const Storage::Modules &modules)
+ void resetRemovedAliasPropertyDeclarationsToNull(
+ Storage::Types &types, AliasPropertyDeclarations &relinkableAliasPropertyDeclarations)
{
- ModuleIds moduleIds;
- moduleIds.reserve(moduleIds.size());
+ PropertyDeclarationIds propertyDeclarationIds;
+ propertyDeclarationIds.reserve(types.size());
- for (auto &&module : modules)
- moduleIds.push_back(fetchModuleIdUnguarded(module));
+ for (auto &&type : types)
+ resetRemovedAliasPropertyDeclarationsToNull(type, propertyDeclarationIds);
- return moduleIds;
- }
-
- void addModuleIdToImports(Storage::Imports &imports)
- {
- for (Storage::Import &import : imports) {
- import.moduleId = fetchModuleIdUnguarded(import.name);
- if (!import.moduleId)
- throw ModuleDoesNotExists{};
- }
+ removeRelinkableEntries(relinkableAliasPropertyDeclarations,
+ propertyDeclarationIds,
+ PropertyCompare<AliasPropertyDeclaration>{});
}
void synchronizeDocumentImports(Storage::Imports &imports, const std::vector<int> &sourceIdValues)
@@ -1096,7 +1216,7 @@ private:
json.append(parameter.name);
json.append("\",\"tn\":\"");
json.append(parameter.typeName);
- if (parameter.traits == Storage::PropertyDeclarationTraits::Non) {
+ if (parameter.traits == Storage::PropertyDeclarationTraits::None) {
json.append("\"}");
} else {
json.append("\",\"tr\":");
@@ -1257,60 +1377,88 @@ private:
Storage::ExportedTypes &exportedTypes)
{
for (const auto &exportedType : type.exportedTypes)
- exportedTypes.emplace_back(exportedType.name, exportedType.version, typeId, type.moduleId);
+ exportedTypes.emplace_back(exportedType.name,
+ exportedType.version,
+ typeId,
+ exportedType.moduleId);
}
- struct ModuleAndTypeId
- {
- ModuleAndTypeId() = default;
- ModuleAndTypeId(int moduleId, long long typeId)
- : moduleId{moduleId}
- , typeId{typeId}
- {}
-
- ModuleId moduleId;
- TypeId typeId;
- };
-
TypeId declareType(Storage::Type &type)
{
- if (!type.moduleId && type.typeName.isEmpty()) {
- auto [moduleId, typeId] = selectModuleAndTypeIdBySourceIdStatement
- .template value<ModuleAndTypeId>(&type.sourceId);
- type.typeId = typeId;
- type.moduleId = moduleId;
+ if (type.typeName.isEmpty()) {
+ type.typeId = selectTypeIdBySourceIdStatement.template value<TypeId>(&type.sourceId);
+
return type.typeId;
}
- if (!type.moduleId)
- throw ModuleDoesNotExists{};
-
- type.typeId = upsertTypeStatement.template value<TypeId>(&type.moduleId,
+ type.typeId = upsertTypeStatement.template value<TypeId>(&type.sourceId,
type.typeName,
- static_cast<int>(type.accessSemantics),
- &type.sourceId);
+ static_cast<int>(
+ type.accessSemantics));
if (!type.typeId)
- type.typeId = selectTypeIdByModuleIdAndNameStatement.template value<TypeId>(&type.moduleId,
+ type.typeId = selectTypeIdBySourceIdAndNameStatement.template value<TypeId>(&type.sourceId,
type.typeName);
- upsertNativeType(type.moduleId, type.typeName, type.typeId);
return type.typeId;
}
void syncDeclarations(Storage::Type &type,
- std::vector<AliasPropertyDeclaration> &insertedAliasPropertyDeclarations,
- std::vector<AliasPropertyDeclaration> &updatedAliasPropertyDeclarations)
+ AliasPropertyDeclarations &insertedAliasPropertyDeclarations,
+ AliasPropertyDeclarations &updatedAliasPropertyDeclarations,
+ PropertyDeclarationIds &propertyDeclarationIds)
{
- auto typeId = type.typeId;
- synchronizePropertyDeclarations(typeId,
+ if (type.changeLevel == Storage::ChangeLevel::Minimal)
+ return;
+
+ synchronizePropertyDeclarations(type.typeId,
type.propertyDeclarations,
type.sourceId,
insertedAliasPropertyDeclarations,
- updatedAliasPropertyDeclarations);
- synchronizeFunctionDeclarations(typeId, type.functionDeclarations);
- synchronizeSignalDeclarations(typeId, type.signalDeclarations);
- synchronizeEnumerationDeclarations(typeId, type.enumerationDeclarations);
+ updatedAliasPropertyDeclarations,
+ propertyDeclarationIds);
+ synchronizeFunctionDeclarations(type.typeId, type.functionDeclarations);
+ synchronizeSignalDeclarations(type.typeId, type.signalDeclarations);
+ synchronizeEnumerationDeclarations(type.typeId, type.enumerationDeclarations);
+ }
+
+ template<typename Relinkable, typename Ids, typename Compare>
+ void removeRelinkableEntries(std::vector<Relinkable> &relinkables, Ids &ids, Compare compare)
+ {
+ std::vector<Relinkable> newRelinkables;
+ newRelinkables.reserve(relinkables.size());
+
+ std::sort(ids.begin(), ids.end());
+ std::sort(relinkables.begin(), relinkables.end(), compare);
+
+ Utils::set_greedy_difference(
+ relinkables.begin(),
+ relinkables.end(),
+ ids.cbegin(),
+ ids.cend(),
+ [&](Relinkable &entry) { newRelinkables.push_back(std::move(entry)); },
+ compare);
+
+ relinkables = std::move(newRelinkables);
+ }
+
+ void syncDeclarations(Storage::Types &types,
+ AliasPropertyDeclarations &insertedAliasPropertyDeclarations,
+ AliasPropertyDeclarations &updatedAliasPropertyDeclarations,
+ PropertyDeclarations &relinkablePropertyDeclarations)
+ {
+ PropertyDeclarationIds propertyDeclarationIds;
+ propertyDeclarationIds.reserve(types.size() * 10);
+
+ for (auto &&type : types)
+ syncDeclarations(type,
+ insertedAliasPropertyDeclarations,
+ updatedAliasPropertyDeclarations,
+ propertyDeclarationIds);
+
+ removeRelinkableEntries(relinkablePropertyDeclarations,
+ propertyDeclarationIds,
+ PropertyCompare<PropertyDeclaration>{});
}
void checkForPrototypeChainCycle(TypeId typeId) const
@@ -1338,7 +1486,7 @@ private:
&propertyDeclarationId);
}
- void syncPrototypes(Storage::Type &type)
+ void syncPrototype(Storage::Type &type, TypeIds &typeIds)
{
if (type.changeLevel == Storage::ChangeLevel::Minimal)
return;
@@ -1358,22 +1506,35 @@ private:
updatePrototypeStatement.write(&type.typeId, &prototypeId, &prototypeTypeNameId);
checkForPrototypeChainCycle(type.typeId);
}
+
+ typeIds.push_back(type.typeId);
+ }
+
+ void syncPrototypes(Storage::Types &types, Prototypes &relinkablePrototypes)
+ {
+ TypeIds typeIds;
+ typeIds.reserve(types.size());
+
+ for (auto &type : types)
+ syncPrototype(type, typeIds);
+
+ removeRelinkableEntries(relinkablePrototypes, typeIds, TypeCompare<Prototype>{});
}
ImportId fetchImportId(SourceId sourceId, const Storage::Import &import) const
{
if (import.version) {
- return selectImportIdBySourceIdAndImportNameAndVersionStatement.template value<ImportId>(
- &sourceId, import.name, import.version.major.value, import.version.minor.value);
+ return selectImportIdBySourceIdAndModuleIdAndVersionStatement.template value<ImportId>(
+ &sourceId, &import.moduleId, import.version.major.value, import.version.minor.value);
}
if (import.version.major) {
- return selectImportIdBySourceIdAndImportNameAndMajorVersionStatement
- .template value<ImportId>(&sourceId, import.name, import.version.major.value);
+ return selectImportIdBySourceIdAndModuleIdAndMajorVersionStatement
+ .template value<ImportId>(&sourceId, &import.moduleId, import.version.major.value);
}
- return selectImportIdBySourceIdAndImportNameStatement.template value<ImportId>(&sourceId,
- import.name);
+ return selectImportIdBySourceIdAndModuleIdStatement.template value<ImportId>(&sourceId,
+ &import.moduleId);
}
ImportedTypeNameId fetchImportedTypeNameId(const Storage::ImportedTypeName &name, SourceId sourceId)
@@ -1440,9 +1601,6 @@ private:
&typeNameId);
}
- if (kind == Storage::TypeNameKind::Native)
- return selectTypeIdForNativeTypeNameNamesStatement.template value<TypeId>(&typeNameId);
-
return selectTypeIdForImportedTypeNameNamesStatement.template value<TypeId>(&typeNameId);
}
@@ -1649,21 +1807,16 @@ private:
typesTable.setUseIfNotExists(true);
typesTable.setName("types");
typesTable.addColumn("typeId", Sqlite::ColumnType::Integer, {Sqlite::PrimaryKey{}});
- auto &moduleIdColumn = typesTable.addForeignKeyColumn("moduleId",
- foreignModuleIdColumn,
- Sqlite::ForeignKeyAction::NoAction,
- Sqlite::ForeignKeyAction::NoAction,
- Sqlite::Enforment::Deferred);
+ auto &sourceIdColumn = typesTable.addColumn("sourceId");
auto &typesNameColumn = typesTable.addColumn("name");
typesTable.addColumn("accessSemantics");
- typesTable.addColumn("sourceId");
typesTable.addForeignKeyColumn("prototypeId",
typesTable,
Sqlite::ForeignKeyAction::NoAction,
Sqlite::ForeignKeyAction::Restrict);
typesTable.addColumn("prototypeNameId");
- typesTable.addUniqueIndex({moduleIdColumn, typesNameColumn});
+ typesTable.addUniqueIndex({sourceIdColumn, typesNameColumn});
typesTable.initialize(database);
@@ -1706,23 +1859,20 @@ private:
auto &moduleIdColumn = table.addForeignKeyColumn("moduleId",
foreignModuleIdColumn,
Sqlite::ForeignKeyAction::NoAction,
- Sqlite::ForeignKeyAction::NoAction,
- Sqlite::Enforment::Deferred);
+ Sqlite::ForeignKeyAction::NoAction);
auto &nameColumn = table.addColumn("name");
- auto &kindColumn = table.addColumn("kind");
auto &typeIdColumn = table.addColumn("typeId");
auto &majorVersionColumn = table.addColumn("majorVersion");
auto &minorVersionColumn = table.addColumn("minorVersion");
- table.addUniqueIndex({moduleIdColumn, nameColumn, kindColumn},
+ table.addUniqueIndex({moduleIdColumn, nameColumn},
"majorVersion IS NULL AND minorVersion IS NULL");
- table.addUniqueIndex({moduleIdColumn, nameColumn, kindColumn, majorVersionColumn},
+ table.addUniqueIndex({moduleIdColumn, nameColumn, majorVersionColumn},
"majorVersion IS NOT NULL AND minorVersion IS NULL");
- table.addUniqueIndex(
- {moduleIdColumn, nameColumn, kindColumn, majorVersionColumn, minorVersionColumn},
- "majorVersion IS NOT NULL AND minorVersion IS NOT NULL");
+ table.addUniqueIndex({moduleIdColumn, nameColumn, majorVersionColumn, minorVersionColumn},
+ "majorVersion IS NOT NULL AND minorVersion IS NOT NULL");
- table.addIndex({typeIdColumn}, "kind=1");
+ table.addIndex({typeIdColumn});
table.initialize(database);
}
@@ -1823,6 +1973,7 @@ private:
Sqlite::Enforment::Deferred);
auto &majorVersionColumn = table.addColumn("majorVersion");
auto &minorVersionColumn = table.addColumn("minorVersion");
+ table.addColumn("kind");
table.addUniqueIndex({sourceIdColumn, moduleIdColumn},
"majorVersion IS NULL AND minorVersion IS NULL");
@@ -1856,18 +2007,18 @@ private:
public:
Database &database;
Initializer initializer;
+ ModuleCache moduleCache{ModuleStorageAdapter{*this}};
ReadWriteStatement<1> upsertTypeStatement{
- "INSERT INTO types(moduleId, name, accessSemantics, sourceId) VALUES(?1, ?2, "
- "?3, nullif(?4, -1)) ON CONFLICT DO UPDATE SET accessSemantics=excluded.accessSemantics, "
- "sourceId=excluded.sourceId WHERE accessSemantics IS NOT excluded.accessSemantics OR "
- "sourceId IS NOT excluded.sourceId RETURNING typeId",
+ "INSERT INTO types(sourceId, name, accessSemantics) VALUES(?1, ?2, ?3) ON CONFLICT DO "
+ "UPDATE SET accessSemantics=excluded.accessSemantics WHERE accessSemantics IS NOT "
+ "excluded.accessSemantics RETURNING typeId",
database};
WriteStatement updatePrototypeStatement{
"UPDATE types SET prototypeId=?2, prototypeNameId=?3 WHERE typeId=?1 AND (prototypeId IS "
"NOT ?2 OR prototypeNameId IS NOT ?3)",
database};
mutable ReadStatement<1> selectTypeIdByExportedNameStatement{
- "SELECT typeId FROM exportedTypeNames WHERE name=?1 AND kind=1", database};
+ "SELECT typeId FROM exportedTypeNames WHERE name=?1", database};
mutable ReadStatement<1> selectPrototypeIdStatement{
"WITH RECURSIVE "
" typeSelection(typeId) AS ("
@@ -1925,18 +2076,14 @@ public:
"INSERT INTO sources(sourceContextId, sourceName) VALUES (?,?)", database};
mutable ReadStatement<3> selectAllSourcesStatement{
"SELECT sourceName, sourceContextId, sourceId FROM sources", database};
- mutable ReadStatement<5> selectTypeByTypeIdStatement{
- "SELECT moduleId, name, (SELECT name FROM types WHERE typeId=outerTypes.prototypeId), "
- "accessSemantics, ifnull(sourceId, -1) FROM types AS outerTypes WHERE typeId=?",
+ mutable ReadStatement<4> selectTypeByTypeIdStatement{
+ "SELECT sourceId, name, prototypeId, accessSemantics FROM types WHERE typeId=?", database};
+ mutable ReadStatement<4> selectExportedTypesByTypeIdStatement{
+ "SELECT moduleId, name, ifnull(majorVersion, -1), ifnull(minorVersion, -1) FROM "
+ "exportedTypeNames WHERE typeId=?",
database};
- mutable ReadStatement<3> selectExportedTypesByTypeIdStatement{
- "SELECT name, ifnull(majorVersion, -1), ifnull(minorVersion, -1) FROM exportedTypeNames "
- "WHERE typeId=? AND kind=1",
- database};
- mutable ReadStatement<6> selectTypesStatement{
- "SELECT moduleId, name, typeId, (SELECT name FROM types WHERE "
- "typeId=t.prototypeId), accessSemantics, ifnull(sourceId, -1) FROM types AS "
- "t",
+ mutable ReadStatement<5> selectTypesStatement{
+ "SELECT sourceId, name, typeId, ifnull(prototypeId, -1), accessSemantics FROM types",
database};
ReadStatement<1> selectNotUpdatedTypesInSourcesStatement{
"SELECT typeId FROM types WHERE (sourceId IN carray(?1) AND typeId NOT IN carray(?2))",
@@ -1953,10 +2100,9 @@ public:
"DELETE FROM signalDeclarations WHERE typeId=?", database};
WriteStatement deleteTypeStatement{"DELETE FROM types WHERE typeId=?", database};
mutable ReadStatement<4> selectPropertyDeclarationsByTypeIdStatement{
- "SELECT name, (SELECT name FROM types WHERE typeId=pd.propertyTypeId), propertyTraits, "
- "(SELECT name FROM propertyDeclarations WHERE "
- "propertyDeclarationId=pd.aliasPropertyDeclarationId) FROM propertyDeclarations AS pd "
- "WHERE typeId=?",
+ "SELECT name, nullif(propertyTypeId, -1), propertyTraits, (SELECT name FROM "
+ "propertyDeclarations WHERE propertyDeclarationId=pd.aliasPropertyDeclarationId) FROM "
+ "propertyDeclarations AS pd WHERE typeId=?",
database};
ReadStatement<6> selectPropertyDeclarationsForTypeIdStatement{
"SELECT name, propertyTraits, propertyTypeId, propertyImportedTypeNameId, "
@@ -2081,25 +2227,18 @@ public:
database};
WriteStatement deleteEnumerationDeclarationStatement{
"DELETE FROM enumerationDeclarations WHERE enumerationDeclarationId=?", database};
- WriteStatement insertModuleStatement{"INSERT INTO modules(name, moduleId) VALUES(?1, ?2)",
- database};
- WriteStatement updateModuleStatement{"UPDATE modules SET name=?2 WHERE moduleId=?1", database};
- WriteStatement deleteModuleStatement{"DELETE FROM modules WHERE moduleId=?", database};
mutable ReadStatement<1> selectModuleIdByNameStatement{
"SELECT moduleId FROM modules WHERE name=? LIMIT 1", database};
- mutable ReadStatement<2> selectModulesForIdsStatement{
- "SELECT name, moduleId FROM modules WHERE moduleId IN carray(?1) ORDER BY "
- "moduleId",
- database};
- mutable ReadStatement<2> selectAllModulesStatement{
- "SELECT name, moduleId FROM modules ORDER BY moduleId", database};
- mutable ReadStatement<1> selectTypeIdsForModuleIdStatement{
- "SELECT typeId FROM types WHERE moduleId=?", database};
- mutable ReadStatement<1> selectTypeIdByModuleIdAndNameStatement{
- "SELECT typeId FROM types WHERE moduleId=?1 and name=?2", database};
+ mutable ReadWriteStatement<1> insertModuleNameStatement{
+ "INSERT INTO modules(name) VALUES(?1) RETURNING moduleId", database};
+ mutable ReadStatement<1> selectModuleNameStatement{
+ "SELECT name FROM modules WHERE moduleId =?1", database};
+ mutable ReadStatement<2> selectAllModulesStatement{"SELECT name, moduleId FROM modules", database};
+ mutable ReadStatement<1> selectTypeIdBySourceIdAndNameStatement{
+ "SELECT typeId FROM types WHERE sourceId=?1 and name=?2", database};
mutable ReadStatement<1> selectTypeIdByModuleIdsAndExportedNameStatement{
"SELECT typeId FROM exportedTypeNames WHERE moduleId IN carray(?1, ?2, 'int32') AND "
- "name=?3 AND kind=1",
+ "name=?3",
database};
mutable ReadStatement<5> selectDocumentImportForSourceIdStatement{
"SELECT importId, sourceId, moduleId, ifnull(majorVersion, -1), ifnull(minorVersion, -1) "
@@ -2241,8 +2380,8 @@ public:
WriteStatement deleteFileStatusStatement{"DELETE FROM fileStatuses WHERE sourceId=?1", database};
WriteStatement updateFileStatusStatement{
"UPDATE fileStatuses SET size=?2, lastModified=?3 WHERE sourceId=?1", database};
- ReadStatement<2> selectModuleAndTypeIdBySourceIdStatement{
- "SELECT moduleId, typeId FROM types WHERE sourceId=?", database};
+ ReadStatement<1> selectTypeIdBySourceIdStatement{"SELECT typeId FROM types WHERE sourceId=?",
+ database};
mutable ReadStatement<1> selectImportedTypeNameIdStatement{
"SELECT importedTypeNameId FROM importedTypeNames WHERE kind=?1 AND importOrSourceId=?2 "
"AND name=?3 LIMIT 1",
@@ -2251,24 +2390,24 @@ public:
"INSERT INTO importedTypeNames(kind, importOrSourceId, name) VALUES (?1, ?2, ?3) "
"RETURNING importedTypeNameId",
database};
- mutable ReadStatement<1> selectImportIdBySourceIdAndImportNameStatement{
- "SELECT importId FROM documentImports JOIN modules AS m USING(moduleId) WHERE sourceId=?1 "
- "AND m.name=?2 AND majorVersion IS NULL AND minorVersion IS NULL LIMIT 1",
+ mutable ReadStatement<1> 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> selectImportIdBySourceIdAndImportNameAndMajorVersionStatement{
- "SELECT importId FROM documentImports JOIN modules AS m USING(moduleId) WHERE sourceId=?1 "
- "AND m.name=?2 AND majorVersion=?3 AND minorVersion IS NULL LIMIT 1",
+ mutable ReadStatement<1> selectImportIdBySourceIdAndModuleIdAndMajorVersionStatement{
+ "SELECT importId FROM documentImports WHERE sourceId=?1 AND moduleId=?2 AND "
+ "majorVersion=?3 AND minorVersion IS NULL LIMIT 1",
database};
- mutable ReadStatement<1> selectImportIdBySourceIdAndImportNameAndVersionStatement{
- "SELECT importId FROM documentImports JOIN modules AS m USING(moduleId) WHERE sourceId=?1 "
- "AND m.name=?2 AND majorVersion=?3 AND minorVersion=?4 LIMIT 1",
+ mutable ReadStatement<1> selectImportIdBySourceIdAndModuleIdAndVersionStatement{
+ "SELECT importId FROM documentImports WHERE sourceId=?1 AND moduleId=?2 AND "
+ "majorVersion=?3 AND minorVersion=?4 LIMIT 1",
database};
mutable ReadStatement<1> selectKindFromImportedTypeNamesStatement{
"SELECT kind FROM importedTypeNames WHERE importedTypeNameId=?1", database};
mutable ReadStatement<1> selectTypeIdForQualifiedImportedTypeNameNamesStatement{
"SELECT typeId FROM importedTypeNames AS itn JOIN documentImports AS di ON "
"importOrSourceId=importId JOIN exportedTypeNames AS etn USING(moduleId) WHERE "
- "itn.kind=2 AND importedTypeNameId=?1 AND itn.name=etn.name AND etn.kind=1 AND "
+ "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",
@@ -2276,39 +2415,29 @@ public:
mutable ReadStatement<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 etn.kind=1 AND "
+ "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 etn.majorVersion DESC NULLS FIRST, "
"etn.minorVersion DESC NULLS FIRST LIMIT 1",
database};
- mutable ReadStatement<1> selectTypeIdForNativeTypeNameNamesStatement{
- "SELECT typeId FROM importedTypeNames AS itn JOIN documentImports AS di ON "
- "importOrSourceId=sourceId JOIN exportedTypeNames AS etn USING(moduleId) WHERE itn.kind=0 "
- "AND importedTypeNameId=?1 AND itn.name=etn.name AND etn.kind=0 LIMIT 1",
- database};
WriteStatement deleteAllSourcesStatement{"DELETE FROM sources", database};
WriteStatement deleteAllSourceContextsStatement{"DELETE FROM sourceContexts", database};
- mutable ReadStatement<6> selectExportedTypesForTypeIdStatement{
- "SELECT moduleId, name, ifnull(majorVersion, -1), ifnull(minorVersion, -1), typeId, "
- "exportedTypeNameId FROM exportedTypeNames WHERE typeId IN carray(?1, ?2, 'int64') AND "
- "kind=1 ORDER BY moduleId, name, majorVersion, minorVersion",
- database};
- WriteStatement upsertExportedTypeNamesWithVersionStatement{
- "INSERT INTO exportedTypeNames(moduleId, name, kind, majorVersion, minorVersion, typeId) "
- "VALUES(?1, ?2, ?3, ?4, ?5, ?6) ON CONFLICT DO UPDATE SET typeId=excluded.typeId",
- database};
- WriteStatement upsertExportedTypeNamesWithMajorVersionStatement{
- "INSERT INTO exportedTypeNames(moduleId, name, kind, majorVersion, typeId) "
- "VALUES(?1, ?2, ?3, ?4, ?5) ON CONFLICT DO UPDATE SET typeId=excluded.typeId",
- database};
- WriteStatement upsertExportedTypeNamesWithoutVersionStatement{
- "INSERT INTO exportedTypeNames(moduleId, name, kind, typeId) VALUES(?1, ?2, ?3, ?4) ON "
- "CONFLICT DO UPDATE SET typeId=excluded.typeId",
- database};
- WriteStatement upsertExportedTypeNameStatement{
- "INSERT INTO exportedTypeNames(moduleId, name, kind, typeId) VALUES(?1, ?2, ?3, ?4) ON "
- "CONFLICT DO UPDATE SET typeId=excluded.typeId WHERE typeId IS NOT excluded.typeId",
- database};
+ mutable ReadStatement<6> selectExportedTypesForSourceIdsStatement{
+ "SELECT moduleId, etn.name, ifnull(majorVersion, -1), ifnull(minorVersion, -1), typeId, "
+ "exportedTypeNameId FROM exportedTypeNames AS etn JOIN types USING(typeId) WHERE sourceId "
+ "IN carray(?1) OR typeId in carray(?2) ORDER BY moduleId, etn.name, majorVersion, "
+ "minorVersion",
+ database};
+ WriteStatement insertExportedTypeNamesWithVersionStatement{
+ "INSERT INTO exportedTypeNames(moduleId, name, majorVersion, minorVersion, typeId) "
+ "VALUES(?1, ?2, ?3, ?4, ?5)",
+ database};
+ WriteStatement insertExportedTypeNamesWithMajorVersionStatement{
+ "INSERT INTO exportedTypeNames(moduleId, name, majorVersion, typeId) "
+ "VALUES(?1, ?2, ?3, ?4)",
+ database};
+ WriteStatement insertExportedTypeNamesWithoutVersionStatement{
+ "INSERT INTO exportedTypeNames(moduleId, name, typeId) VALUES(?1, ?2, ?3)", database};
WriteStatement deleteExportedTypeNameStatement{
"DELETE FROM exportedTypeNames WHERE exportedTypeNameId=?", database};
WriteStatement updateExportedTypeNameTypeIdStatement{
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageexceptions.h b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageexceptions.h
index 0d23e11605..42790bded6 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageexceptions.h
+++ b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageexceptions.h
@@ -101,4 +101,10 @@ public:
const char *what() const noexcept override { return "There is a prototype chain cycle!"; }
};
+class CannotParseQmlTypesFile : std::exception
+{
+public:
+ const char *what() const noexcept override { return "Cannot parse qml types file!"; }
+};
+
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageinterface.h b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageinterface.h
index 302a1801a2..7d27bd22f1 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageinterface.h
+++ b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageinterface.h
@@ -33,15 +33,12 @@ namespace QmlDesigner {
class ProjectStorageInterface
{
public:
- virtual void synchronize(Storage::Modules modules,
- Storage::Imports imports,
- Storage::Types types,
- SourceIds sourceIds,
- FileStatuses fileStatuses)
- = 0;
+ virtual void synchronize(Storage::SynchronizationPackage package) = 0;
+
+ virtual ModuleId moduleId(Utils::SmallStringView name) = 0;
virtual FileStatus fetchFileStatus(SourceId sourceId) const = 0;
- virtual SourceIds fetchSourceDependencieIds(SourceId sourceId) const = 0;
+ virtual Storage::ProjectDatas fetchProjectDatas(SourceId sourceId) const = 0;
protected:
~ProjectStorageInterface() = default;
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstoragetypes.h b/src/plugins/qmldesigner/designercore/projectstorage/projectstoragetypes.h
index 50db7c4853..ef05539076 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/projectstoragetypes.h
+++ b/src/plugins/qmldesigner/designercore/projectstorage/projectstoragetypes.h
@@ -25,6 +25,7 @@
#pragma once
+#include "filestatus.h"
#include "projectstorageids.h"
#include <utils/smallstring.h>
@@ -35,10 +36,10 @@
namespace QmlDesigner::Storage {
-enum class TypeAccessSemantics : int { Invalid, Reference, Value, Sequence, IsEnum = 1 << 8 };
+enum class TypeAccessSemantics : int { None, Reference, Value, Sequence, IsEnum = 1 << 8 };
enum class PropertyDeclarationTraits : unsigned int {
- Non = 0,
+ None = 0,
IsReadOnly = 1 << 0,
IsPointer = 1 << 1,
IsList = 1 << 2
@@ -121,38 +122,6 @@ public:
VersionNumber minor;
};
-class Module
-{
-public:
- explicit Module() = default;
-
- explicit Module(Utils::SmallStringView name, SourceId sourceId = SourceId{})
- : name{name}
- , sourceId{sourceId}
- {}
-
- explicit Module(QStringView name, SourceId sourceId = SourceId{})
- : name{name}
- , sourceId{sourceId}
- {}
-
- explicit Module(Utils::SmallStringView name, int sourceId)
- : name{name}
- , sourceId{sourceId}
- {}
-
- friend bool operator==(const Module &first, const Module &second)
- {
- return first.name == second.name;
- }
-
-public:
- Utils::PathString name;
- SourceId sourceId;
-};
-
-using Modules = std::vector<Module>;
-
enum class IsQualified : int { No, Yes };
inline int operator-(IsQualified first, IsQualified second)
@@ -165,34 +134,36 @@ inline int operator<(IsQualified first, IsQualified second)
return static_cast<int>(first) < static_cast<int>(second);
}
+enum class ImportKind : char { Module, Directory, QmlTypesDependency };
+
class Import
{
public:
explicit Import() = default;
- explicit Import(Utils::SmallStringView name, Version version, SourceId sourceId)
- : name{name}
- , version{version}
+ explicit Import(ModuleId moduleId, Version version, SourceId sourceId)
+ : version{version}
+ , moduleId{moduleId}
, sourceId{sourceId}
{}
- explicit Import(Utils::SmallStringView name, int majorVersion, int minorVersion, int sourceId)
- : name{name}
+ explicit Import(int moduleId, int majorVersion, int minorVersion, int sourceId)
+ : moduleId{moduleId}
, version{majorVersion, minorVersion}
, sourceId{sourceId}
{}
friend bool operator==(const Import &first, const Import &second)
{
- return first.name == second.name && first.version == second.version
+ return first.moduleId == second.moduleId && first.version == second.version
&& first.sourceId == second.sourceId;
}
public:
- Utils::PathString name;
Version version;
ModuleId moduleId;
SourceId sourceId;
+ Utils::SmallString aliasName;
};
using Imports = std::vector<Import>;
@@ -269,6 +240,12 @@ public:
, version{version}
{}
+ explicit ExportedType(ModuleId moduleId, Utils::SmallStringView name, Version version = Version{})
+ : name{name}
+ , version{version}
+ , moduleId{moduleId}
+ {}
+
explicit ExportedType(Utils::SmallStringView name, Version version, TypeId typeId, ModuleId moduleId)
: name{name}
, version{version}
@@ -276,9 +253,10 @@ public:
, moduleId{moduleId}
{}
- explicit ExportedType(Utils::SmallStringView name, int majorVersion, int minorVersion)
+ explicit ExportedType(int moduleId, Utils::SmallStringView name, int majorVersion, int minorVersion)
: name{name}
, version{majorVersion, minorVersion}
+ , moduleId{moduleId}
{}
friend bool operator==(const ExportedType &first, const ExportedType &second)
@@ -299,6 +277,11 @@ class ExportedTypeView
{
public:
explicit ExportedTypeView() = default;
+ explicit ExportedTypeView(ModuleId moduleId, Utils::SmallStringView name, Storage::Version version)
+ : name{name}
+ , version{version}
+ , moduleId{moduleId}
+ {}
explicit ExportedTypeView(int moduleId,
Utils::SmallStringView name,
int majorVersion,
@@ -552,6 +535,15 @@ public:
{}
explicit PropertyDeclaration(Utils::SmallStringView name,
+ TypeId propertyTypeId,
+ PropertyDeclarationTraits traits)
+ : name{name}
+ , traits{traits}
+ , propertyTypeId{propertyTypeId}
+ , kind{PropertyKind::Property}
+ {}
+
+ explicit PropertyDeclaration(Utils::SmallStringView name,
ImportedTypeName typeName,
PropertyDeclarationTraits traits,
Utils::SmallStringView aliasPropertyName)
@@ -563,13 +555,24 @@ public:
{}
explicit PropertyDeclaration(Utils::SmallStringView name,
- Utils::SmallStringView typeName,
+ TypeId propetyTypeId,
+ PropertyDeclarationTraits traits,
+ Utils::SmallStringView aliasPropertyName)
+ : name{name}
+ , aliasPropertyName{aliasPropertyName}
+ , traits{traits}
+ , propertyTypeId{propertyTypeId}
+ , kind{PropertyKind::Property}
+ {}
+
+ explicit PropertyDeclaration(Utils::SmallStringView name,
+ long long propertyTypeId,
int traits,
Utils::SmallStringView aliasPropertyName)
: name{name}
- , typeName{NativeType{typeName}}
, aliasPropertyName{aliasPropertyName}
, traits{static_cast<PropertyDeclarationTraits>(traits)}
+ , propertyTypeId{propertyTypeId}
, kind{PropertyKind::Property}
{}
@@ -594,6 +597,7 @@ public:
ImportedTypeName typeName;
Utils::SmallString aliasPropertyName;
PropertyDeclarationTraits traits = {};
+ TypeId propertyTypeId;
TypeId typeId;
PropertyKind kind = PropertyKind::Property;
};
@@ -632,8 +636,7 @@ class Type
{
public:
explicit Type() = default;
- explicit Type(ModuleId moduleId,
- Utils::SmallStringView typeName,
+ explicit Type(Utils::SmallStringView typeName,
ImportedTypeName prototype,
TypeAccessSemantics accessSemantics,
SourceId sourceId,
@@ -650,37 +653,42 @@ public:
, functionDeclarations{std::move(functionDeclarations)}
, signalDeclarations{std::move(signalDeclarations)}
, enumerationDeclarations{std::move(enumerationDeclarations)}
- , moduleId{moduleId}
, accessSemantics{accessSemantics}
, sourceId{sourceId}
, changeLevel{changeLevel}
{}
- explicit Type(ModuleId moduleId,
- Utils::SmallStringView typeName,
+ explicit Type(Utils::SmallStringView typeName,
+ TypeId prototypeId,
+ TypeAccessSemantics accessSemantics,
+ SourceId sourceId)
+ : typeName{typeName}
+ , accessSemantics{accessSemantics}
+ , sourceId{sourceId}
+ , prototypeId{prototypeId}
+ {}
+
+ explicit Type(Utils::SmallStringView typeName,
Utils::SmallStringView prototype,
int accessSemantics,
int sourceId)
: typeName{typeName}
, prototype{NativeType{prototype}}
- , moduleId{moduleId}
, accessSemantics{static_cast<TypeAccessSemantics>(accessSemantics)}
, sourceId{sourceId}
{}
- explicit Type(int moduleId,
+ explicit Type(int sourceId,
Utils::SmallStringView typeName,
long long typeId,
- Utils::SmallStringView prototype,
- int accessSemantics,
- int sourceId)
+ long long prototypeId,
+ int accessSemantics)
: typeName{typeName}
- , prototype{NativeType{prototype}}
- , moduleId{moduleId}
, accessSemantics{static_cast<TypeAccessSemantics>(accessSemantics)}
, sourceId{sourceId}
, typeId{typeId}
+ , prototypeId{prototypeId}
{}
friend bool operator==(const Type &first, const Type &second) noexcept
@@ -690,7 +698,6 @@ public:
&& first.propertyDeclarations == second.propertyDeclarations
&& first.functionDeclarations == second.functionDeclarations
&& first.signalDeclarations == second.signalDeclarations
- && first.moduleId == second.moduleId && first.sourceId == second.sourceId
&& first.sourceId == second.sourceId;
}
@@ -702,31 +709,52 @@ public:
FunctionDeclarations functionDeclarations;
SignalDeclarations signalDeclarations;
EnumerationDeclarations enumerationDeclarations;
- TypeAccessSemantics accessSemantics = TypeAccessSemantics::Invalid;
+ TypeAccessSemantics accessSemantics = TypeAccessSemantics::None;
SourceId sourceId;
TypeId typeId;
- ModuleId moduleId;
+ TypeId prototypeId;
ChangeLevel changeLevel = ChangeLevel::Full;
};
using Types = std::vector<Type>;
-class ModuleView
+class ProjectData
{
public:
- explicit ModuleView(Utils::SmallStringView name, int sourceId)
- : name{name}
- , sourceId{sourceId}
+ ModuleId extraModuleId;
+ SourceId sourceId;
+};
+
+using ProjectDatas = std::vector<ProjectData>;
+
+class SynchronizationPackage
+{
+public:
+ SynchronizationPackage() = default;
+ SynchronizationPackage(Imports imports, Types types, SourceIds sourceIds)
+ : imports{std::move(imports)}
+ , types{std::move(types)}
+ , sourceIds(std::move(sourceIds))
{}
- friend bool operator==(const ModuleView &first, const ModuleView &second)
- {
- return first.name == second.name && first.sourceId == second.sourceId;
- }
+ SynchronizationPackage(Types types)
+ : types{std::move(types)}
+ {}
+
+ SynchronizationPackage(SourceIds sourceIds)
+ : sourceIds(std::move(sourceIds))
+ {}
+
+ SynchronizationPackage(SourceIds sourceIds, FileStatuses fileStatuses)
+ : sourceIds(std::move(sourceIds))
+ , fileStatuses(std::move(fileStatuses))
+ {}
public:
- Utils::SmallStringView name;
- SourceId sourceId;
+ Imports imports;
+ Types types;
+ SourceIds sourceIds;
+ FileStatuses fileStatuses;
};
} // namespace QmlDesigner::Storage
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.cpp b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.cpp
index b5a7945181..cc91a06fae 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.cpp
+++ b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.cpp
@@ -52,40 +52,34 @@ ComponentReferences createComponentReferences(const QMultiHash<QString, QmlDirPa
void ProjectUpdater::update()
{
- Storage::Modules modules;
- Storage::Imports imports;
- Storage::Types types;
- SourceIds sourceIds;
- FileStatuses fileStatuses;
+ Storage::SynchronizationPackage package;
for (const QString &qmldirPath : m_projectManager.qtQmlDirs()) {
SourcePath qmldirSourcePath{qmldirPath};
SourceId qmlDirSourceId = m_pathCache.sourceId(qmldirSourcePath);
- switch (fileState(qmlDirSourceId, fileStatuses)) {
+ switch (fileState(qmlDirSourceId, package.fileStatuses)) {
case FileState::Changed: {
QmlDirParser parser;
parser.parse(m_fileSystem.contentAsQString(qmldirPath));
- modules.emplace_back(parser.typeNamespace(), qmlDirSourceId);
-
- sourceIds.push_back(qmlDirSourceId);
+ package.sourceIds.push_back(qmlDirSourceId);
SourceContextId directoryId = m_pathCache.sourceContextId(qmlDirSourceId);
- parseTypeInfos(parser.typeInfos(), directoryId, imports, types, sourceIds, fileStatuses);
+ Utils::PathString moduleName{parser.typeNamespace()};
+ ModuleId moduleId = m_projectStorage.moduleId(moduleName);
+
+ parseTypeInfos(parser.typeInfos(), directoryId, package);
parseQmlComponents(createComponentReferences(parser.components()),
directoryId,
- ModuleId{&qmlDirSourceId},
- imports,
- types,
- sourceIds,
- fileStatuses);
+ moduleId,
+ package);
break;
}
case FileState::NotChanged: {
- SourceIds qmltypesSourceIds = m_projectStorage.fetchSourceDependencieIds(qmlDirSourceId);
- parseTypeInfos(qmltypesSourceIds, imports, types, sourceIds, fileStatuses);
+ auto qmlProjectDatas = m_projectStorage.fetchProjectDatas(qmlDirSourceId);
+ parseTypeInfos(qmlProjectDatas, package);
break;
}
case FileState::NotExists: {
@@ -95,21 +89,14 @@ void ProjectUpdater::update()
}
}
- m_projectStorage.synchronize(std::move(modules),
- std::move(imports),
- std::move(types),
- std::move(sourceIds),
- std::move(fileStatuses));
+ m_projectStorage.synchronize(std::move(package));
}
void ProjectUpdater::pathsWithIdsChanged(const std::vector<IdPaths> &idPaths) {}
void ProjectUpdater::parseTypeInfos(const QStringList &typeInfos,
SourceContextId directoryId,
- Storage::Imports &imports,
- Storage::Types &types,
- SourceIds &sourceIds,
- FileStatuses &fileStatuses)
+ Storage::SynchronizationPackage &package)
{
QString directory{m_pathCache.sourceContextPath(directoryId)};
@@ -117,44 +104,37 @@ void ProjectUpdater::parseTypeInfos(const QStringList &typeInfos,
SourceId sourceId = m_pathCache.sourceId(directoryId, Utils::SmallString{typeInfo});
QString qmltypesPath = directory + "/" + typeInfo;
- parseTypeInfo(sourceId, qmltypesPath, imports, types, sourceIds, fileStatuses);
+ Storage::ProjectData projectData{ModuleId{}, sourceId};
+
+ parseTypeInfo(projectData, qmltypesPath, package);
}
}
-void ProjectUpdater::parseTypeInfos(const SourceIds &qmltypesSourceIds,
- Storage::Imports &imports,
- Storage::Types &types,
- SourceIds &sourceIds,
- FileStatuses &fileStatuses)
+void ProjectUpdater::parseTypeInfos(const Storage::ProjectDatas &projectDatas,
+ Storage::SynchronizationPackage &package)
{
- for (SourceId sourceId : qmltypesSourceIds) {
- QString qmltypesPath = m_pathCache.sourcePath(sourceId).toQString();
+ for (const Storage::ProjectData &projectData : projectDatas) {
+ QString qmltypesPath = m_pathCache.sourcePath(projectData.sourceId).toQString();
- parseTypeInfo(sourceId, qmltypesPath, imports, types, sourceIds, fileStatuses);
+ parseTypeInfo(projectData, qmltypesPath, package);
}
}
-void ProjectUpdater::parseTypeInfo(SourceId sourceId,
+void ProjectUpdater::parseTypeInfo(const Storage::ProjectData &projectData,
const QString &qmltypesPath,
- Storage::Imports &imports,
- Storage::Types &types,
- SourceIds &sourceIds,
- FileStatuses &fileStatuses)
+ Storage::SynchronizationPackage &package)
{
- if (fileState(sourceId, fileStatuses) == FileState::Changed) {
- sourceIds.push_back(sourceId);
+ if (fileState(projectData.sourceId, package.fileStatuses) == FileState::Changed) {
+ package.sourceIds.push_back(projectData.sourceId);
const auto content = m_fileSystem.contentAsQString(qmltypesPath);
- m_qmlTypesParser.parse(content, imports, types, sourceIds);
+ m_qmlTypesParser.parse(content, package.imports, package.types, projectData);
}
}
void ProjectUpdater::parseQmlComponents(ComponentReferences components,
SourceContextId directoryId,
ModuleId moduleId,
- Storage::Imports &imports,
- Storage::Types &types,
- SourceIds &sourceIds,
- FileStatuses &fileStatuses)
+ Storage::SynchronizationPackage &package)
{
std::sort(components.begin(), components.end(), [](auto &&first, auto &&second) {
return std::tie(first.get().typeName, first.get().majorVersion, first.get().minorVersion)
@@ -174,23 +154,23 @@ void ProjectUpdater::parseQmlComponents(ComponentReferences components,
Utils::SmallString fileName{component.fileName};
SourceId sourceId = m_pathCache.sourceId(directoryId, fileName);
- if (fileState(sourceId, fileStatuses) != FileState::Changed)
+ if (fileState(sourceId, package.fileStatuses) != FileState::Changed)
continue;
- sourceIds.push_back(sourceId);
+ package.sourceIds.push_back(sourceId);
const auto content = m_fileSystem.contentAsQString(directory + "/" + component.fileName);
- auto type = m_qmlDocumentParser.parse(content, imports);
+ auto type = m_qmlDocumentParser.parse(content, package.imports);
type.typeName = fileName;
- type.moduleId = moduleId;
type.accessSemantics = Storage::TypeAccessSemantics::Reference;
type.sourceId = sourceId;
type.exportedTypes.push_back(
- Storage::ExportedType{Utils::SmallString{component.typeName},
+ Storage::ExportedType{moduleId,
+ Utils::SmallString{component.typeName},
Storage::Version{component.majorVersion, component.minorVersion}});
- types.push_back(std::move(type));
+ package.types.push_back(std::move(type));
}
}
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.h b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.h
index dfe8ce05c4..e3323d7609 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.h
+++ b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.h
@@ -88,28 +88,16 @@ private:
void parseTypeInfos(const QStringList &typeInfos,
SourceContextId directoryId,
- Storage::Imports &imports,
- Storage::Types &types,
- SourceIds &sourceIds,
- FileStatuses &fileStatuses);
- void parseTypeInfos(const SourceIds &qmltypesSourceIds,
- Storage::Imports &imports,
- Storage::Types &types,
- SourceIds &sourceIds,
- FileStatuses &fileStatuses);
- void parseTypeInfo(SourceId sourceId,
+ Storage::SynchronizationPackage &package);
+ void parseTypeInfos(const Storage::ProjectDatas &projectDatas,
+ Storage::SynchronizationPackage &package);
+ void parseTypeInfo(const Storage::ProjectData &projectData,
const QString &qmltypesPath,
- Storage::Imports &imports,
- Storage::Types &types,
- SourceIds &sourceIds,
- FileStatuses &fileStatuses);
+ Storage::SynchronizationPackage &package);
void parseQmlComponents(ComponentReferences components,
SourceContextId directoryId,
ModuleId moduleId,
- Storage::Imports &imports,
- Storage::Types &types,
- SourceIds &sourceIds,
- FileStatuses &fileStatuses);
+ Storage::SynchronizationPackage &package);
FileState fileState(SourceId sourceId, FileStatuses &fileStatuses) const;
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparser.cpp b/src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparser.cpp
new file mode 100644
index 0000000000..c4a2bae617
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparser.cpp
@@ -0,0 +1,197 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "qmldocumentparser.h"
+
+#include "projectstorage.h"
+#include "sourcepathcache.h"
+
+#include <sqlitedatabase.h>
+
+#include <qmldom/qqmldomtop_p.h>
+
+#include <QDateTime>
+
+namespace QmlDesigner {
+
+namespace QmlDom = QQmlJS::Dom;
+
+namespace {
+
+int convertVersionNumber(qint32 versionNumber)
+{
+ return versionNumber < 0 ? -1 : versionNumber;
+}
+
+Storage::Version convertVersion(QmlDom::Version version)
+{
+ return Storage::Version{convertVersionNumber(version.majorVersion),
+ convertVersionNumber(version.minorVersion)};
+}
+
+Utils::PathString convertUri(const QString &uri)
+{
+ Utils::PathString path{QStringView{uri.begin() + 7, uri.end()}};
+ if (path.endsWith("/."))
+ return path;
+ if (path.endsWith("/")) {
+ path += ".";
+ return path;
+ }
+
+ path += "/.";
+ return path;
+}
+
+void addImports(Storage::Imports &imports,
+ const QList<QmlDom::Import> &qmlImports,
+ SourceId sourceId,
+ SourceContextId sourceContextId,
+ QmlDocumentParser::PathCache &pathCache,
+ QmlDocumentParser::ProjectStorage &storage)
+{
+ for (const QmlDom::Import &qmlImport : qmlImports) {
+ if (qmlImport.uri == u"file://.") {
+ auto moduleId = storage.moduleId(pathCache.sourceContextPath(sourceContextId));
+ imports.emplace_back(moduleId, Storage::Version{}, sourceId);
+ } else if (qmlImport.uri.startsWith(u"file://")) {
+ auto moduleId = storage.moduleId(convertUri(qmlImport.uri));
+ imports.emplace_back(moduleId, Storage::Version{}, sourceId);
+ } else {
+ auto moduleId = storage.moduleId(Utils::SmallString{qmlImport.uri});
+ imports.emplace_back(moduleId, convertVersion(qmlImport.version), sourceId);
+ }
+ }
+}
+
+void addPropertyDeclarations(Storage::Type &type, const QmlDom::QmlObject &rootObject)
+{
+ for (const QmlDom::PropertyDefinition &propertyDeclaration : rootObject.propertyDefs()) {
+ type.propertyDeclarations.emplace_back(Utils::SmallString{propertyDeclaration.name},
+ Storage::ImportedType{
+ Utils::SmallString{propertyDeclaration.typeName}},
+ Storage::PropertyDeclarationTraits::None);
+ }
+}
+
+void addParameterDeclaration(Storage::ParameterDeclarations &parameterDeclarations,
+ const QList<QmlDom::MethodParameter> &parameters)
+{
+ for (const QmlDom::MethodParameter &parameter : parameters) {
+ parameterDeclarations.emplace_back(Utils::SmallString{parameter.name},
+ Utils::SmallString{parameter.typeName});
+ }
+}
+
+void addFunctionAndSignalDeclarations(Storage::Type &type, const QmlDom::QmlObject &rootObject)
+{
+ for (const QmlDom::MethodInfo &methodInfo : rootObject.methods()) {
+ if (methodInfo.methodType == QmlDom::MethodInfo::Method) {
+ auto &functionDeclaration = type.functionDeclarations.emplace_back(
+ Utils::SmallString{methodInfo.name}, "", Storage::ParameterDeclarations{});
+ addParameterDeclaration(functionDeclaration.parameters, methodInfo.parameters);
+ } else {
+ auto &signalDeclaration = type.signalDeclarations.emplace_back(
+ Utils::SmallString{methodInfo.name});
+ addParameterDeclaration(signalDeclaration.parameters, methodInfo.parameters);
+ }
+ }
+}
+
+Storage::EnumeratorDeclarations createEnumerators(const QmlDom::EnumDecl &enumeration)
+{
+ Storage::EnumeratorDeclarations enumeratorDeclarations;
+ for (const QmlDom::EnumItem &enumerator : enumeration.values()) {
+ enumeratorDeclarations.emplace_back(Utils::SmallString{enumerator.name()},
+ static_cast<long long>(enumerator.value()));
+ }
+ return enumeratorDeclarations;
+}
+
+void addEnumeraton(Storage::Type &type, const QmlDom::Component &component)
+{
+ for (const QmlDom::EnumDecl &enumeration : component.enumerations()) {
+ Storage::EnumeratorDeclarations enumeratorDeclarations = createEnumerators(enumeration);
+ type.enumerationDeclarations.emplace_back(Utils::SmallString{enumeration.name()},
+ std::move(enumeratorDeclarations));
+ }
+}
+
+} // namespace
+
+Storage::Type QmlDocumentParser::parse(const QString &sourceContent,
+ Storage::Imports &imports,
+ SourceId sourceId,
+ SourceContextId sourceContextId)
+{
+ Storage::Type type;
+
+ QmlDom::DomItem environment = QmlDom::DomEnvironment::create(
+ {},
+ QmlDom::DomEnvironment::Option::SingleThreaded
+ | QmlDom::DomEnvironment::Option::NoDependencies);
+
+ QmlDom::DomItem items;
+
+ environment.loadFile(
+ {},
+ {},
+ sourceContent,
+ QDateTime{},
+ [&](QmlDom::Path, const QmlDom::DomItem &, const QmlDom::DomItem &newItems) {
+ items = newItems;
+ },
+ QmlDom::LoadOption::DefaultLoad,
+ QmlDom::DomType::QmlFile);
+
+ environment.loadPendingDependencies();
+
+ QmlDom::DomItem file = items.field(QmlDom::Fields::currentItem);
+ const QmlDom::QmlFile *qmlFile = file.as<QmlDom::QmlFile>();
+ const auto &components = qmlFile->components();
+
+ if (components.empty())
+ return type;
+
+ const auto &component = components.first();
+ const auto &objects = component.objects();
+
+ if (objects.empty())
+ return type;
+
+ const QmlDom::QmlObject &qmlObject = objects.front();
+
+ type.prototype = Storage::ImportedType{Utils::SmallString{qmlObject.name()}};
+
+ addImports(imports, qmlFile->imports(), sourceId, sourceContextId, m_pathCache, m_storage);
+
+ addPropertyDeclarations(type, qmlObject);
+ addFunctionAndSignalDeclarations(type, qmlObject);
+ addEnumeraton(type, component);
+
+ return type;
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparser.h b/src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparser.h
new file mode 100644
index 0000000000..e2dd243405
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparser.h
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "nonlockingmutex.h"
+#include "qmldocumentparserinterface.h"
+
+namespace Sqlite {
+class Database;
+}
+
+namespace QmlDesigner {
+
+template<typename Database>
+class ProjectStorage;
+
+template<typename ProjectStorage, typename Mutex>
+class SourcePathCache;
+
+class QmlDocumentParser
+{
+public:
+ using ProjectStorage = QmlDesigner::ProjectStorage<Sqlite::Database>;
+ using PathCache = QmlDesigner::SourcePathCache<ProjectStorage, NonLockingMutex>;
+
+ QmlDocumentParser(PathCache &pathCache, ProjectStorage &storage)
+ : m_pathCache{pathCache}
+ , m_storage{storage}
+ {}
+
+ virtual Storage::Type parse(const QString &sourceContent,
+ Storage::Imports &imports,
+ SourceId sourceId,
+ SourceContextId sourceContextId);
+
+private:
+ PathCache &m_pathCache;
+ ProjectStorage &m_storage;
+};
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/qmltypesparser.cpp b/src/plugins/qmldesigner/designercore/projectstorage/qmltypesparser.cpp
new file mode 100644
index 0000000000..f5d09409aa
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/projectstorage/qmltypesparser.cpp
@@ -0,0 +1,307 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "qmltypesparser.h"
+
+#include "projectstorage.h"
+#include "sourcepathcache.h"
+
+#include <sqlitedatabase.h>
+
+#include <qmlcompiler/qqmljstypedescriptionreader_p.h>
+#include <qmldom/qqmldomtop_p.h>
+
+#include <QDateTime>
+
+#include <algorithm>
+#include <tuple>
+
+namespace QmlDesigner {
+
+namespace QmlDom = QQmlJS::Dom;
+
+namespace {
+
+void 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);
+
+ auto majorVersionFound = std::find_if(spaceFound, dependency.end(), [](QChar c) {
+ return c.isDigit();
+ });
+ auto majorVersionEnd = std::find_if(majorVersionFound, dependency.end(), [](QChar c) {
+ return !c.isDigit();
+ });
+
+ Storage::Version version;
+
+ QStringView majorVersionString(majorVersionFound, majorVersionEnd);
+ if (!majorVersionString.isEmpty()) {
+ version.major.value = majorVersionString.toInt();
+
+ auto minorVersionFound = std::find_if(majorVersionEnd, dependency.end(), [](QChar c) {
+ return c.isDigit();
+ });
+ auto minorVersionEnd = std::find_if(minorVersionFound, dependency.end(), [](QChar c) {
+ return !c.isDigit();
+ });
+ QStringView minorVersionString(minorVersionFound, minorVersionEnd);
+ if (!minorVersionString.isEmpty())
+ version.minor.value = QStringView(minorVersionFound, minorVersionEnd).toInt();
+ }
+
+ imports.emplace_back(cppModuleId, version, sourceId);
+}
+
+void addImports(Storage::Imports &imports,
+ SourceId sourceId,
+ const QStringList &dependencies,
+ QmlTypesParser::ProjectStorage &storage)
+{
+ for (const QString &dependency : dependencies)
+ appendImports(imports, dependency, sourceId, storage);
+
+ imports.emplace_back(storage.moduleId("QML"), Storage::Version{}, sourceId);
+ imports.emplace_back(storage.moduleId("QtQml-cppnative"), Storage::Version{}, sourceId);
+}
+
+Storage::TypeAccessSemantics createTypeAccessSemantics(QQmlJSScope::AccessSemantics accessSematics)
+{
+ switch (accessSematics) {
+ case QQmlJSScope::AccessSemantics::Reference:
+ return Storage::TypeAccessSemantics::Reference;
+ case QQmlJSScope::AccessSemantics::Value:
+ return Storage::TypeAccessSemantics::Value;
+ case QQmlJSScope::AccessSemantics::None:
+ return Storage::TypeAccessSemantics::None;
+ case QQmlJSScope::AccessSemantics::Sequence:
+ return Storage::TypeAccessSemantics::Sequence;
+ }
+
+ return Storage::TypeAccessSemantics::None;
+}
+
+Storage::Version createVersion(QTypeRevision qmlVersion)
+{
+ return Storage::Version{qmlVersion.majorVersion(), qmlVersion.minorVersion()};
+}
+
+Storage::ExportedTypes createExports(const QList<QQmlJSScope::Export> &qmlExports,
+ const QQmlJSScope &component,
+ QmlTypesParser::ProjectStorage &storage,
+ ModuleId cppModuleId)
+{
+ Storage::ExportedTypes exportedTypes;
+ exportedTypes.reserve(Utils::usize(qmlExports));
+
+ for (const QQmlJSScope::Export &qmlExport : qmlExports) {
+ exportedTypes.emplace_back(storage.moduleId(Utils::SmallString{qmlExport.package()}),
+ Utils::SmallString{qmlExport.type()},
+ createVersion(qmlExport.version()));
+ }
+
+ exportedTypes.emplace_back(cppModuleId, Utils::SmallString{component.internalName()});
+
+ return exportedTypes;
+}
+
+Storage::PropertyDeclarationTraits createPropertyDeclarationTraits(const QQmlJSMetaProperty &qmlProperty)
+{
+ Storage::PropertyDeclarationTraits traits{};
+
+ if (qmlProperty.isList())
+ traits = traits | Storage::PropertyDeclarationTraits::IsList;
+
+ if (qmlProperty.isPointer())
+ traits = traits | Storage::PropertyDeclarationTraits::IsPointer;
+
+ if (!qmlProperty.isWritable())
+ traits = traits | Storage::PropertyDeclarationTraits::IsReadOnly;
+
+ return traits;
+}
+
+Storage::PropertyDeclarations createProperties(const QHash<QString, QQmlJSMetaProperty> &qmlProperties)
+{
+ Storage::PropertyDeclarations propertyDeclarations;
+ propertyDeclarations.reserve(Utils::usize(qmlProperties));
+
+ for (const QQmlJSMetaProperty &qmlProperty : qmlProperties) {
+ propertyDeclarations.emplace_back(Utils::SmallString{qmlProperty.propertyName()},
+ Storage::NativeType{
+ Utils::SmallString{qmlProperty.typeName()}},
+ createPropertyDeclarationTraits(qmlProperty));
+ }
+
+ return propertyDeclarations;
+}
+
+Storage::ParameterDeclarations createParameters(const QQmlJSMetaMethod &qmlMethod)
+{
+ Storage::ParameterDeclarations parameterDeclarations;
+
+ const QStringList &parameterNames = qmlMethod.parameterNames();
+ const QStringList &parameterTypeNames = qmlMethod.parameterTypeNames();
+ auto currentName = parameterNames.begin();
+ auto currentType = parameterTypeNames.begin();
+ auto nameEnd = parameterNames.end();
+ auto typeEnd = parameterTypeNames.end();
+
+ for (; currentName != nameEnd && currentType != typeEnd; ++currentName, ++currentType) {
+ parameterDeclarations.emplace_back(Utils::SmallString{*currentName},
+ Utils::SmallString{*currentType});
+ }
+
+ return parameterDeclarations;
+}
+
+std::tuple<Storage::FunctionDeclarations, Storage::SignalDeclarations> createFunctionAndSignals(
+ const QMultiHash<QString, QQmlJSMetaMethod> &qmlMethods)
+{
+ std::tuple<Storage::FunctionDeclarations, Storage::SignalDeclarations> functionAndSignalDeclarations;
+ Storage::FunctionDeclarations &functionsDeclarations{std::get<0>(functionAndSignalDeclarations)};
+ functionsDeclarations.reserve(Utils::usize(qmlMethods));
+ Storage::SignalDeclarations &signalDeclarations{std::get<1>(functionAndSignalDeclarations)};
+ signalDeclarations.reserve(Utils::usize(qmlMethods));
+
+ for (const QQmlJSMetaMethod &qmlMethod : qmlMethods) {
+ if (qmlMethod.methodType() != QQmlJSMetaMethod::Type::Signal) {
+ functionsDeclarations.emplace_back(Utils::SmallString{qmlMethod.methodName()},
+ Utils::SmallString{qmlMethod.returnTypeName()},
+ createParameters(qmlMethod));
+ } else {
+ signalDeclarations.emplace_back(Utils::SmallString{qmlMethod.methodName()},
+ createParameters(qmlMethod));
+ }
+ }
+
+ return functionAndSignalDeclarations;
+}
+
+Storage::EnumeratorDeclarations createEnumeratorsWithValues(const QQmlJSMetaEnum &qmlEnumeration)
+{
+ Storage::EnumeratorDeclarations enumeratorDeclarations;
+
+ const QStringList &keys = qmlEnumeration.keys();
+ const QList<int> &values = qmlEnumeration.values();
+ auto currentKey = keys.begin();
+ auto currentValue = values.begin();
+ auto keyEnd = keys.end();
+ auto valueEnd = values.end();
+
+ for (; currentKey != keyEnd && currentValue != valueEnd; ++currentKey, ++currentValue)
+ enumeratorDeclarations.emplace_back(Utils::SmallString{*currentKey}, *currentValue);
+
+ return enumeratorDeclarations;
+}
+
+Storage::EnumeratorDeclarations createEnumeratorsWithoutValues(const QQmlJSMetaEnum &qmlEnumeration)
+{
+ Storage::EnumeratorDeclarations enumeratorDeclarations;
+
+ for (const QString &key : qmlEnumeration.keys())
+ enumeratorDeclarations.emplace_back(Utils::SmallString{key});
+
+ return enumeratorDeclarations;
+}
+
+Storage::EnumeratorDeclarations createEnumerators(const QQmlJSMetaEnum &qmlEnumeration)
+{
+ if (qmlEnumeration.hasValues())
+ return createEnumeratorsWithValues(qmlEnumeration);
+
+ return createEnumeratorsWithoutValues(qmlEnumeration);
+}
+
+Storage::EnumerationDeclarations createEnumeration(const QHash<QString, QQmlJSMetaEnum> &qmlEnumerations)
+{
+ Storage::EnumerationDeclarations enumerationDeclarations;
+ enumerationDeclarations.reserve(Utils::usize(qmlEnumerations));
+
+ for (const QQmlJSMetaEnum &qmlEnumeration : qmlEnumerations) {
+ enumerationDeclarations.emplace_back(Utils::SmallString{qmlEnumeration.name()},
+ createEnumerators(qmlEnumeration));
+ }
+
+ return enumerationDeclarations;
+}
+
+void addType(Storage::Types &types,
+ SourceId sourceId,
+ ModuleId cppModuleId,
+ const QQmlJSScope &component,
+ QmlTypesParser::ProjectStorage &storage)
+{
+ auto [functionsDeclarations, signalDeclarations] = createFunctionAndSignals(component.ownMethods());
+ types.emplace_back(Utils::SmallString{component.internalName()},
+ Storage::NativeType{Utils::SmallString{component.baseTypeName()}},
+ createTypeAccessSemantics(component.accessSemantics()),
+ sourceId,
+ createExports(component.exports(), component, storage, cppModuleId),
+ createProperties(component.ownProperties()),
+ std::move(functionsDeclarations),
+ std::move(signalDeclarations),
+ createEnumeration(component.ownEnumerations()));
+}
+
+void addTypes(Storage::Types &types,
+ const Storage::ProjectData &projectData,
+ const QHash<QString, QQmlJSScope::Ptr> &objects,
+ QmlTypesParser::ProjectStorage &storage)
+{
+ types.reserve(Utils::usize(objects) + types.size());
+
+ for (const auto &object : objects)
+ addType(types, projectData.sourceId, projectData.extraModuleId, *object.get(), storage);
+}
+
+} // namespace
+
+void QmlTypesParser::parse(const QString &sourceContent,
+ Storage::Imports &imports,
+ Storage::Types &types,
+ const Storage::ProjectData &projectData)
+{
+ QQmlJSTypeDescriptionReader reader({}, sourceContent);
+ QHash<QString, QQmlJSScope::Ptr> components;
+ QStringList dependencies;
+ bool isValid = reader(&components, &dependencies);
+ if (!isValid)
+ throw CannotParseQmlTypesFile{};
+
+ addImports(imports, projectData.sourceId, dependencies, m_storage);
+ addTypes(types, projectData, components, m_storage);
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/qmltypesparser.h b/src/plugins/qmldesigner/designercore/projectstorage/qmltypesparser.h
new file mode 100644
index 0000000000..40f88d240d
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/projectstorage/qmltypesparser.h
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "nonlockingmutex.h"
+#include "qmltypesparserinterface.h"
+
+namespace Sqlite {
+class Database;
+}
+
+namespace QmlDesigner {
+
+template<typename Database>
+class ProjectStorage;
+
+template<typename ProjectStorage, typename Mutex>
+class SourcePathCache;
+
+class QmlTypesParser : public QmlTypesParserInterface
+{
+public:
+ using ProjectStorage = QmlDesigner::ProjectStorage<Sqlite::Database>;
+ using PathCache = QmlDesigner::SourcePathCache<ProjectStorage, NonLockingMutex>;
+
+ QmlTypesParser(PathCache &pathCache, ProjectStorage &storage)
+ : m_pathCache{pathCache}
+ , m_storage{storage}
+ {}
+
+ void parse(const QString &sourceContent,
+ Storage::Imports &imports,
+ Storage::Types &types,
+ const Storage::ProjectData &projectData) override;
+
+private:
+ PathCache &m_pathCache;
+ ProjectStorage &m_storage;
+};
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/qmltypesparserinterface.h b/src/plugins/qmldesigner/designercore/projectstorage/qmltypesparserinterface.h
index 40c9883835..3255c0b5aa 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/qmltypesparserinterface.h
+++ b/src/plugins/qmldesigner/designercore/projectstorage/qmltypesparserinterface.h
@@ -37,7 +37,7 @@ public:
virtual void parse(const QString &sourceContent,
Storage::Imports &imports,
Storage::Types &types,
- SourceIds &sourceIds)
+ const Storage::ProjectData &projectData)
= 0;
protected: