Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qqmljsloggingutils.cpp
Go to the documentation of this file.
1// Copyright (C) 2023 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
3// Qt-Security score:significant
4
6
7#include <QtQmlToolingSettings/private/qqmltoolingsettings_p.h>
8#include <QtCore/qcommandlineparser.h>
9
11
12using namespace Qt::StringLiterals;
13
14/*!
15 \enum QQmlSA::WarningSeverity
16 \inmodule QtQmlCompiler
17 \since 6.12
18
19 \brief Holds the possible severity levels of diagnostics messages for a logging category.
20 \value Error Messages emitted by this logging category will cause an error.
21 \value Warning Messages emitted by this logging category are warnings. No error is produced unless the \l{qmllint#Settings}{MaxWarnings} setting is set and exceeded.
22 \value Info Messages emitted by this logging category are purely informative and do not count towards \l{qmllint#Settings}{MaxWarnings}.
23 \value Disable This logging category will not emit any messages.
24*/
25
26/*!
27 \class QQmlSA::LoggerWarningId
28 \inmodule QtQmlCompiler
29
30 \brief A wrapper around a string literal to uniquely identify
31 warning categories in the \c{QQmlSA} framework.
32*/
33
34/*!
35 \fn QQmlSA::LoggerWarningId::LoggerWarningId(QAnyStringView name)
36 Constructs a LoggerWarningId object with logging catergory name \a name.
37*/
38
39/*!
40 \fn QAnyStringView QQmlSA::LoggerWarningId::name() const
41 Returns the name of the wrapped warning category.
42*/
43
44namespace QQmlSA {
45
46static_assert(int(WarningSeverity::Disable) != int(QtMsgType::QtInfoMsg));
47static_assert(int(WarningSeverity::Disable) != int(QtMsgType::QtWarningMsg));
48static_assert(int(WarningSeverity::Disable) != int(QtMsgType::QtCriticalMsg));
49
50} // namespace QQmlSA
51
52namespace QQmlJS {
53
55
62
67
68LoggerCategory::LoggerCategory(LoggerCategory &&) noexcept = default;
69
71{
72 *d_func() = *other.d_func();
73 return *this;
74}
75
77
78LoggerCategory::~LoggerCategory() = default;
79
81{
82 Q_D(const LoggerCategory);
83 return d->name();
84}
85
87{
88 Q_D(const LoggerCategory);
89 return d->settingsName();
90}
91
93{
94 Q_D(const LoggerCategory);
95 return d->description();
96}
97
99{
100 Q_D(const LoggerCategory);
101 return d->severity();
102}
103
105{
106 Q_D(const LoggerCategory);
107 return d->isEssential();
108}
109
111{
112 Q_D(const LoggerCategory);
113 return d->id();
114}
115
121
129
131{
132 if (m_severity == severity)
133 return;
134
136 m_changed = true;
137}
138
144
145namespace LoggingUtils {
146
148{
149 switch (severity) {
151 return QStringLiteral("disable");
153 return QStringLiteral("info");
155 return QStringLiteral("warning");
157 return QStringLiteral("error");
158 default:
159 Q_UNREACHABLE();
160 break;
161 }
162};
163
164static QStringList settingsNamesForCategory(const LoggerCategory &category)
165{
166 const QString name = category.settingsName();
167 QStringList result{ QStringLiteral("Warnings/") + name };
168 const QString sliced = "Warnings/"_L1 + name.sliced(name.indexOf(u'.') + 1);
169 if (sliced != result.last())
170 result.append(sliced);
171 return result;
172}
173
174static QString lookInSettings(const LoggerCategory &category, const QQmlToolingSettings &settings,
175 const QString &settingsName)
176{
177 if (settings.isSet(settingsName))
178 return settings.value(settingsName).toString();
179 static constexpr QLatin1String propertyAliasCyclesKey = "Warnings/PropertyAliasCycles"_L1;
180
181 // keep compatibility to deprecated settings
182 if (category.name() == qmlAliasCycle.name() || category.name() == qmlUnresolvedAlias.name()) {
183 if (settings.isSet(propertyAliasCyclesKey)) {
184 qWarning()
185 << "Detected deprecated setting name \"PropertyAliasCycles\". Use %1 or %2 instead."_L1
186 .arg(qmlAliasCycle.name(), qmlUnresolvedAlias.name());
187 return settings.value(propertyAliasCyclesKey).toString();
188 }
189 }
190 return {};
191}
192
193static QString severityValueForCategory(const LoggerCategory &category,
194 const QQmlToolingSettings &settings,
195 QCommandLineParser *parser)
196{
197 const QString key = category.id().name().toString();
198 if (parser && parser->isSet(key))
199 return parser->value(key);
200
201 const QStringList settingsName = settingsNamesForCategory(category);
202 for (const QString &settingsName : settingsName) {
203 const QString value = lookInSettings(category, settings, settingsName);
204 if (value.isEmpty())
205 continue;
206
207 // Do not try to set the severity if it's due to a default config option.
208 // This way we can tell which options have actually been overwritten by the user.
209 if (severityToString(category.severity()) == value)
210 return QString();
211
212 return value;
213 }
214 return QString();
215}
216
218{
219 if (s == "disable"_L1)
221 if (s == "info"_L1)
223 if (s == "warning"_L1)
225 if (s == "error"_L1)
227 return {};
228}
229
230static constexpr bool less(WarningSeverity lhs, WarningSeverity rhs)
231{
232 const auto orderedValue = [](WarningSeverity s) {
233 switch (s) {
235 return 3;
237 return 2;
239 return 1;
241 return 0;
242 }
243 Q_UNREACHABLE();
244 };
245 return orderedValue(lhs) < orderedValue(rhs);
246}
247
248/*!
249\internal
250Sets the category severity from a settings file and an optional parser.
251Calls \c {parser->showHelp(-1)} for an invalid logging severity.
252*/
253void updateLogSeverities(QList<LoggerCategory> &categories,
254 const QQmlToolingSettings &settings,
255 QCommandLineParser *parser,
256 CategorySelection categorySelection)
257{
258 bool success = true;
259 for (auto &category : categories) {
260 // Disable all non-essential categories, they may still be overriden by settings or command line options
261 if (categorySelection == CategorySelection::Explicit && !category.isEssential())
262 category.setSeverity(QQmlSA::WarningSeverity::Disable);
263
264 const QString value = severityValueForCategory(category, settings, parser);
265 if (value.isEmpty())
266 continue;
267
268 const QString &name = category.id().name().toString();
269 const std::optional<QQmlJS::WarningSeverity> severity = severityFromString(value);
270 if (!severity.has_value()) {
271 qWarning() << "Invalid logging severity" << value << "provided for" << name
272 << "(allowed are: disable, info, warning, error).";
273 success = false;
274 continue;
275 }
276
277 if (category.isEssential() && less(severity.value(), category.severity())) {
278 qWarning() << "In order to ensure the proper function of qmllint, the severity of the "
279 "essential category %1 cannot be lowered."_L1.arg(name);
280 continue;
281 }
282
283 category.setSeverity(*severity);
284 }
285
286 if (!success && parser)
287 parser->showHelp(-1);
288}
289} // namespace LoggingUtils
290
291} // namespace QQmlJS
292
293QT_END_NAMESPACE
static QString severityValueForCategory(const LoggerCategory &category, const QQmlToolingSettings &settings, QCommandLineParser *parser)
static constexpr bool less(WarningSeverity lhs, WarningSeverity rhs)
std::optional< QQmlJS::WarningSeverity > severityFromString(const QString &s)
static QString lookInSettings(const LoggerCategory &category, const QQmlToolingSettings &settings, const QString &settingsName)
void updateLogSeverities(QList< LoggerCategory > &categories, const QQmlToolingSettings &settings, QCommandLineParser *parser, CategorySelection categorySelection)
QString severityToString(QQmlJS::WarningSeverity severity)
static QStringList settingsNamesForCategory(const LoggerCategory &category)
QQmlSA::WarningSeverity WarningSeverity
\inmodule QtQmlCompiler
Combined button and popup list for selecting options.