summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Alpert <aalpert@rim.com>2012-12-03 08:48:18 -0800
committerThe Qt Project <gerrit-noreply@qt-project.org>2012-12-05 19:20:51 +0100
commitdc96bfd00152e25f007511f64bff7c413f657886 (patch)
treeaa5ee99d99c5e8c64dbb36eb038398e2e399abab
parentad86cd24157cc6ded679f40807591981fe52d540 (diff)
Delay loading implicit import
As a performance improvement to avoid accessing the filesystem unecessarily, only import "." implicitly if types cannot be found in the existing imports. This is not a behavior change for type resolution, because "." already has the lowest precedence for type resolution. Change-Id: I8a8f10f7a790e6a02fc2c07c443f7be1984fc979 Reviewed-by: Matthew Vogt <matthew.vogt@qinetic.com.au> Reviewed-by: Christopher Adams <chris.adams@jollamobile.com>
-rw-r--r--src/declarative/qml/qdeclarativeimport.cpp28
-rw-r--r--src/declarative/qml/qdeclarativescriptparser_p.h2
-rw-r--r--src/declarative/qml/qdeclarativetypeloader.cpp72
-rw-r--r--tests/auto/declarative/qdeclarativelanguage/data/LocalLast2.qml2
-rw-r--r--tests/auto/declarative/qdeclarativelanguage/data/localOrderTest.qml7
-rw-r--r--tests/auto/declarative/qdeclarativelanguage/tst_qdeclarativelanguage.cpp23
6 files changed, 98 insertions, 36 deletions
diff --git a/src/declarative/qml/qdeclarativeimport.cpp b/src/declarative/qml/qdeclarativeimport.cpp
index 20331786..db062e47 100644
--- a/src/declarative/qml/qdeclarativeimport.cpp
+++ b/src/declarative/qml/qdeclarativeimport.cpp
@@ -441,6 +441,13 @@ bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomp
set.insert(prefix,(s=new QDeclarativeImportedNamespace));
}
+ bool appendInstead = false;
+ if (importType == QDeclarativeScriptParser::Import::Implicit) {
+ //Treat same as a File import, but lower precedence
+ appendInstead = true;
+ importType = QDeclarativeScriptParser::Import::File;
+ }
+
QString url = uri;
bool versionFound = false;
if (importType == QDeclarativeScriptParser::Import::Library) {
@@ -588,12 +595,21 @@ bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomp
}
}
- s->uris.prepend(uri);
- s->urls.prepend(url);
- s->majversions.prepend(vmaj);
- s->minversions.prepend(vmin);
- s->isLibrary.prepend(importType == QDeclarativeScriptParser::Import::Library);
- s->qmlDirComponents.prepend(qmldircomponents);
+ if (appendInstead) {
+ s->uris.append(uri);
+ s->urls.append(url);
+ s->majversions.append(vmaj);
+ s->minversions.append(vmin);
+ s->isLibrary.append(importType == QDeclarativeScriptParser::Import::Library);
+ s->qmlDirComponents.append(qmldircomponents);
+ } else {
+ s->uris.prepend(uri);
+ s->urls.prepend(url);
+ s->majversions.prepend(vmaj);
+ s->minversions.prepend(vmin);
+ s->isLibrary.prepend(importType == QDeclarativeScriptParser::Import::Library);
+ s->qmlDirComponents.prepend(qmldircomponents);
+ }
return true;
}
diff --git a/src/declarative/qml/qdeclarativescriptparser_p.h b/src/declarative/qml/qdeclarativescriptparser_p.h
index 671326a2..0d02aba5 100644
--- a/src/declarative/qml/qdeclarativescriptparser_p.h
+++ b/src/declarative/qml/qdeclarativescriptparser_p.h
@@ -75,7 +75,7 @@ public:
public:
Import() : type(Library) {}
- enum Type { Library, File, Script };
+ enum Type { Library, File, Script, Implicit }; //Implicit is only used internally
Type type;
QString uri;
diff --git a/src/declarative/qml/qdeclarativetypeloader.cpp b/src/declarative/qml/qdeclarativetypeloader.cpp
index 012afb39..135bff89 100644
--- a/src/declarative/qml/qdeclarativetypeloader.cpp
+++ b/src/declarative/qml/qdeclarativetypeloader.cpp
@@ -1055,19 +1055,6 @@ void QDeclarativeTypeData::resolveTypes()
QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(m_typeLoader->engine());
QDeclarativeImportDatabase *importDatabase = &ep->importDatabase;
- // For local urls, add an implicit import "." as first (most overridden) lookup.
- // This will also trigger the loading of the qmldir and the import of any native
- // types from available plugins.
- if (QDeclarativeQmldirData *qmldir = qmldirForUrl(finalUrl().resolved(QUrl(QLatin1String("./qmldir"))))) {
- m_imports.addImport(importDatabase, QLatin1String("."),
- QString(), -1, -1, QDeclarativeScriptParser::Import::File,
- qmldir->dirComponents(), 0);
- } else {
- m_imports.addImport(importDatabase, QLatin1String("."),
- QString(), -1, -1, QDeclarativeScriptParser::Import::File,
- QDeclarativeDirComponents(), 0);
- }
-
foreach (const QDeclarativeScriptParser::Import &import, scriptParser.imports()) {
QDeclarativeDirComponents qmldircomponentsnetwork;
if (import.type == QDeclarativeScriptParser::Import::Script)
@@ -1107,6 +1094,7 @@ void QDeclarativeTypeData::resolveTypes()
}
}
+ bool implicitImportLoaded = false;
foreach (QDeclarativeScriptParser::TypeReference *parserRef, scriptParser.referencedTypes()) {
QByteArray typeName = parserRef->name.toUtf8();
@@ -1123,23 +1111,49 @@ void QDeclarativeTypeData::resolveTypes()
// Known to not be a type:
// - known to be a namespace (Namespace {})
// - type with unknown namespace (UnknownNamespace.SomeType {})
- QDeclarativeError error;
- error.setUrl(m_imports.baseUrl());
- QString userTypeName = parserRef->name;
- userTypeName.replace(QLatin1Char('/'),QLatin1Char('.'));
- if (typeNamespace)
- error.setDescription(QDeclarativeTypeLoader::tr("Namespace %1 cannot be used as a type").arg(userTypeName));
- else
- error.setDescription(QDeclarativeTypeLoader::tr("%1 %2").arg(userTypeName).arg(errorString));
-
- if (!parserRef->refObjects.isEmpty()) {
- QDeclarativeParser::Object *obj = parserRef->refObjects.first();
- error.setLine(obj->location.start.line);
- error.setColumn(obj->location.start.column);
+ bool typeFound = false;
+
+ if (!typeNamespace && !implicitImportLoaded) {
+ implicitImportLoaded = true;
+ // For local urls, add an implicit import "." as most overridden lookup.
+ // This will also trigger the loading of the qmldir and the import of any native
+ // types from available plugins.
+ // This is only done if the type is not otherwise found, side effects of plugin loading may be avoided
+ // ### This should be an acceptable variation because A) It's only side effects (and img providers) B) You shouldn't be doing that in "." anyways!
+ if (QDeclarativeQmldirData *qmldir = qmldirForUrl(finalUrl().resolved(QUrl(QLatin1String("./qmldir"))))) {
+ m_imports.addImport(importDatabase, QLatin1String("."),
+ QString(), -1, -1, QDeclarativeScriptParser::Import::Implicit,
+ qmldir->dirComponents(), 0);
+ } else {
+ m_imports.addImport(importDatabase, QLatin1String("."),
+ QString(), -1, -1, QDeclarativeScriptParser::Import::Implicit,
+ QDeclarativeDirComponents(), 0);
+ }
+ if (m_imports.resolveType(typeName, &ref.type, &url, &majorVersion, &minorVersion,
+ &typeNamespace, &errorString) || typeNamespace) {
+ typeFound = true;
+ }
+ }
+
+ if (!typeFound) {
+ QDeclarativeError error;
+ error.setUrl(m_imports.baseUrl());
+ QString userTypeName = parserRef->name;
+ userTypeName.replace(QLatin1Char('/'),QLatin1Char('.'));
+ if (typeNamespace)
+ error.setDescription(QDeclarativeTypeLoader::tr("Namespace %1 cannot be used as a type").arg(userTypeName));
+ else
+ error.setDescription(QDeclarativeTypeLoader::tr("%1 %2").arg(userTypeName).arg(errorString));
+
+ if (!parserRef->refObjects.isEmpty()) {
+ QDeclarativeParser::Object *obj = parserRef->refObjects.first();
+ error.setLine(obj->location.start.line);
+ error.setColumn(obj->location.start.column);
+ }
+
+ setError(error);
+ return;
}
-
- setError(error);
- return;
}
if (ref.type) {
diff --git a/tests/auto/declarative/qdeclarativelanguage/data/LocalLast2.qml b/tests/auto/declarative/qdeclarativelanguage/data/LocalLast2.qml
new file mode 100644
index 00000000..4bf7eb2e
--- /dev/null
+++ b/tests/auto/declarative/qdeclarativelanguage/data/LocalLast2.qml
@@ -0,0 +1,2 @@
+import QtQuick 1.0
+MouseArea {}
diff --git a/tests/auto/declarative/qdeclarativelanguage/data/localOrderTest.qml b/tests/auto/declarative/qdeclarativelanguage/data/localOrderTest.qml
new file mode 100644
index 00000000..bdb13756
--- /dev/null
+++ b/tests/auto/declarative/qdeclarativelanguage/data/localOrderTest.qml
@@ -0,0 +1,7 @@
+import QtQuick 1.0
+import com.nokia.installedtest 1.0
+
+LocalLast2 {
+ property Item item: LocalLast {}
+}
+
diff --git a/tests/auto/declarative/qdeclarativelanguage/tst_qdeclarativelanguage.cpp b/tests/auto/declarative/qdeclarativelanguage/tst_qdeclarativelanguage.cpp
index e201807b..edbfeeb8 100644
--- a/tests/auto/declarative/qdeclarativelanguage/tst_qdeclarativelanguage.cpp
+++ b/tests/auto/declarative/qdeclarativelanguage/tst_qdeclarativelanguage.cpp
@@ -132,6 +132,7 @@ private slots:
void reservedWords();
void inlineAssignmentsOverrideBindings();
void nestedComponentRoots();
+ void implicitImportsLast();
void basicRemote_data();
void basicRemote();
@@ -1806,6 +1807,11 @@ void tst_qdeclarativelanguage::importsOrder_data()
"LocalLast {}"
<< (!qmlCheckTypes()?"QDeclarativeRectangle":"")// i.e. from com.nokia.installedtest, not data/LocalLast.qml
<< (!qmlCheckTypes()?"":"LocalLast is ambiguous. Found in lib/com/nokia/installedtest and in local directory");
+ QTest::newRow("local last 3") <<
+ "import com.nokia.installedtest 1.0\n"
+ "LocalLast {LocalLast2{}}"
+ << (!qmlCheckTypes()?"QDeclarativeRectangle":"")// i.e. from com.nokia.installedtest, not data/LocalLast.qml
+ << (!qmlCheckTypes()?"":"LocalLast is ambiguous. Found in lib/com/nokia/installedtest and in local directory");
}
void tst_qdeclarativelanguage::importsOrder()
@@ -2021,6 +2027,23 @@ void tst_qdeclarativelanguage::compatibilitySemicolon()
QVERIFY(o != 0);
}
+// Tests that the implicit import has lowest precedence, in the case where
+// there are conflicting types and types only found in the local import.
+// Tests that just check one (or the root) type are in ::importsOrder
+void tst_qdeclarativelanguage::implicitImportsLast()
+{
+ if (qmlCheckTypes())
+ QSKIP("This test is about maintaining the same choice when type is ambiguous.");
+ QDeclarativeComponent component(&engine, testFileUrl("localOrderTest.qml"));
+ VERIFY_ERRORS(0);
+ QObject *object = qobject_cast<QObject *>(component.create());
+ QVERIFY(object != 0);
+ QVERIFY(QString(object->metaObject()->className()).startsWith(QLatin1String("QDeclarativeMouseArea")));
+ QObject* object2 = object->property("item").value<QObject*>();
+ QVERIFY(object2 != 0);
+ QCOMPARE(QString(object2->metaObject()->className()), QLatin1String("QDeclarativeRectangle"));
+}
+
QTEST_MAIN(tst_qdeclarativelanguage)
#include "tst_qdeclarativelanguage.moc"