samchon / samchon/compiler-knowledge-graph

[Bulk index][C#] Wrap scip-dotnet and Roslyn Workspaces for solution snapshots

Open
#75 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

enhancement
Dominant language
TypeScript
Stars
6
Forks
3
PR merge metrics
No merged PRs in 30d

Description

Outcome

Replace scip-dotnet repair/post-processing with a resident Roslyn semantic
service. Open the real solution once through MSBuildWorkspace, capture one
immutable Solution, walk syntax/semantic/IOperation data once, and export
changed project/document shards. Keep scip-dotnet only as an optional
navigation fallback.

Current master baseline

Current master registers scip-dotnet, but the strict grounding rules claim
zero edge families. Stock scip-dotnet omits enclosing attribution, kinds,
diagnostics and role information required by the graph. Its relationships
flatten transitive ancestry, and its identities have known namespace, generic
arity, project/assembly and declaration-order problems.

The PR #147 Serilog cold cell took 20.498 s, versus 25.085 s with
generic csharp-ls. The small speed difference does not compensate for the
semantic omissions, and no resident edit/no-op measurement exists.

Why Roslyn is the final route

The official
Roslyn workspace model
already represents the solution, projects, documents, parse/compilation
options, project references, syntax trees, semantic models and compilations.
Workspace.CurrentSolution is updated on changes; each captured Solution is
immutable and safe to analyze in isolation.

Roslyn also exposes the exact semantic operations the graph needs:
invocations, object creation, field/property/event references, assignments,
conversions, patterns and attributes through IOperation and symbols.
Running scip-dotnet and then a Roslyn sidecar would open/resolve the solution
twice. The Roslyn service can emit everything scip-dotnet can, with stronger
identity and incremental behavior, so it should be the preferred provider.

Service architecture

Build a pinned .NET sidecar/service:

  1. register the matching MSBuild instance before opening;
  2. open .sln, .slnx, or explicitly selected projects in one
    MSBuildWorkspace;
  3. await workspace diagnostics and capture one immutable Solution;
  4. topologically process each configured project/target framework;
  5. for each source document, walk declarations and operations once and write a
    document shard;
  6. write project relationship/generated-source shards; and
  7. atomically commit only if CurrentSolution and build inputs still match.

Subscribe to WorkspaceChanged and debounce changes. Never keep mutable
compiler handles in the serialized graph. On refresh, capture the new solution
and use solution/project/document changes to bound re-export.

Source generators are part of the semantic universe. Include generated
documents and generator diagnostics with explicit origin; generator, SDK,
props/targets or analyzer changes may invalidate a whole project.

Fact extraction

  • declarations and containment from ISymbol plus every
    DeclaringSyntaxReference;
  • namespace/project exports and using/alias imports;
  • calls from IInvocationOperation.TargetMethod, including reduced extension
    methods and constructed generic methods;
  • construction from IObjectCreationOperation and relevant implicit object
    creation;
  • read/write accesses from field/property/event/local/parameter operations and
    assignment/ref context;
  • type references and conversions from operation/type info;
  • direct base type, direct interfaces, implementations and overridden members;
  • attributes and their constructor/type plus annotated target;
  • compiler/analyzer/generator diagnostics; and
  • framework tests only through a named xUnit/NUnit/MSTest enricher.

Interface/virtual calls are not automatically executed-target edges.
TargetMethod is the selected declaration; publish candidate implementations
as unresolved candidates unless sealed/final/internal-world analysis proves a
single runtime target.

Identity

For source-declared public/member symbols use:

assembly identity + target framework + DocumentationCommentId + symbol kind.

Documentation IDs encode full namespace, generic arity and overload parameter
types and are independent of declaration order. Add explicit handling for:

  • partial declarations: one symbol ID, all declaration spans;
  • partial methods: link definition and implementation parts;
  • records and synthesized members;
  • reduced extension methods: canonicalize to the original definition while
    preserving call evidence;
  • constructed generics: retain original definition plus type arguments as call
    evidence rather than duplicate declaration nodes;
  • locals/parameters/local functions: file + containing stable member +
    structural lexical identity; and
  • anonymous functions/types: generation-scoped structural identity with an
    explicit identity-unstable coverage record if position invariance cannot be
    proven.

Do not adopt scip-dotnet's package ".", truncated namespace, dropped arity or
+N overload key. Exact regression fixtures cover same suffix namespaces,
Foo/Foo<T>, same namespace/type across two projects, partial types and
overload insertion/reordering.

Build universe

Include solution/project graph, assembly identity, target framework and runtime
identifier, configuration/platform, SDK/global.json, language version,
nullable/unsafe/defines, parse and compilation options, project/metadata
references, NuGet lock/config, Directory.Build/Packages props/targets,
analyzers/source generators and generated document digests.

Multi-targeting projects produce separate target universes. Do not merge facts
from net8.0 and net10.0 merely because the source path matches.

Incremental and lifecycle behavior

  • no-op: reuse the immutable solution/generation or validated disk shards;
  • document body edit: use the new solution and re-export changed/affected
    documents;
  • public/API/project-reference change: re-export the changed project and
    dependent-project closure;
  • props/targets/SDK/restore change: reopen affected projects/solution;
  • generator/analyzer change: invalidate generated and consuming shards;
  • delete/rename: explicit shard deletion; and
  • workspace diagnostics, cancel, crash or solution movement: retain the prior
    committed graph.

Do not call dotnet restore on every refresh. Preparation may restore when
assets are absent or stale, under an explicit policy, then record exactly what
was used.

Implementation map

  1. Implement the #63 shard/coverage contract.
  2. Add a versioned .NET service under a dedicated sidecar directory with an
    exact protocol handshake.
  3. Add a Roslyn provider ahead of scip-dotnet in GRAPH_PROVIDERS only after
    its solution-selection gate passes.
  4. Add fake protocol/lifecycle tests and a real multi-project/multi-target
    fixture.
  5. Keep scip-dotnet as an explicitly limited fallback; do not attempt to merge
    its ordinal identities with Roslyn identities.
  6. Measure native solution load, export, merge, no-op and edit phases
    independently.

Acceptance

  • Exact fixtures cover .sln/.slnx, multiple projects, target frameworks,
    project references, partial types/methods, records, generics, overloads,
    constructors, extension methods, attributes, nullable context, source
    generators and tests.
  • Namespace suffix, generic arity, assembly and overload-order collisions
    are impossible.
  • Direct inheritance/override edges are not replaced by a transitive
    closure.
  • All 15 fact families have explicit coverage/unresolved rows.
  • No-op, document/API edit, create/delete/rename, project/TFM/config/restore,
    generator change, diagnostic, cancel, crash and retry are atomic.
  • The strict route opens/resolves the solution once and issues no
    per-symbol LSP requests.
  • Cold time is compared with native MSBuildWorkspace solution load;
    resident no-op target is below 250 ms and body edit target below 2 s on
    the pinned fixture.
  • Windows, Linux and macOS SDK/MSBuild selection and fallback are tested.
  • Focused tests, C# experiment, pnpm build, pnpm test, and
    pnpm coverage pass.

Primary references

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 #63 shard/coverage contract and the GRAPH_PROVIDERS solution-selection path, then review the dedicated sidecar directory and the required protocol and lifecycle behavior. Done means the Roslyn route satisfies the listed fixture, incremental, atomicity, platform, performance, and coverage acceptance criteria; validate with focused tests, pnpm build, pnpm test, and pnpm coverage.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp, typescript
Domain
compilers, devtools
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.