2021-11-17 10:25:36 +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$
|
|
|
|
**
|
|
|
|
****************************************************************************/
|
|
|
|
|
2022-02-03 11:01:35 +00:00
|
|
|
#include "qqmljslinter_p.h"
|
2021-11-17 10:25:36 +00:00
|
|
|
|
2022-02-03 11:01:35 +00:00
|
|
|
#include "qqmljslintercodegen_p.h"
|
2021-11-17 10:25:36 +00:00
|
|
|
|
|
|
|
#include <QtQmlCompiler/private/qqmljsimporter_p.h>
|
2021-12-16 16:15:21 +00:00
|
|
|
#include <QtQmlCompiler/private/qqmljsimportvisitor_p.h>
|
2021-11-17 10:25:36 +00:00
|
|
|
|
|
|
|
#include <QtCore/qjsonobject.h>
|
|
|
|
#include <QtCore/qfileinfo.h>
|
|
|
|
#include <QtCore/qloggingcategory.h>
|
|
|
|
|
|
|
|
#include <QtQml/private/qqmljslexer_p.h>
|
|
|
|
#include <QtQml/private/qqmljsparser_p.h>
|
|
|
|
#include <QtQml/private/qqmljsengine_p.h>
|
|
|
|
#include <QtQml/private/qqmljsastvisitor_p.h>
|
|
|
|
#include <QtQml/private/qqmljsast_p.h>
|
|
|
|
#include <QtQml/private/qqmljsdiagnosticmessage_p.h>
|
|
|
|
|
|
|
|
QT_BEGIN_NAMESPACE
|
|
|
|
|
2022-02-03 11:01:35 +00:00
|
|
|
class CodegenWarningInterface final : public QV4::Compiler::CodegenWarningInterface
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
CodegenWarningInterface(QQmlJSLogger *logger) : m_logger(logger) { }
|
|
|
|
|
|
|
|
void reportVarUsedBeforeDeclaration(const QString &name, const QString &fileName,
|
|
|
|
QQmlJS::SourceLocation declarationLocation,
|
|
|
|
QQmlJS::SourceLocation accessLocation) override
|
|
|
|
{
|
|
|
|
Q_UNUSED(fileName)
|
Redesign QQmlJSLogger internals
High-level goal: be able to reuse existing infrastructure
"as is" to configure semantic analysis categories in tools
(qmllint, qmltc, qmlsc, etc.)
To achieve that, simplify the logging to always "log"
something, without explicitly specifying the severity. The
severity is now baked into the category (and we can extend
those to cover different cases)
One slight deviation is the cache generation which likes
to do its own thing at present. Provide a "forced logging"
option where we can specify which severify we want. The
hope is that this gets removed at some point
Particular list of (noteworthy) changes:
* No more "thresholding" by the level (this is rarely needed
and is actually questionable). Instead, we can ignore a
particular category explicitly
* Category levels are repurposed as category severities
(at least from the high-level picture that always should've
been this way)
* log{Warning,Info,Critical} removed. We use category severity
instead
* "category error" makes zero sense so removed: if our severity
is:
- QtWarningMsg (qmllint), it is already an "error"
- QtCriticalMsg (compilers), it is already an "error"
* Align m_output and m_{infos,warnings,errors} stored information
* Accept the fact that we don't support QtDebugMsg and QtFatalMsg
* Additional categories added to cover for places where the same
category would be both an error and not an error
Task-number: QTBUG-100052
Change-Id: I3cd5d17d58be204f48428877bed053f756ac40a8
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
2022-02-03 12:45:18 +00:00
|
|
|
m_logger->log(
|
2022-02-03 11:01:35 +00:00
|
|
|
u"Variable \"%1\" is used here before its declaration. The declaration is at %2:%3."_qs
|
|
|
|
.arg(name)
|
|
|
|
.arg(declarationLocation.startLine)
|
|
|
|
.arg(declarationLocation.startColumn),
|
|
|
|
Log_Type, accessLocation);
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
QQmlJSLogger *m_logger;
|
|
|
|
};
|
|
|
|
|
|
|
|
QQmlJSLinter::QQmlJSLinter(const QStringList &importPaths, bool useAbsolutePath)
|
2022-02-07 12:53:49 +00:00
|
|
|
: m_useAbsolutePath(useAbsolutePath), m_importer(importPaths, nullptr, true)
|
2021-11-17 10:25:36 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2022-02-03 11:01:35 +00:00
|
|
|
void QQmlJSLinter::parseComments(QQmlJSLogger *logger,
|
|
|
|
const QList<QQmlJS::SourceLocation> &comments)
|
2021-12-16 16:15:21 +00:00
|
|
|
{
|
|
|
|
QHash<int, QSet<QQmlJSLoggerCategory>> disablesPerLine;
|
|
|
|
QHash<int, QSet<QQmlJSLoggerCategory>> enablesPerLine;
|
|
|
|
QHash<int, QSet<QQmlJSLoggerCategory>> oneLineDisablesPerLine;
|
|
|
|
|
|
|
|
const QString code = logger->code();
|
|
|
|
const QStringList lines = code.split(u'\n');
|
|
|
|
|
|
|
|
for (const auto &loc : comments) {
|
|
|
|
const QString comment = code.mid(loc.offset, loc.length);
|
|
|
|
if (!comment.startsWith(u" qmllint ") && !comment.startsWith(u"qmllint "))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
QStringList words = comment.split(u' ');
|
|
|
|
if (words.constFirst().isEmpty())
|
|
|
|
words.removeFirst();
|
|
|
|
|
|
|
|
const QString command = words.at(1);
|
|
|
|
|
|
|
|
QSet<QQmlJSLoggerCategory> categories;
|
|
|
|
for (qsizetype i = 2; i < words.size(); i++) {
|
|
|
|
const QString category = words.at(i);
|
|
|
|
const auto option = logger->options().constFind(category);
|
|
|
|
if (option != logger->options().constEnd())
|
|
|
|
categories << option->m_category;
|
|
|
|
else
|
Redesign QQmlJSLogger internals
High-level goal: be able to reuse existing infrastructure
"as is" to configure semantic analysis categories in tools
(qmllint, qmltc, qmlsc, etc.)
To achieve that, simplify the logging to always "log"
something, without explicitly specifying the severity. The
severity is now baked into the category (and we can extend
those to cover different cases)
One slight deviation is the cache generation which likes
to do its own thing at present. Provide a "forced logging"
option where we can specify which severify we want. The
hope is that this gets removed at some point
Particular list of (noteworthy) changes:
* No more "thresholding" by the level (this is rarely needed
and is actually questionable). Instead, we can ignore a
particular category explicitly
* Category levels are repurposed as category severities
(at least from the high-level picture that always should've
been this way)
* log{Warning,Info,Critical} removed. We use category severity
instead
* "category error" makes zero sense so removed: if our severity
is:
- QtWarningMsg (qmllint), it is already an "error"
- QtCriticalMsg (compilers), it is already an "error"
* Align m_output and m_{infos,warnings,errors} stored information
* Accept the fact that we don't support QtDebugMsg and QtFatalMsg
* Additional categories added to cover for places where the same
category would be both an error and not an error
Task-number: QTBUG-100052
Change-Id: I3cd5d17d58be204f48428877bed053f756ac40a8
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
2022-02-03 12:45:18 +00:00
|
|
|
logger->log(u"qmllint directive on unknown category \"%1\""_qs.arg(category),
|
|
|
|
Log_Syntax, loc);
|
2021-12-16 16:15:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (categories.isEmpty()) {
|
|
|
|
for (const auto &option : logger->options())
|
|
|
|
categories << option.m_category;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (command == u"disable"_qs) {
|
|
|
|
const QString line = lines[loc.startLine - 1];
|
|
|
|
const QString preComment = line.left(line.indexOf(comment) - 2);
|
|
|
|
|
|
|
|
bool lineHasContent = false;
|
|
|
|
for (qsizetype i = 0; i < preComment.size(); i++) {
|
|
|
|
if (!preComment[i].isSpace()) {
|
|
|
|
lineHasContent = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (lineHasContent)
|
|
|
|
oneLineDisablesPerLine[loc.startLine] |= categories;
|
|
|
|
else
|
|
|
|
disablesPerLine[loc.startLine] |= categories;
|
|
|
|
} else if (command == u"enable"_qs) {
|
|
|
|
enablesPerLine[loc.startLine + 1] |= categories;
|
|
|
|
} else {
|
Redesign QQmlJSLogger internals
High-level goal: be able to reuse existing infrastructure
"as is" to configure semantic analysis categories in tools
(qmllint, qmltc, qmlsc, etc.)
To achieve that, simplify the logging to always "log"
something, without explicitly specifying the severity. The
severity is now baked into the category (and we can extend
those to cover different cases)
One slight deviation is the cache generation which likes
to do its own thing at present. Provide a "forced logging"
option where we can specify which severify we want. The
hope is that this gets removed at some point
Particular list of (noteworthy) changes:
* No more "thresholding" by the level (this is rarely needed
and is actually questionable). Instead, we can ignore a
particular category explicitly
* Category levels are repurposed as category severities
(at least from the high-level picture that always should've
been this way)
* log{Warning,Info,Critical} removed. We use category severity
instead
* "category error" makes zero sense so removed: if our severity
is:
- QtWarningMsg (qmllint), it is already an "error"
- QtCriticalMsg (compilers), it is already an "error"
* Align m_output and m_{infos,warnings,errors} stored information
* Accept the fact that we don't support QtDebugMsg and QtFatalMsg
* Additional categories added to cover for places where the same
category would be both an error and not an error
Task-number: QTBUG-100052
Change-Id: I3cd5d17d58be204f48428877bed053f756ac40a8
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
2022-02-03 12:45:18 +00:00
|
|
|
logger->log(u"Invalid qmllint directive \"%1\" provided"_qs.arg(command), Log_Syntax,
|
|
|
|
loc);
|
2021-12-16 16:15:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (disablesPerLine.isEmpty() && oneLineDisablesPerLine.isEmpty())
|
|
|
|
return;
|
|
|
|
|
|
|
|
QSet<QQmlJSLoggerCategory> currentlyDisabled;
|
|
|
|
for (qsizetype i = 1; i <= lines.length(); i++) {
|
|
|
|
currentlyDisabled.unite(disablesPerLine[i]).subtract(enablesPerLine[i]);
|
|
|
|
|
|
|
|
currentlyDisabled.unite(oneLineDisablesPerLine[i]);
|
|
|
|
|
|
|
|
if (!currentlyDisabled.isEmpty())
|
|
|
|
logger->ignoreWarnings(i, currentlyDisabled);
|
|
|
|
|
|
|
|
currentlyDisabled.subtract(oneLineDisablesPerLine[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-03 11:01:35 +00:00
|
|
|
bool QQmlJSLinter::lintFile(const QString &filename, const QString *fileContents, const bool silent,
|
|
|
|
QJsonArray *json, const QStringList &qmlImportPaths,
|
|
|
|
const QStringList &qmldirFiles, const QStringList &resourceFiles,
|
|
|
|
const QMap<QString, QQmlJSLogger::Option> &options)
|
2021-11-17 10:25:36 +00:00
|
|
|
{
|
2021-11-23 14:52:44 +00:00
|
|
|
// Make sure that we don't expose an old logger if we return before a new one is created.
|
|
|
|
m_logger.reset();
|
|
|
|
|
2021-11-17 10:25:36 +00:00
|
|
|
QJsonArray warnings;
|
|
|
|
QJsonObject result;
|
|
|
|
|
|
|
|
bool success = true;
|
|
|
|
|
|
|
|
QScopeGuard jsonOutput([&] {
|
|
|
|
if (!json)
|
|
|
|
return;
|
|
|
|
|
|
|
|
result[u"filename"_qs] = QFileInfo(filename).absoluteFilePath();
|
|
|
|
result[u"warnings"] = warnings;
|
|
|
|
result[u"success"] = success;
|
|
|
|
|
|
|
|
json->append(result);
|
|
|
|
});
|
|
|
|
|
2021-12-07 17:48:08 +00:00
|
|
|
auto addJsonWarning = [&](const QQmlJS::DiagnosticMessage &message,
|
|
|
|
const std::optional<FixSuggestion> &suggestion = {}) {
|
2021-11-17 10:25:36 +00:00
|
|
|
QJsonObject jsonMessage;
|
|
|
|
|
|
|
|
QString type;
|
|
|
|
switch (message.type) {
|
|
|
|
case QtDebugMsg:
|
|
|
|
type = u"debug"_qs;
|
|
|
|
break;
|
|
|
|
case QtWarningMsg:
|
|
|
|
type = u"warning"_qs;
|
|
|
|
break;
|
|
|
|
case QtCriticalMsg:
|
|
|
|
type = u"critical"_qs;
|
|
|
|
break;
|
|
|
|
case QtFatalMsg:
|
|
|
|
type = u"fatal"_qs;
|
|
|
|
break;
|
|
|
|
case QtInfoMsg:
|
|
|
|
type = u"info"_qs;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
type = u"unknown"_qs;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
jsonMessage[u"type"_qs] = type;
|
|
|
|
|
|
|
|
if (message.loc.isValid()) {
|
|
|
|
jsonMessage[u"line"_qs] = static_cast<int>(message.loc.startLine);
|
|
|
|
jsonMessage[u"column"_qs] = static_cast<int>(message.loc.startColumn);
|
|
|
|
jsonMessage[u"charOffset"_qs] = static_cast<int>(message.loc.offset);
|
|
|
|
jsonMessage[u"length"_qs] = static_cast<int>(message.loc.length);
|
|
|
|
}
|
|
|
|
|
|
|
|
jsonMessage[u"message"_qs] = message.message;
|
|
|
|
|
2021-12-07 17:48:08 +00:00
|
|
|
QJsonArray suggestions;
|
|
|
|
if (suggestion.has_value()) {
|
|
|
|
for (const auto &fix : suggestion->fixes) {
|
|
|
|
QJsonObject jsonFix;
|
|
|
|
jsonFix[u"message"] = fix.message;
|
|
|
|
jsonFix[u"line"_qs] = static_cast<int>(fix.cutLocation.startLine);
|
|
|
|
jsonFix[u"column"_qs] = static_cast<int>(fix.cutLocation.startColumn);
|
|
|
|
jsonFix[u"charOffset"_qs] = static_cast<int>(fix.cutLocation.offset);
|
|
|
|
jsonFix[u"length"_qs] = static_cast<int>(fix.cutLocation.length);
|
|
|
|
jsonFix[u"replacement"_qs] = fix.replacementString;
|
2022-02-24 09:28:52 +00:00
|
|
|
jsonFix[u"isHint"] = fix.isHint;
|
2021-12-07 17:48:08 +00:00
|
|
|
suggestions << jsonFix;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
jsonMessage[u"suggestions"] = suggestions;
|
|
|
|
|
2021-11-17 10:25:36 +00:00
|
|
|
warnings << jsonMessage;
|
|
|
|
};
|
|
|
|
|
2021-11-23 14:52:44 +00:00
|
|
|
QString code;
|
|
|
|
|
|
|
|
if (fileContents == nullptr) {
|
|
|
|
QFile file(filename);
|
|
|
|
if (!file.open(QFile::ReadOnly)) {
|
|
|
|
if (json) {
|
2022-02-03 11:01:35 +00:00
|
|
|
addJsonWarning(
|
|
|
|
QQmlJS::DiagnosticMessage { QStringLiteral("Failed to open file %1: %2")
|
|
|
|
.arg(filename, file.errorString()),
|
|
|
|
QtCriticalMsg, QQmlJS::SourceLocation() });
|
2021-11-23 14:52:44 +00:00
|
|
|
success = false;
|
|
|
|
} else if (!silent) {
|
|
|
|
qWarning() << "Failed to open file" << filename << file.error();
|
|
|
|
}
|
|
|
|
return false;
|
2021-11-17 10:25:36 +00:00
|
|
|
}
|
|
|
|
|
2021-11-23 14:52:44 +00:00
|
|
|
code = QString::fromUtf8(file.readAll());
|
|
|
|
file.close();
|
|
|
|
} else {
|
|
|
|
code = *fileContents;
|
|
|
|
}
|
2021-11-17 10:25:36 +00:00
|
|
|
|
|
|
|
QQmlJS::Engine engine;
|
|
|
|
QQmlJS::Lexer lexer(&engine);
|
|
|
|
|
|
|
|
QFileInfo info(filename);
|
|
|
|
const QString lowerSuffix = info.suffix().toLower();
|
|
|
|
const bool isESModule = lowerSuffix == QLatin1String("mjs");
|
|
|
|
const bool isJavaScript = isESModule || lowerSuffix == QLatin1String("js");
|
|
|
|
|
|
|
|
lexer.setCode(code, /*lineno = */ 1, /*qmlMode=*/!isJavaScript);
|
|
|
|
QQmlJS::Parser parser(&engine);
|
|
|
|
|
|
|
|
success = isJavaScript ? (isESModule ? parser.parseModule() : parser.parseProgram())
|
|
|
|
: parser.parse();
|
|
|
|
|
2021-12-07 17:48:08 +00:00
|
|
|
if (!success) {
|
2021-11-17 10:25:36 +00:00
|
|
|
const auto diagnosticMessages = parser.diagnosticMessages();
|
|
|
|
for (const QQmlJS::DiagnosticMessage &m : diagnosticMessages) {
|
|
|
|
if (json) {
|
|
|
|
addJsonWarning(m);
|
2021-12-07 17:48:08 +00:00
|
|
|
} else if (!silent) {
|
|
|
|
qWarning().noquote() << QString::fromLatin1("%1:%2:%3: %4")
|
2021-11-17 10:25:36 +00:00
|
|
|
.arg(filename)
|
|
|
|
.arg(m.loc.startLine)
|
2021-12-07 17:48:08 +00:00
|
|
|
.arg(m.loc.startColumn)
|
2021-11-17 10:25:36 +00:00
|
|
|
.arg(m.message);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (success && !isJavaScript) {
|
2021-12-15 09:25:40 +00:00
|
|
|
const auto processMessages = [&]() {
|
|
|
|
if (json) {
|
|
|
|
for (const auto &error : m_logger->errors())
|
|
|
|
addJsonWarning(error, error.fixSuggestion);
|
|
|
|
for (const auto &warning : m_logger->warnings())
|
|
|
|
addJsonWarning(warning, warning.fixSuggestion);
|
|
|
|
for (const auto &info : m_logger->infos())
|
|
|
|
addJsonWarning(info, info.fixSuggestion);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2021-11-17 10:25:36 +00:00
|
|
|
const auto check = [&](QQmlJSResourceFileMapper *mapper) {
|
|
|
|
if (m_importer.importPaths() != qmlImportPaths)
|
|
|
|
m_importer.setImportPaths(qmlImportPaths);
|
|
|
|
|
|
|
|
m_importer.setResourceFileMapper(mapper);
|
|
|
|
|
2021-11-18 13:26:29 +00:00
|
|
|
m_logger.reset(new QQmlJSLogger);
|
|
|
|
m_logger->setFileName(m_useAbsolutePath ? info.absoluteFilePath() : filename);
|
|
|
|
m_logger->setCode(code);
|
|
|
|
m_logger->setSilent(silent || json);
|
2021-12-16 16:15:21 +00:00
|
|
|
QQmlJSImportVisitor v { &m_importer, m_logger.get(),
|
|
|
|
QQmlJSImportVisitor::implicitImportDirectory(
|
|
|
|
m_logger->fileName(), m_importer.resourceFileMapper()),
|
|
|
|
qmldirFiles };
|
|
|
|
|
|
|
|
parseComments(m_logger.get(), engine.comments());
|
2021-11-17 10:25:36 +00:00
|
|
|
|
|
|
|
for (auto it = options.cbegin(); it != options.cend(); ++it) {
|
2022-01-10 13:52:30 +00:00
|
|
|
if (!it.value().m_changed)
|
|
|
|
continue;
|
|
|
|
|
Redesign QQmlJSLogger internals
High-level goal: be able to reuse existing infrastructure
"as is" to configure semantic analysis categories in tools
(qmllint, qmltc, qmlsc, etc.)
To achieve that, simplify the logging to always "log"
something, without explicitly specifying the severity. The
severity is now baked into the category (and we can extend
those to cover different cases)
One slight deviation is the cache generation which likes
to do its own thing at present. Provide a "forced logging"
option where we can specify which severify we want. The
hope is that this gets removed at some point
Particular list of (noteworthy) changes:
* No more "thresholding" by the level (this is rarely needed
and is actually questionable). Instead, we can ignore a
particular category explicitly
* Category levels are repurposed as category severities
(at least from the high-level picture that always should've
been this way)
* log{Warning,Info,Critical} removed. We use category severity
instead
* "category error" makes zero sense so removed: if our severity
is:
- QtWarningMsg (qmllint), it is already an "error"
- QtCriticalMsg (compilers), it is already an "error"
* Align m_output and m_{infos,warnings,errors} stored information
* Accept the fact that we don't support QtDebugMsg and QtFatalMsg
* Additional categories added to cover for places where the same
category would be both an error and not an error
Task-number: QTBUG-100052
Change-Id: I3cd5d17d58be204f48428877bed053f756ac40a8
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
2022-02-03 12:45:18 +00:00
|
|
|
m_logger->setCategoryIgnored(it.value().m_category, it.value().m_ignored);
|
2021-11-23 14:52:44 +00:00
|
|
|
m_logger->setCategoryLevel(it.value().m_category, it.value().m_level);
|
2021-11-17 10:25:36 +00:00
|
|
|
}
|
|
|
|
|
2021-11-18 13:26:29 +00:00
|
|
|
QQmlJSTypeResolver typeResolver(&m_importer);
|
2021-11-23 15:05:05 +00:00
|
|
|
|
2022-02-03 11:01:35 +00:00
|
|
|
// Type resolving is using document parent mode here so that it produces fewer false
|
|
|
|
// positives on the "parent" property of QQuickItem. It does produce a few false
|
|
|
|
// negatives this way because items can be reparented. Furthermore, even if items are
|
|
|
|
// not reparented, the document parent may indeed not be their visual parent. See
|
|
|
|
// QTBUG-95530. Eventually, we'll need cleverer logic to deal with this.
|
2021-11-18 13:26:29 +00:00
|
|
|
typeResolver.setParentMode(QQmlJSTypeResolver::UseDocumentParent);
|
2021-11-23 15:05:05 +00:00
|
|
|
|
2021-11-18 13:26:29 +00:00
|
|
|
typeResolver.init(&v, parser.rootNode());
|
2021-12-16 16:15:21 +00:00
|
|
|
success = !m_logger->hasWarnings() && !m_logger->hasErrors();
|
2021-11-17 10:25:36 +00:00
|
|
|
|
2021-12-15 09:25:40 +00:00
|
|
|
if (m_logger->hasErrors()) {
|
|
|
|
processMessages();
|
2021-11-17 10:25:36 +00:00
|
|
|
return;
|
2021-12-15 09:25:40 +00:00
|
|
|
}
|
2021-11-17 10:25:36 +00:00
|
|
|
|
|
|
|
QQmlJSTypeInfo typeInfo;
|
2021-11-18 13:26:29 +00:00
|
|
|
|
|
|
|
const QStringList resourcePaths = mapper
|
|
|
|
? mapper->resourcePaths(QQmlJSResourceFileMapper::localFileFilter(filename))
|
|
|
|
: QStringList();
|
2022-02-03 11:01:35 +00:00
|
|
|
const QString resolvedPath =
|
|
|
|
(resourcePaths.size() == 1) ? u':' + resourcePaths.first() : filename;
|
2021-11-18 13:26:29 +00:00
|
|
|
|
2022-02-03 11:01:35 +00:00
|
|
|
QQmlJSLinterCodegen codegen { &m_importer, resolvedPath, qmldirFiles, m_logger.get(),
|
|
|
|
&typeInfo };
|
2021-11-23 15:05:05 +00:00
|
|
|
codegen.setTypeResolver(std::move(typeResolver));
|
2021-11-17 10:25:36 +00:00
|
|
|
QQmlJSSaveFunction saveFunction = [](const QV4::CompiledData::SaveableUnitPointer &,
|
|
|
|
const QQmlJSAotFunctionMap &,
|
|
|
|
QString *) { return true; };
|
|
|
|
|
|
|
|
QQmlJSCompileError error;
|
|
|
|
|
|
|
|
QLoggingCategory::setFilterRules(u"qt.qml.compiler=false"_qs);
|
|
|
|
|
2021-11-23 14:52:44 +00:00
|
|
|
CodegenWarningInterface interface(m_logger.get());
|
2021-12-13 12:19:33 +00:00
|
|
|
qCompileQmlFile(filename, saveFunction, &codegen, &error, true, &interface,
|
|
|
|
fileContents);
|
2021-11-17 10:25:36 +00:00
|
|
|
|
2022-01-18 12:08:09 +00:00
|
|
|
QList<QQmlJS::DiagnosticMessage> warnings = m_importer.takeGlobalWarnings();
|
|
|
|
|
|
|
|
if (!warnings.isEmpty()) {
|
Redesign QQmlJSLogger internals
High-level goal: be able to reuse existing infrastructure
"as is" to configure semantic analysis categories in tools
(qmllint, qmltc, qmlsc, etc.)
To achieve that, simplify the logging to always "log"
something, without explicitly specifying the severity. The
severity is now baked into the category (and we can extend
those to cover different cases)
One slight deviation is the cache generation which likes
to do its own thing at present. Provide a "forced logging"
option where we can specify which severify we want. The
hope is that this gets removed at some point
Particular list of (noteworthy) changes:
* No more "thresholding" by the level (this is rarely needed
and is actually questionable). Instead, we can ignore a
particular category explicitly
* Category levels are repurposed as category severities
(at least from the high-level picture that always should've
been this way)
* log{Warning,Info,Critical} removed. We use category severity
instead
* "category error" makes zero sense so removed: if our severity
is:
- QtWarningMsg (qmllint), it is already an "error"
- QtCriticalMsg (compilers), it is already an "error"
* Align m_output and m_{infos,warnings,errors} stored information
* Accept the fact that we don't support QtDebugMsg and QtFatalMsg
* Additional categories added to cover for places where the same
category would be both an error and not an error
Task-number: QTBUG-100052
Change-Id: I3cd5d17d58be204f48428877bed053f756ac40a8
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
2022-02-03 12:45:18 +00:00
|
|
|
m_logger->log(QStringLiteral("Type warnings occurred while evaluating file:"),
|
|
|
|
Log_Import, QQmlJS::SourceLocation());
|
|
|
|
m_logger->processMessages(warnings, Log_Import);
|
2022-01-18 12:08:09 +00:00
|
|
|
}
|
|
|
|
|
2021-11-23 14:52:44 +00:00
|
|
|
success &= !m_logger->hasWarnings() && !m_logger->hasErrors();
|
2021-11-17 10:25:36 +00:00
|
|
|
|
2021-12-15 09:25:40 +00:00
|
|
|
processMessages();
|
2021-11-17 10:25:36 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
if (resourceFiles.isEmpty()) {
|
|
|
|
check(nullptr);
|
|
|
|
} else {
|
|
|
|
QQmlJSResourceFileMapper mapper(resourceFiles);
|
|
|
|
check(&mapper);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return success;
|
|
|
|
}
|
|
|
|
|
|
|
|
QT_END_NAMESPACE
|