diff options
Diffstat (limited to 'src/libs/3rdparty/syntax-highlighting/src/lib')
28 files changed, 767 insertions, 445 deletions
diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/CMakeLists.txt b/src/libs/3rdparty/syntax-highlighting/src/lib/CMakeLists.txt index 722f92742b..43a60cc19b 100644 --- a/src/libs/3rdparty/syntax-highlighting/src/lib/CMakeLists.txt +++ b/src/libs/3rdparty/syntax-highlighting/src/lib/CMakeLists.txt @@ -1,6 +1,8 @@ +add_library(KF5SyntaxHighlighting) + ecm_create_qm_loader(syntax_highlighting_QM_LOADER syntaxhighlighting5_qt) -set(syntax_highlighting_srcs +target_sources(KF5SyntaxHighlighting PRIVATE abstracthighlighter.cpp context.cpp contextswitch.cpp @@ -20,8 +22,9 @@ set(syntax_highlighting_srcs themedata.cpp worddelimiters.cpp ${syntax_highlighting_QM_LOADER} + $<TARGET_OBJECTS:SyntaxHighlightingData> ) -ecm_qt_declare_logging_category(syntax_highlighting_srcs +ecm_qt_declare_logging_category(KF5SyntaxHighlighting HEADER ksyntaxhighlighting_logging.h IDENTIFIER KSyntaxHighlighting::Log CATEGORY_NAME kf.syntaxhighlighting @@ -30,16 +33,27 @@ ecm_qt_declare_logging_category(syntax_highlighting_srcs EXPORT KSYNTAXHIGHLIGHTING ) -add_library(KF5SyntaxHighlighting ${syntax_highlighting_srcs} $<TARGET_OBJECTS:SyntaxHighlightingData>) -generate_export_header(KF5SyntaxHighlighting BASE_NAME KSyntaxHighlighting) +ecm_generate_export_header(KF5SyntaxHighlighting + BASE_NAME KSyntaxHighlighting + GROUP_BASE_NAME KF + VERSION ${KF_VERSION} + DEPRECATED_BASE_VERSION 0 + DEPRECATION_VERSIONS 5.87 + EXCLUDE_DEPRECATED_BEFORE_AND_AT ${EXCLUDE_DEPRECATED_BEFORE_AND_AT} +) set_target_properties(KF5SyntaxHighlighting PROPERTIES - VERSION ${SyntaxHighlighting_VERSION_STRING} + VERSION ${SyntaxHighlighting_VERSION} SOVERSION ${SyntaxHighlighting_SOVERSION} EXPORT_NAME SyntaxHighlighting ) target_include_directories(KF5SyntaxHighlighting INTERFACE "$<INSTALL_INTERFACE:${KDE_INSTALL_INCLUDEDIR_KF5}/KSyntaxHighlighting;${KDE_INSTALL_INCLUDEDIR_KF5}>") target_include_directories(KF5SyntaxHighlighting PUBLIC "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR};${CMAKE_CURRENT_BINARY_DIR};>") -target_link_libraries(KF5SyntaxHighlighting LINK_PUBLIC Qt5::Gui LINK_PRIVATE Qt5::Network) +target_link_libraries(KF5SyntaxHighlighting + PUBLIC + Qt5::Gui + PRIVATE + Qt5::Network +) ecm_generate_headers(SyntaxHighlighting_HEADERS HEADER_NAMES @@ -52,6 +66,7 @@ ecm_generate_headers(SyntaxHighlighting_HEADERS State SyntaxHighlighter Theme + WildcardMatcher REQUIRED_HEADERS SyntaxHighlighting_HEADERS ) diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/abstracthighlighter.cpp b/src/libs/3rdparty/syntax-highlighting/src/lib/abstracthighlighter.cpp index 2ad9d371f9..d6f8cad0c7 100644 --- a/src/libs/3rdparty/syntax-highlighting/src/lib/abstracthighlighter.cpp +++ b/src/libs/3rdparty/syntax-highlighting/src/lib/abstracthighlighter.cpp @@ -36,11 +36,13 @@ void AbstractHighlighterPrivate::ensureDefinitionLoaded() defData = DefinitionData::get(m_definition); } - if (Q_UNLIKELY(!defData->repo && !defData->fileName.isEmpty())) + if (Q_UNLIKELY(!defData->repo && !defData->fileName.isEmpty())) { qCCritical(Log) << "Repository got deleted while a highlighter is still active!"; + } - if (m_definition.isValid()) + if (m_definition.isValid()) { defData->load(); + } } AbstractHighlighter::AbstractHighlighter() @@ -85,7 +87,7 @@ void AbstractHighlighter::setTheme(const Theme &theme) * Returns the index of the first non-space character. If the line is empty, * or only contains white spaces, text.size() is returned. */ -static inline int firstNonSpaceChar(const QString &text) +static inline int firstNonSpaceChar(QStringView text) { for (int i = 0; i < text.length(); ++i) { if (!text[i].isSpace()) { @@ -95,8 +97,15 @@ static inline int firstNonSpaceChar(const QString &text) return text.size(); } +#if KSYNTAXHIGHLIGHTING_BUILD_DEPRECATED_SINCE(5, 87) State AbstractHighlighter::highlightLine(const QString &text, const State &state) { + return highlightLine(QStringView(text), state); +} +#endif + +State AbstractHighlighter::highlightLine(QStringView text, const State &state) +{ Q_D(AbstractHighlighter); // verify definition, deal with no highlighting being enabled @@ -145,8 +154,9 @@ State AbstractHighlighter::highlightLine(const QString &text, const State &state * skipping empty lines after a line continuation character (see bug 405903) */ } else if (!stateData->topContext()->lineEndContext().isStay() - && !d->switchContext(stateData, stateData->topContext()->lineEndContext(), QStringList())) + && !d->switchContext(stateData, stateData->topContext()->lineEndContext(), QStringList())) { break; + } // guard against endless loops ++endlessLoopingCounter; @@ -160,7 +170,8 @@ State AbstractHighlighter::highlightLine(const QString &text, const State &state return newState; } - int offset = 0, beginOffset = 0; + int offset = 0; + int beginOffset = 0; bool lineContinuation = false; /** @@ -247,8 +258,9 @@ State AbstractHighlighter::highlightLine(const QString &text, const State &state skipOffsets.clear(); } const auto currentSkipOffset = skipOffsets.value(rule.get()); - if (currentSkipOffset < 0 || currentSkipOffset > offset) + if (currentSkipOffset < 0 || currentSkipOffset > offset) { continue; + } const auto newResult = rule->doMatch(text, offset, stateData->topCaptures()); newOffset = newResult.offset(); @@ -265,8 +277,9 @@ State AbstractHighlighter::highlightLine(const QString &text, const State &state } } - if (newOffset <= offset) + if (newOffset <= offset) { continue; + } /** * apply folding. @@ -274,12 +287,14 @@ State AbstractHighlighter::highlightLine(const QString &text, const State &state * - rule with endRegion + beginRegion: in endRegion, the length is 0 * - rule with lookAhead: length is 0 */ - if (rule->endRegion().isValid() && rule->beginRegion().isValid()) + if (rule->endRegion().isValid() && rule->beginRegion().isValid()) { applyFolding(offset, 0, rule->endRegion()); - else if (rule->endRegion().isValid()) + } else if (rule->endRegion().isValid()) { applyFolding(offset, rule->isLookAhead() ? 0 : newOffset - offset, rule->endRegion()); - if (rule->beginRegion().isValid()) + } + if (rule->beginRegion().isValid()) { applyFolding(offset, rule->isLookAhead() ? 0 : newOffset - offset, rule->beginRegion()); + } if (rule->isLookAhead()) { Q_ASSERT(!rule->context().isStay()); @@ -290,12 +305,14 @@ State AbstractHighlighter::highlightLine(const QString &text, const State &state d->switchContext(stateData, rule->context(), newResult.captures()); newFormat = rule->attributeFormat().isValid() ? &rule->attributeFormat() : &stateData->topContext()->attributeFormat(); - if (newOffset == text.size() && std::dynamic_pointer_cast<LineContinue>(rule)) + if (newOffset == text.size() && std::dynamic_pointer_cast<LineContinue>(rule)) { lineContinuation = true; + } break; } - if (isLookAhead) + if (isLookAhead) { continue; + } if (newOffset <= offset) { // no matching rule if (stateData->topContext()->fallthrough()) { @@ -316,8 +333,9 @@ State AbstractHighlighter::highlightLine(const QString &text, const State &state * on format change, apply the last one and switch to new one */ if (newFormat != currentFormat && newFormat->id() != currentFormat->id()) { - if (offset > 0) + if (offset > 0) { applyFormat(beginOffset, offset - beginOffset, *currentFormat); + } beginOffset = offset; currentFormat = newFormat; } @@ -333,8 +351,9 @@ State AbstractHighlighter::highlightLine(const QString &text, const State &state /** * apply format for remaining text, if any */ - if (beginOffset < offset) + if (beginOffset < offset) { applyFormat(beginOffset, text.size() - beginOffset, *currentFormat); + } /** * handle line end context switches @@ -344,8 +363,9 @@ State AbstractHighlighter::highlightLine(const QString &text, const State &state { int endlessLoopingCounter = 0; while (!stateData->topContext()->lineEndContext().isStay() && !lineContinuation) { - if (!d->switchContext(stateData, stateData->topContext()->lineEndContext(), QStringList())) + if (!d->switchContext(stateData, stateData->topContext()->lineEndContext(), QStringList())) { break; + } // guard against endless loops ++endlessLoopingCounter; diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/abstracthighlighter.h b/src/libs/3rdparty/syntax-highlighting/src/lib/abstracthighlighter.h index 5e85873ce0..49cfbf2530 100644 --- a/src/libs/3rdparty/syntax-highlighting/src/lib/abstracthighlighter.h +++ b/src/libs/3rdparty/syntax-highlighting/src/lib/abstracthighlighter.h @@ -108,6 +108,15 @@ protected: AbstractHighlighter(); AbstractHighlighter(AbstractHighlighterPrivate *dd); +#if KSYNTAXHIGHLIGHTING_ENABLE_DEPRECATED_SINCE(5, 87) + /** + * @copydoc highlightLine(QStringView,const State&) + * @deprecated since 5.87, use highlightLine(QStringView, const State&) instead. + */ + // no deprecation warning, as removal of this will automatically "port" the using code + State highlightLine(const QString &text, const State &state); +#endif + // TODO KF6: add an optional void* context argument that is passed through // to the applyX() calls, so highlighters dealing with some form of line object // (such as QSyntaxHighlighter or KTextEditor) can avoid some ugly hacks to have @@ -120,14 +129,14 @@ protected: * @param state The highlighting state handle returned by the call * to highlightLine() for the previous line. For the very first line, * just pass a default constructed State(). - * @returns The state of the highlighing engine after processing the + * @returns The state of the highlighting engine after processing the * given line. This needs to passed into highlightLine() for the * next line. You can store the state for efficient partial * re-highlighting for example during editing. * * @see applyFormat(), applyFolding() */ - State highlightLine(const QString &text, const State &state); + State highlightLine(QStringView text, const State &state); /** * Reimplement this to apply formats to your output. The provided @p format diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/ansihighlighter.cpp b/src/libs/3rdparty/syntax-highlighting/src/lib/ansihighlighter.cpp index 9ff012e1d7..8ae47d80eb 100644 --- a/src/libs/3rdparty/syntax-highlighting/src/lib/ansihighlighter.cpp +++ b/src/libs/3rdparty/syntax-highlighting/src/lib/ansihighlighter.cpp @@ -33,10 +33,6 @@ struct CieLab { double b; }; -#ifndef M_PI -constexpr double M_PI = 3.14159265358979323846; -#endif - // clang-format off // xterm color reference // constexpr Rgb888 xterm256Colors[] { @@ -388,10 +384,11 @@ CieLab rgbToLab(QRgb rgb) // Perform the inverse gamma companding for a sRGB color // http://www.brucelindbloom.com/index.html?Eqn_RGB_to_XYZ.html auto inverseGammaCompanding = [](int c) { - if (c <= 10) + if (c <= 10) { return c / (255.0 * 12.92); - else + } else { return std::pow((c / 255.0 + 0.055) / 1.055, 2.4); + } }; const double r = inverseGammaCompanding(qRed(rgb)); @@ -404,10 +401,11 @@ CieLab rgbToLab(QRgb rgb) // http://www.brucelindbloom.com/index.html?Eqn_XYZ_to_Lab.html auto f = [](double t) { - if (t > 216.0 / 24389.0) + if (t > 216.0 / 24389.0) { return std::cbrt(t); - else + } else { return t * (24389.0 / (27.0 * 116.0)) + 4.0 / 29.0; + } }; const double f_x = f(x / illuminant_D65[0]); @@ -440,8 +438,9 @@ inline double pow2(double x) inline double computeHPrime(double a_prime, double b) { - if (std::abs(a_prime) < epsilon && std::abs(b) < epsilon) + if (std::abs(a_prime) < epsilon && std::abs(b) < epsilon) { return 0.0; + } const double value = std::atan2(b, a_prime) * 180.0 / M_PI; return (value < 0.0) ? value + 360.0 : value; @@ -449,34 +448,38 @@ inline double computeHPrime(double a_prime, double b) inline double computeDeltaHPrime(double C1_prime, double C2_prime, double h1_prime, double h2_prime) { - if (C1_prime * C2_prime < epsilon) + if (C1_prime * C2_prime < epsilon) { return 0.0; + } const double diff = h2_prime - h1_prime; - if (std::abs(diff) <= 180.0) + if (std::abs(diff) <= 180.0) { return diff; - else if (diff > 180.0) + } else if (diff > 180.0) { return diff - 360.0; - else + } else { return diff + 360.0; + } } inline double computeHPrimeBar(double C1_prime, double C2_prime, double h1_prime, double h2_prime) { const double sum = h1_prime + h2_prime; - if (C1_prime * C2_prime < epsilon) + if (C1_prime * C2_prime < epsilon) { return sum; + } const double dist = std::abs(h1_prime - h2_prime); - if (dist <= 180.0) + if (dist <= 180.0) { return 0.5 * sum; - else if (sum < 360.0) + } else if (sum < 360.0) { return 0.5 * (sum + 360.0); - else + } else { return 0.5 * (sum - 360.0); + } } /// Calculate the perceptual color difference based on CIEDE2000. @@ -702,7 +705,7 @@ struct GraphLine { const int n2 = offset - labelLineLength; labelLineLength += n2 + 1; fillLine(labelLine, n2); - labelLine += graphLine.rightRef(graphLine.size() - ps1); + labelLine += QStringView(graphLine).right(graphLine.size() - ps1); } } @@ -781,8 +784,9 @@ public: state = highlightLine(currentLine, state); if (hasSeparator) { - if (!firstLine) + if (!firstLine) { out << QStringLiteral("\x1b[0m────────────────────────────────────────────────────\x1b[K\n"); + } firstLine = false; } @@ -793,14 +797,15 @@ public: for (const auto &fragment : m_highlightedFragments) { auto const &ansiStyle = ansiStyles[fragment.formatId]; - out << ansiStyle.first << currentLine.midRef(fragment.offset, fragment.length) << ansiStyle.second; + out << ansiStyle.first << QStringView(currentLine).mid(fragment.offset, fragment.length) << ansiStyle.second; } out << QStringLiteral("\x1b[K\n"); if (hasFormatOrContextTrace && !m_highlightedFragments.empty()) { - if (m_hasContextTrace || m_hasStackSizeTrace) + if (m_hasContextTrace || m_hasStackSizeTrace) { appendContextNames(oldState, currentLine); + } printFormats(out, infoStyle, ansiStyles); out << resetBgColor; @@ -817,8 +822,9 @@ public: void applyFolding(int offset, int /*length*/, FoldingRegion region) override { - if (!m_hasRegionTrace) + if (!m_hasRegionTrace) { return; + } const auto id = region.id(); @@ -829,8 +835,9 @@ public: auto &previousRegion = m_regions[m_regions.size() - 2]; if (previousRegion.state == Region::State::Close && previousRegion.offset == offset) { std::swap(previousRegion, m_regions.back()); - if (previousRegion.bindIndex != -1) + if (previousRegion.bindIndex != -1) { m_regions[previousRegion.bindIndex].bindIndex = m_regions.size() - 1; + } } } ++m_regionDepth; @@ -840,10 +847,11 @@ public: auto eit = m_regions.rend(); for (int depth = 0; it != eit; ++it) { if (it->regionId == id && it->bindIndex < 0) { - if (it->state == Region::State::Close) + if (it->state == Region::State::Close) { ++depth; - else if (--depth < 0) + } else if (--depth < 0) { break; + } } } @@ -868,8 +876,9 @@ private: void initRegionStyles(const std::vector<QPair<QString, QString>> &ansiStyles) { m_regionStyles.resize(ansiStyles.size()); - for (std::size_t i = 0; i < m_regionStyles.size(); ++i) + for (std::size_t i = 0; i < m_regionStyles.size(); ++i) { m_regionStyles[i] = ansiStyles[i].first; + } std::sort(m_regionStyles.begin(), m_regionStyles.end()); m_regionStyles.erase(std::unique(m_regionStyles.begin(), m_regionStyles.end()), m_regionStyles.end()); @@ -1216,7 +1225,7 @@ void AnsiHighlighter::highlightData(QIODevice *dev, AnsiFormat format, bool useE } // initialize ansiStyles - for (auto &&definition : qAsConst(definitions)) { + for (auto &&definition : std::as_const(definitions)) { const auto formats = definition.formats(); for (auto &&format : formats) { const auto id = format.id(); @@ -1236,20 +1245,26 @@ void AnsiHighlighter::highlightData(QIODevice *dev, AnsiFormat format, bool useE const bool hasUnderline = format.isUnderline(theme); const bool hasStrikeThrough = format.isStrikeThrough(theme); - if (hasFg) + if (hasFg) { buffer.appendForeground(format.textColor(theme).rgb(), is256Colors, colorCache); - else + } else { buffer.append(foregroundDefaultColor); - if (hasBg) + } + if (hasBg) { buffer.appendBackground(format.backgroundColor(theme).rgb(), is256Colors, colorCache); - if (hasBold) + } + if (hasBold) { buffer.append(QLatin1String("1;")); - if (hasItalic) + } + if (hasItalic) { buffer.append(QLatin1String("3;")); - if (hasUnderline) + } + if (hasUnderline) { buffer.append(QLatin1String("4;")); - if (hasStrikeThrough) + } + if (hasStrikeThrough) { buffer.append(QLatin1String("9;")); + } // if there is ANSI style if (buffer.latin1().size() > 2) { @@ -1266,14 +1281,18 @@ void AnsiHighlighter::highlightData(QIODevice *dev, AnsiFormat format, bool useE d->ansiStyles[id].second = buffer.latin1(); } else if (hasEffect) { buffer.append(QLatin1String("\x1b[")); - if (hasBold) + if (hasBold) { buffer.append(QLatin1String("21;")); - if (hasItalic) + } + if (hasItalic) { buffer.append(QLatin1String("23;")); - if (hasUnderline) + } + if (hasUnderline) { buffer.append(QLatin1String("24;")); - if (hasStrikeThrough) + } + if (hasStrikeThrough) { buffer.append(QLatin1String("29;")); + } buffer.setFinalStyle(); d->ansiStyles[id].second = buffer.latin1(); } @@ -1301,10 +1320,11 @@ void AnsiHighlighter::highlightData(QIODevice *dev, AnsiFormat format, bool useE d->currentLine = in.readLine(); state = highlightLine(d->currentLine, state); - if (useEditorBackground) + if (useEditorBackground) { d->out << QStringLiteral("\x1b[K\n"); - else + } else { d->out << QLatin1Char('\n'); + } } } else { AnsiBuffer buffer; @@ -1328,5 +1348,5 @@ void AnsiHighlighter::highlightData(QIODevice *dev, AnsiFormat format, bool useE void AnsiHighlighter::applyFormat(int offset, int length, const Format &format) { auto const &ansiStyle = d->ansiStyles[format.id()]; - d->out << ansiStyle.first << d->currentLine.midRef(offset, length) << ansiStyle.second; + d->out << ansiStyle.first << QStringView(d->currentLine).mid(offset, length) << ansiStyle.second; } diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/context.cpp b/src/libs/3rdparty/syntax-highlighting/src/lib/context.cpp index f980ea5be8..724f37a03f 100644 --- a/src/libs/3rdparty/syntax-highlighting/src/lib/context.cpp +++ b/src/libs/3rdparty/syntax-highlighting/src/lib/context.cpp @@ -30,8 +30,9 @@ void Context::setDefinition(const DefinitionRef &def) bool Context::indentationBasedFoldingEnabled() const { - if (m_noIndentationBasedFolding) + if (m_noIndentationBasedFolding) { return false; + } return m_def.definition().indentationBasedFoldingEnabled(); } @@ -56,8 +57,9 @@ void Context::load(QXmlStreamReader &reader) auto rule = Rule::create(reader.name()); if (rule) { rule->setDefinition(m_def.definition()); - if (rule->load(reader)) + if (rule->load(reader)) { m_rules.push_back(std::move(rule)); + } } else { reader.skipCurrentElement(); } @@ -79,8 +81,9 @@ void Context::resolveContexts() m_lineEndContext.resolve(def); m_lineEmptyContext.resolve(def); m_fallthroughContext.resolve(def); - for (const auto &rule : m_rules) + for (const auto &rule : m_rules) { rule->resolveContext(); + } } Context::ResolveState Context::resolveState() @@ -100,8 +103,9 @@ Context::ResolveState Context::resolveState() void Context::resolveIncludes() { - if (resolveState() == Resolved) + if (resolveState() == Resolved) { return; + } if (resolveState() == Resolving) { qCWarning(Log) << "Cyclic dependency!"; return; @@ -129,10 +133,11 @@ void Context::resolveIncludes() } auto defData = DefinitionData::get(def); defData->load(); - if (inc->contextName().isEmpty()) + if (inc->contextName().isEmpty()) { context = defData->initialContext(); - else + } else { context = defData->contextByName(inc->contextName()); + } } if (!context) { qCWarning(Log) << "Unable to resolve include rule for definition" << inc->contextName() << "##" << inc->definitionName() << "in" diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/contextswitch.cpp b/src/libs/3rdparty/syntax-highlighting/src/lib/contextswitch.cpp index 7ccd73ee9b..e829af463a 100644 --- a/src/libs/3rdparty/syntax-highlighting/src/lib/contextswitch.cpp +++ b/src/libs/3rdparty/syntax-highlighting/src/lib/contextswitch.cpp @@ -29,8 +29,9 @@ Context *ContextSwitch::context() const void ContextSwitch::parse(QStringView contextInstr) { - if (contextInstr.isEmpty() || contextInstr == QLatin1String("#stay")) + if (contextInstr.isEmpty() || contextInstr == QLatin1String("#stay")) { return; + } if (contextInstr.startsWith(QLatin1String("#pop!"))) { ++m_popCount; @@ -60,13 +61,15 @@ void ContextSwitch::resolve(const Definition &def) d = DefinitionData::get(def)->repo->definitionForName(m_defName); auto data = DefinitionData::get(d); data->load(); - if (m_contextName.isEmpty()) + if (m_contextName.isEmpty()) { m_context = data->initialContext(); + } } if (!m_contextName.isEmpty()) { m_context = DefinitionData::get(d)->contextByName(m_contextName); - if (!m_context) + if (!m_context) { qCWarning(Log) << "cannot find context" << m_contextName << "in" << def.name(); + } } } diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/definition.cpp b/src/libs/3rdparty/syntax-highlighting/src/lib/definition.cpp index 7434e745b2..068907a4e2 100644 --- a/src/libs/3rdparty/syntax-highlighting/src/lib/definition.cpp +++ b/src/libs/3rdparty/syntax-highlighting/src/lib/definition.cpp @@ -52,29 +52,20 @@ DefinitionData *DefinitionData::get(const Definition &def) Definition::Definition() : d(new DefinitionData) { -} - -Definition::Definition(const Definition &other) - : d(other.d) -{ d->q = *this; } +Definition::Definition(Definition &&other) noexcept = default; +Definition::Definition(const Definition &) = default; +Definition::~Definition() = default; +Definition &Definition::operator=(Definition &&other) noexcept = default; +Definition &Definition::operator=(const Definition &) = default; + Definition::Definition(std::shared_ptr<DefinitionData> &&dd) : d(std::move(dd)) { } -Definition::~Definition() -{ -} - -Definition &Definition::operator=(const Definition &rhs) -{ - d = rhs.d; - return *this; -} - bool Definition::operator==(const Definition &other) const { return d->fileName == other.d->fileName; @@ -223,8 +214,9 @@ bool Definition::setKeywordList(const QString &name, const QStringList &content) if (list) { list->setKeywordList(content); return true; - } else + } else { return false; + } } QVector<Format> Definition::formats() const @@ -251,7 +243,7 @@ QVector<Definition> Definition::includedDefinitions() const // Iterate all context rules to find associated Definitions. This will // automatically catch other Definitions referenced with IncludeRuldes or ContextSwitch. const auto definition = queue.takeLast(); - for (const auto &context : qAsConst(definition.d->contexts)) { + for (const auto &context : std::as_const(definition.d->contexts)) { // handle context switch attributes of this context itself for (const auto switchContext : {context->lineEndContext().context(), context->lineEmptyContext().context(), context->fallthroughContext().context()}) { @@ -321,8 +313,9 @@ Context *DefinitionData::initialContext() const Context *DefinitionData::contextByName(const QString &wantedName) const { for (const auto context : contexts) { - if (context->name() == wantedName) + if (context->name() == wantedName) { return context; + } } return nullptr; } @@ -336,8 +329,9 @@ KeywordList *DefinitionData::keywordList(const QString &wantedName) Format DefinitionData::formatByName(const QString &wantedName) const { const auto it = formats.constFind(wantedName); - if (it != formats.constEnd()) + if (it != formats.constEnd()) { return it.value(); + } return Format(); } @@ -349,24 +343,29 @@ bool DefinitionData::isLoaded() const bool DefinitionData::load(OnlyKeywords onlyKeywords) { - if (fileName.isEmpty()) + if (fileName.isEmpty()) { return false; + } - if (isLoaded()) + if (isLoaded()) { return true; + } - if (bool(onlyKeywords) && keywordIsLoaded) + if (bool(onlyKeywords) && keywordIsLoaded) { return true; + } QFile file(fileName); - if (!file.open(QFile::ReadOnly)) + if (!file.open(QFile::ReadOnly)) { return false; + } QXmlStreamReader reader(&file); while (!reader.atEnd()) { const auto token = reader.readNext(); - if (token != QXmlStreamReader::StartElement) + if (token != QXmlStreamReader::StartElement) { continue; + } if (reader.name() == QLatin1String("highlighting")) { loadHighlighting(reader, onlyKeywords); @@ -375,21 +374,22 @@ bool DefinitionData::load(OnlyKeywords onlyKeywords) } } - else if (reader.name() == QLatin1String("general")) + else if (reader.name() == QLatin1String("general")) { loadGeneral(reader); + } } for (auto it = keywordLists.begin(); it != keywordLists.end(); ++it) { it->setCaseSensitivity(caseSensitive); } - for (const auto context : qAsConst(contexts)) { + for (const auto context : std::as_const(contexts)) { context->resolveContexts(); context->resolveIncludes(); context->resolveAttributeFormat(); } - for (const auto context : qAsConst(contexts)) { + for (const auto context : std::as_const(contexts)) { for (const auto &rule : context->rules()) { rule->resolvePostProcessing(); } @@ -427,14 +427,16 @@ bool DefinitionData::loadMetaData(const QString &definitionFileName) fileName = definitionFileName; QFile file(definitionFileName); - if (!file.open(QFile::ReadOnly)) + if (!file.open(QFile::ReadOnly)) { return false; + } QXmlStreamReader reader(&file); while (!reader.atEnd()) { const auto token = reader.readNext(); - if (token != QXmlStreamReader::StartElement) + if (token != QXmlStreamReader::StartElement) { continue; + } if (reader.name() == QLatin1String("language")) { return loadLanguage(reader); } @@ -457,11 +459,13 @@ bool DefinitionData::loadMetaData(const QString &file, const QCborMap &obj) fileName = file; const auto exts = obj.value(QLatin1String("extensions")).toString(); - for (const auto &ext : exts.split(QLatin1Char(';'), Qt::SkipEmptyParts)) + for (const auto &ext : exts.split(QLatin1Char(';'), Qt::SkipEmptyParts)) { extensions.push_back(ext); + } const auto mts = obj.value(QLatin1String("mimetype")).toString(); - for (const auto &mt : mts.split(QLatin1Char(';'), Qt::SkipEmptyParts)) + for (const auto &mt : mts.split(QLatin1Char(';'), Qt::SkipEmptyParts)) { mimetypes.push_back(mt); + } return true; } @@ -471,8 +475,9 @@ bool DefinitionData::loadLanguage(QXmlStreamReader &reader) Q_ASSERT(reader.name() == QLatin1String("language")); Q_ASSERT(reader.tokenType() == QXmlStreamReader::StartElement); - if (!checkKateVersion(reader.attributes().value(QLatin1String("kateversion")))) + if (!checkKateVersion(reader.attributes().value(QLatin1String("kateversion")))) { return false; + } name = reader.attributes().value(QLatin1String("name")).toString(); section = reader.attributes().value(QLatin1String("section")).toString(); @@ -485,13 +490,16 @@ bool DefinitionData::loadLanguage(QXmlStreamReader &reader) author = reader.attributes().value(QLatin1String("author")).toString(); license = reader.attributes().value(QLatin1String("license")).toString(); const auto exts = reader.attributes().value(QLatin1String("extensions")).toString(); - for (const auto &ext : exts.split(QLatin1Char(';'), Qt::SkipEmptyParts)) + for (const auto &ext : exts.split(QLatin1Char(';'), Qt::SkipEmptyParts)) { extensions.push_back(ext); + } const auto mts = reader.attributes().value(QLatin1String("mimetype")).toString(); - for (const auto &mt : mts.split(QLatin1Char(';'), Qt::SkipEmptyParts)) + for (const auto &mt : mts.split(QLatin1Char(';'), Qt::SkipEmptyParts)) { mimetypes.push_back(mt); - if (reader.attributes().hasAttribute(QLatin1String("casesensitive"))) + } + if (reader.attributes().hasAttribute(QLatin1String("casesensitive"))) { caseSensitive = Xml::attrToBool(reader.attributes().value(QLatin1String("casesensitive"))) ? Qt::CaseSensitive : Qt::CaseInsensitive; + } return true; } @@ -618,8 +626,9 @@ void DefinitionData::loadGeneral(QXmlStreamReader &reader) ++elementRefCounter; if (reader.name() == QLatin1String("keywords")) { - if (reader.attributes().hasAttribute(QLatin1String("casesensitive"))) + if (reader.attributes().hasAttribute(QLatin1String("casesensitive"))) { caseSensitive = Xml::attrToBool(reader.attributes().value(QLatin1String("casesensitive"))) ? Qt::CaseSensitive : Qt::CaseInsensitive; + } // adapt wordDelimiters wordDelimiters.append(reader.attributes().value(QLatin1String("additionalDeliminator"))); @@ -628,14 +637,15 @@ void DefinitionData::loadGeneral(QXmlStreamReader &reader) // adapt WordWrapDelimiters auto wordWrapDeliminatorAttr = reader.attributes().value( QLatin1String("wordWrapDeliminator")); - if (wordWrapDeliminatorAttr.isEmpty()) + if (wordWrapDeliminatorAttr.isEmpty()) { wordWrapDelimiters = wordDelimiters; - else { + } else { wordWrapDelimiters.append(wordWrapDeliminatorAttr); } } else if (reader.name() == QLatin1String("folding")) { - if (reader.attributes().hasAttribute(QLatin1String("indentationsensitive"))) + if (reader.attributes().hasAttribute(QLatin1String("indentationsensitive"))) { indentationBasedFolding = Xml::attrToBool(reader.attributes().value(QLatin1String("indentationsensitive"))); + } } else if (reader.name() == QLatin1String("emptyLines")) { loadFoldingIgnoreList(reader); } else if (reader.name() == QLatin1String("comments")) { @@ -649,8 +659,9 @@ void DefinitionData::loadGeneral(QXmlStreamReader &reader) break; case QXmlStreamReader::EndElement: --elementRefCounter; - if (elementRefCounter == 0) + if (elementRefCounter == 0) { return; + } reader.readNext(); break; default: @@ -688,8 +699,9 @@ void DefinitionData::loadComments(QXmlStreamReader &reader) break; case QXmlStreamReader::EndElement: --elementRefCounter; - if (elementRefCounter == 0) + if (elementRefCounter == 0) { return; + } reader.readNext(); break; default: @@ -719,8 +731,9 @@ void DefinitionData::loadFoldingIgnoreList(QXmlStreamReader &reader) break; case QXmlStreamReader::EndElement: --elementRefCounter; - if (elementRefCounter == 0) + if (elementRefCounter == 0) { return; + } reader.readNext(); break; default: @@ -754,8 +767,9 @@ void DefinitionData::loadSpellchecking(QXmlStreamReader &reader) break; case QXmlStreamReader::EndElement: --elementRefCounter; - if (elementRefCounter == 0) + if (elementRefCounter == 0) { return; + } reader.readNext(); break; default: @@ -798,10 +812,6 @@ DefinitionRef::DefinitionRef(const Definition &def) { } -DefinitionRef::~DefinitionRef() -{ -} - DefinitionRef &DefinitionRef::operator=(const Definition &def) { d = def.d; @@ -810,8 +820,9 @@ DefinitionRef &DefinitionRef::operator=(const Definition &def) Definition DefinitionRef::definition() const { - if (!d.expired()) + if (!d.expired()) { return Definition(d.lock()); + } return Definition(); } diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/definition.h b/src/libs/3rdparty/syntax-highlighting/src/lib/definition.h index 8226fbdd24..05757ea52a 100644 --- a/src/libs/3rdparty/syntax-highlighting/src/lib/definition.h +++ b/src/libs/3rdparty/syntax-highlighting/src/lib/definition.h @@ -13,6 +13,7 @@ #include <QPair> #include <QVector> #include <memory> +#include <qobjectdefs.h> QT_BEGIN_NAMESPACE class QChar; @@ -74,7 +75,7 @@ enum class CommentPosition { * singleLineCommentMarker() and multiLineCommentMarker() provide comment * markers that can be used for commenting/uncommenting code. Similarly, * formats() returns a list of Format items defined by this Definition (which - * equal the itemDatas of a highlighing definition file). includedDefinitions() + * equal the itemDatas of a highlighting definition file). includedDefinitions() * returns a list of all included Definition%s referenced by this Definition via * the rule IncludeRules, which is useful for displaying all Format items for * color configuration in the user interface. @@ -84,6 +85,13 @@ enum class CommentPosition { */ class KSYNTAXHIGHLIGHTING_EXPORT Definition { + Q_GADGET + Q_PROPERTY(QString name READ name) + Q_PROPERTY(QString translatedName READ translatedName) + Q_PROPERTY(QString section READ section) + Q_PROPERTY(QString translatedSection READ translatedSection) + Q_PROPERTY(QString author READ author) + Q_PROPERTY(QString license READ license) public: /** * Default constructor, creating an empty (invalid) Definition instance. @@ -94,6 +102,14 @@ public: Definition(); /** + * Move constructor. + * This definition takes the Definition data from @p other. + * @note @p other may only be assigned to or destroyed afterwards. + * @since 5.86 + */ + Definition(Definition &&other) noexcept; + + /** * Copy constructor. * Both this definition as well as @p other share the Definition data. */ @@ -105,7 +121,15 @@ public: ~Definition(); /** - * Assignment operator. + * Move assignment operator. + * This definition takes the Definition data from @p other. + * @note @p other may only be assigned to or destroyed afterwards. + * @since 5.86 + */ + Definition &operator=(Definition &&other) noexcept; + + /** + * Copy assignment operator. * Both this definition as well as @p rhs share the Definition data. */ Definition &operator=(const Definition &rhs); diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/definitiondownloader.cpp b/src/libs/3rdparty/syntax-highlighting/src/lib/definitiondownloader.cpp index 3dff1dd436..b16139b731 100644 --- a/src/libs/3rdparty/syntax-highlighting/src/lib/definitiondownloader.cpp +++ b/src/libs/3rdparty/syntax-highlighting/src/lib/definitiondownloader.cpp @@ -51,24 +51,27 @@ void DefinitionDownloaderPrivate::definitionListDownloadFinished(QNetworkReply * while (!parser.atEnd()) { switch (parser.readNext()) { case QXmlStreamReader::StartElement: - if (parser.name() == QLatin1String("Definition")) + if (parser.name() == QLatin1String("Definition")) { updateDefinition(parser); + } break; default: break; } } - if (pendingDownloads == 0) + if (pendingDownloads == 0) { Q_EMIT q->informationMessage(QObject::tr("All syntax definitions are up-to-date.")); + } checkDone(); } void DefinitionDownloaderPrivate::updateDefinition(QXmlStreamReader &parser) { const auto name = parser.attributes().value(QLatin1String("name")); - if (name.isEmpty()) + if (name.isEmpty()) { return; + } auto localDef = repo->definitionForName(name.toString()); if (!localDef.isValid()) { @@ -86,11 +89,13 @@ void DefinitionDownloaderPrivate::updateDefinition(QXmlStreamReader &parser) void DefinitionDownloaderPrivate::downloadDefinition(const QUrl &downloadUrl) { - if (!downloadUrl.isValid()) + if (!downloadUrl.isValid()) { return; + } auto url = downloadUrl; - if (url.scheme() == QLatin1String("http")) + if (url.scheme() == QLatin1String("http")) { url.setScheme(QStringLiteral("https")); + } QNetworkRequest req(url); auto reply = nam->get(req); @@ -133,8 +138,9 @@ void DefinitionDownloaderPrivate::downloadDefinitionFinished(QNetworkReply *repl void DefinitionDownloaderPrivate::checkDone() { if (pendingDownloads == 0) { - if (needsReload) + if (needsReload) { repo->reload(); + } Q_EMIT QTimer::singleShot(0, q, &DefinitionDownloader::done); } diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/definitionref_p.h b/src/libs/3rdparty/syntax-highlighting/src/lib/definitionref_p.h index 25a1a749e4..285fec3e20 100644 --- a/src/libs/3rdparty/syntax-highlighting/src/lib/definitionref_p.h +++ b/src/libs/3rdparty/syntax-highlighting/src/lib/definitionref_p.h @@ -13,7 +13,6 @@ namespace KSyntaxHighlighting { class Definition; class DefinitionData; -class DefinitionPrivate; /** Weak reference for Definition instances. * @@ -21,6 +20,8 @@ class DefinitionPrivate; * in objects hold directly or indirectly by Definition * to avoid reference count loops and thus memory leaks. * + * This class follows the rule of zero. It is implicitly movable and copyable. + * * @internal */ class DefinitionRef @@ -28,7 +29,6 @@ class DefinitionRef public: DefinitionRef(); explicit DefinitionRef(const Definition &def); - ~DefinitionRef(); DefinitionRef &operator=(const Definition &def); Definition definition() const; diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/format.cpp b/src/libs/3rdparty/syntax-highlighting/src/lib/format.cpp index d459ee36d8..bcc64c3c2b 100644 --- a/src/libs/3rdparty/syntax-highlighting/src/lib/format.cpp +++ b/src/libs/3rdparty/syntax-highlighting/src/lib/format.cpp @@ -21,8 +21,9 @@ using namespace KSyntaxHighlighting; static Theme::TextStyle stringToDefaultFormat(QStringView str) { - if (!str.startsWith(QLatin1String("ds"))) + if (!str.startsWith(QLatin1String("ds"))) { return Theme::Normal; + } static const auto idx = Theme::staticMetaObject.indexOfEnumerator("TextStyle"); Q_ASSERT(idx >= 0); @@ -30,8 +31,9 @@ static Theme::TextStyle stringToDefaultFormat(QStringView str) bool ok = false; const auto value = metaEnum.keyToValue(str.mid(2).toLatin1().constData(), &ok); - if (!ok || value < 0) + if (!ok || value < 0) { return Theme::Normal; + } return static_cast<Theme::TextStyle>(value); } @@ -44,8 +46,9 @@ FormatPrivate *FormatPrivate::detachAndGet(Format &format) TextStyleData FormatPrivate::styleOverride(const Theme &theme) const { const auto themeData = ThemeData::get(theme); - if (themeData) + if (themeData) { return themeData->textStyleOverride(definition.definition().name(), name); + } return TextStyleData(); } @@ -113,16 +116,18 @@ bool Format::hasTextColor(const Theme &theme) const QColor Format::textColor(const Theme &theme) const { const auto overrideStyle = d->styleOverride(theme); - if (overrideStyle.textColor) + if (overrideStyle.textColor) { return overrideStyle.textColor; + } return d->style.textColor ? QColor::fromRgba(d->style.textColor) : QColor::fromRgba(theme.textColor(d->defaultStyle)); } QColor Format::selectedTextColor(const Theme &theme) const { const auto overrideStyle = d->styleOverride(theme); - if (overrideStyle.selectedTextColor) + if (overrideStyle.selectedTextColor) { return overrideStyle.selectedTextColor; + } return d->style.selectedTextColor ? QColor::fromRgba(d->style.selectedTextColor) : QColor::fromRgba(theme.selectedTextColor(d->defaultStyle)); } @@ -136,8 +141,9 @@ bool Format::hasBackgroundColor(const Theme &theme) const QColor Format::backgroundColor(const Theme &theme) const { const auto overrideStyle = d->styleOverride(theme); - if (overrideStyle.backgroundColor) + if (overrideStyle.backgroundColor) { return overrideStyle.backgroundColor; + } // use QColor::fromRgba for background QRgb => QColor conversion to avoid unset colors == black! return d->style.backgroundColor ? QColor::fromRgba(d->style.backgroundColor) : QColor::fromRgba(theme.backgroundColor(d->defaultStyle)); @@ -146,8 +152,9 @@ QColor Format::backgroundColor(const Theme &theme) const QColor Format::selectedBackgroundColor(const Theme &theme) const { const auto overrideStyle = d->styleOverride(theme); - if (overrideStyle.selectedBackgroundColor) + if (overrideStyle.selectedBackgroundColor) { return overrideStyle.selectedBackgroundColor; + } // use QColor::fromRgba for background QRgb => QColor conversion to avoid unset colors == black! return d->style.selectedBackgroundColor ? QColor::fromRgba(d->style.selectedBackgroundColor) @@ -157,32 +164,36 @@ QColor Format::selectedBackgroundColor(const Theme &theme) const bool Format::isBold(const Theme &theme) const { const auto overrideStyle = d->styleOverride(theme); - if (overrideStyle.hasBold) + if (overrideStyle.hasBold) { return overrideStyle.bold; + } return d->style.hasBold ? d->style.bold : theme.isBold(d->defaultStyle); } bool Format::isItalic(const Theme &theme) const { const auto overrideStyle = d->styleOverride(theme); - if (overrideStyle.hasItalic) + if (overrideStyle.hasItalic) { return overrideStyle.italic; + } return d->style.hasItalic ? d->style.italic : theme.isItalic(d->defaultStyle); } bool Format::isUnderline(const Theme &theme) const { const auto overrideStyle = d->styleOverride(theme); - if (overrideStyle.hasUnderline) + if (overrideStyle.hasUnderline) { return overrideStyle.underline; + } return d->style.hasUnderline ? d->style.underline : theme.isUnderline(d->defaultStyle); } bool Format::isStrikeThrough(const Theme &theme) const { const auto overrideStyle = d->styleOverride(theme); - if (overrideStyle.hasStrikeThrough) + if (overrideStyle.hasStrikeThrough) { return overrideStyle.strikeThrough; + } return d->style.hasStrikeThrough ? d->style.strikeThrough : theme.isStrikeThrough(d->defaultStyle); } diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/htmlhighlighter.cpp b/src/libs/3rdparty/syntax-highlighting/src/lib/htmlhighlighter.cpp index 5ba421d0e1..688a42d45c 100644 --- a/src/libs/3rdparty/syntax-highlighting/src/lib/htmlhighlighter.cpp +++ b/src/libs/3rdparty/syntax-highlighting/src/lib/htmlhighlighter.cpp @@ -70,10 +70,11 @@ void HtmlHighlighter::highlightFile(const QString &fileName, const QString &titl return; } - if (title.isEmpty()) + if (title.isEmpty()) { highlightData(&f, fi.fileName()); - else + } else { highlightData(&f, title); + } } /** @@ -87,8 +88,9 @@ void HtmlHighlighter::highlightFile(const QString &fileName, const QString &titl */ static QString toHtmlRgbaString(const QColor &color) { - if (color.alpha() == 0xFF) + if (color.alpha() == 0xFF) { return color.name(); + } QString rgba = QStringLiteral("rgba("); rgba.append(QString::number(color.red())); @@ -111,10 +113,11 @@ void HtmlHighlighter::highlightData(QIODevice *dev, const QString &title) } QString htmlTitle; - if (title.isEmpty()) + if (title.isEmpty()) { htmlTitle = QStringLiteral("Kate Syntax Highlighter"); - else + } else { htmlTitle = title.toHtmlEscaped(); + } State state; *d->out << "<!DOCTYPE html>\n"; @@ -125,8 +128,9 @@ void HtmlHighlighter::highlightData(QIODevice *dev, const QString &title) << ")\"/>\n"; *d->out << "</head><body"; *d->out << " style=\"background-color:" << toHtmlRgbaString(QColor::fromRgba(theme().editorColor(Theme::BackgroundColor))); - if (theme().textColor(Theme::Normal)) + if (theme().textColor(Theme::Normal)) { *d->out << ";color:" << toHtmlRgbaString(QColor::fromRgba(theme().textColor(Theme::Normal))); + } *d->out << "\"><pre>\n"; QTextStream in(dev); @@ -148,27 +152,34 @@ void HtmlHighlighter::highlightData(QIODevice *dev, const QString &title) void HtmlHighlighter::applyFormat(int offset, int length, const Format &format) { - if (length == 0) + if (length == 0) { return; + } // collect potential output, cheaper than thinking about "is there any?" QVarLengthArray<QString, 16> formatOutput; - if (format.hasTextColor(theme())) + if (format.hasTextColor(theme())) { formatOutput << QStringLiteral("color:") << toHtmlRgbaString(format.textColor(theme())) << QStringLiteral(";"); - if (format.hasBackgroundColor(theme())) + } + if (format.hasBackgroundColor(theme())) { formatOutput << QStringLiteral("background-color:") << toHtmlRgbaString(format.backgroundColor(theme())) << QStringLiteral(";"); - if (format.isBold(theme())) + } + if (format.isBold(theme())) { formatOutput << QStringLiteral("font-weight:bold;"); - if (format.isItalic(theme())) + } + if (format.isItalic(theme())) { formatOutput << QStringLiteral("font-style:italic;"); - if (format.isUnderline(theme())) + } + if (format.isUnderline(theme())) { formatOutput << QStringLiteral("text-decoration:underline;"); - if (format.isStrikeThrough(theme())) + } + if (format.isStrikeThrough(theme())) { formatOutput << QStringLiteral("text-decoration:line-through;"); + } if (!formatOutput.isEmpty()) { *d->out << "<span style=\""; - for (const auto &out : qAsConst(formatOutput)) { + for (const auto &out : std::as_const(formatOutput)) { *d->out << out; } *d->out << "\">"; diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/keywordlist.cpp b/src/libs/3rdparty/syntax-highlighting/src/lib/keywordlist.cpp index b13e30607b..3a7514897a 100644 --- a/src/libs/3rdparty/syntax-highlighting/src/lib/keywordlist.cpp +++ b/src/libs/3rdparty/syntax-highlighting/src/lib/keywordlist.cpp @@ -16,6 +16,27 @@ using namespace KSyntaxHighlighting; +namespace +{ +struct KeywordComparator { + Qt::CaseSensitivity caseSensitive; + + bool operator()(QStringView a, QStringView b) const + { + if (a.size() < b.size()) { + return true; + } + + if (a.size() > b.size()) { + return false; + } + + return a.compare(b, caseSensitive) < 0; + } +}; + +} + bool KeywordList::contains(QStringView str, Qt::CaseSensitivity caseSensitive) const { /** @@ -26,9 +47,7 @@ bool KeywordList::contains(QStringView str, Qt::CaseSensitivity caseSensitive) c /** * search with right predicate */ - return std::binary_search(vectorToSearch.begin(), vectorToSearch.end(), QStringView(str), [caseSensitive](QStringView a, QStringView b) { - return a.compare(b, caseSensitive) < 0; - }); + return std::binary_search(vectorToSearch.begin(), vectorToSearch.end(), QStringView(str), KeywordComparator{caseSensitive}); } void KeywordList::load(QXmlStreamReader &reader) @@ -85,16 +104,14 @@ void KeywordList::initLookupForCaseSensitivity(Qt::CaseSensitivity caseSensitive * fill vector with refs to keywords */ vectorToSort.reserve(m_keywords.size()); - for (const auto &keyword : qAsConst(m_keywords)) { + for (const auto &keyword : std::as_const(m_keywords)) { vectorToSort.push_back(keyword); } /** * sort with right predicate */ - std::sort(vectorToSort.begin(), vectorToSort.end(), [caseSensitive](QStringView a, QStringView b) { - return a.compare(b, caseSensitive) < 0; - }); + std::sort(vectorToSort.begin(), vectorToSort.end(), KeywordComparator{caseSensitive}); } void KeywordList::resolveIncludeKeywords(DefinitionData &def) diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/ksyntaxhighlighting_export.h b/src/libs/3rdparty/syntax-highlighting/src/lib/ksyntaxhighlighting_export.h deleted file mode 100644 index a39adb5ed6..0000000000 --- a/src/libs/3rdparty/syntax-highlighting/src/lib/ksyntaxhighlighting_export.h +++ /dev/null @@ -1,34 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#pragma once - -#include <QtGlobal> - -#if defined(KSYNTAXHIGHLIGHTING_LIBRARY) -# define KSYNTAXHIGHLIGHTING_EXPORT Q_DECL_EXPORT -#else -# define KSYNTAXHIGHLIGHTING_EXPORT Q_DECL_IMPORT -#endif diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/repository.cpp b/src/libs/3rdparty/syntax-highlighting/src/lib/repository.cpp index 1e3191a7bc..f3b36df459 100644 --- a/src/libs/3rdparty/syntax-highlighting/src/lib/repository.cpp +++ b/src/libs/3rdparty/syntax-highlighting/src/lib/repository.cpp @@ -11,7 +11,7 @@ #include "repository_p.h" #include "theme.h" #include "themedata_p.h" -#include "wildcardmatcher_p.h" +#include "wildcardmatcher.h" #include <QCborMap> #include <QCborValue> @@ -19,15 +19,75 @@ #include <QFile> #include <QFileInfo> #include <QPalette> +#include <QString> +#include <QStringView> #ifndef NO_STANDARD_PATHS #include <QStandardPaths> #endif +#include <algorithm> +#include <iterator> #include <limits> using namespace KSyntaxHighlighting; +namespace +{ +QString fileNameFromFilePath(const QString &filePath) +{ + return QFileInfo{filePath}.fileName(); +} + +auto anyWildcardMatches(QStringView str) +{ + return [str](const Definition &def) { + const auto strings = def.extensions(); + return std::any_of(strings.cbegin(), strings.cend(), [str](QStringView wildcard) { + return WildcardMatcher::exactMatch(str, wildcard); + }); + }; +} + +auto anyMimeTypeEquals(QStringView mimeTypeName) +{ + return [mimeTypeName](const Definition &def) { + const auto strings = def.mimeTypes(); + return std::any_of(strings.cbegin(), strings.cend(), [mimeTypeName](QStringView name) { + return mimeTypeName == name; + }); + }; +} + +// The two function templates below take defs - a map sorted by highlighting name - to be deterministic and independent of translations. + +template<typename UnaryPredicate> +Definition findHighestPriorityDefinitionIf(const QMap<QString, Definition> &defs, UnaryPredicate predicate) +{ + const Definition *match = nullptr; + auto matchPriority = std::numeric_limits<int>::lowest(); + for (const Definition &def : defs) { + const auto defPriority = def.priority(); + if (defPriority > matchPriority && predicate(def)) { + match = &def; + matchPriority = defPriority; + } + } + return match == nullptr ? Definition{} : *match; +} + +template<typename UnaryPredicate> +QVector<Definition> findDefinitionsIf(const QMap<QString, Definition> &defs, UnaryPredicate predicate) +{ + QVector<Definition> matches; + std::copy_if(defs.cbegin(), defs.cend(), std::back_inserter(matches), predicate); + std::stable_sort(matches.begin(), matches.end(), [](const Definition &lhs, const Definition &rhs) { + return lhs.priority() > rhs.priority(); + }); + return matches; +} +} // unnamed namespace + static void initResource() { #ifdef HAS_SYNTAX_RESOURCE @@ -52,8 +112,9 @@ Repository::~Repository() { // reset repo so we can detect in still alive definition instances // that the repo was deleted - for (const auto &def : qAsConst(d->m_sortedDefs)) + for (const auto &def : std::as_const(d->m_sortedDefs)) { DefinitionData::get(def)->repo = nullptr; + } } Definition Repository::definitionForName(const QString &defName) const @@ -61,58 +122,24 @@ Definition Repository::definitionForName(const QString &defName) const return d->m_defs.value(defName); } -static void sortDefinitions(QVector<Definition> &definitions) -{ - std::stable_sort(definitions.begin(), definitions.end(), [](const Definition &lhs, const Definition &rhs) { - return lhs.priority() > rhs.priority(); - }); -} - Definition Repository::definitionForFileName(const QString &fileName) const { - return definitionsForFileName(fileName).value(0); + return findHighestPriorityDefinitionIf(d->m_defs, anyWildcardMatches(fileNameFromFilePath(fileName))); } QVector<Definition> Repository::definitionsForFileName(const QString &fileName) const { - QFileInfo fi(fileName); - const auto name = fi.fileName(); - - // use d->m_defs, sorted map by highlighting name, to be deterministic and independent of translations - QVector<Definition> candidates; - for (const Definition &def : qAsConst(d->m_defs)) { - for (const auto &pattern : def.extensions()) { - if (WildcardMatcher::exactMatch(name, pattern)) { - candidates.push_back(def); - break; - } - } - } - - sortDefinitions(candidates); - return candidates; + return findDefinitionsIf(d->m_defs, anyWildcardMatches(fileNameFromFilePath(fileName))); } Definition Repository::definitionForMimeType(const QString &mimeType) const { - return definitionsForMimeType(mimeType).value(0); + return findHighestPriorityDefinitionIf(d->m_defs, anyMimeTypeEquals(mimeType)); } QVector<Definition> Repository::definitionsForMimeType(const QString &mimeType) const { - // use d->m_defs, sorted map by highlighting name, to be deterministic and independent of translations - QVector<Definition> candidates; - for (const Definition &def : qAsConst(d->m_defs)) { - for (const auto &matchType : def.mimeTypes()) { - if (mimeType == matchType) { - candidates.push_back(def); - break; - } - } - } - - sortDefinitions(candidates); - return candidates; + return findDefinitionsIf(d->m_defs, anyMimeTypeEquals(mimeType)); } QVector<Definition> Repository::definitions() const @@ -127,7 +154,7 @@ QVector<Theme> Repository::themes() const Theme Repository::theme(const QString &themeName) const { - for (const auto &theme : qAsConst(d->m_themes)) { + for (const auto &theme : std::as_const(d->m_themes)) { if (theme.name() == themeName) { return theme; } @@ -138,14 +165,15 @@ Theme Repository::theme(const QString &themeName) const Theme Repository::defaultTheme(Repository::DefaultTheme t) const { - if (t == DarkTheme) + if (t == DarkTheme) { return theme(QLatin1String("Breeze Dark")); + } return theme(QLatin1String("Breeze Light")); } Theme Repository::defaultTheme(Repository::DefaultTheme t) { - return qAsConst(*this).defaultTheme(t); + return std::as_const(*this).defaultTheme(t); } Theme Repository::themeForPalette(const QPalette &palette) const @@ -164,7 +192,7 @@ Theme Repository::themeForPalette(const QPalette &palette) const if (!matchingThemes.empty()) { // if there's multiple, search for one with a matching highlight color const auto highlight = palette.color(QPalette::Highlight); - for (const auto &theme : qAsConst(matchingThemes)) { + for (const auto &theme : std::as_const(matchingThemes)) { auto selection = theme.editorColor(KSyntaxHighlighting::Theme::EditorColorRole::TextSelection); if (selection == highlight.rgb()) { return theme; @@ -179,7 +207,7 @@ Theme Repository::themeForPalette(const QPalette &palette) const Theme Repository::themeForPalette(const QPalette &palette) { - return qAsConst(*this).themeForPalette(palette); + return std::as_const(*this).themeForPalette(palette); } void RepositoryPrivate::load(Repository *repo) @@ -189,29 +217,39 @@ void RepositoryPrivate::load(Repository *repo) // do lookup in standard paths, if not disabled #ifndef NO_STANDARD_PATHS - for (const auto &dir : - QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("org.kde.syntax-highlighting/syntax"), QStandardPaths::LocateDirectory)) + for (const auto &dir : QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, + QStringLiteral("org.kde.syntax-highlighting/syntax"), + QStandardPaths::LocateDirectory)) { loadSyntaxFolder(repo, dir); + } // backward compatibility with Kate - for (const auto &dir : QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("katepart5/syntax"), QStandardPaths::LocateDirectory)) + for (const auto &dir : + QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("katepart5/syntax"), QStandardPaths::LocateDirectory)) { loadSyntaxFolder(repo, dir); + } #endif - // default resources are always used - loadSyntaxFolder(repo, QStringLiteral(":/org.kde.syntax-highlighting/syntax")); + // default resources are always used, this is the one location that has a index cbor file + loadSyntaxFolderFromIndex(repo, QStringLiteral(":/org.kde.syntax-highlighting/syntax")); + + // extra resources provided by 3rdparty libraries/applications + loadSyntaxFolder(repo, QStringLiteral(":/org.kde.syntax-highlighting/syntax-addons")); // user given extra paths - for (const auto &path : qAsConst(m_customSearchPaths)) + for (const auto &path : std::as_const(m_customSearchPaths)) { loadSyntaxFolder(repo, path + QStringLiteral("/syntax")); + } m_sortedDefs.reserve(m_defs.size()); - for (auto it = m_defs.constBegin(); it != m_defs.constEnd(); ++it) + for (auto it = m_defs.constBegin(); it != m_defs.constEnd(); ++it) { m_sortedDefs.push_back(it.value()); + } std::sort(m_sortedDefs.begin(), m_sortedDefs.end(), [](const Definition &left, const Definition &right) { auto comparison = left.translatedSection().compare(right.translatedSection(), Qt::CaseInsensitive); - if (comparison == 0) + if (comparison == 0) { comparison = left.translatedName().compare(right.translatedName(), Qt::CaseInsensitive); + } return comparison < 0; }); @@ -219,54 +257,60 @@ void RepositoryPrivate::load(Repository *repo) // do lookup in standard paths, if not disabled #ifndef NO_STANDARD_PATHS - for (const auto &dir : - QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("org.kde.syntax-highlighting/themes"), QStandardPaths::LocateDirectory)) + for (const auto &dir : QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, + QStringLiteral("org.kde.syntax-highlighting/themes"), + QStandardPaths::LocateDirectory)) { loadThemeFolder(dir); + } #endif // default resources are always used loadThemeFolder(QStringLiteral(":/org.kde.syntax-highlighting/themes")); + // extra resources provided by 3rdparty libraries/applications + loadThemeFolder(QStringLiteral(":/org.kde.syntax-highlighting/themes-addons")); + // user given extra paths - for (const auto &path : qAsConst(m_customSearchPaths)) + for (const auto &path : std::as_const(m_customSearchPaths)) { loadThemeFolder(path + QStringLiteral("/themes")); + } } void RepositoryPrivate::loadSyntaxFolder(Repository *repo, const QString &path) { - if (loadSyntaxFolderFromIndex(repo, path)) - return; - QDirIterator it(path, QStringList() << QLatin1String("*.xml"), QDir::Files); while (it.hasNext()) { Definition def; auto defData = DefinitionData::get(def); defData->repo = repo; - if (defData->loadMetaData(it.next())) + if (defData->loadMetaData(it.next())) { addDefinition(def); + } } } -bool RepositoryPrivate::loadSyntaxFolderFromIndex(Repository *repo, const QString &path) +void RepositoryPrivate::loadSyntaxFolderFromIndex(Repository *repo, const QString &path) { QFile indexFile(path + QLatin1String("/index.katesyntax")); - if (!indexFile.open(QFile::ReadOnly)) - return false; + if (!indexFile.open(QFile::ReadOnly)) { + return; + } const auto indexDoc(QCborValue::fromCbor(indexFile.readAll())); const auto index = indexDoc.toMap(); for (auto it = index.begin(); it != index.end(); ++it) { - if (!it.value().isMap()) + if (!it.value().isMap()) { continue; + } const auto fileName = QString(path + QLatin1Char('/') + it.key().toString()); const auto defMap = it.value().toMap(); Definition def; auto defData = DefinitionData::get(def); defData->repo = repo; - if (defData->loadMetaData(fileName, defMap)) + if (defData->loadMetaData(fileName, defMap)) { addDefinition(def); + } } - return true; } void RepositoryPrivate::addDefinition(const Definition &def) @@ -277,8 +321,9 @@ void RepositoryPrivate::addDefinition(const Definition &def) return; } - if (it.value().version() >= def.version()) + if (it.value().version() >= def.version()) { return; + } m_defs.insert(def.name(), def); } @@ -287,8 +332,9 @@ void RepositoryPrivate::loadThemeFolder(const QString &path) QDirIterator it(path, QStringList() << QLatin1String("*.theme"), QDir::Files); while (it.hasNext()) { auto themeData = std::unique_ptr<ThemeData>(new ThemeData); - if (themeData->load(it.next())) + if (themeData->load(it.next())) { addTheme(Theme(themeData.release())); + } } } @@ -307,15 +353,17 @@ void RepositoryPrivate::addTheme(const Theme &theme) m_themes.insert(it, theme); return; } - if (themeRevision(*it) < themeRevision(theme)) + if (themeRevision(*it) < themeRevision(theme)) { *it = theme; + } } quint16 RepositoryPrivate::foldingRegionId(const QString &defName, const QString &foldName) { const auto it = m_foldingRegionIds.constFind(qMakePair(defName, foldName)); - if (it != m_foldingRegionIds.constEnd()) + if (it != m_foldingRegionIds.constEnd()) { return it.value(); + } m_foldingRegionIds.insert(qMakePair(defName, foldName), ++m_foldingRegionId); return m_foldingRegionId; } @@ -329,8 +377,9 @@ quint16 RepositoryPrivate::nextFormatId() void Repository::reload() { qCDebug(Log) << "Reloading syntax definitions!"; - for (const auto &def : qAsConst(d->m_sortedDefs)) + for (const auto &def : std::as_const(d->m_sortedDefs)) { DefinitionData::get(def)->clear(); + } d->m_defs.clear(); d->m_sortedDefs.clear(); diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/repository.h b/src/libs/3rdparty/syntax-highlighting/src/lib/repository.h index 323407f008..9e19ecda56 100644 --- a/src/libs/3rdparty/syntax-highlighting/src/lib/repository.h +++ b/src/libs/3rdparty/syntax-highlighting/src/lib/repository.h @@ -86,6 +86,11 @@ class Theme; * The internal resource path is ":/org.kde.syntax-highlighting/syntax". * This path should never be touched by other applications. * + * -# Then, all custom files compiled into resources are loaded. + * The resource path is ":/org.kde.syntax-highlighting/syntax-addons". + * This path can be used by other libraries/applications to bundle specialized definitions. + * Per default this path isn't used by the framework itself. + * * -# Finally, the search path can be extended by calling addCustomSearchPath(). * A custom search path can either be a path on disk or again a path to * a Qt resource. @@ -102,6 +107,11 @@ class Theme; * The internal resource path is ":/org.kde.syntax-highlighting/themes". * This path should never be touched by other applications. * + * -# Then, all custom files compiled into resources are loaded. + * The resource path is ":/org.kde.syntax-highlighting/themes-addons". + * This path can be used by other libraries/applications to bundle specialized themes. + * Per default this path isn't used by the framework itself. + * * -# Finally, all Theme%s located in the paths added addCustomSearchPath() * are loaded. * diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/repository_p.h b/src/libs/3rdparty/syntax-highlighting/src/lib/repository_p.h index 447cfae699..abc992358d 100644 --- a/src/libs/3rdparty/syntax-highlighting/src/lib/repository_p.h +++ b/src/libs/3rdparty/syntax-highlighting/src/lib/repository_p.h @@ -29,7 +29,7 @@ public: void load(Repository *repo); void loadSyntaxFolder(Repository *repo, const QString &path); - bool loadSyntaxFolderFromIndex(Repository *repo, const QString &path); + void loadSyntaxFolderFromIndex(Repository *repo, const QString &path); void addDefinition(const Definition &def); diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/rule.cpp b/src/libs/3rdparty/syntax-highlighting/src/lib/rule.cpp index c8d3fa0e63..f4e88b719a 100644 --- a/src/libs/3rdparty/syntax-highlighting/src/lib/rule.cpp +++ b/src/libs/3rdparty/syntax-highlighting/src/lib/rule.cpp @@ -34,10 +34,11 @@ static bool isHexChar(QChar c) return isDigit(c) || (c <= QLatin1Char('f') && QLatin1Char('a') <= c) || (c <= QLatin1Char('F') && QLatin1Char('A') <= c); } -static int matchEscapedChar(const QString &text, int offset) +static int matchEscapedChar(QStringView text, int offset) { - if (text.at(offset) != QLatin1Char('\\') || text.size() < offset + 2) + if (text.at(offset) != QLatin1Char('\\') || text.size() < offset + 2) { return offset; + } const auto c = text.at(offset + 1); switch (c.unicode()) { @@ -59,8 +60,9 @@ static int matchEscapedChar(const QString &text, int offset) // hex encoded character case 'x': if (offset + 2 < text.size() && isHexChar(text.at(offset + 2))) { - if (offset + 3 < text.size() && isHexChar(text.at(offset + 3))) + if (offset + 3 < text.size() && isHexChar(text.at(offset + 3))) { return offset + 4; + } return offset + 3; } return offset; @@ -75,8 +77,9 @@ static int matchEscapedChar(const QString &text, int offset) case '6': case '7': if (offset + 2 < text.size() && isOctalChar(text.at(offset + 2))) { - if (offset + 3 < text.size() && isOctalChar(text.at(offset + 3))) + if (offset + 3 < text.size() && isOctalChar(text.at(offset + 3))) { return offset + 4; + } return offset + 3; } return offset + 2; @@ -116,26 +119,31 @@ bool Rule::load(QXmlStreamReader &reader) Q_ASSERT(reader.tokenType() == QXmlStreamReader::StartElement); m_attribute = reader.attributes().value(QLatin1String("attribute")).toString(); - if (reader.name() != QLatin1String("IncludeRules")) // IncludeRules uses this with a different semantic + if (reader.name() != QLatin1String("IncludeRules")) { // IncludeRules uses this with a different semantic m_context.parse(reader.attributes().value(QLatin1String("context"))); + } m_firstNonSpace = Xml::attrToBool(reader.attributes().value(QLatin1String("firstNonSpace"))); m_lookAhead = Xml::attrToBool(reader.attributes().value(QLatin1String("lookAhead"))); bool colOk = false; m_column = reader.attributes().value(QLatin1String("column")).toInt(&colOk); - if (!colOk) + if (!colOk) { m_column = -1; + } auto regionName = reader.attributes().value(QLatin1String("beginRegion")); - if (!regionName.isEmpty()) + if (!regionName.isEmpty()) { m_beginRegion = FoldingRegion(FoldingRegion::Begin, DefinitionData::get(m_def.definition())->foldingRegionId(regionName.toString())); + } regionName = reader.attributes().value(QLatin1String("endRegion")); - if (!regionName.isEmpty()) + if (!regionName.isEmpty()) { m_endRegion = FoldingRegion(FoldingRegion::End, DefinitionData::get(m_def.definition())->foldingRegionId(regionName.toString())); + } auto result = doLoad(reader); - if (m_lookAhead && m_context.isStay()) + if (m_lookAhead && m_context.isStay()) { result = false; + } // be done with this rule, skip all subelements, e.g. no longer supported sub-rules reader.skipCurrentElement(); @@ -184,42 +192,60 @@ void Rule::loadAdditionalWordDelimiters(QXmlStreamReader &reader) Rule::Ptr Rule::create(QStringView name) { - if (name == QLatin1String("AnyChar")) + if (name == QLatin1String("AnyChar")) { return std::make_shared<AnyChar>(); - if (name == QLatin1String("DetectChar")) + } + if (name == QLatin1String("DetectChar")) { return std::make_shared<DetectChar>(); - if (name == QLatin1String("Detect2Chars")) + } + if (name == QLatin1String("Detect2Chars")) { return std::make_shared<Detect2Char>(); - if (name == QLatin1String("DetectIdentifier")) + } + if (name == QLatin1String("DetectIdentifier")) { return std::make_shared<DetectIdentifier>(); - if (name == QLatin1String("DetectSpaces")) + } + if (name == QLatin1String("DetectSpaces")) { return std::make_shared<DetectSpaces>(); - if (name == QLatin1String("Float")) + } + if (name == QLatin1String("Float")) { return std::make_shared<Float>(); - if (name == QLatin1String("Int")) + } + if (name == QLatin1String("Int")) { return std::make_shared<Int>(); - if (name == QLatin1String("HlCChar")) + } + if (name == QLatin1String("HlCChar")) { return std::make_shared<HlCChar>(); - if (name == QLatin1String("HlCHex")) + } + if (name == QLatin1String("HlCHex")) { return std::make_shared<HlCHex>(); - if (name == QLatin1String("HlCOct")) + } + if (name == QLatin1String("HlCOct")) { return std::make_shared<HlCOct>(); - if (name == QLatin1String("HlCStringChar")) + } + if (name == QLatin1String("HlCStringChar")) { return std::make_shared<HlCStringChar>(); - if (name == QLatin1String("IncludeRules")) + } + if (name == QLatin1String("IncludeRules")) { return std::make_shared<IncludeRules>(); - if (name == QLatin1String("keyword")) + } + if (name == QLatin1String("keyword")) { return std::make_shared<KeywordListRule>(); - if (name == QLatin1String("LineContinue")) + } + if (name == QLatin1String("LineContinue")) { return std::make_shared<LineContinue>(); - if (name == QLatin1String("RangeDetect")) + } + if (name == QLatin1String("RangeDetect")) { return std::make_shared<RangeDetect>(); - if (name == QLatin1String("RegExpr")) + } + if (name == QLatin1String("RegExpr")) { return std::make_shared<RegExpr>(); - if (name == QLatin1String("StringDetect")) + } + if (name == QLatin1String("StringDetect")) { return std::make_shared<StringDetect>(); - if (name == QLatin1String("WordDetect")) + } + if (name == QLatin1String("WordDetect")) { return std::make_shared<WordDetect>(); + } qCWarning(Log) << "Unknown rule type:" << name; return Ptr(nullptr); @@ -233,23 +259,26 @@ bool Rule::isWordDelimiter(QChar c) const bool AnyChar::doLoad(QXmlStreamReader &reader) { m_chars = reader.attributes().value(QLatin1String("String")).toString(); - if (m_chars.size() == 1) + if (m_chars.size() == 1) { qCDebug(Log) << "AnyChar rule with just one char: use DetectChar instead."; + } return !m_chars.isEmpty(); } -MatchResult AnyChar::doMatch(const QString &text, int offset, const QStringList &) const +MatchResult AnyChar::doMatch(QStringView text, int offset, const QStringList &) const { - if (m_chars.contains(text.at(offset))) + if (m_chars.contains(text.at(offset))) { return offset + 1; + } return offset; } bool DetectChar::doLoad(QXmlStreamReader &reader) { const auto s = reader.attributes().value(QLatin1String("char")); - if (s.isEmpty()) + if (s.isEmpty()) { return false; + } m_char = s.at(0); m_dynamic = Xml::attrToBool(reader.attributes().value(QLatin1String("dynamic"))); if (m_dynamic) { @@ -258,18 +287,21 @@ bool DetectChar::doLoad(QXmlStreamReader &reader) return true; } -MatchResult DetectChar::doMatch(const QString &text, int offset, const QStringList &captures) const +MatchResult DetectChar::doMatch(QStringView text, int offset, const QStringList &captures) const { if (m_dynamic) { - if (m_captureIndex == 0 || captures.size() <= m_captureIndex || captures.at(m_captureIndex).isEmpty()) + if (m_captureIndex == 0 || captures.size() <= m_captureIndex || captures.at(m_captureIndex).isEmpty()) { return offset; - if (text.at(offset) == captures.at(m_captureIndex).at(0)) + } + if (text.at(offset) == captures.at(m_captureIndex).at(0)) { return offset + 1; + } return offset; } - if (text.at(offset) == m_char) + if (text.at(offset) == m_char) { return offset + 1; + } return offset; } @@ -277,40 +309,46 @@ bool Detect2Char::doLoad(QXmlStreamReader &reader) { const auto s1 = reader.attributes().value(QLatin1String("char")); const auto s2 = reader.attributes().value(QLatin1String("char1")); - if (s1.isEmpty() || s2.isEmpty()) + if (s1.isEmpty() || s2.isEmpty()) { return false; + } m_char1 = s1.at(0); m_char2 = s2.at(0); return true; } -MatchResult Detect2Char::doMatch(const QString &text, int offset, const QStringList &) const +MatchResult Detect2Char::doMatch(QStringView text, int offset, const QStringList &) const { - if (text.size() - offset < 2) + if (text.size() - offset < 2) { return offset; - if (text.at(offset) == m_char1 && text.at(offset + 1) == m_char2) + } + if (text.at(offset) == m_char1 && text.at(offset + 1) == m_char2) { return offset + 2; + } return offset; } -MatchResult DetectIdentifier::doMatch(const QString &text, int offset, const QStringList &) const +MatchResult DetectIdentifier::doMatch(QStringView text, int offset, const QStringList &) const { - if (!text.at(offset).isLetter() && text.at(offset) != QLatin1Char('_')) + if (!text.at(offset).isLetter() && text.at(offset) != QLatin1Char('_')) { return offset; + } for (int i = offset + 1; i < text.size(); ++i) { const auto c = text.at(i); - if (!c.isLetterOrNumber() && c != QLatin1Char('_')) + if (!c.isLetterOrNumber() && c != QLatin1Char('_')) { return i; + } } return text.size(); } -MatchResult DetectSpaces::doMatch(const QString &text, int offset, const QStringList &) const +MatchResult DetectSpaces::doMatch(QStringView text, int offset, const QStringList &) const { - while (offset < text.size() && text.at(offset).isSpace()) + while (offset < text.size() && text.at(offset).isSpace()) { ++offset; + } return offset; } @@ -320,63 +358,76 @@ bool Float::doLoad(QXmlStreamReader &reader) return true; } -MatchResult Float::doMatch(const QString &text, int offset, const QStringList &) const +MatchResult Float::doMatch(QStringView text, int offset, const QStringList &) const { - if (offset > 0 && !isWordDelimiter(text.at(offset - 1))) + if (offset > 0 && !isWordDelimiter(text.at(offset - 1))) { return offset; + } auto newOffset = offset; - while (newOffset < text.size() && isDigit(text.at(newOffset))) + while (newOffset < text.size() && isDigit(text.at(newOffset))) { ++newOffset; + } - if (newOffset >= text.size() || text.at(newOffset) != QLatin1Char('.')) + if (newOffset >= text.size() || text.at(newOffset) != QLatin1Char('.')) { return offset; + } ++newOffset; - while (newOffset < text.size() && isDigit(text.at(newOffset))) + while (newOffset < text.size() && isDigit(text.at(newOffset))) { ++newOffset; + } - if (newOffset == offset + 1) // we only found a decimal point + if (newOffset == offset + 1) { // we only found a decimal point return offset; + } auto expOffset = newOffset; - if (expOffset >= text.size() || (text.at(expOffset) != QLatin1Char('e') && text.at(expOffset) != QLatin1Char('E'))) + if (expOffset >= text.size() || (text.at(expOffset) != QLatin1Char('e') && text.at(expOffset) != QLatin1Char('E'))) { return newOffset; + } ++expOffset; - if (expOffset < text.size() && (text.at(expOffset) == QLatin1Char('+') || text.at(expOffset) == QLatin1Char('-'))) + if (expOffset < text.size() && (text.at(expOffset) == QLatin1Char('+') || text.at(expOffset) == QLatin1Char('-'))) { ++expOffset; + } bool foundExpDigit = false; while (expOffset < text.size() && isDigit(text.at(expOffset))) { ++expOffset; foundExpDigit = true; } - if (!foundExpDigit) + if (!foundExpDigit) { return newOffset; + } return expOffset; } -MatchResult HlCChar::doMatch(const QString &text, int offset, const QStringList &) const +MatchResult HlCChar::doMatch(QStringView text, int offset, const QStringList &) const { - if (text.size() < offset + 3) + if (text.size() < offset + 3) { return offset; + } - if (text.at(offset) != QLatin1Char('\'') || text.at(offset + 1) == QLatin1Char('\'')) + if (text.at(offset) != QLatin1Char('\'') || text.at(offset + 1) == QLatin1Char('\'')) { return offset; + } auto newOffset = matchEscapedChar(text, offset + 1); if (newOffset == offset + 1) { - if (text.at(newOffset) == QLatin1Char('\\')) + if (text.at(newOffset) == QLatin1Char('\\')) { return offset; - else + } else { ++newOffset; + } } - if (newOffset >= text.size()) + if (newOffset >= text.size()) { return offset; + } - if (text.at(newOffset) == QLatin1Char('\'')) + if (text.at(newOffset) == QLatin1Char('\'')) { return newOffset + 1; + } return offset; } @@ -387,23 +438,28 @@ bool HlCHex::doLoad(QXmlStreamReader &reader) return true; } -MatchResult HlCHex::doMatch(const QString &text, int offset, const QStringList &) const +MatchResult HlCHex::doMatch(QStringView text, int offset, const QStringList &) const { - if (offset > 0 && !isWordDelimiter(text.at(offset - 1))) + if (offset > 0 && !isWordDelimiter(text.at(offset - 1))) { return offset; + } - if (text.size() < offset + 3) + if (text.size() < offset + 3) { return offset; + } - if (text.at(offset) != QLatin1Char('0') || (text.at(offset + 1) != QLatin1Char('x') && text.at(offset + 1) != QLatin1Char('X'))) + if (text.at(offset) != QLatin1Char('0') || (text.at(offset + 1) != QLatin1Char('x') && text.at(offset + 1) != QLatin1Char('X'))) { return offset; + } - if (!isHexChar(text.at(offset + 2))) + if (!isHexChar(text.at(offset + 2))) { return offset; + } offset += 3; - while (offset < text.size() && isHexChar(text.at(offset))) + while (offset < text.size() && isHexChar(text.at(offset))) { ++offset; + } // TODO Kate matches U/L suffix, QtC does not? @@ -416,28 +472,33 @@ bool HlCOct::doLoad(QXmlStreamReader &reader) return true; } -MatchResult HlCOct::doMatch(const QString &text, int offset, const QStringList &) const +MatchResult HlCOct::doMatch(QStringView text, int offset, const QStringList &) const { - if (offset > 0 && !isWordDelimiter(text.at(offset - 1))) + if (offset > 0 && !isWordDelimiter(text.at(offset - 1))) { return offset; + } - if (text.size() < offset + 2) + if (text.size() < offset + 2) { return offset; + } - if (text.at(offset) != QLatin1Char('0')) + if (text.at(offset) != QLatin1Char('0')) { return offset; + } - if (!isOctalChar(text.at(offset + 1))) + if (!isOctalChar(text.at(offset + 1))) { return offset; + } offset += 2; - while (offset < text.size() && isOctalChar(text.at(offset))) + while (offset < text.size() && isOctalChar(text.at(offset))) { ++offset; + } return offset; } -MatchResult HlCStringChar::doMatch(const QString &text, int offset, const QStringList &) const +MatchResult HlCStringChar::doMatch(QStringView text, int offset, const QStringList &) const { return matchEscapedChar(text, offset); } @@ -461,17 +522,19 @@ bool IncludeRules::doLoad(QXmlStreamReader &reader) { const auto s = reader.attributes().value(QLatin1String("context")); const auto split = s.split(QString::fromLatin1("##"), Qt::KeepEmptyParts); - if (split.isEmpty()) + if (split.isEmpty()) { return false; + } m_contextName = split.at(0).toString(); - if (split.size() > 1) + if (split.size() > 1) { m_defName = split.at(1).toString(); + } m_includeAttribute = Xml::attrToBool(reader.attributes().value(QLatin1String("includeAttrib"))); return !m_contextName.isEmpty() || !m_defName.isEmpty(); } -MatchResult IncludeRules::doMatch(const QString &text, int offset, const QStringList &) const +MatchResult IncludeRules::doMatch(QStringView text, int offset, const QStringList &) const { Q_UNUSED(text); qCWarning(Log) << "Unresolved include rule for" << m_contextName << "##" << m_defName; @@ -484,13 +547,15 @@ bool Int::doLoad(QXmlStreamReader &reader) return true; } -MatchResult Int::doMatch(const QString &text, int offset, const QStringList &) const +MatchResult Int::doMatch(QStringView text, int offset, const QStringList &) const { - if (offset > 0 && !isWordDelimiter(text.at(offset - 1))) + if (offset > 0 && !isWordDelimiter(text.at(offset - 1))) { return offset; + } - while (offset < text.size() && isDigit(text.at(offset))) + while (offset < text.size() && isDigit(text.at(offset))) { ++offset; + } return offset; } @@ -522,21 +587,24 @@ bool KeywordListRule::doLoad(QXmlStreamReader &reader) return !m_keywordList->isEmpty(); } -MatchResult KeywordListRule::doMatch(const QString &text, int offset, const QStringList &) const +MatchResult KeywordListRule::doMatch(QStringView text, int offset, const QStringList &) const { auto newOffset = offset; - while (text.size() > newOffset && !isWordDelimiter(text.at(newOffset))) + while (text.size() > newOffset && !isWordDelimiter(text.at(newOffset))) { ++newOffset; - if (newOffset == offset) + } + if (newOffset == offset) { return offset; + } if (m_hasCaseSensitivityOverride) { - if (m_keywordList->contains(QStringView(text).mid(offset, newOffset - offset), - m_caseSensitivityOverride)) + if (m_keywordList->contains(text.mid(offset, newOffset - offset), m_caseSensitivityOverride)) { return newOffset; + } } else { - if (m_keywordList->contains(QStringView(text).mid(offset, newOffset - offset))) + if (m_keywordList->contains(text.mid(offset, newOffset - offset))) { return newOffset; + } } // we don't match, but we can skip until newOffset as we can't start a keyword in-between @@ -546,17 +614,19 @@ MatchResult KeywordListRule::doMatch(const QString &text, int offset, const QStr bool LineContinue::doLoad(QXmlStreamReader &reader) { const auto s = reader.attributes().value(QLatin1String("char")); - if (s.isEmpty()) + if (s.isEmpty()) { m_char = QLatin1Char('\\'); - else + } else { m_char = s.at(0); + } return true; } -MatchResult LineContinue::doMatch(const QString &text, int offset, const QStringList &) const +MatchResult LineContinue::doMatch(QStringView text, int offset, const QStringList &) const { - if (offset == text.size() - 1 && text.at(offset) == m_char) + if (offset == text.size() - 1 && text.at(offset) == m_char) { return offset + 1; + } return offset; } @@ -564,24 +634,28 @@ bool RangeDetect::doLoad(QXmlStreamReader &reader) { const auto s1 = reader.attributes().value(QLatin1String("char")); const auto s2 = reader.attributes().value(QLatin1String("char1")); - if (s1.isEmpty() || s2.isEmpty()) + if (s1.isEmpty() || s2.isEmpty()) { return false; + } m_begin = s1.at(0); m_end = s2.at(0); return true; } -MatchResult RangeDetect::doMatch(const QString &text, int offset, const QStringList &) const +MatchResult RangeDetect::doMatch(QStringView text, int offset, const QStringList &) const { - if (text.size() - offset < 2) + if (text.size() - offset < 2) { return offset; - if (text.at(offset) != m_begin) + } + if (text.at(offset) != m_begin) { return offset; + } auto newOffset = offset + 1; while (newOffset < text.size()) { - if (text.at(newOffset) == m_end) + if (text.at(newOffset) == m_end) { return newOffset + 1; + } ++newOffset; } return offset; @@ -596,7 +670,9 @@ bool RegExpr::doLoad(QXmlStreamReader &reader) m_regexp.setPatternOptions((isMinimal ? QRegularExpression::InvertedGreedinessOption : QRegularExpression::NoPatternOption) | (isCaseInsensitive ? QRegularExpression::CaseInsensitiveOption : QRegularExpression::NoPatternOption) // DontCaptureOption is removed by resolvePostProcessing() when necessary - | QRegularExpression::DontCaptureOption); + | QRegularExpression::DontCaptureOption + // ensure Unicode support is enabled + | QRegularExpression::UseUnicodePropertiesOption); m_dynamic = Xml::attrToBool(reader.attributes().value(QLatin1String("dynamic"))); @@ -605,8 +681,9 @@ bool RegExpr::doLoad(QXmlStreamReader &reader) void KSyntaxHighlighting::RegExpr::resolvePostProcessing() { - if (m_isResolved) + if (m_isResolved) { return; + } m_isResolved = true; bool hasCapture = false; @@ -641,7 +718,7 @@ void KSyntaxHighlighting::RegExpr::resolvePostProcessing() } } -MatchResult RegExpr::doMatch(const QString &text, int offset, const QStringList &captures) const +MatchResult RegExpr::doMatch(QStringView text, int offset, const QStringList &captures) const { /** * for dynamic case: create new pattern with right instantiation @@ -651,7 +728,11 @@ MatchResult RegExpr::doMatch(const QString &text, int offset, const QStringList /** * match the pattern */ +#if QT_VERSION < QT_VERSION_CHECK(5, 15, 2) + const auto result = regexp.match(text.toString(), 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 @@ -683,16 +764,16 @@ bool StringDetect::doLoad(QXmlStreamReader &reader) return !m_string.isEmpty(); } -MatchResult StringDetect::doMatch(const QString &text, int offset, const QStringList &captures) const +MatchResult StringDetect::doMatch(QStringView text, int offset, const QStringList &captures) const { /** * for dynamic case: create new pattern with right instantiation */ const auto &pattern = m_dynamic ? replaceCaptures(m_string, captures, false) : m_string; - if (offset + pattern.size() <= text.size() - && QStringView(text).mid(offset, pattern.size()).compare(pattern, m_caseSensitivity) == 0) + if (offset + pattern.size() <= text.size() && text.mid(offset, pattern.size()).compare(pattern, m_caseSensitivity) == 0) { return offset + pattern.size(); + } return offset; } @@ -704,23 +785,27 @@ bool WordDetect::doLoad(QXmlStreamReader &reader) return !m_word.isEmpty(); } -MatchResult WordDetect::doMatch(const QString &text, int offset, const QStringList &) const +MatchResult WordDetect::doMatch(QStringView text, int offset, const QStringList &) const { - if (text.size() - offset < m_word.size()) + if (text.size() - offset < m_word.size()) { return offset; + } /** * detect delimiter characters on the inner and outer boundaries of the string * NOTE: m_word isn't empty */ - if (offset > 0 && !isWordDelimiter(text.at(offset - 1)) && !isWordDelimiter(text.at(offset))) + if (offset > 0 && !isWordDelimiter(text.at(offset - 1)) && !isWordDelimiter(text.at(offset))) { return offset; + } - if (QStringView(text).mid(offset, m_word.size()).compare(m_word, m_caseSensitivity) != 0) + if (text.mid(offset, m_word.size()).compare(m_word, m_caseSensitivity) != 0) { return offset; + } - if (text.size() == offset + m_word.size() || isWordDelimiter(text.at(offset + m_word.size())) || isWordDelimiter(text.at(offset + m_word.size() - 1))) + if (text.size() == offset + m_word.size() || isWordDelimiter(text.at(offset + m_word.size())) || isWordDelimiter(text.at(offset + m_word.size() - 1))) { return offset + m_word.size(); + } return offset; } diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/rule_p.h b/src/libs/3rdparty/syntax-highlighting/src/lib/rule_p.h index 22c786eaa2..374eb87dfa 100644 --- a/src/libs/3rdparty/syntax-highlighting/src/lib/rule_p.h +++ b/src/libs/3rdparty/syntax-highlighting/src/lib/rule_p.h @@ -87,7 +87,7 @@ public: { } - virtual MatchResult doMatch(const QString &text, int offset, const QStringList &captures) const = 0; + virtual MatchResult doMatch(QStringView text, int offset, const QStringList &captures) const = 0; static Rule::Ptr create(QStringView name); @@ -121,58 +121,58 @@ protected: bool m_dynamic = false; }; -class AnyChar : public Rule +class AnyChar final : public Rule { protected: bool doLoad(QXmlStreamReader &reader) override; - MatchResult doMatch(const QString &text, int offset, const QStringList &) const override; + MatchResult doMatch(QStringView text, int offset, const QStringList &) const override; private: QString m_chars; }; -class DetectChar : public Rule +class DetectChar final : public Rule { protected: bool doLoad(QXmlStreamReader &reader) override; - MatchResult doMatch(const QString &text, int offset, const QStringList &captures) const override; + MatchResult doMatch(QStringView text, int offset, const QStringList &captures) const override; private: QChar m_char; int m_captureIndex = 0; }; -class Detect2Char : public Rule +class Detect2Char final : public Rule { protected: bool doLoad(QXmlStreamReader &reader) override; - MatchResult doMatch(const QString &text, int offset, const QStringList &captures) const override; + MatchResult doMatch(QStringView text, int offset, const QStringList &captures) const override; private: QChar m_char1; QChar m_char2; }; -class DetectIdentifier : public Rule +class DetectIdentifier final : public Rule { protected: - MatchResult doMatch(const QString &text, int offset, const QStringList &) const override; + MatchResult doMatch(QStringView text, int offset, const QStringList &) const override; }; -class DetectSpaces : public Rule +class DetectSpaces final : public Rule { protected: - MatchResult doMatch(const QString &text, int offset, const QStringList &) const override; + MatchResult doMatch(QStringView text, int offset, const QStringList &) const override; }; -class Float : public Rule +class Float final : public Rule { protected: bool doLoad(QXmlStreamReader &reader) override; - MatchResult doMatch(const QString &text, int offset, const QStringList &) const override; + MatchResult doMatch(QStringView text, int offset, const QStringList &) const override; }; -class IncludeRules : public Rule +class IncludeRules final : public Rule { public: QString contextName() const; @@ -181,7 +181,7 @@ public: protected: bool doLoad(QXmlStreamReader &reader) override; - MatchResult doMatch(const QString &text, int offset, const QStringList &) const override; + MatchResult doMatch(QStringView text, int offset, const QStringList &) const override; private: QString m_contextName; @@ -189,44 +189,44 @@ private: bool m_includeAttribute; }; -class Int : public Rule +class Int final : public Rule { protected: bool doLoad(QXmlStreamReader &reader) override; - MatchResult doMatch(const QString &text, int offset, const QStringList &captures) const override; + MatchResult doMatch(QStringView text, int offset, const QStringList &captures) const override; }; -class HlCChar : public Rule +class HlCChar final : public Rule { protected: - MatchResult doMatch(const QString &text, int offset, const QStringList &) const override; + MatchResult doMatch(QStringView text, int offset, const QStringList &) const override; }; -class HlCHex : public Rule +class HlCHex final : public Rule { protected: bool doLoad(QXmlStreamReader &reader) override; - MatchResult doMatch(const QString &text, int offset, const QStringList &) const override; + MatchResult doMatch(QStringView text, int offset, const QStringList &) const override; }; -class HlCOct : public Rule +class HlCOct final : public Rule { protected: bool doLoad(QXmlStreamReader &reader) override; - MatchResult doMatch(const QString &text, int offset, const QStringList &) const override; + MatchResult doMatch(QStringView text, int offset, const QStringList &) const override; }; -class HlCStringChar : public Rule +class HlCStringChar final : public Rule { protected: - MatchResult doMatch(const QString &text, int offset, const QStringList &) const override; + MatchResult doMatch(QStringView text, int offset, const QStringList &) const override; }; -class KeywordListRule : public Rule +class KeywordListRule final : public Rule { protected: bool doLoad(QXmlStreamReader &reader) override; - MatchResult doMatch(const QString &text, int offset, const QStringList &) const override; + MatchResult doMatch(QStringView text, int offset, const QStringList &) const override; private: KeywordList *m_keywordList; @@ -234,55 +234,55 @@ private: Qt::CaseSensitivity m_caseSensitivityOverride; }; -class LineContinue : public Rule +class LineContinue final : public Rule { protected: bool doLoad(QXmlStreamReader &reader) override; - MatchResult doMatch(const QString &text, int offset, const QStringList &) const override; + MatchResult doMatch(QStringView text, int offset, const QStringList &) const override; private: QChar m_char; }; -class RangeDetect : public Rule +class RangeDetect final : public Rule { protected: bool doLoad(QXmlStreamReader &reader) override; - MatchResult doMatch(const QString &text, int offset, const QStringList &) const override; + MatchResult doMatch(QStringView text, int offset, const QStringList &) const override; private: QChar m_begin; QChar m_end; }; -class RegExpr : public Rule +class RegExpr final : public Rule { protected: void resolvePostProcessing() override; bool doLoad(QXmlStreamReader &reader) override; - MatchResult doMatch(const QString &text, int offset, const QStringList &captures) const override; + MatchResult doMatch(QStringView text, int offset, const QStringList &captures) const override; private: QRegularExpression m_regexp; bool m_isResolved = false; }; -class StringDetect : public Rule +class StringDetect final : public Rule { protected: bool doLoad(QXmlStreamReader &reader) override; - MatchResult doMatch(const QString &text, int offset, const QStringList &captures) const override; + MatchResult doMatch(QStringView text, int offset, const QStringList &captures) const override; private: QString m_string; Qt::CaseSensitivity m_caseSensitivity; }; -class WordDetect : public Rule +class WordDetect final : public Rule { protected: bool doLoad(QXmlStreamReader &reader) override; - MatchResult doMatch(const QString &text, int offset, const QStringList &captures) const override; + MatchResult doMatch(QStringView text, int offset, const QStringList &captures) const override; private: QString m_word; diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/state.cpp b/src/libs/3rdparty/syntax-highlighting/src/lib/state.cpp index f9b4f4b4ab..ea21fef215 100644 --- a/src/libs/3rdparty/syntax-highlighting/src/lib/state.cpp +++ b/src/libs/3rdparty/syntax-highlighting/src/lib/state.cpp @@ -104,7 +104,8 @@ bool State::operator!=(const State &other) const bool State::indentationBasedFoldingEnabled() const { - if (!d || d->m_contextStack.isEmpty()) + if (!d || d->m_contextStack.isEmpty()) { return false; + } return d->m_contextStack.last().first->indentationBasedFoldingEnabled(); } diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/syntaxhighlighter.cpp b/src/libs/3rdparty/syntax-highlighting/src/lib/syntaxhighlighter.cpp index d0c4ee98ae..41551e96da 100644 --- a/src/libs/3rdparty/syntax-highlighting/src/lib/syntaxhighlighter.cpp +++ b/src/libs/3rdparty/syntax-highlighting/src/lib/syntaxhighlighter.cpp @@ -37,11 +37,13 @@ public: FoldingRegion SyntaxHighlighterPrivate::foldingRegion(const QTextBlock &startBlock) { const auto data = dynamic_cast<TextBlockUserData *>(startBlock.userData()); - if (!data) + if (!data) { return FoldingRegion(); + } for (int i = data->foldingRegions.size() - 1; i >= 0; --i) { - if (data->foldingRegions.at(i).type() == FoldingRegion::Begin) + if (data->foldingRegions.at(i).type() == FoldingRegion::Begin) { return data->foldingRegions.at(i); + } } return FoldingRegion(); } @@ -68,8 +70,9 @@ void SyntaxHighlighter::setDefinition(const Definition &def) { const auto needsRehighlight = definition() != def; AbstractHighlighter::setDefinition(def); - if (needsRehighlight) + if (needsRehighlight) { rehighlight(); + } } bool SyntaxHighlighter::startsFoldingRegion(const QTextBlock &startBlock) const @@ -86,17 +89,21 @@ QTextBlock SyntaxHighlighter::findFoldingRegionEnd(const QTextBlock &startBlock) while (block.isValid()) { block = block.next(); const auto data = dynamic_cast<TextBlockUserData *>(block.userData()); - if (!data) + if (!data) { continue; + } for (auto it = data->foldingRegions.constBegin(); it != data->foldingRegions.constEnd(); ++it) { - if ((*it).id() != region.id()) + if ((*it).id() != region.id()) { continue; - if ((*it).type() == FoldingRegion::End) + } + if ((*it).type() == FoldingRegion::End) { --depth; - else if ((*it).type() == FoldingRegion::Begin) + } else if ((*it).type() == FoldingRegion::Begin) { ++depth; - if (depth == 0) + } + if (depth == 0) { return block; + } } } @@ -111,8 +118,9 @@ void SyntaxHighlighter::highlightBlock(const QString &text) if (currentBlock().position() > 0) { const auto prevBlock = currentBlock().previous(); const auto prevData = dynamic_cast<TextBlockUserData *>(prevBlock.userData()); - if (prevData) + if (prevData) { state = prevData->state; + } } d->foldingRegions.clear(); state = highlightLine(text, state); @@ -126,35 +134,43 @@ void SyntaxHighlighter::highlightBlock(const QString &text) return; } - if (data->state == state && data->foldingRegions == d->foldingRegions) // we ended up in the same state, so we are done here + if (data->state == state && data->foldingRegions == d->foldingRegions) { // we ended up in the same state, so we are done here return; + } data->state = state; data->foldingRegions = d->foldingRegions; const auto nextBlock = currentBlock().next(); - if (nextBlock.isValid()) + if (nextBlock.isValid()) { QMetaObject::invokeMethod(this, "rehighlightBlock", Qt::QueuedConnection, Q_ARG(QTextBlock, nextBlock)); + } } void SyntaxHighlighter::applyFormat(int offset, int length, const KSyntaxHighlighting::Format &format) { - if (length == 0) + if (length == 0) { return; + } QTextCharFormat tf; // always set the foreground color to avoid palette issues tf.setForeground(format.textColor(theme())); - if (format.hasBackgroundColor(theme())) + if (format.hasBackgroundColor(theme())) { tf.setBackground(format.backgroundColor(theme())); - if (format.isBold(theme())) + } + if (format.isBold(theme())) { tf.setFontWeight(QFont::Bold); - if (format.isItalic(theme())) + } + if (format.isItalic(theme())) { tf.setFontItalic(true); - if (format.isUnderline(theme())) + } + if (format.isUnderline(theme())) { tf.setFontUnderline(true); - if (format.isStrikeThrough(theme())) + } + if (format.isStrikeThrough(theme())) { tf.setFontStrikeOut(true); + } QSyntaxHighlighter::setFormat(offset, length, tf); } @@ -165,13 +181,15 @@ void SyntaxHighlighter::applyFolding(int offset, int length, FoldingRegion regio Q_UNUSED(length); Q_D(SyntaxHighlighter); - if (region.type() == FoldingRegion::Begin) + if (region.type() == FoldingRegion::Begin) { d->foldingRegions.push_back(region); + } if (region.type() == FoldingRegion::End) { for (int i = d->foldingRegions.size() - 1; i >= 0; --i) { - if (d->foldingRegions.at(i).id() != region.id() || d->foldingRegions.at(i).type() != FoldingRegion::Begin) + if (d->foldingRegions.at(i).id() != region.id() || d->foldingRegions.at(i).type() != FoldingRegion::Begin) { continue; + } d->foldingRegions.remove(i); return; } diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/theme.h b/src/libs/3rdparty/syntax-highlighting/src/lib/theme.h index 076e8d0318..37f9de1694 100644 --- a/src/libs/3rdparty/syntax-highlighting/src/lib/theme.h +++ b/src/libs/3rdparty/syntax-highlighting/src/lib/theme.h @@ -64,6 +64,8 @@ class RepositoryPrivate; class KSYNTAXHIGHLIGHTING_EXPORT Theme { Q_GADGET + Q_PROPERTY(QString name READ name) + Q_PROPERTY(QString translatedName READ translatedName) public: // TODO KF6: // - make TextStyle an enum class diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/themedata.cpp b/src/libs/3rdparty/syntax-highlighting/src/lib/themedata.cpp index 2919a31a6e..f9c386bc2a 100644 --- a/src/libs/3rdparty/syntax-highlighting/src/lib/themedata.cpp +++ b/src/libs/3rdparty/syntax-highlighting/src/lib/themedata.cpp @@ -160,8 +160,9 @@ bool ThemeData::load(const QString &filePath) for (auto it = customStyles.begin(); it != customStyles.end(); ++it) { const auto obj = it.value().toObject(); auto &overrideStyle = m_textStyleOverrides[it.key()]; - for (auto it2 = obj.begin(); it2 != obj.end(); ++it2) + for (auto it2 = obj.begin(); it2 != obj.end(); ++it2) { overrideStyle.insert(it2.key(), readThemeData(it2.value().toObject())); + } } return true; diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/wildcardmatcher.cpp b/src/libs/3rdparty/syntax-highlighting/src/lib/wildcardmatcher.cpp index 82d3e4ea80..98daff19d6 100644 --- a/src/libs/3rdparty/syntax-highlighting/src/lib/wildcardmatcher.cpp +++ b/src/libs/3rdparty/syntax-highlighting/src/lib/wildcardmatcher.cpp @@ -4,14 +4,16 @@ SPDX-License-Identifier: MIT */ -#include "wildcardmatcher_p.h" +#include "wildcardmatcher.h" using namespace KSyntaxHighlighting; #include <QChar> -#include <QString> +#include <QStringView> -static bool exactMatch(const QString &candidate, const QString &wildcard, int candidatePosFromRight, int wildcardPosFromRight, bool caseSensitive = true) +namespace +{ +bool wildcardMatch(QStringView candidate, QStringView wildcard, int candidatePosFromRight, int wildcardPosFromRight) { for (; wildcardPosFromRight >= 0; wildcardPosFromRight--) { const auto ch = wildcard.at(wildcardPosFromRight).unicode(); @@ -27,7 +29,7 @@ static bool exactMatch(const QString &candidate, const QString &wildcard, int ca // Eat all we can and go back as far as we have to for (int j = -1; j <= candidatePosFromRight; j++) { - if (exactMatch(candidate, wildcard, j, wildcardPosFromRight - 1)) { + if (wildcardMatch(candidate, wildcard, j, wildcardPosFromRight - 1)) { return true; } } @@ -47,18 +49,19 @@ static bool exactMatch(const QString &candidate, const QString &wildcard, int ca } const auto candidateCh = candidate.at(candidatePosFromRight).unicode(); - const auto match = caseSensitive ? (candidateCh == ch) : (QChar::toLower(candidateCh) == QChar::toLower(ch)); - if (match) { + if (candidateCh == ch) { candidatePosFromRight--; } else { return false; } } } - return true; + return candidatePosFromRight == -1; } -bool WildcardMatcher::exactMatch(const QString &candidate, const QString &wildcard, bool caseSensitive) +} // unnamed namespace + +bool WildcardMatcher::exactMatch(QStringView candidate, QStringView wildcard) { - return ::exactMatch(candidate, wildcard, candidate.length() - 1, wildcard.length() - 1, caseSensitive); + return ::wildcardMatch(candidate, wildcard, candidate.length() - 1, wildcard.length() - 1); } diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/wildcardmatcher.h b/src/libs/3rdparty/syntax-highlighting/src/lib/wildcardmatcher.h new file mode 100644 index 0000000000..4042de3788 --- /dev/null +++ b/src/libs/3rdparty/syntax-highlighting/src/lib/wildcardmatcher.h @@ -0,0 +1,33 @@ +/* + SPDX-FileCopyrightText: 2007 Sebastian Pipping <webmaster@hartwork.org> + + SPDX-License-Identifier: MIT +*/ + +#ifndef KSYNTAXHIGHLIGHTING_WILDCARDMATCHER_H +#define KSYNTAXHIGHLIGHTING_WILDCARDMATCHER_H + +#include "ksyntaxhighlighting_export.h" + +#include <QStringView> + +namespace KSyntaxHighlighting +{ +namespace WildcardMatcher +{ +/** + * Matches a string against a given wildcard case-sensitively. + * The wildcard supports '*' (".*" in regex) and '?' ("." in regex), not more. + * + * @param candidate Text to match + * @param wildcard Wildcard to use + * @return True for an exact match, false otherwise + * + * @since 5.86 + */ +KSYNTAXHIGHLIGHTING_EXPORT bool exactMatch(QStringView candidate, QStringView wildcard); +} + +} + +#endif // KSYNTAXHIGHLIGHTING_WILDCARDMATCHER_H diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/worddelimiters.cpp b/src/libs/3rdparty/syntax-highlighting/src/lib/worddelimiters.cpp index 634eeb70bb..f9079ea1f3 100644 --- a/src/libs/3rdparty/syntax-highlighting/src/lib/worddelimiters.cpp +++ b/src/libs/3rdparty/syntax-highlighting/src/lib/worddelimiters.cpp @@ -11,15 +11,17 @@ using namespace KSyntaxHighlighting; WordDelimiters::WordDelimiters() : asciiDelimiters{} { - for (const char *p = "\t !%&()*+,-./:;<=>?[\\]^{|}~"; *p; ++p) + for (const char *p = "\t !%&()*+,-./:;<=>?[\\]^{|}~"; *p; ++p) { // int(*p) fix -Wchar-subscripts asciiDelimiters[int(*p)] = true; + } } bool WordDelimiters::contains(QChar c) const { - if (c.unicode() < 128) + if (c.unicode() < 128) { return asciiDelimiters[c.unicode()]; + } // perf tells contains is MUCH faster than binary search here, very short array return notAsciiDelimiters.contains(c); } diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/worddelimiters_p.h b/src/libs/3rdparty/syntax-highlighting/src/lib/worddelimiters_p.h index 3fa5db10a4..c1afaaa6bb 100644 --- a/src/libs/3rdparty/syntax-highlighting/src/lib/worddelimiters_p.h +++ b/src/libs/3rdparty/syntax-highlighting/src/lib/worddelimiters_p.h @@ -12,7 +12,7 @@ namespace KSyntaxHighlighting { /** - * Repesents a list of character that separates 2 words. + * Represents a list of character that separates 2 words. * * Default delimiters are .():!+*,-<=>%&/;?[]^{|}~\, space (' ') and tabulator ('\t'). * diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/xml_p.h b/src/libs/3rdparty/syntax-highlighting/src/lib/xml_p.h index 5aae9eebb5..2e1dd25cc8 100644 --- a/src/libs/3rdparty/syntax-highlighting/src/lib/xml_p.h +++ b/src/libs/3rdparty/syntax-highlighting/src/lib/xml_p.h @@ -17,7 +17,7 @@ namespace Xml /** Parse a xs:boolean attribute. */ inline bool attrToBool(QStringView str) { - return str == QLatin1String("1") || str.compare(QString("true"), Qt::CaseInsensitive) == 0; + return str == QStringLiteral("1") || str.compare(QStringLiteral("true"), Qt::CaseInsensitive) == 0; } } |