Browse Source

Run tests with different versions of Roslyn

pull/2194/head
Siegfried Pammer 5 years ago
parent
commit
be57dc454c
  1. 104
      ICSharpCode.Decompiler.Tests/CorrectnessTestRunner.cs
  2. 111
      ICSharpCode.Decompiler.Tests/Helpers/RoslynToolset.cs
  3. 172
      ICSharpCode.Decompiler.Tests/Helpers/Tester.VB.cs
  4. 296
      ICSharpCode.Decompiler.Tests/Helpers/Tester.cs
  5. 2
      ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj
  6. 72
      ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs
  7. 8
      ICSharpCode.Decompiler.Tests/TestCases/Correctness/DeconstructionTests.cs
  8. 6
      ICSharpCode.Decompiler.Tests/TestCases/Correctness/NullableTests.cs
  9. 10
      ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue1325.cs
  10. 2
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/AutoProperties.cs
  11. 6
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.cs
  12. 32
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/DeconstructionTests.cs
  13. 2
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/DelegateConstruction.cs
  14. 2
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/InitializerTests.cs
  15. 2
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/PropertiesAndEvents.cs
  16. 4
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/VariableNaming.cs
  17. 4
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/VariableNamingWithoutSymbols.cs
  18. 2
      ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoArrayInitializers.Expected.cs
  19. 6
      ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoArrayInitializers.opt.roslyn.il
  20. 6
      ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoArrayInitializers.roslyn.il
  21. 8
      ICSharpCode.Decompiler.Tests/UglyTestRunner.cs
  22. 16
      ICSharpCode.Decompiler.Tests/VBPrettyTestRunner.cs
  23. 17
      ICSharpCode.Decompiler/IL/Transforms/AssignVariableNames.cs

104
ICSharpCode.Decompiler.Tests/CorrectnessTestRunner.cs

@ -53,40 +53,66 @@ namespace ICSharpCode.Decompiler.Tests
{ {
CompilerOptions.None, CompilerOptions.None,
CompilerOptions.Optimize, CompilerOptions.Optimize,
CompilerOptions.UseRoslyn, CompilerOptions.UseRoslyn1_3_2,
CompilerOptions.Optimize | CompilerOptions.UseRoslyn, CompilerOptions.Optimize | CompilerOptions.UseRoslyn1_3_2,
CompilerOptions.UseRoslyn2_10_0,
CompilerOptions.Optimize | CompilerOptions.UseRoslyn2_10_0,
CompilerOptions.UseRoslynLatest,
CompilerOptions.Optimize | CompilerOptions.UseRoslynLatest,
}; };
static readonly CompilerOptions[] defaultOptions = static readonly CompilerOptions[] defaultOptions =
{ {
CompilerOptions.None, CompilerOptions.None,
CompilerOptions.Optimize, CompilerOptions.Optimize,
CompilerOptions.UseRoslyn, CompilerOptions.UseRoslyn1_3_2,
CompilerOptions.Optimize | CompilerOptions.UseRoslyn, CompilerOptions.Optimize | CompilerOptions.UseRoslyn1_3_2,
CompilerOptions.UseRoslyn2_10_0,
CompilerOptions.Optimize | CompilerOptions.UseRoslyn2_10_0,
CompilerOptions.UseRoslynLatest,
CompilerOptions.Optimize | CompilerOptions.UseRoslynLatest,
CompilerOptions.UseMcs, CompilerOptions.UseMcs,
CompilerOptions.Optimize | CompilerOptions.UseMcs CompilerOptions.Optimize | CompilerOptions.UseMcs
}; };
static readonly CompilerOptions[] roslynOnlyOptions = static readonly CompilerOptions[] roslynOnlyOptions =
{
CompilerOptions.UseRoslyn1_3_2,
CompilerOptions.Optimize | CompilerOptions.UseRoslyn1_3_2,
CompilerOptions.UseRoslyn2_10_0,
CompilerOptions.Optimize | CompilerOptions.UseRoslyn2_10_0,
CompilerOptions.UseRoslynLatest,
CompilerOptions.Optimize | CompilerOptions.UseRoslynLatest,
};
static readonly CompilerOptions[] roslyn2OrNewerOptions =
{
CompilerOptions.UseRoslyn2_10_0,
CompilerOptions.Optimize | CompilerOptions.UseRoslyn2_10_0,
CompilerOptions.UseRoslynLatest,
CompilerOptions.Optimize | CompilerOptions.UseRoslynLatest,
};
static readonly CompilerOptions[] roslynLatestOnlyOptions =
{ {
CompilerOptions.UseRoslyn, CompilerOptions.UseRoslynLatest,
CompilerOptions.Optimize | CompilerOptions.UseRoslyn CompilerOptions.Optimize | CompilerOptions.UseRoslynLatest,
}; };
[Test] [Test]
public void Comparisons([ValueSource("defaultOptions")] CompilerOptions options) public void Comparisons([ValueSource(nameof(defaultOptions))] CompilerOptions options)
{ {
RunCS(options: options); RunCS(options: options);
} }
[Test] [Test]
public void Conversions([ValueSource("defaultOptions")] CompilerOptions options) public void Conversions([ValueSource(nameof(defaultOptions))] CompilerOptions options)
{ {
RunCS(options: options); RunCS(options: options);
} }
[Test] [Test]
public void FloatingPointArithmetic([ValueSource("noMonoOptions")] CompilerOptions options, [Values(32, 64)] int bits) public void FloatingPointArithmetic([ValueSource(nameof(noMonoOptions))] CompilerOptions options, [Values(32, 64)] int bits)
{ {
// The behavior of the #1794 incorrect `(float)(double)val` cast only causes test failures // The behavior of the #1794 incorrect `(float)(double)val` cast only causes test failures
// for some runtime+compiler combinations. // for some runtime+compiler combinations.
@ -98,115 +124,115 @@ namespace ICSharpCode.Decompiler.Tests
} }
[Test] [Test]
public void HelloWorld([ValueSource("defaultOptions")] CompilerOptions options) public void HelloWorld([ValueSource(nameof(defaultOptions))] CompilerOptions options)
{ {
RunCS(options: options); RunCS(options: options);
} }
[Test] [Test]
public void ControlFlow([ValueSource("defaultOptions")] CompilerOptions options) public void ControlFlow([ValueSource(nameof(defaultOptions))] CompilerOptions options)
{ {
RunCS(options: options); RunCS(options: options);
} }
[Test] [Test]
public void CompoundAssignment([ValueSource("defaultOptions")] CompilerOptions options) public void CompoundAssignment([ValueSource(nameof(defaultOptions))] CompilerOptions options)
{ {
RunCS(options: options); RunCS(options: options);
} }
[Test] [Test]
public void PropertiesAndEvents([ValueSource("defaultOptions")] CompilerOptions options) public void PropertiesAndEvents([ValueSource(nameof(defaultOptions))] CompilerOptions options)
{ {
RunCS(options: options); RunCS(options: options);
} }
[Test] [Test]
public void Switch([ValueSource("defaultOptions")] CompilerOptions options) public void Switch([ValueSource(nameof(defaultOptions))] CompilerOptions options)
{ {
RunCS(options: options); RunCS(options: options);
} }
[Test] [Test]
public void Using([ValueSource("defaultOptions")] CompilerOptions options) public void Using([ValueSource(nameof(defaultOptions))] CompilerOptions options)
{ {
RunCS(options: options); RunCS(options: options);
} }
[Test] [Test]
public void Loops([ValueSource("defaultOptions")] CompilerOptions options) public void Loops([ValueSource(nameof(defaultOptions))] CompilerOptions options)
{ {
RunCS(options: options); RunCS(options: options);
} }
[Test] [Test]
public void NullableTests([ValueSource("defaultOptions")] CompilerOptions options) public void NullableTests([ValueSource(nameof(defaultOptions))] CompilerOptions options)
{ {
RunCS(options: options); RunCS(options: options);
} }
[Test] [Test]
public void Generics([ValueSource("defaultOptions")] CompilerOptions options) public void Generics([ValueSource(nameof(defaultOptions))] CompilerOptions options)
{ {
RunCS(options: options); RunCS(options: options);
} }
[Test] [Test]
public void ValueTypeCall([ValueSource("defaultOptions")] CompilerOptions options) public void ValueTypeCall([ValueSource(nameof(defaultOptions))] CompilerOptions options)
{ {
RunCS(options: options); RunCS(options: options);
} }
[Test] [Test]
public void InitializerTests([ValueSource("defaultOptions")] CompilerOptions options) public void InitializerTests([ValueSource(nameof(defaultOptions))] CompilerOptions options)
{ {
RunCS(options: options); RunCS(options: options);
} }
[Test] [Test]
public void DecimalFields([ValueSource("defaultOptions")] CompilerOptions options) public void DecimalFields([ValueSource(nameof(defaultOptions))] CompilerOptions options)
{ {
RunCS(options: options); RunCS(options: options);
} }
[Test] [Test]
public void UndocumentedExpressions([ValueSource("noMonoOptions")] CompilerOptions options) public void UndocumentedExpressions([ValueSource(nameof(noMonoOptions))] CompilerOptions options)
{ {
RunCS(options: options); RunCS(options: options);
} }
[Test] [Test]
public void Uninit([ValueSource("noMonoOptions")] CompilerOptions options) public void Uninit([ValueSource(nameof(noMonoOptions))] CompilerOptions options)
{ {
RunVB(options: options); RunVB(options: options);
} }
[Test] [Test]
public void MemberLookup([ValueSource("defaultOptions")] CompilerOptions options) public void MemberLookup([ValueSource(nameof(defaultOptions))] CompilerOptions options)
{ {
RunCS(options: options); RunCS(options: options);
} }
[Test] [Test]
public void OverloadResolution([ValueSource("defaultOptions")] CompilerOptions options) public void OverloadResolution([ValueSource(nameof(defaultOptions))] CompilerOptions options)
{ {
RunCS(options: options); RunCS(options: options);
} }
[Test] [Test]
public void ExpressionTrees([ValueSource("defaultOptions")] CompilerOptions options) public void ExpressionTrees([ValueSource(nameof(defaultOptions))] CompilerOptions options)
{ {
RunCS(options: options); RunCS(options: options);
} }
[Test] [Test]
public void NullPropagation([ValueSource("roslynOnlyOptions")] CompilerOptions options) public void NullPropagation([ValueSource(nameof(roslynOnlyOptions))] CompilerOptions options)
{ {
RunCS(options: options); RunCS(options: options);
} }
[Test] [Test]
public void DeconstructionTests([ValueSource("roslynOnlyOptions")] CompilerOptions options) public void DeconstructionTests([ValueSource(nameof(roslyn2OrNewerOptions))] CompilerOptions options)
{ {
RunCS(options: options); RunCS(options: options);
} }
@ -239,7 +265,7 @@ namespace ICSharpCode.Decompiler.Tests
[Test] [Test]
public void StackTypes([Values(false, true)] bool force32Bit) public void StackTypes([Values(false, true)] bool force32Bit)
{ {
CompilerOptions compiler = CompilerOptions.UseRoslyn | CompilerOptions.UseDebug; CompilerOptions compiler = CompilerOptions.UseRoslynLatest | CompilerOptions.UseDebug;
AssemblerOptions asm = AssemblerOptions.None; AssemblerOptions asm = AssemblerOptions.None;
if (force32Bit) if (force32Bit)
{ {
@ -250,7 +276,7 @@ namespace ICSharpCode.Decompiler.Tests
} }
[Test] [Test]
public void UnsafeCode([ValueSource("defaultOptions")] CompilerOptions options) public void UnsafeCode([ValueSource(nameof(defaultOptions))] CompilerOptions options)
{ {
if (options.HasFlag(CompilerOptions.UseMcs)) if (options.HasFlag(CompilerOptions.UseMcs))
{ {
@ -260,25 +286,25 @@ namespace ICSharpCode.Decompiler.Tests
} }
[Test] [Test]
public void ConditionalAttr([ValueSource("defaultOptions")] CompilerOptions options) public void ConditionalAttr([ValueSource(nameof(defaultOptions))] CompilerOptions options)
{ {
RunCS(options: options); RunCS(options: options);
} }
[Test] [Test]
public void TrickyTypes([ValueSource("defaultOptions")] CompilerOptions options) public void TrickyTypes([ValueSource(nameof(defaultOptions))] CompilerOptions options)
{ {
RunCS(options: options); RunCS(options: options);
} }
[Test] [Test]
public void Capturing([ValueSource("defaultOptions")] CompilerOptions options) public void Capturing([ValueSource(nameof(defaultOptions))] CompilerOptions options)
{ {
RunCS(options: options); RunCS(options: options);
} }
[Test] [Test]
public void YieldReturn([ValueSource("defaultOptions")] CompilerOptions options) public void YieldReturn([ValueSource(nameof(defaultOptions))] CompilerOptions options)
{ {
if (options.HasFlag(CompilerOptions.UseMcs)) if (options.HasFlag(CompilerOptions.UseMcs))
{ {
@ -288,25 +314,25 @@ namespace ICSharpCode.Decompiler.Tests
} }
[Test] [Test]
public void Async([ValueSource("noMonoOptions")] CompilerOptions options) public void Async([ValueSource(nameof(noMonoOptions))] CompilerOptions options)
{ {
RunCS(options: options); RunCS(options: options);
} }
[Test] [Test]
public void LINQRaytracer([ValueSource("defaultOptions")] CompilerOptions options) public void LINQRaytracer([ValueSource(nameof(defaultOptions))] CompilerOptions options)
{ {
RunCS(options: options); RunCS(options: options);
} }
[Test] [Test]
public void StringConcat([ValueSource("defaultOptions")] CompilerOptions options) public void StringConcat([ValueSource(nameof(defaultOptions))] CompilerOptions options)
{ {
RunCS(options: options); RunCS(options: options);
} }
[Test] [Test]
public void MiniJSON([ValueSource("defaultOptions")] CompilerOptions options) public void MiniJSON([ValueSource(nameof(defaultOptions))] CompilerOptions options)
{ {
if (options.HasFlag(CompilerOptions.UseMcs)) if (options.HasFlag(CompilerOptions.UseMcs))
{ {
@ -332,7 +358,7 @@ namespace ICSharpCode.Decompiler.Tests
// mcs has some compiler bugs that cause it to not accept ILSpy-generated code, // mcs has some compiler bugs that cause it to not accept ILSpy-generated code,
// for example when there's unreachable code due to other compiler bugs in the first mcs run. // for example when there's unreachable code due to other compiler bugs in the first mcs run.
options &= ~CompilerOptions.UseMcs; options &= ~CompilerOptions.UseMcs;
options |= CompilerOptions.UseRoslyn; options |= CompilerOptions.UseRoslynLatest;
// Also, add an .exe.config so that we consistently use the .NET 4.x runtime. // Also, add an .exe.config so that we consistently use the .NET 4.x runtime.
File.WriteAllText(outputFile.PathToAssembly + ".config", @"<?xml version=""1.0"" encoding=""utf-8""?> File.WriteAllText(outputFile.PathToAssembly + ".config", @"<?xml version=""1.0"" encoding=""utf-8""?>
<configuration> <configuration>

111
ICSharpCode.Decompiler.Tests/Helpers/RoslynToolset.cs

@ -0,0 +1,111 @@
// Copyright (c) 2020 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;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using NuGet.Common;
using NuGet.Packaging;
using NuGet.Protocol;
using NuGet.Protocol.Core.Types;
using NuGet.Versioning;
namespace ICSharpCode.Decompiler.Tests.Helpers
{
class RoslynToolset
{
readonly SourceCacheContext cache;
readonly SourceRepository repository;
readonly FindPackageByIdResource resource;
readonly string nugetDir;
readonly Dictionary<string, string> installedCompilers = new Dictionary<string, string> {
{ "legacy", Environment.ExpandEnvironmentVariables(@"%WINDIR%\Microsoft.NET\Framework\v4.0.30319") }
};
readonly object syncObj = new object();
public RoslynToolset()
{
this.cache = new SourceCacheContext();
this.repository = Repository.Factory.GetCoreV3("https://api.nuget.org/v3/index.json");
this.resource = repository.GetResource<FindPackageByIdResource>();
this.nugetDir = Path.Combine(Path.GetDirectoryName(typeof(RoslynToolset).Assembly.Location), "roslyn");
}
public string GetCSharpCompiler(string version)
{
return GetCompiler("csc.exe", version);
}
public string GetVBCompiler(string version)
{
return GetCompiler("vbc.exe", version);
}
string GetCompiler(string compiler, string version)
{
lock (syncObj)
{
if (installedCompilers.TryGetValue(version, out var path))
return Path.Combine(path, compiler);
string outputPath = Path.Combine(nugetDir, version);
path = Path.Combine(outputPath, "tools");
if (!Directory.Exists(path))
{
FetchPackage(version, outputPath).GetAwaiter().GetResult();
}
installedCompilers.Add(version, path);
return Path.Combine(path, compiler);
}
}
async Task FetchPackage(string version, string outputPath)
{
ILogger logger = NullLogger.Instance;
CancellationToken cancellationToken = CancellationToken.None;
using MemoryStream packageStream = new MemoryStream();
await resource.CopyNupkgToStreamAsync(
"Microsoft.Net.Compilers",
NuGetVersion.Parse(version),
packageStream,
cache,
logger,
cancellationToken);
using PackageArchiveReader packageReader = new PackageArchiveReader(packageStream);
NuspecReader nuspecReader = await packageReader.GetNuspecReaderAsync(cancellationToken);
var files = await packageReader.GetFilesAsync(cancellationToken);
files = files.Where(f => f.StartsWith("tools", StringComparison.OrdinalIgnoreCase));
await packageReader.CopyFilesAsync(outputPath, files,
(sourceFile, targetPath, fileStream) => {
fileStream.CopyToFile(targetPath);
return targetPath;
},
logger, cancellationToken);
}
}
}

172
ICSharpCode.Decompiler.Tests/Helpers/Tester.VB.cs

@ -1,16 +1,30 @@
using System; // Copyright (c) 2015 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;
using System.CodeDom.Compiler; using System.CodeDom.Compiler;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.CodeAnalysis; using NUnit.Framework;
using Microsoft.CodeAnalysis.VisualBasic;
using Microsoft.VisualBasic;
namespace ICSharpCode.Decompiler.Tests.Helpers namespace ICSharpCode.Decompiler.Tests.Helpers
{ {
@ -26,78 +40,116 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
var preprocessorSymbols = GetPreprocessorSymbols(flags).Select(symbol => new KeyValuePair<string, object>(symbol, 1)).ToList(); var preprocessorSymbols = GetPreprocessorSymbols(flags).Select(symbol => new KeyValuePair<string, object>(symbol, 1)).ToList();
if (flags.HasFlag(CompilerOptions.UseRoslyn)) if (!flags.HasFlag(CompilerOptions.UseMcs))
{ {
var parseOptions = new VisualBasicParseOptions(preprocessorSymbols: preprocessorSymbols, languageVersion: LanguageVersion.Latest);
var syntaxTrees = sourceFileNames.Select(f => SyntaxFactory.ParseSyntaxTree(File.ReadAllText(f), parseOptions, path: f));
var references = defaultReferences.Value;
if (flags.HasFlag(CompilerOptions.ReferenceVisualBasic))
{
references = references.Concat(visualBasic.Value);
}
var compilation = VisualBasicCompilation.Create(Path.GetFileNameWithoutExtension(sourceFileName),
syntaxTrees, references,
new VisualBasicCompilationOptions(
flags.HasFlag(CompilerOptions.Library) ? OutputKind.DynamicallyLinkedLibrary : OutputKind.ConsoleApplication,
platform: flags.HasFlag(CompilerOptions.Force32Bit) ? Platform.X86 : Platform.AnyCpu,
optimizationLevel: flags.HasFlag(CompilerOptions.Optimize) ? OptimizationLevel.Release : OptimizationLevel.Debug,
deterministic: true
));
CompilerResults results = new CompilerResults(new TempFileCollection()); CompilerResults results = new CompilerResults(new TempFileCollection());
results.PathToAssembly = outputFileName ?? Path.GetTempFileName(); results.PathToAssembly = outputFileName ?? Path.GetTempFileName();
var emitResult = compilation.Emit(results.PathToAssembly);
if (!emitResult.Success) var (roslynVersion, languageVersion) = (flags & CompilerOptions.UseRoslynMask) switch
{
0 => ("legacy", "11"),
CompilerOptions.UseRoslyn1_3_2 => ("1.3.2", "14"),
CompilerOptions.UseRoslyn2_10_0 => ("2.10.0", "latest"),
_ => (RoslynLatestVersion, flags.HasFlag(CompilerOptions.Preview) ? "preview" : "latest")
};
var vbcPath = roslynToolset.GetVBCompiler(roslynVersion);
IEnumerable<string> references;
if ((flags & CompilerOptions.UseRoslynMask) != 0)
{ {
StringBuilder b = new StringBuilder("Compiler error:"); if (flags.HasFlag(CompilerOptions.ReferenceCore))
foreach (var diag in emitResult.Diagnostics)
{ {
b.AppendLine(diag.ToString()); references = coreDefaultReferences.Value.Select(r => "-r:\"" + r + "\"");
}
else
{
references = roslynDefaultReferences.Value.Select(r => "-r:\"" + r + "\"");
} }
throw new Exception(b.ToString());
} }
return results; else
}
else if (flags.HasFlag(CompilerOptions.UseMcs))
{
throw new NotSupportedException("Cannot use mcs for VB");
}
else
{
var provider = new VBCodeProvider(new Dictionary<string, string> { { "CompilerVersion", "v4.0" } });
CompilerParameters options = new CompilerParameters();
options.GenerateExecutable = !flags.HasFlag(CompilerOptions.Library);
options.CompilerOptions = "/optimize" + (flags.HasFlag(CompilerOptions.Optimize) ? "+" : "-");
options.CompilerOptions += (flags.HasFlag(CompilerOptions.UseDebug) ? " /debug" : "");
options.CompilerOptions += (flags.HasFlag(CompilerOptions.Force32Bit) ? " /platform:anycpu32bitpreferred" : "");
options.CompilerOptions += " /optioninfer+ /optionexplicit+";
if (preprocessorSymbols.Count > 0)
{ {
options.CompilerOptions += " /d:" + string.Join(",", preprocessorSymbols.Select(p => $"{p.Key}={p.Value}")); references = defaultReferences.Value.Select(r => "-r:\"" + r + "\"");
} }
if (outputFileName != null) if (flags.HasFlag(CompilerOptions.ReferenceVisualBasic))
{ {
options.OutputAssembly = outputFileName; if ((flags & CompilerOptions.UseRoslynMask) != 0)
{
references = references.Concat(visualBasic.Value.Select(r => "-r:\"" + r + "\""));
}
else
{
references = references.Concat(new[] { "-r:\"Microsoft.VisualBasic.dll\"" });
}
} }
string otherOptions = $"-noconfig " +
"-optioninfer+ -optionexplicit+ " +
$"-langversion:{languageVersion} " +
$"/optimize{(flags.HasFlag(CompilerOptions.Optimize) ? "+ " : "- ")}";
options.ReferencedAssemblies.Add("System.dll"); // note: the /shared switch is undocumented. It allows us to use the VBCSCompiler.exe compiler
options.ReferencedAssemblies.Add("System.Core.dll"); // server to speed up testing
options.ReferencedAssemblies.Add("System.Xml.dll"); if (roslynVersion != "legacy")
if (flags.HasFlag(CompilerOptions.ReferenceVisualBasic))
{ {
options.ReferencedAssemblies.Add("Microsoft.VisualBasic.dll"); otherOptions += "/shared ";
} }
CompilerResults results = provider.CompileAssemblyFromFile(options, sourceFileNames.ToArray());
if (results.Errors.Cast<CompilerError>().Any(e => !e.IsWarning)) if (flags.HasFlag(CompilerOptions.Library))
{ {
StringBuilder b = new StringBuilder("Compiler error:"); otherOptions += "-t:library ";
foreach (var error in results.Errors)
{
b.AppendLine(error.ToString());
}
throw new Exception(b.ToString());
} }
else
{
otherOptions += "-t:exe ";
}
if (flags.HasFlag(CompilerOptions.GeneratePdb))
{
otherOptions += "-debug:full ";
}
else
{
otherOptions += "-debug- ";
}
if (flags.HasFlag(CompilerOptions.Force32Bit))
{
otherOptions += "-platform:x86 ";
}
else
{
otherOptions += "-platform:anycpu ";
}
if (preprocessorSymbols.Count > 0)
{
otherOptions += " \"-d:" + string.Join(",", preprocessorSymbols.Select(kv => kv.Key + "=" + kv.Value)) + "\" ";
}
ProcessStartInfo info = new ProcessStartInfo(vbcPath);
info.Arguments = $"{otherOptions}{string.Join(" ", references)} -out:\"{Path.GetFullPath(results.PathToAssembly)}\" {string.Join(" ", sourceFileNames.Select(fn => '"' + Path.GetFullPath(fn) + '"'))}";
info.RedirectStandardError = true;
info.RedirectStandardOutput = true;
info.UseShellExecute = false;
Console.WriteLine($"\"{info.FileName}\" {info.Arguments}");
Process process = Process.Start(info);
var outputTask = process.StandardOutput.ReadToEndAsync();
var errorTask = process.StandardError.ReadToEndAsync();
Task.WaitAll(outputTask, errorTask);
process.WaitForExit();
Console.WriteLine("output: " + outputTask.Result);
Console.WriteLine("errors: " + errorTask.Result);
Assert.AreEqual(0, process.ExitCode, "vbc failed");
return results; return results;
} }
else
{
throw new NotSupportedException("Cannot use mcs for VB");
}
} }
} }
} }

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

@ -27,6 +27,8 @@ using System.Text;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Xml.Linq;
using System.Xml.XPath;
using ICSharpCode.Decompiler.CSharp; using ICSharpCode.Decompiler.CSharp;
using ICSharpCode.Decompiler.CSharp.OutputVisitor; using ICSharpCode.Decompiler.CSharp.OutputVisitor;
@ -39,7 +41,6 @@ using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Emit; using Microsoft.CodeAnalysis.Emit;
using Microsoft.CodeAnalysis.Text; using Microsoft.CodeAnalysis.Text;
using Microsoft.CSharp;
using NUnit.Framework; using NUnit.Framework;
@ -53,12 +54,15 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
UseDebug = 0x2, UseDebug = 0x2,
Force32Bit = 0x4, Force32Bit = 0x4,
Library = 0x8, Library = 0x8,
UseRoslyn = 0x10, UseRoslyn1_3_2 = 0x10,
UseMcs = 0x20, UseMcs = 0x20,
ReferenceVisualBasic = 0x40, ReferenceVisualBasic = 0x40,
ReferenceCore = 0x80, ReferenceCore = 0x80,
GeneratePdb = 0x100, GeneratePdb = 0x100,
Preview = 0x200 Preview = 0x200,
UseRoslyn2_10_0 = 0x400,
UseRoslynLatest = 0x800,
UseRoslynMask = UseRoslyn1_3_2 | UseRoslyn2_10_0 | UseRoslynLatest
} }
[Flags] [Flags]
@ -80,6 +84,13 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
Path.GetDirectoryName(typeof(Tester).Assembly.Location), Path.GetDirectoryName(typeof(Tester).Assembly.Location),
"../../../TestCases"); "../../../TestCases");
static readonly string PackagesPropsFile = Path.Combine(
Path.GetDirectoryName(typeof(Tester).Assembly.Location),
"../../../../packages.props");
static readonly string RoslynLatestVersion = XDocument.Load(PackagesPropsFile)
.XPathSelectElement("//RoslynVersion").Value;
public static string AssembleIL(string sourceFileName, AssemblerOptions options = AssemblerOptions.UseDebug) public static string AssembleIL(string sourceFileName, AssemblerOptions options = AssemblerOptions.UseDebug)
{ {
string ilasmPath; string ilasmPath;
@ -206,29 +217,41 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
return Regex.Replace(il, @"'<PrivateImplementationDetails>\{[0-9A-F-]+\}'", "'<PrivateImplementationDetails>'"); return Regex.Replace(il, @"'<PrivateImplementationDetails>\{[0-9A-F-]+\}'", "'<PrivateImplementationDetails>'");
} }
static readonly RoslynToolset roslynToolset = new RoslynToolset();
static readonly string coreRefAsmPath = new DotNetCorePathFinder(TargetFrameworkIdentifier.NETCoreApp, new Version(3, 1)).GetReferenceAssemblyPath(".NETCoreApp, Version = v3.1"); static readonly string coreRefAsmPath = new DotNetCorePathFinder(TargetFrameworkIdentifier.NETCoreApp, new Version(3, 1)).GetReferenceAssemblyPath(".NETCoreApp, Version = v3.1");
static readonly string refAsmPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), static readonly string refAsmPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86),
@"Reference Assemblies\Microsoft\Framework\.NETFramework\v4.7.2"); @"Reference Assemblies\Microsoft\Framework\.NETFramework\v4.7.2");
static readonly string thisAsmPath = Path.GetDirectoryName(typeof(Tester).Assembly.Location); static readonly string thisAsmPath = Path.GetDirectoryName(typeof(Tester).Assembly.Location);
static readonly Lazy<IEnumerable<MetadataReference>> defaultReferences = new Lazy<IEnumerable<MetadataReference>>(delegate { static readonly Lazy<IEnumerable<string>> defaultReferences = new Lazy<IEnumerable<string>>(delegate {
return new[] return new[]
{ {
MetadataReference.CreateFromFile(Path.Combine(refAsmPath, "Facades\\netstandard.dll")), "System.dll",
MetadataReference.CreateFromFile(Path.Combine(refAsmPath, "mscorlib.dll")), "System.Core.dll",
MetadataReference.CreateFromFile(Path.Combine(refAsmPath, "System.dll")), "System.Xml.dll",
MetadataReference.CreateFromFile(Path.Combine(refAsmPath, "System.Core.dll")), "Microsoft.CSharp.dll"
MetadataReference.CreateFromFile(Path.Combine(refAsmPath, @"Facades\System.Runtime.dll")),
MetadataReference.CreateFromFile(Path.Combine(refAsmPath, "System.Xml.dll")),
MetadataReference.CreateFromFile(Path.Combine(refAsmPath, "Microsoft.CSharp.dll")),
MetadataReference.CreateFromFile(typeof(ValueTuple).Assembly.Location),
MetadataReference.CreateFromFile(typeof(ValueTask).Assembly.Location),
MetadataReference.CreateFromFile(typeof(Span<>).Assembly.Location),
}; };
}); });
static readonly Lazy<IEnumerable<MetadataReference>> coreDefaultReferences = new Lazy<IEnumerable<MetadataReference>>(GetDefaultReferences); static readonly Lazy<IEnumerable<string>> roslynDefaultReferences = new Lazy<IEnumerable<string>>(delegate {
return new[]
{
Path.Combine(refAsmPath, "Facades\\netstandard.dll"),
Path.Combine(refAsmPath, "mscorlib.dll"),
Path.Combine(refAsmPath, "System.dll"),
Path.Combine(refAsmPath, "System.Core.dll"),
Path.Combine(refAsmPath, @"Facades\System.Runtime.dll"),
Path.Combine(refAsmPath, "System.Xml.dll"),
Path.Combine(refAsmPath, "Microsoft.CSharp.dll"),
typeof(ValueTuple).Assembly.Location,
typeof(ValueTask).Assembly.Location,
typeof(Span<>).Assembly.Location,
};
});
static readonly Lazy<IEnumerable<string>> coreDefaultReferences = new Lazy<IEnumerable<string>>(GetDefaultReferences);
const string targetFrameworkAttributeSnippet = @" const string targetFrameworkAttributeSnippet = @"
@ -236,17 +259,26 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
"; ";
static IEnumerable<MetadataReference> GetDefaultReferences() static readonly Lazy<string> targetFrameworkAttributeSnippetFile = new Lazy<string>(GetTargetFrameworkAttributeSnippetFile);
static string GetTargetFrameworkAttributeSnippetFile()
{
var tempFile = Path.GetTempFileName();
File.WriteAllText(tempFile, targetFrameworkAttributeSnippet);
return tempFile;
}
static IEnumerable<string> GetDefaultReferences()
{ {
foreach (var reference in Directory.EnumerateFiles(coreRefAsmPath, "*.dll")) foreach (var reference in Directory.EnumerateFiles(coreRefAsmPath, "*.dll"))
{ {
yield return MetadataReference.CreateFromFile(reference); yield return reference;
} }
} }
static readonly Lazy<IEnumerable<MetadataReference>> visualBasic = new Lazy<IEnumerable<MetadataReference>>(delegate { static readonly Lazy<IEnumerable<string>> visualBasic = new Lazy<IEnumerable<string>>(delegate {
return new[] { return new[] {
MetadataReference.CreateFromFile(Path.Combine(refAsmPath, "Microsoft.VisualBasic.dll")) Path.Combine(refAsmPath, "Microsoft.VisualBasic.dll")
}; };
}); });
@ -265,22 +297,29 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
{ {
preprocessorSymbols.Add("NETCORE"); preprocessorSymbols.Add("NETCORE");
} }
if (flags.HasFlag(CompilerOptions.UseRoslyn)) if ((flags & CompilerOptions.UseRoslynMask) != 0)
{ {
preprocessorSymbols.Add("ROSLYN"); preprocessorSymbols.Add("ROSLYN");
preprocessorSymbols.Add("CS60"); preprocessorSymbols.Add("CS60");
preprocessorSymbols.Add("CS70");
preprocessorSymbols.Add("CS71");
preprocessorSymbols.Add("CS72");
preprocessorSymbols.Add("CS73");
preprocessorSymbols.Add("CS80");
preprocessorSymbols.Add("VB11"); preprocessorSymbols.Add("VB11");
preprocessorSymbols.Add("VB14"); preprocessorSymbols.Add("VB14");
preprocessorSymbols.Add("VB15"); if (flags.HasFlag(CompilerOptions.UseRoslyn2_10_0)
|| flags.HasFlag(CompilerOptions.UseRoslynLatest))
if (flags.HasFlag(CompilerOptions.Preview)) {
preprocessorSymbols.Add("CS70");
preprocessorSymbols.Add("CS71");
preprocessorSymbols.Add("CS72");
preprocessorSymbols.Add("VB15");
}
if (flags.HasFlag(CompilerOptions.UseRoslynLatest))
{ {
preprocessorSymbols.Add("CS90"); preprocessorSymbols.Add("CS73");
preprocessorSymbols.Add("CS80");
preprocessorSymbols.Add("VB16");
if (flags.HasFlag(CompilerOptions.Preview))
{
preprocessorSymbols.Add("CS90");
}
} }
} }
else if (flags.HasFlag(CompilerOptions.UseMcs)) else if (flags.HasFlag(CompilerOptions.UseMcs))
@ -302,63 +341,119 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
{ {
sourceFileNames.Add(Path.GetFullPath(Path.Combine(Path.GetDirectoryName(sourceFileName), match.Groups[1].Value))); sourceFileNames.Add(Path.GetFullPath(Path.Combine(Path.GetDirectoryName(sourceFileName), match.Groups[1].Value)));
} }
if (flags.HasFlag(CompilerOptions.ReferenceCore))
{
sourceFileNames.Add(targetFrameworkAttributeSnippetFile.Value);
}
var preprocessorSymbols = GetPreprocessorSymbols(flags); var preprocessorSymbols = GetPreprocessorSymbols(flags);
if (flags.HasFlag(CompilerOptions.UseRoslyn)) if (!flags.HasFlag(CompilerOptions.UseMcs))
{ {
var languageVersion = flags.HasFlag(CompilerOptions.Preview) CompilerResults results = new CompilerResults(new TempFileCollection());
? Microsoft.CodeAnalysis.CSharp.LanguageVersion.Preview results.PathToAssembly = outputFileName ?? Path.GetTempFileName();
: Microsoft.CodeAnalysis.CSharp.LanguageVersion.CSharp8;
var parseOptions = new CSharpParseOptions( var (roslynVersion, languageVersion) = (flags & CompilerOptions.UseRoslynMask) switch
preprocessorSymbols: preprocessorSymbols.ToArray(),
languageVersion: languageVersion
);
var syntaxTrees = sourceFileNames.Select(f => SyntaxFactory.ParseSyntaxTree(File.ReadAllText(f), parseOptions, path: f, encoding: Encoding.UTF8));
if (flags.HasFlag(CompilerOptions.ReferenceCore))
{ {
syntaxTrees = syntaxTrees.Concat(new[] { SyntaxFactory.ParseSyntaxTree(targetFrameworkAttributeSnippet, parseOptions) }); 0 => ("legacy", "5"),
} CompilerOptions.UseRoslyn1_3_2 => ("1.3.2", "6"),
IEnumerable<MetadataReference> references; CompilerOptions.UseRoslyn2_10_0 => ("2.10.0", "latest"),
if (flags.HasFlag(CompilerOptions.ReferenceCore)) _ => (RoslynLatestVersion, flags.HasFlag(CompilerOptions.Preview) ? "preview" : "latest")
};
var cscPath = roslynToolset.GetCSharpCompiler(roslynVersion);
IEnumerable<string> references;
if ((flags & CompilerOptions.UseRoslynMask) != 0)
{ {
references = coreDefaultReferences.Value; if (flags.HasFlag(CompilerOptions.ReferenceCore))
{
references = coreDefaultReferences.Value.Select(r => "-r:\"" + r + "\"");
}
else
{
references = roslynDefaultReferences.Value.Select(r => "-r:\"" + r + "\"");
}
} }
else else
{ {
references = defaultReferences.Value; references = defaultReferences.Value.Select(r => "-r:\"" + r + "\"");
} }
if (flags.HasFlag(CompilerOptions.ReferenceVisualBasic)) if (flags.HasFlag(CompilerOptions.ReferenceVisualBasic))
{ {
references = references.Concat(visualBasic.Value); if ((flags & CompilerOptions.UseRoslynMask) != 0)
{
references = references.Concat(visualBasic.Value.Select(r => "-r:\"" + r + "\""));
}
else
{
references = references.Concat(new[] { "-r:\"Microsoft.VisualBasic.dll\"" });
}
} }
var compilation = CSharpCompilation.Create(Path.GetFileNameWithoutExtension(sourceFileName), string otherOptions = $"-noconfig " +
syntaxTrees, references, $"-langversion:{languageVersion} " +
new CSharpCompilationOptions( $"-unsafe -o{(flags.HasFlag(CompilerOptions.Optimize) ? "+ " : "- ")}";
flags.HasFlag(CompilerOptions.Library) ? OutputKind.DynamicallyLinkedLibrary : OutputKind.ConsoleApplication,
platform: flags.HasFlag(CompilerOptions.Force32Bit) ? Platform.X86 : Platform.AnyCpu, // note: the /shared switch is undocumented. It allows us to use the VBCSCompiler.exe compiler
optimizationLevel: flags.HasFlag(CompilerOptions.Optimize) ? OptimizationLevel.Release : OptimizationLevel.Debug, // server to speed up testing
allowUnsafe: true, if (roslynVersion != "legacy")
deterministic: true {
)); otherOptions += "/shared ";
CompilerResults results = new CompilerResults(new TempFileCollection()); }
results.PathToAssembly = outputFileName ?? Path.GetTempFileName();
string pdbName = null; if (flags.HasFlag(CompilerOptions.Library))
{
otherOptions += "-t:library ";
}
else
{
otherOptions += "-t:exe ";
}
if (flags.HasFlag(CompilerOptions.GeneratePdb)) if (flags.HasFlag(CompilerOptions.GeneratePdb))
pdbName = Path.ChangeExtension(outputFileName, ".pdb");
var emitResult = compilation.Emit(results.PathToAssembly, pdbName);
if (!emitResult.Success)
{ {
StringBuilder b = new StringBuilder("Compiler error:"); otherOptions += "-debug:full ";
foreach (var diag in emitResult.Diagnostics)
{
b.AppendLine(diag.ToString());
}
throw new Exception(b.ToString());
} }
else
{
otherOptions += "-debug- ";
}
if (flags.HasFlag(CompilerOptions.Force32Bit))
{
otherOptions += "-platform:x86 ";
}
else
{
otherOptions += "-platform:anycpu ";
}
if (preprocessorSymbols.Count > 0)
{
otherOptions += " \"-d:" + string.Join(";", preprocessorSymbols) + "\" ";
}
ProcessStartInfo info = new ProcessStartInfo(cscPath);
info.Arguments = $"{otherOptions}{string.Join(" ", references)} -out:\"{Path.GetFullPath(results.PathToAssembly)}\" {string.Join(" ", sourceFileNames.Select(fn => '"' + Path.GetFullPath(fn) + '"'))}";
info.RedirectStandardError = true;
info.RedirectStandardOutput = true;
info.UseShellExecute = false;
Console.WriteLine($"\"{info.FileName}\" {info.Arguments}");
Process process = Process.Start(info);
var outputTask = process.StandardOutput.ReadToEndAsync();
var errorTask = process.StandardError.ReadToEndAsync();
Task.WaitAll(outputTask, errorTask);
process.WaitForExit();
Console.WriteLine("output: " + outputTask.Result);
Console.WriteLine("errors: " + errorTask.Result);
Assert.AreEqual(0, process.ExitCode, "csc failed");
return results; return results;
} }
else if (flags.HasFlag(CompilerOptions.UseMcs)) else
{ {
CompilerResults results = new CompilerResults(new TempFileCollection()); CompilerResults results = new CompilerResults(new TempFileCollection());
results.PathToAssembly = outputFileName ?? Path.GetTempFileName(); results.PathToAssembly = outputFileName ?? Path.GetTempFileName();
@ -419,62 +514,19 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
Assert.AreEqual(0, process.ExitCode, "mcs failed"); Assert.AreEqual(0, process.ExitCode, "mcs failed");
return results; return results;
} }
else
{
var provider = new CSharpCodeProvider(new Dictionary<string, string> { { "CompilerVersion", "v4.0" } });
CompilerParameters options = new CompilerParameters();
options.GenerateExecutable = !flags.HasFlag(CompilerOptions.Library);
options.CompilerOptions = "/unsafe /o" + (flags.HasFlag(CompilerOptions.Optimize) ? "+" : "-");
string debugOption = " /debug";
if (flags.HasFlag(CompilerOptions.GeneratePdb))
{
debugOption += ":full";
options.IncludeDebugInformation = true;
}
options.CompilerOptions += (flags.HasFlag(CompilerOptions.UseDebug) ? debugOption : "");
options.CompilerOptions += (flags.HasFlag(CompilerOptions.Force32Bit) ? " /platform:anycpu32bitpreferred" : "");
if (preprocessorSymbols.Count > 0)
{
options.CompilerOptions += " /d:" + string.Join(";", preprocessorSymbols);
}
if (outputFileName != null)
{
options.OutputAssembly = outputFileName;
}
options.ReferencedAssemblies.Add("System.dll");
options.ReferencedAssemblies.Add("System.Core.dll");
options.ReferencedAssemblies.Add("System.Xml.dll");
options.ReferencedAssemblies.Add("Microsoft.CSharp.dll");
if (flags.HasFlag(CompilerOptions.ReferenceVisualBasic))
{
options.ReferencedAssemblies.Add("Microsoft.VisualBasic.dll");
}
CompilerResults results = provider.CompileAssemblyFromFile(options, sourceFileNames.ToArray());
if (results.Errors.Cast<CompilerError>().Any(e => !e.IsWarning))
{
StringBuilder b = new StringBuilder("Compiler error:");
foreach (var error in results.Errors)
{
b.AppendLine(error.ToString());
}
throw new Exception(b.ToString());
}
return results;
}
} }
internal static DecompilerSettings GetSettings(CompilerOptions cscOptions) internal static DecompilerSettings GetSettings(CompilerOptions cscOptions)
{ {
if (cscOptions.HasFlag(CompilerOptions.UseRoslyn)) if ((cscOptions & CompilerOptions.UseRoslynMask) != 0)
{ {
if (cscOptions.HasFlag(CompilerOptions.Preview)) var langVersion = (cscOptions & CompilerOptions.UseRoslynMask) switch
{ {
return new DecompilerSettings(CSharp.LanguageVersion.Latest); CompilerOptions.UseRoslyn1_3_2 => CSharp.LanguageVersion.CSharp6,
} CompilerOptions.UseRoslyn2_10_0 => CSharp.LanguageVersion.CSharp7_3,
else _ => cscOptions.HasFlag(CompilerOptions.Preview) ? CSharp.LanguageVersion.Latest : CSharp.LanguageVersion.CSharp8_0,
{ };
return new DecompilerSettings(CSharp.LanguageVersion.CSharp8_0); return new DecompilerSettings(langVersion);
}
} }
else else
{ {
@ -503,7 +555,7 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
} }
var compilation = CSharpCompilation.Create(Path.GetFileNameWithoutExtension(assemblyName), var compilation = CSharpCompilation.Create(Path.GetFileNameWithoutExtension(assemblyName),
syntaxTrees, defaultReferences.Value, syntaxTrees, roslynDefaultReferences.Value.Select(r => MetadataReference.CreateFromFile(r)),
new CSharpCompilationOptions( new CSharpCompilationOptions(
OutputKind.DynamicallyLinkedLibrary, OutputKind.DynamicallyLinkedLibrary,
platform: Platform.AnyCpu, platform: Platform.AnyCpu,
@ -536,7 +588,11 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
suffix += ".32"; suffix += ".32";
if ((cscOptions & CompilerOptions.UseDebug) != 0) if ((cscOptions & CompilerOptions.UseDebug) != 0)
suffix += ".dbg"; suffix += ".dbg";
if ((cscOptions & CompilerOptions.UseRoslyn) != 0) if ((cscOptions & CompilerOptions.UseRoslyn1_3_2) != 0)
suffix += ".roslyn1";
if ((cscOptions & CompilerOptions.UseRoslyn2_10_0) != 0)
suffix += ".roslyn2";
if ((cscOptions & CompilerOptions.UseRoslynLatest) != 0)
suffix += ".roslyn"; suffix += ".roslyn";
if ((cscOptions & CompilerOptions.UseMcs) != 0) if ((cscOptions & CompilerOptions.UseMcs) != 0)
suffix += ".mcs"; suffix += ".mcs";

2
ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj

@ -44,6 +44,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="DiffLib" Version="$(DiffLibVersion)" /> <PackageReference Include="DiffLib" Version="$(DiffLibVersion)" />
<PackageReference Include="Microsoft.Build.Locator" Version="1.2.2" /> <PackageReference Include="Microsoft.Build.Locator" Version="1.2.2" />
<PackageReference Include="NuGet.Protocol" Version="5.7.0" />
<PackageReference Include="System.Collections.Immutable" Version="$(SystemCollectionsImmutableVersion)" /> <PackageReference Include="System.Collections.Immutable" Version="$(SystemCollectionsImmutableVersion)" />
<PackageReference Include="System.Reflection.Metadata" Version="$(SystemReflectionMetadataVersion)" /> <PackageReference Include="System.Reflection.Metadata" Version="$(SystemReflectionMetadataVersion)" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="$(RoslynVersion)" /> <PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="$(RoslynVersion)" />
@ -98,6 +99,7 @@
<Compile Include="..\ILSpy\DebugInfo\DebugInfoUtils.cs" Link="DebugInfoUtils.cs" /> <Compile Include="..\ILSpy\DebugInfo\DebugInfoUtils.cs" Link="DebugInfoUtils.cs" />
<Compile Include="..\ILSpy\DebugInfo\PortableDebugInfoProvider.cs" Link="PortableDebugInfoProvider.cs" /> <Compile Include="..\ILSpy\DebugInfo\PortableDebugInfoProvider.cs" Link="PortableDebugInfoProvider.cs" />
<Compile Include="DisassemblerPrettyTestRunner.cs" /> <Compile Include="DisassemblerPrettyTestRunner.cs" />
<Compile Include="Helpers\RoslynToolset.cs" />
<Compile Include="Output\InsertParenthesesVisitorTests.cs" /> <Compile Include="Output\InsertParenthesesVisitorTests.cs" />
<Compile Include="ProjectDecompiler\TargetFrameworkTests.cs" /> <Compile Include="ProjectDecompiler\TargetFrameworkTests.cs" />
<Compile Include="TestAssemblyResolver.cs" /> <Compile Include="TestAssemblyResolver.cs" />

72
ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs

@ -59,30 +59,56 @@ namespace ICSharpCode.Decompiler.Tests
static readonly CompilerOptions[] roslynOnlyOptions = static readonly CompilerOptions[] roslynOnlyOptions =
{ {
CompilerOptions.UseRoslyn, CompilerOptions.UseRoslyn1_3_2,
CompilerOptions.Optimize | CompilerOptions.UseRoslyn CompilerOptions.Optimize | CompilerOptions.UseRoslyn1_3_2,
CompilerOptions.UseRoslyn2_10_0,
CompilerOptions.Optimize | CompilerOptions.UseRoslyn2_10_0,
CompilerOptions.UseRoslynLatest,
CompilerOptions.Optimize | CompilerOptions.UseRoslynLatest,
};
static readonly CompilerOptions[] roslyn2OrNewerOptions =
{
CompilerOptions.UseRoslyn2_10_0,
CompilerOptions.Optimize | CompilerOptions.UseRoslyn2_10_0,
CompilerOptions.UseRoslynLatest,
CompilerOptions.Optimize | CompilerOptions.UseRoslynLatest,
};
static readonly CompilerOptions[] roslynLatestOnlyOptions =
{
CompilerOptions.UseRoslynLatest,
CompilerOptions.Optimize | CompilerOptions.UseRoslynLatest,
}; };
static readonly CompilerOptions[] dotnetCoreOnlyOptions = static readonly CompilerOptions[] dotnetCoreOnlyOptions =
{ {
CompilerOptions.UseRoslyn | CompilerOptions.ReferenceCore, CompilerOptions.UseRoslynLatest | CompilerOptions.ReferenceCore,
CompilerOptions.Optimize | CompilerOptions.UseRoslyn | CompilerOptions.ReferenceCore CompilerOptions.Optimize | CompilerOptions.UseRoslynLatest | CompilerOptions.ReferenceCore,
}; };
static readonly CompilerOptions[] defaultOptions = static readonly CompilerOptions[] defaultOptions =
{ {
CompilerOptions.None, CompilerOptions.None,
CompilerOptions.Optimize, CompilerOptions.Optimize,
CompilerOptions.UseRoslyn, CompilerOptions.UseRoslyn1_3_2,
CompilerOptions.Optimize | CompilerOptions.UseRoslyn CompilerOptions.Optimize | CompilerOptions.UseRoslyn1_3_2,
CompilerOptions.UseRoslyn2_10_0,
CompilerOptions.Optimize | CompilerOptions.UseRoslyn2_10_0,
CompilerOptions.UseRoslynLatest,
CompilerOptions.Optimize | CompilerOptions.UseRoslynLatest,
}; };
static readonly CompilerOptions[] defaultOptionsWithMcs = static readonly CompilerOptions[] defaultOptionsWithMcs =
{ {
CompilerOptions.None, CompilerOptions.None,
CompilerOptions.Optimize, CompilerOptions.Optimize,
CompilerOptions.UseRoslyn, CompilerOptions.UseRoslyn1_3_2,
CompilerOptions.Optimize | CompilerOptions.UseRoslyn, CompilerOptions.Optimize | CompilerOptions.UseRoslyn1_3_2,
CompilerOptions.UseRoslyn2_10_0,
CompilerOptions.Optimize | CompilerOptions.UseRoslyn2_10_0,
CompilerOptions.UseRoslynLatest,
CompilerOptions.Optimize | CompilerOptions.UseRoslynLatest,
CompilerOptions.UseMcs, CompilerOptions.UseMcs,
CompilerOptions.Optimize | CompilerOptions.UseMcs CompilerOptions.Optimize | CompilerOptions.UseMcs
}; };
@ -145,7 +171,7 @@ namespace ICSharpCode.Decompiler.Tests
} }
[Test] [Test]
public void SwitchExpressions([ValueSource(nameof(roslynOnlyOptions))] CompilerOptions cscOptions) public void SwitchExpressions([ValueSource(nameof(roslynLatestOnlyOptions))] CompilerOptions cscOptions)
{ {
RunForLibrary(cscOptions: cscOptions); RunForLibrary(cscOptions: cscOptions);
} }
@ -217,7 +243,7 @@ namespace ICSharpCode.Decompiler.Tests
} }
[Test] [Test]
public void LocalFunctions([ValueSource(nameof(roslynOnlyOptions))] CompilerOptions cscOptions) public void LocalFunctions([ValueSource(nameof(roslyn2OrNewerOptions))] CompilerOptions cscOptions)
{ {
RunForLibrary(cscOptions: cscOptions | CompilerOptions.Preview); RunForLibrary(cscOptions: cscOptions | CompilerOptions.Preview);
} }
@ -272,7 +298,7 @@ namespace ICSharpCode.Decompiler.Tests
} }
[Test] [Test]
public void OutVariables([ValueSource(nameof(roslynOnlyOptions))] CompilerOptions cscOptions) public void OutVariables([ValueSource(nameof(roslyn2OrNewerOptions))] CompilerOptions cscOptions)
{ {
RunForLibrary(cscOptions: cscOptions); RunForLibrary(cscOptions: cscOptions);
} }
@ -322,7 +348,7 @@ namespace ICSharpCode.Decompiler.Tests
} }
[Test] [Test]
public void CS72_PrivateProtected([ValueSource(nameof(roslynOnlyOptions))] CompilerOptions cscOptions) public void CS72_PrivateProtected([ValueSource(nameof(roslyn2OrNewerOptions))] CompilerOptions cscOptions)
{ {
RunForLibrary(cscOptions: cscOptions); RunForLibrary(cscOptions: cscOptions);
} }
@ -334,7 +360,7 @@ namespace ICSharpCode.Decompiler.Tests
} }
[Test] [Test]
public void AsyncMain([ValueSource(nameof(roslynOnlyOptions))] CompilerOptions cscOptions) public void AsyncMain([ValueSource(nameof(roslyn2OrNewerOptions))] CompilerOptions cscOptions)
{ {
Run(cscOptions: cscOptions); Run(cscOptions: cscOptions);
} }
@ -355,25 +381,25 @@ namespace ICSharpCode.Decompiler.Tests
} }
[Test] [Test]
public void CustomTaskType([ValueSource(nameof(roslynOnlyOptions))] CompilerOptions cscOptions) public void CustomTaskType([ValueSource(nameof(roslyn2OrNewerOptions))] CompilerOptions cscOptions)
{ {
RunForLibrary(cscOptions: cscOptions); RunForLibrary(cscOptions: cscOptions);
} }
[Test] [Test]
public void NullableRefTypes([ValueSource(nameof(roslynOnlyOptions))] CompilerOptions cscOptions) public void NullableRefTypes([ValueSource(nameof(roslynLatestOnlyOptions))] CompilerOptions cscOptions)
{ {
RunForLibrary(cscOptions: cscOptions); RunForLibrary(cscOptions: cscOptions);
} }
[Test] [Test]
public void NativeInts([ValueSource(nameof(roslynOnlyOptions))] CompilerOptions cscOptions) public void NativeInts([ValueSource(nameof(roslynLatestOnlyOptions))] CompilerOptions cscOptions)
{ {
RunForLibrary(cscOptions: cscOptions | CompilerOptions.Preview); RunForLibrary(cscOptions: cscOptions | CompilerOptions.Preview);
} }
[Test] [Test]
public void FunctionPointers([ValueSource(nameof(roslynOnlyOptions))] CompilerOptions cscOptions) public void FunctionPointers([ValueSource(nameof(roslynLatestOnlyOptions))] CompilerOptions cscOptions)
{ {
RunForLibrary(cscOptions: cscOptions | CompilerOptions.Preview); RunForLibrary(cscOptions: cscOptions | CompilerOptions.Preview);
} }
@ -391,19 +417,19 @@ namespace ICSharpCode.Decompiler.Tests
} }
[Test] [Test]
public void CS73_StackAllocInitializers([ValueSource(nameof(roslynOnlyOptions))] CompilerOptions cscOptions) public void CS73_StackAllocInitializers([ValueSource(nameof(roslynLatestOnlyOptions))] CompilerOptions cscOptions)
{ {
RunForLibrary(cscOptions: cscOptions); RunForLibrary(cscOptions: cscOptions);
} }
[Test] [Test]
public void RefLocalsAndReturns([ValueSource(nameof(roslynOnlyOptions))] CompilerOptions cscOptions) public void RefLocalsAndReturns([ValueSource(nameof(roslyn2OrNewerOptions))] CompilerOptions cscOptions)
{ {
RunForLibrary(cscOptions: cscOptions); RunForLibrary(cscOptions: cscOptions);
} }
[Test] [Test]
public void ThrowExpressions([ValueSource(nameof(roslynOnlyOptions))] CompilerOptions cscOptions) public void ThrowExpressions([ValueSource(nameof(roslyn2OrNewerOptions))] CompilerOptions cscOptions)
{ {
RunForLibrary(cscOptions: cscOptions); RunForLibrary(cscOptions: cscOptions);
} }
@ -421,7 +447,7 @@ namespace ICSharpCode.Decompiler.Tests
} }
[Test] [Test]
public void TupleTests([ValueSource(nameof(roslynOnlyOptions))] CompilerOptions cscOptions) public void TupleTests([ValueSource(nameof(roslyn2OrNewerOptions))] CompilerOptions cscOptions)
{ {
RunForLibrary(cscOptions: cscOptions); RunForLibrary(cscOptions: cscOptions);
} }
@ -523,13 +549,13 @@ namespace ICSharpCode.Decompiler.Tests
} }
[Test] [Test]
public void Discards([ValueSource(nameof(roslynOnlyOptions))] CompilerOptions cscOptions) public void Discards([ValueSource(nameof(roslyn2OrNewerOptions))] CompilerOptions cscOptions)
{ {
RunForLibrary(cscOptions: cscOptions); RunForLibrary(cscOptions: cscOptions);
} }
[Test] [Test]
public void DeconstructionTests([ValueSource(nameof(roslynOnlyOptions))] CompilerOptions cscOptions) public void DeconstructionTests([ValueSource(nameof(roslyn2OrNewerOptions))] CompilerOptions cscOptions)
{ {
RunForLibrary(cscOptions: cscOptions); RunForLibrary(cscOptions: cscOptions);
} }

8
ICSharpCode.Decompiler.Tests/TestCases/Correctness/DeconstructionTests.cs

@ -63,7 +63,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
public MyInt My { public MyInt My {
get { get {
Console.WriteLine($"{id}.get_My()"); Console.WriteLine($"{id}.get_My()");
return default; return default(MyInt);
} }
set { set {
Console.WriteLine($"{id}.set_My({value})"); Console.WriteLine($"{id}.set_My({value})");
@ -73,7 +73,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
public MyInt? NMy { public MyInt? NMy {
get { get {
Console.WriteLine($"{id}.get_NMy()"); Console.WriteLine($"{id}.get_NMy()");
return default; return default(MyInt?);
} }
set { set {
Console.WriteLine($"{id}.set_NMy({value})"); Console.WriteLine($"{id}.set_NMy({value})");
@ -83,7 +83,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
public int IntProperty { public int IntProperty {
get { get {
Console.WriteLine($"{id}.get_IntProperty()"); Console.WriteLine($"{id}.get_IntProperty()");
return default; return default(int);
} }
set { set {
Console.WriteLine($"{id}.set_IntProperty({value})"); Console.WriteLine($"{id}.set_IntProperty({value})");
@ -93,7 +93,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
public uint UIntProperty { public uint UIntProperty {
get { get {
Console.WriteLine($"{id}.get_UIntProperty()"); Console.WriteLine($"{id}.get_UIntProperty()");
return default; return default(uint);
} }
set { set {
Console.WriteLine($"{id}.set_UIntProperty({value})"); Console.WriteLine($"{id}.set_UIntProperty({value})");

6
ICSharpCode.Decompiler.Tests/TestCases/Correctness/NullableTests.cs

@ -114,7 +114,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
Console.WriteLine("NRE before GetInt:"); Console.WriteLine("NRE before GetInt:");
try try
{ {
#if CS60 #if CS70
ref int i = ref c.intField; ref int i = ref c.intField;
i = GetValue<int>(); i = GetValue<int>();
#endif #endif
@ -141,7 +141,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
Console.WriteLine("NRE before GetInt (with struct):"); Console.WriteLine("NRE before GetInt (with struct):");
try try
{ {
#if CS60 #if CS70
ref SomeStruct s = ref c.structField; ref SomeStruct s = ref c.structField;
s.IntField = GetValue<int>(); s.IntField = GetValue<int>();
#endif #endif
@ -178,7 +178,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
Console.WriteLine("GetArray with ref:"); Console.WriteLine("GetArray with ref:");
try try
{ {
#if CS60 #if CS70
ref int elem = ref GetArray<int>()[GetIndex()]; ref int elem = ref GetArray<int>()[GetIndex()];
elem = GetValue<int>(); elem = GetValue<int>();
#endif #endif

10
ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue1325.cs

@ -24,11 +24,11 @@ namespace Issue1325
} }
public static void TestCode(Test t, int i) public static void TestCode(Test t, int i)
{ {
string str = ""; string text = "";
str += File.ReadAllText("Test.txt"); text += File.ReadAllText("Test.txt");
str += "asdf"; text += "asdf";
t.set_Parameterized(i, str); t.set_Parameterized(i, text);
t.Unparameterized = str + "asdf"; t.Unparameterized = text + "asdf";
} }
} }

2
ICSharpCode.Decompiler.Tests/TestCases/Pretty/AutoProperties.cs

@ -29,7 +29,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
} }
[Obsolete("Property")] [Obsolete("Property")]
#if CS70
[field: Obsolete("Field")] [field: Obsolete("Field")]
#endif
public int PropertyWithAttributeOnBackingField { public int PropertyWithAttributeOnBackingField {
get; get;
set; set;

6
ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.cs

@ -4775,10 +4775,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void Issue1552StmtUseLater(CustomStruct a, CustomStruct b) public void Issue1552StmtUseLater(CustomStruct a, CustomStruct b)
{ {
CustomStruct lhs = a + b; CustomStruct customStruct = a + b;
++lhs; ++customStruct;
Console.WriteLine(); Console.WriteLine();
Console.WriteLine(lhs * b); Console.WriteLine(customStruct * b);
} }
public void Issue1552Decimal(decimal a) public void Issue1552Decimal(decimal a)

32
ICSharpCode.Decompiler.Tests/TestCases/Pretty/DeconstructionTests.cs

@ -195,22 +195,22 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void LocalVariable_NoConversion_Custom() public void LocalVariable_NoConversion_Custom()
{ {
var (myInt3, x) = GetSource<MyInt?, MyInt>(); var (myInt3, myInt4) = GetSource<MyInt?, MyInt>();
Console.WriteLine(myInt3); Console.WriteLine(myInt3);
Console.WriteLine(x); Console.WriteLine(myInt4);
} }
public void LocalVariable_NoConversion_Tuple() public void LocalVariable_NoConversion_Tuple()
{ {
var (myInt, x) = GetTuple<MyInt?, MyInt>(); var (myInt, myInt2) = GetTuple<MyInt?, MyInt>();
Console.WriteLine(myInt); Console.WriteLine(myInt);
Console.WriteLine(x); Console.WriteLine(myInt2);
} }
public void LocalVariable_NoConversion_Custom_DiscardFirst() public void LocalVariable_NoConversion_Custom_DiscardFirst()
{ {
var (_, x, value) = GetSource<MyInt?, MyInt, int>(); var (_, myInt3, value) = GetSource<MyInt?, MyInt, int>();
Console.WriteLine(x); Console.WriteLine(myInt3);
Console.WriteLine(value); Console.WriteLine(value);
} }
@ -224,16 +224,16 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void LocalVariable_NoConversion_Custom_DiscardLast() public void LocalVariable_NoConversion_Custom_DiscardLast()
{ {
var (myInt3, x, _) = GetSource<MyInt?, MyInt, int>(); var (myInt3, myInt4, _) = GetSource<MyInt?, MyInt, int>();
Console.WriteLine(myInt3); Console.WriteLine(myInt3);
Console.WriteLine(x); Console.WriteLine(myInt4);
} }
public void LocalVariable_NoConversion_Tuple_DiscardLast() public void LocalVariable_NoConversion_Tuple_DiscardLast()
{ {
var (myInt, x, _) = GetTuple<MyInt?, MyInt, int>(); var (myInt, myInt2, _) = GetTuple<MyInt?, MyInt, int>();
Console.WriteLine(myInt); Console.WriteLine(myInt);
Console.WriteLine(x); Console.WriteLine(myInt2);
} }
public void LocalVariable_NoConversion_Custom_DiscardSecond() public void LocalVariable_NoConversion_Custom_DiscardSecond()
@ -321,11 +321,11 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void LocalVariable_NoConversion_ComplexValue_Custom() public void LocalVariable_NoConversion_ComplexValue_Custom()
{ {
var (myInt3, x) = new DeconstructionSource<MyInt?, MyInt> { var (myInt3, myInt4) = new DeconstructionSource<MyInt?, MyInt> {
Dummy = 3 Dummy = 3
}; };
Console.WriteLine(myInt3); Console.WriteLine(myInt3);
Console.WriteLine(x); Console.WriteLine(myInt4);
} }
public void Property_NoConversion_Custom() public void Property_NoConversion_Custom()
@ -581,17 +581,17 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void DeconstructDictionaryForEach(Dictionary<string, int> dictionary) public void DeconstructDictionaryForEach(Dictionary<string, int> dictionary)
{ {
foreach (var (str, num2) in dictionary) foreach (var (text2, num2) in dictionary)
{ {
Console.WriteLine(str + ": " + num2); Console.WriteLine(text2 + ": " + num2);
} }
} }
public void DeconstructTupleListForEach(List<(string, int)> tuples) public void DeconstructTupleListForEach(List<(string, int)> tuples)
{ {
foreach (var (str, num) in tuples) foreach (var (text, num) in tuples)
{ {
Console.WriteLine(str + ": " + num); Console.WriteLine(text + ": " + num);
} }
} }
} }

2
ICSharpCode.Decompiler.Tests/TestCases/Pretty/DelegateConstruction.cs

@ -444,7 +444,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
} }
#endif #endif
#if ROSLYN #if CS70
public static Func<string> Issue1773d((int Integer, string String) data) public static Func<string> Issue1773d((int Integer, string String) data)
{ {
(int Integer, string RenamedString) valueTuple = data; (int Integer, string RenamedString) valueTuple = data;

2
ICSharpCode.Decompiler.Tests/TestCases/Pretty/InitializerTests.cs

@ -431,7 +431,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty.InitializerTests
} }
}; };
#if ROSLYN #if CS73
public static ReadOnlySpan<byte> StaticData1 => new byte[1] { public static ReadOnlySpan<byte> StaticData1 => new byte[1] {
0 0
}; };

2
ICSharpCode.Decompiler.Tests/TestCases/Pretty/PropertiesAndEvents.cs

@ -194,6 +194,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
#if ROSLYN #if ROSLYN
// Legacy csc has a bug where EventHandler<dynamic> is only used for the backing field // Legacy csc has a bug where EventHandler<dynamic> is only used for the backing field
public event EventHandler<dynamic> DynamicAutoEvent; public event EventHandler<dynamic> DynamicAutoEvent;
#endif
#if CS73
public event EventHandler<(int A, string B)> AutoEventWithTuple; public event EventHandler<(int A, string B)> AutoEventWithTuple;
#endif #endif
#if CS80 #if CS80

4
ICSharpCode.Decompiler.Tests/TestCases/Pretty/VariableNaming.cs

@ -20,7 +20,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
private void Test(string text, C c) private void Test(string text, C c)
{ {
#if ROSLYN #if CS70
_ = c.Name; _ = c.Name;
#else #else
string name = c.Name; string name = c.Name;
@ -29,7 +29,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
private void Test2(string text, C c) private void Test2(string text, C c)
{ {
#if ROSLYN #if CS70
_ = c.Text; _ = c.Text;
#else #else
string text2 = c.Text; string text2 = c.Text;

4
ICSharpCode.Decompiler.Tests/TestCases/Pretty/VariableNamingWithoutSymbols.cs

@ -10,7 +10,7 @@
private void Test(string text, C c) private void Test(string text, C c)
{ {
#if ROSLYN #if CS70
_ = c.Name; _ = c.Name;
#else #else
string name = c.Name; string name = c.Name;
@ -19,7 +19,7 @@
private void Test2(string text, C c) private void Test2(string text, C c)
{ {
#if ROSLYN #if CS70
_ = c.Text; _ = c.Text;
#else #else
string text2 = c.Text; string text2 = c.Text;

2
ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoArrayInitializers.Expected.cs

@ -9,7 +9,7 @@ internal sealed class _003CPrivateImplementationDetails_003E
private struct __StaticArrayInitTypeSize_003D12 private struct __StaticArrayInitTypeSize_003D12
{ {
} }
internal static readonly __StaticArrayInitTypeSize_003D12 E429CCA3F703A39CC5954A6572FEC9086135B34E/* Not supported: data(01 00 00 00 02 00 00 00 03 00 00 00) */; internal static readonly __StaticArrayInitTypeSize_003D12 _4636993D3E1DA4E9D6B8F87B79E8F7C6D018580D52661950EABC3845C5897A4D/* Not supported: data(01 00 00 00 02 00 00 00 03 00 00 00) */;
} }
namespace ICSharpCode.Decompiler.Tests.TestCases.Ugly namespace ICSharpCode.Decompiler.Tests.TestCases.Ugly

6
ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoArrayInitializers.opt.roslyn.il

@ -48,7 +48,7 @@
IL_0000: ldc.i4.3 IL_0000: ldc.i4.3
IL_0001: newarr [mscorlib]System.Int32 IL_0001: newarr [mscorlib]System.Int32
IL_0006: dup IL_0006: dup
IL_0007: ldtoken field valuetype '<PrivateImplementationDetails>'/'__StaticArrayInitTypeSize=12' '<PrivateImplementationDetails>'::E429CCA3F703A39CC5954A6572FEC9086135B34E IL_0007: ldtoken field valuetype '<PrivateImplementationDetails>'/'__StaticArrayInitTypeSize=12' '<PrivateImplementationDetails>'::'4636993D3E1DA4E9D6B8F87B79E8F7C6D018580D52661950EABC3845C5897A4D'
IL_000c: call void [mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(class [mscorlib]System.Array, IL_000c: call void [mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(class [mscorlib]System.Array,
valuetype [mscorlib]System.RuntimeFieldHandle) valuetype [mscorlib]System.RuntimeFieldHandle)
IL_0011: ret IL_0011: ret
@ -96,12 +96,12 @@
.size 12 .size 12
} // end of class '__StaticArrayInitTypeSize=12' } // end of class '__StaticArrayInitTypeSize=12'
.field static assembly initonly valuetype '<PrivateImplementationDetails>'/'__StaticArrayInitTypeSize=12' E429CCA3F703A39CC5954A6572FEC9086135B34E at I_00002698 .field static assembly initonly valuetype '<PrivateImplementationDetails>'/'__StaticArrayInitTypeSize=12' '4636993D3E1DA4E9D6B8F87B79E8F7C6D018580D52661950EABC3845C5897A4D' at I_00002690
} // end of class '<PrivateImplementationDetails>' } // end of class '<PrivateImplementationDetails>'
// ============================================================= // =============================================================
.data cil I_00002698 = bytearray ( .data cil I_00002690 = bytearray (
01 00 00 00 02 00 00 00 03 00 00 00) 01 00 00 00 02 00 00 00 03 00 00 00)
// *********** DISASSEMBLY COMPLETE *********************** // *********** DISASSEMBLY COMPLETE ***********************

6
ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoArrayInitializers.roslyn.il

@ -50,7 +50,7 @@
IL_0001: ldc.i4.3 IL_0001: ldc.i4.3
IL_0002: newarr [mscorlib]System.Int32 IL_0002: newarr [mscorlib]System.Int32
IL_0007: dup IL_0007: dup
IL_0008: ldtoken field valuetype '<PrivateImplementationDetails>'/'__StaticArrayInitTypeSize=12' '<PrivateImplementationDetails>'::E429CCA3F703A39CC5954A6572FEC9086135B34E IL_0008: ldtoken field valuetype '<PrivateImplementationDetails>'/'__StaticArrayInitTypeSize=12' '<PrivateImplementationDetails>'::'4636993D3E1DA4E9D6B8F87B79E8F7C6D018580D52661950EABC3845C5897A4D'
IL_000d: call void [mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(class [mscorlib]System.Array, IL_000d: call void [mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(class [mscorlib]System.Array,
valuetype [mscorlib]System.RuntimeFieldHandle) valuetype [mscorlib]System.RuntimeFieldHandle)
IL_0012: stloc.0 IL_0012: stloc.0
@ -109,12 +109,12 @@
.size 12 .size 12
} // end of class '__StaticArrayInitTypeSize=12' } // end of class '__StaticArrayInitTypeSize=12'
.field static assembly initonly valuetype '<PrivateImplementationDetails>'/'__StaticArrayInitTypeSize=12' E429CCA3F703A39CC5954A6572FEC9086135B34E at I_000026C8 .field static assembly initonly valuetype '<PrivateImplementationDetails>'/'__StaticArrayInitTypeSize=12' '4636993D3E1DA4E9D6B8F87B79E8F7C6D018580D52661950EABC3845C5897A4D' at I_000026C0
} // end of class '<PrivateImplementationDetails>' } // end of class '<PrivateImplementationDetails>'
// ============================================================= // =============================================================
.data cil I_000026C8 = bytearray ( .data cil I_000026C0 = bytearray (
01 00 00 00 02 00 00 00 03 00 00 00) 01 00 00 00 02 00 00 00 03 00 00 00)
// *********** DISASSEMBLY COMPLETE *********************** // *********** DISASSEMBLY COMPLETE ***********************

8
ICSharpCode.Decompiler.Tests/UglyTestRunner.cs

@ -59,16 +59,16 @@ namespace ICSharpCode.Decompiler.Tests
static readonly CompilerOptions[] roslynOnlyOptions = static readonly CompilerOptions[] roslynOnlyOptions =
{ {
CompilerOptions.UseRoslyn, CompilerOptions.UseRoslynLatest,
CompilerOptions.Optimize | CompilerOptions.UseRoslyn CompilerOptions.Optimize | CompilerOptions.UseRoslynLatest,
}; };
static readonly CompilerOptions[] defaultOptions = static readonly CompilerOptions[] defaultOptions =
{ {
CompilerOptions.None, CompilerOptions.None,
CompilerOptions.Optimize, CompilerOptions.Optimize,
CompilerOptions.UseRoslyn, CompilerOptions.UseRoslynLatest,
CompilerOptions.Optimize | CompilerOptions.UseRoslyn CompilerOptions.Optimize | CompilerOptions.UseRoslynLatest,
}; };
[Test] [Test]

16
ICSharpCode.Decompiler.Tests/VBPrettyTestRunner.cs

@ -54,14 +54,22 @@ namespace ICSharpCode.Decompiler.Tests
{ {
CompilerOptions.None, CompilerOptions.None,
CompilerOptions.Optimize, CompilerOptions.Optimize,
CompilerOptions.UseRoslyn, CompilerOptions.UseRoslyn1_3_2,
CompilerOptions.Optimize | CompilerOptions.UseRoslyn, CompilerOptions.Optimize | CompilerOptions.UseRoslyn1_3_2,
CompilerOptions.UseRoslyn2_10_0,
CompilerOptions.Optimize | CompilerOptions.UseRoslyn2_10_0,
CompilerOptions.UseRoslynLatest,
CompilerOptions.Optimize | CompilerOptions.UseRoslynLatest,
}; };
static readonly CompilerOptions[] roslynOnlyOptions = static readonly CompilerOptions[] roslynOnlyOptions =
{ {
CompilerOptions.UseRoslyn, CompilerOptions.UseRoslyn1_3_2,
CompilerOptions.Optimize | CompilerOptions.UseRoslyn, CompilerOptions.Optimize | CompilerOptions.UseRoslyn1_3_2,
CompilerOptions.UseRoslyn2_10_0,
CompilerOptions.Optimize | CompilerOptions.UseRoslyn2_10_0,
CompilerOptions.UseRoslynLatest,
CompilerOptions.Optimize | CompilerOptions.UseRoslynLatest,
}; };
[Test, Ignore("Implement VB async/await")] [Test, Ignore("Implement VB async/await")]

17
ICSharpCode.Decompiler/IL/Transforms/AssignVariableNames.cs

@ -464,6 +464,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms
if (call is NewObj) if (call is NewObj)
break; break;
IMethod m = call.Method; IMethod m = call.Method;
if (ExcludeMethodFromCandidates(m))
break;
if (m.Name.StartsWith("get_", StringComparison.OrdinalIgnoreCase) && m.Parameters.Count == 0) if (m.Name.StartsWith("get_", StringComparison.OrdinalIgnoreCase) && m.Parameters.Count == 0)
{ {
// use name from properties, but not from indexers // use name from properties, but not from indexers
@ -494,6 +496,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return CleanUpVariableName(field.Name); return CleanUpVariableName(field.Name);
case CallInstruction call: case CallInstruction call:
IMethod m = call.Method; IMethod m = call.Method;
if (ExcludeMethodFromCandidates(m))
return null;
if (m.Parameters.Count == 1 && i == call.Arguments.Count - 1) if (m.Parameters.Count == 1 && i == call.Arguments.Count - 1)
{ {
// argument might be value of a setter // argument might be value of a setter
@ -510,12 +514,23 @@ namespace ICSharpCode.Decompiler.IL.Transforms
if (p != null && !string.IsNullOrEmpty(p.Name)) if (p != null && !string.IsNullOrEmpty(p.Name))
return CleanUpVariableName(p.Name); return CleanUpVariableName(p.Name);
break; break;
case Leave ret: case Leave _:
return "result"; return "result";
} }
return null; return null;
} }
static bool ExcludeMethodFromCandidates(IMethod m)
{
if (m.SymbolKind == SymbolKind.Operator)
return true;
if (m.Name == "ToString")
return true;
if (m.Name == "Concat" && m.DeclaringType.IsKnownType(KnownTypeCode.String))
return true;
return false;
}
static string GetNameByType(IType type) static string GetNameByType(IType type)
{ {
type = NullableType.GetUnderlyingType(type); type = NullableType.GetUnderlyingType(type);

Loading…
Cancel
Save