Add another heuristic to speed up tree-sitter fontification

* lisp/treesit.el (treesit-font-lock-fontify-region): Use
treesit--children-covering-range to reduce the node size.
This commit is contained in:
Yuan Fu 2022-11-20 17:15:42 -08:00
parent 32870d2f20
commit 76eb88df02
No known key found for this signature in database
GPG key ID: 56E19BC57664A442

View file

@ -816,41 +816,51 @@ If LOUDLY is non-nil, display some debugging information."
;; Only activate if ENABLE flag is t.
(activate (eq t enable)))
(ignore activate)
;; The node seems small, enlarge it.
(while (and (< (- (treesit-node-end node-on)
(treesit-node-start node-on))
40)
(treesit-node-parent node-on))
(setq node-on (treesit-node-parent node-on)))
(let ((captures (treesit-query-capture
node-on query start end))
(inhibit-point-motion-hooks t))
(with-silent-modifications
(dolist (capture captures)
(let* ((face (car capture))
(node (cdr capture))
(node-start (treesit-node-start node))
(node-end (treesit-node-end node)))
;; Turns out it is possible to capture a node that's
;; completely outside the region between START and
;; END. If the node is outside of that region, (max
;; node-start start) and friends return bad values.
(when (and (< start node-end)
(< node-start end))
(cond
((facep face)
(treesit-fontify-with-override
(max node-start start) (min node-end end)
face override))
((functionp face)
(funcall face node override start end)))
;; Don't raise an error if FACE is neither a face nor
;; a function. This is to allow intermediate capture
;; names used for #match and #eq.
(when (or loudly treesit--font-lock-verbose)
(message "Fontifying text from %d to %d, Face: %s, Node: %s"
(max node-start start) (min node-end end)
face (treesit-node-type node)))))))))))
;; Maybe the node returned by `treesit-node-on' is the root
;; node, because the region between START and END contains
;; several top-level constructs (e.g., variable declarations
;; in C).
(setq node-on (treesit--children-covering-range
node-on start end))
(dolist (sub-node node-on)
(let ((captures (treesit-query-capture
sub-node query start end))
(inhibit-point-motion-hooks t))
(with-silent-modifications
(dolist (capture captures)
(let* ((face (car capture))
(node (cdr capture))
(node-start (treesit-node-start node))
(node-end (treesit-node-end node)))
;; Turns out it is possible to capture a node that's
;; completely outside the region between START and
;; END. If the node is outside of that region, (max
;; node-start start) and friends return bad values.
(when (and (< start node-end)
(< node-start end))
(cond
((facep face)
(treesit-fontify-with-override
(max node-start start) (min node-end end)
face override))
((functionp face)
(funcall face node override start end)))
;; Don't raise an error if FACE is neither a face nor
;; a function. This is to allow intermediate capture
;; names used for #match and #eq.
(when (or loudly treesit--font-lock-verbose)
(message "Fontifying text from %d to %d, Face: %s, Node: %s"
(max node-start start) (min node-end end)
face (treesit-node-type node))))))))))))
`(jit-lock-bounds ,start . ,end))
(defun treesit--font-lock-notifier (ranges parser)