diff --git a/ILSpy/Metadata/CorTables/ConstantTableTreeNode.cs b/ILSpy/Metadata/CorTables/ConstantTableTreeNode.cs new file mode 100644 index 000000000..bf2a5cca6 --- /dev/null +++ b/ILSpy/Metadata/CorTables/ConstantTableTreeNode.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.Metadata; +using System.Reflection.Metadata.Ecma335; + +using ICSharpCode.Decompiler.Metadata; + +namespace ILSpy.Metadata.CorTables +{ + /// + /// View of the Constant table — compile-time constants attached to fields, parameters, + /// or properties. The Type column is the primitive type code; Value points at a blob + /// holding the literal payload. + /// + public sealed class ConstantTableTreeNode : MetadataTableTreeNode + { + public ConstantTableTreeNode(MetadataFile metadataFile) + : base(TableIndex.Constant, metadataFile) + { + } + + protected override IReadOnlyList LoadTable() + { + var list = new List(); + for (int row = 1; row <= metadataFile.Metadata.GetTableRowCount(TableIndex.Constant); row++) + list.Add(new ConstantEntry(metadataFile, MetadataTokens.ConstantHandle(row))); + return list; + } + + public sealed class ConstantEntry + { + readonly MetadataFile metadataFile; + readonly ConstantHandle handle; + readonly Constant constant; + + 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.Constant) + + metadataFile.Metadata.GetTableRowSize(TableIndex.Constant) * (RID - 1); + + [ColumnInfo("X8")] + public ConstantTypeCode Type => constant.TypeCode; + + [ColumnInfo("X8", Kind = ColumnKind.Token)] + public int Parent => MetadataTokens.GetToken(constant.Parent); + + [ColumnInfo("X8", Kind = ColumnKind.HeapOffset)] + public int Value => MetadataTokens.GetHeapOffset(constant.Value); + + public ConstantEntry(MetadataFile metadataFile, ConstantHandle handle) + { + this.metadataFile = metadataFile; + this.handle = handle; + constant = metadataFile.Metadata.GetConstant(handle); + } + } + } +} diff --git a/ILSpy/Metadata/CorTables/EventTableTreeNode.cs b/ILSpy/Metadata/CorTables/EventTableTreeNode.cs new file mode 100644 index 000000000..1c3014de8 --- /dev/null +++ b/ILSpy/Metadata/CorTables/EventTableTreeNode.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 Event table — every CLR event the module's types declare. Each row + /// references the event's delegate type as a TypeDefOrRef coded token; add/remove/raise + /// accessor bindings live in MethodSemantics. + /// + public sealed class EventTableTreeNode : MetadataTableTreeNode + { + public EventTableTreeNode(MetadataFile metadataFile) + : base(TableIndex.Event, metadataFile) + { + } + + protected override IReadOnlyList LoadTable() + { + var list = new List(); + foreach (var row in metadataFile.Metadata.EventDefinitions) + list.Add(new EventDefEntry(metadataFile, row)); + return list; + } + + public sealed class EventDefEntry + { + readonly MetadataFile metadataFile; + readonly EventDefinitionHandle handle; + readonly EventDefinition eventDef; + + 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.Event) + + metadataFile.Metadata.GetTableRowSize(TableIndex.Event) * (RID - 1); + + [ColumnInfo("X8")] + public EventAttributes Attributes => eventDef.Attributes; + + public string Name => metadataFile.Metadata.GetString(eventDef.Name); + + [ColumnInfo("X8", Kind = ColumnKind.Token)] + public int Type => MetadataTokens.GetToken(eventDef.Type); + + public EventDefEntry(MetadataFile metadataFile, EventDefinitionHandle handle) + { + this.metadataFile = metadataFile; + this.handle = handle; + eventDef = metadataFile.Metadata.GetEventDefinition(handle); + } + } + } +} diff --git a/ILSpy/Metadata/CorTables/ExportedTypeTableTreeNode.cs b/ILSpy/Metadata/CorTables/ExportedTypeTableTreeNode.cs new file mode 100644 index 000000000..b36199fe1 --- /dev/null +++ b/ILSpy/Metadata/CorTables/ExportedTypeTableTreeNode.cs @@ -0,0 +1,86 @@ +// 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 ExportedType table — types this assembly forwards to (or re-exports + /// from) another assembly. Common in type-forwarding scenarios where mscorlib.dll + /// exposes types that physically live in System.Runtime.dll. + /// + public sealed class ExportedTypeTableTreeNode : MetadataTableTreeNode + { + public ExportedTypeTableTreeNode(MetadataFile metadataFile) + : base(TableIndex.ExportedType, metadataFile) + { + } + + protected override IReadOnlyList LoadTable() + { + var list = new List(); + var metadata = metadataFile.Metadata; + foreach (var row in metadata.ExportedTypes) + list.Add(new ExportedTypeEntry(metadataFile, row, metadata.GetExportedType(row))); + return list; + } + + public sealed class ExportedTypeEntry + { + readonly MetadataFile metadataFile; + readonly ExportedTypeHandle handle; + readonly ExportedType type; + + 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.ExportedType) + + metadataFile.Metadata.GetTableRowSize(TableIndex.ExportedType) * (RID - 1); + + [ColumnInfo("X8")] + public TypeAttributes Attributes => type.Attributes; + + [ColumnInfo("X8")] + public int TypeDefId => type.GetTypeDefinitionId(); + + public string TypeName => metadataFile.Metadata.GetString(type.Name); + + public string TypeNamespace => metadataFile.Metadata.GetString(type.Namespace); + + [ColumnInfo("X8", Kind = ColumnKind.Token)] + public int Implementation => MetadataTokens.GetToken(type.Implementation); + + public ExportedTypeEntry(MetadataFile metadataFile, ExportedTypeHandle handle, ExportedType type) + { + this.metadataFile = metadataFile; + this.handle = handle; + this.type = type; + } + } + } +} diff --git a/ILSpy/Metadata/CorTables/GenericParamConstraintTableTreeNode.cs b/ILSpy/Metadata/CorTables/GenericParamConstraintTableTreeNode.cs new file mode 100644 index 000000000..e159de46b --- /dev/null +++ b/ILSpy/Metadata/CorTables/GenericParamConstraintTableTreeNode.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.Metadata; +using System.Reflection.Metadata.Ecma335; + +using ICSharpCode.Decompiler.Metadata; + +namespace ILSpy.Metadata.CorTables +{ + /// + /// View of the GenericParamConstraint table — bounds applied to generic parameters + /// (where T : SomeBase, IEnumerable<X>). Each row pairs a GenericParam + /// owner with a TypeDefOrRef coded token naming the constraining type. + /// + public sealed class GenericParamConstraintTableTreeNode : MetadataTableTreeNode + { + public GenericParamConstraintTableTreeNode(MetadataFile metadataFile) + : base(TableIndex.GenericParamConstraint, metadataFile) + { + } + + protected override IReadOnlyList LoadTable() + { + var list = new List(); + var metadata = metadataFile.Metadata; + for (int row = 1; row <= metadata.GetTableRowCount(TableIndex.GenericParamConstraint); row++) + list.Add(new GenericParamConstraintEntry(metadataFile, MetadataTokens.GenericParameterConstraintHandle(row))); + return list; + } + + public sealed class GenericParamConstraintEntry + { + readonly MetadataFile metadataFile; + readonly GenericParameterConstraintHandle handle; + readonly GenericParameterConstraint genericParamConstraint; + + 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.GenericParamConstraint) + + metadataFile.Metadata.GetTableRowSize(TableIndex.GenericParamConstraint) * (RID - 1); + + [ColumnInfo("X8", Kind = ColumnKind.Token)] + public int Owner => MetadataTokens.GetToken(genericParamConstraint.Parameter); + + [ColumnInfo("X8", Kind = ColumnKind.Token)] + public int Type => MetadataTokens.GetToken(genericParamConstraint.Type); + + public GenericParamConstraintEntry(MetadataFile metadataFile, GenericParameterConstraintHandle handle) + { + this.metadataFile = metadataFile; + this.handle = handle; + genericParamConstraint = metadataFile.Metadata.GetGenericParameterConstraint(handle); + } + } + } +} diff --git a/ILSpy/Metadata/CorTables/GenericParamTableTreeNode.cs b/ILSpy/Metadata/CorTables/GenericParamTableTreeNode.cs new file mode 100644 index 000000000..796c0869e --- /dev/null +++ b/ILSpy/Metadata/CorTables/GenericParamTableTreeNode.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.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 GenericParam table — every type or method generic-parameter slot. Owner + /// is a TypeOrMethodDef coded token; Number is the parameter's 0-based index inside + /// its owner's type-parameter list. + /// + public sealed class GenericParamTableTreeNode : MetadataTableTreeNode + { + public GenericParamTableTreeNode(MetadataFile metadataFile) + : base(TableIndex.GenericParam, metadataFile) + { + } + + protected override IReadOnlyList LoadTable() + { + var list = new List(); + for (int row = 1; row <= metadataFile.Metadata.GetTableRowCount(TableIndex.GenericParam); row++) + list.Add(new GenericParamEntry(metadataFile, MetadataTokens.GenericParameterHandle(row))); + return list; + } + + public sealed class GenericParamEntry + { + readonly MetadataFile metadataFile; + readonly GenericParameterHandle handle; + readonly GenericParameter genericParam; + + 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.GenericParam) + + metadataFile.Metadata.GetTableRowSize(TableIndex.GenericParam) * (RID - 1); + + public int Number => genericParam.Index; + + [ColumnInfo("X8")] + public GenericParameterAttributes Attributes => genericParam.Attributes; + + [ColumnInfo("X8", Kind = ColumnKind.Token)] + public int Owner => MetadataTokens.GetToken(genericParam.Parent); + + public string Name => metadataFile.Metadata.GetString(genericParam.Name); + + public GenericParamEntry(MetadataFile metadataFile, GenericParameterHandle handle) + { + this.metadataFile = metadataFile; + this.handle = handle; + genericParam = metadataFile.Metadata.GetGenericParameter(handle); + } + } + } +} diff --git a/ILSpy/Metadata/CorTables/ManifestResourceTableTreeNode.cs b/ILSpy/Metadata/CorTables/ManifestResourceTableTreeNode.cs new file mode 100644 index 000000000..83dfbeca8 --- /dev/null +++ b/ILSpy/Metadata/CorTables/ManifestResourceTableTreeNode.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; +using System.Reflection.Metadata; +using System.Reflection.Metadata.Ecma335; + +using ICSharpCode.Decompiler.Metadata; + +namespace ILSpy.Metadata.CorTables +{ + /// + /// View of the ManifestResource table — every embedded or linked resource the assembly + /// manifest publishes. Implementation is an Implementation coded token: nil for embedded + /// resources (data lives at .text+offset), otherwise an AssemblyFile or AssemblyRef + /// pointing at the holder of the resource bytes. + /// + public sealed class ManifestResourceTableTreeNode : MetadataTableTreeNode + { + public ManifestResourceTableTreeNode(MetadataFile metadataFile) + : base(TableIndex.ManifestResource, metadataFile) + { + } + + protected override IReadOnlyList LoadTable() + { + var list = new List(); + foreach (var row in metadataFile.Metadata.ManifestResources) + list.Add(new ManifestResourceEntry(metadataFile, row)); + return list; + } + + public sealed class ManifestResourceEntry + { + readonly MetadataFile metadataFile; + readonly ManifestResourceHandle handle; + readonly ManifestResource manifestResource; + + 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.ManifestResource) + + metadataFile.Metadata.GetTableRowSize(TableIndex.ManifestResource) * (RID - 1); + + [ColumnInfo("X8")] + public ManifestResourceAttributes Attributes => manifestResource.Attributes; + + public string Name => metadataFile.Metadata.GetString(manifestResource.Name); + + [ColumnInfo("X8", Kind = ColumnKind.Token)] + public int Implementation => MetadataTokens.GetToken(manifestResource.Implementation); + + public ManifestResourceEntry(MetadataFile metadataFile, ManifestResourceHandle handle) + { + this.metadataFile = metadataFile; + this.handle = handle; + manifestResource = metadataFile.Metadata.GetManifestResource(handle); + } + } + } +} diff --git a/ILSpy/Metadata/CorTables/MethodSpecTableTreeNode.cs b/ILSpy/Metadata/CorTables/MethodSpecTableTreeNode.cs new file mode 100644 index 000000000..8e1d36698 --- /dev/null +++ b/ILSpy/Metadata/CorTables/MethodSpecTableTreeNode.cs @@ -0,0 +1,77 @@ +// 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 MethodSpec table — concrete instantiations of generic methods like + /// List<int>.Add. Each row points back at the open generic method + /// (MethodDef or MemberRef) and carries a blob holding the type-argument list. + /// + public sealed class MethodSpecTableTreeNode : MetadataTableTreeNode + { + public MethodSpecTableTreeNode(MetadataFile metadataFile) + : base(TableIndex.MethodSpec, metadataFile) + { + } + + protected override IReadOnlyList LoadTable() + { + var list = new List(); + foreach (var row in metadataFile.Metadata.GetMethodSpecifications()) + list.Add(new MethodSpecEntry(metadataFile, row)); + return list; + } + + public sealed class MethodSpecEntry + { + readonly MetadataFile metadataFile; + readonly MethodSpecificationHandle handle; + readonly MethodSpecification methodSpec; + + 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.MethodSpec) + + metadataFile.Metadata.GetTableRowSize(TableIndex.MethodSpec) * (RID - 1); + + [ColumnInfo("X8", Kind = ColumnKind.Token)] + public int Method => MetadataTokens.GetToken(methodSpec.Method); + + [ColumnInfo("X8", Kind = ColumnKind.HeapOffset)] + public int Signature => MetadataTokens.GetHeapOffset(methodSpec.Signature); + + public MethodSpecEntry(MetadataFile metadataFile, MethodSpecificationHandle handle) + { + this.metadataFile = metadataFile; + this.handle = handle; + methodSpec = metadataFile.Metadata.GetMethodSpecification(handle); + } + } + } +} diff --git a/ILSpy/Metadata/CorTables/ModuleRefTableTreeNode.cs b/ILSpy/Metadata/CorTables/ModuleRefTableTreeNode.cs new file mode 100644 index 000000000..d40abe6da --- /dev/null +++ b/ILSpy/Metadata/CorTables/ModuleRefTableTreeNode.cs @@ -0,0 +1,72 @@ +// 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 ModuleRef table — every external .netmodule the assembly P/Invokes into + /// or otherwise references by name. Carries just the module's name string handle. + /// + public sealed class ModuleRefTableTreeNode : MetadataTableTreeNode + { + public ModuleRefTableTreeNode(MetadataFile metadataFile) + : base(TableIndex.ModuleRef, metadataFile) + { + } + + protected override IReadOnlyList LoadTable() + { + var list = new List(); + foreach (var row in metadataFile.Metadata.GetModuleReferences()) + list.Add(new ModuleRefEntry(metadataFile, row)); + return list; + } + + public sealed class ModuleRefEntry + { + readonly MetadataFile metadataFile; + readonly ModuleReferenceHandle handle; + readonly ModuleReference moduleRef; + + 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.ModuleRef) + + metadataFile.Metadata.GetTableRowSize(TableIndex.ModuleRef) * (RID - 1); + + public string Name => metadataFile.Metadata.GetString(moduleRef.Name); + + public ModuleRefEntry(MetadataFile metadataFile, ModuleReferenceHandle handle) + { + this.metadataFile = metadataFile; + this.handle = handle; + moduleRef = metadataFile.Metadata.GetModuleReference(handle); + } + } + } +} diff --git a/ILSpy/Metadata/CorTables/PropertyTableTreeNode.cs b/ILSpy/Metadata/CorTables/PropertyTableTreeNode.cs new file mode 100644 index 000000000..6d16d0dd6 --- /dev/null +++ b/ILSpy/Metadata/CorTables/PropertyTableTreeNode.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 Property table — every property the module's types declare. Method-level + /// accessor binding lives in MethodSemantics; this table just carries each property's + /// attributes, name, and signature blob. + /// + public sealed class PropertyTableTreeNode : MetadataTableTreeNode + { + public PropertyTableTreeNode(MetadataFile metadataFile) + : base(TableIndex.Property, metadataFile) + { + } + + protected override IReadOnlyList LoadTable() + { + var list = new List(); + foreach (var row in metadataFile.Metadata.PropertyDefinitions) + list.Add(new PropertyDefEntry(metadataFile, row)); + return list; + } + + public sealed class PropertyDefEntry + { + readonly MetadataFile metadataFile; + readonly PropertyDefinitionHandle handle; + readonly PropertyDefinition propertyDef; + + 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.Property) + + metadataFile.Metadata.GetTableRowSize(TableIndex.Property) * (RID - 1); + + [ColumnInfo("X8")] + public PropertyAttributes Attributes => propertyDef.Attributes; + + public string Name => metadataFile.Metadata.GetString(propertyDef.Name); + + [ColumnInfo("X8", Kind = ColumnKind.HeapOffset)] + public int Signature => MetadataTokens.GetHeapOffset(propertyDef.Signature); + + public PropertyDefEntry(MetadataFile metadataFile, PropertyDefinitionHandle handle) + { + this.metadataFile = metadataFile; + this.handle = handle; + propertyDef = metadataFile.Metadata.GetPropertyDefinition(handle); + } + } + } +} diff --git a/ILSpy/Metadata/CorTables/TypeSpecTableTreeNode.cs b/ILSpy/Metadata/CorTables/TypeSpecTableTreeNode.cs new file mode 100644 index 000000000..8542171c9 --- /dev/null +++ b/ILSpy/Metadata/CorTables/TypeSpecTableTreeNode.cs @@ -0,0 +1,74 @@ +// 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 TypeSpec table — instantiated generic types and other constructed type + /// shapes (arrays, pointers, modreq/modopt) referenced from instructions and signatures. + /// Each row points at a blob signature describing the constructed type. + /// + public sealed class TypeSpecTableTreeNode : MetadataTableTreeNode + { + public TypeSpecTableTreeNode(MetadataFile metadataFile) + : base(TableIndex.TypeSpec, metadataFile) + { + } + + protected override IReadOnlyList LoadTable() + { + var list = new List(); + foreach (var row in metadataFile.Metadata.GetTypeSpecifications()) + list.Add(new TypeSpecEntry(metadataFile, row)); + return list; + } + + public sealed class TypeSpecEntry + { + readonly MetadataFile metadataFile; + readonly TypeSpecificationHandle handle; + readonly TypeSpecification typeSpec; + + 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.TypeSpec) + + metadataFile.Metadata.GetTableRowSize(TableIndex.TypeSpec) * (RID - 1); + + [ColumnInfo("X8", Kind = ColumnKind.HeapOffset)] + public int Signature => MetadataTokens.GetHeapOffset(typeSpec.Signature); + + public TypeSpecEntry(MetadataFile metadataFile, TypeSpecificationHandle handle) + { + this.metadataFile = metadataFile; + this.handle = handle; + typeSpec = metadataFile.Metadata.GetTypeSpecification(handle); + } + } + } +} diff --git a/ILSpy/Metadata/MetadataTablesTreeNode.cs b/ILSpy/Metadata/MetadataTablesTreeNode.cs index e757a4d73..542ced37d 100644 --- a/ILSpy/Metadata/MetadataTablesTreeNode.cs +++ b/ILSpy/Metadata/MetadataTablesTreeNode.cs @@ -81,9 +81,19 @@ namespace ILSpy.Metadata TableIndex.MethodDef => new MethodTableTreeNode(metadataFile), TableIndex.Param => new ParamTableTreeNode(metadataFile), TableIndex.MemberRef => new MemberRefTableTreeNode(metadataFile), + TableIndex.Constant => new ConstantTableTreeNode(metadataFile), TableIndex.CustomAttribute => new CustomAttributeTableTreeNode(metadataFile), + TableIndex.Event => new EventTableTreeNode(metadataFile), + TableIndex.Property => new PropertyTableTreeNode(metadataFile), + TableIndex.ModuleRef => new ModuleRefTableTreeNode(metadataFile), + TableIndex.TypeSpec => new TypeSpecTableTreeNode(metadataFile), TableIndex.Assembly => new AssemblyTableTreeNode(metadataFile), TableIndex.AssemblyRef => new AssemblyRefTableTreeNode(metadataFile), + TableIndex.ExportedType => new ExportedTypeTableTreeNode(metadataFile), + TableIndex.ManifestResource => new ManifestResourceTableTreeNode(metadataFile), + TableIndex.GenericParam => new GenericParamTableTreeNode(metadataFile), + TableIndex.MethodSpec => new MethodSpecTableTreeNode(metadataFile), + TableIndex.GenericParamConstraint => new GenericParamConstraintTableTreeNode(metadataFile), _ => new UnsupportedMetadataTableTreeNode(table, metadataFile), }; }