aboutsummaryrefslogtreecommitdiffstats
path: root/src/libs/3rdparty/syntax-highlighting/src
diff options
context:
space:
mode:
authorDavid Schulz <david.schulz@qt.io>2024-02-13 05:18:33 +0100
committerDavid Schulz <david.schulz@qt.io>2024-02-16 06:28:19 +0000
commit2ceb1e2ad7be8b4d6ec2856da97530723cde7eb8 (patch)
tree86576b15a754e0ea0127f675bc24c2edfcd254a9 /src/libs/3rdparty/syntax-highlighting/src
parentf1f4422dcea46d982feaca177c7b18aedd79486a (diff)
TextEditor: update ksyntaxhighlighting engine to v5.249.0
Task-number: QTCREATORBUG-22558 Change-Id: I0f75fd00828992df37f596148fac98069794248e Reviewed-by: Christian Stenger <christian.stenger@qt.io>
Diffstat (limited to 'src/libs/3rdparty/syntax-highlighting/src')
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/CMakeLists.txt4
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/Messages.sh2
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/cli/CMakeLists.txt8
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/cli/ksyntaxhighlighter.cpp (renamed from src/libs/3rdparty/syntax-highlighting/src/cli/kate-syntax-highlighter.cpp)70
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/indexer/CMakeLists.txt19
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/indexer/katehighlightingindexer.cpp366
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/lib/CMakeLists.txt50
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/lib/abstracthighlighter.cpp123
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/lib/abstracthighlighter.h24
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/lib/abstracthighlighter_p.h3
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/lib/ansihighlighter.cpp107
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/lib/ansihighlighter.h34
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/lib/context.cpp13
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/lib/context_p.h19
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/lib/definition.cpp85
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/lib/definition.h22
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/lib/definition_p.h26
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/lib/definitiondownloader.cpp6
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/lib/definitionref_p.h6
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/lib/dynamicregexpcache_p.h39
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/lib/foldingregion.cpp31
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/lib/foldingregion.h19
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/lib/format.cpp2
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/lib/format.h10
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/lib/format_p.h11
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/lib/highlightingdata.cpp1
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/lib/highlightingdata_p.hpp1
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/lib/htmlhighlighter.cpp153
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/lib/htmlhighlighter.h7
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/lib/keywordlist.cpp7
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/lib/matchresult_p.h6
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/lib/repository.cpp76
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/lib/repository.h66
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/lib/repository_p.h26
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/lib/rule.cpp105
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/lib/rule_p.h55
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/lib/state.cpp77
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/lib/state.h14
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/lib/state_p.h56
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/lib/syntaxhighlighter.cpp141
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/lib/syntaxhighlighter.h1
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/lib/theme.cpp2
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/lib/theme.h9
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/lib/themedata.cpp54
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/lib/themedata_p.h11
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/lib/worddelimiters.cpp6
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/lib/worddelimiters_p.h5
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/quick/CMakeLists.txt5
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/quick/kquicksyntaxhighlighter.cpp14
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/quick/kquicksyntaxhighlighter.h10
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/quick/kquicksyntaxhighlightingplugin.cpp20
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/quick/repositorywrapper.cpp65
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/quick/repositorywrapper.h45
53 files changed, 1230 insertions, 907 deletions
diff --git a/src/libs/3rdparty/syntax-highlighting/src/CMakeLists.txt b/src/libs/3rdparty/syntax-highlighting/src/CMakeLists.txt
index 419b8ed5b7..9d53a5bc3d 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/CMakeLists.txt
+++ b/src/libs/3rdparty/syntax-highlighting/src/CMakeLists.txt
@@ -1,9 +1,9 @@
add_subdirectory(indexer)
-if(TARGET Qt${QT_MAJOR_VERSION}::Gui)
+if(TARGET Qt6::Gui)
add_subdirectory(lib)
add_subdirectory(cli)
endif()
-if(TARGET Qt${QT_MAJOR_VERSION}::Quick)
+if(TARGET Qt6::Quick)
add_subdirectory(quick)
endif()
diff --git a/src/libs/3rdparty/syntax-highlighting/src/Messages.sh b/src/libs/3rdparty/syntax-highlighting/src/Messages.sh
index 6fb605ddf0..4024d9b74d 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/Messages.sh
+++ b/src/libs/3rdparty/syntax-highlighting/src/Messages.sh
@@ -8,4 +8,4 @@ sed -i -e 's/^i18nc/QT_TRANSLATE_NOOP/' rc.cpp
grep --no-filename '"name"' ../data/themes/*.theme | \
sed -r -e 's/"name"/QT_TRANSLATE_NOOP("Theme", /; s/://; s/,?$/);/' >> rc.cpp
-$EXTRACT_TR_STRINGS `find . -name \*.cpp -o -name \*.h -o -name \*.ui -o -name \*.qml` -o $podir/syntaxhighlighting5_qt.pot
+$EXTRACT_TR_STRINGS `find . -name \*.cpp -o -name \*.h -o -name \*.ui -o -name \*.qml` -o $podir/syntaxhighlighting6_qt.pot
diff --git a/src/libs/3rdparty/syntax-highlighting/src/cli/CMakeLists.txt b/src/libs/3rdparty/syntax-highlighting/src/cli/CMakeLists.txt
index 1a4d24d828..3aa3a8afc3 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/cli/CMakeLists.txt
+++ b/src/libs/3rdparty/syntax-highlighting/src/cli/CMakeLists.txt
@@ -1,5 +1,5 @@
-add_executable(kate-syntax-highlighter kate-syntax-highlighter.cpp)
-ecm_mark_nongui_executable(kate-syntax-highlighter)
-target_link_libraries(kate-syntax-highlighter KF5SyntaxHighlighting)
+add_executable(ksyntaxhighlighter6 ksyntaxhighlighter.cpp)
+ecm_mark_nongui_executable(ksyntaxhighlighter6)
+target_link_libraries(ksyntaxhighlighter6 KF6SyntaxHighlighting)
-install(TARGETS kate-syntax-highlighter ${KDE_INSTALL_TARGETS_DEFAULT_ARGS})
+install(TARGETS ksyntaxhighlighter6 ${KDE_INSTALL_TARGETS_DEFAULT_ARGS})
diff --git a/src/libs/3rdparty/syntax-highlighting/src/cli/kate-syntax-highlighter.cpp b/src/libs/3rdparty/syntax-highlighting/src/cli/ksyntaxhighlighter.cpp
index 5ce90e0053..681410cb70 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/cli/kate-syntax-highlighter.cpp
+++ b/src/libs/3rdparty/syntax-highlighting/src/cli/ksyntaxhighlighter.cpp
@@ -26,7 +26,6 @@ static void applyHighlighter(Highlighter &highlighter,
QCommandLineParser &parser,
bool fromFileName,
const QString &inFileName,
- const QCommandLineOption &stdinOption,
const QCommandLineOption &outputName,
const Ts &...highlightParams)
{
@@ -38,30 +37,36 @@ static void applyHighlighter(Highlighter &highlighter,
if (fromFileName) {
highlighter.highlightFile(inFileName, highlightParams...);
- } else if (parser.isSet(stdinOption)) {
+ } else {
QFile inFile;
inFile.open(stdin, QIODevice::ReadOnly);
highlighter.highlightData(&inFile, highlightParams...);
- } else {
- parser.showHelp(1);
}
}
+static Theme theme(const Repository &repo, const QString &themeName, Repository::DefaultTheme t)
+{
+ if (themeName.isEmpty()) {
+ return repo.defaultTheme(t);
+ }
+ return repo.theme(themeName);
+}
+
int main(int argc, char **argv)
{
QCoreApplication app(argc, argv);
- QCoreApplication::setApplicationName(QStringLiteral("kate-syntax-highlighter"));
+ QCoreApplication::setApplicationName(QStringLiteral("ksyntaxhighlighter"));
QCoreApplication::setOrganizationDomain(QStringLiteral("kde.org"));
QCoreApplication::setOrganizationName(QStringLiteral("KDE"));
- QCoreApplication::setApplicationVersion(QStringLiteral(SyntaxHighlighting_VERSION_STRING));
-
- Repository repo;
+ QCoreApplication::setApplicationVersion(QStringLiteral(KSYNTAXHIGHLIGHTING_VERSION_STRING));
QCommandLineParser parser;
- parser.setApplicationDescription(app.translate("SyntaxHighlightingCLI", "Command line syntax highlighter using Kate syntax definitions."));
+ parser.setApplicationDescription(app.translate("SyntaxHighlightingCLI", "Command line syntax highlighter using KSyntaxHighlighting syntax definitions."));
parser.addHelpOption();
parser.addVersionOption();
- parser.addPositionalArgument(app.translate("SyntaxHighlightingCLI", "source"), app.translate("SyntaxHighlightingCLI", "The source file to highlight."));
+ parser.addPositionalArgument(
+ app.translate("SyntaxHighlightingCLI", "source"),
+ app.translate("SyntaxHighlightingCLI", "The source file to highlight. If absent, read the file from stdin and the --syntax option must be used."));
QCommandLineOption listDefs(QStringList() << QStringLiteral("l") << QStringLiteral("list"),
app.translate("SyntaxHighlightingCLI", "List all available syntax definitions."));
@@ -85,8 +90,7 @@ int main(int argc, char **argv)
QCommandLineOption themeName(QStringList() << QStringLiteral("t") << QStringLiteral("theme"),
app.translate("SyntaxHighlightingCLI", "Color theme to use for highlighting."),
- app.translate("SyntaxHighlightingCLI", "theme"),
- repo.defaultTheme(Repository::LightTheme).name());
+ app.translate("SyntaxHighlightingCLI", "theme"));
parser.addOption(themeName);
QCommandLineOption outputFormatOption(
@@ -99,7 +103,7 @@ int main(int argc, char **argv)
QCommandLineOption traceOption(QStringList() << QStringLiteral("syntax-trace"),
app.translate("SyntaxHighlightingCLI",
"Add information to debug a syntax file. Only works with --output-format=ansi or ansi256Colors. Possible "
- "values are format, region, context and stackSize."),
+ "values are format, region, context, stackSize and all."),
app.translate("SyntaxHighlightingCLI", "type"));
parser.addOption(traceOption);
@@ -107,18 +111,20 @@ int main(int argc, char **argv)
app.translate("SyntaxHighlightingCLI", "Disable ANSI background for the default color."));
parser.addOption(noAnsiEditorBg);
+ QCommandLineOption unbufferedAnsi(QStringList() << QStringLiteral("U") << QStringLiteral("unbuffered"),
+ app.translate("SyntaxHighlightingCLI", "For ansi and ansi256Colors formats, flush the output buffer on each line."));
+ parser.addOption(unbufferedAnsi);
+
QCommandLineOption titleOption(
QStringList() << QStringLiteral("T") << QStringLiteral("title"),
- app.translate("SyntaxHighlightingCLI", "Set HTML page's title\n(default: the filename or \"Kate Syntax Highlighter\" if reading from stdin)."),
+ app.translate("SyntaxHighlightingCLI", "Set HTML page's title\n(default: the filename or \"KSyntaxHighlighter\" if reading from stdin)."),
app.translate("SyntaxHighlightingCLI", "title"));
parser.addOption(titleOption);
- QCommandLineOption stdinOption(QStringList() << QStringLiteral("stdin"),
- app.translate("SyntaxHighlightingCLI", "Read file from stdin. The -s option must also be used."));
- parser.addOption(stdinOption);
-
parser.process(app);
+ Repository repo;
+
if (parser.isSet(listDefs)) {
for (const auto &def : repo.definitions()) {
std::cout << qPrintable(def.name()) << std::endl;
@@ -177,7 +183,7 @@ int main(int argc, char **argv)
return 1;
}
- QString outputFormat = parser.value(outputFormatOption);
+ const QString outputFormat = parser.value(outputFormatOption);
if (0 == outputFormat.compare(QLatin1String("html"), Qt::CaseInsensitive)) {
QString title;
if (parser.isSet(titleOption)) {
@@ -186,8 +192,8 @@ int main(int argc, char **argv)
HtmlHighlighter highlighter;
highlighter.setDefinition(def);
- highlighter.setTheme(repo.theme(parser.value(themeName)));
- applyHighlighter(highlighter, parser, fromFileName, inFileName, stdinOption, outputName, title);
+ highlighter.setTheme(theme(repo, parser.value(themeName), Repository::LightTheme));
+ applyHighlighter(highlighter, parser, fromFileName, inFileName, outputName, title);
} else {
auto AnsiFormat = AnsiHighlighter::AnsiFormat::TrueColor;
if (0 == outputFormat.compare(QLatin1String("ansi256Colors"), Qt::CaseInsensitive)) {
@@ -197,18 +203,22 @@ int main(int argc, char **argv)
return 2;
}
- auto debugOptions = AnsiHighlighter::TraceOptions();
+ AnsiHighlighter::Options options{};
+ options |= parser.isSet(noAnsiEditorBg) ? AnsiHighlighter::Option::NoOptions : AnsiHighlighter::Option::UseEditorBackground;
+ options |= parser.isSet(unbufferedAnsi) ? AnsiHighlighter::Option::Unbuffered : AnsiHighlighter::Option::NoOptions;
if (parser.isSet(traceOption)) {
- const auto options = parser.values(traceOption);
- for (auto const &option : options) {
+ const auto traceOptions = parser.values(traceOption);
+ for (auto const &option : traceOptions) {
if (option == QStringLiteral("format")) {
- debugOptions |= AnsiHighlighter::TraceOption::Format;
+ options |= AnsiHighlighter::Option::TraceFormat;
} else if (option == QStringLiteral("region")) {
- debugOptions |= AnsiHighlighter::TraceOption::Region;
+ options |= AnsiHighlighter::Option::TraceRegion;
} else if (option == QStringLiteral("context")) {
- debugOptions |= AnsiHighlighter::TraceOption::Context;
+ options |= AnsiHighlighter::Option::TraceContext;
} else if (option == QStringLiteral("stackSize")) {
- debugOptions |= AnsiHighlighter::TraceOption::StackSize;
+ options |= AnsiHighlighter::Option::TraceStackSize;
+ } else if (option == QStringLiteral("all")) {
+ options |= AnsiHighlighter::Option::TraceAll;
} else {
std::cerr << "Unknown trace name." << std::endl;
return 2;
@@ -218,8 +228,8 @@ int main(int argc, char **argv)
AnsiHighlighter highlighter;
highlighter.setDefinition(def);
- highlighter.setTheme(repo.theme(parser.value(themeName)));
- applyHighlighter(highlighter, parser, fromFileName, inFileName, stdinOption, outputName, AnsiFormat, !parser.isSet(noAnsiEditorBg), debugOptions);
+ highlighter.setTheme(theme(repo, parser.value(themeName), Repository::DarkTheme));
+ applyHighlighter(highlighter, parser, fromFileName, inFileName, outputName, AnsiFormat, options);
}
return 0;
diff --git a/src/libs/3rdparty/syntax-highlighting/src/indexer/CMakeLists.txt b/src/libs/3rdparty/syntax-highlighting/src/indexer/CMakeLists.txt
index 77a16faf22..cf6940b7bd 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/indexer/CMakeLists.txt
+++ b/src/libs/3rdparty/syntax-highlighting/src/indexer/CMakeLists.txt
@@ -4,13 +4,8 @@ if(CMAKE_CROSSCOMPILING AND KATEHIGHLIGHTINGINDEXER_EXECUTABLE)
add_executable(katehighlightingindexer IMPORTED GLOBAL)
set_target_properties(katehighlightingindexer PROPERTIES IMPORTED_LOCATION ${KATEHIGHLIGHTINGINDEXER_EXECUTABLE})
elseif(CMAKE_CROSSCOMPILING)
- if (NOT KF5_HOST_TOOLING)
- message(FATAL_ERROR "Please provide a prefix with a native Qt build and pass -DKF5_HOST_TOOLING=path")
- endif()
-
- # search native tooling prefix
- string(FIND ${KF5_HOST_TOOLING} /lib idx)
- string(SUBSTRING ${KF5_HOST_TOOLING} 0 ${idx} NATIVE_PREFIX)
+ include(ECMQueryQt)
+ ecm_query_qt(NATIVE_PREFIX QT_HOST_PREFIX)
message(STATUS "Building katehighlightingindexer against ${NATIVE_PREFIX}")
include(ExternalProject)
@@ -19,7 +14,7 @@ elseif(CMAKE_CROSSCOMPILING)
CMAKE_ARGS -DKSYNTAXHIGHLIGHTING_USE_GUI=OFF
-DECM_DIR=${ECM_DIR} -DCMAKE_PREFIX_PATH=${NATIVE_PREFIX}
-DCMAKE_INSTALL_PREFIX=${CMAKE_CURRENT_BINARY_DIR}
- -DQT_MAJOR_VERSION=${QT_MAJOR_VERSION}
+ -DQT_MAJOR_VERSION=6
INSTALL_COMMAND ""
BUILD_BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/native_katehighlightingindexer-prefix/src/native_katehighlightingindexer-build/bin/katehighlightingindexer
)
@@ -31,9 +26,11 @@ else()
# host build
add_executable(katehighlightingindexer katehighlightingindexer.cpp ../lib/worddelimiters.cpp)
ecm_mark_nongui_executable(katehighlightingindexer)
- if(Qt5XmlPatterns_FOUND AND NOT ECM_ENABLE_SANITIZERS)
- target_link_libraries(katehighlightingindexer Qt5::XmlPatterns)
+ if(XercesC_FOUND)
+ add_definitions(-DHAS_XERCESC)
+ kde_target_enable_exceptions(katehighlightingindexer PRIVATE)
+ target_link_libraries(katehighlightingindexer Qt6::Core XercesC::XercesC)
else()
- target_link_libraries(katehighlightingindexer Qt${QT_MAJOR_VERSION}::Core)
+ target_link_libraries(katehighlightingindexer Qt6::Core)
endif()
endif()
diff --git a/src/libs/3rdparty/syntax-highlighting/src/indexer/katehighlightingindexer.cpp b/src/libs/3rdparty/syntax-highlighting/src/indexer/katehighlightingindexer.cpp
index 9c541ef1b4..787747e21c 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/indexer/katehighlightingindexer.cpp
+++ b/src/libs/3rdparty/syntax-highlighting/src/indexer/katehighlightingindexer.cpp
@@ -12,12 +12,167 @@
#include <QFileInfo>
#include <QMutableMapIterator>
#include <QRegularExpression>
+#include <QScopeGuard>
#include <QVariant>
#include <QXmlStreamReader>
-#ifdef QT_XMLPATTERNS_LIB
-#include <QXmlSchema>
-#include <QXmlSchemaValidator>
+#ifdef HAS_XERCESC
+
+#include <xercesc/framework/XMLGrammarPoolImpl.hpp>
+
+#include <xercesc/parsers/SAX2XMLReaderImpl.hpp>
+
+#include <xercesc/sax/ErrorHandler.hpp>
+#include <xercesc/sax/SAXParseException.hpp>
+
+#include <xercesc/util/PlatformUtils.hpp>
+#include <xercesc/util/XMLString.hpp>
+#include <xercesc/util/XMLUni.hpp>
+
+#include <xercesc/framework/XMLGrammarPoolImpl.hpp>
+#include <xercesc/validators/common/Grammar.hpp>
+
+using namespace xercesc;
+
+/*
+ * Ideas taken from:
+ *
+ * author : Boris Kolpackov <boris@codesynthesis.com>
+ * copyright : not copyrighted - public domain
+ *
+ * This program uses Xerces-C++ SAX2 parser to load a set of schema files
+ * and then to validate a set of XML documents against these schemas. To
+ * build this program you will need Xerces-C++ 3.0.0 or later. For more
+ * information, see:
+ *
+ * http://www.codesynthesis.com/~boris/blog/2010/03/15/validating-external-schemas-xerces-cxx/
+ */
+
+/**
+ * Error handler object used during xml schema validation.
+ */
+class CustomErrorHandler : public ErrorHandler
+{
+public:
+ /**
+ * Constructor
+ * @param messages Pointer to the error message string to fill.
+ */
+ CustomErrorHandler(QString *messages)
+ : m_messages(messages)
+ {
+ }
+
+ /**
+ * Check global success/fail state.
+ * @return True if there was a failure, false otherwise.
+ */
+ bool failed() const
+ {
+ return m_failed;
+ }
+
+private:
+ /**
+ * Severity classes for error messages.
+ */
+ enum severity { s_warning, s_error, s_fatal };
+
+ /**
+ * Wrapper for warning exceptions.
+ * @param e Exception to handle.
+ */
+ void warning(const SAXParseException &e) override
+ {
+ m_failed = true; // be strict, warnings are evil, too!
+ handle(e, s_warning);
+ }
+
+ /**
+ * Wrapper for error exceptions.
+ * @param e Exception to handle.
+ */
+ void error(const SAXParseException &e) override
+ {
+ m_failed = true;
+ handle(e, s_error);
+ }
+
+ /**
+ * Wrapper for fatal error exceptions.
+ * @param e Exception to handle.
+ */
+ void fatalError(const SAXParseException &e) override
+ {
+ m_failed = true;
+ handle(e, s_fatal);
+ }
+
+ /**
+ * Reset the error status to "no error".
+ */
+ void resetErrors() override
+ {
+ m_failed = false;
+ }
+
+ /**
+ * Generic handler for error/warning/fatal error message exceptions.
+ * @param e Exception to handle.
+ * @param s Enum value encoding the message severtity.
+ */
+ void handle(const SAXParseException &e, severity s)
+ {
+ // get id to print
+ const XMLCh *xid(e.getPublicId());
+ if (!xid)
+ xid = e.getSystemId();
+
+ m_messages << QString::fromUtf16(xid) << ":" << e.getLineNumber() << ":" << e.getColumnNumber() << " " << (s == s_warning ? "warning: " : "error: ")
+ << QString::fromUtf16(e.getMessage()) << Qt::endl;
+ }
+
+private:
+ /**
+ * Storage for created error messages in this handler.
+ */
+ QTextStream m_messages;
+
+ /**
+ * Global error state. True if there was an error, false otherwise.
+ */
+ bool m_failed = false;
+};
+
+void init_parser(SAX2XMLReaderImpl &parser)
+{
+ // Commonly useful configuration.
+ //
+ parser.setFeature(XMLUni::fgSAX2CoreNameSpaces, true);
+ parser.setFeature(XMLUni::fgSAX2CoreNameSpacePrefixes, true);
+ parser.setFeature(XMLUni::fgSAX2CoreValidation, true);
+
+ // Enable validation.
+ //
+ parser.setFeature(XMLUni::fgXercesSchema, true);
+ parser.setFeature(XMLUni::fgXercesSchemaFullChecking, true);
+ parser.setFeature(XMLUni::fgXercesValidationErrorAsFatal, true);
+
+ // Use the loaded grammar during parsing.
+ //
+ parser.setFeature(XMLUni::fgXercesUseCachedGrammarInParse, true);
+
+ // Don't load schemas from any other source (e.g., from XML document's
+ // xsi:schemaLocation attributes).
+ //
+ parser.setFeature(XMLUni::fgXercesLoadSchema, false);
+
+ // Xerces-C++ 3.1.0 is the first version with working multi import
+ // support.
+ //
+ parser.setFeature(XMLUni::fgXercesHandleMultipleImports, true);
+}
+
#endif
#include "../lib/worddelimiters_p.h"
@@ -152,12 +307,10 @@ public:
success = false;
}
- QSet<const Keywords *> referencedKeywords;
QSet<ItemDatas::Style> usedAttributeNames;
QSet<ItemDatas::Style> ignoredAttributeNames;
- success = checkKeywordsList(definition, referencedKeywords) && success;
- success =
- checkContexts(definition, referencedKeywords, usedAttributeNames, ignoredAttributeNames, usedContexts, unreachableIncludedRules) && success;
+ success = checkKeywordsList(definition) && success;
+ success = checkContexts(definition, usedAttributeNames, ignoredAttributeNames, usedContexts, unreachableIncludedRules) && success;
// search for non-existing itemDatas.
const auto invalidNames = usedAttributeNames - definition.itemDatas.styleNames;
@@ -362,7 +515,7 @@ private:
QString content;
int line;
- friend uint qHash(const Item &item, uint seed = 0)
+ friend size_t qHash(const Item &item, size_t seed = 0)
{
return qHash(item.content, seed);
}
@@ -373,7 +526,7 @@ private:
}
};
- QVector<Item> keywords;
+ QList<Item> keywords;
QSet<Item> includes;
bool parseElement(const QString &filename, QXmlStreamReader &xml)
@@ -486,7 +639,7 @@ private:
QString weakDeliminator;
// rules included by IncludeRules (without IncludeRule)
- QVector<const Rule *> includedRules;
+ QList<const Rule *> includedRules;
// IncludeRules included by IncludeRules
QSet<const Rule *> includedIncludeRules;
@@ -683,9 +836,10 @@ private:
ContextName lineEndContext;
ContextName lineEmptyContext;
ContextName fallthroughContext;
- QVector<Rule> rules;
+ QList<Rule> rules;
XmlBool dynamic{};
XmlBool fallthrough{};
+ XmlBool stopEmptyLineContextSwitchLoop{};
bool parseElement(const QString &filename, QXmlStreamReader &xml)
{
@@ -697,12 +851,17 @@ private:
Parser parser{filename, xml, attr, success};
XmlBool noIndentationBasedFolding{};
- const bool isExtracted = parser.extractString(name, QStringLiteral("name")) || parser.extractString(attribute, QStringLiteral("attribute"))
+ // clang-format off
+ const bool isExtracted = parser.extractString(name, QStringLiteral("name"))
+ || parser.extractString(attribute, QStringLiteral("attribute"))
|| parser.extractString(lineEndContext.name, QStringLiteral("lineEndContext"))
|| parser.extractString(lineEmptyContext.name, QStringLiteral("lineEmptyContext"))
|| parser.extractString(fallthroughContext.name, QStringLiteral("fallthroughContext"))
- || parser.extractXmlBool(dynamic, QStringLiteral("dynamic")) || parser.extractXmlBool(fallthrough, QStringLiteral("fallthrough"))
+ || parser.extractXmlBool(dynamic, QStringLiteral("dynamic"))
+ || parser.extractXmlBool(fallthrough, QStringLiteral("fallthrough"))
+ || parser.extractXmlBool(stopEmptyLineContextSwitchLoop, QStringLiteral("stopEmptyLineContextSwitchLoop"))
|| parser.extractXmlBool(noIndentationBasedFolding, QStringLiteral("noIndentationBasedFolding"));
+ // clang-format on
success = parser.checkIfExtracted(isExtracted);
}
@@ -717,11 +876,6 @@ private:
success = false;
}
- if (lineEndContext.name.isEmpty()) {
- qWarning() << filename << "line" << xml.lineNumber() << "missing attribute: lineEndContext";
- success = false;
- }
-
return success;
}
};
@@ -747,7 +901,7 @@ private:
QString name;
int line;
- friend uint qHash(const Style &style, uint seed = 0)
+ friend size_t qHash(const Style &style, size_t seed = 0)
{
return qHash(style.name, seed);
}
@@ -802,7 +956,6 @@ private:
const Context *firstContext = nullptr;
QString filename;
WordDelimiters wordDelimiters;
- XmlBool casesensitive{};
Version kateVersion{};
QString kateVersionStr;
QString languageName;
@@ -865,7 +1018,7 @@ private:
void resolveIncludeRules()
{
QSet<const Context *> usedContexts;
- QVector<const Context *> contexts;
+ QList<const Context *> contexts;
QMutableMapIterator<QString, Definition> def(m_definitions);
while (def.hasNext()) {
@@ -936,7 +1089,7 @@ private:
QSet<const Context *> extractUsedContexts() const
{
QSet<const Context *> usedContexts;
- QVector<const Context *> contexts;
+ QList<const Context *> contexts;
QMapIterator<QString, Definition> def(m_definitions);
while (def.hasNext()) {
@@ -982,13 +1135,12 @@ private:
};
struct IncludedRuleUnreachableBy {
- QVector<RuleAndInclude> unreachableBy;
+ QList<RuleAndInclude> unreachableBy;
bool alwaysUnreachable = true;
};
//! Check contexts and rules
bool checkContexts(const Definition &definition,
- QSet<const Keywords *> &referencedKeywords,
QSet<ItemDatas::Style> &usedAttributeNames,
QSet<ItemDatas::Style> &ignoredAttributeNames,
const QSet<const Context *> &usedContexts,
@@ -1018,7 +1170,7 @@ private:
usedAttributeNames.insert({context.attribute, context.line});
}
- success = checkfallthrough(definition, context) && success;
+ success = checkContextAttribute(definition, context) && success;
success = checkUreachableRules(definition.filename, context, unreachableIncludedRules) && success;
success = suggestRuleMerger(definition.filename, context) && success;
@@ -1032,7 +1184,7 @@ private:
}
success = checkLookAhead(rule) && success;
success = checkStringDetect(rule) && success;
- success = checkKeyword(definition, rule, referencedKeywords) && success;
+ success = checkKeyword(definition, rule) && success;
success = checkRegExpr(filename, rule, context) && success;
success = checkDelimiters(definition, rule) && success;
}
@@ -1047,12 +1199,13 @@ private:
//! - dynamic=true but no place holder used?
//! - is not . with lookAhead="1"
//! - is not ^... without column ou firstNonSpace attribute
- //! - is not equivalent to DetectSpaces, DetectChar, Detect2Chars, StringDetect, DetectIdentifier, RangeDetect
+ //! - is not equivalent to DetectSpaces, DetectChar, Detect2Chars, StringDetect, DetectIdentifier, RangeDetect, LineContinue or AnyChar
//! - has no unused captures
//! - has no unnecessary quantifier with lookAhead
bool checkRegExpr(const QString &filename, const Context::Rule &rule, const Context &context) const
{
- if (rule.type == Context::Rule::Type::RegExpr) {
+ // ignore empty regex because the error is raised during xml parsing
+ if (rule.type == Context::Rule::Type::RegExpr && !rule.string.isEmpty()) {
const QRegularExpression regexp(rule.string);
if (!checkRegularExpression(rule.filename, regexp, rule.line)) {
return false;
@@ -1092,13 +1245,21 @@ private:
// is RangeDetect
static const QRegularExpression isRange(QStringLiteral("^\\^?" REG_CHAR "(?:"
- "\\.\\*[?*]?" REG_CHAR "|"
- "\\[\\^(" REG_ESCAPE_CHAR "|.)\\]\\*[?*]?\\1"
+ "\\.\\*[?+]?" REG_CHAR "|"
+ "\\[\\^(" REG_ESCAPE_CHAR "|.)\\]\\*[?+]?\\1"
")$"));
if ((rule.lookAhead == XmlBool::True || rule.minimal == XmlBool::True || rule.string.contains(QStringLiteral(".*?"))
|| rule.string.contains(QStringLiteral("[^")))
&& reg.contains(isRange)) {
- qWarning() << filename << "line" << rule.line << "RegExpr should be replaced by RangeDetect:" << rule.string;
+ qWarning() << rule.filename << "line" << rule.line << "RegExpr should be replaced by RangeDetect:" << rule.string;
+ return false;
+ }
+
+ // is AnyChar
+ static const QRegularExpression isAnyChar(QStringLiteral(R"(^(\^|\((\?:)?)*\[(?!\^)[-\]]?(\\[^0BDPSWbdpswoux]|[^-\]\\])*\]\)*$)"));
+ if (rule.string.contains(isAnyChar)) {
+ auto extra = (reg[0] == QLatin1Char('^') || reg[1] == QLatin1Char('^')) ? "with column=\"0\"" : "";
+ qWarning() << rule.filename << "line" << rule.line << "RegExpr should be replaced by AnyChar:" << rule.string << extra;
return false;
}
@@ -1106,7 +1267,7 @@ private:
static const QRegularExpression isLineContinue(QStringLiteral("^\\^?" REG_CHAR "\\$$"));
if (reg.contains(isLineContinue)) {
auto extra = (reg[0] == QLatin1Char('^')) ? "with column=\"0\"" : "";
- qWarning() << filename << "line" << rule.line << "RegExpr should be replaced by LineContinue:" << rule.string << extra;
+ qWarning() << rule.filename << "line" << rule.line << "RegExpr should be replaced by LineContinue:" << rule.string << extra;
return false;
}
@@ -1124,7 +1285,7 @@ private:
if (rule.lookAhead == XmlBool::True && rule.minimal != XmlBool::True && reg.contains(isMinimal) && !reg.contains(hasNotGreedy)
&& (!rule.context.context || !rule.context.context->hasDynamicRule || regexp.captureCount() == 0)
&& (reg.back() != QLatin1Char('$') || reg.contains(QLatin1Char('|')))) {
- qWarning() << filename << "line" << rule.line
+ qWarning() << rule.filename << "line" << rule.line
<< "RegExpr should be have minimal=\"1\" or use lazy operator (i.g, '.*' -> '.*?'):" << rule.string;
return false;
}
@@ -1160,8 +1321,8 @@ private:
return false;
}
- // column="0" or firstNonSpace="1"
- if (rule.column == -1 && rule.firstNonSpace != XmlBool::True) {
+ // column="0"
+ if (rule.column == -1) {
// ^ without |
// (^sas*) -> ok
// (^sa|s*) -> ko
@@ -1204,7 +1365,7 @@ private:
}
if (replace) {
- qWarning() << rule.filename << "line" << rule.line << "column=\"0\" or firstNonSpace=\"1\" missing with RegExpr:" << rule.string;
+ qWarning() << rule.filename << "line" << rule.line << "column=\"0\" missing with RegExpr:" << rule.string;
return false;
}
}
@@ -1306,11 +1467,8 @@ private:
if (!useCapture) {
// is DetectIdentifier
- static const QRegularExpression isInsensitiveDetectIdentifier(
- QStringLiteral(R"(^(\((\?:)?)?\[((a-z|_){2}|(A-Z|_){2})\]([+][*?]?)?\[((0-9|a-z|_){3}|(0-9|A-Z|_){3})\][*][*?]?(\))?$)"));
- static const QRegularExpression isSensitiveDetectIdentifier(
- QStringLiteral(R"(^(\((\?:)?)?\[(a-z|A-Z|_){3}\]([+][*?]?)?\[(0-9|a-z|A-Z|_){4}\][*][*?]?(\))?$)"));
- auto &isDetectIdentifier = (rule.insensitive == XmlBool::True) ? isInsensitiveDetectIdentifier : isSensitiveDetectIdentifier;
+ static const QRegularExpression isDetectIdentifier(
+ QStringLiteral(R"(^(\((\?:)?|\^)*\[(\\p\{L\}|_){2}\]([+][?+]?)?\[(\\p\{N\}|\\p\{L\}|_){3}\][*][?+]?\)*$)"));
if (rule.string.contains(isDetectIdentifier)) {
qWarning() << rule.filename << "line" << rule.line << "RegExpr should be replaced by DetectIdentifier:" << rule.string;
return false;
@@ -1357,7 +1515,7 @@ private:
static const QRegularExpression unnecessaryQuantifier2(QStringLiteral(R"([*+?]([.][*+?]{0,2})?[)]*$)"));
auto &unnecessaryQuantifier = useCapture ? unnecessaryQuantifier1 : unnecessaryQuantifier2;
if (rule.lookAhead == XmlBool::True && rule.minimal != XmlBool::True && reg.contains(unnecessaryQuantifier)) {
- qWarning() << filename << "line" << rule.line
+ qWarning() << rule.filename << "line" << rule.line
<< "Last quantifier is not necessary (i.g., 'xyz*' -> 'xy', 'xyz+.' -> 'xyz.'):" << rule.string;
return false;
}
@@ -1418,19 +1576,13 @@ private:
return true;
}
- //! Search for rules with lookAhead="true" and context="#stay".
- //! This would cause an infinite loop.
- bool checkfallthrough(const Definition &definition, const Context &context) const
+ //! Check fallthrough and fallthroughContext.
+ //! Check kateversion for stopEmptyLineContextSwitchLoop.
+ bool checkContextAttribute(const Definition &definition, const Context &context) const
{
bool success = true;
if (!context.fallthroughContext.name.isEmpty()) {
- if (context.fallthroughContext.stay) {
- qWarning() << definition.filename << "line" << context.line << "possible infinite loop due to fallthroughContext=\"#stay\" in context "
- << context.name;
- success = false;
- }
-
const bool mandatoryFallthroughAttribute = definition.kateVersion < Version{5, 62};
if (context.fallthrough == XmlBool::True && !mandatoryFallthroughAttribute) {
qWarning() << definition.filename << "line" << context.line << "fallthrough attribute is unnecessary with kateversion >= 5.62 in context"
@@ -1444,6 +1596,12 @@ private:
}
}
+ if (context.stopEmptyLineContextSwitchLoop != XmlBool::Unspecified && definition.kateVersion < Version{5, 103}) {
+ qWarning() << definition.filename << "line" << context.line
+ << "stopEmptyLineContextSwitchLoop attribute is only valid with kateversion >= 5.103 in context" << context.name;
+ success = false;
+ }
+
return success;
}
@@ -1478,15 +1636,12 @@ private:
return false;
}
- //! Search for rules with lookAhead="true" and context="#stay".
- //! This would cause an infinite loop.
- bool checkKeyword(const Definition &definition, const Context::Rule &rule, QSet<const Keywords *> &referencedKeywords) const
+ //! Check that keyword rule reference an existing keyword list.
+ bool checkKeyword(const Definition &definition, const Context::Rule &rule) const
{
if (rule.type == Context::Rule::Type::keyword) {
auto it = definition.keywordsList.find(rule.string);
- if (it != definition.keywordsList.end()) {
- referencedKeywords.insert(&*it);
- } else {
+ if (it == definition.keywordsList.end()) {
qWarning() << rule.filename << "line" << rule.line << "reference of non-existing keyword list:" << rule.string;
return false;
}
@@ -1504,13 +1659,7 @@ private:
return true;
}
- //! Check that StringDetect contains more that 2 characters
- //! Fix with following command:
- //! \code
- //! sed -E
- //! '/StringDetect/{/dynamic="(1|true)|insensitive="(1|true)/!{s/StringDetect(.*)String="(.|&lt;|&gt;|&quot;|&amp;)(.|&lt;|&gt;|&quot;|&amp;)"/Detect2Chars\1char="\2"
- //! char1="\3"/;t;s/StringDetect(.*)String="(.|&lt;|&gt;|&quot;|&amp;)"/DetectChar\1char="\2"/}}' -i file.xml...
- //! \endcode
+ //! Check that StringDetect contains a placeHolder when dynamic="1"
bool checkStringDetect(const Context::Rule &rule) const
{
if (rule.type == Context::Rule::Type::StringDetect) {
@@ -1527,7 +1676,7 @@ private:
}
//! Check \<include> and delimiter in a keyword list
- bool checkKeywordsList(const Definition &definition, QSet<const Keywords *> &referencedKeywords) const
+ bool checkKeywordsList(const Definition &definition) const
{
bool success = true;
@@ -1542,7 +1691,7 @@ private:
<< "<include> is only available since version \"5.53\". Please, increase kateversion.";
success = false;
}
- success = checkKeywordInclude(definition, include, referencedKeywords) && success;
+ success = checkKeywordInclude(definition, include) && success;
}
// Check that keyword list items do not have deliminator character
@@ -1562,16 +1711,13 @@ private:
}
//! Search for non-existing keyword include.
- bool checkKeywordInclude(const Definition &definition, const Keywords::Items::Item &include, QSet<const Keywords *> &referencedKeywords) const
+ bool checkKeywordInclude(const Definition &definition, const Keywords::Items::Item &include) const
{
bool containsKeywordName = true;
int const idx = include.content.indexOf(QStringLiteral("##"));
if (idx == -1) {
auto it = definition.keywordsList.find(include.content);
containsKeywordName = (it != definition.keywordsList.end());
- if (containsKeywordName) {
- referencedKeywords.insert(&*it);
- }
} else {
auto defName = include.content.mid(idx + 2);
auto listName = include.content.left(idx);
@@ -1644,10 +1790,10 @@ private:
}
/// Search RuleAndInclude associated with the characters of @p s.
- /// \return an empty QVector when at least one character is not found.
- QVector<RuleAndInclude> find(QStringView s) const
+ /// \return an empty QList when at least one character is not found.
+ QList<RuleAndInclude> find(QStringView s) const
{
- QVector<RuleAndInclude> result;
+ QList<RuleAndInclude> result;
for (QChar c : s) {
if (!find(c)) {
@@ -1731,8 +1877,8 @@ private:
}
/// Search RuleAndInclude associated with the characters of @p s.
- /// \return an empty QVector when at least one character is not found.
- QVector<RuleAndInclude> find(QStringView s) const
+ /// \return an empty QList when at least one character is not found.
+ QList<RuleAndInclude> find(QStringView s) const
{
for (int i = 0; i < m_size; ++i) {
auto result = m_charTables[i]->find(s);
@@ -1743,7 +1889,7 @@ private:
return result;
}
}
- return QVector<RuleAndInclude>();
+ return QList<RuleAndInclude>();
}
/// Associates @p c with a rule.
@@ -1785,7 +1931,7 @@ private:
// Iterates over all the rules, including those in includedRules
struct RuleIterator {
- RuleIterator(const QVector<ObservableRule> &rules, const ObservableRule &endRule)
+ RuleIterator(const QList<ObservableRule> &rules, const ObservableRule &endRule)
: m_end(&endRule - rules.data())
, m_rules(rules)
{
@@ -1830,10 +1976,10 @@ private:
private:
int m_i = 0;
- int m_i2;
- int m_end;
- const QVector<ObservableRule> &m_rules;
- const QVector<const Context::Rule *> *m_includedRules = nullptr;
+ int m_i2 = 0;
+ const int m_end;
+ const QList<ObservableRule> &m_rules;
+ const QList<const Context::Rule *> *m_includedRules = nullptr;
};
// Dot regex container that satisfies firstNonSpace and column.
@@ -1915,7 +2061,7 @@ private:
DotRegex dotRegex;
- QVector<ObservableRule> observedRules;
+ QList<ObservableRule> observedRules;
observedRules.reserve(context.rules.size());
for (const Context::Rule &rule : context.rules) {
const Context::Rule *includeRule = nullptr;
@@ -1937,7 +2083,7 @@ private:
for (auto &observedRule : observedRules) {
const Context::Rule &rule = *observedRule.rule;
bool isUnreachable = false;
- QVector<RuleAndInclude> unreachableBy;
+ QList<RuleAndInclude> unreachableBy;
// declare rule as unreachable if ruleAndInclude is not empty
auto updateUnreachable1 = [&](RuleAndInclude ruleAndInclude) {
@@ -1948,7 +2094,7 @@ private:
};
// declare rule as unreachable if ruleAndIncludes is not empty
- auto updateUnreachable2 = [&](const QVector<RuleAndInclude> &ruleAndIncludes) {
+ auto updateUnreachable2 = [&](const QList<RuleAndInclude> &ruleAndIncludes) {
if (!ruleAndIncludes.isEmpty()) {
isUnreachable = true;
unreachableBy.append(ruleAndIncludes);
@@ -2030,6 +2176,8 @@ private:
case Context::Rule::Type::Float:
updateUnreachable2(CharTableArray(detectChars, rule).find(QStringLiteral("0123456789.")));
updateUnreachable1(floatRule.setRule(rule));
+ // check that Float is before Int
+ updateUnreachable1(Rule4(intRule).setRule(rule));
break;
// check if hidden by another DetectIdentifier rule
@@ -2629,12 +2777,32 @@ int main(int argc, char *argv[])
return 1;
}
-#ifdef QT_XMLPATTERNS_LIB
- // open schema
- QXmlSchema schema;
- if (!schema.load(QUrl::fromLocalFile(app.arguments().at(2)))) {
+#ifdef HAS_XERCESC
+ // care for proper init and cleanup
+ XMLPlatformUtils::Initialize();
+ auto cleanup = qScopeGuard(XMLPlatformUtils::Terminate);
+
+ /*
+ * parse XSD first time and cache it
+ */
+ XMLGrammarPoolImpl xsd(XMLPlatformUtils::fgMemoryManager);
+
+ // create parser for the XSD
+ SAX2XMLReaderImpl parser(XMLPlatformUtils::fgMemoryManager, &xsd);
+ init_parser(parser);
+ QString messages;
+ CustomErrorHandler eh(&messages);
+ parser.setErrorHandler(&eh);
+
+ // load grammar into the pool, on error just abort
+ const auto xsdFile = app.arguments().at(2);
+ if (!parser.loadGrammar((const char16_t *)xsdFile.utf16(), Grammar::SchemaGrammarType, true) || eh.failed()) {
+ qWarning("Failed to parse XSD %s: %s", qPrintable(xsdFile), qPrintable(messages));
return 2;
}
+
+ // lock the pool, no later modifications wanted!
+ xsd.lockPool();
#endif
const QString hlFilenamesListing = app.arguments().value(3);
@@ -2665,10 +2833,20 @@ int main(int argc, char *argv[])
continue;
}
-#ifdef QT_XMLPATTERNS_LIB
- // validate against schema
- QXmlSchemaValidator validator(schema);
- if (!validator.validate(&hlFile, QUrl::fromLocalFile(hlFile.fileName()))) {
+#ifdef HAS_XERCESC
+ // create parser
+ SAX2XMLReaderImpl parser(XMLPlatformUtils::fgMemoryManager, &xsd);
+ init_parser(parser);
+ QString messages;
+ CustomErrorHandler eh(&messages);
+ parser.setErrorHandler(&eh);
+
+ // parse the XML file
+ parser.parse((const char16_t *)hlFile.fileName().utf16());
+
+ // report issues
+ if (eh.failed()) {
+ qWarning("Failed to validate XML %s: %s", qPrintable(hlFile.fileName()), qPrintable(messages));
anyError = 4;
continue;
}
@@ -2708,6 +2886,10 @@ int main(int argc, char *argv[])
// add boolean one
hl[QStringLiteral("hidden")] = attrToBool(xml.attributes().value(QLatin1String("hidden")));
+ // keep some strings as UTF-8 for faster translations
+ hl[QStringLiteral("nameUtf8")] = hl[QStringLiteral("name")].toString().toUtf8();
+ hl[QStringLiteral("sectionUtf8")] = hl[QStringLiteral("section")].toString().toUtf8();
+
// remember hl
hls[QFileInfo(hlFile).fileName()] = hl;
diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/CMakeLists.txt b/src/libs/3rdparty/syntax-highlighting/src/lib/CMakeLists.txt
index fe89fdd715..2b2845eba4 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/lib/CMakeLists.txt
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/CMakeLists.txt
@@ -1,8 +1,14 @@
-add_library(KF5SyntaxHighlighting)
+add_library(KF6SyntaxHighlighting)
-ecm_create_qm_loader(syntax_highlighting_QM_LOADER syntaxhighlighting5_qt)
+set_target_properties(KF6SyntaxHighlighting PROPERTIES
+ VERSION ${KSYNTAXHIGHLIGHTING_VERSION}
+ SOVERSION ${KSYNTAXHIGHLIGHTING_SOVERSION}
+ EXPORT_NAME SyntaxHighlighting
+)
+
+ecm_create_qm_loader(syntax_highlighting_QM_LOADER syntaxhighlighting6_qt)
-target_sources(KF5SyntaxHighlighting PRIVATE
+target_sources(KF6SyntaxHighlighting PRIVATE
abstracthighlighter.cpp
context.cpp
contextswitch.cpp
@@ -25,7 +31,7 @@ target_sources(KF5SyntaxHighlighting PRIVATE
${syntax_highlighting_QM_LOADER}
$<TARGET_OBJECTS:SyntaxHighlightingData>
)
-ecm_qt_declare_logging_category(KF5SyntaxHighlighting
+ecm_qt_declare_logging_category(KF6SyntaxHighlighting
HEADER ksyntaxhighlighting_logging.h
IDENTIFIER KSyntaxHighlighting::Log
CATEGORY_NAME kf.syntaxhighlighting
@@ -34,25 +40,21 @@ ecm_qt_declare_logging_category(KF5SyntaxHighlighting
EXPORT KSYNTAXHIGHLIGHTING
)
-ecm_generate_export_header(KF5SyntaxHighlighting
+ecm_generate_export_header(KF6SyntaxHighlighting
BASE_NAME KSyntaxHighlighting
GROUP_BASE_NAME KF
VERSION ${KF_VERSION}
+ USE_VERSION_HEADER
DEPRECATED_BASE_VERSION 0
- DEPRECATION_VERSIONS 5.87
+ DEPRECATION_VERSIONS
EXCLUDE_DEPRECATED_BEFORE_AND_AT ${EXCLUDE_DEPRECATED_BEFORE_AND_AT}
)
-set_target_properties(KF5SyntaxHighlighting PROPERTIES
- VERSION ${SyntaxHighlighting_VERSION}
- SOVERSION ${SyntaxHighlighting_SOVERSION}
- EXPORT_NAME SyntaxHighlighting
-)
-target_link_libraries(KF5SyntaxHighlighting
+target_link_libraries(KF6SyntaxHighlighting
PUBLIC
- Qt${QT_MAJOR_VERSION}::Gui
+ Qt6::Gui
PRIVATE
- Qt${QT_MAJOR_VERSION}::Network
+ Qt6::Network
)
set(Forwarding_Header_Names
@@ -74,12 +76,12 @@ ecm_generate_headers(CamelCase_HEADERS
OUTPUT_DIR ${CMAKE_BINARY_DIR}/KSyntaxHighlighting/KSyntaxHighlighting
)
-target_include_directories(KF5SyntaxHighlighting
+target_include_directories(KF6SyntaxHighlighting
INTERFACE "$<INSTALL_INTERFACE:${KDE_INSTALL_INCLUDEDIR_KF}/KSyntaxHighlighting>"
PUBLIC "$<BUILD_INTERFACE:${CMAKE_BINARY_DIR}/KSyntaxHighlighting;>"
)
-install(TARGETS KF5SyntaxHighlighting EXPORT KF5SyntaxHighlightingTargets ${KDE_INSTALL_TARGETS_DEFAULT_ARGS})
+install(TARGETS KF6SyntaxHighlighting EXPORT KF6SyntaxHighlightingTargets ${KDE_INSTALL_TARGETS_DEFAULT_ARGS})
install(FILES
${CamelCase_HEADERS}
@@ -90,17 +92,17 @@ install(FILES
if(BUILD_QCH)
ecm_add_qch(
- KF5SyntaxHighlighting_QCH
+ KF6SyntaxHighlighting_QCH
NAME KSyntaxHighlighting
- BASE_NAME KF5SyntaxHighlighting
+ BASE_NAME KF6SyntaxHighlighting
VERSION ${KF_VERSION}
ORG_DOMAIN org.kde
SOURCES # using only public headers, to cover only public API
${SyntaxHighlighting_HEADERS}
MD_MAINPAGE "${CMAKE_SOURCE_DIR}/README.md"
LINK_QCHS
- Qt5Core_QCH
- Qt5Gui_QCH
+ Qt6Core_QCH
+ Qt6Gui_QCH
INCLUDE_DIRS
${CMAKE_CURRENT_BINARY_DIR}
BLANK_MACROS
@@ -111,11 +113,3 @@ if(BUILD_QCH)
COMPONENT Devel
)
endif()
-ecm_generate_pri_file(
- BASE_NAME KSyntaxHighlighting LIB_NAME
- KF5SyntaxHighlighting
- DEPS "gui"
- FILENAME_VAR PRI_FILENAME
- INCLUDE_INSTALL_DIR ${KDE_INSTALL_INCLUDEDIR_KF}/KSyntaxHighlighting
-)
-install(FILES ${PRI_FILENAME} DESTINATION ${ECM_MKSPECS_INSTALL_DIR})
diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/abstracthighlighter.cpp b/src/libs/3rdparty/syntax-highlighting/src/lib/abstracthighlighter.cpp
index ac5d98abfb..87dabadc7b 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/lib/abstracthighlighter.cpp
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/abstracthighlighter.cpp
@@ -12,6 +12,7 @@
#include "format.h"
#include "ksyntaxhighlighting_logging.h"
#include "repository.h"
+#include "repository_p.h"
#include "rule_p.h"
#include "state.h"
#include "state_p.h"
@@ -97,13 +98,6 @@ static inline int firstNonSpaceChar(QStringView 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);
@@ -116,43 +110,47 @@ State AbstractHighlighter::highlightLine(QStringView text, const State &state)
return State();
}
+ // limit the cache for unification to some reasonable size
+ // we use here at the moment 64k elements to not hog too much memory
+ // and to make the clearing no big stall
+ if (defData->unify.size() > 64 * 1024)
+ defData->unify.clear();
+
// verify/initialize state
auto newState = state;
auto stateData = StateData::get(newState);
- const auto definitionId = DefinitionData::get(d->m_definition)->id;
- if (!stateData->isEmpty() && stateData->m_defId != definitionId) {
+ bool isSharedData = true;
+ if (Q_UNLIKELY(stateData && stateData->m_defId != defData->id)) {
qCDebug(Log) << "Got invalid state, resetting.";
- stateData->clear();
+ stateData = nullptr;
}
- if (stateData->isEmpty()) {
+ if (Q_UNLIKELY(!stateData)) {
+ stateData = StateData::reset(newState);
stateData->push(defData->initialContext(), QStringList());
- stateData->m_defId = definitionId;
+ stateData->m_defId = defData->id;
+ isSharedData = false;
}
// process empty lines
- if (text.isEmpty()) {
+ if (Q_UNLIKELY(text.isEmpty())) {
/**
* handle line empty context switches
* guard against endless loops
* see https://phabricator.kde.org/D18509
*/
int endlessLoopingCounter = 0;
- while (!stateData->topContext()->lineEmptyContext().isStay() || !stateData->topContext()->lineEndContext().isStay()) {
+ while (!stateData->topContext()->lineEmptyContext().isStay()) {
/**
* line empty context switches
*/
- if (!stateData->topContext()->lineEmptyContext().isStay()) {
- if (!d->switchContext(stateData, stateData->topContext()->lineEmptyContext(), QStringList())) {
- /**
- * end when trying to #pop the main context
- */
- break;
- }
+ if (!d->switchContext(stateData, stateData->topContext()->lineEmptyContext(), QStringList(), newState, isSharedData)) {
/**
- * line end context switches only when lineEmptyContext is #stay. This avoids
- * skipping empty lines after a line continuation character (see bug 405903)
+ * end when trying to #pop the main context
*/
- } else if (!d->switchContext(stateData, stateData->topContext()->lineEndContext(), QStringList())) {
+ break;
+ }
+
+ if (stateData->topContext()->stopEmptyLineContextSwitchLoop()) {
break;
}
@@ -165,9 +163,11 @@ State AbstractHighlighter::highlightLine(QStringView text, const State &state)
}
auto context = stateData->topContext();
applyFormat(0, 0, context->attributeFormat());
- return newState;
+ return *defData->unify.insert(newState);
}
+ auto &dynamicRegexpCache = RepositoryPrivate::get(defData->repo)->m_dynamicRegexpCache;
+
int offset = 0;
int beginOffset = 0;
bool lineContinuation = false;
@@ -178,10 +178,10 @@ State AbstractHighlighter::highlightLine(QStringView text, const State &state)
* - store the result of the first position that matches (or -1 for no match in the full line) in the skipOffsets hash for re-use
* - have capturesForLastDynamicSkipOffset as guard for dynamic regexes to invalidate the cache if they might have changed
*/
- QVarLengthArray<QPair<Rule *, int>, 8> skipOffsets;
+ QVarLengthArray<QPair<const Rule *, int>, 8> skipOffsets;
QStringList capturesForLastDynamicSkipOffset;
- auto getSkipOffsetValue = [&skipOffsets](Rule *r) -> int {
+ auto getSkipOffsetValue = [&skipOffsets](const Rule *r) -> int {
auto i = std::find_if(skipOffsets.begin(), skipOffsets.end(), [r](const auto &v) {
return v.first == r;
});
@@ -190,7 +190,7 @@ State AbstractHighlighter::highlightLine(QStringView text, const State &state)
return i->second;
};
- auto insertSkipOffset = [&skipOffsets](Rule *r, int i) {
+ auto insertSkipOffset = [&skipOffsets](const Rule *r, int i) {
auto it = std::find_if(skipOffsets.begin(), skipOffsets.end(), [r](const auto &v) {
return v.first == r;
});
@@ -237,7 +237,8 @@ State AbstractHighlighter::highlightLine(QStringView text, const State &state)
bool isLookAhead = false;
int newOffset = 0;
const Format *newFormat = nullptr;
- for (const auto &rule : stateData->topContext()->rules()) {
+ for (const auto &ruleShared : stateData->topContext()->rules()) {
+ auto rule = ruleShared.get();
/**
* filter out rules that require a specific column
*/
@@ -265,29 +266,33 @@ State AbstractHighlighter::highlightLine(QStringView text, const State &state)
}
}
- /**
- * shall we skip application of this rule? two cases:
- * - rule can't match at all => currentSkipOffset < 0
- * - rule will only match for some higher offset => currentSkipOffset > offset
- *
- * we need to invalidate this if we are dynamic and have different captures then last time
- */
- if (rule->isDynamic() && (capturesForLastDynamicSkipOffset != stateData->topCaptures())) {
- skipOffsets.clear();
- }
- const auto currentSkipOffset = getSkipOffsetValue(rule.get());
- if (currentSkipOffset < 0 || currentSkipOffset > offset) {
- continue;
+ int currentSkipOffset = 0;
+ if (Q_UNLIKELY(rule->hasSkipOffset())) {
+ /**
+ * shall we skip application of this rule? two cases:
+ * - rule can't match at all => currentSkipOffset < 0
+ * - rule will only match for some higher offset => currentSkipOffset > offset
+ *
+ * we need to invalidate this if we are dynamic and have different captures then last time
+ */
+ if (rule->isDynamic() && (capturesForLastDynamicSkipOffset != stateData->topCaptures())) {
+ skipOffsets.clear();
+ } else {
+ currentSkipOffset = getSkipOffsetValue(rule);
+ if (currentSkipOffset < 0 || currentSkipOffset > offset) {
+ continue;
+ }
+ }
}
- const auto newResult = rule->doMatch(text, offset, stateData->topCaptures());
+ auto newResult = rule->doMatch(text, offset, stateData->topCaptures(), dynamicRegexpCache);
newOffset = newResult.offset();
/**
* update skip offset if new one rules out any later match or is larger than current one
*/
if (newResult.skipOffset() < 0 || newResult.skipOffset() > currentSkipOffset) {
- insertSkipOffset(rule.get(), newResult.skipOffset());
+ insertSkipOffset(rule, newResult.skipOffset());
// remember new captures, if dynamic to enforce proper reset above on change!
if (rule->isDynamic()) {
@@ -316,12 +321,12 @@ State AbstractHighlighter::highlightLine(QStringView text, const State &state)
if (rule->isLookAhead()) {
Q_ASSERT(!rule->context().isStay());
- d->switchContext(stateData, rule->context(), newResult.captures());
+ d->switchContext(stateData, rule->context(), std::move(newResult.captures()), newState, isSharedData);
isLookAhead = true;
break;
}
- d->switchContext(stateData, rule->context(), newResult.captures());
+ d->switchContext(stateData, rule->context(), std::move(newResult.captures()), newState, isSharedData);
newFormat = rule->attributeFormat().isValid() ? &rule->attributeFormat() : &stateData->topContext()->attributeFormat();
if (newOffset == text.size() && rule->isLineContinue()) {
lineContinuation = true;
@@ -334,7 +339,7 @@ State AbstractHighlighter::highlightLine(QStringView text, const State &state)
if (newOffset <= offset) { // no matching rule
if (stateData->topContext()->fallthrough()) {
- d->switchContext(stateData, stateData->topContext()->fallthroughContext(), QStringList());
+ d->switchContext(stateData, stateData->topContext()->fallthroughContext(), QStringList(), newState, isSharedData);
continue;
}
@@ -381,7 +386,7 @@ State AbstractHighlighter::highlightLine(QStringView 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(), newState, isSharedData)) {
break;
}
@@ -394,18 +399,30 @@ State AbstractHighlighter::highlightLine(QStringView text, const State &state)
}
}
- return newState;
+ return *defData->unify.insert(newState);
}
-bool AbstractHighlighterPrivate::switchContext(StateData *data, const ContextSwitch &contextSwitch, const QStringList &captures)
+bool AbstractHighlighterPrivate::switchContext(StateData *&data, const ContextSwitch &contextSwitch, QStringList &&captures, State &state, bool &isSharedData)
{
+ const auto popCount = contextSwitch.popCount();
+ const auto context = contextSwitch.context();
+ if (popCount <= 0 && !context) {
+ return true;
+ }
+
+ // a modified state must be detached before modification
+ if (isSharedData) {
+ data = StateData::detach(state);
+ isSharedData = false;
+ }
+
// kill as many items as requested from the stack, will always keep the initial context alive!
- const bool initialContextSurvived = data->pop(contextSwitch.popCount());
+ const bool initialContextSurvived = data->pop(popCount);
// if we have a new context to add, push it
// then we always "succeed"
- if (contextSwitch.context()) {
- data->push(contextSwitch.context(), captures);
+ if (context) {
+ data->push(context, std::move(captures));
return true;
}
diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/abstracthighlighter.h b/src/libs/3rdparty/syntax-highlighting/src/lib/abstracthighlighter.h
index 49cfbf2530..676a0f522a 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/lib/abstracthighlighter.h
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/abstracthighlighter.h
@@ -7,20 +7,15 @@
#ifndef KSYNTAXHIGHLIGHTING_ABSTRACTHIGHLIGHTERM_H
#define KSYNTAXHIGHLIGHTING_ABSTRACTHIGHLIGHTERM_H
+#include "definition.h"
#include "ksyntaxhighlighting_export.h"
#include <QObject>
-
-#include <memory>
-
-QT_BEGIN_NAMESPACE
-class QString;
-QT_END_NAMESPACE
+#include <QStringView>
namespace KSyntaxHighlighting
{
class AbstractHighlighterPrivate;
-class Definition;
class FoldingRegion;
class Format;
class State;
@@ -106,21 +101,8 @@ public:
protected:
AbstractHighlighter();
- AbstractHighlighter(AbstractHighlighterPrivate *dd);
+ KSYNTAXHIGHLIGHTING_NO_EXPORT explicit 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
- // this context available in their applyX methods
/**
* Highlight the given line. Call this from your derived class
* where appropriate. This will result in any number of applyFormat()
diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/abstracthighlighter_p.h b/src/libs/3rdparty/syntax-highlighting/src/lib/abstracthighlighter_p.h
index 6128beccfa..04ac9898f8 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/lib/abstracthighlighter_p.h
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/abstracthighlighter_p.h
@@ -14,6 +14,7 @@ namespace KSyntaxHighlighting
{
class ContextSwitch;
class StateData;
+class State;
class AbstractHighlighterPrivate
{
@@ -22,7 +23,7 @@ public:
virtual ~AbstractHighlighterPrivate();
void ensureDefinitionLoaded();
- bool switchContext(StateData *data, const ContextSwitch &contextSwitch, const QStringList &captures);
+ bool switchContext(StateData *&data, const ContextSwitch &contextSwitch, QStringList &&captures, State &state, bool &isSharedData);
Definition m_definition;
Theme m_theme;
diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/ansihighlighter.cpp b/src/libs/3rdparty/syntax-highlighting/src/lib/ansihighlighter.cpp
index 31678018f9..e9bea02d1c 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/lib/ansihighlighter.cpp
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/ansihighlighter.cpp
@@ -5,6 +5,7 @@
*/
#include "ansihighlighter.h"
+#include "abstracthighlighter_p.h"
#include "context_p.h"
#include "definition.h"
#include "definition_p.h"
@@ -18,6 +19,7 @@
#include <QFile>
#include <QFileInfo>
#include <QHash>
+#include <QIODevice>
#include <QTextStream>
#include <cmath>
@@ -783,7 +785,7 @@ GraphLine &lineAtOffset(std::vector<GraphLine> &graphLines, int offset)
}
// disable bold, italic and underline on |
-const QLatin1String graphSymbol("\x1b[21;23;24m|");
+const QLatin1String graphSymbol("\x1b[22;23;24m|");
// reverse video
const QLatin1String nameStyle("\x1b[7m");
@@ -793,8 +795,8 @@ const QLatin1String nameStyle("\x1b[7m");
class DebugSyntaxHighlighter : public KSyntaxHighlighting::AbstractHighlighter
{
public:
- using TraceOption = KSyntaxHighlighting::AnsiHighlighter::TraceOption;
- using TraceOptions = KSyntaxHighlighting::AnsiHighlighter::TraceOptions;
+ using Option = KSyntaxHighlighting::AnsiHighlighter::Option;
+ using Options = KSyntaxHighlighting::AnsiHighlighter::Options;
void setDefinition(const KSyntaxHighlighting::Definition &def) override
{
@@ -815,14 +817,14 @@ public:
QLatin1String infoStyle,
QLatin1String editorBackground,
const std::vector<QPair<QString, QString>> &ansiStyles,
- TraceOptions traceOptions)
+ Options options)
{
initRegionStyles(ansiStyles);
- m_hasFormatTrace = traceOptions.testFlag(TraceOption::Format);
- m_hasRegionTrace = traceOptions.testFlag(TraceOption::Region);
- m_hasStackSizeTrace = traceOptions.testFlag(TraceOption::StackSize);
- m_hasContextTrace = traceOptions.testFlag(TraceOption::Context);
+ m_hasFormatTrace = options.testFlag(Option::TraceFormat);
+ m_hasRegionTrace = options.testFlag(Option::TraceRegion);
+ m_hasStackSizeTrace = options.testFlag(Option::TraceStackSize);
+ m_hasContextTrace = options.testFlag(Option::TraceContext);
const bool hasFormatOrContextTrace = m_hasFormatTrace || m_hasContextTrace || m_hasStackSizeTrace;
const bool hasSeparator = hasFormatOrContextTrace && m_hasRegionTrace;
@@ -831,6 +833,7 @@ public:
bool firstLine = true;
State state;
QString currentLine;
+ const bool isUnbuffered = options.testFlag(Option::Unbuffered);
while (in.readLineInto(&currentLine)) {
auto oldState = state;
state = highlightLine(currentLine, state);
@@ -864,6 +867,10 @@ public:
}
m_highlightedFragments.clear();
+
+ if (isUnbuffered) {
+ out.flush();
+ }
}
}
@@ -970,12 +977,14 @@ private:
QString label;
if (m_hasStackSizeTrace) {
- label += QLatin1Char('(') % QString::number(stateData->size()) % QLatin1Char(')');
+ // first state is empty
+ int stateSize = stateData ? stateData->size() : 0;
+ label = QLatin1Char('(') % QString::number(stateSize) % QLatin1Char(')');
}
if (m_hasContextTrace) {
// first state is empty
- if (stateData->isEmpty()) {
+ if (!stateData) {
return label + QStringLiteral("[???]");
}
@@ -1138,7 +1147,7 @@ private:
QString name;
int offset;
int length;
- quint16 formatId;
+ int formatId;
};
struct ContextCaptureHighlighter : KSyntaxHighlighting::AbstractHighlighter {
@@ -1168,7 +1177,7 @@ private:
int depth;
int offset;
int bindIndex;
- quint16 regionId;
+ int regionId;
State state;
};
@@ -1190,7 +1199,7 @@ private:
};
} // anonymous namespace
-class KSyntaxHighlighting::AnsiHighlighterPrivate
+class KSyntaxHighlighting::AnsiHighlighterPrivate : public AbstractHighlighterPrivate
{
public:
QTextStream out;
@@ -1201,7 +1210,7 @@ public:
};
AnsiHighlighter::AnsiHighlighter()
- : d(new AnsiHighlighterPrivate())
+ : AbstractHighlighter(new AnsiHighlighterPrivate())
{
}
@@ -1209,6 +1218,7 @@ AnsiHighlighter::~AnsiHighlighter() = default;
void AnsiHighlighter::setOutputFile(const QString &fileName)
{
+ Q_D(AnsiHighlighter);
if (d->file.isOpen()) {
d->file.close();
}
@@ -1218,21 +1228,16 @@ void AnsiHighlighter::setOutputFile(const QString &fileName)
return;
}
d->out.setDevice(&d->file);
-#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
- d->out.setCodec("UTF-8");
-#endif
}
void AnsiHighlighter::setOutputFile(FILE *fileHandle)
{
+ Q_D(AnsiHighlighter);
d->file.open(fileHandle, QIODevice::WriteOnly);
d->out.setDevice(&d->file);
-#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
- d->out.setCodec("UTF-8");
-#endif
}
-void AnsiHighlighter::highlightFile(const QString &fileName, AnsiFormat format, bool useEditorBackground, TraceOptions traceOptions)
+void AnsiHighlighter::highlightFile(const QString &fileName, AnsiFormat format, Options options)
{
QFileInfo fi(fileName);
QFile f(fileName);
@@ -1241,19 +1246,21 @@ void AnsiHighlighter::highlightFile(const QString &fileName, AnsiFormat format,
return;
}
- highlightData(&f, format, useEditorBackground, traceOptions);
+ highlightData(&f, format, options);
}
-void AnsiHighlighter::highlightData(QIODevice *dev, AnsiFormat format, bool useEditorBackground, TraceOptions traceOptions)
+void AnsiHighlighter::highlightData(QIODevice *dev, AnsiFormat format, Options options)
{
+ Q_D(AnsiHighlighter);
+
if (!d->out.device()) {
qCWarning(Log) << "No output stream defined!";
return;
}
const auto is256Colors = (format == AnsiFormat::XTerm256Color);
- const auto theme = this->theme();
- const auto definition = this->definition();
+ const auto &theme = d->m_theme;
+ const auto &definition = d->m_definition;
auto definitions = definition.includedDefinitions();
definitions.append(definition);
@@ -1265,6 +1272,8 @@ void AnsiHighlighter::highlightData(QIODevice *dev, AnsiFormat format, bool useE
QLatin1String foregroundDefaultColor;
QLatin1String backgroundDefaultColor;
+ const bool useEditorBackground = options.testFlag(Option::UseEditorBackground);
+
// https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_parameters
if (useEditorBackground) {
@@ -1277,23 +1286,19 @@ void AnsiHighlighter::highlightData(QIODevice *dev, AnsiFormat format, bool useE
backgroundDefaultColor = backgroundColorBuffer.latin1().mid(2);
}
- // ansiStyles must not be empty for applyFormat to work even with a definition without any context
- if (d->ansiStyles.empty()) {
- d->ansiStyles.resize(32);
- } else {
- d->ansiStyles[0].first.clear();
- d->ansiStyles[0].second.clear();
+ int maxId = 0;
+ for (const auto &definition : std::as_const(definitions)) {
+ for (const auto &format : std::as_const(DefinitionData::get(definition)->formats)) {
+ maxId = qMax(maxId, format.id());
+ }
}
+ d->ansiStyles.clear();
+ // ansiStyles must not be empty for applyFormat to work even with a definition without any context
+ d->ansiStyles.resize(maxId + 1);
// initialize ansiStyles
- for (auto &&definition : std::as_const(definitions)) {
- for (auto &&format : std::as_const(DefinitionData::get(definition)->formats)) {
- const auto id = format.id();
- if (id >= d->ansiStyles.size()) {
- // better than id + 1 to avoid successive allocations
- d->ansiStyles.resize(id * 2);
- }
-
+ for (const auto &definition : std::as_const(definitions)) {
+ for (const auto &format : std::as_const(DefinitionData::get(definition)->formats)) {
AnsiBuffer buffer;
buffer.append(QLatin1String("\x1b["));
@@ -1329,7 +1334,8 @@ void AnsiHighlighter::highlightData(QIODevice *dev, AnsiFormat format, bool useE
// if there is ANSI style
if (buffer.latin1().size() > 2) {
buffer.setFinalStyle();
- d->ansiStyles[id].first = buffer.latin1();
+ auto &style = d->ansiStyles[format.id()];
+ style.first = buffer.latin1();
if (useEditorBackground) {
buffer.clear();
@@ -1338,11 +1344,11 @@ void AnsiHighlighter::highlightData(QIODevice *dev, AnsiFormat format, bool useE
buffer.append(hasEffect ? QLatin1String("\x1b[0;") : QLatin1String("\x1b["));
buffer.append(backgroundDefaultColor);
buffer.setFinalStyle();
- d->ansiStyles[id].second = buffer.latin1();
+ style.second = buffer.latin1();
} else if (hasEffect) {
buffer.append(QLatin1String("\x1b["));
if (hasBold) {
- buffer.append(QLatin1String("21;"));
+ buffer.append(QLatin1String("22;"));
}
if (hasItalic) {
buffer.append(QLatin1String("23;"));
@@ -1354,10 +1360,10 @@ void AnsiHighlighter::highlightData(QIODevice *dev, AnsiFormat format, bool useE
buffer.append(QLatin1String("29;"));
}
buffer.setFinalStyle();
- d->ansiStyles[id].second = buffer.latin1();
+ style.second = buffer.latin1();
}
} else {
- d->ansiStyles[id].second = QStringLiteral("\x1b[0m");
+ style.second = QStringLiteral("\x1b[0m");
}
}
}
@@ -1370,13 +1376,11 @@ void AnsiHighlighter::highlightData(QIODevice *dev, AnsiFormat format, bool useE
}
QTextStream in(dev);
-#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
- in.setCodec("UTF-8");
-#endif
- if (!traceOptions) {
+ if (!options.testAnyFlag(Option::TraceAll)) {
State state;
QString currentLine;
+ const bool isUnbuffered = options.testFlag(Option::Unbuffered);
while (in.readLineInto(&currentLine)) {
d->currentLine = currentLine;
state = highlightLine(d->currentLine, state);
@@ -1386,6 +1390,10 @@ void AnsiHighlighter::highlightData(QIODevice *dev, AnsiFormat format, bool useE
} else {
d->out << QLatin1Char('\n');
}
+
+ if (isUnbuffered) {
+ d->out.flush();
+ }
}
} else {
AnsiBuffer buffer;
@@ -1394,7 +1402,7 @@ void AnsiHighlighter::highlightData(QIODevice *dev, AnsiFormat format, bool useE
buffer.setFinalStyle();
DebugSyntaxHighlighter debugHighlighter;
debugHighlighter.setDefinition(definition);
- debugHighlighter.highlightData(in, d->out, buffer.latin1(), backgroundDefaultColor, d->ansiStyles, traceOptions);
+ debugHighlighter.highlightData(in, d->out, buffer.latin1(), backgroundDefaultColor, d->ansiStyles, options);
}
if (useEditorBackground) {
@@ -1408,6 +1416,7 @@ void AnsiHighlighter::highlightData(QIODevice *dev, AnsiFormat format, bool useE
void AnsiHighlighter::applyFormat(int offset, int length, const Format &format)
{
+ Q_D(AnsiHighlighter);
auto const &ansiStyle = d->ansiStyles[format.id()];
d->out << ansiStyle.first << d->currentLine.mid(offset, length) << ansiStyle.second;
}
diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/ansihighlighter.h b/src/libs/3rdparty/syntax-highlighting/src/lib/ansihighlighter.h
index ffb13f38f3..0942aa0242 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/lib/ansihighlighter.h
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/ansihighlighter.h
@@ -11,10 +11,11 @@
#include "ksyntaxhighlighting_export.h"
#include <QFlags>
-#include <QIODevice>
#include <QString>
-#include <memory>
+QT_BEGIN_NAMESPACE
+class QIODevice;
+QT_END_NAMESPACE
namespace KSyntaxHighlighting
{
@@ -29,24 +30,25 @@ public:
XTerm256Color,
};
- enum class TraceOption {
+ enum class Option {
NoOptions,
- Format = 1 << 0,
- Region = 1 << 1,
- Context = 1 << 2,
- StackSize = 1 << 3,
+ UseEditorBackground = 1 << 0,
+ Unbuffered = 1 << 1,
+
+ // Options that displays a useful visual aid for syntax creation
+ TraceFormat = 1 << 2,
+ TraceRegion = 1 << 3,
+ TraceContext = 1 << 4,
+ TraceStackSize = 1 << 5,
+ TraceAll = TraceFormat | TraceRegion | TraceContext | TraceStackSize,
};
- Q_DECLARE_FLAGS(TraceOptions, TraceOption)
+ Q_DECLARE_FLAGS(Options, Option)
AnsiHighlighter();
~AnsiHighlighter() override;
- void highlightFile(const QString &fileName,
- AnsiFormat format = AnsiFormat::TrueColor,
- bool useEditorBackground = true,
- TraceOptions traceOptions = TraceOptions());
- void
- highlightData(QIODevice *device, AnsiFormat format = AnsiFormat::TrueColor, bool useEditorBackground = true, TraceOptions traceOptions = TraceOptions());
+ void highlightFile(const QString &fileName, AnsiFormat format = AnsiFormat::TrueColor, Options options = Option::UseEditorBackground);
+ void highlightData(QIODevice *device, AnsiFormat format = AnsiFormat::TrueColor, Options options = Option::UseEditorBackground);
void setOutputFile(const QString &fileName);
void setOutputFile(FILE *fileHandle);
@@ -55,10 +57,10 @@ protected:
void applyFormat(int offset, int length, const Format &format) override;
private:
- std::unique_ptr<AnsiHighlighterPrivate> d;
+ Q_DECLARE_PRIVATE(AnsiHighlighter)
};
}
-Q_DECLARE_OPERATORS_FOR_FLAGS(KSyntaxHighlighting::AnsiHighlighter::TraceOptions)
+Q_DECLARE_OPERATORS_FOR_FLAGS(KSyntaxHighlighting::AnsiHighlighter::Options)
#endif // KSYNTAXHIGHLIGHTING_ANSIHIGHLIGHTER_H
diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/context.cpp b/src/libs/3rdparty/syntax-highlighting/src/lib/context.cpp
index ff5254cb6e..af269d14d0 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/lib/context.cpp
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/context.cpp
@@ -38,7 +38,15 @@ void Context::resolveContexts(DefinitionData &def, const HighlightingContextData
m_lineEndContext.resolve(def, data.lineEndContext);
m_lineEmptyContext.resolve(def, data.lineEmptyContext);
m_fallthroughContext.resolve(def, data.fallthroughContext);
- m_fallthrough = !m_fallthroughContext.isStay();
+ m_stopEmptyLineContextSwitchLoop = data.stopEmptyLineContextSwitchLoop;
+
+ /**
+ * line end context switches only when lineEmptyContext is #stay. This avoids
+ * skipping empty lines after a line continuation character (see bug 405903)
+ */
+ if (m_lineEmptyContext.isStay()) {
+ m_lineEmptyContext = m_lineEndContext;
+ }
m_rules.reserve(data.rules.size());
for (const auto &ruleData : data.rules) {
@@ -65,6 +73,7 @@ void Context::resolveIncludes(DefinitionData &def)
for (auto it = m_rules.begin(); it != m_rules.end();) {
const IncludeRules *includeRules = it->get()->castToIncludeRules();
if (!includeRules) {
+ m_hasDynamicRule = m_hasDynamicRule || it->get()->isDynamic();
++it;
continue;
}
@@ -111,6 +120,8 @@ void Context::resolveIncludes(DefinitionData &def)
context->resolveIncludes(*defData);
}
+ m_hasDynamicRule = m_hasDynamicRule || context->m_hasDynamicRule;
+
/**
* handle included attribute
* transitive closure: we might include attributes included from somewhere else
diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/context_p.h b/src/libs/3rdparty/syntax-highlighting/src/lib/context_p.h
index 7e077b5a24..8cf0f1bfab 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/lib/context_p.h
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/context_p.h
@@ -16,10 +16,6 @@
#include <vector>
-QT_BEGIN_NAMESPACE
-class QXmlStreamReader;
-QT_END_NAMESPACE
-
namespace KSyntaxHighlighting
{
class DefinitionData;
@@ -52,7 +48,17 @@ public:
bool fallthrough() const
{
- return m_fallthrough;
+ return !m_fallthroughContext.isStay();
+ }
+
+ bool hasDynamicRule() const
+ {
+ return m_hasDynamicRule;
+ }
+
+ bool stopEmptyLineContextSwitchLoop() const
+ {
+ return m_stopEmptyLineContextSwitchLoop;
}
const ContextSwitch &fallthroughContext() const
@@ -96,7 +102,8 @@ private:
Format m_attributeFormat;
ResolveState m_resolveState = Unresolved;
- bool m_fallthrough = false;
+ bool m_hasDynamicRule = false;
+ bool m_stopEmptyLineContextSwitchLoop = true;
bool m_indentationBasedFolding;
};
}
diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/definition.cpp b/src/libs/3rdparty/syntax-highlighting/src/lib/definition.cpp
index 670dfddedb..e2cca6da71 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/lib/definition.cpp
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/definition.cpp
@@ -26,8 +26,6 @@
#include <QCborMap>
#include <QCoreApplication>
#include <QFile>
-#include <QHash>
-#include <QStringList>
#include <QXmlStreamReader>
#include <algorithm>
@@ -43,13 +41,8 @@ DefinitionData::DefinitionData()
DefinitionData::~DefinitionData() = default;
-DefinitionData *DefinitionData::get(const Definition &def)
-{
- return def.d.get();
-}
-
Definition::Definition()
- : d(new DefinitionData)
+ : d(std::make_shared<DefinitionData>())
{
d->q = *this;
}
@@ -63,6 +56,9 @@ Definition &Definition::operator=(const Definition &) = default;
Definition::Definition(std::shared_ptr<DefinitionData> &&dd)
: d(std::move(dd))
{
+ if (!d) {
+ Definition().d.swap(d);
+ }
}
bool Definition::operator==(const Definition &other) const
@@ -92,7 +88,10 @@ QString Definition::name() const
QString Definition::translatedName() const
{
- return QCoreApplication::instance()->translate("Language", d->name.toUtf8().constData());
+ if (d->translatedName.isEmpty()) {
+ d->translatedName = QCoreApplication::instance()->translate("Language", d->nameUtf8.isEmpty() ? d->name.toUtf8().constData() : d->nameUtf8.constData());
+ }
+ return d->translatedName;
}
QString Definition::section() const
@@ -102,15 +101,19 @@ QString Definition::section() const
QString Definition::translatedSection() const
{
- return QCoreApplication::instance()->translate("Language Section", d->section.toUtf8().constData());
+ if (d->translatedSection.isEmpty()) {
+ d->translatedSection = QCoreApplication::instance()->translate("Language Section",
+ d->sectionUtf8.isEmpty() ? d->section.toUtf8().constData() : d->sectionUtf8.constData());
+ }
+ return d->translatedSection;
}
-QVector<QString> Definition::mimeTypes() const
+QList<QString> Definition::mimeTypes() const
{
return d->mimetypes;
}
-QVector<QString> Definition::extensions() const
+QList<QString> Definition::extensions() const
{
return d->extensions;
}
@@ -218,12 +221,12 @@ bool Definition::setKeywordList(const QString &name, const QStringList &content)
}
}
-QVector<Format> Definition::formats() const
+QList<Format> Definition::formats() const
{
d->load();
// sort formats so that the order matches the order of the itemDatas in the xml files.
- auto formatList = QVector<Format>::fromList(d->formats.values());
+ auto formatList = d->formats.values();
std::sort(formatList.begin(), formatList.end(), [](const KSyntaxHighlighting::Format &lhs, const KSyntaxHighlighting::Format &rhs) {
return lhs.id() < rhs.id();
});
@@ -231,13 +234,13 @@ QVector<Format> Definition::formats() const
return formatList;
}
-QVector<Definition> Definition::includedDefinitions() const
+QList<Definition> Definition::includedDefinitions() const
{
d->load();
// init worklist and result used as guard with this definition
- QVector<const DefinitionData *> queue{d.get()};
- QVector<Definition> definitions{*this};
+ QList<const DefinitionData *> queue{d.get()};
+ QList<Definition> definitions{*this};
while (!queue.empty()) {
const auto *def = queue.back();
queue.pop_back();
@@ -275,7 +278,7 @@ QPair<QString, QString> Definition::multiLineCommentMarker() const
return {d->multiLineCommentStartMarker, d->multiLineCommentEndMarker};
}
-QVector<QPair<QChar, QString>> Definition::characterEncodings() const
+QList<QPair<QChar, QString>> Definition::characterEncodings() const
{
d->load();
return d->characterEncodings;
@@ -394,7 +397,11 @@ void DefinitionData::clear()
characterEncodings.clear();
fileName.clear();
+ nameUtf8.clear();
+ translatedName.clear();
section.clear();
+ sectionUtf8.clear();
+ translatedSection.clear();
style.clear();
indenter.clear();
author.clear();
@@ -405,6 +412,9 @@ void DefinitionData::clear()
version = 0.0f;
priority = 0;
hidden = false;
+
+ // purge our cache that is used to unify states
+ unify.clear();
}
bool DefinitionData::loadMetaData(const QString &definitionFileName)
@@ -433,7 +443,9 @@ bool DefinitionData::loadMetaData(const QString &definitionFileName)
bool DefinitionData::loadMetaData(const QString &file, const QCborMap &obj)
{
name = obj.value(QLatin1String("name")).toString();
+ nameUtf8 = obj.value(QLatin1String("name")).toByteArray();
section = obj.value(QLatin1String("section")).toString();
+ sectionUtf8 = obj.value(QLatin1String("section")).toByteArray();
version = obj.value(QLatin1String("version")).toInteger();
priority = obj.value(QLatin1String("priority")).toInteger();
style = obj.value(QLatin1String("style")).toString();
@@ -444,13 +456,10 @@ 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)) {
- extensions.push_back(ext);
- }
+ extensions = exts.split(QLatin1Char(';'), Qt::SkipEmptyParts);
+
const auto mts = obj.value(QLatin1String("mimetype")).toString();
- for (const auto &mt : mts.split(QLatin1Char(';'), Qt::SkipEmptyParts)) {
- mimetypes.push_back(mt);
- }
+ mimetypes = mts.split(QLatin1Char(';'), Qt::SkipEmptyParts);
return true;
}
@@ -805,10 +814,10 @@ bool DefinitionData::checkKateVersion(QStringView verStr)
qCWarning(Log) << "Skipping" << fileName << "due to having no valid kateversion attribute:" << verStr;
return false;
}
- const auto major = verStr.left(idx).toString().toInt();
- const auto minor = verStr.mid(idx + 1).toString().toInt();
+ const auto major = verStr.left(idx).toInt();
+ const auto minor = verStr.mid(idx + 1).toInt();
- if (major > SyntaxHighlighting_VERSION_MAJOR || (major == SyntaxHighlighting_VERSION_MAJOR && minor > SyntaxHighlighting_VERSION_MINOR)) {
+ if (major > KSYNTAXHIGHLIGHTING_VERSION_MAJOR || (major == KSYNTAXHIGHLIGHTING_VERSION_MAJOR && minor > KSYNTAXHIGHLIGHTING_VERSION_MINOR)) {
qCWarning(Log) << "Skipping" << fileName << "due to being too new, version:" << verStr;
return false;
}
@@ -834,34 +843,20 @@ void DefinitionData::addImmediateIncludedDefinition(const Definition &def)
DefinitionRef::DefinitionRef() = default;
-DefinitionRef::DefinitionRef(const Definition &def)
+DefinitionRef::DefinitionRef(const Definition &def) noexcept
: d(def.d)
{
}
-DefinitionRef::DefinitionRef(Definition &&def)
- : d(std::move(def.d))
-{
-}
-
-DefinitionRef &DefinitionRef::operator=(const Definition &def)
+DefinitionRef &DefinitionRef::operator=(const Definition &def) noexcept
{
d = def.d;
return *this;
}
-DefinitionRef &DefinitionRef::operator=(Definition &&def)
-{
- d = std::move(def.d);
- return *this;
-}
-
Definition DefinitionRef::definition() const
{
- if (!d.expired()) {
- return Definition(d.lock());
- }
- return Definition();
+ return Definition(d.lock());
}
bool DefinitionRef::operator==(const DefinitionRef &other) const
@@ -873,3 +868,5 @@ bool DefinitionRef::operator==(const Definition &other) const
{
return !d.owner_before(other.d) && !other.d.owner_before(d);
}
+
+#include "moc_definition.cpp"
diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/definition.h b/src/libs/3rdparty/syntax-highlighting/src/lib/definition.h
index 05757ea52a..e69492bee4 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/lib/definition.h
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/definition.h
@@ -10,16 +10,12 @@
#include "ksyntaxhighlighting_export.h"
+#include <QList>
#include <QPair>
-#include <QVector>
+#include <QString>
#include <memory>
#include <qobjectdefs.h>
-QT_BEGIN_NAMESPACE
-class QChar;
-class QString;
-QT_END_NAMESPACE
-
namespace KSyntaxHighlighting
{
class Context;
@@ -185,13 +181,13 @@ public:
/**
* Mime types associated with this syntax definition.
*/
- QVector<QString> mimeTypes() const;
+ QList<QString> mimeTypes() const;
/**
* File extensions associated with this syntax definition.
* The returned list contains wildcards.
*/
- QVector<QString> extensions() const;
+ QList<QString> extensions() const;
/**
* Returns the definition version.
@@ -360,7 +356,7 @@ public:
* The order of the Format items equals the order of the itemDatas in the xml file.
* @since 5.49
*/
- QVector<Format> formats() const;
+ QList<Format> formats() const;
/**
* Returns a list of Definitions that are referenced with the IncludeRules rule.
@@ -369,7 +365,7 @@ public:
*
* @since 5.49
*/
- QVector<Definition> includedDefinitions() const;
+ QList<Definition> includedDefinitions() const;
/**
* Returns the marker that starts a single line comment.
@@ -400,7 +396,7 @@ public:
* the string \"{A} represents the character Ä.
* @since 5.50
*/
- QVector<QPair<QChar, QString>> characterEncodings() const;
+ QList<QPair<QChar, QString>> characterEncodings() const;
/**
* @}
@@ -409,14 +405,14 @@ public:
private:
friend class DefinitionData;
friend class DefinitionRef;
- explicit Definition(std::shared_ptr<DefinitionData> &&dd);
+ KSYNTAXHIGHLIGHTING_NO_EXPORT explicit Definition(std::shared_ptr<DefinitionData> &&dd);
std::shared_ptr<DefinitionData> d;
};
}
QT_BEGIN_NAMESPACE
-Q_DECLARE_TYPEINFO(KSyntaxHighlighting::Definition, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(KSyntaxHighlighting::Definition, Q_RELOCATABLE_TYPE);
QT_END_NAMESPACE
#endif
diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/definition_p.h b/src/libs/3rdparty/syntax-highlighting/src/lib/definition_p.h
index 542f255b32..ec00b31897 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/lib/definition_p.h
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/definition_p.h
@@ -10,11 +10,13 @@
#include "definitionref_p.h"
#include "highlightingdata_p.hpp"
+#include "state.h"
#include "worddelimiters_p.h"
#include <QHash>
+#include <QList>
+#include <QSet>
#include <QString>
-#include <QVector>
#include <vector>
@@ -36,7 +38,10 @@ public:
DefinitionData(const DefinitionData &) = delete;
DefinitionData &operator=(const DefinitionData &) = delete;
- static DefinitionData *get(const Definition &def);
+ static DefinitionData *get(const Definition &def)
+ {
+ return def.d.get();
+ }
bool isLoaded() const;
bool loadMetaData(const QString &definitionFileName);
@@ -80,9 +85,9 @@ public:
std::vector<Context> contexts;
QHash<QString, Format> formats;
// data loaded from xml file and emptied after loading contexts
- QVector<HighlightingContextData> contextDatas;
+ QList<HighlightingContextData> contextDatas;
// Definition referenced by IncludeRules and ContextSwitch
- QVector<DefinitionRef> immediateIncludedDefinitions;
+ QList<DefinitionRef> immediateIncludedDefinitions;
WordDelimiters wordDelimiters;
WordDelimiters wordWrapDelimiters;
bool keywordIsLoaded = false;
@@ -93,21 +98,28 @@ public:
CommentPosition singleLineCommentPosition = CommentPosition::StartOfLine;
QString multiLineCommentStartMarker;
QString multiLineCommentEndMarker;
- QVector<QPair<QChar, QString>> characterEncodings;
+ QList<QPair<QChar, QString>> characterEncodings;
QString fileName;
QString name = QStringLiteral(QT_TRANSLATE_NOOP("Language", "None"));
+ QByteArray nameUtf8;
+ mutable QString translatedName;
QString section;
+ QByteArray sectionUtf8;
+ mutable QString translatedSection;
QString style;
QString indenter;
QString author;
QString license;
- QVector<QString> mimetypes;
- QVector<QString> extensions;
+ QList<QString> mimetypes;
+ QList<QString> extensions;
Qt::CaseSensitivity caseSensitive = Qt::CaseSensitive;
int version = 0;
int priority = 0;
bool hidden = false;
+
+ // cache that is used to unify states in AbstractHighlighter::highlightLine
+ mutable QSet<State> unify;
};
}
diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/definitiondownloader.cpp b/src/libs/3rdparty/syntax-highlighting/src/lib/definitiondownloader.cpp
index c1335789dc..88ba5d7759 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/lib/definitiondownloader.cpp
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/definitiondownloader.cpp
@@ -169,8 +169,8 @@ DefinitionDownloader::~DefinitionDownloader()
void DefinitionDownloader::start()
{
- const QString url = QLatin1String("https://www.kate-editor.org/syntax/update-") + QString::number(SyntaxHighlighting_VERSION_MAJOR) + QLatin1Char('.')
- + QString::number(SyntaxHighlighting_VERSION_MINOR) + QLatin1String(".xml");
+ const QString url = QLatin1String("https://www.kate-editor.org/syntax/update-") + QString::number(KSYNTAXHIGHLIGHTING_VERSION_MAJOR) + QLatin1Char('.')
+ + QString::number(KSYNTAXHIGHLIGHTING_VERSION_MINOR) + QLatin1String(".xml");
auto req = QNetworkRequest(QUrl(url));
req.setAttribute(QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::NoLessSafeRedirectPolicy);
auto reply = d->nam->get(req);
@@ -178,3 +178,5 @@ void DefinitionDownloader::start()
d->definitionListDownloadFinished(reply);
});
}
+
+#include "moc_definitiondownloader.cpp"
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 0bd805624d..a7ef08f614 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/lib/definitionref_p.h
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/definitionref_p.h
@@ -30,10 +30,8 @@ class DefinitionRef
{
public:
DefinitionRef();
- explicit DefinitionRef(const Definition &def);
- explicit DefinitionRef(Definition &&def);
- DefinitionRef &operator=(const Definition &def);
- DefinitionRef &operator=(Definition &&def);
+ explicit DefinitionRef(const Definition &def) noexcept;
+ DefinitionRef &operator=(const Definition &def) noexcept;
Definition definition() const;
diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/dynamicregexpcache_p.h b/src/libs/3rdparty/syntax-highlighting/src/lib/dynamicregexpcache_p.h
new file mode 100644
index 0000000000..dcef97a841
--- /dev/null
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/dynamicregexpcache_p.h
@@ -0,0 +1,39 @@
+/*
+ SPDX-FileCopyrightText: 2023 Jonathan Poelen <jonathan.poelen+kde@gmail.com>
+
+ SPDX-License-Identifier: MIT
+*/
+
+#ifndef KSYNTAXHIGHLIGHTING_DYNAMICREGEXPCACHE_P_H
+#define KSYNTAXHIGHLIGHTING_DYNAMICREGEXPCACHE_P_H
+
+#include <QCache>
+#include <QRegularExpression>
+#include <QString>
+
+#include <utility>
+
+namespace KSyntaxHighlighting
+{
+
+class DynamicRegexpCache
+{
+public:
+ const QRegularExpression &compileRegexp(QString &&pattern, QRegularExpression::PatternOptions patternOptions)
+ {
+ const auto key = std::pair{std::move(pattern), patternOptions};
+ if (const auto regexp = m_cache.object(key)) {
+ return *regexp;
+ }
+ auto regexp = new QRegularExpression(key.first, patternOptions);
+ m_cache.insert(key, regexp);
+ return *regexp;
+ }
+
+private:
+ QCache<std::pair<QString, QRegularExpression::PatternOptions>, QRegularExpression> m_cache;
+};
+
+}
+
+#endif
diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/foldingregion.cpp b/src/libs/3rdparty/syntax-highlighting/src/lib/foldingregion.cpp
index 3bca63eecd..9ed625b12e 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/lib/foldingregion.cpp
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/foldingregion.cpp
@@ -8,36 +8,39 @@
using namespace KSyntaxHighlighting;
-static_assert(sizeof(FoldingRegion) == 2, "FoldingRegion is size-sensitive to frequent use in KTextEditor!");
+static_assert(sizeof(FoldingRegion) == sizeof(int), "FoldingRegion is size-sensitive to frequent use in KTextEditor!");
-FoldingRegion::FoldingRegion()
- : m_type(None)
- , m_id(0)
-{
-}
+FoldingRegion::FoldingRegion() = default;
-FoldingRegion::FoldingRegion(Type type, quint16 id)
- : m_type(type)
- , m_id(id)
+FoldingRegion::FoldingRegion(Type type, int id)
+ : m_idWithType((type == End) ? -id : id)
{
}
bool FoldingRegion::operator==(const FoldingRegion &other) const
{
- return m_id == other.m_id && m_type == other.m_type;
+ return m_idWithType == other.m_idWithType;
}
bool FoldingRegion::isValid() const
{
- return type() != None;
+ return m_idWithType != 0;
}
-quint16 FoldingRegion::id() const
+int FoldingRegion::id() const
{
- return m_id;
+ return (m_idWithType < 0) ? -m_idWithType : m_idWithType;
}
FoldingRegion::Type FoldingRegion::type() const
{
- return static_cast<FoldingRegion::Type>(m_type);
+ if (isValid()) {
+ return (m_idWithType < 0) ? End : Begin;
+ }
+ return None;
+}
+
+FoldingRegion FoldingRegion::sibling() const
+{
+ return isValid() ? FoldingRegion(type() ? End : Begin, id()) : FoldingRegion();
}
diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/foldingregion.h b/src/libs/3rdparty/syntax-highlighting/src/lib/foldingregion.h
index ca4cacafb2..e2a9e1fc68 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/lib/foldingregion.h
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/foldingregion.h
@@ -22,7 +22,7 @@ public:
* Defines whether a FoldingRegion starts or ends a folding region.
*/
enum Type {
- //! Used internally as indicator for invalid FoldingRegion%s.
+ //! Used internally as indicator for an invalid FoldingRegion.
None,
//! Indicates the start of a FoldingRegion.
Begin,
@@ -64,7 +64,7 @@ public:
* brace, you need to do kind of a reference counting to find the correct
* closing brace.
*/
- quint16 id() const;
+ int id() const;
/**
* Returns whether this is the begin or end of a region.
@@ -74,12 +74,21 @@ public:
*/
Type type() const;
+ /**
+ * Returns the matching start or end region.
+ *
+ * @note Will return invalid region for an invalid region.
+ *
+ * @since 6.0
+ */
+ FoldingRegion sibling() const;
+
private:
friend class Rule;
- FoldingRegion(Type type, quint16 id);
+ KSYNTAXHIGHLIGHTING_NO_EXPORT FoldingRegion(Type type, int id);
- quint16 m_type : 2;
- quint16 m_id : 14;
+ // 0 is invalid, positive begin, negative end
+ int m_idWithType = 0;
};
}
diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/format.cpp b/src/libs/3rdparty/syntax-highlighting/src/lib/format.cpp
index 518a1e9ee9..2259cd3411 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/lib/format.cpp
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/format.cpp
@@ -98,7 +98,7 @@ QString Format::name() const
return d->name;
}
-quint16 Format::id() const
+int Format::id() const
{
return d->id;
}
diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/format.h b/src/libs/3rdparty/syntax-highlighting/src/lib/format.h
index 496a54e42c..397a1bab01 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/lib/format.h
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/format.h
@@ -13,12 +13,6 @@
#include <QExplicitlySharedDataPointer>
-QT_BEGIN_NAMESPACE
-class QColor;
-class QString;
-class QXmlStreamReader;
-QT_END_NAMESPACE
-
namespace KSyntaxHighlighting
{
class FormatPrivate;
@@ -54,7 +48,7 @@ public:
* the repository is reloaded (which also invalidatess the corresponding
* Definition anyway).
*/
- quint16 id() const;
+ int id() const;
/** Returns the underlying TextStyle of this Format.
* Every Theme::TextStyle is visually defined by a Theme. A Format uses one
@@ -192,7 +186,7 @@ private:
}
QT_BEGIN_NAMESPACE
-Q_DECLARE_TYPEINFO(KSyntaxHighlighting::Format, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(KSyntaxHighlighting::Format, Q_RELOCATABLE_TYPE);
QT_END_NAMESPACE
#endif // KSYNTAXHIGHLIGHTING_FORMAT_H
diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/format_p.h b/src/libs/3rdparty/syntax-highlighting/src/lib/format_p.h
index d8770f1ef7..ea74531445 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/lib/format_p.h
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/format_p.h
@@ -13,6 +13,10 @@
#include <QSharedData>
#include <QString>
+QT_BEGIN_NAMESPACE
+class QXmlStreamReader;
+QT_END_NAMESPACE
+
namespace KSyntaxHighlighting
{
class FormatPrivate : public QSharedData
@@ -21,6 +25,11 @@ public:
FormatPrivate() = default;
static FormatPrivate *detachAndGet(Format &format);
+ static std::intptr_t ptrId(const Format &format)
+ {
+ return std::intptr_t(format.d.data());
+ }
+
TextStyleData styleOverride(const Theme &theme) const;
void load(QXmlStreamReader &reader);
@@ -33,7 +42,7 @@ public:
QString name;
TextStyleData style;
Theme::TextStyle defaultStyle = Theme::Normal;
- quint16 id = 0;
+ int id = 0;
bool spellCheck = true;
};
diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/highlightingdata.cpp b/src/libs/3rdparty/syntax-highlighting/src/lib/highlightingdata.cpp
index adb1c346c1..d95ad43b7f 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/lib/highlightingdata.cpp
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/highlightingdata.cpp
@@ -379,6 +379,7 @@ void HighlightingContextData::load(const QString &defName, QXmlStreamReader &rea
lineEmptyContext = reader.attributes().value(QLatin1String("lineEmptyContext")).toString();
fallthroughContext = reader.attributes().value(QLatin1String("fallthroughContext")).toString();
noIndentationBasedFolding = Xml::attrToBool(reader.attributes().value(QLatin1String("noIndentationBasedFolding")));
+ stopEmptyLineContextSwitchLoop = Xml::attrToBool(reader.attributes().value(QLatin1String("stopEmptyLineContextSwitchLoop")));
rules.reserve(8);
diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/highlightingdata_p.hpp b/src/libs/3rdparty/syntax-highlighting/src/lib/highlightingdata_p.hpp
index 80aeaf4934..f49227dbf9 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/lib/highlightingdata_p.hpp
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/highlightingdata_p.hpp
@@ -208,6 +208,7 @@ public:
std::vector<Rule> rules;
+ bool stopEmptyLineContextSwitchLoop = false;
bool noIndentationBasedFolding = false;
};
}
diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/htmlhighlighter.cpp b/src/libs/3rdparty/syntax-highlighting/src/lib/htmlhighlighter.cpp
index 1f68e33d3e..928ae149d1 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/lib/htmlhighlighter.cpp
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/htmlhighlighter.cpp
@@ -6,7 +6,9 @@
*/
#include "htmlhighlighter.h"
+#include "abstracthighlighter_p.h"
#include "definition.h"
+#include "definition_p.h"
#include "format.h"
#include "ksyntaxhighlighting_logging.h"
#include "state.h"
@@ -14,21 +16,22 @@
#include <QFile>
#include <QFileInfo>
+#include <QIODevice>
#include <QTextStream>
-#include <QVarLengthArray>
using namespace KSyntaxHighlighting;
-class KSyntaxHighlighting::HtmlHighlighterPrivate
+class KSyntaxHighlighting::HtmlHighlighterPrivate : public AbstractHighlighterPrivate
{
public:
std::unique_ptr<QTextStream> out;
std::unique_ptr<QFile> file;
QString currentLine;
+ std::vector<QString> htmlStyles;
};
HtmlHighlighter::HtmlHighlighter()
- : d(new HtmlHighlighterPrivate())
+ : AbstractHighlighter(new HtmlHighlighterPrivate())
{
}
@@ -38,27 +41,21 @@ HtmlHighlighter::~HtmlHighlighter()
void HtmlHighlighter::setOutputFile(const QString &fileName)
{
+ Q_D(HtmlHighlighter);
d->file.reset(new QFile(fileName));
if (!d->file->open(QFile::WriteOnly | QFile::Truncate)) {
qCWarning(Log) << "Failed to open output file" << fileName << ":" << d->file->errorString();
return;
}
d->out.reset(new QTextStream(d->file.get()));
-#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
d->out->setEncoding(QStringConverter::Utf8);
-#else
- d->out->setCodec("UTF-8");
-#endif
}
void HtmlHighlighter::setOutputFile(FILE *fileHandle)
{
+ Q_D(HtmlHighlighter);
d->out.reset(new QTextStream(fileHandle, QIODevice::WriteOnly));
-#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
d->out->setEncoding(QStringConverter::Utf8);
-#else
- d->out->setCodec("UTF-8");
-#endif
}
void HtmlHighlighter::highlightFile(const QString &fileName, const QString &title)
@@ -79,7 +76,7 @@ void HtmlHighlighter::highlightFile(const QString &fileName, const QString &titl
/**
* @brief toHtmlRgba
- * Converts QColor -> rgba(r, g, b, a) if there is an alpha channel
+ * Converts QColor -> #RRGGBBAA if there is an alpha channel
* otherwise it will just return the hexcode. This is because QColor
* outputs #AARRGGBB, whereas browser support #RRGGBBAA.
*
@@ -91,22 +88,24 @@ static QString toHtmlRgbaString(const QColor &color)
if (color.alpha() == 0xFF) {
return color.name();
}
-
- QString rgba = QStringLiteral("rgba(");
- rgba.append(QString::number(color.red()));
- rgba.append(QLatin1Char(','));
- rgba.append(QString::number(color.green()));
- rgba.append(QLatin1Char(','));
- rgba.append(QString::number(color.blue()));
- rgba.append(QLatin1Char(','));
- // this must be alphaF
- rgba.append(QString::number(color.alphaF()));
- rgba.append(QLatin1Char(')'));
- return rgba;
+ static const char16_t digits[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
+ QChar hexcode[9];
+ hexcode[0] = QLatin1Char('#');
+ hexcode[1] = digits[color.red() >> 4];
+ hexcode[2] = digits[color.red() & 0xf];
+ hexcode[3] = digits[color.green() >> 4];
+ hexcode[4] = digits[color.green() & 0xf];
+ hexcode[5] = digits[color.blue() >> 4];
+ hexcode[6] = digits[color.blue() & 0xf];
+ hexcode[7] = digits[color.alpha() >> 4];
+ hexcode[8] = digits[color.alpha() & 0xf];
+ return QString(hexcode, 9);
}
void HtmlHighlighter::highlightData(QIODevice *dev, const QString &title)
{
+ Q_D(HtmlHighlighter);
+
if (!d->out) {
qCWarning(Log) << "No output stream defined!";
return;
@@ -114,29 +113,73 @@ void HtmlHighlighter::highlightData(QIODevice *dev, const QString &title)
QString htmlTitle;
if (title.isEmpty()) {
- htmlTitle = QStringLiteral("Kate Syntax Highlighter");
+ htmlTitle = QStringLiteral("KSyntaxHighlighter");
} else {
htmlTitle = title.toHtmlEscaped();
}
+ const auto &theme = d->m_theme;
+ const auto &definition = d->m_definition;
+
+ auto definitions = definition.includedDefinitions();
+ definitions.append(definition);
+
+ int maxId = 0;
+ for (const auto &definition : std::as_const(definitions)) {
+ for (const auto &format : std::as_const(DefinitionData::get(definition)->formats)) {
+ maxId = qMax(maxId, format.id());
+ }
+ }
+ d->htmlStyles.clear();
+ // htmlStyles must not be empty for applyFormat to work even with a definition without any context
+ d->htmlStyles.resize(maxId + 1);
+
+ // initialize htmlStyles
+ for (const auto &definition : std::as_const(definitions)) {
+ for (const auto &format : std::as_const(DefinitionData::get(definition)->formats)) {
+ auto &buffer = d->htmlStyles[format.id()];
+ if (format.hasTextColor(theme)) {
+ buffer += QStringLiteral("color:") + toHtmlRgbaString(format.textColor(theme)) + QStringLiteral(";");
+ }
+ if (format.hasBackgroundColor(theme)) {
+ buffer += QStringLiteral("background-color:") + toHtmlRgbaString(format.backgroundColor(theme)) + QStringLiteral(";");
+ }
+ if (format.isBold(theme)) {
+ buffer += QStringLiteral("font-weight:bold;");
+ }
+ if (format.isItalic(theme)) {
+ buffer += QStringLiteral("font-style:italic;");
+ }
+ if (format.isUnderline(theme)) {
+ buffer += QStringLiteral("text-decoration:underline;");
+ }
+ if (format.isStrikeThrough(theme)) {
+ buffer += QStringLiteral("text-decoration:line-through;");
+ }
+
+ if (!buffer.isEmpty()) {
+ buffer.insert(0, QStringLiteral("<span style=\""));
+ // replace last ';'
+ buffer.back() = u'"';
+ buffer += u'>';
+ }
+ }
+ }
+
State state;
*d->out << "<!DOCTYPE html>\n";
*d->out << "<html><head>\n";
*d->out << "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\"/>\n";
*d->out << "<title>" << htmlTitle << "</title>\n";
- *d->out << "<meta name=\"generator\" content=\"KF5::SyntaxHighlighting - Definition (" << definition().name() << ") - Theme (" << theme().name()
- << ")\"/>\n";
+ *d->out << "<meta name=\"generator\" content=\"KF5::SyntaxHighlighting - Definition (" << definition.name() << ") - Theme (" << theme.name() << ")\"/>\n";
*d->out << "</head><body";
- *d->out << " style=\"background-color:" << toHtmlRgbaString(QColor::fromRgba(theme().editorColor(Theme::BackgroundColor)));
- if (theme().textColor(Theme::Normal)) {
- *d->out << ";color:" << toHtmlRgbaString(QColor::fromRgba(theme().textColor(Theme::Normal)));
+ *d->out << " style=\"background-color:" << toHtmlRgbaString(QColor::fromRgba(theme.editorColor(Theme::BackgroundColor)));
+ if (theme.textColor(Theme::Normal)) {
+ *d->out << ";color:" << toHtmlRgbaString(QColor::fromRgba(theme.textColor(Theme::Normal)));
}
*d->out << "\"><pre>\n";
QTextStream in(dev);
-#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
- in.setCodec("UTF-8");
-#endif
while (in.readLineInto(&d->currentLine)) {
state = highlightLine(d->currentLine, state);
*d->out << "\n";
@@ -155,38 +198,24 @@ void HtmlHighlighter::applyFormat(int offset, int length, const Format &format)
return;
}
- // collect potential output, cheaper than thinking about "is there any?"
- QVarLengthArray<QString, 16> formatOutput;
- if (format.hasTextColor(theme())) {
- formatOutput << QStringLiteral("color:") << toHtmlRgbaString(format.textColor(theme())) << QStringLiteral(";");
- }
- if (format.hasBackgroundColor(theme())) {
- formatOutput << QStringLiteral("background-color:") << toHtmlRgbaString(format.backgroundColor(theme())) << QStringLiteral(";");
- }
- if (format.isBold(theme())) {
- formatOutput << QStringLiteral("font-weight:bold;");
- }
- if (format.isItalic(theme())) {
- formatOutput << QStringLiteral("font-style:italic;");
- }
- if (format.isUnderline(theme())) {
- formatOutput << QStringLiteral("text-decoration:underline;");
- }
- if (format.isStrikeThrough(theme())) {
- formatOutput << QStringLiteral("text-decoration:line-through;");
- }
+ Q_D(HtmlHighlighter);
- if (!formatOutput.isEmpty()) {
- *d->out << "<span style=\"";
- for (const auto &out : std::as_const(formatOutput)) {
- *d->out << out;
- }
- *d->out << "\">";
+ auto const &htmlStyle = d->htmlStyles[format.id()];
+
+ if (!htmlStyle.isEmpty()) {
+ *d->out << htmlStyle;
}
- *d->out << d->currentLine.mid(offset, length).toHtmlEscaped();
+ for (QChar ch : QStringView(d->currentLine).mid(offset, length)) {
+ if (ch == u'<')
+ *d->out << QStringLiteral("&lt;");
+ else if (ch == u'&')
+ *d->out << QStringLiteral("&amp;");
+ else
+ *d->out << ch;
+ }
- if (!formatOutput.isEmpty()) {
- *d->out << "</span>";
+ if (!htmlStyle.isEmpty()) {
+ *d->out << QStringLiteral("</span>");
}
}
diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/htmlhighlighter.h b/src/libs/3rdparty/syntax-highlighting/src/lib/htmlhighlighter.h
index 8754057345..741cb85103 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/lib/htmlhighlighter.h
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/htmlhighlighter.h
@@ -10,10 +10,11 @@
#include "abstracthighlighter.h"
#include "ksyntaxhighlighting_export.h"
-#include <QIODevice>
#include <QString>
-#include <memory>
+QT_BEGIN_NAMESPACE
+class QIODevice;
+QT_END_NAMESPACE
namespace KSyntaxHighlighting
{
@@ -35,7 +36,7 @@ protected:
void applyFormat(int offset, int length, const Format &format) override;
private:
- std::unique_ptr<HtmlHighlighterPrivate> d;
+ Q_DECLARE_PRIVATE(HtmlHighlighter)
};
}
diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/keywordlist.cpp b/src/libs/3rdparty/syntax-highlighting/src/lib/keywordlist.cpp
index 133b6d28ac..847f6af6d4 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/lib/keywordlist.cpp
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/keywordlist.cpp
@@ -47,7 +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), KeywordComparator{caseSensitive});
+ return std::binary_search(vectorToSearch.begin(), vectorToSearch.end(), str, KeywordComparator{caseSensitive});
}
void KeywordList::load(QXmlStreamReader &reader)
@@ -103,10 +103,7 @@ void KeywordList::initLookupForCaseSensitivity(Qt::CaseSensitivity caseSensitive
/**
* fill vector with refs to keywords
*/
- vectorToSort.reserve(m_keywords.size());
- for (const auto &keyword : std::as_const(m_keywords)) {
- vectorToSort.push_back(keyword);
- }
+ vectorToSort.assign(m_keywords.constBegin(), m_keywords.constEnd());
/**
* sort with right predicate
diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/matchresult_p.h b/src/libs/3rdparty/syntax-highlighting/src/lib/matchresult_p.h
index 1e0f7c6102..7112d4e291 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/lib/matchresult_p.h
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/matchresult_p.h
@@ -41,9 +41,9 @@ public:
* @param offset offset of match
* @param captures captures of the match
*/
- explicit MatchResult(const int offset, const QStringList &captures)
+ explicit MatchResult(const int offset, QStringList &&captures)
: m_offset(offset)
- , m_captures(captures)
+ , m_captures(std::move(captures))
{
}
@@ -69,7 +69,7 @@ public:
* Captures of the match.
* @return captured text of this match
*/
- const QStringList &captures() const
+ QStringList &captures()
{
return m_captures;
}
diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/repository.cpp b/src/libs/3rdparty/syntax-highlighting/src/lib/repository.cpp
index a12d4ba1a3..07c28454c5 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/lib/repository.cpp
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/repository.cpp
@@ -77,9 +77,9 @@ Definition findHighestPriorityDefinitionIf(const QMap<QString, Definition> &defs
}
template<typename UnaryPredicate>
-QVector<Definition> findDefinitionsIf(const QMap<QString, Definition> &defs, UnaryPredicate predicate)
+QList<Definition> findDefinitionsIf(const QMap<QString, Definition> &defs, UnaryPredicate predicate)
{
- QVector<Definition> matches;
+ QList<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();
@@ -127,7 +127,7 @@ Definition Repository::definitionForFileName(const QString &fileName) const
return findHighestPriorityDefinitionIf(d->m_defs, anyWildcardMatches(fileNameFromFilePath(fileName)));
}
-QVector<Definition> Repository::definitionsForFileName(const QString &fileName) const
+QList<Definition> Repository::definitionsForFileName(const QString &fileName) const
{
return findDefinitionsIf(d->m_defs, anyWildcardMatches(fileNameFromFilePath(fileName)));
}
@@ -137,22 +137,22 @@ Definition Repository::definitionForMimeType(const QString &mimeType) const
return findHighestPriorityDefinitionIf(d->m_defs, anyMimeTypeEquals(mimeType));
}
-QVector<Definition> Repository::definitionsForMimeType(const QString &mimeType) const
+QList<Definition> Repository::definitionsForMimeType(const QString &mimeType) const
{
return findDefinitionsIf(d->m_defs, anyMimeTypeEquals(mimeType));
}
-QVector<Definition> Repository::definitions() const
+QList<Definition> Repository::definitions() const
{
return d->m_sortedDefs;
}
-QVector<Theme> Repository::themes() const
+QList<Theme> Repository::themes() const
{
return d->m_themes;
}
-static auto lowerBoundTheme(const QVector<KSyntaxHighlighting::Theme> &themes, QStringView themeName)
+static auto lowerBoundTheme(const QList<KSyntaxHighlighting::Theme> &themes, QStringView themeName)
{
return std::lower_bound(themes.begin(), themes.end(), themeName, [](const Theme &lhs, QStringView rhs) {
return lhs.name() < rhs;
@@ -177,42 +177,32 @@ Theme Repository::defaultTheme(Repository::DefaultTheme t) const
return theme(QStringLiteral("Breeze Light"));
}
-Theme Repository::defaultTheme(Repository::DefaultTheme t)
-{
- return std::as_const(*this).defaultTheme(t);
-}
-
Theme Repository::themeForPalette(const QPalette &palette) const
{
const auto base = palette.color(QPalette::Base);
+ const auto highlight = palette.color(QPalette::Highlight).rgb();
- // find themes with matching background colors
- QVector<const KSyntaxHighlighting::Theme *> matchingThemes;
+ // find themes with matching background and highlight colors
+ const Theme *firstMatchingTheme = nullptr;
for (const auto &theme : std::as_const(d->m_themes)) {
- const auto background = theme.editorColor(KSyntaxHighlighting::Theme::EditorColorRole::BackgroundColor);
+ const auto background = theme.editorColor(Theme::EditorColorRole::BackgroundColor);
if (background == base.rgb()) {
- matchingThemes.append(&theme);
- }
- }
- 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 : std::as_const(matchingThemes)) {
- auto selection = theme->editorColor(KSyntaxHighlighting::Theme::EditorColorRole::TextSelection);
- if (selection == highlight.rgb()) {
- return *theme;
+ // find theme with a matching highlight color
+ auto selection = theme.editorColor(Theme::EditorColorRole::TextSelection);
+ if (selection == highlight) {
+ return theme;
+ }
+ if (!firstMatchingTheme) {
+ firstMatchingTheme = &theme;
}
}
- return *matchingThemes.first();
+ }
+ if (firstMatchingTheme) {
+ return *firstMatchingTheme;
}
// fallback to just use the default light or dark theme
- return defaultTheme((base.lightness() < 128) ? KSyntaxHighlighting::Repository::DarkTheme : KSyntaxHighlighting::Repository::LightTheme);
-}
-
-Theme Repository::themeForPalette(const QPalette &palette)
-{
- return std::as_const(*this).themeForPalette(palette);
+ return defaultTheme((base.lightness() < 128) ? Repository::DarkTheme : Repository::LightTheme);
}
void RepositoryPrivate::load(Repository *repo)
@@ -238,12 +228,6 @@ void RepositoryPrivate::load(Repository *repo)
QStandardPaths::LocateDirectory)) {
loadSyntaxFolder(repo, dir);
}
-
- // backward compatibility with Kate
- for (const auto &dir :
- QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("katepart5/syntax"), QStandardPaths::LocateDirectory)) {
- loadSyntaxFolder(repo, dir);
- }
#endif
// default resources are always used, this is the one location that has a index cbor file
@@ -377,25 +361,27 @@ void RepositoryPrivate::addTheme(const Theme &theme)
}
}
-quint16 RepositoryPrivate::foldingRegionId(const QString &defName, const QString &foldName)
+int RepositoryPrivate::foldingRegionId(const QString &defName, const QString &foldName)
{
const auto it = m_foldingRegionIds.constFind(qMakePair(defName, foldName));
if (it != m_foldingRegionIds.constEnd()) {
return it.value();
}
+ Q_ASSERT(m_foldingRegionId < std::numeric_limits<int>::max());
m_foldingRegionIds.insert(qMakePair(defName, foldName), ++m_foldingRegionId);
return m_foldingRegionId;
}
-quint16 RepositoryPrivate::nextFormatId()
+int RepositoryPrivate::nextFormatId()
{
- Q_ASSERT(m_formatId < std::numeric_limits<quint16>::max());
+ Q_ASSERT(m_formatId < std::numeric_limits<int>::max());
return ++m_formatId;
}
void Repository::reload()
{
- qCDebug(Log) << "Reloading syntax definitions!";
+ Q_EMIT aboutToReload();
+
for (const auto &def : std::as_const(d->m_sortedDefs)) {
DefinitionData::get(def)->clear();
}
@@ -410,6 +396,8 @@ void Repository::reload()
d->m_formatId = 0;
d->load(this);
+
+ Q_EMIT reloaded();
}
void Repository::addCustomSearchPath(const QString &path)
@@ -418,7 +406,9 @@ void Repository::addCustomSearchPath(const QString &path)
reload();
}
-QVector<QString> Repository::customSearchPaths() const
+QList<QString> Repository::customSearchPaths() const
{
return d->m_customSearchPaths;
}
+
+#include "moc_repository.cpp"
diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/repository.h b/src/libs/3rdparty/syntax-highlighting/src/lib/repository.h
index 7c74753bfe..612ba54d6a 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/lib/repository.h
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/repository.h
@@ -9,7 +9,8 @@
#include "ksyntaxhighlighting_export.h"
-#include <QVector>
+#include <QList>
+#include <QObject>
#include <QtGlobal>
#include <memory>
@@ -76,13 +77,6 @@ class Theme;
* map to $HOME/.local5/share/org.kde.syntax-highlighting/syntax and
* /usr/share/org.kde.syntax-highlighting/syntax.
*
- * -# Next, for backwards compatibility with Kate, all syntax highlighting
- * files are loaded that are located in
- * QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("katepart5/syntax"), QStandardPaths::LocateDirectory);
- * Again, under Unix, this uses $XDG_DATA_HOME and $XDG_DATA_DIRS, which
- * could map to $HOME/.local5/share/katepart5/syntax and
- * /usr/share/katepart5/syntax.
- *
* -# Then, all files compiled into the library through resources are loaded.
* The internal resource path is ":/org.kde.syntax-highlighting/syntax".
* This path should never be touched by other applications.
@@ -124,8 +118,12 @@ class Theme;
* @see Definition, Theme, AbstractHighlighter
* @since 5.28
*/
-class KSYNTAXHIGHLIGHTING_EXPORT Repository
+class KSYNTAXHIGHLIGHTING_EXPORT Repository : public QObject
{
+ Q_OBJECT
+ Q_PROPERTY(QList<KSyntaxHighlighting::Definition> definitions READ definitions NOTIFY reloaded)
+ Q_PROPERTY(QList<KSyntaxHighlighting::Theme> themes READ themes NOTIFY reloaded)
+
public:
/**
* Create a new syntax definition repository.
@@ -148,7 +146,7 @@ public:
* Therefore, only the string "JavaScript" will return a valid
* Definition file.
*/
- Definition definitionForName(const QString &defName) const;
+ Q_INVOKABLE KSyntaxHighlighting::Definition definitionForName(const QString &defName) const;
/**
* Returns the best matching Definition for the file named @p fileName.
@@ -159,7 +157,7 @@ public:
* If no match is found, Definition::isValid() of the returned instance
* returns false.
*/
- Definition definitionForFileName(const QString &fileName) const;
+ Q_INVOKABLE KSyntaxHighlighting::Definition definitionForFileName(const QString &fileName) const;
/**
* Returns all Definition%s for the file named @p fileName sorted by priority.
@@ -168,7 +166,7 @@ public:
*
* @since 5.56
*/
- QVector<Definition> definitionsForFileName(const QString &fileName) const;
+ Q_INVOKABLE QList<KSyntaxHighlighting::Definition> definitionsForFileName(const QString &fileName) const;
/**
* Returns the best matching Definition to the type named @p mimeType
@@ -178,34 +176,34 @@ public:
*
* @since 5.50
*/
- Definition definitionForMimeType(const QString &mimeType) const;
+ Q_INVOKABLE KSyntaxHighlighting::Definition definitionForMimeType(const QString &mimeType) const;
/**
* Returns all Definition%s to the type named @p mimeType sorted by priority
*
* @since 5.56
*/
- QVector<Definition> definitionsForMimeType(const QString &mimeType) const;
+ Q_INVOKABLE QList<KSyntaxHighlighting::Definition> definitionsForMimeType(const QString &mimeType) const;
/**
* Returns all available Definition%s.
* Definition%ss are ordered by translated section and translated names,
* for consistent displaying.
*/
- QVector<Definition> definitions() const;
+ Q_INVOKABLE QList<KSyntaxHighlighting::Definition> definitions() const;
/**
* Returns all available color themes.
* The returned list should never be empty.
*/
- QVector<Theme> themes() const;
+ Q_INVOKABLE QList<KSyntaxHighlighting::Theme> themes() const;
/**
* Returns the theme called @p themeName.
* If the requested theme cannot be found, the retunred Theme is invalid,
* see Theme::isValid().
*/
- Theme theme(const QString &themeName) const;
+ Q_INVOKABLE KSyntaxHighlighting::Theme theme(const QString &themeName) const;
/**
* Built-in default theme types.
@@ -217,21 +215,14 @@ public:
//! Theme with a dark background color.
DarkTheme
};
+ Q_ENUM(DefaultTheme)
/**
* Returns a default theme instance of the given type.
* The returned Theme is guaranteed to be a valid theme.
* @since 5.79
*/
- Theme defaultTheme(DefaultTheme t = LightTheme) const;
-
- /**
- * Returns a default theme instance of the given type.
- * The returned Theme is guaranteed to be a valid theme.
- *
- * KF6: remove in favor of const variant
- */
- Theme defaultTheme(DefaultTheme t = LightTheme);
+ Q_INVOKABLE KSyntaxHighlighting::Theme defaultTheme(DefaultTheme t = LightTheme) const;
/**
* Returns the best matching theme for the given palette
@@ -240,14 +231,6 @@ public:
Theme themeForPalette(const QPalette &palette) const;
/**
- * Returns the best matching theme for the given palette
- * @since 5.77
- *
- * KF6: remove in favor of const variant
- **/
- Theme themeForPalette(const QPalette &palette);
-
- /**
* Reloads the repository.
* This is a moderately expensive operations and should thus only be
* triggered when the installed syntax definition files changed.
@@ -278,7 +261,20 @@ public:
* @see addCustomSearchPath()
* @since 5.39
*/
- QVector<QString> customSearchPaths() const;
+ QList<QString> customSearchPaths() const;
+
+Q_SIGNALS:
+ /**
+ * This signal is emitted before the reload is started.
+ * @since 6.0
+ */
+ void aboutToReload();
+
+ /**
+ * This signal is emitted when the reload is finished.
+ * @since 6.0
+ */
+ void reloaded();
private:
Q_DISABLE_COPY(Repository)
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..bb9f8ba082 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/lib/repository_p.h
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/repository_p.h
@@ -8,11 +8,11 @@
#define KSYNTAXHIGHLIGHTING_REPOSITORY_P_H
#include <QHash>
-#include <QVector>
+#include <QList>
+#include <QMap>
+#include <QString>
-QT_BEGIN_NAMESPACE
-class QString;
-QT_END_NAMESPACE
+#include "dynamicregexpcache_p.h"
namespace KSyntaxHighlighting
{
@@ -36,22 +36,24 @@ public:
void loadThemeFolder(const QString &path);
void addTheme(const Theme &theme);
- quint16 foldingRegionId(const QString &defName, const QString &foldName);
- quint16 nextFormatId();
+ int foldingRegionId(const QString &defName, const QString &foldName);
+ int nextFormatId();
- QVector<QString> m_customSearchPaths;
+ QList<QString> m_customSearchPaths;
// sorted map to have deterministic iteration order for e.g. definitionsForFileName
QMap<QString, Definition> m_defs;
// this vector is sorted by translated sections/names
- QVector<Definition> m_sortedDefs;
+ QList<Definition> m_sortedDefs;
- QVector<Theme> m_themes;
+ QList<Theme> m_themes;
- QHash<QPair<QString, QString>, quint16> m_foldingRegionIds;
- quint16 m_foldingRegionId = 0;
- quint16 m_formatId = 0;
+ QHash<QPair<QString, QString>, int> m_foldingRegionIds;
+ int m_foldingRegionId = 0;
+ int m_formatId = 0;
+
+ DynamicRegexpCache m_dynamicRegexpCache;
};
}
diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/rule.cpp b/src/libs/3rdparty/syntax-highlighting/src/lib/rule.cpp
index 1d02bd6ac3..186ed16120 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/lib/rule.cpp
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/rule.cpp
@@ -1,20 +1,19 @@
/*
SPDX-FileCopyrightText: 2016 Volker Krause <vkrause@kde.org>
SPDX-FileCopyrightText: 2018 Christoph Cullmann <cullmann@kde.org>
- SPDX-FileCopyrightText: 2020 Jonathan Poelen <jonathan.poelen@gmail.com>
+ SPDX-FileCopyrightText: 2020 Jonathan Poelen <jonathan.poelen+kde@gmail.com>
SPDX-License-Identifier: MIT
*/
#include "context_p.h"
#include "definition_p.h"
+#include "dynamicregexpcache_p.h"
#include "ksyntaxhighlighting_logging.h"
#include "rule_p.h"
#include "worddelimiters_p.h"
#include "xml_p.h"
-#include <QString>
-
using namespace KSyntaxHighlighting;
// QChar::isDigit() match any digit in unicode (romain numeral, etc)
@@ -90,8 +89,8 @@ static int matchEscapedChar(QStringView text, int offset)
static QString replaceCaptures(const QString &pattern, const QStringList &captures, bool quote)
{
auto result = pattern;
- for (int i = captures.size() - 1; i >= 1; --i) {
- result.replace(QLatin1Char('%') + QString::number(i), quote ? QRegularExpression::escape(captures.at(i)) : captures.at(i));
+ for (int i = captures.size(); i >= 1; --i) {
+ result.replace(QLatin1Char('%') + QString::number(i), quote ? QRegularExpression::escape(captures.at(i - 1)) : captures.at(i - 1));
}
return result;
}
@@ -233,7 +232,7 @@ AnyChar::AnyChar(const HighlightingContextData::Rule::AnyChar &data)
{
}
-MatchResult AnyChar::doMatch(QStringView text, int offset, const QStringList &) const
+MatchResult AnyChar::doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const
{
if (m_chars.contains(text.at(offset))) {
return offset + 1;
@@ -243,15 +242,15 @@ MatchResult AnyChar::doMatch(QStringView text, int offset, const QStringList &)
DetectChar::DetectChar(const HighlightingContextData::Rule::DetectChar &data)
: m_char(data.char1)
- , m_captureIndex(data.dynamic ? data.char1.digitValue() : 0)
+ , m_captureIndex((data.dynamic ? data.char1.digitValue() : 0) - 1)
{
m_dynamic = data.dynamic;
}
-MatchResult DetectChar::doMatch(QStringView text, int offset, const QStringList &captures) const
+MatchResult DetectChar::doMatch(QStringView text, int offset, const QStringList &captures, DynamicRegexpCache &) const
{
if (m_dynamic) {
- if (m_captureIndex == 0 || captures.size() <= m_captureIndex || captures.at(m_captureIndex).isEmpty()) {
+ if (m_captureIndex == -1 || captures.size() <= m_captureIndex || captures.at(m_captureIndex).isEmpty()) {
return offset;
}
if (text.at(offset) == captures.at(m_captureIndex).at(0)) {
@@ -272,7 +271,7 @@ Detect2Chars::Detect2Chars(const HighlightingContextData::Rule::Detect2Chars &da
{
}
-MatchResult Detect2Chars::doMatch(QStringView text, int offset, const QStringList &) const
+MatchResult Detect2Chars::doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const
{
if (text.size() - offset < 2) {
return offset;
@@ -283,7 +282,7 @@ MatchResult Detect2Chars::doMatch(QStringView text, int offset, const QStringLis
return offset;
}
-MatchResult DetectIdentifier::doMatch(QStringView text, int offset, const QStringList &) const
+MatchResult DetectIdentifier::doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const
{
if (!text.at(offset).isLetter() && text.at(offset) != QLatin1Char('_')) {
return offset;
@@ -299,7 +298,7 @@ MatchResult DetectIdentifier::doMatch(QStringView text, int offset, const QStrin
return text.size();
}
-MatchResult DetectSpaces::doMatch(QStringView text, int offset, const QStringList &) const
+MatchResult DetectSpaces::doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const
{
while (offset < text.size() && text.at(offset).isSpace()) {
++offset;
@@ -313,7 +312,7 @@ Float::Float(DefinitionData &def, const HighlightingContextData::Rule::Float &da
resolveAdditionalWordDelimiters(m_wordDelimiters, data.wordDelimiters);
}
-MatchResult Float::doMatch(QStringView text, int offset, const QStringList &) const
+MatchResult Float::doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const
{
if (offset > 0 && !m_wordDelimiters.contains(text.at(offset - 1))) {
return offset;
@@ -358,7 +357,7 @@ MatchResult Float::doMatch(QStringView text, int offset, const QStringList &) co
return expOffset;
}
-MatchResult HlCChar::doMatch(QStringView text, int offset, const QStringList &) const
+MatchResult HlCChar::doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const
{
if (text.size() < offset + 3) {
return offset;
@@ -393,7 +392,7 @@ HlCHex::HlCHex(DefinitionData &def, const HighlightingContextData::Rule::HlCHex
resolveAdditionalWordDelimiters(m_wordDelimiters, data.wordDelimiters);
}
-MatchResult HlCHex::doMatch(QStringView text, int offset, const QStringList &) const
+MatchResult HlCHex::doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const
{
if (offset > 0 && !m_wordDelimiters.contains(text.at(offset - 1))) {
return offset;
@@ -427,7 +426,7 @@ HlCOct::HlCOct(DefinitionData &def, const HighlightingContextData::Rule::HlCOct
resolveAdditionalWordDelimiters(m_wordDelimiters, data.wordDelimiters);
}
-MatchResult HlCOct::doMatch(QStringView text, int offset, const QStringList &) const
+MatchResult HlCOct::doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const
{
if (offset > 0 && !m_wordDelimiters.contains(text.at(offset - 1))) {
return offset;
@@ -453,7 +452,7 @@ MatchResult HlCOct::doMatch(QStringView text, int offset, const QStringList &) c
return offset;
}
-MatchResult HlCStringChar::doMatch(QStringView text, int offset, const QStringList &) const
+MatchResult HlCStringChar::doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const
{
return matchEscapedChar(text, offset);
}
@@ -464,7 +463,7 @@ IncludeRules::IncludeRules(const HighlightingContextData::Rule::IncludeRules &da
{
}
-MatchResult IncludeRules::doMatch(QStringView text, int offset, const QStringList &) const
+MatchResult IncludeRules::doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const
{
Q_UNUSED(text);
qCWarning(Log) << "Unresolved include rule";
@@ -477,7 +476,7 @@ Int::Int(DefinitionData &def, const HighlightingContextData::Rule::Int &data)
resolveAdditionalWordDelimiters(m_wordDelimiters, data.wordDelimiters);
}
-MatchResult Int::doMatch(QStringView text, int offset, const QStringList &) const
+MatchResult Int::doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const
{
if (offset > 0 && !m_wordDelimiters.contains(text.at(offset - 1))) {
return offset;
@@ -521,9 +520,10 @@ KeywordListRule::KeywordListRule(const KeywordList &keywordList, DefinitionData
, m_caseSensitivity(data.hasCaseSensitivityOverride ? data.caseSensitivityOverride : keywordList.caseSensitivity())
{
resolveAdditionalWordDelimiters(m_wordDelimiters, data.wordDelimiters);
+ m_hasSkipOffset = true;
}
-MatchResult KeywordListRule::doMatch(QStringView text, int offset, const QStringList &) const
+MatchResult KeywordListRule::doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const
{
auto newOffset = offset;
while (text.size() > newOffset && !m_wordDelimiters.contains(text.at(newOffset))) {
@@ -546,7 +546,7 @@ LineContinue::LineContinue(const HighlightingContextData::Rule::LineContinue &da
{
}
-MatchResult LineContinue::doMatch(QStringView text, int offset, const QStringList &) const
+MatchResult LineContinue::doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const
{
if (offset == text.size() - 1 && text.at(offset) == m_char) {
return offset + 1;
@@ -560,7 +560,7 @@ RangeDetect::RangeDetect(const HighlightingContextData::Rule::RangeDetect &data)
{
}
-MatchResult RangeDetect::doMatch(QStringView text, int offset, const QStringList &) const
+MatchResult RangeDetect::doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const
{
if (text.size() - offset < 2) {
return offset;
@@ -591,25 +591,16 @@ static QRegularExpression::PatternOptions makePattenOptions(const HighlightingCo
static void resolveRegex(QRegularExpression &regexp, Context *context)
{
- if (!regexp.isValid()) {
- // DontCaptureOption with back reference capture is an error, remove this option then try again
- regexp.setPatternOptions(regexp.patternOptions() & ~QRegularExpression::DontCaptureOption);
+ bool enableCapture = context && context->hasDynamicRule();
- if (!regexp.isValid()) {
- qCDebug(Log) << "Invalid regexp:" << regexp.pattern();
- }
-
- return;
+ // disable DontCaptureOption when reference a context with dynamic rule or
+ // with invalid regex because DontCaptureOption with back reference capture is an error
+ if (enableCapture || !regexp.isValid()) {
+ regexp.setPatternOptions(regexp.patternOptions() & ~QRegularExpression::DontCaptureOption);
}
- // disable DontCaptureOption when reference a context with dynamic rule
- if (context) {
- for (const Rule::Ptr &rule : context->rules()) {
- if (rule->isDynamic()) {
- regexp.setPatternOptions(regexp.patternOptions() & ~QRegularExpression::DontCaptureOption);
- break;
- }
- }
+ if (!regexp.isValid()) {
+ qCDebug(Log) << "Invalid regexp:" << regexp.pattern();
}
}
@@ -618,15 +609,25 @@ static MatchResult regexMatch(const QRegularExpression &regexp, QStringView text
/**
* match the pattern
*/
+#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0)
+ const auto result = regexp.matchView(text, offset, QRegularExpression::NormalMatch, QRegularExpression::DontCheckSubjectStringMatchOption);
+#else
const auto result = regexp.match(text, offset, QRegularExpression::NormalMatch, QRegularExpression::DontCheckSubjectStringMatchOption);
+#endif
if (result.capturedStart() == offset) {
/**
* we only need to compute the captured texts if we have real capture groups
* highlightings should only address %1..%.., see e.g. replaceCaptures
* DetectChar ignores %0, too
*/
- if (result.lastCapturedIndex() > 0) {
- return MatchResult(offset + result.capturedLength(), result.capturedTexts());
+ int lastCapturedIndex = result.lastCapturedIndex();
+ if (lastCapturedIndex > 0) {
+ QStringList captures;
+ captures.reserve(lastCapturedIndex);
+ // ignore the capturing group number 0
+ for (int i = 1; i <= lastCapturedIndex; ++i)
+ captures.push_back(result.captured(i));
+ return MatchResult(offset + result.capturedLength(), std::move(captures));
}
/**
@@ -645,20 +646,17 @@ static MatchResult regexMatch(const QRegularExpression &regexp, QStringView text
RegExpr::RegExpr(const HighlightingContextData::Rule::RegExpr &data)
: m_regexp(data.pattern, makePattenOptions(data))
{
+ m_hasSkipOffset = true;
}
void RegExpr::resolve()
{
- if (m_isResolved) {
- return;
- }
-
m_isResolved = true;
resolveRegex(m_regexp, context().context());
}
-MatchResult RegExpr::doMatch(QStringView text, int offset, const QStringList &) const
+MatchResult RegExpr::doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const
{
if (Q_UNLIKELY(!m_isResolved)) {
const_cast<RegExpr *>(this)->resolve();
@@ -672,14 +670,11 @@ DynamicRegExpr::DynamicRegExpr(const HighlightingContextData::Rule::RegExpr &dat
, m_patternOptions(makePattenOptions(data))
{
m_dynamic = true;
+ m_hasSkipOffset = true;
}
void DynamicRegExpr::resolve()
{
- if (m_isResolved) {
- return;
- }
-
m_isResolved = true;
QRegularExpression regexp(m_pattern, m_patternOptions);
@@ -687,7 +682,7 @@ void DynamicRegExpr::resolve()
m_patternOptions = regexp.patternOptions();
}
-MatchResult DynamicRegExpr::doMatch(QStringView text, int offset, const QStringList &captures) const
+MatchResult DynamicRegExpr::doMatch(QStringView text, int offset, const QStringList &captures, DynamicRegexpCache &dynamicRegexpCache) const
{
if (Q_UNLIKELY(!m_isResolved)) {
const_cast<DynamicRegExpr *>(this)->resolve();
@@ -696,8 +691,8 @@ MatchResult DynamicRegExpr::doMatch(QStringView text, int offset, const QStringL
/**
* create new pattern with right instantiation
*/
- const QRegularExpression regexp(replaceCaptures(m_pattern, captures, true), m_patternOptions);
-
+ auto pattern = replaceCaptures(m_pattern, captures, true);
+ auto &regexp = dynamicRegexpCache.compileRegexp(std::move(pattern), m_patternOptions);
return regexMatch(regexp, text, offset);
}
@@ -707,7 +702,7 @@ StringDetect::StringDetect(const HighlightingContextData::Rule::StringDetect &da
{
}
-MatchResult StringDetect::doMatch(QStringView text, int offset, const QStringList &) const
+MatchResult StringDetect::doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const
{
return matchString(m_string, text, offset, m_caseSensitivity);
}
@@ -719,7 +714,7 @@ DynamicStringDetect::DynamicStringDetect(const HighlightingContextData::Rule::St
m_dynamic = true;
}
-MatchResult DynamicStringDetect::doMatch(QStringView text, int offset, const QStringList &captures) const
+MatchResult DynamicStringDetect::doMatch(QStringView text, int offset, const QStringList &captures, DynamicRegexpCache &) const
{
/**
* for dynamic case: create new pattern with right instantiation
@@ -736,7 +731,7 @@ WordDetect::WordDetect(DefinitionData &def, const HighlightingContextData::Rule:
resolveAdditionalWordDelimiters(m_wordDelimiters, data.wordDelimiters);
}
-MatchResult WordDetect::doMatch(QStringView text, int offset, const QStringList &) const
+MatchResult WordDetect::doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const
{
if (text.size() - offset < m_word.size()) {
return offset;
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 7536d92e80..bc5f367ad6 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/lib/rule_p.h
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/rule_p.h
@@ -27,6 +27,7 @@ namespace KSyntaxHighlighting
class WordDelimiters;
class DefinitionData;
class IncludeRules;
+class DynamicRegexpCache;
class Rule
{
@@ -83,7 +84,15 @@ public:
return m_type == Type::LineContinue;
}
- virtual MatchResult doMatch(QStringView text, int offset, const QStringList &captures) const = 0;
+ // If true, then the rule uses the skipOffset parameter of MatchResult.
+ // This is used by AbstractHighlighter::highlightLine() to look for a rule
+ // in the skipOffsets cache only if it can be found there.
+ bool hasSkipOffset() const
+ {
+ return m_hasSkipOffset;
+ }
+
+ virtual MatchResult doMatch(QStringView text, int offset, const QStringList &captures, DynamicRegexpCache &dynamicRegexpCache) const = 0;
static Rule::Ptr create(DefinitionData &def, const HighlightingContextData::Rule &ruleData, QStringView lookupContextName);
@@ -98,6 +107,7 @@ private:
IncludeRules,
};
+private:
Format m_attributeFormat;
ContextSwitch m_context;
int m_column = -1;
@@ -108,6 +118,7 @@ private:
bool m_lookAhead = false;
protected:
+ bool m_hasSkipOffset = false;
bool m_dynamic = false;
};
@@ -117,10 +128,10 @@ public:
AnyChar(const HighlightingContextData::Rule::AnyChar &data);
protected:
- MatchResult doMatch(QStringView text, int offset, const QStringList &) const override;
+ MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override;
private:
- QString m_chars;
+ WordDelimiters m_chars;
};
class DetectChar final : public Rule
@@ -129,7 +140,7 @@ public:
DetectChar(const HighlightingContextData::Rule::DetectChar &data);
protected:
- MatchResult doMatch(QStringView text, int offset, const QStringList &) const override;
+ MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override;
private:
QChar m_char;
@@ -142,7 +153,7 @@ public:
Detect2Chars(const HighlightingContextData::Rule::Detect2Chars &data);
protected:
- MatchResult doMatch(QStringView text, int offset, const QStringList &) const override;
+ MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override;
private:
QChar m_char1;
@@ -152,13 +163,13 @@ private:
class DetectIdentifier final : public Rule
{
protected:
- MatchResult doMatch(QStringView text, int offset, const QStringList &) const override;
+ MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override;
};
class DetectSpaces final : public Rule
{
protected:
- MatchResult doMatch(QStringView text, int offset, const QStringList &) const override;
+ MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override;
};
class Float final : public Rule
@@ -167,7 +178,7 @@ public:
Float(DefinitionData &def, const HighlightingContextData::Rule::Float &data);
protected:
- MatchResult doMatch(QStringView text, int offset, const QStringList &) const override;
+ MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override;
private:
WordDelimiters m_wordDelimiters;
@@ -189,7 +200,7 @@ public:
}
protected:
- MatchResult doMatch(QStringView text, int offset, const QStringList &) const override;
+ MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override;
private:
QString m_contextName;
@@ -202,7 +213,7 @@ public:
Int(DefinitionData &def, const HighlightingContextData::Rule::Int &data);
protected:
- MatchResult doMatch(QStringView text, int offset, const QStringList &) const override;
+ MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override;
private:
WordDelimiters m_wordDelimiters;
@@ -211,7 +222,7 @@ private:
class HlCChar final : public Rule
{
protected:
- MatchResult doMatch(QStringView text, int offset, const QStringList &) const override;
+ MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override;
};
class HlCHex final : public Rule
@@ -220,7 +231,7 @@ public:
HlCHex(DefinitionData &def, const HighlightingContextData::Rule::HlCHex &data);
protected:
- MatchResult doMatch(QStringView text, int offset, const QStringList &) const override;
+ MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override;
private:
WordDelimiters m_wordDelimiters;
@@ -232,7 +243,7 @@ public:
HlCOct(DefinitionData &def, const HighlightingContextData::Rule::HlCOct &data);
protected:
- MatchResult doMatch(QStringView text, int offset, const QStringList &) const override;
+ MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override;
private:
WordDelimiters m_wordDelimiters;
@@ -241,7 +252,7 @@ private:
class HlCStringChar final : public Rule
{
protected:
- MatchResult doMatch(QStringView text, int offset, const QStringList &) const override;
+ MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override;
};
class KeywordListRule final : public Rule
@@ -252,7 +263,7 @@ public:
static Rule::Ptr create(DefinitionData &def, const HighlightingContextData::Rule::Keyword &data, QStringView lookupContextName);
protected:
- MatchResult doMatch(QStringView text, int offset, const QStringList &) const override;
+ MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override;
private:
WordDelimiters m_wordDelimiters;
@@ -266,7 +277,7 @@ public:
LineContinue(const HighlightingContextData::Rule::LineContinue &data);
protected:
- MatchResult doMatch(QStringView text, int offset, const QStringList &) const override;
+ MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override;
private:
QChar m_char;
@@ -278,7 +289,7 @@ public:
RangeDetect(const HighlightingContextData::Rule::RangeDetect &data);
protected:
- MatchResult doMatch(QStringView text, int offset, const QStringList &) const override;
+ MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override;
private:
QChar m_begin;
@@ -291,7 +302,7 @@ public:
RegExpr(const HighlightingContextData::Rule::RegExpr &data);
protected:
- MatchResult doMatch(QStringView text, int offset, const QStringList &) const override;
+ MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override;
private:
void resolve();
@@ -305,7 +316,7 @@ public:
DynamicRegExpr(const HighlightingContextData::Rule::RegExpr &data);
protected:
- MatchResult doMatch(QStringView text, int offset, const QStringList &) const override;
+ MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override;
private:
void resolve();
@@ -320,7 +331,7 @@ public:
StringDetect(const HighlightingContextData::Rule::StringDetect &data);
protected:
- MatchResult doMatch(QStringView text, int offset, const QStringList &) const override;
+ MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override;
private:
QString m_string;
@@ -333,7 +344,7 @@ public:
DynamicStringDetect(const HighlightingContextData::Rule::StringDetect &data);
protected:
- MatchResult doMatch(QStringView text, int offset, const QStringList &) const override;
+ MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override;
private:
QString m_string;
@@ -346,7 +357,7 @@ public:
WordDetect(DefinitionData &def, const HighlightingContextData::Rule::WordDetect &data);
protected:
- MatchResult doMatch(QStringView text, int offset, const QStringList &) const override;
+ MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override;
private:
WordDelimiters m_wordDelimiters;
diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/state.cpp b/src/libs/3rdparty/syntax-highlighting/src/lib/state.cpp
index fc44a6dbd4..dca58b35b7 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/lib/state.cpp
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/state.cpp
@@ -1,4 +1,4 @@
-/*
+/*
SPDX-FileCopyrightText: 2016 Volker Krause <vkrause@kde.org>
SPDX-FileCopyrightText: 2018 Christoph Cullmann <cullmann@kde.org>
@@ -14,36 +14,23 @@
using namespace KSyntaxHighlighting;
-StateData *StateData::get(State &state)
+StateData *StateData::reset(State &state)
{
- // create state data on demand, to make default state construction cheap
- if (!state.d) {
- state.d = new StateData();
- } else {
- state.d.detach();
- }
- return state.d.data();
-}
-
-bool StateData::isEmpty() const
-{
- return m_contextStack.isEmpty();
-}
-
-void StateData::clear()
-{
- m_contextStack.clear();
+ auto *p = new StateData();
+ state.d.reset(p);
+ return p;
}
-int StateData::size() const
+StateData *StateData::detach(State &state)
{
- return m_contextStack.size();
+ state.d.detach();
+ return state.d.data();
}
-void StateData::push(Context *context, const QStringList &captures)
+void StateData::push(Context *context, QStringList &&captures)
{
Q_ASSERT(context);
- m_contextStack.push_back(qMakePair(context, captures));
+ m_contextStack.push_back(StackValue{context, std::move(captures)});
}
bool StateData::pop(int popCount)
@@ -54,42 +41,23 @@ bool StateData::pop(int popCount)
}
// keep the initial context alive in any case
- Q_ASSERT(!isEmpty());
- const bool initialContextSurvived = m_contextStack.size() > popCount;
+ Q_ASSERT(!m_contextStack.empty());
+ const bool initialContextSurvived = int(m_contextStack.size()) > popCount;
m_contextStack.resize(std::max(1, int(m_contextStack.size()) - popCount));
return initialContextSurvived;
}
-Context *StateData::topContext() const
-{
- Q_ASSERT(!isEmpty());
- return m_contextStack.last().first;
-}
+State::State() = default;
-const QStringList &StateData::topCaptures() const
-{
- Q_ASSERT(!isEmpty());
- return m_contextStack.last().second;
-}
+State::State(State &&other) noexcept = default;
-State::State()
-{
-}
+State::State(const State &other) noexcept = default;
-State::State(const State &other)
- : d(other.d)
-{
-}
+State::~State() = default;
-State::~State()
-{
-}
+State &State::operator=(State &&other) noexcept = default;
-State &State::operator=(const State &other)
-{
- d = other.d;
- return *this;
-}
+State &State::operator=(const State &other) noexcept = default;
bool State::operator==(const State &other) const
{
@@ -104,8 +72,13 @@ bool State::operator!=(const State &other) const
bool State::indentationBasedFoldingEnabled() const
{
- if (!d || d->m_contextStack.isEmpty()) {
+ if (!d || d->m_contextStack.empty()) {
return false;
}
- return d->m_contextStack.last().first->indentationBasedFoldingEnabled();
+ return d->m_contextStack.back().context->indentationBasedFoldingEnabled();
+}
+
+std::size_t KSyntaxHighlighting::qHash(const State &state, std::size_t seed)
+{
+ return state.d ? qHashMulti(seed, *state.d) : 0;
}
diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/state.h b/src/libs/3rdparty/syntax-highlighting/src/lib/state.h
index 726ff32a88..3003a9b7cb 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/lib/state.h
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/state.h
@@ -10,11 +10,15 @@
#include "ksyntaxhighlighting_export.h"
#include <QExplicitlySharedDataPointer>
+#include <QHash>
namespace KSyntaxHighlighting
{
+class State;
class StateData;
+KSYNTAXHIGHLIGHTING_EXPORT std::size_t qHash(const State &state, std::size_t seed = 0);
+
/** Opaque handle to the state of the highlighting engine.
* This needs to be fed into AbstractHighlighter for every line of text
* and allows concrete highlighter implementations to store state per
@@ -29,9 +33,11 @@ public:
* in a document.
*/
State();
- State(const State &other);
+ State(State &&other) noexcept;
+ State(const State &other) noexcept;
~State();
- State &operator=(const State &rhs);
+ State &operator=(State &&rhs) noexcept;
+ State &operator=(const State &rhs) noexcept;
/** Compares two states for equality.
* For two equal states and identical text input, AbstractHighlighter
@@ -56,13 +62,13 @@ public:
private:
friend class StateData;
+ KSYNTAXHIGHLIGHTING_EXPORT friend std::size_t qHash(const State &, std::size_t);
QExplicitlySharedDataPointer<StateData> d;
};
-
}
QT_BEGIN_NAMESPACE
-Q_DECLARE_TYPEINFO(KSyntaxHighlighting::State, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(KSyntaxHighlighting::State, Q_RELOCATABLE_TYPE);
QT_END_NAMESPACE
#endif // KSYNTAXHIGHLIGHTING_STATE_H
diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/state_p.h b/src/libs/3rdparty/syntax-highlighting/src/lib/state_p.h
index 0248330304..4aee141681 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/lib/state_p.h
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/state_p.h
@@ -8,8 +8,10 @@
#ifndef KSYNTAXHIGHLIGHTING_STATE_P_H
#define KSYNTAXHIGHLIGHTING_STATE_P_H
+#include <vector>
+
#include <QSharedData>
-#include <QVector>
+#include <QStringList>
#include "definitionref_p.h"
@@ -21,15 +23,25 @@ class StateData : public QSharedData
{
friend class State;
friend class AbstractHighlighter;
+ friend std::size_t qHash(const StateData &, std::size_t);
public:
StateData() = default;
- static StateData *get(State &state);
- bool isEmpty() const;
- void clear();
- int size() const;
- void push(Context *context, const QStringList &captures);
+ static StateData *reset(State &state);
+ static StateData *detach(State &state);
+
+ static StateData *get(const State &state)
+ {
+ return state.d.data();
+ }
+
+ int size() const
+ {
+ return m_contextStack.size();
+ }
+
+ void push(Context *context, QStringList &&captures);
/**
* Pop the number of elements given from the top of the current stack.
@@ -39,8 +51,25 @@ public:
*/
bool pop(int popCount);
- Context *topContext() const;
- const QStringList &topCaptures() const;
+ Context *topContext() const
+ {
+ return m_contextStack.back().context;
+ }
+
+ const QStringList &topCaptures() const
+ {
+ return m_contextStack.back().captures;
+ }
+
+ struct StackValue {
+ Context *context;
+ QStringList captures;
+
+ bool operator==(const StackValue &other) const
+ {
+ return context == other.context && captures == other.captures;
+ }
+ };
private:
/**
@@ -51,9 +80,18 @@ private:
/**
* the context stack combines the active context + valid captures
*/
- QVector<QPair<Context *, QStringList>> m_contextStack;
+ std::vector<StackValue> m_contextStack;
};
+inline std::size_t qHash(const StateData::StackValue &stackValue, std::size_t seed = 0)
+{
+ return qHashMulti(seed, stackValue.context, stackValue.captures);
+}
+
+inline std::size_t qHash(const StateData &k, std::size_t seed = 0)
+{
+ return qHashMulti(seed, k.m_defId, qHashRange(k.m_contextStack.begin(), k.m_contextStack.end(), seed));
+}
}
#endif
diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/syntaxhighlighter.cpp b/src/libs/3rdparty/syntax-highlighting/src/lib/syntaxhighlighter.cpp
index 4754da22c6..70b26a79bf 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/lib/syntaxhighlighter.cpp
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/syntaxhighlighter.cpp
@@ -7,10 +7,13 @@
#include "syntaxhighlighter.h"
#include "abstracthighlighter_p.h"
#include "definition.h"
+#include "definition_p.h"
#include "foldingregion.h"
#include "format.h"
+#include "format_p.h"
#include "state.h"
#include "theme.h"
+#include "themedata_p.h"
Q_DECLARE_METATYPE(QTextBlock)
@@ -22,14 +25,26 @@ class TextBlockUserData : public QTextBlockUserData
{
public:
State state;
- QVector<FoldingRegion> foldingRegions;
+ QList<FoldingRegion> foldingRegions;
};
class SyntaxHighlighterPrivate : public AbstractHighlighterPrivate
{
public:
static FoldingRegion foldingRegion(const QTextBlock &startBlock);
- QVector<FoldingRegion> foldingRegions;
+ void initTextFormat(QTextCharFormat &tf, const Format &format);
+ void computeTextFormats();
+
+ struct TextFormat {
+ QTextCharFormat tf;
+ /**
+ * id to check that the format belongs to the definition
+ */
+ std::intptr_t ptrId;
+ };
+
+ QList<FoldingRegion> foldingRegions;
+ std::vector<TextFormat> tfs;
};
}
@@ -48,6 +63,52 @@ FoldingRegion SyntaxHighlighterPrivate::foldingRegion(const QTextBlock &startBlo
return FoldingRegion();
}
+void SyntaxHighlighterPrivate::initTextFormat(QTextCharFormat &tf, const Format &format)
+{
+ // always set the foreground color to avoid palette issues
+ tf.setForeground(format.textColor(m_theme));
+
+ if (format.hasBackgroundColor(m_theme)) {
+ tf.setBackground(format.backgroundColor(m_theme));
+ }
+ if (format.isBold(m_theme)) {
+ tf.setFontWeight(QFont::Bold);
+ }
+ if (format.isItalic(m_theme)) {
+ tf.setFontItalic(true);
+ }
+ if (format.isUnderline(m_theme)) {
+ tf.setFontUnderline(true);
+ }
+ if (format.isStrikeThrough(m_theme)) {
+ tf.setFontStrikeOut(true);
+ }
+}
+
+void SyntaxHighlighterPrivate::computeTextFormats()
+{
+ auto definitions = m_definition.includedDefinitions();
+ definitions.append(m_definition);
+
+ int maxId = 0;
+ for (const auto &definition : std::as_const(definitions)) {
+ for (const auto &format : std::as_const(DefinitionData::get(definition)->formats)) {
+ maxId = qMax(maxId, format.id());
+ }
+ }
+ tfs.clear();
+ tfs.resize(maxId + 1);
+
+ // initialize tfs
+ for (const auto &definition : std::as_const(definitions)) {
+ for (const auto &format : std::as_const(DefinitionData::get(definition)->formats)) {
+ auto &tf = tfs[format.id()];
+ tf.ptrId = FormatPrivate::ptrId(format);
+ initTextFormat(tf.tf, format);
+ }
+ }
+}
+
SyntaxHighlighter::SyntaxHighlighter(QObject *parent)
: QSyntaxHighlighter(parent)
, AbstractHighlighter(new SyntaxHighlighterPrivate)
@@ -68,13 +129,27 @@ SyntaxHighlighter::~SyntaxHighlighter()
void SyntaxHighlighter::setDefinition(const Definition &def)
{
- const auto needsRehighlight = definition() != def;
- AbstractHighlighter::setDefinition(def);
+ Q_D(SyntaxHighlighter);
+
+ const auto needsRehighlight = d->m_definition != def;
+ if (DefinitionData::get(d->m_definition) != DefinitionData::get(def)) {
+ d->m_definition = def;
+ d->tfs.clear();
+ }
if (needsRehighlight) {
rehighlight();
}
}
+void SyntaxHighlighter::setTheme(const Theme &theme)
+{
+ Q_D(SyntaxHighlighter);
+ if (ThemeData::get(d->m_theme) != ThemeData::get(theme)) {
+ d->m_theme = theme;
+ d->tfs.clear();
+ }
+}
+
bool SyntaxHighlighter::startsFoldingRegion(const QTextBlock &startBlock) const
{
return SyntaxHighlighterPrivate::foldingRegion(startBlock).type() == FoldingRegion::Begin;
@@ -92,13 +167,13 @@ QTextBlock SyntaxHighlighter::findFoldingRegionEnd(const QTextBlock &startBlock)
if (!data) {
continue;
}
- for (auto it = data->foldingRegions.constBegin(); it != data->foldingRegions.constEnd(); ++it) {
- if ((*it).id() != region.id()) {
+ for (const auto &foldingRegion : std::as_const(data->foldingRegions)) {
+ if (foldingRegion.id() != region.id()) {
continue;
}
- if ((*it).type() == FoldingRegion::End) {
+ if (foldingRegion.type() == FoldingRegion::End) {
--depth;
- } else if ((*it).type() == FoldingRegion::Begin) {
+ } else if (foldingRegion.type() == FoldingRegion::Begin) {
++depth;
}
if (depth == 0) {
@@ -114,30 +189,31 @@ void SyntaxHighlighter::highlightBlock(const QString &text)
{
Q_D(SyntaxHighlighter);
- State state;
+ static const State emptyState;
+ const State *previousState = &emptyState;
if (currentBlock().position() > 0) {
const auto prevBlock = currentBlock().previous();
const auto prevData = dynamic_cast<TextBlockUserData *>(prevBlock.userData());
if (prevData) {
- state = prevData->state;
+ previousState = &prevData->state;
}
}
d->foldingRegions.clear();
- state = highlightLine(text, state);
+ auto newState = highlightLine(text, *previousState);
auto data = dynamic_cast<TextBlockUserData *>(currentBlockUserData());
if (!data) { // first time we highlight this
data = new TextBlockUserData;
- data->state = state;
+ data->state = std::move(newState);
data->foldingRegions = d->foldingRegions;
setCurrentBlockUserData(data);
return;
}
- if (data->state == state && data->foldingRegions == d->foldingRegions) { // we ended up in the same state, so we are done here
+ if (data->state == newState && data->foldingRegions == d->foldingRegions) { // we ended up in the same state, so we are done here
return;
}
- data->state = state;
+ data->state = std::move(newState);
data->foldingRegions = d->foldingRegions;
const auto nextBlock = currentBlock().next();
@@ -146,40 +222,35 @@ void SyntaxHighlighter::highlightBlock(const QString &text)
}
}
-void SyntaxHighlighter::applyFormat(int offset, int length, const KSyntaxHighlighting::Format &format)
+void SyntaxHighlighter::applyFormat(int offset, int length, const Format &format)
{
if (length == 0) {
return;
}
- QTextCharFormat tf;
- // always set the foreground color to avoid palette issues
- tf.setForeground(format.textColor(theme()));
+ Q_D(SyntaxHighlighter);
- if (format.hasBackgroundColor(theme())) {
- tf.setBackground(format.backgroundColor(theme()));
- }
- if (format.isBold(theme())) {
- tf.setFontWeight(QFont::Bold);
- }
- if (format.isItalic(theme())) {
- tf.setFontItalic(true);
- }
- if (format.isUnderline(theme())) {
- tf.setFontUnderline(true);
- }
- if (format.isStrikeThrough(theme())) {
- tf.setFontStrikeOut(true);
+ if (Q_UNLIKELY(d->tfs.empty())) {
+ d->computeTextFormats();
}
- QSyntaxHighlighter::setFormat(offset, length, tf);
+ const auto id = static_cast<std::size_t>(format.id());
+ // This doesn't happen when format comes from the definition.
+ // But as the user can override the function to pass any format, this is a possible scenario.
+ if (id < d->tfs.size() && d->tfs[id].ptrId == FormatPrivate::ptrId(format)) {
+ QSyntaxHighlighter::setFormat(offset, length, d->tfs[id].tf);
+ } else {
+ QTextCharFormat tf;
+ d->initTextFormat(tf, format);
+ QSyntaxHighlighter::setFormat(offset, length, tf);
+ }
}
void SyntaxHighlighter::applyFolding(int offset, int length, FoldingRegion region)
{
Q_UNUSED(offset);
Q_UNUSED(length);
- [[maybe_unused]] Q_D(SyntaxHighlighter);
+ Q_D(SyntaxHighlighter);
if (region.type() == FoldingRegion::Begin) {
d->foldingRegions.push_back(region);
@@ -196,3 +267,5 @@ void SyntaxHighlighter::applyFolding(int offset, int length, FoldingRegion regio
d->foldingRegions.push_back(region);
}
}
+
+#include "moc_syntaxhighlighter.cpp"
diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/syntaxhighlighter.h b/src/libs/3rdparty/syntax-highlighting/src/lib/syntaxhighlighter.h
index a57455d9ba..c19cb798dd 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/lib/syntaxhighlighter.h
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/syntaxhighlighter.h
@@ -32,6 +32,7 @@ public:
~SyntaxHighlighter() override;
void setDefinition(const Definition &def) override;
+ void setTheme(const Theme &theme) override;
/** Returns whether there is a folding region beginning at @p startBlock.
* This only considers syntax-based folding regions,
diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/theme.cpp b/src/libs/3rdparty/syntax-highlighting/src/lib/theme.cpp
index b23852f337..c54bb38b18 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/lib/theme.cpp
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/theme.cpp
@@ -103,3 +103,5 @@ QRgb Theme::editorColor(EditorColorRole role) const
{
return m_data->editorColor(role);
}
+
+#include "moc_theme.cpp"
diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/theme.h b/src/libs/3rdparty/syntax-highlighting/src/lib/theme.h
index 37f9de1694..c3fb0e6b6e 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/lib/theme.h
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/theme.h
@@ -67,11 +67,6 @@ class KSYNTAXHIGHLIGHTING_EXPORT Theme
Q_PROPERTY(QString name READ name)
Q_PROPERTY(QString translatedName READ translatedName)
public:
- // TODO KF6:
- // - make TextStyle an enum class
- // - move out of Theme into KSyntaxHighlighting
- // - do the same for EditorColorRole
-
/**
* Default styles that can be referenced from syntax definition XML files.
* Make sure to choose readable colors with good contrast especially in
@@ -342,7 +337,7 @@ private:
/**
* Constructor taking a shared ThemeData instance.
*/
- explicit Theme(ThemeData *data);
+ KSYNTAXHIGHLIGHTING_NO_EXPORT explicit Theme(ThemeData *data);
friend class RepositoryPrivate;
friend class ThemeData;
@@ -356,7 +351,7 @@ private:
}
QT_BEGIN_NAMESPACE
-Q_DECLARE_TYPEINFO(KSyntaxHighlighting::Theme, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(KSyntaxHighlighting::Theme, Q_RELOCATABLE_TYPE);
QT_END_NAMESPACE
#endif // KSYNTAXHIGHLIGHTING_THEME_H
diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/themedata.cpp b/src/libs/3rdparty/syntax-highlighting/src/lib/themedata.cpp
index 4f77dcc494..9d42d03db0 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/lib/themedata.cpp
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/themedata.cpp
@@ -18,11 +18,6 @@
using namespace KSyntaxHighlighting;
-ThemeData *ThemeData::get(const Theme &theme)
-{
- return theme.m_data.data();
-}
-
ThemeData::ThemeData()
{
memset(m_editorColors, 0, sizeof(m_editorColors));
@@ -87,9 +82,18 @@ bool ThemeData::load(const QString &filePath)
return false;
}
const QByteArray jsonData = loadFile.readAll();
+ // look for metadata object
+ int metaDataStart = jsonData.indexOf("\"metadata\"");
+ int start = jsonData.indexOf('{', metaDataStart);
+ int end = jsonData.indexOf("}", metaDataStart);
+ if (start < 0 || end < 0) {
+ qCWarning(Log) << "Failed to parse theme file" << filePath << ":"
+ << "no metadata object found";
+ return false;
+ }
QJsonParseError parseError;
- QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonData, &parseError);
+ QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonData.mid(start, (end + 1) - start), &parseError);
if (parseError.error != QJsonParseError::NoError) {
qCWarning(Log) << "Failed to parse theme file" << filePath << ":" << parseError.errorString();
return false;
@@ -97,13 +101,34 @@ bool ThemeData::load(const QString &filePath)
m_filePath = filePath;
- QJsonObject obj = jsonDoc.object();
-
// read metadata
- const QJsonObject metadata = obj.value(QLatin1String("metadata")).toObject();
+ QJsonObject metadata = jsonDoc.object();
m_name = metadata.value(QLatin1String("name")).toString();
m_revision = metadata.value(QLatin1String("revision")).toInt();
+ return true;
+}
+void ThemeData::loadComplete()
+{
+ if (m_completelyLoaded) {
+ return;
+ }
+ m_completelyLoaded = true;
+
+ QFile loadFile(m_filePath);
+ if (!loadFile.open(QIODevice::ReadOnly)) {
+ return;
+ }
+ const QByteArray jsonData = loadFile.readAll();
+
+ QJsonParseError parseError;
+ QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonData, &parseError);
+ if (parseError.error != QJsonParseError::NoError) {
+ qCWarning(Log) << "Failed to parse theme file" << m_filePath << ":" << parseError.errorString();
+ return;
+ }
+
+ QJsonObject obj = jsonDoc.object();
// read text styles
const auto metaEnumStyle = QMetaEnum::fromType<Theme::TextStyle>();
const QJsonObject textStyles = obj.value(QLatin1String("text-styles")).toObject();
@@ -162,7 +187,7 @@ bool ThemeData::load(const QString &filePath)
}
}
- return true;
+ return;
}
QString ThemeData::name() const
@@ -187,6 +212,9 @@ QString ThemeData::filePath() const
TextStyleData ThemeData::textStyle(Theme::TextStyle style) const
{
+ if (!m_completelyLoaded) {
+ const_cast<ThemeData *>(this)->loadComplete();
+ }
return m_textStyles[style];
}
@@ -232,12 +260,18 @@ bool ThemeData::isStrikeThrough(Theme::TextStyle style) const
QRgb ThemeData::editorColor(Theme::EditorColorRole role) const
{
+ if (!m_completelyLoaded) {
+ const_cast<ThemeData *>(this)->loadComplete();
+ }
Q_ASSERT(static_cast<int>(role) >= 0 && static_cast<int>(role) <= static_cast<int>(Theme::TemplateReadOnlyPlaceholder));
return m_editorColors[role];
}
TextStyleData ThemeData::textStyleOverride(const QString &definitionName, const QString &attributeName) const
{
+ if (!m_completelyLoaded) {
+ const_cast<ThemeData *>(this)->loadComplete();
+ }
auto it = m_textStyleOverrides.find(definitionName);
if (it != m_textStyleOverrides.end()) {
return it->value(attributeName);
diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/themedata_p.h b/src/libs/3rdparty/syntax-highlighting/src/lib/themedata_p.h
index 4ce87f0aaf..6ee772f172 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/lib/themedata_p.h
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/themedata_p.h
@@ -24,7 +24,10 @@ namespace KSyntaxHighlighting
class ThemeData : public QSharedData
{
public:
- static ThemeData *get(const Theme &theme);
+ static ThemeData *get(const Theme &theme)
+ {
+ return theme.m_data.data();
+ }
/**
* Default constructor, creating an uninitialized ThemeData instance.
@@ -37,6 +40,8 @@ public:
*/
bool load(const QString &filePath);
+ void loadComplete();
+
/**
* Returns the unique name of this Theme.
*/
@@ -140,6 +145,8 @@ private:
//! on disk (in a read-only or a writeable location).
QString m_filePath;
+ bool m_completelyLoaded = false;
+
//! TextStyles
std::vector<TextStyleData> m_textStyles;
@@ -154,7 +161,7 @@ private:
}
QT_BEGIN_NAMESPACE
-Q_DECLARE_TYPEINFO(KSyntaxHighlighting::TextStyleData, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(KSyntaxHighlighting::TextStyleData, Q_RELOCATABLE_TYPE);
QT_END_NAMESPACE
#endif // KSYNTAXHIGHLIGHTING_THEMEDATA_P_H
diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/worddelimiters.cpp b/src/libs/3rdparty/syntax-highlighting/src/lib/worddelimiters.cpp
index c5401a57cc..ce55cd4b29 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/lib/worddelimiters.cpp
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/worddelimiters.cpp
@@ -16,6 +16,12 @@ WordDelimiters::WordDelimiters()
}
}
+WordDelimiters::WordDelimiters(QStringView str)
+ : asciiDelimiters{}
+{
+ append(str);
+}
+
bool WordDelimiters::contains(QChar c) const
{
if (c.unicode() < 128) {
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 ccad679a4e..c23670d634 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/lib/worddelimiters_p.h
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/worddelimiters_p.h
@@ -27,6 +27,11 @@ public:
WordDelimiters();
/**
+ * Initialize with a default delimiters.
+ */
+ explicit WordDelimiters(QStringView str);
+
+ /**
* Returns @c true if @p c is a word delimiter; otherwise returns @c false.
*/
bool contains(QChar c) const;
diff --git a/src/libs/3rdparty/syntax-highlighting/src/quick/CMakeLists.txt b/src/libs/3rdparty/syntax-highlighting/src/quick/CMakeLists.txt
index 9277c2aee7..1fb92ad220 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/quick/CMakeLists.txt
+++ b/src/libs/3rdparty/syntax-highlighting/src/quick/CMakeLists.txt
@@ -7,11 +7,10 @@ ecm_add_qml_module(kquicksyntaxhighlightingplugin URI "org.kde.syntaxhighlightin
target_sources(kquicksyntaxhighlightingplugin PRIVATE
kquicksyntaxhighlightingplugin.cpp
kquicksyntaxhighlighter.cpp
- repositorywrapper.cpp
)
target_link_libraries(kquicksyntaxhighlightingplugin PRIVATE
- KF5SyntaxHighlighting
- Qt${QT_MAJOR_VERSION}::Quick
+ KF6SyntaxHighlighting
+ Qt6::Quick
)
ecm_finalize_qml_module(kquicksyntaxhighlightingplugin DESTINATION ${KDE_INSTALL_QMLDIR})
diff --git a/src/libs/3rdparty/syntax-highlighting/src/quick/kquicksyntaxhighlighter.cpp b/src/libs/3rdparty/syntax-highlighting/src/quick/kquicksyntaxhighlighter.cpp
index eb795b1468..19cfbacf58 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/quick/kquicksyntaxhighlighter.cpp
+++ b/src/libs/3rdparty/syntax-highlighting/src/quick/kquicksyntaxhighlighter.cpp
@@ -49,7 +49,7 @@ QVariant KQuickSyntaxHighlighter::definition() const
void KQuickSyntaxHighlighter::setDefinition(const QVariant &definition)
{
Definition def;
- if (definition.type() == QVariant::String) {
+ if (definition.userType() == QMetaType::QString) {
def = unwrappedRepository()->definitionForName(definition.toString());
} else {
def = definition.value<Definition>();
@@ -73,9 +73,9 @@ QVariant KQuickSyntaxHighlighter::theme() const
void KQuickSyntaxHighlighter::setTheme(const QVariant &theme)
{
Theme t;
- if (theme.type() == QVariant::String) {
+ if (theme.userType() == QMetaType::QString) {
t = unwrappedRepository()->theme(theme.toString());
- } else if (theme.type() == QVariant::Int) {
+ } else if (theme.userType() == QMetaType::Int) {
t = unwrappedRepository()->defaultTheme(static_cast<Repository::DefaultTheme>(theme.toInt()));
} else {
t = theme.value<Theme>();
@@ -89,12 +89,12 @@ void KQuickSyntaxHighlighter::setTheme(const QVariant &theme)
}
}
-RepositoryWrapper *KQuickSyntaxHighlighter::repository() const
+Repository *KQuickSyntaxHighlighter::repository() const
{
return m_repository;
}
-void KQuickSyntaxHighlighter::setRepository(RepositoryWrapper *repository)
+void KQuickSyntaxHighlighter::setRepository(Repository *repository)
{
if (m_repository == repository) {
return;
@@ -106,7 +106,9 @@ void KQuickSyntaxHighlighter::setRepository(RepositoryWrapper *repository)
Repository *KQuickSyntaxHighlighter::unwrappedRepository() const
{
if (m_repository) {
- return m_repository->m_repository;
+ return m_repository;
}
return defaultRepository();
}
+
+#include "moc_kquicksyntaxhighlighter.cpp"
diff --git a/src/libs/3rdparty/syntax-highlighting/src/quick/kquicksyntaxhighlighter.h b/src/libs/3rdparty/syntax-highlighting/src/quick/kquicksyntaxhighlighter.h
index 211f80d37f..b45c26339f 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/quick/kquicksyntaxhighlighter.h
+++ b/src/libs/3rdparty/syntax-highlighting/src/quick/kquicksyntaxhighlighter.h
@@ -8,8 +8,6 @@
#ifndef KQUICKSYNTAXHIGHLIGHTER_H
#define KQUICKSYNTAXHIGHLIGHTER_H
-#include "repositorywrapper.h"
-
#include <KSyntaxHighlighting/Definition>
#include <KSyntaxHighlighting/Theme>
@@ -29,7 +27,7 @@ class KQuickSyntaxHighlighter : public QObject
Q_PROPERTY(QObject *textEdit READ textEdit WRITE setTextEdit NOTIFY textEditChanged)
Q_PROPERTY(QVariant definition READ definition WRITE setDefinition NOTIFY definitionChanged)
Q_PROPERTY(QVariant theme READ theme WRITE setTheme NOTIFY themeChanged)
- Q_PROPERTY(RepositoryWrapper *repository READ repository WRITE setRepository NOTIFY repositoryChanged)
+ Q_PROPERTY(KSyntaxHighlighting::Repository *repository READ repository WRITE setRepository NOTIFY repositoryChanged)
public:
explicit KQuickSyntaxHighlighter(QObject *parent = nullptr);
@@ -44,8 +42,8 @@ public:
QVariant theme() const;
void setTheme(const QVariant &theme);
- RepositoryWrapper *repository() const;
- void setRepository(RepositoryWrapper *repository);
+ KSyntaxHighlighting::Repository *repository() const;
+ void setRepository(KSyntaxHighlighting::Repository *repository);
Q_SIGNALS:
void textEditChanged() const;
@@ -59,7 +57,7 @@ private:
QObject *m_textEdit;
KSyntaxHighlighting::Definition m_definition;
KSyntaxHighlighting::Theme m_theme;
- RepositoryWrapper *m_repository = nullptr;
+ KSyntaxHighlighting::Repository *m_repository = nullptr;
KSyntaxHighlighting::SyntaxHighlighter *m_highlighter = nullptr;
};
diff --git a/src/libs/3rdparty/syntax-highlighting/src/quick/kquicksyntaxhighlightingplugin.cpp b/src/libs/3rdparty/syntax-highlighting/src/quick/kquicksyntaxhighlightingplugin.cpp
index 9aeb503ec5..5eb06862df 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/quick/kquicksyntaxhighlightingplugin.cpp
+++ b/src/libs/3rdparty/syntax-highlighting/src/quick/kquicksyntaxhighlightingplugin.cpp
@@ -7,7 +7,6 @@
#include "kquicksyntaxhighlightingplugin.h"
#include "kquicksyntaxhighlighter.h"
-#include "repositorywrapper.h"
#include <KSyntaxHighlighting/Definition>
#include <KSyntaxHighlighting/Repository>
@@ -30,17 +29,18 @@ void KQuickSyntaxHighlightingPlugin::registerTypes(const char *uri)
{
Q_ASSERT(QLatin1String(uri) == QLatin1String("org.kde.syntaxhighlighting"));
qRegisterMetaType<Definition>();
- qRegisterMetaType<QVector<Definition>>();
+ qRegisterMetaType<QList<Definition>>();
qRegisterMetaType<Theme>();
- qRegisterMetaType<QVector<Theme>>();
+ qRegisterMetaType<QList<Theme>>();
qmlRegisterType<KQuickSyntaxHighlighter>(uri, 1, 0, "SyntaxHighlighter");
- qmlRegisterUncreatableType<Definition>(uri, 1, 0, "Definition", {});
- qmlRegisterUncreatableType<Theme>(uri, 1, 0, "Theme", {});
- qmlRegisterSingletonType<RepositoryWrapper>(uri, 1, 0, "Repository", [](auto engine, auto scriptEngine) {
+ qmlRegisterUncreatableMetaObject(Definition::staticMetaObject, uri, 1, 0, "Definition", {});
+ qmlRegisterUncreatableMetaObject(Theme::staticMetaObject, uri, 1, 0, "Theme", {});
+ qmlRegisterSingletonType<Repository>(uri, 1, 0, "Repository", [](auto engine, auto scriptEngine) {
(void)engine;
- (void)scriptEngine;
- auto repo = new RepositoryWrapper;
- repo->m_repository = defaultRepository();
- return repo;
+ auto repo = defaultRepository();
+ scriptEngine->setObjectOwnership(repo, QJSEngine::CppOwnership);
+ return defaultRepository();
});
}
+
+#include "moc_kquicksyntaxhighlightingplugin.cpp"
diff --git a/src/libs/3rdparty/syntax-highlighting/src/quick/repositorywrapper.cpp b/src/libs/3rdparty/syntax-highlighting/src/quick/repositorywrapper.cpp
deleted file mode 100644
index 733c799ed1..0000000000
--- a/src/libs/3rdparty/syntax-highlighting/src/quick/repositorywrapper.cpp
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- SPDX-FileCopyrightText: 2021 Volker Krause <vkrause@kde.org>
-
- SPDX-License-Identifier: MIT
-*/
-
-#include "repositorywrapper.h"
-
-#include <KSyntaxHighlighting/Definition>
-#include <KSyntaxHighlighting/Repository>
-#include <KSyntaxHighlighting/Theme>
-
-using namespace KSyntaxHighlighting;
-
-RepositoryWrapper::RepositoryWrapper(QObject *parent)
- : QObject(parent)
-{
-}
-
-Definition RepositoryWrapper::definitionForName(const QString &defName) const
-{
- return m_repository->definitionForName(defName);
-}
-
-Definition RepositoryWrapper::definitionForFileName(const QString &fileName) const
-{
- return m_repository->definitionForFileName(fileName);
-}
-
-QVector<Definition> RepositoryWrapper::definitionsForFileName(const QString &fileName) const
-{
- return m_repository->definitionsForFileName(fileName);
-}
-
-Definition RepositoryWrapper::definitionForMimeType(const QString &mimeType) const
-{
- return m_repository->definitionForMimeType(mimeType);
-}
-
-QVector<Definition> RepositoryWrapper::definitionsForMimeType(const QString &mimeType) const
-{
- return m_repository->definitionsForMimeType(mimeType);
-}
-
-QVector<Definition> RepositoryWrapper::definitions() const
-{
- return m_repository->definitions();
-}
-
-QVector<Theme> RepositoryWrapper::themes() const
-{
- return m_repository->themes();
-}
-
-Theme RepositoryWrapper::theme(const QString &themeName) const
-{
- return m_repository->theme(themeName);
-}
-
-Theme RepositoryWrapper::defaultTheme(DefaultTheme t) const
-{
- return m_repository->defaultTheme(static_cast<Repository::DefaultTheme>(t));
-}
-
-#include "moc_repositorywrapper.cpp"
diff --git a/src/libs/3rdparty/syntax-highlighting/src/quick/repositorywrapper.h b/src/libs/3rdparty/syntax-highlighting/src/quick/repositorywrapper.h
deleted file mode 100644
index d4fb8d251c..0000000000
--- a/src/libs/3rdparty/syntax-highlighting/src/quick/repositorywrapper.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- SPDX-FileCopyrightText: 2021 Volker Krause <vkrause@kde.org>
-
- SPDX-License-Identifier: MIT
-*/
-
-#ifndef REPOSITORYWRAPPER_H
-#define REPOSITORYWRAPPER_H
-
-#include <QObject>
-
-namespace KSyntaxHighlighting
-{
-class Definition;
-class Repository;
-class Theme;
-}
-
-// TODO KF6: merge this into KSyntaxHighlighting::Repository
-class RepositoryWrapper : public QObject
-{
- Q_OBJECT
- // TODO KF6: NOTIFY on reload
- Q_PROPERTY(QVector<KSyntaxHighlighting::Definition> definitions READ definitions CONSTANT)
- Q_PROPERTY(QVector<KSyntaxHighlighting::Theme> themes READ themes CONSTANT)
-public:
- explicit RepositoryWrapper(QObject *parent = nullptr);
-
- Q_INVOKABLE KSyntaxHighlighting::Definition definitionForName(const QString &defName) const;
- Q_INVOKABLE KSyntaxHighlighting::Definition definitionForFileName(const QString &fileName) const;
- Q_INVOKABLE QVector<KSyntaxHighlighting::Definition> definitionsForFileName(const QString &fileName) const;
- Q_INVOKABLE KSyntaxHighlighting::Definition definitionForMimeType(const QString &mimeType) const;
- Q_INVOKABLE QVector<KSyntaxHighlighting::Definition> definitionsForMimeType(const QString &mimeType) const;
- QVector<KSyntaxHighlighting::Definition> definitions() const;
-
- QVector<KSyntaxHighlighting::Theme> themes() const;
- Q_INVOKABLE KSyntaxHighlighting::Theme theme(const QString &themeName) const;
- enum DefaultTheme { LightTheme, DarkTheme };
- Q_ENUM(DefaultTheme)
- Q_INVOKABLE KSyntaxHighlighting::Theme defaultTheme(DefaultTheme t = LightTheme) const;
-
- KSyntaxHighlighting::Repository *m_repository = nullptr;
-};
-
-#endif // REPOSITORYWRAPPER_H