diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Async.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Async.cs index 2c4e38545..99fa25ebe 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Async.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Async.cs @@ -616,6 +616,32 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty return $"val={await t,5:x} end"; } #endif + + public static async Task MultiAwaitInExpression(Task a, Task b, Task c) + { + return await a + await b * await c - await a; + } + +#if CS60 + public static async Task NestedAwaitHandlers(Task t) + { + try + { + await t; + } + catch (Exception ex) + { + try + { + await Task.Delay(ex.Message.Length); + } + finally + { + await Task.Yield(); + } + } + } +#endif } public struct AsyncInStruct diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/AsyncForeach.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/AsyncForeach.cs index 072854c80..1a1423649 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/AsyncForeach.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/AsyncForeach.cs @@ -61,5 +61,15 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty } return sum; } + + public async Task SumNamedTupleElements(IAsyncEnumerable<(int A, string B)> items) + { + int sum = 0; + await foreach (var item in items) + { + sum += item.A + item.B.Length; + } + return sum; + } } } diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/AsyncStreams.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/AsyncStreams.cs index 0cd334e4f..798b47794 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/AsyncStreams.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/AsyncStreams.cs @@ -114,6 +114,36 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty yield return 'a'; yield return AsyncStreamColor.Green; } + + public static async IAsyncEnumerable CancellationAndAwaitInFinally([EnumeratorCancellation] CancellationToken cancellationToken) + { + int handle = await OpenAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); + try + { + yield return handle; + await WorkAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); + } + finally + { + await CloseAsync(handle, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); + } + } + + private static async Task OpenAsync(CancellationToken ct) + { + await Task.Yield(); + return 1; + } + + private static async Task WorkAsync(CancellationToken ct) + { + await Task.Yield(); + } + + private static async Task CloseAsync(int h, CancellationToken ct) + { + await Task.Yield(); + } } public interface IAsyncStreamEntry diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CS73_StackAllocInitializers.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CS73_StackAllocInitializers.cs index 9485527df..0b935a160 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CS73_StackAllocInitializers.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CS73_StackAllocInitializers.cs @@ -128,6 +128,17 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty return UsePointer(ptr); } + public unsafe string SimpleStackAllocEnum() + { + DayOfWeek* ptr = stackalloc DayOfWeek[3] { + DayOfWeek.Monday, + DayOfWeek.Tuesday, + DayOfWeek.Friday + }; + Console.WriteLine(*ptr); + return UsePointer((byte*)ptr); + } + public unsafe string SimpleStackAllocChar() { char* ptr = stackalloc char[4] { '1', '2', '3', '4' }; @@ -373,6 +384,18 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty Console.WriteLine((stackalloc byte[3])[1]); } + public unsafe int PointerStackAllocSingleUse() + { + int* ptr = stackalloc int[4]; + return *ptr; + } + + public unsafe int PointerStackAllocInitializerSingleUse() + { + int* ptr = stackalloc int[3] { 7, 8, 9 }; + return *ptr; + } + public string UseSpan(Span span) { throw new NotImplementedException(); diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CS9_ExtensionGetEnumerator.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CS9_ExtensionGetEnumerator.cs index d72d8b38a..f0b7dd9df 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CS9_ExtensionGetEnumerator.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CS9_ExtensionGetEnumerator.cs @@ -1,6 +1,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Runtime.InteropServices; namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty { @@ -14,6 +15,21 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty { } + public class WithStructEnumerator + { + } + + [StructLayout(LayoutKind.Sequential, Size = 1)] + public struct StructEnumerator + { + public int Current => 0; + + public bool MoveNext() + { + return false; + } + } + public void Test(NonGeneric c) { foreach (object item in c) @@ -29,6 +45,14 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty Console.WriteLine(item); } } + + public void Test(WithStructEnumerator c) + { + foreach (int item in c) + { + Console.WriteLine(item); + } + } #if !NET40 public async void TestAsync(Generic c) { @@ -50,6 +74,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty { throw null; } + public static CS9_ExtensionGetEnumerator.StructEnumerator GetEnumerator(this CS9_ExtensionGetEnumerator.WithStructEnumerator c) + { + return default(CS9_ExtensionGetEnumerator.StructEnumerator); + } #if !NET40 public static IAsyncEnumerator GetAsyncEnumerator(this CS9_ExtensionGetEnumerator.Generic c) { diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CheckedUnchecked.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CheckedUnchecked.cs index 8e66733fb..d958ab0fd 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CheckedUnchecked.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CheckedUnchecked.cs @@ -130,5 +130,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty } } } + + public int HashCodeAccumulator(int type, string text) + { + int num = 1688038063; + num = num * -1521134295 + type.GetHashCode(); + return num * -1521134295 + text.GetHashCode(); + } } } diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.cs index 040474bcd..239bc36e1 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.cs @@ -411,6 +411,16 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty return a == 'A'; } + public void Char_Local_Add(char c) + { + c++; + Console.WriteLine(c++); + Console.WriteLine(++c); + c--; + Console.WriteLine(c--); + Console.WriteLine(--c); + } + public void Int32_Local_Add(int i) { i++; diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CustomAttributes.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CustomAttributes.cs index dd5ec6293..234b6c903 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CustomAttributes.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CustomAttributes.cs @@ -40,6 +40,13 @@ namespace CustomAttributes { } } + [AttributeUsage(AttributeTargets.All)] + public class ParamsArrayAttribute : Attribute + { + public ParamsArrayAttribute(params int[] values) + { + } + } #if CS110 [AttributeUsage(AttributeTargets.All, AllowMultiple = true)] public class GenericAttribute : Attribute @@ -178,5 +185,13 @@ namespace CustomAttributes { } #endif + [ParamsArray(1, 2, 3)] + public static void UseParamsAttributeExpanded() + { + } + [ParamsArray] + public static void UseParamsAttributeEmpty() + { + } } } diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/DynamicTests.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/DynamicTests.cs index 5de9db12a..63922a481 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/DynamicTests.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/DynamicTests.cs @@ -2,6 +2,9 @@ using System; #if CS120 using System.Collections.Generic; #endif +#if !NET40 +using System.Threading.Tasks; +#endif namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty { diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/ExpressionTrees.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/ExpressionTrees.cs index 99acb2186..a073d4d1a 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/ExpressionTrees.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/ExpressionTrees.cs @@ -207,6 +207,13 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty } } + internal class TypeWithNestedMembers + { + public SimpleType Nested = new SimpleType(); + + public List List = new List(); + } + internal class SimpleTypeWithMultipleCtors { public SimpleTypeWithMultipleCtors() @@ -955,6 +962,16 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty ToCode(null, (int a) => (short)a); } } + + public void MemberAndListBindings() + { + ToCode(null, () => new TypeWithNestedMembers { + Nested = { + Field = 2 + }, + List = { 1, 2 } + }); + } } internal static class Extensions diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/LocalFunctions.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/LocalFunctions.cs index e12420b35..17b10accc 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/LocalFunctions.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/LocalFunctions.cs @@ -697,6 +697,20 @@ namespace LocalFunctions } } + public static int LocalFunctionWithOptionalAndParams() + { + return Local(5) + Local(2, 3, 4); + +#if CS80 + static int Local(int x = 5, params int[] rest) +#else + int Local(int x = 5, params int[] rest) +#endif + { + return x + rest.Length; + } + } + public void WriteCapturedParameter(int i) { ParamWrite(); diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Loops.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Loops.cs index a0038f90f..458850357 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Loops.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Loops.cs @@ -1084,5 +1084,15 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty throw new NotImplementedException(); } } + + public static int ForWithCommaLists(int n) + { + int num = 0; + for (int i = 0, j = n; i < j; i++, j--) + { + num += i * j; + } + return num; + } } } diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/NullPropagation.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/NullPropagation.cs index aa834b0d1..66240f5d5 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/NullPropagation.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/NullPropagation.cs @@ -326,5 +326,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty return x?.ToString(); #endif } + + private bool TwoChainsInShortCircuitAnd(MyClass a, MyClass b) + { + return a?.Field?.IntVal > 0 && b?.Property?.Text?.Length == 3; + } } } diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/OptionalArguments.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/OptionalArguments.cs index b45e349b7..4ab0921ec 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/OptionalArguments.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/OptionalArguments.cs @@ -27,6 +27,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty { public delegate int D(int p = 10); + public delegate int ParamsDelegate(params int[] xs); + public enum MyEnum { A, @@ -329,6 +331,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty d(); d(42); } +#endif +#if CS130 + public static ParamsDelegate LambdaWithParamsArray() + { + return (params int[] xs) => xs.Length; + } #endif } } diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/PatternMatching.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/PatternMatching.cs index afed2791d..5eb10898b 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/PatternMatching.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/PatternMatching.cs @@ -33,6 +33,20 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public object Obj { get; set; } } +#if CS80 + public struct DeconstructablePoint + { + public int X; + public int Y; + + public void Deconstruct(out int x, out int y) + { + x = X; + y = Y; + } + } +#endif + public void SimpleTypePattern(object x) { if (x is string value) @@ -333,6 +347,18 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty } #if CS80 + public void PositionalPattern(object obj) + { + if (obj is DeconstructablePoint(0, var y)) + { + Console.WriteLine(y); + } + else + { + Console.WriteLine("no match"); + } + } + public void RecursivePattern_Type(object x) { if (x is X { Obj: string obj }) diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Records.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Records.cs index 1a88b0f4e..e020feacd 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Records.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Records.cs @@ -45,6 +45,13 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public string S = "abc"; } + public record FieldBeforeProperty(int ID, string Text) + { + public int Field; + + public int Property { get; set; } + } + public record Interface(int B) : IRecord; public interface IRecord diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/RefFields.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/RefFields.cs index 7bbb377a6..0308fd9ad 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/RefFields.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/RefFields.cs @@ -44,6 +44,28 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty span = ScopedSpan(span); OutSpan(out span); } + + public int ScopedRefLocal(bool b, ref int x) + { + int num = 42; + scoped ref int reference = ref x; + if (b) + { + reference = ref num; + } + return reference; + } + + public int ScopedRefStructLocal(bool b) + { + int value = 7; + scoped Span span = CreateWithoutCapture(ref value); + if (b) + { + span = CreateAndCapture(ref value); + } + return span[0]; + } } internal ref struct RefFields diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/RefLocalsAndReturns.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/RefLocalsAndReturns.cs index 9c14435cb..2072f7a16 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/RefLocalsAndReturns.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/RefLocalsAndReturns.cs @@ -354,6 +354,11 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty M2(this); } + public static void ConditionalRefInAssignmentTarget(bool b, int[] x, int[] y) + { + (b ? ref x[0] : ref y[0]) = 5; + } + #if CS120 public ref readonly int M(in int x) { diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.cs index a5e5a3bbb..e50eb93ad 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.cs @@ -544,6 +544,24 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty } } + public static string SwitchOverStringWithEmptyCase(string text) + { + Console.WriteLine("SwitchOverStringWithEmptyCase: " + text); + switch (text) + { + case "": + return "empty"; + case " ": + return "space"; + case null: + return "null"; + case "First case": + return "Text1"; + default: + return "Default"; + } + } + public static string SwitchOverString1(string text) { Console.WriteLine("SwitchOverString1: " + text); @@ -1744,6 +1762,16 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty return "Default"; } } + + public static bool IsPatternOverReadOnlySpanChar(ReadOnlySpan text) + { + return text is "hello"; + } + + public static bool OrPatternOverReadOnlySpanChar(ReadOnlySpan text) + { + return text is "hello" or "hi"; + } #endif #if ROSLYN diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/ThrowExpressions.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/ThrowExpressions.cs index a71a013e8..f541c25f5 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/ThrowExpressions.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/ThrowExpressions.cs @@ -200,5 +200,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty { } + + public static int TernaryThrow(bool cond) + { + return cond ? 1 : throw new InvalidOperationException(); + } } } diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.cs index a1359d0c4..c10a23ea8 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.cs @@ -344,5 +344,15 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty { return (int)a == 0; } + + public static bool ReferenceEqualityStrings(string a, string b) + { + return (object)a == (object)b; + } + + public static bool ReferenceInequalityStrings(string a, string b) + { + return (object)a != (object)b; + } } }