[cm6] Account for line shifts when updating the spelling line tracker (#13015)

* Use lineShift

* Use fromA instead of fromB

* Only check the update doc

* Always use oldDoc

* Copy tests

GitOrigin-RevId: 05e5516b09ee4a25d8ac2b5f2994a034f35c9e82
This commit is contained in:
Alf Eaton 2023-05-10 12:52:16 +01:00 committed by Copybot
parent 11716cbd05
commit 466011df86
2 changed files with 42 additions and 14 deletions

View file

@ -58,14 +58,13 @@ export class LineTracker {
applyUpdate(update: ViewUpdate) {
for (const transaction of update.transactions) {
if (transaction.docChanged) {
let positionShift = 0
let lineShift = 0
transaction.changes.iterChanges(
(fromA, toA, fromB, toB, insertedText) => {
const insertedLength = insertedText.length
const removedLength = toA - fromA
const hasInserted = insertedLength > 0
const hasRemoved = removedLength > 0
const doc = update.state.doc
const oldDoc = transaction.startState.doc
if (hasRemoved) {
const startLine = oldDoc.lineAt(fromA).number
@ -85,10 +84,15 @@ export class LineTracker {
* |2|bb| => [false, true, false]
* |3|dddd|
*/
this._lines.splice(startLine - 1, endLine - startLine + 1, true)
this._lines.splice(
startLine - 1 + lineShift,
endLine - startLine + 1,
true
)
lineShift -= endLine - startLine
}
if (hasInserted) {
const startLine = doc.lineAt(fromB).number
const startLine = oldDoc.lineAt(fromA).number
/* Mark start line as changed, and insert new (changed) lines after.
* Example:
* with this text:
@ -108,19 +112,19 @@ export class LineTracker {
* |4|cccc|
*/
const changes = new Array(insertedText.lines).fill(true)
this._lines.splice(startLine - 1, 1, ...changes)
this._lines.splice(startLine - 1 + lineShift, 1, ...changes)
lineShift += changes.length - 1
}
positionShift = positionShift - removedLength + insertedLength
}
)
if (update.state.doc.lines !== this._lines.length) {
throw new OError(
'LineTracker length does not match document line count'
).withInfo({
documentLines: update.state.doc.lines,
trackerLines: this._lines.length,
})
}
}
if (update.state.doc.lines !== this._lines.length) {
throw new OError(
'LineTracker length does not match document line count'
).withInfo({
documentLines: update.state.doc.lines,
trackerLines: this._lines.length,
})
}
}
}

View file

@ -178,5 +178,29 @@ describe('LineTracker', function () {
[5, false],
])
})
it('should handle multiple deletions', function () {
const transaction = view.state.update({
changes: [
{ from: 0, to: 24, insert: '' },
{ from: 39, to: 44, insert: '' },
],
})
view.dispatch(transaction)
check([
[1, true],
[2, true],
])
})
it('should handle multiple insertions', function () {
const transactionUndo = view.state.update({
changes: [
{ from: 0, to: 0, insert: 'big change\n'.repeat(20) },
{ from: 50, to: 50, insert: 'xxxx' },
],
})
view.dispatch(transactionUndo)
})
})
})