Browse Source

Work on metadata tooltips, performance, etc.

pull/1716/head
Siegfried Pammer 6 years ago
parent
commit
416b5efbe8
  1. 20
      ILSpy/Metadata/CorTables/AssemblyRefTableTreeNode.cs
  2. 19
      ILSpy/Metadata/CorTables/AssemblyTableTreeNode.cs
  3. 15
      ILSpy/Metadata/CorTables/ClassLayoutTableTreeNode.cs
  4. 21
      ILSpy/Metadata/CorTables/ConstantTableTreeNode.cs
  5. 15
      ILSpy/Metadata/CorTables/CustomAttributeTableTreeNode.cs
  6. 25
      ILSpy/Metadata/CorTables/DeclSecurityTableTreeNode.cs
  7. 13
      ILSpy/Metadata/CorTables/EventMapTableTreeNode.cs
  8. 22
      ILSpy/Metadata/CorTables/EventTableTreeNode.cs
  9. 34
      ILSpy/Metadata/CorTables/ExportedTypeTableTreeNode.cs
  10. 13
      ILSpy/Metadata/CorTables/FieldLayoutTableTreeNode.cs
  11. 17
      ILSpy/Metadata/CorTables/FieldMarshalTableTreeNode.cs
  12. 13
      ILSpy/Metadata/CorTables/FieldRVATableTreeNode.cs
  13. 52
      ILSpy/Metadata/CorTables/FieldTableTreeNode.cs
  14. 15
      ILSpy/Metadata/CorTables/FileTableTreeNode.cs
  15. 13
      ILSpy/Metadata/CorTables/GenericParamConstraintTableTreeNode.cs
  16. 24
      ILSpy/Metadata/CorTables/GenericParamTableTreeNode.cs
  17. 22
      ILSpy/Metadata/CorTables/ImplMapTableTreeNode.cs
  18. 13
      ILSpy/Metadata/CorTables/InterfaceImplTableTreeNode.cs
  19. 19
      ILSpy/Metadata/CorTables/ManifestResourceTableTreeNode.cs
  20. 18
      ILSpy/Metadata/CorTables/MemberRefTableTreeNode.cs
  21. 16
      ILSpy/Metadata/CorTables/MethodImplTableTreeNode.cs
  22. 29
      ILSpy/Metadata/CorTables/MethodSemanticsTableTreeNode.cs
  23. 24
      ILSpy/Metadata/CorTables/MethodSpecTableTreeNode.cs
  24. 33
      ILSpy/Metadata/CorTables/MethodTableTreeNode.cs
  25. 18
      ILSpy/Metadata/CorTables/ModuleRefTableTreeNode.cs
  26. 12
      ILSpy/Metadata/CorTables/ModuleTableTreeNode.cs
  27. 13
      ILSpy/Metadata/CorTables/NestedClassTableTreeNode.cs
  28. 18
      ILSpy/Metadata/CorTables/ParamTableTreeNode.cs
  29. 13
      ILSpy/Metadata/CorTables/PropertyMapTableTreeNode.cs
  30. 22
      ILSpy/Metadata/CorTables/PropertyTableTreeNode.cs
  31. 21
      ILSpy/Metadata/CorTables/StandAloneSigTableTreeNode.cs
  32. 53
      ILSpy/Metadata/CorTables/TypeDefTableTreeNode.cs
  33. 18
      ILSpy/Metadata/CorTables/TypeRefTableTreeNode.cs
  34. 17
      ILSpy/Metadata/CorTables/TypeSpecTableTreeNode.cs
  35. 11
      ILSpy/Metadata/DataGridCustomTextColumn.cs
  36. 20
      ILSpy/Metadata/FlagsFilterControl.xaml.cs
  37. 36
      ILSpy/Metadata/FlagsTooltip.xaml
  38. 135
      ILSpy/Metadata/FlagsTooltip.xaml.cs
  39. 25
      ILSpy/Metadata/Helpers.cs
  40. 4
      ILSpy/Metadata/MetadataProtocolHandler.cs
  41. 10
      ILSpy/Metadata/MetadataTableTreeNode.cs
  42. 8
      ILSpy/Metadata/MetadataTableViews.xaml
  43. 12
      ILSpy/Metadata/MetadataTreeNode.cs
  44. 28
      ILSpy/Metadata/OptionalHeaderTreeNode.cs

20
ILSpy/Metadata/CorTables/AssemblyRefTableTreeNode.cs

@ -46,14 +46,24 @@ namespace ICSharpCode.ILSpy.Metadata
var view = Helpers.PrepareDataGrid(tabPage); var view = Helpers.PrepareDataGrid(tabPage);
var metadata = module.Metadata; var metadata = module.Metadata;
var list = new List<AssemblyRefEntry>(); var list = new List<AssemblyRefEntry>();
AssemblyRefEntry scrollTargetEntry = default;
foreach (var row in metadata.AssemblyReferences) { foreach (var row in metadata.AssemblyReferences) {
list.Add(new AssemblyRefEntry(module, row)); AssemblyRefEntry entry = new AssemblyRefEntry(module, row);
if (scrollTarget == MetadataTokens.GetRowNumber(row)) {
scrollTargetEntry = entry;
}
list.Add(entry);
} }
view.ItemsSource = list; view.ItemsSource = list;
tabPage.Content = view; tabPage.Content = view;
if (scrollTargetEntry.RID > 0) {
view.ScrollIntoView(scrollTargetEntry);
this.scrollTarget = default;
}
return true; return true;
} }
@ -75,10 +85,14 @@ namespace ICSharpCode.ILSpy.Metadata
public Version Version => assemblyRef.Version; public Version Version => assemblyRef.Version;
[StringFormat("X8")]
public AssemblyFlags Flags => assemblyRef.Flags; public AssemblyFlags Flags => assemblyRef.Flags;
public object FlagsTooltip => new FlagsTooltip((int)assemblyRef.Flags, typeof(AssemblyFlags)); public object FlagsTooltip => new FlagsTooltip((int)assemblyRef.Flags, null) {
FlagGroup.CreateMultipleChoiceGroup(typeof(AssemblyFlags), selectedValue: (int)assemblyRef.Flags, includeAll: false)
};
[StringFormat("X")]
public int PublicKeyOrToken => MetadataTokens.GetHeapOffset(assemblyRef.PublicKeyOrToken); public int PublicKeyOrToken => MetadataTokens.GetHeapOffset(assemblyRef.PublicKeyOrToken);
public string PublicKeyOrTokenTooltip { public string PublicKeyOrTokenTooltip {

19
ILSpy/Metadata/CorTables/AssemblyTableTreeNode.cs

@ -44,12 +44,7 @@ namespace ICSharpCode.ILSpy.Metadata
tabPage.SupportsLanguageSwitching = false; tabPage.SupportsLanguageSwitching = false;
var view = Helpers.PrepareDataGrid(tabPage); var view = Helpers.PrepareDataGrid(tabPage);
var list = new List<AssemblyEntry>(); view.ItemsSource = new[] { new AssemblyEntry(module) };
list.Add(new AssemblyEntry(module));
view.ItemsSource = list;
tabPage.Content = view; tabPage.Content = view;
return true; return true;
} }
@ -69,13 +64,19 @@ namespace ICSharpCode.ILSpy.Metadata
+ metadata.GetTableMetadataOffset(TableIndex.Assembly) + metadata.GetTableMetadataOffset(TableIndex.Assembly)
+ metadata.GetTableRowSize(TableIndex.Assembly) * (RID - 1); + metadata.GetTableRowSize(TableIndex.Assembly) * (RID - 1);
public int HashAlgorithm => (int)assembly.HashAlgorithm; [StringFormat("X4")]
public AssemblyHashAlgorithm HashAlgorithm => assembly.HashAlgorithm;
public string HashAlgorithmTooltip => assembly.HashAlgorithm.ToString(); public object HashAlgorithmTooltip => new FlagsTooltip() {
FlagGroup.CreateSingleChoiceGroup(typeof(AssemblyHashAlgorithm), selectedValue: (int)assembly.HashAlgorithm, defaultFlag: new Flag("None (0000)", 0, false), includeAny: false)
};
[StringFormat("X4")]
public AssemblyFlags Flags => assembly.Flags; public AssemblyFlags Flags => assembly.Flags;
public object FlagsTooltip => new FlagsTooltip((int)assembly.Flags, typeof(AssemblyFlags)); public object FlagsTooltip => new FlagsTooltip() {
FlagGroup.CreateMultipleChoiceGroup(typeof(AssemblyFlags), selectedValue: (int)assembly.Flags, includeAll: false)
};
public Version Version => assembly.Version; public Version Version => assembly.Version;

15
ILSpy/Metadata/CorTables/ClassLayoutTableTreeNode.cs

@ -51,13 +51,24 @@ namespace ICSharpCode.ILSpy.Metadata
var length = metadata.GetTableRowCount(TableIndex.ClassLayout); var length = metadata.GetTableRowCount(TableIndex.ClassLayout);
byte* ptr = metadata.MetadataPointer; byte* ptr = metadata.MetadataPointer;
int metadataOffset = module.Reader.PEHeaders.MetadataStartOffset; int metadataOffset = module.Reader.PEHeaders.MetadataStartOffset;
ClassLayoutEntry scrollTargetEntry = default;
for (int rid = 1; rid <= length; rid++) { for (int rid = 1; rid <= length; rid++) {
list.Add(new ClassLayoutEntry(module, ptr, metadataOffset, rid)); ClassLayoutEntry entry = new ClassLayoutEntry(module, ptr, metadataOffset, rid);
if (scrollTarget == rid) {
scrollTargetEntry = entry;
}
list.Add(entry);
} }
view.ItemsSource = list; view.ItemsSource = list;
tabPage.Content = view; tabPage.Content = view;
if (scrollTargetEntry.RID > 0) {
view.ScrollIntoView(scrollTargetEntry);
this.scrollTarget = default;
}
return true; return true;
} }

21
ILSpy/Metadata/CorTables/ConstantTableTreeNode.cs

@ -48,14 +48,24 @@ namespace ICSharpCode.ILSpy.Metadata
var metadata = module.Metadata; var metadata = module.Metadata;
var list = new List<ConstantEntry>(); var list = new List<ConstantEntry>();
ConstantEntry scrollTargetEntry = default;
for (int row = 1; row <= metadata.GetTableRowCount(TableIndex.Constant); row++) { for (int row = 1; row <= metadata.GetTableRowCount(TableIndex.Constant); row++) {
list.Add(new ConstantEntry(module, MetadataTokens.ConstantHandle(row))); ConstantEntry entry = new ConstantEntry(module, MetadataTokens.ConstantHandle(row));
if (scrollTarget == row) {
scrollTargetEntry = entry;
}
list.Add(entry);
} }
view.ItemsSource = list; view.ItemsSource = list;
tabPage.Content = view; tabPage.Content = view;
if (scrollTargetEntry.RID > 0) {
view.ScrollIntoView(scrollTargetEntry);
this.scrollTarget = default;
}
return true; return true;
} }
@ -75,11 +85,13 @@ namespace ICSharpCode.ILSpy.Metadata
+ metadata.GetTableMetadataOffset(TableIndex.Constant) + metadata.GetTableMetadataOffset(TableIndex.Constant)
+ metadata.GetTableRowSize(TableIndex.Constant) * (RID - 1); + metadata.GetTableRowSize(TableIndex.Constant) * (RID - 1);
public int Type => (int)constant.TypeCode; [StringFormat("X8")]
public ConstantTypeCode Type => constant.TypeCode;
public string TypeTooltip => constant.TypeCode.ToString(); public string TypeTooltip => constant.TypeCode.ToString();
public int ParentHandle => MetadataTokens.GetToken(constant.Parent); [StringFormat("X8")]
public int Parent => MetadataTokens.GetToken(constant.Parent);
public string ParentTooltip { public string ParentTooltip {
get { get {
@ -90,6 +102,7 @@ namespace ICSharpCode.ILSpy.Metadata
} }
} }
[StringFormat("X")]
public int Value => MetadataTokens.GetHeapOffset(constant.Value); public int Value => MetadataTokens.GetHeapOffset(constant.Value);
public string ValueTooltip { public string ValueTooltip {

15
ILSpy/Metadata/CorTables/CustomAttributeTableTreeNode.cs

@ -47,14 +47,25 @@ namespace ICSharpCode.ILSpy.Metadata
var metadata = module.Metadata; var metadata = module.Metadata;
var list = new List<CustomAttributeEntry>(); var list = new List<CustomAttributeEntry>();
CustomAttributeEntry scrollTargetEntry = default;
foreach (var row in metadata.CustomAttributes) { foreach (var row in metadata.CustomAttributes) {
list.Add(new CustomAttributeEntry(module, row)); CustomAttributeEntry entry = new CustomAttributeEntry(module, row);
if (scrollTarget == MetadataTokens.GetRowNumber(row)) {
scrollTargetEntry = entry;
}
list.Add(entry);
} }
view.ItemsSource = list; view.ItemsSource = list;
tabPage.Content = view; tabPage.Content = view;
if (scrollTargetEntry.RID > 0) {
view.ScrollIntoView(scrollTargetEntry);
this.scrollTarget = default;
}
return true; return true;
} }
@ -98,7 +109,7 @@ namespace ICSharpCode.ILSpy.Metadata
} }
} }
[StringFormat("X8")] [StringFormat("X")]
public int Value => MetadataTokens.GetHeapOffset(customAttr.Value); public int Value => MetadataTokens.GetHeapOffset(customAttr.Value);
public string ValueTooltip { public string ValueTooltip {

25
ILSpy/Metadata/CorTables/DeclSecurityTableTreeNode.cs

@ -17,6 +17,7 @@
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System.Collections.Generic; using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Metadata; using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335; using System.Reflection.Metadata.Ecma335;
@ -47,14 +48,25 @@ namespace ICSharpCode.ILSpy.Metadata
var metadata = module.Metadata; var metadata = module.Metadata;
var list = new List<DeclSecurityEntry>(); var list = new List<DeclSecurityEntry>();
DeclSecurityEntry scrollTargetEntry = default;
foreach (var row in metadata.DeclarativeSecurityAttributes) { foreach (var row in metadata.DeclarativeSecurityAttributes) {
list.Add(new DeclSecurityEntry(module, row)); var entry = new DeclSecurityEntry(module, row);
if (scrollTarget == MetadataTokens.GetRowNumber(row)) {
scrollTargetEntry = entry;
}
list.Add(entry);
} }
view.ItemsSource = list; view.ItemsSource = list;
tabPage.Content = view; tabPage.Content = view;
if (scrollTargetEntry.RID > 0) {
view.ScrollIntoView(scrollTargetEntry);
this.scrollTarget = default;
}
return true; return true;
} }
@ -74,7 +86,8 @@ namespace ICSharpCode.ILSpy.Metadata
+ metadata.GetTableMetadataOffset(TableIndex.DeclSecurity) + metadata.GetTableMetadataOffset(TableIndex.DeclSecurity)
+ metadata.GetTableRowSize(TableIndex.DeclSecurity) * (RID - 1); + metadata.GetTableRowSize(TableIndex.DeclSecurity) * (RID - 1);
public int ParentHandle => MetadataTokens.GetToken(declSecAttr.Parent); [StringFormat("X8")]
public int Parent => MetadataTokens.GetToken(declSecAttr.Parent);
public string ParentTooltip { public string ParentTooltip {
get { get {
@ -85,15 +98,17 @@ namespace ICSharpCode.ILSpy.Metadata
} }
} }
public int Action => (int)declSecAttr.Action; [StringFormat("X8")]
public DeclarativeSecurityAction Action => declSecAttr.Action;
public string ActionTooltip { public string ActionTooltip {
get { get {
return null; return declSecAttr.Action.ToString();
} }
} }
public int PermissionSetHandle => MetadataTokens.GetHeapOffset(declSecAttr.PermissionSet); [StringFormat("X")]
public int PermissionSet => MetadataTokens.GetHeapOffset(declSecAttr.PermissionSet);
public string PermissionSetTooltip { public string PermissionSetTooltip {
get { get {

13
ILSpy/Metadata/CorTables/EventMapTableTreeNode.cs

@ -47,17 +47,28 @@ namespace ICSharpCode.ILSpy.Metadata
var metadata = module.Metadata; var metadata = module.Metadata;
var list = new List<EventMapEntry>(); var list = new List<EventMapEntry>();
EventMapEntry scrollTargetEntry = default;
var length = metadata.GetTableRowCount(TableIndex.EventMap); var length = metadata.GetTableRowCount(TableIndex.EventMap);
byte* ptr = metadata.MetadataPointer; byte* ptr = metadata.MetadataPointer;
int metadataOffset = module.Reader.PEHeaders.MetadataStartOffset; int metadataOffset = module.Reader.PEHeaders.MetadataStartOffset;
for (int rid = 1; rid <= length; rid++) { for (int rid = 1; rid <= length; rid++) {
list.Add(new EventMapEntry(module, ptr, metadataOffset, rid)); EventMapEntry entry = new EventMapEntry(module, ptr, metadataOffset, rid);
if (entry.RID == this.scrollTarget) {
scrollTargetEntry = entry;
}
list.Add(entry);
} }
view.ItemsSource = list; view.ItemsSource = list;
tabPage.Content = view; tabPage.Content = view;
if (scrollTargetEntry.RID > 0) {
view.ScrollIntoView(scrollTargetEntry);
this.scrollTarget = default;
}
return true; return true;
} }

22
ILSpy/Metadata/CorTables/EventTableTreeNode.cs

@ -50,13 +50,25 @@ namespace ICSharpCode.ILSpy.Metadata
var metadata = module.Metadata; var metadata = module.Metadata;
var list = new List<EventDefEntry>(); var list = new List<EventDefEntry>();
EventDefEntry scrollTargetEntry = default;
foreach (var row in metadata.EventDefinitions) foreach (var row in metadata.EventDefinitions) {
list.Add(new EventDefEntry(module, row)); EventDefEntry entry = new EventDefEntry(module, row);
if (entry.RID == this.scrollTarget) {
scrollTargetEntry = entry;
}
list.Add(entry);
}
view.ItemsSource = list; view.ItemsSource = list;
tabPage.Content = view; tabPage.Content = view;
if (scrollTargetEntry.RID > 0) {
view.ScrollIntoView(scrollTargetEntry);
this.scrollTarget = default;
}
return true; return true;
} }
@ -76,9 +88,12 @@ namespace ICSharpCode.ILSpy.Metadata
+ metadata.GetTableMetadataOffset(TableIndex.Event) + metadata.GetTableMetadataOffset(TableIndex.Event)
+ metadata.GetTableRowSize(TableIndex.Event) * (RID - 1); + metadata.GetTableRowSize(TableIndex.Event) * (RID - 1);
[StringFormat("X8")]
public EventAttributes Attributes => eventDef.Attributes; public EventAttributes Attributes => eventDef.Attributes;
public object AttributesTooltip => new FlagsTooltip((int)eventDef.Attributes, typeof(EventAttributes)); public object AttributesTooltip => new FlagsTooltip {
FlagGroup.CreateMultipleChoiceGroup(typeof(EventAttributes), selectedValue: (int)eventDef.Attributes, includeAll: false),
};
public string NameTooltip => $"{MetadataTokens.GetHeapOffset(eventDef.Name):X} \"{Name}\""; public string NameTooltip => $"{MetadataTokens.GetHeapOffset(eventDef.Name):X} \"{Name}\"";
@ -86,6 +101,7 @@ namespace ICSharpCode.ILSpy.Metadata
IEntity IMemberTreeNode.Member => ((MetadataModule)module.GetTypeSystemOrNull()?.MainModule).GetDefinition(handle); IEntity IMemberTreeNode.Member => ((MetadataModule)module.GetTypeSystemOrNull()?.MainModule).GetDefinition(handle);
[StringFormat("X8")]
public int Type => MetadataTokens.GetToken(eventDef.Type); public int Type => MetadataTokens.GetToken(eventDef.Type);
public string TypeTooltip { public string TypeTooltip {

34
ILSpy/Metadata/CorTables/ExportedTypeTableTreeNode.cs

@ -22,6 +22,7 @@ using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335; using System.Reflection.Metadata.Ecma335;
using ICSharpCode.Decompiler; using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.IL;
using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.Metadata;
namespace ICSharpCode.ILSpy.Metadata namespace ICSharpCode.ILSpy.Metadata
@ -45,20 +46,32 @@ namespace ICSharpCode.ILSpy.Metadata
var view = Helpers.PrepareDataGrid(tabPage); var view = Helpers.PrepareDataGrid(tabPage);
var metadata = module.Metadata; var metadata = module.Metadata;
var list = new List<ExportedTypeEntry>(); var list = new List<ExportedTypeEntry>();
ExportedTypeEntry scrollTargetEntry = default;
foreach (var row in metadata.ExportedTypes) { foreach (var row in metadata.ExportedTypes) {
list.Add(new ExportedTypeEntry(module.Reader.PEHeaders.MetadataStartOffset, metadata, row, metadata.GetExportedType(row))); ExportedTypeEntry entry = new ExportedTypeEntry(module.Reader.PEHeaders.MetadataStartOffset, module, row, metadata.GetExportedType(row));
if (entry.RID == this.scrollTarget) {
scrollTargetEntry = entry;
}
list.Add(entry);
} }
view.ItemsSource = list; view.ItemsSource = list;
tabPage.Content = view; tabPage.Content = view;
if (scrollTargetEntry.RID > 0) {
view.ScrollIntoView(scrollTargetEntry);
this.scrollTarget = default;
}
return true; return true;
} }
struct ExportedTypeEntry struct ExportedTypeEntry
{ {
readonly int metadataOffset; readonly int metadataOffset;
readonly PEFile module;
readonly MetadataReader metadata; readonly MetadataReader metadata;
readonly ExportedTypeHandle handle; readonly ExportedTypeHandle handle;
readonly ExportedType type; readonly ExportedType type;
@ -85,12 +98,25 @@ namespace ICSharpCode.ILSpy.Metadata
public string TypeNamespace => metadata.GetString(type.Name); public string TypeNamespace => metadata.GetString(type.Name);
[StringFormat("X8")]
public int Implementation => MetadataTokens.GetToken(type.Implementation); public int Implementation => MetadataTokens.GetToken(type.Implementation);
public ExportedTypeEntry(int metadataOffset, MetadataReader metadata, ExportedTypeHandle handle, ExportedType type) public string ImplementationTooltip {
get {
if (type.Implementation.IsNil)
return null;
ITextOutput output = new PlainTextOutput();
var context = new GenericContext(default(TypeDefinitionHandle), module);
type.Implementation.WriteTo(module, output, context);
return output.ToString();
}
}
public ExportedTypeEntry(int metadataOffset, PEFile module, ExportedTypeHandle handle, ExportedType type)
{ {
this.metadataOffset = metadataOffset; this.metadataOffset = metadataOffset;
this.metadata = metadata; this.module = module;
this.metadata = module.Metadata;
this.handle = handle; this.handle = handle;
this.type = type; this.type = type;
} }

13
ILSpy/Metadata/CorTables/FieldLayoutTableTreeNode.cs

@ -47,17 +47,28 @@ namespace ICSharpCode.ILSpy.Metadata
var metadata = module.Metadata; var metadata = module.Metadata;
var list = new List<FieldLayoutEntry>(); var list = new List<FieldLayoutEntry>();
FieldLayoutEntry scrollTargetEntry = default;
var length = metadata.GetTableRowCount(TableIndex.FieldLayout); var length = metadata.GetTableRowCount(TableIndex.FieldLayout);
byte* ptr = metadata.MetadataPointer; byte* ptr = metadata.MetadataPointer;
int metadataOffset = module.Reader.PEHeaders.MetadataStartOffset; int metadataOffset = module.Reader.PEHeaders.MetadataStartOffset;
for (int rid = 1; rid <= length; rid++) { for (int rid = 1; rid <= length; rid++) {
list.Add(new FieldLayoutEntry(module, ptr, metadataOffset, rid)); FieldLayoutEntry entry = new FieldLayoutEntry(module, ptr, metadataOffset, rid);
if (entry.RID == this.scrollTarget) {
scrollTargetEntry = entry;
}
list.Add(entry);
} }
view.ItemsSource = list; view.ItemsSource = list;
tabPage.Content = view; tabPage.Content = view;
if (scrollTargetEntry.RID > 0) {
view.ScrollIntoView(scrollTargetEntry);
this.scrollTarget = default;
}
return true; return true;
} }

17
ILSpy/Metadata/CorTables/FieldMarshalTableTreeNode.cs

@ -47,17 +47,28 @@ namespace ICSharpCode.ILSpy.Metadata
var metadata = module.Metadata; var metadata = module.Metadata;
var list = new List<FieldMarshalEntry>(); var list = new List<FieldMarshalEntry>();
FieldMarshalEntry scrollTargetEntry = default;
var length = metadata.GetTableRowCount(TableIndex.FieldMarshal); var length = metadata.GetTableRowCount(TableIndex.FieldMarshal);
byte* ptr = metadata.MetadataPointer; byte* ptr = metadata.MetadataPointer;
int metadataOffset = module.Reader.PEHeaders.MetadataStartOffset; int metadataOffset = module.Reader.PEHeaders.MetadataStartOffset;
for (int rid = 1; rid <= length; rid++) { for (int rid = 1; rid <= length; rid++) {
list.Add(new FieldMarshalEntry(module, ptr, metadataOffset, rid)); FieldMarshalEntry entry = new FieldMarshalEntry(module, ptr, metadataOffset, rid);
if (entry.RID == this.scrollTarget) {
scrollTargetEntry = entry;
}
list.Add(entry);
} }
view.ItemsSource = list; view.ItemsSource = list;
tabPage.Content = view; tabPage.Content = view;
if (scrollTargetEntry.RID > 0) {
view.ScrollIntoView(scrollTargetEntry);
this.scrollTarget = default;
}
return true; return true;
} }
@ -97,8 +108,8 @@ namespace ICSharpCode.ILSpy.Metadata
} }
} }
[StringFormat("X8")] [StringFormat("X")]
public int NativeType => (int)MetadataTokens.GetHeapOffset(fieldMarshal.NativeType); public int NativeType => MetadataTokens.GetHeapOffset(fieldMarshal.NativeType);
public FieldMarshalEntry(PEFile module, byte* ptr, int metadataOffset, int row) public FieldMarshalEntry(PEFile module, byte* ptr, int metadataOffset, int row)
{ {

13
ILSpy/Metadata/CorTables/FieldRVATableTreeNode.cs

@ -47,17 +47,28 @@ namespace ICSharpCode.ILSpy.Metadata
var metadata = module.Metadata; var metadata = module.Metadata;
var list = new List<FieldRVAEntry>(); var list = new List<FieldRVAEntry>();
FieldRVAEntry scrollTargetEntry = default;
var length = metadata.GetTableRowCount(TableIndex.FieldRva); var length = metadata.GetTableRowCount(TableIndex.FieldRva);
byte* ptr = metadata.MetadataPointer; byte* ptr = metadata.MetadataPointer;
int metadataOffset = module.Reader.PEHeaders.MetadataStartOffset; int metadataOffset = module.Reader.PEHeaders.MetadataStartOffset;
for (int rid = 1; rid <= length; rid++) { for (int rid = 1; rid <= length; rid++) {
list.Add(new FieldRVAEntry(module, ptr, metadataOffset, rid)); FieldRVAEntry entry = new FieldRVAEntry(module, ptr, metadataOffset, rid);
if (entry.RID == this.scrollTarget) {
scrollTargetEntry = entry;
}
list.Add(entry);
} }
view.ItemsSource = list; view.ItemsSource = list;
tabPage.Content = view; tabPage.Content = view;
if (scrollTargetEntry.RID > 0) {
view.ScrollIntoView(scrollTargetEntry);
this.scrollTarget = default;
}
return true; return true;
} }

52
ILSpy/Metadata/CorTables/FieldTableTreeNode.cs

@ -16,11 +16,14 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Reflection; using System.Reflection;
using System.Reflection.Metadata; using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335; using System.Reflection.Metadata.Ecma335;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Threading;
using ICSharpCode.Decompiler; using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Disassembler; using ICSharpCode.Decompiler.Disassembler;
using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.IL;
@ -45,18 +48,30 @@ namespace ICSharpCode.ILSpy.Metadata
{ {
tabPage.Title = Text.ToString(); tabPage.Title = Text.ToString();
tabPage.SupportsLanguageSwitching = false; tabPage.SupportsLanguageSwitching = false;
var view = Helpers.PrepareDataGrid(tabPage); var view = Helpers.PrepareDataGrid(tabPage);
var metadata = module.Metadata; var metadata = module.Metadata;
var list = new List<FieldDefEntry>(); var list = new List<FieldDefEntry>();
foreach (var row in metadata.FieldDefinitions) FieldDefEntry scrollTargetEntry = default;
list.Add(new FieldDefEntry(module, row));
foreach (var row in metadata.FieldDefinitions) {
var entry = new FieldDefEntry(module, row);
if (scrollTarget.Equals(row)) {
scrollTargetEntry = entry;
}
list.Add(entry);
}
view.ItemsSource = list; view.ItemsSource = list;
tabPage.Content = view; tabPage.Content = view;
if (scrollTargetEntry.RID > 0) {
view.ScrollIntoView(scrollTargetEntry);
this.scrollTarget = default;
}
return true; return true;
} }
@ -76,9 +91,15 @@ namespace ICSharpCode.ILSpy.Metadata
+ metadata.GetTableMetadataOffset(TableIndex.Field) + metadata.GetTableMetadataOffset(TableIndex.Field)
+ metadata.GetTableRowSize(TableIndex.Field) * (RID - 1); + metadata.GetTableRowSize(TableIndex.Field) * (RID - 1);
[StringFormat("X8")]
public FieldAttributes Attributes => fieldDef.Attributes; public FieldAttributes Attributes => fieldDef.Attributes;
public object AttributesTooltip => new FlagsTooltip((int)fieldDef.Attributes, typeof(FieldAttributes)); const FieldAttributes otherFlagsMask = ~(FieldAttributes.FieldAccessMask);
public object AttributesTooltip => new FlagsTooltip() {
FlagGroup.CreateSingleChoiceGroup(typeof(FieldAttributes), "Field access: ", (int)FieldAttributes.FieldAccessMask, (int)(fieldDef.Attributes & FieldAttributes.FieldAccessMask), new Flag("CompilerControlled (0000)", 0, false), includeAny: false),
FlagGroup.CreateMultipleChoiceGroup(typeof(FieldAttributes), "Flags:", (int)otherFlagsMask, (int)(fieldDef.Attributes & otherFlagsMask), includeAll: false),
};
public string Name => metadata.GetString(fieldDef.Name); public string Name => metadata.GetString(fieldDef.Name);
@ -86,7 +107,7 @@ namespace ICSharpCode.ILSpy.Metadata
IEntity IMemberTreeNode.Member => ((MetadataModule)module.GetTypeSystemOrNull()?.MainModule).GetDefinition(handle); IEntity IMemberTreeNode.Member => ((MetadataModule)module.GetTypeSystemOrNull()?.MainModule).GetDefinition(handle);
[StringFormat("X8")] [StringFormat("X")]
public int Signature => MetadataTokens.GetHeapOffset(fieldDef.Signature); public int Signature => MetadataTokens.GetHeapOffset(fieldDef.Signature);
public string SignatureTooltip { public string SignatureTooltip {
@ -114,3 +135,22 @@ namespace ICSharpCode.ILSpy.Metadata
} }
} }
} }
class Time : IDisposable
{
readonly System.Diagnostics.Stopwatch stopwatch;
readonly string title;
public Time(string title)
{
this.title = title;
this.stopwatch = new System.Diagnostics.Stopwatch();
stopwatch.Start();
}
public void Dispose()
{
stopwatch.Stop();
System.Diagnostics.Debug.WriteLine(title + " took " + stopwatch.ElapsedMilliseconds + "ms");
}
}

15
ILSpy/Metadata/CorTables/FileTableTreeNode.cs

@ -45,14 +45,25 @@ namespace ICSharpCode.ILSpy.Metadata
var metadata = module.Metadata; var metadata = module.Metadata;
var list = new List<FileEntry>(); var list = new List<FileEntry>();
FileEntry scrollTargetEntry = default;
foreach (var row in metadata.AssemblyFiles) { foreach (var row in metadata.AssemblyFiles) {
list.Add(new FileEntry(module, row)); FileEntry entry = new FileEntry(module, row);
if (entry.RID == this.scrollTarget) {
scrollTargetEntry = entry;
}
list.Add(entry);
} }
view.ItemsSource = list; view.ItemsSource = list;
tabPage.Content = view; tabPage.Content = view;
if (scrollTargetEntry.RID > 0) {
view.ScrollIntoView(scrollTargetEntry);
this.scrollTarget = default;
}
return true; return true;
} }
@ -72,6 +83,7 @@ namespace ICSharpCode.ILSpy.Metadata
+ metadata.GetTableMetadataOffset(TableIndex.File) + metadata.GetTableMetadataOffset(TableIndex.File)
+ metadata.GetTableRowSize(TableIndex.File) * (RID - 1); + metadata.GetTableRowSize(TableIndex.File) * (RID - 1);
[StringFormat("X8")]
public int Attributes => assemblyFile.ContainsMetadata ? 1 : 0; public int Attributes => assemblyFile.ContainsMetadata ? 1 : 0;
public string AttributesTooltip => assemblyFile.ContainsMetadata ? "ContainsMetaData" : "ContainsNoMetaData"; public string AttributesTooltip => assemblyFile.ContainsMetadata ? "ContainsMetaData" : "ContainsNoMetaData";
@ -80,6 +92,7 @@ namespace ICSharpCode.ILSpy.Metadata
public string NameTooltip => $"{MetadataTokens.GetHeapOffset(assemblyFile.Name):X} \"{Name}\""; public string NameTooltip => $"{MetadataTokens.GetHeapOffset(assemblyFile.Name):X} \"{Name}\"";
[StringFormat("X")]
public int HashValue => MetadataTokens.GetHeapOffset(assemblyFile.HashValue); public int HashValue => MetadataTokens.GetHeapOffset(assemblyFile.HashValue);
public string HashValueTooltip { public string HashValueTooltip {

13
ILSpy/Metadata/CorTables/GenericParamConstraintTableTreeNode.cs

@ -47,13 +47,24 @@ namespace ICSharpCode.ILSpy.Metadata
var metadata = module.Metadata; var metadata = module.Metadata;
var list = new List<GenericParamConstraintEntry>(); var list = new List<GenericParamConstraintEntry>();
GenericParamConstraintEntry scrollTargetEntry = default;
for (int row = 1; row <= metadata.GetTableRowCount(TableIndex.GenericParamConstraint); row++) { for (int row = 1; row <= metadata.GetTableRowCount(TableIndex.GenericParamConstraint); row++) {
list.Add(new GenericParamConstraintEntry(module, MetadataTokens.GenericParameterConstraintHandle(row))); GenericParamConstraintEntry entry = new GenericParamConstraintEntry(module, MetadataTokens.GenericParameterConstraintHandle(row));
if (entry.RID == this.scrollTarget) {
scrollTargetEntry = entry;
}
list.Add(entry);
} }
view.ItemsSource = list; view.ItemsSource = list;
tabPage.Content = view; tabPage.Content = view;
if (scrollTargetEntry.RID > 0) {
view.ScrollIntoView(scrollTargetEntry);
this.scrollTarget = default;
}
return true; return true;
} }

24
ILSpy/Metadata/CorTables/GenericParamTableTreeNode.cs

@ -48,13 +48,24 @@ namespace ICSharpCode.ILSpy.Metadata
var metadata = module.Metadata; var metadata = module.Metadata;
var list = new List<GenericParamEntry>(); var list = new List<GenericParamEntry>();
GenericParamEntry scrollTargetEntry = default;
for (int row = 1; row <= module.Metadata.GetTableRowCount(TableIndex.GenericParam); row++) { for (int row = 1; row <= module.Metadata.GetTableRowCount(TableIndex.GenericParam); row++) {
list.Add(new GenericParamEntry(module, MetadataTokens.GenericParameterHandle(row))); GenericParamEntry entry = new GenericParamEntry(module, MetadataTokens.GenericParameterHandle(row));
if (entry.RID == this.scrollTarget) {
scrollTargetEntry = entry;
}
list.Add(entry);
} }
view.ItemsSource = list; view.ItemsSource = list;
tabPage.Content = view; tabPage.Content = view;
if (scrollTargetEntry.RID > 0) {
view.ScrollIntoView(scrollTargetEntry);
this.scrollTarget = default;
}
return true; return true;
} }
@ -76,13 +87,18 @@ namespace ICSharpCode.ILSpy.Metadata
public int Number => genericParam.Index; public int Number => genericParam.Index;
[StringFormat("X8")]
public GenericParameterAttributes Attributes => genericParam.Attributes; public GenericParameterAttributes Attributes => genericParam.Attributes;
public object AttributesTooltip => new FlagsTooltip((int)genericParam.Attributes, typeof(GenericParameterAttributes)); public object AttributesTooltip => new FlagsTooltip {
FlagGroup.CreateSingleChoiceGroup(typeof(GenericParameterAttributes), "Code type: ", (int)GenericParameterAttributes.VarianceMask, (int)(genericParam.Attributes & GenericParameterAttributes.VarianceMask), new Flag("None (0000)", 0, false), includeAny: false),
FlagGroup.CreateSingleChoiceGroup(typeof(GenericParameterAttributes), "Managed type: ", (int)GenericParameterAttributes.SpecialConstraintMask, (int)(genericParam.Attributes & GenericParameterAttributes.SpecialConstraintMask), new Flag("None (0000)", 0, false), includeAny: false),
};
public int OwnerHandle => MetadataTokens.GetToken(genericParam.Parent); [StringFormat("X8")]
public int Owner => MetadataTokens.GetToken(genericParam.Parent);
public string Owner { public string OwnerTooltip {
get { get {
ITextOutput output = new PlainTextOutput(); ITextOutput output = new PlainTextOutput();
genericParam.Parent.WriteTo(module, output, GenericContext.Empty); genericParam.Parent.WriteTo(module, output, GenericContext.Empty);

22
ILSpy/Metadata/CorTables/ImplMapTableTreeNode.cs

@ -49,17 +49,28 @@ namespace ICSharpCode.ILSpy.Metadata
var metadata = module.Metadata; var metadata = module.Metadata;
var list = new List<ImplMapEntry>(); var list = new List<ImplMapEntry>();
ImplMapEntry scrollTargetEntry = default;
var length = metadata.GetTableRowCount(TableIndex.ImplMap); var length = metadata.GetTableRowCount(TableIndex.ImplMap);
byte* ptr = metadata.MetadataPointer; byte* ptr = metadata.MetadataPointer;
int metadataOffset = module.Reader.PEHeaders.MetadataStartOffset; int metadataOffset = module.Reader.PEHeaders.MetadataStartOffset;
for (int rid = 1; rid <= length; rid++) { for (int rid = 1; rid <= length; rid++) {
list.Add(new ImplMapEntry(module, ptr, metadataOffset, rid)); ImplMapEntry entry = new ImplMapEntry(module, ptr, metadataOffset, rid);
if (entry.RID == this.scrollTarget) {
scrollTargetEntry = entry;
}
list.Add(entry);
} }
view.ItemsSource = list; view.ItemsSource = list;
tabPage.Content = view; tabPage.Content = view;
if (scrollTargetEntry.RID > 0) {
view.ScrollIntoView(scrollTargetEntry);
this.scrollTarget = default;
}
return true; return true;
} }
@ -91,9 +102,16 @@ namespace ICSharpCode.ILSpy.Metadata
public int Offset { get; } public int Offset { get; }
[StringFormat("X8")]
public PInvokeAttributes MappingFlags => implMap.MappingFlags; public PInvokeAttributes MappingFlags => implMap.MappingFlags;
public object MappingFlagsTooltip => new FlagsTooltip((int)implMap.MappingFlags, typeof(PInvokeAttributes)); const PInvokeAttributes otherFlagsMask = ~(PInvokeAttributes.CallConvMask | PInvokeAttributes.CharSetMask);
public object MappingFlagsTooltip => new FlagsTooltip {
FlagGroup.CreateSingleChoiceGroup(typeof(PInvokeAttributes), "Character set: ", (int)PInvokeAttributes.CharSetMask, (int)(implMap.MappingFlags & PInvokeAttributes.CharSetMask), new Flag("CharSetNotSpec (0000)", 0, false), includeAny: false),
FlagGroup.CreateSingleChoiceGroup(typeof(PInvokeAttributes), "Calling convention: ", (int)PInvokeAttributes.CallConvMask, (int)(implMap.MappingFlags & PInvokeAttributes.CallConvMask), new Flag("Invalid (0000)", 0, false), includeAny: false),
FlagGroup.CreateMultipleChoiceGroup(typeof(PInvokeAttributes), "Flags:", (int)otherFlagsMask, (int)(implMap.MappingFlags & otherFlagsMask), includeAll: false),
};
[StringFormat("X8")] [StringFormat("X8")]
public int MemberForwarded => MetadataTokens.GetToken(implMap.MemberForwarded); public int MemberForwarded => MetadataTokens.GetToken(implMap.MemberForwarded);

13
ILSpy/Metadata/CorTables/InterfaceImplTableTreeNode.cs

@ -47,17 +47,28 @@ namespace ICSharpCode.ILSpy.Metadata
var metadata = module.Metadata; var metadata = module.Metadata;
var list = new List<InterfaceImplEntry>(); var list = new List<InterfaceImplEntry>();
InterfaceImplEntry scrollTargetEntry = default;
var length = metadata.GetTableRowCount(TableIndex.InterfaceImpl); var length = metadata.GetTableRowCount(TableIndex.InterfaceImpl);
byte* ptr = metadata.MetadataPointer; byte* ptr = metadata.MetadataPointer;
int metadataOffset = module.Reader.PEHeaders.MetadataStartOffset; int metadataOffset = module.Reader.PEHeaders.MetadataStartOffset;
for (int rid = 1; rid <= length; rid++) { for (int rid = 1; rid <= length; rid++) {
list.Add(new InterfaceImplEntry(module, ptr, metadataOffset, rid)); InterfaceImplEntry entry = new InterfaceImplEntry(module, ptr, metadataOffset, rid);
if (entry.RID == this.scrollTarget) {
scrollTargetEntry = entry;
}
list.Add(entry);
} }
view.ItemsSource = list; view.ItemsSource = list;
tabPage.Content = view; tabPage.Content = view;
if (scrollTargetEntry.RID > 0) {
view.ScrollIntoView(scrollTargetEntry);
this.scrollTarget = default;
}
return true; return true;
} }

19
ILSpy/Metadata/CorTables/ManifestResourceTableTreeNode.cs

@ -48,14 +48,25 @@ namespace ICSharpCode.ILSpy.Metadata
var metadata = module.Metadata; var metadata = module.Metadata;
var list = new List<ManifestResourceEntry>(); var list = new List<ManifestResourceEntry>();
ManifestResourceEntry scrollTargetEntry = default;
foreach (var row in metadata.ManifestResources) { foreach (var row in metadata.ManifestResources) {
list.Add(new ManifestResourceEntry(module, row)); ManifestResourceEntry entry = new ManifestResourceEntry(module, row);
if (entry.RID == this.scrollTarget) {
scrollTargetEntry = entry;
}
list.Add(entry);
} }
view.ItemsSource = list; view.ItemsSource = list;
tabPage.Content = view; tabPage.Content = view;
if (scrollTargetEntry.RID > 0) {
view.ScrollIntoView(scrollTargetEntry);
this.scrollTarget = default;
}
return true; return true;
} }
@ -75,15 +86,17 @@ namespace ICSharpCode.ILSpy.Metadata
+ metadata.GetTableMetadataOffset(TableIndex.ManifestResource) + metadata.GetTableMetadataOffset(TableIndex.ManifestResource)
+ metadata.GetTableRowSize(TableIndex.ManifestResource) * (RID - 1); + metadata.GetTableRowSize(TableIndex.ManifestResource) * (RID - 1);
[StringFormat("X8")]
public ManifestResourceAttributes Attributes => manifestResource.Attributes; public ManifestResourceAttributes Attributes => manifestResource.Attributes;
public object AttributesTooltip => new FlagsTooltip((int)manifestResource.Attributes, typeof(ManifestResourceAttributes)); public object AttributesTooltip => manifestResource.Attributes.ToString();
public string Name => metadata.GetString(manifestResource.Name); public string Name => metadata.GetString(manifestResource.Name);
public string NameTooltip => $"{MetadataTokens.GetHeapOffset(manifestResource.Name):X} \"{Name}\""; public string NameTooltip => $"{MetadataTokens.GetHeapOffset(manifestResource.Name):X} \"{Name}\"";
public int ImplementationHandle => MetadataTokens.GetToken(manifestResource.Implementation); [StringFormat("X8")]
public int Implementation => MetadataTokens.GetToken(manifestResource.Implementation);
public string ImplementationTooltip { public string ImplementationTooltip {
get { get {

18
ILSpy/Metadata/CorTables/MemberRefTableTreeNode.cs

@ -47,13 +47,25 @@ namespace ICSharpCode.ILSpy.Metadata
var metadata = module.Metadata; var metadata = module.Metadata;
var list = new List<MemberRefEntry>(); var list = new List<MemberRefEntry>();
MemberRefEntry scrollTargetEntry = default;
foreach (var row in metadata.MemberReferences) foreach (var row in metadata.MemberReferences) {
list.Add(new MemberRefEntry(module, row)); MemberRefEntry entry = new MemberRefEntry(module, row);
if (entry.RID == this.scrollTarget) {
scrollTargetEntry = entry;
}
list.Add(entry);
}
view.ItemsSource = list; view.ItemsSource = list;
tabPage.Content = view; tabPage.Content = view;
if (scrollTargetEntry.RID > 0) {
view.ScrollIntoView(scrollTargetEntry);
this.scrollTarget = default;
}
return true; return true;
} }
@ -88,7 +100,7 @@ namespace ICSharpCode.ILSpy.Metadata
public string NameTooltip => $"{MetadataTokens.GetHeapOffset(memberRef.Name):X} \"{Name}\""; public string NameTooltip => $"{MetadataTokens.GetHeapOffset(memberRef.Name):X} \"{Name}\"";
[StringFormat("X8")] [StringFormat("X")]
public int Signature => MetadataTokens.GetHeapOffset(memberRef.Signature); public int Signature => MetadataTokens.GetHeapOffset(memberRef.Signature);
public string SignatureTooltip { public string SignatureTooltip {

16
ILSpy/Metadata/CorTables/MethodImplTableTreeNode.cs

@ -47,14 +47,25 @@ namespace ICSharpCode.ILSpy.Metadata
var metadata = module.Metadata; var metadata = module.Metadata;
var list = new List<MethodImplEntry>(); var list = new List<MethodImplEntry>();
MethodImplEntry scrollTargetEntry = default;
for (int row = 1; row <= module.Metadata.GetTableRowCount(TableIndex.MethodImpl); row++) { for (int row = 1; row <= module.Metadata.GetTableRowCount(TableIndex.MethodImpl); row++) {
list.Add(new MethodImplEntry(module, MetadataTokens.MethodImplementationHandle(row))); MethodImplEntry entry = new MethodImplEntry(module, MetadataTokens.MethodImplementationHandle(row));
if (entry.RID == this.scrollTarget) {
scrollTargetEntry = entry;
}
list.Add(entry);
} }
view.ItemsSource = list; view.ItemsSource = list;
tabPage.Content = view; tabPage.Content = view;
if (scrollTargetEntry.RID > 0) {
view.ScrollIntoView(scrollTargetEntry);
this.scrollTarget = default;
}
return true; return true;
} }
@ -74,6 +85,7 @@ namespace ICSharpCode.ILSpy.Metadata
+ metadata.GetTableMetadataOffset(TableIndex.MethodDef) + metadata.GetTableMetadataOffset(TableIndex.MethodDef)
+ metadata.GetTableRowSize(TableIndex.MethodDef) * (RID - 1); + metadata.GetTableRowSize(TableIndex.MethodDef) * (RID - 1);
[StringFormat("X8")]
public int MethodDeclaration => MetadataTokens.GetToken(methodImpl.MethodDeclaration); public int MethodDeclaration => MetadataTokens.GetToken(methodImpl.MethodDeclaration);
public string MethodDeclarationTooltip { public string MethodDeclarationTooltip {
@ -84,6 +96,7 @@ namespace ICSharpCode.ILSpy.Metadata
} }
} }
[StringFormat("X8")]
public int MethodBody => MetadataTokens.GetToken(methodImpl.MethodBody); public int MethodBody => MetadataTokens.GetToken(methodImpl.MethodBody);
public string MethodBodyTooltip { public string MethodBodyTooltip {
@ -94,6 +107,7 @@ namespace ICSharpCode.ILSpy.Metadata
} }
} }
[StringFormat("X8")]
public int Type => MetadataTokens.GetToken(methodImpl.Type); public int Type => MetadataTokens.GetToken(methodImpl.Type);
public string TypeTooltip { public string TypeTooltip {

29
ILSpy/Metadata/CorTables/MethodSemanticsTableTreeNode.cs

@ -48,13 +48,25 @@ namespace ICSharpCode.ILSpy.Metadata
var metadata = module.Metadata; var metadata = module.Metadata;
var list = new List<MethodSemanticsEntry>(); var list = new List<MethodSemanticsEntry>();
MethodSemanticsEntry scrollTargetEntry = default;
foreach (var row in metadata.GetMethodSemantics()) foreach (var row in metadata.GetMethodSemantics()) {
list.Add(new MethodSemanticsEntry(module, row.Handle, row.Semantics, row.Method, row.Association)); MethodSemanticsEntry entry = new MethodSemanticsEntry(module, row.Handle, row.Semantics, row.Method, row.Association);
if (entry.RID == this.scrollTarget) {
scrollTargetEntry = entry;
}
list.Add(entry);
}
view.ItemsSource = list; view.ItemsSource = list;
tabPage.Content = view; tabPage.Content = view;
if (scrollTargetEntry.RID > 0) {
view.ScrollIntoView(scrollTargetEntry);
this.scrollTarget = default;
}
return true; return true;
} }
@ -76,13 +88,15 @@ namespace ICSharpCode.ILSpy.Metadata
+ metadata.GetTableMetadataOffset(TableIndex.MethodDef) + metadata.GetTableMetadataOffset(TableIndex.MethodDef)
+ metadata.GetTableRowSize(TableIndex.MethodDef) * (RID - 1); + metadata.GetTableRowSize(TableIndex.MethodDef) * (RID - 1);
public int Semantics => (int)semantics; [StringFormat("X8")]
public MethodSemanticsAttributes Semantics => semantics;
public string SemanticsTooltip => semantics.ToString(); public string SemanticsTooltip => semantics.ToString();
public int MethodHandle => MetadataTokens.GetToken(method); [StringFormat("X8")]
public int Method => MetadataTokens.GetToken(method);
public string Method { public string MethodTooltip {
get { get {
ITextOutput output = new PlainTextOutput(); ITextOutput output = new PlainTextOutput();
((EntityHandle)method).WriteTo(module, output, Decompiler.Metadata.GenericContext.Empty); ((EntityHandle)method).WriteTo(module, output, Decompiler.Metadata.GenericContext.Empty);
@ -90,9 +104,10 @@ namespace ICSharpCode.ILSpy.Metadata
} }
} }
public int AssociationHandle => MetadataTokens.GetToken(association); [StringFormat("X8")]
public int Association => MetadataTokens.GetToken(association);
public string Association { public string AssociationTooltip {
get { get {
ITextOutput output = new PlainTextOutput(); ITextOutput output = new PlainTextOutput();
association.WriteTo(module, output, Decompiler.Metadata.GenericContext.Empty); association.WriteTo(module, output, Decompiler.Metadata.GenericContext.Empty);

24
ILSpy/Metadata/CorTables/MethodSpecTableTreeNode.cs

@ -47,13 +47,25 @@ namespace ICSharpCode.ILSpy.Metadata
var metadata = module.Metadata; var metadata = module.Metadata;
var list = new List<MethodSpecEntry>(); var list = new List<MethodSpecEntry>();
MethodSpecEntry scrollTargetEntry = default;
foreach (var row in metadata.GetMethodSpecifications())
list.Add(new MethodSpecEntry(module, row)); foreach (var row in metadata.GetMethodSpecifications()) {
MethodSpecEntry entry = new MethodSpecEntry(module, row);
if (entry.RID == this.scrollTarget) {
scrollTargetEntry = entry;
}
list.Add(entry);
}
view.ItemsSource = list; view.ItemsSource = list;
tabPage.Content = view; tabPage.Content = view;
if (scrollTargetEntry.RID > 0) {
view.ScrollIntoView(scrollTargetEntry);
this.scrollTarget = default;
}
return true; return true;
} }
@ -73,9 +85,10 @@ namespace ICSharpCode.ILSpy.Metadata
+ metadata.GetTableMetadataOffset(TableIndex.MethodSpec) + metadata.GetTableMetadataOffset(TableIndex.MethodSpec)
+ metadata.GetTableRowSize(TableIndex.MethodSpec) * (RID-1); + metadata.GetTableRowSize(TableIndex.MethodSpec) * (RID-1);
public int MethodHandle => MetadataTokens.GetToken(methodSpec.Method); [StringFormat("X8")]
public int Method => MetadataTokens.GetToken(methodSpec.Method);
public string Method { public string MethodTooltip {
get { get {
ITextOutput output = new PlainTextOutput(); ITextOutput output = new PlainTextOutput();
methodSpec.Method.WriteTo(module, output, GenericContext.Empty); methodSpec.Method.WriteTo(module, output, GenericContext.Empty);
@ -83,6 +96,7 @@ namespace ICSharpCode.ILSpy.Metadata
} }
} }
[StringFormat("X")]
public int Signature => MetadataTokens.GetHeapOffset(methodSpec.Signature); public int Signature => MetadataTokens.GetHeapOffset(methodSpec.Signature);
public string SignatureTooltip { public string SignatureTooltip {

33
ILSpy/Metadata/CorTables/MethodTableTreeNode.cs

@ -49,13 +49,25 @@ namespace ICSharpCode.ILSpy.Metadata
var view = Helpers.PrepareDataGrid(tabPage); var view = Helpers.PrepareDataGrid(tabPage);
var metadata = module.Metadata; var metadata = module.Metadata;
var list = new List<MethodDefEntry>(); var list = new List<MethodDefEntry>();
MethodDefEntry scrollTargetEntry = default;
foreach (var row in metadata.MethodDefinitions) foreach (var row in metadata.MethodDefinitions) {
list.Add(new MethodDefEntry(module, row)); MethodDefEntry entry = new MethodDefEntry(module, row);
if (entry.RID == scrollTarget) {
scrollTargetEntry = entry;
}
list.Add(entry);
}
view.ItemsSource = list; view.ItemsSource = list;
tabPage.Content = view; tabPage.Content = view;
if (scrollTargetEntry.RID > 0) {
view.ScrollIntoView(scrollTargetEntry);
this.scrollTarget = default;
}
return true; return true;
} }
@ -75,13 +87,24 @@ namespace ICSharpCode.ILSpy.Metadata
+ metadata.GetTableMetadataOffset(TableIndex.MethodDef) + metadata.GetTableMetadataOffset(TableIndex.MethodDef)
+ metadata.GetTableRowSize(TableIndex.MethodDef) * (RID - 1); + metadata.GetTableRowSize(TableIndex.MethodDef) * (RID - 1);
[StringFormat("X8")]
public MethodAttributes Attributes => methodDef.Attributes; public MethodAttributes Attributes => methodDef.Attributes;
public object AttributesTooltip => new FlagsTooltip((int)methodDef.Attributes, typeof(MethodAttributes)); const MethodAttributes otherFlagsMask = ~(MethodAttributes.MemberAccessMask | MethodAttributes.VtableLayoutMask);
public object AttributesTooltip => new FlagsTooltip {
FlagGroup.CreateSingleChoiceGroup(typeof(MethodAttributes), "Member access: ", (int)MethodAttributes.MemberAccessMask, (int)(methodDef.Attributes & MethodAttributes.MemberAccessMask), new Flag("CompilerControlled (0000)", 0, false), includeAny: false),
FlagGroup.CreateSingleChoiceGroup(typeof(MethodAttributes), "Vtable layout: ", (int)MethodAttributes.VtableLayoutMask, (int)(methodDef.Attributes & MethodAttributes.VtableLayoutMask), new Flag("ReuseSlot (0000)", 0, false), includeAny: false),
FlagGroup.CreateMultipleChoiceGroup(typeof(MethodAttributes), "Flags:", (int)otherFlagsMask, (int)(methodDef.Attributes & otherFlagsMask), includeAll: false),
};
[StringFormat("X8")]
public MethodImplAttributes ImplAttributes => methodDef.ImplAttributes; public MethodImplAttributes ImplAttributes => methodDef.ImplAttributes;
public object ImplAttributesTooltip => new FlagsTooltip((int)methodDef.ImplAttributes, typeof(MethodImplAttributes)); public object ImplAttributesTooltip => new FlagsTooltip {
FlagGroup.CreateSingleChoiceGroup(typeof(MethodImplAttributes), "Code type: ", (int)MethodImplAttributes.CodeTypeMask, (int)(methodDef.ImplAttributes & MethodImplAttributes.CodeTypeMask), new Flag("IL (0000)", 0, false), includeAny: false),
FlagGroup.CreateSingleChoiceGroup(typeof(MethodImplAttributes), "Managed type: ", (int)MethodImplAttributes.ManagedMask, (int)(methodDef.ImplAttributes & MethodImplAttributes.ManagedMask), new Flag("Managed (0000)", 0, false), includeAny: false),
};
public int RVA => methodDef.RelativeVirtualAddress; public int RVA => methodDef.RelativeVirtualAddress;
@ -89,7 +112,7 @@ namespace ICSharpCode.ILSpy.Metadata
public string NameTooltip => $"{MetadataTokens.GetHeapOffset(methodDef.Name):X} \"{Name}\""; public string NameTooltip => $"{MetadataTokens.GetHeapOffset(methodDef.Name):X} \"{Name}\"";
[StringFormat("X8")] [StringFormat("X")]
public int Signature => MetadataTokens.GetHeapOffset(methodDef.Signature); public int Signature => MetadataTokens.GetHeapOffset(methodDef.Signature);
string signatureTooltip; string signatureTooltip;

18
ILSpy/Metadata/CorTables/ModuleRefTableTreeNode.cs

@ -45,13 +45,25 @@ namespace ICSharpCode.ILSpy.Metadata
var metadata = module.Metadata; var metadata = module.Metadata;
var list = new List<ModuleRefEntry>(); var list = new List<ModuleRefEntry>();
ModuleRefEntry scrollTargetEntry = default;
foreach (var row in metadata.GetModuleReferences())
list.Add(new ModuleRefEntry(module, row)); foreach (var row in metadata.GetModuleReferences()) {
ModuleRefEntry entry = new ModuleRefEntry(module, row);
if (entry.RID == this.scrollTarget) {
scrollTargetEntry = entry;
}
list.Add(entry);
}
view.ItemsSource = list; view.ItemsSource = list;
tabPage.Content = view; tabPage.Content = view;
if (scrollTargetEntry.RID > 0) {
view.ScrollIntoView(scrollTargetEntry);
this.scrollTarget = default;
}
return true; return true;
} }

12
ILSpy/Metadata/CorTables/ModuleTableTreeNode.cs

@ -45,12 +45,19 @@ namespace ICSharpCode.ILSpy.Metadata
var metadata = module.Metadata; var metadata = module.Metadata;
var list = new List<ModuleEntry>(); var list = new List<ModuleEntry>();
ModuleEntry scrollTargetEntry = default;
list.Add(new ModuleEntry(module, EntityHandle.ModuleDefinition)); list.Add(new ModuleEntry(module, EntityHandle.ModuleDefinition));
view.ItemsSource = list; view.ItemsSource = list;
tabPage.Content = view; tabPage.Content = view;
if (scrollTargetEntry.RID > 0) {
view.ScrollIntoView(scrollTargetEntry);
this.scrollTarget = default;
}
return true; return true;
} }
@ -76,14 +83,17 @@ namespace ICSharpCode.ILSpy.Metadata
public string NameTooltip => $"{MetadataTokens.GetHeapOffset(moduleDef.Name):X} \"{Name}\""; public string NameTooltip => $"{MetadataTokens.GetHeapOffset(moduleDef.Name):X} \"{Name}\"";
[StringFormat("X")]
public int Mvid => MetadataTokens.GetHeapOffset(moduleDef.Mvid); public int Mvid => MetadataTokens.GetHeapOffset(moduleDef.Mvid);
public string MvidTooltip => metadata.GetGuid(moduleDef.Mvid).ToString(); public string MvidTooltip => metadata.GetGuid(moduleDef.Mvid).ToString();
[StringFormat("X")]
public int GenerationId => MetadataTokens.GetHeapOffset(moduleDef.GenerationId); public int GenerationId => MetadataTokens.GetHeapOffset(moduleDef.GenerationId);
public string GenerationIdTooltip => moduleDef.GenerationId.IsNil ? null : metadata.GetGuid(moduleDef.GenerationId).ToString(); public string GenerationIdTooltip => moduleDef.GenerationId.IsNil ? null : metadata.GetGuid(moduleDef.GenerationId).ToString();
[StringFormat("X")]
public int BaseGenerationId => MetadataTokens.GetHeapOffset(moduleDef.BaseGenerationId); public int BaseGenerationId => MetadataTokens.GetHeapOffset(moduleDef.BaseGenerationId);
public string BaseGenerationIdTooltip => moduleDef.BaseGenerationId.IsNil ? null : metadata.GetGuid(moduleDef.BaseGenerationId).ToString(); public string BaseGenerationIdTooltip => moduleDef.BaseGenerationId.IsNil ? null : metadata.GetGuid(moduleDef.BaseGenerationId).ToString();

13
ILSpy/Metadata/CorTables/NestedClassTableTreeNode.cs

@ -47,17 +47,28 @@ namespace ICSharpCode.ILSpy.Metadata
var metadata = module.Metadata; var metadata = module.Metadata;
var list = new List<NestedClassEntry>(); var list = new List<NestedClassEntry>();
NestedClassEntry scrollTargetEntry = default;
var length = metadata.GetTableRowCount(TableIndex.NestedClass); var length = metadata.GetTableRowCount(TableIndex.NestedClass);
byte* ptr = metadata.MetadataPointer; byte* ptr = metadata.MetadataPointer;
int metadataOffset = module.Reader.PEHeaders.MetadataStartOffset; int metadataOffset = module.Reader.PEHeaders.MetadataStartOffset;
for (int rid = 1; rid <= length; rid++) { for (int rid = 1; rid <= length; rid++) {
list.Add(new NestedClassEntry(module, ptr, metadataOffset, rid)); NestedClassEntry entry = new NestedClassEntry(module, ptr, metadataOffset, rid);
if (entry.RID == this.scrollTarget) {
scrollTargetEntry = entry;
}
list.Add(entry);
} }
view.ItemsSource = list; view.ItemsSource = list;
tabPage.Content = view; tabPage.Content = view;
if (scrollTargetEntry.RID > 0) {
view.ScrollIntoView(scrollTargetEntry);
this.scrollTarget = default;
}
return true; return true;
} }

18
ILSpy/Metadata/CorTables/ParamTableTreeNode.cs

@ -46,14 +46,25 @@ namespace ICSharpCode.ILSpy.Metadata
var metadata = module.Metadata; var metadata = module.Metadata;
var list = new List<ParamEntry>(); var list = new List<ParamEntry>();
ParamEntry scrollTargetEntry = default;
for (int row = 1; row <= module.Metadata.GetTableRowCount(TableIndex.Param); row++) { for (int row = 1; row <= module.Metadata.GetTableRowCount(TableIndex.Param); row++) {
list.Add(new ParamEntry(module, MetadataTokens.ParameterHandle(row))); ParamEntry entry = new ParamEntry(module, MetadataTokens.ParameterHandle(row));
if (entry.RID == this.scrollTarget) {
scrollTargetEntry = entry;
}
list.Add(entry);
} }
view.ItemsSource = list; view.ItemsSource = list;
tabPage.Content = view; tabPage.Content = view;
if (scrollTargetEntry.RID > 0) {
view.ScrollIntoView(scrollTargetEntry);
this.scrollTarget = default;
}
return true; return true;
} }
@ -73,9 +84,12 @@ namespace ICSharpCode.ILSpy.Metadata
+ metadata.GetTableMetadataOffset(TableIndex.Param) + metadata.GetTableMetadataOffset(TableIndex.Param)
+ metadata.GetTableRowSize(TableIndex.Param) * (RID-1); + metadata.GetTableRowSize(TableIndex.Param) * (RID-1);
[StringFormat("X8")]
public ParameterAttributes Attributes => param.Attributes; public ParameterAttributes Attributes => param.Attributes;
public object AttributesTooltip => new FlagsTooltip((int)param.Attributes, typeof(ParameterAttributes)); public object AttributesTooltip => new FlagsTooltip {
FlagGroup.CreateMultipleChoiceGroup(typeof(ParameterAttributes), selectedValue: (int)param.Attributes, includeAll: false)
};
public string Name => metadata.GetString(param.Name); public string Name => metadata.GetString(param.Name);

13
ILSpy/Metadata/CorTables/PropertyMapTableTreeNode.cs

@ -47,17 +47,28 @@ namespace ICSharpCode.ILSpy.Metadata
var metadata = module.Metadata; var metadata = module.Metadata;
var list = new List<PropertyMapEntry>(); var list = new List<PropertyMapEntry>();
PropertyMapEntry scrollTargetEntry = default;
var length = metadata.GetTableRowCount(TableIndex.PropertyMap); var length = metadata.GetTableRowCount(TableIndex.PropertyMap);
byte* ptr = metadata.MetadataPointer; byte* ptr = metadata.MetadataPointer;
int metadataOffset = module.Reader.PEHeaders.MetadataStartOffset; int metadataOffset = module.Reader.PEHeaders.MetadataStartOffset;
for (int rid = 1; rid <= length; rid++) { for (int rid = 1; rid <= length; rid++) {
list.Add(new PropertyMapEntry(module, ptr, metadataOffset, rid)); PropertyMapEntry entry = new PropertyMapEntry(module, ptr, metadataOffset, rid);
if (entry.RID == this.scrollTarget) {
scrollTargetEntry = entry;
}
list.Add(entry);
} }
view.ItemsSource = list; view.ItemsSource = list;
tabPage.Content = view; tabPage.Content = view;
if (scrollTargetEntry.RID > 0) {
view.ScrollIntoView(scrollTargetEntry);
this.scrollTarget = default;
}
return true; return true;
} }

22
ILSpy/Metadata/CorTables/PropertyTableTreeNode.cs

@ -50,13 +50,25 @@ namespace ICSharpCode.ILSpy.Metadata
var metadata = module.Metadata; var metadata = module.Metadata;
var list = new List<PropertyDefEntry>(); var list = new List<PropertyDefEntry>();
PropertyDefEntry scrollTargetEntry = default;
foreach (var row in metadata.PropertyDefinitions) foreach (var row in metadata.PropertyDefinitions) {
list.Add(new PropertyDefEntry(module, row)); PropertyDefEntry entry = new PropertyDefEntry(module, row);
if (entry.RID == this.scrollTarget) {
scrollTargetEntry = entry;
}
list.Add(entry);
}
view.ItemsSource = list; view.ItemsSource = list;
tabPage.Content = view; tabPage.Content = view;
if (scrollTargetEntry.RID > 0) {
view.ScrollIntoView(scrollTargetEntry);
this.scrollTarget = default;
}
return true; return true;
} }
@ -76,9 +88,12 @@ namespace ICSharpCode.ILSpy.Metadata
+ metadata.GetTableMetadataOffset(TableIndex.Property) + metadata.GetTableMetadataOffset(TableIndex.Property)
+ metadata.GetTableRowSize(TableIndex.Property) * (RID - 1); + metadata.GetTableRowSize(TableIndex.Property) * (RID - 1);
[StringFormat("X8")]
public PropertyAttributes Attributes => propertyDef.Attributes; public PropertyAttributes Attributes => propertyDef.Attributes;
public object AttributesTooltip => new FlagsTooltip((int)propertyDef.Attributes, typeof(PropertyAttributes)); public object AttributesTooltip => new FlagsTooltip {
FlagGroup.CreateMultipleChoiceGroup(typeof(PropertyAttributes), selectedValue: (int)propertyDef.Attributes, includeAll: false),
};
public string Name => metadata.GetString(propertyDef.Name); public string Name => metadata.GetString(propertyDef.Name);
@ -86,6 +101,7 @@ namespace ICSharpCode.ILSpy.Metadata
IEntity IMemberTreeNode.Member => ((MetadataModule)module.GetTypeSystemOrNull()?.MainModule).GetDefinition(handle); IEntity IMemberTreeNode.Member => ((MetadataModule)module.GetTypeSystemOrNull()?.MainModule).GetDefinition(handle);
[StringFormat("X")]
public int Signature => MetadataTokens.GetHeapOffset(propertyDef.Signature); public int Signature => MetadataTokens.GetHeapOffset(propertyDef.Signature);
public string SignatureTooltip { public string SignatureTooltip {

21
ILSpy/Metadata/CorTables/StandAloneSigTableTreeNode.cs

@ -21,6 +21,8 @@ using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335; using System.Reflection.Metadata.Ecma335;
using ICSharpCode.Decompiler; using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Disassembler;
using ICSharpCode.Decompiler.IL;
using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.Metadata;
namespace ICSharpCode.ILSpy.Metadata namespace ICSharpCode.ILSpy.Metadata
@ -45,14 +47,25 @@ namespace ICSharpCode.ILSpy.Metadata
var metadata = module.Metadata; var metadata = module.Metadata;
var list = new List<StandAloneSigEntry>(); var list = new List<StandAloneSigEntry>();
StandAloneSigEntry scrollTargetEntry = default;
for (int row = 1; row <= module.Metadata.GetTableRowCount(TableIndex.StandAloneSig); row++) { for (int row = 1; row <= module.Metadata.GetTableRowCount(TableIndex.StandAloneSig); row++) {
list.Add(new StandAloneSigEntry(module, MetadataTokens.StandaloneSignatureHandle(row))); StandAloneSigEntry entry = new StandAloneSigEntry(module, MetadataTokens.StandaloneSignatureHandle(row));
if (entry.RID == this.scrollTarget) {
scrollTargetEntry = entry;
}
list.Add(entry);
} }
view.ItemsSource = list; view.ItemsSource = list;
tabPage.Content = view; tabPage.Content = view;
if (scrollTargetEntry.RID > 0) {
view.ScrollIntoView(scrollTargetEntry);
this.scrollTarget = default;
}
return true; return true;
} }
@ -72,11 +85,15 @@ namespace ICSharpCode.ILSpy.Metadata
+ metadata.GetTableMetadataOffset(TableIndex.StandAloneSig) + metadata.GetTableMetadataOffset(TableIndex.StandAloneSig)
+ metadata.GetTableRowSize(TableIndex.StandAloneSig) * (RID - 1); + metadata.GetTableRowSize(TableIndex.StandAloneSig) * (RID - 1);
[StringFormat("X")]
public int Signature => MetadataTokens.GetHeapOffset(standaloneSig.Signature); public int Signature => MetadataTokens.GetHeapOffset(standaloneSig.Signature);
public string SignatureTooltip { public string SignatureTooltip {
get { get {
return null; ITextOutput output = new PlainTextOutput();
var context = new Decompiler.Metadata.GenericContext(default(TypeDefinitionHandle), module);
((EntityHandle)handle).WriteTo(module, output, context);
return output.ToString();
} }
} }

53
ILSpy/Metadata/CorTables/TypeDefTableTreeNode.cs

@ -24,6 +24,7 @@ using System.Reflection.Metadata.Ecma335;
using ICSharpCode.Decompiler; using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Disassembler; using ICSharpCode.Decompiler.Disassembler;
using ICSharpCode.Decompiler.IL;
using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.ILSpy.TreeNodes; using ICSharpCode.ILSpy.TreeNodes;
@ -50,13 +51,25 @@ namespace ICSharpCode.ILSpy.Metadata
var metadata = module.Metadata; var metadata = module.Metadata;
var list = new List<TypeDefEntry>(); var list = new List<TypeDefEntry>();
TypeDefEntry scrollTargetEntry = default;
foreach (var row in metadata.TypeDefinitions) foreach (var row in metadata.TypeDefinitions) {
list.Add(new TypeDefEntry(module, row)); TypeDefEntry entry = new TypeDefEntry(module, row);
if (entry.RID == this.scrollTarget) {
scrollTargetEntry = entry;
}
list.Add(entry);
}
view.ItemsSource = list; view.ItemsSource = list;
tabPage.Content = view; tabPage.Content = view;
if (scrollTargetEntry.RID > 0) {
view.ScrollIntoView(scrollTargetEntry);
this.scrollTarget = default;
}
return true; return true;
} }
@ -76,9 +89,19 @@ namespace ICSharpCode.ILSpy.Metadata
+ metadata.GetTableMetadataOffset(TableIndex.TypeDef) + metadata.GetTableMetadataOffset(TableIndex.TypeDef)
+ metadata.GetTableRowSize(TableIndex.TypeDef) * (RID-1); + metadata.GetTableRowSize(TableIndex.TypeDef) * (RID-1);
[StringFormat("X8")]
public TypeAttributes Attributes => typeDef.Attributes; public TypeAttributes Attributes => typeDef.Attributes;
public object AttributesTooltip => new FlagsTooltip((int)typeDef.Attributes, typeof(TypeAttributes)); const TypeAttributes otherFlagsMask = ~(TypeAttributes.VisibilityMask | TypeAttributes.LayoutMask | TypeAttributes.ClassSemanticsMask | TypeAttributes.StringFormatMask | TypeAttributes.CustomFormatMask);
public object AttributesTooltip => new FlagsTooltip {
FlagGroup.CreateSingleChoiceGroup(typeof(TypeAttributes), "Visibility: ", (int)TypeAttributes.VisibilityMask, (int)(typeDef.Attributes & TypeAttributes.VisibilityMask), new Flag("NotPublic (0000)", 0, false), includeAny: false),
FlagGroup.CreateSingleChoiceGroup(typeof(TypeAttributes), "Class layout: ", (int)TypeAttributes.LayoutMask, (int)(typeDef.Attributes & TypeAttributes.LayoutMask), new Flag("AutoLayout (0000)", 0, false), includeAny: false),
FlagGroup.CreateSingleChoiceGroup(typeof(TypeAttributes), "Class semantics: ", (int)TypeAttributes.ClassSemanticsMask, (int)(typeDef.Attributes & TypeAttributes.ClassSemanticsMask), new Flag("Class (0000)", 0, false), includeAny: false),
FlagGroup.CreateSingleChoiceGroup(typeof(TypeAttributes), "String format: ", (int)TypeAttributes.StringFormatMask, (int)(typeDef.Attributes & TypeAttributes.StringFormatMask), new Flag("AnsiClass (0000)", 0, false), includeAny: false),
FlagGroup.CreateSingleChoiceGroup(typeof(TypeAttributes), "Custom format: ", (int)TypeAttributes.CustomFormatMask, (int)(typeDef.Attributes & TypeAttributes.CustomFormatMask), new Flag("Value0 (0000)", 0, false), includeAny: false),
FlagGroup.CreateMultipleChoiceGroup(typeof(TypeAttributes), "Flags:", (int)otherFlagsMask, (int)(typeDef.Attributes & otherFlagsMask), includeAll: false),
};
public string NameTooltip => $"{MetadataTokens.GetHeapOffset(typeDef.Name):X} \"{Name}\""; public string NameTooltip => $"{MetadataTokens.GetHeapOffset(typeDef.Name):X} \"{Name}\"";
@ -116,9 +139,33 @@ namespace ICSharpCode.ILSpy.Metadata
[StringFormat("X8")] [StringFormat("X8")]
public int FieldList => MetadataTokens.GetToken(typeDef.GetFields().FirstOrDefault()); public int FieldList => MetadataTokens.GetToken(typeDef.GetFields().FirstOrDefault());
public string FieldListTooltip {
get {
var field = typeDef.GetFields().FirstOrDefault();
if (field.IsNil)
return null;
ITextOutput output = new PlainTextOutput();
var context = new Decompiler.Metadata.GenericContext(default(TypeDefinitionHandle), module);
((EntityHandle)field).WriteTo(module, output, context);
return output.ToString();
}
}
[StringFormat("X8")] [StringFormat("X8")]
public int MethodList => MetadataTokens.GetToken(typeDef.GetMethods().FirstOrDefault()); public int MethodList => MetadataTokens.GetToken(typeDef.GetMethods().FirstOrDefault());
public string MethodListTooltip {
get {
var method = typeDef.GetMethods().FirstOrDefault();
if (method.IsNil)
return null;
ITextOutput output = new PlainTextOutput();
var context = new Decompiler.Metadata.GenericContext(default(TypeDefinitionHandle), module);
((EntityHandle)method).WriteTo(module, output, context);
return output.ToString();
}
}
IEntity IMemberTreeNode.Member => ((MetadataModule)module.GetTypeSystemOrNull()?.MainModule).GetDefinition(handle); IEntity IMemberTreeNode.Member => ((MetadataModule)module.GetTypeSystemOrNull()?.MainModule).GetDefinition(handle);
public TypeDefEntry(PEFile module, TypeDefinitionHandle handle) public TypeDefEntry(PEFile module, TypeDefinitionHandle handle)

18
ILSpy/Metadata/CorTables/TypeRefTableTreeNode.cs

@ -46,13 +46,25 @@ namespace ICSharpCode.ILSpy.Metadata
var metadata = module.Metadata; var metadata = module.Metadata;
var list = new List<TypeRefEntry>(); var list = new List<TypeRefEntry>();
TypeRefEntry scrollTargetEntry = default;
foreach (var row in metadata.TypeReferences)
list.Add(new TypeRefEntry(module, row)); foreach (var row in metadata.TypeReferences) {
TypeRefEntry entry = new TypeRefEntry(module, row);
if (entry.RID == this.scrollTarget) {
scrollTargetEntry = entry;
}
list.Add(entry);
}
view.ItemsSource = list; view.ItemsSource = list;
tabPage.Content = view; tabPage.Content = view;
if (scrollTargetEntry.RID > 0) {
view.ScrollIntoView(scrollTargetEntry);
this.scrollTarget = default;
}
return true; return true;
} }

17
ILSpy/Metadata/CorTables/TypeSpecTableTreeNode.cs

@ -46,13 +46,25 @@ namespace ICSharpCode.ILSpy.Metadata
var metadata = module.Metadata; var metadata = module.Metadata;
var list = new List<TypeSpecEntry>(); var list = new List<TypeSpecEntry>();
TypeSpecEntry scrollTargetEntry = default;
foreach (var row in metadata.GetTypeSpecifications()) foreach (var row in metadata.GetTypeSpecifications()) {
list.Add(new TypeSpecEntry(module, row)); TypeSpecEntry entry = new TypeSpecEntry(module, row);
if (scrollTarget.Equals(row)) {
scrollTargetEntry = entry;
}
list.Add(entry);
}
view.ItemsSource = list; view.ItemsSource = list;
tabPage.Content = view; tabPage.Content = view;
if (scrollTargetEntry.RID > 0) {
view.ScrollIntoView(scrollTargetEntry);
this.scrollTarget = default;
}
return true; return true;
} }
@ -72,6 +84,7 @@ namespace ICSharpCode.ILSpy.Metadata
+ metadata.GetTableMetadataOffset(TableIndex.TypeSpec) + metadata.GetTableMetadataOffset(TableIndex.TypeSpec)
+ metadata.GetTableRowSize(TableIndex.TypeSpec) * (RID-1); + metadata.GetTableRowSize(TableIndex.TypeSpec) * (RID-1);
[StringFormat("X")]
public int Signature => MetadataTokens.GetHeapOffset(typeSpec.Signature); public int Signature => MetadataTokens.GetHeapOffset(typeSpec.Signature);
public string SignatureTooltip { public string SignatureTooltip {

11
ILSpy/Metadata/DataGridCustomTextColumn.cs

@ -19,6 +19,7 @@
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Data; using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Media; using System.Windows.Media;
namespace ICSharpCode.ILSpy.Metadata namespace ICSharpCode.ILSpy.Metadata
@ -32,9 +33,17 @@ namespace ICSharpCode.ILSpy.Metadata
TextBox textBox = new TextBox() { Style = (Style)MetadataTableViews.Instance["DataGridCustomTextColumnTextBoxStyle"] }; TextBox textBox = new TextBox() { Style = (Style)MetadataTableViews.Instance["DataGridCustomTextColumnTextBoxStyle"] };
BindingOperations.SetBinding(textBox, TextBox.TextProperty, Binding); BindingOperations.SetBinding(textBox, TextBox.TextProperty, Binding);
if (ToolTipBinding != null) { if (ToolTipBinding != null) {
BindingOperations.SetBinding(textBox, TextBox.ToolTipProperty, ToolTipBinding); textBox.MouseMove += TextBox_MouseMove;
} }
return textBox; return textBox;
} }
private void TextBox_MouseMove(object sender, MouseEventArgs e)
{
e.Handled = true;
var textBox = (TextBox)sender;
BindingOperations.SetBinding(textBox, TextBox.ToolTipProperty, ToolTipBinding);
textBox.MouseMove -= TextBox_MouseMove;
}
} }
} }

20
ILSpy/Metadata/FlagsFilterControl.xaml.cs

@ -41,7 +41,7 @@ namespace ICSharpCode.ILSpy.Metadata
base.OnApplyTemplate(); base.OnApplyTemplate();
listBox = Template.FindName("ListBox", this) as ListBox; listBox = Template.FindName("ListBox", this) as ListBox;
listBox.ItemsSource = CreateFlags(FlagsType); listBox.ItemsSource = FlagGroup.GetFlags(FlagsType, neutralItem: "<All>");
var filter = Filter; var filter = Filter;
@ -50,19 +50,6 @@ namespace ICSharpCode.ILSpy.Metadata
} }
} }
internal static IEnumerable<Flag> CreateFlags(Type flagsType, bool includeAll = true)
{
if (includeAll)
yield return new Flag("<All>", -1);
foreach (var item in flagsType.GetFields(BindingFlags.Static | BindingFlags.Public)) {
if (item.Name.EndsWith("Mask", StringComparison.Ordinal))
continue;
int value = (int)CSharpPrimitiveCast.Cast(TypeCode.Int32, item.GetRawConstantValue(), false);
yield return new Flag($"{item.Name} ({value:X4})", value);
}
}
private void Filter_Changed() private void Filter_Changed()
{ {
var filter = Filter; var filter = Filter;
@ -110,7 +97,10 @@ namespace ICSharpCode.ILSpy.Metadata
public bool IsMatch(object value) public bool IsMatch(object value)
{ {
return (Mask & (int)value) != 0; if (value == null)
return true;
return Mask == -1 || (Mask & (int)value) != 0;
} }
} }
} }

36
ILSpy/Metadata/FlagsTooltip.xaml

@ -8,17 +8,37 @@
mc:Ignorable="d" mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"> d:DesignHeight="450" d:DesignWidth="800">
<Control.Resources> <Control.Resources>
<local:FlagActiveConverter x:Key="flagActiveConv" /> <local:NullVisibilityConverter x:Key="nullVisConv" />
<DataTemplate DataType="{x:Type local:MultipleChoiceGroup}">
<StackPanel Orientation="Vertical" Margin="3">
<TextBlock Text="{Binding Header}" FontWeight="Bold" Margin="0 0 0 3" Visibility="{Binding Header, Converter={StaticResource nullVisConv}}" />
<ListBox ItemsSource="{Binding Flags}" BorderThickness="0" Background="Transparent">
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox DockPanel.Dock="Left" Margin="3,2" Content="{Binding Name}" IsChecked="{Binding IsSelected, Mode=OneWay}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</DataTemplate>
<DataTemplate DataType="{x:Type local:SingleChoiceGroup}">
<StackPanel Orientation="Horizontal" Margin="3">
<TextBlock Text="{Binding Header}" FontWeight="Bold" Visibility="{Binding Header, Converter={StaticResource nullVisConv}}" />
<TextBlock Text="{Binding SelectedFlag.Name}" />
</StackPanel>
</DataTemplate>
</Control.Resources> </Control.Resources>
<Control.Template> <Control.Template>
<ControlTemplate> <ControlTemplate>
<ListBox ItemsSource="{Binding Flags, ElementName=root}"> <ItemsControl ItemsSource="{Binding Groups, ElementName=root}">
<ListBox.ItemTemplate> <ItemsControl.ItemsPanel>
<DataTemplate> <ItemsPanelTemplate>
<CheckBox DockPanel.Dock="Left" Margin="3,2" Content="{Binding Name}" IsChecked="{Binding Value, Converter={StaticResource flagActiveConv}, Mode=OneWay}"/> <StackPanel Orientation="Vertical" />
</DataTemplate> </ItemsPanelTemplate>
</ListBox.ItemTemplate> </ItemsControl.ItemsPanel>
</ListBox> </ItemsControl>
</ControlTemplate> </ControlTemplate>
</Control.Template> </Control.Template>
</Control> </Control>

135
ILSpy/Metadata/FlagsTooltip.xaml.cs

@ -1,34 +1,59 @@
using System; // 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.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.Linq; using System.Linq;
using System.Text; using System.Reflection;
using System.Threading.Tasks;
using System.Windows; using System.Windows;
using System.Windows.Controls;
using System.Windows.Data; using System.Windows.Data;
using System.Windows.Documents; using ICSharpCode.Decompiler.Util;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace ICSharpCode.ILSpy.Metadata namespace ICSharpCode.ILSpy.Metadata
{ {
/// <summary> /// <summary>
/// Interaction logic for FlagsTooltip.xaml /// Interaction logic for FlagsTooltip.xaml
/// </summary> /// </summary>
public partial class FlagsTooltip public partial class FlagsTooltip : IEnumerable<FlagGroup>
{ {
public FlagsTooltip(int value, Type flagsType) public FlagsTooltip(int value = 0, Type flagsType = null)
{ {
this.Flags = FlagsFilterControl.CreateFlags(flagsType, includeAll: false);
InitializeComponent(); InitializeComponent();
((FlagActiveConverter)Resources["flagActiveConv"]).Value = value;
} }
public IEnumerable<Flag> Flags { get; } public void Add(FlagGroup group)
{
Groups.Add(group);
}
public IEnumerator<FlagGroup> GetEnumerator()
{
return Groups.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return Groups.GetEnumerator();
}
public List<FlagGroup> Groups { get; } = new List<FlagGroup>();
} }
class FlagActiveConverter : DependencyObject, IValueConverter class FlagActiveConverter : DependencyObject, IValueConverter
@ -56,11 +81,89 @@ namespace ICSharpCode.ILSpy.Metadata
{ {
public string Name { get; } public string Name { get; }
public int Value { get; } public int Value { get; }
public bool IsSelected { get; }
public Flag(string name, int value) public Flag(string name, int value, bool isSelected)
{ {
this.Name = name; this.Name = name;
this.Value = value; this.Value = value;
this.IsSelected = isSelected;
}
}
public abstract class FlagGroup
{
public static MultipleChoiceGroup CreateMultipleChoiceGroup(Type flagsType, string header = null, int mask = -1, int selectedValue = 0, bool includeAll = true)
{
MultipleChoiceGroup group = new MultipleChoiceGroup(GetFlags(flagsType, mask, selectedValue, includeAll ? "<All>" : null));
group.Header = header;
group.SelectedFlags = selectedValue;
return group;
}
public static SingleChoiceGroup CreateSingleChoiceGroup(Type flagsType, string header = null, int mask = -1, int selectedValue = 0, Flag defaultFlag = default, bool includeAny = true)
{
var group = new SingleChoiceGroup(GetFlags(flagsType, mask, selectedValue, includeAny ? "<Any>" : null));
group.Header = header;
group.SelectedFlag = group.Flags.SingleOrDefault(f => f.Value == selectedValue);
if (group.SelectedFlag.Name == null) {
group.SelectedFlag = defaultFlag;
}
return group;
}
public static IEnumerable<Flag> GetFlags(Type flagsType, int mask = -1, int selectedValues = 0, string neutralItem = null)
{
if (neutralItem != null)
yield return new Flag(neutralItem, -1, false);
foreach (var item in flagsType.GetFields(BindingFlags.Static | BindingFlags.Public)) {
if (item.Name.EndsWith("Mask", StringComparison.Ordinal))
continue;
int value = (int)CSharpPrimitiveCast.Cast(TypeCode.Int32, item.GetRawConstantValue(), false);
if ((value & mask) == 0)
continue;
yield return new Flag($"{item.Name} ({value:X4})", value, (selectedValues & value) != 0);
}
}
public string Header { get; set; }
public IList<Flag> Flags { get; protected set; }
}
public class MultipleChoiceGroup : FlagGroup
{
public MultipleChoiceGroup(IEnumerable<Flag> flags)
{
this.Flags = flags.ToList();
}
public int SelectedFlags { get; set; }
}
public class SingleChoiceGroup : FlagGroup
{
public SingleChoiceGroup(IEnumerable<Flag> flags)
{
this.Flags = flags.ToList();
}
public Flag SelectedFlag { get; set; }
}
class NullVisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null)
return Visibility.Collapsed;
return Visibility.Visible;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
} }
} }
} }

25
ILSpy/Metadata/Helpers.cs

@ -34,6 +34,7 @@ using System.Windows.Media;
using DataGridExtensions; using DataGridExtensions;
using ICSharpCode.Decompiler.Util; using ICSharpCode.Decompiler.Util;
using ICSharpCode.ILSpy.Controls; using ICSharpCode.ILSpy.Controls;
using ICSharpCode.ILSpy.TextView;
using ICSharpCode.ILSpy.ViewModels; using ICSharpCode.ILSpy.ViewModels;
namespace ICSharpCode.ILSpy.Metadata namespace ICSharpCode.ILSpy.Metadata
@ -50,6 +51,9 @@ namespace ICSharpCode.ILSpy.Metadata
CanUserDeleteRows = false, CanUserDeleteRows = false,
CanUserReorderColumns = false, CanUserReorderColumns = false,
RowHeaderWidth = 0, RowHeaderWidth = 0,
EnableColumnVirtualization = true,
EnableRowVirtualization = true,
IsReadOnly = true,
SelectionMode = DataGridSelectionMode.Single, SelectionMode = DataGridSelectionMode.Single,
SelectionUnit = DataGridSelectionUnit.FullRow, SelectionUnit = DataGridSelectionUnit.FullRow,
CellStyle = new Style { CellStyle = new Style {
@ -66,6 +70,11 @@ namespace ICSharpCode.ILSpy.Metadata
DataGridFilter.SetIsAutoFilterEnabled(view, true); DataGridFilter.SetIsAutoFilterEnabled(view, true);
DataGridFilter.SetContentFilterFactory(view, new RegexContentFilterFactory()); DataGridFilter.SetContentFilterFactory(view, new RegexContentFilterFactory());
} }
view.RowDetailsTemplateSelector = null;
view.RowDetailsVisibilityMode = DataGridRowDetailsVisibilityMode.Collapsed;
if (!view.AutoGenerateColumns)
view.Columns.Clear();
view.AutoGenerateColumns = true;
view.AutoGeneratingColumn += View_AutoGeneratingColumn; view.AutoGeneratingColumn += View_AutoGeneratingColumn;
view.AutoGeneratedColumns += View_AutoGeneratedColumns; view.AutoGeneratedColumns += View_AutoGeneratedColumns;
@ -99,14 +108,6 @@ namespace ICSharpCode.ILSpy.Metadata
e.Column.SetTemplate((ControlTemplate)MetadataTableViews.Instance["HexFilter"]); e.Column.SetTemplate((ControlTemplate)MetadataTableViews.Instance["HexFilter"]);
((DataGridCustomTextColumn)e.Column).ToolTipBinding = null; ((DataGridCustomTextColumn)e.Column).ToolTipBinding = null;
break; break;
case "Flags":
case "Attributes":
case "ImplAttributes":
case "MappingFlags":
binding.Converter = new UnderlyingEnumValueConverter();
binding.StringFormat = "X4";
e.Column.SetTemplate((ControlTemplate)MetadataTableViews.Instance[e.PropertyType.Name + "Filter"]);
break;
default: default:
e.Cancel = e.PropertyName.Contains("Tooltip"); e.Cancel = e.PropertyName.Contains("Tooltip");
if (!e.Cancel) { if (!e.Cancel) {
@ -119,12 +120,16 @@ namespace ICSharpCode.ILSpy.Metadata
} }
} }
static void ApplyAttributes(PropertyDescriptor descriptor, BindingBase binding, DataGridColumn column) static void ApplyAttributes(PropertyDescriptor descriptor, Binding binding, DataGridColumn column)
{ {
if (descriptor.PropertyType.IsEnum) {
binding.Converter = new UnderlyingEnumValueConverter();
column.SetTemplate((ControlTemplate)MetadataTableViews.Instance[descriptor.PropertyType.Name + "Filter"]);
}
var stringFormat = descriptor.Attributes.OfType<StringFormatAttribute>().FirstOrDefault(); var stringFormat = descriptor.Attributes.OfType<StringFormatAttribute>().FirstOrDefault();
if (stringFormat != null) { if (stringFormat != null) {
binding.StringFormat = stringFormat.Format; binding.StringFormat = stringFormat.Format;
if (stringFormat.Format.StartsWith("X", StringComparison.OrdinalIgnoreCase)) { if (!descriptor.PropertyType.IsEnum && stringFormat.Format.StartsWith("X", StringComparison.OrdinalIgnoreCase)) {
column.SetTemplate((ControlTemplate)MetadataTableViews.Instance["HexFilter"]); column.SetTemplate((ControlTemplate)MetadataTableViews.Instance["HexFilter"]);
} }
} }

4
ILSpy/Metadata/MetadataProtocolHandler.cs

@ -24,7 +24,9 @@ namespace ICSharpCode.ILSpy.Metadata
var mxNode = assemblyTreeNode.Children.OfType<MetadataTreeNode>().FirstOrDefault(); var mxNode = assemblyTreeNode.Children.OfType<MetadataTreeNode>().FirstOrDefault();
if (mxNode != null) { if (mxNode != null) {
mxNode.EnsureLazyChildren(); mxNode.EnsureLazyChildren();
return mxNode.FindNodeByHandleKind(handle.Kind); var node = mxNode.FindNodeByHandleKind(handle.Kind);
node?.ScrollTo(handle);
return node;
} }
return null; return null;
} }

10
ILSpy/Metadata/MetadataTableTreeNode.cs

@ -16,9 +16,13 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System;
using System.Reflection.Metadata; using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.ILSpy.TextView;
using ICSharpCode.ILSpy.TreeNodes; using ICSharpCode.ILSpy.TreeNodes;
using ICSharpCode.ILSpy.ViewModels;
using ICSharpCode.TreeView; using ICSharpCode.TreeView;
namespace ICSharpCode.ILSpy.Metadata namespace ICSharpCode.ILSpy.Metadata
@ -26,6 +30,7 @@ namespace ICSharpCode.ILSpy.Metadata
internal abstract class MetadataTableTreeNode : ILSpyTreeNode internal abstract class MetadataTableTreeNode : ILSpyTreeNode
{ {
protected PEFile module; protected PEFile module;
protected int scrollTarget;
public HandleKind Kind { get; } public HandleKind Kind { get; }
@ -34,5 +39,10 @@ namespace ICSharpCode.ILSpy.Metadata
this.module = module; this.module = module;
this.Kind = kind; this.Kind = kind;
} }
internal void ScrollTo(Handle handle)
{
this.scrollTarget = MetadataTokens.GetRowNumber((EntityHandle)handle);
}
} }
} }

8
ILSpy/Metadata/MetadataTableViews.xaml

@ -48,6 +48,10 @@
<local:FlagsFilterControl FlagsType="{x:Type srm:AssemblyFlags}" Filter="{Binding Path=Filter, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=dgx:DataGridFilterColumnControl}}" /> <local:FlagsFilterControl FlagsType="{x:Type srm:AssemblyFlags}" Filter="{Binding Path=Filter, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=dgx:DataGridFilterColumnControl}}" />
</ControlTemplate> </ControlTemplate>
<ControlTemplate x:Key="AssemblyHashAlgorithmFilter">
<local:FlagsFilterControl FlagsType="{x:Type srm:AssemblyHashAlgorithm}" Filter="{Binding Path=Filter, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=dgx:DataGridFilterColumnControl}}" />
</ControlTemplate>
<ControlTemplate x:Key="MethodAttributesFilter"> <ControlTemplate x:Key="MethodAttributesFilter">
<local:FlagsFilterControl FlagsType="{x:Type reflection:MethodAttributes}" Filter="{Binding Path=Filter, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=dgx:DataGridFilterColumnControl}}" /> <local:FlagsFilterControl FlagsType="{x:Type reflection:MethodAttributes}" Filter="{Binding Path=Filter, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=dgx:DataGridFilterColumnControl}}" />
</ControlTemplate> </ControlTemplate>
@ -56,6 +60,10 @@
<local:FlagsFilterControl FlagsType="{x:Type reflection:MethodImplAttributes}" Filter="{Binding Path=Filter, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=dgx:DataGridFilterColumnControl}}" /> <local:FlagsFilterControl FlagsType="{x:Type reflection:MethodImplAttributes}" Filter="{Binding Path=Filter, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=dgx:DataGridFilterColumnControl}}" />
</ControlTemplate> </ControlTemplate>
<ControlTemplate x:Key="MethodSemanticsAttributesFilter">
<local:FlagsFilterControl FlagsType="{x:Type srm:MethodSemanticsAttributes}" Filter="{Binding Path=Filter, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=dgx:DataGridFilterColumnControl}}" />
</ControlTemplate>
<ControlTemplate x:Key="TypeAttributesFilter"> <ControlTemplate x:Key="TypeAttributesFilter">
<local:FlagsFilterControl FlagsType="{x:Type reflection:TypeAttributes}" Filter="{Binding Path=Filter, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=dgx:DataGridFilterColumnControl}}" /> <local:FlagsFilterControl FlagsType="{x:Type reflection:TypeAttributes}" Filter="{Binding Path=Filter, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=dgx:DataGridFilterColumnControl}}" />
</ControlTemplate> </ControlTemplate>

12
ILSpy/Metadata/MetadataTreeNode.cs

@ -104,7 +104,7 @@ namespace ICSharpCode.ILSpy.Metadata
this.Children.Add(new GenericParamConstraintTableTreeNode(module)); this.Children.Add(new GenericParamConstraintTableTreeNode(module));
} }
public ILSpyTreeNode FindNodeByHandleKind(HandleKind kind) public MetadataTableTreeNode FindNodeByHandleKind(HandleKind kind)
{ {
return this.Children.OfType<MetadataTableTreeNode>().SingleOrDefault(x => x.Kind == kind); return this.Children.OfType<MetadataTableTreeNode>().SingleOrDefault(x => x.Kind == kind);
} }
@ -112,11 +112,11 @@ namespace ICSharpCode.ILSpy.Metadata
class Entry class Entry
{ {
public string Member { get; set; } public string Member { get; }
public int Offset { get; set; } public int Offset { get; }
public int Size { get; set; } public int Size { get; }
public object Value { get; set; } public object Value { get; }
public string Meaning { get; set; } public string Meaning { get; }
public Entry(int offset, object value, int size, string member, string meaning) public Entry(int offset, object value, int size, string member, string meaning)
{ {

28
ILSpy/Metadata/OptionalHeaderTreeNode.cs

@ -43,20 +43,19 @@ namespace ICSharpCode.ILSpy.Metadata
public override bool View(ViewModels.TabPageModel tabPage) public override bool View(ViewModels.TabPageModel tabPage)
{ {
var dataGrid = new DataGrid { tabPage.Title = Text.ToString();
Columns = { tabPage.SupportsLanguageSwitching = false;
new DataGridTextColumn { IsReadOnly = true, Header = "Member", Binding = new Binding("Member") },
new DataGridTextColumn { IsReadOnly = true, Header = "Offset", Binding = new Binding("Offset") { StringFormat = "X8" } }, var dataGrid = Helpers.PrepareDataGrid(tabPage);
new DataGridTextColumn { IsReadOnly = true, Header = "Size", Binding = new Binding("Size") }, dataGrid.RowDetailsTemplateSelector = new DllCharacteristicsDataTemplateSelector();
new DataGridTextColumn { IsReadOnly = true, Header = "Value", Binding = new Binding(".") { Converter = ByteWidthConverter.Instance } }, dataGrid.RowDetailsVisibilityMode = DataGridRowDetailsVisibilityMode.Visible;
new DataGridTextColumn { IsReadOnly = true, Header = "Meaning", Binding = new Binding("Meaning") }, dataGrid.AutoGenerateColumns = false;
}, dataGrid.Columns.Add(new DataGridCustomTextColumn { Header = "Member", Binding = new Binding("Member") { Mode = BindingMode.OneWay } });
AutoGenerateColumns = false, dataGrid.Columns.Add(new DataGridCustomTextColumn { Header = "Offset", Binding = new Binding("Offset") { StringFormat = "X8", Mode = BindingMode.OneWay } });
CanUserAddRows = false, dataGrid.Columns.Add(new DataGridCustomTextColumn { Header = "Size", Binding = new Binding("Size") { Mode = BindingMode.OneWay } });
CanUserDeleteRows = false, dataGrid.Columns.Add(new DataGridCustomTextColumn { Header = "Value", Binding = new Binding(".") { Converter = ByteWidthConverter.Instance, Mode = BindingMode.OneWay } });
RowDetailsTemplateSelector = new DllCharacteristicsDataTemplateSelector(), dataGrid.Columns.Add(new DataGridCustomTextColumn { Header = "Meaning", Binding = new Binding("Meaning") { Mode = BindingMode.OneWay } });
RowDetailsVisibilityMode = DataGridRowDetailsVisibilityMode.Visible
};
var headers = module.Reader.PEHeaders; var headers = module.Reader.PEHeaders;
var reader = module.Reader.GetEntireImage().GetReader(headers.PEHeaderStartOffset, 128); var reader = module.Reader.GetEntireImage().GetReader(headers.PEHeaderStartOffset, 128);
var header = headers.PEHeader; var header = headers.PEHeader;
@ -129,6 +128,7 @@ namespace ICSharpCode.ILSpy.Metadata
new { Value = (flags & 0x4000) != 0, Meaning = "Image supports Control Flow Guard" }, new { Value = (flags & 0x4000) != 0, Meaning = "Image supports Control Flow Guard" },
new { Value = (flags & 0x8000) != 0, Meaning = "Image is Terminal Server aware" }, new { Value = (flags & 0x8000) != 0, Meaning = "Image is Terminal Server aware" },
}); });
dataGridFactory.SetValue(DataGrid.GridLinesVisibilityProperty, DataGridGridLinesVisibility.None);
DataTemplate template = new DataTemplate(); DataTemplate template = new DataTemplate();
template.VisualTree = dataGridFactory; template.VisualTree = dataGridFactory;
return template; return template;

Loading…
Cancel
Save