Browse Source

Finished port of UI (Analyzers still excluded) and Disassembler

pull/1198/head
Siegfried Pammer 7 years ago
parent
commit
cb9787098f
  1. 3
      ICSharpCode.Decompiler.Tests/Helpers/Tester.cs
  2. 4
      ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
  3. 16
      ICSharpCode.Decompiler/CSharp/SequencePointBuilder.cs
  4. 1
      ICSharpCode.Decompiler/CSharp/Transforms/PatternStatementTransform.cs
  5. 223
      ICSharpCode.Decompiler/Disassembler/BlobDecoder.cs
  6. 279
      ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs
  7. 373
      ICSharpCode.Decompiler/Disassembler/DomExtensions.cs
  8. 127
      ICSharpCode.Decompiler/Disassembler/ILStructure.cs
  9. 1290
      ICSharpCode.Decompiler/Disassembler/MethodBodyDisassembler.cs
  10. 115
      ICSharpCode.Decompiler/Disassembler/OpCodeInfo.cs
  11. 607
      ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs
  12. 1231
      ICSharpCode.Decompiler/Dom/Dom.cs
  13. 239
      ICSharpCode.Decompiler/Dom/MetadataExtensions.cs
  14. 230
      ICSharpCode.Decompiler/Dom/MetadataResolver.cs
  15. 92
      ICSharpCode.Decompiler/Dom/SequencePoint.cs
  16. 6
      ICSharpCode.Decompiler/DotNetCore/DotNetCorePathFinder.cs
  17. 16
      ICSharpCode.Decompiler/DotNetCore/DotNetCorePathFinderExtensions.cs
  18. 66
      ICSharpCode.Decompiler/DotNetCore/UniversalAssemblyResolver.cs
  19. 8
      ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
  20. 335
      ICSharpCode.Decompiler/IL/ILOpCodes.cs
  21. 132
      ICSharpCode.Decompiler/IL/ILOpCodes.tt
  22. 41
      ICSharpCode.Decompiler/IL/SequencePoint.cs
  23. 24
      ICSharpCode.Decompiler/TypeSystem/CecilLoader.cs
  24. 27
      ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs
  25. 6
      ICSharpCode.Decompiler/TypeSystem/Implementation/TypeSpecification.cs
  26. 2
      ICSharpCode.Decompiler/Util/EmptyList.cs
  27. 1
      ILSpy.AddIn/ILSpy.AddIn.csproj
  28. 1
      ILSpy.BamlDecompiler.Tests/ILSpy.BamlDecompiler.Tests.csproj
  29. 8
      ILSpy.BamlDecompiler/BamlResourceEntryNode.cs
  30. 5
      ILSpy.BamlDecompiler/BamlResourceNodeFactory.cs
  31. 35
      ILSpy.BamlDecompiler/CecilDependencyPropertyDescriptor.cs
  32. 60
      ILSpy.BamlDecompiler/CecilType.cs
  33. 54
      ILSpy.BamlDecompiler/CecilTypeResolver.cs
  34. 2
      ILSpy.BamlDecompiler/ILSpy.BamlDecompiler.csproj
  35. 30
      ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/IType.cs
  36. 6
      ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/ITypeResolver.cs
  37. 2
      ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/KnownInfo.cs
  38. 18
      ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/TypeDeclaration.cs
  39. 6
      ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlBamlReader.cs
  40. 33
      ILSpy.BamlDecompiler/SRMDependencyPropertyDescriptor.cs
  41. 14
      ILSpy.sln
  42. 2
      ILSpy/Commands/DecompileAllCommand.cs
  43. 10
      ILSpy/DebugSteps.xaml.cs
  44. 36
      ILSpy/ExtensionMethods.cs
  45. 39
      ILSpy/ILSpy.csproj
  46. 49
      ILSpy/Languages/CSharpLanguage.cs
  47. 4
      ILSpy/Languages/ILAstLanguage.cs
  48. 96
      ILSpy/Languages/ILLanguage.cs
  49. 86
      ILSpy/Languages/ITypeProvider.cs
  50. 242
      ILSpy/Languages/Language.cs
  51. 4
      ILSpy/Languages/Languages.cs
  52. 118
      ILSpy/LoadedAssembly.cs
  53. 19
      ILSpy/MainWindow.xaml.cs
  54. 8
      ILSpy/SearchPane.cs
  55. 113
      ILSpy/SearchStrategies.cs
  56. 6
      ILSpy/TextView/DecompilerTextView.cs
  57. 51
      ILSpy/TreeNodes/Analyzer/AnalyzeContextMenuEntry.cs
  58. 24
      ILSpy/TreeNodes/Analyzer/AnalyzedAssemblyTreeNode.cs
  59. 6
      ILSpy/TreeNodes/Analyzer/AnalyzedAttributeAppliedToTreeNode.cs
  60. 2
      ILSpy/TreeNodes/Analyzer/AnalyzedEventAccessorTreeNode.cs
  61. 13
      ILSpy/TreeNodes/Analyzer/AnalyzedEventOverridesTreeNode.cs
  62. 14
      ILSpy/TreeNodes/Analyzer/AnalyzedEventTreeNode.cs
  63. 51
      ILSpy/TreeNodes/Analyzer/AnalyzedFieldAccessTreeNode.cs
  64. 13
      ILSpy/TreeNodes/Analyzer/AnalyzedFieldTreeNode.cs
  65. 11
      ILSpy/TreeNodes/Analyzer/AnalyzedMethodTreeNode.cs
  66. 2
      ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsedByTreeNode.cs
  67. 51
      ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsesTreeNode.cs
  68. 2
      ILSpy/TreeNodes/Analyzer/AnalyzedPropertyAccessorTreeNode.cs
  69. 13
      ILSpy/TreeNodes/Analyzer/AnalyzedPropertyOverridesTreeNode.cs
  70. 23
      ILSpy/TreeNodes/Analyzer/AnalyzedPropertyTreeNode.cs
  71. 11
      ILSpy/TreeNodes/Analyzer/AnalyzedTypeExposedByTreeNode.cs
  72. 39
      ILSpy/TreeNodes/Analyzer/AnalyzedTypeInstantiationsTreeNode.cs
  73. 8
      ILSpy/TreeNodes/Analyzer/AnalyzedTypeTreeNode.cs
  74. 26
      ILSpy/TreeNodes/Analyzer/AnalyzedTypeUsedByTreeNode.cs
  75. 2
      ILSpy/TreeNodes/Analyzer/AnalyzedVirtualMethodUsedByTreeNode.cs
  76. 6
      ILSpy/TreeNodes/Analyzer/AnalyzerEntityTreeNode.cs
  77. 4
      ILSpy/TreeNodes/Analyzer/AnalyzerSearchTreeNode.cs
  78. 6
      ILSpy/TreeNodes/Analyzer/Helpers.cs
  79. 53
      ILSpy/TreeNodes/Analyzer/ScopedWhereUsedAnalyzer.cs
  80. 37
      ILSpy/TreeNodes/AssemblyListTreeNode.cs
  81. 6
      ILSpy/TreeNodes/AssemblyReferenceTreeNode.cs
  82. 43
      ILSpy/TreeNodes/AssemblyTreeNode.cs
  83. 23
      ILSpy/TreeNodes/BaseTypesEntryNode.cs
  84. 14
      ILSpy/TreeNodes/BaseTypesTreeNode.cs
  85. 4
      ILSpy/TreeNodes/CopyFullyQualifiedNameContextMenuEntry.cs
  86. 16
      ILSpy/TreeNodes/DerivedTypesEntryNode.cs
  87. 34
      ILSpy/TreeNodes/DerivedTypesTreeNode.cs
  88. 43
      ILSpy/TreeNodes/EventTreeNode.cs
  89. 42
      ILSpy/TreeNodes/FieldTreeNode.cs
  90. 4
      ILSpy/TreeNodes/IMemberTreeNode.cs
  91. 54
      ILSpy/TreeNodes/MethodTreeNode.cs
  92. 4
      ILSpy/TreeNodes/ModuleReferenceTreeNode.cs
  93. 35
      ILSpy/TreeNodes/PropertyTreeNode.cs
  94. 19
      ILSpy/TreeNodes/ReferenceFolderTreeNode.cs
  95. 6
      ILSpy/TreeNodes/ResourceListTreeNode.cs
  96. 9
      ILSpy/TreeNodes/ResourceNodes/CursorResourceEntryNode.cs
  97. 2
      ILSpy/TreeNodes/ResourceNodes/IResourceNodeFactory.cs
  98. 9
      ILSpy/TreeNodes/ResourceNodes/IconResourceEntryNode.cs
  99. 7
      ILSpy/TreeNodes/ResourceNodes/ImageListResourceEntryNode.cs
  100. 9
      ILSpy/TreeNodes/ResourceNodes/ImageResourceEntryNode.cs
  101. Some files were not shown because too many files have changed in this diff Show More

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

@ -36,7 +36,6 @@ using ICSharpCode.Decompiler.TypeSystem;
using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CSharp; using Microsoft.CSharp;
using Mono.Cecil;
using NUnit.Framework; using NUnit.Framework;
namespace ICSharpCode.Decompiler.Tests.Helpers namespace ICSharpCode.Decompiler.Tests.Helpers
@ -114,7 +113,7 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
using (var writer = new StreamWriter(outputFile)) { using (var writer = new StreamWriter(outputFile)) {
//module.Name = Path.GetFileNameWithoutExtension(outputFile); //module.Name = Path.GetFileNameWithoutExtension(outputFile);
var output = new PlainTextOutput(writer); var output = new PlainTextOutput(writer);
ReflectionDisassembler rd = new ReflectionDisassembler(output, module.GetMetadataReader(), CancellationToken.None); ReflectionDisassembler rd = new ReflectionDisassembler(output, CancellationToken.None);
rd.DetectControlStructure = false; rd.DetectControlStructure = false;
//rd.WriteAssemblyReferences(module); //rd.WriteAssemblyReferences(module);
/*if (module.Assembly != null) /*if (module.Assembly != null)

4
ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs

@ -178,7 +178,7 @@ namespace ICSharpCode.Decompiler.CSharp
} }
public CSharpDecompiler(string fileName, DecompilerSettings settings) public CSharpDecompiler(string fileName, DecompilerSettings settings)
: this(UniversalAssemblyResolver.LoadMainModule(fileName, settings.ThrowOnAssemblyResolveErrors, settings.LoadInMemory), settings) //: this(UniversalAssemblyResolver.LoadMainModule(fileName, settings.ThrowOnAssemblyResolveErrors, settings.LoadInMemory), settings)
{ {
} }
@ -1158,7 +1158,7 @@ namespace ICSharpCode.Decompiler.CSharp
/// ///
/// This only works correctly when the nodes in the syntax tree have line/column information. /// This only works correctly when the nodes in the syntax tree have line/column information.
/// </summary> /// </summary>
public Dictionary<ILFunction, List<SequencePoint>> CreateSequencePoints(SyntaxTree syntaxTree) public Dictionary<ILFunction, List<Dom.SequencePoint>> CreateSequencePoints(SyntaxTree syntaxTree)
{ {
SequencePointBuilder spb = new SequencePointBuilder(); SequencePointBuilder spb = new SequencePointBuilder();
syntaxTree.AcceptVisitor(spb); syntaxTree.AcceptVisitor(spb);

16
ICSharpCode.Decompiler/CSharp/SequencePointBuilder.cs

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

1
ICSharpCode.Decompiler/CSharp/Transforms/PatternStatementTransform.cs

@ -25,6 +25,7 @@ using ICSharpCode.Decompiler.CSharp.Syntax.PatternMatching;
using ICSharpCode.Decompiler.CSharp.TypeSystem; using ICSharpCode.Decompiler.CSharp.TypeSystem;
using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.Semantics; using ICSharpCode.Decompiler.Semantics;
using Mono.Cecil;
namespace ICSharpCode.Decompiler.CSharp.Transforms namespace ICSharpCode.Decompiler.CSharp.Transforms
{ {

223
ICSharpCode.Decompiler/Disassembler/BlobDecoder.cs

@ -0,0 +1,223 @@
// 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.Generic;
using ICSharpCode.Decompiler.Semantics;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.TypeSystem.Implementation;
using SRM = System.Reflection.Metadata;
namespace ICSharpCode.Decompiler.Disassembler
{
sealed class BlobDecoder
{
SRM.BlobReader blob;
static readonly ITypeResolveContext context = new SimpleTypeResolveContext(MinimalCorlib.Instance.CreateCompilation());
public BlobDecoder(SRM.BlobReader blob)
{
this.blob = blob;
}
public int Offset => blob.Offset;
public ResolveResult ReadFixedArg(IType argType)
{
if (argType.Kind == TypeKind.Array) {
if (((ArrayType)argType).Dimensions != 1) {
// Only single-dimensional arrays are supported
return ErrorResolveResult.UnknownError;
}
IType elementType = ((ArrayType)argType).ElementType;
uint numElem = blob.ReadUInt32();
if (numElem == 0xffffffff) {
// null reference
return new ConstantResolveResult(argType, null);
} else {
ResolveResult[] elements = new ResolveResult[numElem];
for (int i = 0; i < elements.Length; i++) {
elements[i] = ReadElem(elementType);
// Stop decoding when encountering an error:
if (elements[i].IsError)
return ErrorResolveResult.UnknownError;
}
IType int32 = context.Compilation.FindType(KnownTypeCode.Int32);
ResolveResult[] sizeArgs = { new ConstantResolveResult(int32, elements.Length) };
return new ArrayCreateResolveResult(argType, sizeArgs, elements);
}
} else {
return ReadElem(argType);
}
}
public ResolveResult ReadElem(IType elementType)
{
ITypeDefinition underlyingType;
if (elementType.Kind == TypeKind.Enum) {
underlyingType = elementType.GetDefinition().EnumUnderlyingType.GetDefinition();
} else {
underlyingType = elementType.GetDefinition();
}
if (underlyingType == null)
return ErrorResolveResult.UnknownError;
KnownTypeCode typeCode = underlyingType.KnownTypeCode;
if (typeCode == KnownTypeCode.Object) {
// boxed value type
IType boxedTyped = ReadCustomAttributeFieldOrPropType();
ResolveResult elem = ReadFixedArg(boxedTyped);
if (elem.IsCompileTimeConstant && elem.ConstantValue == null)
return new ConstantResolveResult(elementType, null);
else
return new ConversionResolveResult(elementType, elem, Conversion.BoxingConversion);
} else if (typeCode == KnownTypeCode.Type) {
var type = ReadType();
if (type != null) {
return new TypeOfResolveResult(underlyingType, type);
} else {
return new ConstantResolveResult(underlyingType, null);
}
} else {
return new ConstantResolveResult(elementType, ReadElemValue(typeCode));
}
}
object ReadElemValue(KnownTypeCode typeCode)
{
switch (typeCode) {
case KnownTypeCode.Boolean:
return blob.ReadBoolean();
case KnownTypeCode.Char:
return blob.ReadChar();
case KnownTypeCode.SByte:
return blob.ReadSByte();
case KnownTypeCode.Byte:
return blob.ReadByte();
case KnownTypeCode.Int16:
return blob.ReadInt16();
case KnownTypeCode.UInt16:
return blob.ReadUInt16();
case KnownTypeCode.Int32:
return blob.ReadInt32();
case KnownTypeCode.UInt32:
return blob.ReadUInt32();
case KnownTypeCode.Int64:
return blob.ReadInt64();
case KnownTypeCode.UInt64:
return blob.ReadUInt64();
case KnownTypeCode.Single:
return blob.ReadSingle();
case KnownTypeCode.Double:
return blob.ReadDouble();
case KnownTypeCode.String:
return blob.ReadSerializedString();
default:
throw new NotSupportedException();
}
}
public KeyValuePair<string, ResolveResult> ReadNamedArg()
{
SymbolKind memberType;
var b = blob.ReadByte();
switch (b) {
case 0x53:
memberType = SymbolKind.Field;
break;
case 0x54:
memberType = SymbolKind.Property;
break;
default:
throw new NotSupportedException(string.Format("Custom member type 0x{0:x} is not supported.", b));
}
IType type = ReadCustomAttributeFieldOrPropType();
string name = blob.ReadSerializedString();
ResolveResult val = ReadFixedArg(type);
return new KeyValuePair<string, ResolveResult>(name, val);
}
IType ReadCustomAttributeFieldOrPropType()
{
ICompilation compilation = context.Compilation;
var b = blob.ReadByte();
switch (b) {
case 0x02:
return compilation.FindType(KnownTypeCode.Boolean);
case 0x03:
return compilation.FindType(KnownTypeCode.Char);
case 0x04:
return compilation.FindType(KnownTypeCode.SByte);
case 0x05:
return compilation.FindType(KnownTypeCode.Byte);
case 0x06:
return compilation.FindType(KnownTypeCode.Int16);
case 0x07:
return compilation.FindType(KnownTypeCode.UInt16);
case 0x08:
return compilation.FindType(KnownTypeCode.Int32);
case 0x09:
return compilation.FindType(KnownTypeCode.UInt32);
case 0x0a:
return compilation.FindType(KnownTypeCode.Int64);
case 0x0b:
return compilation.FindType(KnownTypeCode.UInt64);
case 0x0c:
return compilation.FindType(KnownTypeCode.Single);
case 0x0d:
return compilation.FindType(KnownTypeCode.Double);
case 0x0e:
return compilation.FindType(KnownTypeCode.String);
case 0x1d:
return new ArrayType(compilation, ReadCustomAttributeFieldOrPropType());
case 0x50:
return compilation.FindType(KnownTypeCode.Type);
case 0x51: // boxed value type
return compilation.FindType(KnownTypeCode.Object);
case 0x55: // enum
var type = ReadType();
if (type == null) {
throw new NotSupportedException("Enum type should not be null.");
}
return type;
default:
throw new NotSupportedException(string.Format("Custom attribute type 0x{0:x} is not supported.", b));
}
}
IType ReadType()
{
string typeName = blob.ReadSerializedString();
if (typeName == null) {
return null;
}
ITypeReference typeReference = ReflectionHelper.ParseReflectionName(typeName);
IType typeInCurrentAssembly = typeReference.Resolve(context);
if (typeInCurrentAssembly.Kind != TypeKind.Unknown)
return typeInCurrentAssembly;
// look for the type in mscorlib
ITypeDefinition systemObject = context.Compilation.FindType(KnownTypeCode.Object).GetDefinition();
if (systemObject != null) {
return typeReference.Resolve(new SimpleTypeResolveContext(systemObject.ParentAssembly));
} else {
// couldn't find corlib - return the unknown IType for the current assembly
return typeInCurrentAssembly;
}
}
}
}

279
ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs

@ -18,9 +18,11 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Mono.Cecil; using System.Linq;
using Mono.Cecil.Cil; using System.Reflection.Metadata;
using System.Text; using System.Text;
using ICSharpCode.Decompiler.Dom;
using ICSharpCode.Decompiler.Util;
using SRM = System.Reflection.Metadata; using SRM = System.Reflection.Metadata;
namespace ICSharpCode.Decompiler.Disassembler namespace ICSharpCode.Decompiler.Disassembler
@ -57,62 +59,35 @@ namespace ICSharpCode.Decompiler.Disassembler
return string.Format("IL_{0:x4}", offset); return string.Format("IL_{0:x4}", offset);
} }
public static void WriteOffsetReference(ITextOutput writer, Instruction instruction) public static void WriteOffsetReference(ITextOutput writer, int? offset)
{ {
if (instruction == null) if (offset == null)
writer.Write("null"); writer.Write("null");
else else
writer.WriteReference(OffsetToString(instruction.Offset), instruction); writer.WriteReference(OffsetToString(offset.Value), offset);
} }
public static void WriteTo(this ExceptionHandler exceptionHandler, ITextOutput writer) public static void WriteTo(this SRM.ExceptionRegion exceptionHandler, Dom.MethodDefinition method, ITextOutput writer)
{ {
writer.Write(".try "); writer.Write(".try ");
WriteOffsetReference(writer, exceptionHandler.TryStart); WriteOffsetReference(writer, exceptionHandler.TryOffset);
writer.Write('-'); writer.Write('-');
WriteOffsetReference(writer, exceptionHandler.TryEnd); WriteOffsetReference(writer, exceptionHandler.TryOffset + exceptionHandler.TryLength);
writer.Write(' '); writer.Write(' ');
writer.Write(exceptionHandler.HandlerType.ToString().ToLowerInvariant()); writer.Write(exceptionHandler.Kind.ToString().ToLowerInvariant());
if (exceptionHandler.FilterStart != null) { if (exceptionHandler.FilterOffset != -1) {
writer.Write(' '); writer.Write(' ');
WriteOffsetReference(writer, exceptionHandler.FilterStart); WriteOffsetReference(writer, exceptionHandler.FilterOffset);
writer.Write(" handler "); writer.Write(" handler ");
} }
if (exceptionHandler.CatchType != null) { if (!exceptionHandler.CatchType.IsNil) {
writer.Write(' '); writer.Write(' ');
exceptionHandler.CatchType.WriteTo(writer); exceptionHandler.CatchType.CoerceTypeReference(method.Module).WriteTo(writer, new GenericContext(method));
} }
writer.Write(' '); writer.Write(' ');
WriteOffsetReference(writer, exceptionHandler.HandlerStart); WriteOffsetReference(writer, exceptionHandler.HandlerOffset);
writer.Write('-'); writer.Write('-');
WriteOffsetReference(writer, exceptionHandler.HandlerEnd); WriteOffsetReference(writer, exceptionHandler.HandlerOffset + exceptionHandler.HandlerLength);
}
public static void WriteTo(this Instruction instruction, ITextOutput writer)
{
writer.WriteDefinition(OffsetToString(instruction.Offset), instruction);
writer.Write(": ");
writer.WriteReference(instruction.OpCode.Name, instruction.OpCode);
if (instruction.Operand != null) {
writer.Write(' ');
if (instruction.OpCode == OpCodes.Ldtoken) {
if (instruction.Operand is MethodReference)
writer.Write("method ");
else if (instruction.Operand is FieldReference)
writer.Write("field ");
}
WriteOperand(writer, instruction.Operand);
}
}
static void WriteLabelList(ITextOutput writer, Instruction[] instructions)
{
writer.Write("(");
for (int i = 0; i < instructions.Length; i++) {
if (i != 0) writer.Write(", ");
WriteOffsetReference(writer, instructions[i]);
}
writer.Write(")");
} }
static string ToInvariantCultureString(object value) static string ToInvariantCultureString(object value)
@ -123,57 +98,6 @@ namespace ICSharpCode.Decompiler.Disassembler
: value.ToString(); : value.ToString();
} }
public static void WriteTo(this MethodReference method, ITextOutput writer)
{
if (method.ExplicitThis) {
writer.Write("instance explicit ");
} else if (method.HasThis) {
writer.Write("instance ");
}
if (method.CallingConvention == MethodCallingConvention.VarArg) {
writer.Write("vararg ");
}
method.ReturnType.WriteTo(writer, ILNameSyntax.SignatureNoNamedTypeParameters);
writer.Write(' ');
if (method.DeclaringType != null) {
method.DeclaringType.WriteTo(writer, ILNameSyntax.TypeName);
writer.Write("::");
}
MethodDefinition md = method as MethodDefinition;
if (md != null && md.IsCompilerControlled) {
writer.WriteReference(Escape(method.Name + "$PST" + method.MetadataToken.ToInt32().ToString("X8")), method);
} else {
writer.WriteReference(Escape(method.Name), method);
}
GenericInstanceMethod gim = method as GenericInstanceMethod;
if (gim != null) {
writer.Write('<');
for (int i = 0; i < gim.GenericArguments.Count; i++) {
if (i > 0)
writer.Write(", ");
gim.GenericArguments[i].WriteTo(writer);
}
writer.Write('>');
}
writer.Write("(");
var parameters = method.Parameters;
for (int i = 0; i < parameters.Count; ++i) {
if (i > 0)
writer.Write(", ");
parameters[i].ParameterType.WriteTo(writer, ILNameSyntax.SignatureNoNamedTypeParameters);
}
writer.Write(")");
}
static void WriteTo(this FieldReference field, ITextOutput writer)
{
field.FieldType.WriteTo(writer, ILNameSyntax.SignatureNoNamedTypeParameters);
writer.Write(' ');
field.DeclaringType.WriteTo(writer, ILNameSyntax.TypeName);
writer.Write("::");
writer.WriteReference(Escape(field.Name), field);
}
static bool IsValidIdentifierCharacter(char c) static bool IsValidIdentifierCharacter(char c)
{ {
return c == '_' || c == '$' || c == '@' || c == '?' || c == '`'; return c == '_' || c == '$' || c == '@' || c == '?' || c == '`';
@ -194,48 +118,9 @@ namespace ICSharpCode.Decompiler.Disassembler
return true; return true;
} }
static readonly HashSet<string> ilKeywords = BuildKeywordList(
"abstract", "algorithm", "alignment", "ansi", "any", "arglist",
"array", "as", "assembly", "assert", "at", "auto", "autochar", "beforefieldinit",
"blob", "blob_object", "bool", "brnull", "brnull.s", "brzero", "brzero.s", "bstr",
"bytearray", "byvalstr", "callmostderived", "carray", "catch", "cdecl", "cf",
"char", "cil", "class", "clsid", "const", "currency", "custom", "date", "decimal",
"default", "demand", "deny", "endmac", "enum", "error", "explicit", "extends", "extern",
"false", "famandassem", "family", "famorassem", "fastcall", "fault", "field", "filetime",
"filter", "final", "finally", "fixed", "float", "float32", "float64", "forwardref",
"fromunmanaged", "handler", "hidebysig", "hresult", "idispatch", "il", "illegal",
"implements", "implicitcom", "implicitres", "import", "in", "inheritcheck", "init",
"initonly", "instance", "int", "int16", "int32", "int64", "int8", "interface", "internalcall",
"iunknown", "lasterr", "lcid", "linkcheck", "literal", "localloc", "lpstr", "lpstruct", "lptstr",
"lpvoid", "lpwstr", "managed", "marshal", "method", "modopt", "modreq", "native", "nested",
"newslot", "noappdomain", "noinlining", "nomachine", "nomangle", "nometadata", "noncasdemand",
"noncasinheritance", "noncaslinkdemand", "noprocess", "not", "not_in_gc_heap", "notremotable",
"notserialized", "null", "nullref", "object", "objectref", "opt", "optil", "out",
"permitonly", "pinned", "pinvokeimpl", "prefix1", "prefix2", "prefix3", "prefix4", "prefix5", "prefix6",
"prefix7", "prefixref", "prejitdeny", "prejitgrant", "preservesig", "private", "privatescope", "protected",
"public", "record", "refany", "reqmin", "reqopt", "reqrefuse", "reqsecobj", "request", "retval",
"rtspecialname", "runtime", "safearray", "sealed", "sequential", "serializable", "special", "specialname",
"static", "stdcall", "storage", "stored_object", "stream", "streamed_object", "string", "struct",
"synchronized", "syschar", "sysstring", "tbstr", "thiscall", "tls", "to", "true", "typedref",
"unicode", "unmanaged", "unmanagedexp", "unsigned", "unused", "userdefined", "value", "valuetype",
"vararg", "variant", "vector", "virtual", "void", "wchar", "winapi", "with", "wrapper",
// These are not listed as keywords in spec, but ILAsm treats them as such
"property", "type", "flags", "callconv", "strict"
);
static HashSet<string> BuildKeywordList(params string[] keywords)
{
HashSet<string> s = new HashSet<string>(keywords);
foreach (var field in typeof(OpCodes).GetFields()) {
s.Add(((OpCode)field.GetValue(null)).Name);
}
return s;
}
public static string Escape(string identifier) public static string Escape(string identifier)
{ {
if (IsValidIdentifier(identifier) && !ilKeywords.Contains(identifier)) { if (IsValidIdentifier(identifier) && !IL.ILOpCodeExtensions.ILKeywords.Contains(identifier)) {
return identifier; return identifier;
} else { } else {
// The ECMA specification says that ' inside SQString should be ecaped using an octal escape sequence, // The ECMA specification says that ' inside SQString should be ecaped using an octal escape sequence,
@ -244,92 +129,26 @@ namespace ICSharpCode.Decompiler.Disassembler
} }
} }
public static void WriteTo(this TypeReference type, ITextOutput writer, ILNameSyntax syntax = ILNameSyntax.Signature) public static void WriteParameterReference(ITextOutput writer, Dom.MethodDefinition method, int sequence)
{ {
ILNameSyntax syntaxForElementTypes = syntax == ILNameSyntax.SignatureNoNamedTypeParameters ? syntax : ILNameSyntax.Signature; var metadata = method.Module.GetMetadataReader();
if (type is PinnedType) { var signatureHeader = method.DecodeSignature(new FullTypeNameSignatureDecoder(metadata), default(Unit)).Header;
((PinnedType)type).ElementType.WriteTo(writer, syntaxForElementTypes); int index = signatureHeader.IsInstance && !signatureHeader.HasExplicitThis ? sequence - 1 : sequence;
writer.Write(" pinned"); if (index < 0 || index >= method.Parameters.Count) {
} else if (type is ArrayType) { writer.Write(sequence.ToString());
ArrayType at = (ArrayType)type;
at.ElementType.WriteTo(writer, syntaxForElementTypes);
writer.Write('[');
writer.Write(string.Join(", ", at.Dimensions));
writer.Write(']');
} else if (type is GenericParameter) {
writer.Write('!');
if (((GenericParameter)type).Owner.GenericParameterType == GenericParameterType.Method)
writer.Write('!');
if (string.IsNullOrEmpty(type.Name) || type.Name[0] == '!' || syntax == ILNameSyntax.SignatureNoNamedTypeParameters)
writer.Write(((GenericParameter)type).Position.ToString());
else
writer.Write(Escape(type.Name));
} else if (type is ByReferenceType) {
((ByReferenceType)type).ElementType.WriteTo(writer, syntaxForElementTypes);
writer.Write('&');
} else if (type is PointerType) {
((PointerType)type).ElementType.WriteTo(writer, syntaxForElementTypes);
writer.Write('*');
} else if (type is GenericInstanceType) {
type.GetElementType().WriteTo(writer, syntaxForElementTypes);
writer.Write('<');
var arguments = ((GenericInstanceType)type).GenericArguments;
for (int i = 0; i < arguments.Count; i++) {
if (i > 0)
writer.Write(", ");
arguments[i].WriteTo(writer, syntaxForElementTypes);
}
writer.Write('>');
} else if (type is OptionalModifierType) {
((OptionalModifierType)type).ElementType.WriteTo(writer, syntax);
writer.Write(" modopt(");
((OptionalModifierType)type).ModifierType.WriteTo(writer, ILNameSyntax.TypeName);
writer.Write(") ");
} else if (type is RequiredModifierType) {
((RequiredModifierType)type).ElementType.WriteTo(writer, syntax);
writer.Write(" modreq(");
((RequiredModifierType)type).ModifierType.WriteTo(writer, ILNameSyntax.TypeName);
writer.Write(") ");
} else if (type is FunctionPointerType fpt) {
writer.Write("method ");
fpt.ReturnType.WriteTo(writer, syntax);
writer.Write(" *(");
bool first = true;
foreach (var p in fpt.Parameters) {
if (first)
first = false;
else
writer.Write(", ");
p.ParameterType.WriteTo(writer, syntax);
}
writer.Write(')');
} else if (type is SentinelType) {
writer.Write("..., ");
((SentinelType)type).ElementType.WriteTo(writer, syntax);
} else {
string name = PrimitiveTypeName(type.FullName);
if (syntax == ILNameSyntax.ShortTypeName) {
if (name != null)
writer.Write(name);
else
writer.WriteReference(Escape(type.Name), type);
} else if ((syntax == ILNameSyntax.Signature || syntax == ILNameSyntax.SignatureNoNamedTypeParameters) && name != null) {
writer.Write(name);
} else { } else {
if (syntax == ILNameSyntax.Signature || syntax == ILNameSyntax.SignatureNoNamedTypeParameters) var param = metadata.GetParameter(method.Parameters.ElementAt(index));
writer.Write(type.IsValueType ? "valuetype " : "class "); if (param.Name.IsNil) {
writer.Write(sequence.ToString());
if (type.DeclaringType != null) {
type.DeclaringType.WriteTo(writer, ILNameSyntax.TypeName);
writer.Write('/');
writer.WriteReference(Escape(type.Name), type);
} else { } else {
if (!type.IsDefinition && type.Scope != null && !(type is TypeSpecification)) writer.Write(Escape(metadata.GetString(param.Name)));
writer.Write("[{0}]", Escape(type.Scope.Name));
writer.WriteReference(Escape(type.FullName), type);
} }
} }
} }
public static void WriteVariableReference(ITextOutput writer, Dom.MethodDefinition method, int index)
{
writer.Write(index.ToString());
} }
public static void WriteOperand(ITextOutput writer, object operand) public static void WriteOperand(ITextOutput writer, object operand)
@ -337,19 +156,7 @@ namespace ICSharpCode.Decompiler.Disassembler
if (operand == null) if (operand == null)
throw new ArgumentNullException(nameof(operand)); throw new ArgumentNullException(nameof(operand));
Instruction targetInstruction = operand as Instruction; /*VariableReference variableRef = operand as VariableReference;
if (targetInstruction != null) {
WriteOffsetReference(writer, targetInstruction);
return;
}
Instruction[] targetInstructions = operand as Instruction[];
if (targetInstructions != null) {
WriteLabelList(writer, targetInstructions);
return;
}
VariableReference variableRef = operand as VariableReference;
if (variableRef != null) { if (variableRef != null) {
writer.WriteReference(variableRef.Index.ToString(), variableRef); writer.WriteReference(variableRef.Index.ToString(), variableRef);
return; return;
@ -363,25 +170,7 @@ namespace ICSharpCode.Decompiler.Disassembler
} else } else
writer.WriteReference(Escape(paramRef.Name), paramRef); writer.WriteReference(Escape(paramRef.Name), paramRef);
return; return;
} }*/
MethodReference methodRef = operand as MethodReference;
if (methodRef != null) {
methodRef.WriteTo(writer);
return;
}
TypeReference typeRef = operand as TypeReference;
if (typeRef != null) {
typeRef.WriteTo(writer, ILNameSyntax.TypeName);
return;
}
FieldReference fieldRef = operand as FieldReference;
if (fieldRef != null) {
fieldRef.WriteTo(writer);
return;
}
string s = operand as string; string s = operand as string;
if (s != null) { if (s != null) {

373
ICSharpCode.Decompiler/Disassembler/DomExtensions.cs

@ -0,0 +1,373 @@
// 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 System.Reflection;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using ICSharpCode.Decompiler.Dom;
using ICSharpCode.Decompiler.Util;
namespace ICSharpCode.Decompiler.Disassembler
{
public static class DomExtensions
{
public static void WriteTo(this Dom.FieldDefinition field, ITextOutput output)
{
var signature = field.DecodeSignature(new DisassemblerSignatureProvider(field.Module, output), new GenericContext(field.DeclaringType));
signature(ILNameSyntax.SignatureNoNamedTypeParameters);
output.Write(' ');
field.DeclaringType.WriteTo(output, ILNameSyntax.TypeName);
output.Write("::");
output.Write(DisassemblerHelpers.Escape(field.Name));
}
public static void WriteTo(this IMemberReference member, ITextOutput output, GenericContext genericContext, ILNameSyntax syntax = ILNameSyntax.Signature)
{
void WriteParent(EntityHandle parentHandle)
{
var metadata = member.Module.GetMetadataReader();
switch (parentHandle.Kind) {
case HandleKind.MethodDefinition:
new Dom.MethodDefinition(member.Module, (MethodDefinitionHandle)parentHandle).WriteTo(output, genericContext, syntax);
break;
case HandleKind.ModuleReference:
output.Write('[');
var moduleRef = metadata.GetModuleReference((ModuleReferenceHandle)parentHandle);
output.Write(metadata.GetString(moduleRef.Name));
output.Write(']');
break;
case HandleKind.TypeDefinition:
new Dom.TypeDefinition(member.Module, (TypeDefinitionHandle)parentHandle).WriteTo(output, syntax);
break;
case HandleKind.TypeReference:
new Dom.TypeReference(member.Module, (TypeReferenceHandle)parentHandle).WriteTo(output, syntax);
break;
case HandleKind.TypeSpecification:
new Dom.TypeSpecification(member.Module, (TypeSpecificationHandle)parentHandle).WriteTo(output, genericContext, syntax);
break;
}
}
MethodSignature<Action<ILNameSyntax>> signature;
switch (member) {
case Dom.MethodDefinition md:
md.WriteTo(output);
break;
case Dom.MemberReference mr:
switch (mr.Kind) {
case MemberReferenceKind.Method:
signature = mr.DecodeMethodSignature(new DisassemblerSignatureProvider(member.Module, output), genericContext);
if (signature.Header.HasExplicitThis) {
output.Write("instance explicit ");
} else if (signature.Header.IsInstance) {
output.Write("instance ");
}
if (signature.Header.CallingConvention == SignatureCallingConvention.VarArgs) {
output.Write("vararg ");
}
signature.ReturnType(ILNameSyntax.SignatureNoNamedTypeParameters);
output.Write(' ');
WriteParent(mr.Parent);
output.Write("::");
output.Write(DisassemblerHelpers.Escape(mr.Name));
output.Write("(");
for (int i = 0; i < signature.ParameterTypes.Length; ++i) {
if (i > 0)
output.Write(", ");
signature.ParameterTypes[i](ILNameSyntax.SignatureNoNamedTypeParameters);
}
output.Write(")");
break;
case MemberReferenceKind.Field:
var fieldSignature = mr.DecodeFieldSignature(new DisassemblerSignatureProvider(member.Module, output), genericContext);
fieldSignature(ILNameSyntax.SignatureNoNamedTypeParameters);
output.Write(' ');
WriteParent(mr.Parent);
output.Write("::");
output.Write(DisassemblerHelpers.Escape(mr.Name));
break;
}
break;
case Dom.MethodSpecification ms:
var substitution = ms.DecodeSignature(new DisassemblerSignatureProvider(ms.Module, output), genericContext);
switch (ms.Method) {
case Dom.MethodDefinition method:
var metadata = method.Module.GetMetadataReader();
signature = method.DecodeSignature(new DisassemblerSignatureProvider(method.Module, output), new GenericContext(method));
if (signature.Header.HasExplicitThis) {
output.Write("instance explicit ");
} else if (signature.Header.IsInstance) {
output.Write("instance ");
}
if (signature.Header.CallingConvention == SignatureCallingConvention.VarArgs) {
output.Write("vararg ");
}
signature.ReturnType(ILNameSyntax.SignatureNoNamedTypeParameters);
output.Write(' ');
if (!method.DeclaringType.IsNil) {
method.DeclaringType.WriteTo(output, ILNameSyntax.TypeName);
output.Write("::");
}
bool isCompilerControlled = (method.Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.PrivateScope;
if (isCompilerControlled) {
output.Write(DisassemblerHelpers.Escape(method.Name + "$PST" + MetadataTokens.GetToken(method.Handle).ToString("X8")));
} else {
output.Write(DisassemblerHelpers.Escape(method.Name));
}
output.Write('<');
for (int i = 0; i < substitution.Length; i++) {
if (i > 0)
output.Write(", ");
substitution[i](syntax);
}
output.Write('>');
output.Write("(");
for (int i = 0; i < signature.ParameterTypes.Length; ++i) {
if (i > 0)
output.Write(", ");
signature.ParameterTypes[i](ILNameSyntax.SignatureNoNamedTypeParameters);
}
output.Write(")");
break;
case Dom.MemberReference mr:
signature = mr.DecodeMethodSignature(new DisassemblerSignatureProvider(member.Module, output), genericContext);
if (signature.Header.HasExplicitThis) {
output.Write("instance explicit ");
} else if (signature.Header.IsInstance) {
output.Write("instance ");
}
if (signature.Header.CallingConvention == SignatureCallingConvention.VarArgs) {
output.Write("vararg ");
}
signature.ReturnType(ILNameSyntax.SignatureNoNamedTypeParameters);
output.Write(' ');
WriteParent(mr.Parent);
output.Write("::");
output.Write(DisassemblerHelpers.Escape(mr.Name));
output.Write('<');
for (int i = 0; i < substitution.Length; i++) {
if (i > 0)
output.Write(", ");
substitution[i](syntax);
}
output.Write('>');
output.Write("(");
for (int i = 0; i < signature.ParameterTypes.Length; ++i) {
if (i > 0)
output.Write(", ");
signature.ParameterTypes[i](ILNameSyntax.SignatureNoNamedTypeParameters);
}
output.Write(")");
break;
}
break;
}
}
public static void WriteTo(this Dom.TypeReference typeRef, ITextOutput output, ILNameSyntax syntax = ILNameSyntax.Signature)
{
var metadata = typeRef.Module.GetMetadataReader();
if (!typeRef.ResolutionScope.IsNil) {
output.Write("[");
var currentTypeRef = typeRef;
while (currentTypeRef.ResolutionScope.Kind == HandleKind.TypeReference) {
currentTypeRef = new Dom.TypeReference(currentTypeRef.Module, (TypeReferenceHandle)currentTypeRef.ResolutionScope);
}
switch (currentTypeRef.ResolutionScope.Kind) {
case HandleKind.ModuleReference:
break;
case HandleKind.AssemblyReference:
var asmRef = metadata.GetAssemblyReference((AssemblyReferenceHandle)currentTypeRef.ResolutionScope);
output.Write(DisassemblerHelpers.Escape(metadata.GetString(asmRef.Name)));
break;
}
output.Write("]");
}
output.WriteReference(typeRef.FullName.ToILNameString(), typeRef);
}
public static void WriteTo(this Dom.TypeDefinition typeDefinition, ITextOutput output, ILNameSyntax syntax = ILNameSyntax.Signature)
{
output.WriteReference(typeDefinition.FullName.ToILNameString(), typeDefinition);
}
public static void WriteTo(this Dom.TypeSpecification typeSpecification, ITextOutput output, GenericContext genericContext, ILNameSyntax syntax = ILNameSyntax.Signature)
{
var signature = typeSpecification.DecodeSignature(new DisassemblerSignatureProvider(typeSpecification.Module, output), genericContext);
signature(syntax);
}
public static void WriteTo(this ITypeReference type, ITextOutput output, GenericContext genericContext, ILNameSyntax syntax = ILNameSyntax.Signature)
{
switch (type) {
case Dom.TypeDefinition td:
td.WriteTo(output, syntax);
break;
case Dom.TypeReference tr:
tr.WriteTo(output, syntax);
break;
case Dom.TypeSpecification ts:
ts.WriteTo(output, genericContext, syntax);
break;
}
}
public static void WriteTo(this Dom.MethodDefinition method, ITextOutput output)
{
var metadata = method.Module.GetMetadataReader();
var signature = method.DecodeSignature(new DisassemblerSignatureProvider(method.Module, output), new GenericContext(method));
if (signature.Header.HasExplicitThis) {
output.Write("instance explicit ");
} else if (signature.Header.IsInstance) {
output.Write("instance ");
}
if (signature.Header.CallingConvention == SignatureCallingConvention.VarArgs) {
output.Write("vararg ");
}
signature.ReturnType(ILNameSyntax.SignatureNoNamedTypeParameters);
output.Write(' ');
if (!method.DeclaringType.IsNil) {
method.DeclaringType.WriteTo(output, ILNameSyntax.TypeName);
output.Write("::");
}
bool isCompilerControlled = (method.Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.PrivateScope;
if (isCompilerControlled) {
output.Write(DisassemblerHelpers.Escape(method.Name + "$PST" + MetadataTokens.GetToken(method.Handle).ToString("X8")));
} else {
output.Write(DisassemblerHelpers.Escape(method.Name));
}
var genericParameters = method.GenericParameters;
if (genericParameters.Count > 0) {
output.Write('<');
for (int i = 0; i < genericParameters.Count; i++) {
if (i > 0)
output.Write(", ");
var gp = metadata.GetGenericParameter(genericParameters[i]);
if ((gp.Attributes & GenericParameterAttributes.ReferenceTypeConstraint) == GenericParameterAttributes.ReferenceTypeConstraint) {
output.Write("class ");
} else if ((gp.Attributes & GenericParameterAttributes.NotNullableValueTypeConstraint) == GenericParameterAttributes.NotNullableValueTypeConstraint) {
output.Write("valuetype ");
}
if ((gp.Attributes & GenericParameterAttributes.DefaultConstructorConstraint) == GenericParameterAttributes.DefaultConstructorConstraint) {
output.Write(".ctor ");
}
var constraints = gp.GetConstraints();
if (constraints.Count > 0) {
output.Write('(');
for (int j = 0; j < constraints.Count; j++) {
if (j > 0)
output.Write(", ");
var constraint = metadata.GetGenericParameterConstraint(constraints[j]);
constraint.Type.CoerceTypeReference(method.Module).WriteTo(output, new GenericContext(method), ILNameSyntax.TypeName);
}
output.Write(") ");
}
if ((gp.Attributes & GenericParameterAttributes.Contravariant) == GenericParameterAttributes.Contravariant) {
output.Write('-');
} else if ((gp.Attributes & GenericParameterAttributes.Covariant) == GenericParameterAttributes.Covariant) {
output.Write('+');
}
output.Write(DisassemblerHelpers.Escape(metadata.GetString(gp.Name)));
}
output.Write('>');
}
output.Write("(");
for (int i = 0; i < signature.ParameterTypes.Length; ++i) {
if (i > 0)
output.Write(", ");
signature.ParameterTypes[i](ILNameSyntax.SignatureNoNamedTypeParameters);
}
output.Write(")");
}
public static bool IsBaseTypeOf(this ITypeReference baseType, ITypeReference derivedType)
{
var derivedTypeDefinition = derivedType.GetDefinition();
while (!derivedTypeDefinition.IsNil) {
if (derivedTypeDefinition.FullName == baseType.FullName)
return true;
derivedTypeDefinition = derivedTypeDefinition.BaseType.GetDefinition();
}
return false;
}
}
public class TypeUsedInSignature : ISignatureTypeProvider<bool, Unit>
{
readonly PEFile module;
readonly Dom.TypeDefinition type;
public TypeUsedInSignature(ITypeReference type)
{
this.module = type.Module;
this.type = type.GetDefinition();
}
public bool GetArrayType(bool elementType, ArrayShape shape) => elementType;
public bool GetByReferenceType(bool elementType) => elementType;
public bool GetFunctionPointerType(MethodSignature<bool> signature)
{
throw new NotImplementedException();
}
public bool GetGenericInstantiation(bool genericType, ImmutableArray<bool> typeArguments)
{
throw new NotImplementedException();
}
public bool GetGenericMethodParameter(Unit genericContext, int index) => false;
public bool GetGenericTypeParameter(Unit genericContext, int index) => false;
public bool GetModifiedType(bool modifier, bool unmodifiedType, bool isRequired)
{
throw new NotImplementedException();
}
public bool GetPinnedType(bool elementType) => elementType;
public bool GetPointerType(bool elementType) => elementType;
public bool GetPrimitiveType(PrimitiveTypeCode typeCode)
{
throw new NotImplementedException();
}
public bool GetSZArrayType(bool elementType) => elementType;
public bool GetTypeFromDefinition(MetadataReader reader, TypeDefinitionHandle handle, byte rawTypeKind)
{
return module == type.Module && handle == type.Handle;
}
public bool GetTypeFromReference(MetadataReader reader, TypeReferenceHandle handle, byte rawTypeKind)
{
return new Dom.TypeReference(module, handle).GetDefinition() == type;
}
public bool GetTypeFromSpecification(MetadataReader reader, Unit genericContext, TypeSpecificationHandle handle, byte rawTypeKind)
{
return new Dom.TypeSpecification(module, handle).GetDefinition() == type;
}
}
}

127
ICSharpCode.Decompiler/Disassembler/ILStructure.cs

@ -19,7 +19,9 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
using Mono.Cecil.Cil; using System.Reflection.Metadata;
using ICSharpCode.Decompiler.IL;
using ICSharpCode.Decompiler.Util;
namespace ICSharpCode.Decompiler.Disassembler namespace ICSharpCode.Decompiler.Disassembler
{ {
@ -55,6 +57,7 @@ namespace ICSharpCode.Decompiler.Disassembler
/// </summary> /// </summary>
public class ILStructure public class ILStructure
{ {
public readonly Dom.MethodDefinition Method;
public readonly ILStructureType Type; public readonly ILStructureType Type;
/// <summary> /// <summary>
@ -70,82 +73,83 @@ namespace ICSharpCode.Decompiler.Disassembler
/// <summary> /// <summary>
/// The exception handler associated with the Try, Filter or Handler block. /// The exception handler associated with the Try, Filter or Handler block.
/// </summary> /// </summary>
public readonly ExceptionHandler ExceptionHandler; public readonly ExceptionRegion ExceptionHandler;
/// <summary> /// <summary>
/// The loop's entry point. /// The loop's entry point.
/// </summary> /// </summary>
public readonly Instruction LoopEntryPoint; public readonly int LoopEntryPointOffset;
/// <summary> /// <summary>
/// The list of child structures. /// The list of child structures.
/// </summary> /// </summary>
public readonly List<ILStructure> Children = new List<ILStructure>(); public readonly List<ILStructure> Children = new List<ILStructure>();
public ILStructure(MethodBody body) public ILStructure(Dom.MethodDefinition method, MethodBodyBlock body)
: this(ILStructureType.Root, 0, body.CodeSize) : this(method, ILStructureType.Root, 0, body.GetILReader().Length)
{ {
// Build the tree of exception structures: // Build the tree of exception structures:
for (int i = 0; i < body.ExceptionHandlers.Count; i++) { for (int i = 0; i < body.ExceptionRegions.Length; i++) {
ExceptionHandler eh = body.ExceptionHandlers[i]; ExceptionRegion eh = body.ExceptionRegions[i];
if (!body.ExceptionHandlers.Take(i).Any(oldEh => oldEh.TryStart == eh.TryStart && oldEh.TryEnd == eh.TryEnd)) if (!body.ExceptionRegions.Take(i).Any(oldEh => oldEh.TryOffset == eh.TryOffset && oldEh.TryLength == eh.TryLength))
AddNestedStructure(new ILStructure(ILStructureType.Try, eh.TryStart.Offset, eh.TryEnd.Offset, eh)); AddNestedStructure(new ILStructure(method, ILStructureType.Try, eh.TryOffset, eh.TryOffset + eh.TryLength, eh));
if (eh.HandlerType == ExceptionHandlerType.Filter) if (eh.Kind == ExceptionRegionKind.Filter)
AddNestedStructure(new ILStructure(ILStructureType.Filter, eh.FilterStart.Offset, eh.HandlerStart.Offset, eh)); AddNestedStructure(new ILStructure(method, ILStructureType.Filter, eh.FilterOffset, eh.HandlerOffset, eh));
AddNestedStructure(new ILStructure(ILStructureType.Handler, eh.HandlerStart.Offset, eh.HandlerEnd == null ? body.CodeSize : eh.HandlerEnd.Offset, eh)); AddNestedStructure(new ILStructure(method, ILStructureType.Handler, eh.HandlerOffset, eh.HandlerOffset + eh.HandlerLength, eh));
} }
// Very simple loop detection: look for backward branches // Very simple loop detection: look for backward branches
List<KeyValuePair<Instruction, Instruction>> allBranches = FindAllBranches(body); (var allBranches, var isAfterConditionalBranch) = FindAllBranches(body.GetILReader());
// We go through the branches in reverse so that we find the biggest possible loop boundary first (think loops with "continue;") // We go through the branches in reverse so that we find the biggest possible loop boundary first (think loops with "continue;")
for (int i = allBranches.Count - 1; i >= 0; i--) { for (int i = allBranches.Count - 1; i >= 0; i--) {
int loopEnd = allBranches[i].Key.GetEndOffset(); int loopEnd = allBranches[i].Source.End;
int loopStart = allBranches[i].Value.Offset; int loopStart = allBranches[i].Target;
if (loopStart < loopEnd) { if (loopStart < loopEnd) {
// We found a backward branch. This is a potential loop. // We found a backward branch. This is a potential loop.
// Check that is has only one entry point: // Check that is has only one entry point:
Instruction entryPoint = null; int entryPoint = -1;
// entry point is first instruction in loop if prev inst isn't an unconditional branch // entry point is first instruction in loop if prev inst isn't an unconditional branch
Instruction prev = allBranches[i].Value.Previous; if (!isAfterConditionalBranch[loopStart])
if (prev != null && !prev.OpCode.IsUnconditionalBranch()) entryPoint = allBranches[i].Target;
entryPoint = allBranches[i].Value;
bool multipleEntryPoints = false; bool multipleEntryPoints = false;
foreach (var pair in allBranches) { foreach (var branch in allBranches) {
if (pair.Key.Offset < loopStart || pair.Key.Offset >= loopEnd) { if (branch.Source.Start < loopStart || branch.Source.Start >= loopEnd) {
if (loopStart <= pair.Value.Offset && pair.Value.Offset < loopEnd) { if (loopStart <= branch.Target && branch.Target < loopEnd) {
// jump from outside the loop into the loop // jump from outside the loop into the loop
if (entryPoint == null) if (entryPoint < 0)
entryPoint = pair.Value; entryPoint = branch.Target;
else if (pair.Value != entryPoint) else if (branch.Target != entryPoint)
multipleEntryPoints = true; multipleEntryPoints = true;
} }
} }
} }
if (!multipleEntryPoints) { if (!multipleEntryPoints) {
AddNestedStructure(new ILStructure(ILStructureType.Loop, loopStart, loopEnd, entryPoint)); AddNestedStructure(new ILStructure(method, ILStructureType.Loop, loopStart, loopEnd, entryPoint));
} }
} }
} }
SortChildren(); SortChildren();
} }
public ILStructure(ILStructureType type, int startOffset, int endOffset, ExceptionHandler handler = null) public ILStructure(Dom.MethodDefinition method, ILStructureType type, int startOffset, int endOffset, ExceptionRegion handler = default(ExceptionRegion))
{ {
Debug.Assert(startOffset < endOffset); Debug.Assert(startOffset < endOffset);
this.Method = method;
this.Type = type; this.Type = type;
this.StartOffset = startOffset; this.StartOffset = startOffset;
this.EndOffset = endOffset; this.EndOffset = endOffset;
this.ExceptionHandler = handler; this.ExceptionHandler = handler;
} }
public ILStructure(ILStructureType type, int startOffset, int endOffset, Instruction loopEntryPoint) public ILStructure(Dom.MethodDefinition method, ILStructureType type, int startOffset, int endOffset, int loopEntryPoint)
{ {
Debug.Assert(startOffset < endOffset); Debug.Assert(startOffset < endOffset);
this.Method = method;
this.Type = type; this.Type = type;
this.StartOffset = startOffset; this.StartOffset = startOffset;
this.EndOffset = endOffset; this.EndOffset = endOffset;
this.LoopEntryPoint = loopEntryPoint; this.LoopEntryPointOffset = loopEntryPoint;
} }
bool AddNestedStructure(ILStructure newStructure) bool AddNestedStructure(ILStructure newStructure)
@ -180,29 +184,68 @@ namespace ICSharpCode.Decompiler.Disassembler
return true; return true;
} }
struct Branch
{
public Interval Source;
public int Target;
public Branch(int start, int end, int target)
{
this.Source = new Interval(start, end);
this.Target = target;
}
public override string ToString()
{
return $"[Branch Source={Source}, Target={Target}]";
}
}
/// <summary> /// <summary>
/// Finds all branches. Returns list of source offset->target offset mapping. /// Finds all branches. Returns list of source offset->target offset mapping.
/// Multiple entries for the same source offset are possible (switch statements). /// Multiple entries for the same source offset are possible (switch statements).
/// The result is sorted by source offset. /// The result is sorted by source offset.
/// </summary> /// </summary>
List<KeyValuePair<Instruction, Instruction>> FindAllBranches(MethodBody body) (List<Branch> Branches, BitSet IsAfterUnconditionalBranch) FindAllBranches(BlobReader body)
{ {
var result = new List<KeyValuePair<Instruction, Instruction>>(); var result = new List<Branch>();
foreach (Instruction inst in body.Instructions) { var bitset = new BitSet(body.Length);
switch (inst.OpCode.OperandType) { body.Reset();
case OperandType.InlineBrTarget: int target;
case OperandType.ShortInlineBrTarget: while (body.RemainingBytes > 0) {
result.Add(new KeyValuePair<Instruction, Instruction>(inst, (Instruction)inst.Operand)); var offset = body.Offset;
int endOffset;
var thisOpCode = ILParser.DecodeOpCode(ref body);
switch (thisOpCode.GetOperandType()) {
case OperandType.BrTarget:
case OperandType.ShortBrTarget:
endOffset = body.Offset + thisOpCode.GetBranchOperandSize();
target = ILParser.DecodeBranchTarget(ref body, thisOpCode);
result.Add(new Branch(offset, endOffset, target));
bitset[endOffset] = IsUnconditionalBranch(thisOpCode);
break;
case OperandType.Switch:
var targets = ILParser.DecodeSwitchTargets(ref body);
foreach (int t in targets)
result.Add(new Branch(offset, offset + 4 * (targets.Length + 1), t));
break; break;
case OperandType.InlineSwitch: default:
foreach (Instruction target in (Instruction[])inst.Operand) ILParser.SkipOperand(ref body, thisOpCode);
result.Add(new KeyValuePair<Instruction, Instruction>(inst, target));
break; break;
} }
} }
// ignore the branches where Cecil doesn't decode the target return (result, bitset);
result.RemoveAll(x => x.Value == null); }
return result;
static bool IsUnconditionalBranch(ILOpCode opCode)
{
switch (opCode) {
case ILOpCode.Br:
case ILOpCode.Br_s:
return true;
default:
return false;
}
} }
void SortChildren() void SortChildren()

1290
ICSharpCode.Decompiler/Disassembler/MethodBodyDisassembler.cs

File diff suppressed because it is too large Load Diff

115
ICSharpCode.Decompiler/Disassembler/OpCodeInfo.cs

@ -19,22 +19,25 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using ICSharpCode.Decompiler.IL;
namespace ICSharpCode.Decompiler.Disassembler namespace ICSharpCode.Decompiler.Disassembler
{ {
public struct OpCodeInfo : IEquatable<OpCodeInfo> public struct OpCodeInfo : IEquatable<OpCodeInfo>
{ {
public readonly int Code; public readonly ILOpCode Code;
public readonly string Name; public readonly string Name;
string encodedName; string encodedName;
public OpCodeInfo(int code, string name) public OpCodeInfo(ILOpCode code, string name)
{ {
this.Code = code; this.Code = code;
this.Name = name; this.Name = name ?? "";
this.encodedName = null; this.encodedName = null;
} }
@ -46,6 +49,18 @@ namespace ICSharpCode.Decompiler.Disassembler
public static bool operator ==(OpCodeInfo lhs, OpCodeInfo rhs) => lhs.Equals(rhs); public static bool operator ==(OpCodeInfo lhs, OpCodeInfo rhs) => lhs.Equals(rhs);
public static bool operator !=(OpCodeInfo lhs, OpCodeInfo rhs) => !(lhs == rhs); public static bool operator !=(OpCodeInfo lhs, OpCodeInfo rhs) => !(lhs == rhs);
public override bool Equals(object obj)
{
if (obj is OpCodeInfo opCode)
return Equals(opCode);
return false;
}
public override int GetHashCode()
{
return unchecked(982451629 * Code.GetHashCode() + 982451653 * Name.GetHashCode());
}
public string Link => "http://msdn.microsoft.com/library/system.reflection.emit.opcodes." + EncodedName.ToLowerInvariant() + ".aspx"; public string Link => "http://msdn.microsoft.com/library/system.reflection.emit.opcodes." + EncodedName.ToLowerInvariant() + ".aspx";
public string EncodedName { public string EncodedName {
get { get {
@ -89,4 +104,98 @@ namespace ICSharpCode.Decompiler.Disassembler
} }
} }
} }
public static class ILParser
{
public static ILOpCode DecodeOpCode(ref BlobReader blob)
{
byte opCodeByte = blob.ReadByte();
return (ILOpCode)(opCodeByte == 0xFE ? 0xFE00 + blob.ReadByte() : opCodeByte);
}
public static void SkipOperand(ref BlobReader blob, ILOpCode opCode)
{
switch (opCode.GetOperandType()) {
// 64-bit
case OperandType.I8:
case OperandType.R:
blob.Offset += 8;
break;
// 32-bit
case OperandType.BrTarget:
case OperandType.Field:
case OperandType.Method:
case OperandType.I:
case OperandType.Sig:
case OperandType.String:
case OperandType.Tok:
case OperandType.Type:
case OperandType.ShortR:
blob.Offset += 4;
break;
// (n + 1) * 32-bit
case OperandType.Switch:
uint n = blob.ReadUInt32();
blob.Offset += (int)(n * 4);
break;
// 16-bit
case OperandType.Variable:
blob.Offset += 2;
break;
// 8-bit
case OperandType.ShortVariable:
case OperandType.ShortBrTarget:
case OperandType.ShortI:
blob.Offset++;
break;
}
}
public static int DecodeBranchTarget(ref BlobReader blob, ILOpCode opCode)
{
return (opCode.GetBranchOperandSize() == 4 ? blob.ReadInt32() : blob.ReadSByte()) + blob.Offset;
}
public static int[] DecodeSwitchTargets(ref BlobReader blob)
{
int[] targets = new int[blob.ReadUInt32()];
int offset = blob.Offset + 4 * targets.Length;
for (int i = 0; i < targets.Length; i++)
targets[i] = blob.ReadInt32() + offset;
return targets;
}
public static string DecodeUserString(ref BlobReader blob, Dom.PEFile module)
{
return module.GetMetadataReader().GetUserString(MetadataTokens.UserStringHandle(blob.ReadInt32()));
}
public static Dom.IMemberReference DecodeMemberToken(ref BlobReader blob, Dom.PEFile module)
{
var handle = MetadataTokens.EntityHandle(blob.ReadInt32());
switch (handle.Kind) {
case HandleKind.TypeDefinition:
return new Dom.TypeDefinition(module, (TypeDefinitionHandle)handle);
case HandleKind.TypeReference:
return new Dom.TypeReference(module, (TypeReferenceHandle)handle);
case HandleKind.TypeSpecification:
return new Dom.TypeSpecification(module, (TypeSpecificationHandle)handle);
case HandleKind.MethodDefinition:
return new Dom.MethodDefinition(module, (MethodDefinitionHandle)handle);
case HandleKind.MethodSpecification:
return new Dom.MethodSpecification(module, (MethodSpecificationHandle)handle);
case HandleKind.FieldDefinition:
return new Dom.FieldDefinition(module, (FieldDefinitionHandle)handle);
case HandleKind.MemberReference:
return new Dom.MemberReference(module, (MemberReferenceHandle)handle);
default:
throw new NotSupportedException();
}
}
public static bool IsReturn(this ILOpCode opCode)
{
return opCode == ILOpCode.Ret || opCode == ILOpCode.Endfilter || opCode == ILOpCode.Endfinally;
}
}
} }

607
ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs

File diff suppressed because it is too large Load Diff

1231
ICSharpCode.Decompiler/Dom/Dom.cs

File diff suppressed because it is too large Load Diff

239
ICSharpCode.Decompiler/TypeSystem/MetadataExtensions.cs → ICSharpCode.Decompiler/Dom/MetadataExtensions.cs

@ -1,17 +1,57 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Reflection.Metadata; using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335; using System.Reflection.Metadata.Ecma335;
using System.Reflection.PortableExecutable;
using System.Security.Cryptography; using System.Security.Cryptography;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.TypeSystem.Implementation;
using ICSharpCode.Decompiler.Util;
namespace ICSharpCode.Decompiler.TypeSystem namespace ICSharpCode.Decompiler
{ {
static class MetadataExtensions public static class MetadataExtensions
{ {
public static Dom.ITypeReference CoerceTypeReference(this EntityHandle handle, Dom.PEFile module)
{
if (handle.IsNil)
return null;
switch (handle.Kind) {
case HandleKind.TypeDefinition:
return new Dom.TypeDefinition(module, (TypeDefinitionHandle)handle);
case HandleKind.TypeReference:
return new Dom.TypeReference(module, (TypeReferenceHandle)handle);
case HandleKind.TypeSpecification:
return new Dom.TypeSpecification(module, (TypeSpecificationHandle)handle);
default:
throw new ArgumentException("must be either TypeDef, TypeRef or TypeSpec!", nameof(handle));
}
}
public static Dom.IMemberReference CoerceMemberReference(this EntityHandle handle, Dom.PEFile module)
{
if (handle.IsNil)
return null;
switch (handle.Kind) {
case HandleKind.MemberReference:
return new Dom.MemberReference(module, (MemberReferenceHandle)handle);
case HandleKind.MethodDefinition:
return new Dom.MethodDefinition(module, (MethodDefinitionHandle)handle);
default:
throw new ArgumentException("must be either MethodDef or MemberRef!", nameof(handle));
}
}
public static bool IsNil(this Dom.IAssemblyReference reference)
{
return reference == null || (reference is Dom.AssemblyReference ar && ar.IsNil);
}
public static string GetFullAssemblyName(this MetadataReader reader) public static string GetFullAssemblyName(this MetadataReader reader)
{ {
if (!reader.IsAssembly) if (!reader.IsAssembly)
@ -26,6 +66,20 @@ namespace ICSharpCode.Decompiler.TypeSystem
return $"{reader.GetString(asm.Name)}, Version={asm.Version}, Culture={reader.GetString(asm.Culture)}, PublicKeyToken={publicKey}"; return $"{reader.GetString(asm.Name)}, Version={asm.Version}, Culture={reader.GetString(asm.Culture)}, PublicKeyToken={publicKey}";
} }
public static string GetFullAssemblyName(this AssemblyReference reference, MetadataReader reader)
{
string publicKey = "null";
if (!reference.PublicKeyOrToken.IsNil && (reference.Flags & AssemblyFlags.PublicKey) != 0) {
SHA1 sha1 = SHA1.Create();
var publicKeyTokenBytes = sha1.ComputeHash(reader.GetBlobBytes(reference.PublicKeyOrToken)).Skip(12).ToArray();
publicKey = publicKeyTokenBytes.ToHexString();
}
string properties = "";
if ((reference.Flags & AssemblyFlags.Retargetable) != 0)
properties = ", Retargetable=true";
return $"{reader.GetString(reference.Name)}, Version={reference.Version}, Culture={reader.GetString(reference.Culture)}, PublicKeyToken={publicKey}{properties}";
}
static string ToHexString(this byte[] bytes) static string ToHexString(this byte[] bytes)
{ {
StringBuilder sb = new StringBuilder(bytes.Length * 2); StringBuilder sb = new StringBuilder(bytes.Length * 2);
@ -37,7 +91,24 @@ namespace ICSharpCode.Decompiler.TypeSystem
/// <summary> /// <summary>
/// Gets the type of the attribute. /// Gets the type of the attribute.
/// </summary> /// </summary>
/// <returns>Either <see cref="TypeDefinitionHandle"/>, <see cref="TypeReferenceHandle"/>,<see cref="TypeSpecificationHandle".</returns> public static Dom.ITypeReference GetAttributeType(this CustomAttribute attribute, Dom.PEFile module)
{
var reader = module.GetMetadataReader();
switch (attribute.Constructor.Kind) {
case HandleKind.MethodDefinition:
var md = reader.GetMethodDefinition((MethodDefinitionHandle)attribute.Constructor);
return new Dom.TypeDefinition(module, md.GetDeclaringType());
case HandleKind.MemberReference:
var mr = reader.GetMemberReference((MemberReferenceHandle)attribute.Constructor);
return mr.Parent.CoerceTypeReference(module);
default:
throw new NotSupportedException();
}
}
/// <summary>
/// Gets the type of the attribute.
/// </summary>
public static EntityHandle GetAttributeType(this CustomAttribute attribute, MetadataReader reader) public static EntityHandle GetAttributeType(this CustomAttribute attribute, MetadataReader reader)
{ {
switch (attribute.Constructor.Kind) { switch (attribute.Constructor.Kind) {
@ -52,32 +123,61 @@ namespace ICSharpCode.Decompiler.TypeSystem
} }
} }
public static IEnumerable<TypeDefinitionHandle> GetTopLevelTypeDefinitions(this MetadataReader reader)
{
var queue = new Queue<NamespaceDefinition>();
queue.Enqueue(reader.GetNamespaceDefinitionRoot());
while (queue.Count > 0) {
var ns = queue.Dequeue();
foreach (var td in ns.TypeDefinitions)
yield return td;
foreach (var nestedNS in ns.NamespaceDefinitions)
queue.Enqueue(reader.GetNamespaceDefinition(nestedNS));
}
}
public static FullTypeName GetFullTypeName(this EntityHandle handle, MetadataReader reader) public static FullTypeName GetFullTypeName(this EntityHandle handle, MetadataReader reader)
{ {
if (handle.IsNil)
throw new ArgumentNullException(nameof(handle));
switch (handle.Kind) { switch (handle.Kind) {
case HandleKind.TypeDefinition: case HandleKind.TypeDefinition:
return ((TypeDefinitionHandle)handle).GetFullTypeName(reader); return ((TypeDefinitionHandle)handle).GetFullTypeName(reader);
case HandleKind.TypeReference: case HandleKind.TypeReference:
return ((TypeReferenceHandle)handle).GetFullTypeName(reader); return ((TypeReferenceHandle)handle).GetFullTypeName(reader);
case HandleKind.TypeSpecification:
return ((TypeSpecificationHandle)handle).GetFullTypeName(reader);
default: default:
throw new NotSupportedException(); throw new NotSupportedException();
} }
} }
public static FullTypeName GetFullTypeName(this TypeReferenceHandle handle, MetadataReader reader) public static FullTypeName GetFullTypeName(this TypeSpecificationHandle handle, MetadataReader reader, bool omitGenericParamCount = false)
{
if (handle.IsNil)
throw new ArgumentNullException(nameof(handle));
var ts = reader.GetTypeSpecification(handle);
return ts.DecodeSignature(new Dom.FullTypeNameSignatureDecoder(reader), default(Unit));
}
public static FullTypeName GetFullTypeName(this TypeReferenceHandle handle, MetadataReader reader, bool omitGenericParamCount = false)
{ {
if (handle.IsNil)
throw new ArgumentNullException(nameof(handle));
var tr = reader.GetTypeReference(handle); var tr = reader.GetTypeReference(handle);
TypeReferenceHandle declaringTypeHandle; TypeReferenceHandle declaringTypeHandle;
if ((declaringTypeHandle = tr.GetDeclaringType()).IsNil) { if ((declaringTypeHandle = tr.GetDeclaringType()).IsNil) {
string @namespace = tr.Namespace.IsNil ? "" : reader.GetString(tr.Namespace); string @namespace = tr.Namespace.IsNil ? "" : reader.GetString(tr.Namespace);
return new FullTypeName(new TopLevelTypeName(@namespace, reader.GetString(tr.Name))); return new FullTypeName(new TopLevelTypeName(@namespace, reader.GetString(tr.Name)));
} else { } else {
return declaringTypeHandle.GetFullTypeName(reader).NestedType(reader.GetString(tr.Name), 0); return declaringTypeHandle.GetFullTypeName(reader, omitGenericParamCount).NestedType(reader.GetString(tr.Name), 0);
} }
} }
public static FullTypeName GetFullTypeName(this TypeDefinitionHandle handle, MetadataReader reader) public static FullTypeName GetFullTypeName(this TypeDefinitionHandle handle, MetadataReader reader)
{ {
if (handle.IsNil)
throw new ArgumentNullException(nameof(handle));
return reader.GetTypeDefinition(handle).GetFullTypeName(reader); return reader.GetTypeDefinition(handle).GetFullTypeName(reader);
} }
@ -86,9 +186,21 @@ namespace ICSharpCode.Decompiler.TypeSystem
TypeDefinitionHandle declaringTypeHandle; TypeDefinitionHandle declaringTypeHandle;
if ((declaringTypeHandle = td.GetDeclaringType()).IsNil) { if ((declaringTypeHandle = td.GetDeclaringType()).IsNil) {
string @namespace = td.Namespace.IsNil ? "" : reader.GetString(td.Namespace); string @namespace = td.Namespace.IsNil ? "" : reader.GetString(td.Namespace);
return new FullTypeName(new TopLevelTypeName(@namespace, reader.GetString(td.Name), td.GetGenericParameters().Count)); return new FullTypeName(new TopLevelTypeName(@namespace, reader.GetString(td.Name)));
} else {
return declaringTypeHandle.GetFullTypeName(reader).NestedType(reader.GetString(td.Name), 0);
}
}
public static string ToILNameString(this FullTypeName typeName)
{
var escapedName = Disassembler.DisassemblerHelpers.Escape(typeName.Name);
if (typeName.IsNested) {
return $"{typeName.GetDeclaringType().ToILNameString()}/{escapedName}";
} else if (!string.IsNullOrEmpty(typeName.TopLevelTypeName.Namespace)) {
return $"{typeName.TopLevelTypeName.Namespace}.{escapedName}";
} else { } else {
return declaringTypeHandle.GetFullTypeName(reader).NestedType(reader.GetString(td.Name), td.GetGenericParameters().Count); return $"{escapedName}";
} }
} }
@ -115,23 +227,6 @@ namespace ICSharpCode.Decompiler.TypeSystem
} }
} }
public unsafe static MethodSemanticsAttributes GetMethodSemanticsAttributes(this MethodDefinitionHandle handle, MetadataReader reader)
{
byte* startPointer = reader.MetadataPointer;
int offset = reader.GetTableMetadataOffset(TableIndex.MethodSemantics);
int rowSize = reader.GetTableRowSize(TableIndex.MethodSemantics);
int rowCount = reader.GetTableRowCount(TableIndex.MethodSemantics);
int token = reader.GetToken(handle);
for (int row = rowCount - 1; row >= 0; row--) {
byte* ptr = startPointer + offset + rowSize * row;
ushort methodToken = *(ptr + 2);
if (token == methodToken) {
return (MethodSemanticsAttributes)(*ptr);
}
}
return 0;
}
public static bool IsValueType(this TypeDefinition typeDefinition, MetadataReader reader) public static bool IsValueType(this TypeDefinition typeDefinition, MetadataReader reader)
{ {
if (typeDefinition.BaseType.IsNil) if (typeDefinition.BaseType.IsNil)
@ -157,6 +252,32 @@ namespace ICSharpCode.Decompiler.TypeSystem
return typeDefinition.BaseType.GetFullTypeName(reader).ToString() == "System.Enum"; return typeDefinition.BaseType.GetFullTypeName(reader).ToString() == "System.Enum";
} }
public static string GetDefaultMemberName(this TypeDefinitionHandle type, MetadataReader reader)
{
return type.GetDefaultMemberName(reader, out var attr);
}
static readonly ITypeResolveContext minimalCorlibContext = new SimpleTypeResolveContext(MinimalCorlib.Instance.CreateCompilation());
public static string GetDefaultMemberName(this TypeDefinitionHandle type, MetadataReader reader, out CustomAttributeHandle defaultMemberAttribute)
{
var td = reader.GetTypeDefinition(type);
foreach (var h in td.GetCustomAttributes()) {
var ca = reader.GetCustomAttribute(h);
if (ca.GetAttributeType(reader).ToString() == "System.Reflection.DefaultMemberAttribute") {
var decodedValues = ca.DecodeValue(new TypeSystemAttributeTypeProvider(minimalCorlibContext));
if (decodedValues.FixedArguments.Length == 1 && decodedValues.FixedArguments[0].Value is string value) {
defaultMemberAttribute = h;
return value;
}
}
}
defaultMemberAttribute = default(CustomAttributeHandle);
return null;
}
public static bool HasOverrides(this MethodDefinitionHandle handle, MetadataReader reader) public static bool HasOverrides(this MethodDefinitionHandle handle, MetadataReader reader)
{ {
for (int row = 1; row <= reader.GetTableRowCount(TableIndex.MethodImpl); row++) { for (int row = 1; row <= reader.GetTableRowCount(TableIndex.MethodImpl); row++) {
@ -267,5 +388,75 @@ namespace ICSharpCode.Decompiler.TypeSystem
return KnownTypeCode.None; return KnownTypeCode.None;
} }
} }
public static bool IsSmallReference(this MetadataReader reader, TableIndex table)
{
// TODO detect whether #JTD is present (EnC)
return reader.GetTableRowCount(table) <= ushort.MaxValue;
}
public static int GetReferenceSize(this MetadataReader reader, TableIndex table)
{
return IsSmallReference(reader, table) ? 2 : 4;
}
public static unsafe (int startRow, int endRow) BinarySearchRange(this MetadataReader reader, TableIndex table, int valueOffset, uint referenceValue, bool small)
{
int offset = reader.GetTableMetadataOffset(table);
int rowSize = reader.GetTableRowSize(table);
int rowCount = reader.GetTableRowCount(table);
int tableLength = rowSize * rowCount;
byte* startPointer = reader.MetadataPointer;
int result = BinarySearch();
if (result == -1)
return (-1, -1);
int start = result;
while (start > 0 && GetValue(start - 1) == referenceValue)
start--;
int end = result;
while (end + 1 < tableLength && GetValue(end + 1) == referenceValue)
end++;
return (start, end);
uint GetValue(int row)
{
if (small)
return *(ushort*)(startPointer + offset + row * rowSize + valueOffset);
else
return *(uint*)(startPointer + offset + row * rowSize + valueOffset);
}
int BinarySearch()
{
int startRow = 0;
int endRow = rowCount - 1;
while (startRow <= endRow) {
int row = (startRow + endRow) / 2;
uint currentValue = GetValue(row);
if (referenceValue > currentValue) {
startRow = row + 1;
} else if (referenceValue < currentValue) {
endRow = row - 1;
} else {
return row;
}
}
return -1;
}
}
public static AssemblyDefinition? GetAssemblyDefinition(this PEReader reader)
{
var metadata = reader.GetMetadataReader();
if (metadata.IsAssembly)
return metadata.GetAssemblyDefinition();
return null;
}
} }
} }

230
ICSharpCode.Decompiler/Dom/MetadataResolver.cs

@ -0,0 +1,230 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using System.Reflection.PortableExecutable;
using System.Text;
using System.Threading.Tasks;
using ICSharpCode.Decompiler.Util;
namespace ICSharpCode.Decompiler.Dom
{
public interface IMetadataResolveContext
{
PEFile CurrentModule { get; }
PEFile ResolveAssembly(IAssemblyReference reference);
}
public class SimpleMetadataResolveContext : IMetadataResolveContext
{
readonly PEFile mainModule;
readonly IAssemblyResolver assemblyResolver;
readonly Dictionary<IAssemblyReference, PEFile> loadedModules = new Dictionary<IAssemblyReference, PEFile>();
public SimpleMetadataResolveContext(PEFile mainModule)
{
this.mainModule = mainModule;
this.assemblyResolver = mainModule.AssemblyResolver;
}
public PEFile CurrentModule => mainModule;
public PEFile ResolveAssembly(IAssemblyReference reference)
{
if (loadedModules.TryGetValue(reference, out var module))
return module;
var resolved = assemblyResolver.Resolve(reference);
loadedModules.Add(reference, resolved);
return resolved;
}
}
public static class MetadataResolver
{
/// <summary>
/// Implements resolving of TypeReferences to TypeDefinitions as decribed in II.7.3 of ECMA-335 6th edition.
/// </summary>
public static TypeDefinition Resolve(TypeReferenceHandle handle, IMetadataResolveContext context)
{
var metadata = context.CurrentModule.GetMetadataReader();
var tr = metadata.GetTypeReference(handle);
if (tr.ResolutionScope.IsNil) {
foreach (var h in metadata.ExportedTypes) {
var exportedType = metadata.GetExportedType(h);
if (exportedType.Name == tr.Name && exportedType.Namespace == tr.Namespace) {
// TODO
}
}
}
switch (tr.ResolutionScope.Kind) {
case HandleKind.TypeReference:
//return Resolve((TypeReferenceHandle)tr.ResolutionScope, context).GetNestedType(new );
break;
case HandleKind.ModuleReference:
break;
case HandleKind.AssemblyReference:
var module = context.ResolveAssembly(new AssemblyReference(context.CurrentModule, (AssemblyReferenceHandle)tr.ResolutionScope));
var moduleMetadata = module.GetMetadataReader();
var @namespace = ResolveNamespace(moduleMetadata, metadata.GetString(tr.Namespace).Split('.'));
if (@namespace == null)
throw new NotSupportedException();
var type = FindTypeInNamespace(moduleMetadata, @namespace.Value, metadata.GetString(tr.Name));
if (type.IsNil)
throw new NotSupportedException();
return new TypeDefinition(module, type);
}
throw new NotSupportedException();
}
static NamespaceDefinition? ResolveNamespace(MetadataReader metadata, string[] namespaceParts)
{
var currentNamespace = metadata.GetNamespaceDefinitionRoot();
for (int i = 0; i < namespaceParts.Length; i++) {
string identifier = namespaceParts[i];
var next = currentNamespace.NamespaceDefinitions.FirstOrDefault(ns => metadata.GetString(metadata.GetNamespaceDefinition(ns).Name) == identifier);
if (next.IsNil)
return null;
currentNamespace = metadata.GetNamespaceDefinition(next);
}
return currentNamespace;
}
static TypeDefinitionHandle FindTypeInNamespace(MetadataReader metadata, NamespaceDefinition @namespace, string name)
{
foreach (var type in @namespace.TypeDefinitions) {
var typeName = metadata.GetString(metadata.GetTypeDefinition(type).Name);
if (name == typeName)
return type;
}
return default(TypeDefinitionHandle);
}
public static IMemberDefinition Resolve(MemberReferenceHandle handle, IMetadataResolveContext context)
{
var metadata = context.CurrentModule.GetMetadataReader();
var mr = metadata.GetMemberReference(handle);
TypeDefinition declaringType;
switch (mr.Parent.Kind) {
case HandleKind.TypeDefinition:
declaringType = new TypeDefinition(context.CurrentModule, (TypeDefinitionHandle)mr.Parent);
break;
case HandleKind.TypeReference:
declaringType = Resolve((TypeReferenceHandle)mr.Parent, context);
break;
case HandleKind.TypeSpecification:
case HandleKind.MethodDefinition:
case HandleKind.ModuleReference:
throw new NotImplementedException();
default:
throw new NotSupportedException();
}
var name = metadata.GetString(mr.Name);
switch (mr.GetKind()) {
case MemberReferenceKind.Field:
return declaringType.Fields.FirstOrDefault(fd => fd.Name == name);
case MemberReferenceKind.Method:
var signature = mr.DecodeMethodSignature(new TypeSystem.Implementation.TypeReferenceSignatureDecoder(), default(Unit));
return declaringType.Methods.SingleOrDefault(md => MatchMethodDefinition(name, signature, md));
}
throw new NotSupportedException();
}
static bool MatchMethodDefinition(string name, MethodSignature<TypeSystem.ITypeReference> signature, MethodDefinition md)
{
if (name != md.Name || md.GenericParameters.Count != signature.GenericParameterCount || signature.RequiredParameterCount != md.Parameters.Count)
return false;
// TODO overload resolution... OMG
return true;
}
public static TypeDefinition Resolve(TypeSpecificationHandle handle, IMetadataResolveContext context)
{
var metadata = context.CurrentModule.GetMetadataReader();
var ts = metadata.GetTypeSpecification(handle);
var unspecialized = ts.DecodeSignature(new Unspecializer(), default(Unit));
switch (unspecialized.Kind) {
case HandleKind.TypeDefinition:
return new TypeDefinition(context.CurrentModule, (TypeDefinitionHandle)unspecialized);
case HandleKind.TypeReference:
return Resolve((TypeReferenceHandle)unspecialized, context);
default:
throw new NotImplementedException();
}
}
class Unspecializer : ISignatureTypeProvider<EntityHandle, Unit>
{
public EntityHandle GetArrayType(EntityHandle elementType, ArrayShape shape)
{
return elementType;
}
public EntityHandle GetByReferenceType(EntityHandle elementType)
{
return elementType;
}
public EntityHandle GetFunctionPointerType(MethodSignature<EntityHandle> signature)
{
throw new NotImplementedException();
}
public EntityHandle GetGenericInstantiation(EntityHandle genericType, ImmutableArray<EntityHandle> typeArguments)
{
return genericType;
}
public EntityHandle GetGenericMethodParameter(Unit genericContext, int index)
{
return MetadataTokens.EntityHandle(0);
}
public EntityHandle GetGenericTypeParameter(Unit genericContext, int index)
{
return MetadataTokens.EntityHandle(0);
}
public EntityHandle GetModifiedType(EntityHandle modifier, EntityHandle unmodifiedType, bool isRequired)
{
return unmodifiedType;
}
public EntityHandle GetPinnedType(EntityHandle elementType)
{
return elementType;
}
public EntityHandle GetPointerType(EntityHandle elementType)
{
return elementType;
}
public EntityHandle GetPrimitiveType(PrimitiveTypeCode typeCode)
{
throw new NotImplementedException();
}
public EntityHandle GetSZArrayType(EntityHandle elementType)
{
throw new NotImplementedException();
}
public EntityHandle GetTypeFromDefinition(MetadataReader reader, TypeDefinitionHandle handle, byte rawTypeKind)
{
return handle;
}
public EntityHandle GetTypeFromReference(MetadataReader reader, TypeReferenceHandle handle, byte rawTypeKind)
{
return handle;
}
public EntityHandle GetTypeFromSpecification(MetadataReader reader, Unit genericContext, TypeSpecificationHandle handle, byte rawTypeKind)
{
return reader.GetTypeSpecification(handle).DecodeSignature(this, genericContext);
}
}
}
}

92
ICSharpCode.Decompiler/Dom/SequencePoint.cs

@ -0,0 +1,92 @@
using System;
using System.Collections.Generic;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using System.Text;
namespace ICSharpCode.Decompiler.Dom
{
using SRMDocument = System.Reflection.Metadata.Document;
/// <summary>
/// A sequence point read from a PDB file or produced by the decompiler.
/// </summary>
public struct SequencePoint
{
/// <summary>
/// IL start offset.
/// </summary>
public int Offset { get; set; }
/// <summary>
/// IL end offset.
/// </summary>
/// <remarks>
/// This does not get stored in debug information;
/// it is used internally to create hidden sequence points
/// for the IL fragments not covered by any sequence point.
/// </remarks>
public int EndOffset { get; set; }
public int StartLine { get; set; }
public int StartColumn { get; set; }
public int EndLine { get; set; }
public int EndColumn { get; set; }
public bool IsHidden {
get { return StartLine == 0xfeefee && StartLine == EndLine; }
}
public Document Document { get; set; }
internal void SetHidden()
{
StartLine = EndLine = 0xfeefee;
}
}
public struct Document : IEquatable<Document>
{
public PEFile Module { get; }
public DocumentHandle Handle { get; }
public bool IsNil => Handle.IsNil;
public Document(PEFile module, DocumentHandle handle) : this()
{
this.Module = module ?? throw new ArgumentNullException(nameof(module));
this.Handle = handle;
}
SRMDocument This() => Module.GetMetadataReader().GetDocument(Handle);
public bool Equals(Document other)
{
return Module == other.Module && Handle == other.Handle;
}
public override bool Equals(object obj)
{
if (obj is Document md)
return Equals(md);
return false;
}
public override int GetHashCode()
{
return unchecked(982451629 * Module.GetHashCode() + 982451653 * MetadataTokens.GetToken(Handle));
}
public static bool operator ==(Document lhs, Document rhs) => lhs.Equals(rhs);
public static bool operator !=(Document lhs, Document rhs) => !lhs.Equals(rhs);
public string Url {
get {
if (Handle.IsNil)
return null;
var h = This().Name;
if (h.IsNil) return null;
return Module.GetMetadataReader().GetString(h);
}
}
}
}

6
ICSharpCode.Decompiler/DotNetCore/DotNetCorePathFinder.cs

@ -5,8 +5,8 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text; using System.Text;
using ICSharpCode.Decompiler.Dom;
using LightJson.Serialization; using LightJson.Serialization;
using Mono.Cecil;
namespace ICSharpCode.Decompiler namespace ICSharpCode.Decompiler
{ {
@ -70,7 +70,7 @@ namespace ICSharpCode.Decompiler
} }
} }
public string TryResolveDotNetCore(AssemblyNameReference name) public string TryResolveDotNetCore(IAssemblyReference name)
{ {
foreach (var basePath in packageBasePaths) { foreach (var basePath in packageBasePaths) {
if (File.Exists(Path.Combine(basePath, name.Name + ".dll"))) { if (File.Exists(Path.Combine(basePath, name.Name + ".dll"))) {
@ -106,7 +106,7 @@ namespace ICSharpCode.Decompiler
} }
} }
string FallbackToDotNetSharedDirectory(AssemblyNameReference name, Version version) string FallbackToDotNetSharedDirectory(IAssemblyReference name, Version version)
{ {
if (dotnetBasePath == null) return null; if (dotnetBasePath == null) return null;
var basePath = Path.Combine(dotnetBasePath, "shared", "Microsoft.NETCore.App"); var basePath = Path.Combine(dotnetBasePath, "shared", "Microsoft.NETCore.App");

16
ICSharpCode.Decompiler/DotNetCore/DotNetCorePathFinderExtensions.cs

@ -1,26 +1,28 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using ICSharpCode.Decompiler.TypeSystem.Implementation; using System.Reflection.Metadata;
using Mono.Cecil; using System.Reflection.PortableExecutable;
namespace ICSharpCode.Decompiler namespace ICSharpCode.Decompiler
{ {
public static class DotNetCorePathFinderExtensions public static class DotNetCorePathFinderExtensions
{ {
public static string DetectTargetFrameworkId(this AssemblyDefinition assembly) public static string DetectTargetFrameworkId(this PEReader assembly)
{ {
if (assembly == null) if (assembly == null)
throw new ArgumentNullException(nameof(assembly)); throw new ArgumentNullException(nameof(assembly));
const string TargetFrameworkAttributeName = "System.Runtime.Versioning.TargetFrameworkAttribute"; const string TargetFrameworkAttributeName = "System.Runtime.Versioning.TargetFrameworkAttribute";
var reader = assembly.GetMetadataReader();
foreach (var attribute in assembly.CustomAttributes) { foreach (var h in reader.GetCustomAttributes(Handle.AssemblyDefinition)) {
if (attribute.AttributeType.FullName != TargetFrameworkAttributeName) var attribute = reader.GetCustomAttribute(h);
if (attribute.GetAttributeType(reader).ToString() != TargetFrameworkAttributeName)
continue; continue;
var blobReader = new BlobReader(attribute.GetBlob(), null); var blobReader = reader.GetBlobReader(attribute.Value);
if (blobReader.ReadUInt16() == 0x0001) { if (blobReader.ReadUInt16() == 0x0001) {
return blobReader.ReadSerString(); return blobReader.ReadSerializedString();
} }
} }

66
ICSharpCode.Decompiler/DotNetCore/UniversalAssemblyResolver.cs

@ -1,9 +1,10 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Reflection.PortableExecutable;
using System.Text; using System.Text;
using ICSharpCode.Decompiler.Dom;
using ICSharpCode.Decompiler.Util; using ICSharpCode.Decompiler.Util;
using Mono.Cecil;
namespace ICSharpCode.Decompiler namespace ICSharpCode.Decompiler
{ {
@ -58,26 +59,18 @@ namespace ICSharpCode.Decompiler
AddSearchDirectory(baseDirectory); AddSearchDirectory(baseDirectory);
} }
public static ModuleDefinition LoadMainModule(string mainAssemblyFileName, bool throwOnError = true, bool inMemory = false) public static PEFile LoadMainModule(string mainAssemblyFileName, bool throwOnError = true, bool inMemory = false)
{ {
var resolver = new UniversalAssemblyResolver(mainAssemblyFileName, throwOnError); var resolver = new UniversalAssemblyResolver(mainAssemblyFileName, throwOnError);
var module = ModuleDefinition.ReadModule(mainAssemblyFileName, new ReaderParameters { var module = new PEReader(new FileStream(mainAssemblyFileName, FileMode.Open));
AssemblyResolver = resolver,
InMemory = inMemory
});
resolver.TargetFramework = module.Assembly.DetectTargetFrameworkId(); resolver.TargetFramework = module.DetectTargetFrameworkId();
return module; return new PEFile(mainAssemblyFileName, module, resolver);
} }
public AssemblyDefinition Resolve(AssemblyNameReference name) public PEFile Resolve(IAssemblyReference name)
{
return Resolve(name, new ReaderParameters());
}
public AssemblyDefinition Resolve(AssemblyNameReference name, ReaderParameters parameters)
{ {
var file = FindAssemblyFile(name); var file = FindAssemblyFile(name);
if (file == null) { if (file == null) {
@ -85,10 +78,10 @@ namespace ICSharpCode.Decompiler
throw new AssemblyResolutionException(name); throw new AssemblyResolutionException(name);
return null; return null;
} }
return GetAssembly(file, parameters); return new PEFile(file, GetAssembly(file), this);
} }
public string FindAssemblyFile(AssemblyNameReference name) public string FindAssemblyFile(IAssemblyReference name)
{ {
var targetFramework = TargetFramework.Split(new[] { ",Version=v" }, StringSplitOptions.None); var targetFramework = TargetFramework.Split(new[] { ",Version=v" }, StringSplitOptions.None);
string file = null; string file = null;
@ -110,28 +103,21 @@ namespace ICSharpCode.Decompiler
} }
} }
string ResolveInternal(AssemblyNameReference name) string ResolveInternal(IAssemblyReference name)
{ {
if (name == null) if (name.IsNil())
throw new ArgumentNullException(nameof(name)); throw new ArgumentNullException(nameof(name));
var assembly = SearchDirectory(name, directories); var assembly = SearchDirectory(name, directories);
if (assembly != null) if (assembly != null)
return assembly; return assembly;
if (name.IsRetargetable) {
// if the reference is retargetable, zero it
name = new AssemblyNameReference(name.Name, ZeroVersion) {
PublicKeyToken = Empty<byte>.Array,
};
}
var framework_dir = Path.GetDirectoryName(typeof(object).Module.FullyQualifiedName); var framework_dir = Path.GetDirectoryName(typeof(object).Module.FullyQualifiedName);
var framework_dirs = DetectMono() var framework_dirs = DetectMono()
? new[] { framework_dir, Path.Combine(framework_dir, "Facades") } ? new[] { framework_dir, Path.Combine(framework_dir, "Facades") }
: new[] { framework_dir }; : new[] { framework_dir };
if (IsZero(name.Version)) { if (IsZeroVersionOrRetargetable(name)) {
assembly = SearchDirectory(name, framework_dirs); assembly = SearchDirectory(name, framework_dirs);
if (assembly != null) if (assembly != null)
return assembly; return assembly;
@ -157,7 +143,7 @@ namespace ICSharpCode.Decompiler
} }
#region .NET / mono GAC handling #region .NET / mono GAC handling
string SearchDirectory(AssemblyNameReference name, IEnumerable<string> directories) string SearchDirectory(IAssemblyReference name, IEnumerable<string> directories)
{ {
var extensions = name.IsWindowsRuntime ? new[] { ".winmd", ".dll" } : new[] { ".exe", ".dll" }; var extensions = name.IsWindowsRuntime ? new[] { ".winmd", ".dll" } : new[] { ".exe", ".dll" };
foreach (var directory in directories) { foreach (var directory in directories) {
@ -176,19 +162,22 @@ namespace ICSharpCode.Decompiler
return null; return null;
} }
static bool IsZeroVersionOrRetargetable(IAssemblyReference reference)
{
return IsZero(reference.Version) || reference.IsRetargetable;
}
static bool IsZero(Version version) static bool IsZero(Version version)
{ {
return version.Major == 0 && version.Minor == 0 && version.Build == 0 && version.Revision == 0; return version.Major == 0 && version.Minor == 0 && version.Build == 0 && version.Revision == 0;
} }
static Version ZeroVersion = new Version(0, 0, 0, 0); string GetCorlib(IAssemblyReference reference)
string GetCorlib(AssemblyNameReference reference)
{ {
var version = reference.Version; var version = reference.Version;
var corlib = typeof(object).Assembly.GetName(); var corlib = typeof(object).Assembly.GetName();
if (corlib.Version == version || IsZero(version)) if (corlib.Version == version || IsZeroVersionOrRetargetable(reference))
return typeof(object).Module.FullyQualifiedName; return typeof(object).Module.FullyQualifiedName;
var path = Directory.GetParent( var path = Directory.GetParent(
@ -286,15 +275,12 @@ namespace ICSharpCode.Decompiler
"gac"); "gac");
} }
AssemblyDefinition GetAssembly(string file, ReaderParameters parameters) PEReader GetAssembly(string file)
{ {
if (parameters.AssemblyResolver == null) return new PEReader(new FileStream(file, FileMode.Open));
parameters.AssemblyResolver = this;
return ModuleDefinition.ReadModule(file, parameters).Assembly;
} }
string GetAssemblyInGac(AssemblyNameReference reference) string GetAssemblyInGac(IAssemblyReference reference)
{ {
if (reference.PublicKeyToken == null || reference.PublicKeyToken.Length == 0) if (reference.PublicKeyToken == null || reference.PublicKeyToken.Length == 0)
return null; return null;
@ -305,7 +291,7 @@ namespace ICSharpCode.Decompiler
return GetAssemblyInNetGac(reference); return GetAssemblyInNetGac(reference);
} }
string GetAssemblyInMonoGac(AssemblyNameReference reference) string GetAssemblyInMonoGac(IAssemblyReference reference)
{ {
for (int i = 0; i < gac_paths.Count; i++) { for (int i = 0; i < gac_paths.Count; i++) {
var gac_path = gac_paths[i]; var gac_path = gac_paths[i];
@ -317,7 +303,7 @@ namespace ICSharpCode.Decompiler
return null; return null;
} }
string GetAssemblyInNetGac(AssemblyNameReference reference) string GetAssemblyInNetGac(IAssemblyReference reference)
{ {
var gacs = new[] { "GAC_MSIL", "GAC_32", "GAC_64", "GAC" }; var gacs = new[] { "GAC_MSIL", "GAC_32", "GAC_64", "GAC" };
var prefixes = new[] { string.Empty, "v4.0_" }; var prefixes = new[] { string.Empty, "v4.0_" };
@ -334,7 +320,7 @@ namespace ICSharpCode.Decompiler
return null; return null;
} }
static string GetAssemblyFile(AssemblyNameReference reference, string prefix, string gac) static string GetAssemblyFile(IAssemblyReference reference, string prefix, string gac)
{ {
var gac_folder = new StringBuilder() var gac_folder = new StringBuilder()
.Append(prefix) .Append(prefix)

8
ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj

@ -268,6 +268,8 @@
<Compile Include="CSharp\Transforms\ReplaceMethodCallsWithOperators.cs" /> <Compile Include="CSharp\Transforms\ReplaceMethodCallsWithOperators.cs" />
<Compile Include="CSharp\WholeProjectDecompiler.cs" /> <Compile Include="CSharp\WholeProjectDecompiler.cs" />
<Compile Include="CSharp\Transforms\AddXmlDocumentationTransform.cs" /> <Compile Include="CSharp\Transforms\AddXmlDocumentationTransform.cs" />
<Compile Include="Disassembler\BlobDecoder.cs" />
<Compile Include="Disassembler\DomExtensions.cs" />
<Compile Include="Disassembler\OpCodeInfo.cs" /> <Compile Include="Disassembler\OpCodeInfo.cs" />
<Compile Include="Documentation\GetPotentiallyNestedClassTypeReference.cs" /> <Compile Include="Documentation\GetPotentiallyNestedClassTypeReference.cs" />
<Compile Include="Documentation\IdStringMemberReference.cs" /> <Compile Include="Documentation\IdStringMemberReference.cs" />
@ -275,6 +277,8 @@
<Compile Include="Documentation\XmlDocKeyProvider.cs" /> <Compile Include="Documentation\XmlDocKeyProvider.cs" />
<Compile Include="Documentation\XmlDocLoader.cs" /> <Compile Include="Documentation\XmlDocLoader.cs" />
<Compile Include="Documentation\XmlDocumentationProvider.cs" /> <Compile Include="Documentation\XmlDocumentationProvider.cs" />
<Compile Include="Dom\Dom.cs" />
<Compile Include="Dom\MetadataResolver.cs" />
<Compile Include="DotNetCore\DotNetCorePathFinder.cs" /> <Compile Include="DotNetCore\DotNetCorePathFinder.cs" />
<Compile Include="DotNetCore\DotNetCorePathFinderExtensions.cs" /> <Compile Include="DotNetCore\DotNetCorePathFinderExtensions.cs" />
<Compile Include="DotNetCore\LightJson\JsonArray.cs" /> <Compile Include="DotNetCore\LightJson\JsonArray.cs" />
@ -292,7 +296,7 @@
<Compile Include="IL\ILAstWritingOptions.cs" /> <Compile Include="IL\ILAstWritingOptions.cs" />
<Compile Include="IL\Instructions\LdFlda.cs" /> <Compile Include="IL\Instructions\LdFlda.cs" />
<Compile Include="IL\Instructions\StLoc.cs" /> <Compile Include="IL\Instructions\StLoc.cs" />
<Compile Include="IL\SequencePoint.cs" /> <Compile Include="Dom\SequencePoint.cs" />
<Compile Include="IL\Instructions\CallIndirect.cs" /> <Compile Include="IL\Instructions\CallIndirect.cs" />
<Compile Include="IL\Instructions\DefaultValue.cs" /> <Compile Include="IL\Instructions\DefaultValue.cs" />
<Compile Include="IL\Transforms\EarlyExpressionTransforms.cs" /> <Compile Include="IL\Transforms\EarlyExpressionTransforms.cs" />
@ -326,7 +330,7 @@
<Compile Include="IL\Transforms\TransformCollectionAndObjectInitializers.cs" /> <Compile Include="IL\Transforms\TransformCollectionAndObjectInitializers.cs" />
<Compile Include="Output\TextTokenWriter.cs" /> <Compile Include="Output\TextTokenWriter.cs" />
<Compile Include="TypeSystem\Implementation\TypeSpecification.cs" /> <Compile Include="TypeSystem\Implementation\TypeSpecification.cs" />
<Compile Include="TypeSystem\MetadataExtensions.cs" /> <Compile Include="Dom\MetadataExtensions.cs" />
<Compile Include="Util\GraphVizGraph.cs" /> <Compile Include="Util\GraphVizGraph.cs" />
<Compile Include="Util\KeyComparer.cs" /> <Compile Include="Util\KeyComparer.cs" />
<Compile Include="Util\LongDict.cs" /> <Compile Include="Util\LongDict.cs" />

335
ICSharpCode.Decompiler/IL/ILOpCodes.cs

File diff suppressed because one or more lines are too long

132
ICSharpCode.Decompiler/IL/ILOpCodes.tt

@ -21,40 +21,148 @@
<#@ import namespace="System.Linq" #> <#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #> <#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #> <#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.Reflection.Metadata" #>
<#@ import namespace="System.Reflection.Emit" #> <#@ import namespace="System.Reflection.Emit" #>
<#@ output extension=".cs" #> <#@ output extension=".cs" #>
using System; using System;
using System.Reflection.Emit; using System.Collections.Generic;
using System.Reflection.Metadata;
<# <#
var operandTypes = new OperandType[0x11f]; var operandTypes = Enumerable.Repeat((OperandType)0xff, 0x11f).ToArray();
var operandNames = new string[0x11f];
#> #>
namespace ICSharpCode.Decompiler.IL namespace ICSharpCode.Decompiler.IL
{ {
enum ILOpCode : ushort /// <summary>Describes the operand type of Microsoft intermediate language (MSIL) instruction.</summary>
public enum OperandType
{ {
<# foreach (var field in typeof(OpCodes).GetFields()) { /// <summary>The operand is a 32-bit integer branch target.</summary>
var opCode = (OpCode)field.GetValue(null); BrTarget,
ushort val = (ushort)(((opCode.Value & 0x200) >> 1) | (opCode.Value & 0xff)); /// <summary>The operand is a 32-bit metadata token.</summary>
operandTypes[val] = opCode.OperandType; Field,
#> /// <summary>The operand is a 32-bit integer.</summary>
<#=field.Name#> = 0x<#=val.ToString("x2")#>, I,
<# } // end foreach #> /// <summary>The operand is a 64-bit integer.</summary>
I8,
/// <summary>The operand is a 32-bit metadata token.</summary>
Method,
/// <summary>No operand.</summary>
None,
/// <summary>The operand is reserved and should not be used.</summary>
[Obsolete("This API has been deprecated. http://go.microsoft.com/fwlink/?linkid=14202")]
Phi,
/// <summary>The operand is a 64-bit IEEE floating point number.</summary>
R,
/// <summary>The operand is a 32-bit metadata signature token.</summary>
Sig = 9,
/// <summary>The operand is a 32-bit metadata string token.</summary>
String,
/// <summary>The operand is the 32-bit integer argument to a switch instruction.</summary>
Switch,
/// <summary>The operand is a <see langword="FieldRef" />, <see langword="MethodRef" />, or <see langword="TypeRef" /> token.</summary>
Tok,
/// <summary>The operand is a 32-bit metadata token.</summary>
Type,
/// <summary>The operand is 16-bit integer containing the ordinal of a local variable or an argument.</summary>
Variable,
/// <summary>The operand is an 8-bit integer branch target.</summary>
ShortBrTarget,
/// <summary>The operand is an 8-bit integer.</summary>
ShortI,
/// <summary>The operand is a 32-bit IEEE floating point number.</summary>
ShortR,
/// <summary>The operand is an 8-bit integer containing the ordinal of a local variable or an argumenta.</summary>
ShortVariable
} }
<#
foreach (var field in typeof(OpCodes).GetFields()) {
var opCode = (OpCode)field.GetValue(null);
ushort index = (ushort)(((opCode.Value & 0x200) >> 1) | (opCode.Value & 0xff));
operandTypes[index] = opCode.OperandType;
operandNames[index] = opCode.Name;
} #>
static class ILOpCodeExtensions static class ILOpCodeExtensions
{ {
// We use a byte array instead of an enum array because it can be initialized more efficiently // We use a byte array instead of an enum array because it can be initialized more efficiently
static readonly byte[] operandTypes = { <# static readonly byte[] operandTypes = { <#
foreach (var operandType in operandTypes) { foreach (var operandType in operandTypes) {
if ((byte)operandType == 255) {
Write("255, ");
} else {
string operandTypeName = operandType.ToString().Replace("Inline", "").Replace("Var", "Variable"); string operandTypeName = operandType.ToString().Replace("Inline", "").Replace("Var", "Variable");
Write("(byte)OperandType." + operandTypeName + ", "); Write("(byte)OperandType." + operandTypeName + ", ");
} }
}
#> };
static readonly string[] operandNames = { <#
foreach (var operandName in operandNames) {
Write("\"" + operandName + "\", ");
}
#> }; #> };
public static OperandType GetOperandType(this ILOpCode opCode) public static OperandType GetOperandType(this ILOpCode opCode)
{ {
return (OperandType)operandTypes[(ushort)opCode]; ushort index = (ushort)((((int)opCode & 0x200) >> 1) | ((int)opCode & 0xff));
if (index >= operandTypes.Length)
return (OperandType)255;
return (OperandType)operandTypes[index];
}
public static string GetDisplayName(this ILOpCode opCode)
{
ushort index = (ushort)((((int)opCode & 0x200) >> 1) | ((int)opCode & 0xff));
if (index >= operandNames.Length)
return "";
return operandNames[index];
}
public static bool IsDefined(this ILOpCode opCode)
{
return !string.IsNullOrEmpty(GetDisplayName(opCode));
}
public static readonly HashSet<string> ILKeywords = BuildKeywordList(
"abstract", "algorithm", "alignment", "ansi", "any", "arglist",
"array", "as", "assembly", "assert", "at", "auto", "autochar", "beforefieldinit",
"blob", "blob_object", "bool", "brnull", "brnull.s", "brzero", "brzero.s", "bstr",
"bytearray", "byvalstr", "callmostderived", "carray", "catch", "cdecl", "cf",
"char", "cil", "class", "clsid", "const", "currency", "custom", "date", "decimal",
"default", "demand", "deny", "endmac", "enum", "error", "explicit", "extends", "extern",
"false", "famandassem", "family", "famorassem", "fastcall", "fault", "field", "filetime",
"filter", "final", "finally", "fixed", "float", "float32", "float64", "forwardref",
"fromunmanaged", "handler", "hidebysig", "hresult", "idispatch", "il", "illegal",
"implements", "implicitcom", "implicitres", "import", "in", "inheritcheck", "init",
"initonly", "instance", "int", "int16", "int32", "int64", "int8", "interface", "internalcall",
"iunknown", "lasterr", "lcid", "linkcheck", "literal", "localloc", "lpstr", "lpstruct", "lptstr",
"lpvoid", "lpwstr", "managed", "marshal", "method", "modopt", "modreq", "native", "nested",
"newslot", "noappdomain", "noinlining", "nomachine", "nomangle", "nometadata", "noncasdemand",
"noncasinheritance", "noncaslinkdemand", "noprocess", "not", "not_in_gc_heap", "notremotable",
"notserialized", "null", "nullref", "object", "objectref", "opt", "optil", "out",
"permitonly", "pinned", "pinvokeimpl", "prefix1", "prefix2", "prefix3", "prefix4", "prefix5", "prefix6",
"prefix7", "prefixref", "prejitdeny", "prejitgrant", "preservesig", "private", "privatescope", "protected",
"public", "record", "refany", "reqmin", "reqopt", "reqrefuse", "reqsecobj", "request", "retval",
"rtspecialname", "runtime", "safearray", "sealed", "sequential", "serializable", "special", "specialname",
"static", "stdcall", "storage", "stored_object", "stream", "streamed_object", "string", "struct",
"synchronized", "syschar", "sysstring", "tbstr", "thiscall", "tls", "to", "true", "typedref",
"unicode", "unmanaged", "unmanagedexp", "unsigned", "unused", "userdefined", "value", "valuetype",
"vararg", "variant", "vector", "virtual", "void", "wchar", "winapi", "with", "wrapper",
// These are not listed as keywords in spec, but ILAsm treats them as such
"property", "type", "flags", "callconv", "strict"
);
static HashSet<string> BuildKeywordList(params string[] keywords)
{
HashSet<string> s = new HashSet<string>(keywords);
foreach (var inst in operandNames) {
if (string.IsNullOrEmpty(inst))
continue;
s.Add(inst);
}
return s;
} }
} }
} }

41
ICSharpCode.Decompiler/IL/SequencePoint.cs

@ -1,41 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace ICSharpCode.Decompiler.IL
{
/// <summary>
/// A sequence point produced by the decompiler.
/// </summary>
public struct SequencePoint
{
/// <summary>
/// IL start offset.
/// </summary>
public int Offset { get; set; }
/// <summary>
/// IL end offset.
/// </summary>
/// <remarks>
/// This does not get stored in debug information;
/// it is used internally to create hidden sequence points
/// for the IL fragments not covered by any sequence point.
/// </remarks>
public int EndOffset { get; set; }
public int StartLine { get; set; }
public int StartColumn { get; set; }
public int EndLine { get; set; }
public int EndColumn { get; set; }
public bool IsHidden {
get { return StartLine == 0xfeefee && StartLine == EndLine; }
}
internal void SetHidden()
{
StartLine = EndLine = 0xfeefee;
}
}
}

24
ICSharpCode.Decompiler/TypeSystem/CecilLoader.cs

@ -227,7 +227,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
InitTypeDefinition(cecilTypeDefs[i], typeDefs[i]); InitTypeDefinition(cecilTypeDefs[i], typeDefs[i]);
} }
AddToTypeSystemTranslationTable(this.currentAssembly, assemblyDefinition); //AddToTypeSystemTranslationTable(this.currentAssembly, assemblyDefinition);
// Freezing the assembly here is important: // Freezing the assembly here is important:
// otherwise it will be frozen when a compilation is first created // otherwise it will be frozen when a compilation is first created
// from it. But freezing has the effect of changing some collection instances // from it. But freezing has the effect of changing some collection instances
@ -911,7 +911,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
{ {
foreach (MethodDefinitionHandle h in typeDefinition.GetMethods()) { foreach (MethodDefinitionHandle h in typeDefinition.GetMethods()) {
var method = currentModule.GetMethodDefinition(h); var method = currentModule.GetMethodDefinition(h);
if (IsVisible(method.Attributes) && !IsAccessor(h.GetMethodSemanticsAttributes(currentModule))) { /*if (IsVisible(method.Attributes) && !IsAccessor(h.GetMethodSemanticsAttributes(currentModule))) {
SymbolKind type = SymbolKind.Method; SymbolKind type = SymbolKind.Method;
if ((method.Attributes & MethodAttributes.SpecialName) != 0) { if ((method.Attributes & MethodAttributes.SpecialName) != 0) {
if (method.IsConstructor(currentModule)) if (method.IsConstructor(currentModule))
@ -920,7 +920,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
type = SymbolKind.Operator; type = SymbolKind.Operator;
} }
members.Add(ReadMethod(h, td, type)); members.Add(ReadMethod(h, td, type));
} }*/
} }
foreach (FieldDefinitionHandle h in typeDefinition.GetFields()) { foreach (FieldDefinitionHandle h in typeDefinition.GetFields()) {
var field = currentModule.GetFieldDefinition(h); var field = currentModule.GetFieldDefinition(h);
@ -1714,7 +1714,8 @@ namespace ICSharpCode.Decompiler.TypeSystem
public AssemblyDefinition GetCecilObject (IUnresolvedAssembly content) public AssemblyDefinition GetCecilObject (IUnresolvedAssembly content)
{ {
return InternalGetCecilObject<AssemblyDefinition> (content); throw new NotImplementedException();
//return InternalGetCecilObject<AssemblyDefinition> (content);
} }
@ -1722,31 +1723,36 @@ namespace ICSharpCode.Decompiler.TypeSystem
{ {
if (type == null) if (type == null)
throw new ArgumentNullException ("type"); throw new ArgumentNullException ("type");
return InternalGetCecilObject<TypeDefinition> (type); throw new NotImplementedException();
//return InternalGetCecilObject<TypeDefinition> (type);
} }
public MethodDefinition GetCecilObject (IUnresolvedMethod method) public MethodDefinition GetCecilObject (IUnresolvedMethod method)
{ {
return InternalGetCecilObject<MethodDefinition> (method); throw new NotImplementedException();
//return InternalGetCecilObject<MethodDefinition> (method);
} }
public FieldDefinition GetCecilObject (IUnresolvedField field) public FieldDefinition GetCecilObject (IUnresolvedField field)
{ {
return InternalGetCecilObject<FieldDefinition> (field); throw new NotImplementedException();
//return InternalGetCecilObject<FieldDefinition> (field);
} }
public EventDefinition GetCecilObject (IUnresolvedEvent evt) public EventDefinition GetCecilObject (IUnresolvedEvent evt)
{ {
return InternalGetCecilObject<EventDefinition> (evt); throw new NotImplementedException();
//return InternalGetCecilObject<EventDefinition> (evt);
} }
public PropertyDefinition GetCecilObject (IUnresolvedProperty property) public PropertyDefinition GetCecilObject (IUnresolvedProperty property)
{ {
return InternalGetCecilObject<PropertyDefinition> (property); throw new NotImplementedException();
//return InternalGetCecilObject<PropertyDefinition> (property);
} }
#endregion #endregion
} }

27
ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs

@ -41,7 +41,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
if (moduleDefinition == null) if (moduleDefinition == null)
throw new ArgumentNullException(nameof(moduleDefinition)); throw new ArgumentNullException(nameof(moduleDefinition));
this.moduleDefinition = moduleDefinition; this.moduleDefinition = moduleDefinition;
MetadataLoader cecilLoader = new MetadataLoader { IncludeInternalMembers = true, LazyLoad = true, OnEntityLoaded = StoreMemberReference, ShortenInterfaceImplNames = false }; /*MetadataLoader cecilLoader = new MetadataLoader { IncludeInternalMembers = true, LazyLoad = true, OnEntityLoaded = StoreMemberReference, ShortenInterfaceImplNames = false };
typeReferenceCecilLoader.SetCurrentModule(moduleDefinition); typeReferenceCecilLoader.SetCurrentModule(moduleDefinition);
IUnresolvedAssembly mainAssembly = cecilLoader.LoadModule(moduleDefinition); IUnresolvedAssembly mainAssembly = cecilLoader.LoadModule(moduleDefinition);
// Load referenced assemblies and type-forwarder references. // Load referenced assemblies and type-forwarder references.
@ -69,7 +69,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
referencedAssemblies.Add(MinimalCorlib.Instance); referencedAssemblies.Add(MinimalCorlib.Instance);
compilation = new SimpleCompilation(mainAssembly, referencedAssemblies); compilation = new SimpleCompilation(mainAssembly, referencedAssemblies);
} }
context = new SimpleTypeResolveContext(compilation.MainAssembly); context = new SimpleTypeResolveContext(compilation.MainAssembly);*/
} }
public ICompilation Compilation { public ICompilation Compilation {
@ -130,6 +130,8 @@ namespace ICSharpCode.Decompiler.TypeSystem
#region Resolve Type #region Resolve Type
public IType Resolve(TypeReference typeReference) public IType Resolve(TypeReference typeReference)
{ {
throw new NotImplementedException();
#if false
if (typeReference == null) if (typeReference == null)
return SpecialType.UnknownType; return SpecialType.UnknownType;
// We need to skip SentinelType and PinnedType. // We need to skip SentinelType and PinnedType.
@ -137,15 +139,16 @@ namespace ICSharpCode.Decompiler.TypeSystem
while (typeReference is OptionalModifierType || typeReference is RequiredModifierType) { while (typeReference is OptionalModifierType || typeReference is RequiredModifierType) {
typeReference = ((TypeSpecification)typeReference).ElementType; typeReference = ((TypeSpecification)typeReference).ElementType;
} }
if (typeReference is SentinelType || typeReference is PinnedType) { if (typeReference is SentinelType || typeReference is Mono.Cecil.PinnedType) {
typeReference = ((TypeSpecification)typeReference).ElementType; typeReference = ((TypeSpecification)typeReference).ElementType;
} }
ITypeReference typeRef; ITypeReference typeRef;
lock (typeReferenceCecilLoader) lock (typeReferenceCecilLoader)
typeRef = typeReferenceCecilLoader.ReadTypeReference(typeReference); typeRef = typeReferenceCecilLoader.ReadTypeReference(typeReference);
return typeRef.Resolve(context); return typeRef.Resolve(context);
#endif
} }
#endregion #endregion
#region Resolve Field #region Resolve Field
public IField Resolve(FieldReference fieldReference) public IField Resolve(FieldReference fieldReference)
@ -180,6 +183,8 @@ namespace ICSharpCode.Decompiler.TypeSystem
IField CreateFakeField(FieldReference fieldReference) IField CreateFakeField(FieldReference fieldReference)
{ {
throw new NotImplementedException();
#if false
var declaringType = Resolve(fieldReference.DeclaringType); var declaringType = Resolve(fieldReference.DeclaringType);
var f = new DefaultUnresolvedField(); var f = new DefaultUnresolvedField();
f.Name = fieldReference.Name; f.Name = fieldReference.Name;
@ -187,6 +192,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
f.ReturnType = typeReferenceCecilLoader.ReadTypeReference(fieldReference.FieldType); f.ReturnType = typeReferenceCecilLoader.ReadTypeReference(fieldReference.FieldType);
} }
return new ResolvedFakeField(f, context.WithCurrentTypeDefinition(declaringType.GetDefinition()), declaringType); return new ResolvedFakeField(f, context.WithCurrentTypeDefinition(declaringType.GetDefinition()), declaringType);
#endif
} }
class ResolvedFakeField : DefaultResolvedField class ResolvedFakeField : DefaultResolvedField
@ -204,7 +210,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
get { return declaringType; } get { return declaringType; }
} }
} }
#endregion #endregion
#region Resolve Method #region Resolve Method
public IMethod Resolve(MethodReference methodReference) public IMethod Resolve(MethodReference methodReference)
@ -306,6 +312,8 @@ namespace ICSharpCode.Decompiler.TypeSystem
/// </summary> /// </summary>
IMethod CreateFakeMethod(MethodReference methodReference) IMethod CreateFakeMethod(MethodReference methodReference)
{ {
throw new NotImplementedException();
#if false
var m = new DefaultUnresolvedMethod(); var m = new DefaultUnresolvedMethod();
ITypeReference declaringTypeReference; ITypeReference declaringTypeReference;
lock (typeReferenceCecilLoader) { lock (typeReferenceCecilLoader) {
@ -324,6 +332,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
} }
var type = declaringTypeReference.Resolve(context); var type = declaringTypeReference.Resolve(context);
return new ResolvedFakeMethod(m, context.WithCurrentTypeDefinition(type.GetDefinition()), type); return new ResolvedFakeMethod(m, context.WithCurrentTypeDefinition(type.GetDefinition()), type);
#endif
} }
class ResolvedFakeMethod : DefaultResolvedMethod class ResolvedFakeMethod : DefaultResolvedMethod
@ -343,7 +352,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
} }
#endregion #endregion
#region Resolve Property #region Resolve Property
public IProperty Resolve(PropertyReference propertyReference) public IProperty Resolve(PropertyReference propertyReference)
{ {
if (propertyReference == null) if (propertyReference == null)
@ -378,9 +387,9 @@ namespace ICSharpCode.Decompiler.TypeSystem
} }
return null; return null;
} }
#endregion #endregion
#region Resolve Event #region Resolve Event
public IEvent Resolve(EventReference eventReference) public IEvent Resolve(EventReference eventReference)
{ {
if (eventReference == null) if (eventReference == null)
@ -412,6 +421,6 @@ namespace ICSharpCode.Decompiler.TypeSystem
} }
return null; return null;
} }
#endregion #endregion
} }
} }

6
ICSharpCode.Decompiler/TypeSystem/Implementation/TypeSpecification.cs

@ -105,8 +105,6 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
} }
} }
public struct Unit { }
class TypeReferenceSignatureDecoder : ISignatureTypeProvider<ITypeReference, Unit> class TypeReferenceSignatureDecoder : ISignatureTypeProvider<ITypeReference, Unit>
{ {
public ITypeReference GetArrayType(ITypeReference elementType, ArrayShape shape) public ITypeReference GetArrayType(ITypeReference elementType, ArrayShape shape)
@ -184,10 +182,12 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
} }
} }
class TypeSystemAttributeTypeProvider : ICustomAttributeTypeProvider<IType> public class TypeSystemAttributeTypeProvider : ICustomAttributeTypeProvider<IType>
{ {
readonly ITypeResolveContext context; readonly ITypeResolveContext context;
public static TypeSystemAttributeTypeProvider CreateDefault() => new TypeSystemAttributeTypeProvider(new SimpleTypeResolveContext(MinimalCorlib.Instance.CreateCompilation()));
public TypeSystemAttributeTypeProvider(ITypeResolveContext context) public TypeSystemAttributeTypeProvider(ITypeResolveContext context)
{ {
this.context = context; this.context = context;

2
ICSharpCode.Decompiler/Util/EmptyList.cs

@ -116,4 +116,6 @@ namespace ICSharpCode.Decompiler.Util
{ {
public static readonly T[] Array = new T[0]; public static readonly T[] Array = new T[0];
} }
public struct Unit { }
} }

1
ILSpy.AddIn/ILSpy.AddIn.csproj

@ -49,7 +49,6 @@
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\ICSharpCode.Decompiler\ICSharpCode.Decompiler.csproj" /> <ProjectReference Include="..\ICSharpCode.Decompiler\ICSharpCode.Decompiler.csproj" />
<ProjectReference Include="..\ILSpy.BamlDecompiler\ILSpy.BamlDecompiler.csproj" />
<ProjectReference Include="..\ILSpy\ILSpy.csproj" /> <ProjectReference Include="..\ILSpy\ILSpy.csproj" />
<ProjectReference Include="..\SharpTreeView\ICSharpCode.TreeView.csproj" /> <ProjectReference Include="..\SharpTreeView\ICSharpCode.TreeView.csproj" />
</ItemGroup> </ItemGroup>

1
ILSpy.BamlDecompiler.Tests/ILSpy.BamlDecompiler.Tests.csproj

@ -40,7 +40,6 @@
<ProjectReference Include="..\ICSharpCode.Decompiler.Tests\ICSharpCode.Decompiler.Tests.csproj" /> <ProjectReference Include="..\ICSharpCode.Decompiler.Tests\ICSharpCode.Decompiler.Tests.csproj" />
<ProjectReference Include="..\ILSpy\ILSpy.csproj" /> <ProjectReference Include="..\ILSpy\ILSpy.csproj" />
<ProjectReference Include="..\SharpTreeView\ICSharpCode.TreeView.csproj" /> <ProjectReference Include="..\SharpTreeView\ICSharpCode.TreeView.csproj" />
<ProjectReference Include="..\ILSpy.BamlDecompiler\ILSpy.BamlDecompiler.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

8
ILSpy.BamlDecompiler/BamlResourceEntryNode.cs

@ -10,11 +10,11 @@ using System.Threading.Tasks;
using System.Xml.Linq; using System.Xml.Linq;
using ICSharpCode.AvalonEdit.Highlighting; using ICSharpCode.AvalonEdit.Highlighting;
using ICSharpCode.Decompiler.Dom;
using ICSharpCode.Decompiler.Util; using ICSharpCode.Decompiler.Util;
using ICSharpCode.ILSpy; using ICSharpCode.ILSpy;
using ICSharpCode.ILSpy.TextView; using ICSharpCode.ILSpy.TextView;
using ICSharpCode.ILSpy.TreeNodes; using ICSharpCode.ILSpy.TreeNodes;
using Mono.Cecil;
using Ricciolo.StylesExplorer.MarkupReflection; using Ricciolo.StylesExplorer.MarkupReflection;
namespace ILSpy.BamlDecompiler namespace ILSpy.BamlDecompiler
@ -50,16 +50,16 @@ namespace ILSpy.BamlDecompiler
{ {
var asm = this.Ancestors().OfType<AssemblyTreeNode>().FirstOrDefault().LoadedAssembly; var asm = this.Ancestors().OfType<AssemblyTreeNode>().FirstOrDefault().LoadedAssembly;
Data.Position = 0; Data.Position = 0;
XDocument xamlDocument = LoadIntoDocument(asm.GetAssemblyResolver(), asm.GetAssemblyDefinitionAsync().Result, Data, cancellationToken); XDocument xamlDocument = LoadIntoDocument(asm.GetAssemblyResolver(), asm.GetPEFileOrNull(), Data, cancellationToken);
output.Write(xamlDocument.ToString()); output.Write(xamlDocument.ToString());
return true; return true;
} }
internal static XDocument LoadIntoDocument(IAssemblyResolver resolver, AssemblyDefinition asm, Stream stream, CancellationToken cancellationToken) internal static XDocument LoadIntoDocument(PEFile module, Stream stream, CancellationToken cancellationToken)
{ {
cancellationToken.ThrowIfCancellationRequested(); cancellationToken.ThrowIfCancellationRequested();
XDocument xamlDocument; XDocument xamlDocument;
using (XmlBamlReader reader = new XmlBamlReader(stream, new CecilTypeResolver(resolver, asm))) { using (XmlBamlReader reader = new XmlBamlReader(stream, new NRTypeResolver(resolver, asm))) {
xamlDocument = XDocument.Load(reader); xamlDocument = XDocument.Load(reader);
ConvertConnectionIds(xamlDocument, asm, cancellationToken); ConvertConnectionIds(xamlDocument, asm, cancellationToken);
ConvertToEmptyElements(xamlDocument.Root); ConvertToEmptyElements(xamlDocument.Root);

5
ILSpy.BamlDecompiler/BamlResourceNodeFactory.cs

@ -7,13 +7,14 @@ using System.IO;
using ICSharpCode.ILSpy.TreeNodes; using ICSharpCode.ILSpy.TreeNodes;
using ICSharpCode.ILSpy; using ICSharpCode.ILSpy;
using ICSharpCode.Decompiler.Dom;
namespace ILSpy.BamlDecompiler namespace ILSpy.BamlDecompiler
{ {
[Export(typeof(IResourceNodeFactory))] [Export(typeof(IResourceNodeFactory))]
public sealed class BamlResourceNodeFactory : IResourceNodeFactory public sealed class BamlResourceNodeFactory : IResourceNodeFactory
{ {
public ILSpyTreeNode CreateNode(Mono.Cecil.Resource resource) public ILSpyTreeNode CreateNode(Resource resource)
{ {
return null; return null;
} }
@ -35,7 +36,7 @@ namespace ILSpy.BamlDecompiler
public string WriteResourceToFile(LoadedAssembly assembly, string fileName, Stream stream, DecompilationOptions options) public string WriteResourceToFile(LoadedAssembly assembly, string fileName, Stream stream, DecompilationOptions options)
{ {
var document = BamlResourceEntryNode.LoadIntoDocument(assembly.GetAssemblyResolver(), assembly.GetAssemblyDefinitionAsync().Result, stream, options.CancellationToken); var document = BamlResourceEntryNode.LoadIntoDocument(assembly.GetAssemblyResolver(), assembly.GetPEFileOrNull(), stream, options.CancellationToken);
fileName = Path.ChangeExtension(fileName, ".xaml"); fileName = Path.ChangeExtension(fileName, ".xaml");
document.Save(Path.Combine(options.SaveAsProjectDirectory, fileName)); document.Save(Path.Combine(options.SaveAsProjectDirectory, fileName));
return fileName; return fileName;

35
ILSpy.BamlDecompiler/CecilDependencyPropertyDescriptor.cs

@ -1,35 +0,0 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
// This code is distributed under the MS-PL (for details please see \doc\MS-PL.txt)
using System;
using System.Linq;
using Mono.Cecil;
using Ricciolo.StylesExplorer.MarkupReflection;
namespace ILSpy.BamlDecompiler
{
public class CecilDependencyPropertyDescriptor : IDependencyPropertyDescriptor
{
string member;
TypeDefinition type;
public CecilDependencyPropertyDescriptor(string member, TypeDefinition type)
{
if (type == null)
throw new ArgumentNullException("type");
this.member = member;
this.type = type;
}
public bool IsAttached {
get {
return type.Methods.Any(m => m.Name == "Get" + member);
}
}
public override string ToString()
{
return string.Format("[CecilDependencyPropertyDescriptor Member={0}, Type={1}]", member, type);
}
}
}

60
ILSpy.BamlDecompiler/CecilType.cs

@ -2,68 +2,49 @@
// This code is distributed under the MS-PL (for details please see \doc\MS-PL.txt) // This code is distributed under the MS-PL (for details please see \doc\MS-PL.txt)
using System; using System;
using System.Linq;
using ICSharpCode.Decompiler.TypeSystem;
using Mono.Cecil; using Mono.Cecil;
using Ricciolo.StylesExplorer.MarkupReflection; using Ricciolo.StylesExplorer.MarkupReflection;
namespace ILSpy.BamlDecompiler namespace ILSpy.BamlDecompiler
{ {
public class CecilType : IType public class NRType : IDotNetType
{ {
internal readonly TypeDefinition type; readonly ITypeDefinition type;
public CecilType(TypeDefinition type) public ITypeDefinition Type => type;
public NRType(ITypeDefinition type)
{ {
if (type == null) this.type = type ?? throw new ArgumentNullException(nameof(type));
throw new ArgumentNullException("type");
this.type = type;
} }
public string AssemblyQualifiedName { public string AssemblyQualifiedName {
get { get {
return type.FullName + return type.FullName +
", " + type.Module.Assembly.FullName; ", " + type.ParentAssembly.FullAssemblyName;
} }
} }
public bool IsSubclassOf(IType type) public bool IsSubclassOf(IDotNetType type)
{ {
if (type == null) if (type == null)
throw new ArgumentNullException("type"); throw new ArgumentNullException(nameof(type));
if (!(type is CecilType)) if (!(type is NRType baseType))
return false; return false;
CecilType ct = (CecilType)type; return this.type.GetAllBaseTypeDefinitions().Any(t => t.Equals(baseType.type));
var t = this.type;
if (t == ct.type)
return false;
while (t != null) {
if (t == ct.type)
return true;
foreach (var @interface in t.Interfaces) {
var resolved = @interface.InterfaceType.Resolve();
if (resolved == ct.type)
return true;
}
if (t.BaseType == null)
break;
t = t.BaseType.Resolve();
}
return false;
} }
public bool Equals(IType type) public bool Equals(IDotNetType type)
{ {
if (type == null) if (type == null)
throw new ArgumentNullException("type"); throw new ArgumentNullException("type");
if (!(type is CecilType)) if (!(type is NRType))
return false; return false;
return this.type == ((CecilType)type).type; return this.type.Equals(((NRType)type).type);
} }
public override string ToString() public override string ToString()
@ -71,13 +52,14 @@ namespace ILSpy.BamlDecompiler
return string.Format("[CecilType Type={0}]", type); return string.Format("[CecilType Type={0}]", type);
} }
public IType BaseType { public IDotNetType BaseType {
get { get {
TypeDefinition td = type.BaseType.Resolve(); var t = type.DirectBaseTypes.First();
var td = t.GetDefinition();
if (td == null) if (td == null)
throw new Exception("could not resolve '" + type.BaseType.FullName + "'!"); throw new Exception($"Could not resolve '{t.FullName}'!");
return new CecilType(td); return new NRType(td);
} }
} }
} }

54
ILSpy.BamlDecompiler/CecilTypeResolver.cs

@ -2,6 +2,7 @@
// This code is distributed under the MS-PL (for details please see \doc\MS-PL.txt) // This code is distributed under the MS-PL (for details please see \doc\MS-PL.txt)
using System; using System;
using ICSharpCode.Decompiler.TypeSystem;
using Mono.Cecil; using Mono.Cecil;
using Ricciolo.StylesExplorer.MarkupReflection; using Ricciolo.StylesExplorer.MarkupReflection;
@ -10,20 +11,18 @@ namespace ILSpy.BamlDecompiler
/// <summary> /// <summary>
/// Description of CecilTypeResolver. /// Description of CecilTypeResolver.
/// </summary> /// </summary>
public class CecilTypeResolver : ITypeResolver public class NRTypeResolver : IDotNetTypeResolver
{ {
IAssemblyResolver resolver; readonly ICompilation compilation;
AssemblyDefinition thisAssembly;
public CecilTypeResolver(IAssemblyResolver resolver, AssemblyDefinition asm) public NRTypeResolver(ICompilation compilation)
{ {
this.resolver = resolver; this.compilation = compilation;
this.thisAssembly = asm;
} }
public bool IsLocalAssembly(string name) public bool IsLocalAssembly(string name)
{ {
return MakeShort(name) == this.thisAssembly.Name.Name; return MakeShort(name) == compilation.MainAssembly.AssemblyName;
} }
string MakeShort(string name) string MakeShort(string name)
@ -35,7 +34,7 @@ namespace ILSpy.BamlDecompiler
return name.Substring(0, endOffset); return name.Substring(0, endOffset);
} }
public IType GetTypeByAssemblyQualifiedName(string name) public IDotNetType GetTypeByAssemblyQualifiedName(string name)
{ {
int bracket = name.LastIndexOf(']'); int bracket = name.LastIndexOf(']');
int comma = bracket > -1 ? name.IndexOf(',', bracket) : name.IndexOf(','); int comma = bracket > -1 ? name.IndexOf(',', bracket) : name.IndexOf(',');
@ -46,47 +45,21 @@ namespace ILSpy.BamlDecompiler
string fullName = bracket > -1 ? name.Substring(0, name.IndexOf('[')) : name.Substring(0, comma); string fullName = bracket > -1 ? name.Substring(0, name.IndexOf('[')) : name.Substring(0, comma);
string assemblyName = name.Substring(comma + 1).Trim(); string assemblyName = name.Substring(comma + 1).Trim();
var type = thisAssembly.MainModule.GetType(fullName); var type = compilation.FindType(new FullTypeName(fullName)).GetDefinition();
if (type == null) {
type = TryFindInExportedTypes(fullName, thisAssembly);
}
if (type == null) {
var otherAssembly = resolver.Resolve(AssemblyNameReference.Parse(assemblyName));
if (otherAssembly == null)
return new UnresolvableType(name);
type = otherAssembly.MainModule.GetType(fullName.Replace('+', '/'));
if (type == null) {
type = TryFindInExportedTypes(fullName, otherAssembly);
}
}
if (type == null) if (type == null)
return new UnresolvableType(name); return new UnresolvableType(name);
return new CecilType(type); return new NRType(type);
}
TypeDefinition TryFindInExportedTypes(string fullName, AssemblyDefinition asm)
{
foreach (var exportedType in asm.MainModule.ExportedTypes) {
if (exportedType.IsForwarder && exportedType.FullName == fullName) {
return exportedType.Resolve();
}
}
return null;
} }
public IDependencyPropertyDescriptor GetDependencyPropertyDescriptor(string name, IType ownerType, IType targetType) public IDependencyPropertyDescriptor GetDependencyPropertyDescriptor(string name, IDotNetType ownerType, IDotNetType targetType)
{ {
if (ownerType == null) if (ownerType == null)
throw new ArgumentNullException("ownerType"); throw new ArgumentNullException("ownerType");
if (ownerType is CecilType) if (ownerType is NRType)
return new CecilDependencyPropertyDescriptor(name, ((CecilType)ownerType).type); return new NRTypeDependencyPropertyDescriptor(((NRType)ownerType).Type, name);
if (ownerType is UnresolvableType) if (ownerType is UnresolvableType)
return new UnresolvableDependencyPropertyDescriptor(); return new UnresolvableDependencyPropertyDescriptor();
@ -95,7 +68,8 @@ namespace ILSpy.BamlDecompiler
public string RuntimeVersion { public string RuntimeVersion {
get { get {
return thisAssembly.MainModule.Runtime.ToString(); throw new NotImplementedException();
//return thisAssembly.MainModule.Runtime.ToString();
} }
} }
} }

2
ILSpy.BamlDecompiler/ILSpy.BamlDecompiler.csproj

@ -54,7 +54,7 @@
<ItemGroup> <ItemGroup>
<Compile Include="BamlResourceNodeFactory.cs" /> <Compile Include="BamlResourceNodeFactory.cs" />
<Compile Include="BamlResourceEntryNode.cs" /> <Compile Include="BamlResourceEntryNode.cs" />
<Compile Include="CecilDependencyPropertyDescriptor.cs" /> <Compile Include="SRMDependencyPropertyDescriptor.cs" />
<Compile Include="CecilType.cs" /> <Compile Include="CecilType.cs" />
<Compile Include="CecilTypeResolver.cs" /> <Compile Include="CecilTypeResolver.cs" />
<Compile Include="ConnectMethodDecompiler.cs" /> <Compile Include="ConnectMethodDecompiler.cs" />

30
ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/IType.cs

@ -7,41 +7,31 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
/// <summary> /// <summary>
/// Interface representing a DotNet type /// Interface representing a DotNet type
/// </summary> /// </summary>
public interface IType public interface IDotNetType
{ {
IType BaseType { get; } IDotNetType BaseType { get; }
string AssemblyQualifiedName { get; } string AssemblyQualifiedName { get; }
bool IsSubclassOf(IType type); bool IsSubclassOf(IDotNetType type);
bool Equals(IType type); bool Equals(IDotNetType type);
} }
public class UnresolvableType : IType public class UnresolvableType : IDotNetType
{ {
string assemblyQualifiedName;
public UnresolvableType(string assemblyQualifiedName) public UnresolvableType(string assemblyQualifiedName)
{ {
this.assemblyQualifiedName = assemblyQualifiedName; this.AssemblyQualifiedName = assemblyQualifiedName;
} }
public IType BaseType { public IDotNetType BaseType => null;
get {
return null;
}
}
public string AssemblyQualifiedName { public string AssemblyQualifiedName { get; }
get {
return assemblyQualifiedName;
}
}
public bool IsSubclassOf(IType type) public bool IsSubclassOf(IDotNetType type)
{ {
return Equals(type); return Equals(type);
} }
public bool Equals(IType type) public bool Equals(IDotNetType type)
{ {
return type is UnresolvableType && type.AssemblyQualifiedName == AssemblyQualifiedName; return type is UnresolvableType && type.AssemblyQualifiedName == AssemblyQualifiedName;
} }

6
ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/ITypeResolver.cs

@ -4,11 +4,11 @@
namespace Ricciolo.StylesExplorer.MarkupReflection namespace Ricciolo.StylesExplorer.MarkupReflection
{ {
public interface ITypeResolver public interface IDotNetTypeResolver
{ {
string RuntimeVersion { get; } string RuntimeVersion { get; }
bool IsLocalAssembly(string name); bool IsLocalAssembly(string name);
IType GetTypeByAssemblyQualifiedName(string name); IDotNetType GetTypeByAssemblyQualifiedName(string name);
IDependencyPropertyDescriptor GetDependencyPropertyDescriptor(string name, IType ownerType, IType targetType); IDependencyPropertyDescriptor GetDependencyPropertyDescriptor(string name, IDotNetType ownerType, IDotNetType targetType);
} }
} }

2
ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/KnownInfo.cs

@ -31,7 +31,7 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
{ {
} }
public KnownInfo(ITypeResolver resolver) public KnownInfo(IDotNetTypeResolver resolver)
{ {
switch (resolver.RuntimeVersion) { switch (resolver.RuntimeVersion) {
case "Net_2_0": case "Net_2_0":

18
ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/TypeDeclaration.cs

@ -9,33 +9,33 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
{ {
readonly XmlBamlReader reader; readonly XmlBamlReader reader;
readonly bool _isExtension; readonly bool _isExtension;
IType _type; IDotNetType _type;
bool _typeLoaded; bool _typeLoaded;
readonly ITypeResolver resolver; readonly IDotNetTypeResolver resolver;
protected TypeDeclaration(ITypeResolver resolver) protected TypeDeclaration(IDotNetTypeResolver resolver)
{ {
this.resolver = resolver; this.resolver = resolver;
} }
public TypeDeclaration(ITypeResolver resolver, string name, string namespaceName, short assemblyId) public TypeDeclaration(IDotNetTypeResolver resolver, string name, string namespaceName, short assemblyId)
: this(null, resolver, name, namespaceName, assemblyId) : this(null, resolver, name, namespaceName, assemblyId)
{ {
} }
public TypeDeclaration(ITypeResolver resolver, string name, string enclosingTypeName, string namespaceName, short assemblyId) public TypeDeclaration(IDotNetTypeResolver resolver, string name, string enclosingTypeName, string namespaceName, short assemblyId)
: this(null, resolver, name, namespaceName, assemblyId) : this(null, resolver, name, namespaceName, assemblyId)
{ {
this.EnclosingTypeName = enclosingTypeName; this.EnclosingTypeName = enclosingTypeName;
} }
public TypeDeclaration(ITypeResolver resolver, string name, string namespaceName, short assemblyId, bool isExtension) public TypeDeclaration(IDotNetTypeResolver resolver, string name, string namespaceName, short assemblyId, bool isExtension)
: this(null, resolver, name, namespaceName, assemblyId) : this(null, resolver, name, namespaceName, assemblyId)
{ {
_isExtension = isExtension; _isExtension = isExtension;
} }
public TypeDeclaration(XmlBamlReader reader, ITypeResolver resolver, string name, string namespaceName, short assemblyId) public TypeDeclaration(XmlBamlReader reader, IDotNetTypeResolver resolver, string name, string namespaceName, short assemblyId)
{ {
this.reader = reader; this.reader = reader;
this.resolver = resolver; this.resolver = resolver;
@ -73,7 +73,7 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
public virtual string Name { get; protected set; } public virtual string Name { get; protected set; }
public IType Type { public IDotNetType Type {
get { get {
if (!_typeLoaded) { if (!_typeLoaded) {
if (this.Name.Length > 0) if (this.Name.Length > 0)
@ -119,7 +119,7 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
protected set { throw new NotSupportedException(); } protected set { throw new NotSupportedException(); }
} }
public ResolverTypeDeclaration(ITypeResolver resolver, string assemblyQualifiedName) public ResolverTypeDeclaration(IDotNetTypeResolver resolver, string assemblyQualifiedName)
: base(resolver) : base(resolver)
{ {
string name, @namespace, assembly; string name, @namespace, assembly;

6
ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlBamlReader.cs

@ -22,7 +22,7 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
Dictionary<short, TypeDeclaration> typeTable = new Dictionary<short, TypeDeclaration>(); Dictionary<short, TypeDeclaration> typeTable = new Dictionary<short, TypeDeclaration>();
Dictionary<short, PropertyDeclaration> propertyTable = new Dictionary<short, PropertyDeclaration>(); Dictionary<short, PropertyDeclaration> propertyTable = new Dictionary<short, PropertyDeclaration>();
readonly ITypeResolver _resolver; readonly IDotNetTypeResolver _resolver;
BamlRecordType currentType; BamlRecordType currentType;
@ -99,7 +99,7 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
public ISet<XmlNamespace> XmlnsDefinitions { get; } = new HashSet<XmlNamespace>(); public ISet<XmlNamespace> XmlnsDefinitions { get; } = new HashSet<XmlNamespace>();
public XmlBamlReader(Stream stream, ITypeResolver resolver) public XmlBamlReader(Stream stream, IDotNetTypeResolver resolver)
{ {
if (stream == null) if (stream == null)
throw new ArgumentNullException(nameof(stream)); throw new ArgumentNullException(nameof(stream));
@ -1626,7 +1626,7 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
/// <summary> /// <summary>
/// Returns object used to resolve types /// Returns object used to resolve types
/// </summary> /// </summary>
public ITypeResolver Resolver public IDotNetTypeResolver Resolver
{ {
get { return _resolver; } get { return _resolver; }
} }

33
ILSpy.BamlDecompiler/SRMDependencyPropertyDescriptor.cs

@ -0,0 +1,33 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
// This code is distributed under the MS-PL (for details please see \doc\MS-PL.txt)
using System;
using System.Linq;
using ICSharpCode.Decompiler.TypeSystem;
using Ricciolo.StylesExplorer.MarkupReflection;
namespace ILSpy.BamlDecompiler
{
public class NRTypeDependencyPropertyDescriptor : IDependencyPropertyDescriptor
{
readonly ITypeDefinition typeDefinition;
readonly string member;
public NRTypeDependencyPropertyDescriptor(ITypeDefinition type, string name)
{
this.typeDefinition = type;
this.member = name;
}
public bool IsAttached {
get {
return typeDefinition.GetMethods(m => m.Name == "Get" + member, GetMemberOptions.IgnoreInheritedMembers).Any();
}
}
public override string ToString()
{
return string.Format("[CecilDependencyPropertyDescriptor Member={0}, Type={1}]", member, typeDefinition);
}
}
}

14
ILSpy.sln

@ -1,7 +1,7 @@
 
Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15 # Visual Studio 15
VisualStudioVersion = 15.0.26730.12 VisualStudioVersion = 15.0.27130.2026
MinimumVisualStudioVersion = 15.0 MinimumVisualStudioVersion = 15.0
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "doc", "doc", "{F45DB999-7E72-4000-B5AD-3A7B485A0896}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "doc", "doc", "{F45DB999-7E72-4000-B5AD-3A7B485A0896}"
ProjectSection(SolutionItems) = preProject ProjectSection(SolutionItems) = preProject
@ -24,10 +24,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestPlugin", "TestPlugin\Te
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Cecil.Pdb", "cecil\symbols\pdb\Mono.Cecil.Pdb.csproj", "{63E6915C-7EA4-4D76-AB28-0D7191EEA626}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Cecil.Pdb", "cecil\symbols\pdb\Mono.Cecil.Pdb.csproj", "{63E6915C-7EA4-4D76-AB28-0D7191EEA626}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ILSpy.BamlDecompiler", "ILSpy.BamlDecompiler\ILSpy.BamlDecompiler.csproj", "{A6BAD2BA-76BA-461C-8B6D-418607591247}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ILSpy.BamlDecompiler.Tests", "ILSpy.BamlDecompiler.Tests\ILSpy.BamlDecompiler.Tests.csproj", "{1169E6D1-1899-43D4-A500-07CE4235B388}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ILSpy.AddIn", "ILSpy.AddIn\ILSpy.AddIn.csproj", "{9D7BE6C0-B7B3-4A50-A54E-18A2D84A3384}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ILSpy.AddIn", "ILSpy.AddIn\ILSpy.AddIn.csproj", "{9D7BE6C0-B7B3-4A50-A54E-18A2D84A3384}"
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{0A344E19-D1FC-4F4C-8883-0844AC669113}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{0A344E19-D1FC-4F4C-8883-0844AC669113}"
@ -69,14 +65,6 @@ Global
{63E6915C-7EA4-4D76-AB28-0D7191EEA626}.Debug|Any CPU.Build.0 = net_4_0_Debug|Any CPU {63E6915C-7EA4-4D76-AB28-0D7191EEA626}.Debug|Any CPU.Build.0 = net_4_0_Debug|Any CPU
{63E6915C-7EA4-4D76-AB28-0D7191EEA626}.Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU {63E6915C-7EA4-4D76-AB28-0D7191EEA626}.Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU
{63E6915C-7EA4-4D76-AB28-0D7191EEA626}.Release|Any CPU.Build.0 = net_4_0_Release|Any CPU {63E6915C-7EA4-4D76-AB28-0D7191EEA626}.Release|Any CPU.Build.0 = net_4_0_Release|Any CPU
{A6BAD2BA-76BA-461C-8B6D-418607591247}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A6BAD2BA-76BA-461C-8B6D-418607591247}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A6BAD2BA-76BA-461C-8B6D-418607591247}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A6BAD2BA-76BA-461C-8B6D-418607591247}.Release|Any CPU.Build.0 = Release|Any CPU
{1169E6D1-1899-43D4-A500-07CE4235B388}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1169E6D1-1899-43D4-A500-07CE4235B388}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1169E6D1-1899-43D4-A500-07CE4235B388}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1169E6D1-1899-43D4-A500-07CE4235B388}.Release|Any CPU.Build.0 = Release|Any CPU
{9D7BE6C0-B7B3-4A50-A54E-18A2D84A3384}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {9D7BE6C0-B7B3-4A50-A54E-18A2D84A3384}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9D7BE6C0-B7B3-4A50-A54E-18A2D84A3384}.Debug|Any CPU.Build.0 = Debug|Any CPU {9D7BE6C0-B7B3-4A50-A54E-18A2D84A3384}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9D7BE6C0-B7B3-4A50-A54E-18A2D84A3384}.Release|Any CPU.ActiveCfg = Release|Any CPU {9D7BE6C0-B7B3-4A50-A54E-18A2D84A3384}.Release|Any CPU.ActiveCfg = Release|Any CPU

2
ILSpy/Commands/DecompileAllCommand.cs

@ -16,7 +16,7 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
#if DEBUG #if false && DEBUG
using System; using System;
using System.Diagnostics; using System.Diagnostics;

10
ILSpy/DebugSteps.xaml.cs

@ -20,7 +20,7 @@ namespace ICSharpCode.ILSpy
public static ILAstWritingOptions Options => writingOptions; public static ILAstWritingOptions Options => writingOptions;
#if DEBUG #if false && DEBUG
ILAstLanguage language; ILAstLanguage language;
#endif #endif
@ -28,7 +28,7 @@ namespace ICSharpCode.ILSpy
{ {
InitializeComponent(); InitializeComponent();
#if DEBUG #if false && DEBUG
MainWindow.Instance.SessionSettings.FilterSettings.PropertyChanged += FilterSettings_PropertyChanged; MainWindow.Instance.SessionSettings.FilterSettings.PropertyChanged += FilterSettings_PropertyChanged;
MainWindow.Instance.SelectionChanged += SelectionChanged; MainWindow.Instance.SelectionChanged += SelectionChanged;
writingOptions.PropertyChanged += WritingOptions_PropertyChanged; writingOptions.PropertyChanged += WritingOptions_PropertyChanged;
@ -56,7 +56,7 @@ namespace ICSharpCode.ILSpy
private void FilterSettings_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) private void FilterSettings_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{ {
#if DEBUG #if false && DEBUG
if (e.PropertyName == "Language") { if (e.PropertyName == "Language") {
if (language != null) { if (language != null) {
language.StepperUpdated -= ILAstStepperUpdated; language.StepperUpdated -= ILAstStepperUpdated;
@ -72,7 +72,7 @@ namespace ICSharpCode.ILSpy
private void ILAstStepperUpdated(object sender, EventArgs e) private void ILAstStepperUpdated(object sender, EventArgs e)
{ {
#if DEBUG #if false && DEBUG
if (language == null) return; if (language == null) return;
Dispatcher.Invoke(() => { Dispatcher.Invoke(() => {
tree.ItemsSource = language.Stepper.Steps; tree.ItemsSource = language.Stepper.Steps;
@ -88,7 +88,7 @@ namespace ICSharpCode.ILSpy
void IPane.Closed() void IPane.Closed()
{ {
#if DEBUG #if false && DEBUG
MainWindow.Instance.SessionSettings.FilterSettings.PropertyChanged -= FilterSettings_PropertyChanged; MainWindow.Instance.SessionSettings.FilterSettings.PropertyChanged -= FilterSettings_PropertyChanged;
MainWindow.Instance.SelectionChanged -= SelectionChanged; MainWindow.Instance.SelectionChanged -= SelectionChanged;
writingOptions.PropertyChanged -= WritingOptions_PropertyChanged; writingOptions.PropertyChanged -= WritingOptions_PropertyChanged;

36
ILSpy/ExtensionMethods.cs

@ -102,12 +102,44 @@ namespace ICSharpCode.ILSpy
return false; return false;
} }
public static string ToSuffixString(this MetadataToken token) public static string ToSuffixString(this System.Reflection.Metadata.MethodDefinitionHandle token)
{ {
if (!DisplaySettingsPanel.CurrentDisplaySettings.ShowMetadataTokens) if (!DisplaySettingsPanel.CurrentDisplaySettings.ShowMetadataTokens)
return string.Empty; return string.Empty;
return " @" + token.ToInt32().ToString("x8"); return " @" + System.Reflection.Metadata.Ecma335.MetadataTokens.GetToken(token).ToString("x8");
}
public static string ToSuffixString(this System.Reflection.Metadata.PropertyDefinitionHandle token)
{
if (!DisplaySettingsPanel.CurrentDisplaySettings.ShowMetadataTokens)
return string.Empty;
return " @" + System.Reflection.Metadata.Ecma335.MetadataTokens.GetToken(token).ToString("x8");
}
public static string ToSuffixString(this System.Reflection.Metadata.EventDefinitionHandle token)
{
if (!DisplaySettingsPanel.CurrentDisplaySettings.ShowMetadataTokens)
return string.Empty;
return " @" + System.Reflection.Metadata.Ecma335.MetadataTokens.GetToken(token).ToString("x8");
}
public static string ToSuffixString(this System.Reflection.Metadata.FieldDefinitionHandle token)
{
if (!DisplaySettingsPanel.CurrentDisplaySettings.ShowMetadataTokens)
return string.Empty;
return " @" + System.Reflection.Metadata.Ecma335.MetadataTokens.GetToken(token).ToString("x8");
}
public static string ToSuffixString(this System.Reflection.Metadata.TypeDefinitionHandle token)
{
if (!DisplaySettingsPanel.CurrentDisplaySettings.ShowMetadataTokens)
return string.Empty;
return " @" + System.Reflection.Metadata.Ecma335.MetadataTokens.GetToken(token).ToString("x8");
} }
/// <summary> /// <summary>

39
ILSpy/ILSpy.csproj

@ -76,7 +76,6 @@
<Compile Include="AvalonEdit\ITextMarker.cs" /> <Compile Include="AvalonEdit\ITextMarker.cs" />
<Compile Include="AvalonEdit\TextMarkerService.cs" /> <Compile Include="AvalonEdit\TextMarkerService.cs" />
<Compile Include="Cecil\CecilExtensions.cs" /> <Compile Include="Cecil\CecilExtensions.cs" />
<Compile Include="Cecil\TypesHierarchyHelpers.cs" />
<Compile Include="Commands\CheckForUpdatesCommand.cs" /> <Compile Include="Commands\CheckForUpdatesCommand.cs" />
<Compile Include="Commands\BrowseBackCommand.cs" /> <Compile Include="Commands\BrowseBackCommand.cs" />
<Compile Include="Commands\BrowseForwardCommand.cs" /> <Compile Include="Commands\BrowseForwardCommand.cs" />
@ -127,6 +126,7 @@
<Compile Include="Images\Images.cs" /> <Compile Include="Images\Images.cs" />
<Compile Include="Languages\ILLanguage.cs" /> <Compile Include="Languages\ILLanguage.cs" />
<Compile Include="Languages\IResourceFileHandler.cs" /> <Compile Include="Languages\IResourceFileHandler.cs" />
<Compile Include="Languages\ITypeProvider.cs" />
<Compile Include="Languages\Language.cs" /> <Compile Include="Languages\Language.cs" />
<Compile Include="Languages\Languages.cs" /> <Compile Include="Languages\Languages.cs" />
<Compile Include="LoadedAssembly.cs" /> <Compile Include="LoadedAssembly.cs" />
@ -181,28 +181,8 @@
<Compile Include="TextView\EditorCommands.cs" /> <Compile Include="TextView\EditorCommands.cs" />
<Compile Include="TextView\FoldingCommands.cs" /> <Compile Include="TextView\FoldingCommands.cs" />
<Compile Include="TextView\XmlDocRenderer.cs" /> <Compile Include="TextView\XmlDocRenderer.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzeContextMenuEntry.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzedAssemblyTreeNode.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzedAttributeAppliedToTreeNode.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzedEventOverridesTreeNode.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzedEventTreeNode.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzedInterfacePropertyImplementedByTreeNode.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzedInterfaceMethodImplementedByTreeNode.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzedInterfaceEventImplementedByTreeNode.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzedEventFiredByTreeNode.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzedPropertyAccessorTreeNode.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzedTypeExposedByTreeNode.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzedTypeExtensionMethodsTreeNode.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzedTypeInstantiationsTreeNode.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzedTypeTreeNode.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzedEventAccessorTreeNode.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzedTypeUsedByTreeNode.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzedVirtualMethodUsedByTreeNode.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzerEntityTreeNode.cs" /> <Compile Include="TreeNodes\Analyzer\AnalyzerEntityTreeNode.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzerSearchTreeNode.cs" /> <Compile Include="TreeNodes\Analyzer\AnalyzerTreeNode.cs" />
<Compile Include="TreeNodes\Analyzer\RemoveAnalyzeContextMenuEntry.cs" />
<Compile Include="TreeNodes\Analyzer\Helpers.cs" />
<Compile Include="TreeNodes\Analyzer\ScopedWhereUsedAnalyzer.cs" />
<Compile Include="TreeNodes\BaseTypesEntryNode.cs" /> <Compile Include="TreeNodes\BaseTypesEntryNode.cs" />
<Compile Include="TreeNodes\CopyFullyQualifiedNameContextMenuEntry.cs" /> <Compile Include="TreeNodes\CopyFullyQualifiedNameContextMenuEntry.cs" />
<Compile Include="TreeNodes\DerivedTypesEntryNode.cs" /> <Compile Include="TreeNodes\DerivedTypesEntryNode.cs" />
@ -213,12 +193,12 @@
<Compile Include="TreeNodes\ResourceNodes\IconResourceEntryNode.cs" /> <Compile Include="TreeNodes\ResourceNodes\IconResourceEntryNode.cs" />
<Compile Include="TreeNodes\ResourceNodes\ImageListResourceEntryNode.cs" /> <Compile Include="TreeNodes\ResourceNodes\ImageListResourceEntryNode.cs" />
<Compile Include="TreeNodes\ResourceNodes\ImageResourceEntryNode.cs" /> <Compile Include="TreeNodes\ResourceNodes\ImageResourceEntryNode.cs" />
<Compile Include="TreeNodes\ResourceNodes\XmlResourceNode.cs" />
<Compile Include="TreeNodes\ResourceNodes\IResourceNodeFactory.cs" /> <Compile Include="TreeNodes\ResourceNodes\IResourceNodeFactory.cs" />
<Compile Include="TreeNodes\ResourceNodes\ResourceEntryNode.cs" />
<Compile Include="TreeNodes\ResourceNodes\ResourcesFileTreeNode.cs" /> <Compile Include="TreeNodes\ResourceNodes\ResourcesFileTreeNode.cs" />
<Compile Include="TreeNodes\ResourceNodes\ResourceTreeNode.cs" />
<Compile Include="TreeNodes\ResourceNodes\XamlResourceNode.cs" /> <Compile Include="TreeNodes\ResourceNodes\XamlResourceNode.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzedPropertyOverridesTreeNode.cs" /> <Compile Include="TreeNodes\ResourceNodes\XmlResourceNode.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzedPropertyTreeNode.cs" />
<Compile Include="TreeNodes\SearchMsdnContextMenuEntry.cs" /> <Compile Include="TreeNodes\SearchMsdnContextMenuEntry.cs" />
<EmbeddedResource Include="..\doc\LGPL.txt"> <EmbeddedResource Include="..\doc\LGPL.txt">
<Link>LGPL.txt</Link> <Link>LGPL.txt</Link>
@ -264,13 +244,6 @@
<Compile Include="TextView\ReferenceElementGenerator.cs" /> <Compile Include="TextView\ReferenceElementGenerator.cs" />
<Compile Include="TextView\AvalonEditTextOutput.cs" /> <Compile Include="TextView\AvalonEditTextOutput.cs" />
<Compile Include="TextView\UIElementGenerator.cs" /> <Compile Include="TextView\UIElementGenerator.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\AnalyzerTreeNode.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzedMethodOverridesTreeNode.cs" />
<Compile Include="TreeNodes\AssemblyListTreeNode.cs" /> <Compile Include="TreeNodes\AssemblyListTreeNode.cs" />
<Compile Include="TreeNodes\AssemblyReferenceTreeNode.cs" /> <Compile Include="TreeNodes\AssemblyReferenceTreeNode.cs" />
<Compile Include="TreeNodes\AssemblyTreeNode.cs" /> <Compile Include="TreeNodes\AssemblyTreeNode.cs" />
@ -284,9 +257,7 @@
<Compile Include="TreeNodes\NamespaceTreeNode.cs" /> <Compile Include="TreeNodes\NamespaceTreeNode.cs" />
<Compile Include="TreeNodes\PropertyTreeNode.cs" /> <Compile Include="TreeNodes\PropertyTreeNode.cs" />
<Compile Include="TreeNodes\ReferenceFolderTreeNode.cs" /> <Compile Include="TreeNodes\ReferenceFolderTreeNode.cs" />
<Compile Include="TreeNodes\ResourceNodes\ResourceEntryNode.cs" />
<Compile Include="TreeNodes\ResourceListTreeNode.cs" /> <Compile Include="TreeNodes\ResourceListTreeNode.cs" />
<Compile Include="TreeNodes\ResourceNodes\ResourceTreeNode.cs" />
<Compile Include="TreeNodes\ThreadingSupport.cs" /> <Compile Include="TreeNodes\ThreadingSupport.cs" />
<Compile Include="TreeNodes\TypeTreeNode.cs" /> <Compile Include="TreeNodes\TypeTreeNode.cs" />
<EmbeddedResource Include="README.txt" /> <EmbeddedResource Include="README.txt" />

49
ILSpy/Languages/CSharpLanguage.cs

@ -23,23 +23,21 @@ using System.ComponentModel.Composition;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Resources; using System.Resources;
using System.Windows;
using System.Windows.Controls;
using ICSharpCode.Decompiler; using ICSharpCode.Decompiler;
using ICSharpCode.ILSpy.Options;
using Mono.Cecil;
using ICSharpCode.Decompiler.CSharp; using ICSharpCode.Decompiler.CSharp;
using ICSharpCode.Decompiler.CSharp.OutputVisitor; using ICSharpCode.Decompiler.CSharp.OutputVisitor;
using ICSharpCode.Decompiler.CSharp.Syntax; using ICSharpCode.Decompiler.CSharp.Syntax;
using ICSharpCode.Decompiler.CSharp.Transforms;
using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem;
using System.Windows; using ICSharpCode.ILSpy.Options;
using System.Windows.Controls;
using ICSharpCode.ILSpy.TreeNodes; using ICSharpCode.ILSpy.TreeNodes;
using ICSharpCode.Decompiler.CSharp.Transforms; using Mono.Cecil;
using ICSharpCode.AvalonEdit.Highlighting;
using System.Windows.Media;
namespace ICSharpCode.ILSpy namespace ICSharpCode.ILSpy
{ {
#if false
/// <summary> /// <summary>
/// C# decompiler integration into ILSpy. /// C# decompiler integration into ILSpy.
/// Note: if you're interested in using the decompiler without the ILSpy UI, /// Note: if you're interested in using the decompiler without the ILSpy UI,
@ -252,40 +250,6 @@ namespace ICSharpCode.ILSpy
WriteCode(output, options.DecompilerSettings, decompiler.Decompile(type), decompiler.TypeSystem); WriteCode(output, options.DecompilerSettings, decompiler.Decompile(type), decompiler.TypeSystem);
} }
public static string GetPlatformDisplayName(ModuleDefinition module)
{
switch (module.Architecture) {
case TargetArchitecture.I386:
if ((module.Attributes & ModuleAttributes.Preferred32Bit) == ModuleAttributes.Preferred32Bit)
return "AnyCPU (32-bit preferred)";
else if ((module.Attributes & ModuleAttributes.Required32Bit) == ModuleAttributes.Required32Bit)
return "x86";
else
return "AnyCPU (64-bit preferred)";
case TargetArchitecture.AMD64:
return "x64";
case TargetArchitecture.IA64:
return "Itanium";
default:
return module.Architecture.ToString();
}
}
public static string GetRuntimeDisplayName(ModuleDefinition module)
{
switch (module.Runtime) {
case TargetRuntime.Net_1_0:
return ".NET 1.0";
case TargetRuntime.Net_1_1:
return ".NET 1.1";
case TargetRuntime.Net_2_0:
return ".NET 2.0";
case TargetRuntime.Net_4_0:
return ".NET 4.0";
}
return null;
}
void AddReferenceWarningMessage(AssemblyDefinition assembly, ITextOutput output) void AddReferenceWarningMessage(AssemblyDefinition assembly, ITextOutput output)
{ {
var loadedAssembly = MainWindow.Instance.CurrentAssemblyList.GetAssemblies().FirstOrDefault(la => la.GetAssemblyDefinitionOrNull() == assembly); var loadedAssembly = MainWindow.Instance.CurrentAssemblyList.GetAssemblies().FirstOrDefault(la => la.GetAssemblyDefinitionOrNull() == assembly);
@ -519,4 +483,5 @@ namespace ICSharpCode.ILSpy
return new CSharpAmbience() { ConversionFlags = flags }.ConvertSymbol(symbol); return new CSharpAmbience() { ConversionFlags = flags }.ConvertSymbol(symbol);
} }
} }
#endif
} }

4
ILSpy/Languages/ILAstLanguage.cs

@ -23,14 +23,14 @@ using System.Linq;
using ICSharpCode.Decompiler; using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.CSharp; using ICSharpCode.Decompiler.CSharp;
using ICSharpCode.Decompiler.Disassembler; using ICSharpCode.Decompiler.Disassembler;
using ICSharpCode.Decompiler.Dom;
using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.IL;
using ICSharpCode.Decompiler.IL.Transforms; using ICSharpCode.Decompiler.IL.Transforms;
using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem;
using Mono.Cecil;
namespace ICSharpCode.ILSpy namespace ICSharpCode.ILSpy
{ {
#if DEBUG #if false && DEBUG
/// <summary> /// <summary>
/// Represents the ILAst "language" used for debugging purposes. /// Represents the ILAst "language" used for debugging purposes.
/// </summary> /// </summary>

96
ILSpy/Languages/ILLanguage.cs

@ -25,6 +25,7 @@ using System.Reflection.Metadata;
using System.IO; using System.IO;
using System.Reflection.Metadata.Ecma335; using System.Reflection.Metadata.Ecma335;
using System.Linq; using System.Linq;
using ICSharpCode.Decompiler.Dom;
namespace ICSharpCode.ILSpy namespace ICSharpCode.ILSpy
{ {
@ -48,114 +49,99 @@ namespace ICSharpCode.ILSpy
get { return ".il"; } get { return ".il"; }
} }
protected virtual ReflectionDisassembler CreateDisassembler(ITextOutput output, PEReader reader, DecompilationOptions options) protected virtual ReflectionDisassembler CreateDisassembler(ITextOutput output, DecompilationOptions options)
{ {
return new ReflectionDisassembler(output, reader, options.CancellationToken) { return new ReflectionDisassembler(output, options.CancellationToken) {
DetectControlStructure = detectControlStructure, DetectControlStructure = detectControlStructure,
ShowSequencePoints = options.DecompilerSettings.ShowDebugInfo ShowSequencePoints = options.DecompilerSettings.ShowDebugInfo
}; };
} }
public override void DecompileMethod(Mono.Cecil.MethodDefinition method, ITextOutput output, DecompilationOptions options) public override void DecompileMethod(Decompiler.Dom.MethodDefinition method, ITextOutput output, DecompilationOptions options)
{ {
using (var reader = new PEReader(new FileStream(method.Module.FileName, FileMode.Open, FileAccess.Read))) { var dis = CreateDisassembler(output, options);
var dis = CreateDisassembler(output, reader, options); dis.DisassembleMethod(method);
dis.DisassembleMethod(MetadataTokens.MethodDefinitionHandle(method.MetadataToken.ToInt32()));
}
} }
public override void DecompileField(Mono.Cecil.FieldDefinition field, ITextOutput output, DecompilationOptions options) public override void DecompileField(Decompiler.Dom.FieldDefinition field, ITextOutput output, DecompilationOptions options)
{ {
using (var reader = new PEReader(new FileStream(field.Module.FileName, FileMode.Open, FileAccess.Read))) { var dis = CreateDisassembler(output, options);
var dis = CreateDisassembler(output, reader, options); dis.DisassembleField(field);
dis.DisassembleField(MetadataTokens.FieldDefinitionHandle(field.MetadataToken.ToInt32()));
}
} }
public override void DecompileProperty(Mono.Cecil.PropertyDefinition property, ITextOutput output, DecompilationOptions options) public override void DecompileProperty(Decompiler.Dom.PropertyDefinition property, ITextOutput output, DecompilationOptions options)
{ {
using (var reader = new PEReader(new FileStream(property.Module.FileName, FileMode.Open, FileAccess.Read))) { var dis = CreateDisassembler(output, options);
var dis = CreateDisassembler(output, reader, options); dis.DisassembleProperty(property);
dis.DisassembleProperty(MetadataTokens.PropertyDefinitionHandle(property.MetadataToken.ToInt32()));
if (property.GetMethod != null) { if (!property.GetMethod.IsNil) {
output.WriteLine(); output.WriteLine();
dis.DisassembleMethod(MetadataTokens.MethodDefinitionHandle(property.GetMethod.MetadataToken.ToInt32())); dis.DisassembleMethod(property.GetMethod);
} }
if (property.SetMethod != null) { if (!property.SetMethod.IsNil) {
output.WriteLine(); output.WriteLine();
dis.DisassembleMethod(MetadataTokens.MethodDefinitionHandle(property.SetMethod.MetadataToken.ToInt32())); dis.DisassembleMethod(property.SetMethod);
} }
foreach (var m in property.OtherMethods) { foreach (var m in property.OtherMethods) {
output.WriteLine(); output.WriteLine();
dis.DisassembleMethod(MetadataTokens.MethodDefinitionHandle(m.MetadataToken.ToInt32())); dis.DisassembleMethod(m);
}
} }
} }
public override void DecompileEvent(Mono.Cecil.EventDefinition ev, ITextOutput output, DecompilationOptions options) public override void DecompileEvent(Decompiler.Dom.EventDefinition ev, ITextOutput output, DecompilationOptions options)
{ {
using (var reader = new PEReader(new FileStream(ev.Module.FileName, FileMode.Open, FileAccess.Read))) { var dis = CreateDisassembler(output, options);
var dis = CreateDisassembler(output, reader, options); dis.DisassembleEvent(ev);
dis.DisassembleEvent(MetadataTokens.EventDefinitionHandle(ev.MetadataToken.ToInt32())); if (!ev.AddMethod.IsNil) {
if (ev.AddMethod != null) {
output.WriteLine(); output.WriteLine();
dis.DisassembleMethod(MetadataTokens.MethodDefinitionHandle(ev.AddMethod.MetadataToken.ToInt32())); dis.DisassembleMethod(ev.AddMethod);
} }
if (ev.RemoveMethod != null) { if (!ev.RemoveMethod.IsNil) {
output.WriteLine(); output.WriteLine();
dis.DisassembleMethod(MetadataTokens.MethodDefinitionHandle(ev.RemoveMethod.MetadataToken.ToInt32())); dis.DisassembleMethod(ev.RemoveMethod);
} }
foreach (var m in ev.OtherMethods) { foreach (var m in ev.OtherMethods) {
output.WriteLine(); output.WriteLine();
dis.DisassembleMethod(MetadataTokens.MethodDefinitionHandle(m.MetadataToken.ToInt32())); dis.DisassembleMethod(m);
}
} }
} }
public override void DecompileType(Mono.Cecil.TypeDefinition type, ITextOutput output, DecompilationOptions options) public override void DecompileType(Decompiler.Dom.TypeDefinition type, ITextOutput output, DecompilationOptions options)
{ {
using (var reader = new PEReader(new FileStream(type.Module.FileName, FileMode.Open, FileAccess.Read))) { var dis = CreateDisassembler(output, options);
var dis = CreateDisassembler(output, reader, options); dis.DisassembleType(type);
dis.DisassembleType(MetadataTokens.TypeDefinitionHandle(type.MetadataToken.ToInt32()));
}
} }
public override void DecompileNamespace(string nameSpace, IEnumerable<Mono.Cecil.TypeDefinition> types, ITextOutput output, DecompilationOptions options) public override void DecompileNamespace(string nameSpace, IEnumerable<Decompiler.Dom.TypeDefinition> types, ITextOutput output, DecompilationOptions options)
{ {
if (!types.Any()) var dis = CreateDisassembler(output, options);
return; dis.DisassembleNamespace(nameSpace, types);
using (var reader = new PEReader(new FileStream(types.First().Module.FileName, FileMode.Open, FileAccess.Read))) {
var dis = CreateDisassembler(output, reader, options);
dis.DisassembleNamespace(nameSpace, types.Select(t => MetadataTokens.TypeDefinitionHandle(t.MetadataToken.ToInt32())));
}
} }
public override void DecompileAssembly(LoadedAssembly assembly, ITextOutput output, DecompilationOptions options) public override void DecompileAssembly(LoadedAssembly assembly, ITextOutput output, DecompilationOptions options)
{ {
output.WriteLine("// " + assembly.FileName); output.WriteLine("// " + assembly.FileName);
output.WriteLine(); output.WriteLine();
using (var reader = new PEReader(new FileStream(assembly.FileName, FileMode.Open, FileAccess.Read))) { var module = assembly.GetPEFileOrNull();
var dis = CreateDisassembler(output, reader, options); var metadata = module.GetMetadataReader();
var module = assembly.GetModuleDefinitionAsync().Result; var dis = CreateDisassembler(output, options);
if (options.FullDecompilation) if (options.FullDecompilation)
dis.WriteAssemblyReferences(); dis.WriteAssemblyReferences(module);
if (module.Assembly != null) if (metadata.IsAssembly)
dis.WriteAssemblyHeader(); dis.WriteAssemblyHeader(module);
output.WriteLine(); output.WriteLine();
dis.WriteModuleHeader(); dis.WriteModuleHeader(module);
if (options.FullDecompilation) { if (options.FullDecompilation) {
output.WriteLine(); output.WriteLine();
output.WriteLine(); output.WriteLine();
dis.WriteModuleContents(reader.GetMetadataReader().GetModuleDefinition()); dis.WriteModuleContents(module);
}
} }
} }
public override string TypeToString(Mono.Cecil.TypeReference type, bool includeNamespace, Mono.Cecil.ICustomAttributeProvider typeAttributes = null) public override string TypeToString(Decompiler.Dom.ITypeReference type, bool includeNamespace, Decompiler.Dom.ICustomAttributeProvider typeAttributes = null)
{ {
PlainTextOutput output = new PlainTextOutput(); PlainTextOutput output = new PlainTextOutput();
type.WriteTo(output, includeNamespace ? ILNameSyntax.TypeName : ILNameSyntax.ShortTypeName); type.WriteTo(output, GenericContext.Empty, includeNamespace ? ILNameSyntax.TypeName : ILNameSyntax.ShortTypeName);
return output.ToString(); return output.ToString();
} }
} }

86
ILSpy/Languages/ITypeProvider.cs

@ -0,0 +1,86 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Reflection.Metadata;
using System.Text;
using System.Threading.Tasks;
using ICSharpCode.Decompiler.Dom;
namespace ICSharpCode.ILSpy
{
public sealed class CSharpSignatureTypeProvider : ISignatureTypeProvider<string, GenericContext>
{
public string GetArrayType(string elementType, ArrayShape shape)
{
throw new NotImplementedException();
}
public string GetByReferenceType(string elementType)
{
throw new NotImplementedException();
}
public string GetFunctionPointerType(MethodSignature<string> signature)
{
throw new NotImplementedException();
}
public string GetGenericInstantiation(string genericType, ImmutableArray<string> typeArguments)
{
throw new NotImplementedException();
}
public string GetGenericMethodParameter(GenericContext genericContext, int index)
{
throw new NotImplementedException();
}
public string GetGenericTypeParameter(GenericContext genericContext, int index)
{
throw new NotImplementedException();
}
public string GetModifiedType(string modifier, string unmodifiedType, bool isRequired)
{
throw new NotImplementedException();
}
public string GetPinnedType(string elementType)
{
throw new NotImplementedException();
}
public string GetPointerType(string elementType)
{
throw new NotImplementedException();
}
public string GetPrimitiveType(PrimitiveTypeCode typeCode)
{
throw new NotImplementedException();
}
public string GetSZArrayType(string elementType)
{
throw new NotImplementedException();
}
public string GetTypeFromDefinition(MetadataReader reader, TypeDefinitionHandle handle, byte rawTypeKind)
{
throw new NotImplementedException();
}
public string GetTypeFromReference(MetadataReader reader, TypeReferenceHandle handle, byte rawTypeKind)
{
throw new NotImplementedException();
}
public string GetTypeFromSpecification(MetadataReader reader, GenericContext genericContext, TypeSpecificationHandle handle, byte rawTypeKind)
{
throw new NotImplementedException();
}
}
}

242
ILSpy/Languages/Language.cs

@ -18,8 +18,13 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable;
using System.Reflection.PortableExecutable;
using ICSharpCode.Decompiler; using ICSharpCode.Decompiler;
using Mono.Cecil; using ICSharpCode.Decompiler.Dom;
using static System.Reflection.Metadata.PEReaderExtensions;
using SRM = System.Reflection.Metadata;
namespace ICSharpCode.ILSpy namespace ICSharpCode.ILSpy
{ {
@ -87,16 +92,18 @@ namespace ICSharpCode.ILSpy
public virtual void DecompileAssembly(LoadedAssembly assembly, ITextOutput output, DecompilationOptions options) public virtual void DecompileAssembly(LoadedAssembly assembly, ITextOutput output, DecompilationOptions options)
{ {
WriteCommentLine(output, assembly.FileName); WriteCommentLine(output, assembly.FileName);
var asm = assembly.GetAssemblyDefinitionOrNull(); var asm = assembly.GetPEFileOrNull();
if (asm != null) { if (asm == null) return;
var name = asm.Name; var reader = asm.GetMetadataReader();
if (name.IsWindowsRuntime) { if (reader.IsAssembly) {
var name = reader.GetAssemblyDefinition();
if ((name.Flags & System.Reflection.AssemblyFlags.WindowsRuntime) != 0) {
WriteCommentLine(output, name.Name + " [WinRT]"); WriteCommentLine(output, name.Name + " [WinRT]");
} else { } else {
WriteCommentLine(output, name.FullName); WriteCommentLine(output, reader.GetFullAssemblyName());
} }
} else { } else {
WriteCommentLine(output, assembly.GetModuleDefinitionAsync().Result.Name); WriteCommentLine(output, reader.GetString(reader.GetModuleDefinition().Name));
} }
} }
@ -108,57 +115,69 @@ namespace ICSharpCode.ILSpy
/// <summary> /// <summary>
/// Converts a type reference into a string. This method is used by the member tree node for parameter and return types. /// Converts a type reference into a string. This method is used by the member tree node for parameter and return types.
/// </summary> /// </summary>
public virtual string TypeToString(TypeReference type, bool includeNamespace, ICustomAttributeProvider typeAttributes = null) public virtual string TypeToString(ITypeReference type, bool includeNamespace, ICustomAttributeProvider typeAttributes = null)
{ {
if (includeNamespace) if (includeNamespace)
return type.FullName; return type.FullName.ToString();
else else
return type.Name; return type.Name;
} }
public virtual SRM.ISignatureTypeProvider<string, GenericContext> CreateSignatureTypeProvider(bool includeNamespace)
{
return new ILSignatureProvider(includeNamespace);
}
/// <summary> /// <summary>
/// Converts a member signature to a string. /// Converts a member signature to a string.
/// This is used for displaying the tooltip on a member reference. /// This is used for displaying the tooltip on a member reference.
/// </summary> /// </summary>
public virtual string GetTooltip(MemberReference member) public virtual string GetTooltip(IMemberReference member)
{ {
if (member is TypeReference) return member.Name;
return TypeToString((TypeReference)member, true); }
else
return member.ToString(); /// <summary>
/// Converts a member signature to a string.
/// This is used for displaying the tooltip on a member reference.
/// </summary>
public virtual string GetTooltip(ITypeReference type)
{
return TypeToString(type, true);
} }
public virtual string FormatFieldName(FieldDefinition field) public virtual string FormatFieldName(FieldDefinition field)
{ {
if (field == null) if (field.Handle.IsNil)
throw new ArgumentNullException(nameof(field)); throw new ArgumentNullException(nameof(field));
return field.Name; return field.Name;
} }
public virtual string FormatPropertyName(PropertyDefinition property, bool? isIndexer = null) public virtual string FormatPropertyName(PropertyDefinition property, bool? isIndexer = null)
{ {
if (property == null) if (property.Handle.IsNil)
throw new ArgumentNullException(nameof(property)); throw new ArgumentNullException(nameof(property));
return property.Name; return property.Name;
} }
public virtual string FormatMethodName(MethodDefinition method) public virtual string FormatMethodName(MethodDefinition method)
{ {
if (method == null) if (method.Handle.IsNil)
throw new ArgumentNullException(nameof(method)); throw new ArgumentNullException(nameof(method));
return method.Name; return method.Name;
} }
public virtual string FormatEventName(EventDefinition @event) public virtual string FormatEventName(EventDefinition @event)
{ {
if (@event == null) if (@event.Handle.IsNil)
throw new ArgumentNullException(nameof(@event)); throw new ArgumentNullException(nameof(@event));
return @event.Name; return @event.Name;
} }
public virtual string FormatTypeName(TypeDefinition type) public virtual string FormatTypeName(TypeDefinition type)
{ {
if (type == null) if (type.Handle.IsNil)
throw new ArgumentNullException(nameof(type)); throw new ArgumentNullException(nameof(type));
return type.Name; return type.Name;
} }
@ -171,7 +190,7 @@ namespace ICSharpCode.ILSpy
return Name; return Name;
} }
public virtual bool ShowMember(MemberReference member) public virtual bool ShowMember(IMemberReference member)
{ {
return true; return true;
} }
@ -179,9 +198,190 @@ namespace ICSharpCode.ILSpy
/// <summary> /// <summary>
/// Used by the analyzer to map compiler generated code back to the original code's location /// Used by the analyzer to map compiler generated code back to the original code's location
/// </summary> /// </summary>
public virtual MemberReference GetOriginalCodeLocation(MemberReference member) public virtual IMemberReference GetOriginalCodeLocation(IMemberReference member)
{ {
return member; return member;
} }
public static string GetPlatformDisplayName(PEFile module)
{
var architecture = module.Reader.PEHeaders.CoffHeader.Machine;
var flags = module.Reader.PEHeaders.CorHeader.Flags;
switch (architecture) {
case Machine.I386:
if ((flags & CorFlags.Prefers32Bit) != 0)
return "AnyCPU (32-bit preferred)";
else if ((flags & CorFlags.Requires32Bit) != 0)
return "x86";
else
return "AnyCPU (64-bit preferred)";
case Machine.Amd64:
return "x64";
case Machine.IA64:
return "Itanium";
default:
return architecture.ToString();
}
}
public static string GetRuntimeDisplayName(PEFile module)
{
string version = module.GetMetadataReader().MetadataVersion;
switch (version[1]) {
case '1':
if (version[3] == 1)
return ".NET 1.1";
else
return ".NET 1.0";
case '2':
return ".NET 2.0";
case '4':
return ".NET 4.0";
}
return null;
}
}
class ILSignatureProvider : SRM.ISignatureTypeProvider<string, GenericContext>
{
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)
{
throw new NotImplementedException();
}
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)
{
throw new NotImplementedException();
}
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:
break;
case SRM.PrimitiveTypeCode.Object:
return "object";
case SRM.PrimitiveTypeCode.String:
return "string";
case SRM.PrimitiveTypeCode.TypedReference:
break;
case SRM.PrimitiveTypeCode.Void:
return "void";
default:
break;
}
throw new NotImplementedException();
}
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);
}
} }
} }

4
ILSpy/Languages/Languages.cs

@ -45,8 +45,8 @@ namespace ICSharpCode.ILSpy
languages.AddRange(composition.GetExportedValues<Language>()); languages.AddRange(composition.GetExportedValues<Language>());
languages.Sort((a, b) => a.Name.CompareTo(b.Name)); languages.Sort((a, b) => a.Name.CompareTo(b.Name));
#if DEBUG #if DEBUG
languages.AddRange(ILAstLanguage.GetDebugLanguages()); //languages.AddRange(ILAstLanguage.GetDebugLanguages());
languages.AddRange(CSharpLanguage.GetDebugLanguages()); //languages.AddRange(CSharpLanguage.GetDebugLanguages());
#endif #endif
allLanguages = languages.AsReadOnly(); allLanguages = languages.AsReadOnly();
} }

118
ILSpy/LoadedAssembly.cs

@ -19,13 +19,14 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Reflection.PortableExecutable;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows.Threading;
using ICSharpCode.Decompiler; using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Dom;
using ICSharpCode.ILSpy.Options; using ICSharpCode.ILSpy.Options;
using Mono.Cecil;
using static System.Reflection.Metadata.PEReaderExtensions;
namespace ICSharpCode.ILSpy namespace ICSharpCode.ILSpy
{ {
@ -34,21 +35,17 @@ namespace ICSharpCode.ILSpy
/// </summary> /// </summary>
public sealed class LoadedAssembly public sealed class LoadedAssembly
{ {
readonly Task<ModuleDefinition> assemblyTask; readonly Task<PEFile> assemblyTask;
readonly AssemblyList assemblyList; readonly AssemblyList assemblyList;
readonly string fileName; readonly string fileName;
readonly string shortName; readonly string shortName;
public LoadedAssembly(AssemblyList assemblyList, string fileName, Stream stream = null) public LoadedAssembly(AssemblyList assemblyList, string fileName, Stream stream = null)
{ {
if (assemblyList == null) this.assemblyList = assemblyList ?? throw new ArgumentNullException(nameof(assemblyList));
throw new ArgumentNullException(nameof(assemblyList)); this.fileName = fileName ?? throw new ArgumentNullException(nameof(fileName));
if (fileName == null)
throw new ArgumentNullException(nameof(fileName)); this.assemblyTask = Task.Factory.StartNew(LoadAssembly, stream); // requires that this.fileName is set
this.assemblyList = assemblyList;
this.fileName = fileName;
this.assemblyTask = Task.Factory.StartNew<ModuleDefinition>(LoadAssembly, stream); // requires that this.fileName is set
this.shortName = Path.GetFileNameWithoutExtension(fileName); this.shortName = Path.GetFileNameWithoutExtension(fileName);
} }
@ -58,8 +55,8 @@ namespace ICSharpCode.ILSpy
/// </summary> /// </summary>
public async Task<string> GetTargetFrameworkIdAsync() public async Task<string> GetTargetFrameworkIdAsync()
{ {
var assembly = await GetAssemblyDefinitionAsync().ConfigureAwait(false); var assembly = await GetPEFileAsync().ConfigureAwait(false);
return assembly?.DetectTargetFrameworkId() ?? string.Empty; return assembly.Reader.DetectTargetFrameworkId() ?? string.Empty;
} }
public ReferenceLoadInfo LoadedAssemblyReferencesInfo { get; } = new ReferenceLoadInfo(); public ReferenceLoadInfo LoadedAssemblyReferencesInfo { get; } = new ReferenceLoadInfo();
@ -67,7 +64,7 @@ namespace ICSharpCode.ILSpy
/// <summary> /// <summary>
/// Gets the Cecil ModuleDefinition. /// Gets the Cecil ModuleDefinition.
/// </summary> /// </summary>
public Task<ModuleDefinition> GetModuleDefinitionAsync() public Task<PEFile> GetPEFileAsync()
{ {
return assemblyTask; return assemblyTask;
} }
@ -76,33 +73,10 @@ namespace ICSharpCode.ILSpy
/// Gets the Cecil ModuleDefinition. /// Gets the Cecil ModuleDefinition.
/// Returns null in case of load errors. /// Returns null in case of load errors.
/// </summary> /// </summary>
public ModuleDefinition GetModuleDefinitionOrNull() public PEFile GetPEFileOrNull()
{ {
try { try {
return GetModuleDefinitionAsync().Result; return GetPEFileAsync().Result;
} catch (Exception ex) {
System.Diagnostics.Trace.TraceError(ex.ToString());
return null;
}
}
/// <summary>
/// Gets the Cecil AssemblyDefinition.
/// </summary>
public async Task<AssemblyDefinition> GetAssemblyDefinitionAsync()
{
var module = await assemblyTask.ConfigureAwait(false);
return module != null ? module.Assembly : null;
}
/// <summary>
/// Gets the Cecil AssemblyDefinition.
/// Returns null when there was a load error; or when opening a netmodule.
/// </summary>
public AssemblyDefinition GetAssemblyDefinitionOrNull()
{
try {
return GetAssemblyDefinitionAsync().Result;
} catch (Exception ex) { } catch (Exception ex) {
System.Diagnostics.Trace.TraceError(ex.ToString()); System.Diagnostics.Trace.TraceError(ex.ToString());
return null; return null;
@ -118,7 +92,7 @@ namespace ICSharpCode.ILSpy
public string Text { public string Text {
get { get {
if (IsLoaded && !HasLoadError) { if (IsLoaded && !HasLoadError) {
string version = GetAssemblyDefinitionOrNull()?.Name.Version.ToString(); string version = GetPEFileOrNull()?.Reader.GetAssemblyDefinition()?.Version.ToString();
if (version == null) if (version == null)
return ShortName; return ShortName;
return String.Format("{0} ({1})", ShortName, version); return String.Format("{0} ({1})", ShortName, version);
@ -134,25 +108,26 @@ namespace ICSharpCode.ILSpy
public bool IsAutoLoaded { get; set; } public bool IsAutoLoaded { get; set; }
ModuleDefinition LoadAssembly(object state) PEFile LoadAssembly(object state)
{ {
var stream = state as Stream; var stream = state as Stream;
ModuleDefinition module; PEReader module;
// runs on background thread // runs on background thread
ReaderParameters p = new ReaderParameters();
p.AssemblyResolver = new MyAssemblyResolver(this);
p.InMemory = true;
if (stream != null) if (stream != null)
{ {
// Read the module from a precrafted stream // Read the module from a precrafted stream
module = ModuleDefinition.ReadModule(stream, p); module = new PEReader(stream);
} }
else else
{ {
// Read the module from disk (by default) // Read the module from disk (by default)
module = ModuleDefinition.ReadModule(fileName, p); using (var fs = new FileStream(fileName, FileMode.Open, FileAccess.Read)) {
var ms = new MemoryStream();
fs.CopyTo(ms);
ms.Position = 0;
module = new PEReader(ms, PEStreamOptions.PrefetchEntireImage);
}
} }
if (DecompilerSettingsPanel.CurrentDecompilerSettings.UseDebugSymbols) { if (DecompilerSettingsPanel.CurrentDecompilerSettings.UseDebugSymbols) {
@ -164,17 +139,18 @@ namespace ICSharpCode.ILSpy
// ignore any errors during symbol loading // ignore any errors during symbol loading
} }
} }
return module; return new PEFile(fileName, module, new MyAssemblyResolver(this));
} }
private void LoadSymbols(ModuleDefinition module) private void LoadSymbols(PEReader reader)
{ {
if (!module.HasDebugHeader) { /*string pdbDirectory = Path.GetDirectoryName(fileName);
if (!reader.TryOpenAssociatedPortablePdb(pdbDirectory, OpenStream, out var provider, out var pdbFileName) {
return; return;
} }
// search for pdb in same directory as dll // search for pdb in same directory as dll
string pdbName = Path.Combine(Path.GetDirectoryName(fileName), Path.GetFileNameWithoutExtension(fileName) + ".pdb"); string pdbName = Path.Combine(, Path.GetFileNameWithoutExtension(fileName) + ".pdb");
if (File.Exists(pdbName)) { if (File.Exists(pdbName)) {
using (Stream s = File.OpenRead(pdbName)) { using (Stream s = File.OpenRead(pdbName)) {
module.ReadSymbols(new Mono.Cecil.Pdb.PdbReaderProvider().GetSymbolReader(module, s)); module.ReadSymbols(new Mono.Cecil.Pdb.PdbReaderProvider().GetSymbolReader(module, s));
@ -183,6 +159,11 @@ namespace ICSharpCode.ILSpy
} }
// TODO: use symbol cache, get symbols from microsoft // TODO: use symbol cache, get symbols from microsoft
Stream OpenStream(string pdbFileName)
{
}*/
} }
[ThreadStatic] [ThreadStatic]
@ -218,18 +199,9 @@ namespace ICSharpCode.ILSpy
this.parent = parent; this.parent = parent;
} }
public AssemblyDefinition Resolve(AssemblyNameReference name) public PEFile Resolve(IAssemblyReference reference)
{
return parent.LookupReferencedAssembly(name)?.GetAssemblyDefinitionOrNull();
}
public AssemblyDefinition Resolve(AssemblyNameReference name, ReaderParameters parameters)
{
return parent.LookupReferencedAssembly(name)?.GetAssemblyDefinitionOrNull();
}
public void Dispose()
{ {
return parent.LookupReferencedAssembly(reference)?.GetPEFileOrNull();
} }
} }
@ -238,14 +210,12 @@ namespace ICSharpCode.ILSpy
return new MyAssemblyResolver(this); return new MyAssemblyResolver(this);
} }
public LoadedAssembly LookupReferencedAssembly(AssemblyNameReference name) public LoadedAssembly LookupReferencedAssembly(IAssemblyReference reference)
{ {
if (name == null) if (reference.IsWindowsRuntime) {
throw new ArgumentNullException(nameof(name)); return assemblyList.assemblyLookupCache.GetOrAdd((reference.Name, true), LookupReferencedAssemblyInternal);
if (name.IsWindowsRuntime) {
return assemblyList.assemblyLookupCache.GetOrAdd((name.Name, true), LookupReferencedAssemblyInternal);
} else { } else {
return assemblyList.assemblyLookupCache.GetOrAdd((name.FullName, false), LookupReferencedAssemblyInternal); return assemblyList.assemblyLookupCache.GetOrAdd((reference.FullName, false), LookupReferencedAssemblyInternal);
} }
} }
@ -265,8 +235,10 @@ namespace ICSharpCode.ILSpy
LoadedAssembly asm; LoadedAssembly asm;
lock (loadingAssemblies) { lock (loadingAssemblies) {
foreach (LoadedAssembly loaded in assemblyList.GetAssemblies()) { foreach (LoadedAssembly loaded in assemblyList.GetAssemblies()) {
var asmDef = loaded.GetAssemblyDefinitionOrNull(); var reader = loaded.GetPEFileOrNull()?.GetMetadataReader();
if (asmDef != null && data.fullName.Equals(data.isWinRT ? asmDef.Name.Name : asmDef.FullName, StringComparison.OrdinalIgnoreCase)) { if (reader == null || !reader.IsAssembly) continue;
var asmDef = reader.GetAssemblyDefinition();
if (data.fullName.Equals(data.isWinRT ? reader.GetString(asmDef.Name) : reader.GetFullAssemblyName(), StringComparison.OrdinalIgnoreCase)) {
LoadedAssemblyReferencesInfo.AddMessageOnce(data.fullName, MessageKind.Info, "Success - Found in Assembly List"); LoadedAssemblyReferencesInfo.AddMessageOnce(data.fullName, MessageKind.Info, "Success - Found in Assembly List");
return loaded; return loaded;
} }
@ -312,7 +284,7 @@ namespace ICSharpCode.ILSpy
return asm; return asm;
} }
public Task ContinueWhenLoaded(Action<Task<ModuleDefinition>> onAssemblyLoaded, TaskScheduler taskScheduler) public Task ContinueWhenLoaded(Action<Task<PEFile>> onAssemblyLoaded, TaskScheduler taskScheduler)
{ {
return this.assemblyTask.ContinueWith(onAssemblyLoaded, default(CancellationToken), TaskContinuationOptions.RunContinuationsAsynchronously, taskScheduler); return this.assemblyTask.ContinueWith(onAssemblyLoaded, default(CancellationToken), TaskContinuationOptions.RunContinuationsAsynchronously, taskScheduler);
} }

19
ILSpy/MainWindow.xaml.cs

@ -38,7 +38,6 @@ using ICSharpCode.ILSpy.TextView;
using ICSharpCode.ILSpy.TreeNodes; using ICSharpCode.ILSpy.TreeNodes;
using ICSharpCode.TreeView; using ICSharpCode.TreeView;
using Microsoft.Win32; using Microsoft.Win32;
using Mono.Cecil;
namespace ICSharpCode.ILSpy namespace ICSharpCode.ILSpy
{ {
@ -273,14 +272,14 @@ namespace ICSharpCode.ILSpy
} }
} else { } else {
foreach (LoadedAssembly asm in commandLineLoadedAssemblies) { foreach (LoadedAssembly asm in commandLineLoadedAssemblies) {
ModuleDefinition def = asm.GetModuleDefinitionOrNull(); var def = asm.GetPEFileOrNull();
if (def != null) { if (def != null) {
MemberReference mr = XmlDocKeyProvider.FindMemberByKey(def, args.NavigateTo); /*MemberReference mr = XmlDocKeyProvider.FindMemberByKey(def, args.NavigateTo);
if (mr != null) { if (mr != null) {
found = true; found = true;
JumpToReference(mr); JumpToReference(mr);
break; break;
} }*/
} }
} }
} }
@ -292,7 +291,7 @@ namespace ICSharpCode.ILSpy
} else if (commandLineLoadedAssemblies.Count == 1) { } else if (commandLineLoadedAssemblies.Count == 1) {
// NavigateTo == null and an assembly was given on the command-line: // NavigateTo == null and an assembly was given on the command-line:
// Select the newly loaded assembly // Select the newly loaded assembly
JumpToReference(commandLineLoadedAssemblies[0].GetModuleDefinitionOrNull()); JumpToReference(commandLineLoadedAssemblies[0].GetPEFileOrNull());
} }
if (args.Search != null) if (args.Search != null)
{ {
@ -577,7 +576,7 @@ namespace ICSharpCode.ILSpy
public ILSpyTreeNode FindTreeNode(object reference) public ILSpyTreeNode FindTreeNode(object reference)
{ {
if (reference is TypeReference) /*if (reference is TypeReference)
{ {
return assemblyListTreeNode.FindTypeNode(((TypeReference)reference).Resolve()); return assemblyListTreeNode.FindTypeNode(((TypeReference)reference).Resolve());
} }
@ -597,7 +596,7 @@ namespace ICSharpCode.ILSpy
{ {
return assemblyListTreeNode.FindEventNode(((EventReference)reference).Resolve()); return assemblyListTreeNode.FindEventNode(((EventReference)reference).Resolve());
} }
else if (reference is AssemblyDefinition) else if (reference is PEFile)
{ {
return assemblyListTreeNode.FindAssemblyNode((AssemblyDefinition)reference); return assemblyListTreeNode.FindAssemblyNode((AssemblyDefinition)reference);
} }
@ -607,12 +606,14 @@ namespace ICSharpCode.ILSpy
} }
else if (reference is Resource) else if (reference is Resource)
{ {
return assemblyListTreeNode.FindResourceNode((Resource)reference); return null;
//return assemblyListTreeNode.FindResourceNode((Resource)reference);
} }
else else
{ {
return null; return null;
} }*/
return null;
} }
public void JumpToReference(object reference) public void JumpToReference(object reference)

8
ILSpy/SearchPane.cs

@ -26,7 +26,7 @@ using System.Windows.Controls;
using System.Windows.Input; using System.Windows.Input;
using System.Windows.Media; using System.Windows.Media;
using System.Windows.Threading; using System.Windows.Threading;
using ICSharpCode.Decompiler.Dom;
using ICSharpCode.ILSpy.TreeNodes; using ICSharpCode.ILSpy.TreeNodes;
using Mono.Cecil; using Mono.Cecil;
@ -216,12 +216,12 @@ namespace ICSharpCode.ILSpy
try { try {
var searcher = GetSearchStrategy(searchMode, searchTerm); var searcher = GetSearchStrategy(searchMode, searchTerm);
foreach (var loadedAssembly in assemblies) { foreach (var loadedAssembly in assemblies) {
ModuleDefinition module = loadedAssembly.GetModuleDefinitionOrNull(); var module = loadedAssembly.GetPEFileOrNull();
if (module == null) if (module == null)
continue; continue;
CancellationToken cancellationToken = cts.Token; CancellationToken cancellationToken = cts.Token;
foreach (TypeDefinition type in module.Types) { foreach (var type in module.TypeDefinitions) {
cancellationToken.ThrowIfCancellationRequested(); cancellationToken.ThrowIfCancellationRequested();
searcher.Search(type, language, AddResult); searcher.Search(type, language, AddResult);
} }
@ -333,7 +333,7 @@ namespace ICSharpCode.ILSpy
public static readonly System.Collections.Generic.IComparer<SearchResult> Comparer = new SearchResultComparer(); public static readonly System.Collections.Generic.IComparer<SearchResult> Comparer = new SearchResultComparer();
public MemberReference Member { get; set; } public IMemberReference Member { get; set; }
public float Fitness { get; set; } public float Fitness { get; set; }
public string Location { get; set; } public string Location { get; set; }

113
ILSpy/SearchStrategies.cs

@ -3,11 +3,12 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Windows.Media; using System.Windows.Media;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.Util; using ICSharpCode.Decompiler.Util;
using ICSharpCode.ILSpy.TreeNodes; using ICSharpCode.ILSpy.TreeNodes;
using Mono.Cecil; using ICSharpCode.Decompiler.Dom;
using Code = Mono.Cecil.Cil.Code; using System.Reflection;
using ICSharpCode.Decompiler.Disassembler;
using ILOpCode = System.Reflection.Metadata.ILOpCode;
namespace ICSharpCode.ILSpy namespace ICSharpCode.ILSpy
{ {
@ -37,7 +38,7 @@ namespace ICSharpCode.ILSpy
searchTerm = terms; searchTerm = terms;
} }
protected float CalculateFitness(MemberReference member) protected float CalculateFitness(IMemberReference member)
{ {
string text = member.Name; string text = member.Name;
@ -49,11 +50,11 @@ namespace ICSharpCode.ILSpy
// Constructors always have the same name in IL: // Constructors always have the same name in IL:
// Use type name instead // Use type name instead
if (text == ".cctor" || text == ".ctor") { 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 // Ignore generic arguments, it not possible to search based on them either
text = ReflectionHelper.SplitTypeParameterCountFromReflectionName(text); text = Decompiler.TypeSystem.ReflectionHelper.SplitTypeParameterCountFromReflectionName(text);
return 1.0f / text.Length; return 1.0f / text.Length;
} }
@ -139,7 +140,7 @@ namespace ICSharpCode.ILSpy
} }
} }
void Add<T>(IEnumerable<T> items, TypeDefinition type, Language language, Action<SearchResult> addResult, Func<T, Language, bool> matcher, Func<T, ImageSource> image) where T : MemberReference void Add<T>(IEnumerable<T> items, TypeDefinition type, Language language, Action<SearchResult> addResult, Func<T, Language, bool> matcher, Func<T, ImageSource> image) where T : IMemberReference
{ {
foreach (var item in items) { foreach (var item in items) {
if (matcher(item, language)) { if (matcher(item, language)) {
@ -170,12 +171,12 @@ namespace ICSharpCode.ILSpy
bool NotSpecialMethod(MethodDefinition arg) bool NotSpecialMethod(MethodDefinition arg)
{ {
return (arg.SemanticsAttributes & ( return (arg.GetMethodSemanticsAttributes() & (
MethodSemanticsAttributes.Setter MethodSemanticsAttributes.Setter
| MethodSemanticsAttributes.Getter | MethodSemanticsAttributes.Getter
| MethodSemanticsAttributes.AddOn | MethodSemanticsAttributes.Adder
| MethodSemanticsAttributes.RemoveOn | MethodSemanticsAttributes.Remover
| MethodSemanticsAttributes.Fire)) == 0; | MethodSemanticsAttributes.Raiser)) == 0;
} }
Regex SafeNewRegex(string unsafePattern) Regex SafeNewRegex(string unsafePattern)
@ -227,7 +228,7 @@ namespace ICSharpCode.ILSpy
protected override bool IsMatch(FieldDefinition field, Language language) protected override bool IsMatch(FieldDefinition field, Language language)
{ {
return IsLiteralMatch(field.Constant); return IsLiteralMatch(field.DecodeConstant());
} }
protected override bool IsMatch(PropertyDefinition property, Language language) protected override bool IsMatch(PropertyDefinition property, Language language)
@ -268,91 +269,115 @@ namespace ICSharpCode.ILSpy
bool MethodIsLiteralMatch(MethodDefinition m) bool MethodIsLiteralMatch(MethodDefinition m)
{ {
if (m == null) if (m == null || !m.HasBody)
return false;
var body = m.Body;
if (body == null)
return false; return false;
var blob = m.Body.GetILReader();
if (searchTermLiteralType == TypeCode.Int64) { if (searchTermLiteralType == TypeCode.Int64) {
long val = (long)searchTermLiteralValue; long val = (long)searchTermLiteralValue;
foreach (var inst in body.Instructions) { while (blob.RemainingBytes > 0) {
switch (inst.OpCode.Code) { ILOpCode code;
case Code.Ldc_I8: switch (code = ILParser.DecodeOpCode(ref blob)) {
if (val == (long)inst.Operand) case ILOpCode.Ldc_i8:
if (val == blob.ReadInt64())
return true; return true;
break; break;
case Code.Ldc_I4: case ILOpCode.Ldc_i4:
if (val == (int)inst.Operand) if (val == blob.ReadInt32())
return true; return true;
break; break;
case Code.Ldc_I4_S: case ILOpCode.Ldc_i4_s:
if (val == (sbyte)inst.Operand) if (val == blob.ReadSByte())
return true; return true;
break; break;
case Code.Ldc_I4_M1: case ILOpCode.Ldc_i4_m1:
if (val == -1) if (val == -1)
return true; return true;
break; break;
case Code.Ldc_I4_0: case ILOpCode.Ldc_i4_0:
if (val == 0) if (val == 0)
return true; return true;
break; break;
case Code.Ldc_I4_1: case ILOpCode.Ldc_i4_1:
if (val == 1) if (val == 1)
return true; return true;
break; break;
case Code.Ldc_I4_2: case ILOpCode.Ldc_i4_2:
if (val == 2) if (val == 2)
return true; return true;
break; break;
case Code.Ldc_I4_3: case ILOpCode.Ldc_i4_3:
if (val == 3) if (val == 3)
return true; return true;
break; break;
case Code.Ldc_I4_4: case ILOpCode.Ldc_i4_4:
if (val == 4) if (val == 4)
return true; return true;
break; break;
case Code.Ldc_I4_5: case ILOpCode.Ldc_i4_5:
if (val == 5) if (val == 5)
return true; return true;
break; break;
case Code.Ldc_I4_6: case ILOpCode.Ldc_i4_6:
if (val == 6) if (val == 6)
return true; return true;
break; break;
case Code.Ldc_I4_7: case ILOpCode.Ldc_i4_7:
if (val == 7) if (val == 7)
return true; return true;
break; break;
case Code.Ldc_I4_8: case ILOpCode.Ldc_i4_8:
if (val == 8) if (val == 8)
return true; return true;
break; break;
default:
ILParser.SkipOperand(ref blob, code);
break;
} }
} }
} else if (searchTermLiteralType != TypeCode.Empty) { } else if (searchTermLiteralType != TypeCode.Empty) {
Code expectedCode; ILOpCode expectedCode;
switch (searchTermLiteralType) { switch (searchTermLiteralType) {
case TypeCode.Single: case TypeCode.Single:
expectedCode = Code.Ldc_R4; expectedCode = ILOpCode.Ldc_r4;
break; break;
case TypeCode.Double: case TypeCode.Double:
expectedCode = Code.Ldc_R8; expectedCode = ILOpCode.Ldc_r8;
break; break;
case TypeCode.String: case TypeCode.String:
expectedCode = Code.Ldstr; expectedCode = ILOpCode.Ldstr;
break; break;
default: default:
throw new InvalidOperationException(); throw new InvalidOperationException();
} }
foreach (var inst in body.Instructions) { while (blob.RemainingBytes > 0) {
if (inst.OpCode.Code == expectedCode && searchTermLiteralValue.Equals(inst.Operand)) var code = ILParser.DecodeOpCode(ref blob);
if (code != expectedCode) {
ILParser.SkipOperand(ref blob, code);
continue;
}
switch (code) {
case ILOpCode.Ldc_r4:
if ((float)searchTermLiteralValue == blob.ReadSingle())
return true; return true;
break;
case ILOpCode.Ldc_r8:
if ((double)searchTermLiteralValue == blob.ReadDouble())
return true;
break;
case ILOpCode.Ldstr:
if ((string)searchTermLiteralValue == ILParser.DecodeUserString(ref blob, m.Module))
return true;
break;
}
} }
} else { } else {
foreach (var inst in body.Instructions) { while (blob.RemainingBytes > 0) {
if (inst.OpCode.Code == Code.Ldstr && IsMatch(t => (string)inst.Operand)) var code = ILParser.DecodeOpCode(ref blob);
if (code != ILOpCode.Ldstr) {
ILParser.SkipOperand(ref blob, code);
continue;
}
if (IsMatch(t => ILParser.DecodeUserString(ref blob, m.Module)))
return true; return true;
} }
} }
@ -450,8 +475,8 @@ namespace ICSharpCode.ILSpy
Image = TypeTreeNode.GetIcon(type), Image = TypeTreeNode.GetIcon(type),
Fitness = CalculateFitness(type), Fitness = CalculateFitness(type),
Name = name, Name = name,
LocationImage = type.DeclaringType != null ? TypeTreeNode.GetIcon(type.DeclaringType) : Images.Namespace, LocationImage = !type.DeclaringType.IsNil ? TypeTreeNode.GetIcon(type.DeclaringType) : Images.Namespace,
Location = type.DeclaringType != null ? language.TypeToString(type.DeclaringType, includeNamespace: true) : type.Namespace Location = !type.DeclaringType.IsNil ? language.TypeToString(type.DeclaringType, includeNamespace: true) : type.Namespace
}); });
} }

6
ILSpy/TextView/DecompilerTextView.cs

@ -200,12 +200,12 @@ namespace ICSharpCode.ILSpy.TextView
string documentation = docProvider.GetDocumentation("F:System.Reflection.Emit.OpCodes." + code.EncodedName); string documentation = docProvider.GetDocumentation("F:System.Reflection.Emit.OpCodes." + code.EncodedName);
if (documentation != null) { if (documentation != null) {
XmlDocRenderer renderer = new XmlDocRenderer(); XmlDocRenderer renderer = new XmlDocRenderer();
renderer.AppendText($"{code.Name} (0x{code.Code:x2}) - "); renderer.AppendText($"{code.Name} (0x{code.Code:x}) - ");
renderer.AddXmlDocumentation(documentation); renderer.AddXmlDocumentation(documentation);
return renderer.CreateTextBlock(); return renderer.CreateTextBlock();
} }
} }
return $"{code.Name} (0x{code.Code:x2})"; return $"{code.Name} (0x{code.Code:x})";
} else if (segment.Reference is MemberReference) { } else if (segment.Reference is MemberReference) {
MemberReference mr = (MemberReference)segment.Reference; MemberReference mr = (MemberReference)segment.Reference;
// if possible, resolve the reference // if possible, resolve the reference
@ -215,7 +215,7 @@ namespace ICSharpCode.ILSpy.TextView
mr = ((MethodReference)mr).Resolve() ?? mr; mr = ((MethodReference)mr).Resolve() ?? mr;
} }
XmlDocRenderer renderer = new XmlDocRenderer(); XmlDocRenderer renderer = new XmlDocRenderer();
renderer.AppendText(MainWindow.Instance.CurrentLanguage.GetTooltip(mr)); //renderer.AppendText(MainWindow.Instance.CurrentLanguage.GetTooltip(mr));
try { try {
XmlDocumentationProvider docProvider = XmlDocLoader.LoadDocumentation(mr.Module); XmlDocumentationProvider docProvider = XmlDocLoader.LoadDocumentation(mr.Module);
if (docProvider != null) { if (docProvider != null) {

51
ILSpy/TreeNodes/Analyzer/AnalyzeContextMenuEntry.cs

@ -17,7 +17,7 @@
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System.Linq; using System.Linq;
using Mono.Cecil; using ICSharpCode.Decompiler.Dom;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{ {
@ -62,32 +62,31 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
} }
} }
public static void Analyze(MemberReference member) public static void Analyze(IMemberReference member)
{ {
if (member is TypeReference) { var definition = member.GetDefinition();
TypeDefinition type = ((TypeReference)member).Resolve(); if (definition == null) return;
if (type != null) switch (definition) {
AnalyzerTreeView.Instance.ShowOrFocus(new AnalyzedTypeTreeNode(type)); case TypeDefinition td:
} if (!td.IsNil)
else if (member is FieldReference) { AnalyzerTreeView.Instance.ShowOrFocus(new AnalyzedTypeTreeNode(td));
FieldDefinition field = ((FieldReference)member).Resolve(); break;
if (field != null) case FieldDefinition fd:
AnalyzerTreeView.Instance.ShowOrFocus(new AnalyzedFieldTreeNode(field)); if (!fd.IsNil)
} AnalyzerTreeView.Instance.ShowOrFocus(new AnalyzedFieldTreeNode(fd));
else if (member is MethodReference) { break;
MethodDefinition method = ((MethodReference)member).Resolve(); case MethodDefinition md:
if (method != null) if (!md.IsNil)
AnalyzerTreeView.Instance.ShowOrFocus(new AnalyzedMethodTreeNode(method)); AnalyzerTreeView.Instance.ShowOrFocus(new AnalyzedMethodTreeNode(md));
} break;
else if (member is PropertyReference) { case PropertyDefinition pd:
PropertyDefinition property = ((PropertyReference)member).Resolve(); if (!pd.IsNil)
if (property != null) AnalyzerTreeView.Instance.ShowOrFocus(new AnalyzedPropertyTreeNode(pd));
AnalyzerTreeView.Instance.ShowOrFocus(new AnalyzedPropertyTreeNode(property)); break;
} case EventDefinition ed:
else if (member is EventReference) { if (!ed.IsNil)
EventDefinition @event = ((EventReference)member).Resolve(); AnalyzerTreeView.Instance.ShowOrFocus(new AnalyzedEventTreeNode(ed));
if (@event != null) break;
AnalyzerTreeView.Instance.ShowOrFocus(new AnalyzedEventTreeNode(@event));
} }
} }
} }

24
ILSpy/TreeNodes/Analyzer/AnalyzedAssemblyTreeNode.cs

@ -17,15 +17,15 @@
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System; using System;
using Mono.Cecil; using ICSharpCode.Decompiler.Dom;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{ {
internal class AnalyzedAssemblyTreeNode : AnalyzerEntityTreeNode internal class AnalyzedAssemblyTreeNode : AnalyzerEntityTreeNode
{ {
private readonly ModuleDefinition analyzedAssembly; private readonly PEFile analyzedAssembly;
public AnalyzedAssemblyTreeNode(ModuleDefinition analyzedAssembly) public AnalyzedAssemblyTreeNode(PEFile analyzedAssembly)
{ {
if (analyzedAssembly == null) if (analyzedAssembly == null)
throw new ArgumentNullException(nameof(analyzedAssembly)); throw new ArgumentNullException(nameof(analyzedAssembly));
@ -33,27 +33,15 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
//this.LazyLoading = true; //this.LazyLoading = true;
} }
public override object Icon public override object Icon => Images.Assembly;
{
get { return Images.Assembly; }
}
public override object Text public override object Text => analyzedAssembly.Name;
{
get
{
return analyzedAssembly.Name;
}
}
protected override void LoadChildren() protected override void LoadChildren()
{ {
//this.Children.Add(new AnalyzedAssemblyReferencedByTreeNode(analyzedAssembly)); //this.Children.Add(new AnalyzedAssemblyReferencedByTreeNode(analyzedAssembly));
} }
public override MemberReference Member public override IMemberReference Member => null;
{
get { return null; }
}
} }
} }

6
ILSpy/TreeNodes/Analyzer/AnalyzedAttributeAppliedToTreeNode.cs

@ -20,9 +20,9 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using Mono.Cecil;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using ICSharpCode.Decompiler.Util; using ICSharpCode.Decompiler.Util;
using ICSharpCode.Decompiler.Dom;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{ {
@ -43,7 +43,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
public AnalyzedAttributeAppliedToTreeNode(TypeDefinition analyzedType) public AnalyzedAttributeAppliedToTreeNode(TypeDefinition analyzedType)
{ {
if (analyzedType == null) if (analyzedType.IsNil)
throw new ArgumentNullException(nameof(analyzedType)); throw new ArgumentNullException(nameof(analyzedType));
this.analyzedType = analyzedType; this.analyzedType = analyzedType;
@ -103,7 +103,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
#region standard custom attributes #region standard custom attributes
private IEnumerable<AnalyzerTreeNode> FindReferencesInAssembly(ModuleDefinition module, TypeReference tr, CancellationToken ct) private IEnumerable<AnalyzerTreeNode> FindReferencesInAssembly(PEFile module, TypeReference tr, CancellationToken ct)
{ {
//since we do not display modules as separate entities, coalesce the assembly and module searches //since we do not display modules as separate entities, coalesce the assembly and module searches
bool foundInAssyOrModule = false; bool foundInAssyOrModule = false;

2
ILSpy/TreeNodes/Analyzer/AnalyzedEventAccessorTreeNode.cs

@ -16,7 +16,7 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using Mono.Cecil; using ICSharpCode.Decompiler.Dom;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{ {

13
ILSpy/TreeNodes/Analyzer/AnalyzedEventOverridesTreeNode.cs

@ -19,9 +19,10 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reflection;
using System.Threading; using System.Threading;
using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.Disassembler;
using Mono.Cecil; using ICSharpCode.Decompiler.Dom;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{ {
@ -31,7 +32,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
public AnalyzedEventOverridesTreeNode(EventDefinition analyzedEvent) public AnalyzedEventOverridesTreeNode(EventDefinition analyzedEvent)
{ {
if (analyzedEvent == null) if (analyzedEvent.IsNil)
throw new ArgumentNullException(nameof(analyzedEvent)); throw new ArgumentNullException(nameof(analyzedEvent));
this.analyzedEvent = analyzedEvent; this.analyzedEvent = analyzedEvent;
@ -50,7 +51,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
private IEnumerable<AnalyzerTreeNode> FindReferencesInType(TypeDefinition type) private IEnumerable<AnalyzerTreeNode> FindReferencesInType(TypeDefinition type)
{ {
if (!TypesHierarchyHelpers.IsBaseType(analyzedEvent.DeclaringType, type, resolveTypeArguments: false)) if (!analyzedEvent.DeclaringType.IsBaseTypeOf(type))
yield break; yield break;
foreach (EventDefinition eventDef in type.Events) { foreach (EventDefinition eventDef in type.Events) {
@ -66,8 +67,8 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
public static bool CanShow(EventDefinition property) public static bool CanShow(EventDefinition property)
{ {
var accessor = property.AddMethod ?? property.RemoveMethod; var accessor = property.GetAccessors().First().Method;
return accessor.IsVirtual && !accessor.IsFinal && !accessor.DeclaringType.IsInterface; return accessor.HasFlag(MethodAttributes.Virtual) && !accessor.HasFlag(MethodAttributes.Final) && !accessor.DeclaringType.IsInterface;
} }
} }
} }

14
ILSpy/TreeNodes/Analyzer/AnalyzedEventTreeNode.cs

@ -17,7 +17,8 @@
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System; using System;
using Mono.Cecil; using System.Linq;
using ICSharpCode.Decompiler.Dom;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{ {
@ -35,9 +36,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
this.LazyLoading = true; this.LazyLoading = true;
} }
public override MemberReference Member { public override IMemberReference Member => analyzedEvent;
get { return analyzedEvent; }
}
public override object Icon public override object Icon
{ {
@ -82,13 +81,12 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
return null; return null;
} }
public static bool CanShow(MemberReference member) public static bool CanShow(IMemberReference member)
{ {
var eventDef = member as EventDefinition; if (!(member is EventDefinition eventDef))
if (eventDef == null)
return false; return false;
return !MainWindow.Instance.CurrentLanguage.ShowMember(eventDef.AddMethod ?? eventDef.RemoveMethod) return !MainWindow.Instance.CurrentLanguage.ShowMember(eventDef.GetAccessors().First().Method)
|| AnalyzedEventOverridesTreeNode.CanShow(eventDef); || AnalyzedEventOverridesTreeNode.CanShow(eventDef);
} }
} }

51
ILSpy/TreeNodes/Analyzer/AnalyzedFieldAccessTreeNode.cs

@ -21,8 +21,10 @@ using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using Mono.Cecil; using ICSharpCode.Decompiler.Disassembler;
using Mono.Cecil.Cil; using ICSharpCode.Decompiler.Dom;
using ILOpCode = System.Reflection.Metadata.ILOpCode;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{ {
@ -35,7 +37,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
public AnalyzedFieldAccessTreeNode(FieldDefinition analyzedField, bool showWrites) public AnalyzedFieldAccessTreeNode(FieldDefinition analyzedField, bool showWrites)
{ {
if (analyzedField == null) if (analyzedField.IsNil)
throw new ArgumentNullException(nameof(analyzedField)); throw new ArgumentNullException(nameof(analyzedField));
this.analyzedField = analyzedField; this.analyzedField = analyzedField;
@ -67,24 +69,27 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
bool found = false; bool found = false;
if (!method.HasBody) if (!method.HasBody)
continue; continue;
foreach (Instruction instr in method.Body.Instructions) { var blob = method.Body.GetILReader();
if (CanBeReference(instr.OpCode.Code)) { while (blob.RemainingBytes > 0) {
FieldReference fr = instr.Operand as FieldReference; var opCode = ILParser.DecodeOpCode(ref blob);
if (fr != null && fr.Name == name && if (!CanBeReference(opCode)) {
Helpers.IsReferencedBy(analyzedField.DeclaringType, fr.DeclaringType) && ILParser.SkipOperand(ref blob, opCode);
fr.Resolve() == analyzedField) { continue;
}
var field = ILParser.DecodeMemberToken(ref blob, method.Module);
if (field == null || field.Name != name)
continue;
var definition = field.GetDefinition() as FieldDefinition?;
if (definition?.DeclaringType.FullName != analyzedField.DeclaringType.FullName)
continue;
found = true; found = true;
break; break;
} }
}
}
method.Body = null;
if (found) { if (found) {
MethodDefinition codeLocation = this.Language.GetOriginalCodeLocation(method) as MethodDefinition; MethodDefinition? codeLocation = this.Language.GetOriginalCodeLocation(method) as MethodDefinition?;
if (codeLocation != null && !HasAlreadyBeenFound(codeLocation)) { if (codeLocation != null && !HasAlreadyBeenFound(codeLocation.Value)) {
var node = new AnalyzedMethodTreeNode(codeLocation); var node = new AnalyzedMethodTreeNode(codeLocation.Value);
node.Language = this.Language; node.Language = this.Language;
yield return node; yield return node;
} }
@ -92,17 +97,17 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
} }
} }
private bool CanBeReference(Code code) private bool CanBeReference(ILOpCode code)
{ {
switch (code) { switch (code) {
case Code.Ldfld: case ILOpCode.Ldfld:
case Code.Ldsfld: case ILOpCode.Ldsfld:
return !showWrites; return !showWrites;
case Code.Stfld: case ILOpCode.Stfld:
case Code.Stsfld: case ILOpCode.Stsfld:
return showWrites; return showWrites;
case Code.Ldflda: case ILOpCode.Ldflda:
case Code.Ldsflda: case ILOpCode.Ldsflda:
return true; // always show address-loading return true; // always show address-loading
default: default:
return false; return false;

13
ILSpy/TreeNodes/Analyzer/AnalyzedFieldTreeNode.cs

@ -17,7 +17,7 @@
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System; using System;
using Mono.Cecil; using ICSharpCode.Decompiler.Dom;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{ {
@ -27,16 +27,13 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
public AnalyzedFieldTreeNode(FieldDefinition analyzedField) public AnalyzedFieldTreeNode(FieldDefinition analyzedField)
{ {
if (analyzedField == null) if (analyzedField.IsNil)
throw new ArgumentNullException(nameof(analyzedField)); throw new ArgumentNullException(nameof(analyzedField));
this.analyzedField = analyzedField; this.analyzedField = analyzedField;
this.LazyLoading = true; this.LazyLoading = true;
} }
public override object Icon public override object Icon => FieldTreeNode.GetIcon(analyzedField);
{
get { return FieldTreeNode.GetIcon(analyzedField); }
}
public override object Text public override object Text
{ {
@ -54,8 +51,6 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
this.Children.Add(new AnalyzedFieldAccessTreeNode(analyzedField, true)); this.Children.Add(new AnalyzedFieldAccessTreeNode(analyzedField, true));
} }
public override MemberReference Member { public override IMemberReference Member => analyzedField;
get { return analyzedField; }
}
} }
} }

11
ILSpy/TreeNodes/Analyzer/AnalyzedMethodTreeNode.cs

@ -17,7 +17,8 @@
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System; using System;
using Mono.Cecil; using System.Reflection;
using ICSharpCode.Decompiler.Dom;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{ {
@ -28,7 +29,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
public AnalyzedMethodTreeNode(MethodDefinition analyzedMethod, string prefix = "") public AnalyzedMethodTreeNode(MethodDefinition analyzedMethod, string prefix = "")
{ {
if (analyzedMethod == null) if (analyzedMethod.IsNil)
throw new ArgumentNullException(nameof(analyzedMethod)); throw new ArgumentNullException(nameof(analyzedMethod));
this.analyzedMethod = analyzedMethod; this.analyzedMethod = analyzedMethod;
this.prefix = prefix; this.prefix = prefix;
@ -53,7 +54,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
if (analyzedMethod.HasBody) if (analyzedMethod.HasBody)
this.Children.Add(new AnalyzedMethodUsesTreeNode(analyzedMethod)); this.Children.Add(new AnalyzedMethodUsesTreeNode(analyzedMethod));
if (analyzedMethod.IsVirtual && !(analyzedMethod.IsNewSlot && analyzedMethod.IsFinal)) if (analyzedMethod.HasFlag(MethodAttributes.Virtual) && !(analyzedMethod.HasFlag(MethodAttributes.NewSlot) && analyzedMethod.HasFlag(MethodAttributes.Final)))
this.Children.Add(new AnalyzedVirtualMethodUsedByTreeNode(analyzedMethod)); this.Children.Add(new AnalyzedVirtualMethodUsedByTreeNode(analyzedMethod));
else else
this.Children.Add(new AnalyzedMethodUsedByTreeNode(analyzedMethod)); this.Children.Add(new AnalyzedMethodUsedByTreeNode(analyzedMethod));
@ -65,8 +66,6 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
this.Children.Add(new AnalyzedInterfaceMethodImplementedByTreeNode(analyzedMethod)); this.Children.Add(new AnalyzedInterfaceMethodImplementedByTreeNode(analyzedMethod));
} }
public override MemberReference Member { public override IMemberReference Member => analyzedMethod;
get { return analyzedMethod; }
}
} }
} }

2
ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsedByTreeNode.cs

@ -66,7 +66,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
foreach (Instruction instr in method.Body.Instructions) { foreach (Instruction instr in method.Body.Instructions) {
MethodReference mr = instr.Operand as MethodReference; MethodReference mr = instr.Operand as MethodReference;
if (mr != null && mr.Name == name && if (mr != null && mr.Name == name &&
Helpers.IsReferencedBy(analyzedMethod.DeclaringType, mr.DeclaringType) && Helpers.IsSameType(analyzedMethod.DeclaringType, mr.DeclaringType) &&
mr.Resolve() == analyzedMethod) { mr.Resolve() == analyzedMethod) {
found = true; found = true;
break; break;

51
ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsesTreeNode.cs

@ -20,8 +20,9 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using Mono.Cecil; using ICSharpCode.Decompiler.Disassembler;
using Mono.Cecil.Cil; using ICSharpCode.Decompiler.Dom;
using ICSharpCode.Decompiler.IL;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{ {
@ -34,7 +35,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
public AnalyzedMethodUsesTreeNode(MethodDefinition analyzedMethod) public AnalyzedMethodUsesTreeNode(MethodDefinition analyzedMethod)
{ {
if (analyzedMethod == null) if (analyzedMethod.IsNil)
throw new ArgumentNullException(nameof(analyzedMethod)); throw new ArgumentNullException(nameof(analyzedMethod));
this.analyzedMethod = analyzedMethod; this.analyzedMethod = analyzedMethod;
@ -61,24 +62,42 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
private IEnumerable<MethodDefinition> GetUsedMethods() private IEnumerable<MethodDefinition> GetUsedMethods()
{ {
foreach (Instruction instr in analyzedMethod.Body.Instructions) { if (!analyzedMethod.HasBody) yield break;
MethodReference mr = instr.Operand as MethodReference; var blob = analyzedMethod.Body.GetILReader();
if (mr != null) { while (blob.RemainingBytes > 0) {
MethodDefinition def = mr.Resolve(); var opCode = ILParser.DecodeOpCode(ref blob);
if (def != null) switch (opCode.GetOperandType()) {
yield return def; case OperandType.Method:
case OperandType.Sig:
case OperandType.Tok:
var member = ILParser.DecodeMemberToken(ref blob, analyzedMethod.Module).GetDefinition();
if (member is MethodDefinition md)
yield return md;
break;
default:
ILParser.SkipOperand(ref blob, opCode);
break;
} }
} }
} }
private IEnumerable<FieldDefinition> GetUsedFields() IEnumerable<FieldDefinition> GetUsedFields()
{ {
foreach (Instruction instr in analyzedMethod.Body.Instructions) { if (!analyzedMethod.HasBody) yield break;
FieldReference fr = instr.Operand as FieldReference; var blob = analyzedMethod.Body.GetILReader();
if (fr != null) { while (blob.RemainingBytes > 0) {
FieldDefinition def = fr.Resolve(); var opCode = ILParser.DecodeOpCode(ref blob);
if (def != null) switch (opCode.GetOperandType()) {
yield return def; case OperandType.Field:
case OperandType.Sig:
case OperandType.Tok:
var member = ILParser.DecodeMemberToken(ref blob, analyzedMethod.Module).GetDefinition();
if (member is FieldDefinition fd)
yield return fd;
break;
default:
ILParser.SkipOperand(ref blob, opCode);
break;
} }
} }
} }

2
ILSpy/TreeNodes/Analyzer/AnalyzedPropertyAccessorTreeNode.cs

@ -16,7 +16,7 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using Mono.Cecil; using ICSharpCode.Decompiler.Dom;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{ {

13
ILSpy/TreeNodes/Analyzer/AnalyzedPropertyOverridesTreeNode.cs

@ -19,9 +19,10 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reflection;
using System.Threading; using System.Threading;
using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.Disassembler;
using Mono.Cecil; using ICSharpCode.Decompiler.Dom;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{ {
@ -50,11 +51,11 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
private IEnumerable<AnalyzerTreeNode> FindReferencesInType(TypeDefinition type) private IEnumerable<AnalyzerTreeNode> FindReferencesInType(TypeDefinition type)
{ {
if (!TypesHierarchyHelpers.IsBaseType(analyzedProperty.DeclaringType, type, resolveTypeArguments: false)) if (!analyzedProperty.DeclaringType.IsBaseTypeOf(type))
yield break; yield break;
foreach (PropertyDefinition property in type.Properties) { foreach (PropertyDefinition property in type.Properties) {
analyzedProperty.
if (TypesHierarchyHelpers.IsBaseProperty(analyzedProperty, property)) { if (TypesHierarchyHelpers.IsBaseProperty(analyzedProperty, property)) {
MethodDefinition anyAccessor = property.GetMethod ?? property.SetMethod; MethodDefinition anyAccessor = property.GetMethod ?? property.SetMethod;
bool hidesParent = !anyAccessor.IsVirtual ^ anyAccessor.IsNewSlot; bool hidesParent = !anyAccessor.IsVirtual ^ anyAccessor.IsNewSlot;
@ -67,8 +68,8 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
public static bool CanShow(PropertyDefinition property) public static bool CanShow(PropertyDefinition property)
{ {
var accessor = property.GetMethod ?? property.SetMethod; var accessor = property.GetAccessors().First().Method;
return accessor.IsVirtual && !accessor.IsFinal && !accessor.DeclaringType.IsInterface; return accessor.HasFlag(MethodAttributes.Virtual) && !accessor.HasFlag(MethodAttributes.Final) && !accessor.DeclaringType.IsInterface;
} }
} }
} }

23
ILSpy/TreeNodes/Analyzer/AnalyzedPropertyTreeNode.cs

@ -18,7 +18,7 @@
using System; using System;
using ICSharpCode.Decompiler; using ICSharpCode.Decompiler;
using Mono.Cecil; using ICSharpCode.Decompiler.Dom;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{ {
@ -32,7 +32,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{ {
if (analyzedProperty == null) if (analyzedProperty == null)
throw new ArgumentNullException(nameof(analyzedProperty)); throw new ArgumentNullException(nameof(analyzedProperty));
this.isIndexer = analyzedProperty.IsIndexer(); this.isIndexer = analyzedProperty.IsIndexer;
this.analyzedProperty = analyzedProperty; this.analyzedProperty = analyzedProperty;
this.prefix = prefix; this.prefix = prefix;
this.LazyLoading = true; this.LazyLoading = true;
@ -54,9 +54,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
protected override void LoadChildren() protected override void LoadChildren()
{ {
if (analyzedProperty.GetMethod != null) if (!analyzedProperty.GetMethod.IsNil)
this.Children.Add(new AnalyzedPropertyAccessorTreeNode(analyzedProperty.GetMethod, "get")); this.Children.Add(new AnalyzedPropertyAccessorTreeNode(analyzedProperty.GetMethod, "get"));
if (analyzedProperty.SetMethod != null) if (!analyzedProperty.SetMethod.IsNil)
this.Children.Add(new AnalyzedPropertyAccessorTreeNode(analyzedProperty.SetMethod, "set")); this.Children.Add(new AnalyzedPropertyAccessorTreeNode(analyzedProperty.SetMethod, "set"));
foreach (var accessor in analyzedProperty.OtherMethods) foreach (var accessor in analyzedProperty.OtherMethods)
this.Children.Add(new AnalyzedPropertyAccessorTreeNode(accessor, null)); this.Children.Add(new AnalyzedPropertyAccessorTreeNode(accessor, null));
@ -67,26 +67,23 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
this.Children.Add(new AnalyzedInterfacePropertyImplementedByTreeNode(analyzedProperty)); this.Children.Add(new AnalyzedInterfacePropertyImplementedByTreeNode(analyzedProperty));
} }
public static AnalyzerTreeNode TryCreateAnalyzer(MemberReference member) public static AnalyzerTreeNode TryCreateAnalyzer(IMemberReference member)
{ {
if (CanShow(member)) if (CanShow(member))
return new AnalyzedPropertyTreeNode(member as PropertyDefinition); return new AnalyzedPropertyTreeNode((PropertyDefinition)member);
else else
return null; return null;
} }
public static bool CanShow(MemberReference member) public static bool CanShow(IMemberReference member)
{ {
var property = member as PropertyDefinition; if (!(member is PropertyDefinition property))
if (property == null)
return false; return false;
return !MainWindow.Instance.CurrentLanguage.ShowMember(property.GetMethod ?? property.SetMethod) return !MainWindow.Instance.CurrentLanguage.ShowMember(property.GetMethod.IsNil ? property.SetMethod : property.GetMethod)
|| AnalyzedPropertyOverridesTreeNode.CanShow(property); || AnalyzedPropertyOverridesTreeNode.CanShow(property);
} }
public override MemberReference Member { public override IMemberReference Member => analyzedProperty;
get { return analyzedProperty; }
}
} }
} }

11
ILSpy/TreeNodes/Analyzer/AnalyzedTypeExposedByTreeNode.cs

@ -19,8 +19,9 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reflection;
using System.Threading; using System.Threading;
using Mono.Cecil; using ICSharpCode.Decompiler.Dom;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{ {
@ -30,7 +31,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
public AnalyzedTypeExposedByTreeNode(TypeDefinition analyzedType) public AnalyzedTypeExposedByTreeNode(TypeDefinition analyzedType)
{ {
if (analyzedType == null) if (analyzedType.IsNil)
throw new ArgumentNullException(nameof(analyzedType)); throw new ArgumentNullException(nameof(analyzedType));
this.analyzedType = analyzedType; this.analyzedType = analyzedType;
@ -135,7 +136,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
// exclude methods with 'semantics'. for example, property getters & setters. // exclude methods with 'semantics'. for example, property getters & setters.
// HACK: this is a potentially fragile implementation, as the MethodSemantics may be extended to other uses at a later date. // HACK: this is a potentially fragile implementation, as the MethodSemantics may be extended to other uses at a later date.
if (method.SemanticsAttributes != MethodSemanticsAttributes.None) if (method.GetMethodSemanticsAttributes() != 0)
return false; return false;
if (method.ReturnType.Resolve() == analyzedType) if (method.ReturnType.Resolve() == analyzedType)
@ -153,8 +154,8 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
private static bool IsPrivate(PropertyDefinition property) private static bool IsPrivate(PropertyDefinition property)
{ {
bool isGetterPublic = (property.GetMethod != null && !property.GetMethod.IsPrivate); bool isGetterPublic = (!property.GetMethod.IsNil && !property.GetMethod.IsPrivate);
bool isSetterPublic = (property.SetMethod != null && !property.SetMethod.IsPrivate); bool isSetterPublic = (!property.SetMethod.IsNil && !property.SetMethod.IsPrivate);
return !(isGetterPublic || isSetterPublic); return !(isGetterPublic || isSetterPublic);
} }

39
ILSpy/TreeNodes/Analyzer/AnalyzedTypeInstantiationsTreeNode.cs

@ -19,10 +19,11 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reflection;
using System.Threading; using System.Threading;
using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.Disassembler;
using Mono.Cecil; using ICSharpCode.Decompiler.Dom;
using Mono.Cecil.Cil; using ICSharpCode.Decompiler.IL;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{ {
@ -33,12 +34,12 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
public AnalyzedTypeInstantiationsTreeNode(TypeDefinition analyzedType) public AnalyzedTypeInstantiationsTreeNode(TypeDefinition analyzedType)
{ {
if (analyzedType == null) if (analyzedType.IsNil)
throw new ArgumentNullException(nameof(analyzedType)); throw new ArgumentNullException(nameof(analyzedType));
this.analyzedType = analyzedType; this.analyzedType = analyzedType;
this.isSystemObject = (analyzedType.FullName == "System.Object"); this.isSystemObject = (analyzedType.FullName.ToString() == "System.Object");
} }
public override object Text public override object Text
@ -61,22 +62,30 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
// ignore chained constructors // ignore chained constructors
// (since object is the root of everything, we can short circuit the test in this case) // (since object is the root of everything, we can short circuit the test in this case)
if (method.Name == ".ctor" && if (method.IsConstructor && (isSystemObject || analyzedType == type || analyzedType.IsBaseTypeOf(type)))
(isSystemObject || analyzedType == type || TypesHierarchyHelpers.IsBaseType(analyzedType, type, false)))
continue; continue;
foreach (Instruction instr in method.Body.Instructions) { var blob = method.Body.GetILReader();
MethodReference mr = instr.Operand as MethodReference;
if (mr != null && mr.Name == ".ctor") { while (!found && blob.RemainingBytes > 0) {
if (Helpers.IsReferencedBy(analyzedType, mr.DeclaringType)) { var opCode = ILParser.DecodeOpCode(ref blob);
switch (opCode.GetOperandType()) {
case OperandType.Method:
case OperandType.Sig:
case OperandType.Tok:
var member = ILParser.DecodeMemberToken(ref blob, method.Module);
if (member.Name == ".ctor") {
if (member.DeclaringType.FullName == analyzedType.FullName) {
found = true; found = true;
break;
} }
} }
break;
default:
ILParser.SkipOperand(ref blob, opCode);
break;
}
} }
method.Body = null;
if (found) { if (found) {
var node = new AnalyzedMethodTreeNode(method); var node = new AnalyzedMethodTreeNode(method);
node.Language = this.Language; node.Language = this.Language;
@ -87,7 +96,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
public static bool CanShow(TypeDefinition type) public static bool CanShow(TypeDefinition type)
{ {
return (type.IsClass && !(type.IsAbstract && type.IsSealed) && !type.IsEnum); return (type.IsClass && !(type.HasFlag(TypeAttributes.Abstract) && type.HasFlag(TypeAttributes.Sealed)) && !type.IsEnum);
} }
} }
} }

8
ILSpy/TreeNodes/Analyzer/AnalyzedTypeTreeNode.cs

@ -17,7 +17,7 @@
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System; using System;
using Mono.Cecil; using ICSharpCode.Decompiler.Dom;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{ {
@ -27,7 +27,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
public AnalyzedTypeTreeNode(TypeDefinition analyzedType) public AnalyzedTypeTreeNode(TypeDefinition analyzedType)
{ {
if (analyzedType == null) if (analyzedType.IsNil)
throw new ArgumentNullException(nameof(analyzedType)); throw new ArgumentNullException(nameof(analyzedType));
this.analyzedType = analyzedType; this.analyzedType = analyzedType;
this.LazyLoading = true; this.LazyLoading = true;
@ -64,8 +64,6 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
this.Children.Add(new AnalyzedTypeExtensionMethodsTreeNode(analyzedType)); this.Children.Add(new AnalyzedTypeExtensionMethodsTreeNode(analyzedType));
} }
public override MemberReference Member { public override IMemberReference Member => analyzedType;
get { return analyzedType; }
}
} }
} }

26
ILSpy/TreeNodes/Analyzer/AnalyzedTypeUsedByTreeNode.cs

@ -20,7 +20,9 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using Mono.Cecil; using ICSharpCode.Decompiler.Disassembler;
using ICSharpCode.Decompiler.Dom;
using ICSharpCode.Decompiler.Util;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{ {
@ -30,7 +32,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
public AnalyzedTypeUsedByTreeNode(TypeDefinition analyzedType) public AnalyzedTypeUsedByTreeNode(TypeDefinition analyzedType)
{ {
if (analyzedType == null) if (analyzedType.IsNil)
throw new ArgumentNullException(nameof(analyzedType)); throw new ArgumentNullException(nameof(analyzedType));
this.analyzedType = analyzedType; this.analyzedType = analyzedType;
@ -46,7 +48,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
var analyzer = new ScopedWhereUsedAnalyzer<AnalyzerTreeNode>(analyzedType, FindTypeUsage); var analyzer = new ScopedWhereUsedAnalyzer<AnalyzerTreeNode>(analyzedType, FindTypeUsage);
return analyzer.PerformAnalysis(ct) return analyzer.PerformAnalysis(ct)
.Cast<AnalyzerEntityTreeNode>() .Cast<AnalyzerEntityTreeNode>()
.Where(n => n.Member.DeclaringType != analyzedType) .Where(n => n.Member.DeclaringType.FullName != analyzedType.FullName)
.Distinct(new AnalyzerEntityTreeNodeComparer()) .Distinct(new AnalyzerEntityTreeNodeComparer())
.OrderBy(n => n.Text); .OrderBy(n => n.Text);
} }
@ -59,7 +61,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
if (IsUsedInTypeDefinition(type)) if (IsUsedInTypeDefinition(type))
yield return new AnalyzedTypeTreeNode(type) { Language = Language }; yield return new AnalyzedTypeTreeNode(type) { Language = Language };
foreach (var field in type.Fields.Where(IsUsedInFieldReference)) foreach (var field in type.Fields.Where(IsUsedInField))
yield return new AnalyzedFieldTreeNode(field) { Language = Language }; yield return new AnalyzedFieldTreeNode(field) { Language = Language };
foreach (var method in type.Methods.Where(IsUsedInMethodDefinition)) foreach (var method in type.Methods.Where(IsUsedInMethodDefinition))
@ -80,7 +82,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
return types.Any(IsUsedInTypeReference); return types.Any(IsUsedInTypeReference);
} }
private bool IsUsedInTypeReference(TypeReference type) private bool IsUsedInTypeReference(ITypeReference type)
{ {
if (type == null) if (type == null)
return false; return false;
@ -96,16 +98,14 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
|| IsUsedInTypeReferences(type.Interfaces.Select(i => i.InterfaceType)); || IsUsedInTypeReferences(type.Interfaces.Select(i => i.InterfaceType));
} }
private bool IsUsedInFieldReference(FieldReference field) private bool IsUsedInField(FieldDefinition field)
{ {
if (field == null) if (field.IsNil) return false;
return false;
return TypeMatches(field.DeclaringType) return TypeMatches(field.DeclaringType) || field.DecodeSignature(new TypeUsedInSignature(analyzedType), default(Unit));
|| TypeMatches(field.FieldType);
} }
private bool IsUsedInMethodReference(MethodReference method) private bool IsUsedInMethod(MethodDefinition method)
{ {
if (method == null) if (method == null)
return false; return false;
@ -161,10 +161,10 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
return TypeMatches(parameter.ParameterType); return TypeMatches(parameter.ParameterType);
} }
private bool TypeMatches(TypeReference tref) private bool TypeMatches(ITypeReference tref)
{ {
if (tref != null && tref.Name == analyzedType.Name) { if (tref != null && tref.Name == analyzedType.Name) {
var tdef = tref.Resolve(); var tdef = tref.GetDefinition();
if (tdef != null) { if (tdef != null) {
return (tdef == analyzedType); return (tdef == analyzedType);
} }

2
ILSpy/TreeNodes/Analyzer/AnalyzedVirtualMethodUsedByTreeNode.cs

@ -97,7 +97,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
if (mr != null && mr.Name == name) { if (mr != null && mr.Name == name) {
// explicit call to the requested method // explicit call to the requested method
if (instr.OpCode.Code == Code.Call if (instr.OpCode.Code == Code.Call
&& Helpers.IsReferencedBy(analyzedMethod.DeclaringType, mr.DeclaringType) && Helpers.IsSameType(analyzedMethod.DeclaringType, mr.DeclaringType)
&& mr.Resolve() == analyzedMethod) { && mr.Resolve() == analyzedMethod) {
found = true; found = true;
prefix = "(as base) "; prefix = "(as base) ";

6
ILSpy/TreeNodes/Analyzer/AnalyzerEntityTreeNode.cs

@ -17,8 +17,8 @@
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System.Collections.Generic; using System.Collections.Generic;
using ICSharpCode.Decompiler.Dom;
using ICSharpCode.TreeView; using ICSharpCode.TreeView;
using Mono.Cecil;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{ {
@ -27,7 +27,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
/// </summary> /// </summary>
public abstract class AnalyzerEntityTreeNode : AnalyzerTreeNode, IMemberTreeNode public abstract class AnalyzerEntityTreeNode : AnalyzerTreeNode, IMemberTreeNode
{ {
public abstract MemberReference Member { get; } public abstract IMemberReference Member { get; }
public override void ActivateItem(System.Windows.RoutedEventArgs e) public override void ActivateItem(System.Windows.RoutedEventArgs e)
{ {
@ -38,7 +38,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
public override bool HandleAssemblyListChanged(ICollection<LoadedAssembly> removedAssemblies, ICollection<LoadedAssembly> addedAssemblies) public override bool HandleAssemblyListChanged(ICollection<LoadedAssembly> removedAssemblies, ICollection<LoadedAssembly> addedAssemblies)
{ {
foreach (LoadedAssembly asm in removedAssemblies) { foreach (LoadedAssembly asm in removedAssemblies) {
if (this.Member.Module == asm.GetModuleDefinitionOrNull()) if (this.Member.Module == asm.GetPEFileOrNull())
return false; // remove this node return false; // remove this node
} }
this.Children.RemoveAll( this.Children.RemoveAll(

4
ILSpy/TreeNodes/Analyzer/AnalyzerSearchTreeNode.cs

@ -16,8 +16,12 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Reflection.Metadata;
using System.Threading; using System.Threading;
using ICSharpCode.Decompiler.Disassembler;
using Dom = ICSharpCode.Decompiler.Dom;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{ {

6
ILSpy/TreeNodes/Analyzer/Helpers.cs

@ -26,7 +26,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{ {
internal static class Helpers internal static class Helpers
{ {
public static bool IsReferencedBy(TypeDefinition type, TypeReference typeRef) public static bool IsSameType(TypeDefinition type, TypeReference typeRef)
{ {
// TODO: move it to a better place after adding support for more cases. // TODO: move it to a better place after adding support for more cases.
if (type == null) if (type == null)
@ -44,7 +44,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
if (type.DeclaringType != null || typeRef.DeclaringType != null) { if (type.DeclaringType != null || typeRef.DeclaringType != null) {
if (type.DeclaringType == null || typeRef.DeclaringType == null) if (type.DeclaringType == null || typeRef.DeclaringType == null)
return false; return false;
if (!IsReferencedBy(type.DeclaringType, typeRef.DeclaringType)) if (!IsSameType(type.DeclaringType, typeRef.DeclaringType))
return false; return false;
} }
@ -105,7 +105,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
foreach (Instruction instr in method.Body.Instructions) { foreach (Instruction instr in method.Body.Instructions) {
MethodReference mr = instr.Operand as MethodReference; MethodReference mr = instr.Operand as MethodReference;
if (mr != null && mr.Name == name && if (mr != null && mr.Name == name &&
IsReferencedBy(analyzedMethod.DeclaringType, mr.DeclaringType) && IsSameType(analyzedMethod.DeclaringType, mr.DeclaringType) &&
mr.Resolve() == analyzedMethod) { mr.Resolve() == analyzedMethod) {
found = true; found = true;
break; break;

53
ILSpy/TreeNodes/Analyzer/ScopedWhereUsedAnalyzer.cs

@ -19,9 +19,12 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reflection;
using System.Threading; using System.Threading;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Dom;
using ICSharpCode.Decompiler.TypeSystem.Implementation;
using ICSharpCode.Decompiler.Util; using ICSharpCode.Decompiler.Util;
using Mono.Cecil;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{ {
@ -30,8 +33,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
/// </summary> /// </summary>
internal class ScopedWhereUsedAnalyzer<T> internal class ScopedWhereUsedAnalyzer<T>
{ {
private readonly AssemblyDefinition assemblyScope; private readonly PEFile assemblyScope;
private TypeDefinition typeScope; private TypeDefinition typeScope;
private static readonly TypeSystemAttributeTypeProvider typeProvider = TypeSystemAttributeTypeProvider.CreateDefault();
private readonly Accessibility memberAccessibility = Accessibility.Public; private readonly Accessibility memberAccessibility = Accessibility.Public;
private Accessibility typeAccessibility = Accessibility.Public; private Accessibility typeAccessibility = Accessibility.Public;
@ -40,7 +44,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
public ScopedWhereUsedAnalyzer(TypeDefinition type, Func<TypeDefinition, IEnumerable<T>> typeAnalysisFunction) public ScopedWhereUsedAnalyzer(TypeDefinition type, Func<TypeDefinition, IEnumerable<T>> typeAnalysisFunction)
{ {
this.typeScope = type; this.typeScope = type;
this.assemblyScope = type.Module.Assembly; this.assemblyScope = type.Module;
this.typeAnalysisFunction = typeAnalysisFunction; this.typeAnalysisFunction = typeAnalysisFunction;
} }
@ -53,8 +57,8 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
public ScopedWhereUsedAnalyzer(PropertyDefinition property, Func<TypeDefinition, IEnumerable<T>> typeAnalysisFunction) public ScopedWhereUsedAnalyzer(PropertyDefinition property, Func<TypeDefinition, IEnumerable<T>> typeAnalysisFunction)
: this(property.DeclaringType, typeAnalysisFunction) : this(property.DeclaringType, typeAnalysisFunction)
{ {
Accessibility getterAccessibility = (property.GetMethod == null) ? Accessibility.Private : GetMethodAccessibility(property.GetMethod); Accessibility getterAccessibility = (property.GetMethod.IsNil) ? Accessibility.Private : GetMethodAccessibility(property.GetMethod);
Accessibility setterAccessibility = (property.SetMethod == null) ? Accessibility.Private : GetMethodAccessibility(property.SetMethod); Accessibility setterAccessibility = (property.SetMethod.IsNil) ? Accessibility.Private : GetMethodAccessibility(property.SetMethod);
this.memberAccessibility = (Accessibility)Math.Max((int)getterAccessibility, (int)setterAccessibility); this.memberAccessibility = (Accessibility)Math.Max((int)getterAccessibility, (int)setterAccessibility);
} }
@ -142,7 +146,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
private void DetermineTypeAccessibility() private void DetermineTypeAccessibility()
{ {
while (typeScope.IsNested) { while (!typeScope.DeclaringType.IsNil) {
Accessibility accessibility = GetNestedTypeAccessibility(typeScope); Accessibility accessibility = GetNestedTypeAccessibility(typeScope);
if ((int)typeAccessibility > (int)accessibility) { if ((int)typeAccessibility > (int)accessibility) {
typeAccessibility = accessibility; typeAccessibility = accessibility;
@ -215,9 +219,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
return assemblies.AsParallel().WithCancellation(ct).SelectMany(asm => FindReferencesInAssembly(asm, ct)); return assemblies.AsParallel().WithCancellation(ct).SelectMany(asm => FindReferencesInAssembly(asm, ct));
} }
private IEnumerable<T> FindReferencesInAssembly(AssemblyDefinition asm, CancellationToken ct) private IEnumerable<T> FindReferencesInAssembly(PEFile asm, CancellationToken ct)
{ {
foreach (TypeDefinition type in TreeTraversal.PreOrder(asm.MainModule.Types, t => t.NestedTypes)) { foreach (TypeDefinition type in TreeTraversal.PreOrder(asm.TypeDefinitions, t => t.NestedTypes)) {
ct.ThrowIfCancellationRequested(); ct.ThrowIfCancellationRequested();
foreach (var result in typeAnalysisFunction(type)) { foreach (var result in typeAnalysisFunction(type)) {
ct.ThrowIfCancellationRequested(); ct.ThrowIfCancellationRequested();
@ -248,41 +252,41 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
} }
} }
private IEnumerable<AssemblyDefinition> GetReferencingAssemblies(AssemblyDefinition asm, CancellationToken ct) private IEnumerable<PEFile> GetReferencingAssemblies(PEFile asm, CancellationToken ct)
{ {
yield return asm; yield return asm;
string requiredAssemblyFullName = asm.FullName; string requiredAssemblyFullName = asm.FullName;
IEnumerable<LoadedAssembly> assemblies = MainWindow.Instance.CurrentAssemblyList.GetAssemblies().Where(assy => assy.GetAssemblyDefinitionOrNull() != null); IEnumerable<LoadedAssembly> assemblies = MainWindow.Instance.CurrentAssemblyList.GetAssemblies().Where(assy => assy.GetPEFileOrNull()?.IsAssembly == true);
foreach (var assembly in assemblies) { foreach (var assembly in assemblies) {
ct.ThrowIfCancellationRequested(); ct.ThrowIfCancellationRequested();
bool found = false; bool found = false;
var module = assembly.GetModuleDefinitionOrNull(); var module = assembly.GetPEFileOrNull();
if (module == null) if (module == null)
continue; continue;
var metadata = module.GetMetadataReader();
foreach (var reference in module.AssemblyReferences) { foreach (var reference in module.AssemblyReferences) {
if (requiredAssemblyFullName == reference.FullName) { if (requiredAssemblyFullName == reference.FullName) {
found = true; found = true;
break; break;
} }
} }
if (found && AssemblyReferencesScopeType(module.Assembly)) if (found && AssemblyReferencesScopeType(module))
yield return module.Assembly; yield return module;
} }
} }
private IEnumerable<AssemblyDefinition> GetAssemblyAndAnyFriends(AssemblyDefinition asm, CancellationToken ct) private IEnumerable<PEFile> GetAssemblyAndAnyFriends(PEFile asm, CancellationToken ct)
{ {
yield return asm; yield return asm;
var reader = asm.GetMetadataReader();
if (asm.HasCustomAttributes) { var attributes = reader.CustomAttributes.Select(h => reader.GetCustomAttribute(h)).Where(ca => ca.GetAttributeType(asm).FullName.ToString() == "System.Runtime.CompilerServices.InternalsVisibleToAttribute");
var attributes = asm.CustomAttributes
.Where(attr => attr.AttributeType.FullName == "System.Runtime.CompilerServices.InternalsVisibleToAttribute");
var friendAssemblies = new HashSet<string>(); var friendAssemblies = new HashSet<string>();
foreach (var attribute in attributes) { foreach (var attribute in attributes) {
string assemblyName = attribute.ConstructorArguments[0].Value as string; string assemblyName = attribute.DecodeValue(typeProvider).FixedArguments[0].Value as string;
assemblyName = assemblyName.Split(',')[0]; // strip off any public key info assemblyName = assemblyName.Split(',')[0]; // strip off any public key info
friendAssemblies.Add(assemblyName); friendAssemblies.Add(assemblyName);
} }
@ -293,22 +297,21 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
foreach (var assembly in assemblies) { foreach (var assembly in assemblies) {
ct.ThrowIfCancellationRequested(); ct.ThrowIfCancellationRequested();
if (friendAssemblies.Contains(assembly.ShortName)) { if (friendAssemblies.Contains(assembly.ShortName)) {
var module = assembly.GetModuleDefinitionOrNull(); var module = assembly.GetPEFileOrNull();
if (module == null) if (module == null)
continue; continue;
if (AssemblyReferencesScopeType(module.Assembly)) if (AssemblyReferencesScopeType(module))
yield return module.Assembly; yield return module;
}
} }
} }
} }
} }
private bool AssemblyReferencesScopeType(AssemblyDefinition asm) private bool AssemblyReferencesScopeType(PEFile asm)
{ {
bool hasRef = false; bool hasRef = false;
foreach (var typeref in asm.MainModule.GetTypeReferences()) { foreach (var typeRef in asm.TypeReferences) {
if (typeref.Name == typeScope.Name && typeref.Namespace == typeScope.Namespace) { if (typeRef.Name == typeScope.Name && typeRef.Namespace == typeScope.Namespace) {
hasRef = true; hasRef = true;
break; break;
} }

37
ILSpy/TreeNodes/AssemblyListTreeNode.cs

@ -22,10 +22,11 @@ using System.Collections.ObjectModel;
using System.Collections.Specialized; using System.Collections.Specialized;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Reflection.PortableExecutable;
using System.Windows; using System.Windows;
using ICSharpCode.Decompiler; using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Dom;
using ICSharpCode.TreeView; using ICSharpCode.TreeView;
using Mono.Cecil;
namespace ICSharpCode.ILSpy.TreeNodes namespace ICSharpCode.ILSpy.TreeNodes
{ {
@ -153,7 +154,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
} }
#region Find*Node #region Find*Node
/*
public ILSpyTreeNode FindResourceNode(Resource resource) public ILSpyTreeNode FindResourceNode(Resource resource)
{ {
if (resource == null) if (resource == null)
@ -177,27 +178,15 @@ namespace ICSharpCode.ILSpy.TreeNodes
} }
return null; return null;
} }
*/
public AssemblyTreeNode FindAssemblyNode(PEFile module)
public AssemblyTreeNode FindAssemblyNode(ModuleDefinition module)
{ {
if (module == null) if (module == null)
return null; return null;
App.Current.Dispatcher.VerifyAccess(); App.Current.Dispatcher.VerifyAccess();
foreach (AssemblyTreeNode node in this.Children) { foreach (AssemblyTreeNode node in this.Children) {
if (node.LoadedAssembly.IsLoaded && node.LoadedAssembly.GetModuleDefinitionOrNull() == module) if (node.LoadedAssembly.IsLoaded && node.LoadedAssembly.GetPEFileOrNull() == module)
return node;
}
return null;
}
public AssemblyTreeNode FindAssemblyNode(AssemblyDefinition asm)
{
if (asm == null)
return null;
App.Current.Dispatcher.VerifyAccess();
foreach (AssemblyTreeNode node in this.Children) {
if (node.LoadedAssembly.IsLoaded && node.LoadedAssembly.GetAssemblyDefinitionOrNull() == asm)
return node; return node;
} }
return null; return null;
@ -221,16 +210,14 @@ namespace ICSharpCode.ILSpy.TreeNodes
/// </summary> /// </summary>
public TypeTreeNode FindTypeNode(TypeDefinition def) public TypeTreeNode FindTypeNode(TypeDefinition def)
{ {
if (def == null) if (!def.DeclaringType.IsNil) {
return null;
if (def.DeclaringType != null) {
TypeTreeNode decl = FindTypeNode(def.DeclaringType); TypeTreeNode decl = FindTypeNode(def.DeclaringType);
if (decl != null) { if (decl != null) {
decl.EnsureLazyChildren(); decl.EnsureLazyChildren();
return decl.Children.OfType<TypeTreeNode>().FirstOrDefault(t => t.TypeDefinition == def && !t.IsHidden); return decl.Children.OfType<TypeTreeNode>().FirstOrDefault(t => t.TypeDefinition == def && !t.IsHidden);
} }
} else { } else {
AssemblyTreeNode asm = FindAssemblyNode(def.Module.Assembly); AssemblyTreeNode asm = FindAssemblyNode(def.Module);
if (asm != null) { if (asm != null) {
return asm.FindTypeNode(def); return asm.FindTypeNode(def);
} }
@ -244,8 +231,6 @@ namespace ICSharpCode.ILSpy.TreeNodes
/// </summary> /// </summary>
public ILSpyTreeNode FindMethodNode(MethodDefinition def) public ILSpyTreeNode FindMethodNode(MethodDefinition def)
{ {
if (def == null)
return null;
TypeTreeNode typeNode = FindTypeNode(def.DeclaringType); TypeTreeNode typeNode = FindTypeNode(def.DeclaringType);
if (typeNode == null) if (typeNode == null)
return null; return null;
@ -281,8 +266,6 @@ namespace ICSharpCode.ILSpy.TreeNodes
/// </summary> /// </summary>
public FieldTreeNode FindFieldNode(FieldDefinition def) public FieldTreeNode FindFieldNode(FieldDefinition def)
{ {
if (def == null)
return null;
TypeTreeNode typeNode = FindTypeNode(def.DeclaringType); TypeTreeNode typeNode = FindTypeNode(def.DeclaringType);
if (typeNode == null) if (typeNode == null)
return null; return null;
@ -296,8 +279,6 @@ namespace ICSharpCode.ILSpy.TreeNodes
/// </summary> /// </summary>
public PropertyTreeNode FindPropertyNode(PropertyDefinition def) public PropertyTreeNode FindPropertyNode(PropertyDefinition def)
{ {
if (def == null)
return null;
TypeTreeNode typeNode = FindTypeNode(def.DeclaringType); TypeTreeNode typeNode = FindTypeNode(def.DeclaringType);
if (typeNode == null) if (typeNode == null)
return null; return null;
@ -311,8 +292,6 @@ namespace ICSharpCode.ILSpy.TreeNodes
/// </summary> /// </summary>
public EventTreeNode FindEventNode(EventDefinition def) public EventTreeNode FindEventNode(EventDefinition def)
{ {
if (def == null)
return null;
TypeTreeNode typeNode = FindTypeNode(def.DeclaringType); TypeTreeNode typeNode = FindTypeNode(def.DeclaringType);
if (typeNode == null) if (typeNode == null)
return null; return null;

6
ILSpy/TreeNodes/AssemblyReferenceTreeNode.cs

@ -25,7 +25,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
/// <summary> /// <summary>
/// Node within assembly reference list. /// Node within assembly reference list.
/// </summary> /// </summary>
public sealed class AssemblyReferenceTreeNode : ILSpyTreeNode /*public sealed class AssemblyReferenceTreeNode : ILSpyTreeNode
{ {
readonly AssemblyNameReference r; readonly AssemblyNameReference r;
readonly AssemblyTreeNode parentAssembly; readonly AssemblyTreeNode parentAssembly;
@ -77,7 +77,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
if (assemblyListNode != null) { if (assemblyListNode != null) {
var refNode = assemblyListNode.FindAssemblyNode(parentAssembly.LoadedAssembly.LookupReferencedAssembly(r)); var refNode = assemblyListNode.FindAssemblyNode(parentAssembly.LoadedAssembly.LookupReferencedAssembly(r));
if (refNode != null) { if (refNode != null) {
ModuleDefinition module = refNode.LoadedAssembly.GetModuleDefinitionOrNull(); ModuleDefinition module = refNode.LoadedAssembly.GetPEFileOrNull();
if (module != null) { if (module != null) {
foreach (var childRef in module.AssemblyReferences) foreach (var childRef in module.AssemblyReferences)
this.Children.Add(new AssemblyReferenceTreeNode(childRef, refNode)); this.Children.Add(new AssemblyReferenceTreeNode(childRef, refNode));
@ -106,5 +106,5 @@ namespace ICSharpCode.ILSpy.TreeNodes
output.WriteLine(); output.WriteLine();
} }
} }
} }*/
} }

43
ILSpy/TreeNodes/AssemblyTreeNode.cs

@ -20,15 +20,19 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Reflection.PortableExecutable;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Documents; using System.Windows.Documents;
using ICSharpCode.Decompiler; using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Dom;
using ICSharpCode.ILSpy.TextView; using ICSharpCode.ILSpy.TextView;
using ICSharpCode.TreeView; using ICSharpCode.TreeView;
using Microsoft.Win32; using Microsoft.Win32;
using Mono.Cecil;
using SRM = System.Reflection.Metadata;
using static System.Reflection.Metadata.PEReaderExtensions;
namespace ICSharpCode.ILSpy.TreeNodes namespace ICSharpCode.ILSpy.TreeNodes
{ {
@ -97,18 +101,19 @@ namespace ICSharpCode.ILSpy.TreeNodes
if (tooltip == null && assembly.IsLoaded) { if (tooltip == null && assembly.IsLoaded) {
tooltip = new TextBlock(); tooltip = new TextBlock();
var module = assembly.GetModuleDefinitionOrNull(); var module = assembly.GetPEFileOrNull();
if (module.Assembly != null) { var metadata = module?.GetMetadataReader();
if (metadata?.IsAssembly == true) {
tooltip.Inlines.Add(new Bold(new Run("Name: "))); tooltip.Inlines.Add(new Bold(new Run("Name: ")));
tooltip.Inlines.Add(new Run(module.Assembly.FullName)); tooltip.Inlines.Add(new Run(metadata.GetFullAssemblyName()));
tooltip.Inlines.Add(new LineBreak()); tooltip.Inlines.Add(new LineBreak());
} }
tooltip.Inlines.Add(new Bold(new Run("Location: "))); tooltip.Inlines.Add(new Bold(new Run("Location: ")));
tooltip.Inlines.Add(new Run(assembly.FileName)); tooltip.Inlines.Add(new Run(assembly.FileName));
tooltip.Inlines.Add(new LineBreak()); tooltip.Inlines.Add(new LineBreak());
tooltip.Inlines.Add(new Bold(new Run("Architecture: "))); tooltip.Inlines.Add(new Bold(new Run("Architecture: ")));
tooltip.Inlines.Add(new Run(CSharpLanguage.GetPlatformDisplayName(module))); tooltip.Inlines.Add(new Run(Language.GetPlatformDisplayName(module)));
string runtimeName = CSharpLanguage.GetRuntimeDisplayName(module); string runtimeName = Language.GetRuntimeDisplayName(module);
if (runtimeName != null) { if (runtimeName != null) {
tooltip.Inlines.Add(new LineBreak()); tooltip.Inlines.Add(new LineBreak());
tooltip.Inlines.Add(new Bold(new Run("Runtime: "))); tooltip.Inlines.Add(new Bold(new Run("Runtime: ")));
@ -125,7 +130,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
get { return !assembly.HasLoadError; } get { return !assembly.HasLoadError; }
} }
void OnAssemblyLoaded(Task<ModuleDefinition> moduleTask) void OnAssemblyLoaded(Task<PEFile> moduleTask)
{ {
// change from "Loading" icon to final icon // change from "Loading" icon to final icon
RaisePropertyChanged("Icon"); RaisePropertyChanged("Icon");
@ -145,19 +150,20 @@ namespace ICSharpCode.ILSpy.TreeNodes
protected override void LoadChildren() protected override void LoadChildren()
{ {
ModuleDefinition moduleDefinition = assembly.GetModuleDefinitionOrNull(); var module = assembly.GetPEFileOrNull();
if (moduleDefinition == null) { if (module == null) {
// if we crashed on loading, then we don't have any children // if we crashed on loading, then we don't have any children
return; return;
} }
var metadata = module.GetMetadataReader();
this.Children.Add(new ReferenceFolderTreeNode(moduleDefinition, this)); this.Children.Add(new ReferenceFolderTreeNode(metadata, this));
if (moduleDefinition.HasResources) if (module.Resources.Any())
this.Children.Add(new ResourceListTreeNode(moduleDefinition)); this.Children.Add(new ResourceListTreeNode(module));
foreach (NamespaceTreeNode ns in namespaces.Values) { foreach (NamespaceTreeNode ns in namespaces.Values) {
ns.Children.Clear(); ns.Children.Clear();
} }
foreach (TypeDefinition type in moduleDefinition.Types.OrderBy(t => t.FullName, NaturalStringComparer.Instance)) { foreach (TypeDefinition type in metadata.GetTopLevelTypeDefinitions().Select(td => new TypeDefinition(module, td)).OrderBy(t => t.FullName.ToString(), NaturalStringComparer.Instance)) {
NamespaceTreeNode ns; NamespaceTreeNode ns;
if (!namespaces.TryGetValue(type.Namespace, out ns)) { if (!namespaces.TryGetValue(type.Namespace, out ns)) {
ns = new NamespaceTreeNode(type.Namespace); ns = new NamespaceTreeNode(type.Namespace);
@ -173,9 +179,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
} }
} }
public override bool CanExpandRecursively { public override bool CanExpandRecursively => true;
get { return true; }
}
/// <summary> /// <summary>
/// Finds the node for a top-level type. /// Finds the node for a top-level type.
@ -396,10 +400,11 @@ namespace ICSharpCode.ILSpy.TreeNodes
return; return;
foreach (var node in context.SelectedTreeNodes) { foreach (var node in context.SelectedTreeNodes) {
var la = ((AssemblyTreeNode)node).LoadedAssembly; var la = ((AssemblyTreeNode)node).LoadedAssembly;
var module = la.GetModuleDefinitionOrNull(); var module = la.GetPEFileOrNull();
if (module != null) { if (module != null) {
foreach (var assyRef in module.AssemblyReferences) { var metadata = module.GetMetadataReader();
la.LookupReferencedAssembly(assyRef); foreach (var assyRef in metadata.AssemblyReferences) {
la.LookupReferencedAssembly(new AssemblyReference(module, assyRef));
} }
} }
} }

23
ILSpy/TreeNodes/BaseTypesEntryNode.cs

@ -19,35 +19,33 @@
using System; using System;
using System.Linq; using System.Linq;
using ICSharpCode.Decompiler; using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Dom;
using ICSharpCode.TreeView; using ICSharpCode.TreeView;
using Mono.Cecil;
namespace ICSharpCode.ILSpy.TreeNodes namespace ICSharpCode.ILSpy.TreeNodes
{ {
sealed class BaseTypesEntryNode : ILSpyTreeNode, IMemberTreeNode sealed class BaseTypesEntryNode : ILSpyTreeNode, IMemberTreeNode
{ {
private readonly TypeReference tr; private readonly ITypeReference tr;
private TypeDefinition def; private TypeDefinition def;
private readonly bool isInterface; private readonly bool isInterface;
public BaseTypesEntryNode(TypeReference tr, bool isInterface) public BaseTypesEntryNode(ITypeReference tr, bool isInterface)
{ {
if (tr == null) this.tr = tr ?? throw new ArgumentNullException(nameof(tr));
throw new ArgumentNullException(nameof(tr)); this.def = tr.GetDefinition();
this.tr = tr;
this.def = tr.Resolve();
this.isInterface = isInterface; this.isInterface = isInterface;
this.LazyLoading = true; this.LazyLoading = true;
} }
public override bool ShowExpander public override bool ShowExpander
{ {
get { return def != null && (def.BaseType != null || def.HasInterfaces); } get { return !def.IsNil && (def.BaseType != null || def.HasInterfaces); }
} }
public override object Text public override object Text
{ {
get { return this.Language.TypeToString(tr, true) + tr.MetadataToken.ToSuffixString(); } get { return def.FullName + def.Handle.ToSuffixString(); }
} }
public override object Icon public override object Icon
@ -71,7 +69,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
{ {
// on item activation, try to resolve once again (maybe the user loaded the assembly in the meantime) // on item activation, try to resolve once again (maybe the user loaded the assembly in the meantime)
if (def == null) { if (def == null) {
def = tr.Resolve(); def = tr.GetDefinition();
if (def != null) if (def != null)
this.LazyLoading = true; this.LazyLoading = true;
// re-load children // re-load children
@ -96,9 +94,6 @@ namespace ICSharpCode.ILSpy.TreeNodes
language.WriteCommentLine(output, language.TypeToString(tr, true)); language.WriteCommentLine(output, language.TypeToString(tr, true));
} }
MemberReference IMemberTreeNode.Member IMemberReference IMemberTreeNode.Member => tr;
{
get { return tr; }
}
} }
} }

14
ILSpy/TreeNodes/BaseTypesTreeNode.cs

@ -19,8 +19,8 @@
using System; using System;
using System.Windows.Threading; using System.Windows.Threading;
using ICSharpCode.Decompiler; using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Dom;
using ICSharpCode.TreeView; using ICSharpCode.TreeView;
using Mono.Cecil;
namespace ICSharpCode.ILSpy.TreeNodes namespace ICSharpCode.ILSpy.TreeNodes
{ {
@ -37,15 +37,9 @@ namespace ICSharpCode.ILSpy.TreeNodes
this.LazyLoading = true; this.LazyLoading = true;
} }
public override object Text public override object Text => "Base Types";
{
get { return "Base Types"; }
}
public override object Icon public override object Icon => Images.SuperTypes;
{
get { return Images.SuperTypes; }
}
protected override void LoadChildren() protected override void LoadChildren()
{ {
@ -57,7 +51,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
if (type.BaseType != null) if (type.BaseType != null)
children.Add(new BaseTypesEntryNode(type.BaseType, false)); children.Add(new BaseTypesEntryNode(type.BaseType, false));
foreach (var i in type.Interfaces) { foreach (var i in type.Interfaces) {
children.Add(new BaseTypesEntryNode(i.InterfaceType, true)); children.Add(new BaseTypesEntryNode(i, true));
} }
} }

4
ILSpy/TreeNodes/CopyFullyQualifiedNameContextMenuEntry.cs

@ -15,9 +15,9 @@ namespace ICSharpCode.ILSpy.TreeNodes
public void Execute(TextViewContext context) public void Execute(TextViewContext context)
{ {
var member = GetMemberNodeFromContext(context)?.Member; /*var member = GetMemberNodeFromContext(context)?.Member;
if (member == null) return; if (member == null) return;
Clipboard.SetText(GetFullyQualifiedName(member)); Clipboard.SetText(GetFullyQualifiedName(member));*/
} }
private IMemberTreeNode GetMemberNodeFromContext(TextViewContext context) private IMemberTreeNode GetMemberNodeFromContext(TextViewContext context)

16
ILSpy/TreeNodes/DerivedTypesEntryNode.cs

@ -17,19 +17,21 @@
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System.Collections.Generic; using System.Collections.Generic;
using System.Reflection;
using System.Reflection.PortableExecutable;
using System.Threading; using System.Threading;
using ICSharpCode.Decompiler; using ICSharpCode.Decompiler;
using Mono.Cecil; using ICSharpCode.Decompiler.Dom;
namespace ICSharpCode.ILSpy.TreeNodes namespace ICSharpCode.ILSpy.TreeNodes
{ {
class DerivedTypesEntryNode : ILSpyTreeNode, IMemberTreeNode class DerivedTypesEntryNode : ILSpyTreeNode, IMemberTreeNode
{ {
private readonly TypeDefinition type; private readonly TypeDefinition type;
private readonly ModuleDefinition[] assemblies; private readonly PEFile[] assemblies;
private readonly ThreadingSupport threading; private readonly ThreadingSupport threading;
public DerivedTypesEntryNode(TypeDefinition type, ModuleDefinition[] assemblies) public DerivedTypesEntryNode(TypeDefinition type, PEFile[] assemblies)
{ {
this.type = type; this.type = type;
this.assemblies = assemblies; this.assemblies = assemblies;
@ -39,12 +41,12 @@ namespace ICSharpCode.ILSpy.TreeNodes
public override bool ShowExpander public override bool ShowExpander
{ {
get { return !type.IsSealed && base.ShowExpander; } get { return !type.HasFlag(TypeAttributes.Sealed) && base.ShowExpander; }
} }
public override object Text public override object Text
{ {
get { return this.Language.TypeToString(type, true) + type.MetadataToken.ToSuffixString(); } get { return type.FullName + type.Handle.ToSuffixString(); }
} }
public override object Icon public override object Icon
@ -57,7 +59,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
if (!settings.ShowInternalApi && !IsPublicAPI) if (!settings.ShowInternalApi && !IsPublicAPI)
return FilterResult.Hidden; return FilterResult.Hidden;
if (settings.SearchTermMatches(type.Name)) { if (settings.SearchTermMatches(type.Name)) {
if (type.IsNested && !settings.Language.ShowMember(type)) if (!type.DeclaringType.IsNil && !settings.Language.ShowMember(type))
return FilterResult.Hidden; return FilterResult.Hidden;
else else
return FilterResult.Match; return FilterResult.Match;
@ -100,6 +102,6 @@ namespace ICSharpCode.ILSpy.TreeNodes
language.WriteCommentLine(output, language.TypeToString(type, true)); language.WriteCommentLine(output, language.TypeToString(type, true));
} }
MemberReference IMemberTreeNode.Member => type; IMemberReference IMemberTreeNode.Member => type;
} }
} }

34
ILSpy/TreeNodes/DerivedTypesTreeNode.cs

@ -18,10 +18,13 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reflection.PortableExecutable;
using System.Threading; using System.Threading;
using ICSharpCode.Decompiler; using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Dom;
using ICSharpCode.Decompiler.Util; using ICSharpCode.Decompiler.Util;
using Mono.Cecil;
using static System.Reflection.Metadata.PEReaderExtensions;
namespace ICSharpCode.ILSpy.TreeNodes namespace ICSharpCode.ILSpy.TreeNodes
{ {
@ -60,18 +63,20 @@ namespace ICSharpCode.ILSpy.TreeNodes
IEnumerable<ILSpyTreeNode> FetchChildren(CancellationToken cancellationToken) IEnumerable<ILSpyTreeNode> FetchChildren(CancellationToken cancellationToken)
{ {
// FetchChildren() runs on the main thread; but the enumerator will be consumed on a background thread // FetchChildren() runs on the main thread; but the enumerator will be consumed on a background thread
var assemblies = list.GetAssemblies().Select(node => node.GetModuleDefinitionOrNull()).Where(asm => asm != null).ToArray(); var assemblies = list.GetAssemblies().Select(node => node.GetPEFileOrNull()).Where(asm => asm != null).ToArray();
return FindDerivedTypes(type, assemblies, cancellationToken); return FindDerivedTypes(type, assemblies, cancellationToken);
} }
internal static IEnumerable<DerivedTypesEntryNode> FindDerivedTypes(TypeDefinition type, ModuleDefinition[] assemblies, CancellationToken cancellationToken) internal static IEnumerable<DerivedTypesEntryNode> FindDerivedTypes(TypeDefinition type, PEFile[] assemblies, CancellationToken cancellationToken)
{ {
foreach (ModuleDefinition module in assemblies) { foreach (var module in assemblies) {
foreach (TypeDefinition td in TreeTraversal.PreOrder(module.Types, t => t.NestedTypes)) { var reader = module.GetMetadataReader();
foreach (var h in TreeTraversal.PreOrder(reader.GetTopLevelTypeDefinitions(), t => reader.GetTypeDefinition(t).GetNestedTypes())) {
cancellationToken.ThrowIfCancellationRequested(); cancellationToken.ThrowIfCancellationRequested();
var td = new TypeDefinition(module, h);
if (type.IsInterface && td.HasInterfaces) { if (type.IsInterface && td.HasInterfaces) {
foreach (var iface in td.Interfaces) { foreach (var iface in td.Interfaces) {
if (IsSameType(iface.InterfaceType, type)) if (IsSameType(iface, type))
yield return new DerivedTypesEntryNode(td, assemblies); yield return new DerivedTypesEntryNode(td, assemblies);
} }
} else if (!type.IsInterface && td.BaseType != null && IsSameType(td.BaseType, type)) { } else if (!type.IsInterface && td.BaseType != null && IsSameType(td.BaseType, type)) {
@ -79,22 +84,13 @@ namespace ICSharpCode.ILSpy.TreeNodes
} }
} }
} }
yield break;
} }
static bool IsSameType(TypeReference typeRef, TypeDefinition type) static bool IsSameType(ITypeReference typeRef, TypeDefinition type)
{ {
if (typeRef.FullName == type.FullName) // FullName contains only namespace, name and type parameter count, therefore this should suffice.
return true; return typeRef.FullName == type.FullName;
if (typeRef.Name != type.Name || type.Namespace != typeRef.Namespace)
return false;
if (typeRef.IsNested || type.IsNested)
if (!typeRef.IsNested || !type.IsNested || !IsSameType(typeRef.DeclaringType, type.DeclaringType))
return false;
var gTypeRef = typeRef as GenericInstanceType;
if (gTypeRef != null || type.HasGenericParameters)
if (gTypeRef == null || !type.HasGenericParameters || gTypeRef.GenericArguments.Count != type.GenericParameters.Count)
return false;
return true;
} }
public override void Decompile(Language language, ITextOutput output, DecompilationOptions options) public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)

43
ILSpy/TreeNodes/EventTreeNode.cs

@ -17,9 +17,11 @@
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System; using System;
using System.Linq;
using System.Reflection;
using System.Windows.Media; using System.Windows.Media;
using ICSharpCode.Decompiler; using ICSharpCode.Decompiler;
using Mono.Cecil; using ICSharpCode.Decompiler.Dom;
namespace ICSharpCode.ILSpy.TreeNodes namespace ICSharpCode.ILSpy.TreeNodes
{ {
@ -28,41 +30,39 @@ namespace ICSharpCode.ILSpy.TreeNodes
/// </summary> /// </summary>
public sealed class EventTreeNode : ILSpyTreeNode, IMemberTreeNode public sealed class EventTreeNode : ILSpyTreeNode, IMemberTreeNode
{ {
public EventTreeNode(EventDefinition ev) public EventTreeNode(EventDefinition ev)
{ {
if (ev == null) if (ev.IsNil)
throw new ArgumentNullException(nameof(ev)); throw new ArgumentNullException(nameof(ev));
this.EventDefinition = ev; this.EventDefinition = ev;
if (ev.AddMethod != null) if (!ev.AddMethod.IsNil)
this.Children.Add(new MethodTreeNode(ev.AddMethod)); this.Children.Add(new MethodTreeNode(ev.AddMethod));
if (ev.RemoveMethod != null) if (!ev.RemoveMethod.IsNil)
this.Children.Add(new MethodTreeNode(ev.RemoveMethod)); this.Children.Add(new MethodTreeNode(ev.RemoveMethod));
if (ev.InvokeMethod != null) if (!ev.InvokeMethod.IsNil)
this.Children.Add(new MethodTreeNode(ev.InvokeMethod)); this.Children.Add(new MethodTreeNode(ev.InvokeMethod));
if (ev.HasOtherMethods) {
foreach (var m in ev.OtherMethods) foreach (var m in ev.OtherMethods)
this.Children.Add(new MethodTreeNode(m)); this.Children.Add(new MethodTreeNode(m));
} }
}
public EventDefinition EventDefinition { get; } public EventDefinition EventDefinition { get; }
public override object Text => GetText(EventDefinition, this.Language) + EventDefinition.MetadataToken.ToSuffixString(); public override object Text => GetText(EventDefinition, this.Language) + EventDefinition.Handle.ToSuffixString();
public static object GetText(EventDefinition eventDef, Language language) public static object GetText(EventDefinition eventDef, Language language)
{ {
return HighlightSearchMatch(eventDef.Name, " : " + language.TypeToString(eventDef.EventType, false, eventDef)); var eventType = eventDef.DecodeSignature(language.CreateSignatureTypeProvider(false), new GenericContext(eventDef.DeclaringType));
return HighlightSearchMatch(eventDef.Name, " : " + eventType);
} }
public override object Icon => GetIcon(EventDefinition); public override object Icon => GetIcon(EventDefinition);
public static ImageSource GetIcon(EventDefinition eventDef) public static ImageSource GetIcon(EventDefinition eventDef)
{ {
MethodDefinition accessor = eventDef.AddMethod ?? eventDef.RemoveMethod; MethodDefinition accessor = eventDef.GetAccessors().FirstOrDefault().Method;
if (accessor != null) if (!accessor.IsNil)
return Images.GetIcon(MemberIcon.Event, GetOverlayIcon(eventDef.AddMethod.Attributes), eventDef.AddMethod.IsStatic); return Images.GetIcon(MemberIcon.Event, GetOverlayIcon(accessor.Attributes), accessor.HasFlag(MethodAttributes.Static));
else else
return Images.GetIcon(MemberIcon.Event, AccessOverlayIcon.Public, false); return Images.GetIcon(MemberIcon.Event, AccessOverlayIcon.Public, false);
} }
@ -82,7 +82,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
return AccessOverlayIcon.ProtectedInternal; return AccessOverlayIcon.ProtectedInternal;
case MethodAttributes.Private: case MethodAttributes.Private:
return AccessOverlayIcon.Private; return AccessOverlayIcon.Private;
case MethodAttributes.CompilerControlled: case 0:
return AccessOverlayIcon.CompilerControlled; return AccessOverlayIcon.CompilerControlled;
default: default:
throw new NotSupportedException(); throw new NotSupportedException();
@ -104,14 +104,21 @@ namespace ICSharpCode.ILSpy.TreeNodes
language.DecompileEvent(EventDefinition, output, options); language.DecompileEvent(EventDefinition, output, options);
} }
public override bool IsPublicAPI { public override bool IsPublicAPI {
get { get {
MethodDefinition accessor = EventDefinition.AddMethod ?? EventDefinition.RemoveMethod; MethodDefinition accessor = EventDefinition.GetAccessors().FirstOrDefault().Method;
return accessor != null && (accessor.IsPublic || accessor.IsFamilyOrAssembly || accessor.IsFamily); if (accessor.IsNil) return false;
switch (accessor.Attributes & MethodAttributes.MemberAccessMask) {
case MethodAttributes.Public:
case MethodAttributes.FamORAssem:
case MethodAttributes.Family:
return true;
default:
return false;
}
} }
} }
MemberReference IMemberTreeNode.Member => EventDefinition; IMemberReference IMemberTreeNode.Member => EventDefinition;
} }
} }

42
ILSpy/TreeNodes/FieldTreeNode.cs

@ -17,9 +17,10 @@
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System; using System;
using System.Reflection;
using System.Windows.Media; using System.Windows.Media;
using ICSharpCode.Decompiler; using ICSharpCode.Decompiler;
using Mono.Cecil; using ICSharpCode.Decompiler.Dom;
namespace ICSharpCode.ILSpy.TreeNodes namespace ICSharpCode.ILSpy.TreeNodes
{ {
@ -37,37 +38,35 @@ namespace ICSharpCode.ILSpy.TreeNodes
this.FieldDefinition = field; this.FieldDefinition = field;
} }
public override object Text public override object Text => GetText(FieldDefinition, Language) + FieldDefinition.Handle.ToSuffixString();
public static object GetText(FieldDefinition field, Language language)
{ {
get { string fieldType = field.DecodeSignature(language.CreateSignatureTypeProvider(false), new GenericContext(field.DeclaringType));
return HighlightSearchMatch( return HighlightSearchMatch(field.Name, " : " + fieldType);
FieldDefinition.Name,
" : " + this.Language.TypeToString(FieldDefinition.FieldType, false, FieldDefinition) + FieldDefinition.MetadataToken.ToSuffixString()
);
}
} }
public override object Icon => GetIcon(FieldDefinition); public override object Icon => GetIcon(FieldDefinition);
public static ImageSource GetIcon(FieldDefinition field) public static ImageSource GetIcon(FieldDefinition field)
{ {
if (field.DeclaringType.IsEnum && !field.Attributes.HasFlag(FieldAttributes.SpecialName)) if (field.DeclaringType.IsEnum && !field.HasFlag(FieldAttributes.SpecialName))
return Images.GetIcon(MemberIcon.EnumValue, GetOverlayIcon(field.Attributes), false); return Images.GetIcon(MemberIcon.EnumValue, GetOverlayIcon(field.Attributes), false);
if (field.IsLiteral) if (field.HasFlag(FieldAttributes.Literal))
return Images.GetIcon(MemberIcon.Literal, GetOverlayIcon(field.Attributes), false); return Images.GetIcon(MemberIcon.Literal, GetOverlayIcon(field.Attributes), false);
else if (field.IsInitOnly) { else if (field.HasFlag(FieldAttributes.InitOnly)) {
if (IsDecimalConstant(field)) if (IsDecimalConstant(field))
return Images.GetIcon(MemberIcon.Literal, GetOverlayIcon(field.Attributes), false); return Images.GetIcon(MemberIcon.Literal, GetOverlayIcon(field.Attributes), false);
else else
return Images.GetIcon(MemberIcon.FieldReadOnly, GetOverlayIcon(field.Attributes), field.IsStatic); return Images.GetIcon(MemberIcon.FieldReadOnly, GetOverlayIcon(field.Attributes), field.HasFlag(FieldAttributes.Static));
} else } else
return Images.GetIcon(MemberIcon.Field, GetOverlayIcon(field.Attributes), field.IsStatic); return Images.GetIcon(MemberIcon.Field, GetOverlayIcon(field.Attributes), field.HasFlag(FieldAttributes.Static));
} }
private static bool IsDecimalConstant(FieldDefinition field) private static bool IsDecimalConstant(FieldDefinition field)
{ {
var fieldType = field.FieldType; /*var fieldType = field.FieldType;
if (fieldType.Name == "Decimal" && fieldType.Namespace == "System") { if (fieldType.Name == "Decimal" && fieldType.Namespace == "System") {
if (field.HasCustomAttributes) { if (field.HasCustomAttributes) {
var attrs = field.CustomAttributes; var attrs = field.CustomAttributes;
@ -77,7 +76,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
return true; return true;
} }
} }
} }*/
return false; return false;
} }
@ -96,7 +95,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
return AccessOverlayIcon.ProtectedInternal; return AccessOverlayIcon.ProtectedInternal;
case FieldAttributes.Private: case FieldAttributes.Private:
return AccessOverlayIcon.Private; return AccessOverlayIcon.Private;
case FieldAttributes.CompilerControlled: case 0:
return AccessOverlayIcon.CompilerControlled; return AccessOverlayIcon.CompilerControlled;
default: default:
throw new NotSupportedException(); throw new NotSupportedException();
@ -120,10 +119,17 @@ namespace ICSharpCode.ILSpy.TreeNodes
public override bool IsPublicAPI { public override bool IsPublicAPI {
get { get {
return FieldDefinition.IsPublic || FieldDefinition.IsFamily || FieldDefinition.IsFamilyOrAssembly; switch (FieldDefinition.Attributes & FieldAttributes.FieldAccessMask) {
case FieldAttributes.Public:
case FieldAttributes.FamORAssem:
case FieldAttributes.Family:
return true;
default:
return false;
}
} }
} }
MemberReference IMemberTreeNode.Member => FieldDefinition; IMemberReference IMemberTreeNode.Member => FieldDefinition;
} }
} }

4
ILSpy/TreeNodes/IMemberTreeNode.cs

@ -16,7 +16,7 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using Mono.Cecil; using ICSharpCode.Decompiler.Dom;
namespace ICSharpCode.ILSpy.TreeNodes namespace ICSharpCode.ILSpy.TreeNodes
{ {
@ -27,6 +27,6 @@ namespace ICSharpCode.ILSpy.TreeNodes
/// </summary> /// </summary>
public interface IMemberTreeNode public interface IMemberTreeNode
{ {
MemberReference Member { get; } IMemberReference Member { get; }
} }
} }

54
ILSpy/TreeNodes/MethodTreeNode.cs

@ -17,13 +17,15 @@
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System; using System;
using System.Collections.Immutable;
using System.Linq; using System.Linq;
using System.Reflection;
using System.Text; using System.Text;
using System.Windows.Controls;
using System.Windows.Media; using System.Windows.Media;
using ICSharpCode.Decompiler; using ICSharpCode.Decompiler;
using Mono.Cecil; using ICSharpCode.Decompiler.Dom;
using SRM = System.Reflection.Metadata;
namespace ICSharpCode.ILSpy.TreeNodes namespace ICSharpCode.ILSpy.TreeNodes
{ {
@ -36,24 +38,27 @@ namespace ICSharpCode.ILSpy.TreeNodes
public MethodTreeNode(MethodDefinition method) public MethodTreeNode(MethodDefinition method)
{ {
if (method == null) if (method.IsNil)
throw new ArgumentNullException(nameof(method)); throw new ArgumentNullException(nameof(method));
this.MethodDefinition = method; this.MethodDefinition = method;
} }
public override object Text => GetText(MethodDefinition, Language) + MethodDefinition.MetadataToken.ToSuffixString(); public override object Text => GetText(MethodDefinition, Language) + MethodDefinition.Handle.ToSuffixString();
public static object GetText(MethodDefinition method, Language language) public static object GetText(MethodDefinition method, Language language)
{ {
StringBuilder b = new StringBuilder(); var b = new StringBuilder();
var signatureProvider = language.CreateSignatureTypeProvider(false);
var signature = method.DecodeSignature(signatureProvider, new GenericContext(method));
b.Append('('); b.Append('(');
for (int i = 0; i < method.Parameters.Count; i++) { for (int i = 0; i < signature.ParameterTypes.Length; i++) {
if (i > 0) if (i > 0)
b.Append(", "); b.Append(", ");
b.Append(language.TypeToString(method.Parameters[i].ParameterType, false, method.Parameters[i])); b.Append(signature.ParameterTypes[i]);
} }
if (method.CallingConvention == MethodCallingConvention.VarArg) { if (signature.Header.CallingConvention == SRM.SignatureCallingConvention.VarArgs) {
if (method.HasParameters) if (signature.ParameterTypes.Length > 0)
b.Append(", "); b.Append(", ");
b.Append("..."); b.Append("...");
} }
@ -61,7 +66,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
b.Append(')'); b.Append(')');
} else { } else {
b.Append(") : "); b.Append(") : ");
b.Append(language.TypeToString(method.ReturnType, false, method.MethodReturnType)); b.Append(signature.ReturnType);
} }
return HighlightSearchMatch(language.FormatMethodName(method), b.ToString()); return HighlightSearchMatch(language.FormatMethodName(method), b.ToString());
} }
@ -70,32 +75,28 @@ namespace ICSharpCode.ILSpy.TreeNodes
public static ImageSource GetIcon(MethodDefinition method) public static ImageSource GetIcon(MethodDefinition method)
{ {
if (method.IsSpecialName && method.Name.StartsWith("op_", StringComparison.Ordinal)) { if (method.HasFlag(MethodAttributes.SpecialName) && method.Name.StartsWith("op_", StringComparison.Ordinal)) {
return Images.GetIcon(MemberIcon.Operator, GetOverlayIcon(method.Attributes), false); return Images.GetIcon(MemberIcon.Operator, GetOverlayIcon(method.Attributes), false);
} }
if (method.IsStatic && method.HasCustomAttributes) { if (method.IsExtensionMethod) {
foreach (var ca in method.CustomAttributes) {
if (ca.AttributeType.FullName == "System.Runtime.CompilerServices.ExtensionAttribute") {
return Images.GetIcon(MemberIcon.ExtensionMethod, GetOverlayIcon(method.Attributes), false); return Images.GetIcon(MemberIcon.ExtensionMethod, GetOverlayIcon(method.Attributes), false);
} }
}
}
if (method.IsSpecialName && if (method.HasFlag(MethodAttributes.SpecialName) &&
(method.Name == ".ctor" || method.Name == ".cctor")) { (method.Name == ".ctor" || method.Name == ".cctor")) {
return Images.GetIcon(MemberIcon.Constructor, GetOverlayIcon(method.Attributes), method.IsStatic); return Images.GetIcon(MemberIcon.Constructor, GetOverlayIcon(method.Attributes), method.HasFlag(MethodAttributes.Static));
} }
if (method.HasPInvokeInfo) if (method.HasPInvokeInfo)
return Images.GetIcon(MemberIcon.PInvokeMethod, GetOverlayIcon(method.Attributes), true); return Images.GetIcon(MemberIcon.PInvokeMethod, GetOverlayIcon(method.Attributes), true);
bool showAsVirtual = method.IsVirtual && !(method.IsNewSlot && method.IsFinal) && !method.DeclaringType.IsInterface; bool showAsVirtual = method.HasFlag(MethodAttributes.Virtual) && !(method.HasFlag(MethodAttributes.NewSlot) && method.HasFlag(MethodAttributes.Final)) && !method.DeclaringType.IsInterface;
return Images.GetIcon( return Images.GetIcon(
showAsVirtual ? MemberIcon.VirtualMethod : MemberIcon.Method, showAsVirtual ? MemberIcon.VirtualMethod : MemberIcon.Method,
GetOverlayIcon(method.Attributes), GetOverlayIcon(method.Attributes),
method.IsStatic); method.HasFlag(MethodAttributes.Static));
} }
private static AccessOverlayIcon GetOverlayIcon(MethodAttributes methodAttributes) private static AccessOverlayIcon GetOverlayIcon(MethodAttributes methodAttributes)
@ -113,7 +114,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
return AccessOverlayIcon.ProtectedInternal; return AccessOverlayIcon.ProtectedInternal;
case MethodAttributes.Private: case MethodAttributes.Private:
return AccessOverlayIcon.Private; return AccessOverlayIcon.Private;
case MethodAttributes.CompilerControlled: case 0:
return AccessOverlayIcon.CompilerControlled; return AccessOverlayIcon.CompilerControlled;
default: default:
throw new NotSupportedException(); throw new NotSupportedException();
@ -137,10 +138,17 @@ namespace ICSharpCode.ILSpy.TreeNodes
public override bool IsPublicAPI { public override bool IsPublicAPI {
get { get {
return MethodDefinition.IsPublic || MethodDefinition.IsFamily || MethodDefinition.IsFamilyOrAssembly; switch (MethodDefinition.Attributes & MethodAttributes.MemberAccessMask) {
case MethodAttributes.Public:
case MethodAttributes.Family:
case MethodAttributes.FamORAssem:
return true;
default:
return false;
}
} }
} }
MemberReference IMemberTreeNode.Member => MethodDefinition; IMemberReference IMemberTreeNode.Member => MethodDefinition;
} }
} }

4
ILSpy/TreeNodes/ModuleReferenceTreeNode.cs

@ -25,7 +25,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
/// <summary> /// <summary>
/// Module reference in ReferenceFolderTreeNode. /// Module reference in ReferenceFolderTreeNode.
/// </summary> /// </summary>
sealed class ModuleReferenceTreeNode : ILSpyTreeNode /*sealed class ModuleReferenceTreeNode : ILSpyTreeNode
{ {
readonly ModuleReference r; readonly ModuleReference r;
@ -48,5 +48,5 @@ namespace ICSharpCode.ILSpy.TreeNodes
{ {
language.WriteCommentLine(output, r.Name); language.WriteCommentLine(output, r.Name);
} }
} }*/
} }

35
ILSpy/TreeNodes/PropertyTreeNode.cs

@ -17,9 +17,12 @@
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System; using System;
using System.Reflection;
using System.Windows.Media; using System.Windows.Media;
using ICSharpCode.Decompiler; using ICSharpCode.Decompiler;
using Mono.Cecil; using ICSharpCode.Decompiler.Dom;
using SRM = System.Reflection.Metadata;
namespace ICSharpCode.ILSpy.TreeNodes namespace ICSharpCode.ILSpy.TreeNodes
{ {
@ -36,39 +39,37 @@ namespace ICSharpCode.ILSpy.TreeNodes
throw new ArgumentNullException(nameof(property)); throw new ArgumentNullException(nameof(property));
this.PropertyDefinition = property; this.PropertyDefinition = property;
using (LoadedAssembly.DisableAssemblyLoad()) { using (LoadedAssembly.DisableAssemblyLoad()) {
this.isIndexer = property.IsIndexer(); this.isIndexer = property.IsIndexer;
} }
if (property.GetMethod != null) if (!property.GetMethod.IsNil)
this.Children.Add(new MethodTreeNode(property.GetMethod)); this.Children.Add(new MethodTreeNode(property.GetMethod));
if (property.SetMethod != null) if (!property.SetMethod.IsNil)
this.Children.Add(new MethodTreeNode(property.SetMethod)); this.Children.Add(new MethodTreeNode(property.SetMethod));
if (property.HasOtherMethods) {
foreach (var m in property.OtherMethods) foreach (var m in property.OtherMethods)
this.Children.Add(new MethodTreeNode(m)); this.Children.Add(new MethodTreeNode(m));
} }
}
public PropertyDefinition PropertyDefinition { get; } public PropertyDefinition PropertyDefinition { get; }
public override object Text => GetText(PropertyDefinition, Language, isIndexer) + PropertyDefinition.MetadataToken.ToSuffixString(); public override object Text => GetText(PropertyDefinition, Language, isIndexer) + PropertyDefinition.Handle.ToSuffixString();
public static object GetText(PropertyDefinition property, Language language, bool? isIndexer = null) public static object GetText(PropertyDefinition property, Language language, bool? isIndexer = null)
{ {
string name = language.FormatPropertyName(property, isIndexer); string name = language.FormatPropertyName(property, isIndexer);
var signature = property.DecodeSignature(language.CreateSignatureTypeProvider(false), new GenericContext(property.DeclaringType));
var b = new System.Text.StringBuilder(); var b = new System.Text.StringBuilder();
if (property.HasParameters) if (property.HasParameters)
{ {
b.Append('('); b.Append('(');
for (int i = 0; i < property.Parameters.Count; i++) for (int i = 0; i < signature.ParameterTypes.Length; i++)
{ {
if (i > 0) if (i > 0)
b.Append(", "); b.Append(", ");
b.Append(language.TypeToString(property.Parameters[i].ParameterType, false, property.Parameters[i])); b.Append(signature.ParameterTypes[i]);
} }
var method = property.GetMethod ?? property.SetMethod; if (signature.Header.CallingConvention == SRM.SignatureCallingConvention.VarArgs)
if (method.CallingConvention == MethodCallingConvention.VarArg)
{ {
if (property.HasParameters) if (property.HasParameters)
b.Append(", "); b.Append(", ");
@ -80,7 +81,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
{ {
b.Append(" : "); b.Append(" : ");
} }
b.Append(language.TypeToString(property.PropertyType, false, property)); b.Append(signature.ReturnType);
return HighlightSearchMatch(name, b.ToString()); return HighlightSearchMatch(name, b.ToString());
} }
@ -110,7 +111,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
return AccessOverlayIcon.ProtectedInternal; return AccessOverlayIcon.ProtectedInternal;
case MethodAttributes.Private: case MethodAttributes.Private:
return AccessOverlayIcon.Private; return AccessOverlayIcon.Private;
case MethodAttributes.CompilerControlled: case 0:
return AccessOverlayIcon.CompilerControlled; return AccessOverlayIcon.CompilerControlled;
default: default:
throw new NotSupportedException(); throw new NotSupportedException();
@ -128,7 +129,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
// in numeric order, so we can do an integer comparison of the masked attribute // in numeric order, so we can do an integer comparison of the masked attribute
int accessLevel = 0; int accessLevel = 0;
if (property.GetMethod != null) { if (!property.GetMethod.IsNil) {
int methodAccessLevel = (int)(property.GetMethod.Attributes & MethodAttributes.MemberAccessMask); int methodAccessLevel = (int)(property.GetMethod.Attributes & MethodAttributes.MemberAccessMask);
if (accessLevel < methodAccessLevel) { if (accessLevel < methodAccessLevel) {
accessLevel = methodAccessLevel; accessLevel = methodAccessLevel;
@ -136,7 +137,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
} }
} }
if (property.SetMethod != null) { if (!property.SetMethod.IsNil) {
int methodAccessLevel = (int)(property.SetMethod.Attributes & MethodAttributes.MemberAccessMask); int methodAccessLevel = (int)(property.SetMethod.Attributes & MethodAttributes.MemberAccessMask);
if (accessLevel < methodAccessLevel) { if (accessLevel < methodAccessLevel) {
accessLevel = methodAccessLevel; accessLevel = methodAccessLevel;
@ -144,7 +145,6 @@ namespace ICSharpCode.ILSpy.TreeNodes
} }
} }
if (property.HasOtherMethods) {
foreach (var m in property.OtherMethods) { foreach (var m in property.OtherMethods) {
int methodAccessLevel = (int)(m.Attributes & MethodAttributes.MemberAccessMask); int methodAccessLevel = (int)(m.Attributes & MethodAttributes.MemberAccessMask);
if (accessLevel < methodAccessLevel) { if (accessLevel < methodAccessLevel) {
@ -152,7 +152,6 @@ namespace ICSharpCode.ILSpy.TreeNodes
result = m.Attributes; result = m.Attributes;
} }
} }
}
return result; return result;
} }
@ -185,6 +184,6 @@ namespace ICSharpCode.ILSpy.TreeNodes
} }
} }
MemberReference IMemberTreeNode.Member => PropertyDefinition; IMemberReference IMemberTreeNode.Member => PropertyDefinition;
} }
} }

19
ILSpy/TreeNodes/ReferenceFolderTreeNode.cs

@ -18,9 +18,10 @@
using System; using System;
using System.Linq; using System.Linq;
using System.Reflection.Metadata;
using System.Reflection.PortableExecutable;
using System.Windows.Threading; using System.Windows.Threading;
using ICSharpCode.Decompiler; using ICSharpCode.Decompiler;
using Mono.Cecil;
namespace ICSharpCode.ILSpy.TreeNodes namespace ICSharpCode.ILSpy.TreeNodes
{ {
@ -29,10 +30,10 @@ namespace ICSharpCode.ILSpy.TreeNodes
/// </summary> /// </summary>
sealed class ReferenceFolderTreeNode : ILSpyTreeNode sealed class ReferenceFolderTreeNode : ILSpyTreeNode
{ {
readonly ModuleDefinition module; readonly MetadataReader module;
readonly AssemblyTreeNode parentAssembly; readonly AssemblyTreeNode parentAssembly;
public ReferenceFolderTreeNode(ModuleDefinition module, AssemblyTreeNode parentAssembly) public ReferenceFolderTreeNode(MetadataReader module, AssemblyTreeNode parentAssembly)
{ {
this.module = module; this.module = module;
this.parentAssembly = parentAssembly; this.parentAssembly = parentAssembly;
@ -53,10 +54,10 @@ namespace ICSharpCode.ILSpy.TreeNodes
protected override void LoadChildren() protected override void LoadChildren()
{ {
foreach (var r in module.AssemblyReferences.OrderBy(r => r.Name)) //foreach (var r in module.AssemblyReferences.OrderBy(r => r.Name))
this.Children.Add(new AssemblyReferenceTreeNode(r, parentAssembly)); // this.Children.Add(new AssemblyReferenceTreeNode(r, parentAssembly));
foreach (var r in module.ModuleReferences.OrderBy(r => r.Name)) //foreach (var r in module.ModuleReferences.OrderBy(r => r.Name))
this.Children.Add(new ModuleReferenceTreeNode(r)); // this.Children.Add(new ModuleReferenceTreeNode(r));
} }
public override void Decompile(Language language, ITextOutput output, DecompilationOptions options) public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
@ -66,10 +67,10 @@ namespace ICSharpCode.ILSpy.TreeNodes
output.WriteLine(); output.WriteLine();
language.WriteCommentLine(output, "Referenced assemblies (in metadata order):"); language.WriteCommentLine(output, "Referenced assemblies (in metadata order):");
// Show metadata order of references // Show metadata order of references
foreach (var r in module.AssemblyReferences) /*foreach (var r in module.AssemblyReferences)
new AssemblyReferenceTreeNode(r, parentAssembly).Decompile(language, output, options); new AssemblyReferenceTreeNode(r, parentAssembly).Decompile(language, output, options);
foreach (var r in module.ModuleReferences) foreach (var r in module.ModuleReferences)
language.WriteCommentLine(output, r.Name); language.WriteCommentLine(output, r.Name);*/
} }
} }
} }

6
ILSpy/TreeNodes/ResourceListTreeNode.cs

@ -20,7 +20,7 @@ using System;
using System.Linq; using System.Linq;
using System.Windows.Threading; using System.Windows.Threading;
using ICSharpCode.Decompiler; using ICSharpCode.Decompiler;
using Mono.Cecil; using ICSharpCode.Decompiler.Dom;
namespace ICSharpCode.ILSpy.TreeNodes namespace ICSharpCode.ILSpy.TreeNodes
{ {
@ -29,9 +29,9 @@ namespace ICSharpCode.ILSpy.TreeNodes
/// </summary> /// </summary>
sealed class ResourceListTreeNode : ILSpyTreeNode sealed class ResourceListTreeNode : ILSpyTreeNode
{ {
readonly ModuleDefinition module; readonly PEFile module;
public ResourceListTreeNode(ModuleDefinition module) public ResourceListTreeNode(PEFile module)
{ {
this.LazyLoading = true; this.LazyLoading = true;
this.module = module; this.module = module;

9
ILSpy/TreeNodes/ResourceNodes/CursorResourceEntryNode.cs

@ -21,8 +21,8 @@ using System.ComponentModel.Composition;
using System.IO; using System.IO;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Media.Imaging; using System.Windows.Media.Imaging;
using ICSharpCode.Decompiler.Dom;
using ICSharpCode.ILSpy.TextView; using ICSharpCode.ILSpy.TextView;
using Mono.Cecil;
namespace ICSharpCode.ILSpy.TreeNodes namespace ICSharpCode.ILSpy.TreeNodes
{ {
@ -33,11 +33,10 @@ namespace ICSharpCode.ILSpy.TreeNodes
public ILSpyTreeNode CreateNode(Resource resource) public ILSpyTreeNode CreateNode(Resource resource)
{ {
EmbeddedResource er = resource as EmbeddedResource; Stream stream = resource.TryOpenStream();
if (er != null) { if (stream == null)
return CreateNode(er.Name, er.GetResourceStream());
}
return null; return null;
return CreateNode(resource.Name, stream);
} }
public ILSpyTreeNode CreateNode(string key, object data) public ILSpyTreeNode CreateNode(string key, object data)

2
ILSpy/TreeNodes/ResourceNodes/IResourceNodeFactory.cs

@ -16,7 +16,7 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using Mono.Cecil; using ICSharpCode.Decompiler.Dom;
namespace ICSharpCode.ILSpy.TreeNodes namespace ICSharpCode.ILSpy.TreeNodes
{ {

9
ILSpy/TreeNodes/ResourceNodes/IconResourceEntryNode.cs

@ -21,8 +21,8 @@ using System.ComponentModel.Composition;
using System.IO; using System.IO;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Media.Imaging; using System.Windows.Media.Imaging;
using ICSharpCode.Decompiler.Dom;
using ICSharpCode.ILSpy.TextView; using ICSharpCode.ILSpy.TextView;
using Mono.Cecil;
namespace ICSharpCode.ILSpy.TreeNodes namespace ICSharpCode.ILSpy.TreeNodes
{ {
@ -31,11 +31,10 @@ namespace ICSharpCode.ILSpy.TreeNodes
{ {
public ILSpyTreeNode CreateNode(Resource resource) public ILSpyTreeNode CreateNode(Resource resource)
{ {
EmbeddedResource er = resource as EmbeddedResource; Stream stream = resource.TryOpenStream();
if (er != null) { if (stream == null)
return CreateNode(er.Name, er.GetResourceStream());
}
return null; return null;
return CreateNode(resource.Name, stream);
} }
public ILSpyTreeNode CreateNode(string key, object data) public ILSpyTreeNode CreateNode(string key, object data)

7
ILSpy/TreeNodes/ResourceNodes/ImageListResourceEntryNode.cs

@ -20,15 +20,14 @@ using System.ComponentModel.Composition;
using System.Drawing; using System.Drawing;
using System.Windows.Forms; using System.Windows.Forms;
using ICSharpCode.Decompiler; using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Dom;
namespace ICSharpCode.ILSpy.TreeNodes namespace ICSharpCode.ILSpy.TreeNodes
{ {
[Export(typeof(IResourceNodeFactory))] [Export(typeof(IResourceNodeFactory))]
sealed class ImageListResourceEntryNodeFactory : IResourceNodeFactory sealed class ImageListResourceEntryNodeFactory : IResourceNodeFactory
{ {
#region IResourceNodeFactory Members public ILSpyTreeNode CreateNode(Resource resource)
public ILSpyTreeNode CreateNode(Mono.Cecil.Resource resource)
{ {
return null; return null;
} }
@ -39,8 +38,6 @@ namespace ICSharpCode.ILSpy.TreeNodes
return new ImageListResourceEntryNode(key, (ImageListStreamer)data); return new ImageListResourceEntryNode(key, (ImageListStreamer)data);
return null; return null;
} }
#endregion
} }
sealed class ImageListResourceEntryNode : ILSpyTreeNode sealed class ImageListResourceEntryNode : ILSpyTreeNode

9
ILSpy/TreeNodes/ResourceNodes/ImageResourceEntryNode.cs

@ -21,8 +21,8 @@ using System.ComponentModel.Composition;
using System.IO; using System.IO;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Media.Imaging; using System.Windows.Media.Imaging;
using ICSharpCode.Decompiler.Dom;
using ICSharpCode.ILSpy.TextView; using ICSharpCode.ILSpy.TextView;
using Mono.Cecil;
namespace ICSharpCode.ILSpy.TreeNodes namespace ICSharpCode.ILSpy.TreeNodes
{ {
@ -33,11 +33,10 @@ namespace ICSharpCode.ILSpy.TreeNodes
public ILSpyTreeNode CreateNode(Resource resource) public ILSpyTreeNode CreateNode(Resource resource)
{ {
EmbeddedResource er = resource as EmbeddedResource; Stream stream = resource.TryOpenStream();
if (er != null) { if (stream == null)
return CreateNode(er.Name, er.GetResourceStream());
}
return null; return null;
return CreateNode(resource.Name, stream);
} }
public ILSpyTreeNode CreateNode(string key, object data) public ILSpyTreeNode CreateNode(string key, object data)

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save