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
42
47
48LoggerCategory::LoggerCategory(LoggerCategory &&) noexcept = default;
49
51{
52 *d_func() = *other.d_func();
53 return *this;
54}
55
57
58LoggerCategory::~LoggerCategory() = default;
59
61{
62 Q_D(const LoggerCategory);
63 return d->name();
64}
65
67{
68 Q_D(const LoggerCategory);
69 return d->settingsName();
70}
71
73{
74 Q_D(const LoggerCategory);
75 return d->description();
76}
77
79{
80 Q_D(const LoggerCategory);
81 return d->level();
82}
83
85{
86 Q_D(const LoggerCategory);
87 return d->isIgnored();
88}
89
91{
92 Q_D(const LoggerCategory);
93 return d->isDefault();
94}
95
97{
98 Q_D(const LoggerCategory);
99 return d->id();
100}
101
107
115
117{
118 if (m_level == type)
119 return;
120
121 m_level = type;
122 m_changed = true;
123}
124
130
132{
133 if (m_isIgnored == isIgnored)
134 return;
135
137 m_changed = true;
138}
139
145
146namespace LoggingUtils {
147
148QString levelToString(const QQmlJS::LoggerCategory &category)
149{
150 if (category.isIgnored())
151 return QStringLiteral("disable");
152
153 switch (category.level()) {
154 case QtInfoMsg:
155 return QStringLiteral("info");
156 case QtWarningMsg:
157 return QStringLiteral("warning");
158 case QtCriticalMsg:
159 return QStringLiteral("error");
160 default:
161 Q_UNREACHABLE();
162 break;
163 }
164};
165
166static QStringList settingsNamesForCategory(const LoggerCategory &category)
167{
168 const QString name = category.settingsName();
169 QStringList result{ QStringLiteral("Warnings/") + name };
170 const QString sliced = "Warnings/"_L1 + name.sliced(name.indexOf(u'.') + 1);
171 if (sliced != result.last())
172 result.append(sliced);
173 return result;
174}
175
176static QString lookInSettings(const LoggerCategory &category, const QQmlToolingSettings &settings,
177 const QString &settingsName)
178{
179 if (settings.isSet(settingsName))
180 return settings.value(settingsName).toString();
181 static constexpr QLatin1String propertyAliasCyclesKey = "Warnings/PropertyAliasCycles"_L1;
182
183 // keep compatibility to deprecated settings
184 if (category.name() == qmlAliasCycle.name() || category.name() == qmlUnresolvedAlias.name()) {
185 if (settings.isSet(propertyAliasCyclesKey)) {
186 qWarning()
187 << "Detected deprecated setting name \"PropertyAliasCycles\". Use %1 or %2 instead."_L1
188 .arg(qmlAliasCycle.name(), qmlUnresolvedAlias.name());
189 return settings.value(propertyAliasCyclesKey).toString();
190 }
191 }
192 return {};
193}
194
195static QString levelValueForCategory(const LoggerCategory &category,
196 const QQmlToolingSettings &settings,
197 QCommandLineParser *parser)
198{
199 const QString key = category.id().name().toString();
200 if (parser && parser->isSet(key))
201 return parser->value(key);
202
203 const QStringList settingsName = settingsNamesForCategory(category);
204 for (const QString &settingsName : settingsName) {
205 const QString value = lookInSettings(category, settings, settingsName);
206 if (value.isEmpty())
207 continue;
208
209 // Do not try to set the levels if it's due to a default config option.
210 // This way we can tell which options have actually been overwritten by the user.
211 if (levelToString(category) == value)
212 return QString();
213
214 return value;
215 }
216 return QString();
217}
218
219bool applyLevelToCategory(const QStringView level, LoggerCategory &category)
220{
221 // you can't downgrade errors
222 if (category.level() == QtCriticalMsg && !category.isIgnored() && level != "error"_L1)
223 return false;
224
225 if (level == "disable"_L1) {
226 category.setLevel(QtCriticalMsg);
227 category.setIgnored(true);
228 return true;
229 }
230 if (level == "info"_L1) {
231 category.setLevel(QtInfoMsg);
232 category.setIgnored(false);
233 return true;
234 }
235 if (level == "warning"_L1) {
236 category.setLevel(QtWarningMsg);
237 category.setIgnored(false);
238 return true;
239 }
240 if (level == "error"_L1) {
241 category.setLevel(QtCriticalMsg);
242 category.setIgnored(false);
243 return true;
244 }
245
246 return false;
247};
248
249/*!
250\internal
251Sets the category levels from a settings file and an optional parser.
252Calls \c {parser->showHelp(-1)} for invalid logging levels.
253*/
254void updateLogLevels(QList<LoggerCategory> &categories,
255 const QQmlToolingSettings &settings,
256 QCommandLineParser *parser)
257{
258 bool success = true;
259 for (auto &category : categories) {
260 if (category.isDefault())
261 continue;
262
263 const QString value = levelValueForCategory(category, settings, parser);
264 if (value.isEmpty())
265 continue;
266
267 if (!applyLevelToCategory(value, category)) {
268 qWarning() << "Invalid logging level" << value << "provided for"
269 << category.id().name().toString()
270 << "(allowed are: disable, info, warning, error)\n."
271 "You can't change categories that have level \"error\" by default.";
272 success = false;
273 }
274 }
275 if (!success && parser)
276 parser->showHelp(-1);
277}
278} // namespace LoggingUtils
279
280} // namespace QQmlJS
281
282QT_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)
Combined button and popup list for selecting options.