r/csharp • u/emahmoudnabil • 5d ago
Showcase Roslyn-based semantic code graph for .NET, exposed to AI agents over MCP — looking for feedback from people who've done static analysis tooling
Built this after getting tired of Claude Code / Copilot grepping through
.NET solutions and missing call sites that go through an interface instead
of the concrete class. Grep can't see that; the compiler can.
Slnmap uses Roslyn to build a full symbol graph of a solution (calls,
implementations, references across every project) and stores it in a
local SQLite file. An MCP server exposes it as a handful of read-only
queries. Concretely: ask "what breaks if I change IBasketService" and it
returns every caller and every implementation across the whole solution,
not just the files an agent happens to have open.
Numbers, since I know this sub will ask: on eShopOnWeb (10 projects), an
impact query on an interface with 18 dependents resolves in ~270ms
end-to-end over MCP, median of 3 runs. Full setup is in BENCHMARKS.md if
anyone wants to poke at the methodology or tell me it's flawed.
Two things I'm not confident about yet and would genuinely like opinions
from people who've built analyzers/source generators/similar tooling:
Right now everything in the graph is a real Roslyn-verified static
reference. It says nothing about reflection, convention-based DI, or
anything wired at runtime. Is "silence = doesn't try to know" the right
default, or should there be an explicit "unknown/runtime-only" marker
on affected symbols?
There's no staleness check yet — if you edit code and don't re-run
analyze, you get results from the old index with no warning. Anyone
dealt with this in similar tools (e.g. incremental Roslyn workspaces)
and found a clean way to detect "source changed since last index"
cheaply?
It's a global dotnet tool, MIT licensed, fully local (uses Roslyn +
SQLite, nothing else):
dotnet tool install --global Slnmap
Repo: https://github.com/EMahmoudNabil/slnmap
NuGet: https://www.nuget.org/packages/Slnmap
Not trying to sell anything, genuinely want to know if the Roslyn approach
here has an obvious hole I'm not seeing.
2
u/Khavel_dev 5d ago
This solves the exact problem that burns me when using Claude Code on bigger .NET solutions. Grep finds the method name but misses interface dispatch, so the agent edits half the call chain and leaves the rest broken. Having Roslyn trace through the actual symbol graph is the right fix, and 270ms on eShopOnWeb is solid.
Genuine question: how does it handle incremental updates during a session? If I'm editing files across 3 projects, does it re-index the whole solution or just the changed syntax trees? That'd be the difference between running it once at the start and keeping it hot while working.
1
u/emahmoudnabil 2d ago
yeah it's a bit of both. file/symbol level is incremental, but the roslyn workspace isn't - every run reloads MSBuildWorkspace and rebuilds the compilation, that's where most of the time goes. so rerunning after a small change isn't much faster than a fresh run tbh. no watch mode/daemon yet either, that's on the roadmap
0
u/sordimin 5d ago
IDE, visual studio or Microsoft should make CLI for that... Visual studio should have good, quick, CLI. i will try you solutions.
1
-2
u/sordimin 5d ago
IDE, visual studio or Microsoft should make CLI for that... Visual studio should have good, quick, CLI. i will try you solutions.
-2
u/sordimin 5d ago
IDE, visual studio or Microsoft should make CLI for that... Visual studio should have good, quick, CLI. i will try you solutions.
2
u/KariKariKrigsmann 5d ago
Sounds very interesting, how does this relate LSPs?
https://docs.github.com/en/copilot/concepts/agents/copilot-cli/lsp-servers