Fix parsing of JS imports from JS files
authorSimon Hausmann <simon.hausmann@digia.com>
Wed, 9 Apr 2014 13:39:37 +0000 (15:39 +0200)
committerThe Qt Project <gerrit-noreply@qt-project.org>
Thu, 24 Apr 2014 13:36:42 +0000 (15:36 +0200)
If a .js file had an import of another .js file itself, like so:

    .import "otherFile.js" as Blah

then the import scanner would keep the quotes and store

    "\"otherFile.js\""

in the JSON as opposed to

    "otherFile.js"

This is fixed by making use of the same code for extracting the .import
statements from JS files that is also used by the engine itself.

Additionally this fixes the use of comments in .import lines (and other
whitespace characters not producing tokens).

Change-Id: I4dd4a5217308f6fc93b6b148cd8e13392f97d2a6
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
tools/qmlimportscanner/main.cpp

index d3c5c638e909eb76d30ee844e4812dbd1d4745e2..9ad315016f1a2960d06e2ffc968c39e07f691c72 100644 (file)
@@ -43,7 +43,9 @@
 #include <private/qqmljsparser_p.h>
 #include <private/qqmljsast_p.h>
 #include <private/qv4codegen_p.h>
+#include <private/qv4value_inl_p.h>
 #include <private/qqmlpool_p.h>
+#include <private/qqmlirbuilder_p.h>
 
 #include <QtCore/QCoreApplication>
 #include <QtCore/QDir>
@@ -238,38 +240,38 @@ QVariantList findQmlImportsInJavascriptFile(const QString &filePath)
 
     QVariantList imports;
 
-    // look for ".import Foo.Bar 2.0 as FooBar" lines
-    do {
-        QByteArray rawLine = file.readLine();
-        QByteArray line = rawLine.simplified();
-        if (line.simplified().startsWith(".import")) {
-            QList<QByteArray> parts = line.split(' ');
-
-            if (parts.count() < 2)
-                continue;
-
-            QVariantMap import;
-            QByteArray name = parts.at(1);
-            QByteArray version = parts.at(2);
-
-            // handle import cases: .js file, diriectory (check for precense of "/"),
-            // and module (the most common case)
-            if (name.contains(".js")) {
-                import[QStringLiteral("type")] = QStringLiteral("javascript");
-                import[QStringLiteral("path")] = name;
-            } else if (name.contains("/")) {
-                import[QStringLiteral("type")] = QStringLiteral("directory");
-                import[QStringLiteral("path")] = name;
+    QString sourceCode = QString::fromUtf8(file.readAll());
+    file.close();
+    QmlIR::Document doc(/*debug mode*/false);
+    QQmlJS::DiagnosticMessage error;
+    doc.extractScriptMetaData(sourceCode, &error);
+    if (!error.message.isEmpty())
+        return imports;
+
+    foreach (const QV4::CompiledData::Import *import, doc.imports) {
+        QVariantMap entry;
+        const QString name = doc.stringAt(import->uriIndex);
+        switch (import->type) {
+        case QV4::CompiledData::Import::ImportScript:
+            entry[QStringLiteral("type")] = QStringLiteral("javascript");
+            entry[QStringLiteral("path")] = name;
+            break;
+        case QV4::CompiledData::Import::ImportLibrary:
+            if (name.contains(QLatin1Char('/'))) {
+                entry[QStringLiteral("type")] = QStringLiteral("directory");
+                entry[QStringLiteral("name")] = name;
             } else {
-                import[QStringLiteral("type")] = QStringLiteral("module");
-                import[QStringLiteral("name")] = name;
-                import[QStringLiteral("version")] = version;
+                entry[QStringLiteral("type")] = QStringLiteral("module");
+                entry[QStringLiteral("name")] = name;
+                entry[QStringLiteral("version")] = QString::number(import->majorVersion) + QLatin1Char('.') + QString::number(import->minorVersion);
             }
-
-            imports.append(import);
+            break;
+        default:
+            Q_UNREACHABLE();
+            continue;
         }
+        imports << entry;
     }
-    while (file.canReadLine());
 
     return imports;
 }