mirror of
https://github.com/neovim/neovim.git
synced 2026-03-30 20:32:08 +00:00
fix(marktree): fix edge case bug regarding changing intersections
fix #37867 This bug happens when only one end is moved between different nodes, but the other end is also moved but within the same node. When this happens we need the correct previous position even for the internal move. This code shall be refactored to make the intent clearer, (and avoid some unnecessary processing) but this is a fix for the observable bug. Thanks to KevinGoodsell for providing a deterministic reproduce using fuzzing techniques.
This commit is contained in:
@@ -1860,16 +1860,17 @@ bool marktree_itr_step_overlap(MarkTree *b, MarkTreeIter *itr, MTPair *pair)
|
||||
|
||||
static void swap_keys(MarkTree *b, MarkTreeIter *itr1, MarkTreeIter *itr2, DamageList *damage)
|
||||
{
|
||||
if (itr1->x != itr2->x) {
|
||||
if (mt_paired(rawkey(itr1))) {
|
||||
kvi_push(*damage, ((Damage){ mt_lookup_key(rawkey(itr1)), itr1->x, itr2->x,
|
||||
itr1->i, itr2->i }));
|
||||
}
|
||||
if (mt_paired(rawkey(itr2))) {
|
||||
kvi_push(*damage, ((Damage){ mt_lookup_key(rawkey(itr2)), itr2->x, itr1->x,
|
||||
itr2->i, itr1->i }));
|
||||
}
|
||||
// TODO(bfredl): redactor is planned, see TODO comment next to qsort in marktree_splice
|
||||
if (mt_paired(rawkey(itr1))) {
|
||||
kvi_push(*damage, ((Damage){ mt_lookup_key(rawkey(itr1)), itr1->x, itr2->x,
|
||||
itr1->i, itr2->i }));
|
||||
}
|
||||
if (mt_paired(rawkey(itr2))) {
|
||||
kvi_push(*damage, ((Damage){ mt_lookup_key(rawkey(itr2)), itr2->x, itr1->x,
|
||||
itr2->i, itr1->i }));
|
||||
}
|
||||
|
||||
if (itr1->x != itr2->x) {
|
||||
uint32_t meta_inc_1[kMTMetaCount];
|
||||
meta_describe_key(meta_inc_1, rawkey(itr1));
|
||||
uint32_t meta_inc_2[kMTMetaCount];
|
||||
|
||||
@@ -645,4 +645,28 @@ describe('marktree', function()
|
||||
until not lib.marktree_itr_next_filter(tree, iter, 101, 0, filter)
|
||||
eq(tablelength(seen), tablelength(shadow))
|
||||
end)
|
||||
|
||||
itp('works with edge case splicing overlapping ranges #37867', function()
|
||||
local tree = ffi.new('MarkTree[1]') -- zero initialized by luajit
|
||||
put(tree, 190, 48, false)
|
||||
put(tree, 48, 48, true)
|
||||
put(tree, 190, 48, false)
|
||||
put(tree, 166, 48, false, 166, 48, false)
|
||||
put(tree, 48, 48, true, 48, 48, false)
|
||||
put(tree, 48, 48, true, 48, 48, false)
|
||||
put(tree, 48, 48, true, 255, 48, false)
|
||||
put(tree, 131, 48, false, 48, 48, false)
|
||||
put(tree, 131, 48, false, 48, 48, false)
|
||||
put(tree, 48, 48, true, 131, 48, false)
|
||||
put(tree, 48, 48, false, 216, 48, false)
|
||||
put(tree, 172, 48, false, 51, 48, false)
|
||||
put(tree, 131, 48, false, 131, 48, false)
|
||||
put(tree, 156, 48, false, 131, 48, false)
|
||||
put(tree, 135, 48, false, 166, 48, false)
|
||||
put(tree, 172, 48, false, 250, 48, false)
|
||||
put(tree, 48, 48, false, 143, 48, false)
|
||||
ok(lib.marktree_check_intersections(tree))
|
||||
lib.marktree_splice(tree, 48, 0, 139, 0, 0, 0)
|
||||
ok(lib.marktree_check_intersections(tree))
|
||||
end)
|
||||
end)
|
||||
|
||||
Reference in New Issue
Block a user