Commit 8db6b62d authored by Milian Wolff's avatar Milian Wolff
Browse files

Optimize: prevent double isOperator lookups in findClose

Skip ahead by one char and only look at the remaining text, instead
of handling the current char twice, once in findCommaOrEnd and then
directly again in findClose when called from there.

Doing so requires we properly handle strings in a different way,
which is easy to do. While at it, we also fix this for chars,
which did not get handled correctly in findCommaOrEnd before.

This was suggested by Igor Kushnir during code review, many thanks!
parent 6fa81bed
......@@ -95,6 +95,19 @@ bool isOperator(const QString& str, int pos)
return QStringView(str).mid(0, pos + 1).endsWith(QLatin1String("operator"));
}
int skipStringOrCharLiteral(const QString& str, int pos)
{
const auto quote = str[pos];
Q_ASSERT(quote == QLatin1Char('\'') || quote == QLatin1Char('"'));
const auto end = str.size();
pos++;
while (pos < end && (str[pos] != quote || str[pos - 1] == QLatin1Char('\\'))) {
pos++;
}
return pos;
}
}
namespace KDevelop {
......@@ -130,11 +143,13 @@ bool parenFits(QChar c1, QChar c2)
int findClose(const QString& str, int pos)
{
int depth = 0;
int depth = 1;
QVarLengthArray<QChar, 16> st;
st.append(str[pos]);
QChar last = QLatin1Char(' ');
for (int a = pos; a < str.length(); a++) {
for (int a = pos + 1; a < str.length(); a++) {
switch (str[a].unicode()) {
case '<':
if (isOperator(str, a))
......@@ -161,21 +176,10 @@ int findClose(const QString& str, int pos)
}
break;
case '"':
last = str[a];
a++;
while (a < str.length() && (str[a] != QLatin1Char('"') || last == QLatin1Char('\\'))) {
last = str[a];
a++;
}
continue;
case '\'':
last = str[a];
a++;
while (a < str.length() && (str[a] != QLatin1Char('\'') || last == QLatin1Char('\\'))) {
last = str[a];
a++;
}
continue;
a = skipStringOrCharLiteral(str, a);
last = str[a - 1];
break;
}
last = str[a];
......@@ -192,11 +196,14 @@ int findCommaOrEnd(const QString& str, int pos, QChar validEnd)
{
for (int a = pos; a < str.length(); a++) {
switch (str[a].unicode()) {
case '"':
case '\'':
a = skipStringOrCharLiteral(str, a);
break;
case '<':
if (isOperator(str, a))
break;
[[fallthrough]];
case '"':
case '(':
case '[':
case '{':
......
......@@ -155,6 +155,8 @@ void TestStringHelpers::testParamIterator_data()
{"_Tp", "foo<bar>", "__void_t<decltype(std::declval<_Tp>().operator<=>(std::declval<_Up>()))>"});
addTest("__not_overloaded2<_Tp, foo<bar>, __void_t<decltype(std::declval<_Tp>().operator->(std::declval<_Up>()))>>",
{"_Tp", "foo<bar>", "__void_t<decltype(std::declval<_Tp>().operator->(std::declval<_Up>()))>"});
addTest("A<\">\\\">\">", {"\">\\\">\""});
addTest("A<'>'>", {"'>'"});
}
void TestStringHelpers::testParamIterator()
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment