Each child of a C# AST node is declared as a [Slot] partial property, and the
source generator emits the accessor bodies and an ordered slot schema
(SlotCount/GetSlotRole/IsCollectionSlot) from them. Generating the schema
keeps slot order from being mis-stated by hand and lets a DEBUG invariant
check declared slot order against document order on every decompile. The node
hierarchy is converted family by family; the EntityDeclaration leaves flatten
their inherited Attributes/ReturnType/NameToken into each leaf's ordered slot
set. Storage stays the NRefactory linked list at this stage, so only the
declaration model changes and output is unchanged.
Assisted-by: Claude:claude-opus-4-8:Claude Code
The generator emits the IAstVisitor interface, the AcceptVisitor overloads,
and the null-node and pattern-placeholder nodes from [DecompilerAstNode]
declarations, so drop the hand-written equivalents across the C# AST: per-node
AcceptVisitor/DoMatch, the #region Null / #region PatternPlaceholder blocks,
IAstVisitor.cs, and now-dead usings. Also adds AccessorKind and moves
IdentifierExpressionBackreference into the PatternMatching folder.
Assisted-by: Claude:claude-opus-4-8:Claude Code
Introduce a Roslyn source generator that emits the visitor boilerplate for
the C# AST from [DecompilerAstNode]-tagged node declarations: the
IAstVisitor interface, the AcceptVisitor overloads, the pattern-placeholder
nodes, and the initial DoMatch support. AccessorKind lets an accessor's
keyword be chosen independently of its role, an early step toward shedding
the NRefactory role model.
The C# AST inherited NRefactory's freezable model (IFreezable, Freeze,
IsFrozen, a frozen flag bit, and ThrowIfFrozen guards on every mutator),
but the decompiler never uses it: nothing calls Freeze(), not even the
generated null-node singletons, so every IsFrozen guard only ever
evaluated false. The decompiler is single-threaded and never shares or
freezes nodes. Remove the whole apparatus as preparation for the
slot-based AST rewrite, which has no place for it. Roles are untouched
here, so the flags word keeps its role index; only the freed frozen bit
goes away.