Subject: bug#75387: 29.4; hideshow: hs-hide-level hides multiple top-level blocks as one

From: kobarity <[email-masked]>
Date: Mon, 13 Jan 2025 22:46:54 +0900

kobarity wrote:
> I confirmed the same behavior.  This is not a problem in hideshow.el.
> Only immediately after the file is read, `python-nav-end-of-block'
> behaves unexpectedly.
> 
> 1. emacs -Q
> 2. Find file builder.py
> 3. Search "class SiteFamily" and go there
> 4. M-x python-nav-end-of-block  
> 5. Search "class Symmetry" and go there
> 6. M-x python-nav-end-of-block
> 
> The point moves to the end of the buffer, which is not an expected
> behavior.  However, repeating the steps 5 and 6 does not produce this
> issue.
> 
> This is the direct cause of the problem of `hs-hide-level'.
> 
> This problem does not occur when I run `font-lock-debug-fontify' after
> reading the file, so it might be related to font-lock code in
> python.el, but it seems that disabling font-lock does not solve this
> issue.  I will continue to look into this, but it may take some time.

I think I've found the root cause.  `python-nav-end-of-statement' may
fail to find the end of a long triple-quoted string when the buffer is
"fresh".  It uses the following code to find the end of a
triple-quoted string:

(re-search-forward (rx (syntax string-delimiter)) nil t)

However, the syntax is not always fully propertized.  If the end of
the long multi-line string and beyond are not yet propertized, the
above search fails and `python-nav-end-of-statement' moves the point
to the end of the buffer.

In case of builder.py, `python-nav-end-of-statement' fails to find the
end of the long docstring.  This results in `python-nav-end-of-block'
moving point to the end of the buffer, which causes `hs-hide-level' to
hide multiple blocks as one.

Attached is a patch to fix this issue.  I changed the above search to
searching for triple-quotes and checking syntax.  Checking syntax
involves `syntax-ppss' and syntax properties up to the point are
updated.