QmlDesigner: Add support for import statement in qmldirs

Qmldir files can import and reexport modules.

Task-number: QDS-6242
Change-Id: I3d2186dd13e6357281dfa3ac8435e80250f2491b
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
Marco Bubke
2022-02-15 15:15:55 +01:00
parent bd8e0796c2
commit ad8b8fca9b
2 changed files with 102 additions and 0 deletions

View File

@@ -79,6 +79,18 @@ void addSourceIds(SourceIds &sourceIds, const Storage::ProjectDatas &projectData
sourceIds.push_back(projectData.sourceId); sourceIds.push_back(projectData.sourceId);
} }
Storage::Version convertVersion(LanguageUtils::ComponentVersion version)
{
return Storage::Version{version.majorVersion(), version.minorVersion()};
}
Storage::IsAutoVersion convertToIsAutoVersion(QmlDirParser::Import::Flags flags)
{
if (flags & QmlDirParser::Import::Flag::Auto)
return Storage::IsAutoVersion::Yes;
return Storage::IsAutoVersion::No;
}
void addDependencies(Storage::Imports &dependencies, void addDependencies(Storage::Imports &dependencies,
SourceId sourceId, SourceId sourceId,
const QList<QmlDirParser::Import> &qmldirDependencies, const QList<QmlDirParser::Import> &qmldirDependencies,
@@ -91,6 +103,30 @@ void addDependencies(Storage::Imports &dependencies,
} }
} }
void addModuleExportedImports(Storage::ModuleExportedImports &imports,
ModuleId moduleId,
const QList<QmlDirParser::Import> &qmldirImports,
ProjectStorageInterface &projectStorage)
{
for (const QmlDirParser::Import &qmldirImport : qmldirImports) {
if (qmldirImport.flags & QmlDirParser::Import::Flag::Optional)
continue;
ModuleId exportedModuleId = projectStorage.moduleId(Utils::PathString{qmldirImport.module});
imports.emplace_back(moduleId,
exportedModuleId,
convertVersion(qmldirImport.version),
convertToIsAutoVersion(qmldirImport.flags));
ModuleId exportedCppModuleId = projectStorage.moduleId(
Utils::PathString{qmldirImport.module} + "-cppnative");
imports.emplace_back(moduleId,
exportedCppModuleId,
Storage::Version{},
Storage::IsAutoVersion::No);
}
}
} // namespace } // namespace
void ProjectStorageUpdater::update(QStringList qmlDirs, QStringList qmlTypesPaths) void ProjectStorageUpdater::update(QStringList qmlDirs, QStringList qmlTypesPaths)
@@ -162,6 +198,12 @@ void ProjectStorageUpdater::updateQmldirs(const QStringList &qmlDirs,
Utils::PathString moduleName{parser.typeNamespace()}; Utils::PathString moduleName{parser.typeNamespace()};
ModuleId moduleId = m_projectStorage.moduleId(moduleName); ModuleId moduleId = m_projectStorage.moduleId(moduleName);
addModuleExportedImports(package.moduleExportedImports,
moduleId,
parser.imports(),
m_projectStorage);
package.updatedModuleIds.push_back(moduleId);
const auto qmlProjectDatas = m_projectStorage.fetchProjectDatas(qmlDirSourceId); const auto qmlProjectDatas = m_projectStorage.fetchProjectDatas(qmlDirSourceId);
addSourceIds(package.updatedSourceIds, qmlProjectDatas); addSourceIds(package.updatedSourceIds, qmlProjectDatas);
addSourceIds(package.updatedFileStatusSourceIds, qmlProjectDatas); addSourceIds(package.updatedFileStatusSourceIds, qmlProjectDatas);

View File

@@ -48,6 +48,8 @@ namespace Storage = QmlDesigner::Storage;
using QmlDesigner::IdPaths; using QmlDesigner::IdPaths;
using QmlDesigner::Storage::FileType; using QmlDesigner::Storage::FileType;
using QmlDesigner::Storage::Import; using QmlDesigner::Storage::Import;
using QmlDesigner::Storage::IsAutoVersion;
using QmlDesigner::Storage::ModuleExportedImport;
using QmlDesigner::Storage::ProjectData; using QmlDesigner::Storage::ProjectData;
using QmlDesigner::Storage::SynchronizationPackage; using QmlDesigner::Storage::SynchronizationPackage;
using QmlDesigner::Storage::Version; using QmlDesigner::Storage::Version;
@@ -245,6 +247,8 @@ protected:
ModuleId exampleCppNativeModuleId{storage.moduleId("Example-cppnative")}; ModuleId exampleCppNativeModuleId{storage.moduleId("Example-cppnative")};
ModuleId builtinModuleId{storage.moduleId("QML")}; ModuleId builtinModuleId{storage.moduleId("QML")};
ModuleId builtinCppNativeModuleId{storage.moduleId("QML-cppnative")}; ModuleId builtinCppNativeModuleId{storage.moduleId("QML-cppnative")};
ModuleId quickModuleId{storage.moduleId("Quick")};
ModuleId quickCppNativeModuleId{storage.moduleId("Quick-cppnative")};
Storage::Type objectType{"QObject", Storage::Type objectType{"QObject",
Storage::ImportedType{}, Storage::ImportedType{},
Storage::TypeAccessSemantics::Reference, Storage::TypeAccessSemantics::Reference,
@@ -1089,4 +1093,60 @@ TEST_F(ProjectStorageUpdater, SynchronizeQmldirWithNoDependencies)
updater.update(qmlDirs, {}); updater.update(qmlDirs, {});
} }
TEST_F(ProjectStorageUpdater, SynchronizeQmldirImports)
{
QString qmldir{R"(module Example
import Qml auto
import QML 2.1
import Quick
)"};
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, {});
}
TEST_F(ProjectStorageUpdater, SynchronizeQmldirWithNoImports)
{
QString qmldir{R"(module Example
)"};
ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/qmldir")))).WillByDefault(Return(qmldir));
EXPECT_CALL(projectStorageMock,
synchronize(AllOf(Field(&SynchronizationPackage::moduleExportedImports, IsEmpty()),
Field(&SynchronizationPackage::updatedModuleIds,
ElementsAre(exampleModuleId)))));
updater.update(qmlDirs, {});
}
} // namespace } // namespace