aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tests/auto/qml/qml.pro1
-rw-r--r--tests/auto/qml/qmlmin/qmlmin.pro12
-rw-r--r--tests/auto/qml/qmlmin/tst_qmlmin.cpp225
-rw-r--r--tools/qmlmin/main.cpp700
-rw-r--r--tools/qmlmin/qmlmin.pro7
-rw-r--r--tools/tools.pro3
6 files changed, 1 insertions, 947 deletions
diff --git a/tests/auto/qml/qml.pro b/tests/auto/qml/qml.pro
index 1644632ec6..d9f3fdf1b8 100644
--- a/tests/auto/qml/qml.pro
+++ b/tests/auto/qml/qml.pro
@@ -13,7 +13,6 @@ PUBLICTESTS += \
PUBLICTESTS += \
qmlformat \
- qmlmin \
qqmlcomponent \
qqmlconsole \
qqmlengine \
diff --git a/tests/auto/qml/qmlmin/qmlmin.pro b/tests/auto/qml/qmlmin/qmlmin.pro
deleted file mode 100644
index 93e5caabcf..0000000000
--- a/tests/auto/qml/qmlmin/qmlmin.pro
+++ /dev/null
@@ -1,12 +0,0 @@
-CONFIG += testcase
-TARGET = tst_qmlmin
-QT += qml testlib gui-private
-macx:CONFIG -= app_bundle
-
-SOURCES += tst_qmlmin.cpp
-DEFINES += SRCDIR=\\\"$$PWD\\\"
-
-# Boot2qt is cross compiled but it has sources available
-!boot2qt {
- cross_compile: DEFINES += QTEST_CROSS_COMPILED
-}
diff --git a/tests/auto/qml/qmlmin/tst_qmlmin.cpp b/tests/auto/qml/qmlmin/tst_qmlmin.cpp
deleted file mode 100644
index e7498a8583..0000000000
--- a/tests/auto/qml/qmlmin/tst_qmlmin.cpp
+++ /dev/null
@@ -1,225 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the test suite of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <qtest.h>
-#include <QLibraryInfo>
-#include <QDir>
-#if QT_CONFIG(process)
-#include <QProcess>
-#endif
-#include <QDebug>
-#include <QQmlError>
-#include <cstdlib>
-
-class tst_qmlmin : public QObject
-{
- Q_OBJECT
-public:
- tst_qmlmin();
-
-private slots:
- void initTestCase();
-#if QT_CONFIG(process) && !defined(QTEST_CROSS_COMPILED) // sources not available when cross compiled
- void qmlMinify_data();
- void qmlMinify();
-#endif
-
-private:
- QString qmlminPath;
- QStringList excludedDirs;
- QStringList invalidFiles;
-
- QStringList findFiles(const QDir &);
- bool isInvalidFile(const QFileInfo &fileName) const;
-};
-
-tst_qmlmin::tst_qmlmin()
-{
-}
-
-void tst_qmlmin::initTestCase()
-{
-#if QT_CONFIG(process) && !defined(QTEST_CROSS_COMPILED) // sources not available when cross compiled
- qmlminPath = QLibraryInfo::location(QLibraryInfo::BinariesPath) + QLatin1String("/qmlmin");
-#ifdef Q_OS_WIN
- qmlminPath += QLatin1String(".exe");
-#endif
- if (!QFileInfo(qmlminPath).exists()) {
- QString message = QString::fromLatin1("qmlmin executable not found (looked for %0)")
- .arg(qmlminPath);
- QFAIL(qPrintable(message));
- }
-
- // Add directories you want excluded here
-
- // These snippets are not expected to run on their own.
- excludedDirs << "doc/src/snippets/qml/visualdatamodel_rootindex";
- excludedDirs << "doc/src/snippets/qml/qtbinding";
- excludedDirs << "doc/src/snippets/qml/imports";
- excludedDirs << "doc/src/snippets/qtquick1/visualdatamodel_rootindex";
- excludedDirs << "doc/src/snippets/qtquick1/qtbinding";
- excludedDirs << "doc/src/snippets/qtquick1/imports";
- excludedDirs << "tests/manual/v4";
- excludedDirs << "tests/auto/qml/ecmascripttests";
- excludedDirs << "tests/auto/qml/qmllint";
-
- // Add invalid files (i.e. files with syntax errors)
- invalidFiles << "tests/auto/quick/qquickloader/data/InvalidSourceComponent.qml";
- invalidFiles << "tests/auto/qml/qqmllanguage/data/signal.2.qml";
- invalidFiles << "tests/auto/qml/qqmllanguage/data/signal.3.qml";
- invalidFiles << "tests/auto/qml/qqmllanguage/data/signal.5.qml";
- invalidFiles << "tests/auto/qml/qqmllanguage/data/property.4.qml";
- invalidFiles << "tests/auto/qml/qqmllanguage/data/empty.qml";
- invalidFiles << "tests/auto/qml/qqmllanguage/data/missingObject.qml";
- invalidFiles << "tests/auto/qml/qqmllanguage/data/insertedSemicolon.1.qml";
- invalidFiles << "tests/auto/qml/qqmllanguage/data/nonexistantProperty.5.qml";
- invalidFiles << "tests/auto/qml/qqmllanguage/data/invalidRoot.1.qml";
- invalidFiles << "tests/auto/qml/qqmllanguage/data/invalidQmlEnumValue.1.qml";
- invalidFiles << "tests/auto/qml/qqmllanguage/data/invalidQmlEnumValue.2.qml";
- invalidFiles << "tests/auto/qml/qquickfolderlistmodel/data/dummy.qml";
- invalidFiles << "tests/auto/qml/qqmlecmascript/data/qtbug_22843.js";
- invalidFiles << "tests/auto/qml/qqmlecmascript/data/qtbug_22843.library.js";
- invalidFiles << "tests/auto/qml/qquickworkerscript/data/script_error_onLoad.js";
- invalidFiles << "tests/auto/qml/parserstress/tests/ecma_3/Unicode/regress-352044-02-n.js";
- invalidFiles << "tests/auto/qml/qqmlecmascript/data/incrDecrSemicolon_error1.qml";
- invalidFiles << "tests/auto/qml/qqmlecmascript/data/jsimportfail/malformedFileQualifier.js";
- invalidFiles << "tests/auto/qml/qqmlecmascript/data/jsimportfail/malformedFileQualifier.2.js";
- invalidFiles << "tests/auto/qml/qqmlecmascript/data/jsimportfail/malformedImport.js";
- invalidFiles << "tests/auto/qml/qqmlecmascript/data/jsimportfail/malformedModule.js";
- invalidFiles << "tests/auto/qml/qqmlecmascript/data/jsimportfail/malformedFile.js";
- invalidFiles << "tests/auto/qml/qqmlecmascript/data/jsimportfail/malformedModuleQualifier.js";
- invalidFiles << "tests/auto/qml/qqmlecmascript/data/jsimportfail/malformedModuleQualifier.2.js";
- invalidFiles << "tests/auto/qml/qqmlecmascript/data/jsimportfail/malformedModuleVersion.js";
- invalidFiles << "tests/auto/qml/qqmlecmascript/data/jsimportfail/missingFileQualifier.js";
- invalidFiles << "tests/auto/qml/qqmlecmascript/data/jsimportfail/missingModuleQualifier.js";
- invalidFiles << "tests/auto/qml/qqmlecmascript/data/jsimportfail/missingModuleVersion.js";
- invalidFiles << "tests/auto/qml/qqmlecmascript/data/stringParsing_error.1.qml";
- invalidFiles << "tests/auto/qml/qqmlecmascript/data/stringParsing_error.2.qml";
- invalidFiles << "tests/auto/qml/qqmlecmascript/data/stringParsing_error.3.qml";
- invalidFiles << "tests/auto/qml/qqmlecmascript/data/stringParsing_error.4.qml";
- invalidFiles << "tests/auto/qml/qqmlecmascript/data/stringParsing_error.5.qml";
- invalidFiles << "tests/auto/qml/qqmlecmascript/data/stringParsing_error.6.qml";
- invalidFiles << "tests/auto/qml/qqmlecmascript/data/numberParsing_error.1.qml";
- invalidFiles << "tests/auto/qml/qqmlecmascript/data/numberParsing_error.2.qml";
- invalidFiles << "tests/auto/qml/parserstress/tests/ecma_3/FunExpr/fe-001.js";
- invalidFiles << "tests/auto/qml/qjsengine/script/com/trolltech/syntaxerror/__init__.js";
- invalidFiles << "tests/auto/qml/debugger/qqmlpreview/data/broken.qml";
- invalidFiles << "tests/auto/qml/qqmllanguage/data/fuzzed.2.qml";
- invalidFiles << "tests/auto/qml/qqmllanguage/data/fuzzed.3.qml";
- invalidFiles << "tests/auto/qml/qqmllanguage/data/requiredProperties.2.qml";
- invalidFiles << "tests/auto/qml/qqmllanguage/data/requiredProperties.3.qml";
- // generatorFunction.qml is not invalid per se, but the minifier cannot handle yield statements
- invalidFiles << "tests/auto/qml/qqmlecmascript/data/generatorFunction.qml";
-#endif
-}
-
-QStringList tst_qmlmin::findFiles(const QDir &d)
-{
- for (int ii = 0; ii < excludedDirs.count(); ++ii) {
- QString s = excludedDirs.at(ii);
- if (d.absolutePath().endsWith(s))
- return QStringList();
- }
-
- QStringList rv;
-
- QStringList files = d.entryList(QStringList() << QLatin1String("*.qml") << QLatin1String("*.js"),
- QDir::Files);
- foreach (const QString &file, files) {
- rv << d.absoluteFilePath(file);
- }
-
- QStringList dirs = d.entryList(QDir::Dirs | QDir::NoDotAndDotDot |
- QDir::NoSymLinks);
- foreach (const QString &dir, dirs) {
- QDir sub = d;
- sub.cd(dir);
- rv << findFiles(sub);
- }
-
- return rv;
-}
-
-bool tst_qmlmin::isInvalidFile(const QFileInfo &fileName) const
-{
- foreach (const QString &invalidFile, invalidFiles) {
- if (fileName.absoluteFilePath().endsWith(invalidFile))
- return true;
- }
- return false;
-}
-
-/*
-This test runs all the examples in the Qt QML UI source tree and ensures
-that they start and exit cleanly.
-
-Examples are any .qml files under the examples/ directory that start
-with a lower case letter.
-*/
-
-#if QT_CONFIG(process) && !defined(QTEST_CROSS_COMPILED) // sources not available when cross compiled
-void tst_qmlmin::qmlMinify_data()
-{
- QTest::addColumn<QString>("file");
-
- QString examples = QLatin1String(SRCDIR) + "/../../../../examples/";
- QString tests = QLatin1String(SRCDIR) + "/../../../../tests/";
-
- QStringList files;
- files << findFiles(QDir(examples));
- files << findFiles(QDir(tests));
-
- foreach (const QString &file, files)
- QTest::newRow(qPrintable(file)) << file;
-}
-#endif
-
-#if QT_CONFIG(process) && !defined(QTEST_CROSS_COMPILED) // sources not available when cross compiled
-void tst_qmlmin::qmlMinify()
-{
- QFETCH(QString, file);
-
- QProcess qmlminify;
-
- // Restrict line width to 100 characters
- qmlminify.start(qmlminPath, QStringList() << QLatin1String("--verify-only") << QLatin1String("-w100") << file);
- qmlminify.waitForFinished();
-
- QCOMPARE(qmlminify.error(), QProcess::UnknownError);
- QCOMPARE(qmlminify.exitStatus(), QProcess::NormalExit);
-
- if (isInvalidFile(file))
- QCOMPARE(qmlminify.exitCode(), EXIT_FAILURE); // cannot minify files with syntax errors
- else
- QCOMPARE(qmlminify.exitCode(), 0);
-}
-#endif
-
-QTEST_MAIN(tst_qmlmin)
-
-#include "tst_qmlmin.moc"
diff --git a/tools/qmlmin/main.cpp b/tools/qmlmin/main.cpp
deleted file mode 100644
index 3c9b3c7251..0000000000
--- a/tools/qmlmin/main.cpp
+++ /dev/null
@@ -1,700 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <private/qqmljsengine_p.h>
-#include <private/qqmljslexer_p.h>
-#include <private/qqmljsparser_p.h>
-#include <QtCore/QCoreApplication>
-#include <QtCore/QStringList>
-#include <QtCore/QFile>
-#include <QtCore/QFileInfo>
-#include <QtCore/QDir>
-#include <iostream>
-#include <cstdlib>
-
-QT_BEGIN_NAMESPACE
-
-//
-// QML/JS minifier
-//
-namespace QQmlJS {
-
-enum RegExpFlag {
- Global = 0x01,
- IgnoreCase = 0x02,
- Multiline = 0x04
-};
-
-
-class QmlminLexer: protected Lexer, public Directives
-{
- QQmlJS::Engine _engine;
- QString _fileName;
- QString _directives;
-
-protected:
- QVector<int> _stateStack;
- QList<int> _tokens;
- QList<QString> _tokenStrings;
- int yytoken = -1;
- QString yytokentext;
-
- void lex() {
- if (_tokens.isEmpty()) {
- _tokens.append(Lexer::lex());
- _tokenStrings.append(tokenText());
- }
-
- yytoken = _tokens.takeFirst();
- yytokentext = _tokenStrings.takeFirst();
- }
-
- int lookaheadToken()
- {
- if (yytoken < 0)
- lex();
- return yytoken;
- }
-
- void pushToken(int token)
- {
- _tokens.prepend(yytoken);
- _tokenStrings.prepend(yytokentext);
- yytoken = token;
- yytokentext = QString();
- }
-
-public:
- QmlminLexer()
- : Lexer(&_engine), _stateStack(128) {}
- virtual ~QmlminLexer() {}
-
- QString fileName() const { return _fileName; }
-
- bool operator()(const QString &fileName, const QString &code)
- {
- int startToken = T_FEED_JS_SCRIPT;
- const QFileInfo fileInfo(fileName);
- if (fileInfo.suffix().toLower() == QLatin1String("qml"))
- startToken = T_FEED_UI_PROGRAM;
- setCode(code, /*line = */ 1, /*qmlMode = */ startToken == T_FEED_UI_PROGRAM);
- _fileName = fileName;
- _directives.clear();
- return parse(startToken);
- }
-
- QString directives()
- {
- return _directives;
- }
-
- //
- // Handle the .pragma/.import directives
- //
- void pragmaLibrary() override
- {
- _directives += QLatin1String(".pragma library\n");
- }
-
- void importFile(const QString &jsfile, const QString &module, int line, int column) override
- {
- _directives += QLatin1String(".import");
- _directives += QLatin1Char('"');
- _directives += quote(jsfile);
- _directives += QLatin1Char('"');
- _directives += QLatin1String("as ");
- _directives += module;
- _directives += QLatin1Char('\n');
- Q_UNUSED(line);
- Q_UNUSED(column);
- }
-
- void importModule(const QString &uri, const QString &version, const QString &module, int line, int column) override
- {
- _directives += QLatin1String(".import ");
- _directives += uri;
- _directives += QLatin1Char(' ');
- _directives += version;
- _directives += QLatin1String(" as ");
- _directives += module;
- _directives += QLatin1Char('\n');
- Q_UNUSED(line);
- Q_UNUSED(column);
- }
-
-protected:
- virtual bool parse(int startToken) = 0;
-
- static QString quote(const QString &string)
- {
- QString quotedString;
- for (const QChar &ch : string) {
- if (ch == QLatin1Char('"'))
- quotedString += QLatin1String("\\\"");
- else {
- if (ch == QLatin1Char('\\')) quotedString += QLatin1String("\\\\");
- else if (ch == QLatin1Char('\"')) quotedString += QLatin1String("\\\"");
- else if (ch == QLatin1Char('\b')) quotedString += QLatin1String("\\b");
- else if (ch == QLatin1Char('\f')) quotedString += QLatin1String("\\f");
- else if (ch == QLatin1Char('\n')) quotedString += QLatin1String("\\n");
- else if (ch == QLatin1Char('\r')) quotedString += QLatin1String("\\r");
- else if (ch == QLatin1Char('\t')) quotedString += QLatin1String("\\t");
- else if (ch == QLatin1Char('\v')) quotedString += QLatin1String("\\v");
- else if (ch == QLatin1Char('\0')) quotedString += QLatin1String("\\0");
- else quotedString += ch;
- }
- }
- return quotedString;
- }
-
- bool isIdentChar(const QChar &ch) const
- {
- if (ch.isLetterOrNumber())
- return true;
- else if (ch == QLatin1Char('_') || ch == QLatin1Char('$'))
- return true;
- return false;
- }
-
- bool isRegExpRule(int ruleno) const
- {
- return ruleno == J_SCRIPT_REGEXPLITERAL_RULE1 ||
- ruleno == J_SCRIPT_REGEXPLITERAL_RULE2;
- }
-
- void handleLookaheads(int ruleno) {
- if (ruleno == J_SCRIPT_EXPRESSIONSTATEMENTLOOKAHEAD_RULE) {
- int token = lookaheadToken();
- if (token == T_LBRACE)
- pushToken(T_FORCE_BLOCK);
- else if (token == T_FUNCTION || token == T_CLASS || token == T_LET || token == T_CONST)
- pushToken(T_FORCE_DECLARATION);
- } else if (ruleno == J_SCRIPT_CONCISEBODYLOOKAHEAD_RULE) {
- int token = lookaheadToken();
- if (token == T_LBRACE)
- pushToken(T_FORCE_BLOCK);
- } else if (ruleno == J_SCRIPT_EXPORTDECLARATIONLOOKAHEAD_RULE) {
- int token = lookaheadToken();
- if (token == T_FUNCTION || token == T_CLASS)
- pushToken(T_FORCE_DECLARATION);
- }
- }
-
- bool scanRestOfRegExp(int ruleno, QString *restOfRegExp)
- {
- if (! scanRegExp(ruleno == J_SCRIPT_REGEXPLITERAL_RULE1 ? Lexer::NoPrefix : Lexer::EqualPrefix))
- return false;
-
- *restOfRegExp = regExpPattern();
- if (ruleno == J_SCRIPT_REGEXPLITERAL_RULE2) {
- Q_ASSERT(! restOfRegExp->isEmpty());
- Q_ASSERT(restOfRegExp->at(0) == QLatin1Char('='));
- *restOfRegExp = restOfRegExp->mid(1); // strip the prefix
- }
- *restOfRegExp += QLatin1Char('/');
- const RegExpFlag flags = (RegExpFlag) regExpFlags();
- if (flags & Global)
- *restOfRegExp += QLatin1Char('g');
- if (flags & IgnoreCase)
- *restOfRegExp += QLatin1Char('i');
- if (flags & Multiline)
- *restOfRegExp += QLatin1Char('m');
-
- if (regExpFlags() == 0) {
- // Add an extra space after the regexp literal delimiter (aka '/').
- // This will avoid possible problems when pasting tokens like `instanceof'
- // after the regexp literal.
- *restOfRegExp += QLatin1Char(' ');
- }
- return true;
- }
-};
-
-
-class Minify: public QmlminLexer
-{
- QString _minifiedCode;
- int _maxWidth;
- int _width;
-
-public:
- Minify(int maxWidth);
-
- QString minifiedCode() const;
-
-protected:
- void append(const QString &s);
- bool parse(int startToken) override;
- void escape(const QChar &ch, QString *out);
-};
-
-Minify::Minify(int maxWidth)
- : _maxWidth(maxWidth), _width(0)
-{
-}
-
-QString Minify::minifiedCode() const
-{
- return _minifiedCode;
-}
-
-void Minify::append(const QString &s)
-{
- if (!s.isEmpty()) {
- if (_maxWidth) {
- // Prefer not to exceed the maximum chars per line (but don't break up segments)
- int segmentLength = s.count();
- if (_width && ((_width + segmentLength) > _maxWidth)) {
- _minifiedCode.append(QLatin1Char('\n'));
- _width = 0;
- }
-
- _width += segmentLength;
- }
-
- _minifiedCode.append(s);
- }
-}
-
-void Minify::escape(const QChar &ch, QString *out)
-{
- out->append(QLatin1String("\\u"));
- const QString hx = QString::number(ch.unicode(), 16);
- switch (hx.length()) {
- case 1: out->append(QLatin1String("000")); break;
- case 2: out->append(QLatin1String("00")); break;
- case 3: out->append(QLatin1Char('0')); break;
- case 4: break;
- default: Q_ASSERT(!"unreachable");
- }
- out->append(hx);
-}
-
-bool Minify::parse(int startToken)
-{
- int yyaction = 0;
- int yytos = -1;
- QString assembled;
-
- _minifiedCode.clear();
- _tokens.append(startToken);
- _tokenStrings.append(QString());
-
- if (startToken == T_FEED_JS_SCRIPT) {
- // parse optional pragma directive
- DiagnosticMessage error;
- if (scanDirectives(this, &error)) {
- // append the scanned directives to the minifier code.
- append(directives());
-
- _tokens.append(tokenKind());
- _tokenStrings.append(tokenText());
- } else {
- std::cerr << qPrintable(fileName()) << ':' << tokenStartLine() << ':'
- << tokenStartColumn() << ": syntax error" << std::endl;
- return false;
- }
- }
-
- do {
- if (++yytos == _stateStack.size())
- _stateStack.resize(_stateStack.size() * 2);
-
- _stateStack[yytos] = yyaction;
-
- again:
- if (yytoken == -1 && action_index[yyaction] != -TERMINAL_COUNT)
- lex();
-
- yyaction = t_action(yyaction, yytoken);
- if (yyaction > 0) {
- if (yyaction == ACCEPT_STATE) {
- --yytos;
- if (!assembled.isEmpty())
- append(assembled);
- return true;
- }
-
- const QChar lastChar = assembled.isEmpty() ? (_minifiedCode.isEmpty() ? QChar()
- : _minifiedCode.at(_minifiedCode.length() - 1))
- : assembled.at(assembled.length() - 1);
-
- if (yytoken == T_SEMICOLON) {
- assembled += QLatin1Char(';');
-
- append(assembled);
- assembled.clear();
-
- } else if (yytoken == T_PLUS || yytoken == T_MINUS || yytoken == T_PLUS_PLUS || yytoken == T_MINUS_MINUS) {
- if (lastChar == QLatin1Char(spell[yytoken][0])) {
- // don't merge unary signs, additive expressions and postfix/prefix increments.
- assembled += QLatin1Char(' ');
- }
-
- assembled += QLatin1String(spell[yytoken]);
-
- } else if (yytoken == T_NUMERIC_LITERAL) {
- if (isIdentChar(lastChar))
- assembled += QLatin1Char(' ');
-
- if (yytokentext.startsWith('.'))
- assembled += QLatin1Char('0');
-
- assembled += yytokentext;
-
- if (assembled.endsWith(QLatin1Char('.')))
- assembled += QLatin1Char('0');
-
- } else if (yytoken == T_IDENTIFIER) {
- QString identifier = yytokentext;
-
- if (classify(identifier.constData(), identifier.size(), qmlMode()) != T_IDENTIFIER) {
- // the unescaped identifier is a keyword. In this case just replace
- // the last character of the identifier with it escape sequence.
- const QChar ch = identifier.at(identifier.length() - 1);
- identifier.chop(1);
- escape(ch, &identifier);
- }
-
- if (isIdentChar(lastChar))
- assembled += QLatin1Char(' ');
-
- assembled += identifier;
-
- } else if (yytoken == T_STRING_LITERAL || yytoken == T_MULTILINE_STRING_LITERAL) {
- assembled += QLatin1Char('"');
- assembled += quote(yytokentext);
- assembled += QLatin1Char('"');
- } else {
- if (isIdentChar(lastChar)) {
- if (! yytokentext.isEmpty()) {
- const QChar ch = yytokentext.at(0);
- if (isIdentChar(ch))
- assembled += QLatin1Char(' ');
- }
- }
- assembled += yytokentext;
- }
- yytoken = -1;
- } else if (yyaction < 0) {
- const int ruleno = -yyaction - 1;
- yytos -= rhs[ruleno];
-
- handleLookaheads(ruleno);
-
- if (isRegExpRule(ruleno)) {
- QString restOfRegExp;
-
- if (! scanRestOfRegExp(ruleno, &restOfRegExp))
- break; // break the loop, it wil report a syntax error
-
- assembled += restOfRegExp;
- }
- yyaction = nt_action(_stateStack[yytos], lhs[ruleno] - TERMINAL_COUNT);
- }
- } while (yyaction);
-
- const int yyerrorstate = _stateStack[yytos];
-
- // automatic insertion of `;'
- if (yytoken != -1 && ((t_action(yyerrorstate, T_AUTOMATIC_SEMICOLON) && canInsertAutomaticSemicolon(yytoken))
- || t_action(yyerrorstate, T_COMPATIBILITY_SEMICOLON))) {
- _tokens.prepend(yytoken);
- _tokenStrings.prepend(yytokentext);
- yyaction = yyerrorstate;
- yytoken = T_SEMICOLON;
- goto again;
- }
-
- std::cerr << qPrintable(fileName()) << ':' << tokenStartLine() << ':' << tokenStartColumn()
- << ": syntax error" << std::endl;
- return false;
-}
-
-
-class Tokenize: public QmlminLexer
-{
- QStringList _minifiedCode;
-
-public:
- Tokenize() {}
-
- QStringList tokenStream() const;
-
-protected:
- bool parse(int startToken) override;
-};
-
-QStringList Tokenize::tokenStream() const
-{
- return _minifiedCode;
-}
-
-bool Tokenize::parse(int startToken)
-{
- int yyaction = 0;
- int yytos = -1;
-
- _minifiedCode.clear();
- _tokens.append(startToken);
- _tokenStrings.append(QString());
-
- if (startToken == T_FEED_JS_SCRIPT) {
- // parse optional pragma directive
- DiagnosticMessage error;
- if (scanDirectives(this, &error)) {
- // append the scanned directives as one token to
- // the token stream.
- _minifiedCode.append(directives());
-
- _tokens.append(tokenKind());
- _tokenStrings.append(tokenText());
- } else {
- std::cerr << qPrintable(fileName()) << ':' << tokenStartLine() << ':'
- << tokenStartColumn() << ": syntax error" << std::endl;
- return false;
- }
- }
-
- do {
- if (++yytos == _stateStack.size())
- _stateStack.resize(_stateStack.size() * 2);
-
- _stateStack[yytos] = yyaction;
-
- again:
- if (yytoken == -1 && action_index[yyaction] != -TERMINAL_COUNT)
- lex();
-
- yyaction = t_action(yyaction, yytoken);
- if (yyaction > 0) {
- if (yyaction == ACCEPT_STATE) {
- --yytos;
- return true;
- }
-
- if (yytoken == T_SEMICOLON)
- _minifiedCode += QLatin1String(";");
- else
- _minifiedCode += yytokentext;
-
- yytoken = -1;
- } else if (yyaction < 0) {
- const int ruleno = -yyaction - 1;
- yytos -= rhs[ruleno];
-
- handleLookaheads(ruleno);
-
- if (isRegExpRule(ruleno)) {
- QString restOfRegExp;
-
- if (! scanRestOfRegExp(ruleno, &restOfRegExp))
- break; // break the loop, it wil report a syntax error
-
- _minifiedCode.last().append(restOfRegExp);
- }
-
- yyaction = nt_action(_stateStack[yytos], lhs[ruleno] - TERMINAL_COUNT);
- }
- } while (yyaction);
-
- const int yyerrorstate = _stateStack[yytos];
-
- // automatic insertion of `;'
- if (yytoken != -1 && ((t_action(yyerrorstate, T_AUTOMATIC_SEMICOLON) && canInsertAutomaticSemicolon(yytoken))
- || t_action(yyerrorstate, T_COMPATIBILITY_SEMICOLON))) {
- _tokens.prepend(yytoken);
- _tokenStrings.prepend(yytokentext);
- yyaction = yyerrorstate;
- yytoken = T_SEMICOLON;
- goto again;
- }
-
- std::cerr << qPrintable(fileName()) << ':' << tokenStartLine() << ':'
- << tokenStartColumn() << ": syntax error" << std::endl;
- return false;
-}
-
-} // end of QQmlJS namespace
-
-static void usage(bool showHelp = false)
-{
- std::cerr << "Usage: qmlmin [options] file" << std::endl;
-
- if (showHelp) {
- std::cerr << " Removes comments and layout characters" << std::endl
- << " The options are:" << std::endl
- << " -o<file> write output to file rather than stdout" << std::endl
- << " -v --verify-only just run the verifier, no output" << std::endl
- << " -w<width> restrict line characters to width" << std::endl
- << " -h display this output" << std::endl;
- }
-}
-
-int runQmlmin(int argc, char *argv[])
-{
- QCoreApplication app(argc, argv);
- QCoreApplication::setApplicationVersion(QLatin1String(QT_VERSION_STR));
-
- const QStringList args = app.arguments();
-
- QString fileName;
- QString outputFile;
- bool verifyOnly = false;
-
- // By default ensure the output character width is less than 16-bits (pass 0 to disable)
- int width = USHRT_MAX;
-
- int index = 1;
- while (index < args.size()) {
- const QString arg = args.at(index++);
- const QString next = index < args.size() ? args.at(index) : QString();
-
- if (arg == QLatin1String("-h") || arg == QLatin1String("--help")) {
- usage(/*showHelp*/ true);
- return 0;
- } else if (arg == QLatin1String("-v") || arg == QLatin1String("--verify-only")) {
- verifyOnly = true;
- } else if (arg == QLatin1String("-o")) {
- if (next.isEmpty()) {
- std::cerr << "qmlmin: argument to '-o' is missing" << std::endl;
- return EXIT_FAILURE;
- } else {
- outputFile = next;
- ++index; // consume the next argument
- }
- } else if (arg.startsWith(QLatin1String("-o"))) {
- outputFile = arg.mid(2);
-
- if (outputFile.isEmpty()) {
- std::cerr << "qmlmin: argument to '-o' is missing" << std::endl;
- return EXIT_FAILURE;
- }
- } else if (arg == QLatin1String("-w")) {
- if (next.isEmpty()) {
- std::cerr << "qmlmin: argument to '-w' is missing" << std::endl;
- return EXIT_FAILURE;
- } else {
- bool ok;
- width = next.toInt(&ok);
-
- if (!ok) {
- std::cerr << "qmlmin: argument to '-w' is invalid" << std::endl;
- return EXIT_FAILURE;
- }
-
- ++index; // consume the next argument
- }
- } else if (arg.startsWith(QLatin1String("-w"))) {
- bool ok;
- width = arg.midRef(2).toInt(&ok);
-
- if (!ok) {
- std::cerr << "qmlmin: argument to '-w' is invalid" << std::endl;
- return EXIT_FAILURE;
- }
- } else {
- const bool isInvalidOpt = arg.startsWith(QLatin1Char('-'));
- if (! isInvalidOpt && fileName.isEmpty())
- fileName = arg;
- else {
- usage(/*show help*/ isInvalidOpt);
- if (isInvalidOpt)
- std::cerr << "qmlmin: invalid option '" << qPrintable(arg) << '\'' << std::endl;
- else
- std::cerr << "qmlmin: too many input files specified" << std::endl;
- return EXIT_FAILURE;
- }
- }
- }
-
- if (fileName.isEmpty()) {
- usage();
- return 0;
- }
-
- std::cerr << "qmlmin: This tool is deprecated and will be removed in Qt 6. It is not needed anymore due to QtQml's built-in caching." << std::endl;
-
- QFile file(fileName);
- if (! file.open(QFile::ReadOnly)) {
- std::cerr << "qmlmin: '" << qPrintable(fileName) << "' no such file or directory" << std::endl;
- return EXIT_FAILURE;
- }
-
- const QString code = QString::fromUtf8(file.readAll()); // QML files are UTF-8 encoded.
- file.close();
-
- QQmlJS::Minify minify(width);
- if (! minify(fileName, code)) {
- std::cerr << "qmlmin: cannot minify '" << qPrintable(fileName) << "' (not a valid QML/JS file)" << std::endl;
- return EXIT_FAILURE;
- }
-
- //
- // verify the output
- //
- QQmlJS::Minify secondMinify(width);
- if (! secondMinify(fileName, minify.minifiedCode()) || secondMinify.minifiedCode() != minify.minifiedCode()) {
- std::cerr << "qmlmin: cannot minify '" << qPrintable(fileName) << '\'' << std::endl;
- return EXIT_FAILURE;
- }
-
- QQmlJS::Tokenize originalTokens, minimizedTokens;
- originalTokens(fileName, code);
- minimizedTokens(fileName, minify.minifiedCode());
-
- if (originalTokens.tokenStream().size() != minimizedTokens.tokenStream().size()) {
- std::cerr << "qmlmin: cannot minify '" << qPrintable(fileName) << '\'' << std::endl;
- return EXIT_FAILURE;
- }
-
- if (! verifyOnly) {
- if (outputFile.isEmpty()) {
- const QByteArray chars = minify.minifiedCode().toUtf8();
- std::cout << chars.constData();
- } else {
- QFile file(outputFile);
- if (! file.open(QFile::WriteOnly)) {
- std::cerr << "qmlmin: cannot minify '" << qPrintable(fileName) << "' (permission denied)" << std::endl;
- return EXIT_FAILURE;
- }
-
- file.write(minify.minifiedCode().toUtf8());
- file.close();
- }
- }
-
- return 0;
-}
-
-QT_END_NAMESPACE
-
-int main(int argc, char **argv)
-{
- return QT_PREPEND_NAMESPACE(runQmlmin(argc, argv));
-}
diff --git a/tools/qmlmin/qmlmin.pro b/tools/qmlmin/qmlmin.pro
deleted file mode 100644
index 32d9e3343b..0000000000
--- a/tools/qmlmin/qmlmin.pro
+++ /dev/null
@@ -1,7 +0,0 @@
-option(host_build)
-QT = core qmldevtools-private
-SOURCES += main.cpp
-
-QMAKE_TARGET_DESCRIPTION = QML/JS Minifier
-
-load(qt_tool)
diff --git a/tools/tools.pro b/tools/tools.pro
index e2e4e6b0a0..d16f78071c 100644
--- a/tools/tools.pro
+++ b/tools/tools.pro
@@ -4,7 +4,6 @@ QT_FOR_CONFIG += qml-private
qtConfig(qml-devtools) {
SUBDIRS += \
qmllint \
- qmlmin \
qmlimportscanner \
qmlformat
@@ -45,7 +44,7 @@ qtConfig(qml-devtools) {
qmleasing.depends = qmlimportscanner
}
-# qmlmin, qmlimportscanner & qmlcachegen are build tools.
+# qmlimportscanner & qmlcachegen are build tools.
# qmlscene is needed by the autotests.
# qmltestrunner may be useful for manual testing.
# qmlplugindump cannot be a build tool, because it loads target plugins.