diff options
Diffstat (limited to 'src/libs/3rdparty/syntax-highlighting/src/lib/rule.cpp')
-rw-r--r-- | src/libs/3rdparty/syntax-highlighting/src/lib/rule.cpp | 105 |
1 files changed, 50 insertions, 55 deletions
diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/rule.cpp b/src/libs/3rdparty/syntax-highlighting/src/lib/rule.cpp index 1d02bd6ac34..186ed16120d 100644 --- a/src/libs/3rdparty/syntax-highlighting/src/lib/rule.cpp +++ b/src/libs/3rdparty/syntax-highlighting/src/lib/rule.cpp @@ -1,20 +1,19 @@ /* SPDX-FileCopyrightText: 2016 Volker Krause <vkrause@kde.org> SPDX-FileCopyrightText: 2018 Christoph Cullmann <cullmann@kde.org> - SPDX-FileCopyrightText: 2020 Jonathan Poelen <jonathan.poelen@gmail.com> + SPDX-FileCopyrightText: 2020 Jonathan Poelen <jonathan.poelen+kde@gmail.com> SPDX-License-Identifier: MIT */ #include "context_p.h" #include "definition_p.h" +#include "dynamicregexpcache_p.h" #include "ksyntaxhighlighting_logging.h" #include "rule_p.h" #include "worddelimiters_p.h" #include "xml_p.h" -#include <QString> - using namespace KSyntaxHighlighting; // QChar::isDigit() match any digit in unicode (romain numeral, etc) @@ -90,8 +89,8 @@ static int matchEscapedChar(QStringView text, int offset) static QString replaceCaptures(const QString &pattern, const QStringList &captures, bool quote) { auto result = pattern; - for (int i = captures.size() - 1; i >= 1; --i) { - result.replace(QLatin1Char('%') + QString::number(i), quote ? QRegularExpression::escape(captures.at(i)) : captures.at(i)); + for (int i = captures.size(); i >= 1; --i) { + result.replace(QLatin1Char('%') + QString::number(i), quote ? QRegularExpression::escape(captures.at(i - 1)) : captures.at(i - 1)); } return result; } @@ -233,7 +232,7 @@ AnyChar::AnyChar(const HighlightingContextData::Rule::AnyChar &data) { } -MatchResult AnyChar::doMatch(QStringView text, int offset, const QStringList &) const +MatchResult AnyChar::doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const { if (m_chars.contains(text.at(offset))) { return offset + 1; @@ -243,15 +242,15 @@ MatchResult AnyChar::doMatch(QStringView text, int offset, const QStringList &) DetectChar::DetectChar(const HighlightingContextData::Rule::DetectChar &data) : m_char(data.char1) - , m_captureIndex(data.dynamic ? data.char1.digitValue() : 0) + , m_captureIndex((data.dynamic ? data.char1.digitValue() : 0) - 1) { m_dynamic = data.dynamic; } -MatchResult DetectChar::doMatch(QStringView text, int offset, const QStringList &captures) const +MatchResult DetectChar::doMatch(QStringView text, int offset, const QStringList &captures, DynamicRegexpCache &) const { if (m_dynamic) { - if (m_captureIndex == 0 || captures.size() <= m_captureIndex || captures.at(m_captureIndex).isEmpty()) { + if (m_captureIndex == -1 || captures.size() <= m_captureIndex || captures.at(m_captureIndex).isEmpty()) { return offset; } if (text.at(offset) == captures.at(m_captureIndex).at(0)) { @@ -272,7 +271,7 @@ Detect2Chars::Detect2Chars(const HighlightingContextData::Rule::Detect2Chars &da { } -MatchResult Detect2Chars::doMatch(QStringView text, int offset, const QStringList &) const +MatchResult Detect2Chars::doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const { if (text.size() - offset < 2) { return offset; @@ -283,7 +282,7 @@ MatchResult Detect2Chars::doMatch(QStringView text, int offset, const QStringLis return offset; } -MatchResult DetectIdentifier::doMatch(QStringView text, int offset, const QStringList &) const +MatchResult DetectIdentifier::doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const { if (!text.at(offset).isLetter() && text.at(offset) != QLatin1Char('_')) { return offset; @@ -299,7 +298,7 @@ MatchResult DetectIdentifier::doMatch(QStringView text, int offset, const QStrin return text.size(); } -MatchResult DetectSpaces::doMatch(QStringView text, int offset, const QStringList &) const +MatchResult DetectSpaces::doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const { while (offset < text.size() && text.at(offset).isSpace()) { ++offset; @@ -313,7 +312,7 @@ Float::Float(DefinitionData &def, const HighlightingContextData::Rule::Float &da resolveAdditionalWordDelimiters(m_wordDelimiters, data.wordDelimiters); } -MatchResult Float::doMatch(QStringView text, int offset, const QStringList &) const +MatchResult Float::doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const { if (offset > 0 && !m_wordDelimiters.contains(text.at(offset - 1))) { return offset; @@ -358,7 +357,7 @@ MatchResult Float::doMatch(QStringView text, int offset, const QStringList &) co return expOffset; } -MatchResult HlCChar::doMatch(QStringView text, int offset, const QStringList &) const +MatchResult HlCChar::doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const { if (text.size() < offset + 3) { return offset; @@ -393,7 +392,7 @@ HlCHex::HlCHex(DefinitionData &def, const HighlightingContextData::Rule::HlCHex resolveAdditionalWordDelimiters(m_wordDelimiters, data.wordDelimiters); } -MatchResult HlCHex::doMatch(QStringView text, int offset, const QStringList &) const +MatchResult HlCHex::doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const { if (offset > 0 && !m_wordDelimiters.contains(text.at(offset - 1))) { return offset; @@ -427,7 +426,7 @@ HlCOct::HlCOct(DefinitionData &def, const HighlightingContextData::Rule::HlCOct resolveAdditionalWordDelimiters(m_wordDelimiters, data.wordDelimiters); } -MatchResult HlCOct::doMatch(QStringView text, int offset, const QStringList &) const +MatchResult HlCOct::doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const { if (offset > 0 && !m_wordDelimiters.contains(text.at(offset - 1))) { return offset; @@ -453,7 +452,7 @@ MatchResult HlCOct::doMatch(QStringView text, int offset, const QStringList &) c return offset; } -MatchResult HlCStringChar::doMatch(QStringView text, int offset, const QStringList &) const +MatchResult HlCStringChar::doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const { return matchEscapedChar(text, offset); } @@ -464,7 +463,7 @@ IncludeRules::IncludeRules(const HighlightingContextData::Rule::IncludeRules &da { } -MatchResult IncludeRules::doMatch(QStringView text, int offset, const QStringList &) const +MatchResult IncludeRules::doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const { Q_UNUSED(text); qCWarning(Log) << "Unresolved include rule"; @@ -477,7 +476,7 @@ Int::Int(DefinitionData &def, const HighlightingContextData::Rule::Int &data) resolveAdditionalWordDelimiters(m_wordDelimiters, data.wordDelimiters); } -MatchResult Int::doMatch(QStringView text, int offset, const QStringList &) const +MatchResult Int::doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const { if (offset > 0 && !m_wordDelimiters.contains(text.at(offset - 1))) { return offset; @@ -521,9 +520,10 @@ KeywordListRule::KeywordListRule(const KeywordList &keywordList, DefinitionData , m_caseSensitivity(data.hasCaseSensitivityOverride ? data.caseSensitivityOverride : keywordList.caseSensitivity()) { resolveAdditionalWordDelimiters(m_wordDelimiters, data.wordDelimiters); + m_hasSkipOffset = true; } -MatchResult KeywordListRule::doMatch(QStringView text, int offset, const QStringList &) const +MatchResult KeywordListRule::doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const { auto newOffset = offset; while (text.size() > newOffset && !m_wordDelimiters.contains(text.at(newOffset))) { @@ -546,7 +546,7 @@ LineContinue::LineContinue(const HighlightingContextData::Rule::LineContinue &da { } -MatchResult LineContinue::doMatch(QStringView text, int offset, const QStringList &) const +MatchResult LineContinue::doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const { if (offset == text.size() - 1 && text.at(offset) == m_char) { return offset + 1; @@ -560,7 +560,7 @@ RangeDetect::RangeDetect(const HighlightingContextData::Rule::RangeDetect &data) { } -MatchResult RangeDetect::doMatch(QStringView text, int offset, const QStringList &) const +MatchResult RangeDetect::doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const { if (text.size() - offset < 2) { return offset; @@ -591,25 +591,16 @@ static QRegularExpression::PatternOptions makePattenOptions(const HighlightingCo static void resolveRegex(QRegularExpression ®exp, Context *context) { - if (!regexp.isValid()) { - // DontCaptureOption with back reference capture is an error, remove this option then try again - regexp.setPatternOptions(regexp.patternOptions() & ~QRegularExpression::DontCaptureOption); + bool enableCapture = context && context->hasDynamicRule(); - if (!regexp.isValid()) { - qCDebug(Log) << "Invalid regexp:" << regexp.pattern(); - } - - return; + // disable DontCaptureOption when reference a context with dynamic rule or + // with invalid regex because DontCaptureOption with back reference capture is an error + if (enableCapture || !regexp.isValid()) { + regexp.setPatternOptions(regexp.patternOptions() & ~QRegularExpression::DontCaptureOption); } - // disable DontCaptureOption when reference a context with dynamic rule - if (context) { - for (const Rule::Ptr &rule : context->rules()) { - if (rule->isDynamic()) { - regexp.setPatternOptions(regexp.patternOptions() & ~QRegularExpression::DontCaptureOption); - break; - } - } + if (!regexp.isValid()) { + qCDebug(Log) << "Invalid regexp:" << regexp.pattern(); } } @@ -618,15 +609,25 @@ static MatchResult regexMatch(const QRegularExpression ®exp, QStringView text /** * match the pattern */ +#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0) + const auto result = regexp.matchView(text, offset, QRegularExpression::NormalMatch, QRegularExpression::DontCheckSubjectStringMatchOption); +#else const auto result = regexp.match(text, offset, QRegularExpression::NormalMatch, QRegularExpression::DontCheckSubjectStringMatchOption); +#endif if (result.capturedStart() == offset) { /** * we only need to compute the captured texts if we have real capture groups * highlightings should only address %1..%.., see e.g. replaceCaptures * DetectChar ignores %0, too */ - if (result.lastCapturedIndex() > 0) { - return MatchResult(offset + result.capturedLength(), result.capturedTexts()); + int lastCapturedIndex = result.lastCapturedIndex(); + if (lastCapturedIndex > 0) { + QStringList captures; + captures.reserve(lastCapturedIndex); + // ignore the capturing group number 0 + for (int i = 1; i <= lastCapturedIndex; ++i) + captures.push_back(result.captured(i)); + return MatchResult(offset + result.capturedLength(), std::move(captures)); } /** @@ -645,20 +646,17 @@ static MatchResult regexMatch(const QRegularExpression ®exp, QStringView text RegExpr::RegExpr(const HighlightingContextData::Rule::RegExpr &data) : m_regexp(data.pattern, makePattenOptions(data)) { + m_hasSkipOffset = true; } void RegExpr::resolve() { - if (m_isResolved) { - return; - } - m_isResolved = true; resolveRegex(m_regexp, context().context()); } -MatchResult RegExpr::doMatch(QStringView text, int offset, const QStringList &) const +MatchResult RegExpr::doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const { if (Q_UNLIKELY(!m_isResolved)) { const_cast<RegExpr *>(this)->resolve(); @@ -672,14 +670,11 @@ DynamicRegExpr::DynamicRegExpr(const HighlightingContextData::Rule::RegExpr &dat , m_patternOptions(makePattenOptions(data)) { m_dynamic = true; + m_hasSkipOffset = true; } void DynamicRegExpr::resolve() { - if (m_isResolved) { - return; - } - m_isResolved = true; QRegularExpression regexp(m_pattern, m_patternOptions); @@ -687,7 +682,7 @@ void DynamicRegExpr::resolve() m_patternOptions = regexp.patternOptions(); } -MatchResult DynamicRegExpr::doMatch(QStringView text, int offset, const QStringList &captures) const +MatchResult DynamicRegExpr::doMatch(QStringView text, int offset, const QStringList &captures, DynamicRegexpCache &dynamicRegexpCache) const { if (Q_UNLIKELY(!m_isResolved)) { const_cast<DynamicRegExpr *>(this)->resolve(); @@ -696,8 +691,8 @@ MatchResult DynamicRegExpr::doMatch(QStringView text, int offset, const QStringL /** * create new pattern with right instantiation */ - const QRegularExpression regexp(replaceCaptures(m_pattern, captures, true), m_patternOptions); - + auto pattern = replaceCaptures(m_pattern, captures, true); + auto ®exp = dynamicRegexpCache.compileRegexp(std::move(pattern), m_patternOptions); return regexMatch(regexp, text, offset); } @@ -707,7 +702,7 @@ StringDetect::StringDetect(const HighlightingContextData::Rule::StringDetect &da { } -MatchResult StringDetect::doMatch(QStringView text, int offset, const QStringList &) const +MatchResult StringDetect::doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const { return matchString(m_string, text, offset, m_caseSensitivity); } @@ -719,7 +714,7 @@ DynamicStringDetect::DynamicStringDetect(const HighlightingContextData::Rule::St m_dynamic = true; } -MatchResult DynamicStringDetect::doMatch(QStringView text, int offset, const QStringList &captures) const +MatchResult DynamicStringDetect::doMatch(QStringView text, int offset, const QStringList &captures, DynamicRegexpCache &) const { /** * for dynamic case: create new pattern with right instantiation @@ -736,7 +731,7 @@ WordDetect::WordDetect(DefinitionData &def, const HighlightingContextData::Rule: resolveAdditionalWordDelimiters(m_wordDelimiters, data.wordDelimiters); } -MatchResult WordDetect::doMatch(QStringView text, int offset, const QStringList &) const +MatchResult WordDetect::doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const { if (text.size() - offset < m_word.size()) { return offset; |