QmlDesigner: Show error/warning for root reference

Show an error when an alias property references the root item directly.
Show a warning when an alias property references the root item in a
hierarchy.

Task-number: QDS-4380
Change-Id: I312fc0296e3bb2321a4d9e1113bd0cd4c1c0b8ed
Reviewed-by: Leena Miettinen <riitta-leena.miettinen@qt.io>
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
Henning Gruendl
2022-01-19 10:34:12 +01:00
committed by Henning Gründl
parent ba08864954
commit 73ae5bb1f6
3 changed files with 45 additions and 1 deletions

View File

@@ -1128,6 +1128,44 @@ bool Check::visit(UiPublicMember *ast)
{
if (ast->type == UiPublicMember::Property) {
const QStringView typeName = ast->memberType->name;
// Check alias properties don't reference root item
// Item {
// id: root
// property alias p1: root
// property alias p2: root.child
//
// Item { id: child }
// }
// - Show error for alias property p1
// - Show warning for alias property p2
// Check if type and id stack only contain one item as we are only looking for alias
// properties in the root item.
if (typeName == QLatin1String("alias") && ast->type == AST::UiPublicMember::Property
&& m_typeStack.count() == 1 && m_idStack.count() == 1 && m_idStack.top().count() == 1) {
const QString rootId = m_idStack.top().values().first();
if (!rootId.isEmpty()) {
if (ExpressionStatement *exp = cast<ExpressionStatement *>(ast->statement)) {
ExpressionNode *node = exp->expression;
// Check for case property alias p1: root
if (IdentifierExpression *idExp = cast<IdentifierExpression *>(node)) {
if (!idExp->name.isEmpty() && idExp->name.toString() == rootId)
addMessage(ErrAliasReferRoot, idExp->identifierToken);
// Check for case property alias p2: root.child
} else if (FieldMemberExpression *fmExp = cast<FieldMemberExpression *>(node)) {
if (IdentifierExpression *base = cast<IdentifierExpression *>(fmExp->base)) {
if (!base->name.isEmpty() && base->name.toString() == rootId)
addMessage(WarnAliasReferRootHierarchy, base->identifierToken);
}
}
}
}
}
// warn about dubious use of var/variant
if (typeName == QLatin1String("variant") || typeName == QLatin1String("var")) {
Evaluate evaluator(&_scopeChain);

View File

@@ -255,6 +255,10 @@ StaticAnalysisMessages::StaticAnalysisMessages()
tr("Components are only allowed to have a single child element."));
newMsg(WarnComponentRequiresChildren, Warning,
tr("Components require a child element."));
newMsg(ErrAliasReferRoot, Error,
tr("Do not reference the root item as alias."));
newMsg(WarnAliasReferRootHierarchy, Warning,
tr("Avoid referencing the root item in a hierarchy."));
}
} // anonymous namespace

View File

@@ -134,7 +134,9 @@ enum Type {
WarnLogicalValueDoesNotDependOnValues = 325,
ErrToManyComponentChildren = 326,
WarnComponentRequiresChildren = 327,
WarnDuplicateImport = 400
WarnDuplicateImport = 400,
ErrAliasReferRoot = 401,
WarnAliasReferRootHierarchy = 402
};
class QMLJS_EXPORT PrototypeMessageData {