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)
{
return first.sourceId == second.sourceId && first.size == second.size
&& first.lastModified == second.lastModified && first.size >= 0
&& first.lastModified >= 0;
&& first.lastModified == second.lastModified;
}
friend bool operator!=(const FileStatus &first, const FileStatus &second)
@@ -46,9 +45,9 @@ public:
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>
friend void convertToString(String &string, const FileStatus &fileStatus)

View File

@@ -31,9 +31,9 @@ SourceIds FileSystem::directoryEntries(const QString &directoryPath) const
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

View File

@@ -25,7 +25,7 @@ public:
{}
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;
FileStatus fileStatus(SourceId sourceId) const override;
QString contentAsQString(const QString &filePath) const override;

View File

@@ -15,7 +15,7 @@ class FileSystemInterface
{
public:
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 FileStatus fileStatus(SourceId sourceId) const = 0;
virtual void remove(const SourceIds &sourceIds) = 0;

View File

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

View File

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

View File

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

View File

@@ -104,11 +104,7 @@ public:
const_iterator m_end;
};
enum class FileState {
NotChanged,
Changed,
NotExists,
};
enum class FileState { Unchanged, Changed, NotExists, NotExistsUnchanged, Added, Removed };
struct WatchedSourceIdsIds
{
@@ -157,15 +153,33 @@ private:
NotUpdatedSourceIds &notUpdatedSourceIds,
WatchedSourceIdsIds &watchedSourceIdsIds);
void updateDirectoryChanged(Utils::SmallStringView directoryPath,
Utils::SmallStringView annotationDirectoryPath,
FileState qmldirState,
FileState annotationDirectoryState,
SourcePath qmldirSourcePath,
SourceId qmldirSourceId,
SourceContextId directoryId,
SourceContextId annotationDirectoryId,
Storage::Synchronization::SynchronizationPackage &package,
NotUpdatedSourceIds &notUpdatedSourceIds,
WatchedSourceIdsIds &watchedSourceIdsIds,
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,
Storage::Synchronization::SynchronizationPackage &package,
NotUpdatedSourceIds &notUpdatedSourceIds);

View File

@@ -15,7 +15,10 @@ public:
directoryEntries,
(const QString &directoryPath),
(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(QmlDesigner::FileStatus, fileStatus, (QmlDesigner::SourceId sourceId), (const, 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
<< ", fileStatuses: " << package.fileStatuses
<< ", updatedFileStatusSourceIds: " << package.updatedFileStatusSourceIds
<< ", updatedDirectoryInfoDirectoryIds: " << package.updatedDirectoryInfoDirectoryIds
<< ", directoryInfos: " << package.directoryInfos
<< ", updatedDirectoryInfoDirectoryIds: " << package.updatedDirectoryInfoDirectoryIds
<< ", propertyEditorQmlPaths: " << package.propertyEditorQmlPaths
<< ", updatedPropertyEditorQmlPathSourceIds: "
<< package.updatedPropertyEditorQmlPathSourceContextIds
<< package.updatedPropertyEditorQmlPathDirectoryIds
<< ", typeAnnotations: " << package.typeAnnotations
<< ", 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)
{
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)

View File

@@ -1079,7 +1079,7 @@ protected:
"Item3D",
sourceId3,
sourceContextIdPath6);
package.updatedPropertyEditorQmlPathSourceContextIds.emplace_back(sourceContextIdPath6);
package.updatedPropertyEditorQmlPathDirectoryIds.emplace_back(sourceContextIdPath6);
return package;
}
@@ -5774,6 +5774,13 @@ TEST_F(ProjectStorage, get_module_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)
{
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.moduleExportedImports.empty() && package.updatedModuleIds.empty()
&& package.propertyEditorQmlPaths.empty()
&& package.updatedPropertyEditorQmlPathSourceContextIds.empty()
&& package.updatedPropertyEditorQmlPathDirectoryIds.empty()
&& package.typeAnnotations.empty() && package.updatedTypeAnnotationSourceIds.empty();
}
@@ -188,6 +188,11 @@ public:
qmltypes1SourceId,
qmltypes2SourceId,
itemLibraryPathSourceId});
setFilesDontExistsUnchanged({createDirectorySourceId("/path/designer"),
createDirectorySourceId("/root/designer"),
createDirectorySourceId("/path/one/designer"),
createDirectorySourceId("/path/two/designer"),
createDirectorySourceId("/path/three/designer")});
setFilesAdded({qmldir1SourceId, qmldir2SourceId, qmldir3SourceId});
@@ -279,7 +284,8 @@ public:
void setFilesRemoved(const QmlDesigner::SourceIds &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)))
.WillByDefault(Return(FileStatus{sourceId, 1, 21}));
}
@@ -288,15 +294,34 @@ public:
void setFilesDontExists(const QmlDesigner::SourceIds &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)))
.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)
{
ON_CALL(fileSystemMock, qmlFileNames(Eq(directoryPath))).WillByDefault(Return(qmlFileNames));
setFileNames(directoryPath, qmlFileNames, {"*.qml"});
}
void setDirectoryInfos(SourceContextId directorySourceId, const DirectoryInfos &directoryInfos)
@@ -376,6 +401,7 @@ protected:
SourceId qmlDirPathSourceId = sourcePathCache.sourceId("/path/qmldir");
SourceContextId directoryPathId = qmlDirPathSourceId.contextId();
SourceId directoryPathSourceId = SourceId::create(QmlDesigner::SourceNameId{}, directoryPathId);
SourceId annotationDirectorySourceId = createDirectorySourceId("/path/designer");
SourceId qmlDocumentSourceId1 = sourcePathCache.sourceId("/path/First.qml");
SourceId qmlDocumentSourceId2 = sourcePathCache.sourceId("/path/First2.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)))))),
Field("SynchronizationPackage::updatedSourceIds",
&SynchronizationPackage::updatedSourceIds,
UnorderedElementsAre(qmlDirPathSourceId,
qmlDocumentSourceId1,
qmlDocumentSourceId2,
qmlDocumentSourceId3)),
UnorderedElementsAre(qmlDocumentSourceId1, qmlDocumentSourceId2, qmlDocumentSourceId3)),
Field("SynchronizationPackage::updatedFileStatusSourceIds",
&SynchronizationPackage::updatedFileStatusSourceIds,
UnorderedElementsAre(directoryPathSourceId,
@@ -2291,6 +2314,7 @@ TEST_F(ProjectStorageUpdater, synchronize_qml_documents_without_qmldir)
Field("SynchronizationPackage::fileStatuses",
&SynchronizationPackage::fileStatuses,
UnorderedElementsAre(IsFileStatus(directoryPathSourceId, 1, 21),
IsFileStatus(qmlDirPathSourceId, -1, -1),
IsFileStatus(qmlDocumentSourceId1, 1, 21),
IsFileStatus(qmlDocumentSourceId2, 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)
{
setFilesDontExists({qmlDocumentSourceId1});
setFilesAdded({directoryPathSourceId});
setFilesAdded({directoryPathSourceId, qmlDirPathSourceId, qmlDocumentSourceId2});
QString qmldir{R"(module Example
FirstType 1.0 First.qml
FirstType 2.2 First2.qml)"};
@@ -2379,6 +2403,7 @@ TEST_F(ProjectStorageUpdater,
&SynchronizationPackage::fileStatuses,
UnorderedElementsAre(IsFileStatus(directoryPathSourceId, 1, 21),
IsFileStatus(qmlDirPathSourceId, 1, 21),
IsFileStatus(qmlDocumentSourceId1, -1, -1),
IsFileStatus(qmlDocumentSourceId2, 1, 21))),
Field("SynchronizationPackage::updatedDirectoryInfoDirectoryIds",
&SynchronizationPackage::updatedDirectoryInfoDirectoryIds,
@@ -2397,9 +2422,14 @@ TEST_F(ProjectStorageUpdater,
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,
{{directoryPathId, qmlDocumentSourceId1, 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",
&SynchronizationPackage::updatedFileStatusSourceIds,
UnorderedElementsAre(directoryPathSourceId,
annotationDirectorySourceId,
qmlDirPathSourceId,
qmlDocumentSourceId1,
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)
{
setFilesDontExists({qmlDirPathSourceId});
setFilesDontExistsUnchanged({qmlDirPathSourceId});
setFilesChanged({directoryPathSourceId});
setFilesAdded({qmlDocumentSourceId3});
setFilesDontChanged({qmlDocumentSourceId1, qmlDocumentSourceId2});
@@ -2446,29 +2477,29 @@ TEST_F(ProjectStorageUpdater, synchronize_qml_documents_without_qmldir_add_qml_d
{{directoryPathId, qmlDocumentSourceId1, ModuleId{}, FileType::QmlDocument},
{directoryPathId, qmlDocumentSourceId2, ModuleId{}, FileType::QmlDocument}});
EXPECT_CALL(
projectStorageMock,
synchronize(AllOf(
Field("SynchronizationPackage::imports",
EXPECT_CALL(projectStorageMock,
synchronize(
AllOf(Field("SynchronizationPackage::imports",
&SynchronizationPackage::imports,
UnorderedElementsAre(import3)),
Field("SynchronizationPackage::types",
&SynchronizationPackage::types,
UnorderedElementsAre(AllOf(
IsStorageType("Second.qml",
UnorderedElementsAre(
AllOf(IsStorageType("Second.qml",
ImportedType{"Object3"},
TypeTraitsKind::Reference,
qmlDocumentSourceId3,
ChangeLevel::Full),
Field("Type::exportedTypes",
&Type::exportedTypes,
UnorderedElementsAre(IsExportedType(pathModuleId, "Second", -1, -1)))))),
UnorderedElementsAre(
IsExportedType(pathModuleId, "Second", -1, -1)))))),
Field("SynchronizationPackage::updatedSourceIds",
&SynchronizationPackage::updatedSourceIds,
UnorderedElementsAre(qmlDirPathSourceId, qmlDocumentSourceId3)),
UnorderedElementsAre(qmlDocumentSourceId3)),
Field("SynchronizationPackage::updatedFileStatusSourceIds",
&SynchronizationPackage::updatedFileStatusSourceIds,
UnorderedElementsAre(directoryPathSourceId, qmlDirPathSourceId, qmlDocumentSourceId3)),
UnorderedElementsAre(directoryPathSourceId, qmlDocumentSourceId3)),
Field("SynchronizationPackage::fileStatuses",
&SynchronizationPackage::fileStatuses,
UnorderedElementsAre(IsFileStatus(directoryPathSourceId, 1, 21),
@@ -2478,11 +2509,18 @@ TEST_F(ProjectStorageUpdater, synchronize_qml_documents_without_qmldir_add_qml_d
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))))));
UnorderedElementsAre(IsDirectoryInfo(directoryPathId,
qmlDocumentSourceId1,
ModuleId{},
FileType::QmlDocument),
IsDirectoryInfo(directoryPathId,
qmlDocumentSourceId2,
ModuleId{},
FileType::QmlDocument),
IsDirectoryInfo(directoryPathId,
qmlDocumentSourceId3,
ModuleId{},
FileType::QmlDocument))))));
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::updatedSourceIds",
&SynchronizationPackage::updatedSourceIds,
UnorderedElementsAre(qmlDirPathSourceId, qmlDocumentSourceId3)),
UnorderedElementsAre(qmlDocumentSourceId3)),
Field("SynchronizationPackage::updatedFileStatusSourceIds",
&SynchronizationPackage::updatedFileStatusSourceIds,
UnorderedElementsAre(directoryPathSourceId, qmlDirPathSourceId, qmlDocumentSourceId3)),
Field("SynchronizationPackage::fileStatuses",
&SynchronizationPackage::fileStatuses,
UnorderedElementsAre(IsFileStatus(directoryPathSourceId, 1, 21))),
UnorderedElementsAre(IsFileStatus(directoryPathSourceId, 1, 21),
IsFileStatus(qmlDirPathSourceId, -1, -1))),
Field("SynchronizationPackage::updatedDirectoryInfoDirectoryIds",
&SynchronizationPackage::updatedDirectoryInfoDirectoryIds,
UnorderedElementsAre(directoryPathId)),
@@ -2672,7 +2711,9 @@ TEST_F(ProjectStorageUpdater, watcher_updates_subdirectories)
TEST_F(ProjectStorageUpdater, watcher_updates_removed_directory)
{
auto annotationDirectorySourceId = createDirectorySourceId("/path/designer");
setFilesRemoved({directoryPathSourceId,
annotationDirectorySourceId,
qmlDirPathSourceId,
qmlDocumentSourceId1,
qmlDocumentSourceId2,
@@ -2696,13 +2737,14 @@ TEST_F(ProjectStorageUpdater, watcher_updates_removed_directory)
Field("SynchronizationPackage::updatedFileStatusSourceIds",
&SynchronizationPackage::updatedFileStatusSourceIds,
UnorderedElementsAre(directoryPathSourceId,
annotationDirectorySourceId,
qmlDirPathSourceId,
qmlDocumentSourceId1,
qmlDocumentSourceId2,
qmlDocumentSourceId3)),
Field("SynchronizationPackage::fileStatuses",
&SynchronizationPackage::fileStatuses,
UnorderedElementsAre()),
IsEmpty()),
Field("SynchronizationPackage::updatedDirectoryInfoDirectoryIds",
&SynchronizationPackage::updatedDirectoryInfoDirectoryIds,
UnorderedElementsAre(directoryPathId)),
@@ -3439,7 +3481,9 @@ TEST_F(ProjectStorageUpdater, watcher_updates_qml_documents)
TEST_F(ProjectStorageUpdater, watcher_updates_removed_qml_documents)
{
setFilesDontExistsUnchanged({annotationDirectorySourceId, qmlDirPathSourceId});
setFilesRemoved({qmlDocumentSourceId2});
setFilesChanged({qmlDocumentSourceId1});
EXPECT_CALL(projectStorageMock,
synchronize(
@@ -3450,11 +3494,13 @@ TEST_F(ProjectStorageUpdater, watcher_updates_removed_qml_documents)
&SynchronizationPackage::types,
UnorderedElementsAre(AllOf(
IsStorageType("First.qml",
ImportedType{"Object"},
Storage::Synchronization::ImportedType{"Object"},
TypeTraitsKind::Reference,
qmlDocumentSourceId1,
ChangeLevel::ExcludeExportedTypes),
Field("Type::exportedTypes", &Type::exportedTypes, IsEmpty())))),
Storage::Synchronization::ChangeLevel::ExcludeExportedTypes),
Field("exportedTypes",
&Storage::Synchronization::Type::exportedTypes,
IsEmpty())))),
Field("SynchronizationPackage::updatedSourceIds",
&SynchronizationPackage::updatedSourceIds,
UnorderedElementsAre(qmlDocumentSourceId1, qmlDocumentSourceId2)),
@@ -4162,10 +4208,9 @@ TEST_F(ProjectStorageUpdater, update_property_editor_panes)
setFilesChanged({directorySourceId});
auto qmlModuleId = storage.moduleId("QML", ModuleKind::QmlLibrary);
EXPECT_CALL(
projectStorageMock,
synchronize(AllOf(
Field("SynchronizationPackage::fileStatuses",
EXPECT_CALL(projectStorageMock,
synchronize(
AllOf(Field("SynchronizationPackage::fileStatuses",
&SynchronizationPackage::fileStatuses,
UnorderedElementsAre(IsFileStatus(directorySourceId, 1, 21))),
Field("SynchronizationPackage::updatedFileStatusSourceIds",
@@ -4173,9 +4218,10 @@ TEST_F(ProjectStorageUpdater, update_property_editor_panes)
UnorderedElementsAre(directorySourceId)),
Field("SynchronizationPackage::propertyEditorQmlPaths",
&SynchronizationPackage::propertyEditorQmlPaths,
Contains(IsPropertyEditorQmlPath(qmlModuleId, "QtObject", sourceId, directoryId))),
Field("SynchronizationPackage::updatedPropertyEditorQmlPathSourceContextIds",
&SynchronizationPackage::updatedPropertyEditorQmlPathSourceContextIds,
Contains(IsPropertyEditorQmlPath(
qmlModuleId, "QtObject", sourceId, directoryId))),
Field("SynchronizationPackage::updatedPropertyEditorQmlPathDirectoryIds",
&SynchronizationPackage::updatedPropertyEditorQmlPathDirectoryIds,
ElementsAre(directoryId)))));
updater.update({.propertyEditorResourcesPath = propertyEditorQmlPath});
@@ -4213,8 +4259,8 @@ TEST_F(ProjectStorageUpdater, update_property_editor_specifics)
{IsPropertyEditorQmlPath(qtQuickModuleId, "Text", textSourceId, qtQuickDirectoryId),
IsPropertyEditorQmlPath(
controlsModuleId, "Button", buttonSourceId, controlsDirectoryId)})),
Field("SynchronizationPackage::updatedPropertyEditorQmlPathSourceContextIds",
&SynchronizationPackage::updatedPropertyEditorQmlPathSourceContextIds,
Field("SynchronizationPackage::updatedPropertyEditorQmlPathDirectoryIds",
&SynchronizationPackage::updatedPropertyEditorQmlPathDirectoryIds,
ElementsAre(qtQuickDirectoryId, controlsDirectoryId)))));
updater.update({.propertyEditorResourcesPath = propertyEditorQmlPath});
@@ -4373,4 +4419,242 @@ TEST_F(ProjectStorageUpdater, update_type_annotations_removed_directory)
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

View File

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