From b74c47ec66d99d9ade7621bdae2a76fd10be5f11 Mon Sep 17 00:00:00 2001 From: Marco Bubke Date: Mon, 22 Apr 2024 14:29:50 +0200 Subject: [PATCH] QmlDesigner: Remove template parameter from project storage There are now other ways to prevent locking bugs. So we don't need the template parameter anymore. That makes it possible to move much of the code to a cpp file. Maybe later we have to move some functions back for performance reasons. Change-Id: I01269912618d7cf5e070219e7edaa3a00623b7cf Reviewed-by: Qt CI Patch Build Bot Reviewed-by: Tim Jenssen Reviewed-by: Reviewed-by: Thomas Hartmann --- src/libs/sqlite/sqlitebasestatement.h | 14 +- .../designercore/include/modelfwd.h | 2 +- .../designercore/projectstorage/filesystem.h | 6 +- .../projectstorage/projectstorage.cpp | 3774 +++++++++++++++- .../projectstorage/projectstorage.h | 3777 +---------------- .../projectstorage/projectstoragefwd.h | 1 - .../projectstorage/projectstorageinterface.h | 2 +- .../projectstorage/projectstorageupdater.h | 3 +- .../projectstorage/qmldocumentparser.h | 2 +- .../projectstorage/qmltypesparser.h | 7 +- .../projectstorage/sourcepathcachetypes.h | 2 + .../qmldesigner/qmldesignerprojectmanager.cpp | 4 +- .../projectstorage/projectstorage-test.cpp | 14 +- .../projectstoragepathwatcher-test.cpp | 8 +- .../projectstorageupdater-test.cpp | 8 +- .../projectstorage/qmldocumentparser-test.cpp | 4 +- .../projectstorage/qmltypesparser-test.cpp | 4 +- .../typeannotationreader-test.cpp | 6 +- 18 files changed, 4002 insertions(+), 3636 deletions(-) diff --git a/src/libs/sqlite/sqlitebasestatement.h b/src/libs/sqlite/sqlitebasestatement.h index 81b31473f83..3710021ff53 100644 --- a/src/libs/sqlite/sqlitebasestatement.h +++ b/src/libs/sqlite/sqlitebasestatement.h @@ -210,6 +210,14 @@ public: struct is_container> : std::true_type {}; + template + struct is_small_container : std::false_type + {}; + + template + struct is_small_container> : std::true_type + {}; + template::value>, @@ -223,14 +231,16 @@ public: Resetter resetter{this}; Container resultValues; - resultValues.reserve(std::max(capacity, m_maximumResultCount)); + using size_tupe = typename Container::size_type; + if constexpr (!is_small_container::value) + resultValues.reserve(static_cast(std::max(capacity, m_maximumResultCount))); bindValues(queryValues...); while (BaseStatement::next()) emplaceBackValues(resultValues); - setMaximumResultCount(resultValues.size()); + setMaximumResultCount(static_cast(resultValues.size())); return resultValues; } diff --git a/src/plugins/qmldesigner/designercore/include/modelfwd.h b/src/plugins/qmldesigner/designercore/include/modelfwd.h index 0a062289fd0..91c533fe7b6 100644 --- a/src/plugins/qmldesigner/designercore/include/modelfwd.h +++ b/src/plugins/qmldesigner/designercore/include/modelfwd.h @@ -77,7 +77,7 @@ constexpr bool useProjectStorage() using ProjectStorageType = ProjectStorageInterface; using PathCacheType = SourcePathCacheInterface; #else -using ProjectStorageType = ProjectStorage; +using ProjectStorageType = ProjectStorage; using PathCacheType = SourcePathCache; #endif diff --git a/src/plugins/qmldesigner/designercore/projectstorage/filesystem.h b/src/plugins/qmldesigner/designercore/projectstorage/filesystem.h index 078fd1ee98f..28754a8560b 100644 --- a/src/plugins/qmldesigner/designercore/projectstorage/filesystem.h +++ b/src/plugins/qmldesigner/designercore/projectstorage/filesystem.h @@ -6,6 +6,7 @@ #include "filestatuscache.h" #include "filesysteminterface.h" #include "nonlockingmutex.h" +#include "projectstoragefwd.h" namespace Sqlite { class Database; @@ -16,12 +17,9 @@ namespace QmlDesigner { template class SourcePathCache; -template -class ProjectStorage; - class FileSystem : public FileSystemInterface { - using PathCache = SourcePathCache, NonLockingMutex>; + using PathCache = SourcePathCache; public: FileSystem(PathCache &sourcePathCache) diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstorage.cpp b/src/plugins/qmldesigner/designercore/projectstorage/projectstorage.cpp index 2bef2244d70..a037ddae9a6 100644 --- a/src/plugins/qmldesigner/designercore/projectstorage/projectstorage.cpp +++ b/src/plugins/qmldesigner/designercore/projectstorage/projectstorage.cpp @@ -5,4 +5,3776 @@ #include -template class QmlDesigner::ProjectStorage; +namespace QmlDesigner { + +class ProjectStorage::Initializer +{ +public: + Initializer(Database &database, bool isInitialized) + { + if (!isInitialized) { + auto moduleIdColumn = createModulesTable(database); + createSourceContextsTable(database); + createSourcesTable(database); + createTypesAndePropertyDeclarationsTables(database, moduleIdColumn); + createExportedTypeNamesTable(database, moduleIdColumn); + createImportedTypeNamesTable(database); + createEnumerationsTable(database); + createFunctionsTable(database); + createSignalsTable(database); + createModuleExportedImportsTable(database, moduleIdColumn); + createDocumentImportsTable(database, moduleIdColumn); + createFileStatusesTable(database); + createProjectDatasTable(database); + createPropertyEditorPathsTable(database); + createTypeAnnotionsTable(database); + } + database.setIsInitialized(true); + } + + void createSourceContextsTable(Database &database) + { + Sqlite::Table table; + table.setUseIfNotExists(true); + table.setName("sourceContexts"); + table.addColumn("sourceContextId", Sqlite::ColumnType::Integer, {Sqlite::PrimaryKey{}}); + const Sqlite::Column &sourceContextPathColumn = table.addColumn("sourceContextPath"); + + table.addUniqueIndex({sourceContextPathColumn}); + + table.initialize(database); + } + + void createSourcesTable(Database &database) + { + Sqlite::StrictTable table; + table.setUseIfNotExists(true); + table.setName("sources"); + table.addColumn("sourceId", Sqlite::StrictColumnType::Integer, {Sqlite::PrimaryKey{}}); + const auto &sourceContextIdColumn = table.addColumn( + "sourceContextId", + Sqlite::StrictColumnType::Integer, + {Sqlite::NotNull{}, + Sqlite::ForeignKey{"sourceContexts", + "sourceContextId", + Sqlite::ForeignKeyAction::NoAction, + Sqlite::ForeignKeyAction::Cascade}}); + const auto &sourceNameColumn = table.addColumn("sourceName", Sqlite::StrictColumnType::Text); + table.addUniqueIndex({sourceContextIdColumn, sourceNameColumn}); + + table.initialize(database); + } + + void createTypesAndePropertyDeclarationsTables( + Database &database, [[maybe_unused]] const Sqlite::StrictColumn &foreignModuleIdColumn) + { + Sqlite::StrictTable typesTable; + typesTable.setUseIfNotExists(true); + typesTable.setName("types"); + typesTable.addColumn("typeId", Sqlite::StrictColumnType::Integer, {Sqlite::PrimaryKey{}}); + auto &sourceIdColumn = typesTable.addColumn("sourceId", Sqlite::StrictColumnType::Integer); + auto &typesNameColumn = typesTable.addColumn("name", Sqlite::StrictColumnType::Text); + typesTable.addColumn("traits", Sqlite::StrictColumnType::Integer); + auto &prototypeIdColumn = typesTable.addForeignKeyColumn("prototypeId", + typesTable, + Sqlite::ForeignKeyAction::NoAction, + Sqlite::ForeignKeyAction::Restrict); + typesTable.addColumn("prototypeNameId", Sqlite::StrictColumnType::Integer); + auto &extensionIdColumn = typesTable.addForeignKeyColumn("extensionId", + typesTable, + Sqlite::ForeignKeyAction::NoAction, + Sqlite::ForeignKeyAction::Restrict); + typesTable.addColumn("extensionNameId", Sqlite::StrictColumnType::Integer); + auto &defaultPropertyIdColumn = typesTable.addColumn("defaultPropertyId", + Sqlite::StrictColumnType::Integer); + typesTable.addColumn("annotationTraits", Sqlite::StrictColumnType::Integer); + typesTable.addUniqueIndex({sourceIdColumn, typesNameColumn}); + typesTable.addIndex({defaultPropertyIdColumn}); + typesTable.addIndex({prototypeIdColumn}); + typesTable.addIndex({extensionIdColumn}); + + typesTable.initialize(database); + + { + Sqlite::StrictTable propertyDeclarationTable; + propertyDeclarationTable.setUseIfNotExists(true); + propertyDeclarationTable.setName("propertyDeclarations"); + propertyDeclarationTable.addColumn("propertyDeclarationId", + Sqlite::StrictColumnType::Integer, + {Sqlite::PrimaryKey{}}); + auto &typeIdColumn = propertyDeclarationTable.addColumn("typeId"); + auto &nameColumn = propertyDeclarationTable.addColumn("name"); + auto &propertyTypeIdColumn = propertyDeclarationTable.addForeignKeyColumn( + "propertyTypeId", + typesTable, + Sqlite::ForeignKeyAction::NoAction, + Sqlite::ForeignKeyAction::Restrict); + propertyDeclarationTable.addColumn("propertyTraits", Sqlite::StrictColumnType::Integer); + propertyDeclarationTable.addColumn("propertyImportedTypeNameId", + Sqlite::StrictColumnType::Integer); + auto &aliasPropertyDeclarationIdColumn = propertyDeclarationTable.addForeignKeyColumn( + "aliasPropertyDeclarationId", + propertyDeclarationTable, + Sqlite::ForeignKeyAction::NoAction, + Sqlite::ForeignKeyAction::Restrict); + auto &aliasPropertyDeclarationTailIdColumn = propertyDeclarationTable.addForeignKeyColumn( + "aliasPropertyDeclarationTailId", + propertyDeclarationTable, + Sqlite::ForeignKeyAction::NoAction, + Sqlite::ForeignKeyAction::Restrict); + + propertyDeclarationTable.addUniqueIndex({typeIdColumn, nameColumn}); + propertyDeclarationTable.addIndex({propertyTypeIdColumn}); + propertyDeclarationTable.addIndex({aliasPropertyDeclarationIdColumn}, + "aliasPropertyDeclarationId IS NOT NULL"); + propertyDeclarationTable.addIndex({aliasPropertyDeclarationTailIdColumn}, + "aliasPropertyDeclarationTailId IS NOT NULL"); + + propertyDeclarationTable.initialize(database); + } + } + + void createExportedTypeNamesTable(Database &database, + const Sqlite::StrictColumn &foreignModuleIdColumn) + { + Sqlite::StrictTable table; + table.setUseIfNotExists(true); + table.setName("exportedTypeNames"); + table.addColumn("exportedTypeNameId", + Sqlite::StrictColumnType::Integer, + {Sqlite::PrimaryKey{}}); + auto &moduleIdColumn = table.addForeignKeyColumn("moduleId", + foreignModuleIdColumn, + Sqlite::ForeignKeyAction::NoAction, + Sqlite::ForeignKeyAction::NoAction); + auto &nameColumn = table.addColumn("name", Sqlite::StrictColumnType::Text); + auto &typeIdColumn = table.addColumn("typeId", Sqlite::StrictColumnType::Integer); + auto &majorVersionColumn = table.addColumn("majorVersion", Sqlite::StrictColumnType::Integer); + auto &minorVersionColumn = table.addColumn("minorVersion", Sqlite::StrictColumnType::Integer); + + table.addUniqueIndex({moduleIdColumn, nameColumn}, + "majorVersion IS NULL AND minorVersion IS NULL"); + table.addUniqueIndex({moduleIdColumn, nameColumn, majorVersionColumn}, + "majorVersion IS NOT NULL AND minorVersion IS NULL"); + table.addUniqueIndex({moduleIdColumn, nameColumn, majorVersionColumn, minorVersionColumn}, + "majorVersion IS NOT NULL AND minorVersion IS NOT NULL"); + + table.addIndex({typeIdColumn}); + table.addIndex({moduleIdColumn, nameColumn}); + + table.initialize(database); + } + + void createImportedTypeNamesTable(Database &database) + { + Sqlite::StrictTable table; + table.setUseIfNotExists(true); + table.setName("importedTypeNames"); + table.addColumn("importedTypeNameId", + Sqlite::StrictColumnType::Integer, + {Sqlite::PrimaryKey{}}); + auto &importOrSourceIdColumn = table.addColumn("importOrSourceId"); + auto &nameColumn = table.addColumn("name", Sqlite::StrictColumnType::Text); + auto &kindColumn = table.addColumn("kind", Sqlite::StrictColumnType::Integer); + + table.addUniqueIndex({kindColumn, importOrSourceIdColumn, nameColumn}); + table.addIndex({nameColumn}); + + table.initialize(database); + } + + void createEnumerationsTable(Database &database) + { + Sqlite::StrictTable table; + table.setUseIfNotExists(true); + table.setName("enumerationDeclarations"); + table.addColumn("enumerationDeclarationId", + Sqlite::StrictColumnType::Integer, + {Sqlite::PrimaryKey{}}); + auto &typeIdColumn = table.addColumn("typeId", Sqlite::StrictColumnType::Integer); + auto &nameColumn = table.addColumn("name", Sqlite::StrictColumnType::Text); + table.addColumn("enumeratorDeclarations", Sqlite::StrictColumnType::Text); + + table.addUniqueIndex({typeIdColumn, nameColumn}); + + table.initialize(database); + } + + void createFunctionsTable(Database &database) + { + Sqlite::StrictTable table; + table.setUseIfNotExists(true); + table.setName("functionDeclarations"); + table.addColumn("functionDeclarationId", + Sqlite::StrictColumnType::Integer, + {Sqlite::PrimaryKey{}}); + auto &typeIdColumn = table.addColumn("typeId", Sqlite::StrictColumnType::Integer); + auto &nameColumn = table.addColumn("name", Sqlite::StrictColumnType::Text); + auto &signatureColumn = table.addColumn("signature", Sqlite::StrictColumnType::Text); + table.addColumn("returnTypeName"); + + table.addUniqueIndex({typeIdColumn, nameColumn, signatureColumn}); + + table.initialize(database); + } + + void createSignalsTable(Database &database) + { + Sqlite::StrictTable table; + table.setUseIfNotExists(true); + table.setName("signalDeclarations"); + table.addColumn("signalDeclarationId", + Sqlite::StrictColumnType::Integer, + {Sqlite::PrimaryKey{}}); + auto &typeIdColumn = table.addColumn("typeId", Sqlite::StrictColumnType::Integer); + auto &nameColumn = table.addColumn("name", Sqlite::StrictColumnType::Text); + auto &signatureColumn = table.addColumn("signature", Sqlite::StrictColumnType::Text); + + table.addUniqueIndex({typeIdColumn, nameColumn, signatureColumn}); + + table.initialize(database); + } + + Sqlite::StrictColumn createModulesTable(Database &database) + { + Sqlite::StrictTable table; + table.setUseIfNotExists(true); + table.setName("modules"); + auto &modelIdColumn = table.addColumn("moduleId", + Sqlite::StrictColumnType::Integer, + {Sqlite::PrimaryKey{}}); + auto &nameColumn = table.addColumn("name", Sqlite::StrictColumnType::Text); + + table.addUniqueIndex({nameColumn}); + + table.initialize(database); + + return std::move(modelIdColumn); + } + + void createModuleExportedImportsTable(Database &database, + const Sqlite::StrictColumn &foreignModuleIdColumn) + { + Sqlite::StrictTable table; + table.setUseIfNotExists(true); + table.setName("moduleExportedImports"); + table.addColumn("moduleExportedImportId", + Sqlite::StrictColumnType::Integer, + {Sqlite::PrimaryKey{}}); + auto &moduleIdColumn = table.addForeignKeyColumn("moduleId", + foreignModuleIdColumn, + Sqlite::ForeignKeyAction::NoAction, + Sqlite::ForeignKeyAction::Cascade, + Sqlite::Enforment::Immediate); + auto &sourceIdColumn = table.addColumn("exportedModuleId", Sqlite::StrictColumnType::Integer); + table.addColumn("isAutoVersion", Sqlite::StrictColumnType::Integer); + table.addColumn("majorVersion", Sqlite::StrictColumnType::Integer); + table.addColumn("minorVersion", Sqlite::StrictColumnType::Integer); + + table.addUniqueIndex({sourceIdColumn, moduleIdColumn}); + + table.initialize(database); + } + + void createDocumentImportsTable(Database &database, + const Sqlite::StrictColumn &foreignModuleIdColumn) + { + Sqlite::StrictTable table; + table.setUseIfNotExists(true); + table.setName("documentImports"); + table.addColumn("importId", Sqlite::StrictColumnType::Integer, {Sqlite::PrimaryKey{}}); + auto &sourceIdColumn = table.addColumn("sourceId", Sqlite::StrictColumnType::Integer); + auto &moduleIdColumn = table.addForeignKeyColumn("moduleId", + foreignModuleIdColumn, + Sqlite::ForeignKeyAction::NoAction, + Sqlite::ForeignKeyAction::Cascade, + Sqlite::Enforment::Immediate); + auto &sourceModuleIdColumn = table.addForeignKeyColumn("sourceModuleId", + foreignModuleIdColumn, + Sqlite::ForeignKeyAction::NoAction, + Sqlite::ForeignKeyAction::Cascade, + Sqlite::Enforment::Immediate); + auto &kindColumn = table.addColumn("kind", Sqlite::StrictColumnType::Integer); + auto &majorVersionColumn = table.addColumn("majorVersion", Sqlite::StrictColumnType::Integer); + auto &minorVersionColumn = table.addColumn("minorVersion", Sqlite::StrictColumnType::Integer); + auto &parentImportIdColumn = table.addColumn("parentImportId", + Sqlite::StrictColumnType::Integer); + + table.addUniqueIndex( + {sourceIdColumn, moduleIdColumn, kindColumn, sourceModuleIdColumn, parentImportIdColumn}, + "majorVersion IS NULL AND minorVersion IS NULL"); + table.addUniqueIndex({sourceIdColumn, + moduleIdColumn, + kindColumn, + sourceModuleIdColumn, + majorVersionColumn, + parentImportIdColumn}, + "majorVersion IS NOT NULL AND minorVersion IS NULL"); + table.addUniqueIndex({sourceIdColumn, + moduleIdColumn, + kindColumn, + sourceModuleIdColumn, + majorVersionColumn, + minorVersionColumn, + parentImportIdColumn}, + "majorVersion IS NOT NULL AND minorVersion IS NOT NULL"); + + table.addIndex({sourceIdColumn, kindColumn}); + + table.initialize(database); + } + + void createFileStatusesTable(Database &database) + { + Sqlite::StrictTable table; + table.setUseIfNotExists(true); + table.setName("fileStatuses"); + table.addColumn("sourceId", + Sqlite::StrictColumnType::Integer, + {Sqlite::PrimaryKey{}, + Sqlite::ForeignKey{"sources", + "sourceId", + Sqlite::ForeignKeyAction::NoAction, + Sqlite::ForeignKeyAction::Cascade}}); + table.addColumn("size", Sqlite::StrictColumnType::Integer); + table.addColumn("lastModified", Sqlite::StrictColumnType::Integer); + + table.initialize(database); + } + + void createProjectDatasTable(Database &database) + { + Sqlite::StrictTable table; + table.setUseIfNotExists(true); + table.setUseWithoutRowId(true); + table.setName("projectDatas"); + auto &projectSourceIdColumn = table.addColumn("projectSourceId", + Sqlite::StrictColumnType::Integer); + auto &sourceIdColumn = table.addColumn("sourceId", Sqlite::StrictColumnType::Integer); + table.addColumn("moduleId", Sqlite::StrictColumnType::Integer); + table.addColumn("fileType", Sqlite::StrictColumnType::Integer); + + table.addPrimaryKeyContraint({projectSourceIdColumn, sourceIdColumn}); + table.addUniqueIndex({sourceIdColumn}); + + table.initialize(database); + } + + void createPropertyEditorPathsTable(Database &database) + { + Sqlite::StrictTable table; + table.setUseIfNotExists(true); + table.setUseWithoutRowId(true); + table.setName("propertyEditorPaths"); + table.addColumn("typeId", Sqlite::StrictColumnType::Integer, {Sqlite::PrimaryKey{}}); + table.addColumn("pathSourceId", Sqlite::StrictColumnType::Integer); + auto &directoryIdColumn = table.addColumn("directoryId", Sqlite::StrictColumnType::Integer); + + table.addIndex({directoryIdColumn}); + + table.initialize(database); + } + + void createTypeAnnotionsTable(Database &database) + { + Sqlite::StrictTable table; + table.setUseIfNotExists(true); + table.setUseWithoutRowId(true); + table.setName("typeAnnotations"); + auto &typeIdColumn = table.addColumn("typeId", + Sqlite::StrictColumnType::Integer, + {Sqlite::PrimaryKey{}}); + auto &sourceIdColumn = table.addColumn("sourceId", Sqlite::StrictColumnType::Integer); + auto &directorySourceIdColumn = table.addColumn("directorySourceId", + Sqlite::StrictColumnType::Integer); + + table.addColumn("iconPath", Sqlite::StrictColumnType::Text); + table.addColumn("itemLibrary", Sqlite::StrictColumnType::Text); + table.addColumn("hints", Sqlite::StrictColumnType::Text); + + table.addUniqueIndex({sourceIdColumn, typeIdColumn}); + table.addIndex({directorySourceIdColumn}); + + table.initialize(database); + } +}; + +ProjectStorage::ProjectStorage(Database &database, bool isInitialized) + : database{database} + , exclusiveTransaction{database} + , initializer{std::make_unique(database, isInitialized)} + , moduleCache{ModuleStorageAdapter{*this}} +{ + NanotraceHR::Tracer tracer{"initialize"_t, projectStorageCategory()}; + + exclusiveTransaction.commit(); + + database.walCheckpointFull(); + + moduleCache.populate(); +} + +ProjectStorage::~ProjectStorage() = default; + +void ProjectStorage::synchronize(Storage::Synchronization::SynchronizationPackage package) +{ + NanotraceHR::Tracer tracer{"synchronize"_t, projectStorageCategory()}; + + TypeIds deletedTypeIds; + Sqlite::withImmediateTransaction(database, [&] { + AliasPropertyDeclarations insertedAliasPropertyDeclarations; + AliasPropertyDeclarations updatedAliasPropertyDeclarations; + + AliasPropertyDeclarations relinkableAliasPropertyDeclarations; + PropertyDeclarations relinkablePropertyDeclarations; + Prototypes relinkablePrototypes; + Prototypes relinkableExtensions; + + TypeIds updatedTypeIds; + updatedTypeIds.reserve(package.types.size()); + + TypeIds typeIdsToBeDeleted; + + std::sort(package.updatedSourceIds.begin(), package.updatedSourceIds.end()); + + synchronizeFileStatuses(package.fileStatuses, package.updatedFileStatusSourceIds); + synchronizeImports(package.imports, + package.updatedSourceIds, + package.moduleDependencies, + package.updatedModuleDependencySourceIds, + package.moduleExportedImports, + package.updatedModuleIds); + synchronizeTypes(package.types, + updatedTypeIds, + insertedAliasPropertyDeclarations, + updatedAliasPropertyDeclarations, + relinkableAliasPropertyDeclarations, + relinkablePropertyDeclarations, + relinkablePrototypes, + relinkableExtensions, + package.updatedSourceIds); + synchronizeTypeAnnotations(package.typeAnnotations, package.updatedTypeAnnotationSourceIds); + synchronizePropertyEditorQmlPaths(package.propertyEditorQmlPaths, + package.updatedPropertyEditorQmlPathSourceIds); + + deleteNotUpdatedTypes(updatedTypeIds, + package.updatedSourceIds, + typeIdsToBeDeleted, + relinkableAliasPropertyDeclarations, + relinkablePropertyDeclarations, + relinkablePrototypes, + relinkableExtensions, + deletedTypeIds); + + relink(relinkableAliasPropertyDeclarations, + relinkablePropertyDeclarations, + relinkablePrototypes, + relinkableExtensions, + deletedTypeIds); + + linkAliases(insertedAliasPropertyDeclarations, updatedAliasPropertyDeclarations); + + synchronizeProjectDatas(package.projectDatas, package.updatedProjectSourceIds); + + commonTypeCache_.resetTypeIds(); + }); + + callRefreshMetaInfoCallback(deletedTypeIds); +} + +void ProjectStorage::synchronizeDocumentImports(Storage::Imports imports, SourceId sourceId) +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"synchronize document imports"_t, + projectStorageCategory(), + keyValue("imports", imports), + keyValue("source id", sourceId)}; + + Sqlite::withImmediateTransaction(database, [&] { + synchronizeDocumentImports(imports, {sourceId}, Storage::Synchronization::ImportKind::Import); + }); +} + +void ProjectStorage::addObserver(ProjectStorageObserver *observer) +{ + NanotraceHR::Tracer tracer{"add observer"_t, projectStorageCategory()}; + observers.push_back(observer); +} + +void ProjectStorage::removeObserver(ProjectStorageObserver *observer) +{ + NanotraceHR::Tracer tracer{"remove observer"_t, projectStorageCategory()}; + observers.removeOne(observer); +} + +ModuleId ProjectStorage::moduleId(Utils::SmallStringView moduleName) const +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"get module id"_t, + projectStorageCategory(), + keyValue("module name", moduleName)}; + + auto moduleId = moduleCache.id(moduleName); + + tracer.end(keyValue("module id", moduleId)); + + return moduleId; +} + +Utils::SmallString ProjectStorage::moduleName(ModuleId moduleId) const +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"get module name"_t, + projectStorageCategory(), + keyValue("module id", moduleId)}; + + if (!moduleId) + throw ModuleDoesNotExists{}; + + auto moduleName = moduleCache.value(moduleId); + + tracer.end(keyValue("module name", moduleName)); + + return moduleName; +} + +TypeId ProjectStorage::typeId(ModuleId moduleId, + Utils::SmallStringView exportedTypeName, + Storage::Version version) const +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"get type id by exported name"_t, + projectStorageCategory(), + keyValue("module id", moduleId), + keyValue("exported type name", exportedTypeName), + keyValue("version", version)}; + + TypeId typeId; + + if (version.minor) { + typeId = selectTypeIdByModuleIdAndExportedNameAndVersionStatement.valueWithTransaction( + moduleId, exportedTypeName, version.major.value, version.minor.value); + + } else if (version.major) { + typeId = selectTypeIdByModuleIdAndExportedNameAndMajorVersionStatement + .valueWithTransaction(moduleId, exportedTypeName, version.major.value); + + } else { + typeId = selectTypeIdByModuleIdAndExportedNameStatement + .valueWithTransaction(moduleId, exportedTypeName); + } + + tracer.end(keyValue("type id", typeId)); + + return typeId; +} + +TypeId ProjectStorage::typeId(ImportedTypeNameId typeNameId) const +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"get type id by imported type name"_t, + projectStorageCategory(), + keyValue("imported type name id", typeNameId)}; + + auto typeId = Sqlite::withDeferredTransaction(database, [&] { return fetchTypeId(typeNameId); }); + + tracer.end(keyValue("type id", typeId)); + + return typeId; +} + +QVarLengthArray ProjectStorage::typeIds(ModuleId moduleId) const +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"get type ids by module id"_t, + projectStorageCategory(), + keyValue("module id", moduleId)}; + + auto typeIds = selectTypeIdsByModuleIdStatement.valuesWithTransaction>( + moduleId); + + tracer.end(keyValue("type ids", typeIds)); + + return typeIds; +} + +Storage::Info::ExportedTypeNames ProjectStorage::exportedTypeNames(TypeId typeId) const +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"get exported type names by type id"_t, + projectStorageCategory(), + keyValue("type id", typeId)}; + + auto exportedTypenames = selectExportedTypesByTypeIdStatement + .valuesWithTransaction(typeId); + + tracer.end(keyValue("exported type names", exportedTypenames)); + + return exportedTypenames; +} + +Storage::Info::ExportedTypeNames ProjectStorage::exportedTypeNames(TypeId typeId, SourceId sourceId) const +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"get exported type names by source id"_t, + projectStorageCategory(), + keyValue("type id", typeId), + keyValue("source id", sourceId)}; + + auto exportedTypenames = selectExportedTypesByTypeIdAndSourceIdStatement + .valuesWithTransaction(typeId, + sourceId); + + tracer.end(keyValue("exported type names", exportedTypenames)); + + return exportedTypenames; +} + +ImportId ProjectStorage::importId(const Storage::Import &import) const +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"get import id by import"_t, + projectStorageCategory(), + keyValue("import", import)}; + + auto importId = Sqlite::withDeferredTransaction(database, [&] { + return fetchImportId(import.sourceId, import); + }); + + tracer.end(keyValue("import id", importId)); + + return importId; +} + +ImportedTypeNameId ProjectStorage::importedTypeNameId(ImportId importId, + Utils::SmallStringView typeName) +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"get imported type name id by import id"_t, + projectStorageCategory(), + keyValue("import id", importId), + keyValue("imported type name", typeName)}; + + auto importedTypeNameId = Sqlite::withDeferredTransaction(database, [&] { + return fetchImportedTypeNameId(Storage::Synchronization::TypeNameKind::QualifiedExported, + importId, + typeName); + }); + + tracer.end(keyValue("imported type name id", importedTypeNameId)); + + return importedTypeNameId; +} + +ImportedTypeNameId ProjectStorage::importedTypeNameId(SourceId sourceId, + Utils::SmallStringView typeName) +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"get imported type name id by source id"_t, + projectStorageCategory(), + keyValue("source id", sourceId), + keyValue("imported type name", typeName)}; + + auto importedTypeNameId = Sqlite::withDeferredTransaction(database, [&] { + return fetchImportedTypeNameId(Storage::Synchronization::TypeNameKind::Exported, + sourceId, + typeName); + }); + + tracer.end(keyValue("imported type name id", importedTypeNameId)); + + return importedTypeNameId; +} + +QVarLengthArray ProjectStorage::propertyDeclarationIds(TypeId typeId) const +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"get property declaration ids"_t, + projectStorageCategory(), + keyValue("type id", typeId)}; + + auto propertyDeclarationIds = Sqlite::withDeferredTransaction(database, [&] { + return fetchPropertyDeclarationIds(typeId); + }); + + std::sort(propertyDeclarationIds.begin(), propertyDeclarationIds.end()); + + tracer.end(keyValue("property declaration ids", propertyDeclarationIds)); + + return propertyDeclarationIds; +} + +QVarLengthArray ProjectStorage::localPropertyDeclarationIds(TypeId typeId) const +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"get local property declaration ids"_t, + projectStorageCategory(), + keyValue("type id", typeId)}; + + auto propertyDeclarationIds = selectLocalPropertyDeclarationIdsForTypeStatement + .valuesWithTransaction>( + typeId); + + tracer.end(keyValue("property declaration ids", propertyDeclarationIds)); + + return propertyDeclarationIds; +} + +PropertyDeclarationId ProjectStorage::propertyDeclarationId(TypeId typeId, + Utils::SmallStringView propertyName) const +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"get property declaration id"_t, + projectStorageCategory(), + keyValue("type id", typeId), + keyValue("property name", propertyName)}; + + auto propertyDeclarationId = Sqlite::withDeferredTransaction(database, [&] { + return fetchPropertyDeclarationId(typeId, propertyName); + }); + + tracer.end(keyValue("property declaration id", propertyDeclarationId)); + + return propertyDeclarationId; +} + +PropertyDeclarationId ProjectStorage::localPropertyDeclarationId(TypeId typeId, + Utils::SmallStringView propertyName) const +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"get local property declaration id"_t, + projectStorageCategory(), + keyValue("type id", typeId), + keyValue("property name", propertyName)}; + + auto propertyDeclarationId = selectLocalPropertyDeclarationIdForTypeAndPropertyNameStatement + .valueWithTransaction(typeId, + propertyName); + + tracer.end(keyValue("property declaration id", propertyDeclarationId)); + + return propertyDeclarationId; +} + +PropertyDeclarationId ProjectStorage::defaultPropertyDeclarationId(TypeId typeId) const +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"get default property declaration id"_t, + projectStorageCategory(), + keyValue("type id", typeId)}; + + auto propertyDeclarationId = Sqlite::withDeferredTransaction(database, [&] { + return fetchDefaultPropertyDeclarationId(typeId); + }); + + tracer.end(keyValue("property declaration id", propertyDeclarationId)); + + return propertyDeclarationId; +} + +std::optional ProjectStorage::propertyDeclaration( + PropertyDeclarationId propertyDeclarationId) const +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"get property declaration"_t, + projectStorageCategory(), + keyValue("property declaration id", propertyDeclarationId)}; + + auto propertyDeclaration = selectPropertyDeclarationForPropertyDeclarationIdStatement + .optionalValueWithTransaction( + propertyDeclarationId); + + tracer.end(keyValue("property declaration", propertyDeclaration)); + + return propertyDeclaration; +} + +std::optional ProjectStorage::type(TypeId typeId) const +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"get type"_t, projectStorageCategory(), keyValue("type id", typeId)}; + + auto type = selectInfoTypeByTypeIdStatement.optionalValueWithTransaction( + typeId); + + tracer.end(keyValue("type", type)); + + return type; +} + +Utils::PathString ProjectStorage::typeIconPath(TypeId typeId) const +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"get type icon path"_t, + projectStorageCategory(), + keyValue("type id", typeId)}; + + auto typeIconPath = selectTypeIconPathStatement.valueWithTransaction(typeId); + + tracer.end(keyValue("type icon path", typeIconPath)); + + return typeIconPath; +} + +Storage::Info::TypeHints ProjectStorage::typeHints(TypeId typeId) const +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"get type hints"_t, + projectStorageCategory(), + keyValue("type id", typeId)}; + + auto typeHints = selectTypeHintsStatement.valuesWithTransaction( + typeId); + + tracer.end(keyValue("type hints", typeHints)); + + return typeHints; +} + +SmallSourceIds<4> ProjectStorage::typeAnnotationSourceIds(SourceId directoryId) const +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"get type annotaion source ids"_t, + projectStorageCategory(), + keyValue("source id", directoryId)}; + + auto sourceIds = selectTypeAnnotationSourceIdsStatement.valuesWithTransaction>( + directoryId); + + tracer.end(keyValue("source ids", sourceIds)); + + return sourceIds; +} + +SmallSourceIds<64> ProjectStorage::typeAnnotationDirectorySourceIds() const +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"get type annotaion source ids"_t, projectStorageCategory()}; + + auto sourceIds = selectTypeAnnotationDirectorySourceIdsStatement + .valuesWithTransaction>(); + + tracer.end(keyValue("source ids", sourceIds)); + + return sourceIds; +} + +Storage::Info::ItemLibraryEntries ProjectStorage::itemLibraryEntries(TypeId typeId) const +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"get item library entries by type id"_t, + projectStorageCategory(), + keyValue("type id", typeId)}; + + using Storage::Info::ItemLibraryProperties; + Storage::Info::ItemLibraryEntries entries; + + auto callback = [&](TypeId typeId_, + Utils::SmallStringView name, + Utils::SmallStringView iconPath, + Utils::SmallStringView category, + Utils::SmallStringView import, + Utils::SmallStringView toolTip, + Utils::SmallStringView properties, + Utils::SmallStringView extraFilePaths, + Utils::SmallStringView templatePath) { + auto &last = entries.emplace_back(typeId_, name, iconPath, category, import, toolTip, templatePath); + if (properties.size()) + selectItemLibraryPropertiesStatement.readTo(last.properties, properties); + if (extraFilePaths.size()) + selectItemLibraryExtraFilePathsStatement.readTo(last.extraFilePaths, extraFilePaths); + }; + + selectItemLibraryEntriesByTypeIdStatement.readCallbackWithTransaction(callback, typeId); + + tracer.end(keyValue("item library entries", entries)); + + return entries; +} + +Storage::Info::ItemLibraryEntries ProjectStorage::itemLibraryEntries(ImportId importId) const +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"get item library entries by import id"_t, + projectStorageCategory(), + keyValue("import id", importId)}; + + using Storage::Info::ItemLibraryProperties; + Storage::Info::ItemLibraryEntries entries; + + auto callback = [&](TypeId typeId_, + Utils::SmallStringView name, + Utils::SmallStringView iconPath, + Utils::SmallStringView category, + Utils::SmallStringView import, + Utils::SmallStringView toolTip, + Utils::SmallStringView properties, + Utils::SmallStringView extraFilePaths, + Utils::SmallStringView templatePath) { + auto &last = entries.emplace_back(typeId_, name, iconPath, category, import, toolTip, templatePath); + if (properties.size()) + selectItemLibraryPropertiesStatement.readTo(last.properties, properties); + if (extraFilePaths.size()) + selectItemLibraryExtraFilePathsStatement.readTo(last.extraFilePaths, extraFilePaths); + }; + + selectItemLibraryEntriesByTypeIdStatement.readCallbackWithTransaction(callback, importId); + + tracer.end(keyValue("item library entries", entries)); + + return entries; +} + +Storage::Info::ItemLibraryEntries ProjectStorage::itemLibraryEntries(SourceId sourceId) const +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"get item library entries by source id"_t, + projectStorageCategory(), + keyValue("source id", sourceId)}; + + using Storage::Info::ItemLibraryProperties; + Storage::Info::ItemLibraryEntries entries; + + auto callback = [&](TypeId typeId, + Utils::SmallStringView name, + Utils::SmallStringView iconPath, + Utils::SmallStringView category, + Utils::SmallStringView import, + Utils::SmallStringView toolTip, + Utils::SmallStringView properties, + Utils::SmallStringView extraFilePaths, + Utils::SmallStringView templatePath) { + auto &last = entries.emplace_back(typeId, name, iconPath, category, import, toolTip, templatePath); + if (properties.size()) + selectItemLibraryPropertiesStatement.readTo(last.properties, properties); + if (extraFilePaths.size()) + selectItemLibraryExtraFilePathsStatement.readTo(last.extraFilePaths, extraFilePaths); + }; + + selectItemLibraryEntriesBySourceIdStatement.readCallbackWithTransaction(callback, sourceId); + + tracer.end(keyValue("item library entries", entries)); + + return entries; +} + +Storage::Info::ItemLibraryEntries ProjectStorage::allItemLibraryEntries() const +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"get all item library entries"_t, projectStorageCategory()}; + + using Storage::Info::ItemLibraryProperties; + Storage::Info::ItemLibraryEntries entries; + + auto callback = [&](TypeId typeId, + Utils::SmallStringView name, + Utils::SmallStringView iconPath, + Utils::SmallStringView category, + Utils::SmallStringView import, + Utils::SmallStringView toolTip, + Utils::SmallStringView properties, + Utils::SmallStringView extraFilePaths, + Utils::SmallStringView templatePath) { + auto &last = entries.emplace_back(typeId, name, iconPath, category, import, toolTip, templatePath); + if (properties.size()) + selectItemLibraryPropertiesStatement.readTo(last.properties, properties); + if (extraFilePaths.size()) + selectItemLibraryExtraFilePathsStatement.readTo(last.extraFilePaths, extraFilePaths); + }; + + selectItemLibraryEntriesStatement.readCallbackWithTransaction(callback); + + tracer.end(keyValue("item library entries", entries)); + + return entries; +} + +std::vector ProjectStorage::signalDeclarationNames(TypeId typeId) const +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"get signal names"_t, + projectStorageCategory(), + keyValue("type id", typeId)}; + + auto signalDeclarationNames = selectSignalDeclarationNamesForTypeStatement + .valuesWithTransaction(typeId); + + tracer.end(keyValue("signal names", signalDeclarationNames)); + + return signalDeclarationNames; +} + +std::vector ProjectStorage::functionDeclarationNames(TypeId typeId) const +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"get function names"_t, + projectStorageCategory(), + keyValue("type id", typeId)}; + + auto functionDeclarationNames = selectFuncionDeclarationNamesForTypeStatement + .valuesWithTransaction(typeId); + + tracer.end(keyValue("function names", functionDeclarationNames)); + + return functionDeclarationNames; +} + +std::optional ProjectStorage::propertyName( + PropertyDeclarationId propertyDeclarationId) const +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"get property name"_t, + projectStorageCategory(), + keyValue("property declaration id", propertyDeclarationId)}; + + auto propertyName = selectPropertyNameStatement.optionalValueWithTransaction( + propertyDeclarationId); + + tracer.end(keyValue("property name", propertyName)); + + return propertyName; +} + +SmallTypeIds<16> ProjectStorage::prototypeIds(TypeId type) const +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"get prototypes"_t, projectStorageCategory(), keyValue("type id", type)}; + + auto prototypeIds = selectPrototypeAndExtensionIdsStatement.valuesWithTransaction>( + type); + + tracer.end(keyValue("type ids", prototypeIds)); + + return prototypeIds; +} + +SmallTypeIds<16> ProjectStorage::prototypeAndSelfIds(TypeId typeId) const +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"get prototypes and self"_t, projectStorageCategory()}; + + SmallTypeIds<16> prototypeAndSelfIds; + prototypeAndSelfIds.push_back(typeId); + + selectPrototypeAndExtensionIdsStatement.readToWithTransaction(prototypeAndSelfIds, typeId); + + tracer.end(keyValue("type ids", prototypeAndSelfIds)); + + return prototypeAndSelfIds; +} + +SmallTypeIds<64> ProjectStorage::heirIds(TypeId typeId) const +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"get heirs"_t, projectStorageCategory()}; + + auto heirIds = selectHeirTypeIdsStatement.valuesWithTransaction>(typeId); + + tracer.end(keyValue("type ids", heirIds)); + + return heirIds; +} + +bool ProjectStorage::isBasedOn(TypeId) const +{ + return false; +} + +bool ProjectStorage::isBasedOn(TypeId typeId, TypeId id1) const +{ + return isBasedOn_(typeId, id1); +} + +bool ProjectStorage::isBasedOn(TypeId typeId, TypeId id1, TypeId id2) const +{ + return isBasedOn_(typeId, id1, id2); +} + +bool ProjectStorage::isBasedOn(TypeId typeId, TypeId id1, TypeId id2, TypeId id3) const +{ + return isBasedOn_(typeId, id1, id2, id3); +} + +bool ProjectStorage::isBasedOn(TypeId typeId, TypeId id1, TypeId id2, TypeId id3, TypeId id4) const +{ + return isBasedOn_(typeId, id1, id2, id3, id4); +} + +bool ProjectStorage::isBasedOn(TypeId typeId, TypeId id1, TypeId id2, TypeId id3, TypeId id4, TypeId id5) const +{ + return isBasedOn_(typeId, id1, id2, id3, id4, id5); +} + +bool ProjectStorage::isBasedOn( + TypeId typeId, TypeId id1, TypeId id2, TypeId id3, TypeId id4, TypeId id5, TypeId id6) const +{ + return isBasedOn_(typeId, id1, id2, id3, id4, id5, id6); +} + +bool ProjectStorage::isBasedOn( + TypeId typeId, TypeId id1, TypeId id2, TypeId id3, TypeId id4, TypeId id5, TypeId id6, TypeId id7) const +{ + return isBasedOn_(typeId, id1, id2, id3, id4, id5, id6, id7); +} + +TypeId ProjectStorage::fetchTypeIdByExportedName(Utils::SmallStringView name) const +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"is based on"_t, + projectStorageCategory(), + keyValue("exported type name", name)}; + + auto typeId = selectTypeIdByExportedNameStatement.valueWithTransaction(name); + + tracer.end(keyValue("type id", typeId)); + + return typeId; +} + +TypeId ProjectStorage::fetchTypeIdByModuleIdsAndExportedName(ModuleIds moduleIds, + Utils::SmallStringView name) const +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"fetch type id by module ids and exported name"_t, + projectStorageCategory(), + keyValue("module ids", NanotraceHR::array(moduleIds)), + keyValue("exported type name", name)}; + auto typeId = selectTypeIdByModuleIdsAndExportedNameStatement.valueWithTransaction( + static_cast(moduleIds.data()), static_cast(moduleIds.size()), name); + + tracer.end(keyValue("type id", typeId)); + + return typeId; +} + +TypeId ProjectStorage::fetchTypeIdByName(SourceId sourceId, Utils::SmallStringView name) +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"fetch type id by name"_t, + projectStorageCategory(), + keyValue("source id", sourceId), + keyValue("internal type name", name)}; + + auto typeId = selectTypeIdBySourceIdAndNameStatement.valueWithTransaction(sourceId, name); + + tracer.end(keyValue("type id", typeId)); + + return typeId; +} + +Storage::Synchronization::Type ProjectStorage::fetchTypeByTypeId(TypeId typeId) +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"fetch type by type id"_t, + projectStorageCategory(), + keyValue("type id", typeId)}; + + auto type = Sqlite::withDeferredTransaction(database, [&] { + auto type = selectTypeByTypeIdStatement.value(typeId); + + type.exportedTypes = fetchExportedTypes(typeId); + type.propertyDeclarations = fetchPropertyDeclarations(type.typeId); + type.functionDeclarations = fetchFunctionDeclarations(type.typeId); + type.signalDeclarations = fetchSignalDeclarations(type.typeId); + type.enumerationDeclarations = fetchEnumerationDeclarations(type.typeId); + + return type; + }); + + tracer.end(keyValue("type", type)); + + return type; +} + +Storage::Synchronization::Types ProjectStorage::fetchTypes() +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"fetch types"_t, projectStorageCategory()}; + + auto types = Sqlite::withDeferredTransaction(database, [&] { + auto types = selectTypesStatement.values(); + + for (Storage::Synchronization::Type &type : types) { + type.exportedTypes = fetchExportedTypes(type.typeId); + type.propertyDeclarations = fetchPropertyDeclarations(type.typeId); + type.functionDeclarations = fetchFunctionDeclarations(type.typeId); + type.signalDeclarations = fetchSignalDeclarations(type.typeId); + type.enumerationDeclarations = fetchEnumerationDeclarations(type.typeId); + } + + return types; + }); + + tracer.end(keyValue("type", types)); + + return types; +} + +SourceContextId ProjectStorage::fetchSourceContextIdUnguarded(Utils::SmallStringView sourceContextPath) +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"fetch source context id unguarded"_t, projectStorageCategory()}; + + auto sourceContextId = readSourceContextId(sourceContextPath); + + return sourceContextId ? sourceContextId : writeSourceContextId(sourceContextPath); +} + +SourceContextId ProjectStorage::fetchSourceContextId(Utils::SmallStringView sourceContextPath) +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"fetch source context id"_t, + projectStorageCategory(), + keyValue("source context path", sourceContextPath)}; + + SourceContextId sourceContextId; + try { + sourceContextId = Sqlite::withDeferredTransaction(database, [&] { + return fetchSourceContextIdUnguarded(sourceContextPath); + }); + } catch (const Sqlite::ConstraintPreventsModification &) { + sourceContextId = fetchSourceContextId(sourceContextPath); + } + + tracer.end(keyValue("source context id", sourceContextId)); + + return sourceContextId; +} + +Utils::PathString ProjectStorage::fetchSourceContextPath(SourceContextId sourceContextId) const +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"fetch source context path"_t, + projectStorageCategory(), + keyValue("source context id", sourceContextId)}; + + auto path = Sqlite::withDeferredTransaction(database, [&] { + auto optionalSourceContextPath = selectSourceContextPathFromSourceContextsBySourceContextIdStatement + .optionalValue(sourceContextId); + + if (!optionalSourceContextPath) + throw SourceContextIdDoesNotExists(); + + return std::move(*optionalSourceContextPath); + }); + + tracer.end(keyValue("source context path", path)); + + return path; +} + +Cache::SourceContexts ProjectStorage::fetchAllSourceContexts() const +{ + NanotraceHR::Tracer tracer{"fetch all source contexts"_t, projectStorageCategory()}; + + return selectAllSourceContextsStatement.valuesWithTransaction(); +} + +SourceId ProjectStorage::fetchSourceId(SourceContextId sourceContextId, + Utils::SmallStringView sourceName) +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"fetch source id"_t, + projectStorageCategory(), + keyValue("source context id", sourceContextId), + keyValue("source name", sourceName)}; + + auto sourceId = Sqlite::withDeferredTransaction(database, [&] { + return fetchSourceIdUnguarded(sourceContextId, sourceName); + }); + + tracer.end(keyValue("source id", sourceId)); + + return sourceId; +} + +Cache::SourceNameAndSourceContextId ProjectStorage::fetchSourceNameAndSourceContextId(SourceId sourceId) const +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"fetch source name and source context id"_t, + projectStorageCategory(), + keyValue("source id", sourceId)}; + + auto value = selectSourceNameAndSourceContextIdFromSourcesBySourceIdStatement + .valueWithTransaction(sourceId); + + if (!value.sourceContextId) + throw SourceIdDoesNotExists(); + + tracer.end(keyValue("source name", value.sourceName), + keyValue("source context id", value.sourceContextId)); + + return value; +} + +void ProjectStorage::clearSources() +{ + Sqlite::withImmediateTransaction(database, [&] { + deleteAllSourceContextsStatement.execute(); + deleteAllSourcesStatement.execute(); + }); +} + +SourceContextId ProjectStorage::fetchSourceContextId(SourceId sourceId) const +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"fetch source context id"_t, + projectStorageCategory(), + keyValue("source id", sourceId)}; + + auto sourceContextId = selectSourceContextIdFromSourcesBySourceIdStatement + .valueWithTransaction(sourceId); + + if (!sourceContextId) + throw SourceIdDoesNotExists(); + + tracer.end(keyValue("source context id", sourceContextId)); + + return sourceContextId; +} + +Cache::Sources ProjectStorage::fetchAllSources() const +{ + NanotraceHR::Tracer tracer{"fetch all sources"_t, projectStorageCategory()}; + + return selectAllSourcesStatement.valuesWithTransaction(); +} + +SourceId ProjectStorage::fetchSourceIdUnguarded(SourceContextId sourceContextId, + Utils::SmallStringView sourceName) +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"fetch source id unguarded"_t, + projectStorageCategory(), + keyValue("source context id", sourceContextId), + keyValue("source name", sourceName)}; + + auto sourceId = readSourceId(sourceContextId, sourceName); + + if (!sourceId) + sourceId = writeSourceId(sourceContextId, sourceName); + + tracer.end(keyValue("source id", sourceId)); + + return sourceId; +} + +FileStatus ProjectStorage::fetchFileStatus(SourceId sourceId) const +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"fetch file status"_t, + projectStorageCategory(), + keyValue("source id", sourceId)}; + + auto fileStatus = selectFileStatusesForSourceIdStatement.valueWithTransaction(sourceId); + + tracer.end(keyValue("file status", fileStatus)); + + return fileStatus; +} + +std::optional ProjectStorage::fetchProjectData(SourceId sourceId) const +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"fetch project data"_t, + projectStorageCategory(), + keyValue("source id", sourceId)}; + + auto projectData = selectProjectDataForSourceIdStatement + .optionalValueWithTransaction( + sourceId); + + tracer.end(keyValue("project data", projectData)); + + return projectData; +} + +Storage::Synchronization::ProjectDatas ProjectStorage::fetchProjectDatas(SourceId projectSourceId) const +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"fetch project datas by source id"_t, + projectStorageCategory(), + keyValue("source id", projectSourceId)}; + + auto projectDatas = selectProjectDatasForSourceIdStatement + .valuesWithTransaction( + projectSourceId); + + tracer.end(keyValue("project datas", projectDatas)); + + return projectDatas; +} + +Storage::Synchronization::ProjectDatas ProjectStorage::fetchProjectDatas( + const SourceIds &projectSourceIds) const +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"fetch project datas by source ids"_t, + projectStorageCategory(), + keyValue("source ids", projectSourceIds)}; + + auto projectDatas = selectProjectDatasForSourceIdsStatement + .valuesWithTransaction( + toIntegers(projectSourceIds)); + + tracer.end(keyValue("project datas", projectDatas)); + + return projectDatas; +} + +void ProjectStorage::setPropertyEditorPathId(TypeId typeId, SourceId pathId) +{ + Sqlite::ImmediateSessionTransaction transaction{database}; + + upsertPropertyEditorPathIdStatement.write(typeId, pathId); + + transaction.commit(); +} + +SourceId ProjectStorage::propertyEditorPathId(TypeId typeId) const +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"property editor path id"_t, + projectStorageCategory(), + keyValue("type id", typeId)}; + + auto sourceId = selectPropertyEditorPathIdStatement.valueWithTransaction(typeId); + + tracer.end(keyValue("source id", sourceId)); + + return sourceId; +} + +Storage::Imports ProjectStorage::fetchDocumentImports() const +{ + NanotraceHR::Tracer tracer{"fetch document imports"_t, projectStorageCategory()}; + + return selectAllDocumentImportForSourceIdStatement.valuesWithTransaction(); +} + +void ProjectStorage::resetForTestsOnly() +{ + database.clearAllTablesForTestsOnly(); + commonTypeCache_.clearForTestsOnly(); + moduleCache.clearForTestOnly(); +} + +bool ProjectStorage::moduleNameLess(Utils::SmallStringView first, Utils::SmallStringView second) noexcept +{ + return first < second; +} + +ModuleId ProjectStorage::fetchModuleId(Utils::SmallStringView moduleName) +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"fetch module id"_t, + projectStorageCategory(), + keyValue("module name", moduleName)}; + + auto moduleId = Sqlite::withDeferredTransaction(database, [&] { + return fetchModuleIdUnguarded(moduleName); + }); + + tracer.end(keyValue("module id", moduleId)); + + return moduleId; +} + +Utils::PathString ProjectStorage::fetchModuleName(ModuleId id) +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"fetch module name"_t, + projectStorageCategory(), + keyValue("module id", id)}; + + auto moduleName = Sqlite::withDeferredTransaction(database, + [&] { return fetchModuleNameUnguarded(id); }); + + tracer.end(keyValue("module name", moduleName)); + + return moduleName; +} + +ProjectStorage::Modules ProjectStorage::fetchAllModules() const +{ + NanotraceHR::Tracer tracer{"fetch all modules"_t, projectStorageCategory()}; + + return selectAllModulesStatement.valuesWithTransaction(); +} + +void ProjectStorage::callRefreshMetaInfoCallback(const TypeIds &deletedTypeIds) +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"call refresh meta info callback"_t, + projectStorageCategory(), + keyValue("type ids", deletedTypeIds)}; + + if (deletedTypeIds.size()) { + for (ProjectStorageObserver *observer : observers) + observer->removedTypeIds(deletedTypeIds); + } +} + +SourceIds ProjectStorage::filterSourceIdsWithoutType(const SourceIds &updatedSourceIds, + SourceIds &sourceIdsOfTypes) +{ + std::sort(sourceIdsOfTypes.begin(), sourceIdsOfTypes.end()); + + SourceIds sourceIdsWithoutTypeSourceIds; + sourceIdsWithoutTypeSourceIds.reserve(updatedSourceIds.size()); + std::set_difference(updatedSourceIds.begin(), + updatedSourceIds.end(), + sourceIdsOfTypes.begin(), + sourceIdsOfTypes.end(), + std::back_inserter(sourceIdsWithoutTypeSourceIds)); + + return sourceIdsWithoutTypeSourceIds; +} + +TypeIds ProjectStorage::fetchTypeIds(const SourceIds &sourceIds) +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"fetch type ids"_t, + projectStorageCategory(), + keyValue("source ids", sourceIds)}; + + return selectTypeIdsForSourceIdsStatement.values(toIntegers(sourceIds)); +} + +void ProjectStorage::unique(SourceIds &sourceIds) +{ + std::sort(sourceIds.begin(), sourceIds.end()); + auto newEnd = std::unique(sourceIds.begin(), sourceIds.end()); + sourceIds.erase(newEnd, sourceIds.end()); +} + +void ProjectStorage::synchronizeTypeTraits(TypeId typeId, Storage::TypeTraits traits) +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"synchronize type traits"_t, + projectStorageCategory(), + keyValue("type id", typeId), + keyValue("type traits", traits)}; + + updateTypeAnnotationTraitStatement.write(typeId, traits.annotation); +} + +void ProjectStorage::updateTypeIdInTypeAnnotations(Storage::Synchronization::TypeAnnotations &typeAnnotations) +{ + NanotraceHR::Tracer tracer{"update type id in type annotations"_t, projectStorageCategory()}; + + for (auto &annotation : typeAnnotations) { + annotation.typeId = fetchTypeIdByModuleIdAndExportedName(annotation.moduleId, + annotation.typeName); + } + + for (auto &annotation : typeAnnotations) { + if (!annotation.typeId) + qWarning() << moduleName(annotation.moduleId).toQString() + << annotation.typeName.toQString(); + } + + typeAnnotations.erase(std::remove_if(typeAnnotations.begin(), + typeAnnotations.end(), + [](const auto &annotation) { return !annotation.typeId; }), + typeAnnotations.end()); +} + +void ProjectStorage::synchronizeTypeAnnotations(Storage::Synchronization::TypeAnnotations &typeAnnotations, + const SourceIds &updatedTypeAnnotationSourceIds) +{ + NanotraceHR::Tracer tracer{"synchronize type annotations"_t, projectStorageCategory()}; + + using Storage::Synchronization::TypeAnnotation; + + updateTypeIdInTypeAnnotations(typeAnnotations); + + auto compareKey = [](auto &&first, auto &&second) { return first.typeId - second.typeId; }; + + std::sort(typeAnnotations.begin(), typeAnnotations.end(), [&](auto &&first, auto &&second) { + return first.typeId < second.typeId; + }); + + auto range = selectTypeAnnotationsForSourceIdsStatement.range( + toIntegers(updatedTypeAnnotationSourceIds)); + + auto insert = [&](const TypeAnnotation &annotation) { + if (!annotation.sourceId) + throw TypeAnnotationHasInvalidSourceId{}; + + synchronizeTypeTraits(annotation.typeId, annotation.traits); + + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"insert type annotations"_t, + projectStorageCategory(), + keyValue("type annotation", annotation)}; + + insertTypeAnnotationStatement.write(annotation.typeId, + annotation.sourceId, + annotation.directorySourceId, + annotation.iconPath, + createEmptyAsNull(annotation.itemLibraryJson), + createEmptyAsNull(annotation.hintsJson)); + }; + + auto update = [&](const TypeAnnotationView &annotationFromDatabase, + const TypeAnnotation &annotation) { + synchronizeTypeTraits(annotation.typeId, annotation.traits); + + if (annotationFromDatabase.iconPath != annotation.iconPath + || annotationFromDatabase.itemLibraryJson != annotation.itemLibraryJson + || annotationFromDatabase.hintsJson != annotation.hintsJson) { + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"update type annotations"_t, + projectStorageCategory(), + keyValue("type annotation from database", + annotationFromDatabase), + keyValue("type annotation", annotation)}; + + updateTypeAnnotationStatement.write(annotation.typeId, + annotation.iconPath, + createEmptyAsNull(annotation.itemLibraryJson), + createEmptyAsNull(annotation.hintsJson)); + return Sqlite::UpdateChange::Update; + } + + return Sqlite::UpdateChange::No; + }; + + auto remove = [&](const TypeAnnotationView &annotationFromDatabase) { + synchronizeTypeTraits(annotationFromDatabase.typeId, Storage::TypeTraits{}); + + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"remove type annotations"_t, + projectStorageCategory(), + keyValue("type annotation", annotationFromDatabase)}; + + deleteTypeAnnotationStatement.write(annotationFromDatabase.typeId); + }; + + Sqlite::insertUpdateDelete(range, typeAnnotations, compareKey, insert, update, remove); +} + +void ProjectStorage::synchronizeTypeTrait(const Storage::Synchronization::Type &type) +{ + updateTypeTraitStatement.write(type.typeId, type.traits.type); +} + +void ProjectStorage::synchronizeTypes(Storage::Synchronization::Types &types, + TypeIds &updatedTypeIds, + AliasPropertyDeclarations &insertedAliasPropertyDeclarations, + AliasPropertyDeclarations &updatedAliasPropertyDeclarations, + AliasPropertyDeclarations &relinkableAliasPropertyDeclarations, + PropertyDeclarations &relinkablePropertyDeclarations, + Prototypes &relinkablePrototypes, + Prototypes &relinkableExtensions, + const SourceIds &updatedSourceIds) +{ + NanotraceHR::Tracer tracer{"synchronize types"_t, projectStorageCategory()}; + + Storage::Synchronization::ExportedTypes exportedTypes; + exportedTypes.reserve(types.size() * 3); + SourceIds sourceIdsOfTypes; + sourceIdsOfTypes.reserve(updatedSourceIds.size()); + SourceIds notUpdatedExportedSourceIds; + notUpdatedExportedSourceIds.reserve(updatedSourceIds.size()); + SourceIds exportedSourceIds; + exportedSourceIds.reserve(types.size()); + + for (auto &type : types) { + if (!type.sourceId) + throw TypeHasInvalidSourceId{}; + + TypeId typeId = declareType(type); + synchronizeTypeTrait(type); + sourceIdsOfTypes.push_back(type.sourceId); + updatedTypeIds.push_back(typeId); + if (type.changeLevel != Storage::Synchronization::ChangeLevel::ExcludeExportedTypes) { + exportedSourceIds.push_back(type.sourceId); + extractExportedTypes(typeId, type, exportedTypes); + } + } + + std::sort(types.begin(), types.end(), [](const auto &first, const auto &second) { + return first.typeId < second.typeId; + }); + + unique(exportedSourceIds); + + SourceIds sourceIdsWithoutType = filterSourceIdsWithoutType(updatedSourceIds, sourceIdsOfTypes); + exportedSourceIds.insert(exportedSourceIds.end(), + sourceIdsWithoutType.begin(), + sourceIdsWithoutType.end()); + TypeIds exportedTypeIds = fetchTypeIds(exportedSourceIds); + synchronizeExportedTypes(exportedTypeIds, + exportedTypes, + relinkableAliasPropertyDeclarations, + relinkablePropertyDeclarations, + relinkablePrototypes, + relinkableExtensions); + + syncPrototypesAndExtensions(types, relinkablePrototypes, relinkableExtensions); + resetDefaultPropertiesIfChanged(types); + resetRemovedAliasPropertyDeclarationsToNull(types, relinkableAliasPropertyDeclarations); + syncDeclarations(types, + insertedAliasPropertyDeclarations, + updatedAliasPropertyDeclarations, + relinkablePropertyDeclarations); + syncDefaultProperties(types); +} + +void ProjectStorage::synchronizeProjectDatas(Storage::Synchronization::ProjectDatas &projectDatas, + const SourceIds &updatedProjectSourceIds) +{ + NanotraceHR::Tracer tracer{"synchronize project datas"_t, projectStorageCategory()}; + + auto compareKey = [](auto &&first, auto &&second) { + auto projectSourceIdDifference = first.projectSourceId - second.projectSourceId; + if (projectSourceIdDifference != 0) + return projectSourceIdDifference; + + return first.sourceId - second.sourceId; + }; + + std::sort(projectDatas.begin(), projectDatas.end(), [&](auto &&first, auto &&second) { + return std::tie(first.projectSourceId, first.sourceId) + < std::tie(second.projectSourceId, second.sourceId); + }); + + auto range = selectProjectDatasForSourceIdsStatement.range( + toIntegers(updatedProjectSourceIds)); + + auto insert = [&](const Storage::Synchronization::ProjectData &projectData) { + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"insert project data"_t, + projectStorageCategory(), + keyValue("project data", projectData)}; + + if (!projectData.projectSourceId) + throw ProjectDataHasInvalidProjectSourceId{}; + if (!projectData.sourceId) + throw ProjectDataHasInvalidSourceId{}; + + insertProjectDataStatement.write(projectData.projectSourceId, + projectData.sourceId, + projectData.moduleId, + projectData.fileType); + }; + + auto update = [&](const Storage::Synchronization::ProjectData &projectDataFromDatabase, + const Storage::Synchronization::ProjectData &projectData) { + if (projectDataFromDatabase.fileType != projectData.fileType + || !compareInvalidAreTrue(projectDataFromDatabase.moduleId, projectData.moduleId)) { + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"update project data"_t, + projectStorageCategory(), + keyValue("project data", projectData), + keyValue("project data from database", projectDataFromDatabase)}; + + updateProjectDataStatement.write(projectData.projectSourceId, + projectData.sourceId, + projectData.moduleId, + projectData.fileType); + return Sqlite::UpdateChange::Update; + } + + return Sqlite::UpdateChange::No; + }; + + auto remove = [&](const Storage::Synchronization::ProjectData &projectData) { + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"remove project data"_t, + projectStorageCategory(), + keyValue("project data", projectData)}; + + deleteProjectDataStatement.write(projectData.projectSourceId, projectData.sourceId); + }; + + Sqlite::insertUpdateDelete(range, projectDatas, compareKey, insert, update, remove); +} + +void ProjectStorage::synchronizeFileStatuses(FileStatuses &fileStatuses, + const SourceIds &updatedSourceIds) +{ + NanotraceHR::Tracer tracer{"synchronize file statuses"_t, projectStorageCategory()}; + + auto compareKey = [](auto &&first, auto &&second) { return first.sourceId - second.sourceId; }; + + std::sort(fileStatuses.begin(), fileStatuses.end(), [&](auto &&first, auto &&second) { + return first.sourceId < second.sourceId; + }); + + auto range = selectFileStatusesForSourceIdsStatement.range( + toIntegers(updatedSourceIds)); + + auto insert = [&](const FileStatus &fileStatus) { + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"insert file status"_t, + projectStorageCategory(), + keyValue("file status", fileStatus)}; + + if (!fileStatus.sourceId) + throw FileStatusHasInvalidSourceId{}; + insertFileStatusStatement.write(fileStatus.sourceId, fileStatus.size, fileStatus.lastModified); + }; + + auto update = [&](const FileStatus &fileStatusFromDatabase, const FileStatus &fileStatus) { + if (fileStatusFromDatabase.lastModified != fileStatus.lastModified + || fileStatusFromDatabase.size != fileStatus.size) { + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"update file status"_t, + projectStorageCategory(), + keyValue("file status", fileStatus), + keyValue("file status from database", fileStatusFromDatabase)}; + + updateFileStatusStatement.write(fileStatus.sourceId, + fileStatus.size, + fileStatus.lastModified); + return Sqlite::UpdateChange::Update; + } + + return Sqlite::UpdateChange::No; + }; + + auto remove = [&](const FileStatus &fileStatus) { + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"remove file status"_t, + projectStorageCategory(), + keyValue("file status", fileStatus)}; + + deleteFileStatusStatement.write(fileStatus.sourceId); + }; + + Sqlite::insertUpdateDelete(range, fileStatuses, compareKey, insert, update, remove); +} + +void ProjectStorage::synchronizeImports(Storage::Imports &imports, + const SourceIds &updatedSourceIds, + Storage::Imports &moduleDependencies, + const SourceIds &updatedModuleDependencySourceIds, + Storage::Synchronization::ModuleExportedImports &moduleExportedImports, + const ModuleIds &updatedModuleIds) +{ + NanotraceHR::Tracer tracer{"synchronize imports"_t, projectStorageCategory()}; + + synchromizeModuleExportedImports(moduleExportedImports, updatedModuleIds); + NanotraceHR::Tracer importTracer{"synchronize qml document imports"_t, projectStorageCategory()}; + synchronizeDocumentImports(imports, updatedSourceIds, Storage::Synchronization::ImportKind::Import); + importTracer.end(); + NanotraceHR::Tracer moduleDependenciesTracer{"synchronize module depdencies"_t, + projectStorageCategory()}; + synchronizeDocumentImports(moduleDependencies, + updatedModuleDependencySourceIds, + Storage::Synchronization::ImportKind::ModuleDependency); + moduleDependenciesTracer.end(); +} + +void ProjectStorage::synchromizeModuleExportedImports( + Storage::Synchronization::ModuleExportedImports &moduleExportedImports, + const ModuleIds &updatedModuleIds) +{ + NanotraceHR::Tracer tracer{"synchronize module exported imports"_t, projectStorageCategory()}; + std::sort(moduleExportedImports.begin(), + moduleExportedImports.end(), + [](auto &&first, auto &&second) { + return std::tie(first.moduleId, first.exportedModuleId) + < std::tie(second.moduleId, second.exportedModuleId); + }); + + auto range = selectModuleExportedImportsForSourceIdStatement + .range( + toIntegers(updatedModuleIds)); + + auto compareKey = [](const Storage::Synchronization::ModuleExportedImportView &view, + const Storage::Synchronization::ModuleExportedImport &import) -> long long { + auto moduleIdDifference = view.moduleId - import.moduleId; + if (moduleIdDifference != 0) + return moduleIdDifference; + + return view.exportedModuleId - import.exportedModuleId; + }; + + auto insert = [&](const Storage::Synchronization::ModuleExportedImport &import) { + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"insert module exported import"_t, + projectStorageCategory(), + keyValue("module exported import", import), + keyValue("module id", import.moduleId)}; + tracer.tick("exported module"_t, keyValue("module id", import.exportedModuleId)); + + if (import.version.minor) { + insertModuleExportedImportWithVersionStatement.write(import.moduleId, + import.exportedModuleId, + import.isAutoVersion, + import.version.major.value, + import.version.minor.value); + } else if (import.version.major) { + insertModuleExportedImportWithMajorVersionStatement.write(import.moduleId, + import.exportedModuleId, + import.isAutoVersion, + import.version.major.value); + } else { + insertModuleExportedImportWithoutVersionStatement.write(import.moduleId, + import.exportedModuleId, + import.isAutoVersion); + } + }; + + auto update = [](const Storage::Synchronization::ModuleExportedImportView &, + const Storage::Synchronization::ModuleExportedImport &) { + return Sqlite::UpdateChange::No; + }; + + auto remove = [&](const Storage::Synchronization::ModuleExportedImportView &view) { + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"remove module exported import"_t, + projectStorageCategory(), + keyValue("module exported import view", view), + keyValue("module id", view.moduleId)}; + tracer.tick("exported module"_t, keyValue("module id", view.exportedModuleId)); + + deleteModuleExportedImportStatement.write(view.moduleExportedImportId); + }; + + Sqlite::insertUpdateDelete(range, moduleExportedImports, compareKey, insert, update, remove); +} + +ModuleId ProjectStorage::fetchModuleIdUnguarded(Utils::SmallStringView name) const +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"fetch module id ungarded"_t, + projectStorageCategory(), + keyValue("module name", name)}; + + auto moduleId = selectModuleIdByNameStatement.value(name); + + if (!moduleId) + moduleId = insertModuleNameStatement.value(name); + + tracer.end(keyValue("module id", moduleId)); + + return moduleId; +} + +Utils::PathString ProjectStorage::fetchModuleNameUnguarded(ModuleId id) const +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"fetch module name ungarded"_t, + projectStorageCategory(), + keyValue("module id", id)}; + + auto moduleName = selectModuleNameStatement.value(id); + + if (moduleName.empty()) + throw ModuleDoesNotExists{}; + + tracer.end(keyValue("module name", moduleName)); + + return moduleName; +} + +void ProjectStorage::handleAliasPropertyDeclarationsWithPropertyType( + TypeId typeId, AliasPropertyDeclarations &relinkableAliasPropertyDeclarations) +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"handle alias property declarations with property type"_t, + projectStorageCategory(), + keyValue("type id", typeId), + keyValue("relinkable alias property declarations", + relinkableAliasPropertyDeclarations)}; + + auto callback = [&](TypeId typeId_, + PropertyDeclarationId propertyDeclarationId, + ImportedTypeNameId propertyImportedTypeNameId, + PropertyDeclarationId aliasPropertyDeclarationId, + PropertyDeclarationId aliasPropertyDeclarationTailId) { + auto aliasPropertyName = selectPropertyNameStatement.value( + aliasPropertyDeclarationId); + Utils::SmallString aliasPropertyNameTail; + if (aliasPropertyDeclarationTailId) + aliasPropertyNameTail = selectPropertyNameStatement.value( + aliasPropertyDeclarationTailId); + + relinkableAliasPropertyDeclarations.emplace_back(TypeId{typeId_}, + PropertyDeclarationId{propertyDeclarationId}, + ImportedTypeNameId{propertyImportedTypeNameId}, + std::move(aliasPropertyName), + std::move(aliasPropertyNameTail)); + + updateAliasPropertyDeclarationToNullStatement.write(propertyDeclarationId); + }; + + selectAliasPropertiesDeclarationForPropertiesWithTypeIdStatement.readCallback(callback, typeId); +} + +void ProjectStorage::handlePropertyDeclarationWithPropertyType( + TypeId typeId, PropertyDeclarations &relinkablePropertyDeclarations) +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"handle property declarations with property type"_t, + projectStorageCategory(), + keyValue("type id", typeId), + keyValue("relinkable property declarations", + relinkablePropertyDeclarations)}; + + updatesPropertyDeclarationPropertyTypeToNullStatement.readTo(relinkablePropertyDeclarations, + typeId); +} + +void ProjectStorage::handlePrototypes(TypeId prototypeId, Prototypes &relinkablePrototypes) +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"handle prototypes"_t, + projectStorageCategory(), + keyValue("type id", prototypeId), + keyValue("relinkable prototypes", relinkablePrototypes)}; + + auto callback = [&](TypeId typeId, ImportedTypeNameId prototypeNameId) { + relinkablePrototypes.emplace_back(typeId, prototypeNameId); + }; + + updatePrototypeIdToNullStatement.readCallback(callback, prototypeId); +} + +void ProjectStorage::handleExtensions(TypeId extensionId, Prototypes &relinkableExtensions) +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"handle extension"_t, + projectStorageCategory(), + keyValue("type id", extensionId), + keyValue("relinkable extensions", relinkableExtensions)}; + + auto callback = [&](TypeId typeId, ImportedTypeNameId extensionNameId) { + relinkableExtensions.emplace_back(typeId, extensionNameId); + }; + + updateExtensionIdToNullStatement.readCallback(callback, extensionId); +} + +void ProjectStorage::deleteType(TypeId typeId, + AliasPropertyDeclarations &relinkableAliasPropertyDeclarations, + PropertyDeclarations &relinkablePropertyDeclarations, + Prototypes &relinkablePrototypes, + Prototypes &relinkableExtensions) +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"delete type"_t, projectStorageCategory(), keyValue("type id", typeId)}; + + handlePropertyDeclarationWithPropertyType(typeId, relinkablePropertyDeclarations); + handleAliasPropertyDeclarationsWithPropertyType(typeId, relinkableAliasPropertyDeclarations); + handlePrototypes(typeId, relinkablePrototypes); + handleExtensions(typeId, relinkableExtensions); + deleteTypeNamesByTypeIdStatement.write(typeId); + deleteEnumerationDeclarationByTypeIdStatement.write(typeId); + deletePropertyDeclarationByTypeIdStatement.write(typeId); + deleteFunctionDeclarationByTypeIdStatement.write(typeId); + deleteSignalDeclarationByTypeIdStatement.write(typeId); + deleteTypeStatement.write(typeId); +} + +void ProjectStorage::relinkAliasPropertyDeclarations(AliasPropertyDeclarations &aliasPropertyDeclarations, + const TypeIds &deletedTypeIds) +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"relink alias properties"_t, + projectStorageCategory(), + keyValue("alias property declarations", aliasPropertyDeclarations), + keyValue("deleted type ids", deletedTypeIds)}; + + std::sort(aliasPropertyDeclarations.begin(), aliasPropertyDeclarations.end()); + + Utils::set_greedy_difference( + aliasPropertyDeclarations.cbegin(), + aliasPropertyDeclarations.cend(), + deletedTypeIds.begin(), + deletedTypeIds.end(), + [&](const AliasPropertyDeclaration &alias) { + auto typeId = fetchTypeId(alias.aliasImportedTypeNameId); + + if (!typeId) + throw TypeNameDoesNotExists{fetchImportedTypeName(alias.aliasImportedTypeNameId)}; + + auto [propertyTypeId, aliasId, propertyTraits] = fetchPropertyDeclarationByTypeIdAndNameUngarded( + typeId, alias.aliasPropertyName); + + updatePropertyDeclarationWithAliasAndTypeStatement.write(alias.propertyDeclarationId, + propertyTypeId, + propertyTraits, + alias.aliasImportedTypeNameId, + aliasId); + }, + TypeCompare{}); +} + +void ProjectStorage::relinkPropertyDeclarations(PropertyDeclarations &relinkablePropertyDeclaration, + const TypeIds &deletedTypeIds) +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"relink property declarations"_t, + projectStorageCategory(), + keyValue("relinkable property declarations", + relinkablePropertyDeclaration), + keyValue("deleted type ids", deletedTypeIds)}; + + std::sort(relinkablePropertyDeclaration.begin(), relinkablePropertyDeclaration.end()); + + Utils::set_greedy_difference( + relinkablePropertyDeclaration.cbegin(), + relinkablePropertyDeclaration.cend(), + deletedTypeIds.begin(), + deletedTypeIds.end(), + [&](const PropertyDeclaration &property) { + TypeId propertyTypeId = fetchTypeId(property.importedTypeNameId); + + if (!propertyTypeId) + throw TypeNameDoesNotExists{fetchImportedTypeName(property.importedTypeNameId)}; + + updatePropertyDeclarationTypeStatement.write(property.propertyDeclarationId, + propertyTypeId); + }, + TypeCompare{}); +} + +void ProjectStorage::deleteNotUpdatedTypes(const TypeIds &updatedTypeIds, + const SourceIds &updatedSourceIds, + const TypeIds &typeIdsToBeDeleted, + AliasPropertyDeclarations &relinkableAliasPropertyDeclarations, + PropertyDeclarations &relinkablePropertyDeclarations, + Prototypes &relinkablePrototypes, + Prototypes &relinkableExtensions, + TypeIds &deletedTypeIds) +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"delete not updated types"_t, + projectStorageCategory(), + keyValue("updated type ids", updatedTypeIds), + keyValue("updated source ids", updatedSourceIds), + keyValue("type ids to be deleted", typeIdsToBeDeleted)}; + + auto callback = [&](TypeId typeId) { + deletedTypeIds.push_back(typeId); + deleteType(typeId, + relinkableAliasPropertyDeclarations, + relinkablePropertyDeclarations, + relinkablePrototypes, + relinkableExtensions); + }; + + selectNotUpdatedTypesInSourcesStatement.readCallback(callback, + toIntegers(updatedSourceIds), + toIntegers(updatedTypeIds)); + for (TypeId typeIdToBeDeleted : typeIdsToBeDeleted) + callback(typeIdToBeDeleted); +} + +void ProjectStorage::relink(AliasPropertyDeclarations &relinkableAliasPropertyDeclarations, + PropertyDeclarations &relinkablePropertyDeclarations, + Prototypes &relinkablePrototypes, + Prototypes &relinkableExtensions, + TypeIds &deletedTypeIds) +{ + NanotraceHR::Tracer tracer{"relink"_t, projectStorageCategory()}; + + std::sort(deletedTypeIds.begin(), deletedTypeIds.end()); + + relinkPrototypes(relinkablePrototypes, deletedTypeIds, [&](TypeId typeId, TypeId prototypeId) { + updateTypePrototypeStatement.write(typeId, prototypeId); + }); + relinkPrototypes(relinkableExtensions, deletedTypeIds, [&](TypeId typeId, TypeId prototypeId) { + updateTypeExtensionStatement.write(typeId, prototypeId); + }); + relinkPropertyDeclarations(relinkablePropertyDeclarations, deletedTypeIds); + relinkAliasPropertyDeclarations(relinkableAliasPropertyDeclarations, deletedTypeIds); +} + +PropertyDeclarationId ProjectStorage::fetchAliasId(TypeId aliasTypeId, + Utils::SmallStringView aliasPropertyName, + Utils::SmallStringView aliasPropertyNameTail) +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"fetch alias id"_t, + projectStorageCategory(), + keyValue("alias type id", aliasTypeId), + keyValue("alias property name", aliasPropertyName), + keyValue("alias property name tail", aliasPropertyNameTail)}; + + if (aliasPropertyNameTail.empty()) + return fetchPropertyDeclarationIdByTypeIdAndNameUngarded(aliasTypeId, aliasPropertyName); + + auto stemAlias = fetchPropertyDeclarationByTypeIdAndNameUngarded(aliasTypeId, aliasPropertyName); + + return fetchPropertyDeclarationIdByTypeIdAndNameUngarded(stemAlias.propertyTypeId, + aliasPropertyNameTail); +} + +void ProjectStorage::linkAliasPropertyDeclarationAliasIds(const AliasPropertyDeclarations &aliasDeclarations) +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"link alias property declarations alias ids"_t, + projectStorageCategory(), + keyValue("alias property declarations", aliasDeclarations)}; + + for (const auto &aliasDeclaration : aliasDeclarations) { + auto aliasTypeId = fetchTypeId(aliasDeclaration.aliasImportedTypeNameId); + + if (!aliasTypeId) { + throw TypeNameDoesNotExists{ + fetchImportedTypeName(aliasDeclaration.aliasImportedTypeNameId)}; + } + + auto aliasId = fetchAliasId(aliasTypeId, + aliasDeclaration.aliasPropertyName, + aliasDeclaration.aliasPropertyNameTail); + + updatePropertyDeclarationAliasIdAndTypeNameIdStatement.write( + aliasDeclaration.propertyDeclarationId, aliasId, aliasDeclaration.aliasImportedTypeNameId); + } +} + +void ProjectStorage::updateAliasPropertyDeclarationValues(const AliasPropertyDeclarations &aliasDeclarations) +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"update alias property declarations"_t, + projectStorageCategory(), + keyValue("alias property declarations", aliasDeclarations)}; + + for (const auto &aliasDeclaration : aliasDeclarations) { + updatetPropertiesDeclarationValuesOfAliasStatement.write( + aliasDeclaration.propertyDeclarationId); + updatePropertyAliasDeclarationRecursivelyStatement.write( + aliasDeclaration.propertyDeclarationId); + } +} + +void ProjectStorage::checkAliasPropertyDeclarationCycles(const AliasPropertyDeclarations &aliasDeclarations) +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"check alias property declarations cycles"_t, + projectStorageCategory(), + keyValue("alias property declarations", aliasDeclarations)}; + for (const auto &aliasDeclaration : aliasDeclarations) + checkForAliasChainCycle(aliasDeclaration.propertyDeclarationId); +} + +void ProjectStorage::linkAliases(const AliasPropertyDeclarations &insertedAliasPropertyDeclarations, + const AliasPropertyDeclarations &updatedAliasPropertyDeclarations) +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"link aliases"_t, projectStorageCategory()}; + + linkAliasPropertyDeclarationAliasIds(insertedAliasPropertyDeclarations); + linkAliasPropertyDeclarationAliasIds(updatedAliasPropertyDeclarations); + + checkAliasPropertyDeclarationCycles(insertedAliasPropertyDeclarations); + checkAliasPropertyDeclarationCycles(updatedAliasPropertyDeclarations); + + updateAliasPropertyDeclarationValues(insertedAliasPropertyDeclarations); + updateAliasPropertyDeclarationValues(updatedAliasPropertyDeclarations); +} + +void ProjectStorage::synchronizeExportedTypes(const TypeIds &updatedTypeIds, + Storage::Synchronization::ExportedTypes &exportedTypes, + AliasPropertyDeclarations &relinkableAliasPropertyDeclarations, + PropertyDeclarations &relinkablePropertyDeclarations, + Prototypes &relinkablePrototypes, + Prototypes &relinkableExtensions) +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"synchronize exported types"_t, projectStorageCategory()}; + + std::sort(exportedTypes.begin(), exportedTypes.end(), [](auto &&first, auto &&second) { + if (first.moduleId < second.moduleId) + return true; + else if (first.moduleId > second.moduleId) + return false; + + auto nameCompare = Sqlite::compare(first.name, second.name); + + if (nameCompare < 0) + return true; + else if (nameCompare > 0) + return false; + + return first.version < second.version; + }); + + auto range = selectExportedTypesForSourceIdsStatement + .range(toIntegers(updatedTypeIds)); + + auto compareKey = [](const Storage::Synchronization::ExportedTypeView &view, + const Storage::Synchronization::ExportedType &type) -> long long { + auto moduleIdDifference = view.moduleId - type.moduleId; + if (moduleIdDifference != 0) + return moduleIdDifference; + + auto nameDifference = Sqlite::compare(view.name, type.name); + if (nameDifference != 0) + return nameDifference; + + auto versionDifference = view.version.major.value - type.version.major.value; + if (versionDifference != 0) + return versionDifference; + + return view.version.minor.value - type.version.minor.value; + }; + + auto insert = [&](const Storage::Synchronization::ExportedType &type) { + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"insert exported type"_t, + projectStorageCategory(), + keyValue("exported type", type), + keyValue("type id", type.typeId), + keyValue("module id", type.moduleId)}; + if (!type.moduleId) + throw QmlDesigner::ModuleDoesNotExists{}; + + try { + if (type.version) { + insertExportedTypeNamesWithVersionStatement.write(type.moduleId, + type.name, + type.version.major.value, + type.version.minor.value, + type.typeId); + + } else if (type.version.major) { + insertExportedTypeNamesWithMajorVersionStatement.write(type.moduleId, + type.name, + type.version.major.value, + type.typeId); + } else { + insertExportedTypeNamesWithoutVersionStatement.write(type.moduleId, + type.name, + type.typeId); + } + } catch (const Sqlite::ConstraintPreventsModification &) { + throw QmlDesigner::ExportedTypeCannotBeInserted{type.name}; + } + }; + + auto update = [&](const Storage::Synchronization::ExportedTypeView &view, + const Storage::Synchronization::ExportedType &type) { + if (view.typeId != type.typeId) { + NanotraceHR::Tracer tracer{"update exported type"_t, + projectStorageCategory(), + keyValue("exported type", type), + keyValue("exported type view", view), + keyValue("type id", type.typeId), + keyValue("module id", type.typeId)}; + + handlePropertyDeclarationWithPropertyType(view.typeId, relinkablePropertyDeclarations); + handleAliasPropertyDeclarationsWithPropertyType(view.typeId, + relinkableAliasPropertyDeclarations); + handlePrototypes(view.typeId, relinkablePrototypes); + handleExtensions(view.typeId, relinkableExtensions); + updateExportedTypeNameTypeIdStatement.write(view.exportedTypeNameId, type.typeId); + return Sqlite::UpdateChange::Update; + } + return Sqlite::UpdateChange::No; + }; + + auto remove = [&](const Storage::Synchronization::ExportedTypeView &view) { + NanotraceHR::Tracer tracer{"remove exported type"_t, + projectStorageCategory(), + keyValue("exported type", view), + keyValue("type id", view.typeId), + keyValue("module id", view.moduleId)}; + + handlePropertyDeclarationWithPropertyType(view.typeId, relinkablePropertyDeclarations); + handleAliasPropertyDeclarationsWithPropertyType(view.typeId, + relinkableAliasPropertyDeclarations); + handlePrototypes(view.typeId, relinkablePrototypes); + handleExtensions(view.typeId, relinkableExtensions); + deleteExportedTypeNameStatement.write(view.exportedTypeNameId); + }; + + Sqlite::insertUpdateDelete(range, exportedTypes, compareKey, insert, update, remove); +} + +void ProjectStorage::synchronizePropertyDeclarationsInsertAlias( + AliasPropertyDeclarations &insertedAliasPropertyDeclarations, + const Storage::Synchronization::PropertyDeclaration &value, + SourceId sourceId, + TypeId typeId) +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"insert property declaration to alias"_t, + projectStorageCategory(), + keyValue("property declaration", value)}; + + auto callback = [&](PropertyDeclarationId propertyDeclarationId) { + insertedAliasPropertyDeclarations.emplace_back(typeId, + propertyDeclarationId, + fetchImportedTypeNameId(value.typeName, + sourceId), + value.aliasPropertyName, + value.aliasPropertyNameTail); + return Sqlite::CallbackControl::Abort; + }; + + insertAliasPropertyDeclarationStatement.readCallback(callback, typeId, value.name); +} + +QVarLengthArray ProjectStorage::fetchPropertyDeclarationIds( + TypeId baseTypeId) const +{ + QVarLengthArray propertyDeclarationIds; + + selectLocalPropertyDeclarationIdsForTypeStatement.readTo(propertyDeclarationIds, baseTypeId); + + auto range = selectPrototypeAndExtensionIdsStatement.range(baseTypeId); + + for (TypeId prototype : range) { + selectLocalPropertyDeclarationIdsForTypeStatement.readTo(propertyDeclarationIds, prototype); + } + + return propertyDeclarationIds; +} + +PropertyDeclarationId ProjectStorage::fetchNextPropertyDeclarationId( + TypeId baseTypeId, Utils::SmallStringView propertyName) const +{ + auto range = selectPrototypeAndExtensionIdsStatement.range(baseTypeId); + + for (TypeId prototype : range) { + auto propertyDeclarationId = selectPropertyDeclarationIdByTypeIdAndNameStatement + .value(prototype, propertyName); + + if (propertyDeclarationId) + return propertyDeclarationId; + } + + return PropertyDeclarationId{}; +} + +PropertyDeclarationId ProjectStorage::fetchPropertyDeclarationId(TypeId typeId, + Utils::SmallStringView propertyName) const +{ + auto propertyDeclarationId = selectPropertyDeclarationIdByTypeIdAndNameStatement + .value(typeId, propertyName); + + if (propertyDeclarationId) + return propertyDeclarationId; + + return fetchNextPropertyDeclarationId(typeId, propertyName); +} + +PropertyDeclarationId ProjectStorage::fetchNextDefaultPropertyDeclarationId(TypeId baseTypeId) const +{ + auto range = selectPrototypeAndExtensionIdsStatement.range(baseTypeId); + + for (TypeId prototype : range) { + auto propertyDeclarationId = selectDefaultPropertyDeclarationIdStatement + .value(prototype); + + if (propertyDeclarationId) + return propertyDeclarationId; + } + + return PropertyDeclarationId{}; +} + +PropertyDeclarationId ProjectStorage::fetchDefaultPropertyDeclarationId(TypeId typeId) const +{ + auto propertyDeclarationId = selectDefaultPropertyDeclarationIdStatement.value( + typeId); + + if (propertyDeclarationId) + return propertyDeclarationId; + + return fetchNextDefaultPropertyDeclarationId(typeId); +} + +void ProjectStorage::synchronizePropertyDeclarationsInsertProperty( + const Storage::Synchronization::PropertyDeclaration &value, SourceId sourceId, TypeId typeId) +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"insert property declaration"_t, + projectStorageCategory(), + keyValue("property declaration", value)}; + + auto propertyImportedTypeNameId = fetchImportedTypeNameId(value.typeName, sourceId); + auto propertyTypeId = fetchTypeId(propertyImportedTypeNameId); + + if (!propertyTypeId) + throw TypeNameDoesNotExists{fetchImportedTypeName(propertyImportedTypeNameId), sourceId}; + + auto propertyDeclarationId = insertPropertyDeclarationStatement.value( + typeId, value.name, propertyTypeId, value.traits, propertyImportedTypeNameId); + + auto nextPropertyDeclarationId = fetchNextPropertyDeclarationId(typeId, value.name); + if (nextPropertyDeclarationId) { + updateAliasIdPropertyDeclarationStatement.write(nextPropertyDeclarationId, + propertyDeclarationId); + updatePropertyAliasDeclarationRecursivelyWithTypeAndTraitsStatement.write(propertyDeclarationId, + propertyTypeId, + value.traits); + } +} + +void ProjectStorage::synchronizePropertyDeclarationsUpdateAlias( + AliasPropertyDeclarations &updatedAliasPropertyDeclarations, + const Storage::Synchronization::PropertyDeclarationView &view, + const Storage::Synchronization::PropertyDeclaration &value, + SourceId sourceId) +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"update property declaration to alias"_t, + projectStorageCategory(), + keyValue("property declaration", value), + keyValue("property declaration view", view)}; + + updatedAliasPropertyDeclarations.emplace_back(view.typeId, + view.id, + fetchImportedTypeNameId(value.typeName, sourceId), + value.aliasPropertyName, + value.aliasPropertyNameTail, + view.aliasId); +} + +Sqlite::UpdateChange ProjectStorage::synchronizePropertyDeclarationsUpdateProperty( + const Storage::Synchronization::PropertyDeclarationView &view, + const Storage::Synchronization::PropertyDeclaration &value, + SourceId sourceId, + PropertyDeclarationIds &propertyDeclarationIds) +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"update property declaration"_t, + projectStorageCategory(), + keyValue("property declaration", value), + keyValue("property declaration view", view)}; + + auto propertyImportedTypeNameId = fetchImportedTypeNameId(value.typeName, sourceId); + + auto propertyTypeId = fetchTypeId(propertyImportedTypeNameId); + + if (!propertyTypeId) + throw TypeNameDoesNotExists{fetchImportedTypeName(propertyImportedTypeNameId), sourceId}; + + if (view.traits == value.traits && propertyTypeId == view.typeId + && propertyImportedTypeNameId == view.typeNameId) + return Sqlite::UpdateChange::No; + + updatePropertyDeclarationStatement.write(view.id, + propertyTypeId, + value.traits, + propertyImportedTypeNameId); + updatePropertyAliasDeclarationRecursivelyWithTypeAndTraitsStatement.write(view.id, + propertyTypeId, + value.traits); + propertyDeclarationIds.push_back(view.id); + + tracer.end(keyValue("updated", "yes")); + + return Sqlite::UpdateChange::Update; +} + +void ProjectStorage::synchronizePropertyDeclarations( + TypeId typeId, + Storage::Synchronization::PropertyDeclarations &propertyDeclarations, + SourceId sourceId, + AliasPropertyDeclarations &insertedAliasPropertyDeclarations, + AliasPropertyDeclarations &updatedAliasPropertyDeclarations, + PropertyDeclarationIds &propertyDeclarationIds) +{ + NanotraceHR::Tracer tracer{"synchronize property declaration"_t, projectStorageCategory()}; + + std::sort(propertyDeclarations.begin(), propertyDeclarations.end(), [](auto &&first, auto &&second) { + return Sqlite::compare(first.name, second.name) < 0; + }); + + auto range = selectPropertyDeclarationsForTypeIdStatement + .range(typeId); + + auto compareKey = [](const Storage::Synchronization::PropertyDeclarationView &view, + const Storage::Synchronization::PropertyDeclaration &value) { + return Sqlite::compare(view.name, value.name); + }; + + auto insert = [&](const Storage::Synchronization::PropertyDeclaration &value) { + if (value.kind == Storage::Synchronization::PropertyKind::Alias) { + synchronizePropertyDeclarationsInsertAlias(insertedAliasPropertyDeclarations, + value, + sourceId, + typeId); + } else { + synchronizePropertyDeclarationsInsertProperty(value, sourceId, typeId); + } + }; + + auto update = [&](const Storage::Synchronization::PropertyDeclarationView &view, + const Storage::Synchronization::PropertyDeclaration &value) { + if (value.kind == Storage::Synchronization::PropertyKind::Alias) { + synchronizePropertyDeclarationsUpdateAlias(updatedAliasPropertyDeclarations, + view, + value, + sourceId); + propertyDeclarationIds.push_back(view.id); + } else { + return synchronizePropertyDeclarationsUpdateProperty(view, + value, + sourceId, + propertyDeclarationIds); + } + + return Sqlite::UpdateChange::No; + }; + + auto remove = [&](const Storage::Synchronization::PropertyDeclarationView &view) { + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"remove property declaration"_t, + projectStorageCategory(), + keyValue("property declaratio viewn", view)}; + + auto nextPropertyDeclarationId = fetchNextPropertyDeclarationId(typeId, view.name); + + if (nextPropertyDeclarationId) { + updateAliasPropertyDeclarationByAliasPropertyDeclarationIdStatement + .write(nextPropertyDeclarationId, view.id); + } + + updateDefaultPropertyIdToNullStatement.write(view.id); + deletePropertyDeclarationStatement.write(view.id); + propertyDeclarationIds.push_back(view.id); + }; + + Sqlite::insertUpdateDelete(range, propertyDeclarations, compareKey, insert, update, remove); +} + +void ProjectStorage::resetRemovedAliasPropertyDeclarationsToNull( + Storage::Synchronization::Type &type, PropertyDeclarationIds &propertyDeclarationIds) +{ + NanotraceHR::Tracer tracer{"reset removed alias property declaration to null"_t, + projectStorageCategory()}; + + if (type.changeLevel == Storage::Synchronization::ChangeLevel::Minimal) + return; + + Storage::Synchronization::PropertyDeclarations &aliasDeclarations = type.propertyDeclarations; + + std::sort(aliasDeclarations.begin(), aliasDeclarations.end(), [](auto &&first, auto &&second) { + return Sqlite::compare(first.name, second.name) < 0; + }); + + auto range = selectPropertyDeclarationsWithAliasForTypeIdStatement + .range(type.typeId); + + auto compareKey = [](const AliasPropertyDeclarationView &view, + const Storage::Synchronization::PropertyDeclaration &value) { + return Sqlite::compare(view.name, value.name); + }; + + auto insert = [&](const Storage::Synchronization::PropertyDeclaration &) {}; + + auto update = [&](const AliasPropertyDeclarationView &, + const Storage::Synchronization::PropertyDeclaration &) { + return Sqlite::UpdateChange::No; + }; + + auto remove = [&](const AliasPropertyDeclarationView &view) { + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"reset removed alias property declaration to null"_t, + projectStorageCategory(), + keyValue("alias property declaration view", view)}; + + updatePropertyDeclarationAliasIdToNullStatement.write(view.id); + propertyDeclarationIds.push_back(view.id); + }; + + Sqlite::insertUpdateDelete(range, aliasDeclarations, compareKey, insert, update, remove); +} + +void ProjectStorage::resetRemovedAliasPropertyDeclarationsToNull( + Storage::Synchronization::Types &types, + AliasPropertyDeclarations &relinkableAliasPropertyDeclarations) +{ + NanotraceHR::Tracer tracer{"reset removed alias properties to null"_t, projectStorageCategory()}; + + PropertyDeclarationIds propertyDeclarationIds; + propertyDeclarationIds.reserve(types.size()); + + for (auto &&type : types) + resetRemovedAliasPropertyDeclarationsToNull(type, propertyDeclarationIds); + + removeRelinkableEntries(relinkableAliasPropertyDeclarations, + propertyDeclarationIds, + PropertyCompare{}); +} + +ImportId ProjectStorage::insertDocumentImport(const Storage::Import &import, + Storage::Synchronization::ImportKind importKind, + ModuleId sourceModuleId, + ImportId parentImportId) +{ + if (import.version.minor) { + return insertDocumentImportWithVersionStatement.value(import.sourceId, + import.moduleId, + sourceModuleId, + importKind, + import.version.major.value, + import.version.minor.value, + parentImportId); + } else if (import.version.major) { + return insertDocumentImportWithMajorVersionStatement.value(import.sourceId, + import.moduleId, + sourceModuleId, + importKind, + import.version.major.value, + parentImportId); + } else { + return insertDocumentImportWithoutVersionStatement.value(import.sourceId, + import.moduleId, + sourceModuleId, + importKind, + parentImportId); + } +} + +void ProjectStorage::synchronizeDocumentImports(Storage::Imports &imports, + const SourceIds &updatedSourceIds, + Storage::Synchronization::ImportKind importKind) +{ + std::sort(imports.begin(), imports.end(), [](auto &&first, auto &&second) { + return std::tie(first.sourceId, first.moduleId, first.version) + < std::tie(second.sourceId, second.moduleId, second.version); + }); + + auto range = selectDocumentImportForSourceIdStatement.range( + toIntegers(updatedSourceIds), importKind); + + auto compareKey = [](const Storage::Synchronization::ImportView &view, + const Storage::Import &import) -> long long { + auto sourceIdDifference = view.sourceId - import.sourceId; + if (sourceIdDifference != 0) + return sourceIdDifference; + + auto moduleIdDifference = view.moduleId - import.moduleId; + if (moduleIdDifference != 0) + return moduleIdDifference; + + auto versionDifference = view.version.major.value - import.version.major.value; + if (versionDifference != 0) + return versionDifference; + + return view.version.minor.value - import.version.minor.value; + }; + + auto insert = [&](const Storage::Import &import) { + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"insert import"_t, + projectStorageCategory(), + keyValue("import", import), + keyValue("import kind", importKind), + keyValue("source id", import.sourceId), + keyValue("module id", import.moduleId)}; + + auto importId = insertDocumentImport(import, importKind, import.moduleId, ImportId{}); + auto callback = [&](ModuleId exportedModuleId, int majorVersion, int minorVersion) { + Storage::Import additionImport{exportedModuleId, + Storage::Version{majorVersion, minorVersion}, + import.sourceId}; + + auto exportedImportKind = importKind == Storage::Synchronization::ImportKind::Import + ? Storage::Synchronization::ImportKind::ModuleExportedImport + : Storage::Synchronization::ImportKind::ModuleExportedModuleDependency; + + NanotraceHR::Tracer tracer{"insert indirect import"_t, + projectStorageCategory(), + keyValue("import", import), + keyValue("import kind", exportedImportKind), + keyValue("source id", import.sourceId), + keyValue("module id", import.moduleId)}; + + auto indirectImportId = insertDocumentImport(additionImport, + exportedImportKind, + import.moduleId, + importId); + + tracer.end(keyValue("import id", indirectImportId)); + }; + + selectModuleExportedImportsForModuleIdStatement.readCallback(callback, + import.moduleId, + import.version.major.value, + import.version.minor.value); + tracer.end(keyValue("import id", importId)); + }; + + auto update = [](const Storage::Synchronization::ImportView &, const Storage::Import &) { + return Sqlite::UpdateChange::No; + }; + + auto remove = [&](const Storage::Synchronization::ImportView &view) { + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"remove import"_t, + projectStorageCategory(), + keyValue("import", view), + keyValue("import id", view.importId), + keyValue("source id", view.sourceId), + keyValue("module id", view.moduleId)}; + + deleteDocumentImportStatement.write(view.importId); + deleteDocumentImportsWithParentImportIdStatement.write(view.sourceId, view.importId); + }; + + Sqlite::insertUpdateDelete(range, imports, compareKey, insert, update, remove); +} + +Utils::PathString ProjectStorage::createJson(const Storage::Synchronization::ParameterDeclarations ¶meters) +{ + NanotraceHR::Tracer tracer{"create json from parameter declarations"_t, projectStorageCategory()}; + + Utils::PathString json; + json.append("["); + + Utils::SmallStringView comma{""}; + + for (const auto ¶meter : parameters) { + json.append(comma); + comma = ","; + json.append(R"({"n":")"); + json.append(parameter.name); + json.append(R"(","tn":")"); + json.append(parameter.typeName); + if (parameter.traits == Storage::PropertyDeclarationTraits::None) { + json.append("\"}"); + } else { + json.append(R"(","tr":)"); + json.append(Utils::SmallString::number(to_underlying(parameter.traits))); + json.append("}"); + } + } + + json.append("]"); + + return json; +} + +TypeId ProjectStorage::fetchTypeIdByModuleIdAndExportedName(ModuleId moduleId, + Utils::SmallStringView name) const +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"fetch type id by module id and exported name"_t, + projectStorageCategory(), + keyValue("module id", moduleId), + keyValue("exported name", name)}; + + return selectTypeIdByModuleIdAndExportedNameStatement.value(moduleId, name); +} + +void ProjectStorage::addTypeIdToPropertyEditorQmlPaths( + Storage::Synchronization::PropertyEditorQmlPaths &paths) +{ + NanotraceHR::Tracer tracer{"add type id to property editor qml paths"_t, projectStorageCategory()}; + + for (auto &path : paths) + path.typeId = fetchTypeIdByModuleIdAndExportedName(path.moduleId, path.typeName); +} + +void ProjectStorage::synchronizePropertyEditorPaths(Storage::Synchronization::PropertyEditorQmlPaths &paths, + SourceIds updatedPropertyEditorQmlPathsSourceIds) +{ + using Storage::Synchronization::PropertyEditorQmlPath; + std::sort(paths.begin(), paths.end(), [](auto &&first, auto &&second) { + return first.typeId < second.typeId; + }); + + auto range = selectPropertyEditorPathsForForSourceIdsStatement.range( + toIntegers(updatedPropertyEditorQmlPathsSourceIds)); + + auto compareKey = [](const PropertyEditorQmlPathView &view, + const PropertyEditorQmlPath &value) -> long long { + return view.typeId - value.typeId; + }; + + auto insert = [&](const PropertyEditorQmlPath &path) { + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"insert property editor paths"_t, + projectStorageCategory(), + keyValue("property editor qml path", path)}; + + if (path.typeId) + insertPropertyEditorPathStatement.write(path.typeId, path.pathId, path.directoryId); + }; + + auto update = [&](const PropertyEditorQmlPathView &view, const PropertyEditorQmlPath &value) { + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"update property editor paths"_t, + projectStorageCategory(), + keyValue("property editor qml path", value), + keyValue("property editor qml path view", view)}; + + if (value.pathId != view.pathId || value.directoryId != view.directoryId) { + updatePropertyEditorPathsStatement.write(value.typeId, value.pathId, value.directoryId); + + tracer.end(keyValue("updated", "yes")); + + return Sqlite::UpdateChange::Update; + } + return Sqlite::UpdateChange::No; + }; + + auto remove = [&](const PropertyEditorQmlPathView &view) { + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"remove property editor paths"_t, + projectStorageCategory(), + keyValue("property editor qml path view", view)}; + + deletePropertyEditorPathStatement.write(view.typeId); + }; + + Sqlite::insertUpdateDelete(range, paths, compareKey, insert, update, remove); +} + +void ProjectStorage::synchronizePropertyEditorQmlPaths( + Storage::Synchronization::PropertyEditorQmlPaths &paths, + SourceIds updatedPropertyEditorQmlPathsSourceIds) +{ + NanotraceHR::Tracer tracer{"synchronize property editor qml paths"_t, projectStorageCategory()}; + + addTypeIdToPropertyEditorQmlPaths(paths); + synchronizePropertyEditorPaths(paths, updatedPropertyEditorQmlPathsSourceIds); +} + +void ProjectStorage::synchronizeFunctionDeclarations( + TypeId typeId, Storage::Synchronization::FunctionDeclarations &functionsDeclarations) +{ + NanotraceHR::Tracer tracer{"synchronize function declaration"_t, projectStorageCategory()}; + + std::sort(functionsDeclarations.begin(), + functionsDeclarations.end(), + [](auto &&first, auto &&second) { + auto compare = Sqlite::compare(first.name, second.name); + + if (compare == 0) { + Utils::PathString firstSignature{createJson(first.parameters)}; + Utils::PathString secondSignature{createJson(second.parameters)}; + + return Sqlite::compare(firstSignature, secondSignature) < 0; + } + + return compare < 0; + }); + + auto range = selectFunctionDeclarationsForTypeIdStatement + .range(typeId); + + auto compareKey = [](const Storage::Synchronization::FunctionDeclarationView &view, + const Storage::Synchronization::FunctionDeclaration &value) { + auto nameKey = Sqlite::compare(view.name, value.name); + if (nameKey != 0) + return nameKey; + + Utils::PathString valueSignature{createJson(value.parameters)}; + + return Sqlite::compare(view.signature, valueSignature); + }; + + auto insert = [&](const Storage::Synchronization::FunctionDeclaration &value) { + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"insert function declaration"_t, + projectStorageCategory(), + keyValue("function declaration", value)}; + + Utils::PathString signature{createJson(value.parameters)}; + + insertFunctionDeclarationStatement.write(typeId, value.name, value.returnTypeName, signature); + }; + + auto update = [&](const Storage::Synchronization::FunctionDeclarationView &view, + const Storage::Synchronization::FunctionDeclaration &value) { + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"update function declaration"_t, + projectStorageCategory(), + keyValue("function declaration", value), + keyValue("function declaration view", view)}; + + Utils::PathString signature{createJson(value.parameters)}; + + if (value.returnTypeName == view.returnTypeName && signature == view.signature) + return Sqlite::UpdateChange::No; + + updateFunctionDeclarationStatement.write(view.id, value.returnTypeName, signature); + + tracer.end(keyValue("updated", "yes")); + + return Sqlite::UpdateChange::Update; + }; + + auto remove = [&](const Storage::Synchronization::FunctionDeclarationView &view) { + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"remove function declaration"_t, + projectStorageCategory(), + keyValue("function declaration view", view)}; + + deleteFunctionDeclarationStatement.write(view.id); + }; + + Sqlite::insertUpdateDelete(range, functionsDeclarations, compareKey, insert, update, remove); +} + +void ProjectStorage::synchronizeSignalDeclarations( + TypeId typeId, Storage::Synchronization::SignalDeclarations &signalDeclarations) +{ + NanotraceHR::Tracer tracer{"synchronize signal declaration"_t, projectStorageCategory()}; + + std::sort(signalDeclarations.begin(), signalDeclarations.end(), [](auto &&first, auto &&second) { + auto compare = Sqlite::compare(first.name, second.name); + + if (compare == 0) { + Utils::PathString firstSignature{createJson(first.parameters)}; + Utils::PathString secondSignature{createJson(second.parameters)}; + + return Sqlite::compare(firstSignature, secondSignature) < 0; + } + + return compare < 0; + }); + + auto range = selectSignalDeclarationsForTypeIdStatement + .range(typeId); + + auto compareKey = [](const Storage::Synchronization::SignalDeclarationView &view, + const Storage::Synchronization::SignalDeclaration &value) { + auto nameKey = Sqlite::compare(view.name, value.name); + if (nameKey != 0) + return nameKey; + + Utils::PathString valueSignature{createJson(value.parameters)}; + + return Sqlite::compare(view.signature, valueSignature); + }; + + auto insert = [&](const Storage::Synchronization::SignalDeclaration &value) { + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"insert signal declaration"_t, + projectStorageCategory(), + keyValue("signal declaration", value)}; + + Utils::PathString signature{createJson(value.parameters)}; + + insertSignalDeclarationStatement.write(typeId, value.name, signature); + }; + + auto update = [&]([[maybe_unused]] const Storage::Synchronization::SignalDeclarationView &view, + [[maybe_unused]] const Storage::Synchronization::SignalDeclaration &value) { + return Sqlite::UpdateChange::No; + }; + + auto remove = [&](const Storage::Synchronization::SignalDeclarationView &view) { + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"remove signal declaration"_t, + projectStorageCategory(), + keyValue("signal declaration view", view)}; + + deleteSignalDeclarationStatement.write(view.id); + }; + + Sqlite::insertUpdateDelete(range, signalDeclarations, compareKey, insert, update, remove); +} + +Utils::PathString ProjectStorage::createJson( + const Storage::Synchronization::EnumeratorDeclarations &enumeratorDeclarations) +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"create json from enumerator declarations"_t, projectStorageCategory()}; + + Utils::PathString json; + json.append("{"); + + Utils::SmallStringView comma{"\""}; + + for (const auto &enumerator : enumeratorDeclarations) { + json.append(comma); + comma = ",\""; + json.append(enumerator.name); + if (enumerator.hasValue) { + json.append("\":\""); + json.append(Utils::SmallString::number(enumerator.value)); + json.append("\""); + } else { + json.append("\":null"); + } + } + + json.append("}"); + + return json; +} + +void ProjectStorage::synchronizeEnumerationDeclarations( + TypeId typeId, Storage::Synchronization::EnumerationDeclarations &enumerationDeclarations) +{ + NanotraceHR::Tracer tracer{"synchronize enumeration declaration"_t, projectStorageCategory()}; + + std::sort(enumerationDeclarations.begin(), + enumerationDeclarations.end(), + [](auto &&first, auto &&second) { + return Sqlite::compare(first.name, second.name) < 0; + }); + + auto range = selectEnumerationDeclarationsForTypeIdStatement + .range(typeId); + + auto compareKey = [](const Storage::Synchronization::EnumerationDeclarationView &view, + const Storage::Synchronization::EnumerationDeclaration &value) { + return Sqlite::compare(view.name, value.name); + }; + + auto insert = [&](const Storage::Synchronization::EnumerationDeclaration &value) { + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"insert enumeration declaration"_t, + projectStorageCategory(), + keyValue("enumeration declaration", value)}; + + Utils::PathString signature{createJson(value.enumeratorDeclarations)}; + + insertEnumerationDeclarationStatement.write(typeId, value.name, signature); + }; + + auto update = [&](const Storage::Synchronization::EnumerationDeclarationView &view, + const Storage::Synchronization::EnumerationDeclaration &value) { + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"update enumeration declaration"_t, + projectStorageCategory(), + keyValue("enumeration declaration", value), + keyValue("enumeration declaration view", view)}; + + Utils::PathString enumeratorDeclarations{createJson(value.enumeratorDeclarations)}; + + if (enumeratorDeclarations == view.enumeratorDeclarations) + return Sqlite::UpdateChange::No; + + updateEnumerationDeclarationStatement.write(view.id, enumeratorDeclarations); + + tracer.end(keyValue("updated", "yes")); + + return Sqlite::UpdateChange::Update; + }; + + auto remove = [&](const Storage::Synchronization::EnumerationDeclarationView &view) { + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"remove enumeration declaration"_t, + projectStorageCategory(), + keyValue("enumeration declaration view", view)}; + + deleteEnumerationDeclarationStatement.write(view.id); + }; + + Sqlite::insertUpdateDelete(range, enumerationDeclarations, compareKey, insert, update, remove); +} + +void ProjectStorage::extractExportedTypes(TypeId typeId, + const Storage::Synchronization::Type &type, + Storage::Synchronization::ExportedTypes &exportedTypes) +{ + for (const auto &exportedType : type.exportedTypes) + exportedTypes.emplace_back(exportedType.name, exportedType.version, typeId, exportedType.moduleId); +} + +TypeId ProjectStorage::declareType(Storage::Synchronization::Type &type) +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"declare type"_t, + projectStorageCategory(), + keyValue("source id", type.sourceId), + keyValue("type name", type.typeName)}; + + if (type.typeName.isEmpty()) { + type.typeId = selectTypeIdBySourceIdStatement.value(type.sourceId); + + tracer.end(keyValue("type id", type.typeId)); + + return type.typeId; + } + + type.typeId = insertTypeStatement.value(type.sourceId, type.typeName); + + if (!type.typeId) + type.typeId = selectTypeIdBySourceIdAndNameStatement.value(type.sourceId, + type.typeName); + + tracer.end(keyValue("type id", type.typeId)); + + return type.typeId; +} + +void ProjectStorage::syncDeclarations(Storage::Synchronization::Type &type, + AliasPropertyDeclarations &insertedAliasPropertyDeclarations, + AliasPropertyDeclarations &updatedAliasPropertyDeclarations, + PropertyDeclarationIds &propertyDeclarationIds) +{ + NanotraceHR::Tracer tracer{"synchronize declaration per type"_t, projectStorageCategory()}; + + if (type.changeLevel == Storage::Synchronization::ChangeLevel::Minimal) + return; + + synchronizePropertyDeclarations(type.typeId, + type.propertyDeclarations, + type.sourceId, + insertedAliasPropertyDeclarations, + updatedAliasPropertyDeclarations, + propertyDeclarationIds); + synchronizeFunctionDeclarations(type.typeId, type.functionDeclarations); + synchronizeSignalDeclarations(type.typeId, type.signalDeclarations); + synchronizeEnumerationDeclarations(type.typeId, type.enumerationDeclarations); +} + +void ProjectStorage::syncDeclarations(Storage::Synchronization::Types &types, + AliasPropertyDeclarations &insertedAliasPropertyDeclarations, + AliasPropertyDeclarations &updatedAliasPropertyDeclarations, + PropertyDeclarations &relinkablePropertyDeclarations) +{ + NanotraceHR::Tracer tracer{"synchronize declaration"_t, projectStorageCategory()}; + + PropertyDeclarationIds propertyDeclarationIds; + propertyDeclarationIds.reserve(types.size() * 10); + + for (auto &&type : types) + syncDeclarations(type, + insertedAliasPropertyDeclarations, + updatedAliasPropertyDeclarations, + propertyDeclarationIds); + + removeRelinkableEntries(relinkablePropertyDeclarations, + propertyDeclarationIds, + PropertyCompare{}); +} + +void ProjectStorage::syncDefaultProperties(Storage::Synchronization::Types &types) +{ + NanotraceHR::Tracer tracer{"synchronize default properties"_t, projectStorageCategory()}; + + auto range = selectTypesWithDefaultPropertyStatement.range(); + + auto compareKey = [](const TypeWithDefaultPropertyView &view, + const Storage::Synchronization::Type &value) { + return view.typeId - value.typeId; + }; + + auto insert = [&](const Storage::Synchronization::Type &) { + + }; + + auto update = [&](const TypeWithDefaultPropertyView &view, + const Storage::Synchronization::Type &value) { + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"synchronize default properties by update"_t, + projectStorageCategory(), + keyValue("type id", value.typeId), + keyValue("value", value), + keyValue("view", view)}; + + PropertyDeclarationId valueDefaultPropertyId; + if (value.defaultPropertyName.size()) + valueDefaultPropertyId = fetchPropertyDeclarationByTypeIdAndNameUngarded(value.typeId, + value.defaultPropertyName) + .propertyDeclarationId; + + if (compareInvalidAreTrue(valueDefaultPropertyId, view.defaultPropertyId)) + return Sqlite::UpdateChange::No; + + updateDefaultPropertyIdStatement.write(value.typeId, valueDefaultPropertyId); + + tracer.end(keyValue("updated", "yes"), + keyValue("default property id", valueDefaultPropertyId)); + + return Sqlite::UpdateChange::Update; + }; + + auto remove = [&](const TypeWithDefaultPropertyView &) {}; + + Sqlite::insertUpdateDelete(range, types, compareKey, insert, update, remove); +} + +void ProjectStorage::resetDefaultPropertiesIfChanged(Storage::Synchronization::Types &types) +{ + NanotraceHR::Tracer tracer{"reset changed default properties"_t, projectStorageCategory()}; + + auto range = selectTypesWithDefaultPropertyStatement.range(); + + auto compareKey = [](const TypeWithDefaultPropertyView &view, + const Storage::Synchronization::Type &value) { + return view.typeId - value.typeId; + }; + + auto insert = [&](const Storage::Synchronization::Type &) { + + }; + + auto update = [&](const TypeWithDefaultPropertyView &view, + const Storage::Synchronization::Type &value) { + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"reset changed default properties by update"_t, + projectStorageCategory(), + keyValue("type id", value.typeId), + keyValue("value", value), + keyValue("view", view)}; + + PropertyDeclarationId valueDefaultPropertyId; + if (value.defaultPropertyName.size()) { + auto optionalValueDefaultPropertyId = fetchOptionalPropertyDeclarationByTypeIdAndNameUngarded( + value.typeId, value.defaultPropertyName); + if (optionalValueDefaultPropertyId) + valueDefaultPropertyId = optionalValueDefaultPropertyId->propertyDeclarationId; + } + + if (compareInvalidAreTrue(valueDefaultPropertyId, view.defaultPropertyId)) + return Sqlite::UpdateChange::No; + + updateDefaultPropertyIdStatement.write(value.typeId, Sqlite::NullValue{}); + + tracer.end(keyValue("updated", "yes")); + + return Sqlite::UpdateChange::Update; + }; + + auto remove = [&](const TypeWithDefaultPropertyView &) {}; + + Sqlite::insertUpdateDelete(range, types, compareKey, insert, update, remove); +} + +void ProjectStorage::checkForPrototypeChainCycle(TypeId typeId) const +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"check for prototype chain cycle"_t, + projectStorageCategory(), + keyValue("type id", typeId)}; + + auto callback = [=](TypeId currentTypeId) { + if (typeId == currentTypeId) + throw PrototypeChainCycle{}; + }; + + selectPrototypeAndExtensionIdsStatement.readCallback(callback, typeId); +} + +void ProjectStorage::checkForAliasChainCycle(PropertyDeclarationId propertyDeclarationId) const +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"check for alias chain cycle"_t, + projectStorageCategory(), + keyValue("property declaration id", propertyDeclarationId)}; + auto callback = [=](PropertyDeclarationId currentPropertyDeclarationId) { + if (propertyDeclarationId == currentPropertyDeclarationId) + throw AliasChainCycle{}; + }; + + selectPropertyDeclarationIdsForAliasChainStatement.readCallback(callback, propertyDeclarationId); +} + +std::pair ProjectStorage::fetchImportedTypeNameIdAndTypeId( + const Storage::Synchronization::ImportedTypeName &typeName, SourceId sourceId) +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"fetch imported type name id and type id"_t, + projectStorageCategory(), + keyValue("imported type name", typeName), + keyValue("source id", sourceId)}; + + TypeId typeId; + ImportedTypeNameId typeNameId; + if (!std::visit([](auto &&typeName_) -> bool { return typeName_.name.isEmpty(); }, typeName)) { + typeNameId = fetchImportedTypeNameId(typeName, sourceId); + + typeId = fetchTypeId(typeNameId); + + tracer.end(keyValue("type id", typeId), keyValue("type name id", typeNameId)); + + if (!typeId) + throw TypeNameDoesNotExists{fetchImportedTypeName(typeNameId), sourceId}; + } + + return {typeId, typeNameId}; +} + +void ProjectStorage::syncPrototypeAndExtension(Storage::Synchronization::Type &type, TypeIds &typeIds) +{ + if (type.changeLevel == Storage::Synchronization::ChangeLevel::Minimal) + return; + + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"synchronize prototype and extension"_t, + projectStorageCategory(), + keyValue("prototype", type.prototype), + keyValue("extension", type.extension), + keyValue("type id", type.typeId), + keyValue("source id", type.sourceId)}; + + auto [prototypeId, prototypeTypeNameId] = fetchImportedTypeNameIdAndTypeId(type.prototype, + type.sourceId); + auto [extensionId, extensionTypeNameId] = fetchImportedTypeNameIdAndTypeId(type.extension, + type.sourceId); + + updatePrototypeAndExtensionStatement.write(type.typeId, + prototypeId, + prototypeTypeNameId, + extensionId, + extensionTypeNameId); + + if (prototypeId || extensionId) + checkForPrototypeChainCycle(type.typeId); + + typeIds.push_back(type.typeId); + + tracer.end(keyValue("prototype id", prototypeId), + keyValue("prototype type name id", prototypeTypeNameId), + keyValue("extension id", extensionId), + keyValue("extension type name id", extensionTypeNameId)); +} + +void ProjectStorage::syncPrototypesAndExtensions(Storage::Synchronization::Types &types, + Prototypes &relinkablePrototypes, + Prototypes &relinkableExtensions) +{ + NanotraceHR::Tracer tracer{"synchronize prototypes and extensions"_t, projectStorageCategory()}; + + TypeIds typeIds; + typeIds.reserve(types.size()); + + for (auto &type : types) + syncPrototypeAndExtension(type, typeIds); + + removeRelinkableEntries(relinkablePrototypes, typeIds, TypeCompare{}); + removeRelinkableEntries(relinkableExtensions, typeIds, TypeCompare{}); +} + +ImportId ProjectStorage::fetchImportId(SourceId sourceId, const Storage::Import &import) const +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"fetch imported type name id"_t, + projectStorageCategory(), + keyValue("import", import), + keyValue("source id", sourceId)}; + + ImportId importId; + if (import.version) { + importId = selectImportIdBySourceIdAndModuleIdAndVersionStatement.value( + sourceId, import.moduleId, import.version.major.value, import.version.minor.value); + } else if (import.version.major) { + importId = selectImportIdBySourceIdAndModuleIdAndMajorVersionStatement + .value(sourceId, import.moduleId, import.version.major.value); + } else { + importId = selectImportIdBySourceIdAndModuleIdStatement.value(sourceId, + import.moduleId); + } + + tracer.end(keyValue("import id", importId)); + + return importId; +} + +ImportedTypeNameId ProjectStorage::fetchImportedTypeNameId( + const Storage::Synchronization::ImportedTypeName &name, SourceId sourceId) +{ + struct Inspect + { + auto operator()(const Storage::Synchronization::ImportedType &importedType) + { + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"fetch imported type name id"_t, + projectStorageCategory(), + keyValue("imported type name", importedType.name), + keyValue("source id", sourceId), + keyValue("type name kind", "exported"sv)}; + + return storage.fetchImportedTypeNameId(Storage::Synchronization::TypeNameKind::Exported, + sourceId, + importedType.name); + } + + auto operator()(const Storage::Synchronization::QualifiedImportedType &importedType) + { + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"fetch imported type name id"_t, + projectStorageCategory(), + keyValue("imported type name", importedType.name), + keyValue("import", importedType.import), + keyValue("type name kind", "qualified exported"sv)}; + + ImportId importId = storage.fetchImportId(sourceId, importedType.import); + + auto importedTypeNameId = storage.fetchImportedTypeNameId( + Storage::Synchronization::TypeNameKind::QualifiedExported, importId, importedType.name); + + tracer.end(keyValue("import id", importId), keyValue("source id", sourceId)); + + return importedTypeNameId; + } + + ProjectStorage &storage; + SourceId sourceId; + }; + + return std::visit(Inspect{*this, sourceId}, name); +} + +TypeId ProjectStorage::fetchTypeId(ImportedTypeNameId typeNameId) const +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"fetch type id with type name kind"_t, + projectStorageCategory(), + keyValue("type name id", typeNameId)}; + + auto kind = selectKindFromImportedTypeNamesStatement.value( + typeNameId); + + auto typeId = fetchTypeId(typeNameId, kind); + + tracer.end(keyValue("type id", typeId), keyValue("type name kind", kind)); + + return typeId; +} + +Utils::SmallString ProjectStorage::fetchImportedTypeName(ImportedTypeNameId typeNameId) const +{ + return selectNameFromImportedTypeNamesStatement.value(typeNameId); +} + +TypeId ProjectStorage::fetchTypeId(ImportedTypeNameId typeNameId, + Storage::Synchronization::TypeNameKind kind) const +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"fetch type id"_t, + projectStorageCategory(), + keyValue("type name id", typeNameId), + keyValue("type name kind", kind)}; + + TypeId typeId; + if (kind == Storage::Synchronization::TypeNameKind::Exported) { + typeId = selectTypeIdForImportedTypeNameNamesStatement.value(typeNameId); + } else { + typeId = selectTypeIdForQualifiedImportedTypeNameNamesStatement.value(typeNameId); + } + + tracer.end(keyValue("type id", typeId)); + + return typeId; +} + +std::optional +ProjectStorage::fetchOptionalPropertyDeclarationByTypeIdAndNameUngarded(TypeId typeId, + Utils::SmallStringView name) +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"fetch optional property declaration by type id and name ungarded"_t, + projectStorageCategory(), + keyValue("type id", typeId), + keyValue("property name", name)}; + + auto propertyDeclarationId = fetchPropertyDeclarationId(typeId, name); + auto propertyDeclaration = selectPropertyDeclarationResultByPropertyDeclarationIdStatement + .optionalValue( + propertyDeclarationId); + + tracer.end(keyValue("property declaration", propertyDeclaration)); + + return propertyDeclaration; +} + +ProjectStorage::FetchPropertyDeclarationResult ProjectStorage::fetchPropertyDeclarationByTypeIdAndNameUngarded( + TypeId typeId, Utils::SmallStringView name) +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"fetch property declaration by type id and name ungarded"_t, + projectStorageCategory(), + keyValue("type id", typeId), + keyValue("property name", name)}; + + auto propertyDeclaration = fetchOptionalPropertyDeclarationByTypeIdAndNameUngarded(typeId, name); + tracer.end(keyValue("property declaration", propertyDeclaration)); + + if (propertyDeclaration) + return *propertyDeclaration; + + throw PropertyNameDoesNotExists{}; +} + +PropertyDeclarationId ProjectStorage::fetchPropertyDeclarationIdByTypeIdAndNameUngarded( + TypeId typeId, Utils::SmallStringView name) +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"fetch property declaration id by type id and name ungarded"_t, + projectStorageCategory(), + keyValue("type id", typeId), + keyValue("property name", name)}; + + auto propertyDeclarationId = fetchPropertyDeclarationId(typeId, name); + + tracer.end(keyValue("property declaration id", propertyDeclarationId)); + + if (propertyDeclarationId) + return propertyDeclarationId; + + throw PropertyNameDoesNotExists{}; +} + +SourceContextId ProjectStorage::readSourceContextId(Utils::SmallStringView sourceContextPath) +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"read source context id"_t, + projectStorageCategory(), + keyValue("source context path", sourceContextPath)}; + + auto sourceContextId = selectSourceContextIdFromSourceContextsBySourceContextPathStatement + .value(sourceContextPath); + + tracer.end(keyValue("source context id", sourceContextId)); + + return sourceContextId; +} + +SourceContextId ProjectStorage::writeSourceContextId(Utils::SmallStringView sourceContextPath) +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"write source context id"_t, + projectStorageCategory(), + keyValue("source context path", sourceContextPath)}; + + insertIntoSourceContextsStatement.write(sourceContextPath); + + auto sourceContextId = SourceContextId::create(static_cast(database.lastInsertedRowId())); + + tracer.end(keyValue("source context id", sourceContextId)); + + return sourceContextId; +} + +SourceId ProjectStorage::writeSourceId(SourceContextId sourceContextId, + Utils::SmallStringView sourceName) +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"write source id"_t, + projectStorageCategory(), + keyValue("source context id", sourceContextId), + keyValue("source name", sourceName)}; + + insertIntoSourcesStatement.write(sourceContextId, sourceName); + + auto sourceId = SourceId::create(static_cast(database.lastInsertedRowId())); + + tracer.end(keyValue("source id", sourceId)); + + return sourceId; +} + +SourceId ProjectStorage::readSourceId(SourceContextId sourceContextId, + Utils::SmallStringView sourceName) +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"read source id"_t, + projectStorageCategory(), + keyValue("source context id", sourceContextId), + keyValue("source name", sourceName)}; + + auto sourceId = selectSourceIdFromSourcesBySourceContextIdAndSourceNameStatement + .value(sourceContextId, sourceName); + + tracer.end(keyValue("source id", sourceId)); + + return sourceId; +} + +Storage::Synchronization::ExportedTypes ProjectStorage::fetchExportedTypes(TypeId typeId) +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"fetch exported type"_t, + projectStorageCategory(), + keyValue("type id", typeId)}; + + auto exportedTypes = selectExportedTypesByTypeIdStatement + .values(typeId); + + tracer.end(keyValue("exported types", exportedTypes)); + + return exportedTypes; +} + +Storage::Synchronization::PropertyDeclarations ProjectStorage::fetchPropertyDeclarations(TypeId typeId) +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"fetch property declarations"_t, + projectStorageCategory(), + keyValue("type id", typeId)}; + + auto propertyDeclarations = selectPropertyDeclarationsByTypeIdStatement + .values(typeId); + + tracer.end(keyValue("property declarations", propertyDeclarations)); + + return propertyDeclarations; +} + +Storage::Synchronization::FunctionDeclarations ProjectStorage::fetchFunctionDeclarations(TypeId typeId) +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"fetch signal declarations"_t, + projectStorageCategory(), + keyValue("type id", typeId)}; + + Storage::Synchronization::FunctionDeclarations functionDeclarations; + + auto callback = [&](Utils::SmallStringView name, + Utils::SmallStringView returnType, + FunctionDeclarationId functionDeclarationId) { + auto &functionDeclaration = functionDeclarations.emplace_back(name, returnType); + functionDeclaration.parameters = selectFunctionParameterDeclarationsStatement + .values( + functionDeclarationId); + }; + + selectFunctionDeclarationsForTypeIdWithoutSignatureStatement.readCallback(callback, typeId); + + tracer.end(keyValue("function declarations", functionDeclarations)); + + return functionDeclarations; +} + +Storage::Synchronization::SignalDeclarations ProjectStorage::fetchSignalDeclarations(TypeId typeId) +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"fetch signal declarations"_t, + projectStorageCategory(), + keyValue("type id", typeId)}; + + Storage::Synchronization::SignalDeclarations signalDeclarations; + + auto callback = [&](Utils::SmallStringView name, SignalDeclarationId signalDeclarationId) { + auto &signalDeclaration = signalDeclarations.emplace_back(name); + signalDeclaration.parameters = selectSignalParameterDeclarationsStatement + .values( + signalDeclarationId); + }; + + selectSignalDeclarationsForTypeIdWithoutSignatureStatement.readCallback(callback, typeId); + + tracer.end(keyValue("signal declarations", signalDeclarations)); + + return signalDeclarations; +} + +Storage::Synchronization::EnumerationDeclarations ProjectStorage::fetchEnumerationDeclarations(TypeId typeId) +{ + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"fetch enumeration declarations"_t, + projectStorageCategory(), + keyValue("type id", typeId)}; + + Storage::Synchronization::EnumerationDeclarations enumerationDeclarations; + + auto callback = [&](Utils::SmallStringView name, + EnumerationDeclarationId enumerationDeclarationId) { + enumerationDeclarations.emplace_back( + name, + selectEnumeratorDeclarationStatement + .values(enumerationDeclarationId)); + }; + + selectEnumerationDeclarationsForTypeIdWithoutEnumeratorDeclarationsStatement.readCallback(callback, + typeId); + + tracer.end(keyValue("enumeration declarations", enumerationDeclarations)); + + return enumerationDeclarations; +} + +} // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstorage.h b/src/plugins/qmldesigner/designercore/projectstorage/projectstorage.h index 70d5e92b256..d7687a8c6f9 100644 --- a/src/plugins/qmldesigner/designercore/projectstorage/projectstorage.h +++ b/src/plugins/qmldesigner/designercore/projectstorage/projectstorage.h @@ -33,10 +33,10 @@ using namespace NanotraceHR::Literals; using ProjectStorageTracing::projectStorageCategory; -template class ProjectStorage final : public ProjectStorageInterface { - friend Storage::Info::CommonTypeCache; + using Database = Sqlite::Database; + friend Storage::Info::CommonTypeCache; public: template @@ -46,655 +46,79 @@ public: template using WriteStatement = typename Database::template WriteStatement; - ProjectStorage(Database &database, bool isInitialized) - : database{database} - , exclusiveTransaction{database} - , initializer{database, isInitialized} - { - NanotraceHR::Tracer tracer{"initialize"_t, projectStorageCategory()}; + ProjectStorage(Database &database, bool isInitialized); + ~ProjectStorage(); - exclusiveTransaction.commit(); + void synchronize(Storage::Synchronization::SynchronizationPackage package) override; - database.walCheckpointFull(); + void synchronizeDocumentImports(Storage::Imports imports, SourceId sourceId) override; - moduleCache.populate(); - } + void addObserver(ProjectStorageObserver *observer) override; - void synchronize(Storage::Synchronization::SynchronizationPackage package) override - { - NanotraceHR::Tracer tracer{"synchronize"_t, projectStorageCategory()}; + void removeObserver(ProjectStorageObserver *observer) override; - TypeIds deletedTypeIds; - Sqlite::withImmediateTransaction(database, [&] { - AliasPropertyDeclarations insertedAliasPropertyDeclarations; - AliasPropertyDeclarations updatedAliasPropertyDeclarations; + ModuleId moduleId(Utils::SmallStringView moduleName) const override; - AliasPropertyDeclarations relinkableAliasPropertyDeclarations; - PropertyDeclarations relinkablePropertyDeclarations; - Prototypes relinkablePrototypes; - Prototypes relinkableExtensions; - - TypeIds updatedTypeIds; - updatedTypeIds.reserve(package.types.size()); - - TypeIds typeIdsToBeDeleted; - - std::sort(package.updatedSourceIds.begin(), package.updatedSourceIds.end()); - - synchronizeFileStatuses(package.fileStatuses, package.updatedFileStatusSourceIds); - synchronizeImports(package.imports, - package.updatedSourceIds, - package.moduleDependencies, - package.updatedModuleDependencySourceIds, - package.moduleExportedImports, - package.updatedModuleIds); - synchronizeTypes(package.types, - updatedTypeIds, - insertedAliasPropertyDeclarations, - updatedAliasPropertyDeclarations, - relinkableAliasPropertyDeclarations, - relinkablePropertyDeclarations, - relinkablePrototypes, - relinkableExtensions, - package.updatedSourceIds); - synchronizeTypeAnnotations(package.typeAnnotations, - package.updatedTypeAnnotationSourceIds); - synchronizePropertyEditorQmlPaths(package.propertyEditorQmlPaths, - package.updatedPropertyEditorQmlPathSourceIds); - - deleteNotUpdatedTypes(updatedTypeIds, - package.updatedSourceIds, - typeIdsToBeDeleted, - relinkableAliasPropertyDeclarations, - relinkablePropertyDeclarations, - relinkablePrototypes, - relinkableExtensions, - deletedTypeIds); - - relink(relinkableAliasPropertyDeclarations, - relinkablePropertyDeclarations, - relinkablePrototypes, - relinkableExtensions, - deletedTypeIds); - - linkAliases(insertedAliasPropertyDeclarations, updatedAliasPropertyDeclarations); - - synchronizeProjectDatas(package.projectDatas, package.updatedProjectSourceIds); - - commonTypeCache_.resetTypeIds(); - }); - - callRefreshMetaInfoCallback(deletedTypeIds); - } - - void synchronizeDocumentImports(Storage::Imports imports, SourceId sourceId) override - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"synchronize document imports"_t, - projectStorageCategory(), - keyValue("imports", imports), - keyValue("source id", sourceId)}; - - Sqlite::withImmediateTransaction(database, [&] { - synchronizeDocumentImports(imports, - {sourceId}, - Storage::Synchronization::ImportKind::Import); - }); - } - - void addObserver(ProjectStorageObserver *observer) override - { - NanotraceHR::Tracer tracer{"add observer"_t, projectStorageCategory()}; - observers.push_back(observer); - } - - void removeObserver(ProjectStorageObserver *observer) override - { - NanotraceHR::Tracer tracer{"remove observer"_t, projectStorageCategory()}; - observers.removeOne(observer); - } - - ModuleId moduleId(Utils::SmallStringView moduleName) const override - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"get module id"_t, - projectStorageCategory(), - keyValue("module name", moduleName)}; - - auto moduleId = moduleCache.id(moduleName); - - tracer.end(keyValue("module id", moduleId)); - - return moduleId; - } - - Utils::SmallString moduleName(ModuleId moduleId) const override - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"get module name"_t, - projectStorageCategory(), - keyValue("module id", moduleId)}; - - if (!moduleId) - throw ModuleDoesNotExists{}; - - auto moduleName = moduleCache.value(moduleId); - - tracer.end(keyValue("module name", moduleName)); - - return moduleName; - } + Utils::SmallString moduleName(ModuleId moduleId) const override; TypeId typeId(ModuleId moduleId, Utils::SmallStringView exportedTypeName, - Storage::Version version) const override - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"get type id by exported name"_t, - projectStorageCategory(), - keyValue("module id", moduleId), - keyValue("exported type name", exportedTypeName), - keyValue("version", version)}; + Storage::Version version) const override; - TypeId typeId; + TypeId typeId(ImportedTypeNameId typeNameId) const override; - if (version.minor) { - typeId = selectTypeIdByModuleIdAndExportedNameAndVersionStatement - .template valueWithTransaction(moduleId, - exportedTypeName, - version.major.value, - version.minor.value); + QVarLengthArray typeIds(ModuleId moduleId) const override; - } else if (version.major) { - typeId = selectTypeIdByModuleIdAndExportedNameAndMajorVersionStatement - .template valueWithTransaction(moduleId, - exportedTypeName, - version.major.value); + Storage::Info::ExportedTypeNames exportedTypeNames(TypeId typeId) const override; - } else { - typeId = selectTypeIdByModuleIdAndExportedNameStatement - .template valueWithTransaction(moduleId, exportedTypeName); - } + Storage::Info::ExportedTypeNames exportedTypeNames(TypeId typeId, SourceId sourceId) const override; - tracer.end(keyValue("type id", typeId)); + ImportId importId(const Storage::Import &import) const override; - return typeId; - } + ImportedTypeNameId importedTypeNameId(ImportId importId, Utils::SmallStringView typeName) override; - TypeId typeId(ImportedTypeNameId typeNameId) const override - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"get type id by imported type name"_t, - projectStorageCategory(), - keyValue("imported type name id", typeNameId)}; + ImportedTypeNameId importedTypeNameId(SourceId sourceId, Utils::SmallStringView typeName) override; - auto typeId = Sqlite::withDeferredTransaction(database, - [&] { return fetchTypeId(typeNameId); }); + QVarLengthArray propertyDeclarationIds(TypeId typeId) const override; - tracer.end(keyValue("type id", typeId)); - - return typeId; - } - - QVarLengthArray typeIds(ModuleId moduleId) const override - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"get type ids by module id"_t, - projectStorageCategory(), - keyValue("module id", moduleId)}; - - auto typeIds = selectTypeIdsByModuleIdStatement - .template valuesWithTransaction>(moduleId); - - tracer.end(keyValue("type ids", typeIds)); - - return typeIds; - } - - Storage::Info::ExportedTypeNames exportedTypeNames(TypeId typeId) const override - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"get exported type names by type id"_t, - projectStorageCategory(), - keyValue("type id", typeId)}; - - auto exportedTypenames = selectExportedTypesByTypeIdStatement - .template valuesWithTransaction( - typeId); - - tracer.end(keyValue("exported type names", exportedTypenames)); - - return exportedTypenames; - } - - Storage::Info::ExportedTypeNames exportedTypeNames(TypeId typeId, SourceId sourceId) const override - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"get exported type names by source id"_t, - projectStorageCategory(), - keyValue("type id", typeId), - keyValue("source id", sourceId)}; - - auto exportedTypenames = selectExportedTypesByTypeIdAndSourceIdStatement - .template valuesWithTransaction(typeId, sourceId); - - tracer.end(keyValue("exported type names", exportedTypenames)); - - return exportedTypenames; - } - - ImportId importId(const Storage::Import &import) const override - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"get import id by import"_t, - projectStorageCategory(), - keyValue("import", import)}; - - auto importId = Sqlite::withDeferredTransaction(database, [&] { - return fetchImportId(import.sourceId, import); - }); - - tracer.end(keyValue("import id", importId)); - - return importId; - } - - ImportedTypeNameId importedTypeNameId(ImportId importId, Utils::SmallStringView typeName) override - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"get imported type name id by import id"_t, - projectStorageCategory(), - keyValue("import id", importId), - keyValue("imported type name", typeName)}; - - auto importedTypeNameId = Sqlite::withDeferredTransaction(database, [&] { - return fetchImportedTypeNameId(Storage::Synchronization::TypeNameKind::QualifiedExported, - importId, - typeName); - }); - - tracer.end(keyValue("imported type name id", importedTypeNameId)); - - return importedTypeNameId; - } - - ImportedTypeNameId importedTypeNameId(SourceId sourceId, Utils::SmallStringView typeName) override - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"get imported type name id by source id"_t, - projectStorageCategory(), - keyValue("source id", sourceId), - keyValue("imported type name", typeName)}; - - auto importedTypeNameId = Sqlite::withDeferredTransaction(database, [&] { - return fetchImportedTypeNameId(Storage::Synchronization::TypeNameKind::Exported, - sourceId, - typeName); - }); - - tracer.end(keyValue("imported type name id", importedTypeNameId)); - - return importedTypeNameId; - } - - QVarLengthArray propertyDeclarationIds(TypeId typeId) const override - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"get property declaration ids"_t, - projectStorageCategory(), - keyValue("type id", typeId)}; - - auto propertyDeclarationIds = Sqlite::withDeferredTransaction(database, [&] { - return fetchPropertyDeclarationIds(typeId); - }); - - std::sort(propertyDeclarationIds.begin(), propertyDeclarationIds.end()); - - tracer.end(keyValue("property declaration ids", propertyDeclarationIds)); - - return propertyDeclarationIds; - } - - QVarLengthArray localPropertyDeclarationIds(TypeId typeId) const override - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"get local property declaration ids"_t, - projectStorageCategory(), - keyValue("type id", typeId)}; - - auto propertyDeclarationIds = selectLocalPropertyDeclarationIdsForTypeStatement - .template valuesWithTransaction< - QVarLengthArray>(typeId); - - tracer.end(keyValue("property declaration ids", propertyDeclarationIds)); - - return propertyDeclarationIds; - } + QVarLengthArray localPropertyDeclarationIds(TypeId typeId) const override; PropertyDeclarationId propertyDeclarationId(TypeId typeId, - Utils::SmallStringView propertyName) const override - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"get property declaration id"_t, - projectStorageCategory(), - keyValue("type id", typeId), - keyValue("property name", propertyName)}; - - auto propertyDeclarationId = Sqlite::withDeferredTransaction(database, [&] { - return fetchPropertyDeclarationId(typeId, propertyName); - }); - - tracer.end(keyValue("property declaration id", propertyDeclarationId)); - - return propertyDeclarationId; - } + Utils::SmallStringView propertyName) const override; PropertyDeclarationId localPropertyDeclarationId(TypeId typeId, - Utils::SmallStringView propertyName) const - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"get local property declaration id"_t, - projectStorageCategory(), - keyValue("type id", typeId), - keyValue("property name", propertyName)}; + Utils::SmallStringView propertyName) const; - auto propertyDeclarationId = selectLocalPropertyDeclarationIdForTypeAndPropertyNameStatement - .template valueWithTransaction( - typeId, propertyName); - - tracer.end(keyValue("property declaration id", propertyDeclarationId)); - - return propertyDeclarationId; - } - - PropertyDeclarationId defaultPropertyDeclarationId(TypeId typeId) const override - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"get default property declaration id"_t, - projectStorageCategory(), - keyValue("type id", typeId)}; - - auto propertyDeclarationId = Sqlite::withDeferredTransaction(database, [&] { - return fetchDefaultPropertyDeclarationId(typeId); - }); - - tracer.end(keyValue("property declaration id", propertyDeclarationId)); - - return propertyDeclarationId; - } + PropertyDeclarationId defaultPropertyDeclarationId(TypeId typeId) const override; std::optional propertyDeclaration( - PropertyDeclarationId propertyDeclarationId) const override - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"get property declaration"_t, - projectStorageCategory(), - keyValue("property declaration id", propertyDeclarationId)}; + PropertyDeclarationId propertyDeclarationId) const override; - auto propertyDeclaration = selectPropertyDeclarationForPropertyDeclarationIdStatement - .template optionalValueWithTransaction( - propertyDeclarationId); + std::optional type(TypeId typeId) const override; - tracer.end(keyValue("property declaration", propertyDeclaration)); + Utils::PathString typeIconPath(TypeId typeId) const override; - return propertyDeclaration; - } + Storage::Info::TypeHints typeHints(TypeId typeId) const override; - std::optional type(TypeId typeId) const override - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"get type"_t, projectStorageCategory(), keyValue("type id", typeId)}; + SmallSourceIds<4> typeAnnotationSourceIds(SourceId directoryId) const override; - auto type = selectInfoTypeByTypeIdStatement - .template optionalValueWithTransaction(typeId); + SmallSourceIds<64> typeAnnotationDirectorySourceIds() const override; - tracer.end(keyValue("type", type)); + Storage::Info::ItemLibraryEntries itemLibraryEntries(TypeId typeId) const override; - return type; - } + Storage::Info::ItemLibraryEntries itemLibraryEntries(ImportId importId) const; - Utils::PathString typeIconPath(TypeId typeId) const override - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"get type icon path"_t, - projectStorageCategory(), - keyValue("type id", typeId)}; + Storage::Info::ItemLibraryEntries itemLibraryEntries(SourceId sourceId) const override; - auto typeIconPath = selectTypeIconPathStatement.template valueWithTransaction( - typeId); + Storage::Info::ItemLibraryEntries allItemLibraryEntries() const override; - tracer.end(keyValue("type icon path", typeIconPath)); + std::vector signalDeclarationNames(TypeId typeId) const override; - return typeIconPath; - } + std::vector functionDeclarationNames(TypeId typeId) const override; - Storage::Info::TypeHints typeHints(TypeId typeId) const override - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"get type hints"_t, - projectStorageCategory(), - keyValue("type id", typeId)}; + std::optional propertyName(PropertyDeclarationId propertyDeclarationId) const override; - auto typeHints = selectTypeHintsStatement - .template valuesWithTransaction(typeId); - - tracer.end(keyValue("type hints", typeHints)); - - return typeHints; - } - - SmallSourceIds<4> typeAnnotationSourceIds(SourceId directoryId) const override - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"get type annotaion source ids"_t, - projectStorageCategory(), - keyValue("source id", directoryId)}; - - auto sourceIds = selectTypeAnnotationSourceIdsStatement - .template valuesWithTransaction>(directoryId); - - tracer.end(keyValue("source ids", sourceIds)); - - return sourceIds; - } - - SmallSourceIds<64> typeAnnotationDirectorySourceIds() const override - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"get type annotaion source ids"_t, projectStorageCategory()}; - - auto sourceIds = selectTypeAnnotationDirectorySourceIdsStatement - .template valuesWithTransaction>(); - - tracer.end(keyValue("source ids", sourceIds)); - - return sourceIds; - } - - Storage::Info::ItemLibraryEntries itemLibraryEntries(TypeId typeId) const override - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"get item library entries by type id"_t, - projectStorageCategory(), - keyValue("type id", typeId)}; - - using Storage::Info::ItemLibraryProperties; - Storage::Info::ItemLibraryEntries entries; - - auto callback = [&](TypeId typeId_, - Utils::SmallStringView name, - Utils::SmallStringView iconPath, - Utils::SmallStringView category, - Utils::SmallStringView import, - Utils::SmallStringView toolTip, - Utils::SmallStringView properties, - Utils::SmallStringView extraFilePaths, - Utils::SmallStringView templatePath) { - auto &last = entries.emplace_back( - typeId_, name, iconPath, category, import, toolTip, templatePath); - if (properties.size()) - selectItemLibraryPropertiesStatement.readTo(last.properties, properties); - if (extraFilePaths.size()) - selectItemLibraryExtraFilePathsStatement.readTo(last.extraFilePaths, extraFilePaths); - }; - - selectItemLibraryEntriesByTypeIdStatement.readCallbackWithTransaction(callback, typeId); - - tracer.end(keyValue("item library entries", entries)); - - return entries; - } - - Storage::Info::ItemLibraryEntries itemLibraryEntries(ImportId importId) const - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"get item library entries by import id"_t, - projectStorageCategory(), - keyValue("import id", importId)}; - - using Storage::Info::ItemLibraryProperties; - Storage::Info::ItemLibraryEntries entries; - - auto callback = [&](TypeId typeId_, - Utils::SmallStringView name, - Utils::SmallStringView iconPath, - Utils::SmallStringView category, - Utils::SmallStringView import, - Utils::SmallStringView toolTip, - Utils::SmallStringView properties, - Utils::SmallStringView extraFilePaths, - Utils::SmallStringView templatePath) { - auto &last = entries.emplace_back( - typeId_, name, iconPath, category, import, toolTip, templatePath); - if (properties.size()) - selectItemLibraryPropertiesStatement.readTo(last.properties, properties); - if (extraFilePaths.size()) - selectItemLibraryExtraFilePathsStatement.readTo(last.extraFilePaths, extraFilePaths); - }; - - selectItemLibraryEntriesByTypeIdStatement.readCallbackWithTransaction(callback, importId); - - tracer.end(keyValue("item library entries", entries)); - - return entries; - } - - Storage::Info::ItemLibraryEntries itemLibraryEntries(SourceId sourceId) const override - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"get item library entries by source id"_t, - projectStorageCategory(), - keyValue("source id", sourceId)}; - - using Storage::Info::ItemLibraryProperties; - Storage::Info::ItemLibraryEntries entries; - - auto callback = [&](TypeId typeId, - Utils::SmallStringView name, - Utils::SmallStringView iconPath, - Utils::SmallStringView category, - Utils::SmallStringView import, - Utils::SmallStringView toolTip, - Utils::SmallStringView properties, - Utils::SmallStringView extraFilePaths, - Utils::SmallStringView templatePath) { - auto &last = entries.emplace_back( - typeId, name, iconPath, category, import, toolTip, templatePath); - if (properties.size()) - selectItemLibraryPropertiesStatement.readTo(last.properties, properties); - if (extraFilePaths.size()) - selectItemLibraryExtraFilePathsStatement.readTo(last.extraFilePaths, extraFilePaths); - }; - - selectItemLibraryEntriesBySourceIdStatement.readCallbackWithTransaction(callback, sourceId); - - tracer.end(keyValue("item library entries", entries)); - - return entries; - } - - Storage::Info::ItemLibraryEntries allItemLibraryEntries() const override - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"get all item library entries"_t, projectStorageCategory()}; - - using Storage::Info::ItemLibraryProperties; - Storage::Info::ItemLibraryEntries entries; - - auto callback = [&](TypeId typeId, - Utils::SmallStringView name, - Utils::SmallStringView iconPath, - Utils::SmallStringView category, - Utils::SmallStringView import, - Utils::SmallStringView toolTip, - Utils::SmallStringView properties, - Utils::SmallStringView extraFilePaths, - Utils::SmallStringView templatePath) { - auto &last = entries.emplace_back( - typeId, name, iconPath, category, import, toolTip, templatePath); - if (properties.size()) - selectItemLibraryPropertiesStatement.readTo(last.properties, properties); - if (extraFilePaths.size()) - selectItemLibraryExtraFilePathsStatement.readTo(last.extraFilePaths, extraFilePaths); - }; - - selectItemLibraryEntriesStatement.readCallbackWithTransaction(callback); - - tracer.end(keyValue("item library entries", entries)); - - return entries; - } - - std::vector signalDeclarationNames(TypeId typeId) const override - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"get signal names"_t, - projectStorageCategory(), - keyValue("type id", typeId)}; - - auto signalDeclarationNames = selectSignalDeclarationNamesForTypeStatement - .template valuesWithTransaction( - typeId); - - tracer.end(keyValue("signal names", signalDeclarationNames)); - - return signalDeclarationNames; - } - - std::vector functionDeclarationNames(TypeId typeId) const override - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"get function names"_t, - projectStorageCategory(), - keyValue("type id", typeId)}; - - auto functionDeclarationNames = selectFuncionDeclarationNamesForTypeStatement - .template valuesWithTransaction( - typeId); - - tracer.end(keyValue("function names", functionDeclarationNames)); - - return functionDeclarationNames; - } - - std::optional propertyName(PropertyDeclarationId propertyDeclarationId) const override - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"get property name"_t, - projectStorageCategory(), - keyValue("property declaration id", propertyDeclarationId)}; - - auto propertyName = selectPropertyNameStatement - .template optionalValueWithTransaction( - propertyDeclarationId); - - tracer.end(keyValue("property name", propertyName)); - - return propertyName; - } - - const Storage::Info::CommonTypeCache &commonTypeCache() const override + const Storage::Info::CommonTypeCache &commonTypeCache() const override { return commonTypeCache_; } @@ -708,7 +132,7 @@ public: keyValue("module name", std::string_view{moduleName}), keyValue("type name", std::string_view{typeName})}; - auto typeId = commonTypeCache_.template typeId(); + auto typeId = commonTypeCache_.typeId(); tracer.end(keyValue("type id", typeId)); @@ -722,7 +146,7 @@ public: NanotraceHR::Tracer tracer{"get builtin type id from common type cache"_t, projectStorageCategory()}; - auto typeId = commonTypeCache_.template builtinTypeId(); + auto typeId = commonTypeCache_.builtinTypeId(); tracer.end(keyValue("type id", typeId)); @@ -736,55 +160,18 @@ public: NanotraceHR::Tracer tracer{"get builtin type id from common type cache"_t, projectStorageCategory()}; - auto typeId = commonTypeCache_.template builtinTypeId(); + auto typeId = commonTypeCache_.builtinTypeId(); tracer.end(keyValue("type id", typeId)); return typeId; } - SmallTypeIds<16> prototypeIds(TypeId type) const override - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"get prototypes"_t, - projectStorageCategory(), - keyValue("type id", type)}; + SmallTypeIds<16> prototypeIds(TypeId type) const override; - auto prototypeIds = selectPrototypeAndExtensionIdsStatement - .template valuesWithTransaction>(type); + SmallTypeIds<16> prototypeAndSelfIds(TypeId typeId) const override; - tracer.end(keyValue("type ids", prototypeIds)); - - return prototypeIds; - } - - SmallTypeIds<16> prototypeAndSelfIds(TypeId typeId) const override - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"get prototypes and self"_t, projectStorageCategory()}; - - SmallTypeIds<16> prototypeAndSelfIds; - prototypeAndSelfIds.push_back(typeId); - - selectPrototypeAndExtensionIdsStatement.readToWithTransaction(prototypeAndSelfIds, typeId); - - tracer.end(keyValue("type ids", prototypeAndSelfIds)); - - return prototypeAndSelfIds; - } - - SmallTypeIds<64> heirIds(TypeId typeId) const override - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"get heirs"_t, projectStorageCategory()}; - - auto heirIds = selectHeirTypeIdsStatement.template valuesWithTransaction>( - typeId); - - tracer.end(keyValue("type ids", heirIds)); - - return heirIds; - } + SmallTypeIds<64> heirIds(TypeId typeId) const override; template bool isBasedOn_(TypeId typeId, TypeIds... baseTypeIds) const @@ -802,8 +189,7 @@ public: return true; } - auto range = selectPrototypeAndExtensionIdsStatement.template rangeWithTransaction( - typeId); + auto range = selectPrototypeAndExtensionIdsStatement.rangeWithTransaction(typeId); auto isBasedOn = std::any_of(range.begin(), range.end(), [&](TypeId currentTypeId) { return ((currentTypeId == baseTypeIds) || ...); @@ -814,35 +200,20 @@ public: return isBasedOn; } - bool isBasedOn(TypeId) const { return false; } + bool isBasedOn(TypeId) const; - bool isBasedOn(TypeId typeId, TypeId id1) const override { return isBasedOn_(typeId, id1); } + bool isBasedOn(TypeId typeId, TypeId id1) const override; - bool isBasedOn(TypeId typeId, TypeId id1, TypeId id2) const override - { - return isBasedOn_(typeId, id1, id2); - } + bool isBasedOn(TypeId typeId, TypeId id1, TypeId id2) const override; - bool isBasedOn(TypeId typeId, TypeId id1, TypeId id2, TypeId id3) const override - { - return isBasedOn_(typeId, id1, id2, id3); - } + bool isBasedOn(TypeId typeId, TypeId id1, TypeId id2, TypeId id3) const override; - bool isBasedOn(TypeId typeId, TypeId id1, TypeId id2, TypeId id3, TypeId id4) const override - { - return isBasedOn_(typeId, id1, id2, id3, id4); - } + bool isBasedOn(TypeId typeId, TypeId id1, TypeId id2, TypeId id3, TypeId id4) const override; - bool isBasedOn(TypeId typeId, TypeId id1, TypeId id2, TypeId id3, TypeId id4, TypeId id5) const override - { - return isBasedOn_(typeId, id1, id2, id3, id4, id5); - } + bool isBasedOn(TypeId typeId, TypeId id1, TypeId id2, TypeId id3, TypeId id4, TypeId id5) const override; - bool isBasedOn( - TypeId typeId, TypeId id1, TypeId id2, TypeId id3, TypeId id4, TypeId id5, TypeId id6) const override - { - return isBasedOn_(typeId, id1, id2, id3, id4, id5, id6); - } + bool isBasedOn(TypeId typeId, TypeId id1, TypeId id2, TypeId id3, TypeId id4, TypeId id5, TypeId id6) + const override; bool isBasedOn(TypeId typeId, TypeId id1, @@ -851,361 +222,62 @@ public: TypeId id4, TypeId id5, TypeId id6, - TypeId id7) const override - { - return isBasedOn_(typeId, id1, id2, id3, id4, id5, id6, id7); - } + TypeId id7) const override; - TypeId fetchTypeIdByExportedName(Utils::SmallStringView name) const - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"is based on"_t, - projectStorageCategory(), - keyValue("exported type name", name)}; + TypeId fetchTypeIdByExportedName(Utils::SmallStringView name) const; - auto typeId = selectTypeIdByExportedNameStatement.template valueWithTransaction(name); + TypeId fetchTypeIdByModuleIdsAndExportedName(ModuleIds moduleIds, + Utils::SmallStringView name) const; - tracer.end(keyValue("type id", typeId)); + TypeId fetchTypeIdByName(SourceId sourceId, Utils::SmallStringView name); - return typeId; - } + Storage::Synchronization::Type fetchTypeByTypeId(TypeId typeId); - TypeId fetchTypeIdByModuleIdsAndExportedName(ModuleIds moduleIds, Utils::SmallStringView name) const - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"fetch type id by module ids and exported name"_t, - projectStorageCategory(), - keyValue("module ids", NanotraceHR::array(moduleIds)), - keyValue("exported type name", name)}; - auto typeId = selectTypeIdByModuleIdsAndExportedNameStatement.template valueWithTransaction( - static_cast(moduleIds.data()), static_cast(moduleIds.size()), name); + Storage::Synchronization::Types fetchTypes(); - tracer.end(keyValue("type id", typeId)); + SourceContextId fetchSourceContextIdUnguarded(Utils::SmallStringView sourceContextPath); - return typeId; - } + SourceContextId fetchSourceContextId(Utils::SmallStringView sourceContextPath); - TypeId fetchTypeIdByName(SourceId sourceId, Utils::SmallStringView name) - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"fetch type id by name"_t, - projectStorageCategory(), - keyValue("source id", sourceId), - keyValue("internal type name", name)}; + Utils::PathString fetchSourceContextPath(SourceContextId sourceContextId) const; - auto typeId = selectTypeIdBySourceIdAndNameStatement - .template valueWithTransaction(sourceId, name); + Cache::SourceContexts fetchAllSourceContexts() const; - tracer.end(keyValue("type id", typeId)); + SourceId fetchSourceId(SourceContextId sourceContextId, Utils::SmallStringView sourceName); - return typeId; - } + Cache::SourceNameAndSourceContextId fetchSourceNameAndSourceContextId(SourceId sourceId) const; - Storage::Synchronization::Type fetchTypeByTypeId(TypeId typeId) - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"fetch type by type id"_t, - projectStorageCategory(), - keyValue("type id", typeId)}; + void clearSources(); - auto type = Sqlite::withDeferredTransaction(database, [&] { - auto type = selectTypeByTypeIdStatement.template value( - typeId); + SourceContextId fetchSourceContextId(SourceId sourceId) const; - type.exportedTypes = fetchExportedTypes(typeId); - type.propertyDeclarations = fetchPropertyDeclarations(type.typeId); - type.functionDeclarations = fetchFunctionDeclarations(type.typeId); - type.signalDeclarations = fetchSignalDeclarations(type.typeId); - type.enumerationDeclarations = fetchEnumerationDeclarations(type.typeId); + Cache::Sources fetchAllSources() const; - return type; - }); - - tracer.end(keyValue("type", type)); - - return type; - } - - Storage::Synchronization::Types fetchTypes() - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"fetch types"_t, projectStorageCategory()}; - - auto types = Sqlite::withDeferredTransaction(database, [&] { - auto types = selectTypesStatement.template values(); - - for (Storage::Synchronization::Type &type : types) { - type.exportedTypes = fetchExportedTypes(type.typeId); - type.propertyDeclarations = fetchPropertyDeclarations(type.typeId); - type.functionDeclarations = fetchFunctionDeclarations(type.typeId); - type.signalDeclarations = fetchSignalDeclarations(type.typeId); - type.enumerationDeclarations = fetchEnumerationDeclarations(type.typeId); - } - - return types; - }); - - tracer.end(keyValue("type", types)); - - return types; - } - - SourceContextId fetchSourceContextIdUnguarded(Utils::SmallStringView sourceContextPath) - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"fetch source context id unguarded"_t, projectStorageCategory()}; - - auto sourceContextId = readSourceContextId(sourceContextPath); - - return sourceContextId ? sourceContextId : writeSourceContextId(sourceContextPath); - } - - SourceContextId fetchSourceContextId(Utils::SmallStringView sourceContextPath) - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"fetch source context id"_t, - projectStorageCategory(), - keyValue("source context path", sourceContextPath)}; - - SourceContextId sourceContextId; - try { - sourceContextId = Sqlite::withDeferredTransaction(database, [&] { - return fetchSourceContextIdUnguarded(sourceContextPath); - }); - } catch (const Sqlite::ConstraintPreventsModification &) { - sourceContextId = fetchSourceContextId(sourceContextPath); - } - - tracer.end(keyValue("source context id", sourceContextId)); - - return sourceContextId; - } - - Utils::PathString fetchSourceContextPath(SourceContextId sourceContextId) const - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"fetch source context path"_t, - projectStorageCategory(), - keyValue("source context id", sourceContextId)}; - - auto path = Sqlite::withDeferredTransaction(database, [&] { - auto optionalSourceContextPath = selectSourceContextPathFromSourceContextsBySourceContextIdStatement - .template optionalValue( - sourceContextId); - - if (!optionalSourceContextPath) - throw SourceContextIdDoesNotExists(); - - return std::move(*optionalSourceContextPath); - }); - - tracer.end(keyValue("source context path", path)); - - return path; - } - - auto fetchAllSourceContexts() const - { - NanotraceHR::Tracer tracer{"fetch all source contexts"_t, projectStorageCategory()}; - - return selectAllSourceContextsStatement - .template valuesWithTransaction(); - } - - SourceId fetchSourceId(SourceContextId sourceContextId, Utils::SmallStringView sourceName) - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"fetch source id"_t, - projectStorageCategory(), - keyValue("source context id", sourceContextId), - keyValue("source name", sourceName)}; - - auto sourceId = Sqlite::withDeferredTransaction(database, [&] { - return fetchSourceIdUnguarded(sourceContextId, sourceName); - }); - - tracer.end(keyValue("source id", sourceId)); - - return sourceId; - } - - auto fetchSourceNameAndSourceContextId(SourceId sourceId) const - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"fetch source name and source context id"_t, - projectStorageCategory(), - keyValue("source id", sourceId)}; - - auto value = selectSourceNameAndSourceContextIdFromSourcesBySourceIdStatement - .template valueWithTransaction(sourceId); - - if (!value.sourceContextId) - throw SourceIdDoesNotExists(); - - tracer.end(keyValue("source name", value.sourceName), - keyValue("source context id", value.sourceContextId)); - - return value; - } - - void clearSources() - { - Sqlite::withImmediateTransaction(database, [&] { - deleteAllSourceContextsStatement.execute(); - deleteAllSourcesStatement.execute(); - }); - } - - SourceContextId fetchSourceContextId(SourceId sourceId) const - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"fetch source context id"_t, - projectStorageCategory(), - keyValue("source id", sourceId)}; - - auto sourceContextId = selectSourceContextIdFromSourcesBySourceIdStatement - .template valueWithTransaction(sourceId); - - if (!sourceContextId) - throw SourceIdDoesNotExists(); - - tracer.end(keyValue("source context id", sourceContextId)); - - return sourceContextId; - } - - auto fetchAllSources() const - { - NanotraceHR::Tracer tracer{"fetch all sources"_t, projectStorageCategory()}; - - return selectAllSourcesStatement.template valuesWithTransaction(); - } - - SourceId fetchSourceIdUnguarded(SourceContextId sourceContextId, Utils::SmallStringView sourceName) - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"fetch source id unguarded"_t, - projectStorageCategory(), - keyValue("source context id", sourceContextId), - keyValue("source name", sourceName)}; - - auto sourceId = readSourceId(sourceContextId, sourceName); - - if (!sourceId) - sourceId = writeSourceId(sourceContextId, sourceName); - - tracer.end(keyValue("source id", sourceId)); - - return sourceId; - } + SourceId fetchSourceIdUnguarded(SourceContextId sourceContextId, + Utils::SmallStringView sourceName); auto fetchAllFileStatuses() const { NanotraceHR::Tracer tracer{"fetch all file statuses"_t, projectStorageCategory()}; - return selectAllFileStatusesStatement.template rangeWithTransaction(); + return selectAllFileStatusesStatement.rangeWithTransaction(); } - FileStatus fetchFileStatus(SourceId sourceId) const override - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"fetch file status"_t, - projectStorageCategory(), - keyValue("source id", sourceId)}; + FileStatus fetchFileStatus(SourceId sourceId) const override; - auto fileStatus = selectFileStatusesForSourceIdStatement - .template valueWithTransaction(sourceId); + std::optional fetchProjectData(SourceId sourceId) const override; - tracer.end(keyValue("file status", fileStatus)); + Storage::Synchronization::ProjectDatas fetchProjectDatas(SourceId projectSourceId) const override; - return fileStatus; - } + Storage::Synchronization::ProjectDatas fetchProjectDatas(const SourceIds &projectSourceIds) const; - std::optional fetchProjectData(SourceId sourceId) const override - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"fetch project data"_t, - projectStorageCategory(), - keyValue("source id", sourceId)}; + void setPropertyEditorPathId(TypeId typeId, SourceId pathId); - auto projectData = selectProjectDataForSourceIdStatement.template optionalValueWithTransaction< - Storage::Synchronization::ProjectData>(sourceId); + SourceId propertyEditorPathId(TypeId typeId) const override; - tracer.end(keyValue("project data", projectData)); + Storage::Imports fetchDocumentImports() const; - return projectData; - } - - Storage::Synchronization::ProjectDatas fetchProjectDatas(SourceId projectSourceId) const override - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"fetch project datas by source id"_t, - projectStorageCategory(), - keyValue("source id", projectSourceId)}; - - auto projectDatas = selectProjectDatasForSourceIdStatement - .template valuesWithTransaction( - projectSourceId); - - tracer.end(keyValue("project datas", projectDatas)); - - return projectDatas; - } - - Storage::Synchronization::ProjectDatas fetchProjectDatas(const SourceIds &projectSourceIds) const - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"fetch project datas by source ids"_t, - projectStorageCategory(), - keyValue("source ids", projectSourceIds)}; - - auto projectDatas = selectProjectDatasForSourceIdsStatement - .template valuesWithTransaction( - toIntegers(projectSourceIds)); - - tracer.end(keyValue("project datas", projectDatas)); - - return projectDatas; - } - - void setPropertyEditorPathId(TypeId typeId, SourceId pathId) - { - Sqlite::ImmediateSessionTransaction transaction{database}; - - upsertPropertyEditorPathIdStatement.write(typeId, pathId); - - transaction.commit(); - } - - SourceId propertyEditorPathId(TypeId typeId) const override - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"property editor path id"_t, - projectStorageCategory(), - keyValue("type id", typeId)}; - - auto sourceId = selectPropertyEditorPathIdStatement.template valueWithTransaction( - typeId); - - tracer.end(keyValue("source id", sourceId)); - - return sourceId; - } - - Storage::Imports fetchDocumentImports() const - { - NanotraceHR::Tracer tracer{"fetch document imports"_t, projectStorageCategory()}; - - return selectAllDocumentImportForSourceIdStatement - .template valuesWithTransaction(); - } - - void resetForTestsOnly() - { - database.clearAllTablesForTestsOnly(); - commonTypeCache_.clearForTestsOnly(); - moduleCache.clearForTestOnly(); - } + void resetForTestsOnly(); private: class ModuleStorageAdapter @@ -1233,12 +305,11 @@ private: } }; + using Modules = std::vector; + friend ModuleStorageAdapter; - static bool moduleNameLess(Utils::SmallStringView first, Utils::SmallStringView second) noexcept - { - return first < second; - } + static bool moduleNameLess(Utils::SmallStringView first, Utils::SmallStringView second) noexcept; using ModuleCache = StorageCache; - ModuleId fetchModuleId(Utils::SmallStringView moduleName) - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"fetch module id"_t, - projectStorageCategory(), - keyValue("module name", moduleName)}; + ModuleId fetchModuleId(Utils::SmallStringView moduleName); - auto moduleId = Sqlite::withDeferredTransaction(database, [&] { - return fetchModuleIdUnguarded(moduleName); - }); + Utils::PathString fetchModuleName(ModuleId id); - tracer.end(keyValue("module id", moduleId)); + Modules fetchAllModules() const; - return moduleId; - } - - auto fetchModuleName(ModuleId id) - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"fetch module name"_t, - projectStorageCategory(), - keyValue("module id", id)}; - - auto moduleName = Sqlite::withDeferredTransaction(database, [&] { - return fetchModuleNameUnguarded(id); - }); - - tracer.end(keyValue("module name", moduleName)); - - return moduleName; - } - - auto fetchAllModules() const - { - NanotraceHR::Tracer tracer{"fetch all modules"_t, projectStorageCategory()}; - - return selectAllModulesStatement.template valuesWithTransaction(); - } - - void callRefreshMetaInfoCallback(const TypeIds &deletedTypeIds) - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"call refresh meta info callback"_t, - projectStorageCategory(), - keyValue("type ids", deletedTypeIds)}; - - if (deletedTypeIds.size()) { - for (ProjectStorageObserver *observer : observers) - observer->removedTypeIds(deletedTypeIds); - } - } + void callRefreshMetaInfoCallback(const TypeIds &deletedTypeIds); class AliasPropertyDeclaration { @@ -1457,48 +484,14 @@ private: } }; - SourceIds filterSourceIdsWithoutType(const SourceIds &updatedSourceIds, SourceIds &sourceIdsOfTypes) - { - std::sort(sourceIdsOfTypes.begin(), sourceIdsOfTypes.end()); + SourceIds filterSourceIdsWithoutType(const SourceIds &updatedSourceIds, + SourceIds &sourceIdsOfTypes); - SourceIds sourceIdsWithoutTypeSourceIds; - sourceIdsWithoutTypeSourceIds.reserve(updatedSourceIds.size()); - std::set_difference(updatedSourceIds.begin(), - updatedSourceIds.end(), - sourceIdsOfTypes.begin(), - sourceIdsOfTypes.end(), - std::back_inserter(sourceIdsWithoutTypeSourceIds)); + TypeIds fetchTypeIds(const SourceIds &sourceIds); - return sourceIdsWithoutTypeSourceIds; - } + void unique(SourceIds &sourceIds); - TypeIds fetchTypeIds(const SourceIds &sourceIds) - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"fetch type ids"_t, - projectStorageCategory(), - keyValue("source ids", sourceIds)}; - - return selectTypeIdsForSourceIdsStatement.template values(toIntegers(sourceIds)); - } - - void unique(SourceIds &sourceIds) - { - std::sort(sourceIds.begin(), sourceIds.end()); - auto newEnd = std::unique(sourceIds.begin(), sourceIds.end()); - sourceIds.erase(newEnd, sourceIds.end()); - } - - void synchronizeTypeTraits(TypeId typeId, Storage::TypeTraits traits) - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"synchronize type traits"_t, - projectStorageCategory(), - keyValue("type id", typeId), - keyValue("type traits", traits)}; - - updateTypeAnnotationTraitStatement.write(typeId, traits.annotation); - } + void synchronizeTypeTraits(TypeId typeId, Storage::TypeTraits traits); class TypeAnnotationView { @@ -1533,28 +526,7 @@ private: Utils::PathString hintsJson; }; - void updateTypeIdInTypeAnnotations(Storage::Synchronization::TypeAnnotations &typeAnnotations) - { - NanotraceHR::Tracer tracer{"update type id in type annotations"_t, projectStorageCategory()}; - - for (auto &annotation : typeAnnotations) { - annotation.typeId = fetchTypeIdByModuleIdAndExportedName(annotation.moduleId, - annotation.typeName); - } - - for (auto &annotation : typeAnnotations) { - if (!annotation.typeId) - qWarning() << moduleName(annotation.moduleId).toQString() - << annotation.typeName.toQString(); - } - - typeAnnotations.erase(std::remove_if(typeAnnotations.begin(), - typeAnnotations.end(), - [](const auto &annotation) { - return !annotation.typeId; - }), - typeAnnotations.end()); - } + void updateTypeIdInTypeAnnotations(Storage::Synchronization::TypeAnnotations &typeAnnotations); template static Sqlite::ValueView createEmptyAsNull(const Value &value) @@ -1566,84 +538,9 @@ private: } void synchronizeTypeAnnotations(Storage::Synchronization::TypeAnnotations &typeAnnotations, - const SourceIds &updatedTypeAnnotationSourceIds) - { - NanotraceHR::Tracer tracer{"synchronize type annotations"_t, projectStorageCategory()}; + const SourceIds &updatedTypeAnnotationSourceIds); - using Storage::Synchronization::TypeAnnotation; - - updateTypeIdInTypeAnnotations(typeAnnotations); - - auto compareKey = [](auto &&first, auto &&second) { return first.typeId - second.typeId; }; - - std::sort(typeAnnotations.begin(), typeAnnotations.end(), [&](auto &&first, auto &&second) { - return first.typeId < second.typeId; - }); - - auto range = selectTypeAnnotationsForSourceIdsStatement.template range( - toIntegers(updatedTypeAnnotationSourceIds)); - - auto insert = [&](const TypeAnnotation &annotation) { - if (!annotation.sourceId) - throw TypeAnnotationHasInvalidSourceId{}; - - synchronizeTypeTraits(annotation.typeId, annotation.traits); - - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"insert type annotations"_t, - projectStorageCategory(), - keyValue("type annotation", annotation)}; - - insertTypeAnnotationStatement.write(annotation.typeId, - annotation.sourceId, - annotation.directorySourceId, - annotation.iconPath, - createEmptyAsNull(annotation.itemLibraryJson), - createEmptyAsNull(annotation.hintsJson)); - }; - - auto update = [&](const TypeAnnotationView &annotationFromDatabase, - const TypeAnnotation &annotation) { - synchronizeTypeTraits(annotation.typeId, annotation.traits); - - if (annotationFromDatabase.iconPath != annotation.iconPath - || annotationFromDatabase.itemLibraryJson != annotation.itemLibraryJson - || annotationFromDatabase.hintsJson != annotation.hintsJson) { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"update type annotations"_t, - projectStorageCategory(), - keyValue("type annotation from database", - annotationFromDatabase), - keyValue("type annotation", annotation)}; - - updateTypeAnnotationStatement.write(annotation.typeId, - annotation.iconPath, - createEmptyAsNull(annotation.itemLibraryJson), - createEmptyAsNull(annotation.hintsJson)); - return Sqlite::UpdateChange::Update; - } - - return Sqlite::UpdateChange::No; - }; - - auto remove = [&](const TypeAnnotationView &annotationFromDatabase) { - synchronizeTypeTraits(annotationFromDatabase.typeId, Storage::TypeTraits{}); - - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"remove type annotations"_t, - projectStorageCategory(), - keyValue("type annotation", annotationFromDatabase)}; - - deleteTypeAnnotationStatement.write(annotationFromDatabase.typeId); - }; - - Sqlite::insertUpdateDelete(range, typeAnnotations, compareKey, insert, update, remove); - } - - void synchronizeTypeTrait(const Storage::Synchronization::Type &type) - { - updateTypeTraitStatement.write(type.typeId, type.traits.type); - } + void synchronizeTypeTrait(const Storage::Synchronization::Type &type); void synchronizeTypes(Storage::Synchronization::Types &types, TypeIds &updatedTypeIds, @@ -1653,486 +550,49 @@ private: PropertyDeclarations &relinkablePropertyDeclarations, Prototypes &relinkablePrototypes, Prototypes &relinkableExtensions, - const SourceIds &updatedSourceIds) - { - NanotraceHR::Tracer tracer{"synchronize types"_t, projectStorageCategory()}; - - Storage::Synchronization::ExportedTypes exportedTypes; - exportedTypes.reserve(types.size() * 3); - SourceIds sourceIdsOfTypes; - sourceIdsOfTypes.reserve(updatedSourceIds.size()); - SourceIds notUpdatedExportedSourceIds; - notUpdatedExportedSourceIds.reserve(updatedSourceIds.size()); - SourceIds exportedSourceIds; - exportedSourceIds.reserve(types.size()); - - for (auto &type : types) { - if (!type.sourceId) - throw TypeHasInvalidSourceId{}; - - TypeId typeId = declareType(type); - synchronizeTypeTrait(type); - sourceIdsOfTypes.push_back(type.sourceId); - updatedTypeIds.push_back(typeId); - if (type.changeLevel != Storage::Synchronization::ChangeLevel::ExcludeExportedTypes) { - exportedSourceIds.push_back(type.sourceId); - extractExportedTypes(typeId, type, exportedTypes); - } - } - - std::sort(types.begin(), types.end(), [](const auto &first, const auto &second) { - return first.typeId < second.typeId; - }); - - unique(exportedSourceIds); - - SourceIds sourceIdsWithoutType = filterSourceIdsWithoutType(updatedSourceIds, - sourceIdsOfTypes); - exportedSourceIds.insert(exportedSourceIds.end(), - sourceIdsWithoutType.begin(), - sourceIdsWithoutType.end()); - TypeIds exportedTypeIds = fetchTypeIds(exportedSourceIds); - synchronizeExportedTypes(exportedTypeIds, - exportedTypes, - relinkableAliasPropertyDeclarations, - relinkablePropertyDeclarations, - relinkablePrototypes, - relinkableExtensions); - - syncPrototypesAndExtensions(types, relinkablePrototypes, relinkableExtensions); - resetDefaultPropertiesIfChanged(types); - resetRemovedAliasPropertyDeclarationsToNull(types, relinkableAliasPropertyDeclarations); - syncDeclarations(types, - insertedAliasPropertyDeclarations, - updatedAliasPropertyDeclarations, - relinkablePropertyDeclarations); - syncDefaultProperties(types); - } + const SourceIds &updatedSourceIds); void synchronizeProjectDatas(Storage::Synchronization::ProjectDatas &projectDatas, - const SourceIds &updatedProjectSourceIds) - { - NanotraceHR::Tracer tracer{"synchronize project datas"_t, projectStorageCategory()}; + const SourceIds &updatedProjectSourceIds); - auto compareKey = [](auto &&first, auto &&second) { - auto projectSourceIdDifference = first.projectSourceId - second.projectSourceId; - if (projectSourceIdDifference != 0) - return projectSourceIdDifference; - - return first.sourceId - second.sourceId; - }; - - std::sort(projectDatas.begin(), projectDatas.end(), [&](auto &&first, auto &&second) { - return std::tie(first.projectSourceId, first.sourceId) - < std::tie(second.projectSourceId, second.sourceId); - }); - - auto range = selectProjectDatasForSourceIdsStatement - .template range( - toIntegers(updatedProjectSourceIds)); - - auto insert = [&](const Storage::Synchronization::ProjectData &projectData) { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"insert project data"_t, - projectStorageCategory(), - keyValue("project data", projectData)}; - - if (!projectData.projectSourceId) - throw ProjectDataHasInvalidProjectSourceId{}; - if (!projectData.sourceId) - throw ProjectDataHasInvalidSourceId{}; - - insertProjectDataStatement.write(projectData.projectSourceId, - projectData.sourceId, - projectData.moduleId, - projectData.fileType); - }; - - auto update = [&](const Storage::Synchronization::ProjectData &projectDataFromDatabase, - const Storage::Synchronization::ProjectData &projectData) { - if (projectDataFromDatabase.fileType != projectData.fileType - || !compareInvalidAreTrue(projectDataFromDatabase.moduleId, projectData.moduleId)) { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"update project data"_t, - projectStorageCategory(), - keyValue("project data", projectData), - keyValue("project data from database", - projectDataFromDatabase)}; - - updateProjectDataStatement.write(projectData.projectSourceId, - projectData.sourceId, - projectData.moduleId, - projectData.fileType); - return Sqlite::UpdateChange::Update; - } - - return Sqlite::UpdateChange::No; - }; - - auto remove = [&](const Storage::Synchronization::ProjectData &projectData) { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"remove project data"_t, - projectStorageCategory(), - keyValue("project data", projectData)}; - - deleteProjectDataStatement.write(projectData.projectSourceId, projectData.sourceId); - }; - - Sqlite::insertUpdateDelete(range, projectDatas, compareKey, insert, update, remove); - } - - void synchronizeFileStatuses(FileStatuses &fileStatuses, const SourceIds &updatedSourceIds) - { - NanotraceHR::Tracer tracer{"synchronize file statuses"_t, projectStorageCategory()}; - - auto compareKey = [](auto &&first, auto &&second) { - return first.sourceId - second.sourceId; - }; - - std::sort(fileStatuses.begin(), fileStatuses.end(), [&](auto &&first, auto &&second) { - return first.sourceId < second.sourceId; - }); - - auto range = selectFileStatusesForSourceIdsStatement.template range( - toIntegers(updatedSourceIds)); - - auto insert = [&](const FileStatus &fileStatus) { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"insert file status"_t, - projectStorageCategory(), - keyValue("file status", fileStatus)}; - - if (!fileStatus.sourceId) - throw FileStatusHasInvalidSourceId{}; - insertFileStatusStatement.write(fileStatus.sourceId, - fileStatus.size, - fileStatus.lastModified); - }; - - auto update = [&](const FileStatus &fileStatusFromDatabase, const FileStatus &fileStatus) { - if (fileStatusFromDatabase.lastModified != fileStatus.lastModified - || fileStatusFromDatabase.size != fileStatus.size) { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"update file status"_t, - projectStorageCategory(), - keyValue("file status", fileStatus), - keyValue("file status from database", - fileStatusFromDatabase)}; - - updateFileStatusStatement.write(fileStatus.sourceId, - fileStatus.size, - fileStatus.lastModified); - return Sqlite::UpdateChange::Update; - } - - return Sqlite::UpdateChange::No; - }; - - auto remove = [&](const FileStatus &fileStatus) { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"remove file status"_t, - projectStorageCategory(), - keyValue("file status", fileStatus)}; - - deleteFileStatusStatement.write(fileStatus.sourceId); - }; - - Sqlite::insertUpdateDelete(range, fileStatuses, compareKey, insert, update, remove); - } + void synchronizeFileStatuses(FileStatuses &fileStatuses, const SourceIds &updatedSourceIds); void synchronizeImports(Storage::Imports &imports, const SourceIds &updatedSourceIds, Storage::Imports &moduleDependencies, const SourceIds &updatedModuleDependencySourceIds, Storage::Synchronization::ModuleExportedImports &moduleExportedImports, - const ModuleIds &updatedModuleIds) - { - NanotraceHR::Tracer tracer{"synchronize imports"_t, projectStorageCategory()}; - - synchromizeModuleExportedImports(moduleExportedImports, updatedModuleIds); - NanotraceHR::Tracer importTracer{"synchronize qml document imports"_t, - projectStorageCategory()}; - synchronizeDocumentImports(imports, - updatedSourceIds, - Storage::Synchronization::ImportKind::Import); - importTracer.end(); - NanotraceHR::Tracer moduleDependenciesTracer{"synchronize module depdencies"_t, - projectStorageCategory()}; - synchronizeDocumentImports(moduleDependencies, - updatedModuleDependencySourceIds, - Storage::Synchronization::ImportKind::ModuleDependency); - moduleDependenciesTracer.end(); - } + const ModuleIds &updatedModuleIds); void synchromizeModuleExportedImports( Storage::Synchronization::ModuleExportedImports &moduleExportedImports, - const ModuleIds &updatedModuleIds) - { - NanotraceHR::Tracer tracer{"synchronize module exported imports"_t, projectStorageCategory()}; - std::sort(moduleExportedImports.begin(), - moduleExportedImports.end(), - [](auto &&first, auto &&second) { - return std::tie(first.moduleId, first.exportedModuleId) - < std::tie(second.moduleId, second.exportedModuleId); - }); + const ModuleIds &updatedModuleIds); - auto range = selectModuleExportedImportsForSourceIdStatement - .template range( - toIntegers(updatedModuleIds)); + ModuleId fetchModuleIdUnguarded(Utils::SmallStringView name) const override; - auto compareKey = [](const Storage::Synchronization::ModuleExportedImportView &view, - const Storage::Synchronization::ModuleExportedImport &import) -> long long { - auto moduleIdDifference = view.moduleId - import.moduleId; - if (moduleIdDifference != 0) - return moduleIdDifference; - - return view.exportedModuleId - import.exportedModuleId; - }; - - auto insert = [&](const Storage::Synchronization::ModuleExportedImport &import) { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"insert module exported import"_t, - projectStorageCategory(), - keyValue("module exported import", import), - keyValue("module id", import.moduleId)}; - tracer.tick("exported module"_t, keyValue("module id", import.exportedModuleId)); - - if (import.version.minor) { - insertModuleExportedImportWithVersionStatement.write(import.moduleId, - import.exportedModuleId, - import.isAutoVersion, - import.version.major.value, - import.version.minor.value); - } else if (import.version.major) { - insertModuleExportedImportWithMajorVersionStatement.write(import.moduleId, - import.exportedModuleId, - import.isAutoVersion, - import.version.major.value); - } else { - insertModuleExportedImportWithoutVersionStatement.write(import.moduleId, - import.exportedModuleId, - import.isAutoVersion); - } - }; - - auto update = [](const Storage::Synchronization::ModuleExportedImportView &, - const Storage::Synchronization::ModuleExportedImport &) { - return Sqlite::UpdateChange::No; - }; - - auto remove = [&](const Storage::Synchronization::ModuleExportedImportView &view) { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"remove module exported import"_t, - projectStorageCategory(), - keyValue("module exported import view", view), - keyValue("module id", view.moduleId)}; - tracer.tick("exported module"_t, keyValue("module id", view.exportedModuleId)); - - deleteModuleExportedImportStatement.write(view.moduleExportedImportId); - }; - - Sqlite::insertUpdateDelete(range, moduleExportedImports, compareKey, insert, update, remove); - } - - ModuleId fetchModuleIdUnguarded(Utils::SmallStringView name) const override - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"fetch module id ungarded"_t, - projectStorageCategory(), - keyValue("module name", name)}; - - auto moduleId = selectModuleIdByNameStatement.template value(name); - - if (!moduleId) - moduleId = insertModuleNameStatement.template value(name); - - tracer.end(keyValue("module id", moduleId)); - - return moduleId; - } - - auto fetchModuleNameUnguarded(ModuleId id) const - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"fetch module name ungarded"_t, - projectStorageCategory(), - keyValue("module id", id)}; - - auto moduleName = selectModuleNameStatement.template value(id); - - if (moduleName.empty()) - throw ModuleDoesNotExists{}; - - tracer.end(keyValue("module name", moduleName)); - - return moduleName; - } + Utils::PathString fetchModuleNameUnguarded(ModuleId id) const; void handleAliasPropertyDeclarationsWithPropertyType( - TypeId typeId, AliasPropertyDeclarations &relinkableAliasPropertyDeclarations) - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"handle alias property declarations with property type"_t, - projectStorageCategory(), - keyValue("type id", typeId), - keyValue("relinkable alias property declarations", - relinkableAliasPropertyDeclarations)}; - - auto callback = [&](TypeId typeId_, - PropertyDeclarationId propertyDeclarationId, - ImportedTypeNameId propertyImportedTypeNameId, - PropertyDeclarationId aliasPropertyDeclarationId, - PropertyDeclarationId aliasPropertyDeclarationTailId) { - auto aliasPropertyName = selectPropertyNameStatement.template value( - aliasPropertyDeclarationId); - Utils::SmallString aliasPropertyNameTail; - if (aliasPropertyDeclarationTailId) - aliasPropertyNameTail = selectPropertyNameStatement.template value( - aliasPropertyDeclarationTailId); - - relinkableAliasPropertyDeclarations - .emplace_back(TypeId{typeId_}, - PropertyDeclarationId{propertyDeclarationId}, - ImportedTypeNameId{propertyImportedTypeNameId}, - std::move(aliasPropertyName), - std::move(aliasPropertyNameTail)); - - updateAliasPropertyDeclarationToNullStatement.write(propertyDeclarationId); - }; - - selectAliasPropertiesDeclarationForPropertiesWithTypeIdStatement.readCallback(callback, - typeId); - } + TypeId typeId, AliasPropertyDeclarations &relinkableAliasPropertyDeclarations); void handlePropertyDeclarationWithPropertyType(TypeId typeId, - PropertyDeclarations &relinkablePropertyDeclarations) - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"handle property declarations with property type"_t, - projectStorageCategory(), - keyValue("type id", typeId), - keyValue("relinkable property declarations", - relinkablePropertyDeclarations)}; + PropertyDeclarations &relinkablePropertyDeclarations); - updatesPropertyDeclarationPropertyTypeToNullStatement.readTo(relinkablePropertyDeclarations, - typeId); - } + void handlePrototypes(TypeId prototypeId, Prototypes &relinkablePrototypes); - void handlePrototypes(TypeId prototypeId, Prototypes &relinkablePrototypes) - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"handle prototypes"_t, - projectStorageCategory(), - keyValue("type id", prototypeId), - keyValue("relinkable prototypes", relinkablePrototypes)}; - - auto callback = [&](TypeId typeId, ImportedTypeNameId prototypeNameId) { - relinkablePrototypes.emplace_back(typeId, prototypeNameId); - }; - - updatePrototypeIdToNullStatement.readCallback(callback, prototypeId); - } - - void handleExtensions(TypeId extensionId, Prototypes &relinkableExtensions) - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"handle extension"_t, - projectStorageCategory(), - keyValue("type id", extensionId), - keyValue("relinkable extensions", relinkableExtensions)}; - - auto callback = [&](TypeId typeId, ImportedTypeNameId extensionNameId) { - relinkableExtensions.emplace_back(typeId, extensionNameId); - }; - - updateExtensionIdToNullStatement.readCallback(callback, extensionId); - } + void handleExtensions(TypeId extensionId, Prototypes &relinkableExtensions); void deleteType(TypeId typeId, AliasPropertyDeclarations &relinkableAliasPropertyDeclarations, PropertyDeclarations &relinkablePropertyDeclarations, Prototypes &relinkablePrototypes, - Prototypes &relinkableExtensions) - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"delete type"_t, - projectStorageCategory(), - keyValue("type id", typeId)}; - - handlePropertyDeclarationWithPropertyType(typeId, relinkablePropertyDeclarations); - handleAliasPropertyDeclarationsWithPropertyType(typeId, relinkableAliasPropertyDeclarations); - handlePrototypes(typeId, relinkablePrototypes); - handleExtensions(typeId, relinkableExtensions); - deleteTypeNamesByTypeIdStatement.write(typeId); - deleteEnumerationDeclarationByTypeIdStatement.write(typeId); - deletePropertyDeclarationByTypeIdStatement.write(typeId); - deleteFunctionDeclarationByTypeIdStatement.write(typeId); - deleteSignalDeclarationByTypeIdStatement.write(typeId); - deleteTypeStatement.write(typeId); - } + Prototypes &relinkableExtensions); void relinkAliasPropertyDeclarations(AliasPropertyDeclarations &aliasPropertyDeclarations, - const TypeIds &deletedTypeIds) - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"relink alias properties"_t, - projectStorageCategory(), - keyValue("alias property declarations", aliasPropertyDeclarations), - keyValue("deleted type ids", deletedTypeIds)}; - - std::sort(aliasPropertyDeclarations.begin(), aliasPropertyDeclarations.end()); - - Utils::set_greedy_difference( - aliasPropertyDeclarations.cbegin(), - aliasPropertyDeclarations.cend(), - deletedTypeIds.begin(), - deletedTypeIds.end(), - [&](const AliasPropertyDeclaration &alias) { - auto typeId = fetchTypeId(alias.aliasImportedTypeNameId); - - if (!typeId) - throw TypeNameDoesNotExists{fetchImportedTypeName(alias.aliasImportedTypeNameId)}; - - auto [propertyTypeId, aliasId, propertyTraits] = fetchPropertyDeclarationByTypeIdAndNameUngarded( - typeId, alias.aliasPropertyName); - - updatePropertyDeclarationWithAliasAndTypeStatement.write(alias.propertyDeclarationId, - propertyTypeId, - propertyTraits, - alias.aliasImportedTypeNameId, - aliasId); - }, - TypeCompare{}); - } + const TypeIds &deletedTypeIds); void relinkPropertyDeclarations(PropertyDeclarations &relinkablePropertyDeclaration, - const TypeIds &deletedTypeIds) - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"relink property declarations"_t, - projectStorageCategory(), - keyValue("relinkable property declarations", - relinkablePropertyDeclaration), - keyValue("deleted type ids", deletedTypeIds)}; - - std::sort(relinkablePropertyDeclaration.begin(), relinkablePropertyDeclaration.end()); - - Utils::set_greedy_difference( - relinkablePropertyDeclaration.cbegin(), - relinkablePropertyDeclaration.cend(), - deletedTypeIds.begin(), - deletedTypeIds.end(), - [&](const PropertyDeclaration &property) { - TypeId propertyTypeId = fetchTypeId(property.importedTypeNameId); - - if (!propertyTypeId) - throw TypeNameDoesNotExists{fetchImportedTypeName(property.importedTypeNameId)}; - - updatePropertyDeclarationTypeStatement.write(property.propertyDeclarationId, - propertyTypeId); - }, - TypeCompare{}); - } + const TypeIds &deletedTypeIds); template void relinkPrototypes(Prototypes &relinkablePrototypes, @@ -2171,435 +631,66 @@ private: PropertyDeclarations &relinkablePropertyDeclarations, Prototypes &relinkablePrototypes, Prototypes &relinkableExtensions, - TypeIds &deletedTypeIds) - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"delete not updated types"_t, - projectStorageCategory(), - keyValue("updated type ids", updatedTypeIds), - keyValue("updated source ids", updatedSourceIds), - keyValue("type ids to be deleted", typeIdsToBeDeleted)}; - - auto callback = [&](TypeId typeId) { - deletedTypeIds.push_back(typeId); - deleteType(typeId, - relinkableAliasPropertyDeclarations, - relinkablePropertyDeclarations, - relinkablePrototypes, - relinkableExtensions); - }; - - selectNotUpdatedTypesInSourcesStatement.readCallback(callback, - toIntegers(updatedSourceIds), - toIntegers(updatedTypeIds)); - for (TypeId typeIdToBeDeleted : typeIdsToBeDeleted) - callback(typeIdToBeDeleted); - } + TypeIds &deletedTypeIds); void relink(AliasPropertyDeclarations &relinkableAliasPropertyDeclarations, PropertyDeclarations &relinkablePropertyDeclarations, Prototypes &relinkablePrototypes, Prototypes &relinkableExtensions, - TypeIds &deletedTypeIds) - { - NanotraceHR::Tracer tracer{"relink"_t, projectStorageCategory()}; - - std::sort(deletedTypeIds.begin(), deletedTypeIds.end()); - - relinkPrototypes(relinkablePrototypes, deletedTypeIds, [&](TypeId typeId, TypeId prototypeId) { - updateTypePrototypeStatement.write(typeId, prototypeId); - }); - relinkPrototypes(relinkableExtensions, deletedTypeIds, [&](TypeId typeId, TypeId prototypeId) { - updateTypeExtensionStatement.write(typeId, prototypeId); - }); - relinkPropertyDeclarations(relinkablePropertyDeclarations, deletedTypeIds); - relinkAliasPropertyDeclarations(relinkableAliasPropertyDeclarations, deletedTypeIds); - } + TypeIds &deletedTypeIds); PropertyDeclarationId fetchAliasId(TypeId aliasTypeId, Utils::SmallStringView aliasPropertyName, - Utils::SmallStringView aliasPropertyNameTail) - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"fetch alias id"_t, - projectStorageCategory(), - keyValue("alias type id", aliasTypeId), - keyValue("alias property name", aliasPropertyName), - keyValue("alias property name tail", aliasPropertyNameTail)}; + Utils::SmallStringView aliasPropertyNameTail); - if (aliasPropertyNameTail.empty()) - return fetchPropertyDeclarationIdByTypeIdAndNameUngarded(aliasTypeId, aliasPropertyName); + void linkAliasPropertyDeclarationAliasIds(const AliasPropertyDeclarations &aliasDeclarations); - auto stemAlias = fetchPropertyDeclarationByTypeIdAndNameUngarded(aliasTypeId, - aliasPropertyName); + void updateAliasPropertyDeclarationValues(const AliasPropertyDeclarations &aliasDeclarations); - return fetchPropertyDeclarationIdByTypeIdAndNameUngarded(stemAlias.propertyTypeId, - aliasPropertyNameTail); - } - - void linkAliasPropertyDeclarationAliasIds(const AliasPropertyDeclarations &aliasDeclarations) - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"link alias property declarations alias ids"_t, - projectStorageCategory(), - keyValue("alias property declarations", aliasDeclarations)}; - - for (const auto &aliasDeclaration : aliasDeclarations) { - auto aliasTypeId = fetchTypeId(aliasDeclaration.aliasImportedTypeNameId); - - if (!aliasTypeId) { - throw TypeNameDoesNotExists{ - fetchImportedTypeName(aliasDeclaration.aliasImportedTypeNameId)}; - } - - auto aliasId = fetchAliasId(aliasTypeId, - aliasDeclaration.aliasPropertyName, - aliasDeclaration.aliasPropertyNameTail); - - updatePropertyDeclarationAliasIdAndTypeNameIdStatement - .write(aliasDeclaration.propertyDeclarationId, - aliasId, - aliasDeclaration.aliasImportedTypeNameId); - } - } - - void updateAliasPropertyDeclarationValues(const AliasPropertyDeclarations &aliasDeclarations) - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"update alias property declarations"_t, - projectStorageCategory(), - keyValue("alias property declarations", aliasDeclarations)}; - - for (const auto &aliasDeclaration : aliasDeclarations) { - updatetPropertiesDeclarationValuesOfAliasStatement.write( - aliasDeclaration.propertyDeclarationId); - updatePropertyAliasDeclarationRecursivelyStatement.write( - aliasDeclaration.propertyDeclarationId); - } - } - - void checkAliasPropertyDeclarationCycles(const AliasPropertyDeclarations &aliasDeclarations) - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"check alias property declarations cycles"_t, - projectStorageCategory(), - keyValue("alias property declarations", aliasDeclarations)}; - for (const auto &aliasDeclaration : aliasDeclarations) - checkForAliasChainCycle(aliasDeclaration.propertyDeclarationId); - } + void checkAliasPropertyDeclarationCycles(const AliasPropertyDeclarations &aliasDeclarations); void linkAliases(const AliasPropertyDeclarations &insertedAliasPropertyDeclarations, - const AliasPropertyDeclarations &updatedAliasPropertyDeclarations) - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"link aliases"_t, projectStorageCategory()}; - - linkAliasPropertyDeclarationAliasIds(insertedAliasPropertyDeclarations); - linkAliasPropertyDeclarationAliasIds(updatedAliasPropertyDeclarations); - - checkAliasPropertyDeclarationCycles(insertedAliasPropertyDeclarations); - checkAliasPropertyDeclarationCycles(updatedAliasPropertyDeclarations); - - updateAliasPropertyDeclarationValues(insertedAliasPropertyDeclarations); - updateAliasPropertyDeclarationValues(updatedAliasPropertyDeclarations); - } + const AliasPropertyDeclarations &updatedAliasPropertyDeclarations); void synchronizeExportedTypes(const TypeIds &updatedTypeIds, Storage::Synchronization::ExportedTypes &exportedTypes, AliasPropertyDeclarations &relinkableAliasPropertyDeclarations, PropertyDeclarations &relinkablePropertyDeclarations, Prototypes &relinkablePrototypes, - Prototypes &relinkableExtensions) - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"synchronize exported types"_t, projectStorageCategory()}; - - std::sort(exportedTypes.begin(), exportedTypes.end(), [](auto &&first, auto &&second) { - if (first.moduleId < second.moduleId) - return true; - else if (first.moduleId > second.moduleId) - return false; - - auto nameCompare = Sqlite::compare(first.name, second.name); - - if (nameCompare < 0) - return true; - else if (nameCompare > 0) - return false; - - return first.version < second.version; - }); - - auto range = selectExportedTypesForSourceIdsStatement - .template range( - toIntegers(updatedTypeIds)); - - auto compareKey = [](const Storage::Synchronization::ExportedTypeView &view, - const Storage::Synchronization::ExportedType &type) -> long long { - auto moduleIdDifference = view.moduleId - type.moduleId; - if (moduleIdDifference != 0) - return moduleIdDifference; - - auto nameDifference = Sqlite::compare(view.name, type.name); - if (nameDifference != 0) - return nameDifference; - - auto versionDifference = view.version.major.value - type.version.major.value; - if (versionDifference != 0) - return versionDifference; - - return view.version.minor.value - type.version.minor.value; - }; - - auto insert = [&](const Storage::Synchronization::ExportedType &type) { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"insert exported type"_t, - projectStorageCategory(), - keyValue("exported type", type), - keyValue("type id", type.typeId), - keyValue("module id", type.moduleId)}; - if (!type.moduleId) - throw QmlDesigner::ModuleDoesNotExists{}; - - try { - if (type.version) { - insertExportedTypeNamesWithVersionStatement.write(type.moduleId, - type.name, - type.version.major.value, - type.version.minor.value, - type.typeId); - - } else if (type.version.major) { - insertExportedTypeNamesWithMajorVersionStatement.write(type.moduleId, - type.name, - type.version.major.value, - type.typeId); - } else { - insertExportedTypeNamesWithoutVersionStatement.write(type.moduleId, - type.name, - type.typeId); - } - } catch (const Sqlite::ConstraintPreventsModification &) { - throw QmlDesigner::ExportedTypeCannotBeInserted{type.name}; - } - }; - - auto update = [&](const Storage::Synchronization::ExportedTypeView &view, - const Storage::Synchronization::ExportedType &type) { - if (view.typeId != type.typeId) { - NanotraceHR::Tracer tracer{"update exported type"_t, - projectStorageCategory(), - keyValue("exported type", type), - keyValue("exported type view", view), - keyValue("type id", type.typeId), - keyValue("module id", type.typeId)}; - - handlePropertyDeclarationWithPropertyType(view.typeId, relinkablePropertyDeclarations); - handleAliasPropertyDeclarationsWithPropertyType(view.typeId, - relinkableAliasPropertyDeclarations); - handlePrototypes(view.typeId, relinkablePrototypes); - handleExtensions(view.typeId, relinkableExtensions); - updateExportedTypeNameTypeIdStatement.write(view.exportedTypeNameId, type.typeId); - return Sqlite::UpdateChange::Update; - } - return Sqlite::UpdateChange::No; - }; - - auto remove = [&](const Storage::Synchronization::ExportedTypeView &view) { - NanotraceHR::Tracer tracer{"remove exported type"_t, - projectStorageCategory(), - keyValue("exported type", view), - keyValue("type id", view.typeId), - keyValue("module id", view.moduleId)}; - - handlePropertyDeclarationWithPropertyType(view.typeId, relinkablePropertyDeclarations); - handleAliasPropertyDeclarationsWithPropertyType(view.typeId, - relinkableAliasPropertyDeclarations); - handlePrototypes(view.typeId, relinkablePrototypes); - handleExtensions(view.typeId, relinkableExtensions); - deleteExportedTypeNameStatement.write(view.exportedTypeNameId); - }; - - Sqlite::insertUpdateDelete(range, exportedTypes, compareKey, insert, update, remove); - } + Prototypes &relinkableExtensions); void synchronizePropertyDeclarationsInsertAlias( AliasPropertyDeclarations &insertedAliasPropertyDeclarations, const Storage::Synchronization::PropertyDeclaration &value, SourceId sourceId, - TypeId typeId) - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"insert property declaration to alias"_t, - projectStorageCategory(), - keyValue("property declaration", value)}; + TypeId typeId); - auto callback = [&](PropertyDeclarationId propertyDeclarationId) { - insertedAliasPropertyDeclarations.emplace_back(typeId, - propertyDeclarationId, - fetchImportedTypeNameId(value.typeName, - sourceId), - value.aliasPropertyName, - value.aliasPropertyNameTail); - return Sqlite::CallbackControl::Abort; - }; - - insertAliasPropertyDeclarationStatement.readCallback(callback, typeId, value.name); - } - - auto fetchPropertyDeclarationIds(TypeId baseTypeId) const - { - QVarLengthArray propertyDeclarationIds; - - selectLocalPropertyDeclarationIdsForTypeStatement.readTo(propertyDeclarationIds, baseTypeId); - - auto range = selectPrototypeAndExtensionIdsStatement.template range(baseTypeId); - - for (TypeId prototype : range) { - selectLocalPropertyDeclarationIdsForTypeStatement.readTo(propertyDeclarationIds, - prototype); - } - - return propertyDeclarationIds; - } + QVarLengthArray fetchPropertyDeclarationIds(TypeId baseTypeId) const; PropertyDeclarationId fetchNextPropertyDeclarationId(TypeId baseTypeId, - Utils::SmallStringView propertyName) const - { - auto range = selectPrototypeAndExtensionIdsStatement.template range(baseTypeId); - - for (TypeId prototype : range) { - auto propertyDeclarationId = selectPropertyDeclarationIdByTypeIdAndNameStatement - .template value(prototype, - propertyName); - - if (propertyDeclarationId) - return propertyDeclarationId; - } - - return PropertyDeclarationId{}; - } + Utils::SmallStringView propertyName) const; PropertyDeclarationId fetchPropertyDeclarationId(TypeId typeId, - Utils::SmallStringView propertyName) const - { - auto propertyDeclarationId = selectPropertyDeclarationIdByTypeIdAndNameStatement - .template value(typeId, propertyName); + Utils::SmallStringView propertyName) const; - if (propertyDeclarationId) - return propertyDeclarationId; + PropertyDeclarationId fetchNextDefaultPropertyDeclarationId(TypeId baseTypeId) const; - return fetchNextPropertyDeclarationId(typeId, propertyName); - } - - PropertyDeclarationId fetchNextDefaultPropertyDeclarationId(TypeId baseTypeId) const - { - auto range = selectPrototypeAndExtensionIdsStatement.template range(baseTypeId); - - for (TypeId prototype : range) { - auto propertyDeclarationId = selectDefaultPropertyDeclarationIdStatement - .template value(prototype); - - if (propertyDeclarationId) - return propertyDeclarationId; - } - - return PropertyDeclarationId{}; - } - - PropertyDeclarationId fetchDefaultPropertyDeclarationId(TypeId typeId) const - { - auto propertyDeclarationId = selectDefaultPropertyDeclarationIdStatement - .template value(typeId); - - if (propertyDeclarationId) - return propertyDeclarationId; - - return fetchNextDefaultPropertyDeclarationId(typeId); - } + PropertyDeclarationId fetchDefaultPropertyDeclarationId(TypeId typeId) const; void synchronizePropertyDeclarationsInsertProperty( - const Storage::Synchronization::PropertyDeclaration &value, SourceId sourceId, TypeId typeId) - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"insert property declaration"_t, - projectStorageCategory(), - keyValue("property declaration", value)}; - - auto propertyImportedTypeNameId = fetchImportedTypeNameId(value.typeName, sourceId); - auto propertyTypeId = fetchTypeId(propertyImportedTypeNameId); - - if (!propertyTypeId) - throw TypeNameDoesNotExists{fetchImportedTypeName(propertyImportedTypeNameId), sourceId}; - - auto propertyDeclarationId = insertPropertyDeclarationStatement.template value( - typeId, value.name, propertyTypeId, value.traits, propertyImportedTypeNameId); - - auto nextPropertyDeclarationId = fetchNextPropertyDeclarationId(typeId, value.name); - if (nextPropertyDeclarationId) { - updateAliasIdPropertyDeclarationStatement.write(nextPropertyDeclarationId, - propertyDeclarationId); - updatePropertyAliasDeclarationRecursivelyWithTypeAndTraitsStatement - .write(propertyDeclarationId, propertyTypeId, value.traits); - } - } + const Storage::Synchronization::PropertyDeclaration &value, SourceId sourceId, TypeId typeId); void synchronizePropertyDeclarationsUpdateAlias( AliasPropertyDeclarations &updatedAliasPropertyDeclarations, const Storage::Synchronization::PropertyDeclarationView &view, const Storage::Synchronization::PropertyDeclaration &value, - SourceId sourceId) - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"update property declaration to alias"_t, - projectStorageCategory(), - keyValue("property declaration", value), - keyValue("property declaration view", view)}; + SourceId sourceId); - updatedAliasPropertyDeclarations.emplace_back(view.typeId, - view.id, - fetchImportedTypeNameId(value.typeName, sourceId), - value.aliasPropertyName, - value.aliasPropertyNameTail, - view.aliasId); - } - - auto synchronizePropertyDeclarationsUpdateProperty( + Sqlite::UpdateChange synchronizePropertyDeclarationsUpdateProperty( const Storage::Synchronization::PropertyDeclarationView &view, const Storage::Synchronization::PropertyDeclaration &value, SourceId sourceId, - PropertyDeclarationIds &propertyDeclarationIds) - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"update property declaration"_t, - projectStorageCategory(), - keyValue("property declaration", value), - keyValue("property declaration view", view)}; - - auto propertyImportedTypeNameId = fetchImportedTypeNameId(value.typeName, sourceId); - - auto propertyTypeId = fetchTypeId(propertyImportedTypeNameId); - - if (!propertyTypeId) - throw TypeNameDoesNotExists{fetchImportedTypeName(propertyImportedTypeNameId), sourceId}; - - if (view.traits == value.traits && propertyTypeId == view.typeId - && propertyImportedTypeNameId == view.typeNameId) - return Sqlite::UpdateChange::No; - - updatePropertyDeclarationStatement.write(view.id, - propertyTypeId, - value.traits, - propertyImportedTypeNameId); - updatePropertyAliasDeclarationRecursivelyWithTypeAndTraitsStatement.write(view.id, - propertyTypeId, - value.traits); - propertyDeclarationIds.push_back(view.id); - - tracer.end(keyValue("updated", "yes")); - - return Sqlite::UpdateChange::Update; - } + PropertyDeclarationIds &propertyDeclarationIds); void synchronizePropertyDeclarations( TypeId typeId, @@ -2607,73 +698,7 @@ private: SourceId sourceId, AliasPropertyDeclarations &insertedAliasPropertyDeclarations, AliasPropertyDeclarations &updatedAliasPropertyDeclarations, - PropertyDeclarationIds &propertyDeclarationIds) - { - NanotraceHR::Tracer tracer{"synchronize property declaration"_t, projectStorageCategory()}; - - std::sort(propertyDeclarations.begin(), - propertyDeclarations.end(), - [](auto &&first, auto &&second) { - return Sqlite::compare(first.name, second.name) < 0; - }); - - auto range = selectPropertyDeclarationsForTypeIdStatement - .template range(typeId); - - auto compareKey = [](const Storage::Synchronization::PropertyDeclarationView &view, - const Storage::Synchronization::PropertyDeclaration &value) { - return Sqlite::compare(view.name, value.name); - }; - - auto insert = [&](const Storage::Synchronization::PropertyDeclaration &value) { - if (value.kind == Storage::Synchronization::PropertyKind::Alias) { - synchronizePropertyDeclarationsInsertAlias(insertedAliasPropertyDeclarations, - value, - sourceId, - typeId); - } else { - synchronizePropertyDeclarationsInsertProperty(value, sourceId, typeId); - } - }; - - auto update = [&](const Storage::Synchronization::PropertyDeclarationView &view, - const Storage::Synchronization::PropertyDeclaration &value) { - if (value.kind == Storage::Synchronization::PropertyKind::Alias) { - synchronizePropertyDeclarationsUpdateAlias(updatedAliasPropertyDeclarations, - view, - value, - sourceId); - propertyDeclarationIds.push_back(view.id); - } else { - return synchronizePropertyDeclarationsUpdateProperty(view, - value, - sourceId, - propertyDeclarationIds); - } - - return Sqlite::UpdateChange::No; - }; - - auto remove = [&](const Storage::Synchronization::PropertyDeclarationView &view) { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"remove property declaration"_t, - projectStorageCategory(), - keyValue("property declaratio viewn", view)}; - - auto nextPropertyDeclarationId = fetchNextPropertyDeclarationId(typeId, view.name); - - if (nextPropertyDeclarationId) { - updateAliasPropertyDeclarationByAliasPropertyDeclarationIdStatement - .write(nextPropertyDeclarationId, view.id); - } - - updateDefaultPropertyIdToNullStatement.write(view.id); - deletePropertyDeclarationStatement.write(view.id); - propertyDeclarationIds.push_back(view.id); - }; - - Sqlite::insertUpdateDelete(range, propertyDeclarations, compareKey, insert, update, remove); - } + PropertyDeclarationIds &propertyDeclarationIds); class AliasPropertyDeclarationView { @@ -2706,237 +731,27 @@ private: }; void resetRemovedAliasPropertyDeclarationsToNull(Storage::Synchronization::Type &type, - PropertyDeclarationIds &propertyDeclarationIds) - { - NanotraceHR::Tracer tracer{"reset removed alias property declaration to null"_t, - projectStorageCategory()}; - - if (type.changeLevel == Storage::Synchronization::ChangeLevel::Minimal) - return; - - Storage::Synchronization::PropertyDeclarations &aliasDeclarations = type.propertyDeclarations; - - std::sort(aliasDeclarations.begin(), aliasDeclarations.end(), [](auto &&first, auto &&second) { - return Sqlite::compare(first.name, second.name) < 0; - }); - - auto range = selectPropertyDeclarationsWithAliasForTypeIdStatement - .template range(type.typeId); - - auto compareKey = [](const AliasPropertyDeclarationView &view, - const Storage::Synchronization::PropertyDeclaration &value) { - return Sqlite::compare(view.name, value.name); - }; - - auto insert = [&](const Storage::Synchronization::PropertyDeclaration &) {}; - - auto update = [&](const AliasPropertyDeclarationView &, - const Storage::Synchronization::PropertyDeclaration &) { - return Sqlite::UpdateChange::No; - }; - - auto remove = [&](const AliasPropertyDeclarationView &view) { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"reset removed alias property declaration to null"_t, - projectStorageCategory(), - keyValue("alias property declaration view", view)}; - - updatePropertyDeclarationAliasIdToNullStatement.write(view.id); - propertyDeclarationIds.push_back(view.id); - }; - - Sqlite::insertUpdateDelete(range, aliasDeclarations, compareKey, insert, update, remove); - } + PropertyDeclarationIds &propertyDeclarationIds); void resetRemovedAliasPropertyDeclarationsToNull( Storage::Synchronization::Types &types, - AliasPropertyDeclarations &relinkableAliasPropertyDeclarations) - { - NanotraceHR::Tracer tracer{"reset removed alias properties to null"_t, - projectStorageCategory()}; - - PropertyDeclarationIds propertyDeclarationIds; - propertyDeclarationIds.reserve(types.size()); - - for (auto &&type : types) - resetRemovedAliasPropertyDeclarationsToNull(type, propertyDeclarationIds); - - removeRelinkableEntries(relinkableAliasPropertyDeclarations, - propertyDeclarationIds, - PropertyCompare{}); - } + AliasPropertyDeclarations &relinkableAliasPropertyDeclarations); ImportId insertDocumentImport(const Storage::Import &import, Storage::Synchronization::ImportKind importKind, ModuleId sourceModuleId, - ImportId parentImportId) - { - if (import.version.minor) { - return insertDocumentImportWithVersionStatement - .template value(import.sourceId, - import.moduleId, - sourceModuleId, - importKind, - import.version.major.value, - import.version.minor.value, - parentImportId); - } else if (import.version.major) { - return insertDocumentImportWithMajorVersionStatement - .template value(import.sourceId, - import.moduleId, - sourceModuleId, - importKind, - import.version.major.value, - parentImportId); - } else { - return insertDocumentImportWithoutVersionStatement.template value( - import.sourceId, import.moduleId, sourceModuleId, importKind, parentImportId); - } - } + ImportId parentImportId); void synchronizeDocumentImports(Storage::Imports &imports, const SourceIds &updatedSourceIds, - Storage::Synchronization::ImportKind importKind) - { - std::sort(imports.begin(), imports.end(), [](auto &&first, auto &&second) { - return std::tie(first.sourceId, first.moduleId, first.version) - < std::tie(second.sourceId, second.moduleId, second.version); - }); + Storage::Synchronization::ImportKind importKind); - auto range = selectDocumentImportForSourceIdStatement - .template range(toIntegers( - updatedSourceIds), - importKind); - - auto compareKey = [](const Storage::Synchronization::ImportView &view, - const Storage::Import &import) -> long long { - auto sourceIdDifference = view.sourceId - import.sourceId; - if (sourceIdDifference != 0) - return sourceIdDifference; - - auto moduleIdDifference = view.moduleId - import.moduleId; - if (moduleIdDifference != 0) - return moduleIdDifference; - - auto versionDifference = view.version.major.value - import.version.major.value; - if (versionDifference != 0) - return versionDifference; - - return view.version.minor.value - import.version.minor.value; - }; - - auto insert = [&](const Storage::Import &import) { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"insert import"_t, - projectStorageCategory(), - keyValue("import", import), - keyValue("import kind", importKind), - keyValue("source id", import.sourceId), - keyValue("module id", import.moduleId)}; - - auto importId = insertDocumentImport(import, importKind, import.moduleId, ImportId{}); - auto callback = [&](ModuleId exportedModuleId, int majorVersion, int minorVersion) { - Storage::Import additionImport{exportedModuleId, - Storage::Version{majorVersion, minorVersion}, - import.sourceId}; - - auto exportedImportKind = importKind == Storage::Synchronization::ImportKind::Import - ? Storage::Synchronization::ImportKind::ModuleExportedImport - : Storage::Synchronization::ImportKind::ModuleExportedModuleDependency; - - NanotraceHR::Tracer tracer{"insert indirect import"_t, - projectStorageCategory(), - keyValue("import", import), - keyValue("import kind", exportedImportKind), - keyValue("source id", import.sourceId), - keyValue("module id", import.moduleId)}; - - auto indirectImportId = insertDocumentImport(additionImport, - exportedImportKind, - import.moduleId, - importId); - - tracer.end(keyValue("import id", indirectImportId)); - }; - - selectModuleExportedImportsForModuleIdStatement.readCallback(callback, - import.moduleId, - import.version.major.value, - import.version.minor.value); - tracer.end(keyValue("import id", importId)); - }; - - auto update = [](const Storage::Synchronization::ImportView &, const Storage::Import &) { - return Sqlite::UpdateChange::No; - }; - - auto remove = [&](const Storage::Synchronization::ImportView &view) { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"remove import"_t, - projectStorageCategory(), - keyValue("import", view), - keyValue("import id", view.importId), - keyValue("source id", view.sourceId), - keyValue("module id", view.moduleId)}; - - deleteDocumentImportStatement.write(view.importId); - deleteDocumentImportsWithParentImportIdStatement.write(view.sourceId, view.importId); - }; - - Sqlite::insertUpdateDelete(range, imports, compareKey, insert, update, remove); - } - - static Utils::PathString createJson(const Storage::Synchronization::ParameterDeclarations ¶meters) - { - NanotraceHR::Tracer tracer{"create json from parameter declarations"_t, - projectStorageCategory()}; - - Utils::PathString json; - json.append("["); - - Utils::SmallStringView comma{""}; - - for (const auto ¶meter : parameters) { - json.append(comma); - comma = ","; - json.append(R"({"n":")"); - json.append(parameter.name); - json.append(R"(","tn":")"); - json.append(parameter.typeName); - if (parameter.traits == Storage::PropertyDeclarationTraits::None) { - json.append("\"}"); - } else { - json.append(R"(","tr":)"); - json.append(Utils::SmallString::number(to_underlying(parameter.traits))); - json.append("}"); - } - } - - json.append("]"); - - return json; - } + static Utils::PathString createJson(const Storage::Synchronization::ParameterDeclarations ¶meters); TypeId fetchTypeIdByModuleIdAndExportedName(ModuleId moduleId, - Utils::SmallStringView name) const override - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"fetch type id by module id and exported name"_t, - projectStorageCategory(), - keyValue("module id", moduleId), - keyValue("exported name", name)}; + Utils::SmallStringView name) const override; - return selectTypeIdByModuleIdAndExportedNameStatement.template value(moduleId, name); - } - - void addTypeIdToPropertyEditorQmlPaths(Storage::Synchronization::PropertyEditorQmlPaths &paths) - { - NanotraceHR::Tracer tracer{"add type id to property editor qml paths"_t, - projectStorageCategory()}; - - for (auto &path : paths) - path.typeId = fetchTypeIdByModuleIdAndExportedName(path.moduleId, path.typeName); - } + void addTypeIdToPropertyEditorQmlPaths(Storage::Synchronization::PropertyEditorQmlPaths &paths); class PropertyEditorQmlPathView { @@ -2967,358 +782,33 @@ private: }; void synchronizePropertyEditorPaths(Storage::Synchronization::PropertyEditorQmlPaths &paths, - SourceIds updatedPropertyEditorQmlPathsSourceIds) - { - using Storage::Synchronization::PropertyEditorQmlPath; - std::sort(paths.begin(), paths.end(), [](auto &&first, auto &&second) { - return first.typeId < second.typeId; - }); - - auto range = selectPropertyEditorPathsForForSourceIdsStatement - .template range( - toIntegers(updatedPropertyEditorQmlPathsSourceIds)); - - auto compareKey = [](const PropertyEditorQmlPathView &view, - const PropertyEditorQmlPath &value) -> long long { - return view.typeId - value.typeId; - }; - - auto insert = [&](const PropertyEditorQmlPath &path) { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"insert property editor paths"_t, - projectStorageCategory(), - keyValue("property editor qml path", path)}; - - if (path.typeId) - insertPropertyEditorPathStatement.write(path.typeId, path.pathId, path.directoryId); - }; - - auto update = [&](const PropertyEditorQmlPathView &view, const PropertyEditorQmlPath &value) { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"update property editor paths"_t, - projectStorageCategory(), - keyValue("property editor qml path", value), - keyValue("property editor qml path view", view)}; - - if (value.pathId != view.pathId || value.directoryId != view.directoryId) { - updatePropertyEditorPathsStatement.write(value.typeId, value.pathId, value.directoryId); - - tracer.end(keyValue("updated", "yes")); - - return Sqlite::UpdateChange::Update; - } - return Sqlite::UpdateChange::No; - }; - - auto remove = [&](const PropertyEditorQmlPathView &view) { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"remove property editor paths"_t, - projectStorageCategory(), - keyValue("property editor qml path view", view)}; - - deletePropertyEditorPathStatement.write(view.typeId); - }; - - Sqlite::insertUpdateDelete(range, paths, compareKey, insert, update, remove); - } + SourceIds updatedPropertyEditorQmlPathsSourceIds); void synchronizePropertyEditorQmlPaths(Storage::Synchronization::PropertyEditorQmlPaths &paths, - SourceIds updatedPropertyEditorQmlPathsSourceIds) - { - NanotraceHR::Tracer tracer{"synchronize property editor qml paths"_t, - projectStorageCategory()}; - - addTypeIdToPropertyEditorQmlPaths(paths); - synchronizePropertyEditorPaths(paths, updatedPropertyEditorQmlPathsSourceIds); - } + SourceIds updatedPropertyEditorQmlPathsSourceIds); void synchronizeFunctionDeclarations( - TypeId typeId, Storage::Synchronization::FunctionDeclarations &functionsDeclarations) - { - NanotraceHR::Tracer tracer{"synchronize function declaration"_t, projectStorageCategory()}; - - std::sort(functionsDeclarations.begin(), - functionsDeclarations.end(), - [](auto &&first, auto &&second) { - auto compare = Sqlite::compare(first.name, second.name); - - if (compare == 0) { - Utils::PathString firstSignature{createJson(first.parameters)}; - Utils::PathString secondSignature{createJson(second.parameters)}; - - return Sqlite::compare(firstSignature, secondSignature) < 0; - } - - return compare < 0; - }); - - auto range = selectFunctionDeclarationsForTypeIdStatement - .template range(typeId); - - auto compareKey = [](const Storage::Synchronization::FunctionDeclarationView &view, - const Storage::Synchronization::FunctionDeclaration &value) { - auto nameKey = Sqlite::compare(view.name, value.name); - if (nameKey != 0) - return nameKey; - - Utils::PathString valueSignature{createJson(value.parameters)}; - - return Sqlite::compare(view.signature, valueSignature); - }; - - auto insert = [&](const Storage::Synchronization::FunctionDeclaration &value) { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"insert function declaration"_t, - projectStorageCategory(), - keyValue("function declaration", value)}; - - Utils::PathString signature{createJson(value.parameters)}; - - insertFunctionDeclarationStatement.write(typeId, value.name, value.returnTypeName, signature); - }; - - auto update = [&](const Storage::Synchronization::FunctionDeclarationView &view, - const Storage::Synchronization::FunctionDeclaration &value) { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"update function declaration"_t, - projectStorageCategory(), - keyValue("function declaration", value), - keyValue("function declaration view", view)}; - - Utils::PathString signature{createJson(value.parameters)}; - - if (value.returnTypeName == view.returnTypeName) - return Sqlite::UpdateChange::No; - - updateFunctionDeclarationStatement.write(view.id, value.returnTypeName); - - tracer.end(keyValue("updated", "yes")); - - return Sqlite::UpdateChange::Update; - }; - - auto remove = [&](const Storage::Synchronization::FunctionDeclarationView &view) { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"remove function declaration"_t, - projectStorageCategory(), - keyValue("function declaration view", view)}; - - deleteFunctionDeclarationStatement.write(view.id); - }; - - Sqlite::insertUpdateDelete(range, functionsDeclarations, compareKey, insert, update, remove); - } + TypeId typeId, Storage::Synchronization::FunctionDeclarations &functionsDeclarations); void synchronizeSignalDeclarations(TypeId typeId, - Storage::Synchronization::SignalDeclarations &signalDeclarations) - { - NanotraceHR::Tracer tracer{"synchronize signal declaration"_t, projectStorageCategory()}; - - std::sort(signalDeclarations.begin(), signalDeclarations.end(), [](auto &&first, auto &&second) { - auto compare = Sqlite::compare(first.name, second.name); - - if (compare == 0) { - Utils::PathString firstSignature{createJson(first.parameters)}; - Utils::PathString secondSignature{createJson(second.parameters)}; - - return Sqlite::compare(firstSignature, secondSignature) < 0; - } - - return compare < 0; - }); - - auto range = selectSignalDeclarationsForTypeIdStatement - .template range(typeId); - - auto compareKey = [](const Storage::Synchronization::SignalDeclarationView &view, - const Storage::Synchronization::SignalDeclaration &value) { - auto nameKey = Sqlite::compare(view.name, value.name); - if (nameKey != 0) - return nameKey; - - Utils::PathString valueSignature{createJson(value.parameters)}; - - return Sqlite::compare(view.signature, valueSignature); - }; - - auto insert = [&](const Storage::Synchronization::SignalDeclaration &value) { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"insert signal declaration"_t, - projectStorageCategory(), - keyValue("signal declaration", value)}; - - Utils::PathString signature{createJson(value.parameters)}; - - insertSignalDeclarationStatement.write(typeId, value.name, signature); - }; - - auto update = [&]([[maybe_unused]] const Storage::Synchronization::SignalDeclarationView &view, - [[maybe_unused]] const Storage::Synchronization::SignalDeclaration &value) { - return Sqlite::UpdateChange::No; - }; - - auto remove = [&](const Storage::Synchronization::SignalDeclarationView &view) { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"remove signal declaration"_t, - projectStorageCategory(), - keyValue("signal declaration view", view)}; - - deleteSignalDeclarationStatement.write(view.id); - }; - - Sqlite::insertUpdateDelete(range, signalDeclarations, compareKey, insert, update, remove); - } + Storage::Synchronization::SignalDeclarations &signalDeclarations); static Utils::PathString createJson( - const Storage::Synchronization::EnumeratorDeclarations &enumeratorDeclarations) - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"create json from enumerator declarations"_t, - projectStorageCategory()}; - - Utils::PathString json; - json.append("{"); - - Utils::SmallStringView comma{"\""}; - - for (const auto &enumerator : enumeratorDeclarations) { - json.append(comma); - comma = ",\""; - json.append(enumerator.name); - if (enumerator.hasValue) { - json.append("\":\""); - json.append(Utils::SmallString::number(enumerator.value)); - json.append("\""); - } else { - json.append("\":null"); - } - } - - json.append("}"); - - return json; - } + const Storage::Synchronization::EnumeratorDeclarations &enumeratorDeclarations); void synchronizeEnumerationDeclarations( - TypeId typeId, Storage::Synchronization::EnumerationDeclarations &enumerationDeclarations) - { - NanotraceHR::Tracer tracer{"synchronize enumeration declaration"_t, projectStorageCategory()}; - - std::sort(enumerationDeclarations.begin(), - enumerationDeclarations.end(), - [](auto &&first, auto &&second) { - return Sqlite::compare(first.name, second.name) < 0; - }); - - auto range = selectEnumerationDeclarationsForTypeIdStatement - .template range(typeId); - - auto compareKey = [](const Storage::Synchronization::EnumerationDeclarationView &view, - const Storage::Synchronization::EnumerationDeclaration &value) { - return Sqlite::compare(view.name, value.name); - }; - - auto insert = [&](const Storage::Synchronization::EnumerationDeclaration &value) { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"insert enumeration declaration"_t, - projectStorageCategory(), - keyValue("enumeration declaration", value)}; - - Utils::PathString signature{createJson(value.enumeratorDeclarations)}; - - insertEnumerationDeclarationStatement.write(typeId, value.name, signature); - }; - - auto update = [&](const Storage::Synchronization::EnumerationDeclarationView &view, - const Storage::Synchronization::EnumerationDeclaration &value) { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"update enumeration declaration"_t, - projectStorageCategory(), - keyValue("enumeration declaration", value), - keyValue("enumeration declaration view", view)}; - - Utils::PathString enumeratorDeclarations{createJson(value.enumeratorDeclarations)}; - - if (enumeratorDeclarations == view.enumeratorDeclarations) - return Sqlite::UpdateChange::No; - - updateEnumerationDeclarationStatement.write(view.id, enumeratorDeclarations); - - tracer.end(keyValue("updated", "yes")); - - return Sqlite::UpdateChange::Update; - }; - - auto remove = [&](const Storage::Synchronization::EnumerationDeclarationView &view) { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"remove enumeration declaration"_t, - projectStorageCategory(), - keyValue("enumeration declaration view", view)}; - - deleteEnumerationDeclarationStatement.write(view.id); - }; - - Sqlite::insertUpdateDelete(range, enumerationDeclarations, compareKey, insert, update, remove); - } + TypeId typeId, Storage::Synchronization::EnumerationDeclarations &enumerationDeclarations); void extractExportedTypes(TypeId typeId, const Storage::Synchronization::Type &type, - Storage::Synchronization::ExportedTypes &exportedTypes) - { - for (const auto &exportedType : type.exportedTypes) - exportedTypes.emplace_back(exportedType.name, - exportedType.version, - typeId, - exportedType.moduleId); - } + Storage::Synchronization::ExportedTypes &exportedTypes); - TypeId declareType(Storage::Synchronization::Type &type) - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"declare type"_t, - projectStorageCategory(), - keyValue("source id", type.sourceId), - keyValue("type name", type.typeName)}; - - if (type.typeName.isEmpty()) { - type.typeId = selectTypeIdBySourceIdStatement.template value(type.sourceId); - - tracer.end(keyValue("type id", type.typeId)); - - return type.typeId; - } - - type.typeId = insertTypeStatement.template value(type.sourceId, type.typeName); - - if (!type.typeId) - type.typeId = selectTypeIdBySourceIdAndNameStatement.template value(type.sourceId, - type.typeName); - - tracer.end(keyValue("type id", type.typeId)); - - return type.typeId; - } + TypeId declareType(Storage::Synchronization::Type &type); void syncDeclarations(Storage::Synchronization::Type &type, AliasPropertyDeclarations &insertedAliasPropertyDeclarations, AliasPropertyDeclarations &updatedAliasPropertyDeclarations, - PropertyDeclarationIds &propertyDeclarationIds) - { - NanotraceHR::Tracer tracer{"synchronize declaration per type"_t, projectStorageCategory()}; - - if (type.changeLevel == Storage::Synchronization::ChangeLevel::Minimal) - return; - - synchronizePropertyDeclarations(type.typeId, - type.propertyDeclarations, - type.sourceId, - insertedAliasPropertyDeclarations, - updatedAliasPropertyDeclarations, - propertyDeclarationIds); - synchronizeFunctionDeclarations(type.typeId, type.functionDeclarations); - synchronizeSignalDeclarations(type.typeId, type.signalDeclarations); - synchronizeEnumerationDeclarations(type.typeId, type.enumerationDeclarations); - } + PropertyDeclarationIds &propertyDeclarationIds); template void removeRelinkableEntries(std::vector &relinkables, Ids &ids, Compare compare) @@ -3345,23 +835,7 @@ private: void syncDeclarations(Storage::Synchronization::Types &types, AliasPropertyDeclarations &insertedAliasPropertyDeclarations, AliasPropertyDeclarations &updatedAliasPropertyDeclarations, - PropertyDeclarations &relinkablePropertyDeclarations) - { - NanotraceHR::Tracer tracer{"synchronize declaration"_t, projectStorageCategory()}; - - PropertyDeclarationIds propertyDeclarationIds; - propertyDeclarationIds.reserve(types.size() * 10); - - for (auto &&type : types) - syncDeclarations(type, - insertedAliasPropertyDeclarations, - updatedAliasPropertyDeclarations, - propertyDeclarationIds); - - removeRelinkableEntries(relinkablePropertyDeclarations, - propertyDeclarationIds, - PropertyCompare{}); - } + PropertyDeclarations &relinkablePropertyDeclarations); class TypeWithDefaultPropertyView { @@ -3386,279 +860,27 @@ private: PropertyDeclarationId defaultPropertyId; }; - void syncDefaultProperties(Storage::Synchronization::Types &types) - { - NanotraceHR::Tracer tracer{"synchronize default properties"_t, projectStorageCategory()}; + void syncDefaultProperties(Storage::Synchronization::Types &types); - auto range = selectTypesWithDefaultPropertyStatement.template range(); + void resetDefaultPropertiesIfChanged(Storage::Synchronization::Types &types); - auto compareKey = [](const TypeWithDefaultPropertyView &view, - const Storage::Synchronization::Type &value) { - return view.typeId - value.typeId; - }; + void checkForPrototypeChainCycle(TypeId typeId) const; - auto insert = [&](const Storage::Synchronization::Type &) { - - }; - - auto update = [&](const TypeWithDefaultPropertyView &view, - const Storage::Synchronization::Type &value) { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"synchronize default properties by update"_t, - projectStorageCategory(), - keyValue("type id", value.typeId), - keyValue("value", value), - keyValue("view", view)}; - - PropertyDeclarationId valueDefaultPropertyId; - if (value.defaultPropertyName.size()) - valueDefaultPropertyId = fetchPropertyDeclarationByTypeIdAndNameUngarded( - value.typeId, value.defaultPropertyName) - .propertyDeclarationId; - - if (compareInvalidAreTrue(valueDefaultPropertyId, view.defaultPropertyId)) - return Sqlite::UpdateChange::No; - - updateDefaultPropertyIdStatement.write(value.typeId, valueDefaultPropertyId); - - tracer.end(keyValue("updated", "yes"), - keyValue("default property id", valueDefaultPropertyId)); - - return Sqlite::UpdateChange::Update; - }; - - auto remove = [&](const TypeWithDefaultPropertyView &) {}; - - Sqlite::insertUpdateDelete(range, types, compareKey, insert, update, remove); - } - - void resetDefaultPropertiesIfChanged(Storage::Synchronization::Types &types) - { - NanotraceHR::Tracer tracer{"reset changed default properties"_t, projectStorageCategory()}; - - auto range = selectTypesWithDefaultPropertyStatement.template range(); - - auto compareKey = [](const TypeWithDefaultPropertyView &view, - const Storage::Synchronization::Type &value) { - return view.typeId - value.typeId; - }; - - auto insert = [&](const Storage::Synchronization::Type &) { - - }; - - auto update = [&](const TypeWithDefaultPropertyView &view, - const Storage::Synchronization::Type &value) { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"reset changed default properties by update"_t, - projectStorageCategory(), - keyValue("type id", value.typeId), - keyValue("value", value), - keyValue("view", view)}; - - PropertyDeclarationId valueDefaultPropertyId; - if (value.defaultPropertyName.size()) { - auto optionalValueDefaultPropertyId = fetchOptionalPropertyDeclarationByTypeIdAndNameUngarded( - value.typeId, value.defaultPropertyName); - if (optionalValueDefaultPropertyId) - valueDefaultPropertyId = optionalValueDefaultPropertyId->propertyDeclarationId; - } - - if (compareInvalidAreTrue(valueDefaultPropertyId, view.defaultPropertyId)) - return Sqlite::UpdateChange::No; - - updateDefaultPropertyIdStatement.write(value.typeId, Sqlite::NullValue{}); - - tracer.end(keyValue("updated", "yes")); - - return Sqlite::UpdateChange::Update; - }; - - auto remove = [&](const TypeWithDefaultPropertyView &) {}; - - Sqlite::insertUpdateDelete(range, types, compareKey, insert, update, remove); - } - - void checkForPrototypeChainCycle(TypeId typeId) const - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"check for prototype chain cycle"_t, - projectStorageCategory(), - keyValue("type id", typeId)}; - - auto callback = [=](TypeId currentTypeId) { - if (typeId == currentTypeId) - throw PrototypeChainCycle{}; - }; - - selectPrototypeAndExtensionIdsStatement.readCallback(callback, typeId); - } - - void checkForAliasChainCycle(PropertyDeclarationId propertyDeclarationId) const - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"check for alias chain cycle"_t, - projectStorageCategory(), - keyValue("property declaration id", propertyDeclarationId)}; - auto callback = [=](PropertyDeclarationId currentPropertyDeclarationId) { - if (propertyDeclarationId == currentPropertyDeclarationId) - throw AliasChainCycle{}; - }; - - selectPropertyDeclarationIdsForAliasChainStatement.readCallback(callback, - propertyDeclarationId); - } + void checkForAliasChainCycle(PropertyDeclarationId propertyDeclarationId) const; std::pair fetchImportedTypeNameIdAndTypeId( - const Storage::Synchronization::ImportedTypeName &typeName, SourceId sourceId) - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"fetch imported type name id and type id"_t, - projectStorageCategory(), - keyValue("imported type name", typeName), - keyValue("source id", sourceId)}; + const Storage::Synchronization::ImportedTypeName &typeName, SourceId sourceId); - TypeId typeId; - ImportedTypeNameId typeNameId; - if (!std::visit([](auto &&typeName_) -> bool { return typeName_.name.isEmpty(); }, typeName)) { - typeNameId = fetchImportedTypeNameId(typeName, sourceId); - - typeId = fetchTypeId(typeNameId); - - tracer.end(keyValue("type id", typeId), keyValue("type name id", typeNameId)); - - if (!typeId) - throw TypeNameDoesNotExists{fetchImportedTypeName(typeNameId), sourceId}; - } - - return {typeId, typeNameId}; - } - - void syncPrototypeAndExtension(Storage::Synchronization::Type &type, TypeIds &typeIds) - { - if (type.changeLevel == Storage::Synchronization::ChangeLevel::Minimal) - return; - - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"synchronize prototype and extension"_t, - projectStorageCategory(), - keyValue("prototype", type.prototype), - keyValue("extension", type.extension), - keyValue("type id", type.typeId), - keyValue("source id", type.sourceId)}; - - auto [prototypeId, prototypeTypeNameId] = fetchImportedTypeNameIdAndTypeId(type.prototype, - type.sourceId); - auto [extensionId, extensionTypeNameId] = fetchImportedTypeNameIdAndTypeId(type.extension, - type.sourceId); - - updatePrototypeAndExtensionStatement.write(type.typeId, - prototypeId, - prototypeTypeNameId, - extensionId, - extensionTypeNameId); - - if (prototypeId || extensionId) - checkForPrototypeChainCycle(type.typeId); - - typeIds.push_back(type.typeId); - - tracer.end(keyValue("prototype id", prototypeId), - keyValue("prototype type name id", prototypeTypeNameId), - keyValue("extension id", extensionId), - keyValue("extension type name id", extensionTypeNameId)); - } + void syncPrototypeAndExtension(Storage::Synchronization::Type &type, TypeIds &typeIds); void syncPrototypesAndExtensions(Storage::Synchronization::Types &types, Prototypes &relinkablePrototypes, - Prototypes &relinkableExtensions) - { - NanotraceHR::Tracer tracer{"synchronize prototypes and extensions"_t, - projectStorageCategory()}; + Prototypes &relinkableExtensions); - TypeIds typeIds; - typeIds.reserve(types.size()); - - for (auto &type : types) - syncPrototypeAndExtension(type, typeIds); - - removeRelinkableEntries(relinkablePrototypes, typeIds, TypeCompare{}); - removeRelinkableEntries(relinkableExtensions, typeIds, TypeCompare{}); - } - - ImportId fetchImportId(SourceId sourceId, const Storage::Import &import) const - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"fetch imported type name id"_t, - projectStorageCategory(), - keyValue("import", import), - keyValue("source id", sourceId)}; - - ImportId importId; - if (import.version) { - importId = selectImportIdBySourceIdAndModuleIdAndVersionStatement.template value( - sourceId, import.moduleId, import.version.major.value, import.version.minor.value); - } else if (import.version.major) { - importId = selectImportIdBySourceIdAndModuleIdAndMajorVersionStatement - .template value(sourceId, - import.moduleId, - import.version.major.value); - } else { - importId = selectImportIdBySourceIdAndModuleIdStatement - .template value(sourceId, import.moduleId); - } - - tracer.end(keyValue("import id", importId)); - - return importId; - } + ImportId fetchImportId(SourceId sourceId, const Storage::Import &import) const; ImportedTypeNameId fetchImportedTypeNameId(const Storage::Synchronization::ImportedTypeName &name, - SourceId sourceId) - { - struct Inspect - { - auto operator()(const Storage::Synchronization::ImportedType &importedType) - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"fetch imported type name id"_t, - projectStorageCategory(), - keyValue("imported type name", importedType.name), - keyValue("source id", sourceId), - keyValue("type name kind", "exported"sv)}; - - return storage.fetchImportedTypeNameId(Storage::Synchronization::TypeNameKind::Exported, - sourceId, - importedType.name); - } - - auto operator()(const Storage::Synchronization::QualifiedImportedType &importedType) - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"fetch imported type name id"_t, - projectStorageCategory(), - keyValue("imported type name", importedType.name), - keyValue("import", importedType.import), - keyValue("type name kind", "qualified exported"sv)}; - - ImportId importId = storage.fetchImportId(sourceId, importedType.import); - - auto importedTypeNameId = storage.fetchImportedTypeNameId( - Storage::Synchronization::TypeNameKind::QualifiedExported, - importId, - importedType.name); - - tracer.end(keyValue("import id", importId), keyValue("source id", sourceId)); - - return importedTypeNameId; - } - - ProjectStorage &storage; - SourceId sourceId; - }; - - return std::visit(Inspect{*this, sourceId}, name); - } + SourceId sourceId); template ImportedTypeNameId fetchImportedTypeNameId(Storage::Synchronization::TypeNameKind kind, @@ -3671,60 +893,26 @@ private: keyValue("imported type name", typeName), keyValue("kind", kind)}; - auto importedTypeNameId = selectImportedTypeNameIdStatement - .template value(kind, id, typeName); + auto importedTypeNameId = selectImportedTypeNameIdStatement.value(kind, + id, + typeName); if (!importedTypeNameId) - importedTypeNameId = insertImportedTypeNameIdStatement - .template value(kind, id, typeName); + importedTypeNameId = insertImportedTypeNameIdStatement.value(kind, + id, + typeName); tracer.end(keyValue("imported type name id", importedTypeNameId)); return importedTypeNameId; } - TypeId fetchTypeId(ImportedTypeNameId typeNameId) const - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"fetch type id with type name kind"_t, - projectStorageCategory(), - keyValue("type name id", typeNameId)}; + TypeId fetchTypeId(ImportedTypeNameId typeNameId) const; - auto kind = selectKindFromImportedTypeNamesStatement - .template value(typeNameId); + Utils::SmallString fetchImportedTypeName(ImportedTypeNameId typeNameId) const; - auto typeId = fetchTypeId(typeNameId, kind); - - tracer.end(keyValue("type id", typeId), keyValue("type name kind", kind)); - - return typeId; - } - - Utils::SmallString fetchImportedTypeName(ImportedTypeNameId typeNameId) const - { - return selectNameFromImportedTypeNamesStatement.template value(typeNameId); - } - - TypeId fetchTypeId(ImportedTypeNameId typeNameId, Storage::Synchronization::TypeNameKind kind) const - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"fetch type id"_t, - projectStorageCategory(), - keyValue("type name id", typeNameId), - keyValue("type name kind", kind)}; - - TypeId typeId; - if (kind == Storage::Synchronization::TypeNameKind::Exported) { - typeId = selectTypeIdForImportedTypeNameNamesStatement.template value(typeNameId); - } else { - typeId = selectTypeIdForQualifiedImportedTypeNameNamesStatement.template value( - typeNameId); - } - - tracer.end(keyValue("type id", typeId)); - - return typeId; - } + TypeId fetchTypeId(ImportedTypeNameId typeNameId, + Storage::Synchronization::TypeNameKind kind) const; class FetchPropertyDeclarationResult { @@ -3755,641 +943,41 @@ private: Storage::PropertyDeclarationTraits propertyTraits; }; - auto fetchOptionalPropertyDeclarationByTypeIdAndNameUngarded(TypeId typeId, - Utils::SmallStringView name) - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"fetch optional property declaration by type id and name ungarded"_t, - projectStorageCategory(), - keyValue("type id", typeId), - keyValue("property name", name)}; - - auto propertyDeclarationId = fetchPropertyDeclarationId(typeId, name); - auto propertyDeclaration = selectPropertyDeclarationResultByPropertyDeclarationIdStatement - .template optionalValue( - propertyDeclarationId); - - tracer.end(keyValue("property declaration", propertyDeclaration)); - - return propertyDeclaration; - } + std::optional fetchOptionalPropertyDeclarationByTypeIdAndNameUngarded( + TypeId typeId, Utils::SmallStringView name); FetchPropertyDeclarationResult fetchPropertyDeclarationByTypeIdAndNameUngarded( - TypeId typeId, Utils::SmallStringView name) - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"fetch property declaration by type id and name ungarded"_t, - projectStorageCategory(), - keyValue("type id", typeId), - keyValue("property name", name)}; - - auto propertyDeclaration = fetchOptionalPropertyDeclarationByTypeIdAndNameUngarded(typeId, - name); - tracer.end(keyValue("property declaration", propertyDeclaration)); - - if (propertyDeclaration) - return *propertyDeclaration; - - throw PropertyNameDoesNotExists{}; - } + TypeId typeId, Utils::SmallStringView name); PropertyDeclarationId fetchPropertyDeclarationIdByTypeIdAndNameUngarded(TypeId typeId, - Utils::SmallStringView name) - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"fetch property declaration id by type id and name ungarded"_t, - projectStorageCategory(), - keyValue("type id", typeId), - keyValue("property name", name)}; + Utils::SmallStringView name); - auto propertyDeclarationId = fetchPropertyDeclarationId(typeId, name); + SourceContextId readSourceContextId(Utils::SmallStringView sourceContextPath); - tracer.end(keyValue("property declaration id", propertyDeclarationId)); + SourceContextId writeSourceContextId(Utils::SmallStringView sourceContextPath); - if (propertyDeclarationId) - return propertyDeclarationId; + SourceId writeSourceId(SourceContextId sourceContextId, Utils::SmallStringView sourceName); - throw PropertyNameDoesNotExists{}; - } + SourceId readSourceId(SourceContextId sourceContextId, Utils::SmallStringView sourceName); - SourceContextId readSourceContextId(Utils::SmallStringView sourceContextPath) - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"read source context id"_t, - projectStorageCategory(), - keyValue("source context path", sourceContextPath)}; + Storage::Synchronization::ExportedTypes fetchExportedTypes(TypeId typeId); - auto sourceContextId = selectSourceContextIdFromSourceContextsBySourceContextPathStatement - .template value(sourceContextPath); + Storage::Synchronization::PropertyDeclarations fetchPropertyDeclarations(TypeId typeId); - tracer.end(keyValue("source context id", sourceContextId)); + Storage::Synchronization::FunctionDeclarations fetchFunctionDeclarations(TypeId typeId); - return sourceContextId; - } + Storage::Synchronization::SignalDeclarations fetchSignalDeclarations(TypeId typeId); - SourceContextId writeSourceContextId(Utils::SmallStringView sourceContextPath) - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"write source context id"_t, - projectStorageCategory(), - keyValue("source context path", sourceContextPath)}; + Storage::Synchronization::EnumerationDeclarations fetchEnumerationDeclarations(TypeId typeId); - insertIntoSourceContextsStatement.write(sourceContextPath); - - auto sourceContextId = SourceContextId::create(database.lastInsertedRowId()); - - tracer.end(keyValue("source context id", sourceContextId)); - - return sourceContextId; - } - - SourceId writeSourceId(SourceContextId sourceContextId, Utils::SmallStringView sourceName) - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"write source id"_t, - projectStorageCategory(), - keyValue("source context id", sourceContextId), - keyValue("source name", sourceName)}; - - insertIntoSourcesStatement.write(sourceContextId, sourceName); - - auto sourceId = SourceId::create(database.lastInsertedRowId()); - - tracer.end(keyValue("source id", sourceId)); - - return sourceId; - } - - SourceId readSourceId(SourceContextId sourceContextId, Utils::SmallStringView sourceName) - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"read source id"_t, - projectStorageCategory(), - keyValue("source context id", sourceContextId), - keyValue("source name", sourceName)}; - - auto sourceId = selectSourceIdFromSourcesBySourceContextIdAndSourceNameStatement - .template value(sourceContextId, sourceName); - - tracer.end(keyValue("source id", sourceId)); - - return sourceId; - } - - auto fetchExportedTypes(TypeId typeId) - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"fetch exported type"_t, - projectStorageCategory(), - keyValue("type id", typeId)}; - - auto typeIds = selectExportedTypesByTypeIdStatement - .template values(typeId); - - tracer.end(keyValue("type ids", typeIds)); - - return typeIds; - } - - auto fetchPropertyDeclarations(TypeId typeId) - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"fetch property declarations"_t, - projectStorageCategory(), - keyValue("type id", typeId)}; - - auto propertyDeclarations = selectPropertyDeclarationsByTypeIdStatement - .template values( - typeId); - - tracer.end(keyValue("property declarations", propertyDeclarations)); - - return propertyDeclarations; - } - - auto fetchFunctionDeclarations(TypeId typeId) - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"fetch signal declarations"_t, - projectStorageCategory(), - keyValue("type id", typeId)}; - - Storage::Synchronization::FunctionDeclarations functionDeclarations; - - auto callback = [&](Utils::SmallStringView name, - Utils::SmallStringView returnType, - FunctionDeclarationId functionDeclarationId) { - auto &functionDeclaration = functionDeclarations.emplace_back(name, returnType); - functionDeclaration.parameters = selectFunctionParameterDeclarationsStatement - .template values(functionDeclarationId); - }; - - selectFunctionDeclarationsForTypeIdWithoutSignatureStatement.readCallback(callback, typeId); - - tracer.end(keyValue("function declarations", functionDeclarations)); - - return functionDeclarations; - } - - auto fetchSignalDeclarations(TypeId typeId) - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"fetch signal declarations"_t, - projectStorageCategory(), - keyValue("type id", typeId)}; - - Storage::Synchronization::SignalDeclarations signalDeclarations; - - auto callback = [&](Utils::SmallStringView name, SignalDeclarationId signalDeclarationId) { - auto &signalDeclaration = signalDeclarations.emplace_back(name); - signalDeclaration.parameters = selectSignalParameterDeclarationsStatement - .template values(signalDeclarationId); - }; - - selectSignalDeclarationsForTypeIdWithoutSignatureStatement.readCallback(callback, typeId); - - tracer.end(keyValue("signal declarations", signalDeclarations)); - - return signalDeclarations; - } - - auto fetchEnumerationDeclarations(TypeId typeId) - { - using NanotraceHR::keyValue; - NanotraceHR::Tracer tracer{"fetch enumeration declarations"_t, - projectStorageCategory(), - keyValue("type id", typeId)}; - - Storage::Synchronization::EnumerationDeclarations enumerationDeclarations; - - auto callback = [&](Utils::SmallStringView name, - EnumerationDeclarationId enumerationDeclarationId) { - enumerationDeclarations.emplace_back( - name, - selectEnumeratorDeclarationStatement - .template values( - enumerationDeclarationId)); - }; - - selectEnumerationDeclarationsForTypeIdWithoutEnumeratorDeclarationsStatement - .readCallback(callback, typeId); - - tracer.end(keyValue("enumeration declarations", enumerationDeclarations)); - - return enumerationDeclarations; - } - - class Initializer - { - public: - Initializer(Database &database, bool isInitialized) - { - if (!isInitialized) { - auto moduleIdColumn = createModulesTable(database); - createSourceContextsTable(database); - createSourcesTable(database); - createTypesAndePropertyDeclarationsTables(database, moduleIdColumn); - createExportedTypeNamesTable(database, moduleIdColumn); - createImportedTypeNamesTable(database); - createEnumerationsTable(database); - createFunctionsTable(database); - createSignalsTable(database); - createModuleExportedImportsTable(database, moduleIdColumn); - createDocumentImportsTable(database, moduleIdColumn); - createFileStatusesTable(database); - createProjectDatasTable(database); - createPropertyEditorPathsTable(database); - createTypeAnnotionsTable(database); - } - database.setIsInitialized(true); - } - - void createSourceContextsTable(Database &database) - { - Sqlite::Table table; - table.setUseIfNotExists(true); - table.setName("sourceContexts"); - table.addColumn("sourceContextId", Sqlite::ColumnType::Integer, {Sqlite::PrimaryKey{}}); - const Sqlite::Column &sourceContextPathColumn = table.addColumn("sourceContextPath"); - - table.addUniqueIndex({sourceContextPathColumn}); - - table.initialize(database); - } - - void createSourcesTable(Database &database) - { - Sqlite::StrictTable table; - table.setUseIfNotExists(true); - table.setName("sources"); - table.addColumn("sourceId", Sqlite::StrictColumnType::Integer, {Sqlite::PrimaryKey{}}); - const auto &sourceContextIdColumn = table.addColumn( - "sourceContextId", - Sqlite::StrictColumnType::Integer, - {Sqlite::NotNull{}, - Sqlite::ForeignKey{"sourceContexts", - "sourceContextId", - Sqlite::ForeignKeyAction::NoAction, - Sqlite::ForeignKeyAction::Cascade}}); - const auto &sourceNameColumn = table.addColumn("sourceName", - Sqlite::StrictColumnType::Text); - table.addUniqueIndex({sourceContextIdColumn, sourceNameColumn}); - - table.initialize(database); - } - - void createTypesAndePropertyDeclarationsTables( - Database &database, [[maybe_unused]] const Sqlite::StrictColumn &foreignModuleIdColumn) - { - Sqlite::StrictTable typesTable; - typesTable.setUseIfNotExists(true); - typesTable.setName("types"); - typesTable.addColumn("typeId", Sqlite::StrictColumnType::Integer, {Sqlite::PrimaryKey{}}); - auto &sourceIdColumn = typesTable.addColumn("sourceId", Sqlite::StrictColumnType::Integer); - auto &typesNameColumn = typesTable.addColumn("name", Sqlite::StrictColumnType::Text); - typesTable.addColumn("traits", Sqlite::StrictColumnType::Integer); - auto &prototypeIdColumn = typesTable.addForeignKeyColumn("prototypeId", - typesTable, - Sqlite::ForeignKeyAction::NoAction, - Sqlite::ForeignKeyAction::Restrict); - typesTable.addColumn("prototypeNameId", Sqlite::StrictColumnType::Integer); - auto &extensionIdColumn = typesTable.addForeignKeyColumn("extensionId", - typesTable, - Sqlite::ForeignKeyAction::NoAction, - Sqlite::ForeignKeyAction::Restrict); - typesTable.addColumn("extensionNameId", Sqlite::StrictColumnType::Integer); - auto &defaultPropertyIdColumn = typesTable.addColumn("defaultPropertyId", - Sqlite::StrictColumnType::Integer); - typesTable.addColumn("annotationTraits", Sqlite::StrictColumnType::Integer); - typesTable.addUniqueIndex({sourceIdColumn, typesNameColumn}); - typesTable.addIndex({defaultPropertyIdColumn}); - typesTable.addIndex({prototypeIdColumn}); - typesTable.addIndex({extensionIdColumn}); - - typesTable.initialize(database); - - { - Sqlite::StrictTable propertyDeclarationTable; - propertyDeclarationTable.setUseIfNotExists(true); - propertyDeclarationTable.setName("propertyDeclarations"); - propertyDeclarationTable.addColumn("propertyDeclarationId", - Sqlite::StrictColumnType::Integer, - {Sqlite::PrimaryKey{}}); - auto &typeIdColumn = propertyDeclarationTable.addColumn("typeId"); - auto &nameColumn = propertyDeclarationTable.addColumn("name"); - auto &propertyTypeIdColumn = propertyDeclarationTable.addForeignKeyColumn( - "propertyTypeId", - typesTable, - Sqlite::ForeignKeyAction::NoAction, - Sqlite::ForeignKeyAction::Restrict); - propertyDeclarationTable.addColumn("propertyTraits", - Sqlite::StrictColumnType::Integer); - propertyDeclarationTable.addColumn("propertyImportedTypeNameId", - Sqlite::StrictColumnType::Integer); - auto &aliasPropertyDeclarationIdColumn = propertyDeclarationTable.addForeignKeyColumn( - "aliasPropertyDeclarationId", - propertyDeclarationTable, - Sqlite::ForeignKeyAction::NoAction, - Sqlite::ForeignKeyAction::Restrict); - auto &aliasPropertyDeclarationTailIdColumn = propertyDeclarationTable.addForeignKeyColumn( - "aliasPropertyDeclarationTailId", - propertyDeclarationTable, - Sqlite::ForeignKeyAction::NoAction, - Sqlite::ForeignKeyAction::Restrict); - - propertyDeclarationTable.addUniqueIndex({typeIdColumn, nameColumn}); - propertyDeclarationTable.addIndex({propertyTypeIdColumn}); - propertyDeclarationTable.addIndex({aliasPropertyDeclarationIdColumn}, - "aliasPropertyDeclarationId IS NOT NULL"); - propertyDeclarationTable.addIndex({aliasPropertyDeclarationTailIdColumn}, - "aliasPropertyDeclarationTailId IS NOT NULL"); - - propertyDeclarationTable.initialize(database); - } - } - - void createExportedTypeNamesTable(Database &database, - const Sqlite::StrictColumn &foreignModuleIdColumn) - { - Sqlite::StrictTable table; - table.setUseIfNotExists(true); - table.setName("exportedTypeNames"); - table.addColumn("exportedTypeNameId", - Sqlite::StrictColumnType::Integer, - {Sqlite::PrimaryKey{}}); - auto &moduleIdColumn = table.addForeignKeyColumn("moduleId", - foreignModuleIdColumn, - Sqlite::ForeignKeyAction::NoAction, - Sqlite::ForeignKeyAction::NoAction); - auto &nameColumn = table.addColumn("name", Sqlite::StrictColumnType::Text); - auto &typeIdColumn = table.addColumn("typeId", Sqlite::StrictColumnType::Integer); - auto &majorVersionColumn = table.addColumn("majorVersion", - Sqlite::StrictColumnType::Integer); - auto &minorVersionColumn = table.addColumn("minorVersion", - Sqlite::StrictColumnType::Integer); - - table.addUniqueIndex({moduleIdColumn, nameColumn}, - "majorVersion IS NULL AND minorVersion IS NULL"); - table.addUniqueIndex({moduleIdColumn, nameColumn, majorVersionColumn}, - "majorVersion IS NOT NULL AND minorVersion IS NULL"); - table.addUniqueIndex({moduleIdColumn, nameColumn, majorVersionColumn, minorVersionColumn}, - "majorVersion IS NOT NULL AND minorVersion IS NOT NULL"); - - table.addIndex({typeIdColumn}); - table.addIndex({moduleIdColumn, nameColumn}); - - table.initialize(database); - } - - void createImportedTypeNamesTable(Database &database) - { - Sqlite::StrictTable table; - table.setUseIfNotExists(true); - table.setName("importedTypeNames"); - table.addColumn("importedTypeNameId", - Sqlite::StrictColumnType::Integer, - {Sqlite::PrimaryKey{}}); - auto &importOrSourceIdColumn = table.addColumn("importOrSourceId"); - auto &nameColumn = table.addColumn("name", Sqlite::StrictColumnType::Text); - auto &kindColumn = table.addColumn("kind", Sqlite::StrictColumnType::Integer); - - table.addUniqueIndex({kindColumn, importOrSourceIdColumn, nameColumn}); - table.addIndex({nameColumn}); - - table.initialize(database); - } - - void createEnumerationsTable(Database &database) - { - Sqlite::StrictTable table; - table.setUseIfNotExists(true); - table.setName("enumerationDeclarations"); - table.addColumn("enumerationDeclarationId", - Sqlite::StrictColumnType::Integer, - {Sqlite::PrimaryKey{}}); - auto &typeIdColumn = table.addColumn("typeId", Sqlite::StrictColumnType::Integer); - auto &nameColumn = table.addColumn("name", Sqlite::StrictColumnType::Text); - table.addColumn("enumeratorDeclarations", Sqlite::StrictColumnType::Text); - - table.addUniqueIndex({typeIdColumn, nameColumn}); - - table.initialize(database); - } - - void createFunctionsTable(Database &database) - { - Sqlite::StrictTable table; - table.setUseIfNotExists(true); - table.setName("functionDeclarations"); - table.addColumn("functionDeclarationId", - Sqlite::StrictColumnType::Integer, - {Sqlite::PrimaryKey{}}); - auto &typeIdColumn = table.addColumn("typeId", Sqlite::StrictColumnType::Integer); - auto &nameColumn = table.addColumn("name", Sqlite::StrictColumnType::Text); - auto &signatureColumn = table.addColumn("signature", Sqlite::StrictColumnType::Text); - table.addColumn("returnTypeName"); - - table.addUniqueIndex({typeIdColumn, nameColumn, signatureColumn}); - - table.initialize(database); - } - - void createSignalsTable(Database &database) - { - Sqlite::StrictTable table; - table.setUseIfNotExists(true); - table.setName("signalDeclarations"); - table.addColumn("signalDeclarationId", - Sqlite::StrictColumnType::Integer, - {Sqlite::PrimaryKey{}}); - auto &typeIdColumn = table.addColumn("typeId", Sqlite::StrictColumnType::Integer); - auto &nameColumn = table.addColumn("name", Sqlite::StrictColumnType::Text); - auto &signatureColumn = table.addColumn("signature", Sqlite::StrictColumnType::Text); - - table.addUniqueIndex({typeIdColumn, nameColumn, signatureColumn}); - - table.initialize(database); - } - - Sqlite::StrictColumn createModulesTable(Database &database) - { - Sqlite::StrictTable table; - table.setUseIfNotExists(true); - table.setName("modules"); - auto &modelIdColumn = table.addColumn("moduleId", - Sqlite::StrictColumnType::Integer, - {Sqlite::PrimaryKey{}}); - auto &nameColumn = table.addColumn("name", Sqlite::StrictColumnType::Text); - - table.addUniqueIndex({nameColumn}); - - table.initialize(database); - - return std::move(modelIdColumn); - } - - void createModuleExportedImportsTable(Database &database, - const Sqlite::StrictColumn &foreignModuleIdColumn) - { - Sqlite::StrictTable table; - table.setUseIfNotExists(true); - table.setName("moduleExportedImports"); - table.addColumn("moduleExportedImportId", - Sqlite::StrictColumnType::Integer, - {Sqlite::PrimaryKey{}}); - auto &moduleIdColumn = table.addForeignKeyColumn("moduleId", - foreignModuleIdColumn, - Sqlite::ForeignKeyAction::NoAction, - Sqlite::ForeignKeyAction::Cascade, - Sqlite::Enforment::Immediate); - auto &sourceIdColumn = table.addColumn("exportedModuleId", - Sqlite::StrictColumnType::Integer); - table.addColumn("isAutoVersion", Sqlite::StrictColumnType::Integer); - table.addColumn("majorVersion", Sqlite::StrictColumnType::Integer); - table.addColumn("minorVersion", Sqlite::StrictColumnType::Integer); - - table.addUniqueIndex({sourceIdColumn, moduleIdColumn}); - - table.initialize(database); - } - - void createDocumentImportsTable(Database &database, - const Sqlite::StrictColumn &foreignModuleIdColumn) - { - Sqlite::StrictTable table; - table.setUseIfNotExists(true); - table.setName("documentImports"); - table.addColumn("importId", Sqlite::StrictColumnType::Integer, {Sqlite::PrimaryKey{}}); - auto &sourceIdColumn = table.addColumn("sourceId", Sqlite::StrictColumnType::Integer); - auto &moduleIdColumn = table.addForeignKeyColumn("moduleId", - foreignModuleIdColumn, - Sqlite::ForeignKeyAction::NoAction, - Sqlite::ForeignKeyAction::Cascade, - Sqlite::Enforment::Immediate); - auto &sourceModuleIdColumn = table.addForeignKeyColumn("sourceModuleId", - foreignModuleIdColumn, - Sqlite::ForeignKeyAction::NoAction, - Sqlite::ForeignKeyAction::Cascade, - Sqlite::Enforment::Immediate); - auto &kindColumn = table.addColumn("kind", Sqlite::StrictColumnType::Integer); - auto &majorVersionColumn = table.addColumn("majorVersion", - Sqlite::StrictColumnType::Integer); - auto &minorVersionColumn = table.addColumn("minorVersion", - Sqlite::StrictColumnType::Integer); - auto &parentImportIdColumn = table.addColumn("parentImportId", - Sqlite::StrictColumnType::Integer); - - table.addUniqueIndex({sourceIdColumn, - moduleIdColumn, - kindColumn, - sourceModuleIdColumn, - parentImportIdColumn}, - "majorVersion IS NULL AND minorVersion IS NULL"); - table.addUniqueIndex({sourceIdColumn, - moduleIdColumn, - kindColumn, - sourceModuleIdColumn, - majorVersionColumn, - parentImportIdColumn}, - "majorVersion IS NOT NULL AND minorVersion IS NULL"); - table.addUniqueIndex({sourceIdColumn, - moduleIdColumn, - kindColumn, - sourceModuleIdColumn, - majorVersionColumn, - minorVersionColumn, - parentImportIdColumn}, - "majorVersion IS NOT NULL AND minorVersion IS NOT NULL"); - - table.addIndex({sourceIdColumn, kindColumn}); - - table.initialize(database); - } - - void createFileStatusesTable(Database &database) - { - Sqlite::StrictTable table; - table.setUseIfNotExists(true); - table.setName("fileStatuses"); - table.addColumn("sourceId", - Sqlite::StrictColumnType::Integer, - {Sqlite::PrimaryKey{}, - Sqlite::ForeignKey{"sources", - "sourceId", - Sqlite::ForeignKeyAction::NoAction, - Sqlite::ForeignKeyAction::Cascade}}); - table.addColumn("size", Sqlite::StrictColumnType::Integer); - table.addColumn("lastModified", Sqlite::StrictColumnType::Integer); - - table.initialize(database); - } - - void createProjectDatasTable(Database &database) - { - Sqlite::StrictTable table; - table.setUseIfNotExists(true); - table.setUseWithoutRowId(true); - table.setName("projectDatas"); - auto &projectSourceIdColumn = table.addColumn("projectSourceId", - Sqlite::StrictColumnType::Integer); - auto &sourceIdColumn = table.addColumn("sourceId", Sqlite::StrictColumnType::Integer); - table.addColumn("moduleId", Sqlite::StrictColumnType::Integer); - table.addColumn("fileType", Sqlite::StrictColumnType::Integer); - - table.addPrimaryKeyContraint({projectSourceIdColumn, sourceIdColumn}); - table.addUniqueIndex({sourceIdColumn}); - - table.initialize(database); - } - - void createPropertyEditorPathsTable(Database &database) - { - Sqlite::StrictTable table; - table.setUseIfNotExists(true); - table.setUseWithoutRowId(true); - table.setName("propertyEditorPaths"); - table.addColumn("typeId", Sqlite::StrictColumnType::Integer, {Sqlite::PrimaryKey{}}); - table.addColumn("pathSourceId", Sqlite::StrictColumnType::Integer); - auto &directoryIdColumn = table.addColumn("directoryId", - Sqlite::StrictColumnType::Integer); - - table.addIndex({directoryIdColumn}); - - table.initialize(database); - } - - void createTypeAnnotionsTable(Database &database) - { - Sqlite::StrictTable table; - table.setUseIfNotExists(true); - table.setUseWithoutRowId(true); - table.setName("typeAnnotations"); - auto &typeIdColumn = table.addColumn("typeId", - Sqlite::StrictColumnType::Integer, - {Sqlite::PrimaryKey{}}); - auto &sourceIdColumn = table.addColumn("sourceId", Sqlite::StrictColumnType::Integer); - auto &directorySourceIdColumn = table.addColumn("directorySourceId", - Sqlite::StrictColumnType::Integer); - - table.addColumn("iconPath", Sqlite::StrictColumnType::Text); - table.addColumn("itemLibrary", Sqlite::StrictColumnType::Text); - table.addColumn("hints", Sqlite::StrictColumnType::Text); - - table.addUniqueIndex({sourceIdColumn, typeIdColumn}); - table.addIndex({directorySourceIdColumn}); - - table.initialize(database); - } - }; + class Initializer; public: Database &database; Sqlite::ExclusiveNonThrowingDestructorTransaction exclusiveTransaction; - Initializer initializer; + std::unique_ptr initializer; mutable ModuleCache moduleCache{ModuleStorageAdapter{*this}}; - Storage::Info::CommonTypeCache commonTypeCache_{*this}; + Storage::Info::CommonTypeCache commonTypeCache_{*this}; QVarLengthArray observers; ReadWriteStatement<1, 2> insertTypeStatement{ "INSERT OR IGNORE INTO types(sourceId, name) VALUES(?1, ?2) RETURNING typeId", database}; @@ -4564,8 +1152,10 @@ public: "INSERT INTO functionDeclarations(typeId, name, returnTypeName, signature) VALUES(?1, ?2, " "?3, ?4)", database}; - WriteStatement<2> updateFunctionDeclarationStatement{ - "UPDATE functionDeclarations SET returnTypeName=?2 WHERE functionDeclarationId=?1", database}; + WriteStatement<3> updateFunctionDeclarationStatement{"UPDATE functionDeclarations " + "SET returnTypeName=?2, signature=?3 " + "WHERE functionDeclarationId=?1", + database}; WriteStatement<1> deleteFunctionDeclarationStatement{ "DELETE FROM functionDeclarations WHERE functionDeclarationId=?", database}; mutable ReadStatement<3, 1> selectSignalDeclarationsForTypeIdStatement{ @@ -5078,6 +1668,5 @@ public: database}; }; -extern template class ProjectStorage; } // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstoragefwd.h b/src/plugins/qmldesigner/designercore/projectstorage/projectstoragefwd.h index b33c609509e..cbb7d4265ae 100644 --- a/src/plugins/qmldesigner/designercore/projectstorage/projectstoragefwd.h +++ b/src/plugins/qmldesigner/designercore/projectstorage/projectstoragefwd.h @@ -11,7 +11,6 @@ namespace QmlDesigner { class ProjectStorageInterface; class SourcePathCacheInterface; -template class ProjectStorage; template diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageinterface.h b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageinterface.h index 20d988f7aab..971e635517a 100644 --- a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageinterface.h +++ b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageinterface.h @@ -84,7 +84,7 @@ public: virtual std::optional fetchProjectData(SourceId sourceId) const = 0; virtual SourceId propertyEditorPathId(TypeId typeId) const = 0; - virtual const Storage::Info::CommonTypeCache &commonTypeCache() const = 0; + virtual const Storage::Info::CommonTypeCache &commonTypeCache() const = 0; template TypeId commonTypeId() const diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.h b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.h index e21531deea0..640969fe990 100644 --- a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.h +++ b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.h @@ -32,7 +32,6 @@ class ProjectStorageInterface; template class SourcePathCache; class FileStatusCache; -template class ProjectStorage; class QmlDocumentParserInterface; class QmlTypesParserInterface; @@ -40,7 +39,7 @@ class QmlTypesParserInterface; class ProjectStorageUpdater final : public ProjectStoragePathWatcherNotifierInterface { public: - using PathCache = SourcePathCache, NonLockingMutex>; + using PathCache = SourcePathCache; ProjectStorageUpdater(FileSystemInterface &fileSystem, ProjectStorageType &projectStorage, diff --git a/src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparser.h b/src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparser.h index b8ab4ec4b17..1b494a2f693 100644 --- a/src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparser.h +++ b/src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparser.h @@ -15,7 +15,7 @@ class SourcePathCache; class QmlDocumentParser final : public QmlDocumentParserInterface { public: - using ProjectStorage = QmlDesigner::ProjectStorage; + using ProjectStorage = QmlDesigner::ProjectStorage; using PathCache = QmlDesigner::SourcePathCache; #ifdef QDS_BUILD_QMLPARSER diff --git a/src/plugins/qmldesigner/designercore/projectstorage/qmltypesparser.h b/src/plugins/qmldesigner/designercore/projectstorage/qmltypesparser.h index 7c41925f306..4a6427501b3 100644 --- a/src/plugins/qmldesigner/designercore/projectstorage/qmltypesparser.h +++ b/src/plugins/qmldesigner/designercore/projectstorage/qmltypesparser.h @@ -4,6 +4,7 @@ #pragma once #include "nonlockingmutex.h" +#include "projectstoragefwd.h" #include "qmltypesparserinterface.h" namespace Sqlite { @@ -12,17 +13,13 @@ class Database; namespace QmlDesigner { -template -class ProjectStorage; - template class SourcePathCache; class QmlTypesParser final : public QmlTypesParserInterface { public: - using ProjectStorage = QmlDesigner::ProjectStorage; - + using ProjectStorage = QmlDesigner::ProjectStorage; #ifdef QDS_BUILD_QMLPARSER QmlTypesParser(ProjectStorage &storage) : m_storage{storage} diff --git a/src/plugins/qmldesigner/designercore/projectstorage/sourcepathcachetypes.h b/src/plugins/qmldesigner/designercore/projectstorage/sourcepathcachetypes.h index 5feaf30d006..1ef8ba7f216 100644 --- a/src/plugins/qmldesigner/designercore/projectstorage/sourcepathcachetypes.h +++ b/src/plugins/qmldesigner/designercore/projectstorage/sourcepathcachetypes.h @@ -125,4 +125,6 @@ public: SourceContextId sourceContextId; }; +using SourceNameAndSourceContextIds = std::vector; + } // namespace QmlDesigner::Cache diff --git a/src/plugins/qmldesigner/qmldesignerprojectmanager.cpp b/src/plugins/qmldesigner/qmldesignerprojectmanager.cpp index 2aadc45f24a..9602bf050fa 100644 --- a/src/plugins/qmldesigner/qmldesignerprojectmanager.cpp +++ b/src/plugins/qmldesigner/qmldesignerprojectmanager.cpp @@ -181,7 +181,7 @@ public: pathCache.sourceId(SourcePath{project->projectDirectory().toString() + "/."}).internalId())} {} Sqlite::Database database; - ProjectStorage storage{database, database.isInitialized()}; + ProjectStorage storage{database, database.isInitialized()}; PathCacheType pathCache{storage}; FileSystem fileSystem{pathCache}; FileStatusCache fileStatusCache{fileSystem}; @@ -282,7 +282,7 @@ AsynchronousImageCache &QmlDesignerProjectManager::asynchronousImageCache() } namespace { -[[maybe_unused]] ProjectStorage *dummyProjectStorage() +[[maybe_unused]] ProjectStorage *dummyProjectStorage() { return nullptr; } diff --git a/tests/unit/tests/unittests/projectstorage/projectstorage-test.cpp b/tests/unit/tests/unittests/projectstorage/projectstorage-test.cpp index d16e007cc03..4034ae58f9f 100644 --- a/tests/unit/tests/unittests/projectstorage/projectstorage-test.cpp +++ b/tests/unit/tests/unittests/projectstorage/projectstorage-test.cpp @@ -202,7 +202,7 @@ class HasNameMatcher public: using is_gtest_matcher = void; - HasNameMatcher(const QmlDesigner::ProjectStorage &storage, + HasNameMatcher(const QmlDesigner::ProjectStorage &storage, Utils::SmallStringView name) : storage{storage} , name{name} @@ -231,7 +231,7 @@ public: void DescribeNegationTo(std::ostream *os) const { *os << "is not '" << name << "'"; } private: - const QmlDesigner::ProjectStorage &storage; + const QmlDesigner::ProjectStorage &storage; Utils::SmallStringView name; }; @@ -271,7 +271,7 @@ protected: { static_database = std::make_unique(":memory:", Sqlite::JournalMode::Memory); - static_projectStorage = std::make_unique>( + static_projectStorage = std::make_unique( *static_database, static_database->isInitialized()); } @@ -1136,9 +1136,9 @@ protected: protected: inline static std::unique_ptr static_database; Sqlite::Database &database = *static_database; - inline static std::unique_ptr> static_projectStorage; - QmlDesigner::ProjectStorage &storage = *static_projectStorage; - QmlDesigner::SourcePathCache> sourcePathCache{ + inline static std::unique_ptr static_projectStorage; + QmlDesigner::ProjectStorage &storage = *static_projectStorage; + QmlDesigner::SourcePathCache sourcePathCache{ storage}; QmlDesigner::SourcePathView path1{"/path1/to"}; QmlDesigner::SourcePathView path2{"/path2/to"}; @@ -5102,7 +5102,7 @@ TEST_F(ProjectStorage, populate_module_cache) { auto id = storage.moduleId("Qml"); - QmlDesigner::ProjectStorage newStorage{database, database.isInitialized()}; + QmlDesigner::ProjectStorage newStorage{database, database.isInitialized()}; ASSERT_THAT(newStorage.moduleName(id), Eq("Qml")); } diff --git a/tests/unit/tests/unittests/projectstorage/projectstoragepathwatcher-test.cpp b/tests/unit/tests/unittests/projectstorage/projectstoragepathwatcher-test.cpp index d6ed96d0cfc..26d5af8af8a 100644 --- a/tests/unit/tests/unittests/projectstorage/projectstoragepathwatcher-test.cpp +++ b/tests/unit/tests/unittests/projectstorage/projectstoragepathwatcher-test.cpp @@ -16,7 +16,7 @@ #include namespace { -using SourcePathCache = QmlDesigner::SourcePathCache>; +using SourcePathCache = QmlDesigner::SourcePathCache; using Watcher = QmlDesigner::ProjectStoragePathWatcher, NiceMock, SourcePathCache>; @@ -43,7 +43,7 @@ protected: { static_database = std::make_unique(":memory:", Sqlite::JournalMode::Memory); - static_projectStorage = std::make_unique>( + static_projectStorage = std::make_unique( *static_database, static_database->isInitialized()); } @@ -81,8 +81,8 @@ protected: NiceMock mockFileSystem; inline static std::unique_ptr static_database; Sqlite::Database &database = *static_database; - inline static std::unique_ptr> static_projectStorage; - QmlDesigner::ProjectStorage &storage = *static_projectStorage; + inline static std::unique_ptr static_projectStorage; + QmlDesigner::ProjectStorage &storage = *static_projectStorage; SourcePathCache pathCache{storage}; Watcher watcher{pathCache, mockFileSystem, ¬ifier}; NiceMock &mockQFileSytemWatcher = watcher.fileSystemWatcher(); diff --git a/tests/unit/tests/unittests/projectstorage/projectstorageupdater-test.cpp b/tests/unit/tests/unittests/projectstorage/projectstorageupdater-test.cpp index a0ca9012629..96909857b32 100644 --- a/tests/unit/tests/unittests/projectstorage/projectstorageupdater-test.cpp +++ b/tests/unit/tests/unittests/projectstorage/projectstorageupdater-test.cpp @@ -144,7 +144,7 @@ public: { static_database = std::make_unique(":memory:", Sqlite::JournalMode::Memory); - static_projectStorage = std::make_unique>( + static_projectStorage = std::make_unique( *static_database, static_database->isInitialized()); } @@ -312,9 +312,9 @@ protected: QmlDesigner::FileStatusCache fileStatusCache{fileSystemMock}; inline static std::unique_ptr static_database; Sqlite::Database &database = *static_database; - inline static std::unique_ptr> static_projectStorage; - QmlDesigner::ProjectStorage &storage = *static_projectStorage; - QmlDesigner::SourcePathCache> sourcePathCache{ + inline static std::unique_ptr static_projectStorage; + QmlDesigner::ProjectStorage &storage = *static_projectStorage; + QmlDesigner::SourcePathCache sourcePathCache{ storage}; NiceMock patchWatcherMock; QmlDesigner::ProjectPartId projectPartId = QmlDesigner::ProjectPartId::create(1); diff --git a/tests/unit/tests/unittests/projectstorage/qmldocumentparser-test.cpp b/tests/unit/tests/unittests/projectstorage/qmldocumentparser-test.cpp index affa645330e..513fbf2ec01 100644 --- a/tests/unit/tests/unittests/projectstorage/qmldocumentparser-test.cpp +++ b/tests/unit/tests/unittests/projectstorage/qmldocumentparser-test.cpp @@ -143,8 +143,8 @@ class QmlDocumentParser : public ::testing::Test public: protected: Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory}; - QmlDesigner::ProjectStorage storage{database, database.isInitialized()}; - QmlDesigner::SourcePathCache> sourcePathCache{ + QmlDesigner::ProjectStorage storage{database, database.isInitialized()}; + QmlDesigner::SourcePathCache sourcePathCache{ storage}; QmlDesigner::QmlDocumentParser parser{storage, sourcePathCache}; Storage::Imports imports; diff --git a/tests/unit/tests/unittests/projectstorage/qmltypesparser-test.cpp b/tests/unit/tests/unittests/projectstorage/qmltypesparser-test.cpp index a42a560d07d..64f3631a68f 100644 --- a/tests/unit/tests/unittests/projectstorage/qmltypesparser-test.cpp +++ b/tests/unit/tests/unittests/projectstorage/qmltypesparser-test.cpp @@ -168,8 +168,8 @@ class QmlTypesParser : public ::testing::Test public: protected: Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory}; - QmlDesigner::ProjectStorage storage{database, database.isInitialized()}; - QmlDesigner::SourcePathCache> sourcePathCache{ + QmlDesigner::ProjectStorage storage{database, database.isInitialized()}; + QmlDesigner::SourcePathCache sourcePathCache{ storage}; QmlDesigner::QmlTypesParser parser{storage}; Storage::Imports imports; diff --git a/tests/unit/tests/unittests/projectstorage/typeannotationreader-test.cpp b/tests/unit/tests/unittests/projectstorage/typeannotationreader-test.cpp index b90a4adf1be..a614a5c7cf2 100644 --- a/tests/unit/tests/unittests/projectstorage/typeannotationreader-test.cpp +++ b/tests/unit/tests/unittests/projectstorage/typeannotationreader-test.cpp @@ -20,7 +20,7 @@ protected: { static_database = std::make_unique(":memory:", Sqlite::JournalMode::Memory); - static_projectStorage = std::make_unique>( + static_projectStorage = std::make_unique( *static_database, static_database->isInitialized()); } @@ -35,8 +35,8 @@ protected: protected: inline static std::unique_ptr static_database; Sqlite::Database &database = *static_database; - inline static std::unique_ptr> static_projectStorage; - QmlDesigner::ProjectStorage &storage = *static_projectStorage; + inline static std::unique_ptr static_projectStorage; + QmlDesigner::ProjectStorage &storage = *static_projectStorage; QmlDesigner::Storage::TypeAnnotationReader reader{storage}; QmlDesigner::SourceId sourceId = QmlDesigner::SourceId::create(33); QmlDesigner::SourceId directorySourceId = QmlDesigner::SourceId::create(77);