aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarco Bubke <marco.bubke@qt.io>2022-02-16 16:06:06 +0100
committerMarco Bubke <marco.bubke@qt.io>2022-02-16 18:10:46 +0000
commit3225cd92eba6eacbb64c089796b9ae4bbc86e78e (patch)
tree8bf769dea221707653518f454a5a2409b4c3d718
parent7084ee0eab51edc16c2e79755f451d21697ed895 (diff)
QmlDesigner: Handle double entries in qmldir files
There can be double entries for dependencies or imports. Change-Id: Id2ef9b1bd17ca6f179208215bb782b8b9931e66b Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.cpp40
-rw-r--r--tests/unit/unittest/projectstorageupdater-test.cpp69
2 files changed, 101 insertions, 8 deletions
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.cpp b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.cpp
index d628b3191c..d144647fd2 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.cpp
+++ b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.cpp
@@ -41,6 +41,29 @@
namespace QmlDesigner {
namespace {
+QStringList filterMultipleEntries(QStringList qmlTypes)
+{
+ std::sort(qmlTypes.begin(), qmlTypes.end());
+ qmlTypes.erase(std::unique(qmlTypes.begin(), qmlTypes.end()), qmlTypes.end());
+
+ return qmlTypes;
+}
+
+QList<QmlDirParser::Import> filterMultipleEntries(QList<QmlDirParser::Import> imports)
+{
+ std::stable_sort(imports.begin(), imports.end(), [](auto &&first, auto &&second) {
+ return first.module < second.module;
+ });
+ imports.erase(std::unique(imports.begin(),
+ imports.end(),
+ [](auto &&first, auto &&second) {
+ return first.module == second.module;
+ }),
+ imports.end());
+
+ return imports;
+}
+
ComponentReferences createComponentReferences(const QMultiHash<QString, QmlDirParser::Component> &components)
{
ComponentReferences componentReferences;
@@ -198,21 +221,22 @@ void ProjectStorageUpdater::updateQmldirs(const QStringList &qmlDirs,
Utils::PathString moduleName{parser.typeNamespace()};
ModuleId moduleId = m_projectStorage.moduleId(moduleName);
- addModuleExportedImports(package.moduleExportedImports,
- moduleId,
- parser.imports(),
- m_projectStorage);
+ auto imports = filterMultipleEntries(parser.imports());
+
+ addModuleExportedImports(package.moduleExportedImports, moduleId, imports, m_projectStorage);
package.updatedModuleIds.push_back(moduleId);
const auto qmlProjectDatas = m_projectStorage.fetchProjectDatas(qmlDirSourceId);
addSourceIds(package.updatedSourceIds, qmlProjectDatas);
addSourceIds(package.updatedFileStatusSourceIds, qmlProjectDatas);
- if (!parser.typeInfos().isEmpty()) {
+ auto qmlTypes = filterMultipleEntries(parser.typeInfos());
+
+ if (!qmlTypes.isEmpty()) {
ModuleId cppModuleId = m_projectStorage.moduleId(moduleName + "-cppnative");
- parseTypeInfos(parser.typeInfos(),
- parser.dependencies(),
- parser.imports(),
+ parseTypeInfos(qmlTypes,
+ filterMultipleEntries(parser.dependencies()),
+ imports,
qmlDirSourceId,
directoryId,
cppModuleId,
diff --git a/tests/unit/unittest/projectstorageupdater-test.cpp b/tests/unit/unittest/projectstorageupdater-test.cpp
index 69ed54ef9b..b33c1a89e5 100644
--- a/tests/unit/unittest/projectstorageupdater-test.cpp
+++ b/tests/unit/unittest/projectstorageupdater-test.cpp
@@ -1076,6 +1076,32 @@ TEST_F(ProjectStorageUpdater, SynchronizeQmldirDependencies)
updater.update(qmlDirs, {});
}
+TEST_F(ProjectStorageUpdater, SynchronizeQmldirDependenciesWithDoubleEntries)
+{
+ QString qmldir{R"(module Example
+ depends Qml
+ depends QML
+ depends Qml
+ typeinfo example.qmltypes
+ typeinfo types/example2.qmltypes
+ )"};
+ ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/qmldir")))).WillByDefault(Return(qmldir));
+
+ EXPECT_CALL(
+ projectStorageMock,
+ synchronize(AllOf(
+ Field(&SynchronizationPackage::moduleDependencies,
+ UnorderedElementsAre(
+ Import{qmlCppNativeModuleId, Storage::Version{}, qmltypesPathSourceId},
+ Import{builtinCppNativeModuleId, Storage::Version{}, qmltypesPathSourceId},
+ Import{qmlCppNativeModuleId, Storage::Version{}, qmltypes2PathSourceId},
+ Import{builtinCppNativeModuleId, Storage::Version{}, qmltypes2PathSourceId})),
+ Field(&SynchronizationPackage::updatedModuleDependencySourceIds,
+ UnorderedElementsAre(qmltypesPathSourceId, qmltypes2PathSourceId)))));
+
+ updater.update(qmlDirs, {});
+}
+
TEST_F(ProjectStorageUpdater, SynchronizeQmldirWithNoDependencies)
{
QString qmldir{R"(module Example
@@ -1149,4 +1175,47 @@ TEST_F(ProjectStorageUpdater, SynchronizeQmldirWithNoImports)
updater.update(qmlDirs, {});
}
+TEST_F(ProjectStorageUpdater, SynchronizeQmldirImportsWithDoubleEntries)
+{
+ QString qmldir{R"(module Example
+ import Qml auto
+ import QML 2.1
+ import Quick
+ import Qml
+ )"};
+ ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/qmldir")))).WillByDefault(Return(qmldir));
+
+ EXPECT_CALL(projectStorageMock,
+ synchronize(
+ AllOf(Field(&SynchronizationPackage::moduleExportedImports,
+ UnorderedElementsAre(ModuleExportedImport{exampleModuleId,
+ qmlModuleId,
+ Storage::Version{},
+ IsAutoVersion::Yes},
+ ModuleExportedImport{exampleModuleId,
+ qmlCppNativeModuleId,
+ Storage::Version{},
+ IsAutoVersion::No},
+ ModuleExportedImport{exampleModuleId,
+ builtinModuleId,
+ Storage::Version{2, 1},
+ IsAutoVersion::No},
+ ModuleExportedImport{exampleModuleId,
+ builtinCppNativeModuleId,
+ Storage::Version{},
+ IsAutoVersion::No},
+ ModuleExportedImport{exampleModuleId,
+ quickModuleId,
+ Storage::Version{},
+ IsAutoVersion::No},
+ ModuleExportedImport{exampleModuleId,
+ quickCppNativeModuleId,
+ Storage::Version{},
+ IsAutoVersion::No})),
+ Field(&SynchronizationPackage::updatedModuleIds,
+ ElementsAre(exampleModuleId)))));
+
+ updater.update(qmlDirs, {});
+}
+
} // namespace