forked from qt-creator/qt-creator
QmlDesigner: Add Import Synchronization
Task-number: QDS-4460 Change-Id: Icd419baa7881fe882539f10d335ab6b3d36bc7b5 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
@@ -82,7 +82,8 @@ enum class BasicIdType {
|
||||
StorageCacheIndex,
|
||||
FunctionDeclaration,
|
||||
SignalDeclaration,
|
||||
EnumerationDeclaration
|
||||
EnumerationDeclaration,
|
||||
Import
|
||||
};
|
||||
|
||||
using TypeId = BasicId<BasicIdType::Type>;
|
||||
@@ -106,4 +107,7 @@ using SourceContextIds = std::vector<SourceContextId>;
|
||||
using SourceId = BasicId<BasicIdType::SourceId, int>;
|
||||
using SourceIds = std::vector<SourceId>;
|
||||
|
||||
using ImportId = BasicId<BasicIdType::Import>;
|
||||
using ImportIds = std::vector<ImportId>;
|
||||
|
||||
} // namespace QmlDesigner
|
||||
|
@@ -75,6 +75,16 @@ public:
|
||||
transaction.commit();
|
||||
}
|
||||
|
||||
void synchronizeImports(Storage::Imports imports)
|
||||
{
|
||||
Sqlite::ImmediateTransaction transaction{database};
|
||||
|
||||
synchronizeImportsAndUpdatesImportIds(imports);
|
||||
synchronizeImportDependencies(createSortedImportDependecies(imports));
|
||||
|
||||
transaction.commit();
|
||||
}
|
||||
|
||||
TypeId upsertType(Utils::SmallStringView name,
|
||||
TypeId prototypeId,
|
||||
Storage::TypeAccessSemantics accessSemantics,
|
||||
@@ -255,7 +265,149 @@ public:
|
||||
return writeSourceId(sourceContextId, sourceName);
|
||||
}
|
||||
|
||||
auto fetchAllImports() const
|
||||
{
|
||||
Storage::Imports imports;
|
||||
imports.reserve(128);
|
||||
|
||||
auto callback = [&](Utils::SmallStringView name, int version, int sourceId, long long importId) {
|
||||
auto &lastImport = imports.emplace_back(name,
|
||||
Storage::VersionNumber{version},
|
||||
SourceId{sourceId});
|
||||
|
||||
lastImport.importDependencies = selectImportsForThatDependentOnThisImportIdStatement
|
||||
.template values<Storage::BasicImport>(6, importId);
|
||||
|
||||
return Sqlite::CallbackControl::Continue;
|
||||
};
|
||||
|
||||
selectAllImportsStatement.readCallbackWithTransaction(callback);
|
||||
|
||||
return imports;
|
||||
}
|
||||
|
||||
private:
|
||||
struct ImportDependency
|
||||
{
|
||||
ImportDependency(ImportId id, ImportId dependencyId)
|
||||
: id{id}
|
||||
, dependencyId{dependencyId}
|
||||
{}
|
||||
|
||||
ImportDependency(long long id, long long dependencyId)
|
||||
: id{id}
|
||||
, dependencyId{dependencyId}
|
||||
{}
|
||||
|
||||
ImportId id;
|
||||
ImportId dependencyId;
|
||||
|
||||
friend bool operator<(ImportDependency first, ImportDependency second)
|
||||
{
|
||||
return std::tie(first.id, first.dependencyId) < std::tie(second.id, second.dependencyId);
|
||||
}
|
||||
|
||||
friend bool operator==(ImportDependency first, ImportDependency second)
|
||||
{
|
||||
return first.id == second.id && first.dependencyId == second.dependencyId;
|
||||
}
|
||||
};
|
||||
|
||||
void synchronizeImportsAndUpdatesImportIds(Storage::Imports &imports)
|
||||
{
|
||||
auto compareKey = [](auto &&first, auto &&second) {
|
||||
auto nameCompare = Sqlite::compare(first.name, second.name);
|
||||
|
||||
if (nameCompare != 0)
|
||||
return nameCompare;
|
||||
|
||||
return first.version.version - second.version.version;
|
||||
};
|
||||
|
||||
std::sort(imports.begin(), imports.end(), [&](auto &&first, auto &&second) {
|
||||
return compareKey(first, second) < 0;
|
||||
});
|
||||
|
||||
auto range = selectAllImportsStatement.template range<Storage::ImportView>();
|
||||
|
||||
auto insert = [&](Storage::Import &import) {
|
||||
import.importId = insertImportStatement.template value<ImportId>(import.name,
|
||||
import.version.version,
|
||||
&import.sourceId);
|
||||
};
|
||||
|
||||
auto update = [&](const Storage::ImportView &importView, Storage::Import &import) {
|
||||
if (importView.sourceId.id != import.sourceId.id)
|
||||
updateImportStatement.write(&importView.importId, &import.sourceId);
|
||||
import.importId = importView.importId;
|
||||
};
|
||||
|
||||
auto remove = [&](const Storage::ImportView &importView) {
|
||||
deleteImportStatement.write(&importView.importId);
|
||||
};
|
||||
|
||||
Sqlite::insertUpdateDelete(range, imports, compareKey, insert, update, remove);
|
||||
}
|
||||
|
||||
std::vector<ImportDependency> createSortedImportDependecies(const Storage::Imports &imports) const
|
||||
{
|
||||
std::vector<ImportDependency> importDependecies;
|
||||
importDependecies.reserve(imports.size() * 5);
|
||||
|
||||
for (const Storage::Import &import : imports) {
|
||||
for (const Storage::BasicImport &importDependency : import.importDependencies) {
|
||||
auto importIdForDependency = fetchImportId(importDependency);
|
||||
|
||||
if (!importIdForDependency)
|
||||
throw ImportDoesNotExists{};
|
||||
|
||||
importDependecies.emplace_back(import.importId, importIdForDependency);
|
||||
}
|
||||
}
|
||||
|
||||
std::sort(importDependecies.begin(), importDependecies.end());
|
||||
importDependecies.erase(std::unique(importDependecies.begin(), importDependecies.end()),
|
||||
importDependecies.end());
|
||||
|
||||
return importDependecies;
|
||||
}
|
||||
|
||||
void synchronizeImportDependencies(const std::vector<ImportDependency> &importDependecies)
|
||||
{
|
||||
auto compareKey = [](ImportDependency first, ImportDependency second) {
|
||||
auto idCompare = first.id.id - second.id.id;
|
||||
|
||||
if (idCompare != 0)
|
||||
return idCompare;
|
||||
|
||||
return first.dependencyId.id - second.dependencyId.id;
|
||||
};
|
||||
|
||||
auto range = selectAllImportDependenciesStatement.template range<ImportDependency>();
|
||||
|
||||
auto insert = [&](ImportDependency dependency) {
|
||||
insertImportDependencyStatement.write(&dependency.id, &dependency.dependencyId);
|
||||
};
|
||||
|
||||
auto update = [](ImportDependency, ImportDependency) {};
|
||||
|
||||
auto remove = [&](ImportDependency dependency) {
|
||||
deleteImportDependencyStatement.write(&dependency.id, &dependency.dependencyId);
|
||||
};
|
||||
|
||||
Sqlite::insertUpdateDelete(range, importDependecies, compareKey, insert, update, remove);
|
||||
}
|
||||
|
||||
ImportId fetchImportId(const Storage::BasicImport &import) const
|
||||
{
|
||||
if (import.version) {
|
||||
return selectImportIdByNameAndVersionStatement
|
||||
.template value<ImportId>(import.name, import.version.version);
|
||||
}
|
||||
|
||||
return selectImportIdByNameStatement.template value<ImportId>(import.name);
|
||||
}
|
||||
|
||||
void deleteNotUpdatedTypes(const TypeIds &updatedTypeIds, const SourceIds &sourceIds)
|
||||
{
|
||||
auto updatedTypeIdValues = Utils::transform<std::vector>(updatedTypeIds, [](TypeId typeId) {
|
||||
@@ -638,6 +790,8 @@ private:
|
||||
if (!isInitialized) {
|
||||
Sqlite::ExclusiveTransaction transaction{database};
|
||||
|
||||
createImportsTable(database);
|
||||
createImportDependeciesTable(database);
|
||||
createSourceContextsTable(database);
|
||||
createSourcesTable(database);
|
||||
createTypesTable(database);
|
||||
@@ -791,6 +945,35 @@ private:
|
||||
|
||||
table.initialize(database);
|
||||
}
|
||||
|
||||
void createImportsTable(Database &database)
|
||||
{
|
||||
Sqlite::Table table;
|
||||
table.setUseIfNotExists(true);
|
||||
table.setName("imports");
|
||||
table.addColumn("importId", Sqlite::ColumnType::Integer, {Sqlite::PrimaryKey{}});
|
||||
auto &nameColumn = table.addColumn("name");
|
||||
auto &versionColumn = table.addColumn("version");
|
||||
table.addColumn("sourceId");
|
||||
|
||||
table.addUniqueIndex({nameColumn, versionColumn});
|
||||
|
||||
table.initialize(database);
|
||||
}
|
||||
|
||||
void createImportDependeciesTable(Database &database)
|
||||
{
|
||||
Sqlite::Table table;
|
||||
table.setUseIfNotExists(true);
|
||||
table.setUseWithoutRowId(true);
|
||||
table.setName("importDependencies");
|
||||
auto &importIdColumn = table.addColumn("importId");
|
||||
auto &parentImportIdColumn = table.addColumn("parentImportId");
|
||||
|
||||
table.addPrimaryKeyContraint({importIdColumn, parentImportIdColumn});
|
||||
|
||||
table.initialize(database);
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
@@ -974,6 +1157,28 @@ public:
|
||||
database};
|
||||
WriteStatement deleteEnumerationDeclarationStatement{
|
||||
"DELETE FROM enumerationDeclarations WHERE enumerationDeclarationId=?", database};
|
||||
mutable ReadWriteStatement<1> insertImportStatement{
|
||||
"INSERT INTO imports(name, version, sourceId) VALUES(?1, ?2, ?3) RETURNING importId",
|
||||
database};
|
||||
WriteStatement updateImportStatement{"UPDATE imports SET sourceId=?2 WHERE importId=?1", database};
|
||||
WriteStatement deleteImportStatement{"DELETE FROM imports WHERE importId=?", database};
|
||||
mutable ReadStatement<1> selectImportIdByNameStatement{
|
||||
"SELECT importId FROM imports WHERE name=? ORDER BY version DESC LIMIT 1", database};
|
||||
mutable ReadStatement<1> selectImportIdByNameAndVersionStatement{
|
||||
"SELECT importId FROM imports WHERE name=? AND version=?", database};
|
||||
mutable ReadStatement<4> selectAllImportsStatement{
|
||||
"SELECT name, version, sourceId, importId FROM imports ORDER BY name, version", database};
|
||||
WriteStatement insertImportDependencyStatement{
|
||||
"INSERT INTO importDependencies(importId, parentImportId) VALUES(?1, ?2)", database};
|
||||
WriteStatement deleteImportDependencyStatement{
|
||||
"DELETE FROM importDependencies WHERE importId=?1 AND parentImportId=?2", database};
|
||||
mutable ReadStatement<2> selectAllImportDependenciesStatement{
|
||||
"SELECT importId, parentImportId FROM importDependencies ORDER BY importId, parentImportId",
|
||||
database};
|
||||
mutable ReadStatement<2> selectImportsForThatDependentOnThisImportIdStatement{
|
||||
"SELECT name, version FROM importDependencies JOIN imports ON "
|
||||
"importDependencies.parentImportId = imports.importId WHERE importDependencies.importId=?",
|
||||
database};
|
||||
};
|
||||
|
||||
} // namespace QmlDesigner
|
||||
|
@@ -71,4 +71,10 @@ public:
|
||||
const char *what() const noexcept override { return "The source id is invalid!"; }
|
||||
};
|
||||
|
||||
class ImportDoesNotExists : std::exception
|
||||
{
|
||||
public:
|
||||
const char *what() const noexcept override { return "The simport does not exist!"; }
|
||||
};
|
||||
|
||||
} // namespace QmlDesigner
|
||||
|
@@ -60,7 +60,7 @@ public:
|
||||
: version{version}
|
||||
{}
|
||||
|
||||
explicit operator bool() { return version >= 0; }
|
||||
explicit operator bool() const { return version >= 0; }
|
||||
|
||||
friend bool operator==(VersionNumber first, VersionNumber second) noexcept
|
||||
{
|
||||
@@ -432,4 +432,84 @@ public:
|
||||
|
||||
using Types = std::vector<Type>;
|
||||
|
||||
class BasicImport
|
||||
{
|
||||
public:
|
||||
explicit BasicImport(Utils::SmallStringView name, VersionNumber version = VersionNumber{})
|
||||
: name{name}
|
||||
, version{version}
|
||||
{}
|
||||
|
||||
explicit BasicImport(Utils::SmallStringView name, int version)
|
||||
: name{name}
|
||||
, version{version}
|
||||
{}
|
||||
|
||||
friend bool operator==(const BasicImport &first, const BasicImport &second)
|
||||
{
|
||||
return first.name == second.name && first.version == second.version;
|
||||
}
|
||||
|
||||
public:
|
||||
Utils::PathString name;
|
||||
VersionNumber version;
|
||||
};
|
||||
|
||||
using BasicImports = std::vector<BasicImport>;
|
||||
|
||||
class Import : public BasicImport
|
||||
{
|
||||
public:
|
||||
explicit Import(Utils::SmallStringView name,
|
||||
VersionNumber version = VersionNumber{},
|
||||
SourceId sourceId = SourceId{},
|
||||
BasicImports importDependencies = {})
|
||||
: BasicImport(name, version)
|
||||
, importDependencies{std::move(importDependencies)}
|
||||
, sourceId{sourceId}
|
||||
{}
|
||||
|
||||
explicit Import(Utils::SmallStringView name, int version, int sourceId)
|
||||
: BasicImport(name, version)
|
||||
, sourceId{sourceId}
|
||||
{}
|
||||
|
||||
friend bool operator==(const Import &first, const Import &second)
|
||||
{
|
||||
return static_cast<const BasicImport &>(first) == static_cast<const BasicImport &>(second)
|
||||
&& first.sourceId == second.sourceId
|
||||
&& first.importDependencies == second.importDependencies;
|
||||
}
|
||||
|
||||
public:
|
||||
BasicImports importDependencies;
|
||||
SourceId sourceId;
|
||||
ImportId importId;
|
||||
};
|
||||
|
||||
using Imports = std::vector<Import>;
|
||||
|
||||
class ImportView
|
||||
{
|
||||
public:
|
||||
explicit ImportView(Utils::SmallStringView name, int version, int sourceId, long long importId)
|
||||
: name{name}
|
||||
, version{version}
|
||||
, sourceId{sourceId}
|
||||
, importId{importId}
|
||||
{}
|
||||
|
||||
friend bool operator==(const ImportView &first, const ImportView &second)
|
||||
{
|
||||
return first.name == second.name
|
||||
&& first.version == second.version & first.sourceId == second.sourceId;
|
||||
}
|
||||
|
||||
public:
|
||||
Utils::SmallStringView name;
|
||||
VersionNumber version;
|
||||
SourceId sourceId;
|
||||
ImportId importId;
|
||||
};
|
||||
|
||||
} // namespace QmlDesigner::Storage
|
||||
|
@@ -1732,6 +1732,17 @@ std::ostream &operator<<(std::ostream &out, const EnumerationDeclaration &enumer
|
||||
<< enumerationDeclaration.enumeratorDeclarations << ")";
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &out, const BasicImport &import)
|
||||
{
|
||||
return out << "(" << import.name << ", " << import.version << ")";
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &out, const Import &import)
|
||||
{
|
||||
return out << "(" << import.name << ", " << import.version << ", " << import.sourceId << ", "
|
||||
<< import.importDependencies << ")";
|
||||
}
|
||||
|
||||
} // namespace Storage
|
||||
|
||||
namespace Internal {
|
||||
|
@@ -407,6 +407,8 @@ class ParameterDeclaration;
|
||||
class SignalDeclaration;
|
||||
class EnumerationDeclaration;
|
||||
class EnumeratorDeclaration;
|
||||
class BasicImport;
|
||||
class Import;
|
||||
|
||||
std::ostream &operator<<(std::ostream &out, TypeAccessSemantics accessSemantics);
|
||||
std::ostream &operator<<(std::ostream &out, VersionNumber versionNumber);
|
||||
@@ -420,6 +422,8 @@ std::ostream &operator<<(std::ostream &out, const ParameterDeclaration ¶mete
|
||||
std::ostream &operator<<(std::ostream &out, const SignalDeclaration &signalDeclaration);
|
||||
std::ostream &operator<<(std::ostream &out, const EnumerationDeclaration &enumerationDeclaration);
|
||||
std::ostream &operator<<(std::ostream &out, const EnumeratorDeclaration &enumeratorDeclaration);
|
||||
std::ostream &operator<<(std::ostream &out, const BasicImport &import);
|
||||
std::ostream &operator<<(std::ostream &out, const Import &import);
|
||||
|
||||
} // namespace Storage
|
||||
|
||||
|
@@ -119,6 +119,28 @@ MATCHER_P3(IsPropertyDeclaration,
|
||||
&& propertyDeclaration.traits == traits;
|
||||
}
|
||||
|
||||
MATCHER_P2(IsBasicImport,
|
||||
name,
|
||||
version,
|
||||
std::string(negation ? "isn't " : "is ") + PrintToString(Storage::Import{name, version}))
|
||||
{
|
||||
const Storage::BasicImport &import = arg;
|
||||
|
||||
return import.name == name && import.version == version;
|
||||
}
|
||||
|
||||
MATCHER_P3(IsImport,
|
||||
name,
|
||||
version,
|
||||
sourceId,
|
||||
std::string(negation ? "isn't " : "is ")
|
||||
+ PrintToString(Storage::Import{name, version, sourceId}))
|
||||
{
|
||||
const Storage::Import &import = arg;
|
||||
|
||||
return import.name == name && import.version == version && &import.sourceId == &sourceId;
|
||||
}
|
||||
|
||||
class ProjectStorage : public testing::Test
|
||||
{
|
||||
public:
|
||||
@@ -528,6 +550,24 @@ protected:
|
||||
Storage::ExportedType{"Qml.Object", Storage::Version{5, 1}}}}};
|
||||
}
|
||||
|
||||
auto createImports()
|
||||
{
|
||||
importSourceId1 = sourcePathCache.sourceId(importPath1);
|
||||
importSourceId2 = sourcePathCache.sourceId(importPath2);
|
||||
importSourceId3 = sourcePathCache.sourceId(importPath3);
|
||||
|
||||
return Storage::Imports{Storage::Import{"Qml", Storage::VersionNumber{2}, importSourceId1, {}},
|
||||
Storage::Import{"QtQuick",
|
||||
Storage::VersionNumber{},
|
||||
importSourceId2,
|
||||
{Storage::Import{"Qml", Storage::VersionNumber{2}}}},
|
||||
Storage::Import{"/path/to",
|
||||
Storage::VersionNumber{},
|
||||
SourceId{},
|
||||
{Storage::Import{"QtQuick"},
|
||||
Storage::Import{"Qml", Storage::VersionNumber{2}}}}};
|
||||
}
|
||||
|
||||
protected:
|
||||
using ProjectStorage = QmlDesigner::ProjectStorage<Sqlite::Database>;
|
||||
Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory};
|
||||
@@ -541,6 +581,12 @@ protected:
|
||||
SourceId sourceId2;
|
||||
SourceId sourceId3;
|
||||
SourceId sourceId4;
|
||||
QmlDesigner::SourcePathView importPath1{"/import/path1/to"};
|
||||
QmlDesigner::SourcePathView importPath2{"/import/path2/to"};
|
||||
QmlDesigner::SourcePathView importPath3{"/import/aaaa/to"};
|
||||
SourceId importSourceId1;
|
||||
SourceId importSourceId2;
|
||||
SourceId importSourceId3;
|
||||
};
|
||||
|
||||
TEST_F(ProjectStorageSlowTest, FetchTypeIdByName)
|
||||
@@ -1953,4 +1999,273 @@ TEST_F(ProjectStorageSlowTest, SynchronizeTypesAddEnumerationDeclaration)
|
||||
Eq(types[0].enumerationDeclarations[2]))))));
|
||||
}
|
||||
|
||||
TEST_F(ProjectStorageSlowTest, SynchronizeImportsAddImports)
|
||||
{
|
||||
Storage::Imports imports{createImports()};
|
||||
|
||||
storage.synchronizeImports(imports);
|
||||
|
||||
ASSERT_THAT(storage.fetchAllImports(),
|
||||
UnorderedElementsAre(IsImport("Qml", Storage::VersionNumber{2}, importSourceId1),
|
||||
IsImport("QtQuick", Storage::VersionNumber{}, importSourceId2),
|
||||
IsImport("/path/to", Storage::VersionNumber{}, SourceId{})));
|
||||
}
|
||||
|
||||
TEST_F(ProjectStorageSlowTest, SynchronizeImportsAddImportsAgain)
|
||||
{
|
||||
Storage::Imports imports{createImports()};
|
||||
storage.synchronizeImports(imports);
|
||||
|
||||
storage.synchronizeImports(imports);
|
||||
|
||||
ASSERT_THAT(storage.fetchAllImports(),
|
||||
UnorderedElementsAre(IsImport("Qml", Storage::VersionNumber{2}, importSourceId1),
|
||||
IsImport("QtQuick", Storage::VersionNumber{}, importSourceId2),
|
||||
IsImport("/path/to", Storage::VersionNumber{}, SourceId{})));
|
||||
}
|
||||
|
||||
TEST_F(ProjectStorageSlowTest, SynchronizeImportsAddMoreImports)
|
||||
{
|
||||
Storage::Imports imports{createImports()};
|
||||
storage.synchronizeImports(imports);
|
||||
imports.push_back(Storage::Import{"QtQuick.Foo", Storage::VersionNumber{1}, importSourceId3});
|
||||
|
||||
storage.synchronizeImports(imports);
|
||||
|
||||
ASSERT_THAT(storage.fetchAllImports(),
|
||||
UnorderedElementsAre(IsImport("Qml", Storage::VersionNumber{2}, importSourceId1),
|
||||
IsImport("QtQuick", Storage::VersionNumber{}, importSourceId2),
|
||||
IsImport("/path/to", Storage::VersionNumber{}, SourceId{}),
|
||||
IsImport("QtQuick.Foo", Storage::VersionNumber{1}, importSourceId3)));
|
||||
}
|
||||
|
||||
TEST_F(ProjectStorageSlowTest, SynchronizeImportsAddSameImportNameButDifferentVersion)
|
||||
{
|
||||
Storage::Imports imports{createImports()};
|
||||
imports.push_back(Storage::Import{"Qml", Storage::VersionNumber{4}, importSourceId3});
|
||||
storage.synchronizeImports(imports);
|
||||
imports.pop_back();
|
||||
imports.push_back(Storage::Import{"Qml", Storage::VersionNumber{3}, importSourceId3});
|
||||
|
||||
storage.synchronizeImports(imports);
|
||||
|
||||
ASSERT_THAT(storage.fetchAllImports(),
|
||||
UnorderedElementsAre(IsImport("Qml", Storage::VersionNumber{2}, importSourceId1),
|
||||
IsImport("Qml", Storage::VersionNumber{3}, importSourceId3),
|
||||
IsImport("QtQuick", Storage::VersionNumber{}, importSourceId2),
|
||||
IsImport("/path/to", Storage::VersionNumber{}, SourceId{})));
|
||||
}
|
||||
|
||||
TEST_F(ProjectStorageSlowTest, SynchronizeImportsRemoveImport)
|
||||
{
|
||||
Storage::Imports imports{createImports()};
|
||||
storage.synchronizeImports(imports);
|
||||
imports.pop_back();
|
||||
|
||||
storage.synchronizeImports(imports);
|
||||
|
||||
ASSERT_THAT(storage.fetchAllImports(),
|
||||
UnorderedElementsAre(IsImport("Qml", Storage::VersionNumber{2}, importSourceId1),
|
||||
IsImport("QtQuick", Storage::VersionNumber{}, importSourceId2)));
|
||||
}
|
||||
|
||||
TEST_F(ProjectStorageSlowTest, SynchronizeImportsUpdateImport)
|
||||
{
|
||||
Storage::Imports imports{createImports()};
|
||||
storage.synchronizeImports(imports);
|
||||
imports[1].sourceId = importSourceId3;
|
||||
|
||||
storage.synchronizeImports(imports);
|
||||
|
||||
ASSERT_THAT(storage.fetchAllImports(),
|
||||
UnorderedElementsAre(IsImport("Qml", Storage::VersionNumber{2}, importSourceId1),
|
||||
IsImport("QtQuick", Storage::VersionNumber{}, importSourceId3),
|
||||
IsImport("/path/to", Storage::VersionNumber{}, SourceId{})));
|
||||
}
|
||||
|
||||
TEST_F(ProjectStorageSlowTest, SynchronizeImportsAddImportDependecies)
|
||||
{
|
||||
Storage::Imports imports{createImports()};
|
||||
|
||||
storage.synchronizeImports(imports);
|
||||
|
||||
ASSERT_THAT(storage.fetchAllImports(),
|
||||
UnorderedElementsAre(
|
||||
AllOf(IsImport("Qml", Storage::VersionNumber{2}, importSourceId1),
|
||||
Field(&Storage::Import::importDependencies, IsEmpty())),
|
||||
AllOf(IsImport("QtQuick", Storage::VersionNumber{}, importSourceId2),
|
||||
Field(&Storage::Import::importDependencies,
|
||||
ElementsAre(IsBasicImport("Qml", Storage::VersionNumber{2})))),
|
||||
AllOf(IsImport("/path/to", Storage::VersionNumber{}, SourceId{}),
|
||||
Field(&Storage::Import::importDependencies,
|
||||
UnorderedElementsAre(IsBasicImport("Qml", Storage::VersionNumber{2}),
|
||||
IsBasicImport("QtQuick",
|
||||
Storage::VersionNumber{}))))));
|
||||
}
|
||||
|
||||
TEST_F(ProjectStorageSlowTest, SynchronizeImportsAddImportDependeciesWhichDoesNotExitsThrows)
|
||||
{
|
||||
Storage::Imports imports{createImports()};
|
||||
imports[1].importDependencies.push_back(Storage::Import{"QmlBase", Storage::VersionNumber{2}});
|
||||
|
||||
ASSERT_THROW(storage.synchronizeImports(imports), QmlDesigner::ImportDoesNotExists);
|
||||
}
|
||||
|
||||
TEST_F(ProjectStorageSlowTest, SynchronizeImportsRemovesDependeciesForRemovedImports)
|
||||
{
|
||||
Storage::Imports imports{createImports()};
|
||||
storage.synchronizeImports(imports);
|
||||
auto last = imports.back();
|
||||
imports.pop_back();
|
||||
|
||||
storage.synchronizeImports(imports);
|
||||
|
||||
last.importDependencies.pop_back();
|
||||
imports.push_back(last);
|
||||
storage.synchronizeImports(imports);
|
||||
ASSERT_THAT(storage.fetchAllImports(),
|
||||
UnorderedElementsAre(
|
||||
AllOf(IsImport("Qml", Storage::VersionNumber{2}, importSourceId1),
|
||||
Field(&Storage::Import::importDependencies, IsEmpty())),
|
||||
AllOf(IsImport("QtQuick", Storage::VersionNumber{}, importSourceId2),
|
||||
Field(&Storage::Import::importDependencies,
|
||||
ElementsAre(IsBasicImport("Qml", Storage::VersionNumber{2})))),
|
||||
AllOf(IsImport("/path/to", Storage::VersionNumber{}, SourceId{}),
|
||||
Field(&Storage::Import::importDependencies,
|
||||
UnorderedElementsAre(
|
||||
IsBasicImport("QtQuick", Storage::VersionNumber{}))))));
|
||||
}
|
||||
|
||||
TEST_F(ProjectStorageSlowTest, SynchronizeImportsAddMoreImportDependecies)
|
||||
{
|
||||
Storage::Imports imports{createImports()};
|
||||
storage.synchronizeImports(imports);
|
||||
imports.push_back(Storage::Import{"QmlBase", Storage::VersionNumber{2}, importSourceId1, {}});
|
||||
imports[1].importDependencies.push_back(Storage::Import{"QmlBase", Storage::VersionNumber{2}});
|
||||
|
||||
storage.synchronizeImports(imports);
|
||||
|
||||
ASSERT_THAT(
|
||||
storage.fetchAllImports(),
|
||||
UnorderedElementsAre(
|
||||
AllOf(IsImport("Qml", Storage::VersionNumber{2}, importSourceId1),
|
||||
Field(&Storage::Import::importDependencies, IsEmpty())),
|
||||
AllOf(IsImport("QmlBase", Storage::VersionNumber{2}, importSourceId1),
|
||||
Field(&Storage::Import::importDependencies, IsEmpty())),
|
||||
AllOf(IsImport("QtQuick", Storage::VersionNumber{}, importSourceId2),
|
||||
Field(&Storage::Import::importDependencies,
|
||||
UnorderedElementsAre(IsBasicImport("Qml", Storage::VersionNumber{2}),
|
||||
IsBasicImport("QmlBase", Storage::VersionNumber{2})))),
|
||||
AllOf(IsImport("/path/to", Storage::VersionNumber{}, SourceId{}),
|
||||
Field(&Storage::Import::importDependencies,
|
||||
UnorderedElementsAre(IsBasicImport("Qml", Storage::VersionNumber{2}),
|
||||
IsBasicImport("QtQuick", Storage::VersionNumber{}))))));
|
||||
}
|
||||
|
||||
TEST_F(ProjectStorageSlowTest, SynchronizeImportsAddMoreImportDependeciesWithDifferentVersionNumber)
|
||||
{
|
||||
Storage::Imports imports{createImports()};
|
||||
storage.synchronizeImports(imports);
|
||||
imports.push_back(Storage::Import{"Qml", Storage::VersionNumber{3}, importSourceId1, {}});
|
||||
imports[1].importDependencies.push_back(Storage::Import{"Qml", Storage::VersionNumber{3}});
|
||||
|
||||
storage.synchronizeImports(imports);
|
||||
|
||||
ASSERT_THAT(
|
||||
storage.fetchAllImports(),
|
||||
UnorderedElementsAre(
|
||||
AllOf(IsImport("Qml", Storage::VersionNumber{2}, importSourceId1),
|
||||
Field(&Storage::Import::importDependencies, IsEmpty())),
|
||||
AllOf(IsImport("Qml", Storage::VersionNumber{3}, importSourceId1),
|
||||
Field(&Storage::Import::importDependencies, IsEmpty())),
|
||||
AllOf(IsImport("QtQuick", Storage::VersionNumber{}, importSourceId2),
|
||||
Field(&Storage::Import::importDependencies,
|
||||
UnorderedElementsAre(IsBasicImport("Qml", Storage::VersionNumber{2}),
|
||||
IsBasicImport("Qml", Storage::VersionNumber{3})))),
|
||||
AllOf(IsImport("/path/to", Storage::VersionNumber{}, SourceId{}),
|
||||
Field(&Storage::Import::importDependencies,
|
||||
UnorderedElementsAre(IsBasicImport("Qml", Storage::VersionNumber{2}),
|
||||
IsBasicImport("QtQuick", Storage::VersionNumber{}))))));
|
||||
}
|
||||
|
||||
TEST_F(ProjectStorageSlowTest, SynchronizeImportsDependencyGetsHighestVersionIfNoVersionIsSupplied)
|
||||
{
|
||||
Storage::Imports imports{createImports()};
|
||||
storage.synchronizeImports(imports);
|
||||
imports.push_back(Storage::Import{"Qml", Storage::VersionNumber{3}, importSourceId1, {}});
|
||||
imports[1].importDependencies.push_back(Storage::Import{"Qml"});
|
||||
|
||||
storage.synchronizeImports(imports);
|
||||
|
||||
ASSERT_THAT(
|
||||
storage.fetchAllImports(),
|
||||
UnorderedElementsAre(
|
||||
AllOf(IsImport("Qml", Storage::VersionNumber{2}, importSourceId1),
|
||||
Field(&Storage::Import::importDependencies, IsEmpty())),
|
||||
AllOf(IsImport("Qml", Storage::VersionNumber{3}, importSourceId1),
|
||||
Field(&Storage::Import::importDependencies, IsEmpty())),
|
||||
AllOf(IsImport("QtQuick", Storage::VersionNumber{}, importSourceId2),
|
||||
Field(&Storage::Import::importDependencies,
|
||||
UnorderedElementsAre(IsBasicImport("Qml", Storage::VersionNumber{2}),
|
||||
IsBasicImport("Qml", Storage::VersionNumber{3})))),
|
||||
AllOf(IsImport("/path/to", Storage::VersionNumber{}, SourceId{}),
|
||||
Field(&Storage::Import::importDependencies,
|
||||
UnorderedElementsAre(IsBasicImport("Qml", Storage::VersionNumber{2}),
|
||||
IsBasicImport("QtQuick", Storage::VersionNumber{}))))));
|
||||
}
|
||||
|
||||
TEST_F(ProjectStorageSlowTest, SynchronizeImportsDependencyGetsOnlyTheHighestDependency)
|
||||
{
|
||||
Storage::Imports imports{createImports()};
|
||||
storage.synchronizeImports(imports);
|
||||
imports.push_back(Storage::Import{"Qml", Storage::VersionNumber{1}, importSourceId1, {}});
|
||||
imports[1].importDependencies.push_back(Storage::Import{"Qml"});
|
||||
|
||||
storage.synchronizeImports(imports);
|
||||
|
||||
ASSERT_THAT(
|
||||
storage.fetchAllImports(),
|
||||
UnorderedElementsAre(
|
||||
AllOf(IsImport("Qml", Storage::VersionNumber{2}, importSourceId1),
|
||||
Field(&Storage::Import::importDependencies, IsEmpty())),
|
||||
AllOf(IsImport("Qml", Storage::VersionNumber{1}, importSourceId1),
|
||||
Field(&Storage::Import::importDependencies, IsEmpty())),
|
||||
AllOf(IsImport("QtQuick", Storage::VersionNumber{}, importSourceId2),
|
||||
Field(&Storage::Import::importDependencies,
|
||||
UnorderedElementsAre(IsBasicImport("Qml", Storage::VersionNumber{2})))),
|
||||
AllOf(IsImport("/path/to", Storage::VersionNumber{}, SourceId{}),
|
||||
Field(&Storage::Import::importDependencies,
|
||||
UnorderedElementsAre(IsBasicImport("Qml", Storage::VersionNumber{2}),
|
||||
IsBasicImport("QtQuick", Storage::VersionNumber{}))))));
|
||||
}
|
||||
|
||||
TEST_F(ProjectStorageSlowTest, SynchronizeImportsDependencyRemoveDuplicateDependencies)
|
||||
{
|
||||
Storage::Imports imports{createImports()};
|
||||
storage.synchronizeImports(imports);
|
||||
imports.push_back(Storage::Import{"Qml", Storage::VersionNumber{3}, importSourceId1, {}});
|
||||
imports[2].importDependencies.push_back(Storage::Import{"Qml", Storage::VersionNumber{3}});
|
||||
imports[2].importDependencies.push_back(Storage::Import{"Qml", Storage::VersionNumber{2}});
|
||||
imports[2].importDependencies.push_back(Storage::Import{"Qml", Storage::VersionNumber{3}});
|
||||
imports[2].importDependencies.push_back(Storage::Import{"Qml", Storage::VersionNumber{2}});
|
||||
|
||||
storage.synchronizeImports(imports);
|
||||
|
||||
ASSERT_THAT(
|
||||
storage.fetchAllImports(),
|
||||
UnorderedElementsAre(
|
||||
AllOf(IsImport("Qml", Storage::VersionNumber{2}, importSourceId1),
|
||||
Field(&Storage::Import::importDependencies, IsEmpty())),
|
||||
AllOf(IsImport("Qml", Storage::VersionNumber{3}, importSourceId1),
|
||||
Field(&Storage::Import::importDependencies, IsEmpty())),
|
||||
AllOf(IsImport("QtQuick", Storage::VersionNumber{}, importSourceId2),
|
||||
Field(&Storage::Import::importDependencies,
|
||||
UnorderedElementsAre(IsBasicImport("Qml", Storage::VersionNumber{2})))),
|
||||
AllOf(IsImport("/path/to", Storage::VersionNumber{}, SourceId{}),
|
||||
Field(&Storage::Import::importDependencies,
|
||||
UnorderedElementsAre(IsBasicImport("Qml", Storage::VersionNumber{2}),
|
||||
IsBasicImport("Qml", Storage::VersionNumber{3}),
|
||||
IsBasicImport("QtQuick", Storage::VersionNumber{}))))));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
Reference in New Issue
Block a user