QmlDesigner: Parse components recursively

Change-Id: I8fa892cce8e34b5e58cbdde04c57e30b9fc74866
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
Reviewed-by: Qt CI Patch Build Bot <ci_patchbuild_bot@qt.io>
This commit is contained in:
Marco Bubke
2024-05-06 17:02:32 +02:00
parent fd2c7db691
commit f296f9d77c
19 changed files with 566 additions and 125 deletions

View File

@@ -318,4 +318,13 @@ Component {
Component { Component {
name: "QScxmlError" name: "QScxmlError"
} }
Component {
name: "QList<QQuickLayoutItemProxy*>"
}
Component {
name: "VertexColorMaskFlags"
}
} }

View File

@@ -48,6 +48,8 @@ using EnumerationDeclarationIds = std::vector<EnumerationDeclarationId>;
using SourceContextId = Sqlite::BasicId<BasicIdType::SourceContext, int>; using SourceContextId = Sqlite::BasicId<BasicIdType::SourceContext, int>;
using SourceContextIds = std::vector<SourceContextId>; using SourceContextIds = std::vector<SourceContextId>;
template<std::size_t size>
using SmallSourceContextIds = QVarLengthArray<SourceContextId, size>;
using SourceId = Sqlite::BasicId<BasicIdType::Source, int>; using SourceId = Sqlite::BasicId<BasicIdType::Source, int>;
using SourceIds = std::vector<SourceId>; using SourceIds = std::vector<SourceId>;

View File

@@ -11,6 +11,7 @@
#include <QDateTime> #include <QDateTime>
#include <QDir> #include <QDir>
#include <QDirIterator>
#include <QFileInfo> #include <QFileInfo>
namespace QmlDesigner { namespace QmlDesigner {
@@ -69,6 +70,18 @@ QString FileSystem::contentAsQString(const QString &filePath) const
return {}; return {};
} }
QStringList FileSystem::subdirectories(const QString &directoryPath) const
{
QStringList directoryPaths;
directoryPaths.reserve(100);
QDirIterator directoryIterator{directoryPath, QDir::Dirs | QDir::NoDotAndDotDot};
while (directoryIterator.hasNext())
directoryPaths.push_back(directoryIterator.next());
return directoryPaths;
}
void FileSystem::remove(const SourceIds &sourceIds) void FileSystem::remove(const SourceIds &sourceIds)
{ {
for (SourceId sourceId : sourceIds) for (SourceId sourceId : sourceIds)

View File

@@ -31,6 +31,7 @@ public:
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;
QStringList subdirectories(const QString &directoryPath) const override;
void remove(const SourceIds &sourceIds) override; void remove(const SourceIds &sourceIds) override;

View File

@@ -20,6 +20,7 @@ public:
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;
virtual QString contentAsQString(const QString &filePath) const = 0; virtual QString contentAsQString(const QString &filePath) const = 0;
virtual QStringList subdirectories(const QString &directoryPath) const = 0;
protected: protected:
~FileSystemInterface() = default; ~FileSystemInterface() = default;

View File

@@ -519,6 +519,12 @@ struct ProjectStorage::Statements
"SELECT directorySourceId, sourceId, moduleId, fileType FROM directoryInfos WHERE " "SELECT directorySourceId, sourceId, moduleId, fileType FROM directoryInfos WHERE "
"directorySourceId=?1", "directorySourceId=?1",
database}; database};
mutable Sqlite::ReadStatement<4, 2> selectDirectoryInfosForSourceIdAndFileTypeStatement{
"SELECT directorySourceId, sourceId, moduleId, fileType FROM directoryInfos WHERE "
"directorySourceId=?1 AND fileType=?2",
database};
mutable Sqlite::ReadStatement<1, 2> selectDirectoryInfosSourceIdsForSourceIdAndFileTypeStatement{
"SELECT sourceId FROM directoryInfos WHERE directorySourceId=?1 AND fileType=?2", database};
mutable Sqlite::ReadStatement<4, 1> selectDirectoryInfoForSourceIdStatement{ mutable Sqlite::ReadStatement<4, 1> selectDirectoryInfoForSourceIdStatement{
"SELECT directorySourceId, sourceId, moduleId, fileType FROM directoryInfos WHERE " "SELECT directorySourceId, sourceId, moduleId, fileType FROM directoryInfos WHERE "
"sourceId=?1 LIMIT 1", "sourceId=?1 LIMIT 1",
@@ -1073,10 +1079,11 @@ public:
Sqlite::StrictColumnType::Integer); Sqlite::StrictColumnType::Integer);
auto &sourceIdColumn = table.addColumn("sourceId", Sqlite::StrictColumnType::Integer); auto &sourceIdColumn = table.addColumn("sourceId", Sqlite::StrictColumnType::Integer);
table.addColumn("moduleId", Sqlite::StrictColumnType::Integer); table.addColumn("moduleId", Sqlite::StrictColumnType::Integer);
table.addColumn("fileType", Sqlite::StrictColumnType::Integer); auto &fileTypeColumn = table.addColumn("fileType", Sqlite::StrictColumnType::Integer);
table.addPrimaryKeyContraint({directorySourceIdColumn, sourceIdColumn}); table.addPrimaryKeyContraint({directorySourceIdColumn, sourceIdColumn});
table.addUniqueIndex({sourceIdColumn}); table.addUniqueIndex({sourceIdColumn});
table.addIndex({directorySourceIdColumn, fileTypeColumn});
table.initialize(database); table.initialize(database);
} }
@@ -1196,7 +1203,7 @@ void ProjectStorage::synchronize(Storage::Synchronization::SynchronizationPackag
linkAliases(insertedAliasPropertyDeclarations, updatedAliasPropertyDeclarations); linkAliases(insertedAliasPropertyDeclarations, updatedAliasPropertyDeclarations);
synchronizeDirectoryInfos(package.directoryInfos, package.updatedProjectSourceIds); synchronizeDirectoryInfos(package.directoryInfos, package.updatedDirectoryInfoSourceIds);
commonTypeCache_.resetTypeIds(); commonTypeCache_.resetTypeIds();
}); });
@@ -2116,7 +2123,7 @@ FileStatus ProjectStorage::fetchFileStatus(SourceId sourceId) const
std::optional<Storage::Synchronization::DirectoryInfo> ProjectStorage::fetchDirectoryInfo(SourceId sourceId) const std::optional<Storage::Synchronization::DirectoryInfo> ProjectStorage::fetchDirectoryInfo(SourceId sourceId) const
{ {
using NanotraceHR::keyValue; using NanotraceHR::keyValue;
NanotraceHR::Tracer tracer{"fetch project data"_t, NanotraceHR::Tracer tracer{"fetch directory info"_t,
projectStorageCategory(), projectStorageCategory(),
keyValue("source id", sourceId)}; keyValue("source id", sourceId)};
@@ -2124,7 +2131,7 @@ std::optional<Storage::Synchronization::DirectoryInfo> ProjectStorage::fetchDire
.optionalValueWithTransaction<Storage::Synchronization::DirectoryInfo>( .optionalValueWithTransaction<Storage::Synchronization::DirectoryInfo>(
sourceId); sourceId);
tracer.end(keyValue("project data", directoryInfo)); tracer.end(keyValue("directory info", directoryInfo));
return directoryInfo; return directoryInfo;
} }
@@ -2132,7 +2139,7 @@ std::optional<Storage::Synchronization::DirectoryInfo> ProjectStorage::fetchDire
Storage::Synchronization::DirectoryInfos ProjectStorage::fetchDirectoryInfos(SourceId directorySourceId) const Storage::Synchronization::DirectoryInfos ProjectStorage::fetchDirectoryInfos(SourceId directorySourceId) const
{ {
using NanotraceHR::keyValue; using NanotraceHR::keyValue;
NanotraceHR::Tracer tracer{"fetch project datas by source id"_t, NanotraceHR::Tracer tracer{"fetch directory infos by source id"_t,
projectStorageCategory(), projectStorageCategory(),
keyValue("source id", directorySourceId)}; keyValue("source id", directorySourceId)};
@@ -2140,7 +2147,25 @@ Storage::Synchronization::DirectoryInfos ProjectStorage::fetchDirectoryInfos(Sou
.valuesWithTransaction<Storage::Synchronization::DirectoryInfo, 1024>( .valuesWithTransaction<Storage::Synchronization::DirectoryInfo, 1024>(
directorySourceId); directorySourceId);
tracer.end(keyValue("project datas", directoryInfos)); tracer.end(keyValue("directory infos", directoryInfos));
return directoryInfos;
}
Storage::Synchronization::DirectoryInfos ProjectStorage::fetchDirectoryInfos(
SourceId directorySourceId, Storage::Synchronization::FileType fileType) const
{
using NanotraceHR::keyValue;
NanotraceHR::Tracer tracer{"fetch directory infos by source id and file type"_t,
projectStorageCategory(),
keyValue("source id", directorySourceId),
keyValue("file type", fileType)};
auto directoryInfos = s->selectDirectoryInfosForSourceIdAndFileTypeStatement
.valuesWithTransaction<Storage::Synchronization::DirectoryInfo, 16>(
directorySourceId, fileType);
tracer.end(keyValue("directory infos", directoryInfos));
return directoryInfos; return directoryInfos;
} }
@@ -2149,7 +2174,7 @@ Storage::Synchronization::DirectoryInfos ProjectStorage::fetchDirectoryInfos(
const SourceIds &directorySourceIds) const const SourceIds &directorySourceIds) const
{ {
using NanotraceHR::keyValue; using NanotraceHR::keyValue;
NanotraceHR::Tracer tracer{"fetch project datas by source ids"_t, NanotraceHR::Tracer tracer{"fetch directory infos by source ids"_t,
projectStorageCategory(), projectStorageCategory(),
keyValue("source ids", directorySourceIds)}; keyValue("source ids", directorySourceIds)};
@@ -2157,11 +2182,27 @@ Storage::Synchronization::DirectoryInfos ProjectStorage::fetchDirectoryInfos(
.valuesWithTransaction<Storage::Synchronization::DirectoryInfo, 64>( .valuesWithTransaction<Storage::Synchronization::DirectoryInfo, 64>(
toIntegers(directorySourceIds)); toIntegers(directorySourceIds));
tracer.end(keyValue("project datas", directoryInfos)); tracer.end(keyValue("directory infos", directoryInfos));
return directoryInfos; return directoryInfos;
} }
SmallSourceIds<32> ProjectStorage::fetchSubdirectorySourceIds(SourceId directorySourceId) const
{
using NanotraceHR::keyValue;
NanotraceHR::Tracer tracer{"fetch subdirectory source ids"_t,
projectStorageCategory(),
keyValue("source id", directorySourceId)};
auto sourceIds = s->selectDirectoryInfosSourceIdsForSourceIdAndFileTypeStatement
.valuesWithTransaction<SmallSourceIds<32>>(
directorySourceId, Storage::Synchronization::FileType::Directory);
tracer.end(keyValue("source ids", sourceIds));
return sourceIds;
}
void ProjectStorage::setPropertyEditorPathId(TypeId typeId, SourceId pathId) void ProjectStorage::setPropertyEditorPathId(TypeId typeId, SourceId pathId)
{ {
Sqlite::ImmediateSessionTransaction transaction{database}; Sqlite::ImmediateSessionTransaction transaction{database};
@@ -2466,9 +2507,9 @@ void ProjectStorage::synchronizeTypes(Storage::Synchronization::Types &types,
} }
void ProjectStorage::synchronizeDirectoryInfos(Storage::Synchronization::DirectoryInfos &directoryInfos, void ProjectStorage::synchronizeDirectoryInfos(Storage::Synchronization::DirectoryInfos &directoryInfos,
const SourceIds &updatedProjectSourceIds) const SourceIds &updatedDirectoryInfoSourceIds)
{ {
NanotraceHR::Tracer tracer{"synchronize project datas"_t, projectStorageCategory()}; NanotraceHR::Tracer tracer{"synchronize directory infos"_t, projectStorageCategory()};
auto compareKey = [](auto &&first, auto &&second) { auto compareKey = [](auto &&first, auto &&second) {
auto directorySourceIdDifference = first.directorySourceId - second.directorySourceId; auto directorySourceIdDifference = first.directorySourceId - second.directorySourceId;
@@ -2484,13 +2525,13 @@ void ProjectStorage::synchronizeDirectoryInfos(Storage::Synchronization::Directo
}); });
auto range = s->selectDirectoryInfosForSourceIdsStatement.range<Storage::Synchronization::DirectoryInfo>( auto range = s->selectDirectoryInfosForSourceIdsStatement.range<Storage::Synchronization::DirectoryInfo>(
toIntegers(updatedProjectSourceIds)); toIntegers(updatedDirectoryInfoSourceIds));
auto insert = [&](const Storage::Synchronization::DirectoryInfo &directoryInfo) { auto insert = [&](const Storage::Synchronization::DirectoryInfo &directoryInfo) {
using NanotraceHR::keyValue; using NanotraceHR::keyValue;
NanotraceHR::Tracer tracer{"insert project data"_t, NanotraceHR::Tracer tracer{"insert directory info"_t,
projectStorageCategory(), projectStorageCategory(),
keyValue("project data", directoryInfo)}; keyValue("directory info", directoryInfo)};
if (!directoryInfo.directorySourceId) if (!directoryInfo.directorySourceId)
throw DirectoryInfoHasInvalidProjectSourceId{}; throw DirectoryInfoHasInvalidProjectSourceId{};
@@ -2508,10 +2549,11 @@ void ProjectStorage::synchronizeDirectoryInfos(Storage::Synchronization::Directo
if (directoryInfoFromDatabase.fileType != directoryInfo.fileType if (directoryInfoFromDatabase.fileType != directoryInfo.fileType
|| !compareInvalidAreTrue(directoryInfoFromDatabase.moduleId, directoryInfo.moduleId)) { || !compareInvalidAreTrue(directoryInfoFromDatabase.moduleId, directoryInfo.moduleId)) {
using NanotraceHR::keyValue; using NanotraceHR::keyValue;
NanotraceHR::Tracer tracer{"update project data"_t, NanotraceHR::Tracer tracer{"update directory info"_t,
projectStorageCategory(), projectStorageCategory(),
keyValue("project data", directoryInfo), keyValue("directory info", directoryInfo),
keyValue("project data from database", directoryInfoFromDatabase)}; keyValue("directory info from database",
directoryInfoFromDatabase)};
s->updateDirectoryInfoStatement.write(directoryInfo.directorySourceId, s->updateDirectoryInfoStatement.write(directoryInfo.directorySourceId,
directoryInfo.sourceId, directoryInfo.sourceId,
@@ -2525,9 +2567,9 @@ void ProjectStorage::synchronizeDirectoryInfos(Storage::Synchronization::Directo
auto remove = [&](const Storage::Synchronization::DirectoryInfo &directoryInfo) { auto remove = [&](const Storage::Synchronization::DirectoryInfo &directoryInfo) {
using NanotraceHR::keyValue; using NanotraceHR::keyValue;
NanotraceHR::Tracer tracer{"remove project data"_t, NanotraceHR::Tracer tracer{"remove directory info"_t,
projectStorageCategory(), projectStorageCategory(),
keyValue("project data", directoryInfo)}; keyValue("directory info", directoryInfo)};
s->deleteDirectoryInfoStatement.write(directoryInfo.directorySourceId, directoryInfo.sourceId); s->deleteDirectoryInfoStatement.write(directoryInfo.directorySourceId, directoryInfo.sourceId);
}; };

View File

@@ -232,8 +232,10 @@ public:
std::optional<Storage::Synchronization::DirectoryInfo> fetchDirectoryInfo(SourceId sourceId) const override; std::optional<Storage::Synchronization::DirectoryInfo> fetchDirectoryInfo(SourceId sourceId) const override;
Storage::Synchronization::DirectoryInfos fetchDirectoryInfos(SourceId directorySourceId) const override; Storage::Synchronization::DirectoryInfos fetchDirectoryInfos(SourceId directorySourceId) const override;
Storage::Synchronization::DirectoryInfos fetchDirectoryInfos(
SourceId directorySourceId, Storage::Synchronization::FileType fileType) const override;
Storage::Synchronization::DirectoryInfos fetchDirectoryInfos(const SourceIds &directorySourceIds) const; Storage::Synchronization::DirectoryInfos fetchDirectoryInfos(const SourceIds &directorySourceIds) const;
SmallSourceIds<32> fetchSubdirectorySourceIds(SourceId directorySourceId) const override;
void setPropertyEditorPathId(TypeId typeId, SourceId pathId); void setPropertyEditorPathId(TypeId typeId, SourceId pathId);
@@ -561,7 +563,7 @@ private:
const SourceIds &updatedSourceIds); const SourceIds &updatedSourceIds);
void synchronizeDirectoryInfos(Storage::Synchronization::DirectoryInfos &directoryInfos, void synchronizeDirectoryInfos(Storage::Synchronization::DirectoryInfos &directoryInfos,
const SourceIds &updatedProjectSourceIds); const SourceIds &updatedDirectoryInfoSourceIds);
void synchronizeFileStatuses(FileStatuses &fileStatuses, const SourceIds &updatedSourceIds); void synchronizeFileStatuses(FileStatuses &fileStatuses, const SourceIds &updatedSourceIds);

View File

@@ -8,6 +8,8 @@
#include <sqlite/sqlitevalue.h> #include <sqlite/sqlitevalue.h>
#include <utils/smallstring.h> #include <utils/smallstring.h>
#include <QVarLengthArray>
#include <array> #include <array>
#include <tuple> #include <tuple>
#include <variant> #include <variant>
@@ -15,6 +17,9 @@
namespace QmlDesigner { namespace QmlDesigner {
template<std::size_t size>
using SmallPathStrings = QVarLengthArray<Utils::PathString, size>;
template<typename Enumeration> template<typename Enumeration>
constexpr std::underlying_type_t<Enumeration> to_underlying(Enumeration enumeration) noexcept constexpr std::underlying_type_t<Enumeration> to_underlying(Enumeration enumeration) noexcept
{ {

View File

@@ -81,7 +81,11 @@ public:
virtual FileStatus fetchFileStatus(SourceId sourceId) const = 0; virtual FileStatus fetchFileStatus(SourceId sourceId) const = 0;
virtual Storage::Synchronization::DirectoryInfos fetchDirectoryInfos(SourceId sourceId) const = 0; virtual Storage::Synchronization::DirectoryInfos fetchDirectoryInfos(SourceId sourceId) const = 0;
virtual Storage::Synchronization::DirectoryInfos fetchDirectoryInfos(
SourceId directorySourceId, Storage::Synchronization::FileType) const
= 0;
virtual std::optional<Storage::Synchronization::DirectoryInfo> fetchDirectoryInfo(SourceId sourceId) const = 0; virtual std::optional<Storage::Synchronization::DirectoryInfo> fetchDirectoryInfo(SourceId sourceId) const = 0;
virtual SmallSourceIds<32> fetchSubdirectorySourceIds(SourceId directorySourceId) const = 0;
virtual SourceId propertyEditorPathId(TypeId typeId) const = 0; virtual SourceId propertyEditorPathId(TypeId typeId) const = 0;
virtual const Storage::Info::CommonTypeCache<ProjectStorageType> &commonTypeCache() const = 0; virtual const Storage::Info::CommonTypeCache<ProjectStorageType> &commonTypeCache() const = 0;

View File

@@ -82,7 +82,7 @@ void convertToString(String &string, const TypeNameKind &kind)
} }
} }
enum class FileType : char { QmlTypes, QmlDocument }; enum class FileType : char { QmlTypes, QmlDocument, Directory };
template<typename String> template<typename String>
void convertToString(String &string, const FileType &type) void convertToString(String &string, const FileType &type)
@@ -94,6 +94,9 @@ void convertToString(String &string, const FileType &type)
case FileType::QmlDocument: case FileType::QmlDocument:
convertToString(string, "QmlDocument"); convertToString(string, "QmlDocument");
break; break;
case FileType::Directory:
convertToString(string, "Directory");
break;
} }
} }
@@ -1291,9 +1294,9 @@ public:
, fileStatuses(std::move(fileStatuses)) , fileStatuses(std::move(fileStatuses))
{} {}
SynchronizationPackage(SourceIds updatedProjectSourceIds, DirectoryInfos directoryInfos) SynchronizationPackage(SourceIds updatedDirectoryInfoSourceIds, DirectoryInfos directoryInfos)
: directoryInfos(std::move(directoryInfos)) : directoryInfos(std::move(directoryInfos))
, updatedProjectSourceIds(std::move(updatedProjectSourceIds)) , updatedDirectoryInfoSourceIds(std::move(updatedDirectoryInfoSourceIds))
{} {}
public: public:
@@ -1303,7 +1306,7 @@ public:
SourceIds updatedFileStatusSourceIds; SourceIds updatedFileStatusSourceIds;
FileStatuses fileStatuses; FileStatuses fileStatuses;
DirectoryInfos directoryInfos; DirectoryInfos directoryInfos;
SourceIds updatedProjectSourceIds; SourceIds updatedDirectoryInfoSourceIds;
Imports moduleDependencies; Imports moduleDependencies;
SourceIds updatedModuleDependencySourceIds; SourceIds updatedModuleDependencySourceIds;
ModuleExportedImports moduleExportedImports; ModuleExportedImports moduleExportedImports;

View File

@@ -13,9 +13,9 @@
#include "sourcepathcache.h" #include "sourcepathcache.h"
#include "typeannotationreader.h" #include "typeannotationreader.h"
#include <tracing/qmldesignertracing.h>
#include <sqlitedatabase.h> #include <sqlitedatabase.h>
#include <tracing/qmldesignertracing.h>
#include <utils/set_algorithm.h>
#include <QDirIterator> #include <QDirIterator>
#include <QRegularExpression> #include <QRegularExpression>
@@ -102,6 +102,8 @@ ProjectStorageUpdater::Components createComponents(
} }
for (const QmlDirParser::Component &qmlDirParserComponent : qmlDirParserComponents) { for (const QmlDirParser::Component &qmlDirParserComponent : qmlDirParserComponents) {
if (qmlDirParserComponent.fileName.contains('/'))
continue;
components.push_back(ProjectStorageUpdater::Component{qmlDirParserComponent.fileName, components.push_back(ProjectStorageUpdater::Component{qmlDirParserComponent.fileName,
qmlDirParserComponent.typeName, qmlDirParserComponent.typeName,
moduleId, moduleId,
@@ -285,6 +287,8 @@ void ProjectStorageUpdater::update(QStringList directories,
try { try {
m_projectStorage.synchronize(std::move(package)); m_projectStorage.synchronize(std::move(package));
} catch (const TypeNameDoesNotExists &exception) {
qDebug() << "missing type: " << exception.what();
} catch (...) { } catch (...) {
qWarning() << "Project storage could not been updated!"; qWarning() << "Project storage could not been updated!";
} }
@@ -323,7 +327,7 @@ void ProjectStorageUpdater::updateQmlTypes(const QStringList &qmlTypesPaths,
tracer.tick("append project data"_t, keyValue("project data", directoryInfo)); tracer.tick("append project data"_t, keyValue("project data", directoryInfo));
package.directoryInfos.push_back(std::move(directoryInfo)); package.directoryInfos.push_back(std::move(directoryInfo));
tracer.tick("append updated project source ids"_t, keyValue("source id", sourceId)); tracer.tick("append updated project source ids"_t, keyValue("source id", sourceId));
package.updatedProjectSourceIds.push_back(sourceId); package.updatedDirectoryInfoSourceIds.push_back(sourceId);
} }
} }
} }
@@ -409,7 +413,7 @@ void ProjectStorageUpdater::updateDirectoryChanged(std::string_view directoryPat
watchedSourceIdsIds, watchedSourceIdsIds,
qmldirState); qmldirState);
tracer.tick("append updated project source id"_t, keyValue("module id", moduleId)); tracer.tick("append updated project source id"_t, keyValue("module id", moduleId));
package.updatedProjectSourceIds.push_back(directorySourceId); package.updatedDirectoryInfoSourceIds.push_back(directorySourceId);
} }
void ProjectStorageUpdater::updateDirectories(const QStringList &directories, void ProjectStorageUpdater::updateDirectories(const QStringList &directories,
@@ -420,10 +424,111 @@ void ProjectStorageUpdater::updateDirectories(const QStringList &directories,
NanotraceHR::Tracer tracer{"update directories"_t, category()}; NanotraceHR::Tracer tracer{"update directories"_t, category()};
for (const QString &directory : directories) for (const QString &directory : directories)
updateDirectory({directory}, package, notUpdatedSourceIds, watchedSourceIdsIds); updateDirectory({directory}, {}, package, notUpdatedSourceIds, watchedSourceIdsIds);
}
void ProjectStorageUpdater::updateSubdirectories(const Utils::PathString &directoryPath,
SourceId directorySourceId,
FileState directoryState,
const SourceContextIds &subdirectoriesToIgnore,
Storage::Synchronization::SynchronizationPackage &package,
NotUpdatedSourceIds &notUpdatedSourceIds,
WatchedSourceIdsIds &watchedSourceIdsIds)
{
struct Directory
{
Directory(Utils::SmallStringView path, SourceContextId sourceContextId, SourceId sourceId)
: path{path}
, sourceContextId{sourceContextId}
, sourceId{sourceId}
{}
bool operator<(const Directory &other) const
{
return sourceContextId < other.sourceContextId;
}
bool operator==(const Directory &other) const
{
return sourceContextId == other.sourceContextId;
}
Utils::PathString path;
SourceContextId sourceContextId;
SourceId sourceId;
};
struct Compare
{
bool operator()(const Directory &first, const Directory &second) const
{
return first.sourceContextId < second.sourceContextId;
}
bool operator()(const Directory &first, SourceContextId second) const
{
return first.sourceContextId < second;
}
bool operator()(SourceContextId first, const Directory &second) const
{
return first < second.sourceContextId;
}
};
using Directories = QVarLengthArray<Directory, 32>;
auto subdirectorySourceIds = m_projectStorage.fetchSubdirectorySourceIds(directorySourceId);
auto subdirectories = Utils::transform<Directories>(
subdirectorySourceIds, [&](SourceId sourceId) -> Directory {
auto sourceContextId = m_pathCache.sourceContextId(sourceId);
auto subdirectoryPath = m_pathCache.sourceContextPath(sourceContextId);
return {subdirectoryPath, sourceContextId, sourceId};
});
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"))
continue;
Utils::PathString subdirectoryPath = subdirectory;
auto [sourceContextId, sourceId] = m_pathCache.sourceContextAndSourceId(
SourcePath{subdirectoryPath + "/."});
subdirectories.emplace_back(subdirectoryPath, sourceContextId, sourceId);
existingSubdirecories.emplace_back(subdirectoryPath, sourceContextId, sourceId);
}
std::sort(subdirectories.begin(), subdirectories.end());
subdirectories.erase(std::unique(subdirectories.begin(), subdirectories.end()),
subdirectories.end());
std::set_difference(subdirectories.begin(),
subdirectories.end(),
subdirectoriesToIgnore.begin(),
subdirectoriesToIgnore.end(),
Utils::make_iterator([&](const Directory &subdirectory) {
updateDirectory(subdirectory.path,
subdirectoriesToIgnore,
package,
notUpdatedSourceIds,
watchedSourceIdsIds);
}),
Compare{});
if (directoryState == FileState::Changed) {
for (const auto &[subdirectoryPath, sourceContextId, subdirectorySourceId] :
existingSubdirecories) {
package.directoryInfos.emplace_back(directorySourceId,
subdirectorySourceId,
ModuleId{},
Storage::Synchronization::FileType::Directory);
}
}
} }
void ProjectStorageUpdater::updateDirectory(const Utils::PathString &directoryPath, void ProjectStorageUpdater::updateDirectory(const Utils::PathString &directoryPath,
const SourceContextIds &subdirectoriesToIgnore,
Storage::Synchronization::SynchronizationPackage &package, Storage::Synchronization::SynchronizationPackage &package,
NotUpdatedSourceIds &notUpdatedSourceIds, NotUpdatedSourceIds &notUpdatedSourceIds,
WatchedSourceIdsIds &watchedSourceIdsIds) WatchedSourceIdsIds &watchedSourceIdsIds)
@@ -472,7 +577,7 @@ void ProjectStorageUpdater::updateDirectory(const Utils::PathString &directoryPa
package.updatedFileStatusSourceIds.push_back(directorySourceId); package.updatedFileStatusSourceIds.push_back(directorySourceId);
package.updatedFileStatusSourceIds.push_back(qmldirSourceId); package.updatedFileStatusSourceIds.push_back(qmldirSourceId);
package.updatedProjectSourceIds.push_back(directorySourceId); package.updatedDirectoryInfoSourceIds.push_back(directorySourceId);
package.updatedSourceIds.push_back(qmldirSourceId); package.updatedSourceIds.push_back(qmldirSourceId);
auto qmlDirectoryInfos = m_projectStorage.fetchDirectoryInfos(directorySourceId); auto qmlDirectoryInfos = m_projectStorage.fetchDirectoryInfos(directorySourceId);
for (const Storage::Synchronization::DirectoryInfo &directoryInfo : qmlDirectoryInfos) { for (const Storage::Synchronization::DirectoryInfo &directoryInfo : qmlDirectoryInfos) {
@@ -487,6 +592,14 @@ void ProjectStorageUpdater::updateDirectory(const Utils::PathString &directoryPa
} }
} }
updateSubdirectories(directoryPath,
directorySourceId,
directoryState,
subdirectoriesToIgnore,
package,
notUpdatedSourceIds,
watchedSourceIdsIds);
tracer.end(keyValue("qmldir source path", qmldirSourcePath), tracer.end(keyValue("qmldir source path", qmldirSourcePath),
keyValue("directory source path", directorySourcePath), keyValue("directory source path", directorySourcePath),
keyValue("directory id", directoryId), keyValue("directory id", directoryId),
@@ -788,7 +901,11 @@ void ProjectStorageUpdater::pathsWithIdsChanged(const std::vector<IdPaths> &chan
for (auto sourceContextId : directorySourceContextIds) { for (auto sourceContextId : directorySourceContextIds) {
Utils::PathString directory = m_pathCache.sourceContextPath(sourceContextId); Utils::PathString directory = m_pathCache.sourceContextPath(sourceContextId);
updateDirectory(directory, package, notUpdatedSourceIds, watchedSourceIds); updateDirectory(directory,
directorySourceContextIds,
package,
notUpdatedSourceIds,
watchedSourceIds);
} }
for (SourceId sourceId : filterUniqueSourceIds(qmlDocumentSourceIds)) { for (SourceId sourceId : filterUniqueSourceIds(qmlDocumentSourceIds)) {
@@ -867,7 +984,7 @@ void ProjectStorageUpdater::parseTypeInfos(const QStringList &typeInfos,
tracer.tick("append module dependenct source source id"_t, keyValue("source id", sourceId)); tracer.tick("append module dependenct source source id"_t, keyValue("source id", sourceId));
package.updatedModuleDependencySourceIds.push_back(sourceId); package.updatedModuleDependencySourceIds.push_back(sourceId);
auto directoryInfo = package.directoryInfos.emplace_back( const auto &directoryInfo = package.directoryInfos.emplace_back(
directorySourceId, sourceId, moduleId, Storage::Synchronization::FileType::QmlTypes); directorySourceId, sourceId, moduleId, Storage::Synchronization::FileType::QmlTypes);
tracer.tick("append project data"_t, keyValue("source id", sourceId)); tracer.tick("append project data"_t, keyValue("source id", sourceId));
@@ -898,6 +1015,8 @@ void ProjectStorageUpdater::parseDirectoryInfos(
parseQmlComponent(directoryInfo.sourceId, package, notUpdatedSourceIds); parseQmlComponent(directoryInfo.sourceId, package, notUpdatedSourceIds);
break; break;
} }
case Storage::Synchronization::FileType::Directory:
break;
} }
} }
} }

View File

@@ -143,6 +143,14 @@ private:
WatchedSourceIdsIds &watchedSourceIdsIds); WatchedSourceIdsIds &watchedSourceIdsIds);
void updateDirectory(const Utils::PathString &directory, void updateDirectory(const Utils::PathString &directory,
const SourceContextIds &subdirecoriesToIgnore,
Storage::Synchronization::SynchronizationPackage &package,
NotUpdatedSourceIds &notUpdatedSourceIds,
WatchedSourceIdsIds &watchedSourceIdsIds);
void updateSubdirectories(const Utils::PathString &directory,
SourceId directorySourceId,
FileState directoryFileState,
const SourceContextIds &subdirecoriesToIgnore,
Storage::Synchronization::SynchronizationPackage &package, Storage::Synchronization::SynchronizationPackage &package,
NotUpdatedSourceIds &notUpdatedSourceIds, NotUpdatedSourceIds &notUpdatedSourceIds,
WatchedSourceIdsIds &watchedSourceIdsIds); WatchedSourceIdsIds &watchedSourceIdsIds);

View File

@@ -7,6 +7,8 @@
#include <utils/smallstring.h> #include <utils/smallstring.h>
#include <QVarLengthArray>
namespace QmlDesigner { namespace QmlDesigner {
class SourcePath : public Utils::PathString class SourcePath : public Utils::PathString
@@ -128,5 +130,6 @@ private:
}; };
using SourcePaths = std::vector<SourcePath>; using SourcePaths = std::vector<SourcePath>;
template<std::size_t size>
using SmallSourcePaths = QVarLengthArray<SourcePath, size>;
} // namespace QmlDesigner } // namespace QmlDesigner

View File

@@ -341,81 +341,32 @@ Utils::FilePath qmlPath(::ProjectExplorer::Target *target)
return {}; return {};
} }
template<typename... Path>
bool skipDirectoriesWith(const QStringView directoryPath, const Path &...paths)
{
return (directoryPath.contains(paths) || ...);
}
template<typename... Path>
bool skipDirectoriesEndsWith(const QStringView directoryPath, const Path &...paths)
{
return (directoryPath.endsWith(paths) || ...);
}
bool skipPath(const QString &directoryPath)
{
return skipDirectoriesWith(directoryPath,
u"QtApplicationManager",
u"QtInterfaceFramework",
u"QtOpcUa",
u"Qt3D",
u"Scene2D",
u"Scene3D",
u"QtWayland",
u"Qt5Compat",
u"QtCharts",
u"QtLocation",
u"QtPositioning",
u"MaterialEditor",
u"QtTextToSpeech",
u"QtWebEngine",
u"Qt/labs",
u"QtDataVisualization")
|| skipDirectoriesEndsWith(directoryPath, u"designer");
}
void collectQmldirPaths(const QString &path, QStringList &qmldirPaths)
{
QDirIterator dirIterator{path, QDir::Dirs | QDir::NoDotAndDotDot, QDirIterator::Subdirectories};
QString rootQmldirPath = path + "/qmldir";
if (!skipPath(path) && QFileInfo::exists(rootQmldirPath))
qmldirPaths.push_back(path);
while (dirIterator.hasNext()) {
auto directoryPath = dirIterator.next();
QString qmldirPath = directoryPath + "/qmldir";
if (!skipPath(directoryPath) && QFileInfo::exists(qmldirPath))
qmldirPaths.push_back(directoryPath);
}
}
[[maybe_unused]] void projectQmldirPaths(::ProjectExplorer::Target *target, QStringList &qmldirPaths) [[maybe_unused]] void projectQmldirPaths(::ProjectExplorer::Target *target, QStringList &qmldirPaths)
{ {
::QmlProjectManager::QmlBuildSystem *buildSystem = getQmlBuildSystem(target); ::QmlProjectManager::QmlBuildSystem *buildSystem = getQmlBuildSystem(target);
const Utils::FilePath projectDirectoryPath = buildSystem->canonicalProjectDir(); const Utils::FilePath projectDirectoryPath = buildSystem->canonicalProjectDir();
const QStringList importPaths = buildSystem->importPaths();
const QDir projectDirectory(projectDirectoryPath.toString());
for (const QString &importPath : importPaths) qmldirPaths.push_back(projectDirectoryPath.path());
collectQmldirPaths(importPath, qmldirPaths);
} }
[[maybe_unused]] void qtQmldirPaths(::ProjectExplorer::Target *target, QStringList &qmldirPaths) [[maybe_unused]] void qtQmldirPaths(::ProjectExplorer::Target *target, QStringList &qmldirPaths)
{ {
if constexpr (useProjectStorage()) if constexpr (useProjectStorage()) {
collectQmldirPaths(qmlPath(target).toString(), qmldirPaths); auto qmlRootPath = qmlPath(target).toString();
qmldirPaths.push_back(qmlRootPath + "/QtQml");
qmldirPaths.push_back(qmlRootPath + "/QtQuick");
qmldirPaths.push_back(qmlRootPath + "/QtQuick3D");
qmldirPaths.push_back(qmlRootPath + "/Qt5Compat");
}
} }
[[maybe_unused]] void qtQmldirPathsForLiteDesigner(QStringList &qmldirPaths) [[maybe_unused]] void qtQmldirPathsForLiteDesigner(QStringList &qmldirPaths)
{ {
if constexpr (useProjectStorage()) { if constexpr (useProjectStorage()) {
auto qmlRootPath = QLibraryInfo::path(QLibraryInfo::QmlImportsPath); auto qmlRootPath = QLibraryInfo::path(QLibraryInfo::QmlImportsPath);
collectQmldirPaths(qmlRootPath + "/QtQml", qmldirPaths); qmldirPaths.push_back(qmlRootPath + "/QtQml");
collectQmldirPaths(qmlRootPath + "/QtQuick", qmldirPaths); qmldirPaths.push_back(qmlRootPath + "/QtQuick");
} }
} }

View File

@@ -20,4 +20,5 @@ public:
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));
MOCK_METHOD(QString, contentAsQString, (const QString &filePath), (const, override)); MOCK_METHOD(QString, contentAsQString, (const QString &filePath), (const, override));
MOCK_METHOD(QStringList, subdirectories, (const QString &directoryPath), (const, override));
}; };

View File

@@ -305,6 +305,16 @@ public:
(QmlDesigner::SourceId sourceId), (QmlDesigner::SourceId sourceId),
(const, override)); (const, override));
MOCK_METHOD(QmlDesigner::Storage::Synchronization::DirectoryInfos,
fetchDirectoryInfos,
(QmlDesigner::SourceId sourceId, QmlDesigner::Storage::Synchronization::FileType),
(const, override));
MOCK_METHOD(QmlDesigner::SmallSourceIds<32>,
fetchSubdirectorySourceIds,
(QmlDesigner::SourceId sourceId),
(const, override));
MOCK_METHOD(std::optional<QmlDesigner::Storage::Synchronization::DirectoryInfo>, MOCK_METHOD(std::optional<QmlDesigner::Storage::Synchronization::DirectoryInfo>,
fetchDirectoryInfo, fetchDirectoryInfo,
(QmlDesigner::SourceId sourceId), (QmlDesigner::SourceId sourceId),

View File

@@ -754,6 +754,8 @@ const char *fileTypeToText(FileType fileType)
return "QmlDocument"; return "QmlDocument";
case FileType::QmlTypes: case FileType::QmlTypes:
return "QmlTypes"; return "QmlTypes";
case FileType::Directory:
return "Directory";
} }
return ""; return "";
@@ -791,7 +793,7 @@ 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
<< ", updatedProjectSourceIds: " << package.updatedProjectSourceIds << ", updatedDirectoryInfoSourceIds: " << package.updatedDirectoryInfoSourceIds
<< ", directoryInfos: " << package.directoryInfos << ", directoryInfos: " << package.directoryInfos
<< ", propertyEditorQmlPaths: " << package.propertyEditorQmlPaths << ", propertyEditorQmlPaths: " << package.propertyEditorQmlPaths
<< ", updatedPropertyEditorQmlPathSourceIds: " << ", updatedPropertyEditorQmlPathSourceIds: "

View File

@@ -5317,6 +5317,49 @@ TEST_F(ProjectStorage, fetch_directory_infos_by_directory_source_id)
ASSERT_THAT(directoryInfo, UnorderedElementsAre(directoryInfo1, directoryInfo2)); ASSERT_THAT(directoryInfo, UnorderedElementsAre(directoryInfo1, directoryInfo2));
} }
TEST_F(ProjectStorage, fetch_directory_infos_by_directory_source_id_and_file_type)
{
Storage::Synchronization::DirectoryInfo directoryInfo1{
qmlProjectSourceId, sourceId1, qmlModuleId, Storage::Synchronization::FileType::QmlDocument};
Storage::Synchronization::DirectoryInfo directoryInfo2{
qmlProjectSourceId, sourceId2, ModuleId{}, Storage::Synchronization::FileType::Directory};
Storage::Synchronization::DirectoryInfo directoryInfo3{qtQuickProjectSourceId,
sourceId3,
qtQuickModuleId,
Storage::Synchronization::FileType::QmlTypes};
Storage::Synchronization::DirectoryInfo directoryInfo4{
qmlProjectSourceId, sourceId4, ModuleId{}, Storage::Synchronization::FileType::Directory};
storage.synchronize(
SynchronizationPackage{{qmlProjectSourceId, qtQuickProjectSourceId},
{directoryInfo1, directoryInfo2, directoryInfo3, directoryInfo4}});
auto directoryInfo = storage.fetchDirectoryInfos(qmlProjectSourceId,
Storage::Synchronization::FileType::Directory);
ASSERT_THAT(directoryInfo, UnorderedElementsAre(directoryInfo2, directoryInfo4));
}
TEST_F(ProjectStorage, fetch_subdirectory_source_ids)
{
Storage::Synchronization::DirectoryInfo directoryInfo1{
qmlProjectSourceId, sourceId1, qmlModuleId, Storage::Synchronization::FileType::QmlDocument};
Storage::Synchronization::DirectoryInfo directoryInfo2{
qmlProjectSourceId, sourceId2, ModuleId{}, Storage::Synchronization::FileType::Directory};
Storage::Synchronization::DirectoryInfo directoryInfo3{qtQuickProjectSourceId,
sourceId3,
qtQuickModuleId,
Storage::Synchronization::FileType::QmlTypes};
Storage::Synchronization::DirectoryInfo directoryInfo4{
qmlProjectSourceId, sourceId4, ModuleId{}, Storage::Synchronization::FileType::Directory};
storage.synchronize(
SynchronizationPackage{{qmlProjectSourceId, qtQuickProjectSourceId},
{directoryInfo1, directoryInfo2, directoryInfo3, directoryInfo4}});
auto directoryInfo = storage.fetchSubdirectorySourceIds(qmlProjectSourceId);
ASSERT_THAT(directoryInfo, UnorderedElementsAre(sourceId2, sourceId4));
}
TEST_F(ProjectStorage, fetch_directory_info_by_source_ids) TEST_F(ProjectStorage, fetch_directory_info_by_source_ids)
{ {
Storage::Synchronization::DirectoryInfo directoryInfo1{qmlProjectSourceId, Storage::Synchronization::DirectoryInfo directoryInfo1{qmlProjectSourceId,

View File

@@ -119,8 +119,9 @@ MATCHER(PackageIsEmpty, std::string(negation ? "isn't empty" : "is empty"))
return package.imports.empty() && package.types.empty() && package.fileStatuses.empty() return package.imports.empty() && package.types.empty() && package.fileStatuses.empty()
&& package.updatedSourceIds.empty() && package.directoryInfos.empty() && package.updatedSourceIds.empty() && package.directoryInfos.empty()
&& package.updatedFileStatusSourceIds.empty() && package.updatedProjectSourceIds.empty() && package.updatedFileStatusSourceIds.empty()
&& package.moduleDependencies.empty() && package.updatedModuleDependencySourceIds.empty() && package.updatedDirectoryInfoSourceIds.empty() && package.moduleDependencies.empty()
&& package.updatedModuleDependencySourceIds.empty()
&& package.moduleExportedImports.empty() && package.updatedModuleIds.empty() && package.moduleExportedImports.empty() && package.updatedModuleIds.empty()
&& package.propertyEditorQmlPaths.empty() && package.propertyEditorQmlPaths.empty()
&& package.updatedPropertyEditorQmlPathSourceIds.empty() && package.updatedPropertyEditorQmlPathSourceIds.empty()
@@ -303,6 +304,18 @@ public:
EXPECT_CALL(fileSystemMock, contentAsQString(Eq(path))).WillRepeatedly(Return(content)); EXPECT_CALL(fileSystemMock, contentAsQString(Eq(path))).WillRepeatedly(Return(content));
} }
void setSubdirectoryPaths(QStringView directoryPath, const QStringList &subdirectoryPaths)
{
ON_CALL(fileSystemMock, subdirectories(Eq(directoryPath))).WillByDefault(Return(subdirectoryPaths));
}
void setSubdirectorySourceIds(SourceId directorySourceId,
const QmlDesigner::SmallSourceIds<32> &subdirectorySourceId)
{
ON_CALL(projectStorageMock, fetchSubdirectorySourceIds(Eq(directorySourceId)))
.WillByDefault(Return(subdirectorySourceId));
}
auto moduleId(Utils::SmallStringView name, ModuleKind kind) const auto moduleId(Utils::SmallStringView name, ModuleKind kind) const
{ {
return storage.moduleId(name, kind); return storage.moduleId(name, kind);
@@ -430,6 +443,24 @@ TEST_F(ProjectStorageUpdater, get_content_for_qml_dir_paths_if_file_status_is_di
updater.update(directories, {}, {}, {}); updater.update(directories, {}, {}, {});
} }
TEST_F(ProjectStorageUpdater,
get_content_for_qml_dir_paths_if_file_status_is_different_for_subdirectories)
{
SourceId qmlDir1PathSourceId = sourcePathCache.sourceId("/path/one/qmldir");
SourceId qmlDir2PathSourceId = sourcePathCache.sourceId("/path/two/qmldir");
SourceId qmlDir3PathSourceId = sourcePathCache.sourceId("/path/three/qmldir");
SourceId path3SourceId = sourcePathCache.sourceId("/path/three/.");
QStringList directories = {"/path/one"};
setSubdirectoryPaths(u"/path/one", {"/path/two", "/path/three"});
setFilesChanged({qmlDir1PathSourceId, qmlDir2PathSourceId});
setFilesDontChanged({qmlDir3PathSourceId, path3SourceId});
EXPECT_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/one/qmldir"))));
EXPECT_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/two/qmldir"))));
updater.update(directories, {}, {}, {});
}
TEST_F(ProjectStorageUpdater, request_file_status_from_file_system) TEST_F(ProjectStorageUpdater, request_file_status_from_file_system)
{ {
EXPECT_CALL(fileSystemMock, fileStatus(Ne(directoryPathSourceId))).Times(AnyNumber()); EXPECT_CALL(fileSystemMock, fileStatus(Ne(directoryPathSourceId))).Times(AnyNumber());
@@ -439,6 +470,20 @@ TEST_F(ProjectStorageUpdater, request_file_status_from_file_system)
updater.update(directories, {}, {}, {}); updater.update(directories, {}, {}, {});
} }
TEST_F(ProjectStorageUpdater, request_file_status_from_file_system_for_subdirectories)
{
EXPECT_CALL(fileSystemMock,
fileStatus(AllOf(Ne(directoryPathSourceId), Ne(path1SourceId), Ne(path2SourceId))))
.Times(AnyNumber());
setSubdirectoryPaths(u"/path", {"/path/one", "/path/two"});
EXPECT_CALL(fileSystemMock, fileStatus(Eq(path1SourceId)));
EXPECT_CALL(fileSystemMock, fileStatus(Eq(path2SourceId)));
EXPECT_CALL(fileSystemMock, fileStatus(Eq(directoryPathSourceId)));
updater.update(directories, {}, {}, {});
}
TEST_F(ProjectStorageUpdater, get_content_for_qml_types) TEST_F(ProjectStorageUpdater, get_content_for_qml_types)
{ {
QString qmldir{R"(module Example QString qmldir{R"(module Example
@@ -483,6 +528,27 @@ TEST_F(ProjectStorageUpdater, parse_qml_types)
updater.update(directories, {}, {}, {}); updater.update(directories, {}, {}, {});
} }
TEST_F(ProjectStorageUpdater, parse_qml_types_in_subdirectories)
{
QString qmldir{R"(module Example
typeinfo example.qmltypes
typeinfo example2.qmltypes)"};
setContent(u"/path/qmldir", qmldir);
QString qmltypes{"Module {\ndependencies: []}"};
QString qmltypes2{"Module {\ndependencies: [foo]}"};
setContent(u"/path/example.qmltypes", qmltypes);
setContent(u"/path/example2.qmltypes", qmltypes2);
QStringList directories = {"/root"};
setSubdirectoryPaths(u"/root", {"/path"});
EXPECT_CALL(qmlTypesParserMock,
parse(qmltypes, _, _, Field(&DirectoryInfo::moduleId, exampleCppNativeModuleId)));
EXPECT_CALL(qmlTypesParserMock,
parse(qmltypes2, _, _, Field(&DirectoryInfo::moduleId, exampleCppNativeModuleId)));
updater.update(directories, {}, {}, {});
}
TEST_F(ProjectStorageUpdater, synchronize_is_empty_for_no_change) TEST_F(ProjectStorageUpdater, synchronize_is_empty_for_no_change)
{ {
setFilesDontChanged({qmltypesPathSourceId, qmltypes2PathSourceId, qmlDirPathSourceId}); setFilesDontChanged({qmltypesPathSourceId, qmltypes2PathSourceId, qmlDirPathSourceId});
@@ -492,6 +558,23 @@ TEST_F(ProjectStorageUpdater, synchronize_is_empty_for_no_change)
updater.update(directories, {}, {}, {}); updater.update(directories, {}, {}, {});
} }
TEST_F(ProjectStorageUpdater, synchronize_is_empty_for_no_change_in_subdirectory)
{
SourceId qmlDirRootPathSourceId = sourcePathCache.sourceId("/root/qmldir");
SourceId rootPathSourceId = sourcePathCache.sourceId("/root/.");
setFilesDontChanged({qmltypesPathSourceId,
qmltypes2PathSourceId,
qmlDirPathSourceId,
qmlDirRootPathSourceId,
rootPathSourceId});
QStringList directories = {"/root"};
setSubdirectoryPaths(u"/root", {"/path"});
EXPECT_CALL(projectStorageMock, synchronize(PackageIsEmpty()));
updater.update(directories, {}, {}, {});
}
TEST_F(ProjectStorageUpdater, synchronize_qml_types) TEST_F(ProjectStorageUpdater, synchronize_qml_types)
{ {
Storage::Import import{qmlModuleId, Storage::Version{2, 3}, qmltypesPathSourceId}; Storage::Import import{qmlModuleId, Storage::Version{2, 3}, qmltypesPathSourceId};
@@ -521,12 +604,83 @@ TEST_F(ProjectStorageUpdater, synchronize_qml_types)
qmltypesPathSourceId, qmltypesPathSourceId,
exampleCppNativeModuleId, exampleCppNativeModuleId,
FileType::QmlTypes))), FileType::QmlTypes))),
Field(&SynchronizationPackage::updatedProjectSourceIds, Field(&SynchronizationPackage::updatedDirectoryInfoSourceIds,
UnorderedElementsAre(directoryPathSourceId))))); UnorderedElementsAre(directoryPathSourceId)))));
updater.update(directories, {}, {}, {}); updater.update(directories, {}, {}, {});
} }
TEST_F(ProjectStorageUpdater, synchronize_subdircectories)
{
QStringList directories = {"/root"};
setSubdirectoryPaths(u"/root", {"/path/one", "/path/two"});
setSubdirectoryPaths(u"/path/one", {"/path/three"});
SourceId rootDirectoryPathSourceId = sourcePathCache.sourceId("/root/.");
setFilesChanged({rootDirectoryPathSourceId, path1SourceId, path2SourceId, path3SourceId});
EXPECT_CALL(
projectStorageMock,
synchronize(AllOf(
Field(&SynchronizationPackage::directoryInfos,
UnorderedElementsAre(
IsDirectoryInfo(rootDirectoryPathSourceId, path1SourceId, ModuleId{}, FileType::Directory),
IsDirectoryInfo(rootDirectoryPathSourceId, path2SourceId, ModuleId{}, FileType::Directory),
IsDirectoryInfo(path1SourceId, path3SourceId, ModuleId{}, FileType::Directory))),
Field(&SynchronizationPackage::updatedDirectoryInfoSourceIds,
UnorderedElementsAre(
rootDirectoryPathSourceId, path1SourceId, path2SourceId, path3SourceId)))));
updater.update(directories, {}, {}, {});
}
TEST_F(ProjectStorageUpdater, synchronize_subdircectories_even_for_no_changes)
{
QStringList directories = {"/root"};
setSubdirectoryPaths(u"/root", {"/path/one", "/path/two"});
setSubdirectoryPaths(u"/path/one", {"/path/three"});
SourceId rootDirectoryPathSourceId = sourcePathCache.sourceId("/root/.");
setFilesChanged({path1SourceId, path2SourceId, path3SourceId});
setFilesDontChanged({rootDirectoryPathSourceId});
EXPECT_CALL(projectStorageMock,
synchronize(
AllOf(Field(&SynchronizationPackage::directoryInfos,
UnorderedElementsAre(IsDirectoryInfo(
path1SourceId, path3SourceId, ModuleId{}, FileType::Directory))),
Field(&SynchronizationPackage::updatedDirectoryInfoSourceIds,
UnorderedElementsAre(path1SourceId, path2SourceId, path3SourceId)))));
updater.update(directories, {}, {}, {});
}
TEST_F(ProjectStorageUpdater, synchronize_subdircectories_for_deleted_subdirecties)
{
QStringList directories = {"/root"};
setSubdirectoryPaths(u"/root", {"/path/two"});
SourceId rootDirectoryPathSourceId = sourcePathCache.sourceId("/root/.");
setFilesChanged({rootDirectoryPathSourceId});
setFilesDontExists({
path1SourceId,
path3SourceId,
});
setSubdirectorySourceIds(rootDirectoryPathSourceId, {path1SourceId, path2SourceId});
setSubdirectorySourceIds(path1SourceId, {path3SourceId});
EXPECT_CALL(projectStorageMock,
synchronize(AllOf(Field(&SynchronizationPackage::directoryInfos,
UnorderedElementsAre(IsDirectoryInfo(rootDirectoryPathSourceId,
path2SourceId,
ModuleId{},
FileType::Directory))),
Field(&SynchronizationPackage::updatedDirectoryInfoSourceIds,
UnorderedElementsAre(rootDirectoryPathSourceId,
path1SourceId,
path2SourceId,
path3SourceId)))));
updater.update(directories, {}, {}, {});
}
TEST_F(ProjectStorageUpdater, synchronize_qml_types_throws_if_qmltpes_does_not_exists) TEST_F(ProjectStorageUpdater, synchronize_qml_types_throws_if_qmltpes_does_not_exists)
{ {
Storage::Import import{qmlModuleId, Storage::Version{2, 3}, qmltypesPathSourceId}; Storage::Import import{qmlModuleId, Storage::Version{2, 3}, qmltypesPathSourceId};
@@ -653,7 +807,7 @@ TEST_F(ProjectStorageUpdater, synchronize_qml_documents)
IsFileStatus(qmlDocumentSourceId1, 1, 21), IsFileStatus(qmlDocumentSourceId1, 1, 21),
IsFileStatus(qmlDocumentSourceId2, 1, 21), IsFileStatus(qmlDocumentSourceId2, 1, 21),
IsFileStatus(qmlDocumentSourceId3, 1, 21))), IsFileStatus(qmlDocumentSourceId3, 1, 21))),
Field(&SynchronizationPackage::updatedProjectSourceIds, Field(&SynchronizationPackage::updatedDirectoryInfoSourceIds,
UnorderedElementsAre(directoryPathSourceId)), UnorderedElementsAre(directoryPathSourceId)),
Field(&SynchronizationPackage::directoryInfos, Field(&SynchronizationPackage::directoryInfos,
UnorderedElementsAre(IsDirectoryInfo(directoryPathSourceId, UnorderedElementsAre(IsDirectoryInfo(directoryPathSourceId,
@@ -713,7 +867,7 @@ TEST_F(ProjectStorageUpdater, synchronize_add_only_qml_document_in_directory)
Field(&SynchronizationPackage::fileStatuses, Field(&SynchronizationPackage::fileStatuses,
UnorderedElementsAre(IsFileStatus(qmlDocumentSourceId2, 1, 21), UnorderedElementsAre(IsFileStatus(qmlDocumentSourceId2, 1, 21),
IsFileStatus(directoryPathSourceId, 1, 21))), IsFileStatus(directoryPathSourceId, 1, 21))),
Field(&SynchronizationPackage::updatedProjectSourceIds, Field(&SynchronizationPackage::updatedDirectoryInfoSourceIds,
UnorderedElementsAre(directoryPathSourceId)), UnorderedElementsAre(directoryPathSourceId)),
Field(&SynchronizationPackage::directoryInfos, Field(&SynchronizationPackage::directoryInfos,
UnorderedElementsAre(IsDirectoryInfo(directoryPathSourceId, UnorderedElementsAre(IsDirectoryInfo(directoryPathSourceId,
@@ -777,7 +931,7 @@ TEST_F(ProjectStorageUpdater, synchronize_removes_qml_document)
UnorderedElementsAre(qmlDirPathSourceId, qmlDocumentSourceId3)), UnorderedElementsAre(qmlDirPathSourceId, qmlDocumentSourceId3)),
Field(&SynchronizationPackage::fileStatuses, Field(&SynchronizationPackage::fileStatuses,
UnorderedElementsAre(IsFileStatus(qmlDirPathSourceId, 1, 21))), UnorderedElementsAre(IsFileStatus(qmlDirPathSourceId, 1, 21))),
Field(&SynchronizationPackage::updatedProjectSourceIds, Field(&SynchronizationPackage::updatedDirectoryInfoSourceIds,
UnorderedElementsAre(directoryPathSourceId)), UnorderedElementsAre(directoryPathSourceId)),
Field(&SynchronizationPackage::directoryInfos, Field(&SynchronizationPackage::directoryInfos,
UnorderedElementsAre(IsDirectoryInfo(directoryPathSourceId, UnorderedElementsAre(IsDirectoryInfo(directoryPathSourceId,
@@ -832,7 +986,7 @@ TEST_F(ProjectStorageUpdater, synchronize_removes_qml_document_in_qmldir_only)
UnorderedElementsAre(qmlDirPathSourceId)), UnorderedElementsAre(qmlDirPathSourceId)),
Field(&SynchronizationPackage::fileStatuses, Field(&SynchronizationPackage::fileStatuses,
UnorderedElementsAre(IsFileStatus(qmlDirPathSourceId, 1, 21))), UnorderedElementsAre(IsFileStatus(qmlDirPathSourceId, 1, 21))),
Field(&SynchronizationPackage::updatedProjectSourceIds, Field(&SynchronizationPackage::updatedDirectoryInfoSourceIds,
UnorderedElementsAre(directoryPathSourceId)), UnorderedElementsAre(directoryPathSourceId)),
Field(&SynchronizationPackage::directoryInfos, Field(&SynchronizationPackage::directoryInfos,
UnorderedElementsAre(IsDirectoryInfo(directoryPathSourceId, UnorderedElementsAre(IsDirectoryInfo(directoryPathSourceId,
@@ -890,7 +1044,7 @@ TEST_F(ProjectStorageUpdater, synchronize_add_qml_document_to_qmldir)
UnorderedElementsAre(qmlDirPathSourceId)), UnorderedElementsAre(qmlDirPathSourceId)),
Field(&SynchronizationPackage::fileStatuses, Field(&SynchronizationPackage::fileStatuses,
UnorderedElementsAre(IsFileStatus(qmlDirPathSourceId, 1, 21))), UnorderedElementsAre(IsFileStatus(qmlDirPathSourceId, 1, 21))),
Field(&SynchronizationPackage::updatedProjectSourceIds, Field(&SynchronizationPackage::updatedDirectoryInfoSourceIds,
UnorderedElementsAre(directoryPathSourceId)), UnorderedElementsAre(directoryPathSourceId)),
Field(&SynchronizationPackage::directoryInfos, Field(&SynchronizationPackage::directoryInfos,
UnorderedElementsAre(IsDirectoryInfo(directoryPathSourceId, UnorderedElementsAre(IsDirectoryInfo(directoryPathSourceId,
@@ -945,7 +1099,7 @@ TEST_F(ProjectStorageUpdater, synchronize_remove_qml_document_from_qmldir)
UnorderedElementsAre(qmlDirPathSourceId)), UnorderedElementsAre(qmlDirPathSourceId)),
Field(&SynchronizationPackage::fileStatuses, Field(&SynchronizationPackage::fileStatuses,
UnorderedElementsAre(IsFileStatus(qmlDirPathSourceId, 1, 21))), UnorderedElementsAre(IsFileStatus(qmlDirPathSourceId, 1, 21))),
Field(&SynchronizationPackage::updatedProjectSourceIds, Field(&SynchronizationPackage::updatedDirectoryInfoSourceIds,
UnorderedElementsAre(directoryPathSourceId)), UnorderedElementsAre(directoryPathSourceId)),
Field(&SynchronizationPackage::directoryInfos, Field(&SynchronizationPackage::directoryInfos,
UnorderedElementsAre(IsDirectoryInfo(directoryPathSourceId, UnorderedElementsAre(IsDirectoryInfo(directoryPathSourceId,
@@ -1011,7 +1165,7 @@ TEST_F(ProjectStorageUpdater, synchronize_qml_documents_dont_update_if_up_to_dat
IsFileStatus(qmlDocumentSourceId2, 1, 21))), IsFileStatus(qmlDocumentSourceId2, 1, 21))),
Field(&SynchronizationPackage::updatedFileStatusSourceIds, Field(&SynchronizationPackage::updatedFileStatusSourceIds,
UnorderedElementsAre(qmlDirPathSourceId, qmlDocumentSourceId1, qmlDocumentSourceId2)), UnorderedElementsAre(qmlDirPathSourceId, qmlDocumentSourceId1, qmlDocumentSourceId2)),
Field(&SynchronizationPackage::updatedProjectSourceIds, Field(&SynchronizationPackage::updatedDirectoryInfoSourceIds,
UnorderedElementsAre(directoryPathSourceId)), UnorderedElementsAre(directoryPathSourceId)),
Field(&SynchronizationPackage::directoryInfos, Field(&SynchronizationPackage::directoryInfos,
UnorderedElementsAre(IsDirectoryInfo(directoryPathSourceId, UnorderedElementsAre(IsDirectoryInfo(directoryPathSourceId,
@@ -1193,7 +1347,7 @@ TEST_F(ProjectStorageUpdater, update_qml_types_files_is_empty)
Field(&SynchronizationPackage::fileStatuses, IsEmpty()), Field(&SynchronizationPackage::fileStatuses, IsEmpty()),
Field(&SynchronizationPackage::updatedFileStatusSourceIds, IsEmpty()), Field(&SynchronizationPackage::updatedFileStatusSourceIds, IsEmpty()),
Field(&SynchronizationPackage::directoryInfos, IsEmpty()), Field(&SynchronizationPackage::directoryInfos, IsEmpty()),
Field(&SynchronizationPackage::updatedProjectSourceIds, IsEmpty())))); Field(&SynchronizationPackage::updatedDirectoryInfoSourceIds, IsEmpty()))));
updater.update({}, {}, {}, {}); updater.update({}, {}, {}, {});
} }
@@ -1220,7 +1374,7 @@ TEST_F(ProjectStorageUpdater, update_qml_types_files)
qmltypes2PathSourceId, qmltypes2PathSourceId,
builtinCppNativeModuleId, builtinCppNativeModuleId,
FileType::QmlTypes))), FileType::QmlTypes))),
Field(&SynchronizationPackage::updatedProjectSourceIds, Field(&SynchronizationPackage::updatedDirectoryInfoSourceIds,
UnorderedElementsAre(qmltypesPathSourceId, qmltypes2PathSourceId))))); UnorderedElementsAre(qmltypesPathSourceId, qmltypes2PathSourceId)))));
updater.update({}, {"/path/example.qmltypes", "/path/example2.qmltypes"}, {}, {}); updater.update({}, {"/path/example.qmltypes", "/path/example2.qmltypes"}, {}, {});
@@ -1245,7 +1399,7 @@ TEST_F(ProjectStorageUpdater, dont_update_qml_types_files_if_unchanged)
qmltypesPathSourceId, qmltypesPathSourceId,
builtinCppNativeModuleId, builtinCppNativeModuleId,
FileType::QmlTypes))), FileType::QmlTypes))),
Field(&SynchronizationPackage::updatedProjectSourceIds, Field(&SynchronizationPackage::updatedDirectoryInfoSourceIds,
UnorderedElementsAre(qmltypesPathSourceId))))); UnorderedElementsAre(qmltypesPathSourceId)))));
updater.update({}, {"/path/example.qmltypes", "/path/example2.qmltypes"}, {}, {}); updater.update({}, {"/path/example.qmltypes", "/path/example2.qmltypes"}, {}, {});
@@ -1283,7 +1437,7 @@ TEST_F(ProjectStorageUpdater, synchronize_qml_documents_with_different_version_b
Field(&SynchronizationPackage::fileStatuses, Field(&SynchronizationPackage::fileStatuses,
UnorderedElementsAre(IsFileStatus(qmlDirPathSourceId, 1, 21), UnorderedElementsAre(IsFileStatus(qmlDirPathSourceId, 1, 21),
IsFileStatus(qmlDocumentSourceId1, 1, 21))), IsFileStatus(qmlDocumentSourceId1, 1, 21))),
Field(&SynchronizationPackage::updatedProjectSourceIds, Field(&SynchronizationPackage::updatedDirectoryInfoSourceIds,
UnorderedElementsAre(directoryPathSourceId)), UnorderedElementsAre(directoryPathSourceId)),
Field(&SynchronizationPackage::directoryInfos, Field(&SynchronizationPackage::directoryInfos,
UnorderedElementsAre(IsDirectoryInfo(directoryPathSourceId, UnorderedElementsAre(IsDirectoryInfo(directoryPathSourceId,
@@ -1324,7 +1478,7 @@ TEST_F(ProjectStorageUpdater, synchronize_qml_documents_with_different_type_name
Field(&SynchronizationPackage::fileStatuses, Field(&SynchronizationPackage::fileStatuses,
UnorderedElementsAre(IsFileStatus(qmlDirPathSourceId, 1, 21), UnorderedElementsAre(IsFileStatus(qmlDirPathSourceId, 1, 21),
IsFileStatus(qmlDocumentSourceId1, 1, 21))), IsFileStatus(qmlDocumentSourceId1, 1, 21))),
Field(&SynchronizationPackage::updatedProjectSourceIds, Field(&SynchronizationPackage::updatedDirectoryInfoSourceIds,
UnorderedElementsAre(directoryPathSourceId)), UnorderedElementsAre(directoryPathSourceId)),
Field(&SynchronizationPackage::directoryInfos, Field(&SynchronizationPackage::directoryInfos,
UnorderedElementsAre(IsDirectoryInfo(directoryPathSourceId, UnorderedElementsAre(IsDirectoryInfo(directoryPathSourceId,
@@ -1926,7 +2080,7 @@ TEST_F(ProjectStorageUpdater, synchronize_qml_documents_without_qmldir)
IsFileStatus(qmlDocumentSourceId1, 1, 21), IsFileStatus(qmlDocumentSourceId1, 1, 21),
IsFileStatus(qmlDocumentSourceId2, 1, 21), IsFileStatus(qmlDocumentSourceId2, 1, 21),
IsFileStatus(qmlDocumentSourceId3, 1, 21))), IsFileStatus(qmlDocumentSourceId3, 1, 21))),
Field(&SynchronizationPackage::updatedProjectSourceIds, Field(&SynchronizationPackage::updatedDirectoryInfoSourceIds,
UnorderedElementsAre(directoryPathSourceId)), UnorderedElementsAre(directoryPathSourceId)),
Field(&SynchronizationPackage::directoryInfos, Field(&SynchronizationPackage::directoryInfos,
UnorderedElementsAre(IsDirectoryInfo(directoryPathSourceId, UnorderedElementsAre(IsDirectoryInfo(directoryPathSourceId,
@@ -1977,7 +2131,7 @@ TEST_F(ProjectStorageUpdater, synchronize_qml_documents_without_qmldir_throws_if
qmlDocumentSourceId2, qmlDocumentSourceId2,
qmlDocumentSourceId3)), qmlDocumentSourceId3)),
Field(&SynchronizationPackage::fileStatuses, IsEmpty()), Field(&SynchronizationPackage::fileStatuses, IsEmpty()),
Field(&SynchronizationPackage::updatedProjectSourceIds, Field(&SynchronizationPackage::updatedDirectoryInfoSourceIds,
UnorderedElementsAre(directoryPathSourceId)), UnorderedElementsAre(directoryPathSourceId)),
Field(&SynchronizationPackage::directoryInfos, IsEmpty())))); Field(&SynchronizationPackage::directoryInfos, IsEmpty()))));
@@ -2014,7 +2168,7 @@ TEST_F(ProjectStorageUpdater, synchronize_qml_documents_without_qmldir_add_qml_d
Field(&SynchronizationPackage::fileStatuses, Field(&SynchronizationPackage::fileStatuses,
UnorderedElementsAre(IsFileStatus(directoryPathSourceId, 1, 21), UnorderedElementsAre(IsFileStatus(directoryPathSourceId, 1, 21),
IsFileStatus(qmlDocumentSourceId3, 1, 21))), IsFileStatus(qmlDocumentSourceId3, 1, 21))),
Field(&SynchronizationPackage::updatedProjectSourceIds, Field(&SynchronizationPackage::updatedDirectoryInfoSourceIds,
UnorderedElementsAre(directoryPathSourceId)), UnorderedElementsAre(directoryPathSourceId)),
Field(&SynchronizationPackage::directoryInfos, Field(&SynchronizationPackage::directoryInfos,
UnorderedElementsAre(IsDirectoryInfo(directoryPathSourceId, UnorderedElementsAre(IsDirectoryInfo(directoryPathSourceId,
@@ -2058,7 +2212,7 @@ TEST_F(ProjectStorageUpdater, synchronize_qml_documents_without_qmldir_removes_q
qmlDocumentSourceId3)), qmlDocumentSourceId3)),
Field(&SynchronizationPackage::fileStatuses, Field(&SynchronizationPackage::fileStatuses,
UnorderedElementsAre(IsFileStatus(directoryPathSourceId, 1, 21))), UnorderedElementsAre(IsFileStatus(directoryPathSourceId, 1, 21))),
Field(&SynchronizationPackage::updatedProjectSourceIds, Field(&SynchronizationPackage::updatedDirectoryInfoSourceIds,
UnorderedElementsAre(directoryPathSourceId)), UnorderedElementsAre(directoryPathSourceId)),
Field(&SynchronizationPackage::directoryInfos, Field(&SynchronizationPackage::directoryInfos,
UnorderedElementsAre(IsDirectoryInfo(directoryPathSourceId, UnorderedElementsAre(IsDirectoryInfo(directoryPathSourceId,
@@ -2126,7 +2280,7 @@ TEST_F(ProjectStorageUpdater, watcher_updates_directories)
IsFileStatus(qmlDocumentSourceId1, 1, 21), IsFileStatus(qmlDocumentSourceId1, 1, 21),
IsFileStatus(qmlDocumentSourceId2, 1, 21), IsFileStatus(qmlDocumentSourceId2, 1, 21),
IsFileStatus(qmlDocumentSourceId3, 1, 21))), IsFileStatus(qmlDocumentSourceId3, 1, 21))),
Field(&SynchronizationPackage::updatedProjectSourceIds, Field(&SynchronizationPackage::updatedDirectoryInfoSourceIds,
UnorderedElementsAre(directoryPathSourceId)), UnorderedElementsAre(directoryPathSourceId)),
Field(&SynchronizationPackage::directoryInfos, Field(&SynchronizationPackage::directoryInfos,
UnorderedElementsAre(IsDirectoryInfo(directoryPathSourceId, UnorderedElementsAre(IsDirectoryInfo(directoryPathSourceId,
@@ -2145,6 +2299,74 @@ TEST_F(ProjectStorageUpdater, watcher_updates_directories)
updater.pathsWithIdsChanged({{directoryProjectChunkId, {directoryPathSourceId}}}); updater.pathsWithIdsChanged({{directoryProjectChunkId, {directoryPathSourceId}}});
} }
TEST_F(ProjectStorageUpdater, watcher_updates_subdirectories)
{
QString qmldir{R"(module Example
FirstType 1.0 First.qml
FirstType 2.2 First2.qml
SecondType 2.2 Second.qml)"};
setContent(u"/path/qmldir", qmldir);
SourceId rootPathSourceId = sourcePathCache.sourceId("/root/.");
SourceId rootQmldirPathSourceId = sourcePathCache.sourceId("/root/qmldir");
setFilesChanged({directoryPathSourceId, rootPathSourceId});
setFilesDontChanged({qmlDirPathSourceId, rootQmldirPathSourceId});
setSubdirectoryPaths(u"/root", {"/path"});
setSubdirectorySourceIds(rootPathSourceId, {directoryPathSourceId});
EXPECT_CALL(
projectStorageMock,
synchronize(AllOf(
Field(&SynchronizationPackage::imports, UnorderedElementsAre(import1, import2, import3)),
Field(
&SynchronizationPackage::types,
UnorderedElementsAre(
AllOf(IsStorageType("First.qml",
Storage::Synchronization::ImportedType{"Object"},
TypeTraitsKind::Reference,
qmlDocumentSourceId1,
Storage::Synchronization::ChangeLevel::Full),
Field(&Storage::Synchronization::Type::exportedTypes,
UnorderedElementsAre(IsExportedType(exampleModuleId, "FirstType", 1, 0),
IsExportedType(pathModuleId, "First", -1, -1)))),
AllOf(IsStorageType("First2.qml",
Storage::Synchronization::ImportedType{"Object2"},
TypeTraitsKind::Reference,
qmlDocumentSourceId2,
Storage::Synchronization::ChangeLevel::Full),
Field(&Storage::Synchronization::Type::exportedTypes,
UnorderedElementsAre(IsExportedType(exampleModuleId, "FirstType", 2, 2),
IsExportedType(pathModuleId, "First2", -1, -1)))),
AllOf(IsStorageType("Second.qml",
Storage::Synchronization::ImportedType{"Object3"},
TypeTraitsKind::Reference,
qmlDocumentSourceId3,
Storage::Synchronization::ChangeLevel::Full),
Field(&Storage::Synchronization::Type::exportedTypes,
UnorderedElementsAre(IsExportedType(exampleModuleId, "SecondType", 2, 2),
IsExportedType(pathModuleId, "Second", -1, -1)))))),
Field(&SynchronizationPackage::updatedSourceIds,
UnorderedElementsAre(qmlDocumentSourceId1, qmlDocumentSourceId2, qmlDocumentSourceId3)),
Field(&SynchronizationPackage::directoryInfos,
UnorderedElementsAre(IsDirectoryInfo(directoryPathSourceId,
qmlDocumentSourceId1,
ModuleId{},
FileType::QmlDocument),
IsDirectoryInfo(directoryPathSourceId,
qmlDocumentSourceId2,
ModuleId{},
FileType::QmlDocument),
IsDirectoryInfo(directoryPathSourceId,
qmlDocumentSourceId3,
ModuleId{},
FileType::QmlDocument),
IsDirectoryInfo(rootPathSourceId,
directoryPathSourceId,
ModuleId{},
FileType::Directory))))));
updater.pathsWithIdsChanged({{directoryProjectChunkId, {rootPathSourceId, directoryPathSourceId}}});
}
TEST_F(ProjectStorageUpdater, watcher_updates_removed_directory) TEST_F(ProjectStorageUpdater, watcher_updates_removed_directory)
{ {
setFilesRemoved({directoryPathSourceId, setFilesRemoved({directoryPathSourceId,
@@ -2173,7 +2395,7 @@ TEST_F(ProjectStorageUpdater, watcher_updates_removed_directory)
qmlDocumentSourceId2, qmlDocumentSourceId2,
qmlDocumentSourceId3)), qmlDocumentSourceId3)),
Field(&SynchronizationPackage::fileStatuses, UnorderedElementsAre()), Field(&SynchronizationPackage::fileStatuses, UnorderedElementsAre()),
Field(&SynchronizationPackage::updatedProjectSourceIds, Field(&SynchronizationPackage::updatedDirectoryInfoSourceIds,
UnorderedElementsAre(directoryPathSourceId)), UnorderedElementsAre(directoryPathSourceId)),
Field(&SynchronizationPackage::directoryInfos, IsEmpty())))); Field(&SynchronizationPackage::directoryInfos, IsEmpty()))));
@@ -2275,7 +2497,7 @@ TEST_F(ProjectStorageUpdater, watcher_updates_directories_and_qmldir)
IsFileStatus(qmlDocumentSourceId1, 1, 21), IsFileStatus(qmlDocumentSourceId1, 1, 21),
IsFileStatus(qmlDocumentSourceId2, 1, 21), IsFileStatus(qmlDocumentSourceId2, 1, 21),
IsFileStatus(qmlDocumentSourceId3, 1, 21))), IsFileStatus(qmlDocumentSourceId3, 1, 21))),
Field(&SynchronizationPackage::updatedProjectSourceIds, Field(&SynchronizationPackage::updatedDirectoryInfoSourceIds,
UnorderedElementsAre(directoryPathSourceId)), UnorderedElementsAre(directoryPathSourceId)),
Field(&SynchronizationPackage::directoryInfos, Field(&SynchronizationPackage::directoryInfos,
UnorderedElementsAre(IsDirectoryInfo(directoryPathSourceId, UnorderedElementsAre(IsDirectoryInfo(directoryPathSourceId,
@@ -2372,7 +2594,7 @@ TEST_F(ProjectStorageUpdater, watcher_updates_add_only_qml_document_in_directory
Field(&SynchronizationPackage::fileStatuses, Field(&SynchronizationPackage::fileStatuses,
UnorderedElementsAre(IsFileStatus(qmlDocumentSourceId2, 1, 21), UnorderedElementsAre(IsFileStatus(qmlDocumentSourceId2, 1, 21),
IsFileStatus(directoryPathSourceId, 1, 21))), IsFileStatus(directoryPathSourceId, 1, 21))),
Field(&SynchronizationPackage::updatedProjectSourceIds, Field(&SynchronizationPackage::updatedDirectoryInfoSourceIds,
UnorderedElementsAre(directoryPathSourceId)), UnorderedElementsAre(directoryPathSourceId)),
Field(&SynchronizationPackage::directoryInfos, Field(&SynchronizationPackage::directoryInfos,
UnorderedElementsAre(IsDirectoryInfo(directoryPathSourceId, UnorderedElementsAre(IsDirectoryInfo(directoryPathSourceId,
@@ -2436,7 +2658,7 @@ TEST_F(ProjectStorageUpdater, watcher_updates_removes_qml_document)
UnorderedElementsAre(qmlDirPathSourceId, qmlDocumentSourceId3)), UnorderedElementsAre(qmlDirPathSourceId, qmlDocumentSourceId3)),
Field(&SynchronizationPackage::fileStatuses, Field(&SynchronizationPackage::fileStatuses,
UnorderedElementsAre(IsFileStatus(qmlDirPathSourceId, 1, 21))), UnorderedElementsAre(IsFileStatus(qmlDirPathSourceId, 1, 21))),
Field(&SynchronizationPackage::updatedProjectSourceIds, Field(&SynchronizationPackage::updatedDirectoryInfoSourceIds,
UnorderedElementsAre(directoryPathSourceId)), UnorderedElementsAre(directoryPathSourceId)),
Field(&SynchronizationPackage::directoryInfos, Field(&SynchronizationPackage::directoryInfos,
UnorderedElementsAre(IsDirectoryInfo(directoryPathSourceId, UnorderedElementsAre(IsDirectoryInfo(directoryPathSourceId,
@@ -2491,7 +2713,7 @@ TEST_F(ProjectStorageUpdater, watcher_updates_removes_qml_document_in_qmldir_onl
UnorderedElementsAre(qmlDirPathSourceId)), UnorderedElementsAre(qmlDirPathSourceId)),
Field(&SynchronizationPackage::fileStatuses, Field(&SynchronizationPackage::fileStatuses,
UnorderedElementsAre(IsFileStatus(qmlDirPathSourceId, 1, 21))), UnorderedElementsAre(IsFileStatus(qmlDirPathSourceId, 1, 21))),
Field(&SynchronizationPackage::updatedProjectSourceIds, Field(&SynchronizationPackage::updatedDirectoryInfoSourceIds,
UnorderedElementsAre(directoryPathSourceId)), UnorderedElementsAre(directoryPathSourceId)),
Field(&SynchronizationPackage::directoryInfos, Field(&SynchronizationPackage::directoryInfos,
UnorderedElementsAre(IsDirectoryInfo(directoryPathSourceId, UnorderedElementsAre(IsDirectoryInfo(directoryPathSourceId,
@@ -2549,7 +2771,7 @@ TEST_F(ProjectStorageUpdater, watcher_updates_directories_add_qml_document_to_qm
UnorderedElementsAre(qmlDirPathSourceId)), UnorderedElementsAre(qmlDirPathSourceId)),
Field(&SynchronizationPackage::fileStatuses, Field(&SynchronizationPackage::fileStatuses,
UnorderedElementsAre(IsFileStatus(qmlDirPathSourceId, 1, 21))), UnorderedElementsAre(IsFileStatus(qmlDirPathSourceId, 1, 21))),
Field(&SynchronizationPackage::updatedProjectSourceIds, Field(&SynchronizationPackage::updatedDirectoryInfoSourceIds,
UnorderedElementsAre(directoryPathSourceId)), UnorderedElementsAre(directoryPathSourceId)),
Field(&SynchronizationPackage::directoryInfos, Field(&SynchronizationPackage::directoryInfos,
UnorderedElementsAre(IsDirectoryInfo(directoryPathSourceId, UnorderedElementsAre(IsDirectoryInfo(directoryPathSourceId,
@@ -2604,7 +2826,7 @@ TEST_F(ProjectStorageUpdater, watcher_updates_directories_remove_qml_document_fr
UnorderedElementsAre(qmlDirPathSourceId)), UnorderedElementsAre(qmlDirPathSourceId)),
Field(&SynchronizationPackage::fileStatuses, Field(&SynchronizationPackage::fileStatuses,
UnorderedElementsAre(IsFileStatus(qmlDirPathSourceId, 1, 21))), UnorderedElementsAre(IsFileStatus(qmlDirPathSourceId, 1, 21))),
Field(&SynchronizationPackage::updatedProjectSourceIds, Field(&SynchronizationPackage::updatedDirectoryInfoSourceIds,
UnorderedElementsAre(directoryPathSourceId)), UnorderedElementsAre(directoryPathSourceId)),
Field(&SynchronizationPackage::directoryInfos, Field(&SynchronizationPackage::directoryInfos,
UnorderedElementsAre(IsDirectoryInfo(directoryPathSourceId, UnorderedElementsAre(IsDirectoryInfo(directoryPathSourceId,
@@ -2670,7 +2892,7 @@ TEST_F(ProjectStorageUpdater, watcher_updates_directories_dont_update_qml_docume
IsFileStatus(qmlDocumentSourceId2, 1, 21))), IsFileStatus(qmlDocumentSourceId2, 1, 21))),
Field(&SynchronizationPackage::updatedFileStatusSourceIds, Field(&SynchronizationPackage::updatedFileStatusSourceIds,
UnorderedElementsAre(qmlDirPathSourceId, qmlDocumentSourceId1, qmlDocumentSourceId2)), UnorderedElementsAre(qmlDirPathSourceId, qmlDocumentSourceId1, qmlDocumentSourceId2)),
Field(&SynchronizationPackage::updatedProjectSourceIds, Field(&SynchronizationPackage::updatedDirectoryInfoSourceIds,
UnorderedElementsAre(directoryPathSourceId)), UnorderedElementsAre(directoryPathSourceId)),
Field(&SynchronizationPackage::directoryInfos, Field(&SynchronizationPackage::directoryInfos,
UnorderedElementsAre(IsDirectoryInfo(directoryPathSourceId, UnorderedElementsAre(IsDirectoryInfo(directoryPathSourceId,
@@ -2740,7 +2962,7 @@ TEST_F(ProjectStorageUpdater, watcher_updates_qmldirs_dont_update_qml_documents_
IsFileStatus(qmlDocumentSourceId2, 1, 21))), IsFileStatus(qmlDocumentSourceId2, 1, 21))),
Field(&SynchronizationPackage::updatedFileStatusSourceIds, Field(&SynchronizationPackage::updatedFileStatusSourceIds,
UnorderedElementsAre(qmlDirPathSourceId, qmlDocumentSourceId1, qmlDocumentSourceId2)), UnorderedElementsAre(qmlDirPathSourceId, qmlDocumentSourceId1, qmlDocumentSourceId2)),
Field(&SynchronizationPackage::updatedProjectSourceIds, Field(&SynchronizationPackage::updatedDirectoryInfoSourceIds,
UnorderedElementsAre(directoryPathSourceId)), UnorderedElementsAre(directoryPathSourceId)),
Field(&SynchronizationPackage::directoryInfos, Field(&SynchronizationPackage::directoryInfos,
UnorderedElementsAre(IsDirectoryInfo(directoryPathSourceId, UnorderedElementsAre(IsDirectoryInfo(directoryPathSourceId,
@@ -3053,7 +3275,7 @@ TEST_F(ProjectStorageUpdater, watcher_updates_directories_and_but_not_included_q
IsFileStatus(qmlDocumentSourceId1, 1, 21), IsFileStatus(qmlDocumentSourceId1, 1, 21),
IsFileStatus(qmlDocumentSourceId2, 1, 21), IsFileStatus(qmlDocumentSourceId2, 1, 21),
IsFileStatus(qmlDocumentSourceId3, 1, 21))), IsFileStatus(qmlDocumentSourceId3, 1, 21))),
Field(&SynchronizationPackage::updatedProjectSourceIds, Field(&SynchronizationPackage::updatedDirectoryInfoSourceIds,
UnorderedElementsAre(directoryPathSourceId)), UnorderedElementsAre(directoryPathSourceId)),
Field(&SynchronizationPackage::directoryInfos, Field(&SynchronizationPackage::directoryInfos,
UnorderedElementsAre(IsDirectoryInfo(directoryPathSourceId, UnorderedElementsAre(IsDirectoryInfo(directoryPathSourceId,
@@ -3130,7 +3352,7 @@ TEST_F(ProjectStorageUpdater, watcher_updates_qmldir_and_but_not_included_qml_do
IsFileStatus(qmlDocumentSourceId1, 1, 21), IsFileStatus(qmlDocumentSourceId1, 1, 21),
IsFileStatus(qmlDocumentSourceId2, 1, 21), IsFileStatus(qmlDocumentSourceId2, 1, 21),
IsFileStatus(qmlDocumentSourceId3, 1, 21))), IsFileStatus(qmlDocumentSourceId3, 1, 21))),
Field(&SynchronizationPackage::updatedProjectSourceIds, Field(&SynchronizationPackage::updatedDirectoryInfoSourceIds,
UnorderedElementsAre(directoryPathSourceId)), UnorderedElementsAre(directoryPathSourceId)),
Field(&SynchronizationPackage::directoryInfos, Field(&SynchronizationPackage::directoryInfos,
UnorderedElementsAre(IsDirectoryInfo(directoryPathSourceId, UnorderedElementsAre(IsDirectoryInfo(directoryPathSourceId,
@@ -3229,7 +3451,7 @@ TEST_F(ProjectStorageUpdater, watcher_updates_qmldir_and_but_not_included_qmltyp
IsFileStatus(qmlDocumentSourceId1, 1, 21), IsFileStatus(qmlDocumentSourceId1, 1, 21),
IsFileStatus(qmlDocumentSourceId2, 1, 21), IsFileStatus(qmlDocumentSourceId2, 1, 21),
IsFileStatus(qmlDocumentSourceId3, 1, 21))), IsFileStatus(qmlDocumentSourceId3, 1, 21))),
Field(&SynchronizationPackage::updatedProjectSourceIds, Field(&SynchronizationPackage::updatedDirectoryInfoSourceIds,
UnorderedElementsAre(directoryPathSourceId)), UnorderedElementsAre(directoryPathSourceId)),
Field(&SynchronizationPackage::directoryInfos, Field(&SynchronizationPackage::directoryInfos,
UnorderedElementsAre(IsDirectoryInfo(directoryPathSourceId, UnorderedElementsAre(IsDirectoryInfo(directoryPathSourceId,