From b4fcd05451dd35fd2f3abb0b73a66c82327d22fb Mon Sep 17 00:00:00 2001 From: Marco Bubke Date: Tue, 19 Oct 2021 14:42:28 +0200 Subject: [PATCH] QmlDesigner: Introduce different modules for cpp, qml and directories There are now different modules for qml, cpp and directory imports. Cpp imports are qml import append by "-cppnative". Task-number: QDS-5196 Change-Id: I599b224892c5ada0224a765d0bde8b32de20b061 Reviewed-by: Tim Jenssen Reviewed-by: Qt CI Bot --- .../projectstorage/projectstorage.h | 5 ++- .../projectstorage/projectstorageinterface.h | 2 +- .../projectstorage/projectstoragetypes.h | 9 +++++ .../projectstorage/projectstorageupdater.cpp | 38 ++++++++----------- .../projectstorage/projectstorageupdater.h | 7 +--- .../projectstorage/qmltypesparser.cpp | 37 +++++++++--------- .../projectstorage/qmltypesparser.h | 3 +- .../projectstorage/qmltypesparserinterface.h | 3 +- tests/unit/unittest/projectstoragemock.h | 4 +- .../unittest/projectstorageupdater-test.cpp | 19 +++++----- tests/unit/unittest/qmltypesparser-test.cpp | 37 +++++++++--------- tests/unit/unittest/qmltypesparsermock.h | 3 +- 12 files changed, 86 insertions(+), 81 deletions(-) diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstorage.h b/src/plugins/qmldesigner/designercore/projectstorage/projectstorage.h index f6412d231b4..2e7b0629cc5 100644 --- a/src/plugins/qmldesigner/designercore/projectstorage/projectstorage.h +++ b/src/plugins/qmldesigner/designercore/projectstorage/projectstorage.h @@ -308,7 +308,10 @@ public: &sourceId); } - SourceIds fetchSourceDependencieIds(SourceId sourceId) const override { return {}; } + Storage::ProjectDatas fetchProjectDatas(SourceId sourceId) const override + { + return Storage::ProjectDatas{}; + } private: class ModuleStorageAdapter diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageinterface.h b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageinterface.h index 4eaa0527d23..219c6137a10 100644 --- a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageinterface.h +++ b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageinterface.h @@ -42,7 +42,7 @@ public: virtual ModuleId moduleId(Utils::SmallStringView name) = 0; virtual FileStatus fetchFileStatus(SourceId sourceId) const = 0; - virtual SourceIds fetchSourceDependencieIds(SourceId sourceId) const = 0; + virtual Storage::ProjectDatas fetchProjectDatas(SourceId sourceId) const = 0; protected: ~ProjectStorageInterface() = default; diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstoragetypes.h b/src/plugins/qmldesigner/designercore/projectstorage/projectstoragetypes.h index ffbfe7364cb..43a0109a6ad 100644 --- a/src/plugins/qmldesigner/designercore/projectstorage/projectstoragetypes.h +++ b/src/plugins/qmldesigner/designercore/projectstorage/projectstoragetypes.h @@ -717,4 +717,13 @@ public: using Types = std::vector; +class ProjectData +{ +public: + ModuleId extraModuleId; + SourceId sourceId; +}; + +using ProjectDatas = std::vector; + } // namespace QmlDesigner::Storage diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.cpp b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.cpp index 5a23b699448..83fc1399ab9 100644 --- a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.cpp +++ b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.cpp @@ -70,10 +70,10 @@ void ProjectUpdater::update() SourceContextId directoryId = m_pathCache.sourceContextId(qmlDirSourceId); - ModuleId moduleId = m_projectStorage.moduleId(Utils::PathString{parser.typeNamespace()}); + Utils::PathString moduleName{parser.typeNamespace()}; + ModuleId moduleId = m_projectStorage.moduleId(moduleName); - parseTypeInfos( - parser.typeInfos(), directoryId, moduleId, imports, types, sourceIds, fileStatuses); + parseTypeInfos(parser.typeInfos(), directoryId, imports, types, sourceIds, fileStatuses); parseQmlComponents(createComponentReferences(parser.components()), directoryId, moduleId, @@ -84,13 +84,8 @@ void ProjectUpdater::update() break; } case FileState::NotChanged: { - SourceIds qmltypesSourceIds = m_projectStorage.fetchSourceDependencieIds(qmlDirSourceId); - parseTypeInfos(ModuleId{&qmlDirSourceId}, - qmltypesSourceIds, - imports, - types, - sourceIds, - fileStatuses); + auto qmlProjectDatas = m_projectStorage.fetchProjectDatas(qmlDirSourceId); + parseTypeInfos(qmlProjectDatas, imports, types, sourceIds, fileStatuses); break; } case FileState::NotExists: { @@ -110,7 +105,6 @@ void ProjectUpdater::pathsWithIdsChanged(const std::vector &idPaths) {} void ProjectUpdater::parseTypeInfos(const QStringList &typeInfos, SourceContextId directoryId, - ModuleId moduleId, Storage::Imports &imports, Storage::Types &types, SourceIds &sourceIds, @@ -122,36 +116,36 @@ void ProjectUpdater::parseTypeInfos(const QStringList &typeInfos, SourceId sourceId = m_pathCache.sourceId(directoryId, Utils::SmallString{typeInfo}); QString qmltypesPath = directory + "/" + typeInfo; - parseTypeInfo(sourceId, moduleId, qmltypesPath, imports, types, sourceIds, fileStatuses); + Storage::ProjectData projectData{ModuleId{}, sourceId}; + + parseTypeInfo(projectData, qmltypesPath, imports, types, sourceIds, fileStatuses); } } -void ProjectUpdater::parseTypeInfos(ModuleId moduleId, - const SourceIds &qmltypesSourceIds, +void ProjectUpdater::parseTypeInfos(const Storage::ProjectDatas &projectDatas, Storage::Imports &imports, Storage::Types &types, SourceIds &sourceIds, FileStatuses &fileStatuses) { - for (SourceId sourceId : qmltypesSourceIds) { - QString qmltypesPath = m_pathCache.sourcePath(sourceId).toQString(); + for (const Storage::ProjectData &projectData : projectDatas) { + QString qmltypesPath = m_pathCache.sourcePath(projectData.sourceId).toQString(); - parseTypeInfo(sourceId, moduleId, qmltypesPath, imports, types, sourceIds, fileStatuses); + parseTypeInfo(projectData, qmltypesPath, imports, types, sourceIds, fileStatuses); } } -void ProjectUpdater::parseTypeInfo(SourceId sourceId, - ModuleId moduleId, +void ProjectUpdater::parseTypeInfo(const Storage::ProjectData &projectData, const QString &qmltypesPath, Storage::Imports &imports, Storage::Types &types, SourceIds &sourceIds, FileStatuses &fileStatuses) { - if (fileState(sourceId, fileStatuses) == FileState::Changed) { - sourceIds.push_back(sourceId); + if (fileState(projectData.sourceId, fileStatuses) == FileState::Changed) { + sourceIds.push_back(projectData.sourceId); const auto content = m_fileSystem.contentAsQString(qmltypesPath); - m_qmlTypesParser.parse(content, imports, types, sourceId, moduleId); + m_qmlTypesParser.parse(content, imports, types, projectData); } } diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.h b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.h index ce611b71412..2ef61aaaf97 100644 --- a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.h +++ b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.h @@ -88,19 +88,16 @@ private: void parseTypeInfos(const QStringList &typeInfos, SourceContextId directoryId, - ModuleId moduleId, Storage::Imports &imports, Storage::Types &types, SourceIds &sourceIds, FileStatuses &fileStatuses); - void parseTypeInfos(ModuleId moduleId, - const SourceIds &qmltypesSourceIds, + void parseTypeInfos(const Storage::ProjectDatas &projectDatas, Storage::Imports &imports, Storage::Types &types, SourceIds &sourceIds, FileStatuses &fileStatuses); - void parseTypeInfo(SourceId sourceId, - ModuleId moduleId, + void parseTypeInfo(const Storage::ProjectData &projectData, const QString &qmltypesPath, Storage::Imports &imports, Storage::Types &types, diff --git a/src/plugins/qmldesigner/designercore/projectstorage/qmltypesparser.cpp b/src/plugins/qmldesigner/designercore/projectstorage/qmltypesparser.cpp index e3942653218..f5d09409aa3 100644 --- a/src/plugins/qmldesigner/designercore/projectstorage/qmltypesparser.cpp +++ b/src/plugins/qmldesigner/designercore/projectstorage/qmltypesparser.cpp @@ -43,7 +43,6 @@ namespace QmlDesigner { namespace QmlDom = QQmlJS::Dom; namespace { -void addType(const QQmlJSScope::Ptr &object, Storage::Types &types) {} void appendImports(Storage::Imports &imports, const QString &dependency, @@ -55,8 +54,6 @@ void appendImports(Storage::Imports &imports, }); Utils::PathString moduleName{QStringView(dependency.begin(), spaceFound)}; - ModuleId moduleId = storage.moduleId(moduleName); - moduleName.append("-cppnative"); ModuleId cppModuleId = storage.moduleId(moduleName); @@ -84,7 +81,6 @@ void appendImports(Storage::Imports &imports, version.minor.value = QStringView(minorVersionFound, minorVersionEnd).toInt(); } - imports.emplace_back(moduleId, version, sourceId); imports.emplace_back(cppModuleId, version, sourceId); } @@ -97,7 +93,6 @@ void addImports(Storage::Imports &imports, appendImports(imports, dependency, sourceId, storage); imports.emplace_back(storage.moduleId("QML"), Storage::Version{}, sourceId); - imports.emplace_back(storage.moduleId("QtQml"), Storage::Version{}, sourceId); imports.emplace_back(storage.moduleId("QtQml-cppnative"), Storage::Version{}, sourceId); } @@ -122,17 +117,22 @@ Storage::Version createVersion(QTypeRevision qmlVersion) return Storage::Version{qmlVersion.majorVersion(), qmlVersion.minorVersion()}; } -Storage::ExportedTypes createExports(ModuleId moduleId, const QList &qmlExports) +Storage::ExportedTypes createExports(const QList &qmlExports, + const QQmlJSScope &component, + QmlTypesParser::ProjectStorage &storage, + ModuleId cppModuleId) { Storage::ExportedTypes exportedTypes; exportedTypes.reserve(Utils::usize(qmlExports)); for (const QQmlJSScope::Export &qmlExport : qmlExports) { - exportedTypes.emplace_back(moduleId, + exportedTypes.emplace_back(storage.moduleId(Utils::SmallString{qmlExport.package()}), Utils::SmallString{qmlExport.type()}, createVersion(qmlExport.version())); } + exportedTypes.emplace_back(cppModuleId, Utils::SmallString{component.internalName()}); + return exportedTypes; } @@ -257,14 +257,18 @@ Storage::EnumerationDeclarations createEnumeration(const QHash &objects) + const Storage::ProjectData &projectData, + const QHash &objects, + QmlTypesParser::ProjectStorage &storage) { types.reserve(Utils::usize(objects) + types.size()); for (const auto &object : objects) - addType(types, sourceId, moduleId, *object.get()); + addType(types, projectData.sourceId, projectData.extraModuleId, *object.get(), storage); } } // namespace @@ -287,8 +291,7 @@ void addTypes(Storage::Types &types, void QmlTypesParser::parse(const QString &sourceContent, Storage::Imports &imports, Storage::Types &types, - SourceId sourceId, - ModuleId moduleId) + const Storage::ProjectData &projectData) { QQmlJSTypeDescriptionReader reader({}, sourceContent); QHash components; @@ -297,8 +300,8 @@ void QmlTypesParser::parse(const QString &sourceContent, if (!isValid) throw CannotParseQmlTypesFile{}; - addImports(imports, sourceId, dependencies, m_storage); - addTypes(types, sourceId, moduleId, components); + addImports(imports, projectData.sourceId, dependencies, m_storage); + addTypes(types, projectData, components, m_storage); } } // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/designercore/projectstorage/qmltypesparser.h b/src/plugins/qmldesigner/designercore/projectstorage/qmltypesparser.h index eeb58f0e318..40f88d240dc 100644 --- a/src/plugins/qmldesigner/designercore/projectstorage/qmltypesparser.h +++ b/src/plugins/qmldesigner/designercore/projectstorage/qmltypesparser.h @@ -54,8 +54,7 @@ public: void parse(const QString &sourceContent, Storage::Imports &imports, Storage::Types &types, - SourceId sourceId, - ModuleId moduleId) override; + const Storage::ProjectData &projectData) override; private: PathCache &m_pathCache; diff --git a/src/plugins/qmldesigner/designercore/projectstorage/qmltypesparserinterface.h b/src/plugins/qmldesigner/designercore/projectstorage/qmltypesparserinterface.h index d3b102954c0..3255c0b5aac 100644 --- a/src/plugins/qmldesigner/designercore/projectstorage/qmltypesparserinterface.h +++ b/src/plugins/qmldesigner/designercore/projectstorage/qmltypesparserinterface.h @@ -37,8 +37,7 @@ public: virtual void parse(const QString &sourceContent, Storage::Imports &imports, Storage::Types &types, - SourceId sourceId, - ModuleId moduleId) + const Storage::ProjectData &projectData) = 0; protected: diff --git a/tests/unit/unittest/projectstoragemock.h b/tests/unit/unittest/projectstoragemock.h index 0f4c40e56e4..161a2a0fe1b 100644 --- a/tests/unit/unittest/projectstoragemock.h +++ b/tests/unit/unittest/projectstoragemock.h @@ -51,8 +51,8 @@ public: (QmlDesigner::SourceId sourceId), (const, override)); - MOCK_METHOD(QmlDesigner::SourceIds, - fetchSourceDependencieIds, + MOCK_METHOD(QmlDesigner::Storage::ProjectDatas, + fetchProjectDatas, (QmlDesigner::SourceId sourceId), (const, override)); diff --git a/tests/unit/unittest/projectstorageupdater-test.cpp b/tests/unit/unittest/projectstorageupdater-test.cpp index 2b70d332c7d..d63448063d4 100644 --- a/tests/unit/unittest/projectstorageupdater-test.cpp +++ b/tests/unit/unittest/projectstorageupdater-test.cpp @@ -126,8 +126,10 @@ public: ON_CALL(projectStorageMock, fetchFileStatus(Eq(qmlDirPathSourceId))) .WillByDefault(Return(FileStatus{qmlDirPathSourceId, 2, 421})); - ON_CALL(projectStorageMock, fetchSourceDependencieIds(Eq(qmlDirPathSourceId))) - .WillByDefault(Return(QmlDesigner::SourceIds{qmltypesPathSourceId, qmltypes2PathSourceId})); + ON_CALL(projectStorageMock, fetchProjectDatas(Eq(qmlDirPathSourceId))) + .WillByDefault( + Return(QmlDesigner::Storage::ProjectDatas{{ModuleId{}, qmltypesPathSourceId}, + {ModuleId{}, qmltypes2PathSourceId}})); QString qmldir{"module Example\ntypeinfo example.qmltypes\n"}; ON_CALL(projectManagerMock, qtQmlDirs()).WillByDefault(Return(QStringList{"/path/qmldir"})); @@ -300,8 +302,8 @@ TEST_F(ProjectStorageUpdater, ParseQmlTypes) ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/example2.qmltypes")))) .WillByDefault(Return(qmltypes2)); - EXPECT_CALL(qmlTypesParserMock, parse(qmltypes, _, _, _, _)); - EXPECT_CALL(qmlTypesParserMock, parse(qmltypes2, _, _, _, _)); + EXPECT_CALL(qmlTypesParserMock, parse(qmltypes, _, _, _)); + EXPECT_CALL(qmlTypesParserMock, parse(qmltypes2, _, _, _)); updater.update(); } @@ -328,8 +330,8 @@ TEST_F(ProjectStorageUpdater, SynchronizeQmlTypes) QString qmltypes{"Module {\ndependencies: []}"}; ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/example.qmltypes")))) .WillByDefault(Return(qmltypes)); - ON_CALL(qmlTypesParserMock, parse(qmltypes, _, _, _, _)) - .WillByDefault([&](auto, auto &imports, auto &types, auto, auto) { + ON_CALL(qmlTypesParserMock, parse(qmltypes, _, _, _)) + .WillByDefault([&](auto, auto &imports, auto &types, auto) { types.push_back(objectType); imports.push_back(import); }); @@ -350,9 +352,8 @@ TEST_F(ProjectStorageUpdater, SynchronizeQmlTypesAreEmptyIfFileDoesNotChanged) QString qmltypes{"Module {\ndependencies: []}"}; ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/example.qmltypes")))) .WillByDefault(Return(qmltypes)); - ON_CALL(qmlTypesParserMock, parse(qmltypes, _, _, _, _)) - .WillByDefault( - [&](auto, auto &imports, auto &types, auto, auto) { types.push_back(objectType); }); + ON_CALL(qmlTypesParserMock, parse(qmltypes, _, _, _)) + .WillByDefault([&](auto, auto &, auto &types, auto) { types.push_back(objectType); }); ON_CALL(fileSystemMock, fileStatus(Eq(qmltypesPathSourceId))) .WillByDefault(Return(FileStatus{qmltypesPathSourceId, 2, 421})); ON_CALL(fileSystemMock, fileStatus(Eq(qmltypes2PathSourceId))) diff --git a/tests/unit/unittest/qmltypesparser-test.cpp b/tests/unit/unittest/qmltypesparser-test.cpp index 8fd4263d223..9de60a1807f 100644 --- a/tests/unit/unittest/qmltypesparser-test.cpp +++ b/tests/unit/unittest/qmltypesparser-test.cpp @@ -173,6 +173,8 @@ protected: Storage::Imports imports; Storage::Types types; SourceId qmltypesFileSourceId{sourcePathCache.sourceId("path/to/types.qmltypes")}; + QmlDesigner::Storage::ProjectData projectData{storage.moduleId("QtQml-cppnative"), + qmltypesFileSourceId}; SourceContextId qmltypesFileSourceContextId{sourcePathCache.sourceContextId(qmltypesFileSourceId)}; ModuleId directoryModuleId{storage.moduleId("path/to/")}; }; @@ -184,21 +186,17 @@ TEST_F(QmlTypesParser, Imports) dependencies: ["QtQuick 2.15", "QtQuick.Window 2.1", "QtFoo 6"]})"}; - parser.parse(source, imports, types, qmltypesFileSourceId, directoryModuleId); + parser.parse(source, imports, types, projectData); ASSERT_THAT( imports, UnorderedElementsAre( IsImport(storage.moduleId("QML"), Storage::Version{}, qmltypesFileSourceId), - IsImport(storage.moduleId("QtQml"), Storage::Version{}, qmltypesFileSourceId), IsImport(storage.moduleId("QtQml-cppnative"), Storage::Version{}, qmltypesFileSourceId), - IsImport(storage.moduleId("QtQuick"), Storage::Version{2, 15}, qmltypesFileSourceId), IsImport(storage.moduleId("QtQuick-cppnative"), Storage::Version{2, 15}, qmltypesFileSourceId), - IsImport(storage.moduleId("QtQuick.Window"), Storage::Version{2, 1}, qmltypesFileSourceId), IsImport(storage.moduleId("QtQuick.Window-cppnative"), Storage::Version{2, 1}, qmltypesFileSourceId), - IsImport(storage.moduleId("QtFoo"), Storage::Version{6}, qmltypesFileSourceId), IsImport(storage.moduleId("QtFoo-cppnative"), Storage::Version{6}, qmltypesFileSourceId))); } @@ -210,7 +208,7 @@ TEST_F(QmlTypesParser, Types) Component { name: "QQmlComponent" prototype: "QObject"}})"}; - parser.parse(source, imports, types, qmltypesFileSourceId, directoryModuleId); + parser.parse(source, imports, types, projectData); ASSERT_THAT(types, UnorderedElementsAre(IsType("QObject", @@ -228,17 +226,20 @@ TEST_F(QmlTypesParser, ExportedTypes) QString source{R"(import QtQuick.tooling 1.2 Module{ Component { name: "QObject" - exports: ["QtQml/QtObject 1.0", "QtQml/QtObject 2.1"] + exports: ["QML/QtObject 1.0", "QtQml/QtObject 2.1"] }})"}; + ModuleId qmlModuleId = storage.moduleId("QML"); + ModuleId qtQmlModuleId = storage.moduleId("QtQml"); + ModuleId qtQmlNativeModuleId = storage.moduleId("QtQml-cppnative"); - parser.parse(source, imports, types, qmltypesFileSourceId, directoryModuleId); + parser.parse(source, imports, types, projectData); - ASSERT_THAT( - types, - ElementsAre( - Field(&Storage::Type::exportedTypes, - ElementsAre(IsExportedType(directoryModuleId, "QtObject", Storage::Version{1, 0}), - IsExportedType(directoryModuleId, "QtObject", Storage::Version{2, 1}))))); + ASSERT_THAT(types, + ElementsAre(Field( + &Storage::Type::exportedTypes, + ElementsAre(IsExportedType(qmlModuleId, "QtObject", Storage::Version{1, 0}), + IsExportedType(qtQmlModuleId, "QtObject", Storage::Version{2, 1}), + IsExportedType(qtQmlNativeModuleId, "QObject", Storage::Version{}))))); } TEST_F(QmlTypesParser, Properties) @@ -252,7 +253,7 @@ TEST_F(QmlTypesParser, Properties) Property { name: "targets"; type: "QQuickItem"; isList: true; isReadonly: true; isPointer: true } }})"}; - parser.parse(source, imports, types, qmltypesFileSourceId, directoryModuleId); + parser.parse(source, imports, types, projectData); ASSERT_THAT(types, ElementsAre(Field( @@ -296,7 +297,7 @@ TEST_F(QmlTypesParser, Functions) } }})"}; - parser.parse(source, imports, types, qmltypesFileSourceId, directoryModuleId); + parser.parse(source, imports, types, projectData); ASSERT_THAT(types, ElementsAre( @@ -337,7 +338,7 @@ TEST_F(QmlTypesParser, Signals) } }})"}; - parser.parse(source, imports, types, qmltypesFileSourceId, directoryModuleId); + parser.parse(source, imports, types, projectData); ASSERT_THAT(types, ElementsAre(Field(&Storage::Type::signalDeclarations, @@ -375,7 +376,7 @@ TEST_F(QmlTypesParser, Enumerations) } }})"}; - parser.parse(source, imports, types, qmltypesFileSourceId, directoryModuleId); + parser.parse(source, imports, types, projectData); ASSERT_THAT(types, ElementsAre( diff --git a/tests/unit/unittest/qmltypesparsermock.h b/tests/unit/unittest/qmltypesparsermock.h index cfbb8729841..6cf52713797 100644 --- a/tests/unit/unittest/qmltypesparsermock.h +++ b/tests/unit/unittest/qmltypesparsermock.h @@ -37,7 +37,6 @@ public: (const QString &sourceContent, QmlDesigner::Storage::Imports &imports, QmlDesigner::Storage::Types &types, - QmlDesigner::SourceId sourceId, - QmlDesigner::ModuleId moduleId), + const QmlDesigner::Storage::ProjectData &projectData), (override)); };