TextEditor: handle syntax highlight in batches

Use an elapsed timer in the syntax highlighter to periodically return
from the highlight and push a continue highlight to the end of the event
loop.
This allows the user to interact with the editor in between those
batches. If the user modifies the document in between highlighting
batches, the area that still needs a rehighlight is increased if needed.

This also reverts 62ea85ee6a and the
related changes.

Task-number: QTCREATORBUG-28727
Change-Id: I7c394dbdff658330bb72f3b68b9928980947db75
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
David Schulz
2024-03-13 14:57:59 +01:00
parent 8500dd03bf
commit d4e775ebc6
26 changed files with 242 additions and 791 deletions

View File

@@ -10,10 +10,10 @@
#include "tabsettings.h"
#include "textdocumentlayout.h"
#include "texteditor.h"
#include "texteditorsettings.h"
#include "texteditortr.h"
#include "textindenter.h"
#include "typingsettings.h"
#include "syntaxhighlighterrunner.h"
#include <coreplugin/coreconstants.h>
#include <coreplugin/diffservice.h>
@@ -64,8 +64,6 @@ public:
~TextDocumentPrivate()
{
if (m_highlighterRunner)
m_highlighterRunner->deleteLater();
}
MultiTextCursor indentOrUnindent(const MultiTextCursor &cursor, bool doIndent, const TabSettings &tabSettings);
@@ -101,7 +99,7 @@ public:
TextMarks m_marksCache; // Marks not owned
Utils::Guard m_modificationChangedGuard;
SyntaxHighlighterRunner *m_highlighterRunner = nullptr;
SyntaxHighlighter *m_highlighter = nullptr;
};
MultiTextCursor TextDocumentPrivate::indentOrUnindent(const MultiTextCursor &cursors,
@@ -462,8 +460,8 @@ void TextDocument::applyFontSettings()
block = block.next();
}
updateLayout();
if (d->m_highlighterRunner)
d->m_highlighterRunner->setFontSettings(d->m_fontSettings);
if (d->m_highlighter)
d->m_highlighter->setFontSettings(d->m_fontSettings);
}
const FontSettings &TextDocument::fontSettings() const
@@ -533,6 +531,15 @@ bool TextDocument::applyChangeSet(const ChangeSet &changeSet)
// the blocks list must be sorted
void TextDocument::setIfdefedOutBlocks(const QList<BlockRange> &blocks)
{
if (syntaxHighlighter() && !syntaxHighlighter()->syntaxHighlighterUpToDate()) {
connect(syntaxHighlighter(),
&SyntaxHighlighter::finished,
this,
[this, blocks] { setIfdefedOutBlocks(blocks); },
Qt::SingleShotConnection);
return;
}
QTextDocument *doc = document();
auto documentLayout = qobject_cast<TextDocumentLayout*>(doc->documentLayout());
QTC_ASSERT(documentLayout, return);
@@ -635,11 +642,6 @@ QTextDocument *TextDocument::document() const
return &d->m_document;
}
SyntaxHighlighterRunner *TextDocument::syntaxHighlighterRunner() const
{
return d->m_highlighterRunner;
}
/*!
* Saves the document to the file specified by \a fileName. If errors occur,
* \a errorString contains their cause.
@@ -911,26 +913,19 @@ bool TextDocument::reload(QString *errorString, ReloadFlag flag, ChangeType type
return reload(errorString);
}
void TextDocument::resetSyntaxHighlighter(const std::function<SyntaxHighlighter *()> &creator,
bool threaded)
void TextDocument::resetSyntaxHighlighter(const std::function<SyntaxHighlighter *()> &creator)
{
delete d->m_highlighterRunner;
static const std::optional<bool> envValue = []() -> std::optional<bool> {
const QString key("QTC_USE_THREADED_HIGHLIGHTER");
if (qtcEnvironmentVariableIsSet(key)) {
const QString value = qtcEnvironmentVariable(key).toUpper();
return value != "FALSE" && value != "0";
}
return {};
}();
SyntaxHighlighter *highlighter = creator();
highlighter->setParent(this);
highlighter->setDocument(this->document());
highlighter->setFontSettings(TextEditorSettings::fontSettings());
highlighter->setMimeType(mimeType());
d->m_highlighterRunner = new SyntaxHighlighterRunner(highlighter,
document(),
envValue.value_or(threaded));
d->m_highlighter = highlighter;
}
SyntaxHighlighter *TextDocument::syntaxHighlighter() const
{
return d->m_highlighter;
}
void TextDocument::cleanWhitespace(const QTextCursor &cursor)