Browse Source

Carry the child type on CSharpSlotInfo<T>

Add a generic CSharpSlotInfo<T> (T is the child type, the element type for a
collection) and have the generator emit each per-node slot field as the typed
variant. This lets the typed child accessors infer the result type from the slot,
so the explicit type argument can drop out of the SlotKind-based child API in the
following steps. No behavior change -- the typed slots are still consumed through
the non-generic CSharpSlotInfo base.

Assisted-by: Claude:claude-opus-4-8:Claude Code
pull/3807/head
Siegfried Pammer 3 weeks ago committed by Siegfried Pammer
parent
commit
603d43a8d9
  1. 5
      ICSharpCode.Decompiler.Generators/DecompilerSyntaxTreeGenerator.cs
  2. 16
      ICSharpCode.Decompiler/CSharp/Syntax/CSharpSlotInfo.cs

5
ICSharpCode.Decompiler.Generators/DecompilerSyntaxTreeGenerator.cs

@ -608,9 +608,10 @@ internal class DecompilerSyntaxTreeGenerator : IIncrementalGenerator @@ -608,9 +608,10 @@ internal class DecompilerSyntaxTreeGenerator : IIncrementalGenerator
builder.AppendLine("\t}");
builder.AppendLine();
// One CSharpSlotInfo static per slot; node.Slot compares against these by object identity.
// One typed CSharpSlotInfo<T> static per slot; node.Slot compares against these by object
// identity, and the typed child accessors infer the child type from the slot.
foreach (var s in slots)
builder.AppendLine($"\tpublic static readonly CSharpSlotInfo {s.PropertyName}Slot = new CSharpSlotInfo(\"{s.PropertyName}\", typeof({s.ElementType}), {(s.IsCollection ? "true" : "false")}, SlotKind.{s.KindName}, {(s.IsCollection || s.IsNullable ? "true" : "false")});");
builder.AppendLine($"\tpublic static readonly CSharpSlotInfo<{s.ElementType}> {s.PropertyName}Slot = new CSharpSlotInfo<{s.ElementType}>(\"{s.PropertyName}\", {(s.IsCollection ? "true" : "false")}, SlotKind.{s.KindName}, {(s.IsCollection || s.IsNullable ? "true" : "false")});");
builder.AppendLine();
builder.AppendLine("\tinternal override CSharpSlotInfo GetChildSlotInfo(int index)");

16
ICSharpCode.Decompiler/CSharp/Syntax/CSharpSlotInfo.cs

@ -29,7 +29,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -29,7 +29,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
/// its parent, so <c>node.Slot == X.YSlot</c> identifies a node's position by object identity (the
/// successor to <c>node.Role == X.YRole</c>).
/// </summary>
public sealed class CSharpSlotInfo
public class CSharpSlotInfo
{
/// <summary>The slot's property name, e.g. "Left", "Body", "Parameters".</summary>
public string Name { get; }
@ -64,4 +64,18 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -64,4 +64,18 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
public override string ToString() => Name;
}
/// <summary>
/// A <see cref="CSharpSlotInfo"/> that carries its child type as a type parameter, so the typed
/// child accessors (<c>node.GetChild(SomeNode.XSlot)</c>) infer the result type from the slot
/// instead of needing an explicit type argument. <typeparamref name="T"/> is the child type (the
/// element type for a collection slot).
/// </summary>
public sealed class CSharpSlotInfo<T> : CSharpSlotInfo where T : AstNode
{
internal CSharpSlotInfo(string name, bool isCollection, SlotKind kind, bool isOptional)
: base(name, typeof(T), isCollection, kind, isOptional)
{
}
}
}

Loading…
Cancel
Save