diff options
| -rw-r--r-- | src/qmlcompiler/qqmljsimportvisitor.cpp | 24 | ||||
| -rw-r--r-- | src/qmlcompiler/qqmljsimportvisitor_p.h | 2 | ||||
| -rw-r--r-- | tests/auto/qml/qmllint/tst_qmllint.cpp | 36 |
3 files changed, 48 insertions, 14 deletions
diff --git a/src/qmlcompiler/qqmljsimportvisitor.cpp b/src/qmlcompiler/qqmljsimportvisitor.cpp index 6f1558383d..6c1d22c90d 100644 --- a/src/qmlcompiler/qqmljsimportvisitor.cpp +++ b/src/qmlcompiler/qqmljsimportvisitor.cpp @@ -2398,6 +2398,19 @@ void QQmlJSImportVisitor::endVisit(UiArrayBinding *arrayBinding) } } +void QQmlJSImportVisitor::handleDuplicateEnums(UiEnumMemberList *members, const QString &key, + const QQmlJS::SourceLocation &location) +{ + m_logger->log(u"Enum key '%1' has already been declared"_s.arg(key), qmlSyntax, location); + for (const auto *member = members; member; member = member->next) { + if (member->member.toString() == key) { + m_logger->log(u"Note: previous declaration of '%1' here"_s.arg(key), qmlSyntax, + member->memberToken); + return; + } + } +} + bool QQmlJSImportVisitor::visit(QQmlJS::AST::UiEnumDeclaration *uied) { if (m_currentScope->inlineComponentName()) { @@ -2407,7 +2420,16 @@ bool QQmlJSImportVisitor::visit(QQmlJS::AST::UiEnumDeclaration *uied) QQmlJSMetaEnum qmlEnum(uied->name.toString()); qmlEnum.setIsQml(true); for (const auto *member = uied->members; member; member = member->next) { - qmlEnum.addKey(member->member.toString()); + const QString key = member->member.toString(); + + if (!key.front().isUpper()) { + m_logger->log(u"Enum keys should start with an uppercase."_s, qmlSyntax, + member->memberToken); + } + if (qmlEnum.hasKey(key)) + handleDuplicateEnums(uied->members, key, member->memberToken); + + qmlEnum.addKey(key); qmlEnum.addValue(int(member->value)); } m_currentScope->addOwnEnumeration(qmlEnum); diff --git a/src/qmlcompiler/qqmljsimportvisitor_p.h b/src/qmlcompiler/qqmljsimportvisitor_p.h index 0d12ea0b6a..5de1c80c32 100644 --- a/src/qmlcompiler/qqmljsimportvisitor_p.h +++ b/src/qmlcompiler/qqmljsimportvisitor_p.h @@ -109,6 +109,8 @@ protected: bool visit(QQmlJS::AST::UiArrayBinding *) override; void endVisit(QQmlJS::AST::UiArrayBinding *) override; bool visit(QQmlJS::AST::UiEnumDeclaration *uied) override; + void handleDuplicateEnums(QQmlJS::AST::UiEnumMemberList *members, const QString &key, + const QQmlJS::SourceLocation &location); bool visit(QQmlJS::AST::FunctionExpression *fexpr) override; void endVisit(QQmlJS::AST::FunctionExpression *) override; bool visit(QQmlJS::AST::UiSourceElement *) override; diff --git a/tests/auto/qml/qmllint/tst_qmllint.cpp b/tests/auto/qml/qmllint/tst_qmllint.cpp index a151b70f13..5aaf05612b 100644 --- a/tests/auto/qml/qmllint/tst_qmllint.cpp +++ b/tests/auto/qml/qmllint/tst_qmllint.cpp @@ -1324,6 +1324,20 @@ void TestQmllint::dirtyQmlCode() }); } +static void addLocationOffsetTo(TestQmllint::Result *result, qsizetype lineOffset, + qsizetype columnOffset = 0) +{ + for (auto *messages : + { &result->expectedMessages, &result->badMessages, &result->expectedReplacements }) { + for (auto &message : *messages) { + if (message.line != 0) + message.line += lineOffset; + if (message.column != 0) + message.column += columnOffset; + } + } +} + void TestQmllint::dirtyQmlSnippet_data() { QTest::addColumn<QString>("code"); @@ -1331,6 +1345,11 @@ void TestQmllint::dirtyQmlSnippet_data() QTest::newRow("testSnippet") << u"property int qwer: \"Hello\""_s << Result{ { { "Cannot assign literal of type string to int"_L1 } } }; + + QTest::newRow("enum") << u"enum Hello { World, Kitty, World, dlrow }"_s + << Result{ { { "Enum key 'World' has already been declared"_L1, 1, 28 }, + { "Note: previous declaration of 'World' here"_L1, 1, 14 }, + { "Enum keys should start with an uppercase"_L1, 1, 35 } } }; } void TestQmllint::dirtyQmlSnippet() @@ -1338,7 +1357,9 @@ void TestQmllint::dirtyQmlSnippet() QFETCH(QString, code); QFETCH(Result, result); - QString qmlCode = "import QtQuick\nItem {%1}"_L1.arg(code); + QString qmlCode = "import QtQuick\nItem {\n%1}"_L1.arg(code); + + addLocationOffsetTo(&result, 2); QJsonArray warnings; callQmllint(QString(), result.flags.testFlag(Result::ExitsNormally), &warnings, {}, {}, {}, @@ -1353,6 +1374,7 @@ void TestQmllint::cleanQmlSnippet_data() QTest::addColumn<QString>("code"); QTest::newRow("testSnippet") << u"property int qwer: 123"_s; + QTest::newRow("enum") << u"enum Hello { World, Kitty, DlroW }"_s; } void TestQmllint::cleanQmlSnippet() @@ -1386,18 +1408,6 @@ void TestQmllint::dirtyJsSnippet_data() }; } -static void addLocationOffsetTo(TestQmllint::Result *result, qsizetype lineOffset, - qsizetype columnOffset = 0) -{ - for (auto *messages : - { &result->expectedMessages, &result->badMessages, &result->expectedReplacements }) { - for (auto &message : *messages) { - message.line += lineOffset; - message.column += columnOffset; - } - } -} - void TestQmllint::dirtyJsSnippet() { QFETCH(QString, code); |
