forked from qt-creator/qt-creator
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:
@@ -6,7 +6,6 @@
|
|||||||
#include <cplusplus/MatchingText.h>
|
#include <cplusplus/MatchingText.h>
|
||||||
|
|
||||||
#include <texteditor/tabsettings.h>
|
#include <texteditor/tabsettings.h>
|
||||||
#include <texteditor/syntaxhighlighterrunner.h>
|
|
||||||
|
|
||||||
#include <QTextBlock>
|
#include <QTextBlock>
|
||||||
#include <QTextCursor>
|
#include <QTextCursor>
|
||||||
@@ -17,6 +16,7 @@
|
|||||||
|
|
||||||
#include <coreplugin/editormanager/editormanager.h>
|
#include <coreplugin/editormanager/editormanager.h>
|
||||||
#include <texteditor/icodestylepreferences.h>
|
#include <texteditor/icodestylepreferences.h>
|
||||||
|
#include <texteditor/syntaxhighlighter.h>
|
||||||
#include <texteditor/textdocument.h>
|
#include <texteditor/textdocument.h>
|
||||||
#include <texteditor/texteditor.h>
|
#include <texteditor/texteditor.h>
|
||||||
#include <texteditor/texteditorsettings.h>
|
#include <texteditor/texteditorsettings.h>
|
||||||
@@ -276,9 +276,9 @@ void AutoCompleterTest::testAutoComplete()
|
|||||||
|
|
||||||
TextEditor::BaseTextEditor *cppEditor = creteCppEditor(text);
|
TextEditor::BaseTextEditor *cppEditor = creteCppEditor(text);
|
||||||
QVERIFY(cppEditor);
|
QVERIFY(cppEditor);
|
||||||
QTRY_VERIFY(cppEditor->textDocument()->syntaxHighlighterRunner()->syntaxInfoUpdated());
|
QTRY_VERIFY(cppEditor->textDocument()->syntaxHighlighter()->syntaxHighlighterUpToDate());
|
||||||
QTextCursor tc = openEditor(cppEditor);
|
QTextCursor tc = openEditor(cppEditor);
|
||||||
QTRY_VERIFY(cppEditor->textDocument()->syntaxHighlighterRunner()->syntaxInfoUpdated());
|
QTRY_VERIFY(cppEditor->textDocument()->syntaxHighlighter()->syntaxHighlighterUpToDate());
|
||||||
|
|
||||||
QVERIFY(!tc.isNull());
|
QVERIFY(!tc.isNull());
|
||||||
|
|
||||||
@@ -339,9 +339,9 @@ void AutoCompleterTest::testSurroundWithSelection()
|
|||||||
const QScopeGuard cleanup([] { Core::EditorManager::closeAllEditors(false); });
|
const QScopeGuard cleanup([] { Core::EditorManager::closeAllEditors(false); });
|
||||||
TextEditor::BaseTextEditor *cppEditor = creteCppEditor(text);
|
TextEditor::BaseTextEditor *cppEditor = creteCppEditor(text);
|
||||||
QVERIFY(cppEditor);
|
QVERIFY(cppEditor);
|
||||||
QTRY_VERIFY(cppEditor->textDocument()->syntaxHighlighterRunner()->syntaxInfoUpdated());
|
QTRY_VERIFY(cppEditor->textDocument()->syntaxHighlighter()->syntaxHighlighterUpToDate());
|
||||||
QTextCursor tc = openEditor(cppEditor);
|
QTextCursor tc = openEditor(cppEditor);
|
||||||
QTRY_VERIFY(cppEditor->textDocument()->syntaxHighlighterRunner()->syntaxInfoUpdated());
|
QTRY_VERIFY(cppEditor->textDocument()->syntaxHighlighter()->syntaxHighlighterUpToDate());
|
||||||
|
|
||||||
QVERIFY(!tc.isNull());
|
QVERIFY(!tc.isNull());
|
||||||
|
|
||||||
@@ -376,9 +376,9 @@ void AutoCompleterTest::testAutoBackspace()
|
|||||||
const QScopeGuard cleanup([] { Core::EditorManager::closeAllEditors(false); });
|
const QScopeGuard cleanup([] { Core::EditorManager::closeAllEditors(false); });
|
||||||
TextEditor::BaseTextEditor *cppEditor = creteCppEditor(text);
|
TextEditor::BaseTextEditor *cppEditor = creteCppEditor(text);
|
||||||
QVERIFY(cppEditor);
|
QVERIFY(cppEditor);
|
||||||
QTRY_VERIFY(cppEditor->textDocument()->syntaxHighlighterRunner()->syntaxInfoUpdated());
|
QTRY_VERIFY(cppEditor->textDocument()->syntaxHighlighter()->syntaxHighlighterUpToDate());
|
||||||
QTextCursor tc = openEditor(cppEditor);
|
QTextCursor tc = openEditor(cppEditor);
|
||||||
QTRY_VERIFY(cppEditor->textDocument()->syntaxHighlighterRunner()->syntaxInfoUpdated());
|
QTRY_VERIFY(cppEditor->textDocument()->syntaxHighlighter()->syntaxHighlighterUpToDate());
|
||||||
|
|
||||||
QVERIFY(!tc.isNull());
|
QVERIFY(!tc.isNull());
|
||||||
|
|
||||||
@@ -420,9 +420,9 @@ void AutoCompleterTest::testInsertParagraph()
|
|||||||
const QScopeGuard cleanup([] { Core::EditorManager::closeAllEditors(false); });
|
const QScopeGuard cleanup([] { Core::EditorManager::closeAllEditors(false); });
|
||||||
TextEditor::BaseTextEditor *cppEditor = creteCppEditor(text);
|
TextEditor::BaseTextEditor *cppEditor = creteCppEditor(text);
|
||||||
QVERIFY(cppEditor);
|
QVERIFY(cppEditor);
|
||||||
QTRY_VERIFY(cppEditor->textDocument()->syntaxHighlighterRunner()->syntaxInfoUpdated());
|
QTRY_VERIFY(cppEditor->textDocument()->syntaxHighlighter()->syntaxHighlighterUpToDate());
|
||||||
QTextCursor tc = openEditor(cppEditor);
|
QTextCursor tc = openEditor(cppEditor);
|
||||||
QTRY_VERIFY(cppEditor->textDocument()->syntaxHighlighterRunner()->syntaxInfoUpdated());
|
QTRY_VERIFY(cppEditor->textDocument()->syntaxHighlighter()->syntaxHighlighterUpToDate());
|
||||||
|
|
||||||
QVERIFY(!tc.isNull());
|
QVERIFY(!tc.isNull());
|
||||||
|
|
||||||
|
@@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
#include <coreplugin/editormanager/editormanager.h>
|
#include <coreplugin/editormanager/editormanager.h>
|
||||||
#include <texteditor/codeassist/iassistproposal.h>
|
#include <texteditor/codeassist/iassistproposal.h>
|
||||||
#include <texteditor/syntaxhighlighterrunner.h>
|
#include <texteditor/syntaxhighlighter.h>
|
||||||
#include <texteditor/textdocument.h>
|
#include <texteditor/textdocument.h>
|
||||||
#include <texteditor/texteditor.h>
|
#include <texteditor/texteditor.h>
|
||||||
|
|
||||||
@@ -146,12 +146,10 @@ public:
|
|||||||
TextEditor::BaseTextEditor *cppEditor = qobject_cast<TextEditor::BaseTextEditor *>(m_editor);
|
TextEditor::BaseTextEditor *cppEditor = qobject_cast<TextEditor::BaseTextEditor *>(m_editor);
|
||||||
if (!cppEditor)
|
if (!cppEditor)
|
||||||
return false;
|
return false;
|
||||||
if (cppEditor->textDocument()->syntaxHighlighterRunner()->syntaxInfoUpdated())
|
if (cppEditor->textDocument()->syntaxHighlighter()->syntaxHighlighterUpToDate())
|
||||||
return true;
|
return true;
|
||||||
return ::CppEditor::Tests::waitForSignalOrTimeout(
|
return ::CppEditor::Tests::waitForSignalOrTimeout(
|
||||||
cppEditor->textDocument()->syntaxHighlighterRunner(),
|
cppEditor->textDocument()->syntaxHighlighter(), &SyntaxHighlighter::finished, 5000);
|
||||||
&SyntaxHighlighterRunner::highlightingFinished,
|
|
||||||
5000);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@@ -20,7 +20,6 @@
|
|||||||
#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>
|
||||||
@@ -164,7 +163,7 @@ QByteArray CppEditorDocument::contentsText() const
|
|||||||
|
|
||||||
void CppEditorDocument::applyFontSettings()
|
void CppEditorDocument::applyFontSettings()
|
||||||
{
|
{
|
||||||
if (TextEditor::SyntaxHighlighterRunner *highlighter = syntaxHighlighterRunner())
|
if (TextEditor::SyntaxHighlighter *highlighter = syntaxHighlighter())
|
||||||
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)
|
||||||
@@ -408,7 +407,7 @@ 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
|
||||||
if (SyntaxHighlighterRunner *highlighter = syntaxHighlighterRunner())
|
if (SyntaxHighlighter *highlighter = syntaxHighlighter())
|
||||||
highlighter->setLanguageFeaturesFlags(document->languageFeatures().flags);
|
highlighter->setLanguageFeaturesFlags(document->languageFeatures().flags);
|
||||||
|
|
||||||
m_overviewModel.update(usesClangd() ? nullptr : document);
|
m_overviewModel.update(usesClangd() ? nullptr : document);
|
||||||
|
@@ -84,8 +84,13 @@ void CppHighlighter::highlightBlock(const QString &text)
|
|||||||
const int firstNonSpace = tokens.first().utf16charsBegin();
|
const int firstNonSpace = tokens.first().utf16charsBegin();
|
||||||
|
|
||||||
// Keep "semantic parentheses".
|
// Keep "semantic parentheses".
|
||||||
Parentheses parentheses = Utils::filtered(TextDocumentLayout::parentheses(currentBlock()),
|
Parentheses parentheses;
|
||||||
[](const Parenthesis &p) { return p.source.isValid(); });
|
if (TextBlockUserData *userData = TextDocumentLayout::textUserData(currentBlock())) {
|
||||||
|
parentheses = Utils::filtered(userData->parentheses(), [](const Parenthesis &p) {
|
||||||
|
return p.source.isValid();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const auto insertParen = [&parentheses](const Parenthesis &p) { insertSorted(parentheses, p); };
|
const auto insertParen = [&parentheses](const Parenthesis &p) { insertSorted(parentheses, p); };
|
||||||
parentheses.reserve(5);
|
parentheses.reserve(5);
|
||||||
|
|
||||||
@@ -235,7 +240,8 @@ void CppHighlighter::highlightBlock(const QString &text)
|
|||||||
// if the block is ifdefed out, we only store the parentheses, but
|
// if the block is ifdefed out, we only store the parentheses, but
|
||||||
|
|
||||||
// do not adjust the brace depth.
|
// do not adjust the brace depth.
|
||||||
if (TextDocumentLayout::ifdefedOut(currentBlock())) {
|
if (TextBlockUserData *userData = TextDocumentLayout::textUserData(currentBlock());
|
||||||
|
userData && userData->ifdefedOut()) {
|
||||||
braceDepth = initialBraceDepth;
|
braceDepth = initialBraceDepth;
|
||||||
foldingIndent = initialBraceDepth;
|
foldingIndent = initialBraceDepth;
|
||||||
}
|
}
|
||||||
|
@@ -26,7 +26,7 @@
|
|||||||
#include <texteditor/codeassist/iassistproposal.h>
|
#include <texteditor/codeassist/iassistproposal.h>
|
||||||
#include <texteditor/codeassist/iassistproposalmodel.h>
|
#include <texteditor/codeassist/iassistproposalmodel.h>
|
||||||
#include <texteditor/storagesettings.h>
|
#include <texteditor/storagesettings.h>
|
||||||
#include <texteditor/syntaxhighlighterrunner.h>
|
#include <texteditor/syntaxhighlighter.h>
|
||||||
#include <texteditor/texteditor.h>
|
#include <texteditor/texteditor.h>
|
||||||
|
|
||||||
#include <utils/environment.h>
|
#include <utils/environment.h>
|
||||||
@@ -238,8 +238,8 @@ bool TestCase::openCppEditor(const FilePath &filePath, TextEditor::BaseTextEdito
|
|||||||
[e] {
|
[e] {
|
||||||
return e->editorWidget()
|
return e->editorWidget()
|
||||||
->textDocument()
|
->textDocument()
|
||||||
->syntaxHighlighterRunner()
|
->syntaxHighlighter()
|
||||||
->syntaxInfoUpdated();
|
->syntaxHighlighterUpToDate();
|
||||||
},
|
},
|
||||||
5000))
|
5000))
|
||||||
return false;
|
return false;
|
||||||
|
@@ -8,7 +8,6 @@
|
|||||||
#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>
|
||||||
@@ -67,12 +66,15 @@ void SemanticHighlighter::run()
|
|||||||
|
|
||||||
Parentheses SemanticHighlighter::getClearedParentheses(const QTextBlock &block)
|
Parentheses SemanticHighlighter::getClearedParentheses(const QTextBlock &block)
|
||||||
{
|
{
|
||||||
Parentheses parens = TextDocumentLayout::parentheses(block);
|
Parentheses parens;
|
||||||
|
if (TextBlockUserData *userData = TextDocumentLayout::textUserData(block))
|
||||||
|
parens = userData->parentheses();
|
||||||
if (m_seenBlocks.insert(block.blockNumber()).second) {
|
if (m_seenBlocks.insert(block.blockNumber()).second) {
|
||||||
parens = Utils::filtered(parens, [](const Parenthesis &p) {
|
parens = Utils::filtered(parens, [](const Parenthesis &p) {
|
||||||
return p.source != parenSource();
|
return p.source != parenSource();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return parens;
|
return parens;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,7 +109,7 @@ void SemanticHighlighter::handleHighlighterResults()
|
|||||||
QElapsedTimer t;
|
QElapsedTimer t;
|
||||||
t.start();
|
t.start();
|
||||||
|
|
||||||
SyntaxHighlighterRunner *highlighter = m_baseTextDocument->syntaxHighlighterRunner();
|
SyntaxHighlighter *highlighter = m_baseTextDocument->syntaxHighlighter();
|
||||||
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);
|
||||||
|
|
||||||
@@ -195,7 +197,7 @@ void SemanticHighlighter::onHighlighterFinished()
|
|||||||
t.start();
|
t.start();
|
||||||
|
|
||||||
if (!m_watcher->isCanceled() && documentRevision() == m_revision) {
|
if (!m_watcher->isCanceled() && documentRevision() == m_revision) {
|
||||||
SyntaxHighlighterRunner *highlighter = m_baseTextDocument->syntaxHighlighterRunner();
|
SyntaxHighlighter *highlighter = m_baseTextDocument->syntaxHighlighter();
|
||||||
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());
|
||||||
|
@@ -9,9 +9,9 @@
|
|||||||
#include "fakevimhandler.h"
|
#include "fakevimhandler.h"
|
||||||
|
|
||||||
#include <coreplugin/editormanager/editormanager.h>
|
#include <coreplugin/editormanager/editormanager.h>
|
||||||
#include <texteditor/texteditor.h>
|
#include <texteditor/syntaxhighlighter.h>
|
||||||
#include <texteditor/textdocument.h>
|
#include <texteditor/textdocument.h>
|
||||||
#include <texteditor/syntaxhighlighterrunner.h>
|
#include <texteditor/texteditor.h>
|
||||||
|
|
||||||
#include <QtTest>
|
#include <QtTest>
|
||||||
#include <QTextEdit>
|
#include <QTextEdit>
|
||||||
@@ -350,7 +350,7 @@ struct FakeVimTester::TestData
|
|||||||
void doCommand(const char *cmd) { doCommand(_(cmd)); }
|
void doCommand(const char *cmd) { doCommand(_(cmd)); }
|
||||||
void doKeys(const QString &keys) {
|
void doKeys(const QString &keys) {
|
||||||
handler->handleInput(keys);
|
handler->handleInput(keys);
|
||||||
QTRY_VERIFY(editor()->textDocument()->syntaxHighlighterRunner()->syntaxInfoUpdated());
|
QTRY_VERIFY(editor()->textDocument()->syntaxHighlighter()->syntaxHighlighterUpToDate());
|
||||||
}
|
}
|
||||||
void doKeys(const char *keys) { doKeys(_(keys)); }
|
void doKeys(const char *keys) { doKeys(_(keys)); }
|
||||||
|
|
||||||
@@ -364,7 +364,7 @@ struct FakeVimTester::TestData
|
|||||||
else
|
else
|
||||||
i = 0;
|
i = 0;
|
||||||
editor()->document()->setPlainText(_(str));
|
editor()->document()->setPlainText(_(str));
|
||||||
QTRY_VERIFY(editor()->textDocument()->syntaxHighlighterRunner()->syntaxInfoUpdated());
|
QTRY_VERIFY(editor()->textDocument()->syntaxHighlighter()->syntaxHighlighterUpToDate());
|
||||||
setPosition(i);
|
setPosition(i);
|
||||||
QCOMPARE(position(), i);
|
QCOMPARE(position(), i);
|
||||||
}
|
}
|
||||||
@@ -375,7 +375,7 @@ struct FakeVimTester::TestData
|
|||||||
QTextCursor tc = editor()->textCursor();
|
QTextCursor tc = editor()->textCursor();
|
||||||
tc.insertText(_(text));
|
tc.insertText(_(text));
|
||||||
editor()->setTextCursor(tc);
|
editor()->setTextCursor(tc);
|
||||||
QTRY_VERIFY(editor()->textDocument()->syntaxHighlighterRunner()->syntaxInfoUpdated());
|
QTRY_VERIFY(editor()->textDocument()->syntaxHighlighter()->syntaxHighlighterUpToDate());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Simulate external position change.
|
// Simulate external position change.
|
||||||
|
@@ -190,7 +190,8 @@ void GlslHighlighter::highlightBlock(const QString &text)
|
|||||||
|
|
||||||
// if the block is ifdefed out, we only store the parentheses, but
|
// if the block is ifdefed out, we only store the parentheses, but
|
||||||
// do not adjust the brace depth.
|
// do not adjust the brace depth.
|
||||||
if (TextDocumentLayout::ifdefedOut(currentBlock())) {
|
if (TextBlockUserData *userData = TextDocumentLayout::textUserData(currentBlock());
|
||||||
|
userData && userData->ifdefedOut()) {
|
||||||
braceDepth = initialBraceDepth;
|
braceDepth = initialBraceDepth;
|
||||||
foldingIndent = initialBraceDepth;
|
foldingIndent = initialBraceDepth;
|
||||||
}
|
}
|
||||||
|
@@ -10,7 +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 <texteditor/syntaxhighlighter.h>
|
||||||
#include <utils/algorithm.h>
|
#include <utils/algorithm.h>
|
||||||
#include <utils/mimeutils.h>
|
#include <utils/mimeutils.h>
|
||||||
|
|
||||||
@@ -183,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::SyntaxHighlighterRunner *highlighter = doc->syntaxHighlighterRunner())
|
if (TextEditor::SyntaxHighlighter *highlighter = doc->syntaxHighlighter())
|
||||||
highlighter->clearAllExtraFormats();
|
highlighter->clearAllExtraFormats();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -413,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;
|
||||||
SyntaxHighlighterRunner *highlighter = doc->syntaxHighlighterRunner();
|
SyntaxHighlighter *highlighter = doc->syntaxHighlighter();
|
||||||
if (!highlighter)
|
if (!highlighter)
|
||||||
return;
|
return;
|
||||||
const VersionedTokens versionedTokens = m_tokens.value(filePath);
|
const VersionedTokens versionedTokens = m_tokens.value(filePath);
|
||||||
|
@@ -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->syntaxHighlighterRunner(), m_watcher.future(), from, to, m_extraFormats);
|
m_document->syntaxHighlighter(), 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->syntaxHighlighterRunner(), m_watcher.future());
|
m_document->syntaxHighlighter(), m_watcher.future());
|
||||||
}
|
}
|
||||||
|
|
||||||
void SemanticHighlighter::run(QPromise<Use> &promise,
|
void SemanticHighlighter::run(QPromise<Use> &promise,
|
||||||
|
@@ -96,7 +96,6 @@ 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
|
||||||
|
@@ -1,11 +1,10 @@
|
|||||||
// 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 "syntaxhighlighterrunner.h"
|
|
||||||
|
|
||||||
#include "highlighter_test.h"
|
#include "highlighter_test.h"
|
||||||
|
|
||||||
#include "fontsettings.h"
|
#include "fontsettings.h"
|
||||||
|
#include "syntaxhighlighter.h"
|
||||||
#include "textdocument.h"
|
#include "textdocument.h"
|
||||||
#include "texteditor.h"
|
#include "texteditor.h"
|
||||||
#include "texteditorsettings.h"
|
#include "texteditorsettings.h"
|
||||||
@@ -61,7 +60,7 @@ void GenerigHighlighterTests::initTestCase()
|
|||||||
m_editor->editorWidget()->configureGenericHighlighter(
|
m_editor->editorWidget()->configureGenericHighlighter(
|
||||||
Utils::mimeTypeForName(Utils::Constants::JSON_MIMETYPE));
|
Utils::mimeTypeForName(Utils::Constants::JSON_MIMETYPE));
|
||||||
QVERIFY(m_editor);
|
QVERIFY(m_editor);
|
||||||
m_editor->textDocument()->syntaxHighlighterRunner()->rehighlight();
|
m_editor->textDocument()->syntaxHighlighter()->rehighlight();
|
||||||
}
|
}
|
||||||
|
|
||||||
using FormatRanges = QList<QTextLayout::FormatRange>;
|
using FormatRanges = QList<QTextLayout::FormatRange>;
|
||||||
@@ -214,7 +213,7 @@ void GenerigHighlighterTests::testPreeditText()
|
|||||||
block.layout()->setPreeditArea(7, "uaf");
|
block.layout()->setPreeditArea(7, "uaf");
|
||||||
c.endEditBlock();
|
c.endEditBlock();
|
||||||
|
|
||||||
m_editor->textDocument()->syntaxHighlighterRunner()->rehighlight();
|
m_editor->textDocument()->syntaxHighlighter()->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,7 +9,6 @@
|
|||||||
#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>
|
||||||
@@ -210,8 +209,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 (auto highlighterRunner = textEditor->textDocument()->syntaxHighlighterRunner();
|
if (auto highlighter = textEditor->textDocument()->syntaxHighlighter();
|
||||||
highlighterRunner && highlighterRunner->useGenericHighlighter()) {
|
highlighter && qobject_cast<SyntaxHighlighter*>(highlighter)) {
|
||||||
textEditor->editorWidget()->configureGenericHighlighter();
|
textEditor->editorWidget()->configureGenericHighlighter();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -5,7 +5,6 @@
|
|||||||
|
|
||||||
#include "syntaxhighlighter.h"
|
#include "syntaxhighlighter.h"
|
||||||
#include "texteditorsettings.h"
|
#include "texteditorsettings.h"
|
||||||
#include "syntaxhighlighterrunner.h"
|
|
||||||
|
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
|
|
||||||
@@ -75,7 +74,7 @@ const Ranges rangesForResult(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SemanticHighlighter::incrementalApplyExtraAdditionalFormats(
|
void SemanticHighlighter::incrementalApplyExtraAdditionalFormats(
|
||||||
SyntaxHighlighterRunner *highlighter,
|
SyntaxHighlighter *highlighter,
|
||||||
const QFuture<HighlightingResult> &future,
|
const QFuture<HighlightingResult> &future,
|
||||||
int from,
|
int from,
|
||||||
int to,
|
int to,
|
||||||
@@ -114,21 +113,17 @@ void SemanticHighlighter::incrementalApplyExtraAdditionalFormats(
|
|||||||
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) {
|
||||||
clearBlockNumberVector.append(currentBlock.blockNumber());
|
highlighter->clearExtraFormats(currentBlock);
|
||||||
currentBlock = currentBlock.next();
|
currentBlock = currentBlock.next();
|
||||||
}
|
}
|
||||||
blockNumberMap[block.blockNumber()] = ranges;
|
highlighter->setExtraFormats(block, std::move(ranges));
|
||||||
currentBlock = block.next();
|
currentBlock = block.next();
|
||||||
}
|
}
|
||||||
highlighter->clearExtraFormats(clearBlockNumberVector);
|
|
||||||
highlighter->setExtraFormats(blockNumberMap);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SemanticHighlighter::setExtraAdditionalFormats(SyntaxHighlighterRunner *highlighter,
|
void SemanticHighlighter::setExtraAdditionalFormats(SyntaxHighlighter *highlighter,
|
||||||
const QList<HighlightingResult> &results,
|
const QList<HighlightingResult> &results,
|
||||||
const QHash<int, QTextCharFormat> &kindToFormat)
|
const QHash<int, QTextCharFormat> &kindToFormat)
|
||||||
{
|
{
|
||||||
@@ -139,19 +134,19 @@ void SemanticHighlighter::setExtraAdditionalFormats(SyntaxHighlighterRunner *hig
|
|||||||
QTextDocument *doc = highlighter->document();
|
QTextDocument *doc = highlighter->document();
|
||||||
QTC_ASSERT(doc, return );
|
QTC_ASSERT(doc, return );
|
||||||
|
|
||||||
QMap<int, QList<QTextLayout::FormatRange>> blockNumberMap;
|
std::map<QTextBlock, QVector<QTextLayout::FormatRange>> formatRanges;
|
||||||
|
|
||||||
for (const HighlightingResult &result : results) {
|
for (auto result : results) {
|
||||||
const Ranges ranges = rangesForResult(result, doc, kindToFormat);
|
for (const Range &range : rangesForResult(result, doc, kindToFormat))
|
||||||
for (const Range &range : ranges)
|
formatRanges[range.block].append(range.formatRange);
|
||||||
blockNumberMap[range.block.blockNumber()].append(range.formatRange);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
highlighter->setExtraFormats(blockNumberMap);
|
for (auto &[block, ranges] : formatRanges)
|
||||||
|
highlighter->setExtraFormats(block, std::move(ranges));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SemanticHighlighter::clearExtraAdditionalFormatsUntilEnd(
|
void SemanticHighlighter::clearExtraAdditionalFormatsUntilEnd(
|
||||||
SyntaxHighlighterRunner *highlighter, const QFuture<HighlightingResult> &future)
|
SyntaxHighlighter *highlighter, const QFuture<HighlightingResult> &future)
|
||||||
{
|
{
|
||||||
const QTextDocument * const doc = highlighter->document();
|
const QTextDocument * const doc = highlighter->document();
|
||||||
QTextBlock firstBlockToClear = doc->begin();
|
QTextBlock firstBlockToClear = doc->begin();
|
||||||
@@ -168,7 +163,6 @@ void SemanticHighlighter::clearExtraAdditionalFormatsUntilEnd(
|
|||||||
|
|
||||||
QList<int> clearBlockNumberVector;
|
QList<int> clearBlockNumberVector;
|
||||||
for (QTextBlock b = firstBlockToClear; b.isValid(); b = b.next())
|
for (QTextBlock b = firstBlockToClear; b.isValid(); b = b.next())
|
||||||
clearBlockNumberVector.append(b.blockNumber());
|
highlighter->clearExtraFormats(b);
|
||||||
|
|
||||||
highlighter->clearExtraFormats(clearBlockNumberVector);
|
|
||||||
}
|
}
|
||||||
|
@@ -21,7 +21,6 @@ QT_END_NAMESPACE
|
|||||||
namespace TextEditor {
|
namespace TextEditor {
|
||||||
|
|
||||||
class SyntaxHighlighter;
|
class SyntaxHighlighter;
|
||||||
class SyntaxHighlighterRunner;
|
|
||||||
|
|
||||||
class TEXTEDITOR_EXPORT HighlightingResult
|
class TEXTEDITOR_EXPORT HighlightingResult
|
||||||
{
|
{
|
||||||
@@ -74,7 +73,7 @@ using Splitter = std::function<const QList<std::pair<HighlightingResult, QTextBl
|
|||||||
// 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
|
void TEXTEDITOR_EXPORT
|
||||||
incrementalApplyExtraAdditionalFormats(SyntaxHighlighterRunner *highlighter,
|
incrementalApplyExtraAdditionalFormats(SyntaxHighlighter *highlighter,
|
||||||
const QFuture<HighlightingResult> &future,
|
const QFuture<HighlightingResult> &future,
|
||||||
int from,
|
int from,
|
||||||
int to,
|
int to,
|
||||||
@@ -85,7 +84,7 @@ incrementalApplyExtraAdditionalFormats(SyntaxHighlighterRunner *highlighter,
|
|||||||
// 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(SyntaxHighlighterRunner *highlighter,
|
void TEXTEDITOR_EXPORT setExtraAdditionalFormats(SyntaxHighlighter *highlighter,
|
||||||
const HighlightingResults &results,
|
const HighlightingResults &results,
|
||||||
const QHash<int, QTextCharFormat> &kindToFormat);
|
const QHash<int, QTextCharFormat> &kindToFormat);
|
||||||
|
|
||||||
@@ -93,7 +92,7 @@ void TEXTEDITOR_EXPORT setExtraAdditionalFormats(SyntaxHighlighterRunner *highli
|
|||||||
// 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(
|
||||||
SyntaxHighlighterRunner *highlighter, const QFuture<HighlightingResult> &future);
|
SyntaxHighlighter *highlighter, const QFuture<HighlightingResult> &future);
|
||||||
|
|
||||||
} // namespace SemanticHighlighter
|
} // namespace SemanticHighlighter
|
||||||
} // namespace TextEditor
|
} // namespace TextEditor
|
||||||
|
@@ -25,8 +25,6 @@ enum HighlighterTypeProperty
|
|||||||
|
|
||||||
class SyntaxHighlighterPrivate
|
class SyntaxHighlighterPrivate
|
||||||
{
|
{
|
||||||
SyntaxHighlighter *q_ptr = nullptr;
|
|
||||||
Q_DECLARE_PUBLIC(SyntaxHighlighter)
|
|
||||||
public:
|
public:
|
||||||
SyntaxHighlighterPrivate() = default;
|
SyntaxHighlighterPrivate() = default;
|
||||||
|
|
||||||
@@ -37,8 +35,10 @@ public:
|
|||||||
|
|
||||||
QPointer<QTextDocument> doc;
|
QPointer<QTextDocument> doc;
|
||||||
|
|
||||||
|
void updateFormats(int from, int charsRemoved, int charsAdded);
|
||||||
void reformatBlocks(int from, int charsRemoved, int charsAdded);
|
void reformatBlocks(int from, int charsRemoved, int charsAdded);
|
||||||
void reformatBlock(const QTextBlock &block, int from, int charsRemoved, int charsAdded);
|
void reformatBlocks();
|
||||||
|
void reformatBlock(const QTextBlock &block);
|
||||||
|
|
||||||
inline void rehighlight(QTextCursor &cursor, QTextCursor::MoveOperation operation) {
|
inline void rehighlight(QTextCursor &cursor, QTextCursor::MoveOperation operation) {
|
||||||
inReformatBlocks = true;
|
inReformatBlocks = true;
|
||||||
@@ -48,7 +48,7 @@ public:
|
|||||||
inReformatBlocks = false;
|
inReformatBlocks = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void applyFormatChanges(int from, int charsRemoved, int charsAdded);
|
void applyFormatChanges();
|
||||||
void updateFormats(const FontSettings &fontSettings);
|
void updateFormats(const FontSettings &fontSettings);
|
||||||
|
|
||||||
FontSettings fontSettings;
|
FontSettings fontSettings;
|
||||||
@@ -61,6 +61,11 @@ public:
|
|||||||
QList<std::pair<int,TextStyle>> formatCategories;
|
QList<std::pair<int,TextStyle>> formatCategories;
|
||||||
QTextCharFormat whitespaceFormat;
|
QTextCharFormat whitespaceFormat;
|
||||||
QString mimeType;
|
QString mimeType;
|
||||||
|
bool syntaxInfoUpToDate = false;
|
||||||
|
int highlightStartBlock = 0;
|
||||||
|
int highlightEndBlock = 0;
|
||||||
|
QSet<int> forceRehighlightBlocks;
|
||||||
|
SyntaxHighlighter *q;
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool adjustRange(QTextLayout::FormatRange &range, int from, int charsDelta)
|
static bool adjustRange(QTextLayout::FormatRange &range, int from, int charsDelta)
|
||||||
@@ -77,31 +82,30 @@ static bool adjustRange(QTextLayout::FormatRange &range, int from, int charsDelt
|
|||||||
|
|
||||||
void SyntaxHighlighter::delayedRehighlight()
|
void SyntaxHighlighter::delayedRehighlight()
|
||||||
{
|
{
|
||||||
Q_D(SyntaxHighlighter);
|
|
||||||
if (!d->rehighlightPending)
|
if (!d->rehighlightPending)
|
||||||
return;
|
return;
|
||||||
d->rehighlightPending = false;
|
d->rehighlightPending = false;
|
||||||
|
|
||||||
if (document()->isEmpty())
|
|
||||||
return;
|
|
||||||
|
|
||||||
rehighlight();
|
rehighlight();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SyntaxHighlighter::continueRehighlight()
|
||||||
|
{
|
||||||
|
d->reformatBlocks();
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef WITH_TESTS
|
#ifdef WITH_TESTS
|
||||||
SyntaxHighlighter::SyntaxHighlighter(QTextDocument *parent, const FontSettings &fontsettings)
|
SyntaxHighlighter::SyntaxHighlighter(QTextDocument *parent, const FontSettings &fontsettings)
|
||||||
: QObject(parent), d_ptr(new SyntaxHighlighterPrivate(fontsettings))
|
: QObject(parent), d(new SyntaxHighlighterPrivate(fontsettings))
|
||||||
{
|
{
|
||||||
d_ptr->q_ptr = this;
|
d->q = this;
|
||||||
if (parent)
|
if (parent)
|
||||||
setDocument(parent);
|
setDocument(parent);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void SyntaxHighlighterPrivate::applyFormatChanges(int from, int charsRemoved, int charsAdded)
|
void SyntaxHighlighterPrivate::applyFormatChanges()
|
||||||
{
|
{
|
||||||
bool formatsChanged = false;
|
|
||||||
|
|
||||||
QTextLayout *layout = currentBlock.layout();
|
QTextLayout *layout = currentBlock.layout();
|
||||||
|
|
||||||
QList<QTextLayout::FormatRange> ranges;
|
QList<QTextLayout::FormatRange> ranges;
|
||||||
@@ -111,12 +115,6 @@ void SyntaxHighlighterPrivate::applyFormatChanges(int from, int charsRemoved, in
|
|||||||
return range.format.property(SyntaxHighlight).toBool();
|
return range.format.property(SyntaxHighlight).toBool();
|
||||||
});
|
});
|
||||||
|
|
||||||
if (currentBlock.contains(from)) {
|
|
||||||
const int charsDelta = charsAdded - charsRemoved;
|
|
||||||
for (QTextLayout::FormatRange &range : ranges)
|
|
||||||
formatsChanged |= adjustRange(range, from - currentBlock.position(), charsDelta);
|
|
||||||
}
|
|
||||||
|
|
||||||
QTextCharFormat emptyFormat;
|
QTextCharFormat emptyFormat;
|
||||||
|
|
||||||
QTextLayout::FormatRange r;
|
QTextLayout::FormatRange r;
|
||||||
@@ -157,7 +155,7 @@ void SyntaxHighlighterPrivate::applyFormatChanges(int from, int charsRemoved, in
|
|||||||
newRanges << r;
|
newRanges << r;
|
||||||
}
|
}
|
||||||
|
|
||||||
formatsChanged = formatsChanged || (newRanges.size() != oldRanges.size());
|
bool formatsChanged = (newRanges.size() != oldRanges.size());
|
||||||
|
|
||||||
for (int i = 0; !formatsChanged && i < newRanges.size(); ++i) {
|
for (int i = 0; !formatsChanged && i < newRanges.size(); ++i) {
|
||||||
const QTextLayout::FormatRange &o = oldRanges.at(i);
|
const QTextLayout::FormatRange &o = oldRanges.at(i);
|
||||||
@@ -174,85 +172,103 @@ void SyntaxHighlighterPrivate::applyFormatChanges(int from, int charsRemoved, in
|
|||||||
|
|
||||||
void SyntaxHighlighter::reformatBlocks(int from, int charsRemoved, int charsAdded)
|
void SyntaxHighlighter::reformatBlocks(int from, int charsRemoved, int charsAdded)
|
||||||
{
|
{
|
||||||
Q_D(SyntaxHighlighter);
|
|
||||||
if (!d->inReformatBlocks)
|
if (!d->inReformatBlocks)
|
||||||
d->reformatBlocks(from, charsRemoved, charsAdded);
|
d->reformatBlocks(from, charsRemoved, charsAdded);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SyntaxHighlighterPrivate::updateFormats(int from, int charsRemoved, int charsAdded)
|
||||||
|
{
|
||||||
|
bool formatsChanged = false;
|
||||||
|
|
||||||
|
const QTextBlock block = doc->findBlock(from);
|
||||||
|
QTextLayout *layout = block.layout();
|
||||||
|
|
||||||
|
QList<QTextLayout::FormatRange> ranges = layout->formats();
|
||||||
|
|
||||||
|
const int charsDelta = charsAdded - charsRemoved;
|
||||||
|
for (QTextLayout::FormatRange &range : ranges)
|
||||||
|
formatsChanged |= adjustRange(range, from - block.position(), charsDelta);
|
||||||
|
|
||||||
|
if (formatsChanged) {
|
||||||
|
layout->setFormats(ranges);
|
||||||
|
doc->markContentsDirty(block.position(), block.length());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void SyntaxHighlighterPrivate::reformatBlocks(int from, int charsRemoved, int charsAdded)
|
void SyntaxHighlighterPrivate::reformatBlocks(int from, int charsRemoved, int charsAdded)
|
||||||
{
|
{
|
||||||
Q_Q(SyntaxHighlighter);
|
updateFormats(from, charsRemoved, charsAdded);
|
||||||
foldValidator.reset();
|
|
||||||
|
|
||||||
rehighlightPending = false;
|
|
||||||
|
|
||||||
QTextBlock block = doc->findBlock(from);
|
QTextBlock block = doc->findBlock(from);
|
||||||
|
if (block.isValid() && block.blockNumber() < highlightStartBlock)
|
||||||
|
highlightStartBlock = block.blockNumber();
|
||||||
|
block = doc->findBlock(from + charsAdded + (charsRemoved > 0 ? 1 : 0));
|
||||||
if (!block.isValid())
|
if (!block.isValid())
|
||||||
return;
|
highlightEndBlock = doc->blockCount() - 1;
|
||||||
|
else if (block.blockNumber() > highlightEndBlock)
|
||||||
|
highlightEndBlock = block.blockNumber();
|
||||||
|
|
||||||
int endPosition;
|
reformatBlocks();
|
||||||
QTextBlock lastBlock = doc->findBlock(from + charsAdded + (charsRemoved > 0 ? 1 : 0));
|
}
|
||||||
if (lastBlock.isValid())
|
|
||||||
endPosition = lastBlock.position() + lastBlock.length();
|
void SyntaxHighlighterPrivate::reformatBlocks()
|
||||||
else
|
{
|
||||||
endPosition = doc->lastBlock().position() + doc->lastBlock().length();
|
QElapsedTimer et;
|
||||||
|
et.start();
|
||||||
|
|
||||||
|
syntaxInfoUpToDate = false;
|
||||||
|
rehighlightPending = false;
|
||||||
|
|
||||||
|
foldValidator.reset();
|
||||||
|
|
||||||
bool forceHighlightOfNextBlock = false;
|
bool forceHighlightOfNextBlock = false;
|
||||||
|
QTextBlock block = doc->findBlockByNumber(highlightStartBlock);
|
||||||
|
QTC_ASSERT(block.isValid(), block = doc->firstBlock());
|
||||||
|
QTextBlock endBlock = doc->findBlockByNumber(highlightEndBlock);
|
||||||
|
QTC_ASSERT(endBlock.isValid(), endBlock = doc->lastBlock());
|
||||||
|
|
||||||
QList<SyntaxHighlighter::Result> vecRes;
|
while (block.isValid()) {
|
||||||
|
if (et.elapsed() > 20)
|
||||||
SyntaxHighlighter::Result resStart;
|
break;
|
||||||
resStart.m_state = SyntaxHighlighter::State::Start;
|
|
||||||
vecRes << resStart;
|
|
||||||
|
|
||||||
while (block.isValid() && (block.position() < endPosition || forceHighlightOfNextBlock)) {
|
|
||||||
if (QThread::currentThread()->isInterruptionRequested() || q->isInterrupted()) {
|
|
||||||
inReformatBlocks = false;
|
|
||||||
emit q->resultsReady({});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const int stateBeforeHighlight = block.userState();
|
const int stateBeforeHighlight = block.userState();
|
||||||
|
|
||||||
reformatBlock(block, from, charsRemoved, charsAdded);
|
if (forceHighlightOfNextBlock || forceRehighlightBlocks.contains(block.blockNumber())
|
||||||
|
|| block.blockNumber() <= highlightEndBlock) {
|
||||||
forceHighlightOfNextBlock = (block.userState() != stateBeforeHighlight);
|
reformatBlock(block);
|
||||||
|
forceRehighlightBlocks.remove(block.blockNumber());
|
||||||
SyntaxHighlighter::Result res;
|
forceHighlightOfNextBlock = (block.userState() != stateBeforeHighlight);
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
highlightStartBlock = block.blockNumber();
|
||||||
|
|
||||||
|
if (block == endBlock && !forceHighlightOfNextBlock)
|
||||||
|
break;
|
||||||
block = block.next();
|
block = block.next();
|
||||||
}
|
}
|
||||||
|
|
||||||
formatChanges.clear();
|
formatChanges.clear();
|
||||||
|
|
||||||
foldValidator.finalize();
|
foldValidator.finalize();
|
||||||
SyntaxHighlighter::Result res;
|
|
||||||
res.m_state = SyntaxHighlighter::State::Done;
|
if (endBlock.isValid() && block.isValid() && block.blockNumber() < endBlock.blockNumber()) {
|
||||||
vecRes << res;
|
QMetaObject::invokeMethod(q, &SyntaxHighlighter::continueRehighlight, Qt::QueuedConnection);
|
||||||
emit q->resultsReady(vecRes);
|
if (forceHighlightOfNextBlock)
|
||||||
|
forceRehighlightBlocks << block.blockNumber();
|
||||||
|
} else {
|
||||||
|
highlightEndBlock = 0;
|
||||||
|
syntaxInfoUpToDate = true;
|
||||||
|
emit q->finished();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SyntaxHighlighterPrivate::reformatBlock(const QTextBlock &block, int from, int charsRemoved, int charsAdded)
|
void SyntaxHighlighterPrivate::reformatBlock(const QTextBlock &block)
|
||||||
{
|
{
|
||||||
Q_Q(SyntaxHighlighter);
|
QTC_ASSERT(!currentBlock.isValid(), return);
|
||||||
|
|
||||||
Q_ASSERT_X(!currentBlock.isValid(), "SyntaxHighlighter::reformatBlock()", "reFormatBlock() called recursively");
|
|
||||||
|
|
||||||
currentBlock = block;
|
currentBlock = block;
|
||||||
|
|
||||||
formatChanges.fill(QTextCharFormat(), block.length() - 1);
|
formatChanges.fill(QTextCharFormat(), block.length() - 1);
|
||||||
q->highlightBlock(block.text());
|
q->highlightBlock(block.text());
|
||||||
applyFormatChanges(from, charsRemoved, charsAdded);
|
applyFormatChanges();
|
||||||
|
|
||||||
foldValidator.process(currentBlock);
|
foldValidator.process(currentBlock);
|
||||||
|
|
||||||
@@ -293,9 +309,9 @@ void SyntaxHighlighterPrivate::reformatBlock(const QTextBlock &block, int from,
|
|||||||
Constructs a SyntaxHighlighter with the given \a parent.
|
Constructs a SyntaxHighlighter with the given \a parent.
|
||||||
*/
|
*/
|
||||||
SyntaxHighlighter::SyntaxHighlighter(QObject *parent)
|
SyntaxHighlighter::SyntaxHighlighter(QObject *parent)
|
||||||
: QObject(parent), d_ptr(new SyntaxHighlighterPrivate)
|
: QObject(parent), d(new SyntaxHighlighterPrivate)
|
||||||
{
|
{
|
||||||
d_ptr->q_ptr = this;
|
d->q = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -304,9 +320,9 @@ SyntaxHighlighter::SyntaxHighlighter(QObject *parent)
|
|||||||
SyntaxHighlighter.
|
SyntaxHighlighter.
|
||||||
*/
|
*/
|
||||||
SyntaxHighlighter::SyntaxHighlighter(QTextDocument *parent)
|
SyntaxHighlighter::SyntaxHighlighter(QTextDocument *parent)
|
||||||
: QObject(parent), d_ptr(new SyntaxHighlighterPrivate)
|
: QObject(parent), d(new SyntaxHighlighterPrivate)
|
||||||
{
|
{
|
||||||
d_ptr->q_ptr = this;
|
d->q = this;
|
||||||
if (parent)
|
if (parent)
|
||||||
setDocument(parent);
|
setDocument(parent);
|
||||||
}
|
}
|
||||||
@@ -317,9 +333,9 @@ SyntaxHighlighter::SyntaxHighlighter(QTextDocument *parent)
|
|||||||
the SyntaxHighlighter.
|
the SyntaxHighlighter.
|
||||||
*/
|
*/
|
||||||
SyntaxHighlighter::SyntaxHighlighter(QTextEdit *parent)
|
SyntaxHighlighter::SyntaxHighlighter(QTextEdit *parent)
|
||||||
: QObject(parent), d_ptr(new SyntaxHighlighterPrivate)
|
: QObject(parent), d(new SyntaxHighlighterPrivate)
|
||||||
{
|
{
|
||||||
d_ptr->q_ptr = this;
|
d->q = this;
|
||||||
if (parent)
|
if (parent)
|
||||||
setDocument(parent->document());
|
setDocument(parent->document());
|
||||||
}
|
}
|
||||||
@@ -338,7 +354,6 @@ SyntaxHighlighter::~SyntaxHighlighter()
|
|||||||
*/
|
*/
|
||||||
void SyntaxHighlighter::setDocument(QTextDocument *doc)
|
void SyntaxHighlighter::setDocument(QTextDocument *doc)
|
||||||
{
|
{
|
||||||
Q_D(SyntaxHighlighter);
|
|
||||||
if (d->doc == doc)
|
if (d->doc == doc)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -356,10 +371,7 @@ void SyntaxHighlighter::setDocument(QTextDocument *doc)
|
|||||||
documentChanged(oldDoc, d->doc);
|
documentChanged(oldDoc, d->doc);
|
||||||
if (d->doc) {
|
if (d->doc) {
|
||||||
connect(d->doc, &QTextDocument::contentsChange, this, &SyntaxHighlighter::reformatBlocks);
|
connect(d->doc, &QTextDocument::contentsChange, this, &SyntaxHighlighter::reformatBlocks);
|
||||||
d->rehighlightPending = true;
|
scheduleRehighlight();
|
||||||
QMetaObject::invokeMethod(this,
|
|
||||||
&SyntaxHighlighter::delayedRehighlight,
|
|
||||||
Qt::QueuedConnection);
|
|
||||||
d->foldValidator.setup(qobject_cast<TextDocumentLayout *>(doc->documentLayout()));
|
d->foldValidator.setup(qobject_cast<TextDocumentLayout *>(doc->documentLayout()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -370,19 +382,16 @@ void SyntaxHighlighter::setDocument(QTextDocument *doc)
|
|||||||
*/
|
*/
|
||||||
QTextDocument *SyntaxHighlighter::document() const
|
QTextDocument *SyntaxHighlighter::document() const
|
||||||
{
|
{
|
||||||
Q_D(const SyntaxHighlighter);
|
|
||||||
return d->doc;
|
return d->doc;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SyntaxHighlighter::setMimeType(const QString &mimeType)
|
void SyntaxHighlighter::setMimeType(const QString &mimeType)
|
||||||
{
|
{
|
||||||
Q_D(SyntaxHighlighter);
|
|
||||||
d->mimeType = mimeType;
|
d->mimeType = mimeType;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString SyntaxHighlighter::mimeType() const
|
QString SyntaxHighlighter::mimeType() const
|
||||||
{
|
{
|
||||||
Q_D(const SyntaxHighlighter);
|
|
||||||
return d->mimeType;
|
return d->mimeType;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -395,7 +404,6 @@ QString SyntaxHighlighter::mimeType() const
|
|||||||
*/
|
*/
|
||||||
void SyntaxHighlighter::rehighlight()
|
void SyntaxHighlighter::rehighlight()
|
||||||
{
|
{
|
||||||
Q_D(SyntaxHighlighter);
|
|
||||||
if (!d->doc)
|
if (!d->doc)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -403,6 +411,17 @@ void SyntaxHighlighter::rehighlight()
|
|||||||
d->rehighlight(cursor, QTextCursor::End);
|
d->rehighlight(cursor, QTextCursor::End);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SyntaxHighlighter::scheduleRehighlight()
|
||||||
|
{
|
||||||
|
if (d->rehighlightPending)
|
||||||
|
return;
|
||||||
|
d->rehighlightPending = true;
|
||||||
|
d->syntaxInfoUpToDate = false;
|
||||||
|
QMetaObject::invokeMethod(this,
|
||||||
|
&SyntaxHighlighter::delayedRehighlight,
|
||||||
|
Qt::QueuedConnection);
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\since 4.6
|
\since 4.6
|
||||||
|
|
||||||
@@ -412,7 +431,6 @@ void SyntaxHighlighter::rehighlight()
|
|||||||
*/
|
*/
|
||||||
void SyntaxHighlighter::rehighlightBlock(const QTextBlock &block)
|
void SyntaxHighlighter::rehighlightBlock(const QTextBlock &block)
|
||||||
{
|
{
|
||||||
Q_D(SyntaxHighlighter);
|
|
||||||
if (!d->doc || !block.isValid() || block.document() != d->doc)
|
if (!d->doc || !block.isValid() || block.document() != d->doc)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -486,7 +504,6 @@ void SyntaxHighlighter::rehighlightBlock(const QTextBlock &block)
|
|||||||
*/
|
*/
|
||||||
void SyntaxHighlighter::setFormat(int start, int count, const QTextCharFormat &format)
|
void SyntaxHighlighter::setFormat(int start, int count, const QTextCharFormat &format)
|
||||||
{
|
{
|
||||||
Q_D(SyntaxHighlighter);
|
|
||||||
if (start < 0 || start >= d->formatChanges.count())
|
if (start < 0 || start >= d->formatChanges.count())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -533,7 +550,6 @@ void SyntaxHighlighter::setFormat(int start, int count, const QFont &font)
|
|||||||
|
|
||||||
void SyntaxHighlighter::formatSpaces(const QString &text, int start, int count)
|
void SyntaxHighlighter::formatSpaces(const QString &text, int start, int count)
|
||||||
{
|
{
|
||||||
Q_D(const SyntaxHighlighter);
|
|
||||||
int offset = start;
|
int offset = start;
|
||||||
const int end = std::min(start + count, int(text.length()));
|
const int end = std::min(start + count, int(text.length()));
|
||||||
while (offset < end) {
|
while (offset < end) {
|
||||||
@@ -585,10 +601,7 @@ void SyntaxHighlighter::setFormatWithSpaces(const QString &text, int start, int
|
|||||||
*/
|
*/
|
||||||
QTextCharFormat SyntaxHighlighter::format(int pos) const
|
QTextCharFormat SyntaxHighlighter::format(int pos) const
|
||||||
{
|
{
|
||||||
Q_D(const SyntaxHighlighter);
|
return d->formatChanges.value(pos);
|
||||||
if (pos < 0 || pos >= d->formatChanges.count())
|
|
||||||
return QTextCharFormat();
|
|
||||||
return d->formatChanges.at(pos);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -600,7 +613,6 @@ QTextCharFormat SyntaxHighlighter::format(int pos) const
|
|||||||
*/
|
*/
|
||||||
int SyntaxHighlighter::previousBlockState() const
|
int SyntaxHighlighter::previousBlockState() const
|
||||||
{
|
{
|
||||||
Q_D(const SyntaxHighlighter);
|
|
||||||
if (!d->currentBlock.isValid())
|
if (!d->currentBlock.isValid())
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@@ -617,7 +629,6 @@ int SyntaxHighlighter::previousBlockState() const
|
|||||||
*/
|
*/
|
||||||
int SyntaxHighlighter::currentBlockState() const
|
int SyntaxHighlighter::currentBlockState() const
|
||||||
{
|
{
|
||||||
Q_D(const SyntaxHighlighter);
|
|
||||||
if (!d->currentBlock.isValid())
|
if (!d->currentBlock.isValid())
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@@ -631,7 +642,6 @@ int SyntaxHighlighter::currentBlockState() const
|
|||||||
*/
|
*/
|
||||||
void SyntaxHighlighter::setCurrentBlockState(int newState)
|
void SyntaxHighlighter::setCurrentBlockState(int newState)
|
||||||
{
|
{
|
||||||
Q_D(SyntaxHighlighter);
|
|
||||||
if (!d->currentBlock.isValid())
|
if (!d->currentBlock.isValid())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -674,7 +684,6 @@ void SyntaxHighlighter::setCurrentBlockState(int newState)
|
|||||||
*/
|
*/
|
||||||
void SyntaxHighlighter::setCurrentBlockUserData(QTextBlockUserData *data)
|
void SyntaxHighlighter::setCurrentBlockUserData(QTextBlockUserData *data)
|
||||||
{
|
{
|
||||||
Q_D(SyntaxHighlighter);
|
|
||||||
if (!d->currentBlock.isValid())
|
if (!d->currentBlock.isValid())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -689,7 +698,6 @@ void SyntaxHighlighter::setCurrentBlockUserData(QTextBlockUserData *data)
|
|||||||
*/
|
*/
|
||||||
QTextBlockUserData *SyntaxHighlighter::currentBlockUserData() const
|
QTextBlockUserData *SyntaxHighlighter::currentBlockUserData() const
|
||||||
{
|
{
|
||||||
Q_D(const SyntaxHighlighter);
|
|
||||||
if (!d->currentBlock.isValid())
|
if (!d->currentBlock.isValid())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
@@ -703,7 +711,6 @@ QTextBlockUserData *SyntaxHighlighter::currentBlockUserData() const
|
|||||||
*/
|
*/
|
||||||
QTextBlock SyntaxHighlighter::currentBlock() const
|
QTextBlock SyntaxHighlighter::currentBlock() const
|
||||||
{
|
{
|
||||||
Q_D(const SyntaxHighlighter);
|
|
||||||
return d->currentBlock;
|
return d->currentBlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -715,8 +722,6 @@ static bool byStartOfRange(const QTextLayout::FormatRange &range, const QTextLay
|
|||||||
void SyntaxHighlighter::setExtraFormats(const QTextBlock &block,
|
void SyntaxHighlighter::setExtraFormats(const QTextBlock &block,
|
||||||
const QList<QTextLayout::FormatRange> &formats)
|
const QList<QTextLayout::FormatRange> &formats)
|
||||||
{
|
{
|
||||||
Q_D(SyntaxHighlighter);
|
|
||||||
|
|
||||||
QList<QTextLayout::FormatRange> formatsCopy = formats;
|
QList<QTextLayout::FormatRange> formatsCopy = formats;
|
||||||
|
|
||||||
const int blockLength = block.length();
|
const int blockLength = block.length();
|
||||||
@@ -766,20 +771,17 @@ void SyntaxHighlighter::setExtraFormats(const QTextBlock &block,
|
|||||||
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);
|
|
||||||
res.m_state = SyntaxHighlighter::State::Extras;
|
|
||||||
emit resultsReady({std::move(res)});
|
|
||||||
|
|
||||||
document()->markContentsDirty(block.position(), blockLength - 1);
|
document()->markContentsDirty(block.position(), blockLength - 1);
|
||||||
d->inReformatBlocks = wasInReformatBlocks;
|
d->inReformatBlocks = wasInReformatBlocks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SyntaxHighlighter::syntaxHighlighterUpToDate() const
|
||||||
|
{
|
||||||
|
return d->syntaxInfoUpToDate;
|
||||||
|
}
|
||||||
|
|
||||||
void SyntaxHighlighter::clearExtraFormats(const QTextBlock &block)
|
void SyntaxHighlighter::clearExtraFormats(const QTextBlock &block)
|
||||||
{
|
{
|
||||||
Q_D(SyntaxHighlighter);
|
|
||||||
|
|
||||||
const int blockLength = block.length();
|
const int blockLength = block.length();
|
||||||
if (block.layout() == nullptr || blockLength == 0)
|
if (block.layout() == nullptr || blockLength == 0)
|
||||||
return;
|
return;
|
||||||
@@ -793,12 +795,6 @@ void SyntaxHighlighter::clearExtraFormats(const QTextBlock &block)
|
|||||||
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);
|
|
||||||
res.m_state = SyntaxHighlighter::State::Extras;
|
|
||||||
emit resultsReady({std::move(res)});
|
|
||||||
|
|
||||||
document()->markContentsDirty(block.position(), blockLength - 1);
|
document()->markContentsDirty(block.position(), blockLength - 1);
|
||||||
d->inReformatBlocks = wasInReformatBlocks;
|
d->inReformatBlocks = wasInReformatBlocks;
|
||||||
}
|
}
|
||||||
@@ -848,13 +844,11 @@ QList<QColor> SyntaxHighlighter::generateColors(int n, const QColor &background)
|
|||||||
|
|
||||||
void SyntaxHighlighter::setFontSettings(const FontSettings &fontSettings)
|
void SyntaxHighlighter::setFontSettings(const FontSettings &fontSettings)
|
||||||
{
|
{
|
||||||
Q_D(SyntaxHighlighter);
|
|
||||||
d->updateFormats(fontSettings);
|
d->updateFormats(fontSettings);
|
||||||
}
|
}
|
||||||
|
|
||||||
FontSettings SyntaxHighlighter::fontSettings() const
|
FontSettings SyntaxHighlighter::fontSettings() const
|
||||||
{
|
{
|
||||||
Q_D(const SyntaxHighlighter);
|
|
||||||
return d->fontSettings;
|
return d->fontSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -897,7 +891,6 @@ void SyntaxHighlighter::setTextFormatCategories(int count,
|
|||||||
*/
|
*/
|
||||||
void SyntaxHighlighter::setTextFormatCategories(const QList<std::pair<int, TextStyle>> &categories)
|
void SyntaxHighlighter::setTextFormatCategories(const QList<std::pair<int, TextStyle>> &categories)
|
||||||
{
|
{
|
||||||
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 = QList<QTextCharFormat>(maxCategory + 1);
|
d->formats = QList<QTextCharFormat>(maxCategory + 1);
|
||||||
@@ -906,7 +899,6 @@ void SyntaxHighlighter::setTextFormatCategories(const QList<std::pair<int, TextS
|
|||||||
|
|
||||||
QTextCharFormat SyntaxHighlighter::formatForCategory(int category) const
|
QTextCharFormat SyntaxHighlighter::formatForCategory(int category) const
|
||||||
{
|
{
|
||||||
Q_D(const SyntaxHighlighter);
|
|
||||||
QTC_ASSERT(d->formats.size() > category, return QTextCharFormat());
|
QTC_ASSERT(d->formats.size() > category, return QTextCharFormat());
|
||||||
|
|
||||||
return d->formats.at(category);
|
return d->formats.at(category);
|
||||||
@@ -914,7 +906,6 @@ QTextCharFormat SyntaxHighlighter::formatForCategory(int category) const
|
|||||||
|
|
||||||
QTextCharFormat SyntaxHighlighter::whitespacified(const QTextCharFormat &fmt)
|
QTextCharFormat SyntaxHighlighter::whitespacified(const QTextCharFormat &fmt)
|
||||||
{
|
{
|
||||||
Q_D(SyntaxHighlighter);
|
|
||||||
QTextCharFormat format = d->whitespaceFormat;
|
QTextCharFormat format = d->whitespaceFormat;
|
||||||
format.setBackground(fmt.background());
|
format.setBackground(fmt.background());
|
||||||
return format;
|
return format;
|
||||||
|
@@ -34,7 +34,6 @@ class SyntaxHighlighterPrivate;
|
|||||||
class TEXTEDITOR_EXPORT SyntaxHighlighter : public QObject
|
class TEXTEDITOR_EXPORT SyntaxHighlighter : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_DECLARE_PRIVATE(SyntaxHighlighter)
|
|
||||||
public:
|
public:
|
||||||
SyntaxHighlighter(QObject *parent = nullptr);
|
SyntaxHighlighter(QObject *parent = nullptr);
|
||||||
SyntaxHighlighter(QTextDocument *parent);
|
SyntaxHighlighter(QTextDocument *parent);
|
||||||
@@ -53,79 +52,16 @@ public:
|
|||||||
virtual void setFontSettings(const TextEditor::FontSettings &fontSettings);
|
virtual void setFontSettings(const TextEditor::FontSettings &fontSettings);
|
||||||
TextEditor::FontSettings fontSettings() const;
|
TextEditor::FontSettings fontSettings() const;
|
||||||
|
|
||||||
enum State {
|
|
||||||
Start,
|
|
||||||
InProgress,
|
|
||||||
Done,
|
|
||||||
Extras
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Result
|
|
||||||
{
|
|
||||||
void fillByBlock(const QTextBlock &block)
|
|
||||||
{
|
|
||||||
m_blockNumber = block.blockNumber();
|
|
||||||
m_userState = block.userState();
|
|
||||||
|
|
||||||
TextBlockUserData *userDate = TextDocumentLayout::textUserData(block);
|
|
||||||
if (!userDate)
|
|
||||||
return;
|
|
||||||
|
|
||||||
m_hasBlockUserData = true;
|
|
||||||
m_foldingIndent = userDate->foldingIndent();
|
|
||||||
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)
|
|
||||||
return;
|
|
||||||
|
|
||||||
TextBlockUserData *data = TextDocumentLayout::userData(block);
|
|
||||||
data->setExpectedRawStringSuffix(m_expectedRawStringSuffix);
|
|
||||||
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_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;
|
|
||||||
|
|
||||||
State m_state = InProgress;
|
|
||||||
};
|
|
||||||
|
|
||||||
void setInterrupted(bool interrupted) { m_interrupted = interrupted; }
|
|
||||||
bool isInterrupted() { return m_interrupted; }
|
|
||||||
void setExtraFormats(const QTextBlock &block, const QList<QTextLayout::FormatRange> &formats);
|
void setExtraFormats(const QTextBlock &block, const QList<QTextLayout::FormatRange> &formats);
|
||||||
virtual void setLanguageFeaturesFlags(unsigned int /*flags*/) {}; // needed for CppHighlighting
|
virtual void setLanguageFeaturesFlags(unsigned int /*flags*/) {}; // needed for CppHighlighting
|
||||||
virtual void setEnabled(bool /*enabled*/) {}; // needed for DiffAndLogHighlighter
|
virtual void setEnabled(bool /*enabled*/) {}; // needed for DiffAndLogHighlighter
|
||||||
virtual void setDefinitionName(const QString & /*definitionName*/) {} // needed for Highlighter
|
virtual void setDefinitionName(const QString & /*definitionName*/) {} // needed for Highlighter
|
||||||
|
|
||||||
|
bool syntaxHighlighterUpToDate() const;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
virtual void rehighlight();
|
virtual void rehighlight();
|
||||||
|
virtual void scheduleRehighlight();
|
||||||
void rehighlightBlock(const QTextBlock &block);
|
void rehighlightBlock(const QTextBlock &block);
|
||||||
void clearExtraFormats(const QTextBlock &block);
|
void clearExtraFormats(const QTextBlock &block);
|
||||||
void reformatBlocks(int from, int charsRemoved, int charsAdded);
|
void reformatBlocks(int from, int charsRemoved, int charsAdded);
|
||||||
@@ -160,18 +96,18 @@ protected:
|
|||||||
|
|
||||||
QTextBlock currentBlock() const;
|
QTextBlock currentBlock() const;
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual void documentChanged(QTextDocument * /*oldDoc*/, QTextDocument * /*newDoc*/) {};
|
virtual void documentChanged(QTextDocument * /*oldDoc*/, QTextDocument * /*newDoc*/) {};
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void resultsReady(const QList<Result> &result);
|
void finished();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void setTextFormatCategories(const QList<std::pair<int, TextStyle>> &categories);
|
void setTextFormatCategories(const QList<std::pair<int, TextStyle>> &categories);
|
||||||
void delayedRehighlight();
|
void delayedRehighlight();
|
||||||
|
void continueRehighlight();
|
||||||
|
|
||||||
QScopedPointer<SyntaxHighlighterPrivate> d_ptr;
|
friend class SyntaxHighlighterPrivate;
|
||||||
std::atomic<bool> m_interrupted = false;
|
std::unique_ptr<SyntaxHighlighterPrivate> d;
|
||||||
|
|
||||||
#ifdef WITH_TESTS
|
#ifdef WITH_TESTS
|
||||||
friend class tst_highlighter;
|
friend class tst_highlighter;
|
||||||
|
@@ -1,385 +0,0 @@
|
|||||||
// 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 "fontsettings.h"
|
|
||||||
#include "textdocumentlayout.h"
|
|
||||||
#include "texteditorsettings.h"
|
|
||||||
#include "highlighter.h"
|
|
||||||
|
|
||||||
#include <utils/algorithm.h>
|
|
||||||
#include <utils/textutils.h>
|
|
||||||
|
|
||||||
#include <QMetaObject>
|
|
||||||
#include <QTextCursor>
|
|
||||||
#include <QTextDocument>
|
|
||||||
#include <QThread>
|
|
||||||
|
|
||||||
namespace TextEditor {
|
|
||||||
|
|
||||||
struct BlockPreeditData {
|
|
||||||
int position;
|
|
||||||
QString text;
|
|
||||||
};
|
|
||||||
|
|
||||||
class SyntaxHighlighterRunnerPrivate : public QObject
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
SyntaxHighlighterRunnerPrivate(SyntaxHighlighter *highlighter,
|
|
||||||
QTextDocument *document,
|
|
||||||
bool async)
|
|
||||||
: m_highlighter(highlighter)
|
|
||||||
{
|
|
||||||
if (async) {
|
|
||||||
m_document = new QTextDocument(this);
|
|
||||||
m_document->setDocumentLayout(new TextDocumentLayout(m_document));
|
|
||||||
} else {
|
|
||||||
m_document = document;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_highlighter->setParent(m_document);
|
|
||||||
m_highlighter->setDocument(m_document);
|
|
||||||
|
|
||||||
connect(m_highlighter,
|
|
||||||
&SyntaxHighlighter::resultsReady,
|
|
||||||
this,
|
|
||||||
&SyntaxHighlighterRunnerPrivate::resultsReady);
|
|
||||||
}
|
|
||||||
|
|
||||||
void changeDocument(int from,
|
|
||||||
int charsRemoved,
|
|
||||||
const QString textAdded,
|
|
||||||
const QMap<int, 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->findBlockByNumber(it.key());
|
|
||||||
block.layout()->setPreeditArea(it.value().position, it.value().text);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void setExtraFormats(const QMap<int, QList<QTextLayout::FormatRange>> &formatMap)
|
|
||||||
{
|
|
||||||
QTC_ASSERT(m_highlighter, return);
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
QTC_ASSERT(m_highlighter, return);
|
|
||||||
for (auto it = blockNumbers.cbegin(); it != blockNumbers.cend(); ++it)
|
|
||||||
m_highlighter->clearExtraFormats(m_document->findBlockByNumber(*it));
|
|
||||||
}
|
|
||||||
|
|
||||||
void clearAllExtraFormats()
|
|
||||||
{
|
|
||||||
QTC_ASSERT(m_highlighter, return);
|
|
||||||
m_highlighter->clearAllExtraFormats();
|
|
||||||
}
|
|
||||||
|
|
||||||
void setFontSettings(const TextEditor::FontSettings &fontSettings)
|
|
||||||
{
|
|
||||||
QTC_ASSERT(m_highlighter, return);
|
|
||||||
m_highlighter->setFontSettings(fontSettings);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setDefinitionName(const QString &name)
|
|
||||||
{
|
|
||||||
QTC_ASSERT(m_highlighter, return);
|
|
||||||
m_highlighter->setDefinitionName(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setLanguageFeaturesFlags(unsigned int flags)
|
|
||||||
{
|
|
||||||
QTC_ASSERT(m_highlighter, return);
|
|
||||||
m_highlighter->setLanguageFeaturesFlags(flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setEnabled(bool enabled)
|
|
||||||
{
|
|
||||||
QTC_ASSERT(m_highlighter, return);
|
|
||||||
m_highlighter->setEnabled(enabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
void rehighlight()
|
|
||||||
{
|
|
||||||
QTC_ASSERT(m_highlighter, return);
|
|
||||||
m_highlighter->rehighlight();
|
|
||||||
}
|
|
||||||
|
|
||||||
void reformatBlocks(int from, int charsRemoved, int charsAdded)
|
|
||||||
{
|
|
||||||
QTC_ASSERT(m_highlighter, return);
|
|
||||||
m_highlighter->reformatBlocks(from, charsRemoved, charsAdded);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setInterrupted(bool interrupted)
|
|
||||||
{
|
|
||||||
QTC_ASSERT(m_highlighter, return);
|
|
||||||
m_highlighter->setInterrupted(interrupted);
|
|
||||||
}
|
|
||||||
|
|
||||||
QPointer<SyntaxHighlighter> m_highlighter = nullptr;
|
|
||||||
QTextDocument *m_document = nullptr;
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void resultsReady(const QList<SyntaxHighlighter::Result> &result);
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
void SyntaxHighlighterRunner::HighlightingStatus::notInterrupted(int from,
|
|
||||||
int charsRemoved,
|
|
||||||
int charsAdded)
|
|
||||||
{
|
|
||||||
m_from = from;
|
|
||||||
m_addedChars = charsAdded;
|
|
||||||
m_removedChars = charsRemoved;
|
|
||||||
m_current = from;
|
|
||||||
m_newFrom = from + m_addedChars;
|
|
||||||
m_interruptionRequested = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SyntaxHighlighterRunner::HighlightingStatus::interrupted(int from,
|
|
||||||
int charsRemoved,
|
|
||||||
int charsAdded)
|
|
||||||
{
|
|
||||||
m_newFrom = std::min(m_newFrom, from);
|
|
||||||
m_newFrom = std::min(m_current, m_newFrom);
|
|
||||||
m_removedChars += charsRemoved;
|
|
||||||
m_addedChars += charsAdded;
|
|
||||||
m_interruptionRequested = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SyntaxHighlighterRunner::HighlightingStatus::applyNewFrom()
|
|
||||||
{
|
|
||||||
m_from = m_newFrom;
|
|
||||||
m_current = m_newFrom;
|
|
||||||
m_interruptionRequested = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
SyntaxHighlighterRunner::SyntaxHighlighterRunner(SyntaxHighlighter *highlighter,
|
|
||||||
QTextDocument *document,
|
|
||||||
bool async)
|
|
||||||
: d(new SyntaxHighlighterRunnerPrivate(highlighter, document, async))
|
|
||||||
, m_document(document)
|
|
||||||
{
|
|
||||||
m_useGenericHighlighter = qobject_cast<Highlighter *>(d->m_highlighter);
|
|
||||||
|
|
||||||
if (async) {
|
|
||||||
m_thread.emplace();
|
|
||||||
d->moveToThread(&*m_thread);
|
|
||||||
connect(&*m_thread, &QThread::finished, d, &QObject::deleteLater);
|
|
||||||
m_thread->start();
|
|
||||||
|
|
||||||
connect(d,
|
|
||||||
&SyntaxHighlighterRunnerPrivate::resultsReady,
|
|
||||||
this,
|
|
||||||
&SyntaxHighlighterRunner::applyFormatRanges);
|
|
||||||
|
|
||||||
changeDocument(0, 0, m_document->characterCount());
|
|
||||||
connect(m_document,
|
|
||||||
&QTextDocument::contentsChange,
|
|
||||||
this,
|
|
||||||
&SyntaxHighlighterRunner::changeDocument);
|
|
||||||
|
|
||||||
m_foldValidator.setup(qobject_cast<TextDocumentLayout *>(document->documentLayout()));
|
|
||||||
} else {
|
|
||||||
connect(d,
|
|
||||||
&SyntaxHighlighterRunnerPrivate::resultsReady,
|
|
||||||
this,
|
|
||||||
[this](const QList<SyntaxHighlighter::Result> &result) {
|
|
||||||
if (result.size() == 1
|
|
||||||
&& result.at(0).m_state == SyntaxHighlighter::State::Extras)
|
|
||||||
return;
|
|
||||||
|
|
||||||
auto done = std::find_if(result.cbegin(),
|
|
||||||
result.cend(),
|
|
||||||
[](const SyntaxHighlighter::Result &res) {
|
|
||||||
return res.m_state
|
|
||||||
== SyntaxHighlighter::State::Done;
|
|
||||||
});
|
|
||||||
if (done != result.cend()) {
|
|
||||||
m_syntaxInfoUpdated = SyntaxHighlighter::State::Done;
|
|
||||||
emit highlightingFinished();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
m_syntaxInfoUpdated = SyntaxHighlighter::State::InProgress;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SyntaxHighlighterRunner::~SyntaxHighlighterRunner()
|
|
||||||
{
|
|
||||||
if (m_thread) {
|
|
||||||
m_thread->requestInterruption();
|
|
||||||
m_thread->quit();
|
|
||||||
m_thread->wait();
|
|
||||||
} else {
|
|
||||||
delete d;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SyntaxHighlighterRunner::applyFormatRanges(const QList<SyntaxHighlighter::Result> &results)
|
|
||||||
{
|
|
||||||
if (m_document == nullptr)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (m_highlightingStatus.m_interruptionRequested) {
|
|
||||||
d->setInterrupted(false);
|
|
||||||
m_highlightingStatus.applyNewFrom();
|
|
||||||
reformatBlocks(m_highlightingStatus.m_newFrom,
|
|
||||||
m_highlightingStatus.m_removedChars,
|
|
||||||
m_highlightingStatus.m_addedChars);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto processResult = [this](SyntaxHighlighter::Result result, QTextBlock docBlock) {
|
|
||||||
if (!docBlock.isValid())
|
|
||||||
return;
|
|
||||||
|
|
||||||
result.copyToBlock(docBlock);
|
|
||||||
m_highlightingStatus.m_current = docBlock.position() + docBlock.length() - 1;
|
|
||||||
|
|
||||||
if (result.m_formatRanges != docBlock.layout()->formats()) {
|
|
||||||
docBlock.layout()->setFormats(result.m_formatRanges);
|
|
||||||
m_document->markContentsDirty(docBlock.position(), docBlock.length());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if (results.size() == 1 && results.at(0).m_state == SyntaxHighlighter::State::Extras) {
|
|
||||||
QTextBlock docBlock = m_document->findBlockByNumber(results.at(0).m_blockNumber);
|
|
||||||
processResult(results.at(0), docBlock);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const SyntaxHighlighter::Result &result : results) {
|
|
||||||
m_syntaxInfoUpdated = result.m_state;
|
|
||||||
if (m_syntaxInfoUpdated == SyntaxHighlighter::State::Start) {
|
|
||||||
m_foldValidator.reset();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (m_syntaxInfoUpdated == SyntaxHighlighter::State::Done) {
|
|
||||||
m_foldValidator.finalize();
|
|
||||||
emit highlightingFinished();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QTextBlock docBlock = m_document->findBlockByNumber(result.m_blockNumber);
|
|
||||||
processResult(result, docBlock);
|
|
||||||
m_foldValidator.process(docBlock);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SyntaxHighlighterRunner::changeDocument(int from, int charsRemoved, int charsAdded)
|
|
||||||
{
|
|
||||||
QTC_ASSERT(m_document, return);
|
|
||||||
SyntaxHighlighter::State prevSyntaxInfoUpdated = m_syntaxInfoUpdated;
|
|
||||||
m_syntaxInfoUpdated = SyntaxHighlighter::State::InProgress;
|
|
||||||
|
|
||||||
QMap<int, BlockPreeditData> blocksPreedit;
|
|
||||||
QTextBlock block = m_document->findBlock(from);
|
|
||||||
const QTextBlock endBlock = m_document->findBlock(from + charsAdded);
|
|
||||||
while (block.isValid() && block != endBlock) {
|
|
||||||
if (QTextLayout *layout = block.layout()) {
|
|
||||||
if (const int pos = layout->preeditAreaPosition(); pos != -1)
|
|
||||||
blocksPreedit[block.blockNumber()] = {pos, layout->preeditAreaText()};
|
|
||||||
}
|
|
||||||
block = block.next();
|
|
||||||
}
|
|
||||||
const QString text = Utils::Text::textAt(QTextCursor(m_document), from, charsAdded);
|
|
||||||
QMetaObject::invokeMethod(d, [this, from, charsRemoved, text, blocksPreedit] {
|
|
||||||
d->changeDocument(from, charsRemoved, text, blocksPreedit);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (prevSyntaxInfoUpdated == SyntaxHighlighter::State::InProgress) {
|
|
||||||
m_highlightingStatus.interrupted(from, charsRemoved, charsAdded);
|
|
||||||
d->setInterrupted(true);
|
|
||||||
} else {
|
|
||||||
m_highlightingStatus.notInterrupted(from, charsRemoved, charsAdded);
|
|
||||||
d->setInterrupted(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SyntaxHighlighterRunner::useGenericHighlighter() const
|
|
||||||
{
|
|
||||||
return m_useGenericHighlighter;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SyntaxHighlighterRunner::setExtraFormats(
|
|
||||||
const QMap<int, QList<QTextLayout::FormatRange>> &formatMap)
|
|
||||||
{
|
|
||||||
QMetaObject::invokeMethod(d, [this, formatMap] { d->setExtraFormats(formatMap); });
|
|
||||||
}
|
|
||||||
|
|
||||||
void SyntaxHighlighterRunner::clearExtraFormats(const QList<int> &blockNumbers)
|
|
||||||
{
|
|
||||||
QMetaObject::invokeMethod(d, [this, blockNumbers] { d->clearExtraFormats(blockNumbers); });
|
|
||||||
}
|
|
||||||
|
|
||||||
void SyntaxHighlighterRunner::clearAllExtraFormats()
|
|
||||||
{
|
|
||||||
QMetaObject::invokeMethod(d, [this] { d->clearAllExtraFormats(); });
|
|
||||||
}
|
|
||||||
|
|
||||||
void SyntaxHighlighterRunner::setFontSettings(const TextEditor::FontSettings &fontSettings)
|
|
||||||
{
|
|
||||||
QMetaObject::invokeMethod(d, [this, fontSettings] { d->setFontSettings(fontSettings); });
|
|
||||||
rehighlight();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SyntaxHighlighterRunner::setLanguageFeaturesFlags(unsigned int flags)
|
|
||||||
{
|
|
||||||
QMetaObject::invokeMethod(d, [this, flags] { d->setLanguageFeaturesFlags(flags); });
|
|
||||||
}
|
|
||||||
|
|
||||||
void SyntaxHighlighterRunner::setEnabled(bool enabled)
|
|
||||||
{
|
|
||||||
QMetaObject::invokeMethod(d, [this, enabled] { d->setEnabled(enabled); });
|
|
||||||
}
|
|
||||||
|
|
||||||
void SyntaxHighlighterRunner::rehighlight()
|
|
||||||
{
|
|
||||||
if (m_syntaxInfoUpdated == SyntaxHighlighter::State::InProgress) {
|
|
||||||
m_highlightingStatus.interrupted(0, 0, m_document->characterCount());
|
|
||||||
d->setInterrupted(true);
|
|
||||||
} else {
|
|
||||||
m_highlightingStatus.notInterrupted(0, 0, m_document->characterCount());
|
|
||||||
d->setInterrupted(false);
|
|
||||||
QMetaObject::invokeMethod(d, [this] { d->rehighlight(); });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void SyntaxHighlighterRunner::reformatBlocks(int from, int charsRemoved, int charsAdded)
|
|
||||||
{
|
|
||||||
QMetaObject::invokeMethod(
|
|
||||||
d,
|
|
||||||
[this, from, charsRemoved, charsAdded] {
|
|
||||||
d->reformatBlocks(from, charsRemoved, charsAdded);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QString SyntaxHighlighterRunner::definitionName()
|
|
||||||
{
|
|
||||||
return m_definitionName;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SyntaxHighlighterRunner::setDefinitionName(const QString &name)
|
|
||||||
{
|
|
||||||
if (name.isEmpty())
|
|
||||||
return;
|
|
||||||
|
|
||||||
m_definitionName = name;
|
|
||||||
QMetaObject::invokeMethod(d, [this, name] { d->setDefinitionName(name); });
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace TextEditor
|
|
||||||
|
|
||||||
#include "syntaxhighlighterrunner.moc"
|
|
@@ -1,79 +0,0 @@
|
|||||||
// 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/fontsettings.h>
|
|
||||||
#include <texteditor/syntaxhighlighter.h>
|
|
||||||
#include <texteditor/texteditorsettings.h>
|
|
||||||
|
|
||||||
#include <QObject>
|
|
||||||
#include <QPointer>
|
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
|
||||||
class QTextDocument;
|
|
||||||
QT_END_NAMESPACE
|
|
||||||
|
|
||||||
namespace TextEditor {
|
|
||||||
|
|
||||||
class SyntaxHighlighterRunnerPrivate;
|
|
||||||
|
|
||||||
class TEXTEDITOR_EXPORT SyntaxHighlighterRunner : public QObject
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
using SyntaxHighlighterCreator = std::function<SyntaxHighlighter *()>;
|
|
||||||
|
|
||||||
SyntaxHighlighterRunner(SyntaxHighlighter *highlighter, QTextDocument *document, bool async);
|
|
||||||
virtual ~SyntaxHighlighterRunner();
|
|
||||||
|
|
||||||
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();
|
|
||||||
void reformatBlocks(int from, int charsRemoved, int charsAdded);
|
|
||||||
|
|
||||||
QString definitionName();
|
|
||||||
void setDefinitionName(const QString &name);
|
|
||||||
|
|
||||||
QTextDocument *document() const { return m_document; }
|
|
||||||
bool useGenericHighlighter() const;
|
|
||||||
|
|
||||||
bool syntaxInfoUpdated() const { return m_syntaxInfoUpdated == SyntaxHighlighter::State::Done; }
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void highlightingFinished();
|
|
||||||
|
|
||||||
private:
|
|
||||||
void applyFormatRanges(const QList<SyntaxHighlighter::Result> &results);
|
|
||||||
void changeDocument(int from, int charsRemoved, int charsAdded);
|
|
||||||
|
|
||||||
SyntaxHighlighterRunnerPrivate *d;
|
|
||||||
QPointer<QTextDocument> m_document = nullptr;
|
|
||||||
SyntaxHighlighter::State m_syntaxInfoUpdated = SyntaxHighlighter::State::Done;
|
|
||||||
|
|
||||||
struct HighlightingStatus
|
|
||||||
{
|
|
||||||
int m_from = 0;
|
|
||||||
int m_addedChars = 0;
|
|
||||||
int m_current = 0;
|
|
||||||
int m_removedChars = 0;
|
|
||||||
int m_newFrom = 0;
|
|
||||||
bool m_interruptionRequested = false;
|
|
||||||
|
|
||||||
void notInterrupted(int from, int charsRemoved, int charsAdded);
|
|
||||||
void interrupted(int from, int charsRemoved, int charsAdded);
|
|
||||||
void applyNewFrom();
|
|
||||||
} m_highlightingStatus;
|
|
||||||
|
|
||||||
bool m_useGenericHighlighter = false;
|
|
||||||
QString m_definitionName;
|
|
||||||
std::optional<QThread> m_thread;
|
|
||||||
TextDocumentLayout::FoldValidator m_foldValidator;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace TextEditor
|
|
||||||
|
|
@@ -10,10 +10,10 @@
|
|||||||
#include "tabsettings.h"
|
#include "tabsettings.h"
|
||||||
#include "textdocumentlayout.h"
|
#include "textdocumentlayout.h"
|
||||||
#include "texteditor.h"
|
#include "texteditor.h"
|
||||||
|
#include "texteditorsettings.h"
|
||||||
#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>
|
||||||
@@ -64,8 +64,6 @@ public:
|
|||||||
|
|
||||||
~TextDocumentPrivate()
|
~TextDocumentPrivate()
|
||||||
{
|
{
|
||||||
if (m_highlighterRunner)
|
|
||||||
m_highlighterRunner->deleteLater();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MultiTextCursor indentOrUnindent(const MultiTextCursor &cursor, bool doIndent, const TabSettings &tabSettings);
|
MultiTextCursor indentOrUnindent(const MultiTextCursor &cursor, bool doIndent, const TabSettings &tabSettings);
|
||||||
@@ -101,7 +99,7 @@ public:
|
|||||||
TextMarks m_marksCache; // Marks not owned
|
TextMarks m_marksCache; // Marks not owned
|
||||||
Utils::Guard m_modificationChangedGuard;
|
Utils::Guard m_modificationChangedGuard;
|
||||||
|
|
||||||
SyntaxHighlighterRunner *m_highlighterRunner = nullptr;
|
SyntaxHighlighter *m_highlighter = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
MultiTextCursor TextDocumentPrivate::indentOrUnindent(const MultiTextCursor &cursors,
|
MultiTextCursor TextDocumentPrivate::indentOrUnindent(const MultiTextCursor &cursors,
|
||||||
@@ -462,8 +460,8 @@ void TextDocument::applyFontSettings()
|
|||||||
block = block.next();
|
block = block.next();
|
||||||
}
|
}
|
||||||
updateLayout();
|
updateLayout();
|
||||||
if (d->m_highlighterRunner)
|
if (d->m_highlighter)
|
||||||
d->m_highlighterRunner->setFontSettings(d->m_fontSettings);
|
d->m_highlighter->setFontSettings(d->m_fontSettings);
|
||||||
}
|
}
|
||||||
|
|
||||||
const FontSettings &TextDocument::fontSettings() const
|
const FontSettings &TextDocument::fontSettings() const
|
||||||
@@ -533,6 +531,15 @@ bool TextDocument::applyChangeSet(const ChangeSet &changeSet)
|
|||||||
// the blocks list must be sorted
|
// the blocks list must be sorted
|
||||||
void TextDocument::setIfdefedOutBlocks(const QList<BlockRange> &blocks)
|
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();
|
QTextDocument *doc = document();
|
||||||
auto documentLayout = qobject_cast<TextDocumentLayout*>(doc->documentLayout());
|
auto documentLayout = qobject_cast<TextDocumentLayout*>(doc->documentLayout());
|
||||||
QTC_ASSERT(documentLayout, return);
|
QTC_ASSERT(documentLayout, return);
|
||||||
@@ -635,11 +642,6 @@ QTextDocument *TextDocument::document() const
|
|||||||
return &d->m_document;
|
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,
|
* Saves the document to the file specified by \a fileName. If errors occur,
|
||||||
* \a errorString contains their cause.
|
* \a errorString contains their cause.
|
||||||
@@ -911,26 +913,19 @@ bool TextDocument::reload(QString *errorString, ReloadFlag flag, ChangeType type
|
|||||||
return reload(errorString);
|
return reload(errorString);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextDocument::resetSyntaxHighlighter(const std::function<SyntaxHighlighter *()> &creator,
|
void TextDocument::resetSyntaxHighlighter(const std::function<SyntaxHighlighter *()> &creator)
|
||||||
bool threaded)
|
|
||||||
{
|
{
|
||||||
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();
|
SyntaxHighlighter *highlighter = creator();
|
||||||
|
highlighter->setParent(this);
|
||||||
|
highlighter->setDocument(this->document());
|
||||||
highlighter->setFontSettings(TextEditorSettings::fontSettings());
|
highlighter->setFontSettings(TextEditorSettings::fontSettings());
|
||||||
highlighter->setMimeType(mimeType());
|
highlighter->setMimeType(mimeType());
|
||||||
d->m_highlighterRunner = new SyntaxHighlighterRunner(highlighter,
|
d->m_highlighter = highlighter;
|
||||||
document(),
|
}
|
||||||
envValue.value_or(threaded));
|
|
||||||
|
SyntaxHighlighter *TextDocument::syntaxHighlighter() const
|
||||||
|
{
|
||||||
|
return d->m_highlighter;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextDocument::cleanWhitespace(const QTextCursor &cursor)
|
void TextDocument::cleanWhitespace(const QTextCursor &cursor)
|
||||||
|
@@ -34,7 +34,6 @@ class FontSettings;
|
|||||||
class IAssistProvider;
|
class IAssistProvider;
|
||||||
class StorageSettings;
|
class StorageSettings;
|
||||||
class SyntaxHighlighter;
|
class SyntaxHighlighter;
|
||||||
class SyntaxHighlighterRunner;
|
|
||||||
class TabSettings;
|
class TabSettings;
|
||||||
class TextDocumentPrivate;
|
class TextDocumentPrivate;
|
||||||
class TextMark;
|
class TextMark;
|
||||||
@@ -127,8 +126,8 @@ public:
|
|||||||
QTextDocument *document() const;
|
QTextDocument *document() const;
|
||||||
|
|
||||||
using SyntaxHighLighterCreator = std::function<SyntaxHighlighter *()>;
|
using SyntaxHighLighterCreator = std::function<SyntaxHighlighter *()>;
|
||||||
void resetSyntaxHighlighter(const SyntaxHighLighterCreator &creator, bool threaded = false);
|
void resetSyntaxHighlighter(const SyntaxHighLighterCreator &creator);
|
||||||
SyntaxHighlighterRunner *syntaxHighlighterRunner() const;
|
SyntaxHighlighter *syntaxHighlighter() const;
|
||||||
|
|
||||||
bool reload(QString *errorString, QTextCodec *codec);
|
bool reload(QString *errorString, QTextCodec *codec);
|
||||||
void cleanWhitespace(const QTextCursor &cursor);
|
void cleanWhitespace(const QTextCursor &cursor);
|
||||||
|
@@ -34,7 +34,6 @@
|
|||||||
#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>
|
||||||
|
|
||||||
@@ -1935,8 +1934,8 @@ void TextEditorWidgetPrivate::foldLicenseHeader()
|
|||||||
QStringList commentMarker;
|
QStringList commentMarker;
|
||||||
QStringList docMarker;
|
QStringList docMarker;
|
||||||
HighlighterHelper::Definition def;
|
HighlighterHelper::Definition def;
|
||||||
if (SyntaxHighlighterRunner *highlighter = q->textDocument()->syntaxHighlighterRunner())
|
if (auto highlighter = qobject_cast<Highlighter *>(q->textDocument()->syntaxHighlighter()))
|
||||||
def = HighlighterHelper::definitionForName(highlighter->definitionName());
|
def = highlighter->definition();
|
||||||
|
|
||||||
if (def.isValid()) {
|
if (def.isValid()) {
|
||||||
for (const QString &marker :
|
for (const QString &marker :
|
||||||
@@ -3494,10 +3493,10 @@ QByteArray TextEditorWidget::saveState() const
|
|||||||
|
|
||||||
bool TextEditorWidget::singleShotAfterHighlightingDone(std::function<void()> &&f)
|
bool TextEditorWidget::singleShotAfterHighlightingDone(std::function<void()> &&f)
|
||||||
{
|
{
|
||||||
if (d->m_document->syntaxHighlighterRunner()
|
if (d->m_document->syntaxHighlighter()
|
||||||
&& !d->m_document->syntaxHighlighterRunner()->syntaxInfoUpdated()) {
|
&& !d->m_document->syntaxHighlighter()->syntaxHighlighterUpToDate()) {
|
||||||
connect(d->m_document->syntaxHighlighterRunner(),
|
connect(d->m_document->syntaxHighlighter(),
|
||||||
&SyntaxHighlighterRunner::highlightingFinished,
|
&SyntaxHighlighter::finished,
|
||||||
this,
|
this,
|
||||||
[f = std::move(f)] { f(); }, Qt::SingleShotConnection);
|
[f = std::move(f)] { f(); }, Qt::SingleShotConnection);
|
||||||
return true;
|
return true;
|
||||||
@@ -3741,10 +3740,11 @@ void TextEditorWidgetPrivate::configureGenericHighlighter(
|
|||||||
|
|
||||||
const QString definitionFilesPath
|
const QString definitionFilesPath
|
||||||
= TextEditorSettings::highlighterSettings().definitionFilesPath().toString();
|
= TextEditorSettings::highlighterSettings().definitionFilesPath().toString();
|
||||||
m_document->resetSyntaxHighlighter([definitionFilesPath] {
|
m_document->resetSyntaxHighlighter([definitionFilesPath, definition] {
|
||||||
return new Highlighter(definitionFilesPath);
|
auto highlighter = new Highlighter(definitionFilesPath);
|
||||||
|
highlighter->setDefinition(definition);
|
||||||
|
return highlighter;
|
||||||
});
|
});
|
||||||
m_document->syntaxHighlighterRunner()->setDefinitionName(definition.name());
|
|
||||||
|
|
||||||
m_document->setFontSettings(TextEditorSettings::fontSettings());
|
m_document->setFontSettings(TextEditorSettings::fontSettings());
|
||||||
}
|
}
|
||||||
@@ -3769,8 +3769,8 @@ void TextEditorWidgetPrivate::setupFromDefinition(const KSyntaxHighlighting::Def
|
|||||||
|
|
||||||
KSyntaxHighlighting::Definition TextEditorWidgetPrivate::currentDefinition()
|
KSyntaxHighlighting::Definition TextEditorWidgetPrivate::currentDefinition()
|
||||||
{
|
{
|
||||||
if (SyntaxHighlighterRunner *highlighter = m_document->syntaxHighlighterRunner())
|
if (auto *highlighter = qobject_cast<Highlighter *>(m_document->syntaxHighlighter()))
|
||||||
return HighlighterHelper::definitionForName(highlighter->definitionName());
|
return highlighter->definition();
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5127,7 +5127,8 @@ void TextEditorWidgetPrivate::setupBlockLayout(const PaintEventData &data,
|
|||||||
blockData.layout = data.block.layout();
|
blockData.layout = data.block.layout();
|
||||||
|
|
||||||
QTextOption option = blockData.layout->textOption();
|
QTextOption option = blockData.layout->textOption();
|
||||||
if (data.suppressSyntaxInIfdefedOutBlock && TextDocumentLayout::ifdefedOut(data.block)) {
|
if (data.suppressSyntaxInIfdefedOutBlock
|
||||||
|
&& TextDocumentLayout::ifdefedOut(data.block)) {
|
||||||
option.setFlags(option.flags() | QTextOption::SuppressColors);
|
option.setFlags(option.flags() | QTextOption::SuppressColors);
|
||||||
painter.setPen(data.ifdefedOutFormat.foreground().color());
|
painter.setPen(data.ifdefedOutFormat.foreground().color());
|
||||||
} else {
|
} else {
|
||||||
@@ -5746,8 +5747,8 @@ void TextEditorWidgetPrivate::paintCodeFolding(QPainter &painter,
|
|||||||
TextBlockUserData *nextBlockUserData = TextDocumentLayout::textUserData(nextBlock);
|
TextBlockUserData *nextBlockUserData = TextDocumentLayout::textUserData(nextBlock);
|
||||||
|
|
||||||
bool drawBox = nextBlockUserData
|
bool drawBox = nextBlockUserData
|
||||||
&& TextDocumentLayout::foldingIndent(data.block) < nextBlockUserData->foldingIndent();
|
&& TextDocumentLayout::foldingIndent(data.block)
|
||||||
|
< nextBlockUserData->foldingIndent();
|
||||||
|
|
||||||
const int blockNumber = data.block.blockNumber();
|
const int blockNumber = data.block.blockNumber();
|
||||||
bool active = blockNumber == extraAreaHighlightFoldBlockNumber;
|
bool active = blockNumber == extraAreaHighlightFoldBlockNumber;
|
||||||
@@ -8183,7 +8184,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 (SyntaxHighlighterRunner *highlighter = textDocument()->syntaxHighlighterRunner())
|
if (SyntaxHighlighter *highlighter = textDocument()->syntaxHighlighter())
|
||||||
highlighter->rehighlight();
|
highlighter->rehighlight();
|
||||||
QTextOption option = document()->defaultTextOption();
|
QTextOption option = document()->defaultTextOption();
|
||||||
option.setFlags(optionFlags);
|
option.setFlags(optionFlags);
|
||||||
|
@@ -124,8 +124,6 @@ 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",
|
||||||
|
@@ -4,6 +4,7 @@
|
|||||||
#include "baseannotationhighlighter.h"
|
#include "baseannotationhighlighter.h"
|
||||||
|
|
||||||
#include <texteditor/fontsettings.h>
|
#include <texteditor/fontsettings.h>
|
||||||
|
#include <texteditor/syntaxhighlighter.h>
|
||||||
#include <texteditor/texteditorsettings.h>
|
#include <texteditor/texteditorsettings.h>
|
||||||
|
|
||||||
#include <utils/algorithm.h>
|
#include <utils/algorithm.h>
|
||||||
@@ -163,7 +164,7 @@ void BaseAnnotationHighlighter::rehighlight()
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
setChangeNumbers(changes);
|
setChangeNumbers(changes);
|
||||||
TextEditor::SyntaxHighlighter::rehighlight();
|
SyntaxHighlighter::rehighlight();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace VcsBase
|
} // namespace VcsBase
|
||||||
|
@@ -30,7 +30,7 @@
|
|||||||
#include <texteditor/texteditoractionhandler.h>
|
#include <texteditor/texteditoractionhandler.h>
|
||||||
#include <texteditor/textdocument.h>
|
#include <texteditor/textdocument.h>
|
||||||
#include <texteditor/textdocumentlayout.h>
|
#include <texteditor/textdocumentlayout.h>
|
||||||
#include <texteditor/syntaxhighlighterrunner.h>
|
#include <texteditor/syntaxhighlighter.h>
|
||||||
|
|
||||||
#include <utils/algorithm.h>
|
#include <utils/algorithm.h>
|
||||||
#include <utils/progressindicator.h>
|
#include <utils/progressindicator.h>
|
||||||
@@ -821,7 +821,7 @@ void VcsBaseEditorWidget::setFileLogAnnotateEnabled(bool e)
|
|||||||
|
|
||||||
void VcsBaseEditorWidget::setHighlightingEnabled(bool e)
|
void VcsBaseEditorWidget::setHighlightingEnabled(bool e)
|
||||||
{
|
{
|
||||||
textDocument()->syntaxHighlighterRunner()->setEnabled(e);
|
textDocument()->syntaxHighlighter()->setEnabled(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
FilePath VcsBaseEditorWidget::workingDirectory() const
|
FilePath VcsBaseEditorWidget::workingDirectory() const
|
||||||
@@ -1102,7 +1102,7 @@ void VcsBaseEditorWidget::slotActivateAnnotation()
|
|||||||
|
|
||||||
disconnect(this, &QPlainTextEdit::textChanged, this, &VcsBaseEditorWidget::slotActivateAnnotation);
|
disconnect(this, &QPlainTextEdit::textChanged, this, &VcsBaseEditorWidget::slotActivateAnnotation);
|
||||||
|
|
||||||
if (SyntaxHighlighterRunner *ah = textDocument()->syntaxHighlighterRunner()) {
|
if (SyntaxHighlighter *ah = textDocument()->syntaxHighlighter()) {
|
||||||
ah->rehighlight();
|
ah->rehighlight();
|
||||||
} else {
|
} else {
|
||||||
BaseAnnotationHighlighterCreator creator = annotationHighlighterCreator();
|
BaseAnnotationHighlighterCreator creator = annotationHighlighterCreator();
|
||||||
|
@@ -7,7 +7,6 @@
|
|||||||
|
|
||||||
#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>
|
||||||
@@ -32,7 +31,7 @@ private slots:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
QTextDocument *doc = nullptr;
|
QTextDocument *doc = nullptr;
|
||||||
SyntaxHighlighterRunner *highlighterRunner = nullptr;
|
SyntaxHighlighter *highlighter = nullptr;
|
||||||
FontSettings fontsettings;
|
FontSettings fontsettings;
|
||||||
QHash<int, QTextCharFormat> formatHash;
|
QHash<int, QTextCharFormat> formatHash;
|
||||||
QTextCharFormat whitespaceFormat;
|
QTextCharFormat whitespaceFormat;
|
||||||
@@ -58,8 +57,7 @@ Last)";
|
|||||||
|
|
||||||
doc = new QTextDocument();
|
doc = new QTextDocument();
|
||||||
doc->setPlainText(text);
|
doc->setPlainText(text);
|
||||||
auto highlighter = new SyntaxHighlighter(doc, fontsettings);
|
highlighter = new SyntaxHighlighter(doc, fontsettings);
|
||||||
highlighterRunner = new SyntaxHighlighterRunner(highlighter, doc, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const HighlightingResults &highlightingResults()
|
static const HighlightingResults &highlightingResults()
|
||||||
@@ -77,7 +75,7 @@ void tst_highlighter::test_setExtraAdditionalFormats()
|
|||||||
{
|
{
|
||||||
QCOMPARE(doc->blockCount(), 4);
|
QCOMPARE(doc->blockCount(), 4);
|
||||||
|
|
||||||
SemanticHighlighter::setExtraAdditionalFormats(highlighterRunner, highlightingResults(), formatHash);
|
SemanticHighlighter::setExtraAdditionalFormats(highlighter, 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 +138,17 @@ void tst_highlighter::test_clearExtraFormats()
|
|||||||
{
|
{
|
||||||
QCOMPARE(doc->blockCount(), 4);
|
QCOMPARE(doc->blockCount(), 4);
|
||||||
|
|
||||||
SemanticHighlighter::setExtraAdditionalFormats(highlighterRunner, highlightingResults(), formatHash);
|
SemanticHighlighter::setExtraAdditionalFormats(highlighter, 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);
|
||||||
|
|
||||||
highlighterRunner->clearExtraFormats({emptyLineBlock.blockNumber()});
|
highlighter->clearExtraFormats(emptyLineBlock);
|
||||||
QVERIFY(emptyLineBlock.layout()->formats().isEmpty());
|
QVERIFY(emptyLineBlock.layout()->formats().isEmpty());
|
||||||
|
|
||||||
highlighterRunner->clearExtraFormats({spacesLineBlock.blockNumber()});
|
highlighter->clearExtraFormats(spacesLineBlock);
|
||||||
|
|
||||||
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 +183,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);
|
||||||
|
|
||||||
highlighterRunner->clearAllExtraFormats();
|
highlighter->clearAllExtraFormats();
|
||||||
|
|
||||||
QVERIFY(firstBlock.layout()->formats().isEmpty());
|
QVERIFY(firstBlock.layout()->formats().isEmpty());
|
||||||
QVERIFY(emptyLineBlock.layout()->formats().isEmpty());
|
QVERIFY(emptyLineBlock.layout()->formats().isEmpty());
|
||||||
@@ -221,7 +219,7 @@ void tst_highlighter::test_incrementalApplyAdditionalFormats()
|
|||||||
|
|
||||||
QFutureInterface<HighlightingResult> fiOld;
|
QFutureInterface<HighlightingResult> fiOld;
|
||||||
fiOld.reportResults(highlightingResults());
|
fiOld.reportResults(highlightingResults());
|
||||||
SemanticHighlighter::incrementalApplyExtraAdditionalFormats(highlighterRunner,
|
SemanticHighlighter::incrementalApplyExtraAdditionalFormats(highlighter,
|
||||||
fiOld.future(),
|
fiOld.future(),
|
||||||
2,
|
2,
|
||||||
0,
|
0,
|
||||||
@@ -229,7 +227,7 @@ void tst_highlighter::test_incrementalApplyAdditionalFormats()
|
|||||||
auto formats = firstBlock.layout()->formats();
|
auto formats = firstBlock.layout()->formats();
|
||||||
QVERIFY(formats.isEmpty());
|
QVERIFY(formats.isEmpty());
|
||||||
|
|
||||||
SemanticHighlighter::incrementalApplyExtraAdditionalFormats(highlighterRunner,
|
SemanticHighlighter::incrementalApplyExtraAdditionalFormats(highlighter,
|
||||||
fiOld.future(),
|
fiOld.future(),
|
||||||
0,
|
0,
|
||||||
2,
|
2,
|
||||||
@@ -254,7 +252,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(highlighterRunner,
|
SemanticHighlighter::incrementalApplyExtraAdditionalFormats(highlighter,
|
||||||
fiOld.future(),
|
fiOld.future(),
|
||||||
3,
|
3,
|
||||||
6,
|
6,
|
||||||
@@ -280,7 +278,7 @@ void tst_highlighter::test_incrementalApplyAdditionalFormats()
|
|||||||
|
|
||||||
QFutureInterface<HighlightingResult> fiNew;
|
QFutureInterface<HighlightingResult> fiNew;
|
||||||
fiNew.reportResults(newResults);
|
fiNew.reportResults(newResults);
|
||||||
SemanticHighlighter::incrementalApplyExtraAdditionalFormats(highlighterRunner,
|
SemanticHighlighter::incrementalApplyExtraAdditionalFormats(highlighter,
|
||||||
fiNew.future(),
|
fiNew.future(),
|
||||||
0,
|
0,
|
||||||
3,
|
3,
|
||||||
@@ -294,7 +292,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(highlighterRunner,
|
SemanticHighlighter::incrementalApplyExtraAdditionalFormats(highlighter,
|
||||||
fiNew.future(),
|
fiNew.future(),
|
||||||
3,
|
3,
|
||||||
4,
|
4,
|
||||||
@@ -305,14 +303,14 @@ void tst_highlighter::test_incrementalApplyAdditionalFormats()
|
|||||||
QVERIFY(formats.isEmpty());
|
QVERIFY(formats.isEmpty());
|
||||||
|
|
||||||
// QTCREATORBUG-29218
|
// QTCREATORBUG-29218
|
||||||
highlighterRunner->clearAllExtraFormats();
|
highlighter->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(highlighterRunner,
|
SemanticHighlighter::incrementalApplyExtraAdditionalFormats(highlighter,
|
||||||
fi29218.future(),
|
fi29218.future(),
|
||||||
0,
|
0,
|
||||||
1,
|
1,
|
||||||
@@ -323,7 +321,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(highlighterRunner,
|
SemanticHighlighter::incrementalApplyExtraAdditionalFormats(highlighter,
|
||||||
fi29218.future(),
|
fi29218.future(),
|
||||||
1,
|
1,
|
||||||
2,
|
2,
|
||||||
@@ -347,7 +345,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(highlighterRunner, highlightingResults(), formatHash);
|
SemanticHighlighter::setExtraAdditionalFormats(highlighter, highlightingResults(), formatHash);
|
||||||
|
|
||||||
auto formats = firstBlock.layout()->formats();
|
auto formats = firstBlock.layout()->formats();
|
||||||
QCOMPARE(formats.size(), 2);
|
QCOMPARE(formats.size(), 2);
|
||||||
@@ -366,7 +364,7 @@ void tst_highlighter::cleanup()
|
|||||||
{
|
{
|
||||||
delete doc;
|
delete doc;
|
||||||
doc = nullptr;
|
doc = nullptr;
|
||||||
highlighterRunner = nullptr;
|
highlighter = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace TextEditor
|
} // namespace TextEditor
|
||||||
|
Reference in New Issue
Block a user