summaryrefslogtreecommitdiff
path: root/ICSharpCode.Decompiler/Tests
diff options
context:
space:
mode:
Diffstat (limited to 'ICSharpCode.Decompiler/Tests')
-rw-r--r--ICSharpCode.Decompiler/Tests/Async.cs155
-rw-r--r--ICSharpCode.Decompiler/Tests/BooleanConsumedAsInteger.il59
-rw-r--r--ICSharpCode.Decompiler/Tests/CallOverloadedMethod.cs52
-rw-r--r--ICSharpCode.Decompiler/Tests/CheckedUnchecked.cs117
-rw-r--r--ICSharpCode.Decompiler/Tests/CodeSampleFileParser.cs133
-rw-r--r--ICSharpCode.Decompiler/Tests/ControlFlow.cs97
-rw-r--r--ICSharpCode.Decompiler/Tests/CustomAttributes.code.cs41
-rw-r--r--ICSharpCode.Decompiler/Tests/CustomAttributes/CustomAttributeTests.cs30
-rw-r--r--ICSharpCode.Decompiler/Tests/CustomAttributes/S_AssemblyCustomAttribute.cs21
-rw-r--r--ICSharpCode.Decompiler/Tests/CustomAttributes/S_CustomAttributeSamples.cs508
-rw-r--r--ICSharpCode.Decompiler/Tests/CustomAttributes/S_CustomAttributes.cs79
-rw-r--r--ICSharpCode.Decompiler/Tests/CustomShortCircuitOperators.cs88
-rw-r--r--ICSharpCode.Decompiler/Tests/DecompilerTestBase.cs89
-rw-r--r--ICSharpCode.Decompiler/Tests/DelegateConstruction.cs205
-rw-r--r--ICSharpCode.Decompiler/Tests/DoubleConstants.cs28
-rw-r--r--ICSharpCode.Decompiler/Tests/ExceptionHandling.cs128
-rw-r--r--ICSharpCode.Decompiler/Tests/ExpressionTrees.cs370
-rw-r--r--ICSharpCode.Decompiler/Tests/Generics.cs165
-rw-r--r--ICSharpCode.Decompiler/Tests/Helpers/CodeAssert.cs110
-rw-r--r--ICSharpCode.Decompiler/Tests/Helpers/RemoveCompilerAttribute.cs38
-rw-r--r--ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj137
-rw-r--r--ICSharpCode.Decompiler/Tests/IL/ILTests.cs51
-rw-r--r--ICSharpCode.Decompiler/Tests/IL/SequenceOfNestedIfs.Output.cs53
-rw-r--r--ICSharpCode.Decompiler/Tests/IL/SequenceOfNestedIfs.il140
-rw-r--r--ICSharpCode.Decompiler/Tests/IL/StackTests.il132
-rw-r--r--ICSharpCode.Decompiler/Tests/IncrementDecrement.cs254
-rw-r--r--ICSharpCode.Decompiler/Tests/InitializerTests.cs885
-rw-r--r--ICSharpCode.Decompiler/Tests/LiftedOperators.cs830
-rw-r--r--ICSharpCode.Decompiler/Tests/Lock.cs38
-rw-r--r--ICSharpCode.Decompiler/Tests/Loops.cs74
-rw-r--r--ICSharpCode.Decompiler/Tests/MultidimensionalArray.cs58
-rw-r--r--ICSharpCode.Decompiler/Tests/PInvoke.cs96
-rw-r--r--ICSharpCode.Decompiler/Tests/PropertiesAndEvents.cs80
-rw-r--r--ICSharpCode.Decompiler/Tests/QueryExpressions.cs188
-rw-r--r--ICSharpCode.Decompiler/Tests/Switch.cs89
-rw-r--r--ICSharpCode.Decompiler/Tests/TestRunner.cs198
-rw-r--r--ICSharpCode.Decompiler/Tests/TypeAnalysisTests.cs153
-rw-r--r--ICSharpCode.Decompiler/Tests/Types/EnumTests.cs18
-rw-r--r--ICSharpCode.Decompiler/Tests/Types/S_EnumSamples.cs129
-rw-r--r--ICSharpCode.Decompiler/Tests/Types/S_TypeDeclarations.cs17
-rw-r--r--ICSharpCode.Decompiler/Tests/Types/S_TypeMemberDeclarations.cs1138
-rw-r--r--ICSharpCode.Decompiler/Tests/Types/TypeTests.cs18
-rw-r--r--ICSharpCode.Decompiler/Tests/UndocumentedExpressions.cs41
-rw-r--r--ICSharpCode.Decompiler/Tests/UnsafeCode.cs145
-rw-r--r--ICSharpCode.Decompiler/Tests/ValueTypes.cs188
-rw-r--r--ICSharpCode.Decompiler/Tests/YieldReturn.cs148
-rw-r--r--ICSharpCode.Decompiler/Tests/packages.config6
47 files changed, 7817 insertions, 0 deletions
diff --git a/ICSharpCode.Decompiler/Tests/Async.cs b/ICSharpCode.Decompiler/Tests/Async.cs
new file mode 100644
index 00000000..7629dd5e
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/Async.cs
@@ -0,0 +1,155 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+#pragma warning disable 1998
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Runtime.CompilerServices;
+using System.Threading.Tasks;
+
+public class Async
+{
+ public async void SimpleVoidMethod()
+ {
+ Console.WriteLine("Before");
+ await Task.Delay(TimeSpan.FromSeconds(1.0));
+ Console.WriteLine("After");
+ }
+
+ public async void VoidMethodWithoutAwait()
+ {
+ Console.WriteLine("No Await");
+ }
+
+ public async void AwaitYield()
+ {
+ await Task.Yield();
+ }
+
+ public async void AwaitDefaultYieldAwaitable()
+ {
+ await default(YieldAwaitable);
+ }
+
+ public async Task SimpleVoidTaskMethod()
+ {
+ Console.WriteLine("Before");
+ await Task.Delay(TimeSpan.FromSeconds(1.0));
+ Console.WriteLine("After");
+ }
+
+ public async Task TaskMethodWithoutAwait()
+ {
+ Console.WriteLine("No Await");
+ }
+
+ public async Task<bool> SimpleBoolTaskMethod()
+ {
+ Console.WriteLine("Before");
+ await Task.Delay(TimeSpan.FromSeconds(1.0));
+ Console.WriteLine("After");
+ return true;
+ }
+
+ public async void TwoAwaitsWithDifferentAwaiterTypes()
+ {
+ Console.WriteLine("Before");
+ if (await this.SimpleBoolTaskMethod())
+ {
+ await Task.Delay(TimeSpan.FromSeconds(1.0));
+ }
+ Console.WriteLine("After");
+ }
+
+ public async void StreamCopyTo(Stream destination, int bufferSize)
+ {
+ byte[] array = new byte[bufferSize];
+ int count;
+ while ((count = await destination.ReadAsync(array, 0, array.Length)) != 0)
+ {
+ await destination.WriteAsync(array, 0, count);
+ }
+ }
+
+ public async void StreamCopyToWithConfigureAwait(Stream destination, int bufferSize)
+ {
+ byte[] array = new byte[bufferSize];
+ int count;
+ while ((count = await destination.ReadAsync(array, 0, array.Length).ConfigureAwait(false)) != 0)
+ {
+ await destination.WriteAsync(array, 0, count).ConfigureAwait(false);
+ }
+ }
+
+ public async void AwaitInLoopCondition()
+ {
+ while (await this.SimpleBoolTaskMethod())
+ {
+ Console.WriteLine("Body");
+ }
+ }
+
+ public async Task<int> AwaitInForEach(IEnumerable<Task<int>> elements)
+ {
+ int num = 0;
+ foreach (Task<int> current in elements)
+ {
+ num += await current;
+ }
+ return num;
+ }
+
+ public async Task TaskMethodWithoutAwaitButWithExceptionHandling()
+ {
+ try
+ {
+ using (new StringWriter())
+ {
+ Console.WriteLine("No Await");
+ }
+ }
+ catch (Exception)
+ {
+ Console.WriteLine("Crash");
+ }
+ }
+
+ public async Task<int> NestedAwait(Task<Task<int>> task)
+ {
+ return await(await task);
+ }
+
+ public async Task AwaitWithStack(Task<int> task)
+ {
+ Console.WriteLine("A", 1, await task);
+ }
+
+ public async Task AwaitWithStack2(Task<int> task)
+ {
+ if (await this.SimpleBoolTaskMethod())
+ {
+ Console.WriteLine("A", 1, await task);
+ }
+ else
+ {
+ int num = 1;
+ Console.WriteLine("A", 1, num);
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/BooleanConsumedAsInteger.il b/ICSharpCode.Decompiler/Tests/BooleanConsumedAsInteger.il
new file mode 100644
index 00000000..9e300027
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/BooleanConsumedAsInteger.il
@@ -0,0 +1,59 @@
+.assembly extern mscorlib
+{
+ .publickeytoken = (B7 7A 5C 56 19 34 E0 89 )
+ .ver 4:0:0:0
+}
+.assembly BooleanConsumedAsInteger
+{
+ .hash algorithm 0x00008004
+ .ver 1:0:0:0
+}
+.module BooleanConsumedAsInteger.exe
+.imagebase 0x00400000
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003 // WINDOWS_CUI
+.corflags 0x00000003 // ILONLY 32BITREQUIRED
+
+.class private auto ansi beforefieldinit BooleanConsumedAsInteger.Program extends [mscorlib]System.Object
+{
+ .method public hidebysig static void Main(string[] args) cil managed
+ {
+ .entrypoint
+ .maxstack 8
+
+ ret
+ }
+
+ .method public hidebysig static int32 ReturnBoolAsInt() cil managed
+ {
+ ldnull
+ ldnull
+ call bool [mscorlib] System.Object::Equals(object, object)
+ ret
+ }
+
+ .method public hidebysig static int32 BitwiseOperationOnBool() cil managed
+ {
+ ldnull
+ ldnull
+ call bool [mscorlib] System.Object::Equals(object, object)
+ ldc.i4 255
+ and
+ ret
+ }
+
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ // Code size 7 (0x7)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [mscorlib]System.Object::.ctor()
+ IL_0006: ret
+ } // end of method Program::.ctor
+
+} // end of class StackTests.Program
+
+
+// =============================================================
diff --git a/ICSharpCode.Decompiler/Tests/CallOverloadedMethod.cs b/ICSharpCode.Decompiler/Tests/CallOverloadedMethod.cs
new file mode 100644
index 00000000..4f493ef2
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/CallOverloadedMethod.cs
@@ -0,0 +1,52 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+
+public class CallOverloadedMethod
+{
+ public void OverloadedMethod(object a)
+ {
+ }
+
+ public void OverloadedMethod(int? a)
+ {
+ }
+
+ public void OverloadedMethod(string a)
+ {
+ }
+
+ public void Call()
+ {
+ this.OverloadedMethod("(string)");
+ this.OverloadedMethod((object)"(object)");
+ this.OverloadedMethod(5);
+ this.OverloadedMethod((object)5);
+ this.OverloadedMethod(5L);
+ this.OverloadedMethod((object)null);
+ this.OverloadedMethod((string)null);
+ this.OverloadedMethod((int?)null);
+ }
+
+ public void CallMethodUsingInterface(List<int> list)
+ {
+ ((ICollection<int>)list).Clear();
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/CheckedUnchecked.cs b/ICSharpCode.Decompiler/Tests/CheckedUnchecked.cs
new file mode 100644
index 00000000..fd1c4d89
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/CheckedUnchecked.cs
@@ -0,0 +1,117 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+
+public class CheckedUnchecked
+{
+ public int Operators(int a, int b)
+ {
+ int num = checked(a + b);
+ int num2 = a + b;
+ int num3 = checked(a - b);
+ int num4 = a - b;
+ int num5 = checked(a * b);
+ int num6 = a * b;
+ int num7 = a / b;
+ int num8 = a % b;
+ // The division operators / and % only exist in one form (checked vs. unchecked doesn't matter for them)
+ return num * num2 * num3 * num4 * num5 * num6 * num7 * num8;
+ }
+
+ public int Cast(int a)
+ {
+ short num = checked((short)a);
+ short num2 = (short)a;
+ byte b = checked((byte)a);
+ byte b2 = (byte)a;
+ return num * num2 * b * b2;
+ }
+
+ public void ForWithCheckedIteratorAndUncheckedBody(int n)
+ {
+ checked
+ {
+ for (int i = n + 1; i < n + 1; i++)
+ {
+ n = unchecked(i * i);
+ }
+ }
+ }
+
+ public void ForWithCheckedInitializerAndUncheckedIterator(int n)
+ {
+ checked
+ {
+ int i = n;
+ for (i -= 10; i < n; i = unchecked(i + 1))
+ {
+ n--;
+ }
+ }
+ }
+ public void ObjectCreationInitializerChecked()
+ {
+ this.TestHelp(new
+ {
+ x = 0,
+ l = 0
+ }, n => checked(new
+ {
+ x = n.x + 1,
+ l = n.l + 1
+ }));
+ }
+
+ public void ObjectCreationWithOneFieldChecked()
+ {
+ this.TestHelp(new
+ {
+ x = 0,
+ l = 0
+ }, n => new
+ {
+ x = checked(n.x + 1),
+ l = n.l + 1
+ });
+ }
+
+
+ public void ArrayInitializerChecked()
+ {
+ this.TestHelp<int[]>(new int[]
+ {
+ 1,
+ 2
+ }, (int[] n) => checked(new int[]
+ {
+ n[0] + 1,
+ n[1] + 1
+ }));
+ }
+
+ public T TestHelp<T>(T t, Func<T, T> f)
+ {
+ return f(t);
+ }
+
+ public void CheckedInArrayCreationArgument(int a, int b)
+ {
+ Console.WriteLine(new int[checked(a + b)]);
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/CodeSampleFileParser.cs b/ICSharpCode.Decompiler/Tests/CodeSampleFileParser.cs
new file mode 100644
index 00000000..5cb49aad
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/CodeSampleFileParser.cs
@@ -0,0 +1,133 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.IO;
+
+namespace ICSharpCode.Decompiler.Tests
+{
+ static class CodeSampleFileParser
+ {
+ public static IEnumerable<string> ListSections(string s)
+ {
+ var query = from line in ToLines(s)
+ let sectionName = ReadSectionName(line)
+ where sectionName != null
+ select sectionName;
+ return query;
+ }
+
+ public static string GetSection(string sectionName, string s)
+ {
+ var lines = ToLines(s);
+
+ bool sectionFound = false;
+ var sectionText = new StringBuilder();
+
+ Action<string> parser = null;
+
+ Action<string> commonSectionReader = line =>
+ {
+ if (IsCommonSectionEnd(line))
+ parser = null;
+ else
+ sectionText.AppendLine(line);
+ };
+
+ Action<string> namedSectionReader = line =>
+ {
+ string name = ReadSectionName(line);
+ if (name == null)
+ sectionText.AppendLine(line);
+ else if (name != sectionName)
+ parser = null;
+ };
+
+ Action<string> defaultReader = line =>
+ {
+ if (IsCommonSectionStart(line))
+ parser = commonSectionReader;
+ else if (ReadSectionName(line) == sectionName)
+ {
+ parser = namedSectionReader;
+ sectionFound = true;
+ }
+ };
+
+ foreach(var line in lines)
+ {
+ (parser ?? defaultReader)(line);
+ }
+
+ if (sectionFound)
+ return sectionText.ToString();
+ else
+ return "";
+ }
+
+ public static bool IsCommentOrBlank(string s)
+ {
+ if(String.IsNullOrWhiteSpace(s))
+ return true;
+ s = s.Trim();
+ return s.StartsWith("//") || s.StartsWith("#"); // Also ignore #pragmas for warning suppression
+ }
+
+ public static string ConcatLines(IEnumerable<string> lines)
+ {
+ var buffer = new StringBuilder();
+ foreach (var line in lines)
+ {
+ buffer.AppendLine(line);
+ }
+ return buffer.ToString();
+ }
+
+ static string ReadSectionName(string line)
+ {
+ line = line.TrimStart();
+ if (line.StartsWith("//$$"))
+ return line.Substring(4).Trim();
+ else
+ return null;
+ }
+
+ static bool IsCommonSectionStart(string line)
+ {
+ return line.Trim() == "//$CS";
+ }
+
+ static bool IsCommonSectionEnd(string line)
+ {
+ return line.Trim() == "//$CE";
+ }
+
+ static IEnumerable<string> ToLines(string s)
+ {
+ var reader = new StringReader(s);
+ string line;
+ while ((line = reader.ReadLine()) != null)
+ {
+ yield return line;
+ }
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/ControlFlow.cs b/ICSharpCode.Decompiler/Tests/ControlFlow.cs
new file mode 100644
index 00000000..d83f04a2
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/ControlFlow.cs
@@ -0,0 +1,97 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+
+public static class ControlFlow
+{
+ public static void EmptyIf(string input, List<string> value, Dictionary<int, string> _headers)
+ {
+ if (value.Contains("test"))
+ {
+ }
+ _headers.Add(2, "result");
+ }
+
+ public static void NormalIf(string input, List<string> value, Dictionary<int, string> _headers)
+ {
+ if (value.Contains("test"))
+ {
+ _headers.Add(1, "result");
+ }
+ else
+ {
+ _headers.Add(1, "else");
+ }
+ _headers.Add(2, "end");
+ }
+
+ public static void NormalIf2(string input, List<string> value, Dictionary<int, string> _headers)
+ {
+ if (value.Contains("test"))
+ {
+ _headers.Add(1, "result");
+ }
+ _headers.Add(2, "end");
+ }
+
+ public static void NormalIf3(string input, List<string> value, Dictionary<int, string> _headers)
+ {
+ if (value.Contains("test"))
+ {
+ _headers.Add(1, "result");
+ }
+ else
+ {
+ _headers.Add(1, "else");
+ }
+ }
+
+ public static void Test(string input, List<string> value, Dictionary<int, string> _headers)
+ {
+ foreach (string current in value)
+ {
+ _headers.Add(0, current);
+ }
+ if (value.Contains("test"))
+ {
+ _headers.Add(1, "result");
+ }
+ else
+ {
+ _headers.Add(1, "else");
+ }
+ }
+
+ public static void CascadingIfElse(bool condition, string input, int index)
+ {
+ if (condition)
+ {
+ Console.WriteLine("condition");
+ }
+ else if (input == null)
+ {
+ Console.WriteLine("condition2");
+ }
+ else if (index > 1)
+ {
+ Console.WriteLine("condition3");
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/CustomAttributes.code.cs b/ICSharpCode.Decompiler/Tests/CustomAttributes.code.cs
new file mode 100644
index 00000000..4130b0b0
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/CustomAttributes.code.cs
@@ -0,0 +1,41 @@
+using System;
+namespace aa
+{
+ public static class CustomAtributes
+ {
+ [Flags]
+ public enum EnumWithFlag
+ {
+ All = 15,
+ None = 0,
+ Item1 = 1,
+ Item2 = 2,
+ Item3 = 4,
+ Item4 = 8
+ }
+ [AttributeUsage(AttributeTargets.All)]
+ public class MyAttribute : Attribute
+ {
+ public MyAttribute(CustomAtributes.EnumWithFlag en)
+ {
+ }
+ }
+ [CustomAtributes.MyAttribute(CustomAtributes.EnumWithFlag.Item1 | CustomAtributes.EnumWithFlag.Item2)]
+ private static int field;
+ [CustomAtributes.MyAttribute(CustomAtributes.EnumWithFlag.All)]
+ public static string Property
+ {
+ get
+ {
+ return "aa";
+ }
+ }
+ [Obsolete("some message")]
+ public static void ObsoletedMethod()
+ {
+ Console.WriteLine("{0} $$$ {1}", AttributeTargets.Interface, AttributeTargets.Property | AttributeTargets.Field);
+ AttributeTargets attributeTargets = AttributeTargets.Property | AttributeTargets.Field;
+ Console.WriteLine("{0} $$$ {1}", AttributeTargets.Interface, attributeTargets);
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/CustomAttributes/CustomAttributeTests.cs b/ICSharpCode.Decompiler/Tests/CustomAttributes/CustomAttributeTests.cs
new file mode 100644
index 00000000..892f33bf
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/CustomAttributes/CustomAttributeTests.cs
@@ -0,0 +1,30 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using NUnit.Framework;
+
+namespace ICSharpCode.Decompiler.Tests.CustomAttributes
+{
+ [TestFixture]
+ public class CustomAttributeTests : DecompilerTestBase
+ {
+ [Test]
+ public void CustomAttributeSamples()
+ {
+ ValidateFileRoundtrip(@"CustomAttributes\S_CustomAttributeSamples.cs");
+ }
+
+ [Test]
+ public void CustomAttributesMultiTest()
+ {
+ ValidateFileRoundtrip(@"CustomAttributes\S_CustomAttributes.cs");
+ }
+
+ [Test]
+ public void AssemblyCustomAttributesMultiTest()
+ {
+ ValidateFileRoundtrip(@"CustomAttributes\S_AssemblyCustomAttribute.cs");
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/CustomAttributes/S_AssemblyCustomAttribute.cs b/ICSharpCode.Decompiler/Tests/CustomAttributes/S_AssemblyCustomAttribute.cs
new file mode 100644
index 00000000..feaa04a6
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/CustomAttributes/S_AssemblyCustomAttribute.cs
@@ -0,0 +1,21 @@
+// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+
+[assembly: CLSCompliant(false)]
diff --git a/ICSharpCode.Decompiler/Tests/CustomAttributes/S_CustomAttributeSamples.cs b/ICSharpCode.Decompiler/Tests/CustomAttributes/S_CustomAttributeSamples.cs
new file mode 100644
index 00000000..7154b2c3
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/CustomAttributes/S_CustomAttributeSamples.cs
@@ -0,0 +1,508 @@
+// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+//$CS
+using System;
+//$CE
+
+//$$ TargetModule (ignored)
+//[module: CLSCompliantAttribute(false)]
+//$$ ParameterlessAttributeUsage
+namespace ParameterLessAttributeUsage
+{
+ [Flags]
+ public enum EnumWithFlagsAttribute
+ {
+ None = 0
+ }
+}
+//$$ AttributeWithEnumArgument
+namespace AttributeWithEnumArgument
+{
+ [AttributeUsage(AttributeTargets.All)]
+ public class MyAttributeAttribute : Attribute
+ {
+ }
+}
+//$$ AttributeWithEnumExpressionArgument
+namespace AttributeWithEnumExpressionArgument
+{
+ [AttributeUsage(AttributeTargets.Method | AttributeTargets.Interface)]
+ public class MyAttributeAttribute : Attribute
+ {
+ }
+}
+//$$ AttributeWithStringExpressionArgument
+namespace AttributeWithStringExpressionArgument
+{
+ [Obsolete("message")]
+ public class ObsoletedClass
+ {
+ }
+}
+//$$ AttributeWithTypeArgument
+namespace AttributeWithTypeArgument
+{
+ [AttributeUsage(AttributeTargets.All)]
+ public class MyTypeAttribute : Attribute
+ {
+ public MyTypeAttribute(Type t)
+ {
+ }
+ }
+
+ [MyType(typeof(Attribute))]
+ public class SomeClass
+ {
+ }
+}
+//$$ AppliedToEvent
+namespace AppliedToEvent
+{
+ [AttributeUsage(AttributeTargets.Event)]
+ public class MyAttributeAttribute : Attribute
+ {
+ }
+ public class TestClass
+ {
+ [MyAttribute]
+ public event EventHandler MyEvent;
+ }
+}
+//$$ AppliedToEventMethods
+namespace AppliedToEventMethods
+{
+ [AttributeUsage(AttributeTargets.Method)]
+ public class MyAttributeAttribute : Attribute
+ {
+ }
+ public class TestClass
+ {
+ [method: MyAttribute]
+ public event EventHandler MyEvent;
+ }
+}
+//$$ AppliedToField
+namespace AppliedToField
+{
+ [AttributeUsage(AttributeTargets.Field)]
+ public class MyAttributeAttribute : Attribute
+ {
+ }
+ public class TestClass
+ {
+ [MyAttribute]
+ public int Field;
+ }
+}
+//$$ AppliedToProperty
+namespace AppliedToProperty
+{
+ public class TestClass
+ {
+ [Obsolete("reason")]
+ public int Property
+ {
+ get
+ {
+ return 0;
+ }
+ }
+ }
+}
+//$$ AppliedToPropertyGet
+namespace AppliedToPropertyGet
+{
+ [AttributeUsage(AttributeTargets.All)]
+ public class MyAttributeAttribute : Attribute
+ {
+ }
+ public class TestClass
+ {
+ public int Property
+ {
+ [MyAttribute]
+ get
+ {
+ return 0;
+ }
+ }
+ }
+}
+//$$ AppliedToPropertySet
+namespace AppliedToPropertySet
+{
+ [AttributeUsage(AttributeTargets.All)]
+ public class MyAttributeAttribute : Attribute
+ {
+ }
+ public class TestClass
+ {
+ public int Property
+ {
+ get
+ {
+ return 3;
+ }
+ [MyAttribute]
+ set
+ {
+ }
+ }
+ }
+}
+//$$ AppliedToIndexer
+namespace AppliedToIndexer
+{
+ public class TestClass
+ {
+ [Obsolete("reason")]
+ public int this[int i]
+ {
+ get
+ {
+ return 0;
+ }
+ }
+ }
+}
+//$$ AppliedToDelegate
+[Obsolete("reason")]
+public delegate int AppliedToDelegate();
+//$$ AppliedToMethod
+namespace AppliedToMethod
+{
+ [AttributeUsage(AttributeTargets.Method)]
+ public class MyAttributeAttribute : Attribute
+ {
+ }
+ public class TestClass
+ {
+ [MyAttribute]
+ public void Method()
+ {
+ }
+ }
+}
+//$$ AppliedToInterface
+[Obsolete("reason")]
+public interface AppliedToInterface
+{
+}
+//$$ AppliedToStruct
+[Obsolete("reason")]
+public struct AppliedToStruct
+{
+ public int Field;
+}
+//$$ AppliedToParameter
+namespace AppliedToParameter
+{
+ [AttributeUsage(AttributeTargets.Parameter)]
+ public class MyAttributeAttribute : Attribute
+ {
+ }
+ public class MyClass
+ {
+ public void Method([MyAttribute] int val)
+ {
+ }
+ }
+}
+//$$ NamedInitializerProperty
+namespace NamedInitializerProperty
+{
+ [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
+ public class MyAttributeAttribute : Attribute
+ {
+ }
+}
+//$$ NamedInitializerPropertyString
+namespace NamedInitializerPropertyString
+{
+ [AttributeUsage(AttributeTargets.All)]
+ public class MyAttributeAttribute : Attribute
+ {
+ public string Prop
+ {
+ get
+ {
+ return "";
+ }
+ set
+ {
+ }
+ }
+ }
+ [MyAttribute(Prop = "value")]
+ public class MyClass
+ {
+ }
+}
+//$$ NamedInitializerPropertyType
+namespace NamedInitializerPropertyType
+{
+ [AttributeUsage(AttributeTargets.All)]
+ public class MyAttributeAttribute : Attribute
+ {
+ public Type Prop
+ {
+ get
+ {
+ return null;
+ }
+ set
+ {
+ }
+ }
+ }
+ [MyAttribute(Prop = typeof(Enum))]
+ public class MyClass
+ {
+ }
+}
+//$$ NamedInitializerPropertyEnum
+namespace NamedInitializerPropertyEnum
+{
+ [AttributeUsage(AttributeTargets.All)]
+ public class MyAttributeAttribute : Attribute
+ {
+ public AttributeTargets Prop
+ {
+ get
+ {
+ return AttributeTargets.All;
+ }
+ set
+ {
+ }
+ }
+ }
+ [MyAttribute(Prop = (AttributeTargets.Class | AttributeTargets.Method))]
+ public class MyClass
+ {
+ }
+}
+//$$ NamedInitializerFieldEnum
+namespace NamedInitializerFieldEnum
+{
+ [AttributeUsage(AttributeTargets.All)]
+ public class MyAttributeAttribute : Attribute
+ {
+ public AttributeTargets Field;
+ }
+ [MyAttribute(Field = (AttributeTargets.Class | AttributeTargets.Method))]
+ public class MyClass
+ {
+ }
+}
+//$$ TargetReturn
+namespace TargetReturn
+{
+ [AttributeUsage(AttributeTargets.All)]
+ public class MyAttributeAttribute : Attribute
+ {
+ }
+ public class MyClass
+ {
+ [return: MyAttribute]
+ public int MyMethod()
+ {
+ return 5;
+ }
+ }
+}
+//$$ TargetPropertyGetReturn
+namespace TargetPropertyGetReturn
+{
+ [AttributeUsage(AttributeTargets.All)]
+ public class MyAttributeAttribute : Attribute
+ {
+ }
+ public class MyClass
+ {
+ public int Prop
+ {
+ [return: MyAttribute]
+ get
+ {
+ return 3;
+ }
+ }
+ }
+}
+//$$ TargetPropertySetParam
+namespace TargetPropertySetParam
+{
+ [AttributeUsage(AttributeTargets.All)]
+ public class MyAttributeAttribute : Attribute
+ {
+ }
+ public class MyClass
+ {
+ public int Prop
+ {
+ [param: MyAttribute]
+ set
+ {
+ }
+ }
+ }
+}
+//$$ TargetPropertySetReturn
+namespace TargetPropertySetReturn
+{
+ [AttributeUsage(AttributeTargets.All)]
+ public class MyAttributeAttribute : Attribute
+ {
+ }
+ public class MyClass
+ {
+ public int Prop
+ {
+ get
+ {
+ return 3;
+ }
+ [return: MyAttribute]
+ set
+ {
+ }
+ }
+ }
+}
+//$$ TargetPropertyIndexGetReturn
+namespace TargetPropertyIndexGetReturn
+{
+ [AttributeUsage(AttributeTargets.All)]
+ public class MyAttributeAttribute : Attribute
+ {
+ }
+ public class MyClass
+ {
+ public int this[string s]
+ {
+ [return: MyAttribute]
+ get
+ {
+ return 3;
+ }
+ }
+ }
+}
+//$$ TargetPropertyIndexParamOnlySet
+namespace TargetPropertyIndexParamOnlySet
+{
+ [AttributeUsage(AttributeTargets.All)]
+ public class MyAttributeAttribute : Attribute
+ {
+ }
+ public class MyClass
+ {
+ public int this[[MyAttribute] string s]
+ {
+ set
+ {
+ }
+ }
+ }
+}
+//$$ TargetPropertyIndexParamOnlyGet
+namespace TargetPropertyIndexParamOnlyGet
+{
+ [AttributeUsage(AttributeTargets.All)]
+ public class MyAttributeAttribute : Attribute
+ {
+ }
+ public class MyClass
+ {
+ public int this[[MyAttribute] string s]
+ {
+ get
+ {
+ return 3;
+ }
+ }
+ }
+}
+//$$ TargetPropertyIndexSetReturn
+namespace TargetPropertyIndexSetReturn
+{
+ [AttributeUsage(AttributeTargets.All)]
+ public class MyAttributeAttribute : Attribute
+ {
+ }
+ public class MyClass
+ {
+ public string this[int index]
+ {
+ get
+ {
+ return "";
+ }
+ [return: MyAttribute]
+ set
+ {
+ }
+ }
+ }
+}
+//$$ TargetPropertyIndexSetMultiParam
+namespace TargetPropertyIndexSetMultiParam
+{
+ [AttributeUsage(AttributeTargets.All)]
+ public class MyAttributeAttribute : Attribute
+ {
+ public int Field;
+ }
+ public class MyClass
+ {
+ public string this[[MyAttribute(Field = 2)] int index1, [MyAttribute(Field = 3)] int index2]
+ {
+ get
+ {
+ return "";
+ }
+ [param: MyAttribute]
+ set
+ {
+ }
+ }
+ }
+}
+//$$ ClassAttributeOnTypeParameter
+namespace ClassAttributeOnTypeParameter
+{
+ [AttributeUsage(AttributeTargets.All)]
+ public class MyAttributeAttribute : Attribute
+ {
+ }
+ public class MyClass<[MyAttribute] T>
+ {
+ }
+}
+//$$ AttributeOnReturnTypeOfDelegate
+namespace AttributeOnReturnTypeOfDelegate
+{
+ [AttributeUsage(AttributeTargets.All)]
+ public class MyAttributeAttribute : Attribute
+ {
+ }
+ [return: MyAttribute]
+ public delegate void Test();
+}
diff --git a/ICSharpCode.Decompiler/Tests/CustomAttributes/S_CustomAttributes.cs b/ICSharpCode.Decompiler/Tests/CustomAttributes/S_CustomAttributes.cs
new file mode 100644
index 00000000..37c1c0d7
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/CustomAttributes/S_CustomAttributes.cs
@@ -0,0 +1,79 @@
+// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+
+namespace aa
+{
+ public static class CustomAttributes
+ {
+ [Flags]
+ public enum EnumWithFlag
+ {
+ All = 15,
+ None = 0,
+ Item1 = 1,
+ Item2 = 2,
+ Item3 = 4,
+ Item4 = 8
+ }
+ [AttributeUsage(AttributeTargets.All)]
+ public class MyAttribute : Attribute
+ {
+ public MyAttribute(object val)
+ {
+ }
+ }
+ [CustomAttributes.MyAttribute(CustomAttributes.EnumWithFlag.Item1 | CustomAttributes.EnumWithFlag.Item2)]
+ private static int field;
+ [CustomAttributes.MyAttribute(CustomAttributes.EnumWithFlag.All)]
+ public static string Property
+ {
+ get
+ {
+ return "aa";
+ }
+ }
+ [Obsolete("some message")]
+ public static void ObsoletedMethod()
+ {
+ //Console.WriteLine("{0} $$$ {1}", AttributeTargets.Interface, (AttributeTargets)(AttributeTargets.Property | AttributeTargets.Field));
+ Console.WriteLine("{0} $$$ {1}", AttributeTargets.Interface, AttributeTargets.Property | AttributeTargets.Field);
+ AttributeTargets attributeTargets = AttributeTargets.Property | AttributeTargets.Field;
+ Console.WriteLine("{0} $$$ {1}", AttributeTargets.Interface, attributeTargets);
+ }
+ // No Boxing
+ [CustomAttributes.MyAttribute(new StringComparison[]
+ {
+ StringComparison.Ordinal,
+ StringComparison.CurrentCulture
+ })]
+ public static void ArrayAsAttribute1()
+ {
+ }
+ // Boxing of each array element
+ [CustomAttributes.MyAttribute(new object[]
+ {
+ StringComparison.Ordinal,
+ StringComparison.CurrentCulture
+ })]
+ public static void ArrayAsAttribute2()
+ {
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/CustomShortCircuitOperators.cs b/ICSharpCode.Decompiler/Tests/CustomShortCircuitOperators.cs
new file mode 100644
index 00000000..5bd0ec51
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/CustomShortCircuitOperators.cs
@@ -0,0 +1,88 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+
+public static class CustomShortCircuitOperators
+{
+ // TODO: Restore base class after https://roslyn.codeplex.com/workitem/358 is fixed.
+ private class C
+ {
+ public static bool operator true(CustomShortCircuitOperators.C x)
+ {
+ return true;
+ }
+
+ public static bool operator false(CustomShortCircuitOperators.C x)
+ {
+ return false;
+ }
+
+ public static CustomShortCircuitOperators.C operator &(CustomShortCircuitOperators.C x, CustomShortCircuitOperators.C y)
+ {
+ return null;
+ }
+
+ public static CustomShortCircuitOperators.C operator |(CustomShortCircuitOperators.C x, CustomShortCircuitOperators.C y)
+ {
+ return null;
+ }
+
+ public static bool operator !(CustomShortCircuitOperators.C x)
+ {
+ return false;
+ }
+
+ private static void Main()
+ {
+ CustomShortCircuitOperators.C c = new CustomShortCircuitOperators.C();
+ CustomShortCircuitOperators.C c2 = new CustomShortCircuitOperators.C();
+ CustomShortCircuitOperators.C c3 = c && c2;
+ CustomShortCircuitOperators.C c4 = c || c2;
+ Console.WriteLine(c3.ToString());
+ Console.WriteLine(c4.ToString());
+ }
+
+ private static void Test2()
+ {
+ CustomShortCircuitOperators.C c = new CustomShortCircuitOperators.C();
+ if (c && c)
+ {
+ Console.WriteLine(c.ToString());
+ }
+
+ if (!(c && c))
+ {
+ Console.WriteLine(c.ToString());
+ }
+ }
+
+ private static void Test3()
+ {
+ CustomShortCircuitOperators.C c = new CustomShortCircuitOperators.C();
+ if (c)
+ {
+ Console.WriteLine(c.ToString());
+ }
+ if (!c)
+ {
+ Console.WriteLine(c.ToString());
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/ICSharpCode.Decompiler/Tests/DecompilerTestBase.cs b/ICSharpCode.Decompiler/Tests/DecompilerTestBase.cs
new file mode 100644
index 00000000..659bb2be
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/DecompilerTestBase.cs
@@ -0,0 +1,89 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.CodeDom.Compiler;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+
+using ICSharpCode.Decompiler.Ast;
+using ICSharpCode.Decompiler.Tests.Helpers;
+using Microsoft.CSharp;
+using Mono.Cecil;
+using NUnit.Framework;
+
+namespace ICSharpCode.Decompiler.Tests
+{
+ public abstract class DecompilerTestBase
+ {
+ protected static void ValidateFileRoundtrip(string samplesFileName)
+ {
+ var fullPath = Path.Combine(@"..\..\Tests", samplesFileName);
+ AssertRoundtripCode(fullPath);
+ }
+
+ static string RemoveIgnorableLines(IEnumerable<string> lines)
+ {
+ return CodeSampleFileParser.ConcatLines(lines.Where(l => !CodeSampleFileParser.IsCommentOrBlank(l)));
+ }
+
+ protected static void AssertRoundtripCode(string fileName, bool optimize = false, bool useDebug = false, int compilerVersion = 4)
+ {
+ var code = RemoveIgnorableLines(File.ReadLines(fileName));
+ AssemblyDefinition assembly = CompileLegacy(code, optimize, useDebug, compilerVersion);
+
+ AstBuilder decompiler = new AstBuilder(new DecompilerContext(assembly.MainModule));
+ decompiler.AddAssembly(assembly);
+ new Helpers.RemoveCompilerAttribute().Run(decompiler.SyntaxTree);
+
+ StringWriter output = new StringWriter();
+ decompiler.GenerateCode(new PlainTextOutput(output));
+ CodeAssert.AreEqual(code, output.ToString());
+ }
+
+ protected static AssemblyDefinition CompileLegacy(string code, bool optimize, bool useDebug, int compilerVersion)
+ {
+ CSharpCodeProvider provider = new CSharpCodeProvider(new Dictionary<string, string> { { "CompilerVersion", "v" + new Version(compilerVersion, 0) } });
+ CompilerParameters options = new CompilerParameters();
+ options.CompilerOptions = "/unsafe /o" + (optimize ? "+" : "-") + (useDebug ? " /debug" : "");
+ if (compilerVersion >= 4)
+ options.ReferencedAssemblies.Add("System.Core.dll");
+ CompilerResults results = provider.CompileAssemblyFromSource(options, code);
+ try
+ {
+ if (results.Errors.Count > 0)
+ {
+ StringBuilder b = new StringBuilder("Compiler error:");
+ foreach (var error in results.Errors)
+ {
+ b.AppendLine(error.ToString());
+ }
+ throw new Exception(b.ToString());
+ }
+ return AssemblyDefinition.ReadAssembly(results.PathToAssembly);
+ }
+ finally
+ {
+ File.Delete(results.PathToAssembly);
+ results.TempFiles.Delete();
+ }
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/DelegateConstruction.cs b/ICSharpCode.Decompiler/Tests/DelegateConstruction.cs
new file mode 100644
index 00000000..70c00fc6
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/DelegateConstruction.cs
@@ -0,0 +1,205 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+public static class DelegateConstruction
+{
+ class InstanceTests
+ {
+ public Action CaptureOfThis()
+ {
+ return delegate {
+ CaptureOfThis();
+ };
+ }
+
+ public Action CaptureOfThisAndParameter(int a)
+ {
+ return delegate {
+ CaptureOfThisAndParameter(a);
+ };
+ }
+
+ public Action CaptureOfThisAndParameterInForEach(int a)
+ {
+ foreach (int item in Enumerable.Empty<int>()) {
+ if (item > 0) {
+ return delegate {
+ CaptureOfThisAndParameter(item + a);
+ };
+ }
+ }
+ return null;
+ }
+
+ public Action CaptureOfThisAndParameterInForEachWithItemCopy(int a)
+ {
+ foreach (int item in Enumerable.Empty<int>()) {
+ int copyOfItem = item;
+ if (item > 0) {
+ return delegate {
+ CaptureOfThisAndParameter(item + a + copyOfItem);
+ };
+ }
+ }
+ return null;
+ }
+
+ public void LambdaInForLoop()
+ {
+ for (int i = 0; i < 100000; i++) {
+ Bar(() => Foo());
+ }
+ }
+
+ public int Foo()
+ {
+ return 0;
+ }
+
+ public void Bar(Func<int> f)
+ {
+ }
+ }
+
+ public static void Test(this string a)
+ {
+ }
+
+ public static Action<string> ExtensionMethodUnbound()
+ {
+ return new Action<string>(DelegateConstruction.Test);
+ }
+
+ public static Action ExtensionMethodBound()
+ {
+ return new Action("abc".Test);
+ }
+
+ public static Action ExtensionMethodBoundOnNull()
+ {
+ return new Action(((string)null).Test);
+ }
+
+ public static object StaticMethod()
+ {
+ return new Func<Action>(DelegateConstruction.ExtensionMethodBound);
+ }
+
+ public static object InstanceMethod()
+ {
+ return new Func<string>("hello".ToUpper);
+ }
+
+ public static object InstanceMethodOnNull()
+ {
+ return new Func<string>(((string)null).ToUpper);
+ }
+
+ public static List<Action<int>> AnonymousMethodStoreWithinLoop()
+ {
+ List<Action<int>> list = new List<Action<int>>();
+ for (int i = 0; i < 10; i++)
+ {
+ int counter;
+ list.Add(delegate(int x)
+ {
+ counter = x;
+ }
+ );
+ }
+ return list;
+ }
+
+ public static List<Action<int>> AnonymousMethodStoreOutsideLoop()
+ {
+ List<Action<int>> list = new List<Action<int>>();
+ int counter;
+ for (int i = 0; i < 10; i++)
+ {
+ list.Add(delegate(int x)
+ {
+ counter = x;
+ }
+ );
+ }
+ return list;
+ }
+
+ public static Action StaticAnonymousMethodNoClosure()
+ {
+ return delegate
+ {
+ Console.WriteLine();
+ };
+ }
+
+ public static void NameConflict()
+ {
+ // i is captured variable,
+ // j is parameter in anonymous method
+ // k is local in anonymous method,
+ // l is local in main method
+ // Ensure that the decompiler doesn't introduce name conflicts
+ List<Action<int>> list = new List<Action<int>>();
+ for (int l = 0; l < 10; l++) {
+ int i;
+ for (i = 0; i < 10; i++) {
+ list.Add(
+ delegate (int j) {
+ for (int k = 0; k < i; k += j) {
+ Console.WriteLine();
+ }
+ });
+ }
+ }
+ }
+
+ public static void NameConflict2(int j)
+ {
+ List<Action<int>> list = new List<Action<int>>();
+ for (int k = 0; k < 10; k++) {
+ list.Add(
+ delegate(int i) {
+ Console.WriteLine(i);
+ });
+ }
+ }
+
+ public static Action<int> NameConflict3(int i)
+ {
+ return delegate(int j) {
+ for (int k = 0; k < j; k++) {
+ Console.WriteLine(k);
+ }
+ };
+ }
+
+ public static Func<int, Func<int, int>> CurriedAddition(int a)
+ {
+ return b => c => a + b + c;
+ }
+
+ public static Func<int, Func<int, Func<int, int>>> CurriedAddition2(int a)
+ {
+ return b => c => d => a + b + c + d;
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/DoubleConstants.cs b/ICSharpCode.Decompiler/Tests/DoubleConstants.cs
new file mode 100644
index 00000000..2bc20a77
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/DoubleConstants.cs
@@ -0,0 +1,28 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+
+public class DoubleConstants
+{
+ public const double Zero = 0.0;
+ public const double MinusZero = -0.0;
+ public const double NaN = double.NaN;
+ public const double PositiveInfinity = double.PositiveInfinity;
+ public const double NegativeInfinity = double.NegativeInfinity;
+}
diff --git a/ICSharpCode.Decompiler/Tests/ExceptionHandling.cs b/ICSharpCode.Decompiler/Tests/ExceptionHandling.cs
new file mode 100644
index 00000000..0db35e35
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/ExceptionHandling.cs
@@ -0,0 +1,128 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Threading;
+
+public class ExceptionHandling
+{
+ public void MethodEndingWithEndFinally()
+ {
+ try
+ {
+ throw null;
+ }
+ finally
+ {
+ Console.WriteLine();
+ }
+ }
+
+ public void MethodEndingWithRethrow()
+ {
+ try
+ {
+ throw null;
+ }
+ catch
+ {
+ throw;
+ }
+ }
+
+ public void TryCatchFinally()
+ {
+ try
+ {
+ Console.WriteLine("Try");
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine(ex.Message);
+ }
+ finally
+ {
+ Console.WriteLine("Finally");
+ }
+ }
+
+ public void TryCatchMultipleHandlers()
+ {
+ try
+ {
+ Console.WriteLine("Try");
+ }
+ catch (InvalidOperationException ex)
+ {
+ Console.WriteLine(ex.Message);
+ }
+ catch (Exception ex2)
+ {
+ Console.WriteLine(ex2.Message);
+ }
+ catch
+ {
+ Console.WriteLine("other");
+ }
+ }
+
+ public void NoUsingStatementBecauseTheVariableIsAssignedTo()
+ {
+ CancellationTokenSource cancellationTokenSource = null;
+ try
+ {
+ cancellationTokenSource = new CancellationTokenSource();
+ }
+ finally
+ {
+ if (cancellationTokenSource != null)
+ {
+ cancellationTokenSource.Dispose();
+ }
+ }
+ }
+
+ public void UsingStatementThatChangesTheVariable()
+ {
+ CancellationTokenSource cancellationTokenSource = null;
+ using (cancellationTokenSource)
+ {
+ cancellationTokenSource = new CancellationTokenSource();
+ }
+ }
+
+ public void TwoCatchBlocksWithSameVariable()
+ {
+ try
+ {
+ Console.WriteLine("Try1");
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine(ex.Message);
+ }
+ try
+ {
+ Console.WriteLine("Try2");
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine(ex.Message);
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/ExpressionTrees.cs b/ICSharpCode.Decompiler/Tests/ExpressionTrees.cs
new file mode 100644
index 00000000..9d325e9e
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/ExpressionTrees.cs
@@ -0,0 +1,370 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Xml;
+
+public class ExpressionTrees
+{
+ class GenericClass<X>
+ {
+ public static X StaticField;
+ public X InstanceField;
+ public static X StaticProperty { get; set; }
+ public X InstanceProperty { get; set; }
+
+ public static bool GenericMethod<Y>()
+ {
+ return false;
+ }
+ }
+
+ int field;
+
+ static object ToCode<R>(object x, Expression<Func<R>> expr)
+ {
+ return expr;
+ }
+
+ static object ToCode<T, R>(object x, Expression<Func<T, R>> expr)
+ {
+ return expr;
+ }
+
+ static object X()
+ {
+ return null;
+ }
+
+ public void Parameter(bool a)
+ {
+ ToCode(X(), () => a);
+ }
+
+ public void LocalVariable()
+ {
+ bool a = true;
+ ToCode(X(), () => a);
+ }
+
+ public void LambdaParameter()
+ {
+ ToCode(X(), (bool a) => a);
+ }
+
+ public void AddOperator(int x)
+ {
+ ToCode(X(), () => 1 + x + 2);
+ }
+
+ public void AnonymousClasses()
+ {
+ ToCode(X(), () => new { X = 3, A = "a" });
+ }
+
+ public void ArrayIndex()
+ {
+ ToCode(X(), () => new[] { 3, 4, 5 }[0 + (int)(DateTime.Now.Ticks % 3)]);
+ }
+
+ public void ArrayLengthAndDoubles()
+ {
+ ToCode(X(), () => new[] { 1.0, 2.01, 3.5 }.Concat(new[] { 1.0, 2.0 }).ToArray().Length);
+ }
+
+ public void AsOperator()
+ {
+ ToCode(X(), () => new object() as string);
+ }
+
+ public void ComplexGenericName()
+ {
+ ToCode(X(), () => ((Func<int, bool>)(x => x > 0))(0));
+ }
+
+ public void DefaultValue()
+ {
+ ToCode(X(), () => new TimeSpan(1, 2, 3) == default(TimeSpan));
+ }
+
+ public void EnumConstant()
+ {
+ ToCode(X(), () => new object().Equals(MidpointRounding.ToEven));
+ }
+
+ public void IndexerAccess()
+ {
+ var dict = Enumerable.Range(1, 20).ToDictionary(n => n.ToString());
+ ToCode(X(), () => dict["3"] == 3);
+ }
+
+ public void IsOperator()
+ {
+ ToCode(X(), () => new object() is string);
+ }
+
+ public void ListInitializer()
+ {
+ ToCode(X(), () => new Dictionary<int, int> { { 1, 1 }, { 2, 2 }, { 3, 4 } }.Count == 3);
+ }
+
+ public void ListInitializer2()
+ {
+ ToCode(X(), () => new List<int>(50) { 1, 2, 3 }.Count == 3);
+ }
+
+ public void ListInitializer3()
+ {
+ ToCode(X(), () => new List<int> { 1, 2, 3 }.Count == 3);
+ }
+
+ public void LiteralCharAndProperty()
+ {
+ ToCode(X(), () => new string(' ', 3).Length == 1);
+ }
+
+ public void CharNoCast()
+ {
+ ToCode(X(), () => "abc"[1] == 'b');
+ }
+
+ public void StringsImplicitCast()
+ {
+ int i = 1;
+ string x = "X";
+ ToCode(X(), () => (("a\n\\b" ?? x) + x).Length == 2 ? false : true && (1m + -i > 0 || false));
+ }
+
+ public void NotImplicitCast()
+ {
+ byte z = 42;
+ ToCode(X(), () => ~z == 0);
+ }
+
+ public void MembersBuiltin()
+ {
+ ToCode(X(), () => 1.23m.ToString());
+ ToCode(X(), () => AttributeTargets.All.HasFlag((Enum)AttributeTargets.Assembly));
+ ToCode(X(), () => "abc".Length == 3);
+ ToCode(X(), () => 'a'.CompareTo('b') < 0);
+ }
+
+ public void MembersDefault()
+ {
+ ToCode(X(), () => default(DateTime).Ticks == 0);
+ ToCode(X(), () => default(int[]).Length == 0);
+ ToCode(X(), () => default(Type).IsLayoutSequential);
+ ToCode(X(), () => default(List<int>).Count);
+ ToCode(X(), () => default(int[]).Clone() == null);
+ ToCode(X(), () => default(Type).IsInstanceOfType(new object()));
+ ToCode(X(), () => default(List<int>).AsReadOnly());
+ }
+
+ public void DoAssert()
+ {
+ field = 37;
+ ToCode(X(), () => field != C());
+ ToCode(X(), () => !ReferenceEquals(this, new ExpressionTrees()));
+ ToCode(X(), () => MyEquals(this) && !MyEquals(default(ExpressionTrees)));
+ }
+
+ int C()
+ {
+ return field + 5;
+ }
+
+ bool MyEquals(ExpressionTrees other)
+ {
+ return other != null && field == other.field;
+ }
+
+ public void MethodGroupAsExtensionMethod()
+ {
+ ToCode(X(), () => (Func<bool>)new[] { 2000, 2004, 2008, 2012 }.Any);
+ }
+
+ public void MethodGroupConstant()
+ {
+ ToCode(X(), () => Array.TrueForAll(new[] { 2000, 2004, 2008, 2012 }, DateTime.IsLeapYear));
+
+ HashSet<int> set = new HashSet<int>();
+ ToCode(X(), () => new[] { 2000, 2004, 2008, 2012 }.All(set.Add));
+
+ Func<Func<object, object, bool>, bool> sink = f => f(null, null);
+ ToCode(X(), () => sink(int.Equals));
+ }
+
+ public void MultipleCasts()
+ {
+ ToCode(X(), () => 1 == (int)(object)1);
+ }
+
+ public void MultipleDots()
+ {
+ ToCode(X(), () => 3.ToString().ToString().Length > 0);
+ }
+
+ public void NestedLambda()
+ {
+ Func<Func<int>, int> call = f => f();
+ //no params
+ ToCode(X(), () => call(() => 42));
+ //one param
+ ToCode(X(), () => new[] { 37, 42 }.Select(x => x * 2));
+ //two params
+ ToCode(X(), () => new[] { 37, 42 }.Select((x, i) => x * 2));
+ }
+
+ public void CurriedLambda()
+ {
+ ToCode<int, Func<int, Func<int, int>>>(X(), a => b => c => a + b + c);
+ }
+
+ bool Fizz(Func<int, bool> a)
+ {
+ return a(42);
+ }
+
+ bool Buzz(Func<int, bool> a)
+ {
+ return a(42);
+ }
+
+ bool Fizz(Func<string, bool> a)
+ {
+ return a("42");
+ }
+
+ public void NestedLambda2()
+ {
+ ToCode(X(), () => Fizz(x => x == "a"));
+ ToCode(X(), () => Fizz(x => x == 37));
+
+ ToCode(X(), () => Fizz((int x) => true));
+ ToCode(X(), () => Buzz(x => true));
+ }
+
+ public void NewArrayAndExtensionMethod()
+ {
+ ToCode(X(), () => new[] { 1.0, 2.01, 3.5 }.SequenceEqual(new[] { 1.0, 2.01, 3.5 }));
+ }
+
+ public void NewMultiDimArray()
+ {
+ ToCode(X(), () => new int[3, 4].Length == 1);
+ }
+
+ public void NewObject()
+ {
+ ToCode(X(), () => new object() != new object());
+ }
+
+ public void NotOperator()
+ {
+ bool x = true;
+ int y = 3;
+ byte z = 42;
+ ToCode(X(), () => ~(int)z == 0);
+ ToCode(X(), () => ~y == 0);
+ ToCode(X(), () => !x);
+ }
+
+ public void ObjectInitializers()
+ {
+ XmlReaderSettings s = new XmlReaderSettings {
+ CloseInput = false,
+ CheckCharacters = false
+ };
+ ToCode(X(), () => new XmlReaderSettings { CloseInput = s.CloseInput, CheckCharacters = s.CheckCharacters }.Equals(s));
+ }
+
+ public void Quoted()
+ {
+ ToCode(X(), () => (Expression<Func<int, string, string>>)((n, s) => s + n.ToString()) != null);
+ }
+
+ public void Quoted2()
+ {
+ ToCode(X(), () => ToCode(X(), () => true).Equals(null));
+ }
+
+ public void QuotedWithAnonymous()
+ {
+ ToCode(X(), () => new[] { new { X = "a", Y = "b" } }.Select(o => o.X + o.Y).Single());
+ }
+
+ public void StaticCall()
+ {
+ ToCode(X(), () => Equals(3, 0));
+ }
+
+ public void ThisCall()
+ {
+ ToCode(X(), () => !Equals(3));
+ }
+
+ public void ThisExplicit()
+ {
+ ToCode(X(), () => object.Equals(this, 3));
+ }
+
+ public void TypedConstant()
+ {
+ ToCode(X(), () => new[] { typeof(int), typeof(string) });
+ }
+
+ public void StaticCallImplicitCast()
+ {
+ ToCode(X(), () => Equals(3, 0));
+ }
+
+ public void StaticMembers()
+ {
+ ToCode(X(), () => (DateTime.Now > DateTime.Now + TimeSpan.FromMilliseconds(10.001)).ToString() == "False");
+ }
+
+ public void Strings()
+ {
+ int i = 1;
+ string x = "X";
+ ToCode(X(), () => (("a\n\\b" ?? x) + x).Length == 2 ? false : true && (1m + (decimal)-i > 0m || false));
+ }
+
+ public void StringAccessor()
+ {
+ ToCode(X(), () => (int)"abc"[1] == 98);
+ }
+
+ public void GenericClassInstance()
+ {
+ ToCode(X(), () => new GenericClass<int>().InstanceField + new GenericClass<double>().InstanceProperty);
+ }
+
+ public void GenericClassStatic()
+ {
+ ToCode(X(), () => GenericClass<int>.StaticField + GenericClass<double>.StaticProperty);
+ }
+
+ public void InvokeGenericMethod()
+ {
+ ToCode(X(), () => GenericClass<int>.GenericMethod<double>());
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/Generics.cs b/ICSharpCode.Decompiler/Tests/Generics.cs
new file mode 100644
index 00000000..9776d42f
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/Generics.cs
@@ -0,0 +1,165 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+
+public static class Generics
+{
+ public class MyArray<T>
+ {
+ public class NestedClass<Y>
+ {
+ public T Item1;
+ public Y Item2;
+ }
+
+ public enum NestedEnum
+ {
+ A,
+ B
+ }
+
+ private T[] arr;
+
+ public MyArray(int capacity)
+ {
+ this.arr = new T[capacity];
+ }
+
+ public void Size(int capacity)
+ {
+ Array.Resize<T>(ref this.arr, capacity);
+ }
+
+ public void Grow(int capacity)
+ {
+ if (capacity >= this.arr.Length)
+ {
+ this.Size(capacity);
+ }
+ }
+ }
+
+ public interface IInterface
+ {
+ void Method1<T>() where T : class;
+ void Method2<T>() where T : class;
+ }
+
+ public abstract class Base : Generics.IInterface
+ {
+ // constraints must be repeated on implicit interface implementation
+ public abstract void Method1<T>() where T : class;
+
+ // constraints must not be specified on explicit interface implementation
+ void Generics.IInterface.Method2<T>()
+ {
+ }
+ }
+
+ public class Derived : Generics.Base
+ {
+ // constraints are inherited automatically and must not be specified
+ public override void Method1<T>()
+ {
+ }
+ }
+
+ private const Generics.MyArray<string>.NestedEnum enumVal = Generics.MyArray<string>.NestedEnum.A;
+ private static Type type1 = typeof(List<>);
+ private static Type type2 = typeof(Generics.MyArray<>);
+ private static Type type3 = typeof(List<>.Enumerator);
+ private static Type type4 = typeof(Generics.MyArray<>.NestedClass<>);
+ private static Type type5 = typeof(List<int>[]);
+ private static Type type6 = typeof(Generics.MyArray<>.NestedEnum);
+
+ public static void MethodWithConstraint<T, S>() where T : class, S where S : ICloneable, new()
+ {
+ }
+
+ public static void MethodWithStructConstraint<T>() where T : struct
+ {
+ }
+
+ private static void MultidimensionalArray<T>(T[,] array)
+ {
+ array[0, 0] = array[0, 1];
+ }
+
+ public static Dictionary<string, string>.KeyCollection.Enumerator GetEnumerator(Dictionary<string, string> d, Generics.MyArray<string>.NestedClass<int> nc)
+ {
+ // Tests references to inner classes in generic classes
+ return d.Keys.GetEnumerator();
+ }
+
+ public static bool IsString<T>(T input)
+ {
+ return input is string;
+ }
+
+ public static string AsString<T>(T input)
+ {
+ return input as string;
+ }
+
+ public static string CastToString<T>(T input)
+ {
+ return (string)((object)input);
+ }
+
+ public static T CastFromString<T>(string input)
+ {
+ return (T)((object)input);
+ }
+
+ public static bool IsInt<T>(T input)
+ {
+ return input is int;
+ }
+
+ public static int CastToInt<T>(T input)
+ {
+ return (int)((object)input);
+ }
+
+ public static T CastFromInt<T>(int input)
+ {
+ return (T)((object)input);
+ }
+
+ public static bool IsNullableInt<T>(T input)
+ {
+ return input is int?;
+ }
+
+ public static int? AsNullableInt<T>(T input)
+ {
+ return input as int?;
+ }
+
+ public static int? CastToNullableInt<T>(T input)
+ {
+ return (int?)((object)input);
+ }
+
+ public static T CastFromNullableInt<T>(int? input)
+ {
+ return (T)((object)input);
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/Helpers/CodeAssert.cs b/ICSharpCode.Decompiler/Tests/Helpers/CodeAssert.cs
new file mode 100644
index 00000000..d06e2db2
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/Helpers/CodeAssert.cs
@@ -0,0 +1,110 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using DiffLib;
+using NUnit.Framework;
+
+namespace ICSharpCode.Decompiler.Tests.Helpers
+{
+ public class CodeAssert
+ {
+ public static void AreEqual(string input1, string input2)
+ {
+ var diff = new StringWriter();
+ if (!Compare(input1, input2, diff)) {
+ Assert.Fail(diff.ToString());
+ }
+ }
+
+ static bool Compare(string input1, string input2, StringWriter diff)
+ {
+ var differ = new AlignedDiff<string>(
+ NormalizeAndSplitCode(input1),
+ NormalizeAndSplitCode(input2),
+ new CodeLineEqualityComparer(),
+ new StringSimilarityComparer(),
+ new StringAlignmentFilter());
+
+ bool result = true, ignoreChange;
+
+ int line1 = 0, line2 = 0;
+
+ foreach (var change in differ.Generate()) {
+ switch (change.Change) {
+ case ChangeType.Same:
+ diff.Write("{0,4} {1,4} ", ++line1, ++line2);
+ diff.Write(" ");
+ diff.WriteLine(change.Element1);
+ break;
+ case ChangeType.Added:
+ diff.Write(" {1,4} ", line1, ++line2);
+ result &= ignoreChange = ShouldIgnoreChange(change.Element2);
+ diff.Write(ignoreChange ? " " : " + ");
+ diff.WriteLine(change.Element2);
+ break;
+ case ChangeType.Deleted:
+ diff.Write("{0,4} ", ++line1, line2);
+ result &= ignoreChange = ShouldIgnoreChange(change.Element1);
+ diff.Write(ignoreChange ? " " : " - ");
+ diff.WriteLine(change.Element1);
+ break;
+ case ChangeType.Changed:
+ diff.Write("{0,4} ", ++line1, line2);
+ result = false;
+ diff.Write("(-) ");
+ diff.WriteLine(change.Element1);
+ diff.Write(" {1,4} ", line1, ++line2);
+ diff.Write("(+) ");
+ diff.WriteLine(change.Element2);
+ break;
+ }
+ }
+
+ return result;
+ }
+
+ class CodeLineEqualityComparer : IEqualityComparer<string>
+ {
+ private IEqualityComparer<string> baseComparer = EqualityComparer<string>.Default;
+
+ public bool Equals(string x, string y)
+ {
+ return baseComparer.Equals(
+ NormalizeLine(x),
+ NormalizeLine(y)
+ );
+ }
+
+ public int GetHashCode(string obj)
+ {
+ return baseComparer.GetHashCode(NormalizeLine(obj));
+ }
+ }
+
+ private static string NormalizeLine(string line)
+ {
+ line = line.Trim();
+ var index = line.IndexOf("//");
+ if (index >= 0) {
+ return line.Substring(0, index);
+ } else if (line.StartsWith("#")) {
+ return string.Empty;
+ } else {
+ return line;
+ }
+ }
+
+ private static bool ShouldIgnoreChange(string line)
+ {
+ // for the result, we should ignore blank lines and added comments
+ return NormalizeLine(line) == string.Empty;
+ }
+
+ private static IEnumerable<string> NormalizeAndSplitCode(string input)
+ {
+ return input.Split(new[] { "\r\n", "\n\r", "\n", "\r" }, StringSplitOptions.RemoveEmptyEntries);
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/Helpers/RemoveCompilerAttribute.cs b/ICSharpCode.Decompiler/Tests/Helpers/RemoveCompilerAttribute.cs
new file mode 100644
index 00000000..cb656202
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/Helpers/RemoveCompilerAttribute.cs
@@ -0,0 +1,38 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+using ICSharpCode.Decompiler.Ast.Transforms;
+using ICSharpCode.NRefactory.CSharp;
+
+namespace ICSharpCode.Decompiler.Tests.Helpers
+{
+ class RemoveCompilerAttribute : DepthFirstAstVisitor<object, object>, IAstTransform
+ {
+ public override object VisitAttribute(NRefactory.CSharp.Attribute attribute, object data)
+ {
+ var section = (AttributeSection)attribute.Parent;
+ SimpleType type = attribute.Type as SimpleType;
+ if (section.AttributeTarget == "assembly" &&
+ (type.Identifier == "CompilationRelaxations" || type.Identifier == "RuntimeCompatibility" || type.Identifier == "SecurityPermission" || type.Identifier == "AssemblyVersion" || type.Identifier == "Debuggable"))
+ {
+ attribute.Remove();
+ if (section.Attributes.Count == 0)
+ section.Remove();
+ }
+ if (section.AttributeTarget == "module" && type.Identifier == "UnverifiableCode")
+ {
+ attribute.Remove();
+ if (section.Attributes.Count == 0)
+ section.Remove();
+ }
+ return null;
+ }
+
+ public void Run(AstNode node)
+ {
+ node.AcceptVisitor(this, null);
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj b/ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj
new file mode 100644
index 00000000..808290a4
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj
@@ -0,0 +1,137 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build">
+ <PropertyGroup>
+ <ProjectGuid>{FEC0DA52-C4A6-4710-BE36-B484A20C5E22}</ProjectGuid>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
+ <OutputType>Library</OutputType>
+ <RootNamespace>ICSharpCode.Decompiler.Tests</RootNamespace>
+ <AssemblyName>ICSharpCode.Decompiler.Tests</AssemblyName>
+ <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <AllowUnsafeBlocks>True</AllowUnsafeBlocks>
+ <NoStdLib>False</NoStdLib>
+ <WarningLevel>4</WarningLevel>
+ <TreatWarningsAsErrors>false</TreatWarningsAsErrors>
+ <CheckForOverflowUnderflow>False</CheckForOverflowUnderflow>
+ <NoWarn>67,169,1058,728,1720,649</NoWarn>
+ <TargetFrameworkProfile />
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Platform)' == 'x86' ">
+ <PlatformTarget>x86</PlatformTarget>
+ <RegisterForComInterop>False</RegisterForComInterop>
+ <GenerateSerializationAssemblies>Auto</GenerateSerializationAssemblies>
+ <BaseAddress>4194304</BaseAddress>
+ <FileAlignment>4096</FileAlignment>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Platform)' == 'AnyCPU' ">
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <RegisterForComInterop>False</RegisterForComInterop>
+ <GenerateSerializationAssemblies>Auto</GenerateSerializationAssemblies>
+ <BaseAddress>4194304</BaseAddress>
+ <FileAlignment>4096</FileAlignment>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
+ <OutputPath>..\bin\Debug\</OutputPath>
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>Full</DebugType>
+ <Optimize>False</Optimize>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
+ <OutputPath>..\bin\Release\</OutputPath>
+ <DebugSymbols>false</DebugSymbols>
+ <DebugType>None</DebugType>
+ <Optimize>True</Optimize>
+ <DefineConstants>TRACE</DefineConstants>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="DiffLib">
+ <HintPath>..\..\packages\DiffLib.1.0.0.55\lib\net35-Client\DiffLib.dll</HintPath>
+ </Reference>
+ <Reference Include="ICSharpCode.NRefactory">
+ <HintPath>..\..\packages\ICSharpCode.NRefactory.5.5.1\lib\Net40\ICSharpCode.NRefactory.dll</HintPath>
+ </Reference>
+ <Reference Include="ICSharpCode.NRefactory.CSharp">
+ <HintPath>..\..\packages\ICSharpCode.NRefactory.5.5.1\lib\Net40\ICSharpCode.NRefactory.CSharp.dll</HintPath>
+ </Reference>
+ <Reference Include="nunit.framework">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>.\nunit.framework.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Core">
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.Xml" />
+ <Reference Include="System.Xml.Linq">
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
+ </Reference>
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Async.cs" />
+ <Compile Include="CallOverloadedMethod.cs" />
+ <Compile Include="CheckedUnchecked.cs" />
+ <Compile Include="ControlFlow.cs" />
+ <Compile Include="DoubleConstants.cs" />
+ <Compile Include="ExpressionTrees.cs" />
+ <None Include="IL\SequenceOfNestedIfs.Output.cs" />
+ <Compile Include="IL\ILTests.cs" />
+ <Compile Include="LiftedOperators.cs" />
+ <Compile Include="CustomShortCircuitOperators.cs" />
+ <Compile Include="Helpers\CodeAssert.cs" />
+ <Compile Include="IncrementDecrement.cs" />
+ <Compile Include="Lock.cs" />
+ <Compile Include="PInvoke.cs" />
+ <Compile Include="QueryExpressions.cs" />
+ <Compile Include="Switch.cs" />
+ <Compile Include="TypeAnalysisTests.cs" />
+ <Compile Include="UndocumentedExpressions.cs" />
+ <Compile Include="UnsafeCode.cs" />
+ <Compile Include="Types\S_TypeDeclarations.cs" />
+ <Compile Include="YieldReturn.cs" />
+ <None Include="IL\SequenceOfNestedIfs.dll" />
+ <None Include="IL\SequenceOfNestedIfs.il" />
+ <None Include="IL\StackTests.exe" />
+ <None Include="IL\StackTests.il" />
+ <None Include="packages.config" />
+ <None Include="Types\S_EnumSamples.cs" />
+ <None Include="CustomAttributes\S_AssemblyCustomAttribute.cs" />
+ <Compile Include="Helpers\RemoveCompilerAttribute.cs" />
+ <Compile Include="Types\S_TypeMemberDeclarations.cs" />
+ <Compile Include="Types\EnumTests.cs" />
+ <Compile Include="Types\TypeTests.cs" />
+ <Compile Include="DelegateConstruction.cs" />
+ <None Include="CustomAttributes\S_CustomAttributes.cs" />
+ <Compile Include="Loops.cs" />
+ <Compile Include="PropertiesAndEvents.cs" />
+ <None Include="CustomAttributes\S_CustomAttributeSamples.cs" />
+ <Compile Include="CodeSampleFileParser.cs" />
+ <Compile Include="CustomAttributes\CustomAttributeTests.cs" />
+ <Compile Include="DecompilerTestBase.cs" />
+ <Compile Include="InitializerTests.cs" />
+ <Compile Include="ExceptionHandling.cs" />
+ <Compile Include="Generics.cs" />
+ <Compile Include="MultidimensionalArray.cs" />
+ <Compile Include="TestRunner.cs" />
+ <Compile Include="ValueTypes.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\Mono.Cecil\Mono.Cecil.csproj">
+ <Project>{D68133BD-1E63-496E-9EDE-4FBDBF77B486}</Project>
+ <Name>Mono.Cecil</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\ICSharpCode.Decompiler.csproj">
+ <Project>{984CC812-9470-4A13-AFF9-CC44068D666C}</Project>
+ <Name>ICSharpCode.Decompiler</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup />
+ <ItemGroup>
+ <None Include="BooleanConsumedAsInteger.il" />
+ </ItemGroup>
+ <ItemGroup>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.Targets" />
+</Project> \ No newline at end of file
diff --git a/ICSharpCode.Decompiler/Tests/IL/ILTests.cs b/ICSharpCode.Decompiler/Tests/IL/ILTests.cs
new file mode 100644
index 00000000..f06f3108
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/IL/ILTests.cs
@@ -0,0 +1,51 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.IO;
+using ICSharpCode.Decompiler.Ast;
+using ICSharpCode.Decompiler.Tests.Helpers;
+using Mono.Cecil;
+using NUnit.Framework;
+
+namespace ICSharpCode.Decompiler.Tests
+{
+ [TestFixture]
+ public class ILTests
+ {
+ const string path = "../../Tests/IL";
+
+ [Test]
+ public void SequenceOfNestedIfs()
+ {
+ Run("SequenceOfNestedIfs.dll", "SequenceOfNestedIfs.Output.cs");
+ }
+
+ void Run(string compiledFile, string expectedOutputFile)
+ {
+ string expectedOutput = File.ReadAllText(Path.Combine(path, expectedOutputFile));
+ var assembly = AssemblyDefinition.ReadAssembly(Path.Combine(path, compiledFile));
+ AstBuilder decompiler = new AstBuilder(new DecompilerContext(assembly.MainModule));
+ decompiler.AddAssembly(assembly);
+ new Helpers.RemoveCompilerAttribute().Run(decompiler.SyntaxTree);
+ StringWriter output = new StringWriter();
+ decompiler.GenerateCode(new PlainTextOutput(output));
+ CodeAssert.AreEqual(expectedOutput, output.ToString());
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/IL/SequenceOfNestedIfs.Output.cs b/ICSharpCode.Decompiler/Tests/IL/SequenceOfNestedIfs.Output.cs
new file mode 100644
index 00000000..754d7daf
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/IL/SequenceOfNestedIfs.Output.cs
@@ -0,0 +1,53 @@
+using System;
+[Serializable]
+public class Material
+{
+ public static implicit operator bool(Material m)
+ {
+ return m == null;
+ }
+}
+[Serializable]
+public class SequenceOfNestedIfs
+{
+ public bool _clear;
+ public Material _material;
+ public override bool CheckShader()
+ {
+ return false;
+ }
+ public override void CreateMaterials()
+ {
+ if (!this._clear)
+ {
+ if (!this.CheckShader())
+ {
+ return;
+ }
+ this._material = new Material();
+ }
+ if (!this._material)
+ {
+ if (!this.CheckShader())
+ {
+ return;
+ }
+ this._material = new Material();
+ }
+ if (!this._material)
+ {
+ if (!this.CheckShader())
+ {
+ return;
+ }
+ this._material = new Material();
+ }
+ if (!this._material)
+ {
+ if (this.CheckShader())
+ {
+ this._material = new Material();
+ }
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/IL/SequenceOfNestedIfs.il b/ICSharpCode.Decompiler/Tests/IL/SequenceOfNestedIfs.il
new file mode 100644
index 00000000..9c9b749c
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/IL/SequenceOfNestedIfs.il
@@ -0,0 +1,140 @@
+// Metadata version: v2.0.50727
+.assembly extern mscorlib
+{
+ .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
+ .ver 2:0:0:0
+}
+
+.assembly SequenceOfNestedIfs
+{
+ .custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx
+ 63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 ) // ceptionThrows.
+ .hash algorithm 0x00008004
+ .ver 0:0:0:0
+}
+.module SequenceOfNestedIfs
+// MVID: {DCEC8A87-5679-4EBE-89A3-51274D8B5446}
+.imagebase 0x00400000
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003 // WINDOWS_CUI
+.corflags 0x00000001 // ILONLY
+// Image base: 0x01D60000
+
+
+// =============== CLASS MEMBERS DECLARATION ===================
+
+.class public auto ansi serializable beforefieldinit Material
+ extends [mscorlib]System.Object
+{
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ // Code size 7 (0x7)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [mscorlib]System.Object::.ctor()
+ IL_0006: ret
+ } // end of method Material::.ctor
+
+ .method public hidebysig specialname static
+ bool op_Implicit(class Material m) cil managed
+ {
+ // Code size 11 (0xb)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldnull
+ IL_0008: ceq
+ IL_000a: ret
+ } // end of method Material::op_Implicit
+
+} // end of class Material
+
+.class public auto ansi serializable beforefieldinit SequenceOfNestedIfs
+ extends [mscorlib]System.Object
+{
+ .field public bool _clear
+ .field public class Material _material
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ // Code size 7 (0x7)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [mscorlib]System.Object::.ctor()
+ IL_0006: ret
+ } // end of method SequenceOfNestedIfs::.ctor
+
+ .method public hidebysig virtual instance bool
+ CheckShader() cil managed
+ {
+ // Code size 2 (0x2)
+ .maxstack 8
+ IL_0000: ldc.i4.0
+ IL_0001: ret
+ } // end of method SequenceOfNestedIfs::CheckShader
+
+ .method public hidebysig virtual instance void
+ CreateMaterials() cil managed
+ {
+ // Code size 168 (0xa8)
+ .maxstack 13
+ IL_0000: ldarg.0
+ IL_0001: ldfld bool SequenceOfNestedIfs::_clear
+ IL_0006: brtrue IL_0026
+
+ IL_000b: ldarg.0
+ IL_000c: callvirt instance bool SequenceOfNestedIfs::CheckShader()
+ IL_0011: brtrue IL_001b
+
+ IL_0016: br IL_00a7
+
+ IL_001b: ldarg.0
+ IL_001c: newobj instance void Material::.ctor()
+ IL_0021: stfld class Material SequenceOfNestedIfs::_material
+ IL_0026: ldarg.0
+ IL_0027: ldfld class Material SequenceOfNestedIfs::_material
+ IL_002c: call bool Material::op_Implicit(class Material)
+ IL_0031: brtrue IL_0051
+
+ IL_0036: ldarg.0
+ IL_0037: callvirt instance bool SequenceOfNestedIfs::CheckShader()
+ IL_003c: brtrue IL_0046
+
+ IL_0041: br IL_00a7
+
+ IL_0046: ldarg.0
+ IL_0047: newobj instance void Material::.ctor()
+ IL_004c: stfld class Material SequenceOfNestedIfs::_material
+ IL_0051: ldarg.0
+ IL_0052: ldfld class Material SequenceOfNestedIfs::_material
+ IL_0057: call bool Material::op_Implicit(class Material)
+ IL_005c: brtrue IL_007c
+
+ IL_0061: ldarg.0
+ IL_0062: callvirt instance bool SequenceOfNestedIfs::CheckShader()
+ IL_0067: brtrue IL_0071
+
+ IL_006c: br IL_00a7
+
+ IL_0071: ldarg.0
+ IL_0072: newobj instance void Material::.ctor()
+ IL_0077: stfld class Material SequenceOfNestedIfs::_material
+ IL_007c: ldarg.0
+ IL_007d: ldfld class Material SequenceOfNestedIfs::_material
+ IL_0082: call bool Material::op_Implicit(class Material)
+ IL_0087: brtrue IL_00a7
+
+ IL_008c: ldarg.0
+ IL_008d: callvirt instance bool SequenceOfNestedIfs::CheckShader()
+ IL_0092: brtrue IL_009c
+
+ IL_0097: br IL_00a7
+
+ IL_009c: ldarg.0
+ IL_009d: newobj instance void Material::.ctor()
+ IL_00a2: stfld class Material SequenceOfNestedIfs::_material
+ IL_00a7: ret
+ } // end of method SequenceOfNestedIfs::CreateMaterials
+
+} // end of class SequenceOfNestedIfs \ No newline at end of file
diff --git a/ICSharpCode.Decompiler/Tests/IL/StackTests.il b/ICSharpCode.Decompiler/Tests/IL/StackTests.il
new file mode 100644
index 00000000..51cee375
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/IL/StackTests.il
@@ -0,0 +1,132 @@
+.assembly extern mscorlib
+{
+ .publickeytoken = (B7 7A 5C 56 19 34 E0 89 )
+ .ver 4:0:0:0
+}
+.assembly StackTests
+{
+ .hash algorithm 0x00008004
+ .ver 1:0:4059:39717
+}
+.module StackTests.exe
+.imagebase 0x00400000
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003 // WINDOWS_CUI
+.corflags 0x00000003 // ILONLY 32BITREQUIRED
+
+.class private auto ansi beforefieldinit StackTests.Program extends [mscorlib]System.Object
+{
+ .method public hidebysig static void Main(string[] args) cil managed
+ {
+ .entrypoint
+ .maxstack 8
+
+ ldc.i4.0
+ call string StackTests.Program::Test1(bool cond)
+ call void [mscorlib]System.Console::WriteLine(string) // false
+
+ ldc.i4.1
+ call string StackTests.Program::Test1(bool cond)
+ call void [mscorlib]System.Console::WriteLine(string) // true
+
+ ldc.i4.0
+ ldc.i4.0
+ ldc.i4.0
+ call int32 StackTests.Program::Test2(int32 switch1, int32 br1, int32 br2)
+ call void [mscorlib]System.Console::WriteLine(int32) // 11
+
+ ldc.i4.0
+ ldc.i4.1
+ ldc.i4.0
+ call int32 StackTests.Program::Test2(int32 switch1, int32 br1, int32 br2)
+ call void [mscorlib]System.Console::WriteLine(int32) // 21
+
+ ldc.i4.1
+ ldc.i4.1
+ ldc.i4.1
+ call int32 StackTests.Program::Test2(int32 switch1, int32 br1, int32 br2)
+ call void [mscorlib]System.Console::WriteLine(int32) // 32
+
+ ldc.i4.2
+ ldc.i4.1
+ ldc.i4.0
+ call int32 StackTests.Program::Test2(int32 switch1, int32 br1, int32 br2)
+ call void [mscorlib]System.Console::WriteLine(int32) // 23
+
+ ret
+ }
+
+ .method public hidebysig static string Test1(bool cond) cil managed
+ {
+ ldarg.0
+ brtrue TRUE
+
+ FALSE:
+ ldstr "false"
+ br EXIT
+
+ TRUE:
+ ldstr "true"
+
+ EXIT:
+ ret
+ }
+
+ .method public hidebysig static int32 Test2(int32 switch1, int32 br1, int32 br2) cil managed
+ {
+ ldarg.0
+ switch (ENTRY1, ENTRY2, ENTRY3)
+ ldc.i4.0
+ ret
+
+ ENTRY1:
+ ldc.i4.1
+ br BRANCH1
+
+ ENTRY2:
+ ldc.i4.2
+ br BRANCH1
+
+ ENTRY3:
+ ldc.i4.3
+ br BRANCH2
+
+ BRANCH1:
+ ldarg.1
+ brtrue BRANCH2
+
+ EXIT1:
+ ldc.i4 10
+ add
+ ret
+
+ BRANCH2:
+ ldarg.2
+ brtrue.s EXIT3
+
+ EXIT2:
+ ldc.i4 20
+ add
+ ret
+
+ EXIT3:
+ ldc.i4 30
+ add
+ ret
+ }
+
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ // Code size 7 (0x7)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [mscorlib]System.Object::.ctor()
+ IL_0006: ret
+ } // end of method Program::.ctor
+
+} // end of class StackTests.Program
+
+
+// =============================================================
diff --git a/ICSharpCode.Decompiler/Tests/IncrementDecrement.cs b/ICSharpCode.Decompiler/Tests/IncrementDecrement.cs
new file mode 100644
index 00000000..e06b680d
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/IncrementDecrement.cs
@@ -0,0 +1,254 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+
+public class IncrementDecrement
+{
+ [Flags]
+ private enum MyEnum
+ {
+ None = 0,
+ One = 1,
+ Two = 2,
+ Four = 4
+ }
+
+ public class MutableClass
+ {
+ public int Field;
+
+ public int Property
+ {
+ get;
+ set;
+ }
+
+ public uint this[string name]
+ {
+ get
+ {
+ return 0u;
+ }
+ set
+ {
+ }
+ }
+ }
+
+ private IncrementDecrement.MyEnum enumField;
+ public static int StaticField;
+
+ public static int StaticProperty
+ {
+ get;
+ set;
+ }
+
+ private IncrementDecrement.MutableClass M()
+ {
+ return new IncrementDecrement.MutableClass();
+ }
+
+ private int[,] Array()
+ {
+ return null;
+ }
+
+ private unsafe int* GetPointer()
+ {
+ return null;
+ }
+
+ public int PreIncrementInAddition(int i, int j)
+ {
+ return i + ++j;
+ }
+
+ public int PreIncrementArrayElement(int[] array, int pos)
+ {
+ return --array[pos];
+ }
+
+ public int PreIncrementInstanceField()
+ {
+ return ++this.M().Field;
+ }
+
+ public int PreIncrementInstanceField2(IncrementDecrement.MutableClass m)
+ {
+ return ++m.Field;
+ }
+
+ public int PreIncrementInstanceProperty()
+ {
+ return ++this.M().Property;
+ }
+
+ public int PreIncrementStaticField()
+ {
+ return ++IncrementDecrement.StaticField;
+ }
+
+ public int PreIncrementStaticProperty()
+ {
+ return ++IncrementDecrement.StaticProperty;
+ }
+
+// public uint PreIncrementIndexer(string name)
+// {
+// return ++this.M()[name];
+// }
+
+ public int PreIncrementByRef(ref int i)
+ {
+ return ++i;
+ }
+
+ public unsafe int PreIncrementByPointer()
+ {
+ return ++(*this.GetPointer());
+ }
+
+ public int PreIncrement2DArray()
+ {
+ return ++this.Array()[1, 2];
+ }
+
+ public int CompoundAssignInstanceField()
+ {
+ return this.M().Field *= 10;
+ }
+
+ public int CompoundAssignInstanceProperty()
+ {
+ return this.M().Property *= 10;
+ }
+
+ public int CompoundAssignStaticField()
+ {
+ return IncrementDecrement.StaticField ^= 100;
+ }
+
+ public int CompoundAssignStaticProperty()
+ {
+ return IncrementDecrement.StaticProperty &= 10;
+ }
+
+ public int CompoundAssignArrayElement1(int[] array, int pos)
+ {
+ return array[pos] *= 10;
+ }
+
+ public int CompoundAssignArrayElement2(int[] array)
+ {
+ return array[Environment.TickCount] *= 10;
+ }
+
+// public uint CompoundAssignIndexer(string name)
+// {
+// return this.M()[name] -= 2;
+// }
+
+ public int CompoundAssignIncrement2DArray()
+ {
+ return this.Array()[1, 2] %= 10;
+ }
+
+ public int CompoundAssignByRef(ref int i)
+ {
+ return i <<= 2;
+ }
+
+ public unsafe double CompoundAssignByPointer(double* ptr)
+ {
+ return *ptr /= 1.5;
+ }
+
+ public void CompoundAssignEnum()
+ {
+ this.enumField |= IncrementDecrement.MyEnum.Two;
+ this.enumField &= ~IncrementDecrement.MyEnum.Four;
+ }
+
+ public int PostIncrementInAddition(int i, int j)
+ {
+ return i++ + j;
+ }
+
+ public void PostIncrementInlineLocalVariable(Func<int, int> f)
+ {
+ int num = 0;
+ f(num++);
+ }
+
+ public int PostIncrementArrayElement(int[] array, int pos)
+ {
+ return array[pos]--;
+ }
+
+ public int PostIncrementStaticField()
+ {
+ return IncrementDecrement.StaticField++;
+ }
+
+ public int PostIncrementStaticProperty()
+ {
+ return IncrementDecrement.StaticProperty++;
+ }
+
+ public int PostIncrementInstanceField(IncrementDecrement.MutableClass m)
+ {
+ return m.Field++;
+ }
+
+// public uint PostIncrementIndexer(string name)
+// {
+// return this.M()[name]++;
+// }
+
+// public unsafe int PostIncrementOfPointer(int* ptr)
+// {
+// return *(ptr++);
+// }
+
+ public int PostIncrementInstanceField()
+ {
+ return this.M().Field--;
+ }
+
+ public int PostIncrementInstanceProperty()
+ {
+ return this.M().Property--;
+ }
+
+ public int PostIncrement2DArray()
+ {
+ return this.Array()[IncrementDecrement.StaticField, IncrementDecrement.StaticProperty]++;
+ }
+
+ public int PostIncrementByRef(ref int i)
+ {
+ return i++;
+ }
+
+ public unsafe int PostIncrementByPointer()
+ {
+ return (*this.GetPointer())++;
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/InitializerTests.cs b/ICSharpCode.Decompiler/Tests/InitializerTests.cs
new file mode 100644
index 00000000..29e3d1d5
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/InitializerTests.cs
@@ -0,0 +1,885 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+
+public class InitializerTests
+{
+ private enum MyEnum
+ {
+ a,
+ b
+ }
+
+ private enum MyEnum2
+ {
+ c,
+ d
+ }
+
+ private class Data
+ {
+ public List<InitializerTests.MyEnum2> FieldList = new List<InitializerTests.MyEnum2>();
+ public InitializerTests.MyEnum a
+ {
+ get;
+ set;
+ }
+ public List<InitializerTests.MyEnum2> PropertyList
+ {
+ get;
+ set;
+ }
+
+ public InitializerTests.Data MoreData
+ {
+ get;
+ set;
+ }
+
+ public InitializerTests.StructData NestedStruct
+ {
+ get;
+ set;
+ }
+ }
+
+ private struct StructData
+ {
+ public int Field;
+ public int Property
+ {
+ get;
+ set;
+ }
+
+ public InitializerTests.Data MoreData
+ {
+ get;
+ set;
+ }
+
+ public StructData(int initialValue)
+ {
+ this = default(InitializerTests.StructData);
+ this.Field = initialValue;
+ this.Property = initialValue;
+ }
+ }
+
+ // Helper methods used to ensure initializers used within expressions work correctly
+ private static void X(object a, object b)
+ {
+ }
+
+ private static object Y()
+ {
+ return null;
+ }
+
+ #region Array Initializers
+ public static void Array1()
+ {
+ InitializerTests.X(InitializerTests.Y(), new int[]
+ {
+ 1,
+ 2,
+ 3,
+ 4,
+ 5,
+ 6,
+ 7,
+ 8,
+ 9,
+ 10
+ });
+ }
+
+ public static void Array2(int a, int b, int c)
+ {
+ InitializerTests.X(InitializerTests.Y(), new int[]
+ {
+ a,
+ 0,
+ b,
+ 0,
+ c
+ });
+ }
+
+ public static void NestedArray(int a, int b, int c)
+ {
+ InitializerTests.X(InitializerTests.Y(), new int[][]
+ {
+ new int[]
+ {
+ 1,
+ 2,
+ 3,
+ 4,
+ 5,
+ 6,
+ 7,
+ 8,
+ 9,
+ 10
+ },
+ new int[]
+ {
+ a,
+ b,
+ c
+ },
+ new int[]
+ {
+ 1,
+ 2,
+ 3,
+ 4,
+ 5,
+ 6
+ }
+ });
+ }
+
+ public static void ArrayBoolean()
+ {
+ InitializerTests.X(InitializerTests.Y(), new bool[]
+ {
+ true,
+ false,
+ true,
+ false,
+ false,
+ false,
+ true,
+ true
+ });
+ }
+
+ public static void ArrayByte()
+ {
+ InitializerTests.X(InitializerTests.Y(), new byte[]
+ {
+ 1,
+ 2,
+ 3,
+ 4,
+ 5,
+ 6,
+ 7,
+ 8,
+ 254,
+ 255
+ });
+ }
+
+ public static void ArraySByte()
+ {
+ InitializerTests.X(InitializerTests.Y(), new sbyte[]
+ {
+ -128,
+ -127,
+ 0,
+ 1,
+ 2,
+ 3,
+ 4,
+ 127
+ });
+ }
+
+ public static void ArrayShort()
+ {
+ InitializerTests.X(InitializerTests.Y(), new short[]
+ {
+ -32768,
+ -1,
+ 0,
+ 1,
+ 32767
+ });
+ }
+
+ public static void ArrayUShort()
+ {
+ InitializerTests.X(InitializerTests.Y(), new ushort[]
+ {
+ 0,
+ 1,
+ 32767,
+ 32768,
+ 65534,
+ 65535
+ });
+ }
+
+ public static void ArrayInt()
+ {
+ InitializerTests.X(InitializerTests.Y(), new int[]
+ {
+ 1,
+ -2,
+ 2000000000,
+ 4,
+ 5,
+ -6,
+ 7,
+ 8,
+ 9,
+ 10
+ });
+ }
+
+ public static void ArrayUInt()
+ {
+ InitializerTests.X(InitializerTests.Y(), new uint[]
+ {
+ 1u,
+ 2000000000u,
+ 3000000000u,
+ 4u,
+ 5u,
+ 6u,
+ 7u,
+ 8u,
+ 9u,
+ 10u
+ });
+ }
+
+ public static void ArrayLong()
+ {
+ InitializerTests.X(InitializerTests.Y(), new long[]
+ {
+ -4999999999999999999L,
+ -1L,
+ 0L,
+ 1L,
+ 4999999999999999999L
+ });
+ }
+
+ public static void ArrayULong()
+ {
+ InitializerTests.X(InitializerTests.Y(), new ulong[]
+ {
+ 1uL,
+ 2000000000uL,
+ 3000000000uL,
+ 4uL,
+ 5uL,
+ 6uL,
+ 7uL,
+ 8uL,
+ 4999999999999999999uL,
+ 9999999999999999999uL
+ });
+ }
+
+ public static void ArrayFloat()
+ {
+ InitializerTests.X(InitializerTests.Y(), new float[]
+ {
+ -1.5f,
+ 0f,
+ 1.5f,
+ float.NegativeInfinity,
+ float.PositiveInfinity,
+ float.NaN
+ });
+ }
+
+ public static void ArrayDouble()
+ {
+ InitializerTests.X(InitializerTests.Y(), new double[]
+ {
+ -1.5,
+ 0.0,
+ 1.5,
+ double.NegativeInfinity,
+ double.PositiveInfinity,
+ double.NaN
+ });
+ }
+
+ public static void ArrayDecimal()
+ {
+ InitializerTests.X(InitializerTests.Y(), new decimal[]
+ {
+ -100m,
+ 0m,
+ 100m,
+ -79228162514264337593543950335m,
+ 79228162514264337593543950335m,
+ 0.0000001m
+ });
+ }
+
+ public static void ArrayString()
+ {
+ InitializerTests.X(InitializerTests.Y(), new string[]
+ {
+ "",
+ null,
+ "Hello",
+ "World"
+ });
+ }
+
+ public static void ArrayEnum()
+ {
+ InitializerTests.X(InitializerTests.Y(), new InitializerTests.MyEnum[]
+ {
+ InitializerTests.MyEnum.a,
+ InitializerTests.MyEnum.b,
+ InitializerTests.MyEnum.a,
+ InitializerTests.MyEnum.b
+ });
+ }
+
+ public static void RecursiveArrayInitializer()
+ {
+ int[] array = new int[3];
+ array[0] = 1;
+ array[1] = 2;
+ array[2] = array[1] + 1;
+ array[0] = 0;
+ }
+ #endregion
+
+ public static void CollectionInitializerList()
+ {
+ InitializerTests.X(InitializerTests.Y(), new List<int>
+ {
+ 1,
+ 2,
+ 3
+ });
+ }
+
+ public static object RecursiveCollectionInitializer()
+ {
+ List<object> list = new List<object>();
+ list.Add(list);
+ return list;
+ }
+
+ public static void CollectionInitializerDictionary()
+ {
+ InitializerTests.X(InitializerTests.Y(), new Dictionary<string, int>
+ {
+ {
+ "First",
+ 1
+ },
+ {
+ "Second",
+ 2
+ },
+ {
+ "Third",
+ 3
+ }
+ });
+ }
+
+ public static void CollectionInitializerDictionaryWithEnumTypes()
+ {
+ InitializerTests.X(InitializerTests.Y(), new Dictionary<InitializerTests.MyEnum, InitializerTests.MyEnum2>
+ {
+ {
+ InitializerTests.MyEnum.a,
+ InitializerTests.MyEnum2.c
+ },
+ {
+ InitializerTests.MyEnum.b,
+ InitializerTests.MyEnum2.d
+ }
+ });
+ }
+
+ public static void NotACollectionInitializer()
+ {
+ List<int> list = new List<int>();
+ list.Add(1);
+ list.Add(2);
+ list.Add(3);
+ InitializerTests.X(InitializerTests.Y(), list);
+ }
+
+ public static void ObjectInitializer()
+ {
+ InitializerTests.X(InitializerTests.Y(), new InitializerTests.Data
+ {
+ a = InitializerTests.MyEnum.a
+ });
+ }
+
+ public static void NotAObjectInitializer()
+ {
+ InitializerTests.Data data = new InitializerTests.Data();
+ data.a = InitializerTests.MyEnum.a;
+ InitializerTests.X(InitializerTests.Y(), data);
+ }
+
+ public static void ObjectInitializerAssignCollectionToField()
+ {
+ InitializerTests.X(InitializerTests.Y(), new InitializerTests.Data
+ {
+ a = InitializerTests.MyEnum.a,
+ FieldList = new List<InitializerTests.MyEnum2>
+ {
+ InitializerTests.MyEnum2.c,
+ InitializerTests.MyEnum2.d
+ }
+ });
+ }
+
+ public static void ObjectInitializerAddToCollectionInField()
+ {
+ InitializerTests.X(InitializerTests.Y(), new InitializerTests.Data
+ {
+ a = InitializerTests.MyEnum.a,
+ FieldList =
+ {
+ InitializerTests.MyEnum2.c,
+ InitializerTests.MyEnum2.d
+ }
+ });
+ }
+
+ public static void ObjectInitializerAssignCollectionToProperty()
+ {
+ InitializerTests.X(InitializerTests.Y(), new InitializerTests.Data
+ {
+ a = InitializerTests.MyEnum.a,
+ PropertyList = new List<InitializerTests.MyEnum2>
+ {
+ InitializerTests.MyEnum2.c,
+ InitializerTests.MyEnum2.d
+ }
+ });
+ }
+
+ public static void ObjectInitializerAddToCollectionInProperty()
+ {
+ InitializerTests.X(InitializerTests.Y(), new InitializerTests.Data
+ {
+ a = InitializerTests.MyEnum.a,
+ PropertyList =
+ {
+ InitializerTests.MyEnum2.c,
+ InitializerTests.MyEnum2.d
+ }
+ });
+ }
+
+ public static void ObjectInitializerWithInitializationOfNestedObjects()
+ {
+ InitializerTests.X(InitializerTests.Y(), new InitializerTests.Data
+ {
+ MoreData =
+ {
+ a = InitializerTests.MyEnum.a
+ }
+ });
+ }
+
+ public static void StructInitializer_DefaultConstructor()
+ {
+ InitializerTests.X(InitializerTests.Y(), new InitializerTests.StructData
+ {
+ Field = 1,
+ Property = 2
+ });
+ }
+
+ public static void StructInitializer_ExplicitConstructor()
+ {
+ InitializerTests.X(InitializerTests.Y(), new InitializerTests.StructData(0)
+ {
+ Field = 1,
+ Property = 2
+ });
+ }
+
+ public static void StructInitializerWithInitializationOfNestedObjects()
+ {
+ InitializerTests.X(InitializerTests.Y(), new InitializerTests.StructData
+ {
+ MoreData =
+ {
+ a = InitializerTests.MyEnum.a,
+ FieldList =
+ {
+ InitializerTests.MyEnum2.c,
+ InitializerTests.MyEnum2.d
+ }
+ }
+ });
+ }
+
+ public static void StructInitializerWithinObjectInitializer()
+ {
+ InitializerTests.X(InitializerTests.Y(), new InitializerTests.Data
+ {
+ NestedStruct = new InitializerTests.StructData(2)
+ {
+ Field = 1,
+ Property = 2
+ }
+ });
+ }
+
+ public int[,] MultidimensionalInit()
+ {
+ return new int[,]
+ {
+
+ {
+ 0,
+ 0,
+ 0,
+ 0
+ },
+
+ {
+ 1,
+ 1,
+ 1,
+ 1
+ },
+
+ {
+ 0,
+ 0,
+ 0,
+ 0
+ },
+
+ {
+ 0,
+ 0,
+ 0,
+ 0
+ },
+
+ {
+ 0,
+ 0,
+ 1,
+ 0
+ },
+
+ {
+ 0,
+ 0,
+ 1,
+ 0
+ },
+
+ {
+ 0,
+ 0,
+ 1,
+ 0
+ },
+
+ {
+ 0,
+ 0,
+ 1,
+ 0
+ },
+
+ {
+ 0,
+ 0,
+ 0,
+ 0
+ },
+
+ {
+ 1,
+ 1,
+ 1,
+ 1
+ },
+
+ {
+ 0,
+ 0,
+ 0,
+ 0
+ },
+
+ {
+ 0,
+ 0,
+ 0,
+ 0
+ },
+
+ {
+ 0,
+ 0,
+ 1,
+ 0
+ },
+
+ {
+ 0,
+ 0,
+ 1,
+ 0
+ },
+
+ {
+ 0,
+ 0,
+ 1,
+ 0
+ },
+
+ {
+ 0,
+ 0,
+ 1,
+ 0
+ }
+ };
+ }
+
+ public int[][,] MultidimensionalInit2()
+ {
+ return new int[][,]
+ {
+ new int[,]
+ {
+
+ {
+ 0,
+ 0,
+ 0,
+ 0
+ },
+
+ {
+ 1,
+ 1,
+ 1,
+ 1
+ },
+
+ {
+ 0,
+ 0,
+ 0,
+ 0
+ },
+
+ {
+ 0,
+ 0,
+ 0,
+ 0
+ }
+
+ },
+ new int[,]
+ {
+
+ {
+ 0,
+ 0,
+ 1,
+ 0
+ },
+
+ {
+ 0,
+ 0,
+ 1,
+ 0
+ },
+
+ {
+ 0,
+ 0,
+ 1,
+ 0
+ },
+
+ {
+ 0,
+ 0,
+ 1,
+ 0
+ }
+
+ },
+ new int[,]
+ {
+
+ {
+ 0,
+ 0,
+ 0,
+ 0
+ },
+
+ {
+ 1,
+ 1,
+ 1,
+ 1
+ },
+
+ {
+ 0,
+ 0,
+ 0,
+ 0
+ },
+
+ {
+ 0,
+ 0,
+ 0,
+ 0
+ }
+ },
+ new int[,]
+ {
+
+ {
+ 0,
+ 0,
+ 1,
+ 0
+ },
+
+ {
+ 0,
+ 0,
+ 1,
+ 0
+ },
+
+ {
+ 0,
+ 0,
+ 1,
+ 0
+ },
+
+ {
+ 0,
+ 0,
+ 1,
+ 0
+ }
+
+ }
+ };
+ }
+
+ public int[][,,] ArrayOfArrayOfArrayInit()
+ {
+ return new int[][,,]
+ {
+ new int[,,]
+ {
+ {
+ {
+ 1,
+ 2,
+ 3
+ },
+ {
+ 4,
+ 5,
+ 6
+ },
+ {
+ 7,
+ 8,
+ 9
+ }
+ },
+ {
+ {
+ 11,
+ 12,
+ 13
+ },
+ {
+ 14,
+ 15,
+ 16
+ },
+ {
+ 17,
+ 18,
+ 19
+ }
+ }
+ },
+
+ new int[,,]
+ {
+ {
+ {
+ 21,
+ 22,
+ 23
+ },
+ {
+ 24,
+ 25,
+ 26
+ },
+ {
+ 27,
+ 28,
+ 29
+ }
+ },
+ {
+ {
+ 31,
+ 32,
+ 33
+ },
+ {
+ 34,
+ 35,
+ 36
+ },
+ {
+ 37,
+ 38,
+ 39
+ }
+ }
+ }
+ };
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/LiftedOperators.cs b/ICSharpCode.Decompiler/Tests/LiftedOperators.cs
new file mode 100644
index 00000000..426276ab
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/LiftedOperators.cs
@@ -0,0 +1,830 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Runtime.InteropServices;
+
+public static class LiftedOperators
+{
+ // C# uses 4 different patterns of IL for lifted operators: bool, other primitive types, decimal, other structs.
+ // Different patterns are used depending on whether both of the operands are nullable or only the left/right operand is nullable.
+ // Negation must not be pushed through such comparisons because it would change the semantics.
+ // A comparison used in a condition differs somewhat from a comparison used as a simple value.
+
+ public static void BoolBasic(bool? a, bool? b)
+ {
+ if (a == b)
+ {
+ Console.WriteLine();
+ }
+ if (a != b)
+ {
+ Console.WriteLine();
+ }
+
+ if (!(a == b))
+ {
+ Console.WriteLine();
+ }
+ if (!(a != b))
+ {
+ Console.WriteLine();
+ }
+ }
+
+ public static void BoolComplex(bool? a, Func<bool> x)
+ {
+ if (a == x())
+ {
+ Console.WriteLine();
+ }
+ if (a != x())
+ {
+ Console.WriteLine();
+ }
+
+ if (x() == a)
+ {
+ Console.WriteLine();
+ }
+ if (x() != a)
+ {
+ Console.WriteLine();
+ }
+
+ if (!(a == x()))
+ {
+ Console.WriteLine();
+ }
+ if (!(a != x()))
+ {
+ Console.WriteLine();
+ }
+ if (!(x() == a))
+ {
+ Console.WriteLine();
+ }
+ if (!(x() != a))
+ {
+ Console.WriteLine();
+ }
+ }
+
+ public static void BoolConst(bool? a)
+ {
+ if (a == true)
+ {
+ Console.WriteLine();
+ }
+ if (a != true)
+ {
+ Console.WriteLine();
+ }
+ if (a == false)
+ {
+ Console.WriteLine();
+ }
+ if (a != false)
+ {
+ Console.WriteLine();
+ }
+ if (a ?? true)
+ {
+ Console.WriteLine();
+ }
+ if (a ?? false)
+ {
+ Console.WriteLine();
+ }
+ }
+
+ public static void BoolValueBasic(bool? a, bool? 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);
+ a &= b;
+ a |= b;
+ a ^= b;
+ }
+
+ public static void BoolValueComplex(bool? a, Func<bool> x)
+ {
+ Console.WriteLine(a == x());
+ Console.WriteLine(a != x());
+
+ Console.WriteLine(x() == a);
+ Console.WriteLine(x() != a);
+
+ Console.WriteLine(!(a == x()));
+ Console.WriteLine(!(a != x()));
+
+ Console.WriteLine(a & x());
+ Console.WriteLine(a | x());
+ Console.WriteLine(a ^ x());
+ Console.WriteLine(a ?? x());
+ a &= x();
+ a |= x();
+ a ^= x();
+
+ Console.WriteLine(x() ^ a);
+ (new bool?[0])[0] ^= x();
+ }
+
+ public static void BoolValueConst(bool? a)
+ {
+ Console.WriteLine(a == true);
+ Console.WriteLine(a != true);
+ Console.WriteLine(a == false);
+ Console.WriteLine(a != false);
+ Console.WriteLine(a ?? true);
+ Console.WriteLine(a ?? false);
+ }
+
+ public static void IntBasic(int? a, int? b)
+ {
+ if (a == b)
+ {
+ Console.WriteLine();
+ }
+ if (a != b)
+ {
+ Console.WriteLine();
+ }
+ if (a > b)
+ {
+ Console.WriteLine();
+ }
+ if (a < b)
+ {
+ Console.WriteLine();
+ }
+ if (a >= b)
+ {
+ Console.WriteLine();
+ }
+ if (a <= b)
+ {
+ Console.WriteLine();
+ }
+
+ if (!(a == b))
+ {
+ Console.WriteLine();
+ }
+ if (!(a != b))
+ {
+ Console.WriteLine();
+ }
+ if (!(a > b))
+ {
+ Console.WriteLine();
+ }
+ }
+
+ public static void IntComplex(int? a, Func<int> x)
+ {
+ if (a == x())
+ {
+ Console.WriteLine();
+ }
+ if (a != x())
+ {
+ Console.WriteLine();
+ }
+ if (a > x())
+ {
+ Console.WriteLine();
+ }
+
+ if (x() == a)
+ {
+ Console.WriteLine();
+ }
+ if (x() != a)
+ {
+ Console.WriteLine();
+ }
+ if (x() > a)
+ {
+ Console.WriteLine();
+ }
+
+ if (!(a == x()))
+ {
+ Console.WriteLine();
+ }
+ if (!(a != x()))
+ {
+ Console.WriteLine();
+ }
+ if (!(a > x()))
+ {
+ Console.WriteLine();
+ }
+ }
+
+ public static void IntConst(int? a)
+ {
+ if (a == 2)
+ {
+ Console.WriteLine();
+ }
+ if (a != 2)
+ {
+ Console.WriteLine();
+ }
+ if (a > 2)
+ {
+ Console.WriteLine();
+ }
+
+ if (2 == a)
+ {
+ Console.WriteLine();
+ }
+ if (2 != a)
+ {
+ Console.WriteLine();
+ }
+ if (2 > a)
+ {
+ Console.WriteLine();
+ }
+ }
+
+ public static void IntValueBasic(int? a, int? 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);
+ 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);
+ Console.WriteLine(~a);
+ // TODO:
+ //Console.WriteLine(a++);
+ //Console.WriteLine(a--);
+ Console.WriteLine(++a);
+ Console.WriteLine(--a);
+ a += b;
+ a -= b;
+ a *= b;
+ a /= b;
+ a %= b;
+ a &= b;
+ a |= b;
+ a ^= b;
+ a <<= b;
+ a >>= b;
+ }
+
+ public static void IntValueComplex(int? a, Func<int> x)
+ {
+ Console.WriteLine(a == x());
+ Console.WriteLine(a != x());
+ Console.WriteLine(a > x());
+
+ Console.WriteLine(x() == a);
+ Console.WriteLine(x() != a);
+ Console.WriteLine(x() > a);
+
+ Console.WriteLine(a + x());
+ Console.WriteLine(a - x());
+ Console.WriteLine(a * x());
+ Console.WriteLine(a / x());
+ Console.WriteLine(a % x());
+ Console.WriteLine(a & x());
+ Console.WriteLine(a | x());
+ Console.WriteLine(a ^ x());
+ Console.WriteLine(a << x());
+ Console.WriteLine(a >> x());
+ Console.WriteLine(a ?? x());
+ a += x();
+ a -= x();
+ a *= x();
+ a /= x();
+ a %= x();
+ a &= x();
+ a |= x();
+ a ^= x();
+ a <<= x();
+ a >>= x();
+
+ Console.WriteLine(x() + a);
+ (new int?[0])[0] += x();
+ }
+
+ public static void IntValueConst(int? a)
+ {
+ Console.WriteLine(a == 2);
+ Console.WriteLine(a != 2);
+ Console.WriteLine(a > 2);
+
+ Console.WriteLine(2 == a);
+ Console.WriteLine(2 != a);
+ Console.WriteLine(2 > a);
+
+ Console.WriteLine(a + 2);
+ Console.WriteLine(a - 2);
+ Console.WriteLine(a * 2);
+ Console.WriteLine(a / 2);
+ Console.WriteLine(a % 2);
+ Console.WriteLine(a & 2);
+ Console.WriteLine(a | 2);
+ Console.WriteLine(a ^ 2);
+ Console.WriteLine(a << 2);
+ Console.WriteLine(a >> 2);
+ Console.WriteLine(a ?? 2);
+ a += 2;
+ a -= 2;
+ a *= 2;
+ a /= 2;
+ a %= 2;
+ a &= 2;
+ a |= 2;
+ a ^= 2;
+ a <<= 2;
+ a >>= 2;
+
+ Console.WriteLine(2 + a);
+ }
+
+ public static void NumberBasic(decimal? a, decimal? b)
+ {
+ if (a == b)
+ {
+ Console.WriteLine();
+ }
+ if (a != b)
+ {
+ Console.WriteLine();
+ }
+ if (a > b)
+ {
+ Console.WriteLine();
+ }
+ if (a < b)
+ {
+ Console.WriteLine();
+ }
+ if (a >= b)
+ {
+ Console.WriteLine();
+ }
+ if (a <= b)
+ {
+ Console.WriteLine();
+ }
+
+ if (!(a == b))
+ {
+ Console.WriteLine();
+ }
+ if (!(a != b))
+ {
+ Console.WriteLine();
+ }
+ if (!(a > b))
+ {
+ Console.WriteLine();
+ }
+ }
+
+ public static void NumberComplex(decimal? a, Func<decimal> x)
+ {
+ if (a == x())
+ {
+ Console.WriteLine();
+ }
+ if (a != x())
+ {
+ Console.WriteLine();
+ }
+ if (a > x())
+ {
+ Console.WriteLine();
+ }
+
+ if (x() == a)
+ {
+ Console.WriteLine();
+ }
+ if (x() != a)
+ {
+ Console.WriteLine();
+ }
+ if (x() > a)
+ {
+ Console.WriteLine();
+ }
+ }
+
+ public static void NumberConst(decimal? a)
+ {
+ if (a == 2m)
+ {
+ Console.WriteLine();
+ }
+ if (a != 2m)
+ {
+ Console.WriteLine();
+ }
+ if (a > 2m)
+ {
+ Console.WriteLine();
+ }
+
+ if (2m == a)
+ {
+ Console.WriteLine();
+ }
+ if (2m != a)
+ {
+ Console.WriteLine();
+ }
+ if (2m > a)
+ {
+ Console.WriteLine();
+ }
+ }
+
+ public static void NumberValueBasic(decimal? a, decimal? 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);
+ Console.WriteLine(a / b);
+ Console.WriteLine(a % b);
+ Console.WriteLine(a ?? b);
+ Console.WriteLine(-a);
+ // TODO:
+ //Console.WriteLine(a++);
+ //Console.WriteLine(a--);
+ //Console.WriteLine(++a);
+ //Console.WriteLine(--a);
+ a += b;
+ a -= b;
+ a *= b;
+ a /= b;
+ a %= b;
+ }
+
+ public static void NumberValueComplex(decimal? a, Func<decimal> x)
+ {
+ Console.WriteLine(a == x());
+ Console.WriteLine(a != x());
+ Console.WriteLine(a > x());
+
+ Console.WriteLine(x() == a);
+ Console.WriteLine(x() != a);
+ Console.WriteLine(x() > a);
+
+ Console.WriteLine(a + x());
+ Console.WriteLine(a - x());
+ Console.WriteLine(a * x());
+ Console.WriteLine(a / x());
+ Console.WriteLine(a % x());
+ Console.WriteLine(a ?? x());
+ a += x();
+ a -= x();
+ a *= x();
+ a /= x();
+ a %= x();
+
+ Console.WriteLine(x() + a);
+ (new decimal?[0])[0] += x();
+ }
+
+ public static void NumberValueConst(decimal? a)
+ {
+ Console.WriteLine(a == 2m);
+ Console.WriteLine(a != 2m);
+ Console.WriteLine(a > 2m);
+
+ Console.WriteLine(2m == a);
+ Console.WriteLine(2m != a);
+ Console.WriteLine(2m > a);
+
+ Console.WriteLine(a + 2m);
+ Console.WriteLine(a - 2m);
+ Console.WriteLine(a * 2m);
+ Console.WriteLine(a / 2m);
+ Console.WriteLine(a % 2m);
+ Console.WriteLine(a ?? 2m);
+ a += 2m;
+ a -= 2m;
+ a *= 2m;
+ a /= 2m;
+ a %= 2m;
+
+ Console.WriteLine(2m + a);
+ }
+
+ public static void StructBasic(TS? a, TS? b)
+ {
+ if (a == b)
+ {
+ Console.WriteLine();
+ }
+ if (a != b)
+ {
+ Console.WriteLine();
+ }
+ if (a > b)
+ {
+ Console.WriteLine();
+ }
+ if (a < b)
+ {
+ Console.WriteLine();
+ }
+ if (a >= b)
+ {
+ Console.WriteLine();
+ }
+ if (a <= b)
+ {
+ Console.WriteLine();
+ }
+
+ if (!(a == b))
+ {
+ Console.WriteLine();
+ }
+ if (!(a != b))
+ {
+ Console.WriteLine();
+ }
+ if (!(a > b))
+ {
+ Console.WriteLine();
+ }
+ }
+
+ public static void StructComplex(TS? a, Func<TS> x)
+ {
+ if (a == x())
+ {
+ Console.WriteLine();
+ }
+ if (a != x())
+ {
+ Console.WriteLine();
+ }
+ if (a > x())
+ {
+ Console.WriteLine();
+ }
+
+ if (x() == a)
+ {
+ Console.WriteLine();
+ }
+ if (x() != a)
+ {
+ Console.WriteLine();
+ }
+ if (x() > a)
+ {
+ Console.WriteLine();
+ }
+ }
+
+ public static void StructValueBasic(TS? a, TS? b, int? i)
+ {
+ 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);
+ Console.WriteLine(a % b);
+ Console.WriteLine(a & b);
+ Console.WriteLine(a | b);
+ Console.WriteLine(a ^ b);
+ Console.WriteLine(a << i);
+ Console.WriteLine(a >> i);
+ Console.WriteLine(a ?? b);
+ Console.WriteLine(+a);
+ Console.WriteLine(-a);
+ Console.WriteLine(!a);
+ Console.WriteLine(~a);
+ // TODO:
+ //Console.WriteLine(a++);
+ //Console.WriteLine(a--);
+ //Console.WriteLine(++a);
+ //Console.WriteLine(--a);
+ //Console.WriteLine((int?)a);
+ a += b;
+ a -= b;
+ a *= b;
+ a /= b;
+ a %= b;
+ a &= b;
+ a |= b;
+ a ^= b;
+ a <<= i;
+ a >>= i;
+ }
+
+ public static void StructValueComplex(TS? a, Func<TS> x, Func<int> i)
+ {
+ Console.WriteLine(a == x());
+ Console.WriteLine(a != x());
+ Console.WriteLine(a > x());
+
+ Console.WriteLine(x() == a);
+ Console.WriteLine(x() != a);
+ Console.WriteLine(x() > a);
+
+ Console.WriteLine(a + x());
+ Console.WriteLine(a - x());
+ Console.WriteLine(a * x());
+ Console.WriteLine(a / x());
+ Console.WriteLine(a % x());
+ Console.WriteLine(a & x());
+ Console.WriteLine(a | x());
+ Console.WriteLine(a ^ x());
+ Console.WriteLine(a << i());
+ Console.WriteLine(a >> i());
+ Console.WriteLine(a ?? x());
+ a += x();
+ a -= x();
+ a *= x();
+ a /= x();
+ a %= x();
+ a &= x();
+ a |= x();
+ a ^= x();
+ a <<= i();
+ a >>= i();
+
+ Console.WriteLine(x() + a);
+ (new TS?[0])[0] += x();
+ }
+}
+
+// dummy structure for testing custom operators
+[StructLayout(LayoutKind.Sequential, Size = 1)]
+public struct TS
+{
+ // unary
+ public static TS operator +(TS a)
+ {
+ throw null;
+ }
+ public static TS operator -(TS a)
+ {
+ throw null;
+ }
+ public static TS operator !(TS a)
+ {
+ throw null;
+ }
+ public static TS operator ~(TS a)
+ {
+ throw null;
+ }
+ public static TS operator ++(TS a)
+ {
+ throw null;
+ }
+ public static TS operator --(TS a)
+ {
+ throw null;
+ }
+
+ public static explicit operator int(TS a)
+ {
+ throw null;
+ }
+
+ // binary
+ public static TS operator +(TS a, TS b)
+ {
+ throw null;
+ }
+ public static TS operator -(TS a, TS b)
+ {
+ throw null;
+ }
+ public static TS operator *(TS a, TS b)
+ {
+ throw null;
+ }
+ public static TS operator /(TS a, TS b)
+ {
+ throw null;
+ }
+ public static TS operator %(TS a, TS b)
+ {
+ throw null;
+ }
+ public static TS operator &(TS a, TS b)
+ {
+ throw null;
+ }
+ public static TS operator |(TS a, TS b)
+ {
+ throw null;
+ }
+ public static TS operator ^(TS a, TS b)
+ {
+ throw null;
+ }
+ public static TS operator <<(TS a, int b)
+ {
+ throw null;
+ }
+ public static TS operator >>(TS a, int b)
+ {
+ throw null;
+ }
+
+ // comparisons
+ public static bool operator ==(TS a, TS b)
+ {
+ throw null;
+ }
+ public static bool operator !=(TS a, TS b)
+ {
+ throw null;
+ }
+ public static bool operator <(TS a, TS b)
+ {
+ throw null;
+ }
+ public static bool operator <=(TS a, TS b)
+ {
+ throw null;
+ }
+ public static bool operator >(TS a, TS b)
+ {
+ throw null;
+ }
+ public static bool operator >=(TS a, TS b)
+ {
+ throw null;
+ }
+
+ public override bool Equals(object obj)
+ {
+ throw null;
+ }
+ public override int GetHashCode()
+ {
+ throw null;
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/Lock.cs b/ICSharpCode.Decompiler/Tests/Lock.cs
new file mode 100644
index 00000000..da5a59c7
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/Lock.cs
@@ -0,0 +1,38 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+
+public class Lock
+{
+ public void LockThis()
+ {
+ lock (this)
+ {
+ Console.WriteLine();
+ }
+ }
+
+ public void LockOnType()
+ {
+ lock (typeof(Lock))
+ {
+ Console.WriteLine();
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/Loops.cs b/ICSharpCode.Decompiler/Tests/Loops.cs
new file mode 100644
index 00000000..03427a8b
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/Loops.cs
@@ -0,0 +1,74 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+
+public class Loops
+{
+ public void ForEach(IEnumerable<string> enumerable)
+ {
+ foreach (string current in enumerable)
+ {
+ current.ToLower();
+ }
+ }
+
+ public void ForEachOverList(List<string> list)
+ {
+ // List has a struct as enumerator, so produces quite different IL than foreach over the IEnumerable interface
+ foreach (string current in list)
+ {
+ current.ToLower();
+ }
+ }
+
+ public void ForEachOverNonGenericEnumerable(IEnumerable enumerable)
+ {
+ foreach (object current in enumerable)
+ {
+ current.ToString();
+ }
+ }
+
+ public void ForEachOverNonGenericEnumerableWithAutomaticCast(IEnumerable enumerable)
+ {
+ foreach (int num in enumerable)
+ {
+ num.ToString();
+ }
+ }
+
+// public void ForEachOverArray(string[] array)
+// {
+// foreach (string text in array)
+// {
+// text.ToLower();
+// }
+// }
+
+ public void ForOverArray(string[] array)
+ {
+ for (int i = 0; i < array.Length; i++)
+ {
+ array[i].ToLower();
+ }
+ }
+}
+
diff --git a/ICSharpCode.Decompiler/Tests/MultidimensionalArray.cs b/ICSharpCode.Decompiler/Tests/MultidimensionalArray.cs
new file mode 100644
index 00000000..c3557cee
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/MultidimensionalArray.cs
@@ -0,0 +1,58 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+
+public class MultidimensionalArray
+{
+ internal class Generic<T, S> where T : new()
+ {
+ private T[,] a = new T[20, 20];
+ private S[,][] b = new S[20, 20][];
+
+ public T this[int i, int j]
+ {
+ get
+ {
+ return this.a[i, j];
+ }
+ set
+ {
+ this.a[i, j] = value;
+ }
+ }
+
+ public void TestB(S x, ref S y)
+ {
+ this.b[5, 3] = new S[10];
+ this.b[5, 3][0] = default(S);
+ this.b[5, 3][1] = x;
+ this.b[5, 3][2] = y;
+ }
+
+ public void PassByReference(ref T arr)
+ {
+ this.PassByReference(ref this.a[10, 10]);
+ }
+ }
+
+ public int[][,] MakeArray()
+ {
+ return new int[10][,];
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/PInvoke.cs b/ICSharpCode.Decompiler/Tests/PInvoke.cs
new file mode 100644
index 00000000..0c828ac6
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/PInvoke.cs
@@ -0,0 +1,96 @@
+// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Runtime.InteropServices;
+
+// P/Invoke and marshalling attribute tests
+public class PInvoke
+{
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode, Pack = 2)]
+ public struct MarshalAsTest
+ {
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
+ public uint[] FixedArray;
+
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4, ArraySubType = UnmanagedType.Bool)]
+ public int[] FixedBoolArray;
+
+ [MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_BSTR)]
+ public string[] SafeBStrArray;
+
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]
+ public string FixedString;
+ }
+
+ [StructLayout(LayoutKind.Explicit)]
+ public struct Rect
+ {
+ [FieldOffset(0)]
+ public int left;
+ [FieldOffset(4)]
+ public int top;
+ [FieldOffset(8)]
+ public int right;
+ [FieldOffset(12)]
+ public int bottom;
+ }
+
+ public static decimal MarshalAttributesOnPropertyAccessors
+ {
+ [return: MarshalAs(UnmanagedType.Currency)]
+ get
+ {
+ return 0m;
+ }
+ [param: MarshalAs(UnmanagedType.Currency)]
+ set
+ {
+ }
+ }
+
+ [DllImport("xyz.dll", CharSet = CharSet.Auto)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool Method([MarshalAs(UnmanagedType.LPStr)] string input);
+
+ [DllImport("xyz.dll")]
+ private static extern void New1(int ElemCnt, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] int[] ar);
+
+ [DllImport("xyz.dll")]
+ private static extern void New2([MarshalAs(UnmanagedType.LPArray, SizeConst = 128)] int[] ar);
+
+ [DllImport("xyz.dll")]
+ private static extern void New3([MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.Bool, SizeConst = 64, SizeParamIndex = 1)] int[] ar);
+
+ public void CustomMarshal1([MarshalAs(UnmanagedType.CustomMarshaler, MarshalType = "MyCompany.MyMarshaler")] object o)
+ {
+ }
+
+ public void CustomMarshal2([MarshalAs(UnmanagedType.CustomMarshaler, MarshalType = "MyCompany.MyMarshaler", MarshalCookie = "Cookie")] object o)
+ {
+ }
+
+ [DllImport("ws2_32.dll", SetLastError = true)]
+ internal static extern IntPtr ioctlsocket([In] IntPtr socketHandle, [In] int cmd, [In] [Out] ref int argp);
+
+ public void CallMethodWithInOutParameter()
+ {
+ int num = 0;
+ PInvoke.ioctlsocket(IntPtr.Zero, 0, ref num);
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/PropertiesAndEvents.cs b/ICSharpCode.Decompiler/Tests/PropertiesAndEvents.cs
new file mode 100644
index 00000000..9b3d1658
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/PropertiesAndEvents.cs
@@ -0,0 +1,80 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Text;
+
+public class PropertiesAndEvents
+{
+ public event EventHandler AutomaticEvent;
+
+ [field: NonSerialized]
+ public event EventHandler AutomaticEventWithInitializer = delegate(object sender, EventArgs e)
+ {
+ };
+
+ public event EventHandler CustomEvent
+ {
+ add
+ {
+ this.AutomaticEvent += value;
+ }
+ remove
+ {
+ this.AutomaticEvent -= value;
+ }
+ }
+
+ public int AutomaticProperty
+ {
+ get;
+ set;
+ }
+
+ public int CustomProperty
+ {
+ get
+ {
+ return this.AutomaticProperty;
+ }
+ set
+ {
+ this.AutomaticProperty = value;
+ }
+ }
+
+ public int Getter(StringBuilder b)
+ {
+ return b.Length;
+ }
+
+ public void Setter(StringBuilder b)
+ {
+ b.Capacity = 100;
+ }
+
+ public char IndexerGetter(StringBuilder b)
+ {
+ return b[50];
+ }
+
+ public void IndexerSetter(StringBuilder b)
+ {
+ b[42] = 'b';
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/QueryExpressions.cs b/ICSharpCode.Decompiler/Tests/QueryExpressions.cs
new file mode 100644
index 00000000..d8b6e062
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/QueryExpressions.cs
@@ -0,0 +1,188 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+public class QueryExpressions
+{
+ public class Customer
+ {
+ public int CustomerID;
+ public IEnumerable<QueryExpressions.Order> Orders;
+ public string Name;
+ public string Country;
+ public string City;
+ }
+
+ public class Order
+ {
+ public int OrderID;
+ public DateTime OrderDate;
+ public QueryExpressions.Customer Customer;
+ public int CustomerID;
+ public decimal Total;
+ public IEnumerable<QueryExpressions.OrderDetail> Details;
+ }
+
+ public class OrderDetail
+ {
+ public decimal UnitPrice;
+ public int Quantity;
+ }
+
+ public IEnumerable<QueryExpressions.Customer> customers;
+ public IEnumerable<QueryExpressions.Order> orders;
+
+ public object MultipleWhere()
+ {
+ return from c in this.customers
+ where c.Orders.Count<QueryExpressions.Order>() > 10
+ where c.Country == "DE"
+ select c;
+ }
+
+ public object SelectManyFollowedBySelect()
+ {
+ return from c in this.customers
+ from o in c.Orders
+ select new
+ {
+ c.Name,
+ o.OrderID,
+ o.Total
+ };
+ }
+
+ public object SelectManyFollowedByOrderBy()
+ {
+ return from c in this.customers
+ from o in c.Orders
+ orderby o.Total descending
+ select new
+ {
+ c.Name,
+ o.OrderID,
+ o.Total
+ };
+ }
+
+ public object MultipleSelectManyFollowedBySelect()
+ {
+ return from c in this.customers
+ from o in c.Orders
+ from d in o.Details
+ select new
+ {
+ c.Name,
+ o.OrderID,
+ d.Quantity
+ };
+ }
+
+ public object MultipleSelectManyFollowedByLet()
+ {
+ return from c in this.customers
+ from o in c.Orders
+ from d in o.Details
+ let x = d.Quantity * d.UnitPrice
+ select new
+ {
+ c.Name,
+ o.OrderID,
+ x
+ };
+ }
+
+ public object FromLetWhereSelect()
+ {
+ return from o in this.orders
+ let t = o.Details.Sum((QueryExpressions.OrderDetail d) => d.UnitPrice * d.Quantity)
+ where t >= 1000m
+ select new
+ {
+ OrderID = o.OrderID,
+ Total = t
+ };
+ }
+
+ public object MultipleLet()
+ {
+ return from a in this.customers
+ let b = a.Country
+ let c = a.Name
+ select b + c;
+ }
+
+ public object Join()
+ {
+ return from c in this.customers
+ join o in this.orders on c.CustomerID equals o.CustomerID
+ select new
+ {
+ c.Name,
+ o.OrderDate,
+ o.Total
+ };
+ }
+
+ public object JoinInto()
+ {
+ return from c in this.customers
+ join o in this.orders on c.CustomerID equals o.CustomerID into co
+ let n = co.Count<QueryExpressions.Order>()
+ where n >= 10
+ select new
+ {
+ Name = c.Name,
+ OrderCount = n
+ };
+ }
+
+ public object OrderBy()
+ {
+ return from o in this.orders
+ orderby o.Customer.Name, o.Total descending
+ select o;
+ }
+
+ public object GroupBy()
+ {
+ return from c in this.customers
+ group c.Name by c.Country;
+ }
+
+ public object ExplicitType()
+ {
+ return from QueryExpressions.Customer c in this.customers
+ where c.City == "London"
+ select c;
+ }
+
+ public object QueryContinuation()
+ {
+ return from c in this.customers
+ group c by c.Country into g
+ select new
+ {
+ Country = g.Key,
+ CustCount = g.Count<QueryExpressions.Customer>()
+ };
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/Switch.cs b/ICSharpCode.Decompiler/Tests/Switch.cs
new file mode 100644
index 00000000..4a20a639
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/Switch.cs
@@ -0,0 +1,89 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+
+public static class Switch
+{
+ public static string ShortSwitchOverString(string text)
+ {
+ switch (text) {
+ case "First case":
+ return "Text";
+ default:
+ return "Default";
+ }
+ }
+
+ public static string SwitchOverString1(string text)
+ {
+ switch (text)
+ {
+ case "First case":
+ return "Text1";
+ case "Second case":
+ case "2nd case":
+ return "Text2";
+ case "Third case":
+ return "Text3";
+ case "Fourth case":
+ return "Text4";
+ case "Fifth case":
+ return "Text5";
+ case "Sixth case":
+ return "Text6";
+ case null:
+ return null;
+ default:
+ return "Default";
+ }
+ }
+
+ public static string SwitchOverString2()
+ {
+ switch (Environment.UserName)
+ {
+ case "First case":
+ return "Text1";
+ case "Second case":
+ return "Text2";
+ case "Third case":
+ return "Text3";
+ case "Fourth case":
+ return "Text4";
+ case "Fifth case":
+ return "Text5";
+ case "Sixth case":
+ return "Text6";
+ default:
+ return "Default";
+ }
+ }
+
+ public static string SwitchOverBool(bool b)
+ {
+ switch (b) {
+ case true:
+ return bool.TrueString;
+ case false:
+ return bool.FalseString;
+ default:
+ return null;
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/TestRunner.cs b/ICSharpCode.Decompiler/Tests/TestRunner.cs
new file mode 100644
index 00000000..215725b0
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/TestRunner.cs
@@ -0,0 +1,198 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.CodeDom.Compiler;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using DiffLib;
+using ICSharpCode.Decompiler.Ast;
+using ICSharpCode.Decompiler.Tests.Helpers;
+using Microsoft.CSharp;
+using Mono.Cecil;
+using NUnit.Framework;
+
+namespace ICSharpCode.Decompiler.Tests
+{
+ [TestFixture]
+ public class TestRunner : DecompilerTestBase
+ {
+ [Test]
+ public void Async()
+ {
+ TestFile(@"..\..\Tests\Async.cs");
+ }
+
+ [Test, Ignore("disambiguating overloads is not yet implemented")]
+ public void CallOverloadedMethod()
+ {
+ TestFile(@"..\..\Tests\CallOverloadedMethod.cs");
+ }
+
+ [Test, Ignore("unncessary primitive casts")]
+ public void CheckedUnchecked()
+ {
+ TestFile(@"..\..\Tests\CheckedUnchecked.cs");
+ }
+
+ [Test, Ignore("Missing cast on null")]
+ public void DelegateConstruction()
+ {
+ TestFile(@"..\..\Tests\DelegateConstruction.cs");
+ }
+
+ [Test, Ignore("Not yet implemented")]
+ public void ExpressionTrees()
+ {
+ TestFile(@"..\..\Tests\ExpressionTrees.cs");
+ }
+
+ [Test]
+ public void ExceptionHandling()
+ {
+ AssertRoundtripCode(@"..\..\Tests\ExceptionHandling.cs", optimize: false);
+ AssertRoundtripCode(@"..\..\Tests\ExceptionHandling.cs", optimize: false);
+ }
+
+ [Test]
+ public void Generics()
+ {
+ TestFile(@"..\..\Tests\Generics.cs");
+ }
+
+ [Test]
+ public void CustomShortCircuitOperators()
+ {
+ TestFile(@"..\..\Tests\CustomShortCircuitOperators.cs");
+ }
+
+ [Test]
+ public void ControlFlowWithDebug()
+ {
+ AssertRoundtripCode(@"..\..\Tests\ControlFlow.cs", optimize: false, useDebug: true);
+ AssertRoundtripCode(@"..\..\Tests\ControlFlow.cs", optimize: false, useDebug: true);
+ }
+
+ [Test]
+ public void DoubleConstants()
+ {
+ TestFile(@"..\..\Tests\DoubleConstants.cs");
+ }
+
+ [Test]
+ public void IncrementDecrement()
+ {
+ TestFile(@"..\..\Tests\IncrementDecrement.cs");
+ }
+
+ [Test]
+ public void InitializerTests()
+ {
+ TestFile(@"..\..\Tests\InitializerTests.cs");
+ }
+
+ [Test]
+ public void LiftedOperators()
+ {
+ TestFile(@"..\..\Tests\LiftedOperators.cs");
+ }
+
+ [Test]
+ public void Lock()
+ {
+ //TestFile(@"..\..\Tests\Lock.cs", compilerVersion: 2);
+ TestFile(@"..\..\Tests\Lock.cs", compilerVersion: 4);
+ }
+
+ [Test]
+ public void Loops()
+ {
+ TestFile(@"..\..\Tests\Loops.cs");
+ }
+
+ [Test]
+ public void MultidimensionalArray()
+ {
+ TestFile(@"..\..\Tests\MultidimensionalArray.cs");
+ }
+
+ [Test]
+ public void PInvoke()
+ {
+ TestFile(@"..\..\Tests\PInvoke.cs");
+ }
+
+ [Test]
+ public void PropertiesAndEvents()
+ {
+ TestFile(@"..\..\Tests\PropertiesAndEvents.cs");
+ }
+
+ [Test]
+ public void QueryExpressions()
+ {
+ TestFile(@"..\..\Tests\QueryExpressions.cs");
+ }
+
+ [Test, Ignore("switch transform doesn't recreate the exact original switch")]
+ public void Switch()
+ {
+ TestFile(@"..\..\Tests\Switch.cs");
+ }
+
+ [Test]
+ public void UndocumentedExpressions()
+ {
+ TestFile(@"..\..\Tests\UndocumentedExpressions.cs");
+ }
+
+ [Test, Ignore("has incorrect casts to IntPtr")]
+ public void UnsafeCode()
+ {
+ TestFile(@"..\..\Tests\UnsafeCode.cs");
+ }
+
+ [Test]
+ public void ValueTypes()
+ {
+ TestFile(@"..\..\Tests\ValueTypes.cs");
+ }
+
+ [Test, Ignore("Redundant yield break; not removed")]
+ public void YieldReturn()
+ {
+ TestFile(@"..\..\Tests\YieldReturn.cs");
+ }
+
+ [Test]
+ public void TypeAnalysis()
+ {
+ TestFile(@"..\..\Tests\TypeAnalysisTests.cs");
+ }
+
+ static void TestFile(string fileName, bool useDebug = false, int compilerVersion = 4)
+ {
+ AssertRoundtripCode(fileName, optimize: false, useDebug: useDebug, compilerVersion: compilerVersion);
+ AssertRoundtripCode(fileName, optimize: true, useDebug: useDebug, compilerVersion: compilerVersion);
+ AssertRoundtripCode(fileName, optimize: false, useDebug: useDebug, compilerVersion: compilerVersion);
+ AssertRoundtripCode(fileName, optimize: true, useDebug: useDebug, compilerVersion: compilerVersion);
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/TypeAnalysisTests.cs b/ICSharpCode.Decompiler/Tests/TypeAnalysisTests.cs
new file mode 100644
index 00000000..760bb862
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/TypeAnalysisTests.cs
@@ -0,0 +1,153 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+
+public class TypeAnalysisTests
+{
+ public byte SubtractFrom256(byte b)
+ {
+ return (byte)(256 - (int)b);
+ }
+
+ #region Shift
+ public int LShiftInteger(int num1, int num2)
+ {
+ return num1 << num2;
+ }
+
+ public uint LShiftUnsignedInteger(uint num1, uint num2)
+ {
+ return num1 << (int)num2;
+ }
+
+ public long LShiftLong(long num1, long num2)
+ {
+ return num1 << (int)num2;
+ }
+
+ public ulong LShiftUnsignedLong(ulong num1, ulong num2)
+ {
+ return num1 << (int)num2;
+ }
+
+ public int RShiftInteger(int num1, int num2)
+ {
+ return num1 >> num2;
+ }
+
+ public uint RShiftUnsignedInteger(uint num1, int num2)
+ {
+ return num1 >> num2;
+ }
+
+ public long RShiftLong(long num1, long num2)
+ {
+ return num1 >> (int)num2;
+ }
+
+ public ulong RShiftUnsignedLong(ulong num1, ulong num2)
+ {
+ return num1 >> (int)num2;
+ }
+
+ public int ShiftByte(byte num)
+ {
+ return (int)num << 8;
+ }
+
+ public int RShiftByte(byte num)
+ {
+ return num >> 8;
+ }
+
+ public uint RShiftByteWithZeroExtension(byte num)
+ {
+ return (uint)num >> 8;
+ }
+
+ public int RShiftByteAsSByte(byte num)
+ {
+ return (sbyte)num >> 8;
+ }
+
+ public int RShiftSByte(sbyte num)
+ {
+ return num >> 8;
+ }
+
+ public uint RShiftSByteWithZeroExtension(sbyte num)
+ {
+ return (uint)num >> 8;
+ }
+
+ public int RShiftSByteAsByte(sbyte num)
+ {
+ return (byte)num >> 8;
+ }
+ #endregion
+
+ public int GetHashCode(long num)
+ {
+ return (int)num ^ (int)(num >> 32);
+ }
+
+ public void TernaryOp(Random a, Random b, bool c)
+ {
+ if ((c ? a : b) == null)
+ {
+ Console.WriteLine();
+ }
+ }
+
+ public void OperatorIs(object o)
+ {
+ Console.WriteLine(o is Random);
+ Console.WriteLine(!(o is Random));
+ }
+
+ public byte[] CreateArrayWithInt(int length)
+ {
+ return new byte[length];
+ }
+
+ public byte[] CreateArrayWithLong(long length)
+ {
+ return new byte[length];
+ }
+
+ public byte[] CreateArrayWithUInt(uint length)
+ {
+ return new byte[length];
+ }
+
+ public byte[] CreateArrayWithULong(ulong length)
+ {
+ return new byte[length];
+ }
+
+ public StringComparison EnumDiffNumber(StringComparison data)
+ {
+ return data - 1;
+ }
+
+ public int EnumDiff(StringComparison a, StringComparison b)
+ {
+ return Math.Abs(a - b);
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/Types/EnumTests.cs b/ICSharpCode.Decompiler/Tests/Types/EnumTests.cs
new file mode 100644
index 00000000..fb48d016
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/Types/EnumTests.cs
@@ -0,0 +1,18 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using NUnit.Framework;
+
+namespace ICSharpCode.Decompiler.Tests.Types
+{
+ [TestFixture]
+ public class EnumTests : DecompilerTestBase
+ {
+ [Test]
+ public void EnumSamples()
+ {
+ ValidateFileRoundtrip(@"Types\S_EnumSamples.cs");
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/Types/S_EnumSamples.cs b/ICSharpCode.Decompiler/Tests/Types/S_EnumSamples.cs
new file mode 100644
index 00000000..3149f575
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/Types/S_EnumSamples.cs
@@ -0,0 +1,129 @@
+// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+//$CS
+using System;
+//$CE
+
+//$$ SingleValue
+public class TS_SingleValue
+{
+ public AttributeTargets Method()
+ {
+ return AttributeTargets.Class;
+ }
+}
+//$$ TwoValuesOr
+public class TS_TwoValuesOr
+{
+ public AttributeTargets Method()
+ {
+ return AttributeTargets.Class | AttributeTargets.Method;
+ }
+}
+//$$ ThreeValuesOr
+public class TS_ThreeValuesOr
+{
+ public AttributeTargets Method()
+ {
+ return AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Parameter;
+ }
+}
+//$$ UnknownNumericValue
+public class TS_UnknownNumericValue
+{
+ public AttributeTargets Method()
+ {
+ return (AttributeTargets)1000000;
+ }
+}
+//$$ AllValue
+public class TS_AllValue
+{
+ public AttributeTargets Method()
+ {
+ return AttributeTargets.All;
+ }
+}
+//$$ ZeroValue
+public class TS_ZeroValue
+{
+ public AttributeTargets Method()
+ {
+ return (AttributeTargets)0;
+ }
+}
+//$$ PreservingTypeWhenBoxed
+public class TS_PreservingTypeWhenBoxed
+{
+ public object Method()
+ {
+ return AttributeTargets.Delegate;
+ }
+}
+//$$ PreservingTypeWhenBoxedTwoEnum
+public class TS_PreservingTypeWhenBoxedTwoEnum
+{
+ public object Method()
+ {
+ return AttributeTargets.Class | AttributeTargets.Delegate;
+ }
+}
+//$$ DeclarationSimpleEnum
+public enum TS_DeclarationSimpleEnum
+{
+ Item1,
+ Item2
+}
+//$$ DeclarationLongBasedEnum
+public enum TS_DeclarationLongBasedEnum : long
+{
+ Item1,
+ Item2
+}
+//$$ DeclarationLongWithInitializers
+public enum TS_DeclarationLongWithInitializers : long
+{
+ Item1,
+ Item2 = 20L,
+ Item3
+}
+//$$ DeclarationShortWithInitializers
+public enum TS_DeclarationShortWithInitializers : short
+{
+ Item1,
+ Item2 = 20,
+ Item3
+}
+//$$ DeclarationByteWithInitializers
+public enum TS_DeclarationByteWithInitializers : byte
+{
+ Item1,
+ Item2 = 20,
+ Item3
+}
+//$$ DeclarationFlags
+[Flags]
+public enum TS_DeclarationFlags
+{
+ None = 0,
+ Item1 = 1,
+ Item2 = 2,
+ Item3 = 4,
+ All = 7
+}
diff --git a/ICSharpCode.Decompiler/Tests/Types/S_TypeDeclarations.cs b/ICSharpCode.Decompiler/Tests/Types/S_TypeDeclarations.cs
new file mode 100644
index 00000000..99bf4279
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/Types/S_TypeDeclarations.cs
@@ -0,0 +1,17 @@
+using System;
+
+namespace ClassMultiInterface
+{
+ public interface IA
+ {
+ }
+ public interface IA2 : IA
+ {
+ }
+ public interface IB
+ {
+ }
+ public class C : IA2, IB
+ {
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/Types/S_TypeMemberDeclarations.cs b/ICSharpCode.Decompiler/Tests/Types/S_TypeMemberDeclarations.cs
new file mode 100644
index 00000000..4a85b9f8
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/Types/S_TypeMemberDeclarations.cs
@@ -0,0 +1,1138 @@
+// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+//$CS
+using System;
+//$CE
+
+//$$ IndexerWithGetOnly
+namespace IndexerWithGetOnly
+{
+ public class MyClass
+ {
+ public int this[int i]
+ {
+ get
+ {
+ return i;
+ }
+ }
+ }
+}
+//$$ IndexerWithSetOnly
+namespace IndexerWithSetOnly
+{
+ public class MyClass
+ {
+ public int this[int i]
+ {
+ set
+ {
+ }
+ }
+ }
+}
+//$$ IndexerWithMoreParameters
+namespace IndexerWithMoreParameters
+{
+ public class MyClass
+ {
+ public int this[int i, string s, Type t]
+ {
+ get
+ {
+ return 0;
+ }
+ }
+ }
+}
+//$$ IndexerInGenericClass
+namespace IndexerInGenericClass
+{
+ public class MyClass<T>
+ {
+ public int this[T t]
+ {
+ get
+ {
+ return 0;
+ }
+ }
+ }
+}
+//$$ OverloadedIndexer
+namespace OverloadedIndexer
+{
+ public class MyClass
+ {
+ public int this[int t]
+ {
+ get
+ {
+ return 0;
+ }
+ }
+ public int this[string s]
+ {
+ get
+ {
+ return 0;
+ }
+ set
+ {
+ Console.WriteLine(value + " " + s);
+ }
+ }
+ }
+}
+//$$ IndexerInInterface
+namespace IndexerInInterface
+{
+ public interface IInterface
+ {
+ int this[string s, string s2]
+ {
+ set;
+ }
+ }
+}
+//$$ IndexerInterfaceExplicitImplementation
+namespace IndexerInterfaceExplicitImplementation
+{
+ public interface IMyInterface
+ {
+ int this[string s]
+ {
+ get;
+ }
+ }
+ public class MyClass : IMyInterface
+ {
+ int IMyInterface.this[string s]
+ {
+ get
+ {
+ return 3;
+ }
+ }
+ }
+}
+//$$ IndexerInterfaceImplementation
+namespace IndexerInterfaceImplementation
+{
+ public interface IMyInterface
+ {
+ int this[string s]
+ {
+ get;
+ }
+ }
+ public class MyClass : IMyInterface
+ {
+ public int this[string s]
+ {
+ get
+ {
+ return 3;
+ }
+ }
+ }
+}
+//$$ IndexerAbstract
+namespace IndexerAbstract
+{
+ public abstract class MyClass
+ {
+ public abstract int this[string s, string s2]
+ {
+ set;
+ }
+ protected abstract string this[int index]
+ {
+ get;
+ }
+ }
+}
+//$$ MethodExplicit
+namespace MethodExplicit
+{
+ public interface IMyInterface
+ {
+ void MyMethod();
+ }
+ public class MyClass : IMyInterface
+ {
+ void IMyInterface.MyMethod()
+ {
+ }
+ }
+}
+//$$ MethodFromInterfaceVirtual
+namespace MethodFromInterfaceVirtual
+{
+ public interface IMyInterface
+ {
+ void MyMethod();
+ }
+ public class MyClass : IMyInterface
+ {
+ public virtual void MyMethod()
+ {
+ }
+ }
+}
+//$$ MethodFromInterface
+namespace MethodFromInterface
+{
+ public interface IMyInterface
+ {
+ void MyMethod();
+ }
+ public class MyClass : IMyInterface
+ {
+ public void MyMethod()
+ {
+ }
+ }
+}
+//$$ MethodFromInterfaceAbstract
+namespace MethodFromInterfaceAbstract
+{
+ public interface IMyInterface
+ {
+ void MyMethod();
+ }
+ public abstract class MyClass : IMyInterface
+ {
+ public abstract void MyMethod();
+ }
+}
+//$$ PropertyInterface
+namespace PropertyInterface
+{
+ public interface IMyInterface
+ {
+ int MyProperty
+ {
+ get;
+ set;
+ }
+ }
+}
+//$$ PropertyInterfaceExplicitImplementation
+namespace PropertyInterfaceExplicitImplementation
+{
+ public interface IMyInterface
+ {
+ int MyProperty
+ {
+ get;
+ set;
+ }
+ }
+ public class MyClass : IMyInterface
+ {
+ int IMyInterface.MyProperty
+ {
+ get
+ {
+ return 0;
+ }
+ set
+ {
+ }
+ }
+ }
+}
+//$$ PropertyInterfaceImplementation
+namespace PropertyInterfaceImplementation
+{
+ public interface IMyInterface
+ {
+ int MyProperty
+ {
+ get;
+ set;
+ }
+ }
+ public class MyClass : IMyInterface
+ {
+ public int MyProperty
+ {
+ get
+ {
+ return 0;
+ }
+ set
+ {
+ }
+ }
+ }
+}
+//$$ PropertyPrivateGetPublicSet
+namespace PropertyPrivateGetPublicSet
+{
+ public class MyClass
+ {
+ public int MyProperty
+ {
+ private get
+ {
+ return 3;
+ }
+ set
+ {
+ }
+ }
+ }
+}
+//$$ PropertyPublicGetProtectedSet
+namespace PropertyPublicGetProtectedSet
+{
+ public class MyClass
+ {
+ public int MyProperty
+ {
+ get
+ {
+ return 3;
+ }
+ protected set
+ {
+ }
+ }
+ }
+}
+//$$ PropertyOverrideDefaultAccessorOnly
+namespace PropertyOverrideDefaultAccessorOnly
+{
+ public class MyClass
+ {
+ public virtual int MyProperty
+ {
+ get
+ {
+ return 3;
+ }
+ protected set
+ {
+ }
+ }
+ }
+ public class Derived : MyClass
+ {
+ public override int MyProperty
+ {
+ get
+ {
+ return 4;
+ }
+ }
+ }
+}
+//$$ PropertyOverrideRestrictedAccessorOnly
+namespace PropertyOverrideRestrictedAccessorOnly
+{
+ public class MyClass
+ {
+ public virtual int MyProperty
+ {
+ get
+ {
+ return 3;
+ }
+ protected set
+ {
+ }
+ }
+ }
+ public class Derived : MyClass
+ {
+ public override int MyProperty
+ {
+ protected set
+ {
+ }
+ }
+ }
+}
+//$$ PropertyOverrideOneAccessor
+namespace PropertyOverrideOneAccessor
+{
+ public class MyClass
+ {
+ protected internal virtual int MyProperty
+ {
+ get
+ {
+ return 3;
+ }
+ protected set
+ {
+ }
+ }
+ }
+ public class DerivedNew : MyClass
+ {
+ public new virtual int MyProperty
+ {
+ set
+ {
+ }
+ }
+ }
+ public class DerivedOverride : DerivedNew
+ {
+ public override int MyProperty
+ {
+ set
+ {
+ }
+ }
+ }
+}
+//$$ IndexerOverrideRestrictedAccessorOnly
+namespace IndexerOverrideRestrictedAccessorOnly
+{
+ public class MyClass
+ {
+ public virtual int this[string s]
+ {
+ get
+ {
+ return 3;
+ }
+ protected set
+ {
+ }
+ }
+ protected internal virtual int this[int i]
+ {
+ protected get
+ {
+ return 2;
+ }
+ set
+ {
+ }
+ }
+ }
+ public class Derived : MyClass
+ {
+ protected internal override int this[int i]
+ {
+ protected get
+ {
+ return 4;
+ }
+ }
+ }
+}
+//$$ HideProperty
+namespace HideProperty
+{
+ public class A
+ {
+ public virtual int P
+ {
+ get
+ {
+ return 0;
+ }
+ set
+ {
+ }
+ }
+ }
+ public class B : A
+ {
+ private new int P
+ {
+ get
+ {
+ return 0;
+ }
+ set
+ {
+ }
+ }
+ }
+ public class C : B
+ {
+ public override int P
+ {
+ set
+ {
+ }
+ }
+ }
+}
+//$$ HideMembers
+namespace HideMembers
+{
+ public class A
+ {
+ public int F;
+ public int Prop
+ {
+ get
+ {
+ return 3;
+ }
+ }
+ public int G
+ {
+ get
+ {
+ return 3;
+ }
+ }
+ }
+ public class B : A
+ {
+ public new int F
+ {
+ get
+ {
+ return 3;
+ }
+ }
+ public new string Prop
+ {
+ get
+ {
+ return "a";
+ }
+ }
+ }
+ public class C : A
+ {
+ public new int G;
+ }
+ public class D : A
+ {
+ public new void F()
+ {
+ }
+ }
+ public class D1 : D
+ {
+ public new int F;
+ }
+ public class E : A
+ {
+ private new class F
+ {
+ }
+ }
+}
+//$$ HideMembers2
+namespace HideMembers2
+{
+ public class G
+ {
+ public int Item
+ {
+ get
+ {
+ return 1;
+ }
+ }
+ }
+ public class G2 : G
+ {
+ public int this[int i]
+ {
+ get
+ {
+ return 2;
+ }
+ }
+ }
+ public class G3 : G2
+ {
+ public new int Item
+ {
+ get
+ {
+ return 4;
+ }
+ }
+ }
+ public class H
+ {
+ public int this[int j]
+ {
+ get
+ {
+ return 0;
+ }
+ }
+ }
+ public class H2 : H
+ {
+ public int Item
+ {
+ get
+ {
+ return 2;
+ }
+ }
+ }
+ public class H3 : H2
+ {
+ public new string this[int j]
+ {
+ get
+ {
+ return null;
+ }
+ }
+ }
+}
+//$$ HideMembers2a
+namespace HideMembers2a
+{
+ public interface IA
+ {
+ int this[int i]
+ {
+ get;
+ }
+ }
+ public class A : IA
+ {
+ int IA.this[int i]
+ {
+ get
+ {
+ throw new NotImplementedException();
+ }
+ }
+ }
+ public class A1 : A
+ {
+ public int this[int i]
+ {
+ get
+ {
+ return 3;
+ }
+ }
+ }
+}
+//$$ HideMembers3
+namespace HideMembers3
+{
+ public class G<T>
+ {
+ public void M1(T p)
+ {
+ }
+ public int M2(int t)
+ {
+ return 3;
+ }
+ }
+ public class G1<T> : G<int>
+ {
+ public new int M1(int i)
+ {
+ return 0;
+ }
+ public int M2(T i)
+ {
+ return 2;
+ }
+ }
+ public class G2<T> : G<int>
+ {
+ public int M1(T p)
+ {
+ return 4;
+ }
+ }
+ public class J
+ {
+ public int P
+ {
+ get
+ {
+ return 2;
+ }
+ }
+ }
+ public class J2 : J
+ {
+#pragma warning disable 0108 // Deliberate bad code for test case
+ public int get_P;
+#pragma warning restore 0108
+ }
+}
+//$$ HideMembers4
+namespace HideMembers4
+{
+ public class A
+ {
+ public void M<T>(T t)
+ {
+ }
+ }
+ public class A1 : A
+ {
+ public new void M<K>(K t)
+ {
+ }
+ public void M(int t)
+ {
+ }
+ }
+ public class B
+ {
+ public void M<T>()
+ {
+ }
+ public void M1<T>()
+ {
+ }
+ public void M2<T>(T t)
+ {
+ }
+ }
+ public class B1 : B
+ {
+ public void M<T1, T2>()
+ {
+ }
+ public new void M1<R>()
+ {
+ }
+ public new void M2<R>(R r)
+ {
+ }
+ }
+ public class C<T>
+ {
+ public void M<TT>(T t)
+ {
+ }
+ }
+ public class C1<K> : C<K>
+ {
+ public void M<TT>(TT t)
+ {
+ }
+ }
+}
+//$$ HideMembers5
+namespace HideMembers5
+{
+ public class A
+ {
+ public void M(int t)
+ {
+ }
+ }
+ public class A1 : A
+ {
+ public void M(ref int t)
+ {
+ }
+ }
+ public class B
+ {
+ public void M(ref int l)
+ {
+ }
+ }
+ public class B1 : B
+ {
+ public void M(out int l)
+ {
+ l = 2;
+ }
+ public void M(ref long l)
+ {
+ }
+ }
+}
+//$$ HideMemberSkipNotVisible
+namespace HideMemberSkipNotVisible
+{
+ public class A
+ {
+ protected int F;
+ protected string P
+ {
+ get
+ {
+ return null;
+ }
+ }
+ }
+ public class B : A
+ {
+ private new string F;
+ private new int P
+ {
+ set
+ {
+ }
+ }
+ }
+}
+//$$ HideNestedClass
+namespace HideNestedClass
+{
+ public class A
+ {
+ public class N1
+ {
+ }
+ protected class N2
+ {
+ }
+ private class N3
+ {
+ }
+ internal class N4
+ {
+ }
+ protected internal class N5
+ {
+ }
+ }
+ public class B : A
+ {
+ public new int N1;
+ public new int N2;
+ public int N3;
+ public new int N4;
+ public new int N5;
+ }
+}
+//$$ HidePropertyReservedMethod
+namespace HidePropertyReservedMethod
+{
+ public class A
+ {
+ public int P
+ {
+ get
+ {
+ return 1;
+ }
+ }
+ }
+ public class B : A
+ {
+ public int get_P()
+ {
+ return 2;
+ }
+ public void set_P(int value)
+ {
+ }
+ }
+}
+//$$ HideIndexerDiffAccessor
+namespace HideIndexerDiffAccessor
+{
+ public class A
+ {
+ public int this[int i]
+ {
+ get
+ {
+ return 2;
+ }
+ }
+ }
+ public class B : A
+ {
+ public new int this[int j]
+ {
+ set
+ {
+ }
+ }
+ }
+}
+//$$ HideIndexerGeneric
+namespace HideIndexerGeneric
+{
+ public class A<T>
+ {
+ public virtual int this[T r]
+ {
+ get
+ {
+ return 0;
+ }
+ set
+ {
+ }
+ }
+ }
+ public class B : A<int>
+ {
+ private new int this[int k]
+ {
+ get
+ {
+ return 0;
+ }
+ set
+ {
+ }
+ }
+ }
+ public class C<T> : A<T>
+ {
+ public override int this[T s]
+ {
+ set
+ {
+ }
+ }
+ }
+ public class D<T> : C<T>
+ {
+ public new virtual int this[T s]
+ {
+ set
+ {
+ }
+ }
+ }
+}
+//$$ HideMethod
+namespace HideMethod
+{
+ public class A
+ {
+ public virtual void F()
+ {
+ }
+ }
+ public class B : A
+ {
+ private new void F()
+ {
+ base.F();
+ }
+ }
+ public class C : B
+ {
+ public override void F()
+ {
+ base.F();
+ }
+ }
+}
+//$$ HideMethodGeneric
+namespace HideMethodGeneric
+{
+ public class A<T>
+ {
+ public virtual void F(T s)
+ {
+ }
+ public new static bool Equals(object o1, object o2)
+ {
+ return true;
+ }
+ }
+ public class B : A<string>
+ {
+ private new void F(string k)
+ {
+ }
+ public void F(int i)
+ {
+ }
+ }
+ public class C<T> : A<T>
+ {
+ public override void F(T r)
+ {
+ }
+ public void G(T t)
+ {
+ }
+ }
+ public class D<T1> : C<T1>
+ {
+ public new virtual void F(T1 k)
+ {
+ }
+ public virtual void F<T2>(T2 k)
+ {
+ }
+ public virtual void G<T2>(T2 t)
+ {
+ }
+ }
+}
+//$$ HideMethodGenericSkipPrivate
+namespace HideMethodGenericSkipPrivate
+{
+ public class A<T>
+ {
+ public virtual void F(T t)
+ {
+ }
+ }
+ public class B<T> : A<T>
+ {
+ private new void F(T t)
+ {
+ }
+ private void K()
+ {
+ }
+ }
+ public class C<T> : B<T>
+ {
+ public override void F(T tt)
+ {
+ }
+ public void K()
+ {
+ }
+ }
+ public class D : B<int>
+ {
+ public override void F(int t)
+ {
+ }
+ }
+}
+//$$ HideMethodGeneric2
+namespace HideMethodGeneric2
+{
+ public class A
+ {
+ public virtual void F(int i)
+ {
+ }
+ public void K()
+ {
+ }
+ }
+ public class B<T> : A
+ {
+ protected virtual void F(T t)
+ {
+ }
+ public void K<T2>()
+ {
+ }
+ }
+ public class C : B<int>
+ {
+ protected override void F(int k)
+ {
+ }
+ public new void K<T3>()
+ {
+ }
+ }
+ public class D : B<string>
+ {
+ public override void F(int k)
+ {
+ }
+ public void L<T4>()
+ {
+ }
+ }
+ public class E<T>
+ {
+ public void M<T2>(T t, T2 t2)
+ {
+ }
+ }
+ public class F<T> : E<T>
+ {
+ public void M(T t1, T t2)
+ {
+ }
+ }
+}
+//$$ HideMethodDiffSignatures
+namespace HideMethodDiffSignatures
+{
+ public class C1<T>
+ {
+ public virtual void M(T arg)
+ {
+ }
+ }
+ public class C2<T1, T2> : C1<T2>
+ {
+ public new virtual void M(T2 arg)
+ {
+ }
+ }
+ public class C3 : C2<int, bool>
+ {
+ public new virtual void M(bool arg)
+ {
+ }
+ }
+}
+//$$ HideMethodStatic
+namespace HideMethodStatic
+{
+ public class A
+ {
+ public int N
+ {
+ get
+ {
+ return 0;
+ }
+ }
+ }
+ public class B
+ {
+ public int N()
+ {
+ return 0;
+ }
+ }
+}
+//$$ HideEvent
+namespace HideEvent
+{
+ public class A
+ {
+ public virtual event EventHandler E;
+ public event EventHandler F;
+ }
+ public class B : A
+ {
+ public new virtual event EventHandler E;
+ public new event EventHandler F;
+ }
+ public class C : B
+ {
+ public override event EventHandler E;
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/Types/TypeTests.cs b/ICSharpCode.Decompiler/Tests/Types/TypeTests.cs
new file mode 100644
index 00000000..3bb80ed8
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/Types/TypeTests.cs
@@ -0,0 +1,18 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using NUnit.Framework;
+
+namespace ICSharpCode.Decompiler.Tests.Types
+{
+ [TestFixture]
+ public class TypeTests : DecompilerTestBase
+ {
+ [Test]
+ public void TypeMemberDeclarations()
+ {
+ ValidateFileRoundtrip(@"Types\S_TypeMemberDeclarations.cs");
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/UndocumentedExpressions.cs b/ICSharpCode.Decompiler/Tests/UndocumentedExpressions.cs
new file mode 100644
index 00000000..80f5b037
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/UndocumentedExpressions.cs
@@ -0,0 +1,41 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+
+public class UndocumentedExpressions
+{
+ public static int GetArgCount(__arglist)
+ {
+ ArgIterator argIterator = new ArgIterator(__arglist);
+ return argIterator.GetRemainingCount();
+ }
+
+ public static void MakeTypedRef(object o)
+ {
+ TypedReference tr = __makeref(o);
+ UndocumentedExpressions.AcceptTypedRef(tr);
+ }
+
+ private static void AcceptTypedRef(TypedReference tr)
+ {
+ Console.WriteLine("Value is: " + __refvalue(tr, object).ToString());
+ Console.WriteLine("Type is: " + __reftype(tr).Name);
+ __refvalue(tr, object) = 1;
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/UnsafeCode.cs b/ICSharpCode.Decompiler/Tests/UnsafeCode.cs
new file mode 100644
index 00000000..1a3bd6a0
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/UnsafeCode.cs
@@ -0,0 +1,145 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+
+public class UnsafeCode
+{
+ public unsafe int* NullPointer
+ {
+ get
+ {
+ return null;
+ }
+ }
+
+ public unsafe long ConvertDoubleToLong(double d)
+ {
+ return *(long*)(&d);
+ }
+
+ public unsafe double ConvertLongToDouble(long d)
+ {
+ return *(double*)(&d);
+ }
+
+ public unsafe int ConvertFloatToInt(float d)
+ {
+ return *(int*)(&d);
+ }
+
+ public unsafe float ConvertIntToFloat(int d)
+ {
+ return *(float*)(&d);
+ }
+
+ public unsafe void PassRefParameterAsPointer(ref int p)
+ {
+ fixed (int* ptr = &p)
+ {
+ this.PassPointerAsRefParameter(ptr);
+ }
+ }
+
+ public unsafe void PassPointerAsRefParameter(int* p)
+ {
+ this.PassRefParameterAsPointer(ref *p);
+ }
+
+ public unsafe void AddressInMultiDimensionalArray(double[,] matrix)
+ {
+ fixed (double* ptr = &matrix[1, 2])
+ {
+ this.PointerReferenceExpression(ptr);
+ }
+ }
+
+ public unsafe void FixedStringAccess(string text)
+ {
+ fixed (char* ptr = text)
+ {
+ char* ptr2 = ptr;
+ while (*ptr2 != '\0')
+ {
+ *ptr2 = 'A';
+ ptr2++;
+ }
+ }
+ }
+
+ public unsafe void PutDoubleIntoLongArray1(long[] array, int index, double val)
+ {
+ fixed (long* ptr = array)
+ {
+ ((double*)ptr)[index] = val;
+ }
+ }
+
+ public unsafe void PutDoubleIntoLongArray2(long[] array, int index, double val)
+ {
+ fixed (long* ptr = &array[index])
+ {
+ *(double*)ptr = val;
+ }
+ }
+
+ public unsafe string PointerReferenceExpression(double* d)
+ {
+ return d->ToString();
+ }
+
+ public unsafe void FixMultipleStrings(string text)
+ {
+ fixed (char* ptr = text, userName = Environment.UserName, ptr2 = text)
+ {
+ *ptr = 'c';
+ *userName = 'd';
+ *ptr2 = 'e';
+ }
+ }
+
+ public unsafe string StackAlloc(int count)
+ {
+ char* ptr = stackalloc char[count];
+ for (int i = 0; i < count; i++)
+ {
+ ptr[i] = (char)i;
+ }
+ return this.PointerReferenceExpression((double*)ptr);
+ }
+
+ public unsafe int* PointerArithmetic(int* p)
+ {
+ return p + 2;
+ }
+
+ public unsafe byte* PointerArithmetic2(long* p, int y, int x)
+ {
+ return (byte*)p + (y * x);
+ }
+
+ public unsafe long* PointerArithmetic3(long* p)
+ {
+ return (long*)((byte*)p + 3);
+ }
+
+ unsafe ~UnsafeCode()
+ {
+ this.PassPointerAsRefParameter(this.NullPointer);
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/ValueTypes.cs b/ICSharpCode.Decompiler/Tests/ValueTypes.cs
new file mode 100644
index 00000000..1493cff4
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/ValueTypes.cs
@@ -0,0 +1,188 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+
+public static class ValueTypes
+{
+ public struct S
+ {
+ public int Field;
+
+ public S(int field)
+ {
+ this.Field = field;
+ }
+
+ public void SetField()
+ {
+ this.Field = 5;
+ }
+
+ public void MethodCalls()
+ {
+ this.SetField();
+ ValueTypes.S.Test(this);
+ ValueTypes.S.Test(ref this);
+ }
+
+ private static void Test(ValueTypes.S byVal)
+ {
+ }
+
+ private static void Test(ref ValueTypes.S byRef)
+ {
+ }
+ }
+
+ private static readonly ValueTypes.S ReadOnlyS = default(ValueTypes.S);
+ private static ValueTypes.S MutableS = default(ValueTypes.S);
+ private static volatile int VolatileInt;
+
+ public static void CallMethodViaField()
+ {
+ ValueTypes.ReadOnlyS.SetField();
+ ValueTypes.MutableS.SetField();
+ ValueTypes.S mutableS = ValueTypes.MutableS;
+ mutableS.SetField();
+ }
+
+ public static ValueTypes.S InitObj1()
+ {
+ ValueTypes.S result = default(ValueTypes.S);
+ ValueTypes.MakeArray();
+ return result;
+ }
+
+ public static ValueTypes.S InitObj2()
+ {
+ return default(ValueTypes.S);
+ }
+
+ public static void InitObj3(out ValueTypes.S p)
+ {
+ p = default(ValueTypes.S);
+ }
+
+ public static ValueTypes.S CallValueTypeCtor1()
+ {
+ return new ValueTypes.S(10);
+ }
+
+ public static ValueTypes.S CallValueTypeCtor2()
+ {
+ ValueTypes.S result = new ValueTypes.S(10);
+ return result;
+ }
+
+ public static ValueTypes.S Copy1(ValueTypes.S p)
+ {
+ return p;
+ }
+
+ public static ValueTypes.S Copy2(ref ValueTypes.S p)
+ {
+ return p;
+ }
+
+ public static void Copy3(ValueTypes.S p, out ValueTypes.S o)
+ {
+ o = p;
+ }
+
+ public static void Copy4(ref ValueTypes.S p, out ValueTypes.S o)
+ {
+ o = p;
+ }
+
+ public static void Copy4b(ref ValueTypes.S p, out ValueTypes.S o)
+ {
+ // test passing through by-ref arguments
+ ValueTypes.Copy4(ref p, out o);
+ }
+
+ public static void Issue56(int i, out string str)
+ {
+ str = "qq";
+ str += i.ToString();
+ }
+
+ public static void CopyAroundAndModifyField(ValueTypes.S s)
+ {
+ ValueTypes.S s2 = s;
+ s2.Field += 10;
+ s = s2;
+ }
+
+ private static int[] MakeArray()
+ {
+ return null;
+ }
+
+ public static void IncrementArrayLocation()
+ {
+ ValueTypes.MakeArray()[Environment.TickCount]++;
+ }
+
+ public static bool Is(object obj)
+ {
+ return obj is ValueTypes.S;
+ }
+
+ public static bool IsNullable(object obj)
+ {
+ return obj is ValueTypes.S?;
+ }
+
+ public static ValueTypes.S? As(object obj)
+ {
+ return obj as ValueTypes.S?;
+ }
+
+ public static ValueTypes.S OnlyChangeTheCopy(ValueTypes.S p)
+ {
+ ValueTypes.S s = p;
+ s.SetField();
+ return p;
+ }
+
+ public static void UseRefBoolInCondition(ref bool x)
+ {
+ if (x)
+ {
+ Console.WriteLine("true");
+ }
+ }
+
+ public static void CompareNotEqual0IsReallyNotEqual(IComparable<int> a)
+ {
+ if (a.CompareTo(0) != 0)
+ {
+ Console.WriteLine("true");
+ }
+ }
+
+ public static void CompareEqual0IsReallyEqual(IComparable<int> a)
+ {
+ if (a.CompareTo(0) == 0)
+ {
+ Console.WriteLine("true");
+ }
+ }
+
+}
diff --git a/ICSharpCode.Decompiler/Tests/YieldReturn.cs b/ICSharpCode.Decompiler/Tests/YieldReturn.cs
new file mode 100644
index 00000000..7546b194
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/YieldReturn.cs
@@ -0,0 +1,148 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+
+public static class YieldReturn
+{
+ public static IEnumerable<string> SimpleYieldReturn()
+ {
+ yield return "A";
+ yield return "B";
+ yield return "C";
+ }
+
+ public static IEnumerable<int> YieldReturnInLoop()
+ {
+ for (int i = 0; i < 100; i++) {
+ yield return i;
+ }
+ }
+
+ public static IEnumerable<int> YieldReturnWithTryFinally()
+ {
+ yield return 0;
+ try {
+ yield return 1;
+ } finally {
+ Console.WriteLine("Finally!");
+ }
+ yield return 2;
+ }
+
+ public static IEnumerable<int> YieldReturnInLock1(object o)
+ {
+ lock (o) {
+ yield return 1;
+ }
+ }
+
+ public static IEnumerable<int> YieldReturnInLock2(object o)
+ {
+ lock (o) {
+ yield return 1;
+ o = null;
+ yield return 2;
+ }
+ }
+
+ public static IEnumerable<string> YieldReturnWithNestedTryFinally(bool breakInMiddle)
+ {
+ Console.WriteLine("Start of method - 1");
+ yield return "Start of method";
+ Console.WriteLine("Start of method - 2");
+ try {
+ Console.WriteLine("Within outer try - 1");
+ yield return "Within outer try";
+ Console.WriteLine("Within outer try - 2");
+ try {
+ Console.WriteLine("Within inner try - 1");
+ yield return "Within inner try";
+ Console.WriteLine("Within inner try - 2");
+ if (breakInMiddle)
+ yield break;
+ Console.WriteLine("End of inner try - 1");
+ yield return "End of inner try";
+ Console.WriteLine("End of inner try - 2");
+ } finally {
+ Console.WriteLine("Inner Finally");
+ }
+ Console.WriteLine("End of outer try - 1");
+ yield return "End of outer try";
+ Console.WriteLine("End of outer try - 2");
+ } finally {
+ Console.WriteLine("Outer Finally");
+ }
+ Console.WriteLine("End of method - 1");
+ yield return "End of method";
+ Console.WriteLine("End of method - 2");
+ }
+
+ public static IEnumerable<string> YieldReturnWithTwoNonNestedFinallyBlocks(IEnumerable<string> input)
+ {
+ // outer try-finally block
+ foreach (string line in input) {
+ // nested try-finally block
+ try {
+ yield return line;
+ } finally {
+ Console.WriteLine("Processed " + line);
+ }
+ }
+ yield return "A";
+ yield return "B";
+ yield return "C";
+ yield return "D";
+ yield return "E";
+ yield return "F";
+ // outer try-finally block
+ foreach (string line in input)
+ yield return line.ToUpper();
+ }
+
+ public static IEnumerable<Func<string>> YieldReturnWithAnonymousMethods1(IEnumerable<string> input)
+ {
+ foreach (string line in input) {
+ yield return () => line;
+ }
+ }
+
+ public static IEnumerable<Func<string>> YieldReturnWithAnonymousMethods2(IEnumerable<string> input)
+ {
+ foreach (string line in input) {
+ string copy = line;
+ yield return () => copy;
+ }
+ }
+
+ public static IEnumerable<int> GetEvenNumbers(int n)
+ {
+ for (int i = 0; i < n; i++) {
+ if (i % 2 == 0)
+ yield return i;
+ }
+ }
+
+ public static IEnumerable<char> YieldChars()
+ {
+ yield return 'a';
+ yield return 'b';
+ yield return 'c';
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/packages.config b/ICSharpCode.Decompiler/Tests/packages.config
new file mode 100644
index 00000000..b6522ccd
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/packages.config
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+ <package id="DiffLib" version="1.0.0.55" />
+ <package id="ICSharpCode.NRefactory" version="5.5.1" targetFramework="net45" />
+ <package id="Mono.Cecil" version="0.9.5.4" targetFramework="net45" />
+</packages> \ No newline at end of file