diff --git a/src/bugzillaintegration/bugzillalib.cpp b/src/bugzillaintegration/bugzillalib.cpp --- a/src/bugzillaintegration/bugzillalib.cpp +++ b/src/bugzillaintegration/bugzillalib.cpp @@ -22,6 +22,7 @@ #include "bugzillalib.h" #include +#include #include "libbugzilla/clients/commentclient.h" #include "libbugzilla/connection.h" @@ -138,11 +139,10 @@ // the change should actually be implemented. const int nVersionParts = 3; - QString seps = QLatin1String("[._-]"); #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) - QStringList digits = version.split(QRegExp(seps), QString::SkipEmptyParts); + QStringList digits = version.split(QRegularExpression(QStringLiteral("[._-]")), QString::SkipEmptyParts); #else - QStringList digits = version.split(QRegExp(seps), Qt::SkipEmptyParts); + QStringList digits = version.split(QRegularExpression(QStringLiteral("[._-]")), Qt::SkipEmptyParts); #endif while (digits.count() < nVersionParts) { digits << QLatin1String("0"); diff --git a/src/gdbhighlighter.cpp b/src/gdbhighlighter.cpp --- a/src/gdbhighlighter.cpp +++ b/src/gdbhighlighter.cpp @@ -17,6 +17,7 @@ */ #include "gdbhighlighter.h" +#include #include #include @@ -51,7 +52,7 @@ int cur = 0; int next; int diff; - const QRegExp hexptrPattern(QStringLiteral("0x[0-9a-f]+"), Qt::CaseSensitive, QRegExp::RegExp2); + const static QRegularExpression hexptrPattern(QStringLiteral("0x[0-9a-f]+")); int lineNr = currentBlock().firstLineNumber(); while ( cur < text.length() ) { next = text.indexOf(QLatin1Char('\n'), cur); @@ -122,12 +123,12 @@ } } // highlight hexadecimal ptrs - int idx = 0; - while ((idx = hexptrPattern.indexIn(lineStr, idx)) != -1) { - if (hexptrPattern.cap() == QLatin1String("0x0")) { - setFormat(idx, hexptrPattern.matchedLength(), nullptrFormat); + QRegularExpressionMatchIterator iter = hexptrPattern.globalMatch(lineStr); + while (iter.hasNext()) { + const QRegularExpressionMatch match = iter.next(); + if (match.captured(0) == QLatin1String("0x0")) { + setFormat(match.capturedStart(0), match.capturedLength(0), nullptrFormat); } - idx += hexptrPattern.matchedLength(); } } diff --git a/src/parser/backtraceparser.cpp b/src/parser/backtraceparser.cpp --- a/src/parser/backtraceparser.cpp +++ b/src/parser/backtraceparser.cpp @@ -22,7 +22,8 @@ #include "backtraceparsercdb.h" #include "backtraceparsernull.h" #include "drkonqi_parser_debug.h" -#include + +#include #include //factory @@ -145,24 +146,25 @@ || line.rating() == BacktraceLine::MissingFunction ) return false; - //this is the base frame for all threads except the main thread - //FIXME that probably works only on linux - if ( line.functionName() == QLatin1String("start_thread") ) - return true; - - QRegExp regExp; - regExp.setPattern(QStringLiteral("(kde)?main")); //main() or kdemain() is the base for the main thread - if ( regExp.exactMatch(line.functionName()) ) + // "start_thread" is the base frame for all threads except the main thread, FIXME "start_thread" + // probably works only on linux + // main() or kdemain() is the base for the main thread + if (line.functionName() == QLatin1String("start_thread") + || line.functionName() == QLatin1String("main") + || line.functionName() == QLatin1String("kdemain")) { return true; + } //HACK for better rating. we ignore all stack frames below any function that matches //the following regular expression. The functions that match this expression are usually //"QApplicationPrivate::notify_helper", "QApplication::notify" and similar, which //are used to send any kind of event to the Qt application. All stack frames below this, //with or without debug symbols, are useless to KDE developers, so we ignore them. - regExp.setPattern(QStringLiteral("(Q|K)(Core)?Application(Private)?::notify.*")); - if ( regExp.exactMatch(line.functionName()) ) + const QRegularExpression re(QRegularExpression::anchoredPattern( + QStringLiteral("(Q|K)(Core)?Application(Private)?::notify.*"))); + if (re.match(line.functionName()).hasMatch()) { return true; + } //attempt to recognize crashes that happen after main has returned (bug 200993) if ( line.functionName() == QLatin1String("~KCleanUpGlobalStatic") || diff --git a/src/parser/backtraceparsergdb.cpp b/src/parser/backtraceparsergdb.cpp --- a/src/parser/backtraceparsergdb.cpp +++ b/src/parser/backtraceparsergdb.cpp @@ -18,8 +18,9 @@ #include "backtraceparsergdb.h" #include "backtraceparser_p.h" #include "drkonqi_parser_debug.h" -#include + #include +#include //BEGIN BacktraceLineGdb @@ -36,7 +37,6 @@ void BacktraceLineGdb::parse() { - QRegExp regExp; if (d->m_line == QLatin1Char('\n')) { d->m_type = EmptyLine; @@ -49,14 +49,20 @@ return; } - regExp.setPattern(QStringLiteral("^#([0-9]+)" //matches the stack frame number, ex. "#0" - "[\\s]+(0x[0-9a-f]+[\\s]+in[\\s]+)?" // matches " 0x0000dead in " (optionally) - "((\\(anonymous namespace\\)::)?[^\\(]+)?" //matches the function name + static QRegularExpression regExp; + // make dot "." char match new lines, to match e.g.: + // "#5 0x00007f50e99f776f in QWidget::testAttribute_helper (this=0x6e6440,\n attribute=Qt::WA_WState_Created) at kernel/qwidget.cpp:9081\n" + // gdb breaks long stack frame lines into multiple ones for readability + regExp.setPatternOptions(QRegularExpression::DotMatchesEverythingOption); + regExp.setPattern(QStringLiteral( + "^#([0-9]+)" //matches the stack frame number, ex. "#0" + "[\\s]+(?:0x[0-9a-f]+[\\s]+in[\\s]+)?" // matches " 0x0000dead in " (optionally) + "((?:\\(anonymous namespace\\)::)?[^\\(]+)?" //matches the function name //(anything except left parenthesis, which is the start of the arguments section) //and optionally the prefix "(anonymous namespace)::" - "(\\(.*\\))?" //matches the function arguments + "(?:\\(.*\\))?" //matches the function arguments //(when the app doesn't have debugging symbols) - "[\\s]+(const[\\s]+)?" //matches a traling const, if it exists + "[\\s]+(?:const[\\s]+)?" //matches a traling const, if it exists "\\(.*\\)" //matches the arguments of the function with their values //(when the app has debugging symbols) "([\\s]+" //beginning of optional file information @@ -66,22 +72,23 @@ //the )? at the end closes the parenthesis before [\\s]+(from|at) and //notes that the whole expression from there is optional. - if (regExp.exactMatch(d->m_line)) { + QRegularExpressionMatch match = regExp.match(d->m_line); + if (match.hasMatch()) { d->m_type = StackFrame; - d->m_stackFrameNumber = regExp.cap(1).toInt(); - d->m_functionName = regExp.cap(3).trimmed(); + d->m_stackFrameNumber = match.captured(1).toInt(); + d->m_functionName = match.captured(2).trimmed(); - if (!regExp.cap(7).isEmpty()) { //we have file information (stuff after from|at) - bool file = regExp.cap(8) == QLatin1String("at"); //'at' means we have a source file (likely) + if (!match.captured(3).isEmpty()) { //we have file information (stuff after from|at) + bool file = match.captured(4) == QLatin1String("at"); //'at' means we have a source file (likely) // Gdb isn't entirely consistent here, when it uses 'from' it always refers to a library, but // sometimes the stack can resolve to a library even when it uses the 'at' key word. // This specifically seems to happen when a frame has no function name. - const QString path = regExp.cap(9); + const QString path = match.captured(5); file = file && !QFileInfo(path).completeSuffix().contains(QLatin1String(".so")); if (file) { - d->m_file = regExp.cap(9); + d->m_file = match.captured(5); } else { //'from' means we have a library - d->m_library = regExp.cap(9); + d->m_library = match.captured(5); } } @@ -94,21 +101,21 @@ ".*\\[New .*|" "0x[0-9a-f]+.*|" "Current language:.*")); - if (regExp.exactMatch(d->m_line)) { + if (regExp.match(d->m_line).hasMatch()) { qCDebug(DRKONQI_PARSER_LOG) << "garbage detected:" << d->m_line; d->m_type = Crap; return; } regExp.setPattern(QStringLiteral("Thread [0-9]+\\s+\\(Thread [0-9a-fx]+\\s+\\(.*\\)\\):\n")); - if (regExp.exactMatch(d->m_line)) { + if (regExp.match(d->m_line).hasMatch()) { qCDebug(DRKONQI_PARSER_LOG) << "thread start detected:" << d->m_line; d->m_type = ThreadStart; return; } regExp.setPattern(QStringLiteral("\\[Current thread is [0-9]+ \\(.*\\)\\]\n")); - if (regExp.exactMatch(d->m_line)) { + if (regExp.match(d->m_line).hasMatch()) { qCDebug(DRKONQI_PARSER_LOG) << "thread indicator detected:" << d->m_line; d->m_type = ThreadIndicator; return; diff --git a/src/parser/backtraceparserkdbgwin.cpp b/src/parser/backtraceparserkdbgwin.cpp --- a/src/parser/backtraceparserkdbgwin.cpp +++ b/src/parser/backtraceparserkdbgwin.cpp @@ -19,6 +19,8 @@ #include "backtraceparser_p.h" #include "drkonqi_parser_debug.h" +#include + //BEGIN BacktraceLineKdbgwin class BacktraceLineKdbgwin : public BacktraceLine @@ -54,17 +56,18 @@ return; } - QRegExp regExp; - regExp.setPattern(QStringLiteral("([^!]+)!" //match the module name, followed by ! - "([^\\(]+)\\(\\) " //match the function name, followed by () - "\\[([^@]+)@ [\\-\\d]+\\] " // [filename @ line] - "at 0x.*")); //at 0xdeadbeef + static const QRegularExpression re(QRegularExpression::anchoredPattern(QStringLiteral( + "([^!]+)!" //match the module name, followed by ! + "([^\\(]+)\\(\\) " //match the function name, followed by () + "\\[([^@]+)@ [\\-\\d]+\\] " // [filename @ line] + "at 0x.*"))); //at 0xdeadbeef - if (regExp.exactMatch(d->m_line)) { + const QRegularExpressionMatch match = re.match(d->m_line); + if (match.hasMatch()) { d->m_type = StackFrame; - d->m_library = regExp.cap(1); - d->m_functionName = regExp.cap(2); - d->m_file = regExp.cap(3).trimmed(); + d->m_library = match.captured(1); + d->m_functionName = match.captured(2); + d->m_file = match.captured(3).trimmed(); qCDebug(DRKONQI_PARSER_LOG) << d->m_functionName << d->m_file << d->m_library; return;