forked from qt-creator/qt-creator
LanguageClient: avoid creating a QTextDocument for every contents change
clone the document when it is opened and adjust it after each contents change Change-Id: I4fd511a3b142b1875f1da7d241ab5cddf49322e8 Reviewed-by: <github-actions-qt-creator@cristianadam.eu> Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
This commit is contained in:
@@ -289,9 +289,10 @@ public:
|
|||||||
~OpenedDocument()
|
~OpenedDocument()
|
||||||
{
|
{
|
||||||
QObject::disconnect(contentsChangedConnection);
|
QObject::disconnect(contentsChangedConnection);
|
||||||
|
delete document;
|
||||||
}
|
}
|
||||||
QMetaObject::Connection contentsChangedConnection;
|
QMetaObject::Connection contentsChangedConnection;
|
||||||
QString documentContents;
|
QTextDocument *document = nullptr;
|
||||||
};
|
};
|
||||||
QMap<TextEditor::TextDocument *, OpenedDocument> m_openedDocument;
|
QMap<TextEditor::TextDocument *, OpenedDocument> m_openedDocument;
|
||||||
|
|
||||||
@@ -628,7 +629,7 @@ void Client::openDocument(TextEditor::TextDocument *document)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
d->m_openedDocument[document].documentContents = document->plainText();
|
d->m_openedDocument[document].document = document->document()->clone(this);
|
||||||
d->m_openedDocument[document].contentsChangedConnection
|
d->m_openedDocument[document].contentsChangedConnection
|
||||||
= connect(document,
|
= connect(document,
|
||||||
&TextDocument::contentsChangedWithPosition,
|
&TextDocument::contentsChangedWithPosition,
|
||||||
@@ -1076,6 +1077,19 @@ void Client::documentContentsChanged(TextEditor::TextDocument *document,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const QString &text = document->textAt(position, charsAdded);
|
||||||
|
QTextCursor cursor(d->m_openedDocument[document].document);
|
||||||
|
// Workaround https://bugreports.qt.io/browse/QTBUG-80662
|
||||||
|
// The contentsChanged gives a character count that can be wrong for QTextCursor
|
||||||
|
// when there are special characters removed/added (like formating characters).
|
||||||
|
// Also, characterCount return the number of characters + 1 because of the hidden
|
||||||
|
// paragraph separator character.
|
||||||
|
// This implementation is based on QWidgetTextControlPrivate::_q_contentsChanged.
|
||||||
|
// For charsAdded, textAt handles the case itself.
|
||||||
|
cursor.setPosition(qMin(d->m_openedDocument[document].document->characterCount() - 1,
|
||||||
|
position + charsRemoved));
|
||||||
|
cursor.setPosition(position, QTextCursor::KeepAnchor);
|
||||||
|
|
||||||
if (syncKind != TextDocumentSyncKind::None) {
|
if (syncKind != TextDocumentSyncKind::None) {
|
||||||
if (syncKind == TextDocumentSyncKind::Incremental) {
|
if (syncKind == TextDocumentSyncKind::Incremental) {
|
||||||
// If the new change is a pure insertion and its range is adjacent to the range of the
|
// If the new change is a pure insertion and its range is adjacent to the range of the
|
||||||
@@ -1083,7 +1097,6 @@ void Client::documentContentsChanged(TextEditor::TextDocument *document,
|
|||||||
// For the typical case of the user typing a continuous sequence of characters,
|
// For the typical case of the user typing a continuous sequence of characters,
|
||||||
// this will save a lot of TextDocumentContentChangeEvent elements in the data stream,
|
// this will save a lot of TextDocumentContentChangeEvent elements in the data stream,
|
||||||
// as otherwise we'd send tons of single-character changes.
|
// as otherwise we'd send tons of single-character changes.
|
||||||
const QString &text = document->textAt(position, charsAdded);
|
|
||||||
auto &queue = d->m_documentsToUpdate[document];
|
auto &queue = d->m_documentsToUpdate[document];
|
||||||
bool append = true;
|
bool append = true;
|
||||||
if (!queue.isEmpty() && charsRemoved == 0) {
|
if (!queue.isEmpty() && charsRemoved == 0) {
|
||||||
@@ -1096,17 +1109,6 @@ void Client::documentContentsChanged(TextEditor::TextDocument *document,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (append) {
|
if (append) {
|
||||||
QTextDocument oldDoc(d->m_openedDocument[document].documentContents);
|
|
||||||
QTextCursor cursor(&oldDoc);
|
|
||||||
// Workaround https://bugreports.qt.io/browse/QTBUG-80662
|
|
||||||
// The contentsChanged gives a character count that can be wrong for QTextCursor
|
|
||||||
// when there are special characters removed/added (like formating characters).
|
|
||||||
// Also, characterCount return the number of characters + 1 because of the hidden
|
|
||||||
// paragraph separator character.
|
|
||||||
// This implementation is based on QWidgetTextControlPrivate::_q_contentsChanged.
|
|
||||||
// For charsAdded, textAt handles the case itself.
|
|
||||||
cursor.setPosition(qMin(oldDoc.characterCount() - 1, position + charsRemoved));
|
|
||||||
cursor.setPosition(position, QTextCursor::KeepAnchor);
|
|
||||||
DidChangeTextDocumentParams::TextDocumentContentChangeEvent change;
|
DidChangeTextDocumentParams::TextDocumentContentChangeEvent change;
|
||||||
change.setRange(Range(cursor));
|
change.setRange(Range(cursor));
|
||||||
change.setRangeLength(cursor.selectionEnd() - cursor.selectionStart());
|
change.setRangeLength(cursor.selectionEnd() - cursor.selectionStart());
|
||||||
@@ -1117,8 +1119,8 @@ void Client::documentContentsChanged(TextEditor::TextDocument *document,
|
|||||||
d->m_documentsToUpdate[document] = {
|
d->m_documentsToUpdate[document] = {
|
||||||
DidChangeTextDocumentParams::TextDocumentContentChangeEvent(document->plainText())};
|
DidChangeTextDocumentParams::TextDocumentContentChangeEvent(document->plainText())};
|
||||||
}
|
}
|
||||||
d->m_openedDocument[document].documentContents = document->plainText();
|
|
||||||
}
|
}
|
||||||
|
cursor.insertText(text);
|
||||||
|
|
||||||
++d->m_documentVersions[document->filePath()];
|
++d->m_documentVersions[document->filePath()];
|
||||||
using namespace TextEditor;
|
using namespace TextEditor;
|
||||||
|
Reference in New Issue
Block a user