diff options
author | Jason Smith <jason.smith@xamarin.com> | 2016-03-22 13:02:25 -0700 |
---|---|---|
committer | Jason Smith <jason.smith@xamarin.com> | 2016-03-22 16:13:41 -0700 |
commit | 17fdde66d94155fc62a034fa6658995bef6fd6e5 (patch) | |
tree | b5e5073a2a7b15cdbe826faa5c763e270a505729 /ICSharpCode.Decompiler/Tests | |
download | xamarin-forms-17fdde66d94155fc62a034fa6658995bef6fd6e5.tar.gz xamarin-forms-17fdde66d94155fc62a034fa6658995bef6fd6e5.tar.bz2 xamarin-forms-17fdde66d94155fc62a034fa6658995bef6fd6e5.zip |
Initial import
Diffstat (limited to 'ICSharpCode.Decompiler/Tests')
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 |