diff options
author | Ulf Hermann <[email protected]> | 2020-01-15 14:11:49 +0100 |
---|---|---|
committer | Ulf Hermann <[email protected]> | 2020-01-15 15:15:12 +0100 |
commit | 4527d87e8f24e99658020900d9eb114d86d4dc82 (patch) | |
tree | bf8df4f57c653b9065140fea4bc7b22d59a49920 | |
parent | 499c6ed78d9657fbab344d5688c3c86b606c05b1 (diff) |
Remove qmlmin
It was deprecated in 5.15. Now we can remove it.
Change-Id: Id50af37206af246207e24d077906eaf913dc796a
Reviewed-by: Maximilian Goldstein <[email protected]>
Reviewed-by: Fabian Kosmale <[email protected]>
-rw-r--r-- | tests/auto/qml/qml.pro | 1 | ||||
-rw-r--r-- | tests/auto/qml/qmlmin/qmlmin.pro | 12 | ||||
-rw-r--r-- | tests/auto/qml/qmlmin/tst_qmlmin.cpp | 225 | ||||
-rw-r--r-- | tools/qmlmin/main.cpp | 700 | ||||
-rw-r--r-- | tools/qmlmin/qmlmin.pro | 7 | ||||
-rw-r--r-- | tools/tools.pro | 3 |
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. |