aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuuk van Baal <luukvbaal@gmail.com>2024-09-02 16:21:34 +0200
committerLuuk van Baal <luukvbaal@gmail.com>2024-09-04 15:13:12 +0200
commit34ded4d97b78063f5174b0e8dfb9d9bafdcb3110 (patch)
treecbeadc591a84250a8f49b1bea3674b0a515960c6
parentb6e350a6b4df40fcc99931c460668c36fadc9989 (diff)
downloadrneovim-34ded4d97b78063f5174b0e8dfb9d9bafdcb3110.tar.gz
rneovim-34ded4d97b78063f5174b0e8dfb9d9bafdcb3110.tar.bz2
rneovim-34ded4d97b78063f5174b0e8dfb9d9bafdcb3110.zip
fix(decor): exclude invalid marks from meta total
Problem: Marktree meta count still includes invalidated marks, making guards that check the meta total ineffective. Solution: Revise marktree metadata when in/revalidating a mark.
-rw-r--r--src/nvim/extmark.c17
-rw-r--r--src/nvim/marktree.c12
-rw-r--r--test/functional/ui/decorations_spec.lua13
3 files changed, 24 insertions, 18 deletions
diff --git a/src/nvim/extmark.c b/src/nvim/extmark.c
index 4ff298cde5..c20c7dea23 100644
--- a/src/nvim/extmark.c
+++ b/src/nvim/extmark.c
@@ -70,24 +70,19 @@ void extmark_set(buf_T *buf, uint32_t ns_id, uint32_t *idp, int row, colnr_T col
extmark_del_id(buf, ns_id, id);
} else {
assert(marktree_itr_valid(itr));
- bool invalid = mt_invalid(old_mark);
if (old_mark.pos.row == row && old_mark.pos.col == col) {
// not paired: we can revise in place
- if (!invalid && mt_decor_any(old_mark)) {
- // TODO(bfredl): conflict of concerns: buf_decor_remove() must process
- // the buffer as if MT_FLAG_DECOR_SIGNTEXT is already removed, however
- // marktree must precisely adjust the set of flags from the old set to the new
- uint16_t save_flags = mt_itr_rawkey(itr).flags;
- mt_itr_rawkey(itr).flags &= (uint16_t) ~MT_FLAG_DECOR_SIGNTEXT;
+ if (!mt_invalid(old_mark) && mt_decor_any(old_mark)) {
+ mt_itr_rawkey(itr).flags &= (uint16_t) ~MT_FLAG_EXTERNAL_MASK;
buf_decor_remove(buf, row, row, col, mt_decor(old_mark), true);
- mt_itr_rawkey(itr).flags = save_flags;
}
- marktree_revise_flags(buf->b_marktree, itr, flags);
+ mt_itr_rawkey(itr).flags |= flags;
mt_itr_rawkey(itr).decor_data = decor.data;
+ marktree_revise_meta(buf->b_marktree, itr, old_mark);
goto revised;
}
marktree_del_itr(buf->b_marktree, itr, false);
- if (!invalid) {
+ if (!mt_invalid(old_mark)) {
buf_decor_remove(buf, old_mark.pos.row, old_mark.pos.row, old_mark.pos.col,
mt_decor(old_mark), true);
}
@@ -131,6 +126,7 @@ static void extmark_setraw(buf_T *buf, uint64_t mark, int row, colnr_T col, bool
int row2 = 0;
if (invalid) {
mt_itr_rawkey(itr).flags &= (uint16_t) ~MT_FLAG_INVALID;
+ marktree_revise_meta(buf->b_marktree, itr, key);
} else if (move && key.flags & MT_FLAG_DECOR_SIGNTEXT && buf->b_signcols.autom) {
MTPos end = marktree_get_altpos(buf->b_marktree, key, NULL);
row1 = MIN(end.row, MIN(key.pos.row, row));
@@ -394,6 +390,7 @@ void extmark_splice_delete(buf_T *buf, int l_row, colnr_T l_col, int u_row, coln
} else {
invalidated = true;
mt_itr_rawkey(itr).flags |= MT_FLAG_INVALID;
+ marktree_revise_meta(buf->b_marktree, itr, mark);
buf_decor_remove(buf, mark.pos.row, endpos.row, mark.pos.col, mt_decor(mark), false);
}
}
diff --git a/src/nvim/marktree.c b/src/nvim/marktree.c
index 9e3005b6a3..555fef5bbd 100644
--- a/src/nvim/marktree.c
+++ b/src/nvim/marktree.c
@@ -446,7 +446,7 @@ static MTNode *marktree_alloc_node(MarkTree *b, bool internal)
// really meta_inc[kMTMetaCount]
static void meta_describe_key_inc(uint32_t *meta_inc, MTKey *k)
{
- if (!mt_end(*k)) {
+ if (!mt_end(*k) && !mt_invalid(*k)) {
meta_inc[kMTMetaInline] += (k->flags & MT_FLAG_DECOR_VIRT_TEXT_INLINE) ? 1 : 0;
meta_inc[kMTMetaLines] += (k->flags & MT_FLAG_DECOR_VIRT_LINES) ? 1 : 0;
meta_inc[kMTMetaSignHL] += (k->flags & MT_FLAG_DECOR_SIGNHL) ? 1 : 0;
@@ -774,14 +774,10 @@ uint64_t marktree_del_itr(MarkTree *b, MarkTreeIter *itr, bool rev)
return other;
}
-void marktree_revise_flags(MarkTree *b, MarkTreeIter *itr, uint16_t new_flags)
+void marktree_revise_meta(MarkTree *b, MarkTreeIter *itr, MTKey old_key)
{
- uint32_t meta_old[4];
- meta_describe_key(meta_old, rawkey(itr));
- rawkey(itr).flags &= (uint16_t) ~MT_FLAG_EXTERNAL_MASK;
- rawkey(itr).flags |= new_flags;
-
- uint32_t meta_new[4];
+ uint32_t meta_old[4], meta_new[4];
+ meta_describe_key(meta_old, old_key);
meta_describe_key(meta_new, rawkey(itr));
if (!memcmp(meta_old, meta_new, sizeof(meta_old))) {
diff --git a/test/functional/ui/decorations_spec.lua b/test/functional/ui/decorations_spec.lua
index 61a5e1d6f7..042975f898 100644
--- a/test/functional/ui/decorations_spec.lua
+++ b/test/functional/ui/decorations_spec.lua
@@ -5641,6 +5641,19 @@ l5
]])
eq("Invalid 'sign_text'", pcall_err(api.nvim_buf_set_extmark, 0, ns, 5, 0, {sign_text='❤️x'}))
end)
+
+ it('auto signcolumn hides with invalidated sign', function()
+ api.nvim_set_option_value('signcolumn', 'auto', {})
+ api.nvim_buf_set_extmark(0, ns, 0, 0, {sign_text='S1', invalidate=true})
+ feed('ia<cr>b<esc>dd')
+ screen:expect({
+ grid = [[
+ ^a |
+ {1:~ }|*8
+ |
+ ]]
+ })
+ end)
end)
describe('decorations: virt_text', function()