diff --git a/ILSpy.Tests/Metadata/TypedMetadataTableTreeTests.cs b/ILSpy.Tests/Metadata/TypedMetadataTableTreeTests.cs index f3e0804da..b6a0d7f43 100644 --- a/ILSpy.Tests/Metadata/TypedMetadataTableTreeTests.cs +++ b/ILSpy.Tests/Metadata/TypedMetadataTableTreeTests.cs @@ -102,6 +102,40 @@ public class TypedMetadataTableTreeTests tab.Text.Should().Contain("Object"); } + [AvaloniaTest] + public async Task FieldAndMethodTables_Decompile_With_Their_Own_Typed_Leaves() + { + // Field / MethodDef are by far the largest tables in any real assembly. The typed + // leaf should report the right table kind, expose a row count, and decompile to a + // table whose first column header is "RID" (the per-table row identifier). + + var window = AppComposition.Current.GetExport(); + window.Show(); + var vm = (MainWindowViewModel)window.DataContext!; + await vm.AssemblyTreeModel.WaitForAssembliesAsync(minimumCount: 1); + + var coreLibName = typeof(object).Assembly.GetName().Name!; + var assemblyNode = vm.AssemblyTreeModel.FindNode(coreLibName); + assemblyNode.EnsureLazyChildren(); + var metadataNode = assemblyNode.Children.OfType().Single(); + metadataNode.EnsureLazyChildren(); + var tablesNode = metadataNode.Children.OfType().Single(); + tablesNode.EnsureLazyChildren(); + + tablesNode.Children.OfType().Should().ContainSingle(); + tablesNode.Children.OfType().Should().ContainSingle(); + tablesNode.Children.OfType().Should().ContainSingle(); + tablesNode.Children.OfType().Should().ContainSingle(); + tablesNode.Children.OfType().Should().ContainSingle(); + tablesNode.Children.OfType().Should().ContainSingle(); + + var methodNode = tablesNode.Children.OfType().Single(); + vm.AssemblyTreeModel.SelectNode(methodNode); + var tab = await vm.DockWorkspace.WaitForDecompiledTextAsync(); + tab.Text.Should().Contain("MethodDef"); + tab.Text.Should().Contain("RID"); + } + [AvaloniaTest] public async Task ModuleTableTreeNode_Decompiles_To_A_Single_Row_Carrying_The_Module_Name() { diff --git a/ILSpy/Metadata/CorTables/AssemblyTableTreeNode.cs b/ILSpy/Metadata/CorTables/AssemblyTableTreeNode.cs new file mode 100644 index 000000000..08fdde3a2 --- /dev/null +++ b/ILSpy/Metadata/CorTables/AssemblyTableTreeNode.cs @@ -0,0 +1,82 @@ +// Copyright (c) 2026 AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Reflection.Metadata; +using System.Reflection.Metadata.Ecma335; + +using ICSharpCode.Decompiler.Metadata; + +namespace ILSpy.Metadata.CorTables +{ + /// + /// View of the Assembly table — at most one row, present only when the metadata file is + /// itself an assembly manifest (vs. a plain .netmodule). Carries the assembly's name, + /// culture, version, hash algorithm, and signing flags. + /// + public sealed class AssemblyTableTreeNode : MetadataTableTreeNode + { + public AssemblyTableTreeNode(MetadataFile metadataFile) + : base(TableIndex.Assembly, metadataFile) + { + } + + protected override IReadOnlyList LoadTable() + => metadataFile.Metadata.IsAssembly + ? [new AssemblyEntry(metadataFile.Metadata, metadataFile.MetadataOffset)] + : []; + + public sealed class AssemblyEntry + { + readonly int metadataOffset; + readonly MetadataReader metadata; + readonly AssemblyDefinition assembly; + + public int RID => MetadataTokens.GetRowNumber(EntityHandle.AssemblyDefinition); + + [ColumnInfo("X8")] + public int Token => MetadataTokens.GetToken(EntityHandle.AssemblyDefinition); + + [ColumnInfo("X8")] + public int Offset => metadataOffset + + metadata.GetTableMetadataOffset(TableIndex.Assembly) + + metadata.GetTableRowSize(TableIndex.Assembly) * (RID - 1); + + [ColumnInfo("X4")] + public AssemblyHashAlgorithm HashAlgorithm => assembly.HashAlgorithm; + + [ColumnInfo("X4")] + public AssemblyFlags Flags => assembly.Flags; + + public Version Version => assembly.Version; + + public string Name => metadata.GetString(assembly.Name); + + public string Culture => metadata.GetString(assembly.Culture); + + public AssemblyEntry(MetadataReader metadata, int metadataOffset) + { + this.metadata = metadata; + this.metadataOffset = metadataOffset; + assembly = metadata.GetAssemblyDefinition(); + } + } + } +} diff --git a/ILSpy/Metadata/CorTables/CustomAttributeTableTreeNode.cs b/ILSpy/Metadata/CorTables/CustomAttributeTableTreeNode.cs new file mode 100644 index 000000000..5b0cbfeab --- /dev/null +++ b/ILSpy/Metadata/CorTables/CustomAttributeTableTreeNode.cs @@ -0,0 +1,81 @@ +// Copyright (c) 2026 AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System.Collections.Generic; +using System.Reflection.Metadata; +using System.Reflection.Metadata.Ecma335; + +using ICSharpCode.Decompiler.Metadata; + +namespace ILSpy.Metadata.CorTables +{ + /// + /// View of the CustomAttribute table — every [Attr(...)] annotation attached to + /// every metadata row. Parent is a HasCustomAttribute coded token; Constructor points at + /// the attribute class's ctor (MethodDef or MemberRef); Value blob holds the constructor + /// arguments + named properties as a serialised payload. + /// + public sealed class CustomAttributeTableTreeNode : MetadataTableTreeNode + { + public CustomAttributeTableTreeNode(MetadataFile metadataFile) + : base(TableIndex.CustomAttribute, metadataFile) + { + } + + protected override IReadOnlyList LoadTable() + { + var list = new List(); + foreach (var row in metadataFile.Metadata.CustomAttributes) + list.Add(new CustomAttributeEntry(metadataFile, row)); + return list; + } + + public sealed class CustomAttributeEntry + { + readonly MetadataFile metadataFile; + readonly CustomAttributeHandle handle; + readonly CustomAttribute customAttr; + + public int RID => MetadataTokens.GetRowNumber(handle); + + [ColumnInfo("X8")] + public int Token => MetadataTokens.GetToken(handle); + + [ColumnInfo("X8")] + public int Offset => metadataFile.MetadataOffset + + metadataFile.Metadata.GetTableMetadataOffset(TableIndex.CustomAttribute) + + metadataFile.Metadata.GetTableRowSize(TableIndex.CustomAttribute) * (RID - 1); + + [ColumnInfo("X8", Kind = ColumnKind.Token)] + public int Parent => MetadataTokens.GetToken(customAttr.Parent); + + [ColumnInfo("X8", Kind = ColumnKind.Token)] + public int Constructor => MetadataTokens.GetToken(customAttr.Constructor); + + [ColumnInfo("X8", Kind = ColumnKind.HeapOffset)] + public int Value => MetadataTokens.GetHeapOffset(customAttr.Value); + + public CustomAttributeEntry(MetadataFile metadataFile, CustomAttributeHandle handle) + { + this.metadataFile = metadataFile; + this.handle = handle; + customAttr = metadataFile.Metadata.GetCustomAttribute(handle); + } + } + } +} diff --git a/ILSpy/Metadata/CorTables/FieldTableTreeNode.cs b/ILSpy/Metadata/CorTables/FieldTableTreeNode.cs new file mode 100644 index 000000000..71820c9bf --- /dev/null +++ b/ILSpy/Metadata/CorTables/FieldTableTreeNode.cs @@ -0,0 +1,80 @@ +// Copyright (c) 2026 AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System.Collections.Generic; +using System.Reflection; +using System.Reflection.Metadata; +using System.Reflection.Metadata.Ecma335; + +using ICSharpCode.Decompiler.Metadata; + +namespace ILSpy.Metadata.CorTables +{ + /// + /// View of the Field table — every field defined by the module's types. Each row carries + /// the field's attributes (visibility / static / const / …), name, and the heap offset + /// of its signature blob. + /// + public sealed class FieldTableTreeNode : MetadataTableTreeNode + { + public FieldTableTreeNode(MetadataFile metadataFile) + : base(TableIndex.Field, metadataFile) + { + } + + protected override IReadOnlyList LoadTable() + { + var list = new List(); + foreach (var row in metadataFile.Metadata.FieldDefinitions) + list.Add(new FieldDefEntry(metadataFile, row)); + return list; + } + + public sealed class FieldDefEntry + { + readonly MetadataFile metadataFile; + readonly FieldDefinitionHandle handle; + readonly FieldDefinition fieldDef; + + public int RID => MetadataTokens.GetRowNumber(handle); + + [ColumnInfo("X8")] + public int Token => MetadataTokens.GetToken(handle); + + [ColumnInfo("X8")] + public int Offset => metadataFile.MetadataOffset + + metadataFile.Metadata.GetTableMetadataOffset(TableIndex.Field) + + metadataFile.Metadata.GetTableRowSize(TableIndex.Field) * (RID - 1); + + [ColumnInfo("X8")] + public FieldAttributes Attributes => fieldDef.Attributes; + + public string Name => metadataFile.Metadata.GetString(fieldDef.Name); + + [ColumnInfo("X8", Kind = ColumnKind.HeapOffset)] + public int Signature => MetadataTokens.GetHeapOffset(fieldDef.Signature); + + public FieldDefEntry(MetadataFile metadataFile, FieldDefinitionHandle handle) + { + this.metadataFile = metadataFile; + this.handle = handle; + fieldDef = metadataFile.Metadata.GetFieldDefinition(handle); + } + } + } +} diff --git a/ILSpy/Metadata/CorTables/MemberRefTableTreeNode.cs b/ILSpy/Metadata/CorTables/MemberRefTableTreeNode.cs new file mode 100644 index 000000000..c37d6a4cd --- /dev/null +++ b/ILSpy/Metadata/CorTables/MemberRefTableTreeNode.cs @@ -0,0 +1,79 @@ +// Copyright (c) 2026 AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System.Collections.Generic; +using System.Reflection.Metadata; +using System.Reflection.Metadata.Ecma335; + +using ICSharpCode.Decompiler.Metadata; + +namespace ILSpy.Metadata.CorTables +{ + /// + /// View of the MemberRef table — every external method or field the module references. + /// Parent is a MemberRefParent coded token (TypeRef / ModuleRef / MethodDef / TypeSpec / + /// TypeDef) carrying the owner of the referenced member. + /// + public sealed class MemberRefTableTreeNode : MetadataTableTreeNode + { + public MemberRefTableTreeNode(MetadataFile metadataFile) + : base(TableIndex.MemberRef, metadataFile) + { + } + + protected override IReadOnlyList LoadTable() + { + var list = new List(); + foreach (var row in metadataFile.Metadata.MemberReferences) + list.Add(new MemberRefEntry(metadataFile, row)); + return list; + } + + public sealed class MemberRefEntry + { + readonly MetadataFile metadataFile; + readonly MemberReferenceHandle handle; + readonly MemberReference memberRef; + + public int RID => MetadataTokens.GetRowNumber(handle); + + [ColumnInfo("X8")] + public int Token => MetadataTokens.GetToken(handle); + + [ColumnInfo("X8")] + public int Offset => metadataFile.MetadataOffset + + metadataFile.Metadata.GetTableMetadataOffset(TableIndex.MemberRef) + + metadataFile.Metadata.GetTableRowSize(TableIndex.MemberRef) * (RID - 1); + + [ColumnInfo("X8", Kind = ColumnKind.Token)] + public int Parent => MetadataTokens.GetToken(memberRef.Parent); + + public string Name => metadataFile.Metadata.GetString(memberRef.Name); + + [ColumnInfo("X8", Kind = ColumnKind.HeapOffset)] + public int Signature => MetadataTokens.GetHeapOffset(memberRef.Signature); + + public MemberRefEntry(MetadataFile metadataFile, MemberReferenceHandle handle) + { + this.metadataFile = metadataFile; + this.handle = handle; + memberRef = metadataFile.Metadata.GetMemberReference(handle); + } + } + } +} diff --git a/ILSpy/Metadata/CorTables/MethodTableTreeNode.cs b/ILSpy/Metadata/CorTables/MethodTableTreeNode.cs new file mode 100644 index 000000000..db846f0aa --- /dev/null +++ b/ILSpy/Metadata/CorTables/MethodTableTreeNode.cs @@ -0,0 +1,90 @@ +// Copyright (c) 2026 AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Reflection.Metadata; +using System.Reflection.Metadata.Ecma335; + +using ICSharpCode.Decompiler.Metadata; + +namespace ILSpy.Metadata.CorTables +{ + /// + /// View of the MethodDef table — every method body the module ships. The RVA points + /// into the .text section's IL stream (0 for abstract / interface methods); the + /// ParamList token is the first row in the Param table covering this method's parameters. + /// + public sealed class MethodTableTreeNode : MetadataTableTreeNode + { + public MethodTableTreeNode(MetadataFile metadataFile) + : base(TableIndex.MethodDef, metadataFile) + { + } + + protected override IReadOnlyList LoadTable() + { + var list = new List(); + foreach (var row in metadataFile.Metadata.MethodDefinitions) + list.Add(new MethodDefEntry(metadataFile, row)); + return list; + } + + public sealed class MethodDefEntry + { + readonly MetadataFile metadataFile; + readonly MethodDefinitionHandle handle; + readonly MethodDefinition methodDef; + + public int RID => MetadataTokens.GetRowNumber(handle); + + [ColumnInfo("X8")] + public int Token => MetadataTokens.GetToken(handle); + + [ColumnInfo("X8")] + public int Offset => metadataFile.MetadataOffset + + metadataFile.Metadata.GetTableMetadataOffset(TableIndex.MethodDef) + + metadataFile.Metadata.GetTableRowSize(TableIndex.MethodDef) * (RID - 1); + + [ColumnInfo("X8")] + public MethodAttributes Attributes => methodDef.Attributes; + + [ColumnInfo("X8")] + public MethodImplAttributes ImplAttributes => methodDef.ImplAttributes; + + [ColumnInfo("X8")] + public int RVA => methodDef.RelativeVirtualAddress; + + public string Name => metadataFile.Metadata.GetString(methodDef.Name); + + [ColumnInfo("X8", Kind = ColumnKind.HeapOffset)] + public int Signature => MetadataTokens.GetHeapOffset(methodDef.Signature); + + [ColumnInfo("X8", Kind = ColumnKind.Token)] + public int ParamList => MetadataTokens.GetToken(methodDef.GetParameters().FirstOrDefault()); + + public MethodDefEntry(MetadataFile metadataFile, MethodDefinitionHandle handle) + { + this.metadataFile = metadataFile; + this.handle = handle; + methodDef = metadataFile.Metadata.GetMethodDefinition(handle); + } + } + } +} diff --git a/ILSpy/Metadata/CorTables/ParamTableTreeNode.cs b/ILSpy/Metadata/CorTables/ParamTableTreeNode.cs new file mode 100644 index 000000000..3c01624f8 --- /dev/null +++ b/ILSpy/Metadata/CorTables/ParamTableTreeNode.cs @@ -0,0 +1,78 @@ +// Copyright (c) 2026 AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System.Collections.Generic; +using System.Reflection; +using System.Reflection.Metadata; +using System.Reflection.Metadata.Ecma335; + +using ICSharpCode.Decompiler.Metadata; + +namespace ILSpy.Metadata.CorTables +{ + /// + /// View of the Param table — every formal parameter declared on every method body. Walked + /// by 1-based row index because the metadata reader doesn't expose Param as an IEnumerable. + /// + public sealed class ParamTableTreeNode : MetadataTableTreeNode + { + public ParamTableTreeNode(MetadataFile metadataFile) + : base(TableIndex.Param, metadataFile) + { + } + + protected override IReadOnlyList LoadTable() + { + var list = new List(); + for (int row = 1; row <= metadataFile.Metadata.GetTableRowCount(TableIndex.Param); row++) + list.Add(new ParamEntry(metadataFile, MetadataTokens.ParameterHandle(row))); + return list; + } + + public sealed class ParamEntry + { + readonly MetadataFile metadataFile; + readonly ParameterHandle handle; + readonly Parameter param; + + public int RID => MetadataTokens.GetRowNumber(handle); + + [ColumnInfo("X8")] + public int Token => MetadataTokens.GetToken(handle); + + [ColumnInfo("X8")] + public int Offset => metadataFile.MetadataOffset + + metadataFile.Metadata.GetTableMetadataOffset(TableIndex.Param) + + metadataFile.Metadata.GetTableRowSize(TableIndex.Param) * (RID - 1); + + [ColumnInfo("X8")] + public ParameterAttributes Attributes => param.Attributes; + + public int Sequence => param.SequenceNumber; + + public string Name => metadataFile.Metadata.GetString(param.Name); + + public ParamEntry(MetadataFile metadataFile, ParameterHandle handle) + { + this.metadataFile = metadataFile; + this.handle = handle; + param = metadataFile.Metadata.GetParameter(handle); + } + } + } +} diff --git a/ILSpy/Metadata/MetadataTablesTreeNode.cs b/ILSpy/Metadata/MetadataTablesTreeNode.cs index eaba79aea..e757a4d73 100644 --- a/ILSpy/Metadata/MetadataTablesTreeNode.cs +++ b/ILSpy/Metadata/MetadataTablesTreeNode.cs @@ -77,6 +77,12 @@ namespace ILSpy.Metadata TableIndex.Module => new ModuleTableTreeNode(metadataFile), TableIndex.TypeRef => new TypeRefTableTreeNode(metadataFile), TableIndex.TypeDef => new TypeDefTableTreeNode(metadataFile), + TableIndex.Field => new FieldTableTreeNode(metadataFile), + TableIndex.MethodDef => new MethodTableTreeNode(metadataFile), + TableIndex.Param => new ParamTableTreeNode(metadataFile), + TableIndex.MemberRef => new MemberRefTableTreeNode(metadataFile), + TableIndex.CustomAttribute => new CustomAttributeTableTreeNode(metadataFile), + TableIndex.Assembly => new AssemblyTableTreeNode(metadataFile), TableIndex.AssemblyRef => new AssemblyRefTableTreeNode(metadataFile), _ => new UnsupportedMetadataTableTreeNode(table, metadataFile), };