QmlDesigner: Use one synchronization struct

The arguments of the synchronization function are changing constantly, so
all tests have to adapted even for default arguments. To reduce this
changes now a struct is used as parameter.

Task-number: QDS-5196
Change-Id: Id3b6a530bcb8ab043eccce6526088f345d746235
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
This commit is contained in:
Marco Bubke
2021-10-20 17:34:46 +02:00
committed by Tim Jenssen
parent b4fcd05451
commit 428a9ee509
8 changed files with 1264 additions and 2019 deletions

View File

@@ -60,10 +60,7 @@ public:
moduleCache.populate(); moduleCache.populate();
} }
void synchronize(Storage::Imports imports, void synchronize(Storage::SynchronizationPackage package) override
Storage::Types types,
SourceIds sourceIds,
FileStatuses fileStatuses) override
{ {
Sqlite::ImmediateTransaction transaction{database}; Sqlite::ImmediateTransaction transaction{database};
@@ -76,19 +73,19 @@ public:
TypeIds deletedTypeIds; TypeIds deletedTypeIds;
TypeIds updatedTypeIds; TypeIds updatedTypeIds;
updatedTypeIds.reserve(types.size()); updatedTypeIds.reserve(package.types.size());
TypeIds typeIdsToBeDeleted; TypeIds typeIdsToBeDeleted;
auto sourceIdValues = Utils::transform<std::vector>(sourceIds, [](SourceId sourceId) { auto sourceIdValues = Utils::transform<std::vector>(package.sourceIds, [](SourceId sourceId) {
return &sourceId; return &sourceId;
}); });
std::sort(sourceIdValues.begin(), sourceIdValues.end()); std::sort(sourceIdValues.begin(), sourceIdValues.end());
synchronizeFileStatuses(fileStatuses, sourceIdValues); synchronizeFileStatuses(package.fileStatuses, sourceIdValues);
synchronizeImports(imports, sourceIdValues); synchronizeImports(package.imports, sourceIdValues);
synchronizeTypes(types, synchronizeTypes(package.types,
updatedTypeIds, updatedTypeIds,
insertedAliasPropertyDeclarations, insertedAliasPropertyDeclarations,
updatedAliasPropertyDeclarations, updatedAliasPropertyDeclarations,
@@ -897,6 +894,7 @@ private:
if (!type.moduleId) if (!type.moduleId)
throw QmlDesigner::ModuleDoesNotExists{}; throw QmlDesigner::ModuleDoesNotExists{};
try {
if (type.version) { if (type.version) {
insertExportedTypeNamesWithVersionStatement.write(&type.moduleId, insertExportedTypeNamesWithVersionStatement.write(&type.moduleId,
type.name, type.name,
@@ -914,6 +912,9 @@ private:
type.name, type.name,
&type.typeId); &type.typeId);
} }
} catch (const Sqlite::ConstraintPreventsModification &) {
throw QmlDesigner::ModuleDoesNotExists{};
}
}; };
auto update = [&](const Storage::ExportedTypeView &view, const Storage::ExportedType &type) { auto update = [&](const Storage::ExportedTypeView &view, const Storage::ExportedType &type) {
@@ -1858,8 +1859,7 @@ private:
auto &moduleIdColumn = table.addForeignKeyColumn("moduleId", auto &moduleIdColumn = table.addForeignKeyColumn("moduleId",
foreignModuleIdColumn, foreignModuleIdColumn,
Sqlite::ForeignKeyAction::NoAction, Sqlite::ForeignKeyAction::NoAction,
Sqlite::ForeignKeyAction::NoAction, Sqlite::ForeignKeyAction::NoAction);
Sqlite::Enforment::Deferred);
auto &nameColumn = table.addColumn("name"); auto &nameColumn = table.addColumn("name");
auto &typeIdColumn = table.addColumn("typeId"); auto &typeIdColumn = table.addColumn("typeId");
auto &majorVersionColumn = table.addColumn("majorVersion"); auto &majorVersionColumn = table.addColumn("majorVersion");

View File

@@ -33,11 +33,7 @@ namespace QmlDesigner {
class ProjectStorageInterface class ProjectStorageInterface
{ {
public: public:
virtual void synchronize(Storage::Imports imports, virtual void synchronize(Storage::SynchronizationPackage package) = 0;
Storage::Types types,
SourceIds sourceIds,
FileStatuses fileStatuses)
= 0;
virtual ModuleId moduleId(Utils::SmallStringView name) = 0; virtual ModuleId moduleId(Utils::SmallStringView name) = 0;

View File

@@ -25,6 +25,7 @@
#pragma once #pragma once
#include "filestatus.h"
#include "projectstorageids.h" #include "projectstorageids.h"
#include <utils/smallstring.h> #include <utils/smallstring.h>
@@ -726,4 +727,34 @@ public:
using ProjectDatas = std::vector<ProjectData>; using ProjectDatas = std::vector<ProjectData>;
class SynchronizationPackage
{
public:
SynchronizationPackage() = default;
SynchronizationPackage(Imports imports, Types types, SourceIds sourceIds)
: imports{std::move(imports)}
, types{std::move(types)}
, sourceIds(std::move(sourceIds))
{}
SynchronizationPackage(Types types)
: types{std::move(types)}
{}
SynchronizationPackage(SourceIds sourceIds)
: sourceIds(std::move(sourceIds))
{}
SynchronizationPackage(SourceIds sourceIds, FileStatuses fileStatuses)
: sourceIds(std::move(sourceIds))
, fileStatuses(std::move(fileStatuses))
{}
public:
Imports imports;
Types types;
SourceIds sourceIds;
FileStatuses fileStatuses;
};
} // namespace QmlDesigner::Storage } // namespace QmlDesigner::Storage

View File

@@ -52,40 +52,34 @@ ComponentReferences createComponentReferences(const QMultiHash<QString, QmlDirPa
void ProjectUpdater::update() void ProjectUpdater::update()
{ {
Storage::Imports imports; Storage::SynchronizationPackage package;
Storage::Types types;
SourceIds sourceIds;
FileStatuses fileStatuses;
for (const QString &qmldirPath : m_projectManager.qtQmlDirs()) { for (const QString &qmldirPath : m_projectManager.qtQmlDirs()) {
SourcePath qmldirSourcePath{qmldirPath}; SourcePath qmldirSourcePath{qmldirPath};
SourceId qmlDirSourceId = m_pathCache.sourceId(qmldirSourcePath); SourceId qmlDirSourceId = m_pathCache.sourceId(qmldirSourcePath);
switch (fileState(qmlDirSourceId, fileStatuses)) { switch (fileState(qmlDirSourceId, package.fileStatuses)) {
case FileState::Changed: { case FileState::Changed: {
QmlDirParser parser; QmlDirParser parser;
parser.parse(m_fileSystem.contentAsQString(qmldirPath)); parser.parse(m_fileSystem.contentAsQString(qmldirPath));
sourceIds.push_back(qmlDirSourceId); package.sourceIds.push_back(qmlDirSourceId);
SourceContextId directoryId = m_pathCache.sourceContextId(qmlDirSourceId); SourceContextId directoryId = m_pathCache.sourceContextId(qmlDirSourceId);
Utils::PathString moduleName{parser.typeNamespace()}; Utils::PathString moduleName{parser.typeNamespace()};
ModuleId moduleId = m_projectStorage.moduleId(moduleName); ModuleId moduleId = m_projectStorage.moduleId(moduleName);
parseTypeInfos(parser.typeInfos(), directoryId, imports, types, sourceIds, fileStatuses); parseTypeInfos(parser.typeInfos(), directoryId, package);
parseQmlComponents(createComponentReferences(parser.components()), parseQmlComponents(createComponentReferences(parser.components()),
directoryId, directoryId,
moduleId, moduleId,
imports, package);
types,
sourceIds,
fileStatuses);
break; break;
} }
case FileState::NotChanged: { case FileState::NotChanged: {
auto qmlProjectDatas = m_projectStorage.fetchProjectDatas(qmlDirSourceId); auto qmlProjectDatas = m_projectStorage.fetchProjectDatas(qmlDirSourceId);
parseTypeInfos(qmlProjectDatas, imports, types, sourceIds, fileStatuses); parseTypeInfos(qmlProjectDatas, package);
break; break;
} }
case FileState::NotExists: { case FileState::NotExists: {
@@ -95,20 +89,14 @@ void ProjectUpdater::update()
} }
} }
m_projectStorage.synchronize(std::move(imports), m_projectStorage.synchronize(std::move(package));
std::move(types),
std::move(sourceIds),
std::move(fileStatuses));
} }
void ProjectUpdater::pathsWithIdsChanged(const std::vector<IdPaths> &idPaths) {} void ProjectUpdater::pathsWithIdsChanged(const std::vector<IdPaths> &idPaths) {}
void ProjectUpdater::parseTypeInfos(const QStringList &typeInfos, void ProjectUpdater::parseTypeInfos(const QStringList &typeInfos,
SourceContextId directoryId, SourceContextId directoryId,
Storage::Imports &imports, Storage::SynchronizationPackage &package)
Storage::Types &types,
SourceIds &sourceIds,
FileStatuses &fileStatuses)
{ {
QString directory{m_pathCache.sourceContextPath(directoryId)}; QString directory{m_pathCache.sourceContextPath(directoryId)};
@@ -118,44 +106,35 @@ void ProjectUpdater::parseTypeInfos(const QStringList &typeInfos,
Storage::ProjectData projectData{ModuleId{}, sourceId}; Storage::ProjectData projectData{ModuleId{}, sourceId};
parseTypeInfo(projectData, qmltypesPath, imports, types, sourceIds, fileStatuses); parseTypeInfo(projectData, qmltypesPath, package);
} }
} }
void ProjectUpdater::parseTypeInfos(const Storage::ProjectDatas &projectDatas, void ProjectUpdater::parseTypeInfos(const Storage::ProjectDatas &projectDatas,
Storage::Imports &imports, Storage::SynchronizationPackage &package)
Storage::Types &types,
SourceIds &sourceIds,
FileStatuses &fileStatuses)
{ {
for (const Storage::ProjectData &projectData : projectDatas) { for (const Storage::ProjectData &projectData : projectDatas) {
QString qmltypesPath = m_pathCache.sourcePath(projectData.sourceId).toQString(); QString qmltypesPath = m_pathCache.sourcePath(projectData.sourceId).toQString();
parseTypeInfo(projectData, qmltypesPath, imports, types, sourceIds, fileStatuses); parseTypeInfo(projectData, qmltypesPath, package);
} }
} }
void ProjectUpdater::parseTypeInfo(const Storage::ProjectData &projectData, void ProjectUpdater::parseTypeInfo(const Storage::ProjectData &projectData,
const QString &qmltypesPath, const QString &qmltypesPath,
Storage::Imports &imports, Storage::SynchronizationPackage &package)
Storage::Types &types,
SourceIds &sourceIds,
FileStatuses &fileStatuses)
{ {
if (fileState(projectData.sourceId, fileStatuses) == FileState::Changed) { if (fileState(projectData.sourceId, package.fileStatuses) == FileState::Changed) {
sourceIds.push_back(projectData.sourceId); package.sourceIds.push_back(projectData.sourceId);
const auto content = m_fileSystem.contentAsQString(qmltypesPath); const auto content = m_fileSystem.contentAsQString(qmltypesPath);
m_qmlTypesParser.parse(content, imports, types, projectData); m_qmlTypesParser.parse(content, package.imports, package.types, projectData);
} }
} }
void ProjectUpdater::parseQmlComponents(ComponentReferences components, void ProjectUpdater::parseQmlComponents(ComponentReferences components,
SourceContextId directoryId, SourceContextId directoryId,
ModuleId moduleId, ModuleId moduleId,
Storage::Imports &imports, Storage::SynchronizationPackage &package)
Storage::Types &types,
SourceIds &sourceIds,
FileStatuses &fileStatuses)
{ {
std::sort(components.begin(), components.end(), [](auto &&first, auto &&second) { std::sort(components.begin(), components.end(), [](auto &&first, auto &&second) {
return std::tie(first.get().typeName, first.get().majorVersion, first.get().minorVersion) return std::tie(first.get().typeName, first.get().majorVersion, first.get().minorVersion)
@@ -175,13 +154,13 @@ void ProjectUpdater::parseQmlComponents(ComponentReferences components,
Utils::SmallString fileName{component.fileName}; Utils::SmallString fileName{component.fileName};
SourceId sourceId = m_pathCache.sourceId(directoryId, fileName); SourceId sourceId = m_pathCache.sourceId(directoryId, fileName);
if (fileState(sourceId, fileStatuses) != FileState::Changed) if (fileState(sourceId, package.fileStatuses) != FileState::Changed)
continue; continue;
sourceIds.push_back(sourceId); package.sourceIds.push_back(sourceId);
const auto content = m_fileSystem.contentAsQString(directory + "/" + component.fileName); const auto content = m_fileSystem.contentAsQString(directory + "/" + component.fileName);
auto type = m_qmlDocumentParser.parse(content, imports); auto type = m_qmlDocumentParser.parse(content, package.imports);
type.typeName = fileName; type.typeName = fileName;
type.accessSemantics = Storage::TypeAccessSemantics::Reference; type.accessSemantics = Storage::TypeAccessSemantics::Reference;
@@ -191,7 +170,7 @@ void ProjectUpdater::parseQmlComponents(ComponentReferences components,
Utils::SmallString{component.typeName}, Utils::SmallString{component.typeName},
Storage::Version{component.majorVersion, component.minorVersion}}); Storage::Version{component.majorVersion, component.minorVersion}});
types.push_back(std::move(type)); package.types.push_back(std::move(type));
} }
} }

View File

@@ -88,28 +88,16 @@ private:
void parseTypeInfos(const QStringList &typeInfos, void parseTypeInfos(const QStringList &typeInfos,
SourceContextId directoryId, SourceContextId directoryId,
Storage::Imports &imports, Storage::SynchronizationPackage &package);
Storage::Types &types,
SourceIds &sourceIds,
FileStatuses &fileStatuses);
void parseTypeInfos(const Storage::ProjectDatas &projectDatas, void parseTypeInfos(const Storage::ProjectDatas &projectDatas,
Storage::Imports &imports, Storage::SynchronizationPackage &package);
Storage::Types &types,
SourceIds &sourceIds,
FileStatuses &fileStatuses);
void parseTypeInfo(const Storage::ProjectData &projectData, void parseTypeInfo(const Storage::ProjectData &projectData,
const QString &qmltypesPath, const QString &qmltypesPath,
Storage::Imports &imports, Storage::SynchronizationPackage &package);
Storage::Types &types,
SourceIds &sourceIds,
FileStatuses &fileStatuses);
void parseQmlComponents(ComponentReferences components, void parseQmlComponents(ComponentReferences components,
SourceContextId directoryId, SourceContextId directoryId,
ModuleId moduleId, ModuleId moduleId,
Storage::Imports &imports, Storage::SynchronizationPackage &package);
Storage::Types &types,
SourceIds &sourceIds,
FileStatuses &fileStatuses);
FileState fileState(SourceId sourceId, FileStatuses &fileStatuses) const; FileState fileState(SourceId sourceId, FileStatuses &fileStatuses) const;

File diff suppressed because it is too large Load Diff

View File

@@ -36,13 +36,7 @@
class ProjectStorageMock : public QmlDesigner::ProjectStorageInterface class ProjectStorageMock : public QmlDesigner::ProjectStorageInterface
{ {
public: public:
MOCK_METHOD(void, MOCK_METHOD(void, synchronize, (QmlDesigner::Storage::SynchronizationPackage package), (override));
synchronize,
(QmlDesigner::Storage::Imports imports,
QmlDesigner::Storage::Types types,
QmlDesigner::SourceIds sourceIds,
QmlDesigner::FileStatuses fileStatuses),
(override));
MOCK_METHOD(QmlDesigner::ModuleId, moduleId, (Utils::SmallStringView), (override)); MOCK_METHOD(QmlDesigner::ModuleId, moduleId, (Utils::SmallStringView), (override));

View File

@@ -47,6 +47,7 @@ using QmlDesigner::SourceId;
using QmlDesigner::Storage::TypeAccessSemantics; using QmlDesigner::Storage::TypeAccessSemantics;
namespace Storage = QmlDesigner::Storage; namespace Storage = QmlDesigner::Storage;
using QmlDesigner::IdPaths; using QmlDesigner::IdPaths;
using QmlDesigner::Storage::SynchronizationPackage;
using QmlDesigner::Storage::Version; using QmlDesigner::Storage::Version;
MATCHER_P4(IsStorageType, MATCHER_P4(IsStorageType,
@@ -106,6 +107,14 @@ MATCHER_P3(IsFileStatus,
&& fileStatus.lastModified == lastModified; && fileStatus.lastModified == lastModified;
} }
MATCHER(PackageIsEmpty, std::string(negation ? "isn't empty" : "is empty"))
{
const Storage::SynchronizationPackage &package = arg;
return package.imports.empty() && package.types.empty() && package.fileStatuses.empty()
&& package.sourceIds.empty();
}
class ProjectStorageUpdater : public testing::Test class ProjectStorageUpdater : public testing::Test
{ {
public: public:
@@ -317,7 +326,7 @@ TEST_F(ProjectStorageUpdater, SynchronizeIsEmptyForNoChange)
ON_CALL(projectStorageMock, fetchFileStatus(Eq(qmlDirPathSourceId))) ON_CALL(projectStorageMock, fetchFileStatus(Eq(qmlDirPathSourceId)))
.WillByDefault(Return(FileStatus{qmlDirPathSourceId, 21, 421})); .WillByDefault(Return(FileStatus{qmlDirPathSourceId, 21, 421}));
EXPECT_CALL(projectStorageMock, synchronize(IsEmpty(), IsEmpty(), IsEmpty(), IsEmpty())); EXPECT_CALL(projectStorageMock, synchronize(PackageIsEmpty()));
updater.update(); updater.update();
} }
@@ -338,11 +347,14 @@ TEST_F(ProjectStorageUpdater, SynchronizeQmlTypes)
EXPECT_CALL(projectStorageMock, moduleId(Eq("Example"))); EXPECT_CALL(projectStorageMock, moduleId(Eq("Example")));
EXPECT_CALL(projectStorageMock, EXPECT_CALL(projectStorageMock,
synchronize(ElementsAre(import), synchronize(
ElementsAre(Eq(objectType)), AllOf(Field(&SynchronizationPackage::imports, ElementsAre(import)),
UnorderedElementsAre(qmlDirPathSourceId, qmltypesPathSourceId), Field(&SynchronizationPackage::types, ElementsAre(Eq(objectType))),
Field(&SynchronizationPackage::sourceIds,
UnorderedElementsAre(qmlDirPathSourceId, qmltypesPathSourceId)),
Field(&SynchronizationPackage::fileStatuses,
UnorderedElementsAre(IsFileStatus(qmlDirPathSourceId, 21, 421), UnorderedElementsAre(IsFileStatus(qmlDirPathSourceId, 21, 421),
IsFileStatus(qmltypesPathSourceId, 21, 421)))); IsFileStatus(qmltypesPathSourceId, 21, 421))))));
updater.update(); updater.update();
} }
@@ -361,7 +373,7 @@ TEST_F(ProjectStorageUpdater, SynchronizeQmlTypesAreEmptyIfFileDoesNotChanged)
ON_CALL(fileSystemMock, fileStatus(Eq(qmlDirPathSourceId))) ON_CALL(fileSystemMock, fileStatus(Eq(qmlDirPathSourceId)))
.WillByDefault(Return(FileStatus{qmlDirPathSourceId, 2, 421})); .WillByDefault(Return(FileStatus{qmlDirPathSourceId, 2, 421}));
EXPECT_CALL(projectStorageMock, synchronize(IsEmpty(), IsEmpty(), IsEmpty(), IsEmpty())); EXPECT_CALL(projectStorageMock, synchronize(PackageIsEmpty()));
updater.update(); updater.update();
} }
@@ -410,7 +422,9 @@ TEST_F(ProjectStorageUpdater, SynchronizeQmlDocuments)
EXPECT_CALL( EXPECT_CALL(
projectStorageMock, projectStorageMock,
synchronize(UnorderedElementsAre(import1, import2, import3), synchronize(AllOf(
Field(&SynchronizationPackage::imports, UnorderedElementsAre(import1, import2, import3)),
Field(&SynchronizationPackage::types,
UnorderedElementsAre( UnorderedElementsAre(
AllOf(IsStorageType("First.qml", AllOf(IsStorageType("First.qml",
Storage::ImportedType{"Object"}, Storage::ImportedType{"Object"},
@@ -429,15 +443,17 @@ TEST_F(ProjectStorageUpdater, SynchronizeQmlDocuments)
TypeAccessSemantics::Reference, TypeAccessSemantics::Reference,
qmlDocumentSourceId3), qmlDocumentSourceId3),
Field(&Storage::Type::exportedTypes, Field(&Storage::Type::exportedTypes,
ElementsAre(IsExportedType(exampleModuleId, "SecondType", 2, 2))))), ElementsAre(IsExportedType(exampleModuleId, "SecondType", 2, 2)))))),
Field(&SynchronizationPackage::sourceIds,
UnorderedElementsAre(qmlDirPathSourceId, UnorderedElementsAre(qmlDirPathSourceId,
qmlDocumentSourceId1, qmlDocumentSourceId1,
qmlDocumentSourceId2, qmlDocumentSourceId2,
qmlDocumentSourceId3), qmlDocumentSourceId3)),
Field(&SynchronizationPackage::fileStatuses,
UnorderedElementsAre(IsFileStatus(qmlDirPathSourceId, 21, 421), UnorderedElementsAre(IsFileStatus(qmlDirPathSourceId, 21, 421),
IsFileStatus(qmlDocumentSourceId1, 22, 12), IsFileStatus(qmlDocumentSourceId1, 22, 12),
IsFileStatus(qmlDocumentSourceId2, 22, 13), IsFileStatus(qmlDocumentSourceId2, 22, 13),
IsFileStatus(qmlDocumentSourceId3, 22, 14)))); IsFileStatus(qmlDocumentSourceId3, 22, 14))))));
updater.update(); updater.update();
} }
@@ -452,7 +468,9 @@ TEST_F(ProjectStorageUpdater, SynchronizeQmlDocumentsDontUpdateIfUpToDate)
EXPECT_CALL( EXPECT_CALL(
projectStorageMock, projectStorageMock,
synchronize(UnorderedElementsAre(import1, import2), synchronize(AllOf(
Field(&SynchronizationPackage::imports, UnorderedElementsAre(import1, import2)),
Field(&SynchronizationPackage::types,
UnorderedElementsAre( UnorderedElementsAre(
AllOf(IsStorageType("First.qml", AllOf(IsStorageType("First.qml",
Storage::ImportedType{"Object"}, Storage::ImportedType{"Object"},
@@ -465,11 +483,13 @@ TEST_F(ProjectStorageUpdater, SynchronizeQmlDocumentsDontUpdateIfUpToDate)
TypeAccessSemantics::Reference, TypeAccessSemantics::Reference,
qmlDocumentSourceId2), qmlDocumentSourceId2),
Field(&Storage::Type::exportedTypes, Field(&Storage::Type::exportedTypes,
ElementsAre(IsExportedType(exampleModuleId, "FirstType", 2, 2))))), ElementsAre(IsExportedType(exampleModuleId, "FirstType", 2, 2)))))),
UnorderedElementsAre(qmlDirPathSourceId, qmlDocumentSourceId1, qmlDocumentSourceId2), Field(&SynchronizationPackage::sourceIds,
UnorderedElementsAre(qmlDirPathSourceId, qmlDocumentSourceId1, qmlDocumentSourceId2)),
Field(&SynchronizationPackage::fileStatuses,
UnorderedElementsAre(IsFileStatus(qmlDirPathSourceId, 21, 421), UnorderedElementsAre(IsFileStatus(qmlDirPathSourceId, 21, 421),
IsFileStatus(qmlDocumentSourceId1, 22, 12), IsFileStatus(qmlDocumentSourceId1, 22, 12),
IsFileStatus(qmlDocumentSourceId2, 22, 13)))); IsFileStatus(qmlDocumentSourceId2, 22, 13))))));
updater.update(); updater.update();
} }