diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2020-03-16 14:50:24 +0100 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2020-03-19 16:37:44 +0100 |
commit | f726d237277de0f4c8f276d20a5bb1b6a8cd007c (patch) | |
tree | b6e089eb68027297447bcd2cfd633830679855f5 | |
parent | 266dbbef1fdc34a9740458e86f0a0ee3fffa3f98 (diff) |
qmllint: Break inheritance cycles
Previously we would run into infinite loops on those. Mind that qmllint
will reject a file called Window.qml that imports QtQuick.Window and
then instantiates a Window {}. Such a thing is bad style.
Task-number: QTBUG-82817
Change-Id: I6db82ca1794c3020dcb7d7e837fe44f72bca5029
Reviewed-by: Maximilian Goldstein <max.goldstein@qt.io>
Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
-rw-r--r-- | tests/auto/qml/qmllint/data/Cycle1.qml | 2 | ||||
-rw-r--r-- | tests/auto/qml/qmllint/data/Cycle2.qml | 2 | ||||
-rw-r--r-- | tests/auto/qml/qmllint/data/Cycle3.qml | 2 | ||||
-rw-r--r-- | tests/auto/qml/qmllint/tst_qmllint.cpp | 4 | ||||
-rw-r--r-- | tools/qmllint/findunqualified.cpp | 17 |
5 files changed, 27 insertions, 0 deletions
diff --git a/tests/auto/qml/qmllint/data/Cycle1.qml b/tests/auto/qml/qmllint/data/Cycle1.qml new file mode 100644 index 0000000000..8095e9f732 --- /dev/null +++ b/tests/auto/qml/qmllint/data/Cycle1.qml @@ -0,0 +1,2 @@ +import QtQml 2.0 +Cycle2 {} diff --git a/tests/auto/qml/qmllint/data/Cycle2.qml b/tests/auto/qml/qmllint/data/Cycle2.qml new file mode 100644 index 0000000000..90c376fcda --- /dev/null +++ b/tests/auto/qml/qmllint/data/Cycle2.qml @@ -0,0 +1,2 @@ +import QtQml 2.0 +Cycle3 {} diff --git a/tests/auto/qml/qmllint/data/Cycle3.qml b/tests/auto/qml/qmllint/data/Cycle3.qml new file mode 100644 index 0000000000..f4cba68653 --- /dev/null +++ b/tests/auto/qml/qmllint/data/Cycle3.qml @@ -0,0 +1,2 @@ +import QtQml 2.0 +Cycle1 {} diff --git a/tests/auto/qml/qmllint/tst_qmllint.cpp b/tests/auto/qml/qmllint/tst_qmllint.cpp index ed968d6623..8697495a6f 100644 --- a/tests/auto/qml/qmllint/tst_qmllint.cpp +++ b/tests/auto/qml/qmllint/tst_qmllint.cpp @@ -164,6 +164,10 @@ void TestQmllint::dirtyQmlCode_data() << QStringLiteral("incompleteQmltypes.qml") << QString("Warning: Type \"QPalette\" of member \"palette\" not found at 5:26") << QString(); + QTest::newRow("inheritanceCylce") + << QStringLiteral("Cycle1.qml") + << QString("Warning: Cycle2 is part of an inheritance cycle: Cycle2 -> Cycle3 -> Cycle1 -> Cycle2") + << QString(); } void TestQmllint::dirtyQmlCode() diff --git a/tools/qmllint/findunqualified.cpp b/tools/qmllint/findunqualified.cpp index 5bb9b62529..9bb9395015 100644 --- a/tools/qmllint/findunqualified.cpp +++ b/tools/qmllint/findunqualified.cpp @@ -367,11 +367,28 @@ void FindUnqualifiedIDVisitor::importFileOrDirectory(const QString &fileOrDirect void FindUnqualifiedIDVisitor::importExportedNames(const QStringRef &prefix, QString name) { + QList<ScopeTree::ConstPtr> scopes; for (;;) { ScopeTree::ConstPtr scope = m_exportedName2Scope.value(m_exportedName2Scope.contains(name) ? name : prefix + QLatin1Char('.') + name); if (scope) { + if (scopes.contains(scope)) { + QString inheritenceCycle = name; + for (const auto seen: qAsConst(scopes)) { + inheritenceCycle.append(QLatin1String(" -> ")); + inheritenceCycle.append(seen->superclassName()); + } + + m_colorOut.write(QLatin1String("Warning: "), Warning); + m_colorOut.write(QString::fromLatin1("%1 is part of an inheritance cycle: %2\n") + .arg(name) + .arg(inheritenceCycle)); + m_unknownImports.insert(name); + m_visitFailed = true; + break; + } + scopes.append(scope); const auto properties = scope->properties(); for (auto property : properties) { property.setType(m_exportedName2Scope.value(property.typeName()).get()); |