Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qqmldomerrormessage.cpp
Go to the documentation of this file.
1// Copyright (C) 2020 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3#include "qqmldomitem_p.h"
6
7#include <QtCore/QCborMap>
8#include <QtCore/QMutex>
9#include <QtCore/QMutexLocker>
10
12
13namespace QQmlJS {
14namespace Dom {
15
16Q_LOGGING_CATEGORY(domLog, "qt.qmldom", QtWarningMsg);
17
18enum {
20};
21
41{
42 sink(u"[");
43 sink(groupName());
44 sink(u"]");
45}
46
48{
49 sink(u"[");
51 sink(u"]");
52}
53
55{
56 return QLatin1String(m_groupId);
57}
58
60{
61 return tr(m_groupId);
62}
63
74{
75 for (int i = 0; i < groups.size(); ++i)
76 groups.at(i).dump(sink);
77}
78
80{
81 for (int i = 0; i < groups.size(); ++i)
82 groups.at(i).dumpId(sink);
83}
84
86{
88 for (int i = 0; i < groups.size(); ++i)
89 res.append(QCborValue(groups.at(i).groupId()));
90 return res;
91}
92
142{
144 fatal(msg, element, canonicalFilePath, location);
145 return ErrorMessage(dumperToString(msg), *this, level, element, canonicalFilePath, location);
146}
147
148ErrorMessage ErrorGroups::errorMessage(const DiagnosticMessage &msg, Path element, QString canonicalFilePath) const
149{
150 ErrorMessage res(*this, msg, element, canonicalFilePath);
151 if (res.location == SourceLocation()
152 && (res.location.startLine != 0 || res.location.startColumn != 0)) {
153 res.location.offset = -1;
154 res.location.length = 1;
155 }
156 return res;
157}
158
159void ErrorGroups::fatal(Dumper msg, Path element, QStringView canonicalFilePath, SourceLocation location) const
160{
161 enum { FatalMsgMaxLen = 1023 };
162 char buf[FatalMsgMaxLen+1];
163 int ibuf = 0;
164 auto sink = [&ibuf, &buf](QStringView s) {
165 int is = 0;
166 while (ibuf < FatalMsgMaxLen && is < s.size()) {
167 QChar c = s.at(is);
168 if (c == QChar::fromLatin1('\n') || c == QChar::fromLatin1('\r') || (c >= QChar::fromLatin1(' ') && c <= QChar::fromLatin1('~')))
169 buf[ibuf++] = c.toLatin1();
170 else
171 buf[ibuf++] = '~';
172 ++is;
173 }
174 };
175 if (!canonicalFilePath.isEmpty()) {
176 sink(canonicalFilePath);
177 sink(u":");
178 }
179 if (location.length) {
180 sinkInt(sink, location.startLine);
181 sink(u":");
182 sinkInt(sink, location.startColumn);
183 sink(u":");
184 }
185 dump(sink);
186 msg(sink);
187 if (element.length()>0) {
188 sink(u" for ");
189 element.dump(sink);
190 }
191 buf[ibuf] = 0;
192 qFatal("%s", buf);
193}
194
196{
197 return ErrorMessage(message, *this, ErrorLevel::Debug);
198}
199
201{
203}
204
206{
207 return ErrorMessage(message, *this, ErrorLevel::Info);
208}
209
211{
213}
214
216{
218}
219
221{
223}
224
226{
227 return ErrorMessage(message, *this, ErrorLevel::Error);
228}
229
231{
233}
234
235int ErrorGroups::cmp(const ErrorGroups &o1, const ErrorGroups &o2)
236{
237 auto &g1 = o1.groups;
238 auto &g2 = o2.groups;
239 if (g1.size() < g2.size())
240 return -1;
241 if (g1.size() < g2.size())
242 return 1;
243 for (int i = 0; i < g1.size(); ++i) {
244 int c = std::strcmp(g1.at(i).groupId().data(), g2.at(i).groupId().data());
245 if (c != 0)
246 return c;
247 }
248 return 0;
249}
250
252 errorId(errorId), message(msg), errorGroups(errorGroups), level(level), path(element), file(canonicalFilePath), location(location)
253{
254 if (level == Level::Fatal) // we should not end up here, it should have been handled at a higher level already
255 errorGroups.fatal(msg, element, canonicalFilePath, location);
256}
257
259 QString canonicalFilePath, QLatin1String errorId):
260 errorId(errorId), message(msg.message), errorGroups(errorGroups),
261 level(errorLevelFromQtMsgType(msg.type)), path(element), file(canonicalFilePath), location(msg.loc)
262{
263 if (level == Level::Fatal) // we should not end up here, it should have been handled at a higher level already
264 errorGroups.fatal(msg.message, element, canonicalFilePath, location);
265}
266
267
269{
270 static QBasicMutex rMutex{};
271 return &rMutex;
272}
273
274
276{
277 static ErrorGroups g = {{NewErrorGroup("ErrorMessage")}};
278 return g;
279}
280
284 {}
285
287 msg(e)
288 {}
289
291};
292
294{
296 return r;
297}
298
300{
301 return msg(QLatin1String(errorId), err);
302}
303
305{
306 bool doubleRegister = false;
307 ErrorMessage old = myErrors().debug(u"dummy");
308 {
310 auto &r = registry();
311 if (r.contains(err.errorId)) {
312 old = r[err.errorId].msg;
313 doubleRegister = true;
314 }
316 }
317 if (doubleRegister)
318 defaultErrorHandler(myErrors().warning(tr("Double registration of error %1: (%2) vs (%3)").arg(errorId, err.withErrorId(errorId).toString(), old.toString())));
319 return errorId;
320}
321
323{
325 {
327 r = registry();
328 }
329 auto it = r.cbegin();
330 auto end = r.cend();
331 while (it != end) {
332 visitor(it->msg);
333 ++it;
334 }
335}
336
338{
340 s(u"Unregistered error ");
341 s(QString(errorId)); });
342 {
344 res = registry().value(errorId,res).msg;
345 }
346 return res;
347}
348
350{
351 return load(QLatin1String(errorId));
352}
353
355{
356 this->errorId = errorId;
357 return *this;
358}
359
361{
362 this->path = path;
363 return *this;
364}
365
367{
368 file=f;
369 return *this;
370}
371
373{
374 file = f.toString();
375 return *this;
376}
377
379{
380 location = loc;
381 return *this;
382}
383
385{
386 if (path.length() == 0)
387 path = el.canonicalPath();
388 if (file.isEmpty())
389 file = el.canonicalFilePath();
390 if (location == SourceLocation()) {
391 if (const FileLocations *fLocPtr = FileLocations::fileLocationsOf(el)) {
392 location = fLocPtr->regions.value(QString(), fLocPtr->fullRegion);
393 }
394 }
395 return *this;
396}
397
399{
400 if (errorHandler)
401 errorHandler(*this);
402 else
403 defaultErrorHandler(*this);
404 return *this;
405}
406
408{
409 if (!file.isEmpty()) {
410 sink(file);
411 sink(u":");
412 }
413 if (location.length) {
414 sinkInt(sink, location.startLine);
415 sink(u":");
416 sinkInt(sink, location.startColumn);
417 sink(u": ");
418 }
420 sink(u" ");
422 if (! errorId.isEmpty()) {
423 sink(u" ");
425 }
426 sink(u": ");
427 sink(message);
428 if (path.length()>0) {
429 sink(u" for ");
430 if (!file.isEmpty() && path.length() > 3 && path.headKind() == Path::Kind::Root)
431 path.mid(3).dump(sink);
432 else
433 path.dump(sink);
434 }
435}
436
438{
439 return dumperToString([this](Sink sink){ this->dump(sink); });
440}
441
443{
444 return QCborMap({
445 {QStringLiteral(u"errorId"),errorId},
446 {QStringLiteral(u"message"), message},
447 {QStringLiteral(u"errorGroups"), errorGroups.toCbor()},
448 {QStringLiteral(u"level"), int(level)},
449 {QStringLiteral(u"path"), path.toString()},
450 {QStringLiteral(u"file"), file},
451 {QStringLiteral(u"location"), QCborMap({
452 {QStringLiteral(u"offset"),location.offset},
453 {QStringLiteral(u"length"),location.length},
454 {QStringLiteral(u"startLine"),location.startLine},
455 {QStringLiteral(u"startColumn"),location.startColumn}})}
456 });
457}
458
465{
466 dumperToQDebug([&error](Sink s){ error.dump(s); }, error.level);
467}
468
474{
475}
476
477void errorHandlerHandler(const ErrorMessage &msg, ErrorHandler *h = nullptr)
478{
479 static ErrorHandler handler = &errorToQDebug;
480 if (h) {
481 handler = *h;
482 } else {
483 handler(msg);
484 }
485}
486
492{
494}
495
501{
503}
504
506{
507 switch (msgType) {
508 case QtFatalMsg:
509 return ErrorLevel::Fatal;
510 case QtCriticalMsg:
511 return ErrorLevel::Error;
512 case QtWarningMsg:
513 return ErrorLevel::Warning;
514 case QtInfoMsg:
515 return ErrorLevel::Info;
516 case QtDebugMsg:
517 return ErrorLevel::Debug;
518 default:
519 return ErrorLevel::Error;
520 }
521}
522
523} // end namespace Dom
524} // end namespace QQmlJS
525
527
528#include "moc_qqmldomerrormessage_p.cpp"
\inmodule QtCore\reentrant
Definition qcborarray.h:20
\inmodule QtCore\reentrant
Definition qcbormap.h:21
\inmodule QtCore\reentrant
Definition qcborvalue.h:50
\inmodule QtCore
Definition qchar.h:48
constexpr char toLatin1() const noexcept
Returns the Latin-1 character equivalent to the QChar, or 0.
Definition qchar.h:457
static constexpr QChar fromLatin1(char c) noexcept
Converts the Latin-1 character c to its equivalent QChar.
Definition qchar.h:461
\inmodule QtCore
Definition qhash.h:818
constexpr bool isEmpty() const noexcept
\inmodule QtCore
Definition qmutex.h:317
\inmodule QtCore
Definition qmutex.h:285
A Sink is a function that accepts a QStringView as input.
void dumpId(Sink sink) const
QLatin1String groupId() const
void dump(Sink sink) const
Represents a set of tags grouping a set of related error messages.
ErrorMessage info(QString message) const
ErrorMessage warning(QString message) const
QVector< ErrorGroup > groups
void dumpId(Sink sink) const
static int cmp(const ErrorGroups &g1, const ErrorGroups &g2)
ErrorMessage debug(QString message) const
void fatal(Dumper msg, Path element=Path(), QStringView canonicalFilePath=u"", SourceLocation location=SourceLocation()) const
ErrorMessage errorMessage(Dumper msg, ErrorLevel level, Path element=Path(), QString canonicalFilePath=QString(), SourceLocation location=SourceLocation()) const
ErrorMessage error(QString message) const
Represents an error message connected to the dom.
ErrorMessage & withPath(const Path &)
ErrorMessage & withErrorId(QLatin1String errorId)
static void visitRegisteredMessages(function_ref< bool(ErrorMessage)> visitor)
ErrorMessage & withLocation(SourceLocation)
ErrorMessage handle(const ErrorHandler &errorHandler=nullptr)
static QLatin1String msg(const char *errorId, ErrorMessage err)
static ErrorMessage load(QLatin1String errorId)
ErrorMessage & withItem(DomItem)
ErrorMessage & withFile(QString)
ErrorMessage(QString message, ErrorGroups errorGroups, Level level=Level::Warning, Path path=Path(), QString file=QString(), SourceLocation location=SourceLocation(), QLatin1String errorId=QLatin1String(""))
Represents and maintains a mapping between elements and their location in a file.
static const FileLocations * fileLocationsOf(DomItem &)
void dump(Sink sink) const
const_iterator cbegin() const noexcept
Definition qset.h:138
\inmodule QtCore
Definition qstringview.h:76
constexpr bool isEmpty() const noexcept
Returns whether this string view is empty - that is, whether {size() == 0}.
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:1083
double e
QSet< QString >::iterator it
void errorHandlerHandler(const ErrorMessage &msg, ErrorHandler *h=nullptr)
static QHash< QLatin1String, StorableMsg > & registry()
std::function< void(const ErrorMessage &)> ErrorHandler
void silentError(const ErrorMessage &)
Error handler that ignores all errors (excluding fatal ones)
void dumpErrorLevel(Sink s, ErrorLevel level)
Dumps a string describing the given error level (ErrorLevel::Error -> Error,...)
void errorToQDebug(const ErrorMessage &error)
writes an ErrorMessage to QDebug
ErrorLevel errorLevelFromQtMsgType(QtMsgType msgType)
static ErrorGroups myErrors()
void defaultErrorHandler(const ErrorMessage &error)
Calls the default error handler (by default errorToQDebug)
void sinkInt(Sink s, T i)
void setDefaultErrorHandler(ErrorHandler h)
Sets the default error handler.
QString dumperToString(Dumper writer)
Converts a dumper to a string.
static QBasicMutex * registryMutex()
void dumperToQDebug(Dumper dumper, QDebug debug)
Combined button and popup list for selecting options.
DBusConnection const char DBusError * error
QtMsgType
Definition qlogging.h:29
@ QtCriticalMsg
Definition qlogging.h:32
@ QtInfoMsg
Definition qlogging.h:34
@ QtWarningMsg
Definition qlogging.h:31
@ QtFatalMsg
Definition qlogging.h:33
@ QtDebugMsg
Definition qlogging.h:30
#define qFatal
Definition qlogging.h:164
#define Q_LOGGING_CATEGORY(name,...)
GLint location
GLsizei GLuint * groups
GLenum GLuint GLint level
GLboolean r
[2]
GLuint GLuint end
GLfloat GLfloat f
GLenum type
GLenum GLuint GLenum GLsizei const GLchar * buf
GLuint GLsizei const GLchar * message
GLboolean GLboolean g
GLfloat GLfloat GLfloat GLfloat h
GLuint res
const GLubyte * c
GLsizei const GLchar *const * path
GLsizei GLenum GLboolean sink
GLdouble s
[6]
Definition qopenglext.h:235
#define NewErrorGroup(name)
SSL_CTX int(*) void arg)
QLatin1StringView QLatin1String
Definition qstringfwd.h:31
#define QStringLiteral(str)
#define tr(X)
QFile file
[0]
QStringView el
StorableMsg(const ErrorMessage &e)