QmlDesigner: Project property sheet path collection

The property sheet paths are always collected if the designer directory,
module directory, or the qmldir file is changed. We could minimize the
updates, but then we must add an extra linking step in the project
storage. That extra linking step would be needed because there could be
property sheets for non-existing types.

Task-number: QDS-14618
Change-Id: Idc26e41e3b4298fb118452045f3d907ad9f5e619
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
Marco Bubke
2025-02-10 18:10:04 +01:00
committed by Thomas Hartmann
parent 48b65e32c8
commit 8862233fb8
13 changed files with 608 additions and 144 deletions

View File

@@ -22,8 +22,7 @@ public:
friend bool operator==(const FileStatus &first, const FileStatus &second) friend bool operator==(const FileStatus &first, const FileStatus &second)
{ {
return first.sourceId == second.sourceId && first.size == second.size return first.sourceId == second.sourceId && first.size == second.size
&& first.lastModified == second.lastModified && first.size >= 0 && first.lastModified == second.lastModified;
&& first.lastModified >= 0;
} }
friend bool operator!=(const FileStatus &first, const FileStatus &second) friend bool operator!=(const FileStatus &first, const FileStatus &second)
@@ -46,9 +45,9 @@ public:
return first.sourceId < second; return first.sourceId < second;
} }
bool isValid() const { return sourceId && size >= 0 && lastModified >= 0; } bool isExisting() const { return sourceId && size >= 0 && lastModified >= 0; }
explicit operator bool() const { return isValid(); } explicit operator bool() const { return bool(sourceId); }
template<typename String> template<typename String>
friend void convertToString(String &string, const FileStatus &fileStatus) friend void convertToString(String &string, const FileStatus &fileStatus)

View File

@@ -31,9 +31,9 @@ SourceIds FileSystem::directoryEntries(const QString &directoryPath) const
return sourceIds; return sourceIds;
} }
QStringList FileSystem::qmlFileNames(const QString &directoryPath) const QStringList FileSystem::fileNames(const QString &directoryPath, const QStringList &nameFilters) const
{ {
return QDir{directoryPath}.entryList({"*.qml"}, QDir::Files); return QDir{directoryPath}.entryList(nameFilters, QDir::Files);
} }
long long FileSystem::lastModified(SourceId sourceId) const long long FileSystem::lastModified(SourceId sourceId) const

View File

@@ -25,7 +25,7 @@ public:
{} {}
SourceIds directoryEntries(const QString &directoryPath) const override; SourceIds directoryEntries(const QString &directoryPath) const override;
QStringList qmlFileNames(const QString &directoryPath) const override; QStringList fileNames(const QString &directoryPath, const QStringList &nameFilters) const override;
long long lastModified(SourceId sourceId) const override; long long lastModified(SourceId sourceId) const override;
FileStatus fileStatus(SourceId sourceId) const override; FileStatus fileStatus(SourceId sourceId) const override;
QString contentAsQString(const QString &filePath) const override; QString contentAsQString(const QString &filePath) const override;

View File

@@ -15,7 +15,7 @@ class FileSystemInterface
{ {
public: public:
virtual SourceIds directoryEntries(const QString &directoryPath) const = 0; virtual SourceIds directoryEntries(const QString &directoryPath) const = 0;
virtual QStringList qmlFileNames(const QString &directoryPath) const = 0; virtual QStringList fileNames(const QString &directoryPath, const QStringList &nameFilters) const = 0;
virtual long long lastModified(SourceId sourceId) const = 0; virtual long long lastModified(SourceId sourceId) const = 0;
virtual FileStatus fileStatus(SourceId sourceId) const = 0; virtual FileStatus fileStatus(SourceId sourceId) const = 0;
virtual void remove(const SourceIds &sourceIds) = 0; virtual void remove(const SourceIds &sourceIds) = 0;

View File

@@ -1335,7 +1335,7 @@ void ProjectStorage::synchronize(Storage::Synchronization::SynchronizationPackag
package.updatedSourceIds); package.updatedSourceIds);
synchronizeTypeAnnotations(package.typeAnnotations, package.updatedTypeAnnotationSourceIds); synchronizeTypeAnnotations(package.typeAnnotations, package.updatedTypeAnnotationSourceIds);
synchronizePropertyEditorQmlPaths(package.propertyEditorQmlPaths, synchronizePropertyEditorQmlPaths(package.propertyEditorQmlPaths,
package.updatedPropertyEditorQmlPathSourceContextIds); package.updatedPropertyEditorQmlPathDirectoryIds);
deleteNotUpdatedTypes(updatedTypeIds, deleteNotUpdatedTypes(updatedTypeIds,
package.updatedSourceIds, package.updatedSourceIds,
@@ -1413,6 +1413,9 @@ ModuleId ProjectStorage::moduleId(Utils::SmallStringView moduleName, Storage::Mo
projectStorageCategory(), projectStorageCategory(),
keyValue("module name", moduleName)}; keyValue("module name", moduleName)};
if (moduleName.empty())
return ModuleId{};
auto moduleId = moduleCache.id({moduleName, kind}); auto moduleId = moduleCache.id({moduleName, kind});
tracer.end(keyValue("module id", moduleId)); tracer.end(keyValue("module id", moduleId));

View File

@@ -1331,7 +1331,7 @@ public:
ModuleExportedImports moduleExportedImports; ModuleExportedImports moduleExportedImports;
ModuleIds updatedModuleIds; ModuleIds updatedModuleIds;
PropertyEditorQmlPaths propertyEditorQmlPaths; PropertyEditorQmlPaths propertyEditorQmlPaths;
SourceContextIds updatedPropertyEditorQmlPathSourceContextIds; SourceContextIds updatedPropertyEditorQmlPathDirectoryIds;
TypeAnnotations typeAnnotations; TypeAnnotations typeAnnotations;
SourceIds updatedTypeAnnotationSourceIds; SourceIds updatedTypeAnnotationSourceIds;
}; };

View File

@@ -37,12 +37,21 @@ void convertToString(String &string, const ProjectStorageUpdater::FileState &sta
case ProjectStorageUpdater::FileState::Changed: case ProjectStorageUpdater::FileState::Changed:
convertToString(string, "Changed"); convertToString(string, "Changed");
break; break;
case ProjectStorageUpdater::FileState::NotChanged: case ProjectStorageUpdater::FileState::Unchanged:
convertToString(string, "NotChanged"); convertToString(string, "Unchanged");
break; break;
case ProjectStorageUpdater::FileState::NotExists: case ProjectStorageUpdater::FileState::NotExists:
convertToString(string, "NotExists"); convertToString(string, "NotExists");
break; break;
case ProjectStorageUpdater::FileState::NotExistsUnchanged:
convertToString(string, "NotExistsUnchanged");
break;
case ProjectStorageUpdater::FileState::Added:
convertToString(string, "Added");
break;
case ProjectStorageUpdater::FileState::Removed:
convertToString(string, "Removed");
break;
} }
} }
@@ -92,7 +101,7 @@ ProjectStorageUpdater::Components createComponents(
{ {
ProjectStorageUpdater::Components components; ProjectStorageUpdater::Components components;
auto qmlFileNames = fileSystem.qmlFileNames(directory); auto qmlFileNames = fileSystem.fileNames(directory, {"*.qml"});
components.reserve(static_cast<std::size_t>(qmlDirParserComponents.size() + qmlFileNames.size())); components.reserve(static_cast<std::size_t>(qmlDirParserComponents.size() + qmlFileNames.size()));
@@ -289,35 +298,87 @@ void ProjectStorageUpdater::update(Update update)
} }
namespace { namespace {
bool isChanged(ProjectStorageUpdater::FileState state)
{
using FileState = ProjectStorageUpdater::FileState;
switch (state) {
case FileState::Changed:
case FileState::Added:
case FileState::Removed:
return true;
case FileState::NotExists:
case FileState::NotExistsUnchanged:
case FileState::Unchanged:
break;
}
return false;
}
bool isUnchanged(ProjectStorageUpdater::FileState state)
{
return !isChanged(state);
}
template<typename... FileStates> template<typename... FileStates>
ProjectStorageUpdater::FileState combineState(FileStates... fileStates) ProjectStorageUpdater::FileState combineState(FileStates... fileStates)
{ {
if (((fileStates == ProjectStorageUpdater::FileState::Changed) || ...)) if (((fileStates == ProjectStorageUpdater::FileState::Removed) && ...))
return ProjectStorageUpdater::FileState::Removed;
if (((fileStates == ProjectStorageUpdater::FileState::Added) && ...))
return ProjectStorageUpdater::FileState::Added;
if ((isChanged(fileStates) || ...))
return ProjectStorageUpdater::FileState::Changed; return ProjectStorageUpdater::FileState::Changed;
if (((fileStates == ProjectStorageUpdater::FileState::NotChanged) || ...)) if (((fileStates == ProjectStorageUpdater::FileState::Unchanged) || ...))
return ProjectStorageUpdater::FileState::NotChanged; return ProjectStorageUpdater::FileState::Unchanged;
return ProjectStorageUpdater::FileState::NotExists; return ProjectStorageUpdater::FileState::NotExists;
} }
bool isExisting(ProjectStorageUpdater::FileState state)
{
using FileState = ProjectStorageUpdater::FileState;
switch (state) {
case FileState::Changed:
case FileState::Added:
case FileState::Unchanged:
return true;
case FileState::NotExistsUnchanged:
case FileState::NotExists:
case FileState::Removed:
break;
}
return false;
}
bool isNotExisting(ProjectStorageUpdater::FileState state)
{
return !isExisting(state);
}
} // namespace } // namespace
void ProjectStorageUpdater::updateDirectoryChanged(Utils::SmallStringView directoryPath, void ProjectStorageUpdater::updateDirectoryChanged(Utils::SmallStringView directoryPath,
Utils::SmallStringView annotationDirectoryPath,
FileState qmldirState, FileState qmldirState,
FileState annotationDirectoryState,
SourcePath qmldirSourcePath, SourcePath qmldirSourcePath,
SourceId qmldirSourceId, SourceId qmldirSourceId,
SourceContextId directoryId, SourceContextId directoryId,
SourceContextId annotationDirectoryId,
Storage::Synchronization::SynchronizationPackage &package, Storage::Synchronization::SynchronizationPackage &package,
NotUpdatedSourceIds &notUpdatedSourceIds, NotUpdatedSourceIds &notUpdatedSourceIds,
WatchedSourceIdsIds &watchedSourceIdsIds, WatchedSourceIdsIds &watchedSourceIdsIds,
Tracer &tracer) Tracer &tracer)
{ {
QmlDirParser parser; QmlDirParser parser;
if (qmldirState != FileState::NotExists) if (isExisting(qmldirState))
parser.parse(m_fileSystem.contentAsQString(QString{qmldirSourcePath})); parser.parse(m_fileSystem.contentAsQString(QString{qmldirSourcePath}));
if (qmldirState != FileState::NotChanged) { if (isChanged(qmldirState)) {
tracer.tick("append updated source id", keyValue("module id", qmldirSourceId)); tracer.tick("append updated source id", keyValue("module id", qmldirSourceId));
package.updatedSourceIds.push_back(qmldirSourceId); package.updatedSourceIds.push_back(qmldirSourceId);
} }
@@ -374,6 +435,17 @@ void ProjectStorageUpdater::updateDirectoryChanged(Utils::SmallStringView direct
qmldirSourceId); qmldirSourceId);
tracer.tick("append updated project source id", keyValue("module id", moduleId)); tracer.tick("append updated project source id", keyValue("module id", moduleId));
package.updatedDirectoryInfoDirectoryIds.push_back(directoryId); 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);
}
} }
void ProjectStorageUpdater::updateDirectories(const QStringList &directories, void ProjectStorageUpdater::updateDirectories(const QStringList &directories,
@@ -417,11 +489,12 @@ void ProjectStorageUpdater::updateSubdirectories(const Utils::PathString &direct
auto exisitingSubdirectoryPaths = m_fileSystem.subdirectories(directoryPath.toQString()); auto exisitingSubdirectoryPaths = m_fileSystem.subdirectories(directoryPath.toQString());
Directories existingSubdirecories; Directories existingSubdirecories;
for (const QString &subdirectory : exisitingSubdirectoryPaths) {
if (subdirectory.endsWith("/designer") || subdirectory.endsWith("/QtQuick/Scene2D") for (Utils::PathString subdirectoryPath : exisitingSubdirectoryPaths) {
|| subdirectory.endsWith("/QtQuick/Scene3D")) if (subdirectoryPath.endsWith("designer") || subdirectoryPath.endsWith("/QtQuick/Scene2D")
|| subdirectoryPath.endsWith("/QtQuick/Scene3D"))
continue; continue;
Utils::PathString subdirectoryPath = subdirectory;
SourceContextId sourceContextId = m_pathCache.sourceContextId(subdirectoryPath); SourceContextId sourceContextId = m_pathCache.sourceContextId(subdirectoryPath);
subdirectories.emplace_back(subdirectoryPath, sourceContextId); subdirectories.emplace_back(subdirectoryPath, sourceContextId);
existingSubdirecories.emplace_back(subdirectoryPath, sourceContextId); existingSubdirecories.emplace_back(subdirectoryPath, sourceContextId);
@@ -454,6 +527,64 @@ void ProjectStorageUpdater::updateSubdirectories(const Utils::PathString &direct
} }
} }
void ProjectStorageUpdater::annotationDirectoryChanged(
Utils::SmallStringView directoryPath,
SourceContextId directoryId,
SourceContextId annotationDirectoryId,
ModuleId moduleId,
Storage::Synchronization::SynchronizationPackage &package,
NotUpdatedSourceIds &notUpdatedSourceIds)
{
NanotraceHR::Tracer tracer{"annotation directory changed",
category(),
keyValue("directory path", directoryPath),
keyValue("directory id", directoryId)};
package.updatedPropertyEditorQmlPathDirectoryIds.push_back(annotationDirectoryId);
updatePropertyEditorFiles(directoryPath, annotationDirectoryId, moduleId, package, notUpdatedSourceIds);
}
void ProjectStorageUpdater::updatePropertyEditorFiles(
Utils::SmallStringView directoryPath,
SourceContextId directoryId,
ModuleId moduleId,
Storage::Synchronization::SynchronizationPackage &package,
NotUpdatedSourceIds &notUpdatedSourceIds)
{
NanotraceHR::Tracer tracer{"update property editor files",
category(),
keyValue("directory path", directoryPath),
keyValue("directory id", directoryId)};
const auto fileNames = m_fileSystem.fileNames(QString{directoryPath},
{"*Pane.qml",
"*Specifics.qml",
"*SpecificsDynamic.qml"});
for (const QString &fileName : fileNames)
updatePropertyEditorFile(fileName, directoryId, moduleId, package, notUpdatedSourceIds);
}
void ProjectStorageUpdater::updatePropertyEditorFile(
const QString &fileName,
SourceContextId directoryId,
ModuleId moduleId,
Storage::Synchronization::SynchronizationPackage &package,
NotUpdatedSourceIds &notUpdatedSourceIds)
{
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);
Storage::TypeNameString typeName{match.capturedView(1)};
package.propertyEditorQmlPaths.emplace_back(moduleId, typeName, propertyEditorSourceId, directoryId);
}
void ProjectStorageUpdater::updateDirectory(const Utils::PathString &directoryPath, void ProjectStorageUpdater::updateDirectory(const Utils::PathString &directoryPath,
const SourceContextIds &subdirectoriesToIgnore, const SourceContextIds &subdirectoriesToIgnore,
Storage::Synchronization::SynchronizationPackage &package, Storage::Synchronization::SynchronizationPackage &package,
@@ -462,32 +593,39 @@ void ProjectStorageUpdater::updateDirectory(const Utils::PathString &directoryPa
{ {
NanotraceHR::Tracer tracer{"update directory", category(), keyValue("directory", directoryPath)}; NanotraceHR::Tracer tracer{"update directory", category(), keyValue("directory", directoryPath)};
SourcePath qmldirSourcePath{directoryPath + "/qmldir"}; SourcePath qmldirPath{directoryPath + "/qmldir"};
auto [directoryId, qmldirSourceId] = m_pathCache.sourceContextAndSourceId(qmldirSourcePath); auto [directoryId, qmldirSourceId] = m_pathCache.sourceContextAndSourceId(qmldirPath);
auto directoryState = fileState(directoryId, package, notUpdatedSourceIds); auto directoryState = fileState(directoryId, package, notUpdatedSourceIds);
if (directoryState != FileState::NotExists) if (isExisting(directoryState))
watchedSourceIdsIds.directoryIds.push_back(SourceId::create(SourceNameId{}, directoryId)); watchedSourceIdsIds.directoryIds.push_back(SourceId::create(SourceNameId{}, directoryId));
auto qmldirState = fileState(qmldirSourceId, package, notUpdatedSourceIds); auto qmldirState = fileState(qmldirSourceId, package, notUpdatedSourceIds);
if (qmldirState != FileState::NotExists) if (isExisting(qmldirState))
watchedSourceIdsIds.qmldirSourceIds.push_back(qmldirSourceId); watchedSourceIdsIds.qmldirSourceIds.push_back(qmldirSourceId);
switch (combineState(directoryState, qmldirState)) { SourcePath annotationDirectoryPath{directoryPath + "/designer"};
case FileState::Changed: { auto annotationDirectoryId = m_pathCache.sourceContextId(annotationDirectoryPath);
auto annotationDirectoryState = fileState(annotationDirectoryId, package, notUpdatedSourceIds);
switch (combineState(directoryState, qmldirState, annotationDirectoryState)) {
case FileState::Changed:
case FileState::Added:
tracer.tick("update directory changed"); tracer.tick("update directory changed");
updateDirectoryChanged(directoryPath, updateDirectoryChanged(directoryPath,
annotationDirectoryPath,
qmldirState, qmldirState,
qmldirSourcePath, annotationDirectoryState,
qmldirPath,
qmldirSourceId, qmldirSourceId,
directoryId, directoryId,
annotationDirectoryId,
package, package,
notUpdatedSourceIds, notUpdatedSourceIds,
watchedSourceIdsIds, watchedSourceIdsIds,
tracer); tracer);
break; break;
} case FileState::Unchanged:
case FileState::NotChanged: {
tracer.tick("update directory not changed"); tracer.tick("update directory not changed");
parseDirectoryInfos(m_projectStorage.fetchDirectoryInfos(directoryId), parseDirectoryInfos(m_projectStorage.fetchDirectoryInfos(directoryId),
@@ -495,13 +633,9 @@ void ProjectStorageUpdater::updateDirectory(const Utils::PathString &directoryPa
notUpdatedSourceIds, notUpdatedSourceIds,
watchedSourceIdsIds); watchedSourceIdsIds);
break; break;
} case FileState::Removed: {
case FileState::NotExists: {
tracer.tick("update directory don't exits"); tracer.tick("update directory don't exits");
auto directorySourceId = SourceId::create(SourceNameId{}, directoryId);
package.updatedFileStatusSourceIds.push_back(directorySourceId);
package.updatedFileStatusSourceIds.push_back(qmldirSourceId);
package.updatedDirectoryInfoDirectoryIds.push_back(directoryId); package.updatedDirectoryInfoDirectoryIds.push_back(directoryId);
package.updatedSourceIds.push_back(qmldirSourceId); package.updatedSourceIds.push_back(qmldirSourceId);
auto qmlDirectoryInfos = m_projectStorage.fetchDirectoryInfos(directoryId); auto qmlDirectoryInfos = m_projectStorage.fetchDirectoryInfos(directoryId);
@@ -512,9 +646,11 @@ void ProjectStorageUpdater::updateDirectory(const Utils::PathString &directoryPa
keyValue("source id", directoryInfo.sourceId)); keyValue("source id", directoryInfo.sourceId));
package.updatedFileStatusSourceIds.push_back(directoryInfo.sourceId); package.updatedFileStatusSourceIds.push_back(directoryInfo.sourceId);
} }
break; break;
} }
case FileState::NotExists:
case FileState::NotExistsUnchanged:
break;
} }
updateSubdirectories(directoryPath, updateSubdirectories(directoryPath,
@@ -525,7 +661,7 @@ void ProjectStorageUpdater::updateDirectory(const Utils::PathString &directoryPa
notUpdatedSourceIds, notUpdatedSourceIds,
watchedSourceIdsIds); watchedSourceIdsIds);
tracer.end(keyValue("qmldir source path", qmldirSourcePath), tracer.end(keyValue("qmldir source path", qmldirPath),
keyValue("directory id", directoryId), keyValue("directory id", directoryId),
keyValue("qmldir source id", qmldirSourceId), keyValue("qmldir source id", qmldirSourceId),
keyValue("qmldir state", qmldirState), keyValue("qmldir state", qmldirState),
@@ -630,7 +766,7 @@ void ProjectStorageUpdater::updateTypeAnnotations(
if (state == FileState::Changed) if (state == FileState::Changed)
updateTypeAnnotation(directoryPath, fileInfo.filePath(), sourceId, directoryId, package); updateTypeAnnotation(directoryPath, fileInfo.filePath(), sourceId, directoryId, package);
if (state != FileState::NotChanged) if (state != FileState::Unchanged)
updatedSourceIdsDictonary[directoryId].push_back(sourceId); updatedSourceIdsDictonary[directoryId].push_back(sourceId);
} }
} }
@@ -643,7 +779,7 @@ void ProjectStorageUpdater::updateTypeAnnotationDirectories(
for (auto &[directoryId, updatedSourceIds] : updatedSourceIdsDictonary) { for (auto &[directoryId, updatedSourceIds] : updatedSourceIdsDictonary) {
auto directoryState = fileState(directoryId, package, notUpdatedSourceIds); auto directoryState = fileState(directoryId, package, notUpdatedSourceIds);
if (directoryState != FileState::NotChanged) { if (directoryState != FileState::Unchanged) {
auto existingTypeAnnotationSourceIds = m_projectStorage.typeAnnotationSourceIds( auto existingTypeAnnotationSourceIds = m_projectStorage.typeAnnotationSourceIds(
directoryId); directoryId);
@@ -708,7 +844,7 @@ void ProjectStorageUpdater::updatePropertyEditorPath(
tracer.tick("append updated property editor qml path source id", tracer.tick("append updated property editor qml path source id",
keyValue("source id", directoryId)); keyValue("source id", directoryId));
package.updatedPropertyEditorQmlPathSourceContextIds.push_back(directoryId); package.updatedPropertyEditorQmlPathDirectoryIds.push_back(directoryId);
auto dir = QDir{directoryPath}; auto dir = QDir{directoryPath};
const auto fileInfos = dir.entryInfoList({"*Pane.qml", "*Specifics.qml"}, QDir::Files); const auto fileInfos = dir.entryInfoList({"*Pane.qml", "*Specifics.qml"}, QDir::Files);
for (const auto &fileInfo : fileInfos) for (const auto &fileInfo : fileInfos)
@@ -950,6 +1086,7 @@ auto ProjectStorageUpdater::parseTypeInfo(const Storage::Synchronization::Direct
auto state = fileState(directoryInfo.sourceId, package, notUpdatedSourceIds); auto state = fileState(directoryInfo.sourceId, package, notUpdatedSourceIds);
switch (state) { switch (state) {
case FileState::Added:
case FileState::Changed: { case FileState::Changed: {
tracer.tick("append updated source ids", keyValue("source id", directoryInfo.sourceId)); tracer.tick("append updated source ids", keyValue("source id", directoryInfo.sourceId));
package.updatedSourceIds.push_back(directoryInfo.sourceId); package.updatedSourceIds.push_back(directoryInfo.sourceId);
@@ -958,12 +1095,14 @@ auto ProjectStorageUpdater::parseTypeInfo(const Storage::Synchronization::Direct
m_qmlTypesParser.parse(content, package.imports, package.types, directoryInfo); m_qmlTypesParser.parse(content, package.imports, package.types, directoryInfo);
break; break;
} }
case FileState::NotChanged: { case FileState::Unchanged: {
tracer.tick("append not updated source ids", keyValue("source id", directoryInfo.sourceId)); tracer.tick("append not updated source ids", keyValue("source id", directoryInfo.sourceId));
notUpdatedSourceIds.sourceIds.push_back(directoryInfo.sourceId); notUpdatedSourceIds.sourceIds.push_back(directoryInfo.sourceId);
break; break;
} }
case FileState::NotExists: case FileState::NotExists:
case FileState::NotExistsUnchanged:
case FileState::Removed:
throw CannotParseQmlTypesFile{}; throw CannotParseQmlTypesFile{};
} }
@@ -1003,8 +1142,8 @@ void ProjectStorageUpdater::parseQmlComponent(Utils::SmallStringView relativeFil
watchedSourceIds.qmlSourceIds.push_back(sourceId); watchedSourceIds.qmlSourceIds.push_back(sourceId);
switch (state) { switch (state) {
case FileState::NotChanged: case FileState::Unchanged:
if (qmldirState == FileState::NotExists) { if (isNotExisting(qmldirState)) {
tracer.tick("append not updated source id", keyValue("source id", sourceId)); tracer.tick("append not updated source id", keyValue("source id", sourceId));
notUpdatedSourceIds.sourceIds.emplace_back(sourceId); notUpdatedSourceIds.sourceIds.emplace_back(sourceId);
@@ -1017,6 +1156,7 @@ void ProjectStorageUpdater::parseQmlComponent(Utils::SmallStringView relativeFil
type.changeLevel = Storage::Synchronization::ChangeLevel::Minimal; type.changeLevel = Storage::Synchronization::ChangeLevel::Minimal;
break; break;
case FileState::NotExists: case FileState::NotExists:
case FileState::Removed:
tracer.tick("file does not exits", keyValue("source id", sourceId)); tracer.tick("file does not exits", keyValue("source id", sourceId));
for (const auto &exportedType : exportedTypes) for (const auto &exportedType : exportedTypes)
m_errorNotifier.qmlDocumentDoesNotExistsForQmldirEntry(exportedType.name, m_errorNotifier.qmlDocumentDoesNotExistsForQmldirEntry(exportedType.name,
@@ -1024,6 +1164,9 @@ void ProjectStorageUpdater::parseQmlComponent(Utils::SmallStringView relativeFil
sourceId, sourceId,
qmldirSourceId); qmldirSourceId);
break; break;
case FileState::NotExistsUnchanged:
break;
case FileState::Added:
case FileState::Changed: case FileState::Changed:
tracer.tick("update from qml document", keyValue("source id", sourceId)); tracer.tick("update from qml document", keyValue("source id", sourceId));
const auto content = m_fileSystem.contentAsQString(QString{qmlFilePath}); const auto content = m_fileSystem.contentAsQString(QString{qmlFilePath});
@@ -1033,7 +1176,7 @@ void ProjectStorageUpdater::parseQmlComponent(Utils::SmallStringView relativeFil
const auto &directoryInfo = package.directoryInfos.emplace_back( const auto &directoryInfo = package.directoryInfos.emplace_back(
directoryId, sourceId, ModuleId{}, Storage::Synchronization::FileType::QmlDocument); directoryId, sourceId, ModuleId{}, Storage::Synchronization::FileType::QmlDocument);
tracer.tick("append project data", keyValue("project data", directoryInfo)); tracer.tick("append directory info", keyValue("project data", directoryInfo));
tracer.tick("append updated source id", keyValue("source id", sourceId)); tracer.tick("append updated source id", keyValue("source id", sourceId));
package.updatedSourceIds.push_back(sourceId); package.updatedSourceIds.push_back(sourceId);
@@ -1054,13 +1197,13 @@ void ProjectStorageUpdater::parseQmlComponent(SourceId sourceId,
NanotraceHR::Tracer tracer{"parse qml component", category(), keyValue("source id", sourceId)}; NanotraceHR::Tracer tracer{"parse qml component", category(), keyValue("source id", sourceId)};
auto state = fileState(sourceId, package, notUpdatedSourceIds); auto state = fileState(sourceId, package, notUpdatedSourceIds);
if (state == FileState::NotChanged) if (isUnchanged(state))
return; return;
tracer.tick("append updated source id", keyValue("source id", sourceId)); tracer.tick("append updated source id", keyValue("source id", sourceId));
package.updatedSourceIds.push_back(sourceId); package.updatedSourceIds.push_back(sourceId);
if (state == FileState::NotExists) if (isNotExisting(state))
return; return;
SourcePath sourcePath = m_pathCache.sourcePath(sourceId); SourcePath sourcePath = m_pathCache.sourcePath(sourceId);
@@ -1186,33 +1329,42 @@ ProjectStorageUpdater::FileState ProjectStorageUpdater::fileState(
keyValue("source id", sourceId)}; keyValue("source id", sourceId)};
auto currentFileStatus = m_fileStatusCache.find(sourceId); auto currentFileStatus = m_fileStatusCache.find(sourceId);
auto projectStorageFileStatus = m_projectStorage.fetchFileStatus(sourceId);
if (!currentFileStatus.isValid()) { if (!currentFileStatus.isExisting()) {
tracer.tick("append updated file status source id", keyValue("source id", sourceId)); if (projectStorageFileStatus.isExisting()) {
package.updatedFileStatusSourceIds.push_back(sourceId);
return FileState::Removed;
}
if (projectStorageFileStatus) {
notUpdatedSourceIds.fileStatusSourceIds.push_back(sourceId);
return FileState::NotExistsUnchanged;
}
package.fileStatuses.push_back(currentFileStatus);
package.updatedFileStatusSourceIds.push_back(sourceId); package.updatedFileStatusSourceIds.push_back(sourceId);
tracer.end(keyValue("state", FileState::NotExists));
return FileState::NotExists; return FileState::NotExists;
} }
auto projectStorageFileStatus = m_projectStorage.fetchFileStatus(sourceId); if (!projectStorageFileStatus) {
package.fileStatuses.push_back(currentFileStatus);
if (!projectStorageFileStatus.isValid() || projectStorageFileStatus != currentFileStatus) { package.updatedFileStatusSourceIds.push_back(sourceId);
tracer.tick("append file status", keyValue("file status", sourceId));
return FileState::Added;
}
if (projectStorageFileStatus != currentFileStatus) {
package.fileStatuses.push_back(currentFileStatus); package.fileStatuses.push_back(currentFileStatus);
tracer.tick("append updated file status source id", keyValue("source id", sourceId));
package.updatedFileStatusSourceIds.push_back(sourceId); package.updatedFileStatusSourceIds.push_back(sourceId);
tracer.end(keyValue("state", FileState::Changed));
return FileState::Changed; return FileState::Changed;
} }
tracer.tick("append not updated file status source id", keyValue("source id", sourceId));
notUpdatedSourceIds.fileStatusSourceIds.push_back(sourceId); notUpdatedSourceIds.fileStatusSourceIds.push_back(sourceId);
tracer.end(keyValue("state", FileState::NotChanged)); return FileState::Unchanged;
return FileState::NotChanged;
} }
} // namespace QmlDesigner } // namespace QmlDesigner

View File

@@ -104,11 +104,7 @@ public:
const_iterator m_end; const_iterator m_end;
}; };
enum class FileState { enum class FileState { Unchanged, Changed, NotExists, NotExistsUnchanged, Added, Removed };
NotChanged,
Changed,
NotExists,
};
struct WatchedSourceIdsIds struct WatchedSourceIdsIds
{ {
@@ -157,15 +153,33 @@ private:
NotUpdatedSourceIds &notUpdatedSourceIds, NotUpdatedSourceIds &notUpdatedSourceIds,
WatchedSourceIdsIds &watchedSourceIdsIds); WatchedSourceIdsIds &watchedSourceIdsIds);
void updateDirectoryChanged(Utils::SmallStringView directoryPath, void updateDirectoryChanged(Utils::SmallStringView directoryPath,
Utils::SmallStringView annotationDirectoryPath,
FileState qmldirState, FileState qmldirState,
FileState annotationDirectoryState,
SourcePath qmldirSourcePath, SourcePath qmldirSourcePath,
SourceId qmldirSourceId, SourceId qmldirSourceId,
SourceContextId directoryId, SourceContextId directoryId,
SourceContextId annotationDirectoryId,
Storage::Synchronization::SynchronizationPackage &package, Storage::Synchronization::SynchronizationPackage &package,
NotUpdatedSourceIds &notUpdatedSourceIds, NotUpdatedSourceIds &notUpdatedSourceIds,
WatchedSourceIdsIds &watchedSourceIdsIds, WatchedSourceIdsIds &watchedSourceIdsIds,
ProjectStorageTracing::Category::TracerType &tracer); ProjectStorageTracing::Category::TracerType &tracer);
void annotationDirectoryChanged(Utils::SmallStringView directoryPath,
SourceContextId directoryId,
SourceContextId annotationDirectoryId,
ModuleId moduleId,
Storage::Synchronization::SynchronizationPackage &package,
NotUpdatedSourceIds &notUpdatedSourceIds);
void updatePropertyEditorFiles(Utils::SmallStringView directyPath,
SourceContextId directoryId,
ModuleId moduleId,
Storage::Synchronization::SynchronizationPackage &package,
NotUpdatedSourceIds &notUpdatedSourceIds);
void updatePropertyEditorFile(const QString &fileName,
SourceContextId directoryId,
ModuleId moduleId,
Storage::Synchronization::SynchronizationPackage &package,
NotUpdatedSourceIds &notUpdatedSourceIds);
void updatePropertyEditorPaths(const QString &propertyEditorResourcesPath, void updatePropertyEditorPaths(const QString &propertyEditorResourcesPath,
Storage::Synchronization::SynchronizationPackage &package, Storage::Synchronization::SynchronizationPackage &package,
NotUpdatedSourceIds &notUpdatedSourceIds); NotUpdatedSourceIds &notUpdatedSourceIds);

View File

@@ -15,7 +15,10 @@ public:
directoryEntries, directoryEntries,
(const QString &directoryPath), (const QString &directoryPath),
(const, override)); (const, override));
MOCK_METHOD(QStringList, qmlFileNames, (const QString &directoryPath), (const, override)); MOCK_METHOD(QStringList,
fileNames,
(const QString &directoryPath, const QStringList &nameFilters),
(const, override));
MOCK_METHOD(long long, lastModified, (QmlDesigner::SourceId sourceId), (const, override)); MOCK_METHOD(long long, lastModified, (QmlDesigner::SourceId sourceId), (const, override));
MOCK_METHOD(QmlDesigner::FileStatus, fileStatus, (QmlDesigner::SourceId sourceId), (const, override)); MOCK_METHOD(QmlDesigner::FileStatus, fileStatus, (QmlDesigner::SourceId sourceId), (const, override));
MOCK_METHOD(void, remove, (const QmlDesigner::SourceIds &sourceIds), (override)); MOCK_METHOD(void, remove, (const QmlDesigner::SourceIds &sourceIds), (override));

View File

@@ -853,11 +853,11 @@ std::ostream &operator<<(std::ostream &out, const SynchronizationPackage &packag
<< ", updatedSourceIds: " << package.updatedSourceIds << ", updatedSourceIds: " << package.updatedSourceIds
<< ", fileStatuses: " << package.fileStatuses << ", fileStatuses: " << package.fileStatuses
<< ", updatedFileStatusSourceIds: " << package.updatedFileStatusSourceIds << ", updatedFileStatusSourceIds: " << package.updatedFileStatusSourceIds
<< ", updatedDirectoryInfoDirectoryIds: " << package.updatedDirectoryInfoDirectoryIds
<< ", directoryInfos: " << package.directoryInfos << ", directoryInfos: " << package.directoryInfos
<< ", updatedDirectoryInfoDirectoryIds: " << package.updatedDirectoryInfoDirectoryIds
<< ", propertyEditorQmlPaths: " << package.propertyEditorQmlPaths << ", propertyEditorQmlPaths: " << package.propertyEditorQmlPaths
<< ", updatedPropertyEditorQmlPathSourceIds: " << ", updatedPropertyEditorQmlPathSourceIds: "
<< package.updatedPropertyEditorQmlPathSourceContextIds << package.updatedPropertyEditorQmlPathDirectoryIds
<< ", typeAnnotations: " << package.typeAnnotations << ", typeAnnotations: " << package.typeAnnotations
<< ", updatedTypeAnnotationSourceIds: " << package.updatedTypeAnnotationSourceIds << ", updatedTypeAnnotationSourceIds: " << package.updatedTypeAnnotationSourceIds
<< ")"; << ")";
@@ -963,7 +963,8 @@ std::ostream &operator<<(std::ostream &out, const ModuleExportedImport &import)
std::ostream &operator<<(std::ostream &out, const PropertyEditorQmlPath &path) std::ostream &operator<<(std::ostream &out, const PropertyEditorQmlPath &path)
{ {
return out << "(" << path.moduleId << ", " << path.typeName << ", " << path.pathId << ")"; return out << "(" << path.moduleId << ", " << path.typeName << ", " << path.pathId << ", "
<< path.directoryId << ", " << path.typeId << ")";
} }
std::ostream &operator<<(std::ostream &out, const TypeAnnotation &annotation) std::ostream &operator<<(std::ostream &out, const TypeAnnotation &annotation)

View File

@@ -1079,7 +1079,7 @@ protected:
"Item3D", "Item3D",
sourceId3, sourceId3,
sourceContextIdPath6); sourceContextIdPath6);
package.updatedPropertyEditorQmlPathSourceContextIds.emplace_back(sourceContextIdPath6); package.updatedPropertyEditorQmlPathDirectoryIds.emplace_back(sourceContextIdPath6);
return package; return package;
} }
@@ -5774,6 +5774,13 @@ TEST_F(ProjectStorage, get_module_id)
ASSERT_TRUE(id); ASSERT_TRUE(id);
} }
TEST_F(ProjectStorage, get_invalid_module_id_for_empty_name)
{
auto id = storage.moduleId("", ModuleKind::QmlLibrary);
ASSERT_FALSE(id);
}
TEST_F(ProjectStorage, get_same_module_id_again) TEST_F(ProjectStorage, get_same_module_id_again)
{ {
auto initialId = storage.moduleId("Qml", ModuleKind::QmlLibrary); auto initialId = storage.moduleId("Qml", ModuleKind::QmlLibrary);

View File

@@ -133,7 +133,7 @@ MATCHER(PackageIsEmpty, std::string(negation ? "isn't empty" : "is empty"))
&& package.updatedModuleDependencySourceIds.empty() && package.updatedModuleDependencySourceIds.empty()
&& package.moduleExportedImports.empty() && package.updatedModuleIds.empty() && package.moduleExportedImports.empty() && package.updatedModuleIds.empty()
&& package.propertyEditorQmlPaths.empty() && package.propertyEditorQmlPaths.empty()
&& package.updatedPropertyEditorQmlPathSourceContextIds.empty() && package.updatedPropertyEditorQmlPathDirectoryIds.empty()
&& package.typeAnnotations.empty() && package.updatedTypeAnnotationSourceIds.empty(); && package.typeAnnotations.empty() && package.updatedTypeAnnotationSourceIds.empty();
} }
@@ -188,6 +188,11 @@ public:
qmltypes1SourceId, qmltypes1SourceId,
qmltypes2SourceId, qmltypes2SourceId,
itemLibraryPathSourceId}); itemLibraryPathSourceId});
setFilesDontExistsUnchanged({createDirectorySourceId("/path/designer"),
createDirectorySourceId("/root/designer"),
createDirectorySourceId("/path/one/designer"),
createDirectorySourceId("/path/two/designer"),
createDirectorySourceId("/path/three/designer")});
setFilesAdded({qmldir1SourceId, qmldir2SourceId, qmldir3SourceId}); setFilesAdded({qmldir1SourceId, qmldir2SourceId, qmldir3SourceId});
@@ -279,7 +284,8 @@ public:
void setFilesRemoved(const QmlDesigner::SourceIds &sourceIds) void setFilesRemoved(const QmlDesigner::SourceIds &sourceIds)
{ {
for (auto sourceId : sourceIds) { for (auto sourceId : sourceIds) {
ON_CALL(fileSystemMock, fileStatus(Eq(sourceId))).WillByDefault(Return(FileStatus{})); ON_CALL(fileSystemMock, fileStatus(Eq(sourceId)))
.WillByDefault(Return(FileStatus{sourceId, -1, -1}));
ON_CALL(projectStorageMock, fetchFileStatus(Eq(sourceId))) ON_CALL(projectStorageMock, fetchFileStatus(Eq(sourceId)))
.WillByDefault(Return(FileStatus{sourceId, 1, 21})); .WillByDefault(Return(FileStatus{sourceId, 1, 21}));
} }
@@ -288,15 +294,34 @@ public:
void setFilesDontExists(const QmlDesigner::SourceIds &sourceIds) void setFilesDontExists(const QmlDesigner::SourceIds &sourceIds)
{ {
for (auto sourceId : sourceIds) { for (auto sourceId : sourceIds) {
ON_CALL(fileSystemMock, fileStatus(Eq(sourceId))).WillByDefault(Return(FileStatus{})); ON_CALL(fileSystemMock, fileStatus(Eq(sourceId)))
.WillByDefault(Return(FileStatus{sourceId, -1, -1}));
ON_CALL(projectStorageMock, fetchFileStatus(Eq(sourceId))) ON_CALL(projectStorageMock, fetchFileStatus(Eq(sourceId)))
.WillByDefault(Return(FileStatus{})); .WillByDefault(Return(FileStatus{SourceId{}, -1, -1}));
} }
} }
void setFilesDontExistsUnchanged(const QmlDesigner::SourceIds &sourceIds)
{
for (auto sourceId : sourceIds) {
ON_CALL(fileSystemMock, fileStatus(Eq(sourceId)))
.WillByDefault(Return(FileStatus{sourceId, -1, -1}));
ON_CALL(projectStorageMock, fetchFileStatus(Eq(sourceId)))
.WillByDefault(Return(FileStatus{sourceId, -1, -1}));
}
}
void setFileNames(QStringView directoryPath,
const QStringList &fileNames,
const QStringList &nameFilters)
{
ON_CALL(fileSystemMock, fileNames(Eq(directoryPath), UnorderedElementsAreArray(nameFilters)))
.WillByDefault(Return(fileNames));
}
void setQmlFileNames(QStringView directoryPath, const QStringList &qmlFileNames) void setQmlFileNames(QStringView directoryPath, const QStringList &qmlFileNames)
{ {
ON_CALL(fileSystemMock, qmlFileNames(Eq(directoryPath))).WillByDefault(Return(qmlFileNames)); setFileNames(directoryPath, qmlFileNames, {"*.qml"});
} }
void setDirectoryInfos(SourceContextId directorySourceId, const DirectoryInfos &directoryInfos) void setDirectoryInfos(SourceContextId directorySourceId, const DirectoryInfos &directoryInfos)
@@ -376,6 +401,7 @@ protected:
SourceId qmlDirPathSourceId = sourcePathCache.sourceId("/path/qmldir"); SourceId qmlDirPathSourceId = sourcePathCache.sourceId("/path/qmldir");
SourceContextId directoryPathId = qmlDirPathSourceId.contextId(); SourceContextId directoryPathId = qmlDirPathSourceId.contextId();
SourceId directoryPathSourceId = SourceId::create(QmlDesigner::SourceNameId{}, directoryPathId); SourceId directoryPathSourceId = SourceId::create(QmlDesigner::SourceNameId{}, directoryPathId);
SourceId annotationDirectorySourceId = createDirectorySourceId("/path/designer");
SourceId qmlDocumentSourceId1 = sourcePathCache.sourceId("/path/First.qml"); SourceId qmlDocumentSourceId1 = sourcePathCache.sourceId("/path/First.qml");
SourceId qmlDocumentSourceId2 = sourcePathCache.sourceId("/path/First2.qml"); SourceId qmlDocumentSourceId2 = sourcePathCache.sourceId("/path/First2.qml");
SourceId qmlDocumentSourceId3 = sourcePathCache.sourceId("/path/Second.qml"); SourceId qmlDocumentSourceId3 = sourcePathCache.sourceId("/path/Second.qml");
@@ -2277,10 +2303,7 @@ TEST_F(ProjectStorageUpdater, synchronize_qml_documents_without_qmldir)
UnorderedElementsAre(IsExportedType(pathModuleId, "Second", -1, -1)))))), UnorderedElementsAre(IsExportedType(pathModuleId, "Second", -1, -1)))))),
Field("SynchronizationPackage::updatedSourceIds", Field("SynchronizationPackage::updatedSourceIds",
&SynchronizationPackage::updatedSourceIds, &SynchronizationPackage::updatedSourceIds,
UnorderedElementsAre(qmlDirPathSourceId, UnorderedElementsAre(qmlDocumentSourceId1, qmlDocumentSourceId2, qmlDocumentSourceId3)),
qmlDocumentSourceId1,
qmlDocumentSourceId2,
qmlDocumentSourceId3)),
Field("SynchronizationPackage::updatedFileStatusSourceIds", Field("SynchronizationPackage::updatedFileStatusSourceIds",
&SynchronizationPackage::updatedFileStatusSourceIds, &SynchronizationPackage::updatedFileStatusSourceIds,
UnorderedElementsAre(directoryPathSourceId, UnorderedElementsAre(directoryPathSourceId,
@@ -2291,6 +2314,7 @@ TEST_F(ProjectStorageUpdater, synchronize_qml_documents_without_qmldir)
Field("SynchronizationPackage::fileStatuses", Field("SynchronizationPackage::fileStatuses",
&SynchronizationPackage::fileStatuses, &SynchronizationPackage::fileStatuses,
UnorderedElementsAre(IsFileStatus(directoryPathSourceId, 1, 21), UnorderedElementsAre(IsFileStatus(directoryPathSourceId, 1, 21),
IsFileStatus(qmlDirPathSourceId, -1, -1),
IsFileStatus(qmlDocumentSourceId1, 1, 21), IsFileStatus(qmlDocumentSourceId1, 1, 21),
IsFileStatus(qmlDocumentSourceId2, 1, 21), IsFileStatus(qmlDocumentSourceId2, 1, 21),
IsFileStatus(qmlDocumentSourceId3, 1, 21))), IsFileStatus(qmlDocumentSourceId3, 1, 21))),
@@ -2331,7 +2355,7 @@ TEST_F(ProjectStorageUpdater,
synchronize_qml_documents_without_parsed_type_if_qml_document_does_not_exists) synchronize_qml_documents_without_parsed_type_if_qml_document_does_not_exists)
{ {
setFilesDontExists({qmlDocumentSourceId1}); setFilesDontExists({qmlDocumentSourceId1});
setFilesAdded({directoryPathSourceId}); setFilesAdded({directoryPathSourceId, qmlDirPathSourceId, qmlDocumentSourceId2});
QString qmldir{R"(module Example QString qmldir{R"(module Example
FirstType 1.0 First.qml FirstType 1.0 First.qml
FirstType 2.2 First2.qml)"}; FirstType 2.2 First2.qml)"};
@@ -2379,6 +2403,7 @@ TEST_F(ProjectStorageUpdater,
&SynchronizationPackage::fileStatuses, &SynchronizationPackage::fileStatuses,
UnorderedElementsAre(IsFileStatus(directoryPathSourceId, 1, 21), UnorderedElementsAre(IsFileStatus(directoryPathSourceId, 1, 21),
IsFileStatus(qmlDirPathSourceId, 1, 21), IsFileStatus(qmlDirPathSourceId, 1, 21),
IsFileStatus(qmlDocumentSourceId1, -1, -1),
IsFileStatus(qmlDocumentSourceId2, 1, 21))), IsFileStatus(qmlDocumentSourceId2, 1, 21))),
Field("SynchronizationPackage::updatedDirectoryInfoDirectoryIds", Field("SynchronizationPackage::updatedDirectoryInfoDirectoryIds",
&SynchronizationPackage::updatedDirectoryInfoDirectoryIds, &SynchronizationPackage::updatedDirectoryInfoDirectoryIds,
@@ -2397,9 +2422,14 @@ TEST_F(ProjectStorageUpdater,
updater.update({.directories = directories}); updater.update({.directories = directories});
} }
TEST_F(ProjectStorageUpdater, synchronize_qml_documents_without_qmldir_throws_if_directory_does_not_exists) TEST_F(ProjectStorageUpdater, synchronize_qml_documents_without_qmldir_if_directory_is_removed)
{ {
setFilesDontExists({qmlDirPathSourceId, directoryPathSourceId}); setFilesRemoved({qmlDirPathSourceId,
directoryPathSourceId,
annotationDirectorySourceId,
qmlDocumentSourceId1,
qmlDocumentSourceId2,
qmlDocumentSourceId3});
setDirectoryInfos(directoryPathId, setDirectoryInfos(directoryPathId,
{{directoryPathId, qmlDocumentSourceId1, ModuleId{}, FileType::QmlDocument}, {{directoryPathId, qmlDocumentSourceId1, ModuleId{}, FileType::QmlDocument},
{directoryPathId, qmlDocumentSourceId2, ModuleId{}, FileType::QmlDocument}, {directoryPathId, qmlDocumentSourceId2, ModuleId{}, FileType::QmlDocument},
@@ -2419,6 +2449,7 @@ TEST_F(ProjectStorageUpdater, synchronize_qml_documents_without_qmldir_throws_if
Field("SynchronizationPackage::updatedFileStatusSourceIds", Field("SynchronizationPackage::updatedFileStatusSourceIds",
&SynchronizationPackage::updatedFileStatusSourceIds, &SynchronizationPackage::updatedFileStatusSourceIds,
UnorderedElementsAre(directoryPathSourceId, UnorderedElementsAre(directoryPathSourceId,
annotationDirectorySourceId,
qmlDirPathSourceId, qmlDirPathSourceId,
qmlDocumentSourceId1, qmlDocumentSourceId1,
qmlDocumentSourceId2, qmlDocumentSourceId2,
@@ -2438,7 +2469,7 @@ TEST_F(ProjectStorageUpdater, synchronize_qml_documents_without_qmldir_throws_if
TEST_F(ProjectStorageUpdater, synchronize_qml_documents_without_qmldir_add_qml_document) TEST_F(ProjectStorageUpdater, synchronize_qml_documents_without_qmldir_add_qml_document)
{ {
setFilesDontExists({qmlDirPathSourceId}); setFilesDontExistsUnchanged({qmlDirPathSourceId});
setFilesChanged({directoryPathSourceId}); setFilesChanged({directoryPathSourceId});
setFilesAdded({qmlDocumentSourceId3}); setFilesAdded({qmlDocumentSourceId3});
setFilesDontChanged({qmlDocumentSourceId1, qmlDocumentSourceId2}); setFilesDontChanged({qmlDocumentSourceId1, qmlDocumentSourceId2});
@@ -2446,29 +2477,29 @@ TEST_F(ProjectStorageUpdater, synchronize_qml_documents_without_qmldir_add_qml_d
{{directoryPathId, qmlDocumentSourceId1, ModuleId{}, FileType::QmlDocument}, {{directoryPathId, qmlDocumentSourceId1, ModuleId{}, FileType::QmlDocument},
{directoryPathId, qmlDocumentSourceId2, ModuleId{}, FileType::QmlDocument}}); {directoryPathId, qmlDocumentSourceId2, ModuleId{}, FileType::QmlDocument}});
EXPECT_CALL( EXPECT_CALL(projectStorageMock,
projectStorageMock, synchronize(
synchronize(AllOf( AllOf(Field("SynchronizationPackage::imports",
Field("SynchronizationPackage::imports",
&SynchronizationPackage::imports, &SynchronizationPackage::imports,
UnorderedElementsAre(import3)), UnorderedElementsAre(import3)),
Field("SynchronizationPackage::types", Field("SynchronizationPackage::types",
&SynchronizationPackage::types, &SynchronizationPackage::types,
UnorderedElementsAre(AllOf( UnorderedElementsAre(
IsStorageType("Second.qml", AllOf(IsStorageType("Second.qml",
ImportedType{"Object3"}, ImportedType{"Object3"},
TypeTraitsKind::Reference, TypeTraitsKind::Reference,
qmlDocumentSourceId3, qmlDocumentSourceId3,
ChangeLevel::Full), ChangeLevel::Full),
Field("Type::exportedTypes", Field("Type::exportedTypes",
&Type::exportedTypes, &Type::exportedTypes,
UnorderedElementsAre(IsExportedType(pathModuleId, "Second", -1, -1)))))), UnorderedElementsAre(
IsExportedType(pathModuleId, "Second", -1, -1)))))),
Field("SynchronizationPackage::updatedSourceIds", Field("SynchronizationPackage::updatedSourceIds",
&SynchronizationPackage::updatedSourceIds, &SynchronizationPackage::updatedSourceIds,
UnorderedElementsAre(qmlDirPathSourceId, qmlDocumentSourceId3)), UnorderedElementsAre(qmlDocumentSourceId3)),
Field("SynchronizationPackage::updatedFileStatusSourceIds", Field("SynchronizationPackage::updatedFileStatusSourceIds",
&SynchronizationPackage::updatedFileStatusSourceIds, &SynchronizationPackage::updatedFileStatusSourceIds,
UnorderedElementsAre(directoryPathSourceId, qmlDirPathSourceId, qmlDocumentSourceId3)), UnorderedElementsAre(directoryPathSourceId, qmlDocumentSourceId3)),
Field("SynchronizationPackage::fileStatuses", Field("SynchronizationPackage::fileStatuses",
&SynchronizationPackage::fileStatuses, &SynchronizationPackage::fileStatuses,
UnorderedElementsAre(IsFileStatus(directoryPathSourceId, 1, 21), UnorderedElementsAre(IsFileStatus(directoryPathSourceId, 1, 21),
@@ -2478,11 +2509,18 @@ TEST_F(ProjectStorageUpdater, synchronize_qml_documents_without_qmldir_add_qml_d
UnorderedElementsAre(directoryPathId)), UnorderedElementsAre(directoryPathId)),
Field("SynchronizationPackage::directoryInfos", Field("SynchronizationPackage::directoryInfos",
&SynchronizationPackage::directoryInfos, &SynchronizationPackage::directoryInfos,
UnorderedElementsAre( UnorderedElementsAre(IsDirectoryInfo(directoryPathId,
IsDirectoryInfo(directoryPathId, qmlDocumentSourceId1, ModuleId{}, FileType::QmlDocument), qmlDocumentSourceId1,
IsDirectoryInfo(directoryPathId, qmlDocumentSourceId2, ModuleId{}, FileType::QmlDocument), ModuleId{},
IsDirectoryInfo( FileType::QmlDocument),
directoryPathId, qmlDocumentSourceId3, ModuleId{}, FileType::QmlDocument)))))); IsDirectoryInfo(directoryPathId,
qmlDocumentSourceId2,
ModuleId{},
FileType::QmlDocument),
IsDirectoryInfo(directoryPathId,
qmlDocumentSourceId3,
ModuleId{},
FileType::QmlDocument))))));
updater.update({.directories = directories}); updater.update({.directories = directories});
} }
@@ -2506,13 +2544,14 @@ TEST_F(ProjectStorageUpdater, synchronize_qml_documents_without_qmldir_removes_q
Field("SynchronizationPackage::types", &SynchronizationPackage::types, IsEmpty()), Field("SynchronizationPackage::types", &SynchronizationPackage::types, IsEmpty()),
Field("SynchronizationPackage::updatedSourceIds", Field("SynchronizationPackage::updatedSourceIds",
&SynchronizationPackage::updatedSourceIds, &SynchronizationPackage::updatedSourceIds,
UnorderedElementsAre(qmlDirPathSourceId, qmlDocumentSourceId3)), UnorderedElementsAre(qmlDocumentSourceId3)),
Field("SynchronizationPackage::updatedFileStatusSourceIds", Field("SynchronizationPackage::updatedFileStatusSourceIds",
&SynchronizationPackage::updatedFileStatusSourceIds, &SynchronizationPackage::updatedFileStatusSourceIds,
UnorderedElementsAre(directoryPathSourceId, qmlDirPathSourceId, qmlDocumentSourceId3)), UnorderedElementsAre(directoryPathSourceId, qmlDirPathSourceId, qmlDocumentSourceId3)),
Field("SynchronizationPackage::fileStatuses", Field("SynchronizationPackage::fileStatuses",
&SynchronizationPackage::fileStatuses, &SynchronizationPackage::fileStatuses,
UnorderedElementsAre(IsFileStatus(directoryPathSourceId, 1, 21))), UnorderedElementsAre(IsFileStatus(directoryPathSourceId, 1, 21),
IsFileStatus(qmlDirPathSourceId, -1, -1))),
Field("SynchronizationPackage::updatedDirectoryInfoDirectoryIds", Field("SynchronizationPackage::updatedDirectoryInfoDirectoryIds",
&SynchronizationPackage::updatedDirectoryInfoDirectoryIds, &SynchronizationPackage::updatedDirectoryInfoDirectoryIds,
UnorderedElementsAre(directoryPathId)), UnorderedElementsAre(directoryPathId)),
@@ -2672,7 +2711,9 @@ TEST_F(ProjectStorageUpdater, watcher_updates_subdirectories)
TEST_F(ProjectStorageUpdater, watcher_updates_removed_directory) TEST_F(ProjectStorageUpdater, watcher_updates_removed_directory)
{ {
auto annotationDirectorySourceId = createDirectorySourceId("/path/designer");
setFilesRemoved({directoryPathSourceId, setFilesRemoved({directoryPathSourceId,
annotationDirectorySourceId,
qmlDirPathSourceId, qmlDirPathSourceId,
qmlDocumentSourceId1, qmlDocumentSourceId1,
qmlDocumentSourceId2, qmlDocumentSourceId2,
@@ -2696,13 +2737,14 @@ TEST_F(ProjectStorageUpdater, watcher_updates_removed_directory)
Field("SynchronizationPackage::updatedFileStatusSourceIds", Field("SynchronizationPackage::updatedFileStatusSourceIds",
&SynchronizationPackage::updatedFileStatusSourceIds, &SynchronizationPackage::updatedFileStatusSourceIds,
UnorderedElementsAre(directoryPathSourceId, UnorderedElementsAre(directoryPathSourceId,
annotationDirectorySourceId,
qmlDirPathSourceId, qmlDirPathSourceId,
qmlDocumentSourceId1, qmlDocumentSourceId1,
qmlDocumentSourceId2, qmlDocumentSourceId2,
qmlDocumentSourceId3)), qmlDocumentSourceId3)),
Field("SynchronizationPackage::fileStatuses", Field("SynchronizationPackage::fileStatuses",
&SynchronizationPackage::fileStatuses, &SynchronizationPackage::fileStatuses,
UnorderedElementsAre()), IsEmpty()),
Field("SynchronizationPackage::updatedDirectoryInfoDirectoryIds", Field("SynchronizationPackage::updatedDirectoryInfoDirectoryIds",
&SynchronizationPackage::updatedDirectoryInfoDirectoryIds, &SynchronizationPackage::updatedDirectoryInfoDirectoryIds,
UnorderedElementsAre(directoryPathId)), UnorderedElementsAre(directoryPathId)),
@@ -3439,7 +3481,9 @@ TEST_F(ProjectStorageUpdater, watcher_updates_qml_documents)
TEST_F(ProjectStorageUpdater, watcher_updates_removed_qml_documents) TEST_F(ProjectStorageUpdater, watcher_updates_removed_qml_documents)
{ {
setFilesDontExistsUnchanged({annotationDirectorySourceId, qmlDirPathSourceId});
setFilesRemoved({qmlDocumentSourceId2}); setFilesRemoved({qmlDocumentSourceId2});
setFilesChanged({qmlDocumentSourceId1});
EXPECT_CALL(projectStorageMock, EXPECT_CALL(projectStorageMock,
synchronize( synchronize(
@@ -3450,11 +3494,13 @@ TEST_F(ProjectStorageUpdater, watcher_updates_removed_qml_documents)
&SynchronizationPackage::types, &SynchronizationPackage::types,
UnorderedElementsAre(AllOf( UnorderedElementsAre(AllOf(
IsStorageType("First.qml", IsStorageType("First.qml",
ImportedType{"Object"}, Storage::Synchronization::ImportedType{"Object"},
TypeTraitsKind::Reference, TypeTraitsKind::Reference,
qmlDocumentSourceId1, qmlDocumentSourceId1,
ChangeLevel::ExcludeExportedTypes), Storage::Synchronization::ChangeLevel::ExcludeExportedTypes),
Field("Type::exportedTypes", &Type::exportedTypes, IsEmpty())))), Field("exportedTypes",
&Storage::Synchronization::Type::exportedTypes,
IsEmpty())))),
Field("SynchronizationPackage::updatedSourceIds", Field("SynchronizationPackage::updatedSourceIds",
&SynchronizationPackage::updatedSourceIds, &SynchronizationPackage::updatedSourceIds,
UnorderedElementsAre(qmlDocumentSourceId1, qmlDocumentSourceId2)), UnorderedElementsAre(qmlDocumentSourceId1, qmlDocumentSourceId2)),
@@ -4162,10 +4208,9 @@ TEST_F(ProjectStorageUpdater, update_property_editor_panes)
setFilesChanged({directorySourceId}); setFilesChanged({directorySourceId});
auto qmlModuleId = storage.moduleId("QML", ModuleKind::QmlLibrary); auto qmlModuleId = storage.moduleId("QML", ModuleKind::QmlLibrary);
EXPECT_CALL( EXPECT_CALL(projectStorageMock,
projectStorageMock, synchronize(
synchronize(AllOf( AllOf(Field("SynchronizationPackage::fileStatuses",
Field("SynchronizationPackage::fileStatuses",
&SynchronizationPackage::fileStatuses, &SynchronizationPackage::fileStatuses,
UnorderedElementsAre(IsFileStatus(directorySourceId, 1, 21))), UnorderedElementsAre(IsFileStatus(directorySourceId, 1, 21))),
Field("SynchronizationPackage::updatedFileStatusSourceIds", Field("SynchronizationPackage::updatedFileStatusSourceIds",
@@ -4173,9 +4218,10 @@ TEST_F(ProjectStorageUpdater, update_property_editor_panes)
UnorderedElementsAre(directorySourceId)), UnorderedElementsAre(directorySourceId)),
Field("SynchronizationPackage::propertyEditorQmlPaths", Field("SynchronizationPackage::propertyEditorQmlPaths",
&SynchronizationPackage::propertyEditorQmlPaths, &SynchronizationPackage::propertyEditorQmlPaths,
Contains(IsPropertyEditorQmlPath(qmlModuleId, "QtObject", sourceId, directoryId))), Contains(IsPropertyEditorQmlPath(
Field("SynchronizationPackage::updatedPropertyEditorQmlPathSourceContextIds", qmlModuleId, "QtObject", sourceId, directoryId))),
&SynchronizationPackage::updatedPropertyEditorQmlPathSourceContextIds, Field("SynchronizationPackage::updatedPropertyEditorQmlPathDirectoryIds",
&SynchronizationPackage::updatedPropertyEditorQmlPathDirectoryIds,
ElementsAre(directoryId))))); ElementsAre(directoryId)))));
updater.update({.propertyEditorResourcesPath = propertyEditorQmlPath}); updater.update({.propertyEditorResourcesPath = propertyEditorQmlPath});
@@ -4213,8 +4259,8 @@ TEST_F(ProjectStorageUpdater, update_property_editor_specifics)
{IsPropertyEditorQmlPath(qtQuickModuleId, "Text", textSourceId, qtQuickDirectoryId), {IsPropertyEditorQmlPath(qtQuickModuleId, "Text", textSourceId, qtQuickDirectoryId),
IsPropertyEditorQmlPath( IsPropertyEditorQmlPath(
controlsModuleId, "Button", buttonSourceId, controlsDirectoryId)})), controlsModuleId, "Button", buttonSourceId, controlsDirectoryId)})),
Field("SynchronizationPackage::updatedPropertyEditorQmlPathSourceContextIds", Field("SynchronizationPackage::updatedPropertyEditorQmlPathDirectoryIds",
&SynchronizationPackage::updatedPropertyEditorQmlPathSourceContextIds, &SynchronizationPackage::updatedPropertyEditorQmlPathDirectoryIds,
ElementsAre(qtQuickDirectoryId, controlsDirectoryId))))); ElementsAre(qtQuickDirectoryId, controlsDirectoryId)))));
updater.update({.propertyEditorResourcesPath = propertyEditorQmlPath}); updater.update({.propertyEditorResourcesPath = propertyEditorQmlPath});
@@ -4373,4 +4419,242 @@ TEST_F(ProjectStorageUpdater, update_type_annotations_removed_directory)
updater.update({.typeAnnotationPaths = {itemLibraryPath}}); updater.update({.typeAnnotationPaths = {itemLibraryPath}});
} }
TEST_F(ProjectStorageUpdater, synchronize_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});
EXPECT_CALL(projectStorageMock,
synchronize(
AllOf(Field("SynchronizationPackage::fileStatuses",
&SynchronizationPackage::fileStatuses,
IsSupersetOf({IsFileStatus(designer1SourceId, 1, 21)})),
Field("SynchronizationPackage::updatedFileStatusSourceIds",
&SynchronizationPackage::updatedFileStatusSourceIds,
IsSupersetOf({designer1SourceId})),
Field("SynchronizationPackage::propertyEditorQmlPaths",
&SynchronizationPackage::propertyEditorQmlPaths,
Each(Field("PropertyEditorQmlPath::directoryId",
&PropertyEditorQmlPath::directoryId,
designer1DirectoryId))),
Field("SynchronizationPackage::updatedPropertyEditorQmlPathDirectoryIds",
&SynchronizationPackage::updatedPropertyEditorQmlPathDirectoryIds,
UnorderedElementsAre(designer1DirectoryId)),
Field("SynchronizationPackage::directoryInfos",
&SynchronizationPackage::directoryInfos,
IsEmpty()),
Field("SynchronizationPackage::updatedDirectoryInfoDirectoryIds",
&SynchronizationPackage::updatedDirectoryInfoDirectoryIds,
UnorderedElementsAre(path1SourceContextId)))));
updater.update({.directories = directories});
}
TEST_F(ProjectStorageUpdater, dont_synchronize_empty_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});
EXPECT_CALL(projectStorageMock,
synchronize(
AllOf(Field("SynchronizationPackage::fileStatuses",
&SynchronizationPackage::fileStatuses,
IsSupersetOf({IsFileStatus(designer1SourceId, 1, 21)})),
Field("SynchronizationPackage::updatedFileStatusSourceIds",
&SynchronizationPackage::updatedFileStatusSourceIds,
IsSupersetOf({designer1SourceId, designer2SourceId})),
Field("SynchronizationPackage::propertyEditorQmlPaths",
&SynchronizationPackage::propertyEditorQmlPaths,
Each(Field("PropertyEditorQmlPath::directoryId",
&PropertyEditorQmlPath::directoryId,
designer1DirectoryId))),
Field("SynchronizationPackage::updatedPropertyEditorQmlPathDirectoryIds",
&SynchronizationPackage::updatedPropertyEditorQmlPathDirectoryIds,
UnorderedElementsAre(designer1DirectoryId)),
Field("SynchronizationPackage::directoryInfos",
&SynchronizationPackage::directoryInfos,
IsEmpty()),
Field("SynchronizationPackage::updatedDirectoryInfoDirectoryIds",
&SynchronizationPackage::updatedDirectoryInfoDirectoryIds,
UnorderedElementsAre(path1SourceContextId, path2SourceContextId)))));
updater.update({.directories = directories});
}
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});
setFilesRemoved({designer1SourceId});
EXPECT_CALL(projectStorageMock,
synchronize(
AllOf(Field("SynchronizationPackage::fileStatuses",
&SynchronizationPackage::fileStatuses,
IsEmpty()),
Field("SynchronizationPackage::updatedFileStatusSourceIds",
&SynchronizationPackage::updatedFileStatusSourceIds,
IsSupersetOf({designer1SourceId})),
Field("SynchronizationPackage::propertyEditorQmlPaths",
&SynchronizationPackage::propertyEditorQmlPaths,
IsEmpty()),
Field("SynchronizationPackage::updatedPropertyEditorQmlPathDirectoryIds",
&SynchronizationPackage::updatedPropertyEditorQmlPathDirectoryIds,
UnorderedElementsAre(designer1DirectoryId)),
Field("SynchronizationPackage::directoryInfos",
&SynchronizationPackage::directoryInfos,
IsEmpty()),
Field("SynchronizationPackage::updatedDirectoryInfoDirectoryIds",
&SynchronizationPackage::updatedDirectoryInfoDirectoryIds,
UnorderedElementsAre(path1SourceContextId)))));
updater.update({.directories = directories});
}
TEST_F(ProjectStorageUpdater,
synchronize_annotation_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);
SourceContextId designer1DirectoryId = sourcePathCache.sourceContextId("/path/one/designer");
SourceId propertyEditorSpecificSourceId = sourcePathCache.sourceId(
"/path/one/designer/FooSpecifics.qml");
SourceId propertyEditorSpecificDynamicSourceId = sourcePathCache.sourceId(
"/path/one/designer/HuoSpecificsDynamic.qml");
SourceId propertyEditorPaneSourceId = sourcePathCache.sourceId(
"/path/one/designer/CaoPane.qml");
SourceId designer1SourceId = SourceId::create(QmlDesigner::SourceNameId{}, designer1DirectoryId);
setFilesChanged({designer1SourceId});
setFilesDontChanged({path1SourceId, qmldir1SourceId});
auto barModuleId = storage.moduleId("Bar", ModuleKind::QmlLibrary);
setFileNames(u"/path/one/designer",
{"FooSpecifics.qml", "HuoSpecificsDynamic.qml", "CaoPane.qml"},
{"*Pane.qml", "*Specifics.qml", "*SpecificsDynamic.qml"});
EXPECT_CALL(projectStorageMock,
synchronize(
AllOf(Field("SynchronizationPackage::propertyEditorQmlPaths",
&SynchronizationPackage::propertyEditorQmlPaths,
IsSupersetOf({IsPropertyEditorQmlPath(barModuleId,
Eq("Foo"),
propertyEditorSpecificSourceId,
designer1DirectoryId),
IsPropertyEditorQmlPath(barModuleId,
Eq("Huo"),
propertyEditorSpecificDynamicSourceId,
designer1DirectoryId),
IsPropertyEditorQmlPath(barModuleId,
Eq("Cao"),
propertyEditorPaneSourceId,
designer1DirectoryId)})),
Field("SynchronizationPackage::updatedPropertyEditorQmlPathDirectoryIds",
&SynchronizationPackage::updatedPropertyEditorQmlPathDirectoryIds,
Contains(designer1DirectoryId)))));
updater.update({.directories = directories});
}
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);
SourceContextId designer1DirectoryId = sourcePathCache.sourceContextId("/path/one/designer");
SourceId propertyEditorSpecificSourceId = sourcePathCache.sourceId(
"/path/one/designer/FooSpecifics.qml");
SourceId propertyEditorSpecificDynamicSourceId = sourcePathCache.sourceId(
"/path/one/designer/HuoSpecificsDynamic.qml");
SourceId propertyEditorPaneSourceId = sourcePathCache.sourceId(
"/path/one/designer/CaoPane.qml");
SourceId designer1SourceId = SourceId::create(QmlDesigner::SourceNameId{}, designer1DirectoryId);
setFilesChanged({path1SourceId});
setFilesDontChanged({qmldir1SourceId, designer1SourceId});
auto barModuleId = storage.moduleId("Bar", ModuleKind::QmlLibrary);
setFileNames(u"/path/one/designer",
{"FooSpecifics.qml", "HuoSpecificsDynamic.qml", "CaoPane.qml"},
{"*Pane.qml", "*Specifics.qml", "*SpecificsDynamic.qml"});
EXPECT_CALL(projectStorageMock,
synchronize(
AllOf(Field("SynchronizationPackage::propertyEditorQmlPaths",
&SynchronizationPackage::propertyEditorQmlPaths,
IsSupersetOf({IsPropertyEditorQmlPath(barModuleId,
Eq("Foo"),
propertyEditorSpecificSourceId,
designer1DirectoryId),
IsPropertyEditorQmlPath(barModuleId,
Eq("Huo"),
propertyEditorSpecificDynamicSourceId,
designer1DirectoryId),
IsPropertyEditorQmlPath(barModuleId,
Eq("Cao"),
propertyEditorPaneSourceId,
designer1DirectoryId)})),
Field("SynchronizationPackage::updatedPropertyEditorQmlPathDirectoryIds",
&SynchronizationPackage::updatedPropertyEditorQmlPathDirectoryIds,
Contains(designer1DirectoryId)))));
updater.update({.directories = directories});
}
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);
SourceContextId designer1DirectoryId = sourcePathCache.sourceContextId("/path/one/designer");
SourceId propertyEditorSpecificSourceId = sourcePathCache.sourceId(
"/path/one/designer/FooSpecifics.qml");
SourceId propertyEditorSpecificDynamicSourceId = sourcePathCache.sourceId(
"/path/one/designer/HuoSpecificsDynamic.qml");
SourceId propertyEditorPaneSourceId = sourcePathCache.sourceId(
"/path/one/designer/CaoPane.qml");
SourceId designer1SourceId = SourceId::create(QmlDesigner::SourceNameId{}, designer1DirectoryId);
setFilesChanged({qmldir1SourceId});
setFilesDontChanged({path1SourceId, designer1SourceId});
auto barModuleId = storage.moduleId("Bar", ModuleKind::QmlLibrary);
setFileNames(u"/path/one/designer",
{"FooSpecifics.qml", "HuoSpecificsDynamic.qml", "CaoPane.qml"},
{"*Pane.qml", "*Specifics.qml", "*SpecificsDynamic.qml"});
EXPECT_CALL(projectStorageMock,
synchronize(
AllOf(Field("SynchronizationPackage::propertyEditorQmlPaths",
&SynchronizationPackage::propertyEditorQmlPaths,
IsSupersetOf({IsPropertyEditorQmlPath(barModuleId,
Eq("Foo"),
propertyEditorSpecificSourceId,
designer1DirectoryId),
IsPropertyEditorQmlPath(barModuleId,
Eq("Huo"),
propertyEditorSpecificDynamicSourceId,
designer1DirectoryId),
IsPropertyEditorQmlPath(barModuleId,
Eq("Cao"),
propertyEditorPaneSourceId,
designer1DirectoryId)})),
Field("SynchronizationPackage::updatedPropertyEditorQmlPathDirectoryIds",
&SynchronizationPackage::updatedPropertyEditorQmlPathDirectoryIds,
Contains(designer1DirectoryId)))));
updater.update({.directories = directories});
}
} // namespace } // namespace

View File

@@ -19,6 +19,7 @@ using testing::ByMove;
using testing::ByRef; using testing::ByRef;
using testing::ContainerEq; using testing::ContainerEq;
using testing::Contains; using testing::Contains;
using testing::Each;
using testing::ElementsAre; using testing::ElementsAre;
using testing::Eq; using testing::Eq;
using testing::Exactly; using testing::Exactly;