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:
Marco Bubke
2024-07-17 18:01:19 +02:00
parent 6daee01869
commit a29ff454a6
9 changed files with 274 additions and 98 deletions

View File

@@ -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,
propertyTypeId,
propertyTraits,
propertyImportedTypeNameId,
aliasId);
} else {
errorNotifier->typeNameCannotBeResolved(fetchImportedTypeName(
alias.aliasImportedTypeNameId),
fetchTypeSourceId(alias.typeId));
s->resetAliasPropertyDeclarationStatement.write(alias.propertyDeclarationId,
Storage::PropertyDeclarationTraits{});
s->updatePropertyDeclarationWithAliasAndTypeStatement
.write(alias.propertyDeclarationId,
propertyTypeId,
propertyTraits,
propertyImportedTypeNameId,
aliasId);
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);
s->updatePropertyDeclarationAliasIdAndTypeNameIdStatement
.write(aliasDeclaration.propertyDeclarationId,
aliasId,
aliasDeclaration.aliasImportedTypeNameId);
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,8 +4839,8 @@ TypeId ProjectStorage::fetchTypeId(ImportedTypeNameId typeNameId,
}
std::optional<ProjectStorage::FetchPropertyDeclarationResult>
ProjectStorage::fetchOptionalPropertyDeclarationByTypeIdAndNameUngarded(TypeId typeId,
Utils::SmallStringView name)
ProjectStorage::fetchPropertyDeclarationByTypeIdAndNameUngarded(TypeId typeId,
Utils::SmallStringView name)
{
using NanotraceHR::keyValue;
NanotraceHR::Tracer tracer{"fetch optional property declaration by type id and name ungarded"_t,
@@ -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{};
return propertyDeclarationId;
}
SourceContextId ProjectStorage::readSourceContextId(Utils::SmallStringView sourceContextPath)

View File

@@ -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,

View File

@@ -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

View File

@@ -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;

View File

@@ -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;

View File

@@ -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);

View File

@@ -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: