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 | |
4 | #include "qqmljsloggingutils_p.h" |
5 | |
6 | #include <QtQmlToolingSettings/private/qqmltoolingsettings_p.h> |
7 | #include <QtCore/qcommandlineparser.h> |
8 | |
9 | QT_BEGIN_NAMESPACE |
10 | |
11 | using namespace Qt::StringLiterals; |
12 | |
13 | namespace QQmlJS { |
14 | |
15 | LoggerCategory::LoggerCategory() : d_ptr{ new LoggerCategoryPrivate } { } |
16 | |
17 | LoggerCategory::LoggerCategory(QString name, QString settingsName, QString description, |
18 | QtMsgType level, bool ignored, bool isDefault) |
19 | : d_ptr{ new LoggerCategoryPrivate } |
20 | { |
21 | Q_D(LoggerCategory); |
22 | d->m_name = name; |
23 | d->m_settingsName = settingsName; |
24 | d->m_description = description; |
25 | d->m_level = level; |
26 | d->m_ignored = ignored; |
27 | d->m_isDefault = isDefault; |
28 | } |
29 | |
30 | LoggerCategory::LoggerCategory(const LoggerCategory &other) |
31 | : d_ptr{ new LoggerCategoryPrivate{ *other.d_func() } } |
32 | { |
33 | } |
34 | |
35 | LoggerCategory::LoggerCategory(LoggerCategory &&) noexcept = default; |
36 | |
37 | LoggerCategory &LoggerCategory::operator=(const LoggerCategory &other) |
38 | { |
39 | *d_func() = *other.d_func(); |
40 | return *this; |
41 | } |
42 | |
43 | LoggerCategory &LoggerCategory::operator=(LoggerCategory &&) noexcept = default; |
44 | |
45 | LoggerCategory::~LoggerCategory() = default; |
46 | |
47 | QString LoggerCategory::name() const |
48 | { |
49 | Q_D(const LoggerCategory); |
50 | return d->m_name; |
51 | } |
52 | |
53 | QString LoggerCategory::settingsName() const |
54 | { |
55 | Q_D(const LoggerCategory); |
56 | return d->m_settingsName; |
57 | } |
58 | |
59 | QString LoggerCategory::description() const |
60 | { |
61 | Q_D(const LoggerCategory); |
62 | return d->m_description; |
63 | } |
64 | |
65 | QtMsgType LoggerCategory::level() const |
66 | { |
67 | Q_D(const LoggerCategory); |
68 | return d->m_level; |
69 | } |
70 | |
71 | bool LoggerCategory::isIgnored() const |
72 | { |
73 | Q_D(const LoggerCategory); |
74 | return d->m_ignored; |
75 | } |
76 | |
77 | bool LoggerCategory::isDefault() const |
78 | { |
79 | Q_D(const LoggerCategory); |
80 | return d->m_isDefault; |
81 | } |
82 | |
83 | LoggerWarningId LoggerCategory::id() const |
84 | { |
85 | Q_D(const LoggerCategory); |
86 | return d->id(); |
87 | } |
88 | |
89 | void LoggerCategory::setLevel(QtMsgType type) |
90 | { |
91 | Q_D(LoggerCategory); |
92 | d->setLevel(type); |
93 | } |
94 | |
95 | void LoggerCategoryPrivate::setLevel(QtMsgType type) |
96 | { |
97 | if (m_level == type) |
98 | return; |
99 | |
100 | m_level = type; |
101 | m_changed = true; |
102 | } |
103 | |
104 | void LoggerCategory::setIgnored(bool isIgnored) |
105 | { |
106 | Q_D(LoggerCategory); |
107 | d->setIgnored(isIgnored); |
108 | } |
109 | |
110 | void LoggerCategoryPrivate::setIgnored(bool isIgnored) |
111 | { |
112 | if (m_ignored == isIgnored) |
113 | return; |
114 | |
115 | m_ignored = isIgnored; |
116 | m_changed = true; |
117 | } |
118 | |
119 | bool LoggerCategoryPrivate::hasChanged() const |
120 | { |
121 | return m_changed; |
122 | } |
123 | |
124 | LoggerCategoryPrivate *LoggerCategoryPrivate::get(LoggerCategory *loggerCategory) |
125 | { |
126 | Q_ASSERT(loggerCategory); |
127 | return loggerCategory->d_func(); |
128 | } |
129 | |
130 | /*! |
131 | \class QQmlSA::LoggerWarningId |
132 | \inmodule QtQmlCompiler |
133 | |
134 | \brief A wrapper around a string literal to uniquely identify |
135 | warning categories in the \c{QQmlSA} framework. |
136 | */ |
137 | |
138 | namespace LoggingUtils { |
139 | |
140 | QString levelToString(const QQmlJS::LoggerCategory &category) |
141 | { |
142 | Q_ASSERT(category.isIgnored() || category.level() != QtCriticalMsg); |
143 | if (category.isIgnored()) |
144 | return QStringLiteral("disable" ); |
145 | |
146 | switch (category.level()) { |
147 | case QtInfoMsg: |
148 | return QStringLiteral("info" ); |
149 | case QtWarningMsg: |
150 | return QStringLiteral("warning" ); |
151 | default: |
152 | Q_UNREACHABLE(); |
153 | break; |
154 | } |
155 | }; |
156 | |
157 | /*! |
158 | \internal |
159 | Sets the category levels from a settings file and an optional parser. |
160 | Calls \c {parser->showHelp(-1)} for invalid logging levels. |
161 | */ |
162 | void updateLogLevels(QList<LoggerCategory> &categories, |
163 | const QQmlToolingSettings &settings, |
164 | QCommandLineParser *parser) |
165 | { |
166 | bool success = true; |
167 | for (auto &category : categories) { |
168 | if (category.isDefault()) |
169 | continue; |
170 | |
171 | const QString value = [&] () { |
172 | const QString key = category.id().name().toString(); |
173 | if (parser && parser->isSet(name: key)) |
174 | return parser->value(name: key); |
175 | |
176 | // Do not try to set the levels if it's due to a default config option. |
177 | // This way we can tell which options have actually been overwritten by the user. |
178 | const QString settingsName = QStringLiteral("Warnings/" ) + category.settingsName(); |
179 | const QString value = settings.value(name: settingsName).toString(); |
180 | if (levelToString(category) == value) |
181 | return QString(); |
182 | |
183 | return value; |
184 | }(); |
185 | if (value.isEmpty()) |
186 | continue; |
187 | |
188 | if (value == "disable"_L1 ) { |
189 | category.setLevel(QtCriticalMsg); |
190 | category.setIgnored(true); |
191 | } else if (value == "info"_L1 ) { |
192 | category.setLevel(QtInfoMsg); |
193 | category.setIgnored(false); |
194 | } else if (value == "warning"_L1 ) { |
195 | category.setLevel(QtWarningMsg); |
196 | category.setIgnored(false); |
197 | } else { |
198 | qWarning() << "Invalid logging level" << value << "provided for" |
199 | << category.id().name().toString() |
200 | << "(allowed are: disable, info, warning)" ; |
201 | success = false; |
202 | |
203 | } |
204 | } |
205 | if (!success && parser) |
206 | parser->showHelp(exitCode: -1); |
207 | } |
208 | } // namespace LoggingUtils |
209 | |
210 | } // namespace QQmlJS |
211 | |
212 | QT_END_NAMESPACE |
213 | |