Use treesit-subtree-stat to determine treesit--font-lock-fast-mode
* lisp/treesit.el: (treesit--children-covering-range-recurse): Return nil if LIMIT is exceeded. (treesit--font-lock-fast-mode): Change to a ternary value. (treesit-font-lock-fontify-region): Enable fast mode based on the result of treesit-subtree-stat.
This commit is contained in:
parent
382e018856
commit
1970726e26
1 changed files with 26 additions and 24 deletions
|
@ -913,14 +913,15 @@ LIMIT is the recursion limit, which defaults to 100."
|
||||||
(push r result))
|
(push r result))
|
||||||
(push child result))
|
(push child result))
|
||||||
(setq child (treesit-node-next-sibling child)))
|
(setq child (treesit-node-next-sibling child)))
|
||||||
;; If NODE has no child, keep NODE.
|
;; If NODE has no child, keep NODE. If LIMIT is exceeded, return
|
||||||
(or result (list node))))
|
;; nil.
|
||||||
|
(or result (and (> limit 0) (list node)))))
|
||||||
|
|
||||||
(defsubst treesit--node-length (node)
|
(defsubst treesit--node-length (node)
|
||||||
"Return the length of the text of NODE."
|
"Return the length of the text of NODE."
|
||||||
(- (treesit-node-end node) (treesit-node-start node)))
|
(- (treesit-node-end node) (treesit-node-start node)))
|
||||||
|
|
||||||
(defvar-local treesit--font-lock-fast-mode nil
|
(defvar-local treesit--font-lock-fast-mode 'unspecified
|
||||||
"If this variable is t, change the way we query so it's faster.
|
"If this variable is t, change the way we query so it's faster.
|
||||||
This is not a general optimization and should be RARELY needed!
|
This is not a general optimization and should be RARELY needed!
|
||||||
See comments in `treesit-font-lock-fontify-region' for more
|
See comments in `treesit-font-lock-fontify-region' for more
|
||||||
|
@ -985,36 +986,34 @@ If LOUDLY is non-nil, display some debugging information."
|
||||||
(enable (nth 1 setting))
|
(enable (nth 1 setting))
|
||||||
(override (nth 3 setting))
|
(override (nth 3 setting))
|
||||||
(language (treesit-query-language query)))
|
(language (treesit-query-language query)))
|
||||||
(when-let ((nodes (list (treesit-buffer-root-node language)))
|
|
||||||
|
;; Use deterministic way to decide whether to turn on "fast
|
||||||
|
;; mode". (See bug#60691, bug#60223.)
|
||||||
|
(when (eq treesit--font-lock-fast-mode 'unspecified)
|
||||||
|
(pcase-let ((`(,max-depth ,max-width)
|
||||||
|
(treesit-subtree-stat
|
||||||
|
(treesit-buffer-root-node language))))
|
||||||
|
(if (or (> max-depth 100) (> max-width 4000))
|
||||||
|
(setq treesit--font-lock-fast-mode t)
|
||||||
|
(setq treesit--font-lock-fast-mode nil))))
|
||||||
|
|
||||||
|
(when-let* ((root (treesit-buffer-root-node language))
|
||||||
|
(nodes (if (eq t treesit--font-lock-fast-mode)
|
||||||
|
(treesit--children-covering-range-recurse
|
||||||
|
root start end (* 4 jit-lock-chunk-size))
|
||||||
|
(list (treesit-buffer-root-node language))))
|
||||||
;; Only activate if ENABLE flag is t.
|
;; Only activate if ENABLE flag is t.
|
||||||
(activate (eq t enable)))
|
(activate (eq t enable)))
|
||||||
(ignore activate)
|
(ignore activate)
|
||||||
|
|
||||||
;; If we run into problematic files, use the "fast mode" to
|
|
||||||
;; try to recover. See comment #2 above for more explanation.
|
|
||||||
(when treesit--font-lock-fast-mode
|
|
||||||
(setq nodes (treesit--children-covering-range-recurse
|
|
||||||
(car nodes) start end (* 4 jit-lock-chunk-size))))
|
|
||||||
|
|
||||||
;; Query each node.
|
;; Query each node.
|
||||||
(dolist (sub-node nodes)
|
(dolist (sub-node nodes)
|
||||||
(let* ((delta-start (car treesit--font-lock-query-expand-range))
|
(let* ((delta-start (car treesit--font-lock-query-expand-range))
|
||||||
(delta-end (cdr treesit--font-lock-query-expand-range))
|
(delta-end (cdr treesit--font-lock-query-expand-range))
|
||||||
(start-time (current-time))
|
|
||||||
(captures (treesit-query-capture
|
(captures (treesit-query-capture
|
||||||
sub-node query
|
sub-node query
|
||||||
(max (- start delta-start) (point-min))
|
(max (- start delta-start) (point-min))
|
||||||
(min (+ end delta-end) (point-max))))
|
(min (+ end delta-end) (point-max)))))
|
||||||
(end-time (current-time)))
|
|
||||||
;; If for any query the query time is strangely long,
|
|
||||||
;; switch to fast mode (see comments above).
|
|
||||||
(when (and (null treesit--font-lock-fast-mode)
|
|
||||||
(> (time-to-seconds
|
|
||||||
(time-subtract end-time start-time))
|
|
||||||
0.01))
|
|
||||||
(if (> treesit--font-lock-fast-mode-grace-count 0)
|
|
||||||
(cl-decf treesit--font-lock-fast-mode-grace-count)
|
|
||||||
(setq-local treesit--font-lock-fast-mode t)))
|
|
||||||
|
|
||||||
;; For each captured node, fontify that node.
|
;; For each captured node, fontify that node.
|
||||||
(with-silent-modifications
|
(with-silent-modifications
|
||||||
|
@ -1023,12 +1022,14 @@ If LOUDLY is non-nil, display some debugging information."
|
||||||
(node (cdr capture))
|
(node (cdr capture))
|
||||||
(node-start (treesit-node-start node))
|
(node-start (treesit-node-start node))
|
||||||
(node-end (treesit-node-end node)))
|
(node-end (treesit-node-end node)))
|
||||||
|
|
||||||
;; If node is not in the region, take them out. See
|
;; If node is not in the region, take them out. See
|
||||||
;; comment #3 above for more detail.
|
;; comment #3 above for more detail.
|
||||||
(if (and (facep face)
|
(if (and (facep face)
|
||||||
(or (>= start node-end) (>= node-start end)))
|
(or (>= start node-end) (>= node-start end)))
|
||||||
(when (or loudly treesit--font-lock-verbose)
|
(when (or loudly treesit--font-lock-verbose)
|
||||||
(message "Captured node %s(%s-%s) but it is outside of fontifing region" node node-start node-end))
|
(message "Captured node %s(%s-%s) but it is outside of fontifing region" node node-start node-end))
|
||||||
|
|
||||||
(cond
|
(cond
|
||||||
((facep face)
|
((facep face)
|
||||||
(treesit-fontify-with-override
|
(treesit-fontify-with-override
|
||||||
|
@ -1036,6 +1037,7 @@ If LOUDLY is non-nil, display some debugging information."
|
||||||
face override))
|
face override))
|
||||||
((functionp face)
|
((functionp face)
|
||||||
(funcall face node override start end)))
|
(funcall face node override start end)))
|
||||||
|
|
||||||
;; Don't raise an error if FACE is neither a face nor
|
;; Don't raise an error if FACE is neither a face nor
|
||||||
;; a function. This is to allow intermediate capture
|
;; a function. This is to allow intermediate capture
|
||||||
;; names used for #match and #eq.
|
;; names used for #match and #eq.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue