Browse Source

Fix assembly resolving and Tester for .NET Core 3.0

pull/1730/head
Siegfried Pammer 6 years ago
parent
commit
3b0402b381
  1. 41
      ICSharpCode.Decompiler.Tests/Helpers/Tester.cs
  2. 9
      ICSharpCode.Decompiler/CSharp/CallBuilder.cs
  3. 19
      ICSharpCode.Decompiler/Metadata/DotNetCorePathFinder.cs
  4. 32
      ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs

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

@ -89,12 +89,12 @@ namespace ICSharpCode.Decompiler.Tests.Helpers @@ -89,12 +89,12 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
outputFile += ".exe";
otherOptions += "/exe ";
}
if (options.HasFlag(AssemblerOptions.UseDebug)) {
otherOptions += "/debug ";
}
ProcessStartInfo info = new ProcessStartInfo(ilasmPath);
info.Arguments = $"/nologo {otherOptions}/output=\"{outputFile}\" \"{sourceFileName}\"";
info.RedirectStandardError = true;
@ -115,7 +115,7 @@ namespace ICSharpCode.Decompiler.Tests.Helpers @@ -115,7 +115,7 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
return outputFile;
}
public static string Disassemble(string sourceFileName, string outputFile, AssemblerOptions asmOptions)
{
if (asmOptions.HasFlag(AssemblerOptions.UseOwnDisassembler)) {
@ -141,7 +141,7 @@ namespace ICSharpCode.Decompiler.Tests.Helpers @@ -141,7 +141,7 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
}
string ildasmPath = SdkUtility.GetSdkPath("ildasm.exe");
ProcessStartInfo info = new ProcessStartInfo(ildasmPath);
info.Arguments = $"/nobar /utf8 /out=\"{outputFile}\" \"{sourceFileName}\"";
info.RedirectStandardError = true;
@ -182,24 +182,11 @@ namespace ICSharpCode.Decompiler.Tests.Helpers @@ -182,24 +182,11 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
return Regex.Replace(il, @"'<PrivateImplementationDetails>\{[0-9A-F-]+\}'", "'<PrivateImplementationDetails>'");
}
static readonly string refAsmPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86),
@"Reference Assemblies\Microsoft\Framework\.NETFramework\v4.7.2");
static readonly string refAsmPath = new DotNetCorePathFinder(new Version(3, 0)).GetReferenceAssemblyPath(".NETCoreApp, Version = v3.0");
static readonly string thisAsmPath = Path.GetDirectoryName(typeof(Tester).Assembly.Location);
static readonly Lazy<IEnumerable<MetadataReference>> defaultReferences = new Lazy<IEnumerable<MetadataReference>>(GetDefaultReferences);
static readonly string[] references = new string[] {
"netstandard, Version=2.1.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51",
"mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089",
"System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089",
"System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089",
"System.Runtime, Version=4.2.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
"System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
"Microsoft.CSharp, Version=4.0.4.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
"System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e",
"System.Console, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
};
const string targetFrameworkAttributeSnippet = @"
[assembly: System.Runtime.Versioning.TargetFramework("".NETCoreApp, Version = v3.0"", FrameworkDisplayName = """")]
@ -208,12 +195,8 @@ namespace ICSharpCode.Decompiler.Tests.Helpers @@ -208,12 +195,8 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
static IEnumerable<MetadataReference> GetDefaultReferences()
{
DotNetCorePathFinder pathFinder = new DotNetCorePathFinder(new Version(3, 0));
foreach (var reference in references) {
var result = pathFinder.TryResolveDotNetCore(AssemblyNameReference.Parse(reference));
if (result != null) {
yield return MetadataReference.CreateFromFile(result);
}
foreach (var reference in Directory.EnumerateFiles(refAsmPath, "*.dll")) {
yield return MetadataReference.CreateFromFile(reference);
}
}
@ -462,7 +445,7 @@ namespace ICSharpCode.Decompiler.Tests.Helpers @@ -462,7 +445,7 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
settings = new DecompilerSettings();
using (var file = new FileStream(assemblyFileName, FileMode.Open, FileAccess.Read)) {
var module = new PEFile(assemblyFileName, file, PEStreamOptions.PrefetchEntireImage);
var resolver = new UniversalAssemblyResolver(assemblyFileName, true,
var resolver = new UniversalAssemblyResolver(assemblyFileName, false,
module.Reader.DetectTargetFrameworkId(), PEStreamOptions.PrefetchMetadata);
resolver.AddSearchDirectory(Path.GetDirectoryName(typeof(Span<>).Assembly.Location));
var typeSystem = new DecompilerTypeSystem(module, resolver, settings);
@ -482,16 +465,16 @@ namespace ICSharpCode.Decompiler.Tests.Helpers @@ -482,16 +465,16 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
return fileName;
}
}
public static void RunAndCompareOutput(string testFileName, string outputFile, string decompiledOutputFile, string decompiledCodeFile = null)
{
string output1, output2, error1, error2;
int result1 = Tester.Run(outputFile, out output1, out error1);
int result2 = Tester.Run(decompiledOutputFile, out output2, out error2);
Assert.AreEqual(0, result1, "Exit code != 0; did the test case crash?" + Environment.NewLine + error1);
Assert.AreEqual(0, result2, "Exit code != 0; did the decompiled code crash?" + Environment.NewLine + error2);
if (output1 != output2 || error1 != error2) {
StringBuilder b = new StringBuilder();
b.AppendLine($"Test {testFileName} failed: output does not match.");

9
ICSharpCode.Decompiler/CSharp/CallBuilder.cs

@ -989,6 +989,10 @@ namespace ICSharpCode.Decompiler.CSharp @@ -989,6 +989,10 @@ namespace ICSharpCode.Decompiler.CSharp
foundMember = null;
bestCandidateIsExpandedForm = false;
var lookup = new MemberLookup(resolver.CurrentTypeDefinition, resolver.CurrentTypeDefinition.ParentModule);
Log.WriteLine("IsUnambiguousCall: Performing overload resolution for " + method);
Log.WriteCollection(" Arguments: ", arguments.Select(a => a.ResolveResult));
var or = new OverloadResolution(resolver.Compilation,
firstOptionalArgumentIndex < 0 ? arguments.SelectArray(a => a.ResolveResult) : arguments.Take(firstOptionalArgumentIndex).Select(a => a.ResolveResult).ToArray(),
argumentNames: firstOptionalArgumentIndex < 0 || argumentNames == null ? argumentNames : argumentNames.Take(firstOptionalArgumentIndex).ToArray(),
@ -1043,6 +1047,9 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1043,6 +1047,9 @@ namespace ICSharpCode.Decompiler.CSharp
bool IsUnambiguousAccess(ExpectedTargetDetails expectedTargetDetails, ResolveResult target, IMethod method,
IList<TranslatedExpression> arguments, string[] argumentNames, out IMember foundMember)
{
Log.WriteLine("IsUnambiguousAccess: Performing overload resolution for " + method);
Log.WriteCollection(" Arguments: ", arguments.Select(a => a.ResolveResult));
foundMember = null;
if (target == null) {
var result = resolver.ResolveSimpleName(method.AccessorOwner.Name,
@ -1400,6 +1407,8 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1400,6 +1407,8 @@ namespace ICSharpCode.Decompiler.CSharp
bool IsUnambiguousMethodReference(ExpectedTargetDetails expectedTargetDetails, IMethod method, ResolveResult target, IReadOnlyList<IType> typeArguments, out ResolveResult result)
{
Log.WriteLine("IsUnambiguousMethodReference: Performing overload resolution for " + method);
var lookup = new MemberLookup(resolver.CurrentTypeDefinition, resolver.CurrentTypeDefinition.ParentModule);
var or = new OverloadResolution(resolver.Compilation,
arguments: method.Parameters.SelectReadOnlyArray(p => new TypeResolveResult(p.Type)), // there are no arguments, use parameter types

19
ICSharpCode.Decompiler/Metadata/DotNetCorePathFinder.cs

@ -109,6 +109,25 @@ namespace ICSharpCode.Decompiler.Metadata @@ -109,6 +109,25 @@ namespace ICSharpCode.Decompiler.Metadata
return FallbackToDotNetSharedDirectory(name, version);
}
internal string GetReferenceAssemblyPath(string targetFramework)
{
var (tfi, version) = UniversalAssemblyResolver.ParseTargetFramework(targetFramework);
string identifier, identifierExt;
switch (tfi) {
case TargetFrameworkIdentifier.NETCoreApp:
identifier = "Microsoft.NETCore.App";
identifierExt = "netcoreapp" + version.Major + "." + version.Minor;
break;
case TargetFrameworkIdentifier.NETStandard:
identifier = "NETStandard.Library";
identifierExt = "netstandard" + version.Major + "." + version.Minor;
break;
default:
throw new NotSupportedException();
}
return Path.Combine(dotnetBasePath, "packs", identifier + ".Ref", version.ToString(), "ref", identifierExt);
}
static IEnumerable<DotNetCorePackageInfo> LoadPackageInfos(string depsJsonFileName, string targetFramework)
{
var dependencies = JsonReader.Parse(File.ReadAllText(depsJsonFileName));

32
ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs

@ -26,6 +26,21 @@ using System.Text; @@ -26,6 +26,21 @@ using System.Text;
namespace ICSharpCode.Decompiler.Metadata
{
enum TargetFrameworkIdentifier
{
NETFramework,
NETCoreApp,
NETStandard,
Silverlight
}
enum DecompilerRuntime
{
NETFramework,
NETCoreApp,
Mono
}
// This is inspired by Mono.Cecil's BaseAssemblyResolver/DefaultAssemblyResolver.
public class UniversalAssemblyResolver : IAssemblyResolver
{
@ -67,21 +82,6 @@ namespace ICSharpCode.Decompiler.Metadata @@ -67,21 +82,6 @@ namespace ICSharpCode.Decompiler.Metadata
return directories.ToArray();
}
enum TargetFrameworkIdentifier
{
NETFramework,
NETCoreApp,
NETStandard,
Silverlight
}
enum DecompilerRuntime
{
NETFramework,
NETCoreApp,
Mono
}
string targetFramework;
TargetFrameworkIdentifier targetFrameworkIdentifier;
Version targetFrameworkVersion;
@ -101,7 +101,7 @@ namespace ICSharpCode.Decompiler.Metadata @@ -101,7 +101,7 @@ namespace ICSharpCode.Decompiler.Metadata
AddSearchDirectory(baseDirectory);
}
static (TargetFrameworkIdentifier, Version) ParseTargetFramework(string targetFramework)
internal static (TargetFrameworkIdentifier, Version) ParseTargetFramework(string targetFramework)
{
string[] tokens = targetFramework.Split(',');
TargetFrameworkIdentifier identifier;

Loading…
Cancel
Save