forked from qt-creator/qt-creator
LanguageClient: Merge adjacent change events
This saves a lot of data going over the wire. Change-Id: Iac1220c72797643ba09bf90b02f7b5155cda4b0f Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
@@ -698,22 +698,41 @@ void Client::documentContentsChanged(TextEditor::TextDocument *document,
|
|||||||
|
|
||||||
if (syncKind != TextDocumentSyncKind::None) {
|
if (syncKind != TextDocumentSyncKind::None) {
|
||||||
if (syncKind == TextDocumentSyncKind::Incremental) {
|
if (syncKind == TextDocumentSyncKind::Incremental) {
|
||||||
DidChangeTextDocumentParams::TextDocumentContentChangeEvent change;
|
// If the new change is a pure insertion and its range is adjacent to the range of the
|
||||||
QTextDocument oldDoc(m_openedDocument[document]);
|
// previous change, we can trivially merge the two changes.
|
||||||
QTextCursor cursor(&oldDoc);
|
// For the typical case of the user typing a continuous sequence of characters,
|
||||||
// Workaround https://bugreports.qt.io/browse/QTBUG-80662
|
// this will save a lot of TextDocumentContentChangeEvent elements in the data stream,
|
||||||
// The contentsChanged gives a character count that can be wrong for QTextCursor
|
// as otherwise we'd send tons of single-character changes.
|
||||||
// when there are special characters removed/added (like formating characters).
|
const QString &text = document->textAt(position, charsAdded);
|
||||||
// Also, characterCount return the number of characters + 1 because of the hidden
|
auto &queue = m_documentsToUpdate[document];
|
||||||
// paragraph separator character.
|
bool append = true;
|
||||||
// This implementation is based on QWidgetTextControlPrivate::_q_contentsChanged.
|
if (!queue.isEmpty() && charsRemoved == 0) {
|
||||||
// For charsAdded, textAt handles the case itself.
|
auto &prev = queue.last();
|
||||||
cursor.setPosition(qMin(oldDoc.characterCount() - 1, position + charsRemoved));
|
const int prevStart = prev.range()->start()
|
||||||
cursor.setPosition(position, QTextCursor::KeepAnchor);
|
.toPositionInDocument(document->document());
|
||||||
change.setRange(Range(cursor));
|
if (prevStart + prev.text().length() == position) {
|
||||||
change.setRangeLength(cursor.selectionEnd() - cursor.selectionStart());
|
prev.setText(prev.text() + text);
|
||||||
change.setText(document->textAt(position, charsAdded));
|
append = false;
|
||||||
m_documentsToUpdate[document] << change;
|
}
|
||||||
|
}
|
||||||
|
if (append) {
|
||||||
|
QTextDocument oldDoc(m_openedDocument[document]);
|
||||||
|
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;
|
||||||
|
change.setRange(Range(cursor));
|
||||||
|
change.setRangeLength(cursor.selectionEnd() - cursor.selectionStart());
|
||||||
|
change.setText(text);
|
||||||
|
queue << change;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
m_documentsToUpdate[document] = {
|
m_documentsToUpdate[document] = {
|
||||||
DidChangeTextDocumentParams::TextDocumentContentChangeEvent(document->plainText())};
|
DidChangeTextDocumentParams::TextDocumentContentChangeEvent(document->plainText())};
|
||||||
|
|||||||
Reference in New Issue
Block a user