Skip to content

Collapsible chained expressions (Method and Field Chains) #19620

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
PRO-2684 opened this issue Apr 18, 2025 · 2 comments · May be fixed by #19659
Open

Collapsible chained expressions (Method and Field Chains) #19620

PRO-2684 opened this issue Apr 18, 2025 · 2 comments · May be fixed by #19659
Assignees
Labels
A-ide general IDE features C-feature Category: feature request

Comments

@PRO-2684
Copy link

PRO-2684 commented Apr 18, 2025

Summary

Add support for collapsing/folding chained expressions in rust-analyzer to improve code readability and navigation in editors.

Problem

Currently, rust-analyzer does not provide a folding option for chained expressions, which are sequences of method calls or field accesses connected by the dot operator (.). For example:

Image

In the editor, there is no folding arrow (or equivalent UI element) before the let statement to collapse this method chain into a single line, unlike other foldable constructs such as blocks or match expressions. This limitation makes it harder to navigate and read code with long chained expressions, especially in complex expressions.

Proposal

Introduce support for collapsing chained expressions in rust-analyzer. When a method chain spans multiple lines, rust-analyzer should:

  1. Display a folding arrow in the editor gutter at the start of the chain (e.g., before the let statement in the example above).
  2. Allow collapsing the entire chain into a single line, such as:
    let a = b.c.d.e();
  3. Preserve the original formatting when expanding the chain back to its multi-line form.

This feature would align with existing folding capabilities for other Rust constructs and improve the editing experience for codebases with frequent method chaining, such as those using iterator patterns.

Use Case

Consider the following code:

let result = collection
    .iter()
    .filter(|x| x > 0)
    .map(|x| x * 2)
    .collect::<Vec<_>>();

With the proposed feature, users could collapse this chain to:

let result = collection.iter().filter(...).map(...).collect::<Vec<_>>();

This would reduce visual clutter and make it easier to focus on surrounding code, especially in larger functions or modules.

Alternatives

To simplify implementation, rust-analyzer could support alternative collapsing formats that are less complex than fully inlining the chain. These include:

  1. Truncated Prefix with Ellipsis: Collapse the chain to the base expression followed by an ellipsis (...).

    • Example: let result = collection...;
    • Benefit: Minimizes visual clutter and is easy to implement by identifying the base expression.
  2. Base Expression with Chain Indicator: Collapse the chain to the base expression with a placeholder like <chain> to indicate a chain exists.

    • Example: let result = collection.<chain>;
    • Benefit: Signals the presence of a chain without parsing its contents.
  3. First Method/Field with Ellipsis: Collapse the chain to the base expression plus the first method call or field access, followed by an ellipsis.

    • Example: let result = collection.iter()...;
    • Benefit: Preserves context about the chain's starting point while remaining simple.
  4. Type-Informed Collapse: Collapse the chain to the base expression and the resulting type (if available), indicating the chain's outcome.

    • Example: let result = collection -> Vec<_>;
    • Benefit: Provides meaningful context about the chain's purpose, leveraging rust-analyzer's type inference.
    • Note: This alternative may not be so useful if type hints are enabled.

These alternatives reduce the complexity of handling complex method arguments (e.g., closures or generics) and provide flexible options for users to customize folding behavior.

@PRO-2684 PRO-2684 added the C-feature Category: feature request label Apr 18, 2025
@ChayimFriedman2
Copy link
Contributor

The 2nd request is problematic. Folding cannot change the source code, and we'll have major troubles if it did, even via a protocol extension. Perhaps we can somehow show this as an inlay hint, but I don't think we have a way on inlay hints to know the line is folded.

@roife roife added the A-ide general IDE features label Apr 21, 2025
@roife
Copy link
Member

roife commented Apr 21, 2025

There's a field called collapsedText in the response to the FoldingRange request, but it seems that VS Code did not implement this feature 😂 (nvim might have). This could potentially be used for the 2nd request.

@roife roife self-assigned this Apr 22, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-ide general IDE features C-feature Category: feature request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants