Browse Source

Surface the type-forwarder bit in the flags filter schema

The schema inferer only walks the enum's declared fields, so the
ECMA-335 Forwarder bit (0x00200000, no member in
System.Reflection.TypeAttributes) was invisible to the per-column
flags filter even though the cell tooltip already shows it. An
explicit per-enum extras table appends it as an independent flag,
making forwarders filterable on the ExportedType table.

Assisted-by: Claude:claude-fable-5[1m]:Claude Code
pull/3759/head
Siegfried Pammer 4 weeks ago
parent
commit
858c2e77c3
  1. 12
      ILSpy.Tests/Metadata/FlagsSchemaInfererTests.cs
  2. 13
      ILSpy/Metadata/FlagsSchemaInferer.cs

12
ILSpy.Tests/Metadata/FlagsSchemaInfererTests.cs

@ -112,6 +112,18 @@ public class FlagsSchemaInfererTests @@ -112,6 +112,18 @@ public class FlagsSchemaInfererTests
schema.IndependentFlags.Select(f => f.Name).Should().NotContain("LayoutMask");
}
[Test]
public void TypeAttributes_Includes_The_Type_Forwarder_Bit()
{
// 0x00200000 is the ECMA-335 Forwarder bit (II.23.1.15), set on type-forwarder
// ExportedType rows. System.Reflection.TypeAttributes has no member for it, so the
// enum field walk alone would leave forwarders unfilterable in the flags filter.
var schema = FlagsSchemaInferer.For(typeof(TypeAttributes));
schema.IndependentFlags.Should().ContainSingle(f => f.Name == "IsTypeForwarder")
.Which.Bit.Should().Be(0x00200000u);
}
[Test]
public void MethodAttributes_Has_Member_Access_Mutex_Plus_Independent_Modifiers()
{

13
ILSpy/Metadata/FlagsSchemaInferer.cs

@ -36,6 +36,16 @@ namespace ILSpy.Metadata.Filters @@ -36,6 +36,16 @@ namespace ILSpy.Metadata.Filters
{
static readonly ConcurrentDictionary<Type, FlagsSchema> cache = new();
/// <summary>
/// Bits that exist in ECMA-335 but have no member in the runtime's enum, so the
/// field walk cannot surface them. Appended to the inferred independent flags.
/// </summary>
static readonly Dictionary<Type, IndependentFlag[]> extraFlags = new() {
// ECMA-335 II.23.1.15 Forwarder: set on ExportedType rows that forward the
// type to another assembly.
[typeof(TypeAttributes)] = [new IndependentFlag("IsTypeForwarder", 0x00200000)],
};
public static FlagsSchema For(Type enumType)
{
ArgumentNullException.ThrowIfNull(enumType);
@ -90,6 +100,9 @@ namespace ILSpy.Metadata.Filters @@ -90,6 +100,9 @@ namespace ILSpy.Metadata.Filters
independentFlags.Add(new IndependentFlag(name, value));
}
if (extraFlags.TryGetValue(enumType, out var extras))
independentFlags.AddRange(extras);
// Build the final mutex groups. Drop empty buckets — a *Mask field whose
// values weren't named in the enum (or were aliased away) doesn't earn a
// dropdown section. Each group always leads with a synthesised "(none)" entry

Loading…
Cancel
Save