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);
|
auto typeId = fetchTypeId(alias.aliasImportedTypeNameId);
|
||||||
|
|
||||||
if (typeId) {
|
if (typeId) {
|
||||||
auto [propertyImportedTypeNameId, propertyTypeId, aliasId, propertyTraits]
|
auto propertyDeclaration = fetchPropertyDeclarationByTypeIdAndNameUngarded(
|
||||||
= fetchPropertyDeclarationByTypeIdAndNameUngarded(typeId, alias.aliasPropertyName);
|
typeId, alias.aliasPropertyName);
|
||||||
|
if (propertyDeclaration) {
|
||||||
|
auto [propertyImportedTypeNameId, propertyTypeId, aliasId, propertyTraits] = *propertyDeclaration;
|
||||||
|
|
||||||
s->updatePropertyDeclarationWithAliasAndTypeStatement.write(alias.propertyDeclarationId,
|
s->updatePropertyDeclarationWithAliasAndTypeStatement
|
||||||
propertyTypeId,
|
.write(alias.propertyDeclarationId,
|
||||||
propertyTraits,
|
propertyTypeId,
|
||||||
propertyImportedTypeNameId,
|
propertyTraits,
|
||||||
aliasId);
|
propertyImportedTypeNameId,
|
||||||
} else {
|
aliasId);
|
||||||
errorNotifier->typeNameCannotBeResolved(fetchImportedTypeName(
|
return;
|
||||||
alias.aliasImportedTypeNameId),
|
}
|
||||||
fetchTypeSourceId(alias.typeId));
|
|
||||||
s->resetAliasPropertyDeclarationStatement.write(alias.propertyDeclarationId,
|
|
||||||
Storage::PropertyDeclarationTraits{});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
errorNotifier->typeNameCannotBeResolved(fetchImportedTypeName(alias.aliasImportedTypeNameId),
|
||||||
|
fetchTypeSourceId(alias.typeId));
|
||||||
|
s->resetAliasPropertyDeclarationStatement.write(alias.propertyDeclarationId,
|
||||||
|
Storage::PropertyDeclarationTraits{});
|
||||||
},
|
},
|
||||||
TypeCompare<AliasPropertyDeclaration>{});
|
TypeCompare<AliasPropertyDeclaration>{});
|
||||||
}
|
}
|
||||||
@@ -3321,7 +3325,10 @@ PropertyDeclarationId ProjectStorage::fetchAliasId(TypeId aliasTypeId,
|
|||||||
|
|
||||||
auto stemAlias = fetchPropertyDeclarationByTypeIdAndNameUngarded(aliasTypeId, aliasPropertyName);
|
auto stemAlias = fetchPropertyDeclarationByTypeIdAndNameUngarded(aliasTypeId, aliasPropertyName);
|
||||||
|
|
||||||
return fetchPropertyDeclarationIdByTypeIdAndNameUngarded(stemAlias.propertyTypeId,
|
if (!stemAlias)
|
||||||
|
return PropertyDeclarationId{};
|
||||||
|
|
||||||
|
return fetchPropertyDeclarationIdByTypeIdAndNameUngarded(stemAlias->propertyTypeId,
|
||||||
aliasPropertyNameTail);
|
aliasPropertyNameTail);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3341,10 +3348,22 @@ void ProjectStorage::linkAliasPropertyDeclarationAliasIds(
|
|||||||
aliasDeclaration.aliasPropertyName,
|
aliasDeclaration.aliasPropertyName,
|
||||||
aliasDeclaration.aliasPropertyNameTail);
|
aliasDeclaration.aliasPropertyNameTail);
|
||||||
|
|
||||||
s->updatePropertyDeclarationAliasIdAndTypeNameIdStatement
|
if (aliasId) {
|
||||||
.write(aliasDeclaration.propertyDeclarationId,
|
s->updatePropertyDeclarationAliasIdAndTypeNameIdStatement
|
||||||
aliasId,
|
.write(aliasDeclaration.propertyDeclarationId,
|
||||||
aliasDeclaration.aliasImportedTypeNameId);
|
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) {
|
} else if (raiseError == RaiseError::Yes) {
|
||||||
errorNotifier->typeNameCannotBeResolved(fetchImportedTypeName(
|
errorNotifier->typeNameCannotBeResolved(fetchImportedTypeName(
|
||||||
aliasDeclaration.aliasImportedTypeNameId),
|
aliasDeclaration.aliasImportedTypeNameId),
|
||||||
@@ -4516,10 +4535,18 @@ void ProjectStorage::syncDefaultProperties(Storage::Synchronization::Types &type
|
|||||||
keyValue("view", view)};
|
keyValue("view", view)};
|
||||||
|
|
||||||
PropertyDeclarationId valueDefaultPropertyId;
|
PropertyDeclarationId valueDefaultPropertyId;
|
||||||
if (value.defaultPropertyName.size())
|
if (value.defaultPropertyName.size()) {
|
||||||
valueDefaultPropertyId = fetchPropertyDeclarationByTypeIdAndNameUngarded(value.typeId,
|
auto defaultPropertyDeclaration = fetchPropertyDeclarationByTypeIdAndNameUngarded(
|
||||||
value.defaultPropertyName)
|
value.typeId, value.defaultPropertyName);
|
||||||
.propertyDeclarationId;
|
|
||||||
|
if (defaultPropertyDeclaration) {
|
||||||
|
valueDefaultPropertyId = defaultPropertyDeclaration->propertyDeclarationId;
|
||||||
|
} else {
|
||||||
|
errorNotifier->missingDefaultProperty(value.typeName,
|
||||||
|
value.defaultPropertyName,
|
||||||
|
value.sourceId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (compareInvalidAreTrue(valueDefaultPropertyId, view.defaultPropertyId))
|
if (compareInvalidAreTrue(valueDefaultPropertyId, view.defaultPropertyId))
|
||||||
return Sqlite::UpdateChange::No;
|
return Sqlite::UpdateChange::No;
|
||||||
@@ -4563,10 +4590,8 @@ void ProjectStorage::resetDefaultPropertiesIfChanged(Storage::Synchronization::T
|
|||||||
|
|
||||||
PropertyDeclarationId valueDefaultPropertyId;
|
PropertyDeclarationId valueDefaultPropertyId;
|
||||||
if (value.defaultPropertyName.size()) {
|
if (value.defaultPropertyName.size()) {
|
||||||
auto optionalValueDefaultPropertyId = fetchOptionalPropertyDeclarationByTypeIdAndNameUngarded(
|
valueDefaultPropertyId = fetchPropertyDeclarationIdByTypeIdAndNameUngarded(
|
||||||
value.typeId, value.defaultPropertyName);
|
value.typeId, value.defaultPropertyName);
|
||||||
if (optionalValueDefaultPropertyId)
|
|
||||||
valueDefaultPropertyId = optionalValueDefaultPropertyId->propertyDeclarationId;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (compareInvalidAreTrue(valueDefaultPropertyId, view.defaultPropertyId))
|
if (compareInvalidAreTrue(valueDefaultPropertyId, view.defaultPropertyId))
|
||||||
@@ -4814,8 +4839,8 @@ TypeId ProjectStorage::fetchTypeId(ImportedTypeNameId typeNameId,
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::optional<ProjectStorage::FetchPropertyDeclarationResult>
|
std::optional<ProjectStorage::FetchPropertyDeclarationResult>
|
||||||
ProjectStorage::fetchOptionalPropertyDeclarationByTypeIdAndNameUngarded(TypeId typeId,
|
ProjectStorage::fetchPropertyDeclarationByTypeIdAndNameUngarded(TypeId typeId,
|
||||||
Utils::SmallStringView name)
|
Utils::SmallStringView name)
|
||||||
{
|
{
|
||||||
using NanotraceHR::keyValue;
|
using NanotraceHR::keyValue;
|
||||||
NanotraceHR::Tracer tracer{"fetch optional property declaration by type id and name ungarded"_t,
|
NanotraceHR::Tracer tracer{"fetch optional property declaration by type id and name ungarded"_t,
|
||||||
@@ -4833,24 +4858,6 @@ ProjectStorage::fetchOptionalPropertyDeclarationByTypeIdAndNameUngarded(TypeId t
|
|||||||
return propertyDeclaration;
|
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(
|
PropertyDeclarationId ProjectStorage::fetchPropertyDeclarationIdByTypeIdAndNameUngarded(
|
||||||
TypeId typeId, Utils::SmallStringView name)
|
TypeId typeId, Utils::SmallStringView name)
|
||||||
{
|
{
|
||||||
@@ -4864,10 +4871,7 @@ PropertyDeclarationId ProjectStorage::fetchPropertyDeclarationIdByTypeIdAndNameU
|
|||||||
|
|
||||||
tracer.end(keyValue("property declaration id", propertyDeclarationId));
|
tracer.end(keyValue("property declaration id", propertyDeclarationId));
|
||||||
|
|
||||||
if (propertyDeclarationId)
|
return propertyDeclarationId;
|
||||||
return propertyDeclarationId;
|
|
||||||
|
|
||||||
throw PropertyNameDoesNotExists{};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SourceContextId ProjectStorage::readSourceContextId(Utils::SmallStringView sourceContextPath)
|
SourceContextId ProjectStorage::readSourceContextId(Utils::SmallStringView sourceContextPath)
|
||||||
|
|||||||
@@ -411,6 +411,14 @@ private:
|
|||||||
convertToString(string, dict);
|
convertToString(string, dict);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Utils::PathString composedProperyName() const
|
||||||
|
{
|
||||||
|
if (aliasPropertyNameTail.empty())
|
||||||
|
return aliasPropertyName;
|
||||||
|
|
||||||
|
return Utils::PathString::join({aliasPropertyName, ".", aliasPropertyNameTail});
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TypeId typeId;
|
TypeId typeId;
|
||||||
PropertyDeclarationId propertyDeclarationId;
|
PropertyDeclarationId propertyDeclarationId;
|
||||||
@@ -991,10 +999,7 @@ private:
|
|||||||
Storage::PropertyDeclarationTraits propertyTraits;
|
Storage::PropertyDeclarationTraits propertyTraits;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::optional<FetchPropertyDeclarationResult> fetchOptionalPropertyDeclarationByTypeIdAndNameUngarded(
|
std::optional<FetchPropertyDeclarationResult> fetchPropertyDeclarationByTypeIdAndNameUngarded(
|
||||||
TypeId typeId, Utils::SmallStringView name);
|
|
||||||
|
|
||||||
FetchPropertyDeclarationResult fetchPropertyDeclarationByTypeIdAndNameUngarded(
|
|
||||||
TypeId typeId, Utils::SmallStringView name);
|
TypeId typeId, Utils::SmallStringView name);
|
||||||
|
|
||||||
PropertyDeclarationId fetchPropertyDeclarationIdByTypeIdAndNameUngarded(TypeId typeId,
|
PropertyDeclarationId fetchPropertyDeclarationIdByTypeIdAndNameUngarded(TypeId typeId,
|
||||||
|
|||||||
@@ -14,4 +14,20 @@ void ProjectStorageErrorNotifier::typeNameCannotBeResolved(Utils::SmallStringVie
|
|||||||
<< " in file: " << m_pathCache.sourcePath(sourceId).toStringView();
|
<< " 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
|
} // namespace QmlDesigner
|
||||||
|
|||||||
@@ -16,7 +16,11 @@ public:
|
|||||||
: m_pathCache{pathCache}
|
: 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:
|
private:
|
||||||
PathCacheType &m_pathCache;
|
PathCacheType &m_pathCache;
|
||||||
|
|||||||
@@ -18,7 +18,12 @@ public:
|
|||||||
ProjectStorageErrorNotifierInterface(const ProjectStorageErrorNotifierInterface &) = delete;
|
ProjectStorageErrorNotifierInterface(const ProjectStorageErrorNotifierInterface &) = delete;
|
||||||
ProjectStorageErrorNotifierInterface &operator=(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:
|
protected:
|
||||||
~ProjectStorageErrorNotifierInterface() = default;
|
~ProjectStorageErrorNotifierInterface() = default;
|
||||||
|
|||||||
@@ -98,16 +98,6 @@ TypeNameDoesNotExists::TypeNameDoesNotExists(std::string_view typeName, SourceId
|
|||||||
keyValue("source id", 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()
|
PrototypeChainCycle::PrototypeChainCycle()
|
||||||
{
|
{
|
||||||
category().threadEvent("PrototypeChainCycle"_t);
|
category().threadEvent("PrototypeChainCycle"_t);
|
||||||
|
|||||||
@@ -95,13 +95,6 @@ public:
|
|||||||
TypeNameDoesNotExists(std::string_view typeName, SourceId sourceId = SourceId{});
|
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
|
class QMLDESIGNERCORE_EXPORT PrototypeChainCycle : public ProjectStorageError
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -12,6 +12,16 @@ class ProjectStorageErrorNotifierMock : public QmlDesigner::ProjectStorageErrorN
|
|||||||
public:
|
public:
|
||||||
MOCK_METHOD(void,
|
MOCK_METHOD(void,
|
||||||
typeNameCannotBeResolved,
|
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));
|
(override));
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -216,6 +216,11 @@ auto IsNullTypeId()
|
|||||||
return Property(&QmlDesigner::TypeId::isNull, true);
|
return Property(&QmlDesigner::TypeId::isNull, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto IsNullPropertyDeclarationId()
|
||||||
|
{
|
||||||
|
return Property(&QmlDesigner::PropertyDeclarationId::isNull, true);
|
||||||
|
}
|
||||||
|
|
||||||
template<typename Matcher>
|
template<typename Matcher>
|
||||||
auto HasPrototypeId(const Matcher &matcher)
|
auto HasPrototypeId(const Matcher &matcher)
|
||||||
{
|
{
|
||||||
@@ -1182,6 +1187,19 @@ protected:
|
|||||||
return storage.fetchTypeByTypeId(storage.fetchTypeIdByName(sourceId, name));
|
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,
|
static auto &findType(Storage::Synchronization::SynchronizationPackage &package,
|
||||||
Utils::SmallStringView name)
|
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")))));
|
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()};
|
auto package{createSynchronizationPackageWithAliases()};
|
||||||
package.types[2].propertyDeclarations[1].aliasPropertyName = "childrenWrong";
|
package.types[2].propertyDeclarations[1].aliasPropertyName = "childrenWrong";
|
||||||
|
|
||||||
ASSERT_THROW(storage.synchronize(SynchronizationPackage{package.imports,
|
EXPECT_CALL(errorNotifierMock, propertyNameDoesNotExists(Eq("childrenWrong"), sourceId3))
|
||||||
package.types,
|
.Times(AtLeast(1));
|
||||||
{sourceId4},
|
|
||||||
package.moduleDependencies,
|
storage.synchronize(
|
||||||
{sourceId4}}),
|
{package.imports, package.types, {sourceId4}, package.moduleDependencies, {sourceId4}});
|
||||||
QmlDesigner::PropertyNameDoesNotExists);
|
}
|
||||||
|
|
||||||
|
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)
|
TEST_F(ProjectStorage, synchronize_types_change_alias_declarations_type_name)
|
||||||
@@ -6540,33 +6587,94 @@ TEST_F(ProjectStorage,
|
|||||||
PropertyDeclarations(Not(Contains(IsPropertyDeclaration("objects", IsNullTypeId())))));
|
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()};
|
auto package{createSynchronizationPackageWithIndirectAliases()};
|
||||||
storage.synchronize(package);
|
storage.synchronize(package);
|
||||||
package.types[2].propertyDeclarations[1].aliasPropertyName = "childrenWrong";
|
package.types[2].propertyDeclarations[1].aliasPropertyName = "childrenWrong";
|
||||||
|
|
||||||
ASSERT_THROW(storage.synchronize(SynchronizationPackage{importsSourceId3,
|
EXPECT_CALL(errorNotifierMock, propertyNameDoesNotExists(Eq("childrenWrong.objects"), sourceId3));
|
||||||
{package.types[2]},
|
|
||||||
{sourceId3},
|
storage.synchronize(
|
||||||
moduleDependenciesSourceId3,
|
{importsSourceId3, {package.types[2]}, {sourceId3}, moduleDependenciesSourceId3, {sourceId3}});
|
||||||
{sourceId3}}),
|
|
||||||
QmlDesigner::PropertyNameDoesNotExists);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ProjectStorage,
|
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()};
|
auto package{createSynchronizationPackageWithIndirectAliases()};
|
||||||
storage.synchronize(package);
|
storage.synchronize(package);
|
||||||
package.types[2].propertyDeclarations[1].aliasPropertyNameTail = "objectsWrong";
|
package.types[2].propertyDeclarations[1].aliasPropertyNameTail = "objectsWrong";
|
||||||
|
|
||||||
ASSERT_THROW(storage.synchronize(SynchronizationPackage{importsSourceId3,
|
EXPECT_CALL(errorNotifierMock, propertyNameDoesNotExists(Eq("children.objectsWrong"), sourceId3));
|
||||||
{package.types[2]},
|
|
||||||
{sourceId3},
|
storage.synchronize(SynchronizationPackage{
|
||||||
moduleDependenciesSourceId3,
|
importsSourceId3, {package.types[2]}, {sourceId3}, moduleDependenciesSourceId3, {sourceId3}});
|
||||||
{sourceId3}}),
|
}
|
||||||
QmlDesigner::PropertyNameDoesNotExists);
|
|
||||||
|
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)
|
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()))));
|
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()};
|
auto package{createSimpleSynchronizationPackage()};
|
||||||
package.types.front().defaultPropertyName = "child";
|
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,
|
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()};
|
auto package{createSimpleSynchronizationPackage()};
|
||||||
package.types.front().defaultPropertyName = "children";
|
package.types.front().defaultPropertyName = "children";
|
||||||
storage.synchronize(package);
|
storage.synchronize(package);
|
||||||
removeProperty(package, "QQuickItem", "children");
|
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)
|
TEST_F(ProjectStorage, synchronize_changes_default_property_and_removes_old_default_property)
|
||||||
|
|||||||
Reference in New Issue
Block a user