diff --git a/ILSpy/ILSpy.csproj b/ILSpy/ILSpy.csproj
index 6d41b8b59..d1ec22e33 100644
--- a/ILSpy/ILSpy.csproj
+++ b/ILSpy/ILSpy.csproj
@@ -212,9 +212,28 @@
+
+ Code
+ MSBuild:Compile
+
+
+ Code
+ MSBuild:Compile
+
+
+ Code
+ MSBuild:Compile
+
+
+ Code
+ MSBuild:Compile
+
+
+
+
diff --git a/ILSpy/Metadata/DebugMetadataTablesTreeNode.cs b/ILSpy/Metadata/DebugMetadataTablesTreeNode.cs
new file mode 100644
index 000000000..8fc5a3734
--- /dev/null
+++ b/ILSpy/Metadata/DebugMetadataTablesTreeNode.cs
@@ -0,0 +1,84 @@
+// Copyright (c) 2021 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;
+using ICSharpCode.Decompiler.Metadata;
+using ICSharpCode.ILSpy.Options;
+using ICSharpCode.ILSpy.TreeNodes;
+using ICSharpCode.ILSpy.ViewModels;
+
+namespace ICSharpCode.ILSpy.Metadata
+{
+ class DebugMetadataTablesTreeNode : ILSpyTreeNode
+ {
+ private PEFile module;
+ private bool isEmbedded;
+ private MetadataReader provider;
+
+ public DebugMetadataTablesTreeNode(PEFile module, bool isEmbedded, MetadataReader provider)
+ {
+ this.module = module;
+ this.isEmbedded = isEmbedded;
+ this.provider = provider;
+ this.LazyLoading = true;
+ }
+
+ public override object Text => "Tables";
+
+ public override object Icon => Images.Literal;
+
+ protected override void LoadChildren()
+ {
+ if (ShowTable(TableIndex.Document))
+ this.Children.Add(new DocumentTableTreeNode(this.module, this.provider, isEmbedded));
+ if (ShowTable(TableIndex.MethodDebugInformation))
+ this.Children.Add(new MethodDebugInformationTableTreeNode(this.module, this.provider, isEmbedded));
+ if (ShowTable(TableIndex.LocalScope))
+ this.Children.Add(new LocalScopeTableTreeNode(this.module, this.provider, isEmbedded));
+ if (ShowTable(TableIndex.LocalVariable))
+ this.Children.Add(new LocalVariableTableTreeNode(this.module, this.provider, isEmbedded));
+ if (ShowTable(TableIndex.LocalConstant))
+ this.Children.Add(new LocalConstantTableTreeNode(this.module, this.provider, isEmbedded));
+ if (ShowTable(TableIndex.ImportScope))
+ this.Children.Add(new ImportScopeTableTreeNode(this.module, this.provider, isEmbedded));
+ if (ShowTable(TableIndex.StateMachineMethod))
+ this.Children.Add(new StateMachineMethodTableTreeNode(this.module, this.provider, isEmbedded));
+ if (ShowTable(TableIndex.CustomDebugInformation))
+ this.Children.Add(new CustomDebugInformationTableTreeNode(this.module, this.provider, isEmbedded));
+
+ bool ShowTable(TableIndex table) => !DisplaySettingsPanel.CurrentDisplaySettings.HideEmptyMetadataTables || this.provider.GetTableRowCount(table) > 0;
+ }
+
+ public override bool View(TabPageModel tabPage)
+ {
+ tabPage.Title = Text.ToString();
+ tabPage.SupportsLanguageSwitching = false;
+
+ return false;
+ }
+
+ public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
+ {
+ language.WriteCommentLine(output, "Metadata Tables");
+ }
+ }
+}
diff --git a/ILSpy/Metadata/DebugMetadataTreeNode.cs b/ILSpy/Metadata/DebugMetadataTreeNode.cs
index d14556511..c0edc0d02 100644
--- a/ILSpy/Metadata/DebugMetadataTreeNode.cs
+++ b/ILSpy/Metadata/DebugMetadataTreeNode.cs
@@ -64,24 +64,11 @@ namespace ICSharpCode.ILSpy.Metadata
protected override void LoadChildren()
{
- if (ShowTable(TableIndex.Document))
- this.Children.Add(new DocumentTableTreeNode(this.module, this.provider, isEmbedded));
- if (ShowTable(TableIndex.MethodDebugInformation))
- this.Children.Add(new MethodDebugInformationTableTreeNode(this.module, this.provider, isEmbedded));
- if (ShowTable(TableIndex.LocalScope))
- this.Children.Add(new LocalScopeTableTreeNode(this.module, this.provider, isEmbedded));
- if (ShowTable(TableIndex.LocalVariable))
- this.Children.Add(new LocalVariableTableTreeNode(this.module, this.provider, isEmbedded));
- if (ShowTable(TableIndex.LocalConstant))
- this.Children.Add(new LocalConstantTableTreeNode(this.module, this.provider, isEmbedded));
- if (ShowTable(TableIndex.ImportScope))
- this.Children.Add(new ImportScopeTableTreeNode(this.module, this.provider, isEmbedded));
- if (ShowTable(TableIndex.StateMachineMethod))
- this.Children.Add(new StateMachineMethodTableTreeNode(this.module, this.provider, isEmbedded));
- if (ShowTable(TableIndex.CustomDebugInformation))
- this.Children.Add(new CustomDebugInformationTableTreeNode(this.module, this.provider, isEmbedded));
-
- bool ShowTable(TableIndex table) => !DisplaySettingsPanel.CurrentDisplaySettings.HideEmptyMetadataTables || this.provider.GetTableRowCount(table) > 0;
+ this.Children.Add(new DebugMetadataTablesTreeNode(module, this.isEmbedded, this.provider));
+ this.Children.Add(new StringHeapTreeNode(module, this.provider));
+ this.Children.Add(new UserStringHeapTreeNode(module, this.provider));
+ this.Children.Add(new GuidHeapTreeNode(module, this.provider));
+ this.Children.Add(new BlobHeapTreeNode(module, this.provider));
}
public MetadataTableTreeNode FindNodeByHandleKind(HandleKind kind)
diff --git a/ILSpy/Metadata/Heaps/BlobHeapTreeNode.cs b/ILSpy/Metadata/Heaps/BlobHeapTreeNode.cs
new file mode 100644
index 000000000..f439e9acd
--- /dev/null
+++ b/ILSpy/Metadata/Heaps/BlobHeapTreeNode.cs
@@ -0,0 +1,97 @@
+// Copyright (c) 2011 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;
+using System.Collections.Generic;
+using System.Reflection;
+using System.Reflection.Metadata;
+using System.Reflection.Metadata.Ecma335;
+using System.Text;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+
+using ICSharpCode.Decompiler;
+using ICSharpCode.Decompiler.DebugInfo;
+using ICSharpCode.Decompiler.Disassembler;
+using ICSharpCode.Decompiler.IL;
+using ICSharpCode.Decompiler.Metadata;
+
+namespace ICSharpCode.ILSpy.Metadata
+{
+ internal class BlobHeapTreeNode : MetadataHeapTreeNode
+ {
+ readonly List list;
+
+ public BlobHeapTreeNode(PEFile module, MetadataReader metadata)
+ : base(HandleKind.Blob, module, metadata)
+ {
+ list = new List();
+
+ BlobHandle handle = MetadataTokens.BlobHandle(0);
+ do
+ {
+ BlobHeapEntry entry = new BlobHeapEntry(metadata, handle);
+ list.Add(entry);
+ handle = metadata.GetNextHandle(handle);
+ } while (!handle.IsNil);
+ }
+
+ public override object Text => $"Blob Heap ({list.Count})";
+
+ public override object Icon => Images.Literal;
+
+ public override bool View(ViewModels.TabPageModel tabPage)
+ {
+ tabPage.Title = Text.ToString();
+ tabPage.SupportsLanguageSwitching = false;
+
+ var view = Helpers.PrepareDataGrid(tabPage, this);
+
+ view.ItemsSource = list;
+
+ tabPage.Content = view;
+
+ return true;
+ }
+
+ class BlobHeapEntry
+ {
+ readonly MetadataReader metadata;
+ readonly BlobHandle handle;
+
+ public int Offset => metadata.GetHeapOffset(handle);
+
+ public int Length => metadata.GetBlobReader(handle).Length;
+
+ public string Value => metadata.GetBlobReader(handle).ToHexString();
+
+ public BlobHeapEntry(MetadataReader metadata, BlobHandle handle)
+ {
+ this.metadata = metadata;
+ this.handle = handle;
+ }
+ }
+
+ public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
+ {
+ language.WriteCommentLine(output, "Blob Heap");
+ }
+ }
+}
\ No newline at end of file
diff --git a/ILSpy/Metadata/Heaps/GuidHeapTreeNode.cs b/ILSpy/Metadata/Heaps/GuidHeapTreeNode.cs
new file mode 100644
index 000000000..f3f742619
--- /dev/null
+++ b/ILSpy/Metadata/Heaps/GuidHeapTreeNode.cs
@@ -0,0 +1,86 @@
+// Copyright (c) 2021 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.Metadata;
+using System.Reflection.Metadata.Ecma335;
+
+using ICSharpCode.Decompiler;
+using ICSharpCode.Decompiler.Metadata;
+
+namespace ICSharpCode.ILSpy.Metadata
+{
+ internal class GuidHeapTreeNode : MetadataHeapTreeNode
+ {
+ readonly List list;
+
+ public GuidHeapTreeNode(PEFile module, MetadataReader metadata)
+ : base(HandleKind.Guid, module, metadata)
+ {
+ list = new List();
+ int count = metadata.GetHeapSize(HeapIndex.Guid) >> 4;
+ for (int i = 1; i <= count; i++)
+ {
+ GuidHeapEntry entry = new GuidHeapEntry(metadata, MetadataTokens.GuidHandle(i));
+ list.Add(entry);
+ }
+ }
+
+ public override object Text => $"Guid Heap ({list.Count})";
+
+ public override object Icon => Images.Literal;
+
+ public override bool View(ViewModels.TabPageModel tabPage)
+ {
+ tabPage.Title = Text.ToString();
+ tabPage.SupportsLanguageSwitching = false;
+
+ var view = Helpers.PrepareDataGrid(tabPage, this);
+
+ view.ItemsSource = list;
+
+ tabPage.Content = view;
+
+ return true;
+ }
+
+ class GuidHeapEntry
+ {
+ readonly MetadataReader metadata;
+ readonly GuidHandle handle;
+
+ public int Index => metadata.GetHeapOffset(handle);
+
+ public int Length => 16;
+
+ public string Value => metadata.GetGuid(handle).ToString();
+
+ public GuidHeapEntry(MetadataReader metadata, GuidHandle handle)
+ {
+ this.metadata = metadata;
+ this.handle = handle;
+ }
+ }
+
+ public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
+ {
+ language.WriteCommentLine(output, "Guid Heap");
+ }
+ }
+}
\ No newline at end of file
diff --git a/ILSpy/Metadata/Heaps/StringHeapTreeNode.cs b/ILSpy/Metadata/Heaps/StringHeapTreeNode.cs
new file mode 100644
index 000000000..2e2ca4370
--- /dev/null
+++ b/ILSpy/Metadata/Heaps/StringHeapTreeNode.cs
@@ -0,0 +1,96 @@
+// Copyright (c) 2011 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;
+using System.Collections.Generic;
+using System.Reflection;
+using System.Reflection.Metadata;
+using System.Reflection.Metadata.Ecma335;
+using System.Text;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+
+using ICSharpCode.Decompiler;
+using ICSharpCode.Decompiler.DebugInfo;
+using ICSharpCode.Decompiler.Disassembler;
+using ICSharpCode.Decompiler.IL;
+using ICSharpCode.Decompiler.Metadata;
+
+namespace ICSharpCode.ILSpy.Metadata
+{
+ internal class StringHeapTreeNode : MetadataHeapTreeNode
+ {
+ readonly List list;
+
+ public StringHeapTreeNode(PEFile module, MetadataReader metadata)
+ : base(HandleKind.String, module, metadata)
+ {
+ list = new List();
+ StringHandle handle = MetadataTokens.StringHandle(0);
+ do
+ {
+ StringHeapEntry entry = new StringHeapEntry(metadata, handle);
+ list.Add(entry);
+ handle = metadata.GetNextHandle(handle);
+ } while (!handle.IsNil);
+ }
+
+ public override object Text => $"String Heap ({list.Count})";
+
+ public override object Icon => Images.Literal;
+
+ public override bool View(ViewModels.TabPageModel tabPage)
+ {
+ tabPage.Title = Text.ToString();
+ tabPage.SupportsLanguageSwitching = false;
+
+ var view = Helpers.PrepareDataGrid(tabPage, this);
+
+ view.ItemsSource = list;
+
+ tabPage.Content = view;
+
+ return true;
+ }
+
+ class StringHeapEntry
+ {
+ readonly MetadataReader metadata;
+ readonly StringHandle handle;
+
+ public int Offset => metadata.GetHeapOffset(handle);
+
+ public int Length => metadata.GetString(handle).Length;
+
+ public string Value => metadata.GetString(handle);
+
+ public StringHeapEntry(MetadataReader metadata, StringHandle handle)
+ {
+ this.metadata = metadata;
+ this.handle = handle;
+ }
+ }
+
+ public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
+ {
+ language.WriteCommentLine(output, "String Heap");
+ }
+ }
+}
\ No newline at end of file
diff --git a/ILSpy/Metadata/Heaps/UserStringHeapTreeNode.cs b/ILSpy/Metadata/Heaps/UserStringHeapTreeNode.cs
new file mode 100644
index 000000000..882a1c3a6
--- /dev/null
+++ b/ILSpy/Metadata/Heaps/UserStringHeapTreeNode.cs
@@ -0,0 +1,97 @@
+// Copyright (c) 2011 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;
+using System.Collections.Generic;
+using System.Reflection;
+using System.Reflection.Metadata;
+using System.Reflection.Metadata.Ecma335;
+using System.Text;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+
+using ICSharpCode.Decompiler;
+using ICSharpCode.Decompiler.DebugInfo;
+using ICSharpCode.Decompiler.Disassembler;
+using ICSharpCode.Decompiler.IL;
+using ICSharpCode.Decompiler.Metadata;
+
+namespace ICSharpCode.ILSpy.Metadata
+{
+ internal class UserStringHeapTreeNode : MetadataHeapTreeNode
+ {
+ readonly List list;
+
+ public UserStringHeapTreeNode(PEFile module, MetadataReader metadata)
+ : base(HandleKind.UserString, module, metadata)
+ {
+ list = new List();
+
+ UserStringHandle handle = MetadataTokens.UserStringHandle(0);
+ do
+ {
+ UserStringHeapEntry entry = new UserStringHeapEntry(metadata, handle);
+ list.Add(entry);
+ handle = metadata.GetNextHandle(handle);
+ } while (!handle.IsNil);
+ }
+
+ public override object Text => $"UserString Heap ({list.Count})";
+
+ public override object Icon => Images.Literal;
+
+ public override bool View(ViewModels.TabPageModel tabPage)
+ {
+ tabPage.Title = Text.ToString();
+ tabPage.SupportsLanguageSwitching = false;
+
+ var view = Helpers.PrepareDataGrid(tabPage, this);
+
+ view.ItemsSource = list;
+
+ tabPage.Content = view;
+
+ return true;
+ }
+
+ class UserStringHeapEntry
+ {
+ readonly MetadataReader metadata;
+ readonly UserStringHandle handle;
+
+ public int Offset => metadata.GetHeapOffset(handle);
+
+ public int Length => metadata.GetUserString(handle).Length;
+
+ public string Value => metadata.GetUserString(handle);
+
+ public UserStringHeapEntry(MetadataReader metadata, UserStringHandle handle)
+ {
+ this.metadata = metadata;
+ this.handle = handle;
+ }
+ }
+
+ public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
+ {
+ language.WriteCommentLine(output, "UserString Heap");
+ }
+ }
+}
\ No newline at end of file
diff --git a/ILSpy/Metadata/MetadataHeapTreeNode.cs b/ILSpy/Metadata/MetadataHeapTreeNode.cs
new file mode 100644
index 000000000..3be811d3d
--- /dev/null
+++ b/ILSpy/Metadata/MetadataHeapTreeNode.cs
@@ -0,0 +1,68 @@
+// Copyright (c) 2011 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.Reflection.Metadata;
+using System.Reflection.Metadata.Ecma335;
+using System.Windows.Controls;
+using System.Windows.Threading;
+
+using ICSharpCode.Decompiler.Metadata;
+using ICSharpCode.ILSpy.TextView;
+using ICSharpCode.ILSpy.TreeNodes;
+using ICSharpCode.ILSpy.ViewModels;
+using ICSharpCode.TreeView;
+
+namespace ICSharpCode.ILSpy.Metadata
+{
+ internal abstract class MetadataHeapTreeNode : ILSpyTreeNode
+ {
+ protected PEFile module;
+ protected MetadataReader metadata;
+ protected int scrollTarget;
+
+ public HandleKind Kind { get; }
+
+ public MetadataHeapTreeNode(HandleKind kind, PEFile module, MetadataReader metadata)
+ {
+ this.module = module;
+ this.Kind = kind;
+ this.metadata = metadata;
+ }
+
+ internal void ScrollTo(Handle handle)
+ {
+ //this.scrollTarget = MetadataTokens.GetHeapOffset((EntityHandle)handle);
+ }
+
+ protected void ScrollItemIntoView(DataGrid view, object item)
+ {
+ view.Loaded += View_Loaded;
+ view.Dispatcher.BeginInvoke((Action)(() => view.SelectItem(item)), DispatcherPriority.Background);
+ }
+
+ private void View_Loaded(object sender, System.Windows.RoutedEventArgs e)
+ {
+ DataGrid view = (DataGrid)sender;
+ var sv = view.FindVisualChild();
+ sv.ScrollToVerticalOffset(scrollTarget - 1);
+ view.Loaded -= View_Loaded;
+ this.scrollTarget = default;
+ }
+ }
+}
\ No newline at end of file
diff --git a/ILSpy/Metadata/MetadataProtocolHandler.cs b/ILSpy/Metadata/MetadataProtocolHandler.cs
index ced6a7497..3fb5219d9 100644
--- a/ILSpy/Metadata/MetadataProtocolHandler.cs
+++ b/ILSpy/Metadata/MetadataProtocolHandler.cs
@@ -1,10 +1,24 @@
-using System;
-using System.Collections.Generic;
+// Copyright (c) 2011 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.ComponentModel.Composition;
using System.Linq;
using System.Reflection.Metadata;
-using System.Text;
-using System.Threading.Tasks;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.ILSpy.TreeNodes;
diff --git a/ILSpy/Metadata/MetadataTableTreeNode.cs b/ILSpy/Metadata/MetadataTableTreeNode.cs
index a2644484b..dbd8a424c 100644
--- a/ILSpy/Metadata/MetadataTableTreeNode.cs
+++ b/ILSpy/Metadata/MetadataTableTreeNode.cs
@@ -45,7 +45,7 @@ namespace ICSharpCode.ILSpy.Metadata
internal void ScrollTo(Handle handle)
{
- this.scrollTarget = MetadataTokens.GetRowNumber((EntityHandle)handle);
+ this.scrollTarget = module.Metadata.GetRowNumber((EntityHandle)handle);
}
protected void ScrollItemIntoView(DataGrid view, object item)
diff --git a/ILSpy/Metadata/MetadataTablesTreeNode.cs b/ILSpy/Metadata/MetadataTablesTreeNode.cs
new file mode 100644
index 000000000..6d264792d
--- /dev/null
+++ b/ILSpy/Metadata/MetadataTablesTreeNode.cs
@@ -0,0 +1,132 @@
+// Copyright (c) 2021 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.Ecma335;
+
+using ICSharpCode.Decompiler;
+using ICSharpCode.Decompiler.Metadata;
+using ICSharpCode.ILSpy.Options;
+using ICSharpCode.ILSpy.TreeNodes;
+using ICSharpCode.ILSpy.ViewModels;
+
+namespace ICSharpCode.ILSpy.Metadata
+{
+ class MetadataTablesTreeNode : ILSpyTreeNode
+ {
+ private PEFile module;
+
+ public MetadataTablesTreeNode(PEFile module)
+ {
+ this.module = module;
+ this.LazyLoading = true;
+ }
+
+ public override object Text => "Tables";
+
+ public override object Icon => Images.Literal;
+
+ protected override void LoadChildren()
+ {
+ if (ShowTable(TableIndex.Module))
+ this.Children.Add(new ModuleTableTreeNode(module));
+ if (ShowTable(TableIndex.TypeRef))
+ this.Children.Add(new TypeRefTableTreeNode(module));
+ if (ShowTable(TableIndex.TypeDef))
+ this.Children.Add(new TypeDefTableTreeNode(module));
+ if (ShowTable(TableIndex.Field))
+ this.Children.Add(new FieldTableTreeNode(module));
+ if (ShowTable(TableIndex.MethodDef))
+ this.Children.Add(new MethodTableTreeNode(module));
+ if (ShowTable(TableIndex.Param))
+ this.Children.Add(new ParamTableTreeNode(module));
+ if (ShowTable(TableIndex.InterfaceImpl))
+ this.Children.Add(new InterfaceImplTableTreeNode(module));
+ if (ShowTable(TableIndex.MemberRef))
+ this.Children.Add(new MemberRefTableTreeNode(module));
+ if (ShowTable(TableIndex.Constant))
+ this.Children.Add(new ConstantTableTreeNode(module));
+ if (ShowTable(TableIndex.CustomAttribute))
+ this.Children.Add(new CustomAttributeTableTreeNode(module));
+ if (ShowTable(TableIndex.FieldMarshal))
+ this.Children.Add(new FieldMarshalTableTreeNode(module));
+ if (ShowTable(TableIndex.DeclSecurity))
+ this.Children.Add(new DeclSecurityTableTreeNode(module));
+ if (ShowTable(TableIndex.ClassLayout))
+ this.Children.Add(new ClassLayoutTableTreeNode(module));
+ if (ShowTable(TableIndex.FieldLayout))
+ this.Children.Add(new FieldLayoutTableTreeNode(module));
+ if (ShowTable(TableIndex.StandAloneSig))
+ this.Children.Add(new StandAloneSigTableTreeNode(module));
+ if (ShowTable(TableIndex.EventMap))
+ this.Children.Add(new EventMapTableTreeNode(module));
+ if (ShowTable(TableIndex.Event))
+ this.Children.Add(new EventTableTreeNode(module));
+ if (ShowTable(TableIndex.PropertyMap))
+ this.Children.Add(new PropertyMapTableTreeNode(module));
+ if (ShowTable(TableIndex.Property))
+ this.Children.Add(new PropertyTableTreeNode(module));
+ if (ShowTable(TableIndex.MethodSemantics))
+ this.Children.Add(new MethodSemanticsTableTreeNode(module));
+ if (ShowTable(TableIndex.MethodImpl))
+ this.Children.Add(new MethodImplTableTreeNode(module));
+ if (ShowTable(TableIndex.ModuleRef))
+ this.Children.Add(new ModuleRefTableTreeNode(module));
+ if (ShowTable(TableIndex.TypeSpec))
+ this.Children.Add(new TypeSpecTableTreeNode(module));
+ if (ShowTable(TableIndex.ImplMap))
+ this.Children.Add(new ImplMapTableTreeNode(module));
+ if (ShowTable(TableIndex.FieldRva))
+ this.Children.Add(new FieldRVATableTreeNode(module));
+ if (ShowTable(TableIndex.Assembly))
+ this.Children.Add(new AssemblyTableTreeNode(module));
+ if (ShowTable(TableIndex.AssemblyRef))
+ this.Children.Add(new AssemblyRefTableTreeNode(module));
+ if (ShowTable(TableIndex.File))
+ this.Children.Add(new FileTableTreeNode(module));
+ if (ShowTable(TableIndex.ExportedType))
+ this.Children.Add(new ExportedTypeTableTreeNode(module));
+ if (ShowTable(TableIndex.ManifestResource))
+ this.Children.Add(new ManifestResourceTableTreeNode(module));
+ if (ShowTable(TableIndex.NestedClass))
+ this.Children.Add(new NestedClassTableTreeNode(module));
+ if (ShowTable(TableIndex.GenericParam))
+ this.Children.Add(new GenericParamTableTreeNode(module));
+ if (ShowTable(TableIndex.MethodSpec))
+ this.Children.Add(new MethodSpecTableTreeNode(module));
+ if (ShowTable(TableIndex.GenericParamConstraint))
+ this.Children.Add(new GenericParamConstraintTableTreeNode(module));
+
+ bool ShowTable(TableIndex table) => !DisplaySettingsPanel.CurrentDisplaySettings.HideEmptyMetadataTables || module.Metadata.GetTableRowCount(table) > 0;
+
+ }
+
+ public override bool View(TabPageModel tabPage)
+ {
+ tabPage.Title = Text.ToString();
+ tabPage.SupportsLanguageSwitching = false;
+
+ return false;
+ }
+
+ public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
+ {
+ language.WriteCommentLine(output, "Metadata Tables");
+ }
+ }
+}
diff --git a/ILSpy/Metadata/MetadataTreeNode.cs b/ILSpy/Metadata/MetadataTreeNode.cs
index ebd96a069..03b98bf6a 100644
--- a/ILSpy/Metadata/MetadataTreeNode.cs
+++ b/ILSpy/Metadata/MetadataTreeNode.cs
@@ -17,20 +17,13 @@
// DEALINGS IN THE SOFTWARE.
using System;
-using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Reflection.Metadata;
-using System.Reflection.Metadata.Ecma335;
-using System.Reflection.PortableExecutable;
-using System.Text;
-using System.Threading.Tasks;
-using System.Windows;
using System.Windows.Data;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
-using ICSharpCode.ILSpy.Options;
using ICSharpCode.ILSpy.TreeNodes;
using ICSharpCode.ILSpy.ViewModels;
@@ -72,81 +65,17 @@ namespace ICSharpCode.ILSpy.Metadata
this.Children.Add(new OptionalHeaderTreeNode(module));
this.Children.Add(new DataDirectoriesTreeNode(module));
this.Children.Add(new DebugDirectoryTreeNode(module));
- if (ShowTable(TableIndex.Module))
- this.Children.Add(new ModuleTableTreeNode(module));
- if (ShowTable(TableIndex.TypeRef))
- this.Children.Add(new TypeRefTableTreeNode(module));
- if (ShowTable(TableIndex.TypeDef))
- this.Children.Add(new TypeDefTableTreeNode(module));
- if (ShowTable(TableIndex.Field))
- this.Children.Add(new FieldTableTreeNode(module));
- if (ShowTable(TableIndex.MethodDef))
- this.Children.Add(new MethodTableTreeNode(module));
- if (ShowTable(TableIndex.Param))
- this.Children.Add(new ParamTableTreeNode(module));
- if (ShowTable(TableIndex.InterfaceImpl))
- this.Children.Add(new InterfaceImplTableTreeNode(module));
- if (ShowTable(TableIndex.MemberRef))
- this.Children.Add(new MemberRefTableTreeNode(module));
- if (ShowTable(TableIndex.Constant))
- this.Children.Add(new ConstantTableTreeNode(module));
- if (ShowTable(TableIndex.CustomAttribute))
- this.Children.Add(new CustomAttributeTableTreeNode(module));
- if (ShowTable(TableIndex.FieldMarshal))
- this.Children.Add(new FieldMarshalTableTreeNode(module));
- if (ShowTable(TableIndex.DeclSecurity))
- this.Children.Add(new DeclSecurityTableTreeNode(module));
- if (ShowTable(TableIndex.ClassLayout))
- this.Children.Add(new ClassLayoutTableTreeNode(module));
- if (ShowTable(TableIndex.FieldLayout))
- this.Children.Add(new FieldLayoutTableTreeNode(module));
- if (ShowTable(TableIndex.StandAloneSig))
- this.Children.Add(new StandAloneSigTableTreeNode(module));
- if (ShowTable(TableIndex.EventMap))
- this.Children.Add(new EventMapTableTreeNode(module));
- if (ShowTable(TableIndex.Event))
- this.Children.Add(new EventTableTreeNode(module));
- if (ShowTable(TableIndex.PropertyMap))
- this.Children.Add(new PropertyMapTableTreeNode(module));
- if (ShowTable(TableIndex.Property))
- this.Children.Add(new PropertyTableTreeNode(module));
- if (ShowTable(TableIndex.MethodSemantics))
- this.Children.Add(new MethodSemanticsTableTreeNode(module));
- if (ShowTable(TableIndex.MethodImpl))
- this.Children.Add(new MethodImplTableTreeNode(module));
- if (ShowTable(TableIndex.ModuleRef))
- this.Children.Add(new ModuleRefTableTreeNode(module));
- if (ShowTable(TableIndex.TypeSpec))
- this.Children.Add(new TypeSpecTableTreeNode(module));
- if (ShowTable(TableIndex.ImplMap))
- this.Children.Add(new ImplMapTableTreeNode(module));
- if (ShowTable(TableIndex.FieldRva))
- this.Children.Add(new FieldRVATableTreeNode(module));
- if (ShowTable(TableIndex.Assembly))
- this.Children.Add(new AssemblyTableTreeNode(module));
- if (ShowTable(TableIndex.AssemblyRef))
- this.Children.Add(new AssemblyRefTableTreeNode(module));
- if (ShowTable(TableIndex.File))
- this.Children.Add(new FileTableTreeNode(module));
- if (ShowTable(TableIndex.ExportedType))
- this.Children.Add(new ExportedTypeTableTreeNode(module));
- if (ShowTable(TableIndex.ManifestResource))
- this.Children.Add(new ManifestResourceTableTreeNode(module));
- if (ShowTable(TableIndex.NestedClass))
- this.Children.Add(new NestedClassTableTreeNode(module));
- if (ShowTable(TableIndex.GenericParam))
- this.Children.Add(new GenericParamTableTreeNode(module));
- if (ShowTable(TableIndex.MethodSpec))
- this.Children.Add(new MethodSpecTableTreeNode(module));
- if (ShowTable(TableIndex.GenericParamConstraint))
- this.Children.Add(new GenericParamConstraintTableTreeNode(module));
-
- bool ShowTable(TableIndex table) => !DisplaySettingsPanel.CurrentDisplaySettings.HideEmptyMetadataTables || module.Metadata.GetTableRowCount(table) > 0;
+ this.Children.Add(new MetadataTablesTreeNode(module));
+ this.Children.Add(new StringHeapTreeNode(module, module.Metadata));
+ this.Children.Add(new UserStringHeapTreeNode(module, module.Metadata));
+ this.Children.Add(new GuidHeapTreeNode(module, module.Metadata));
+ this.Children.Add(new BlobHeapTreeNode(module, module.Metadata));
}
public MetadataTableTreeNode FindNodeByHandleKind(HandleKind kind)
{
- return this.Children.OfType().SingleOrDefault(x => x.Kind == kind);
+ return this.Children.OfType().Single()
+ .Children.OfType().SingleOrDefault(x => x.Kind == kind);
}
}