forked from qt-creator/qt-creator
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:
committed by
Thomas Hartmann
parent
48b65e32c8
commit
8862233fb8
@@ -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)
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
@@ -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));
|
||||
|
@@ -1331,7 +1331,7 @@ public:
|
||||
ModuleExportedImports moduleExportedImports;
|
||||
ModuleIds updatedModuleIds;
|
||||
PropertyEditorQmlPaths propertyEditorQmlPaths;
|
||||
SourceContextIds updatedPropertyEditorQmlPathSourceContextIds;
|
||||
SourceContextIds updatedPropertyEditorQmlPathDirectoryIds;
|
||||
TypeAnnotations typeAnnotations;
|
||||
SourceIds updatedTypeAnnotationSourceIds;
|
||||
};
|
||||
|
@@ -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 ¬UpdatedSourceIds,
|
||||
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 ¬UpdatedSourceIds)
|
||||
{
|
||||
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 ¬UpdatedSourceIds)
|
||||
{
|
||||
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 ¬UpdatedSourceIds)
|
||||
{
|
||||
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
|
||||
|
@@ -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 ¬UpdatedSourceIds,
|
||||
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 ¬UpdatedSourceIds,
|
||||
WatchedSourceIdsIds &watchedSourceIdsIds,
|
||||
ProjectStorageTracing::Category::TracerType &tracer);
|
||||
|
||||
void annotationDirectoryChanged(Utils::SmallStringView directoryPath,
|
||||
SourceContextId directoryId,
|
||||
SourceContextId annotationDirectoryId,
|
||||
ModuleId moduleId,
|
||||
Storage::Synchronization::SynchronizationPackage &package,
|
||||
NotUpdatedSourceIds ¬UpdatedSourceIds);
|
||||
void updatePropertyEditorFiles(Utils::SmallStringView directyPath,
|
||||
SourceContextId directoryId,
|
||||
ModuleId moduleId,
|
||||
Storage::Synchronization::SynchronizationPackage &package,
|
||||
NotUpdatedSourceIds ¬UpdatedSourceIds);
|
||||
void updatePropertyEditorFile(const QString &fileName,
|
||||
SourceContextId directoryId,
|
||||
ModuleId moduleId,
|
||||
Storage::Synchronization::SynchronizationPackage &package,
|
||||
NotUpdatedSourceIds ¬UpdatedSourceIds);
|
||||
void updatePropertyEditorPaths(const QString &propertyEditorResourcesPath,
|
||||
Storage::Synchronization::SynchronizationPackage &package,
|
||||
NotUpdatedSourceIds ¬UpdatedSourceIds);
|
||||
|
@@ -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));
|
||||
|
@@ -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)
|
||||
|
@@ -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);
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
|
Reference in New Issue
Block a user