diff --git a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
index af30932cb..ccd715010 100644
--- a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
+++ b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
@@ -269,6 +269,7 @@
+
@@ -295,6 +296,7 @@
+
diff --git a/ICSharpCode.Decompiler/Metadata/AssemblyReferences.cs b/ICSharpCode.Decompiler/Metadata/AssemblyReferences.cs
new file mode 100644
index 000000000..173c4a9fe
--- /dev/null
+++ b/ICSharpCode.Decompiler/Metadata/AssemblyReferences.cs
@@ -0,0 +1,198 @@
+// Copyright (c) 2018 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.IO;
+using System.Linq;
+using System.Reflection;
+using System.Reflection.Metadata;
+using System.Security.Cryptography;
+using System.Text;
+using ICSharpCode.Decompiler.Util;
+
+namespace ICSharpCode.Decompiler.Metadata
+{
+ public sealed class AssemblyResolutionException : FileNotFoundException
+ {
+ public IAssemblyReference Reference { get; }
+
+ public AssemblyResolutionException(IAssemblyReference reference)
+ : this(reference, null)
+ {
+ }
+
+ public AssemblyResolutionException(IAssemblyReference reference, Exception innerException)
+ : base($"Failed to resolve assembly: '{reference}'", innerException)
+ {
+ this.Reference = reference;
+ }
+ }
+
+ public interface IAssemblyResolver
+ {
+ PEFile Resolve(IAssemblyReference reference);
+ }
+
+ public interface IAssemblyReference
+ {
+ string Name { get; }
+ string FullName { get; }
+ Version Version { get; }
+ string Culture { get; }
+ byte[] PublicKeyToken { get; }
+
+ bool IsWindowsRuntime { get; }
+ bool IsRetargetable { get; }
+ }
+
+ public class AssemblyNameReference : IAssemblyReference
+ {
+ string fullName;
+
+ public string Name { get; private set; }
+
+ public string FullName {
+ get {
+ if (fullName != null)
+ return fullName;
+
+ const string sep = ", ";
+
+ var builder = new StringBuilder();
+ builder.Append(Name);
+ builder.Append(sep);
+ builder.Append("Version=");
+ builder.Append(Version.ToString(fieldCount: 4));
+ builder.Append(sep);
+ builder.Append("Culture=");
+ builder.Append(string.IsNullOrEmpty(Culture) ? "neutral" : Culture);
+ builder.Append(sep);
+ builder.Append("PublicKeyToken=");
+
+ var pk_token = PublicKeyToken;
+ if (pk_token != null && pk_token.Length > 0) {
+ for (int i = 0; i < pk_token.Length; i++) {
+ builder.Append(pk_token[i].ToString("x2"));
+ }
+ } else
+ builder.Append("null");
+
+ if (IsRetargetable) {
+ builder.Append(sep);
+ builder.Append("Retargetable=Yes");
+ }
+
+ return fullName = builder.ToString();
+ }
+ }
+
+ public Version Version { get; private set; }
+
+ public string Culture { get; private set; }
+
+ public byte[] PublicKeyToken { get; private set; }
+
+ public bool IsWindowsRuntime { get; private set; }
+
+ public bool IsRetargetable { get; private set; }
+
+ public static AssemblyNameReference Parse(string fullName)
+ {
+ if (fullName == null)
+ throw new ArgumentNullException("fullName");
+ if (fullName.Length == 0)
+ throw new ArgumentException("Name can not be empty");
+
+ var name = new AssemblyNameReference();
+ var tokens = fullName.Split(',');
+ for (int i = 0; i < tokens.Length; i++) {
+ var token = tokens[i].Trim();
+
+ if (i == 0) {
+ name.Name = token;
+ continue;
+ }
+
+ var parts = token.Split('=');
+ if (parts.Length != 2)
+ throw new ArgumentException("Malformed name");
+
+ switch (parts[0].ToLowerInvariant()) {
+ case "version":
+ name.Version = new Version(parts[1]);
+ break;
+ case "culture":
+ name.Culture = parts[1] == "neutral" ? "" : parts[1];
+ break;
+ case "publickeytoken":
+ var pk_token = parts[1];
+ if (pk_token == "null")
+ break;
+
+ name.PublicKeyToken = new byte[pk_token.Length / 2];
+ for (int j = 0; j < name.PublicKeyToken.Length; j++)
+ name.PublicKeyToken[j] = Byte.Parse(pk_token.Substring(j * 2, 2), System.Globalization.NumberStyles.HexNumber);
+
+ break;
+ }
+ }
+
+ return name;
+ }
+ }
+
+ public class AssemblyReference : IAssemblyReference
+ {
+ static readonly SHA1 sha1 = SHA1.Create();
+
+ public PEFile Module { get; }
+ public AssemblyReferenceHandle Handle { get; }
+
+ System.Reflection.Metadata.AssemblyReference This() => Module.Metadata.GetAssemblyReference(Handle);
+
+ public bool IsWindowsRuntime => (This().Flags & AssemblyFlags.WindowsRuntime) != 0;
+ public bool IsRetargetable => (This().Flags & AssemblyFlags.Retargetable) != 0;
+
+ public string Name => Module.Metadata.GetString(This().Name);
+ public string FullName => This().GetFullAssemblyName(Module.Metadata);
+ public Version Version => This().Version;
+ public string Culture => Module.Metadata.GetString(This().Culture);
+ byte[] IAssemblyReference.PublicKeyToken => GetPublicKeyToken();
+
+ public byte[] GetPublicKeyToken()
+ {
+ var inst = This();
+ if (inst.PublicKeyOrToken.IsNil)
+ return Empty.Array;
+ var bytes = Module.Metadata.GetBlobBytes(inst.PublicKeyOrToken);
+ if ((inst.Flags & AssemblyFlags.PublicKey) != 0) {
+ return sha1.ComputeHash(bytes).Skip(12).ToArray();
+ }
+ return bytes;
+ }
+
+ public AssemblyReference(PEFile module, AssemblyReferenceHandle handle)
+ {
+ Module = module ?? throw new ArgumentNullException(nameof(module));
+ if (handle.IsNil)
+ throw new ArgumentNullException(nameof(handle));
+ Handle = handle;
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/Metadata/Dom.cs b/ICSharpCode.Decompiler/Metadata/Dom.cs
index dddb74855..ec9dd13a3 100644
--- a/ICSharpCode.Decompiler/Metadata/Dom.cs
+++ b/ICSharpCode.Decompiler/Metadata/Dom.cs
@@ -26,38 +26,7 @@ namespace ICSharpCode.Decompiler.Metadata
using SRMTypeSpec = System.Reflection.Metadata.TypeSpecification;
using SRMAssemblyReference = System.Reflection.Metadata.AssemblyReference;
- public sealed class AssemblyResolutionException : FileNotFoundException
- {
- public IAssemblyReference Reference { get; }
-
- public AssemblyResolutionException(IAssemblyReference reference)
- : this(reference, null)
- {
- }
-
- public AssemblyResolutionException(IAssemblyReference reference, Exception innerException)
- : base($"Failed to resolve assembly: '{reference}'", innerException)
- {
- this.Reference = reference;
- }
- }
- public interface IAssemblyResolver
- {
- PEFile Resolve(IAssemblyReference reference);
- }
-
- public interface IAssemblyReference
- {
- string Name { get; }
- string FullName { get; }
- Version Version { get; }
- string Culture { get; }
- byte[] PublicKeyToken { get; }
-
- bool IsWindowsRuntime { get; }
- bool IsRetargetable { get; }
- }
public interface IAssemblyDocumentationResolver
{
@@ -92,170 +61,6 @@ namespace ICSharpCode.Decompiler.Metadata
Net_4_0
}
- public class PEFile : IDisposable, TypeSystem.IAssemblyReference
- {
- public string FileName { get; }
- public PEReader Reader { get; }
- public MetadataReader Metadata { get; }
- public IAssemblyResolver AssemblyResolver { get; }
- public IAssemblyDocumentationResolver DocumentationResolver { get; set; }
- public IDebugInfoProvider DebugInfo { get; set; }
-
- public PEFile(string fileName, Stream stream, bool throwOnResolveError = false, PEStreamOptions options = PEStreamOptions.Default)
- {
- this.FileName = fileName;
- this.Reader = new PEReader(stream, options);
- this.Metadata = Reader.GetMetadataReader();
- this.AssemblyResolver = new UniversalAssemblyResolver(fileName, throwOnResolveError, Reader.DetectTargetFrameworkId(), options);
- }
-
- public PEFile(string fileName, Stream stream, IAssemblyResolver assemblyResolver, PEStreamOptions options = PEStreamOptions.Default)
- {
- this.FileName = fileName;
- this.Reader = new PEReader(stream, options);
- this.Metadata = Reader.GetMetadataReader();
- this.AssemblyResolver = assemblyResolver;
- }
-
- public bool IsAssembly => Metadata.IsAssembly;
- public string Name => GetName();
- public string FullName => IsAssembly ? Metadata.GetFullAssemblyName() : Name;
-
- public TargetRuntime GetRuntime()
- {
- string version = Metadata.MetadataVersion;
- switch (version[1]) {
- case '1':
- if (version[3] == 1)
- return TargetRuntime.Net_1_0;
- else
- return TargetRuntime.Net_1_1;
- case '2':
- return TargetRuntime.Net_2_0;
- case '4':
- return TargetRuntime.Net_4_0;
- default:
- return TargetRuntime.Unknown;
- }
-
- }
-
- string GetName()
- {
- var metadata = Metadata;
- if (metadata.IsAssembly)
- return metadata.GetString(metadata.GetAssemblyDefinition().Name);
- return metadata.GetString(metadata.GetModuleDefinition().Name);
- }
-
- public ImmutableArray AssemblyReferences => Metadata.AssemblyReferences.Select(r => new AssemblyReference(this, r)).ToImmutableArray();
- public ImmutableArray ModuleReferences => Metadata.GetModuleReferences().ToImmutableArray();
- public ImmutableArray TopLevelTypeDefinitions => Metadata.GetTopLevelTypeDefinitions().Select(t => new TypeDefinition(this, t)).ToImmutableArray();
- public ImmutableArray Resources => GetResources().ToImmutableArray();
-
- IEnumerable GetResources()
- {
- var metadata = Metadata;
- foreach (var h in metadata.ManifestResources) {
- yield return new Resource(this, h);
- }
- }
-
- public void Dispose()
- {
- Reader.Dispose();
- }
-
- Dictionary typeLookup;
-
- ///
- /// Finds the top-level-type with the specified name.
- ///
- public TypeDefinitionHandle GetTypeDefinition(TopLevelTypeName typeName)
- {
- var lookup = LazyInit.VolatileRead(ref typeLookup);
- if (lookup == null) {
- lookup = new Dictionary();
- foreach (var handle in Metadata.TypeDefinitions) {
- var td = Metadata.GetTypeDefinition(handle);
- if (!td.GetDeclaringType().IsNil) {
- continue; // nested type
- }
- var nsHandle = td.Namespace;
- string ns = nsHandle.IsNil ? string.Empty : Metadata.GetString(nsHandle);
- string name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(Metadata.GetString(td.Name), out int typeParameterCount);
- lookup[new TopLevelTypeName(ns, name, typeParameterCount)] = handle;
- }
- lookup = LazyInit.GetOrSet(ref typeLookup, lookup);
- }
- if (lookup.TryGetValue(typeName, out var resultHandle))
- return resultHandle;
- else
- return default;
- }
-
- Dictionary typeForwarderLookup;
-
- ///
- /// Finds the type forwarder with the specified name.
- ///
- public ExportedTypeHandle GetTypeForwarder(FullTypeName typeName)
- {
- var lookup = LazyInit.VolatileRead(ref typeForwarderLookup);
- if (lookup == null) {
- lookup = new Dictionary();
- foreach (var handle in Metadata.ExportedTypes) {
- var td = Metadata.GetExportedType(handle);
- lookup[td.GetFullTypeName(Metadata)] = handle;
- }
- lookup = LazyInit.GetOrSet(ref typeForwarderLookup, lookup);
- }
- if (lookup.TryGetValue(typeName, out var resultHandle))
- return resultHandle;
- else
- return default;
- }
-
- MethodSemanticsLookup methodSemanticsLookup;
-
- internal MethodSemanticsLookup MethodSemanticsLookup {
- get {
- var r = LazyInit.VolatileRead(ref methodSemanticsLookup);
- if (r != null)
- return r;
- else
- return LazyInit.GetOrSet(ref methodSemanticsLookup, new MethodSemanticsLookup(Metadata));
- }
- }
-
- public TypeSystem.IAssemblyReference WithOptions(TypeSystemOptions options)
- {
- return new PEFileWithOptions(this, options);
- }
-
- IAssembly TypeSystem.IAssemblyReference.Resolve(ITypeResolveContext context)
- {
- return new MetadataAssembly(context.Compilation, this, TypeSystemOptions.Default);
- }
-
- private class PEFileWithOptions : TypeSystem.IAssemblyReference
- {
- readonly PEFile peFile;
- readonly TypeSystemOptions options;
-
- public PEFileWithOptions(PEFile peFile, TypeSystemOptions options)
- {
- this.peFile = peFile;
- this.options = options;
- }
-
- IAssembly TypeSystem.IAssemblyReference.Resolve(ITypeResolveContext context)
- {
- return new MetadataAssembly(context.Compilation, peFile, options);
- }
- }
- }
-
public enum ResourceType
{
Linked,
@@ -331,160 +136,6 @@ namespace ICSharpCode.Decompiler.Metadata
}
}
- public class AssemblyNameReference : IAssemblyReference
- {
- string fullName;
-
- public string Name { get; private set; }
-
- public string FullName {
- get {
- if (fullName != null)
- return fullName;
-
- const string sep = ", ";
-
- var builder = new StringBuilder();
- builder.Append(Name);
- builder.Append(sep);
- builder.Append("Version=");
- builder.Append(Version.ToString(fieldCount: 4));
- builder.Append(sep);
- builder.Append("Culture=");
- builder.Append(string.IsNullOrEmpty(Culture) ? "neutral" : Culture);
- builder.Append(sep);
- builder.Append("PublicKeyToken=");
-
- var pk_token = PublicKeyToken;
- if (pk_token != null && pk_token.Length > 0) {
- for (int i = 0; i < pk_token.Length; i++) {
- builder.Append(pk_token[i].ToString("x2"));
- }
- } else
- builder.Append("null");
-
- if (IsRetargetable) {
- builder.Append(sep);
- builder.Append("Retargetable=Yes");
- }
-
- return fullName = builder.ToString();
- }
- }
-
- public Version Version { get; private set; }
-
- public string Culture { get; private set; }
-
- public byte[] PublicKeyToken { get; private set; }
-
- public bool IsWindowsRuntime { get; private set; }
-
- public bool IsRetargetable { get; private set; }
-
- public static AssemblyNameReference Parse(string fullName)
- {
- if (fullName == null)
- throw new ArgumentNullException("fullName");
- if (fullName.Length == 0)
- throw new ArgumentException("Name can not be empty");
-
- var name = new AssemblyNameReference();
- var tokens = fullName.Split(',');
- for (int i = 0; i < tokens.Length; i++) {
- var token = tokens[i].Trim();
-
- if (i == 0) {
- name.Name = token;
- continue;
- }
-
- var parts = token.Split('=');
- if (parts.Length != 2)
- throw new ArgumentException("Malformed name");
-
- switch (parts[0].ToLowerInvariant()) {
- case "version":
- name.Version = new Version(parts[1]);
- break;
- case "culture":
- name.Culture = parts[1] == "neutral" ? "" : parts[1];
- break;
- case "publickeytoken":
- var pk_token = parts[1];
- if (pk_token == "null")
- break;
-
- name.PublicKeyToken = new byte[pk_token.Length / 2];
- for (int j = 0; j < name.PublicKeyToken.Length; j++)
- name.PublicKeyToken[j] = Byte.Parse(pk_token.Substring(j * 2, 2), System.Globalization.NumberStyles.HexNumber);
-
- break;
- }
- }
-
- return name;
- }
- }
-
- public struct AssemblyReference : IAssemblyReference, IEquatable
- {
- static readonly SHA1 sha1 = SHA1.Create();
-
- public PEFile Module { get; }
- public AssemblyReferenceHandle Handle { get; }
- public bool IsNil => Handle.IsNil;
-
- SRMAssemblyReference This() => Module.Metadata.GetAssemblyReference(Handle);
-
- public bool IsWindowsRuntime => (This().Flags & AssemblyFlags.WindowsRuntime) != 0;
- public bool IsRetargetable => (This().Flags & AssemblyFlags.Retargetable) != 0;
-
- public string Name => Module.Metadata.GetString(This().Name);
- public string FullName => This().GetFullAssemblyName(Module.Metadata);
- public Version Version => This().Version;
- public string Culture => Module.Metadata.GetString(This().Culture);
- byte[] IAssemblyReference.PublicKeyToken => GetPublicKeyToken();
-
- public byte[] GetPublicKeyToken()
- {
- var inst = This();
- if (inst.PublicKeyOrToken.IsNil)
- return Empty.Array;
- var bytes = Module.Metadata.GetBlobBytes(inst.PublicKeyOrToken);
- if ((inst.Flags & AssemblyFlags.PublicKey) != 0) {
- return sha1.ComputeHash(bytes).Skip(12).ToArray();
- }
- return bytes;
- }
-
- public bool Equals(AssemblyReference other)
- {
- return Module == other.Module && Handle == other.Handle;
- }
-
- public override bool Equals(object obj)
- {
- if (obj is AssemblyReference reference)
- return Equals(reference);
- return false;
- }
-
- public override int GetHashCode()
- {
- return unchecked(982451629 * Module.GetHashCode() + 982451653 * MetadataTokens.GetToken(Handle));
- }
-
- public static bool operator ==(AssemblyReference lhs, AssemblyReference rhs) => lhs.Equals(rhs);
- public static bool operator !=(AssemblyReference lhs, AssemblyReference rhs) => !lhs.Equals(rhs);
-
- public AssemblyReference(PEFile module, AssemblyReferenceHandle handle)
- {
- Module = module;
- Handle = handle;
- }
- }
-
public struct Entity : IEquatable, IMetadataEntity
{
public PEFile Module { get; }
diff --git a/ICSharpCode.Decompiler/Metadata/DotNetCorePathFinder.cs b/ICSharpCode.Decompiler/Metadata/DotNetCorePathFinder.cs
index 36ef08128..77b1f9f54 100644
--- a/ICSharpCode.Decompiler/Metadata/DotNetCorePathFinder.cs
+++ b/ICSharpCode.Decompiler/Metadata/DotNetCorePathFinder.cs
@@ -1,4 +1,22 @@
-using System;
+// Copyright (c) 2018 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.Diagnostics;
using System.IO;
diff --git a/ICSharpCode.Decompiler/Metadata/DotNetCorePathFinderExtensions.cs b/ICSharpCode.Decompiler/Metadata/DotNetCorePathFinderExtensions.cs
index 72f82efe8..40da69cc1 100644
--- a/ICSharpCode.Decompiler/Metadata/DotNetCorePathFinderExtensions.cs
+++ b/ICSharpCode.Decompiler/Metadata/DotNetCorePathFinderExtensions.cs
@@ -1,4 +1,22 @@
-using System;
+// Copyright (c) 2018 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.Linq;
using System.Reflection.Metadata;
diff --git a/ICSharpCode.Decompiler/Metadata/MetadataExtensions.cs b/ICSharpCode.Decompiler/Metadata/MetadataExtensions.cs
index f4ec65fce..1b2c07061 100644
--- a/ICSharpCode.Decompiler/Metadata/MetadataExtensions.cs
+++ b/ICSharpCode.Decompiler/Metadata/MetadataExtensions.cs
@@ -18,11 +18,6 @@ namespace ICSharpCode.Decompiler.Metadata
{
public static class MetadataExtensions
{
- public static bool IsNil(this IAssemblyReference reference)
- {
- return reference == null || (reference is Metadata.AssemblyReference ar && ar.IsNil);
- }
-
public static string GetFullAssemblyName(this MetadataReader reader)
{
if (!reader.IsAssembly)
diff --git a/ICSharpCode.Decompiler/Metadata/MetadataResolver.cs b/ICSharpCode.Decompiler/Metadata/MetadataResolver.cs
index b842f640e..aa6f9c2cf 100644
--- a/ICSharpCode.Decompiler/Metadata/MetadataResolver.cs
+++ b/ICSharpCode.Decompiler/Metadata/MetadataResolver.cs
@@ -1,4 +1,22 @@
-using System;
+// Copyright (c) 2018 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.Diagnostics;
diff --git a/ICSharpCode.Decompiler/Metadata/PEFile.cs b/ICSharpCode.Decompiler/Metadata/PEFile.cs
new file mode 100644
index 000000000..1d89260cb
--- /dev/null
+++ b/ICSharpCode.Decompiler/Metadata/PEFile.cs
@@ -0,0 +1,194 @@
+// Copyright (c) 2018 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.IO;
+using System.Linq;
+using System.Reflection.Metadata;
+using System.Reflection.PortableExecutable;
+using ICSharpCode.Decompiler.TypeSystem;
+using ICSharpCode.Decompiler.Util;
+
+namespace ICSharpCode.Decompiler.Metadata
+{
+ public class PEFile : IDisposable, TypeSystem.IAssemblyReference
+ {
+ public string FileName { get; }
+ public PEReader Reader { get; }
+ public MetadataReader Metadata { get; }
+ public IAssemblyResolver AssemblyResolver { get; }
+ public IAssemblyDocumentationResolver DocumentationResolver { get; set; }
+ public IDebugInfoProvider DebugInfo { get; set; }
+
+ public PEFile(string fileName, Stream stream, bool throwOnResolveError = false, PEStreamOptions options = PEStreamOptions.Default)
+ {
+ this.FileName = fileName;
+ this.Reader = new PEReader(stream, options);
+ this.Metadata = Reader.GetMetadataReader();
+ this.AssemblyResolver = new UniversalAssemblyResolver(fileName, throwOnResolveError, Reader.DetectTargetFrameworkId(), options);
+ }
+
+ public PEFile(string fileName, Stream stream, IAssemblyResolver assemblyResolver, PEStreamOptions options = PEStreamOptions.Default)
+ {
+ this.FileName = fileName;
+ this.Reader = new PEReader(stream, options);
+ this.Metadata = Reader.GetMetadataReader();
+ this.AssemblyResolver = assemblyResolver;
+ }
+
+ public bool IsAssembly => Metadata.IsAssembly;
+ public string Name => GetName();
+ public string FullName => IsAssembly ? Metadata.GetFullAssemblyName() : Name;
+
+ public TargetRuntime GetRuntime()
+ {
+ string version = Metadata.MetadataVersion;
+ switch (version[1]) {
+ case '1':
+ if (version[3] == 1)
+ return TargetRuntime.Net_1_0;
+ else
+ return TargetRuntime.Net_1_1;
+ case '2':
+ return TargetRuntime.Net_2_0;
+ case '4':
+ return TargetRuntime.Net_4_0;
+ default:
+ return TargetRuntime.Unknown;
+ }
+
+ }
+
+ string GetName()
+ {
+ var metadata = Metadata;
+ if (metadata.IsAssembly)
+ return metadata.GetString(metadata.GetAssemblyDefinition().Name);
+ return metadata.GetString(metadata.GetModuleDefinition().Name);
+ }
+
+ public ImmutableArray AssemblyReferences => Metadata.AssemblyReferences.Select(r => new AssemblyReference(this, r)).ToImmutableArray();
+ public ImmutableArray ModuleReferences => Metadata.GetModuleReferences().ToImmutableArray();
+ public ImmutableArray TopLevelTypeDefinitions => Metadata.GetTopLevelTypeDefinitions().Select(t => new TypeDefinition(this, t)).ToImmutableArray();
+ public ImmutableArray Resources => GetResources().ToImmutableArray();
+
+ IEnumerable GetResources()
+ {
+ var metadata = Metadata;
+ foreach (var h in metadata.ManifestResources) {
+ yield return new Resource(this, h);
+ }
+ }
+
+ public void Dispose()
+ {
+ Reader.Dispose();
+ }
+
+ Dictionary typeLookup;
+
+ ///
+ /// Finds the top-level-type with the specified name.
+ ///
+ public TypeDefinitionHandle GetTypeDefinition(TopLevelTypeName typeName)
+ {
+ var lookup = LazyInit.VolatileRead(ref typeLookup);
+ if (lookup == null) {
+ lookup = new Dictionary();
+ foreach (var handle in Metadata.TypeDefinitions) {
+ var td = Metadata.GetTypeDefinition(handle);
+ if (!td.GetDeclaringType().IsNil) {
+ continue; // nested type
+ }
+ var nsHandle = td.Namespace;
+ string ns = nsHandle.IsNil ? string.Empty : Metadata.GetString(nsHandle);
+ string name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(Metadata.GetString(td.Name), out int typeParameterCount);
+ lookup[new TopLevelTypeName(ns, name, typeParameterCount)] = handle;
+ }
+ lookup = LazyInit.GetOrSet(ref typeLookup, lookup);
+ }
+ if (lookup.TryGetValue(typeName, out var resultHandle))
+ return resultHandle;
+ else
+ return default;
+ }
+
+ Dictionary typeForwarderLookup;
+
+ ///
+ /// Finds the type forwarder with the specified name.
+ ///
+ public ExportedTypeHandle GetTypeForwarder(FullTypeName typeName)
+ {
+ var lookup = LazyInit.VolatileRead(ref typeForwarderLookup);
+ if (lookup == null) {
+ lookup = new Dictionary();
+ foreach (var handle in Metadata.ExportedTypes) {
+ var td = Metadata.GetExportedType(handle);
+ lookup[td.GetFullTypeName(Metadata)] = handle;
+ }
+ lookup = LazyInit.GetOrSet(ref typeForwarderLookup, lookup);
+ }
+ if (lookup.TryGetValue(typeName, out var resultHandle))
+ return resultHandle;
+ else
+ return default;
+ }
+
+ MethodSemanticsLookup methodSemanticsLookup;
+
+ internal MethodSemanticsLookup MethodSemanticsLookup {
+ get {
+ var r = LazyInit.VolatileRead(ref methodSemanticsLookup);
+ if (r != null)
+ return r;
+ else
+ return LazyInit.GetOrSet(ref methodSemanticsLookup, new MethodSemanticsLookup(Metadata));
+ }
+ }
+
+ public TypeSystem.IAssemblyReference WithOptions(TypeSystemOptions options)
+ {
+ return new PEFileWithOptions(this, options);
+ }
+
+ IAssembly TypeSystem.IAssemblyReference.Resolve(ITypeResolveContext context)
+ {
+ return new MetadataAssembly(context.Compilation, this, TypeSystemOptions.Default);
+ }
+
+ private class PEFileWithOptions : TypeSystem.IAssemblyReference
+ {
+ readonly PEFile peFile;
+ readonly TypeSystemOptions options;
+
+ public PEFileWithOptions(PEFile peFile, TypeSystemOptions options)
+ {
+ this.peFile = peFile;
+ this.options = options;
+ }
+
+ IAssembly TypeSystem.IAssemblyReference.Resolve(ITypeResolveContext context)
+ {
+ return new MetadataAssembly(context.Compilation, peFile, options);
+ }
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/Metadata/SequencePoint.cs b/ICSharpCode.Decompiler/Metadata/SequencePoint.cs
index d43829d30..5534b21fc 100644
--- a/ICSharpCode.Decompiler/Metadata/SequencePoint.cs
+++ b/ICSharpCode.Decompiler/Metadata/SequencePoint.cs
@@ -1,13 +1,25 @@
-using System;
-using System.Collections.Generic;
-using System.Reflection.Metadata;
-using System.Reflection.Metadata.Ecma335;
-using System.Text;
+// Copyright (c) 2018 Daniel Grunwald
+//
+// 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;
namespace ICSharpCode.Decompiler.Metadata
{
- using SRMDocument = System.Reflection.Metadata.Document;
-
///
/// A sequence point read from a PDB file or produced by the decompiler.
///
diff --git a/ICSharpCode.Decompiler/Metadata/SignatureBlobComparer.cs b/ICSharpCode.Decompiler/Metadata/SignatureBlobComparer.cs
index 556839487..47f237834 100644
--- a/ICSharpCode.Decompiler/Metadata/SignatureBlobComparer.cs
+++ b/ICSharpCode.Decompiler/Metadata/SignatureBlobComparer.cs
@@ -1,4 +1,22 @@
-using System.Reflection.Metadata;
+// Copyright (c) 2018 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.Reflection.Metadata;
namespace ICSharpCode.Decompiler.Metadata
{
diff --git a/ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs b/ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs
index 267fd9772..639ef2d17 100644
--- a/ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs
+++ b/ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs
@@ -1,4 +1,22 @@
-using System;
+// Copyright (c) 2018 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.IO;
using System.Linq;
@@ -7,6 +25,7 @@ using System.Text;
namespace ICSharpCode.Decompiler.Metadata
{
+ // This inspired by Mono.Cecil's BaseAssemblyResolver/DefaultAssemblyResolver.
public class UniversalAssemblyResolver : IAssemblyResolver
{
DotNetCorePathFinder dotNetCorePathFinder;
@@ -141,7 +160,7 @@ namespace ICSharpCode.Decompiler.Metadata
string ResolveInternal(IAssemblyReference name)
{
- if (name.IsNil())
+ if (name == null)
throw new ArgumentNullException(nameof(name));
var assembly = SearchDirectory(name, directories);
diff --git a/ICSharpCode.Decompiler/Metadata/UnresolvedAssemblyNameReference.cs b/ICSharpCode.Decompiler/Metadata/UnresolvedAssemblyNameReference.cs
index 13b1ecb7b..fa07e147c 100644
--- a/ICSharpCode.Decompiler/Metadata/UnresolvedAssemblyNameReference.cs
+++ b/ICSharpCode.Decompiler/Metadata/UnresolvedAssemblyNameReference.cs
@@ -1,4 +1,22 @@
-using System;
+// Copyright (c) 2018 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.Linq;
using System.Text;