mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-02-16 09:14:18 +00:00
Ditch the async range update in tree-sitter (bug#78402)
Right now in treesit-outline-search -> treesit-navigate-thing, a freshly created tree-sitter node becomes outdated within the function. I'm not sure _exactly_ how it happend, but it might look like this: we first get a node from, say, html parser, then get another node from, say, liquid parser. Creating the node from liquid parser causes a reparse which updated the range of the html parser, which rendered the html node outdated. There're several problems with the current design, let's start with the most obvious one: we add treesit--font-lock-mark-ranges-to-fontify as a notifier of the primar parser in treesit-major-mode-setup. Now, if a ts major mode inherits another major mode, treesit-major-mode-setup will be called twice, once in the parent mode and once in the child node, and two parsers will have the notifier. But treesit--font-lock-mark-ranges-to-fontify is designed to run only once. I believe this bug, together with some mysterious async execution order, led to the problems we saw in the bug report. My solution is to just make everything synchronous. So I added treesit-parser-changed-regions, and modified treesit--font-lock-mark-ranges-to-fontify to use it. Now we don't need to add the notifier to the primary parser anymore. I also applied the tree-sitter-outline change we discussed in the bug report. (Change to treesit-outline-search, and remove treesit--after-change.) * lisp/treesit.el: (treesit--font-lock-mark-ranges-to-fontify): Remove the unused PARSER arg. (treesit--pre-redisplay): Make use of treesit-parser-changed-regions. (treesit-outline-search): Call treesit--pre-redisplay in the beginning. (treesit--after-change): Remove function. (treesit-major-mode-setup): Don't add notifier to primary parser.
This commit is contained in:
parent
564b947745
commit
159ddd27ee
1 changed files with 10 additions and 20 deletions
|
|
@ -2020,7 +2020,7 @@ Because `pre-redisplay-functions' could be called multiple times
|
|||
during a single command loop, we use this variable to debounce
|
||||
calls to `treesit--pre-redisplay'.")
|
||||
|
||||
(defun treesit--font-lock-mark-ranges-to-fontify (ranges _parser)
|
||||
(defun treesit--font-lock-mark-ranges-to-fontify (ranges)
|
||||
"A notifier that marks ranges that needs refontification.
|
||||
|
||||
For RANGES and PARSER see `treesit-parser-add-notifier'.
|
||||
|
|
@ -2074,17 +2074,15 @@ parser."
|
|||
(car (treesit-parser-list))))
|
||||
|
||||
(defun treesit--pre-redisplay (&rest _)
|
||||
"Force a reparse on the primary parser and mark regions to be fontified.
|
||||
|
||||
The actual work is carried out by
|
||||
`treesit--font-lock-mark-ranges-to-fontify', which see."
|
||||
"Force a reparse on primary parser and mark regions to be fontified."
|
||||
(unless (eq treesit--pre-redisplay-tick (buffer-chars-modified-tick))
|
||||
(when treesit-primary-parser
|
||||
;; Force a reparse on the primary parser, if everything is setup
|
||||
;; correctly, the parser should call
|
||||
;; `treesit--font-lock-mark-ranges-to-fontify' (which should be a
|
||||
;; notifier function of the primary parser).
|
||||
(treesit-parser-root-node treesit-primary-parser))
|
||||
;; Force a reparse on the primary parser and update embedded
|
||||
;; parser ranges in the changed ranges.
|
||||
(let ((affected-ranges (treesit-parser-changed-regions
|
||||
treesit-primary-parser)))
|
||||
(when affected-ranges
|
||||
(treesit--font-lock-mark-ranges-to-fontify affected-ranges))))
|
||||
|
||||
(setq treesit--pre-redisplay-tick (buffer-chars-modified-tick))))
|
||||
|
||||
|
|
@ -4072,6 +4070,7 @@ this variable takes priority.")
|
|||
"Search for the next outline heading in the syntax tree.
|
||||
For BOUND, MOVE, BACKWARD, LOOKING-AT, see the descriptions in
|
||||
`outline-search-function'."
|
||||
(treesit--pre-redisplay)
|
||||
(if looking-at
|
||||
(when (treesit-outline--at-point) (pos-bol))
|
||||
|
||||
|
|
@ -4158,11 +4157,6 @@ For BOUND, MOVE, BACKWARD, LOOKING-AT, see the descriptions in
|
|||
|
||||
level))
|
||||
|
||||
(defun treesit--after-change (beg end _len)
|
||||
"Force updating the ranges in BEG...END.
|
||||
Expected to be called after each text change."
|
||||
(treesit-update-ranges beg end))
|
||||
|
||||
;;; Hideshow mode
|
||||
|
||||
(defun treesit-hs-block-end ()
|
||||
|
|
@ -4374,9 +4368,6 @@ before calling this function."
|
|||
. treesit-font-lock-fontify-region)))
|
||||
(treesit-font-lock-recompute-features)
|
||||
(add-hook 'pre-redisplay-functions #'treesit--pre-redisplay 0 t)
|
||||
(when treesit-primary-parser
|
||||
(treesit-parser-add-notifier
|
||||
treesit-primary-parser #'treesit--font-lock-mark-ranges-to-fontify))
|
||||
(treesit-validate-font-lock-rules treesit-font-lock-settings))
|
||||
;; Syntax
|
||||
(add-hook 'syntax-propertize-extend-region-functions
|
||||
|
|
@ -4462,8 +4453,7 @@ before calling this function."
|
|||
(setq treesit-outline-predicate
|
||||
#'treesit-outline-predicate--from-imenu))
|
||||
(setq-local outline-search-function #'treesit-outline-search
|
||||
outline-level #'treesit-outline-level)
|
||||
(add-hook 'outline-after-change-functions #'treesit--after-change nil t))
|
||||
outline-level #'treesit-outline-level))
|
||||
|
||||
;; Remove existing local parsers.
|
||||
(dolist (ov (overlays-in (point-min) (point-max)))
|
||||
|
|
|
|||
Loading…
Reference in a new issue