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 \class QQmlSA::LoggerWarningId
16 \inmodule QtQmlCompiler
17
18 \brief A wrapper around a string literal to uniquely identify
19 warning categories in the \c{QQmlSA} framework.
20*/
21
22/*!
23 \fn QQmlSA::LoggerWarningId::LoggerWarningId(QAnyStringView name)
24 Constructs a LoggerWarningId object with logging catergory name \a name.
25*/
26
27/*!
28 \fn QAnyStringView QQmlSA::LoggerWarningId::name() const
29 Returns the name of the wrapped warning category.
30*/
31
32namespace QQmlJS {
33
35
49
54
55LoggerCategory::LoggerCategory(LoggerCategory &&) noexcept = default;
56
58{
59 *d_func() = *other.d_func();
60 return *this;
61}
62
64
65LoggerCategory::~LoggerCategory() = default;
66
68{
69 Q_D(const LoggerCategory);
70 return d->m_name;
71}
72
74{
75 Q_D(const LoggerCategory);
76 return d->m_settingsName;
77}
78
80{
81 Q_D(const LoggerCategory);
82 return d->m_description;
83}
84
86{
87 Q_D(const LoggerCategory);
88 return d->m_level;
89}
90
92{
93 Q_D(const LoggerCategory);
94 return d->m_ignored;
95}
96
98{
99 Q_D(const LoggerCategory);
100 return d->m_isDefault;
101}
102
104{
105 Q_D(const LoggerCategory);
106 return d->id();
107}
108
114
116{
117 if (m_level == type)
118 return;
119
120 m_level = type;
121 m_changed = true;
122}
123
129
131{
132 if (m_ignored == isIgnored)
133 return;
134
136 m_changed = true;
137}
138
140{
141 return m_changed;
142}
143
149
150namespace LoggingUtils {
151
152QString levelToString(const QQmlJS::LoggerCategory &category)
153{
154 if (category.isIgnored())
155 return QStringLiteral("disable");
156
157 switch (category.level()) {
158 case QtInfoMsg:
159 return QStringLiteral("info");
160 case QtWarningMsg:
161 return QStringLiteral("warning");
162 case QtCriticalMsg:
163 return QStringLiteral("error");
164 default:
165 Q_UNREACHABLE();
166 break;
167 }
168};
169
170static QStringList settingsNamesForCategory(const LoggerCategory &category)
171{
172 const QString name = category.settingsName();
173 const QStringList result{ QStringLiteral("Warnings/") += name,
174 QStringLiteral("Warnings/") += name.sliced(name.indexOf(u'.') + 1) };
175 return result;
176}
177
178static QString lookInSettings(const LoggerCategory &category, const QQmlToolingSettings &settings,
179 const QString &settingsName)
180{
181 if (settings.isSet(settingsName))
182 return settings.value(settingsName).toString();
183 static constexpr QLatin1String propertyAliasCyclesKey = "Warnings/PropertyAliasCycles"_L1;
184
185 // keep compatibility to deprecated settings
186 if (category.name() == qmlAliasCycle.name() || category.name() == qmlUnresolvedAlias.name()) {
187 if (settings.isSet(propertyAliasCyclesKey)) {
188 qWarning()
189 << "Detected deprecated setting name \"PropertyAliasCycles\". Use %1 or %2 instead."_L1
190 .arg(qmlAliasCycle.name(), qmlUnresolvedAlias.name());
191 return settings.value(propertyAliasCyclesKey).toString();
192 }
193 }
194 return {};
195}
196
197static QString levelValueForCategory(const LoggerCategory &category,
198 const QQmlToolingSettings &settings,
199 QCommandLineParser *parser)
200{
201 const QString key = category.id().name().toString();
202 if (parser && parser->isSet(key))
203 return parser->value(key);
204
205 const QStringList settingsName = settingsNamesForCategory(category);
206 for (const QString &settingsName : settingsName) {
207 const QString value = lookInSettings(category, settings, settingsName);
208 if (value.isEmpty())
209 continue;
210
211 // Do not try to set the levels if it's due to a default config option.
212 // This way we can tell which options have actually been overwritten by the user.
213 if (levelToString(category) == value)
214 return QString();
215
216 return value;
217 }
218 return QString();
219}
220
221bool applyLevelToCategory(const QStringView level, LoggerCategory &category)
222{
223 // you can't downgrade errors
224 if (category.level() == QtCriticalMsg && !category.isIgnored() && level != "error"_L1)
225 return false;
226
227 if (level == "disable"_L1) {
228 category.setLevel(QtCriticalMsg);
229 category.setIgnored(true);
230 return true;
231 }
232 if (level == "info"_L1) {
233 category.setLevel(QtInfoMsg);
234 category.setIgnored(false);
235 return true;
236 }
237 if (level == "warning"_L1) {
238 category.setLevel(QtWarningMsg);
239 category.setIgnored(false);
240 return true;
241 }
242 if (level == "error"_L1) {
243 category.setLevel(QtCriticalMsg);
244 category.setIgnored(false);
245 return true;
246 }
247
248 return false;
249};
250
251/*!
252\internal
253Sets the category levels from a settings file and an optional parser.
254Calls \c {parser->showHelp(-1)} for invalid logging levels.
255*/
256void updateLogLevels(QList<LoggerCategory> &categories,
257 const QQmlToolingSettings &settings,
258 QCommandLineParser *parser)
259{
260 bool success = true;
261 for (auto &category : categories) {
262 if (category.isDefault())
263 continue;
264
265 const QString value = levelValueForCategory(category, settings, parser);
266 if (value.isEmpty())
267 continue;
268
269 if (!applyLevelToCategory(value, category)) {
270 qWarning() << "Invalid logging level" << value << "provided for"
271 << category.id().name().toString()
272 << "(allowed are: disable, info, warning, error)\n."
273 "You can't change categories that have level \"error\" by default.";
274 success = false;
275 }
276 }
277 if (!success && parser)
278 parser->showHelp(-1);
279}
280} // namespace LoggingUtils
281
282} // namespace QQmlJS
283
284QT_END_NAMESPACE
bool applyLevelToCategory(const QStringView level, LoggerCategory &category)
static QString lookInSettings(const LoggerCategory &category, const QQmlToolingSettings &settings, const QString &settingsName)
QString levelToString(const QQmlJS::LoggerCategory &category)
static QString levelValueForCategory(const LoggerCategory &category, const QQmlToolingSettings &settings, QCommandLineParser *parser)
static QStringList settingsNamesForCategory(const LoggerCategory &category)
void updateLogLevels(QList< LoggerCategory > &categories, const QQmlToolingSettings &settings, QCommandLineParser *parser)