Nimblesite / Nimblesite/SharpLsp

[Bug]: .editorconfig severity overrides are read once at load and never refreshed

Open
#238 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug
Dominant language
TypeScript
Stars
132
Forks
5
Avg merge
6h 24m
Merged PRs (30d)
27

Description

What happened?

.editorconfig severity overrides are read once, when the sidecar first loads the solution, and never again. Editing .editorconfig in a running session has no effect on published diagnostics until the language server is restarted.

Concretely: test-fixtures/workspace/.editorconfig sets

[*.{cs,vb}]
dotnet_diagnostic.CS0219.severity = error

and Refactor.cs has an unused local. dotnet build agrees and emits error CS0219. The live session keeps showing it as a warning.

This directly violates [DIAG-LSP-REFRESH], which already lists .editorconfig file change inside the solutionas a required refresh trigger, and the project's "100% reactive" hard rule inCLAUDE.md`.

Root cause

Nothing in the stack observes .editorconfig:

  1. No file watcher covers it. The only two globs in the extension are
    • src/editors/vscode/src/extension.ts:646const SOLUTION_FILE_GLOB = '**/*.{sln,slnx}';
    • src/editors/vscode/src/project-deps-store.ts:18const WATCH_GLOB = '**/{*.csproj,*.fsproj,Directory.Packages.props}';
  2. The Rust host registers no workspace/didChangeWatchedFiles handler at allgrep -rn "DidChangeWatchedFiles" src/sharplsp/src/ returns nothing.
  3. The sidecar never mutates its analyzer config. WithAnalyzerConfigDocumentText / AnalyzerConfigDocument appear nowhere in C# sidecar production code. WorkspaceManager.GetDiagnosticsAsync (src/sidecars/SharpLsp.Sidecar.CSharp/Workspace/WorkspaceManager.cs:227) reads through MapDiagnosticsmodel.GetDiagnostics() (.../WorkspaceManager.Helpers.cs:23) against the long-lived MSBuildWorkspace solution, whose AnalyzerConfigDocument text is a snapshot from load time.

So the severity is baked into the compilation at load and stays there.

Evidence

Roslyn itself is not at fault — it honours the file correctly on the exact code path the sidecar uses. Standalone probe against TestFixtures.csproj with the same package versions (Microsoft.CodeAnalysis 5.3.0, Microsoft.Build.Locator 1.11.2):

AnalyzerConfigDocuments: 3
  ACD: C:\Code\SharpLsp\.editorconfig
  ACD: ...\test-fixtures\workspace\.editorconfig
  ACD: ...\obj\Debug\net10.0\TestFixtures.GeneratedMSBuildEditorConfig.editorconfig
--- model.GetDiagnostics() (what MapDiagnostics uses) ---
  CS0219 severity=Error defaultSeverity=Warning isWarnAsError=True
SyntaxTreeOptionsProvider: Microsoft.CodeAnalysis.ProjectState+ProjectSyntaxTreeOptionsProvider

And the staleness itself, reproduced against a long-lived MSBuildWorkspace — the sidecar's exact lifetime model:

1. editorconfig says error -> live server reports: Error
2. editorconfig now says none -> live server STILL reports: Error
3. after restart (fresh load) -> reports: <absent>

AnalyzerConfigDocument text held by the live workspace after the edit:
  root = true |  | [*.cs] | dotnet_diagnostic.CS0219.severity = error |

Step 2 is the bug: the file on disk said none, the workspace still served Error, and the AnalyzerConfigDocument still held the pre-edit text.

dotnet build on the fixture, for comparison:

Refactor.cs(7,20): error CS0219: The variable 'unused' is assigned but its value is never used
    1 Warning(s)
    1 Error(s)
Steps to reproduce
  1. Open src/editors/vscode/test-fixtures/workspace and let the server load TestFixtures.sln.
  2. Open Refactor.csCS0219 is reported at its default severity, Warning.
  3. Add dotnet_diagnostic.CS0219.severity = error under [*.{cs,vb}] in that folder's .editorconfig and save.
  4. Edit and save Refactor.cs to force a re-pull.
  5. Observed: CS0219 is still a Warning.
    Expected: it becomes an Error, matching dotnet build.
  6. Restart the language server — it now reports Error, confirming the value is only ever read at load.
Scope

The same staleness class applies to every build-input file the workspace snapshots but nothing watches: .editorconfig, Directory.Build.props / .targets, global.json, and .globalconfig. A fix should cover the family, not just .editorconfig.

The F# sidecar should be checked separately — FCS does not consume dotnet_diagnostic.*.severity the way Roslyn does, so the parity story for F# needs its own answer rather than being assumed fixed by the C# change.

Suggested fix
  1. Watch **/.editorconfig (and the siblings above) in the extension, or — better, since it is editor-agnostic — register workspace/didChangeWatchedFiles from the Rust host so every editor gets it.
  2. On change, have the sidecar apply Solution.WithAnalyzerConfigDocumentText(...) for a known document, or reload the project when the file is new/deleted.
  3. Emit the diagnostics/refresh IPC notification so the host sends workspace/diagnostic/refresh, per [DIAG-LSP-REFRESH].
  4. Cover it with a coarse e2e test: load the fixture, assert CS0219 is a Warning, rewrite .editorconfig to error, assert it becomes an Error without a restart.
Note on the pasted marker

The Problems entry that surfaced this carries "owner": "msCompile", "source": "cpp" — that is VS Code's built-in $msCompile task problem matcher, i.e. a marker left by a dotnet build task, not a SharpLsp diagnostic (SharpLsp tags its own sharplsp-csharp / sharplsp-fsharp, src/sharplsp/src/diagnostics.rs:537). That particular row is a stale build marker. The SharpLsp defect above is separate and independently reproduced.

Component

C# sidecar (Roslyn) — with a required piece in the Rust LSP host and/or VS Code extension.

Language

C# (F# needs a separate assessment, see Scope)

SharpLsp version

0.1.0

Editor & OS

VS Code, Windows 11 (26200), .NET SDK 10.0.303

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the [DIAG-LSP-REFRESH] requirements and inspect extension.ts, project-deps-store.ts, the Rust host under src/sharplsp/src/, and WorkspaceManager.cs plus WorkspaceManager.Helpers.cs. Reproduce the fixture workflow with Refactor.cs and .editorconfig, then trace watched-file handling, workspace updates, and diagnostics refresh. Done means build-input changes refresh diagnostics without restart, with the suggested C# end-to-end coverage and a separate F# assessment.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp, rust, typescript, vscode
Domain
developer-experience, devtools, testing-qa
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.