aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorMorten Johan Sørvig <morten.sorvig@digia.com>2014-02-11 15:19:33 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-02-25 17:08:02 +0100
commitf7a8a41e48fda4d7cb395e435fad292770d9c467 (patch)
tree63308d0262c82c9a477fd1f8ab4deea3e914f1cc /tools
parent501bd0fa6709caff3d5425abc16fa8ef3f5c88af (diff)
Add support for scanning javascript files.
Javascript may contain ".import" pragmas/statements, which should be treated in a similar way as qml file imports. Add findQmlImportsInJavascriptFile() which extracts and parses the .import lines. Refactor findQmlImportsInFile() to handle both .qml and .js and call out to the correct parsing function. Add "-jsFiles" for specifying javascript files on the command line similar to "-qmlFiles". Task-number: QTBUG-35349 Change-Id: I6b8e0cc254c1edcf16940bec5cfda7c2637f115e Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
Diffstat (limited to 'tools')
-rw-r--r--tools/qmlimportscanner/main.cpp94
1 files changed, 77 insertions, 17 deletions
diff --git a/tools/qmlimportscanner/main.cpp b/tools/qmlimportscanner/main.cpp
index 08b88142bb..d3c5c638e9 100644
--- a/tools/qmlimportscanner/main.cpp
+++ b/tools/qmlimportscanner/main.cpp
@@ -200,15 +200,15 @@ QVariantList findPathsForModuleImports(const QVariantList &imports)
}
// Scan a single qml file for import statements
-QVariantList findQmlImportsInFile(const QString &qmlFilePath)
+QVariantList findQmlImportsInQmlFile(const QString &filePath)
{
- QFile qmlFile(qmlFilePath);
- if (!qmlFile.open(QIODevice::ReadOnly)) {
- std::cerr << "Cannot open input file " << QDir::toNativeSeparators(qmlFile.fileName()).toStdString()
- << ':' << qmlFile.errorString().toStdString() << std::endl;
+ QFile file(filePath);
+ if (!file.open(QIODevice::ReadOnly)) {
+ std::cerr << "Cannot open input file " << QDir::toNativeSeparators(file.fileName()).toStdString()
+ << ':' << file.errorString().toStdString() << std::endl;
return QVariantList();
}
- QString code = QString::fromUtf8(qmlFile.readAll());
+ QString code = QString::fromUtf8(file.readAll());
QQmlJS::Engine engine;
QQmlJS::Lexer lexer(&engine);
@@ -218,14 +218,72 @@ QVariantList findQmlImportsInFile(const QString &qmlFilePath)
if (!parser.parse() || !parser.diagnosticMessages().isEmpty()) {
// Extract errors from the parser
foreach (const QQmlJS::DiagnosticMessage &m, parser.diagnosticMessages()) {
- std::cerr << QDir::toNativeSeparators(qmlFile.fileName()).toStdString() << ':'
+ std::cerr << QDir::toNativeSeparators(file.fileName()).toStdString() << ':'
<< m.loc.startLine << ':' << m.message.toStdString() << std::endl;
}
return QVariantList();
}
+ return findImportsInAst(parser.ast()->headers, code, file.fileName());
+}
+
+// Scan a single javascrupt file for import statements
+QVariantList findQmlImportsInJavascriptFile(const QString &filePath)
+{
+ QFile file(filePath);
+ if (!file.open(QIODevice::ReadOnly)) {
+ std::cerr << "Cannot open input file " << QDir::toNativeSeparators(file.fileName()).toStdString()
+ << ':' << file.errorString().toStdString() << std::endl;
+ return QVariantList();
+ }
+
+ 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;
+ } else {
+ import[QStringLiteral("type")] = QStringLiteral("module");
+ import[QStringLiteral("name")] = name;
+ import[QStringLiteral("version")] = version;
+ }
+
+ imports.append(import);
+ }
+ }
+ while (file.canReadLine());
+
+ return imports;
+}
- return findPathsForModuleImports(
- findImportsInAst(parser.ast()->headers, code, QFileInfo(qmlFilePath).absolutePath()));
+// Scan a single qml or js file for import statements
+QVariantList findQmlImportsInFile(const QString &filePath)
+{
+ QVariantList imports;
+ if (filePath.endsWith(QStringLiteral(".qml")))
+ imports = findQmlImportsInQmlFile(filePath);
+ else if (filePath.endsWith(QStringLiteral(".js")))
+ imports = findQmlImportsInJavascriptFile(filePath);
+
+ return findPathsForModuleImports(imports);
}
// Merge two lists of imports, discard duplicates.
@@ -250,8 +308,6 @@ QVariantList findQmlImportsInDirectory(const QString &qmlDir)
while (iterator.hasNext()) {
iterator.next();
QString path = iterator.filePath();
- if (!path.endsWith(QStringLiteral(".qml")))
- continue;
// skip obvious build output directories
if (path.contains(QStringLiteral("Debug-iphoneos")) || path.contains(QStringLiteral("Release-iphoneos")) ||
@@ -284,7 +340,7 @@ QSet<QString> importModulePaths(QVariantList imports) {
// Find Qml Imports Recursively from a root set of qml files.
// The directories in qmlDirs are searched recursively.
// The files in qmlFiles parsed directly.
-QVariantList findQmlImportsRecursively(const QStringList &qmlDirs, const QStringList &qmlFiles)
+QVariantList findQmlImportsRecursively(const QStringList &qmlDirs, const QStringList &scanFiles)
{
QVariantList ret;
@@ -295,8 +351,8 @@ QVariantList findQmlImportsRecursively(const QStringList &qmlDirs, const QString
}
// scan app qml files for imports
- foreach (const QString &qmlFile, qmlFiles) {
- QVariantList imports = findQmlImportsInFile(qmlFile);
+ foreach (const QString &file, scanFiles) {
+ QVariantList imports = findQmlImportsInFile(file);
ret = mergeImports(ret, imports);
}
@@ -332,7 +388,7 @@ int main(int argc, char *argv[])
}
QStringList qmlRootPaths;
- QStringList qmlFiles;
+ QStringList scanFiles;
QStringList qmlImportPaths;
int i = 1;
@@ -349,7 +405,11 @@ int main(int argc, char *argv[])
} else if (arg == QLatin1String("-qmlFiles")) {
if (i >= args.count())
std::cerr << "-qmlFiles requires an argument\n";
- argReceiver = &qmlFiles;
+ argReceiver = &scanFiles;
+ } else if (arg == QLatin1String("-jsFiles")) {
+ if (i >= args.count())
+ std::cerr << "-jsFiles requires an argument\n";
+ argReceiver = &scanFiles;
} else if (arg == QLatin1String("-importPath")) {
if (i >= args.count())
std::cerr << "-importPath requires an argument\n";
@@ -371,7 +431,7 @@ int main(int argc, char *argv[])
g_qmlImportPaths = qmlImportPaths;
// Find the imports!
- QVariantList imports = findQmlImportsRecursively(qmlRootPaths, qmlFiles);
+ QVariantList imports = findQmlImportsRecursively(qmlRootPaths, scanFiles);
// Convert to JSON
QByteArray json = QJsonDocument(QJsonArray::fromVariantList(imports)).toJson();