diff options
author | Olivier De Cannière <[email protected]> | 2025-05-28 15:00:38 +0200 |
---|---|---|
committer | Olivier De Cannière <[email protected]> | 2025-05-30 22:25:39 +0200 |
commit | 2e00bc40cce9286dcb1ef9ff88845778c316592c (patch) | |
tree | 3806195ff655f2c41443748d4da8229d8c3b3ef6 /src/qmlcompiler | |
parent | afc5a1c6f49e33cee07d098728e3c0702e95d168 (diff) |
If a property binding is a js block without any statements, it could
mean that the user intended to create an object literal instead of an
empty block that returns undefined.
Task-number: QTBUG-129307
Change-Id: If242ddac140cce6479062194b785096ba1f6c0a6
Reviewed-by: Fabian Kosmale <[email protected]>
Diffstat (limited to 'src/qmlcompiler')
-rw-r--r-- | src/qmlcompiler/qqmljsimportvisitor_p.h | 2 | ||||
-rw-r--r-- | src/qmlcompiler/qqmljslintervisitor.cpp | 16 | ||||
-rw-r--r-- | src/qmlcompiler/qqmljslintervisitor_p.h | 3 | ||||
-rw-r--r-- | src/qmlcompiler/qqmljslogger.cpp | 2 | ||||
-rw-r--r-- | src/qmlcompiler/qqmljsloggingutils.h | 1 |
5 files changed, 23 insertions, 1 deletions
diff --git a/src/qmlcompiler/qqmljsimportvisitor_p.h b/src/qmlcompiler/qqmljsimportvisitor_p.h index 32f6915b32..c13f09f112 100644 --- a/src/qmlcompiler/qqmljsimportvisitor_p.h +++ b/src/qmlcompiler/qqmljsimportvisitor_p.h @@ -305,7 +305,7 @@ protected: enum class BindingExpressionParseResult { Invalid, Script, Literal, Translation }; enum class BindingForPropertyDefintion { Yes, No }; - BindingExpressionParseResult parseBindingExpression( + virtual BindingExpressionParseResult parseBindingExpression( const QString &name, const QQmlJS::AST::Statement *statement, const QQmlJS::AST::UiPublicMember *associatedPropertyDefinition = nullptr); bool isImportPrefix(QString prefix) const; diff --git a/src/qmlcompiler/qqmljslintervisitor.cpp b/src/qmlcompiler/qqmljslintervisitor.cpp index b5d254a00c..540ba6c535 100644 --- a/src/qmlcompiler/qqmljslintervisitor.cpp +++ b/src/qmlcompiler/qqmljslintervisitor.cpp @@ -416,6 +416,22 @@ bool LinterVisitor::visit(ExpressionStatement *ast) return true; } +QQmlJSImportVisitor::BindingExpressionParseResult LinterVisitor::parseBindingExpression( + const QString &name, const QQmlJS::AST::Statement *statement, + const QQmlJS::AST::UiPublicMember *associatedPropertyDefinition) +{ + if (statement && statement->kind == (int)AST::Node::Kind::Kind_Block) { + const auto *block = static_cast<const AST::Block *>(statement); + if (!block->statements && associatedPropertyDefinition) { + m_logger->log("Unintentional empty block, use ({}) for empty object literal"_L1, + qmlUnintentionalEmptyBlock, + combine(block->lbraceToken, block->rbraceToken)); + } + } + + return QQmlJSImportVisitor::parseBindingExpression(name, statement, associatedPropertyDefinition); +} + void LinterVisitor::handleLiteralBinding(const QQmlJSMetaPropertyBinding &binding, const UiPublicMember *associatedPropertyDefinition) { diff --git a/src/qmlcompiler/qqmljslintervisitor_p.h b/src/qmlcompiler/qqmljslintervisitor_p.h index 416dc972c1..efec9b3abf 100644 --- a/src/qmlcompiler/qqmljslintervisitor_p.h +++ b/src/qmlcompiler/qqmljslintervisitor_p.h @@ -92,6 +92,9 @@ private: void warnCaseNoFlowControl(QQmlJS::SourceLocation caseToken) const; void checkCaseFallthrough(QQmlJS::AST::StatementList *statements, SourceLocation errorLoc, SourceLocation nextLoc); + BindingExpressionParseResult parseBindingExpression( + const QString &name, const QQmlJS::AST::Statement *statement, + const QQmlJS::AST::UiPublicMember *associatedPropertyDefinition = nullptr) override; void handleLiteralBinding(const QQmlJSMetaPropertyBinding &binding, const AST::UiPublicMember *associatedPropertyDefinition) override; }; diff --git a/src/qmlcompiler/qqmljslogger.cpp b/src/qmlcompiler/qqmljslogger.cpp index d3cf05fb1d..40bdd9c48d 100644 --- a/src/qmlcompiler/qqmljslogger.cpp +++ b/src/qmlcompiler/qqmljslogger.cpp @@ -131,6 +131,8 @@ using namespace Qt::StringLiterals; false, false) \ X(qmlUncreatableType, "uncreatable-type", "UncreatableType", \ "Warn if uncreatable types are created", QtWarningMsg, false, false) \ + X(qmlUnintentionalEmptyBlock, "unintentional-empty-block", "UnintentionalEmptyBlock", \ + "Warn about bindings that contain only an empty block", QtWarningMsg, false, false) \ X(qmlUnqualified, "unqualified", "UnqualifiedAccess", \ "Warn about unqualified identifiers and how to fix them", QtWarningMsg, false, false) \ X(qmlUnreachableCode, "unreachable-code", "UnreachableCode", "Warn about unreachable code.", \ diff --git a/src/qmlcompiler/qqmljsloggingutils.h b/src/qmlcompiler/qqmljsloggingutils.h index c33fe5a407..05067c7d64 100644 --- a/src/qmlcompiler/qqmljsloggingutils.h +++ b/src/qmlcompiler/qqmljsloggingutils.h @@ -88,6 +88,7 @@ extern const Q_QMLCOMPILER_EXPORT QQmlSA::LoggerWarningId qmlSyntaxIdQuotation; extern const Q_QMLCOMPILER_EXPORT QQmlSA::LoggerWarningId qmlTopLevelComponent; extern const Q_QMLCOMPILER_EXPORT QQmlSA::LoggerWarningId qmlTranslationFunctionMismatch; extern const Q_QMLCOMPILER_EXPORT QQmlSA::LoggerWarningId qmlUncreatableType; +extern const Q_QMLCOMPILER_EXPORT QQmlSA::LoggerWarningId qmlUnintentionalEmptyBlock; extern const Q_QMLCOMPILER_EXPORT QQmlSA::LoggerWarningId qmlUnqualified; extern const Q_QMLCOMPILER_EXPORT QQmlSA::LoggerWarningId qmlUnreachableCode; extern const Q_QMLCOMPILER_EXPORT QQmlSA::LoggerWarningId qmlUnresolvedAlias; |