forked from qt-creator/qt-creator
SyntaxHighlighter: Move SyntaxHighlighter to separate thread
This change involves the relocation of SyntaxHighlighter processing to another thread. The core idea is to create a duplicate of the original TextDocument using SyntaxHighlighterRunnerPrivate::cloneDocument. A new SyntaxHighlighter is then instantiated by SyntaxHighLighterCreator for the cloned document. The entire SyntaxHighLighterCreator class is moved to a new thread, where it performs highlighting on the cloned document. Upon completion of the highlighting process, the resultsReady signal is emitted, and the updated highlighting data is applied to the original document. This shift of SyntaxHighlighter to another thread enhances the user experience by preventing UI slowdowns during the highlighting process. - Introduction of BaseSyntaxHighlighterRunner as an interface class for future *SyntaxHighlighterRunner. - Inclusion of DirectSyntaxHighlighterRunner class for performing highlighting in the main thread, suitable for syntax highlighters that cannot be moved to another thread. - Introduction of ThreadedSyntaxHighlighterRunner class for highlighting in a separate thread, preventing UI blocking during the process. - Addition of Result data to the SyntaxHighlighter class to facilitate data exchange between threads. Task-number: QTCREATORBUG-28727 Change-Id: I4b6a38d15f5ec9b8828055d38d2a0c6f21a657b4 Reviewed-by: Jarek Kobus <jaroslaw.kobus@qt.io> Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
@@ -131,7 +131,7 @@ ClangFormatConfigWidget::ClangFormatConfigWidget(TextEditor::ICodeStylePreferenc
|
|||||||
d->preview->setPlainText(QLatin1String(CppEditor::Constants::DEFAULT_CODE_STYLE_SNIPPETS[0]));
|
d->preview->setPlainText(QLatin1String(CppEditor::Constants::DEFAULT_CODE_STYLE_SNIPPETS[0]));
|
||||||
d->preview->textDocument()->setIndenter(new ClangFormatIndenter(d->preview->document()));
|
d->preview->textDocument()->setIndenter(new ClangFormatIndenter(d->preview->document()));
|
||||||
d->preview->textDocument()->setFontSettings(TextEditor::TextEditorSettings::fontSettings());
|
d->preview->textDocument()->setFontSettings(TextEditor::TextEditorSettings::fontSettings());
|
||||||
d->preview->textDocument()->setSyntaxHighlighterCreator(
|
d->preview->textDocument()->resetSyntaxHighlighter(
|
||||||
[] { return new CppEditor::CppHighlighter(); });
|
[] { return new CppEditor::CppHighlighter(); });
|
||||||
d->preview->textDocument()->indenter()->setFileName(fileName);
|
d->preview->textDocument()->indenter()->setFileName(fileName);
|
||||||
|
|
||||||
|
@@ -22,6 +22,7 @@
|
|||||||
#include <texteditor/storagesettings.h>
|
#include <texteditor/storagesettings.h>
|
||||||
#include <texteditor/textdocumentlayout.h>
|
#include <texteditor/textdocumentlayout.h>
|
||||||
#include <texteditor/texteditorsettings.h>
|
#include <texteditor/texteditorsettings.h>
|
||||||
|
#include <texteditor/syntaxhighlighterrunner.h>
|
||||||
|
|
||||||
#include <utils/infobar.h>
|
#include <utils/infobar.h>
|
||||||
#include <utils/mimeconstants.h>
|
#include <utils/mimeconstants.h>
|
||||||
@@ -79,7 +80,7 @@ private:
|
|||||||
CppEditorDocument::CppEditorDocument()
|
CppEditorDocument::CppEditorDocument()
|
||||||
{
|
{
|
||||||
setId(CppEditor::Constants::CPPEDITOR_ID);
|
setId(CppEditor::Constants::CPPEDITOR_ID);
|
||||||
setSyntaxHighlighterCreator([] { return new CppHighlighter(); });
|
resetSyntaxHighlighter([] { return new CppHighlighter(); });
|
||||||
|
|
||||||
ICodeStylePreferencesFactory *factory
|
ICodeStylePreferencesFactory *factory
|
||||||
= TextEditorSettings::codeStyleFactory(Constants::CPP_SETTINGS_ID);
|
= TextEditorSettings::codeStyleFactory(Constants::CPP_SETTINGS_ID);
|
||||||
@@ -165,7 +166,7 @@ QByteArray CppEditorDocument::contentsText() const
|
|||||||
|
|
||||||
void CppEditorDocument::applyFontSettings()
|
void CppEditorDocument::applyFontSettings()
|
||||||
{
|
{
|
||||||
if (TextEditor::SyntaxHighlighter *highlighter = syntaxHighlighter())
|
if (TextEditor::BaseSyntaxHighlighterRunner *highlighter = syntaxHighlighterRunner())
|
||||||
highlighter->clearAllExtraFormats(); // Clear all additional formats since they may have changed
|
highlighter->clearAllExtraFormats(); // Clear all additional formats since they may have changed
|
||||||
TextDocument::applyFontSettings(); // rehighlights and updates additional formats
|
TextDocument::applyFontSettings(); // rehighlights and updates additional formats
|
||||||
if (m_processor)
|
if (m_processor)
|
||||||
@@ -409,8 +410,8 @@ BaseEditorDocumentProcessor *CppEditorDocument::processor()
|
|||||||
connect(m_processor.data(), &BaseEditorDocumentProcessor::cppDocumentUpdated, this,
|
connect(m_processor.data(), &BaseEditorDocumentProcessor::cppDocumentUpdated, this,
|
||||||
[this](const CPlusPlus::Document::Ptr document) {
|
[this](const CPlusPlus::Document::Ptr document) {
|
||||||
// Update syntax highlighter
|
// Update syntax highlighter
|
||||||
auto *highlighter = qobject_cast<CppHighlighter *>(syntaxHighlighter());
|
if (BaseSyntaxHighlighterRunner *highlighter = syntaxHighlighterRunner())
|
||||||
highlighter->setLanguageFeatures(document->languageFeatures());
|
highlighter->setLanguageFeaturesFlags(document->languageFeatures().flags);
|
||||||
|
|
||||||
m_overviewModel.update(usesClangd() ? nullptr : document);
|
m_overviewModel.update(usesClangd() ? nullptr : document);
|
||||||
|
|
||||||
|
@@ -268,10 +268,10 @@ void CppHighlighter::highlightBlock(const QString &text)
|
|||||||
tokenize.expectedRawStringSuffix());
|
tokenize.expectedRawStringSuffix());
|
||||||
}
|
}
|
||||||
|
|
||||||
void CppHighlighter::setLanguageFeatures(const LanguageFeatures &languageFeatures)
|
void CppHighlighter::setLanguageFeaturesFlags(unsigned int flags)
|
||||||
{
|
{
|
||||||
if (languageFeatures != m_languageFeatures) {
|
if (flags != m_languageFeatures.flags) {
|
||||||
m_languageFeatures = languageFeatures;
|
m_languageFeatures.flags = flags;
|
||||||
rehighlight();
|
rehighlight();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -22,7 +22,7 @@ class CPPEDITOR_EXPORT CppHighlighter : public TextEditor::SyntaxHighlighter
|
|||||||
public:
|
public:
|
||||||
CppHighlighter(QTextDocument *document = nullptr);
|
CppHighlighter(QTextDocument *document = nullptr);
|
||||||
|
|
||||||
void setLanguageFeatures(const CPlusPlus::LanguageFeatures &languageFeatures);
|
void setLanguageFeaturesFlags(unsigned int flags) override;
|
||||||
void highlightBlock(const QString &text) override;
|
void highlightBlock(const QString &text) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@@ -854,7 +854,7 @@ namespace Internal {
|
|||||||
|
|
||||||
void decorateCppEditor(TextEditor::TextEditorWidget *editor)
|
void decorateCppEditor(TextEditor::TextEditorWidget *editor)
|
||||||
{
|
{
|
||||||
editor->textDocument()->setSyntaxHighlighterCreator([] { return new CppHighlighter(); });
|
editor->textDocument()->resetSyntaxHighlighter([] { return new CppHighlighter(); });
|
||||||
editor->textDocument()->setIndenter(
|
editor->textDocument()->setIndenter(
|
||||||
new CppQtStyleIndenter(editor->textDocument()->document()));
|
new CppQtStyleIndenter(editor->textDocument()->document()));
|
||||||
editor->setAutoCompleter(new CppAutoCompleter);
|
editor->setAutoCompleter(new CppAutoCompleter);
|
||||||
|
@@ -8,6 +8,7 @@
|
|||||||
#include <texteditor/syntaxhighlighter.h>
|
#include <texteditor/syntaxhighlighter.h>
|
||||||
#include <texteditor/textdocument.h>
|
#include <texteditor/textdocument.h>
|
||||||
#include <texteditor/textdocumentlayout.h>
|
#include <texteditor/textdocumentlayout.h>
|
||||||
|
#include <texteditor/syntaxhighlighterrunner.h>
|
||||||
|
|
||||||
#include <utils/algorithm.h>
|
#include <utils/algorithm.h>
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
@@ -111,7 +112,7 @@ void SemanticHighlighter::handleHighlighterResults()
|
|||||||
QElapsedTimer t;
|
QElapsedTimer t;
|
||||||
t.start();
|
t.start();
|
||||||
|
|
||||||
SyntaxHighlighter *highlighter = m_baseTextDocument->syntaxHighlighter();
|
BaseSyntaxHighlighterRunner *highlighter = m_baseTextDocument->syntaxHighlighterRunner();
|
||||||
QTC_ASSERT(highlighter, return);
|
QTC_ASSERT(highlighter, return);
|
||||||
incrementalApplyExtraAdditionalFormats(highlighter, m_watcher->future(), from, to, m_formatMap);
|
incrementalApplyExtraAdditionalFormats(highlighter, m_watcher->future(), from, to, m_formatMap);
|
||||||
|
|
||||||
@@ -199,7 +200,7 @@ void SemanticHighlighter::onHighlighterFinished()
|
|||||||
t.start();
|
t.start();
|
||||||
|
|
||||||
if (!m_watcher->isCanceled() && documentRevision() == m_revision) {
|
if (!m_watcher->isCanceled() && documentRevision() == m_revision) {
|
||||||
SyntaxHighlighter *highlighter = m_baseTextDocument->syntaxHighlighter();
|
BaseSyntaxHighlighterRunner *highlighter = m_baseTextDocument->syntaxHighlighterRunner();
|
||||||
if (QTC_GUARD(highlighter)) {
|
if (QTC_GUARD(highlighter)) {
|
||||||
qCDebug(log) << "onHighlighterFinished() - clearing formats";
|
qCDebug(log) << "onHighlighterFinished() - clearing formats";
|
||||||
clearExtraAdditionalFormatsUntilEnd(highlighter, m_watcher->future());
|
clearExtraAdditionalFormatsUntilEnd(highlighter, m_watcher->future());
|
||||||
|
@@ -93,7 +93,7 @@ DescriptionEditorWidget::DescriptionEditorWidget(QWidget *parent)
|
|||||||
context->setContext(Context(Constants::C_DIFF_EDITOR_DESCRIPTION));
|
context->setContext(Context(Constants::C_DIFF_EDITOR_DESCRIPTION));
|
||||||
ICore::addContextObject(context);
|
ICore::addContextObject(context);
|
||||||
|
|
||||||
textDocument()->setSyntaxHighlighterCreator([] { return new SyntaxHighlighter(); });
|
textDocument()->resetSyntaxHighlighter([] { return new SyntaxHighlighter(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
QSize DescriptionEditorWidget::sizeHint() const
|
QSize DescriptionEditorWidget::sizeHint() const
|
||||||
|
@@ -246,10 +246,10 @@ void GitEditorWidget::init()
|
|||||||
return;
|
return;
|
||||||
const QChar commentChar = gitClient().commentChar(source());
|
const QChar commentChar = gitClient().commentChar(source());
|
||||||
if (isCommitEditor)
|
if (isCommitEditor)
|
||||||
textDocument()->setSyntaxHighlighterCreator(
|
textDocument()->resetSyntaxHighlighter(
|
||||||
[commentChar] { return new GitSubmitHighlighter(commentChar); });
|
[commentChar] { return new GitSubmitHighlighter(commentChar); });
|
||||||
else if (isRebaseEditor)
|
else if (isRebaseEditor)
|
||||||
textDocument()->setSyntaxHighlighterCreator(
|
textDocument()->resetSyntaxHighlighter(
|
||||||
[commentChar] { return new GitRebaseHighlighter(commentChar); });
|
[commentChar] { return new GitRebaseHighlighter(commentChar); });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -10,6 +10,7 @@
|
|||||||
#include <texteditor/syntaxhighlighter.h>
|
#include <texteditor/syntaxhighlighter.h>
|
||||||
#include <texteditor/texteditor.h>
|
#include <texteditor/texteditor.h>
|
||||||
#include <texteditor/texteditorsettings.h>
|
#include <texteditor/texteditorsettings.h>
|
||||||
|
#include <texteditor/syntaxhighlighterrunner.h>
|
||||||
#include <utils/algorithm.h>
|
#include <utils/algorithm.h>
|
||||||
#include <utils/mimeutils.h>
|
#include <utils/mimeutils.h>
|
||||||
|
|
||||||
@@ -182,7 +183,7 @@ void SemanticTokenSupport::queueDocumentReload(TextEditor::TextDocument *doc)
|
|||||||
void SemanticTokenSupport::clearHighlight(TextEditor::TextDocument *doc)
|
void SemanticTokenSupport::clearHighlight(TextEditor::TextDocument *doc)
|
||||||
{
|
{
|
||||||
if (m_tokens.contains(doc->filePath())){
|
if (m_tokens.contains(doc->filePath())){
|
||||||
if (TextEditor::SyntaxHighlighter *highlighter = doc->syntaxHighlighter())
|
if (TextEditor::BaseSyntaxHighlighterRunner *highlighter = doc->syntaxHighlighterRunner())
|
||||||
highlighter->clearAllExtraFormats();
|
highlighter->clearAllExtraFormats();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -412,7 +413,7 @@ void SemanticTokenSupport::highlight(const Utils::FilePath &filePath, bool force
|
|||||||
TextDocument *doc = TextDocument::textDocumentForFilePath(filePath);
|
TextDocument *doc = TextDocument::textDocumentForFilePath(filePath);
|
||||||
if (!doc || LanguageClientManager::clientForDocument(doc) != m_client)
|
if (!doc || LanguageClientManager::clientForDocument(doc) != m_client)
|
||||||
return;
|
return;
|
||||||
SyntaxHighlighter *highlighter = doc->syntaxHighlighter();
|
BaseSyntaxHighlighterRunner *highlighter = doc->syntaxHighlighterRunner();
|
||||||
if (!highlighter)
|
if (!highlighter)
|
||||||
return;
|
return;
|
||||||
const VersionedTokens versionedTokens = m_tokens.value(filePath);
|
const VersionedTokens versionedTokens = m_tokens.value(filePath);
|
||||||
|
@@ -51,7 +51,7 @@ NimEditorFactory::NimEditorFactory()
|
|||||||
|
|
||||||
void NimEditorFactory::decorateEditor(TextEditorWidget *editor)
|
void NimEditorFactory::decorateEditor(TextEditorWidget *editor)
|
||||||
{
|
{
|
||||||
editor->textDocument()->setSyntaxHighlighterCreator([] { return new NimHighlighter();});
|
editor->textDocument()->resetSyntaxHighlighter([] { return new NimHighlighter();});
|
||||||
editor->textDocument()->setIndenter(new NimIndenter(editor->textDocument()->document()));
|
editor->textDocument()->setIndenter(new NimIndenter(editor->textDocument()->document()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -167,7 +167,7 @@ BindingEditorFactory::BindingEditorFactory()
|
|||||||
|
|
||||||
void BindingEditorFactory::decorateEditor(TextEditor::TextEditorWidget *editor)
|
void BindingEditorFactory::decorateEditor(TextEditor::TextEditorWidget *editor)
|
||||||
{
|
{
|
||||||
editor->textDocument()->setSyntaxHighlighterCreator(
|
editor->textDocument()->resetSyntaxHighlighter(
|
||||||
[] { return new QmlJSEditor::QmlJSHighlighter(); });
|
[] { return new QmlJSEditor::QmlJSHighlighter(); });
|
||||||
editor->textDocument()->setIndenter(new QmlJSEditor::Internal::Indenter(
|
editor->textDocument()->setIndenter(new QmlJSEditor::Internal::Indenter(
|
||||||
editor->textDocument()->document()));
|
editor->textDocument()->document()));
|
||||||
|
@@ -743,7 +743,7 @@ void QmlJSEditorWidget::inspectElementUnderCursor() const
|
|||||||
|
|
||||||
widget->setReadOnly(true);
|
widget->setReadOnly(true);
|
||||||
widget->textDocument()->setTemporary(true);
|
widget->textDocument()->setTemporary(true);
|
||||||
widget->textDocument()->setSyntaxHighlighterCreator([] {return new QmlJSHighlighter();});
|
widget->textDocument()->resetSyntaxHighlighter([] { return new QmlJSHighlighter(); });
|
||||||
|
|
||||||
const QString buf = inspectCppComponent(cppValue);
|
const QString buf = inspectCppComponent(cppValue);
|
||||||
widget->textDocument()->setPlainText(buf);
|
widget->textDocument()->setPlainText(buf);
|
||||||
@@ -1159,7 +1159,7 @@ QmlJSEditorFactory::QmlJSEditorFactory(Utils::Id _id)
|
|||||||
|
|
||||||
void QmlJSEditorFactory::decorateEditor(TextEditorWidget *editor)
|
void QmlJSEditorFactory::decorateEditor(TextEditorWidget *editor)
|
||||||
{
|
{
|
||||||
editor->textDocument()->setSyntaxHighlighterCreator([] { return new QmlJSHighlighter(); });
|
editor->textDocument()->resetSyntaxHighlighter([] { return new QmlJSHighlighter(); });
|
||||||
editor->textDocument()->setIndenter(new Internal::Indenter(editor->textDocument()->document()));
|
editor->textDocument()->setIndenter(new Internal::Indenter(editor->textDocument()->document()));
|
||||||
editor->setAutoCompleter(new AutoCompleter);
|
editor->setAutoCompleter(new AutoCompleter);
|
||||||
}
|
}
|
||||||
|
@@ -820,7 +820,7 @@ QmlJSEditorDocument::QmlJSEditorDocument(Utils::Id id)
|
|||||||
d, &Internal::QmlJSEditorDocumentPrivate::invalidateFormatterCache);
|
d, &Internal::QmlJSEditorDocumentPrivate::invalidateFormatterCache);
|
||||||
connect(this, &TextEditor::TextDocument::openFinishedSuccessfully,
|
connect(this, &TextEditor::TextDocument::openFinishedSuccessfully,
|
||||||
d, &Internal::QmlJSEditorDocumentPrivate::settingsChanged);
|
d, &Internal::QmlJSEditorDocumentPrivate::settingsChanged);
|
||||||
setSyntaxHighlighterCreator([] { return new QmlJSHighlighter(); });
|
resetSyntaxHighlighter([] { return new QmlJSHighlighter(); });
|
||||||
setCodec(QTextCodec::codecForName("UTF-8")); // qml files are defined to be utf-8
|
setCodec(QTextCodec::codecForName("UTF-8")); // qml files are defined to be utf-8
|
||||||
setIndenter(new Internal::Indenter(document()));
|
setIndenter(new Internal::Indenter(document()));
|
||||||
}
|
}
|
||||||
|
@@ -569,7 +569,7 @@ void SemanticHighlighter::applyResults(int from, int to)
|
|||||||
|
|
||||||
if (m_enableHighlighting)
|
if (m_enableHighlighting)
|
||||||
TextEditor::SemanticHighlighter::incrementalApplyExtraAdditionalFormats(
|
TextEditor::SemanticHighlighter::incrementalApplyExtraAdditionalFormats(
|
||||||
m_document->syntaxHighlighter(), m_watcher.future(), from, to, m_extraFormats);
|
m_document->syntaxHighlighterRunner(), m_watcher.future(), from, to, m_extraFormats);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SemanticHighlighter::finished()
|
void SemanticHighlighter::finished()
|
||||||
@@ -584,7 +584,7 @@ void SemanticHighlighter::finished()
|
|||||||
|
|
||||||
if (m_enableHighlighting)
|
if (m_enableHighlighting)
|
||||||
TextEditor::SemanticHighlighter::clearExtraAdditionalFormatsUntilEnd(
|
TextEditor::SemanticHighlighter::clearExtraAdditionalFormatsUntilEnd(
|
||||||
m_document->syntaxHighlighter(), m_watcher.future());
|
m_document->syntaxHighlighterRunner(), m_watcher.future());
|
||||||
}
|
}
|
||||||
|
|
||||||
void SemanticHighlighter::run(QPromise<Use> &promise,
|
void SemanticHighlighter::run(QPromise<Use> &promise,
|
||||||
|
@@ -96,6 +96,7 @@ add_qtc_plugin(TextEditor
|
|||||||
snippets/snippetssettingspage.cpp snippets/snippetssettingspage.h
|
snippets/snippetssettingspage.cpp snippets/snippetssettingspage.h
|
||||||
storagesettings.cpp storagesettings.h
|
storagesettings.cpp storagesettings.h
|
||||||
syntaxhighlighter.cpp syntaxhighlighter.h
|
syntaxhighlighter.cpp syntaxhighlighter.h
|
||||||
|
syntaxhighlighterrunner.cpp syntaxhighlighterrunner.h
|
||||||
tabsettings.cpp tabsettings.h
|
tabsettings.cpp tabsettings.h
|
||||||
tabsettingswidget.cpp tabsettingswidget.h
|
tabsettingswidget.cpp tabsettingswidget.h
|
||||||
textdocument.cpp textdocument.h
|
textdocument.cpp textdocument.h
|
||||||
|
@@ -74,6 +74,11 @@ Highlighter::Highlighter()
|
|||||||
&categoryForTextStyle);
|
&categoryForTextStyle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
KSyntaxHighlighting::Definition Highlighter::getDefinition()
|
||||||
|
{
|
||||||
|
return definition();
|
||||||
|
}
|
||||||
|
|
||||||
static bool isOpeningParenthesis(QChar c)
|
static bool isOpeningParenthesis(QChar c)
|
||||||
{
|
{
|
||||||
return c == QLatin1Char('{') || c == QLatin1Char('[') || c == QLatin1Char('(');
|
return c == QLatin1Char('{') || c == QLatin1Char('[') || c == QLatin1Char('(');
|
||||||
|
@@ -19,6 +19,8 @@ class Highlighter : public SyntaxHighlighter, public KSyntaxHighlighting::Abstra
|
|||||||
public:
|
public:
|
||||||
Highlighter();
|
Highlighter();
|
||||||
|
|
||||||
|
KSyntaxHighlighting::Definition getDefinition() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void highlightBlock(const QString &text) override;
|
void highlightBlock(const QString &text) override;
|
||||||
void applyFormat(int offset, int length, const KSyntaxHighlighting::Format &format) override;
|
void applyFormat(int offset, int length, const KSyntaxHighlighting::Format &format) override;
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
// Copyright (C) 2023 The Qt Company Ltd.
|
// Copyright (C) 2023 The Qt Company Ltd.
|
||||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||||
|
|
||||||
#include "syntaxhighlighter.h"
|
#include "syntaxhighlighterrunner.h"
|
||||||
|
|
||||||
#include "highlighter_test.h"
|
#include "highlighter_test.h"
|
||||||
|
|
||||||
@@ -42,7 +42,7 @@ void GenerigHighlighterTests::initTestCase()
|
|||||||
m_editor = qobject_cast<BaseTextEditor *>(editor);
|
m_editor = qobject_cast<BaseTextEditor *>(editor);
|
||||||
m_editor->editorWidget()->configureGenericHighlighter(Utils::mimeTypeForName("application/json"));
|
m_editor->editorWidget()->configureGenericHighlighter(Utils::mimeTypeForName("application/json"));
|
||||||
QVERIFY(m_editor);
|
QVERIFY(m_editor);
|
||||||
m_editor->textDocument()->syntaxHighlighter()->rehighlight();
|
m_editor->textDocument()->syntaxHighlighterRunner()->rehighlight();
|
||||||
}
|
}
|
||||||
|
|
||||||
using FormatRanges = QList<QTextLayout::FormatRange>;
|
using FormatRanges = QList<QTextLayout::FormatRange>;
|
||||||
@@ -190,8 +190,12 @@ void GenerigHighlighterTests::testPreeditText()
|
|||||||
QTextBlock block = m_editor->textDocument()->document()->findBlockByNumber(2);
|
QTextBlock block = m_editor->textDocument()->document()->findBlockByNumber(2);
|
||||||
QVERIFY(block.isValid());
|
QVERIFY(block.isValid());
|
||||||
|
|
||||||
|
QTextCursor c(block);
|
||||||
|
c.beginEditBlock();
|
||||||
block.layout()->setPreeditArea(7, "uaf");
|
block.layout()->setPreeditArea(7, "uaf");
|
||||||
m_editor->textDocument()->syntaxHighlighter()->rehighlight();
|
c.endEditBlock();
|
||||||
|
|
||||||
|
m_editor->textDocument()->syntaxHighlighterRunner()->rehighlight();
|
||||||
|
|
||||||
const FormatRanges formatRanges = {{0, 4, toFormat(C_VISUAL_WHITESPACE)},
|
const FormatRanges formatRanges = {{0, 4, toFormat(C_VISUAL_WHITESPACE)},
|
||||||
{4, 3, toFormat(C_TYPE)},
|
{4, 3, toFormat(C_TYPE)},
|
||||||
|
@@ -9,6 +9,7 @@
|
|||||||
#include "texteditor.h"
|
#include "texteditor.h"
|
||||||
#include "texteditorsettings.h"
|
#include "texteditorsettings.h"
|
||||||
#include "texteditortr.h"
|
#include "texteditortr.h"
|
||||||
|
#include "syntaxhighlighterrunner.h"
|
||||||
|
|
||||||
#include <coreplugin/editormanager/documentmodel.h>
|
#include <coreplugin/editormanager/documentmodel.h>
|
||||||
#include <coreplugin/icore.h>
|
#include <coreplugin/icore.h>
|
||||||
@@ -209,7 +210,8 @@ void reload()
|
|||||||
highlightRepository()->reload();
|
highlightRepository()->reload();
|
||||||
for (auto editor : Core::DocumentModel::editorsForOpenedDocuments()) {
|
for (auto editor : Core::DocumentModel::editorsForOpenedDocuments()) {
|
||||||
if (auto textEditor = qobject_cast<BaseTextEditor *>(editor)) {
|
if (auto textEditor = qobject_cast<BaseTextEditor *>(editor)) {
|
||||||
if (qobject_cast<Highlighter *>(textEditor->textDocument()->syntaxHighlighter()))
|
auto highlighterCreator = textEditor->textDocument()->syntaxHighlighterRunner()->creator();
|
||||||
|
if (highlighterCreator && qobject_cast<Highlighter *>(highlighterCreator()))
|
||||||
textEditor->editorWidget()->configureGenericHighlighter();
|
textEditor->editorWidget()->configureGenericHighlighter();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
#include "syntaxhighlighter.h"
|
#include "syntaxhighlighter.h"
|
||||||
#include "texteditorsettings.h"
|
#include "texteditorsettings.h"
|
||||||
|
#include "syntaxhighlighterrunner.h"
|
||||||
|
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
|
|
||||||
@@ -73,9 +74,11 @@ const Ranges rangesForResult(
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SemanticHighlighter::incrementalApplyExtraAdditionalFormats(SyntaxHighlighter *highlighter,
|
void SemanticHighlighter::incrementalApplyExtraAdditionalFormats(
|
||||||
|
BaseSyntaxHighlighterRunner *highlighter,
|
||||||
const QFuture<HighlightingResult> &future,
|
const QFuture<HighlightingResult> &future,
|
||||||
int from, int to,
|
int from,
|
||||||
|
int to,
|
||||||
const QHash<int, QTextCharFormat> &kindToFormat,
|
const QHash<int, QTextCharFormat> &kindToFormat,
|
||||||
const Splitter &splitter)
|
const Splitter &splitter)
|
||||||
{
|
{
|
||||||
@@ -111,17 +114,21 @@ void SemanticHighlighter::incrementalApplyExtraAdditionalFormats(SyntaxHighlight
|
|||||||
formatRanges[range.block].append(range.formatRange);
|
formatRanges[range.block].append(range.formatRange);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QList<int> clearBlockNumberVector;
|
||||||
|
QMap<int, QList<QTextLayout::FormatRange>> blockNumberMap;
|
||||||
for (auto &[block, ranges] : formatRanges) {
|
for (auto &[block, ranges] : formatRanges) {
|
||||||
while (currentBlock < block) {
|
while (currentBlock < block) {
|
||||||
highlighter->clearExtraFormats(currentBlock);
|
clearBlockNumberVector.append(currentBlock.blockNumber());
|
||||||
currentBlock = currentBlock.next();
|
currentBlock = currentBlock.next();
|
||||||
}
|
}
|
||||||
highlighter->setExtraFormats(block, std::move(ranges));
|
blockNumberMap[block.blockNumber()] = ranges;
|
||||||
currentBlock = block.next();
|
currentBlock = block.next();
|
||||||
}
|
}
|
||||||
|
highlighter->clearExtraFormats(clearBlockNumberVector);
|
||||||
|
highlighter->setExtraFormats(blockNumberMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SemanticHighlighter::setExtraAdditionalFormats(SyntaxHighlighter *highlighter,
|
void SemanticHighlighter::setExtraAdditionalFormats(BaseSyntaxHighlighterRunner *highlighter,
|
||||||
const QList<HighlightingResult> &results,
|
const QList<HighlightingResult> &results,
|
||||||
const QHash<int, QTextCharFormat> &kindToFormat)
|
const QHash<int, QTextCharFormat> &kindToFormat)
|
||||||
{
|
{
|
||||||
@@ -132,20 +139,19 @@ void SemanticHighlighter::setExtraAdditionalFormats(SyntaxHighlighter *highlight
|
|||||||
QTextDocument *doc = highlighter->document();
|
QTextDocument *doc = highlighter->document();
|
||||||
QTC_ASSERT(doc, return );
|
QTC_ASSERT(doc, return );
|
||||||
|
|
||||||
std::map<QTextBlock, QVector<QTextLayout::FormatRange>> formatRanges;
|
QMap<int, QList<QTextLayout::FormatRange>> blockNumberMap;
|
||||||
|
|
||||||
for (auto result : results) {
|
for (const HighlightingResult &result : results) {
|
||||||
for (const Range &range : rangesForResult(result, doc, kindToFormat))
|
const Ranges ranges = rangesForResult(result, doc, kindToFormat);
|
||||||
formatRanges[range.block].append(range.formatRange);
|
for (const Range &range : ranges)
|
||||||
|
blockNumberMap[range.block.blockNumber()].append(range.formatRange);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto &[block, ranges] : formatRanges)
|
highlighter->setExtraFormats(blockNumberMap);
|
||||||
highlighter->setExtraFormats(block, std::move(ranges));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SemanticHighlighter::clearExtraAdditionalFormatsUntilEnd(
|
void SemanticHighlighter::clearExtraAdditionalFormatsUntilEnd(
|
||||||
SyntaxHighlighter *highlighter,
|
BaseSyntaxHighlighterRunner *highlighter, const QFuture<HighlightingResult> &future)
|
||||||
const QFuture<HighlightingResult> &future)
|
|
||||||
{
|
{
|
||||||
const QTextDocument * const doc = highlighter->document();
|
const QTextDocument * const doc = highlighter->document();
|
||||||
QTextBlock firstBlockToClear = doc->begin();
|
QTextBlock firstBlockToClear = doc->begin();
|
||||||
@@ -160,6 +166,9 @@ void SemanticHighlighter::clearExtraAdditionalFormatsUntilEnd(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QList<int> clearBlockNumberVector;
|
||||||
for (QTextBlock b = firstBlockToClear; b.isValid(); b = b.next())
|
for (QTextBlock b = firstBlockToClear; b.isValid(); b = b.next())
|
||||||
highlighter->clearExtraFormats(b);
|
clearBlockNumberVector.append(b.blockNumber());
|
||||||
|
|
||||||
|
highlighter->clearExtraFormats(clearBlockNumberVector);
|
||||||
}
|
}
|
||||||
|
@@ -21,6 +21,7 @@ QT_END_NAMESPACE
|
|||||||
namespace TextEditor {
|
namespace TextEditor {
|
||||||
|
|
||||||
class SyntaxHighlighter;
|
class SyntaxHighlighter;
|
||||||
|
class BaseSyntaxHighlighterRunner;
|
||||||
|
|
||||||
class TEXTEDITOR_EXPORT HighlightingResult
|
class TEXTEDITOR_EXPORT HighlightingResult
|
||||||
{
|
{
|
||||||
@@ -72,10 +73,11 @@ using Splitter = std::function<const QList<std::pair<HighlightingResult, QTextBl
|
|||||||
// from all lines that have no results between the (from-1).line result and
|
// from all lines that have no results between the (from-1).line result and
|
||||||
// the (to-1).line result.
|
// the (to-1).line result.
|
||||||
// Requires that results of the Future are ordered by line.
|
// Requires that results of the Future are ordered by line.
|
||||||
void TEXTEDITOR_EXPORT incrementalApplyExtraAdditionalFormats(
|
void TEXTEDITOR_EXPORT
|
||||||
SyntaxHighlighter *highlighter,
|
incrementalApplyExtraAdditionalFormats(BaseSyntaxHighlighterRunner *highlighter,
|
||||||
const QFuture<HighlightingResult> &future,
|
const QFuture<HighlightingResult> &future,
|
||||||
int from, int to,
|
int from,
|
||||||
|
int to,
|
||||||
const QHash<int, QTextCharFormat> &kindToFormat,
|
const QHash<int, QTextCharFormat> &kindToFormat,
|
||||||
const Splitter &splitter = {});
|
const Splitter &splitter = {});
|
||||||
|
|
||||||
@@ -83,8 +85,7 @@ void TEXTEDITOR_EXPORT incrementalApplyExtraAdditionalFormats(
|
|||||||
// indicated by Result::kind and kindToFormat to the correct location using
|
// indicated by Result::kind and kindToFormat to the correct location using
|
||||||
// SyntaxHighlighter::setExtraFormats. In contrast to
|
// SyntaxHighlighter::setExtraFormats. In contrast to
|
||||||
// incrementalApplyExtraAdditionalFormats the results do not have to be ordered by line.
|
// incrementalApplyExtraAdditionalFormats the results do not have to be ordered by line.
|
||||||
void TEXTEDITOR_EXPORT setExtraAdditionalFormats(
|
void TEXTEDITOR_EXPORT setExtraAdditionalFormats(BaseSyntaxHighlighterRunner *highlighter,
|
||||||
SyntaxHighlighter *highlighter,
|
|
||||||
const HighlightingResults &results,
|
const HighlightingResults &results,
|
||||||
const QHash<int, QTextCharFormat> &kindToFormat);
|
const QHash<int, QTextCharFormat> &kindToFormat);
|
||||||
|
|
||||||
@@ -92,9 +93,7 @@ void TEXTEDITOR_EXPORT setExtraAdditionalFormats(
|
|||||||
// until the end of the document.
|
// until the end of the document.
|
||||||
// Requires that results of the Future are ordered by line.
|
// Requires that results of the Future are ordered by line.
|
||||||
void TEXTEDITOR_EXPORT clearExtraAdditionalFormatsUntilEnd(
|
void TEXTEDITOR_EXPORT clearExtraAdditionalFormatsUntilEnd(
|
||||||
SyntaxHighlighter *highlighter,
|
BaseSyntaxHighlighterRunner *highlighter, const QFuture<HighlightingResult> &future);
|
||||||
const QFuture<HighlightingResult> &future);
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace SemanticHighlighter
|
} // namespace SemanticHighlighter
|
||||||
} // namespace TextEditor
|
} // namespace TextEditor
|
||||||
|
@@ -2,7 +2,6 @@
|
|||||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||||
|
|
||||||
#include "syntaxhighlighter.h"
|
#include "syntaxhighlighter.h"
|
||||||
#include "textdocument.h"
|
|
||||||
#include "textdocumentlayout.h"
|
#include "textdocumentlayout.h"
|
||||||
#include "texteditorsettings.h"
|
#include "texteditorsettings.h"
|
||||||
#include "fontsettings.h"
|
#include "fontsettings.h"
|
||||||
@@ -54,13 +53,13 @@ public:
|
|||||||
void updateFormats(const FontSettings &fontSettings);
|
void updateFormats(const FontSettings &fontSettings);
|
||||||
|
|
||||||
FontSettings fontSettings;
|
FontSettings fontSettings;
|
||||||
QVector<QTextCharFormat> formatChanges;
|
QList<QTextCharFormat> formatChanges;
|
||||||
QTextBlock currentBlock;
|
QTextBlock currentBlock;
|
||||||
bool rehighlightPending = false;
|
bool rehighlightPending = false;
|
||||||
bool inReformatBlocks = false;
|
bool inReformatBlocks = false;
|
||||||
TextDocumentLayout::FoldValidator foldValidator;
|
TextDocumentLayout::FoldValidator foldValidator;
|
||||||
QVector<QTextCharFormat> formats;
|
QList<QTextCharFormat> formats;
|
||||||
QVector<std::pair<int,TextStyle>> formatCategories;
|
QList<std::pair<int,TextStyle>> formatCategories;
|
||||||
QTextCharFormat whitespaceFormat;
|
QTextCharFormat whitespaceFormat;
|
||||||
bool noAutomaticHighlighting = false;
|
bool noAutomaticHighlighting = false;
|
||||||
};
|
};
|
||||||
@@ -102,8 +101,8 @@ void SyntaxHighlighterPrivate::applyFormatChanges(int from, int charsRemoved, in
|
|||||||
|
|
||||||
QTextLayout *layout = currentBlock.layout();
|
QTextLayout *layout = currentBlock.layout();
|
||||||
|
|
||||||
QVector<QTextLayout::FormatRange> ranges;
|
QList<QTextLayout::FormatRange> ranges;
|
||||||
QVector<QTextLayout::FormatRange> oldRanges;
|
QList<QTextLayout::FormatRange> oldRanges;
|
||||||
std::tie(oldRanges, ranges)
|
std::tie(oldRanges, ranges)
|
||||||
= Utils::partition(layout->formats(), [](const QTextLayout::FormatRange &range) {
|
= Utils::partition(layout->formats(), [](const QTextLayout::FormatRange &range) {
|
||||||
return range.format.property(SyntaxHighlight).toBool();
|
return range.format.property(SyntaxHighlight).toBool();
|
||||||
@@ -119,7 +118,7 @@ void SyntaxHighlighterPrivate::applyFormatChanges(int from, int charsRemoved, in
|
|||||||
|
|
||||||
QTextLayout::FormatRange r;
|
QTextLayout::FormatRange r;
|
||||||
|
|
||||||
QVector<QTextLayout::FormatRange> newRanges;
|
QList<QTextLayout::FormatRange> newRanges;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while (i < formatChanges.count()) {
|
while (i < formatChanges.count()) {
|
||||||
|
|
||||||
@@ -179,6 +178,7 @@ void SyntaxHighlighter::reformatBlocks(int from, int charsRemoved, int charsAdde
|
|||||||
|
|
||||||
void SyntaxHighlighterPrivate::reformatBlocks(int from, int charsRemoved, int charsAdded)
|
void SyntaxHighlighterPrivate::reformatBlocks(int from, int charsRemoved, int charsAdded)
|
||||||
{
|
{
|
||||||
|
Q_Q(SyntaxHighlighter);
|
||||||
foldValidator.reset();
|
foldValidator.reset();
|
||||||
|
|
||||||
rehighlightPending = false;
|
rehighlightPending = false;
|
||||||
@@ -192,10 +192,12 @@ void SyntaxHighlighterPrivate::reformatBlocks(int from, int charsRemoved, int ch
|
|||||||
if (lastBlock.isValid())
|
if (lastBlock.isValid())
|
||||||
endPosition = lastBlock.position() + lastBlock.length();
|
endPosition = lastBlock.position() + lastBlock.length();
|
||||||
else
|
else
|
||||||
endPosition = doc->lastBlock().position() + doc->lastBlock().length(); //doc->docHandle()->length();
|
endPosition = doc->lastBlock().position() + doc->lastBlock().length();
|
||||||
|
|
||||||
bool forceHighlightOfNextBlock = false;
|
bool forceHighlightOfNextBlock = false;
|
||||||
|
|
||||||
|
QList<SyntaxHighlighter::Result> vecRes;
|
||||||
|
|
||||||
while (block.isValid() && (block.position() < endPosition || forceHighlightOfNextBlock)) {
|
while (block.isValid() && (block.position() < endPosition || forceHighlightOfNextBlock)) {
|
||||||
const int stateBeforeHighlight = block.userState();
|
const int stateBeforeHighlight = block.userState();
|
||||||
|
|
||||||
@@ -203,12 +205,25 @@ void SyntaxHighlighterPrivate::reformatBlocks(int from, int charsRemoved, int ch
|
|||||||
|
|
||||||
forceHighlightOfNextBlock = (block.userState() != stateBeforeHighlight);
|
forceHighlightOfNextBlock = (block.userState() != stateBeforeHighlight);
|
||||||
|
|
||||||
|
SyntaxHighlighter::Result res;
|
||||||
|
res.m_formatRanges = block.layout()->formats();
|
||||||
|
res.fillByBlock(block);
|
||||||
|
vecRes << res;
|
||||||
|
|
||||||
|
// Sending data to the text editor in chunks of 200 blocks is a sensible approach.
|
||||||
|
// This helps avoid UI slowdowns when applying formatting to the text.
|
||||||
|
if (vecRes.size() >= 200) {
|
||||||
|
emit q->resultsReady(vecRes);
|
||||||
|
vecRes.clear();
|
||||||
|
}
|
||||||
|
|
||||||
block = block.next();
|
block = block.next();
|
||||||
}
|
}
|
||||||
|
|
||||||
formatChanges.clear();
|
formatChanges.clear();
|
||||||
|
|
||||||
foldValidator.finalize();
|
foldValidator.finalize();
|
||||||
|
emit q->resultsReady(vecRes);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SyntaxHighlighterPrivate::reformatBlock(const QTextBlock &block, int from, int charsRemoved, int charsAdded)
|
void SyntaxHighlighterPrivate::reformatBlock(const QTextBlock &block, int from, int charsRemoved, int charsAdded)
|
||||||
@@ -670,22 +685,22 @@ static bool byStartOfRange(const QTextLayout::FormatRange &range, const QTextLay
|
|||||||
return range.start < other.start;
|
return range.start < other.start;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The formats is passed in by rvalue reference in order to prevent unnecessary copying of its items.
|
|
||||||
// After this function returns, the list is modified, and should be considered invalidated!
|
|
||||||
void SyntaxHighlighter::setExtraFormats(const QTextBlock &block,
|
void SyntaxHighlighter::setExtraFormats(const QTextBlock &block,
|
||||||
QVector<QTextLayout::FormatRange> &&formats)
|
const QList<QTextLayout::FormatRange> &formats)
|
||||||
{
|
{
|
||||||
Q_D(SyntaxHighlighter);
|
Q_D(SyntaxHighlighter);
|
||||||
|
|
||||||
|
QList<QTextLayout::FormatRange> formatsCopy = formats;
|
||||||
|
|
||||||
const int blockLength = block.length();
|
const int blockLength = block.length();
|
||||||
if (block.layout() == nullptr || blockLength == 0)
|
if (block.layout() == nullptr || blockLength == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const QString preeditText = block.layout()->preeditAreaText();
|
const QString preeditText = block.layout()->preeditAreaText();
|
||||||
if (!preeditText.isEmpty()) {
|
if (!preeditText.isEmpty()) {
|
||||||
QVector<QTextLayout::FormatRange> additionalRanges;
|
QList<QTextLayout::FormatRange> additionalRanges;
|
||||||
const int preeditPosition = block.layout()->preeditAreaPosition();
|
const int preeditPosition = block.layout()->preeditAreaPosition();
|
||||||
for (QTextLayout::FormatRange &r : formats) {
|
for (QTextLayout::FormatRange &r : formatsCopy) {
|
||||||
if (r.start >= preeditPosition) {
|
if (r.start >= preeditPosition) {
|
||||||
r.start += preeditText.length();
|
r.start += preeditText.length();
|
||||||
} else if (r.start + r.length > preeditPosition) {
|
} else if (r.start + r.length > preeditPosition) {
|
||||||
@@ -696,33 +711,39 @@ void SyntaxHighlighter::setExtraFormats(const QTextBlock &block,
|
|||||||
r.length = preeditPosition - r.start;
|
r.length = preeditPosition - r.start;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
formats << additionalRanges;
|
formatsCopy << additionalRanges;
|
||||||
}
|
}
|
||||||
|
|
||||||
Utils::sort(formats, byStartOfRange);
|
Utils::sort(formatsCopy, byStartOfRange);
|
||||||
|
|
||||||
const QVector<QTextLayout::FormatRange> all = block.layout()->formats();
|
const QList<QTextLayout::FormatRange> all = block.layout()->formats();
|
||||||
QVector<QTextLayout::FormatRange> previousSemanticFormats;
|
QList<QTextLayout::FormatRange> previousSemanticFormats;
|
||||||
QVector<QTextLayout::FormatRange> formatsToApply;
|
QList<QTextLayout::FormatRange> formatsToApply;
|
||||||
std::tie(previousSemanticFormats, formatsToApply)
|
std::tie(previousSemanticFormats, formatsToApply)
|
||||||
= Utils::partition(all, [](const QTextLayout::FormatRange &r) {
|
= Utils::partition(all, [](const QTextLayout::FormatRange &r) {
|
||||||
return r.format.property(SemanticHighlight).toBool();
|
return r.format.property(SemanticHighlight).toBool();
|
||||||
});
|
});
|
||||||
|
|
||||||
for (auto &format : formats)
|
for (auto &format : formatsCopy)
|
||||||
format.format.setProperty(SemanticHighlight, true);
|
format.format.setProperty(SemanticHighlight, true);
|
||||||
|
|
||||||
if (formats.size() == previousSemanticFormats.size()) {
|
if (formatsCopy.size() == previousSemanticFormats.size()) {
|
||||||
Utils::sort(previousSemanticFormats, byStartOfRange);
|
Utils::sort(previousSemanticFormats, byStartOfRange);
|
||||||
if (formats == previousSemanticFormats)
|
if (formats == previousSemanticFormats)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
formatsToApply += formats;
|
formatsToApply += formatsCopy;
|
||||||
|
|
||||||
bool wasInReformatBlocks = d->inReformatBlocks;
|
bool wasInReformatBlocks = d->inReformatBlocks;
|
||||||
d->inReformatBlocks = true;
|
d->inReformatBlocks = true;
|
||||||
block.layout()->setFormats(formatsToApply);
|
block.layout()->setFormats(formatsToApply);
|
||||||
|
|
||||||
|
SyntaxHighlighter::Result res;
|
||||||
|
res.m_formatRanges = block.layout()->formats();
|
||||||
|
res.fillByBlock(block);
|
||||||
|
emit resultsReady({res});
|
||||||
|
|
||||||
document()->markContentsDirty(block.position(), blockLength - 1);
|
document()->markContentsDirty(block.position(), blockLength - 1);
|
||||||
d->inReformatBlocks = wasInReformatBlocks;
|
d->inReformatBlocks = wasInReformatBlocks;
|
||||||
}
|
}
|
||||||
@@ -735,7 +756,7 @@ void SyntaxHighlighter::clearExtraFormats(const QTextBlock &block)
|
|||||||
if (block.layout() == nullptr || blockLength == 0)
|
if (block.layout() == nullptr || blockLength == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const QVector<QTextLayout::FormatRange> formatsToApply
|
const QList<QTextLayout::FormatRange> formatsToApply
|
||||||
= Utils::filtered(block.layout()->formats(), [](const QTextLayout::FormatRange &r) {
|
= Utils::filtered(block.layout()->formats(), [](const QTextLayout::FormatRange &r) {
|
||||||
return !r.format.property(SemanticHighlight).toBool();
|
return !r.format.property(SemanticHighlight).toBool();
|
||||||
});
|
});
|
||||||
@@ -743,6 +764,12 @@ void SyntaxHighlighter::clearExtraFormats(const QTextBlock &block)
|
|||||||
bool wasInReformatBlocks = d->inReformatBlocks;
|
bool wasInReformatBlocks = d->inReformatBlocks;
|
||||||
d->inReformatBlocks = true;
|
d->inReformatBlocks = true;
|
||||||
block.layout()->setFormats(formatsToApply);
|
block.layout()->setFormats(formatsToApply);
|
||||||
|
|
||||||
|
SyntaxHighlighter::Result res;
|
||||||
|
res.m_formatRanges = block.layout()->formats();
|
||||||
|
res.fillByBlock(block);
|
||||||
|
emit resultsReady({res});
|
||||||
|
|
||||||
document()->markContentsDirty(block.position(), blockLength - 1);
|
document()->markContentsDirty(block.position(), blockLength - 1);
|
||||||
d->inReformatBlocks = wasInReformatBlocks;
|
d->inReformatBlocks = wasInReformatBlocks;
|
||||||
}
|
}
|
||||||
@@ -832,7 +859,7 @@ void SyntaxHighlighter::setDefaultTextFormatCategories()
|
|||||||
void SyntaxHighlighter::setTextFormatCategories(int count,
|
void SyntaxHighlighter::setTextFormatCategories(int count,
|
||||||
std::function<TextStyle(int)> formatMapping)
|
std::function<TextStyle(int)> formatMapping)
|
||||||
{
|
{
|
||||||
QVector<std::pair<int, TextStyle>> categories;
|
QList<std::pair<int, TextStyle>> categories;
|
||||||
categories.reserve(count);
|
categories.reserve(count);
|
||||||
for (int i = 0; i < count; ++i)
|
for (int i = 0; i < count; ++i)
|
||||||
categories.append({i, formatMapping(i)});
|
categories.append({i, formatMapping(i)});
|
||||||
@@ -848,12 +875,12 @@ void SyntaxHighlighter::setTextFormatCategories(int count,
|
|||||||
|
|
||||||
\sa setDefaultTextFormatCategories()
|
\sa setDefaultTextFormatCategories()
|
||||||
*/
|
*/
|
||||||
void SyntaxHighlighter::setTextFormatCategories(const QVector<std::pair<int, TextStyle>> &categories)
|
void SyntaxHighlighter::setTextFormatCategories(const QList<std::pair<int, TextStyle>> &categories)
|
||||||
{
|
{
|
||||||
Q_D(SyntaxHighlighter);
|
Q_D(SyntaxHighlighter);
|
||||||
d->formatCategories = categories;
|
d->formatCategories = categories;
|
||||||
const int maxCategory = Utils::maxElementOr(categories, {-1, C_TEXT}).first;
|
const int maxCategory = Utils::maxElementOr(categories, {-1, C_TEXT}).first;
|
||||||
d->formats = QVector<QTextCharFormat>(maxCategory + 1);
|
d->formats = QList<QTextCharFormat>(maxCategory + 1);
|
||||||
d->updateFormats(TextEditorSettings::fontSettings());
|
d->updateFormats(TextEditorSettings::fontSettings());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -899,4 +926,3 @@ void SyntaxHighlighterPrivate::updateFormats(const FontSettings &fontSettings)
|
|||||||
|
|
||||||
} // namespace TextEditor
|
} // namespace TextEditor
|
||||||
|
|
||||||
#include "moc_syntaxhighlighter.cpp"
|
|
||||||
|
@@ -6,6 +6,9 @@
|
|||||||
#include "texteditor_global.h"
|
#include "texteditor_global.h"
|
||||||
|
|
||||||
#include <texteditor/texteditorconstants.h>
|
#include <texteditor/texteditorconstants.h>
|
||||||
|
#include <texteditor/textdocumentlayout.h>
|
||||||
|
|
||||||
|
#include <KSyntaxHighlighting/Definition>
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QTextLayout>
|
#include <QTextLayout>
|
||||||
@@ -41,10 +44,6 @@ public:
|
|||||||
void setDocument(QTextDocument *doc);
|
void setDocument(QTextDocument *doc);
|
||||||
QTextDocument *document() const;
|
QTextDocument *document() const;
|
||||||
|
|
||||||
void setExtraFormats(const QTextBlock &block, QVector<QTextLayout::FormatRange> &&formats);
|
|
||||||
void clearExtraFormats(const QTextBlock &block);
|
|
||||||
void clearAllExtraFormats();
|
|
||||||
|
|
||||||
static QList<QColor> generateColors(int n, const QColor &background);
|
static QList<QColor> generateColors(int n, const QColor &background);
|
||||||
|
|
||||||
// Don't call in constructors of derived classes
|
// Don't call in constructors of derived classes
|
||||||
@@ -53,9 +52,73 @@ public:
|
|||||||
|
|
||||||
void setNoAutomaticHighlighting(bool noAutomatic);
|
void setNoAutomaticHighlighting(bool noAutomatic);
|
||||||
|
|
||||||
|
struct Result
|
||||||
|
{
|
||||||
|
void fillByBlock(const QTextBlock &block)
|
||||||
|
{
|
||||||
|
m_blockNumber = block.position();
|
||||||
|
m_userState = block.userState();
|
||||||
|
|
||||||
|
TextBlockUserData *userDate = TextDocumentLayout::textUserData(block);
|
||||||
|
if (!userDate)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_hasBlockUserData = true;
|
||||||
|
m_foldingIndent = userDate->foldingIndent();
|
||||||
|
m_folded = userDate->folded();
|
||||||
|
m_ifdefedOut = userDate->ifdefedOut();
|
||||||
|
m_foldingStartIncluded = userDate->foldingStartIncluded();
|
||||||
|
m_foldingEndIncluded = userDate->foldingEndIncluded();
|
||||||
|
m_parentheses = userDate->parentheses();
|
||||||
|
m_expectedRawStringSuffix = userDate->expectedRawStringSuffix();
|
||||||
|
}
|
||||||
|
|
||||||
|
void copyToBlock(QTextBlock &block) const
|
||||||
|
{
|
||||||
|
block.setUserState(m_userState);
|
||||||
|
|
||||||
|
if (m_hasBlockUserData) {
|
||||||
|
TextBlockUserData *data = TextDocumentLayout::userData(block);
|
||||||
|
data->setExpectedRawStringSuffix(m_expectedRawStringSuffix);
|
||||||
|
data->setFolded(m_folded);
|
||||||
|
data->setFoldingIndent(m_foldingIndent);
|
||||||
|
data->setFoldingStartIncluded(m_foldingStartIncluded);
|
||||||
|
data->setFoldingEndIncluded(m_foldingEndIncluded);
|
||||||
|
|
||||||
|
if (m_ifdefedOut)
|
||||||
|
data->setIfdefedOut();
|
||||||
|
else
|
||||||
|
data->clearIfdefedOut();
|
||||||
|
|
||||||
|
data->setParentheses(m_parentheses);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int m_blockNumber;
|
||||||
|
bool m_hasBlockUserData = false;
|
||||||
|
|
||||||
|
int m_foldingIndent : 16;
|
||||||
|
uint m_folded : 1;
|
||||||
|
uint m_ifdefedOut : 1;
|
||||||
|
uint m_foldingStartIncluded : 1;
|
||||||
|
uint m_foldingEndIncluded : 1;
|
||||||
|
|
||||||
|
Parentheses m_parentheses;
|
||||||
|
QByteArray m_expectedRawStringSuffix;
|
||||||
|
int m_userState = -1;
|
||||||
|
QList<QTextLayout::FormatRange> m_formatRanges;
|
||||||
|
};
|
||||||
|
|
||||||
|
void setExtraFormats(const QTextBlock &block, const QList<QTextLayout::FormatRange> &formats);
|
||||||
|
virtual void setLanguageFeaturesFlags(unsigned int /*flags*/) {}; // needed for CppHighlighting
|
||||||
|
virtual void setEnabled(bool /*enabled*/) {}; // needed for DiffAndLogHighlighter
|
||||||
|
virtual KSyntaxHighlighting::Definition getDefinition() { return {}; }
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
virtual void rehighlight();
|
virtual void rehighlight();
|
||||||
void rehighlightBlock(const QTextBlock &block);
|
void rehighlightBlock(const QTextBlock &block);
|
||||||
|
void clearExtraFormats(const QTextBlock &block);
|
||||||
|
void clearAllExtraFormats();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void setDefaultTextFormatCategories();
|
void setDefaultTextFormatCategories();
|
||||||
@@ -89,8 +152,11 @@ protected:
|
|||||||
protected:
|
protected:
|
||||||
virtual void documentChanged(QTextDocument * /*oldDoc*/, QTextDocument * /*newDoc*/) {};
|
virtual void documentChanged(QTextDocument * /*oldDoc*/, QTextDocument * /*newDoc*/) {};
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void resultsReady(const QList<Result> &result);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void setTextFormatCategories(const QVector<std::pair<int, TextStyle>> &categories);
|
void setTextFormatCategories(const QList<std::pair<int, TextStyle>> &categories);
|
||||||
void reformatBlocks(int from, int charsRemoved, int charsAdded);
|
void reformatBlocks(int from, int charsRemoved, int charsAdded);
|
||||||
void delayedRehighlight();
|
void delayedRehighlight();
|
||||||
|
|
||||||
|
255
src/plugins/texteditor/syntaxhighlighterrunner.cpp
Normal file
255
src/plugins/texteditor/syntaxhighlighterrunner.cpp
Normal file
@@ -0,0 +1,255 @@
|
|||||||
|
// Copyright (C) 2023 The Qt Company Ltd.
|
||||||
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||||
|
|
||||||
|
#include "syntaxhighlighterrunner.h"
|
||||||
|
|
||||||
|
#include <texteditor/fontsettings.h>
|
||||||
|
#include <texteditor/textdocumentlayout.h>
|
||||||
|
|
||||||
|
#include <utils/textutils.h>
|
||||||
|
|
||||||
|
#include <QMetaObject>
|
||||||
|
#include <QTextCursor>
|
||||||
|
#include <QTextDocument>
|
||||||
|
#include <QThread>
|
||||||
|
|
||||||
|
namespace TextEditor {
|
||||||
|
|
||||||
|
class SyntaxHighlighterRunnerPrivate : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
SyntaxHighlighterRunnerPrivate(BaseSyntaxHighlighterRunner::SyntaxHighLighterCreator creator,
|
||||||
|
QTextDocument *document)
|
||||||
|
: m_creator(creator)
|
||||||
|
{
|
||||||
|
m_highlighter.reset(m_creator());
|
||||||
|
m_highlighter->setDocument(document);
|
||||||
|
m_document = document;
|
||||||
|
}
|
||||||
|
|
||||||
|
void create()
|
||||||
|
{
|
||||||
|
if (m_document != nullptr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_document = new QTextDocument(this);
|
||||||
|
m_document->setDocumentLayout(new TextDocumentLayout(m_document));
|
||||||
|
|
||||||
|
m_highlighter.reset(m_creator());
|
||||||
|
m_highlighter->setDocument(m_document);
|
||||||
|
|
||||||
|
connect(m_highlighter.get(),
|
||||||
|
&SyntaxHighlighter::resultsReady,
|
||||||
|
this,
|
||||||
|
&SyntaxHighlighterRunnerPrivate::resultsReady);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cloneDocument(int from,
|
||||||
|
int charsRemoved,
|
||||||
|
const QString textAdded,
|
||||||
|
const QMap<int, BaseSyntaxHighlighterRunner::BlockPreeditData> &blocksPreedit)
|
||||||
|
{
|
||||||
|
QTextCursor cursor(m_document);
|
||||||
|
cursor.setPosition(qMin(m_document->characterCount() - 1, from + charsRemoved));
|
||||||
|
cursor.setPosition(from, QTextCursor::KeepAnchor);
|
||||||
|
cursor.insertText(textAdded);
|
||||||
|
|
||||||
|
for (auto it = blocksPreedit.cbegin(); it != blocksPreedit.cend(); ++it) {
|
||||||
|
const QTextBlock block = m_document->findBlock(it.key());
|
||||||
|
block.layout()->setPreeditArea(it.value().position, it.value().text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setExtraFormats(const QMap<int, QList<QTextLayout::FormatRange>> &formatMap)
|
||||||
|
{
|
||||||
|
for (auto it = formatMap.cbegin(); it != formatMap.cend(); ++it)
|
||||||
|
m_highlighter->setExtraFormats(m_document->findBlockByNumber(it.key()), it.value());
|
||||||
|
}
|
||||||
|
|
||||||
|
void clearExtraFormats(const QList<int> &blockNumbers)
|
||||||
|
{
|
||||||
|
for (auto it = blockNumbers.cbegin(); it != blockNumbers.cend(); ++it)
|
||||||
|
m_highlighter->clearExtraFormats(m_document->findBlockByNumber(*it));
|
||||||
|
}
|
||||||
|
|
||||||
|
void clearAllExtraFormats() { m_highlighter->clearAllExtraFormats(); }
|
||||||
|
|
||||||
|
void setFontSettings(const TextEditor::FontSettings &fontSettings)
|
||||||
|
{
|
||||||
|
m_highlighter->setFontSettings(fontSettings);
|
||||||
|
m_highlighter->rehighlight();
|
||||||
|
}
|
||||||
|
|
||||||
|
KSyntaxHighlighting::Definition getDefinition() { return m_highlighter->getDefinition(); }
|
||||||
|
|
||||||
|
void setLanguageFeaturesFlags(unsigned int flags)
|
||||||
|
{
|
||||||
|
m_highlighter->setLanguageFeaturesFlags(flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setEnabled(bool enabled) { m_highlighter->setEnabled(enabled); }
|
||||||
|
|
||||||
|
void rehighlight() { m_highlighter->rehighlight(); }
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void resultsReady(const QList<SyntaxHighlighter::Result> &result);
|
||||||
|
|
||||||
|
private:
|
||||||
|
BaseSyntaxHighlighterRunner::SyntaxHighLighterCreator m_creator;
|
||||||
|
std::unique_ptr<SyntaxHighlighter> m_highlighter;
|
||||||
|
QTextDocument *m_document = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
// ----------------------------- BaseSyntaxHighlighterRunner --------------------------------------
|
||||||
|
|
||||||
|
BaseSyntaxHighlighterRunner::BaseSyntaxHighlighterRunner(
|
||||||
|
BaseSyntaxHighlighterRunner::SyntaxHighLighterCreator creator, QTextDocument *document)
|
||||||
|
: d(new SyntaxHighlighterRunnerPrivate(creator, document))
|
||||||
|
{
|
||||||
|
m_document = document;
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseSyntaxHighlighterRunner::~BaseSyntaxHighlighterRunner() = default;
|
||||||
|
|
||||||
|
void BaseSyntaxHighlighterRunner::applyFormatRanges(const SyntaxHighlighter::Result &result)
|
||||||
|
{
|
||||||
|
QTextBlock docBlock = m_document->findBlock(result.m_blockNumber);
|
||||||
|
if (!docBlock.isValid())
|
||||||
|
return;
|
||||||
|
|
||||||
|
result.copyToBlock(docBlock);
|
||||||
|
|
||||||
|
if (!result.m_formatRanges.empty()) {
|
||||||
|
TextDocumentLayout::FoldValidator foldValidator;
|
||||||
|
foldValidator.setup(qobject_cast<TextDocumentLayout *>(m_document->documentLayout()));
|
||||||
|
docBlock.layout()->setFormats(result.m_formatRanges);
|
||||||
|
m_document->markContentsDirty(docBlock.position(), docBlock.length());
|
||||||
|
foldValidator.process(docBlock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseSyntaxHighlighterRunner::cloneDocumentData(int from, int charsRemoved, int charsAdded)
|
||||||
|
{
|
||||||
|
QMap<int, BaseSyntaxHighlighterRunner::BlockPreeditData> blocksPreedit;
|
||||||
|
QTextBlock firstBlock = m_document->findBlock(from);
|
||||||
|
QTextBlock endBlock = m_document->findBlock(from + charsAdded);
|
||||||
|
while (firstBlock.isValid() && firstBlock.position() < endBlock.position()) {
|
||||||
|
const int position = firstBlock.position();
|
||||||
|
if (firstBlock.layout()) {
|
||||||
|
const int preeditAreaPosition = firstBlock.layout()->preeditAreaPosition();
|
||||||
|
const QString preeditAreaText = firstBlock.layout()->preeditAreaText();
|
||||||
|
if (preeditAreaPosition != -1)
|
||||||
|
blocksPreedit[position] = {preeditAreaPosition, preeditAreaText};
|
||||||
|
}
|
||||||
|
firstBlock = firstBlock.next();
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString text = Utils::Text::textAt(QTextCursor(m_document), from, charsAdded);
|
||||||
|
cloneDocument(from, charsRemoved, text, blocksPreedit);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseSyntaxHighlighterRunner::cloneDocument(int from,
|
||||||
|
int charsRemoved,
|
||||||
|
const QString textAdded,
|
||||||
|
const QMap<int, BlockPreeditData> &blocksPreedit)
|
||||||
|
{
|
||||||
|
QMetaObject::invokeMethod(d.get(), [this, from, charsRemoved, textAdded, blocksPreedit] {
|
||||||
|
d->cloneDocument(from, charsRemoved, textAdded, blocksPreedit);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseSyntaxHighlighterRunner::setExtraFormats(
|
||||||
|
const QMap<int, QList<QTextLayout::FormatRange>> &formatMap)
|
||||||
|
{
|
||||||
|
QMetaObject::invokeMethod(d.get(), [this, formatMap] { d->setExtraFormats(formatMap); });
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseSyntaxHighlighterRunner::clearExtraFormats(const QList<int> &blockNumbers)
|
||||||
|
{
|
||||||
|
QMetaObject::invokeMethod(d.get(), [this, blockNumbers] { d->clearExtraFormats(blockNumbers); });
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseSyntaxHighlighterRunner::clearAllExtraFormats()
|
||||||
|
{
|
||||||
|
QMetaObject::invokeMethod(d.get(), [this] { d->clearAllExtraFormats(); });
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseSyntaxHighlighterRunner::setFontSettings(const TextEditor::FontSettings &fontSettings)
|
||||||
|
{
|
||||||
|
QMetaObject::invokeMethod(d.get(), [this, fontSettings] { d->setFontSettings(fontSettings); });
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseSyntaxHighlighterRunner::setLanguageFeaturesFlags(unsigned int flags)
|
||||||
|
{
|
||||||
|
QMetaObject::invokeMethod(d.get(), [this, flags] { d->setLanguageFeaturesFlags(flags); });
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseSyntaxHighlighterRunner::setEnabled(bool enabled)
|
||||||
|
{
|
||||||
|
QMetaObject::invokeMethod(d.get(), [this, enabled] { d->setEnabled(enabled); });
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseSyntaxHighlighterRunner::rehighlight()
|
||||||
|
{
|
||||||
|
QMetaObject::invokeMethod(d.get(), [this] { d->rehighlight(); });
|
||||||
|
}
|
||||||
|
|
||||||
|
KSyntaxHighlighting::Definition BaseSyntaxHighlighterRunner::getDefinition()
|
||||||
|
{
|
||||||
|
return d->getDefinition();
|
||||||
|
}
|
||||||
|
|
||||||
|
// --------------------------- ThreadedSyntaxHighlighterRunner ------------------------------------
|
||||||
|
|
||||||
|
ThreadedSyntaxHighlighterRunner::ThreadedSyntaxHighlighterRunner(SyntaxHighLighterCreator creator,
|
||||||
|
QTextDocument *document)
|
||||||
|
: BaseSyntaxHighlighterRunner(creator, nullptr)
|
||||||
|
{
|
||||||
|
QTC_ASSERT(document, return);
|
||||||
|
|
||||||
|
d->moveToThread(&m_thread);
|
||||||
|
connect(&m_thread, &QThread::finished, d.get(), [this] { d.release()->deleteLater(); });
|
||||||
|
m_thread.start();
|
||||||
|
|
||||||
|
QMetaObject::invokeMethod(d.get(), &SyntaxHighlighterRunnerPrivate::create);
|
||||||
|
|
||||||
|
m_document = document;
|
||||||
|
connect(d.get(),
|
||||||
|
&SyntaxHighlighterRunnerPrivate::resultsReady,
|
||||||
|
document,
|
||||||
|
[this](const QList<SyntaxHighlighter::Result> &result) {
|
||||||
|
for (const SyntaxHighlighter::Result &res : result)
|
||||||
|
applyFormatRanges(res);
|
||||||
|
});
|
||||||
|
cloneDocumentData(0, 0, document->characterCount());
|
||||||
|
connect(document,
|
||||||
|
&QTextDocument::contentsChange,
|
||||||
|
this,
|
||||||
|
[this](int from, int charsRemoved, int charsAdded) {
|
||||||
|
if (!this->document())
|
||||||
|
return;
|
||||||
|
|
||||||
|
cloneDocumentData(from, charsRemoved, charsAdded);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ThreadedSyntaxHighlighterRunner::~ThreadedSyntaxHighlighterRunner()
|
||||||
|
{
|
||||||
|
m_thread.quit();
|
||||||
|
m_thread.wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
KSyntaxHighlighting::Definition ThreadedSyntaxHighlighterRunner::getDefinition()
|
||||||
|
{
|
||||||
|
KSyntaxHighlighting::Definition definition;
|
||||||
|
QMetaObject::invokeMethod(
|
||||||
|
d.get(),
|
||||||
|
[this, &definition] { definition = d->getDefinition(); },
|
||||||
|
Qt::BlockingQueuedConnection);
|
||||||
|
return definition;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace TextEditor
|
||||||
|
|
||||||
|
#include "syntaxhighlighterrunner.moc"
|
75
src/plugins/texteditor/syntaxhighlighterrunner.h
Normal file
75
src/plugins/texteditor/syntaxhighlighterrunner.h
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
// Copyright (C) 2023 The Qt Company Ltd.
|
||||||
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <texteditor/syntaxhighlighter.h>
|
||||||
|
|
||||||
|
#include <KSyntaxHighlighting/Definition>
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QPointer>
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
class QTextDocument;
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
namespace TextEditor {
|
||||||
|
|
||||||
|
class SyntaxHighlighterRunnerPrivate;
|
||||||
|
|
||||||
|
class TEXTEDITOR_EXPORT BaseSyntaxHighlighterRunner : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
using SyntaxHighLighterCreator = std::function<SyntaxHighlighter *()>;
|
||||||
|
struct BlockPreeditData {
|
||||||
|
int position;
|
||||||
|
QString text;
|
||||||
|
};
|
||||||
|
|
||||||
|
BaseSyntaxHighlighterRunner(SyntaxHighLighterCreator creator, QTextDocument *document);
|
||||||
|
virtual ~BaseSyntaxHighlighterRunner();
|
||||||
|
|
||||||
|
void setExtraFormats(const QMap<int, QList<QTextLayout::FormatRange>> &formats);
|
||||||
|
void clearExtraFormats(const QList<int> &blockNumbers);
|
||||||
|
void clearAllExtraFormats();
|
||||||
|
void setFontSettings(const TextEditor::FontSettings &fontSettings);
|
||||||
|
void setLanguageFeaturesFlags(unsigned int flags);
|
||||||
|
void setEnabled(bool enabled);
|
||||||
|
void rehighlight();
|
||||||
|
|
||||||
|
virtual KSyntaxHighlighting::Definition getDefinition();
|
||||||
|
|
||||||
|
QTextDocument *document() const { return m_document; }
|
||||||
|
SyntaxHighLighterCreator creator() const { return m_creator; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::unique_ptr<SyntaxHighlighterRunnerPrivate> d;
|
||||||
|
QPointer<QTextDocument> m_document = nullptr;
|
||||||
|
void applyFormatRanges(const SyntaxHighlighter::Result &result);
|
||||||
|
void cloneDocumentData(int from, int charsRemoved, int charsAdded);
|
||||||
|
void cloneDocument(int from,
|
||||||
|
int charsRemoved,
|
||||||
|
const QString textAdded,
|
||||||
|
const QMap<int, BlockPreeditData> &blocksPreedit);
|
||||||
|
|
||||||
|
private:
|
||||||
|
SyntaxHighLighterCreator m_creator;
|
||||||
|
};
|
||||||
|
|
||||||
|
class TEXTEDITOR_EXPORT ThreadedSyntaxHighlighterRunner : public BaseSyntaxHighlighterRunner
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ThreadedSyntaxHighlighterRunner(SyntaxHighLighterCreator SyntaxHighLighterCreator,
|
||||||
|
QTextDocument *document);
|
||||||
|
~ThreadedSyntaxHighlighterRunner();
|
||||||
|
|
||||||
|
KSyntaxHighlighting::Definition getDefinition() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QThread m_thread;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace TextEditor
|
||||||
|
|
@@ -13,11 +13,13 @@
|
|||||||
#include "texteditortr.h"
|
#include "texteditortr.h"
|
||||||
#include "textindenter.h"
|
#include "textindenter.h"
|
||||||
#include "typingsettings.h"
|
#include "typingsettings.h"
|
||||||
|
#include "syntaxhighlighterrunner.h"
|
||||||
|
|
||||||
#include <coreplugin/coreconstants.h>
|
#include <coreplugin/coreconstants.h>
|
||||||
#include <coreplugin/diffservice.h>
|
#include <coreplugin/diffservice.h>
|
||||||
#include <coreplugin/editormanager/documentmodel.h>
|
#include <coreplugin/editormanager/documentmodel.h>
|
||||||
#include <coreplugin/editormanager/editormanager.h>
|
#include <coreplugin/editormanager/editormanager.h>
|
||||||
|
#include <coreplugin/documentmanager.h>
|
||||||
#include <coreplugin/icore.h>
|
#include <coreplugin/icore.h>
|
||||||
#include <coreplugin/progressmanager/progressmanager.h>
|
#include <coreplugin/progressmanager/progressmanager.h>
|
||||||
|
|
||||||
@@ -73,7 +75,6 @@ public:
|
|||||||
FontSettings m_fontSettings;
|
FontSettings m_fontSettings;
|
||||||
bool m_fontSettingsNeedsApply = false; // for applying font settings delayed till an editor becomes visible
|
bool m_fontSettingsNeedsApply = false; // for applying font settings delayed till an editor becomes visible
|
||||||
QTextDocument m_document;
|
QTextDocument m_document;
|
||||||
SyntaxHighlighter *m_highlighter = nullptr;
|
|
||||||
CompletionAssistProvider *m_completionAssistProvider = nullptr;
|
CompletionAssistProvider *m_completionAssistProvider = nullptr;
|
||||||
CompletionAssistProvider *m_functionHintAssistProvider = nullptr;
|
CompletionAssistProvider *m_functionHintAssistProvider = nullptr;
|
||||||
IAssistProvider *m_quickFixProvider = nullptr;
|
IAssistProvider *m_quickFixProvider = nullptr;
|
||||||
@@ -92,6 +93,8 @@ public:
|
|||||||
|
|
||||||
TextMarks m_marksCache; // Marks not owned
|
TextMarks m_marksCache; // Marks not owned
|
||||||
Utils::Guard m_modificationChangedGuard;
|
Utils::Guard m_modificationChangedGuard;
|
||||||
|
|
||||||
|
BaseSyntaxHighlighterRunner *m_highlighterRunner = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
MultiTextCursor TextDocumentPrivate::indentOrUnindent(const MultiTextCursor &cursors,
|
MultiTextCursor TextDocumentPrivate::indentOrUnindent(const MultiTextCursor &cursors,
|
||||||
@@ -450,10 +453,8 @@ void TextDocument::applyFontSettings()
|
|||||||
block = block.next();
|
block = block.next();
|
||||||
}
|
}
|
||||||
updateLayout();
|
updateLayout();
|
||||||
if (d->m_highlighter) {
|
if (d->m_highlighterRunner)
|
||||||
d->m_highlighter->setFontSettings(d->m_fontSettings);
|
d->m_highlighterRunner->setFontSettings(d->m_fontSettings);
|
||||||
d->m_highlighter->rehighlight();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const FontSettings &TextDocument::fontSettings() const
|
const FontSettings &TextDocument::fontSettings() const
|
||||||
@@ -625,9 +626,9 @@ QTextDocument *TextDocument::document() const
|
|||||||
return &d->m_document;
|
return &d->m_document;
|
||||||
}
|
}
|
||||||
|
|
||||||
SyntaxHighlighter *TextDocument::syntaxHighlighter() const
|
BaseSyntaxHighlighterRunner *TextDocument::syntaxHighlighterRunner() const
|
||||||
{
|
{
|
||||||
return d->m_highlighter;
|
return d->m_highlighterRunner;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -901,14 +902,18 @@ bool TextDocument::reload(QString *errorString, ReloadFlag flag, ChangeType type
|
|||||||
return reload(errorString);
|
return reload(errorString);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextDocument::setSyntaxHighlighterCreator(const SyntaxHighLighterCreator &creator)
|
void TextDocument::resetSyntaxHighlighter(const std::function<SyntaxHighlighter *()> &creator,
|
||||||
|
bool threaded)
|
||||||
{
|
{
|
||||||
if (d->m_highlighter)
|
if (d->m_highlighterRunner)
|
||||||
delete d->m_highlighter;
|
delete d->m_highlighterRunner;
|
||||||
|
|
||||||
d->m_highlighter = creator();
|
if (threaded) {
|
||||||
d->m_highlighter->setParent(this);
|
d->m_highlighterRunner = new ThreadedSyntaxHighlighterRunner(creator, document());
|
||||||
d->m_highlighter->setDocument(&d->m_document);
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
d->m_highlighterRunner = new BaseSyntaxHighlighterRunner(creator, document());
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextDocument::cleanWhitespace(const QTextCursor &cursor)
|
void TextDocument::cleanWhitespace(const QTextCursor &cursor)
|
||||||
|
@@ -34,6 +34,7 @@ class FontSettings;
|
|||||||
class IAssistProvider;
|
class IAssistProvider;
|
||||||
class StorageSettings;
|
class StorageSettings;
|
||||||
class SyntaxHighlighter;
|
class SyntaxHighlighter;
|
||||||
|
class BaseSyntaxHighlighterRunner;
|
||||||
class TabSettings;
|
class TabSettings;
|
||||||
class TextDocumentPrivate;
|
class TextDocumentPrivate;
|
||||||
class TextMark;
|
class TextMark;
|
||||||
@@ -126,8 +127,8 @@ public:
|
|||||||
QTextDocument *document() const;
|
QTextDocument *document() const;
|
||||||
|
|
||||||
using SyntaxHighLighterCreator = std::function<SyntaxHighlighter *()>;
|
using SyntaxHighLighterCreator = std::function<SyntaxHighlighter *()>;
|
||||||
void setSyntaxHighlighterCreator(const SyntaxHighLighterCreator &creator);
|
void resetSyntaxHighlighter(const SyntaxHighLighterCreator &creator, bool threaded = true);
|
||||||
SyntaxHighlighter *syntaxHighlighter() const;
|
BaseSyntaxHighlighterRunner *syntaxHighlighterRunner() const;
|
||||||
|
|
||||||
bool reload(QString *errorString, QTextCodec *codec);
|
bool reload(QString *errorString, QTextCodec *codec);
|
||||||
void cleanWhitespace(const QTextCursor &cursor);
|
void cleanWhitespace(const QTextCursor &cursor);
|
||||||
|
@@ -34,6 +34,7 @@
|
|||||||
#include "texteditorsettings.h"
|
#include "texteditorsettings.h"
|
||||||
#include "texteditortr.h"
|
#include "texteditortr.h"
|
||||||
#include "typingsettings.h"
|
#include "typingsettings.h"
|
||||||
|
#include "syntaxhighlighterrunner.h"
|
||||||
|
|
||||||
#include <aggregation/aggregate.h>
|
#include <aggregation/aggregate.h>
|
||||||
|
|
||||||
@@ -1930,9 +1931,11 @@ void TextEditorWidgetPrivate::foldLicenseHeader()
|
|||||||
const QString trimmedText = text.trimmed();
|
const QString trimmedText = text.trimmed();
|
||||||
QStringList commentMarker;
|
QStringList commentMarker;
|
||||||
QStringList docMarker;
|
QStringList docMarker;
|
||||||
if (auto highlighter = qobject_cast<Highlighter *>(
|
HighlighterHelper::Definition def;
|
||||||
q->textDocument()->syntaxHighlighter())) {
|
if (BaseSyntaxHighlighterRunner *highlighter = q->textDocument()->syntaxHighlighterRunner())
|
||||||
const HighlighterHelper::Definition def = highlighter->definition();
|
def = highlighter->getDefinition();
|
||||||
|
|
||||||
|
if (def.isValid()) {
|
||||||
for (const QString &marker :
|
for (const QString &marker :
|
||||||
{def.singleLineCommentMarker(), def.multiLineCommentMarker().first}) {
|
{def.singleLineCommentMarker(), def.multiLineCommentMarker().first}) {
|
||||||
if (!marker.isEmpty())
|
if (!marker.isEmpty())
|
||||||
@@ -3706,12 +3709,12 @@ void TextEditorWidgetPrivate::configureGenericHighlighter(
|
|||||||
q->setCodeFoldingSupported(false);
|
q->setCodeFoldingSupported(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_document->setSyntaxHighlighterCreator([definition] {
|
m_document->resetSyntaxHighlighter([definition] {
|
||||||
auto highlighter = new Highlighter();
|
auto highlighter = new Highlighter();
|
||||||
if (definition.isValid())
|
if (definition.isValid())
|
||||||
highlighter->setDefinition(definition);
|
highlighter->setDefinition(definition);
|
||||||
return highlighter;
|
return highlighter;
|
||||||
});
|
}, false);
|
||||||
|
|
||||||
m_document->setFontSettings(TextEditorSettings::fontSettings());
|
m_document->setFontSettings(TextEditorSettings::fontSettings());
|
||||||
}
|
}
|
||||||
@@ -3736,8 +3739,8 @@ void TextEditorWidgetPrivate::setupFromDefinition(const KSyntaxHighlighting::Def
|
|||||||
|
|
||||||
KSyntaxHighlighting::Definition TextEditorWidgetPrivate::currentDefinition()
|
KSyntaxHighlighting::Definition TextEditorWidgetPrivate::currentDefinition()
|
||||||
{
|
{
|
||||||
if (auto highlighter = qobject_cast<Highlighter *>(m_document->syntaxHighlighter()))
|
if (BaseSyntaxHighlighterRunner *highlighter = m_document->syntaxHighlighterRunner())
|
||||||
return highlighter->definition();
|
return highlighter->getDefinition();
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -8120,7 +8123,7 @@ void TextEditorWidget::setDisplaySettings(const DisplaySettings &ds)
|
|||||||
optionFlags.setFlag(QTextOption::AddSpaceForLineAndParagraphSeparators);
|
optionFlags.setFlag(QTextOption::AddSpaceForLineAndParagraphSeparators);
|
||||||
optionFlags.setFlag(QTextOption::ShowTabsAndSpaces, ds.m_visualizeWhitespace);
|
optionFlags.setFlag(QTextOption::ShowTabsAndSpaces, ds.m_visualizeWhitespace);
|
||||||
if (optionFlags != currentOptionFlags) {
|
if (optionFlags != currentOptionFlags) {
|
||||||
if (SyntaxHighlighter *highlighter = textDocument()->syntaxHighlighter())
|
if (BaseSyntaxHighlighterRunner *highlighter = textDocument()->syntaxHighlighterRunner())
|
||||||
highlighter->rehighlight();
|
highlighter->rehighlight();
|
||||||
QTextOption option = document()->defaultTextOption();
|
QTextOption option = document()->defaultTextOption();
|
||||||
option.setFlags(optionFlags);
|
option.setFlags(optionFlags);
|
||||||
@@ -9259,7 +9262,7 @@ QString TextEditorWidget::textAt(int from, int to) const
|
|||||||
|
|
||||||
void TextEditorWidget::configureGenericHighlighter()
|
void TextEditorWidget::configureGenericHighlighter()
|
||||||
{
|
{
|
||||||
HighlighterHelper::Definitions definitions = HighlighterHelper::definitionsForDocument(textDocument());
|
const HighlighterHelper::Definitions definitions = HighlighterHelper::definitionsForDocument(textDocument());
|
||||||
d->configureGenericHighlighter(definitions.isEmpty() ? HighlighterHelper::Definition()
|
d->configureGenericHighlighter(definitions.isEmpty() ? HighlighterHelper::Definition()
|
||||||
: definitions.first());
|
: definitions.first());
|
||||||
d->updateSyntaxInfoBar(definitions, textDocument()->filePath().fileName());
|
d->updateSyntaxInfoBar(definitions, textDocument()->filePath().fileName());
|
||||||
@@ -9267,7 +9270,7 @@ void TextEditorWidget::configureGenericHighlighter()
|
|||||||
|
|
||||||
void TextEditorWidget::configureGenericHighlighter(const Utils::MimeType &mimeType)
|
void TextEditorWidget::configureGenericHighlighter(const Utils::MimeType &mimeType)
|
||||||
{
|
{
|
||||||
HighlighterHelper::Definitions definitions = HighlighterHelper::definitionsForMimeType(mimeType.name());
|
const HighlighterHelper::Definitions definitions = HighlighterHelper::definitionsForMimeType(mimeType.name());
|
||||||
d->configureGenericHighlighter(definitions.isEmpty() ? HighlighterHelper::Definition()
|
d->configureGenericHighlighter(definitions.isEmpty() ? HighlighterHelper::Definition()
|
||||||
: definitions.first());
|
: definitions.first());
|
||||||
d->removeSyntaxInfoBar();
|
d->removeSyntaxInfoBar();
|
||||||
@@ -9275,7 +9278,7 @@ void TextEditorWidget::configureGenericHighlighter(const Utils::MimeType &mimeTy
|
|||||||
|
|
||||||
expected_str<void> TextEditorWidget::configureGenericHighlighter(const QString &definitionName)
|
expected_str<void> TextEditorWidget::configureGenericHighlighter(const QString &definitionName)
|
||||||
{
|
{
|
||||||
HighlighterHelper::Definition definition = TextEditor::HighlighterHelper::definitionForName(definitionName);
|
const HighlighterHelper::Definition definition = TextEditor::HighlighterHelper::definitionForName(definitionName);
|
||||||
if (!definition.isValid())
|
if (!definition.isValid())
|
||||||
return make_unexpected(Tr::tr("Could not find definition."));
|
return make_unexpected(Tr::tr("Could not find definition."));
|
||||||
|
|
||||||
@@ -9453,7 +9456,7 @@ void TextEditorFactory::setEditorCreator(const EditorCreator &creator)
|
|||||||
doc->setIndenter(d->m_indenterCreator(doc->document()));
|
doc->setIndenter(d->m_indenterCreator(doc->document()));
|
||||||
|
|
||||||
if (d->m_syntaxHighlighterCreator)
|
if (d->m_syntaxHighlighterCreator)
|
||||||
doc->setSyntaxHighlighterCreator(d->m_syntaxHighlighterCreator);
|
doc->resetSyntaxHighlighter(d->m_syntaxHighlighterCreator);
|
||||||
|
|
||||||
doc->setCompletionAssistProvider(d->m_completionAssistProvider ? d->m_completionAssistProvider
|
doc->setCompletionAssistProvider(d->m_completionAssistProvider ? d->m_completionAssistProvider
|
||||||
: &basicSnippetProvider);
|
: &basicSnippetProvider);
|
||||||
|
@@ -124,6 +124,8 @@ QtcPlugin {
|
|||||||
"storagesettings.h",
|
"storagesettings.h",
|
||||||
"syntaxhighlighter.cpp",
|
"syntaxhighlighter.cpp",
|
||||||
"syntaxhighlighter.h",
|
"syntaxhighlighter.h",
|
||||||
|
"syntaxhighlighterrunner.cpp",
|
||||||
|
"syntaxhighlighterrunner.h",
|
||||||
"tabsettings.cpp",
|
"tabsettings.cpp",
|
||||||
"tabsettings.h",
|
"tabsettings.h",
|
||||||
"tabsettingswidget.cpp",
|
"tabsettingswidget.cpp",
|
||||||
|
@@ -222,9 +222,9 @@ void DiffAndLogHighlighter::setFontSettings(const TextEditor::FontSettings &font
|
|||||||
d->updateOtherFormats();
|
d->updateOtherFormats();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DiffAndLogHighlighter::setEnabled(bool e)
|
void DiffAndLogHighlighter::setEnabled(bool enabled)
|
||||||
{
|
{
|
||||||
d->m_enabled = e;
|
d->m_enabled = enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace VcsBase
|
} // namespace VcsBase
|
||||||
|
@@ -23,11 +23,11 @@ public:
|
|||||||
~DiffAndLogHighlighter() override;
|
~DiffAndLogHighlighter() override;
|
||||||
|
|
||||||
void highlightBlock(const QString &text) override;
|
void highlightBlock(const QString &text) override;
|
||||||
|
void setEnabled(bool enabled) override;
|
||||||
|
|
||||||
|
protected:
|
||||||
void setFontSettings(const TextEditor::FontSettings &fontSettings) override;
|
void setFontSettings(const TextEditor::FontSettings &fontSettings) override;
|
||||||
|
|
||||||
void setEnabled(bool e);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class DiffAndLogHighlighterPrivate;
|
friend class DiffAndLogHighlighterPrivate;
|
||||||
DiffAndLogHighlighterPrivate *const d;
|
DiffAndLogHighlighterPrivate *const d;
|
||||||
|
@@ -28,6 +28,7 @@
|
|||||||
|
|
||||||
#include <texteditor/textdocument.h>
|
#include <texteditor/textdocument.h>
|
||||||
#include <texteditor/textdocumentlayout.h>
|
#include <texteditor/textdocumentlayout.h>
|
||||||
|
#include <texteditor/syntaxhighlighterrunner.h>
|
||||||
|
|
||||||
#include <utils/algorithm.h>
|
#include <utils/algorithm.h>
|
||||||
#include <utils/progressindicator.h>
|
#include <utils/progressindicator.h>
|
||||||
@@ -761,7 +762,7 @@ void VcsBaseEditorWidget::init()
|
|||||||
}
|
}
|
||||||
if (hasDiff()) {
|
if (hasDiff()) {
|
||||||
setCodeFoldingSupported(true);
|
setCodeFoldingSupported(true);
|
||||||
textDocument()->setSyntaxHighlighterCreator(
|
textDocument()->resetSyntaxHighlighter(
|
||||||
[diffFilePattern = d->m_diffFilePattern, logEntryPattern = d->m_logEntryPattern] {
|
[diffFilePattern = d->m_diffFilePattern, logEntryPattern = d->m_logEntryPattern] {
|
||||||
return new DiffAndLogHighlighter(diffFilePattern, logEntryPattern);
|
return new DiffAndLogHighlighter(diffFilePattern, logEntryPattern);
|
||||||
});
|
});
|
||||||
@@ -824,8 +825,7 @@ void VcsBaseEditorWidget::setFileLogAnnotateEnabled(bool e)
|
|||||||
|
|
||||||
void VcsBaseEditorWidget::setHighlightingEnabled(bool e)
|
void VcsBaseEditorWidget::setHighlightingEnabled(bool e)
|
||||||
{
|
{
|
||||||
auto dh = static_cast<DiffAndLogHighlighter *>(textDocument()->syntaxHighlighter());
|
textDocument()->syntaxHighlighterRunner()->setEnabled(e);
|
||||||
dh->setEnabled(e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FilePath VcsBaseEditorWidget::workingDirectory() const
|
FilePath VcsBaseEditorWidget::workingDirectory() const
|
||||||
@@ -1100,11 +1100,11 @@ void VcsBaseEditorWidget::slotActivateAnnotation()
|
|||||||
|
|
||||||
disconnect(this, &QPlainTextEdit::textChanged, this, &VcsBaseEditorWidget::slotActivateAnnotation);
|
disconnect(this, &QPlainTextEdit::textChanged, this, &VcsBaseEditorWidget::slotActivateAnnotation);
|
||||||
|
|
||||||
if (auto ah = qobject_cast<BaseAnnotationHighlighter *>(textDocument()->syntaxHighlighter())) {
|
if (BaseSyntaxHighlighterRunner *ah = textDocument()->syntaxHighlighterRunner()) {
|
||||||
ah->rehighlight();
|
ah->rehighlight();
|
||||||
} else {
|
} else {
|
||||||
BaseAnnotationHighlighterCreator creator = annotationHighlighterCreator();
|
BaseAnnotationHighlighterCreator creator = annotationHighlighterCreator();
|
||||||
textDocument()->setSyntaxHighlighterCreator(
|
textDocument()->resetSyntaxHighlighter(
|
||||||
[creator, annotation = d->m_annotation] { return creator(annotation); });
|
[creator, annotation = d->m_annotation] { return creator(annotation); });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
#include <texteditor/semantichighlighter.h>
|
#include <texteditor/semantichighlighter.h>
|
||||||
#include <texteditor/syntaxhighlighter.h>
|
#include <texteditor/syntaxhighlighter.h>
|
||||||
|
#include <texteditor/syntaxhighlighterrunner.h>
|
||||||
#include <texteditor/texteditorsettings.h>
|
#include <texteditor/texteditorsettings.h>
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
@@ -31,7 +32,7 @@ private slots:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
QTextDocument *doc = nullptr;
|
QTextDocument *doc = nullptr;
|
||||||
SyntaxHighlighter *highlighter = nullptr;
|
BaseSyntaxHighlighterRunner *highlighterRunner = nullptr;
|
||||||
FontSettings fontsettings;
|
FontSettings fontsettings;
|
||||||
QHash<int, QTextCharFormat> formatHash;
|
QHash<int, QTextCharFormat> formatHash;
|
||||||
QTextCharFormat whitespaceFormat;
|
QTextCharFormat whitespaceFormat;
|
||||||
@@ -59,7 +60,9 @@ Last)";
|
|||||||
doc = new QTextDocument();
|
doc = new QTextDocument();
|
||||||
doc->setPlainText(text);
|
doc->setPlainText(text);
|
||||||
|
|
||||||
highlighter = new SyntaxHighlighter(doc, fontsettings);
|
highlighterRunner
|
||||||
|
= new BaseSyntaxHighlighterRunner([this] { return new SyntaxHighlighter(doc, fontsettings); },
|
||||||
|
doc);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const HighlightingResults &highlightingResults()
|
static const HighlightingResults &highlightingResults()
|
||||||
@@ -77,7 +80,7 @@ void tst_highlighter::test_setExtraAdditionalFormats()
|
|||||||
{
|
{
|
||||||
QCOMPARE(doc->blockCount(), 4);
|
QCOMPARE(doc->blockCount(), 4);
|
||||||
|
|
||||||
SemanticHighlighter::setExtraAdditionalFormats(highlighter, highlightingResults(), formatHash);
|
SemanticHighlighter::setExtraAdditionalFormats(highlighterRunner, highlightingResults(), formatHash);
|
||||||
|
|
||||||
for (auto block = doc->firstBlock(); block.isValid(); block = block.next()) {
|
for (auto block = doc->firstBlock(); block.isValid(); block = block.next()) {
|
||||||
QVERIFY(block.blockNumber() < 4);
|
QVERIFY(block.blockNumber() < 4);
|
||||||
@@ -140,17 +143,17 @@ void tst_highlighter::test_clearExtraFormats()
|
|||||||
{
|
{
|
||||||
QCOMPARE(doc->blockCount(), 4);
|
QCOMPARE(doc->blockCount(), 4);
|
||||||
|
|
||||||
SemanticHighlighter::setExtraAdditionalFormats(highlighter, highlightingResults(), formatHash);
|
SemanticHighlighter::setExtraAdditionalFormats(highlighterRunner, highlightingResults(), formatHash);
|
||||||
|
|
||||||
QTextBlock firstBlock = doc->findBlockByNumber(0);
|
QTextBlock firstBlock = doc->findBlockByNumber(0);
|
||||||
QTextBlock spacesLineBlock = doc->findBlockByNumber(1);
|
QTextBlock spacesLineBlock = doc->findBlockByNumber(1);
|
||||||
QTextBlock emptyLineBlock = doc->findBlockByNumber(2);
|
QTextBlock emptyLineBlock = doc->findBlockByNumber(2);
|
||||||
QTextBlock lastBlock = doc->findBlockByNumber(3);
|
QTextBlock lastBlock = doc->findBlockByNumber(3);
|
||||||
|
|
||||||
highlighter->clearExtraFormats(emptyLineBlock);
|
highlighterRunner->clearExtraFormats({emptyLineBlock.blockNumber()});
|
||||||
QVERIFY(emptyLineBlock.layout()->formats().isEmpty());
|
QVERIFY(emptyLineBlock.layout()->formats().isEmpty());
|
||||||
|
|
||||||
highlighter->clearExtraFormats(spacesLineBlock);
|
highlighterRunner->clearExtraFormats({spacesLineBlock.blockNumber()});
|
||||||
|
|
||||||
auto formats = spacesLineBlock.layout()->formats();
|
auto formats = spacesLineBlock.layout()->formats();
|
||||||
// the spaces are not extra formats and should remain when clearing extra formats
|
// the spaces are not extra formats and should remain when clearing extra formats
|
||||||
@@ -185,7 +188,7 @@ void tst_highlighter::test_clearExtraFormats()
|
|||||||
QCOMPARE(formats.at(1).start, 0);
|
QCOMPARE(formats.at(1).start, 0);
|
||||||
QCOMPARE(formats.at(1).length, 5);
|
QCOMPARE(formats.at(1).length, 5);
|
||||||
|
|
||||||
highlighter->clearAllExtraFormats();
|
highlighterRunner->clearAllExtraFormats();
|
||||||
|
|
||||||
QVERIFY(firstBlock.layout()->formats().isEmpty());
|
QVERIFY(firstBlock.layout()->formats().isEmpty());
|
||||||
QVERIFY(emptyLineBlock.layout()->formats().isEmpty());
|
QVERIFY(emptyLineBlock.layout()->formats().isEmpty());
|
||||||
@@ -221,7 +224,7 @@ void tst_highlighter::test_incrementalApplyAdditionalFormats()
|
|||||||
|
|
||||||
QFutureInterface<HighlightingResult> fiOld;
|
QFutureInterface<HighlightingResult> fiOld;
|
||||||
fiOld.reportResults(highlightingResults());
|
fiOld.reportResults(highlightingResults());
|
||||||
SemanticHighlighter::incrementalApplyExtraAdditionalFormats(highlighter,
|
SemanticHighlighter::incrementalApplyExtraAdditionalFormats(highlighterRunner,
|
||||||
fiOld.future(),
|
fiOld.future(),
|
||||||
2,
|
2,
|
||||||
0,
|
0,
|
||||||
@@ -229,7 +232,7 @@ void tst_highlighter::test_incrementalApplyAdditionalFormats()
|
|||||||
auto formats = firstBlock.layout()->formats();
|
auto formats = firstBlock.layout()->formats();
|
||||||
QVERIFY(formats.isEmpty());
|
QVERIFY(formats.isEmpty());
|
||||||
|
|
||||||
SemanticHighlighter::incrementalApplyExtraAdditionalFormats(highlighter,
|
SemanticHighlighter::incrementalApplyExtraAdditionalFormats(highlighterRunner,
|
||||||
fiOld.future(),
|
fiOld.future(),
|
||||||
0,
|
0,
|
||||||
2,
|
2,
|
||||||
@@ -254,7 +257,7 @@ void tst_highlighter::test_incrementalApplyAdditionalFormats()
|
|||||||
QCOMPARE(formats.at(1).start, 11);
|
QCOMPARE(formats.at(1).start, 11);
|
||||||
QCOMPARE(formats.at(1).length, 1);
|
QCOMPARE(formats.at(1).length, 1);
|
||||||
|
|
||||||
SemanticHighlighter::incrementalApplyExtraAdditionalFormats(highlighter,
|
SemanticHighlighter::incrementalApplyExtraAdditionalFormats(highlighterRunner,
|
||||||
fiOld.future(),
|
fiOld.future(),
|
||||||
3,
|
3,
|
||||||
6,
|
6,
|
||||||
@@ -280,7 +283,7 @@ void tst_highlighter::test_incrementalApplyAdditionalFormats()
|
|||||||
|
|
||||||
QFutureInterface<HighlightingResult> fiNew;
|
QFutureInterface<HighlightingResult> fiNew;
|
||||||
fiNew.reportResults(newResults);
|
fiNew.reportResults(newResults);
|
||||||
SemanticHighlighter::incrementalApplyExtraAdditionalFormats(highlighter,
|
SemanticHighlighter::incrementalApplyExtraAdditionalFormats(highlighterRunner,
|
||||||
fiNew.future(),
|
fiNew.future(),
|
||||||
0,
|
0,
|
||||||
3,
|
3,
|
||||||
@@ -294,7 +297,7 @@ void tst_highlighter::test_incrementalApplyAdditionalFormats()
|
|||||||
QCOMPARE(formats.at(0).start, 0);
|
QCOMPARE(formats.at(0).start, 0);
|
||||||
QCOMPARE(formats.at(0).length, 1);
|
QCOMPARE(formats.at(0).length, 1);
|
||||||
|
|
||||||
SemanticHighlighter::incrementalApplyExtraAdditionalFormats(highlighter,
|
SemanticHighlighter::incrementalApplyExtraAdditionalFormats(highlighterRunner,
|
||||||
fiNew.future(),
|
fiNew.future(),
|
||||||
3,
|
3,
|
||||||
4,
|
4,
|
||||||
@@ -305,14 +308,14 @@ void tst_highlighter::test_incrementalApplyAdditionalFormats()
|
|||||||
QVERIFY(formats.isEmpty());
|
QVERIFY(formats.isEmpty());
|
||||||
|
|
||||||
// QTCREATORBUG-29218
|
// QTCREATORBUG-29218
|
||||||
highlighter->clearAllExtraFormats();
|
highlighterRunner->clearAllExtraFormats();
|
||||||
const HighlightingResults bug29218Results{HighlightingResult(1, 1, 2, 0),
|
const HighlightingResults bug29218Results{HighlightingResult(1, 1, 2, 0),
|
||||||
HighlightingResult(1, 3, 2, 1)};
|
HighlightingResult(1, 3, 2, 1)};
|
||||||
QFutureInterface<HighlightingResult> fi29218;
|
QFutureInterface<HighlightingResult> fi29218;
|
||||||
fi29218.reportResults(bug29218Results);
|
fi29218.reportResults(bug29218Results);
|
||||||
formats = firstBlock.layout()->formats();
|
formats = firstBlock.layout()->formats();
|
||||||
QVERIFY(formats.isEmpty());
|
QVERIFY(formats.isEmpty());
|
||||||
SemanticHighlighter::incrementalApplyExtraAdditionalFormats(highlighter,
|
SemanticHighlighter::incrementalApplyExtraAdditionalFormats(highlighterRunner,
|
||||||
fi29218.future(),
|
fi29218.future(),
|
||||||
0,
|
0,
|
||||||
1,
|
1,
|
||||||
@@ -323,7 +326,7 @@ void tst_highlighter::test_incrementalApplyAdditionalFormats()
|
|||||||
QCOMPARE(formats.at(0).format.fontOverline(), false);
|
QCOMPARE(formats.at(0).format.fontOverline(), false);
|
||||||
QCOMPARE(formats.at(0).start, 0);
|
QCOMPARE(formats.at(0).start, 0);
|
||||||
QCOMPARE(formats.at(0).length, 2);
|
QCOMPARE(formats.at(0).length, 2);
|
||||||
SemanticHighlighter::incrementalApplyExtraAdditionalFormats(highlighter,
|
SemanticHighlighter::incrementalApplyExtraAdditionalFormats(highlighterRunner,
|
||||||
fi29218.future(),
|
fi29218.future(),
|
||||||
1,
|
1,
|
||||||
2,
|
2,
|
||||||
@@ -347,7 +350,7 @@ void tst_highlighter::test_preeditText()
|
|||||||
QTextBlock firstBlock = doc->findBlockByNumber(0);
|
QTextBlock firstBlock = doc->findBlockByNumber(0);
|
||||||
firstBlock.layout()->setPreeditArea(2, "uaf");
|
firstBlock.layout()->setPreeditArea(2, "uaf");
|
||||||
|
|
||||||
SemanticHighlighter::setExtraAdditionalFormats(highlighter, highlightingResults(), formatHash);
|
SemanticHighlighter::setExtraAdditionalFormats(highlighterRunner, highlightingResults(), formatHash);
|
||||||
|
|
||||||
auto formats = firstBlock.layout()->formats();
|
auto formats = firstBlock.layout()->formats();
|
||||||
QCOMPARE(formats.size(), 2);
|
QCOMPARE(formats.size(), 2);
|
||||||
@@ -366,7 +369,7 @@ void tst_highlighter::cleanup()
|
|||||||
{
|
{
|
||||||
delete doc;
|
delete doc;
|
||||||
doc = nullptr;
|
doc = nullptr;
|
||||||
highlighter = nullptr;
|
highlighterRunner = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace TextEditor
|
} // namespace TextEditor
|
||||||
|
Reference in New Issue
Block a user