diff --git a/src/plugins/qmldesigner/libs/designercore/include/nodemetainfo.h b/src/plugins/qmldesigner/libs/designercore/include/nodemetainfo.h index 9429ada9c4d..2161e8c3e9a 100644 --- a/src/plugins/qmldesigner/libs/designercore/include/nodemetainfo.h +++ b/src/plugins/qmldesigner/libs/designercore/include/nodemetainfo.h @@ -76,6 +76,7 @@ public: MetaInfoType type() const; bool isFileComponent() const; bool isSingleton() const; + bool isInsideProject() const; FlagIs canBeContainer() const; FlagIs forceClip() const; FlagIs doesLayoutChildren() const; diff --git a/src/plugins/qmldesigner/libs/designercore/metainfo/nodemetainfo.cpp b/src/plugins/qmldesigner/libs/designercore/metainfo/nodemetainfo.cpp index aab341f13f4..af1d4266a41 100644 --- a/src/plugins/qmldesigner/libs/designercore/metainfo/nodemetainfo.cpp +++ b/src/plugins/qmldesigner/libs/designercore/metainfo/nodemetainfo.cpp @@ -1547,6 +1547,26 @@ bool NodeMetaInfo::isSingleton() const } } +bool NodeMetaInfo::isInsideProject() const +{ + if constexpr (useProjectStorage()) { + if (!isValid()) + return {}; + + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"is inside project", category(), keyValue("type id", m_typeId)}; + + auto isInsideProject = typeData().traits.isInsideProject; + + tracer.end(keyValue("is inside project", isInsideProject)); + + return isInsideProject; + + } else { + return false; + } +} + FlagIs NodeMetaInfo::canBeContainer() const { if constexpr (useProjectStorage()) { diff --git a/src/plugins/qmldesigner/libs/designercore/projectstorage/projectstorageinfotypes.h b/src/plugins/qmldesigner/libs/designercore/projectstorage/projectstorageinfotypes.h index e82e385d78c..a23e2bd0212 100644 --- a/src/plugins/qmldesigner/libs/designercore/projectstorage/projectstorageinfotypes.h +++ b/src/plugins/qmldesigner/libs/designercore/projectstorage/projectstorageinfotypes.h @@ -125,6 +125,8 @@ void convertToString(String &string, const TypeTraitsKind &kind) } } +enum class IsInsideProject : char { No, Yes }; + struct TypeTraits { constexpr TypeTraits() @@ -133,6 +135,7 @@ struct TypeTraits , isFileComponent{false} , usesCustomParser{false} , isSingleton{false} + , isInsideProject{false} , dummy{0U} , canBeContainer{FlagIs::False} , forceClip{FlagIs::False} @@ -208,7 +211,8 @@ struct TypeTraits unsigned int isFileComponent : 1; unsigned int usesCustomParser : 1; unsigned int isSingleton : 1; - unsigned int dummy : 24; + unsigned int isInsideProject : 1; + unsigned int dummy : 23; }; unsigned int type; diff --git a/src/plugins/qmldesigner/libs/designercore/projectstorage/projectstorageupdater.cpp b/src/plugins/qmldesigner/libs/designercore/projectstorage/projectstorageupdater.cpp index aaa2a8e0d02..9e40093916c 100644 --- a/src/plugins/qmldesigner/libs/designercore/projectstorage/projectstorageupdater.cpp +++ b/src/plugins/qmldesigner/libs/designercore/projectstorage/projectstorageupdater.cpp @@ -253,36 +253,53 @@ void addModuleExportedImports(Storage::Synchronization::ModuleExportedImports &i } } -std::vector createIdPaths(ProjectStorageUpdater::WatchedSourceIdsIds watchedSourceIds, - ProjectPartId projectPartId) +using Storage::IsInsideProject; + +using WatchedSourceIds = ProjectStorageUpdater::WatchedSourceIds; + +void appendIdPaths(WatchedSourceIds watchedSourceIds, ProjectPartId id, std::vector &idPaths) { - std::vector idPaths; - idPaths.reserve(4); + if (watchedSourceIds.directoryIds.size()) + idPaths.emplace_back(id, SourceType::Directory, std::move(watchedSourceIds.directoryIds)); - idPaths.push_back({projectPartId, SourceType::Directory, std::move(watchedSourceIds.directoryIds)}); - idPaths.push_back({projectPartId, SourceType::QmlDir, std::move(watchedSourceIds.qmldirSourceIds)}); - idPaths.push_back({projectPartId, SourceType::Qml, std::move(watchedSourceIds.qmlSourceIds)}); - idPaths.push_back( - {projectPartId, SourceType::QmlTypes, std::move(watchedSourceIds.qmltypesSourceIds)}); + if (watchedSourceIds.qmldirSourceIds.size()) + idPaths.emplace_back(id, SourceType::QmlDir, std::move(watchedSourceIds.qmldirSourceIds)); - return idPaths; + if (watchedSourceIds.qmlSourceIds.size()) + idPaths.emplace_back(id, SourceType::Qml, std::move(watchedSourceIds.qmlSourceIds)); + + if (watchedSourceIds.qmltypesSourceIds.size()) + idPaths.emplace_back(id, SourceType::QmlTypes, std::move(watchedSourceIds.qmltypesSourceIds)); } } // namespace void ProjectStorageUpdater::update(Update update) { - QStringList directories = std::move(update.directories); + QStringList qtDirectories = std::move(update.qtDirectories); const QString &propertyEditorResourcesPath = update.propertyEditorResourcesPath; const QStringList &typeAnnotationPaths = update.typeAnnotationPaths; + const Utils::PathString projectDirectory = update.projectDirectory; - NanotraceHR::Tracer tracer{"update", category(), keyValue("directories", directories)}; + NanotraceHR::Tracer tracer{"update", + category(), + keyValue("Qt directories", qtDirectories), + keyValue("project directory", projectDirectory)}; Storage::Synchronization::SynchronizationPackage package; - WatchedSourceIdsIds watchedSourceIds{Utils::usize(directories)}; - NotUpdatedSourceIds notUpdatedSourceIds{Utils::usize(directories)}; + WatchedSourceIds watchedQtSourceIds{32}; + WatchedSourceIds watchedProjectSourceIds{32}; + NotUpdatedSourceIds notUpdatedSourceIds{1024}; - updateDirectories(directories, package, notUpdatedSourceIds, watchedSourceIds); + updateDirectories(qtDirectories, package, notUpdatedSourceIds, watchedQtSourceIds); + if (projectDirectory.size()) { + updateDirectory(projectDirectory, + {}, + package, + notUpdatedSourceIds, + watchedProjectSourceIds, + IsInsideProject::Yes); + } updatePropertyEditorPaths(propertyEditorResourcesPath, package, notUpdatedSourceIds); updateTypeAnnotations(typeAnnotationPaths, package, notUpdatedSourceIds); @@ -294,7 +311,11 @@ void ProjectStorageUpdater::update(Update update) m_projectStorage.synchronize(std::move(package)); - m_pathWatcher.updateIdPaths(createIdPaths(watchedSourceIds, m_projectPartId)); + std::vector idPaths; + idPaths.reserve(8); + appendIdPaths(std::move(watchedQtSourceIds), m_qtPartId, idPaths); + appendIdPaths(std::move(watchedProjectSourceIds), m_projectPartId, idPaths); + m_pathWatcher.updateIdPaths(idPaths); } namespace { @@ -320,13 +341,29 @@ bool isUnchanged(ProjectStorageUpdater::FileState state) return !isChanged(state); } +bool isChangedOrAdded(ProjectStorageUpdater::FileState state) +{ + using FileState = ProjectStorageUpdater::FileState; + switch (state) { + case FileState::Changed: + case FileState::Added: + return true; + case FileState::Removed: + case FileState::NotExists: + case FileState::NotExistsUnchanged: + case FileState::Unchanged: + break; + } + return false; +} + template ProjectStorageUpdater::FileState combineState(FileStates... fileStates) { if (((fileStates == ProjectStorageUpdater::FileState::Removed) && ...)) return ProjectStorageUpdater::FileState::Removed; - if (((fileStates == ProjectStorageUpdater::FileState::Added) && ...)) + if (((fileStates == ProjectStorageUpdater::FileState::Added) || ...)) return ProjectStorageUpdater::FileState::Added; if ((isChanged(fileStates) || ...)) @@ -371,7 +408,8 @@ void ProjectStorageUpdater::updateDirectoryChanged(Utils::SmallStringView direct SourceContextId annotationDirectoryId, Storage::Synchronization::SynchronizationPackage &package, NotUpdatedSourceIds ¬UpdatedSourceIds, - WatchedSourceIdsIds &watchedSourceIdsIds, + WatchedSourceIds &WatchedSourceIds, + IsInsideProject isInsideProject, Tracer &tracer) { QmlDirParser parser; @@ -391,12 +429,8 @@ void ProjectStorageUpdater::updateDirectoryChanged(Utils::SmallStringView direct auto imports = filterMultipleEntries(parser.imports()); - addModuleExportedImports(package.moduleExportedImports, - moduleId, - cppModuleId, - moduleName, - imports, - m_projectStorage); + addModuleExportedImports( + package.moduleExportedImports, moduleId, cppModuleId, moduleName, imports, m_projectStorage); tracer.tick("append updated module id", keyValue("module id", moduleId)); package.updatedModuleIds.push_back(moduleId); @@ -420,7 +454,8 @@ void ProjectStorageUpdater::updateDirectoryChanged(Utils::SmallStringView direct cppModuleId, package, notUpdatedSourceIds, - watchedSourceIdsIds); + WatchedSourceIds, + isInsideProject); } parseQmlComponents(createComponents(parser.components(), moduleId, @@ -430,33 +465,36 @@ void ProjectStorageUpdater::updateDirectoryChanged(Utils::SmallStringView direct directoryId, package, notUpdatedSourceIds, - watchedSourceIdsIds, + WatchedSourceIds, qmldirState, - qmldirSourceId); + qmldirSourceId, + isInsideProject); tracer.tick("append updated project source id", keyValue("module id", moduleId)); package.updatedDirectoryInfoDirectoryIds.push_back(directoryId); - if (isExisting(annotationDirectoryState)) { - annotationDirectoryChanged(annotationDirectoryPath, - directoryId, - annotationDirectoryId, - moduleId, - package, - notUpdatedSourceIds); - } else if (annotationDirectoryState == FileState::Removed) { - package.updatedPropertyEditorQmlPathDirectoryIds.push_back(annotationDirectoryId); + if (isInsideProject == IsInsideProject::Yes) { + if (isExisting(annotationDirectoryState)) { + annotationDirectoryChanged(annotationDirectoryPath, + directoryId, + annotationDirectoryId, + moduleId, + package); + } else if (annotationDirectoryState == FileState::Removed) { + package.updatedPropertyEditorQmlPathDirectoryIds.push_back(annotationDirectoryId); + } } } void ProjectStorageUpdater::updateDirectories(const QStringList &directories, Storage::Synchronization::SynchronizationPackage &package, NotUpdatedSourceIds ¬UpdatedSourceIds, - WatchedSourceIdsIds &watchedSourceIdsIds) + WatchedSourceIds &WatchedSourceIds) { NanotraceHR::Tracer tracer{"update directories", category()}; for (const QString &directory : directories) - updateDirectory({directory}, {}, package, notUpdatedSourceIds, watchedSourceIdsIds); + updateDirectory( + {directory}, {}, package, notUpdatedSourceIds, WatchedSourceIds, IsInsideProject::No); } void ProjectStorageUpdater::updateSubdirectories(const Utils::PathString &directoryPath, @@ -465,7 +503,8 @@ void ProjectStorageUpdater::updateSubdirectories(const Utils::PathString &direct const SourceContextIds &subdirectoriesToIgnore, Storage::Synchronization::SynchronizationPackage &package, NotUpdatedSourceIds ¬UpdatedSourceIds, - WatchedSourceIdsIds &watchedSourceIdsIds) + WatchedSourceIds &WatchedSourceIds, + IsInsideProject isInsideProject) { struct Directory { @@ -490,12 +529,34 @@ void ProjectStorageUpdater::updateSubdirectories(const Utils::PathString &direct auto exisitingSubdirectoryPaths = m_fileSystem.subdirectories(directoryPath.toQString()); Directories existingSubdirecories; + auto skipDirectory = [&](std::string_view subdirectoryPath, SourceContextId sourceContextId) { + if (subdirectoryPath.ends_with("designer")) + return true; + + if (isInsideProject == IsInsideProject::Yes) { + static SourceNameId ignoreInQdsSourceNameId = m_pathCache.sourceNameId("ignore-in-qds"); + + SourceId ignoreInQdsSourceId = SourceId::create(ignoreInQdsSourceNameId, sourceContextId); + + auto ignoreInQdsState = fileState(ignoreInQdsSourceId, package, notUpdatedSourceIds); + + if (isExisting(ignoreInQdsState)) + return true; + } else { + if (subdirectoryPath.ends_with("/QtQuick/Scene2D") + || subdirectoryPath.ends_with("/QtQuick/Scene3D")) + return true; + } + + return false; + }; + for (Utils::PathString subdirectoryPath : exisitingSubdirectoryPaths) { - if (subdirectoryPath.endsWith("designer") || subdirectoryPath.endsWith("/QtQuick/Scene2D") - || subdirectoryPath.endsWith("/QtQuick/Scene3D")) + SourceContextId sourceContextId = m_pathCache.sourceContextId(subdirectoryPath); + + if (skipDirectory(subdirectoryPath, sourceContextId)) continue; - SourceContextId sourceContextId = m_pathCache.sourceContextId(subdirectoryPath); subdirectories.emplace_back(subdirectoryPath, sourceContextId); existingSubdirecories.emplace_back(subdirectoryPath, sourceContextId); } @@ -504,20 +565,22 @@ void ProjectStorageUpdater::updateSubdirectories(const Utils::PathString &direct auto removed = std::ranges::unique(subdirectories, {}, &Directory::sourceContextId); subdirectories.erase(removed.begin(), removed.end()); - Utils::set_greedy_difference( - subdirectories, - subdirectoriesToIgnore, - [&](const Directory &subdirectory) { - updateDirectory(subdirectory.path, - subdirectoriesToIgnore, - package, - notUpdatedSourceIds, - watchedSourceIdsIds); - }, - {}, - &Directory::sourceContextId); + auto updateDirectory = [&](const Directory &subdirectory) { + this->updateDirectory(subdirectory.path, + subdirectoriesToIgnore, + package, + notUpdatedSourceIds, + WatchedSourceIds, + isInsideProject); + }; - if (directoryState == FileState::Changed) { + Utils::set_greedy_difference(subdirectories, + subdirectoriesToIgnore, + updateDirectory, + {}, + &Directory::sourceContextId); + + if (isChanged(directoryState)) { for (const auto &[subdirectoryPath, subdirectoryId] : existingSubdirecories) { package.directoryInfos.emplace_back(directoryId, SourceId::create(SourceNameId{}, subdirectoryId), @@ -532,8 +595,7 @@ void ProjectStorageUpdater::annotationDirectoryChanged( SourceContextId directoryId, SourceContextId annotationDirectoryId, ModuleId moduleId, - Storage::Synchronization::SynchronizationPackage &package, - NotUpdatedSourceIds ¬UpdatedSourceIds) + Storage::Synchronization::SynchronizationPackage &package) { NanotraceHR::Tracer tracer{"annotation directory changed", category(), @@ -542,15 +604,14 @@ void ProjectStorageUpdater::annotationDirectoryChanged( package.updatedPropertyEditorQmlPathDirectoryIds.push_back(annotationDirectoryId); - updatePropertyEditorFiles(directoryPath, annotationDirectoryId, moduleId, package, notUpdatedSourceIds); + updatePropertyEditorFiles(directoryPath, annotationDirectoryId, moduleId, package); } void ProjectStorageUpdater::updatePropertyEditorFiles( Utils::SmallStringView directoryPath, SourceContextId directoryId, ModuleId moduleId, - Storage::Synchronization::SynchronizationPackage &package, - NotUpdatedSourceIds ¬UpdatedSourceIds) + Storage::Synchronization::SynchronizationPackage &package) { NanotraceHR::Tracer tracer{"update property editor files", category(), @@ -562,21 +623,18 @@ void ProjectStorageUpdater::updatePropertyEditorFiles( "*Specifics.qml", "*SpecificsDynamic.qml"}); for (const QString &fileName : fileNames) - updatePropertyEditorFile(fileName, directoryId, moduleId, package, notUpdatedSourceIds); + updatePropertyEditorFile(fileName, directoryId, moduleId, package); } void ProjectStorageUpdater::updatePropertyEditorFile( const QString &fileName, SourceContextId directoryId, ModuleId moduleId, - Storage::Synchronization::SynchronizationPackage &package, - NotUpdatedSourceIds ¬UpdatedSourceIds) + Storage::Synchronization::SynchronizationPackage &package) { Utils::PathString propertyEditorFileName{fileName}; auto propertyEditorSourceId = m_pathCache.sourceId(directoryId, propertyEditorFileName); - fileState(propertyEditorSourceId, package, notUpdatedSourceIds); - QRegularExpression regex{R"xo((\w+)(Specifics|Pane|SpecificsDynamic).qml)xo"}; auto match = regex.match(fileName); @@ -589,7 +647,8 @@ void ProjectStorageUpdater::updateDirectory(const Utils::PathString &directoryPa const SourceContextIds &subdirectoriesToIgnore, Storage::Synchronization::SynchronizationPackage &package, NotUpdatedSourceIds ¬UpdatedSourceIds, - WatchedSourceIdsIds &watchedSourceIdsIds) + WatchedSourceIds &WatchedSourceIds, + IsInsideProject isInsideProject) { NanotraceHR::Tracer tracer{"update directory", category(), keyValue("directory", directoryPath)}; @@ -599,19 +658,19 @@ void ProjectStorageUpdater::updateDirectory(const Utils::PathString &directoryPa auto directoryState = fileState(directoryId, package, notUpdatedSourceIds); if (isExisting(directoryState)) - watchedSourceIdsIds.directoryIds.push_back(SourceId::create(SourceNameId{}, directoryId)); + WatchedSourceIds.directoryIds.push_back(SourceId::create(SourceNameId{}, directoryId)); auto qmldirState = fileState(qmldirSourceId, package, notUpdatedSourceIds); if (isExisting(qmldirState)) - watchedSourceIdsIds.qmldirSourceIds.push_back(qmldirSourceId); + WatchedSourceIds.qmldirSourceIds.push_back(qmldirSourceId); SourcePath annotationDirectoryPath{directoryPath + "/designer"}; auto annotationDirectoryId = m_pathCache.sourceContextId(annotationDirectoryPath); auto annotationDirectoryState = fileState(annotationDirectoryId, package, notUpdatedSourceIds); switch (combineState(directoryState, qmldirState, annotationDirectoryState)) { - case FileState::Changed: case FileState::Added: + case FileState::Changed: tracer.tick("update directory changed"); updateDirectoryChanged(directoryPath, annotationDirectoryPath, @@ -623,7 +682,8 @@ void ProjectStorageUpdater::updateDirectory(const Utils::PathString &directoryPa annotationDirectoryId, package, notUpdatedSourceIds, - watchedSourceIdsIds, + WatchedSourceIds, + isInsideProject, tracer); break; case FileState::Unchanged: @@ -632,7 +692,8 @@ void ProjectStorageUpdater::updateDirectory(const Utils::PathString &directoryPa parseDirectoryInfos(m_projectStorage.fetchDirectoryInfos(directoryId), package, notUpdatedSourceIds, - watchedSourceIdsIds); + WatchedSourceIds, + isInsideProject); break; case FileState::Removed: { tracer.tick("update directory don't exits"); @@ -660,7 +721,8 @@ void ProjectStorageUpdater::updateDirectory(const Utils::PathString &directoryPa subdirectoriesToIgnore, package, notUpdatedSourceIds, - watchedSourceIdsIds); + WatchedSourceIds, + isInsideProject); tracer.end(keyValue("qmldir source path", qmldirPath), keyValue("directory id", directoryId), @@ -693,7 +755,7 @@ void ProjectStorageUpdater::updatePropertyEditorPaths( auto state = fileState(directoryId, package, notUpdatedSourceIds); - if (state == FileState::Changed) { + if (isChanged(state)) { updatePropertyEditorPath(pathInfo.filePath(), package, directoryId, @@ -709,11 +771,7 @@ SmallSourceIds<16> mergedSourceIds(const SourceIds1 &sourceIds1, const SourceIds { SmallSourceIds<16> mergedSourceIds; - std::set_union(sourceIds1.begin(), - sourceIds1.end(), - sourceIds2.begin(), - sourceIds2.end(), - std::back_inserter(mergedSourceIds)); + std::ranges::set_union(sourceIds1, sourceIds2, std::back_inserter(mergedSourceIds)); return mergedSourceIds; } @@ -764,10 +822,10 @@ void ProjectStorageUpdater::updateTypeAnnotations( SourceContextId directoryId = m_pathCache.sourceContextId(Utils::PathString{directoryPath}); auto state = fileState(sourceId, package, notUpdatedSourceIds); - if (state == FileState::Changed) + if (isChangedOrAdded(state)) updateTypeAnnotation(directoryPath, fileInfo.filePath(), sourceId, directoryId, package); - if (state != FileState::Unchanged) + if (isChanged(state)) updatedSourceIdsDictonary[directoryId].push_back(sourceId); } } @@ -780,13 +838,14 @@ void ProjectStorageUpdater::updateTypeAnnotationDirectories( for (auto &[directoryId, updatedSourceIds] : updatedSourceIdsDictonary) { auto directoryState = fileState(directoryId, package, notUpdatedSourceIds); - if (directoryState != FileState::Unchanged) { - auto existingTypeAnnotationSourceIds = m_projectStorage.typeAnnotationSourceIds( - directoryId); + if (isChanged(directoryState)) { + auto storedTypeAnnotationSourceIds = m_projectStorage.typeAnnotationSourceIds(directoryId); + storedTypeAnnotationSourceIds.removeIf( + [&](SourceId sourceId) { return m_fileStatusCache.find(sourceId).isExisting(); }); - std::sort(updatedSourceIds.begin(), updatedSourceIds.end()); + std::ranges::sort(updatedSourceIds); - auto changedSourceIds = mergedSourceIds(existingTypeAnnotationSourceIds, updatedSourceIds); + auto changedSourceIds = mergedSourceIds(storedTypeAnnotationSourceIds, updatedSourceIds); package.updatedTypeAnnotationSourceIds.insert(package.updatedTypeAnnotationSourceIds.end(), changedSourceIds.begin(), changedSourceIds.end()); @@ -881,8 +940,7 @@ void ProjectStorageUpdater::updatePropertyEditorFilePath( typeName, pathId, directoryId); - tracer.tick("append property editor qml paths", - keyValue("property editor qml paths", paths)); + tracer.tick("append property editor qml paths", keyValue("property editor qml paths", paths)); } } @@ -912,6 +970,40 @@ bool contains(const Container &container, Id id) { return std::find(container.begin(), container.end(), id) != container.end(); } + +struct ProjectChunkSourceIds +{ + ProjectChunkSourceIds() + { + directory.reserve(32); + qmlDocument.reserve(128); + qmltypes.reserve(32); + } + + SourceIds directory; + SourceIds qmlDocument; + SourceIds qmltypes; +}; + +void appendProjectChunkSourceIds(ProjectChunkSourceIds &ids, + const ProjectChunkId &projectChunkId, + const SourceIds &sourceIds) +{ + switch (projectChunkId.sourceType) { + case SourceType::Directory: + case SourceType::QmlDir: + ids.directory.insert(ids.directory.end(), sourceIds.begin(), sourceIds.end()); + break; + case SourceType::Qml: + case SourceType::QmlUi: + ids.qmlDocument.insert(ids.qmlDocument.end(), sourceIds.begin(), sourceIds.end()); + break; + case SourceType::QmlTypes: + ids.qmltypes.insert(ids.qmltypes.end(), sourceIds.begin(), sourceIds.end()); + break; + } +} + } // namespace void ProjectStorageUpdater::pathsWithIdsChanged(const std::vector &changedIdPaths) @@ -924,58 +1016,73 @@ void ProjectStorageUpdater::pathsWithIdsChanged(const std::vector &chan Storage::Synchronization::SynchronizationPackage package; - WatchedSourceIdsIds watchedSourceIds{10}; + WatchedSourceIds watchedQtSourceIds{10}; + WatchedSourceIds watchedProjectSourceIds{10}; NotUpdatedSourceIds notUpdatedSourceIds{10}; std::vector idPaths; idPaths.reserve(4); - SourceIds directorySourceIds; - directorySourceIds.reserve(32); - SourceIds qmlDocumentSourceIds; - qmlDocumentSourceIds.reserve(128); - SourceIds qmltypesSourceIds; - qmltypesSourceIds.reserve(32); + ProjectChunkSourceIds project; + ProjectChunkSourceIds qt; for (const auto &[projectChunkId, sourceIds] : m_changedIdPaths) { - if (projectChunkId.id != m_projectPartId) - continue; + if (projectChunkId.id == m_projectPartId) + appendProjectChunkSourceIds(project, projectChunkId, sourceIds); + else if (projectChunkId.id == m_qtPartId) + appendProjectChunkSourceIds(qt, projectChunkId, sourceIds); + } - switch (projectChunkId.sourceType) { - case SourceType::Directory: - case SourceType::QmlDir: - directorySourceIds.insert(directorySourceIds.end(), sourceIds.begin(), sourceIds.end()); - break; - case SourceType::Qml: - case SourceType::QmlUi: - qmlDocumentSourceIds.insert(qmlDocumentSourceIds.end(), sourceIds.begin(), sourceIds.end()); - break; - case SourceType::QmlTypes: - qmltypesSourceIds.insert(qmltypesSourceIds.end(), sourceIds.begin(), sourceIds.end()); - break; + auto updateDirectory = [&](const SourceIds &directorySourceIds, + WatchedSourceIds &watchedSourceIds) { + auto directoryIds = filterUniqueSourceContextIds(directorySourceIds); + for (auto directoryId : directoryIds) { + Utils::PathString directory = m_pathCache.sourceContextPath(directoryId); + this->updateDirectory(directory, + directoryIds, + package, + notUpdatedSourceIds, + watchedSourceIds, + IsInsideProject::No); } - } - auto directoryIds = filterUniqueSourceContextIds(directorySourceIds); + return directoryIds; + }; - for (auto directoryId : directoryIds) { - Utils::PathString directory = m_pathCache.sourceContextPath(directoryId); - updateDirectory(directory, directoryIds, package, notUpdatedSourceIds, watchedSourceIds); - } + auto qtDirectoryIds = updateDirectory(qt.directory, watchedQtSourceIds); + auto projectDirectoryIds = updateDirectory(project.directory, watchedProjectSourceIds); - for (SourceId sourceId : filterUniqueSourceIds(qmlDocumentSourceIds)) { - if (!contains(directoryIds, sourceId.contextId())) - parseQmlComponent(sourceId, package, notUpdatedSourceIds); - } + auto parseQmlComponent = [&](SourceIds qmlDocumentSourceIds, + const SourceContextIds &directoryIds, + IsInsideProject isInsideProject) { + for (SourceId sourceId : filterUniqueSourceIds(std::move(qmlDocumentSourceIds))) { + if (!contains(directoryIds, sourceId.contextId())) + this->parseQmlComponent(sourceId, package, notUpdatedSourceIds, isInsideProject); + } + }; - try { + parseQmlComponent(std::move(qt.qmlDocument), qtDirectoryIds, IsInsideProject::No); + parseQmlComponent(std::move(project.qmlDocument), projectDirectoryIds, IsInsideProject::Yes); + + auto parseTypeInfo = [&](SourceIds qmltypesSourceIds, + const SourceContextIds &directoryIds, + IsInsideProject isInsideProject) { for (SourceId sourceId : filterUniqueSourceIds(std::move(qmltypesSourceIds))) { if (!contains(directoryIds, sourceId.contextId())) { QString qmltypesPath{m_pathCache.sourcePath(sourceId)}; auto directoryInfo = m_projectStorage.fetchDirectoryInfo(sourceId); if (directoryInfo) - parseTypeInfo(*directoryInfo, qmltypesPath, package, notUpdatedSourceIds); + this->parseTypeInfo(*directoryInfo, + qmltypesPath, + package, + notUpdatedSourceIds, + isInsideProject); } } + }; + + try { + parseTypeInfo(std::move(qt.qmltypes), qtDirectoryIds, IsInsideProject::No); + parseTypeInfo(std::move(project.qmltypes), projectDirectoryIds, IsInsideProject::Yes); } catch (const QmlDesigner::CannotParseQmlTypesFile &) { return; } @@ -992,9 +1099,17 @@ void ProjectStorageUpdater::pathsWithIdsChanged(const std::vector &chan return; } - if (directoryIds.size()) { - m_pathWatcher.updateContextIdPaths(createIdPaths(watchedSourceIds, m_projectPartId), - directoryIds); + auto directoryIdsSize = projectDirectoryIds.size() + qtDirectoryIds.size(); + if (directoryIdsSize > 0) { + SourceContextIds directoryIds; + std::vector newIdPaths; + idPaths.reserve(8); + appendIdPaths(std::move(watchedQtSourceIds), m_qtPartId, newIdPaths); + appendIdPaths(std::move(watchedProjectSourceIds), m_projectPartId, newIdPaths); + + directoryIds.reserve(directoryIdsSize); + std::ranges::merge(projectDirectoryIds, qtDirectoryIds, std::back_inserter(directoryIds)); + m_pathWatcher.updateContextIdPaths(newIdPaths, directoryIds); } m_changedIdPaths.clear(); @@ -1010,7 +1125,8 @@ void ProjectStorageUpdater::parseTypeInfos(const QStringList &typeInfos, ModuleId moduleId, Storage::Synchronization::SynchronizationPackage &package, NotUpdatedSourceIds ¬UpdatedSourceIds, - WatchedSourceIdsIds &watchedSourceIds) + WatchedSourceIds &watchedSourceIds, + IsInsideProject isInsideProject) { NanotraceHR::Tracer tracer{"parse type infos", category(), @@ -1043,7 +1159,7 @@ void ProjectStorageUpdater::parseTypeInfos(const QStringList &typeInfos, const QString qmltypesPath = directoryPath + "/" + typeInfo; - parseTypeInfo(directoryInfo, qmltypesPath, package, notUpdatedSourceIds); + parseTypeInfo(directoryInfo, qmltypesPath, package, notUpdatedSourceIds, isInsideProject); } } @@ -1051,7 +1167,8 @@ void ProjectStorageUpdater::parseDirectoryInfos( const Storage::Synchronization::DirectoryInfos &directoryInfos, Storage::Synchronization::SynchronizationPackage &package, NotUpdatedSourceIds ¬UpdatedSourceIds, - WatchedSourceIdsIds &watchedSourceIds) + WatchedSourceIds &watchedSourceIds, + IsInsideProject isInsideProject) { NanotraceHR::Tracer tracer{"parse project datas", category()}; @@ -1061,13 +1178,13 @@ void ProjectStorageUpdater::parseDirectoryInfos( watchedSourceIds.qmltypesSourceIds.push_back(directoryInfo.sourceId); QString qmltypesPath{m_pathCache.sourcePath(directoryInfo.sourceId)}; - parseTypeInfo(directoryInfo, qmltypesPath, package, notUpdatedSourceIds); + parseTypeInfo(directoryInfo, qmltypesPath, package, notUpdatedSourceIds, isInsideProject); break; } case Storage::Synchronization::FileType::QmlDocument: { watchedSourceIds.qmlSourceIds.push_back(directoryInfo.sourceId); - parseQmlComponent(directoryInfo.sourceId, package, notUpdatedSourceIds); + parseQmlComponent(directoryInfo.sourceId, package, notUpdatedSourceIds, isInsideProject); break; } case Storage::Synchronization::FileType::Directory: @@ -1079,11 +1196,10 @@ void ProjectStorageUpdater::parseDirectoryInfos( auto ProjectStorageUpdater::parseTypeInfo(const Storage::Synchronization::DirectoryInfo &directoryInfo, const QString &qmltypesPath, Storage::Synchronization::SynchronizationPackage &package, - NotUpdatedSourceIds ¬UpdatedSourceIds) -> FileState + NotUpdatedSourceIds ¬UpdatedSourceIds, + IsInsideProject isInsideProject) -> FileState { - NanotraceHR::Tracer tracer{"parse type info", - category(), - keyValue("qmltypes path", qmltypesPath)}; + NanotraceHR::Tracer tracer{"parse type info", category(), keyValue("qmltypes path", qmltypesPath)}; auto state = fileState(directoryInfo.sourceId, package, notUpdatedSourceIds); switch (state) { @@ -1093,7 +1209,7 @@ auto ProjectStorageUpdater::parseTypeInfo(const Storage::Synchronization::Direct package.updatedSourceIds.push_back(directoryInfo.sourceId); const auto content = m_fileSystem.contentAsQString(qmltypesPath); - m_qmlTypesParser.parse(content, package.imports, package.types, directoryInfo); + m_qmlTypesParser.parse(content, package.imports, package.types, directoryInfo, isInsideProject); break; } case FileState::Unchanged: { @@ -1118,9 +1234,10 @@ void ProjectStorageUpdater::parseQmlComponent(Utils::SmallStringView relativeFil SourceContextId directoryId, Storage::Synchronization::SynchronizationPackage &package, NotUpdatedSourceIds ¬UpdatedSourceIds, - WatchedSourceIdsIds &watchedSourceIds, + WatchedSourceIds &watchedSourceIds, FileState qmldirState, - SourceId qmldirSourceId) + SourceId qmldirSourceId, + IsInsideProject isInsideProject) { NanotraceHR::Tracer tracer{"parse qml component", category(), @@ -1171,7 +1288,7 @@ void ProjectStorageUpdater::parseQmlComponent(Utils::SmallStringView relativeFil case FileState::Changed: tracer.tick("update from qml document", keyValue("source id", sourceId)); const auto content = m_fileSystem.contentAsQString(QString{qmlFilePath}); - type = m_qmlDocumentParser.parse(content, package.imports, sourceId, directoryPath); + type = m_qmlDocumentParser.parse(content, package.imports, sourceId, directoryPath, isInsideProject); break; } @@ -1193,7 +1310,8 @@ void ProjectStorageUpdater::parseQmlComponent(Utils::SmallStringView relativeFil void ProjectStorageUpdater::parseQmlComponent(SourceId sourceId, Storage::Synchronization::SynchronizationPackage &package, - NotUpdatedSourceIds ¬UpdatedSourceIds) + NotUpdatedSourceIds ¬UpdatedSourceIds, + IsInsideProject isInsideProject) { NanotraceHR::Tracer tracer{"parse qml component", category(), keyValue("source id", sourceId)}; @@ -1210,7 +1328,11 @@ void ProjectStorageUpdater::parseQmlComponent(SourceId sourceId, SourcePath sourcePath = m_pathCache.sourcePath(sourceId); const auto content = m_fileSystem.contentAsQString(QString{sourcePath}); - auto type = m_qmlDocumentParser.parse(content, package.imports, sourceId, sourcePath.directory()); + auto type = m_qmlDocumentParser.parse(content, + package.imports, + sourceId, + sourcePath.directory(), + isInsideProject); type.typeName = sourcePath.name(); type.traits = Storage::TypeTraitsKind::Reference; @@ -1222,15 +1344,6 @@ void ProjectStorageUpdater::parseQmlComponent(SourceId sourceId, package.types.push_back(std::move(type)); } -ProjectStorageUpdater::FileState ProjectStorageUpdater::fileState( - SourceContextId sourceContextId, - Storage::Synchronization::SynchronizationPackage &package, - NotUpdatedSourceIds ¬UpdatedSourceIds) const -{ - auto sourceId = SourceId::create(SourceNameId{}, sourceContextId); - return fileState(sourceId, package, notUpdatedSourceIds); -} - namespace { template @@ -1289,9 +1402,10 @@ void ProjectStorageUpdater::parseQmlComponents(Components components, SourceContextId directoryId, Storage::Synchronization::SynchronizationPackage &package, NotUpdatedSourceIds ¬UpdatedSourceIds, - WatchedSourceIdsIds &watchedSourceIdsIds, + WatchedSourceIds &WatchedSourceIds, FileState qmldirState, - SourceId qmldirSourceId) + SourceId qmldirSourceId, + IsInsideProject isInsideProject) { NanotraceHR::Tracer tracer{"parse qml components", category(), @@ -1312,9 +1426,10 @@ void ProjectStorageUpdater::parseQmlComponents(Components components, directoryId, package, notUpdatedSourceIds, - watchedSourceIdsIds, + WatchedSourceIds, qmldirState, - qmldirSourceId); + qmldirSourceId, + isInsideProject); }; rangeForTheSameFileName(components, callback); @@ -1368,4 +1483,13 @@ ProjectStorageUpdater::FileState ProjectStorageUpdater::fileState( return FileState::Unchanged; } +ProjectStorageUpdater::FileState ProjectStorageUpdater::fileState( + SourceContextId sourceContextId, + Storage::Synchronization::SynchronizationPackage &package, + NotUpdatedSourceIds ¬UpdatedSourceIds) const +{ + auto sourceId = SourceId::create(SourceNameId{}, sourceContextId); + return fileState(sourceId, package, notUpdatedSourceIds); +} + } // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/libs/designercore/projectstorage/projectstorageupdater.h b/src/plugins/qmldesigner/libs/designercore/projectstorage/projectstorageupdater.h index f6cf60c736c..093090c34ef 100644 --- a/src/plugins/qmldesigner/libs/designercore/projectstorage/projectstorageupdater.h +++ b/src/plugins/qmldesigner/libs/designercore/projectstorage/projectstorageupdater.h @@ -50,7 +50,8 @@ public: QmlTypesParserInterface &qmlTypesParser, class ProjectStoragePathWatcherInterface &pathWatcher, ProjectStorageErrorNotifierInterface &errorNotifier, - ProjectPartId projectPartId) + ProjectPartId projectPartId, + ProjectPartId qtPartId) : m_fileSystem{fileSystem} , m_projectStorage{projectStorage} , m_fileStatusCache{fileStatusCache} @@ -60,13 +61,15 @@ public: , m_pathWatcher{pathWatcher} , m_errorNotifier{errorNotifier} , m_projectPartId{projectPartId} + , m_qtPartId{qtPartId} {} struct Update { - QStringList directories = {}; + QStringList qtDirectories = {}; const QString propertyEditorResourcesPath = {}; const QStringList typeAnnotationPaths = {}; + QString projectDirectory = {}; }; void update(Update update); @@ -106,9 +109,9 @@ public: enum class FileState { Unchanged, Changed, NotExists, NotExistsUnchanged, Added, Removed }; - struct WatchedSourceIdsIds + struct WatchedSourceIds { - WatchedSourceIdsIds(std::size_t reserve) + WatchedSourceIds(std::size_t reserve) { directoryIds.reserve(reserve); qmldirSourceIds.reserve(reserve); @@ -135,23 +138,25 @@ public: }; private: + using IsInsideProject = Storage::IsInsideProject; void updateDirectories(const QStringList &directories, Storage::Synchronization::SynchronizationPackage &package, NotUpdatedSourceIds ¬UpdatedSourceIds, - WatchedSourceIdsIds &watchedSourceIdsIds); - + WatchedSourceIds &WatchedSourceIds); void updateDirectory(const Utils::PathString &directory, const SourceContextIds &subdirecoriesToIgnore, Storage::Synchronization::SynchronizationPackage &package, NotUpdatedSourceIds ¬UpdatedSourceIds, - WatchedSourceIdsIds &watchedSourceIdsIds); + WatchedSourceIds &WatchedSourceIds, + IsInsideProject isInsideProject); void updateSubdirectories(const Utils::PathString &directory, SourceContextId directoryId, FileState directoryFileState, const SourceContextIds &subdirecoriesToIgnore, Storage::Synchronization::SynchronizationPackage &package, NotUpdatedSourceIds ¬UpdatedSourceIds, - WatchedSourceIdsIds &watchedSourceIdsIds); + WatchedSourceIds &WatchedSourceIds, + IsInsideProject isInsideProject); void updateDirectoryChanged(Utils::SmallStringView directoryPath, Utils::SmallStringView annotationDirectoryPath, FileState qmldirState, @@ -162,24 +167,22 @@ private: SourceContextId annotationDirectoryId, Storage::Synchronization::SynchronizationPackage &package, NotUpdatedSourceIds ¬UpdatedSourceIds, - WatchedSourceIdsIds &watchedSourceIdsIds, + WatchedSourceIds &WatchedSourceIds, + IsInsideProject isInsideProject, ProjectStorageTracing::Category::TracerType &tracer); void annotationDirectoryChanged(Utils::SmallStringView directoryPath, SourceContextId directoryId, SourceContextId annotationDirectoryId, ModuleId moduleId, - Storage::Synchronization::SynchronizationPackage &package, - NotUpdatedSourceIds ¬UpdatedSourceIds); + Storage::Synchronization::SynchronizationPackage &package); void updatePropertyEditorFiles(Utils::SmallStringView directyPath, SourceContextId directoryId, ModuleId moduleId, - Storage::Synchronization::SynchronizationPackage &package, - NotUpdatedSourceIds ¬UpdatedSourceIds); + Storage::Synchronization::SynchronizationPackage &package); void updatePropertyEditorFile(const QString &fileName, SourceContextId directoryId, ModuleId moduleId, - Storage::Synchronization::SynchronizationPackage &package, - NotUpdatedSourceIds ¬UpdatedSourceIds); + Storage::Synchronization::SynchronizationPackage &package); void updatePropertyEditorPaths(const QString &propertyEditorResourcesPath, Storage::Synchronization::SynchronizationPackage &package, NotUpdatedSourceIds ¬UpdatedSourceIds); @@ -215,34 +218,40 @@ private: ModuleId moduleId, Storage::Synchronization::SynchronizationPackage &package, NotUpdatedSourceIds ¬UpdatedSourceIds, - WatchedSourceIdsIds &watchedSourceIdsIds); + WatchedSourceIds &WatchedSourceIds, + IsInsideProject isInsideProject); void parseDirectoryInfos(const Storage::Synchronization::DirectoryInfos &directoryInfos, Storage::Synchronization::SynchronizationPackage &package, NotUpdatedSourceIds ¬UpdatedSourceIds, - WatchedSourceIdsIds &watchedSourceIdsIds); + WatchedSourceIds &WatchedSourceIds, + IsInsideProject isInsideProject); FileState parseTypeInfo(const Storage::Synchronization::DirectoryInfo &directoryInfo, const QString &qmltypesPath, Storage::Synchronization::SynchronizationPackage &package, - NotUpdatedSourceIds ¬UpdatedSourceIds); + NotUpdatedSourceIds ¬UpdatedSourceIds, + IsInsideProject isInsideProject); void parseQmlComponents(Components components, SourceContextId directoryId, Storage::Synchronization::SynchronizationPackage &package, NotUpdatedSourceIds ¬UpdatedSourceIds, - WatchedSourceIdsIds &watchedSourceIdsIds, + WatchedSourceIds &WatchedSourceIds, FileState qmldirState, - SourceId qmldirSourceId); + SourceId qmldirSourceId, + IsInsideProject isInsideProject); void parseQmlComponent(Utils::SmallStringView fileName, Utils::SmallStringView directory, Storage::Synchronization::ExportedTypes exportedTypes, SourceContextId directoryId, Storage::Synchronization::SynchronizationPackage &package, NotUpdatedSourceIds ¬UpdatedSourceIds, - WatchedSourceIdsIds &watchedSourceIdsIds, + WatchedSourceIds &WatchedSourceIds, FileState qmldirState, - SourceId qmldirSourceId); + SourceId qmldirSourceId, + IsInsideProject isInsideProject); void parseQmlComponent(SourceId sourceId, Storage::Synchronization::SynchronizationPackage &package, - NotUpdatedSourceIds ¬UpdatedSourceIds); + NotUpdatedSourceIds ¬UpdatedSourceIds, + IsInsideProject isInsideProject); FileState fileState(SourceId sourceId, Storage::Synchronization::SynchronizationPackage &package, @@ -262,6 +271,7 @@ private: ProjectStoragePathWatcherInterface &m_pathWatcher; ProjectStorageErrorNotifierInterface &m_errorNotifier; ProjectPartId m_projectPartId; + ProjectPartId m_qtPartId; }; } // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/libs/designercore/projectstorage/qmldocumentparser.cpp b/src/plugins/qmldesigner/libs/designercore/projectstorage/qmldocumentparser.cpp index c8db6e8f6b6..c043a393fb8 100644 --- a/src/plugins/qmldesigner/libs/designercore/projectstorage/qmldocumentparser.cpp +++ b/src/plugins/qmldesigner/libs/designercore/projectstorage/qmldocumentparser.cpp @@ -25,6 +25,7 @@ namespace QmlDesigner { constexpr auto category = ProjectStorageTracing::projectStorageUpdaterCategory; using NanotraceHR::keyValue; +using Storage::IsInsideProject; using Tracer = ProjectStorageTracing::Category::TracerType; namespace QmlDom = QQmlJS::Dom; @@ -306,7 +307,7 @@ bool isSingleton(const QmlDom::QmlFile *qmlFile) return std::ranges::find(pragmas, "Singleton"_L1, &QQmlJS::Dom::Pragma::name) != pragmas.end(); } -Storage::TypeTraits createTypeTraits(const QmlDom::QmlFile *qmlFile) +Storage::TypeTraits createTypeTraits(const QmlDom::QmlFile *qmlFile, IsInsideProject isInsideProject) { Storage::TypeTraits traits = Storage::TypeTraitsKind::Reference; @@ -314,6 +315,8 @@ Storage::TypeTraits createTypeTraits(const QmlDom::QmlFile *qmlFile) traits.isSingleton = isSingleton(qmlFile); + traits.isInsideProject = isInsideProject == IsInsideProject::Yes; + return traits; } @@ -322,7 +325,8 @@ Storage::TypeTraits createTypeTraits(const QmlDom::QmlFile *qmlFile) Storage::Synchronization::Type QmlDocumentParser::parse(const QString &sourceContent, Storage::Imports &imports, SourceId sourceId, - Utils::SmallStringView directoryPath) + Utils::SmallStringView directoryPath, + IsInsideProject isInsideProject) { NanotraceHR::Tracer tracer{"qml document parser parse", category(), @@ -372,7 +376,7 @@ Storage::Synchronization::Type QmlDocumentParser::parse(const QString &sourceCon directoryPath, m_storage); - type.traits = createTypeTraits(qmlFile); + type.traits = createTypeTraits(qmlFile, isInsideProject); type.prototype = createImportedTypeName(qmlObject.name(), qualifiedImports); type.defaultPropertyName = qmlObject.localDefaultPropertyName(); addImports(imports, qmlFile->imports(), sourceId, directoryPath, m_storage); @@ -390,7 +394,8 @@ Storage::Synchronization::Type QmlDocumentParser::parse( [[maybe_unused]] const QString &sourceContent, [[maybe_unused]] Storage::Imports &imports, [[maybe_unused]] SourceId sourceId, - [[maybe_unused]] Utils::SmallStringView directoryPath) + [[maybe_unused]] Utils::SmallStringView directoryPath, + [[maybe_unused]] IsInsideProject isInsideProject) { return Storage::Synchronization::Type{}; } diff --git a/src/plugins/qmldesigner/libs/designercore/projectstorage/qmldocumentparser.h b/src/plugins/qmldesigner/libs/designercore/projectstorage/qmldocumentparser.h index bdf50aac23e..b6ebcc1dc67 100644 --- a/src/plugins/qmldesigner/libs/designercore/projectstorage/qmldocumentparser.h +++ b/src/plugins/qmldesigner/libs/designercore/projectstorage/qmldocumentparser.h @@ -32,7 +32,8 @@ public: Storage::Synchronization::Type parse(const QString &sourceContent, Storage::Imports &imports, SourceId sourceId, - Utils::SmallStringView directoryPath) override; + Utils::SmallStringView directoryPath, + IsInsideProject isInsideProject) override; private: // m_pathCache and m_storage are only used when compiled for QDS diff --git a/src/plugins/qmldesigner/libs/designercore/projectstorage/qmldocumentparserinterface.h b/src/plugins/qmldesigner/libs/designercore/projectstorage/qmldocumentparserinterface.h index 20d7083fc77..2be646e1aef 100644 --- a/src/plugins/qmldesigner/libs/designercore/projectstorage/qmldocumentparserinterface.h +++ b/src/plugins/qmldesigner/libs/designercore/projectstorage/qmldocumentparserinterface.h @@ -12,10 +12,13 @@ namespace QmlDesigner { class QmlDocumentParserInterface { public: + using IsInsideProject = Storage::IsInsideProject; + virtual Storage::Synchronization::Type parse(const QString &sourceContent, Storage::Imports &imports, SourceId sourceId, - Utils::SmallStringView directoryPath) + Utils::SmallStringView directoryPath, + IsInsideProject isInsideProject) = 0; protected: diff --git a/src/plugins/qmldesigner/libs/designercore/projectstorage/qmltypesparser.cpp b/src/plugins/qmldesigner/libs/designercore/projectstorage/qmltypesparser.cpp index 807889a71f2..11066e3307f 100644 --- a/src/plugins/qmldesigner/libs/designercore/projectstorage/qmltypesparser.cpp +++ b/src/plugins/qmldesigner/libs/designercore/projectstorage/qmltypesparser.cpp @@ -27,6 +27,7 @@ namespace QmlDesigner { constexpr auto category = ProjectStorageTracing::projectStorageUpdaterCategory; using NanotraceHR::keyValue; +using Storage::IsInsideProject; using Tracer = ProjectStorageTracing::Category::TracerType; using Storage::ModuleKind; namespace QmlDom = QQmlJS::Dom; @@ -120,15 +121,16 @@ Storage::TypeTraits createAccessTypeTraits(QQmlJSScope::AccessSemantics accessSe Storage::TypeTraits createTypeTraits(QQmlJSScope::AccessSemantics accessSematics, bool hasCustomParser, - bool isSingleton) + bool isSingleton, + IsInsideProject isInsideProject) { auto typeTrait = createAccessTypeTraits(accessSematics); - if (hasCustomParser) - typeTrait.usesCustomParser = true; + typeTrait.usesCustomParser = hasCustomParser; - if (isSingleton) - typeTrait.isSingleton = true; + typeTrait.isSingleton = isSingleton; + + typeTrait.isInsideProject = isInsideProject == IsInsideProject::Yes; return typeTrait; } @@ -444,7 +446,8 @@ void addType(Storage::Synchronization::Types &types, ModuleId cppModuleId, const QQmlJSExportedScope &exportScope, QmlTypesParser::ProjectStorage &storage, - const ComponentWithoutNamespaces &componentNameWithoutNamespace) + const ComponentWithoutNamespaces &componentNameWithoutNamespace, + IsInsideProject isInsideProject) { NanotraceHR::Tracer tracer{"add type", category(), @@ -466,7 +469,8 @@ void addType(Storage::Synchronization::Types &types, Storage::Synchronization::ImportedType{extensionTypeName(component)}, createTypeTraits(component.accessSemantics(), component.hasCustomParser(), - component.isSingleton()), + component.isSingleton(), + isInsideProject), sourceId, createExports(exports, typeName, storage, cppModuleId), createProperties(component.ownProperties(), enumerationTypes, componentNameWithoutNamespace), @@ -509,7 +513,8 @@ void addTypes(Storage::Synchronization::Types &types, const Storage::Synchronization::DirectoryInfo &directoryInfo, const QList &objects, QmlTypesParser::ProjectStorage &storage, - const ComponentWithoutNamespaces &componentNameWithoutNamespaces) + const ComponentWithoutNamespaces &componentNameWithoutNamespaces, + IsInsideProject isInsideProject) { NanotraceHR::Tracer tracer{"add types", category()}; types.reserve(Utils::usize(objects) + types.size()); @@ -525,7 +530,8 @@ void addTypes(Storage::Synchronization::Types &types, directoryInfo.moduleId, object, storage, - componentNameWithoutNamespaces); + componentNameWithoutNamespaces, + isInsideProject); } } @@ -534,7 +540,8 @@ void addTypes(Storage::Synchronization::Types &types, void QmlTypesParser::parse(const QString &sourceContent, Storage::Imports &imports, Storage::Synchronization::Types &types, - const Storage::Synchronization::DirectoryInfo &directoryInfo) + const Storage::Synchronization::DirectoryInfo &directoryInfo, + IsInsideProject isInsideProject) { NanotraceHR::Tracer tracer{"qmltypes parser parse", category()}; @@ -548,7 +555,7 @@ void QmlTypesParser::parse(const QString &sourceContent, auto componentNameWithoutNamespaces = createComponentNameWithoutNamespaces(components); addImports(imports, directoryInfo.sourceId, dependencies, m_storage, directoryInfo.moduleId); - addTypes(types, directoryInfo, components, m_storage, componentNameWithoutNamespaces); + addTypes(types, directoryInfo, components, m_storage, componentNameWithoutNamespaces, isInsideProject); } #else @@ -556,7 +563,8 @@ void QmlTypesParser::parse(const QString &sourceContent, void QmlTypesParser::parse([[maybe_unused]] const QString &sourceContent, [[maybe_unused]] Storage::Imports &imports, [[maybe_unused]] Storage::Synchronization::Types &types, - [[maybe_unused]] const Storage::Synchronization::DirectoryInfo &directoryInfo) + [[maybe_unused]] const Storage::Synchronization::DirectoryInfo &directoryInfo, + [[maybe_unused]] IsInsideProject isInsideProject) {} #endif diff --git a/src/plugins/qmldesigner/libs/designercore/projectstorage/qmltypesparser.h b/src/plugins/qmldesigner/libs/designercore/projectstorage/qmltypesparser.h index b2c40fddd38..8dd6d307d0d 100644 --- a/src/plugins/qmldesigner/libs/designercore/projectstorage/qmltypesparser.h +++ b/src/plugins/qmldesigner/libs/designercore/projectstorage/qmltypesparser.h @@ -33,7 +33,8 @@ public: void parse(const QString &sourceContent, Storage::Imports &imports, Storage::Synchronization::Types &types, - const Storage::Synchronization::DirectoryInfo &directoryInfo) override; + const Storage::Synchronization::DirectoryInfo &directoryInfo, + IsInsideProject isInsideProject) override; private: #ifdef QDS_BUILD_QMLPARSER diff --git a/src/plugins/qmldesigner/libs/designercore/projectstorage/qmltypesparserinterface.h b/src/plugins/qmldesigner/libs/designercore/projectstorage/qmltypesparserinterface.h index c0880cf5c64..e4eb88c6922 100644 --- a/src/plugins/qmldesigner/libs/designercore/projectstorage/qmltypesparserinterface.h +++ b/src/plugins/qmldesigner/libs/designercore/projectstorage/qmltypesparserinterface.h @@ -12,10 +12,13 @@ namespace QmlDesigner { class QmlTypesParserInterface { public: + using IsInsideProject = Storage::IsInsideProject; + virtual void parse(const QString &sourceContent, Storage::Imports &imports, Storage::Synchronization::Types &types, - const Storage::Synchronization::DirectoryInfo &directoryInfo) + const Storage::Synchronization::DirectoryInfo &directoryInfo, + IsInsideProject isInsideProject) = 0; protected: diff --git a/src/plugins/qmldesigner/project/qmldesignerprojectmanager.cpp b/src/plugins/qmldesigner/project/qmldesignerprojectmanager.cpp index 4361322af28..45e1d811af4 100644 --- a/src/plugins/qmldesigner/project/qmldesignerprojectmanager.cpp +++ b/src/plugins/qmldesigner/project/qmldesignerprojectmanager.cpp @@ -184,6 +184,24 @@ Sqlite::JournalMode projectStorageJournalMode() return Sqlite::JournalMode::Wal; } +[[maybe_unused]] QString qmlPath(::ProjectExplorer::Target *target) +{ + auto qt = QtSupport::QtKitAspect::qtVersion(target->kit()); + if (qt) + return qt->qmlPath().path(); + + return QLibraryInfo::path(QLibraryInfo::QmlImportsPath); +} + +[[maybe_unused]] QString qmlPath(::ProjectExplorer::Project *project) +{ + auto qt = QtSupport::QtKitAspect::qtVersion(project->activeKit()); + if (qt) + return qt->qmlPath().path(); + + return QLibraryInfo::path(QLibraryInfo::QmlImportsPath); +} + class ProjectStorageData { public: @@ -195,7 +213,10 @@ public: , qmlDocumentParser{storage, pathCache} , pathWatcher{pathCache, fileSystem, &updater} , projectPartId{ProjectPartId::create( - pathCache.sourceId(SourcePath{project->projectDirectory().toUrlishString() + "/."}).internalId())} + pathCache.sourceContextId(Utils::PathString{project->projectDirectory().path()}) + .internalId())} + , qtPartId{ProjectPartId::create( + pathCache.sourceContextId(Utils::PathString{qmlPath(project)}).internalId())} , updater{fileSystem, storage, fileStatusCache, @@ -204,7 +225,8 @@ public: qmlTypesParser, pathWatcher, errorNotifier, - projectPartId} + projectPartId, + qtPartId} {} Sqlite::Database database; ProjectStorageErrorNotifier errorNotifier; @@ -215,6 +237,7 @@ public: QmlTypesParser qmlTypesParser{storage}; ProjectStoragePathWatcher pathWatcher; ProjectPartId projectPartId; + ProjectPartId qtPartId; ProjectStorageUpdater updater; }; @@ -363,22 +386,11 @@ void QmlDesignerProjectManager::editorsClosed(const QList<::Core::IEditor *> &) namespace { -[[maybe_unused]] QString qmlPath(::ProjectExplorer::Target *target) -{ - auto qt = QtSupport::QtKitAspect::qtVersion(target->kit()); - if (qt) - return qt->qmlPath().path(); - - return QLibraryInfo::path(QLibraryInfo::QmlImportsPath); -} - -[[maybe_unused]] void projectQmldirPaths(::ProjectExplorer::Target *target, QStringList &qmldirPaths) +[[maybe_unused]] QString projectDirectory(::ProjectExplorer::Target *target) { ::QmlProjectManager::QmlBuildSystem *buildSystem = getQmlBuildSystem(target); - const Utils::FilePath projectDirectoryPath = buildSystem->canonicalProjectDir(); - - qmldirPaths.push_back(projectDirectoryPath.path()); + return buildSystem->canonicalProjectDir().path(); } [[maybe_unused]] void qtQmldirPaths(::ProjectExplorer::Target *target, QStringList &qmldirPaths) @@ -414,10 +426,6 @@ namespace { qmldirPaths.reserve(100); qtQmldirPaths(target, qmldirPaths); - projectQmldirPaths(target, qmldirPaths); - - std::sort(qmldirPaths.begin(), qmldirPaths.end()); - qmldirPaths.erase(std::unique(qmldirPaths.begin(), qmldirPaths.end()), qmldirPaths.end()); return qmldirPaths; } @@ -584,13 +592,17 @@ void QmlDesignerProjectManager::update() try { if constexpr (isUsingQmlDesignerLite()) { - m_projectData->projectStorageData->updater.update({directoriesForLiteDesigner(), - propertyEditorResourcesPath(), - {qtCreatorItemLibraryPath()}}); + m_projectData->projectStorageData->updater.update( + {directoriesForLiteDesigner(), + propertyEditorResourcesPath(), + {qtCreatorItemLibraryPath()}, + projectDirectory(m_projectData->activeTarget)}); } else { - m_projectData->projectStorageData->updater.update({directories(m_projectData->activeTarget), - propertyEditorResourcesPath(), - {qtCreatorItemLibraryPath()}}); + m_projectData->projectStorageData->updater.update( + {directories(m_projectData->activeTarget), + propertyEditorResourcesPath(), + {qtCreatorItemLibraryPath()}, + projectDirectory(m_projectData->activeTarget)}); } } catch (const Sqlite::Exception &exception) { const auto &location = exception.location(); diff --git a/tests/unit/tests/mocks/qmldocumentparsermock.h b/tests/unit/tests/mocks/qmldocumentparsermock.h index 242fd3c277e..a75e78f296b 100644 --- a/tests/unit/tests/mocks/qmldocumentparsermock.h +++ b/tests/unit/tests/mocks/qmldocumentparsermock.h @@ -15,6 +15,7 @@ public: (const QString &sourceContent, QmlDesigner::Storage::Imports &imports, QmlDesigner::SourceId sourceId, - Utils::SmallStringView directoryPath), + Utils::SmallStringView directoryPath, + IsInsideProject isInsideProject), (override)); }; diff --git a/tests/unit/tests/mocks/qmltypesparsermock.h b/tests/unit/tests/mocks/qmltypesparsermock.h index 0f57c634d07..36afebdb4d2 100644 --- a/tests/unit/tests/mocks/qmltypesparsermock.h +++ b/tests/unit/tests/mocks/qmltypesparsermock.h @@ -15,6 +15,7 @@ public: (const QString &sourceContent, QmlDesigner::Storage::Imports &imports, QmlDesigner::Storage::Synchronization::Types &types, - const QmlDesigner::Storage::Synchronization::DirectoryInfo &directoryInfo), + const QmlDesigner::Storage::Synchronization::DirectoryInfo &directoryInfo, + IsInsideProject isInsideProject), (override)); }; diff --git a/tests/unit/tests/printers/gtest-creator-printing.cpp b/tests/unit/tests/printers/gtest-creator-printing.cpp index 73909bbf66e..40cc868edea 100644 --- a/tests/unit/tests/printers/gtest-creator-printing.cpp +++ b/tests/unit/tests/printers/gtest-creator-printing.cpp @@ -709,6 +709,17 @@ std::ostream &operator<<(std::ostream &out, PropertyDeclarationTraits traits) return out << ")"; } +std::ostream &operator<<(std::ostream &out, IsInsideProject isInsideProject) +{ + switch (isInsideProject) { + case IsInsideProject::No: + return out << "IsInsideProject::No"; + case IsInsideProject::Yes: + return out << "IsInsideProject::Yes"; + } + return out; +} + std::ostream &operator<<(std::ostream &out, VersionNumber versionNumber) { return out << versionNumber.value; diff --git a/tests/unit/tests/printers/gtest-creator-printing.h b/tests/unit/tests/printers/gtest-creator-printing.h index 1438c889b8c..cb5731c53e6 100644 --- a/tests/unit/tests/printers/gtest-creator-printing.h +++ b/tests/unit/tests/printers/gtest-creator-printing.h @@ -182,6 +182,7 @@ std::ostream &operator<<(std::ostream &out, const FontCollectorSizesAuxiliaryDat namespace Storage { enum class PropertyDeclarationTraits : int; enum class TypeTraitsKind : unsigned int; +enum class IsInsideProject : char; struct TypeTraits; class Import; class Version; @@ -190,6 +191,7 @@ class VersionNumber; std::ostream &operator<<(std::ostream &out, PropertyDeclarationTraits traits); std::ostream &operator<<(std::ostream &out, TypeTraitsKind kind); std::ostream &operator<<(std::ostream &out, TypeTraits traits); +std::ostream &operator<<(std::ostream &out, IsInsideProject isInsideProject); std::ostream &operator<<(std::ostream &out, const Import &import); std::ostream &operator<<(std::ostream &out, VersionNumber versionNumber); std::ostream &operator<<(std::ostream &out, Version version); diff --git a/tests/unit/tests/unittests/metainfo/nodemetainfo-test.cpp b/tests/unit/tests/unittests/metainfo/nodemetainfo-test.cpp index 925834b8235..ed28cb28544 100644 --- a/tests/unit/tests/unittests/metainfo/nodemetainfo-test.cpp +++ b/tests/unit/tests/unittests/metainfo/nodemetainfo-test.cpp @@ -273,6 +273,43 @@ TEST_F(NodeMetaInfo, component_is_singleton) ASSERT_TRUE(isSingleton); } +TEST_F(NodeMetaInfo, object_is_not_inside_project) +{ + bool isInsideProject = objectMetaInfo.isInsideProject(); + + ASSERT_FALSE(isInsideProject); +} + +TEST_F(NodeMetaInfo, default_is_not_inside_project) +{ + bool isInsideProject = QmlDesigner::NodeMetaInfo{}.isInsideProject(); + + ASSERT_FALSE(isInsideProject); +} + +TEST_F(NodeMetaInfo, invalid_is_not_inside_project) +{ + auto node = model.createModelNode("Foo"); + auto metaInfo = node.metaInfo(); + + bool isInsideProject = metaInfo.isInsideProject(); + + ASSERT_FALSE(isInsideProject); +} + +TEST_F(NodeMetaInfo, component_is_inside_project) +{ + auto moduleId = projectStorageMock.createModule("/path/to/project", ModuleKind::PathLibrary); + TypeTraits traits{TypeTraitsKind::Reference}; + traits.isInsideProject = true; + auto typeId = projectStorageMock.createType(moduleId, "Foo", traits); + QmlDesigner::NodeMetaInfo metaInfo{typeId, &projectStorageMock}; + + bool isInsideProject = metaInfo.isInsideProject(); + + ASSERT_TRUE(isInsideProject); +} + TEST_F(NodeMetaInfo, has_property) { auto metaInfo = model.qtQuickItemMetaInfo(); @@ -3355,3 +3392,4 @@ TEST_F(NodeMetaInfo, no_item_library_entries_for_default) } } // namespace + diff --git a/tests/unit/tests/unittests/projectstorage/projectstorageupdater-test.cpp b/tests/unit/tests/unittests/projectstorage/projectstorageupdater-test.cpp index 2d7df558c9b..17fd86b033b 100644 --- a/tests/unit/tests/unittests/projectstorage/projectstorageupdater-test.cpp +++ b/tests/unit/tests/unittests/projectstorage/projectstorageupdater-test.cpp @@ -31,6 +31,7 @@ using QmlDesigner::SourceNameId; namespace Storage = QmlDesigner::Storage; using QmlDesigner::IdPaths; using Storage::Import; +using Storage::IsInsideProject; using Storage::ModuleKind; using Storage::Synchronization::ChangeLevel; using Storage::Synchronization::DirectoryInfo; @@ -171,12 +172,8 @@ public: ProjectStorageUpdater() { - setFilesChanged({qmltypesPathSourceId, - qmltypes2PathSourceId, - qmlDirPathSourceId, - qmlDocumentSourceId1, - qmlDocumentSourceId2, - qmlDocumentSourceId3}); + setFilesChanged({qmltypesPathSourceId, qmlDirPathSourceId, qmlDocumentSourceId1}); + setFilesAdded({qmltypes2PathSourceId, qmlDocumentSourceId2, qmlDocumentSourceId3}); setFilesDontChanged({directoryPathSourceId, path1SourceId, @@ -222,28 +219,28 @@ public: setContent(u"/path/one/example.qmltypes", qmltypes1); setContent(u"/path/two/example2.qmltypes", qmltypes2); - ON_CALL(qmlDocumentParserMock, parse(qmlDocument1, _, _, _)) - .WillByDefault([&](auto, auto &imports, auto, auto) { + ON_CALL(qmlDocumentParserMock, parse(qmlDocument1, _, _, _, _)) + .WillByDefault([&](auto, auto &imports, auto, auto, auto) { imports.push_back(import1); return firstType; }); - ON_CALL(qmlDocumentParserMock, parse(qmlDocument2, _, _, _)) - .WillByDefault([&](auto, auto &imports, auto, auto) { + ON_CALL(qmlDocumentParserMock, parse(qmlDocument2, _, _, _, _)) + .WillByDefault([&](auto, auto &imports, auto, auto, auto) { imports.push_back(import2); return secondType; }); - ON_CALL(qmlDocumentParserMock, parse(qmlDocument3, _, _, _)) - .WillByDefault([&](auto, auto &imports, auto, auto) { + ON_CALL(qmlDocumentParserMock, parse(qmlDocument3, _, _, _, _)) + .WillByDefault([&](auto, auto &imports, auto, auto, auto) { imports.push_back(import3); return thirdType; }); - ON_CALL(qmlTypesParserMock, parse(Eq(qmltypes1), _, _, _)) - .WillByDefault([&](auto, auto &imports, auto &types, auto) { + ON_CALL(qmlTypesParserMock, parse(Eq(qmltypes1), _, _, _, _)) + .WillByDefault([&](auto, auto &imports, auto &types, auto, auto) { types.push_back(objectType); imports.push_back(import4); }); - ON_CALL(qmlTypesParserMock, parse(Eq(qmltypes2), _, _, _)) - .WillByDefault([&](auto, auto &imports, auto &types, auto) { + ON_CALL(qmlTypesParserMock, parse(Eq(qmltypes2), _, _, _, _)) + .WillByDefault([&](auto, auto &imports, auto &types, auto, auto) { types.push_back(itemType); imports.push_back(import5); }); @@ -386,7 +383,8 @@ protected: NiceMock patchWatcherMock; NiceMock errorNotifierMock; QmlDesigner::ProjectPartId projectPartId = QmlDesigner::ProjectPartId::create(1); - QmlDesigner::ProjectPartId otherProjectPartId = QmlDesigner::ProjectPartId::create(0); + QmlDesigner::ProjectPartId otherProjectPartId = QmlDesigner::ProjectPartId::create(2); + QmlDesigner::ProjectPartId qtPartId = QmlDesigner::ProjectPartId::create(10); QmlDesigner::ProjectStorageUpdater updater{fileSystemMock, projectStorageMock, fileStatusCache, @@ -395,7 +393,8 @@ protected: qmlTypesParserMock, patchWatcherMock, errorNotifierMock, - projectPartId}; + projectPartId, + qtPartId}; SourceId qmltypesPathSourceId = sourcePathCache.sourceId("/path/example.qmltypes"); SourceId qmltypes2PathSourceId = sourcePathCache.sourceId("/path/example2.qmltypes"); SourceId qmlDirPathSourceId = sourcePathCache.sourceId("/path/qmldir"); @@ -454,12 +453,10 @@ protected: QStringList directories = {"/path"}; QStringList directories2 = {"/path/one", "/path/two"}; QStringList directories3 = {"/path/one", "/path/two", "/path/three"}; - QmlDesigner::ProjectChunkId directoryProjectChunkId{projectPartId, - QmlDesigner::SourceType::Directory}; - QmlDesigner::ProjectChunkId qmldirProjectChunkId{projectPartId, QmlDesigner::SourceType::QmlDir}; - QmlDesigner::ProjectChunkId qmlDocumentProjectChunkId{projectPartId, QmlDesigner::SourceType::Qml}; - QmlDesigner::ProjectChunkId qmltypesProjectChunkId{projectPartId, - QmlDesigner::SourceType::QmlTypes}; + QmlDesigner::ProjectChunkId directoryProjectChunkId{qtPartId, QmlDesigner::SourceType::Directory}; + QmlDesigner::ProjectChunkId qmldirProjectChunkId{qtPartId, QmlDesigner::SourceType::QmlDir}; + QmlDesigner::ProjectChunkId qmlDocumentProjectChunkId{qtPartId, QmlDesigner::SourceType::Qml}; + QmlDesigner::ProjectChunkId qmltypesProjectChunkId{qtPartId, QmlDesigner::SourceType::QmlTypes}; QmlDesigner::ProjectChunkId otherDirectoryProjectChunkId{otherProjectPartId, QmlDesigner::SourceType::Directory}; QmlDesigner::ProjectChunkId otherQmldirProjectChunkId{otherProjectPartId, @@ -491,13 +488,14 @@ TEST_F(ProjectStorageUpdater, get_content_for_qml_dir_paths_if_file_status_is_di SourceId qmlDir3PathSourceId = sourcePathCache.sourceId("/path/three/qmldir"); SourceId path3SourceId = createDirectorySourceId("/path/three"); QStringList directories = {"/path/one", "/path/two", "/path/three"}; - setFilesChanged({qmlDir1PathSourceId, qmlDir2PathSourceId}); + setFilesChanged({qmlDir1PathSourceId}); + setFilesAdded({qmlDir2PathSourceId}); setFilesDontChanged({qmlDir3PathSourceId, path3SourceId}); EXPECT_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/one/qmldir")))); EXPECT_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/two/qmldir")))); - updater.update({.directories = directories}); + updater.update({.qtDirectories = directories}); } TEST_F(ProjectStorageUpdater, @@ -509,13 +507,14 @@ TEST_F(ProjectStorageUpdater, SourceId path3SourceId = createDirectorySourceId("/path/three"); QStringList directories = {"/path/one"}; setSubdirectoryPaths(u"/path/one", {"/path/two", "/path/three"}); - setFilesChanged({qmlDir1PathSourceId, qmlDir2PathSourceId}); + setFilesChanged({qmlDir1PathSourceId}); + setFilesAdded({qmlDir2PathSourceId}); setFilesDontChanged({qmlDir3PathSourceId, path3SourceId}); EXPECT_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/one/qmldir")))); EXPECT_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/two/qmldir")))); - updater.update({.directories = directories}); + updater.update({.qtDirectories = directories}); } TEST_F(ProjectStorageUpdater, request_file_status_from_file_system) @@ -524,7 +523,7 @@ TEST_F(ProjectStorageUpdater, request_file_status_from_file_system) EXPECT_CALL(fileSystemMock, fileStatus(Eq(directoryPathSourceId))); - updater.update({.directories = directories}); + updater.update({.qtDirectories = directories}); } TEST_F(ProjectStorageUpdater, request_file_status_from_file_system_for_subdirectories) @@ -538,7 +537,7 @@ TEST_F(ProjectStorageUpdater, request_file_status_from_file_system_for_subdirect EXPECT_CALL(fileSystemMock, fileStatus(Eq(path2SourceId))); EXPECT_CALL(fileSystemMock, fileStatus(Eq(directoryPathSourceId))); - updater.update({.directories = directories}); + updater.update({.qtDirectories = directories}); } TEST_F(ProjectStorageUpdater, get_content_for_qml_types) @@ -550,7 +549,7 @@ TEST_F(ProjectStorageUpdater, get_content_for_qml_types) EXPECT_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/example.qmltypes")))); - updater.update({.directories = directories}); + updater.update({.qtDirectories = directories}); } TEST_F(ProjectStorageUpdater, get_content_for_qml_types_if_project_storage_file_status_is_invalid) @@ -563,7 +562,7 @@ TEST_F(ProjectStorageUpdater, get_content_for_qml_types_if_project_storage_file_ EXPECT_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/example.qmltypes")))); - updater.update({.directories = directories}); + updater.update({.qtDirectories = directories}); } TEST_F(ProjectStorageUpdater, parse_qml_types) @@ -581,18 +580,89 @@ TEST_F(ProjectStorageUpdater, parse_qml_types) parse(qmltypes, _, _, - Field("DirectoryInfo::moduleId", - &DirectoryInfo::moduleId, - exampleCppNativeModuleId))); + Field("DirectoryInfo::moduleId", &DirectoryInfo::moduleId, exampleCppNativeModuleId), + IsInsideProject::No)); EXPECT_CALL(qmlTypesParserMock, parse(qmltypes2, _, _, - Field("DirectoryInfo::moduleId", - &DirectoryInfo::moduleId, - exampleCppNativeModuleId))); + Field("DirectoryInfo::moduleId", &DirectoryInfo::moduleId, exampleCppNativeModuleId), + IsInsideProject::No)); - updater.update({.directories = directories}); + updater.update({.qtDirectories = directories}); +} + +TEST_F(ProjectStorageUpdater, parse_added_qml_types) +{ + QString qmldir{R"(module Example + typeinfo example.qmltypes + typeinfo example2.qmltypes)"}; + setContent(u"/path/qmldir", qmldir); + QString qmltypes{"Module {\ndependencies: []}"}; + QString qmltypes2{"Module {\ndependencies: [foo]}"}; + setContent(u"/path/example.qmltypes", qmltypes); + setContent(u"/path/example2.qmltypes", qmltypes2); + setFilesAdded({directoryPathSourceId, + qmlDirPathSourceId, + qmltypesPathSourceId, + qmltypes2PathSourceId, + qmlDocumentSourceId2, + qmlDocumentSourceId3}); + + EXPECT_CALL(qmlTypesParserMock, + parse(qmltypes, + _, + _, + Field("DirectoryInfo::moduleId", &DirectoryInfo::moduleId, exampleCppNativeModuleId), + IsInsideProject::No)); + EXPECT_CALL(qmlTypesParserMock, + parse(qmltypes2, + _, + _, + Field("DirectoryInfo::moduleId", &DirectoryInfo::moduleId, exampleCppNativeModuleId), + IsInsideProject::No)); + + updater.update({.qtDirectories = directories}); +} + +TEST_F(ProjectStorageUpdater, parse_qml_types_in_project) +{ + QString qmldir{R"(module Example + typeinfo example.qmltypes)"}; + setContent(u"/path/qmldir", qmldir); + QString qmltypes{"Module {\ndependencies: []}"}; + setContent(u"/path/example.qmltypes", qmltypes); + + EXPECT_CALL(qmlTypesParserMock, parse(qmltypes, _, _, _, IsInsideProject::Yes)); + + updater.update({.projectDirectory = "/path"}); +} + +TEST_F(ProjectStorageUpdater, parse_qml_types_inside_project) +{ + QString qmldir{R"(module Example + typeinfo example.qmltypes + typeinfo example2.qmltypes)"}; + setContent(u"/path/qmldir", qmldir); + QString qmltypes{"Module {\ndependencies: []}"}; + QString qmltypes2{"Module {\ndependencies: [foo]}"}; + setContent(u"/path/example.qmltypes", qmltypes); + setContent(u"/path/example2.qmltypes", qmltypes2); + + EXPECT_CALL(qmlTypesParserMock, + parse(qmltypes, + _, + _, + Field("DirectoryInfo::moduleId", &DirectoryInfo::moduleId, exampleCppNativeModuleId), + IsInsideProject::Yes)); + EXPECT_CALL(qmlTypesParserMock, + parse(qmltypes2, + _, + _, + Field("DirectoryInfo::moduleId", &DirectoryInfo::moduleId, exampleCppNativeModuleId), + IsInsideProject::Yes)); + + updater.update({.projectDirectory = "/path"}); } TEST_F(ProjectStorageUpdater, parse_qml_types_in_subdirectories) @@ -612,18 +682,16 @@ TEST_F(ProjectStorageUpdater, parse_qml_types_in_subdirectories) parse(qmltypes, _, _, - Field("DirectoryInfo::moduleId", - &DirectoryInfo::moduleId, - exampleCppNativeModuleId))); + Field("DirectoryInfo::moduleId", &DirectoryInfo::moduleId, exampleCppNativeModuleId), + IsInsideProject::No)); EXPECT_CALL(qmlTypesParserMock, parse(qmltypes2, _, _, - Field("DirectoryInfo::moduleId", - &DirectoryInfo::moduleId, - exampleCppNativeModuleId))); + Field("DirectoryInfo::moduleId", &DirectoryInfo::moduleId, exampleCppNativeModuleId), + IsInsideProject::No)); - updater.update({.directories = directories}); + updater.update({.qtDirectories = directories}); } TEST_F(ProjectStorageUpdater, synchronize_is_empty_for_no_change) @@ -632,7 +700,7 @@ TEST_F(ProjectStorageUpdater, synchronize_is_empty_for_no_change) EXPECT_CALL(projectStorageMock, synchronize(PackageIsEmpty())); - updater.update({.directories = directories}); + updater.update({.qtDirectories = directories}); } TEST_F(ProjectStorageUpdater, synchronize_is_empty_for_no_change_in_subdirectory) @@ -649,7 +717,49 @@ TEST_F(ProjectStorageUpdater, synchronize_is_empty_for_no_change_in_subdirectory EXPECT_CALL(projectStorageMock, synchronize(PackageIsEmpty())); - updater.update({.directories = directories}); + updater.update({.qtDirectories = directories}); +} + +TEST_F(ProjectStorageUpdater, synchronize_is_empty_for_ignored_subdirectory) +{ + SourceId qmlDirRootPathSourceId = sourcePathCache.sourceId("/root/qmldir"); + SourceId ignoreInQdsSourceId = sourcePathCache.sourceId("/path/ignore-in-qds"); + SourceId rootPathSourceId = createDirectorySourceId("/root"); + setFilesChanged({qmltypesPathSourceId, qmltypes2PathSourceId, qmlDirPathSourceId}); + setFilesDontChanged({rootPathSourceId, qmlDirRootPathSourceId, ignoreInQdsSourceId}); + setSubdirectoryPaths(u"/root", {"/path"}); + + EXPECT_CALL(projectStorageMock, synchronize(PackageIsEmpty())); + + updater.update({.projectDirectory = "/root"}); +} + +TEST_F(ProjectStorageUpdater, synchronize_is_empty_for_added_ignored_subdirectory) +{ + SourceId qmlDirRootPathSourceId = sourcePathCache.sourceId("/root/qmldir"); + SourceId ignoreInQdsSourceId = sourcePathCache.sourceId("/path/ignore-in-qds"); + SourceId rootPathSourceId = createDirectorySourceId("/root"); + setFilesChanged({qmltypesPathSourceId, qmltypes2PathSourceId, qmlDirPathSourceId}); + setFilesAdded({ignoreInQdsSourceId}); + setFilesDontChanged({rootPathSourceId, qmlDirRootPathSourceId}); + setSubdirectoryPaths(u"/root", {"/path"}); + + EXPECT_CALL( + projectStorageMock, + synchronize( + AllOf(Field("SynchronizationPackage::imports", &SynchronizationPackage::imports, IsEmpty()), + Field("SynchronizationPackage::types", &SynchronizationPackage::types, IsEmpty()), + Field("SynchronizationPackage::updatedSourceIds", + &SynchronizationPackage::updatedSourceIds, + IsEmpty()), + Field("SynchronizationPackage::fileStatuses", + &SynchronizationPackage::fileStatuses, + UnorderedElementsAre(IsFileStatus(ignoreInQdsSourceId, 1, 21))), + Field("SynchronizationPackage::updatedFileStatusSourceIds", + &SynchronizationPackage::updatedFileStatusSourceIds, + UnorderedElementsAre(ignoreInQdsSourceId))))); + + updater.update({.projectDirectory = "/root"}); } TEST_F(ProjectStorageUpdater, synchronize_qml_types) @@ -658,8 +768,8 @@ TEST_F(ProjectStorageUpdater, synchronize_qml_types) QString qmltypes{"Module {\ndependencies: []}"}; setQmlFileNames(u"/path", {}); setContent(u"/path/example.qmltypes", qmltypes); - ON_CALL(qmlTypesParserMock, parse(qmltypes, _, _, _)) - .WillByDefault([&](auto, auto &imports, auto &types, auto) { + ON_CALL(qmlTypesParserMock, parse(qmltypes, _, _, _, _)) + .WillByDefault([&](auto, auto &imports, auto &types, auto, auto) { types.push_back(objectType); imports.push_back(import); }); @@ -692,7 +802,7 @@ TEST_F(ProjectStorageUpdater, synchronize_qml_types) &SynchronizationPackage::updatedDirectoryInfoDirectoryIds, UnorderedElementsAre(directoryPathId))))); - updater.update({.directories = directories}); + updater.update({.qtDirectories = directories}); } TEST_F(ProjectStorageUpdater, synchronize_subdircectories) @@ -721,7 +831,7 @@ TEST_F(ProjectStorageUpdater, synchronize_subdircectories) path2SourceContextId, path3SourceContextId))))); - updater.update({.directories = directories}); + updater.update({.qtDirectories = directories}); } TEST_F(ProjectStorageUpdater, synchronize_subdircectories_even_for_no_changes) @@ -746,7 +856,7 @@ TEST_F(ProjectStorageUpdater, synchronize_subdircectories_even_for_no_changes) path2SourceContextId, path3SourceContextId))))); - updater.update({.directories = directories}); + updater.update({.qtDirectories = directories}); } TEST_F(ProjectStorageUpdater, synchronize_subdircectories_for_deleted_subdirecties) @@ -778,7 +888,7 @@ TEST_F(ProjectStorageUpdater, synchronize_subdircectories_for_deleted_subdirecti path2SourceContextId, path3SourceContextId))))); - updater.update({.directories = directories}); + updater.update({.qtDirectories = directories}); } TEST_F(ProjectStorageUpdater, synchronize_qml_types_throws_if_qmltpes_does_not_exists) @@ -786,20 +896,20 @@ TEST_F(ProjectStorageUpdater, synchronize_qml_types_throws_if_qmltpes_does_not_e Storage::Import import{qmlModuleId, Storage::Version{2, 3}, qmltypesPathSourceId}; setFilesDontExists({qmltypesPathSourceId}); - ASSERT_THROW(updater.update({.directories = directories}), QmlDesigner::CannotParseQmlTypesFile); + ASSERT_THROW(updater.update({.qtDirectories = directories}), QmlDesigner::CannotParseQmlTypesFile); } TEST_F(ProjectStorageUpdater, synchronize_qml_types_are_empty_if_file_does_not_changed) { QString qmltypes{"Module {\ndependencies: []}"}; setContent(u"/path/example.qmltypes", qmltypes); - ON_CALL(qmlTypesParserMock, parse(qmltypes, _, _, _)) - .WillByDefault([&](auto, auto &, auto &types, auto) { types.push_back(objectType); }); + ON_CALL(qmlTypesParserMock, parse(qmltypes, _, _, _, _)) + .WillByDefault([&](auto, auto &, auto &types, auto, auto) { types.push_back(objectType); }); setFilesDontChanged({qmltypesPathSourceId, qmltypes2PathSourceId, qmlDirPathSourceId}); EXPECT_CALL(projectStorageMock, synchronize(PackageIsEmpty())); - updater.update({.directories = directories}); + updater.update({.qtDirectories = directories}); } TEST_F(ProjectStorageUpdater, get_content_for_qml_documents) @@ -820,7 +930,7 @@ TEST_F(ProjectStorageUpdater, get_content_for_qml_documents) EXPECT_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/OldSecond.qml")))); EXPECT_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/Second.qml")))); - updater.update({.directories = directories}); + updater.update({.qtDirectories = directories}); } TEST_F(ProjectStorageUpdater, parse_qml_documents) @@ -837,11 +947,25 @@ TEST_F(ProjectStorageUpdater, parse_qml_documents) setContent(u"/path/First2.qml", qmlDocument2); setContent(u"/path/Second.qml", qmlDocument3); - EXPECT_CALL(qmlDocumentParserMock, parse(qmlDocument1, _, _, _)); - EXPECT_CALL(qmlDocumentParserMock, parse(qmlDocument2, _, _, _)); - EXPECT_CALL(qmlDocumentParserMock, parse(qmlDocument3, _, _, _)); + EXPECT_CALL(qmlDocumentParserMock, parse(qmlDocument1, _, _, _, IsInsideProject::No)); + EXPECT_CALL(qmlDocumentParserMock, parse(qmlDocument2, _, _, _, IsInsideProject::No)); + EXPECT_CALL(qmlDocumentParserMock, parse(qmlDocument3, _, _, _, IsInsideProject::No)); - updater.update({.directories = directories}); + updater.update({.qtDirectories = directories}); +} + +TEST_F(ProjectStorageUpdater, parse_qml_documents_inside_project) +{ + QString qmldir{R"(module Example + FirstType 1.0 First.qml)"}; + QString qmlDocument1{"First{}"}; + setFileNames(u"/path", {"First.qml"}, {"*.qml"}); + setContent(u"/path/qmldir", qmldir); + setContent(u"/path/First.qml", qmlDocument1); + + EXPECT_CALL(qmlDocumentParserMock, parse(qmlDocument1, _, _, _, IsInsideProject::Yes)); + + updater.update({.projectDirectory = "/path"}); } TEST_F(ProjectStorageUpdater, non_existing_qml_documents_are_ignored) @@ -859,11 +983,11 @@ TEST_F(ProjectStorageUpdater, non_existing_qml_documents_are_ignored) setContent(u"/path/First2.qml", qmlDocument2); setContent(u"/path/Second.qml", qmlDocument3); - EXPECT_CALL(qmlDocumentParserMock, parse(qmlDocument1, _, _, _)); - EXPECT_CALL(qmlDocumentParserMock, parse(qmlDocument2, _, _, _)); - EXPECT_CALL(qmlDocumentParserMock, parse(qmlDocument3, _, _, _)); + EXPECT_CALL(qmlDocumentParserMock, parse(qmlDocument1, _, _, _, _)); + EXPECT_CALL(qmlDocumentParserMock, parse(qmlDocument2, _, _, _, _)); + EXPECT_CALL(qmlDocumentParserMock, parse(qmlDocument3, _, _, _, _)); - updater.update({.directories = directories}); + updater.update({.qtDirectories = directories}); } TEST_F(ProjectStorageUpdater, synchronize_qml_documents) @@ -939,7 +1063,83 @@ TEST_F(ProjectStorageUpdater, synchronize_qml_documents) IsDirectoryInfo( directoryPathId, qmlDocumentSourceId3, ModuleId{}, FileType::QmlDocument)))))); - updater.update({.directories = directories}); + updater.update({.qtDirectories = directories}); +} + +TEST_F(ProjectStorageUpdater, synchronize_qml_documents_in_project) +{ + QString qmldir{R"(module Example + FirstType 1.0 First.qml + FirstType 2.2 First2.qml + SecondType 2.2 Second.qml)"}; + setContent(u"/path/qmldir", qmldir); + + EXPECT_CALL( + projectStorageMock, + synchronize(AllOf( + Field("SynchronizationPackage::imports", + &SynchronizationPackage::imports, + UnorderedElementsAre(import1, import2, import3)), + Field( + &SynchronizationPackage::types, + UnorderedElementsAre( + AllOf(IsStorageType("First.qml", + ImportedType{"Object"}, + TypeTraitsKind::Reference, + qmlDocumentSourceId1, + ChangeLevel::Full), + Field("Type::exportedTypes", + &Type::exportedTypes, + UnorderedElementsAre(IsExportedType(exampleModuleId, "FirstType", 1, 0), + IsExportedType(pathModuleId, "First", -1, -1)))), + AllOf(IsStorageType("First2.qml", + ImportedType{"Object2"}, + TypeTraitsKind::Reference, + qmlDocumentSourceId2, + ChangeLevel::Full), + Field("Type::exportedTypes", + &Type::exportedTypes, + UnorderedElementsAre(IsExportedType(exampleModuleId, "FirstType", 2, 2), + IsExportedType(pathModuleId, "First2", -1, -1)))), + AllOf(IsStorageType("Second.qml", + ImportedType{"Object3"}, + TypeTraitsKind::Reference, + qmlDocumentSourceId3, + ChangeLevel::Full), + Field("Type::exportedTypes", + &Type::exportedTypes, + UnorderedElementsAre(IsExportedType(exampleModuleId, "SecondType", 2, 2), + IsExportedType(pathModuleId, "Second", -1, -1)))))), + Field("SynchronizationPackage::updatedSourceIds", + &SynchronizationPackage::updatedSourceIds, + UnorderedElementsAre(qmlDirPathSourceId, + qmlDocumentSourceId1, + qmlDocumentSourceId2, + qmlDocumentSourceId3)), + Field("SynchronizationPackage::updatedFileStatusSourceIds", + &SynchronizationPackage::updatedFileStatusSourceIds, + UnorderedElementsAre(qmlDirPathSourceId, + qmlDocumentSourceId1, + qmlDocumentSourceId2, + qmlDocumentSourceId3)), + Field("SynchronizationPackage::fileStatuses", + &SynchronizationPackage::fileStatuses, + UnorderedElementsAre(IsFileStatus(qmlDirPathSourceId, 1, 21), + IsFileStatus(qmlDocumentSourceId1, 1, 21), + IsFileStatus(qmlDocumentSourceId2, 1, 21), + IsFileStatus(qmlDocumentSourceId3, 1, 21))), + Field("SynchronizationPackage::updatedDirectoryInfoDirectoryIds", + &SynchronizationPackage::updatedDirectoryInfoDirectoryIds, + UnorderedElementsAre(directoryPathId)), + Field("SynchronizationPackage::directoryInfos", + &SynchronizationPackage::directoryInfos, + UnorderedElementsAre( + IsDirectoryInfo(directoryPathId, qmlDocumentSourceId1, ModuleId{}, FileType::QmlDocument), + IsDirectoryInfo(directoryPathId, qmlDocumentSourceId2, ModuleId{}, FileType::QmlDocument), + IsDirectoryInfo( + directoryPathId, qmlDocumentSourceId3, ModuleId{}, FileType::QmlDocument)))))); + + updater.update({.projectDirectory = "/path"}); } TEST_F(ProjectStorageUpdater, skip_duplicate_qmldir_entries) @@ -1018,7 +1218,7 @@ TEST_F(ProjectStorageUpdater, skip_duplicate_qmldir_entries) IsDirectoryInfo( directoryPathId, qmlDocumentSourceId3, ModuleId{}, FileType::QmlDocument)))))); - updater.update({.directories = directories}); + updater.update({.qtDirectories = directories}); } TEST_F(ProjectStorageUpdater, synchronize_add_only_qml_document_in_directory) @@ -1084,7 +1284,7 @@ TEST_F(ProjectStorageUpdater, synchronize_add_only_qml_document_in_directory) ModuleId{}, FileType::QmlDocument)))))); - updater.update({.directories = directories}); + updater.update({.qtDirectories = directories}); } TEST_F(ProjectStorageUpdater, synchronize_removes_qml_document) @@ -1155,7 +1355,7 @@ TEST_F(ProjectStorageUpdater, synchronize_removes_qml_document) ModuleId{}, FileType::QmlDocument)))))); - updater.update({.directories = directories}); + updater.update({.qtDirectories = directories}); } TEST_F(ProjectStorageUpdater, synchronize_removes_qml_document_in_qmldir_only) @@ -1218,7 +1418,7 @@ TEST_F(ProjectStorageUpdater, synchronize_removes_qml_document_in_qmldir_only) ModuleId{}, FileType::QmlDocument)))))); - updater.update({.directories = directories}); + updater.update({.qtDirectories = directories}); } TEST_F(ProjectStorageUpdater, synchronize_add_qml_document_to_qmldir) @@ -1283,7 +1483,7 @@ TEST_F(ProjectStorageUpdater, synchronize_add_qml_document_to_qmldir) ModuleId{}, FileType::QmlDocument)))))); - updater.update({.directories = directories}); + updater.update({.qtDirectories = directories}); } TEST_F(ProjectStorageUpdater, synchronize_remove_qml_document_from_qmldir) @@ -1346,7 +1546,7 @@ TEST_F(ProjectStorageUpdater, synchronize_remove_qml_document_from_qmldir) ModuleId{}, FileType::QmlDocument)))))); - updater.update({.directories = directories}); + updater.update({.qtDirectories = directories}); } TEST_F(ProjectStorageUpdater, synchronize_qml_documents_dont_update_if_up_to_date) @@ -1419,7 +1619,7 @@ TEST_F(ProjectStorageUpdater, synchronize_qml_documents_dont_update_if_up_to_dat IsDirectoryInfo( directoryPathId, qmlDocumentSourceId3, ModuleId{}, FileType::QmlDocument)))))); - updater.update({.directories = directories}); + updater.update({.qtDirectories = directories}); } TEST_F(ProjectStorageUpdater, synchroniz_if_qmldir_file_has_not_changed) @@ -1475,7 +1675,7 @@ TEST_F(ProjectStorageUpdater, synchroniz_if_qmldir_file_has_not_changed) &SynchronizationPackage::directoryInfos, IsEmpty())))); - updater.update({.directories = directories}); + updater.update({.qtDirectories = directories}); } TEST_F(ProjectStorageUpdater, synchroniz_if_qmldir_file_has_not_changed_and_some_updated_files) @@ -1516,7 +1716,7 @@ TEST_F(ProjectStorageUpdater, synchroniz_if_qmldir_file_has_not_changed_and_some &SynchronizationPackage::directoryInfos, IsEmpty())))); - updater.update({.directories = directories}); + updater.update({.qtDirectories = directories}); } TEST_F(ProjectStorageUpdater, synchroniz_if_qmldir_file_not_changed_and_some_removed_files) @@ -1530,7 +1730,7 @@ TEST_F(ProjectStorageUpdater, synchroniz_if_qmldir_file_not_changed_and_some_rem setFilesDontChanged({qmlDirPathSourceId, qmltypes2PathSourceId, qmlDocumentSourceId2}); setFilesRemoved({qmltypesPathSourceId, qmlDocumentSourceId1}); - ASSERT_THROW(updater.update({.directories = directories}), QmlDesigner::CannotParseQmlTypesFile); + ASSERT_THROW(updater.update({.qtDirectories = directories}), QmlDesigner::CannotParseQmlTypesFile); } TEST_F(ProjectStorageUpdater, synchroniz_if_qmldir_file_has_changed_and_some_removed_files) @@ -1587,7 +1787,7 @@ TEST_F(ProjectStorageUpdater, synchroniz_if_qmldir_file_has_changed_and_some_rem exampleCppNativeModuleId, FileType::QmlTypes)))))); - updater.update({.directories = directories}); + updater.update({.qtDirectories = directories}); } TEST_F(ProjectStorageUpdater, update_qml_types_files_is_empty) @@ -1663,7 +1863,7 @@ TEST_F(ProjectStorageUpdater, synchronize_qml_documents_with_different_version_b UnorderedElementsAre(IsDirectoryInfo( directoryPathId, qmlDocumentSourceId1, ModuleId{}, FileType::QmlDocument)))))); - updater.update({.directories = directories}); + updater.update({.qtDirectories = directories}); } TEST_F(ProjectStorageUpdater, synchronize_qml_documents_with_different_type_name_but_same_version_and_file_name) @@ -1711,7 +1911,7 @@ TEST_F(ProjectStorageUpdater, synchronize_qml_documents_with_different_type_name UnorderedElementsAre(IsDirectoryInfo( directoryPathId, qmlDocumentSourceId1, ModuleId{}, FileType::QmlDocument)))))); - updater.update({.directories = directories}); + updater.update({.qtDirectories = directories}); } TEST_F(ProjectStorageUpdater, dont_synchronize_selectors) @@ -1730,7 +1930,7 @@ TEST_F(ProjectStorageUpdater, dont_synchronize_selectors) &Type::exportedTypes, Contains(IsExportedType(exampleModuleId, "FirstType", 1, 0)))))))); - updater.update({.directories = directories}); + updater.update({.qtDirectories = directories}); } TEST_F(ProjectStorageUpdater, synchronize_qmldir_dependencies) @@ -1757,7 +1957,7 @@ TEST_F(ProjectStorageUpdater, synchronize_qmldir_dependencies) &SynchronizationPackage::updatedModuleDependencySourceIds, UnorderedElementsAre(qmltypesPathSourceId, qmltypes2PathSourceId))))); - updater.update({.directories = directories}); + updater.update({.qtDirectories = directories}); } TEST_F(ProjectStorageUpdater, synchronize_qmldir_dependencies_with_double_entries) @@ -1785,7 +1985,7 @@ TEST_F(ProjectStorageUpdater, synchronize_qmldir_dependencies_with_double_entrie &SynchronizationPackage::updatedModuleDependencySourceIds, UnorderedElementsAre(qmltypesPathSourceId, qmltypes2PathSourceId))))); - updater.update({.directories = directories}); + updater.update({.qtDirectories = directories}); } TEST_F(ProjectStorageUpdater, synchronize_qmldir_dependencies_with_colliding_imports) @@ -1813,7 +2013,7 @@ TEST_F(ProjectStorageUpdater, synchronize_qmldir_dependencies_with_colliding_imp &SynchronizationPackage::updatedModuleDependencySourceIds, UnorderedElementsAre(qmltypesPathSourceId, qmltypes2PathSourceId))))); - updater.update({.directories = directories}); + updater.update({.qtDirectories = directories}); } TEST_F(ProjectStorageUpdater, synchronize_qmldir_with_no_dependencies) @@ -1833,7 +2033,7 @@ TEST_F(ProjectStorageUpdater, synchronize_qmldir_with_no_dependencies) &SynchronizationPackage::updatedModuleDependencySourceIds, UnorderedElementsAre(qmltypesPathSourceId, qmltypes2PathSourceId))))); - updater.update({.directories = directories}); + updater.update({.qtDirectories = directories}); } TEST_F(ProjectStorageUpdater, synchronize_qmldir_imports) @@ -1877,7 +2077,7 @@ TEST_F(ProjectStorageUpdater, synchronize_qmldir_imports) &SynchronizationPackage::updatedModuleIds, ElementsAre(exampleModuleId))))); - updater.update({.directories = directories}); + updater.update({.qtDirectories = directories}); } TEST_F(ProjectStorageUpdater, synchronize_qmldir_with_no_imports) @@ -1894,7 +2094,7 @@ TEST_F(ProjectStorageUpdater, synchronize_qmldir_with_no_imports) &SynchronizationPackage::updatedModuleIds, ElementsAre(exampleModuleId))))); - updater.update({.directories = directories}); + updater.update({.qtDirectories = directories}); } TEST_F(ProjectStorageUpdater, synchronize_qmldir_imports_with_double_entries) @@ -1939,7 +2139,7 @@ TEST_F(ProjectStorageUpdater, synchronize_qmldir_imports_with_double_entries) &SynchronizationPackage::updatedModuleIds, ElementsAre(exampleModuleId))))); - updater.update({.directories = directories}); + updater.update({.qtDirectories = directories}); } TEST_F(ProjectStorageUpdater, synchronize_qmldir_default_imports) @@ -1983,7 +2183,7 @@ TEST_F(ProjectStorageUpdater, synchronize_qmldir_default_imports) &SynchronizationPackage::updatedModuleIds, ElementsAre(exampleModuleId))))); - updater.update({.directories = directories}); + updater.update({.qtDirectories = directories}); } TEST_F(ProjectStorageUpdater, do_not_synchronize_qmldir_optional_imports) @@ -2019,17 +2219,17 @@ TEST_F(ProjectStorageUpdater, do_not_synchronize_qmldir_optional_imports) &SynchronizationPackage::updatedModuleIds, ElementsAre(exampleModuleId))))); - updater.update({.directories = directories}); + updater.update({.qtDirectories = directories}); } TEST_F(ProjectStorageUpdater, update_path_watcher_directories) { EXPECT_CALL(patchWatcherMock, - updateIdPaths(Contains(IdPaths{projectPartId, + updateIdPaths(Contains(IdPaths{qtPartId, QmlDesigner::SourceType::Directory, {path1SourceId, path2SourceId, path3SourceId}}))); - updater.update({.directories = directories3}); + updater.update({.qtDirectories = directories3}); } TEST_F(ProjectStorageUpdater, update_path_watcher_directory_does_not_exists) @@ -2037,11 +2237,11 @@ TEST_F(ProjectStorageUpdater, update_path_watcher_directory_does_not_exists) setFilesDontExists({path2SourceId}); EXPECT_CALL(patchWatcherMock, - updateIdPaths(Contains(IdPaths{projectPartId, + updateIdPaths(Contains(IdPaths{qtPartId, QmlDesigner::SourceType::Directory, {path1SourceId, path3SourceId}}))); - updater.update({.directories = directories3}); + updater.update({.qtDirectories = directories3}); } TEST_F(ProjectStorageUpdater, update_path_watcher_directory_does_not_changed) @@ -2049,11 +2249,11 @@ TEST_F(ProjectStorageUpdater, update_path_watcher_directory_does_not_changed) setFilesDontChanged({qmldir1SourceId, qmldir2SourceId, path1SourceId, path2SourceId}); EXPECT_CALL(patchWatcherMock, - updateIdPaths(Contains(IdPaths{projectPartId, + updateIdPaths(Contains(IdPaths{qtPartId, QmlDesigner::SourceType::Directory, {path1SourceId, path2SourceId}}))); - updater.update({.directories = directories2}); + updater.update({.qtDirectories = directories2}); } TEST_F(ProjectStorageUpdater, update_path_watcher_directory_removed) @@ -2062,19 +2262,19 @@ TEST_F(ProjectStorageUpdater, update_path_watcher_directory_removed) EXPECT_CALL(patchWatcherMock, updateIdPaths(Contains( - IdPaths{projectPartId, QmlDesigner::SourceType::Directory, {path2SourceId}}))); + IdPaths{qtPartId, QmlDesigner::SourceType::Directory, {path2SourceId}}))); - updater.update({.directories = directories2}); + updater.update({.qtDirectories = directories2}); } TEST_F(ProjectStorageUpdater, update_path_watcher_qmldirs) { EXPECT_CALL(patchWatcherMock, - updateIdPaths(Contains(IdPaths{projectPartId, + updateIdPaths(Contains(IdPaths{qtPartId, QmlDesigner::SourceType::QmlDir, {qmldir1SourceId, qmldir2SourceId, qmldir3SourceId}}))); - updater.update({.directories = directories3}); + updater.update({.qtDirectories = directories3}); } TEST_F(ProjectStorageUpdater, update_path_watcher_qmldir_does_not_exists) @@ -2082,11 +2282,11 @@ TEST_F(ProjectStorageUpdater, update_path_watcher_qmldir_does_not_exists) setFilesDontExists({qmldir2SourceId}); EXPECT_CALL(patchWatcherMock, - updateIdPaths(Contains(IdPaths{projectPartId, + updateIdPaths(Contains(IdPaths{qtPartId, QmlDesigner::SourceType::QmlDir, {qmldir1SourceId, qmldir3SourceId}}))); - updater.update({.directories = directories3}); + updater.update({.qtDirectories = directories3}); } TEST_F(ProjectStorageUpdater, update_path_watcher_qmldir_does_not_changed) @@ -2094,11 +2294,11 @@ TEST_F(ProjectStorageUpdater, update_path_watcher_qmldir_does_not_changed) setFilesDontChanged({qmldir1SourceId, qmldir2SourceId, path1SourceId, path2SourceId}); EXPECT_CALL(patchWatcherMock, - updateIdPaths(Contains(IdPaths{projectPartId, + updateIdPaths(Contains(IdPaths{qtPartId, QmlDesigner::SourceType::QmlDir, {qmldir1SourceId, qmldir2SourceId}}))); - updater.update({.directories = directories2}); + updater.update({.qtDirectories = directories2}); } TEST_F(ProjectStorageUpdater, update_path_watcher_qmldir_removed) @@ -2107,9 +2307,9 @@ TEST_F(ProjectStorageUpdater, update_path_watcher_qmldir_removed) EXPECT_CALL(patchWatcherMock, updateIdPaths(Contains( - IdPaths{projectPartId, QmlDesigner::SourceType::QmlDir, {qmldir2SourceId}}))); + IdPaths{qtPartId, QmlDesigner::SourceType::QmlDir, {qmldir2SourceId}}))); - updater.update({.directories = directories2}); + updater.update({.qtDirectories = directories2}); } TEST_F(ProjectStorageUpdater, update_path_watcher_qml_files) @@ -2122,11 +2322,11 @@ TEST_F(ProjectStorageUpdater, update_path_watcher_qml_files) setContent(u"/path/one/qmldir", qmldir1); EXPECT_CALL(patchWatcherMock, - updateIdPaths(Contains(IdPaths{projectPartId, + updateIdPaths(Contains(IdPaths{qtPartId, QmlDesigner::SourceType::Qml, {firstSourceId, secondSourceId, thirdSourceId}}))); - updater.update({.directories = directories2}); + updater.update({.qtDirectories = directories2}); } TEST_F(ProjectStorageUpdater, update_path_watcher_only_qml_files_dont_changed) @@ -2140,11 +2340,11 @@ TEST_F(ProjectStorageUpdater, update_path_watcher_only_qml_files_dont_changed) setFilesDontChanged({firstSourceId, secondSourceId, thirdSourceId}); EXPECT_CALL(patchWatcherMock, - updateIdPaths(Contains(IdPaths{projectPartId, + updateIdPaths(Contains(IdPaths{qtPartId, QmlDesigner::SourceType::Qml, {firstSourceId, secondSourceId, thirdSourceId}}))); - updater.update({.directories = directories2}); + updater.update({.qtDirectories = directories2}); } TEST_F(ProjectStorageUpdater, update_path_watcher_only_qml_files_changed) @@ -2158,11 +2358,11 @@ TEST_F(ProjectStorageUpdater, update_path_watcher_only_qml_files_changed) {{path2SourceContextId, thirdSourceId, ModuleId{}, FileType::QmlDocument}}); EXPECT_CALL(patchWatcherMock, - updateIdPaths(Contains(IdPaths{projectPartId, + updateIdPaths(Contains(IdPaths{qtPartId, QmlDesigner::SourceType::Qml, {firstSourceId, secondSourceId, thirdSourceId}}))); - updater.update({.directories = directories2}); + updater.update({.qtDirectories = directories2}); } TEST_F(ProjectStorageUpdater, update_path_watcher_qml_files_and_directories_dont_changed) @@ -2181,11 +2381,11 @@ TEST_F(ProjectStorageUpdater, update_path_watcher_qml_files_and_directories_dont {{path2SourceContextId, thirdSourceId, ModuleId{}, FileType::QmlDocument}}); EXPECT_CALL(patchWatcherMock, - updateIdPaths(Contains(IdPaths{projectPartId, + updateIdPaths(Contains(IdPaths{qtPartId, QmlDesigner::SourceType::Qml, {firstSourceId, secondSourceId, thirdSourceId}}))); - updater.update({.directories = directories2}); + updater.update({.qtDirectories = directories2}); } TEST_F(ProjectStorageUpdater, update_path_watcher_qmltypes_files_in_qmldir) @@ -2200,11 +2400,11 @@ TEST_F(ProjectStorageUpdater, update_path_watcher_qmltypes_files_in_qmldir) setFilesDontChanged({firstSourceId, secondSourceId, thirdSourceId}); EXPECT_CALL(patchWatcherMock, - updateIdPaths(Contains(IdPaths{projectPartId, + updateIdPaths(Contains(IdPaths{qtPartId, QmlDesigner::SourceType::QmlTypes, {qmltypes1SourceId, qmltypes2SourceId}}))); - updater.update({.directories = directories2}); + updater.update({.qtDirectories = directories2}); } TEST_F(ProjectStorageUpdater, update_path_watcher_only_qmltypes_files_in_qmldir_dont_changed) @@ -2218,11 +2418,11 @@ TEST_F(ProjectStorageUpdater, update_path_watcher_only_qmltypes_files_in_qmldir_ setFilesDontChanged({qmltypes1SourceId, qmltypes2SourceId}); EXPECT_CALL(patchWatcherMock, - updateIdPaths(Contains(IdPaths{projectPartId, + updateIdPaths(Contains(IdPaths{qtPartId, QmlDesigner::SourceType::QmlTypes, {qmltypes1SourceId, qmltypes2SourceId}}))); - updater.update({.directories = directories2}); + updater.update({.qtDirectories = directories2}); } TEST_F(ProjectStorageUpdater, update_path_watcher_only_qmltypes_files_changed) @@ -2235,11 +2435,11 @@ TEST_F(ProjectStorageUpdater, update_path_watcher_only_qmltypes_files_changed) {{path2SourceContextId, qmltypes2SourceId, exampleModuleId, FileType::QmlTypes}}); EXPECT_CALL(patchWatcherMock, - updateIdPaths(Contains(IdPaths{projectPartId, + updateIdPaths(Contains(IdPaths{qtPartId, QmlDesigner::SourceType::QmlTypes, {qmltypes1SourceId, qmltypes2SourceId}}))); - updater.update({.directories = directories2}); + updater.update({.qtDirectories = directories2}); } TEST_F(ProjectStorageUpdater, update_path_watcher_qmltypes_files_and_directories_dont_changed) @@ -2256,11 +2456,11 @@ TEST_F(ProjectStorageUpdater, update_path_watcher_qmltypes_files_and_directories {{path2SourceContextId, qmltypes2SourceId, exampleModuleId, FileType::QmlTypes}}); EXPECT_CALL(patchWatcherMock, - updateIdPaths(Contains(IdPaths{projectPartId, + updateIdPaths(Contains(IdPaths{qtPartId, QmlDesigner::SourceType::QmlTypes, {qmltypes1SourceId, qmltypes2SourceId}}))); - updater.update({.directories = directories2}); + updater.update({.qtDirectories = directories2}); } TEST_F(ProjectStorageUpdater, synchronize_qml_documents_without_qmldir) @@ -2329,7 +2529,7 @@ TEST_F(ProjectStorageUpdater, synchronize_qml_documents_without_qmldir) IsDirectoryInfo( directoryPathId, qmlDocumentSourceId3, ModuleId{}, FileType::QmlDocument)))))); - updater.update({.directories = directories}); + updater.update({.qtDirectories = directories}); } TEST_F(ProjectStorageUpdater, warn_about_non_existing_qml_document) @@ -2348,7 +2548,7 @@ TEST_F(ProjectStorageUpdater, warn_about_non_existing_qml_document) qmlDocumentSourceId1, qmlDirPathSourceId)); - updater.update({.directories = directories}); + updater.update({.qtDirectories = directories}); } TEST_F(ProjectStorageUpdater, @@ -2419,7 +2619,7 @@ TEST_F(ProjectStorageUpdater, ModuleId{}, FileType::QmlDocument)))))); - updater.update({.directories = directories}); + updater.update({.qtDirectories = directories}); } TEST_F(ProjectStorageUpdater, synchronize_qml_documents_without_qmldir_if_directory_is_removed) @@ -2464,7 +2664,7 @@ TEST_F(ProjectStorageUpdater, synchronize_qml_documents_without_qmldir_if_direct &SynchronizationPackage::directoryInfos, IsEmpty())))); - updater.update({.directories = directories}); + updater.update({.qtDirectories = directories}); } TEST_F(ProjectStorageUpdater, synchronize_qml_documents_without_qmldir_add_qml_document) @@ -2522,7 +2722,7 @@ TEST_F(ProjectStorageUpdater, synchronize_qml_documents_without_qmldir_add_qml_d ModuleId{}, FileType::QmlDocument)))))); - updater.update({.directories = directories}); + updater.update({.qtDirectories = directories}); } TEST_F(ProjectStorageUpdater, synchronize_qml_documents_without_qmldir_removes_qml_document) @@ -2566,7 +2766,7 @@ TEST_F(ProjectStorageUpdater, synchronize_qml_documents_without_qmldir_removes_q ModuleId{}, FileType::QmlDocument)))))); - updater.update({.directories = directories}); + updater.update({.qtDirectories = directories}); } TEST_F(ProjectStorageUpdater, watcher_updates_directories) @@ -2769,12 +2969,11 @@ TEST_F(ProjectStorageUpdater, watcher_watches_directories_after_directory_change EXPECT_CALL(patchWatcherMock, updateContextIdPaths( UnorderedElementsAre( - IdPaths{projectPartId, QmlDesigner::SourceType::Directory, {directoryPathSourceId}}, - IdPaths{projectPartId, QmlDesigner::SourceType::QmlDir, {qmlDirPathSourceId}}, - IdPaths{projectPartId, + IdPaths{qtPartId, QmlDesigner::SourceType::Directory, {directoryPathSourceId}}, + IdPaths{qtPartId, QmlDesigner::SourceType::QmlDir, {qmlDirPathSourceId}}, + IdPaths{qtPartId, QmlDesigner::SourceType::Qml, - {qmlDocumentSourceId1, qmlDocumentSourceId2, qmlDocumentSourceId3}}, - IdPaths{projectPartId, QmlDesigner::SourceType::QmlTypes, {}}), + {qmlDocumentSourceId1, qmlDocumentSourceId2, qmlDocumentSourceId3}}), UnorderedElementsAre(directorySourceContextId))); updater.pathsWithIdsChanged({{directoryProjectChunkId, {directoryPathSourceId}}}); @@ -2885,12 +3084,11 @@ TEST_F(ProjectStorageUpdater, watcher_watches_directories_after_qmldir_changes) EXPECT_CALL(patchWatcherMock, updateContextIdPaths( UnorderedElementsAre( - IdPaths{projectPartId, QmlDesigner::SourceType::Directory, {directoryPathSourceId}}, - IdPaths{projectPartId, QmlDesigner::SourceType::QmlDir, {qmlDirPathSourceId}}, - IdPaths{projectPartId, + IdPaths{qtPartId, QmlDesigner::SourceType::Directory, {directoryPathSourceId}}, + IdPaths{qtPartId, QmlDesigner::SourceType::QmlDir, {qmlDirPathSourceId}}, + IdPaths{qtPartId, QmlDesigner::SourceType::Qml, - {qmlDocumentSourceId1, qmlDocumentSourceId2, qmlDocumentSourceId3}}, - IdPaths{projectPartId, QmlDesigner::SourceType::QmlTypes, {}}), + {qmlDocumentSourceId1, qmlDocumentSourceId2, qmlDocumentSourceId3}}), UnorderedElementsAre(directorySourceContextId))); updater.pathsWithIdsChanged({{qmldirProjectChunkId, {qmlDirPathSourceId}}}); @@ -4283,11 +4481,11 @@ TEST_F(ProjectStorageUpdater, update_property_editor_panes_is_empty_if_directory TEST_F(ProjectStorageUpdater, update_type_annotations) { - auto itemSourceId = sourcePathCache.sourceId( + auto qtQuickSourceId = sourcePathCache.sourceId( QmlDesigner::SourcePath{itemLibraryPath + "/quick.metainfo"}); - auto buttonSourceId = sourcePathCache.sourceId( + auto qtQuickControlSourceId = sourcePathCache.sourceId( QmlDesigner::SourcePath{itemLibraryPath + "/qtquickcontrols2.metainfo"}); - setFilesChanged({itemLibraryPathSourceId, itemSourceId, buttonSourceId}); + setFilesAdded({itemLibraryPathSourceId, qtQuickSourceId, qtQuickControlSourceId}); auto qtQuickModuleId = moduleId("QtQuick", ModuleKind::QmlLibrary); auto qtQuickControlsModuleId = moduleId("QtQuick.Controls.Basic", ModuleKind::QmlLibrary); QmlDesigner::Storage::TypeTraits itemTraits; @@ -4296,7 +4494,7 @@ TEST_F(ProjectStorageUpdater, update_type_annotations) EXPECT_CALL(projectStorageMock, synchronize(AllOf(Field("SynchronizationPackage::typeAnnotations", &SynchronizationPackage::typeAnnotations, - IsSupersetOf({IsTypeAnnotation(itemSourceId, + IsSupersetOf({IsTypeAnnotation(qtQuickSourceId, itemLibraryPathSourceContextId, "Item", qtQuickModuleId, @@ -4304,7 +4502,7 @@ TEST_F(ProjectStorageUpdater, update_type_annotations) _, _, _), - IsTypeAnnotation(buttonSourceId, + IsTypeAnnotation(qtQuickControlSourceId, itemLibraryPathSourceContextId, "Button", qtQuickControlsModuleId, @@ -4314,19 +4512,58 @@ TEST_F(ProjectStorageUpdater, update_type_annotations) _)})), Field("SynchronizationPackage::updatedTypeAnnotationSourceIds", &SynchronizationPackage::updatedTypeAnnotationSourceIds, - IsSupersetOf({itemSourceId, buttonSourceId}))))); + IsSupersetOf({qtQuickSourceId, qtQuickControlSourceId}))))); + + updater.update({.typeAnnotationPaths = {itemLibraryPath}}); +} + +TEST_F(ProjectStorageUpdater, update_added_type_annotation) +{ + auto qtQuickSourceId = sourcePathCache.sourceId( + QmlDesigner::SourcePath{itemLibraryPath + "/quick.metainfo"}); + auto qtQuickControlSourceId = sourcePathCache.sourceId( + QmlDesigner::SourcePath{itemLibraryPath + "/qtquickcontrols2.metainfo"}); + setFilesDontChanged({itemLibraryPathSourceId}); + setFilesAdded({qtQuickSourceId, qtQuickControlSourceId}); + auto qtQuickModuleId = moduleId("QtQuick", ModuleKind::QmlLibrary); + auto qtQuickControlsModuleId = moduleId("QtQuick.Controls.Basic", ModuleKind::QmlLibrary); + QmlDesigner::Storage::TypeTraits itemTraits; + itemTraits.canBeContainer = QmlDesigner::FlagIs::True; + + EXPECT_CALL(projectStorageMock, + synchronize(AllOf(Field("SynchronizationPackage::typeAnnotations", + &SynchronizationPackage::typeAnnotations, + IsSupersetOf({IsTypeAnnotation(qtQuickSourceId, + itemLibraryPathSourceContextId, + "Item", + qtQuickModuleId, + StartsWith(itemLibraryPath), + _, + _, + _), + IsTypeAnnotation(qtQuickControlSourceId, + itemLibraryPathSourceContextId, + "Button", + qtQuickControlsModuleId, + StartsWith(itemLibraryPath), + _, + _, + _)})), + Field("SynchronizationPackage::updatedTypeAnnotationSourceIds", + &SynchronizationPackage::updatedTypeAnnotationSourceIds, + IsSupersetOf({qtQuickSourceId, qtQuickControlSourceId}))))); updater.update({.typeAnnotationPaths = {itemLibraryPath}}); } TEST_F(ProjectStorageUpdater, update_changed_type_annotation) { - auto itemSourceId = sourcePathCache.sourceId( + auto qtQuickSourceId = sourcePathCache.sourceId( QmlDesigner::SourcePath{itemLibraryPath + "/quick.metainfo"}); - auto buttonSourceId = sourcePathCache.sourceId( + auto qtQuickControlSourceId = sourcePathCache.sourceId( QmlDesigner::SourcePath{itemLibraryPath + "/qtquickcontrols2.metainfo"}); setFilesDontChanged({itemLibraryPathSourceId}); - setFilesChanged({itemSourceId, buttonSourceId}); + setFilesChanged({qtQuickSourceId, qtQuickControlSourceId}); auto qtQuickModuleId = moduleId("QtQuick", ModuleKind::QmlLibrary); auto qtQuickControlsModuleId = moduleId("QtQuick.Controls.Basic", ModuleKind::QmlLibrary); QmlDesigner::Storage::TypeTraits itemTraits; @@ -4335,7 +4572,7 @@ TEST_F(ProjectStorageUpdater, update_changed_type_annotation) EXPECT_CALL(projectStorageMock, synchronize(AllOf(Field("SynchronizationPackage::typeAnnotations", &SynchronizationPackage::typeAnnotations, - IsSupersetOf({IsTypeAnnotation(itemSourceId, + IsSupersetOf({IsTypeAnnotation(qtQuickSourceId, itemLibraryPathSourceContextId, "Item", qtQuickModuleId, @@ -4343,7 +4580,7 @@ TEST_F(ProjectStorageUpdater, update_changed_type_annotation) _, _, _), - IsTypeAnnotation(buttonSourceId, + IsTypeAnnotation(qtQuickControlSourceId, itemLibraryPathSourceContextId, "Button", qtQuickControlsModuleId, @@ -4353,7 +4590,26 @@ TEST_F(ProjectStorageUpdater, update_changed_type_annotation) _)})), Field("SynchronizationPackage::updatedTypeAnnotationSourceIds", &SynchronizationPackage::updatedTypeAnnotationSourceIds, - IsSupersetOf({itemSourceId, buttonSourceId}))))); + IsSupersetOf({qtQuickSourceId, qtQuickControlSourceId}))))); + + updater.update({.typeAnnotationPaths = {itemLibraryPath}}); +} + +TEST_F(ProjectStorageUpdater, update_removed_type_annotations) +{ + auto qtQuickSourceId = sourcePathCache.sourceId( + QmlDesigner::SourcePath{itemLibraryPath + "/quick.metainfo"}); + auto qtQuickControlSourceId = sourcePathCache.sourceId( + QmlDesigner::SourcePath{itemLibraryPath + "/qtquickcontrols2.metainfo"}); + setFilesRemoved({itemLibraryPathSourceId, qtQuickSourceId, qtQuickControlSourceId}); + + EXPECT_CALL(projectStorageMock, + synchronize(AllOf(Field("SynchronizationPackage::typeAnnotations", + &SynchronizationPackage::typeAnnotations, + IsEmpty()), + Field("SynchronizationPackage::updatedTypeAnnotationSourceIds", + &SynchronizationPackage::updatedTypeAnnotationSourceIds, + IsSupersetOf({qtQuickSourceId, qtQuickControlSourceId}))))); updater.update({.typeAnnotationPaths = {itemLibraryPath}}); } @@ -4366,16 +4622,17 @@ TEST_F(ProjectStorageUpdater, update_type_annotations_removed_meta_info_file) ON_CALL(projectStorageMock, fetchFileStatus(_)).WillByDefault([](SourceId sourceId) { return FileStatus{sourceId, 1, 21}; }); - auto itemSourceId = sourcePathCache.sourceId( + auto qtQuickSourceId = sourcePathCache.sourceId( QmlDesigner::SourcePath{itemLibraryPath + "/quick.metainfo"}); - auto buttonSourceId = sourcePathCache.sourceId( + auto qtQuickControlSourceId = sourcePathCache.sourceId( QmlDesigner::SourcePath{itemLibraryPath + "/qtquickcontrols2.metainfo"}); ON_CALL(projectStorageMock, typeAnnotationDirectoryIds()) .WillByDefault(Return(QmlDesigner::SmallSourceContextIds<64>{itemLibraryPathSourceContextId})); ON_CALL(projectStorageMock, typeAnnotationSourceIds(itemLibraryPathSourceContextId)) - .WillByDefault(Return(QmlDesigner::SmallSourceIds<4>{itemSourceId, buttonSourceId})); + .WillByDefault(Return(QmlDesigner::SmallSourceIds<4>{qtQuickSourceId, qtQuickControlSourceId})); setFilesChanged({itemLibraryPathSourceId}); - setFilesDontChanged({itemSourceId, buttonSourceId}); + setFilesRemoved({qtQuickSourceId}); + setFilesDontChanged({qtQuickControlSourceId}); EXPECT_CALL(projectStorageMock, synchronize(AllOf(Field("SynchronizationPackage::typeAnnotations", @@ -4383,7 +4640,8 @@ TEST_F(ProjectStorageUpdater, update_type_annotations_removed_meta_info_file) IsEmpty()), Field("SynchronizationPackage::updatedTypeAnnotationSourceIds", &SynchronizationPackage::updatedTypeAnnotationSourceIds, - IsSupersetOf({itemSourceId, buttonSourceId}))))); + AllOf(IsSupersetOf({qtQuickSourceId}), + Not(Contains(qtQuickControlSourceId))))))); updater.update({.typeAnnotationPaths = {itemLibraryPath}}); } @@ -4396,17 +4654,17 @@ TEST_F(ProjectStorageUpdater, update_type_annotations_removed_directory) ON_CALL(projectStorageMock, fetchFileStatus(_)).WillByDefault([](SourceId sourceId) { return FileStatus{sourceId, 1, 21}; }); - auto itemSourceId = sourcePathCache.sourceId( + auto qtQuickSourceId = sourcePathCache.sourceId( QmlDesigner::SourcePath{itemLibraryPath + "/quick.metainfo"}); - auto buttonSourceId = sourcePathCache.sourceId( + auto qtQuickControlSourceId = sourcePathCache.sourceId( QmlDesigner::SourcePath{itemLibraryPath + "/qtquickcontrols2.metainfo"}); ON_CALL(projectStorageMock, typeAnnotationDirectoryIds()) .WillByDefault(Return(QmlDesigner::SmallSourceContextIds<64>{ itemLibraryPathSourceContextId, })); ON_CALL(projectStorageMock, typeAnnotationSourceIds(itemLibraryPathSourceContextId)) - .WillByDefault(Return(QmlDesigner::SmallSourceIds<4>{itemSourceId, buttonSourceId})); - setFilesDontExists({itemLibraryPathSourceId, buttonSourceId, itemSourceId}); + .WillByDefault(Return(QmlDesigner::SmallSourceIds<4>{qtQuickSourceId, qtQuickControlSourceId})); + setFilesRemoved({itemLibraryPathSourceId, qtQuickSourceId, qtQuickControlSourceId}); EXPECT_CALL(projectStorageMock, synchronize(AllOf(Field("SynchronizationPackage::typeAnnotations", @@ -4414,18 +4672,18 @@ TEST_F(ProjectStorageUpdater, update_type_annotations_removed_directory) IsEmpty()), Field("SynchronizationPackage::updatedTypeAnnotationSourceIds", &SynchronizationPackage::updatedTypeAnnotationSourceIds, - IsSupersetOf({buttonSourceId, itemSourceId}))))); + IsSupersetOf({qtQuickSourceId, qtQuickControlSourceId}))))); updater.update({.typeAnnotationPaths = {itemLibraryPath}}); } -TEST_F(ProjectStorageUpdater, synchronize_property_editor_qml_paths_directory) +TEST_F(ProjectStorageUpdater, synchronize_added_property_editor_qml_paths_directory) { - QStringList directories = {"/path/one"}; setSubdirectoryPaths(u"/path/one", {"/path/one/designer"}); SourceContextId designer1DirectoryId = sourcePathCache.sourceContextId("/path/one/designer"); SourceId designer1SourceId = SourceId::create(QmlDesigner::SourceNameId{}, designer1DirectoryId); - setFilesChanged({path1SourceId, designer1SourceId}); + setFilesDontChanged({path1SourceId}); + setFilesAdded({designer1SourceId}); EXPECT_CALL(projectStorageMock, synchronize( @@ -4450,20 +4708,16 @@ TEST_F(ProjectStorageUpdater, synchronize_property_editor_qml_paths_directory) &SynchronizationPackage::updatedDirectoryInfoDirectoryIds, UnorderedElementsAre(path1SourceContextId))))); - updater.update({.directories = directories}); + updater.update({.projectDirectory = "/path/one"}); } -TEST_F(ProjectStorageUpdater, dont_synchronize_empty_property_editor_qml_paths_directory) +TEST_F(ProjectStorageUpdater, synchronize_changed_property_editor_qml_paths_directory) { - QStringList directories = {"/path/one", "/path/two"}; setSubdirectoryPaths(u"/path/one", {"/path/one/designer"}); - setSubdirectoryPaths(u"/path/two", {}); SourceContextId designer1DirectoryId = sourcePathCache.sourceContextId("/path/one/designer"); SourceId designer1SourceId = SourceId::create(QmlDesigner::SourceNameId{}, designer1DirectoryId); - SourceContextId designer2DirectoryId = sourcePathCache.sourceContextId("/path/two/designer"); - SourceId designer2SourceId = SourceId::create(QmlDesigner::SourceNameId{}, designer2DirectoryId); - setFilesChanged({path1SourceId, path2SourceId, designer1SourceId}); - setFilesDontExists({designer2SourceId}); + setFilesDontChanged({path1SourceId}); + setFilesChanged({designer1SourceId}); EXPECT_CALL(projectStorageMock, synchronize( @@ -4472,7 +4726,7 @@ TEST_F(ProjectStorageUpdater, dont_synchronize_empty_property_editor_qml_paths_d IsSupersetOf({IsFileStatus(designer1SourceId, 1, 21)})), Field("SynchronizationPackage::updatedFileStatusSourceIds", &SynchronizationPackage::updatedFileStatusSourceIds, - IsSupersetOf({designer1SourceId, designer2SourceId})), + IsSupersetOf({designer1SourceId})), Field("SynchronizationPackage::propertyEditorQmlPaths", &SynchronizationPackage::propertyEditorQmlPaths, Each(Field("PropertyEditorQmlPath::directoryId", @@ -4486,14 +4740,46 @@ TEST_F(ProjectStorageUpdater, dont_synchronize_empty_property_editor_qml_paths_d IsEmpty()), Field("SynchronizationPackage::updatedDirectoryInfoDirectoryIds", &SynchronizationPackage::updatedDirectoryInfoDirectoryIds, - UnorderedElementsAre(path1SourceContextId, path2SourceContextId))))); + UnorderedElementsAre(path1SourceContextId))))); - updater.update({.directories = directories}); + updater.update({.projectDirectory = "/path/one"}); +} + +TEST_F(ProjectStorageUpdater, dont_synchronize_empty_property_editor_qml_paths_directory) +{ + setSubdirectoryPaths(u"/path/two", {}); + SourceContextId designer2DirectoryId = sourcePathCache.sourceContextId("/path/two/designer"); + SourceId designer2SourceId = SourceId::create(QmlDesigner::SourceNameId{}, designer2DirectoryId); + setFilesChanged({path2SourceId}); + setFilesDontExists({designer2SourceId}); + + EXPECT_CALL(projectStorageMock, + synchronize( + AllOf(Field("SynchronizationPackage::fileStatuses", + &SynchronizationPackage::fileStatuses, + IsSupersetOf({IsFileStatus(path2SourceId, 1, 21), + IsFileStatus(designer2SourceId, -1, -1)})), + Field("SynchronizationPackage::updatedFileStatusSourceIds", + &SynchronizationPackage::updatedFileStatusSourceIds, + IsSupersetOf({designer2SourceId})), + Field("SynchronizationPackage::propertyEditorQmlPaths", + &SynchronizationPackage::propertyEditorQmlPaths, + IsEmpty()), + Field("SynchronizationPackage::updatedPropertyEditorQmlPathDirectoryIds", + &SynchronizationPackage::updatedPropertyEditorQmlPathDirectoryIds, + IsEmpty()), + Field("SynchronizationPackage::directoryInfos", + &SynchronizationPackage::directoryInfos, + IsEmpty()), + Field("SynchronizationPackage::updatedDirectoryInfoDirectoryIds", + &SynchronizationPackage::updatedDirectoryInfoDirectoryIds, + UnorderedElementsAre(path2SourceContextId))))); + + updater.update({.projectDirectory = "/path/two"}); } TEST_F(ProjectStorageUpdater, remove_property_editor_qml_paths_if_designer_directory_is_removed) { - QStringList directories = {"/path/one"}; SourceContextId designer1DirectoryId = sourcePathCache.sourceContextId("/path/one/designer"); SourceId designer1SourceId = SourceId::create(QmlDesigner::SourceNameId{}, designer1DirectoryId); setFilesDontChanged({path1SourceId, qmldir1SourceId}); @@ -4520,13 +4806,12 @@ TEST_F(ProjectStorageUpdater, remove_property_editor_qml_paths_if_designer_direc &SynchronizationPackage::updatedDirectoryInfoDirectoryIds, UnorderedElementsAre(path1SourceContextId))))); - updater.update({.directories = directories}); + updater.update({.projectDirectory = "/path/one"}); } TEST_F(ProjectStorageUpdater, - synchronize_annotation_property_editor_qml_paths_directory_if_designer_directory_is_changed) + synchronize_property_editor_qml_paths_directory_if_designer_directory_is_changed) { - QStringList directories = {"/path/one"}; setSubdirectoryPaths(u"/path/one", {"/path/one/designer"}); QString qmldir{R"(module Bar)"}; setContent(u"/path/one/qmldir", qmldir); @@ -4565,13 +4850,12 @@ TEST_F(ProjectStorageUpdater, &SynchronizationPackage::updatedPropertyEditorQmlPathDirectoryIds, Contains(designer1DirectoryId))))); - updater.update({.directories = directories}); + updater.update({.projectDirectory = "/path/one"}); } TEST_F(ProjectStorageUpdater, synchronize_property_editor_qml_paths_directory_if_qml_directory_is_changed) { - QStringList directories = {"/path/one"}; setSubdirectoryPaths(u"/path/one", {"/path/one/designer"}); QString qmldir{R"(module Bar)"}; setContent(u"/path/one/qmldir", qmldir); @@ -4610,12 +4894,11 @@ TEST_F(ProjectStorageUpdater, &SynchronizationPackage::updatedPropertyEditorQmlPathDirectoryIds, Contains(designer1DirectoryId))))); - updater.update({.directories = directories}); + updater.update({.projectDirectory = "/path/one"}); } TEST_F(ProjectStorageUpdater, synchronize_property_editor_qml_paths_directory_if_qmldir_is_changed) { - QStringList directories = {"/path/one"}; setSubdirectoryPaths(u"/path/one", {"/path/one/designer"}); QString qmldir{R"(module Bar)"}; setContent(u"/path/one/qmldir", qmldir); @@ -4654,7 +4937,7 @@ TEST_F(ProjectStorageUpdater, synchronize_property_editor_qml_paths_directory_if &SynchronizationPackage::updatedPropertyEditorQmlPathDirectoryIds, Contains(designer1DirectoryId))))); - updater.update({.directories = directories}); + updater.update({.projectDirectory = "/path/one"}); } } // namespace diff --git a/tests/unit/tests/unittests/projectstorage/qmldocumentparser-test.cpp b/tests/unit/tests/unittests/projectstorage/qmldocumentparser-test.cpp index ebcb9c1a3cc..848d76082bb 100644 --- a/tests/unit/tests/unittests/projectstorage/qmldocumentparser-test.cpp +++ b/tests/unit/tests/unittests/projectstorage/qmldocumentparser-test.cpp @@ -167,7 +167,11 @@ TEST_F(QmlDocumentParser, prototype) { QString component = "Example{}"; - auto type = parser.parse(component, imports, qmlFileSourceId, directoryPath); + auto type = parser.parse(component, + imports, + qmlFileSourceId, + directoryPath, + Storage::IsInsideProject::No); ASSERT_THAT(type, HasPrototype(Synchronization::ImportedType("Example"))); } @@ -178,7 +182,11 @@ TEST_F(QmlDocumentParser, qualified_prototype) QString component = R"(import Example 2.1 as Example Example.Item{})"; - auto type = parser.parse(component, imports, qmlFileSourceId, directoryPath); + auto type = parser.parse(component, + imports, + qmlFileSourceId, + directoryPath, + Storage::IsInsideProject::No); ASSERT_THAT(type, HasPrototype(Synchronization::QualifiedImportedType( @@ -190,7 +198,11 @@ TEST_F(QmlDocumentParser, properties) { QString component = R"(Example{ property int foo })"; - auto type = parser.parse(component, imports, qmlFileSourceId, directoryPath); + auto type = parser.parse(component, + imports, + qmlFileSourceId, + directoryPath, + Storage::IsInsideProject::No); ASSERT_THAT(type.propertyDeclarations, UnorderedElementsAre(IsPropertyDeclaration("foo", @@ -204,7 +216,11 @@ TEST_F(QmlDocumentParser, qualified_properties) QString component = R"(import Example 2.1 as Example Item{ property Example.Foo foo})"; - auto type = parser.parse(component, imports, qmlFileSourceId, directoryPath); + auto type = parser.parse(component, + imports, + qmlFileSourceId, + directoryPath, + Storage::IsInsideProject::No); ASSERT_THAT(type.propertyDeclarations, UnorderedElementsAre(IsPropertyDeclaration( @@ -221,7 +237,11 @@ TEST_F(QmlDocumentParser, enumeration_in_properties) QString component = R"(import Example 2.1 as Example Item{ property Enumeration.Foo foo})"; - auto type = parser.parse(component, imports, qmlFileSourceId, directoryPath); + auto type = parser.parse(component, + imports, + qmlFileSourceId, + directoryPath, + Storage::IsInsideProject::No); ASSERT_THAT(type.propertyDeclarations, UnorderedElementsAre( @@ -236,7 +256,11 @@ TEST_F(QmlDocumentParser, qualified_enumeration_in_properties) QString component = R"(import Example 2.1 as Example Item{ property Example.Enumeration.Foo foo})"; - auto type = parser.parse(component, imports, qmlFileSourceId, directoryPath); + auto type = parser.parse(component, + imports, + qmlFileSourceId, + directoryPath, + Storage::IsInsideProject::No); ASSERT_THAT(type.propertyDeclarations, UnorderedElementsAre(IsPropertyDeclaration( @@ -257,7 +281,11 @@ TEST_F(QmlDocumentParser, imports) import "../foo" Example{})"; - auto type = parser.parse(component, imports, qmlFileSourceId, directoryPath); + auto type = parser.parse(component, + imports, + qmlFileSourceId, + directoryPath, + Storage::IsInsideProject::No); ASSERT_THAT(imports, UnorderedElementsAre( @@ -276,7 +304,11 @@ TEST_F(QmlDocumentParser, imports_with_version) import "../foo" Example{})"; - auto type = parser.parse(component, imports, qmlFileSourceId, directoryPath); + auto type = parser.parse(component, + imports, + qmlFileSourceId, + directoryPath, + Storage::IsInsideProject::No); ASSERT_THAT(imports, UnorderedElementsAre( @@ -295,7 +327,11 @@ TEST_F(QmlDocumentParser, imports_with_explict_directory) import "." Example{})"; - auto type = parser.parse(component, imports, qmlFileSourceId, directoryPath); + auto type = parser.parse(component, + imports, + qmlFileSourceId, + directoryPath, + Storage::IsInsideProject::No); ASSERT_THAT( imports, @@ -308,7 +344,11 @@ TEST_F(QmlDocumentParser, functions) { QString component = "Example{\n function someScript(x, y) {}\n function otherFunction() {}\n}"; - auto type = parser.parse(component, imports, qmlFileSourceId, directoryPath); + auto type = parser.parse(component, + imports, + qmlFileSourceId, + directoryPath, + Storage::IsInsideProject::No); ASSERT_THAT(type.functionDeclarations, UnorderedElementsAre( @@ -326,7 +366,8 @@ TEST_F(QmlDocumentParser, signals) auto type = parser.parse("Example{\n signal someSignal(int x, real y)\n signal signal2()\n}", imports, qmlFileSourceId, - directoryPath); + directoryPath, + Storage::IsInsideProject::No); ASSERT_THAT(type.signalDeclarations, UnorderedElementsAre( @@ -343,7 +384,11 @@ TEST_F(QmlDocumentParser, enumeration) enum Color{red, green, blue=10, white} enum State{On,Off}})"; - auto type = parser.parse(component, imports, qmlFileSourceId, directoryPath); + auto type = parser.parse(component, + imports, + qmlFileSourceId, + directoryPath, + Storage::IsInsideProject::No); ASSERT_THAT(type.enumerationDeclarations, UnorderedElementsAre( @@ -373,7 +418,11 @@ TEST_F(QmlDocumentParser, DISABLED_duplicate_imports_are_removed) Example{})"; - auto type = parser.parse(component, imports, qmlFileSourceId, directoryPath); + auto type = parser.parse(component, + imports, + qmlFileSourceId, + directoryPath, + Storage::IsInsideProject::No); ASSERT_THAT(imports, UnorderedElementsAre( @@ -393,7 +442,11 @@ TEST_F(QmlDocumentParser, alias_item_properties) } })"; - auto type = parser.parse(component, imports, qmlFileSourceId, directoryPath); + auto type = parser.parse(component, + imports, + qmlFileSourceId, + directoryPath, + Storage::IsInsideProject::No); ASSERT_THAT(type.propertyDeclarations, UnorderedElementsAre(IsPropertyDeclaration("delegate", @@ -410,7 +463,11 @@ TEST_F(QmlDocumentParser, alias_properties) } })"; - auto type = parser.parse(component, imports, qmlFileSourceId, directoryPath); + auto type = parser.parse(component, + imports, + qmlFileSourceId, + directoryPath, + Storage::IsInsideProject::No); ASSERT_THAT(type.propertyDeclarations, UnorderedElementsAre( @@ -429,7 +486,11 @@ TEST_F(QmlDocumentParser, indirect_alias_properties) } })"; - auto type = parser.parse(component, imports, qmlFileSourceId, directoryPath); + auto type = parser.parse(component, + imports, + qmlFileSourceId, + directoryPath, + Storage::IsInsideProject::No); ASSERT_THAT(type.propertyDeclarations, UnorderedElementsAre( @@ -449,7 +510,11 @@ TEST_F(QmlDocumentParser, invalid_alias_properties_are_skipped) } })"; - auto type = parser.parse(component, imports, qmlFileSourceId, directoryPath); + auto type = parser.parse(component, + imports, + qmlFileSourceId, + directoryPath, + Storage::IsInsideProject::No); ASSERT_THAT(type.propertyDeclarations, IsEmpty()); } @@ -460,7 +525,11 @@ TEST_F(QmlDocumentParser, list_property) property list foos })"; - auto type = parser.parse(component, imports, qmlFileSourceId, directoryPath); + auto type = parser.parse(component, + imports, + qmlFileSourceId, + directoryPath, + Storage::IsInsideProject::No); ASSERT_THAT(type.propertyDeclarations, UnorderedElementsAre( @@ -480,7 +549,11 @@ TEST_F(QmlDocumentParser, alias_on_list_property) } })"; - auto type = parser.parse(component, imports, qmlFileSourceId, directoryPath); + auto type = parser.parse(component, + imports, + qmlFileSourceId, + directoryPath, + Storage::IsInsideProject::No); ASSERT_THAT(type.propertyDeclarations, UnorderedElementsAre( @@ -497,7 +570,11 @@ TEST_F(QmlDocumentParser, qualified_list_property) property list foos })"; - auto type = parser.parse(component, imports, qmlFileSourceId, directoryPath); + auto type = parser.parse(component, + imports, + qmlFileSourceId, + directoryPath, + Storage::IsInsideProject::No); ASSERT_THAT(type.propertyDeclarations, UnorderedElementsAre(IsPropertyDeclaration( @@ -516,7 +593,11 @@ TEST_F(QmlDocumentParser, default_property) default property list foos })"; - auto type = parser.parse(component, imports, qmlFileSourceId, directoryPath); + auto type = parser.parse(component, + imports, + qmlFileSourceId, + directoryPath, + Storage::IsInsideProject::No); ASSERT_THAT(type.defaultPropertyName, Eq("foos")); } @@ -527,7 +608,11 @@ TEST_F(QmlDocumentParser, has_file_component_trait) Item{ })"; - auto type = parser.parse(component, imports, qmlFileSourceId, directoryPath); + auto type = parser.parse(component, + imports, + qmlFileSourceId, + directoryPath, + Storage::IsInsideProject::No); ASSERT_TRUE(type.traits.isFileComponent); } @@ -538,7 +623,11 @@ TEST_F(QmlDocumentParser, has_is_reference_trait) Item{ })"; - auto type = parser.parse(component, imports, qmlFileSourceId, directoryPath); + auto type = parser.parse(component, + imports, + qmlFileSourceId, + directoryPath, + Storage::IsInsideProject::No); ASSERT_THAT(type.traits.kind, QmlDesigner::Storage::TypeTraitsKind::Reference); } @@ -549,7 +638,11 @@ TEST_F(QmlDocumentParser, is_singleton) Item{ })"; - auto type = parser.parse(component, imports, qmlFileSourceId, directoryPath); + auto type = parser.parse(component, + imports, + qmlFileSourceId, + directoryPath, + Storage::IsInsideProject::No); ASSERT_TRUE(type.traits.isSingleton); } @@ -559,9 +652,41 @@ TEST_F(QmlDocumentParser, is_not_singleton) QString component = R"(Item{ })"; - auto type = parser.parse(component, imports, qmlFileSourceId, directoryPath); + auto type = parser.parse(component, + imports, + qmlFileSourceId, + directoryPath, + Storage::IsInsideProject::No); ASSERT_FALSE(type.traits.isSingleton); } +TEST_F(QmlDocumentParser, is_inside_project) +{ + QString component = R"(Item{ + })"; + + auto type = parser.parse(component, + imports, + qmlFileSourceId, + directoryPath, + Storage::IsInsideProject::Yes); + + ASSERT_TRUE(type.traits.isInsideProject); +} + +TEST_F(QmlDocumentParser, is_not_inside_project) +{ + QString component = R"(Item{ + })"; + + auto type = parser.parse(component, + imports, + qmlFileSourceId, + directoryPath, + Storage::IsInsideProject::No); + + ASSERT_FALSE(type.traits.isInsideProject); +} + } // namespace diff --git a/tests/unit/tests/unittests/projectstorage/qmltypesparser-test.cpp b/tests/unit/tests/unittests/projectstorage/qmltypesparser-test.cpp index d56004a15c1..d25dc12a83a 100644 --- a/tests/unit/tests/unittests/projectstorage/qmltypesparser-test.cpp +++ b/tests/unit/tests/unittests/projectstorage/qmltypesparser-test.cpp @@ -77,6 +77,13 @@ MATCHER_P(IsSingleton, value, std::string(negation ? "isn't singleton " : "is si return traits.isSingleton == value; } +MATCHER_P(IsInsideProject, value, std::string(negation ? "isn't inside project " : "is inside project ")) +{ + const Storage::TypeTraits &traits = arg; + + return traits.isInsideProject == value; +} + template auto IsTypeTrait(const Matcher &matcher) { @@ -203,7 +210,7 @@ TEST_F(QmlTypesParser, imports) dependencies: ["QtQuick 2.15", "QtQuick.Window 2.1", "QtFoo 6"]})"}; - parser.parse(source, imports, types, directoryInfo); + parser.parse(source, imports, types, directoryInfo, Storage::IsInsideProject::No); ASSERT_THAT(imports, UnorderedElementsAre(IsImport(storage.moduleId("QML", ModuleKind::CppLibrary), @@ -230,7 +237,7 @@ TEST_F(QmlTypesParser, types) Component { name: "QObject"} Component { name: "QQmlComponent"}})"}; - parser.parse(source, imports, types, directoryInfo); + parser.parse(source, imports, types, directoryInfo, Storage::IsInsideProject::No); ASSERT_THAT(types, UnorderedElementsAre(IsType("QObject", @@ -253,7 +260,7 @@ TEST_F(QmlTypesParser, prototype) Component { name: "QQmlComponent" prototype: "QObject"}})"}; - parser.parse(source, imports, types, directoryInfo); + parser.parse(source, imports, types, directoryInfo, Storage::IsInsideProject::No); ASSERT_THAT(types, UnorderedElementsAre(IsType("QObject", @@ -276,7 +283,7 @@ TEST_F(QmlTypesParser, extension) Component { name: "QQmlComponent" extension: "QObject"}})"}; - parser.parse(source, imports, types, directoryInfo); + parser.parse(source, imports, types, directoryInfo, Storage::IsInsideProject::No); ASSERT_THAT(types, UnorderedElementsAre(IsType("QObject", @@ -301,7 +308,7 @@ TEST_F(QmlTypesParser, ignore_java_script_extensions) extensionIsJavaScript: true }})"}; - parser.parse(source, imports, types, directoryInfo); + parser.parse(source, imports, types, directoryInfo, Storage::IsInsideProject::No); ASSERT_THAT(types, Contains(IsType("QQmlComponent", @@ -321,7 +328,7 @@ TEST_F(QmlTypesParser, exported_types) ModuleId qmlModuleId = storage.moduleId("QML", ModuleKind::QmlLibrary); ModuleId qtQmlModuleId = storage.moduleId("QtQml", ModuleKind::QmlLibrary); - parser.parse(source, imports, types, directoryInfo); + parser.parse(source, imports, types, directoryInfo, Storage::IsInsideProject::No); ASSERT_THAT( types, @@ -344,7 +351,7 @@ TEST_F(QmlTypesParser, properties) Property { name: "targets"; type: "QQuickItem"; isList: true; isReadonly: true; isPointer: true } }})"}; - parser.parse(source, imports, types, directoryInfo); + parser.parse(source, imports, types, directoryInfo, Storage::IsInsideProject::No); ASSERT_THAT(types, ElementsAre(Field( @@ -378,7 +385,7 @@ TEST_F(QmlTypesParser, properties_with_qualified_types) Property { name: "values2"; type: "Qt::Vector" } }})"}; - parser.parse(source, imports, types, directoryInfo); + parser.parse(source, imports, types, directoryInfo, Storage::IsInsideProject::No); ASSERT_THAT(types, Contains( @@ -404,7 +411,7 @@ TEST_F(QmlTypesParser, properties_without_type) Property { name: "target"; type: "QObject"; isPointer: true } }})"}; - parser.parse(source, imports, types, directoryInfo); + parser.parse(source, imports, types, directoryInfo, Storage::IsInsideProject::No); ASSERT_THAT(types, ElementsAre( @@ -437,7 +444,7 @@ TEST_F(QmlTypesParser, functions) } }})"}; - parser.parse(source, imports, types, directoryInfo); + parser.parse(source, imports, types, directoryInfo, Storage::IsInsideProject::No); ASSERT_THAT(types, ElementsAre(Field( @@ -468,7 +475,7 @@ TEST_F(QmlTypesParser, skip_java_script_functions) } }})"}; - parser.parse(source, imports, types, directoryInfo); + parser.parse(source, imports, types, directoryInfo, Storage::IsInsideProject::No); ASSERT_THAT(types, ElementsAre(Field("Synchronization::Type::functionDeclarations", &Synchronization::Type::functionDeclarations, IsEmpty()))); } @@ -488,7 +495,7 @@ TEST_F(QmlTypesParser, functions_with_qualified_types) } }})"}; - parser.parse(source, imports, types, directoryInfo); + parser.parse(source, imports, types, directoryInfo, Storage::IsInsideProject::No); ASSERT_THAT(types, Contains( @@ -523,7 +530,7 @@ TEST_F(QmlTypesParser, signals) } }})"}; - parser.parse(source, imports, types, directoryInfo); + parser.parse(source, imports, types, directoryInfo, Storage::IsInsideProject::No); ASSERT_THAT(types, ElementsAre(Field("Synchronization::Type::signalDeclarations", &Synchronization::Type::signalDeclarations, @@ -556,7 +563,7 @@ TEST_F(QmlTypesParser, signals_with_qualified_types) } }})"}; - parser.parse(source, imports, types, directoryInfo); + parser.parse(source, imports, types, directoryInfo, Storage::IsInsideProject::No); ASSERT_THAT(types, Contains( @@ -589,7 +596,7 @@ TEST_F(QmlTypesParser, enumerations) } }})"}; - parser.parse(source, imports, types, directoryInfo); + parser.parse(source, imports, types, directoryInfo, Storage::IsInsideProject::No); ASSERT_THAT(types, Contains(Field( @@ -628,7 +635,7 @@ TEST_F(QmlTypesParser, enumeration_is_exported_as_type) exports: ["QML/QtObject 1.0", "QtQml/QtObject 2.1"] }})"}; - parser.parse(source, imports, types, directoryInfo); + parser.parse(source, imports, types, directoryInfo, Storage::IsInsideProject::No); QmlDesigner::Storage::TypeTraits traits{QmlDesigner::Storage::TypeTraitsKind::Value}; traits.isEnum = true; @@ -674,7 +681,7 @@ TEST_F(QmlTypesParser, enumeration_is_exported_as_type_with_alias) exports: ["QML/QtObject 1.0", "QtQml/QtObject 2.1"] }})"}; - parser.parse(source, imports, types, directoryInfo); + parser.parse(source, imports, types, directoryInfo, Storage::IsInsideProject::No); QmlDesigner::Storage::TypeTraits traits{QmlDesigner::Storage::TypeTraitsKind::Value}; traits.isEnum = true; @@ -722,7 +729,7 @@ TEST_F(QmlTypesParser, enumeration_is_exported_as_type_with_alias_too) exports: ["QML/QtObject 1.0", "QtQml/QtObject 2.1"] }})"}; - parser.parse(source, imports, types, directoryInfo); + parser.parse(source, imports, types, directoryInfo, Storage::IsInsideProject::No); QmlDesigner::Storage::TypeTraits traits{QmlDesigner::Storage::TypeTraitsKind::Value}; traits.isEnum = true; @@ -760,7 +767,7 @@ TEST_F(QmlTypesParser, enumeration_is_referenced_by_qualified_name) } }})"}; - parser.parse(source, imports, types, directoryInfo); + parser.parse(source, imports, types, directoryInfo, Storage::IsInsideProject::No); ASSERT_THAT(types, Contains(Field("Synchronization::Type::propertyDeclarations", &Synchronization::Type::propertyDeclarations, @@ -788,7 +795,7 @@ TEST_F(QmlTypesParser, alias_enumeration_is_referenced_by_qualified_name) } }})"}; - parser.parse(source, imports, types, directoryInfo); + parser.parse(source, imports, types, directoryInfo, Storage::IsInsideProject::No); ASSERT_THAT(types, Contains(Field("Synchronization::Type::propertyDeclarations", &Synchronization::Type::propertyDeclarations, @@ -805,7 +812,7 @@ TEST_F(QmlTypesParser, access_type_is_reference) Component { name: "QObject" accessSemantics: "reference"}})"}; - parser.parse(source, imports, types, directoryInfo); + parser.parse(source, imports, types, directoryInfo, Storage::IsInsideProject::No); ASSERT_THAT(types, ElementsAre(IsTypeTrait(Storage::TypeTraitsKind::Reference))); } @@ -817,7 +824,7 @@ TEST_F(QmlTypesParser, access_type_is_value) Component { name: "QObject" accessSemantics: "value"}})"}; - parser.parse(source, imports, types, directoryInfo); + parser.parse(source, imports, types, directoryInfo, Storage::IsInsideProject::No); ASSERT_THAT(types, ElementsAre(IsTypeTrait(Storage::TypeTraitsKind::Value))); } @@ -829,7 +836,7 @@ TEST_F(QmlTypesParser, access_type_is_sequence) Component { name: "QObject" accessSemantics: "sequence"}})"}; - parser.parse(source, imports, types, directoryInfo); + parser.parse(source, imports, types, directoryInfo, Storage::IsInsideProject::No); ASSERT_THAT(types, ElementsAre(IsTypeTrait(Storage::TypeTraitsKind::Sequence))); } @@ -841,7 +848,7 @@ TEST_F(QmlTypesParser, access_type_is_none) Component { name: "QObject" accessSemantics: "none"}})"}; - parser.parse(source, imports, types, directoryInfo); + parser.parse(source, imports, types, directoryInfo, Storage::IsInsideProject::No); ASSERT_THAT(types, ElementsAre(IsTypeTrait(Storage::TypeTraitsKind::None))); } @@ -853,7 +860,7 @@ TEST_F(QmlTypesParser, uses_custom_parser) Component { name: "QObject" hasCustomParser: true }})"}; - parser.parse(source, imports, types, directoryInfo); + parser.parse(source, imports, types, directoryInfo, Storage::IsInsideProject::No); ASSERT_THAT(types, ElementsAre(IsTypeTrait(UsesCustomParser(true)))); } @@ -865,7 +872,7 @@ TEST_F(QmlTypesParser, uses_no_custom_parser) Component { name: "QObject" hasCustomParser: false }})"}; - parser.parse(source, imports, types, directoryInfo); + parser.parse(source, imports, types, directoryInfo, Storage::IsInsideProject::No); ASSERT_THAT(types, ElementsAre(IsTypeTrait(UsesCustomParser(false)))); } @@ -877,7 +884,7 @@ TEST_F(QmlTypesParser, default_property) Component { name: "QObject" defaultProperty: "children" }})"}; - parser.parse(source, imports, types, directoryInfo); + parser.parse(source, imports, types, directoryInfo, Storage::IsInsideProject::No); ASSERT_THAT(types, ElementsAre(Field("Synchronization::Type::defaultPropertyName", &Synchronization::Type::defaultPropertyName, Eq("children")))); @@ -895,7 +902,7 @@ TEST_F(QmlTypesParser, skip_template_item) Component { name: "QQuickItem"} Component { name: "QQmlComponent"}})"}; - parser.parse(source, imports, types, directoryInfo); + parser.parse(source, imports, types, directoryInfo, Storage::IsInsideProject::No); ASSERT_THAT(types, UnorderedElementsAre(IsType("QQmlComponent", @@ -912,7 +919,7 @@ TEST_F(QmlTypesParser, is_singleton) Component { name: "QObject" isSingleton: true}})"}; - parser.parse(source, imports, types, directoryInfo); + parser.parse(source, imports, types, directoryInfo, Storage::IsInsideProject::No); ASSERT_THAT(types, ElementsAre(IsTypeTrait(IsSingleton(true)))); } @@ -924,7 +931,7 @@ TEST_F(QmlTypesParser, is_not_singleton) Component { name: "QObject" isSingleton: false}})"}; - parser.parse(source, imports, types, directoryInfo); + parser.parse(source, imports, types, directoryInfo, Storage::IsInsideProject::No); ASSERT_THAT(types, ElementsAre(IsTypeTrait(IsSingleton(false)))); } @@ -935,9 +942,31 @@ TEST_F(QmlTypesParser, is_by_default_not_singleton) Module{ Component { name: "QObject"}})"}; - parser.parse(source, imports, types, directoryInfo); + parser.parse(source, imports, types, directoryInfo, Storage::IsInsideProject::No); ASSERT_THAT(types, ElementsAre(IsTypeTrait(IsSingleton(false)))); } +TEST_F(QmlTypesParser, is_inside_project) +{ + QString source{R"(import QtQuick.tooling 1.2 + Module{ + Component { name: "QObject"}})"}; + + parser.parse(source, imports, types, directoryInfo, Storage::IsInsideProject::Yes); + + ASSERT_THAT(types, ElementsAre(IsTypeTrait(IsInsideProject(true)))); +} + +TEST_F(QmlTypesParser, is_not_inside_project) +{ + QString source{R"(import QtQuick.tooling 1.2 + Module{ + Component { name: "QObject"}})"}; + + parser.parse(source, imports, types, directoryInfo, Storage::IsInsideProject::No); + + ASSERT_THAT(types, ElementsAre(IsTypeTrait(IsInsideProject(false)))); +} + } // namespace