OpenCoverage

qmlcachegen.cpp

Absolute File Name:/home/opencoverage/opencoverage/guest-scripts/qtdeclarative/src/qtdeclarative/tools/qmlcachegen/qmlcachegen.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 QtQml module 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 <QCoreApplication>-
30#include <QStringList>-
31#include <QCommandLineParser>-
32#include <QFile>-
33#include <QFileInfo>-
34#include <QDateTime>-
35#include <QHashFunctions>-
36#include <QSaveFile>-
37-
38#include <private/qqmlirbuilder_p.h>-
39#include <private/qqmljsparser_p.h>-
40#include <private/qqmljslexer_p.h>-
41-
42#include "resourcefilemapper.h"-
43-
44int filterResourceFile(const QString &input, const QString &output);-
45bool generateLoader(const QStringList &compiledFiles, const QString &output, const QStringList &resourceFileMappings, QString *errorString);-
46QString symbolNamespaceForPath(const QString &relativePath);-
47-
48QSet<QString> illegalNames;-
49-
50void setupIllegalNames()-
51{-
52 // #### this in incomplete-
53 illegalNames.insert(QStringLiteral("Math"));
executed 12 times by 1 test: return qstring_literal_temp;
Executed by:
  • tst_qmlcachegen
12
54 illegalNames.insert(QStringLiteral("Array"));
executed 12 times by 1 test: return qstring_literal_temp;
Executed by:
  • tst_qmlcachegen
12
55 illegalNames.insert(QStringLiteral("String"));
executed 12 times by 1 test: return qstring_literal_temp;
Executed by:
  • tst_qmlcachegen
12
56 illegalNames.insert(QStringLiteral("Function"));
executed 12 times by 1 test: return qstring_literal_temp;
Executed by:
  • tst_qmlcachegen
12
57 illegalNames.insert(QStringLiteral("Boolean"));
executed 12 times by 1 test: return qstring_literal_temp;
Executed by:
  • tst_qmlcachegen
12
58 illegalNames.insert(QStringLiteral("Number"));
executed 12 times by 1 test: return qstring_literal_temp;
Executed by:
  • tst_qmlcachegen
12
59 illegalNames.insert(QStringLiteral("Date"));
executed 12 times by 1 test: return qstring_literal_temp;
Executed by:
  • tst_qmlcachegen
12
60 illegalNames.insert(QStringLiteral("RegExp"));
executed 12 times by 1 test: return qstring_literal_temp;
Executed by:
  • tst_qmlcachegen
12
61 illegalNames.insert(QStringLiteral("Error"));
executed 12 times by 1 test: return qstring_literal_temp;
Executed by:
  • tst_qmlcachegen
12
62 illegalNames.insert(QStringLiteral("Object"));
executed 12 times by 1 test: return qstring_literal_temp;
Executed by:
  • tst_qmlcachegen
12
63}
executed 12 times by 1 test: end of block
Executed by:
  • tst_qmlcachegen
12
64-
65struct Error-
66{-
67 QString message;-
68 void print();-
69 Error augment(const QString &contextErrorMessage) const;-
70};-
71-
72void Error::print()-
73{-
74 fprintf(stderr, "%s\n", qPrintable(message));-
75}
executed 2 times by 1 test: end of block
Executed by:
  • tst_qmlcachegen
2
76-
77Error Error::augment(const QString &contextErrorMessage) const-
78{-
79 Error augmented;-
80 augmented.message = contextErrorMessage + message;-
81 return augmented;
executed 4 times by 1 test: return augmented;
Executed by:
  • tst_qmlcachegen
4
82}-
83-
84QString diagnosticErrorMessage(const QString &fileName, const QQmlJS::DiagnosticMessage &m)-
85{-
86 QString message;-
87 message = fileName + QLatin1Char(':') + QString::number(m.loc.startLine) + QLatin1Char(':');-
88 if (m.loc.startColumn > 0)
m.loc.startColumn > 0Description
TRUEnever evaluated
FALSEnever evaluated
0
89 message += QString::number(m.loc.startColumn) + QLatin1Char(':');
never executed: message += QString::number(m.loc.startColumn) + QLatin1Char(':');
0
90-
91 if (m.isError())
m.isError()Description
TRUEnever evaluated
FALSEnever evaluated
0
92 message += QLatin1String(" error: ");
never executed: message += QLatin1String(" error: ");
0
93 else-
94 message += QLatin1String(" warning: ");
never executed: message += QLatin1String(" warning: ");
0
95 message += m.message;-
96 return message;
never executed: return message;
0
97}-
98-
99// Ensure that ListElement objects keep all property assignments in their string form-
100static void annotateListElements(QmlIR::Document *document)-
101{-
102 QStringList listElementNames;-
103-
104 foreach (const QV4::CompiledData::Import *import, document->imports) {
_container_.controlDescription
TRUEevaluated 14 times by 1 test
Evaluated by:
  • tst_qmlcachegen
FALSEevaluated 14 times by 1 test
Evaluated by:
  • tst_qmlcachegen
_container_.controlDescription
TRUEevaluated 26 times by 1 test
Evaluated by:
  • tst_qmlcachegen
FALSEnever evaluated
_container_.i != _container_.eDescription
TRUEevaluated 14 times by 1 test
Evaluated by:
  • tst_qmlcachegen
FALSEevaluated 12 times by 1 test
Evaluated by:
  • tst_qmlcachegen
0-26
105 const QString uri = document->stringAt(import->uriIndex);-
106 if (uri != QStringLiteral("QtQml.Models") && uri != QStringLiteral("QtQuick"))
executed 12 times by 1 test: return qstring_literal_temp;
Executed by:
  • tst_qmlcachegen
12
107 continue;
executed 10 times by 1 test: continue;
Executed by:
  • tst_qmlcachegen
10
108-
109 QString listElementName = QStringLiteral("ListElement");
dead code: QString listElementName = ([]() noexcept
-
110 const QString qualifier = document->stringAt(import->qualifierIndex);-
111 if (!qualifier.isEmpty()) {
!qualifier.isEmpty()Description
TRUEnever evaluated
FALSEevaluated 4 times by 1 test
Evaluated by:
  • tst_qmlcachegen
0-4
112 listElementName.prepend(QLatin1Char('.'));-
113 listElementName.prepend(qualifier);-
114 }
never executed: end of block
0
115 listElementNames.append(listElementName);-
116 }
executed 4 times by 1 test: end of block
Executed by:
  • tst_qmlcachegen
4
117-
118 if (listElementNames.isEmpty())
listElementNames.isEmpty()Description
TRUEevaluated 8 times by 1 test
Evaluated by:
  • tst_qmlcachegen
FALSEevaluated 4 times by 1 test
Evaluated by:
  • tst_qmlcachegen
4-8
119 return;
executed 8 times by 1 test: return;
Executed by:
  • tst_qmlcachegen
8
120-
121 foreach (QmlIR::Object *object, document->objects) {
_container_.controlDescription
TRUEevaluated 12 times by 1 test
Evaluated by:
  • tst_qmlcachegen
FALSEevaluated 12 times by 1 test
Evaluated by:
  • tst_qmlcachegen
_container_.controlDescription
TRUEevaluated 16 times by 1 test
Evaluated by:
  • tst_qmlcachegen
FALSEnever evaluated
_container_.i != _container_.eDescription
TRUEevaluated 12 times by 1 test
Evaluated by:
  • tst_qmlcachegen
FALSEevaluated 4 times by 1 test
Evaluated by:
  • tst_qmlcachegen
0-16
122 if (!listElementNames.contains(document->stringAt(object->inheritedTypeNameIndex)))
!listElementNa...ypeNameIndex))Description
TRUEevaluated 8 times by 1 test
Evaluated by:
  • tst_qmlcachegen
FALSEevaluated 4 times by 1 test
Evaluated by:
  • tst_qmlcachegen
4-8
123 continue;
executed 8 times by 1 test: continue;
Executed by:
  • tst_qmlcachegen
8
124 for (QmlIR::Binding *binding = object->firstBinding(); binding; binding = binding->next) {
bindingDescription
TRUEevaluated 4 times by 1 test
Evaluated by:
  • tst_qmlcachegen
FALSEevaluated 4 times by 1 test
Evaluated by:
  • tst_qmlcachegen
4
125 if (binding->type != QV4::CompiledData::Binding::Type_Script)
binding->type ...g::Type_ScriptDescription
TRUEevaluated 4 times by 1 test
Evaluated by:
  • tst_qmlcachegen
FALSEnever evaluated
0-4
126 continue;
executed 4 times by 1 test: continue;
Executed by:
  • tst_qmlcachegen
4
127 binding->stringIndex = document->registerString(object->bindingAsString(document, binding->value.compiledScriptIndex));-
128 }
never executed: end of block
0
129 }
executed 4 times by 1 test: end of block
Executed by:
  • tst_qmlcachegen
4
130}
executed 4 times by 1 test: end of block
Executed by:
  • tst_qmlcachegen
4
131-
132static bool checkArgumentsObjectUseInSignalHandlers(const QmlIR::Document &doc, Error *error)-
133{-
134 for (QmlIR::Object *object: qAsConst(doc.objects)) {-
135 for (auto binding = object->bindingsBegin(); binding != object->bindingsEnd(); ++binding) {
binding != obj...>bindingsEnd()Description
TRUEevaluated 36 times by 1 test
Evaluated by:
  • tst_qmlcachegen
FALSEevaluated 18 times by 1 test
Evaluated by:
  • tst_qmlcachegen
18-36
136 if (binding->type != QV4::CompiledData::Binding::Type_Script)
binding->type ...g::Type_ScriptDescription
TRUEevaluated 20 times by 1 test
Evaluated by:
  • tst_qmlcachegen
FALSEevaluated 16 times by 1 test
Evaluated by:
  • tst_qmlcachegen
16-20
137 continue;
executed 20 times by 1 test: continue;
Executed by:
  • tst_qmlcachegen
20
138 const QString propName = doc.stringAt(binding->propertyNameIndex);-
139 if (!propName.startsWith(QLatin1String("on"))
!propName.star...1String("on"))Description
TRUEevaluated 8 times by 1 test
Evaluated by:
  • tst_qmlcachegen
FALSEevaluated 8 times by 1 test
Evaluated by:
  • tst_qmlcachegen
8
140 || propName.length() < 3
propName.length() < 3Description
TRUEnever evaluated
FALSEevaluated 8 times by 1 test
Evaluated by:
  • tst_qmlcachegen
0-8
141 || !propName.at(2).isUpper())
!propName.at(2).isUpper()Description
TRUEnever evaluated
FALSEevaluated 8 times by 1 test
Evaluated by:
  • tst_qmlcachegen
0-8
142 continue;
executed 8 times by 1 test: continue;
Executed by:
  • tst_qmlcachegen
8
143 auto compiledFunction = doc.jsModule.functions.value(object->runtimeFunctionIndices.at(binding->value.compiledScriptIndex));-
144 if (!compiledFunction)
!compiledFunctionDescription
TRUEnever evaluated
FALSEevaluated 8 times by 1 test
Evaluated by:
  • tst_qmlcachegen
0-8
145 continue;
never executed: continue;
0
146 if (compiledFunction->usesArgumentsObject == QV4::Compiler::Context::ArgumentsObjectUsed) {
compiledFuncti...entsObjectUsedDescription
TRUEevaluated 2 times by 1 test
Evaluated by:
  • tst_qmlcachegen
FALSEevaluated 6 times by 1 test
Evaluated by:
  • tst_qmlcachegen
2-6
147 error->message = QLatin1Char(':') + QString::number(compiledFunction->line) + QLatin1Char(':');-
148 if (compiledFunction->column > 0)
compiledFunction->column > 0Description
TRUEevaluated 2 times by 1 test
Evaluated by:
  • tst_qmlcachegen
FALSEnever evaluated
0-2
149 error->message += QString::number(compiledFunction->column) + QLatin1Char(':');
executed 2 times by 1 test: error->message += QString::number(compiledFunction->column) + QLatin1Char(':');
Executed by:
  • tst_qmlcachegen
2
150-
151 error->message += QLatin1String(" error: The use of eval() or the use of the arguments object in signal handlers is\n"-
152 "not supported when compiling qml files ahead of time. That is because it's ambiguous if \n"-
153 "any signal parameter is called \"arguments\". Similarly the string passed to eval might use\n"-
154 "\"arguments\". Unfortunately we cannot distinguish between it being a parameter or the\n"-
155 "JavaScript arguments object at this point.\n"-
156 "Consider renaming the parameter of the signal if applicable or moving the code into a\n"-
157 "helper function.");-
158 return false;
executed 2 times by 1 test: return false;
Executed by:
  • tst_qmlcachegen
2
159 }-
160 }
executed 6 times by 1 test: end of block
Executed by:
  • tst_qmlcachegen
6
161 }
executed 18 times by 1 test: end of block
Executed by:
  • tst_qmlcachegen
18
162 return true;
executed 10 times by 1 test: return true;
Executed by:
  • tst_qmlcachegen
10
163}-
164-
165using SaveFunction = std::function<bool (QV4::CompiledData::CompilationUnit *, QString *)>;-
166-
167static bool compileQmlFile(const QString &inputFileName, SaveFunction saveFunction, Error *error)-
168{-
169 QmlIR::Document irDocument(/*debugMode*/false);-
170-
171 QString sourceCode;-
172 {-
173 QFile f(inputFileName);-
174 if (!f.open(QIODevice::ReadOnly)) {
!f.open(QIODevice::ReadOnly)Description
TRUEnever evaluated
FALSEevaluated 12 times by 1 test
Evaluated by:
  • tst_qmlcachegen
0-12
175 error->message = QLatin1String("Error opening ") + inputFileName + QLatin1Char(':') + f.errorString();-
176 return false;
never executed: return false;
0
177 }-
178 sourceCode = QString::fromUtf8(f.readAll());-
179 if (f.error() != QFileDevice::NoError) {
f.error() != Q...evice::NoErrorDescription
TRUEnever evaluated
FALSEevaluated 12 times by 1 test
Evaluated by:
  • tst_qmlcachegen
0-12
180 error->message = QLatin1String("Error reading from ") + inputFileName + QLatin1Char(':') + f.errorString();-
181 return false;
never executed: return false;
0
182 }-
183 }-
184-
185 {-
186 QmlIR::IRBuilder irBuilder(illegalNames);-
187 if (!irBuilder.generateFromQml(sourceCode, inputFileName, &irDocument)) {
!irBuilder.gen..., &irDocument)Description
TRUEnever evaluated
FALSEevaluated 12 times by 1 test
Evaluated by:
  • tst_qmlcachegen
0-12
188 for (const QQmlJS::DiagnosticMessage &parseError: qAsConst(irBuilder.errors)) {-
189 if (!error->message.isEmpty())
!error->message.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
190 error->message += QLatin1Char('\n');
never executed: error->message += QLatin1Char('\n');
0
191 error->message += diagnosticErrorMessage(inputFileName, parseError);-
192 }
never executed: end of block
0
193 return false;
never executed: return false;
0
194 }-
195 }-
196-
197 annotateListElements(&irDocument);-
198-
199 {-
200 QmlIR::JSCodeGen v4CodeGen(irDocument.code,-
201 &irDocument.jsGenerator, &irDocument.jsModule,-
202 &irDocument.jsParserEngine, irDocument.program,-
203 /*import cache*/nullptr, &irDocument.jsGenerator.stringTable, illegalNames);-
204 v4CodeGen.setUseFastLookups(false); // Disable lookups in non-standalone (aka QML) mode-
205 for (QmlIR::Object *object: qAsConst(irDocument.objects)) {-
206 if (object->functionsAndExpressions->count == 0)
object->functi...ns->count == 0Description
TRUEevaluated 6 times by 1 test
Evaluated by:
  • tst_qmlcachegen
FALSEevaluated 14 times by 1 test
Evaluated by:
  • tst_qmlcachegen
6-14
207 continue;
executed 6 times by 1 test: continue;
Executed by:
  • tst_qmlcachegen
6
208 QList<QmlIR::CompiledFunctionOrExpression> functionsToCompile;-
209 for (QmlIR::CompiledFunctionOrExpression *foe = object->functionsAndExpressions->first; foe; foe = foe->next) {
foeDescription
TRUEevaluated 22 times by 1 test
Evaluated by:
  • tst_qmlcachegen
FALSEevaluated 14 times by 1 test
Evaluated by:
  • tst_qmlcachegen
14-22
210 foe->disableAcceleratedLookups = true;-
211 functionsToCompile << *foe;-
212 }
executed 22 times by 1 test: end of block
Executed by:
  • tst_qmlcachegen
22
213 const QVector<int> runtimeFunctionIndices = v4CodeGen.generateJSCodeForFunctionsAndBindings(functionsToCompile);-
214 QList<QQmlJS::DiagnosticMessage> jsErrors = v4CodeGen.errors();-
215 if (!jsErrors.isEmpty()) {
!jsErrors.isEmpty()Description
TRUEnever evaluated
FALSEevaluated 14 times by 1 test
Evaluated by:
  • tst_qmlcachegen
0-14
216 for (const QQmlJS::DiagnosticMessage &e: qAsConst(jsErrors)) {-
217 if (!error->message.isEmpty())
!error->message.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
218 error->message += QLatin1Char('\n');
never executed: error->message += QLatin1Char('\n');
0
219 error->message += diagnosticErrorMessage(inputFileName, e);-
220 }
never executed: end of block
0
221 return false;
never executed: return false;
0
222 }-
223-
224 QQmlJS::MemoryPool *pool = irDocument.jsParserEngine.pool();-
225 object->runtimeFunctionIndices.allocate(pool, runtimeFunctionIndices);-
226 }
executed 14 times by 1 test: end of block
Executed by:
  • tst_qmlcachegen
14
227-
228 if (!checkArgumentsObjectUseInSignalHandlers(irDocument, error)) {
!checkArgument...cument, error)Description
TRUEevaluated 2 times by 1 test
Evaluated by:
  • tst_qmlcachegen
FALSEevaluated 10 times by 1 test
Evaluated by:
  • tst_qmlcachegen
2-10
229 *error = error->augment(inputFileName);-
230 return false;
executed 2 times by 1 test: return false;
Executed by:
  • tst_qmlcachegen
2
231 }-
232-
233 QmlIR::QmlUnitGenerator generator;-
234 irDocument.javaScriptCompilationUnit = v4CodeGen.generateCompilationUnit(/*generate unit*/false);-
235 QV4::CompiledData::Unit *unit = generator.generate(irDocument);-
236 unit->flags |= QV4::CompiledData::Unit::StaticData;-
237 unit->flags |= QV4::CompiledData::Unit::PendingTypeCompilation;-
238 irDocument.javaScriptCompilationUnit->data = unit;-
239-
240 if (!saveFunction(irDocument.javaScriptCompilationUnit.data(), &error->message))
!saveFunction(...rror->message)Description
TRUEnever evaluated
FALSEevaluated 10 times by 1 test
Evaluated by:
  • tst_qmlcachegen
0-10
241 return false;
never executed: return false;
0
242-
243 free(unit);-
244 }-
245 return true;
executed 10 times by 1 test: return true;
Executed by:
  • tst_qmlcachegen
10
246}-
247-
248static bool compileJSFile(const QString &inputFileName, const QString &inputFileUrl, SaveFunction saveFunction, Error *error)-
249{-
250 QmlIR::Document irDocument(/*debugMode*/false);-
251-
252 QString sourceCode;-
253 {-
254 QFile f(inputFileName);-
255 if (!f.open(QIODevice::ReadOnly)) {
!f.open(QIODevice::ReadOnly)Description
TRUEnever evaluated
FALSEnever evaluated
0
256 error->message = QLatin1String("Error opening ") + inputFileName + QLatin1Char(':') + f.errorString();-
257 return false;
never executed: return false;
0
258 }-
259 sourceCode = QString::fromUtf8(f.readAll());-
260 if (f.error() != QFileDevice::NoError) {
f.error() != Q...evice::NoErrorDescription
TRUEnever evaluated
FALSEnever evaluated
0
261 error->message = QLatin1String("Error reading from ") + inputFileName + QLatin1Char(':') + f.errorString();-
262 return false;
never executed: return false;
0
263 }-
264 }-
265-
266 QQmlJS::Engine *engine = &irDocument.jsParserEngine;-
267 QmlIR::ScriptDirectivesCollector directivesCollector(&irDocument);-
268 QQmlJS::Directives *oldDirs = engine->directives();-
269 engine->setDirectives(&directivesCollector);-
270-
271 QQmlJS::AST::Program *program = nullptr;-
272-
273 {-
274 QQmlJS::Lexer lexer(engine);-
275 lexer.setCode(sourceCode, /*line*/1, /*parseAsBinding*/false);-
276 QQmlJS::Parser parser(engine);-
277-
278 bool parsed = parser.parseProgram();-
279-
280 for (const QQmlJS::DiagnosticMessage &parseError: parser.diagnosticMessages()) {-
281 if (!error->message.isEmpty())
!error->message.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
282 error->message += QLatin1Char('\n');
never executed: error->message += QLatin1Char('\n');
0
283 error->message += diagnosticErrorMessage(inputFileName, parseError);-
284 }
never executed: end of block
0
285-
286 if (!parsed) {
!parsedDescription
TRUEnever evaluated
FALSEnever evaluated
0
287 engine->setDirectives(oldDirs);-
288 return false;
never executed: return false;
0
289 }-
290-
291 program = QQmlJS::AST::cast<QQmlJS::AST::Program*>(parser.rootNode());-
292 if (!program) {
!programDescription
TRUEnever evaluated
FALSEnever evaluated
0
293 lexer.setCode(QStringLiteral("undefined;"), 1, false);
never executed: return qstring_literal_temp;
0
294 parsed = parser.parseProgram();-
295 Q_ASSERT(parsed);-
296 program = QQmlJS::AST::cast<QQmlJS::AST::Program*>(parser.rootNode());-
297 Q_ASSERT(program);-
298 }
never executed: end of block
0
299 }-
300-
301 {-
302 QmlIR::JSCodeGen v4CodeGen(irDocument.code, &irDocument.jsGenerator,-
303 &irDocument.jsModule, &irDocument.jsParserEngine,-
304 irDocument.program, /*import cache*/nullptr,-
305 &irDocument.jsGenerator.stringTable, illegalNames);-
306 v4CodeGen.setUseFastLookups(false); // Disable lookups in non-standalone (aka QML) mode-
307 v4CodeGen.generateFromProgram(inputFileName, inputFileUrl, sourceCode, program,-
308 &irDocument.jsModule, QV4::Compiler::ContextType::Global);-
309 QList<QQmlJS::DiagnosticMessage> jsErrors = v4CodeGen.errors();-
310 if (!jsErrors.isEmpty()) {
!jsErrors.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
311 for (const QQmlJS::DiagnosticMessage &e: qAsConst(jsErrors)) {-
312 if (!error->message.isEmpty())
!error->message.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
313 error->message += QLatin1Char('\n');
never executed: error->message += QLatin1Char('\n');
0
314 error->message += diagnosticErrorMessage(inputFileName, e);-
315 }
never executed: end of block
0
316 engine->setDirectives(oldDirs);-
317 return false;
never executed: return false;
0
318 }-
319-
320 QmlIR::QmlUnitGenerator generator;-
321-
322 irDocument.javaScriptCompilationUnit = v4CodeGen.generateCompilationUnit(/*generate unit*/false);-
323 QV4::CompiledData::Unit *unit = generator.generate(irDocument);-
324 unit->flags |= QV4::CompiledData::Unit::StaticData;-
325 irDocument.javaScriptCompilationUnit->data = unit;-
326-
327 if (!saveFunction(irDocument.javaScriptCompilationUnit.data(), &error->message)) {
!saveFunction(...rror->message)Description
TRUEnever evaluated
FALSEnever evaluated
0
328 engine->setDirectives(oldDirs);-
329 return false;
never executed: return false;
0
330 }-
331-
332 free(unit);-
333 }-
334 engine->setDirectives(oldDirs);-
335 return true;
never executed: return true;
0
336}-
337-
338static bool saveUnitAsCpp(const QString &inputFileName, const QString &outputFileName, QV4::CompiledData::CompilationUnit *unit, QString *errorString)-
339{-
340 QSaveFile f(outputFileName);-
341 if (!f.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
!f.open(QIODev...ice::Truncate)Description
TRUEnever evaluated
FALSEnever evaluated
0
342 *errorString = f.errorString();-
343 return false;
never executed: return false;
0
344 }-
345-
346 auto writeStr = [&f, errorString](const QByteArray &data) {-
347 if (f.write(data) != data.size()) {
f.write(data) != data.size()Description
TRUEnever evaluated
FALSEnever evaluated
0
348 *errorString = f.errorString();-
349 return false;
never executed: return false;
0
350 }-
351 return true;
never executed: return true;
0
352 };-
353-
354 if (!writeStr("// "))
!writeStr("// ")Description
TRUEnever evaluated
FALSEnever evaluated
0
355 return false;
never executed: return false;
0
356-
357 if (!writeStr(inputFileName.toUtf8()))
!writeStr(inpu...Name.toUtf8())Description
TRUEnever evaluated
FALSEnever evaluated
0
358 return false;
never executed: return false;
0
359-
360 if (!writeStr("\n"))
!writeStr("\n")Description
TRUEnever evaluated
FALSEnever evaluated
0
361 return false;
never executed: return false;
0
362-
363 if (!writeStr(QByteArrayLiteral("namespace QmlCacheGeneratedCode {\nnamespace ")))
never executed: return ba;
!writeStr(([](...turn ba; }()))Description
TRUEnever evaluated
FALSEnever evaluated
0
364 return false;
never executed: return false;
0
365-
366 if (!writeStr(symbolNamespaceForPath(inputFileName).toUtf8()))
!writeStr(symb...ame).toUtf8())Description
TRUEnever evaluated
FALSEnever evaluated
0
367 return false;
never executed: return false;
0
368-
369 if (!writeStr(QByteArrayLiteral(" {\nextern const unsigned char qmlData alignas(16) [] = {\n")))
never executed: return ba;
!writeStr(([](...turn ba; }()))Description
TRUEnever evaluated
FALSEnever evaluated
0
370 return false;
never executed: return false;
0
371-
372 QByteArray hexifiedData;-
373 {-
374 QByteArray modifiedUnit;-
375 modifiedUnit.resize(unit->data->unitSize);-
376 memcpy(modifiedUnit.data(), unit->data, unit->data->unitSize);-
377 const char *dataPtr = modifiedUnit.data();-
378 QV4::CompiledData::Unit *unitPtr;-
379 memcpy(&unitPtr, &dataPtr, sizeof(unitPtr));-
380 unitPtr->flags |= QV4::CompiledData::Unit::StaticData;-
381-
382 QTextStream stream(&hexifiedData);-
383 const uchar *begin = reinterpret_cast<const uchar *>(modifiedUnit.constData());-
384 const uchar *end = begin + unit->data->unitSize;-
385 stream << hex;-
386 int col = 0;-
387 for (const uchar *data = begin; data < end; ++data, ++col) {
data < endDescription
TRUEnever evaluated
FALSEnever evaluated
0
388 if (data > begin)
data > beginDescription
TRUEnever evaluated
FALSEnever evaluated
0
389 stream << ',';
never executed: stream << ',';
0
390 if (col % 8 == 0) {
col % 8 == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
391 stream << '\n';-
392 col = 0;-
393 }
never executed: end of block
0
394 stream << "0x" << *data;-
395 }
never executed: end of block
0
396 stream << '\n';-
397 };-
398-
399 if (!writeStr(hexifiedData))
!writeStr(hexifiedData)Description
TRUEnever evaluated
FALSEnever evaluated
0
400 return false;
never executed: return false;
0
401-
402 if (!writeStr("};\n}\n}\n"))
!writeStr("};\n}\n}\n")Description
TRUEnever evaluated
FALSEnever evaluated
0
403 return false;
never executed: return false;
0
404-
405 if (!f.commit()) {
!f.commit()Description
TRUEnever evaluated
FALSEnever evaluated
0
406 *errorString = f.errorString();-
407 return false;
never executed: return false;
0
408 }-
409-
410 return true;
never executed: return true;
0
411}-
412-
413int main(int argc, char **argv)-
414{-
415 // Produce reliably the same output for the same input by disabling QHash's random seeding.-
416 qSetGlobalQHashSeed(0);-
417-
418 QCoreApplication app(argc, argv);-
419 QCoreApplication::setApplicationName(QStringLiteral("qmlcachegen"));
executed 12 times by 1 test: return qstring_literal_temp;
Executed by:
  • tst_qmlcachegen
12
420 QCoreApplication::setApplicationVersion(QLatin1String(QT_VERSION_STR));-
421-
422 QCommandLineParser parser;-
423 parser.addHelpOption();-
424 parser.addVersionOption();-
425-
426 QCommandLineOption filterResourceFileOption(QStringLiteral("filter-resource-file"), QCoreApplication::translate("main", "Filter out QML/JS files from a resource file that can be cached ahead of time instead"));
executed 12 times by 1 test: return qstring_literal_temp;
Executed by:
  • tst_qmlcachegen
12
427 parser.addOption(filterResourceFileOption);-
428 QCommandLineOption resourceFileMappingOption(QStringLiteral("resource-file-mapping"), QCoreApplication::translate("main", "Path from original resource file to new one"), QCoreApplication::translate("main", "old-name:new-name"));
executed 12 times by 1 test: return qstring_literal_temp;
Executed by:
  • tst_qmlcachegen
12
429 parser.addOption(resourceFileMappingOption);-
430 QCommandLineOption resourceOption(QStringLiteral("resource"), QCoreApplication::translate("main", "Qt resource file that might later contain one of the compiled files"), QCoreApplication::translate("main", "resource-file-name"));
executed 12 times by 1 test: return qstring_literal_temp;
Executed by:
  • tst_qmlcachegen
12
431 parser.addOption(resourceOption);-
432 QCommandLineOption resourcePathOption(QStringLiteral("resource-path"), QCoreApplication::translate("main", "Qt resource file path corresponding to the file being compiled"), QCoreApplication::translate("main", "resource-path"));
executed 12 times by 1 test: return qstring_literal_temp;
Executed by:
  • tst_qmlcachegen
12
433 parser.addOption(resourcePathOption);-
434-
435 QCommandLineOption outputFileOption(QStringLiteral("o"), QCoreApplication::translate("main", "Output file name"), QCoreApplication::translate("main", "file name"));
executed 12 times by 1 test: return qstring_literal_temp;
Executed by:
  • tst_qmlcachegen
12
436 parser.addOption(outputFileOption);-
437-
438 parser.addPositionalArgument(QStringLiteral("[qml file]"),
executed 12 times by 1 test: return qstring_literal_temp;
Executed by:
  • tst_qmlcachegen
12
439 QStringLiteral("QML source file to generate cache for."));
executed 12 times by 1 test: return qstring_literal_temp;
Executed by:
  • tst_qmlcachegen
12
440-
441 parser.setSingleDashWordOptionMode(QCommandLineParser::ParseAsLongOptions);-
442-
443 parser.process(app);-
444-
445 enum Output {-
446 GenerateCpp,-
447 GenerateCacheFile,-
448 GenerateLoader-
449 } target = GenerateCacheFile;-
450-
451 QString outputFileName;-
452 if (parser.isSet(outputFileOption))
parser.isSet(outputFileOption)Description
TRUEnever evaluated
FALSEevaluated 12 times by 1 test
Evaluated by:
  • tst_qmlcachegen
0-12
453 outputFileName = parser.value(outputFileOption);
never executed: outputFileName = parser.value(outputFileOption);
0
454-
455 if (outputFileName.endsWith(QLatin1String(".cpp"))) {
outputFileName...tring(".cpp"))Description
TRUEnever evaluated
FALSEevaluated 12 times by 1 test
Evaluated by:
  • tst_qmlcachegen
0-12
456 target = GenerateCpp;-
457 if (outputFileName.endsWith(QLatin1String("qmlcache_loader.cpp")))
outputFileName..._loader.cpp"))Description
TRUEnever evaluated
FALSEnever evaluated
0
458 target = GenerateLoader;
never executed: target = GenerateLoader;
0
459 }
never executed: end of block
0
460-
461 const QStringList sources = parser.positionalArguments();-
462 if (sources.isEmpty()){
sources.isEmpty()Description
TRUEnever evaluated
FALSEevaluated 12 times by 1 test
Evaluated by:
  • tst_qmlcachegen
0-12
463 parser.showHelp();-
464 } else if (sources.count() > 1 && target != GenerateLoader) {
never executed: end of block
sources.count() > 1Description
TRUEnever evaluated
FALSEevaluated 12 times by 1 test
Evaluated by:
  • tst_qmlcachegen
target != GenerateLoaderDescription
TRUEnever evaluated
FALSEnever evaluated
0-12
465 fprintf(stderr, "%s\n", qPrintable(QStringLiteral("Too many input files specified: '") + sources.join(QStringLiteral("' '")) + QLatin1Char('\'')));
never executed: return qstring_literal_temp;
never executed: return qstring_literal_temp;
0
466 return EXIT_FAILURE;
never executed: return 1 ;
0
467 }-
468-
469 const QString inputFile = sources.first();-
470 if (outputFileName.isEmpty())
outputFileName.isEmpty()Description
TRUEevaluated 12 times by 1 test
Evaluated by:
  • tst_qmlcachegen
FALSEnever evaluated
0-12
471 outputFileName = inputFile + QLatin1Char('c');
executed 12 times by 1 test: outputFileName = inputFile + QLatin1Char('c');
Executed by:
  • tst_qmlcachegen
12
472-
473 if (parser.isSet(filterResourceFileOption)) {
parser.isSet(f...rceFileOption)Description
TRUEnever evaluated
FALSEevaluated 12 times by 1 test
Evaluated by:
  • tst_qmlcachegen
0-12
474 return filterResourceFile(inputFile, outputFileName);
never executed: return filterResourceFile(inputFile, outputFileName);
0
475 }-
476-
477 if (target == GenerateLoader) {
target == GenerateLoaderDescription
TRUEnever evaluated
FALSEevaluated 12 times by 1 test
Evaluated by:
  • tst_qmlcachegen
0-12
478 ResourceFileMapper mapper(sources);-
479-
480 Error error;-
481 if (!generateLoader(mapper.qmlCompilerFiles(), outputFileName, parser.values(resourceFileMappingOption), &error.message)) {
!generateLoade...error.message)Description
TRUEnever evaluated
FALSEnever evaluated
0
482 error.augment(QLatin1String("Error generating loader stub: ")).print();-
483 return EXIT_FAILURE;
never executed: return 1 ;
0
484 }-
485 return EXIT_SUCCESS;
never executed: return 0 ;
0
486 }-
487-
488 QString inputFileUrl = inputFile;-
489-
490 SaveFunction saveFunction;-
491 if (target == GenerateCpp) {
target == GenerateCppDescription
TRUEnever evaluated
FALSEevaluated 12 times by 1 test
Evaluated by:
  • tst_qmlcachegen
0-12
492 ResourceFileMapper fileMapper(parser.values(resourceOption));-
493 QString inputResourcePath = parser.value(resourcePathOption);-
494-
495 if (!inputResourcePath.isEmpty() && !fileMapper.isEmpty()) {
!inputResourcePath.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
!fileMapper.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
496 fprintf(stderr, "--%s and --%s are mutually exclusive.\n",-
497 qPrintable(resourcePathOption.names().first()),-
498 qPrintable(resourceOption.names().first()));-
499 return EXIT_FAILURE;
never executed: return 1 ;
0
500 }-
501-
502 // If the user didn't specify the resource path corresponding to the file on disk being-
503 // compiled, try to determine it from the resource file, if one was supplied.-
504 if (inputResourcePath.isEmpty()) {
inputResourcePath.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
505 const QStringList resourcePaths = fileMapper.resourcePaths(inputFile);-
506 if (resourcePaths.isEmpty()) {
resourcePaths.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
507 fprintf(stderr, "No resource path for file: %s\n", qPrintable(inputFile));-
508 return EXIT_FAILURE;
never executed: return 1 ;
0
509 }-
510-
511 if (resourcePaths.size() != 1) {
resourcePaths.size() != 1Description
TRUEnever evaluated
FALSEnever evaluated
0
512 fprintf(stderr, "Multiple resource paths for file %s. "-
513 "Use the --%s option to disambiguate:\n",-
514 qPrintable(inputFile),-
515 qPrintable(resourcePathOption.names().first()));-
516 for (const QString &resourcePath: resourcePaths)-
517 fprintf(stderr, "\t%s\n", qPrintable(resourcePath));
never executed: fprintf( stderr , "\t%s\n", QtPrivate::asString(resourcePath).toLocal8Bit().constData());
0
518 return EXIT_FAILURE;
never executed: return 1 ;
0
519 }-
520-
521 inputResourcePath = resourcePaths.first();-
522 }
never executed: end of block
0
523-
524 inputFileUrl = QStringLiteral("qrc://") + inputResourcePath;-
525-
526 saveFunction = [inputResourcePath, outputFileName](QV4::CompiledData::CompilationUnit *unit, QString *errorString) {-
527 return saveUnitAsCpp(inputResourcePath, outputFileName, unit, errorString);
never executed: return saveUnitAsCpp(inputResourcePath, outputFileName, unit, errorString);
0
528 };-
529-
530 } else {
never executed: end of block
0
531 saveFunction = [outputFileName](QV4::CompiledData::CompilationUnit *unit, QString *errorString) {-
532 return unit->saveToDisk(outputFileName, errorString);
executed 10 times by 1 test: return unit->saveToDisk(outputFileName, errorString);
Executed by:
  • tst_qmlcachegen
10
533 };-
534 }
executed 12 times by 1 test: end of block
Executed by:
  • tst_qmlcachegen
12
535-
536 setupIllegalNames();-
537-
538-
539 if (inputFile.endsWith(QLatin1String(".qml"))) {
inputFile.ends...tring(".qml"))Description
TRUEevaluated 12 times by 1 test
Evaluated by:
  • tst_qmlcachegen
FALSEnever evaluated
0-12
540 Error error;-
541 if (!compileQmlFile(inputFile, saveFunction, &error)) {
!compileQmlFil...ction, &error)Description
TRUEevaluated 2 times by 1 test
Evaluated by:
  • tst_qmlcachegen
FALSEevaluated 10 times by 1 test
Evaluated by:
  • tst_qmlcachegen
2-10
542 error.augment(QLatin1String("Error compiling qml file: ")).print();-
543 return EXIT_FAILURE;
executed 2 times by 1 test: return 1 ;
Executed by:
  • tst_qmlcachegen
2
544 }-
545 } else if (inputFile.endsWith(QLatin1String(".js"))) {
executed 10 times by 1 test: end of block
Executed by:
  • tst_qmlcachegen
inputFile.ends...String(".js"))Description
TRUEnever evaluated
FALSEnever evaluated
0-10
546 Error error;-
547 if (!compileJSFile(inputFile, inputFileUrl, saveFunction, &error)) {
!compileJSFile...ction, &error)Description
TRUEnever evaluated
FALSEnever evaluated
0
548 error.augment(QLatin1String("Error compiling js file: ")).print();-
549 return EXIT_FAILURE;
never executed: return 1 ;
0
550 }-
551 } else {
never executed: end of block
0
552 fprintf(stderr, "Ignoring %s input file as it is not QML source code - maybe remove from QML_FILES?\n", qPrintable(inputFile));-
553 }
never executed: end of block
0
554-
555 return EXIT_SUCCESS;
executed 10 times by 1 test: return 0 ;
Executed by:
  • tst_qmlcachegen
10
556}-
Source codeSwitch to Preprocessed file

Generated by Squish Coco 4.2.0