Browse Source

Merge pull request #1198 from icsharpcode/ts-in-ui

Ts in ui
pull/1030/head
Siegfried Pammer 7 years ago committed by GitHub
parent
commit
8fd8aa2e3a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      ICSharpCode.Decompiler.PdbProvider.Cecil/MonoCecilDebugInfoProvider.cs
  2. 13
      ICSharpCode.Decompiler.Tests/Helpers/Tester.cs
  3. 5
      ICSharpCode.Decompiler.Tests/RoundtripAssembly.cs
  4. 45
      ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
  5. 16
      ICSharpCode.Decompiler/CSharp/SequencePointBuilder.cs
  6. 15
      ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs
  7. 5
      ICSharpCode.Decompiler/CSharp/Transforms/AddXmlDocumentationTransform.cs
  8. 9
      ICSharpCode.Decompiler/CSharp/WholeProjectDecompiler.cs
  9. 19
      ICSharpCode.Decompiler/DebugInfo/IDebugInfoProvider.cs
  10. 6
      ICSharpCode.Decompiler/DebugInfo/PortablePdbWriter.cs
  11. 2
      ICSharpCode.Decompiler/DebugInfo/SequencePoint.cs
  12. 2
      ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs
  13. 15
      ICSharpCode.Decompiler/Disassembler/DomExtensions.cs
  14. 27
      ICSharpCode.Decompiler/Disassembler/MethodBodyDisassembler.cs
  15. 267
      ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs
  16. 591
      ICSharpCode.Decompiler/Documentation/XmlDocKeyProvider.cs
  17. 20
      ICSharpCode.Decompiler/Documentation/XmlDocumentationProvider.cs
  18. 7
      ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
  19. 6
      ICSharpCode.Decompiler/IL/ControlFlow/YieldReturnDecompiler.cs
  20. 12
      ICSharpCode.Decompiler/IL/ILReader.cs
  21. 4
      ICSharpCode.Decompiler/IL/ILVariable.cs
  22. 10
      ICSharpCode.Decompiler/IL/InstructionOutputExtensions.cs
  23. 2
      ICSharpCode.Decompiler/IL/Instructions/Block.cs
  24. 4
      ICSharpCode.Decompiler/IL/Instructions/BlockContainer.cs
  25. 2
      ICSharpCode.Decompiler/IL/Instructions/Branch.cs
  26. 2
      ICSharpCode.Decompiler/IL/Instructions/Leave.cs
  27. 2
      ICSharpCode.Decompiler/IL/Instructions/SwitchInstruction.cs
  28. 2
      ICSharpCode.Decompiler/IL/Instructions/TryInstruction.cs
  29. 5
      ICSharpCode.Decompiler/IL/Transforms/DelegateConstruction.cs
  30. 16
      ICSharpCode.Decompiler/IL/Transforms/IILTransform.cs
  31. 18
      ICSharpCode.Decompiler/IL/Transforms/ProxyCallReplacer.cs
  32. 419
      ICSharpCode.Decompiler/Metadata/Dom.cs
  33. 36
      ICSharpCode.Decompiler/Metadata/MetadataExtensions.cs
  34. 64
      ICSharpCode.Decompiler/Metadata/MetadataResolver.cs
  35. 20
      ICSharpCode.Decompiler/Metadata/PEFile.cs
  36. 5
      ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs
  37. 12
      ICSharpCode.Decompiler/Output/ITextOutput.cs
  38. 28
      ICSharpCode.Decompiler/Output/PlainTextOutput.cs
  39. 86
      ICSharpCode.Decompiler/Output/TextTokenWriter.cs
  40. 12
      ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs
  41. 6
      ICSharpCode.Decompiler/TypeSystem/IAssembly.cs
  42. 2
      ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultUnresolvedAssembly.cs
  43. 3
      ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeDefinition.cs
  44. 6
      ICSharpCode.Decompiler/TypeSystem/MetadataAssembly.cs
  45. 5
      ILSpy.BamlDecompiler.Tests/BamlTestRunner.cs
  46. 14
      ILSpy.BamlDecompiler/BamlResourceEntryNode.cs
  47. 2
      ILSpy.BamlDecompiler/BamlResourceNodeFactory.cs
  48. 7
      ILSpy.BamlDecompiler/CecilTypeResolver.cs
  49. 38
      ILSpy.BamlDecompiler/ConnectMethodDecompiler.cs
  50. 4
      ILSpy/AnalyzerTreeView.cs
  51. 2
      ILSpy/Commands/DecompileAllCommand.cs
  52. 9
      ILSpy/DebugInfo/DiaSymNativeDebugInfoProvider.cs
  53. 7
      ILSpy/DebugInfo/PortableDebugInfoProvider.cs
  54. 4
      ILSpy/DebugSteps.xaml.cs
  55. 19
      ILSpy/ILSpy.csproj
  56. 4
      ILSpy/Languages/CSharpILMixedLanguage.cs
  57. 433
      ILSpy/Languages/CSharpLanguage.cs
  58. 3
      ILSpy/Languages/CodeMappingInfo.cs
  59. 36
      ILSpy/Languages/ILAstLanguage.cs
  60. 46
      ILSpy/Languages/ILLanguage.cs
  61. 172
      ILSpy/Languages/ILSignatureProvider.cs
  62. 215
      ILSpy/Languages/Language.cs
  63. 55
      ILSpy/LoadedAssembly.cs
  64. 36
      ILSpy/LoadedAssemblyExtensions.cs
  65. 86
      ILSpy/MainWindow.xaml.cs
  66. 9
      ILSpy/SearchPane.cs
  67. 157
      ILSpy/SearchStrategies.cs
  68. 65
      ILSpy/TextView/AvalonEditTextOutput.cs
  69. 38
      ILSpy/TextView/DecompilerTextView.cs
  70. 13
      ILSpy/TreeNodes/Analyzer/AnalyzeContextMenuEntry.cs
  71. 6
      ILSpy/TreeNodes/Analyzer/ScopedWhereUsedAnalyzer.cs
  72. 99
      ILSpy/TreeNodes/AssemblyListTreeNode.cs
  73. 26
      ILSpy/TreeNodes/AssemblyTreeNode.cs
  74. 74
      ILSpy/TreeNodes/BaseTypesEntryNode.cs
  75. 34
      ILSpy/TreeNodes/BaseTypesTreeNode.cs
  76. 52
      ILSpy/TreeNodes/CopyFullyQualifiedNameContextMenuEntry.cs
  77. 50
      ILSpy/TreeNodes/DerivedTypesEntryNode.cs
  78. 48
      ILSpy/TreeNodes/DerivedTypesTreeNode.cs
  79. 52
      ILSpy/TreeNodes/EventTreeNode.cs
  80. 54
      ILSpy/TreeNodes/FieldTreeNode.cs
  81. 4
      ILSpy/TreeNodes/GeneratePdbContextMenuEntry.cs
  82. 10
      ILSpy/TreeNodes/IMemberTreeNode.cs
  83. 84
      ILSpy/TreeNodes/MethodTreeNode.cs
  84. 44
      ILSpy/TreeNodes/PropertyTreeNode.cs
  85. 134
      ILSpy/TreeNodes/TypeTreeNode.cs
  86. 9
      TestPlugin/CustomLanguage.cs

4
ICSharpCode.Decompiler.PdbProvider.Cecil/MonoCecilDebugInfoProvider.cs

@ -20,7 +20,7 @@ using System.Collections.Generic; @@ -20,7 +20,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Reflection.Metadata.Ecma335;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.DebugInfo;
using ICSharpCode.Decompiler.Util;
using Mono.Cecil;
@ -43,7 +43,7 @@ namespace ICSharpCode.Decompiler.PdbProvider.Cecil @@ -43,7 +43,7 @@ namespace ICSharpCode.Decompiler.PdbProvider.Cecil
var method = this.module.LookupToken(MetadataTokens.GetToken(handle)) as Mono.Cecil.MethodDefinition;
if (method?.DebugInformation == null || !method.DebugInformation.HasSequencePoints)
return EmptyList<SequencePoint>.Instance;
return method.DebugInformation.SequencePoints.Select(point => new Metadata.SequencePoint {
return method.DebugInformation.SequencePoints.Select(point => new SequencePoint {
Offset = point.Offset,
StartLine = point.StartLine,
StartColumn = point.StartColumn,

13
ICSharpCode.Decompiler.Tests/Helpers/Tester.cs

@ -348,8 +348,9 @@ namespace ICSharpCode.Decompiler.Tests.Helpers @@ -348,8 +348,9 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
var emitResult = compilation.Emit(peStream);
peStream.Position = 0;
var moduleDefinition = new PEFile("TestAssembly.dll", peStream, false, PEStreamOptions.PrefetchEntireImage);
var decompiler = new CSharpDecompiler(moduleDefinition, new DecompilerSettings());
var moduleDefinition = new PEFile("TestAssembly.dll", peStream, PEStreamOptions.PrefetchEntireImage);
var resolver = new UniversalAssemblyResolver("TestAssembly.dll", false, moduleDefinition.Reader.DetectTargetFrameworkId(), PEStreamOptions.PrefetchEntireImage);
var decompiler = new CSharpDecompiler(moduleDefinition, resolver, new DecompilerSettings());
return decompiler;
}
@ -394,9 +395,11 @@ namespace ICSharpCode.Decompiler.Tests.Helpers @@ -394,9 +395,11 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
public static string DecompileCSharp(string assemblyFileName, DecompilerSettings settings = null)
{
using (var file = new FileStream(assemblyFileName, FileMode.Open, FileAccess.Read)) {
var module = new PEFile(assemblyFileName, file, false, PEStreamOptions.PrefetchEntireImage);
var typeSystem = new DecompilerTypeSystem(module);
CSharpDecompiler decompiler = new CSharpDecompiler(typeSystem, settings ?? new DecompilerSettings());
var module = new PEFile(assemblyFileName, file, PEStreamOptions.PrefetchEntireImage);
var resolver = new UniversalAssemblyResolver(assemblyFileName, false,
module.Reader.DetectTargetFrameworkId(), PEStreamOptions.PrefetchMetadata);
var typeSystem = new DecompilerTypeSystem(module, resolver);
CSharpDecompiler decompiler = new CSharpDecompiler(typeSystem, resolver, settings ?? new DecompilerSettings());
decompiler.AstTransforms.Insert(0, new RemoveEmbeddedAtttributes());
decompiler.AstTransforms.Insert(0, new RemoveCompilerAttribute());
decompiler.AstTransforms.Add(new EscapeInvalidIdentifiers());

5
ICSharpCode.Decompiler.Tests/RoundtripAssembly.cs

@ -144,11 +144,12 @@ namespace ICSharpCode.Decompiler.Tests @@ -144,11 +144,12 @@ namespace ICSharpCode.Decompiler.Tests
Console.WriteLine($"Decompiling {fileToRoundtrip}...");
Stopwatch w = Stopwatch.StartNew();
using (var fileStream = new FileStream(file, FileMode.Open, FileAccess.Read)) {
PEFile module = new PEFile(file, fileStream, false, PEStreamOptions.PrefetchEntireImage);
UniversalAssemblyResolver resolver = (UniversalAssemblyResolver)module.AssemblyResolver;
PEFile module = new PEFile(file, fileStream, PEStreamOptions.PrefetchEntireImage);
UniversalAssemblyResolver resolver = new UniversalAssemblyResolver(file, false, module.Reader.DetectTargetFrameworkId(), PEStreamOptions.PrefetchMetadata);
resolver.AddSearchDirectory(inputDir);
resolver.RemoveSearchDirectory(".");
var decompiler = new TestProjectDecompiler(inputDir);
decompiler.AssemblyResolver = resolver;
// use a fixed GUID so that we can diff the output between different ILSpy runs without spurious changes
decompiler.ProjectGuid = Guid.Parse("{127C83E4-4587-4CF9-ADCA-799875F3DFE6}");
decompiler.DecompileProject(module, decompiledDir);

45
ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs

@ -39,6 +39,8 @@ using System.Reflection.Metadata; @@ -39,6 +39,8 @@ using System.Reflection.Metadata;
using SRM = System.Reflection.Metadata;
using ICSharpCode.Decompiler.Metadata;
using System.Reflection.PortableExecutable;
using ICSharpCode.Decompiler.Documentation;
using ICSharpCode.Decompiler.DebugInfo;
namespace ICSharpCode.Decompiler.CSharp
{
@ -179,6 +181,18 @@ namespace ICSharpCode.Decompiler.CSharp @@ -179,6 +181,18 @@ namespace ICSharpCode.Decompiler.CSharp
public IDecompilerTypeSystem TypeSystem => typeSystem;
public IAssemblyResolver AssemblyResolver { get; }
/// <summary>
/// Gets or sets the optional provider for debug info.
/// </summary>
public IDebugInfoProvider DebugInfoProvider { get; set; }
/// <summary>
/// Gets or sets the optional provider for XML documentation strings.
/// </summary>
public IDocumentationProvider DocumentationProvider { get; set; }
/// <summary>
/// IL transforms.
/// </summary>
@ -193,21 +207,20 @@ namespace ICSharpCode.Decompiler.CSharp @@ -193,21 +207,20 @@ namespace ICSharpCode.Decompiler.CSharp
get { return astTransforms; }
}
public CSharpDecompiler(string fileName, DecompilerSettings settings)
: this(LoadPEFile(fileName, settings), settings)
public CSharpDecompiler(string fileName, IAssemblyResolver assemblyResolver, DecompilerSettings settings)
: this(LoadPEFile(fileName, settings), assemblyResolver, settings)
{
}
public CSharpDecompiler(Metadata.PEFile module, DecompilerSettings settings)
: this(new DecompilerTypeSystem(module, settings), settings)
public CSharpDecompiler(PEFile module, IAssemblyResolver assemblyResolver, DecompilerSettings settings)
: this(new DecompilerTypeSystem(module, assemblyResolver, settings), assemblyResolver, settings)
{
}
public CSharpDecompiler(DecompilerTypeSystem typeSystem, DecompilerSettings settings)
public CSharpDecompiler(DecompilerTypeSystem typeSystem, IAssemblyResolver assemblyResolver, DecompilerSettings settings)
{
if (typeSystem == null)
throw new ArgumentNullException(nameof(typeSystem));
this.typeSystem = typeSystem;
this.typeSystem = typeSystem ?? throw new ArgumentNullException(nameof(typeSystem));
this.AssemblyResolver = assemblyResolver ?? throw new ArgumentNullException(nameof(assemblyResolver));
this.settings = settings;
}
@ -318,7 +331,6 @@ namespace ICSharpCode.Decompiler.CSharp @@ -318,7 +331,6 @@ namespace ICSharpCode.Decompiler.CSharp
return new PEFile(
fileName,
new FileStream(fileName, FileMode.Open, FileAccess.Read),
settings.ThrowOnAssemblyResolveErrors,
options: settings.LoadInMemory ? PEStreamOptions.PrefetchEntireImage : PEStreamOptions.Default
);
}
@ -436,7 +448,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -436,7 +448,7 @@ namespace ICSharpCode.Decompiler.CSharp
{
var decompileRun = new DecompileRun(settings) { CancellationToken = CancellationToken };
RequiredNamespaceCollector.CollectNamespaces(function.Method, typeSystem, decompileRun.Namespaces);
return new ILTransformContext(function, typeSystem, settings) {
return new ILTransformContext(function, typeSystem, DebugInfoProvider, settings) {
CancellationToken = CancellationToken,
DecompileRun = decompileRun
};
@ -887,10 +899,13 @@ namespace ICSharpCode.Decompiler.CSharp @@ -887,10 +899,13 @@ namespace ICSharpCode.Decompiler.CSharp
{
try {
var specializingTypeSystem = typeSystem.GetSpecializingTypeSystem(decompilationContext);
var ilReader = new ILReader(specializingTypeSystem);
ilReader.UseDebugSymbols = settings.UseDebugSymbols;
var ilReader = new ILReader(specializingTypeSystem) {
UseDebugSymbols = settings.UseDebugSymbols,
DebugInfo = DebugInfoProvider
};
var methodDef = typeSystem.ModuleDefinition.Metadata.GetMethodDefinition((MethodDefinitionHandle)method.MetadataToken);
var function = ilReader.ReadIL(typeSystem.ModuleDefinition, (MethodDefinitionHandle)method.MetadataToken, typeSystem.ModuleDefinition.Reader.GetMethodBody(methodDef.RelativeVirtualAddress), CancellationToken);
var methodBody = typeSystem.ModuleDefinition.Reader.GetMethodBody(methodDef.RelativeVirtualAddress);
var function = ilReader.ReadIL(typeSystem.ModuleDefinition, (MethodDefinitionHandle)method.MetadataToken, methodBody, CancellationToken);
function.CheckInvariant(ILPhase.Normal);
if (entityDecl != null) {
@ -911,7 +926,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -911,7 +926,7 @@ namespace ICSharpCode.Decompiler.CSharp
localSettings.AlwaysCastTargetsOfExplicitInterfaceImplementationCalls = true;
}
var context = new ILTransformContext(function, specializingTypeSystem, localSettings) {
var context = new ILTransformContext(function, specializingTypeSystem, DebugInfoProvider, localSettings) {
CancellationToken = CancellationToken,
DecompileRun = decompileRun
};
@ -1126,7 +1141,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1126,7 +1141,7 @@ namespace ICSharpCode.Decompiler.CSharp
///
/// This only works correctly when the nodes in the syntax tree have line/column information.
/// </summary>
public Dictionary<ILFunction, List<Metadata.SequencePoint>> CreateSequencePoints(SyntaxTree syntaxTree)
public Dictionary<ILFunction, List<DebugInfo.SequencePoint>> CreateSequencePoints(SyntaxTree syntaxTree)
{
SequencePointBuilder spb = new SequencePointBuilder();
syntaxTree.AcceptVisitor(spb);

16
ICSharpCode.Decompiler/CSharp/SequencePointBuilder.cs

@ -56,7 +56,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -56,7 +56,7 @@ namespace ICSharpCode.Decompiler.CSharp
}
}
readonly List<(ILFunction, Metadata.SequencePoint)> sequencePoints = new List<(ILFunction, Metadata.SequencePoint)>();
readonly List<(ILFunction, DebugInfo.SequencePoint)> sequencePoints = new List<(ILFunction, DebugInfo.SequencePoint)>();
readonly HashSet<ILInstruction> mappedInstructions = new HashSet<ILInstruction>();
// Stack holding information for outer statements.
@ -219,7 +219,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -219,7 +219,7 @@ namespace ICSharpCode.Decompiler.CSharp
// use LongSet to deduplicate and merge the intervals
var longSet = new LongSet(current.Intervals.Select(i => new LongInterval(i.Start, i.End)));
Debug.Assert(!longSet.IsEmpty);
sequencePoints.Add((current.Function, new Metadata.SequencePoint {
sequencePoints.Add((current.Function, new DebugInfo.SequencePoint {
Offset = (int)longSet.Intervals[0].Start,
EndOffset = (int)longSet.Intervals[0].End,
StartLine = startLocation.Line,
@ -277,18 +277,18 @@ namespace ICSharpCode.Decompiler.CSharp @@ -277,18 +277,18 @@ namespace ICSharpCode.Decompiler.CSharp
/// <summary>
/// Called after the visitor is done to return the results.
/// </summary>
internal Dictionary<ILFunction, List<Metadata.SequencePoint>> GetSequencePoints()
internal Dictionary<ILFunction, List<DebugInfo.SequencePoint>> GetSequencePoints()
{
var dict = new Dictionary<ILFunction, List<Metadata.SequencePoint>>();
var dict = new Dictionary<ILFunction, List<DebugInfo.SequencePoint>>();
foreach (var (function, sequencePoint) in this.sequencePoints) {
if (!dict.TryGetValue(function, out var list)) {
dict.Add(function, list = new List<Metadata.SequencePoint>());
dict.Add(function, list = new List<DebugInfo.SequencePoint>());
}
list.Add(sequencePoint);
}
foreach (var (function, list) in dict.ToList()) {
// For each function, sort sequence points and fix overlaps+gaps
var newList = new List<Metadata.SequencePoint>();
var newList = new List<DebugInfo.SequencePoint>();
int pos = 0;
foreach (var sequencePoint in list.OrderBy(sp => sp.Offset).ThenBy(sp => sp.EndOffset)) {
if (sequencePoint.Offset < pos) {
@ -305,7 +305,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -305,7 +305,7 @@ namespace ICSharpCode.Decompiler.CSharp
}
} else if (sequencePoint.Offset > pos) {
// insert hidden sequence point in the gap.
var hidden = new Metadata.SequencePoint();
var hidden = new DebugInfo.SequencePoint();
hidden.Offset = pos;
hidden.EndOffset = sequencePoint.Offset;
hidden.SetHidden();
@ -315,7 +315,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -315,7 +315,7 @@ namespace ICSharpCode.Decompiler.CSharp
pos = sequencePoint.EndOffset;
}
if (pos < function.CodeSize) {
var hidden = new Metadata.SequencePoint();
var hidden = new DebugInfo.SequencePoint();
hidden.Offset = pos;
hidden.EndOffset = function.CodeSize;
hidden.SetHidden();

15
ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs

@ -64,6 +64,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -64,6 +64,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
#region Properties
void InitProperties()
{
this.AlwaysUseBuiltinTypeNames = true;
this.ShowAccessibility = true;
this.ShowModifiers = true;
this.ShowBaseTypes = true;
@ -135,13 +136,19 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -135,13 +136,19 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
/// The default value is <c>false</c>.
/// </summary>
public bool ShowAttributes { get; set; }
/// <summary>
/// Controls whether to use fully-qualified type names or short type names.
/// The default value is <c>false</c>.
/// </summary>
public bool AlwaysUseShortTypeNames { get; set; }
/// <summary>
/// Controls whether to use fully-qualified type names or short type names.
/// The default value is <c>true</c>.
/// </summary>
public bool AlwaysUseBuiltinTypeNames { get; set; }
/// <summary>
/// Determines the name lookup mode for converting a type name.
///
@ -233,7 +240,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -233,7 +240,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
}
}
if (type is ParameterizedType pt) {
if (pt.IsKnownType(KnownTypeCode.NullableOfT)) {
if (AlwaysUseBuiltinTypeNames && pt.IsKnownType(KnownTypeCode.NullableOfT)) {
return ConvertType(pt.TypeArguments[0]).MakeNullableType();
}
return ConvertTypeHelper(pt.GenericType, pt.TypeArguments);
@ -269,7 +276,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -269,7 +276,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
Debug.Assert(genericType is ITypeDefinition || genericType.Kind == TypeKind.Unknown);
ITypeDefinition typeDef = genericType as ITypeDefinition;
if (typeDef != null) {
if (AlwaysUseBuiltinTypeNames && typeDef != null) {
string keyword = KnownTypeReference.GetCSharpNameByTypeCode(typeDef.KnownTypeCode);
if (keyword != null)
return new PrimitiveType(keyword);

5
ICSharpCode.Decompiler/CSharp/Transforms/AddXmlDocumentationTransform.cs

@ -41,10 +41,9 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -41,10 +41,9 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
if (xmldoc == null)
return;
foreach (var entity in rootNode.DescendantsAndSelf.OfType<EntityDeclaration>()) {
var handle = ((entity.GetSymbol() as IEntity)?.MetadataToken).Value;
if (handle.IsNil)
if (!(entity.GetSymbol() is IEntity symbolicEntity))
continue;
string doc = xmldoc.GetDocumentation(XmlDocKeyProvider.GetKey(context.TypeSystem.GetMetadata(), handle));
string doc = xmldoc.GetDocumentation(XmlDocKeyProvider.GetKey(symbolicEntity));
if (doc != null) {
InsertXmlDocumentation(entity, new StringReader(doc));
}

9
ICSharpCode.Decompiler/CSharp/WholeProjectDecompiler.cs

@ -34,6 +34,7 @@ using System.Reflection.PortableExecutable; @@ -34,6 +34,7 @@ using System.Reflection.PortableExecutable;
using System.Reflection.Metadata;
using static ICSharpCode.Decompiler.Metadata.DotNetCorePathFinderExtensions;
using static ICSharpCode.Decompiler.Metadata.MetadataExtensions;
using ICSharpCode.Decompiler.Metadata;
namespace ICSharpCode.Decompiler.CSharp
{
@ -56,6 +57,8 @@ namespace ICSharpCode.Decompiler.CSharp @@ -56,6 +57,8 @@ namespace ICSharpCode.Decompiler.CSharp
}
}
public IAssemblyResolver AssemblyResolver { get; set; }
/// <summary>
/// The MSBuild ProjectGuid to use for the new project.
/// <c>null</c> to automatically generate a new GUID.
@ -218,7 +221,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -218,7 +221,7 @@ namespace ICSharpCode.Decompiler.CSharp
if (r.Name != "mscorlib") {
w.WriteStartElement("Reference");
w.WriteAttributeString("Include", r.Name);
var asm = module.AssemblyResolver.Resolve(r);
var asm = AssemblyResolver.Resolve(r);
if (!IsGacAssembly(r, asm)) {
if (asm != null) {
w.WriteElementString("HintPath", asm.FileName);
@ -275,7 +278,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -275,7 +278,7 @@ namespace ICSharpCode.Decompiler.CSharp
CSharpDecompiler CreateDecompiler(DecompilerTypeSystem ts)
{
var decompiler = new CSharpDecompiler(ts, settings);
var decompiler = new CSharpDecompiler(ts, AssemblyResolver, settings);
decompiler.AstTransforms.Add(new EscapeInvalidIdentifiers());
decompiler.AstTransforms.Add(new RemoveCLSCompliantAttribute());
return decompiler;
@ -314,7 +317,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -314,7 +317,7 @@ namespace ICSharpCode.Decompiler.CSharp
return Path.Combine(dir, file);
}
}, StringComparer.OrdinalIgnoreCase).ToList();
DecompilerTypeSystem ts = new DecompilerTypeSystem(module);
DecompilerTypeSystem ts = new DecompilerTypeSystem(module, AssemblyResolver);
Parallel.ForEach(
files,
new ParallelOptions {

19
ICSharpCode.Decompiler/DebugInfo/IDebugInfoProvider.cs

@ -0,0 +1,19 @@ @@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Reflection.Metadata;
using System.Text;
namespace ICSharpCode.Decompiler.DebugInfo
{
public struct Variable
{
public string Name { get; set; }
}
public interface IDebugInfoProvider
{
IList<SequencePoint> GetSequencePoints(MethodDefinitionHandle method);
IList<Variable> GetVariables(MethodDefinitionHandle method);
bool TryGetName(MethodDefinitionHandle method, int index, out string name);
}
}

6
ICSharpCode.Decompiler/Pdb/PortablePdbWriter.cs → ICSharpCode.Decompiler/DebugInfo/PortablePdbWriter.cs

@ -17,7 +17,7 @@ using ICSharpCode.Decompiler.Metadata; @@ -17,7 +17,7 @@ using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.Util;
namespace ICSharpCode.Decompiler.Pdb
namespace ICSharpCode.Decompiler.DebugInfo
{
public class PortablePdbWriter
{
@ -39,7 +39,7 @@ namespace ICSharpCode.Decompiler.Pdb @@ -39,7 +39,7 @@ namespace ICSharpCode.Decompiler.Pdb
var hasher = SHA256.Create();
var sequencePointBlobs = new Dictionary<MethodDefinitionHandle, (DocumentHandle Document, BlobHandle SequencePoints)>();
var importScopeBlobs = new Dictionary<MethodDefinitionHandle, (DocumentHandle Document, BlobHandle ImportScope)>();
var emptyList = new List<Metadata.SequencePoint>();
var emptyList = new List<SequencePoint>();
foreach (var handle in reader.GetTopLevelTypeDefinitions()) {
var type = reader.GetTypeDefinition(handle);
@ -156,7 +156,7 @@ namespace ICSharpCode.Decompiler.Pdb @@ -156,7 +156,7 @@ namespace ICSharpCode.Decompiler.Pdb
return metadata.GetOrAddBlob(writer);
}
static BlobHandle EncodeSequencePoints(MetadataBuilder metadata, int localSignatureRowId, List<Metadata.SequencePoint> sequencePoints)
static BlobHandle EncodeSequencePoints(MetadataBuilder metadata, int localSignatureRowId, List<SequencePoint> sequencePoints)
{
if (sequencePoints.Count == 0)
return default;

2
ICSharpCode.Decompiler/Metadata/SequencePoint.cs → ICSharpCode.Decompiler/DebugInfo/SequencePoint.cs

@ -18,7 +18,7 @@ @@ -18,7 +18,7 @@
using System;
namespace ICSharpCode.Decompiler.Metadata
namespace ICSharpCode.Decompiler.DebugInfo
{
/// <summary>
/// A sequence point read from a PDB file or produced by the decompiler.

2
ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs

@ -64,7 +64,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -64,7 +64,7 @@ namespace ICSharpCode.Decompiler.Disassembler
if (offset == null)
writer.Write("null");
else
writer.WriteReference(OffsetToString(offset.Value), offset);
writer.WriteLocalReference(OffsetToString(offset.Value), offset);
}
public static void WriteTo(this SRM.ExceptionRegion exceptionHandler, Metadata.PEFile module, GenericContext context, ITextOutput writer)

15
ICSharpCode.Decompiler/Disassembler/DomExtensions.cs

@ -43,7 +43,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -43,7 +43,7 @@ namespace ICSharpCode.Decompiler.Disassembler
switch (entity.Kind) {
case HandleKind.TypeDefinition: {
var td = metadata.GetTypeDefinition((TypeDefinitionHandle)entity);
output.WriteReference(td.GetFullTypeName(metadata).ToILNameString(), new Metadata.TypeDefinition(module, (TypeDefinitionHandle)entity));
output.WriteReference(module, entity, td.GetFullTypeName(metadata).ToILNameString());
break;
}
case HandleKind.TypeReference: {
@ -68,7 +68,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -68,7 +68,7 @@ namespace ICSharpCode.Decompiler.Disassembler
}
output.Write("]");
}
output.WriteReference(entity.GetFullTypeName(metadata).ToILNameString(), new Metadata.TypeReference(module, (TypeReferenceHandle)entity));
output.WriteReference(module, entity, entity.GetFullTypeName(metadata).ToILNameString());
break;
}
case HandleKind.TypeSpecification: {
@ -84,7 +84,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -84,7 +84,7 @@ namespace ICSharpCode.Decompiler.Disassembler
output.Write(' ');
((EntityHandle)fd.GetDeclaringType()).WriteTo(module, output, GenericContext.Empty, ILNameSyntax.TypeName);
output.Write("::");
output.WriteReference(DisassemblerHelpers.Escape(metadata.GetString(fd.Name)), new Metadata.FieldDefinition(module, (FieldDefinitionHandle)entity));
output.WriteReference(module, entity, DisassemblerHelpers.Escape(metadata.GetString(fd.Name)));
break;
}
case HandleKind.MethodDefinition: {
@ -106,11 +106,10 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -106,11 +106,10 @@ namespace ICSharpCode.Decompiler.Disassembler
output.Write("::");
}
bool isCompilerControlled = (md.Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.PrivateScope;
var reference = new Metadata.MethodDefinition(module, (MethodDefinitionHandle)entity);
if (isCompilerControlled) {
output.WriteReference(DisassemblerHelpers.Escape(metadata.GetString(md.Name) + "$PST" + MetadataTokens.GetToken(entity).ToString("X8")), reference);
output.WriteReference(module, entity, DisassemblerHelpers.Escape(metadata.GetString(md.Name) + "$PST" + MetadataTokens.GetToken(entity).ToString("X8")));
} else {
output.WriteReference(DisassemblerHelpers.Escape(metadata.GetString(md.Name)), reference);
output.WriteReference(module, entity, DisassemblerHelpers.Escape(metadata.GetString(md.Name)));
}
var genericParameters = md.GetGenericParameters();
if (genericParameters.Count > 0) {
@ -174,7 +173,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -174,7 +173,7 @@ namespace ICSharpCode.Decompiler.Disassembler
output.Write(' ');
WriteParent(output, module, metadata, mr.Parent, genericContext, syntax);
output.Write("::");
output.WriteReference(DisassemblerHelpers.Escape(memberName), new Metadata.MemberReference(module, (MemberReferenceHandle)entity));
output.WriteReference(module, entity, DisassemblerHelpers.Escape(memberName));
output.Write("(");
for (int i = 0; i < methodSignature.ParameterTypes.Length; ++i) {
if (i > 0)
@ -191,7 +190,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -191,7 +190,7 @@ namespace ICSharpCode.Decompiler.Disassembler
output.Write(' ');
WriteParent(output, module, metadata, mr.Parent, genericContext, syntax);
output.Write("::");
output.WriteReference(DisassemblerHelpers.Escape(memberName), new Metadata.MemberReference(module, (MemberReferenceHandle)entity));
output.WriteReference(module, entity, DisassemblerHelpers.Escape(memberName));
break;
}
break;

27
ICSharpCode.Decompiler/Disassembler/MethodBodyDisassembler.cs

@ -21,7 +21,7 @@ using System.Collections.Generic; @@ -21,7 +21,7 @@ using System.Collections.Generic;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using System.Threading;
using ICSharpCode.Decompiler.DebugInfo;
using ICSharpCode.Decompiler.IL;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.Util;
@ -51,7 +51,12 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -51,7 +51,12 @@ namespace ICSharpCode.Decompiler.Disassembler
/// </summary>
public bool ShowMetadataTokens { get; set; }
IList<Metadata.SequencePoint> sequencePoints;
/// <summary>
/// Optional provider for sequence points.
/// </summary>
public IDebugInfoProvider DebugInfo { get; set; }
IList<DebugInfo.SequencePoint> sequencePoints;
int nextSequencePointIndex;
// cache info
@ -68,7 +73,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -68,7 +73,7 @@ namespace ICSharpCode.Decompiler.Disassembler
public virtual void Disassemble(PEFile module, MethodDefinitionHandle handle)
{
this.module = module;
this.module = module ?? throw new ArgumentNullException(nameof(module));
metadata = module.Metadata;
genericContext = new GenericContext(handle, module);
signatureDecoder = new DisassemblerSignatureProvider(module, output);
@ -94,7 +99,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -94,7 +99,7 @@ namespace ICSharpCode.Decompiler.Disassembler
DisassembleLocalsBlock(body);
output.WriteLine();
sequencePoints = module.DebugInfo?.GetSequencePoints(handle) ?? EmptyList<Metadata.SequencePoint>.Instance;
sequencePoints = DebugInfo?.GetSequencePoints(handle) ?? EmptyList<DebugInfo.SequencePoint>.Instance;
nextSequencePointIndex = 0;
if (DetectControlStructure && blob.Length > 0) {
blob.Reset();
@ -133,7 +138,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -133,7 +138,7 @@ namespace ICSharpCode.Decompiler.Disassembler
output.Indent();
int index = 0;
foreach (var v in signature) {
output.WriteDefinition("[" + index + "] ", v);
output.WriteLocalReference("[" + index + "] ", v, isDefinition: true);
v(ILNameSyntax.TypeName);
if (index + 1 < signature.Length)
output.Write(',');
@ -278,7 +283,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -278,7 +283,7 @@ namespace ICSharpCode.Decompiler.Disassembler
{
int offset = blob.Offset;
if (ShowSequencePoints && nextSequencePointIndex < sequencePoints?.Count) {
Metadata.SequencePoint sp = sequencePoints[nextSequencePointIndex];
var sp = sequencePoints[nextSequencePointIndex];
if (sp.Offset <= offset) {
output.Write("// sequence point: ");
if (sp.Offset != offset) {
@ -293,16 +298,16 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -293,16 +298,16 @@ namespace ICSharpCode.Decompiler.Disassembler
}
}
ILOpCode opCode = ILParser.DecodeOpCode(ref blob);
output.WriteDefinition(DisassemblerHelpers.OffsetToString(offset), offset);
output.WriteLocalReference(DisassemblerHelpers.OffsetToString(offset), offset, isDefinition: true);
output.Write(": ");
if (opCode.IsDefined()) {
output.WriteReference(opCode.GetDisplayName(), new OpCodeInfo(opCode, opCode.GetDisplayName()));
output.WriteReference(new OpCodeInfo(opCode, opCode.GetDisplayName()));
switch (opCode.GetOperandType()) {
case OperandType.BrTarget:
case OperandType.ShortBrTarget:
output.Write(' ');
int targetOffset = ILParser.DecodeBranchTarget(ref blob, opCode);
output.WriteReference($"IL_{targetOffset:x4}", targetOffset, true);
output.WriteLocalReference($"IL_{targetOffset:x4}", targetOffset);
break;
case OperandType.Field:
case OperandType.Method:
@ -387,7 +392,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -387,7 +392,7 @@ namespace ICSharpCode.Decompiler.Disassembler
for (int i = 0; i < targets.Length; i++) {
if (i > 0)
output.Write(", ");
output.WriteReference($"IL_{targets[i]:x4}", targets[i], true);
output.WriteLocalReference($"IL_{targets[i]:x4}", targets[i]);
}
output.Write(")");
break;
@ -416,7 +421,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -416,7 +421,7 @@ namespace ICSharpCode.Decompiler.Disassembler
// split 16-bit value into two emitbyte directives
output.WriteLine($".emitbyte 0x{(byte)(opCodeValue >> 8):x}");
// add label
output.WriteDefinition(DisassemblerHelpers.OffsetToString(offset + 1), offset + 1);
output.WriteLocalReference(DisassemblerHelpers.OffsetToString(offset + 1), offset + 1, isDefinition: true);
output.Write(": ");
output.Write($".emitbyte 0x{(byte)(opCodeValue & 0xFF):x}");
} else {

267
ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs

@ -27,6 +27,7 @@ using System.Threading; @@ -27,6 +27,7 @@ using System.Threading;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.IL;
using ICSharpCode.Decompiler.DebugInfo;
namespace ICSharpCode.Decompiler.Disassembler
{
@ -55,8 +56,15 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -55,8 +56,15 @@ namespace ICSharpCode.Decompiler.Disassembler
set => methodBodyDisassembler.ShowMetadataTokens = value;
}
public IDebugInfoProvider DebugInfo {
get => methodBodyDisassembler.DebugInfo;
set => methodBodyDisassembler.DebugInfo = value;
}
public bool ExpandMemberDefinitions { get; set; } = false;
public IAssemblyResolver AssemblyResolver { get; set; }
public ReflectionDisassembler(ITextOutput output, CancellationToken cancellationToken)
: this(output, new MethodBodyDisassembler(output, cancellationToken), cancellationToken)
{
@ -125,25 +133,27 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -125,25 +133,27 @@ namespace ICSharpCode.Decompiler.Disassembler
public void DisassembleMethod(PEFile module, MethodDefinitionHandle handle)
{
var metadata = module.Metadata;
var genericContext = new GenericContext(handle, module);
// write method header
output.WriteDefinition(".method ", new Metadata.MethodDefinition(module, handle));
DisassembleMethodHeaderInternal(module, handle, metadata, genericContext);
DisassembleMethodBlock(module, handle, metadata, genericContext);
output.WriteReference(module, handle, ".method", isDefinition: true);
output.Write(" ");
DisassembleMethodHeaderInternal(module, handle, genericContext);
DisassembleMethodBlock(module, handle, genericContext);
}
public void DisassembleMethodHeader(PEFile module, MethodDefinitionHandle handle)
{
var metadata = module.Metadata;
var genericContext = new GenericContext(handle, module);
// write method header
output.WriteDefinition(".method ", new Metadata.MethodDefinition(module, handle));
DisassembleMethodHeaderInternal(module, handle, metadata, genericContext);
output.WriteReference(module, handle, ".method", isDefinition: true);
output.Write(" ");
DisassembleMethodHeaderInternal(module, handle, genericContext);
}
void DisassembleMethodHeaderInternal(PEFile module, MethodDefinitionHandle handle, MetadataReader metadata, GenericContext genericContext)
void DisassembleMethodHeaderInternal(PEFile module, MethodDefinitionHandle handle, GenericContext genericContext)
{
var metadata = module.Metadata;
WriteMetadataToken(handle, spaceAfter:true);
var methodDefinition = metadata.GetMethodDefinition(handle);
// .method public hidebysig specialname
@ -272,8 +282,9 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -272,8 +282,9 @@ namespace ICSharpCode.Decompiler.Disassembler
}
}
void DisassembleMethodBlock(PEFile module, MethodDefinitionHandle handle, MetadataReader metadata, GenericContext genericContext)
void DisassembleMethodBlock(PEFile module, MethodDefinitionHandle handle, GenericContext genericContext)
{
var metadata = module.Metadata;
var methodDefinition = metadata.GetMethodDefinition(handle);
OpenBlock(defaultCollapsed: isInType);
@ -359,59 +370,61 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -359,59 +370,61 @@ namespace ICSharpCode.Decompiler.Disassembler
output.Write(secdecl.Action.ToString());
break;
}
output.WriteLine(" = {");
output.Indent();
var blob = metadata.GetBlobReader(secdecl.PermissionSet);
if ((char)blob.ReadByte() != '.') {
blob.Reset();
WriteXmlSecurityDeclaration(blob.ReadUTF8(blob.RemainingBytes));
if (AssemblyResolver == null) {
output.Write(" = ");
WriteBlob(secdecl.PermissionSet, metadata);
} else {
string currentAssemblyName = null;
string currentFullAssemblyName = null;
if (metadata.IsAssembly) {
currentAssemblyName = metadata.GetString(metadata.GetAssemblyDefinition().Name);
currentFullAssemblyName = metadata.GetFullAssemblyName();
}
int count = blob.ReadCompressedInteger();
for (int i = 0; i < count; i++) {
var typeName = blob.ReadSerializedString();
string[] nameParts = typeName.Split(new[] { ", " }, StringSplitOptions.None);
if (nameParts.Length < 2 || nameParts[1] == currentAssemblyName) {
output.Write("class ");
output.Write(DisassemblerHelpers.Escape(typeName + ", " + currentFullAssemblyName));
} else {
string[] typeNameParts = typeName.Split(new[] { ", " }, StringSplitOptions.None);
if (typeNameParts.Length < 2)
throw new NotImplementedException();
output.Write('[');
output.Write(typeNameParts[1]);
output.Write(']');
output.WriteReference(typeNameParts[0], null); // TODO : hyperlink!
output.WriteLine(" = {");
output.Indent();
var blob = metadata.GetBlobReader(secdecl.PermissionSet);
if ((char)blob.ReadByte() != '.') {
blob.Reset();
WriteXmlSecurityDeclaration(blob.ReadUTF8(blob.RemainingBytes));
} else {
string currentAssemblyName = null;
string currentFullAssemblyName = null;
if (metadata.IsAssembly) {
currentAssemblyName = metadata.GetString(metadata.GetAssemblyDefinition().Name);
currentFullAssemblyName = metadata.GetFullAssemblyName();
}
output.Write(" = {");
blob.ReadCompressedInteger(); // ?
// The specification seems to be incorrect here, so I'm using the logic from Cecil instead.
int argCount = blob.ReadCompressedInteger();
if (argCount > 0) {
output.WriteLine();
output.Indent();
for (int j = 0; j < argCount; j++) {
WriteSecurityDeclarationArgument(module, ref blob);
int count = blob.ReadCompressedInteger();
for (int i = 0; i < count; i++) {
var typeName = blob.ReadSerializedString();
string[] nameParts = typeName.Split(new[] { ", " }, StringSplitOptions.None);
if (nameParts.Length < 2 || nameParts[1] == currentAssemblyName) {
output.Write("class ");
output.Write(DisassemblerHelpers.Escape(typeName + ", " + currentFullAssemblyName));
} else {
output.Write('[');
output.Write(nameParts[1]);
output.Write(']');
output.Write(nameParts[0]);
}
output.Write(" = {");
blob.ReadCompressedInteger(); // ?
// The specification seems to be incorrect here, so I'm using the logic from Cecil instead.
int argCount = blob.ReadCompressedInteger();
if (argCount > 0) {
output.WriteLine();
output.Indent();
for (int j = 0; j < argCount; j++) {
WriteSecurityDeclarationArgument(module, ref blob);
output.WriteLine();
}
output.Unindent();
}
output.Write('}');
output.Unindent();
if (i + 1 < count)
output.Write(',');
output.WriteLine();
}
output.Write('}');
if (i + 1 < count)
output.Write(',');
output.WriteLine();
}
output.Unindent();
output.WriteLine("}");
}
output.Unindent();
output.WriteLine("}");
}
}
@ -481,7 +494,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -481,7 +494,7 @@ namespace ICSharpCode.Decompiler.Disassembler
}
}
PrimitiveSerializationTypeCode ResolveEnumUnderlyingType(string typeName, PEFile module, out Metadata.TypeDefinition typeDefinition)
PrimitiveSerializationTypeCode ResolveEnumUnderlyingType(string typeName, PEFile module, out (PEFile Module, EntityHandle Handle) typeDefinition)
{
typeDefinition = default;
@ -522,21 +535,21 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -522,21 +535,21 @@ namespace ICSharpCode.Decompiler.Disassembler
PEFile containingModule = null;
// if we deal with an assembly-qualified name, resolve the assembly
if (nameParts.Length == 2)
containingModule = module.AssemblyResolver.Resolve(AssemblyNameReference.Parse(nameParts[1]));
containingModule = AssemblyResolver.Resolve(AssemblyNameReference.Parse(nameParts[1]));
if (containingModule != null) {
// try to find the type in the assembly
var handle = FindType(containingModule, typeNameParts);
var metadata = containingModule.Metadata;
if (handle.IsNil || !handle.IsEnum(metadata, out var typeCode))
throw new NotSupportedException();
typeDefinition = new Metadata.TypeDefinition(containingModule, handle);
typeDefinition = (containingModule, handle);
return (PrimitiveSerializationTypeCode)typeCode;
} else {
// just fully-qualified name, try current assembly
var handle = FindType(module, typeNameParts);
if (handle.IsNil) {
// otherwise try mscorlib
var mscorlib = module.AssemblyResolver.Resolve(AssemblyNameReference.Parse("mscorlib"));
var mscorlib = AssemblyResolver.Resolve(AssemblyNameReference.Parse("mscorlib"));
handle = FindType(mscorlib, typeNameParts);
if (handle.IsNil)
throw new NotImplementedException();
@ -545,7 +558,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -545,7 +558,7 @@ namespace ICSharpCode.Decompiler.Disassembler
var metadata = module.Metadata;
if (handle.IsNil || !handle.IsEnum(metadata, out var typeCode))
throw new NotSupportedException();
typeDefinition = new Metadata.TypeDefinition(module, handle);
typeDefinition = (module, handle);
return (PrimitiveSerializationTypeCode)typeCode;
}
}
@ -625,14 +638,14 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -625,14 +638,14 @@ namespace ICSharpCode.Decompiler.Disassembler
}
var typeInfo = ReadArgumentType(ref blob);
var typeCode = typeInfo.TypeCode;
var typeDefinition = default(Metadata.TypeDefinition);
var typeDefinition = default((PEFile Module, EntityHandle Handle));
if (typeInfo.Kind == TypeKind.Enum) {
typeCode = ResolveEnumUnderlyingType(typeInfo.TypeName, module, out typeDefinition);
}
var name = blob.ReadSerializedString();
object value = ReadArgumentValue(ref blob, typeCode, typeInfo.Kind, typeInfo.IsArray, typeInfo.TypeName);
WriteTypeInfo(typeInfo.TypeCode, typeInfo.Kind, typeInfo.IsArray, typeInfo.TypeName, typeDefinition, module);
WriteTypeInfo(module, typeInfo.TypeCode, typeInfo.Kind, typeInfo.IsArray, typeInfo.TypeName, typeDefinition.Module, typeDefinition.Handle);
output.Write(' ');
output.Write(DisassemblerHelpers.Escape(name));
@ -645,7 +658,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -645,7 +658,7 @@ namespace ICSharpCode.Decompiler.Disassembler
if (typeInfo.Kind == TypeKind.Enum || typeInfo.Kind == TypeKind.Primitive) {
WritePrimitiveTypeCode(typeCode);
} else {
WriteTypeInfo(typeCode, typeInfo.Kind, typeInfo.IsArray, typeInfo.TypeName, typeDefinition, module);
WriteTypeInfo(module, typeInfo.TypeCode, typeInfo.Kind, typeInfo.IsArray, typeInfo.TypeName, typeDefinition.Module, typeDefinition.Handle);
}
output.Write('(');
DisassemblerHelpers.WriteOperand(output, value);
@ -653,7 +666,8 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -653,7 +666,8 @@ namespace ICSharpCode.Decompiler.Disassembler
}
}
private void WriteTypeInfo(PrimitiveSerializationTypeCode typeCode, TypeKind kind, bool isArray, string typeName, Metadata.TypeDefinition type, PEFile currentModule)
private void WriteTypeInfo(PEFile currentModule, PrimitiveSerializationTypeCode typeCode, TypeKind kind,
bool isArray, string typeName, PEFile referencedModule, EntityHandle type)
{
switch (kind) {
case TypeKind.Primitive:
@ -669,12 +683,11 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -669,12 +683,11 @@ namespace ICSharpCode.Decompiler.Disassembler
output.Write(DisassemblerHelpers.Escape(typeName));
break;
}
var referencedModule = type.Module;
if (referencedModule != currentModule) {
output.Write('[');
output.Write(referencedModule.Name);
output.Write(']');
output.WriteReference(type.Handle.GetFullTypeName(type.Module.Metadata).ToString(), type);
output.WriteReference(referencedModule, type, type.GetFullTypeName(referencedModule.Metadata).ToString());
} else {
output.Write(DisassemblerHelpers.Escape(typeName));
}
@ -932,7 +945,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -932,7 +945,7 @@ namespace ICSharpCode.Decompiler.Disassembler
if (!md.IsNil) {
WriteMarshalInfo(metadata.GetBlobReader(md));
}
output.WriteDefinition(DisassemblerHelpers.Escape(metadata.GetString(p.Name)), p);
output.WriteLocalReference(DisassemblerHelpers.Escape(metadata.GetString(p.Name)), p, isDefinition: true);
} else {
signature.ParameterTypes[i](ILNameSyntax.Signature);
output.Write(" ''");
@ -1019,11 +1032,11 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -1019,11 +1032,11 @@ namespace ICSharpCode.Decompiler.Disassembler
{ FieldAttributes.NotSerialized, "notserialized" },
};
public void DisassembleField(Metadata.FieldDefinition field)
public void DisassembleField(PEFile module, FieldDefinitionHandle field)
{
var metadata = field.Module.Metadata;
var fieldDefinition = metadata.GetFieldDefinition(field.Handle);
output.WriteDefinition(".field ", field);
var metadata = module.Metadata;
var fieldDefinition = metadata.GetFieldDefinition(field);
output.WriteReference(module, field, ".field ", isDefinition: true);
int offset = fieldDefinition.GetOffset();
if (offset > -1) {
output.Write("[" + offset + "] ");
@ -1032,7 +1045,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -1032,7 +1045,7 @@ namespace ICSharpCode.Decompiler.Disassembler
const FieldAttributes hasXAttributes = FieldAttributes.HasDefault | FieldAttributes.HasFieldMarshal | FieldAttributes.HasFieldRVA;
WriteFlags(fieldDefinition.Attributes & ~(FieldAttributes.FieldAccessMask | hasXAttributes), fieldAttributes);
var signature = fieldDefinition.DecodeSignature(new DisassemblerSignatureProvider(field.Module, output), new GenericContext(fieldDefinition.GetDeclaringType(), field.Module));
var signature = fieldDefinition.DecodeSignature(new DisassemblerSignatureProvider(module, output), new GenericContext(fieldDefinition.GetDeclaringType(), module));
var marshallingDescriptor = fieldDefinition.GetMarshallingDescriptor();
if (!marshallingDescriptor.IsNil) {
@ -1056,7 +1069,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -1056,7 +1069,7 @@ namespace ICSharpCode.Decompiler.Disassembler
var attributes = fieldDefinition.GetCustomAttributes();
if (attributes.Count > 0) {
output.MarkFoldStart();
WriteAttributes(field.Module, fieldDefinition.GetCustomAttributes());
WriteAttributes(module, fieldDefinition.GetCustomAttributes());
output.MarkFoldEnd();
}
}
@ -1069,15 +1082,16 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -1069,15 +1082,16 @@ namespace ICSharpCode.Decompiler.Disassembler
{ PropertyAttributes.HasDefault, "hasdefault" },
};
public void DisassembleProperty(Metadata.PropertyDefinition property)
public void DisassembleProperty(PEFile module, PropertyDefinitionHandle property)
{
var metadata = property.Module.Metadata;
var propertyDefinition = metadata.GetPropertyDefinition(property.Handle);
output.WriteDefinition(".property ", property);
var metadata = module.Metadata;
var propertyDefinition = metadata.GetPropertyDefinition(property);
output.WriteReference(module, property, ".property", true);
output.Write(" ");
WriteFlags(propertyDefinition.Attributes, propertyAttributes);
var accessors = propertyDefinition.GetAccessors();
var declaringType = metadata.GetMethodDefinition(accessors.GetAny()).GetDeclaringType();
var signature = propertyDefinition.DecodeSignature(new DisassemblerSignatureProvider(property.Module, output), new GenericContext(declaringType, property.Module));
var signature = propertyDefinition.DecodeSignature(new DisassemblerSignatureProvider(module, output), new GenericContext(declaringType, module));
if (signature.Header.IsInstance)
output.Write("instance ");
@ -1098,23 +1112,23 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -1098,23 +1112,23 @@ namespace ICSharpCode.Decompiler.Disassembler
output.Write(')');
OpenBlock(false);
WriteAttributes(property.Module, propertyDefinition.GetCustomAttributes());
WriteNestedMethod(".get", new Metadata.MethodDefinition(property.Module, accessors.Getter));
WriteNestedMethod(".set", new Metadata.MethodDefinition(property.Module, accessors.Setter));
WriteAttributes(module, propertyDefinition.GetCustomAttributes());
WriteNestedMethod(".get", module, accessors.Getter);
WriteNestedMethod(".set", module, accessors.Setter);
/*foreach (var method in property.OtherMethods) {
WriteNestedMethod(".other", method);
}*/
CloseBlock();
}
void WriteNestedMethod(string keyword, Metadata.MethodDefinition method)
void WriteNestedMethod(string keyword, PEFile module, MethodDefinitionHandle method)
{
if (method.IsNil)
return;
output.Write(keyword);
output.Write(' ');
((EntityHandle)method.Handle).WriteTo(method.Module, output, GenericContext.Empty);
((EntityHandle)method).WriteTo(module, output, GenericContext.Empty);
output.WriteLine();
}
#endregion
@ -1127,28 +1141,28 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -1127,28 +1141,28 @@ namespace ICSharpCode.Decompiler.Disassembler
public void DisassembleEvent(PEFile module, EventDefinitionHandle handle)
{
var metadata = module.Metadata;
var eventDefinition = metadata.GetEventDefinition(handle);
var eventDefinition = module.Metadata.GetEventDefinition(handle);
var accessors = eventDefinition.GetAccessors();
TypeDefinitionHandle declaringType;
if (!accessors.Adder.IsNil) {
declaringType = metadata.GetMethodDefinition(accessors.Adder).GetDeclaringType();
declaringType = module.Metadata.GetMethodDefinition(accessors.Adder).GetDeclaringType();
} else if (!accessors.Remover.IsNil) {
declaringType = metadata.GetMethodDefinition(accessors.Remover).GetDeclaringType();
declaringType = module.Metadata.GetMethodDefinition(accessors.Remover).GetDeclaringType();
} else {
declaringType = metadata.GetMethodDefinition(accessors.Raiser).GetDeclaringType();
declaringType = module.Metadata.GetMethodDefinition(accessors.Raiser).GetDeclaringType();
}
output.WriteDefinition(".event ", new Metadata.EventDefinition(module, handle));
output.WriteReference(module, handle, ".event", true);
output.Write(" ");
WriteFlags(eventDefinition.Attributes, eventAttributes);
var signature = eventDefinition.DecodeSignature(metadata, new DisassemblerSignatureProvider(module, output), new GenericContext(declaringType, module));
var signature = eventDefinition.DecodeSignature(module.Metadata, new DisassemblerSignatureProvider(module, output), new GenericContext(declaringType, module));
signature(ILNameSyntax.TypeName);
output.Write(' ');
output.Write(DisassemblerHelpers.Escape(metadata.GetString(eventDefinition.Name)));
output.Write(DisassemblerHelpers.Escape(module.Metadata.GetString(eventDefinition.Name)));
OpenBlock(false);
WriteAttributes(module, eventDefinition.GetCustomAttributes());
WriteNestedMethod(".addon", new Metadata.MethodDefinition(module, accessors.Adder));
WriteNestedMethod(".removeon", new Metadata.MethodDefinition(module, accessors.Remover));
WriteNestedMethod(".fire", new Metadata.MethodDefinition(module, accessors.Raiser));
WriteNestedMethod(".addon", module, accessors.Adder);
WriteNestedMethod(".removeon", module, accessors.Remover);
WriteNestedMethod(".fire", module, accessors.Raiser);
/*foreach (var method in ev.OtherMethods) {
WriteNestedMethod(".other", method);
}*/
@ -1191,12 +1205,11 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -1191,12 +1205,11 @@ namespace ICSharpCode.Decompiler.Disassembler
{ TypeAttributes.HasSecurity, null },
};
public void DisassembleType(Metadata.TypeDefinition type)
public void DisassembleType(PEFile module, TypeDefinitionHandle type)
{
var metadata = type.Module.Metadata;
var typeDefinition = metadata.GetTypeDefinition(type.Handle);
output.WriteDefinition(".class ", type);
var typeDefinition = module.Metadata.GetTypeDefinition(type);
output.WriteReference(module, type, ".class", true);
output.Write(" ");
if ((typeDefinition.Attributes & TypeAttributes.ClassSemanticsMask) == TypeAttributes.Interface)
output.Write("interface ");
WriteEnum(typeDefinition.Attributes & TypeAttributes.VisibilityMask, typeVisibility);
@ -1205,15 +1218,16 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -1205,15 +1218,16 @@ namespace ICSharpCode.Decompiler.Disassembler
const TypeAttributes masks = TypeAttributes.ClassSemanticsMask | TypeAttributes.VisibilityMask | TypeAttributes.LayoutMask | TypeAttributes.StringFormatMask;
WriteFlags(typeDefinition.Attributes & ~masks, typeAttributes);
output.Write(typeDefinition.GetDeclaringType().IsNil ? typeDefinition.GetFullTypeName(metadata).ToILNameString() : DisassemblerHelpers.Escape(metadata.GetString(typeDefinition.Name)));
WriteTypeParameters(output, type.Module, new GenericContext(type), typeDefinition.GetGenericParameters());
output.Write(typeDefinition.GetDeclaringType().IsNil ? typeDefinition.GetFullTypeName(module.Metadata).ToILNameString() : DisassemblerHelpers.Escape(module.Metadata.GetString(typeDefinition.Name)));
GenericContext genericContext = new GenericContext(type, module);
WriteTypeParameters(output, module, genericContext, typeDefinition.GetGenericParameters());
output.MarkFoldStart(defaultCollapsed: !ExpandMemberDefinitions && isInType);
output.WriteLine();
if (!typeDefinition.BaseType.IsNil) {
output.Indent();
output.Write("extends ");
typeDefinition.BaseType.WriteTo(type.Module, output, new GenericContext(type), ILNameSyntax.TypeName);
typeDefinition.BaseType.WriteTo(module, output, genericContext, ILNameSyntax.TypeName);
output.WriteLine();
output.Unindent();
}
@ -1229,9 +1243,9 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -1229,9 +1243,9 @@ namespace ICSharpCode.Decompiler.Disassembler
else
output.Write(" ");
first = false;
var iface = metadata.GetInterfaceImplementation(i);
WriteAttributes(type.Module, iface.GetCustomAttributes());
iface.Interface.WriteTo(type.Module, output, new GenericContext(type), ILNameSyntax.TypeName);
var iface = module.Metadata.GetInterfaceImplementation(i);
WriteAttributes(module, iface.GetCustomAttributes());
iface.Interface.WriteTo(module, output, genericContext, ILNameSyntax.TypeName);
}
output.WriteLine();
output.Unindent();
@ -1241,8 +1255,8 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -1241,8 +1255,8 @@ namespace ICSharpCode.Decompiler.Disassembler
output.Indent();
bool oldIsInType = isInType;
isInType = true;
WriteAttributes(type.Module, typeDefinition.GetCustomAttributes());
WriteSecurityDeclarations(type.Module, typeDefinition.GetDeclarativeSecurityAttributes());
WriteAttributes(module, typeDefinition.GetCustomAttributes());
WriteSecurityDeclarations(module, typeDefinition.GetDeclarativeSecurityAttributes());
var layout = typeDefinition.GetLayout();
if (!layout.IsDefault) {
output.WriteLine(".pack {0}", layout.PackingSize);
@ -1254,7 +1268,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -1254,7 +1268,7 @@ namespace ICSharpCode.Decompiler.Disassembler
output.WriteLine("// Nested Types");
foreach (var nestedType in nestedTypes) {
cancellationToken.ThrowIfCancellationRequested();
DisassembleType(new Metadata.TypeDefinition(type.Module, nestedType));
DisassembleType(module, nestedType);
output.WriteLine();
}
output.WriteLine();
@ -1264,7 +1278,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -1264,7 +1278,7 @@ namespace ICSharpCode.Decompiler.Disassembler
output.WriteLine("// Fields");
foreach (var field in fields) {
cancellationToken.ThrowIfCancellationRequested();
DisassembleField(new Metadata.FieldDefinition(type.Module, field));
DisassembleField(module, field);
}
output.WriteLine();
}
@ -1273,7 +1287,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -1273,7 +1287,7 @@ namespace ICSharpCode.Decompiler.Disassembler
output.WriteLine("// Methods");
foreach (var m in methods) {
cancellationToken.ThrowIfCancellationRequested();
DisassembleMethod(type.Module, m);
DisassembleMethod(module, m);
output.WriteLine();
}
}
@ -1282,7 +1296,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -1282,7 +1296,7 @@ namespace ICSharpCode.Decompiler.Disassembler
output.WriteLine("// Events");
foreach (var ev in events) {
cancellationToken.ThrowIfCancellationRequested();
DisassembleEvent(type.Module, ev);
DisassembleEvent(module, ev);
output.WriteLine();
}
output.WriteLine();
@ -1292,11 +1306,11 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -1292,11 +1306,11 @@ namespace ICSharpCode.Decompiler.Disassembler
output.WriteLine("// Properties");
foreach (var prop in properties) {
cancellationToken.ThrowIfCancellationRequested();
DisassembleProperty(new Metadata.PropertyDefinition(type.Module, prop));
DisassembleProperty(module, prop);
}
output.WriteLine();
}
CloseBlock("end of class " + (!typeDefinition.GetDeclaringType().IsNil ? metadata.GetString(typeDefinition.Name) : typeDefinition.GetFullTypeName(metadata).ToString()));
CloseBlock("end of class " + (!typeDefinition.GetDeclaringType().IsNil ? module.Metadata.GetString(typeDefinition.Name) : typeDefinition.GetFullTypeName(module.Metadata).ToString()));
isInType = oldIsInType;
}
@ -1348,27 +1362,27 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -1348,27 +1362,27 @@ namespace ICSharpCode.Decompiler.Disassembler
output.Write(".custom ");
var attr = metadata.GetCustomAttribute(a);
attr.Constructor.WriteTo(module, output, GenericContext.Empty);
byte[] blob = metadata.GetBlobBytes(attr.Value);
if (blob.Length > 0) {
if (!attr.Value.IsNil) {
output.Write(" = ");
WriteBlob(blob);
WriteBlob(attr.Value, metadata);
}
output.WriteLine();
}
}
void WriteBlob(byte[] blob)
void WriteBlob(BlobHandle blob, MetadataReader metadata)
{
var reader = metadata.GetBlobReader(blob);
output.Write("(");
output.Indent();
for (int i = 0; i < blob.Length; i++) {
if (i % 16 == 0 && i < blob.Length - 1) {
for (int i = 0; i < reader.Length; i++) {
if (i % 16 == 0 && i < reader.Length - 1) {
output.WriteLine();
} else {
output.Write(' ');
}
output.Write(blob[i].ToString("x2"));
output.Write(reader.ReadByte().ToString("x2"));
}
output.WriteLine();
@ -1449,7 +1463,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -1449,7 +1463,7 @@ namespace ICSharpCode.Decompiler.Disassembler
}
#endregion
public void DisassembleNamespace(string nameSpace, IEnumerable<Metadata.TypeDefinition> types)
public void DisassembleNamespace(string nameSpace, PEFile module, IEnumerable<TypeDefinitionHandle> types)
{
if (!string.IsNullOrEmpty(nameSpace)) {
output.Write(".namespace " + DisassemblerHelpers.Escape(nameSpace));
@ -1459,7 +1473,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -1459,7 +1473,7 @@ namespace ICSharpCode.Decompiler.Disassembler
isInType = true;
foreach (var td in types) {
cancellationToken.ThrowIfCancellationRequested();
DisassembleType(td);
DisassembleType(module, td);
output.WriteLine();
}
if (!string.IsNullOrEmpty(nameSpace)) {
@ -1480,10 +1494,9 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -1480,10 +1494,9 @@ namespace ICSharpCode.Decompiler.Disassembler
OpenBlock(false);
WriteAttributes(module, asm.GetCustomAttributes());
WriteSecurityDeclarations(module, asm.GetDeclarativeSecurityAttributes());
var publicKey = metadata.GetBlobBytes(asm.PublicKey);
if (publicKey.Length > 0) {
if (!asm.PublicKey.IsNil) {
output.Write(".publickey = ");
WriteBlob(publicKey);
WriteBlob(asm.PublicKey, metadata);
output.WriteLine();
}
if (asm.HashAlgorithm != AssemblyHashAlgorithm.None) {
@ -1514,7 +1527,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -1514,7 +1527,7 @@ namespace ICSharpCode.Decompiler.Disassembler
OpenBlock(false);
if (!aref.PublicKeyOrToken.IsNil) {
output.Write(".publickeytoken = ");
WriteBlob(metadata.GetBlobBytes(aref.PublicKeyOrToken));
WriteBlob(aref.PublicKeyOrToken, metadata);
output.WriteLine();
}
if (aref.Version != null) {
@ -1590,8 +1603,8 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -1590,8 +1603,8 @@ namespace ICSharpCode.Decompiler.Disassembler
public void WriteModuleContents(PEFile module)
{
foreach (var handle in module.TopLevelTypeDefinitions) {
DisassembleType(handle);
foreach (var handle in module.Metadata.GetTopLevelTypeDefinitions()) {
DisassembleType(module, handle);
output.WriteLine();
}
}

591
ICSharpCode.Decompiler/Documentation/XmlDocKeyProvider.cs

@ -18,14 +18,10 @@ @@ -18,14 +18,10 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.Metadata;
using SRM = System.Reflection.Metadata;
using ICSharpCode.Decompiler.Util;
using System.Collections.Immutable;
using ICSharpCode.Decompiler.TypeSystem.Implementation;
namespace ICSharpCode.Decompiler.Documentation
{
@ -35,324 +31,361 @@ namespace ICSharpCode.Decompiler.Documentation @@ -35,324 +31,361 @@ namespace ICSharpCode.Decompiler.Documentation
public static class XmlDocKeyProvider
{
#region GetKey
public static string GetKey(Entity entity)
{
return GetKey(entity.Module.Metadata, entity.Handle);
}
public static string GetKey(SRM.MetadataReader metadata, SRM.EntityHandle member)
/// <summary>
/// Gets the ID string (C# 4.0 spec, §A.3.1) for the specified entity.
/// </summary>
public static string GetKey(IEntity entity)
{
StringBuilder b = new StringBuilder();
void AppendTypeName(SRM.EntityHandle type)
{
switch (type.Kind) {
case SRM.HandleKind.TypeDefinition:
b.Append("T:");
b.Append(((SRM.TypeDefinitionHandle)type).GetFullTypeName(metadata));
break;
case SRM.HandleKind.TypeReference:
b.Append("T:");
b.Append(((SRM.TypeReferenceHandle)type).GetFullTypeName(metadata));
break;
default:
throw new NotImplementedException();
/*case SRM.HandleKind.TypeSpecification:
b.Append("T:");
var typeSpec = metadata.GetTypeSpecification((SRM.TypeSpecificationHandle)type);
b.Append(typeSpec.DecodeSignature(new DocumentationKeySignatureTypeProvider(), default(Unit)));
break;*/
}
switch (entity.SymbolKind) {
case SymbolKind.TypeDefinition:
b.Append("T:");
AppendTypeName(b, (ITypeDefinition)entity, false);
return b.ToString();
case SymbolKind.Field:
b.Append("F:");
break;
case SymbolKind.Property:
case SymbolKind.Indexer:
b.Append("P:");
break;
case SymbolKind.Event:
b.Append("E:");
break;
default:
b.Append("M:");
break;
}
void AppendSignature(SRM.MethodSignature<string> signature, bool printExplicitReturnType = false)
{
if (signature.GenericParameterCount > 0) {
b.Append("``");
b.Append(signature.GenericParameterCount);
}
IMember member = (IMember)entity;
if (member.DeclaringType != null) {
AppendTypeName(b, member.DeclaringType, false);
b.Append('.');
}
if (member.IsExplicitInterfaceImplementation && member.Name.IndexOf('.') < 0 && member.ExplicitlyImplementedInterfaceMembers.Count() == 1) {
AppendTypeName(b, member.ExplicitlyImplementedInterfaceMembers.First().DeclaringType, true);
b.Append('#');
}
b.Append(member.Name.Replace('.', '#'));
IMethod method = member as IMethod;
if (method != null && method.TypeParameters.Count > 0) {
b.Append("``");
b.Append(method.TypeParameters.Count);
}
IParameterizedMember parameterizedMember = member as IParameterizedMember;
if (parameterizedMember != null && parameterizedMember.Parameters.Count > 0) {
b.Append('(');
for (int i = 0; i < signature.ParameterTypes.Length; i++) {
if (i > 0)
b.Append(',');
b.Append(signature.ParameterTypes[i]);
var parameters = parameterizedMember.Parameters;
for (int i = 0; i < parameters.Count; i++) {
if (i > 0) b.Append(',');
AppendTypeName(b, parameters[i].Type, false);
}
b.Append(')');
if (printExplicitReturnType) {
b.Append('~');
b.Append(signature.ReturnType);
}
}
if (member.SymbolKind == SymbolKind.Operator && (member.Name == "op_Implicit" || member.Name == "op_Explicit")) {
b.Append('~');
AppendTypeName(b, member.ReturnType, false);
}
return b.ToString();
}
#endregion
switch (member.Kind) {
case SRM.HandleKind.TypeDefinition:
case SRM.HandleKind.TypeReference:
case SRM.HandleKind.TypeSpecification:
b.Append("T:");
AppendTypeName(member);
break;
case SRM.HandleKind.FieldDefinition:
b.Append("F:");
var field = metadata.GetFieldDefinition((SRM.FieldDefinitionHandle)member);
AppendTypeName(field.GetDeclaringType());
b.Append('.');
b.Append(metadata.GetString(field.Name).Replace('.', '#'));
#region GetTypeName
public static string GetTypeName(IType type)
{
if (type == null)
throw new ArgumentNullException("type");
StringBuilder b = new StringBuilder();
AppendTypeName(b, type, false);
return b.ToString();
}
static void AppendTypeName(StringBuilder b, IType type, bool explicitInterfaceImpl)
{
switch (type.Kind) {
case TypeKind.Dynamic:
b.Append(explicitInterfaceImpl ? "System#Object" : "System.Object");
break;
case SRM.HandleKind.PropertyDefinition: {
b.Append("P:");
var property = metadata.GetPropertyDefinition((SRM.PropertyDefinitionHandle)member);
var accessors = property.GetAccessors();
SRM.TypeDefinitionHandle declaringType;
if (!accessors.Getter.IsNil) {
declaringType = metadata.GetMethodDefinition(accessors.Getter).GetDeclaringType();
case TypeKind.TypeParameter:
ITypeParameter tp = (ITypeParameter)type;
if (explicitInterfaceImpl) {
b.Append(tp.Name);
} else {
declaringType = metadata.GetMethodDefinition(accessors.Setter).GetDeclaringType();
b.Append('`');
if (tp.OwnerType == SymbolKind.Method)
b.Append('`');
b.Append(tp.Index);
}
AppendTypeName(declaringType);
b.Append('.');
b.Append(metadata.GetString(property.Name).Replace('.', '#'));
AppendSignature(property.DecodeSignature(new DocumentationKeySignatureTypeProvider(), default(Unit)));
break;
}
case SRM.HandleKind.MethodDefinition:
b.Append("M:");
var method = metadata.GetMethodDefinition((SRM.MethodDefinitionHandle)member);
AppendTypeName(method.GetDeclaringType());
b.Append('.');
var methodName = metadata.GetString(method.Name);
b.Append(metadata.GetString(method.Name).Replace('.', '#'));
AppendSignature(method.DecodeSignature(new DocumentationKeySignatureTypeProvider(), default(Unit)), methodName == "op_Implicit" || methodName == "op_Explicit");
case TypeKind.Array:
ArrayType array = (ArrayType)type;
AppendTypeName(b, array.ElementType, explicitInterfaceImpl);
b.Append('[');
if (array.Dimensions > 1) {
for (int i = 0; i < array.Dimensions; i++) {
if (i > 0)
b.Append(explicitInterfaceImpl ? '@' : ',');
if (!explicitInterfaceImpl)
b.Append("0:");
}
}
b.Append(']');
break;
case SRM.HandleKind.EventDefinition: {
b.Append("E:");
var @event = metadata.GetEventDefinition((SRM.EventDefinitionHandle)member);
var accessors = @event.GetAccessors();
SRM.TypeDefinitionHandle declaringType;
if (!accessors.Adder.IsNil) {
declaringType = metadata.GetMethodDefinition(accessors.Adder).GetDeclaringType();
} else if (!accessors.Remover.IsNil) {
declaringType = metadata.GetMethodDefinition(accessors.Remover).GetDeclaringType();
case TypeKind.Pointer:
AppendTypeName(b, ((PointerType)type).ElementType, explicitInterfaceImpl);
b.Append('*');
break;
case TypeKind.ByReference:
AppendTypeName(b, ((ByReferenceType)type).ElementType, explicitInterfaceImpl);
b.Append('@');
break;
default:
IType declType = type.DeclaringType;
if (declType != null) {
AppendTypeName(b, declType, explicitInterfaceImpl);
b.Append(explicitInterfaceImpl ? '#' : '.');
b.Append(type.Name);
AppendTypeParameters(b, type, declType.TypeParameterCount, explicitInterfaceImpl);
} else {
declaringType = metadata.GetMethodDefinition(accessors.Raiser).GetDeclaringType();
if (explicitInterfaceImpl)
b.Append(type.FullName.Replace('.', '#'));
else
b.Append(type.FullName);
AppendTypeParameters(b, type, 0, explicitInterfaceImpl);
}
AppendTypeName(declaringType);
b.Append('.');
b.Append(metadata.GetString(@event.Name).Replace('.', '#'));
break;
}
default:
throw new NotImplementedException();
}
return b.ToString();
}
public sealed class DocumentationKeySignatureTypeProvider : SRM.ISignatureTypeProvider<string, Unit>
static void AppendTypeParameters(StringBuilder b, IType type, int outerTypeParameterCount, bool explicitInterfaceImpl)
{
public string GetArrayType(string elementType, SRM.ArrayShape shape)
{
string shapeString = "";
for (int i = 0; i < shape.Rank; i++) {
if (i > 0)
shapeString += ',';
int? lowerBound = i < shape.LowerBounds.Length ? (int?)shape.LowerBounds[i] : null;
int? size = i < shape.Sizes.Length ? (int?)shape.Sizes[i] : null;
if (lowerBound != null || size != null) {
shapeString += lowerBound.ToString();
shapeString += ':';
shapeString += (lowerBound + size - 1).ToString();
int tpc = type.TypeParameterCount - outerTypeParameterCount;
if (tpc > 0) {
ParameterizedType pt = type as ParameterizedType;
if (pt != null) {
b.Append('{');
var ta = pt.TypeArguments;
for (int i = outerTypeParameterCount; i < ta.Count; i++) {
if (i > outerTypeParameterCount)
b.Append(explicitInterfaceImpl ? '@' : ',');
AppendTypeName(b, ta[i], explicitInterfaceImpl);
}
b.Append('}');
} else {
b.Append('`');
b.Append(tpc);
}
return elementType + "[" + shapeString + "]";
}
public string GetByReferenceType(string elementType)
{
return elementType + '@';
}
public string GetFunctionPointerType(SRM.MethodSignature<string> signature)
{
return "";
}
public string GetGenericInstantiation(string genericType, ImmutableArray<string> typeArguments)
{
string arguments = "";
for (int i = 0; i < typeArguments.Length; i++) {
if (i > 0)
arguments += ',';
arguments += typeArguments[i];
}
return genericType + "{" + arguments + "}";
}
public string GetGenericMethodParameter(Unit genericContext, int index)
{
return "``" + index;
}
public string GetGenericTypeParameter(Unit genericContext, int index)
{
return "`" + index;
}
public string GetModifiedType(string modifier, string unmodifiedType, bool isRequired)
{
return unmodifiedType;
}
public string GetPinnedType(string elementType)
{
return elementType;
}
public string GetPointerType(string elementType)
{
return elementType + '*';
}
public string GetPrimitiveType(SRM.PrimitiveTypeCode typeCode)
{
return $"System.{typeCode}";
}
public string GetSZArrayType(string elementType)
{
return elementType + "[]";
}
public string GetTypeFromDefinition(SRM.MetadataReader reader, SRM.TypeDefinitionHandle handle, byte rawTypeKind)
{
return handle.GetFullTypeName(reader).ToString();
}
public string GetTypeFromReference(SRM.MetadataReader reader, SRM.TypeReferenceHandle handle, byte rawTypeKind)
{
return handle.GetFullTypeName(reader).ToString();
}
}
#endregion
public string GetTypeFromSpecification(SRM.MetadataReader reader, Unit genericContext, SRM.TypeSpecificationHandle handle, byte rawTypeKind)
{
return handle.GetFullTypeName(reader).ToString();
}
#region ParseMemberName
/// <summary>
/// Parse the ID string into a member reference.
/// </summary>
/// <param name="memberIdString">The ID string representing the member (with "M:", "F:", "P:" or "E:" prefix).</param>
/// <returns>A member reference that represents the ID string.</returns>
/// <exception cref="ReflectionNameParseException">The syntax of the ID string is invalid</exception>
/// <remarks>
/// The member reference will look in <see cref="ITypeResolveContext.CurrentAssembly"/> first,
/// and if the member is not found there,
/// it will look in all other assemblies of the compilation.
/// </remarks>
public static IMemberReference ParseMemberIdString(string memberIdString)
{
if (memberIdString == null)
throw new ArgumentNullException("memberIdString");
if (memberIdString.Length < 2 || memberIdString[1] != ':')
throw new ReflectionNameParseException(0, "Missing type tag");
char typeChar = memberIdString[0];
int parenPos = memberIdString.IndexOf('(');
if (parenPos < 0)
parenPos = memberIdString.LastIndexOf('~');
if (parenPos < 0)
parenPos = memberIdString.Length;
int dotPos = memberIdString.LastIndexOf('.', parenPos - 1);
if (dotPos < 0)
throw new ReflectionNameParseException(0, "Could not find '.' separating type name from member name");
string typeName = memberIdString.Substring(0, dotPos);
int pos = 2;
ITypeReference typeReference = ParseTypeName(typeName, ref pos);
if (pos != typeName.Length)
throw new ReflectionNameParseException(pos, "Expected end of type name");
// string memberName = memberIDString.Substring(dotPos + 1, parenPos - (dotPos + 1));
// pos = memberName.LastIndexOf("``");
// if (pos > 0)
// memberName = memberName.Substring(0, pos);
// memberName = memberName.Replace('#', '.');
return new IdStringMemberReference(typeReference, typeChar, memberIdString);
}
#endregion
#region FindMemberByKey
public static Entity FindMemberByKey(PEFile module, string key)
#region ParseTypeName
/// <summary>
/// Parse the ID string type name into a type reference.
/// </summary>
/// <param name="typeName">The ID string representing the type (the "T:" prefix is optional).</param>
/// <returns>A type reference that represents the ID string.</returns>
/// <exception cref="ReflectionNameParseException">The syntax of the ID string is invalid</exception>
/// <remarks>
/// <para>
/// The type reference will look in <see cref="ITypeResolveContext.CurrentAssembly"/> first,
/// and if the type is not found there,
/// it will look in all other assemblies of the compilation.
/// </para>
/// <para>
/// If the type is open (contains type parameters '`0' or '``0'),
/// an <see cref="ITypeResolveContext"/> with the appropriate CurrentTypeDefinition/CurrentMember is required
/// to resolve the reference to the ITypeParameter.
/// </para>
/// </remarks>
public static ITypeReference ParseTypeName(string typeName)
{
if (module == null)
throw new ArgumentNullException(nameof(module));
if (key == null || key.Length < 2 || key[1] != ':')
return default(Entity);
switch (key[0]) {
case 'T':
return FindType(module, key.Substring(2));
case 'F':
return FindMember(module, key, type => module.Metadata.GetTypeDefinition(type.Handle).GetFields().Select(f => new Entity(module, f)));
case 'P':
return FindMember(module, key, type => module.Metadata.GetTypeDefinition(type.Handle).GetProperties().Select(p => new Entity(module, p)));
case 'E':
return FindMember(module, key, type => module.Metadata.GetTypeDefinition(type.Handle).GetEvents().Select(e => new Entity(module, e)));
case 'M':
return FindMember(module, key, type => module.Metadata.GetTypeDefinition(type.Handle).GetMethods().Select(m => new Entity(module, m)));
if (typeName == null)
throw new ArgumentNullException("typeName");
int pos = 0;
if (typeName.StartsWith("T:", StringComparison.Ordinal))
pos = 2;
ITypeReference r = ParseTypeName(typeName, ref pos);
if (pos < typeName.Length)
throw new ReflectionNameParseException(pos, "Expected end of type name");
return r;
}
static bool IsIDStringSpecialCharacter(char c)
{
switch (c) {
case ':':
case '{':
case '}':
case '[':
case ']':
case '(':
case ')':
case '`':
case '*':
case '@':
case ',':
return true;
default:
return default(Entity);
return false;
}
}
static Entity FindMember(PEFile module, string key, Func<TypeDefinition, IEnumerable<Entity>> memberSelector)
static ITypeReference ParseTypeName(string typeName, ref int pos)
{
Debug.WriteLine("Looking for member " + key);
int parenPos = key.IndexOf('(');
int dotPos;
if (parenPos > 0) {
dotPos = key.LastIndexOf('.', parenPos - 1, parenPos);
} else {
dotPos = key.LastIndexOf('.');
}
if (dotPos < 0)
return default(Entity);
TypeDefinition type = FindType(module, key.Substring(2, dotPos - 2));
if (type == null)
return default(Entity);
string shortName;
if (parenPos > 0) {
shortName = key.Substring(dotPos + 1, parenPos - (dotPos + 1));
string reflectionTypeName = typeName;
if (pos == typeName.Length)
throw new ReflectionNameParseException(pos, "Unexpected end");
ITypeReference result;
if (reflectionTypeName[pos] == '`') {
// type parameter reference
pos++;
if (pos == reflectionTypeName.Length)
throw new ReflectionNameParseException(pos, "Unexpected end");
if (reflectionTypeName[pos] == '`') {
// method type parameter reference
pos++;
int index = ReflectionHelper.ReadTypeParameterCount(reflectionTypeName, ref pos);
result = TypeParameterReference.Create(SymbolKind.Method, index);
} else {
// class type parameter reference
int index = ReflectionHelper.ReadTypeParameterCount(reflectionTypeName, ref pos);
result = TypeParameterReference.Create(SymbolKind.TypeDefinition, index);
}
} else {
shortName = key.Substring(dotPos + 1);
// not a type parameter reference: read the actual type name
List<ITypeReference> typeArguments = new List<ITypeReference>();
int typeParameterCount;
string typeNameWithoutSuffix = ReadTypeName(typeName, ref pos, true, out typeParameterCount, typeArguments);
result = new GetPotentiallyNestedClassTypeReference(typeNameWithoutSuffix, typeParameterCount);
while (pos < typeName.Length && typeName[pos] == '.') {
pos++;
string nestedTypeName = ReadTypeName(typeName, ref pos, false, out typeParameterCount, typeArguments);
result = new NestedTypeReference(result, nestedTypeName, typeParameterCount);
}
if (typeArguments.Count > 0) {
result = new ParameterizedTypeReference(result, typeArguments);
}
}
var metadata = module.Metadata;
Debug.WriteLine("Searching in type {0} for {1}", type.Handle.GetFullTypeName(metadata), shortName);
Entity shortNameMatch = default(Entity);
foreach (var member in memberSelector(type)) {
string memberKey = GetKey(member);
Debug.WriteLine(memberKey);
if (memberKey == key)
return member;
string name;
switch (member.Handle.Kind) {
case SRM.HandleKind.MethodDefinition:
name = metadata.GetString(metadata.GetMethodDefinition((SRM.MethodDefinitionHandle)member.Handle).Name);
break;
case SRM.HandleKind.FieldDefinition:
name = metadata.GetString(metadata.GetFieldDefinition((SRM.FieldDefinitionHandle)member.Handle).Name);
while (pos < typeName.Length) {
switch (typeName[pos]) {
case '[':
int dimensions = 1;
do {
pos++;
if (pos == typeName.Length)
throw new ReflectionNameParseException(pos, "Unexpected end");
if (typeName[pos] == ',')
dimensions++;
} while (typeName[pos] != ']');
result = new ArrayTypeReference(result, dimensions);
break;
case SRM.HandleKind.PropertyDefinition:
name = metadata.GetString(metadata.GetPropertyDefinition((SRM.PropertyDefinitionHandle)member.Handle).Name);
case '*':
result = new PointerTypeReference(result);
break;
case SRM.HandleKind.EventDefinition:
name = metadata.GetString(metadata.GetEventDefinition((SRM.EventDefinitionHandle)member.Handle).Name);
case '@':
result = new ByReferenceTypeReference(result);
break;
default:
throw new NotSupportedException();
return result;
}
if (shortName == name.Replace('.', '#'))
shortNameMatch = member;
pos++;
}
// if there's no match by ID string (key), return the match by name.
return shortNameMatch;
return result;
}
static TypeDefinition FindType(PEFile module, string name)
static string ReadTypeName(string typeName, ref int pos, bool allowDottedName, out int typeParameterCount, List<ITypeReference> typeArguments)
{
var metadata = module.Metadata;
string[] segments = name.Split('.');
var currentNamespace = metadata.GetNamespaceDefinitionRoot();
int i = 0;
while (i < segments.Length) {
string part = segments[i];
var next = currentNamespace.NamespaceDefinitions.FirstOrDefault(ns => metadata.GetString(metadata.GetNamespaceDefinition(ns).Name) == part);
if (next.IsNil)
break;
currentNamespace = metadata.GetNamespaceDefinition(next);
i++;
int startPos = pos;
// skip the simple name portion:
while (pos < typeName.Length && !IsIDStringSpecialCharacter(typeName[pos]) && (allowDottedName || typeName[pos] != '.'))
pos++;
if (pos == startPos)
throw new ReflectionNameParseException(pos, "Expected type name");
string shortTypeName = typeName.Substring(startPos, pos - startPos);
// read type arguments:
typeParameterCount = 0;
if (pos < typeName.Length && typeName[pos] == '`') {
// unbound generic type
pos++;
typeParameterCount = ReflectionHelper.ReadTypeParameterCount(typeName, ref pos);
} else if (pos < typeName.Length && typeName[pos] == '{') {
// bound generic type
typeArguments = new List<ITypeReference>();
do {
pos++;
typeArguments.Add(ParseTypeName(typeName, ref pos));
typeParameterCount++;
if (pos == typeName.Length)
throw new ReflectionNameParseException(pos, "Unexpected end");
} while (typeName[pos] == ',');
if (typeName[pos] != '}')
throw new ReflectionNameParseException(pos, "Expected '}'");
pos++;
}
if (i == segments.Length)
return default(TypeDefinition);
var typeDefinitions = currentNamespace.TypeDefinitions;
while (i < segments.Length) {
string part = segments[i];
foreach (var t in typeDefinitions) {
var type = metadata.GetTypeDefinition(t);
if (metadata.GetString(type.Name) == part) {
if (i + 1 == segments.Length)
return new TypeDefinition(module, t);
typeDefinitions = type.GetNestedTypes();
i++;
break;
}
}
return shortTypeName;
}
#endregion
#region FindEntity
/// <summary>
/// Finds the entity in the given type resolve context.
/// </summary>
/// <param name="idString">ID string of the entity.</param>
/// <param name="context">Type resolve context</param>
/// <returns>Returns the entity, or null if it is not found.</returns>
/// <exception cref="ReflectionNameParseException">The syntax of the ID string is invalid</exception>
public static IEntity FindEntity(string idString, ITypeResolveContext context)
{
if (idString == null)
throw new ArgumentNullException("idString");
if (context == null)
throw new ArgumentNullException("context");
if (idString.StartsWith("T:", StringComparison.Ordinal)) {
return ParseTypeName(idString.Substring(2)).Resolve(context).GetDefinition();
} else {
return ParseMemberIdString(idString).Resolve(context);
}
// TODO : add support for type forwarders
//foreach (var h in metadata.ExportedTypes) {
// var exportedType = metadata.GetExportedType(h);
// if (metadata.StringComparer.Equals(exportedType.Name, name) && exportedType.Namespace == ns) {
// type = exportedType.Resolve();
// break;
// }
//}
return default;
}
#endregion
}

20
ICSharpCode.Decompiler/Documentation/XmlDocumentationProvider.cs

@ -23,9 +23,15 @@ using System.IO; @@ -23,9 +23,15 @@ using System.IO;
using System.Runtime.Serialization;
using System.Text;
using System.Xml;
using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.Decompiler.Documentation
{
public interface IDocumentationProvider
{
string GetDocumentation(IEntity entity);
}
/// <summary>
/// Provides documentation from an .xml file (as generated by the Microsoft C# compiler).
/// </summary>
@ -36,7 +42,7 @@ namespace ICSharpCode.Decompiler.Documentation @@ -36,7 +42,7 @@ namespace ICSharpCode.Decompiler.Documentation
/// If the .xml file is changed, the index will automatically be recreated.
/// </remarks>
[Serializable]
public class XmlDocumentationProvider : IDeserializationCallback
public class XmlDocumentationProvider : IDeserializationCallback, IDocumentationProvider
{
#region Cache
sealed class XmlDocumentationCache
@ -316,7 +322,17 @@ namespace ICSharpCode.Decompiler.Documentation @@ -316,7 +322,17 @@ namespace ICSharpCode.Decompiler.Documentation
throw new ArgumentNullException("key");
return GetDocumentation(key, true);
}
/// <summary>
/// Get the documentation for the specified member.
/// </summary>
public string GetDocumentation(IEntity entity)
{
if (entity == null)
throw new ArgumentNullException(nameof(entity));
return GetDocumentation(XmlDocKeyProvider.GetKey(entity));
}
string GetDocumentation(string key, bool allowReload)
{
int hashcode = GetHashCode(key);

7
ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj

@ -270,6 +270,7 @@ @@ -270,6 +270,7 @@
<Compile Include="DecompileRun.cs" />
<Compile Include="Disassembler\DomExtensions.cs" />
<Compile Include="Metadata\AssemblyReferences.cs" />
<Compile Include="Metadata\MetadataResolver.cs" />
<Compile Include="Metadata\MetadataTokenHelpers.cs" />
<Compile Include="Disassembler\OpCodeInfo.cs" />
<Compile Include="Documentation\GetPotentiallyNestedClassTypeReference.cs" />
@ -283,7 +284,6 @@ @@ -283,7 +284,6 @@
<Compile Include="IL\ControlFlow\YieldReturnDecompiler.cs" />
<Compile Include="Metadata\CustomAttributeDecoder.cs" />
<Compile Include="Metadata\Dom.cs" />
<Compile Include="Metadata\MetadataResolver.cs" />
<Compile Include="Metadata\DotNetCorePathFinder.cs" />
<Compile Include="Metadata\DotNetCorePathFinderExtensions.cs" />
<Compile Include="Metadata\LightJson\JsonArray.cs" />
@ -306,7 +306,7 @@ @@ -306,7 +306,7 @@
<Compile Include="IL\Instructions\LdFlda.cs" />
<Compile Include="IL\Instructions\NullableInstructions.cs" />
<Compile Include="IL\Instructions\StLoc.cs" />
<Compile Include="Metadata\SequencePoint.cs" />
<Compile Include="DebugInfo\SequencePoint.cs" />
<Compile Include="IL\Instructions\CallIndirect.cs" />
<Compile Include="IL\Instructions\DefaultValue.cs" />
<Compile Include="IL\Transforms\DynamicCallSiteTransform.cs" />
@ -342,7 +342,8 @@ @@ -342,7 +342,8 @@
<Compile Include="IL\Transforms\StatementTransform.cs" />
<Compile Include="IL\Transforms\TransformCollectionAndObjectInitializers.cs" />
<Compile Include="Output\TextTokenWriter.cs" />
<Compile Include="Pdb\PortablePdbWriter.cs" />
<Compile Include="DebugInfo\IDebugInfoProvider.cs" />
<Compile Include="DebugInfo\PortablePdbWriter.cs" />
<Compile Include="SRMExtensions.cs" />
<Compile Include="SRMHacks.cs" />
<Compile Include="TypeSystem\ApplyAttributeTypeVisitor.cs" />

6
ICSharpCode.Decompiler/IL/ControlFlow/YieldReturnDecompiler.cs

@ -384,9 +384,11 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -384,9 +384,11 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
)
);
}
var il = new ILReader(typeSystem).ReadIL(typeSystem.ModuleDefinition, method, typeSystem.ModuleDefinition.Reader.GetMethodBody(methodDef.RelativeVirtualAddress), context.CancellationToken);
var body = typeSystem.ModuleDefinition.Reader.GetMethodBody(methodDef.RelativeVirtualAddress);
var il = context.CreateILReader(typeSystem)
.ReadIL(typeSystem.ModuleDefinition, method, body, context.CancellationToken);
il.RunTransforms(CSharpDecompiler.EarlyILTransforms(true),
new ILTransformContext(il, typeSystem, context.Settings) {
new ILTransformContext(il, typeSystem, context.DebugInfo, context.Settings) {
CancellationToken = context.CancellationToken,
DecompileRun = context.DecompileRun
});

12
ICSharpCode.Decompiler/IL/ILReader.cs

@ -40,6 +40,7 @@ namespace ICSharpCode.Decompiler.IL @@ -40,6 +40,7 @@ namespace ICSharpCode.Decompiler.IL
readonly IDecompilerTypeSystem typeSystem;
public bool UseDebugSymbols { get; set; }
public DebugInfo.IDebugInfoProvider DebugInfo { get; set; }
public List<string> Warnings { get; } = new List<string>();
public ILReader(IDecompilerTypeSystem typeSystem)
@ -53,7 +54,6 @@ namespace ICSharpCode.Decompiler.IL @@ -53,7 +54,6 @@ namespace ICSharpCode.Decompiler.IL
MetadataReader metadata;
IMethod method;
MethodBodyBlock body;
Metadata.IDebugInfoProvider debugInfo;
StackType methodReturnStackType;
BlobReader reader;
ImmutableStack<ILVariable> currentStack;
@ -79,7 +79,6 @@ namespace ICSharpCode.Decompiler.IL @@ -79,7 +79,6 @@ namespace ICSharpCode.Decompiler.IL
var methodDefinition = metadata.GetMethodDefinition(methodDefinitionHandle);
this.body = body;
this.reader = body.GetILReader();
this.debugInfo = module.DebugInfo;
this.currentStack = ImmutableStack<ILVariable>.Empty;
this.unionFind = new UnionFind<ILVariable>();
this.stackMismatchPairs = new List<(ILVariable, ILVariable)>();
@ -177,7 +176,7 @@ namespace ICSharpCode.Decompiler.IL @@ -177,7 +176,7 @@ namespace ICSharpCode.Decompiler.IL
kind = VariableKind.Local;
}
ILVariable ilVar = new ILVariable(kind, type, index);
if (!UseDebugSymbols || debugInfo == null || !debugInfo.TryGetName((MethodDefinitionHandle)method.MetadataToken, index, out string name)) {
if (!UseDebugSymbols || DebugInfo == null || !DebugInfo.TryGetName((MethodDefinitionHandle)method.MetadataToken, index, out string name)) {
ilVar.Name = "V_" + index;
ilVar.HasGeneratedName = true;
} else if (string.IsNullOrWhiteSpace(name)) {
@ -410,7 +409,8 @@ namespace ICSharpCode.Decompiler.IL @@ -410,7 +409,8 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>
/// Debugging helper: writes the decoded instruction stream interleaved with the inferred evaluation stack layout.
/// </summary>
public void WriteTypedIL(Metadata.PEFile module, MethodDefinitionHandle method, MethodBodyBlock body, ITextOutput output, CancellationToken cancellationToken = default(CancellationToken))
public void WriteTypedIL(Metadata.PEFile module,
MethodDefinitionHandle method, MethodBodyBlock body, ITextOutput output, CancellationToken cancellationToken = default)
{
Init(module, method, body);
ReadInstructions(cancellationToken);
@ -428,7 +428,7 @@ namespace ICSharpCode.Decompiler.IL @@ -428,7 +428,7 @@ namespace ICSharpCode.Decompiler.IL
isFirstElement = false;
else
output.Write(", ");
output.WriteReference(element.Name, element, isLocal: true);
output.WriteLocalReference(element.Name, element);
output.Write(":");
output.Write(element.StackType);
}
@ -438,7 +438,7 @@ namespace ICSharpCode.Decompiler.IL @@ -438,7 +438,7 @@ namespace ICSharpCode.Decompiler.IL
output.Write('*');
else
output.Write(' ');
output.WriteDefinition("IL_" + inst.ILRange.Start.ToString("x4"), inst.ILRange.Start);
output.WriteLocalReference("IL_" + inst.ILRange.Start.ToString("x4"), inst.ILRange.Start, isDefinition: true);
output.Write(": ");
inst.WriteTo(output, new ILAstWritingOptions());
output.WriteLine();

4
ICSharpCode.Decompiler/IL/ILVariable.cs

@ -319,7 +319,7 @@ namespace ICSharpCode.Decompiler.IL @@ -319,7 +319,7 @@ namespace ICSharpCode.Decompiler.IL
default:
throw new ArgumentOutOfRangeException();
}
output.WriteDefinition(this.Name, this, isLocal: true);
output.WriteLocalReference(this.Name, this, isDefinition: true);
output.Write(" : ");
Type.WriteTo(output);
output.Write('(');
@ -340,7 +340,7 @@ namespace ICSharpCode.Decompiler.IL @@ -340,7 +340,7 @@ namespace ICSharpCode.Decompiler.IL
internal void WriteTo(ITextOutput output)
{
output.WriteReference(this.Name, this, isLocal: true);
output.WriteLocalReference(this.Name, this);
}
/// <summary>

10
ICSharpCode.Decompiler/IL/InstructionOutputExtensions.cs

@ -41,15 +41,15 @@ namespace ICSharpCode.Decompiler.IL @@ -41,15 +41,15 @@ namespace ICSharpCode.Decompiler.IL
public static void WriteTo(this IType type, ITextOutput output, ILNameSyntax nameSyntax = ILNameSyntax.ShortTypeName)
{
output.WriteReference(type.ReflectionName, type);
output.WriteReference(type, type.ReflectionName);
}
public static void WriteTo(this ISymbol symbol, ITextOutput output)
public static void WriteTo(this IMember member, ITextOutput output)
{
if (symbol is IMethod method && method.IsConstructor)
output.WriteReference(method.DeclaringType?.Name + "." + method.Name, symbol);
if (member is IMethod method && method.IsConstructor)
output.WriteReference(member, method.DeclaringType?.Name + "." + method.Name);
else
output.WriteReference(symbol.Name, symbol);
output.WriteReference(member, member.Name);
}
public static void WriteTo(this Interval interval, ITextOutput output, ILAstWritingOptions options)

2
ICSharpCode.Decompiler/IL/Instructions/Block.cs

@ -152,7 +152,7 @@ namespace ICSharpCode.Decompiler.IL @@ -152,7 +152,7 @@ namespace ICSharpCode.Decompiler.IL
{
ILRange.WriteTo(output, options);
output.Write("Block ");
output.WriteDefinition(Label, this);
output.WriteLocalReference(Label, this, isDefinition: true);
if (Kind != BlockKind.ControlFlow)
output.Write($" ({Kind})");
if (Parent is BlockContainer)

4
ICSharpCode.Decompiler/IL/Instructions/BlockContainer.cs

@ -118,7 +118,7 @@ namespace ICSharpCode.Decompiler.IL @@ -118,7 +118,7 @@ namespace ICSharpCode.Decompiler.IL
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
{
ILRange.WriteTo(output, options);
output.WriteDefinition("BlockContainer", this);
output.WriteLocalReference("BlockContainer", this, isDefinition: true);
output.Write(' ');
switch (Kind) {
case ContainerKind.Loop:
@ -145,7 +145,7 @@ namespace ICSharpCode.Decompiler.IL @@ -145,7 +145,7 @@ namespace ICSharpCode.Decompiler.IL
inst.WriteTo(output, options);
} else {
output.Write("stale reference to ");
output.WriteReference(inst.Label, inst, isLocal: true);
output.WriteLocalReference(inst.Label, inst);
}
output.WriteLine();
output.WriteLine();

2
ICSharpCode.Decompiler/IL/Instructions/Branch.cs

@ -116,7 +116,7 @@ namespace ICSharpCode.Decompiler.IL @@ -116,7 +116,7 @@ namespace ICSharpCode.Decompiler.IL
ILRange.WriteTo(output, options);
output.Write(OpCode);
output.Write(' ');
output.WriteReference(TargetLabel, (object)targetBlock ?? TargetILOffset, isLocal: true);
output.WriteLocalReference(TargetLabel, (object)targetBlock ?? TargetILOffset);
}
}

2
ICSharpCode.Decompiler/IL/Instructions/Leave.cs

@ -115,7 +115,7 @@ namespace ICSharpCode.Decompiler.IL @@ -115,7 +115,7 @@ namespace ICSharpCode.Decompiler.IL
output.Write(OpCode);
if (targetContainer != null) {
output.Write(' ');
output.WriteReference(TargetLabel, targetContainer, isLocal: true);
output.WriteLocalReference(TargetLabel, targetContainer);
output.Write(" (");
value.WriteTo(output, options);
output.Write(')');

2
ICSharpCode.Decompiler/IL/Instructions/SwitchInstruction.cs

@ -183,7 +183,7 @@ namespace ICSharpCode.Decompiler.IL @@ -183,7 +183,7 @@ namespace ICSharpCode.Decompiler.IL
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
{
ILRange.WriteTo(output, options);
output.WriteDefinition("case", this, isLocal: true);
output.WriteLocalReference("case", this, isDefinition: true);
output.Write(' ');
if (HasNullLabel) {
output.Write("null");

2
ICSharpCode.Decompiler/IL/Instructions/TryInstruction.cs

@ -165,7 +165,7 @@ namespace ICSharpCode.Decompiler.IL @@ -165,7 +165,7 @@ namespace ICSharpCode.Decompiler.IL
ILRange.WriteTo(output, options);
output.Write("catch ");
if (variable != null) {
output.WriteDefinition(variable.Name, variable);
output.WriteLocalReference(variable.Name, variable, isDefinition: true);
output.Write(" : ");
Disassembler.DisassemblerHelpers.WriteOperand(output, variable.Type);
}

5
ICSharpCode.Decompiler/IL/Transforms/DelegateConstruction.cs

@ -145,8 +145,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -145,8 +145,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
if (!methodDefinition.HasBody())
return null;
var localTypeSystem = context.TypeSystem.GetSpecializingTypeSystem(targetMethod.Substitution);
var ilReader = new ILReader(localTypeSystem);
ilReader.UseDebugSymbols = context.Settings.UseDebugSymbols;
var ilReader = context.CreateILReader(localTypeSystem);
var function = ilReader.ReadIL(context.TypeSystem.ModuleDefinition, (MethodDefinitionHandle)targetMethod.MetadataToken, context.TypeSystem.ModuleDefinition.Reader.GetMethodBody(methodDefinition.RelativeVirtualAddress), context.CancellationToken);
function.DelegateType = value.Method.DeclaringType;
function.CheckInvariant(ILPhase.Normal);
@ -156,7 +155,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -156,7 +155,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
v.Name = contextPrefix + v.Name;
}
var nestedContext = new ILTransformContext(function, localTypeSystem, context.Settings) {
var nestedContext = new ILTransformContext(function, localTypeSystem, context.DebugInfo, context.Settings) {
CancellationToken = context.CancellationToken,
DecompileRun = context.DecompileRun
};

16
ICSharpCode.Decompiler/IL/Transforms/IILTransform.cs

@ -22,6 +22,7 @@ using System.Collections.Immutable; @@ -22,6 +22,7 @@ using System.Collections.Immutable;
using System.Diagnostics;
using System.Threading;
using ICSharpCode.Decompiler.CSharp.TypeSystem;
using ICSharpCode.Decompiler.DebugInfo;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.Util;
@ -42,6 +43,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -42,6 +43,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
{
public ILFunction Function { get; }
public IDecompilerTypeSystem TypeSystem { get; }
public IDebugInfoProvider DebugInfo { get; }
public DecompilerSettings Settings { get; }
public CancellationToken CancellationToken { get; set; }
public Stepper Stepper { get; set; }
@ -49,11 +51,12 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -49,11 +51,12 @@ namespace ICSharpCode.Decompiler.IL.Transforms
internal DecompileRun DecompileRun { get; set; }
internal ResolvedUsingScope UsingScope => DecompileRun.UsingScope.Resolve(TypeSystem.Compilation);
public ILTransformContext(ILFunction function, IDecompilerTypeSystem typeSystem, DecompilerSettings settings = null)
public ILTransformContext(ILFunction function, IDecompilerTypeSystem typeSystem, IDebugInfoProvider debugInfo, DecompilerSettings settings = null)
{
this.Function = function ?? throw new ArgumentNullException(nameof(function));
this.TypeSystem = typeSystem ?? throw new ArgumentNullException(nameof(typeSystem));
this.Settings = settings ?? new DecompilerSettings();
this.DebugInfo = debugInfo;
Stepper = new Stepper();
}
@ -61,12 +64,23 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -61,12 +64,23 @@ namespace ICSharpCode.Decompiler.IL.Transforms
{
this.Function = context.Function;
this.TypeSystem = context.TypeSystem;
this.DebugInfo = context.DebugInfo;
this.Settings = context.Settings;
this.DecompileRun = context.DecompileRun;
this.CancellationToken = context.CancellationToken;
this.Stepper = context.Stepper;
}
public ILReader CreateILReader(IDecompilerTypeSystem typeSystem = null)
{
if (typeSystem == null)
typeSystem = this.TypeSystem;
return new ILReader(typeSystem) {
UseDebugSymbols = Settings.UseDebugSymbols,
DebugInfo = DebugInfo
};
}
/// <summary>
/// Call this method immediately before performing a transform step.
/// Unlike <c>context.Stepper.Step()</c>, calls to this method are only compiled in debug builds.

18
ICSharpCode.Decompiler/IL/Transforms/ProxyCallReplacer.cs

@ -31,20 +31,14 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -31,20 +31,14 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return;
// partially copied from CSharpDecompiler
var specializingTypeSystem = context.TypeSystem.GetSpecializingTypeSystem(inst.Method.Substitution);
var ilReader = new ILReader(specializingTypeSystem);
System.Threading.CancellationToken cancellationToken = new System.Threading.CancellationToken();
var proxyFunction = ilReader.ReadIL(module, handle, module.Reader.GetMethodBody(methodDef.RelativeVirtualAddress), cancellationToken);
var transformContext = new ILTransformContext(proxyFunction, specializingTypeSystem, context.Settings) {
CancellationToken = cancellationToken,
var ilReader = context.CreateILReader(specializingTypeSystem);
var body = module.Reader.GetMethodBody(methodDef.RelativeVirtualAddress);
var proxyFunction = ilReader.ReadIL(module, handle, body, context.CancellationToken);
var transformContext = new ILTransformContext(proxyFunction, specializingTypeSystem, context.DebugInfo, context.Settings) {
CancellationToken = context.CancellationToken,
DecompileRun = context.DecompileRun
};
foreach (var transform in CSharp.CSharpDecompiler.GetILTransforms()) {
if (transform.GetType() != typeof(ProxyCallReplacer)) { // don't call itself on itself
cancellationToken.ThrowIfCancellationRequested();
transform.Run(proxyFunction, transformContext);
}
}
proxyFunction.RunTransforms(CSharp.CSharpDecompiler.EarlyILTransforms(), transformContext);
if (!(proxyFunction.Body is BlockContainer blockContainer))
return;
if (blockContainer.Blocks.Count != 1)

419
ICSharpCode.Decompiler/Metadata/Dom.cs

@ -15,43 +15,6 @@ using ICSharpCode.Decompiler.Util; @@ -15,43 +15,6 @@ using ICSharpCode.Decompiler.Util;
namespace ICSharpCode.Decompiler.Metadata
{
using SRMMemberRef = System.Reflection.Metadata.MemberReference;
using SRMMethod = System.Reflection.Metadata.MethodDefinition;
using SRMMethodSpec = System.Reflection.Metadata.MethodSpecification;
using SRMProperty = System.Reflection.Metadata.PropertyDefinition;
using SRMEvent = System.Reflection.Metadata.EventDefinition;
using SRMField = System.Reflection.Metadata.FieldDefinition;
using SRMTypeDef = System.Reflection.Metadata.TypeDefinition;
using SRMTypeRef = System.Reflection.Metadata.TypeReference;
using SRMTypeSpec = System.Reflection.Metadata.TypeSpecification;
using SRMAssemblyReference = System.Reflection.Metadata.AssemblyReference;
public interface IAssemblyDocumentationResolver
{
XmlDocumentationProvider GetProvider();
}
public interface IMetadataEntity
{
PEFile Module { get; }
EntityHandle Handle { get; }
bool IsNil { get; }
}
public struct Variable
{
public string Name { get; set; }
}
public interface IDebugInfoProvider
{
IList<SequencePoint> GetSequencePoints(MethodDefinitionHandle method);
IList<Variable> GetVariables(MethodDefinitionHandle method);
bool TryGetName(MethodDefinitionHandle method, int index, out string name);
}
public enum TargetRuntime
{
Unknown,
@ -136,378 +99,6 @@ namespace ICSharpCode.Decompiler.Metadata @@ -136,378 +99,6 @@ namespace ICSharpCode.Decompiler.Metadata
}
}
public struct Entity : IEquatable<Entity>, IMetadataEntity
{
public PEFile Module { get; }
public EntityHandle Handle { get; }
public bool IsNil => Handle.IsNil;
public Entity(PEFile module, EntityHandle handle) : this()
{
this.Module = module ?? throw new ArgumentNullException(nameof(module));
this.Handle = handle;
}
public bool IsType() => Handle.Kind == HandleKind.TypeDefinition || Handle.Kind == HandleKind.TypeReference || Handle.Kind == HandleKind.TypeSpecification;
public TypeDefinition ResolveAsType()
{
return MetadataResolver.ResolveType(Handle, new SimpleMetadataResolveContext(Module));
}
public FieldDefinition ResolveAsField()
{
return MetadataResolver.ResolveAsField(Handle, new SimpleMetadataResolveContext(Module));
}
public MethodDefinition ResolveAsMethod()
{
return MetadataResolver.ResolveAsMethod(Handle, new SimpleMetadataResolveContext(Module));
}
public bool Equals(Entity other)
{
return Module == other.Module && Handle == other.Handle;
}
public override bool Equals(object obj)
{
if (obj is Entity entity)
return Equals(entity);
return false;
}
public override int GetHashCode()
{
return unchecked(982451629 * Module.GetHashCode() + 982451653 * MetadataTokens.GetToken(Handle));
}
public static bool operator ==(Entity lhs, Entity rhs) => lhs.Equals(rhs);
public static bool operator !=(Entity lhs, Entity rhs) => !lhs.Equals(rhs);
public static implicit operator Entity(MethodDefinition method)
{
return new Entity(method.Module, method.Handle);
}
public static implicit operator Entity(PropertyDefinition property)
{
return new Entity(property.Module, property.Handle);
}
public static implicit operator Entity(EventDefinition @event)
{
return new Entity(@event.Module, @event.Handle);
}
public static implicit operator Entity(FieldDefinition field)
{
return new Entity(field.Module, field.Handle);
}
public static implicit operator Entity(TypeDefinition type)
{
return new Entity(type.Module, type.Handle);
}
public static implicit operator TypeDefinition(Entity entity)
{
return new TypeDefinition(entity.Module, (TypeDefinitionHandle)entity.Handle);
}
public static implicit operator MethodDefinition(Entity entity)
{
return new MethodDefinition(entity.Module, (MethodDefinitionHandle)entity.Handle);
}
public static implicit operator PropertyDefinition(Entity entity)
{
return new PropertyDefinition(entity.Module, (PropertyDefinitionHandle)entity.Handle);
}
public static implicit operator EventDefinition(Entity entity)
{
return new EventDefinition(entity.Module, (EventDefinitionHandle)entity.Handle);
}
public static implicit operator FieldDefinition(Entity entity)
{
return new FieldDefinition(entity.Module, (FieldDefinitionHandle)entity.Handle);
}
}
public struct MethodDefinition : IEquatable<MethodDefinition>, IMetadataEntity
{
public PEFile Module { get; }
public MethodDefinitionHandle Handle { get; }
public bool IsNil => Handle.IsNil;
EntityHandle IMetadataEntity.Handle => Handle;
public MethodDefinition(PEFile module, MethodDefinitionHandle handle) : this()
{
this.Module = module ?? throw new ArgumentNullException(nameof(module));
this.Handle = handle;
}
public bool Equals(MethodDefinition other)
{
return Module == other.Module && Handle == other.Handle;
}
public override bool Equals(object obj)
{
if (obj is MethodDefinition md)
return Equals(md);
return false;
}
public override int GetHashCode()
{
return unchecked(982451629 * Module.GetHashCode() + 982451653 * MetadataTokens.GetToken(Handle));
}
public static bool operator ==(MethodDefinition lhs, MethodDefinition rhs) => lhs.Equals(rhs);
public static bool operator !=(MethodDefinition lhs, MethodDefinition rhs) => !lhs.Equals(rhs);
public IList<SequencePoint> GetSequencePoints()
{
return Module.DebugInfo?.GetSequencePoints(Handle) ?? EmptyList<SequencePoint>.Instance;
}
public IList<Variable> GetVariables()
{
return Module.DebugInfo?.GetVariables(Handle) ?? EmptyList<Variable>.Instance;
}
}
public struct PropertyDefinition : IEquatable<PropertyDefinition>, IMetadataEntity
{
public PEFile Module { get; }
public PropertyDefinitionHandle Handle { get; }
public bool IsNil => Handle.IsNil;
EntityHandle IMetadataEntity.Handle => Handle;
public PropertyDefinition(PEFile module, PropertyDefinitionHandle handle) : this()
{
this.Module = module ?? throw new ArgumentNullException(nameof(module));
this.Handle = handle;
}
public bool Equals(PropertyDefinition other)
{
return Module == other.Module && Handle == other.Handle;
}
public override bool Equals(object obj)
{
if (obj is PropertyDefinition pd)
return Equals(pd);
return false;
}
public override int GetHashCode()
{
return unchecked(982451629 * Module.GetHashCode() + 982451653 * MetadataTokens.GetToken(Handle));
}
public static bool operator ==(PropertyDefinition lhs, PropertyDefinition rhs) => lhs.Equals(rhs);
public static bool operator !=(PropertyDefinition lhs, PropertyDefinition rhs) => !lhs.Equals(rhs);
}
public struct FieldDefinition : IEquatable<FieldDefinition>, IMetadataEntity
{
public PEFile Module { get; }
public FieldDefinitionHandle Handle { get; }
public bool IsNil => Handle.IsNil;
EntityHandle IMetadataEntity.Handle => Handle;
public FieldDefinition(PEFile module, FieldDefinitionHandle handle) : this()
{
this.Module = module ?? throw new ArgumentNullException(nameof(module));
this.Handle = handle;
}
public bool Equals(FieldDefinition other)
{
return Module == other.Module && Handle == other.Handle;
}
public override bool Equals(object obj)
{
if (obj is FieldDefinition fd)
return Equals(fd);
return false;
}
public override int GetHashCode()
{
return unchecked(982451629 * Module.GetHashCode() + 982451653 * MetadataTokens.GetToken(Handle));
}
public static bool operator ==(FieldDefinition lhs, FieldDefinition rhs) => lhs.Equals(rhs);
public static bool operator !=(FieldDefinition lhs, FieldDefinition rhs) => !lhs.Equals(rhs);
public object DecodeConstant()
{
var metadata = Module.Metadata;
var constant = metadata.GetConstant(metadata.GetFieldDefinition(Handle).GetDefaultValue());
var blob = metadata.GetBlobReader(constant.Value);
switch (constant.TypeCode) {
case ConstantTypeCode.Boolean:
return blob.ReadBoolean();
case ConstantTypeCode.Char:
return blob.ReadChar();
case ConstantTypeCode.SByte:
return blob.ReadSByte();
case ConstantTypeCode.Byte:
return blob.ReadByte();
case ConstantTypeCode.Int16:
return blob.ReadInt16();
case ConstantTypeCode.UInt16:
return blob.ReadUInt16();
case ConstantTypeCode.Int32:
return blob.ReadInt32();
case ConstantTypeCode.UInt32:
return blob.ReadUInt32();
case ConstantTypeCode.Int64:
return blob.ReadInt64();
case ConstantTypeCode.UInt64:
return blob.ReadUInt64();
case ConstantTypeCode.Single:
return blob.ReadSingle();
case ConstantTypeCode.Double:
return blob.ReadDouble();
case ConstantTypeCode.String:
return blob.ReadSerializedString();
case ConstantTypeCode.NullReference:
return null;
default:
throw new NotSupportedException();
}
}
}
public struct EventDefinition : IEquatable<EventDefinition>, IMetadataEntity
{
public PEFile Module { get; }
public EventDefinitionHandle Handle { get; }
public bool IsNil => Handle.IsNil;
EntityHandle IMetadataEntity.Handle => Handle;
public EventDefinition(PEFile module, EventDefinitionHandle handle)
{
this.Module = module ?? throw new ArgumentNullException(nameof(module));
this.Handle = handle;
}
public bool Equals(EventDefinition other)
{
return Module == other.Module && Handle == other.Handle;
}
public override bool Equals(object obj)
{
if (obj is EventDefinition ed)
return Equals(ed);
return false;
}
public override int GetHashCode()
{
return unchecked(982451629 * Module.GetHashCode() + 982451653 * MetadataTokens.GetToken(Handle));
}
public static bool operator ==(EventDefinition lhs, EventDefinition rhs) => lhs.Equals(rhs);
public static bool operator !=(EventDefinition lhs, EventDefinition rhs) => !lhs.Equals(rhs);
}
public struct TypeDefinition : IEquatable<TypeDefinition>, IMetadataEntity
{
public PEFile Module { get; }
public TypeDefinitionHandle Handle { get; }
public bool IsNil => Handle.IsNil;
EntityHandle IMetadataEntity.Handle => Handle;
public TypeDefinition(PEFile module, TypeDefinitionHandle handle)
{
this.Module = module ?? throw new ArgumentNullException(nameof(module));
this.Handle = handle;
}
public bool Equals(TypeDefinition other)
{
return Module == other.Module && Handle == other.Handle;
}
public override bool Equals(object obj)
{
if (obj is TypeDefinition td)
return Equals(td);
return false;
}
public override int GetHashCode()
{
return unchecked(982451629 * Module.GetHashCode() + 982451653 * MetadataTokens.GetToken(Handle));
}
public static bool operator ==(TypeDefinition lhs, TypeDefinition rhs) => lhs.Equals(rhs);
public static bool operator !=(TypeDefinition lhs, TypeDefinition rhs) => !lhs.Equals(rhs);
}
public struct TypeReference
{
public PEFile Module { get; }
public TypeReferenceHandle Handle { get; }
public bool IsNil => Handle.IsNil;
public TypeReference(PEFile module, TypeReferenceHandle handle)
{
this.Module = module ?? throw new ArgumentNullException(nameof(module));
this.Handle = handle;
}
}
public struct TypeSpecification
{
public PEFile Module { get; }
public TypeSpecificationHandle Handle { get; }
public bool IsNil => Handle.IsNil;
public TypeSpecification(PEFile module, TypeSpecificationHandle handle)
{
this.Module = module ?? throw new ArgumentNullException(nameof(module));
this.Handle = handle;
}
}
public struct MethodSpecification
{
public PEFile Module { get; }
public MethodSpecificationHandle Handle { get; }
public bool IsNil => Handle.IsNil;
public MethodSpecification(PEFile module, MethodSpecificationHandle handle)
{
this.Module = module ?? throw new ArgumentNullException(nameof(module));
this.Handle = handle;
}
}
public struct MemberReference
{
public PEFile Module { get; }
public MemberReferenceHandle Handle { get; }
public bool IsNil => Handle.IsNil;
public MemberReference(PEFile module, MemberReferenceHandle handle)
{
this.Module = module ?? throw new ArgumentNullException(nameof(module));
this.Handle = handle;
}
}
public sealed class FullTypeNameSignatureDecoder : ISignatureTypeProvider<FullTypeName, Unit>
{
readonly MetadataReader metadata;
@ -606,22 +197,12 @@ namespace ICSharpCode.Decompiler.Metadata @@ -606,22 +197,12 @@ namespace ICSharpCode.Decompiler.Metadata
this.declaringType = module.Metadata.GetMethodDefinition(method).GetDeclaringType();
}
public GenericContext(MethodDefinition method)
: this(method.Handle, method.Module)
{
}
public GenericContext(TypeDefinitionHandle declaringType, PEFile module)
{
this.module = module;
this.declaringType = declaringType;
}
public GenericContext(TypeDefinition declaringType)
: this(declaringType.Handle, declaringType.Module)
{
}
public string GetGenericTypeParameterName(int index)
{
GenericParameterHandle genericParameter = GetGenericTypeParameterHandleOrNull(index);

36
ICSharpCode.Decompiler/Metadata/MetadataExtensions.cs

@ -104,42 +104,6 @@ namespace ICSharpCode.Decompiler.Metadata @@ -104,42 +104,6 @@ namespace ICSharpCode.Decompiler.Metadata
&& (name == ".cctor" || name == ".ctor");
}
public static bool HasMatchingDefaultMemberAttribute(this PropertyDefinitionHandle handle, PEFile module, out CustomAttributeHandle defaultMemberAttribute)
{
defaultMemberAttribute = default(CustomAttributeHandle);
var metadata = module.Metadata;
var propertyDefinition = metadata.GetPropertyDefinition(handle);
var accessorHandle = propertyDefinition.GetAccessors().GetAny();
var accessor = metadata.GetMethodDefinition(accessorHandle);
if (accessor.GetParameters().Count > 0) {
var basePropDef = propertyDefinition;
var firstOverrideHandle = accessorHandle.GetMethodImplementations(metadata).FirstOrDefault();
if (!firstOverrideHandle.IsNil) {
// if the property is explicitly implementing an interface, look up the property in the interface:
var firstOverride = metadata.GetMethodImplementation(firstOverrideHandle);
var baseAccessor = new Metadata.Entity(module, firstOverride.MethodDeclaration).ResolveAsMethod();
if (!baseAccessor.IsNil) {
var declaringType = metadata.GetTypeDefinition(metadata.GetMethodDefinition(baseAccessor.Handle).GetDeclaringType());
foreach (var basePropHandle in declaringType.GetProperties()) {
var baseProp = metadata.GetPropertyDefinition(basePropHandle);
var accessors = baseProp.GetAccessors();
if (accessors.Getter == baseAccessor.Handle || accessors.Setter == baseAccessor.Handle) {
basePropDef = baseProp;
break;
}
}
} else
return false;
}
var defaultMemberName = accessor.GetDeclaringType().GetDefaultMemberName(metadata, out var attr);
if (defaultMemberName == metadata.GetString(basePropDef.Name)) {
defaultMemberAttribute = attr;
return true;
}
}
return false;
}
public static string GetDefaultMemberName(this TypeDefinitionHandle type, MetadataReader reader)
{
return type.GetDefaultMemberName(reader, out var attr);

64
ICSharpCode.Decompiler/Metadata/MetadataResolver.cs

@ -40,18 +40,18 @@ namespace ICSharpCode.Decompiler.Metadata @@ -40,18 +40,18 @@ namespace ICSharpCode.Decompiler.Metadata
readonly IAssemblyResolver assemblyResolver;
readonly Dictionary<IAssemblyReference, PEFile> loadedModules;
public SimpleMetadataResolveContext(PEFile mainModule)
public SimpleMetadataResolveContext(PEFile mainModule, IAssemblyResolver assemblyResolver)
{
this.mainModule = mainModule;
this.assemblyResolver = mainModule.AssemblyResolver;
this.mainModule = mainModule ?? throw new ArgumentNullException(nameof(mainModule));
this.assemblyResolver = assemblyResolver ?? throw new ArgumentNullException(nameof(assemblyResolver));
this.loadedModules = new Dictionary<IAssemblyReference, PEFile>();
}
public SimpleMetadataResolveContext(PEFile mainModule, IMetadataResolveContext parentContext)
public SimpleMetadataResolveContext(PEFile mainModule, SimpleMetadataResolveContext parentContext)
{
this.mainModule = mainModule;
this.assemblyResolver = mainModule.AssemblyResolver;
this.loadedModules = parentContext is SimpleMetadataResolveContext simple ? simple.loadedModules : new Dictionary<IAssemblyReference, PEFile>();
this.mainModule = mainModule ?? throw new ArgumentNullException(nameof(mainModule));
this.assemblyResolver = parentContext.assemblyResolver;
this.loadedModules = parentContext.loadedModules;
}
public PEFile CurrentModule => mainModule;
@ -68,13 +68,13 @@ namespace ICSharpCode.Decompiler.Metadata @@ -68,13 +68,13 @@ namespace ICSharpCode.Decompiler.Metadata
public static class MetadataResolver
{
public static TypeDefinition ResolveType(EntityHandle handle, IMetadataResolveContext context)
public static (PEFile Module, TypeDefinitionHandle Handle) ResolveType(EntityHandle handle, IMetadataResolveContext context)
{
if (handle.IsNil)
return default;
switch (handle.Kind) {
case HandleKind.TypeDefinition:
return new TypeDefinition(context.CurrentModule, (TypeDefinitionHandle)handle);
return (context.CurrentModule, (TypeDefinitionHandle)handle);
case HandleKind.TypeReference:
return Resolve((TypeReferenceHandle)handle, context);
case HandleKind.TypeSpecification:
@ -84,39 +84,39 @@ namespace ICSharpCode.Decompiler.Metadata @@ -84,39 +84,39 @@ namespace ICSharpCode.Decompiler.Metadata
}
}
public static MethodDefinition ResolveAsMethod(EntityHandle handle, IMetadataResolveContext context)
public static (PEFile Module, MethodDefinitionHandle Handle) ResolveAsMethod(EntityHandle handle, IMetadataResolveContext context)
{
if (handle.IsNil)
return default;
switch (handle.Kind) {
case HandleKind.MethodDefinition:
return new MethodDefinition(context.CurrentModule, (MethodDefinitionHandle)handle);
return (context.CurrentModule, (MethodDefinitionHandle)handle);
case HandleKind.MemberReference:
var resolved = ((MemberReferenceHandle)handle).Resolve(context);
if (resolved is MethodDefinition m)
return m;
if (resolved.Handle.Kind == HandleKind.MethodDefinition)
return (resolved.Module, (MethodDefinitionHandle)resolved.Handle);
return default;
case HandleKind.MethodSpecification:
resolved = ((MethodSpecificationHandle)handle).Resolve(context);
if (resolved is MethodDefinition m2)
return m2;
if (resolved.Handle.Kind == HandleKind.MethodDefinition)
return (resolved.Module, (MethodDefinitionHandle)resolved.Handle);
return default;
default:
throw new NotSupportedException();
}
}
public static FieldDefinition ResolveAsField(EntityHandle handle, IMetadataResolveContext context)
public static (PEFile Module, FieldDefinitionHandle Handle) ResolveAsField(EntityHandle handle, IMetadataResolveContext context)
{
if (handle.IsNil)
return default;
switch (handle.Kind) {
case HandleKind.FieldDefinition:
return new FieldDefinition(context.CurrentModule, (FieldDefinitionHandle)handle);
return (context.CurrentModule, (FieldDefinitionHandle)handle);
case HandleKind.MemberReference:
var resolved = ((MemberReferenceHandle)handle).Resolve(context);
if (resolved is FieldDefinition m)
return m;
if (resolved.Handle.Kind == HandleKind.FieldDefinition)
return (resolved.Module, (FieldDefinitionHandle)resolved.Handle);
return default;
default:
throw new NotSupportedException();
@ -126,7 +126,7 @@ namespace ICSharpCode.Decompiler.Metadata @@ -126,7 +126,7 @@ namespace ICSharpCode.Decompiler.Metadata
/// <summary>
/// Implements resolving of TypeReferences to TypeDefinitions as decribed in II.7.3 of ECMA-335 6th edition.
/// </summary>
public static TypeDefinition Resolve(this TypeReferenceHandle handle, IMetadataResolveContext context)
public static (PEFile Module, TypeDefinitionHandle Handle) Resolve(this TypeReferenceHandle handle, IMetadataResolveContext context)
{
if (handle.IsNil)
return default;
@ -150,14 +150,14 @@ namespace ICSharpCode.Decompiler.Metadata @@ -150,14 +150,14 @@ namespace ICSharpCode.Decompiler.Metadata
switch (tr.ResolutionScope.Kind) {
case HandleKind.TypeReference:
var outerType = Resolve((TypeReferenceHandle)tr.ResolutionScope, context);
if (outerType == null)
if (outerType.Module == null)
throw new NotSupportedException();
var td = outerType.Module.Metadata.GetTypeDefinition(outerType.Handle);
var name = metadata.GetString(tr.Name);
foreach (var nestedType in td.GetNestedTypes()) {
var nestedTypeDef = outerType.Module.Metadata.GetTypeDefinition(nestedType);
if (outerType.Module.Metadata.GetString(nestedTypeDef.Name) == name)
return new TypeDefinition(outerType.Module, nestedType);
return (outerType.Module, nestedType);
}
break;
case HandleKind.ModuleReference:
@ -167,7 +167,7 @@ namespace ICSharpCode.Decompiler.Metadata @@ -167,7 +167,7 @@ namespace ICSharpCode.Decompiler.Metadata
}
throw new NotSupportedException();
TypeDefinition ResolveTypeInOtherAssembly(AssemblyReferenceHandle asm, string ns, string typeName)
(PEFile Module, TypeDefinitionHandle Handle) ResolveTypeInOtherAssembly(AssemblyReferenceHandle asm, string ns, string typeName)
{
var module = context.ResolveAssembly(new AssemblyReference(context.CurrentModule, asm));
if (module == null)
@ -176,7 +176,7 @@ namespace ICSharpCode.Decompiler.Metadata @@ -176,7 +176,7 @@ namespace ICSharpCode.Decompiler.Metadata
Debug.Assert(@namespace != null);
var type = FindTypeInNamespace(module.Metadata, @namespace.Value, typeName);
Debug.Assert(!type.IsNil);
return new TypeDefinition(module, type);
return (module, type);
}
}
@ -210,7 +210,7 @@ namespace ICSharpCode.Decompiler.Metadata @@ -210,7 +210,7 @@ namespace ICSharpCode.Decompiler.Metadata
return default;
}
public static IMetadataEntity Resolve(this MemberReferenceHandle handle, IMetadataResolveContext context)
static (PEFile Module, EntityHandle Handle) Resolve(this MemberReferenceHandle handle, IMetadataResolveContext context)
{
var metadata = context.CurrentModule.Metadata;
var mr = metadata.GetMemberReference(handle);
@ -225,7 +225,7 @@ namespace ICSharpCode.Decompiler.Metadata @@ -225,7 +225,7 @@ namespace ICSharpCode.Decompiler.Metadata
break;
case HandleKind.TypeReference:
var resolvedTypeReference = Resolve((TypeReferenceHandle)mr.Parent, context);
if (resolvedTypeReference.IsNil)
if (resolvedTypeReference.Module == null)
return default;
targetModule = resolvedTypeReference.Module;
targetMetadata = targetModule.Metadata;
@ -233,7 +233,7 @@ namespace ICSharpCode.Decompiler.Metadata @@ -233,7 +233,7 @@ namespace ICSharpCode.Decompiler.Metadata
break;
case HandleKind.TypeSpecification:
resolvedTypeReference = Resolve((TypeSpecificationHandle)mr.Parent, context);
if (resolvedTypeReference.IsNil)
if (resolvedTypeReference.Module == null)
return default;
targetModule = resolvedTypeReference.Module;
targetMetadata = targetModule.Metadata;
@ -251,7 +251,7 @@ namespace ICSharpCode.Decompiler.Metadata @@ -251,7 +251,7 @@ namespace ICSharpCode.Decompiler.Metadata
foreach (var f in declaringType.GetFields()) {
var fd = targetMetadata.GetFieldDefinition(f);
if (targetMetadata.StringComparer.Equals(fd.Name, name))
return new FieldDefinition(targetModule, f);
return (targetModule, f);
}
return default;
case MemberReferenceKind.Method:
@ -263,7 +263,7 @@ namespace ICSharpCode.Decompiler.Metadata @@ -263,7 +263,7 @@ namespace ICSharpCode.Decompiler.Metadata
}
foreach (var (method, signature) in candidates) {
if (SignatureBlobComparer.EqualsMethodSignature(targetMetadata.GetBlobReader(signature), metadata.GetBlobReader(mr.Signature), targetMetadata, metadata))
return new MethodDefinition(targetModule, method);
return (targetModule, method);
}
return default;
default:
@ -271,7 +271,7 @@ namespace ICSharpCode.Decompiler.Metadata @@ -271,7 +271,7 @@ namespace ICSharpCode.Decompiler.Metadata
}
}
public static TypeDefinition Resolve(this TypeSpecificationHandle handle, IMetadataResolveContext context)
public static (PEFile Module, TypeDefinitionHandle Handle) Resolve(this TypeSpecificationHandle handle, IMetadataResolveContext context)
{
var metadata = context.CurrentModule.Metadata;
var ts = metadata.GetTypeSpecification(handle);
@ -280,7 +280,7 @@ namespace ICSharpCode.Decompiler.Metadata @@ -280,7 +280,7 @@ namespace ICSharpCode.Decompiler.Metadata
return default;
switch (unspecialized.Kind) {
case HandleKind.TypeDefinition:
return new TypeDefinition(context.CurrentModule, (TypeDefinitionHandle)unspecialized);
return (context.CurrentModule, (TypeDefinitionHandle)unspecialized);
case HandleKind.TypeReference:
return Resolve((TypeReferenceHandle)unspecialized, context);
default:
@ -288,7 +288,7 @@ namespace ICSharpCode.Decompiler.Metadata @@ -288,7 +288,7 @@ namespace ICSharpCode.Decompiler.Metadata
}
}
public static MethodDefinition Resolve(this MethodSpecificationHandle handle, IMetadataResolveContext context)
public static (PEFile Module, MethodDefinitionHandle Handle) Resolve(this MethodSpecificationHandle handle, IMetadataResolveContext context)
{
var metadata = context.CurrentModule.Metadata;
var ms = metadata.GetMethodSpecification(handle);

20
ICSharpCode.Decompiler/Metadata/PEFile.cs

@ -33,24 +33,17 @@ namespace ICSharpCode.Decompiler.Metadata @@ -33,24 +33,17 @@ namespace ICSharpCode.Decompiler.Metadata
public string FileName { get; }
public PEReader Reader { get; }
public MetadataReader Metadata { get; }
public IAssemblyResolver AssemblyResolver { get; }
public IAssemblyDocumentationResolver DocumentationResolver { get; set; }
public IDebugInfoProvider DebugInfo { get; set; }
public PEFile(string fileName, Stream stream, bool throwOnResolveError = false, PEStreamOptions options = PEStreamOptions.Default)
public PEFile(string fileName, Stream stream, PEStreamOptions options = PEStreamOptions.Default)
: this(fileName, new PEReader(stream, options))
{
this.FileName = fileName;
this.Reader = new PEReader(stream, options);
this.Metadata = Reader.GetMetadataReader();
this.AssemblyResolver = new UniversalAssemblyResolver(fileName, throwOnResolveError, Reader.DetectTargetFrameworkId(), options);
}
public PEFile(string fileName, Stream stream, IAssemblyResolver assemblyResolver, PEStreamOptions options = PEStreamOptions.Default)
public PEFile(string fileName, PEReader reader)
{
this.FileName = fileName;
this.Reader = new PEReader(stream, options);
this.Metadata = Reader.GetMetadataReader();
this.AssemblyResolver = assemblyResolver;
this.FileName = fileName ?? throw new ArgumentNullException(nameof(fileName));
this.Reader = reader ?? throw new ArgumentNullException(nameof(reader));
this.Metadata = reader.GetMetadataReader();
}
public bool IsAssembly => Metadata.IsAssembly;
@ -85,7 +78,6 @@ namespace ICSharpCode.Decompiler.Metadata @@ -85,7 +78,6 @@ namespace ICSharpCode.Decompiler.Metadata
}
public ImmutableArray<AssemblyReference> AssemblyReferences => Metadata.AssemblyReferences.Select(r => new AssemblyReference(this, r)).ToImmutableArray();
public ImmutableArray<TypeDefinition> TopLevelTypeDefinitions => Metadata.GetTopLevelTypeDefinitions().Select(t => new TypeDefinition(this, t)).ToImmutableArray();
public ImmutableArray<Resource> Resources => GetResources().ToImmutableArray();
IEnumerable<Resource> GetResources()

5
ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs

@ -69,7 +69,8 @@ namespace ICSharpCode.Decompiler.Metadata @@ -69,7 +69,8 @@ namespace ICSharpCode.Decompiler.Metadata
public string TargetFramework { get; }
public UniversalAssemblyResolver(string mainAssemblyFileName, bool throwOnError, string targetFramework, PEStreamOptions options)
public UniversalAssemblyResolver(string mainAssemblyFileName, bool throwOnError, string targetFramework,
PEStreamOptions options = PEStreamOptions.Default)
{
this.options = options;
this.TargetFramework = targetFramework;
@ -89,7 +90,7 @@ namespace ICSharpCode.Decompiler.Metadata @@ -89,7 +90,7 @@ namespace ICSharpCode.Decompiler.Metadata
throw new AssemblyResolutionException(name);
return null;
}
return new PEFile(file, new FileStream(file, FileMode.Open, FileAccess.Read), this, options);
return new PEFile(file, new FileStream(file, FileMode.Open, FileAccess.Read), options);
}
public string FindAssemblyFile(IAssemblyReference name)

12
ICSharpCode.Decompiler/Output/ITextOutput.cs

@ -17,6 +17,11 @@ @@ -17,6 +17,11 @@
// DEALINGS IN THE SOFTWARE.
using System.Reflection.Metadata;
using ICSharpCode.Decompiler.Disassembler;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.Decompiler
{
public interface ITextOutput
@ -26,8 +31,11 @@ namespace ICSharpCode.Decompiler @@ -26,8 +31,11 @@ namespace ICSharpCode.Decompiler
void Write(char ch);
void Write(string text);
void WriteLine();
void WriteDefinition(string text, object definition, bool isLocal = true);
void WriteReference(string text, object reference, bool isLocal = false);
void WriteReference(OpCodeInfo opCode);
void WriteReference(PEFile module, EntityHandle handle, string text, bool isDefinition = false);
void WriteReference(IType type, string text, bool isDefinition = false);
void WriteReference(IMember member, string text, bool isDefinition = false);
void WriteLocalReference(string text, object reference, bool isDefinition = false);
void MarkFoldStart(string collapsedText = "...", bool defaultCollapsed = false);
void MarkFoldEnd();

28
ICSharpCode.Decompiler/Output/PlainTextOutput.cs

@ -18,7 +18,10 @@ @@ -18,7 +18,10 @@
using System;
using System.IO;
using System.Reflection.Metadata;
using ICSharpCode.Decompiler.CSharp.Syntax;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.Decompiler
{
@ -96,17 +99,32 @@ namespace ICSharpCode.Decompiler @@ -96,17 +99,32 @@ namespace ICSharpCode.Decompiler
line++;
column = 1;
}
public void WriteDefinition(string text, object definition, bool isLocal = true)
public void WriteReference(Disassembler.OpCodeInfo opCode)
{
Write(opCode.Name);
}
public void WriteReference(PEFile module, EntityHandle handle, string text, bool isDefinition = false)
{
Write(text);
}
public void WriteReference(string text, object reference, bool isLocal = false)
public void WriteReference(IType type, string text, bool isDefinition = false)
{
Write(text);
}
public void WriteReference(IMember member, string text, bool isDefinition = false)
{
Write(text);
}
public void WriteLocalReference(string text, object reference, bool isDefinition = false)
{
Write(text);
}
void ITextOutput.MarkFoldStart(string collapsedText, bool defaultCollapsed)
{
}

86
ICSharpCode.Decompiler/Output/TextTokenWriter.cs

@ -63,32 +63,34 @@ namespace ICSharpCode.Decompiler @@ -63,32 +63,34 @@ namespace ICSharpCode.Decompiler
}
var definition = GetCurrentDefinition();
if (definition != null) {
IMetadataEntity entity = SymbolToMetadata(definition);
if (entity != null) {
output.WriteDefinition(identifier.Name, entity, false);
switch (definition) {
case IType t:
output.WriteReference(t, identifier.Name, true);
return;
case IMember m:
output.WriteReference(m, identifier.Name, true);
return;
}
}
var member = GetCurrentMemberReference();
if (member != null) {
IMetadataEntity entity = SymbolToMetadata(member);
if (entity != null) {
output.WriteReference(identifier.Name, entity);
switch (member) {
case IType t:
output.WriteReference(t, identifier.Name, false);
return;
case IMember m:
output.WriteReference(m, identifier.Name, false);
return;
}
}
var localDefinition = GetCurrentLocalDefinition();
if (localDefinition != null) {
output.WriteDefinition(identifier.Name, localDefinition);
output.WriteLocalReference(identifier.Name, localDefinition, isDefinition: true);
return;
}
var localRef = GetCurrentLocalReference();
if (localRef != null) {
output.WriteReference(identifier.Name, localRef, true);
output.WriteLocalReference(identifier.Name, localRef);
return;
}
@ -100,35 +102,6 @@ namespace ICSharpCode.Decompiler @@ -100,35 +102,6 @@ namespace ICSharpCode.Decompiler
output.Write(identifier.Name);
}
IMetadataEntity SymbolToMetadata(ISymbol symbol)
{
switch (symbol) {
case IType type:
var definition = type.GetDefinition();
if (definition == null || definition.MetadataToken.IsNil)
return null;
return new TypeDefinition(typeSystem.GetModuleDefinition(definition.ParentAssembly), (SRM.TypeDefinitionHandle)definition.MetadataToken);
case IMethod method:
if (method.MetadataToken.IsNil)
return null;
return new MethodDefinition(typeSystem.GetModuleDefinition(method.ParentAssembly), (SRM.MethodDefinitionHandle)method.MetadataToken);
case IProperty property:
if (property.MetadataToken.IsNil)
return null;
return new PropertyDefinition(typeSystem.GetModuleDefinition(property.ParentAssembly), (SRM.PropertyDefinitionHandle)property.MetadataToken);
case IEvent @event:
if (@event.MetadataToken.IsNil)
return null;
return new EventDefinition(typeSystem.GetModuleDefinition(@event.ParentAssembly), (SRM.EventDefinitionHandle)@event.MetadataToken);
case IField field:
if (field.MetadataToken.IsNil)
return null;
return new FieldDefinition(typeSystem.GetModuleDefinition(field.ParentAssembly), (SRM.FieldDefinitionHandle)field.MetadataToken);
default:
return null;
}
}
ISymbol GetCurrentMemberReference()
{
AstNode node = nodeStack.Peek();
@ -219,11 +192,8 @@ namespace ICSharpCode.Decompiler @@ -219,11 +192,8 @@ namespace ICSharpCode.Decompiler
//To make reference for 'this' and 'base' keywords in the ClassName():this() expression
if (role == ConstructorInitializer.ThisKeywordRole || role == ConstructorInitializer.BaseKeywordRole) {
if (nodeStack.Peek() is ConstructorInitializer initializer && initializer.GetSymbol() is IMember member) {
var entity = SymbolToMetadata(member);
if (entity != null) {
output.WriteReference(keyword, entity);
return;
}
output.WriteReference(member, keyword);
return;
}
}
output.Write(keyword);
@ -254,11 +224,18 @@ namespace ICSharpCode.Decompiler @@ -254,11 +224,18 @@ namespace ICSharpCode.Decompiler
break;
default:
// Attach member reference to token only if there's no identifier in the current node.
var member = SymbolToMetadata(GetCurrentMemberReference());
var member = GetCurrentMemberReference();
var node = nodeStack.Peek();
if (member != null && node.GetChildByRole(Roles.Identifier).IsNull)
output.WriteReference(token, member);
else
if (member != null && node.GetChildByRole(Roles.Identifier).IsNull) {
switch (member) {
case IType t:
output.WriteReference(t, token, false);
return;
case IMember m:
output.WriteReference(m, token, false);
return;
}
} else
output.Write(token);
break;
}
@ -368,7 +345,14 @@ namespace ICSharpCode.Decompiler @@ -368,7 +345,14 @@ namespace ICSharpCode.Decompiler
symbol = nodeStack.Peek().GetSymbol();
}
if (symbol == null) goto default;
output.WriteReference(type, SymbolToMetadata(symbol));
switch (symbol) {
case IType t:
output.WriteReference(t, type, false);
return;
case IMember m:
output.WriteReference(m, type, false);
return;
}
break;
default:
output.Write(type);

12
ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs

@ -26,6 +26,7 @@ using ICSharpCode.Decompiler.Util; @@ -26,6 +26,7 @@ using ICSharpCode.Decompiler.Util;
using static ICSharpCode.Decompiler.Metadata.MetadataExtensions;
using System.Diagnostics;
using System.Collections.Immutable;
using ICSharpCode.Decompiler.Metadata;
namespace ICSharpCode.Decompiler.TypeSystem
{
@ -77,18 +78,21 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -77,18 +78,21 @@ namespace ICSharpCode.Decompiler.TypeSystem
{
readonly Metadata.PEFile moduleDefinition;
readonly ICompilation compilation;
readonly IAssemblyResolver assemblyResolver;
readonly TypeSystemOptions typeSystemOptions;
readonly MetadataAssembly mainAssembly;
public DecompilerTypeSystem(Metadata.PEFile moduleDefinition) : this(moduleDefinition, new DecompilerSettings())
public DecompilerTypeSystem(Metadata.PEFile moduleDefinition, IAssemblyResolver assemblyResolver)
: this(moduleDefinition, assemblyResolver, new DecompilerSettings())
{
}
public DecompilerTypeSystem(Metadata.PEFile moduleDefinition, DecompilerSettings settings)
public DecompilerTypeSystem(PEFile moduleDefinition, IAssemblyResolver assemblyResolver, DecompilerSettings settings)
{
if (settings == null)
throw new ArgumentNullException(nameof(settings));
this.moduleDefinition = moduleDefinition;
this.moduleDefinition = moduleDefinition ?? throw new ArgumentNullException(nameof(moduleDefinition));
this.assemblyResolver = assemblyResolver ?? throw new ArgumentNullException(nameof(assemblyResolver));
typeSystemOptions = TypeSystemOptions.None;
if (settings.Dynamic)
typeSystemOptions |= TypeSystemOptions.Dynamic;
@ -106,7 +110,7 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -106,7 +110,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
var asmRef = assemblyReferenceQueue.Dequeue();
if (!processedAssemblyReferences.Add(asmRef))
continue;
var asm = moduleDefinition.AssemblyResolver.Resolve(asmRef);
var asm = assemblyResolver.Resolve(asmRef);
if (asm != null) {
referencedAssemblies.Add(asm.WithOptions(typeSystemOptions));
var metadata = asm.Metadata;

6
ICSharpCode.Decompiler/TypeSystem/IAssembly.cs

@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
using System.Collections.Generic;
using System.Reflection.Metadata;
using ICSharpCode.Decompiler.Metadata;
namespace ICSharpCode.Decompiler.TypeSystem
{
@ -65,6 +66,11 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -65,6 +66,11 @@ namespace ICSharpCode.Decompiler.TypeSystem
/// </summary>
public interface IAssembly : ICompilationProvider
{
/// <summary>
/// Gets the underlying metadata file. May return null, if the IAssembly was not created from a PE file.
/// </summary>
PEFile PEFile { get; }
/// <summary>
/// Gets whether this assembly is the main assembly of the compilation.
/// </summary>

2
ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultUnresolvedAssembly.cs

@ -329,6 +329,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -329,6 +329,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
this.AssemblyAttributes = unresolved.AssemblyAttributes.CreateResolvedAttributes(context);
this.ModuleAttributes = unresolved.ModuleAttributes.CreateResolvedAttributes(context);
}
public Metadata.PEFile PEFile => null;
public IUnresolvedAssembly UnresolvedAssembly {
get { return unresolvedAssembly; }

3
ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeDefinition.cs

@ -212,9 +212,10 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -212,9 +212,10 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
var metadata = assembly.metadata;
var methodsCollection = metadata.GetTypeDefinition(handle).GetMethods();
var methodsList = new List<IMethod>(methodsCollection.Count);
var methodSemantics = assembly.PEFile.MethodSemanticsLookup;
foreach (MethodDefinitionHandle h in methodsCollection) {
var md = metadata.GetMethodDefinition(h);
if (assembly.IsVisible(md.Attributes)) {
if (methodSemantics.GetSemantics(h).Item2 == 0 && assembly.IsVisible(md.Attributes)) {
methodsList.Add(assembly.GetDefinition(h));
}
}

6
ICSharpCode.Decompiler/TypeSystem/MetadataAssembly.cs

@ -38,7 +38,6 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -38,7 +38,6 @@ namespace ICSharpCode.Decompiler.TypeSystem
public class MetadataAssembly : IAssembly
{
public ICompilation Compilation { get; }
internal readonly Metadata.PEFile PEFile;
internal readonly MetadataReader metadata;
readonly TypeSystemOptions options;
internal readonly TypeProvider TypeProvider;
@ -86,6 +85,8 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -86,6 +85,8 @@ namespace ICSharpCode.Decompiler.TypeSystem
public TypeSystemOptions TypeSystemOptions => options;
#region IAssembly interface
public PEFile PEFile { get; }
public bool IsMainAssembly => this == Compilation.MainAssembly;
public string AssemblyName { get; }
@ -581,8 +582,9 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -581,8 +582,9 @@ namespace ICSharpCode.Decompiler.TypeSystem
IType ResolveForwardedType(ExportedType forwarder)
{
IAssembly assembly = ResolveAssembly(forwarder);
Debug.Assert(assembly != null);
var typeName = forwarder.GetFullTypeName(metadata);
if (assembly == null)
return new UnknownType(typeName);
using (var busyLock = BusyManager.Enter(this)) {
if (busyLock.Success) {
var td = assembly.GetTypeDefinition(typeName);

5
ILSpy.BamlDecompiler.Tests/BamlTestRunner.cs

@ -114,16 +114,15 @@ namespace ILSpy.BamlDecompiler.Tests @@ -114,16 +114,15 @@ namespace ILSpy.BamlDecompiler.Tests
{
using (var fileStream = new FileStream(asmPath, FileMode.Open, FileAccess.Read)) {
var module = new PEFile(asmPath, fileStream);
var resolver = (UniversalAssemblyResolver)module.AssemblyResolver;
var resolver = new UniversalAssemblyResolver(asmPath, false, module.Reader.DetectTargetFrameworkId());
resolver.RemoveSearchDirectory(".");
resolver.AddSearchDirectory(Path.GetDirectoryName(asmPath));
var res = module.Resources.First();
Stream bamlStream = LoadBaml(res, name + ".baml");
Assert.IsNotNull(bamlStream);
XDocument document = BamlResourceEntryNode.LoadIntoDocument(module, bamlStream, CancellationToken.None);
XDocument document = BamlResourceEntryNode.LoadIntoDocument(module, resolver, bamlStream, CancellationToken.None);
XamlIsEqual(File.ReadAllText(sourcePath), document.ToString());
}
}

14
ILSpy.BamlDecompiler/BamlResourceEntryNode.cs

@ -50,30 +50,32 @@ namespace ILSpy.BamlDecompiler @@ -50,30 +50,32 @@ namespace ILSpy.BamlDecompiler
{
var asm = this.Ancestors().OfType<AssemblyTreeNode>().FirstOrDefault().LoadedAssembly;
Data.Position = 0;
XDocument xamlDocument = LoadIntoDocument(asm.GetPEFileOrNull(), Data, cancellationToken);
XDocument xamlDocument = LoadIntoDocument(asm.GetPEFileOrNull(), asm.GetAssemblyResolver(), Data, cancellationToken);
output.Write(xamlDocument.ToString());
return true;
}
internal static XDocument LoadIntoDocument(PEFile module, Stream stream, CancellationToken cancellationToken)
internal static XDocument LoadIntoDocument(PEFile module, IAssemblyResolver assemblyResolver,
Stream stream, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
XDocument xamlDocument;
using (XmlBamlReader reader = new XmlBamlReader(stream, new NRTypeResolver(module))) {
using (XmlBamlReader reader = new XmlBamlReader(stream, new NRTypeResolver(module, assemblyResolver))) {
xamlDocument = XDocument.Load(reader);
ConvertConnectionIds(xamlDocument, module, cancellationToken);
ConvertConnectionIds(xamlDocument, module, assemblyResolver, cancellationToken);
ConvertToEmptyElements(xamlDocument.Root);
MoveNamespacesToRoot(xamlDocument, reader.XmlnsDefinitions);
return xamlDocument;
}
}
static void ConvertConnectionIds(XDocument xamlDocument, PEFile asm, CancellationToken cancellationToken)
static void ConvertConnectionIds(XDocument xamlDocument, PEFile asm, IAssemblyResolver assemblyResolver,
CancellationToken cancellationToken)
{
var attr = xamlDocument.Root.Attribute(XName.Get("Class", XmlBamlReader.XWPFNamespace));
if (attr != null) {
string fullTypeName = attr.Value;
var mappings = new ConnectMethodDecompiler().DecompileEventMappings(asm, fullTypeName, cancellationToken);
var mappings = new ConnectMethodDecompiler().DecompileEventMappings(asm, assemblyResolver, fullTypeName, cancellationToken);
RemoveConnectionIds(xamlDocument.Root, mappings);
}
}

2
ILSpy.BamlDecompiler/BamlResourceNodeFactory.cs

@ -36,7 +36,7 @@ namespace ILSpy.BamlDecompiler @@ -36,7 +36,7 @@ namespace ILSpy.BamlDecompiler
public string WriteResourceToFile(LoadedAssembly assembly, string fileName, Stream stream, DecompilationOptions options)
{
var document = BamlResourceEntryNode.LoadIntoDocument(assembly.GetPEFileOrNull(), stream, options.CancellationToken);
var document = BamlResourceEntryNode.LoadIntoDocument(assembly.GetPEFileOrNull(), assembly.GetAssemblyResolver(), stream, options.CancellationToken);
fileName = Path.ChangeExtension(fileName, ".xaml");
document.Save(Path.Combine(options.SaveAsProjectDirectory, fileName));
return fileName;

7
ILSpy.BamlDecompiler/CecilTypeResolver.cs

@ -4,6 +4,7 @@ @@ -4,6 +4,7 @@
using System;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.ILSpy;
using Ricciolo.StylesExplorer.MarkupReflection;
namespace ILSpy.BamlDecompiler
@ -17,10 +18,10 @@ namespace ILSpy.BamlDecompiler @@ -17,10 +18,10 @@ namespace ILSpy.BamlDecompiler
readonly DecompilerTypeSystem typeSystem;
readonly ICompilation compilation;
public NRTypeResolver(PEFile module)
public NRTypeResolver(PEFile module, IAssemblyResolver resolver)
{
this.module = module;
this.typeSystem = new DecompilerTypeSystem(module);
this.module = module ?? throw new ArgumentNullException(nameof(module));
this.typeSystem = new DecompilerTypeSystem(module, resolver);
this.compilation = typeSystem.Compilation;
}

38
ILSpy.BamlDecompiler/ConnectMethodDecompiler.cs

@ -3,17 +3,17 @@ @@ -3,17 +3,17 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Reflection.Metadata;
using System.Threading;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.CSharp;
using ICSharpCode.Decompiler.Documentation;
using ICSharpCode.Decompiler.IL;
using ICSharpCode.Decompiler.IL.Transforms;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.TypeSystem.Implementation;
using ICSharpCode.Decompiler.Util;
using ICSharpCode.ILSpy;
using Metadata = ICSharpCode.Decompiler.Metadata;
namespace ILSpy.BamlDecompiler
@ -31,38 +31,36 @@ namespace ILSpy.BamlDecompiler @@ -31,38 +31,36 @@ namespace ILSpy.BamlDecompiler
/// </summary>
sealed class ConnectMethodDecompiler
{
public List<(LongSet, EventRegistration[])> DecompileEventMappings(Metadata.PEFile module, string fullTypeName, CancellationToken cancellationToken)
public List<(LongSet, EventRegistration[])> DecompileEventMappings(Metadata.PEFile module, IAssemblyResolver assemblyResolver,
string fullTypeName, CancellationToken cancellationToken)
{
var result = new List<(LongSet, EventRegistration[])>();
var typeSystem = new DecompilerTypeSystem(module, assemblyResolver);
var typeDefinition = (Metadata.TypeDefinition)XmlDocKeyProvider.FindMemberByKey(module, "T:" + fullTypeName);
if (typeDefinition.IsNil)
var typeDefinition = typeSystem.Compilation.FindType(new FullTypeName(fullTypeName)).GetDefinition();
if (typeDefinition == null)
return result;
var metadata = module.Metadata;
TypeDefinition type = metadata.GetTypeDefinition(typeDefinition.Handle);
MethodDefinition method = default;
MethodDefinitionHandle handle = default;
IMethod method = null;
MethodDefinition metadataEntry = default;
foreach (var h in type.GetMethods()) {
var m = metadata.GetMethodDefinition(h);
if (metadata.GetString(m.Name) == "System.Windows.Markup.IComponentConnector.Connect") {
handle = h;
foreach (var m in typeDefinition.GetMethods()) {
if (m.Name == "System.Windows.Markup.IComponentConnector.Connect") {
method = m;
metadataEntry = module.Metadata.GetMethodDefinition((MethodDefinitionHandle)method.MetadataToken);
break;
}
}
if (handle.IsNil)
if (method == null || metadataEntry.RelativeVirtualAddress <= 0)
return result;
// decompile method and optimize the switch
var typeSystem = new DecompilerTypeSystem(typeDefinition.Module);
var ilReader = new ILReader(typeSystem);
var function = ilReader.ReadIL(typeDefinition.Module, handle, typeDefinition.Module.Reader.GetMethodBody(method.RelativeVirtualAddress), cancellationToken);
var function = ilReader.ReadIL(module, (MethodDefinitionHandle)method.MetadataToken,
module.Reader.GetMethodBody(metadataEntry.RelativeVirtualAddress), cancellationToken);
var context = new ILTransformContext(function, typeSystem) {
var context = new ILTransformContext(function, typeSystem, null) {
CancellationToken = cancellationToken
};
function.RunTransforms(CSharpDecompiler.GetILTransforms(), context);

4
ILSpy/AnalyzerTreeView.cs

@ -86,7 +86,7 @@ namespace ICSharpCode.ILSpy @@ -86,7 +86,7 @@ namespace ICSharpCode.ILSpy
public void ShowOrFocus(AnalyzerTreeNode node)
{
if (node is AnalyzerEntityTreeNode) {
/*if (node is AnalyzerEntityTreeNode) {
var an = node as AnalyzerEntityTreeNode;
var found = this.Root.Children.OfType<AnalyzerEntityTreeNode>().FirstOrDefault(n => n.Member == an.Member);
if (found != null) {
@ -98,7 +98,7 @@ namespace ICSharpCode.ILSpy @@ -98,7 +98,7 @@ namespace ICSharpCode.ILSpy
return;
}
}
Show(node);
Show(node);*/
}
void IPane.Closed()

2
ILSpy/Commands/DecompileAllCommand.cs

@ -45,7 +45,7 @@ namespace ICSharpCode.ILSpy @@ -45,7 +45,7 @@ namespace ICSharpCode.ILSpy
Exception exception = null;
using (var writer = new System.IO.StreamWriter("c:\\temp\\decompiled\\" + asm.ShortName + ".cs")) {
try {
new CSharpLanguage().DecompileAssembly(asm, new Decompiler.PlainTextOutput(writer), new DecompilationOptions() { FullDecompilation = true, CancellationToken = ct });
//new CSharpLanguage().DecompileAssembly(asm, new Decompiler.PlainTextOutput(writer), new DecompilationOptions() { FullDecompilation = true, CancellationToken = ct });
}
catch (Exception ex) {
writer.WriteLine(ex.ToString());

9
ILSpy/DebugInfo/DiaSymNativeDebugInfoProvider.cs

@ -25,6 +25,7 @@ using System.Reflection.Metadata; @@ -25,6 +25,7 @@ using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using System.Text;
using System.Threading.Tasks;
using ICSharpCode.Decompiler.DebugInfo;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.Util;
using Microsoft.DiaSymReader;
@ -48,12 +49,12 @@ namespace ICSharpCode.ILSpy.DebugInfo @@ -48,12 +49,12 @@ namespace ICSharpCode.ILSpy.DebugInfo
this.reader = SymUnmanagedReaderFactory.CreateReader<ISymUnmanagedReader5>(stream, this);
}
public IList<Decompiler.Metadata.SequencePoint> GetSequencePoints(MethodDefinitionHandle handle)
public IList<Decompiler.DebugInfo.SequencePoint> GetSequencePoints(MethodDefinitionHandle handle)
{
var method = reader.GetMethod(MetadataTokens.GetToken(handle));
if (method == null || method.GetSequencePointCount(out int count) != 0)
return Empty<Decompiler.Metadata.SequencePoint>.Array;
var sequencePoints = new Decompiler.Metadata.SequencePoint[count];
return Empty<Decompiler.DebugInfo.SequencePoint>.Array;
var sequencePoints = new Decompiler.DebugInfo.SequencePoint[count];
var points = method.GetSequencePoints();
int i = 0;
var buffer = new char[1024];
@ -64,7 +65,7 @@ namespace ICSharpCode.ILSpy.DebugInfo @@ -64,7 +65,7 @@ namespace ICSharpCode.ILSpy.DebugInfo
} else {
url = "";
}
sequencePoints[i] = new Decompiler.Metadata.SequencePoint() {
sequencePoints[i] = new Decompiler.DebugInfo.SequencePoint() {
Offset = point.Offset,
StartLine = point.StartLine,
StartColumn = point.StartColumn,

7
ILSpy/DebugInfo/PortableDebugInfoProvider.cs

@ -19,6 +19,7 @@ @@ -19,6 +19,7 @@
using System;
using System.Collections.Generic;
using System.Reflection.Metadata;
using ICSharpCode.Decompiler.DebugInfo;
using ICSharpCode.Decompiler.Metadata;
namespace ICSharpCode.ILSpy.DebugInfo
@ -34,11 +35,11 @@ namespace ICSharpCode.ILSpy.DebugInfo @@ -34,11 +35,11 @@ namespace ICSharpCode.ILSpy.DebugInfo
this.provider = provider;
}
public IList<Decompiler.Metadata.SequencePoint> GetSequencePoints(MethodDefinitionHandle method)
public IList<Decompiler.DebugInfo.SequencePoint> GetSequencePoints(MethodDefinitionHandle method)
{
var metadata = provider.GetMetadataReader();
var debugInfo = metadata.GetMethodDebugInformation(method);
var sequencePoints = new List<Decompiler.Metadata.SequencePoint>();
var sequencePoints = new List<Decompiler.DebugInfo.SequencePoint>();
foreach (var point in debugInfo.GetSequencePoints()) {
string documentFileName;
@ -50,7 +51,7 @@ namespace ICSharpCode.ILSpy.DebugInfo @@ -50,7 +51,7 @@ namespace ICSharpCode.ILSpy.DebugInfo
documentFileName = "";
}
sequencePoints.Add(new Decompiler.Metadata.SequencePoint() {
sequencePoints.Add(new Decompiler.DebugInfo.SequencePoint() {
Offset = point.Offset,
StartLine = point.StartLine,
StartColumn = point.StartColumn,

4
ILSpy/DebugSteps.xaml.cs

@ -7,10 +7,6 @@ using ICSharpCode.Decompiler.IL.Transforms; @@ -7,10 +7,6 @@ using ICSharpCode.Decompiler.IL.Transforms;
namespace ICSharpCode.ILSpy
{
/// <summary>
/// Interaktionslogik für DebugSteps.xaml
/// </summary>
public partial class DebugSteps : UserControl, IPane
{
static readonly ILAstWritingOptions writingOptions = new ILAstWritingOptions {

19
ILSpy/ILSpy.csproj

@ -113,8 +113,6 @@ @@ -113,8 +113,6 @@
</Compile>
<Compile Include="ILSpyTraceListener.cs" />
<Compile Include="Languages\CodeMappingInfo.cs" />
<Compile Include="Languages\CSharpILMixedLanguage.cs" />
<Compile Include="Languages\CSharpLanguage.cs" />
<Compile Include="DecompilationOptions.cs" />
<Compile Include="ExtensionMethods.cs" />
<Compile Include="FilterSettings.cs" />
@ -122,9 +120,10 @@ @@ -122,9 +120,10 @@
<Compile Include="GacInterop.cs" />
<Compile Include="GuessFileType.cs" />
<Compile Include="ContextMenuEntry.cs" />
<Compile Include="Languages\CSharpILMixedLanguage.cs" />
<Compile Include="Languages\CSharpLanguage.cs" />
<Compile Include="Languages\CSharpLexer.cs" />
<Compile Include="Languages\CSharpHighlightingTokenWriter.cs" />
<Compile Include="Languages\ILAstLanguage.cs" />
<Compile Include="ILSpySettings.cs" />
<Compile Include="Images\AccessOverlayIcon.cs" />
<Compile Include="Images\MemberIcon.cs" />
@ -132,12 +131,13 @@ @@ -132,12 +131,13 @@
<Compile Include="IPane.cs" />
<Compile Include="ISmartTextOutput.cs" />
<Compile Include="Images\Images.cs" />
<Compile Include="Languages\ILAstLanguage.cs" />
<Compile Include="Languages\ILLanguage.cs" />
<Compile Include="Languages\ILSignatureProvider.cs" />
<Compile Include="Languages\IResourceFileHandler.cs" />
<Compile Include="Languages\Language.cs" />
<Compile Include="Languages\Languages.cs" />
<Compile Include="LoadedAssembly.cs" />
<Compile Include="LoadedAssemblyExtensions.cs" />
<Compile Include="LoadedNugetPackage.cs" />
<Compile Include="NativeMethods.cs" />
<Compile Include="NavigationHistory.cs" />
@ -190,17 +190,6 @@ @@ -190,17 +190,6 @@
<Compile Include="TextView\FoldingCommands.cs" />
<Compile Include="TextView\XmlDocRenderer.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzeContextMenuEntry.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzedFieldAccessTreeNode.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzedFieldTreeNode.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzedMethodTreeNode.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzedMethodUsedByTreeNode.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzedMethodUsesTreeNode.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzedPropertyAccessorTreeNode.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzedPropertyTreeNode.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzedTypeInstantiationsTreeNode.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzedTypeTreeNode.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzedTypeUsedByTreeNode.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzerEntityTreeNode.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzerSearchTreeNode.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzerTreeNode.cs" />
<Compile Include="TreeNodes\Analyzer\Extensions.cs" />

4
ILSpy/Languages/CSharpILMixedLanguage.cs

@ -38,7 +38,7 @@ using ICSharpCode.Decompiler.Util; @@ -38,7 +38,7 @@ using ICSharpCode.Decompiler.Util;
namespace ICSharpCode.ILSpy
{
using SequencePoint = ICSharpCode.Decompiler.Metadata.SequencePoint;
using SequencePoint = ICSharpCode.Decompiler.DebugInfo.SequencePoint;
[Export(typeof(Language))]
class CSharpILMixedLanguage : ILLanguage
@ -57,7 +57,7 @@ namespace ICSharpCode.ILSpy @@ -57,7 +57,7 @@ namespace ICSharpCode.ILSpy
static CSharpDecompiler CreateDecompiler(PEFile module, DecompilationOptions options)
{
CSharpDecompiler decompiler = new CSharpDecompiler(module, options.DecompilerSettings);
CSharpDecompiler decompiler = new CSharpDecompiler(module, module.GetAssemblyResolver(), options.DecompilerSettings);
decompiler.CancellationToken = options.CancellationToken;
return decompiler;
}

433
ILSpy/Languages/CSharpLanguage.cs

@ -110,9 +110,9 @@ namespace ICSharpCode.ILSpy @@ -110,9 +110,9 @@ namespace ICSharpCode.ILSpy
}
}
CSharpDecompiler CreateDecompiler(Decompiler.Metadata.PEFile module, DecompilationOptions options)
CSharpDecompiler CreateDecompiler(PEFile module, DecompilationOptions options)
{
CSharpDecompiler decompiler = new CSharpDecompiler(module, options.DecompilerSettings);
CSharpDecompiler decompiler = new CSharpDecompiler(module, module.GetAssemblyResolver(), options.DecompilerSettings);
decompiler.CancellationToken = options.CancellationToken;
while (decompiler.AstTransforms.Count > transformCount)
decompiler.AstTransforms.RemoveAt(decompiler.AstTransforms.Count - 1);
@ -129,19 +129,19 @@ namespace ICSharpCode.ILSpy @@ -129,19 +129,19 @@ namespace ICSharpCode.ILSpy
syntaxTree.AcceptVisitor(new CSharpOutputVisitor(tokenWriter, settings.CSharpFormattingOptions));
}
public override void DecompileMethod(Decompiler.Metadata.MethodDefinition method, ITextOutput output, DecompilationOptions options)
public override void DecompileMethod(IMethod method, ITextOutput output, DecompilationOptions options)
{
AddReferenceWarningMessage(method.Module, output);
var md = method.Module.Metadata.GetMethodDefinition(method.Handle);
WriteCommentLine(output, TypeToString(new Entity(method.Module, md.GetDeclaringType()), includeNamespace: true));
CSharpDecompiler decompiler = CreateDecompiler(method.Module, options);
var methodDefinition = decompiler.TypeSystem.ResolveAsMethod(method.Handle);
PEFile assembly = method.ParentAssembly.PEFile;
AddReferenceWarningMessage(assembly, output);
WriteCommentLine(output, TypeToString(method.DeclaringType, includeNamespace: true));
CSharpDecompiler decompiler = CreateDecompiler(assembly, options);
var methodDefinition = decompiler.TypeSystem.ResolveAsMethod(method.MetadataToken);
if (methodDefinition.IsConstructor && methodDefinition.DeclaringType.IsReferenceType != false) {
var members = CollectFieldsAndCtors(methodDefinition.DeclaringTypeDefinition, methodDefinition.IsStatic);
decompiler.AstTransforms.Add(new SelectCtorTransform(methodDefinition));
WriteCode(output, options.DecompilerSettings, decompiler.Decompile(members), decompiler.TypeSystem);
} else {
WriteCode(output, options.DecompilerSettings, decompiler.Decompile(method.Handle), decompiler.TypeSystem);
WriteCode(output, options.DecompilerSettings, decompiler.Decompile(method.MetadataToken), decompiler.TypeSystem);
}
}
@ -196,28 +196,26 @@ namespace ICSharpCode.ILSpy @@ -196,28 +196,26 @@ namespace ICSharpCode.ILSpy
}
}
public override void DecompileProperty(Decompiler.Metadata.PropertyDefinition property, ITextOutput output, DecompilationOptions options)
public override void DecompileProperty(IProperty property, ITextOutput output, DecompilationOptions options)
{
AddReferenceWarningMessage(property.Module, output);
CSharpDecompiler decompiler = CreateDecompiler(property.Module, options);
var metadata = property.Module.Metadata;
var accessorHandle = metadata.GetPropertyDefinition(property.Handle).GetAccessors().GetAny();
WriteCommentLine(output, TypeToString(new Decompiler.Metadata.TypeDefinition(property.Module, metadata.GetMethodDefinition(accessorHandle).GetDeclaringType()), includeNamespace: true));
WriteCode(output, options.DecompilerSettings, decompiler.Decompile(property.Handle), decompiler.TypeSystem);
PEFile assembly = property.ParentAssembly.PEFile;
AddReferenceWarningMessage(assembly, output);
CSharpDecompiler decompiler = CreateDecompiler(assembly, options);
WriteCommentLine(output, TypeToString(property.DeclaringType, includeNamespace: true));
WriteCode(output, options.DecompilerSettings, decompiler.Decompile(property.MetadataToken), decompiler.TypeSystem);
}
public override void DecompileField(Decompiler.Metadata.FieldDefinition field, ITextOutput output, DecompilationOptions options)
public override void DecompileField(IField field, ITextOutput output, DecompilationOptions options)
{
AddReferenceWarningMessage(field.Module, output);
var fd = field.Module.Metadata.GetFieldDefinition(field.Handle);
WriteCommentLine(output, TypeToString(new Decompiler.Metadata.TypeDefinition(field.Module, fd.GetDeclaringType()), includeNamespace: true));
CSharpDecompiler decompiler = CreateDecompiler(field.Module, options);
var fieldDefinition = decompiler.TypeSystem.ResolveAsField(field.Handle);
if (fd.HasFlag(FieldAttributes.Literal)) {
WriteCode(output, options.DecompilerSettings, decompiler.Decompile(field.Handle), decompiler.TypeSystem);
PEFile assembly = field.ParentAssembly.PEFile;
AddReferenceWarningMessage(assembly, output);
WriteCommentLine(output, TypeToString(field.DeclaringType, includeNamespace: true));
CSharpDecompiler decompiler = CreateDecompiler(assembly, options);
if (field.IsConst) {
WriteCode(output, options.DecompilerSettings, decompiler.Decompile(field.MetadataToken), decompiler.TypeSystem);
} else {
var members = CollectFieldsAndCtors(fieldDefinition.DeclaringTypeDefinition, fieldDefinition.IsStatic);
decompiler.AstTransforms.Add(new SelectFieldTransform(fieldDefinition));
var members = CollectFieldsAndCtors(field.DeclaringTypeDefinition, field.IsStatic);
decompiler.AstTransforms.Add(new SelectFieldTransform(field));
WriteCode(output, options.DecompilerSettings, decompiler.Decompile(members), decompiler.TypeSystem);
}
}
@ -266,25 +264,25 @@ namespace ICSharpCode.ILSpy @@ -266,25 +264,25 @@ namespace ICSharpCode.ILSpy
}
}
public override void DecompileEvent(Decompiler.Metadata.EventDefinition ev, ITextOutput output, DecompilationOptions options)
public override void DecompileEvent(IEvent @event, ITextOutput output, DecompilationOptions options)
{
AddReferenceWarningMessage(ev.Module, output);
var metadata = ev.Module.Metadata;
var accessorHandle = metadata.GetEventDefinition(ev.Handle).GetAccessors().GetAny();
base.WriteCommentLine(output, TypeToString(new Decompiler.Metadata.TypeDefinition(ev.Module, metadata.GetMethodDefinition(accessorHandle).GetDeclaringType()), includeNamespace: true));
CSharpDecompiler decompiler = CreateDecompiler(ev.Module, options);
WriteCode(output, options.DecompilerSettings, decompiler.Decompile(ev.Handle), decompiler.TypeSystem);
PEFile assembly = @event.ParentAssembly.PEFile;
AddReferenceWarningMessage(assembly, output);
base.WriteCommentLine(output, TypeToString(@event.DeclaringType, includeNamespace: true));
CSharpDecompiler decompiler = CreateDecompiler(assembly, options);
WriteCode(output, options.DecompilerSettings, decompiler.Decompile(@event.MetadataToken), decompiler.TypeSystem);
}
public override void DecompileType(Decompiler.Metadata.TypeDefinition type, ITextOutput output, DecompilationOptions options)
public override void DecompileType(ITypeDefinition type, ITextOutput output, DecompilationOptions options)
{
AddReferenceWarningMessage(type.Module, output);
PEFile assembly = type.ParentAssembly.PEFile;
AddReferenceWarningMessage(assembly, output);
WriteCommentLine(output, TypeToString(type, includeNamespace: true));
CSharpDecompiler decompiler = CreateDecompiler(type.Module, options);
WriteCode(output, options.DecompilerSettings, decompiler.Decompile(type.Handle), decompiler.TypeSystem);
CSharpDecompiler decompiler = CreateDecompiler(assembly, options);
WriteCode(output, options.DecompilerSettings, decompiler.Decompile(type.MetadataToken), decompiler.TypeSystem);
}
void AddReferenceWarningMessage(Decompiler.Metadata.PEFile assembly, ITextOutput output)
void AddReferenceWarningMessage(PEFile assembly, ITextOutput output)
{
var loadedAssembly = MainWindow.Instance.CurrentAssemblyList.GetAssemblies().FirstOrDefault(la => la.GetPEFileOrNull() == assembly);
if (loadedAssembly == null || !loadedAssembly.LoadedAssemblyReferencesInfo.HasErrors)
@ -320,7 +318,7 @@ namespace ICSharpCode.ILSpy @@ -320,7 +318,7 @@ namespace ICSharpCode.ILSpy
public override void DecompileAssembly(LoadedAssembly assembly, ITextOutput output, DecompilationOptions options)
{
var module = assembly.GetPEFileAsync().Result;
var module = assembly.GetPEFileOrNull();
if (options.FullDecompilation && options.SaveAsProjectDirectory != null) {
var decompiler = new ILSpyWholeProjectDecompiler(assembly, options);
decompiler.DecompileProject(module, options.SaveAsProjectDirectory, new TextOutputWriter(output), options.CancellationToken);
@ -328,23 +326,24 @@ namespace ICSharpCode.ILSpy @@ -328,23 +326,24 @@ namespace ICSharpCode.ILSpy
AddReferenceWarningMessage(module, output);
output.WriteLine();
base.DecompileAssembly(assembly, output, options);
var metadata = module.Metadata;
if (metadata.TypeDefinitions.Count > 0) {
IAssemblyResolver assemblyResolver = assembly.GetAssemblyResolver();
var typeSystem = new DecompilerTypeSystem(module, assemblyResolver, options.DecompilerSettings);
var globalType = typeSystem.MainAssembly.TypeDefinitions.FirstOrDefault();
if (globalType != null) {
output.Write("// Global type: ");
var globalType = metadata.TypeDefinitions.First();
output.WriteReference(globalType.GetFullTypeName(metadata).ToString(), new Decompiler.Metadata.TypeDefinition(module, globalType));
output.WriteReference(globalType, globalType.FullName);
output.WriteLine();
}
var metadata = module.Metadata;
var corHeader = module.Reader.PEHeaders.CorHeader;
var entrypointHandle = MetadataTokenHelpers.EntityHandleOrNil(corHeader.EntryPointTokenOrRelativeVirtualAddress);
if (!entrypointHandle.IsNil && entrypointHandle.Kind == HandleKind.MethodDefinition) {
var entrypoint = metadata.GetMethodDefinition((MethodDefinitionHandle)entrypointHandle);
output.Write("// Entry point: ");
string name = entrypoint.GetDeclaringType().GetFullTypeName(metadata) + "." + metadata.GetString(entrypoint.Name);
var entrypointEntity = new Decompiler.Metadata.MethodDefinition(module, (MethodDefinitionHandle)entrypointHandle);
output.WriteReference(name, entrypointEntity);
output.WriteLine();
var entrypoint = typeSystem.ResolveAsMethod(entrypointHandle);
if (entrypoint != null) {
output.Write("// Entry point: ");
output.WriteReference(entrypoint, entrypoint.DeclaringType.FullName + "." + entrypoint.Name);
output.WriteLine();
}
}
output.WriteLine("// Architecture: " + GetPlatformDisplayName(module));
if ((corHeader.Flags & System.Reflection.PortableExecutable.CorFlags.ILOnly) == 0) {
@ -358,7 +357,7 @@ namespace ICSharpCode.ILSpy @@ -358,7 +357,7 @@ namespace ICSharpCode.ILSpy
// don't automatically load additional assemblies when an assembly node is selected in the tree view
using (options.FullDecompilation ? null : LoadedAssembly.DisableAssemblyLoad()) {
CSharpDecompiler decompiler = new CSharpDecompiler(module, options.DecompilerSettings);
CSharpDecompiler decompiler = new CSharpDecompiler(typeSystem, assemblyResolver, options.DecompilerSettings);
decompiler.CancellationToken = options.CancellationToken;
SyntaxTree st;
if (options.FullDecompilation) {
@ -405,229 +404,102 @@ namespace ICSharpCode.ILSpy @@ -405,229 +404,102 @@ namespace ICSharpCode.ILSpy
}
}
public override string TypeToString(Entity type, Decompiler.Metadata.GenericContext genericContext = null, bool includeNamespace = true)
static readonly CSharpFormattingOptions TypeToStringFormattingOptions = FormattingOptionsFactory.CreateEmpty();
public override string TypeToString(IType type, bool includeNamespace)
{
if (type.Handle.IsNil)
if (type == null)
throw new ArgumentNullException(nameof(type));
var metadata = type.Module.Metadata;
ConvertTypeOptions convertTypeOptions = ConvertTypeOptions.IncludeTypeParameterDefinitions;
if (includeNamespace)
convertTypeOptions |= ConvertTypeOptions.IncludeNamespace;
//if (includeTypeName)
// convertTypeOptions |= ConvertTypeOptions.IncludeOuterTypeName;
var builder = new AstTypeBuilder(convertTypeOptions);
AstType astType;
switch (type.Handle.Kind) {
case HandleKind.TypeReference:
astType = builder.GetTypeFromReference(metadata, (TypeReferenceHandle)type.Handle, 0);
return TypeToString(astType, metadata, null);
case HandleKind.TypeDefinition:
var td = metadata.GetTypeDefinition((TypeDefinitionHandle)type.Handle);
var genericParams = td.GetGenericParameters();
var buffer = new System.Text.StringBuilder();
var name = td.GetFullTypeName(metadata);
if (includeNamespace)
buffer.Append(name.ToString());
else
buffer.Append(name.Name);
if (genericParams.Count > 0) {
buffer.Append('<');
int i = 0;
foreach (var h in genericParams) {
var gp = metadata.GetGenericParameter(h);
if (i > 0)
buffer.Append(", ");
buffer.Append(metadata.GetString(gp.Name));
i++;
}
buffer.Append('>');
}
return buffer.ToString();
case HandleKind.TypeSpecification:
var ts = metadata.GetTypeSpecification((TypeSpecificationHandle)type.Handle);
astType = builder.GetTypeFromSpecification(metadata, genericContext ?? GenericContext.Empty, (TypeSpecificationHandle)type.Handle, 0);
return TypeToString(astType, metadata, ts.GetCustomAttributes());
default:
throw new NotSupportedException();
if (type is ITypeDefinition definition && definition.TypeParameterCount > 0) {
return TypeToStringInternal(new ParameterizedType(definition, definition.TypeParameters), includeNamespace, false);
}
return TypeToStringInternal(type, includeNamespace, false);
}
public override string FieldToString(Decompiler.Metadata.FieldDefinition field, bool includeTypeName, bool includeNamespace)
string TypeToStringInternal(IType t, bool includeNamespace, bool useBuiltinTypeNames = true)
{
if (field.Handle.IsNil)
TypeSystemAstBuilder builder = new TypeSystemAstBuilder();
builder.AlwaysUseShortTypeNames = !includeNamespace;
builder.AlwaysUseBuiltinTypeNames = useBuiltinTypeNames;
AstType astType = builder.ConvertType(t);
StringWriter w = new StringWriter();
astType.AcceptVisitor(new CSharpOutputVisitor(w, TypeToStringFormattingOptions));
return w.ToString();
}
public override string FieldToString(IField field, bool includeTypeName, bool includeNamespace)
{
if (field == null)
throw new ArgumentNullException(nameof(field));
ConvertTypeOptions convertTypeOptions = ConvertTypeOptions.IncludeTypeParameterDefinitions;
if (includeNamespace)
convertTypeOptions |= ConvertTypeOptions.IncludeNamespace;
if (includeTypeName)
convertTypeOptions |= ConvertTypeOptions.IncludeOuterTypeName;
var metadata = field.Module.Metadata;
var fd = metadata.GetFieldDefinition(field.Handle);
AstType fieldType = fd.DecodeSignature(new AstTypeBuilder(convertTypeOptions), new GenericContext(fd.GetDeclaringType(), field.Module));
string simple = metadata.GetString(fd.Name) + " : " + TypeToString(fieldType, metadata, fd.GetCustomAttributes());
string simple = field.Name + " : " + TypeToString(field.Type, includeNamespace);
if (!includeTypeName)
return simple;
var typeName = fd.GetDeclaringType().GetFullTypeName(metadata);
if (!includeNamespace)
return typeName.Name + "." + simple;
return typeName + "." + simple;
return TypeToStringInternal(field.DeclaringTypeDefinition, includeNamespace) + "." + simple;
}
public override string PropertyToString(Decompiler.Metadata.PropertyDefinition property, bool includeTypeName, bool includeNamespace, bool? isIndexer = null)
public override string PropertyToString(IProperty property, bool includeTypeName, bool includeNamespace, bool? isIndexer = null)
{
if (property.IsNil)
if (property == null)
throw new ArgumentNullException(nameof(property));
ConvertTypeOptions convertTypeOptions = ConvertTypeOptions.IncludeTypeParameterDefinitions;
if (includeNamespace)
convertTypeOptions |= ConvertTypeOptions.IncludeNamespace;
if (includeTypeName)
convertTypeOptions |= ConvertTypeOptions.IncludeOuterTypeName;
var metadata = property.Module.Metadata;
var pd = metadata.GetPropertyDefinition(property.Handle);
var accessors = pd.GetAccessors();
var accessorHandle = accessors.GetAny();
var accessor = metadata.GetMethodDefinition(accessorHandle);
var declaringType = metadata.GetTypeDefinition(accessor.GetDeclaringType());
if (!isIndexer.HasValue) {
isIndexer = accessor.GetDeclaringType().GetDefaultMemberName(metadata) != null;
}
var buffer = new System.Text.StringBuilder();
if (isIndexer.Value) {
var overrides = accessorHandle.GetMethodImplementations(metadata);
if (overrides.Any()) {
string name = metadata.GetString(pd.Name);
if (property.IsExplicitInterfaceImplementation) {
string name = property.Name;
int index = name.LastIndexOf('.');
if (index > 0) {
buffer.Append(name.Substring(0, index));
buffer.Append(@".");
buffer.Append('.');
}
}
buffer.Append(@"this[");
var signature = pd.DecodeSignature(new AstTypeBuilder(convertTypeOptions), new GenericContext(accessorHandle, property.Module));
var parameterHandles = accessor.GetParameters();
int i = 0;
CustomAttributeHandleCollection? returnTypeAttributes = null;
if (signature.RequiredParameterCount > parameterHandles.Count) {
foreach (var type in signature.ParameterTypes) {
if (i > 0)
buffer.Append(", ");
buffer.Append(TypeToString(signature.ParameterTypes[i], metadata, null));
i++;
}
} else {
foreach (var h in parameterHandles) {
var p = metadata.GetParameter(h);
if (p.SequenceNumber > 0 && i < signature.ParameterTypes.Length) {
if (i > 0)
buffer.Append(", ");
buffer.Append(TypeToString(signature.ParameterTypes[i], metadata, p.GetCustomAttributes(), h));
i++;
}
if (p.SequenceNumber == 0) {
returnTypeAttributes = p.GetCustomAttributes();
}
}
}
if (signature.Header.CallingConvention == SignatureCallingConvention.VarArgs) {
if (signature.ParameterTypes.Length > 0)
var parameters = property.Parameters;
foreach (var param in parameters) {
if (i > 0)
buffer.Append(", ");
buffer.Append("...");
buffer.Append(TypeToStringInternal(param.Type, includeNamespace));
i++;
}
buffer.Append(@"]");
buffer.Append(" : ");
buffer.Append(TypeToString(signature.ReturnType, metadata, returnTypeAttributes));
} else {
var signature = pd.DecodeSignature(new AstTypeBuilder(convertTypeOptions), new GenericContext(accessorHandle, property.Module));
var parameterHandles = accessor.GetParameters();
CustomAttributeHandleCollection? returnTypeAttributes = null;
if (parameterHandles.Count > 0) {
var p = metadata.GetParameter(parameterHandles.First());
if (p.SequenceNumber == 0) {
returnTypeAttributes = p.GetCustomAttributes();
}
}
buffer.Append(metadata.GetString(pd.Name));
buffer.Append(" : ");
buffer.Append(TypeToString(signature.ReturnType, metadata, returnTypeAttributes));
buffer.Append(property.Name);
}
return buffer.ToString();
}
static readonly CSharpFormattingOptions TypeToStringFormattingOptions = FormattingOptionsFactory.CreateEmpty();
string TypeToString(AstType astType, MetadataReader metadata, CustomAttributeHandleCollection? customAttributes, ParameterHandle paramHandle = default)
{
StringWriter w = new StringWriter();
if (astType is ComposedType ct && ct.HasRefSpecifier) {
if (!paramHandle.IsNil) {
var p = metadata.GetParameter(paramHandle);
if ((p.Attributes & ParameterAttributes.In) == 0 && (p.Attributes & ParameterAttributes.Out) != 0) {
w.Write("out ");
} else {
w.Write("ref ");
}
} else {
w.Write("ref ");
}
astType = ct.BaseType;
astType.Remove();
}
var st = new SyntaxTree();
st.AddChild(astType, Roles.Type);
//st.AcceptVisitor(new InsertDynamicTypeVisitor(metadata, customAttributes));
// TODO: we should probably remove AstTypeBuilder and use TypeBuilder(with dummy compilation)+TSAstBuilder instead.
// Otherwise we'd need to duplicate a whole bunch of logic...
st.FirstChild.AcceptVisitor(new CSharpOutputVisitor(w, TypeToStringFormattingOptions));
return w.ToString();
buffer.Append(" : ");
buffer.Append(TypeToStringInternal(property.ReturnType, includeNamespace));
if (!includeTypeName)
return buffer.ToString();
return TypeToString(property.DeclaringTypeDefinition, includeNamespace) + "." + buffer.ToString();
}
public override string MethodToString(Decompiler.Metadata.MethodDefinition method, bool includeTypeName, bool includeNamespace)
public override string MethodToString(IMethod method, bool includeTypeName, bool includeNamespace)
{
if (method.IsNil)
throw new ArgumentNullException("method");
ConvertTypeOptions convertTypeOptions = ConvertTypeOptions.IncludeTypeParameterDefinitions;
if (includeNamespace)
convertTypeOptions |= ConvertTypeOptions.IncludeNamespace;
if (includeTypeName)
convertTypeOptions |= ConvertTypeOptions.IncludeOuterTypeName;
var metadata = method.Module.Metadata;
var md = metadata.GetMethodDefinition(method.Handle);
if (method == null)
throw new ArgumentNullException(nameof(method));
string name;
if (md.IsConstructor(metadata)) {
name = TypeToString(new Decompiler.Metadata.TypeDefinition(method.Module, md.GetDeclaringType()), includeNamespace: includeNamespace);
if (method.IsConstructor) {
name = TypeToString(method.DeclaringTypeDefinition, includeNamespace: includeNamespace);
} else {
if (includeTypeName) {
name = TypeToString(new Decompiler.Metadata.TypeDefinition(method.Module, md.GetDeclaringType()), includeNamespace: includeNamespace) + ".";
name = TypeToString(method.DeclaringTypeDefinition, includeNamespace: includeNamespace) + ".";
} else {
name = "";
}
name += metadata.GetString(md.Name);
name += method.Name;
}
var signature = md.DecodeSignature(new AstTypeBuilder(convertTypeOptions), new GenericContext(method));
int i = 0;
var buffer = new System.Text.StringBuilder(name);
var genericParams = md.GetGenericParameters();
if (genericParams.Count > 0) {
if (method.TypeParameters.Count > 0) {
buffer.Append('<');
foreach (var h in genericParams) {
var gp = metadata.GetGenericParameter(h);
foreach (var tp in method.TypeParameters) {
if (i > 0)
buffer.Append(", ");
buffer.Append(metadata.GetString(gp.Name));
buffer.Append(tp.Name);
i++;
}
buffer.Append('>');
@ -635,107 +507,44 @@ namespace ICSharpCode.ILSpy @@ -635,107 +507,44 @@ namespace ICSharpCode.ILSpy
buffer.Append('(');
i = 0;
var parameterHandles = md.GetParameters();
CustomAttributeHandleCollection? returnTypeAttributes = null;
if (signature.RequiredParameterCount > parameterHandles.Count) {
foreach (var type in signature.ParameterTypes) {
if (i > 0)
buffer.Append(", ");
buffer.Append(TypeToString(signature.ParameterTypes[i], metadata, null));
i++;
}
} else {
foreach (var h in parameterHandles) {
var p = metadata.GetParameter(h);
if (p.SequenceNumber > 0 && i < signature.ParameterTypes.Length) {
if (i > 0)
buffer.Append(", ");
buffer.Append(TypeToString(signature.ParameterTypes[i], metadata, p.GetCustomAttributes(), h));
i++;
}
if (p.SequenceNumber == 0) {
returnTypeAttributes = p.GetCustomAttributes();
}
}
}
if (signature.Header.CallingConvention == SignatureCallingConvention.VarArgs) {
if (signature.ParameterTypes.Length > 0)
var parameters = method.Parameters;
foreach (var param in parameters) {
if (i > 0)
buffer.Append(", ");
buffer.Append("...");
buffer.Append(TypeToStringInternal(param.Type, includeNamespace));
i++;
}
buffer.Append(')');
buffer.Append(" : ");
buffer.Append(TypeToString(signature.ReturnType, metadata, returnTypeAttributes));
buffer.Append(TypeToStringInternal(method.ReturnType, includeNamespace));
return buffer.ToString();
}
public override string EventToString(Decompiler.Metadata.EventDefinition @event, bool includeTypeName, bool includeNamespace)
public override string EventToString(IEvent @event, bool includeTypeName, bool includeNamespace)
{
if (@event.IsNil)
if (@event == null)
throw new ArgumentNullException(nameof(@event));
ConvertTypeOptions convertTypeOptions = ConvertTypeOptions.IncludeTypeParameterDefinitions;
if (includeNamespace)
convertTypeOptions |= ConvertTypeOptions.IncludeNamespace;
if (includeTypeName)
convertTypeOptions |= ConvertTypeOptions.IncludeOuterTypeName;
var metadata = @event.Module.Metadata;
var ed = metadata.GetEventDefinition(@event.Handle);
var accessors = ed.GetAccessors();
var accessorHandle = accessors.GetAny();
var accessor = metadata.GetMethodDefinition(accessorHandle);
var declaringType = metadata.GetTypeDefinition(accessor.GetDeclaringType());
var signature = ed.DecodeSignature(metadata, new AstTypeBuilder(convertTypeOptions), new GenericContext(accessorHandle, @event.Module));
var parameterHandles = accessor.GetParameters();
CustomAttributeHandleCollection? returnTypeAttributes = null;
if (parameterHandles.Count > 0) {
var p = metadata.GetParameter(parameterHandles.First());
if (p.SequenceNumber == 0) {
returnTypeAttributes = p.GetCustomAttributes();
}
}
var buffer = new System.Text.StringBuilder();
buffer.Append(metadata.GetString(ed.Name));
if (includeTypeName) {
buffer.Append(TypeToString(@event.DeclaringTypeDefinition, includeNamespace) + ".");
}
buffer.Append(@event.Name);
buffer.Append(" : ");
buffer.Append(TypeToString(signature, metadata, returnTypeAttributes));
buffer.Append(TypeToStringInternal(@event.ReturnType, includeNamespace));
return buffer.ToString();
}
public override bool ShowMember(IMetadataEntity member)
public override bool ShowMember(IEntity member)
{
return showAllMembers || !CSharpDecompiler.MemberIsHidden(member.Module, member.Handle, new DecompilationOptions().DecompilerSettings);
PEFile assembly = member.ParentAssembly.PEFile;
return showAllMembers || !CSharpDecompiler.MemberIsHidden(assembly, member.MetadataToken, new DecompilationOptions().DecompilerSettings);
}
public override string GetTooltip(Entity entity)
public override string GetTooltip(IEntity entity)
{
var decompilerTypeSystem = new DecompilerTypeSystem(entity.Module);
ISymbol symbol;
switch (entity.Handle.Kind) {
case HandleKind.MethodDefinition:
symbol = decompilerTypeSystem.ResolveAsMethod(entity.Handle);
if (symbol == null) return base.GetTooltip(entity);
break;
case HandleKind.PropertyDefinition:
symbol = decompilerTypeSystem.ResolveAsProperty(entity.Handle);
if (symbol == null) return base.GetTooltip(entity);
break;
case HandleKind.EventDefinition:
symbol = decompilerTypeSystem.ResolveAsEvent(entity.Handle);
if (symbol == null) return base.GetTooltip(entity);
break;
case HandleKind.FieldDefinition:
symbol = decompilerTypeSystem.ResolveAsField(entity.Handle);
if (symbol == null) return base.GetTooltip(entity);
break;
case HandleKind.TypeDefinition:
symbol = decompilerTypeSystem.ResolveAsType(entity.Handle).GetDefinition();
if (symbol == null) return base.GetTooltip(entity);
break;
default:
return base.GetTooltip(entity);
}
var flags = ConversionFlags.All & ~ConversionFlags.ShowBody;
return new CSharpAmbience() { ConversionFlags = flags }.ConvertSymbol(symbol);
return new CSharpAmbience() { ConversionFlags = flags }.ConvertSymbol(entity);
}
public override CodeMappingInfo GetCodeMappingInfo(PEFile module, EntityHandle member)

3
ILSpy/Languages/CodeMappingInfo.cs

@ -30,7 +30,8 @@ namespace ICSharpCode.ILSpy @@ -30,7 +30,8 @@ namespace ICSharpCode.ILSpy
public bool ShowMember(EntityHandle entity)
{
return Language.ShowMember(new Decompiler.Metadata.Entity(Module, entity));
throw null;
//return Language.ShowMember(new Decompiler.Metadata.Entity(Module, entity));
}
public IEnumerable<MethodDefinitionHandle> GetMethodParts(MethodDefinitionHandle method)

36
ILSpy/Languages/ILAstLanguage.cs

@ -70,11 +70,11 @@ namespace ICSharpCode.ILSpy @@ -70,11 +70,11 @@ namespace ICSharpCode.ILSpy
}
}
public override void DecompileMethod(MethodDefinition method, ITextOutput output, DecompilationOptions options)
public override void DecompileMethod(IMethod method, ITextOutput output, DecompilationOptions options)
{
base.DecompileMethod(method, output, options);
var module = method.Module;
new ReflectionDisassembler(output, options.CancellationToken).DisassembleMethodHeader(module, method.Handle);
new ReflectionDisassembler(output, options.CancellationToken)
.DisassembleMethodHeader(method.ParentAssembly.PEFile, (SRM.MethodDefinitionHandle)method.MetadataToken);
output.WriteLine();
output.WriteLine();
}
@ -83,17 +83,17 @@ namespace ICSharpCode.ILSpy @@ -83,17 +83,17 @@ namespace ICSharpCode.ILSpy
{
public TypedIL() : base("Typed IL") {}
public override void DecompileMethod(MethodDefinition method, ITextOutput output, DecompilationOptions options)
public override void DecompileMethod(IMethod method, ITextOutput output, DecompilationOptions options)
{
base.DecompileMethod(method, output, options);
var metadata = method.Module.Metadata;
var methodDef = metadata.GetMethodDefinition(method.Handle);
var module = method.ParentAssembly.PEFile;
var methodDef = module.Metadata.GetMethodDefinition((SRM.MethodDefinitionHandle)method.MetadataToken);
if (!methodDef.HasBody())
return;
var typeSystem = new DecompilerTypeSystem(method.Module);
var typeSystem = new DecompilerTypeSystem(module, module.GetAssemblyResolver());
ILReader reader = new ILReader(typeSystem);
var methodBody = method.Module.Reader.GetMethodBody(methodDef.RelativeVirtualAddress);
reader.WriteTypedIL(method.Module, method.Handle, methodBody, output, options.CancellationToken);
var methodBody = module.Reader.GetMethodBody(methodDef.RelativeVirtualAddress);
reader.WriteTypedIL(module, (SRM.MethodDefinitionHandle)method.MetadataToken, methodBody, output, options.CancellationToken);
}
}
@ -106,21 +106,23 @@ namespace ICSharpCode.ILSpy @@ -106,21 +106,23 @@ namespace ICSharpCode.ILSpy
this.transforms = transforms;
}
public override void DecompileMethod(MethodDefinition method, ITextOutput output, DecompilationOptions options)
public override void DecompileMethod(IMethod method, ITextOutput output, DecompilationOptions options)
{
base.DecompileMethod(method, output, options);
var metadata = method.Module.Metadata;
var methodDef = metadata.GetMethodDefinition(method.Handle);
var module = method.ParentAssembly.PEFile;
var metadata = module.Metadata;
var methodDef = metadata.GetMethodDefinition((SRM.MethodDefinitionHandle)method.MetadataToken);
if (!methodDef.HasBody())
return;
var typeSystem = new DecompilerTypeSystem(method.Module);
var specializingTypeSystem = typeSystem.GetSpecializingTypeSystem(new SimpleTypeResolveContext(typeSystem.ResolveAsMethod(method.Handle)));
IAssemblyResolver assemblyResolver = module.GetAssemblyResolver();
var typeSystem = new DecompilerTypeSystem(module, assemblyResolver);
var specializingTypeSystem = typeSystem.GetSpecializingTypeSystem(new SimpleTypeResolveContext(typeSystem.ResolveAsMethod(method.MetadataToken)));
var reader = new ILReader(specializingTypeSystem);
reader.UseDebugSymbols = options.DecompilerSettings.UseDebugSymbols;
var methodBody = method.Module.Reader.GetMethodBody(methodDef.RelativeVirtualAddress);
ILFunction il = reader.ReadIL(method.Module, method.Handle, methodBody, options.CancellationToken);
var methodBody = module.Reader.GetMethodBody(methodDef.RelativeVirtualAddress);
ILFunction il = reader.ReadIL(module, (SRM.MethodDefinitionHandle)method.MetadataToken, methodBody, options.CancellationToken);
var namespaces = new HashSet<string>();
var decompiler = new CSharpDecompiler(typeSystem, options.DecompilerSettings) { CancellationToken = options.CancellationToken };
var decompiler = new CSharpDecompiler(typeSystem, assemblyResolver, options.DecompilerSettings) { CancellationToken = options.CancellationToken };
ILTransformContext context = decompiler.CreateILTransformContext(il);
context.Stepper.StepLimit = options.StepLimit;
context.Stepper.IsDebug = options.IsDebug;

46
ILSpy/Languages/ILLanguage.cs

@ -26,6 +26,7 @@ using System.IO; @@ -26,6 +26,7 @@ using System.IO;
using System.Reflection.Metadata.Ecma335;
using System.Linq;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.ILSpy
{
@ -59,32 +60,33 @@ namespace ICSharpCode.ILSpy @@ -59,32 +60,33 @@ namespace ICSharpCode.ILSpy
};
}
public override void DecompileMethod(Decompiler.Metadata.MethodDefinition method, ITextOutput output, DecompilationOptions options)
public override void DecompileMethod(IMethod method, ITextOutput output, DecompilationOptions options)
{
var dis = CreateDisassembler(output, options);
dis.DisassembleMethod(method.Module, method.Handle);
dis.DisassembleMethod(method.ParentAssembly.PEFile, (MethodDefinitionHandle)method.MetadataToken);
}
public override void DecompileField(Decompiler.Metadata.FieldDefinition field, ITextOutput output, DecompilationOptions options)
public override void DecompileField(IField field, ITextOutput output, DecompilationOptions options)
{
var dis = CreateDisassembler(output, options);
dis.DisassembleField(field);
dis.DisassembleField(field.ParentAssembly.PEFile, (FieldDefinitionHandle)field.MetadataToken);
}
public override void DecompileProperty(Decompiler.Metadata.PropertyDefinition property, ITextOutput output, DecompilationOptions options)
public override void DecompileProperty(IProperty property, ITextOutput output, DecompilationOptions options)
{
var dis = CreateDisassembler(output, options);
dis.DisassembleProperty(property);
var pd = property.Module.Metadata.GetPropertyDefinition(property.Handle);
PEFile module = property.ParentAssembly.PEFile;
dis.DisassembleProperty(module, (PropertyDefinitionHandle)property.MetadataToken);
var pd = module.Metadata.GetPropertyDefinition((PropertyDefinitionHandle)property.MetadataToken);
var accessors = pd.GetAccessors();
if (!accessors.Getter.IsNil) {
output.WriteLine();
dis.DisassembleMethod(property.Module, accessors.Getter);
dis.DisassembleMethod(module, accessors.Getter);
}
if (!accessors.Setter.IsNil) {
output.WriteLine();
dis.DisassembleMethod(property.Module, accessors.Setter);
dis.DisassembleMethod(module, accessors.Setter);
}
/*foreach (var m in property.OtherMethods) {
output.WriteLine();
@ -92,25 +94,25 @@ namespace ICSharpCode.ILSpy @@ -92,25 +94,25 @@ namespace ICSharpCode.ILSpy
}*/
}
public override void DecompileEvent(Decompiler.Metadata.EventDefinition ev, ITextOutput output, DecompilationOptions options)
public override void DecompileEvent(IEvent ev, ITextOutput output, DecompilationOptions options)
{
var dis = CreateDisassembler(output, options);
var metadata = ev.Module.Metadata;
dis.DisassembleEvent(ev.Module, ev.Handle);
PEFile module = ev.ParentAssembly.PEFile;
dis.DisassembleEvent(module, (EventDefinitionHandle)ev.MetadataToken);
var ed = metadata.GetEventDefinition(ev.Handle);
var ed = ((MetadataReader)module.Metadata).GetEventDefinition((EventDefinitionHandle)ev.MetadataToken);
var accessors = ed.GetAccessors();
if (!accessors.Adder.IsNil) {
output.WriteLine();
dis.DisassembleMethod(ev.Module, accessors.Adder);
dis.DisassembleMethod(module, accessors.Adder);
}
if (!accessors.Remover.IsNil) {
output.WriteLine();
dis.DisassembleMethod(ev.Module, accessors.Remover);
dis.DisassembleMethod(module, accessors.Remover);
}
if (!accessors.Raiser.IsNil) {
output.WriteLine();
dis.DisassembleMethod(ev.Module, accessors.Raiser);
dis.DisassembleMethod(module, accessors.Raiser);
}
/*foreach (var m in ev.OtherMethods) {
output.WriteLine();
@ -118,16 +120,18 @@ namespace ICSharpCode.ILSpy @@ -118,16 +120,18 @@ namespace ICSharpCode.ILSpy
}*/
}
public override void DecompileType(Decompiler.Metadata.TypeDefinition type, ITextOutput output, DecompilationOptions options)
public override void DecompileType(ITypeDefinition type, ITextOutput output, DecompilationOptions options)
{
var dis = CreateDisassembler(output, options);
dis.DisassembleType(type);
PEFile module = type.ParentAssembly.PEFile;
dis.DisassembleType(module, (TypeDefinitionHandle)type.MetadataToken);
}
public override void DecompileNamespace(string nameSpace, IEnumerable<Decompiler.Metadata.TypeDefinition> types, ITextOutput output, DecompilationOptions options)
public override void DecompileNamespace(string nameSpace, IEnumerable<ITypeDefinition> types, ITextOutput output, DecompilationOptions options)
{
var dis = CreateDisassembler(output, options);
dis.DisassembleNamespace(nameSpace, types);
PEFile module = types.FirstOrDefault()?.ParentAssembly.PEFile;
dis.DisassembleNamespace(nameSpace, module, types.Select(t => (TypeDefinitionHandle)t.MetadataToken));
}
public override void DecompileAssembly(LoadedAssembly assembly, ITextOutput output, DecompilationOptions options)

172
ILSpy/Languages/ILSignatureProvider.cs

@ -1,172 +0,0 @@ @@ -1,172 +0,0 @@
// 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.Immutable;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
using SRM = System.Reflection.Metadata;
namespace ICSharpCode.ILSpy
{
class ILSignatureProvider : SRM.ISignatureTypeProvider<string, GenericContext>
{
public static readonly ILSignatureProvider WithoutNamespace = new ILSignatureProvider(false);
public static readonly ILSignatureProvider WithNamespace = new ILSignatureProvider(true);
bool includeNamespace;
public ILSignatureProvider(bool includeNamespace)
{
this.includeNamespace = includeNamespace;
}
public string GetArrayType(string elementType, SRM.ArrayShape shape)
{
string printedShape = "";
for (int i = 0; i < shape.Rank; i++) {
if (i > 0)
printedShape += ", ";
if (i < shape.LowerBounds.Length || i < shape.Sizes.Length) {
int lower = 0;
if (i < shape.LowerBounds.Length) {
lower = shape.LowerBounds[i];
printedShape += lower.ToString();
}
printedShape += "...";
if (i < shape.Sizes.Length)
printedShape += (lower + shape.Sizes[i] - 1).ToString();
}
}
return $"{elementType}[{printedShape}]";
}
public string GetByReferenceType(string elementType)
{
return elementType + "&";
}
public string GetFunctionPointerType(SRM.MethodSignature<string> signature)
{
return "method " + signature.ReturnType + " *(" + string.Join(", ", signature.ParameterTypes) + ")";
}
public string GetGenericInstantiation(string genericType, ImmutableArray<string> typeArguments)
{
return genericType + "<" + string.Join(", ", typeArguments) + ">";
}
public string GetGenericMethodParameter(GenericContext genericContext, int index)
{
return "!!" + genericContext.GetGenericMethodTypeParameterName(index);
}
public string GetGenericTypeParameter(GenericContext genericContext, int index)
{
return "!" + genericContext.GetGenericTypeParameterName(index);
}
public string GetModifiedType(string modifier, string unmodifiedType, bool isRequired)
{
string modifierKeyword = isRequired ? "modreq" : "modopt";
return $"{unmodifiedType} {modifierKeyword}({modifier})";
}
public string GetPinnedType(string elementType)
{
throw new NotImplementedException();
}
public string GetPointerType(string elementType)
{
return elementType + "*";
}
public string GetPrimitiveType(SRM.PrimitiveTypeCode typeCode)
{
switch (typeCode) {
case SRM.PrimitiveTypeCode.Boolean:
return "bool";
case SRM.PrimitiveTypeCode.Byte:
return "uint8";
case SRM.PrimitiveTypeCode.SByte:
return "int8";
case SRM.PrimitiveTypeCode.Char:
return "char";
case SRM.PrimitiveTypeCode.Int16:
return "int16";
case SRM.PrimitiveTypeCode.UInt16:
return "uint16";
case SRM.PrimitiveTypeCode.Int32:
return "int32";
case SRM.PrimitiveTypeCode.UInt32:
return "uint32";
case SRM.PrimitiveTypeCode.Int64:
return "int64";
case SRM.PrimitiveTypeCode.UInt64:
return "uint64";
case SRM.PrimitiveTypeCode.Single:
return "float32";
case SRM.PrimitiveTypeCode.Double:
return "float64";
case SRM.PrimitiveTypeCode.IntPtr:
return "native int";
case SRM.PrimitiveTypeCode.UIntPtr:
return "native uint";
case SRM.PrimitiveTypeCode.Object:
return "object";
case SRM.PrimitiveTypeCode.String:
return "string";
case SRM.PrimitiveTypeCode.TypedReference:
return "typedref";
case SRM.PrimitiveTypeCode.Void:
return "void";
default:
throw new ArgumentOutOfRangeException();
}
}
public string GetSZArrayType(string elementType)
{
return elementType + "[]";
}
public string GetTypeFromDefinition(SRM.MetadataReader reader, SRM.TypeDefinitionHandle handle, byte rawTypeKind)
{
if (!includeNamespace) {
return Decompiler.Disassembler.DisassemblerHelpers.Escape(handle.GetFullTypeName(reader).Name);
}
return handle.GetFullTypeName(reader).ToILNameString();
}
public string GetTypeFromReference(SRM.MetadataReader reader, SRM.TypeReferenceHandle handle, byte rawTypeKind)
{
if (!includeNamespace) {
return Decompiler.Disassembler.DisassemblerHelpers.Escape(handle.GetFullTypeName(reader).Name);
}
return handle.GetFullTypeName(reader).ToILNameString();
}
public string GetTypeFromSpecification(SRM.MetadataReader reader, GenericContext genericContext, SRM.TypeSpecificationHandle handle, byte rawTypeKind)
{
return reader.GetTypeSpecification(handle).DecodeSignature(this, genericContext);
}
}
}

215
ILSpy/Languages/Language.cs

@ -20,11 +20,10 @@ using System; @@ -20,11 +20,10 @@ using System;
using System.Collections.Generic;
using System.Reflection.PortableExecutable;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Util;
using ICSharpCode.Decompiler.Disassembler;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.Util;
using static System.Reflection.Metadata.PEReaderExtensions;
using SRM = System.Reflection.Metadata;
namespace ICSharpCode.ILSpy
@ -96,42 +95,32 @@ namespace ICSharpCode.ILSpy @@ -96,42 +95,32 @@ namespace ICSharpCode.ILSpy
}
}
public virtual void DecompileMethod(MethodDefinition method, ITextOutput output, DecompilationOptions options)
public virtual void DecompileMethod(IMethod method, ITextOutput output, DecompilationOptions options)
{
var metadata = method.Module.Metadata;
var methodDefinition = metadata.GetMethodDefinition(method.Handle);
WriteCommentLine(output, TypeToString(new TypeDefinition(method.Module, methodDefinition.GetDeclaringType()), includeNamespace: true) + "." + metadata.GetString(methodDefinition.Name));
WriteCommentLine(output, TypeToString(method.DeclaringTypeDefinition, includeNamespace: true) + "." + method.Name);
}
public virtual void DecompileProperty(PropertyDefinition property, ITextOutput output, DecompilationOptions options)
public virtual void DecompileProperty(IProperty property, ITextOutput output, DecompilationOptions options)
{
var metadata = property.Module.Metadata;
var propertyDefinition = metadata.GetPropertyDefinition(property.Handle);
var declaringType = metadata.GetMethodDefinition(propertyDefinition.GetAccessors().GetAny()).GetDeclaringType();
WriteCommentLine(output, TypeToString(new TypeDefinition(property.Module, declaringType), includeNamespace: true) + "." + metadata.GetString(propertyDefinition.Name));
WriteCommentLine(output, TypeToString(property.DeclaringTypeDefinition, includeNamespace: true) + "." + property.Name);
}
public virtual void DecompileField(FieldDefinition field, ITextOutput output, DecompilationOptions options)
public virtual void DecompileField(IField field, ITextOutput output, DecompilationOptions options)
{
var metadata = field.Module.Metadata;
var fieldDefinition = metadata.GetFieldDefinition(field.Handle);
WriteCommentLine(output, TypeToString(new TypeDefinition(field.Module, fieldDefinition.GetDeclaringType()), includeNamespace: true) + "." + metadata.GetString(fieldDefinition.Name));
WriteCommentLine(output, TypeToString(field.DeclaringTypeDefinition, includeNamespace: true) + "." + field.Name);
}
public virtual void DecompileEvent(EventDefinition ev, ITextOutput output, DecompilationOptions options)
public virtual void DecompileEvent(IEvent @event, ITextOutput output, DecompilationOptions options)
{
var metadata = ev.Module.Metadata;
var eventDefinition = metadata.GetEventDefinition(ev.Handle);
var declaringType = metadata.GetMethodDefinition(eventDefinition.GetAccessors().GetAny()).GetDeclaringType();
WriteCommentLine(output, TypeToString(new TypeDefinition(ev.Module, declaringType), includeNamespace: true) + "." + metadata.GetString(eventDefinition.Name));
WriteCommentLine(output, TypeToString(@event.DeclaringTypeDefinition, includeNamespace: true) + "." + @event.Name);
}
public virtual void DecompileType(TypeDefinition type, ITextOutput output, DecompilationOptions options)
public virtual void DecompileType(ITypeDefinition type, ITextOutput output, DecompilationOptions options)
{
WriteCommentLine(output, TypeToString(type, includeNamespace: true));
}
public virtual void DecompileNamespace(string nameSpace, IEnumerable<TypeDefinition> types, ITextOutput output, DecompilationOptions options)
public virtual void DecompileNamespace(string nameSpace, IEnumerable<ITypeDefinition> types, ITextOutput output, DecompilationOptions options)
{
WriteCommentLine(output, nameSpace);
}
@ -160,35 +149,18 @@ namespace ICSharpCode.ILSpy @@ -160,35 +149,18 @@ namespace ICSharpCode.ILSpy
}
/// <summary>
/// Converts a type definition, reference or specification into a string. This method is used by the type tree nodes and search results.
/// Converts a type definition, reference or specification into a string. This method is used by tree nodes and search results.
/// </summary>
public virtual string TypeToString(Entity type, GenericContext genericContext = null, bool includeNamespace = true)
public virtual string TypeToString(IType type, bool includeNamespace)
{
var provider = includeNamespace ? ILSignatureProvider.WithNamespace : ILSignatureProvider.WithoutNamespace;
var metadata = type.Module.Metadata;
switch (type.Handle.Kind) {
case SRM.HandleKind.TypeReference:
return provider.GetTypeFromReference(metadata, (SRM.TypeReferenceHandle)type.Handle, 0);
case SRM.HandleKind.TypeDefinition:
var td = metadata.GetTypeDefinition((SRM.TypeDefinitionHandle)type.Handle);
if (includeNamespace) {
var buffer = new System.Text.StringBuilder();
if (!td.GetDeclaringType().IsNil) {
buffer.Append(TypeToString(new TypeDefinition(type.Module, td.GetDeclaringType()), genericContext, includeNamespace));
buffer.Append('+');
} else if (!td.Namespace.IsNil) {
buffer.Append(metadata.GetString(td.Namespace));
buffer.Append('.');
}
buffer.Append(metadata.GetString(td.Name));
return buffer.ToString();
} else {
return metadata.GetString(td.Name);
}
case SRM.HandleKind.TypeSpecification:
return provider.GetTypeFromSpecification(metadata, genericContext ?? GenericContext.Empty, (SRM.TypeSpecificationHandle)type.Handle, 0);
default:
throw new NotSupportedException();
if (includeNamespace)
return type.ReflectionName;
else {
int index = type.ReflectionName.LastIndexOf('.');
if (index > 0) {
return type.ReflectionName.Substring(index + 1);
}
return type.ReflectionName;
}
}
@ -196,91 +168,40 @@ namespace ICSharpCode.ILSpy @@ -196,91 +168,40 @@ namespace ICSharpCode.ILSpy
/// Converts a member signature to a string.
/// This is used for displaying the tooltip on a member reference.
/// </summary>
public virtual string GetTooltip(Entity entity)
public virtual string GetTooltip(IEntity entity)
{
var metadata = entity.Module.Metadata;
switch (entity.Handle.Kind) {
case SRM.HandleKind.TypeReference:
case SRM.HandleKind.TypeDefinition:
case SRM.HandleKind.TypeSpecification:
return entity.Handle.GetFullTypeName(metadata).ToString();
case SRM.HandleKind.FieldDefinition:
var fieldDefinition = metadata.GetFieldDefinition((SRM.FieldDefinitionHandle)entity.Handle);
string fieldType = fieldDefinition.DecodeSignature(ILSignatureProvider.WithoutNamespace, new GenericContext(fieldDefinition.GetDeclaringType(), entity.Module));
return fieldType + " " + fieldDefinition.GetDeclaringType().GetFullTypeName(metadata) + "." + metadata.GetString(fieldDefinition.Name);
case SRM.HandleKind.MethodDefinition:
return TreeNodes.MethodTreeNode.GetText(entity, this).ToString();
case SRM.HandleKind.EventDefinition:
return TreeNodes.EventTreeNode.GetText(entity, this).ToString();
case SRM.HandleKind.PropertyDefinition:
return TreeNodes.PropertyTreeNode.GetText(entity, this).ToString();
default:
throw new NotSupportedException();
}
return GetDisplayName(entity, true, true);
}
public virtual string FieldToString(FieldDefinition field, bool includeTypeName, bool includeNamespace)
public virtual string FieldToString(IField field, bool includeTypeName, bool includeNamespace)
{
if (field.Handle.IsNil)
if (field == null)
throw new ArgumentNullException(nameof(field));
var metadata = field.Module.Metadata;
var fd = metadata.GetFieldDefinition(field.Handle);
string fieldType = fd.DecodeSignature(ILSignatureProvider.WithoutNamespace, new GenericContext(fd.GetDeclaringType(), field.Module));
string simple = metadata.GetString(fd.Name) + " : " + fieldType;
if (!includeTypeName)
return simple;
var typeName = fd.GetDeclaringType().GetFullTypeName(metadata);
if (!includeNamespace)
return typeName.Name + "." + simple;
return typeName + "." + simple;
return GetDisplayName(field, includeTypeName, includeNamespace) + " : " + TypeToString(field.ReturnType, includeNamespace);
}
public virtual string PropertyToString(PropertyDefinition property, bool includeTypeName, bool includeNamespace, bool? isIndexer = null)
public virtual string PropertyToString(IProperty property, bool includeTypeName, bool includeNamespace, bool? isIndexer = null)
{
if (property.Handle.IsNil)
if (property == null)
throw new ArgumentNullException(nameof(property));
var metadata = property.Module.Metadata;
var pd = metadata.GetPropertyDefinition(property.Handle);
var declaringType = metadata.GetMethodDefinition(pd.GetAccessors().GetAny()).GetDeclaringType();
var signature = pd.DecodeSignature(!includeNamespace ? ILSignatureProvider.WithoutNamespace : ILSignatureProvider.WithNamespace, new GenericContext(declaringType, property.Module));
string simple = metadata.GetString(metadata.GetPropertyDefinition(property.Handle).Name) + " : " + signature.ReturnType;
if (!includeTypeName)
return simple;
var typeName = declaringType.GetFullTypeName(metadata);
if (!includeNamespace)
return typeName.Name + "." + simple;
return typeName + "." + simple;
return GetDisplayName(property, includeTypeName, includeNamespace) + " : " + TypeToString(property.ReturnType, includeNamespace);
}
public virtual string MethodToString(MethodDefinition method, bool includeTypeName, bool includeNamespace)
public virtual string MethodToString(IMethod method, bool includeTypeName, bool includeNamespace)
{
if (method.IsNil)
if (method == null)
throw new ArgumentNullException(nameof(method));
var metadata = method.Module.Metadata;
var md = metadata.GetMethodDefinition(method.Handle);
string name;
if (includeTypeName) {
if (includeNamespace) {
name = md.GetDeclaringType().GetFullTypeName(metadata) + ".";
} else {
name = md.GetDeclaringType().GetFullTypeName(metadata).Name + ".";
}
name += metadata.GetString(md.Name);
} else {
name = metadata.GetString(md.Name);
}
var signature = md.DecodeSignature(includeNamespace ? ILSignatureProvider.WithNamespace : ILSignatureProvider.WithoutNamespace, new GenericContext(method));
int i = 0;
var buffer = new System.Text.StringBuilder(name);
var genericParams = md.GetGenericParameters();
if (genericParams.Count > 0) {
var buffer = new System.Text.StringBuilder();
buffer.Append(GetDisplayName(method, includeTypeName, includeNamespace));
var typeParameters = method.TypeParameters;
if (typeParameters.Count > 0) {
buffer.Append('<');
foreach (var h in genericParams) {
var gp = metadata.GetGenericParameter(h);
foreach (var tp in typeParameters) {
if (i > 0)
buffer.Append(", ");
buffer.Append(metadata.GetString(gp.Name));
buffer.Append(tp.Name);
i++;
}
buffer.Append('>');
@ -288,51 +209,47 @@ namespace ICSharpCode.ILSpy @@ -288,51 +209,47 @@ namespace ICSharpCode.ILSpy
buffer.Append('(');
i = 0;
var parameterHandles = md.GetParameters();
if (signature.RequiredParameterCount > parameterHandles.Count) {
foreach (var type in signature.ParameterTypes) {
if (i > 0)
buffer.Append(", ");
buffer.Append(signature.ParameterTypes[i]);
i++;
}
} else {
foreach (var h in parameterHandles) {
var p = metadata.GetParameter(h);
if (p.SequenceNumber > 0 && i < signature.ParameterTypes.Length) {
if (i > 0)
buffer.Append(", ");
buffer.Append(signature.ParameterTypes[i]);
i++;
}
}
}
if (signature.Header.CallingConvention == SRM.SignatureCallingConvention.VarArgs) {
if (signature.ParameterTypes.Length > 0)
var parameters = method.Parameters;
foreach (var param in parameters) {
if (i > 0)
buffer.Append(", ");
buffer.Append("...");
buffer.Append(TypeToString(param.Type, includeNamespace));
i++;
}
buffer.Append(')');
buffer.Append(" : ");
buffer.Append(signature.ReturnType);
buffer.Append(TypeToString(method.ReturnType, includeNamespace));
return buffer.ToString();
}
public virtual string EventToString(EventDefinition @event, bool includeTypeName, bool includeNamespace)
public virtual string EventToString(IEvent @event, bool includeTypeName, bool includeNamespace)
{
if (@event.IsNil)
if (@event == null)
throw new ArgumentNullException(nameof(@event));
var metadata = @event.Module.Metadata;
var ed = metadata.GetEventDefinition(@event.Handle);
var accessorHandle = ed.GetAccessors().GetAny();
var signature = ed.DecodeSignature(metadata, includeNamespace ? ILSignatureProvider.WithNamespace : ILSignatureProvider.WithoutNamespace, new GenericContext(accessorHandle, @event.Module));
var buffer = new System.Text.StringBuilder();
buffer.Append(metadata.GetString(ed.Name));
buffer.Append(GetDisplayName(@event, includeTypeName, includeNamespace));
buffer.Append(" : ");
buffer.Append(signature);
buffer.Append(TypeToString(@event.ReturnType, includeNamespace));
return buffer.ToString();
}
protected string GetDisplayName(IEntity entity, bool includeTypeName, bool includeNamespace)
{
if (includeTypeName && entity.DeclaringTypeDefinition != null) {
string name;
if (includeNamespace) {
name = entity.DeclaringTypeDefinition.FullName;
} else {
name = entity.DeclaringTypeDefinition.Name;
}
return name + "." + entity.Name;
} else {
if (includeNamespace)
return entity.FullName;
return entity.Name;
}
}
/// <summary>
/// Used for WPF keyboard navigation.
/// </summary>
@ -341,7 +258,7 @@ namespace ICSharpCode.ILSpy @@ -341,7 +258,7 @@ namespace ICSharpCode.ILSpy
return Name;
}
public virtual bool ShowMember(IMetadataEntity member)
public virtual bool ShowMember(IEntity member)
{
return true;
}

55
ILSpy/LoadedAssembly.cs

@ -21,10 +21,14 @@ using System.Collections.Generic; @@ -21,10 +21,14 @@ using System.Collections.Generic;
using System.IO;
using System.Reflection.Metadata;
using System.Reflection.PortableExecutable;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.DebugInfo;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.TypeSystem.Implementation;
using ICSharpCode.ILSpy.DebugInfo;
using ICSharpCode.ILSpy.Options;
@ -37,6 +41,8 @@ namespace ICSharpCode.ILSpy @@ -37,6 +41,8 @@ namespace ICSharpCode.ILSpy
/// </summary>
public sealed class LoadedAssembly
{
internal static readonly ConditionalWeakTable<PEFile, LoadedAssembly> loadedAssemblies = new ConditionalWeakTable<PEFile, LoadedAssembly>();
readonly Task<PEFile> assemblyTask;
readonly AssemblyList assemblyList;
readonly string fileName;
@ -63,6 +69,8 @@ namespace ICSharpCode.ILSpy @@ -63,6 +69,8 @@ namespace ICSharpCode.ILSpy
public ReferenceLoadInfo LoadedAssemblyReferencesInfo { get; } = new ReferenceLoadInfo();
IDebugInfoProvider debugInfoProvider;
/// <summary>
/// Gets the Cecil ModuleDefinition.
/// </summary>
@ -85,6 +93,22 @@ namespace ICSharpCode.ILSpy @@ -85,6 +93,22 @@ namespace ICSharpCode.ILSpy
}
}
ICompilation typeSystem;
/// <summary>
/// Gets a type system containing all types from this assembly + primitve types from mscorlib.
/// Returns null in case of load errors.
/// </summary>
public ICompilation GetTypeSystemOrNull()
{
if (typeSystem != null)
return typeSystem;
var module = GetPEFileOrNull();
if (module == null)
return null;
return typeSystem = new SimpleCompilation(module, MinimalCorlib.Instance);
}
public AssemblyList AssemblyList => assemblyList;
public string FileName => fileName;
@ -119,12 +143,12 @@ namespace ICSharpCode.ILSpy @@ -119,12 +143,12 @@ namespace ICSharpCode.ILSpy
if (stream != null)
{
// Read the module from a precrafted stream
module = new PEFile(fileName, stream, new MyAssemblyResolver(this), PEStreamOptions.Default);
module = new PEFile(fileName, stream);
}
else
{
// Read the module from disk (by default)
module = new PEFile(fileName, new FileStream(fileName, FileMode.Open, FileAccess.Read), new MyAssemblyResolver(this), PEStreamOptions.PrefetchEntireImage);
module = new PEFile(fileName, new FileStream(fileName, FileMode.Open, FileAccess.Read), PEStreamOptions.PrefetchEntireImage);
}
if (DecompilerSettingsPanel.CurrentDecompilerSettings.UseDebugSymbols) {
@ -136,6 +160,9 @@ namespace ICSharpCode.ILSpy @@ -136,6 +160,9 @@ namespace ICSharpCode.ILSpy
// ignore any errors during symbol loading
}
}
lock (loadedAssemblies) {
loadedAssemblies.Add(module, this);
}
return module;
}
@ -144,13 +171,13 @@ namespace ICSharpCode.ILSpy @@ -144,13 +171,13 @@ namespace ICSharpCode.ILSpy
var reader = module.Reader;
// try to open portable pdb file/embedded pdb info:
if (reader.TryOpenAssociatedPortablePdb(fileName, OpenStream, out var provider, out var pdbFileName)) {
module.DebugInfo = new PortableDebugInfoProvider(pdbFileName, provider);
debugInfoProvider = new PortableDebugInfoProvider(pdbFileName, provider);
} else {
// search for pdb in same directory as dll
string pdbDirectory = Path.GetDirectoryName(fileName);
pdbFileName = Path.Combine(pdbDirectory, Path.GetFileNameWithoutExtension(fileName) + ".pdb");
if (File.Exists(pdbFileName)) {
module.DebugInfo = new DiaSymNativeDebugInfoProvider(module, pdbFileName, OpenStream(pdbFileName));
debugInfoProvider = new DiaSymNativeDebugInfoProvider(module, pdbFileName, OpenStream(pdbFileName));
return;
}
@ -193,7 +220,7 @@ namespace ICSharpCode.ILSpy @@ -193,7 +220,7 @@ namespace ICSharpCode.ILSpy
}
}
sealed class MyAssemblyResolver : IAssemblyResolver
sealed class MyAssemblyResolver : Decompiler.Metadata.IAssemblyResolver
{
readonly LoadedAssembly parent;
@ -202,7 +229,7 @@ namespace ICSharpCode.ILSpy @@ -202,7 +229,7 @@ namespace ICSharpCode.ILSpy
this.parent = parent;
}
public PEFile Resolve(IAssemblyReference reference)
public PEFile Resolve(Decompiler.Metadata.IAssemblyReference reference)
{
return parent.LookupReferencedAssembly(reference)?.GetPEFileOrNull();
}
@ -212,8 +239,18 @@ namespace ICSharpCode.ILSpy @@ -212,8 +239,18 @@ namespace ICSharpCode.ILSpy
{
return new MyAssemblyResolver(this);
}
/// <summary>
/// Returns the debug info for this assembly. Returns null in case of load errors or no debug info is available.
/// </summary>
public IDebugInfoProvider GetDebugInfoOrNull()
{
if (GetPEFileOrNull() == null)
return null;
return debugInfoProvider;
}
public LoadedAssembly LookupReferencedAssembly(IAssemblyReference reference)
public LoadedAssembly LookupReferencedAssembly(Decompiler.Metadata.IAssemblyReference reference)
{
if (reference == null)
throw new ArgumentNullException(nameof(reference));
@ -234,9 +271,9 @@ namespace ICSharpCode.ILSpy @@ -234,9 +271,9 @@ namespace ICSharpCode.ILSpy
static Dictionary<string, LoadedAssembly> loadingAssemblies = new Dictionary<string, LoadedAssembly>();
LoadedAssembly LookupReferencedAssemblyInternal(IAssemblyReference fullName, bool isWinRT)
LoadedAssembly LookupReferencedAssemblyInternal(Decompiler.Metadata.IAssemblyReference fullName, bool isWinRT)
{
string GetName(IAssemblyReference name) => isWinRT ? name.Name : name.FullName;
string GetName(Decompiler.Metadata.IAssemblyReference name) => isWinRT ? name.Name : name.FullName;
string file;
LoadedAssembly asm;

36
ILSpy/LoadedAssemblyExtensions.cs

@ -0,0 +1,36 @@ @@ -0,0 +1,36 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.ILSpy
{
public static class LoadedAssemblyExtensions
{
public static IAssemblyResolver GetAssemblyResolver(this PEFile file)
{
return GetLoadedAssembly(file).GetAssemblyResolver();
}
public static ICompilation GetTypeSystemOrNull(this PEFile file)
{
return GetLoadedAssembly(file).GetTypeSystemOrNull();
}
static LoadedAssembly GetLoadedAssembly(PEFile file)
{
if (file == null)
throw new ArgumentNullException(nameof(file));
LoadedAssembly loadedAssembly;
lock (LoadedAssembly.loadedAssemblies) {
if (!LoadedAssembly.loadedAssemblies.TryGetValue(file, out loadedAssembly))
throw new ArgumentException("The specified file is not associated with a LoadedAssembly!");
}
return loadedAssembly;
}
}
}

86
ILSpy/MainWindow.xaml.cs

@ -34,6 +34,8 @@ using System.Windows.Threading; @@ -34,6 +34,8 @@ using System.Windows.Threading;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Documentation;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.TypeSystem.Implementation;
using ICSharpCode.ILSpy.TextView;
using ICSharpCode.ILSpy.TreeNodes;
using ICSharpCode.TreeView;
@ -287,8 +289,8 @@ namespace ICSharpCode.ILSpy @@ -287,8 +289,8 @@ namespace ICSharpCode.ILSpy
foreach (LoadedAssembly asm in commandLineLoadedAssemblies) {
var def = asm.GetPEFileOrNull();
if (def != null) {
var mr = XmlDocKeyProvider.FindMemberByKey(def, args.NavigateTo);
if (!mr.IsNil) {
var mr = XmlDocKeyProvider.FindEntity(args.NavigateTo, new SimpleCompilation(def, MinimalCorlib.Instance).TypeResolveContext);
if (mr != null) {
found = true;
// Defer JumpToReference call to allow an assembly that was loaded while
// resolving a type-forwarder in FindMemberByKey to appear in the assembly list.
@ -599,55 +601,16 @@ namespace ICSharpCode.ILSpy @@ -599,55 +601,16 @@ namespace ICSharpCode.ILSpy
return assemblyListTreeNode.FindAssemblyNode(asm);
case Resource res:
return assemblyListTreeNode.FindResourceNode(res);
case IMetadataEntity entity:
switch (entity) {
case TypeDefinition td:
return assemblyListTreeNode.FindTypeNode(td);
case FieldDefinition fd:
return assemblyListTreeNode.FindFieldNode(fd);
case MethodDefinition md:
return assemblyListTreeNode.FindMethodNode(md);
case PropertyDefinition pd:
return assemblyListTreeNode.FindPropertyNode(pd);
case EventDefinition ed:
return assemblyListTreeNode.FindEventNode(ed);
default:
throw new NotSupportedException();
}
case TypeReference tr:
var resolved = tr.Handle.Resolve(new SimpleMetadataResolveContext(tr.Module));
if (resolved != null && !resolved.IsNil)
return assemblyListTreeNode.FindTypeNode(resolved);
return null;
case TypeSpecification ts:
resolved = ts.Handle.Resolve(new SimpleMetadataResolveContext(ts.Module));
if (!resolved.IsNil)
return assemblyListTreeNode.FindTypeNode(resolved);
return null;
case MemberReference mr:
var resolvedMember = mr.Handle.Resolve(new SimpleMetadataResolveContext(mr.Module));
if (resolvedMember != null && !resolvedMember.IsNil) {
switch (resolvedMember) {
case FieldDefinition fd:
return assemblyListTreeNode.FindFieldNode(fd);
case MethodDefinition md:
return assemblyListTreeNode.FindMethodNode(md);
default:
throw new NotSupportedException();
}
}
return null;
case MethodSpecification ms:
resolvedMember = ms.Handle.Resolve(new SimpleMetadataResolveContext(ms.Module));
if (resolvedMember != null && !resolvedMember.IsNil) {
switch (resolvedMember) {
case MethodDefinition md:
return assemblyListTreeNode.FindMethodNode(md);
default:
throw new NotSupportedException();
}
}
return null;
case ITypeDefinition type:
return assemblyListTreeNode.FindTypeNode(type);
case IField fd:
return assemblyListTreeNode.FindFieldNode(fd);
case IMethod md:
return assemblyListTreeNode.FindMethodNode(md);
case IProperty pd:
return assemblyListTreeNode.FindPropertyNode(pd);
case IEvent ed:
return assemblyListTreeNode.FindEventNode(ed);
default:
return null;
}
@ -668,11 +631,22 @@ namespace ICSharpCode.ILSpy @@ -668,11 +631,22 @@ namespace ICSharpCode.ILSpy
public Task JumpToReferenceAsync(object reference)
{
decompilationTask = TaskHelper.CompletedTask;
ILSpyTreeNode treeNode = FindTreeNode(reference);
if (treeNode != null) {
SelectNode(treeNode);
} else if (reference is Decompiler.Disassembler.OpCodeInfo opCode) {
OpenLink(opCode.Link);
switch (reference) {
case Decompiler.Disassembler.OpCodeInfo opCode:
OpenLink(opCode.Link);
break;
case ValueTuple<PEFile, System.Reflection.Metadata.EntityHandle> unresolvedEntity:
var typeSystem = new DecompilerTypeSystem(unresolvedEntity.Item1, unresolvedEntity.Item1.GetAssemblyResolver());
if (unresolvedEntity.Item2.Kind.IsTypeKind())
reference = typeSystem.ResolveAsType(unresolvedEntity.Item2).GetDefinition();
else
reference = typeSystem.ResolveAsMember(unresolvedEntity.Item2);
goto default;
default:
ILSpyTreeNode treeNode = FindTreeNode(reference);
if (treeNode != null)
SelectNode(treeNode);
break;
}
return decompilationTask;
}

9
ILSpy/SearchPane.cs

@ -27,6 +27,7 @@ using System.Windows.Input; @@ -27,6 +27,7 @@ using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Threading;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.ILSpy.TreeNodes;
namespace ICSharpCode.ILSpy
@ -216,12 +217,12 @@ namespace ICSharpCode.ILSpy @@ -216,12 +217,12 @@ namespace ICSharpCode.ILSpy
try {
var searcher = GetSearchStrategy(searchMode, searchTerm);
foreach (var loadedAssembly in assemblies) {
var module = loadedAssembly.GetPEFileOrNull();
if (module == null)
var typeSystem = loadedAssembly.GetTypeSystemOrNull();
if (typeSystem == null)
continue;
CancellationToken cancellationToken = cts.Token;
foreach (var type in module.TopLevelTypeDefinitions) {
foreach (var type in typeSystem.GetTopLevelTypeDefinitions()) {
cancellationToken.ThrowIfCancellationRequested();
searcher.Search(type, language, AddResult);
}
@ -333,7 +334,7 @@ namespace ICSharpCode.ILSpy @@ -333,7 +334,7 @@ namespace ICSharpCode.ILSpy
{
public static readonly System.Collections.Generic.IComparer<SearchResult> Comparer = new SearchResultComparer();
public IMetadataEntity Member { get; set; }
public IEntity Member { get; set; }
public float Fitness { get; set; }
public string Location { get; set; }

157
ILSpy/SearchStrategies.cs

@ -14,6 +14,7 @@ using ILOpCode = System.Reflection.Metadata.ILOpCode; @@ -14,6 +14,7 @@ using ILOpCode = System.Reflection.Metadata.ILOpCode;
using ICSharpCode.Decompiler;
using static System.Reflection.Metadata.PEReaderExtensions;
using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.ILSpy
{
@ -43,29 +44,9 @@ namespace ICSharpCode.ILSpy @@ -43,29 +44,9 @@ namespace ICSharpCode.ILSpy
searchTerm = terms;
}
protected float CalculateFitness(IMetadataEntity member)
protected float CalculateFitness(IEntity member)
{
var metadata = member.Module.Metadata;
string text;
switch (member) {
case TypeDefinition td:
text = metadata.GetString(metadata.GetTypeDefinition(td.Handle).Name);
break;
case FieldDefinition fd:
text = metadata.GetString(metadata.GetFieldDefinition(fd.Handle).Name);
break;
case MethodDefinition md:
text = metadata.GetString(metadata.GetMethodDefinition(md.Handle).Name);
break;
case PropertyDefinition pd:
text = metadata.GetString(metadata.GetPropertyDefinition(pd.Handle).Name);
break;
case EventDefinition ed:
text = metadata.GetString(metadata.GetEventDefinition(ed.Handle).Name);
break;
default:
throw new NotSupportedException();
}
string text = member.Name;
// Probably compiler generated types without meaningful names, show them last
if (text.StartsWith("<")) {
@ -75,36 +56,36 @@ namespace ICSharpCode.ILSpy @@ -75,36 +56,36 @@ namespace ICSharpCode.ILSpy
// Constructors always have the same name in IL:
// Use type name instead
if (text == ".cctor" || text == ".ctor") {
//text = member.DeclaringType.Name;
text = member.DeclaringType.Name;
}
// Ignore generic arguments, it not possible to search based on them either
text = Decompiler.TypeSystem.ReflectionHelper.SplitTypeParameterCountFromReflectionName(text);
text = ReflectionHelper.SplitTypeParameterCountFromReflectionName(text);
return 1.0f / text.Length;
}
protected virtual bool IsMatch(FieldDefinition field, Language language)
protected virtual bool IsMatch(IField field, Language language)
{
return false;
}
protected virtual bool IsMatch(PropertyDefinition property, Language language)
protected virtual bool IsMatch(IProperty property, Language language)
{
return false;
}
protected virtual bool IsMatch(EventDefinition ev, Language language)
protected virtual bool IsMatch(IEvent ev, Language language)
{
return false;
}
protected virtual bool IsMatch(MethodDefinition m, Language language)
protected virtual bool IsMatch(IMethod m, Language language)
{
return false;
}
protected virtual bool MatchName(IMetadataEntity m, Language language)
protected virtual bool MatchName(IEntity m, Language language)
{
return IsMatch(t => GetLanguageSpecificName(language, m, regex != null ? fullNameSearch : t.Contains(".")));
}
@ -178,26 +159,25 @@ namespace ICSharpCode.ILSpy @@ -178,26 +159,25 @@ namespace ICSharpCode.ILSpy
return false;
}
string GetLanguageSpecificName(Language language, IMetadataEntity member, bool fullName = false)
string GetLanguageSpecificName(Language language, IEntity member, bool fullName = false)
{
var metadata = member.Module.Metadata;
switch (member) {
case TypeDefinition t:
case ITypeDefinition t:
return language.TypeToString(t, includeNamespace: fullName);
case FieldDefinition f:
case IField f:
return language.FieldToString(f, fullName, fullName);
case PropertyDefinition p:
return language.PropertyToString(p, fullName, fullName, p.Handle.HasMatchingDefaultMemberAttribute(member.Module, out _));
case MethodDefinition m:
case IProperty p:
return language.PropertyToString(p, fullName, fullName, p.IsIndexer);
case IMethod m:
return language.MethodToString(m, fullName, fullName);
case EventDefinition e:
case IEvent e:
return language.EventToString(e, fullName, fullName);
default:
throw new NotSupportedException(member?.GetType() + " not supported!");
}
}
void Add<T>(Func<IEnumerable<T>> itemsGetter, TypeDefinition type, Language language, Action<SearchResult> addResult, Func<T, Language, bool> matcher, Func<T, ImageSource> image) where T : IMetadataEntity
void Add<T>(Func<IEnumerable<T>> itemsGetter, ITypeDefinition type, Language language, Action<SearchResult> addResult, Func<T, Language, bool> matcher, Func<T, ImageSource> image) where T : IEntity
{
IEnumerable<T> items = Enumerable.Empty<T>();
try {
@ -219,30 +199,18 @@ namespace ICSharpCode.ILSpy @@ -219,30 +199,18 @@ namespace ICSharpCode.ILSpy
}
}
public virtual void Search(TypeDefinition type, Language language, Action<SearchResult> addResult)
public virtual void Search(ITypeDefinition type, Language language, Action<SearchResult> addResult)
{
var metadata = type.Module.Metadata;
var td = metadata.GetTypeDefinition(type.Handle);
Add(() => td.GetFields().Select(f => new FieldDefinition(type.Module, f)), type, language, addResult, IsMatch, FieldTreeNode.GetIcon);
Add(() => td.GetProperties().Select(p => new PropertyDefinition(type.Module, p)), type, language, addResult, IsMatch, p => PropertyTreeNode.GetIcon(p));
Add(() => td.GetEvents().Select(e => new EventDefinition(type.Module, e)), type, language, addResult, IsMatch, EventTreeNode.GetIcon);
Add(() => td.GetMethods().Where(m => NotSpecialMethod(m, metadata)).Select(m => new MethodDefinition(type.Module, m)), type, language, addResult, IsMatch, MethodTreeNode.GetIcon);
Add(() => type.Fields, type, language, addResult, IsMatch, FieldTreeNode.GetIcon);
Add(() => type.Properties, type, language, addResult, IsMatch, p => PropertyTreeNode.GetIcon(p));
Add(() => type.Events, type, language, addResult, IsMatch, EventTreeNode.GetIcon);
Add(() => type.Methods.Where(m => !m.IsAccessor), type, language, addResult, IsMatch, MethodTreeNode.GetIcon);
foreach (var nestedType in td.GetNestedTypes()) {
Search(new TypeDefinition(type.Module, nestedType), language, addResult);
foreach (var nestedType in type.NestedTypes) {
Search(nestedType, language, addResult);
}
}
bool NotSpecialMethod(SRM.MethodDefinitionHandle method, SRM.MetadataReader metadata)
{
return (method.GetMethodSemanticsAttributes(metadata) & (
MethodSemanticsAttributes.Setter
| MethodSemanticsAttributes.Getter
| MethodSemanticsAttributes.Adder
| MethodSemanticsAttributes.Remover
| MethodSemanticsAttributes.Raiser)) == 0;
}
Regex SafeNewRegex(string unsafePattern)
{
try {
@ -265,9 +233,9 @@ namespace ICSharpCode.ILSpy @@ -265,9 +233,9 @@ namespace ICSharpCode.ILSpy
}
}
protected override bool MatchName(IMetadataEntity m, Language language)
protected override bool MatchName(IEntity m, Language language)
{
return SRM.Ecma335.MetadataTokens.GetToken(m.Handle) == searchTermToken;
return SRM.Ecma335.MetadataTokens.GetToken(m.MetadataToken) == searchTermToken;
}
}
@ -308,26 +276,24 @@ namespace ICSharpCode.ILSpy @@ -308,26 +276,24 @@ namespace ICSharpCode.ILSpy
}
}
protected override bool IsMatch(FieldDefinition field, Language language)
protected override bool IsMatch(IField field, Language language)
{
return IsLiteralMatch(field.DecodeConstant());
return IsLiteralMatch(field.ConstantValue);
}
protected override bool IsMatch(PropertyDefinition property, Language language)
protected override bool IsMatch(IProperty property, Language language)
{
var accessors = property.Module.Metadata.GetPropertyDefinition(property.Handle).GetAccessors();
return MethodIsLiteralMatch(accessors.Getter, property.Module) || MethodIsLiteralMatch(accessors.Setter, property.Module);
return MethodIsLiteralMatch(property.Getter) || MethodIsLiteralMatch(property.Setter);
}
protected override bool IsMatch(EventDefinition ev, Language language)
protected override bool IsMatch(IEvent ev, Language language)
{
var accessors = ev.Module.Metadata.GetEventDefinition(ev.Handle).GetAccessors();
return MethodIsLiteralMatch(accessors.Adder, ev.Module) || MethodIsLiteralMatch(accessors.Remover, ev.Module) || MethodIsLiteralMatch(accessors.Raiser, ev.Module);
return MethodIsLiteralMatch(ev.AddAccessor) || MethodIsLiteralMatch(ev.RemoveAccessor) || MethodIsLiteralMatch(ev.InvokeAccessor);
}
protected override bool IsMatch(MethodDefinition m, Language language)
protected override bool IsMatch(IMethod m, Language language)
{
return MethodIsLiteralMatch(m.Handle, m.Module);
return MethodIsLiteralMatch(m);
}
bool IsLiteralMatch(object val)
@ -351,14 +317,15 @@ namespace ICSharpCode.ILSpy @@ -351,14 +317,15 @@ namespace ICSharpCode.ILSpy
}
}
bool MethodIsLiteralMatch(SRM.MethodDefinitionHandle m, PEFile module)
bool MethodIsLiteralMatch(IMethod method)
{
if (module == null)
if (method == null)
return false;
var metadata = module.Metadata;
var module = ((MetadataAssembly)method.ParentAssembly).PEFile;
var m = (SRM.MethodDefinitionHandle)method.MetadataToken;
if (m.IsNil)
return false;
var methodDefinition = metadata.GetMethodDefinition(m);
var methodDefinition = module.Metadata.GetMethodDefinition(m);
if (!methodDefinition.HasBody())
return false;
var blob = module.Reader.GetMethodBody(methodDefinition.RelativeVirtualAddress).GetILReader();
@ -455,7 +422,7 @@ namespace ICSharpCode.ILSpy @@ -455,7 +422,7 @@ namespace ICSharpCode.ILSpy
return true;
break;
case ILOpCode.Ldstr:
if ((string)searchTermLiteralValue == ILParser.DecodeUserString(ref blob, metadata))
if ((string)searchTermLiteralValue == ILParser.DecodeUserString(ref blob, module.Metadata))
return true;
break;
}
@ -467,7 +434,7 @@ namespace ICSharpCode.ILSpy @@ -467,7 +434,7 @@ namespace ICSharpCode.ILSpy
ILParser.SkipOperand(ref blob, code);
continue;
}
if (IsMatch(t => ILParser.DecodeUserString(ref blob, metadata)))
if (base.IsMatch(t => ILParser.DecodeUserString(ref blob, module.Metadata)))
return true;
}
}
@ -499,22 +466,22 @@ namespace ICSharpCode.ILSpy @@ -499,22 +466,22 @@ namespace ICSharpCode.ILSpy
this.searchKind = searchKind;
}
protected override bool IsMatch(FieldDefinition field, Language language)
protected override bool IsMatch(IField field, Language language)
{
return (searchKind == MemberSearchKind.All || searchKind == MemberSearchKind.Field) && MatchName(field, language);
}
protected override bool IsMatch(PropertyDefinition property, Language language)
protected override bool IsMatch(IProperty property, Language language)
{
return (searchKind == MemberSearchKind.All || searchKind == MemberSearchKind.Property) && MatchName(property, language);
}
protected override bool IsMatch(EventDefinition ev, Language language)
protected override bool IsMatch(IEvent ev, Language language)
{
return (searchKind == MemberSearchKind.All || searchKind == MemberSearchKind.Event) && MatchName(ev, language);
}
protected override bool IsMatch(MethodDefinition m, Language language)
protected override bool IsMatch(IMethod m, Language language)
{
return (searchKind == MemberSearchKind.All || searchKind == MemberSearchKind.Method) && MatchName(m, language);
}
@ -527,26 +494,23 @@ namespace ICSharpCode.ILSpy @@ -527,26 +494,23 @@ namespace ICSharpCode.ILSpy
{
}
public override void Search(TypeDefinition type, Language language, Action<SearchResult> addResult)
public override void Search(ITypeDefinition type, Language language, Action<SearchResult> addResult)
{
var metadata = type.Module.Metadata;
var td = metadata.GetTypeDefinition(type.Handle);
if (MatchName(type, language)) {
string name = language.TypeToString(type, includeNamespace: false);
var declaringType = td.GetDeclaringType();
var declaringType = type.DeclaringTypeDefinition;
addResult(new SearchResult {
Member = type,
Fitness = CalculateFitness(type),
Image = TypeTreeNode.GetIcon(type),
Name = name,
LocationImage = !declaringType.IsNil ? TypeTreeNode.GetIcon(new TypeDefinition(type.Module, declaringType)) : Images.Namespace,
Location = !declaringType.IsNil ? language.TypeToString(new TypeDefinition(type.Module, declaringType), includeNamespace: true) : type.Handle.GetFullTypeName(metadata).TopLevelTypeName.Namespace
LocationImage = declaringType != null ? TypeTreeNode.GetIcon(declaringType) : Images.Namespace,
Location = declaringType != null ? language.TypeToString(declaringType, includeNamespace: true) : type.Namespace
});
}
foreach (var nestedType in td.GetNestedTypes()) {
Search(new TypeDefinition(type.Module, nestedType), language, addResult);
foreach (var nestedType in type.NestedTypes) {
Search(nestedType, language, addResult);
}
}
}
@ -558,42 +522,41 @@ namespace ICSharpCode.ILSpy @@ -558,42 +522,41 @@ namespace ICSharpCode.ILSpy
{
}
public override void Search(TypeDefinition type, Language language, Action<SearchResult> addResult)
public override void Search(ITypeDefinition type, Language language, Action<SearchResult> addResult)
{
if (MatchName(type, language))
{
string name = language.TypeToString(type, includeNamespace: false);
var metadata = type.Module.Metadata;
var declaringType = metadata.GetTypeDefinition(type.Handle).GetDeclaringType();
var declaringType = type.DeclaringTypeDefinition;
addResult(new SearchResult {
Member = type,
Image = TypeTreeNode.GetIcon(type),
Fitness = CalculateFitness(type),
Name = name,
LocationImage = !declaringType.IsNil ? TypeTreeNode.GetIcon(new TypeDefinition(type.Module, declaringType)) : Images.Namespace,
Location = !declaringType.IsNil ? language.TypeToString(new TypeDefinition(type.Module, declaringType), includeNamespace: true) : type.Handle.GetFullTypeName(metadata).TopLevelTypeName.Namespace
LocationImage = declaringType != null ? TypeTreeNode.GetIcon(declaringType) : Images.Namespace,
Location = declaringType != null ? language.TypeToString(declaringType, includeNamespace: true) : type.Namespace
});
}
base.Search(type, language, addResult);
}
protected override bool IsMatch(FieldDefinition field, Language language)
protected override bool IsMatch(IField field, Language language)
{
return MatchName(field, language);
}
protected override bool IsMatch(PropertyDefinition property, Language language)
protected override bool IsMatch(IProperty property, Language language)
{
return MatchName(property, language);
}
protected override bool IsMatch(EventDefinition ev, Language language)
protected override bool IsMatch(IEvent ev, Language language)
{
return MatchName(ev, language);
}
protected override bool IsMatch(MethodDefinition m, Language language)
protected override bool IsMatch(IMethod m, Language language)
{
return MatchName(m, language);
}

65
ILSpy/TextView/AvalonEditTextOutput.cs

@ -20,6 +20,7 @@ using System; @@ -20,6 +20,7 @@ using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection.Metadata;
using System.Text;
using System.Windows;
@ -27,6 +28,8 @@ using ICSharpCode.AvalonEdit.Document; @@ -27,6 +28,8 @@ using ICSharpCode.AvalonEdit.Document;
using ICSharpCode.AvalonEdit.Folding;
using ICSharpCode.AvalonEdit.Highlighting;
using ICSharpCode.AvalonEdit.Rendering;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
using TextLocation = ICSharpCode.Decompiler.CSharp.Syntax.TextLocation;
namespace ICSharpCode.ILSpy.TextView
@ -206,26 +209,72 @@ namespace ICSharpCode.ILSpy.TextView @@ -206,26 +209,72 @@ namespace ICSharpCode.ILSpy.TextView
throw new OutputLengthExceededException();
}
}
public void WriteDefinition(string text, object definition, bool isLocal = true)
public void WriteReference(Decompiler.Disassembler.OpCodeInfo opCode)
{
WriteIndent();
int start = this.TextLength;
b.Append(opCode.Name);
int end = this.TextLength;
references.Add(new ReferenceSegment { StartOffset = start, EndOffset = end, Reference = opCode });
}
public void WriteReference(PEFile module, EntityHandle handle, string text, bool isDefinition = false)
{
WriteIndent();
int start = this.TextLength;
b.Append(text);
int end = this.TextLength;
this.DefinitionLookup.AddDefinition(definition, this.TextLength);
references.Add(new ReferenceSegment { StartOffset = start, EndOffset = end, Reference = definition, IsLocal = isLocal, IsLocalTarget = true });
if (isDefinition) {
this.DefinitionLookup.AddDefinition((module, handle), this.TextLength);
references.Add(new ReferenceSegment { StartOffset = start, EndOffset = end, Reference = (module, handle) });
} else {
references.Add(new ReferenceSegment { StartOffset = start, EndOffset = end, Reference = (module, handle) });
}
}
public void WriteReference(string text, object reference, bool isLocal = false)
public void WriteReference(IType type, string text, bool isDefinition = false)
{
WriteIndent();
int start = this.TextLength;
b.Append(text);
int end = this.TextLength;
references.Add(new ReferenceSegment { StartOffset = start, EndOffset = end, Reference = reference, IsLocal = isLocal });
if (isDefinition) {
this.DefinitionLookup.AddDefinition(type, this.TextLength);
references.Add(new ReferenceSegment { StartOffset = start, EndOffset = end, Reference = type });
} else {
references.Add(new ReferenceSegment { StartOffset = start, EndOffset = end, Reference = type });
}
}
public void WriteReference(IMember member, string text, bool isDefinition = false)
{
WriteIndent();
int start = this.TextLength;
b.Append(text);
int end = this.TextLength;
if (isDefinition) {
this.DefinitionLookup.AddDefinition(member, this.TextLength);
references.Add(new ReferenceSegment { StartOffset = start, EndOffset = end, Reference = member });
} else {
references.Add(new ReferenceSegment { StartOffset = start, EndOffset = end, Reference = member });
}
}
public void WriteLocalReference(string text, object reference, bool isDefinition = false)
{
WriteIndent();
int start = this.TextLength;
b.Append(text);
int end = this.TextLength;
if (isDefinition) {
this.DefinitionLookup.AddDefinition(reference, this.TextLength);
references.Add(new ReferenceSegment { StartOffset = start, EndOffset = end, Reference = reference, IsLocal = true, IsLocalTarget = true });
} else {
references.Add(new ReferenceSegment { StartOffset = start, EndOffset = end, Reference = reference, IsLocal = true });
}
}
public void MarkFoldStart(string collapsedText = "...", bool defaultCollapsed = false)
{
WriteIndent();

38
ILSpy/TextView/DecompilerTextView.cs

@ -46,6 +46,7 @@ using ICSharpCode.Decompiler; @@ -46,6 +46,7 @@ using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.CSharp;
using ICSharpCode.Decompiler.Documentation;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.ILSpy.AvalonEdit;
using ICSharpCode.ILSpy.Options;
using ICSharpCode.ILSpy.TreeNodes;
@ -206,14 +207,41 @@ namespace ICSharpCode.ILSpy.TextView @@ -206,14 +207,41 @@ namespace ICSharpCode.ILSpy.TextView
}
}
return $"{code.Name} (0x{code.Code:x})";
} else if (segment.Reference is IMetadataEntity entity) {
} else if (segment.Reference is IEntity entity) {
XmlDocRenderer renderer = new XmlDocRenderer();
renderer.AppendText(MainWindow.Instance.CurrentLanguage.GetTooltip(new Entity(entity.Module, entity.Handle)));
renderer.AppendText(MainWindow.Instance.CurrentLanguage.GetTooltip(entity));
try {
//var docProvider = entity.Module.DocumentationResolver.GetProvider(); // TODO implement proper API
var docProvider = XmlDocLoader.LoadDocumentation(entity.Module);
if (entity.ParentAssembly == null || entity.ParentAssembly.PEFile == null)
return null;
var docProvider = XmlDocLoader.LoadDocumentation(entity.ParentAssembly.PEFile);
if (docProvider != null) {
string documentation = docProvider.GetDocumentation(XmlDocKeyProvider.GetKey(new Entity(entity.Module, entity.Handle)));
string documentation = docProvider.GetDocumentation(XmlDocKeyProvider.GetKey(entity));
if (documentation != null) {
renderer.AppendText(Environment.NewLine);
renderer.AddXmlDocumentation(documentation);
}
}
} catch (XmlException) {
// ignore
}
return renderer.CreateTextBlock();
} else if (segment.Reference is ValueTuple<PEFile, System.Reflection.Metadata.EntityHandle> unresolvedEntity) {
var typeSystem = new DecompilerTypeSystem(unresolvedEntity.Item1, unresolvedEntity.Item1.GetAssemblyResolver());
IEntity resolved;
if (unresolvedEntity.Item2.Kind.IsTypeKind())
resolved = typeSystem.ResolveAsType(unresolvedEntity.Item2).GetDefinition();
else
resolved = typeSystem.ResolveAsMember(unresolvedEntity.Item2);
if (resolved == null)
return null;
XmlDocRenderer renderer = new XmlDocRenderer();
renderer.AppendText(MainWindow.Instance.CurrentLanguage.GetTooltip(resolved));
try {
if (resolved.ParentAssembly == null || resolved.ParentAssembly.PEFile == null)
return null;
var docProvider = XmlDocLoader.LoadDocumentation(resolved.ParentAssembly.PEFile);
if (docProvider != null) {
string documentation = docProvider.GetDocumentation(XmlDocKeyProvider.GetKey(resolved));
if (documentation != null) {
renderer.AppendText(Environment.NewLine);
renderer.AddXmlDocumentation(documentation);

13
ILSpy/TreeNodes/Analyzer/AnalyzeContextMenuEntry.cs

@ -18,7 +18,7 @@ @@ -18,7 +18,7 @@
using System;
using System.Linq;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{
@ -37,7 +37,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -37,7 +37,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
public bool IsEnabled(TextViewContext context)
{
if (context.SelectedTreeNodes == null)
return context.Reference != null && context.Reference.Reference is IMetadataEntity;
return context.Reference != null && context.Reference.Reference is IEntity;
foreach (IMemberTreeNode node in context.SelectedTreeNodes) {
if (!IsValidReference(node.Member))
return false;
@ -48,11 +48,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -48,11 +48,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
bool IsValidReference(object reference)
{
return reference is IMetadataEntity
|| reference is MemberReference
|| reference is MethodSpecification
|| reference is TypeReference
|| reference is TypeSpecification;
return reference is IEntity;
}
public void Execute(TextViewContext context)
@ -67,7 +63,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -67,7 +63,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
}
public static void Analyze(object member)
{
{/*
switch (member) {
case IMetadataEntity entity:
switch (entity) {
@ -133,6 +129,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -133,6 +129,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
}
break;
}
*/
}
}
}

6
ILSpy/TreeNodes/Analyzer/ScopedWhereUsedAnalyzer.cs

@ -233,7 +233,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -233,7 +233,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
IEnumerable<T> FindReferencesInAssembly(Decompiler.Metadata.PEFile module, CancellationToken ct)
{
IDecompilerTypeSystem ts = provideTypeSystem ? new DecompilerTypeSystem(module) : null;
IDecompilerTypeSystem ts = provideTypeSystem ? new DecompilerTypeSystem(module, module.GetAssemblyResolver()) : null;
var metadata = module.Metadata;
foreach (var type in TreeTraversal.PreOrder(metadata.TypeDefinitions, t => metadata.GetTypeDefinition(t).GetNestedTypes())) {
ct.ThrowIfCancellationRequested();
@ -247,7 +247,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -247,7 +247,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
IEnumerable<T> FindReferencesInTypeScope(CancellationToken ct)
{
IDecompilerTypeSystem ts = provideTypeSystem ? new DecompilerTypeSystem(assemblyScope) : null;
IDecompilerTypeSystem ts = provideTypeSystem ? new DecompilerTypeSystem(assemblyScope, assemblyScope.GetAssemblyResolver()) : null;
foreach (var type in TreeTraversal.PreOrder(typeScopeHandle, t => assemblyScope.Metadata.GetTypeDefinition(t).GetNestedTypes())) {
ct.ThrowIfCancellationRequested();
var codeMappingInfo = language.GetCodeMappingInfo(assemblyScope, type);
@ -260,7 +260,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -260,7 +260,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
IEnumerable<T> FindReferencesInEnclosingTypeScope(CancellationToken ct)
{
IDecompilerTypeSystem ts = provideTypeSystem ? new DecompilerTypeSystem(assemblyScope) : null;
IDecompilerTypeSystem ts = provideTypeSystem ? new DecompilerTypeSystem(assemblyScope, assemblyScope.GetAssemblyResolver()) : null;
var codeMappingInfo = language.GetCodeMappingInfo(assemblyScope, typeScope.GetDeclaringType());
foreach (var type in TreeTraversal.PreOrder(typeScope.GetDeclaringType(), t => assemblyScope.Metadata.GetTypeDefinition(t).GetNestedTypes())) {
ct.ThrowIfCancellationRequested();

99
ILSpy/TreeNodes/AssemblyListTreeNode.cs

@ -26,6 +26,7 @@ using System.Reflection.PortableExecutable; @@ -26,6 +26,7 @@ using System.Reflection.PortableExecutable;
using System.Windows;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.TreeView;
namespace ICSharpCode.ILSpy.TreeNodes
@ -176,6 +177,13 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -176,6 +177,13 @@ namespace ICSharpCode.ILSpy.TreeNodes
return null;
}
public AssemblyTreeNode FindAssemblyNode(IAssembly module)
{
if (!(module is MetadataAssembly assembly))
return null;
return FindAssemblyNode(assembly.PEFile);
}
public AssemblyTreeNode FindAssemblyNode(PEFile module)
{
if (module == null)
@ -204,17 +212,19 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -204,17 +212,19 @@ namespace ICSharpCode.ILSpy.TreeNodes
/// Looks up the type node corresponding to the type definition.
/// Returns null if no matching node is found.
/// </summary>
public TypeTreeNode FindTypeNode(TypeDefinition def)
public TypeTreeNode FindTypeNode(ITypeDefinition def)
{
var declaringType = def.Module.Metadata.GetTypeDefinition(def.Handle).GetDeclaringType();
if (!declaringType.IsNil) {
TypeTreeNode decl = FindTypeNode(new TypeDefinition(def.Module, declaringType));
if (def == null)
return null;
var declaringType = def.DeclaringTypeDefinition;
if (declaringType != null) {
TypeTreeNode decl = FindTypeNode(declaringType);
if (decl != null) {
decl.EnsureLazyChildren();
return decl.Children.OfType<TypeTreeNode>().FirstOrDefault(t => t.TypeDefinition == def && !t.IsHidden);
return decl.Children.OfType<TypeTreeNode>().FirstOrDefault(t => t.TypeDefinition.Equals(def) && !t.IsHidden);
}
} else {
AssemblyTreeNode asm = FindAssemblyNode(def.Module);
AssemblyTreeNode asm = FindAssemblyNode(def.ParentAssembly);
if (asm != null) {
return asm.FindTypeNode(def);
}
@ -226,78 +236,79 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -226,78 +236,79 @@ namespace ICSharpCode.ILSpy.TreeNodes
/// Looks up the method node corresponding to the method definition.
/// Returns null if no matching node is found.
/// </summary>
public ILSpyTreeNode FindMethodNode(MethodDefinition def)
public ILSpyTreeNode FindMethodNode(IMethod def)
{
TypeTreeNode typeNode = FindTypeNode(new TypeDefinition(def.Module, def.Module.Metadata.GetMethodDefinition(def.Handle).GetDeclaringType()));
TypeTreeNode typeNode = FindTypeNode(def.DeclaringTypeDefinition);
if (typeNode == null)
return null;
typeNode.EnsureLazyChildren();
MethodTreeNode methodNode = typeNode.Children.OfType<MethodTreeNode>().FirstOrDefault(m => m.MethodDefinition == def && !m.IsHidden);
if (methodNode != null)
return methodNode;
foreach (var p in typeNode.Children.OfType<ILSpyTreeNode>()) {
if (p.IsHidden)
continue;
// method might be a child of a property or event
if (p is PropertyTreeNode || p is EventTreeNode) {
p.EnsureLazyChildren();
methodNode = p.Children.OfType<MethodTreeNode>().FirstOrDefault(m => m.MethodDefinition == def);
if (methodNode != null) {
// If the requested method is a property or event accessor, and accessors are
// hidden in the UI, then return the owning property or event.
if (methodNode.IsHidden)
return p;
else
return methodNode;
}
}
// method might be an accessor, must look for parent node
ILSpyTreeNode parentNode = typeNode;
MethodTreeNode methodNode;
parentNode.EnsureLazyChildren();
switch (def.AccessorOwner) {
case IProperty p:
parentNode = parentNode.Children.OfType<PropertyTreeNode>().FirstOrDefault(m => m.PropertyDefinition.MetadataToken == p.MetadataToken && !m.IsHidden);
if (parentNode == null)
return null;
parentNode.EnsureLazyChildren();
methodNode = parentNode.Children.OfType<MethodTreeNode>().FirstOrDefault(m => m.MethodDefinition.MetadataToken == def.MetadataToken && !m.IsHidden);
if (methodNode == null || methodNode.IsHidden)
return parentNode;
return methodNode;
case IEvent e:
parentNode = parentNode.Children.OfType<EventTreeNode>().FirstOrDefault(m => m.EventDefinition.MetadataToken == e.MetadataToken && !m.IsHidden);
if (parentNode == null)
return null;
parentNode.EnsureLazyChildren();
methodNode = parentNode.Children.OfType<MethodTreeNode>().FirstOrDefault(m => m.MethodDefinition.MetadataToken == def.MetadataToken && !m.IsHidden);
if (methodNode == null || methodNode.IsHidden)
return parentNode;
return methodNode;
default:
methodNode = typeNode.Children.OfType<MethodTreeNode>().FirstOrDefault(m => m.MethodDefinition.MetadataToken == def.MetadataToken && !m.IsHidden);
if (methodNode != null)
return methodNode;
return null;
}
return null;
}
/// <summary>
/// Looks up the field node corresponding to the field definition.
/// Returns null if no matching node is found.
/// </summary>
public FieldTreeNode FindFieldNode(FieldDefinition def)
public FieldTreeNode FindFieldNode(IField def)
{
TypeTreeNode typeNode = FindTypeNode(new TypeDefinition(def.Module, def.Module.Metadata.GetFieldDefinition(def.Handle).GetDeclaringType()));
TypeTreeNode typeNode = FindTypeNode(def.DeclaringTypeDefinition);
if (typeNode == null)
return null;
typeNode.EnsureLazyChildren();
return typeNode.Children.OfType<FieldTreeNode>().FirstOrDefault(m => m.FieldDefinition == def && !m.IsHidden);
return typeNode.Children.OfType<FieldTreeNode>().FirstOrDefault(m => m.FieldDefinition.Equals(def) && !m.IsHidden);
}
/// <summary>
/// Looks up the property node corresponding to the property definition.
/// Returns null if no matching node is found.
/// </summary>
public PropertyTreeNode FindPropertyNode(PropertyDefinition def)
public PropertyTreeNode FindPropertyNode(IProperty def)
{
var metadata = def.Module.Metadata;
var accessor = metadata.GetMethodDefinition(metadata.GetPropertyDefinition(def.Handle).GetAccessors().GetAny());
TypeTreeNode typeNode = FindTypeNode(new TypeDefinition(def.Module, accessor.GetDeclaringType()));
TypeTreeNode typeNode = FindTypeNode(def.DeclaringTypeDefinition);
if (typeNode == null)
return null;
typeNode.EnsureLazyChildren();
return typeNode.Children.OfType<PropertyTreeNode>().FirstOrDefault(m => m.PropertyDefinition == def && !m.IsHidden);
return typeNode.Children.OfType<PropertyTreeNode>().FirstOrDefault(m => m.PropertyDefinition.Equals(def) && !m.IsHidden);
}
/// <summary>
/// Looks up the event node corresponding to the event definition.
/// Returns null if no matching node is found.
/// </summary>
public EventTreeNode FindEventNode(EventDefinition def)
public EventTreeNode FindEventNode(IEvent def)
{
var metadata = def.Module.Metadata;
var accessor = metadata.GetMethodDefinition(metadata.GetEventDefinition(def.Handle).GetAccessors().GetAny());
TypeTreeNode typeNode = FindTypeNode(new TypeDefinition(def.Module, accessor.GetDeclaringType()));
TypeTreeNode typeNode = FindTypeNode(def.DeclaringTypeDefinition);
if (typeNode == null)
return null;
typeNode.EnsureLazyChildren();
return typeNode.Children.OfType<EventTreeNode>().FirstOrDefault(m => m.EventDefinition == def && !m.IsHidden);
return typeNode.Children.OfType<EventTreeNode>().FirstOrDefault(m => m.EventDefinition.Equals(def) && !m.IsHidden);
}
#endregion
}

26
ILSpy/TreeNodes/AssemblyTreeNode.cs

@ -30,7 +30,7 @@ using ICSharpCode.ILSpy.TextView; @@ -30,7 +30,7 @@ using ICSharpCode.ILSpy.TextView;
using ICSharpCode.TreeView;
using Microsoft.Win32;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.TypeSystem.Implementation;
using TypeDefinitionHandle = System.Reflection.Metadata.TypeDefinitionHandle;
namespace ICSharpCode.ILSpy.TreeNodes
{
@ -41,7 +41,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -41,7 +41,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
public sealed class AssemblyTreeNode : ILSpyTreeNode
{
readonly Dictionary<string, NamespaceTreeNode> namespaces = new Dictionary<string, NamespaceTreeNode>();
readonly Dictionary<TypeDefinition, TypeTreeNode> typeDict = new Dictionary<TypeDefinition, TypeTreeNode>();
readonly Dictionary<TypeDefinitionHandle, TypeTreeNode> typeDict = new Dictionary<TypeDefinitionHandle, TypeTreeNode>();
ICompilation typeSystem;
public AssemblyTreeNode(LoadedAssembly assembly)
@ -135,7 +135,8 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -135,7 +135,8 @@ namespace ICSharpCode.ILSpy.TreeNodes
// if we crashed on loading, then we don't have any children
return;
}
typeSystem = new SimpleCompilation(module, MinimalCorlib.Instance);
typeSystem = LoadedAssembly.GetTypeSystemOrNull();
var assembly = (MetadataAssembly)typeSystem.MainAssembly;
var metadata = module.Metadata;
this.Children.Add(new ReferenceFolderTreeNode(module, this));
@ -144,16 +145,13 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -144,16 +145,13 @@ namespace ICSharpCode.ILSpy.TreeNodes
foreach (NamespaceTreeNode ns in namespaces.Values) {
ns.Children.Clear();
}
foreach (var typeHandle in metadata.GetTopLevelTypeDefinitions().OrderBy(t => t.GetFullTypeName(metadata).ToString(), NaturalStringComparer.Instance)) {
NamespaceTreeNode ns;
var type = new TypeDefinition(module, typeHandle);
var namespaceString = metadata.GetString(metadata.GetTypeDefinition(typeHandle).Namespace);
if (!namespaces.TryGetValue(namespaceString, out ns)) {
ns = new NamespaceTreeNode(namespaceString);
namespaces[namespaceString] = ns;
foreach (var type in assembly.TopLevelTypeDefinitions.OrderBy(t => t.ReflectionName, NaturalStringComparer.Instance)) {
if (!namespaces.TryGetValue(type.Namespace, out NamespaceTreeNode ns)) {
ns = new NamespaceTreeNode(type.Namespace);
namespaces[type.Namespace] = ns;
}
TypeTreeNode node = new TypeTreeNode(type, this);
typeDict[type] = node;
typeDict[(TypeDefinitionHandle)type.MetadataToken] = node;
ns.Children.Add(node);
}
foreach (NamespaceTreeNode ns in namespaces.Values.OrderBy(n => n.Name, NaturalStringComparer.Instance)) {
@ -167,13 +165,13 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -167,13 +165,13 @@ namespace ICSharpCode.ILSpy.TreeNodes
/// <summary>
/// Finds the node for a top-level type.
/// </summary>
public TypeTreeNode FindTypeNode(TypeDefinition def)
public TypeTreeNode FindTypeNode(ITypeDefinition type)
{
if (def == null)
if (type == null)
return null;
EnsureLazyChildren();
TypeTreeNode node;
if (typeDict.TryGetValue(def, out node))
if (typeDict.TryGetValue((TypeDefinitionHandle)type.MetadataToken, out node))
return node;
else
return null;

74
ILSpy/TreeNodes/BaseTypesEntryNode.cs

@ -17,66 +17,76 @@ @@ -17,66 +17,76 @@
// DEALINGS IN THE SOFTWARE.
using System;
using System.Diagnostics;
using System.Linq;
using System.Reflection.Metadata;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.TreeView;
namespace ICSharpCode.ILSpy.TreeNodes
{
sealed class BaseTypesEntryNode : ILSpyTreeNode, IMemberTreeNode
{
readonly Entity tr;
readonly GenericContext context;
readonly PEFile module;
readonly EntityHandle handle;
readonly IType type;
readonly bool isInterface;
readonly bool showExpander;
readonly object icon;
bool showExpander;
public BaseTypesEntryNode(GenericContext context, Entity entity, bool isInterface)
public BaseTypesEntryNode(PEFile module, EntityHandle handle, IType type, bool isInterface)
{
if (entity.IsNil) throw new ArgumentNullException(nameof(entity));
this.tr = entity;
this.context = context;
if (handle.IsNil)
throw new ArgumentNullException(nameof(handle));
this.module = module ?? throw new ArgumentNullException(nameof(module));
this.handle = handle;
this.type = type;
this.isInterface = isInterface;
this.LazyLoading = true;
TryResolve(module, handle, type);
}
var td = tr.ResolveAsType();
if (!td.IsNil) {
var typeDef = td.Module.Metadata.GetTypeDefinition(td.Handle);
showExpander = !typeDef.BaseType.IsNil || typeDef.GetInterfaceImplementations().Any();
icon = TypeTreeNode.GetIcon(td);
ITypeDefinition TryResolve(PEFile module, EntityHandle handle, IType type, bool mayRetry = true)
{
DecompilerTypeSystem typeSystem = new DecompilerTypeSystem(module, module.GetAssemblyResolver());
var t = typeSystem.ResolveAsType(handle).GetDefinition();
if (t != null) {
showExpander = t.DirectBaseTypes.Any();
var other = t.ParentAssembly.PEFile.GetTypeSystemOrNull();
Debug.Assert(other != null);
t = other.FindType(t.FullTypeName).GetDefinition();
} else {
showExpander = false;
icon = isInterface ? Images.Interface : Images.Class;
showExpander = mayRetry;
}
RaisePropertyChanged(nameof(Text));
RaisePropertyChanged(nameof(ShowExpander));
return t;
}
public override bool ShowExpander => showExpander;
public override bool ShowExpander => showExpander && base.ShowExpander;
public override object Text
{
get { return this.Language.TypeToString(tr, context, includeNamespace: true) + tr.Handle.ToSuffixString(); }
}
public override object Text => this.Language.TypeToString(type, includeNamespace: true) + handle.ToSuffixString();
public override object Icon => icon;
public override object Icon => isInterface ? Images.Interface : Images.Class;
protected override void LoadChildren()
{
var td = tr.ResolveAsType();
if (!td.IsNil) {
BaseTypesTreeNode.AddBaseTypes(this.Children, td);
var t = TryResolve(module, handle, type, false);
if (t != null) {
BaseTypesTreeNode.AddBaseTypes(this.Children, t.ParentAssembly.PEFile, t);
}
}
public override void ActivateItem(System.Windows.RoutedEventArgs e)
{
var td = tr.ResolveAsType();
e.Handled = ActivateItem(this, td);
var t = TryResolve(module, handle, type, false);
e.Handled = ActivateItem(this, t);
}
internal static bool ActivateItem(SharpTreeNode node, TypeDefinition def)
internal static bool ActivateItem(SharpTreeNode node, ITypeDefinition def)
{
if (!def.IsNil) {
if (def != null) {
var assemblyListNode = node.Ancestors().OfType<AssemblyListTreeNode>().FirstOrDefault();
if (assemblyListNode != null) {
assemblyListNode.Select(assemblyListNode.FindTypeNode(def));
@ -88,9 +98,13 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -88,9 +98,13 @@ namespace ICSharpCode.ILSpy.TreeNodes
public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
{
language.WriteCommentLine(output, language.TypeToString(tr, context, includeNamespace: true));
language.WriteCommentLine(output, language.TypeToString(type, includeNamespace: true));
}
IMetadataEntity IMemberTreeNode.Member => tr;
IEntity IMemberTreeNode.Member {
get {
return TryResolve(module, handle, type, false);
}
}
}
}

34
ILSpy/TreeNodes/BaseTypesTreeNode.cs

@ -17,9 +17,12 @@ @@ -17,9 +17,12 @@
// DEALINGS IN THE SOFTWARE.
using System;
using System.Linq;
using System.Reflection.Metadata;
using System.Windows.Threading;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.TreeView;
namespace ICSharpCode.ILSpy.TreeNodes
@ -29,10 +32,12 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -29,10 +32,12 @@ namespace ICSharpCode.ILSpy.TreeNodes
/// </summary>
sealed class BaseTypesTreeNode : ILSpyTreeNode
{
readonly TypeDefinition type;
readonly PEFile module;
readonly ITypeDefinition type;
public BaseTypesTreeNode(TypeDefinition type)
public BaseTypesTreeNode(PEFile module, ITypeDefinition type)
{
this.module = module;
this.type = type;
this.LazyLoading = true;
}
@ -43,19 +48,24 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -43,19 +48,24 @@ namespace ICSharpCode.ILSpy.TreeNodes
protected override void LoadChildren()
{
AddBaseTypes(this.Children, type);
AddBaseTypes(this.Children, module, type);
}
internal static void AddBaseTypes(SharpTreeNodeCollection children, TypeDefinition type)
internal static void AddBaseTypes(SharpTreeNodeCollection children, PEFile module, ITypeDefinition typeDefinition)
{
var metadata = type.Module.Metadata;
var def = metadata.GetTypeDefinition(type.Handle);
var context = new GenericContext(type);
if (!def.BaseType.IsNil)
children.Add(new BaseTypesEntryNode(context, new Entity(type.Module, def.BaseType), false));
foreach (var i in def.GetInterfaceImplementations()) {
var interfaceImpl = metadata.GetInterfaceImplementation(i);
children.Add(new BaseTypesEntryNode(context, new Entity(type.Module, interfaceImpl.Interface), true));
var typeDef = module.Metadata.GetTypeDefinition((TypeDefinitionHandle)typeDefinition.MetadataToken);
var baseTypes = typeDefinition.DirectBaseTypes.ToArray();
int i = 0;
if (typeDefinition.Kind == TypeKind.Interface) {
i++;
} else if (!typeDef.BaseType.IsNil) {
children.Add(new BaseTypesEntryNode(module, typeDef.BaseType, baseTypes[i], false));
i++;
}
foreach (var h in typeDef.GetInterfaceImplementations()) {
var impl = module.Metadata.GetInterfaceImplementation(h);
children.Add(new BaseTypesEntryNode(module, impl.Interface, baseTypes[i], true));
i++;
}
}

52
ILSpy/TreeNodes/CopyFullyQualifiedNameContextMenuEntry.cs

@ -2,6 +2,7 @@ @@ -2,6 +2,7 @@
using System.Windows;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.ILSpy.TreeNodes
{
@ -18,60 +19,13 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -18,60 +19,13 @@ namespace ICSharpCode.ILSpy.TreeNodes
public void Execute(TextViewContext context)
{
var member = GetMemberNodeFromContext(context)?.Member;
if (member == null || member.IsNil) return;
Clipboard.SetText(GetFullyQualifiedName(member));
if (member == null) return;
Clipboard.SetText(member.ReflectionName);
}
private IMemberTreeNode GetMemberNodeFromContext(TextViewContext context)
{
return context.SelectedTreeNodes?.Length == 1 ? context.SelectedTreeNodes[0] as IMemberTreeNode : null;
}
/// <summary>
/// Resolve full type name using .NET type representation for nested types.
/// </summary>
private string GetFullyQualifiedName(IMetadataEntity member)
{
string name;
System.Reflection.Metadata.TypeDefinitionHandle declaringType;
switch (member.Handle.Kind) {
case System.Reflection.Metadata.HandleKind.TypeDefinition:
return ((System.Reflection.Metadata.TypeDefinitionHandle)member.Handle).GetFullTypeName(member.Module.Metadata).ToString();
case System.Reflection.Metadata.HandleKind.FieldDefinition:
name = "";
declaringType = member.Handle.GetDeclaringType(member.Module.Metadata);
var fd = member.Module.Metadata.GetFieldDefinition((System.Reflection.Metadata.FieldDefinitionHandle)member.Handle);
if (!declaringType.IsNil) {
name = declaringType.GetFullTypeName(member.Module.Metadata) + ".";
}
return name + member.Module.Metadata.GetString(fd.Name);
case System.Reflection.Metadata.HandleKind.MethodDefinition:
name = "";
declaringType = member.Handle.GetDeclaringType(member.Module.Metadata);
var md = member.Module.Metadata.GetMethodDefinition((System.Reflection.Metadata.MethodDefinitionHandle)member.Handle);
if (!declaringType.IsNil) {
name = declaringType.GetFullTypeName(member.Module.Metadata) + ".";
}
return name + member.Module.Metadata.GetString(md.Name);
case System.Reflection.Metadata.HandleKind.EventDefinition:
name = "";
declaringType = member.Handle.GetDeclaringType(member.Module.Metadata);
var ed = member.Module.Metadata.GetEventDefinition((System.Reflection.Metadata.EventDefinitionHandle)member.Handle);
if (!declaringType.IsNil) {
name = declaringType.GetFullTypeName(member.Module.Metadata) + ".";
}
return name + member.Module.Metadata.GetString(ed.Name);
case System.Reflection.Metadata.HandleKind.PropertyDefinition:
name = "";
declaringType = member.Handle.GetDeclaringType(member.Module.Metadata);
var pd = member.Module.Metadata.GetPropertyDefinition((System.Reflection.Metadata.PropertyDefinitionHandle)member.Handle);
if (!declaringType.IsNil) {
name = declaringType.GetFullTypeName(member.Module.Metadata) + ".";
}
return name + member.Module.Metadata.GetString(pd.Name);
default:
throw new ArgumentOutOfRangeException();
}
}
}
}

50
ILSpy/TreeNodes/DerivedTypesEntryNode.cs

@ -17,54 +17,42 @@ @@ -17,54 +17,42 @@
// DEALINGS IN THE SOFTWARE.
using System.Collections.Generic;
using System.Reflection;
using System.Reflection.PortableExecutable;
using System.Linq;
using System.Threading;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
using SRM = System.Reflection.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.ILSpy.TreeNodes
{
class DerivedTypesEntryNode : ILSpyTreeNode, IMemberTreeNode
{
private readonly TypeDefinition type;
private readonly PEFile[] assemblies;
private readonly ThreadingSupport threading;
private readonly SRM.TypeDefinition td;
readonly AssemblyList list;
readonly ITypeDefinition type;
readonly ThreadingSupport threading;
public DerivedTypesEntryNode(TypeDefinition type, PEFile[] assemblies)
public DerivedTypesEntryNode(AssemblyList list, ITypeDefinition type)
{
this.list = list;
this.type = type;
this.td = type.Module.Metadata.GetTypeDefinition(type.Handle);
this.assemblies = assemblies;
this.LazyLoading = true;
threading = new ThreadingSupport();
}
public override bool ShowExpander
{
get { return !type.Module.Metadata.GetTypeDefinition(type.Handle).HasFlag(TypeAttributes.Sealed) && base.ShowExpander; }
}
public override bool ShowExpander => !type.IsSealed && base.ShowExpander;
public override object Text
{
get { return type.Handle.GetFullTypeName(type.Module.Metadata) + type.Handle.ToSuffixString(); }
get { return type.FullName + type.MetadataToken.ToSuffixString(); }
}
public override object Icon
{
get { return TypeTreeNode.GetIcon(type); }
}
public override object Icon => TypeTreeNode.GetIcon(type);
public override FilterResult Filter(FilterSettings settings)
{
if (!settings.ShowInternalApi && !IsPublicAPI)
return FilterResult.Hidden;
var metadata = type.Module.Metadata;
var typeDefinition = metadata.GetTypeDefinition(type.Handle);
if (settings.SearchTermMatches(metadata.GetString(typeDefinition.Name))) {
if (!typeDefinition.GetDeclaringType().IsNil && !settings.Language.ShowMember(type))
if (settings.SearchTermMatches(type.Name)) {
if (type.DeclaringType != null && !settings.Language.ShowMember(type))
return FilterResult.Hidden;
else
return FilterResult.Match;
@ -74,11 +62,10 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -74,11 +62,10 @@ namespace ICSharpCode.ILSpy.TreeNodes
public override bool IsPublicAPI {
get {
switch (td.Attributes & TypeAttributes.VisibilityMask) {
case TypeAttributes.Public:
case TypeAttributes.NestedPublic:
case TypeAttributes.NestedFamily:
case TypeAttributes.NestedFamORAssem:
switch (type.Accessibility) {
case Accessibility.Public:
case Accessibility.Internal:
case Accessibility.ProtectedOrInternal:
return true;
default:
return false;
@ -94,7 +81,8 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -94,7 +81,8 @@ namespace ICSharpCode.ILSpy.TreeNodes
IEnumerable<ILSpyTreeNode> FetchChildren(CancellationToken ct)
{
// FetchChildren() runs on the main thread; but the enumerator will be consumed on a background thread
return DerivedTypesTreeNode.FindDerivedTypes(type, assemblies, ct);
var assemblies = list.GetAssemblies().Select(node => node.GetPEFileOrNull()).Where(asm => asm != null).ToArray();
return DerivedTypesTreeNode.FindDerivedTypes(list, type, assemblies, ct);
}
public override void ActivateItem(System.Windows.RoutedEventArgs e)
@ -107,6 +95,6 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -107,6 +95,6 @@ namespace ICSharpCode.ILSpy.TreeNodes
language.WriteCommentLine(output, language.TypeToString(type, includeNamespace: true));
}
IMetadataEntity IMemberTreeNode.Member => type;
IEntity IMemberTreeNode.Member => type;
}
}

48
ILSpy/TreeNodes/DerivedTypesTreeNode.cs

@ -21,22 +21,22 @@ using System.Linq; @@ -21,22 +21,22 @@ using System.Linq;
using System.Threading;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.Util;
using ICSharpCode.Decompiler.TypeSystem;
using SRM = System.Reflection.Metadata;
namespace ICSharpCode.ILSpy.TreeNodes
{
/// <summary>
/// Lists the super types of a class.
/// Lists the sub types of a class.
/// </summary>
sealed class DerivedTypesTreeNode : ILSpyTreeNode
{
readonly AssemblyList list;
readonly TypeDefinition type;
readonly ITypeDefinition type;
readonly ThreadingSupport threading;
public DerivedTypesTreeNode(AssemblyList list, TypeDefinition type)
public DerivedTypesTreeNode(AssemblyList list, ITypeDefinition type)
{
this.list = list;
this.type = type;
@ -44,15 +44,9 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -44,15 +44,9 @@ namespace ICSharpCode.ILSpy.TreeNodes
this.threading = new ThreadingSupport();
}
public override object Text
{
get { return "Derived Types"; }
}
public override object Text => "Derived Types";
public override object Icon
{
get { return Images.SubTypes; }
}
public override object Icon => Images.SubTypes;
protected override void LoadChildren()
{
@ -63,34 +57,38 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -63,34 +57,38 @@ namespace ICSharpCode.ILSpy.TreeNodes
{
// FetchChildren() runs on the main thread; but the enumerator will be consumed on a background thread
var assemblies = list.GetAssemblies().Select(node => node.GetPEFileOrNull()).Where(asm => asm != null).ToArray();
return FindDerivedTypes(type, assemblies, cancellationToken);
return FindDerivedTypes(list, type, assemblies, cancellationToken);
}
internal static IEnumerable<DerivedTypesEntryNode> FindDerivedTypes(TypeDefinition type, PEFile[] assemblies, CancellationToken cancellationToken)
internal static IEnumerable<DerivedTypesEntryNode> FindDerivedTypes(AssemblyList list, ITypeDefinition type,
PEFile[] assemblies, CancellationToken cancellationToken)
{
var definitionMetadata = type.ParentAssembly.PEFile.Metadata;
var metadataToken = (SRM.TypeDefinitionHandle)type.MetadataToken;
foreach (var module in assemblies) {
var metadata = module.Metadata;
foreach (var h in TreeTraversal.PreOrder(metadata.GetTopLevelTypeDefinitions(), t => metadata.GetTypeDefinition(t).GetNestedTypes())) {
var assembly = (MetadataAssembly)module.GetTypeSystemOrNull().MainAssembly;
foreach (var h in metadata.TypeDefinitions) {
cancellationToken.ThrowIfCancellationRequested();
var td = new TypeDefinition(module, h);
var typeDefinition = metadata.GetTypeDefinition(h);
foreach (var iface in typeDefinition.GetInterfaceImplementations()) {
var td = metadata.GetTypeDefinition(h);
foreach (var iface in td.GetInterfaceImplementations()) {
var ifaceImpl = metadata.GetInterfaceImplementation(iface);
if (IsSameType(metadata, ifaceImpl.Interface, type))
yield return new DerivedTypesEntryNode(td, assemblies);
if (IsSameType(metadata, ifaceImpl.Interface, definitionMetadata, metadataToken))
yield return new DerivedTypesEntryNode(list, assembly.GetDefinition(h));
}
if (!typeDefinition.BaseType.IsNil && IsSameType(metadata, typeDefinition.BaseType, type)) {
yield return new DerivedTypesEntryNode(td, assemblies);
if (!td.BaseType.IsNil && IsSameType(metadata, td.BaseType, definitionMetadata, metadataToken)) {
yield return new DerivedTypesEntryNode(list, assembly.GetDefinition(h));
}
}
}
yield break;
}
static bool IsSameType(SRM.MetadataReader referenceMetadata, SRM.EntityHandle typeRef, TypeDefinition type)
static bool IsSameType(SRM.MetadataReader referenceMetadata, SRM.EntityHandle typeRef,
SRM.MetadataReader definitionMetadata, SRM.TypeDefinitionHandle typeDef)
{
// FullName contains only namespace, name and type parameter count, therefore this should suffice.
return typeRef.GetFullTypeName(referenceMetadata) == type.Handle.GetFullTypeName(type.Module.Metadata);
return typeRef.GetFullTypeName(referenceMetadata) == typeDef.GetFullTypeName(definitionMetadata);
}
public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)

52
ILSpy/TreeNodes/EventTreeNode.cs

@ -23,6 +23,8 @@ using SRM = System.Reflection.Metadata; @@ -23,6 +23,8 @@ using SRM = System.Reflection.Metadata;
using System.Windows.Media;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
using System.Reflection.Metadata;
namespace ICSharpCode.ILSpy.TreeNodes
{
@ -31,39 +33,34 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -31,39 +33,34 @@ namespace ICSharpCode.ILSpy.TreeNodes
/// </summary>
public sealed class EventTreeNode : ILSpyTreeNode, IMemberTreeNode
{
public EventTreeNode(EventDefinition ev)
public EventTreeNode(IEvent @event)
{
if (ev.IsNil)
throw new ArgumentNullException(nameof(ev));
this.EventDefinition = ev;
var metadata = ev.Module.Metadata;
var eventDefinition = metadata.GetEventDefinition(ev.Handle);
var accessors = eventDefinition.GetAccessors();
if (!accessors.Adder.IsNil)
this.Children.Add(new MethodTreeNode(new MethodDefinition(ev.Module, accessors.Adder)));
if (!accessors.Remover.IsNil)
this.Children.Add(new MethodTreeNode(new MethodDefinition(ev.Module, accessors.Remover)));
if (!accessors.Raiser.IsNil)
this.Children.Add(new MethodTreeNode(new MethodDefinition(ev.Module, accessors.Raiser)));
this.EventDefinition = @event ?? throw new ArgumentNullException(nameof(@event));
if (@event.CanAdd)
this.Children.Add(new MethodTreeNode(@event.AddAccessor));
if (@event.CanRemove)
this.Children.Add(new MethodTreeNode(@event.RemoveAccessor));
if (@event.CanInvoke)
this.Children.Add(new MethodTreeNode(@event.InvokeAccessor));
//foreach (var m in ev.OtherMethods)
// this.Children.Add(new MethodTreeNode(m));
}
public EventDefinition EventDefinition { get; }
public IEvent EventDefinition { get; }
public override object Text => GetText(EventDefinition, this.Language) + EventDefinition.Handle.ToSuffixString();
public override object Text => GetText(EventDefinition, this.Language) + EventDefinition.MetadataToken.ToSuffixString();
public static object GetText(EventDefinition ev, Language language)
public static object GetText(IEvent ev, Language language)
{
return language.EventToString(ev, false, false);
}
public override object Icon => GetIcon(EventDefinition);
public static ImageSource GetIcon(EventDefinition @event)
public static ImageSource GetIcon(IEvent @event)
{
var metadata = @event.Module.Metadata;
var accessor = metadata.GetEventDefinition(@event.Handle).GetAccessors().GetAny();
var metadata = ((MetadataAssembly)@event.ParentAssembly).PEFile.Metadata;
var accessor = metadata.GetEventDefinition((EventDefinitionHandle)@event.MetadataToken).GetAccessors().GetAny();
if (!accessor.IsNil) {
var accessorMethod = metadata.GetMethodDefinition(accessor);
return Images.GetIcon(MemberIcon.Event, GetOverlayIcon(accessorMethod.Attributes), accessorMethod.HasFlag(MethodAttributes.Static));
@ -97,8 +94,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -97,8 +94,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
{
if (!settings.ShowInternalApi && !IsPublicAPI)
return FilterResult.Hidden;
var metadata = EventDefinition.Module.Metadata;
if (settings.SearchTermMatches(metadata.GetString(metadata.GetEventDefinition(EventDefinition.Handle).Name)) && settings.Language.ShowMember(EventDefinition))
if (settings.SearchTermMatches(EventDefinition.Name) && settings.Language.ShowMember(EventDefinition))
return FilterResult.Match;
else
return FilterResult.Hidden;
@ -111,14 +107,10 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -111,14 +107,10 @@ namespace ICSharpCode.ILSpy.TreeNodes
public override bool IsPublicAPI {
get {
var metadata = EventDefinition.Module.Metadata;
var accessor = metadata.GetEventDefinition(EventDefinition.Handle).GetAccessors().GetAny();
if (accessor.IsNil) return false;
var accessorMethod = metadata.GetMethodDefinition(accessor);
switch (accessorMethod.Attributes & MethodAttributes.MemberAccessMask) {
case MethodAttributes.Public:
case MethodAttributes.FamORAssem:
case MethodAttributes.Family:
switch (EventDefinition.Accessibility) {
case Accessibility.Public:
case Accessibility.ProtectedOrInternal:
case Accessibility.Protected:
return true;
default:
return false;
@ -126,6 +118,6 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -126,6 +118,6 @@ namespace ICSharpCode.ILSpy.TreeNodes
}
}
IMetadataEntity IMemberTreeNode.Member => EventDefinition;
IEntity IMemberTreeNode.Member => EventDefinition;
}
}

54
ILSpy/TreeNodes/FieldTreeNode.cs

@ -18,9 +18,11 @@ @@ -18,9 +18,11 @@
using System;
using System.Reflection;
using System.Reflection.Metadata;
using System.Windows.Media;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.Util;
namespace ICSharpCode.ILSpy.TreeNodes
@ -30,28 +32,26 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -30,28 +32,26 @@ namespace ICSharpCode.ILSpy.TreeNodes
/// </summary>
public sealed class FieldTreeNode : ILSpyTreeNode, IMemberTreeNode
{
public FieldDefinition FieldDefinition { get; }
public IField FieldDefinition { get; }
public FieldTreeNode(FieldDefinition field)
public FieldTreeNode(IField field)
{
if (field.IsNil)
throw new ArgumentNullException(nameof(field));
this.FieldDefinition = field;
this.FieldDefinition = field ?? throw new ArgumentNullException(nameof(field));
}
public override object Text => GetText(FieldDefinition, Language) + FieldDefinition.Handle.ToSuffixString();
public override object Text => GetText(FieldDefinition, Language) + FieldDefinition.MetadataToken.ToSuffixString();
public static object GetText(FieldDefinition field, Language language)
public static object GetText(IField field, Language language)
{
return language.FieldToString(field, includeTypeName: false, includeNamespace: false);
}
public override object Icon => GetIcon(FieldDefinition);
public static ImageSource GetIcon(FieldDefinition field)
public static ImageSource GetIcon(IField field)
{
var metadata = field.Module.Metadata;
var fieldDefinition = metadata.GetFieldDefinition(field.Handle);
var metadata = ((MetadataAssembly)field.ParentAssembly).PEFile.Metadata;
var fieldDefinition = metadata.GetFieldDefinition((FieldDefinitionHandle)field.MetadataToken);
if (fieldDefinition.GetDeclaringType().IsEnum(metadata) && !fieldDefinition.HasFlag(FieldAttributes.SpecialName))
return Images.GetIcon(MemberIcon.EnumValue, GetOverlayIcon(fieldDefinition.Attributes), false);
@ -66,22 +66,9 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -66,22 +66,9 @@ namespace ICSharpCode.ILSpy.TreeNodes
return Images.GetIcon(MemberIcon.Field, GetOverlayIcon(fieldDefinition.Attributes), fieldDefinition.HasFlag(FieldAttributes.Static));
}
private static bool IsDecimalConstant(FieldDefinition field)
private static bool IsDecimalConstant(IField field)
{
var metadata = field.Module.Metadata;
var fieldDefinition = metadata.GetFieldDefinition(field.Handle);
var fieldType = fieldDefinition.DecodeSignature(new FullTypeNameSignatureDecoder(metadata), default(Unit));
if (fieldType.ToString() == "System.Decimal") {
var attrs = fieldDefinition.GetCustomAttributes();
foreach (var h in attrs) {
var attr = metadata.GetCustomAttribute(h);
var attrType = attr.GetAttributeType(metadata).GetFullTypeName(metadata);
if (attrType.ToString() == "System.Runtime.CompilerServices.DecimalConstantAttribute")
return true;
}
}
return false;
return field.IsConst && field.Type.IsKnownType(KnownTypeCode.Decimal) && field.ConstantValue != null;
}
private static AccessOverlayIcon GetOverlayIcon(FieldAttributes fieldAttributes)
@ -110,9 +97,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -110,9 +97,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
{
if (!settings.ShowInternalApi && !IsPublicAPI)
return FilterResult.Hidden;
var metadata = FieldDefinition.Module.Metadata;
var fieldDefinition = metadata.GetFieldDefinition(FieldDefinition.Handle);
if (settings.SearchTermMatches(metadata.GetString(fieldDefinition.Name)) && settings.Language.ShowMember(FieldDefinition))
if (settings.SearchTermMatches(FieldDefinition.Name) && settings.Language.ShowMember(FieldDefinition))
return FilterResult.Match;
else
return FilterResult.Hidden;
@ -125,13 +110,10 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -125,13 +110,10 @@ namespace ICSharpCode.ILSpy.TreeNodes
public override bool IsPublicAPI {
get {
var metadata = FieldDefinition.Module.Metadata;
var fieldDefinition = metadata.GetFieldDefinition(FieldDefinition.Handle);
switch (fieldDefinition.Attributes & FieldAttributes.FieldAccessMask) {
case FieldAttributes.Public:
case FieldAttributes.FamORAssem:
case FieldAttributes.Family:
switch (FieldDefinition.Accessibility) {
case Accessibility.Public:
case Accessibility.Protected:
case Accessibility.ProtectedOrInternal:
return true;
default:
return false;
@ -139,6 +121,6 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -139,6 +121,6 @@ namespace ICSharpCode.ILSpy.TreeNodes
}
}
IMetadataEntity IMemberTreeNode.Member => FieldDefinition;
IEntity IMemberTreeNode.Member => FieldDefinition;
}
}

4
ILSpy/TreeNodes/GeneratePdbContextMenuEntry.cs

@ -7,7 +7,7 @@ using System.Text; @@ -7,7 +7,7 @@ using System.Text;
using System.Threading.Tasks;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.CSharp;
using ICSharpCode.Decompiler.Pdb;
using ICSharpCode.Decompiler.DebugInfo;
using ICSharpCode.ILSpy.TextView;
using Microsoft.Win32;
@ -33,7 +33,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -33,7 +33,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
using (FileStream stream = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.Write)) {
try {
var file = assembly.GetPEFileOrNull();
var decompiler = new CSharpDecompiler(file, options.DecompilerSettings);
var decompiler = new CSharpDecompiler(file, assembly.GetAssemblyResolver(), options.DecompilerSettings);
PortablePdbWriter.WritePdb(file, decompiler, options.DecompilerSettings, stream);
} catch (OperationCanceledException) {
output.WriteLine();

10
ILSpy/TreeNodes/IMemberTreeNode.cs

@ -16,17 +16,21 @@ @@ -16,17 +16,21 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.ILSpy.TreeNodes
{
/// <summary>
/// Interface implemented by all tree nodes
/// (both in main tree view and in analyzer)
/// that represent Cecil members.
/// that represent TypeSystem members.
/// </summary>
public interface IMemberTreeNode
{
IMetadataEntity Member { get; }
/// <summary>
/// Returns the entity that is represented by this tree node.
/// May return null, if the member cannot be resolved.
/// </summary>
IEntity Member { get; }
}
}

84
ILSpy/TreeNodes/MethodTreeNode.cs

@ -20,11 +20,13 @@ using System; @@ -20,11 +20,13 @@ using System;
using System.Collections.Immutable;
using System.Linq;
using System.Reflection;
using System.Reflection.Metadata;
using System.Text;
using System.Windows.Media;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
using SRM = System.Reflection.Metadata;
namespace ICSharpCode.ILSpy.TreeNodes
@ -34,76 +36,57 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -34,76 +36,57 @@ namespace ICSharpCode.ILSpy.TreeNodes
/// </summary>
public sealed class MethodTreeNode : ILSpyTreeNode, IMemberTreeNode
{
public MethodDefinition MethodDefinition { get; }
SRM.MethodDefinition md;
public IMethod MethodDefinition { get; }
public MethodTreeNode(MethodDefinition method)
public MethodTreeNode(IMethod method)
{
if (method.IsNil)
throw new ArgumentNullException(nameof(method));
this.MethodDefinition = method;
this.md = method.Module.Metadata.GetMethodDefinition(method.Handle);
this.MethodDefinition = method ?? throw new ArgumentNullException(nameof(method));
}
public override object Text => GetText(MethodDefinition, Language) + MethodDefinition.Handle.ToSuffixString();
public override object Text => GetText(MethodDefinition, Language) + MethodDefinition.MetadataToken.ToSuffixString();
public static object GetText(MethodDefinition method, Language language)
public static object GetText(IMethod method, Language language)
{
return language.MethodToString(method, false, false);
}
public override object Icon => GetIcon(MethodDefinition);
public static ImageSource GetIcon(MethodDefinition method)
public static ImageSource GetIcon(IMethod method)
{
var metadata = method.Module.Metadata;
var methodDefinition = metadata.GetMethodDefinition(method.Handle);
var methodName = metadata.GetString(methodDefinition.Name);
if (methodDefinition.HasFlag(MethodAttributes.SpecialName) && methodName.StartsWith("op_", StringComparison.Ordinal)) {
return Images.GetIcon(MemberIcon.Operator, GetOverlayIcon(methodDefinition.Attributes), false);
}
if (methodDefinition.IsExtensionMethod(metadata)) {
return Images.GetIcon(MemberIcon.ExtensionMethod, GetOverlayIcon(methodDefinition.Attributes), false);
}
if (method.IsOperator)
return Images.GetIcon(MemberIcon.Operator, GetOverlayIcon(method), false);
if (methodDefinition.HasFlag(MethodAttributes.SpecialName) &&
(methodName == ".ctor" || methodName == ".cctor")) {
return Images.GetIcon(MemberIcon.Constructor, GetOverlayIcon(methodDefinition.Attributes), methodDefinition.HasFlag(MethodAttributes.Static));
}
if (method.IsExtensionMethod)
return Images.GetIcon(MemberIcon.ExtensionMethod, GetOverlayIcon(method), false);
if (methodDefinition.HasFlag(MethodAttributes.PinvokeImpl) && !methodDefinition.GetImport().Module.IsNil)
return Images.GetIcon(MemberIcon.PInvokeMethod, GetOverlayIcon(methodDefinition.Attributes), true);
if (method.IsConstructor)
return Images.GetIcon(MemberIcon.Constructor, GetOverlayIcon(method), method.IsStatic);
bool showAsVirtual = methodDefinition.HasFlag(MethodAttributes.Virtual)
&& !(methodDefinition.HasFlag(MethodAttributes.NewSlot) && methodDefinition.HasFlag(MethodAttributes.Final))
&& (metadata.GetTypeDefinition(methodDefinition.GetDeclaringType()).Attributes & TypeAttributes.ClassSemanticsMask) != TypeAttributes.Interface;
if (!method.HasBody && method.HasAttribute(KnownAttribute.DllImport))
return Images.GetIcon(MemberIcon.PInvokeMethod, GetOverlayIcon(method), true);
return Images.GetIcon(
showAsVirtual ? MemberIcon.VirtualMethod : MemberIcon.Method,
GetOverlayIcon(methodDefinition.Attributes),
methodDefinition.HasFlag(MethodAttributes.Static));
return Images.GetIcon(method.IsVirtual ? MemberIcon.VirtualMethod : MemberIcon.Method,
GetOverlayIcon(method), method.IsStatic);
}
private static AccessOverlayIcon GetOverlayIcon(MethodAttributes methodAttributes)
static AccessOverlayIcon GetOverlayIcon(IMethod method)
{
switch (methodAttributes & MethodAttributes.MemberAccessMask) {
case MethodAttributes.Public:
switch (method.Accessibility) {
case Accessibility.Public:
return AccessOverlayIcon.Public;
case MethodAttributes.Assembly:
case Accessibility.Internal:
return AccessOverlayIcon.Internal;
case MethodAttributes.FamANDAssem:
case Accessibility.ProtectedAndInternal:
return AccessOverlayIcon.PrivateProtected;
case MethodAttributes.Family:
case Accessibility.Protected:
return AccessOverlayIcon.Protected;
case MethodAttributes.FamORAssem:
case Accessibility.ProtectedOrInternal:
return AccessOverlayIcon.ProtectedInternal;
case MethodAttributes.Private:
case Accessibility.Private:
return AccessOverlayIcon.Private;
case 0:
return AccessOverlayIcon.CompilerControlled;
default:
throw new NotSupportedException();
return AccessOverlayIcon.CompilerControlled;
}
}
@ -116,8 +99,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -116,8 +99,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
{
if (!settings.ShowInternalApi && !IsPublicAPI)
return FilterResult.Hidden;
var metadata = MethodDefinition.Module.Metadata;
if (settings.SearchTermMatches(metadata.GetString(md.Name)) && settings.Language.ShowMember(MethodDefinition))
if (settings.SearchTermMatches(MethodDefinition.Name) && settings.Language.ShowMember(MethodDefinition))
return FilterResult.Match;
else
return FilterResult.Hidden;
@ -125,10 +107,10 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -125,10 +107,10 @@ namespace ICSharpCode.ILSpy.TreeNodes
public override bool IsPublicAPI {
get {
switch (md.Attributes & MethodAttributes.MemberAccessMask) {
case MethodAttributes.Public:
case MethodAttributes.Family:
case MethodAttributes.FamORAssem:
switch (MethodDefinition.Accessibility) {
case Accessibility.Public:
case Accessibility.Protected:
case Accessibility.ProtectedOrInternal:
return true;
default:
return false;
@ -136,6 +118,6 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -136,6 +118,6 @@ namespace ICSharpCode.ILSpy.TreeNodes
}
}
IMetadataEntity IMemberTreeNode.Member => MethodDefinition;
IEntity IMemberTreeNode.Member => MethodDefinition;
}
}

44
ILSpy/TreeNodes/PropertyTreeNode.cs

@ -18,10 +18,11 @@ @@ -18,10 +18,11 @@
using System;
using System.Reflection;
using System.Reflection.Metadata;
using System.Windows.Media;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
using SRM = System.Reflection.Metadata;
namespace ICSharpCode.ILSpy.TreeNodes
@ -33,38 +34,31 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -33,38 +34,31 @@ namespace ICSharpCode.ILSpy.TreeNodes
{
readonly bool isIndexer;
public PropertyTreeNode(PropertyDefinition property)
public PropertyTreeNode(IProperty property)
{
if (property == null)
throw new ArgumentNullException(nameof(property));
this.PropertyDefinition = property;
var metadata = property.Module.Metadata;
var propertyDefinition = metadata.GetPropertyDefinition(property.Handle);
var accessors = propertyDefinition.GetAccessors();
using (LoadedAssembly.DisableAssemblyLoad()) {
this.isIndexer = property.Handle.HasMatchingDefaultMemberAttribute(property.Module, out _);
}
this.PropertyDefinition = property ?? throw new ArgumentNullException(nameof(property));
this.isIndexer = property.IsIndexer;
if (!accessors.Getter.IsNil)
this.Children.Add(new MethodTreeNode(new MethodDefinition(property.Module, accessors.Getter)));
if (!accessors.Setter.IsNil)
this.Children.Add(new MethodTreeNode(new MethodDefinition(property.Module, accessors.Setter)));
if (property.CanGet)
this.Children.Add(new MethodTreeNode(property.Getter));
if (property.CanSet)
this.Children.Add(new MethodTreeNode(property.Setter));
/*foreach (var m in property.OtherMethods)
this.Children.Add(new MethodTreeNode(m));*/
}
public PropertyDefinition PropertyDefinition { get; }
public IProperty PropertyDefinition { get; }
public override object Text => GetText(PropertyDefinition, Language, isIndexer) + PropertyDefinition.Handle.ToSuffixString();
public override object Text => GetText(PropertyDefinition, Language, isIndexer) + PropertyDefinition.MetadataToken.ToSuffixString();
public static object GetText(PropertyDefinition property, Language language, bool? isIndexer = null)
public static object GetText(IProperty property, Language language, bool? isIndexer = null)
{
return language.PropertyToString(property, false, false, isIndexer);
}
public override object Icon => GetIcon(PropertyDefinition);
public static ImageSource GetIcon(PropertyDefinition property, bool isIndexer = false)
public static ImageSource GetIcon(IProperty property, bool isIndexer = false)
{
MemberIcon icon = isIndexer ? MemberIcon.Indexer : MemberIcon.Property;
MethodAttributes attributesOfMostAccessibleMethod = GetAttributesOfMostAccessibleMethod(property);
@ -94,7 +88,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -94,7 +88,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
}
}
private static MethodAttributes GetAttributesOfMostAccessibleMethod(PropertyDefinition property)
private static MethodAttributes GetAttributesOfMostAccessibleMethod(IProperty property)
{
// There should always be at least one method from which to
// obtain the result, but the compiler doesn't know this so
@ -105,8 +99,8 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -105,8 +99,8 @@ namespace ICSharpCode.ILSpy.TreeNodes
// in numeric order, so we can do an integer comparison of the masked attribute
int accessLevel = 0;
var metadata = property.Module.Metadata;
var propertyDefinition = metadata.GetPropertyDefinition(property.Handle);
var metadata = ((MetadataAssembly)property.ParentAssembly).PEFile.Metadata;
var propertyDefinition = metadata.GetPropertyDefinition((PropertyDefinitionHandle)property.MetadataToken);
var accessors = propertyDefinition.GetAccessors();
if (!accessors.Getter.IsNil) {
@ -142,9 +136,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -142,9 +136,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
{
if (!settings.ShowInternalApi && !IsPublicAPI)
return FilterResult.Hidden;
var metadata = PropertyDefinition.Module.Metadata;
var propertyDefinition = metadata.GetPropertyDefinition(PropertyDefinition.Handle);
if (settings.SearchTermMatches(metadata.GetString(propertyDefinition.Name)) && settings.Language.ShowMember(PropertyDefinition))
if (settings.SearchTermMatches(PropertyDefinition.Name) && settings.Language.ShowMember(PropertyDefinition))
return FilterResult.Match;
else
return FilterResult.Hidden;
@ -168,6 +160,6 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -168,6 +160,6 @@ namespace ICSharpCode.ILSpy.TreeNodes
}
}
IMetadataEntity IMemberTreeNode.Member => PropertyDefinition;
IEntity IMemberTreeNode.Member => PropertyDefinition;
}
}

134
ILSpy/TreeNodes/TypeTreeNode.cs

@ -22,39 +22,33 @@ using System.Reflection; @@ -22,39 +22,33 @@ using System.Reflection;
using System.Windows.Media;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
using SRM = System.Reflection.Metadata;
namespace ICSharpCode.ILSpy.TreeNodes
{
public sealed class TypeTreeNode : ILSpyTreeNode, IMemberTreeNode
{
readonly SRM.TypeDefinition td;
public TypeTreeNode(TypeDefinition typeDefinition, AssemblyTreeNode parentAssemblyNode)
public TypeTreeNode(ITypeDefinition typeDefinition, AssemblyTreeNode parentAssemblyNode)
{
if (typeDefinition.IsNil)
throw new ArgumentNullException(nameof(typeDefinition));
this.ParentAssemblyNode = parentAssemblyNode ?? throw new ArgumentNullException(nameof(parentAssemblyNode));
this.TypeDefinition = typeDefinition;
this.td = typeDefinition.Module.Metadata.GetTypeDefinition(typeDefinition.Handle);
this.TypeDefinition = typeDefinition ?? throw new ArgumentNullException(nameof(typeDefinition));
this.LazyLoading = true;
}
public TypeDefinition TypeDefinition { get; }
public ITypeDefinition TypeDefinition { get; }
public AssemblyTreeNode ParentAssemblyNode { get; }
public override object Text => this.Language.TypeToString(TypeDefinition, includeNamespace: false) + TypeDefinition.Handle.ToSuffixString();
public override object Text => this.Language.TypeToString(TypeDefinition, includeNamespace: false)
+ TypeDefinition.MetadataToken.ToSuffixString();
public override bool IsPublicAPI {
get {
switch (td.Attributes & TypeAttributes.VisibilityMask) {
case TypeAttributes.Public:
case TypeAttributes.NestedPublic:
case TypeAttributes.NestedFamily:
case TypeAttributes.NestedFamORAssem:
switch (TypeDefinition.Accessibility) {
case Accessibility.Public:
case Accessibility.Protected:
case Accessibility.ProtectedOrInternal:
return true;
default:
return false;
@ -66,7 +60,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -66,7 +60,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
{
if (!settings.ShowInternalApi && !IsPublicAPI)
return FilterResult.Hidden;
if (settings.SearchTermMatches(TypeDefinition.Module.Metadata.GetString(td.Name))) {
if (settings.SearchTermMatches(TypeDefinition.Name)) {
if (settings.Language.ShowMember(TypeDefinition))
return FilterResult.Match;
else
@ -78,28 +72,25 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -78,28 +72,25 @@ namespace ICSharpCode.ILSpy.TreeNodes
protected override void LoadChildren()
{
var metadata = TypeDefinition.Module.Metadata;
if (!td.BaseType.IsNil || td.GetInterfaceImplementations().Any())
this.Children.Add(new BaseTypesTreeNode(TypeDefinition));
if (!td.HasFlag(TypeAttributes.Sealed))
if (TypeDefinition.DirectBaseTypes.Any())
this.Children.Add(new BaseTypesTreeNode(ParentAssemblyNode.LoadedAssembly.GetPEFileOrNull(), TypeDefinition));
if (!TypeDefinition.IsSealed)
this.Children.Add(new DerivedTypesTreeNode(ParentAssemblyNode.AssemblyList, TypeDefinition));
foreach (var nestedType in td.GetNestedTypes().OrderBy(m => metadata.GetString(metadata.GetTypeDefinition(m).Name), NaturalStringComparer.Instance)) {
this.Children.Add(new TypeTreeNode(new TypeDefinition(TypeDefinition.Module, nestedType), ParentAssemblyNode));
foreach (var nestedType in TypeDefinition.NestedTypes.OrderBy(t => t.Name, NaturalStringComparer.Instance)) {
this.Children.Add(new TypeTreeNode(nestedType, ParentAssemblyNode));
}
foreach (var field in td.GetFields().OrderBy(m => metadata.GetString(metadata.GetFieldDefinition(m).Name), NaturalStringComparer.Instance)) {
this.Children.Add(new FieldTreeNode(new FieldDefinition(TypeDefinition.Module, field)));
foreach (var field in TypeDefinition.Fields.OrderBy(f => f.Name, NaturalStringComparer.Instance)) {
this.Children.Add(new FieldTreeNode(field));
}
foreach (var property in td.GetProperties().OrderBy(m => metadata.GetString(metadata.GetPropertyDefinition(m).Name), NaturalStringComparer.Instance)) {
this.Children.Add(new PropertyTreeNode(new PropertyDefinition(TypeDefinition.Module, property)));
foreach (var property in TypeDefinition.Properties.OrderBy(p => p.Name, NaturalStringComparer.Instance)) {
this.Children.Add(new PropertyTreeNode(property));
}
foreach (var ev in td.GetEvents().OrderBy(m => metadata.GetString(metadata.GetEventDefinition(m).Name), NaturalStringComparer.Instance)) {
this.Children.Add(new EventTreeNode(new EventDefinition(TypeDefinition.Module, ev)));
foreach (var ev in TypeDefinition.Events.OrderBy(e => e.Name, NaturalStringComparer.Instance)) {
this.Children.Add(new EventTreeNode(ev));
}
foreach (var method in td.GetMethods().OrderBy(m => metadata.GetString(metadata.GetMethodDefinition(m).Name), NaturalStringComparer.Instance)) {
if (method.GetMethodSemanticsAttributes(metadata) == 0) {
this.Children.Add(new MethodTreeNode(new MethodDefinition(TypeDefinition.Module, method)));
}
foreach (var method in TypeDefinition.Methods.OrderBy(m => m.Name, NaturalStringComparer.Instance)) {
this.Children.Add(new MethodTreeNode(method));
}
}
@ -112,69 +103,48 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -112,69 +103,48 @@ namespace ICSharpCode.ILSpy.TreeNodes
public override object Icon => GetIcon(TypeDefinition);
public static ImageSource GetIcon(TypeDefinition type)
public static ImageSource GetIcon(ITypeDefinition type)
{
TypeIcon typeIcon = GetTypeIcon(type);
AccessOverlayIcon overlayIcon = GetOverlayIcon(type);
return Images.GetIcon(typeIcon, overlayIcon);
return Images.GetIcon(GetTypeIcon(type), GetOverlayIcon(type));
}
static TypeIcon GetTypeIcon(TypeDefinition type)
internal static TypeIcon GetTypeIcon(IType type)
{
var metadata = type.Module.Metadata;
var typeDefinition = metadata.GetTypeDefinition(type.Handle);
if (typeDefinition.IsValueType(metadata)) {
if (typeDefinition.IsEnum(metadata))
return TypeIcon.Enum;
else
return TypeIcon.Struct;
} else {
if ((typeDefinition.Attributes & TypeAttributes.ClassSemanticsMask) == TypeAttributes.Interface)
switch (type.Kind) {
case TypeKind.Interface:
return TypeIcon.Interface;
else if (typeDefinition.IsDelegate(metadata))
case TypeKind.Struct:
return TypeIcon.Struct;
case TypeKind.Delegate:
return TypeIcon.Delegate;
else if (IsStaticClass(typeDefinition))
return TypeIcon.StaticClass;
else
case TypeKind.Enum:
return TypeIcon.Enum;
default:
if (type.GetDefinition()?.IsStatic == true)
return TypeIcon.StaticClass;
return TypeIcon.Class;
}
}
private static AccessOverlayIcon GetOverlayIcon(TypeDefinition type)
static AccessOverlayIcon GetOverlayIcon(ITypeDefinition type)
{
var def = type.Module.Metadata.GetTypeDefinition(type.Handle);
AccessOverlayIcon overlay;
switch (def.Attributes & TypeAttributes.VisibilityMask) {
case TypeAttributes.Public:
case TypeAttributes.NestedPublic:
overlay = AccessOverlayIcon.Public;
break;
case TypeAttributes.NotPublic:
case TypeAttributes.NestedAssembly:
overlay = AccessOverlayIcon.Internal;
break;
case TypeAttributes.NestedFamANDAssem:
overlay = AccessOverlayIcon.PrivateProtected;
break;
case TypeAttributes.NestedFamily:
case TypeAttributes.NestedFamORAssem:
overlay = AccessOverlayIcon.Protected;
break;
case TypeAttributes.NestedPrivate:
overlay = AccessOverlayIcon.Private;
break;
switch (type.Accessibility) {
case Accessibility.Public:
return AccessOverlayIcon.Public;
case Accessibility.Internal:
return AccessOverlayIcon.Internal;
case Accessibility.ProtectedAndInternal:
return AccessOverlayIcon.PrivateProtected;
case Accessibility.Protected:
case Accessibility.ProtectedOrInternal:
return AccessOverlayIcon.Protected;
case Accessibility.Private:
return AccessOverlayIcon.Private;
default:
throw new NotSupportedException();
return AccessOverlayIcon.CompilerControlled;
}
return overlay;
}
static bool IsStaticClass(SRM.TypeDefinition type)
{
return type.HasFlag(TypeAttributes.Sealed) && type.HasFlag(TypeAttributes.Abstract);
}
IMetadataEntity IMemberTreeNode.Member => TypeDefinition;
IEntity IMemberTreeNode.Member => TypeDefinition;
}
}

9
TestPlugin/CustomLanguage.cs

@ -6,6 +6,7 @@ using System.Reflection.Metadata; @@ -6,6 +6,7 @@ using System.Reflection.Metadata;
using System.Windows.Controls;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.ILSpy;
namespace TestPlugin
@ -30,12 +31,12 @@ namespace TestPlugin @@ -30,12 +31,12 @@ namespace TestPlugin
}
// There are several methods available to override; in this sample, we deal with methods only
public override void DecompileMethod(ICSharpCode.Decompiler.Metadata.MethodDefinition method, ITextOutput output, DecompilationOptions options)
public override void DecompileMethod(IMethod method, ITextOutput output, DecompilationOptions options)
{
var metadata = method.Module.Metadata;
var methodDef = metadata.GetMethodDefinition(method.Handle);
var module = ((MetadataAssembly)method.ParentAssembly).PEFile;
var methodDef = module.Metadata.GetMethodDefinition((MethodDefinitionHandle)method.MetadataToken);
if (methodDef.HasBody()) {
var methodBody = method.Module.Reader.GetMethodBody(methodDef.RelativeVirtualAddress);
var methodBody = module.Reader.GetMethodBody(methodDef.RelativeVirtualAddress);
output.WriteLine("Size of method: {0} bytes", methodBody.GetCodeSize());
ISmartTextOutput smartOutput = output as ISmartTextOutput;

Loading…
Cancel
Save