QmlDesigner: Support multiple module ids per type

The type will be use source id and name instead of module id and name as
key.

Task-number: QDS-5236
Task-number: QDS-5238
Change-Id: Ibc9c298dc0a6363b630173ec4981d574cecd02ff
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-11 11:15:47 +02:00
committed by Tim Jenssen
parent 3871e40f43
commit cb946ec307
16 changed files with 1835 additions and 2206 deletions

View File

@@ -42,26 +42,25 @@ namespace {
namespace Storage = QmlDesigner::Storage;
using QmlDesigner::FileStatus;
using QmlDesigner::ModuleId;
using QmlDesigner::SourceId;
using QmlDesigner::Storage::TypeAccessSemantics;
namespace Storage = QmlDesigner::Storage;
using QmlDesigner::IdPaths;
using QmlDesigner::Storage::Version;
MATCHER_P5(IsStorageType,
moduleId,
MATCHER_P4(IsStorageType,
typeName,
prototype,
accessSemantics,
sourceId,
std::string(negation ? "isn't " : "is ")
+ PrintToString(Storage::Type{moduleId, typeName, prototype, accessSemantics, sourceId}))
+ PrintToString(Storage::Type{typeName, prototype, accessSemantics, sourceId}))
{
const Storage::Type &type = arg;
return type.moduleId == moduleId && type.typeName == typeName
&& type.accessSemantics == accessSemantics && type.sourceId == sourceId
&& Storage::ImportedTypeName{prototype} == type.prototype;
return type.typeName == typeName && type.accessSemantics == accessSemantics
&& type.sourceId == sourceId && Storage::ImportedTypeName{prototype} == type.prototype;
}
MATCHER_P3(IsPropertyDeclaration,
@@ -78,27 +77,20 @@ MATCHER_P3(IsPropertyDeclaration,
&& propertyDeclaration.traits == traits;
}
MATCHER_P3(IsExportedType,
MATCHER_P4(IsExportedType,
moduleId,
name,
majorVersion,
minorVersion,
std::string(negation ? "isn't " : "is ")
+ PrintToString(Storage::ExportedType{name,
+ PrintToString(Storage::ExportedType{moduleId,
name,
Storage::Version{majorVersion, minorVersion}}))
{
const Storage::ExportedType &type = arg;
return type.name == name && type.version == Storage::Version{majorVersion, minorVersion};
}
MATCHER_P2(IsModule,
name,
sourceId,
std::string(negation ? "isn't " : "is ") + PrintToString(Storage::Module{name, sourceId}))
{
const Storage::Module &module = arg;
return module.name == name && module.sourceId == sourceId;
return type.moduleId == moduleId && type.name == name
&& type.version == Storage::Version{majorVersion, minorVersion};
}
MATCHER_P3(IsFileStatus,
@@ -154,6 +146,8 @@ public:
.WillByDefault(Return(FileStatus{qmlDocumentSourceId3, 22, 14}));
ON_CALL(projectStorageMock, fetchFileStatus(Eq(qmlDocumentSourceId3)))
.WillByDefault(Return(FileStatus{qmlDocumentSourceId3, 22, 2}));
ON_CALL(projectStorageMock, moduleId(Eq("Example"))).WillByDefault(Return(exampleModuleId));
ON_CALL(projectStorageMock, moduleId(Eq("Qml"))).WillByDefault(Return(qmlModuleId));
firstType.prototype = Storage::ImportedType{"Object"};
secondType.prototype = Storage::ImportedType{"Object2"};
@@ -203,25 +197,26 @@ protected:
SourceId qmltypesPathSourceId = sourcePathCache.sourceId("/path/example.qmltypes");
SourceId qmltypes2PathSourceId = sourcePathCache.sourceId("/path/example2.qmltypes");
SourceId qmlDirPathSourceId = sourcePathCache.sourceId("/path/qmldir");
QmlDesigner::ModuleId exampleModuleId{&qmlDirPathSourceId};
SourceId qmlDocumentSourceId1 = sourcePathCache.sourceId("/path/First.qml");
SourceId qmlDocumentSourceId2 = sourcePathCache.sourceId("/path/First.2.qml");
SourceId qmlDocumentSourceId3 = sourcePathCache.sourceId("/path/Second.qml");
Storage::Type objectType{exampleModuleId,
"QObject",
ModuleId qmlModuleId{storage.moduleId("Qml")};
ModuleId exampleModuleId{storage.moduleId("Example")};
Storage::Type objectType{"QObject",
Storage::NativeType{},
Storage::TypeAccessSemantics::Reference,
objectTypeSourceId,
{Storage::ExportedType{"Object"}, Storage::ExportedType{"Obj"}}};
{Storage::ExportedType{exampleModuleId, "Object"},
Storage::ExportedType{exampleModuleId, "Obj"}}};
QString qmlDocument1{"First{}"};
QString qmlDocument2{"Second{}"};
QString qmlDocument3{"Third{}"};
Storage::Type firstType;
Storage::Type secondType;
Storage::Type thirdType;
Storage::Import import1{"Qml", Storage::Version{2, 3}, qmlDocumentSourceId1};
Storage::Import import2{"Qml", Storage::Version{}, qmlDocumentSourceId2};
Storage::Import import3{"Qml", Storage::Version{2}, qmlDocumentSourceId3};
Storage::Import import1{qmlModuleId, Storage::Version{2, 3}, qmlDocumentSourceId1};
Storage::Import import2{qmlModuleId, Storage::Version{}, qmlDocumentSourceId2};
Storage::Import import3{qmlModuleId, Storage::Version{2}, qmlDocumentSourceId3};
};
TEST_F(ProjectStorageUpdater, GetContentForQmlDirPathsIfFileStatusIsDifferent)
@@ -320,8 +315,7 @@ TEST_F(ProjectStorageUpdater, SynchronizeIsEmptyForNoChange)
ON_CALL(projectStorageMock, fetchFileStatus(Eq(qmlDirPathSourceId)))
.WillByDefault(Return(FileStatus{qmlDirPathSourceId, 21, 421}));
EXPECT_CALL(projectStorageMock,
synchronize(IsEmpty(), IsEmpty(), IsEmpty(), IsEmpty(), IsEmpty()));
EXPECT_CALL(projectStorageMock, synchronize(IsEmpty(), IsEmpty(), IsEmpty(), IsEmpty()));
updater.update();
}
@@ -330,7 +324,7 @@ TEST_F(ProjectStorageUpdater, SynchronizeQmlTypes)
{
auto qmlDirPathSourceId = sourcePathCache.sourceId("/path/qmldir");
auto qmltypesPathSourceId = sourcePathCache.sourceId("/path/example.qmltypes");
Storage::Import import{"Qml", Storage::Version{2, 3}, qmltypesPathSourceId};
Storage::Import import{qmlModuleId, Storage::Version{2, 3}, qmltypesPathSourceId};
QString qmltypes{"Module {\ndependencies: []}"};
ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/example.qmltypes"))))
.WillByDefault(Return(qmltypes));
@@ -340,9 +334,9 @@ TEST_F(ProjectStorageUpdater, SynchronizeQmlTypes)
imports.push_back(import);
});
EXPECT_CALL(projectStorageMock, moduleId(Eq("Example")));
EXPECT_CALL(projectStorageMock,
synchronize(ElementsAre(IsModule("Example", qmlDirPathSourceId)),
ElementsAre(import),
synchronize(ElementsAre(import),
ElementsAre(Eq(objectType)),
UnorderedElementsAre(qmlDirPathSourceId, qmltypesPathSourceId),
UnorderedElementsAre(IsFileStatus(qmlDirPathSourceId, 21, 421),
@@ -366,8 +360,7 @@ TEST_F(ProjectStorageUpdater, SynchronizeQmlTypesAreEmptyIfFileDoesNotChanged)
ON_CALL(fileSystemMock, fileStatus(Eq(qmlDirPathSourceId)))
.WillByDefault(Return(FileStatus{qmlDirPathSourceId, 2, 421}));
EXPECT_CALL(projectStorageMock,
synchronize(IsEmpty(), IsEmpty(), IsEmpty(), IsEmpty(), IsEmpty()));
EXPECT_CALL(projectStorageMock, synchronize(IsEmpty(), IsEmpty(), IsEmpty(), IsEmpty()));
updater.update();
}
@@ -414,39 +407,36 @@ TEST_F(ProjectStorageUpdater, SynchronizeQmlDocuments)
"First.2.qml\nSecondType 2.1 OldSecond.qml\nSecondType 2.2 Second.qml\n"};
ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/qmldir")))).WillByDefault(Return(qmldir));
EXPECT_CALL(projectStorageMock,
synchronize(ElementsAre(IsModule("Example", qmlDirPathSourceId)),
UnorderedElementsAre(import1, import2, import3),
UnorderedElementsAre(
AllOf(IsStorageType(exampleModuleId,
"First.qml",
Storage::ImportedType{"Object"},
TypeAccessSemantics::Reference,
qmlDocumentSourceId1),
Field(&Storage::Type::exportedTypes,
ElementsAre(IsExportedType("FirstType", 1, 0)))),
AllOf(IsStorageType(exampleModuleId,
"First.2.qml",
Storage::ImportedType{"Object2"},
TypeAccessSemantics::Reference,
qmlDocumentSourceId2),
Field(&Storage::Type::exportedTypes,
ElementsAre(IsExportedType("FirstType", 2, 2)))),
AllOf(IsStorageType(exampleModuleId,
"Second.qml",
Storage::ImportedType{"Object3"},
TypeAccessSemantics::Reference,
qmlDocumentSourceId3),
Field(&Storage::Type::exportedTypes,
ElementsAre(IsExportedType("SecondType", 2, 2))))),
UnorderedElementsAre(qmlDirPathSourceId,
qmlDocumentSourceId1,
qmlDocumentSourceId2,
qmlDocumentSourceId3),
UnorderedElementsAre(IsFileStatus(qmlDirPathSourceId, 21, 421),
IsFileStatus(qmlDocumentSourceId1, 22, 12),
IsFileStatus(qmlDocumentSourceId2, 22, 13),
IsFileStatus(qmlDocumentSourceId3, 22, 14))));
EXPECT_CALL(
projectStorageMock,
synchronize(UnorderedElementsAre(import1, import2, import3),
UnorderedElementsAre(
AllOf(IsStorageType("First.qml",
Storage::ImportedType{"Object"},
TypeAccessSemantics::Reference,
qmlDocumentSourceId1),
Field(&Storage::Type::exportedTypes,
ElementsAre(IsExportedType(exampleModuleId, "FirstType", 1, 0)))),
AllOf(IsStorageType("First.2.qml",
Storage::ImportedType{"Object2"},
TypeAccessSemantics::Reference,
qmlDocumentSourceId2),
Field(&Storage::Type::exportedTypes,
ElementsAre(IsExportedType(exampleModuleId, "FirstType", 2, 2)))),
AllOf(IsStorageType("Second.qml",
Storage::ImportedType{"Object3"},
TypeAccessSemantics::Reference,
qmlDocumentSourceId3),
Field(&Storage::Type::exportedTypes,
ElementsAre(IsExportedType(exampleModuleId, "SecondType", 2, 2))))),
UnorderedElementsAre(qmlDirPathSourceId,
qmlDocumentSourceId1,
qmlDocumentSourceId2,
qmlDocumentSourceId3),
UnorderedElementsAre(IsFileStatus(qmlDirPathSourceId, 21, 421),
IsFileStatus(qmlDocumentSourceId1, 22, 12),
IsFileStatus(qmlDocumentSourceId2, 22, 13),
IsFileStatus(qmlDocumentSourceId3, 22, 14))));
updater.update();
}
@@ -461,22 +451,20 @@ TEST_F(ProjectStorageUpdater, SynchronizeQmlDocumentsDontUpdateIfUpToDate)
EXPECT_CALL(
projectStorageMock,
synchronize(ElementsAre(IsModule("Example", qmlDirPathSourceId)),
UnorderedElementsAre(import1, import2),
UnorderedElementsAre(AllOf(IsStorageType(exampleModuleId,
"First.qml",
Storage::ImportedType{"Object"},
TypeAccessSemantics::Reference,
qmlDocumentSourceId1),
Field(&Storage::Type::exportedTypes,
ElementsAre(IsExportedType("FirstType", 1, 0)))),
AllOf(IsStorageType(exampleModuleId,
"First.2.qml",
Storage::ImportedType{"Object2"},
TypeAccessSemantics::Reference,
qmlDocumentSourceId2),
Field(&Storage::Type::exportedTypes,
ElementsAre(IsExportedType("FirstType", 2, 2))))),
synchronize(UnorderedElementsAre(import1, import2),
UnorderedElementsAre(
AllOf(IsStorageType("First.qml",
Storage::ImportedType{"Object"},
TypeAccessSemantics::Reference,
qmlDocumentSourceId1),
Field(&Storage::Type::exportedTypes,
ElementsAre(IsExportedType(exampleModuleId, "FirstType", 1, 0)))),
AllOf(IsStorageType("First.2.qml",
Storage::ImportedType{"Object2"},
TypeAccessSemantics::Reference,
qmlDocumentSourceId2),
Field(&Storage::Type::exportedTypes,
ElementsAre(IsExportedType(exampleModuleId, "FirstType", 2, 2))))),
UnorderedElementsAre(qmlDirPathSourceId, qmlDocumentSourceId1, qmlDocumentSourceId2),
UnorderedElementsAre(IsFileStatus(qmlDirPathSourceId, 21, 421),
IsFileStatus(qmlDocumentSourceId1, 22, 12),
@@ -485,31 +473,6 @@ TEST_F(ProjectStorageUpdater, SynchronizeQmlDocumentsDontUpdateIfUpToDate)
updater.update();
}
TEST_F(ProjectStorageUpdater, SynchronizeModules)
{
SourceId qmlDirPathSourceId2 = sourcePathCache.sourceId("/path2/qmldir");
ON_CALL(fileSystemMock, fileStatus(Eq(qmlDirPathSourceId2)))
.WillByDefault(Return(FileStatus{qmlDirPathSourceId2, 22, 423}));
ON_CALL(projectStorageMock, fetchFileStatus(Eq(qmlDirPathSourceId2)))
.WillByDefault(Return(FileStatus{qmlDirPathSourceId2, 2, 421}));
QString qmldir2{"module Example2\n"};
ON_CALL(projectManagerMock, qtQmlDirs())
.WillByDefault(Return(QStringList{"/path/qmldir", "/path2/qmldir"}));
ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path2/qmldir")))).WillByDefault(Return(qmldir2));
EXPECT_CALL(projectStorageMock,
synchronize(UnorderedElementsAre(IsModule("Example", qmlDirPathSourceId),
IsModule("Example2", qmlDirPathSourceId2)),
_,
_,
_,
UnorderedElementsAre(IsFileStatus(qmlDirPathSourceId, 21, 421),
IsFileStatus(qmltypesPathSourceId, 21, 421),
IsFileStatus(qmlDirPathSourceId2, 22, 423))));
updater.update();
}
TEST_F(ProjectStorageUpdater, UpdateQmldirDocuments)
{
QString qmldir{"module Example\nFirstType 1.1 First.qml\nFirstType 2.2 "