aboutsummaryrefslogtreecommitdiffstats
path: root/tools/qmlimportscanner/main.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tools/qmlimportscanner/main.cpp')
-rw-r--r--tools/qmlimportscanner/main.cpp97
1 files changed, 79 insertions, 18 deletions
diff --git a/tools/qmlimportscanner/main.cpp b/tools/qmlimportscanner/main.cpp
index bc2dfce025..7365e1ad81 100644
--- a/tools/qmlimportscanner/main.cpp
+++ b/tools/qmlimportscanner/main.cpp
@@ -40,6 +40,7 @@
#include <QtCore/QDirIterator>
#include <QtCore/QFile>
#include <QtCore/QFileInfo>
+#include <QtCore/QHash>
#include <QtCore/QSet>
#include <QtCore/QStringList>
#include <QtCore/QMetaObject>
@@ -62,6 +63,8 @@ using namespace Qt::StringLiterals;
Q_LOGGING_CATEGORY(lcImportScanner, "qt.qml.import.scanner");
Q_LOGGING_CATEGORY(lcImportScannerFiles, "qt.qml.import.scanner.files");
+using FileImportsWithoutDepsCache = QHash<QString, QVariantList>;
+
namespace {
QStringList g_qmlImportPaths;
@@ -152,8 +155,9 @@ QVariantList findImportsInAst(QQmlJS::AST::UiHeaderItemList *headerItemList, con
return imports;
}
-QVariantList findQmlImportsInQmlFile(const QString &filePath);
-QVariantList findQmlImportsInJavascriptFile(const QString &filePath);
+QVariantList findQmlImportsInFileWithoutDeps(const QString &filePath,
+ FileImportsWithoutDepsCache
+ &fileImportsWithoutDepsCache);
static QString versionSuffix(QTypeRevision version)
{
@@ -163,7 +167,18 @@ static QString versionSuffix(QTypeRevision version)
// Read the qmldir file, extract a list of plugins by
// parsing the "plugin", "import", and "classname" directives.
-QVariantMap pluginsForModulePath(const QString &modulePath, const QString &version) {
+QVariantMap pluginsForModulePath(const QString &modulePath,
+ const QString &version,
+ FileImportsWithoutDepsCache
+ &fileImportsWithoutDepsCache) {
+ using Cache = QHash<QPair<QString, QString>, QVariantMap>;
+ static Cache pluginsCache;
+ const QPair<QString, QString> cacheKey = std::make_pair(modulePath, version);
+ const Cache::const_iterator it = pluginsCache.find(cacheKey);
+ if (it != pluginsCache.end()) {
+ return *it;
+ }
+
QFile qmldirFile(modulePath + QLatin1String("/qmldir"));
if (!qmldirFile.exists()) {
qWarning() << "qmldir file not found at" << modulePath;
@@ -236,14 +251,16 @@ QVariantMap pluginsForModulePath(const QString &modulePath, const QString &versi
const QString componentFullPath = modulePath + QLatin1Char('/') + component.fileName;
componentFiles.append(componentFullPath);
importsFromFiles
- += findQmlImportsInQmlFile(componentFullPath);
+ += findQmlImportsInFileWithoutDeps(componentFullPath,
+ fileImportsWithoutDepsCache);
}
const auto scripts = parser.scripts();
for (const auto &script : scripts) {
const QString scriptFullPath = modulePath + QLatin1Char('/') + script.fileName;
scriptFiles.append(scriptFullPath);
importsFromFiles
- += findQmlImportsInJavascriptFile(scriptFullPath);
+ += findQmlImportsInFileWithoutDeps(scriptFullPath,
+ fileImportsWithoutDepsCache);
}
for (const QVariant &import : importsFromFiles) {
@@ -256,8 +273,10 @@ QVariantMap pluginsForModulePath(const QString &modulePath, const QString &versi
version.isEmpty() ? name : (name + QLatin1Char(' ') + version));
}
- if (!importsAndDependencies.isEmpty())
+ if (!importsAndDependencies.isEmpty()) {
+ importsAndDependencies.removeDuplicates();
pluginInfo[dependenciesLiteral()] = importsAndDependencies;
+ }
if (!componentFiles.isEmpty()) {
componentFiles.sort();
pluginInfo[componentsLiteral()] = componentFiles;
@@ -270,6 +289,7 @@ QVariantMap pluginsForModulePath(const QString &modulePath, const QString &versi
if (!parser.preferredPath().isEmpty())
pluginInfo[preferLiteral()] = parser.preferredPath();
+ pluginsCache.insert(cacheKey, pluginInfo);
return pluginInfo;
}
@@ -340,7 +360,9 @@ QPair<QString, QString> resolveImportPath(const QString &uri, const QString &ver
}
// Find absolute file system paths and plugins for a list of modules.
-QVariantList findPathsForModuleImports(const QVariantList &imports)
+QVariantList findPathsForModuleImports(
+ const QVariantList &imports,
+ FileImportsWithoutDepsCache &fileImportsWithoutDepsCache)
{
QVariantList done;
QVariantList importsCopy(imports);
@@ -355,7 +377,9 @@ QVariantList findPathsForModuleImports(const QVariantList &imports)
if (!paths.first.isEmpty()) {
import.insert(pathLiteral(), paths.first);
import.insert(relativePathLiteral(), paths.second);
- plugininfo = pluginsForModulePath(paths.first, version);
+ plugininfo = pluginsForModulePath(paths.first,
+ version,
+ fileImportsWithoutDepsCache);
}
QString linkTarget = plugininfo.value(linkTargetLiteral()).toString();
QString plugins = plugininfo.value(pluginsLiteral()).toString();
@@ -506,10 +530,17 @@ QVariantList findQmlImportsInJavascriptFile(const QString &filePath)
return collector.imports;
}
-// Scan a single qml or js file for import statements
-QVariantList findQmlImportsInFile(const QString &filePath)
+// Scan a single qml or js file for import statements without resolving dependencies.
+QVariantList findQmlImportsInFileWithoutDeps(const QString &filePath,
+ FileImportsWithoutDepsCache
+ &fileImportsWithoutDepsCache)
{
- const auto fileProcessTimeBegin = QDateTime::currentDateTime();
+ const FileImportsWithoutDepsCache::const_iterator it =
+ fileImportsWithoutDepsCache.find(filePath);
+ if (it != fileImportsWithoutDepsCache.end()) {
+ return *it;
+ }
+
QVariantList imports;
if (filePath == QLatin1String("-")) {
QFile f;
@@ -524,11 +555,28 @@ QVariantList findQmlImportsInFile(const QString &filePath)
return imports;
}
+ fileImportsWithoutDepsCache.insert(filePath, imports);
+ return imports;
+}
+
+// Scan a single qml or js file for import statements, resolve dependencies and return the full
+// list of modules the file depends on.
+QVariantList findQmlImportsInFile(const QString &filePath,
+ FileImportsWithoutDepsCache
+ &fileImportsWithoutDepsCache) {
+ const auto fileProcessTimeBegin = QDateTime::currentDateTime();
+
+ QVariantList imports = findQmlImportsInFileWithoutDeps(filePath,
+ fileImportsWithoutDepsCache);
+ if (imports.empty())
+ return imports;
+
const auto pathsTimeBegin = QDateTime::currentDateTime();
qCDebug(lcImportScanner) << "Finding module paths for imported modules in" << filePath
<< "TS:" << pathsTimeBegin.toMSecsSinceEpoch();
- QVariantList importPaths = findPathsForModuleImports(imports);
+ QVariantList importPaths = findPathsForModuleImports(imports,
+ fileImportsWithoutDepsCache);
const auto pathsTimeEnd = QDateTime::currentDateTime();
const auto duration = pathsTimeBegin.msecsTo(pathsTimeEnd);
@@ -570,7 +618,9 @@ struct pathStartsWith {
// Scan all qml files in directory for import statements
-QVariantList findQmlImportsInDirectory(const QString &qmlDir)
+QVariantList findQmlImportsInDirectory(const QString &qmlDir,
+ FileImportsWithoutDepsCache
+ &fileImportsWithoutDepsCache)
{
QVariantList ret;
if (qmlDir.isEmpty())
@@ -608,7 +658,10 @@ QVariantList findQmlImportsInDirectory(const QString &qmlDir)
const auto entryAbsolutePath = x.absoluteFilePath();
qCDebug(lcImportScanner) << "Scanning file" << entryAbsolutePath
<< "TS:" << QDateTime::currentMSecsSinceEpoch();
- ret = mergeImports(ret, findQmlImportsInFile(entryAbsolutePath));
+ ret = mergeImports(ret,
+ findQmlImportsInFile(
+ entryAbsolutePath,
+ fileImportsWithoutDepsCache));
}
}
return ret;
@@ -617,7 +670,10 @@ QVariantList findQmlImportsInDirectory(const QString &qmlDir)
// 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 &scanFiles)
+QVariantList findQmlImportsRecursively(const QStringList &qmlDirs,
+ const QStringList &scanFiles,
+ FileImportsWithoutDepsCache
+ &fileImportsWithoutDepsCache)
{
QVariantList ret;
@@ -628,7 +684,7 @@ QVariantList findQmlImportsRecursively(const QStringList &qmlDirs, const QString
for (const QString &qmlDir : qmlDirs) {
qCDebug(lcImportScanner) << "Scanning root" << qmlDir
<< "TS:" << QDateTime::currentMSecsSinceEpoch();
- QVariantList imports = findQmlImportsInDirectory(qmlDir);
+ QVariantList imports = findQmlImportsInDirectory(qmlDir, fileImportsWithoutDepsCache);
ret = mergeImports(ret, imports);
}
@@ -636,7 +692,7 @@ QVariantList findQmlImportsRecursively(const QStringList &qmlDirs, const QString
for (const QString &file : scanFiles) {
qCDebug(lcImportScanner) << "Scanning file" << file
<< "TS:" << QDateTime::currentMSecsSinceEpoch();
- QVariantList imports = findQmlImportsInFile(file);
+ QVariantList imports = findQmlImportsInFile(file, fileImportsWithoutDepsCache);
ret = mergeImports(ret, imports);
}
@@ -802,8 +858,13 @@ int main(int argc, char *argv[])
g_qmlImportPaths = qmlImportPaths;
+ FileImportsWithoutDepsCache fileImportsWithoutDepsCache;
+
// Find the imports!
- QVariantList imports = findQmlImportsRecursively(qmlRootPaths, scanFiles);
+ QVariantList imports = findQmlImportsRecursively(qmlRootPaths,
+ scanFiles,
+ fileImportsWithoutDepsCache
+ );
QByteArray content;
if (generateCmakeContent) {