mirror of
https://github.com/icsharpcode/ILSpy.git
synced 2026-10-12 02:15:58 +00:00
Add the unlanded remainder of the coverage-audit fixtures
The coverage audit's green tests landed on master as per-topic commits; this collects what remains from the exploration branch: failing Pretty cases documenting decompiler gaps (stackalloc initializers, attribute params, local-function optional/params parameters, async-foreach tuple element names, for-loop comma lists, char increment operators, string reference equality, nested await handlers, async-stream cancellation with await in finally, expression-tree member/list bindings, and friends) plus small green additions that never landed. Some cases are red by design; run before harvesting to see which gaps still exist. Assisted-by: Claude:claude-fable-5:Claude Code
This commit is contained in:
@@ -616,6 +616,32 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
|
||||
return $"val={await t,5:x} end";
|
||||
}
|
||||
#endif
|
||||
|
||||
public static async Task<int> MultiAwaitInExpression(Task<int> a, Task<int> b, Task<int> 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
|
||||
|
||||
@@ -61,5 +61,15 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
public async Task<int> SumNamedTupleElements(IAsyncEnumerable<(int A, string B)> items)
|
||||
{
|
||||
int sum = 0;
|
||||
await foreach (var item in items)
|
||||
{
|
||||
sum += item.A + item.B.Length;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,6 +114,36 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
|
||||
yield return 'a';
|
||||
yield return AsyncStreamColor.Green;
|
||||
}
|
||||
|
||||
public static async IAsyncEnumerable<int> 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<int> 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
|
||||
|
||||
@@ -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<int> span)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
|
||||
@@ -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<int> 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<T> GetAsyncEnumerator<T>(this CS9_ExtensionGetEnumerator.Generic<T> c)
|
||||
{
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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++;
|
||||
|
||||
@@ -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<T> : Attribute
|
||||
@@ -178,5 +185,13 @@ namespace CustomAttributes
|
||||
{
|
||||
}
|
||||
#endif
|
||||
[ParamsArray(1, 2, 3)]
|
||||
public static void UseParamsAttributeExpanded()
|
||||
{
|
||||
}
|
||||
[ParamsArray]
|
||||
public static void UseParamsAttributeEmpty()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -207,6 +207,13 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
|
||||
}
|
||||
}
|
||||
|
||||
internal class TypeWithNestedMembers
|
||||
{
|
||||
public SimpleType Nested = new SimpleType();
|
||||
|
||||
public List<int> List = new List<int>();
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 })
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<int> span = CreateWithoutCapture(ref value);
|
||||
if (b)
|
||||
{
|
||||
span = CreateAndCapture(ref value);
|
||||
}
|
||||
return span[0];
|
||||
}
|
||||
}
|
||||
|
||||
internal ref struct RefFields
|
||||
|
||||
@@ -354,6 +354,11 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
|
||||
M2<RefLocalsAndReturns>(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)
|
||||
{
|
||||
|
||||
@@ -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<char> text)
|
||||
{
|
||||
return text is "hello";
|
||||
}
|
||||
|
||||
public static bool OrPatternOverReadOnlySpanChar(ReadOnlySpan<char> text)
|
||||
{
|
||||
return text is "hello" or "hi";
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ROSLYN
|
||||
|
||||
@@ -200,5 +200,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public static int TernaryThrow(bool cond)
|
||||
{
|
||||
return cond ? 1 : throw new InvalidOperationException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user