Browse Source

Fixed #1164: AddIn opens reference assembly when trying to open symbol in ILSpy

pull/1213/head
Andreas Weizel 7 years ago
parent
commit
2fb6e14339
  1. 3
      ICSharpCode.Decompiler/DotNetCore/DotNetCorePathFinder.cs
  2. 32
      ICSharpCode.Decompiler/DotNetCore/DotNetCorePathFinderExtensions.cs
  3. 61
      ILSpy.AddIn/AssemblyFileFinder.cs
  4. 9
      ILSpy.AddIn/Commands/OpenILSpyCommand.cs
  5. 1
      ILSpy.AddIn/ILSpy.AddIn.csproj

3
ICSharpCode.Decompiler/DotNetCore/DotNetCorePathFinder.cs

@ -5,6 +5,7 @@ using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using ICSharpCode.Decompiler.Util;
using LightJson.Serialization;
using Mono.Cecil;
@ -27,7 +28,7 @@ namespace ICSharpCode.Decompiler
this.Version = parts[1];
this.Type = type;
this.Path = path;
this.RuntimeComponents = runtimeComponents ?? new string[0];
this.RuntimeComponents = runtimeComponents ?? Empty<string>.Array;
}
}

32
ICSharpCode.Decompiler/DotNetCore/DotNetCorePathFinderExtensions.cs

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using ICSharpCode.Decompiler.TypeSystem.Implementation;
using Mono.Cecil;
@ -8,7 +9,11 @@ namespace ICSharpCode.Decompiler
{
public static class DotNetCorePathFinderExtensions
{
public static string DetectTargetFrameworkId(this AssemblyDefinition assembly)
static readonly string RefPathPattern =
@"(Reference Assemblies[/\\]Microsoft[/\\]Framework[/\\](?<1>.NETFramework)[/\\]v(?<2>[^/\\]+)[/\\])" +
@"|(NuGetFallbackFolder[/\\](?<1>[^/\\]+)\\(?<2>[^/\\]+)([/\\].*)?[/\\]ref[/\\])";
public static string DetectTargetFrameworkId(this AssemblyDefinition assembly, string assemblyPath = null)
{
if (assembly == null)
throw new ArgumentNullException(nameof(assembly));
@ -24,6 +29,31 @@ namespace ICSharpCode.Decompiler
}
}
// Optionally try to detect target version through assembly path as a fallback (use case: reference assemblies)
if (assemblyPath != null) {
/*
* Detected path patterns (examples):
*
* - .NETFramework -> C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\mscorlib.dll
* - .NETCore -> C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Console.dll
* - .NETStandard -> C:\Program Files\dotnet\sdk\NuGetFallbackFolder\netstandard.library\2.0.3\build\netstandard2.0\ref\netstandard.dll
*/
var pathMatch = Regex.Match(assemblyPath, RefPathPattern,
RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.ExplicitCapture);
if (pathMatch.Success) {
var type = pathMatch.Groups[1].Value;
var version = pathMatch.Groups[2].Value;
if (type == ".NETFramework") {
return $".NETFramework,Version=v{version}";
} else if (type.Contains("netcore")) {
return $".NETCoreApp,Version=v{version}";
} else if (type.Contains("netstandard")) {
return $".NETStandard,Version=v{version}";
}
}
}
return string.Empty;
}
}

61
ILSpy.AddIn/AssemblyFileFinder.cs

@ -0,0 +1,61 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Util;
using Mono.Cecil;
namespace ICSharpCode.ILSpy.AddIn
{
public class AssemblyFileFinder
{
public static string FindAssemblyFile(AssemblyDefinition assemblyDefinition, string assemblyFile)
{
var assemblyName = assemblyDefinition.Name;
var detectedTargetFramework = assemblyDefinition.DetectTargetFrameworkId(assemblyFile);
if (string.IsNullOrEmpty(detectedTargetFramework)) {
// Without a target framework id it makes no sense to continue
return null;
}
var targetFramework = detectedTargetFramework.Split(new[] { ",Version=v" }, StringSplitOptions.None);
string file = null;
switch (targetFramework[0]) {
case ".NETCoreApp":
case ".NETStandard":
if (targetFramework.Length != 2)
return FindAssemblyFromGAC(assemblyDefinition);
var version = targetFramework[1].Length == 3 ? targetFramework[1] + ".0" : targetFramework[1];
var dotNetCorePathFinder = new DotNetCorePathFinder(assemblyFile, detectedTargetFramework, version);
file = dotNetCorePathFinder.TryResolveDotNetCore(assemblyName);
if (file != null)
return file;
return FindAssemblyFromGAC(assemblyDefinition);
default:
return FindAssemblyFromGAC(assemblyDefinition);
}
}
static string FindAssemblyFromGAC(AssemblyDefinition assemblyDefinition)
{
return GacInterop.FindAssemblyInNetGac(assemblyDefinition.Name);
}
static readonly string RefPathPattern = @"NuGetFallbackFolder[/\\][^/\\]+[/\\][^/\\]+[/\\]ref[/\\]";
public static bool IsReferenceAssembly(AssemblyDefinition assemblyDef, string assemblyFile)
{
if (assemblyDef.CustomAttributes.Any(ca => ca.AttributeType.FullName == "System.Runtime.CompilerServices.ReferenceAssemblyAttribute"))
return true;
// Try to detect reference assembly through specific path pattern
var refPathMatch = Regex.Match(assemblyFile, RefPathPattern, RegexOptions.IgnoreCase | RegexOptions.Compiled);
return refPathMatch.Success;
}
}
}

9
ILSpy.AddIn/Commands/OpenILSpyCommand.cs

@ -89,8 +89,8 @@ namespace ICSharpCode.ILSpy.AddIn.Commands
foreach (var reference in parentProject.MetadataReferences) {
using (var assemblyDef = AssemblyDefinition.ReadAssembly(reference.Display)) {
string assemblyName = assemblyDef.Name.Name;
if (IsReferenceAssembly(assemblyDef)) {
string resolvedAssemblyFile = GacInterop.FindAssemblyInNetGac(assemblyDef.Name);
if (AssemblyFileFinder.IsReferenceAssembly(assemblyDef, reference.Display)) {
string resolvedAssemblyFile = AssemblyFileFinder.FindAssemblyFile(assemblyDef, reference.Display);
dict.Add(assemblyName,
new DetectedReference(assemblyName, resolvedAssemblyFile, false));
} else {
@ -127,11 +127,6 @@ namespace ICSharpCode.ILSpy.AddIn.Commands
return null;
}
protected bool IsReferenceAssembly(AssemblyDefinition assemblyDef)
{
return assemblyDef.CustomAttributes.Any(ca => ca.AttributeType.FullName == "System.Runtime.CompilerServices.ReferenceAssemblyAttribute");
}
}
class OpenILSpyCommand : ILSpyCommand

1
ILSpy.AddIn/ILSpy.AddIn.csproj

@ -85,6 +85,7 @@
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="PkgCmdID.cs" />
<Compile Include="SyntaxNodeExtensions.cs" />
<Compile Include="AssemblyFileFinder.cs" />
<Compile Include="Utils.cs" />
</ItemGroup>

Loading…
Cancel
Save