Browse Source

#2128: Reformat the whole code base.

pull/2134/head
dotnet format 5 years ago committed by Siegfried Pammer
parent
commit
0d9f871a4f
  1. 34
      ICSharpCode.Decompiler.PdbProvider.Cecil/MonoCecilDebugInfoProvider.cs
  2. 50
      ICSharpCode.Decompiler.Tests/CorrectnessTestRunner.cs
  3. 2
      ICSharpCode.Decompiler.Tests/DataFlowTest.cs
  4. 8
      ICSharpCode.Decompiler.Tests/DisassemblerPrettyTestRunner.cs
  5. 60
      ICSharpCode.Decompiler.Tests/Helpers/CodeAssert.cs
  6. 14
      ICSharpCode.Decompiler.Tests/Helpers/RemoveCompilerAttribute.cs
  7. 122
      ICSharpCode.Decompiler.Tests/Helpers/SdkUtility.cs
  8. 39
      ICSharpCode.Decompiler.Tests/Helpers/Tester.VB.cs
  9. 191
      ICSharpCode.Decompiler.Tests/Helpers/Tester.cs
  10. 11
      ICSharpCode.Decompiler.Tests/ILPrettyTestRunner.cs
  11. 5
      ICSharpCode.Decompiler.Tests/Output/CSharpAmbienceTests.cs
  12. 18
      ICSharpCode.Decompiler.Tests/PdbGenerationTestRunner.cs
  13. 20
      ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs
  14. 2
      ICSharpCode.Decompiler.Tests/ProjectDecompiler/TargetFrameworkTests.cs
  15. 86
      ICSharpCode.Decompiler.Tests/RoundtripAssembly.cs
  16. 8
      ICSharpCode.Decompiler.Tests/Semantics/ConversionTests.cs
  17. 8
      ICSharpCode.Decompiler.Tests/Semantics/ExplicitConversionTest.cs
  18. 18
      ICSharpCode.Decompiler.Tests/Semantics/OverloadResolutionTests.cs
  19. 4
      ICSharpCode.Decompiler.Tests/TestAssemblyResolver.cs
  20. 129
      ICSharpCode.Decompiler.Tests/TestCases/Correctness/Async.cs
  21. 60
      ICSharpCode.Decompiler.Tests/TestCases/Correctness/Capturing.cs
  22. 16
      ICSharpCode.Decompiler.Tests/TestCases/Correctness/Comparisons.cs
  23. 22
      ICSharpCode.Decompiler.Tests/TestCases/Correctness/CompoundAssignment.cs
  24. 56
      ICSharpCode.Decompiler.Tests/TestCases/Correctness/ControlFlow.cs
  25. 77
      ICSharpCode.Decompiler.Tests/TestCases/Correctness/Conversions.cs
  26. 2
      ICSharpCode.Decompiler.Tests/TestCases/Correctness/DecimalFields.cs
  27. 24
      ICSharpCode.Decompiler.Tests/TestCases/Correctness/DeconstructionTests.cs
  28. 3
      ICSharpCode.Decompiler.Tests/TestCases/Correctness/FloatingPointArithmetic.cs
  29. 6
      ICSharpCode.Decompiler.Tests/TestCases/Correctness/Generics.cs
  30. 60
      ICSharpCode.Decompiler.Tests/TestCases/Correctness/InitializerTests.cs
  31. 15
      ICSharpCode.Decompiler.Tests/TestCases/Correctness/LINQRaytracer.cs
  32. 103
      ICSharpCode.Decompiler.Tests/TestCases/Correctness/Loops.cs
  33. 26
      ICSharpCode.Decompiler.Tests/TestCases/Correctness/MemberLookup.cs
  34. 202
      ICSharpCode.Decompiler.Tests/TestCases/Correctness/MiniJSON.cs
  35. 2
      ICSharpCode.Decompiler.Tests/TestCases/Correctness/NullPropagation.cs
  36. 49
      ICSharpCode.Decompiler.Tests/TestCases/Correctness/NullableTests.cs
  37. 3
      ICSharpCode.Decompiler.Tests/TestCases/Correctness/OverloadResolution.cs
  38. 8
      ICSharpCode.Decompiler.Tests/TestCases/Correctness/PropertiesAndEvents.cs
  39. 69
      ICSharpCode.Decompiler.Tests/TestCases/Correctness/Switch.cs
  40. 4
      ICSharpCode.Decompiler.Tests/TestCases/Correctness/TrickyTypes.cs
  41. 10
      ICSharpCode.Decompiler.Tests/TestCases/Correctness/UndocumentedExpressions.cs
  42. 8
      ICSharpCode.Decompiler.Tests/TestCases/Correctness/UnsafeCode.cs
  43. 70
      ICSharpCode.Decompiler.Tests/TestCases/Correctness/Using.cs
  44. 45
      ICSharpCode.Decompiler.Tests/TestCases/Correctness/ValueTypeCall.cs
  45. 232
      ICSharpCode.Decompiler.Tests/TestCases/Correctness/YieldReturn.cs
  46. 55
      ICSharpCode.Decompiler.Tests/TestCases/ILPretty/CS1xSwitch_Debug.cs
  47. 55
      ICSharpCode.Decompiler.Tests/TestCases/ILPretty/CS1xSwitch_Release.cs
  48. 21
      ICSharpCode.Decompiler.Tests/TestCases/ILPretty/FSharpLoops_Debug.cs
  49. 21
      ICSharpCode.Decompiler.Tests/TestCases/ILPretty/FSharpLoops_Release.cs
  50. 18
      ICSharpCode.Decompiler.Tests/TestCases/ILPretty/FSharpUsing_Debug.cs
  51. 18
      ICSharpCode.Decompiler.Tests/TestCases/ILPretty/FSharpUsing_Release.cs
  52. 3
      ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue1047.cs
  53. 3
      ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue1454.cs
  54. 2
      ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue1681.cs
  55. 13
      ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue1918.cs
  56. 3
      ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue646.cs
  57. 25
      ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue684.cs
  58. 3
      ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue959.cs
  59. 21
      ICSharpCode.Decompiler.Tests/TestCases/ILPretty/SequenceOfNestedIfs.cs
  60. 25
      ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Unsafe.cs
  61. 43
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/Async.cs
  62. 12
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/AsyncForeach.cs
  63. 16
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/AsyncStreams.cs
  64. 12
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/AsyncUsing.cs
  65. 18
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/CheckedUnchecked.cs
  66. 64
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.cs
  67. 5
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/CustomAttributeConflicts.cs
  68. 41
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/CustomShortCircuitOperators.cs
  69. 37
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/CustomTaskType.cs
  70. 6
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/DeconstructionTests.cs
  71. 67
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/DelegateConstruction.cs
  72. 32
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/DynamicTests.cs
  73. 232
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/ExceptionHandling.cs
  74. 15
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/ExpressionTrees.cs
  75. 10
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/FixProxyCalls.cs
  76. 3
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/Generics.cs
  77. 15
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/InitializerTests.cs
  78. 21
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.cs
  79. 3
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/Issue1080.cs
  80. 179
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/LiftedOperators.cs
  81. 47
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/LocalFunctions.cs
  82. 6
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/Lock.cs
  83. 299
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/Loops.cs
  84. 9
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/NativeInts.cs
  85. 18
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/NullPropagation.cs
  86. 6
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/OutVariables.cs
  87. 2
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/PInvoke.cs
  88. 3
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/QualifierTests.cs
  89. 6
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/QueryExpressions.cs
  90. 304
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/ReduceNesting.cs
  91. 21
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/RefLocalsAndReturns.cs
  92. 156
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/ShortCircuit.cs
  93. 368
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.cs
  94. 21
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/SwitchExpressions.cs
  95. 3
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/ThrowExpressions.cs
  96. 12
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/TupleTests.cs
  97. 3
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.cs
  98. 2
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeMemberTests.cs
  99. 63
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.cs
  100. 36
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/Using.cs
  101. Some files were not shown because too many files have changed in this diff Show More

34
ICSharpCode.Decompiler.PdbProvider.Cecil/MonoCecilDebugInfoProvider.cs

@ -28,6 +28,7 @@ using ICSharpCode.Decompiler.Util;
using Mono.Cecil; using Mono.Cecil;
using Mono.Cecil.Pdb; using Mono.Cecil.Pdb;
using SRM = System.Reflection.Metadata; using SRM = System.Reflection.Metadata;
namespace ICSharpCode.Decompiler.PdbProvider namespace ICSharpCode.Decompiler.PdbProvider
@ -38,11 +39,13 @@ namespace ICSharpCode.Decompiler.PdbProvider
public unsafe MonoCecilDebugInfoProvider(PEFile module, string pdbFileName, string description = null) public unsafe MonoCecilDebugInfoProvider(PEFile module, string pdbFileName, string description = null)
{ {
if (module == null) { if (module == null)
{
throw new ArgumentNullException(nameof(module)); throw new ArgumentNullException(nameof(module));
} }
if (!module.Reader.IsEntireImageAvailable) { if (!module.Reader.IsEntireImageAvailable)
{
throw new ArgumentException("This provider needs access to the full image!"); throw new ArgumentException("This provider needs access to the full image!");
} }
@ -51,18 +54,22 @@ namespace ICSharpCode.Decompiler.PdbProvider
var image = module.Reader.GetEntireImage(); var image = module.Reader.GetEntireImage();
this.debugInfo = new Dictionary<SRM.MethodDefinitionHandle, (IList<SequencePoint> SequencePoints, IList<Variable> Variables)>(); this.debugInfo = new Dictionary<SRM.MethodDefinitionHandle, (IList<SequencePoint> SequencePoints, IList<Variable> Variables)>();
using (UnmanagedMemoryStream stream = new UnmanagedMemoryStream(image.Pointer, image.Length)) using (UnmanagedMemoryStream stream = new UnmanagedMemoryStream(image.Pointer, image.Length))
using (var moduleDef = ModuleDefinition.ReadModule(stream)) { using (var moduleDef = ModuleDefinition.ReadModule(stream))
{
moduleDef.ReadSymbols(new PdbReaderProvider().GetSymbolReader(moduleDef, pdbFileName)); moduleDef.ReadSymbols(new PdbReaderProvider().GetSymbolReader(moduleDef, pdbFileName));
foreach (var method in module.Metadata.MethodDefinitions) { foreach (var method in module.Metadata.MethodDefinitions)
{
var cecilMethod = moduleDef.LookupToken(MetadataTokens.GetToken(method)) as MethodDefinition; var cecilMethod = moduleDef.LookupToken(MetadataTokens.GetToken(method)) as MethodDefinition;
var debugInfo = cecilMethod?.DebugInformation; var debugInfo = cecilMethod?.DebugInformation;
if (debugInfo == null) if (debugInfo == null)
continue; continue;
IList<SequencePoint> sequencePoints = EmptyList<SequencePoint>.Instance; IList<SequencePoint> sequencePoints = EmptyList<SequencePoint>.Instance;
if (debugInfo.HasSequencePoints) { if (debugInfo.HasSequencePoints)
{
sequencePoints = new List<SequencePoint>(debugInfo.SequencePoints.Count); sequencePoints = new List<SequencePoint>(debugInfo.SequencePoints.Count);
foreach (var point in debugInfo.SequencePoints) { foreach (var point in debugInfo.SequencePoints)
{
sequencePoints.Add(new SequencePoint { sequencePoints.Add(new SequencePoint {
Offset = point.Offset, Offset = point.Offset,
StartLine = point.StartLine, StartLine = point.StartLine,
@ -74,10 +81,12 @@ namespace ICSharpCode.Decompiler.PdbProvider
} }
} }
var variables = new List<Variable>(); var variables = new List<Variable>();
foreach (var scope in debugInfo.GetScopes()) { foreach (var scope in debugInfo.GetScopes())
{
if (!scope.HasVariables) if (!scope.HasVariables)
continue; continue;
foreach (var v in scope.Variables) { foreach (var v in scope.Variables)
{
variables.Add(new Variable(v.Index, v.Name)); variables.Add(new Variable(v.Index, v.Name));
} }
} }
@ -90,7 +99,8 @@ namespace ICSharpCode.Decompiler.PdbProvider
public IList<SequencePoint> GetSequencePoints(SRM.MethodDefinitionHandle handle) public IList<SequencePoint> GetSequencePoints(SRM.MethodDefinitionHandle handle)
{ {
if (!debugInfo.TryGetValue(handle, out var info)) { if (!debugInfo.TryGetValue(handle, out var info))
{
return EmptyList<SequencePoint>.Instance; return EmptyList<SequencePoint>.Instance;
} }
@ -99,7 +109,8 @@ namespace ICSharpCode.Decompiler.PdbProvider
public IList<Variable> GetVariables(SRM.MethodDefinitionHandle handle) public IList<Variable> GetVariables(SRM.MethodDefinitionHandle handle)
{ {
if (!debugInfo.TryGetValue(handle, out var info)) { if (!debugInfo.TryGetValue(handle, out var info))
{
return EmptyList<Variable>.Instance; return EmptyList<Variable>.Instance;
} }
@ -109,7 +120,8 @@ namespace ICSharpCode.Decompiler.PdbProvider
public bool TryGetName(SRM.MethodDefinitionHandle handle, int index, out string name) public bool TryGetName(SRM.MethodDefinitionHandle handle, int index, out string name)
{ {
name = null; name = null;
if (!debugInfo.TryGetValue(handle, out var info)) { if (!debugInfo.TryGetValue(handle, out var info))
{
return false; return false;
} }

50
ICSharpCode.Decompiler.Tests/CorrectnessTestRunner.cs

@ -21,7 +21,9 @@ using System.CodeDom.Compiler;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using ICSharpCode.Decompiler.Tests.Helpers; using ICSharpCode.Decompiler.Tests.Helpers;
using NUnit.Framework; using NUnit.Framework;
namespace ICSharpCode.Decompiler.Tests namespace ICSharpCode.Decompiler.Tests
@ -38,7 +40,8 @@ namespace ICSharpCode.Decompiler.Tests
.Where(m => m.GetCustomAttributes(typeof(TestAttribute), false).Any()) .Where(m => m.GetCustomAttributes(typeof(TestAttribute), false).Any())
.Select(m => m.Name) .Select(m => m.Name)
.ToArray(); .ToArray();
foreach (var file in new DirectoryInfo(TestCasePath).EnumerateFiles()) { foreach (var file in new DirectoryInfo(TestCasePath).EnumerateFiles())
{
if (file.Extension == ".txt" || file.Extension == ".exe" || file.Extension == ".config") if (file.Extension == ".txt" || file.Extension == ".exe" || file.Extension == ".config")
continue; continue;
var testName = Path.GetFileNameWithoutExtension(file.Name); var testName = Path.GetFileNameWithoutExtension(file.Name);
@ -213,7 +216,8 @@ namespace ICSharpCode.Decompiler.Tests
{ {
CompilerOptions compiler = CompilerOptions.UseDebug; CompilerOptions compiler = CompilerOptions.UseDebug;
AssemblerOptions asm = AssemblerOptions.None; AssemblerOptions asm = AssemblerOptions.None;
if (force32Bit) { if (force32Bit)
{
compiler |= CompilerOptions.Force32Bit; compiler |= CompilerOptions.Force32Bit;
asm |= AssemblerOptions.Force32Bit; asm |= AssemblerOptions.Force32Bit;
} }
@ -237,7 +241,8 @@ namespace ICSharpCode.Decompiler.Tests
{ {
CompilerOptions compiler = CompilerOptions.UseRoslyn | CompilerOptions.UseDebug; CompilerOptions compiler = CompilerOptions.UseRoslyn | CompilerOptions.UseDebug;
AssemblerOptions asm = AssemblerOptions.None; AssemblerOptions asm = AssemblerOptions.None;
if (force32Bit) { if (force32Bit)
{
compiler |= CompilerOptions.Force32Bit; compiler |= CompilerOptions.Force32Bit;
asm |= AssemblerOptions.Force32Bit; asm |= AssemblerOptions.Force32Bit;
} }
@ -247,7 +252,8 @@ namespace ICSharpCode.Decompiler.Tests
[Test] [Test]
public void UnsafeCode([ValueSource("defaultOptions")] CompilerOptions options) public void UnsafeCode([ValueSource("defaultOptions")] CompilerOptions options)
{ {
if (options.HasFlag(CompilerOptions.UseMcs)) { if (options.HasFlag(CompilerOptions.UseMcs))
{
Assert.Ignore("Decompiler bug with mono!"); Assert.Ignore("Decompiler bug with mono!");
} }
RunCS(options: options); RunCS(options: options);
@ -274,7 +280,8 @@ namespace ICSharpCode.Decompiler.Tests
[Test] [Test]
public void YieldReturn([ValueSource("defaultOptions")] CompilerOptions options) public void YieldReturn([ValueSource("defaultOptions")] CompilerOptions options)
{ {
if (options.HasFlag(CompilerOptions.UseMcs)) { if (options.HasFlag(CompilerOptions.UseMcs))
{
Assert.Ignore("Decompiler bug with mono!"); Assert.Ignore("Decompiler bug with mono!");
} }
RunCS(options: options); RunCS(options: options);
@ -301,7 +308,8 @@ namespace ICSharpCode.Decompiler.Tests
[Test] [Test]
public void MiniJSON([ValueSource("defaultOptions")] CompilerOptions options) public void MiniJSON([ValueSource("defaultOptions")] CompilerOptions options)
{ {
if (options.HasFlag(CompilerOptions.UseMcs)) { if (options.HasFlag(CompilerOptions.UseMcs))
{
Assert.Ignore("Decompiler bug with mono!"); Assert.Ignore("Decompiler bug with mono!");
} }
RunCS(options: options); RunCS(options: options);
@ -313,11 +321,13 @@ namespace ICSharpCode.Decompiler.Tests
string testOutputFileName = testName + Tester.GetSuffix(options) + ".exe"; string testOutputFileName = testName + Tester.GetSuffix(options) + ".exe";
CompilerResults outputFile = null, decompiledOutputFile = null; CompilerResults outputFile = null, decompiledOutputFile = null;
try { try
{
outputFile = Tester.CompileCSharp(Path.Combine(TestCasePath, testFileName), options, outputFile = Tester.CompileCSharp(Path.Combine(TestCasePath, testFileName), options,
outputFileName: Path.Combine(TestCasePath, testOutputFileName)); outputFileName: Path.Combine(TestCasePath, testOutputFileName));
string decompiledCodeFile = Tester.DecompileCSharp(outputFile.PathToAssembly, Tester.GetSettings(options)); string decompiledCodeFile = Tester.DecompileCSharp(outputFile.PathToAssembly, Tester.GetSettings(options));
if (forceRoslynRecompile || options.HasFlag(CompilerOptions.UseMcs)) { if (forceRoslynRecompile || options.HasFlag(CompilerOptions.UseMcs))
{
// For second pass, use roslyn instead of mcs. // For second pass, use roslyn instead of mcs.
// 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.
@ -332,12 +342,14 @@ namespace ICSharpCode.Decompiler.Tests
</configuration>"); </configuration>");
} }
decompiledOutputFile = Tester.CompileCSharp(decompiledCodeFile, options); decompiledOutputFile = Tester.CompileCSharp(decompiledCodeFile, options);
Tester.RunAndCompareOutput(testFileName, outputFile.PathToAssembly, decompiledOutputFile.PathToAssembly, decompiledCodeFile); Tester.RunAndCompareOutput(testFileName, outputFile.PathToAssembly, decompiledOutputFile.PathToAssembly, decompiledCodeFile);
Tester.RepeatOnIOError(() => File.Delete(decompiledCodeFile)); Tester.RepeatOnIOError(() => File.Delete(decompiledCodeFile));
Tester.RepeatOnIOError(() => File.Delete(decompiledOutputFile.PathToAssembly)); Tester.RepeatOnIOError(() => File.Delete(decompiledOutputFile.PathToAssembly));
} finally { }
finally
{
if (outputFile != null) if (outputFile != null)
outputFile.TempFiles.Delete(); outputFile.TempFiles.Delete();
if (decompiledOutputFile != null) if (decompiledOutputFile != null)
@ -352,7 +364,8 @@ namespace ICSharpCode.Decompiler.Tests
string testOutputFileName = testName + Tester.GetSuffix(options) + ".exe"; string testOutputFileName = testName + Tester.GetSuffix(options) + ".exe";
CompilerResults outputFile = null, decompiledOutputFile = null; CompilerResults outputFile = null, decompiledOutputFile = null;
try { try
{
outputFile = Tester.CompileVB(Path.Combine(TestCasePath, testFileName), options, outputFile = Tester.CompileVB(Path.Combine(TestCasePath, testFileName), options,
outputFileName: Path.Combine(TestCasePath, testOutputFileName)); outputFileName: Path.Combine(TestCasePath, testOutputFileName));
string decompiledCodeFile = Tester.DecompileCSharp(outputFile.PathToAssembly, Tester.GetSettings(options)); string decompiledCodeFile = Tester.DecompileCSharp(outputFile.PathToAssembly, Tester.GetSettings(options));
@ -362,7 +375,9 @@ namespace ICSharpCode.Decompiler.Tests
Tester.RepeatOnIOError(() => File.Delete(decompiledCodeFile)); Tester.RepeatOnIOError(() => File.Delete(decompiledCodeFile));
Tester.RepeatOnIOError(() => File.Delete(decompiledOutputFile.PathToAssembly)); Tester.RepeatOnIOError(() => File.Delete(decompiledOutputFile.PathToAssembly));
} finally { }
finally
{
if (outputFile != null) if (outputFile != null)
outputFile.TempFiles.Delete(); outputFile.TempFiles.Delete();
if (decompiledOutputFile != null) if (decompiledOutputFile != null)
@ -375,16 +390,19 @@ namespace ICSharpCode.Decompiler.Tests
string outputFile = null; string outputFile = null;
CompilerResults decompiledOutputFile = null; CompilerResults decompiledOutputFile = null;
try { try
{
outputFile = Tester.AssembleIL(Path.Combine(TestCasePath, testFileName), asmOptions); outputFile = Tester.AssembleIL(Path.Combine(TestCasePath, testFileName), asmOptions);
string decompiledCodeFile = Tester.DecompileCSharp(outputFile, Tester.GetSettings(options)); string decompiledCodeFile = Tester.DecompileCSharp(outputFile, Tester.GetSettings(options));
decompiledOutputFile = Tester.CompileCSharp(decompiledCodeFile, options); decompiledOutputFile = Tester.CompileCSharp(decompiledCodeFile, options);
Tester.RunAndCompareOutput(testFileName, outputFile, decompiledOutputFile.PathToAssembly, decompiledCodeFile); Tester.RunAndCompareOutput(testFileName, outputFile, decompiledOutputFile.PathToAssembly, decompiledCodeFile);
Tester.RepeatOnIOError(() => File.Delete(decompiledCodeFile)); Tester.RepeatOnIOError(() => File.Delete(decompiledCodeFile));
Tester.RepeatOnIOError(() => File.Delete(decompiledOutputFile.PathToAssembly)); Tester.RepeatOnIOError(() => File.Delete(decompiledOutputFile.PathToAssembly));
} finally { }
finally
{
if (decompiledOutputFile != null) if (decompiledOutputFile != null)
decompiledOutputFile.TempFiles.Delete(); decompiledOutputFile.TempFiles.Delete();
} }

2
ICSharpCode.Decompiler.Tests/DataFlowTest.cs

@ -22,9 +22,11 @@ using System.Linq;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using ICSharpCode.Decompiler.FlowAnalysis; using ICSharpCode.Decompiler.FlowAnalysis;
using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.IL;
using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem;
using NUnit.Framework; using NUnit.Framework;
namespace ICSharpCode.Decompiler.Tests namespace ICSharpCode.Decompiler.Tests

8
ICSharpCode.Decompiler.Tests/DisassemblerPrettyTestRunner.cs

@ -23,7 +23,9 @@ using System.Linq;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using ICSharpCode.Decompiler.Tests.Helpers; using ICSharpCode.Decompiler.Tests.Helpers;
using NUnit.Framework; using NUnit.Framework;
namespace ICSharpCode.Decompiler.Tests namespace ICSharpCode.Decompiler.Tests
@ -40,8 +42,10 @@ namespace ICSharpCode.Decompiler.Tests
.Where(m => m.GetCustomAttributes(typeof(TestAttribute), false).Any()) .Where(m => m.GetCustomAttributes(typeof(TestAttribute), false).Any())
.Select(m => m.Name) .Select(m => m.Name)
.ToArray(); .ToArray();
foreach (var file in new DirectoryInfo(TestCasePath).EnumerateFiles()) { foreach (var file in new DirectoryInfo(TestCasePath).EnumerateFiles())
if (file.Extension.Equals(".il", StringComparison.OrdinalIgnoreCase)) { {
if (file.Extension.Equals(".il", StringComparison.OrdinalIgnoreCase))
{
var testName = file.Name.Split('.')[0]; var testName = file.Name.Split('.')[0];
Assert.Contains(testName, testNames); Assert.Contains(testName, testNames);
} }

60
ICSharpCode.Decompiler.Tests/Helpers/CodeAssert.cs

@ -2,9 +2,12 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using DiffLib; using DiffLib;
using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp;
using NUnit.Framework; using NUnit.Framework;
namespace ICSharpCode.Decompiler.Tests.Helpers namespace ICSharpCode.Decompiler.Tests.Helpers
@ -19,7 +22,8 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
public static void AreEqual(string input1, string input2, string[] definedSymbols = null) public static void AreEqual(string input1, string input2, string[] definedSymbols = null)
{ {
var diff = new StringWriter(); var diff = new StringWriter();
if (!CodeComparer.Compare(input1, input2, diff, CodeComparer.NormalizeLine, definedSymbols)) { if (!CodeComparer.Compare(input1, input2, diff, CodeComparer.NormalizeLine, definedSymbols))
{
Assert.Fail(diff.ToString()); Assert.Fail(diff.ToString());
} }
} }
@ -35,32 +39,40 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
collection1, collection2, new CodeLineEqualityComparer(normalizeLine) collection1, collection2, new CodeLineEqualityComparer(normalizeLine)
); );
var alignedDiff = Diff.AlignElements(collection1, collection2, diffSections, new StringSimilarityDiffElementAligner()); var alignedDiff = Diff.AlignElements(collection1, collection2, diffSections, new StringSimilarityDiffElementAligner());
bool result = true; bool result = true;
int line1 = 0, line2 = 0; int line1 = 0, line2 = 0;
const int contextSize = 10; const int contextSize = 10;
int consecutiveMatches = contextSize; int consecutiveMatches = contextSize;
var hiddenMatches = new List<string>(); var hiddenMatches = new List<string>();
foreach (var change in alignedDiff) { foreach (var change in alignedDiff)
switch (change.Operation) { {
switch (change.Operation)
{
case DiffOperation.Match: case DiffOperation.Match:
AppendMatch($"{++line1,4} {++line2,4} ", change.ElementFromCollection1.Value); AppendMatch($"{++line1,4} {++line2,4} ", change.ElementFromCollection1.Value);
break; break;
case DiffOperation.Insert: case DiffOperation.Insert:
string pos = $" {++line2,4} "; string pos = $" {++line2,4} ";
if (ShouldIgnoreChange(change.ElementFromCollection2.Value)) { if (ShouldIgnoreChange(change.ElementFromCollection2.Value))
{
AppendMatch(pos, change.ElementFromCollection2.Value); AppendMatch(pos, change.ElementFromCollection2.Value);
} else { }
else
{
AppendDelta(pos, " + ", change.ElementFromCollection2.Value); AppendDelta(pos, " + ", change.ElementFromCollection2.Value);
result = false; result = false;
} }
break; break;
case DiffOperation.Delete: case DiffOperation.Delete:
pos = $"{++line1,4} "; pos = $"{++line1,4} ";
if (ShouldIgnoreChange(change.ElementFromCollection1.Value)) { if (ShouldIgnoreChange(change.ElementFromCollection1.Value))
{
AppendMatch(pos, change.ElementFromCollection1.Value); AppendMatch(pos, change.ElementFromCollection1.Value);
} else { }
else
{
AppendDelta(pos, " - ", change.ElementFromCollection1.Value); AppendDelta(pos, " - ", change.ElementFromCollection1.Value);
result = false; result = false;
} }
@ -73,7 +85,8 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
break; break;
} }
} }
if (hiddenMatches.Count > 0) { if (hiddenMatches.Count > 0)
{
diff.WriteLine(" ..."); diff.WriteLine(" ...");
} }
@ -82,10 +95,13 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
void AppendMatch(string pos, string code) void AppendMatch(string pos, string code)
{ {
consecutiveMatches++; consecutiveMatches++;
if (consecutiveMatches > contextSize) { if (consecutiveMatches > contextSize)
{
// hide this match // hide this match
hiddenMatches.Add(pos + " " + code); hiddenMatches.Add(pos + " " + code);
} else { }
else
{
diff.WriteLine(pos + " " + code); diff.WriteLine(pos + " " + code);
} }
} }
@ -93,10 +109,12 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
void AppendDelta(string pos, string changeType, string code) void AppendDelta(string pos, string changeType, string code)
{ {
consecutiveMatches = 0; consecutiveMatches = 0;
if (hiddenMatches.Count > contextSize) { if (hiddenMatches.Count > contextSize)
{
diff.WriteLine(" ..."); diff.WriteLine(" ...");
} }
for (int i = Math.Max(0, hiddenMatches.Count - contextSize); i < hiddenMatches.Count; i++) { for (int i = Math.Max(0, hiddenMatches.Count - contextSize); i < hiddenMatches.Count; i++)
{
diff.WriteLine(hiddenMatches[i]); diff.WriteLine(hiddenMatches[i]);
} }
hiddenMatches.Clear(); hiddenMatches.Clear();
@ -132,11 +150,16 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
{ {
line = line.Trim(); line = line.Trim();
var index = line.IndexOf("//", StringComparison.Ordinal); var index = line.IndexOf("//", StringComparison.Ordinal);
if (index >= 0) { if (index >= 0)
{
return line.Substring(0, index); return line.Substring(0, index);
} else if (line.StartsWith("#", StringComparison.Ordinal)) { }
else if (line.StartsWith("#", StringComparison.Ordinal))
{
return string.Empty; return string.Empty;
} else { }
else
{
return line; return line;
} }
} }
@ -151,7 +174,8 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
{ {
public override SyntaxTrivia VisitTrivia(SyntaxTrivia trivia) public override SyntaxTrivia VisitTrivia(SyntaxTrivia trivia)
{ {
if (trivia.IsKind(SyntaxKind.DisabledTextTrivia)) { if (trivia.IsKind(SyntaxKind.DisabledTextTrivia))
{
return default(SyntaxTrivia); // delete return default(SyntaxTrivia); // delete
} }
return base.VisitTrivia(trivia); return base.VisitTrivia(trivia);

14
ICSharpCode.Decompiler.Tests/Helpers/RemoveCompilerAttribute.cs

@ -1,4 +1,5 @@
using System.Collections.Generic; using System.Collections.Generic;
using ICSharpCode.Decompiler.CSharp; using ICSharpCode.Decompiler.CSharp;
using ICSharpCode.Decompiler.CSharp.Syntax; using ICSharpCode.Decompiler.CSharp.Syntax;
using ICSharpCode.Decompiler.CSharp.Transforms; using ICSharpCode.Decompiler.CSharp.Transforms;
@ -13,12 +14,14 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
var section = (AttributeSection)attribute.Parent; var section = (AttributeSection)attribute.Parent;
SimpleType type = attribute.Type as SimpleType; SimpleType type = attribute.Type as SimpleType;
if (section.AttributeTarget == "assembly" && if (section.AttributeTarget == "assembly" &&
(type.Identifier == "CompilationRelaxations" || type.Identifier == "RuntimeCompatibility" || type.Identifier == "SecurityPermission" || type.Identifier == "PermissionSet" || type.Identifier == "AssemblyVersion" || type.Identifier == "Debuggable" || type.Identifier == "TargetFramework")) { (type.Identifier == "CompilationRelaxations" || type.Identifier == "RuntimeCompatibility" || type.Identifier == "SecurityPermission" || type.Identifier == "PermissionSet" || type.Identifier == "AssemblyVersion" || type.Identifier == "Debuggable" || type.Identifier == "TargetFramework"))
{
attribute.Remove(); attribute.Remove();
if (section.Attributes.Count == 0) if (section.Attributes.Count == 0)
section.Remove(); section.Remove();
} }
if (section.AttributeTarget == "module" && type.Identifier == "UnverifiableCode") { if (section.AttributeTarget == "module" && type.Identifier == "UnverifiableCode")
{
attribute.Remove(); attribute.Remove();
if (section.Attributes.Count == 0) if (section.Attributes.Count == 0)
section.Remove(); section.Remove();
@ -64,9 +67,12 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
{ {
public override void VisitNamespaceDeclaration(NamespaceDeclaration namespaceDeclaration) public override void VisitNamespaceDeclaration(NamespaceDeclaration namespaceDeclaration)
{ {
if (namespaceDeclaration.Name == "My") { if (namespaceDeclaration.Name == "My")
{
namespaceDeclaration.Remove(); namespaceDeclaration.Remove();
} else { }
else
{
base.VisitNamespaceDeclaration(namespaceDeclaration); base.VisitNamespaceDeclaration(namespaceDeclaration);
} }
} }

122
ICSharpCode.Decompiler.Tests/Helpers/SdkUtility.cs

@ -17,6 +17,7 @@
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System.IO; using System.IO;
using Microsoft.Win32; using Microsoft.Win32;
namespace ICSharpCode.Decompiler.Tests.Helpers namespace ICSharpCode.Decompiler.Tests.Helpers
@ -25,10 +26,13 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
{ {
static string GetPathFromRegistry(string key, string valueName) static string GetPathFromRegistry(string key, string valueName)
{ {
using (RegistryKey installRootKey = Registry.LocalMachine.OpenSubKey(key)) { using (RegistryKey installRootKey = Registry.LocalMachine.OpenSubKey(key))
if (installRootKey != null) { {
if (installRootKey != null)
{
object o = installRootKey.GetValue(valueName); object o = installRootKey.GetValue(valueName);
if (o != null) { if (o != null)
{
string r = o.ToString(); string r = o.ToString();
if (!string.IsNullOrEmpty(r)) if (!string.IsNullOrEmpty(r))
return r; return r;
@ -37,14 +41,18 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
} }
return null; return null;
} }
static string GetPathFromRegistryX86(string key, string valueName) static string GetPathFromRegistryX86(string key, string valueName)
{ {
using (RegistryKey baseKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32)) { using (RegistryKey baseKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32))
using (RegistryKey installRootKey = baseKey.OpenSubKey(key)) { {
if (installRootKey != null) { using (RegistryKey installRootKey = baseKey.OpenSubKey(key))
{
if (installRootKey != null)
{
object o = installRootKey.GetValue(valueName); object o = installRootKey.GetValue(valueName);
if (o != null) { if (o != null)
{
string r = o.ToString(); string r = o.ToString();
if (!string.IsNullOrEmpty(r)) if (!string.IsNullOrEmpty(r))
return r; return r;
@ -54,107 +62,115 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
} }
return null; return null;
} }
#region InstallRoot Properties #region InstallRoot Properties
static string netFrameworkInstallRoot = null; static string netFrameworkInstallRoot = null;
/// <summary> /// <summary>
/// Gets the installation root of the .NET Framework (@"C:\Windows\Microsoft.NET\Framework\") /// Gets the installation root of the .NET Framework (@"C:\Windows\Microsoft.NET\Framework\")
/// </summary> /// </summary>
public static string NetFrameworkInstallRoot { public static string NetFrameworkInstallRoot {
get { get {
if (netFrameworkInstallRoot == null) { if (netFrameworkInstallRoot == null)
{
netFrameworkInstallRoot = GetPathFromRegistry(@"SOFTWARE\Microsoft\.NETFramework", "InstallRoot") ?? string.Empty; netFrameworkInstallRoot = GetPathFromRegistry(@"SOFTWARE\Microsoft\.NETFramework", "InstallRoot") ?? string.Empty;
} }
return netFrameworkInstallRoot; return netFrameworkInstallRoot;
} }
} }
static string netSdk20InstallRoot = null; static string netSdk20InstallRoot = null;
/// <summary> /// <summary>
/// Location of the .NET 2.0 SDK install root. /// Location of the .NET 2.0 SDK install root.
/// </summary> /// </summary>
public static string NetSdk20InstallRoot { public static string NetSdk20InstallRoot {
get { get {
if (netSdk20InstallRoot == null) { if (netSdk20InstallRoot == null)
{
netSdk20InstallRoot = GetPathFromRegistry(@"SOFTWARE\Microsoft\.NETFramework", "sdkInstallRootv2.0") ?? string.Empty; netSdk20InstallRoot = GetPathFromRegistry(@"SOFTWARE\Microsoft\.NETFramework", "sdkInstallRootv2.0") ?? string.Empty;
} }
return netSdk20InstallRoot; return netSdk20InstallRoot;
} }
} }
static string windowsSdk60InstallRoot = null; static string windowsSdk60InstallRoot = null;
/// <summary> /// <summary>
/// Location of the .NET 3.0 SDK (Windows SDK 6.0) install root. /// Location of the .NET 3.0 SDK (Windows SDK 6.0) install root.
/// </summary> /// </summary>
public static string WindowsSdk60InstallRoot { public static string WindowsSdk60InstallRoot {
get { get {
if (windowsSdk60InstallRoot == null) { if (windowsSdk60InstallRoot == null)
{
windowsSdk60InstallRoot = GetPathFromRegistry(@"SOFTWARE\Microsoft\Microsoft SDKs\Windows\v6.0", "InstallationFolder") ?? string.Empty; windowsSdk60InstallRoot = GetPathFromRegistry(@"SOFTWARE\Microsoft\Microsoft SDKs\Windows\v6.0", "InstallationFolder") ?? string.Empty;
} }
return windowsSdk60InstallRoot; return windowsSdk60InstallRoot;
} }
} }
static string windowsSdk60aInstallRoot = null; static string windowsSdk60aInstallRoot = null;
/// <summary> /// <summary>
/// Location of the Windows SDK Components in Visual Studio 2008 (.NET 3.5; Windows SDK 6.0a). /// Location of the Windows SDK Components in Visual Studio 2008 (.NET 3.5; Windows SDK 6.0a).
/// </summary> /// </summary>
public static string WindowsSdk60aInstallRoot { public static string WindowsSdk60aInstallRoot {
get { get {
if (windowsSdk60aInstallRoot == null) { if (windowsSdk60aInstallRoot == null)
{
windowsSdk60aInstallRoot = GetPathFromRegistry(@"SOFTWARE\Microsoft\Microsoft SDKs\Windows\v6.0a", "InstallationFolder") ?? string.Empty; windowsSdk60aInstallRoot = GetPathFromRegistry(@"SOFTWARE\Microsoft\Microsoft SDKs\Windows\v6.0a", "InstallationFolder") ?? string.Empty;
} }
return windowsSdk60aInstallRoot; return windowsSdk60aInstallRoot;
} }
} }
static string windowsSdk61InstallRoot = null; static string windowsSdk61InstallRoot = null;
/// <summary> /// <summary>
/// Location of the .NET 3.5 SDK (Windows SDK 6.1) install root. /// Location of the .NET 3.5 SDK (Windows SDK 6.1) install root.
/// </summary> /// </summary>
public static string WindowsSdk61InstallRoot { public static string WindowsSdk61InstallRoot {
get { get {
if (windowsSdk61InstallRoot == null) { if (windowsSdk61InstallRoot == null)
{
windowsSdk61InstallRoot = GetPathFromRegistry(@"SOFTWARE\Microsoft\Microsoft SDKs\Windows\v6.1", "InstallationFolder") ?? string.Empty; windowsSdk61InstallRoot = GetPathFromRegistry(@"SOFTWARE\Microsoft\Microsoft SDKs\Windows\v6.1", "InstallationFolder") ?? string.Empty;
} }
return windowsSdk61InstallRoot; return windowsSdk61InstallRoot;
} }
} }
static string windowsSdk70InstallRoot = null; static string windowsSdk70InstallRoot = null;
/// <summary> /// <summary>
/// Location of the .NET 3.5 SP1 SDK (Windows SDK 7.0) install root. /// Location of the .NET 3.5 SP1 SDK (Windows SDK 7.0) install root.
/// </summary> /// </summary>
public static string WindowsSdk70InstallRoot { public static string WindowsSdk70InstallRoot {
get { get {
if (windowsSdk70InstallRoot == null) { if (windowsSdk70InstallRoot == null)
{
windowsSdk70InstallRoot = GetPathFromRegistry(@"SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.0", "InstallationFolder") ?? string.Empty; windowsSdk70InstallRoot = GetPathFromRegistry(@"SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.0", "InstallationFolder") ?? string.Empty;
} }
return windowsSdk70InstallRoot; return windowsSdk70InstallRoot;
} }
} }
static string windowsSdk71InstallRoot = null; static string windowsSdk71InstallRoot = null;
/// <summary> /// <summary>
/// Location of the .NET 4.0 SDK (Windows SDK 7.1) install root. /// Location of the .NET 4.0 SDK (Windows SDK 7.1) install root.
/// </summary> /// </summary>
public static string WindowsSdk71InstallRoot { public static string WindowsSdk71InstallRoot {
get { get {
if (windowsSdk71InstallRoot == null) { if (windowsSdk71InstallRoot == null)
{
windowsSdk71InstallRoot = GetPathFromRegistry(@"SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.1", "InstallationFolder") ?? string.Empty; windowsSdk71InstallRoot = GetPathFromRegistry(@"SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.1", "InstallationFolder") ?? string.Empty;
} }
return windowsSdk71InstallRoot; return windowsSdk71InstallRoot;
} }
} }
static string windowsSdk80InstallRoot = null; static string windowsSdk80InstallRoot = null;
/// <summary> /// <summary>
/// Location of the .NET 4.5 SDK (Windows SDK 8.0) install root. /// Location of the .NET 4.5 SDK (Windows SDK 8.0) install root.
/// </summary> /// </summary>
public static string WindowsSdk80NetFxTools { public static string WindowsSdk80NetFxTools {
get { get {
if (windowsSdk80InstallRoot == null) { if (windowsSdk80InstallRoot == null)
{
windowsSdk80InstallRoot = GetPathFromRegistryX86(@"SOFTWARE\Microsoft\Microsoft SDKs\Windows\v8.0A\WinSDK-NetFx40Tools", "InstallationFolder") ?? string.Empty; windowsSdk80InstallRoot = GetPathFromRegistryX86(@"SOFTWARE\Microsoft\Microsoft SDKs\Windows\v8.0A\WinSDK-NetFx40Tools", "InstallationFolder") ?? string.Empty;
} }
return windowsSdk80InstallRoot; return windowsSdk80InstallRoot;
@ -167,53 +183,71 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
/// </summary> /// </summary>
public static string WindowsSdk461NetFxTools { public static string WindowsSdk461NetFxTools {
get { get {
if (WindowsSdk461InstallRoot == null) { if (WindowsSdk461InstallRoot == null)
{
WindowsSdk461InstallRoot = GetPathFromRegistryX86(@"SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\NETFXSDK\4.6.1\WinSDK-NetFx40Tools", "InstallationFolder") ?? string.Empty; WindowsSdk461InstallRoot = GetPathFromRegistryX86(@"SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\NETFXSDK\4.6.1\WinSDK-NetFx40Tools", "InstallationFolder") ?? string.Empty;
} }
return WindowsSdk461InstallRoot; return WindowsSdk461InstallRoot;
} }
} }
#endregion #endregion
/// <summary> /// <summary>
/// Searches all the .net sdk bin folders and return the path of the /// Searches all the .net sdk bin folders and return the path of the
/// exe from the latest sdk. /// exe from the latest sdk.
/// </summary> /// </summary>
/// <param name="exeName">The EXE to search for.</param> /// <param name="exeName">The EXE to search for.</param>
/// <returns>The path of the executable, or null if the exe is not found.</returns> /// <returns>The path of the executable, or null if the exe is not found.</returns>
public static string GetSdkPath(string exeName) { public static string GetSdkPath(string exeName)
{
string execPath; string execPath;
if (!string.IsNullOrEmpty(WindowsSdk461NetFxTools)) { if (!string.IsNullOrEmpty(WindowsSdk461NetFxTools))
{
execPath = Path.Combine(WindowsSdk461NetFxTools, exeName); execPath = Path.Combine(WindowsSdk461NetFxTools, exeName);
if (File.Exists(execPath)) { return execPath; } if (File.Exists(execPath))
{ return execPath; }
} }
if (!string.IsNullOrEmpty(WindowsSdk80NetFxTools)) { if (!string.IsNullOrEmpty(WindowsSdk80NetFxTools))
{
execPath = Path.Combine(WindowsSdk80NetFxTools, exeName); execPath = Path.Combine(WindowsSdk80NetFxTools, exeName);
if (File.Exists(execPath)) { return execPath; } if (File.Exists(execPath))
{ return execPath; }
} }
if (!string.IsNullOrEmpty(WindowsSdk71InstallRoot)) { if (!string.IsNullOrEmpty(WindowsSdk71InstallRoot))
{
execPath = Path.Combine(WindowsSdk71InstallRoot, "bin\\" + exeName); execPath = Path.Combine(WindowsSdk71InstallRoot, "bin\\" + exeName);
if (File.Exists(execPath)) { return execPath; } if (File.Exists(execPath))
{ return execPath; }
} }
if (!string.IsNullOrEmpty(WindowsSdk70InstallRoot)) { if (!string.IsNullOrEmpty(WindowsSdk70InstallRoot))
{
execPath = Path.Combine(WindowsSdk70InstallRoot, "bin\\" + exeName); execPath = Path.Combine(WindowsSdk70InstallRoot, "bin\\" + exeName);
if (File.Exists(execPath)) { return execPath; } if (File.Exists(execPath))
{ return execPath; }
} }
if (!string.IsNullOrEmpty(WindowsSdk61InstallRoot)) { if (!string.IsNullOrEmpty(WindowsSdk61InstallRoot))
{
execPath = Path.Combine(WindowsSdk61InstallRoot, "bin\\" + exeName); execPath = Path.Combine(WindowsSdk61InstallRoot, "bin\\" + exeName);
if (File.Exists(execPath)) { return execPath; } if (File.Exists(execPath))
{ return execPath; }
} }
if (!string.IsNullOrEmpty(WindowsSdk60aInstallRoot)) { if (!string.IsNullOrEmpty(WindowsSdk60aInstallRoot))
{
execPath = Path.Combine(WindowsSdk60aInstallRoot, "bin\\" + exeName); execPath = Path.Combine(WindowsSdk60aInstallRoot, "bin\\" + exeName);
if (File.Exists(execPath)) { return execPath; } if (File.Exists(execPath))
{ return execPath; }
} }
if (!string.IsNullOrEmpty(WindowsSdk60InstallRoot)) { if (!string.IsNullOrEmpty(WindowsSdk60InstallRoot))
{
execPath = Path.Combine(WindowsSdk60InstallRoot, "bin\\" + exeName); execPath = Path.Combine(WindowsSdk60InstallRoot, "bin\\" + exeName);
if (File.Exists(execPath)) { return execPath; } if (File.Exists(execPath))
{ return execPath; }
} }
if (!string.IsNullOrEmpty(NetSdk20InstallRoot)) { if (!string.IsNullOrEmpty(NetSdk20InstallRoot))
{
execPath = Path.Combine(NetSdk20InstallRoot, "bin\\" + exeName); execPath = Path.Combine(NetSdk20InstallRoot, "bin\\" + exeName);
if (File.Exists(execPath)) { return execPath; } if (File.Exists(execPath))
{ return execPath; }
} }
return null; return null;
} }

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

@ -7,6 +7,7 @@ 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 Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.VisualBasic; using Microsoft.CodeAnalysis.VisualBasic;
using Microsoft.VisualBasic; using Microsoft.VisualBasic;
@ -18,17 +19,20 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
public static CompilerResults CompileVB(string sourceFileName, CompilerOptions flags = CompilerOptions.UseDebug, string outputFileName = null) public static CompilerResults CompileVB(string sourceFileName, CompilerOptions flags = CompilerOptions.UseDebug, string outputFileName = null)
{ {
List<string> sourceFileNames = new List<string> { sourceFileName }; List<string> sourceFileNames = new List<string> { sourceFileName };
foreach (Match match in Regex.Matches(File.ReadAllText(sourceFileName), @"#include ""([\w\d./]+)""")) { foreach (Match match in Regex.Matches(File.ReadAllText(sourceFileName), @"#include ""([\w\d./]+)"""))
{
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)));
} }
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.UseRoslyn))
{
var parseOptions = new VisualBasicParseOptions(preprocessorSymbols: preprocessorSymbols, languageVersion: LanguageVersion.Latest); var parseOptions = new VisualBasicParseOptions(preprocessorSymbols: preprocessorSymbols, languageVersion: LanguageVersion.Latest);
var syntaxTrees = sourceFileNames.Select(f => SyntaxFactory.ParseSyntaxTree(File.ReadAllText(f), parseOptions, path: f)); var syntaxTrees = sourceFileNames.Select(f => SyntaxFactory.ParseSyntaxTree(File.ReadAllText(f), parseOptions, path: f));
var references = defaultReferences.Value; var references = defaultReferences.Value;
if (flags.HasFlag(CompilerOptions.ReferenceVisualBasic)) { if (flags.HasFlag(CompilerOptions.ReferenceVisualBasic))
{
references = references.Concat(visualBasic.Value); references = references.Concat(visualBasic.Value);
} }
var compilation = VisualBasicCompilation.Create(Path.GetFileNameWithoutExtension(sourceFileName), var compilation = VisualBasicCompilation.Create(Path.GetFileNameWithoutExtension(sourceFileName),
@ -42,17 +46,23 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
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); var emitResult = compilation.Emit(results.PathToAssembly);
if (!emitResult.Success) { if (!emitResult.Success)
{
StringBuilder b = new StringBuilder("Compiler error:"); StringBuilder b = new StringBuilder("Compiler error:");
foreach (var diag in emitResult.Diagnostics) { foreach (var diag in emitResult.Diagnostics)
{
b.AppendLine(diag.ToString()); b.AppendLine(diag.ToString());
} }
throw new Exception(b.ToString()); throw new Exception(b.ToString());
} }
return results; return results;
} else if (flags.HasFlag(CompilerOptions.UseMcs)) { }
else if (flags.HasFlag(CompilerOptions.UseMcs))
{
throw new NotSupportedException("Cannot use mcs for VB"); throw new NotSupportedException("Cannot use mcs for VB");
} else { }
else
{
var provider = new VBCodeProvider(new Dictionary<string, string> { { "CompilerVersion", "v4.0" } }); var provider = new VBCodeProvider(new Dictionary<string, string> { { "CompilerVersion", "v4.0" } });
CompilerParameters options = new CompilerParameters(); CompilerParameters options = new CompilerParameters();
options.GenerateExecutable = !flags.HasFlag(CompilerOptions.Library); options.GenerateExecutable = !flags.HasFlag(CompilerOptions.Library);
@ -60,23 +70,28 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
options.CompilerOptions += (flags.HasFlag(CompilerOptions.UseDebug) ? " /debug" : ""); options.CompilerOptions += (flags.HasFlag(CompilerOptions.UseDebug) ? " /debug" : "");
options.CompilerOptions += (flags.HasFlag(CompilerOptions.Force32Bit) ? " /platform:anycpu32bitpreferred" : ""); options.CompilerOptions += (flags.HasFlag(CompilerOptions.Force32Bit) ? " /platform:anycpu32bitpreferred" : "");
options.CompilerOptions += " /optioninfer+ /optionexplicit+"; options.CompilerOptions += " /optioninfer+ /optionexplicit+";
if (preprocessorSymbols.Count > 0) { if (preprocessorSymbols.Count > 0)
{
options.CompilerOptions += " /d:" + string.Join(",", preprocessorSymbols.Select(p => $"{p.Key}={p.Value}")); options.CompilerOptions += " /d:" + string.Join(",", preprocessorSymbols.Select(p => $"{p.Key}={p.Value}"));
} }
if (outputFileName != null) { if (outputFileName != null)
{
options.OutputAssembly = outputFileName; options.OutputAssembly = outputFileName;
} }
options.ReferencedAssemblies.Add("System.dll"); options.ReferencedAssemblies.Add("System.dll");
options.ReferencedAssemblies.Add("System.Core.dll"); options.ReferencedAssemblies.Add("System.Core.dll");
options.ReferencedAssemblies.Add("System.Xml.dll"); options.ReferencedAssemblies.Add("System.Xml.dll");
if (flags.HasFlag(CompilerOptions.ReferenceVisualBasic)) { if (flags.HasFlag(CompilerOptions.ReferenceVisualBasic))
{
options.ReferencedAssemblies.Add("Microsoft.VisualBasic.dll"); options.ReferencedAssemblies.Add("Microsoft.VisualBasic.dll");
} }
CompilerResults results = provider.CompileAssemblyFromFile(options, sourceFileNames.ToArray()); CompilerResults results = provider.CompileAssemblyFromFile(options, sourceFileNames.ToArray());
if (results.Errors.Cast<CompilerError>().Any(e => !e.IsWarning)) { if (results.Errors.Cast<CompilerError>().Any(e => !e.IsWarning))
{
StringBuilder b = new StringBuilder("Compiler error:"); StringBuilder b = new StringBuilder("Compiler error:");
foreach (var error in results.Errors) { foreach (var error in results.Errors)
{
b.AppendLine(error.ToString()); b.AppendLine(error.ToString());
} }
throw new Exception(b.ToString()); throw new Exception(b.ToString());

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

@ -28,18 +28,21 @@ 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 ICSharpCode.Decompiler.CSharp; using ICSharpCode.Decompiler.CSharp;
using ICSharpCode.Decompiler.CSharp.OutputVisitor; using ICSharpCode.Decompiler.CSharp.OutputVisitor;
using ICSharpCode.Decompiler.CSharp.Transforms; using ICSharpCode.Decompiler.CSharp.Transforms;
using ICSharpCode.Decompiler.Disassembler; using ICSharpCode.Decompiler.Disassembler;
using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem;
using Microsoft.CodeAnalysis; 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 Microsoft.CSharp;
using Microsoft.DiaSymReader.Tools; using Microsoft.DiaSymReader.Tools;
using NUnit.Framework; using NUnit.Framework;
namespace ICSharpCode.Decompiler.Tests.Helpers namespace ICSharpCode.Decompiler.Tests.Helpers
@ -81,20 +84,25 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
string ilasmPath = Path.Combine(Environment.GetEnvironmentVariable("windir"), @"Microsoft.NET\Framework\v4.0.30319\ilasm.exe"); string ilasmPath = Path.Combine(Environment.GetEnvironmentVariable("windir"), @"Microsoft.NET\Framework\v4.0.30319\ilasm.exe");
string outputFile = Path.Combine(Path.GetDirectoryName(sourceFileName), Path.GetFileNameWithoutExtension(sourceFileName)); string outputFile = Path.Combine(Path.GetDirectoryName(sourceFileName), Path.GetFileNameWithoutExtension(sourceFileName));
string otherOptions = " "; string otherOptions = " ";
if (options.HasFlag(AssemblerOptions.Force32Bit)) { if (options.HasFlag(AssemblerOptions.Force32Bit))
{
outputFile += ".32"; outputFile += ".32";
otherOptions += "/32BitPreferred "; otherOptions += "/32BitPreferred ";
} }
if (options.HasFlag(AssemblerOptions.Library)) { if (options.HasFlag(AssemblerOptions.Library))
{
outputFile += ".dll"; outputFile += ".dll";
otherOptions += "/dll "; otherOptions += "/dll ";
} else { }
else
{
outputFile += ".exe"; outputFile += ".exe";
otherOptions += "/exe "; otherOptions += "/exe ";
} }
if (options.HasFlag(AssemblerOptions.UseDebug)) { if (options.HasFlag(AssemblerOptions.UseDebug))
{
otherOptions += "/debug "; otherOptions += "/debug ";
} }
@ -121,10 +129,12 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
public static string Disassemble(string sourceFileName, string outputFile, AssemblerOptions asmOptions) public static string Disassemble(string sourceFileName, string outputFile, AssemblerOptions asmOptions)
{ {
if (asmOptions.HasFlag(AssemblerOptions.UseOwnDisassembler)) { if (asmOptions.HasFlag(AssemblerOptions.UseOwnDisassembler))
{
using (var peFileStream = new FileStream(sourceFileName, FileMode.Open, FileAccess.Read)) using (var peFileStream = new FileStream(sourceFileName, FileMode.Open, FileAccess.Read))
using (var peFile = new PEFile(sourceFileName, peFileStream)) using (var peFile = new PEFile(sourceFileName, peFileStream))
using (var writer = new StringWriter()) { using (var writer = new StringWriter())
{
var metadata = peFile.Metadata; var metadata = peFile.Metadata;
var output = new PlainTextOutput(writer); var output = new PlainTextOutput(writer);
ReflectionDisassembler rd = new ReflectionDisassembler(output, CancellationToken.None); ReflectionDisassembler rd = new ReflectionDisassembler(output, CancellationToken.None);
@ -186,7 +196,7 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
} }
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);
@ -217,7 +227,8 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
static IEnumerable<MetadataReference> GetDefaultReferences() static IEnumerable<MetadataReference> GetDefaultReferences()
{ {
foreach (var reference in Directory.EnumerateFiles(coreRefAsmPath, "*.dll")) { foreach (var reference in Directory.EnumerateFiles(coreRefAsmPath, "*.dll"))
{
yield return MetadataReference.CreateFromFile(reference); yield return MetadataReference.CreateFromFile(reference);
} }
} }
@ -231,16 +242,20 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
public static List<string> GetPreprocessorSymbols(CompilerOptions flags) public static List<string> GetPreprocessorSymbols(CompilerOptions flags)
{ {
var preprocessorSymbols = new List<string>(); var preprocessorSymbols = new List<string>();
if (flags.HasFlag(CompilerOptions.UseDebug)) { if (flags.HasFlag(CompilerOptions.UseDebug))
{
preprocessorSymbols.Add("DEBUG"); preprocessorSymbols.Add("DEBUG");
} }
if (flags.HasFlag(CompilerOptions.Optimize)) { if (flags.HasFlag(CompilerOptions.Optimize))
{
preprocessorSymbols.Add("OPT"); preprocessorSymbols.Add("OPT");
} }
if (flags.HasFlag(CompilerOptions.ReferenceCore)) { if (flags.HasFlag(CompilerOptions.ReferenceCore))
{
preprocessorSymbols.Add("NETCORE"); preprocessorSymbols.Add("NETCORE");
} }
if (flags.HasFlag(CompilerOptions.UseRoslyn)) { if (flags.HasFlag(CompilerOptions.UseRoslyn))
{
preprocessorSymbols.Add("ROSLYN"); preprocessorSymbols.Add("ROSLYN");
preprocessorSymbols.Add("CS60"); preprocessorSymbols.Add("CS60");
preprocessorSymbols.Add("CS70"); preprocessorSymbols.Add("CS70");
@ -252,12 +267,17 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
preprocessorSymbols.Add("VB14"); preprocessorSymbols.Add("VB14");
preprocessorSymbols.Add("VB15"); preprocessorSymbols.Add("VB15");
if (flags.HasFlag(CompilerOptions.Preview)) { if (flags.HasFlag(CompilerOptions.Preview))
{
preprocessorSymbols.Add("CS90"); preprocessorSymbols.Add("CS90");
} }
} else if (flags.HasFlag(CompilerOptions.UseMcs)) { }
else if (flags.HasFlag(CompilerOptions.UseMcs))
{
preprocessorSymbols.Add("MCS"); preprocessorSymbols.Add("MCS");
} else { }
else
{
preprocessorSymbols.Add("LEGACY_CSC"); preprocessorSymbols.Add("LEGACY_CSC");
preprocessorSymbols.Add("LEGACY_VBC"); preprocessorSymbols.Add("LEGACY_VBC");
} }
@ -267,28 +287,35 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
public static CompilerResults CompileCSharp(string sourceFileName, CompilerOptions flags = CompilerOptions.UseDebug, string outputFileName = null) public static CompilerResults CompileCSharp(string sourceFileName, CompilerOptions flags = CompilerOptions.UseDebug, string outputFileName = null)
{ {
List<string> sourceFileNames = new List<string> { sourceFileName }; List<string> sourceFileNames = new List<string> { sourceFileName };
foreach (Match match in Regex.Matches(File.ReadAllText(sourceFileName), @"#include ""([\w\d./]+)""")) { foreach (Match match in Regex.Matches(File.ReadAllText(sourceFileName), @"#include ""([\w\d./]+)"""))
{
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)));
} }
var preprocessorSymbols = GetPreprocessorSymbols(flags); var preprocessorSymbols = GetPreprocessorSymbols(flags);
if (flags.HasFlag(CompilerOptions.UseRoslyn)) { if (flags.HasFlag(CompilerOptions.UseRoslyn))
{
var parseOptions = new CSharpParseOptions( var parseOptions = new CSharpParseOptions(
preprocessorSymbols: preprocessorSymbols.ToArray(), preprocessorSymbols: preprocessorSymbols.ToArray(),
languageVersion: flags.HasFlag(CompilerOptions.Preview) ? Microsoft.CodeAnalysis.CSharp.LanguageVersion.Preview : Microsoft.CodeAnalysis.CSharp.LanguageVersion.CSharp8 languageVersion: flags.HasFlag(CompilerOptions.Preview) ? Microsoft.CodeAnalysis.CSharp.LanguageVersion.Preview : Microsoft.CodeAnalysis.CSharp.LanguageVersion.CSharp8
); );
var syntaxTrees = sourceFileNames.Select(f => SyntaxFactory.ParseSyntaxTree(File.ReadAllText(f), parseOptions, path: f, encoding: Encoding.UTF8)); var syntaxTrees = sourceFileNames.Select(f => SyntaxFactory.ParseSyntaxTree(File.ReadAllText(f), parseOptions, path: f, encoding: Encoding.UTF8));
if (flags.HasFlag(CompilerOptions.ReferenceCore)) { if (flags.HasFlag(CompilerOptions.ReferenceCore))
{
syntaxTrees = syntaxTrees.Concat(new[] { SyntaxFactory.ParseSyntaxTree(targetFrameworkAttributeSnippet) }); syntaxTrees = syntaxTrees.Concat(new[] { SyntaxFactory.ParseSyntaxTree(targetFrameworkAttributeSnippet) });
} }
IEnumerable<MetadataReference> references; IEnumerable<MetadataReference> references;
if (flags.HasFlag(CompilerOptions.ReferenceCore)) { if (flags.HasFlag(CompilerOptions.ReferenceCore))
{
references = coreDefaultReferences.Value; references = coreDefaultReferences.Value;
} else { }
else
{
references = defaultReferences.Value; references = defaultReferences.Value;
} }
if (flags.HasFlag(CompilerOptions.ReferenceVisualBasic)) { if (flags.HasFlag(CompilerOptions.ReferenceVisualBasic))
{
references = references.Concat(visualBasic.Value); references = references.Concat(visualBasic.Value);
} }
var compilation = CSharpCompilation.Create(Path.GetFileNameWithoutExtension(sourceFileName), var compilation = CSharpCompilation.Create(Path.GetFileNameWithoutExtension(sourceFileName),
@ -306,41 +333,54 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
if (flags.HasFlag(CompilerOptions.GeneratePdb)) if (flags.HasFlag(CompilerOptions.GeneratePdb))
pdbName = Path.ChangeExtension(outputFileName, ".pdb"); pdbName = Path.ChangeExtension(outputFileName, ".pdb");
var emitResult = compilation.Emit(results.PathToAssembly, pdbName); var emitResult = compilation.Emit(results.PathToAssembly, pdbName);
if (!emitResult.Success) { if (!emitResult.Success)
{
StringBuilder b = new StringBuilder("Compiler error:"); StringBuilder b = new StringBuilder("Compiler error:");
foreach (var diag in emitResult.Diagnostics) { foreach (var diag in emitResult.Diagnostics)
{
b.AppendLine(diag.ToString()); b.AppendLine(diag.ToString());
} }
throw new Exception(b.ToString()); throw new Exception(b.ToString());
} }
return results; return results;
} else if (flags.HasFlag(CompilerOptions.UseMcs)) { }
else if (flags.HasFlag(CompilerOptions.UseMcs))
{
CompilerResults results = new CompilerResults(new TempFileCollection()); CompilerResults results = new CompilerResults(new TempFileCollection());
results.PathToAssembly = outputFileName ?? Path.GetTempFileName(); results.PathToAssembly = outputFileName ?? Path.GetTempFileName();
string testBasePath = RoundtripAssembly.TestDir; string testBasePath = RoundtripAssembly.TestDir;
if (!Directory.Exists(testBasePath)) { if (!Directory.Exists(testBasePath))
{
Assert.Ignore($"Compilation with mcs ignored: test directory '{testBasePath}' needs to be checked out separately." + Environment.NewLine + Assert.Ignore($"Compilation with mcs ignored: test directory '{testBasePath}' needs to be checked out separately." + Environment.NewLine +
$"git clone https://github.com/icsharpcode/ILSpy-tests \"{testBasePath}\""); $"git clone https://github.com/icsharpcode/ILSpy-tests \"{testBasePath}\"");
} }
string mcsPath = Path.Combine(testBasePath, @"mcs\2.6.4\bin\gmcs.bat"); string mcsPath = Path.Combine(testBasePath, @"mcs\2.6.4\bin\gmcs.bat");
string otherOptions = " -unsafe -o" + (flags.HasFlag(CompilerOptions.Optimize) ? "+ " : "- "); string otherOptions = " -unsafe -o" + (flags.HasFlag(CompilerOptions.Optimize) ? "+ " : "- ");
if (flags.HasFlag(CompilerOptions.Library)) { if (flags.HasFlag(CompilerOptions.Library))
{
otherOptions += "-t:library "; otherOptions += "-t:library ";
} else { }
else
{
otherOptions += "-t:exe "; otherOptions += "-t:exe ";
} }
if (flags.HasFlag(CompilerOptions.UseDebug)) { if (flags.HasFlag(CompilerOptions.UseDebug))
{
otherOptions += "-g "; otherOptions += "-g ";
} }
if (flags.HasFlag(CompilerOptions.Force32Bit)) { if (flags.HasFlag(CompilerOptions.Force32Bit))
{
otherOptions += "-platform:x86 "; otherOptions += "-platform:x86 ";
} else { }
else
{
otherOptions += "-platform:anycpu "; otherOptions += "-platform:anycpu ";
} }
if (preprocessorSymbols.Count > 0) { if (preprocessorSymbols.Count > 0)
{
otherOptions += " \"-d:" + string.Join(";", preprocessorSymbols) + "\" "; otherOptions += " \"-d:" + string.Join(";", preprocessorSymbols) + "\" ";
} }
@ -364,35 +404,43 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
Console.WriteLine("errors: " + errorTask.Result); Console.WriteLine("errors: " + errorTask.Result);
Assert.AreEqual(0, process.ExitCode, "mcs failed"); Assert.AreEqual(0, process.ExitCode, "mcs failed");
return results; return results;
} else { }
else
{
var provider = new CSharpCodeProvider(new Dictionary<string, string> { { "CompilerVersion", "v4.0" } }); var provider = new CSharpCodeProvider(new Dictionary<string, string> { { "CompilerVersion", "v4.0" } });
CompilerParameters options = new CompilerParameters(); CompilerParameters options = new CompilerParameters();
options.GenerateExecutable = !flags.HasFlag(CompilerOptions.Library); options.GenerateExecutable = !flags.HasFlag(CompilerOptions.Library);
options.CompilerOptions = "/unsafe /o" + (flags.HasFlag(CompilerOptions.Optimize) ? "+" : "-"); options.CompilerOptions = "/unsafe /o" + (flags.HasFlag(CompilerOptions.Optimize) ? "+" : "-");
string debugOption = " /debug"; string debugOption = " /debug";
if (flags.HasFlag(CompilerOptions.GeneratePdb)) { if (flags.HasFlag(CompilerOptions.GeneratePdb))
{
debugOption += ":full"; debugOption += ":full";
options.IncludeDebugInformation = true; options.IncludeDebugInformation = true;
} }
options.CompilerOptions += (flags.HasFlag(CompilerOptions.UseDebug) ? debugOption : ""); options.CompilerOptions += (flags.HasFlag(CompilerOptions.UseDebug) ? debugOption : "");
options.CompilerOptions += (flags.HasFlag(CompilerOptions.Force32Bit) ? " /platform:anycpu32bitpreferred" : ""); options.CompilerOptions += (flags.HasFlag(CompilerOptions.Force32Bit) ? " /platform:anycpu32bitpreferred" : "");
if (preprocessorSymbols.Count > 0) { if (preprocessorSymbols.Count > 0)
{
options.CompilerOptions += " /d:" + string.Join(";", preprocessorSymbols); options.CompilerOptions += " /d:" + string.Join(";", preprocessorSymbols);
} }
if (outputFileName != null) { if (outputFileName != null)
{
options.OutputAssembly = outputFileName; options.OutputAssembly = outputFileName;
} }
options.ReferencedAssemblies.Add("System.dll"); options.ReferencedAssemblies.Add("System.dll");
options.ReferencedAssemblies.Add("System.Core.dll"); options.ReferencedAssemblies.Add("System.Core.dll");
options.ReferencedAssemblies.Add("System.Xml.dll"); options.ReferencedAssemblies.Add("System.Xml.dll");
options.ReferencedAssemblies.Add("Microsoft.CSharp.dll"); options.ReferencedAssemblies.Add("Microsoft.CSharp.dll");
if (flags.HasFlag(CompilerOptions.ReferenceVisualBasic)) { if (flags.HasFlag(CompilerOptions.ReferenceVisualBasic))
{
options.ReferencedAssemblies.Add("Microsoft.VisualBasic.dll"); options.ReferencedAssemblies.Add("Microsoft.VisualBasic.dll");
} }
CompilerResults results = provider.CompileAssemblyFromFile(options, sourceFileNames.ToArray()); CompilerResults results = provider.CompileAssemblyFromFile(options, sourceFileNames.ToArray());
if (results.Errors.Cast<CompilerError>().Any(e => !e.IsWarning)) { if (results.Errors.Cast<CompilerError>().Any(e => !e.IsWarning))
{
StringBuilder b = new StringBuilder("Compiler error:"); StringBuilder b = new StringBuilder("Compiler error:");
foreach (var error in results.Errors) { foreach (var error in results.Errors)
{
b.AppendLine(error.ToString()); b.AppendLine(error.ToString());
} }
throw new Exception(b.ToString()); throw new Exception(b.ToString());
@ -403,13 +451,19 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
internal static DecompilerSettings GetSettings(CompilerOptions cscOptions) internal static DecompilerSettings GetSettings(CompilerOptions cscOptions)
{ {
if (cscOptions.HasFlag(CompilerOptions.UseRoslyn)) { if (cscOptions.HasFlag(CompilerOptions.UseRoslyn))
if (cscOptions.HasFlag(CompilerOptions.Preview)) { {
if (cscOptions.HasFlag(CompilerOptions.Preview))
{
return new DecompilerSettings(CSharp.LanguageVersion.Latest); return new DecompilerSettings(CSharp.LanguageVersion.Latest);
} else { }
else
{
return new DecompilerSettings(CSharp.LanguageVersion.CSharp8_0); return new DecompilerSettings(CSharp.LanguageVersion.CSharp8_0);
} }
} else { }
else
{
return new DecompilerSettings(CSharp.LanguageVersion.CSharp5); return new DecompilerSettings(CSharp.LanguageVersion.CSharp5);
} }
} }
@ -421,7 +475,8 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
List<EmbeddedText> embeddedTexts = new List<EmbeddedText>(); List<EmbeddedText> embeddedTexts = new List<EmbeddedText>();
List<SyntaxTree> syntaxTrees = new List<SyntaxTree>(); List<SyntaxTree> syntaxTrees = new List<SyntaxTree>();
foreach (KeyValuePair<string, string> file in sourceFiles) { foreach (KeyValuePair<string, string> file in sourceFiles)
{
var sourceText = SourceText.From(file.Value, new UTF8Encoding(false), SourceHashAlgorithm.Sha256); var sourceText = SourceText.From(file.Value, new UTF8Encoding(false), SourceHashAlgorithm.Sha256);
syntaxTrees.Add(SyntaxFactory.ParseSyntaxTree(sourceText, parseOptions, file.Key)); syntaxTrees.Add(SyntaxFactory.ParseSyntaxTree(sourceText, parseOptions, file.Key));
embeddedTexts.Add(EmbeddedText.FromSource(file.Key, sourceText)); embeddedTexts.Add(EmbeddedText.FromSource(file.Key, sourceText));
@ -437,11 +492,14 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
deterministic: true deterministic: true
)); ));
using (FileStream peStream = File.Open(assemblyName + ".dll", FileMode.OpenOrCreate, FileAccess.ReadWrite)) using (FileStream peStream = File.Open(assemblyName + ".dll", FileMode.OpenOrCreate, FileAccess.ReadWrite))
using (FileStream pdbStream = File.Open(assemblyName + ".pdb", FileMode.OpenOrCreate, FileAccess.ReadWrite)) { using (FileStream pdbStream = File.Open(assemblyName + ".pdb", FileMode.OpenOrCreate, FileAccess.ReadWrite))
{
var emitResult = compilation.Emit(peStream, pdbStream, options: new EmitOptions(debugInformationFormat: DebugInformationFormat.PortablePdb, pdbFilePath: assemblyName + ".pdb"), embeddedTexts: embeddedTexts); var emitResult = compilation.Emit(peStream, pdbStream, options: new EmitOptions(debugInformationFormat: DebugInformationFormat.PortablePdb, pdbFilePath: assemblyName + ".pdb"), embeddedTexts: embeddedTexts);
if (!emitResult.Success) { if (!emitResult.Success)
{
StringBuilder b = new StringBuilder("Compiler error:"); StringBuilder b = new StringBuilder("Compiler error:");
foreach (var diag in emitResult.Diagnostics) { foreach (var diag in emitResult.Diagnostics)
{
b.AppendLine(diag.ToString()); b.AppendLine(diag.ToString());
} }
throw new Exception(b.ToString()); throw new Exception(b.ToString());
@ -490,7 +548,8 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
{ {
if (settings == null) if (settings == null)
settings = new DecompilerSettings(); settings = new DecompilerSettings();
using (var file = new FileStream(assemblyFileName, FileMode.Open, FileAccess.Read)) { using (var file = new FileStream(assemblyFileName, FileMode.Open, FileAccess.Read))
{
var module = new PEFile(assemblyFileName, file, PEStreamOptions.PrefetchEntireImage); var module = new PEFile(assemblyFileName, file, PEStreamOptions.PrefetchEntireImage);
var resolver = new UniversalAssemblyResolver(assemblyFileName, false, var resolver = new UniversalAssemblyResolver(assemblyFileName, false,
module.Reader.DetectTargetFrameworkId(), PEStreamOptions.PrefetchMetadata); module.Reader.DetectTargetFrameworkId(), PEStreamOptions.PrefetchMetadata);
@ -526,13 +585,16 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
Assert.AreEqual(0, result1, "Exit code != 0; did the test case crash?" + Environment.NewLine + error1); 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); Assert.AreEqual(0, result2, "Exit code != 0; did the decompiled code crash?" + Environment.NewLine + error2);
if (output1 != output2 || error1 != error2) { if (output1 != output2 || error1 != error2)
{
StringBuilder b = new StringBuilder(); StringBuilder b = new StringBuilder();
b.AppendLine($"Test {testFileName} failed: output does not match."); b.AppendLine($"Test {testFileName} failed: output does not match.");
if (decompiledCodeFile != null) { if (decompiledCodeFile != null)
{
b.AppendLine($"Decompiled code in {decompiledCodeFile}:line 1"); b.AppendLine($"Decompiled code in {decompiledCodeFile}:line 1");
} }
if (error1 != error2) { if (error1 != error2)
{
b.AppendLine("Got different error output."); b.AppendLine("Got different error output.");
b.AppendLine("Original error:"); b.AppendLine("Original error:");
b.AppendLine(error1); b.AppendLine(error1);
@ -541,25 +603,30 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
b.AppendLine(error2); b.AppendLine(error2);
b.AppendLine(); b.AppendLine();
} }
if (output1 != output2) { if (output1 != output2)
{
string outputFileName = Path.Combine(Path.GetTempPath(), Path.GetFileNameWithoutExtension(testFileName)); string outputFileName = Path.Combine(Path.GetTempPath(), Path.GetFileNameWithoutExtension(testFileName));
File.WriteAllText(outputFileName + ".original.out", output1); File.WriteAllText(outputFileName + ".original.out", output1);
File.WriteAllText(outputFileName + ".decompiled.out", output2); File.WriteAllText(outputFileName + ".decompiled.out", output2);
int diffLine = 0; int diffLine = 0;
string lastHeader = null; string lastHeader = null;
Tuple<string, string> errorItem = null; Tuple<string, string> errorItem = null;
foreach (var pair in output1.Replace("\r", "").Split('\n').Zip(output2.Replace("\r", "").Split('\n'), Tuple.Create)) { foreach (var pair in output1.Replace("\r", "").Split('\n').Zip(output2.Replace("\r", "").Split('\n'), Tuple.Create))
{
diffLine++; diffLine++;
if (pair.Item1 != pair.Item2) { if (pair.Item1 != pair.Item2)
{
errorItem = pair; errorItem = pair;
break; break;
} }
if (pair.Item1.EndsWith(":", StringComparison.Ordinal)) { if (pair.Item1.EndsWith(":", StringComparison.Ordinal))
{
lastHeader = pair.Item1; lastHeader = pair.Item1;
} }
} }
b.AppendLine($"Output differs; first difference in line {diffLine}"); b.AppendLine($"Output differs; first difference in line {diffLine}");
if (lastHeader != null) { if (lastHeader != null)
{
b.AppendLine(lastHeader); b.AppendLine(lastHeader);
} }
b.AppendLine($"{outputFileName}.original.out:line {diffLine}"); b.AppendLine($"{outputFileName}.original.out:line {diffLine}");
@ -573,12 +640,18 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
internal static void RepeatOnIOError(Action action, int numTries = 5) internal static void RepeatOnIOError(Action action, int numTries = 5)
{ {
for (int i = 0; i < numTries - 1; i++) { for (int i = 0; i < numTries - 1; i++)
try { {
try
{
action(); action();
return; return;
} catch (IOException) { }
} catch (UnauthorizedAccessException) { catch (IOException)
{
}
catch (UnauthorizedAccessException)
{
// potential virus scanner problem // potential virus scanner problem
} }
Thread.Sleep(10); Thread.Sleep(10);

11
ICSharpCode.Decompiler.Tests/ILPrettyTestRunner.cs

@ -20,7 +20,9 @@ using System;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using ICSharpCode.Decompiler.Tests.Helpers; using ICSharpCode.Decompiler.Tests.Helpers;
using NUnit.Framework; using NUnit.Framework;
namespace ICSharpCode.Decompiler.Tests namespace ICSharpCode.Decompiler.Tests
@ -37,8 +39,10 @@ namespace ICSharpCode.Decompiler.Tests
.Where(m => m.GetCustomAttributes(typeof(TestAttribute), false).Any()) .Where(m => m.GetCustomAttributes(typeof(TestAttribute), false).Any())
.Select(m => m.Name) .Select(m => m.Name)
.ToArray(); .ToArray();
foreach (var file in new DirectoryInfo(TestCasePath).EnumerateFiles()) { foreach (var file in new DirectoryInfo(TestCasePath).EnumerateFiles())
if (file.Extension.Equals(".il", StringComparison.OrdinalIgnoreCase)) { {
if (file.Extension.Equals(".il", StringComparison.OrdinalIgnoreCase))
{
var testName = file.Name.Split('.')[0]; var testName = file.Name.Split('.')[0];
Assert.Contains(testName, testNames); Assert.Contains(testName, testNames);
Assert.IsTrue(File.Exists(Path.Combine(TestCasePath, testName + ".cs"))); Assert.IsTrue(File.Exists(Path.Combine(TestCasePath, testName + ".cs")));
@ -243,7 +247,8 @@ namespace ICSharpCode.Decompiler.Tests
static void CopyFSharpCoreDll() static void CopyFSharpCoreDll()
{ {
lock (copyLock) { lock (copyLock)
{
if (File.Exists(Path.Combine(TestCasePath, "FSharp.Core.dll"))) if (File.Exists(Path.Combine(TestCasePath, "FSharp.Core.dll")))
return; return;
string fsharpCoreDll = Path.Combine(TestCasePath, "..\\..\\..\\ILSpy-tests\\FSharp\\FSharp.Core.dll"); string fsharpCoreDll = Path.Combine(TestCasePath, "..\\..\\..\\ILSpy-tests\\FSharp\\FSharp.Core.dll");

5
ICSharpCode.Decompiler.Tests/Output/CSharpAmbienceTests.cs

@ -19,11 +19,13 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using ICSharpCode.Decompiler.CSharp.OutputVisitor; using ICSharpCode.Decompiler.CSharp.OutputVisitor;
using ICSharpCode.Decompiler.Output; using ICSharpCode.Decompiler.Output;
using ICSharpCode.Decompiler.Tests.TypeSystem; using ICSharpCode.Decompiler.Tests.TypeSystem;
using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.TypeSystem.Implementation; using ICSharpCode.Decompiler.TypeSystem.Implementation;
using NUnit.Framework; using NUnit.Framework;
using static ICSharpCode.Decompiler.Output.ConversionFlags; using static ICSharpCode.Decompiler.Output.ConversionFlags;
@ -47,7 +49,8 @@ namespace ICSharpCode.Decompiler.Tests.Output
ITypeDefinition GetDefinition(Type type) ITypeDefinition GetDefinition(Type type)
{ {
if (type == null) { if (type == null)
{
throw new ArgumentNullException(nameof(type)); throw new ArgumentNullException(nameof(type));
} }

18
ICSharpCode.Decompiler.Tests/PdbGenerationTestRunner.cs

@ -6,14 +6,17 @@ using System.Reflection.PortableExecutable;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Text; using System.Text;
using System.Xml.Linq; using System.Xml.Linq;
using ICSharpCode.Decompiler.CSharp; using ICSharpCode.Decompiler.CSharp;
using ICSharpCode.Decompiler.CSharp.OutputVisitor; using ICSharpCode.Decompiler.CSharp.OutputVisitor;
using ICSharpCode.Decompiler.DebugInfo; using ICSharpCode.Decompiler.DebugInfo;
using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.Tests.Helpers; using ICSharpCode.Decompiler.Tests.Helpers;
using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem;
using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp;
using Microsoft.DiaSymReader.Tools; using Microsoft.DiaSymReader.Tools;
using NUnit.Framework; using NUnit.Framework;
namespace ICSharpCode.Decompiler.Tests namespace ICSharpCode.Decompiler.Tests
@ -58,17 +61,21 @@ namespace ICSharpCode.Decompiler.Tests
var moduleDefinition = new PEFile(peFileName); var moduleDefinition = new PEFile(peFileName);
var resolver = new UniversalAssemblyResolver(peFileName, false, moduleDefinition.Reader.DetectTargetFrameworkId(), PEStreamOptions.PrefetchEntireImage); var resolver = new UniversalAssemblyResolver(peFileName, false, moduleDefinition.Reader.DetectTargetFrameworkId(), PEStreamOptions.PrefetchEntireImage);
var decompiler = new CSharpDecompiler(moduleDefinition, resolver, new DecompilerSettings()); var decompiler = new CSharpDecompiler(moduleDefinition, resolver, new DecompilerSettings());
using (FileStream pdbStream = File.Open(Path.Combine(TestCasePath, testName + ".pdb"), FileMode.OpenOrCreate, FileAccess.ReadWrite)) { using (FileStream pdbStream = File.Open(Path.Combine(TestCasePath, testName + ".pdb"), FileMode.OpenOrCreate, FileAccess.ReadWrite))
{
pdbStream.SetLength(0); pdbStream.SetLength(0);
PortablePdbWriter.WritePdb(moduleDefinition, decompiler, new DecompilerSettings(), pdbStream, noLogo: true); PortablePdbWriter.WritePdb(moduleDefinition, decompiler, new DecompilerSettings(), pdbStream, noLogo: true);
pdbStream.Position = 0; pdbStream.Position = 0;
using (Stream peStream = File.OpenRead(peFileName)) using (Stream peStream = File.OpenRead(peFileName))
using (Stream expectedPdbStream = File.OpenRead(pdbFileName)) { using (Stream expectedPdbStream = File.OpenRead(pdbFileName))
using (StreamWriter writer = new StreamWriter(Path.ChangeExtension(pdbFileName, ".xml"), false, Encoding.UTF8)) { {
using (StreamWriter writer = new StreamWriter(Path.ChangeExtension(pdbFileName, ".xml"), false, Encoding.UTF8))
{
PdbToXmlConverter.ToXml(writer, expectedPdbStream, peStream, options); PdbToXmlConverter.ToXml(writer, expectedPdbStream, peStream, options);
} }
peStream.Position = 0; peStream.Position = 0;
using (StreamWriter writer = new StreamWriter(Path.ChangeExtension(xmlFile, ".generated.xml"), false, Encoding.UTF8)) { using (StreamWriter writer = new StreamWriter(Path.ChangeExtension(xmlFile, ".generated.xml"), false, Encoding.UTF8))
{
PdbToXmlConverter.ToXml(writer, pdbStream, peStream, options); PdbToXmlConverter.ToXml(writer, pdbStream, peStream, options);
} }
} }
@ -83,7 +90,8 @@ namespace ICSharpCode.Decompiler.Tests
private void ProcessXmlFile(string fileName) private void ProcessXmlFile(string fileName)
{ {
var document = XDocument.Load(fileName); var document = XDocument.Load(fileName);
foreach (var file in document.Descendants("file")) { foreach (var file in document.Descendants("file"))
{
file.Attribute("checksum").Remove(); file.Attribute("checksum").Remove();
file.Attribute("embeddedSourceLength").Remove(); file.Attribute("embeddedSourceLength").Remove();
file.ReplaceNodes(new XCData(file.Value.Replace("\uFEFF", ""))); file.ReplaceNodes(new XCData(file.Value.Replace("\uFEFF", "")));

20
ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs

@ -21,7 +21,9 @@ using System.CodeDom.Compiler;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using ICSharpCode.Decompiler.Tests.Helpers; using ICSharpCode.Decompiler.Tests.Helpers;
using NUnit.Framework; using NUnit.Framework;
namespace ICSharpCode.Decompiler.Tests namespace ICSharpCode.Decompiler.Tests
@ -38,9 +40,11 @@ namespace ICSharpCode.Decompiler.Tests
.Where(m => m.GetCustomAttributes(typeof(TestAttribute), false).Any()) .Where(m => m.GetCustomAttributes(typeof(TestAttribute), false).Any())
.Select(m => m.Name) .Select(m => m.Name)
.ToArray(); .ToArray();
foreach (var file in new DirectoryInfo(TestCasePath).EnumerateFiles()) { foreach (var file in new DirectoryInfo(TestCasePath).EnumerateFiles())
{
if (file.Extension.Equals(".il", StringComparison.OrdinalIgnoreCase) if (file.Extension.Equals(".il", StringComparison.OrdinalIgnoreCase)
|| file.Extension.Equals(".cs", StringComparison.OrdinalIgnoreCase)) { || file.Extension.Equals(".cs", StringComparison.OrdinalIgnoreCase))
{
var testName = file.Name.Split('.')[0]; var testName = file.Name.Split('.')[0];
Assert.Contains(testName, testNames); Assert.Contains(testName, testNames);
} }
@ -533,22 +537,26 @@ namespace ICSharpCode.Decompiler.Tests
{ {
var csFile = Path.Combine(TestCasePath, testName + ".cs"); var csFile = Path.Combine(TestCasePath, testName + ".cs");
var exeFile = Path.Combine(TestCasePath, testName) + Tester.GetSuffix(cscOptions) + ".exe"; var exeFile = Path.Combine(TestCasePath, testName) + Tester.GetSuffix(cscOptions) + ".exe";
if (cscOptions.HasFlag(CompilerOptions.Library)) { if (cscOptions.HasFlag(CompilerOptions.Library))
{
exeFile = Path.ChangeExtension(exeFile, ".dll"); exeFile = Path.ChangeExtension(exeFile, ".dll");
} }
// 1. Compile // 1. Compile
CompilerResults output = null; CompilerResults output = null;
try { try
{
output = Tester.CompileCSharp(csFile, cscOptions, exeFile); output = Tester.CompileCSharp(csFile, cscOptions, exeFile);
} finally { }
finally
{
if (output != null) if (output != null)
output.TempFiles.Delete(); output.TempFiles.Delete();
} }
// 2. Decompile // 2. Decompile
var decompiled = Tester.DecompileCSharp(exeFile, decompilerSettings ?? Tester.GetSettings(cscOptions)); var decompiled = Tester.DecompileCSharp(exeFile, decompilerSettings ?? Tester.GetSettings(cscOptions));
// 3. Compile // 3. Compile
CodeAssert.FilesAreEqual(csFile, decompiled, Tester.GetPreprocessorSymbols(cscOptions).ToArray()); CodeAssert.FilesAreEqual(csFile, decompiled, Tester.GetPreprocessorSymbols(cscOptions).ToArray());
} }

2
ICSharpCode.Decompiler.Tests/ProjectDecompiler/TargetFrameworkTests.cs

@ -17,7 +17,9 @@
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System; using System;
using ICSharpCode.Decompiler.CSharp.ProjectDecompiler; using ICSharpCode.Decompiler.CSharp.ProjectDecompiler;
using NUnit.Framework; using NUnit.Framework;
namespace ICSharpCode.Decompiler.Tests namespace ICSharpCode.Decompiler.Tests

86
ICSharpCode.Decompiler.Tests/RoundtripAssembly.cs

@ -23,12 +23,15 @@ using System.Linq;
using System.Reflection.PortableExecutable; using System.Reflection.PortableExecutable;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading; using System.Threading;
using ICSharpCode.Decompiler.CSharp; using ICSharpCode.Decompiler.CSharp;
using ICSharpCode.Decompiler.CSharp.ProjectDecompiler; using ICSharpCode.Decompiler.CSharp.ProjectDecompiler;
using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.Tests.Helpers; using ICSharpCode.Decompiler.Tests.Helpers;
using Microsoft.Build.Locator; using Microsoft.Build.Locator;
using Microsoft.Win32; using Microsoft.Win32;
using NUnit.Framework; using NUnit.Framework;
namespace ICSharpCode.Decompiler.Tests namespace ICSharpCode.Decompiler.Tests
@ -38,7 +41,7 @@ namespace ICSharpCode.Decompiler.Tests
{ {
public static readonly string TestDir = Path.GetFullPath(Path.Combine(Tester.TestCasePath, "../../ILSpy-tests")); public static readonly string TestDir = Path.GetFullPath(Path.Combine(Tester.TestCasePath, "../../ILSpy-tests"));
static readonly string nunit = Path.Combine(TestDir, "nunit", "nunit3-console.exe"); static readonly string nunit = Path.Combine(TestDir, "nunit", "nunit3-console.exe");
[Test] [Test]
public void Cecil_net45() public void Cecil_net45()
{ {
@ -54,9 +57,12 @@ namespace ICSharpCode.Decompiler.Tests
[Test] [Test]
public void NewtonsoftJson_pcl_debug() public void NewtonsoftJson_pcl_debug()
{ {
try { try
{
RunWithTest("Newtonsoft.Json-pcl-debug", "Newtonsoft.Json.dll", "Newtonsoft.Json.Tests.dll", useOldProjectFormat: true); RunWithTest("Newtonsoft.Json-pcl-debug", "Newtonsoft.Json.dll", "Newtonsoft.Json.Tests.dll", useOldProjectFormat: true);
} catch (CompilationFailedException) { }
catch (CompilationFailedException)
{
Assert.Ignore("Cannot yet re-compile PCL projects."); Assert.Ignore("Cannot yet re-compile PCL projects.");
} }
} }
@ -148,14 +154,16 @@ namespace ICSharpCode.Decompiler.Tests
void RunInternal(string dir, string fileToRoundtrip, Action<string> testAction, LanguageVersion languageVersion, string snkFilePath = null, bool useOldProjectFormat = false) void RunInternal(string dir, string fileToRoundtrip, Action<string> testAction, LanguageVersion languageVersion, string snkFilePath = null, bool useOldProjectFormat = false)
{ {
if (!Directory.Exists(TestDir)) { if (!Directory.Exists(TestDir))
{
Assert.Ignore($"Assembly-roundtrip test ignored: test directory '{TestDir}' needs to be checked out separately." + Environment.NewLine + Assert.Ignore($"Assembly-roundtrip test ignored: test directory '{TestDir}' needs to be checked out separately." + Environment.NewLine +
$"git clone https://github.com/icsharpcode/ILSpy-tests \"{TestDir}\""); $"git clone https://github.com/icsharpcode/ILSpy-tests \"{TestDir}\"");
} }
string inputDir = Path.Combine(TestDir, dir); string inputDir = Path.Combine(TestDir, dir);
string decompiledDir = inputDir + "-decompiled"; string decompiledDir = inputDir + "-decompiled";
string outputDir = inputDir + "-output"; string outputDir = inputDir + "-output";
if (inputDir.EndsWith("TestCases")) { if (inputDir.EndsWith("TestCases"))
{
// make sure output dir names are unique so that we don't get trouble due to parallel test execution // make sure output dir names are unique so that we don't get trouble due to parallel test execution
decompiledDir += Path.GetFileNameWithoutExtension(fileToRoundtrip) + "_" + languageVersion.ToString(); decompiledDir += Path.GetFileNameWithoutExtension(fileToRoundtrip) + "_" + languageVersion.ToString();
outputDir += Path.GetFileNameWithoutExtension(fileToRoundtrip) + "_" + languageVersion.ToString(); outputDir += Path.GetFileNameWithoutExtension(fileToRoundtrip) + "_" + languageVersion.ToString();
@ -163,16 +171,20 @@ namespace ICSharpCode.Decompiler.Tests
ClearDirectory(decompiledDir); ClearDirectory(decompiledDir);
ClearDirectory(outputDir); ClearDirectory(outputDir);
string projectFile = null; string projectFile = null;
foreach (string file in Directory.EnumerateFiles(inputDir, "*", SearchOption.AllDirectories)) { foreach (string file in Directory.EnumerateFiles(inputDir, "*", SearchOption.AllDirectories))
if (!file.StartsWith(inputDir + Path.DirectorySeparatorChar, StringComparison.OrdinalIgnoreCase)) { {
if (!file.StartsWith(inputDir + Path.DirectorySeparatorChar, StringComparison.OrdinalIgnoreCase))
{
Assert.Fail($"Unexpected file name: {file}"); Assert.Fail($"Unexpected file name: {file}");
} }
string relFile = file.Substring(inputDir.Length + 1); string relFile = file.Substring(inputDir.Length + 1);
Directory.CreateDirectory(Path.Combine(outputDir, Path.GetDirectoryName(relFile))); Directory.CreateDirectory(Path.Combine(outputDir, Path.GetDirectoryName(relFile)));
if (relFile.Equals(fileToRoundtrip, StringComparison.OrdinalIgnoreCase)) { if (relFile.Equals(fileToRoundtrip, StringComparison.OrdinalIgnoreCase))
{
Console.WriteLine($"Decompiling {fileToRoundtrip}..."); Console.WriteLine($"Decompiling {fileToRoundtrip}...");
Stopwatch w = Stopwatch.StartNew(); Stopwatch w = Stopwatch.StartNew();
using (var fileStream = new FileStream(file, FileMode.Open, FileAccess.Read)) { using (var fileStream = new FileStream(file, FileMode.Open, FileAccess.Read))
{
PEFile module = new PEFile(file, fileStream, PEStreamOptions.PrefetchEntireImage); PEFile module = new PEFile(file, fileStream, PEStreamOptions.PrefetchEntireImage);
var resolver = new TestAssemblyResolver(file, inputDir, module.Reader.DetectTargetFrameworkId()); var resolver = new TestAssemblyResolver(file, inputDir, module.Reader.DetectTargetFrameworkId());
resolver.AddSearchDirectory(inputDir); resolver.AddSearchDirectory(inputDir);
@ -182,25 +194,29 @@ namespace ICSharpCode.Decompiler.Tests
var projectGuid = Guid.Parse("{127C83E4-4587-4CF9-ADCA-799875F3DFE6}"); var projectGuid = Guid.Parse("{127C83E4-4587-4CF9-ADCA-799875F3DFE6}");
var settings = new DecompilerSettings(languageVersion); var settings = new DecompilerSettings(languageVersion);
if (useOldProjectFormat) { if (useOldProjectFormat)
{
settings.UseSdkStyleProjectFormat = false; settings.UseSdkStyleProjectFormat = false;
} }
var decompiler = new TestProjectDecompiler(projectGuid, resolver, settings); var decompiler = new TestProjectDecompiler(projectGuid, resolver, settings);
if (snkFilePath != null) { if (snkFilePath != null)
{
decompiler.StrongNameKeyFile = Path.Combine(inputDir, snkFilePath); decompiler.StrongNameKeyFile = Path.Combine(inputDir, snkFilePath);
} }
decompiler.DecompileProject(module, decompiledDir); decompiler.DecompileProject(module, decompiledDir);
Console.WriteLine($"Decompiled {fileToRoundtrip} in {w.Elapsed.TotalSeconds:f2}"); Console.WriteLine($"Decompiled {fileToRoundtrip} in {w.Elapsed.TotalSeconds:f2}");
projectFile = Path.Combine(decompiledDir, module.Name + ".csproj"); projectFile = Path.Combine(decompiledDir, module.Name + ".csproj");
} }
} else { }
else
{
File.Copy(file, Path.Combine(outputDir, relFile)); File.Copy(file, Path.Combine(outputDir, relFile));
} }
} }
Assert.IsNotNull(projectFile, $"Could not find {fileToRoundtrip}"); Assert.IsNotNull(projectFile, $"Could not find {fileToRoundtrip}");
Compile(projectFile, outputDir); Compile(projectFile, outputDir);
testAction(outputDir); testAction(outputDir);
} }
@ -208,19 +224,25 @@ namespace ICSharpCode.Decompiler.Tests
static void ClearDirectory(string dir) static void ClearDirectory(string dir)
{ {
Directory.CreateDirectory(dir); Directory.CreateDirectory(dir);
foreach (string subdir in Directory.EnumerateDirectories(dir)) { foreach (string subdir in Directory.EnumerateDirectories(dir))
for (int attempt = 0; ; attempt++) { {
try { for (int attempt = 0; ; attempt++)
{
try
{
Directory.Delete(subdir, true); Directory.Delete(subdir, true);
break; break;
} catch (IOException) { }
catch (IOException)
{
if (attempt >= 10) if (attempt >= 10)
throw; throw;
Thread.Sleep(100); Thread.Sleep(100);
} }
} }
} }
foreach (string file in Directory.EnumerateFiles(dir)) { foreach (string file in Directory.EnumerateFiles(dir))
{
File.Delete(file); File.Delete(file);
} }
} }
@ -228,9 +250,9 @@ namespace ICSharpCode.Decompiler.Tests
static string FindMSBuild() static string FindMSBuild()
{ {
string vsPath = MSBuildLocator.QueryVisualStudioInstances(new VisualStudioInstanceQueryOptions { DiscoveryTypes = DiscoveryType.VisualStudioSetup }) string vsPath = MSBuildLocator.QueryVisualStudioInstances(new VisualStudioInstanceQueryOptions { DiscoveryTypes = DiscoveryType.VisualStudioSetup })
.OrderByDescending(i => i.Version) .OrderByDescending(i => i.Version)
.FirstOrDefault() .FirstOrDefault()
?.MSBuildPath; ?.MSBuildPath;
if (vsPath == null) if (vsPath == null)
throw new InvalidOperationException("Could not find MSBuild"); throw new InvalidOperationException("Could not find MSBuild");
return Path.Combine(vsPath, "msbuild.exe"); return Path.Combine(vsPath, "msbuild.exe");
@ -247,16 +269,20 @@ namespace ICSharpCode.Decompiler.Tests
info.EnvironmentVariables.Remove("Configuration"); info.EnvironmentVariables.Remove("Configuration");
info.EnvironmentVariables.Remove("Platform"); info.EnvironmentVariables.Remove("Platform");
Console.WriteLine($"\"{info.FileName}\" {info.Arguments}"); Console.WriteLine($"\"{info.FileName}\" {info.Arguments}");
using (var p = Process.Start(info)) { using (var p = Process.Start(info))
{
Regex errorRegex = new Regex(@"^[\w\d.\\-]+\(\d+,\d+\):"); Regex errorRegex = new Regex(@"^[\w\d.\\-]+\(\d+,\d+\):");
string suffix = $" [{projectFile}]"; string suffix = $" [{projectFile}]";
string line; string line;
while ((line = p.StandardOutput.ReadLine()) != null) { while ((line = p.StandardOutput.ReadLine()) != null)
if (line.EndsWith(suffix, StringComparison.OrdinalIgnoreCase)) { {
if (line.EndsWith(suffix, StringComparison.OrdinalIgnoreCase))
{
line = line.Substring(0, line.Length - suffix.Length); line = line.Substring(0, line.Length - suffix.Length);
} }
Match m = errorRegex.Match(line); Match m = errorRegex.Match(line);
if (m.Success) { if (m.Success)
{
// Make path absolute so that it gets hyperlinked // Make path absolute so that it gets hyperlinked
line = Path.GetDirectoryName(projectFile) + Path.DirectorySeparatorChar + line; line = Path.GetDirectoryName(projectFile) + Path.DirectorySeparatorChar + line;
} }
@ -267,7 +293,7 @@ namespace ICSharpCode.Decompiler.Tests
throw new CompilationFailedException($"Compilation of {Path.GetFileName(projectFile)} failed"); throw new CompilationFailedException($"Compilation of {Path.GetFileName(projectFile)} failed");
} }
} }
static void RunTest(string outputDir, string fileToTest) static void RunTest(string outputDir, string fileToTest)
{ {
var info = new ProcessStartInfo(nunit); var info = new ProcessStartInfo(nunit);
@ -277,9 +303,11 @@ namespace ICSharpCode.Decompiler.Tests
info.UseShellExecute = false; info.UseShellExecute = false;
info.RedirectStandardOutput = true; info.RedirectStandardOutput = true;
Console.WriteLine($"\"{info.FileName}\" {info.Arguments}"); Console.WriteLine($"\"{info.FileName}\" {info.Arguments}");
using (var p = Process.Start(info)) { using (var p = Process.Start(info))
{
string line; string line;
while ((line = p.StandardOutput.ReadLine()) != null) { while ((line = p.StandardOutput.ReadLine()) != null)
{
Console.WriteLine(line); Console.WriteLine(line);
} }
p.WaitForExit(); p.WaitForExit();
@ -302,7 +330,7 @@ namespace ICSharpCode.Decompiler.Tests
{ {
} }
} }
class TestRunFailedException : Exception class TestRunFailedException : Exception
{ {
public TestRunFailedException(string message) : base(message) public TestRunFailedException(string message) : base(message)

8
ICSharpCode.Decompiler.Tests/Semantics/ConversionTests.cs

@ -20,21 +20,23 @@ using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable; using System.Collections.Immutable;
using ICSharpCode.Decompiler.CSharp.Resolver; using ICSharpCode.Decompiler.CSharp.Resolver;
using ICSharpCode.Decompiler.Semantics; using ICSharpCode.Decompiler.Semantics;
using ICSharpCode.Decompiler.Tests.TypeSystem; using ICSharpCode.Decompiler.Tests.TypeSystem;
using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.TypeSystem.Implementation; using ICSharpCode.Decompiler.TypeSystem.Implementation;
using NUnit.Framework; using NUnit.Framework;
namespace ICSharpCode.Decompiler.Tests.Semantics namespace ICSharpCode.Decompiler.Tests.Semantics
{ {
// assign short names to the fake reflection types // assign short names to the fake reflection types
using Null = ICSharpCode.Decompiler.TypeSystem.ReflectionHelper.Null; using C = Conversion;
using dynamic = ICSharpCode.Decompiler.TypeSystem.ReflectionHelper.Dynamic; using dynamic = ICSharpCode.Decompiler.TypeSystem.ReflectionHelper.Dynamic;
using nuint = ICSharpCode.Decompiler.TypeSystem.ReflectionHelper.NUInt;
using nint = ICSharpCode.Decompiler.TypeSystem.ReflectionHelper.NInt; using nint = ICSharpCode.Decompiler.TypeSystem.ReflectionHelper.NInt;
using C = Conversion; using nuint = ICSharpCode.Decompiler.TypeSystem.ReflectionHelper.NUInt;
using Null = ICSharpCode.Decompiler.TypeSystem.ReflectionHelper.Null;
[TestFixture, Parallelizable(ParallelScope.All)] [TestFixture, Parallelizable(ParallelScope.All)]
public unsafe class ConversionTest public unsafe class ConversionTest

8
ICSharpCode.Decompiler.Tests/Semantics/ExplicitConversionTest.cs

@ -19,17 +19,19 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using ICSharpCode.Decompiler.CSharp.Resolver; using ICSharpCode.Decompiler.CSharp.Resolver;
using ICSharpCode.Decompiler.Semantics; using ICSharpCode.Decompiler.Semantics;
using ICSharpCode.Decompiler.Tests.TypeSystem; using ICSharpCode.Decompiler.Tests.TypeSystem;
using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.TypeSystem.Implementation; using ICSharpCode.Decompiler.TypeSystem.Implementation;
using NUnit.Framework; using NUnit.Framework;
namespace ICSharpCode.Decompiler.Tests.Semantics namespace ICSharpCode.Decompiler.Tests.Semantics
{ {
using dynamic = ICSharpCode.Decompiler.TypeSystem.ReflectionHelper.Dynamic;
using C = Conversion; using C = Conversion;
using dynamic = ICSharpCode.Decompiler.TypeSystem.ReflectionHelper.Dynamic;
[TestFixture, Parallelizable(ParallelScope.All)] [TestFixture, Parallelizable(ParallelScope.All)]
public class ExplicitConversionsTest public class ExplicitConversionsTest
@ -40,8 +42,8 @@ namespace ICSharpCode.Decompiler.Tests.Semantics
[OneTimeSetUp] [OneTimeSetUp]
public void SetUp() public void SetUp()
{ {
compilation = new SimpleCompilation(TypeSystemLoaderTests.TestAssembly, compilation = new SimpleCompilation(TypeSystemLoaderTests.TestAssembly,
TypeSystemLoaderTests.Mscorlib, TypeSystemLoaderTests.Mscorlib,
TypeSystemLoaderTests.SystemCore); TypeSystemLoaderTests.SystemCore);
conversions = new CSharpConversions(compilation); conversions = new CSharpConversions(compilation);
} }

18
ICSharpCode.Decompiler.Tests/Semantics/OverloadResolutionTests.cs

@ -20,11 +20,13 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Linq.Expressions; using System.Linq.Expressions;
using ICSharpCode.Decompiler.CSharp.Resolver; using ICSharpCode.Decompiler.CSharp.Resolver;
using ICSharpCode.Decompiler.Semantics; using ICSharpCode.Decompiler.Semantics;
using ICSharpCode.Decompiler.Tests.TypeSystem; using ICSharpCode.Decompiler.Tests.TypeSystem;
using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.TypeSystem.Implementation; using ICSharpCode.Decompiler.TypeSystem.Implementation;
using NUnit.Framework; using NUnit.Framework;
namespace ICSharpCode.Decompiler.Tests.Semantics namespace ICSharpCode.Decompiler.Tests.Semantics
@ -37,8 +39,8 @@ namespace ICSharpCode.Decompiler.Tests.Semantics
[OneTimeSetUp] [OneTimeSetUp]
public void SetUp() public void SetUp()
{ {
compilation = new SimpleCompilation(TypeSystemLoaderTests.TestAssembly, compilation = new SimpleCompilation(TypeSystemLoaderTests.TestAssembly,
TypeSystemLoaderTests.Mscorlib, TypeSystemLoaderTests.Mscorlib,
TypeSystemLoaderTests.SystemCore); TypeSystemLoaderTests.SystemCore);
} }
@ -53,7 +55,8 @@ namespace ICSharpCode.Decompiler.Tests.Semantics
var m = new FakeMethod(compilation, SymbolKind.Method); var m = new FakeMethod(compilation, SymbolKind.Method);
m.Name = "Method"; m.Name = "Method";
var parameters = new List<IParameter>(); var parameters = new List<IParameter>();
foreach (var typeOrDefaultValue in parameterTypesOrDefaultValues) { foreach (var typeOrDefaultValue in parameterTypesOrDefaultValues)
{
Type type = typeOrDefaultValue as Type; Type type = typeOrDefaultValue as Type;
if (type != null) if (type != null)
parameters.Add(new DefaultParameter(compilation.FindType(type), string.Empty, owner: m)); parameters.Add(new DefaultParameter(compilation.FindType(type), string.Empty, owner: m));
@ -77,7 +80,7 @@ namespace ICSharpCode.Decompiler.Tests.Semantics
m.Parameters = parameters; m.Parameters = parameters;
return m; return m;
} }
[Test] [Test]
public void PreferIntOverUInt() public void PreferIntOverUInt()
{ {
@ -320,15 +323,16 @@ namespace ICSharpCode.Decompiler.Tests.Semantics
var container = compilation.FindType(typeof(BetterFunctionMemberIsNotTransitiveTestCase)).GetDefinition(); var container = compilation.FindType(typeof(BetterFunctionMemberIsNotTransitiveTestCase)).GetDefinition();
var args = new ResolveResult[] { var args = new ResolveResult[] {
new MockLambda(compilation.FindType(KnownTypeCode.String)) { parameters = { new DefaultParameter(SpecialType.UnknownType, "arg") } } new MockLambda(compilation.FindType(KnownTypeCode.String)) { parameters = { new DefaultParameter(SpecialType.UnknownType, "arg") } }
}; };
OverloadResolution r = new OverloadResolution(compilation, args); OverloadResolution r = new OverloadResolution(compilation, args);
foreach (var method in container.GetMethods(m => m.Name == "Method")) { foreach (var method in container.GetMethods(m => m.Name == "Method"))
{
Assert.AreEqual(OverloadResolutionErrors.None, r.AddCandidate(method)); Assert.AreEqual(OverloadResolutionErrors.None, r.AddCandidate(method));
} }
Assert.AreEqual(container.GetMethods(m => m.Name == "Method").Last(), r.BestCandidate); Assert.AreEqual(container.GetMethods(m => m.Name == "Method").Last(), r.BestCandidate);
} }
class BetterFunctionMemberIsNotTransitiveTestCase class BetterFunctionMemberIsNotTransitiveTestCase

4
ICSharpCode.Decompiler.Tests/TestAssemblyResolver.cs

@ -3,6 +3,7 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Reflection.Metadata; using System.Reflection.Metadata;
using System.Reflection.PortableExecutable; using System.Reflection.PortableExecutable;
using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.Metadata;
namespace ICSharpCode.Decompiler.Tests namespace ICSharpCode.Decompiler.Tests
@ -15,7 +16,8 @@ namespace ICSharpCode.Decompiler.Tests
: base(mainAssemblyFileName, false, targetFramework, PEStreamOptions.PrefetchMetadata, MetadataReaderOptions.ApplyWindowsRuntimeProjections) : base(mainAssemblyFileName, false, targetFramework, PEStreamOptions.PrefetchMetadata, MetadataReaderOptions.ApplyWindowsRuntimeProjections)
{ {
var assemblyNames = new DirectoryInfo(baseDir).EnumerateFiles("*.dll").Select(f => Path.GetFileNameWithoutExtension(f.Name)); var assemblyNames = new DirectoryInfo(baseDir).EnumerateFiles("*.dll").Select(f => Path.GetFileNameWithoutExtension(f.Name));
foreach (var name in assemblyNames) { foreach (var name in assemblyNames)
{
localAssemblies.Add(name); localAssemblies.Add(name);
} }
} }

129
ICSharpCode.Decompiler.Tests/TestCases/Correctness/Async.cs

@ -44,9 +44,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
await AwaitMultipleCatchBlocks(Task.FromResult(1)); await AwaitMultipleCatchBlocks(Task.FromResult(1));
await AwaitMultipleCatchBlocks2(Task.FromResult(1)); await AwaitMultipleCatchBlocks2(Task.FromResult(1));
Console.WriteLine(await AwaitInComplexFinally()); Console.WriteLine(await AwaitInComplexFinally());
try { try
{
await AwaitFinally(Task.FromResult(2)); await AwaitFinally(Task.FromResult(2));
} catch (Exception ex) { }
catch (Exception ex)
{
Console.WriteLine(ex + " caught!"); Console.WriteLine(ex + " caught!");
} }
#endif #endif
@ -75,7 +78,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
byte[] array = new byte[bufferSize]; byte[] array = new byte[bufferSize];
int count; int count;
Console.WriteLine("BeforeLoop"); Console.WriteLine("BeforeLoop");
while ((count = await destination.ReadAsync(array, 0, array.Length)) != 0) { while ((count = await destination.ReadAsync(array, 0, array.Length)) != 0)
{
Console.WriteLine("In Loop after condition!"); Console.WriteLine("In Loop after condition!");
await destination.WriteAsync(array, 0, count); await destination.WriteAsync(array, 0, count);
Console.WriteLine("In Loop after inner await"); Console.WriteLine("In Loop after inner await");
@ -89,7 +93,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
byte[] array = new byte[bufferSize]; byte[] array = new byte[bufferSize];
int count; int count;
Console.WriteLine("Before Loop"); Console.WriteLine("Before Loop");
while ((count = await destination.ReadAsync(array, 0, array.Length).ConfigureAwait(false)) != 0) { while ((count = await destination.ReadAsync(array, 0, array.Length).ConfigureAwait(false)) != 0)
{
Console.WriteLine("Before Inner Await"); Console.WriteLine("Before Inner Await");
await destination.WriteAsync(array, 0, count).ConfigureAwait(false); await destination.WriteAsync(array, 0, count).ConfigureAwait(false);
Console.WriteLine("After Inner Await"); Console.WriteLine("After Inner Await");
@ -101,7 +106,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
{ {
int num = 0; int num = 0;
Console.WriteLine("Before Loop"); Console.WriteLine("Before Loop");
foreach (Task<int> current in elements) { foreach (Task<int> current in elements)
{
Console.WriteLine("Before Inner Await"); Console.WriteLine("Before Inner Await");
num += await current; num += await current;
Console.WriteLine("After Inner Await"); Console.WriteLine("After Inner Await");
@ -112,11 +118,15 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
public async Task TaskMethodWithoutAwaitButWithExceptionHandling() public async Task TaskMethodWithoutAwaitButWithExceptionHandling()
{ {
try { try
using (new StringWriter()) { {
using (new StringWriter())
{
Console.WriteLine("No Await"); Console.WriteLine("No Await");
} }
} catch (Exception) { }
catch (Exception)
{
Console.WriteLine("Crash"); Console.WriteLine("Crash");
} }
} }
@ -124,23 +134,31 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
#if CS60 #if CS60
public async Task AwaitCatch(Task<int> task) public async Task AwaitCatch(Task<int> task)
{ {
try { try
{
Console.WriteLine("Before throw"); Console.WriteLine("Before throw");
throw new Exception(); throw new Exception();
} catch { }
catch
{
Console.WriteLine(await task); Console.WriteLine(await task);
} }
} }
public async Task AwaitMultipleCatchBlocks(Task<int> task) public async Task AwaitMultipleCatchBlocks(Task<int> task)
{ {
try { try
{
Console.WriteLine("Before throw"); Console.WriteLine("Before throw");
throw new Exception(); throw new Exception();
} catch (OutOfMemoryException ex) { }
catch (OutOfMemoryException ex)
{
Console.WriteLine(ex.ToString()); Console.WriteLine(ex.ToString());
Console.WriteLine(await task); Console.WriteLine(await task);
} catch { }
catch
{
Console.WriteLine(await task); Console.WriteLine(await task);
} }
} }
@ -148,25 +166,35 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
public async Task AwaitMultipleCatchBlocks2(Task<int> task) public async Task AwaitMultipleCatchBlocks2(Task<int> task)
{ {
try { try
{
Console.WriteLine("Before throw"); Console.WriteLine("Before throw");
throw new Exception(); throw new Exception();
} catch (OutOfMemoryException ex) { }
catch (OutOfMemoryException ex)
{
Console.WriteLine(ex.ToString()); Console.WriteLine(ex.ToString());
Console.WriteLine(await task); Console.WriteLine(await task);
} catch (InternalBufferOverflowException ex) { }
catch (InternalBufferOverflowException ex)
{
Console.WriteLine(ex.ToString()); Console.WriteLine(ex.ToString());
} catch { }
catch
{
Console.WriteLine(await task); Console.WriteLine(await task);
} }
} }
public async Task AwaitFinally(Task<int> task) public async Task AwaitFinally(Task<int> task)
{ {
try { try
{
Console.WriteLine("Before throw"); Console.WriteLine("Before throw");
throw new Exception(); throw new Exception();
} finally { }
finally
{
Console.WriteLine(await task); Console.WriteLine(await task);
} }
} }
@ -184,9 +212,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
public async Task AwaitWithStack2(Task<int> task) public async Task AwaitWithStack2(Task<int> task)
{ {
if (await this.SimpleBoolTaskMethod()) { if (await this.SimpleBoolTaskMethod())
{
Console.WriteLine("A", 1, await task); Console.WriteLine("A", 1, await task);
} else { }
else
{
int num = 1; int num = 1;
Console.WriteLine("A", 1, num); Console.WriteLine("A", 1, num);
} }
@ -195,11 +226,14 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
#if CS60 #if CS60
public async Task AwaitInCatch(Task<int> task1, Task<int> task2) public async Task AwaitInCatch(Task<int> task1, Task<int> task2)
{ {
try { try
{
Console.WriteLine("Start try"); Console.WriteLine("Start try");
await task1; await task1;
Console.WriteLine("End try"); Console.WriteLine("End try");
} catch (Exception) { }
catch (Exception)
{
Console.WriteLine("Start catch"); Console.WriteLine("Start catch");
await task2; await task2;
Console.WriteLine("End catch"); Console.WriteLine("End catch");
@ -209,11 +243,14 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
public async Task AwaitInFinally(Task<int> task1, Task<int> task2) public async Task AwaitInFinally(Task<int> task1, Task<int> task2)
{ {
try { try
{
Console.WriteLine("Start try"); Console.WriteLine("Start try");
await task1; await task1;
Console.WriteLine("End try"); Console.WriteLine("End try");
} finally { }
finally
{
Console.WriteLine("Start finally"); Console.WriteLine("Start finally");
await task2; await task2;
Console.WriteLine("End finally"); Console.WriteLine("End finally");
@ -224,20 +261,29 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
public static async Task<int> AwaitInComplexFinally() public static async Task<int> AwaitInComplexFinally()
{ {
Console.WriteLine("a"); Console.WriteLine("a");
try { try
{
Console.WriteLine("b"); Console.WriteLine("b");
await Task.Delay(1); await Task.Delay(1);
Console.WriteLine("c"); Console.WriteLine("c");
} catch (Exception ex) { }
catch (Exception ex)
{
await Task.Delay(ex.HResult); await Task.Delay(ex.HResult);
} finally { }
finally
{
Console.WriteLine("d"); Console.WriteLine("d");
int i = 0; int i = 0;
if (Console.CapsLock) { if (Console.CapsLock)
{
i++; i++;
await Task.Delay(i); await Task.Delay(i);
} else { }
while (i < 5) { else
{
while (i < 5)
{
Console.WriteLine("i: " + i); Console.WriteLine("i: " + i);
i++; i++;
} }
@ -250,15 +296,20 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
public async Task AwaitInCatchAndFinally(Task<int> task1, Task<int> task2, Task<int> task3) public async Task AwaitInCatchAndFinally(Task<int> task1, Task<int> task2, Task<int> task3)
{ {
try { try
{
Console.WriteLine("Start try"); Console.WriteLine("Start try");
await task1; await task1;
Console.WriteLine("End try"); Console.WriteLine("End try");
} catch (Exception ex) { }
catch (Exception ex)
{
Console.WriteLine("Start catch"); Console.WriteLine("Start catch");
await task2; await task2;
Console.WriteLine("End catch"); Console.WriteLine("End catch");
} finally { }
finally
{
Console.WriteLine("Start finally"); Console.WriteLine("Start finally");
await task3; await task3;
Console.WriteLine("End finally"); Console.WriteLine("End finally");
@ -268,12 +319,16 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
public async Task<int> AwaitInFinallyInUsing(Task<IDisposable> task1, Task<int> task2, Task<int> task3) public async Task<int> AwaitInFinallyInUsing(Task<IDisposable> task1, Task<int> task2, Task<int> task3)
{ {
using (await task1) { using (await task1)
{
Console.WriteLine("Start using"); Console.WriteLine("Start using");
try { try
{
Console.WriteLine("Before return"); Console.WriteLine("Before return");
return await task2; return await task2;
} finally { }
finally
{
Console.WriteLine("Start finally"); Console.WriteLine("Start finally");
await task3; await task3;
Console.WriteLine("End finally"); Console.WriteLine("End finally");

60
ICSharpCode.Decompiler.Tests/TestCases/Correctness/Capturing.cs

@ -31,7 +31,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
List<Action> actions = new List<Action>(); List<Action> actions = new List<Action>();
int max = 5; int max = 5;
string line; string line;
while (ReadLine(out line, ref max)) { while (ReadLine(out line, ref max))
{
actions.Add(() => Console.WriteLine(line)); actions.Add(() => Console.WriteLine(line));
} }
// line still declared // line still declared
@ -47,7 +48,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
List<Action> actions = new List<Action>(); List<Action> actions = new List<Action>();
int max = 5; int max = 5;
string line; string line;
while (ReadLine(out line, ref max)) { while (ReadLine(out line, ref max))
{
string capture = line; string capture = line;
actions.Add(() => Console.WriteLine(capture)); actions.Add(() => Console.WriteLine(capture));
} }
@ -64,7 +66,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
List<Action> actions = new List<Action>(); List<Action> actions = new List<Action>();
int max = 5; int max = 5;
string line, capture; string line, capture;
while (ReadLine(out line, ref max)) { while (ReadLine(out line, ref max))
{
capture = line; capture = line;
actions.Add(() => Console.WriteLine(capture)); actions.Add(() => Console.WriteLine(capture));
} }
@ -96,16 +99,19 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
Console.WriteLine("OutsideLoop"); Console.WriteLine("OutsideLoop");
var list = new List<int> { 1, 2, 3 }; var list = new List<int> { 1, 2, 3 };
var functions = new List<Func<int>>(); var functions = new List<Func<int>>();
using (var e = list.GetEnumerator()) { using (var e = list.GetEnumerator())
{
int val; // declared outside loop int val; // declared outside loop
// The decompiler cannot convert this to a foreach-loop without // The decompiler cannot convert this to a foreach-loop without
// changing the lambda capture semantics. // changing the lambda capture semantics.
while (e.MoveNext()) { while (e.MoveNext())
{
val = e.Current; val = e.Current;
functions.Add(() => val); functions.Add(() => val);
} }
} }
foreach (var func in functions) { foreach (var func in functions)
{
Console.WriteLine(func()); Console.WriteLine(func());
} }
} }
@ -115,13 +121,16 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
Console.WriteLine("InsideLoop"); Console.WriteLine("InsideLoop");
var list = new List<int> { 1, 2, 3 }; var list = new List<int> { 1, 2, 3 };
var functions = new List<Func<int>>(); var functions = new List<Func<int>>();
using (var e = list.GetEnumerator()) { using (var e = list.GetEnumerator())
while (e.MoveNext()) { {
while (e.MoveNext())
{
int val = e.Current; int val = e.Current;
functions.Add(() => val); functions.Add(() => val);
} }
} }
foreach (var func in functions) { foreach (var func in functions)
{
Console.WriteLine(func()); Console.WriteLine(func());
} }
} }
@ -134,11 +143,13 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
int val; // declared outside loop int val; // declared outside loop
// The decompiler cannot convert this to a foreach-loop without // The decompiler cannot convert this to a foreach-loop without
// changing the lambda capture semantics. // changing the lambda capture semantics.
for (int i = 0; i < array.Length; ++i) { for (int i = 0; i < array.Length; ++i)
{
val = array[i]; val = array[i];
functions.Add(() => val); functions.Add(() => val);
} }
foreach (var func in functions) { foreach (var func in functions)
{
Console.WriteLine(func()); Console.WriteLine(func());
} }
} }
@ -151,12 +162,14 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
int val; // declared outside loop int val; // declared outside loop
// The decompiler can convert this to a foreach-loop, but the 'val' // The decompiler can convert this to a foreach-loop, but the 'val'
// variable must be declared outside. // variable must be declared outside.
for (int i = 0; i < array.Length; ++i) { for (int i = 0; i < array.Length; ++i)
{
int element = array[i]; int element = array[i];
val = element * 2; val = element * 2;
functions.Add(() => val); functions.Add(() => val);
} }
foreach (var func in functions) { foreach (var func in functions)
{
Console.WriteLine(func()); Console.WriteLine(func());
} }
} }
@ -166,12 +179,14 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
Console.WriteLine("InsideLoopOverArray2:"); Console.WriteLine("InsideLoopOverArray2:");
var functions = new List<Func<int>>(); var functions = new List<Func<int>>();
var array = new int[] { 1, 2, 3 }; var array = new int[] { 1, 2, 3 };
for (int i = 0; i < array.Length; ++i) { for (int i = 0; i < array.Length; ++i)
{
int element = array[i]; int element = array[i];
int val = element * 2; int val = element * 2;
functions.Add(() => val); functions.Add(() => val);
} }
foreach (var func in functions) { foreach (var func in functions)
{
Console.WriteLine(func()); Console.WriteLine(func());
} }
} }
@ -187,13 +202,15 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
{ {
Console.WriteLine("NotWhileDueToVariableInsideLoop:"); Console.WriteLine("NotWhileDueToVariableInsideLoop:");
var functions = new List<Func<int>>(); var functions = new List<Func<int>>();
while (true) { while (true)
{
int v; int v;
if ((v = GetVal()) == 0) if ((v = GetVal()) == 0)
break; break;
functions.Add(() => v); functions.Add(() => v);
} }
foreach (var f in functions) { foreach (var f in functions)
{
Console.WriteLine(f()); Console.WriteLine(f());
} }
} }
@ -202,13 +219,15 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
{ {
Console.WriteLine("NotDoWhileDueToVariableInsideLoop:"); Console.WriteLine("NotDoWhileDueToVariableInsideLoop:");
var functions = new List<Func<int>>(); var functions = new List<Func<int>>();
while (true) { while (true)
{
int v = GetVal(); int v = GetVal();
functions.Add(() => v); functions.Add(() => v);
if (v == 0) if (v == 0)
break; break;
} }
foreach (var f in functions) { foreach (var f in functions)
{
Console.WriteLine(f()); Console.WriteLine(f());
} }
} }
@ -216,7 +235,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
public static void Issue1936() public static void Issue1936()
{ {
IEnumerable<object> outerCapture = null; IEnumerable<object> outerCapture = null;
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++)
{
int innerCapture = 0; int innerCapture = 0;
Action a = (delegate { Action a = (delegate {
List<object> list = new List<object>(); List<object> list = new List<object>();

16
ICSharpCode.Decompiler.Tests/TestCases/Correctness/Comparisons.cs

@ -38,7 +38,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
TestFloatOp("!>", (a, b) => !(a > b)); TestFloatOp("!>", (a, b) => !(a > b));
TestFloatOp("!<=", (a, b) => !(a <= b)); TestFloatOp("!<=", (a, b) => !(a <= b));
TestFloatOp("!>=", (a, b) => !(a >= b)); TestFloatOp("!>=", (a, b) => !(a >= b));
TestUInt(0); TestUInt(0);
TestUInt(uint.MaxValue); TestUInt(uint.MaxValue);
TestUShort(0); TestUShort(0);
@ -50,12 +50,14 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
Console.WriteLine(NullIsNot(new OverloadedOperators())); Console.WriteLine(NullIsNot(new OverloadedOperators()));
return 0; return 0;
} }
static void TestFloatOp(string name, Func<float, float, bool> f) static void TestFloatOp(string name, Func<float, float, bool> f)
{ {
float[] vals = { -1, 0, 3, float.PositiveInfinity, float.NaN }; float[] vals = { -1, 0, 3, float.PositiveInfinity, float.NaN };
for (int i = 0; i < vals.Length; i++) { for (int i = 0; i < vals.Length; i++)
for (int j = 0; j < vals.Length; j++) { {
for (int j = 0; j < vals.Length; j++)
{
Console.WriteLine("Float: {0} {1} {2:r} = {3}", Console.WriteLine("Float: {0} {1} {2:r} = {3}",
vals[i].ToString("r", CultureInfo.InvariantCulture), vals[i].ToString("r", CultureInfo.InvariantCulture),
name, name,
@ -64,12 +66,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
} }
} }
} }
static T Id<T>(T arg) static T Id<T>(T arg)
{ {
return arg; return arg;
} }
static void TestUShort(ushort i) static void TestUShort(ushort i)
{ {
Console.WriteLine("ushort: {0} == ushort.MaxValue = {1}", i, i == ushort.MaxValue); Console.WriteLine("ushort: {0} == ushort.MaxValue = {1}", i, i == ushort.MaxValue);
@ -77,7 +79,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
Console.WriteLine("ushort: {0} == Id<short>(-1) = {1}", i, i == Id<short>(-1)); Console.WriteLine("ushort: {0} == Id<short>(-1) = {1}", i, i == Id<short>(-1));
Console.WriteLine("ushort: {0} == 0x1ffff = {1}", i, i == 0x1ffff); Console.WriteLine("ushort: {0} == 0x1ffff = {1}", i, i == 0x1ffff);
} }
static void TestUInt(uint i) static void TestUInt(uint i)
{ {
Console.WriteLine("uint: {0} == uint.MaxValue = {1}", i, i == uint.MaxValue); Console.WriteLine("uint: {0} == uint.MaxValue = {1}", i, i == uint.MaxValue);

22
ICSharpCode.Decompiler.Tests/TestCases/Correctness/CompoundAssignment.cs

@ -50,11 +50,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
static int instanceCount; static int instanceCount;
int instanceNumber = ++instanceCount; int instanceNumber = ++instanceCount;
int instanceField; int instanceField;
public int InstanceProperty public int InstanceProperty {
{
get { get {
Console.WriteLine("In {0}.get_InstanceProperty", instanceNumber); Console.WriteLine("In {0}.get_InstanceProperty", instanceNumber);
return instanceField; return instanceField;
@ -67,8 +66,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
static int staticField; static int staticField;
public static int StaticProperty public static int StaticProperty {
{
get { get {
Console.WriteLine("In get_StaticProperty"); Console.WriteLine("In get_StaticProperty");
return staticField; return staticField;
@ -203,18 +201,24 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
Console.WriteLine("Overflow:"); Console.WriteLine("Overflow:");
ByteProperty = 0; ByteProperty = 0;
ByteProperty = (byte)checked(ByteProperty + 300); ByteProperty = (byte)checked(ByteProperty + 300);
try { try
{
ByteProperty = checked((byte)(ByteProperty + 300)); ByteProperty = checked((byte)(ByteProperty + 300));
} catch (OverflowException) { }
catch (OverflowException)
{
Console.WriteLine("Overflow OK"); Console.WriteLine("Overflow OK");
} }
ByteProperty = 200; ByteProperty = 200;
ByteProperty = (byte)checked(ByteProperty + 100); ByteProperty = (byte)checked(ByteProperty + 100);
ByteProperty = 201; ByteProperty = 201;
try { try
{
ByteProperty = checked((byte)(ByteProperty + 100)); ByteProperty = checked((byte)(ByteProperty + 100));
} catch (OverflowException) { }
catch (OverflowException)
{
Console.WriteLine("Overflow OK"); Console.WriteLine("Overflow OK");
} }
} }

56
ICSharpCode.Decompiler.Tests/TestCases/Correctness/ControlFlow.cs

@ -47,7 +47,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
static void EmptyIf(string input, ref int result) static void EmptyIf(string input, ref int result)
{ {
if (input.Contains("test")) { if (input.Contains("test"))
{
} }
result = result + 1; result = result + 1;
Console.WriteLine("EmptyIf"); Console.WriteLine("EmptyIf");
@ -55,9 +56,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
static void NormalIf(string input, ref int result) static void NormalIf(string input, ref int result)
{ {
if (input.Contains("test")) { if (input.Contains("test"))
{
Console.WriteLine("result"); Console.WriteLine("result");
} else { }
else
{
Console.WriteLine("else"); Console.WriteLine("else");
} }
result = result + 1; result = result + 1;
@ -66,7 +70,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
static void NormalIf2(string input, ref int result) static void NormalIf2(string input, ref int result)
{ {
if (input.Contains("test")) { if (input.Contains("test"))
{
Console.WriteLine("result"); Console.WriteLine("result");
} }
result = result + 1; result = result + 1;
@ -75,9 +80,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
static void NormalIf3(string input, ref int result) static void NormalIf3(string input, ref int result)
{ {
if (input.Contains("test")) { if (input.Contains("test"))
{
Console.WriteLine("result"); Console.WriteLine("result");
} else { }
else
{
Console.WriteLine("else"); Console.WriteLine("else");
} }
result = result + 1; result = result + 1;
@ -85,13 +93,17 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
static void Test(string input, ref int result) static void Test(string input, ref int result)
{ {
foreach (char c in input) { foreach (char c in input)
{
Console.Write(c); Console.Write(c);
result = result + 1; result = result + 1;
} }
if (input.Contains("test")) { if (input.Contains("test"))
{
Console.WriteLine("result"); Console.WriteLine("result");
} else { }
else
{
Console.WriteLine("else"); Console.WriteLine("else");
} }
} }
@ -101,8 +113,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
var tens = new[] { 10, 20, 30 }; var tens = new[] { 10, 20, 30 };
var ones = new[] { 1, 2, 3 }; var ones = new[] { 1, 2, 3 };
for (int i = 0; i < tens.Length; i++) { for (int i = 0; i < tens.Length; i++)
for (int j = 0; j < ones.Length; j++) { {
for (int j = 0; j < ones.Length; j++)
{
if (tens[i] + ones[j] == arg) if (tens[i] + ones[j] == arg)
return i; return i;
} }
@ -114,7 +128,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
static void ForeachWithAssignment(IEnumerable<int> inputs) static void ForeachWithAssignment(IEnumerable<int> inputs)
{ {
Console.WriteLine("ForeachWithAssignment"); Console.WriteLine("ForeachWithAssignment");
foreach (int input in inputs) { foreach (int input in inputs)
{
int i = input; int i = input;
if (i < 10) if (i < 10)
i *= 2; i *= 2;
@ -125,11 +140,13 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
static void BreakUnlessContinue(bool b) static void BreakUnlessContinue(bool b)
{ {
Console.WriteLine("BreakUnlessContinue({0})", b); Console.WriteLine("BreakUnlessContinue({0})", b);
for (int i = 0; i < 5; i++) { for (int i = 0; i < 5; i++)
{
if ((i % 3) == 0) if ((i % 3) == 0)
continue; continue;
Console.WriteLine(i); Console.WriteLine(i);
if (b) { if (b)
{
Console.WriteLine("continuing"); Console.WriteLine("continuing");
continue; continue;
} }
@ -154,11 +171,16 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
static string Issue1946() static string Issue1946()
{ {
string obj = "1"; string obj = "1";
try { try
{
obj = "2"; obj = "2";
} catch { }
catch
{
obj = "3"; obj = "3";
} finally { }
finally
{
obj = "4"; obj = "4";
} }
return obj; return obj;

77
ICSharpCode.Decompiler.Tests/TestCases/Correctness/Conversions.cs

@ -19,6 +19,7 @@
// #include "../../../ICSharpCode.Decompiler/Util/CSharpPrimitiveCast.cs" // #include "../../../ICSharpCode.Decompiler/Util/CSharpPrimitiveCast.cs"
using System; using System;
using ICSharpCode.Decompiler.Util; using ICSharpCode.Decompiler.Util;
namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
@ -39,48 +40,48 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
TypeCode.Double, TypeCode.Double,
TypeCode.Decimal TypeCode.Decimal
}; };
static object[] inputValues = { static object[] inputValues = {
'\0', '\0',
'a', 'a',
'\uFFFE', '\uFFFE',
sbyte.MinValue, sbyte.MinValue,
sbyte.MaxValue, sbyte.MaxValue,
(sbyte)-1, (sbyte)-1,
(sbyte)1, (sbyte)1,
byte.MinValue, byte.MinValue,
byte.MaxValue, byte.MaxValue,
(byte)1, (byte)1,
short.MinValue, short.MinValue,
short.MaxValue, short.MaxValue,
(short)-1, (short)-1,
(short)1, (short)1,
ushort.MinValue, ushort.MinValue,
ushort.MaxValue, ushort.MaxValue,
(ushort)1, (ushort)1,
int.MinValue, int.MinValue,
int.MaxValue, int.MaxValue,
(int)-1, (int)-1,
(int)1, (int)1,
uint.MinValue, uint.MinValue,
uint.MaxValue, uint.MaxValue,
(uint)1, (uint)1,
long.MinValue, long.MinValue,
long.MaxValue, long.MaxValue,
(long)-1, (long)-1,
(long)1, (long)1,
ulong.MinValue, ulong.MinValue,
ulong.MaxValue, ulong.MaxValue,
(ulong)1, (ulong)1,
-1.1f, -1.1f,
1.1f, 1.1f,
float.MinValue, float.MinValue,
@ -88,7 +89,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
float.NegativeInfinity, float.NegativeInfinity,
float.PositiveInfinity, float.PositiveInfinity,
float.NaN, float.NaN,
-1.1, -1.1,
1.1, 1.1,
double.MinValue, double.MinValue,
@ -96,64 +97,72 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
double.NegativeInfinity, double.NegativeInfinity,
double.PositiveInfinity, double.PositiveInfinity,
double.NaN, double.NaN,
decimal.MinValue, decimal.MinValue,
decimal.MaxValue, decimal.MaxValue,
decimal.MinusOne, decimal.MinusOne,
decimal.One decimal.One
}; };
static void Main(string[] args) static void Main(string[] args)
{ {
RunTest(checkForOverflow: false); RunTest(checkForOverflow: false);
RunTest(checkForOverflow: true); RunTest(checkForOverflow: true);
Console.WriteLine(ReadZeroTerminatedString("Hello World!".Length)); Console.WriteLine(ReadZeroTerminatedString("Hello World!".Length));
C1.Test(); C1.Test();
} }
static void RunTest(bool checkForOverflow) static void RunTest(bool checkForOverflow)
{ {
string mode = checkForOverflow ? "checked" : "unchecked"; string mode = checkForOverflow ? "checked" : "unchecked";
foreach (object input in inputValues) { foreach (object input in inputValues)
{
string inputType = input.GetType().Name; string inputType = input.GetType().Name;
foreach (var targetType in targetTypes) { foreach (var targetType in targetTypes)
try { {
try
{
object result = CSharpPrimitiveCast.Cast(targetType, input, checkForOverflow); object result = CSharpPrimitiveCast.Cast(targetType, input, checkForOverflow);
Console.WriteLine("{0} ({1})({2}){3} = ({4}){5}", mode, targetType, inputType, input, Console.WriteLine("{0} ({1})({2}){3} = ({4}){5}", mode, targetType, inputType, input,
result.GetType().Name, result); result.GetType().Name, result);
} catch (Exception ex) { }
catch (Exception ex)
{
Console.WriteLine("{0} ({1})({2}){3} = {4}", mode, targetType, inputType, input, Console.WriteLine("{0} ({1})({2}){3} = {4}", mode, targetType, inputType, input,
ex.GetType().Name); ex.GetType().Name);
} }
} }
} }
} }
static object MM(sbyte c) static object MM(sbyte c)
{ {
checked { checked
{
return (UInt64)c; return (UInt64)c;
} }
} }
static string ReadZeroTerminatedString (int length) static string ReadZeroTerminatedString(int length)
{ {
int read = 0; int read = 0;
var buffer = new char [length]; var buffer = new char[length];
var bytes = ReadBytes (length); var bytes = ReadBytes(length);
while (read < length) { while (read < length)
var current = bytes [read]; {
var current = bytes[read];
if (current == 0) if (current == 0)
break; break;
buffer [read++] = (char) current; buffer[read++] = (char)current;
} }
return new string (buffer, 0, read); return new string(buffer, 0, read);
} }
static byte[] ReadBytes(int length) { static byte[] ReadBytes(int length)
{
return System.Text.Encoding.ASCII.GetBytes("Hello World!"); return System.Text.Encoding.ASCII.GetBytes("Hello World!");
} }
} }
@ -176,7 +185,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
{ {
Console.WriteLine(((Type)c).Name); Console.WriteLine(((Type)c).Name);
} }
static Type ChainedImplicitConversions(C2 c) static Type ChainedImplicitConversions(C2 c)
{ {
return (C1)c; return (C1)c;

2
ICSharpCode.Decompiler.Tests/TestCases/Correctness/DecimalFields.cs

@ -29,7 +29,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
public const decimal field2 = decimal.One; public const decimal field2 = decimal.One;
public const decimal field3 = decimal.MaxValue; public const decimal field3 = decimal.MaxValue;
public const decimal field4 = decimal.MinValue; public const decimal field4 = decimal.MinValue;
public static int Main() public static int Main()
{ {
Console.WriteLine(field1); Console.WriteLine(field1);

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

@ -194,10 +194,13 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
public void NullReferenceException_Field_Deconstruction(out int a) public void NullReferenceException_Field_Deconstruction(out int a)
{ {
try { try
{
AssignmentTargets t0 = null; AssignmentTargets t0 = null;
(t0.IntField, a) = GetSource<int, int>(); (t0.IntField, a) = GetSource<int, int>();
} catch (Exception ex) { }
catch (Exception ex)
{
a = 0; a = 0;
Console.WriteLine(ex.GetType().FullName); Console.WriteLine(ex.GetType().FullName);
} }
@ -205,11 +208,14 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
public void NullReferenceException_RefLocalReferencesField_Deconstruction(out int a) public void NullReferenceException_RefLocalReferencesField_Deconstruction(out int a)
{ {
try { try
{
AssignmentTargets t0 = null; AssignmentTargets t0 = null;
ref int i = ref t0.IntField; ref int i = ref t0.IntField;
(i, a) = GetSource<int, int>(); (i, a) = GetSource<int, int>();
} catch (Exception ex) { }
catch (Exception ex)
{
a = 0; a = 0;
Console.WriteLine(ex.GetType().FullName); Console.WriteLine(ex.GetType().FullName);
} }
@ -217,10 +223,13 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
public void NullReferenceException_RefLocalReferencesArrayElement_Deconstruction(out int a, int[] arr) public void NullReferenceException_RefLocalReferencesArrayElement_Deconstruction(out int a, int[] arr)
{ {
try { try
{
ref int i = ref arr[0]; ref int i = ref arr[0];
(i, a) = GetSource<int, int>(); (i, a) = GetSource<int, int>();
} catch (Exception ex) { }
catch (Exception ex)
{
a = 0; a = 0;
Console.WriteLine(ex.GetType().FullName); Console.WriteLine(ex.GetType().FullName);
} }
@ -238,7 +247,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
public void DeconstructTupleListForEachSameVar(List<(string, string)> tuples) public void DeconstructTupleListForEachSameVar(List<(string, string)> tuples)
{ {
Console.WriteLine("DeconstructTupleListForEachSameVar:"); Console.WriteLine("DeconstructTupleListForEachSameVar:");
foreach (var tuple in tuples) { foreach (var tuple in tuples)
{
string a; string a;
a = tuple.Item1; a = tuple.Item1;
a = tuple.Item2; a = tuple.Item2;

3
ICSharpCode.Decompiler.Tests/TestCases/Correctness/FloatingPointArithmetic.cs

@ -91,7 +91,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
static void CxAssert(bool v) static void CxAssert(bool v)
{ {
if (!v) { if (!v)
{
throw new InvalidOperationException(); throw new InvalidOperationException();
} }
} }

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

@ -37,18 +37,18 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
{ {
return default(T); return default(T);
} }
public static void TestGenericParam<T>() public static void TestGenericParam<T>()
{ {
Console.WriteLine(typeof(T)); Console.WriteLine(typeof(T));
} }
public static void TestGenericParam<T1, T2>() public static void TestGenericParam<T1, T2>()
{ {
Console.WriteLine(typeof(T1) + " " + typeof(T2)); Console.WriteLine(typeof(T1) + " " + typeof(T2));
} }
} }
class GenericClass<T> class GenericClass<T>
{ {
public void M(out GenericClass<T> self) public void M(out GenericClass<T> self)

60
ICSharpCode.Decompiler.Tests/TestCases/Correctness/InitializerTests.cs

@ -52,36 +52,30 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
private class Data private class Data
{ {
public List<InitializerTests.MyEnum2> FieldList = new List<InitializerTests.MyEnum2>(); public List<InitializerTests.MyEnum2> FieldList = new List<InitializerTests.MyEnum2>();
public InitializerTests.MyEnum a public InitializerTests.MyEnum a {
{
get; get;
set; set;
} }
public InitializerTests.MyEnum b public InitializerTests.MyEnum b {
{
get; get;
set; set;
} }
public List<InitializerTests.MyEnum2> PropertyList public List<InitializerTests.MyEnum2> PropertyList {
{
get; get;
set; set;
} }
public InitializerTests.Data MoreData public InitializerTests.Data MoreData {
{
get; get;
set; set;
} }
public InitializerTests.StructData NestedStruct public InitializerTests.StructData NestedStruct {
{
get; get;
set; set;
} }
public InitializerTests.Data this[int i] public InitializerTests.Data this[int i] {
{
get { get {
return null; return null;
} }
@ -99,14 +93,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
private struct StructData private struct StructData
{ {
public int Field; public int Field;
public int Property public int Property {
{
get; get;
set; set;
} }
public InitializerTests.Data MoreData public InitializerTests.Data MoreData {
{
get; get;
set; set;
} }
@ -191,8 +183,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
public static void ObjectInitializer() public static void ObjectInitializer()
{ {
InitializerTests.X(InitializerTests.Y(), new InitializerTests.Data InitializerTests.X(InitializerTests.Y(), new InitializerTests.Data {
{
a = InitializerTests.MyEnum.a a = InitializerTests.MyEnum.a
}); });
} }
@ -206,8 +197,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
public static void ObjectInitializerAssignCollectionToField() public static void ObjectInitializerAssignCollectionToField()
{ {
InitializerTests.X(InitializerTests.Y(), new InitializerTests.Data InitializerTests.X(InitializerTests.Y(), new InitializerTests.Data {
{
a = InitializerTests.MyEnum.a, a = InitializerTests.MyEnum.a,
FieldList = new List<InitializerTests.MyEnum2> FieldList = new List<InitializerTests.MyEnum2>
{ {
@ -219,8 +209,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
public static void ObjectInitializerAddToCollectionInField() public static void ObjectInitializerAddToCollectionInField()
{ {
InitializerTests.X(InitializerTests.Y(), new InitializerTests.Data InitializerTests.X(InitializerTests.Y(), new InitializerTests.Data {
{
a = InitializerTests.MyEnum.a, a = InitializerTests.MyEnum.a,
FieldList = FieldList =
{ {
@ -232,8 +221,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
public static void ObjectInitializerAssignCollectionToProperty() public static void ObjectInitializerAssignCollectionToProperty()
{ {
InitializerTests.X(InitializerTests.Y(), new InitializerTests.Data InitializerTests.X(InitializerTests.Y(), new InitializerTests.Data {
{
a = InitializerTests.MyEnum.a, a = InitializerTests.MyEnum.a,
PropertyList = new List<InitializerTests.MyEnum2> PropertyList = new List<InitializerTests.MyEnum2>
{ {
@ -245,8 +233,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
public static void ObjectInitializerAddToCollectionInProperty() public static void ObjectInitializerAddToCollectionInProperty()
{ {
InitializerTests.X(InitializerTests.Y(), new InitializerTests.Data InitializerTests.X(InitializerTests.Y(), new InitializerTests.Data {
{
a = InitializerTests.MyEnum.a, a = InitializerTests.MyEnum.a,
PropertyList = PropertyList =
{ {
@ -258,8 +245,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
public static void ObjectInitializerWithInitializationOfNestedObjects() public static void ObjectInitializerWithInitializationOfNestedObjects()
{ {
InitializerTests.X(InitializerTests.Y(), new InitializerTests.Data InitializerTests.X(InitializerTests.Y(), new InitializerTests.Data {
{
MoreData = MoreData =
{ {
a = InitializerTests.MyEnum.a, a = InitializerTests.MyEnum.a,
@ -342,8 +328,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
public static void StructInitializer_DefaultConstructor() public static void StructInitializer_DefaultConstructor()
{ {
InitializerTests.X(InitializerTests.Y(), new InitializerTests.StructData InitializerTests.X(InitializerTests.Y(), new InitializerTests.StructData {
{
Field = 1, Field = 1,
Property = 2 Property = 2
}); });
@ -359,8 +344,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
public static void StructInitializer_ExplicitConstructor() public static void StructInitializer_ExplicitConstructor()
{ {
InitializerTests.X(InitializerTests.Y(), new InitializerTests.StructData(0) InitializerTests.X(InitializerTests.Y(), new InitializerTests.StructData(0) {
{
Field = 1, Field = 1,
Property = 2 Property = 2
}); });
@ -368,8 +352,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
public static void StructInitializerWithInitializationOfNestedObjects() public static void StructInitializerWithInitializationOfNestedObjects()
{ {
InitializerTests.X(InitializerTests.Y(), new InitializerTests.StructData InitializerTests.X(InitializerTests.Y(), new InitializerTests.StructData {
{
MoreData = MoreData =
{ {
a = InitializerTests.MyEnum.a, a = InitializerTests.MyEnum.a,
@ -384,10 +367,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
public static void StructInitializerWithinObjectInitializer() public static void StructInitializerWithinObjectInitializer()
{ {
InitializerTests.X(InitializerTests.Y(), new InitializerTests.Data InitializerTests.X(InitializerTests.Y(), new InitializerTests.Data {
{ NestedStruct = new InitializerTests.StructData(2) {
NestedStruct = new InitializerTests.StructData(2)
{
Field = 1, Field = 1,
Property = 2 Property = 2
} }
@ -435,7 +416,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
int num = 0; int num = 0;
for (int i = 0; i < 2; i++) { for (int i = 0; i < 2; i++)
{
if (num < 10) if (num < 10)
items.SetItem(num, Item(string.Empty, new Data { Obj = null })); items.SetItem(num, Item(string.Empty, new Data { Obj = null }));
} }

15
ICSharpCode.Decompiler.Tests/TestCases/Correctness/LINQRaytracer.cs

@ -1,8 +1,8 @@
// This test case is taken from https://blogs.msdn.microsoft.com/lukeh/2007/10/01/taking-linq-to-objects-to-extremes-a-fully-linqified-raytracer/ // This test case is taken from https://blogs.msdn.microsoft.com/lukeh/2007/10/01/taking-linq-to-objects-to-extremes-a-fully-linqified-raytracer/
using System.Linq;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
namespace RayTracer namespace RayTracer
{ {
@ -333,13 +333,17 @@ namespace RayTracer
Vector eo = Vector.Minus(Center, ray.Start); Vector eo = Vector.Minus(Center, ray.Start);
double v = Vector.Dot(eo, ray.Dir); double v = Vector.Dot(eo, ray.Dir);
double dist; double dist;
if (v < 0) { if (v < 0)
{
dist = 0; dist = 0;
} else { }
else
{
double disc = Math.Pow(Radius, 2) - (Vector.Dot(eo, eo) - Math.Pow(v, 2)); double disc = Math.Pow(Radius, 2) - (Vector.Dot(eo, eo) - Math.Pow(v, 2));
dist = disc < 0 ? 0 : v - Math.Sqrt(disc); dist = disc < 0 ? 0 : v - Math.Sqrt(disc);
} }
if (dist == 0) return null; if (dist == 0)
return null;
return new ISect() { return new ISect() {
Thing = this, Thing = this,
Ray = ray, Ray = ray,
@ -361,7 +365,8 @@ namespace RayTracer
public override ISect Intersect(Ray ray) public override ISect Intersect(Ray ray)
{ {
double denom = Vector.Dot(Norm, ray.Dir); double denom = Vector.Dot(Norm, ray.Dir);
if (denom > 0) return null; if (denom > 0)
return null;
return new ISect() { return new ISect() {
Thing = this, Thing = this,
Ray = ray, Ray = ray,

103
ICSharpCode.Decompiler.Tests/TestCases/Correctness/Loops.cs

@ -41,7 +41,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
public bool MoveNext() public bool MoveNext()
{ {
if (next) { if (next)
{
next = false; next = false;
return true; return true;
} }
@ -87,7 +88,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
{ {
int x, y; int x, y;
Console.WriteLine("before for"); Console.WriteLine("before for");
for (x = y = 0; x < 10; x++) { for (x = y = 0; x < 10; x++)
{
y++; y++;
Console.WriteLine("x = " + x + ", y = " + y); Console.WriteLine("x = " + x + ", y = " + y);
} }
@ -97,11 +99,13 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
public static void DoubleForEachWithSameVariable(IEnumerable<string> enumerable) public static void DoubleForEachWithSameVariable(IEnumerable<string> enumerable)
{ {
Console.WriteLine("DoubleForEachWithSameVariable:"); Console.WriteLine("DoubleForEachWithSameVariable:");
foreach (string current in enumerable) { foreach (string current in enumerable)
{
Console.WriteLine(current.ToLower()); Console.WriteLine(current.ToLower());
} }
Console.WriteLine("after first loop"); Console.WriteLine("after first loop");
foreach (string current in enumerable) { foreach (string current in enumerable)
{
Console.WriteLine(current.ToUpper()); Console.WriteLine(current.ToUpper());
} }
Console.WriteLine("after second loop"); Console.WriteLine("after second loop");
@ -111,8 +115,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
{ {
Console.WriteLine("ForeachWithNameCollision:"); Console.WriteLine("ForeachWithNameCollision:");
int current; int current;
using (IEnumerator<int> enumerator = inputs.GetEnumerator()) { using (IEnumerator<int> enumerator = inputs.GetEnumerator())
while (enumerator.MoveNext()) { {
while (enumerator.MoveNext())
{
current = enumerator.Current; current = enumerator.Current;
Console.WriteLine(current); Console.WriteLine(current);
} }
@ -125,8 +131,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
{ {
Console.WriteLine("ForeachExceptForContinuedUse"); Console.WriteLine("ForeachExceptForContinuedUse");
int num = 0; int num = 0;
using (IEnumerator<int> enumerator = inputs.GetEnumerator()) { using (IEnumerator<int> enumerator = inputs.GetEnumerator())
while (enumerator.MoveNext()) { {
while (enumerator.MoveNext())
{
num = enumerator.Current; num = enumerator.Current;
Console.WriteLine(num); Console.WriteLine(num);
} }
@ -138,15 +146,20 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
{ {
Console.WriteLine("NonGenericForeachWithReturnFallback:"); Console.WriteLine("NonGenericForeachWithReturnFallback:");
IEnumerator enumerator = e.GetEnumerator(); IEnumerator enumerator = e.GetEnumerator();
try { try
{
Console.WriteLine("MoveNext"); Console.WriteLine("MoveNext");
if (enumerator.MoveNext()) { if (enumerator.MoveNext())
{
object current = enumerator.Current; object current = enumerator.Current;
Console.WriteLine("current: " + current); Console.WriteLine("current: " + current);
} }
} finally { }
finally
{
IDisposable disposable = enumerator as IDisposable; IDisposable disposable = enumerator as IDisposable;
if (disposable != null) { if (disposable != null)
{
disposable.Dispose(); disposable.Dispose();
} }
} }
@ -156,7 +169,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
public static object NonGenericForeachWithReturn(IEnumerable enumerable) public static object NonGenericForeachWithReturn(IEnumerable enumerable)
{ {
Console.WriteLine("NonGenericForeachWithReturn:"); Console.WriteLine("NonGenericForeachWithReturn:");
foreach (var obj in enumerable) { foreach (var obj in enumerable)
{
Console.WriteLine("return: " + obj); Console.WriteLine("return: " + obj);
return obj; return obj;
} }
@ -168,7 +182,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
public static int? ForeachWithReturn(IEnumerable<int> enumerable) public static int? ForeachWithReturn(IEnumerable<int> enumerable)
{ {
Console.WriteLine("ForeachWithReturn:"); Console.WriteLine("ForeachWithReturn:");
foreach (var obj in enumerable) { foreach (var obj in enumerable)
{
Console.WriteLine("return: " + obj); Console.WriteLine("return: " + obj);
return obj; return obj;
} }
@ -180,7 +195,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
public static void ForeachWithRefUsage(List<int> items) public static void ForeachWithRefUsage(List<int> items)
{ {
Console.WriteLine("ForeachWithRefUsage:"); Console.WriteLine("ForeachWithRefUsage:");
foreach (var item in items) { foreach (var item in items)
{
var itemToChange = item; var itemToChange = item;
Console.WriteLine("item: " + item); Console.WriteLine("item: " + item);
Operation(ref itemToChange); Operation(ref itemToChange);
@ -191,7 +207,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
public static T FirstOrDefault<T>(IEnumerable<T> items) public static T FirstOrDefault<T>(IEnumerable<T> items)
{ {
T result = default(T); T result = default(T);
foreach (T item in items) { foreach (T item in items)
{
result = item; result = item;
break; break;
} }
@ -202,8 +219,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
{ {
Console.WriteLine("NoForeachDueToMultipleCurrentAccess:"); Console.WriteLine("NoForeachDueToMultipleCurrentAccess:");
T result = default(T); T result = default(T);
using (IEnumerator<T> enumerator = items.GetEnumerator()) { using (IEnumerator<T> enumerator = items.GetEnumerator())
while (enumerator.MoveNext()) { {
while (enumerator.MoveNext())
{
result = enumerator.Current; result = enumerator.Current;
Console.WriteLine("result: " + result); Console.WriteLine("result: " + result);
} }
@ -214,14 +233,16 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
public static T NoForeachCallWithSideEffect<T>(CustomClassEnumeratorWithIDisposable<T> items) public static T NoForeachCallWithSideEffect<T>(CustomClassEnumeratorWithIDisposable<T> items)
{ {
Console.WriteLine("NoForeachCallWithSideEffect:"); Console.WriteLine("NoForeachCallWithSideEffect:");
using (CustomClassEnumeratorWithIDisposable<T> enumerator = items.GetEnumerator()) { using (CustomClassEnumeratorWithIDisposable<T> enumerator = items.GetEnumerator())
while (enumerator.MoveNext()) { {
while (enumerator.MoveNext())
{
T result = enumerator.Current; T result = enumerator.Current;
} }
return CallWithSideEffect<T>(); return CallWithSideEffect<T>();
} }
} }
static bool GetBool(string text) static bool GetBool(string text)
{ {
return false; return false;
@ -231,31 +252,39 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
static void LoopWithGotoRepeat() static void LoopWithGotoRepeat()
{ {
Console.WriteLine("LoopWithGotoRepeat:"); Console.WriteLine("LoopWithGotoRepeat:");
try { try
{
REPEAT: REPEAT:
Console.WriteLine("after repeat label"); Console.WriteLine("after repeat label");
while (GetBool("Loop condition")) { while (GetBool("Loop condition"))
if (GetBool("if1")) { {
if (GetBool("if3")) { if (GetBool("if1"))
{
if (GetBool("if3"))
{
goto REPEAT; goto REPEAT;
} }
break; break;
} }
} }
Console.WriteLine("after loop"); Console.WriteLine("after loop");
} finally { }
finally
{
Console.WriteLine("finally"); Console.WriteLine("finally");
} }
Console.WriteLine("after finally"); Console.WriteLine("after finally");
} }
private static int LoopFollowedByIf() private static int LoopFollowedByIf()
{ {
int num = 0; int num = 0;
while (num == 0) { while (num == 0)
{
num++; num++;
} }
if (num == 0) { if (num == 0)
{
return -1; return -1;
} }
return num; return num;
@ -263,9 +292,11 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
static void Issue1392ForWithNestedSwitchPlusGoto() static void Issue1392ForWithNestedSwitchPlusGoto()
{ {
for (int i = 0; i < 100; i++) { for (int i = 0; i < 100; i++)
{
again: again:
switch (i) { switch (i)
{
case 10: case 10:
Console.WriteLine("10"); Console.WriteLine("10");
break; break;
@ -281,13 +312,17 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
private static void NoForeachDueToVariableAssignment() private static void NoForeachDueToVariableAssignment()
{ {
try { try
{
int[] array = new int[] { 1, 2, 3 }; int[] array = new int[] { 1, 2, 3 };
for (int i = 0; i < array.Length; i++) { for (int i = 0; i < array.Length; i++)
{
Console.WriteLine(array[i]); Console.WriteLine(array[i]);
array = null; array = null;
} }
} catch (Exception ex) { }
catch (Exception ex)
{
Console.WriteLine(ex.GetType() + ": " + ex.Message); Console.WriteLine(ex.GetType() + ": " + ex.Message);
} }
} }

26
ICSharpCode.Decompiler.Tests/TestCases/Correctness/MemberLookup.cs

@ -23,7 +23,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
public class MemberLookup public class MemberLookup
{ {
static readonly Action delegateConstruction = (new Child1() as Base1).TestAction; static readonly Action delegateConstruction = (new Child1() as Base1).TestAction;
public static int Main() public static int Main()
{ {
Console.WriteLine((new Child1() as Base1).Field); Console.WriteLine((new Child1() as Base1).Field);
@ -32,49 +32,49 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
new Child2b().CallTestMethod(); new Child2b().CallTestMethod();
return 0; return 0;
} }
class Base1 class Base1
{ {
public int Field = 1; public int Field = 1;
protected virtual void TestMethod() protected virtual void TestMethod()
{ {
Property = 5; Property = 5;
Console.WriteLine("Base1.TestMethod()"); Console.WriteLine("Base1.TestMethod()");
Console.WriteLine(Property); Console.WriteLine(Property);
} }
public void TestAction() public void TestAction()
{ {
Console.WriteLine("Base1.TestAction()"); Console.WriteLine("Base1.TestAction()");
} }
public int Property { get; set; } public int Property { get; set; }
public virtual int VirtProp { public virtual int VirtProp {
get { get {
return 3; return 3;
} }
} }
} }
class Child1 : Base1 class Child1 : Base1
{ {
Child1 child; Child1 child;
new public int Field = 2; new public int Field = 2;
public static void Test() public static void Test()
{ {
var o = new Child1(); var o = new Child1();
o.child = new Child1(); o.child = new Child1();
o.TestMethod(); o.TestMethod();
Console.WriteLine(((Base1)o).Property); Console.WriteLine(((Base1)o).Property);
Console.WriteLine(o.Property); Console.WriteLine(o.Property);
Console.WriteLine(((Base1)o).VirtProp); Console.WriteLine(((Base1)o).VirtProp);
Console.WriteLine(o.VirtProp); Console.WriteLine(o.VirtProp);
} }
protected override void TestMethod() protected override void TestMethod()
{ {
Property = 10; Property = 10;
@ -86,14 +86,14 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
Console.WriteLine("Field = " + Field); Console.WriteLine("Field = " + Field);
Console.WriteLine("base.Field = " + base.Field); Console.WriteLine("base.Field = " + base.Field);
} }
new public void TestAction() new public void TestAction()
{ {
Console.WriteLine("Child1.TestAction()"); Console.WriteLine("Child1.TestAction()");
} }
new public int Property { get; set; } new public int Property { get; set; }
public override int VirtProp { public override int VirtProp {
get { get {
return base.VirtProp * 2; return base.VirtProp * 2;

202
ICSharpCode.Decompiler.Tests/TestCases/Correctness/MiniJSON.cs

@ -9,30 +9,32 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
// taken from https://github.com/Jackyjjc/MiniJSON.cs // taken from https://github.com/Jackyjjc/MiniJSON.cs
// Copyright (c) 2013 Calvin Rien. // Copyright (c) 2013 Calvin Rien.
// Licensed under the MIT LICENSE. // Licensed under the MIT LICENSE.
public class MiniJSONTest { public class MiniJSONTest
public static void Main(string[] args) { {
var jsonString = "{ \"array\": [1.44,2,3], " + public static void Main(string[] args)
"\"object\": {\"key1\":\"value1\", \"key2\":256}, " + {
"\"string\": \"The quick brown fox \\\"jumps\\\" over the lazy dog \", " + var jsonString = "{ \"array\": [1.44,2,3], " +
"\"unicode\": \"\\u3041 Men\u00fa sesi\u00f3n\", " + "\"object\": {\"key1\":\"value1\", \"key2\":256}, " +
"\"int\": 65536, " + "\"string\": \"The quick brown fox \\\"jumps\\\" over the lazy dog \", " +
"\"float\": 3.1415926, " + "\"unicode\": \"\\u3041 Men\u00fa sesi\u00f3n\", " +
"\"bool\": true, " + "\"int\": 65536, " +
"\"null\": null }"; "\"float\": 3.1415926, " +
"\"bool\": true, " +
var dict = Json.Deserialize(jsonString) as Dictionary<string,object>; "\"null\": null }";
Console.WriteLine("deserialized: " + dict.GetType()); var dict = Json.Deserialize(jsonString) as Dictionary<string, object>;
Console.WriteLine("dict['array'][0]: " + ((List<object>) dict["array"])[0]);
Console.WriteLine("dict['string']: " + (string) dict["string"]); Console.WriteLine("deserialized: " + dict.GetType());
Console.WriteLine("dict['float']: " + (double) dict["float"]); // floats come out as doubles Console.WriteLine("dict['array'][0]: " + ((List<object>)dict["array"])[0]);
Console.WriteLine("dict['int']: " + (long) dict["int"]); // ints come out as longs Console.WriteLine("dict['string']: " + (string)dict["string"]);
Console.WriteLine("dict['unicode']: " + (string) dict["unicode"]); Console.WriteLine("dict['float']: " + (double)dict["float"]); // floats come out as doubles
Console.WriteLine("dict['int']: " + (long)dict["int"]); // ints come out as longs
var str = Json.Serialize(dict); Console.WriteLine("dict['unicode']: " + (string)dict["unicode"]);
Console.WriteLine("serialized: " + str); var str = Json.Serialize(dict);
}
Console.WriteLine("serialized: " + str);
}
} }
public static class Json public static class Json
@ -45,7 +47,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
public static object Deserialize(string json) public static object Deserialize(string json)
{ {
// save the string for debug information // save the string for debug information
if (json == null) { if (json == null)
{
return null; return null;
} }
@ -93,7 +96,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
public static object Parse(string jsonString) public static object Parse(string jsonString)
{ {
using (var instance = new Parser(jsonString)) { using (var instance = new Parser(jsonString))
{
return instance.ParseValue(); return instance.ParseValue();
} }
} }
@ -112,8 +116,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
json.Read(); json.Read();
// { // {
while (true) { while (true)
switch (NextToken) { {
switch (NextToken)
{
case TOKEN.NONE: case TOKEN.NONE:
return null; return null;
case TOKEN.COMMA: case TOKEN.COMMA:
@ -123,12 +129,14 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
case TOKEN.STRING: case TOKEN.STRING:
// name // name
string name = ParseString(); string name = ParseString();
if (name == null) { if (name == null)
{
return null; return null;
} }
// : // :
if (NextToken != TOKEN.COLON) { if (NextToken != TOKEN.COLON)
{
return null; return null;
} }
// ditch the colon // ditch the colon
@ -156,10 +164,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
// [ // [
var parsing = true; var parsing = true;
while (parsing) { while (parsing)
{
TOKEN nextToken = NextToken; TOKEN nextToken = NextToken;
switch (nextToken) { switch (nextToken)
{
case TOKEN.NONE: case TOKEN.NONE:
return null; return null;
case TOKEN.COMMA: case TOKEN.COMMA:
@ -187,7 +197,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
object ParseByToken(TOKEN token) object ParseByToken(TOKEN token)
{ {
switch (token) { switch (token)
{
case TOKEN.STRING: case TOKEN.STRING:
return ParseString(); return ParseString();
case TOKEN.NUMBER: case TOKEN.NUMBER:
@ -216,26 +227,31 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
json.Read(); json.Read();
bool parsing = true; bool parsing = true;
while (parsing) { while (parsing)
{
if (json.Peek() == -1) { if (json.Peek() == -1)
{
parsing = false; parsing = false;
break; break;
} }
c = NextChar; c = NextChar;
switch (c) { switch (c)
{
case '"': case '"':
parsing = false; parsing = false;
break; break;
case '\\': case '\\':
if (json.Peek() == -1) { if (json.Peek() == -1)
{
parsing = false; parsing = false;
break; break;
} }
c = NextChar; c = NextChar;
switch (c) { switch (c)
{
case '"': case '"':
case '\\': case '\\':
case '/': case '/':
@ -259,7 +275,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
case 'u': case 'u':
var hex = new char[4]; var hex = new char[4];
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++)
{
hex[i] = NextChar; hex[i] = NextChar;
if (!IsHexDigit(hex[i])) if (!IsHexDigit(hex[i]))
return null; return null;
@ -282,7 +299,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
{ {
string number = NextWord; string number = NextWord;
if (number.IndexOf('.') == -1 && number.IndexOf('E') == -1 && number.IndexOf('e') == -1) { if (number.IndexOf('.') == -1 && number.IndexOf('E') == -1 && number.IndexOf('e') == -1)
{
long parsedInt; long parsedInt;
Int64.TryParse(number, System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture, out parsedInt); Int64.TryParse(number, System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture, out parsedInt);
return parsedInt; return parsedInt;
@ -295,10 +313,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
void EatWhitespace() void EatWhitespace()
{ {
while (Char.IsWhiteSpace(PeekChar)) { while (Char.IsWhiteSpace(PeekChar))
{
json.Read(); json.Read();
if (json.Peek() == -1) { if (json.Peek() == -1)
{
break; break;
} }
} }
@ -320,10 +340,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
get { get {
StringBuilder word = new StringBuilder(); StringBuilder word = new StringBuilder();
while (!IsWordBreak(PeekChar)) { while (!IsWordBreak(PeekChar))
{
word.Append(NextChar); word.Append(NextChar);
if (json.Peek() == -1) { if (json.Peek() == -1)
{
break; break;
} }
} }
@ -336,11 +358,13 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
get { get {
EatWhitespace(); EatWhitespace();
if (json.Peek() == -1) { if (json.Peek() == -1)
{
return TOKEN.NONE; return TOKEN.NONE;
} }
switch (PeekChar) { switch (PeekChar)
{
case '{': case '{':
return TOKEN.CURLY_OPEN; return TOKEN.CURLY_OPEN;
case '}': case '}':
@ -372,7 +396,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
return TOKEN.NUMBER; return TOKEN.NUMBER;
} }
switch (NextWord) { switch (NextWord)
{
case "false": case "false":
return TOKEN.FALSE; return TOKEN.FALSE;
case "true": case "true":
@ -420,19 +445,32 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
IDictionary asDict; IDictionary asDict;
string asStr; string asStr;
if (value == null) { if (value == null)
{
builder.Append("null"); builder.Append("null");
} else if ((asStr = value as string) != null) { }
else if ((asStr = value as string) != null)
{
SerializeString(asStr); SerializeString(asStr);
} else if (value is bool) { }
else if (value is bool)
{
builder.Append((bool)value ? "true" : "false"); builder.Append((bool)value ? "true" : "false");
} else if ((asList = value as IList) != null) { }
else if ((asList = value as IList) != null)
{
SerializeArray(asList); SerializeArray(asList);
} else if ((asDict = value as IDictionary) != null) { }
else if ((asDict = value as IDictionary) != null)
{
SerializeObject(asDict); SerializeObject(asDict);
} else if (value is char) { }
else if (value is char)
{
SerializeString(new string((char)value, 1)); SerializeString(new string((char)value, 1));
} else { }
else
{
SerializeOther(value); SerializeOther(value);
} }
} }
@ -443,8 +481,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
builder.Append('{'); builder.Append('{');
foreach (object e in obj.Keys) { foreach (object e in obj.Keys)
if (!first) { {
if (!first)
{
builder.Append(','); builder.Append(',');
} }
@ -465,9 +505,11 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
bool first = true; bool first = true;
for (int i = 0; i < anArray.Count; i++) { for (int i = 0; i < anArray.Count; i++)
{
object obj = anArray[i]; object obj = anArray[i];
if (!first) { if (!first)
{
builder.Append(','); builder.Append(',');
} }
@ -484,9 +526,11 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
builder.Append('\"'); builder.Append('\"');
char[] charArray = str.ToCharArray(); char[] charArray = str.ToCharArray();
for (int i = 0; i < charArray.Length; i++) { for (int i = 0; i < charArray.Length; i++)
{
char c = charArray[i]; char c = charArray[i];
switch (c) { switch (c)
{
case '"': case '"':
builder.Append("\\\""); builder.Append("\\\"");
break; break;
@ -510,9 +554,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
break; break;
default: default:
int codepoint = Convert.ToInt32(c); int codepoint = Convert.ToInt32(c);
if ((codepoint >= 32) && (codepoint <= 126)) { if ((codepoint >= 32) && (codepoint <= 126))
{
builder.Append(c); builder.Append(c);
} else { }
else
{
builder.Append("\\u"); builder.Append("\\u");
builder.Append(codepoint.ToString("x4")); builder.Append(codepoint.ToString("x4"));
} }
@ -528,21 +575,28 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
// NOTE: decimals lose precision during serialization. // NOTE: decimals lose precision during serialization.
// They always have, I'm just letting you know. // They always have, I'm just letting you know.
// Previously floats and doubles lost precision too. // Previously floats and doubles lost precision too.
if (value is float) { if (value is float)
{
builder.Append(((float)value).ToString("R", System.Globalization.CultureInfo.InvariantCulture)); builder.Append(((float)value).ToString("R", System.Globalization.CultureInfo.InvariantCulture));
} else if (value is int }
|| value is uint else if (value is int
|| value is long || value is uint
|| value is sbyte || value is long
|| value is byte || value is sbyte
|| value is short || value is byte
|| value is ushort || value is short
|| value is ulong) { || value is ushort
|| value is ulong)
{
builder.Append(value); builder.Append(value);
} else if (value is double }
|| value is decimal) { else if (value is double
|| value is decimal)
{
builder.Append(Convert.ToDouble(value).ToString("R", System.Globalization.CultureInfo.InvariantCulture)); builder.Append(Convert.ToDouble(value).ToString("R", System.Globalization.CultureInfo.InvariantCulture));
} else { }
else
{
SerializeString(value.ToString()); SerializeString(value.ToString());
} }
} }

2
ICSharpCode.Decompiler.Tests/TestCases/Correctness/NullPropagation.cs

@ -13,7 +13,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
{ {
public string Text; public string Text;
} }
void TestNotCoalescing() void TestNotCoalescing()
{ {
Console.WriteLine("TestNotCoalescing:"); Console.WriteLine("TestNotCoalescing:");

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

@ -103,18 +103,24 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
static void FieldAccessOrderOfEvaluation(NullableTests c) static void FieldAccessOrderOfEvaluation(NullableTests c)
{ {
Console.WriteLine("GetInt, then NRE:"); Console.WriteLine("GetInt, then NRE:");
try { try
{
c.intField = GetValue<int>(); c.intField = GetValue<int>();
} catch (Exception ex) { }
catch (Exception ex)
{
Console.WriteLine(ex.Message); Console.WriteLine(ex.Message);
} }
Console.WriteLine("NRE before GetInt:"); Console.WriteLine("NRE before GetInt:");
try { try
{
#if CS60 #if CS60
ref int i = ref c.intField; ref int i = ref c.intField;
i = GetValue<int>(); i = GetValue<int>();
#endif #endif
} catch (Exception ex) { }
catch (Exception ex)
{
Console.WriteLine(ex.Message); Console.WriteLine(ex.Message);
} }
} }
@ -124,18 +130,24 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
static void FieldAccessOrderOfEvaluationWithStruct(NullableTests c) static void FieldAccessOrderOfEvaluationWithStruct(NullableTests c)
{ {
Console.WriteLine("GetInt, then NRE (with struct):"); Console.WriteLine("GetInt, then NRE (with struct):");
try { try
{
c.structField.IntField = GetValue<int>(); c.structField.IntField = GetValue<int>();
} catch (Exception ex) { }
catch (Exception ex)
{
Console.WriteLine(ex.Message); Console.WriteLine(ex.Message);
} }
Console.WriteLine("NRE before GetInt (with struct):"); Console.WriteLine("NRE before GetInt (with struct):");
try { try
{
#if CS60 #if CS60
ref SomeStruct s = ref c.structField; ref SomeStruct s = ref c.structField;
s.IntField = GetValue<int>(); s.IntField = GetValue<int>();
#endif #endif
} catch (Exception ex) { }
catch (Exception ex)
{
Console.WriteLine(ex.Message); Console.WriteLine(ex.Message);
} }
} }
@ -155,27 +167,36 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
static void ArrayAccessOrderOfEvaluation() static void ArrayAccessOrderOfEvaluation()
{ {
Console.WriteLine("GetArray direct:"); Console.WriteLine("GetArray direct:");
try { try
{
GetArray<int>()[GetIndex()] = GetValue<int>(); GetArray<int>()[GetIndex()] = GetValue<int>();
} catch (Exception ex) { }
catch (Exception ex)
{
Console.WriteLine(ex.Message); Console.WriteLine(ex.Message);
} }
Console.WriteLine("GetArray with ref:"); Console.WriteLine("GetArray with ref:");
try { try
{
#if CS60 #if CS60
ref int elem = ref GetArray<int>()[GetIndex()]; ref int elem = ref GetArray<int>()[GetIndex()];
elem = GetValue<int>(); elem = GetValue<int>();
#endif #endif
} catch (Exception ex) { }
catch (Exception ex)
{
Console.WriteLine(ex.Message); Console.WriteLine(ex.Message);
} }
Console.WriteLine("GetArray direct with value-type:"); Console.WriteLine("GetArray direct with value-type:");
try { try
{
// This line is mis-compiled by legacy csc: // This line is mis-compiled by legacy csc:
// with the legacy compiler the NRE is thrown before the GetValue call; // with the legacy compiler the NRE is thrown before the GetValue call;
// with Roslyn the NRE is thrown after the GetValue call. // with Roslyn the NRE is thrown after the GetValue call.
GetArray<TimeSpan>()[GetIndex()] = GetValue<TimeSpan>(); GetArray<TimeSpan>()[GetIndex()] = GetValue<TimeSpan>();
} catch (Exception ex) { }
catch (Exception ex)
{
Console.WriteLine(ex.Message); Console.WriteLine(ex.Message);
} }
} }

3
ICSharpCode.Decompiler.Tests/TestCases/Correctness/OverloadResolution.cs

@ -100,7 +100,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
static void TestCallIssue1281(params object[] args) static void TestCallIssue1281(params object[] args)
{ {
Console.Write("TestCallIssue1281: count = " + args.Length + ": "); Console.Write("TestCallIssue1281: count = " + args.Length + ": ");
foreach (var arg in args) { foreach (var arg in args)
{
Console.Write(arg); Console.Write(arg);
Console.Write(", "); Console.Write(", ");
} }

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

@ -21,16 +21,14 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
{ {
int thisValue; int thisValue;
public int this[int i] public int this[int i] {
{
get { Console.WriteLine("get_this({0})", i); return i * i; } get { Console.WriteLine("get_this({0})", i); return i * i; }
set { Console.WriteLine("set_this({0}, {1})", i, value); thisValue = value; } set { Console.WriteLine("set_this({0}, {1})", i, value); thisValue = value; }
} }
public string AutoProp { get; set; } public string AutoProp { get; set; }
public double PISquare public double PISquare {
{
get { Console.WriteLine("get_PISquare"); return Math.Pow(Math.PI, 2); } get { Console.WriteLine("get_PISquare"); return Math.Pow(Math.PI, 2); }
} }
} }

69
ICSharpCode.Decompiler.Tests/TestCases/Correctness/Switch.cs

@ -41,7 +41,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
static void TestCase<T>(Func<T, string> target, params T[] args) static void TestCase<T>(Func<T, string> target, params T[] args)
{ {
foreach (var arg in args) { foreach (var arg in args)
{
Console.WriteLine(target(arg)); Console.WriteLine(target(arg));
} }
} }
@ -49,26 +50,40 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
public static string SparseIntegerSwitch(int i) public static string SparseIntegerSwitch(int i)
{ {
Console.WriteLine("SparseIntegerSwitch: " + i); Console.WriteLine("SparseIntegerSwitch: " + i);
switch (i) { switch (i)
case -10000000: return "-10 mln"; {
case -100: return "-hundred"; case -10000000:
case -1: return "-1"; return "-10 mln";
case 0: return "0"; case -100:
case 1: return "1"; return "-hundred";
case 2: return "2"; case -1:
case 4: return "4"; return "-1";
case 100: return "hundred"; case 0:
case 10000: return "ten thousand"; return "0";
case 10001: return "ten thousand and one"; case 1:
case int.MaxValue: return "int.MaxValue"; return "1";
default: return "something else"; case 2:
return "2";
case 4:
return "4";
case 100:
return "hundred";
case 10000:
return "ten thousand";
case 10001:
return "ten thousand and one";
case int.MaxValue:
return "int.MaxValue";
default:
return "something else";
} }
} }
public static string ShortSwitchOverString(string text) public static string ShortSwitchOverString(string text)
{ {
Console.WriteLine("ShortSwitchOverString: " + text); Console.WriteLine("ShortSwitchOverString: " + text);
switch (text) { switch (text)
{
case "First case": case "First case":
return "Text"; return "Text";
default: default:
@ -79,7 +94,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
public static string ShortSwitchOverString2(string text) public static string ShortSwitchOverString2(string text)
{ {
Console.WriteLine("ShortSwitchOverString2: " + text); Console.WriteLine("ShortSwitchOverString2: " + text);
switch (text) { switch (text)
{
case "First case": case "First case":
return "Text1"; return "Text1";
case "Second case": case "Second case":
@ -94,7 +110,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
public static string ShortSwitchOverStringNoExplicitDefault(string text) public static string ShortSwitchOverStringNoExplicitDefault(string text)
{ {
Console.WriteLine("ShortSwitchOverStringNoExplicitDefault: " + text); Console.WriteLine("ShortSwitchOverStringNoExplicitDefault: " + text);
switch (text) { switch (text)
{
case "First case": case "First case":
return "Text1"; return "Text1";
case "Second case": case "Second case":
@ -108,7 +125,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
public static string SwitchOverString1(string text) public static string SwitchOverString1(string text)
{ {
Console.WriteLine("SwitchOverString1: " + text); Console.WriteLine("SwitchOverString1: " + text);
switch (text) { switch (text)
{
case "First case": case "First case":
return "Text1"; return "Text1";
case "Second case": case "Second case":
@ -132,7 +150,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
public static string SwitchOverString2() public static string SwitchOverString2()
{ {
Console.WriteLine("SwitchOverString2:"); Console.WriteLine("SwitchOverString2:");
switch (Environment.UserName) { switch (Environment.UserName)
{
case "First case": case "First case":
return "Text1"; return "Text1";
case "Second case": case "Second case":
@ -163,7 +182,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
public static string SwitchOverBool(bool b) public static string SwitchOverBool(bool b)
{ {
Console.WriteLine("SwitchOverBool: " + b); Console.WriteLine("SwitchOverBool: " + b);
switch (b) { switch (b)
{
case true: case true:
return bool.TrueString; return bool.TrueString;
case false: case false:
@ -178,8 +198,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
public static void SwitchInLoop(int i) public static void SwitchInLoop(int i)
{ {
Console.WriteLine("SwitchInLoop: " + i); Console.WriteLine("SwitchInLoop: " + i);
while (true) { while (true)
switch (i) { {
switch (i)
{
case 1: case 1:
Console.WriteLine("one"); Console.WriteLine("one");
break; break;
@ -204,7 +226,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
public static void SwitchWithGoto(int i) public static void SwitchWithGoto(int i)
{ {
Console.WriteLine("SwitchWithGoto: " + i); Console.WriteLine("SwitchWithGoto: " + i);
switch (i) { switch (i)
{
case 1: case 1:
Console.WriteLine("one"); Console.WriteLine("one");
goto default; goto default;

4
ICSharpCode.Decompiler.Tests/TestCases/Correctness/TrickyTypes.cs

@ -59,13 +59,13 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
Console.WriteLine("TruncatedComp1(-1):"); Console.WriteLine("TruncatedComp1(-1):");
TruncatedComp1(-1); TruncatedComp1(-1);
Console.WriteLine("TruncatedComp1(0x100000001):"); Console.WriteLine("TruncatedComp1(0x100000001):");
TruncatedComp1(0x100000001); TruncatedComp1(0x100000001);
Console.WriteLine("TruncatedComp1(long.MinValue):"); Console.WriteLine("TruncatedComp1(long.MinValue):");
TruncatedComp1(long.MinValue); TruncatedComp1(long.MinValue);
Console.WriteLine("TruncatedComp2(1):"); Console.WriteLine("TruncatedComp2(1):");
TruncatedComp2(1, 1); TruncatedComp2(1, 1);

10
ICSharpCode.Decompiler.Tests/TestCases/Correctness/UndocumentedExpressions.cs

@ -38,12 +38,16 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
ArgIterator argIterator = new ArgIterator(__arglist); ArgIterator argIterator = new ArgIterator(__arglist);
Console.WriteLine("Called with {0} arguments", argIterator.GetRemainingCount()); Console.WriteLine("Called with {0} arguments", argIterator.GetRemainingCount());
int pos = 0; int pos = 0;
while (argIterator.GetRemainingCount() > 0) { while (argIterator.GetRemainingCount() > 0)
{
TypedReference tr = argIterator.GetNextArg(); TypedReference tr = argIterator.GetNextArg();
object val; object val;
try { try
{
val = __refvalue(tr, object); val = __refvalue(tr, object);
} catch (Exception ex) { }
catch (Exception ex)
{
val = ex.GetType().Name; val = ex.GetType().Name;
} }
Console.WriteLine("{0} : {1} = {2}", pos++, __reftype(tr).Name, val); Console.WriteLine("{0} : {1} = {2}", pos++, __reftype(tr).Name, val);

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

@ -36,7 +36,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
public unsafe int MultipleExitsOutOfFixedBlock(int[] arr) public unsafe int MultipleExitsOutOfFixedBlock(int[] arr)
{ {
fixed (int* ptr = &arr[0]) { fixed (int* ptr = &arr[0])
{
if (*ptr < 0) if (*ptr < 0)
return *ptr; return *ptr;
if (*ptr == 21) if (*ptr == 21)
@ -49,10 +50,11 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
Console.WriteLine("outside"); Console.WriteLine("outside");
return 2; return 2;
} }
public unsafe void FixMultipleStrings(string text) public unsafe void FixMultipleStrings(string text)
{ {
fixed (char* ptr = text, userName = Environment.UserName, ptr2 = text) { fixed (char* ptr = text, userName = Environment.UserName, ptr2 = text)
{
*ptr = 'c'; *ptr = 'c';
*userName = 'd'; *userName = 'd';
*ptr2 = 'e'; *ptr2 = 'e';

70
ICSharpCode.Decompiler.Tests/TestCases/Correctness/Using.cs

@ -57,7 +57,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
Console.WriteLine("before using"); Console.WriteLine("before using");
// Mono has a compiler bug and introduces an assembly reference to [gmcs] here... // Mono has a compiler bug and introduces an assembly reference to [gmcs] here...
#if !MCS #if !MCS
using (null) { using (null)
{
Console.WriteLine("using (null)"); Console.WriteLine("using (null)");
} }
#endif #endif
@ -67,9 +68,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
public static void NoUsingDueToAssignment() public static void NoUsingDueToAssignment()
{ {
PrintOnDispose printOnDispose = new PrintOnDispose("Wrong"); PrintOnDispose printOnDispose = new PrintOnDispose("Wrong");
try { try
{
printOnDispose = new PrintOnDispose("Correct"); printOnDispose = new PrintOnDispose("Correct");
} finally { }
finally
{
printOnDispose.Dispose(); printOnDispose.Dispose();
} }
} }
@ -77,11 +81,15 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
public static void NoUsingDueToAssignment2() public static void NoUsingDueToAssignment2()
{ {
PrintOnDispose printOnDispose = new PrintOnDispose("NoUsing(): Wrong"); PrintOnDispose printOnDispose = new PrintOnDispose("NoUsing(): Wrong");
try { try
{
printOnDispose = new PrintOnDispose("NoUsing(): Correct"); printOnDispose = new PrintOnDispose("NoUsing(): Correct");
} finally { }
finally
{
IDisposable disposable = (object)printOnDispose as IDisposable; IDisposable disposable = (object)printOnDispose as IDisposable;
if (disposable != null) { if (disposable != null)
{
disposable.Dispose(); disposable.Dispose();
} }
} }
@ -95,12 +103,16 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
public static void NoUsingDueToByRefCall() public static void NoUsingDueToByRefCall()
{ {
PrintOnDispose printOnDispose = new PrintOnDispose("NoUsingDueToByRefCall(): Wrong"); PrintOnDispose printOnDispose = new PrintOnDispose("NoUsingDueToByRefCall(): Wrong");
try { try
{
Console.WriteLine("NoUsingDueToByRefCall"); Console.WriteLine("NoUsingDueToByRefCall");
Clear(ref printOnDispose); Clear(ref printOnDispose);
} finally { }
finally
{
IDisposable disposable = (object)printOnDispose as IDisposable; IDisposable disposable = (object)printOnDispose as IDisposable;
if (disposable != null) { if (disposable != null)
{
disposable.Dispose(); disposable.Dispose();
} }
} }
@ -110,11 +122,15 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
{ {
var obj = new System.IO.StringWriter(); var obj = new System.IO.StringWriter();
IDisposable disposable; IDisposable disposable;
try { try
{
obj.WriteLine("NoUsingDueToContinuedDisposableUse"); obj.WriteLine("NoUsingDueToContinuedDisposableUse");
} finally { }
finally
{
disposable = (object)obj as IDisposable; disposable = (object)obj as IDisposable;
if (disposable != null) { if (disposable != null)
{
disposable.Dispose(); disposable.Dispose();
} }
} }
@ -124,11 +140,15 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
public static void ContinuedObjectUse() public static void ContinuedObjectUse()
{ {
var obj = new System.IO.StringWriter(); var obj = new System.IO.StringWriter();
try { try
{
obj.WriteLine("ContinuedObjectUse"); obj.WriteLine("ContinuedObjectUse");
} finally { }
finally
{
IDisposable disposable = (object)obj as IDisposable; IDisposable disposable = (object)obj as IDisposable;
if (disposable != null) { if (disposable != null)
{
disposable.Dispose(); disposable.Dispose();
} }
} }
@ -141,11 +161,15 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
obj.Write("VariableAlreadyUsedBefore - 1"); obj.Write("VariableAlreadyUsedBefore - 1");
Console.WriteLine(obj); Console.WriteLine(obj);
obj = new System.IO.StringWriter(); obj = new System.IO.StringWriter();
try { try
{
obj.WriteLine("VariableAlreadyUsedBefore - 2"); obj.WriteLine("VariableAlreadyUsedBefore - 2");
} finally { }
finally
{
IDisposable disposable = (object)obj as IDisposable; IDisposable disposable = (object)obj as IDisposable;
if (disposable != null) { if (disposable != null)
{
disposable.Dispose(); disposable.Dispose();
} }
} }
@ -154,11 +178,15 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
public static void UsingObject() public static void UsingObject()
{ {
object obj = new object(); object obj = new object();
try { try
{
Console.WriteLine("UsingObject: {0}", obj); Console.WriteLine("UsingObject: {0}", obj);
} finally { }
finally
{
IDisposable disposable = obj as IDisposable; IDisposable disposable = obj as IDisposable;
if (disposable != null) { if (disposable != null)
{
disposable.Dispose(); disposable.Dispose();
} }
} }

45
ICSharpCode.Decompiler.Tests/TestCases/Correctness/ValueTypeCall.cs

@ -6,7 +6,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
public struct MutValueType : IDisposable public struct MutValueType : IDisposable
{ {
public int val; public int val;
public void Increment() public void Increment()
{ {
Console.WriteLine("Inc() called on {0}", val); Console.WriteLine("Inc() called on {0}", val);
@ -23,35 +23,35 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
return "MutValueType.ToString() " + (++val); return "MutValueType.ToString() " + (++val);
} }
} }
public struct GenericValueType<T> public struct GenericValueType<T>
{ {
T data; T data;
int num; int num;
public GenericValueType(T data) public GenericValueType(T data)
{ {
this.data = data; this.data = data;
this.num = 1; this.num = 1;
} }
public void Call(ref GenericValueType<T> v) public void Call(ref GenericValueType<T> v)
{ {
num++; num++;
Console.WriteLine("Call #{0}: {1} with v=#{2}", num, data, v.num); Console.WriteLine("Call #{0}: {1} with v=#{2}", num, data, v.num);
} }
} }
public struct ValueTypeWithReadOnlyMember public struct ValueTypeWithReadOnlyMember
{ {
public readonly int Member; public readonly int Member;
public ValueTypeWithReadOnlyMember(int member) public ValueTypeWithReadOnlyMember(int member)
{ {
this.Member = member; this.Member = member;
} }
} }
public class ValueTypeCall public class ValueTypeCall
{ {
public static void Main() public static void Main()
@ -68,22 +68,22 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
new ValueTypeCall().InstanceFieldTests(); new ValueTypeCall().InstanceFieldTests();
ForEach(); ForEach();
} }
static void RefParameter(ref MutValueType m) static void RefParameter(ref MutValueType m)
{ {
m.Increment(); m.Increment();
m.Increment(); m.Increment();
} }
static void ValueParameter(MutValueType m) static void ValueParameter(MutValueType m)
{ {
m.Increment(); m.Increment();
m.Increment(); m.Increment();
} }
static readonly MutValueType ReadonlyField = new MutValueType { val = 100 }; static readonly MutValueType ReadonlyField = new MutValueType { val = 100 };
static MutValueType MutableField = new MutValueType { val = 200 }; static MutValueType MutableField = new MutValueType { val = 200 };
static void Field() static void Field()
{ {
ReadonlyField.Increment(); ReadonlyField.Increment();
@ -99,7 +99,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
MutValueType localCopy = ReadonlyField; MutValueType localCopy = ReadonlyField;
RefParameter(ref localCopy); RefParameter(ref localCopy);
} }
static void Box() static void Box()
{ {
Console.WriteLine("Box"); Console.WriteLine("Box");
@ -126,7 +126,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
MutValueType instanceField; MutValueType instanceField;
ValueTypeWithReadOnlyMember mutableInstanceFieldWithReadOnlyMember; ValueTypeWithReadOnlyMember mutableInstanceFieldWithReadOnlyMember;
void InstanceFieldTests() void InstanceFieldTests()
{ {
this.instanceField.val = 42; this.instanceField.val = 42;
@ -145,7 +145,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
static void Using1() static void Using1()
{ {
Console.WriteLine("Using:"); Console.WriteLine("Using:");
using (var x = new MutValueType()) { using (var x = new MutValueType())
{
x.Increment(); x.Increment();
} }
} }
@ -154,9 +155,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
{ {
Console.WriteLine("Not using:"); Console.WriteLine("Not using:");
var y = new MutValueType(); var y = new MutValueType();
try { try
{
y.Increment(); y.Increment();
} finally { }
finally
{
MutValueType x = y; MutValueType x = y;
x.Dispose(); x.Dispose();
} }
@ -166,7 +170,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
{ {
Console.WriteLine("Using with variable declared outside:"); Console.WriteLine("Using with variable declared outside:");
MutValueType z; MutValueType z;
using (z = new MutValueType()) { using (z = new MutValueType())
{
z.Increment(); z.Increment();
} }
} }
@ -190,7 +195,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
static void ForEach1(List<MutValueType> list) static void ForEach1(List<MutValueType> list)
{ {
Console.WriteLine("ForEach1:"); Console.WriteLine("ForEach1:");
foreach (var val in list) { foreach (var val in list)
{
val.Increment(); val.Increment();
val.Increment(); val.Increment();
} }
@ -200,7 +206,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
static void ForEachArray1(MutValueType[] list) static void ForEachArray1(MutValueType[] list)
{ {
Console.WriteLine("ForEachArray1:"); Console.WriteLine("ForEachArray1:");
foreach (var val in list) { foreach (var val in list)
{
val.Increment(); val.Increment();
val.Increment(); val.Increment();
} }

232
ICSharpCode.Decompiler.Tests/TestCases/Correctness/YieldReturn.cs

@ -47,9 +47,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
Print("YieldBreakInTryCatchInTryFinally", YieldBreakInTryCatchInTryFinally().GetEnumerator()); Print("YieldBreakInTryCatchInTryFinally", YieldBreakInTryCatchInTryFinally().GetEnumerator());
Print("YieldBreakInTryFinallyInTryFinally(false)", YieldBreakInTryFinallyInTryFinally(false).GetEnumerator()); Print("YieldBreakInTryFinallyInTryFinally(false)", YieldBreakInTryFinallyInTryFinally(false).GetEnumerator());
Print("YieldBreakInTryFinallyInTryFinally(true)", YieldBreakInTryFinallyInTryFinally(true).GetEnumerator()); Print("YieldBreakInTryFinallyInTryFinally(true)", YieldBreakInTryFinallyInTryFinally(true).GetEnumerator());
try { try
{
Print("UnconditionalThrowInTryFinally()", UnconditionalThrowInTryFinally().GetEnumerator()); Print("UnconditionalThrowInTryFinally()", UnconditionalThrowInTryFinally().GetEnumerator());
} catch (Exception ex) { }
catch (Exception ex)
{
Console.WriteLine(ex.Message); Console.WriteLine(ex.Message);
} }
Print("NestedTryFinallyStartingOnSamePosition", NestedTryFinallyStartingOnSamePosition().GetEnumerator()); Print("NestedTryFinallyStartingOnSamePosition", NestedTryFinallyStartingOnSamePosition().GetEnumerator());
@ -69,7 +72,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
internal static void Print<T>(string name, IEnumerator<T> enumerator) internal static void Print<T>(string name, IEnumerator<T> enumerator)
{ {
Console.WriteLine(name + ": Test start"); Console.WriteLine(name + ": Test start");
while (enumerator.MoveNext()) { while (enumerator.MoveNext())
{
Console.WriteLine(name + ": " + enumerator.Current); Console.WriteLine(name + ": " + enumerator.Current);
} }
} }
@ -112,7 +116,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
public static IEnumerable<int> YieldReturnInLoop() public static IEnumerable<int> YieldReturnInLoop()
{ {
for (int i = 0; i < 100; i++) { for (int i = 0; i < 100; i++)
{
yield return i; yield return i;
} }
} }
@ -120,9 +125,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
public static IEnumerable<int> YieldReturnWithTryFinally() public static IEnumerable<int> YieldReturnWithTryFinally()
{ {
yield return 0; yield return 0;
try { try
{
yield return 1; yield return 1;
} finally { }
finally
{
Console.WriteLine("Finally!"); Console.WriteLine("Finally!");
} }
yield return 2; yield return 2;
@ -130,14 +138,16 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
public static IEnumerable<int> YieldReturnInLock1(object o) public static IEnumerable<int> YieldReturnInLock1(object o)
{ {
lock (o) { lock (o)
{
yield return 1; yield return 1;
} }
} }
public static IEnumerable<int> YieldReturnInLock2(object o) public static IEnumerable<int> YieldReturnInLock2(object o)
{ {
lock (o) { lock (o)
{
yield return 1; yield return 1;
o = null; o = null;
yield return 2; yield return 2;
@ -149,28 +159,35 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
Console.WriteLine("Start of method - 1"); Console.WriteLine("Start of method - 1");
yield return "Start of method"; yield return "Start of method";
Console.WriteLine("Start of method - 2"); Console.WriteLine("Start of method - 2");
try { try
{
Console.WriteLine("Within outer try - 1"); Console.WriteLine("Within outer try - 1");
yield return "Within outer try"; yield return "Within outer try";
Console.WriteLine("Within outer try - 2"); Console.WriteLine("Within outer try - 2");
try { try
{
Console.WriteLine("Within inner try - 1"); Console.WriteLine("Within inner try - 1");
yield return "Within inner try"; yield return "Within inner try";
Console.WriteLine("Within inner try - 2"); Console.WriteLine("Within inner try - 2");
if (breakInMiddle) { if (breakInMiddle)
{
Console.WriteLine("Breaking..."); Console.WriteLine("Breaking...");
yield break; yield break;
} }
Console.WriteLine("End of inner try - 1"); Console.WriteLine("End of inner try - 1");
yield return "End of inner try"; yield return "End of inner try";
Console.WriteLine("End of inner try - 2"); Console.WriteLine("End of inner try - 2");
} finally { }
finally
{
Console.WriteLine("Inner Finally"); Console.WriteLine("Inner Finally");
} }
Console.WriteLine("End of outer try - 1"); Console.WriteLine("End of outer try - 1");
yield return "End of outer try"; yield return "End of outer try";
Console.WriteLine("End of outer try - 2"); Console.WriteLine("End of outer try - 2");
} finally { }
finally
{
Console.WriteLine("Outer Finally"); Console.WriteLine("Outer Finally");
} }
Console.WriteLine("End of method - 1"); Console.WriteLine("End of method - 1");
@ -181,11 +198,15 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
public static IEnumerable<string> YieldReturnWithTwoNonNestedFinallyBlocks(IEnumerable<string> input) public static IEnumerable<string> YieldReturnWithTwoNonNestedFinallyBlocks(IEnumerable<string> input)
{ {
// outer try-finally block // outer try-finally block
foreach (string line in input) { foreach (string line in input)
{
// nested try-finally block // nested try-finally block
try { try
{
yield return line; yield return line;
} finally { }
finally
{
Console.WriteLine("Processed " + line); Console.WriteLine("Processed " + line);
} }
} }
@ -196,21 +217,24 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
yield return "E"; yield return "E";
yield return "F"; yield return "F";
// outer try-finally block // outer try-finally block
foreach (string line in input) { foreach (string line in input)
{
yield return line.ToUpper(); yield return line.ToUpper();
} }
} }
public static IEnumerable<Func<string>> YieldReturnWithAnonymousMethods1(IEnumerable<string> input) public static IEnumerable<Func<string>> YieldReturnWithAnonymousMethods1(IEnumerable<string> input)
{ {
foreach (string line in input) { foreach (string line in input)
{
yield return () => line; yield return () => line;
} }
} }
public static IEnumerable<Func<string>> YieldReturnWithAnonymousMethods2(IEnumerable<string> input) public static IEnumerable<Func<string>> YieldReturnWithAnonymousMethods2(IEnumerable<string> input)
{ {
foreach (string line in input) { foreach (string line in input)
{
string copy = line; string copy = line;
yield return () => copy; yield return () => copy;
} }
@ -218,8 +242,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
public static IEnumerable<int> GetEvenNumbers(int n) public static IEnumerable<int> GetEvenNumbers(int n)
{ {
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++)
if (i % 2 == 0) { {
if (i % 2 == 0)
{
yield return i; yield return i;
} }
} }
@ -229,20 +255,29 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
public static IEnumerable<char> ExceptionHandling() public static IEnumerable<char> ExceptionHandling()
{ {
yield return 'a'; yield return 'a';
try { try
{
Console.WriteLine("1 - try"); Console.WriteLine("1 - try");
} catch (Exception) { }
catch (Exception)
{
Console.WriteLine("1 - catch"); Console.WriteLine("1 - catch");
} }
yield return 'b'; yield return 'b';
try { try
try { {
try
{
Console.WriteLine("2 - try"); Console.WriteLine("2 - try");
} finally { }
finally
{
Console.WriteLine("2 - finally"); Console.WriteLine("2 - finally");
} }
yield return 'c'; yield return 'c';
} finally { }
finally
{
Console.WriteLine("outer finally"); Console.WriteLine("outer finally");
} }
} }
@ -250,22 +285,29 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
public static IEnumerable<int> YieldBreakInCatch() public static IEnumerable<int> YieldBreakInCatch()
{ {
yield return 0; yield return 0;
try { try
{
Console.WriteLine("In Try"); Console.WriteLine("In Try");
} catch { }
catch
{
// yield return is not allowed in catch, but yield break is // yield return is not allowed in catch, but yield break is
yield break; yield break;
} }
yield return 1; yield return 1;
} }
public static IEnumerable<int> YieldBreakInCatchInTryFinally() public static IEnumerable<int> YieldBreakInCatchInTryFinally()
{ {
try { try
{
yield return 0; yield return 0;
try { try
{
Console.WriteLine("In Try"); Console.WriteLine("In Try");
} catch { }
catch
{
// yield return is not allowed in catch, but yield break is // yield return is not allowed in catch, but yield break is
// Note that pre-roslyn, this code triggers a compiler bug: // Note that pre-roslyn, this code triggers a compiler bug:
// If the finally block throws an exception, it ends up getting // If the finally block throws an exception, it ends up getting
@ -273,43 +315,58 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
yield break; yield break;
} }
yield return 1; yield return 1;
} finally { }
finally
{
Console.WriteLine("Finally"); Console.WriteLine("Finally");
} }
} }
public static IEnumerable<int> YieldBreakInTryCatchInTryFinally() public static IEnumerable<int> YieldBreakInTryCatchInTryFinally()
{ {
try { try
{
yield return 0; yield return 0;
try { try
{
Console.WriteLine("In Try"); Console.WriteLine("In Try");
// same compiler bug as in YieldBreakInCatchInTryFinally // same compiler bug as in YieldBreakInCatchInTryFinally
yield break; yield break;
} catch { }
catch
{
Console.WriteLine("Catch"); Console.WriteLine("Catch");
} }
yield return 1; yield return 1;
} finally { }
finally
{
Console.WriteLine("Finally"); Console.WriteLine("Finally");
} }
} }
public static IEnumerable<int> YieldBreakInTryFinallyInTryFinally(bool b) public static IEnumerable<int> YieldBreakInTryFinallyInTryFinally(bool b)
{ {
try { try
{
yield return 0; yield return 0;
try { try
{
Console.WriteLine("In Try"); Console.WriteLine("In Try");
if (b) { if (b)
{
// same compiler bug as in YieldBreakInCatchInTryFinally // same compiler bug as in YieldBreakInCatchInTryFinally
yield break; yield break;
} }
} finally { }
finally
{
Console.WriteLine("Inner Finally"); Console.WriteLine("Inner Finally");
} }
yield return 1; yield return 1;
} finally { }
finally
{
Console.WriteLine("Finally"); Console.WriteLine("Finally");
} }
} }
@ -318,15 +375,18 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
{ {
yield break; yield break;
} }
public static IEnumerable<int> UnconditionalThrowInTryFinally() public static IEnumerable<int> UnconditionalThrowInTryFinally()
{ {
// Here, MoveNext() doesn't call the finally methods at all // Here, MoveNext() doesn't call the finally methods at all
// (only indirectly via Dispose()) // (only indirectly via Dispose())
try { try
{
yield return 0; yield return 0;
throw new NotImplementedException(); throw new NotImplementedException();
} finally { }
finally
{
Console.WriteLine("Finally"); Console.WriteLine("Finally");
} }
} }
@ -334,13 +394,19 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
public static IEnumerable<int> NestedTryFinallyStartingOnSamePosition() public static IEnumerable<int> NestedTryFinallyStartingOnSamePosition()
{ {
// The first user IL instruction is already in 2 nested try blocks. // The first user IL instruction is already in 2 nested try blocks.
try { try
try { {
try
{
yield return 0; yield return 0;
} finally { }
finally
{
Console.WriteLine("Inner Finally"); Console.WriteLine("Inner Finally");
} }
} finally { }
finally
{
Console.WriteLine("Outer Finally"); Console.WriteLine("Outer Finally");
} }
} }
@ -349,15 +415,21 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
public static IEnumerable<int> TryFinallyWithTwoExitPoints(bool b) public static IEnumerable<int> TryFinallyWithTwoExitPoints(bool b)
{ {
// Uses goto for multiple non-exceptional exits out of try-finally. // Uses goto for multiple non-exceptional exits out of try-finally.
try { try
if (b) { {
if (b)
{
yield return 1; yield return 1;
goto exit1; goto exit1;
} else { }
else
{
yield return 2; yield return 2;
goto exit2; goto exit2;
} }
} finally { }
finally
{
Console.WriteLine("Finally"); Console.WriteLine("Finally");
} }
exit1: exit1:
@ -370,15 +442,21 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
#if !LEGACY_CSC #if !LEGACY_CSC
public static IEnumerable<int> YieldBreakInNestedTryFinally() public static IEnumerable<int> YieldBreakInNestedTryFinally()
{ {
try { try
{
yield return 1; yield return 1;
try { try
{
// Compiler bug: pre-Roslyn, the finally blocks will execute in the wrong order // Compiler bug: pre-Roslyn, the finally blocks will execute in the wrong order
yield break; yield break;
} finally { }
finally
{
Console.WriteLine("Inner Finally"); Console.WriteLine("Inner Finally");
} }
} finally { }
finally
{
Console.WriteLine("Outer Finally"); Console.WriteLine("Outer Finally");
} }
} }
@ -388,17 +466,23 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
// that exception gets caught by the catch block. // that exception gets caught by the catch block.
public static IEnumerable<int> TryFinallyWithTwoExitPointsInNestedTry(bool b) public static IEnumerable<int> TryFinallyWithTwoExitPointsInNestedTry(bool b)
{ {
try { try
{
yield return 1; yield return 1;
try { try
{
if (b) if (b)
goto exit1; goto exit1;
else else
goto exit2; goto exit2;
} catch { }
catch
{
Console.WriteLine("Catch"); Console.WriteLine("Catch");
} }
} finally { }
finally
{
Console.WriteLine("Finally"); Console.WriteLine("Finally");
} }
exit1: exit1:
@ -410,17 +494,23 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
public static IEnumerable<int> TryFinallyWithTwoExitPointsInNestedCatch(bool b) public static IEnumerable<int> TryFinallyWithTwoExitPointsInNestedCatch(bool b)
{ {
try { try
{
yield return 1; yield return 1;
try { try
{
Console.WriteLine("Nested Try"); Console.WriteLine("Nested Try");
} catch { }
catch
{
if (b) if (b)
goto exit1; goto exit1;
else else
goto exit2; goto exit2;
} }
} finally { }
finally
{
Console.WriteLine("Finally"); Console.WriteLine("Finally");
} }
exit1: exit1:
@ -434,9 +524,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
public static IEnumerable<int> LocalInFinally<T>(T a) where T : IDisposable public static IEnumerable<int> LocalInFinally<T>(T a) where T : IDisposable
{ {
yield return 1; yield return 1;
try { try
{
yield return 2; yield return 2;
} finally { }
finally
{
T val = a; T val = a;
val.Dispose(); val.Dispose();
val.Dispose(); val.Dispose();
@ -447,7 +540,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
public static IEnumerable<T> GenericYield<T>() where T : new() public static IEnumerable<T> GenericYield<T>() where T : new()
{ {
T val = new T(); T val = new T();
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++)
{
yield return val; yield return val;
} }
} }

55
ICSharpCode.Decompiler.Tests/TestCases/ILPretty/CS1xSwitch_Debug.cs

@ -55,7 +55,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static string SparseIntegerSwitch(int i) public static string SparseIntegerSwitch(int i)
{ {
Console.WriteLine("SparseIntegerSwitch: " + i); Console.WriteLine("SparseIntegerSwitch: " + i);
switch (i) { switch (i)
{
case -10000000: case -10000000:
return "-10 mln"; return "-10 mln";
case -100: case -100:
@ -85,7 +86,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static void SwitchOverInt(int i) public static void SwitchOverInt(int i)
{ {
switch (i) { switch (i)
{
case 0: case 0:
Console.WriteLine("zero"); Console.WriteLine("zero");
break; break;
@ -113,7 +115,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static string ShortSwitchOverString(string text) public static string ShortSwitchOverString(string text)
{ {
Console.WriteLine("ShortSwitchOverString: " + text); Console.WriteLine("ShortSwitchOverString: " + text);
switch (text) { switch (text)
{
case "First case": case "First case":
return "Text1"; return "Text1";
case "Second case": case "Second case":
@ -128,7 +131,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static string ShortSwitchOverStringWithNullCase(string text) public static string ShortSwitchOverStringWithNullCase(string text)
{ {
Console.WriteLine("ShortSwitchOverStringWithNullCase: " + text); Console.WriteLine("ShortSwitchOverStringWithNullCase: " + text);
switch (text) { switch (text)
{
case "First case": case "First case":
return "Text1"; return "Text1";
case "Second case": case "Second case":
@ -143,7 +147,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static string SwitchOverString1(string text) public static string SwitchOverString1(string text)
{ {
Console.WriteLine("SwitchOverString1: " + text); Console.WriteLine("SwitchOverString1: " + text);
switch (text) { switch (text)
{
case "First case": case "First case":
return "Text1"; return "Text1";
case "Second case": case "Second case":
@ -167,7 +172,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static string SwitchOverString2() public static string SwitchOverString2()
{ {
Console.WriteLine("SwitchOverString2:"); Console.WriteLine("SwitchOverString2:");
switch (Environment.UserName) { switch (Environment.UserName)
{
case "First case": case "First case":
return "Text1"; return "Text1";
case "Second case": case "Second case":
@ -197,9 +203,11 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static string TwoDifferentSwitchBlocksInTryFinally() public static string TwoDifferentSwitchBlocksInTryFinally()
{ {
try { try
{
Console.WriteLine("TwoDifferentSwitchBlocks:"); Console.WriteLine("TwoDifferentSwitchBlocks:");
switch (Environment.UserName) { switch (Environment.UserName)
{
case "First case": case "First case":
return "Text1"; return "Text1";
case "Second case": case "Second case":
@ -225,9 +233,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
default: default:
return "Default"; return "Default";
} }
} finally { }
finally
{
Console.WriteLine("Second switch:"); Console.WriteLine("Second switch:");
switch (Console.ReadLine()) { switch (Console.ReadLine())
{
case "12": case "12":
Console.WriteLine("Te43234xt1"); Console.WriteLine("Te43234xt1");
break; break;
@ -271,7 +282,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static string SwitchOverBool(bool b) public static string SwitchOverBool(bool b)
{ {
Console.WriteLine("SwitchOverBool: " + b); Console.WriteLine("SwitchOverBool: " + b);
switch (b) { switch (b)
{
case true: case true:
return bool.TrueString; return bool.TrueString;
case false: case false:
@ -284,8 +296,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static void SwitchInLoop(int i) public static void SwitchInLoop(int i)
{ {
Console.WriteLine("SwitchInLoop: " + i); Console.WriteLine("SwitchInLoop: " + i);
while (true) { while (true)
switch (i) { {
switch (i)
{
case 1: case 1:
Console.WriteLine("one"); Console.WriteLine("one");
break; break;
@ -310,7 +324,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static void SwitchWithGoto(int i) public static void SwitchWithGoto(int i)
{ {
Console.WriteLine("SwitchWithGoto: " + i); Console.WriteLine("SwitchWithGoto: " + i);
switch (i) { switch (i)
{
case 1: case 1:
Console.WriteLine("one"); Console.WriteLine("one");
goto default; goto default;
@ -340,10 +355,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
ArrayList arrayList = new ArrayList(); ArrayList arrayList = new ArrayList();
ArrayList arrayList2 = new ArrayList(); ArrayList arrayList2 = new ArrayList();
SetProperty[] properties = GetProperties(); SetProperty[] properties = GetProperties();
for (int i = 0; i < properties.Length; i++) { for (int i = 0; i < properties.Length; i++)
{
Console.WriteLine("In for-loop"); Console.WriteLine("In for-loop");
SetProperty setProperty = properties[i]; SetProperty setProperty = properties[i];
switch (setProperty.Property.Name) { switch (setProperty.Property.Name)
{
case "Name1": case "Name1":
setProperty.Set = 1; setProperty.Set = 1;
arrayList.Add(setProperty); arrayList.Add(setProperty);
@ -373,7 +390,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static void SwitchWithComplexCondition(string[] args) public static void SwitchWithComplexCondition(string[] args)
{ {
switch ((args.Length == 0) ? "dummy" : args[0]) { switch ((args.Length == 0) ? "dummy" : args[0])
{
case "a": case "a":
Console.WriteLine("a"); Console.WriteLine("a");
break; break;
@ -392,7 +410,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static void SwitchWithArray(string[] args) public static void SwitchWithArray(string[] args)
{ {
switch (args[0]) { switch (args[0])
{
case "a": case "a":
Console.WriteLine("a"); Console.WriteLine("a");
break; break;

55
ICSharpCode.Decompiler.Tests/TestCases/ILPretty/CS1xSwitch_Release.cs

@ -55,7 +55,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static string SparseIntegerSwitch(int i) public static string SparseIntegerSwitch(int i)
{ {
Console.WriteLine("SparseIntegerSwitch: " + i); Console.WriteLine("SparseIntegerSwitch: " + i);
switch (i) { switch (i)
{
case -10000000: case -10000000:
return "-10 mln"; return "-10 mln";
case -100: case -100:
@ -85,7 +86,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static void SwitchOverInt(int i) public static void SwitchOverInt(int i)
{ {
switch (i) { switch (i)
{
case 0: case 0:
Console.WriteLine("zero"); Console.WriteLine("zero");
break; break;
@ -113,7 +115,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static string ShortSwitchOverString(string text) public static string ShortSwitchOverString(string text)
{ {
Console.WriteLine("ShortSwitchOverString: " + text); Console.WriteLine("ShortSwitchOverString: " + text);
switch (text) { switch (text)
{
case "First case": case "First case":
return "Text1"; return "Text1";
case "Second case": case "Second case":
@ -128,7 +131,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static string ShortSwitchOverStringWithNullCase(string text) public static string ShortSwitchOverStringWithNullCase(string text)
{ {
Console.WriteLine("ShortSwitchOverStringWithNullCase: " + text); Console.WriteLine("ShortSwitchOverStringWithNullCase: " + text);
switch (text) { switch (text)
{
case "First case": case "First case":
return "Text1"; return "Text1";
case "Second case": case "Second case":
@ -143,7 +147,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static string SwitchOverString1(string text) public static string SwitchOverString1(string text)
{ {
Console.WriteLine("SwitchOverString1: " + text); Console.WriteLine("SwitchOverString1: " + text);
switch (text) { switch (text)
{
case "First case": case "First case":
return "Text1"; return "Text1";
case "Second case": case "Second case":
@ -167,7 +172,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static string SwitchOverString2() public static string SwitchOverString2()
{ {
Console.WriteLine("SwitchOverString2:"); Console.WriteLine("SwitchOverString2:");
switch (Environment.UserName) { switch (Environment.UserName)
{
case "First case": case "First case":
return "Text1"; return "Text1";
case "Second case": case "Second case":
@ -197,9 +203,11 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static string TwoDifferentSwitchBlocksInTryFinally() public static string TwoDifferentSwitchBlocksInTryFinally()
{ {
try { try
{
Console.WriteLine("TwoDifferentSwitchBlocks:"); Console.WriteLine("TwoDifferentSwitchBlocks:");
switch (Environment.UserName) { switch (Environment.UserName)
{
case "First case": case "First case":
return "Text1"; return "Text1";
case "Second case": case "Second case":
@ -225,9 +233,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
default: default:
return "Default"; return "Default";
} }
} finally { }
finally
{
Console.WriteLine("Second switch:"); Console.WriteLine("Second switch:");
switch (Console.ReadLine()) { switch (Console.ReadLine())
{
case "12": case "12":
Console.WriteLine("Te43234xt1"); Console.WriteLine("Te43234xt1");
break; break;
@ -271,7 +282,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static string SwitchOverBool(bool b) public static string SwitchOverBool(bool b)
{ {
Console.WriteLine("SwitchOverBool: " + b); Console.WriteLine("SwitchOverBool: " + b);
switch (b) { switch (b)
{
case true: case true:
return bool.TrueString; return bool.TrueString;
case false: case false:
@ -284,8 +296,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static void SwitchInLoop(int i) public static void SwitchInLoop(int i)
{ {
Console.WriteLine("SwitchInLoop: " + i); Console.WriteLine("SwitchInLoop: " + i);
while (true) { while (true)
switch (i) { {
switch (i)
{
case 1: case 1:
Console.WriteLine("one"); Console.WriteLine("one");
break; break;
@ -310,7 +324,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static void SwitchWithGoto(int i) public static void SwitchWithGoto(int i)
{ {
Console.WriteLine("SwitchWithGoto: " + i); Console.WriteLine("SwitchWithGoto: " + i);
switch (i) { switch (i)
{
case 1: case 1:
Console.WriteLine("one"); Console.WriteLine("one");
goto default; goto default;
@ -340,10 +355,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
ArrayList arrayList = new ArrayList(); ArrayList arrayList = new ArrayList();
ArrayList arrayList2 = new ArrayList(); ArrayList arrayList2 = new ArrayList();
SetProperty[] properties = GetProperties(); SetProperty[] properties = GetProperties();
for (int i = 0; i < properties.Length; i++) { for (int i = 0; i < properties.Length; i++)
{
Console.WriteLine("In for-loop"); Console.WriteLine("In for-loop");
SetProperty setProperty = properties[i]; SetProperty setProperty = properties[i];
switch (setProperty.Property.Name) { switch (setProperty.Property.Name)
{
case "Name1": case "Name1":
setProperty.Set = 1; setProperty.Set = 1;
arrayList.Add(setProperty); arrayList.Add(setProperty);
@ -373,7 +390,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static void SwitchWithComplexCondition(string[] args) public static void SwitchWithComplexCondition(string[] args)
{ {
switch ((args.Length == 0) ? "dummy" : args[0]) { switch ((args.Length == 0) ? "dummy" : args[0])
{
case "a": case "a":
Console.WriteLine("a"); Console.WriteLine("a");
break; break;
@ -392,7 +410,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static void SwitchWithArray(string[] args) public static void SwitchWithArray(string[] args)
{ {
switch (args[0]) { switch (args[0])
{
case "a": case "a":
Console.WriteLine("a"); Console.WriteLine("a");
break; break;

21
ICSharpCode.Decompiler.Tests/TestCases/ILPretty/FSharpLoops_Debug.cs

@ -65,7 +65,8 @@ public static class Program
public override int GenerateNext(ref IEnumerable<int> next) public override int GenerateNext(ref IEnumerable<int> next)
{ {
switch (pc) { switch (pc)
{
default: default:
pc = 1; pc = 1;
current = 1; current = 1;
@ -87,7 +88,8 @@ public static class Program
public override bool get_CheckClose() public override bool get_CheckClose()
{ {
switch (pc) { switch (pc)
{
default: default:
return false; return false;
case 0: case 0:
@ -137,23 +139,28 @@ public static class Program
public static int main(string[] argv) public static int main(string[] argv)
{ {
IDisposable disposable; IDisposable disposable;
using (Program.disposable()) { using (Program.disposable())
{
Console.WriteLine("Hello 1"); Console.WriteLine("Hello 1");
disposable = Program.disposable(); disposable = Program.disposable();
} }
using (disposable) { using (disposable)
{
IEnumerable<int> seq = getSeq(); IEnumerable<int> seq = getSeq();
foreach (int item in seq) { foreach (int item in seq)
{
Console.WriteLine(item); Console.WriteLine(item);
} }
FSharpList<int> fSharpList = getList(); FSharpList<int> fSharpList = getList();
for (FSharpList<int> tailOrNull = fSharpList.TailOrNull; tailOrNull != null; tailOrNull = fSharpList.TailOrNull) { for (FSharpList<int> tailOrNull = fSharpList.TailOrNull; tailOrNull != null; tailOrNull = fSharpList.TailOrNull)
{
int headOrDefault = fSharpList.HeadOrDefault; int headOrDefault = fSharpList.HeadOrDefault;
Console.WriteLine(headOrDefault); Console.WriteLine(headOrDefault);
fSharpList = tailOrNull; fSharpList = tailOrNull;
} }
int[] array = getArray(); int[] array = getArray();
foreach (int value in array) { foreach (int value in array)
{
Console.WriteLine(value); Console.WriteLine(value);
} }
return 0; return 0;

21
ICSharpCode.Decompiler.Tests/TestCases/ILPretty/FSharpLoops_Release.cs

@ -66,7 +66,8 @@ public static class Program
public override int GenerateNext(ref IEnumerable<int> next) public override int GenerateNext(ref IEnumerable<int> next)
{ {
switch (pc) { switch (pc)
{
default: default:
pc = 1; pc = 1;
current = 1; current = 1;
@ -88,7 +89,8 @@ public static class Program
public override bool get_CheckClose() public override bool get_CheckClose()
{ {
switch (pc) { switch (pc)
{
default: default:
return false; return false;
case 0: case 0:
@ -138,17 +140,21 @@ public static class Program
public static int main(string[] argv) public static int main(string[] argv)
{ {
IDisposable disposable; IDisposable disposable;
using (Program.disposable()) { using (Program.disposable())
{
Console.WriteLine("Hello 1"); Console.WriteLine("Hello 1");
disposable = Program.disposable(); disposable = Program.disposable();
} }
using (disposable) { using (disposable)
{
IEnumerable<int> seq = getSeq(); IEnumerable<int> seq = getSeq();
foreach (int item in seq) { foreach (int item in seq)
{
Console.WriteLine(item); Console.WriteLine(item);
} }
FSharpList<int> fSharpList = FSharpList<int>.Cons(1, FSharpList<int>.Empty); FSharpList<int> fSharpList = FSharpList<int>.Cons(1, FSharpList<int>.Empty);
for (FSharpList<int> tailOrNull = fSharpList.TailOrNull; tailOrNull != null; tailOrNull = fSharpList.TailOrNull) { for (FSharpList<int> tailOrNull = fSharpList.TailOrNull; tailOrNull != null; tailOrNull = fSharpList.TailOrNull)
{
int headOrDefault = fSharpList.HeadOrDefault; int headOrDefault = fSharpList.HeadOrDefault;
Console.WriteLine(headOrDefault); Console.WriteLine(headOrDefault);
fSharpList = tailOrNull; fSharpList = tailOrNull;
@ -156,7 +162,8 @@ public static class Program
int[] array = new int[1] { int[] array = new int[1] {
1 1
}; };
for (int headOrDefault = 0; headOrDefault < array.Length; headOrDefault++) { for (int headOrDefault = 0; headOrDefault < array.Length; headOrDefault++)
{
Console.WriteLine(array[headOrDefault]); Console.WriteLine(array[headOrDefault]);
} }
return 0; return 0;

18
ICSharpCode.Decompiler.Tests/TestCases/ILPretty/FSharpUsing_Debug.cs

@ -5,7 +5,8 @@ public static class FSharpUsingPatterns
{ {
public static void sample1() public static void sample1()
{ {
using (FileStream fileStream = File.Create("x.txt")) { using (FileStream fileStream = File.Create("x.txt"))
{
fileStream.WriteByte((byte)1); fileStream.WriteByte((byte)1);
} }
} }
@ -13,7 +14,8 @@ public static class FSharpUsingPatterns
public static void sample2() public static void sample2()
{ {
Console.WriteLine("some text"); Console.WriteLine("some text");
using (FileStream fileStream = File.Create("x.txt")) { using (FileStream fileStream = File.Create("x.txt"))
{
fileStream.WriteByte((byte)2); fileStream.WriteByte((byte)2);
Console.WriteLine("some text"); Console.WriteLine("some text");
} }
@ -22,7 +24,8 @@ public static class FSharpUsingPatterns
public static void sample3() public static void sample3()
{ {
Console.WriteLine("some text"); Console.WriteLine("some text");
using (FileStream fileStream = File.Create("x.txt")) { using (FileStream fileStream = File.Create("x.txt"))
{
fileStream.WriteByte((byte)3); fileStream.WriteByte((byte)3);
} }
Console.WriteLine("some text"); Console.WriteLine("some text");
@ -32,7 +35,8 @@ public static class FSharpUsingPatterns
{ {
Console.WriteLine("some text"); Console.WriteLine("some text");
int num; int num;
using (FileStream fileStream = File.OpenRead("x.txt")) { using (FileStream fileStream = File.OpenRead("x.txt"))
{
num = fileStream.ReadByte(); num = fileStream.ReadByte();
} }
int num2 = num; int num2 = num;
@ -43,12 +47,14 @@ public static class FSharpUsingPatterns
{ {
Console.WriteLine("some text"); Console.WriteLine("some text");
int num; int num;
using (FileStream fileStream = File.OpenRead("x.txt")) { using (FileStream fileStream = File.OpenRead("x.txt"))
{
num = fileStream.ReadByte(); num = fileStream.ReadByte();
} }
int num2 = num; int num2 = num;
int num3; int num3;
using (FileStream fileStream = File.OpenRead("x.txt")) { using (FileStream fileStream = File.OpenRead("x.txt"))
{
fileStream.ReadByte(); fileStream.ReadByte();
num3 = fileStream.ReadByte(); num3 = fileStream.ReadByte();
} }

18
ICSharpCode.Decompiler.Tests/TestCases/ILPretty/FSharpUsing_Release.cs

@ -5,7 +5,8 @@ public static class FSharpUsingPatterns
{ {
public static void sample1() public static void sample1()
{ {
using (FileStream fileStream = File.Create("x.txt")) { using (FileStream fileStream = File.Create("x.txt"))
{
fileStream.WriteByte(1); fileStream.WriteByte(1);
} }
} }
@ -13,7 +14,8 @@ public static class FSharpUsingPatterns
public static void sample2() public static void sample2()
{ {
Console.WriteLine("some text"); Console.WriteLine("some text");
using (FileStream fileStream = File.Create("x.txt")) { using (FileStream fileStream = File.Create("x.txt"))
{
fileStream.WriteByte(2); fileStream.WriteByte(2);
Console.WriteLine("some text"); Console.WriteLine("some text");
} }
@ -22,7 +24,8 @@ public static class FSharpUsingPatterns
public static void sample3() public static void sample3()
{ {
Console.WriteLine("some text"); Console.WriteLine("some text");
using (FileStream fileStream = File.Create("x.txt")) { using (FileStream fileStream = File.Create("x.txt"))
{
fileStream.WriteByte(3); fileStream.WriteByte(3);
} }
Console.WriteLine("some text"); Console.WriteLine("some text");
@ -32,7 +35,8 @@ public static class FSharpUsingPatterns
{ {
Console.WriteLine("some text"); Console.WriteLine("some text");
int num; int num;
using (FileStream fileStream = File.OpenRead("x.txt")) { using (FileStream fileStream = File.OpenRead("x.txt"))
{
num = fileStream.ReadByte(); num = fileStream.ReadByte();
} }
int num2 = num; int num2 = num;
@ -43,12 +47,14 @@ public static class FSharpUsingPatterns
{ {
Console.WriteLine("some text"); Console.WriteLine("some text");
int num; int num;
using (FileStream fileStream = File.OpenRead("x.txt")) { using (FileStream fileStream = File.OpenRead("x.txt"))
{
num = fileStream.ReadByte(); num = fileStream.ReadByte();
} }
int num2 = num; int num2 = num;
int num3; int num3;
using (FileStream fileStream = File.OpenRead("x.txt")) { using (FileStream fileStream = File.OpenRead("x.txt"))
{
fileStream.ReadByte(); fileStream.ReadByte();
num3 = fileStream.ReadByte(); num3 = fileStream.ReadByte();
} }

3
ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue1047.cs

@ -6,7 +6,8 @@
private void ProblemMethod() private void ProblemMethod()
{ {
while (!dummy) { while (!dummy)
{
} }
} }
} }

3
ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue1454.cs

@ -10,7 +10,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.ILPretty
bitArray.CopyTo(array, 0); bitArray.CopyTo(array, 0);
int num = 0; int num = 0;
array[array.Length - 1] &= ~(-1 << bitArray.Count % 32); array[array.Length - 1] &= ~(-1 << bitArray.Count % 32);
for (int i = 0; i < array.Length; i++) { for (int i = 0; i < array.Length; i++)
{
int num2 = array[i]; int num2 = array[i];
num2 -= ((num2 >> 1) & 0x55555555); num2 -= ((num2 >> 1) & 0x55555555);
num2 = (num2 & 0x33333333) + ((num2 >> 2) & 0x33333333); num2 = (num2 & 0x33333333) + ((num2 >> 2) & 0x33333333);

2
ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue1681.cs

@ -4,7 +4,7 @@
{ {
public int importsClausePosition; public int importsClausePosition;
} }
internal class Issue1681 : BaseClass internal class Issue1681 : BaseClass
{ {
public void Test() public void Test()

13
ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue1918.cs

@ -8,17 +8,22 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.ILPretty
public unsafe void ProblemFunction(Guid[] A_0, int A_1) public unsafe void ProblemFunction(Guid[] A_0, int A_1)
{ {
fixed (Guid* ptr = A_0) { fixed (Guid* ptr = A_0)
{
void* ptr2 = ptr; void* ptr2 = ptr;
UIntPtr* ptr3 = (UIntPtr*)((byte*)ptr2 - sizeof(UIntPtr)); UIntPtr* ptr3 = (UIntPtr*)((byte*)ptr2 - sizeof(UIntPtr));
UIntPtr uIntPtr = *ptr3; UIntPtr uIntPtr = *ptr3;
try { try
{
*ptr3 = (UIntPtr)(ulong)A_1; *ptr3 = (UIntPtr)(ulong)A_1;
} finally { }
finally
{
*ptr3 = uIntPtr; *ptr3 = uIntPtr;
} }
} }
fixed (Guid[] ptr = NullVal) { fixed (Guid[] ptr = NullVal)
{
} }
} }
} }

3
ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue646.cs

@ -12,7 +12,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.ILPretty
public static void Main() public static void Main()
{ {
List<string> list = new List<string>(); List<string> list = new List<string>();
foreach (string item in list) { foreach (string item in list)
{
Debug.WriteLine(item); Debug.WriteLine(item);
} }
} }

25
ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue684.cs

@ -9,25 +9,34 @@ public static class Issue684
// Point of this test was to ensure the stack slot here uses an appropriate type, // Point of this test was to ensure the stack slot here uses an appropriate type,
// (bool instead of int). Unfortunately our type fixup runs too late to affect variable names. // (bool instead of int). Unfortunately our type fixup runs too late to affect variable names.
bool num2 = num >= 1000; bool num2 = num >= 1000;
if (!num2) { if (!num2)
{
num2 = (num < 2); num2 = (num < 2);
} }
if (num2) { if (num2)
{
Console.WriteLine(-1); Console.WriteLine(-1);
} else { }
else
{
int i = 2; int i = 2;
for (int num3 = 2; num3 <= num; num3 = i) { for (int num3 = 2; num3 <= num; num3 = i)
{
Console.WriteLine(num3); Console.WriteLine(num3);
for (; i <= num; i += num3) { for (; i <= num; i += num3)
{
int num4 = array[i] = 1; int num4 = array[i] = 1;
} }
i = num3; i = num3;
while (true) { while (true)
{
bool num5 = i <= num; bool num5 = i <= num;
if (num5) { if (num5)
{
num5 = (array[i] != 0); num5 = (array[i] != 0);
} }
if (!num5) { if (!num5)
{
break; break;
} }
i++; i++;

3
ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue959.cs

@ -4,7 +4,8 @@
{ {
public void Test(bool arg) public void Test(bool arg)
{ {
if (!arg && arg) { if (!arg && arg)
{
} }
} }

21
ICSharpCode.Decompiler.Tests/TestCases/ILPretty/SequenceOfNestedIfs.cs

@ -18,25 +18,32 @@ public class SequenceOfNestedIfs
} }
public override void CreateMaterials() public override void CreateMaterials()
{ {
if (!_clear) { if (!_clear)
if (!CheckShader()) { {
if (!CheckShader())
{
return; return;
} }
_material = new Material(); _material = new Material();
} }
if (!_material) { if (!_material)
if (!CheckShader()) { {
if (!CheckShader())
{
return; return;
} }
_material = new Material(); _material = new Material();
} }
if (!_material) { if (!_material)
if (!CheckShader()) { {
if (!CheckShader())
{
return; return;
} }
_material = new Material(); _material = new Material();
} }
if (!_material && CheckShader()) { if (!_material && CheckShader())
{
_material = new Material(); _material = new Material();
} }
} }

25
ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Unsafe.cs

@ -17,7 +17,8 @@ internal sealed class ExtraUnsafeTests
{ {
public unsafe static void PinWithTypeMismatch(ref uint managedPtr) public unsafe static void PinWithTypeMismatch(ref uint managedPtr)
{ {
fixed (ushort* ptr = &Unsafe.As<uint, ushort>(ref managedPtr)) { fixed (ushort* ptr = &Unsafe.As<uint, ushort>(ref managedPtr))
{
} }
} }
@ -29,7 +30,8 @@ internal sealed class ExtraUnsafeTests
public static ref ulong RefAssignTypeMismatch(ref uint a, ref uint b) public static ref ulong RefAssignTypeMismatch(ref uint a, ref uint b)
{ {
ref ushort reference = ref Unsafe.As<uint, ushort>(ref a); ref ushort reference = ref Unsafe.As<uint, ushort>(ref a);
if (a != 0) { if (a != 0)
{
reference = ref Unsafe.As<uint, ushort>(ref b); reference = ref Unsafe.As<uint, ushort>(ref b);
} }
Console.WriteLine(reference); Console.WriteLine(reference);
@ -40,11 +42,15 @@ internal sealed class ExtraUnsafeTests
{ {
//The blocks IL_0019 are reachable both inside and outside the pinned region starting at IL_0013. ILSpy has duplicated these blocks in order to place them both within and outside the `fixed` statement. //The blocks IL_0019 are reachable both inside and outside the pinned region starting at IL_0013. ILSpy has duplicated these blocks in order to place them both within and outside the `fixed` statement.
byte[] array; byte[] array;
if ((array = arr) != null && array.Length != 0) { if ((array = arr) != null && array.Length != 0)
fixed (byte* ptr = &array[0]) { {
fixed (byte* ptr = &array[0])
{
*(int*)ptr = val; *(int*)ptr = val;
} }
} else { }
else
{
/*pinned*/ref byte reference = ref *(byte*)null; /*pinned*/ref byte reference = ref *(byte*)null;
*(int*)Unsafe.AsPointer(ref reference) = val; *(int*)Unsafe.AsPointer(ref reference) = val;
} }
@ -55,14 +61,17 @@ internal sealed class ExtraUnsafeTests
{ {
//The blocks IL_0016 are reachable both inside and outside the pinned region starting at IL_0007. ILSpy has duplicated these blocks in order to place them both within and outside the `fixed` statement. //The blocks IL_0016 are reachable both inside and outside the pinned region starting at IL_0007. ILSpy has duplicated these blocks in order to place them both within and outside the `fixed` statement.
ref int reference; ref int reference;
fixed (int* ptr = &a[0]) { fixed (int* ptr = &a[0])
if (*ptr <= 0) { {
if (*ptr <= 0)
{
ptr[4 * 0] = 1; ptr[4 * 0] = 1;
return; return;
} }
reference = ref *ptr; reference = ref *ptr;
} }
fixed (int* ptr = &b[reference]) { fixed (int* ptr = &b[reference])
{
ptr[4 * 0] = 1; ptr[4 * 0] = 1;
} }
} }

43
ICSharpCode.Decompiler.Tests/TestCases/Pretty/Async.cs

@ -95,7 +95,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public async void TwoAwaitsWithDifferentAwaiterTypes() public async void TwoAwaitsWithDifferentAwaiterTypes()
{ {
Console.WriteLine("Before"); Console.WriteLine("Before");
if (await SimpleBoolTaskMethod()) { if (await SimpleBoolTaskMethod())
{
await Task.Delay(TimeSpan.FromSeconds(1.0)); await Task.Delay(TimeSpan.FromSeconds(1.0));
} }
Console.WriteLine("After"); Console.WriteLine("After");
@ -103,7 +104,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public async void AwaitInLoopCondition() public async void AwaitInLoopCondition()
{ {
while (await SimpleBoolTaskMethod()) { while (await SimpleBoolTaskMethod())
{
Console.WriteLine("Body"); Console.WriteLine("Body");
} }
} }
@ -111,14 +113,20 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
#if CS60 #if CS60
public async Task AwaitInCatch(bool b, Task<int> task1, Task<int> task2) public async Task AwaitInCatch(bool b, Task<int> task1, Task<int> task2)
{ {
try { try
{
Console.WriteLine("Start try"); Console.WriteLine("Start try");
await task1; await task1;
Console.WriteLine("End try"); Console.WriteLine("End try");
} catch (Exception) { }
if (!b) { catch (Exception)
{
if (!b)
{
await task2; await task2;
} else { }
else
{
Console.WriteLine("No await"); Console.WriteLine("No await");
} }
} }
@ -126,14 +134,20 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public async Task AwaitInFinally(bool b, Task<int> task1, Task<int> task2) public async Task AwaitInFinally(bool b, Task<int> task1, Task<int> task2)
{ {
try { try
{
Console.WriteLine("Start try"); Console.WriteLine("Start try");
await task1; await task1;
Console.WriteLine("End try"); Console.WriteLine("End try");
} finally { }
if (!b) { finally
{
if (!b)
{
await task2; await task2;
} else { }
else
{
Console.WriteLine("No await"); Console.WriteLine("No await");
} }
} }
@ -144,7 +158,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{ {
await Task.Delay(100); await Task.Delay(100);
int num = 0; int num = 0;
foreach (int item in items) { foreach (int item in items)
{
num += item; num += item;
} }
return num; return num;
@ -174,13 +189,15 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static async Task InfiniteLoop() public static async Task InfiniteLoop()
{ {
while (true) { while (true)
{
} }
} }
public static async Task InfiniteLoopWithAwait() public static async Task InfiniteLoopWithAwait()
{ {
while (true) { while (true)
{
await Task.Delay(10); await Task.Delay(10);
} }
} }

12
ICSharpCode.Decompiler.Tests/TestCases/Pretty/AsyncForeach.cs

@ -27,8 +27,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public async Task<int> SumIntegers(IAsyncEnumerable<int> items, CancellationToken token) public async Task<int> SumIntegers(IAsyncEnumerable<int> items, CancellationToken token)
{ {
int sum = 0; int sum = 0;
await foreach (int item in items.WithCancellation(token)) { await foreach (int item in items.WithCancellation(token))
if (token.IsCancellationRequested) { {
if (token.IsCancellationRequested)
{
break; break;
} }
sum += item; sum += item;
@ -39,8 +41,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public async Task<int> MaxInteger(IAsyncEnumerable<int> items) public async Task<int> MaxInteger(IAsyncEnumerable<int> items)
{ {
int max = int.MinValue; int max = int.MinValue;
await foreach (int item in items) { await foreach (int item in items)
if (item > max) { {
if (item > max)
{
max = item; max = item;
} }
} }

16
ICSharpCode.Decompiler.Tests/TestCases/Pretty/AsyncStreams.cs

@ -10,7 +10,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{ {
public static async IAsyncEnumerable<int> CountTo(int until) public static async IAsyncEnumerable<int> CountTo(int until)
{ {
for (int i = 0; i < until; i++) { for (int i = 0; i < until; i++)
{
yield return i; yield return i;
await Task.Delay(10); await Task.Delay(10);
} }
@ -24,14 +25,16 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static async IAsyncEnumerator<int> InfiniteLoop() public static async IAsyncEnumerator<int> InfiniteLoop()
{ {
while (true) { while (true)
{
} }
yield break; yield break;
} }
public static async IAsyncEnumerable<int> InfiniteLoopWithAwait() public static async IAsyncEnumerable<int> InfiniteLoopWithAwait()
{ {
while (true) { while (true)
{
await Task.Delay(10); await Task.Delay(10);
} }
yield break; yield break;
@ -39,11 +42,14 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public async IAsyncEnumerable<int> AwaitInFinally() public async IAsyncEnumerable<int> AwaitInFinally()
{ {
try { try
{
Console.WriteLine("try"); Console.WriteLine("try");
yield return 1; yield return 1;
Console.WriteLine("end try"); Console.WriteLine("end try");
} finally { }
finally
{
Console.WriteLine("finally"); Console.WriteLine("finally");
await Task.Yield(); await Task.Yield();
Console.WriteLine("end finally"); Console.WriteLine("end finally");

12
ICSharpCode.Decompiler.Tests/TestCases/Pretty/AsyncUsing.cs

@ -25,28 +25,32 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static async void TestAsyncUsing(IAsyncDisposable disposable) public static async void TestAsyncUsing(IAsyncDisposable disposable)
{ {
await using (disposable) { await using (disposable)
{
Console.WriteLine("Hello"); Console.WriteLine("Hello");
} }
} }
public static async void TestAsyncUsingClass() public static async void TestAsyncUsingClass()
{ {
await using (AsyncDisposableClass test = new AsyncDisposableClass()) { await using (AsyncDisposableClass test = new AsyncDisposableClass())
{
Use(test); Use(test);
} }
} }
public static async void TestAsyncUsingStruct() public static async void TestAsyncUsingStruct()
{ {
await using (AsyncDisposableStruct asyncDisposableStruct = default(AsyncDisposableStruct)) { await using (AsyncDisposableStruct asyncDisposableStruct = default(AsyncDisposableStruct))
{
Use(asyncDisposableStruct); Use(asyncDisposableStruct);
} }
} }
public static async void TestAsyncUsingNullableStruct() public static async void TestAsyncUsingNullableStruct()
{ {
await using (AsyncDisposableStruct? asyncDisposableStruct = new AsyncDisposableStruct?(default(AsyncDisposableStruct))) { await using (AsyncDisposableStruct? asyncDisposableStruct = new AsyncDisposableStruct?(default(AsyncDisposableStruct)))
{
Use(asyncDisposableStruct); Use(asyncDisposableStruct);
} }
} }

18
ICSharpCode.Decompiler.Tests/TestCases/Pretty/CheckedUnchecked.cs

@ -52,8 +52,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void ForWithCheckedIteratorAndUncheckedBody(int n) public void ForWithCheckedIteratorAndUncheckedBody(int n)
{ {
checked { checked
for (int i = n + 1; i < n + 1; i++) { {
for (int i = n + 1; i < n + 1; i++)
{
n = unchecked(i * i); n = unchecked(i * i);
} }
} }
@ -62,7 +64,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void ForWithCheckedInitializerAndUncheckedIterator(int n) public void ForWithCheckedInitializerAndUncheckedIterator(int n)
{ {
int num = n; int num = n;
for (num = checked(num - 10); num < n; num++) { for (num = checked(num - 10); num < n; num++)
{
n--; n--;
} }
} }
@ -111,13 +114,16 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public short Unbox(TypeCode c, object b) public short Unbox(TypeCode c, object b)
{ {
checked { checked
switch (c) { {
switch (c)
{
case TypeCode.Int32: case TypeCode.Int32:
return (short)((Box<int>)b).Value; return (short)((Box<int>)b).Value;
case TypeCode.UInt32: case TypeCode.UInt32:
return (short)((Box<uint>)b).Value; return (short)((Box<uint>)b).Value;
case TypeCode.Double: { case TypeCode.Double:
{
float num = (float)((Box<double>)b).Value; float num = (float)((Box<double>)b).Value;
Console.WriteLine(num); Console.WriteLine(num);
return (short)num; return (short)num;

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

@ -45,12 +45,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public bool HasIndex; public bool HasIndex;
public int Field; public int Field;
} }
public class MutableClass public class MutableClass
{ {
public int Field; public int Field;
public short ShortField; public short ShortField;
public int Property { public int Property {
get; get;
set; set;
@ -65,7 +65,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
get; get;
set; set;
} }
public uint this[string name] { public uint this[string name] {
get { get {
return 0u; return 0u;
@ -500,27 +500,27 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{ {
return new MutableClass(); return new MutableClass();
} }
private int[,] Array() private int[,] Array()
{ {
return null; return null;
} }
private unsafe int* GetPointer() private unsafe int* GetPointer()
{ {
return null; return null;
} }
public int GetIndex() public int GetIndex()
{ {
return new Random().Next(0, 100); return new Random().Next(0, 100);
} }
public int[] GetArray() public int[] GetArray()
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
public int GetValue(int value) public int GetValue(int value)
{ {
return value; return value;
@ -530,7 +530,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{ {
return a == 'A'; return a == 'A';
} }
public void Int32_Local_Add(int i) public void Int32_Local_Add(int i)
{ {
i++; i++;
@ -539,7 +539,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
i += 5; i += 5;
Console.WriteLine(i += 5); Console.WriteLine(i += 5);
} }
public void Int32_Local_Sub(int i) public void Int32_Local_Sub(int i)
{ {
i--; i--;
@ -548,61 +548,61 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
i -= 5; i -= 5;
Console.WriteLine(i -= 5); Console.WriteLine(i -= 5);
} }
public void Int32_Local_Mul(int i) public void Int32_Local_Mul(int i)
{ {
i *= 5; i *= 5;
Console.WriteLine(i *= 5); Console.WriteLine(i *= 5);
} }
public void Int32_Local_Div(int i) public void Int32_Local_Div(int i)
{ {
i /= 5; i /= 5;
Console.WriteLine(i /= 5); Console.WriteLine(i /= 5);
} }
public void Int32_Local_Rem(int i) public void Int32_Local_Rem(int i)
{ {
i %= 5; i %= 5;
Console.WriteLine(i %= 5); Console.WriteLine(i %= 5);
} }
public void Int32_Local_BitAnd(int i) public void Int32_Local_BitAnd(int i)
{ {
i &= 5; i &= 5;
Console.WriteLine(i &= 5); Console.WriteLine(i &= 5);
} }
public void Int32_Local_BitOr(int i) public void Int32_Local_BitOr(int i)
{ {
i |= 5; i |= 5;
Console.WriteLine(i |= 5); Console.WriteLine(i |= 5);
} }
public void Int32_Local_BitXor(int i) public void Int32_Local_BitXor(int i)
{ {
i ^= 5; i ^= 5;
Console.WriteLine(i ^= 5); Console.WriteLine(i ^= 5);
} }
public void Int32_Local_ShiftLeft(int i) public void Int32_Local_ShiftLeft(int i)
{ {
i <<= 5; i <<= 5;
Console.WriteLine(i <<= 5); Console.WriteLine(i <<= 5);
} }
public void Int32_Local_ShiftRight(int i) public void Int32_Local_ShiftRight(int i)
{ {
i >>= 5; i >>= 5;
Console.WriteLine(i >>= 5); Console.WriteLine(i >>= 5);
} }
public void IntegerWithInline(int i) public void IntegerWithInline(int i)
{ {
Console.WriteLine(i += 5); Console.WriteLine(i += 5);
Console.WriteLine(i); Console.WriteLine(i);
} }
public void IntegerField(int i) public void IntegerField(int i)
{ {
Console.WriteLine(test1 += i); Console.WriteLine(test1 += i);
@ -610,27 +610,28 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
Console.WriteLine(test1 -= i); Console.WriteLine(test1 -= i);
Console.WriteLine(test1); Console.WriteLine(test1);
} }
public void Array(int i) public void Array(int i)
{ {
Console.WriteLine(array1[i] += i); Console.WriteLine(array1[i] += i);
Console.WriteLine(array1[i * 2] += i * 2); Console.WriteLine(array1[i * 2] += i * 2);
} }
public int ArrayUsageWithMethods() public int ArrayUsageWithMethods()
{ {
return GetArray()[GetIndex()]++; return GetArray()[GetIndex()]++;
} }
public void NestedField() public void NestedField()
{ {
if (field1.HasIndex) { if (field1.HasIndex)
{
Console.WriteLine(field1.Field *= 2); Console.WriteLine(field1.Field *= 2);
field1.Field++; field1.Field++;
Console.WriteLine(field1.Field++); Console.WriteLine(field1.Field++);
} }
} }
public void Enum() public void Enum()
{ {
enumField |= MyEnum.Two; enumField |= MyEnum.Two;
@ -651,7 +652,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{ {
return i + ++j; return i + ++j;
} }
public int PreIncrementArrayElement(int[] array, int pos) public int PreIncrementArrayElement(int[] array, int pos)
{ {
return --array[pos]; return --array[pos];
@ -706,7 +707,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{ {
return ++M().Field; return ++M().Field;
} }
public int PostIncrementInstanceField() public int PostIncrementInstanceField()
{ {
return M().Field++; return M().Field++;
@ -731,7 +732,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{ {
return ++m.Field; return ++m.Field;
} }
public int PostIncrementInstanceField2(MutableClass m) public int PostIncrementInstanceField2(MutableClass m)
{ {
return m.Field++; return m.Field++;
@ -4587,9 +4588,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
// The 'chars[i]' result is stored in a temporary, and both branches use the // The 'chars[i]' result is stored in a temporary, and both branches use the
// same temporary. In order to inline the generated value-type temporary, we // same temporary. In order to inline the generated value-type temporary, we
// need to split it, even though it has the address taken for the ToString() call. // need to split it, even though it has the address taken for the ToString() call.
if (flag) { if (flag)
{
strings[1] += chars[i]; strings[1] += chars[i];
} else { }
else
{
strings[0] += chars[i]; strings[0] += chars[i];
} }
} }

5
ICSharpCode.Decompiler.Tests/TestCases/Pretty/CustomAttributeConflicts.cs

@ -1,8 +1,9 @@
using CustomAttributeConflicts.NS1; using System;
using CustomAttributeConflicts.NS1;
using CustomAttributeConflicts.NS2; using CustomAttributeConflicts.NS2;
using CustomAttributeConflicts.NSWithConflictingTypes; using CustomAttributeConflicts.NSWithConflictingTypes;
using CustomAttributeConflicts.NSWithConflictingTypes2; using CustomAttributeConflicts.NSWithConflictingTypes2;
using System;
namespace CustomAttributeConflicts namespace CustomAttributeConflicts
{ {

41
ICSharpCode.Decompiler.Tests/TestCases/Pretty/CustomShortCircuitOperators.cs

@ -82,13 +82,16 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty.CustomShortCircuitOperat
private static void Test2() private static void Test2()
{ {
if (GetC(1) && GetC(2)) { if (GetC(1) && GetC(2))
{
Console.WriteLine(GetC(3)); Console.WriteLine(GetC(3));
} }
if (GetC(1) || GetC(2)) { if (GetC(1) || GetC(2))
{
Console.WriteLine(GetC(3)); Console.WriteLine(GetC(3));
} }
if (!(GetC(1) && GetC(2))) { if (!(GetC(1) && GetC(2)))
{
Console.WriteLine(GetC(3)); Console.WriteLine(GetC(3));
} }
} }
@ -96,10 +99,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty.CustomShortCircuitOperat
private static void Test3() private static void Test3()
{ {
C c = new C(); C c = new C();
if (c) { if (c)
{
Console.WriteLine(c.ToString()); Console.WriteLine(c.ToString());
} }
if (!c) { if (!c)
{
Console.WriteLine(c.ToString()); Console.WriteLine(c.ToString());
} }
} }
@ -108,10 +113,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty.CustomShortCircuitOperat
{ {
Console.WriteLine(GetC(1) && d.P); Console.WriteLine(GetC(1) && d.P);
Console.WriteLine(GetC(2) || d.P); Console.WriteLine(GetC(2) || d.P);
if (GetC(3) && d.P) { if (GetC(3) && d.P)
{
Console.WriteLine(GetC(4)); Console.WriteLine(GetC(4));
} }
if (GetC(5) || d.P) { if (GetC(5) || d.P)
{
Console.WriteLine(GetC(6)); Console.WriteLine(GetC(6));
} }
} }
@ -169,14 +176,20 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty.CustomShortCircuitOperat
public void InConditionDetection() public void InConditionDetection()
{ {
Console.WriteLine("a"); Console.WriteLine("a");
if (Get(1) && Get(2)) { if (Get(1) && Get(2))
{
Console.WriteLine("b"); Console.WriteLine("b");
} else { }
else
{
Console.WriteLine("c"); Console.WriteLine("c");
} }
if (Get(1) || Get(2)) { if (Get(1) || Get(2))
{
Console.WriteLine("d"); Console.WriteLine("d");
} else { }
else
{
Console.WriteLine("e"); Console.WriteLine("e");
} }
} }
@ -185,10 +198,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty.CustomShortCircuitOperat
{ {
Console.WriteLine(Get(1) && d.P); Console.WriteLine(Get(1) && d.P);
Console.WriteLine(Get(2) || d.P); Console.WriteLine(Get(2) || d.P);
if (Get(3) && d.P) { if (Get(3) && d.P)
{
Console.WriteLine(Get(4)); Console.WriteLine(Get(4));
} }
if (Get(5) || d.P) { if (Get(5) || d.P)
{
Console.WriteLine(Get(6)); Console.WriteLine(Get(6));
} }
} }

37
ICSharpCode.Decompiler.Tests/TestCases/Pretty/CustomTaskType.cs

@ -44,7 +44,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public async void TwoAwaitsWithDifferentAwaiterTypes() public async void TwoAwaitsWithDifferentAwaiterTypes()
{ {
Console.WriteLine("Before"); Console.WriteLine("Before");
if (await SimpleBoolTaskMethod()) { if (await SimpleBoolTaskMethod())
{
await Task.Delay(TimeSpan.FromSeconds(1.0)); await Task.Delay(TimeSpan.FromSeconds(1.0));
} }
Console.WriteLine("After"); Console.WriteLine("After");
@ -52,21 +53,28 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public async void AwaitInLoopCondition() public async void AwaitInLoopCondition()
{ {
while (await SimpleBoolTaskMethod()) { while (await SimpleBoolTaskMethod())
{
Console.WriteLine("Body"); Console.WriteLine("Body");
} }
} }
public async ValueTask AwaitInCatch(bool b, ValueTask<int> task1, ValueTask<int> task2) public async ValueTask AwaitInCatch(bool b, ValueTask<int> task1, ValueTask<int> task2)
{ {
try { try
{
Console.WriteLine("Start try"); Console.WriteLine("Start try");
await task1; await task1;
Console.WriteLine("End try"); Console.WriteLine("End try");
} catch (Exception) { }
if (!b) { catch (Exception)
{
if (!b)
{
await task2; await task2;
} else { }
else
{
Console.WriteLine("No await"); Console.WriteLine("No await");
} }
} }
@ -74,14 +82,20 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public async ValueTask AwaitInFinally(bool b, ValueTask<int> task1, ValueTask<int> task2) public async ValueTask AwaitInFinally(bool b, ValueTask<int> task1, ValueTask<int> task2)
{ {
try { try
{
Console.WriteLine("Start try"); Console.WriteLine("Start try");
await task1; await task1;
Console.WriteLine("End try"); Console.WriteLine("End try");
} finally { }
if (!b) { finally
{
if (!b)
{
await task2; await task2;
} else { }
else
{
Console.WriteLine("No await"); Console.WriteLine("No await");
} }
} }
@ -91,7 +105,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{ {
await Task.Delay(100); await Task.Delay(100);
int num = 0; int num = 0;
foreach (int item in items) { foreach (int item in items)
{
num += item; num += item;
} }
return num; return num;

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

@ -581,14 +581,16 @@ 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 (str, num2) in dictionary)
{
Console.WriteLine(str + ": " + num2); Console.WriteLine(str + ": " + num2);
} }
} }
public void DeconstructTupleListForEach(List<(string, int)> tuples) public void DeconstructTupleListForEach(List<(string, int)> tuples)
{ {
foreach (var (str, num) in tuples) { foreach (var (str, num) in tuples)
{
Console.WriteLine(str + ": " + num); Console.WriteLine(str + ": " + num);
} }
} }

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

@ -48,8 +48,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public Action CaptureOfThisAndParameterInForEach(int a) public Action CaptureOfThisAndParameterInForEach(int a)
{ {
foreach (int item in Enumerable.Empty<int>()) { foreach (int item in Enumerable.Empty<int>())
if (item > 0) { {
if (item > 0)
{
return delegate { return delegate {
CaptureOfThisAndParameter(item + a); CaptureOfThisAndParameter(item + a);
}; };
@ -60,9 +62,11 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public Action CaptureOfThisAndParameterInForEachWithItemCopy(int a) public Action CaptureOfThisAndParameterInForEachWithItemCopy(int a)
{ {
foreach (int item in Enumerable.Empty<int>()) { foreach (int item in Enumerable.Empty<int>())
{
int copyOfItem = item; int copyOfItem = item;
if (item > 0) { if (item > 0)
{
return delegate { return delegate {
CaptureOfThisAndParameter(item + a + copyOfItem); CaptureOfThisAndParameter(item + a + copyOfItem);
}; };
@ -73,7 +77,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void LambdaInForLoop() public void LambdaInForLoop()
{ {
for (int i = 0; i < 100000; i++) { for (int i = 0; i < 100000; i++)
{
Bar(() => Foo()); Bar(() => Foo());
} }
} }
@ -96,7 +101,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void Bug951(int amount) public void Bug951(int amount)
{ {
DoAction(delegate { DoAction(delegate {
if (amount < 0) { if (amount < 0)
{
amount = 0; amount = 0;
} }
DoAction(delegate { DoAction(delegate {
@ -109,7 +115,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{ {
int amount = Foo(); int amount = Foo();
DoAction(delegate { DoAction(delegate {
if (amount < 0) { if (amount < 0)
{
amount = 0; amount = 0;
} }
DoAction(delegate { DoAction(delegate {
@ -225,7 +232,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public Func<TNonCaptured, TNonCapturedMP, TCaptured> GetFunc<TNonCapturedMP>(Func<TCaptured> f) public Func<TNonCaptured, TNonCapturedMP, TCaptured> GetFunc<TNonCapturedMP>(Func<TCaptured> f)
{ {
TCaptured captured = f(); TCaptured captured = f();
return delegate(TNonCaptured a, TNonCapturedMP d) { return delegate (TNonCaptured a, TNonCapturedMP d) {
Console.WriteLine(a.GetHashCode()); Console.WriteLine(a.GetHashCode());
Console.WriteLine(captured.GetType().FullName); Console.WriteLine(captured.GetType().FullName);
return captured; return captured;
@ -248,10 +255,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static Predicate<T> And<T>(this Predicate<T> filter1, Predicate<T> filter2) public static Predicate<T> And<T>(this Predicate<T> filter1, Predicate<T> filter2)
{ {
if (filter1 == null) { if (filter1 == null)
{
return filter2; return filter2;
} }
if (filter2 == null) { if (filter2 == null)
{
return filter1; return filter1;
} }
return (T m) => filter1(m) && filter2(m); return (T m) => filter1(m) && filter2(m);
@ -295,9 +304,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static List<Action<int>> AnonymousMethodStoreWithinLoop() public static List<Action<int>> AnonymousMethodStoreWithinLoop()
{ {
List<Action<int>> list = new List<Action<int>>(); List<Action<int>> list = new List<Action<int>>();
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++)
{
int counter; int counter;
list.Add(delegate(int x) { list.Add(delegate (int x) {
counter = x; counter = x;
}); });
} }
@ -308,8 +318,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{ {
List<Action<int>> list = new List<Action<int>>(); List<Action<int>> list = new List<Action<int>>();
int counter; int counter;
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++)
list.Add(delegate(int x) { {
list.Add(delegate (int x) {
counter = x; counter = x;
}); });
} }
@ -331,11 +342,14 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
// k is local in main method // k is local in main method
// Ensure that the decompiler doesn't introduce name conflicts // Ensure that the decompiler doesn't introduce name conflicts
List<Action<int>> list = new List<Action<int>>(); List<Action<int>> list = new List<Action<int>>();
for (int k = 0; k < 10; k++) { for (int k = 0; k < 10; k++)
{
int i; int i;
for (i = 0; i < 10; i++) { for (i = 0; i < 10; i++)
list.Add(delegate(int j) { {
for (int l = 0; l < i; l += j) { list.Add(delegate (int j) {
for (int l = 0; l < i; l += j)
{
Console.WriteLine(); Console.WriteLine();
} }
}); });
@ -346,8 +360,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static void NameConflict2(int j) public static void NameConflict2(int j)
{ {
List<Action<int>> list = new List<Action<int>>(); List<Action<int>> list = new List<Action<int>>();
for (int k = 0; k < 10; k++) { for (int k = 0; k < 10; k++)
list.Add(delegate(int i) { {
list.Add(delegate (int i) {
Console.WriteLine(i); Console.WriteLine(i);
}); });
} }
@ -355,8 +370,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static Action<int> NameConflict3(int i) public static Action<int> NameConflict3(int i)
{ {
return delegate(int j) { return delegate (int j) {
for (int k = 0; k < j; k++) { for (int k = 0; k < j; k++)
{
Console.WriteLine(k); Console.WriteLine(k);
} }
}; };
@ -450,10 +466,13 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{ {
Issue1867 m1; Issue1867 m1;
Issue1867 m2; Issue1867 m2;
if (x.value > value) { if (x.value > value)
{
m1 = this; m1 = this;
m2 = x; m2 = x;
} else { }
else
{
m1 = x; m1 = x;
m2 = this; m2 = this;
} }

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

@ -126,9 +126,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
private static void DynamicThrow() private static void DynamicThrow()
{ {
try { try
{
throw (Exception)field; throw (Exception)field;
} catch (Exception ex) { }
catch (Exception ex)
{
Console.WriteLine(ex.ToString()); Console.WriteLine(ex.ToString());
throw; throw;
} }
@ -247,7 +250,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
private static void CheckedArithmeticBinaryOperators(dynamic a, dynamic b) private static void CheckedArithmeticBinaryOperators(dynamic a, dynamic b)
{ {
checked { checked
{
DynamicTests.MemberAccess(a + b); DynamicTests.MemberAccess(a + b);
DynamicTests.MemberAccess(a + 1); DynamicTests.MemberAccess(a + 1);
DynamicTests.MemberAccess(a + null); DynamicTests.MemberAccess(a + null);
@ -268,7 +272,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
private static void UncheckedArithmeticBinaryOperators(dynamic a, dynamic b) private static void UncheckedArithmeticBinaryOperators(dynamic a, dynamic b)
{ {
checked { checked
{
DynamicTests.MemberAccess(a + b); DynamicTests.MemberAccess(a + b);
DynamicTests.MemberAccess(a + 1); DynamicTests.MemberAccess(a + 1);
DynamicTests.MemberAccess(a + null); DynamicTests.MemberAccess(a + null);
@ -375,37 +380,44 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
private static void Loops(dynamic list) private static void Loops(dynamic list)
{ {
foreach (dynamic item in list) { foreach (dynamic item in list)
{
DynamicTests.UnaryOperators(item); DynamicTests.UnaryOperators(item);
} }
} }
private static void If(dynamic a, dynamic b) private static void If(dynamic a, dynamic b)
{ {
if (a == b) { if (a == b)
{
Console.WriteLine("Equal"); Console.WriteLine("Equal");
} }
} }
private static void If2(dynamic a, dynamic b) private static void If2(dynamic a, dynamic b)
{ {
if (a == null || b == null) { if (a == null || b == null)
{
Console.WriteLine("One is null"); Console.WriteLine("One is null");
} }
} }
private static void If3(dynamic a, dynamic b) private static void If3(dynamic a, dynamic b)
{ {
if (a == null && b == null) { if (a == null && b == null)
{
Console.WriteLine("Both are null"); Console.WriteLine("Both are null");
} }
} }
private static void If4(dynamic a, dynamic b) private static void If4(dynamic a, dynamic b)
{ {
if ((a == null || b == null) && GetDynamic(1) && !(GetDynamic(2) && GetDynamic(3))) { if ((a == null || b == null) && GetDynamic(1) && !(GetDynamic(2) && GetDynamic(3)))
{
Console.WriteLine("then"); Console.WriteLine("then");
} else { }
else
{
Console.WriteLine("else"); Console.WriteLine("else");
} }
} }

232
ICSharpCode.Decompiler.Tests/TestCases/Pretty/ExceptionHandling.cs

@ -33,21 +33,28 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public bool ConditionalReturnInThrow() public bool ConditionalReturnInThrow()
{ {
try { try
if (B(0)) { {
if (B(0))
{
return B(1); return B(1);
} }
} catch { }
catch
{
} }
return false; return false;
} }
public bool SimpleTryCatchException() public bool SimpleTryCatchException()
{ {
try { try
{
Console.WriteLine("Try"); Console.WriteLine("Try");
return B(new Random().Next()); return B(new Random().Next());
} catch (Exception) { }
catch (Exception)
{
Console.WriteLine("CatchException"); Console.WriteLine("CatchException");
} }
return false; return false;
@ -55,10 +62,13 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public bool SimpleTryCatchExceptionWithName() public bool SimpleTryCatchExceptionWithName()
{ {
try { try
{
Console.WriteLine("Try"); Console.WriteLine("Try");
return B(new Random().Next()); return B(new Random().Next());
} catch (Exception ex) { }
catch (Exception ex)
{
Console.WriteLine("CatchException ex: " + ex.ToString()); Console.WriteLine("CatchException ex: " + ex.ToString());
} }
return false; return false;
@ -67,10 +77,13 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
#if CS60 #if CS60
public bool SimpleTryCatchExceptionWithNameAndCondition() public bool SimpleTryCatchExceptionWithNameAndCondition()
{ {
try { try
{
Console.WriteLine("Try"); Console.WriteLine("Try");
return B(new Random().Next()); return B(new Random().Next());
} catch (Exception ex) when (ex.Message.Contains("test")) { }
catch (Exception ex) when (ex.Message.Contains("test"))
{
Console.WriteLine("CatchException ex: " + ex.ToString()); Console.WriteLine("CatchException ex: " + ex.ToString());
} }
return false; return false;
@ -78,10 +91,13 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public bool SimpleTryCatchExceptionWithNameAndConditionWithOr() public bool SimpleTryCatchExceptionWithNameAndConditionWithOr()
{ {
try { try
{
Console.WriteLine("Try"); Console.WriteLine("Try");
return B(new Random().Next()); return B(new Random().Next());
} catch (Exception ex) when (ex is ArgumentException || ex is IOException) { }
catch (Exception ex) when (ex is ArgumentException || ex is IOException)
{
Console.WriteLine("CatchException ex: " + ex.ToString()); Console.WriteLine("CatchException ex: " + ex.ToString());
} }
return false; return false;
@ -89,10 +105,13 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public async Task<bool> SimpleAsyncTryCatchExceptionWithNameAndConditionWithOr() public async Task<bool> SimpleAsyncTryCatchExceptionWithNameAndConditionWithOr()
{ {
try { try
{
Console.WriteLine("Try"); Console.WriteLine("Try");
return await T(); return await T();
} catch (Exception ex) when (ex is ArgumentException || ex is IOException) { }
catch (Exception ex) when (ex is ArgumentException || ex is IOException)
{
Console.WriteLine("CatchException ex: " + ex.ToString()); Console.WriteLine("CatchException ex: " + ex.ToString());
} }
return false; return false;
@ -101,9 +120,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void CatchWhenWithConditionWithoutExceptionVar() public void CatchWhenWithConditionWithoutExceptionVar()
{ {
int num = 0; int num = 0;
try { try
{
throw new Exception(); throw new Exception();
} catch (Exception) when (num == 0) { }
catch (Exception) when (num == 0)
{
Console.WriteLine("jo"); Console.WriteLine("jo");
} }
} }
@ -112,9 +134,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public bool SimpleTryFinally() public bool SimpleTryFinally()
{ {
try { try
{
Console.WriteLine("Try"); Console.WriteLine("Try");
} finally { }
finally
{
Console.WriteLine("Finally"); Console.WriteLine("Finally");
} }
return false; return false;
@ -122,42 +147,60 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void MethodEndingWithEndFinally() public void MethodEndingWithEndFinally()
{ {
try { try
{
throw null; throw null;
} finally { }
finally
{
Console.WriteLine(); Console.WriteLine();
} }
} }
public void MethodEndingWithRethrow() public void MethodEndingWithRethrow()
{ {
try { try
{
throw null; throw null;
} catch { }
catch
{
throw; throw;
} }
} }
public void TryCatchFinally() public void TryCatchFinally()
{ {
try { try
{
Console.WriteLine("Try"); Console.WriteLine("Try");
} catch (Exception ex) { }
catch (Exception ex)
{
Console.WriteLine(ex.Message); Console.WriteLine(ex.Message);
} finally { }
finally
{
Console.WriteLine("Finally"); Console.WriteLine("Finally");
} }
} }
public void TryCatchMultipleHandlers() public void TryCatchMultipleHandlers()
{ {
try { try
{
Console.WriteLine("Try"); Console.WriteLine("Try");
} catch (InvalidOperationException ex) { }
catch (InvalidOperationException ex)
{
Console.WriteLine(ex.Message); Console.WriteLine(ex.Message);
} catch (SystemException ex2) { }
catch (SystemException ex2)
{
Console.WriteLine(ex2.Message); Console.WriteLine(ex2.Message);
} catch { }
catch
{
Console.WriteLine("other"); Console.WriteLine("other");
} }
} }
@ -179,10 +222,14 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void NoUsingStatementBecauseTheVariableIsAssignedTo() public void NoUsingStatementBecauseTheVariableIsAssignedTo()
{ {
CancellationTokenSource cancellationTokenSource = null; CancellationTokenSource cancellationTokenSource = null;
try { try
{
cancellationTokenSource = new CancellationTokenSource(); cancellationTokenSource = new CancellationTokenSource();
} finally { }
if (cancellationTokenSource != null) { finally
{
if (cancellationTokenSource != null)
{
cancellationTokenSource.Dispose(); cancellationTokenSource.Dispose();
} }
} }
@ -190,8 +237,11 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void ThrowInFinally() public void ThrowInFinally()
{ {
try { try
} finally { {
}
finally
{
throw new Exception(); throw new Exception();
} }
} }
@ -214,14 +264,19 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
//} //}
public bool EarlyExitInLoopTry() public bool EarlyExitInLoopTry()
{ {
while (true) { while (true)
try { {
if (!B(0)) { try
{
if (!B(0))
{
return false; return false;
} }
Console.WriteLine(); Console.WriteLine();
} catch { }
catch
{
} }
} }
} }
@ -229,14 +284,18 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public bool ComplexConditionalReturnInThrow() public bool ComplexConditionalReturnInThrow()
{ {
try { try
if (B(0)) { {
if (B(1)) { if (B(0))
{
if (B(1))
{
Console.WriteLine("0 && 1"); Console.WriteLine("0 && 1");
return B(2); return B(2);
} }
if (B(3)) { if (B(3))
{
Console.WriteLine("0 && 3"); Console.WriteLine("0 && 3");
return !B(2); return !B(2);
} }
@ -246,22 +305,34 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
Console.WriteLine("End Try"); Console.WriteLine("End Try");
} catch { }
try { catch
try { {
if (((B(0) || B(1)) && B(2)) || B(3)) { try
{
try
{
if (((B(0) || B(1)) && B(2)) || B(3))
{
return B(4) && !B(5); return B(4) && !B(5);
} }
if (B(6) || B(7)) { if (B(6) || B(7))
{
return B(8) || B(9); return B(8) || B(9);
} }
} catch { }
catch
{
Console.WriteLine("Catch2"); Console.WriteLine("Catch2");
} }
return B(10) && B(11); return B(10) && B(11);
} catch { }
catch
{
Console.WriteLine("Catch"); Console.WriteLine("Catch");
} finally { }
finally
{
Console.WriteLine("Finally"); Console.WriteLine("Finally");
} }
} }
@ -271,12 +342,18 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void AppropriateLockExit() public void AppropriateLockExit()
{ {
int num = 0; int num = 0;
lock (this) { lock (this)
if (num <= 256) { {
if (num <= 256)
{
Console.WriteLine(0); Console.WriteLine(0);
} else if (num <= 1024) { }
else if (num <= 1024)
{
Console.WriteLine(1); Console.WriteLine(1);
} else if (num <= 16384) { }
else if (num <= 16384)
{
Console.WriteLine(2); Console.WriteLine(2);
} }
} }
@ -284,10 +361,14 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void ReassignExceptionVar() public void ReassignExceptionVar()
{ {
try { try
{
Console.WriteLine("ReassignExceptionVar"); Console.WriteLine("ReassignExceptionVar");
} catch (Exception innerException) { }
if (innerException.InnerException != null) { catch (Exception innerException)
{
if (innerException.InnerException != null)
{
innerException = innerException.InnerException; innerException = innerException.InnerException;
} }
Console.WriteLine(innerException); Console.WriteLine(innerException);
@ -297,9 +378,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public int UseExceptionVarOutsideCatch() public int UseExceptionVarOutsideCatch()
{ {
Exception ex2; Exception ex2;
try { try
{
return 1; return 1;
} catch (Exception ex) { }
catch (Exception ex)
{
ex2 = ex; ex2 = ex;
} }
Console.WriteLine(ex2 != null); Console.WriteLine(ex2 != null);
@ -308,9 +392,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void GenericException<TException>(int input) where TException : Exception public void GenericException<TException>(int input) where TException : Exception
{ {
try { try
{
Console.WriteLine(input); Console.WriteLine(input);
} catch (TException val) { }
catch (TException val)
{
Console.WriteLine(val.Message); Console.WriteLine(val.Message);
throw; throw;
} }
@ -318,14 +405,19 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void GenericException2<T>() where T : Exception public void GenericException2<T>() where T : Exception
{ {
try { try
{
Console.WriteLine("CatchT"); Console.WriteLine("CatchT");
#if ROSLYN #if ROSLYN
} catch (T val) { }
catch (T val)
{
Console.WriteLine("{0} {1}", val, val.ToString()); Console.WriteLine("{0} {1}", val, val.ToString());
} }
#else #else
} catch (T arg) { }
catch (T arg)
{
Console.WriteLine("{0} {1}", arg, arg.ToString()); Console.WriteLine("{0} {1}", arg, arg.ToString());
} }
#endif #endif
@ -334,9 +426,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
#if CS60 #if CS60
public void GenericExceptionWithCondition<TException>(int input) where TException : Exception public void GenericExceptionWithCondition<TException>(int input) where TException : Exception
{ {
try { try
{
Console.WriteLine(input); Console.WriteLine(input);
} catch (TException val) when (val.Message.Contains("Test")) { }
catch (TException val) when (val.Message.Contains("Test"))
{
Console.WriteLine(val.Message); Console.WriteLine(val.Message);
throw; throw;
} }
@ -344,9 +439,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void GenericException2WithCondition<TException>(int input) where TException : Exception public void GenericException2WithCondition<TException>(int input) where TException : Exception
{ {
try { try
{
Console.WriteLine(input); Console.WriteLine(input);
} catch (TException val) when (val.Message.Contains("Test")) { }
catch (TException val) when (val.Message.Contains("Test"))
{
Console.WriteLine("{0} {1}", val, val.ToString()); Console.WriteLine("{0} {1}", val, val.ToString());
} }
} }

15
ICSharpCode.Decompiler.Tests/TestCases/Pretty/ExpressionTrees.cs

@ -332,7 +332,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
private void Issue1249(int ID) private void Issue1249(int ID)
{ {
if (ID == 0) { if (ID == 0)
{
ViewBag.data = "''"; ViewBag.data = "''";
return; return;
} }
@ -960,15 +961,15 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
Test<Func<int, string>>((int a) => a.ToString(), (int a) => a.ToString()); Test<Func<int, string>>((int a) => a.ToString(), (int a) => a.ToString());
Test<Func<string, char[]>>((string a) => a.ToArray(), (string a) => a.ToArray()); Test<Func<string, char[]>>((string a) => a.ToArray(), (string a) => a.ToArray());
Test<Func<bool>>(() => 'a'.CompareTo('b') < 0, () => 'a'.CompareTo('b') < 0); Test<Func<bool>>(() => 'a'.CompareTo('b') < 0, () => 'a'.CompareTo('b') < 0);
Test<Action<object, bool>>(delegate(object lockObj, bool lockTaken) { Test<Action<object, bool>>(delegate (object lockObj, bool lockTaken) {
Monitor.Enter(lockObj, ref lockTaken); Monitor.Enter(lockObj, ref lockTaken);
}, (object lockObj, bool lockTaken) => Monitor.Enter(lockObj, ref lockTaken)); }, (object lockObj, bool lockTaken) => Monitor.Enter(lockObj, ref lockTaken));
Test<Func<string, int, bool>>((string str, int num) => int.TryParse(str, out num), (string str, int num) => int.TryParse(str, out num)); Test<Func<string, int, bool>>((string str, int num) => int.TryParse(str, out num), (string str, int num) => int.TryParse(str, out num));
Test<Func<string, SimpleType, bool>>((string str, SimpleType t) => int.TryParse(str, out t.Field), (string str, SimpleType t) => int.TryParse(str, out t.Field)); Test<Func<string, SimpleType, bool>>((string str, SimpleType t) => int.TryParse(str, out t.Field), (string str, SimpleType t) => int.TryParse(str, out t.Field));
Test<Action<object>>(delegate(object o) { Test<Action<object>>(delegate (object o) {
TestCall(o); TestCall(o);
}, (object o) => TestCall(o)); }, (object o) => TestCall(o));
Test<Action<object>>(delegate(object o) { Test<Action<object>>(delegate (object o) {
TestCall(ref o); TestCall(ref o);
}, (object o) => TestCall(ref o)); }, (object o) => TestCall(ref o));
} }
@ -1038,10 +1039,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{ {
await Task.Delay(100); await Task.Delay(100);
#if CS70 #if CS70
if (string.IsNullOrEmpty(str) && int.TryParse(str, out int id)) { if (string.IsNullOrEmpty(str) && int.TryParse(str, out int id))
{
#else #else
int id; int id;
if (string.IsNullOrEmpty(str) && int.TryParse(str, out id)) { if (string.IsNullOrEmpty(str) && int.TryParse(str, out id))
{
#endif #endif
(from a in new List<int>().AsQueryable() (from a in new List<int>().AsQueryable()
where a == id where a == id

10
ICSharpCode.Decompiler.Tests/TestCases/Pretty/FixProxyCalls.cs

@ -96,10 +96,11 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.ILPretty
protected internal override void Test(string test) protected internal override void Test(string test)
{ {
action = delegate(string a) { action = delegate (string a) {
base.Test(a); base.Test(a);
}; };
if (test.Equals(1)) { if (test.Equals(1))
{
throw new Exception("roslyn optimizes is inlining the assignment which lets the test fail"); throw new Exception("roslyn optimizes is inlining the assignment which lets the test fail");
} }
action(test); action(test);
@ -118,7 +119,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.ILPretty
{ {
public Action<object> M(object state) public Action<object> M(object state)
{ {
return delegate(object x) { return delegate (object x) {
base.BaseCall(x, state, (Func<object>)(() => null)); base.BaseCall(x, state, (Func<object>)(() => null));
}; };
} }
@ -138,7 +139,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.ILPretty
Action action = delegate { Action action = delegate {
base.Test(a); base.Test(a);
}; };
if (a.Equals(1)) { if (a.Equals(1))
{
throw new Exception("roslyn optimize is inlining the assignment which lets the test fail"); throw new Exception("roslyn optimize is inlining the assignment which lets the test fail");
} }
action(); action();

3
ICSharpCode.Decompiler.Tests/TestCases/Pretty/Generics.cs

@ -73,7 +73,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void Grow(int capacity) public void Grow(int capacity)
{ {
if (capacity >= arr.Length) { if (capacity >= arr.Length)
{
Size(capacity); Size(capacity);
} }
} }

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

@ -1233,9 +1233,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty.InitializerTests
} }
}; };
} }
#endregion #endregion
#region Object initializers #region Object initializers
public C Test1() public C Test1()
{ {
C c = new C(); C c = new C();
@ -1537,7 +1537,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty.InitializerTests
private Data Issue1279(int p) private Data Issue1279(int p)
{ {
if (p == 1) { if (p == 1)
{
Data data = new Data(); Data data = new Data();
data.a = MyEnum.a; data.a = MyEnum.a;
data.TestEvent += Data_TestEvent; data.TestEvent += Data_TestEvent;
@ -1546,9 +1547,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty.InitializerTests
return null; return null;
} }
#endregion #endregion
#region Collection initializer #region Collection initializer
public static void ExtensionMethodInCollectionInitializer() public static void ExtensionMethodInCollectionInitializer()
{ {
@ -1733,6 +1734,6 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty.InitializerTests
} }
#endif #endif
#endregion #endregion
} }
} }

21
ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.cs

@ -52,7 +52,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
Console.WriteLine(GetFormat(), value = new InlineAssignmentTest()); Console.WriteLine(GetFormat(), value = new InlineAssignmentTest());
Console.WriteLine(value); Console.WriteLine(value);
} }
public void SimpleInlineWithFields() public void SimpleInlineWithFields()
{ {
Console.WriteLine(field1 = 5); Console.WriteLine(field1 = 5);
@ -71,7 +71,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
UseShort(field4 = UseShort(0)); UseShort(field4 = UseShort(0));
Console.WriteLine(field4); Console.WriteLine(field4);
} }
public short UseShort(short s) public short UseShort(short s)
{ {
Console.WriteLine(s); Console.WriteLine(s);
@ -81,7 +81,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void ReadLoop1(TextReader r) public void ReadLoop1(TextReader r)
{ {
string value; string value;
while ((value = r.ReadLine()) != null) { while ((value = r.ReadLine()) != null)
{
Console.WriteLine(value); Console.WriteLine(value);
} }
} }
@ -92,32 +93,32 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
Console.WriteLine(num = a[0]); Console.WriteLine(num = a[0]);
Console.WriteLine(a[num] = num); Console.WriteLine(a[num] = num);
} }
public int Return(ref int a) public int Return(ref int a)
{ {
return a = 3; return a = 3;
} }
public int Array(int[] a, int i) public int Array(int[] a, int i)
{ {
return a[i] = i; return a[i] = i;
} }
public int Array2(int i) public int Array2(int i)
{ {
return field3[i] = 1; return field3[i] = 1;
} }
public int GetIndex() public int GetIndex()
{ {
return new Random().Next(0, 100); return new Random().Next(0, 100);
} }
public int[] GetArray() public int[] GetArray()
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
public string GetFormat() public string GetFormat()
{ {
return "{0}"; return "{0}";
@ -127,7 +128,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{ {
return value; return value;
} }
public int ArrayUsageWithMethods() public int ArrayUsageWithMethods()
{ {
return GetArray()[GetIndex()] = GetValue(GetIndex()); return GetArray()[GetIndex()] = GetValue(GetIndex());

3
ICSharpCode.Decompiler.Tests/TestCases/Pretty/Issue1080.cs

@ -13,7 +13,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty.Issue1080
private static void Test(object obj) private static void Test(object obj)
{ {
ICSharpCode.Decompiler.Tests.TestCases.Pretty.Issue1080.SpaceA.Type2 type = obj as ICSharpCode.Decompiler.Tests.TestCases.Pretty.Issue1080.SpaceA.Type2; ICSharpCode.Decompiler.Tests.TestCases.Pretty.Issue1080.SpaceA.Type2 type = obj as ICSharpCode.Decompiler.Tests.TestCases.Pretty.Issue1080.SpaceA.Type2;
if (type != null) { if (type != null)
{
ICSharpCode.Decompiler.Tests.TestCases.Pretty.Issue1080.SpaceC.Extensions.Extension(type); ICSharpCode.Decompiler.Tests.TestCases.Pretty.Issue1080.SpaceC.Extensions.Extension(type);
} }
} }

179
ICSharpCode.Decompiler.Tests/TestCases/Pretty/LiftedOperators.cs

@ -30,54 +30,67 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static void BoolBasic(bool? a, bool? b) public static void BoolBasic(bool? a, bool? b)
{ {
if (a == b) { if (a == b)
{
Console.WriteLine(); Console.WriteLine();
} }
if (a != b) { if (a != b)
{
Console.WriteLine(); Console.WriteLine();
} }
} }
public static void BoolComplex(bool? a, Func<bool> x) public static void BoolComplex(bool? a, Func<bool> x)
{ {
if (a == x()) { if (a == x())
{
Console.WriteLine(); Console.WriteLine();
} }
if (a != x()) { if (a != x())
{
Console.WriteLine(); Console.WriteLine();
} }
if (x() == a) { if (x() == a)
{
Console.WriteLine(); Console.WriteLine();
} }
if (x() != a) { if (x() != a)
{
Console.WriteLine(); Console.WriteLine();
} }
if (a ?? x()) { if (a ?? x())
{
Console.WriteLine(); Console.WriteLine();
} }
} }
public static void BoolConst(bool? a) public static void BoolConst(bool? a)
{ {
if (a == true) { if (a == true)
{
Console.WriteLine(); Console.WriteLine();
} }
if (a != true) { if (a != true)
{
Console.WriteLine(); Console.WriteLine();
} }
if (a == false) { if (a == false)
{
Console.WriteLine(); Console.WriteLine();
} }
if (a != false) { if (a != false)
{
Console.WriteLine(); Console.WriteLine();
} }
if (a ?? true) { if (a ?? true)
{
Console.WriteLine(); Console.WriteLine();
} }
#if !ROSLYN #if !ROSLYN
// Roslyn 3 (VS2019) started optimizing this to "a.GetValueOrDefault()" // Roslyn 3 (VS2019) started optimizing this to "a.GetValueOrDefault()"
if (a ?? false) { if (a ?? false)
{
Console.WriteLine(); Console.WriteLine();
} }
#endif #endif
@ -87,7 +100,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{ {
Console.WriteLine(a == b); Console.WriteLine(a == b);
Console.WriteLine(a != b); Console.WriteLine(a != b);
Console.WriteLine(a & b); Console.WriteLine(a & b);
Console.WriteLine(a | b); Console.WriteLine(a | b);
Console.WriteLine(a ^ b); Console.WriteLine(a ^ b);
@ -105,7 +118,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
Console.WriteLine(x() == a); Console.WriteLine(x() == a);
Console.WriteLine(x() != a); Console.WriteLine(x() != a);
//Console.WriteLine(a & x()); // we currently can't tell the order //Console.WriteLine(a & x()); // we currently can't tell the order
//Console.WriteLine(a | x()); // of the operands in bool [&|] bool? //Console.WriteLine(a | x()); // of the operands in bool [&|] bool?
Console.WriteLine(a ^ x()); Console.WriteLine(a ^ x());
@ -136,82 +149,104 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static void IntBasic(int? a, int? b) public static void IntBasic(int? a, int? b)
{ {
if (a == b) { if (a == b)
{
Console.WriteLine(); Console.WriteLine();
} }
if (a != b) { if (a != b)
{
Console.WriteLine(); Console.WriteLine();
} }
if (a > b) { if (a > b)
{
Console.WriteLine(); Console.WriteLine();
} }
if (a < b) { if (a < b)
{
Console.WriteLine(); Console.WriteLine();
} }
if (a >= b) { if (a >= b)
{
Console.WriteLine(); Console.WriteLine();
} }
if (a <= b) { if (a <= b)
{
Console.WriteLine(); Console.WriteLine();
} }
if (!(a > b)) { if (!(a > b))
{
Console.WriteLine(); Console.WriteLine();
} }
if (!(a <= b)) { if (!(a <= b))
{
Console.WriteLine(); Console.WriteLine();
} }
} }
public static void IntComplex(int? a, Func<int> x) public static void IntComplex(int? a, Func<int> x)
{ {
if (a == x()) { if (a == x())
{
Console.WriteLine(); Console.WriteLine();
} }
if (a != x()) { if (a != x())
{
Console.WriteLine(); Console.WriteLine();
} }
if (a > x()) { if (a > x())
{
Console.WriteLine(); Console.WriteLine();
} }
if (x() == a) { if (x() == a)
{
Console.WriteLine(); Console.WriteLine();
} }
if (x() != a) { if (x() != a)
{
Console.WriteLine(); Console.WriteLine();
} }
if (x() > a) { if (x() > a)
{
Console.WriteLine(); Console.WriteLine();
} }
if (!(a > x())) { if (!(a > x()))
{
Console.WriteLine(); Console.WriteLine();
} }
if (!(a <= x())) { if (!(a <= x()))
{
Console.WriteLine(); Console.WriteLine();
} }
} }
public static void IntConst(int? a) public static void IntConst(int? a)
{ {
if (a == 2) { if (a == 2)
{
Console.WriteLine(); Console.WriteLine();
} }
if (a != 2) { if (a != 2)
{
Console.WriteLine(); Console.WriteLine();
} }
if (a > 2) { if (a > 2)
{
Console.WriteLine(); Console.WriteLine();
} }
if (2 == a) { if (2 == a)
{
Console.WriteLine(); Console.WriteLine();
} }
if (2 != a) { if (2 != a)
{
Console.WriteLine(); Console.WriteLine();
} }
if (2 > a) { if (2 > a)
{
Console.WriteLine(); Console.WriteLine();
} }
} }
@ -221,7 +256,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
Console.WriteLine(a == b); Console.WriteLine(a == b);
Console.WriteLine(a != b); Console.WriteLine(a != b);
Console.WriteLine(a > b); Console.WriteLine(a > b);
Console.WriteLine(!(a > b)); Console.WriteLine(!(a > b));
Console.WriteLine(!(a >= b)); Console.WriteLine(!(a >= b));
@ -328,36 +363,45 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static void NumberBasic(decimal? a, decimal? b) public static void NumberBasic(decimal? a, decimal? b)
{ {
if (a == b) { if (a == b)
{
Console.WriteLine(); Console.WriteLine();
} }
#if ROSLYN #if ROSLYN
// Roslyn 2.9 started invoking op_Equality even if the source code says 'a != b' // Roslyn 2.9 started invoking op_Equality even if the source code says 'a != b'
if (!(a == b)) { if (!(a == b))
{
Console.WriteLine(); Console.WriteLine();
} }
#else #else
if (a != b) { if (a != b)
{
Console.WriteLine(); Console.WriteLine();
} }
#endif #endif
if (a > b) { if (a > b)
{
Console.WriteLine(); Console.WriteLine();
} }
if (a < b) { if (a < b)
{
Console.WriteLine(); Console.WriteLine();
} }
if (a >= b) { if (a >= b)
{
Console.WriteLine(); Console.WriteLine();
} }
if (a <= b) { if (a <= b)
{
Console.WriteLine(); Console.WriteLine();
} }
if (!(a > b)) { if (!(a > b))
{
Console.WriteLine(); Console.WriteLine();
} }
if (!(a < b)) { if (!(a < b))
{
Console.WriteLine(); Console.WriteLine();
} }
} }
@ -502,10 +546,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static void CompareWithImplictCast(int? a, long? b) public static void CompareWithImplictCast(int? a, long? b)
{ {
if (a < b) { if (a < b)
{
Console.WriteLine(); Console.WriteLine();
} }
if (a == b) { if (a == b)
{
Console.WriteLine(); Console.WriteLine();
} }
// TODO: unnecessary cast // TODO: unnecessary cast
@ -519,7 +565,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static void CompareWithSignChange(int? a, int? b) public static void CompareWithSignChange(int? a, int? b)
{ {
if ((uint?)a < (uint?)b) { if ((uint?)a < (uint?)b)
{
Console.WriteLine(); Console.WriteLine();
} }
// TODO: unnecessary cast // TODO: unnecessary cast
@ -530,32 +577,41 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static void StructBasic(TS? a, TS? b) public static void StructBasic(TS? a, TS? b)
{ {
if (a == b) { if (a == b)
{
Console.WriteLine(); Console.WriteLine();
} }
if (a != b) { if (a != b)
{
Console.WriteLine(); Console.WriteLine();
} }
if (a > b) { if (a > b)
{
Console.WriteLine(); Console.WriteLine();
} }
if (a < b) { if (a < b)
{
Console.WriteLine(); Console.WriteLine();
} }
if (a >= b) { if (a >= b)
{
Console.WriteLine(); Console.WriteLine();
} }
if (a <= b) { if (a <= b)
{
Console.WriteLine(); Console.WriteLine();
} }
if (!(a == b)) { if (!(a == b))
{
Console.WriteLine(); Console.WriteLine();
} }
if (!(a != b)) { if (!(a != b))
{
Console.WriteLine(); Console.WriteLine();
} }
if (!(a > b)) { if (!(a > b))
{
Console.WriteLine(); Console.WriteLine();
} }
} }
@ -785,7 +841,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static void CheckedCasts(int? i4, long? i8, float? f) public static void CheckedCasts(int? i4, long? i8, float? f)
{ {
checked { checked
{
Print((byte?)i4); Print((byte?)i4);
Print((short?)i4); Print((short?)i4);
Print((uint?)i4); Print((uint?)i4);

47
ICSharpCode.Decompiler.Tests/TestCases/Pretty/LocalFunctions.cs

@ -36,7 +36,8 @@ namespace LocalFunctions
#pragma warning disable CS0219 #pragma warning disable CS0219
T2 t2 = default(T2); T2 t2 = default(T2);
object z = this; object z = this;
for (int j = 0; j < 10; j++) { for (int j = 0; j < 10; j++)
{
int i = 0; int i = 0;
i += NonStaticMethod6<object>(0); i += NonStaticMethod6<object>(0);
#if CS90 #if CS90
@ -115,7 +116,8 @@ namespace LocalFunctions
{ {
T2 t2 = default(T2); T2 t2 = default(T2);
object z = this; object z = this;
for (int j = 0; j < 10; j++) { for (int j = 0; j < 10; j++)
{
int i = 0; int i = 0;
i += StaticInvokeAsFunc(NonStaticMethod6<object>); i += StaticInvokeAsFunc(NonStaticMethod6<object>);
int NonStaticMethod6<T3>() int NonStaticMethod6<T3>()
@ -366,7 +368,8 @@ namespace LocalFunctions
public static void StaticContextNoCapture(int length) public static void StaticContextNoCapture(int length)
{ {
for (int i = 0; i < length; i++) { for (int i = 0; i < length; i++)
{
LocalWrite("Hello " + i); LocalWrite("Hello " + i);
} }
@ -382,7 +385,8 @@ namespace LocalFunctions
public static void StaticContextSimpleCapture(int length) public static void StaticContextSimpleCapture(int length)
{ {
for (int i = 0; i < length; i++) { for (int i = 0; i < length; i++)
{
LocalWrite(); LocalWrite();
} }
@ -395,7 +399,8 @@ namespace LocalFunctions
public static void StaticContextCaptureForLoopVariable(int length) public static void StaticContextCaptureForLoopVariable(int length)
{ {
int i; int i;
for (i = 0; i < length; i++) { for (i = 0; i < length; i++)
{
LocalWrite(); LocalWrite();
} }
void LocalWrite() void LocalWrite()
@ -406,7 +411,8 @@ namespace LocalFunctions
public void ContextNoCapture() public void ContextNoCapture()
{ {
for (int i = 0; i < field; i++) { for (int i = 0; i < field; i++)
{
LocalWrite("Hello " + i); LocalWrite("Hello " + i);
} }
@ -422,7 +428,8 @@ namespace LocalFunctions
public void ContextSimpleCapture() public void ContextSimpleCapture()
{ {
for (int i = 0; i < field; i++) { for (int i = 0; i < field; i++)
{
LocalWrite(); LocalWrite();
} }
@ -435,7 +442,8 @@ namespace LocalFunctions
public void ContextCaptureForLoopVariable() public void ContextCaptureForLoopVariable()
{ {
int i; int i;
for (i = 0; i < field; i++) { for (i = 0; i < field; i++)
{
LocalWrite(); LocalWrite();
} }
void LocalWrite() void LocalWrite()
@ -447,7 +455,8 @@ namespace LocalFunctions
public void CapturedOutsideLoop() public void CapturedOutsideLoop()
{ {
int i = 0; int i = 0;
while (i < field) { while (i < field)
{
i = GetInt("asdf"); i = GetInt("asdf");
LocalWrite(); LocalWrite();
} }
@ -460,7 +469,8 @@ namespace LocalFunctions
public void CapturedInForeachLoop(IEnumerable<string> args) public void CapturedInForeachLoop(IEnumerable<string> args)
{ {
foreach (string arg2 in args) { foreach (string arg2 in args)
{
string arg = arg2; string arg = arg2;
LocalWrite(); LocalWrite();
void LocalWrite() void LocalWrite()
@ -563,7 +573,8 @@ namespace LocalFunctions
int FibHelper(int n) int FibHelper(int n)
#endif #endif
{ {
if (n <= 0) { if (n <= 0)
{
return 0; return 0;
} }
@ -580,7 +591,8 @@ namespace LocalFunctions
int A(int i) int A(int i)
#endif #endif
{ {
if (i > 0) { if (i > 0)
{
return A(i - 1) + 2 * B(i - 1) + 3 * C(i - 1); return A(i - 1) + 2 * B(i - 1) + 3 * C(i - 1);
} }
return 1; return 1;
@ -592,7 +604,8 @@ namespace LocalFunctions
int B(int i) int B(int i)
#endif #endif
{ {
if (i > 0) { if (i > 0)
{
return 3 * A(i - 1) + B(i - 1); return 3 * A(i - 1) + B(i - 1);
} }
return 1; return 1;
@ -604,7 +617,8 @@ namespace LocalFunctions
int C(int i) int C(int i)
#endif #endif
{ {
if (i > 0) { if (i > 0)
{
return 2 * A(i - 1) + C(i - 1); return 2 * A(i - 1) + C(i - 1);
} }
return 1; return 1;
@ -629,7 +643,7 @@ namespace LocalFunctions
public static int LocalFunctionInLambda(IEnumerable<int> xs) public static int LocalFunctionInLambda(IEnumerable<int> xs)
{ {
return xs.First(delegate(int x) { return xs.First(delegate (int x) {
return Do(); return Do();
bool Do() bool Do()
@ -645,7 +659,8 @@ namespace LocalFunctions
IEnumerable<int> GetNumbers() IEnumerable<int> GetNumbers()
{ {
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++)
{
yield return i; yield return i;
} }
} }

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

@ -24,14 +24,16 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{ {
public void LockThis() public void LockThis()
{ {
lock (this) { lock (this)
{
Console.WriteLine(); Console.WriteLine();
} }
} }
public void LockOnType() public void LockOnType()
{ {
lock (typeof(Lock)) { lock (typeof(Lock))
{
Console.WriteLine(); Console.WriteLine();
} }
} }

299
ICSharpCode.Decompiler.Tests/TestCases/Pretty/Loops.cs

@ -290,14 +290,16 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void ForEachOnField() public void ForEachOnField()
{ {
foreach (string alternative in alternatives) { foreach (string alternative in alternatives)
{
alternative.ToLower(); alternative.ToLower();
} }
} }
public void ForEach(IEnumerable<string> alternatives) public void ForEach(IEnumerable<string> alternatives)
{ {
foreach (string alternative in alternatives) { foreach (string alternative in alternatives)
{
alternative.ToLower(); alternative.ToLower();
} }
} }
@ -305,35 +307,40 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void ForEachOverList(List<string> list) public void ForEachOverList(List<string> list)
{ {
// List has a struct as enumerator, so produces quite different IL than foreach over the IEnumerable interface // List has a struct as enumerator, so produces quite different IL than foreach over the IEnumerable interface
foreach (string item in list) { foreach (string item in list)
{
item.ToLower(); item.ToLower();
} }
} }
public void ForEachOverNonGenericEnumerable(IEnumerable enumerable) public void ForEachOverNonGenericEnumerable(IEnumerable enumerable)
{ {
foreach (object item in enumerable) { foreach (object item in enumerable)
{
item.ToString(); item.ToString();
} }
} }
public void ForEachOverNonGenericEnumerableWithAutomaticCastValueType(IEnumerable enumerable) public void ForEachOverNonGenericEnumerableWithAutomaticCastValueType(IEnumerable enumerable)
{ {
foreach (int item in enumerable) { foreach (int item in enumerable)
{
item.ToString(); item.ToString();
} }
} }
public void ForEachOverNonGenericEnumerableWithAutomaticCastRefType(IEnumerable enumerable) public void ForEachOverNonGenericEnumerableWithAutomaticCastRefType(IEnumerable enumerable)
{ {
foreach (string item in enumerable) { foreach (string item in enumerable)
{
Console.WriteLine(item); Console.WriteLine(item);
} }
} }
public void ForEachOnCustomClassEnumerator(CustomClassEnumerator e) public void ForEachOnCustomClassEnumerator(CustomClassEnumerator e)
{ {
foreach (object item in e) { foreach (object item in e)
{
Console.WriteLine(item); Console.WriteLine(item);
} }
} }
@ -350,7 +357,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void ForEachOnGenericCustomClassEnumerator<T>(CustomClassEnumerator<T> e) public void ForEachOnGenericCustomClassEnumerator<T>(CustomClassEnumerator<T> e)
{ {
foreach (T item in e) { foreach (T item in e)
{
Console.WriteLine(item); Console.WriteLine(item);
} }
} }
@ -367,28 +375,32 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void ForEachOnCustomClassEnumeratorWithIDisposable(CustomClassEnumeratorWithIDisposable e) public void ForEachOnCustomClassEnumeratorWithIDisposable(CustomClassEnumeratorWithIDisposable e)
{ {
foreach (object item in e) { foreach (object item in e)
{
Console.WriteLine(item); Console.WriteLine(item);
} }
} }
public void ForEachOnCustomStructEnumeratorWithIDisposable(CustomStructEnumeratorWithIDisposable e) public void ForEachOnCustomStructEnumeratorWithIDisposable(CustomStructEnumeratorWithIDisposable e)
{ {
foreach (object item in e) { foreach (object item in e)
{
Console.WriteLine(item); Console.WriteLine(item);
} }
} }
public void ForEachOnGenericCustomClassEnumeratorWithIDisposable<T>(CustomClassEnumeratorWithIDisposable<T> e) public void ForEachOnGenericCustomClassEnumeratorWithIDisposable<T>(CustomClassEnumeratorWithIDisposable<T> e)
{ {
foreach (T item in e) { foreach (T item in e)
{
Console.WriteLine(item); Console.WriteLine(item);
} }
} }
public void ForEachOnGenericCustomStructEnumeratorWithIDisposable<T>(CustomStructEnumeratorWithIDisposable<T> e) public void ForEachOnGenericCustomStructEnumeratorWithIDisposable<T>(CustomStructEnumeratorWithIDisposable<T> e)
{ {
foreach (T item in e) { foreach (T item in e)
{
Console.WriteLine(item); Console.WriteLine(item);
} }
} }
@ -397,16 +409,21 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{ {
Console.WriteLine("NonGenericForeachWithReturnFallback:"); Console.WriteLine("NonGenericForeachWithReturnFallback:");
IEnumerator enumerator = e.GetEnumerator(); IEnumerator enumerator = e.GetEnumerator();
try { try
{
Console.WriteLine("MoveNext"); Console.WriteLine("MoveNext");
if (enumerator.MoveNext()) { if (enumerator.MoveNext())
{
object current = enumerator.Current; object current = enumerator.Current;
Console.WriteLine("please don't inline 'current'"); Console.WriteLine("please don't inline 'current'");
Console.WriteLine(current); Console.WriteLine(current);
} }
} finally { }
finally
{
IDisposable disposable = enumerator as IDisposable; IDisposable disposable = enumerator as IDisposable;
if (disposable != null) { if (disposable != null)
{
disposable.Dispose(); disposable.Dispose();
} }
} }
@ -415,7 +432,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static void ForeachWithRefUsage(List<int> items) public static void ForeachWithRefUsage(List<int> items)
{ {
foreach (int item in items) { foreach (int item in items)
{
#if ROSLYN && OPT #if ROSLYN && OPT
// The variable name differs based on whether roslyn optimizes out the 'item' variable // The variable name differs based on whether roslyn optimizes out the 'item' variable
int i = item; int i = item;
@ -429,7 +447,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static void ForeachWithCapturedVariable(List<int> items) public static void ForeachWithCapturedVariable(List<int> items)
{ {
foreach (int item in items) { foreach (int item in items)
{
int c = item; int c = item;
Operation(() => c == 5); Operation(() => c == 5);
} }
@ -438,7 +457,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static T LastOrDefault<T>(IEnumerable<T> items) public static T LastOrDefault<T>(IEnumerable<T> items)
{ {
T result = default(T); T result = default(T);
foreach (T item in items) { foreach (T item in items)
{
result = item; result = item;
} }
return result; return result;
@ -446,14 +466,16 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void ForEachOverArray(string[] array) public void ForEachOverArray(string[] array)
{ {
foreach (string text in array) { foreach (string text in array)
{
Console.WriteLine(text.ToLower() + text.ToUpper()); Console.WriteLine(text.ToLower() + text.ToUpper());
} }
} }
public unsafe void ForEachOverArrayOfPointers(int*[] array) public unsafe void ForEachOverArrayOfPointers(int*[] array)
{ {
foreach (int* value in array) { foreach (int* value in array)
{
Console.WriteLine(new IntPtr(value)); Console.WriteLine(new IntPtr(value));
Console.WriteLine(new IntPtr(value)); Console.WriteLine(new IntPtr(value));
} }
@ -462,15 +484,19 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void ForEachBreakWhenFound(string name, ref StringComparison output) public void ForEachBreakWhenFound(string name, ref StringComparison output)
{ {
#if MCS #if MCS
foreach (int value in Enum.GetValues(typeof(StringComparison))) { foreach (int value in Enum.GetValues(typeof(StringComparison)))
if (((StringComparison)value).ToString() == name) { {
if (((StringComparison)value).ToString() == name)
{
output = (StringComparison)value; output = (StringComparison)value;
break; break;
} }
} }
#else #else
foreach (StringComparison value in Enum.GetValues(typeof(StringComparison))) { foreach (StringComparison value in Enum.GetValues(typeof(StringComparison)))
if (value.ToString() == name) { {
if (value.ToString() == name)
{
output = value; output = value;
break; break;
} }
@ -480,7 +506,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void ForEachOverListOfStruct(List<DataItem> items, int value) public void ForEachOverListOfStruct(List<DataItem> items, int value)
{ {
foreach (DataItem item in items) { foreach (DataItem item in items)
{
#if ROSLYN && OPT #if ROSLYN && OPT
// The variable name differs based on whether roslyn optimizes out the 'item' variable // The variable name differs based on whether roslyn optimizes out the 'item' variable
DataItem current = item; DataItem current = item;
@ -494,7 +521,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void ForEachOverListOfStruct2(List<DataItem> items, int value) public void ForEachOverListOfStruct2(List<DataItem> items, int value)
{ {
foreach (DataItem item in items) { foreach (DataItem item in items)
{
#if ROSLYN && OPT #if ROSLYN && OPT
// The variable name differs based on whether roslyn optimizes out the 'item' variable // The variable name differs based on whether roslyn optimizes out the 'item' variable
DataItem current = item; DataItem current = item;
@ -510,7 +538,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void ForEachOverListOfStruct3(List<DataItem> items, int value) public void ForEachOverListOfStruct3(List<DataItem> items, int value)
{ {
foreach (DataItem item in items) { foreach (DataItem item in items)
{
item.TestCall(); item.TestCall();
} }
} }
@ -518,7 +547,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
#if !MCS #if !MCS
public void ForEachOverMultiDimArray(int[,] items) public void ForEachOverMultiDimArray(int[,] items)
{ {
foreach (int value in items) { foreach (int value in items)
{
Console.WriteLine(value); Console.WriteLine(value);
Console.WriteLine(value); Console.WriteLine(value);
} }
@ -526,7 +556,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void ForEachOverMultiDimArray2(int[,,] items) public void ForEachOverMultiDimArray2(int[,,] items)
{ {
foreach (int value in items) { foreach (int value in items)
{
Console.WriteLine(value); Console.WriteLine(value);
Console.WriteLine(value); Console.WriteLine(value);
} }
@ -535,12 +566,14 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public unsafe void ForEachOverMultiDimArray3(int*[,] items) public unsafe void ForEachOverMultiDimArray3(int*[,] items)
{ {
#if ROSLYN && OPT #if ROSLYN && OPT
foreach (int* intPtr in items) { foreach (int* intPtr in items)
{
Console.WriteLine(*intPtr); Console.WriteLine(*intPtr);
Console.WriteLine(*intPtr); Console.WriteLine(*intPtr);
} }
#else #else
foreach (int* ptr in items) { foreach (int* ptr in items)
{
Console.WriteLine(*ptr); Console.WriteLine(*ptr);
Console.WriteLine(*ptr); Console.WriteLine(*ptr);
} }
@ -548,20 +581,23 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
} }
#endif #endif
#endregion #endregion
public void ForOverArray(string[] array) public void ForOverArray(string[] array)
{ {
for (int i = 0; i < array.Length; i++) { for (int i = 0; i < array.Length; i++)
{
array[i].ToLower(); array[i].ToLower();
} }
} }
public void NoForeachOverArray(string[] array) public void NoForeachOverArray(string[] array)
{ {
for (int i = 0; i < array.Length; i++) { for (int i = 0; i < array.Length; i++)
{
string value = array[i]; string value = array[i];
if (i % 5 == 0) { if (i % 5 == 0)
{
Console.WriteLine(value); Console.WriteLine(value);
} }
} }
@ -569,12 +605,17 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void NestedLoops() public void NestedLoops()
{ {
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++)
if (i % 2 == 0) { {
for (int j = 0; j < 5; j++) { if (i % 2 == 0)
{
for (int j = 0; j < 5; j++)
{
Console.WriteLine("Y"); Console.WriteLine("Y");
} }
} else { }
else
{
Console.WriteLine("X"); Console.WriteLine("X");
} }
} }
@ -583,17 +624,22 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public int MultipleExits() public int MultipleExits()
{ {
int num = 0; int num = 0;
while (true) { while (true)
if (num % 4 == 0) { {
if (num % 4 == 0)
{
return 4; return 4;
} }
if (num % 7 == 0) { if (num % 7 == 0)
{
break; break;
} }
if (num % 9 == 0) { if (num % 9 == 0)
{
return 5; return 5;
} }
if (num % 11 == 0) { if (num % 11 == 0)
{
break; break;
} }
num++; num++;
@ -630,18 +676,25 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public int InterestingLoop() public int InterestingLoop()
{ {
int num = 0; int num = 0;
if (num % 11 == 0) { if (num % 11 == 0)
while (true) { {
if (num % 4 == 0) { while (true)
if (num % 7 != 0) { {
if (num % 4 == 0)
{
if (num % 7 != 0)
{
Console.WriteLine("!7"); Console.WriteLine("!7");
break; break;
} }
if (num % 11 != 0) { if (num % 11 != 0)
{
Console.WriteLine("7"); Console.WriteLine("7");
break; break;
} }
} else { }
else
{
num++; num++;
} }
} }
@ -659,14 +712,19 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void WhileLoop() public void WhileLoop()
{ {
Console.WriteLine("Initial"); Console.WriteLine("Initial");
if (Condition("if")) { if (Condition("if"))
while (Condition("while")) { {
while (Condition("while"))
{
Console.WriteLine("Loop Body"); Console.WriteLine("Loop Body");
if (Condition("test")) { if (Condition("test"))
if (Condition("continue")) { {
if (Condition("continue"))
{
continue; continue;
} }
if (!Condition("break")) { if (!Condition("break"))
{
break; break;
} }
} }
@ -676,20 +734,23 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
} }
Console.WriteLine("End of method"); Console.WriteLine("End of method");
} }
//other configurations work fine, just with different labels //other configurations work fine, just with different labels
#if OPT && !MCS #if OPT && !MCS
public void WhileWithGoto() public void WhileWithGoto()
{ {
while (Condition("Main Loop")) { while (Condition("Main Loop"))
if (Condition("Condition")) { {
if (Condition("Condition"))
{
goto IL_000f; goto IL_000f;
} }
// TODO reorder branches with successive block? // TODO reorder branches with successive block?
goto IL_0026; goto IL_0026;
IL_000f: IL_000f:
Console.WriteLine("Block1"); Console.WriteLine("Block1");
if (Condition("Condition2")) { if (Condition("Condition2"))
{
continue; continue;
} }
// TODO remove redundant goto? // TODO remove redundant goto?
@ -704,14 +765,19 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void DoWhileLoop() public void DoWhileLoop()
{ {
Console.WriteLine("Initial"); Console.WriteLine("Initial");
if (Condition("if")) { if (Condition("if"))
do { {
do
{
Console.WriteLine("Loop Body"); Console.WriteLine("Loop Body");
if (Condition("test")) { if (Condition("test"))
if (Condition("continue")) { {
if (Condition("continue"))
{
continue; continue;
} }
if (!Condition("break")) { if (!Condition("break"))
{
break; break;
} }
} }
@ -725,30 +791,38 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void Issue1395(int count) public void Issue1395(int count)
{ {
Environment.GetCommandLineArgs(); Environment.GetCommandLineArgs();
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++)
{
Environment.GetCommandLineArgs(); Environment.GetCommandLineArgs();
do { do
{
#if OPT || MCS #if OPT || MCS
IL_0013: IL_0013:
#else #else
IL_0016: IL_0016:
#endif #endif
Environment.GetCommandLineArgs(); Environment.GetCommandLineArgs();
if (Condition("part1")) { if (Condition("part1"))
{
Environment.GetEnvironmentVariables(); Environment.GetEnvironmentVariables();
if (Condition("restart")) { if (Condition("restart"))
{
#if OPT || MCS #if OPT || MCS
goto IL_0013; goto IL_0013;
#else #else
goto IL_0016; goto IL_0016;
#endif #endif
} }
} else { }
else
{
Environment.GetLogicalDrives(); Environment.GetLogicalDrives();
} }
Environment.GetCommandLineArgs(); Environment.GetCommandLineArgs();
while (count > 0) { while (count > 0)
switch (count) { {
switch (count)
{
case 0: case 0:
case 1: case 1:
case 2: case 2:
@ -774,14 +848,19 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void ForLoop() public void ForLoop()
{ {
Console.WriteLine("Initial"); Console.WriteLine("Initial");
if (Condition("if")) { if (Condition("if"))
for (int i = 0; Condition("for"); i++) { {
for (int i = 0; Condition("for"); i++)
{
Console.WriteLine("Loop Body"); Console.WriteLine("Loop Body");
if (Condition("test")) { if (Condition("test"))
if (Condition("continue")) { {
if (Condition("continue"))
{
continue; continue;
} }
if (!Condition("not-break")) { if (!Condition("not-break"))
{
break; break;
} }
} }
@ -794,15 +873,20 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void ReturnFromDoWhileInTryFinally() public void ReturnFromDoWhileInTryFinally()
{ {
try { try
do { {
if (Condition("return")) { do
{
if (Condition("return"))
{
return; return;
} }
} while (Condition("repeat")); } while (Condition("repeat"));
Environment.GetCommandLineArgs(); Environment.GetCommandLineArgs();
} finally { }
finally
{
Environment.GetCommandLineArgs(); Environment.GetCommandLineArgs();
} }
@ -811,10 +895,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void ForLoopWithEarlyReturn(int[] ids) public void ForLoopWithEarlyReturn(int[] ids)
{ {
for (int i = 0; i < ids.Length; i++) { for (int i = 0; i < ids.Length; i++)
{
Item item = null; Item item = null;
TryGetItem(ids[i], out item); TryGetItem(ids[i], out item);
if (item == null) { if (item == null)
{
break; break;
} }
} }
@ -822,8 +908,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void ForeachLoopWithEarlyReturn(List<object> items) public void ForeachLoopWithEarlyReturn(List<object> items)
{ {
foreach (object item in items) { foreach (object item in items)
if ((someObject = item) == null) { {
if ((someObject = item) == null)
{
break; break;
} }
} }
@ -831,16 +919,20 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void NestedForeach(List<object> items1, List<object> items2) public void NestedForeach(List<object> items1, List<object> items2)
{ {
foreach (object item in items1) { foreach (object item in items1)
{
bool flag = false; bool flag = false;
foreach (object item2 in items2) { foreach (object item2 in items2)
if (item2 == item) { {
if (item2 == item)
{
flag = true; flag = true;
break; break;
} }
} }
if (!flag) { if (!flag)
{
Console.WriteLine(item); Console.WriteLine(item);
} }
} }
@ -849,23 +941,34 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void MergeAroundContinue() public void MergeAroundContinue()
{ {
for (int i = 0; i < 20; i++) { for (int i = 0; i < 20; i++)
if (i % 3 == 0) { {
if (i != 6) { if (i % 3 == 0)
{
if (i != 6)
{
continue; continue;
} }
} else if (i % 5 == 0) { }
if (i != 5) { else if (i % 5 == 0)
{
if (i != 5)
{
continue; continue;
} }
} else if (i % 7 == 0) { }
if (i != 7) { else if (i % 7 == 0)
{
if (i != 7)
{
continue; continue;
} }
} else if (i % 11 == 0) { }
else if (i % 11 == 0)
{
continue; continue;
} }
Console.WriteLine(i); Console.WriteLine(i);
} }
Console.WriteLine("end"); Console.WriteLine("end");

9
ICSharpCode.Decompiler.Tests/TestCases/Pretty/NativeInts.cs

@ -143,15 +143,18 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void CompoundAssign() public void CompoundAssign()
{ {
GetInstance(0).i += i32; GetInstance(0).i += i32;
checked { checked
{
GetInstance(1).i += i32; GetInstance(1).i += i32;
} }
GetInstance(2).u *= 2u; GetInstance(2).u *= 2u;
checked { checked
{
GetInstance(3).u *= 2u; GetInstance(3).u *= 2u;
} }
GetInstance(4).intptr += (nint)i32; GetInstance(4).intptr += (nint)i32;
checked { checked
{
// Note: the cast is necessary here, without it we'd call IntPtr.op_Addition // Note: the cast is necessary here, without it we'd call IntPtr.op_Addition
// but that is always unchecked. // but that is always unchecked.
GetInstance(5).intptr += (nint)i32; GetInstance(5).intptr += (nint)i32;

18
ICSharpCode.Decompiler.Tests/TestCases/Pretty/NullPropagation.cs

@ -68,7 +68,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{ {
} }
} }
private class Container<T1, T2> private class Container<T1, T2>
{ {
public GenericStruct<T1, T2> Other; public GenericStruct<T1, T2> Other;
@ -84,7 +84,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{ {
return "(" + Field1?.ToString() + ", " + Field2?.ToString() + ")"; return "(" + Field1?.ToString() + ", " + Field2?.ToString() + ")";
} }
public int? GetTextLength() public int? GetTextLength()
{ {
return Field1?.ToString().Length + Field2?.ToString().Length + 4; return Field1?.ToString().Length + Field2?.ToString().Length + 4;
@ -250,10 +250,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
private void NotNullPropagation(MyClass c) private void NotNullPropagation(MyClass c)
{ {
// don't decompile this to "(c?.IntVal ?? 0) != 0" // don't decompile this to "(c?.IntVal ?? 0) != 0"
if (c != null && c.IntVal != 0) { if (c != null && c.IntVal != 0)
{
Console.WriteLine("non-zero"); Console.WriteLine("non-zero");
} }
if (c == null || c.IntVal == 0) { if (c == null || c.IntVal == 0)
{
Console.WriteLine("null or zero"); Console.WriteLine("null or zero");
} }
Console.WriteLine("end of method"); Console.WriteLine("end of method");
@ -261,11 +263,13 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
private void Setter(MyClass c) private void Setter(MyClass c)
{ {
if (c != null) { if (c != null)
{
c.IntVal = 1; c.IntVal = 1;
} }
Console.WriteLine(); Console.WriteLine();
if (c != null) { if (c != null)
{
c.Property = null; c.Property = null;
} }
} }
@ -310,7 +314,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
Console.WriteLine(setsOfNumbers?[0]?[1].ToString() == "2"); Console.WriteLine(setsOfNumbers?[0]?[1].ToString() == "2");
Console.WriteLine(setsOfNumbers?[1]?[1].ToString() == null); Console.WriteLine(setsOfNumbers?[1]?[1].ToString() == null);
} }
private static dynamic DynamicNullProp(dynamic a) private static dynamic DynamicNullProp(dynamic a)
{ {
return a?.b.c(1)?.d[10]; return a?.b.c(1)?.d[10];

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

@ -25,7 +25,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{ {
public static void OutVarInShortCircuit(Dictionary<int, string> d) public static void OutVarInShortCircuit(Dictionary<int, string> d)
{ {
if (d.Count > 2 && d.TryGetValue(42, out string value)) { if (d.Count > 2 && d.TryGetValue(42, out string value))
{
Console.WriteLine(value); Console.WriteLine(value);
} }
} }
@ -34,7 +35,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{ {
// Note: needs reasoning about "definitely assigned if true" // Note: needs reasoning about "definitely assigned if true"
// to ensure that the value is initialized when the delegate is declared. // to ensure that the value is initialized when the delegate is declared.
if (d.Count > 2 && d.TryGetValue(42, out string value)) { if (d.Count > 2 && d.TryGetValue(42, out string value))
{
return delegate { return delegate {
Console.WriteLine(value); Console.WriteLine(value);
}; };

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

@ -88,7 +88,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
} }
[DllImport("ws2_32.dll", SetLastError = true)] [DllImport("ws2_32.dll", SetLastError = true)]
internal static extern IntPtr ioctlsocket([In] IntPtr socketHandle, [In] int cmd, [In] [Out] ref int argp); internal static extern IntPtr ioctlsocket([In] IntPtr socketHandle, [In] int cmd, [In][Out] ref int argp);
public void CallMethodWithInOutParameter() public void CallMethodWithInOutParameter()
{ {

3
ICSharpCode.Decompiler.Tests/TestCases/Pretty/QualifierTests.cs

@ -264,7 +264,8 @@ namespace ICSharpCode.Decompiler.Tests.Pretty
private void LocalConflictsWithTypeName() private void LocalConflictsWithTypeName()
{ {
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++)
{
QualifierTests.i.Test(); QualifierTests.i.Test();
} }
} }

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

@ -165,11 +165,11 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
let pname = pi.Name let pname = pi.Name
let pvalue = pi.GetValue(customers, null) let pvalue = pi.GetValue(customers, null)
select new HbmParam { select new HbmParam {
Name = pname, Name = pname,
Text = new string[1] { Text = new string[1] {
(pvalue == null) ? "null" : pvalue.ToString() (pvalue == null) ? "null" : pvalue.ToString()
} }
}).ToArray(); }).ToArray();
} }
public object Join() public object Join()

304
ICSharpCode.Decompiler.Tests/TestCases/Pretty/ReduceNesting.cs

@ -9,12 +9,14 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void IfIf() public void IfIf()
{ {
if (B(0)) { if (B(0))
{
Console.WriteLine(0); Console.WriteLine(0);
return; return;
} }
if (B(1)) { if (B(1))
{
Console.WriteLine(1); Console.WriteLine(1);
} }
@ -23,13 +25,15 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void IfSwitch() public void IfSwitch()
{ {
if (B(0)) { if (B(0))
{
Console.WriteLine(0); Console.WriteLine(0);
return; return;
} }
Console.WriteLine("switch"); Console.WriteLine("switch");
switch (I(0)) { switch (I(0))
{
case 0: case 0:
Console.WriteLine("case 0"); Console.WriteLine("case 0");
break; break;
@ -44,13 +48,15 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void IfSwitchSwitch() public void IfSwitchSwitch()
{ {
if (B(0)) { if (B(0))
{
Console.WriteLine(0); Console.WriteLine(0);
return; return;
} }
Console.WriteLine("switch 0"); Console.WriteLine("switch 0");
switch (I(1)) { switch (I(1))
{
case 0: case 0:
Console.WriteLine("case 0"); Console.WriteLine("case 0");
return; return;
@ -60,7 +66,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
} }
Console.WriteLine("switch 1"); Console.WriteLine("switch 1");
switch (I(1)) { switch (I(1))
{
case 0: case 0:
Console.WriteLine("case 0"); Console.WriteLine("case 0");
break; break;
@ -75,12 +82,14 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void IfLoop() public void IfLoop()
{ {
if (B(0)) { if (B(0))
{
Console.WriteLine(0); Console.WriteLine(0);
return; return;
} }
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++)
{
Console.WriteLine(i); Console.WriteLine(i);
} }
@ -89,14 +98,17 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void LoopContinue() public void LoopContinue()
{ {
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++)
{
Console.WriteLine(i); Console.WriteLine(i);
if (B(0)) { if (B(0))
{
Console.WriteLine(0); Console.WriteLine(0);
continue; continue;
} }
if (B(1)) { if (B(1))
{
Console.WriteLine(1); Console.WriteLine(1);
} }
Console.WriteLine("loop-tail"); Console.WriteLine("loop-tail");
@ -105,19 +117,23 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void LoopBreak() public void LoopBreak()
{ {
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++)
{
Console.WriteLine(i); Console.WriteLine(i);
if (B(0)) { if (B(0))
{
Console.WriteLine(0); Console.WriteLine(0);
continue; continue;
} }
if (B(1)) { if (B(1))
{
Console.WriteLine(1); Console.WriteLine(1);
break; break;
} }
if (B(2)) { if (B(2))
{
Console.WriteLine(2); Console.WriteLine(2);
} }
@ -129,16 +145,21 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void LoopBreakElseIf() public void LoopBreakElseIf()
{ {
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++)
{
Console.WriteLine(i); Console.WriteLine(i);
if (B(0)) { if (B(0))
{
Console.WriteLine(0); Console.WriteLine(0);
continue; continue;
} }
if (B(1)) { if (B(1))
{
Console.WriteLine(1); Console.WriteLine(1);
} else if (B(2)) { }
else if (B(2))
{
Console.WriteLine(2); Console.WriteLine(2);
} }
break; break;
@ -148,7 +169,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void SwitchIf() public void SwitchIf()
{ {
switch (I(0)) { switch (I(0))
{
case 0: case 0:
Console.WriteLine("case 0"); Console.WriteLine("case 0");
return; return;
@ -156,8 +178,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
Console.WriteLine("case 1"); Console.WriteLine("case 1");
return; return;
} }
if (B(0)) { if (B(0))
{
Console.WriteLine(0); Console.WriteLine(0);
} }
Console.WriteLine("end"); Console.WriteLine("end");
@ -165,8 +188,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void NestedSwitchIf() public void NestedSwitchIf()
{ {
if (B(0)) { if (B(0))
switch (I(0)) { {
switch (I(0))
{
case 0: case 0:
Console.WriteLine("case 0"); Console.WriteLine("case 0");
return; return;
@ -175,10 +200,13 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
return; return;
} }
if (B(1)) { if (B(1))
{
Console.WriteLine(1); Console.WriteLine(1);
} }
} else { }
else
{
Console.WriteLine("else"); Console.WriteLine("else");
} }
} }
@ -186,66 +214,84 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
// nesting should not be reduced as maximum nesting level is 1 // nesting should not be reduced as maximum nesting level is 1
public void EarlyExit1() public void EarlyExit1()
{ {
if (!B(0)) { if (!B(0))
for (int i = 0; i < 10; i++) { {
for (int i = 0; i < 10; i++)
{
Console.WriteLine(i); Console.WriteLine(i);
} }
Console.WriteLine("end"); Console.WriteLine("end");
} }
} }
// nesting should be reduced as maximum nesting level is 2 // nesting should be reduced as maximum nesting level is 2
public void EarlyExit2() public void EarlyExit2()
{ {
if (B(0)) { if (B(0))
{
return; return;
} }
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++)
{
Console.WriteLine(i); Console.WriteLine(i);
if (i % 2 == 0) { if (i % 2 == 0)
{
Console.WriteLine("even"); Console.WriteLine("even");
} }
} }
Console.WriteLine("end"); Console.WriteLine("end");
} }
// nesting should not be reduced as maximum nesting level is 1 and the else block has no more instructions than any other block // nesting should not be reduced as maximum nesting level is 1 and the else block has no more instructions than any other block
public void BalancedIf() public void BalancedIf()
{ {
if (B(0)) { if (B(0))
{
Console.WriteLine("true"); Console.WriteLine("true");
if (B(1)) { if (B(1))
{
Console.WriteLine(1); Console.WriteLine(1);
} }
} else { }
if (B(2)) { else
{
if (B(2))
{
Console.WriteLine(2); Console.WriteLine(2);
} }
Console.WriteLine("false"); Console.WriteLine("false");
} }
} }
public string ComplexCase1(string s) public string ComplexCase1(string s)
{ {
if (B(0)) { if (B(0))
{
return s; return s;
} }
for (int i = 0; i < s.Length; i++) { for (int i = 0; i < s.Length; i++)
if (B(1)) { {
if (B(1))
{
Console.WriteLine(1); Console.WriteLine(1);
} else if (B(2)) { }
switch (i) { else if (B(2))
{
switch (i)
{
case 1: case 1:
if (B(3)) { if (B(3))
{
Console.WriteLine(3); Console.WriteLine(3);
break; break;
} }
Console.WriteLine("case1"); Console.WriteLine("case1");
if (B(4)) { if (B(4))
{
Console.WriteLine(4); Console.WriteLine(4);
} }
break; break;
@ -255,10 +301,15 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
break; break;
} }
Console.WriteLine(2); Console.WriteLine(2);
} else if (B(5)) { }
else if (B(5))
{
Console.WriteLine(5); Console.WriteLine(5);
} else { }
if (B(6)) { else
{
if (B(6))
{
Console.WriteLine(6); Console.WriteLine(6);
} }
Console.WriteLine("else"); Console.WriteLine("else");
@ -269,48 +320,64 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void EarlyExitBeforeTry() public void EarlyExitBeforeTry()
{ {
if (B(0)) { if (B(0))
{
return; return;
} }
try { try
if (B(1)) { {
if (B(1))
{
Console.WriteLine(); Console.WriteLine();
} }
} catch { }
catch
{
} }
} }
public void EarlyExitInTry() public void EarlyExitInTry()
{ {
try { try
if (B(0)) { {
if (B(0))
{
return; return;
} }
Console.WriteLine(); Console.WriteLine();
if (B(1)) { if (B(1))
for (int i = 0; i < 10; i++) { {
for (int i = 0; i < 10; i++)
{
Console.WriteLine(i); Console.WriteLine(i);
} }
} }
} catch { }
catch
{
} }
} }
public void ContinueLockInLoop() public void ContinueLockInLoop()
{ {
while (B(0)) { while (B(0))
lock (Console.Out) { {
if (B(1)) { lock (Console.Out)
{
if (B(1))
{
continue; continue;
} }
Console.WriteLine(); Console.WriteLine();
if (B(2)) { if (B(2))
for (int i = 0; i < 10; i++) { {
for (int i = 0; i < 10; i++)
{
Console.WriteLine(i); Console.WriteLine(i);
} }
} }
@ -320,18 +387,23 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void BreakLockInLoop() public void BreakLockInLoop()
{ {
while (B(0)) { while (B(0))
lock (Console.Out) { {
lock (Console.Out)
{
// Before ReduceNestingTransform, the rest of the lock body is nested in if(!B(1)) with a continue; // Before ReduceNestingTransform, the rest of the lock body is nested in if(!B(1)) with a continue;
// the B(1) case falls through to a break outside the lock // the B(1) case falls through to a break outside the lock
if (B(1)) { if (B(1))
{
break; break;
} }
Console.WriteLine(); Console.WriteLine();
if (B(2)) { if (B(2))
for (int i = 0; i < 10; i++) { {
for (int i = 0; i < 10; i++)
{
Console.WriteLine(i); Console.WriteLine(i);
} }
} }
@ -347,16 +419,21 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public unsafe void BreakPinnedInLoop(int[] arr) public unsafe void BreakPinnedInLoop(int[] arr)
{ {
while (B(0)) { while (B(0))
fixed (int* ptr = arr) { {
if (B(1)) { fixed (int* ptr = arr)
{
if (B(1))
{
break; break;
} }
Console.WriteLine(); Console.WriteLine();
if (B(2)) { if (B(2))
for (int i = 0; i < 10; i++) { {
for (int i = 0; i < 10; i++)
{
Console.WriteLine(ptr[i]); Console.WriteLine(ptr[i]);
} }
} }
@ -370,29 +447,39 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void CannotEarlyExitInTry() public void CannotEarlyExitInTry()
{ {
try { try
if (B(0)) { {
if (B(0))
{
Console.WriteLine(); Console.WriteLine();
if (B(1)) { if (B(1))
for (int i = 0; i < 10; i++) { {
for (int i = 0; i < 10; i++)
{
Console.WriteLine(i); Console.WriteLine(i);
} }
} }
} }
} catch { }
catch
{
} }
Console.WriteLine(); Console.WriteLine();
} }
public void EndpointUnreachableDueToEarlyExit() public void EndpointUnreachableDueToEarlyExit()
{ {
using (Console.Out) { using (Console.Out)
if (B(0)) { {
if (B(0))
{
return; return;
} }
do { do
if (B(1)) { {
if (B(1))
{
return; return;
} }
} while (B(2)); } while (B(2));
@ -402,8 +489,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void SwitchInTry() public void SwitchInTry()
{ {
try { try
switch (I(0)) { {
switch (I(0))
{
case 1: case 1:
Console.WriteLine(1); Console.WriteLine(1);
return; return;
@ -412,19 +501,25 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
return; return;
} }
Console.WriteLine(3); Console.WriteLine(3);
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++)
{
Console.WriteLine(i); Console.WriteLine(i);
} }
} catch { }
catch
{
throw; throw;
} }
} }
public void SwitchInTryInLoopReturn() public void SwitchInTryInLoopReturn()
{ {
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++)
try { {
switch (I(0)) { try
{
switch (I(0))
{
case 1: case 1:
Console.WriteLine(1); Console.WriteLine(1);
return; return;
@ -433,10 +528,13 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
return; return;
} }
Console.WriteLine(3); Console.WriteLine(3);
for (int j = 0; j < 10; j++) { for (int j = 0; j < 10; j++)
{
Console.WriteLine(j); Console.WriteLine(j);
} }
} catch { }
catch
{
throw; throw;
} }
} }
@ -444,9 +542,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void SwitchInTryInLoopContinue() public void SwitchInTryInLoopContinue()
{ {
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++)
try { {
switch (I(0)) { try
{
switch (I(0))
{
case 1: case 1:
Console.WriteLine(1); Console.WriteLine(1);
continue; continue;
@ -455,10 +556,13 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
continue; continue;
} }
Console.WriteLine(3); Console.WriteLine(3);
for (int j = 0; j < 10; j++) { for (int j = 0; j < 10; j++)
{
Console.WriteLine(j); Console.WriteLine(j);
} }
} catch { }
catch
{
throw; throw;
} }
} }

21
ICSharpCode.Decompiler.Tests/TestCases/Pretty/RefLocalsAndReturns.cs

@ -36,7 +36,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{ {
Issue1630[] array = new Issue1630[1]; Issue1630[] array = new Issue1630[1];
int num = 0; int num = 0;
while (num >= 0) { while (num >= 0)
{
ref Issue1630 reference = ref array[num]; ref Issue1630 reference = ref array[num];
Console.WriteLine(reference.data); Console.WriteLine(reference.data);
num = reference.next; num = reference.next;
@ -225,8 +226,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static ref int FindNumber(int target) public static ref int FindNumber(int target)
{ {
for (int i = 0; i < numbers.Length; i++) { for (int i = 0; i < numbers.Length; i++)
if (numbers[i] >= target) { {
if (numbers[i] >= target)
{
return ref numbers[i]; return ref numbers[i];
} }
} }
@ -240,7 +243,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static ref int ElementAtOrDefault(int index) public static ref int ElementAtOrDefault(int index)
{ {
if (index >= 0 && index < numbers.Length) { if (index >= 0 && index < numbers.Length)
{
return ref numbers[index]; return ref numbers[index];
} }
return ref DefaultInt; return ref DefaultInt;
@ -248,7 +252,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static ref int LastOrDefault() public static ref int LastOrDefault()
{ {
if (numbers.Length != 0) { if (numbers.Length != 0)
{
return ref numbers[numbers.Length - 1]; return ref numbers[numbers.Length - 1];
} }
return ref DefaultInt; return ref DefaultInt;
@ -263,7 +268,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static ref string GetOrSetString(int index) public static ref string GetOrSetString(int index)
{ {
if (index < 0 || index >= strings.Length) { if (index < 0 || index >= strings.Length)
{
return ref NullString; return ref NullString;
} }
@ -285,7 +291,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{ {
ref NormalStruct @ref = ref GetRef<NormalStruct>(); ref NormalStruct @ref = ref GetRef<NormalStruct>();
RefReassignment(ref @ref); RefReassignment(ref @ref);
if (s.GetHashCode() == 0) { if (s.GetHashCode() == 0)
{
@ref = ref GetRef<NormalStruct>(); @ref = ref GetRef<NormalStruct>();
} }
RefReassignment(ref @ref.GetHashCode() == 4 ? ref @ref : ref s); RefReassignment(ref @ref.GetHashCode() == 4 ? ref @ref : ref s);

156
ICSharpCode.Decompiler.Tests/TestCases/Pretty/ShortCircuit.cs

@ -31,37 +31,37 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public abstract void M1(); public abstract void M1();
public abstract void M2(); public abstract void M2();
public abstract void E(); public abstract void E();
public void ExprAnd() public void ExprAnd()
{ {
B(F(0) && F(1)); B(F(0) && F(1));
} }
public void ExprOr() public void ExprOr()
{ {
B(F(0) || F(1)); B(F(0) || F(1));
} }
public void ExprCond() public void ExprCond()
{ {
B(F(0) ? F(1) : F(2)); B(F(0) ? F(1) : F(2));
} }
public void ExprCondAnd() public void ExprCondAnd()
{ {
B((F(0) && F(1)) ? F(2) : F(3)); B((F(0) && F(1)) ? F(2) : F(3));
} }
public void ExprMix4A() public void ExprMix4A()
{ {
B(((F(0) || F(1)) && F(2)) || F(3)); B(((F(0) || F(1)) && F(2)) || F(3));
} }
public void ExprMix4B() public void ExprMix4B()
{ {
B((F(0) || F(1)) && (F(2) || F(3))); B((F(0) || F(1)) && (F(2) || F(3)));
} }
public void ExprMix4C() public void ExprMix4C()
{ {
B((F(0) && F(1)) || (F(2) && F(3))); B((F(0) && F(1)) || (F(2) && F(3)));
@ -69,9 +69,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void StmtAnd2() public void StmtAnd2()
{ {
if (F(0) && F(1)) { if (F(0) && F(1))
{
M1(); M1();
} else { }
else
{
M2(); M2();
} }
E(); E();
@ -79,16 +82,20 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void StmtOr2A() public void StmtOr2A()
{ {
if (F(0) || F(1)) { if (F(0) || F(1))
{
M1(); M1();
} }
} }
public void StmtOr2B() public void StmtOr2B()
{ {
if (F(0) || F(1)) { if (F(0) || F(1))
{
M1(); M1();
} else { }
else
{
M2(); M2();
} }
E(); E();
@ -96,9 +103,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void StmtAnd3() public void StmtAnd3()
{ {
if (F(0) && F(1) && F(2)) { if (F(0) && F(1) && F(2))
{
M1(); M1();
} else { }
else
{
M2(); M2();
} }
E(); E();
@ -106,9 +116,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void StmtOr3() public void StmtOr3()
{ {
if (F(0) || F(1) || F(2)) { if (F(0) || F(1) || F(2))
{
M1(); M1();
} else { }
else
{
M2(); M2();
} }
E(); E();
@ -116,9 +129,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void StmtOr4() public void StmtOr4()
{ {
if (GetInt(0) != 0 || GetInt(1) != 0) { if (GetInt(0) != 0 || GetInt(1) != 0)
{
M1(); M1();
} else { }
else
{
M2(); M2();
} }
E(); E();
@ -126,73 +142,92 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void StmtMix3A() public void StmtMix3A()
{ {
if ((F(0) || F(1)) && F(2)) { if ((F(0) || F(1)) && F(2))
{
M1(); M1();
} }
} }
public void StmtMix3B() public void StmtMix3B()
{ {
if ((F(0) || F(1)) && F(2)) { if ((F(0) || F(1)) && F(2))
{
M1(); M1();
} else { }
else
{
M2(); M2();
} }
} }
public void StmtMix4V1A() public void StmtMix4V1A()
{ {
if (((F(0) || F(1)) && F(2)) || F(3)) { if (((F(0) || F(1)) && F(2)) || F(3))
{
M1(); M1();
} }
} }
public void StmtMix4V1B() public void StmtMix4V1B()
{ {
if (((F(0) || F(1)) && F(2)) || F(3)) { if (((F(0) || F(1)) && F(2)) || F(3))
{
M1(); M1();
} else { }
else
{
M2(); M2();
} }
} }
public void StmtMix4V2A() public void StmtMix4V2A()
{ {
if ((F(0) || F(1)) && (F(2) || F(3))) { if ((F(0) || F(1)) && (F(2) || F(3)))
{
M1(); M1();
} }
} }
public void StmtMix4V2B() public void StmtMix4V2B()
{ {
if ((F(0) || F(1)) && (F(2) || F(3))) { if ((F(0) || F(1)) && (F(2) || F(3)))
{
M1(); M1();
} else { }
else
{
M2(); M2();
} }
} }
public void StmtMix4V3A() public void StmtMix4V3A()
{ {
if ((F(0) && F(1)) || (F(2) && F(3))) { if ((F(0) && F(1)) || (F(2) && F(3)))
{
M1(); M1();
} }
} }
public void StmtMix4V3B() public void StmtMix4V3B()
{ {
if ((F(0) && F(1)) || (F(2) && F(3))) { if ((F(0) && F(1)) || (F(2) && F(3)))
{
M1(); M1();
} else { }
else
{
M2(); M2();
} }
} }
public void StmtComplex() public void StmtComplex()
{ {
if (F(0) && F(1) && !F(2) && (F(3) || F(4))) { if (F(0) && F(1) && !F(2) && (F(3) || F(4)))
{
M1(); M1();
} else { }
else
{
M2(); M2();
} }
E(); E();
@ -200,9 +235,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void StmtComplex2(int i) public void StmtComplex2(int i)
{ {
if (i > 1000 || (i >= 1 && i <= 8) || i == 42) { if (i > 1000 || (i >= 1 && i <= 8) || i == 42)
{
M1(); M1();
} else { }
else
{
M2(); M2();
} }
E(); E();
@ -210,9 +248,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void StmtComplex3(int i) public void StmtComplex3(int i)
{ {
if (i > 1000 || (i >= 1 && i <= 8) || (i >= 100 && i <= 200) || i == 42) { if (i > 1000 || (i >= 1 && i <= 8) || (i >= 100 && i <= 200) || i == 42)
{
M1(); M1();
} else { }
else
{
M2(); M2();
} }
E(); E();
@ -220,9 +261,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void StmtComplex4(int i) public void StmtComplex4(int i)
{ {
if (i > 1000 || (i >= 1 && i <= 8) || i == 42 || i == 23) { if (i > 1000 || (i >= 1 && i <= 8) || i == 42 || i == 23)
{
M1(); M1();
} else { }
else
{
M2(); M2();
} }
E(); E();
@ -230,11 +274,15 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void StmtComplex5() public void StmtComplex5()
{ {
if (F(0)) { if (F(0))
if (!F(1) && !F(2)) { {
if (!F(1) && !F(2))
{
return; return;
} }
} else if (!F(3) || !F(4)) { }
else if (!F(3) || !F(4))
{
M2(); M2();
return; return;
} }
@ -243,9 +291,11 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public int StmtComplex6() public int StmtComplex6()
{ {
if (F(0)) { if (F(0))
{
M1(); M1();
if (F(1) || F(2)) { if (F(1) || F(2))
{
return 1; return 1;
} }
} }
@ -254,7 +304,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public int InferCorrectOrder() public int InferCorrectOrder()
{ {
if (F(1) || F(2)) { if (F(1) || F(2))
{
return 1; return 1;
} }
return 2; return 2;
@ -263,15 +314,20 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
#if !OPT #if !OPT
public void EmptyIf() public void EmptyIf()
{ {
if (F(0)) { if (F(0))
{
} }
if (!F(1)) { if (!F(1))
{
} }
if (F(2) && F(3)) { if (F(2) && F(3))
{
} }
if (F(4) || F(5)) { if (F(4) || F(5))
{
} }
if (F(0) && F(1) && !F(2) && (F(3) || F(4))) { if (F(0) && F(1) && !F(2) && (F(3) || F(4)))
{
} }
E(); E();
} }

368
ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.cs

@ -52,7 +52,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
#if !ROSLYN #if !ROSLYN
public static State SwitchOverNullableBool(bool? value) public static State SwitchOverNullableBool(bool? value)
{ {
switch (value) { switch (value)
{
case false: case false:
return State.False; return State.False;
case true: case true:
@ -67,7 +68,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static bool? SwitchOverNullableEnum(State? state) public static bool? SwitchOverNullableEnum(State? state)
{ {
switch (state) { switch (state)
{
case State.False: case State.False:
return false; return false;
case State.True: case State.True:
@ -82,7 +84,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static string SparseIntegerSwitch(int i) public static string SparseIntegerSwitch(int i)
{ {
Console.WriteLine("SparseIntegerSwitch: " + i); Console.WriteLine("SparseIntegerSwitch: " + i);
switch (i) { switch (i)
{
case -10000000: case -10000000:
return "-10 mln"; return "-10 mln";
case -100: case -100:
@ -112,7 +115,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static void SparseIntegerSwitch2(int i) public static void SparseIntegerSwitch2(int i)
{ {
switch (i) { switch (i)
{
case 4: case 4:
case 10: case 10:
case 11: case 11:
@ -130,7 +134,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static bool SparseIntegerSwitch3(int i) public static bool SparseIntegerSwitch3(int i)
{ {
switch (i) { switch (i)
{
case 0: case 0:
case 10: case 10:
case 11: case 11:
@ -146,7 +151,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static string SwitchOverNullableInt(int? i) public static string SwitchOverNullableInt(int? i)
{ {
switch (i) { switch (i)
{
case null: case null:
return "null"; return "null";
case 0: case 0:
@ -162,7 +168,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static string SwitchOverNullableIntNullCaseCombined(int? i) public static string SwitchOverNullableIntNullCaseCombined(int? i)
{ {
switch (i) { switch (i)
{
case null: case null:
case 0: case 0:
return "zero"; return "zero";
@ -177,7 +184,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static string SwitchOverNullableIntShifted(int? i) public static string SwitchOverNullableIntShifted(int? i)
{ {
switch (i + 5) { switch (i + 5)
{
case null: case null:
return "null"; return "null";
case 0: case 0:
@ -193,7 +201,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static string SwitchOverNullableIntShiftedNullCaseCombined(int? i) public static string SwitchOverNullableIntShiftedNullCaseCombined(int? i)
{ {
switch (i + 5) { switch (i + 5)
{
case null: case null:
case 0: case 0:
return "zero"; return "zero";
@ -208,7 +217,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static string SwitchOverNullableIntNoNullCase(int? i) public static string SwitchOverNullableIntNoNullCase(int? i)
{ {
switch (i) { switch (i)
{
case 0: case 0:
return "zero"; return "zero";
case 5: case 5:
@ -222,7 +232,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static string SwitchOverNullableIntNoNullCaseShifted(int? i) public static string SwitchOverNullableIntNoNullCaseShifted(int? i)
{ {
switch (i + 5) { switch (i + 5)
{
case 0: case 0:
return "zero"; return "zero";
case 5: case 5:
@ -236,7 +247,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static void SwitchOverInt(int i) public static void SwitchOverInt(int i)
{ {
switch (i) { switch (i)
{
case 0: case 0:
Console.WriteLine("zero"); Console.WriteLine("zero");
break; break;
@ -264,7 +276,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
// SwitchDetection.UseCSharpSwitch requires more complex heuristic to identify this when compiled with Roslyn // SwitchDetection.UseCSharpSwitch requires more complex heuristic to identify this when compiled with Roslyn
public static void CompactSwitchOverInt(int i) public static void CompactSwitchOverInt(int i)
{ {
switch (i) { switch (i)
{
case 0: case 0:
case 1: case 1:
case 2: case 2:
@ -283,7 +296,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static string ShortSwitchOverString(string text) public static string ShortSwitchOverString(string text)
{ {
Console.WriteLine("ShortSwitchOverString: " + text); Console.WriteLine("ShortSwitchOverString: " + text);
switch (text) { switch (text)
{
case "First case": case "First case":
return "Text1"; return "Text1";
case "Second case": case "Second case":
@ -298,7 +312,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static string ShortSwitchOverStringWithNullCase(string text) public static string ShortSwitchOverStringWithNullCase(string text)
{ {
Console.WriteLine("ShortSwitchOverStringWithNullCase: " + text); Console.WriteLine("ShortSwitchOverStringWithNullCase: " + text);
switch (text) { switch (text)
{
case "First case": case "First case":
return "Text1"; return "Text1";
case "Second case": case "Second case":
@ -313,7 +328,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static string SwitchOverString1(string text) public static string SwitchOverString1(string text)
{ {
Console.WriteLine("SwitchOverString1: " + text); Console.WriteLine("SwitchOverString1: " + text);
switch (text) { switch (text)
{
case "First case": case "First case":
return "Text1"; return "Text1";
case "Second case": case "Second case":
@ -337,7 +353,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static string SwitchOverString2() public static string SwitchOverString2()
{ {
Console.WriteLine("SwitchOverString2:"); Console.WriteLine("SwitchOverString2:");
switch (Environment.UserName) { switch (Environment.UserName)
{
case "First case": case "First case":
return "Text1"; return "Text1";
case "Second case": case "Second case":
@ -369,7 +386,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static string SwitchOverBool(bool b) public static string SwitchOverBool(bool b)
{ {
Console.WriteLine("SwitchOverBool: " + b); Console.WriteLine("SwitchOverBool: " + b);
switch (b) { switch (b)
{
case true: case true:
return bool.TrueString; return bool.TrueString;
case false: case false:
@ -383,8 +401,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static void SwitchInLoop(int i) public static void SwitchInLoop(int i)
{ {
Console.WriteLine("SwitchInLoop: " + i); Console.WriteLine("SwitchInLoop: " + i);
while (true) { while (true)
switch (i) { {
switch (i)
{
case 1: case 1:
Console.WriteLine("one"); Console.WriteLine("one");
break; break;
@ -409,7 +429,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static void SwitchWithGoto(int i) public static void SwitchWithGoto(int i)
{ {
Console.WriteLine("SwitchWithGoto: " + i); Console.WriteLine("SwitchWithGoto: " + i);
switch (i) { switch (i)
{
case 1: case 1:
Console.WriteLine("one"); Console.WriteLine("one");
goto default; goto default;
@ -433,7 +454,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static void SwitchWithGotoString(string s) public static void SwitchWithGotoString(string s)
{ {
Console.WriteLine("SwitchWithGotoString: " + s); Console.WriteLine("SwitchWithGotoString: " + s);
switch (s) { switch (s)
{
case "1": case "1":
Console.WriteLine("one"); Console.WriteLine("one");
goto default; goto default;
@ -471,7 +493,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static void SwitchWithGotoComplex(string s) public static void SwitchWithGotoComplex(string s)
{ {
Console.WriteLine("SwitchWithGotoComplex: " + s); Console.WriteLine("SwitchWithGotoComplex: " + s);
switch (s) { switch (s)
{
case "1": case "1":
Console.WriteLine("one"); Console.WriteLine("one");
goto case "8"; goto case "8";
@ -480,7 +503,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
goto case "3"; goto case "3";
case "3": case "3":
Console.WriteLine("three"); Console.WriteLine("three");
if (s.Length != 2) { if (s.Length != 2)
{
break; break;
} }
goto case "5"; goto case "5";
@ -518,10 +542,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
List<SetProperty> list = new List<SetProperty>(); List<SetProperty> list = new List<SetProperty>();
List<SetProperty> list2 = new List<SetProperty>(); List<SetProperty> list2 = new List<SetProperty>();
SetProperty[] properties = GetProperties(); SetProperty[] properties = GetProperties();
for (int i = 0; i < properties.Length; i++) { for (int i = 0; i < properties.Length; i++)
{
Console.WriteLine("In for-loop"); Console.WriteLine("In for-loop");
SetProperty setProperty = properties[i]; SetProperty setProperty = properties[i];
switch (setProperty.Property.Name) { switch (setProperty.Property.Name)
{
case "Name1": case "Name1":
setProperty.Set = 1; setProperty.Set = 1;
list.Add(setProperty); list.Add(setProperty);
@ -551,8 +577,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static void SwitchInTryBlock(string value) public static void SwitchInTryBlock(string value)
{ {
try { try
switch (value.Substring(5)) { {
switch (value.Substring(5))
{
case "Name1": case "Name1":
Console.WriteLine("1"); Console.WriteLine("1");
break; break;
@ -573,14 +601,17 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
Console.WriteLine("default"); Console.WriteLine("default");
break; break;
} }
} catch (Exception) { }
catch (Exception)
{
Console.WriteLine("catch block"); Console.WriteLine("catch block");
} }
} }
public static void SwitchWithComplexCondition(string[] args) public static void SwitchWithComplexCondition(string[] args)
{ {
switch ((args.Length == 0) ? "dummy" : args[0]) { switch ((args.Length == 0) ? "dummy" : args[0])
{
case "a": case "a":
Console.WriteLine("a"); Console.WriteLine("a");
break; break;
@ -599,7 +630,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static void SwitchWithArray(string[] args) public static void SwitchWithArray(string[] args)
{ {
switch (args[0]) { switch (args[0])
{
case "a": case "a":
Console.WriteLine("a"); Console.WriteLine("a");
break; break;
@ -618,19 +650,23 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static void SwitchWithContinue1(int i, bool b) public static void SwitchWithContinue1(int i, bool b)
{ {
while (true) { while (true)
switch (i) { {
switch (i)
{
#if OPT #if OPT
case 1: case 1:
continue; continue;
#endif #endif
case 0: case 0:
if (b) { if (b)
{
continue; continue;
} }
break; break;
case 2: case 2:
if (!b) { if (!b)
{
continue; continue;
} }
break; break;
@ -646,10 +682,13 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
// while condition, return and break cases // while condition, return and break cases
public static void SwitchWithContinue2(int i, bool b) public static void SwitchWithContinue2(int i, bool b)
{ {
while (i < 10) { while (i < 10)
switch (i) { {
switch (i)
{
case 0: case 0:
if (b) { if (b)
{
Console.WriteLine("0b"); Console.WriteLine("0b");
continue; continue;
} }
@ -657,14 +696,16 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
break; break;
case 2: case 2:
#if OPT #if OPT
if (b) { if (b)
{
Console.WriteLine("2b"); Console.WriteLine("2b");
return; return;
} }
Console.WriteLine("2!b"); Console.WriteLine("2!b");
continue; continue;
#else #else
if (!b) { if (!b)
{
Console.WriteLine("2!b"); Console.WriteLine("2!b");
continue; continue;
} }
@ -687,10 +728,13 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
// for loop version // for loop version
public static void SwitchWithContinue3(bool b) public static void SwitchWithContinue3(bool b)
{ {
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++)
switch (i) { {
switch (i)
{
case 0: case 0:
if (b) { if (b)
{
Console.WriteLine("0b"); Console.WriteLine("0b");
continue; continue;
} }
@ -698,14 +742,16 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
break; break;
case 2: case 2:
#if OPT #if OPT
if (b) { if (b)
{
Console.WriteLine("2b"); Console.WriteLine("2b");
return; return;
} }
Console.WriteLine("2!b"); Console.WriteLine("2!b");
continue; continue;
#else #else
if (!b) { if (!b)
{
Console.WriteLine("2!b"); Console.WriteLine("2!b");
continue; continue;
} }
@ -727,16 +773,20 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
// foreach version // foreach version
public static void SwitchWithContinue4(bool b) public static void SwitchWithContinue4(bool b)
{ {
foreach (int item in Enumerable.Range(0, 10)) { foreach (int item in Enumerable.Range(0, 10))
{
Console.WriteLine("loop: " + item); Console.WriteLine("loop: " + item);
switch (item) { switch (item)
{
case 1: case 1:
if (b) { if (b)
{
continue; continue;
} }
break; break;
case 3: case 3:
if (!b) { if (!b)
{
continue; continue;
} }
return; return;
@ -747,20 +797,24 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
Console.WriteLine(5); Console.WriteLine(5);
goto default; goto default;
case 6: case 6:
if (b) { if (b)
{
continue; continue;
} }
goto case 3; goto case 3;
case 7: case 7:
if (item % 2 == 0) { if (item % 2 == 0)
{
goto case 3; goto case 3;
} }
if (!b) { if (!b)
{
continue; continue;
} }
goto case 8; goto case 8;
case 8: case 8:
if (b) { if (b)
{
continue; continue;
} }
goto case 5; goto case 5;
@ -776,11 +830,15 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
// internal if statement, loop increment block not dominated by the switch head // internal if statement, loop increment block not dominated by the switch head
public static void SwitchWithContinue5(bool b) public static void SwitchWithContinue5(bool b)
{ {
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++)
if (i < 5) { {
switch (i) { if (i < 5)
{
switch (i)
{
case 0: case 0:
if (b) { if (b)
{
Console.WriteLine("0b"); Console.WriteLine("0b");
continue; continue;
} }
@ -788,14 +846,16 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
break; break;
case 2: case 2:
#if OPT #if OPT
if (b) { if (b)
{
Console.WriteLine("2b"); Console.WriteLine("2b");
return; return;
} }
Console.WriteLine("2!b"); Console.WriteLine("2!b");
continue; continue;
#else #else
if (!b) { if (!b)
{
Console.WriteLine("2!b"); Console.WriteLine("2!b");
continue; continue;
} }
@ -819,10 +879,13 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
// do-while loop version // do-while loop version
public static void SwitchWithContinue6(int i, bool b) public static void SwitchWithContinue6(int i, bool b)
{ {
do { do
switch (i) { {
switch (i)
{
case 0: case 0:
if (!b) { if (!b)
{
Console.WriteLine("0!b"); Console.WriteLine("0!b");
break; break;
} }
@ -830,7 +893,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
// ConditionDetection doesn't recognise Do-While continues yet // ConditionDetection doesn't recognise Do-While continues yet
continue; continue;
case 2: case 2:
if (b) { if (b)
{
Console.WriteLine("2b"); Console.WriteLine("2b");
return; return;
} }
@ -851,9 +915,11 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
// double break from switch to loop exit requires additional pattern matching in HighLevelLoopTransform // double break from switch to loop exit requires additional pattern matching in HighLevelLoopTransform
public static void SwitchWithContinue7() public static void SwitchWithContinue7()
{ {
for (int num = 0; num >= 0; num--) { for (int num = 0; num >= 0; num--)
{
Console.WriteLine("loop-head"); Console.WriteLine("loop-head");
switch (num) { switch (num)
{
default: default:
Console.WriteLine("default"); Console.WriteLine("default");
break; break;
@ -870,9 +936,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static void SwitchWithContinueInDoubleLoop() public static void SwitchWithContinueInDoubleLoop()
{ {
bool value = false; bool value = false;
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++)
for (int j = 0; j < 10; j++) { {
switch (i + j) { for (int j = 0; j < 10; j++)
{
switch (i + j)
{
case 1: case 1:
case 3: case 3:
case 5: case 5:
@ -893,8 +962,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static void SwitchLoopNesting() public static void SwitchLoopNesting()
{ {
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++)
switch (i) { {
switch (i)
{
case 0: case 0:
Console.WriteLine(0); Console.WriteLine(0);
break; break;
@ -902,8 +973,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
Console.WriteLine(1); Console.WriteLine(1);
break; break;
default: default:
if (i % 2 == 0) { if (i % 2 == 0)
while (i % 3 != 0) { {
while (i % 3 != 0)
{
Console.WriteLine(i++); Console.WriteLine(i++);
} }
} }
@ -911,9 +984,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
break; break;
} }
if (i > 4) { if (i > 4)
{
Console.WriteLine("high"); Console.WriteLine("high");
} else { }
else
{
Console.WriteLine("low"); Console.WriteLine("low");
} }
} }
@ -925,7 +1001,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
#if ROSLYN || OPT #if ROSLYN || OPT
public static void SingleIf1(int i, bool a) public static void SingleIf1(int i, bool a)
{ {
if (i == 1 || (i == 2 && a)) { if (i == 1 || (i == 2 && a))
{
Console.WriteLine(1); Console.WriteLine(1);
} }
Console.WriteLine(2); Console.WriteLine(2);
@ -934,7 +1011,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static void SingleIf2(int i, bool a, bool b) public static void SingleIf2(int i, bool a, bool b)
{ {
if (i == 1 || (i == 2 && a) || (i == 3 && b)) { if (i == 1 || (i == 2 && a) || (i == 3 && b))
{
Console.WriteLine(1); Console.WriteLine(1);
} }
Console.WriteLine(2); Console.WriteLine(2);
@ -942,7 +1020,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static void SingleIf3(int i, bool a, bool b) public static void SingleIf3(int i, bool a, bool b)
{ {
if (a || i == 1 || (i == 2 && b)) { if (a || i == 1 || (i == 2 && b))
{
Console.WriteLine(1); Console.WriteLine(1);
} }
Console.WriteLine(2); Console.WriteLine(2);
@ -950,7 +1029,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static void SingleIf4(int i, bool a) public static void SingleIf4(int i, bool a)
{ {
if (i == 1 || i == 2 || (i != 3 && a) || i != 4) { if (i == 1 || i == 2 || (i != 3 && a) || i != 4)
{
Console.WriteLine(1); Console.WriteLine(1);
} }
Console.WriteLine(2); Console.WriteLine(2);
@ -958,8 +1038,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static void NestedIf(int i) public static void NestedIf(int i)
{ {
if (i != 1) { if (i != 1)
if (i == 2) { {
if (i == 2)
{
Console.WriteLine(2); Console.WriteLine(2);
} }
Console.WriteLine("default"); Console.WriteLine("default");
@ -969,19 +1051,32 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static void IfChainWithCondition(int i) public static void IfChainWithCondition(int i)
{ {
if (i == 0) { if (i == 0)
{
Console.WriteLine(0); Console.WriteLine(0);
} else if (i == 1) { }
else if (i == 1)
{
Console.WriteLine(1); Console.WriteLine(1);
} else if (i == 2) { }
else if (i == 2)
{
Console.WriteLine(2); Console.WriteLine(2);
} else if (i == 3) { }
else if (i == 3)
{
Console.WriteLine(3); Console.WriteLine(3);
} else if (i == 4) { }
else if (i == 4)
{
Console.WriteLine(4); Console.WriteLine(4);
} else if (i == 5 && Console.CapsLock) { }
else if (i == 5 && Console.CapsLock)
{
Console.WriteLine("5A"); Console.WriteLine("5A");
} else { }
else
{
Console.WriteLine("default"); Console.WriteLine("default");
} }
@ -990,37 +1085,48 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static bool SwitchlikeIf(int i, int j) public static bool SwitchlikeIf(int i, int j)
{ {
if (i != 0 && j != 0) { if (i != 0 && j != 0)
if (i == -1 && j == -1) { {
if (i == -1 && j == -1)
{
Console.WriteLine("-1, -1"); Console.WriteLine("-1, -1");
} }
if (i == -1 && j == 1) { if (i == -1 && j == 1)
{
Console.WriteLine("-1, 1"); Console.WriteLine("-1, 1");
} }
if (i == 1 && j == -1) { if (i == 1 && j == -1)
{
Console.WriteLine("1, -1"); Console.WriteLine("1, -1");
} }
if (i == 1 && j == 1) { if (i == 1 && j == 1)
{
Console.WriteLine("1, 1"); Console.WriteLine("1, 1");
} }
return false; return false;
} }
if (i != 0) { if (i != 0)
if (i == -1) { {
if (i == -1)
{
Console.WriteLine("-1, 0"); Console.WriteLine("-1, 0");
} }
if (i == 1) { if (i == 1)
{
Console.WriteLine("1, 0"); Console.WriteLine("1, 0");
} }
return false; return false;
} }
if (j != 0) { if (j != 0)
if (j == -1) { {
if (j == -1)
{
Console.WriteLine("0, -1"); Console.WriteLine("0, -1");
} }
if (j == 1) { if (j == 1)
{
Console.WriteLine("0, 1"); Console.WriteLine("0, 1");
} }
return false; return false;
@ -1031,15 +1137,19 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static bool SwitchlikeIf2(int i) public static bool SwitchlikeIf2(int i)
{ {
if (i != 0) { if (i != 0)
{
// note that using else-if in this chain creates a nice-looking switch here (as expected) // note that using else-if in this chain creates a nice-looking switch here (as expected)
if (i == 1) { if (i == 1)
{
Console.WriteLine(1); Console.WriteLine(1);
} }
if (i == 2) { if (i == 2)
{
Console.WriteLine(2); Console.WriteLine(2);
} }
if (i == 3) { if (i == 3)
{
Console.WriteLine(3); Console.WriteLine(3);
} }
return false; return false;
@ -1049,7 +1159,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static void SingleIntervalIf(char c) public static void SingleIntervalIf(char c)
{ {
if (c >= 'A' && c <= 'Z') { if (c >= 'A' && c <= 'Z')
{
Console.WriteLine("alphabet"); Console.WriteLine("alphabet");
} }
Console.WriteLine("end"); Console.WriteLine("end");
@ -1057,8 +1168,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static bool Loop8(char c, bool b, Func<char> getChar) public static bool Loop8(char c, bool b, Func<char> getChar)
{ {
if (b) { if (b)
while ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) { {
while ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))
{
c = getChar(); c = getChar();
} }
} }
@ -1069,7 +1182,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static void Loop9(Func<char> getChar) public static void Loop9(Func<char> getChar)
{ {
char c; char c;
do { do
{
c = getChar(); c = getChar();
} while (c != -1 && c != '\n' && c != '\u2028' && c != '\u2029'); } while (c != -1 && c != '\n' && c != '\u2028' && c != '\u2029');
} }
@ -1078,8 +1192,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
// Ensure correctness of SwitchDetection.UseCSharpSwitch control flow heuristics // Ensure correctness of SwitchDetection.UseCSharpSwitch control flow heuristics
public static void SwitchWithBreakCase(int i, bool b) public static void SwitchWithBreakCase(int i, bool b)
{ {
if (b) { if (b)
switch (i) { {
switch (i)
{
case 1: case 1:
Console.WriteLine(1); Console.WriteLine(1);
break; break;
@ -1096,14 +1212,17 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static void SwitchWithReturnAndBreak(int i, bool b) public static void SwitchWithReturnAndBreak(int i, bool b)
{ {
switch (i) { switch (i)
{
case 0: case 0:
if (b) { if (b)
{
return; return;
} }
break; break;
case 1: case 1:
if (!b) { if (!b)
{
return; return;
} }
break; break;
@ -1113,13 +1232,15 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static int SwitchWithReturnAndBreak2(int i, bool b) public static int SwitchWithReturnAndBreak2(int i, bool b)
{ {
switch (i) { switch (i)
{
case 4: case 4:
case 33: case 33:
Console.WriteLine(); Console.WriteLine();
return 1; return 1;
case 334: case 334:
if (b) { if (b)
{
return 2; return 2;
} }
break; break;
@ -1135,7 +1256,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static void SwitchWithReturnAndBreak3(int i) public static void SwitchWithReturnAndBreak3(int i)
{ {
switch (i) { switch (i)
{
default: default:
return; return;
case 0: case 0:
@ -1150,10 +1272,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static string Issue1621(int x) public static string Issue1621(int x)
{ {
if (x == 5) { if (x == 5)
{
return "5"; return "5";
} }
switch (x) { switch (x)
{
case 1: case 1:
return "1"; return "1";
case 2: case 2:
@ -1173,7 +1297,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static int Issue1602(string x) public static int Issue1602(string x)
{ {
switch (x) { switch (x)
{
case null: case null:
return 0; return 0;
case "": case "":
@ -1197,7 +1322,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static void Issue1745(string aaa) public static void Issue1745(string aaa)
{ {
switch (aaa) { switch (aaa)
{
case "a": case "a":
case "b": case "b":
case "c": case "c":
@ -1218,7 +1344,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static bool DoNotRemoveAssignmentBeforeSwitch(string x, out ConsoleKey key) public static bool DoNotRemoveAssignmentBeforeSwitch(string x, out ConsoleKey key)
{ {
key = (ConsoleKey)0; key = (ConsoleKey)0;
switch (x) { switch (x)
{
case "A": case "A":
key = ConsoleKey.A; key = ConsoleKey.A;
break; break;
@ -1234,7 +1361,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static void Issue1767(string s) public static void Issue1767(string s)
{ {
switch (s) { switch (s)
{
case "a": case "a":
ch1767 = s[0]; ch1767 = s[0];
break; break;

21
ICSharpCode.Decompiler.Tests/TestCases/Pretty/SwitchExpressions.cs

@ -31,7 +31,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static bool? SwitchOverNullableEnum(State? state) public static bool? SwitchOverNullableEnum(State? state)
{ {
return state switch { return state switch
{
State.False => false, State.False => false,
State.True => true, State.True => true,
State.Null => null, State.Null => null,
@ -42,7 +43,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static string SparseIntegerSwitch(int i) public static string SparseIntegerSwitch(int i)
{ {
Console.WriteLine("SparseIntegerSwitch: " + i); Console.WriteLine("SparseIntegerSwitch: " + i);
return i switch { return i switch
{
-10000000 => "-10 mln", -10000000 => "-10 mln",
-100 => "-hundred", -100 => "-hundred",
-1 => "-1", -1 => "-1",
@ -61,7 +63,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static bool SparseIntegerSwitch3(int i) public static bool SparseIntegerSwitch3(int i)
{ {
// not using a switch expression because we'd have to duplicate the 'true' branch // not using a switch expression because we'd have to duplicate the 'true' branch
switch (i) { switch (i)
{
case 0: case 0:
case 10: case 10:
case 11: case 11:
@ -77,7 +80,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static string SwitchOverNullableInt(int? i, int? j) public static string SwitchOverNullableInt(int? i, int? j)
{ {
return (i + j) switch { return (i + j) switch
{
null => "null", null => "null",
0 => "zero", 0 => "zero",
5 => "five", 5 => "five",
@ -88,7 +92,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static void SwitchOverInt(int i) public static void SwitchOverInt(int i)
{ {
Console.WriteLine(i switch { Console.WriteLine(i switch
{
0 => "zero", 0 => "zero",
5 => "five", 5 => "five",
10 => "ten", 10 => "ten",
@ -103,7 +108,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static string SwitchOverString1(string text) public static string SwitchOverString1(string text)
{ {
Console.WriteLine("SwitchOverString1: " + text); Console.WriteLine("SwitchOverString1: " + text);
return text switch { return text switch
{
"First case" => "Text1", "First case" => "Text1",
"Second case" => "Text2", "Second case" => "Text2",
"Third case" => "Text3", "Third case" => "Text3",
@ -119,7 +125,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{ {
Console.WriteLine("SwitchOverString1: " + text); Console.WriteLine("SwitchOverString1: " + text);
// Cannot use switch expression, because "return Text2;" would need to be duplicated // Cannot use switch expression, because "return Text2;" would need to be duplicated
switch (text) { switch (text)
{
case "First case": case "First case":
return "Text1"; return "Text1";
case "Second case": case "Second case":

3
ICSharpCode.Decompiler.Tests/TestCases/Pretty/ThrowExpressions.cs

@ -32,7 +32,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
private static int? GetIntOrNull(string v) private static int? GetIntOrNull(string v)
{ {
if (int.TryParse(v, out int result)) { if (int.TryParse(v, out int result))
{
return result; return result;
} }

12
ICSharpCode.Decompiler.Tests/TestCases/Pretty/TupleTests.cs

@ -129,7 +129,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void UseDict() public void UseDict()
{ {
if (TupleDict.Count > 10) { if (TupleDict.Count > 10)
{
TupleDict.Clear(); TupleDict.Clear();
} }
// TODO: it would be nice if we could infer the name 'c' for the local // TODO: it would be nice if we could infer the name 'c' for the local
@ -153,21 +154,24 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void Foreach(IEnumerable<(int, string)> input) public void Foreach(IEnumerable<(int, string)> input)
{ {
foreach (var item in input) { foreach (var item in input)
{
Console.WriteLine($"{item.Item1}: {item.Item2}"); Console.WriteLine($"{item.Item1}: {item.Item2}");
} }
} }
public void ForeachNamedElements(IEnumerable<(int Index, string Data)> input) public void ForeachNamedElements(IEnumerable<(int Index, string Data)> input)
{ {
foreach (var item in input) { foreach (var item in input)
{
Console.WriteLine($"{item.Index}: {item.Data}"); Console.WriteLine($"{item.Index}: {item.Data}");
} }
} }
public void NonGenericForeach(IEnumerable input) public void NonGenericForeach(IEnumerable input)
{ {
foreach ((string, int) item in input) { foreach ((string, int) item in input)
{
Console.WriteLine($"{item.Item1}: {item.Item2}"); Console.WriteLine($"{item.Item1}: {item.Item2}");
} }
} }

3
ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.cs

@ -118,7 +118,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void TernaryOp(Random a, Random b, bool c) public void TernaryOp(Random a, Random b, bool c)
{ {
if ((c ? a : b) == null) { if ((c ? a : b) == null)
{
Console.WriteLine(); Console.WriteLine();
} }
} }

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

@ -201,7 +201,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
} }
} }
public interface T15_IMyInterface_PropertyInterfaceImplementation public interface T15_IMyInterface_PropertyInterfaceImplementation
{ {
int MyProperty { int MyProperty {
get; get;
set; set;

63
ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.cs

@ -170,7 +170,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public unsafe void PassRefParameterAsPointer(ref int p) public unsafe void PassRefParameterAsPointer(ref int p)
{ {
fixed (int* ptr = &p) { fixed (int* ptr = &p)
{
UsePointer(ptr); UsePointer(ptr);
} }
} }
@ -187,16 +188,19 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public unsafe void AddressInMultiDimensionalArray(double[,] matrix) public unsafe void AddressInMultiDimensionalArray(double[,] matrix)
{ {
fixed (double* d = &matrix[1, 2]) { fixed (double* d = &matrix[1, 2])
{
PointerReferenceExpression(d); PointerReferenceExpression(d);
PointerReferenceExpression(d); PointerReferenceExpression(d);
} }
} }
public unsafe void FixedStringAccess(string text) public unsafe void FixedStringAccess(string text)
{ {
fixed (char* ptr = text) { fixed (char* ptr = text)
for (char* ptr2 = ptr; *ptr2 == 'a'; ptr2++) { {
for (char* ptr2 = ptr; *ptr2 == 'a'; ptr2++)
{
*ptr2 = 'A'; *ptr2 = 'A';
} }
} }
@ -204,7 +208,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public unsafe void FixedStringNoPointerUse(string text) public unsafe void FixedStringNoPointerUse(string text)
{ {
fixed (char* ptr = text) { fixed (char* ptr = text)
{
} }
} }
@ -213,21 +218,24 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
// leaving no pinned region we could detect. // leaving no pinned region we could detect.
public unsafe void FixedArrayNoPointerUse(int[] arr) public unsafe void FixedArrayNoPointerUse(int[] arr)
{ {
fixed (int* ptr = arr) { fixed (int* ptr = arr)
{
} }
} }
#endif #endif
public unsafe void PutDoubleIntoLongArray1(long[] array, int index, double val) public unsafe void PutDoubleIntoLongArray1(long[] array, int index, double val)
{ {
fixed (long* ptr = array) { fixed (long* ptr = array)
{
*(double*)(ptr + index) = val; *(double*)(ptr + index) = val;
} }
} }
public unsafe void PutDoubleIntoLongArray2(long[] array, int index, double val) public unsafe void PutDoubleIntoLongArray2(long[] array, int index, double val)
{ {
fixed (long* ptr = &array[index]) { fixed (long* ptr = &array[index])
{
*(double*)ptr = val; *(double*)ptr = val;
} }
} }
@ -355,7 +363,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public unsafe void PinFixedMember(ref StructWithFixedSizeMembers m) public unsafe void PinFixedMember(ref StructWithFixedSizeMembers m)
{ {
fixed (int* ptr = m.Integers) { fixed (int* ptr = m.Integers)
{
UsePointer(ptr); UsePointer(ptr);
} }
} }
@ -376,7 +385,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public unsafe void FixedMultiDimArray(int[,] arr) public unsafe void FixedMultiDimArray(int[,] arr)
{ {
fixed (int* ptr = arr) { fixed (int* ptr = arr)
{
UsePointer(ptr); UsePointer(ptr);
} }
} }
@ -384,7 +394,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
#if CS73 #if CS73
public unsafe void FixedSpan(Span<int> span) public unsafe void FixedSpan(Span<int> span)
{ {
fixed (int* ptr = span) { fixed (int* ptr = span)
{
UsePointer(ptr); UsePointer(ptr);
} }
} }
@ -401,7 +412,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{ {
char* ptr = stackalloc char[count]; char* ptr = stackalloc char[count];
char* ptr2 = stackalloc char[100]; char* ptr2 = stackalloc char[100];
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++)
{
ptr[i] = (char)i; ptr[i] = (char)i;
ptr2[i] = '\0'; ptr2[i] = '\0';
} }
@ -417,7 +429,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
#endif #endif
ptr->X = count; ptr->X = count;
ptr[1].X = ptr->X; ptr[1].X = ptr->X;
for (int i = 2; i < 10; i++) { for (int i = 2; i < 10; i++)
{
ptr[i].X = count; ptr[i].X = count;
} }
return UsePointer(&ptr->Y); return UsePointer(&ptr->Y);
@ -450,13 +463,18 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
private unsafe static ResultStruct NestedFixedBlocks(byte[] array) private unsafe static ResultStruct NestedFixedBlocks(byte[] array)
{ {
try { try
fixed (byte* ptr = array) { {
fixed (byte* ptr2 = Get<byte[]>()) { fixed (byte* ptr = array)
{
fixed (byte* ptr2 = Get<byte[]>())
{
return new ResultStruct(ptr, ptr2); return new ResultStruct(ptr, ptr2);
} }
} }
} finally { }
finally
{
Console.WriteLine("Finally"); Console.WriteLine("Finally");
} }
} }
@ -468,17 +486,20 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
private unsafe static object Issue1386(int arraySize, bool createFirstBuffer) private unsafe static object Issue1386(int arraySize, bool createFirstBuffer)
{ {
if (createFirstBuffer) { if (createFirstBuffer)
{
byte[] array = new byte[arraySize]; byte[] array = new byte[arraySize];
Console.WriteLine("first fixed"); Console.WriteLine("first fixed");
fixed (byte* ptr = array) { fixed (byte* ptr = array)
{
return CreateBuffer(array.Length, ptr); return CreateBuffer(array.Length, ptr);
} }
} }
byte[] array2 = new byte[arraySize]; byte[] array2 = new byte[arraySize];
Console.WriteLine("second fixed"); Console.WriteLine("second fixed");
fixed (byte* ptr2 = array2) { fixed (byte* ptr2 = array2)
{
return CreateBuffer(array2.Length, ptr2); return CreateBuffer(array2.Length, ptr2);
} }
} }

36
ICSharpCode.Decompiler.Tests/TestCases/Pretty/Using.cs

@ -62,7 +62,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
// roslyn optimizes out the try-finally; mcs has a compiler bug on using(null-literal) // roslyn optimizes out the try-finally; mcs has a compiler bug on using(null-literal)
public void SimpleUsingNullStatement() public void SimpleUsingNullStatement()
{ {
using (null) { using (null)
{
Console.WriteLine("using (null)"); Console.WriteLine("using (null)");
} }
} }
@ -70,14 +71,16 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void SimpleUsingExpressionStatement() public void SimpleUsingExpressionStatement()
{ {
using (new MemoryStream()) { using (new MemoryStream())
{
Console.WriteLine("using-body"); Console.WriteLine("using-body");
} }
} }
public void SimpleUsingExpressionStatementWithDeclaration() public void SimpleUsingExpressionStatementWithDeclaration()
{ {
using (MemoryStream memoryStream = new MemoryStream()) { using (MemoryStream memoryStream = new MemoryStream())
{
memoryStream.WriteByte(42); memoryStream.WriteByte(42);
Console.WriteLine("using-body: " + memoryStream.Position); Console.WriteLine("using-body: " + memoryStream.Position);
} }
@ -86,7 +89,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void UsingStatementThatChangesTheVariable() public void UsingStatementThatChangesTheVariable()
{ {
CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(); CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
using (cancellationTokenSource) { using (cancellationTokenSource)
{
cancellationTokenSource = new CancellationTokenSource(); cancellationTokenSource = new CancellationTokenSource();
} }
cancellationTokenSource.Cancel(); cancellationTokenSource.Cancel();
@ -94,49 +98,56 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void UsingStatementOnStruct() public void UsingStatementOnStruct()
{ {
using (new UsingStruct(1)) { using (new UsingStruct(1))
{
Console.WriteLine("using-body"); Console.WriteLine("using-body");
} }
} }
public void UsingStatementOnStructWithVariable() public void UsingStatementOnStructWithVariable()
{ {
using (UsingStruct usingStruct = new UsingStruct(2)) { using (UsingStruct usingStruct = new UsingStruct(2))
{
Console.WriteLine("using-body: " + usingStruct); Console.WriteLine("using-body: " + usingStruct);
} }
} }
private void UsingStatementOnNullableStruct(UsingStruct? us) private void UsingStatementOnNullableStruct(UsingStruct? us)
{ {
using (us) { using (us)
{
Console.WriteLine("using-body: " + us.ToString()); Console.WriteLine("using-body: " + us.ToString());
} }
} }
public void GenericUsing<T>(T t) where T : IDisposable public void GenericUsing<T>(T t) where T : IDisposable
{ {
using (t) { using (t)
{
Console.WriteLine(t); Console.WriteLine(t);
} }
} }
public void GenericStructUsing<T>(T t) where T : struct, IDisposable public void GenericStructUsing<T>(T t) where T : struct, IDisposable
{ {
using (t) { using (t)
{
Console.WriteLine(t); Console.WriteLine(t);
} }
} }
public void GenericClassUsing<T>(T t) where T : class, IDisposable public void GenericClassUsing<T>(T t) where T : class, IDisposable
{ {
using (t) { using (t)
{
Console.WriteLine(t); Console.WriteLine(t);
} }
} }
public void GenericNullableUsing<T>(T? t) where T : struct, IDisposable public void GenericNullableUsing<T>(T? t) where T : struct, IDisposable
{ {
using (t) { using (t)
{
Console.WriteLine(t); Console.WriteLine(t);
} }
} }
@ -144,7 +155,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
#if CS80 #if CS80
public void UsingRefStruct1(UsingRefStruct s) public void UsingRefStruct1(UsingRefStruct s)
{ {
using (s) { using (s)
{
Console.WriteLine(s.i); Console.WriteLine(s.i);
} }
} }

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save