QmlDesigner: Add exported type name notification

If an exported type name will be updated, the notifier will put it into
removed and added. That can anyway happen if the module is moved with a time difference.

Task-number: QDS-14669
Change-Id: I5ede7ce8edc8c02056bea35f27d266379bae044c
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
Marco Bubke
2025-03-31 18:06:23 +02:00
committed by Thomas Hartmann
parent 5abeb01ca2
commit 4fdf1522ff
17 changed files with 255 additions and 96 deletions

View File

@@ -155,6 +155,9 @@ public:
virtual void modelAboutToBeDetached(Model *model);
virtual void refreshMetaInfos(const TypeIds &deletedTypeIds);
using ExportedTypeNames = Storage::Info::ExportedTypeNames;
virtual void exportedTypeNamesChanged(const ExportedTypeNames &added,
const ExportedTypeNames &removed);
virtual void nodeCreated(const ModelNode &createdNode);
virtual void nodeAboutToBeRemoved(const ModelNode &removedNode);

View File

@@ -177,6 +177,8 @@ void AbstractView::modelAboutToBeDetached(Model *)
void AbstractView::refreshMetaInfos(const TypeIds &) {}
void AbstractView::exportedTypeNamesChanged(const ExportedTypeNames &, const ExportedTypeNames &) {}
/*!
\enum QmlDesigner::AbstractView::PropertyChangeFlag

View File

@@ -474,6 +474,13 @@ void ModelPrivate::exportedTypesChanged()
}
}
void ModelPrivate::exportedTypeNamesChanged(const ExportedTypeNames &added,
const ExportedTypeNames &removed)
{
notifyNodeInstanceViewLast(
[&](AbstractView *view) { view->exportedTypeNamesChanged(added, removed); });
}
void ModelPrivate::removeAllSubNodes(const InternalNodePointer &node)
{
for (const InternalNodePointer &subNode : node->allSubNodes())

View File

@@ -326,6 +326,8 @@ public:
protected:
void removedTypeIds(const TypeIds &removedTypeIds) override;
void exportedTypesChanged() override;
void exportedTypeNamesChanged(const ExportedTypeNames &added,
const ExportedTypeNames &removed) override;
void removeNode(const InternalNodePointer &node);
private:

View File

@@ -107,14 +107,20 @@ struct ProjectStorage::Statements
"defaultPropertyId=propertyDeclarationId "
"WHERE t.typeId=?",
database};
mutable Sqlite::ReadStatement<4, 1> selectExportedTypesByTypeIdStatement{
"SELECT moduleId, name, ifnull(majorVersion, -1), ifnull(minorVersion, -1) FROM "
"exportedTypeNames WHERE typeId=?",
mutable Sqlite::ReadStatement<5, 1> selectExportedTypesByTypeIdStatement{
"SELECT moduleId, typeId, name, ifnull(majorVersion, -1), ifnull(minorVersion, -1) "
"FROM exportedTypeNames "
"WHERE typeId=?",
database};
mutable Sqlite::ReadStatement<4, 2> selectExportedTypesByTypeIdAndSourceIdStatement{
"SELECT etn.moduleId, name, ifnull(etn.majorVersion, -1), ifnull(etn.minorVersion, -1) "
"FROM exportedTypeNames AS etn JOIN documentImports USING(moduleId) WHERE typeId=?1 AND "
"sourceId=?2",
mutable Sqlite::ReadStatement<5, 2> selectExportedTypesByTypeIdAndSourceIdStatement{
"SELECT etn.moduleId, "
" typeId, "
" name, "
" ifnull(etn.majorVersion, -1), "
" ifnull(etn.minorVersion, -1) "
"FROM exportedTypeNames AS etn "
"JOIN documentImports USING(moduleId) "
"WHERE typeId=?1 AND sourceId=?2",
database};
mutable Sqlite::ReadStatement<8> selectTypesStatement{
"SELECT sourceId, t.name, t.typeId, prototypeId, extensionId, traits, annotationTraits, "
@@ -1298,6 +1304,8 @@ void ProjectStorage::synchronize(Storage::Synchronization::SynchronizationPackag
NanotraceHR::Tracer tracer{"synchronize", projectStorageCategory()};
TypeIds deletedTypeIds;
Storage::Info::ExportedTypeNames removedExportedTypeNames;
Storage::Info::ExportedTypeNames addedExportedTypeNames;
ExportedTypesChanged exportedTypesChanged = ExportedTypesChanged::No;
Sqlite::withImmediateTransaction(database, [&] {
@@ -1332,6 +1340,8 @@ void ProjectStorage::synchronize(Storage::Synchronization::SynchronizationPackag
relinkablePrototypes,
relinkableExtensions,
exportedTypesChanged,
removedExportedTypeNames,
addedExportedTypeNames,
package.updatedSourceIds);
synchronizeTypeAnnotations(package.typeAnnotations, package.updatedTypeAnnotationSourceIds);
synchronizePropertyEditorQmlPaths(package.propertyEditorQmlPaths,
@@ -1361,7 +1371,10 @@ void ProjectStorage::synchronize(Storage::Synchronization::SynchronizationPackag
commonTypeCache_.resetTypeIds();
});
callRefreshMetaInfoCallback(deletedTypeIds, exportedTypesChanged);
callRefreshMetaInfoCallback(deletedTypeIds,
exportedTypesChanged,
removedExportedTypeNames,
addedExportedTypeNames);
}
void ProjectStorage::synchronizeDocumentImports(Storage::Imports imports, SourceId sourceId)
@@ -2348,8 +2361,11 @@ ProjectStorage::ModuleCacheEntries ProjectStorage::fetchAllModules() const
return s->selectAllModulesStatement.valuesWithTransaction<ModuleCacheEntry, 128>();
}
void ProjectStorage::callRefreshMetaInfoCallback(TypeIds &deletedTypeIds,
ExportedTypesChanged &exportedTypesChanged)
void ProjectStorage::callRefreshMetaInfoCallback(
TypeIds &deletedTypeIds,
ExportedTypesChanged exportedTypesChanged,
const Storage::Info::ExportedTypeNames &removedExportedTypeNames,
const Storage::Info::ExportedTypeNames &addedExportedTypeNames)
{
using NanotraceHR::keyValue;
NanotraceHR::Tracer tracer{"call refresh meta info callback",
@@ -2364,8 +2380,10 @@ void ProjectStorage::callRefreshMetaInfoCallback(TypeIds &deletedTypeIds,
}
if (exportedTypesChanged == ExportedTypesChanged::Yes) {
for (ProjectStorageObserver *observer : observers)
for (ProjectStorageObserver *observer : observers) {
observer->exportedTypesChanged();
observer->exportedTypeNamesChanged(addedExportedTypeNames, removedExportedTypeNames);
}
}
}
@@ -2428,7 +2446,6 @@ void ProjectStorage::synchronizeTypeAnnotations(Storage::Synchronization::TypeAn
{
NanotraceHR::Tracer tracer{"synchronize type annotations", projectStorageCategory()};
updateTypeIdInTypeAnnotations(typeAnnotations);
auto compareKey = [](auto &&first, auto &&second) { return first.typeId <=> second.typeId; };
@@ -2522,6 +2539,8 @@ void ProjectStorage::synchronizeTypes(Storage::Synchronization::Types &types,
Prototypes &relinkablePrototypes,
Prototypes &relinkableExtensions,
ExportedTypesChanged &exportedTypesChanged,
Storage::Info::ExportedTypeNames &removedExportedTypeNames,
Storage::Info::ExportedTypeNames &addedExportedTypeNames,
const SourceIds &updatedSourceIds)
{
NanotraceHR::Tracer tracer{"synchronize types", projectStorageCategory()};
@@ -2564,7 +2583,9 @@ void ProjectStorage::synchronizeTypes(Storage::Synchronization::Types &types,
relinkablePropertyDeclarations,
relinkablePrototypes,
relinkableExtensions,
exportedTypesChanged);
exportedTypesChanged,
removedExportedTypeNames,
addedExportedTypeNames);
syncPrototypesAndExtensions(types, relinkablePrototypes, relinkableExtensions);
resetDefaultPropertiesIfChanged(types);
@@ -3299,17 +3320,23 @@ void ProjectStorage::repairBrokenAliasPropertyDeclarations()
linkAliases(brokenAliasPropertyDeclarations, RaiseError::No);
}
void ProjectStorage::synchronizeExportedTypes(const TypeIds &updatedTypeIds,
void ProjectStorage::synchronizeExportedTypes(
const TypeIds &updatedTypeIds,
Storage::Synchronization::ExportedTypes &exportedTypes,
AliasPropertyDeclarations &relinkableAliasPropertyDeclarations,
PropertyDeclarations &relinkablePropertyDeclarations,
Prototypes &relinkablePrototypes,
Prototypes &relinkableExtensions,
ExportedTypesChanged &exportedTypesChanged)
ExportedTypesChanged &exportedTypesChanged,
Storage::Info::ExportedTypeNames &removedExportedTypeNames,
Storage::Info::ExportedTypeNames &addedExportedTypeNames)
{
using NanotraceHR::keyValue;
NanotraceHR::Tracer tracer{"synchronize exported types", projectStorageCategory()};
removedExportedTypeNames.reserve(exportedTypes.size());
addedExportedTypeNames.reserve(exportedTypes.size());
std::ranges::sort(exportedTypes, [](auto &&first, auto &&second) {
if (first.moduleId < second.moduleId)
return true;
@@ -3376,6 +3403,8 @@ void ProjectStorage::synchronizeExportedTypes(const TypeIds &updatedTypeIds,
handlePrototypesWithExportedTypeNameAndTypeId(type.name, unresolvedTypeId, relinkablePrototypes);
handleExtensionsWithExportedTypeNameAndTypeId(type.name, unresolvedTypeId, relinkableExtensions);
addedExportedTypeNames.emplace_back(type.moduleId, type.typeId, type.name, type.version);
exportedTypesChanged = ExportedTypesChanged::Yes;
};
@@ -3397,6 +3426,9 @@ void ProjectStorage::synchronizeExportedTypes(const TypeIds &updatedTypeIds,
s->updateExportedTypeNameTypeIdStatement.write(view.exportedTypeNameId, type.typeId);
exportedTypesChanged = ExportedTypesChanged::Yes;
addedExportedTypeNames.emplace_back(type.moduleId, type.typeId, type.name, type.version);
removedExportedTypeNames.emplace_back(view.moduleId, view.typeId, view.name, view.version);
return Sqlite::UpdateChange::Update;
}
return Sqlite::UpdateChange::No;
@@ -3417,6 +3449,8 @@ void ProjectStorage::synchronizeExportedTypes(const TypeIds &updatedTypeIds,
s->deleteExportedTypeNameStatement.write(view.exportedTypeNameId);
removedExportedTypeNames.emplace_back(view.moduleId, view.typeId, view.name, view.version);
exportedTypesChanged = ExportedTypesChanged::Yes;
};

View File

@@ -325,7 +325,9 @@ private:
enum class ExportedTypesChanged { No, Yes };
void callRefreshMetaInfoCallback(TypeIds &deletedTypeIds,
ExportedTypesChanged &exportedTypesChanged);
ExportedTypesChanged exportedTypesChanged,
const Storage::Info::ExportedTypeNames &removedExportedTypeNames,
const Storage::Info::ExportedTypeNames &addedExportedTypeNames);
class AliasPropertyDeclaration
{
@@ -565,6 +567,8 @@ private:
Prototypes &relinkablePrototypes,
Prototypes &relinkableExtensions,
ExportedTypesChanged &exportedTypesChanged,
Storage::Info::ExportedTypeNames &removedExportedTypeNames,
Storage::Info::ExportedTypeNames &addedExportedTypeNames,
const SourceIds &updatedSourceIds);
void synchronizeDirectoryInfos(Storage::Synchronization::DirectoryInfos &directoryInfos,
@@ -666,7 +670,9 @@ private:
PropertyDeclarations &relinkablePropertyDeclarations,
Prototypes &relinkablePrototypes,
Prototypes &relinkableExtensions,
ExportedTypesChanged &exportedTypesChanged);
ExportedTypesChanged &exportedTypesChanged,
Storage::Info::ExportedTypeNames &removedExportedTypeNames,
Storage::Info::ExportedTypeNames &addedExportedTypeNames);
void synchronizePropertyDeclarationsInsertAlias(
AliasPropertyDeclarations &insertedAliasPropertyDeclarations,

View File

@@ -257,20 +257,7 @@ public:
explicit operator bool() const { return value >= 0; }
friend bool operator==(VersionNumber first, VersionNumber second) noexcept
{
return first.value == second.value;
}
friend bool operator!=(VersionNumber first, VersionNumber second) noexcept
{
return !(first == second);
}
friend bool operator<(VersionNumber first, VersionNumber second) noexcept
{
return first.value < second.value;
}
auto operator<=>(const VersionNumber &first) const noexcept = default;
public:
int value = -1;
@@ -294,15 +281,7 @@ public:
: major{major}
{}
friend bool operator==(Version first, Version second) noexcept
{
return first.major == second.major && first.minor == second.minor;
}
friend bool operator<(Version first, Version second) noexcept
{
return std::tie(first.major, first.minor) < std::tie(second.major, second.minor);
}
auto operator<=>(const Version &first) const noexcept = default;
explicit operator bool() const { return major && minor; }
@@ -470,32 +449,36 @@ public:
ExportedTypeName() = default;
ExportedTypeName(ModuleId moduleId,
TypeId typeId,
::Utils::SmallStringView name,
Storage::Version version = Storage::Version{})
: name{name}
, version{version}
, moduleId{moduleId}
, typeId{typeId}
{}
ExportedTypeName(ModuleId moduleId,
TypeId typeId,
::Utils::SmallStringView name,
int majorVersion,
int minorVersion)
: name{name}
, version{majorVersion, minorVersion}
, moduleId{moduleId}
, typeId{typeId}
{}
friend bool operator==(const ExportedTypeName &first, const ExportedTypeName &second)
{
return first.moduleId == second.moduleId && first.version == second.version
&& first.name == second.name;
return first.moduleId == second.moduleId && first.typeId == second.typeId
&& first.version == second.version && first.name == second.name;
}
friend bool operator<(const ExportedTypeName &first, const ExportedTypeName &second)
friend auto operator<=>(const ExportedTypeName &first, const ExportedTypeName &second)
{
return std::tie(first.moduleId, first.name, first.version)
< std::tie(second.moduleId, second.name, second.version);
return std::tie(first.moduleId, first.name, first.version, second.typeId)
<=> std::tie(second.moduleId, second.name, second.version, second.typeId);
}
template<typename String>
@@ -505,7 +488,8 @@ public:
using NanotraceHR::keyValue;
auto dict = dictonary(keyValue("name", exportedTypeName.name),
keyValue("version", exportedTypeName.version),
keyValue("module id", exportedTypeName.moduleId));
keyValue("module id", exportedTypeName.moduleId),
keyValue("type id", exportedTypeName.typeId));
convertToString(string, dict);
}
@@ -514,6 +498,7 @@ public:
::Utils::SmallString name;
Storage::Version version;
ModuleId moduleId;
TypeId typeId;
};
using ExportedTypeNames = std::vector<ExportedTypeName>;

View File

@@ -4,13 +4,17 @@
#pragma once
#include "projectstorageids.h"
#include "projectstorageinfotypes.h"
namespace QmlDesigner {
class ProjectStorageObserver
{
public:
using ExportedTypeNames = Storage::Info::ExportedTypeNames;
virtual void removedTypeIds(const TypeIds &removedTypeIds) = 0;
virtual void exportedTypesChanged() = 0;
virtual void exportedTypeNamesChanged(const ExportedTypeNames &added, const ExportedTypeNames &removed) = 0;
};
} // namespace QmlDesigner

View File

@@ -393,11 +393,13 @@ public:
{}
explicit ExportedType(ModuleId moduleId,
TypeId typeId,
::Utils::SmallStringView name,
int majorVersion,
int minorVersion)
: name{name}
, version{majorVersion, minorVersion}
, typeId{typeId}
, moduleId{moduleId}
{}

View File

@@ -7,27 +7,43 @@
#include <projectstorage/projectstorageinfotypes.h>
template<typename ModuleIdMatcher,
typename NameMatcher,
typename MajorVersionMatcher,
typename MinorVersionMatcher>
auto IsInfoExportTypeNames(const ModuleIdMatcher &moduleIdMatcher,
template<typename ModuleIdMatcher, typename TypeIdMatcher, typename NameMatcher, typename MajorVersionMatcher, typename MinorVersionMatcher>
auto IsInfoExportTypeName(const ModuleIdMatcher &moduleIdMatcher,
const TypeIdMatcher &typeIdMatcher,
const NameMatcher &nameMatcher,
const MajorVersionMatcher &majorVersionMatcher,
const MinorVersionMatcher &minorVersionMatcher)
{
return AllOf(Field("QmlDesigner::Storage::Info::ExportedTypeName::moduleId", &QmlDesigner::Storage::Info::ExportedTypeName::moduleId, moduleIdMatcher),
Field("QmlDesigner::Storage::Info::ExportedTypeName::name", &QmlDesigner::Storage::Info::ExportedTypeName::name, nameMatcher),
Field("QmlDesigner::Storage::Info::ExportedTypeName::version", &QmlDesigner::Storage::Info::ExportedTypeName::version,
return AllOf(Field("QmlDesigner::Storage::Info::ExportedTypeName::moduleId",
&QmlDesigner::Storage::Info::ExportedTypeName::moduleId,
moduleIdMatcher),
Field("QmlDesigner::Storage::Info::ExportedTypeName::typeId",
&QmlDesigner::Storage::Info::ExportedTypeName::typeId,
typeIdMatcher),
Field("QmlDesigner::Storage::Info::ExportedTypeName::name",
&QmlDesigner::Storage::Info::ExportedTypeName::name,
nameMatcher),
Field("QmlDesigner::Storage::Info::ExportedTypeName::version",
&QmlDesigner::Storage::Info::ExportedTypeName::version,
IsVersion(majorVersionMatcher, minorVersionMatcher)));
}
template<typename ModuleIdMatcher, typename NameMatcher, typename VersionMatcher>
auto IsInfoExportTypeNames(const ModuleIdMatcher &moduleIdMatcher,
template<typename ModuleIdMatcher, typename TypeIdMatcher, typename NameMatcher, typename VersionMatcher>
auto IsInfoExportTypeName(const ModuleIdMatcher &moduleIdMatcher,
const TypeIdMatcher &typeIdMatcher,
const NameMatcher &nameMatcher,
const VersionMatcher &versionMatcher)
{
return AllOf(Field("QmlDesigner::Storage::Info::ExportedTypeName::moduleId", &QmlDesigner::Storage::Info::ExportedTypeName::moduleId, moduleIdMatcher),
Field("QmlDesigner::Storage::Info::ExportedTypeName::name", &QmlDesigner::Storage::Info::ExportedTypeName::name, nameMatcher),
Field("QmlDesigner::Storage::Info::ExportedTypeName::version", &QmlDesigner::Storage::Info::ExportedTypeName::version, versionMatcher));
return AllOf(Field("QmlDesigner::Storage::Info::ExportedTypeName::moduleId",
&QmlDesigner::Storage::Info::ExportedTypeName::moduleId,
moduleIdMatcher),
Field("QmlDesigner::Storage::Info::ExportedTypeName::typeId",
&QmlDesigner::Storage::Info::ExportedTypeName::typeId,
typeIdMatcher),
Field("QmlDesigner::Storage::Info::ExportedTypeName::name",
&QmlDesigner::Storage::Info::ExportedTypeName::name,
nameMatcher),
Field("QmlDesigner::Storage::Info::ExportedTypeName::version",
&QmlDesigner::Storage::Info::ExportedTypeName::version,
versionMatcher));
}

View File

@@ -65,6 +65,10 @@ public:
(override));
MOCK_METHOD(void, nodeAboutToBeRemoved, (const QmlDesigner::ModelNode &removedNode), (override));
MOCK_METHOD(void, refreshMetaInfos, (const QmlDesigner::TypeIds &), (override));
MOCK_METHOD(void,
exportedTypeNamesChanged,
(const ExportedTypeNames &added, const ExportedTypeNames &removed),
(override));
MOCK_METHOD(void, modelAttached, (QmlDesigner::Model *), (override));
MOCK_METHOD(void, modelAboutToBeDetached, (QmlDesigner::Model *), (override));

View File

@@ -128,7 +128,7 @@ void ProjectStorageMock::addExportedTypeName(QmlDesigner::TypeId typeId,
ON_CALL(*this, typeId(Eq(moduleId), Eq(typeName), _)).WillByDefault(Return(typeId));
ON_CALL(*this, fetchTypeIdByModuleIdAndExportedName(Eq(moduleId), Eq(typeName)))
.WillByDefault(Return(typeId));
exportedTypeName[typeId].emplace_back(moduleId, typeName);
exportedTypeName[typeId].emplace_back(moduleId, typeId, typeName);
}
void ProjectStorageMock::addExportedTypeNameBySourceId(QmlDesigner::TypeId typeId,
@@ -136,7 +136,7 @@ void ProjectStorageMock::addExportedTypeNameBySourceId(QmlDesigner::TypeId typeI
Utils::SmallStringView typeName,
QmlDesigner::SourceId sourceId)
{
exportedTypeNameBySourceId[{typeId, sourceId}].emplace_back(moduleId, typeName);
exportedTypeNameBySourceId[{typeId, sourceId}].emplace_back(moduleId, typeId, typeName);
}
void ProjectStorageMock::removeExportedTypeName(QmlDesigner::TypeId typeId,

View File

@@ -12,4 +12,8 @@ class ProjectStorageObserverMock : public QmlDesigner::ProjectStorageObserver
public:
MOCK_METHOD(void, removedTypeIds, (const QmlDesigner::TypeIds &), (override));
MOCK_METHOD(void, exportedTypesChanged, (), (override));
MOCK_METHOD(void,
exportedTypeNamesChanged,
(const ExportedTypeNames &added, const ExportedTypeNames &removed),
(override));
};

View File

@@ -751,7 +751,8 @@ std::ostream &operator<<(std::ostream &out, const Type &type)
std::ostream &operator<<(std::ostream &out, const ExportedTypeName &name)
{
return out << "(\"" << name.name << "\", " << name.moduleId << ", " << name.version << ")";
return out << "(\"" << name.name << "\", " << name.moduleId << ", " << name.version << ", "
<< name.typeId << ")";
}
std::ostream &operator<<(std::ostream &out, const TypeHint &hint)

View File

@@ -2624,23 +2624,23 @@ TEST_F(NodeMetaInfo, default_is_not_enumeration)
TEST_F(NodeMetaInfo, all_external_type_names)
{
QmlDesigner::Storage::Info::ExportedTypeNames names{{qmlModuleId, "Object", 2, -1},
{qmlModuleId, "Obj", 2, 1}};
auto metaInfo = createMetaInfo("QML", ModuleKind::QmlLibrary, "Foo");
QmlDesigner::Storage::Info::ExportedTypeNames names{{qmlModuleId, metaInfo.id(), "Object", 2, -1},
{qmlModuleId, metaInfo.id(), "Obj", 2, 1}};
ON_CALL(projectStorageMock, exportedTypeNames(metaInfo.id())).WillByDefault(Return(names));
auto exportedTypeNames = metaInfo.allExportedTypeNames();
ASSERT_THAT(exportedTypeNames,
UnorderedElementsAre(IsInfoExportTypeNames(qmlModuleId, "Object", 2, -1),
IsInfoExportTypeNames(qmlModuleId, "Obj", 2, 1)));
UnorderedElementsAre(IsInfoExportTypeName(qmlModuleId, metaInfo.id(), "Object", 2, -1),
IsInfoExportTypeName(qmlModuleId, metaInfo.id(), "Obj", 2, 1)));
}
TEST_F(NodeMetaInfo, default_has_no_external_type_names)
{
QmlDesigner::Storage::Info::ExportedTypeNames names{{qmlModuleId, "Object", 2, -1},
{qmlModuleId, "Obj", 2, 1}};
QmlDesigner::NodeMetaInfo metaInfo;
QmlDesigner::Storage::Info::ExportedTypeNames names{{qmlModuleId, metaInfo.id(), "Object", 2, -1},
{qmlModuleId, metaInfo.id(), "Obj", 2, 1}};
ON_CALL(projectStorageMock, exportedTypeNames(_)).WillByDefault(Return(names));
auto exportedTypeNames = metaInfo.allExportedTypeNames();
@@ -2650,24 +2650,24 @@ TEST_F(NodeMetaInfo, default_has_no_external_type_names)
TEST_F(NodeMetaInfo, external_type_names_for_source_id)
{
QmlDesigner::Storage::Info::ExportedTypeNames names{{qmlModuleId, "Object", 2, -1},
{qmlModuleId, "Obj", 2, 1}};
auto metaInfo = createMetaInfo("QML", ModuleKind::QmlLibrary, "Foo");
QmlDesigner::Storage::Info::ExportedTypeNames names{{qmlModuleId, metaInfo.id(), "Object", 2, -1},
{qmlModuleId, metaInfo.id(), "Obj", 2, 1}};
ON_CALL(projectStorageMock, exportedTypeNames(metaInfo.id(), model.fileUrlSourceId()))
.WillByDefault(Return(names));
auto exportedTypeNames = metaInfo.exportedTypeNamesForSourceId(model.fileUrlSourceId());
ASSERT_THAT(exportedTypeNames,
UnorderedElementsAre(IsInfoExportTypeNames(qmlModuleId, "Object", 2, -1),
IsInfoExportTypeNames(qmlModuleId, "Obj", 2, 1)));
UnorderedElementsAre(IsInfoExportTypeName(qmlModuleId, metaInfo.id(), "Object", 2, -1),
IsInfoExportTypeName(qmlModuleId, metaInfo.id(), "Obj", 2, 1)));
}
TEST_F(NodeMetaInfo, default_has_no_external_type_names_for_source_id)
{
QmlDesigner::Storage::Info::ExportedTypeNames names{{qmlModuleId, "Object", 2, -1},
{qmlModuleId, "Obj", 2, 1}};
QmlDesigner::NodeMetaInfo metaInfo;
QmlDesigner::Storage::Info::ExportedTypeNames names{{qmlModuleId, metaInfo.id(), "Object", 2, -1},
{qmlModuleId, metaInfo.id(), "Obj", 2, 1}};
ON_CALL(projectStorageMock, exportedTypeNames(metaInfo.id(), model.fileUrlSourceId()))
.WillByDefault(Return(names));
@@ -2678,9 +2678,9 @@ TEST_F(NodeMetaInfo, default_has_no_external_type_names_for_source_id)
TEST_F(NodeMetaInfo, invalid_source_id_has_no_external_type_names_for_source_id)
{
QmlDesigner::Storage::Info::ExportedTypeNames names{{qmlModuleId, "Object", 2, -1},
{qmlModuleId, "Obj", 2, 1}};
auto metaInfo = createMetaInfo("QML", ModuleKind::QmlLibrary, "Foo");
QmlDesigner::Storage::Info::ExportedTypeNames names{{qmlModuleId, metaInfo.id(), "Object", 2, -1},
{qmlModuleId, metaInfo.id(), "Obj", 2, 1}};
ON_CALL(projectStorageMock, exportedTypeNames(metaInfo.id(), model.fileUrlSourceId()))
.WillByDefault(Return(names));
QmlDesigner::SourceId sourceId;

View File

@@ -1141,14 +1141,13 @@ TEST_F(Model_MetaInfo, remove_project_storage_observer_from_project_storage)
QmlDesigner::Model model{{projectStorageMock, pathCacheMock}, "Item", -1, -1, nullptr, {}};
}
TEST_F(Model_MetaInfo, refresh_callback_is_calling_abstract_view)
TEST_F(Model_MetaInfo, refresh_meta_infos_callback_is_calling_abstract_view)
{
const QmlDesigner::TypeIds typeIds = {QmlDesigner::TypeId::create(3),
QmlDesigner::TypeId::create(1)};
ProjectStorageObserverMock observerMock;
QmlDesigner::ProjectStorageObserver *observer = nullptr;
ON_CALL(projectStorageMock, addObserver(_)).WillByDefault([&](auto *o) { observer = o; });
QmlDesigner::Model model{{projectStorageMock, pathCacheMock}, "Item", -1, -1, nullptr, {}};
model.attachView(&viewMock);
@@ -1157,6 +1156,36 @@ TEST_F(Model_MetaInfo, refresh_callback_is_calling_abstract_view)
observer->removedTypeIds(typeIds);
}
TEST_F(Model_MetaInfo, added_exported_type_names_are_changed_callback_is_calling_abstract_view)
{
using QmlDesigner::Storage::Info::ExportedTypeNames;
ExportedTypeNames added = {{qtQuickModuleId, itemTypeId, "Foo", 1, 1}};
ProjectStorageObserverMock observerMock;
QmlDesigner::ProjectStorageObserver *observer = nullptr;
ON_CALL(projectStorageMock, addObserver(_)).WillByDefault([&](auto *o) { observer = o; });
QmlDesigner::Model model{{projectStorageMock, pathCacheMock}, "Item", -1, -1, nullptr, {}};
model.attachView(&viewMock);
EXPECT_CALL(viewMock, exportedTypeNamesChanged(added, IsEmpty()));
observer->exportedTypeNamesChanged(added, {});
}
TEST_F(Model_MetaInfo, removed_exported_type_names_are_changed_callback_is_calling_abstract_view)
{
using QmlDesigner::Storage::Info::ExportedTypeNames;
ExportedTypeNames removed = {{qtQuickModuleId, itemTypeId, "Foo", 1, 1}};
ProjectStorageObserverMock observerMock;
QmlDesigner::ProjectStorageObserver *observer = nullptr;
ON_CALL(projectStorageMock, addObserver(_)).WillByDefault([&](auto *o) { observer = o; });
QmlDesigner::Model model{{projectStorageMock, pathCacheMock}, "Item", -1, -1, nullptr, {}};
model.attachView(&viewMock);
EXPECT_CALL(viewMock, exportedTypeNamesChanged(IsEmpty(), removed));
observer->exportedTypeNamesChanged({}, removed);
}
TEST_F(Model_MetaInfo, meta_infos_for_mdoule)
{
projectStorageMock.createModule("Foo", ModuleKind::QmlLibrary);

View File

@@ -8189,9 +8189,9 @@ TEST_F(ProjectStorage, get_exported_type_names)
auto exportedTypeNames = storage.exportedTypeNames(typeId);
ASSERT_THAT(exportedTypeNames,
UnorderedElementsAre(IsInfoExportTypeNames(qmlModuleId, "Object", 2, -1),
IsInfoExportTypeNames(qmlModuleId, "Obj", 2, -1),
IsInfoExportTypeNames(qmlNativeModuleId, "QObject", -1, -1)));
UnorderedElementsAre(IsInfoExportTypeName(qmlModuleId, typeId, "Object", 2, -1),
IsInfoExportTypeName(qmlModuleId, typeId, "Obj", 2, -1),
IsInfoExportTypeName(qmlNativeModuleId, typeId, "QObject", -1, -1)));
}
TEST_F(ProjectStorage, get_no_exported_type_names_if_type_id_is_invalid)
@@ -8215,8 +8215,8 @@ TEST_F(ProjectStorage, get_exported_type_names_for_source_id)
auto exportedTypeNames = storage.exportedTypeNames(typeId, sourceId3);
ASSERT_THAT(exportedTypeNames,
UnorderedElementsAre(IsInfoExportTypeNames(qmlModuleId, "Object", 2, -1),
IsInfoExportTypeNames(qmlModuleId, "Obj", 2, -1)));
UnorderedElementsAre(IsInfoExportTypeName(qmlModuleId, typeId, "Object", 2, -1),
IsInfoExportTypeName(qmlModuleId, typeId, "Obj", 2, -1)));
}
TEST_F(ProjectStorage, get_no_exported_type_names_for_source_id_for_invalid_type_id)
@@ -9075,7 +9075,7 @@ TEST_F(ProjectStorage, added_document_import_fixes_unresolved_extension)
ASSERT_THAT(fetchType(sourceId1, "QQuickItem"), HasExtensionId(fetchTypeId(sourceId2, "QObject")));
}
TEST_F(ProjectStorage, added_export_is_notifing_changed_exported_types)
TEST_F(ProjectStorage, added_export_is_notifying_changed_exported_types)
{
auto package{createSimpleSynchronizationPackage()};
storage.synchronize(package);
@@ -9088,7 +9088,7 @@ TEST_F(ProjectStorage, added_export_is_notifing_changed_exported_types)
storage.synchronize(std::move(package));
}
TEST_F(ProjectStorage, removed_export_is_notifing_changed_exported_types)
TEST_F(ProjectStorage, removed_export_is_notifying_changed_exported_types)
{
auto package{createSimpleSynchronizationPackage()};
storage.synchronize(package);
@@ -9101,7 +9101,7 @@ TEST_F(ProjectStorage, removed_export_is_notifing_changed_exported_types)
storage.synchronize(std::move(package));
}
TEST_F(ProjectStorage, changed_export_is_notifing_changed_exported_types)
TEST_F(ProjectStorage, changed_export_is_notifying_changed_exported_types)
{
auto package{createSimpleSynchronizationPackage()};
storage.synchronize(package);
@@ -9114,6 +9114,66 @@ TEST_F(ProjectStorage, changed_export_is_notifing_changed_exported_types)
storage.synchronize(std::move(package));
}
TEST_F(ProjectStorage, added_export_is_notifying_changed_exported_type_names)
{
auto package{createSimpleSynchronizationPackage()};
storage.synchronize(package);
package.types[1].exportedTypes.emplace_back(qmlNativeModuleId, "Objec");
NiceMock<ProjectStorageObserverMock> observerMock;
storage.addObserver(&observerMock);
EXPECT_CALL(observerMock,
exportedTypeNamesChanged(ElementsAre(
IsInfoExportTypeName(qmlNativeModuleId,
fetchTypeId(sourceId2, "QObject"),
Eq("Objec"),
A<QmlDesigner::Storage::Version>())),
IsEmpty()));
storage.synchronize(std::move(package));
}
TEST_F(ProjectStorage, removed_export_is_notifying_changed_exported_type_names)
{
auto package{createSimpleSynchronizationPackage()};
storage.synchronize(package);
package.types[1].exportedTypes.pop_back();
NiceMock<ProjectStorageObserverMock> observerMock;
storage.addObserver(&observerMock);
EXPECT_CALL(observerMock,
exportedTypeNamesChanged(IsEmpty(),
ElementsAre(
IsInfoExportTypeName(qmlNativeModuleId,
fetchTypeId(sourceId2, "QObject"),
Eq("QObject"),
A<QmlDesigner::Storage::Version>()))));
storage.synchronize(std::move(package));
}
TEST_F(ProjectStorage, changed_export_is_notifying_changed_exported_type_names)
{
auto package{createSimpleSynchronizationPackage()};
storage.synchronize(package);
package.types[1].exportedTypes[1].name = "Obj2";
NiceMock<ProjectStorageObserverMock> observerMock;
storage.addObserver(&observerMock);
EXPECT_CALL(observerMock,
exportedTypeNamesChanged(
ElementsAre(IsInfoExportTypeName(qmlModuleId,
fetchTypeId(sourceId2, "QObject"),
Eq("Obj2"),
A<QmlDesigner::Storage::Version>())),
ElementsAre(IsInfoExportTypeName(qmlModuleId,
fetchTypeId(sourceId2, "QObject"),
Eq("Obj"),
A<QmlDesigner::Storage::Version>()))));
storage.synchronize(std::move(package));
}
TEST_F(ProjectStorage, get_unqiue_singleton_type_ids)
{
auto package{createSimpleSynchronizationPackage()};