QRegularExpression: print the pattern when warning

Just as a minor debugging helper: when warning that an invalid
regular expression object is being used to match, also print
the used regular expression pattern.

Change-Id: I0f99bcf4ca87ec67d04ed91d9dc315814f56d392
Fixes: QTBUG-76670
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
bb10
Giuseppe D'Angelo 2019-07-01 20:05:36 +02:00
parent b727f2190f
commit 8123a69e6e
4 changed files with 73 additions and 22 deletions

View File

@ -823,6 +823,24 @@ struct QRegularExpressionMatchIteratorPrivate : QSharedData
const QRegularExpression::MatchOptions matchOptions;
};
/*!
\internal
Used to centralize the warning about using an invalid QRegularExpression.
In case the pattern is an illegal UTF-16 string, we can't pass print it
(pass it to qUtf16Printable, etc.), so we need to check for that.
*/
Q_DECL_COLD_FUNCTION
void qtWarnAboutInvalidRegularExpression(const QString &pattern, const char *where)
{
if (pattern.isValidUtf16()) {
qWarning("%s(): called on an invalid QRegularExpression object "
"(pattern is '%ls')", where, qUtf16Printable(pattern));
} else {
qWarning("%s(): called on an invalid QRegularExpression object", where);
}
}
/*!
\internal
*/
@ -1131,7 +1149,7 @@ void QRegularExpressionPrivate::doMatch(QRegularExpressionMatchPrivate *priv,
return;
if (Q_UNLIKELY(!compiledPattern)) {
qWarning("QRegularExpressionPrivate::doMatch(): called on an invalid QRegularExpression object");
qtWarnAboutInvalidRegularExpression(pattern, "QRegularExpressionPrivate::doMatch");
return;
}

View File

@ -1641,6 +1641,10 @@ static int qArgDigitValue(QChar ch) noexcept
return -1;
}
#if QT_CONFIG(regularexpression)
Q_DECL_COLD_FUNCTION
void qtWarnAboutInvalidRegularExpression(const QString &pattern, const char *where);
#endif
/*!
\macro QT_RESTRICTED_CAST_FROM_ASCII
@ -4347,7 +4351,7 @@ Q_DECLARE_TYPEINFO(QStringCapture, Q_PRIMITIVE_TYPE);
QString &QString::replace(const QRegularExpression &re, const QString &after)
{
if (!re.isValid()) {
qWarning("QString::replace: invalid QRegularExpression object");
qtWarnAboutInvalidRegularExpression(re.pattern(), "QString::replace");
return *this;
}
@ -4873,7 +4877,7 @@ static QString extractSections(const QList<qt_section_chunk> &sections, qsizetyp
QString QString::section(const QRegularExpression &re, qsizetype start, qsizetype end, SectionFlags flags) const
{
if (!re.isValid()) {
qWarning("QString::section: invalid QRegularExpression object");
qtWarnAboutInvalidRegularExpression(re.pattern(), "QString::section");
return QString();
}
@ -7682,7 +7686,7 @@ static ResultList splitString(const String &source, const QRegularExpression &re
{
ResultList list;
if (!re.isValid()) {
qWarning("QString::split: invalid QRegularExpression object");
qtWarnAboutInvalidRegularExpression(re.pattern(), "QString::split");
return list;
}
@ -10584,7 +10588,7 @@ qsizetype QtPrivate::lastIndexOf(QLatin1String haystack, qsizetype from, QLatin1
qsizetype QtPrivate::indexOf(QStringView haystack, const QRegularExpression &re, qsizetype from, QRegularExpressionMatch *rmatch)
{
if (!re.isValid()) {
qWarning("QString(View)::indexOf: invalid QRegularExpression object");
qtWarnAboutInvalidRegularExpression(re.pattern(), "QString(View)::indexOf");
return -1;
}
@ -10602,7 +10606,7 @@ qsizetype QtPrivate::indexOf(QStringView haystack, const QRegularExpression &re,
qsizetype QtPrivate::lastIndexOf(QStringView haystack, const QRegularExpression &re, qsizetype from, QRegularExpressionMatch *rmatch)
{
if (!re.isValid()) {
qWarning("QString(View)::lastIndexOf: invalid QRegularExpression object");
qtWarnAboutInvalidRegularExpression(re.pattern(), "QString(View)::lastIndexOf");
return -1;
}
@ -10627,7 +10631,7 @@ qsizetype QtPrivate::lastIndexOf(QStringView haystack, const QRegularExpression
bool QtPrivate::contains(QStringView haystack, const QRegularExpression &re, QRegularExpressionMatch *rmatch)
{
if (!re.isValid()) {
qWarning("QString(View)::contains: invalid QRegularExpression object");
qtWarnAboutInvalidRegularExpression(re.pattern(), "QString(View)::contains");
return false;
}
QRegularExpressionMatch m = re.match(haystack);
@ -10640,7 +10644,7 @@ bool QtPrivate::contains(QStringView haystack, const QRegularExpression &re, QRe
qsizetype QtPrivate::count(QStringView haystack, const QRegularExpression &re)
{
if (!re.isValid()) {
qWarning("QString(View)::count: invalid QRegularExpression object");
qtWarnAboutInvalidRegularExpression(re.pattern(), "QString(View)::count");
return 0;
}
qsizetype count = 0;

View File

@ -712,18 +712,23 @@ void tst_QRegularExpression::validity_data()
void tst_QRegularExpression::validity()
{
static const QRegularExpression ignoreMessagePattern(
"^" + QRegularExpression::escape("QRegularExpressionPrivate::doMatch(): "
"called on an invalid QRegularExpression object")
);
QFETCH(QString, pattern);
QFETCH(bool, validity);
QRegularExpression re(pattern);
QCOMPARE(re.isValid(), validity);
if (!validity)
QTest::ignoreMessage(QtWarningMsg, "QRegularExpressionPrivate::doMatch(): called on an invalid QRegularExpression object");
QTest::ignoreMessage(QtWarningMsg, ignoreMessagePattern);
QRegularExpressionMatch match = re.match("a pattern");
QCOMPARE(match.isValid(), validity);
consistencyCheck(match);
if (!validity)
QTest::ignoreMessage(QtWarningMsg, "QRegularExpressionPrivate::doMatch(): called on an invalid QRegularExpression object");
QTest::ignoreMessage(QtWarningMsg, ignoreMessagePattern);
QRegularExpressionMatchIterator iterator = re.globalMatch("a pattern");
QCOMPARE(iterator.isValid(), validity);
}

View File

@ -1725,14 +1725,18 @@ void tst_QString::indexOf2()
#if QT_CONFIG(regularexpression)
void tst_QString::indexOfInvalidRegex()
{
QTest::ignoreMessage(QtWarningMsg, "QString(View)::indexOf: invalid QRegularExpression object");
static const QRegularExpression ignoreMessagePattern(
"^QString\\(View\\)::indexOf\\(\\): called on an invalid QRegularExpression object"
);
QTest::ignoreMessage(QtWarningMsg, ignoreMessagePattern);
QCOMPARE(QString("invalid regex\\").indexOf(QRegularExpression("invalid regex\\")), -1);
QTest::ignoreMessage(QtWarningMsg, "QString(View)::indexOf: invalid QRegularExpression object");
QTest::ignoreMessage(QtWarningMsg, ignoreMessagePattern);
QCOMPARE(QString("invalid regex\\").indexOf(QRegularExpression("invalid regex\\"), -1, nullptr), -1);
QRegularExpressionMatch match;
QVERIFY(!match.hasMatch());
QTest::ignoreMessage(QtWarningMsg, "QString(View)::indexOf: invalid QRegularExpression object");
QTest::ignoreMessage(QtWarningMsg, ignoreMessagePattern);
QCOMPARE(QString("invalid regex\\").indexOf(QRegularExpression("invalid regex\\"), -1, &match), -1);
QVERIFY(!match.hasMatch());
}
@ -1851,14 +1855,18 @@ void tst_QString::lastIndexOf()
#if QT_CONFIG(regularexpression)
void tst_QString::lastIndexOfInvalidRegex()
{
QTest::ignoreMessage(QtWarningMsg, "QString(View)::lastIndexOf: invalid QRegularExpression object");
static const QRegularExpression ignoreMessagePattern(
"^QString\\(View\\)::lastIndexOf\\(\\): called on an invalid QRegularExpression object"
);
QTest::ignoreMessage(QtWarningMsg, ignoreMessagePattern);
QCOMPARE(QString("invalid regex\\").lastIndexOf(QRegularExpression("invalid regex\\"), 0), -1);
QTest::ignoreMessage(QtWarningMsg, "QString(View)::lastIndexOf: invalid QRegularExpression object");
QTest::ignoreMessage(QtWarningMsg, ignoreMessagePattern);
QCOMPARE(QString("invalid regex\\").lastIndexOf(QRegularExpression("invalid regex\\"), -1, nullptr), -1);
QRegularExpressionMatch match;
QVERIFY(!match.hasMatch());
QTest::ignoreMessage(QtWarningMsg, "QString(View)::lastIndexOf: invalid QRegularExpression object");
QTest::ignoreMessage(QtWarningMsg, ignoreMessagePattern);
QCOMPARE(QString("invalid regex\\").lastIndexOf(QRegularExpression("invalid regex\\"), -1, &match), -1);
QVERIFY(!match.hasMatch());
}
@ -1866,6 +1874,10 @@ void tst_QString::lastIndexOfInvalidRegex()
void tst_QString::count()
{
static const QRegularExpression ignoreMessagePattern(
"^QString\\(View\\)::count\\(\\): called on an invalid QRegularExpression object"
);
QString a;
a="ABCDEFGHIEfGEFG"; // 15 chars
QCOMPARE(a.count('A'),1);
@ -1881,7 +1893,7 @@ void tst_QString::count()
QCOMPARE(a.count(QRegularExpression("")), 16);
QCOMPARE(a.count(QRegularExpression("[FG][HI]")), 1);
QCOMPARE(a.count(QRegularExpression("[G][HE]")), 2);
QTest::ignoreMessage(QtWarningMsg, "QString(View)::count: invalid QRegularExpression object");
QTest::ignoreMessage(QtWarningMsg, ignoreMessagePattern);
QCOMPARE(a.count(QRegularExpression("invalid regex\\")), 0);
#endif
@ -1900,7 +1912,7 @@ void tst_QString::count()
#if QT_CONFIG(regularexpression)
QCOMPARE(nullStr.count(QRegularExpression("")), 1);
QCOMPARE(nullStr.count(QRegularExpression("[FG][HI]")), 0);
QTest::ignoreMessage(QtWarningMsg, "QString(View)::count: invalid QRegularExpression object");
QTest::ignoreMessage(QtWarningMsg, ignoreMessagePattern);
QCOMPARE(nullStr.count(QRegularExpression("invalid regex\\")), 0);
#endif
@ -1914,13 +1926,17 @@ void tst_QString::count()
#if QT_CONFIG(regularexpression)
QCOMPARE(emptyStr.count(QRegularExpression("")), 1);
QCOMPARE(emptyStr.count(QRegularExpression("[FG][HI]")), 0);
QTest::ignoreMessage(QtWarningMsg, "QString(View)::count: invalid QRegularExpression object");
QTest::ignoreMessage(QtWarningMsg, ignoreMessagePattern);
QCOMPARE(emptyStr.count(QRegularExpression("invalid regex\\")), 0);
#endif
}
void tst_QString::contains()
{
static const QRegularExpression ignoreMessagePattern(
"^QString\\(View\\)::contains\\(\\): called on an invalid QRegularExpression object"
);
QString a;
a="ABCDEFGHIEfGEFG"; // 15 chars
QVERIFY(a.contains('A'));
@ -1987,7 +2003,7 @@ void tst_QString::contains()
QVERIFY(!a.contains(QRegularExpression("ZZZ"), 0));
}
QTest::ignoreMessage(QtWarningMsg, "QString(View)::contains: invalid QRegularExpression object");
QTest::ignoreMessage(QtWarningMsg, ignoreMessagePattern);
QVERIFY(!a.contains(QRegularExpression("invalid regex\\")));
#endif
@ -3226,13 +3242,17 @@ void tst_QString::replace_string_extra()
#if QT_CONFIG(regularexpression)
void tst_QString::replace_regexp()
{
static const QRegularExpression ignoreMessagePattern(
"^QString::replace\\(\\): called on an invalid QRegularExpression object"
);
QFETCH( QString, string );
QFETCH( QString, regexp );
QFETCH( QString, after );
QRegularExpression regularExpression(regexp);
if (!regularExpression.isValid())
QTest::ignoreMessage(QtWarningMsg, "QString::replace: invalid QRegularExpression object");
QTest::ignoreMessage(QtWarningMsg, ignoreMessagePattern);
string.replace(regularExpression, after);
QTEST(string, "result");
}
@ -3347,6 +3367,10 @@ void tst_QString::remove_regexp_data()
void tst_QString::remove_regexp()
{
static const QRegularExpression ignoreMessagePattern(
"^QString::replace\\(\\): called on an invalid QRegularExpression object"
);
QFETCH( QString, string );
QFETCH( QString, regexp );
QTEST(QString(), "after"); // non-empty replacement text tests should go in replace_regexp_data()
@ -3354,7 +3378,7 @@ void tst_QString::remove_regexp()
QRegularExpression regularExpression(regexp);
// remove() delegates to replace(), which produces this warning:
if (!regularExpression.isValid())
QTest::ignoreMessage(QtWarningMsg, "QString::replace: invalid QRegularExpression object");
QTest::ignoreMessage(QtWarningMsg, ignoreMessagePattern);
string.remove(regularExpression);
QTEST(string, "result");
}