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>
This commit is contained in:
Marco Bubke
2022-02-16 16:06:06 +01:00
parent 7084ee0eab
commit 3225cd92eb
2 changed files with 101 additions and 8 deletions

View File

@@ -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,

View File

@@ -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