Nimblesite / Nimblesite/SharpLsp
F# sidecar coverage gate has zero headroom and under-reports inlined functions
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 132
- Forks
- 5
- Avg merge
- 6h 24m
- Merged PRs (30d)
- 27
Description
What
The .NET / Sidecars coverage gate now passes, but the F# package clears it by a single line:
[sharplsp-sidecar-fsharp] coverage: 94.0034% (threshold: 95%, effective: 94% with 1pp tolerance)
That is 179 missed lines against 179 allowed. The next F# line added without a covering test turns the gate red.
Why it is fragile beyond the margin
Coverlet under-reports F#: it loses sequence points for small functions the compiler inlines, so lines that demonstrably execute are reported as never hit. Two confirmed examples, both of which run in every one of the 32 passing sidecar rename tests:
FSharpRenameToken.tokenMatchesName— its body is called on every rename viaOption.filter, and reports 0 hits.FSharpRenameIndexers.sameSymbol—IsEffectivelySameAs; a probe proved it executes (isIndexerSymbolreturns true only if it does), and it reports 0 hits.
So an unknown share of the 179 "missed" lines is unreachable by any test. The gate is currently balanced on that artifact rather than on real coverage.
How it got here
FSharpRenameAliases.fs, FSharpRenameIndexers.fs and FSharpRenameToken.fs are new on the cleanup branch — roughly 560 lines of rename machinery whose only tests ran through the VS Code extension host, which the .NET coverage gate does not measure. The F# package fell to 88.77% against an unchanged 95% threshold. It was masked because _check_cov checks C# first and exits on the first failure, so neither the F# nor the Common package was evaluated while C# was red.
Coverage was restored to 94.00% by adding sidecar tests (not by lowering the threshold). This issue is about the remaining fragility.
Suggested fix
One of:
- Exclude or correct the inlined-function attribution so the number reflects reality, then set the threshold from the corrected baseline.
- Set
sharplsp-sidecar-fsharpin.config/coverage/thresholds.jsonto a deliberate value with the artifact documented, instead of leaving it one line from red.
Also worth changing: _check_cov should evaluate all three packages and report every failure, rather than exiting on the first. A masked gate is how this went unnoticed.
Related smaller items
src/sidecars/SharpLsp.Sidecar.FSharp/FSharpRename.fsis 516 LOC, over the 500-line limit in CLAUDE.md. Extracting the foreign-rename/transient-projection block is the natural seam but it depends on six private helpers.FSharpRenameSemanticTests.fs/FSharpCodeActionSemanticTests.fsandHeadlessOverrideGenerationTests.cs/MergeDeclarationAssignmentTests.cseach duplicate a temp-project + code-action harness. A shared harness was started and withdrawn during a concurrent edit; it should be extracted once nothing is in flight.
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 with .config/coverage/thresholds.json and _check_cov, then inspect FSharpRenameToken.fs and FSharpRenameIndexers.fs alongside the 32 sidecar rename tests. Compare the reported coverage with the confirmed inlined-function cases and determine how all three packages are evaluated. Done means the F# baseline and attribution are deliberate and documented, and every package failure is reported.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp, fsharp
- Domain
- build-system, ci-cd, testing-qa
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100