diff --git a/src/lib/rule.cpp b/src/lib/rule.cpp --- a/src/lib/rule.cpp +++ b/src/lib/rule.cpp @@ -229,7 +229,7 @@ return true; } -MatchResult Rule::match(const QString &text, int offset, const QStringList &captures) +MatchResult Rule::match(const QString &text, int offset, const QStringList &captures) const { Q_ASSERT(!text.isEmpty()); @@ -306,7 +306,7 @@ return !m_chars.isEmpty(); } -MatchResult AnyChar::doMatch(const QString& text, int offset, const QStringList&) +MatchResult AnyChar::doMatch(const QString& text, int offset, const QStringList&) const { if (m_chars.contains(text.at(offset))) return offset + 1; @@ -326,7 +326,7 @@ return true; } -MatchResult DetectChar::doMatch(const QString& text, int offset, const QStringList &captures) +MatchResult DetectChar::doMatch(const QString& text, int offset, const QStringList &captures) const { if (isDynamic()) { if (captures.size() <= m_captureIndex || captures.at(m_captureIndex).isEmpty()) @@ -353,7 +353,7 @@ return true; } -MatchResult Detect2Char::doMatch(const QString& text, int offset, const QStringList &captures) +MatchResult Detect2Char::doMatch(const QString& text, int offset, const QStringList &captures) const { Q_UNUSED(captures); // TODO if (text.size() - offset < 2) @@ -364,7 +364,7 @@ } -MatchResult DetectIdentifier::doMatch(const QString& text, int offset, const QStringList&) +MatchResult DetectIdentifier::doMatch(const QString& text, int offset, const QStringList&) const { if (!text.at(offset).isLetter() && text.at(offset) != QLatin1Char('_')) return offset; @@ -379,15 +379,15 @@ } -MatchResult DetectSpaces::doMatch(const QString& text, int offset, const QStringList&) +MatchResult DetectSpaces::doMatch(const QString& text, int offset, const QStringList&) const { while(offset < text.size() && text.at(offset).isSpace()) ++offset; return offset; } -MatchResult Float::doMatch(const QString& text, int offset, const QStringList&) +MatchResult Float::doMatch(const QString& text, int offset, const QStringList&) const { if (offset > 0 && !isWordDelimiter(text.at(offset - 1))) return offset; @@ -425,7 +425,7 @@ } -MatchResult HlCChar::doMatch(const QString& text, int offset, const QStringList&) +MatchResult HlCChar::doMatch(const QString& text, int offset, const QStringList&) const { if (text.size() < offset + 3) return offset; @@ -450,7 +450,7 @@ } -MatchResult HlCHex::doMatch(const QString& text, int offset, const QStringList&) +MatchResult HlCHex::doMatch(const QString& text, int offset, const QStringList&) const { if (offset > 0 && !isWordDelimiter(text.at(offset - 1))) return offset; @@ -474,7 +474,7 @@ } -MatchResult HlCOct::doMatch(const QString& text, int offset, const QStringList&) +MatchResult HlCOct::doMatch(const QString& text, int offset, const QStringList&) const { if (offset > 0 && !isWordDelimiter(text.at(offset - 1))) return offset; @@ -496,7 +496,7 @@ } -MatchResult HlCStringChar::doMatch(const QString& text, int offset, const QStringList&) +MatchResult HlCStringChar::doMatch(const QString& text, int offset, const QStringList&) const { return matchEscapedChar(text, offset); } @@ -531,15 +531,15 @@ return !m_contextName.isEmpty() || !m_defName.isEmpty(); } -MatchResult IncludeRules::doMatch(const QString& text, int offset, const QStringList&) +MatchResult IncludeRules::doMatch(const QString& text, int offset, const QStringList&) const { Q_UNUSED(text); qCWarning(Log) << "Unresolved include rule for" << m_contextName << "##" << m_defName; return offset; } -MatchResult Int::doMatch(const QString& text, int offset, const QStringList &captures) +MatchResult Int::doMatch(const QString& text, int offset, const QStringList &captures) const { if (offset > 0 && !isWordDelimiter(text.at(offset - 1))) return offset; @@ -564,7 +564,7 @@ return !m_listName.isEmpty(); } -MatchResult KeywordListRule::doMatch(const QString& text, int offset, const QStringList&) +MatchResult KeywordListRule::doMatch(const QString& text, int offset, const QStringList&) const { if (m_keywordList.isEmpty()) { const auto def = definition(); @@ -602,7 +602,7 @@ return true; } -MatchResult LineContinue::doMatch(const QString& text, int offset, const QStringList&) +MatchResult LineContinue::doMatch(const QString& text, int offset, const QStringList&) const { if (offset == text.size() - 1 && text.at(offset) == m_char) return offset + 1; @@ -621,7 +621,7 @@ return true; } -MatchResult RangeDetect::doMatch(const QString& text, int offset, const QStringList&) +MatchResult RangeDetect::doMatch(const QString& text, int offset, const QStringList&) const { if (text.size() - offset < 2) return offset; @@ -641,22 +641,31 @@ { m_pattern = reader.attributes().value(QStringLiteral("String")).toString(); m_regexp.setPattern(m_pattern); + const auto isMinimal = Xml::attrToBool(reader.attributes().value(QStringLiteral("minimal"))); const auto isCaseInsensitive = Xml::attrToBool(reader.attributes().value(QStringLiteral("insensitive"))); m_regexp.setPatternOptions( (isMinimal ? QRegularExpression::InvertedGreedinessOption : QRegularExpression::NoPatternOption) | (isCaseInsensitive ? QRegularExpression::CaseInsensitiveOption : QRegularExpression::NoPatternOption)); - return !m_pattern.isEmpty(); // m_regexp.isValid() would be better, but parses the regexp and thus is way too expensive -} -MatchResult RegExpr::doMatch(const QString& text, int offset, const QStringList &captures) -{ + // optimize the pattern for the non-dynamic case, we use them OFTEN + if (!isDynamic()) { + m_regexp.optimize(); + } + + // always using m_regexp.isValid() would be better, but parses the regexp and thus is way too expensive for release builds Q_ASSERT(m_regexp.isValid()); + return !m_pattern.isEmpty(); +} - if (isDynamic()) - m_regexp.setPattern(replaceCaptures(m_pattern, captures, true)); +MatchResult RegExpr::doMatch(const QString& text, int offset, const QStringList &captures) const +{ + /** + * for dynamic case: create new pattern with right instantiation + */ + const auto ®exp = isDynamic() ? QRegularExpression(replaceCaptures(m_pattern, captures, true), m_regexp.patternOptions()) : m_regexp; - auto result = m_regexp.match(text, offset, QRegularExpression::NormalMatch, QRegularExpression::DontCheckSubjectStringMatchOption); + auto result = regexp.match(text, offset, QRegularExpression::NormalMatch, QRegularExpression::DontCheckSubjectStringMatchOption); if (result.capturedStart() == offset) return MatchResult(offset + result.capturedLength(), result.capturedTexts()); return MatchResult(offset, result.capturedStart()); @@ -670,11 +679,13 @@ return !m_string.isEmpty(); } -MatchResult StringDetect::doMatch(const QString& text, int offset, const QStringList &captures) +MatchResult StringDetect::doMatch(const QString& text, int offset, const QStringList &captures) const { - auto pattern = m_string; - if (isDynamic()) - pattern = replaceCaptures(m_string, captures, false); + /** + * for dynamic case: create new pattern with right instantiation + */ + const auto &pattern = isDynamic() ? replaceCaptures(m_string, captures, false) : m_string; + if (text.midRef(offset, pattern.size()).compare(pattern, m_caseSensitivity) == 0) return offset + pattern.size(); return offset; @@ -688,7 +699,7 @@ return !m_word.isEmpty(); } -MatchResult WordDetect::doMatch(const QString& text, int offset, const QStringList &captures) +MatchResult WordDetect::doMatch(const QString& text, int offset, const QStringList &captures) const { Q_UNUSED(captures); // TODO if (text.size() - offset < m_word.size()) diff --git a/src/lib/rule_p.h b/src/lib/rule_p.h --- a/src/lib/rule_p.h +++ b/src/lib/rule_p.h @@ -71,13 +71,13 @@ void resolveContext(); void resolveAttributeFormat(Context *lookupContext); - MatchResult match(const QString &text, int offset, const QStringList &captures); + MatchResult match(const QString &text, int offset, const QStringList &captures) const; static Rule::Ptr create(const QStringRef &name); protected: virtual bool doLoad(QXmlStreamReader &reader); - virtual MatchResult doMatch(const QString &text, int offset, const QStringList &captures) = 0; + virtual MatchResult doMatch(const QString &text, int offset, const QStringList &captures) const = 0; bool isWordDelimiter(QChar c) const; @@ -105,7 +105,7 @@ { protected: bool doLoad(QXmlStreamReader & reader) override; - MatchResult doMatch(const QString & text, int offset, const QStringList&) override; + MatchResult doMatch(const QString & text, int offset, const QStringList&) const override; private: QString m_chars; @@ -115,7 +115,7 @@ { protected: bool doLoad(QXmlStreamReader & reader) override; - MatchResult doMatch(const QString & text, int offset, const QStringList &captures) override; + MatchResult doMatch(const QString & text, int offset, const QStringList &captures) const override; private: QChar m_char; @@ -126,7 +126,7 @@ { protected: bool doLoad(QXmlStreamReader & reader) override; - MatchResult doMatch(const QString & text, int offset, const QStringList &captures) override; + MatchResult doMatch(const QString & text, int offset, const QStringList &captures) const override; private: QChar m_char1; @@ -136,19 +136,19 @@ class DetectIdentifier : public Rule { protected: - MatchResult doMatch(const QString & text, int offset, const QStringList&) override; + MatchResult doMatch(const QString & text, int offset, const QStringList&) const override; }; class DetectSpaces : public Rule { protected: - MatchResult doMatch(const QString & text, int offset, const QStringList&) override; + MatchResult doMatch(const QString & text, int offset, const QStringList&) const override; }; class Float : public Rule { protected: - MatchResult doMatch(const QString & text, int offset, const QStringList&) override; + MatchResult doMatch(const QString & text, int offset, const QStringList&) const override; }; class IncludeRules : public Rule @@ -160,7 +160,7 @@ protected: bool doLoad(QXmlStreamReader & reader) override; - MatchResult doMatch(const QString & text, int offset, const QStringList&) override; + MatchResult doMatch(const QString & text, int offset, const QStringList&) const override; private: QString m_contextName; @@ -171,51 +171,51 @@ class Int : public Rule { protected: - MatchResult doMatch(const QString & text, int offset, const QStringList &captures) override; + MatchResult doMatch(const QString & text, int offset, const QStringList &captures) const override; }; class HlCChar : public Rule { protected: - MatchResult doMatch(const QString & text, int offset, const QStringList&) override; + MatchResult doMatch(const QString & text, int offset, const QStringList&) const override; }; class HlCHex : public Rule { protected: - MatchResult doMatch(const QString & text, int offset, const QStringList&) override; + MatchResult doMatch(const QString & text, int offset, const QStringList&) const override; }; class HlCOct : public Rule { protected: - MatchResult doMatch(const QString & text, int offset, const QStringList&) override; + MatchResult doMatch(const QString & text, int offset, const QStringList&) const override; }; class HlCStringChar : public Rule { protected: - MatchResult doMatch(const QString & text, int offset, const QStringList&) override; + MatchResult doMatch(const QString & text, int offset, const QStringList&) const override; }; class KeywordListRule : public Rule { protected: bool doLoad(QXmlStreamReader & reader) override; - MatchResult doMatch(const QString & text, int offset, const QStringList&) override; + MatchResult doMatch(const QString & text, int offset, const QStringList&) const override; private: QString m_listName; - KeywordList m_keywordList; + mutable KeywordList m_keywordList; bool m_hasCaseSensitivityOverride; Qt::CaseSensitivity m_caseSensitivityOverride; }; class LineContinue : public Rule { protected: bool doLoad(QXmlStreamReader & reader) override; - MatchResult doMatch(const QString & text, int offset, const QStringList&) override; + MatchResult doMatch(const QString & text, int offset, const QStringList&) const override; private: QChar m_char; @@ -225,7 +225,7 @@ { protected: bool doLoad(QXmlStreamReader & reader) override; - MatchResult doMatch(const QString & text, int offset, const QStringList&) override; + MatchResult doMatch(const QString & text, int offset, const QStringList&) const override; private: QChar m_begin; @@ -236,7 +236,7 @@ { protected: bool doLoad(QXmlStreamReader & reader) override; - MatchResult doMatch(const QString & text, int offset, const QStringList &captures) override; + MatchResult doMatch(const QString & text, int offset, const QStringList &captures) const override; private: QString m_pattern; @@ -247,7 +247,7 @@ { protected: bool doLoad(QXmlStreamReader & reader) override; - MatchResult doMatch(const QString & text, int offset, const QStringList &captures) override; + MatchResult doMatch(const QString & text, int offset, const QStringList &captures) const override; private: QString m_string; @@ -258,7 +258,7 @@ { protected: bool doLoad(QXmlStreamReader & reader) override; - MatchResult doMatch(const QString & text, int offset, const QStringList &captures) override; + MatchResult doMatch(const QString & text, int offset, const QStringList &captures) const override; private: QString m_word;