aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorYuan Fu2022-06-15 21:53:15 -0700
committerYuan Fu2022-06-16 11:52:04 -0700
commit7cee82a91d287e42e6596960cbee17157cde4b29 (patch)
treeeb6ec90eaacdc78137d87fc63632a18226027735 /src
parentbd1b27b7c7bbd969cf76409499bb84a83600c42a (diff)
downloademacs-7cee82a91d287e42e6596960cbee17157cde4b29.tar.gz
emacs-7cee82a91d287e42e6596960cbee17157cde4b29.zip
Fix treesit function ts_record_change and friends
In ts_record_change, the way we calculate tree-sitter change was wrong: ptrdiff_t affected_start = max (visible_beg, start_byte) - visible_beg; ptrdiff_t affected_old_end = min (visible_end, affected_start + bytes_del); ptrdiff_t affected_new_end = affected_start + bytes_ins; I changed it to below (also renamed variables) ptrdiff_t start_offset = min (visible_end, max (visible_beg, start_byte)) - visible_beg; ptrdiff_t old_end_offset = min (visible_end, max (visible_beg, old_end_byte)) - visible_beg; ptrdiff_t new_end_offset = min (visible_end, max (visible_beg, new_end_byte)) - visible_beg; Also previously only visible_end is changed (in a wrong way) XTS_PARSER (lisp_parser)->visible_end = affected_new_end; Now we have a whole new bunch of code that makes the right change. * src/treesit.c (ts_tree_edit_1): Add assertion. (ts_record_change): See above. (ts_ensure_position_synced): Add assertion. (ts_ensure_parsed): Only free if non-NULL. (make_ts_parser): Add assertion. (Ftreesit_parser_set_included_ranges): Ensure parsed before setting ranges. (Ftreesit_parser_included_ranges): Add assertion.
Diffstat (limited to 'src')
-rw-r--r--src/treesit.c87
1 files changed, 68 insertions, 19 deletions
diff --git a/src/treesit.c b/src/treesit.c
index 585683aa1ba..5a53b09675c 100644
--- a/src/treesit.c
+++ b/src/treesit.c
@@ -324,6 +324,9 @@ static inline void
324ts_tree_edit_1 (TSTree *tree, ptrdiff_t start_byte, 324ts_tree_edit_1 (TSTree *tree, ptrdiff_t start_byte,
325 ptrdiff_t old_end_byte, ptrdiff_t new_end_byte) 325 ptrdiff_t old_end_byte, ptrdiff_t new_end_byte)
326{ 326{
327 eassert (start_byte >= 0);
328 eassert (start_byte <= old_end_byte);
329 eassert (start_byte <= new_end_byte);
327 TSPoint dummy_point = {0, 0}; 330 TSPoint dummy_point = {0, 0};
328 TSInputEdit edit = {(uint32_t) start_byte, 331 TSInputEdit edit = {(uint32_t) start_byte,
329 (uint32_t) old_end_byte, 332 (uint32_t) old_end_byte,
@@ -356,24 +359,56 @@ ts_record_change (ptrdiff_t start_byte, ptrdiff_t old_end_byte,
356 insert, and think of them as moving unchanged text back 359 insert, and think of them as moving unchanged text back
357 and forth. After all, the whole point of updating the 360 and forth. After all, the whole point of updating the
358 tree is to update the position of unchanged text. */ 361 tree is to update the position of unchanged text. */
359 ptrdiff_t bytes_del = old_end_byte - start_byte;
360 ptrdiff_t bytes_ins = new_end_byte - start_byte;
361
362 ptrdiff_t visible_beg = XTS_PARSER (lisp_parser)->visible_beg; 362 ptrdiff_t visible_beg = XTS_PARSER (lisp_parser)->visible_beg;
363 ptrdiff_t visible_end = XTS_PARSER (lisp_parser)->visible_end; 363 ptrdiff_t visible_end = XTS_PARSER (lisp_parser)->visible_end;
364 364 eassert (visible_beg >= 0);
365 ptrdiff_t affected_start = 365 eassert (visible_beg <= visible_end);
366 max (visible_beg, start_byte) - visible_beg; 366
367 ptrdiff_t affected_old_end = 367 /* AFFECTED_START/OLD_END/NEW_END are (0-based) offsets from
368 min (visible_end, affected_start + bytes_del); 368 VISIBLE_BEG. min(visi_end, max(visi_beg, value)) clips
369 ptrdiff_t affected_new_end = 369 value into [visi_beg, visi_end], and subtracting visi_beg
370 affected_start + bytes_ins; 370 gives the offset from visi_beg. */
371 371 ptrdiff_t start_offset =
372 ts_tree_edit_1 (tree, affected_start, affected_old_end, 372 min (visible_end,
373 affected_new_end); 373 max (visible_beg, start_byte)) - visible_beg;
374 XTS_PARSER (lisp_parser)->visible_end = affected_new_end; 374 ptrdiff_t old_end_offset =
375 min (visible_end,
376 max (visible_beg, old_end_byte)) - visible_beg;
377 ptrdiff_t new_end_offset =
378 min (visible_end,
379 max (visible_beg, new_end_byte)) - visible_beg;
380 eassert (start_offset <= old_end_offset);
381 eassert (start_offset <= new_end_offset);
382
383 ts_tree_edit_1 (tree, start_offset, old_end_offset,
384 new_end_offset);
375 XTS_PARSER (lisp_parser)->need_reparse = true; 385 XTS_PARSER (lisp_parser)->need_reparse = true;
376 XTS_PARSER (lisp_parser)->timestamp++; 386 XTS_PARSER (lisp_parser)->timestamp++;
387
388 /* VISIBLE_BEG/END records tree-sitter's range of view in
389 the buffer. Ee need to adjust them when tree-sitter's
390 view changes. */
391 ptrdiff_t visi_beg_delta;
392 if (old_end_byte > new_end_byte)
393 {
394 /* Move backward. */
395 visi_beg_delta = min (visible_beg, new_end_byte)
396 - min (visible_beg, old_end_byte);
397 }
398 else
399 {
400 /* Move forward. */
401 visi_beg_delta = old_end_byte < visible_beg
402 ? new_end_byte - old_end_byte : 0;
403 }
404 XTS_PARSER (lisp_parser)->visible_beg
405 = visible_beg + visi_beg_delta;
406 XTS_PARSER (lisp_parser)->visible_end
407 = visible_end + visi_beg_delta
408 + (new_end_offset - old_end_offset);
409 eassert (XTS_PARSER (lisp_parser)->visible_beg >= 0);
410 eassert (XTS_PARSER (lisp_parser)->visible_beg
411 <= XTS_PARSER (lisp_parser)->visible_end);
377 } 412 }
378 } 413 }
379} 414}
@@ -389,6 +424,9 @@ ts_ensure_position_synced (Lisp_Object parser)
389 struct buffer *buffer = XBUFFER (XTS_PARSER (parser)->buffer); 424 struct buffer *buffer = XBUFFER (XTS_PARSER (parser)->buffer);
390 ptrdiff_t visible_beg = XTS_PARSER (parser)->visible_beg; 425 ptrdiff_t visible_beg = XTS_PARSER (parser)->visible_beg;
391 ptrdiff_t visible_end = XTS_PARSER (parser)->visible_end; 426 ptrdiff_t visible_end = XTS_PARSER (parser)->visible_end;
427 eassert (0 <= visible_beg);
428 eassert (visible_beg <= visible_end);
429
392 /* Before we parse or set ranges, catch up with the narrowing 430 /* Before we parse or set ranges, catch up with the narrowing
393 situation. We change visible_beg and visible_end to match 431 situation. We change visible_beg and visible_end to match
394 BUF_BEGV_BYTE and BUF_ZV_BYTE, and inform tree-sitter of the 432 BUF_BEGV_BYTE and BUF_ZV_BYTE, and inform tree-sitter of the
@@ -403,6 +441,7 @@ ts_ensure_position_synced (Lisp_Object parser)
403 /* Tree-sitter sees: insert at the beginning. */ 441 /* Tree-sitter sees: insert at the beginning. */
404 ts_tree_edit_1 (tree, 0, 0, visible_beg - BUF_BEGV_BYTE (buffer)); 442 ts_tree_edit_1 (tree, 0, 0, visible_beg - BUF_BEGV_BYTE (buffer));
405 visible_beg = BUF_BEGV_BYTE (buffer); 443 visible_beg = BUF_BEGV_BYTE (buffer);
444 eassert (visible_beg <= visible_end);
406 } 445 }
407 /* 2. Make sure visible_end = BUF_ZV_BYTE. */ 446 /* 2. Make sure visible_end = BUF_ZV_BYTE. */
408 if (visible_end < BUF_ZV_BYTE (buffer)) 447 if (visible_end < BUF_ZV_BYTE (buffer))
@@ -412,6 +451,7 @@ ts_ensure_position_synced (Lisp_Object parser)
412 visible_end - visible_beg, 451 visible_end - visible_beg,
413 BUF_ZV_BYTE (buffer) - visible_beg); 452 BUF_ZV_BYTE (buffer) - visible_beg);
414 visible_end = BUF_ZV_BYTE (buffer); 453 visible_end = BUF_ZV_BYTE (buffer);
454 eassert (visible_beg <= visible_end);
415 } 455 }
416 else if (visible_end > BUF_ZV_BYTE (buffer)) 456 else if (visible_end > BUF_ZV_BYTE (buffer))
417 { 457 {
@@ -420,6 +460,7 @@ ts_ensure_position_synced (Lisp_Object parser)
420 visible_end - visible_beg, 460 visible_end - visible_beg,
421 BUF_ZV_BYTE (buffer) - visible_beg); 461 BUF_ZV_BYTE (buffer) - visible_beg);
422 visible_end = BUF_ZV_BYTE (buffer); 462 visible_end = BUF_ZV_BYTE (buffer);
463 eassert (visible_beg <= visible_end);
423 } 464 }
424 /* 3. Make sure visible_beg = BUF_BEGV_BYTE. */ 465 /* 3. Make sure visible_beg = BUF_BEGV_BYTE. */
425 if (visible_beg < BUF_BEGV_BYTE (buffer)) 466 if (visible_beg < BUF_BEGV_BYTE (buffer))
@@ -427,6 +468,7 @@ ts_ensure_position_synced (Lisp_Object parser)
427 /* Tree-sitter sees: delete at the beginning. */ 468 /* Tree-sitter sees: delete at the beginning. */
428 ts_tree_edit_1 (tree, 0, BUF_BEGV_BYTE (buffer) - visible_beg, 0); 469 ts_tree_edit_1 (tree, 0, BUF_BEGV_BYTE (buffer) - visible_beg, 0);
429 visible_beg = BUF_BEGV_BYTE (buffer); 470 visible_beg = BUF_BEGV_BYTE (buffer);
471 eassert (visible_beg <= visible_end);
430 } 472 }
431 eassert (0 <= visible_beg); 473 eassert (0 <= visible_beg);
432 eassert (visible_beg <= visible_end); 474 eassert (visible_beg <= visible_end);
@@ -477,7 +519,8 @@ ts_ensure_parsed (Lisp_Object parser)
477 xsignal1 (Qtreesit_parse_error, buf); 519 xsignal1 (Qtreesit_parse_error, buf);
478 } 520 }
479 521
480 ts_tree_delete (tree); 522 if (tree != NULL)
523 ts_tree_delete (tree);
481 XTS_PARSER (parser)->tree = new_tree; 524 XTS_PARSER (parser)->tree = new_tree;
482 XTS_PARSER (parser)->need_reparse = false; 525 XTS_PARSER (parser)->need_reparse = false;
483} 526}
@@ -551,6 +594,7 @@ make_ts_parser (Lisp_Object buffer, TSParser *parser,
551 lisp_parser->need_reparse = true; 594 lisp_parser->need_reparse = true;
552 lisp_parser->visible_beg = BUF_BEGV (XBUFFER (buffer)); 595 lisp_parser->visible_beg = BUF_BEGV (XBUFFER (buffer));
553 lisp_parser->visible_end = BUF_ZV (XBUFFER (buffer)); 596 lisp_parser->visible_end = BUF_ZV (XBUFFER (buffer));
597 eassert (lisp_parser->visible_beg <= lisp_parser->visible_end);
554 return make_lisp_ptr (lisp_parser, Lisp_Vectorlike); 598 return make_lisp_ptr (lisp_parser, Lisp_Vectorlike);
555} 599}
556 600
@@ -673,10 +717,7 @@ function provided by a tree-sitter language dynamic module, e.g.,
673 ts_parser_set_language (parser, lang); 717 ts_parser_set_language (parser, lang);
674 718
675 Lisp_Object lisp_parser 719 Lisp_Object lisp_parser
676 = make_ts_parser (buffer, parser, NULL, language); 720 = make_ts_parser (Fcurrent_buffer (), parser, NULL, language);
677
678 struct buffer *old_buffer = current_buffer;
679 set_buffer_internal (XBUFFER (buffer));
680 721
681 Fset (Qtreesit_parser_list, 722 Fset (Qtreesit_parser_list,
682 Fcons (lisp_parser, Fsymbol_value (Qtreesit_parser_list))); 723 Fcons (lisp_parser, Fsymbol_value (Qtreesit_parser_list)));
@@ -835,6 +876,11 @@ nil. */)
835 (XTS_PARSER (parser)->parser, &len); 876 (XTS_PARSER (parser)->parser, &len);
836 if (len == 0) 877 if (len == 0)
837 return Qnil; 878 return Qnil;
879
880 /* Our return value depends on the buffer state (BUF_BEGV_BYTE,
881 etc), so we need to sync up. */
882 ts_ensure_position_synced (parser);
883
838 struct buffer *buffer = XBUFFER (XTS_PARSER (parser)->buffer); 884 struct buffer *buffer = XBUFFER (XTS_PARSER (parser)->buffer);
839 885
840 Lisp_Object list = Qnil; 886 Lisp_Object list = Qnil;
@@ -843,6 +889,9 @@ nil. */)
843 TSRange range = ranges[idx]; 889 TSRange range = ranges[idx];
844 uint32_t beg_byte = range.start_byte + BUF_BEGV_BYTE (buffer); 890 uint32_t beg_byte = range.start_byte + BUF_BEGV_BYTE (buffer);
845 uint32_t end_byte = range.end_byte + BUF_BEGV_BYTE (buffer); 891 uint32_t end_byte = range.end_byte + BUF_BEGV_BYTE (buffer);
892 eassert (BUF_BEGV_BYTE (buffer) <= beg_byte);
893 eassert (beg_byte <= end_byte);
894 eassert (end_byte <= BUF_ZV_BYTE (buffer));
846 895
847 Lisp_Object lisp_range = 896 Lisp_Object lisp_range =
848 Fcons (make_fixnum (buf_bytepos_to_charpos (buffer, beg_byte)) , 897 Fcons (make_fixnum (buf_bytepos_to_charpos (buffer, beg_byte)) ,