Report clashing qmldir entries for components and scripts
authorMatthew Vogt <matthew.vogt@nokia.com>
Tue, 19 Jun 2012 02:57:57 +0000 (12:57 +1000)
committerQt by Nokia <qt-info@nokia.com>
Thu, 21 Jun 2012 22:13:20 +0000 (00:13 +0200)
If a qmldir contains multiple lines that install the same versioned
property for a single component name or script qualifier, report an
error rather than silently suppress one entry.

Task-number: QTBUG-25834
Change-Id: I25d3a24102a5a4fa3d82f1d31d7e52505026fff7
Reviewed-by: Chris Adams <christopher.adams@nokia.com>
src/qml/qml/qqmlimport.cpp
tests/auto/qml/qqmllanguage/data/lib/com/nokia/installedtest1/Test1.qml [new file with mode: 0644]
tests/auto/qml/qqmllanguage/data/lib/com/nokia/installedtest1/Test2.qml [new file with mode: 0644]
tests/auto/qml/qqmllanguage/data/lib/com/nokia/installedtest1/qmldir [new file with mode: 0644]
tests/auto/qml/qqmllanguage/data/lib/com/nokia/installedtest2/qmldir [new file with mode: 0644]
tests/auto/qml/qqmllanguage/data/lib/com/nokia/installedtest2/test1.js [new file with mode: 0644]
tests/auto/qml/qqmllanguage/data/lib/com/nokia/installedtest2/test2.js [new file with mode: 0644]
tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp

index 9bdc67a..f1e9074 100644 (file)
@@ -852,19 +852,45 @@ bool QQmlImportsPrivate::addImport(const QQmlDirComponents &qmldircomponentsnetw
                 typedef QQmlDirComponents::const_iterator ConstIterator;
                 typedef QList<QQmlDirParser::Script>::const_iterator SConstIterator;
 
-                ConstIterator cend = qmldircomponents.end();
-                for (ConstIterator cit = qmldircomponents.begin(); cit != cend; ++cit) {
+                ConstIterator cend = qmldircomponents.constEnd();
+                for (ConstIterator cit = qmldircomponents.constBegin(); cit != cend; ++cit) {
+                    for (ConstIterator cit2 = qmldircomponents.constBegin(); cit2 != cit; ++cit2) {
+                        if ((cit2->typeName == cit->typeName) &&
+                            (cit2->majorVersion == cit->majorVersion) &&
+                            (cit2->minorVersion == cit->minorVersion)) {
+                            // This is entry clashes with a predecessor
+                            QQmlError error;
+                            error.setDescription(tr("\"%1\" version %2.%3 is already defined in module \"%4\"")
+                                                 .arg(cit->typeName).arg(cit->majorVersion).arg(cit->minorVersion).arg(importedUri));
+                            errors->prepend(error);
+                            return false;
+                        }
+                    }
+
                     if (cit->majorVersion == vmaj) {
                         lowest_min = qMin(lowest_min, cit->minorVersion);
                         highest_min = qMax(highest_min, cit->minorVersion);
                     }
                 }
 
-                for (SConstIterator cit = qmldirscripts.constBegin();
-                     cit != qmldirscripts.constEnd(); ++cit) {
-                    if (cit->majorVersion == vmaj) {
-                        lowest_min = qMin(lowest_min, cit->minorVersion);
-                        highest_min = qMax(highest_min, cit->minorVersion);
+                SConstIterator send = qmldirscripts.constEnd();
+                for (SConstIterator sit = qmldirscripts.constBegin(); sit != send; ++sit) {
+                    for (SConstIterator sit2 = qmldirscripts.constBegin(); sit2 != sit; ++sit2) {
+                        if ((sit2->nameSpace == sit->nameSpace) &&
+                            (sit2->majorVersion == sit->majorVersion) &&
+                            (sit2->minorVersion == sit->minorVersion)) {
+                            // This is entry clashes with a predecessor
+                            QQmlError error;
+                            error.setDescription(tr("\"%1\" version %2.%3 is already defined in module \"%4\"")
+                                                 .arg(sit->nameSpace).arg(sit->majorVersion).arg(sit->minorVersion).arg(importedUri));
+                            errors->prepend(error);
+                            return false;
+                        }
+                    }
+
+                    if (sit->majorVersion == vmaj) {
+                        lowest_min = qMin(lowest_min, sit->minorVersion);
+                        highest_min = qMax(highest_min, sit->minorVersion);
                     }
                 }
 
diff --git a/tests/auto/qml/qqmllanguage/data/lib/com/nokia/installedtest1/Test1.qml b/tests/auto/qml/qqmllanguage/data/lib/com/nokia/installedtest1/Test1.qml
new file mode 100644 (file)
index 0000000..617bdaa
--- /dev/null
@@ -0,0 +1,3 @@
+import QtQuick 2.0
+
+Item {}
diff --git a/tests/auto/qml/qqmllanguage/data/lib/com/nokia/installedtest1/Test2.qml b/tests/auto/qml/qqmllanguage/data/lib/com/nokia/installedtest1/Test2.qml
new file mode 100644 (file)
index 0000000..617bdaa
--- /dev/null
@@ -0,0 +1,3 @@
+import QtQuick 2.0
+
+Item {}
diff --git a/tests/auto/qml/qqmllanguage/data/lib/com/nokia/installedtest1/qmldir b/tests/auto/qml/qqmllanguage/data/lib/com/nokia/installedtest1/qmldir
new file mode 100644 (file)
index 0000000..90ad9fd
--- /dev/null
@@ -0,0 +1,2 @@
+Test 1.0 Test1.qml
+Test 1.0 Test2.qml
diff --git a/tests/auto/qml/qqmllanguage/data/lib/com/nokia/installedtest2/qmldir b/tests/auto/qml/qqmllanguage/data/lib/com/nokia/installedtest2/qmldir
new file mode 100644 (file)
index 0000000..c492dec
--- /dev/null
@@ -0,0 +1,2 @@
+Test 1.0 test1.js
+Test 1.0 test2.js
diff --git a/tests/auto/qml/qqmllanguage/data/lib/com/nokia/installedtest2/test1.js b/tests/auto/qml/qqmllanguage/data/lib/com/nokia/installedtest2/test1.js
new file mode 100644 (file)
index 0000000..6a53b53
--- /dev/null
@@ -0,0 +1 @@
+var foo = 1
diff --git a/tests/auto/qml/qqmllanguage/data/lib/com/nokia/installedtest2/test2.js b/tests/auto/qml/qqmllanguage/data/lib/com/nokia/installedtest2/test2.js
new file mode 100644 (file)
index 0000000..34d5cdd
--- /dev/null
@@ -0,0 +1 @@
+var bar = 2
index 9205f2d..d5abef3 100644 (file)
@@ -2201,6 +2201,16 @@ void tst_qqmllanguage::importsInstalled_data()
            "PrivateType {}"
         << ""
         << "PrivateType is not a type";
+    QTest::newRow("installed import version QML clash")
+        << "import com.nokia.installedtest1 1.0\n"
+           "Test {}"
+        << ""
+        << "\"Test\" version 1.0 is already defined in module \"com.nokia.installedtest1\"";
+    QTest::newRow("installed import version JS clash")
+        << "import com.nokia.installedtest2 1.0\n"
+           "Test {}"
+        << ""
+        << "\"Test\" version 1.0 is already defined in module \"com.nokia.installedtest2\"";
 }
 
 void tst_qqmllanguage::importsInstalled()