Browse Source

Commit of non-compiling WIP

pull/1198/head
Siegfried Pammer 8 years ago
parent
commit
02b7dc98be
  1. 16
      ICSharpCode.Decompiler.Tests/Helpers/Tester.cs
  2. 1
      ICSharpCode.Decompiler/CSharp/Transforms/CustomPatterns.cs
  3. 1
      ICSharpCode.Decompiler/CSharp/Transforms/PatternStatementTransform.cs
  4. 144
      ICSharpCode.Decompiler/CecilExtensions.cs
  5. 1
      ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs
  6. 1109
      ICSharpCode.Decompiler/Disassembler/MethodBodyDisassembler.cs
  7. 92
      ICSharpCode.Decompiler/Disassembler/OpCodeInfo.cs
  8. 1302
      ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs
  9. 6
      ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
  10. 3
      ICSharpCode.Decompiler/IL/ILOpCodes.cs
  11. 3
      ICSharpCode.Decompiler/IL/ILOpCodes.tt
  12. 4
      ICSharpCode.Decompiler/IL/ILReader.cs
  13. 87
      ICSharpCode.Decompiler/TypeSystem/AssemblyLoader.cs
  14. 585
      ICSharpCode.Decompiler/TypeSystem/CecilLoader.cs
  15. 4
      ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs
  16. 6
      ICSharpCode.Decompiler/TypeSystem/IAssembly.cs
  17. 11
      ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultUnresolvedAssembly.cs
  18. 214
      ICSharpCode.Decompiler/TypeSystem/Implementation/TypeSpecification.cs
  19. 13
      ICSharpCode.Decompiler/TypeSystem/KnownTypeReference.cs
  20. 199
      ICSharpCode.Decompiler/TypeSystem/MetadataExtensions.cs
  21. 65
      ILSpy/Cecil/CecilExtensions.cs
  22. 2
      ILSpy/Cecil/TypesHierarchyHelpers.cs
  23. 2
      ILSpy/ILSpy.csproj
  24. 2
      ILSpy/Languages/CSharpILMixedLanguage.cs
  25. 2
      ILSpy/Languages/ILAstLanguage.cs
  26. 132
      ILSpy/Languages/ILLanguage.cs
  27. 5
      ILSpy/MainWindow.xaml.cs
  28. 11
      ILSpy/TextView/DecompilerTextView.cs

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

@ -22,6 +22,8 @@ using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Reflection.Metadata;
using System.Reflection.PortableExecutable;
using System.Text; using System.Text;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading; using System.Threading;
@ -108,19 +110,19 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
public static string Disassemble(string sourceFileName, string outputFile, AssemblerOptions asmOptions) public static string Disassemble(string sourceFileName, string outputFile, AssemblerOptions asmOptions)
{ {
if (asmOptions.HasFlag(AssemblerOptions.UseOwnDisassembler)) { if (asmOptions.HasFlag(AssemblerOptions.UseOwnDisassembler)) {
using (ModuleDefinition module = ModuleDefinition.ReadModule(sourceFileName)) using (var module = new PEReader(new FileStream(sourceFileName, FileMode.Open)))
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, CancellationToken.None); ReflectionDisassembler rd = new ReflectionDisassembler(output, module.GetMetadataReader(), CancellationToken.None);
rd.DetectControlStructure = false; rd.DetectControlStructure = false;
rd.WriteAssemblyReferences(module); //rd.WriteAssemblyReferences(module);
if (module.Assembly != null) /*if (module.Assembly != null)
rd.WriteAssemblyHeader(module.Assembly); rd.WriteAssemblyHeader(module.Assembly);
output.WriteLine(); output.WriteLine();
rd.WriteModuleHeader(module); rd.WriteModuleHeader(module);
output.WriteLine(); output.WriteLine();
rd.WriteModuleContents(module); rd.WriteModuleContents(module);*/
} }
return outputFile; return outputFile;
} }
@ -275,7 +277,7 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
public static string DecompileCSharp(string assemblyFileName, DecompilerSettings settings = null) public static string DecompileCSharp(string assemblyFileName, DecompilerSettings settings = null)
{ {
using (var module = ModuleDefinition.ReadModule(assemblyFileName)) { using (var module = Mono.Cecil.ModuleDefinition.ReadModule(assemblyFileName)) {
var typeSystem = new DecompilerTypeSystem(module); var typeSystem = new DecompilerTypeSystem(module);
CSharpDecompiler decompiler = new CSharpDecompiler(typeSystem, settings ?? new DecompilerSettings()); CSharpDecompiler decompiler = new CSharpDecompiler(typeSystem, settings ?? new DecompilerSettings());
decompiler.AstTransforms.Insert(0, new RemoveCompilerAttribute()); decompiler.AstTransforms.Insert(0, new RemoveCompilerAttribute());

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

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

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

@ -24,7 +24,6 @@ using ICSharpCode.Decompiler.CSharp.Syntax;
using ICSharpCode.Decompiler.CSharp.Syntax.PatternMatching; 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 Mono.Cecil;
using ICSharpCode.Decompiler.Semantics; using ICSharpCode.Decompiler.Semantics;
namespace ICSharpCode.Decompiler.CSharp.Transforms namespace ICSharpCode.Decompiler.CSharp.Transforms

144
ICSharpCode.Decompiler/CecilExtensions.cs

@ -31,119 +31,6 @@ namespace ICSharpCode.Decompiler
/// </summary> /// </summary>
public static class CecilExtensions public static class CecilExtensions
{ {
#region GetPushDelta / GetPopDelta
public static int GetPushDelta(this Instruction instruction)
{
OpCode code = instruction.OpCode;
switch (code.StackBehaviourPush) {
case StackBehaviour.Push0:
return 0;
case StackBehaviour.Push1:
case StackBehaviour.Pushi:
case StackBehaviour.Pushi8:
case StackBehaviour.Pushr4:
case StackBehaviour.Pushr8:
case StackBehaviour.Pushref:
return 1;
case StackBehaviour.Push1_push1:
return 2;
case StackBehaviour.Varpush:
if (code.FlowControl != FlowControl.Call)
break;
IMethodSignature method = (IMethodSignature) instruction.Operand;
return IsVoid (method.ReturnType) ? 0 : 1;
}
throw new NotSupportedException ();
}
public static int? GetPopDelta(this Instruction instruction, MethodDefinition methodDef)
{
OpCode code = instruction.OpCode;
switch (code.StackBehaviourPop) {
case StackBehaviour.Pop0:
return 0;
case StackBehaviour.Popi:
case StackBehaviour.Popref:
case StackBehaviour.Pop1:
return 1;
case StackBehaviour.Pop1_pop1:
case StackBehaviour.Popi_pop1:
case StackBehaviour.Popi_popi:
case StackBehaviour.Popi_popi8:
case StackBehaviour.Popi_popr4:
case StackBehaviour.Popi_popr8:
case StackBehaviour.Popref_pop1:
case StackBehaviour.Popref_popi:
return 2;
case StackBehaviour.Popi_popi_popi:
case StackBehaviour.Popref_popi_popi:
case StackBehaviour.Popref_popi_popi8:
case StackBehaviour.Popref_popi_popr4:
case StackBehaviour.Popref_popi_popr8:
case StackBehaviour.Popref_popi_popref:
return 3;
case StackBehaviour.PopAll:
return null;
case StackBehaviour.Varpop:
if (code == OpCodes.Ret)
return methodDef.ReturnType.IsVoid() ? 0 : 1;
if (code.FlowControl != FlowControl.Call)
break;
IMethodSignature method = (IMethodSignature) instruction.Operand;
int count = method.HasParameters ? method.Parameters.Count : 0;
if (method.HasThis && code != OpCodes.Newobj)
++count;
if (code == OpCodes.Calli)
++count; // calli takes a function pointer in additional to the normal args
return count;
}
throw new NotSupportedException ();
}
public static bool IsVoid(this TypeReference type)
{
while (type is OptionalModifierType || type is RequiredModifierType)
type = ((TypeSpecification)type).ElementType;
return type.MetadataType == MetadataType.Void;
}
public static bool IsValueTypeOrVoid(this TypeReference type)
{
while (type is OptionalModifierType || type is RequiredModifierType)
type = ((TypeSpecification)type).ElementType;
if (type is ArrayType)
return false;
return type.IsValueType || type.IsVoid();
}
/// <summary>
/// checks if the given TypeReference is one of the following types:
/// [sbyte, short, int, long, IntPtr]
/// </summary>
public static bool IsSignedIntegralType(this TypeReference type)
{
return type.MetadataType == MetadataType.SByte ||
type.MetadataType == MetadataType.Int16 ||
type.MetadataType == MetadataType.Int32 ||
type.MetadataType == MetadataType.Int64 ||
type.MetadataType == MetadataType.IntPtr;
}
#endregion
/// <summary> /// <summary>
/// Gets the (exclusive) end offset of this instruction. /// Gets the (exclusive) end offset of this instruction.
/// </summary> /// </summary>
@ -164,37 +51,6 @@ namespace ICSharpCode.Decompiler
return string.Format("IL_{0:x4}", offset); return string.Format("IL_{0:x4}", offset);
} }
public static HashSet<MethodDefinition> GetAccessorMethods(this TypeDefinition type)
{
HashSet<MethodDefinition> accessorMethods = new HashSet<MethodDefinition>();
foreach (var property in type.Properties) {
accessorMethods.Add(property.GetMethod);
accessorMethods.Add(property.SetMethod);
if (property.HasOtherMethods) {
foreach (var m in property.OtherMethods)
accessorMethods.Add(m);
}
}
foreach (EventDefinition ev in type.Events) {
accessorMethods.Add(ev.AddMethod);
accessorMethods.Add(ev.RemoveMethod);
accessorMethods.Add(ev.InvokeMethod);
if (ev.HasOtherMethods) {
foreach (var m in ev.OtherMethods)
accessorMethods.Add(m);
}
}
return accessorMethods;
}
public static TypeDefinition ResolveWithinSameModule(this TypeReference type)
{
if (type != null && type.GetElementType().Module == type.Module)
return type.Resolve();
else
return null;
}
public static FieldDefinition ResolveWithinSameModule(this FieldReference field) public static FieldDefinition ResolveWithinSameModule(this FieldReference field)
{ {
if (field != null && field.DeclaringType.GetElementType().Module == field.Module) if (field != null && field.DeclaringType.GetElementType().Module == field.Module)

1
ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs

@ -21,6 +21,7 @@ using System.Collections.Generic;
using Mono.Cecil; using Mono.Cecil;
using Mono.Cecil.Cil; using Mono.Cecil.Cil;
using System.Text; using System.Text;
using SRM = System.Reflection.Metadata;
namespace ICSharpCode.Decompiler.Disassembler namespace ICSharpCode.Decompiler.Disassembler
{ {

1109
ICSharpCode.Decompiler/Disassembler/MethodBodyDisassembler.cs

File diff suppressed because it is too large Load Diff

92
ICSharpCode.Decompiler/Disassembler/OpCodeInfo.cs

@ -0,0 +1,92 @@
// 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 System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ICSharpCode.Decompiler.Disassembler
{
public struct OpCodeInfo : IEquatable<OpCodeInfo>
{
public readonly int Code;
public readonly string Name;
string encodedName;
public OpCodeInfo(int code, string name)
{
this.Code = code;
this.Name = name;
this.encodedName = null;
}
public bool Equals(OpCodeInfo other)
{
return other.Code == this.Code && other.Name == this.Name;
}
public static bool operator ==(OpCodeInfo lhs, OpCodeInfo rhs) => lhs.Equals(rhs);
public static bool operator !=(OpCodeInfo lhs, OpCodeInfo rhs) => !(lhs == rhs);
public string Link => "http://msdn.microsoft.com/library/system.reflection.emit.opcodes." + EncodedName.ToLowerInvariant() + ".aspx";
public string EncodedName {
get {
if (encodedName != null)
return encodedName;
switch (Name) {
case "constrained.":
encodedName = "Constrained";
return encodedName;
case "no.":
encodedName = "No";
return encodedName;
case "readonly.":
encodedName = "Reaonly";
return encodedName;
case "tail.":
encodedName = "Tailcall";
return encodedName;
case "unaligned.":
encodedName = "Unaligned";
return encodedName;
case "volatile.":
encodedName = "Volatile";
return encodedName;
}
string text = "";
bool toUpperCase = true;
foreach (var ch in Name) {
if (ch == '.') {
text += '_';
toUpperCase = true;
} else if (toUpperCase) {
text += char.ToUpperInvariant(ch);
toUpperCase = false;
} else {
text += ch;
}
}
encodedName = text;
return encodedName;
}
}
}
}

1302
ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs

File diff suppressed because it is too large Load Diff

6
ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj

@ -55,6 +55,7 @@
<PackageReference Include="Humanizer.Core" Version="2.2.0" /> <PackageReference Include="Humanizer.Core" Version="2.2.0" />
<PackageReference Include="Mono.Cecil" Version="0.10.0-beta7" /> <PackageReference Include="Mono.Cecil" Version="0.10.0-beta7" />
<PackageReference Include="System.Collections.Immutable" Version="1.3.1" /> <PackageReference Include="System.Collections.Immutable" Version="1.3.1" />
<PackageReference Include="System.Reflection.Metadata" Version="1.4.2" />
<PackageReference Include="System.ValueTuple" Version="4.3.0" /> <PackageReference Include="System.ValueTuple" Version="4.3.0" />
</ItemGroup> </ItemGroup>
@ -267,6 +268,7 @@
<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\OpCodeInfo.cs" />
<Compile Include="Documentation\GetPotentiallyNestedClassTypeReference.cs" /> <Compile Include="Documentation\GetPotentiallyNestedClassTypeReference.cs" />
<Compile Include="Documentation\IdStringMemberReference.cs" /> <Compile Include="Documentation\IdStringMemberReference.cs" />
<Compile Include="Documentation\IdStringProvider.cs" /> <Compile Include="Documentation\IdStringProvider.cs" />
@ -323,6 +325,8 @@
<Compile Include="IL\Transforms\StatementTransform.cs" /> <Compile Include="IL\Transforms\StatementTransform.cs" />
<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\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" />
@ -432,7 +436,6 @@
<Compile Include="TypeSystem\Accessibility.cs" /> <Compile Include="TypeSystem\Accessibility.cs" />
<Compile Include="TypeSystem\AnonymousType.cs" /> <Compile Include="TypeSystem\AnonymousType.cs" />
<Compile Include="TypeSystem\ArrayType.cs" /> <Compile Include="TypeSystem\ArrayType.cs" />
<Compile Include="TypeSystem\AssemblyLoader.cs" />
<Compile Include="TypeSystem\AssemblyQualifiedTypeName.cs" /> <Compile Include="TypeSystem\AssemblyQualifiedTypeName.cs" />
<Compile Include="TypeSystem\ByReferenceType.cs" /> <Compile Include="TypeSystem\ByReferenceType.cs" />
<Compile Include="TypeSystem\CecilLoader.cs" /> <Compile Include="TypeSystem\CecilLoader.cs" />
@ -545,7 +548,6 @@
<Compile Include="TypeSystem\SpecializingDecompilerTypeSystem.cs" /> <Compile Include="TypeSystem\SpecializingDecompilerTypeSystem.cs" />
<Compile Include="TypeSystem\IDecompilerTypeSystem.cs" /> <Compile Include="TypeSystem\IDecompilerTypeSystem.cs" />
<Compile Include="TypeSystem\ReferenceResolvingException.cs" /> <Compile Include="TypeSystem\ReferenceResolvingException.cs" />
<Compile Include="TypeSystem\TypesHierarchyHelpers.cs" />
<Compile Include="TypeSystem\TypeVisitor.cs" /> <Compile Include="TypeSystem\TypeVisitor.cs" />
<Compile Include="TypeSystem\VarArgInstanceMethod.cs" /> <Compile Include="TypeSystem\VarArgInstanceMethod.cs" />
<Compile Include="Util\BitVector16.cs" /> <Compile Include="Util\BitVector16.cs" />

3
ICSharpCode.Decompiler/IL/ILOpCodes.cs

@ -17,6 +17,7 @@
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System; using System;
using System.Reflection.Emit;
namespace ICSharpCode.Decompiler.IL namespace ICSharpCode.Decompiler.IL
{ {
enum ILOpCode : ushort enum ILOpCode : ushort
@ -249,7 +250,6 @@ namespace ICSharpCode.Decompiler.IL
Readonly = 0x11e, Readonly = 0x11e,
} }
/*
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
@ -260,5 +260,4 @@ namespace ICSharpCode.Decompiler.IL
return (OperandType)operandTypes[(ushort)opCode]; return (OperandType)operandTypes[(ushort)opCode];
} }
} }
*/
} }

3
ICSharpCode.Decompiler/IL/ILOpCodes.tt

@ -24,6 +24,7 @@
<#@ import namespace="System.Reflection.Emit" #> <#@ import namespace="System.Reflection.Emit" #>
<#@ output extension=".cs" #> <#@ output extension=".cs" #>
using System; using System;
using System.Reflection.Emit;
<# <#
var operandTypes = new OperandType[0x11f]; var operandTypes = new OperandType[0x11f];
@ -41,7 +42,6 @@ namespace ICSharpCode.Decompiler.IL
<# } // end foreach #> <# } // end foreach #>
} }
/*
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
@ -57,5 +57,4 @@ namespace ICSharpCode.Decompiler.IL
return (OperandType)operandTypes[(ushort)opCode]; return (OperandType)operandTypes[(ushort)opCode];
} }
} }
*/
} }

4
ICSharpCode.Decompiler/IL/ILReader.cs

@ -412,8 +412,8 @@ namespace ICSharpCode.Decompiler.IL
inst.WriteTo(output, new ILAstWritingOptions()); inst.WriteTo(output, new ILAstWritingOptions());
output.WriteLine(); output.WriteLine();
} }
new Disassembler.MethodBodyDisassembler(output, cancellationToken) { DetectControlStructure = false } /*new Disassembler.MethodBodyDisassembler(output, cancellationToken) { DetectControlStructure = false }
.WriteExceptionHandlers(body); .WriteExceptionHandlers(body);*/
} }
/// <summary> /// <summary>

87
ICSharpCode.Decompiler/TypeSystem/AssemblyLoader.cs

@ -1,87 +0,0 @@
//
// AssemblyLoader.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2013 Xamarin Inc. (http://xamarin.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Reflection;
using System.Threading;
using ICSharpCode.Decompiler.TypeSystem.Implementation;
namespace ICSharpCode.Decompiler.TypeSystem
{
public enum AssemblyLoaderBackend {
Auto,
Cecil,
IKVM
}
public abstract class AssemblyLoader
{
public static AssemblyLoader Create ()
{
return Create (AssemblyLoaderBackend.Auto);
}
public static AssemblyLoader Create (AssemblyLoaderBackend backend)
{
switch (backend) {
case AssemblyLoaderBackend.Auto:
case AssemblyLoaderBackend.Cecil:
return (AssemblyLoader)Assembly.Load ("ICSharpCode.Decompiler.Cecil").CreateInstance ("ICSharpCode.Decompiler.TypeSystem.CecilLoader");
case AssemblyLoaderBackend.IKVM:
return (AssemblyLoader)Assembly.Load ("ICSharpCode.Decompiler.IKVM").CreateInstance ("ICSharpCode.Decompiler.TypeSystem.IkvmLoader");
default:
throw new ArgumentOutOfRangeException ();
}
}
/// <summary>
/// Specifies whether to include internal members. The default is false.
/// </summary>
public bool IncludeInternalMembers { get; set; }
/// <summary>
/// Gets/Sets the cancellation token used by the assembly loader.
/// </summary>
public CancellationToken CancellationToken { get; set; }
protected InterningProvider interningProvider = new SimpleInterningProvider();
/// <summary>
/// Gets/Sets the interning provider.
/// </summary>
public InterningProvider InterningProvider {
get { return interningProvider; }
set {
if (value == null)
throw new ArgumentNullException();
interningProvider = value;
}
}
public abstract IUnresolvedAssembly LoadAssemblyFile(string fileName);
}
}

585
ICSharpCode.Decompiler/TypeSystem/CecilLoader.cs

@ -20,34 +20,49 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Reflection;
using System.Reflection.Metadata;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Threading; using System.Threading;
using ICSharpCode.Decompiler.TypeSystem.Implementation; using ICSharpCode.Decompiler.TypeSystem.Implementation;
using ICSharpCode.Decompiler.Util; using ICSharpCode.Decompiler.Util;
using Mono.Cecil;
namespace ICSharpCode.Decompiler.TypeSystem namespace ICSharpCode.Decompiler.TypeSystem
{ {
using BlobReader = BlobReader;
/// <summary> /// <summary>
/// Allows loading an IProjectContent from an already compiled assembly. /// Allows loading an IProjectContent from an already compiled assembly.
/// </summary> /// </summary>
/// <remarks>Instance methods are not thread-safe; you need to create multiple instances of CecilLoader /// <remarks>Instance methods are not thread-safe; you need to create multiple instances of CecilLoader
/// if you want to load multiple project contents in parallel.</remarks> /// if you want to load multiple project contents in parallel.</remarks>
public sealed class CecilLoader : AssemblyLoader public sealed class MetadataLoader
{ {
#region Options
/// <summary> /// <summary>
/// Version number of the cecil loader. /// Specifies whether to include internal members. The default is false.
/// Should be incremented when fixing bugs in the cecil loader so that project contents cached on disk
/// (which might be incorrect due to the bug) are re-created.
/// </summary> /// </summary>
const int cecilLoaderVersion = 1; public bool IncludeInternalMembers { get; set; }
#region Options /// <summary>
// Most options are defined in the AssemblyLoader base class /// Gets/Sets the cancellation token used by the assembly loader.
/// </summary>
public CancellationToken CancellationToken { get; set; }
InterningProvider interningProvider = new SimpleInterningProvider();
/// <summary>
/// Gets/Sets the interning provider.
/// </summary>
public InterningProvider InterningProvider {
get { return interningProvider; }
set {
if (value == null)
throw new ArgumentNullException();
interningProvider = value;
}
}
/// <summary> /// <summary>
/// Specifies whether to use lazy loading. The default is false. /// Specifies whether to use lazy loading. The default is false.
/// If this property is set to true, the CecilLoader will not copy all the relevant information /// If this property is set to true, the CecilLoader will not copy all the relevant information
@ -73,7 +88,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
/// Warning: if delay-loading is used and the type system is accessed by multiple threads, /// Warning: if delay-loading is used and the type system is accessed by multiple threads,
/// the callback may be invoked concurrently on multiple threads. /// the callback may be invoked concurrently on multiple threads.
/// </remarks> /// </remarks>
public Action<IUnresolvedEntity, MemberReference> OnEntityLoaded { get; set; } public Action<IUnresolvedEntity, EntityHandle> OnEntityLoaded { get; set; }
/// <summary> /// <summary>
/// Gets a value indicating whether this instance stores references to the cecil objects. /// Gets a value indicating whether this instance stores references to the cecil objects.
@ -98,21 +113,21 @@ namespace ICSharpCode.Decompiler.TypeSystem
} }
} }
#endregion #endregion
ModuleDefinition currentModule; MetadataReader currentModule;
DefaultUnresolvedAssembly currentAssembly; DefaultUnresolvedAssembly currentAssembly;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="CecilLoader"/> class. /// Initializes a new instance of the <see cref="MetadataLoader"/> class.
/// </summary> /// </summary>
public CecilLoader() public MetadataLoader()
{ {
} }
/// <summary> /// <summary>
/// Creates a nested CecilLoader for lazy-loading. /// Creates a nested CecilLoader for lazy-loading.
/// </summary> /// </summary>
private CecilLoader(CecilLoader loader) private MetadataLoader(MetadataLoader loader)
{ {
// use a shared typeSystemTranslationTable // use a shared typeSystemTranslationTable
this.typeSystemTranslationTable = loader.typeSystemTranslationTable; this.typeSystemTranslationTable = loader.typeSystemTranslationTable;
@ -129,74 +144,72 @@ namespace ICSharpCode.Decompiler.TypeSystem
#region Load From AssemblyDefinition #region Load From AssemblyDefinition
/// <summary> /// <summary>
/// Loads the assembly definition into a project content. /// Loads a module definition into a project content.
/// </summary>
/// <returns>Unresolved type system representing the assembly</returns>
public IUnresolvedAssembly LoadAssembly(AssemblyDefinition assemblyDefinition)
{
if (assemblyDefinition == null)
throw new ArgumentNullException("assemblyDefinition");
return LoadModule(assemblyDefinition.MainModule);
}
/// <summary>
/// Loads the module definition into a project content.
/// </summary> /// </summary>
/// <returns>Unresolved type system representing the assembly</returns> /// <returns>Unresolved type system representing the assembly</returns>
public IUnresolvedAssembly LoadModule(ModuleDefinition moduleDefinition) public IUnresolvedAssembly LoadModule(MetadataReader module)
{ {
if (moduleDefinition == null) this.currentModule = module;
throw new ArgumentNullException("moduleDefinition");
this.currentModule = moduleDefinition;
// Read assembly and module attributes // Read assembly and module attributes
IList<IUnresolvedAttribute> assemblyAttributes = new List<IUnresolvedAttribute>(); IList<IUnresolvedAttribute> assemblyAttributes = new List<IUnresolvedAttribute>();
IList<IUnresolvedAttribute> moduleAttributes = new List<IUnresolvedAttribute>(); IList<IUnresolvedAttribute> moduleAttributes = new List<IUnresolvedAttribute>();
AssemblyDefinition assemblyDefinition = moduleDefinition.Assembly; AssemblyDefinition assemblyDefinition = default(AssemblyDefinition);
if (assemblyDefinition != null) { if (currentModule.IsAssembly) {
AddAttributes(assemblyDefinition, assemblyAttributes); AddAttributes(currentModule.GetAssemblyDefinition(), assemblyAttributes);
} }
AddAttributes(moduleDefinition, moduleAttributes); AddAttributes(Handle.ModuleDefinition, moduleAttributes);
assemblyAttributes = interningProvider.InternList(assemblyAttributes); assemblyAttributes = interningProvider.InternList(assemblyAttributes);
moduleAttributes = interningProvider.InternList(moduleAttributes); moduleAttributes = interningProvider.InternList(moduleAttributes);
this.currentAssembly = new DefaultUnresolvedAssembly(assemblyDefinition != null ? assemblyDefinition.Name.FullName : moduleDefinition.Name); this.currentAssembly = new DefaultUnresolvedAssembly(currentModule.IsAssembly ? assemblyDefinition.GetFullName(currentModule) : currentModule.GetString(currentModule.GetModuleDefinition().Name));
currentAssembly.Location = moduleDefinition.FileName;
currentAssembly.AssemblyAttributes.AddRange(assemblyAttributes); currentAssembly.AssemblyAttributes.AddRange(assemblyAttributes);
currentAssembly.ModuleAttributes.AddRange(assemblyAttributes); currentAssembly.ModuleAttributes.AddRange(assemblyAttributes);
// Register type forwarders: // Register type forwarders:
foreach (ExportedType type in moduleDefinition.ExportedTypes) { foreach (ExportedTypeHandle t in currentModule.ExportedTypes) {
var type = currentModule.GetExportedType(t);
if (type.IsForwarder) { if (type.IsForwarder) {
throw new NotImplementedException();/*
switch (type.Implementation.Kind) {
case HandleKind.AssemblyFile:
throw new NotImplementedException(); // type is defined in another module.
case HandleKind.ExportedType:
break;
case HandleKind.AssemblyReference:
break;
}
int typeParameterCount; int typeParameterCount;
string ns = type.Namespace; string ns = currentModule.GetString(type.Namespace);
string name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(type.Name, out typeParameterCount); string name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(currentModule.GetString(type.Name), out typeParameterCount);
ns = interningProvider.Intern(ns); ns = interningProvider.Intern(ns);
name = interningProvider.Intern(name); name = interningProvider.Intern(name);
var typeRef = new GetClassTypeReference(GetAssemblyReference(type.Scope), ns, name, typeParameterCount);
var typeRef = new GetClassTypeReference(, ns, name, typeParameterCount);
typeRef = interningProvider.Intern(typeRef); typeRef = interningProvider.Intern(typeRef);
var key = new TopLevelTypeName(ns, name, typeParameterCount); var key = new TopLevelTypeName(ns, name, typeParameterCount);
currentAssembly.AddTypeForwarder(key, typeRef); currentAssembly.AddTypeForwarder(key, typeRef);*/
} }
} }
// Create and register all types: // Create and register all types:
CecilLoader cecilLoaderCloneForLazyLoading = LazyLoad ? new CecilLoader(this) : null; MetadataLoader cecilLoaderCloneForLazyLoading = LazyLoad ? new MetadataLoader(this) : null;
List<TypeDefinition> cecilTypeDefs = new List<TypeDefinition>(); List<TypeDefinition> cecilTypeDefs = new List<TypeDefinition>();
List<DefaultUnresolvedTypeDefinition> typeDefs = new List<DefaultUnresolvedTypeDefinition>(); List<DefaultUnresolvedTypeDefinition> typeDefs = new List<DefaultUnresolvedTypeDefinition>();
foreach (TypeDefinition td in moduleDefinition.Types) { foreach (TypeDefinitionHandle h in module.TypeDefinitions) {
this.CancellationToken.ThrowIfCancellationRequested(); this.CancellationToken.ThrowIfCancellationRequested();
var td = module.GetTypeDefinition(h);
if (this.IncludeInternalMembers || (td.Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.Public) { if (this.IncludeInternalMembers || (td.Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.Public) {
string name = td.Name; string name = module.GetString(td.Name);
if (name.Length == 0) if (name.Length == 0)
continue; continue;
if (this.LazyLoad) { if (this.LazyLoad) {
var t = new LazyCecilTypeDefinition(cecilLoaderCloneForLazyLoading, td); var t = new LazyCecilTypeDefinition(cecilLoaderCloneForLazyLoading, td);
currentAssembly.AddTypeDefinition(t); currentAssembly.AddTypeDefinition(t);
RegisterCecilObject(t, td); RegisterCecilObject(t, h);
} else { } else {
var t = CreateTopLevelTypeDefinition(td); var t = CreateTopLevelTypeDefinition(td);
cecilTypeDefs.Add(td); cecilTypeDefs.Add(td);
@ -210,7 +223,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
for (int i = 0; i < typeDefs.Count; i++) { for (int i = 0; i < typeDefs.Count; i++) {
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
@ -221,7 +234,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
// By freezing the assembly now, we ensure it is usable on multiple // By freezing the assembly now, we ensure it is usable on multiple
// threads without issues. // threads without issues.
currentAssembly.Freeze(); currentAssembly.Freeze();
var result = this.currentAssembly; var result = this.currentAssembly;
this.currentAssembly = null; this.currentAssembly = null;
this.currentModule = null; this.currentModule = null;
@ -233,7 +246,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
/// This causes ReadTypeReference() to use <see cref="DefaultAssemblyReference.CurrentAssembly"/> for references /// This causes ReadTypeReference() to use <see cref="DefaultAssemblyReference.CurrentAssembly"/> for references
/// in that module. /// in that module.
/// </summary> /// </summary>
public void SetCurrentModule(ModuleDefinition module) public void SetCurrentModule(MetadataReader module)
{ {
this.currentModule = module; this.currentModule = module;
} }
@ -243,12 +256,12 @@ namespace ICSharpCode.Decompiler.TypeSystem
/// </summary> /// </summary>
/// <param name="typeDefinition">The Cecil TypeDefinition.</param> /// <param name="typeDefinition">The Cecil TypeDefinition.</param>
/// <returns>ITypeDefinition representing the Cecil type.</returns> /// <returns>ITypeDefinition representing the Cecil type.</returns>
public IUnresolvedTypeDefinition LoadType(TypeDefinition typeDefinition) public IUnresolvedTypeDefinition LoadType(TypeDefinitionHandle typeDefinition)
{ {
if (typeDefinition == null) if (typeDefinition.IsNil)
throw new ArgumentNullException("typeDefinition"); throw new ArgumentNullException(nameof(typeDefinition));
var td = CreateTopLevelTypeDefinition(typeDefinition); var td = CreateTopLevelTypeDefinition(currentModule.GetTypeDefinition(typeDefinition));
InitTypeDefinition(typeDefinition, td); InitTypeDefinition(currentModule.GetTypeDefinition(typeDefinition), td);
return td; return td;
} }
#endregion #endregion
@ -263,34 +276,6 @@ namespace ICSharpCode.Decompiler.TypeSystem
return LoadModule(module); return LoadModule(module);
} }
} }
// used to prevent Cecil from loading referenced assemblies
sealed class DummyAssemblyResolver : IAssemblyResolver
{
public AssemblyDefinition Resolve(AssemblyNameReference name)
{
return null;
}
public AssemblyDefinition Resolve(string fullName)
{
return null;
}
public AssemblyDefinition Resolve(AssemblyNameReference name, ReaderParameters parameters)
{
return null;
}
public AssemblyDefinition Resolve(string fullName, ReaderParameters parameters)
{
return null;
}
public void Dispose()
{
}
}
#endregion #endregion
#region Read Type Reference #region Read Type Reference
@ -301,101 +286,51 @@ namespace ICSharpCode.Decompiler.TypeSystem
/// a type system type reference.</param> /// a type system type reference.</param>
/// <param name="typeAttributes">Attributes associated with the Cecil type reference. /// <param name="typeAttributes">Attributes associated with the Cecil type reference.
/// This is used to support the 'dynamic' type.</param> /// This is used to support the 'dynamic' type.</param>
public ITypeReference ReadTypeReference(TypeReference type, ICustomAttributeProvider typeAttributes = null) public ITypeReference ReadTypeReference(EntityHandle type, CustomAttributeHandleCollection typeAttributes = default(CustomAttributeHandleCollection))
{ {
int typeIndex = 0; int typeIndex = 0;
return CreateType(type, typeAttributes, ref typeIndex); return CreateType(type, typeAttributes, ref typeIndex);
} }
ITypeReference CreateType(TypeReference type, ICustomAttributeProvider typeAttributes, ref int typeIndex) class DynamicTypeVisitor : TypeVisitor
{ {
while (type is OptionalModifierType || type is RequiredModifierType) { public override IType VisitPointerType(PointerType type)
type = ((TypeSpecification)type).ElementType; {
} return base.VisitPointerType(type);
if (type == null) {
return SpecialType.UnknownType;
}
if (type is Mono.Cecil.ByReferenceType) {
typeIndex++;
return interningProvider.Intern(
new ByReferenceTypeReference(
CreateType(
(type as Mono.Cecil.ByReferenceType).ElementType,
typeAttributes, ref typeIndex)));
} else if (type is Mono.Cecil.PointerType) {
typeIndex++;
return interningProvider.Intern(
new PointerTypeReference(
CreateType(
(type as Mono.Cecil.PointerType).ElementType,
typeAttributes, ref typeIndex)));
} else if (type is Mono.Cecil.ArrayType) {
typeIndex++;
return interningProvider.Intern(
new ArrayTypeReference(
CreateType(
(type as Mono.Cecil.ArrayType).ElementType,
typeAttributes, ref typeIndex),
(type as Mono.Cecil.ArrayType).Rank));
} else if (type is GenericInstanceType) {
GenericInstanceType gType = (GenericInstanceType)type;
ITypeReference baseType = CreateType(gType.ElementType, typeAttributes, ref typeIndex);
ITypeReference[] para = new ITypeReference[gType.GenericArguments.Count];
for (int i = 0; i < para.Length; ++i) {
typeIndex++;
para[i] = CreateType(gType.GenericArguments[i], typeAttributes, ref typeIndex);
}
return interningProvider.Intern(new ParameterizedTypeReference(baseType, para));
} else if (type is GenericParameter) {
GenericParameter typeGP = (GenericParameter)type;
return TypeParameterReference.Create(typeGP.Owner is MethodReference ? SymbolKind.Method : SymbolKind.TypeDefinition, typeGP.Position);
} else if (type is FunctionPointerType) {
return KnownTypeReference.Get(KnownTypeCode.IntPtr);
} else if (type.IsNested) {
ITypeReference typeRef = CreateType(type.DeclaringType, typeAttributes, ref typeIndex);
int partTypeParameterCount;
string namepart = ReflectionHelper.SplitTypeParameterCountFromReflectionName(type.Name, out partTypeParameterCount);
namepart = interningProvider.Intern(namepart);
return interningProvider.Intern(new NestedTypeReference(typeRef, namepart, partTypeParameterCount));
} else {
string ns = interningProvider.Intern(type.Namespace ?? string.Empty);
string name = type.Name;
if (name == null)
throw new InvalidOperationException("type.Name returned null. Type: " + type.ToString());
if (name == "Object" && ns == "System" && HasDynamicAttribute(typeAttributes, typeIndex)) {
return SpecialType.Dynamic;
} else {
int typeParameterCount;
name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(name, out typeParameterCount);
name = interningProvider.Intern(name);
if (currentAssembly != null) {
IUnresolvedTypeDefinition c = currentAssembly.GetTypeDefinition(ns, name, typeParameterCount);
if (c != null)
return c;
}
return interningProvider.Intern(new GetClassTypeReference(GetAssemblyReference(type.Scope), ns, name, typeParameterCount));
}
} }
} }
IAssemblyReference GetAssemblyReference(IMetadataScope scope) ITypeReference CreateType(EntityHandle type, CustomAttributeHandleCollection typeAttributes, ref int typeIndex)
{ {
if (scope == null || scope == currentModule) ITypeReference CreateTypeReference(TypeReferenceHandle handle)
return DefaultAssemblyReference.CurrentAssembly; {
else var t = currentModule.GetTypeReference(handle);
return interningProvider.Intern(new DefaultAssemblyReference(scope.Name)); var asmref = handle.GetDeclaringAssembly(currentModule);
if (asmref.IsNil)
return new GetClassTypeReference(handle.GetFullTypeName(currentModule), DefaultAssemblyReference.CurrentAssembly);
var asm = currentModule.GetAssemblyReference(asmref);
return new GetClassTypeReference(handle.GetFullTypeName(currentModule), new DefaultAssemblyReference(currentModule.GetString(asm.Name)));
}
switch (type.Kind) {
case HandleKind.TypeSpecification:
return new SignatureTypeReference((TypeSpecificationHandle)type, currentModule);
case HandleKind.TypeReference:
return CreateTypeReference((TypeReferenceHandle)type);
case HandleKind.TypeDefinition:
return new DefaultUnresolvedTypeDefinition(type.GetFullTypeName(currentModule).ReflectionName);
}
} }
static bool HasDynamicAttribute(ICustomAttributeProvider attributeProvider, int typeIndex) bool HasDynamicAttribute(CustomAttributeHandleCollection attributes, int typeIndex)
{ {
if (attributeProvider == null || !attributeProvider.HasCustomAttributes) foreach (CustomAttributeHandle handle in attributes) {
return false; var a = currentModule.GetCustomAttribute(handle);
foreach (CustomAttribute a in attributeProvider.CustomAttributes) { var type = a.GetAttributeType(currentModule);
TypeReference type = a.AttributeType; if (type.GetFullTypeName(currentModule).ToString() == "System.Runtime.CompilerServices.DynamicAttribute") {
if (type.Name == "DynamicAttribute" && type.Namespace == "System.Runtime.CompilerServices") { var ctor = a.DecodeValue(new TypeSystemAttributeTypeProvider());
if (a.ConstructorArguments.Count == 1) { ctor.FixedArguments[0].
if (a..Count == 1) {
CustomAttributeArgument[] values = a.ConstructorArguments[0].Value as CustomAttributeArgument[]; CustomAttributeArgument[] values = a.ConstructorArguments[0].Value as CustomAttributeArgument[];
if (values != null && typeIndex < values.Length && values[typeIndex].Value is bool) if (values != null && typeIndex < values.Length && values[typeIndex].Value is bool)
return (bool)values[typeIndex].Value; return (bool)values[typeIndex].Value;
@ -413,17 +348,13 @@ namespace ICSharpCode.Decompiler.TypeSystem
void AddAttributes(AssemblyDefinition assembly, IList<IUnresolvedAttribute> outputList) void AddAttributes(AssemblyDefinition assembly, IList<IUnresolvedAttribute> outputList)
{ {
if (assembly.HasCustomAttributes) { AddCustomAttributes(currentModule.GetCustomAttributes((EntityHandle)Handle.AssemblyDefinition), outputList);
AddCustomAttributes(assembly.CustomAttributes, outputList); AddSecurityAttributes(assembly.GetDeclarativeSecurityAttributes(), outputList);
}
if (assembly.HasSecurityDeclarations) {
AddSecurityAttributes(assembly.SecurityDeclarations, outputList);
}
// AssemblyVersionAttribute // AssemblyVersionAttribute
if (assembly.Name.Version != null) { if (assembly.Version != null) {
var assemblyVersion = new DefaultUnresolvedAttribute(assemblyVersionAttributeTypeRef, new[] { KnownTypeReference.String }); var assemblyVersion = new DefaultUnresolvedAttribute(assemblyVersionAttributeTypeRef, new[] { KnownTypeReference.String });
assemblyVersion.PositionalArguments.Add(CreateSimpleConstantValue(KnownTypeReference.String, assembly.Name.Version.ToString())); assemblyVersion.PositionalArguments.Add(CreateSimpleConstantValue(KnownTypeReference.String, assembly.Version.ToString()));
outputList.Add(interningProvider.Intern(assemblyVersion)); outputList.Add(interningProvider.Intern(assemblyVersion));
} }
} }
@ -435,11 +366,9 @@ namespace ICSharpCode.Decompiler.TypeSystem
#endregion #endregion
#region Module Attributes #region Module Attributes
void AddAttributes(ModuleDefinition module, IList<IUnresolvedAttribute> outputList) void AddAttributes(ModuleDefinitionHandle module, IList<IUnresolvedAttribute> outputList)
{ {
if (module.HasCustomAttributes) { AddCustomAttributes(currentModule.GetCustomAttributes(module), outputList);
AddCustomAttributes(module.CustomAttributes, outputList);
}
} }
#endregion #endregion
@ -447,20 +376,16 @@ namespace ICSharpCode.Decompiler.TypeSystem
static readonly IUnresolvedAttribute inAttribute = new DefaultUnresolvedAttribute(typeof(InAttribute).ToTypeReference()); static readonly IUnresolvedAttribute inAttribute = new DefaultUnresolvedAttribute(typeof(InAttribute).ToTypeReference());
static readonly IUnresolvedAttribute outAttribute = new DefaultUnresolvedAttribute(typeof(OutAttribute).ToTypeReference()); static readonly IUnresolvedAttribute outAttribute = new DefaultUnresolvedAttribute(typeof(OutAttribute).ToTypeReference());
void AddAttributes(ParameterDefinition parameter, DefaultUnresolvedParameter targetParameter) void AddAttributes(Parameter parameter, DefaultUnresolvedParameter targetParameter)
{ {
if (!targetParameter.IsOut) { if (!targetParameter.IsOut) {
if (parameter.IsIn) if ((parameter.Attributes & ParameterAttributes.In) == ParameterAttributes.In)
targetParameter.Attributes.Add(inAttribute); targetParameter.Attributes.Add(inAttribute);
if (parameter.IsOut) if ((parameter.Attributes & ParameterAttributes.Out) == ParameterAttributes.Out)
targetParameter.Attributes.Add(outAttribute); targetParameter.Attributes.Add(outAttribute);
} }
if (parameter.HasCustomAttributes) { AddCustomAttributes(parameter.GetCustomAttributes(), targetParameter.Attributes);
AddCustomAttributes(parameter.CustomAttributes, targetParameter.Attributes); AddMarshalInfo(parameter.GetMarshallingDescriptor(), targetParameter.Attributes);
}
if (parameter.HasMarshalInfo) {
targetParameter.Attributes.Add(ConvertMarshalInfo(parameter.MarshalInfo));
}
} }
#endregion #endregion
@ -475,7 +400,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
static bool HasAnyAttributes(MethodDefinition methodDefinition) static bool HasAnyAttributes(MethodDefinition methodDefinition)
{ {
if (methodDefinition.HasPInvokeInfo) if (!methodDefinition.Attributes )
return true; return true;
if ((methodDefinition.ImplAttributes & ~MethodImplAttributes.CodeTypeMask) != 0) if ((methodDefinition.ImplAttributes & ~MethodImplAttributes.CodeTypeMask) != 0)
return true; return true;
@ -604,11 +529,11 @@ namespace ICSharpCode.Decompiler.TypeSystem
void AddAttributes(TypeDefinition typeDefinition, IUnresolvedTypeDefinition targetEntity) void AddAttributes(TypeDefinition typeDefinition, IUnresolvedTypeDefinition targetEntity)
{ {
// SerializableAttribute // SerializableAttribute
if (typeDefinition.IsSerializable) if ((typeDefinition.Attributes & TypeAttributes.Serializable) != 0)
targetEntity.Attributes.Add(serializableAttribute); targetEntity.Attributes.Add(serializableAttribute);
// ComImportAttribute // ComImportAttribute
if (typeDefinition.IsImport) if ((typeDefinition.Attributes & TypeAttributes.Import) != 0)
targetEntity.Attributes.Add(comImportAttribute); targetEntity.Attributes.Add(comImportAttribute);
#region StructLayoutAttribute #region StructLayoutAttribute
@ -633,29 +558,26 @@ namespace ICSharpCode.Decompiler.TypeSystem
charSet = CharSet.Unicode; charSet = CharSet.Unicode;
break; break;
} }
LayoutKind defaultLayoutKind = (typeDefinition.IsValueType && !typeDefinition.IsEnum) ? LayoutKind.Sequential: LayoutKind.Auto; var layout = typeDefinition.GetLayout();
if (layoutKind != defaultLayoutKind || charSet != CharSet.Ansi || typeDefinition.PackingSize > 0 || typeDefinition.ClassSize > 0) { LayoutKind defaultLayoutKind = (typeDefinition.IsValueType(currentModule) && !typeDefinition.IsEnum(currentModule)) ? LayoutKind.Sequential : LayoutKind.Auto;
if (layoutKind != defaultLayoutKind || charSet != CharSet.Ansi || layout.PackingSize > 0 || layout.Size > 0) {
DefaultUnresolvedAttribute structLayout = new DefaultUnresolvedAttribute(structLayoutAttributeTypeRef, new[] { layoutKindTypeRef }); DefaultUnresolvedAttribute structLayout = new DefaultUnresolvedAttribute(structLayoutAttributeTypeRef, new[] { layoutKindTypeRef });
structLayout.PositionalArguments.Add(CreateSimpleConstantValue(layoutKindTypeRef, (int)layoutKind)); structLayout.PositionalArguments.Add(CreateSimpleConstantValue(layoutKindTypeRef, (int)layoutKind));
if (charSet != CharSet.Ansi) { if (charSet != CharSet.Ansi) {
structLayout.AddNamedFieldArgument("CharSet", CreateSimpleConstantValue(charSetTypeRef, (int)charSet)); structLayout.AddNamedFieldArgument("CharSet", CreateSimpleConstantValue(charSetTypeRef, (int)charSet));
} }
if (typeDefinition.PackingSize > 0) { if (layout.PackingSize > 0) {
structLayout.AddNamedFieldArgument("Pack", CreateSimpleConstantValue(KnownTypeReference.Int32, (int)typeDefinition.PackingSize)); structLayout.AddNamedFieldArgument("Pack", CreateSimpleConstantValue(KnownTypeReference.Int32, (int)layout.PackingSize));
} }
if (typeDefinition.ClassSize > 0) { if (layout.Size > 0) {
structLayout.AddNamedFieldArgument("Size", CreateSimpleConstantValue(KnownTypeReference.Int32, (int)typeDefinition.ClassSize)); structLayout.AddNamedFieldArgument("Size", CreateSimpleConstantValue(KnownTypeReference.Int32, (int)layout.Size));
} }
targetEntity.Attributes.Add(interningProvider.Intern(structLayout)); targetEntity.Attributes.Add(interningProvider.Intern(structLayout));
} }
#endregion #endregion
if (typeDefinition.HasCustomAttributes) { AddCustomAttributes(typeDefinition.GetCustomAttributes(), targetEntity.Attributes);
AddCustomAttributes(typeDefinition.CustomAttributes, targetEntity.Attributes); AddSecurityAttributes(typeDefinition.GetDeclarativeSecurityAttributes(), targetEntity.Attributes);
}
if (typeDefinition.HasSecurityDeclarations) {
AddSecurityAttributes(typeDefinition.SecurityDeclarations, targetEntity.Attributes);
}
} }
#endregion #endregion
@ -678,7 +600,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
} }
if (fieldDefinition.HasMarshalInfo) { if (fieldDefinition.HasMarshalInfo) {
targetEntity.Attributes.Add(ConvertMarshalInfo(fieldDefinition.MarshalInfo)); targetEntity.Attributes.Add(ConvertMarshalInfo(fieldDefinition.GetMarshallingDescriptor()));
} }
if (fieldDefinition.HasCustomAttributes) { if (fieldDefinition.HasCustomAttributes) {
@ -717,8 +639,14 @@ namespace ICSharpCode.Decompiler.TypeSystem
#region MarshalAsAttribute (ConvertMarshalInfo) #region MarshalAsAttribute (ConvertMarshalInfo)
static readonly ITypeReference marshalAsAttributeTypeRef = typeof(MarshalAsAttribute).ToTypeReference(); static readonly ITypeReference marshalAsAttributeTypeRef = typeof(MarshalAsAttribute).ToTypeReference();
static readonly ITypeReference unmanagedTypeTypeRef = typeof(UnmanagedType).ToTypeReference(); static readonly ITypeReference unmanagedTypeTypeRef = typeof(UnmanagedType).ToTypeReference();
void AddMarshalInfo(BlobHandle marshalInfo, IList<IUnresolvedAttribute> target)
{
if (marshalInfo.IsNil) return;
}
IUnresolvedAttribute ConvertMarshalInfo(MarshalInfo marshalInfo) IUnresolvedAttribute ConvertMarshalInfo(System.Reflection.Metadata.BlobReader marshalInfo)
{ {
DefaultUnresolvedAttribute attr = new DefaultUnresolvedAttribute(marshalAsAttributeTypeRef, new[] { unmanagedTypeTypeRef }); DefaultUnresolvedAttribute attr = new DefaultUnresolvedAttribute(marshalAsAttributeTypeRef, new[] { unmanagedTypeTypeRef });
attr.PositionalArguments.Add(CreateSimpleConstantValue(unmanagedTypeTypeRef, (int)marshalInfo.NativeType)); attr.PositionalArguments.Add(CreateSimpleConstantValue(unmanagedTypeTypeRef, (int)marshalInfo.NativeType));
@ -759,26 +687,27 @@ namespace ICSharpCode.Decompiler.TypeSystem
#endregion #endregion
#region Custom Attributes (ReadAttribute) #region Custom Attributes (ReadAttribute)
void AddCustomAttributes(Mono.Collections.Generic.Collection<CustomAttribute> attributes, IList<IUnresolvedAttribute> targetCollection) void AddCustomAttributes(CustomAttributeHandleCollection attributes, IList<IUnresolvedAttribute> targetCollection)
{ {
foreach (var cecilAttribute in attributes) { foreach (var handle in attributes) {
TypeReference type = cecilAttribute.AttributeType; var attribute = currentModule.GetCustomAttribute(handle);
if (type.Namespace == "System.Runtime.CompilerServices") { var typeHandle = attribute.GetAttributeType(currentModule);
if (type.Name == "DynamicAttribute" || type.Name == "ExtensionAttribute" || type.Name == "DecimalConstantAttribute") switch (typeHandle.GetFullTypeName(currentModule).ReflectionName) {
case "System.Runtime.CompilerServices.DynamicAttribute":
case "System.Runtime.CompilerServices.ExtensionAttribute":
case "System.Runtime.CompilerServices.DecimalConstantAttribute":
case "System.ParamArrayAttribute":
continue; continue;
} else if (type.Name == "ParamArrayAttribute" && type.Namespace == "System") {
continue;
} }
targetCollection.Add(ReadAttribute(cecilAttribute)); targetCollection.Add(ReadAttribute(attribute));
} }
} }
public IUnresolvedAttribute ReadAttribute(CustomAttribute attribute) public IUnresolvedAttribute ReadAttribute(CustomAttribute attribute)
{ {
if (attribute == null) var ctor = attribute.Constructor;
throw new ArgumentNullException("attribute");
MethodReference ctor = attribute.Constructor; ITypeReference attributeType = ReadTypeReference(attribute.GetAttributeType(currentModule));
ITypeReference attributeType = ReadTypeReference(attribute.AttributeType);
IList<ITypeReference> ctorParameterTypes = EmptyList<ITypeReference>.Instance; IList<ITypeReference> ctorParameterTypes = EmptyList<ITypeReference>.Instance;
if (ctor.HasParameters) { if (ctor.HasParameters) {
ctorParameterTypes = new ITypeReference[ctor.Parameters.Count]; ctorParameterTypes = new ITypeReference[ctor.Parameters.Count];
@ -804,21 +733,17 @@ namespace ICSharpCode.Decompiler.TypeSystem
return result; return result;
} }
void AddSecurityAttributes(Mono.Collections.Generic.Collection<SecurityDeclaration> securityDeclarations, IList<IUnresolvedAttribute> targetCollection) void AddSecurityAttributes(DeclarativeSecurityAttributeHandleCollection securityDeclarations, IList<IUnresolvedAttribute> targetCollection)
{ {
foreach (var secDecl in securityDeclarations) { foreach (var secDecl in securityDeclarations) {
AddSecurityAttributes(secDecl, targetCollection); if (secDecl.IsNil) continue;
AddSecurityAttributes(currentModule.GetDeclarativeSecurityAttribute(secDecl), targetCollection);
} }
} }
void AddSecurityAttributes(SecurityDeclaration secDecl, IList<IUnresolvedAttribute> targetCollection) void AddSecurityAttributes(DeclarativeSecurityAttribute secDecl, IList<IUnresolvedAttribute> targetCollection)
{ {
byte[] blob; var blob = currentModule.GetBlobBytes(secDecl.PermissionSet);
try {
blob = secDecl.GetBlob();
} catch (NotSupportedException) {
return; // https://github.com/icsharpcode/SharpDevelop/issues/284
}
var blobSecDecl = new UnresolvedSecurityDeclarationBlob((int)secDecl.Action, blob); var blobSecDecl = new UnresolvedSecurityDeclarationBlob((int)secDecl.Action, blob);
targetCollection.AddRange(blobSecDecl.UnresolvedAttributes); targetCollection.AddRange(blobSecDecl.UnresolvedAttributes);
} }
@ -828,27 +753,29 @@ namespace ICSharpCode.Decompiler.TypeSystem
#region Read Type Definition #region Read Type Definition
DefaultUnresolvedTypeDefinition CreateTopLevelTypeDefinition(TypeDefinition typeDefinition) DefaultUnresolvedTypeDefinition CreateTopLevelTypeDefinition(TypeDefinition typeDefinition)
{ {
string name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(typeDefinition.Name); string name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(currentModule.GetString(typeDefinition.Name));
var td = new DefaultUnresolvedTypeDefinition(typeDefinition.Namespace, name); var td = new DefaultUnresolvedTypeDefinition(currentModule.GetString(typeDefinition.Namespace), name);
if (typeDefinition.HasGenericParameters) InitTypeParameters(typeDefinition, td.TypeParameters);
InitTypeParameters(typeDefinition, td.TypeParameters);
return td; return td;
} }
static void InitTypeParameters(TypeDefinition typeDefinition, IList<IUnresolvedTypeParameter> typeParameters) void InitTypeParameters(TypeDefinition typeDefinition, IList<IUnresolvedTypeParameter> typeParameters)
{ {
// Type parameters are initialized within the constructor so that the class can be put into the type storage // Type parameters are initialized within the constructor so that the class can be put into the type storage
// before the rest of the initialization runs - this allows it to be available for early binding as soon as possible. // before the rest of the initialization runs - this allows it to be available for early binding as soon as possible.
for (int i = 0; i < typeDefinition.GenericParameters.Count; i++) { var genericParams = typeDefinition.GetGenericParameters();
if (typeDefinition.GenericParameters[i].Position != i) for (int i = 0; i < genericParams.Count; i++) {
var gp = currentModule.GetGenericParameter(genericParams[i]);
if (gp.Index != i)
throw new InvalidOperationException("g.Position != i"); throw new InvalidOperationException("g.Position != i");
typeParameters.Add(new DefaultUnresolvedTypeParameter( typeParameters.Add(new DefaultUnresolvedTypeParameter(
SymbolKind.TypeDefinition, i, typeDefinition.GenericParameters[i].Name)); SymbolKind.TypeDefinition, i, currentModule.GetString(gp.Name)));
} }
} }
void InitTypeParameterConstraints(TypeDefinition typeDefinition, IList<IUnresolvedTypeParameter> typeParameters) void InitTypeParameterConstraints(TypeDefinition typeDefinition, IList<IUnresolvedTypeParameter> typeParameters)
{ {
var genericParams = typeDefinition.GetGenericParameters();
for (int i = 0; i < typeParameters.Count; i++) { for (int i = 0; i < typeParameters.Count; i++) {
var tp = (DefaultUnresolvedTypeParameter)typeParameters[i]; var tp = (DefaultUnresolvedTypeParameter)typeParameters[i];
AddConstraints(tp, typeDefinition.GenericParameters[i]); AddConstraints(tp, typeDefinition.GenericParameters[i]);
@ -1082,7 +1009,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
sealed class LazyCecilTypeDefinition : AbstractUnresolvedEntity, IUnresolvedTypeDefinition sealed class LazyCecilTypeDefinition : AbstractUnresolvedEntity, IUnresolvedTypeDefinition
{ {
// loader + cecilTypeDef, used for lazy-loading; and set to null after lazy loading is complete // loader + cecilTypeDef, used for lazy-loading; and set to null after lazy loading is complete
CecilLoader loader; MetadataLoader loader;
TypeDefinition cecilTypeDef; TypeDefinition cecilTypeDef;
readonly string namespaceName; readonly string namespaceName;
@ -1094,7 +1021,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
IList<IUnresolvedTypeDefinition> nestedTypes; IList<IUnresolvedTypeDefinition> nestedTypes;
IList<IUnresolvedMember> members; IList<IUnresolvedMember> members;
public LazyCecilTypeDefinition(CecilLoader loader, TypeDefinition typeDefinition) public LazyCecilTypeDefinition(MetadataLoader loader, TypeDefinition typeDefinition)
{ {
this.loader = loader; this.loader = loader;
this.cecilTypeDef = typeDefinition; this.cecilTypeDef = typeDefinition;
@ -1295,15 +1222,16 @@ namespace ICSharpCode.Decompiler.TypeSystem
#endregion #endregion
#region Read Method #region Read Method
public IUnresolvedMethod ReadMethod(MethodDefinition method, IUnresolvedTypeDefinition parentType, SymbolKind methodType = SymbolKind.Method) public IUnresolvedMethod ReadMethod(MethodDefinitionHandle method, IUnresolvedTypeDefinition parentType, SymbolKind methodType = SymbolKind.Method)
{ {
return ReadMethod(method, parentType, methodType, null); return ReadMethod(method, parentType, methodType, null);
} }
IUnresolvedMethod ReadMethod(MethodDefinition method, IUnresolvedTypeDefinition parentType, SymbolKind methodType, IUnresolvedMember accessorOwner) IUnresolvedMethod ReadMethod(MethodDefinitionHandle handle, IUnresolvedTypeDefinition parentType, SymbolKind methodType, IUnresolvedMember accessorOwner)
{ {
if (method == null) if (handle.IsNil)
return null; return null;
var method = currentModule.GetMethodDefinition(handle);
DefaultUnresolvedMethod m = new DefaultUnresolvedMethod(parentType, method.Name); DefaultUnresolvedMethod m = new DefaultUnresolvedMethod(parentType, method.Name);
m.SymbolKind = methodType; m.SymbolKind = methodType;
m.AccessorOwner = accessorOwner; m.AccessorOwner = accessorOwner;
@ -1399,42 +1327,43 @@ namespace ICSharpCode.Decompiler.TypeSystem
} }
} }
void TranslateModifiers(MethodDefinition method, AbstractUnresolvedMember m) void TranslateModifiers(MethodDefinitionHandle handle, AbstractUnresolvedMember m)
{ {
var method = currentModule.GetMethodDefinition(handle);
if (m.DeclaringTypeDefinition.Kind == TypeKind.Interface) { if (m.DeclaringTypeDefinition.Kind == TypeKind.Interface) {
// interface members don't have modifiers, but we want to handle them as "public abstract" // interface members don't have modifiers, but we want to handle them as "public abstract"
m.Accessibility = Accessibility.Public; m.Accessibility = Accessibility.Public;
m.IsAbstract = true; m.IsAbstract = true;
} else { } else {
m.Accessibility = GetAccessibility(method.Attributes); m.Accessibility = GetAccessibility(method.Attributes);
if (method.IsAbstract) { if ((method.Attributes & MethodAttributes.Abstract) == MethodAttributes.Abstract) {
m.IsAbstract = true; m.IsAbstract = true;
m.IsOverride = !method.IsNewSlot; m.IsOverride = (method.Attributes & MethodAttributes.NewSlot) != MethodAttributes.NewSlot;
} else if (method.IsFinal) { } else if ((method.Attributes & MethodAttributes.Final) == MethodAttributes.Final) {
if (!method.IsNewSlot) { if ((method.Attributes & MethodAttributes.NewSlot) != MethodAttributes.NewSlot) {
m.IsSealed = true; m.IsSealed = true;
m.IsOverride = true; m.IsOverride = true;
} }
} else if (method.IsVirtual) { } else if ((method.Attributes & MethodAttributes.Virtual) == MethodAttributes.Virtual) {
if (method.IsNewSlot) if ((method.Attributes & MethodAttributes.NewSlot) == MethodAttributes.NewSlot)
m.IsVirtual = true; m.IsVirtual = true;
else else
m.IsOverride = true; m.IsOverride = true;
} }
m.IsStatic = method.IsStatic; m.IsStatic = (method.Attributes & MethodAttributes.Static) == MethodAttributes.Static;
} }
} }
#endregion #endregion
#region Read Parameter #region Read Parameter
public IUnresolvedParameter ReadParameter(ParameterDefinition parameter) public IUnresolvedParameter ReadParameter(ParameterHandle handle, ITypeReference type)
{ {
if (parameter == null) if (handle.IsNil)
throw new ArgumentNullException("parameter"); throw new ArgumentNullException(nameof(handle));
var type = ReadTypeReference(parameter.ParameterType, typeAttributes: parameter); var parameter = currentModule.GetParameter(handle);
var p = new DefaultUnresolvedParameter(type, interningProvider.Intern(parameter.Name)); var p = new DefaultUnresolvedParameter(type, interningProvider.Intern(currentModule.GetString(parameter.Name)));
if (parameter.ParameterType is Mono.Cecil.ByReferenceType) { if (type is ByReferenceTypeReference) {
if (!parameter.IsIn && parameter.IsOut) if (!parameter.IsIn && parameter.IsOut)
p.IsOut = true; p.IsOut = true;
else else
@ -1505,18 +1434,19 @@ namespace ICSharpCode.Decompiler.TypeSystem
return new decimal((int)ctorArgs[4], (int)ctorArgs[3], (int)ctorArgs[2], (byte)ctorArgs[1] != 0, (byte)ctorArgs[0]); return new decimal((int)ctorArgs[4], (int)ctorArgs[3], (int)ctorArgs[2], (byte)ctorArgs[1] != 0, (byte)ctorArgs[0]);
} }
public IUnresolvedField ReadField(FieldDefinition field, IUnresolvedTypeDefinition parentType) public IUnresolvedField ReadField(FieldDefinitionHandle handle, IUnresolvedTypeDefinition parentType)
{ {
if (field == null) if (handle.IsNil)
throw new ArgumentNullException("field"); throw new ArgumentNullException(nameof(handle));
if (parentType == null) if (parentType == null)
throw new ArgumentNullException("parentType"); throw new ArgumentNullException(nameof(parentType));
DefaultUnresolvedField f = new DefaultUnresolvedField(parentType, field.Name); var field = currentModule.GetFieldDefinition(handle);
DefaultUnresolvedField f = new DefaultUnresolvedField(parentType, currentModule.GetString(field.Name));
f.Accessibility = GetAccessibility(field.Attributes); f.Accessibility = GetAccessibility(field.Attributes);
f.IsReadOnly = field.IsInitOnly; f.IsReadOnly = (field.Attributes & FieldAttributes.InitOnly) == FieldAttributes.InitOnly;
f.IsStatic = field.IsStatic; f.IsStatic = (field.Attributes & FieldAttributes.Static) == FieldAttributes.Static;
f.ReturnType = ReadTypeReference(field.FieldType, typeAttributes: field); f.ReturnType = field.DecodeSignature(new TypeReferenceSignatureDecoder(), default(Unit));
if (field.HasConstant) { if (field.HasConstant) {
f.ConstantValue = CreateSimpleConstantValue(f.ReturnType, field.Constant); f.ConstantValue = CreateSimpleConstantValue(f.ReturnType, field.Constant);
} }
@ -1570,14 +1500,13 @@ namespace ICSharpCode.Decompiler.TypeSystem
break; break;
} }
tp.HasReferenceTypeConstraint = g.HasReferenceTypeConstraint; tp.HasReferenceTypeConstraint = (g.Attributes & GenericParameterAttributes.ReferenceTypeConstraint) != 0;
tp.HasValueTypeConstraint = g.HasNotNullableValueTypeConstraint; tp.HasValueTypeConstraint = (g.Attributes & GenericParameterAttributes.NotNullableValueTypeConstraint) != 0;
tp.HasDefaultConstructorConstraint = g.HasDefaultConstructorConstraint; tp.HasDefaultConstructorConstraint = (g.Attributes & GenericParameterAttributes.DefaultConstructorConstraint) != 0;
if (g.HasConstraints) { foreach (GenericParameterConstraintHandle h in g.GetConstraints()) {
foreach (TypeReference constraint in g.Constraints) { var constraint = currentModule.GetGenericParameterConstraint(h);
tp.Constraints.Add(ReadTypeReference(constraint)); tp.Constraints.Add(ReadTypeReference(constraint.Type));
}
} }
} }
#endregion #endregion
@ -1608,67 +1537,90 @@ namespace ICSharpCode.Decompiler.TypeSystem
return left; return left;
} }
public IUnresolvedProperty ReadProperty(PropertyDefinition property, IUnresolvedTypeDefinition parentType, SymbolKind propertyType = SymbolKind.Property) public IUnresolvedProperty ReadProperty(PropertyDefinitionHandle handle, IUnresolvedTypeDefinition parentType, SymbolKind propertyType = SymbolKind.Property)
{ {
if (property == null) if (handle.IsNil)
throw new ArgumentNullException("property"); throw new ArgumentNullException(nameof(handle));
if (parentType == null) if (parentType == null)
throw new ArgumentNullException("parentType"); throw new ArgumentNullException(nameof(parentType));
DefaultUnresolvedProperty p = new DefaultUnresolvedProperty(parentType, property.Name); var property = currentModule.GetPropertyDefinition(handle);
var propertyName = currentModule.GetString(property.Name);
DefaultUnresolvedProperty p = new DefaultUnresolvedProperty(parentType, propertyName);
p.SymbolKind = propertyType; p.SymbolKind = propertyType;
TranslateModifiers(property.GetMethod ?? property.SetMethod, p); var accessors = property.GetAccessors();
if (property.GetMethod != null && property.SetMethod != null) TranslateModifiers(accessors.Getter.IsNil ? accessors.Setter : accessors.Getter, p);
p.Accessibility = MergePropertyAccessibility (GetAccessibility (property.GetMethod.Attributes), GetAccessibility (property.SetMethod.Attributes)); if (!accessors.Getter.IsNil && !accessors.Setter.IsNil)
p.Accessibility = MergePropertyAccessibility(GetAccessibility(currentModule.GetMethodDefinition(accessors.Getter).Attributes), GetAccessibility (currentModule.GetMethodDefinition(accessors.Setter).Attributes));
p.ReturnType = ReadTypeReference(property.PropertyType, typeAttributes: property); var signature = property.DecodeSignature(new TypeReferenceSignatureDecoder(), default(Unit));
p.ReturnType = signature.ReturnType;
p.Getter = ReadMethod(property.GetMethod, parentType, SymbolKind.Accessor, p);
p.Setter = ReadMethod(property.SetMethod, parentType, SymbolKind.Accessor, p);
if (property.HasParameters) { p.Getter = ReadMethod(accessors.Getter, parentType, SymbolKind.Accessor, p);
foreach (ParameterDefinition par in property.Parameters) { p.Setter = ReadMethod(accessors.Setter, parentType, SymbolKind.Accessor, p);
p.Parameters.Add(ReadParameter(par));
ParameterHandleCollection parameterHandles = default(ParameterHandleCollection);
int parameterCount = 0;
if (!accessors.Getter.IsNil) {
var getter = currentModule.GetMethodDefinition(accessors.Getter);
parameterHandles = getter.GetParameters();
parameterCount = parameterHandles.Count;
} else {
if (!accessors.Setter.IsNil) {
var setter = currentModule.GetMethodDefinition(accessors.Setter);
parameterHandles = setter.GetParameters();
parameterCount = parameterHandles.Count - 1;
} }
} }
int i = 0;
foreach (var par in parameterHandles) {
if (i >= parameterCount) break;
p.Parameters.Add(ReadParameter(par, signature.ParameterTypes[i]));
i++;
}
AddAttributes(property, p); AddAttributes(property, p);
var accessor = p.Getter ?? p.Setter; var accessor = p.Getter ?? p.Setter;
if (accessor != null && accessor.IsExplicitInterfaceImplementation) { if (accessor != null && accessor.IsExplicitInterfaceImplementation) {
if (ShortenInterfaceImplNames) if (ShortenInterfaceImplNames)
p.Name = property.Name.Substring(property.Name.LastIndexOf('.') + 1); p.Name = propertyName.Substring(propertyName.LastIndexOf('.') + 1);
p.IsExplicitInterfaceImplementation = true; p.IsExplicitInterfaceImplementation = true;
foreach (var mr in accessor.ExplicitInterfaceImplementations) { foreach (var mr in accessor.ExplicitInterfaceImplementations) {
p.ExplicitInterfaceImplementations.Add(new AccessorOwnerMemberReference(mr)); p.ExplicitInterfaceImplementations.Add(new AccessorOwnerMemberReference(mr));
} }
} }
FinishReadMember(p, property); FinishReadMember(p, handle);
return p; return p;
} }
#endregion #endregion
#region Read Event #region Read Event
public IUnresolvedEvent ReadEvent(EventDefinition ev, IUnresolvedTypeDefinition parentType) public IUnresolvedEvent ReadEvent(EventDefinitionHandle ev, IUnresolvedTypeDefinition parentType)
{ {
if (ev == null) if (ev.IsNil)
throw new ArgumentNullException("ev"); throw new ArgumentNullException(nameof(ev));
if (parentType == null) if (parentType == null)
throw new ArgumentNullException("parentType"); throw new ArgumentNullException(nameof(parentType));
DefaultUnresolvedEvent e = new DefaultUnresolvedEvent(parentType, ev.Name); var ed = currentModule.GetEventDefinition(ev);
TranslateModifiers(ev.AddMethod, e); var eventName = currentModule.GetString(ed.Name);
e.ReturnType = ReadTypeReference(ev.EventType, typeAttributes: ev);
DefaultUnresolvedEvent e = new DefaultUnresolvedEvent(parentType, eventName);
var accessors = ed.GetAccessors();
TranslateModifiers(accessors.Adder, e);
e.ReturnType = ReadTypeReference(ed.Type, typeAttributes: ed.GetCustomAttributes());
e.AddAccessor = ReadMethod(ev.AddMethod, parentType, SymbolKind.Accessor, e); e.AddAccessor = ReadMethod(accessors.Adder, parentType, SymbolKind.Accessor, e);
e.RemoveAccessor = ReadMethod(ev.RemoveMethod, parentType, SymbolKind.Accessor, e); e.RemoveAccessor = ReadMethod(accessors.Remover, parentType, SymbolKind.Accessor, e);
e.InvokeAccessor = ReadMethod(ev.InvokeMethod, parentType, SymbolKind.Accessor, e); e.InvokeAccessor = ReadMethod(accessors.Raiser, parentType, SymbolKind.Accessor, e);
AddAttributes(ev, e); AddAttributes(ed, e);
var accessor = e.AddAccessor ?? e.RemoveAccessor ?? e.InvokeAccessor; var accessor = e.AddAccessor ?? e.RemoveAccessor ?? e.InvokeAccessor;
if (accessor != null && accessor.IsExplicitInterfaceImplementation) { if (accessor != null && accessor.IsExplicitInterfaceImplementation) {
if (ShortenInterfaceImplNames) if (ShortenInterfaceImplNames)
e.Name = ev.Name.Substring(ev.Name.LastIndexOf('.') + 1); e.Name = eventName.Substring(eventName.LastIndexOf('.') + 1);
e.IsExplicitInterfaceImplementation = true; e.IsExplicitInterfaceImplementation = true;
foreach (var mr in accessor.ExplicitInterfaceImplementations) { foreach (var mr in accessor.ExplicitInterfaceImplementations) {
e.ExplicitInterfaceImplementations.Add(new AccessorOwnerMemberReference(mr)); e.ExplicitInterfaceImplementations.Add(new AccessorOwnerMemberReference(mr));
@ -1682,7 +1634,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
#endregion #endregion
#region FinishReadMember / Interning #region FinishReadMember / Interning
void FinishReadMember(AbstractUnresolvedMember member, MemberReference cecilDefinition) void FinishReadMember(AbstractUnresolvedMember member, EntityHandle cecilDefinition)
{ {
member.ApplyInterningProvider(interningProvider); member.ApplyInterningProvider(interningProvider);
member.Freeze(); member.Freeze();
@ -1691,17 +1643,16 @@ namespace ICSharpCode.Decompiler.TypeSystem
#endregion #endregion
#region Type system translation table #region Type system translation table
readonly Dictionary<object, object> typeSystemTranslationTable; readonly Dictionary<object, EntityHandle> typeSystemTranslationTable;
void RegisterCecilObject(IUnresolvedEntity typeSystemObject, MemberReference cecilObject) void RegisterCecilObject(IUnresolvedEntity typeSystemObject, EntityHandle cecilObject)
{ {
if (OnEntityLoaded != null) OnEntityLoaded?.Invoke(typeSystemObject, cecilObject);
OnEntityLoaded(typeSystemObject, cecilObject);
AddToTypeSystemTranslationTable(typeSystemObject, cecilObject); AddToTypeSystemTranslationTable(typeSystemObject, cecilObject);
} }
void AddToTypeSystemTranslationTable(object typeSystemObject, object cecilObject) void AddToTypeSystemTranslationTable(object typeSystemObject, EntityHandle cecilObject)
{ {
if (typeSystemTranslationTable != null) { if (typeSystemTranslationTable != null) {
// When lazy-loading, the dictionary might be shared between multiple cecil-loaders that are used concurrently // When lazy-loading, the dictionary might be shared between multiple cecil-loaders that are used concurrently
@ -1717,7 +1668,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
throw new ArgumentNullException ("typeSystemObject"); throw new ArgumentNullException ("typeSystemObject");
if (!HasCecilReferences) if (!HasCecilReferences)
throw new NotSupportedException ("This instance contains no cecil references."); throw new NotSupportedException ("This instance contains no cecil references.");
object result; EntityHandle result;
lock (typeSystemTranslationTable) { lock (typeSystemTranslationTable) {
if (!typeSystemTranslationTable.TryGetValue (typeSystemObject, out result)) if (!typeSystemTranslationTable.TryGetValue (typeSystemObject, out result))
return null; return null;

4
ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs

@ -23,7 +23,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
/// CecilLoader used for converting cecil type references to ITypeReference. /// CecilLoader used for converting cecil type references to ITypeReference.
/// May only be accessed within lock(typeReferenceCecilLoader). /// May only be accessed within lock(typeReferenceCecilLoader).
/// </summary> /// </summary>
readonly CecilLoader typeReferenceCecilLoader = new CecilLoader(); readonly MetadataLoader typeReferenceCecilLoader = new MetadataLoader();
/// <summary> /// <summary>
/// Dictionary for NRefactory->Cecil lookup. /// Dictionary for NRefactory->Cecil lookup.
@ -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;
CecilLoader cecilLoader = new CecilLoader { 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.

6
ICSharpCode.Decompiler/TypeSystem/IAssembly.cs

@ -35,12 +35,6 @@ namespace ICSharpCode.Decompiler.TypeSystem
/// </summary> /// </summary>
string FullAssemblyName { get; } string FullAssemblyName { get; }
/// <summary>
/// Gets the path to the assembly location.
/// For projects it is the same as the output path.
/// </summary>
string Location { get; }
/// <summary> /// <summary>
/// Gets the list of all assembly attributes in the project. /// Gets the list of all assembly attributes in the project.
/// </summary> /// </summary>

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

@ -98,17 +98,6 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
fullAssemblyName = value; fullAssemblyName = value;
} }
} }
string location;
public string Location {
get {
return location;
}
set {
FreezableHelper.ThrowIfFrozen(this);
location = value;
}
}
public IList<IUnresolvedAttribute> AssemblyAttributes { public IList<IUnresolvedAttribute> AssemblyAttributes {
get { return assemblyAttributes; } get { return assemblyAttributes; }

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

@ -0,0 +1,214 @@
// Copyright (c) 2017 Siegfried Pammer
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Collections.ObjectModel;
using System.Linq;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using ICSharpCode.Decompiler.Util;
namespace ICSharpCode.Decompiler.TypeSystem.Implementation
{
class SignatureTypeReference : ITypeReference
{
readonly TypeSpecification typeSpecification;
readonly MetadataReader reader;
public SignatureTypeReference(TypeSpecificationHandle handle, MetadataReader reader)
{
this.typeSpecification = reader.GetTypeSpecification(handle);
this.reader = reader;
}
public IType Resolve(ITypeResolveContext context)
{
return typeSpecification.DecodeSignature(new TypeReferenceSignatureDecoder(), default(Unit)).Resolve(context);
}
}
public sealed class PinnedType : TypeWithElementType
{
public PinnedType(IType elementType)
: base(elementType)
{
}
public override string NameSuffix => " pinned";
public override bool? IsReferenceType => elementType.IsReferenceType;
public override TypeKind Kind => TypeKind.Other;
public override ITypeReference ToTypeReference()
{
return new PinnedTypeReference(elementType.ToTypeReference());
}
public override IType VisitChildren(TypeVisitor visitor)
{
var newType = elementType.AcceptVisitor(visitor);
if (newType == elementType)
return this;
return new PinnedType(newType);
}
}
public sealed class PinnedTypeReference : ITypeReference
{
readonly ITypeReference elementType;
public PinnedTypeReference(ITypeReference elementType)
{
this.elementType = elementType;
}
public IType Resolve(ITypeResolveContext context)
{
return new PinnedType(elementType.Resolve(context));
}
}
public struct Unit { }
class TypeReferenceSignatureDecoder : ISignatureTypeProvider<ITypeReference, Unit>
{
public ITypeReference GetArrayType(ITypeReference elementType, ArrayShape shape)
{
return new ArrayTypeReference(elementType, shape.Rank);
}
public ITypeReference GetByReferenceType(ITypeReference elementType)
{
return new ByReferenceTypeReference(elementType);
}
public ITypeReference GetFunctionPointerType(MethodSignature<ITypeReference> signature)
{
return KnownTypeReference.IntPtr;
}
public ITypeReference GetGenericInstantiation(ITypeReference genericType, ImmutableArray<ITypeReference> typeArguments)
{
return new ParameterizedTypeReference(genericType, typeArguments);
}
public ITypeReference GetGenericMethodParameter(Unit genericContext, int index)
{
return new TypeParameterReference(SymbolKind.Method, index);
}
public ITypeReference GetGenericTypeParameter(Unit genericContext, int index)
{
return new TypeParameterReference(SymbolKind.TypeDefinition, index);
}
public ITypeReference GetModifiedType(ITypeReference modifier, ITypeReference unmodifiedType, bool isRequired)
{
return unmodifiedType;
}
public ITypeReference GetPinnedType(ITypeReference elementType)
{
return new PinnedTypeReference(elementType);
}
public ITypeReference GetPointerType(ITypeReference elementType)
{
return new PointerTypeReference(elementType);
}
public ITypeReference GetPrimitiveType(PrimitiveTypeCode typeCode)
{
return KnownTypeReference.Get(typeCode.ToKnownTypeCode());
}
public ITypeReference GetSZArrayType(ITypeReference elementType)
{
return new ArrayTypeReference(elementType);
}
public ITypeReference GetTypeFromDefinition(MetadataReader reader, TypeDefinitionHandle handle, byte rawTypeKind)
{
return new DefaultUnresolvedTypeDefinition(handle.GetFullTypeName(reader).ReflectionName);
}
public ITypeReference GetTypeFromReference(MetadataReader reader, TypeReferenceHandle handle, byte rawTypeKind)
{
var asmref = handle.GetDeclaringAssembly(reader);
if (asmref.IsNil)
return new GetClassTypeReference(handle.GetFullTypeName(reader), DefaultAssemblyReference.CurrentAssembly);
var asm = reader.GetAssemblyReference(asmref);
return new GetClassTypeReference(handle.GetFullTypeName(reader), new DefaultAssemblyReference(reader.GetString(asm.Name)));
}
public ITypeReference GetTypeFromSpecification(MetadataReader reader, Unit genericContext, TypeSpecificationHandle handle, byte rawTypeKind)
{
return new SignatureTypeReference(handle, reader);
}
}
class TypeSystemAttributeTypeProvider : ICustomAttributeTypeProvider<ITypeReference>
{
public ITypeReference GetPrimitiveType(PrimitiveTypeCode typeCode)
{
return KnownTypeReference.Get(typeCode.ToKnownTypeCode());
}
public ITypeReference GetSystemType()
{
return KnownTypeReference.Get(KnownTypeCode.Type);
}
public ITypeReference GetSZArrayType(ITypeReference elementType)
{
return new ArrayTypeReference(elementType);
}
public ITypeReference GetTypeFromDefinition(MetadataReader reader, TypeDefinitionHandle handle, byte rawTypeKind)
{
var type = reader.GetTypeDefinition(handle);
return new DefaultUnresolvedTypeDefinition(type.GetFullTypeName(reader).ToString());
}
public ITypeReference GetTypeFromReference(MetadataReader reader, TypeReferenceHandle handle, byte rawTypeKind)
{
return new DefaultUnresolvedTypeDefinition(handle.GetFullTypeName(reader).ToString());
}
public ITypeReference GetTypeFromSerializedName(string name)
{
return new GetClassTypeReference(new FullTypeName(name));
}
public PrimitiveTypeCode GetUnderlyingEnumType(ITypeReference type)
{
var def = type.GetEnumUnderlyingType().GetDefinition();
if (def == null)
throw new InvalidOperationException();
return def.KnownTypeCode.ToPrimtiveTypeCode();
}
public bool IsSystemType(IType type)
{
return type.IsKnownType(KnownTypeCode.Type);
}
}
}

13
ICSharpCode.Decompiler/TypeSystem/KnownTypeReference.cs

@ -123,6 +123,8 @@ namespace ICSharpCode.Decompiler.TypeSystem
INotifyCompletion, INotifyCompletion,
/// <summary><c>System.Runtime.CompilerServices.ICriticalNotifyCompletion</c></summary> /// <summary><c>System.Runtime.CompilerServices.ICriticalNotifyCompletion</c></summary>
ICriticalNotifyCompletion, ICriticalNotifyCompletion,
/// <summary><c>System.TypedReference</c></summary>
TypedReference,
} }
/// <summary> /// <summary>
@ -131,8 +133,8 @@ namespace ICSharpCode.Decompiler.TypeSystem
[Serializable] [Serializable]
public sealed class KnownTypeReference : ITypeReference public sealed class KnownTypeReference : ITypeReference
{ {
internal const int KnownTypeCodeCount = (int)KnownTypeCode.ICriticalNotifyCompletion + 1; internal const int KnownTypeCodeCount = (int)KnownTypeCode.TypedReference + 1;
static readonly KnownTypeReference[] knownTypeReferences = new KnownTypeReference[KnownTypeCodeCount] { static readonly KnownTypeReference[] knownTypeReferences = new KnownTypeReference[KnownTypeCodeCount] {
null, // None null, // None
new KnownTypeReference(KnownTypeCode.Object, "System", "Object", baseType: KnownTypeCode.None), new KnownTypeReference(KnownTypeCode.Object, "System", "Object", baseType: KnownTypeCode.None),
@ -181,6 +183,8 @@ namespace ICSharpCode.Decompiler.TypeSystem
new KnownTypeReference(KnownTypeCode.IDisposable, "System", "IDisposable"), new KnownTypeReference(KnownTypeCode.IDisposable, "System", "IDisposable"),
new KnownTypeReference(KnownTypeCode.INotifyCompletion, "System.Runtime.CompilerServices", "INotifyCompletion"), new KnownTypeReference(KnownTypeCode.INotifyCompletion, "System.Runtime.CompilerServices", "INotifyCompletion"),
new KnownTypeReference(KnownTypeCode.ICriticalNotifyCompletion, "System.Runtime.CompilerServices", "ICriticalNotifyCompletion"), new KnownTypeReference(KnownTypeCode.ICriticalNotifyCompletion, "System.Runtime.CompilerServices", "ICriticalNotifyCompletion"),
new KnownTypeReference(KnownTypeCode.TypedReference, "System", "TypedReference", baseType: KnownTypeCode.ValueType),
}; };
/// <summary> /// <summary>
@ -411,6 +415,11 @@ namespace ICSharpCode.Decompiler.TypeSystem
/// Gets a type reference pointing to the <c>System.Runtime.CompilerServices.ICriticalNotifyCompletion</c> type. /// Gets a type reference pointing to the <c>System.Runtime.CompilerServices.ICriticalNotifyCompletion</c> type.
/// </summary> /// </summary>
public static readonly KnownTypeReference ICriticalNotifyCompletion = Get(KnownTypeCode.ICriticalNotifyCompletion); public static readonly KnownTypeReference ICriticalNotifyCompletion = Get(KnownTypeCode.ICriticalNotifyCompletion);
/// <summary>
/// Gets a type reference pointing to the <c>System.TypedReference</c> type.
/// </summary>
public static readonly KnownTypeReference TypedReference = Get(KnownTypeCode.TypedReference);
readonly KnownTypeCode knownTypeCode; readonly KnownTypeCode knownTypeCode;
readonly string namespaceName; readonly string namespaceName;

199
ICSharpCode.Decompiler/TypeSystem/MetadataExtensions.cs

@ -0,0 +1,199 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection.Metadata;
using System.Text;
using System.Threading.Tasks;
namespace ICSharpCode.Decompiler.TypeSystem
{
static class MetadataExtensions
{
/// <summary>
/// Gets the type of the attribute.
/// </summary>
/// <returns>Either <see cref="TypeDefinitionHandle"/>, <see cref="TypeReferenceHandle"/>,<see cref="TypeSpecificationHandle".</returns>
public static EntityHandle GetAttributeType(this CustomAttribute attribute, MetadataReader reader)
{
switch (attribute.Constructor.Kind) {
case HandleKind.MethodDefinition:
var md = reader.GetMethodDefinition((MethodDefinitionHandle)attribute.Constructor);
return md.GetDeclaringType();
case HandleKind.MemberReference:
var mr = reader.GetMemberReference((MemberReferenceHandle)attribute.Constructor);
return mr.Parent;
default:
throw new NotSupportedException();
}
}
public static FullTypeName GetFullTypeName(this EntityHandle handle, MetadataReader reader)
{
switch (handle.Kind) {
case HandleKind.TypeDefinition:
return ((TypeDefinitionHandle)handle).GetFullTypeName(reader);
case HandleKind.TypeReference:
return ((TypeReferenceHandle)handle).GetFullTypeName(reader);
default:
throw new NotSupportedException();
}
}
public static FullTypeName GetFullTypeName(this TypeReferenceHandle handle, MetadataReader reader)
{
var tr = reader.GetTypeReference(handle);
TypeReferenceHandle declaringTypeHandle;
if ((declaringTypeHandle = tr.GetDeclaringType()).IsNil) {
string @namespace = tr.Namespace.IsNil ? "" : reader.GetString(tr.Namespace);
return new FullTypeName(new TopLevelTypeName(@namespace, reader.GetString(tr.Name)));
} else {
return declaringTypeHandle.GetFullTypeName(reader).NestedType(reader.GetString(tr.Name), 0);
}
}
public static FullTypeName GetFullTypeName(this TypeDefinitionHandle handle, MetadataReader reader)
{
return reader.GetTypeDefinition(handle).GetFullTypeName(reader);
}
public static FullTypeName GetFullTypeName(this TypeDefinition td, MetadataReader reader)
{
TypeDefinitionHandle declaringTypeHandle;
if ((declaringTypeHandle = td.GetDeclaringType()).IsNil) {
string @namespace = td.Namespace.IsNil ? "" : reader.GetString(td.Namespace);
return new FullTypeName(new TopLevelTypeName(@namespace, reader.GetString(td.Name), td.GetGenericParameters().Count));
} else {
return declaringTypeHandle.GetFullTypeName(reader).NestedType(reader.GetString(td.Name), td.GetGenericParameters().Count);
}
}
public static TypeReferenceHandle GetDeclaringType(this TypeReference tr)
{
switch (tr.ResolutionScope.Kind) {
case HandleKind.TypeReference:
return (TypeReferenceHandle)tr.ResolutionScope;
default:
return default(TypeReferenceHandle);
}
}
public static AssemblyReferenceHandle GetDeclaringAssembly(this TypeReferenceHandle handle, MetadataReader reader)
{
var tr = reader.GetTypeReference(handle);
switch (tr.ResolutionScope.Kind) {
case HandleKind.TypeReference:
return ((TypeReferenceHandle)tr.ResolutionScope).GetDeclaringAssembly(reader);
case HandleKind.AssemblyReference:
return (AssemblyReferenceHandle)tr.ResolutionScope;
default:
return default(AssemblyReferenceHandle);
}
}
public static bool IsValueType(this TypeDefinition typeDefinition, MetadataReader reader)
{
if (typeDefinition.BaseType.IsNil)
return false;
var baseType = typeDefinition.BaseType.GetFullTypeName(reader).ToString();
if (baseType == "System.Enum")
return true;
var thisType = typeDefinition.GetFullTypeName(reader).ToString();
return baseType == "System.ValueType" && thisType != "System.Enum";
}
public static bool IsEnum(this TypeDefinition typeDefinition, MetadataReader reader)
{
if (typeDefinition.BaseType.IsNil)
return false;
return typeDefinition.BaseType.GetFullTypeName(reader).ToString() == "System.Enum";
}
public static PrimitiveTypeCode ToPrimtiveTypeCode(this KnownTypeCode typeCode)
{
switch (typeCode) {
case KnownTypeCode.Object:
return PrimitiveTypeCode.Object;
case KnownTypeCode.Boolean:
return PrimitiveTypeCode.Boolean;
case KnownTypeCode.Char:
return PrimitiveTypeCode.Char;
case KnownTypeCode.SByte:
return PrimitiveTypeCode.SByte;
case KnownTypeCode.Byte:
return PrimitiveTypeCode.Byte;
case KnownTypeCode.Int16:
return PrimitiveTypeCode.Int16;
case KnownTypeCode.UInt16:
return PrimitiveTypeCode.UInt16;
case KnownTypeCode.Int32:
return PrimitiveTypeCode.Int32;
case KnownTypeCode.UInt32:
return PrimitiveTypeCode.UInt32;
case KnownTypeCode.Int64:
return PrimitiveTypeCode.Int64;
case KnownTypeCode.UInt64:
return PrimitiveTypeCode.UInt64;
case KnownTypeCode.Single:
return PrimitiveTypeCode.Single;
case KnownTypeCode.Double:
return PrimitiveTypeCode.Double;
case KnownTypeCode.String:
return PrimitiveTypeCode.String;
case KnownTypeCode.Void:
return PrimitiveTypeCode.Void;
case KnownTypeCode.TypedReference:
return PrimitiveTypeCode.TypedReference;
case KnownTypeCode.IntPtr:
return PrimitiveTypeCode.IntPtr;
case KnownTypeCode.UIntPtr:
return PrimitiveTypeCode.UIntPtr;
default:
throw new NotSupportedException();
}
}
public static KnownTypeCode ToKnownTypeCode(this PrimitiveTypeCode typeCode)
{
switch (typeCode) {
case PrimitiveTypeCode.Boolean:
return KnownTypeCode.Boolean;
case PrimitiveTypeCode.Byte:
return KnownTypeCode.Byte;
case PrimitiveTypeCode.SByte:
return KnownTypeCode.SByte;
case PrimitiveTypeCode.Char:
return KnownTypeCode.Byte;
case PrimitiveTypeCode.Int16:
return KnownTypeCode.Byte;
case PrimitiveTypeCode.UInt16:
return KnownTypeCode.Byte;
case PrimitiveTypeCode.Int32:
return KnownTypeCode.Int32;
case PrimitiveTypeCode.UInt32:
return KnownTypeCode.UInt32;
case PrimitiveTypeCode.Int64:
return KnownTypeCode.Int64;
case PrimitiveTypeCode.UInt64:
return KnownTypeCode.UInt64;
case PrimitiveTypeCode.Single:
return KnownTypeCode.Single;
case PrimitiveTypeCode.Double:
return KnownTypeCode.Double;
case PrimitiveTypeCode.IntPtr:
return KnownTypeCode.IntPtr;
case PrimitiveTypeCode.UIntPtr:
return KnownTypeCode.UIntPtr;
case PrimitiveTypeCode.Object:
return KnownTypeCode.Object;
case PrimitiveTypeCode.String:
return KnownTypeCode.String;
case PrimitiveTypeCode.TypedReference:
return KnownTypeCode.TypedReference;
case PrimitiveTypeCode.Void:
return KnownTypeCode.Void;
default:
return KnownTypeCode.None;
}
}
}
}

65
ILSpy/Cecil/CecilExtensions.cs

@ -0,0 +1,65 @@
// 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 System.Linq;
using ICSharpCode.Decompiler.TypeSystem;
using Mono.Cecil;
using Mono.Cecil.Cil;
using ArrayType = Mono.Cecil.ArrayType;
namespace ICSharpCode.ILSpy.Cecil
{
/// <summary>
/// Cecil helper methods.
/// </summary>
public static class CecilExtensions
{
public static HashSet<MethodDefinition> GetAccessorMethods(this TypeDefinition type)
{
HashSet<MethodDefinition> accessorMethods = new HashSet<MethodDefinition>();
foreach (var property in type.Properties) {
accessorMethods.Add(property.GetMethod);
accessorMethods.Add(property.SetMethod);
if (property.HasOtherMethods) {
foreach (var m in property.OtherMethods)
accessorMethods.Add(m);
}
}
foreach (EventDefinition ev in type.Events) {
accessorMethods.Add(ev.AddMethod);
accessorMethods.Add(ev.RemoveMethod);
accessorMethods.Add(ev.InvokeMethod);
if (ev.HasOtherMethods) {
foreach (var m in ev.OtherMethods)
accessorMethods.Add(m);
}
}
return accessorMethods;
}
public static TypeDefinition ResolveWithinSameModule(this TypeReference type)
{
if (type != null && type.GetElementType().Module == type.Module)
return type.Resolve();
else
return null;
}
}
}

2
ICSharpCode.Decompiler/TypeSystem/TypesHierarchyHelpers.cs → ILSpy/Cecil/TypesHierarchyHelpers.cs

@ -22,7 +22,7 @@ using System.Collections.ObjectModel;
using System.Linq; using System.Linq;
using Mono.Cecil; using Mono.Cecil;
namespace ICSharpCode.Decompiler.TypeSystem namespace ICSharpCode.ILSpy.Cecil
{ {
public static class TypesHierarchyHelpers public static class TypesHierarchyHelpers
{ {

2
ILSpy/ILSpy.csproj

@ -75,6 +75,8 @@
<Compile Include="AssemblyListManager.cs" /> <Compile Include="AssemblyListManager.cs" />
<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\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" />

2
ILSpy/Languages/CSharpILMixedLanguage.cs

@ -21,6 +21,7 @@ using Mono.Cecil.Cil;
namespace ICSharpCode.ILSpy namespace ICSharpCode.ILSpy
{ {
#if false
[Export(typeof(Language))] [Export(typeof(Language))]
class CSharpILMixedLanguage : ILLanguage class CSharpILMixedLanguage : ILLanguage
{ {
@ -145,4 +146,5 @@ namespace ICSharpCode.ILSpy
} }
} }
} }
#endif
} }

2
ILSpy/Languages/ILAstLanguage.cs

@ -77,7 +77,7 @@ namespace ICSharpCode.ILSpy
public override void DecompileMethod(MethodDefinition method, ITextOutput output, DecompilationOptions options) public override void DecompileMethod(MethodDefinition method, ITextOutput output, DecompilationOptions options)
{ {
base.DecompileMethod(method, output, options); base.DecompileMethod(method, output, options);
new ReflectionDisassembler(output, options.CancellationToken).DisassembleMethodHeader(method); //new ReflectionDisassembler(output, options.CancellationToken).DisassembleMethodHeader(method);
output.WriteLine(); output.WriteLine();
output.WriteLine(); output.WriteLine();
} }

132
ILSpy/Languages/ILLanguage.cs

@ -19,8 +19,12 @@
using System.Collections.Generic; using System.Collections.Generic;
using ICSharpCode.Decompiler; using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Disassembler; using ICSharpCode.Decompiler.Disassembler;
using Mono.Cecil;
using System.ComponentModel.Composition; using System.ComponentModel.Composition;
using System.Reflection.PortableExecutable;
using System.Reflection.Metadata;
using System.IO;
using System.Reflection.Metadata.Ecma335;
using System.Linq;
namespace ICSharpCode.ILSpy namespace ICSharpCode.ILSpy
{ {
@ -44,95 +48,111 @@ namespace ICSharpCode.ILSpy
get { return ".il"; } get { return ".il"; }
} }
protected virtual ReflectionDisassembler CreateDisassembler(ITextOutput output, DecompilationOptions options) protected virtual ReflectionDisassembler CreateDisassembler(ITextOutput output, PEReader reader, DecompilationOptions options)
{ {
return new ReflectionDisassembler(output, options.CancellationToken) { return new ReflectionDisassembler(output, reader, options.CancellationToken) {
DetectControlStructure = detectControlStructure, DetectControlStructure = detectControlStructure,
ShowSequencePoints = options.DecompilerSettings.ShowDebugInfo ShowSequencePoints = options.DecompilerSettings.ShowDebugInfo
}; };
} }
public override void DecompileMethod(MethodDefinition method, ITextOutput output, DecompilationOptions options) public override void DecompileMethod(Mono.Cecil.MethodDefinition method, ITextOutput output, DecompilationOptions options)
{ {
var dis = CreateDisassembler(output, options); using (var reader = new PEReader(new FileStream(method.Module.FileName, FileMode.Open, FileAccess.Read))) {
dis.DisassembleMethod(method); var dis = CreateDisassembler(output, reader, options);
dis.DisassembleMethod(MetadataTokens.MethodDefinitionHandle(method.MetadataToken.ToInt32()));
}
} }
public override void DecompileField(FieldDefinition field, ITextOutput output, DecompilationOptions options) public override void DecompileField(Mono.Cecil.FieldDefinition field, ITextOutput output, DecompilationOptions options)
{ {
var dis = CreateDisassembler(output, options); using (var reader = new PEReader(new FileStream(field.Module.FileName, FileMode.Open, FileAccess.Read))) {
dis.DisassembleField(field); var dis = CreateDisassembler(output, reader, options);
dis.DisassembleField(MetadataTokens.FieldDefinitionHandle(field.MetadataToken.ToInt32()));
}
} }
public override void DecompileProperty(PropertyDefinition property, ITextOutput output, DecompilationOptions options) public override void DecompileProperty(Mono.Cecil.PropertyDefinition property, ITextOutput output, DecompilationOptions options)
{ {
ReflectionDisassembler rd = CreateDisassembler(output, options); using (var reader = new PEReader(new FileStream(property.Module.FileName, FileMode.Open, FileAccess.Read))) {
rd.DisassembleProperty(property); var dis = CreateDisassembler(output, reader, options);
if (property.GetMethod != null) { dis.DisassembleProperty(MetadataTokens.PropertyDefinitionHandle(property.MetadataToken.ToInt32()));
output.WriteLine();
rd.DisassembleMethod(property.GetMethod); if (property.GetMethod != null) {
} output.WriteLine();
if (property.SetMethod != null) { dis.DisassembleMethod(MetadataTokens.MethodDefinitionHandle(property.GetMethod.MetadataToken.ToInt32()));
output.WriteLine(); }
rd.DisassembleMethod(property.SetMethod); if (property.SetMethod != null) {
} output.WriteLine();
foreach (var m in property.OtherMethods) { dis.DisassembleMethod(MetadataTokens.MethodDefinitionHandle(property.SetMethod.MetadataToken.ToInt32()));
output.WriteLine(); }
rd.DisassembleMethod(m); foreach (var m in property.OtherMethods) {
output.WriteLine();
dis.DisassembleMethod(MetadataTokens.MethodDefinitionHandle(m.MetadataToken.ToInt32()));
}
} }
} }
public override void DecompileEvent(EventDefinition ev, ITextOutput output, DecompilationOptions options) public override void DecompileEvent(Mono.Cecil.EventDefinition ev, ITextOutput output, DecompilationOptions options)
{ {
ReflectionDisassembler rd = CreateDisassembler(output, options); using (var reader = new PEReader(new FileStream(ev.Module.FileName, FileMode.Open, FileAccess.Read))) {
rd.DisassembleEvent(ev); var dis = CreateDisassembler(output, reader, options);
if (ev.AddMethod != null) { dis.DisassembleEvent(MetadataTokens.EventDefinitionHandle(ev.MetadataToken.ToInt32()));
output.WriteLine(); if (ev.AddMethod != null) {
rd.DisassembleMethod(ev.AddMethod); output.WriteLine();
} dis.DisassembleMethod(MetadataTokens.MethodDefinitionHandle(ev.AddMethod.MetadataToken.ToInt32()));
if (ev.RemoveMethod != null) { }
output.WriteLine(); if (ev.RemoveMethod != null) {
rd.DisassembleMethod(ev.RemoveMethod); output.WriteLine();
} dis.DisassembleMethod(MetadataTokens.MethodDefinitionHandle(ev.RemoveMethod.MetadataToken.ToInt32()));
foreach (var m in ev.OtherMethods) { }
output.WriteLine(); foreach (var m in ev.OtherMethods) {
rd.DisassembleMethod(m); output.WriteLine();
dis.DisassembleMethod(MetadataTokens.MethodDefinitionHandle(m.MetadataToken.ToInt32()));
}
} }
} }
public override void DecompileType(TypeDefinition type, ITextOutput output, DecompilationOptions options) public override void DecompileType(Mono.Cecil.TypeDefinition type, ITextOutput output, DecompilationOptions options)
{ {
var dis = CreateDisassembler(output, options); using (var reader = new PEReader(new FileStream(type.Module.FileName, FileMode.Open, FileAccess.Read))) {
dis.DisassembleType(type); var dis = CreateDisassembler(output, reader, options);
dis.DisassembleType(MetadataTokens.TypeDefinitionHandle(type.MetadataToken.ToInt32()));
}
} }
public override void DecompileNamespace(string nameSpace, IEnumerable<TypeDefinition> types, ITextOutput output, DecompilationOptions options) public override void DecompileNamespace(string nameSpace, IEnumerable<Mono.Cecil.TypeDefinition> types, ITextOutput output, DecompilationOptions options)
{ {
var dis = CreateDisassembler(output, options); if (!types.Any())
dis.DisassembleNamespace(nameSpace, types); return;
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 dis = CreateDisassembler(output, options); var dis = CreateDisassembler(output, reader, options);
var module = assembly.GetModuleDefinitionAsync().Result; var module = assembly.GetModuleDefinitionAsync().Result;
if (options.FullDecompilation) if (options.FullDecompilation)
dis.WriteAssemblyReferences(module); dis.WriteAssemblyReferences();
if (module.Assembly != null) if (module.Assembly != null)
dis.WriteAssemblyHeader(module.Assembly); dis.WriteAssemblyHeader();
output.WriteLine();
dis.WriteModuleHeader(module);
if (options.FullDecompilation) {
output.WriteLine();
output.WriteLine(); output.WriteLine();
dis.WriteModuleContents(module); dis.WriteModuleHeader();
if (options.FullDecompilation) {
output.WriteLine();
output.WriteLine();
dis.WriteModuleContents(reader.GetMetadataReader().GetModuleDefinition());
}
} }
} }
public override string TypeToString(TypeReference type, bool includeNamespace, ICustomAttributeProvider typeAttributes = null) public override string TypeToString(Mono.Cecil.TypeReference type, bool includeNamespace, Mono.Cecil.ICustomAttributeProvider typeAttributes = null)
{ {
PlainTextOutput output = new PlainTextOutput(); PlainTextOutput output = new PlainTextOutput();
type.WriteTo(output, includeNamespace ? ILNameSyntax.TypeName : ILNameSyntax.ShortTypeName); type.WriteTo(output, includeNamespace ? ILNameSyntax.TypeName : ILNameSyntax.ShortTypeName);

5
ILSpy/MainWindow.xaml.cs

@ -633,9 +633,8 @@ namespace ICSharpCode.ILSpy
ILSpyTreeNode treeNode = FindTreeNode(reference); ILSpyTreeNode treeNode = FindTreeNode(reference);
if (treeNode != null) { if (treeNode != null) {
SelectNode(treeNode); SelectNode(treeNode);
} else if (reference is Mono.Cecil.Cil.OpCode) { } else if (reference is ICSharpCode.Decompiler.Disassembler.OpCodeInfo opCode) {
string link = "http://msdn.microsoft.com/library/system.reflection.emit.opcodes." + ((Mono.Cecil.Cil.OpCode)reference).Code.ToString().ToLowerInvariant() + ".aspx"; OpenLink(opCode.Link);
OpenLink(link);
} }
return decompilationTask; return decompilationTask;
} }

11
ILSpy/TextView/DecompilerTextView.cs

@ -194,21 +194,18 @@ namespace ICSharpCode.ILSpy.TextView
object GenerateTooltip(ReferenceSegment segment) object GenerateTooltip(ReferenceSegment segment)
{ {
if (segment.Reference is Mono.Cecil.Cil.OpCode) { if (segment.Reference is ICSharpCode.Decompiler.Disassembler.OpCodeInfo code) {
Mono.Cecil.Cil.OpCode code = (Mono.Cecil.Cil.OpCode)segment.Reference;
string encodedName = code.Code.ToString();
string opCodeHex = code.Size > 1 ? string.Format("0x{0:x2}{1:x2}", code.Op1, code.Op2) : string.Format("0x{0:x2}", code.Op2);
XmlDocumentationProvider docProvider = XmlDocLoader.MscorlibDocumentation; XmlDocumentationProvider docProvider = XmlDocLoader.MscorlibDocumentation;
if (docProvider != null){ if (docProvider != null){
string documentation = docProvider.GetDocumentation("F:System.Reflection.Emit.OpCodes." + 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(string.Format("{0} ({1}) - ", code.Name, opCodeHex)); renderer.AppendText($"{code.Name} (0x{code.Code:x2}) - ");
renderer.AddXmlDocumentation(documentation); renderer.AddXmlDocumentation(documentation);
return renderer.CreateTextBlock(); return renderer.CreateTextBlock();
} }
} }
return string.Format("{0} ({1})", code.Name, opCodeHex); return $"{code.Name} (0x{code.Code:x2})";
} 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

Loading…
Cancel
Save