Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
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
40void ErrorGroup::dump(const Sink &sink) const
41{
42 sink(u"[");
43 sink(groupName());
44 sink(u"]");
45}
46
47void ErrorGroup::dumpId(const Sink &sink) const
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
73void ErrorGroups::dump(const Sink &sink) const
74{
75 for (int i = 0; i < groups.size(); ++i)
76 groups.at(i).dump(sink);
77}
78
79void ErrorGroups::dumpId(const Sink &sink) const
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 const Dumper &msg, ErrorLevel level, const Path &element, const QString &canonicalFilePath,
144{
146 fatal(msg, element, canonicalFilePath, location);
147 return ErrorMessage(dumperToString(msg), *this, level, element, canonicalFilePath, location);
148}
149
150ErrorMessage ErrorGroups::errorMessage(const DiagnosticMessage &msg, const Path &element, const QString &canonicalFilePath) const
151{
152 ErrorMessage res(*this, msg, element, canonicalFilePath);
153 if (res.location == SourceLocation()
154 && (res.location.startLine != 0 || res.location.startColumn != 0)) {
155 res.location.offset = -1;
156 res.location.length = 1;
157 }
158 return res;
159}
160
162 const Dumper &msg, const Path &element, QStringView canonicalFilePath,
164{
165 enum { FatalMsgMaxLen = 1023 };
166 char buf[FatalMsgMaxLen+1];
167 int ibuf = 0;
168 auto sink = [&ibuf, &buf](QStringView s) {
169 int is = 0;
170 while (ibuf < FatalMsgMaxLen && is < s.size()) {
171 QChar c = s.at(is);
172 if (c == QChar::fromLatin1('\n') || c == QChar::fromLatin1('\r') || (c >= QChar::fromLatin1(' ') && c <= QChar::fromLatin1('~')))
173 buf[ibuf++] = c.toLatin1();
174 else
175 buf[ibuf++] = '~';
176 ++is;
177 }
178 };
179 if (!canonicalFilePath.isEmpty()) {
180 sink(canonicalFilePath);
181 sink(u":");
182 }
183 if (location.length) {
184 sinkInt(sink, location.startLine);
185 sink(u":");
186 sinkInt(sink, location.startColumn);
187 sink(u":");
188 }
189 dump(sink);
190 msg(sink);
191 if (element.length()>0) {
192 sink(u" for ");
193 element.dump(sink);
194 }
195 buf[ibuf] = 0;
196 qFatal("%s", buf);
197}
198
203
208
213
218
223
228
233
238
239int ErrorGroups::cmp(const ErrorGroups &o1, const ErrorGroups &o2)
240{
241 auto &g1 = o1.groups;
242 auto &g2 = o2.groups;
243 if (g1.size() < g2.size())
244 return -1;
245 if (g1.size() < g2.size())
246 return 1;
247 for (int i = 0; i < g1.size(); ++i) {
248 int c = std::strcmp(g1.at(i).groupId().data(), g2.at(i).groupId().data());
249 if (c != 0)
250 return c;
251 }
252 return 0;
253}
254
256 const QString &msg, const ErrorGroups &errorGroups, Level level, const Path &element,
257 const QString &canonicalFilePath, SourceLocation location, QLatin1String errorId)
258 : errorId(errorId)
259 , message(msg)
260 , errorGroups(errorGroups)
261 , level(level)
262 , path(element)
263 , file(canonicalFilePath)
265{
266 if (level == Level::Fatal) // we should not end up here, it should have been handled at a higher level already
267 errorGroups.fatal(msg, element, canonicalFilePath, location);
268}
269
271 const ErrorGroups &errorGroups, const DiagnosticMessage &msg, const Path &element,
272 const QString &canonicalFilePath, QLatin1String errorId)
273 : errorId(errorId)
274 , message(msg.message)
275 , errorGroups(errorGroups)
277 , path(element)
278 , file(canonicalFilePath)
279 , location(msg.loc)
280{
281 if (level == Level::Fatal) // we should not end up here, it should have been handled at a higher level already
282 errorGroups.fatal(msg.message, element, canonicalFilePath, location);
283}
284
285
287{
288 static QBasicMutex rMutex{};
289 return &rMutex;
290}
291
292
294{
295 static ErrorGroups g = {{NewErrorGroup("ErrorMessage")}};
296 return g;
297}
298
302 {}
303
305 msg(e)
306 {}
307
309 msg(std::move(e))
310 {}
311
313};
314
315static QHash<QLatin1String, StorableMsg> &registry()
316{
317 static QHash<QLatin1String, StorableMsg> r;
318 return r;
319}
320
322{
323 return msg(QLatin1String(errorId), std::move(err));
324}
325
327{
328 bool doubleRegister = false;
329 ErrorMessage old = myErrors().debug(u"dummy");
330 {
332 auto &r = registry();
333 if (r.contains(err.errorId)) {
334 old = r[err.errorId].msg;
335 doubleRegister = true;
336 }
337 r[errorId] = StorableMsg{std::move(err.withErrorId(errorId))};
338 }
339 if (doubleRegister)
340 defaultErrorHandler(myErrors().warning(tr("Double registration of error %1: (%2) vs (%3)").arg(errorId, err.withErrorId(errorId).toString(), old.toString())));
341 return errorId;
342}
343
345{
346 QHash<QLatin1String, StorableMsg> r;
347 {
349 r = registry();
350 }
351 auto it = r.cbegin();
352 auto end = r.cend();
353 while (it != end) {
354 visitor(it->msg);
355 ++it;
356 }
357}
358
360{
361 ErrorMessage res = myErrors().error([errorId](const Sink &s){
362 s(u"Unregistered error ");
363 s(QString(errorId)); });
364 {
366 res = registry().value(errorId,res).msg;
367 }
368 return res;
369}
370
372{
373 return load(QLatin1String(errorId));
374}
375
377{
378 this->errorId = errorId;
379 return *this;
380}
381
383{
384 this->path = path;
385 return *this;
386}
387
389{
390 file=f;
391 return *this;
392}
393
395{
396 file = f.toString();
397 return *this;
398}
399
401{
402 location = loc;
403 return *this;
404}
405
407{
408 if (path.length() == 0)
409 path = el.canonicalPath();
410 if (file.isEmpty())
411 file = el.canonicalFilePath();
412 if (location == SourceLocation()) {
413 if (const FileLocations::Tree tree = FileLocations::treeOf(el)) {
415 }
416 }
417 return *this;
418}
419
421{
422 if (errorHandler)
423 errorHandler(*this);
424 else
425 defaultErrorHandler(*this);
426 return *this;
427}
428
429void ErrorMessage::dump(const Sink &sink) const
430{
431 if (!file.isEmpty()) {
432 sink(file);
433 sink(u":");
434 }
435 if (location.length) {
436 sinkInt(sink, location.startLine);
437 sink(u":");
438 sinkInt(sink, location.startColumn);
439 sink(u": ");
440 }
442 sink(u" ");
444 if (! errorId.isEmpty()) {
445 sink(u" ");
447 }
448 sink(u": ");
449 sink(message);
450 if (path.length()>0) {
451 sink(u" for ");
452 if (!file.isEmpty() && path.length() > 3 && path.headKind() == Path::Kind::Root)
453 path.mid(3).dump(sink);
454 else
455 path.dump(sink);
456 }
457}
458
460{
461 return dumperToString([this](const Sink &sink){ this->dump(sink); });
462}
463
465{
466 return QCborMap({
467 {QStringLiteral(u"errorId"),errorId},
468 {QStringLiteral(u"message"), message},
469 {QStringLiteral(u"errorGroups"), errorGroups.toCbor()},
470 {QStringLiteral(u"level"), int(level)},
471 {QStringLiteral(u"path"), path.toString()},
472 {QStringLiteral(u"file"), file},
473 {QStringLiteral(u"location"), QCborMap({
474 {QStringLiteral(u"offset"),location.offset},
475 {QStringLiteral(u"length"),location.length},
476 {QStringLiteral(u"startLine"),location.startLine},
477 {QStringLiteral(u"startColumn"),location.startColumn}})}
478 });
479}
480
487{
488 dumperToQDebug([&error](const Sink &s){ error.dump(s); }, error.level);
489}
490
496{
497}
498
499void errorHandlerHandler(const ErrorMessage &msg, const ErrorHandler *h = nullptr)
500{
501 static ErrorHandler handler = &errorToQDebug;
502 if (h) {
503 handler = *h;
504 } else {
505 handler(msg);
506 }
507}
508
517
526
528{
529 switch (msgType) {
530 case QtFatalMsg:
531 return ErrorLevel::Fatal;
532 case QtCriticalMsg:
533 return ErrorLevel::Error;
534 case QtWarningMsg:
535 return ErrorLevel::Warning;
536 case QtInfoMsg:
537 return ErrorLevel::Info;
538 case QtDebugMsg:
539 return ErrorLevel::Debug;
540 default:
541 return ErrorLevel::Error;
542 }
543}
544
545} // end namespace Dom
546} // end namespace QQmlJS
547
549
550#include "moc_qqmldomerrormessage_p.cpp"
\inmodule QtCore\reentrant
Definition qcborarray.h:20
void append(const QCborValue &value)
Definition qcborarray.h:244
\inmodule QtCore\reentrant
Definition qcbormap.h:21
\inmodule QtCore\reentrant
Definition qcborvalue.h:47
\inmodule QtCore
constexpr bool isEmpty() const noexcept
QString toString() const
Definition qstring.h:1108
\inmodule QtCore
Definition qmutex.h:313
\inmodule QtCore
Definition qmutex.h:281
A Sink is a function that accepts a QStringView as input.
QLatin1String groupId() const
void dumpId(const Sink &sink) const
void dump(const Sink &sink) const
Represents a set of tags grouping a set of related error messages.
ErrorMessage error(const QString &message) const
void dump(const Sink &sink) const
static int cmp(const ErrorGroups &g1, const ErrorGroups &g2)
ErrorMessage debug(const QString &message) const
void dumpId(const Sink &sink) const
ErrorMessage info(const QString &message) const
ErrorMessage warning(const QString &message) const
ErrorMessage errorMessage(const Dumper &msg, ErrorLevel level, const Path &element=Path(), const QString &canonicalFilePath=QString(), SourceLocation location=SourceLocation()) const
void fatal(const Dumper &msg, const Path &element=Path(), QStringView canonicalFilePath=u"", SourceLocation location=SourceLocation()) const
Represents an error message connected to the dom.
ErrorMessage & withPath(const Path &)
ErrorMessage & withErrorId(QLatin1String errorId)
ErrorMessage & withLocation(SourceLocation)
ErrorMessage handle(const ErrorHandler &errorHandler=nullptr)
static QLatin1String msg(const char *errorId, ErrorMessage &&err)
ErrorMessage & withFile(const QString &)
ErrorMessage & withItem(const DomItem &)
ErrorMessage(const QString &message, const ErrorGroups &errorGroups, Level level=Level::Warning, const Path &path=Path(), const QString &file=QString(), SourceLocation location=SourceLocation(), QLatin1String errorId=QLatin1String(""))
void dump(const Sink &s) const
static ErrorMessage load(QLatin1String errorId)
static void visitRegisteredMessages(function_ref< bool(const ErrorMessage &)> visitor)
static QQmlJS::SourceLocation region(const Tree &fLoc, FileLocationRegion region)
std::shared_ptr< AttachedInfoT< FileLocations > > Tree
static FileLocations::Tree treeOf(const DomItem &)
void dump(const Sink &sink) const
const_iterator cbegin() const noexcept
Definition qset.h:138
\inmodule QtCore
Definition qstringview.h:78
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:129
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:192
QSet< QString >::iterator it
void dumpErrorLevel(const Sink &s, ErrorLevel level)
Dumps a string describing the given error level (ErrorLevel::Error -> Error,...)
static QHash< QLatin1String, StorableMsg > & registry()
void sinkInt(const Sink &s, T i)
void silentError(const ErrorMessage &)
Error handler that ignores all errors (excluding fatal ones)
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 setDefaultErrorHandler(const ErrorHandler &h)
Sets the default error handler.
void errorHandlerHandler(const ErrorMessage &msg, const ErrorHandler *h=nullptr)
QString dumperToString(const Dumper &writer)
Converts a dumper to a string.
void dumperToQDebug(const Dumper &dumper, QDebug debug)
std::function< void(const ErrorMessage &)> ErrorHandler
static QBasicMutex * registryMutex()
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:168
#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
GLdouble s
[6]
Definition qopenglext.h:235
GLuint res
const GLubyte * c
GLsizei const GLchar *const * path
GLsizei GLenum GLboolean sink
#define NewErrorGroup(name)
QDebug warning(QAnyStringView fileName, int lineNumber)
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)