mirror of https://github.com/icsharpcode/ILSpy.git
17 changed files with 398 additions and 58 deletions
@ -0,0 +1,125 @@ |
|||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.IO; |
||||||
|
using System.Linq; |
||||||
|
using ICSharpCode.Decompiler.TypeSystem.Implementation; |
||||||
|
using Mono.Cecil; |
||||||
|
using Newtonsoft.Json.Linq; |
||||||
|
|
||||||
|
namespace ICSharpCode.Decompiler |
||||||
|
{ |
||||||
|
public class DotNetCorePathFinder |
||||||
|
{ |
||||||
|
class DotNetCorePackageInfo |
||||||
|
{ |
||||||
|
public readonly string Name; |
||||||
|
public readonly string Version; |
||||||
|
public readonly string Type; |
||||||
|
public readonly string Path; |
||||||
|
public readonly string[] RuntimeComponents; |
||||||
|
|
||||||
|
public DotNetCorePackageInfo(string fullName, string type, string path, string[] runtimeComponents) |
||||||
|
{ |
||||||
|
var parts = fullName.Split('/'); |
||||||
|
this.Name = parts[0]; |
||||||
|
this.Version = parts[1]; |
||||||
|
this.Type = type; |
||||||
|
this.Path = path; |
||||||
|
this.RuntimeComponents = runtimeComponents ?? new string[0]; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
static readonly string[] LookupPaths = new string[] { |
||||||
|
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".nuget\\packages") |
||||||
|
}; |
||||||
|
|
||||||
|
readonly Dictionary<string, DotNetCorePackageInfo> packages; |
||||||
|
ISet<string> packageBasePaths = new HashSet<string>(StringComparer.Ordinal); |
||||||
|
readonly string assemblyName; |
||||||
|
readonly string basePath; |
||||||
|
readonly string targetFrameworkId; |
||||||
|
readonly string version; |
||||||
|
readonly string dotnetBasePath = FindDotNetExeDirectory(); |
||||||
|
readonly Dictionary<string, UnresolvedAssemblyNameReference> loadInfo; |
||||||
|
|
||||||
|
public DotNetCorePathFinder(string parentAssemblyFileName, string targetFrameworkId, string version, Dictionary<string, UnresolvedAssemblyNameReference> loadInfo) |
||||||
|
{ |
||||||
|
this.assemblyName = Path.GetFileNameWithoutExtension(parentAssemblyFileName); |
||||||
|
this.basePath = Path.GetDirectoryName(parentAssemblyFileName); |
||||||
|
this.targetFrameworkId = targetFrameworkId; |
||||||
|
this.version = version; |
||||||
|
this.loadInfo = loadInfo; |
||||||
|
|
||||||
|
var depsJsonFileName = Path.Combine(basePath, $"{assemblyName}.deps.json"); |
||||||
|
if (!File.Exists(depsJsonFileName)) { |
||||||
|
loadInfo.AddMessage(assemblyName, MessageKind.Error, $"{assemblyName}.deps.json could not be found!"); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
packages = LoadPackageInfos(depsJsonFileName, targetFrameworkId).ToDictionary(i => i.Name); |
||||||
|
|
||||||
|
foreach (var path in LookupPaths) { |
||||||
|
foreach (var pk in packages) { |
||||||
|
foreach (var item in pk.Value.RuntimeComponents) { |
||||||
|
var itemPath = Path.GetDirectoryName(item); |
||||||
|
var fullPath = Path.Combine(path, pk.Value.Name, pk.Value.Version, itemPath); |
||||||
|
if (Directory.Exists(fullPath)) |
||||||
|
packageBasePaths.Add(fullPath); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public string TryResolveDotNetCore(AssemblyNameReference name) |
||||||
|
{ |
||||||
|
foreach (var basePath in packageBasePaths) { |
||||||
|
if (File.Exists(Path.Combine(basePath, name.Name + ".dll"))) { |
||||||
|
return Path.Combine(basePath, name.Name + ".dll"); |
||||||
|
} else if (File.Exists(Path.Combine(basePath, name.Name + ".exe"))) { |
||||||
|
return Path.Combine(basePath, name.Name + ".exe"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return FallbackToDotNetSharedDirectory(name, version); |
||||||
|
} |
||||||
|
|
||||||
|
static IEnumerable<DotNetCorePackageInfo> LoadPackageInfos(string depsJsonFileName, string targetFramework) |
||||||
|
{ |
||||||
|
var dependencies = JObject.Parse(File.ReadAllText(depsJsonFileName)); |
||||||
|
var runtimeInfos = dependencies["targets"][targetFramework].Children().OfType<JProperty>().ToArray(); |
||||||
|
var libraries = dependencies["libraries"].Children().OfType<JProperty>().ToArray(); |
||||||
|
|
||||||
|
foreach (var library in libraries) { |
||||||
|
var type = library.First()["type"].ToString(); |
||||||
|
var path = library.First()["path"]?.ToString(); |
||||||
|
var runtimeInfo = runtimeInfos.FirstOrDefault(r => r.Name == library.Name)?.First()["runtime"]?.Children().OfType<JProperty>().Select(i => i.Name).ToArray(); |
||||||
|
|
||||||
|
yield return new DotNetCorePackageInfo(library.Name, type, path, runtimeInfo); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
string FallbackToDotNetSharedDirectory(AssemblyNameReference name, string version) |
||||||
|
{ |
||||||
|
if (dotnetBasePath == null) return null; |
||||||
|
var basePath = Path.Combine(dotnetBasePath, "shared\\Microsoft.NETCore.App", version); |
||||||
|
if (File.Exists(Path.Combine(basePath, name.Name + ".dll"))) { |
||||||
|
return Path.Combine(basePath, name.Name + ".dll"); |
||||||
|
} else if (File.Exists(Path.Combine(basePath, name.Name + ".exe"))) { |
||||||
|
return Path.Combine(basePath, name.Name + ".exe"); |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
static string FindDotNetExeDirectory() |
||||||
|
{ |
||||||
|
string dotnetExeName = (Environment.OSVersion.Platform == PlatformID.Unix) ? "dotnet" : "dotnet.exe"; |
||||||
|
foreach (var item in Environment.GetEnvironmentVariable("PATH").Split(Path.PathSeparator)) { |
||||||
|
try { |
||||||
|
if (File.Exists(Path.Combine(item, dotnetExeName))) |
||||||
|
return item; |
||||||
|
} catch (ArgumentException) { } |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,44 @@ |
|||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.IO; |
||||||
|
using System.Linq; |
||||||
|
using ICSharpCode.Decompiler.TypeSystem.Implementation; |
||||||
|
using Mono.Cecil; |
||||||
|
using Newtonsoft.Json.Linq; |
||||||
|
|
||||||
|
namespace ICSharpCode.Decompiler |
||||||
|
{ |
||||||
|
|
||||||
|
public static class DotNetCorePathFinderExtensions |
||||||
|
{ |
||||||
|
public static string DetectTargetFrameworkId(this AssemblyDefinition assembly) |
||||||
|
{ |
||||||
|
if (assembly == null) |
||||||
|
throw new ArgumentNullException(nameof(assembly)); |
||||||
|
|
||||||
|
const string TargetFrameworkAttributeName = "System.Runtime.Versioning.TargetFrameworkAttribute"; |
||||||
|
|
||||||
|
foreach (var attribute in assembly.CustomAttributes) { |
||||||
|
if (attribute.AttributeType.FullName != TargetFrameworkAttributeName) |
||||||
|
continue; |
||||||
|
var blobReader = new BlobReader(attribute.GetBlob(), null); |
||||||
|
if (blobReader.ReadUInt16() == 0x0001) { |
||||||
|
return blobReader.ReadSerString(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return string.Empty; |
||||||
|
} |
||||||
|
|
||||||
|
public static void AddMessage(this Dictionary<string, UnresolvedAssemblyNameReference> container, string fullName, MessageKind kind, string message) |
||||||
|
{ |
||||||
|
if (container == null) |
||||||
|
throw new ArgumentNullException(nameof(container)); |
||||||
|
if (!container.TryGetValue(fullName, out var referenceInfo)) { |
||||||
|
referenceInfo = new UnresolvedAssemblyNameReference(fullName); |
||||||
|
container.Add(fullName, referenceInfo); |
||||||
|
} |
||||||
|
referenceInfo.Messages.Add((kind, message)); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,24 @@ |
|||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.Linq; |
||||||
|
using System.Text; |
||||||
|
using System.Threading.Tasks; |
||||||
|
|
||||||
|
namespace ICSharpCode.Decompiler |
||||||
|
{ |
||||||
|
public sealed class UnresolvedAssemblyNameReference |
||||||
|
{ |
||||||
|
public string FullName { get; } |
||||||
|
|
||||||
|
public bool HasErrors => Messages.Any(m => m.Item1 == MessageKind.Error); |
||||||
|
|
||||||
|
public List<(MessageKind, string)> Messages { get; } = new List<(MessageKind, string)>(); |
||||||
|
|
||||||
|
public UnresolvedAssemblyNameReference(string fullName) |
||||||
|
{ |
||||||
|
this.FullName = fullName; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public enum MessageKind { Error, Warning, Info } |
||||||
|
} |
@ -0,0 +1,81 @@ |
|||||||
|
// Copyright (c) 2010-2013 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; |
||||||
|
|
||||||
|
namespace ICSharpCode.Decompiler.Util |
||||||
|
{ |
||||||
|
public static class KeyComparer |
||||||
|
{ |
||||||
|
public static KeyComparer<TElement, TKey> Create<TElement, TKey>(Func<TElement, TKey> keySelector) |
||||||
|
{ |
||||||
|
return new KeyComparer<TElement, TKey>(keySelector, Comparer<TKey>.Default, EqualityComparer<TKey>.Default); |
||||||
|
} |
||||||
|
|
||||||
|
public static KeyComparer<TElement, TKey> Create<TElement, TKey>(Func<TElement, TKey> keySelector, IComparer<TKey> comparer, IEqualityComparer<TKey> equalityComparer) |
||||||
|
{ |
||||||
|
return new KeyComparer<TElement, TKey>(keySelector, comparer, equalityComparer); |
||||||
|
} |
||||||
|
|
||||||
|
public static IComparer<TElement> Create<TElement, TKey>(Func<TElement, TKey> keySelector, IComparer<TKey> comparer) |
||||||
|
{ |
||||||
|
return new KeyComparer<TElement, TKey>(keySelector, comparer, EqualityComparer<TKey>.Default); |
||||||
|
} |
||||||
|
|
||||||
|
public static IEqualityComparer<TElement> Create<TElement, TKey>(Func<TElement, TKey> keySelector, IEqualityComparer<TKey> equalityComparer) |
||||||
|
{ |
||||||
|
return new KeyComparer<TElement, TKey>(keySelector, Comparer<TKey>.Default, equalityComparer); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public class KeyComparer<TElement, TKey> : IComparer<TElement>, IEqualityComparer<TElement> |
||||||
|
{ |
||||||
|
readonly Func<TElement, TKey> keySelector; |
||||||
|
readonly IComparer<TKey> keyComparer; |
||||||
|
readonly IEqualityComparer<TKey> keyEqualityComparer; |
||||||
|
|
||||||
|
public KeyComparer(Func<TElement, TKey> keySelector, IComparer<TKey> keyComparer, IEqualityComparer<TKey> keyEqualityComparer) |
||||||
|
{ |
||||||
|
if (keySelector == null) |
||||||
|
throw new ArgumentNullException("keySelector"); |
||||||
|
if (keyComparer == null) |
||||||
|
throw new ArgumentNullException("keyComparer"); |
||||||
|
if (keyEqualityComparer == null) |
||||||
|
throw new ArgumentNullException("keyEqualityComparer"); |
||||||
|
this.keySelector = keySelector; |
||||||
|
this.keyComparer = keyComparer; |
||||||
|
this.keyEqualityComparer = keyEqualityComparer; |
||||||
|
} |
||||||
|
|
||||||
|
public int Compare(TElement x, TElement y) |
||||||
|
{ |
||||||
|
return keyComparer.Compare(keySelector(x), keySelector(y)); |
||||||
|
} |
||||||
|
|
||||||
|
public bool Equals(TElement x, TElement y) |
||||||
|
{ |
||||||
|
return keyEqualityComparer.Equals(keySelector(x), keySelector(y)); |
||||||
|
} |
||||||
|
|
||||||
|
public int GetHashCode(TElement obj) |
||||||
|
{ |
||||||
|
return keyEqualityComparer.GetHashCode(keySelector(obj)); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
After Width: | Height: | Size: 1.5 KiB |
Loading…
Reference in new issue