Skip to content

Spec errata: codeanalyzer-dotnet § 4.3 project loading, D7 precedent, and four unrecorded decisions #40

Description

@rahlk

Plan

Spec: docs/design/specs/codeanalyzer-dotnet.md (this repo).

Problem

The codeanalyzer-dotnet datamodel was walked node by node with the maintainer before L1
implementation started. The walk confirmed every decision the spec already records (D1–D16),
but it also surfaced two factual errors in the spec and four decisions the spec never stated.

Left as-is, the spec misleads the next reader on how project loading works, cites a precedent
that does not exist, and omits four schema decisions that are now encoded in the analyzer.

1. § 4.3 misstates what project.assets.json contains.

The spec says its targets section plus packageFolders "produce the absolute path of every
metadata reference, including the framework reference pack". Verified against a real restore
(dotnet new console + one package, SDK 10.0.302): targets carries NuGet packages only. The
framework appears solely as a name under
project.frameworks.<tfm>.frameworkReferences.Microsoft.NETCore.App, with no path.

What the file does carry is project.frameworks.<tfm>.runtimeIdentifierGraphPath, e.g.
~/.dotnet/sdk/10.0.302/PortableRuntimeIdentifierGraph.json, which locates the dotnet root and
therefore the targeting pack at packs/Microsoft.NETCore.App.Ref/<version>/ref/<tfm>/ (167
assemblies on the probed install). D2 is unaffected — no MSBuild is invoked either way — but
the mechanism must be described correctly, because it is the step most likely to fail on an
unusual install layout.

2. D7 cites a TypeScript precedent that does not exist.

D7's comparison column reads "TS accessor_kind + #get/#set keys". codeanalyzer-typescript
v2 does neither: src/schema/v2/model.ts declares accessors as first-class callable kinds,
"getter" | "setter" | "arrow" | "function_expression". The C# decision (dual view, #get /
#set keys, accessor kind: "method") is unchanged and was re-confirmed, but it is a
divergence from TypeScript rather than a match, and the spec should say so.

3. Four decisions are missing.

D17 heritage field shape, D18 top-level statements, D19 attributes, D20 call-site keying. All
four were decided in the walk and are recorded in codeanalyzer-dotnet/.claude/SCHEMA_DECISIONS.md;
the spec is the provenance record and should carry them too.

Scope boundary

In:

  • Rewrite § 4.3 step 2 to describe package resolution and targeting-pack discovery separately,
    and to name runtimeIdentifierGraphPath as the dotnet-root signal.
  • Correct D7's precedent column and add a sentence recording the divergence from
    codeanalyzer-typescript's getter/setter kinds.
  • Add D17–D20 to § 3, with the rationale and the known loss each carries.
  • Note in § 8 that D17 and D19 are two further points where the mature analyzers disagree with
    the keystone and with each other.

Out:

  • Any change to a decision already recorded. This is an accuracy pass on the record, not a
    redesign.
  • Reconciling codeanalyzer-typescript to any of these answers — still its own design session.

Goals

  • § 4.3 step 2 rewritten; targeting-pack discovery described
  • § 4.3 gains the failure mode for an undiscoverable targeting pack
  • D7 precedent column corrected; divergence recorded
  • D17 heritage: base_types[] / interfaces[], ids where resolvable, externals dropped
  • D18 top-level statements: synthesized Program type, functions{} always empty
  • D19 attributes: structured decorators[{name, args[], span}], named args flattened
  • D20 call keys: line:col, /k on collision
  • § 8 updated with the two new sibling divergences

Caveats and known risks

  • The targeting-pack path is now load-bearing and undocumented by Microsoft as an API. The
    packs/ layout is an implementation detail of the SDK install. A layout change breaks
    reference resolution for every analyzed project at once. The spec should say this plainly so
    the fallback is designed rather than discovered.
  • runtimeIdentifierGraphPath is not guaranteed present. It appeared on SDK 10.0.302; older
    restores may omit it, leaving DOTNET_ROOT and PATH as the only signals.
  • This issue edits the design record after implementation began. The four added decisions are
    already encoded in codeanalyzer-dotnet; the spec is catching up to the analyzer, which is
    the wrong direction and worth noting so it is not treated as normal.

Definition of done

  • docs/design/specs/codeanalyzer-dotnet.md describes reference resolution in terms a reader can
    reproduce against a real obj/project.assets.json, with no claim that the file carries
    framework paths.
  • D7's precedent column matches what codeanalyzer-typescript/src/schema/v2/model.ts actually
    declares.
  • § 3 carries D1–D20; the numbering in the spec and in
    codeanalyzer-dotnet/.claude/SCHEMA_DECISIONS.md agree, decision for decision.
  • No decision text changed other than the two corrections and the four additions.

Metadata

Metadata

Assignees

No one assigned

    Labels

    documentationImprovements or additions to documentation

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions