Subject: bug#59415: 29.0.50; [feature/tree-sitter] c-ts-mode fails to fontify a portion of a large C file

From: Theodor Thornhill <[email-masked]>
Date: Mon, 21 Nov 2022 12:00:37 +0100

Yuan Fu <[email-masked]> writes:

>> On Nov 20, 2022, at 1:56 PM, Theodor Thornhill via Bug reports for GNU Emacs, the Swiss army knife of text editors <[email-masked]> wrote:
>> 
>>>> 
>>>> I appreciate the explanation.  I think getting the root is a bit
>>>> excessive.  I got the same results as you in the capture.  Maybe reuse
>>>> the treesit-defun-type-regexp, and default to root if none found?
>>> 
>>> I tried the "top-level node” approach, and it didn’t help in
>>> package-rrc.c: the top-level node (a function definition) is still too
>>> large (spans 7680306-9936062). Since the case I described in the
>>> comment against using treesit-node-on is the exception rather than the
>>> norm, maybe we can go the other way around: use treesit-node-on first,
>>> and if the node seems too small (by some heuristic), enlarge it to
>>> some degree.
>>> 
>> 
>> Makes sense!
>
> I pushed a change that uses treesit-node-on. Now scrolling in most
> parts of the buffer is pretty fast. Scrolling around 194770 is still
> laggy, because the node we get from treesit-node-on is still too
> large. I tried some heuristics but they didn’t work very well, IMO
> because tree-sitter couldn’t parse that part of the code very
> well. The code should observe a structure like {{}, {}, {}, {}, {}, …}
> where there are tens thousands of inner brackets, so ideally we only
> need to grab the {}’s in the region we want to fontify. But
> tree-sitter seems to understand it in some weird structure and we
> still end up with very large nodes, which is far larger than the
> region we want to fontify and is slow to query.
>
> I’ll try to improve it further in the future, but for now I think it’s
> good enough (because in most cases fontification is pretty fast).
>
> Also I think we should probably disable fontifying errors in C. C’s
> macros just create too much errors.

Good job.  I ran this in both c-ts-mode and c-mode on the same file:

(defun scroll-up-benchmark ()
  (interactive)
  (let ((oldgc gcs-done)
        (oldtime (float-time)))
    (condition-case nil (while t (scroll-up) (redisplay))
      (error (message "GCs: %d Elapsed time: %f seconds"
                      (- gcs-done oldgc) (- (float-time) oldtime))))))

c-ts-mode: GCs: 87 Elapsed time: 135.700742 seconds

c-mode: GCs: 224 Elapsed time: 133.329396 seconds

Font locking seems correct too.

Theo