[ty] Emit folding ranges for an entire block from the language server. (#25113)
<!--
Thank you for contributing to Ruff/ty! To help us out with reviewing,
please consider the following:
- Does this pull request include a summary of the change? (See below.)
- Does this pull request include a descriptive title? (Please prefix
with `[ty]` for ty pull
requests.)
- Does this pull request include references to any relevant issues?
- Does this PR follow our AI policy
(https://github.com/astral-sh/.github/blob/main/AI_POLICY.md)?
-->
## Summary
<!-- What's the purpose of the change? What does it do, and why? -->
Building on https://github.com/astral-sh/ruff/pull/25118, this adds a
folding range to every block that allows the user to fold the entire
block (i.e., it's header and its body). This supplements the now nested
inner range for just the block body, thereby allowing a user to fold
either the entire block or just the block body.
For example, the diagram below shows where folding triggers appear for a
function definition with a multi-line param list and a multi-line body:
```py
def foo(
^
bar,
baz,
):
^
qux = bar + baz
return qux
```
When a user clicks the first folding trigger the entire function folds
as:
```py
def foo(...
```
and the second folding trigger is hidden. But when a user clicks the
second folding trigger first, we show the following (the first folding
trigger is still accessible for an additional fold):
```py
def foo(
^
bar,
baz,
): ...
```
After which you could fold again to get:
```py
def foo(...
```
This second scenario is also accessible via a sequence of the "Fold
Level 2" and "Fold Level 1" commands exposed by many editors (e.g., VS
Code, Zed).
Closes https://github.com/astral-sh/ty/issues/3320.
## Test Plan
- I have also tested this manually in VS Code and Zed (see
[below](https://github.com/astral-sh/ruff/pull/25113#issuecomment-4437228675)).
- I have updated unit tests and e2e tests in this PR.
<!-- How was it tested? -->