Nimblesite / Nimblesite/SharpLsp
F# folding: the `open` and `xml_doc` arms in collect_folding are dead code
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 132
- Forks
- 5
- Avg merge
- 6h 24m
- Merged PRs (30d)
- 27
Description
Summary
src/sharplsp/src/syntax.rs collect_folding gained F# node kinds on PR #218. Two of the new match arms can never produce a fold:
// Comments: C# `comment`, F# `block_comment` ((* *)) and `xml_doc` (///) — multi-line only.
"comment" | "block_comment" | "xml_doc"
if node.start_position().row != node.end_position().row => { ... }
// Using directives group (C# `using_directive`, F# `open`)
"using_directive" | "open" => Some(FoldingRangeKind::Imports),
1. "open" matches a keyword token, not a declaration node
In tree-sitter-fsharp 0.3.11 (fsharp/src/node-types.json), open is "named": false — it is the bare open keyword token. The F# import declaration node is import_decl ("named": true, one long_identifier child).
The open keyword token always spans exactly one line, so start.row < end.row in the emit guard is never true. The arm is unreachable in effect.
2. "xml_doc" never spans more than one line
The grammar emits one xml_doc node per /// line, so a multi-line doc block is N single-line nodes, and the start_position().row != end_position().row guard is never satisfied. The arm is dead too.
Reproduction
Adding to the fixture in test_folding_range_on_fsharp_file (src/sharplsp/tests/e2e_modules/folding.rs):
module M
open System
(* a multi-line
block comment *)
/// Computes the area of a shape.
/// The doc block spans two lines, so it folds.
type Shape =
...
textDocument/foldingRange returns 4 ranges — three region folds and exactly one comment fold (the (* *) block, lines 2–3). There is no imports fold for open System and no comment fold for the two /// lines.
The existing assertion passes only because kinds.contains(&"comment") is satisfied by the (* *) block alone.
Expected
- Consecutive
///(xml_doc) sibling nodes should merge into a singlecommentfold spanning the run — this is what Visual Studio / Rider / C# Dev Kit do for///blocks, and F# is a first-class citizen (CLAUDE.md aim #2). - Consecutive
import_decl(F#) /using_directive(C#) siblings should merge into a singleimportsfold. Note the C# side has the same latent problem: a one-lineusing X;also fails thestart.row < end.rowguard, soFoldingRangeKind::Importsis likely never emitted for either language today.
Both need sibling-run grouping in collect_folding, not just a node-kind rename.
Notes
Coverage does not catch this: the arms share instrumented lines with live arms, so the file reports 220/224 lines covered on both Linux CI and macOS.
Found while auditing PR #218's Rust coverage gate.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in src/sharplsp/src/syntax.rs at collect_folding and inspect how sibling nodes are traversed and folding ranges are emitted. Reproduce the behavior with the fixture in src/sharplsp/tests/e2e_modules/folding.rs, then extend coverage for consecutive xml_doc and import_decl/using_directive nodes. Done means consecutive documentation and import declarations produce the expected comment and imports ranges.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp, rust
- Domain
- devtools
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 68/100