2021-09-16 07:35:33 +00:00
|
|
|
/****************************************************************************
|
|
|
|
**
|
|
|
|
** Copyright (C) 2021 The Qt Company Ltd.
|
|
|
|
** Contact: https://www.qt.io/licensing/
|
|
|
|
**
|
|
|
|
** This file is part of the tools applications 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 "qmltccommandlineutils.h"
|
2021-02-16 11:52:41 +00:00
|
|
|
#include "prototype/codegenerator.h"
|
|
|
|
#include "prototype/visitor.h"
|
|
|
|
#include "prototype/typeresolver.h"
|
2021-09-16 07:35:33 +00:00
|
|
|
|
|
|
|
#include <QtQml/private/qqmlirbuilder_p.h>
|
|
|
|
#include <private/qqmljscompiler_p.h>
|
2022-01-24 12:46:58 +00:00
|
|
|
#include <private/qqmljsresourcefilemapper_p.h>
|
2021-09-16 07:35:33 +00:00
|
|
|
|
|
|
|
#include <QtCore/qcoreapplication.h>
|
|
|
|
#include <QtCore/qurl.h>
|
|
|
|
#include <QtCore/qhashfunctions.h>
|
|
|
|
#include <QtCore/qfileinfo.h>
|
|
|
|
#include <QtCore/qlibraryinfo.h>
|
2022-01-18 15:16:20 +00:00
|
|
|
#include <QtCore/qcommandlineparser.h>
|
2021-09-16 07:35:33 +00:00
|
|
|
|
2021-02-16 11:52:41 +00:00
|
|
|
#include <cstdlib> // EXIT_SUCCESS, EXIT_FAILURE
|
2021-09-16 07:35:33 +00:00
|
|
|
|
2021-09-21 08:52:24 +00:00
|
|
|
void setupLogger(QQmlJSLogger &logger) // prepare logger to work with compiler
|
|
|
|
{
|
2021-11-15 16:10:31 +00:00
|
|
|
// TODO: support object bindings and change to setCategoryLevel(QtInfoMsg)
|
2021-09-21 08:52:24 +00:00
|
|
|
logger.setCategoryError(Log_Compiler, true);
|
|
|
|
}
|
|
|
|
|
2021-09-16 07:35:33 +00:00
|
|
|
int main(int argc, char **argv)
|
|
|
|
{
|
|
|
|
// Produce reliably the same output for the same input by disabling QHash's
|
|
|
|
// random seeding.
|
|
|
|
qSetGlobalQHashSeed(0);
|
|
|
|
QCoreApplication app(argc, argv);
|
|
|
|
QCoreApplication::setApplicationName(u"qmltc"_qs);
|
|
|
|
QCoreApplication::setApplicationVersion(QStringLiteral(QT_VERSION_STR));
|
|
|
|
|
|
|
|
// command-line parsing:
|
|
|
|
QCommandLineParser parser;
|
|
|
|
parser.addHelpOption();
|
|
|
|
parser.addVersionOption();
|
|
|
|
|
|
|
|
QCommandLineOption importPathOption {
|
|
|
|
u"I"_qs, QCoreApplication::translate("main", "Look for QML modules in specified directory"),
|
|
|
|
QCoreApplication::translate("main", "import directory")
|
|
|
|
};
|
|
|
|
parser.addOption(importPathOption);
|
2021-12-09 10:22:52 +00:00
|
|
|
QCommandLineOption qmldirOption {
|
|
|
|
u"i"_qs, QCoreApplication::translate("main", "Include extra qmldir files"),
|
|
|
|
QCoreApplication::translate("main", "qmldir file")
|
2021-09-16 07:35:33 +00:00
|
|
|
};
|
2021-12-09 10:22:52 +00:00
|
|
|
parser.addOption(qmldirOption);
|
2021-09-16 07:35:33 +00:00
|
|
|
QCommandLineOption outputCppOption {
|
|
|
|
u"impl"_qs, QCoreApplication::translate("main", "Generated C++ source file path"),
|
|
|
|
QCoreApplication::translate("main", "cpp path")
|
|
|
|
};
|
|
|
|
parser.addOption(outputCppOption);
|
|
|
|
QCommandLineOption outputHOption {
|
|
|
|
u"header"_qs, QCoreApplication::translate("main", "Generated C++ header file path"),
|
|
|
|
QCoreApplication::translate("main", "h path")
|
|
|
|
};
|
|
|
|
parser.addOption(outputHOption);
|
2022-01-24 12:46:58 +00:00
|
|
|
QCommandLineOption resourceOption {
|
|
|
|
u"resource"_qs,
|
|
|
|
QCoreApplication::translate(
|
|
|
|
"main", "Qt resource file that might later contain one of the compiled files"),
|
|
|
|
QCoreApplication::translate("main", "resource file name")
|
|
|
|
};
|
|
|
|
parser.addOption(resourceOption);
|
2021-10-20 09:14:52 +00:00
|
|
|
QCommandLineOption namespaceOption {
|
|
|
|
u"namespace"_qs, QCoreApplication::translate("main", "Namespace of the generated C++ code"),
|
|
|
|
QCoreApplication::translate("main", "namespace")
|
|
|
|
};
|
|
|
|
parser.addOption(namespaceOption);
|
2021-09-16 07:35:33 +00:00
|
|
|
|
|
|
|
parser.process(app);
|
|
|
|
|
|
|
|
const QStringList sources = parser.positionalArguments();
|
|
|
|
if (sources.size() != 1) {
|
|
|
|
if (sources.isEmpty()) {
|
|
|
|
parser.showHelp();
|
|
|
|
} else {
|
|
|
|
fprintf(stderr, "%s\n",
|
|
|
|
qPrintable(u"Too many input files specified: '"_qs + sources.join(u"' '"_qs)
|
|
|
|
+ u'\''));
|
|
|
|
}
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
const QString inputFile = sources.first();
|
|
|
|
|
|
|
|
QString url = parseUrlArgument(inputFile);
|
|
|
|
if (url.isNull())
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
if (!url.endsWith(u".qml")) {
|
|
|
|
fprintf(stderr, "Non-QML file passed as input\n");
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
QString sourceCode = loadUrl(url);
|
|
|
|
if (sourceCode.isEmpty())
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
|
|
|
|
QString implicitImportDirectory = getImplicitImportDirectory(url);
|
|
|
|
if (implicitImportDirectory.isEmpty())
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
|
|
|
|
QStringList importPaths = parser.values(importPathOption);
|
2021-11-09 07:33:45 +00:00
|
|
|
importPaths.append(QLibraryInfo::path(QLibraryInfo::QmlImportsPath));
|
2021-12-09 10:22:52 +00:00
|
|
|
QStringList qmldirFiles = parser.values(qmldirOption);
|
2021-09-16 07:35:33 +00:00
|
|
|
|
|
|
|
QString outputCppFile;
|
|
|
|
if (!parser.isSet(outputCppOption)) {
|
|
|
|
outputCppFile = url.first(url.size() - 3) + u"cpp"_qs;
|
|
|
|
} else {
|
|
|
|
outputCppFile = parser.value(outputCppOption);
|
|
|
|
}
|
|
|
|
|
|
|
|
QString outputHFile;
|
|
|
|
if (!parser.isSet(outputHOption)) {
|
|
|
|
outputHFile = url.first(url.size() - 3) + u"h"_qs;
|
|
|
|
} else {
|
|
|
|
outputHFile = parser.value(outputHOption);
|
|
|
|
}
|
|
|
|
|
2022-01-26 12:04:29 +00:00
|
|
|
if (!parser.isSet(resourceOption)) {
|
2022-01-24 12:46:58 +00:00
|
|
|
fprintf(stderr, "No resource paths for file: %s\n", qPrintable(inputFile));
|
2021-09-16 07:35:33 +00:00
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// main logic:
|
|
|
|
QmlIR::Document document(false); // used by QmltcTypeResolver/QQmlJSTypeResolver
|
|
|
|
// NB: JS unit generated here is ignored, so use noop function
|
|
|
|
QQmlJSSaveFunction noop([](auto &&...) { return true; });
|
|
|
|
QQmlJSCompileError error;
|
|
|
|
if (!qCompileQmlFile(document, url, noop, nullptr, &error)) {
|
|
|
|
error.augment(u"Error compiling qml file: "_qs).print();
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
|
2022-01-24 12:46:58 +00:00
|
|
|
const QStringList resourceFiles = parser.values(resourceOption);
|
|
|
|
QQmlJSResourceFileMapper mapper(resourceFiles);
|
|
|
|
|
|
|
|
// verify that we can map current file to qrc (then use the qrc path later)
|
|
|
|
const QStringList paths = mapper.resourcePaths(QQmlJSResourceFileMapper::localFileFilter(url));
|
2022-01-26 12:04:29 +00:00
|
|
|
if (paths.isEmpty()) {
|
|
|
|
fprintf(stderr, "Failed to find a resource path for file: %s\n", qPrintable(inputFile));
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
} else if (paths.size() > 1) {
|
|
|
|
fprintf(stderr, "Too many (expected 1) resource paths for file: %s\n",
|
|
|
|
qPrintable(inputFile));
|
|
|
|
return EXIT_FAILURE;
|
2022-01-24 12:46:58 +00:00
|
|
|
}
|
|
|
|
|
2021-02-16 11:52:41 +00:00
|
|
|
Options options;
|
|
|
|
options.outputCppFile = parser.value(outputCppOption);
|
|
|
|
options.outputHFile = parser.value(outputHOption);
|
2022-01-26 12:04:29 +00:00
|
|
|
options.resourcePath = paths.first();
|
2021-02-16 11:52:41 +00:00
|
|
|
options.outNamespace = parser.value(namespaceOption);
|
2021-09-16 07:35:33 +00:00
|
|
|
|
2022-01-24 12:46:58 +00:00
|
|
|
QQmlJSImporter importer { importPaths, &mapper };
|
2021-11-18 13:26:29 +00:00
|
|
|
QQmlJSLogger logger;
|
|
|
|
logger.setFileName(url);
|
|
|
|
logger.setCode(sourceCode);
|
2021-09-21 08:52:24 +00:00
|
|
|
setupLogger(logger);
|
2021-02-16 11:52:41 +00:00
|
|
|
|
2022-01-24 12:46:58 +00:00
|
|
|
Qmltc::Visitor visitor(&importer, &logger,
|
|
|
|
QQmlJSImportVisitor::implicitImportDirectory(url, &mapper), qmldirFiles);
|
2021-02-16 11:52:41 +00:00
|
|
|
Qmltc::TypeResolver typeResolver { &importer };
|
|
|
|
typeResolver.init(visitor, document.program);
|
2021-11-18 13:24:12 +00:00
|
|
|
|
2021-11-09 07:33:45 +00:00
|
|
|
if (logger.hasWarnings() || logger.hasErrors())
|
|
|
|
return EXIT_FAILURE;
|
2021-09-16 07:35:33 +00:00
|
|
|
|
2021-02-16 11:52:41 +00:00
|
|
|
CodeGenerator generator(url, &logger, &document, &typeResolver);
|
|
|
|
generator.generate(options);
|
2021-10-29 09:56:25 +00:00
|
|
|
|
2022-01-18 12:08:09 +00:00
|
|
|
# if 0 // TODO: Currently disabled due to QTBUG-100103, remove this #if guard once the issue has
|
|
|
|
// been addressed
|
|
|
|
QList<QQmlJS::DiagnosticMessage> warnings = importer.takeGlobalWarnings();
|
|
|
|
|
|
|
|
if (!warnings.isEmpty()) {
|
|
|
|
logger.logWarning(QStringLiteral("Type warnings occurred while compiling file:"),
|
|
|
|
Log_Import);
|
|
|
|
logger.processMessages(warnings, QtWarningMsg, Log_Import);
|
|
|
|
}
|
|
|
|
# endif
|
|
|
|
|
2021-11-09 07:33:45 +00:00
|
|
|
if (logger.hasWarnings() || logger.hasErrors())
|
2021-09-16 07:35:33 +00:00
|
|
|
return EXIT_FAILURE;
|
2021-11-09 07:33:45 +00:00
|
|
|
|
2021-09-16 07:35:33 +00:00
|
|
|
return EXIT_SUCCESS;
|
|
|
|
}
|