Browse Source

Support recursive pattern for value types

pull/3049/head
Siegfried Pammer 2 years ago
parent
commit
8cb3a67c0c
  1. 65
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/PatternMatching.cs
  2. 2
      ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
  3. 2
      ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpOutputVisitor.cs
  4. 4
      ICSharpCode.Decompiler/IL/Transforms/PatternMatchingTransform.cs

65
ICSharpCode.Decompiler.Tests/TestCases/Pretty/PatternMatching.cs

@ -6,14 +6,17 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -6,14 +6,17 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{
public class X
{
public int A { get; set; }
public string B { get; set; }
public object C { get; set; }
public int I { get; set; }
public string Text { get; set; }
public object Obj { get; set; }
public S CustomStruct { get; set; }
}
public struct S
{
public int I;
public string Text { get; set; }
public object Obj { get; set; }
}
public void SimpleTypePattern(object x)
@ -318,9 +321,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -318,9 +321,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
#if CS80
public void RecursivePattern_Type(object x)
{
if (x is X { C: string c })
if (x is X { Obj: string obj })
{
Console.WriteLine("Test " + c);
Console.WriteLine("Test " + obj);
}
else
{
@ -330,7 +333,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -330,7 +333,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void RecursivePattern_Constant(object obj)
{
if (obj is X { C: null } x)
if (obj is X { Obj: null } x)
{
Console.WriteLine("Test " + x);
}
@ -342,7 +345,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -342,7 +345,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void RecursivePattern_StringConstant(object obj)
{
if (obj is X { B: "Hello" } x)
if (obj is X { Text: "Hello" } x)
{
Console.WriteLine("Test " + x);
}
@ -354,7 +357,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -354,7 +357,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void RecursivePattern_MultipleConstants(object obj)
{
if (obj is X { A: 42, B: "Hello" } x)
if (obj is X { I: 42, Text: "Hello" } x)
{
Console.WriteLine("Test " + x);
}
@ -378,9 +381,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -378,9 +381,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void RecursivePattern_MultipleConstantsMixedWithVar(object x)
{
if (x is X { A: 42, C: var c, B: "Hello" })
if (x is X { I: 42, Obj: var obj, Text: "Hello" })
{
Console.WriteLine("Test " + c);
Console.WriteLine("Test " + obj);
}
else
{
@ -390,7 +393,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -390,7 +393,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void RecursivePattern_NonTypePattern(object obj)
{
if (obj is X { A: 42, B: { Length: 0 } } x)
if (obj is X { I: 42, Text: { Length: 0 } } x)
{
Console.WriteLine("Test " + x);
}
@ -400,11 +403,47 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -400,11 +403,47 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
}
}
public void RecursivePatternValueType_NonTypePatternTwoProps(object obj)
{
if (obj is X { I: 42, CustomStruct: { I: 0, Text: "Test" } } x)
{
Console.WriteLine("Test " + x);
}
else
{
Console.WriteLine("not Test");
}
}
public void RecursivePattern_NonTypePatternNotNull(object o)
{
if (o is X { I: 42, Text: not null, Obj: var obj } x)
{
Console.WriteLine("Test " + x.I + " " + obj.GetType());
}
else
{
Console.WriteLine("not Test");
}
}
public void RecursivePattern_VarLengthPattern(object obj)
{
if (obj is X { A: 42, B: { Length: var length } } x)
if (obj is X { I: 42, Text: { Length: var length } } x)
{
Console.WriteLine("Test " + x.I + ": " + length);
}
else
{
Console.WriteLine("not Test");
}
}
public void RecursivePatternValueType_VarLengthPattern(object obj)
{
if (obj is S { I: 42, Text: { Length: var length } } s)
{
Console.WriteLine("Test " + x.A + ": " + length);
Console.WriteLine("Test " + s.I + ": " + length);
}
else
{

2
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

@ -4571,7 +4571,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -4571,7 +4571,7 @@ namespace ICSharpCode.Decompiler.CSharp
}
else
{
Debug.Assert(matchInstruction.CheckNotNull);
Debug.Assert(matchInstruction.CheckNotNull || matchInstruction.Variable.Type.IsReferenceType == false);
}
foreach (var subPattern in matchInstruction.SubPatterns)
{

2
ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpOutputVisitor.cs

@ -1302,7 +1302,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -1302,7 +1302,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
StartNode(unaryOperatorExpression);
UnaryOperatorType opType = unaryOperatorExpression.Operator;
var opSymbol = UnaryOperatorExpression.GetOperatorRole(opType);
if (opType == UnaryOperatorType.Await)
if (opType is UnaryOperatorType.Await or UnaryOperatorType.PatternNot)
{
WriteKeyword(opSymbol);
Space();

4
ICSharpCode.Decompiler/IL/Transforms/PatternMatchingTransform.cs

@ -268,6 +268,10 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -268,6 +268,10 @@ namespace ICSharpCode.Decompiler.IL.Transforms
targetVariable.Kind = VariableKind.PatternLocal;
if (!MatchNullCheckPattern(block, varPattern, parentFalseInst, context, ref cfg))
{
if (targetVariable.Type.IsReferenceType == false)
{
DetectPropertySubPatterns(varPattern, block, parentFalseInst, context, ref cfg);
}
DetectPropertySubPatterns(parentPattern, block, parentFalseInst, context, ref cfg);
}
}

Loading…
Cancel
Save