forked from qt-creator/qt-creator
QmlDesigner: Adding missing property error notifier
Alias properties are quite often broken. So we have to handle that broken aliases. Task-number: QDS-12761 Change-Id: Id9b53b98080733e5939de6b3761c923fa35e1dcf Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
This commit is contained in:
@@ -3165,21 +3165,25 @@ void ProjectStorage::relinkAliasPropertyDeclarations(AliasPropertyDeclarations &
|
||||
auto typeId = fetchTypeId(alias.aliasImportedTypeNameId);
|
||||
|
||||
if (typeId) {
|
||||
auto [propertyImportedTypeNameId, propertyTypeId, aliasId, propertyTraits]
|
||||
= fetchPropertyDeclarationByTypeIdAndNameUngarded(typeId, alias.aliasPropertyName);
|
||||
auto propertyDeclaration = fetchPropertyDeclarationByTypeIdAndNameUngarded(
|
||||
typeId, alias.aliasPropertyName);
|
||||
if (propertyDeclaration) {
|
||||
auto [propertyImportedTypeNameId, propertyTypeId, aliasId, propertyTraits] = *propertyDeclaration;
|
||||
|
||||
s->updatePropertyDeclarationWithAliasAndTypeStatement.write(alias.propertyDeclarationId,
|
||||
s->updatePropertyDeclarationWithAliasAndTypeStatement
|
||||
.write(alias.propertyDeclarationId,
|
||||
propertyTypeId,
|
||||
propertyTraits,
|
||||
propertyImportedTypeNameId,
|
||||
aliasId);
|
||||
} else {
|
||||
errorNotifier->typeNameCannotBeResolved(fetchImportedTypeName(
|
||||
alias.aliasImportedTypeNameId),
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
errorNotifier->typeNameCannotBeResolved(fetchImportedTypeName(alias.aliasImportedTypeNameId),
|
||||
fetchTypeSourceId(alias.typeId));
|
||||
s->resetAliasPropertyDeclarationStatement.write(alias.propertyDeclarationId,
|
||||
Storage::PropertyDeclarationTraits{});
|
||||
}
|
||||
},
|
||||
TypeCompare<AliasPropertyDeclaration>{});
|
||||
}
|
||||
@@ -3321,7 +3325,10 @@ PropertyDeclarationId ProjectStorage::fetchAliasId(TypeId aliasTypeId,
|
||||
|
||||
auto stemAlias = fetchPropertyDeclarationByTypeIdAndNameUngarded(aliasTypeId, aliasPropertyName);
|
||||
|
||||
return fetchPropertyDeclarationIdByTypeIdAndNameUngarded(stemAlias.propertyTypeId,
|
||||
if (!stemAlias)
|
||||
return PropertyDeclarationId{};
|
||||
|
||||
return fetchPropertyDeclarationIdByTypeIdAndNameUngarded(stemAlias->propertyTypeId,
|
||||
aliasPropertyNameTail);
|
||||
}
|
||||
|
||||
@@ -3341,10 +3348,22 @@ void ProjectStorage::linkAliasPropertyDeclarationAliasIds(
|
||||
aliasDeclaration.aliasPropertyName,
|
||||
aliasDeclaration.aliasPropertyNameTail);
|
||||
|
||||
if (aliasId) {
|
||||
s->updatePropertyDeclarationAliasIdAndTypeNameIdStatement
|
||||
.write(aliasDeclaration.propertyDeclarationId,
|
||||
aliasId,
|
||||
aliasDeclaration.aliasImportedTypeNameId);
|
||||
} else {
|
||||
s->resetAliasPropertyDeclarationStatement.write(aliasDeclaration.propertyDeclarationId,
|
||||
Storage::PropertyDeclarationTraits{});
|
||||
s->updatePropertyAliasDeclarationRecursivelyWithTypeAndTraitsStatement
|
||||
.write(aliasDeclaration.propertyDeclarationId,
|
||||
TypeId{},
|
||||
Storage::PropertyDeclarationTraits{});
|
||||
|
||||
errorNotifier->propertyNameDoesNotExists(aliasDeclaration.composedProperyName(),
|
||||
aliasDeclaration.sourceId);
|
||||
}
|
||||
} else if (raiseError == RaiseError::Yes) {
|
||||
errorNotifier->typeNameCannotBeResolved(fetchImportedTypeName(
|
||||
aliasDeclaration.aliasImportedTypeNameId),
|
||||
@@ -4516,10 +4535,18 @@ void ProjectStorage::syncDefaultProperties(Storage::Synchronization::Types &type
|
||||
keyValue("view", view)};
|
||||
|
||||
PropertyDeclarationId valueDefaultPropertyId;
|
||||
if (value.defaultPropertyName.size())
|
||||
valueDefaultPropertyId = fetchPropertyDeclarationByTypeIdAndNameUngarded(value.typeId,
|
||||
value.defaultPropertyName)
|
||||
.propertyDeclarationId;
|
||||
if (value.defaultPropertyName.size()) {
|
||||
auto defaultPropertyDeclaration = fetchPropertyDeclarationByTypeIdAndNameUngarded(
|
||||
value.typeId, value.defaultPropertyName);
|
||||
|
||||
if (defaultPropertyDeclaration) {
|
||||
valueDefaultPropertyId = defaultPropertyDeclaration->propertyDeclarationId;
|
||||
} else {
|
||||
errorNotifier->missingDefaultProperty(value.typeName,
|
||||
value.defaultPropertyName,
|
||||
value.sourceId);
|
||||
}
|
||||
}
|
||||
|
||||
if (compareInvalidAreTrue(valueDefaultPropertyId, view.defaultPropertyId))
|
||||
return Sqlite::UpdateChange::No;
|
||||
@@ -4563,10 +4590,8 @@ void ProjectStorage::resetDefaultPropertiesIfChanged(Storage::Synchronization::T
|
||||
|
||||
PropertyDeclarationId valueDefaultPropertyId;
|
||||
if (value.defaultPropertyName.size()) {
|
||||
auto optionalValueDefaultPropertyId = fetchOptionalPropertyDeclarationByTypeIdAndNameUngarded(
|
||||
valueDefaultPropertyId = fetchPropertyDeclarationIdByTypeIdAndNameUngarded(
|
||||
value.typeId, value.defaultPropertyName);
|
||||
if (optionalValueDefaultPropertyId)
|
||||
valueDefaultPropertyId = optionalValueDefaultPropertyId->propertyDeclarationId;
|
||||
}
|
||||
|
||||
if (compareInvalidAreTrue(valueDefaultPropertyId, view.defaultPropertyId))
|
||||
@@ -4814,7 +4839,7 @@ TypeId ProjectStorage::fetchTypeId(ImportedTypeNameId typeNameId,
|
||||
}
|
||||
|
||||
std::optional<ProjectStorage::FetchPropertyDeclarationResult>
|
||||
ProjectStorage::fetchOptionalPropertyDeclarationByTypeIdAndNameUngarded(TypeId typeId,
|
||||
ProjectStorage::fetchPropertyDeclarationByTypeIdAndNameUngarded(TypeId typeId,
|
||||
Utils::SmallStringView name)
|
||||
{
|
||||
using NanotraceHR::keyValue;
|
||||
@@ -4833,24 +4858,6 @@ ProjectStorage::fetchOptionalPropertyDeclarationByTypeIdAndNameUngarded(TypeId t
|
||||
return propertyDeclaration;
|
||||
}
|
||||
|
||||
ProjectStorage::FetchPropertyDeclarationResult ProjectStorage::fetchPropertyDeclarationByTypeIdAndNameUngarded(
|
||||
TypeId typeId, Utils::SmallStringView name)
|
||||
{
|
||||
using NanotraceHR::keyValue;
|
||||
NanotraceHR::Tracer tracer{"fetch property declaration by type id and name ungarded"_t,
|
||||
projectStorageCategory(),
|
||||
keyValue("type id", typeId),
|
||||
keyValue("property name", name)};
|
||||
|
||||
auto propertyDeclaration = fetchOptionalPropertyDeclarationByTypeIdAndNameUngarded(typeId, name);
|
||||
tracer.end(keyValue("property declaration", propertyDeclaration));
|
||||
|
||||
if (propertyDeclaration)
|
||||
return *propertyDeclaration;
|
||||
|
||||
throw PropertyNameDoesNotExists{};
|
||||
}
|
||||
|
||||
PropertyDeclarationId ProjectStorage::fetchPropertyDeclarationIdByTypeIdAndNameUngarded(
|
||||
TypeId typeId, Utils::SmallStringView name)
|
||||
{
|
||||
@@ -4864,10 +4871,7 @@ PropertyDeclarationId ProjectStorage::fetchPropertyDeclarationIdByTypeIdAndNameU
|
||||
|
||||
tracer.end(keyValue("property declaration id", propertyDeclarationId));
|
||||
|
||||
if (propertyDeclarationId)
|
||||
return propertyDeclarationId;
|
||||
|
||||
throw PropertyNameDoesNotExists{};
|
||||
}
|
||||
|
||||
SourceContextId ProjectStorage::readSourceContextId(Utils::SmallStringView sourceContextPath)
|
||||
|
||||
@@ -411,6 +411,14 @@ private:
|
||||
convertToString(string, dict);
|
||||
}
|
||||
|
||||
Utils::PathString composedProperyName() const
|
||||
{
|
||||
if (aliasPropertyNameTail.empty())
|
||||
return aliasPropertyName;
|
||||
|
||||
return Utils::PathString::join({aliasPropertyName, ".", aliasPropertyNameTail});
|
||||
}
|
||||
|
||||
public:
|
||||
TypeId typeId;
|
||||
PropertyDeclarationId propertyDeclarationId;
|
||||
@@ -991,10 +999,7 @@ private:
|
||||
Storage::PropertyDeclarationTraits propertyTraits;
|
||||
};
|
||||
|
||||
std::optional<FetchPropertyDeclarationResult> fetchOptionalPropertyDeclarationByTypeIdAndNameUngarded(
|
||||
TypeId typeId, Utils::SmallStringView name);
|
||||
|
||||
FetchPropertyDeclarationResult fetchPropertyDeclarationByTypeIdAndNameUngarded(
|
||||
std::optional<FetchPropertyDeclarationResult> fetchPropertyDeclarationByTypeIdAndNameUngarded(
|
||||
TypeId typeId, Utils::SmallStringView name);
|
||||
|
||||
PropertyDeclarationId fetchPropertyDeclarationIdByTypeIdAndNameUngarded(TypeId typeId,
|
||||
|
||||
@@ -14,4 +14,20 @@ void ProjectStorageErrorNotifier::typeNameCannotBeResolved(Utils::SmallStringVie
|
||||
<< " in file: " << m_pathCache.sourcePath(sourceId).toStringView();
|
||||
}
|
||||
|
||||
void ProjectStorageErrorNotifier::missingDefaultProperty(Utils::SmallStringView typeName,
|
||||
Utils::SmallStringView propertyName,
|
||||
SourceId sourceId)
|
||||
|
||||
{
|
||||
qDebug() << "Missing default property: " << propertyName << " in type: " << typeName
|
||||
<< " in file: " << m_pathCache.sourcePath(sourceId).toStringView();
|
||||
}
|
||||
|
||||
void ProjectStorageErrorNotifier::propertyNameDoesNotExists(Utils::SmallStringView propertyName,
|
||||
SourceId sourceId)
|
||||
{
|
||||
qDebug() << "Missing property: " << propertyName
|
||||
<< " in file: " << m_pathCache.sourcePath(sourceId).toStringView();
|
||||
}
|
||||
|
||||
} // namespace QmlDesigner
|
||||
|
||||
@@ -16,7 +16,11 @@ public:
|
||||
: m_pathCache{pathCache}
|
||||
{}
|
||||
|
||||
void typeNameCannotBeResolved(Utils::SmallStringView typeName, SourceId souceId) override;
|
||||
void typeNameCannotBeResolved(Utils::SmallStringView typeName, SourceId sourceId) override;
|
||||
void missingDefaultProperty(Utils::SmallStringView typeName,
|
||||
Utils::SmallStringView propertyName,
|
||||
SourceId sourceId) override;
|
||||
void propertyNameDoesNotExists(Utils::SmallStringView propertyName, SourceId sourceId) override;
|
||||
|
||||
private:
|
||||
PathCacheType &m_pathCache;
|
||||
|
||||
@@ -18,7 +18,12 @@ public:
|
||||
ProjectStorageErrorNotifierInterface(const ProjectStorageErrorNotifierInterface &) = delete;
|
||||
ProjectStorageErrorNotifierInterface &operator=(const ProjectStorageErrorNotifierInterface &) = delete;
|
||||
|
||||
virtual void typeNameCannotBeResolved(Utils::SmallStringView typeName, SourceId souceId) = 0;
|
||||
virtual void typeNameCannotBeResolved(Utils::SmallStringView typeName, SourceId sourceId) = 0;
|
||||
virtual void missingDefaultProperty(Utils::SmallStringView typeName,
|
||||
Utils::SmallStringView propertyName,
|
||||
SourceId sourceId)
|
||||
= 0;
|
||||
virtual void propertyNameDoesNotExists(Utils::SmallStringView propertyName, SourceId sourceId) = 0;
|
||||
|
||||
protected:
|
||||
~ProjectStorageErrorNotifierInterface() = default;
|
||||
|
||||
@@ -98,16 +98,6 @@ TypeNameDoesNotExists::TypeNameDoesNotExists(std::string_view typeName, SourceId
|
||||
keyValue("source id", sourceId));
|
||||
}
|
||||
|
||||
PropertyNameDoesNotExists::PropertyNameDoesNotExists()
|
||||
{
|
||||
category().threadEvent("PropertyNameDoesNotExists"_t);
|
||||
}
|
||||
|
||||
const char *PropertyNameDoesNotExists::what() const noexcept
|
||||
{
|
||||
return "The property name does not exist!";
|
||||
}
|
||||
|
||||
PrototypeChainCycle::PrototypeChainCycle()
|
||||
{
|
||||
category().threadEvent("PrototypeChainCycle"_t);
|
||||
|
||||
@@ -95,13 +95,6 @@ public:
|
||||
TypeNameDoesNotExists(std::string_view typeName, SourceId sourceId = SourceId{});
|
||||
};
|
||||
|
||||
class QMLDESIGNERCORE_EXPORT PropertyNameDoesNotExists : public ProjectStorageError
|
||||
{
|
||||
public:
|
||||
PropertyNameDoesNotExists();
|
||||
const char *what() const noexcept override;
|
||||
};
|
||||
|
||||
class QMLDESIGNERCORE_EXPORT PrototypeChainCycle : public ProjectStorageError
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -12,6 +12,16 @@ class ProjectStorageErrorNotifierMock : public QmlDesigner::ProjectStorageErrorN
|
||||
public:
|
||||
MOCK_METHOD(void,
|
||||
typeNameCannotBeResolved,
|
||||
(Utils::SmallStringView typeName, QmlDesigner::SourceId souceId),
|
||||
(Utils::SmallStringView typeName, QmlDesigner::SourceId sourceId),
|
||||
(override));
|
||||
MOCK_METHOD(void,
|
||||
missingDefaultProperty,
|
||||
(Utils::SmallStringView typeName,
|
||||
Utils::SmallStringView propertyName,
|
||||
QmlDesigner::SourceId sourceId),
|
||||
(override));
|
||||
MOCK_METHOD(void,
|
||||
propertyNameDoesNotExists,
|
||||
(Utils::SmallStringView propertyName, QmlDesigner::SourceId sourceId),
|
||||
(override));
|
||||
};
|
||||
|
||||
@@ -216,6 +216,11 @@ auto IsNullTypeId()
|
||||
return Property(&QmlDesigner::TypeId::isNull, true);
|
||||
}
|
||||
|
||||
auto IsNullPropertyDeclarationId()
|
||||
{
|
||||
return Property(&QmlDesigner::PropertyDeclarationId::isNull, true);
|
||||
}
|
||||
|
||||
template<typename Matcher>
|
||||
auto HasPrototypeId(const Matcher &matcher)
|
||||
{
|
||||
@@ -1182,6 +1187,19 @@ protected:
|
||||
return storage.fetchTypeByTypeId(storage.fetchTypeIdByName(sourceId, name));
|
||||
}
|
||||
|
||||
auto defaultPropertyDeclarationId(SourceId sourceId, Utils::SmallStringView typeName)
|
||||
{
|
||||
return storage.defaultPropertyDeclarationId(storage.fetchTypeIdByName(sourceId, typeName));
|
||||
}
|
||||
|
||||
auto propertyDeclarationId(SourceId sourceId,
|
||||
Utils::SmallStringView typeName,
|
||||
Utils::SmallStringView propertyName)
|
||||
{
|
||||
return storage.propertyDeclarationId(storage.fetchTypeIdByName(sourceId, typeName),
|
||||
propertyName);
|
||||
}
|
||||
|
||||
static auto &findType(Storage::Synchronization::SynchronizationPackage &package,
|
||||
Utils::SmallStringView name)
|
||||
{
|
||||
@@ -3508,17 +3526,46 @@ TEST_F(ProjectStorage, synchronize_types_fixes_null_type_id_after_add_alias_decl
|
||||
Contains(IsPropertyDeclaration("items", fetchTypeId(sourceId1, "QQuickItem")))));
|
||||
}
|
||||
|
||||
TEST_F(ProjectStorage, synchronize_types_add_alias_declarations_throws_for_wrong_property_name)
|
||||
TEST_F(ProjectStorage, synchronize_types_add_alias_declarations_notifies_error_for_wrong_property_name)
|
||||
{
|
||||
auto package{createSynchronizationPackageWithAliases()};
|
||||
package.types[2].propertyDeclarations[1].aliasPropertyName = "childrenWrong";
|
||||
|
||||
ASSERT_THROW(storage.synchronize(SynchronizationPackage{package.imports,
|
||||
package.types,
|
||||
{sourceId4},
|
||||
package.moduleDependencies,
|
||||
{sourceId4}}),
|
||||
QmlDesigner::PropertyNameDoesNotExists);
|
||||
EXPECT_CALL(errorNotifierMock, propertyNameDoesNotExists(Eq("childrenWrong"), sourceId3))
|
||||
.Times(AtLeast(1));
|
||||
|
||||
storage.synchronize(
|
||||
{package.imports, package.types, {sourceId4}, package.moduleDependencies, {sourceId4}});
|
||||
}
|
||||
|
||||
TEST_F(ProjectStorage,
|
||||
synchronize_types_add_alias_declarations_returns_invalid_type_for_wrong_property_name)
|
||||
{
|
||||
auto package{createSynchronizationPackageWithAliases()};
|
||||
package.types[2].propertyDeclarations[1].aliasPropertyName = "childrenWrong";
|
||||
|
||||
storage.synchronize(
|
||||
{package.imports, package.types, {sourceId4}, package.moduleDependencies, {sourceId4}});
|
||||
|
||||
ASSERT_THAT(fetchType(sourceId3, "QAliasItem"),
|
||||
PropertyDeclarations(Contains(IsPropertyDeclaration("items", IsNullTypeId()))));
|
||||
}
|
||||
|
||||
TEST_F(ProjectStorage,
|
||||
synchronize_types_update_alias_declarations_returns_item_type_for_fixed_property_name)
|
||||
{
|
||||
auto package{createSynchronizationPackageWithAliases()};
|
||||
package.types[2].propertyDeclarations[1].aliasPropertyName = "childrenWrong";
|
||||
storage.synchronize(
|
||||
{package.imports, package.types, {sourceId4}, package.moduleDependencies, {sourceId4}});
|
||||
package.types[2].propertyDeclarations[1].aliasPropertyName = "children";
|
||||
|
||||
storage.synchronize(
|
||||
{importsSourceId3 + moduleDependenciesSourceId3, {package.types[2]}, {sourceId3}});
|
||||
|
||||
ASSERT_THAT(fetchType(sourceId3, "QAliasItem"),
|
||||
PropertyDeclarations(
|
||||
Contains(IsPropertyDeclaration("items", fetchTypeId(sourceId1, "QQuickItem")))));
|
||||
}
|
||||
|
||||
TEST_F(ProjectStorage, synchronize_types_change_alias_declarations_type_name)
|
||||
@@ -6540,33 +6587,94 @@ TEST_F(ProjectStorage,
|
||||
PropertyDeclarations(Not(Contains(IsPropertyDeclaration("objects", IsNullTypeId())))));
|
||||
}
|
||||
|
||||
TEST_F(ProjectStorage, synchronize_types_add_indirect_alias_declarations_throws_for_wrong_property_name)
|
||||
TEST_F(ProjectStorage,
|
||||
synchronize_types_add_indirect_alias_declarations_notifies_error_for_wrong_property_name)
|
||||
{
|
||||
auto package{createSynchronizationPackageWithIndirectAliases()};
|
||||
storage.synchronize(package);
|
||||
package.types[2].propertyDeclarations[1].aliasPropertyName = "childrenWrong";
|
||||
|
||||
ASSERT_THROW(storage.synchronize(SynchronizationPackage{importsSourceId3,
|
||||
{package.types[2]},
|
||||
{sourceId3},
|
||||
moduleDependenciesSourceId3,
|
||||
{sourceId3}}),
|
||||
QmlDesigner::PropertyNameDoesNotExists);
|
||||
EXPECT_CALL(errorNotifierMock, propertyNameDoesNotExists(Eq("childrenWrong.objects"), sourceId3));
|
||||
|
||||
storage.synchronize(
|
||||
{importsSourceId3, {package.types[2]}, {sourceId3}, moduleDependenciesSourceId3, {sourceId3}});
|
||||
}
|
||||
|
||||
TEST_F(ProjectStorage,
|
||||
synchronize_types_add_indirect_alias_declarations_throws_for_wrong_property_name_tail)
|
||||
synchronize_types_add_indirect_alias_declarations_returns_null_type_id_for_wrong_property_name)
|
||||
{
|
||||
auto package{createSynchronizationPackageWithIndirectAliases()};
|
||||
storage.synchronize(package);
|
||||
package.types[2].propertyDeclarations[1].aliasPropertyName = "childrenWrong";
|
||||
|
||||
storage.synchronize(
|
||||
{importsSourceId3, {package.types[2]}, {sourceId3}, moduleDependenciesSourceId3, {sourceId3}});
|
||||
|
||||
ASSERT_THAT(fetchType(sourceId3, "QAliasItem"),
|
||||
PropertyDeclarations(Contains(IsPropertyDeclaration("objects", IsNullTypeId()))));
|
||||
}
|
||||
|
||||
TEST_F(ProjectStorage,
|
||||
synchronize_types_updated_indirect_alias_declarations_returns_item_type_id_for_wrong_property_name)
|
||||
{
|
||||
auto package{createSynchronizationPackageWithIndirectAliases()};
|
||||
storage.synchronize(package);
|
||||
package.types[2].propertyDeclarations[1].aliasPropertyName = "childrenWrong";
|
||||
storage.synchronize(
|
||||
{importsSourceId3, {package.types[2]}, {sourceId3}, moduleDependenciesSourceId3, {sourceId3}});
|
||||
package.types[2].propertyDeclarations[1].aliasPropertyName = "children";
|
||||
|
||||
storage.synchronize(
|
||||
{importsSourceId3 + moduleDependenciesSourceId3, {package.types[2]}, {sourceId3}});
|
||||
|
||||
ASSERT_THAT(fetchType(sourceId3, "QAliasItem"),
|
||||
PropertyDeclarations(
|
||||
Contains(IsPropertyDeclaration("objects", fetchTypeId(sourceId2, "QObject")))));
|
||||
}
|
||||
|
||||
TEST_F(ProjectStorage,
|
||||
synchronize_types_add_indirect_alias_declarations_notifies_error_for_wrong_property_name_tail)
|
||||
{
|
||||
auto package{createSynchronizationPackageWithIndirectAliases()};
|
||||
storage.synchronize(package);
|
||||
package.types[2].propertyDeclarations[1].aliasPropertyNameTail = "objectsWrong";
|
||||
|
||||
ASSERT_THROW(storage.synchronize(SynchronizationPackage{importsSourceId3,
|
||||
{package.types[2]},
|
||||
{sourceId3},
|
||||
moduleDependenciesSourceId3,
|
||||
{sourceId3}}),
|
||||
QmlDesigner::PropertyNameDoesNotExists);
|
||||
EXPECT_CALL(errorNotifierMock, propertyNameDoesNotExists(Eq("children.objectsWrong"), sourceId3));
|
||||
|
||||
storage.synchronize(SynchronizationPackage{
|
||||
importsSourceId3, {package.types[2]}, {sourceId3}, moduleDependenciesSourceId3, {sourceId3}});
|
||||
}
|
||||
|
||||
TEST_F(ProjectStorage,
|
||||
synchronize_types_add_indirect_alias_declarations_sets_property_declaration_id_to_null_for_the_wrong_property_name_tail)
|
||||
{
|
||||
auto package{createSynchronizationPackageWithIndirectAliases()};
|
||||
storage.synchronize(package);
|
||||
package.types[2].propertyDeclarations[1].aliasPropertyNameTail = "objectsWrong";
|
||||
|
||||
storage.synchronize(SynchronizationPackage{
|
||||
importsSourceId3, {package.types[2]}, {sourceId3}, moduleDependenciesSourceId3, {sourceId3}});
|
||||
|
||||
ASSERT_THAT(fetchType(sourceId3, "QAliasItem"),
|
||||
PropertyDeclarations(Contains(IsPropertyDeclaration("objects", IsNullTypeId()))));
|
||||
}
|
||||
|
||||
TEST_F(ProjectStorage,
|
||||
synchronize_types_updates_indirect_alias_declarations_fixed_property_declaration_id_for_property_name_tail)
|
||||
{
|
||||
auto package{createSynchronizationPackageWithIndirectAliases()};
|
||||
storage.synchronize(package);
|
||||
package.types[2].propertyDeclarations[1].aliasPropertyNameTail = "objectsWrong";
|
||||
storage.synchronize(
|
||||
{importsSourceId3, {package.types[2]}, {sourceId3}, moduleDependenciesSourceId3, {sourceId3}});
|
||||
package.types[2].propertyDeclarations[1].aliasPropertyNameTail = "objects";
|
||||
|
||||
storage.synchronize(
|
||||
{importsSourceId3 + moduleDependenciesSourceId3, {package.types[2]}, {sourceId3}});
|
||||
|
||||
ASSERT_THAT(fetchType(sourceId3, "QAliasItem"),
|
||||
PropertyDeclarations(Contains(
|
||||
IsPropertyDeclaration("objects", Eq(fetchTypeId(sourceId2, "QObject"))))));
|
||||
}
|
||||
|
||||
TEST_F(ProjectStorage, synchronize_types_change_indirect_alias_declaration_type_name)
|
||||
@@ -7407,23 +7515,64 @@ TEST_F(ProjectStorage, synchronize_to_removed_default_property)
|
||||
Contains(AllOf(HasTypeName(Eq("QQuickItem")), HasDefaultPropertyName(IsEmpty()))));
|
||||
}
|
||||
|
||||
TEST_F(ProjectStorage, synchronize_default_property_throws_for_missing_default_property)
|
||||
TEST_F(ProjectStorage, synchronize_default_property_notifies_error_for_missing_default_property)
|
||||
{
|
||||
auto package{createSimpleSynchronizationPackage()};
|
||||
package.types.front().defaultPropertyName = "child";
|
||||
|
||||
ASSERT_THROW(storage.synchronize(package), QmlDesigner::PropertyNameDoesNotExists);
|
||||
EXPECT_CALL(errorNotifierMock, missingDefaultProperty(Eq("QQuickItem"), Eq("child"), sourceId1));
|
||||
|
||||
storage.synchronize(package);
|
||||
}
|
||||
|
||||
TEST_F(ProjectStorage, gets_null_default_property_id_for_broken_default_property_name)
|
||||
{
|
||||
auto package{createSimpleSynchronizationPackage()};
|
||||
package.types.front().defaultPropertyName = "child";
|
||||
|
||||
storage.synchronize(package);
|
||||
|
||||
ASSERT_THAT(defaultPropertyDeclarationId(sourceId1, "QQuickItem"), IsNullPropertyDeclarationId());
|
||||
}
|
||||
|
||||
TEST_F(ProjectStorage, synchronize_default_fixes_default_property_name)
|
||||
{
|
||||
auto package{createSimpleSynchronizationPackage()};
|
||||
package.types.front().defaultPropertyName = "child";
|
||||
storage.synchronize(package);
|
||||
package.types.front().defaultPropertyName = "data";
|
||||
|
||||
storage.synchronize(package);
|
||||
|
||||
ASSERT_THAT(defaultPropertyDeclarationId(sourceId1, "QQuickItem"),
|
||||
Eq(propertyDeclarationId(sourceId1, "QQuickItem", "data")));
|
||||
}
|
||||
|
||||
TEST_F(ProjectStorage,
|
||||
synchronize_default_property_throws_for_removing_property_without_changing_default_property)
|
||||
synchronize_default_property_notifies_error_for_removing_property_without_changing_default_property)
|
||||
{
|
||||
auto package{createSimpleSynchronizationPackage()};
|
||||
package.types.front().defaultPropertyName = "children";
|
||||
storage.synchronize(package);
|
||||
removeProperty(package, "QQuickItem", "children");
|
||||
|
||||
ASSERT_THROW(storage.synchronize(package), QmlDesigner::PropertyNameDoesNotExists);
|
||||
EXPECT_CALL(errorNotifierMock,
|
||||
missingDefaultProperty(Eq("QQuickItem"), Eq("children"), sourceId1));
|
||||
|
||||
storage.synchronize(package);
|
||||
}
|
||||
|
||||
TEST_F(ProjectStorage,
|
||||
synchronize_default_property_has_null_id_for_removing_property_without_changing_default_property)
|
||||
{
|
||||
auto package{createSimpleSynchronizationPackage()};
|
||||
package.types.front().defaultPropertyName = "children";
|
||||
storage.synchronize(package);
|
||||
removeProperty(package, "QQuickItem", "children");
|
||||
|
||||
storage.synchronize(package);
|
||||
|
||||
ASSERT_THAT(defaultPropertyDeclarationId(sourceId1, "QQuickItem"), IsNullPropertyDeclarationId());
|
||||
}
|
||||
|
||||
TEST_F(ProjectStorage, synchronize_changes_default_property_and_removes_old_default_property)
|
||||
|
||||
Reference in New Issue
Block a user