OpenCoverage

main.cpp

Absolute File Name:/home/opencoverage/opencoverage/guest-scripts/qtdeclarative/src/qtdeclarative/tools/qmlimportscanner/main.cpp
Source codeSwitch to Preprocessed file
LineSourceCount
1/****************************************************************************-
2**-
3** Copyright (C) 2016 The Qt Company Ltd.-
4** Contact: https://www.qt.io/licensing/-
5**-
6** This file is part of the tools applications of the Qt Toolkit.-
7**-
8** $QT_BEGIN_LICENSE:GPL-EXCEPT$-
9** Commercial License Usage-
10** Licensees holding valid commercial Qt licenses may use this file in-
11** accordance with the commercial license agreement provided with the-
12** Software or, alternatively, in accordance with the terms contained in-
13** a written agreement between you and The Qt Company. For licensing terms-
14** and conditions see https://www.qt.io/terms-conditions. For further-
15** information use the contact form at https://www.qt.io/contact-us.-
16**-
17** GNU General Public License Usage-
18** Alternatively, this file may be used under the terms of the GNU-
19** General Public License version 3 as published by the Free Software-
20** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT-
21** included in the packaging of this file. Please review the following-
22** information to ensure the GNU General Public License requirements will-
23** be met: https://www.gnu.org/licenses/gpl-3.0.html.-
24**-
25** $QT_END_LICENSE$-
26**-
27****************************************************************************/-
28-
29#include <private/qqmljslexer_p.h>-
30#include <private/qqmljsparser_p.h>-
31#include <private/qqmljsast_p.h>-
32#include <private/qv4codegen_p.h>-
33#include <private/qv4value_p.h>-
34#include <private/qqmlirbuilder_p.h>-
35-
36#include <QtCore/QCoreApplication>-
37#include <QtCore/QDir>-
38#include <QtCore/QDirIterator>-
39#include <QtCore/QFile>-
40#include <QtCore/QFileInfo>-
41#include <QtCore/QSet>-
42#include <QtCore/QStringList>-
43#include <QtCore/QMetaObject>-
44#include <QtCore/QMetaProperty>-
45#include <QtCore/QVariant>-
46#include <QtCore/QJsonObject>-
47#include <QtCore/QJsonArray>-
48#include <QtCore/QJsonDocument>-
49#include <QtCore/QLibraryInfo>-
50-
51#include <iostream>-
52#include <algorithm>-
53-
54QT_USE_NAMESPACE-
55-
56QStringList g_qmlImportPaths;-
57-
58static
never executed: end of block
inline QString typeLiteral() { return QStringLiteral("type"); }
never executed: end of block
0
59static
never executed: end of block
inline QString versionLiteral() { return QStringLiteral("version"); }
never executed: end of block
0
60static
never executed: end of block
inline QString nameLiteral() { return QStringLiteral("name"); }
never executed: end of block
0
61static
never executed: end of block
inline QString relativePathLiteral() { return QStringLiteral("relativePath"); }
never executed: end of block
0
62static
never executed: end of block
inline QString pluginsLiteral() { return QStringLiteral("plugins"); }
never executed: end of block
0
63static
never executed: end of block
inline QString pathLiteral() { return QStringLiteral("path"); }
never executed: end of block
0
64static
never executed: end of block
inline QString classnamesLiteral() { return QStringLiteral("classnames"); }
never executed: end of block
0
65static
never executed: end of block
inline QString dependenciesLiteral() { return QStringLiteral("dependencies"); }
never executed: end of block
0
66-
67static void printUsage(const QString &appNameIn)-
68{-
69 const std::wstring appName = appNameIn.toStdWString();-
70#ifndef QT_BOOTSTRAPPED-
71 const QString qmlPath = QLibraryInfo::location(QLibraryInfo::Qml2ImportsPath);-
72#else-
73 const QString qmlPath = QStringLiteral("/home/user/dev/qt-install/qml");-
74#endif-
75 std::wcerr-
76 << "Usage: " << appName << " -rootPath path/to/app/qml/directory -importPath path/to/qt/qml/directory\n"-
77 " " << appName << " -qmlFiles file1 file2 -importPath path/to/qt/qml/directory\n\n"-
78 "Example: " << appName << " -rootPath . -importPath "-
79 << QDir::toNativeSeparators(qmlPath).toStdWString()-
80 << '\n';-
81}
never executed: end of block
0
82-
83QVariantList findImportsInAst(QQmlJS::AST::UiHeaderItemList *headerItemList, const QString &code, const QString &path)-
84{-
85 QVariantList imports;-
86-
87 // extract uri and version from the imports (which look like "import Foo.Bar 1.2.3")-
88 for (QQmlJS::AST::UiHeaderItemList *headerItemIt = headerItemList; headerItemIt; headerItemIt = headerItemIt->next) {
headerItemItDescription
TRUEnever evaluated
FALSEnever evaluated
0
89 QVariantMap import;-
90 QQmlJS::AST::UiImport *importNode = QQmlJS::AST::cast<QQmlJS::AST::UiImport *>(headerItemIt->headerItem);-
91 if (!importNode)
!importNodeDescription
TRUEnever evaluated
FALSEnever evaluated
0
92 continue;
never executed: continue;
0
93 // handle directory imports-
94 if (!importNode->fileName.isEmpty()) {
!importNode->f...Name.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
95 QString name = importNode->fileName.toString();-
96 import[nameLiteral()] = name;-
97 if (name.endsWith(QLatin1String(".js"))) {
name.endsWith(...String(".js"))Description
TRUEnever evaluated
FALSEnever evaluated
0
98 import[typeLiteral()] = QStringLiteral("javascript");-
99 } else {
never executed: end of block
0
100 import[typeLiteral()] = QStringLiteral("directory");-
101 }
never executed: end of block
0
102-
103 import[pathLiteral()] = QDir::cleanPath(path + QLatin1Char('/') + name);-
104 } else {
never executed: end of block
0
105 // Walk the id chain ("Foo" -> "Bar" -> etc)-
106 QString name;-
107 QQmlJS::AST::UiQualifiedId *uri = importNode->importUri;-
108 while (uri) {
uriDescription
TRUEnever evaluated
FALSEnever evaluated
0
109 name.append(uri->name);-
110 name.append(QLatin1Char('.'));-
111 uri = uri->next;-
112 }
never executed: end of block
0
113 name.chop(1); // remove trailing "."-
114 if (!name.isEmpty())
!name.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
115 import[nameLiteral()] = name;
never executed: import[nameLiteral()] = name;
0
116 import[typeLiteral()] = QStringLiteral("module");-
117 import[versionLiteral()] = code.mid(importNode->versionToken.offset, importNode->versionToken.length);-
118 }
never executed: end of block
0
119-
120 imports.append(import);-
121 }
never executed: end of block
0
122-
123 return imports;
never executed: return imports;
0
124}-
125-
126// Read the qmldir file, extract a list of plugins by-
127// parsing the "plugin" and "classname" lines.-
128QVariantMap pluginsForModulePath(const QString &modulePath) {-
129 QFile qmldirFile(modulePath + QLatin1String("/qmldir"));-
130 if (!qmldirFile.exists())
!qmldirFile.exists()Description
TRUEnever evaluated
FALSEnever evaluated
0
131 return QVariantMap();
never executed: return QVariantMap();
0
132-
133 qmldirFile.open(QIODevice::ReadOnly | QIODevice::Text);-
134-
135 // a qml import may contain several plugins-
136 QString plugins;-
137 QString classnames;-
138 QStringList dependencies;-
139 QByteArray line;-
140 do {-
141 line = qmldirFile.readLine();-
142 if (line.startsWith("plugin")) {
line.startsWith("plugin")Description
TRUEnever evaluated
FALSEnever evaluated
0
143 plugins += QString::fromUtf8(line.split(' ').at(1));-
144 plugins += QLatin1Char(' ');-
145 } else if (line.startsWith("classname")) {
never executed: end of block
line.startsWith("classname")Description
TRUEnever evaluated
FALSEnever evaluated
0
146 classnames += QString::fromUtf8(line.split(' ').at(1));-
147 classnames += QLatin1Char(' ');-
148 } else if (line.startsWith("depends")) {
never executed: end of block
line.startsWith("depends")Description
TRUEnever evaluated
FALSEnever evaluated
0
149 const QList<QByteArray> dep = line.split(' ');-
150 if (dep.length() != 3)
dep.length() != 3Description
TRUEnever evaluated
FALSEnever evaluated
0
151 std::cerr << "depends: expected 2 arguments: module identifier and version" << std::endl;
never executed: std::cerr << "depends: expected 2 arguments: module identifier and version" << std::endl;
0
152 else-
153 dependencies << QString::fromUtf8(dep[1]) + QLatin1Char(' ') + QString::fromUtf8(dep[2]).simplified();
never executed: dependencies << QString::fromUtf8(dep[1]) + QLatin1Char(' ') + QString::fromUtf8(dep[2]).simplified();
0
154 }-
155-
156 } while (line.length() > 0);
never executed: end of block
line.length() > 0Description
TRUEnever evaluated
FALSEnever evaluated
0
157-
158 QVariantMap pluginInfo;-
159 pluginInfo[pluginsLiteral()] = plugins.simplified();-
160 pluginInfo[classnamesLiteral()] = classnames.simplified();-
161 if (dependencies.length())
dependencies.length()Description
TRUEnever evaluated
FALSEnever evaluated
0
162 pluginInfo[dependenciesLiteral()] = dependencies;
never executed: pluginInfo[dependenciesLiteral()] = dependencies;
0
163 return pluginInfo;
never executed: return pluginInfo;
0
164}-
165-
166// Search for a given qml import in g_qmlImportPaths and return a pair-
167// of absolute / relative paths (for deployment).-
168QPair<QString, QString> resolveImportPath(const QString &uri, const QString &version)-
169{-
170 const QLatin1Char dot('.');-
171 const QLatin1Char slash('/');-
172 const QStringList parts = uri.split(dot, QString::SkipEmptyParts);-
173-
174 QString ver = version;-
175 while (true) {-
176 for (const QString &qmlImportPath : qAsConst(g_qmlImportPaths)) {-
177 // Search for the most specific version first, and search-
178 // also for the version in parent modules. For example:-
179 // - qml/QtQml/Models.2.0-
180 // - qml/QtQml.2.0/Models-
181 // - qml/QtQml/Models.2-
182 // - qml/QtQml.2/Models-
183 // - qml/QtQml/Models-
184 if (ver.isEmpty()) {
ver.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
185 QString relativePath = parts.join(slash);-
186 if (relativePath.endsWith(slash))
relativePath.endsWith(slash)Description
TRUEnever evaluated
FALSEnever evaluated
0
187 relativePath.chop(1);
never executed: relativePath.chop(1);
0
188 const QString candidatePath = QDir::cleanPath(qmlImportPath + slash + relativePath);-
189 if (QDir(candidatePath).exists())
QDir(candidatePath).exists()Description
TRUEnever evaluated
FALSEnever evaluated
0
190 return qMakePair(candidatePath, relativePath); // import found
never executed: return qMakePair(candidatePath, relativePath);
0
191 } else {
never executed: end of block
0
192 for (int index = parts.count() - 1; index >= 0; --index) {
index >= 0Description
TRUEnever evaluated
FALSEnever evaluated
0
193 QString relativePath = parts.mid(0, index + 1).join(slash)-
194 + dot + ver + slash + parts.mid(index + 1).join(slash);-
195 if (relativePath.endsWith(slash))
relativePath.endsWith(slash)Description
TRUEnever evaluated
FALSEnever evaluated
0
196 relativePath.chop(1);
never executed: relativePath.chop(1);
0
197 const QString candidatePath = QDir::cleanPath(qmlImportPath + slash + relativePath);-
198 if (QDir(candidatePath).exists())
QDir(candidatePath).exists()Description
TRUEnever evaluated
FALSEnever evaluated
0
199 return qMakePair(candidatePath, relativePath); // import found
never executed: return qMakePair(candidatePath, relativePath);
0
200 }
never executed: end of block
0
201 }
never executed: end of block
0
202 }-
203-
204 // remove the last version digit; stop if there are none left-
205 if (ver.isEmpty())
ver.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
206 break;
never executed: break;
0
207-
208 int lastDot = ver.lastIndexOf(dot);-
209 if (lastDot == -1)
lastDot == -1Description
TRUEnever evaluated
FALSEnever evaluated
0
210 ver.clear();
never executed: ver.clear();
0
211 else-
212 ver = ver.mid(0, lastDot);
never executed: ver = ver.mid(0, lastDot);
0
213 }-
214-
215 return QPair<QString, QString>(); // not found
never executed: return QPair<QString, QString>();
0
216}-
217-
218// Find absolute file system paths and plugins for a list of modules.-
219QVariantList findPathsForModuleImports(const QVariantList &imports)-
220{-
221 QVariantList done;-
222 QVariantList importsCopy(imports);-
223-
224 for (int i = 0; i < importsCopy.length(); ++i) {
i < importsCopy.length()Description
TRUEnever evaluated
FALSEnever evaluated
0
225 QVariantMap import = qvariant_cast<QVariantMap>(importsCopy.at(i));-
226 if (import.value(typeLiteral()) == QLatin1String("module")) {
import.value(t...ring("module")Description
TRUEnever evaluated
FALSEnever evaluated
0
227 const QPair<QString, QString> paths =-
228 resolveImportPath(import.value(nameLiteral()).toString(), import.value(versionLiteral()).toString());-
229 if (!paths.first.isEmpty()) {
!paths.first.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
230 import.insert(pathLiteral(), paths.first);-
231 import.insert(relativePathLiteral(), paths.second);-
232 }
never executed: end of block
0
233 QVariantMap plugininfo = pluginsForModulePath(import.value(pathLiteral()).toString());-
234 QString plugins = plugininfo.value(pluginsLiteral()).toString();-
235 QString classnames = plugininfo.value(classnamesLiteral()).toString();-
236 if (!plugins.isEmpty())
!plugins.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
237 import.insert(QStringLiteral("plugin"), plugins);
never executed: import.insert(([]() noexcept -> QString { enum { Size = sizeof(u"" "plugin")/2 - 1 }; static const QStaticStringData<Size> qstring_literal = { { { { -1 } }, Size, 0, 0, sizeof(QStringData) }, u"" "plugin" }; QStringDataPtr holder = { qstring_literal.data_ptr() }; const QString qstring_literal_temp(holder); return qstring_literal_temp; }()), plugins);
never executed: return qstring_literal_temp;
0
238 if (!classnames.isEmpty())
!classnames.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
239 import.insert(QStringLiteral("classname"), classnames);
never executed: import.insert(([]() noexcept -> QString { enum { Size = sizeof(u"" "classname")/2 - 1 }; static const QStaticStringData<Size> qstring_literal = { { { { -1 } }, Size, 0, 0, sizeof(QStringData) }, u"" "classname" }; QStringDataPtr holder = { qstring_literal.data_ptr() }; const QString qstring_literal_temp(holder); return qstring_literal_temp; }()), classnames);
never executed: return qstring_literal_temp;
0
240 if (plugininfo.contains(dependenciesLiteral())) {
plugininfo.con...ciesLiteral())Description
TRUEnever evaluated
FALSEnever evaluated
0
241 const QStringList dependencies = plugininfo.value(dependenciesLiteral()).toStringList();-
242 for (const QString &line : dependencies) {-
243 const auto dep = line.splitRef(QLatin1Char(' '));-
244 QVariantMap depImport;-
245 depImport[typeLiteral()] = QStringLiteral("module");-
246 depImport[nameLiteral()] = dep[0].toString();-
247 depImport[versionLiteral()] = dep[1].toString();-
248 importsCopy.append(depImport);-
249 }
never executed: end of block
0
250 }
never executed: end of block
0
251 }
never executed: end of block
0
252 done.append(import);-
253 }
never executed: end of block
0
254 return done;
never executed: return done;
0
255}-
256-
257// Scan a single qml file for import statements-
258static QVariantList findQmlImportsInQmlCode(const QString &filePath, const QString &code)-
259{-
260 QQmlJS::Engine engine;-
261 QQmlJS::Lexer lexer(&engine);-
262 lexer.setCode(code, /*line = */ 1);-
263 QQmlJS::Parser parser(&engine);-
264-
265 if (!parser.parse() || !parser.diagnosticMessages().isEmpty()) {
!parser.parse()Description
TRUEnever evaluated
FALSEnever evaluated
!parser.diagno...es().isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
266 // Extract errors from the parser-
267 const auto diagnosticMessages = parser.diagnosticMessages();-
268 for (const QQmlJS::DiagnosticMessage &m : diagnosticMessages) {-
269 std::cerr << QDir::toNativeSeparators(filePath).toStdString() << ':'-
270 << m.loc.startLine << ':' << m.message.toStdString() << std::endl;-
271 }
never executed: end of block
0
272 return QVariantList();
never executed: return QVariantList();
0
273 }-
274 return findImportsInAst(parser.ast()->headers, code, filePath);
never executed: return findImportsInAst(parser.ast()->headers, code, filePath);
0
275}-
276-
277// Scan a single qml file for import statements-
278static QVariantList findQmlImportsInQmlFile(const QString &filePath)-
279{-
280 QFile file(filePath);-
281 if (!file.open(QIODevice::ReadOnly)) {
!file.open(QIO...ice::ReadOnly)Description
TRUEnever evaluated
FALSEnever evaluated
0
282 std::cerr << "Cannot open input file " << QDir::toNativeSeparators(file.fileName()).toStdString()-
283 << ':' << file.errorString().toStdString() << std::endl;-
284 return QVariantList();
never executed: return QVariantList();
0
285 }-
286 QString code = QString::fromUtf8(file.readAll());-
287 return findQmlImportsInQmlCode(filePath, code);
never executed: return findQmlImportsInQmlCode(filePath, code);
0
288}-
289-
290struct ImportCollector : public QQmlJS::Directives-
291{-
292 QVariantList imports;-
293-
294 void importFile(const QString &jsfile, const QString &module, int line, int column) override-
295 {-
296 QVariantMap entry;-
297 entry[typeLiteral()] = QStringLiteral("javascript");-
298 entry[pathLiteral()] = jsfile;-
299 imports << entry;-
300-
301 Q_UNUSED(module);-
302 Q_UNUSED(line);-
303 Q_UNUSED(column);-
304 }
never executed: end of block
0
305-
306 void importModule(const QString &uri, const QString &version, const QString &module, int line, int column) override-
307 {-
308 QVariantMap entry;-
309 if (uri.contains(QLatin1Char('/'))) {
uri.contains(QLatin1Char('/'))Description
TRUEnever evaluated
FALSEnever evaluated
0
310 entry[typeLiteral()] = QStringLiteral("directory");-
311 entry[nameLiteral()] = uri;-
312 } else {
never executed: end of block
0
313 entry[typeLiteral()] = QStringLiteral("module");-
314 entry[nameLiteral()] = uri;-
315 entry[versionLiteral()] = version;-
316 }
never executed: end of block
0
317 imports << entry;-
318-
319 Q_UNUSED(module);-
320 Q_UNUSED(line);-
321 Q_UNUSED(column);-
322 }
never executed: end of block
0
323};-
324-
325// Scan a single javascrupt file for import statements-
326QVariantList findQmlImportsInJavascriptFile(const QString &filePath)-
327{-
328 QFile file(filePath);-
329 if (!file.open(QIODevice::ReadOnly)) {
!file.open(QIO...ice::ReadOnly)Description
TRUEnever evaluated
FALSEnever evaluated
0
330 std::cerr << "Cannot open input file " << QDir::toNativeSeparators(file.fileName()).toStdString()-
331 << ':' << file.errorString().toStdString() << std::endl;-
332 return QVariantList();
never executed: return QVariantList();
0
333 }-
334-
335 QString sourceCode = QString::fromUtf8(file.readAll());-
336 file.close();-
337-
338 QQmlJS::Engine ee;-
339 ImportCollector collector;-
340 ee.setDirectives(&collector);-
341 QQmlJS::Lexer lexer(&ee);-
342 lexer.setCode(sourceCode, /*line*/1, /*qml mode*/false);-
343 QQmlJS::Parser parser(&ee);-
344 parser.parseProgram();-
345-
346 const auto diagnosticMessages = parser.diagnosticMessages();-
347 for (const QQmlJS::DiagnosticMessage &m : diagnosticMessages)-
348 if (m.isError())
m.isError()Description
TRUEnever evaluated
FALSEnever evaluated
0
349 return QVariantList();
never executed: return QVariantList();
0
350-
351 return collector.imports;
never executed: return collector.imports;
0
352}-
353-
354// Scan a single qml or js file for import statements-
355QVariantList findQmlImportsInFile(const QString &filePath)-
356{-
357 QVariantList imports;-
358 if (filePath == QLatin1String("-")) {
filePath == QLatin1String("-")Description
TRUEnever evaluated
FALSEnever evaluated
0
359 QFile f;-
360 if (f.open(stdin, QIODevice::ReadOnly))
f.open( stdin ...ice::ReadOnly)Description
TRUEnever evaluated
FALSEnever evaluated
0
361 imports = findQmlImportsInQmlCode(QLatin1String("<stdin>"), QString::fromUtf8(f.readAll()));
never executed: imports = findQmlImportsInQmlCode(QLatin1String("<stdin>"), QString::fromUtf8(f.readAll()));
0
362 } else if (filePath.endsWith(QLatin1String(".qml"))) {
never executed: end of block
filePath.endsW...tring(".qml"))Description
TRUEnever evaluated
FALSEnever evaluated
0
363 imports = findQmlImportsInQmlFile(filePath);-
364 } else if (filePath.endsWith(QLatin1String(".js"))) {
never executed: end of block
filePath.endsW...String(".js"))Description
TRUEnever evaluated
FALSEnever evaluated
0
365 imports = findQmlImportsInJavascriptFile(filePath);-
366 }
never executed: end of block
0
367-
368 return findPathsForModuleImports(imports);
never executed: return findPathsForModuleImports(imports);
0
369}-
370-
371// Merge two lists of imports, discard duplicates.-
372QVariantList mergeImports(const QVariantList &a, const QVariantList &b)-
373{-
374 QVariantList merged = a;-
375 for (const QVariant &variant : b) {-
376 if (!merged.contains(variant))
!merged.contains(variant)Description
TRUEnever evaluated
FALSEnever evaluated
0
377 merged.append(variant);
never executed: merged.append(variant);
0
378 }
never executed: end of block
0
379 return merged;
never executed: return merged;
0
380}-
381-
382// Predicates needed by findQmlImportsInDirectory.-
383-
384struct isMetainfo {-
385 bool operator() (const QFileInfo &x) const {-
386 return x.suffix() == QLatin1String("metainfo");
never executed: return x.suffix() == QLatin1String("metainfo");
0
387 }-
388};-
389-
390struct pathStartsWith {-
391 pathStartsWith(const QString &path) : _path(path) {}
never executed: end of block
0
392 bool operator() (const QString &x) const {-
393 return _path.startsWith(x);
never executed: return _path.startsWith(x);
0
394 }-
395 const QString _path;-
396};-
397-
398-
399-
400// Scan all qml files in directory for import statements-
401QVariantList findQmlImportsInDirectory(const QString &qmlDir)-
402{-
403 QVariantList ret;-
404 if (qmlDir.isEmpty())
qmlDir.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
405 return ret;
never executed: return ret;
0
406-
407 QDirIterator iterator(qmlDir, QDir::AllDirs | QDir::NoDotDot, QDirIterator::Subdirectories);-
408 QStringList blacklist;-
409-
410 while (iterator.hasNext()) {
iterator.hasNext()Description
TRUEnever evaluated
FALSEnever evaluated
0
411 iterator.next();-
412 const QString path = iterator.filePath();-
413 const QFileInfoList entries = QDir(path).entryInfoList();-
414-
415 // Skip designer related stuff-
416 if (std::find_if(entries.cbegin(), entries.cend(), isMetainfo()) != entries.cend()) {
std::find_if(e...entries.cend()Description
TRUEnever evaluated
FALSEnever evaluated
0
417 blacklist << path;-
418 continue;
never executed: continue;
0
419 }-
420-
421 if (std::find_if(blacklist.cbegin(), blacklist.cend(), pathStartsWith(path)) != blacklist.cend())
std::find_if(b...acklist.cend()Description
TRUEnever evaluated
FALSEnever evaluated
0
422 continue;
never executed: continue;
0
423-
424 // skip obvious build output directories-
425 if (path.contains(QLatin1String("Debug-iphoneos")) || path.contains(QLatin1String("Release-iphoneos")) ||
path.contains(...ug-iphoneos"))Description
TRUEnever evaluated
FALSEnever evaluated
path.contains(...se-iphoneos"))Description
TRUEnever evaluated
FALSEnever evaluated
0
426 path.contains(QLatin1String("Debug-iphonesimulator")) || path.contains(QLatin1String("Release-iphonesimulator"))
path.contains(...nesimulator"))Description
TRUEnever evaluated
FALSEnever evaluated
path.contains(...nesimulator"))Description
TRUEnever evaluated
FALSEnever evaluated
0
427#ifdef Q_OS_WIN-
428 || path.endsWith(QLatin1String("/release")) || path.endsWith(QLatin1String("/debug"))-
429#endif-
430 ){-
431 continue;
never executed: continue;
0
432 }-
433-
434 for (const QFileInfo &x : entries)-
435 if (x.isFile())
x.isFile()Description
TRUEnever evaluated
FALSEnever evaluated
0
436 ret = mergeImports(ret, findQmlImportsInFile(x.absoluteFilePath()));
never executed: ret = mergeImports(ret, findQmlImportsInFile(x.absoluteFilePath()));
0
437 }
never executed: end of block
0
438 return ret;
never executed: return ret;
0
439}-
440-
441QSet<QString> importModulePaths(const QVariantList &imports) {-
442 QSet<QString> ret;-
443 for (const QVariant &importVariant : imports) {-
444 QVariantMap import = qvariant_cast<QVariantMap>(importVariant);-
445 QString path = import.value(pathLiteral()).toString();-
446 QString type = import.value(typeLiteral()).toString();-
447 if (type == QLatin1String("module") && !path.isEmpty())
type == QLatin...ring("module")Description
TRUEnever evaluated
FALSEnever evaluated
!path.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
448 ret.insert(QDir(path).canonicalPath());
never executed: ret.insert(QDir(path).canonicalPath());
0
449 }
never executed: end of block
0
450 return ret;
never executed: return ret;
0
451}-
452-
453// Find Qml Imports Recursively from a root set of qml files.-
454// The directories in qmlDirs are searched recursively.-
455// The files in qmlFiles parsed directly.-
456QVariantList findQmlImportsRecursively(const QStringList &qmlDirs, const QStringList &scanFiles)-
457{-
458 QVariantList ret;-
459-
460 // scan all app root qml directories for imports-
461 for (const QString &qmlDir : qmlDirs) {-
462 QVariantList imports = findQmlImportsInDirectory(qmlDir);-
463 ret = mergeImports(ret, imports);-
464 }
never executed: end of block
0
465-
466 // scan app qml files for imports-
467 for (const QString &file : scanFiles) {-
468 QVariantList imports = findQmlImportsInFile(file);-
469 ret = mergeImports(ret, imports);-
470 }
never executed: end of block
0
471-
472-
473 // get the paths to theimports found in the app qml-
474 QSet<QString> toVisit = importModulePaths(ret);-
475-
476 // recursivly scan for import dependencies.-
477 QSet<QString> visited;-
478 while (!toVisit.isEmpty()) {
!toVisit.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
479 QString qmlDir = *toVisit.begin();-
480 toVisit.erase(toVisit.begin());-
481 visited.insert(qmlDir);-
482-
483 QVariantList imports = findQmlImportsInDirectory(qmlDir);-
484 ret = mergeImports(ret, imports);-
485-
486 QSet<QString> candidatePaths = importModulePaths(ret);-
487 candidatePaths.subtract(visited);-
488 toVisit.unite(candidatePaths);-
489 }
never executed: end of block
0
490 return ret;
never executed: return ret;
0
491}-
492-
493int main(int argc, char *argv[])-
494{-
495 QCoreApplication app(argc, argv);-
496 QCoreApplication::setApplicationVersion(QLatin1String(QT_VERSION_STR));-
497 QStringList args = app.arguments();-
498 const QString appName = QFileInfo(app.applicationFilePath()).baseName();-
499 if (args.size() < 2) {
args.size() < 2Description
TRUEnever evaluated
FALSEnever evaluated
0
500 printUsage(appName);-
501 return 1;
never executed: return 1;
0
502 }-
503-
504 QStringList qmlRootPaths;-
505 QStringList scanFiles;-
506 QStringList qmlImportPaths;-
507-
508 int i = 1;-
509 while (i < args.count()) {
i < args.count()Description
TRUEnever evaluated
FALSEnever evaluated
0
510 const QString &arg = args.at(i);-
511 ++i;-
512 QStringList *argReceiver = nullptr;-
513 if (!arg.startsWith(QLatin1Char('-')) || arg == QLatin1String("-")) {
!arg.startsWit...tin1Char('-'))Description
TRUEnever evaluated
FALSEnever evaluated
arg == QLatin1String("-")Description
TRUEnever evaluated
FALSEnever evaluated
0
514 qmlRootPaths += arg;-
515 } else if (arg == QLatin1String("-rootPath")) {
never executed: end of block
arg == QLatin1...g("-rootPath")Description
TRUEnever evaluated
FALSEnever evaluated
0
516 if (i >= args.count())
i >= args.count()Description
TRUEnever evaluated
FALSEnever evaluated
0
517 std::cerr << "-rootPath requires an argument\n";
never executed: std::cerr << "-rootPath requires an argument\n";
0
518 argReceiver = &qmlRootPaths;-
519 } else if (arg == QLatin1String("-qmlFiles")) {
never executed: end of block
arg == QLatin1...g("-qmlFiles")Description
TRUEnever evaluated
FALSEnever evaluated
0
520 if (i >= args.count())
i >= args.count()Description
TRUEnever evaluated
FALSEnever evaluated
0
521 std::cerr << "-qmlFiles requires an argument\n";
never executed: std::cerr << "-qmlFiles requires an argument\n";
0
522 argReceiver = &scanFiles;-
523 } else if (arg == QLatin1String("-jsFiles")) {
never executed: end of block
arg == QLatin1...ng("-jsFiles")Description
TRUEnever evaluated
FALSEnever evaluated
0
524 if (i >= args.count())
i >= args.count()Description
TRUEnever evaluated
FALSEnever evaluated
0
525 std::cerr << "-jsFiles requires an argument\n";
never executed: std::cerr << "-jsFiles requires an argument\n";
0
526 argReceiver = &scanFiles;-
527 } else if (arg == QLatin1String("-importPath")) {
never executed: end of block
arg == QLatin1..."-importPath")Description
TRUEnever evaluated
FALSEnever evaluated
0
528 if (i >= args.count())
i >= args.count()Description
TRUEnever evaluated
FALSEnever evaluated
0
529 std::cerr << "-importPath requires an argument\n";
never executed: std::cerr << "-importPath requires an argument\n";
0
530 argReceiver = &qmlImportPaths;-
531 } else {
never executed: end of block
0
532 std::cerr << qPrintable(appName) << ": Invalid argument: \""-
533 << qPrintable(arg) << "\"\n";-
534 return 1;
never executed: return 1;
0
535 }-
536-
537 while (i < args.count()) {
i < args.count()Description
TRUEnever evaluated
FALSEnever evaluated
0
538 const QString arg = args.at(i);-
539 if (arg.startsWith(QLatin1Char('-')) && arg != QLatin1String("-"))
arg.startsWith...tin1Char('-'))Description
TRUEnever evaluated
FALSEnever evaluated
arg != QLatin1String("-")Description
TRUEnever evaluated
FALSEnever evaluated
0
540 break;
never executed: break;
0
541 ++i;-
542 if (arg != QLatin1String("-") && !QFile::exists(arg)) {
arg != QLatin1String("-")Description
TRUEnever evaluated
FALSEnever evaluated
!QFile::exists(arg)Description
TRUEnever evaluated
FALSEnever evaluated
0
543 std::cerr << qPrintable(appName) << ": No such file or directory: \""-
544 << qPrintable(arg) << "\"\n";-
545 return 1;
never executed: return 1;
0
546 } else {-
547 *argReceiver += arg;-
548 }
never executed: end of block
0
549 }-
550 }
never executed: end of block
0
551-
552 g_qmlImportPaths = qmlImportPaths;-
553-
554 // Find the imports!-
555 QVariantList imports = findQmlImportsRecursively(qmlRootPaths, scanFiles);-
556-
557 // Convert to JSON-
558 QByteArray json = QJsonDocument(QJsonArray::fromVariantList(imports)).toJson();-
559 std::cout << json.constData() << std::endl;-
560 return 0;
never executed: return 0;
0
561}-
Source codeSwitch to Preprocessed file

Generated by Squish Coco 4.2.0