aboutsummaryrefslogtreecommitdiffstats
path: root/src/libs/3rdparty/syntax-highlighting/src/lib/rule.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/3rdparty/syntax-highlighting/src/lib/rule.cpp')
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/lib/rule.cpp105
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 &regexp, 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 &regexp, 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 &regexp, 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 &regexp = 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;