From 535fb30c7b420639ef3c25ffd879390eca4ade19 Mon Sep 17 00:00:00 2001 From: belav Date: Tue, 10 Aug 2021 14:59:15 -0500 Subject: [PATCH] Getting pattern matching formatting straightened out. closes #154 --- .../IsPatternExpressions.cst | 120 ++++++++++++++++-- .../SwitchExpression/SwitchExpressions.cst | 21 +++ Src/CSharpier/DocTypes/Doc.cs | 5 + .../SyntaxNodePrinters/BinaryExpression.cs | 3 +- .../SyntaxNodePrinters/BinaryPattern.cs | 66 +++++++++- .../SyntaxNodePrinters/IsPatternExpression.cs | 16 ++- .../ParenthesizedPattern.cs | 2 +- .../SyntaxNodePrinters/RecursivePattern.cs | 102 +++++++++------ 8 files changed, 271 insertions(+), 64 deletions(-) diff --git a/Src/CSharpier.Tests/TestFiles/IsPatternExpression/IsPatternExpressions.cst b/Src/CSharpier.Tests/TestFiles/IsPatternExpression/IsPatternExpressions.cst index d52601f1b..219ec8504 100644 --- a/Src/CSharpier.Tests/TestFiles/IsPatternExpression/IsPatternExpressions.cst +++ b/Src/CSharpier.Tests/TestFiles/IsPatternExpression/IsPatternExpressions.cst @@ -12,14 +12,6 @@ class ClassName return; } - if ( - MethodKind - is not (MethodKind.Ordinary_________________________ - or MethodKind.LocalFunctionn) - ) { - return; - } - if (expr is < 'A' or > 'Z') { return; @@ -35,14 +27,14 @@ class ClassName var useLine = node.OperatorToken.Kind() is SyntaxKind.BarBarToken - or SyntaxKind.BarToken - or SyntaxKind.AmpersandAmpersandToken - or SyntaxKind.AmpersandToken - or SyntaxKind.PlusToken; + or SyntaxKind.BarToken + or SyntaxKind.AmpersandAmpersandToken + or SyntaxKind.AmpersandToken + or SyntaxKind.PlusToken; if ( - Nullable.GetUnderlyingType111111111111111(typeof(T)) is Type innerType - && innerType.IsEnum + someRandomValue___________________ is SomeRandomType someRandomType + && someRandomType.IsEnum ) { return; } @@ -56,5 +48,105 @@ class ClassName { return; } + + if ( + someValue_________________________ is SomeType_________________ someType + && someType.SomeProperty + ) { } + + var value = + someOtherValue + is SomeType___________________ + { + SomeProperty: SomeOtherType_____________________________________________ + } + or SomeThirdType___________; + + var value = + someOtherValue + is SomeType___________________ + { + SomeProperty: SomeOtherType_____________________________________________, + AnotherProperty: SomeType + } + or SomeThirdType___________; + + var value = + someOtherValue + is SomeType___________________ + { + SomeProperty: SomeType or SomeOtherType + }; + + var value = + someOtherValue + is SomeType___________________ + { + SomeProperty: SomeLongType_______________ + or SomeOtherLongType___________________ + }; + + var value = + someOtherValue + is SomeType___________________ + or SomeOtherType___________________ + or SomeThirdType___________ + && someLongValue_________________; + + if (someOtherValue is (SomeType or SomeOtherType)) + { + return; + } + + if (someOtherValue is not (SomeType or SomeOtherType)) + { + return; + } + + if ( + someOtherValue_____________ + is (SomeLongType_____________ or SomeOtherLongType_____________) + ) { + return; + } + + if ( + someOtherValue_____________ + is not (SomeLongType_____________ or SomeOtherLongType_____________) + ) { + return; + } + + if ( + node is SomeType_______________ + { + SomeProperty: SomeOtherType_____________________________ + } + ) { + return; + } + + if ( + node is PrefixUnaryExpressionSyntax + { + Operand: ParenthesizedExpressionSyntax + { + Expression: IsPatternExpressionSyntax or IsPatternExpressionSyntax + }, + } + ) { + return; + } + + if ( + !( + node is PrefixUnaryExpressionSyntax + { + Operand: ParenthesizedExpressionSyntax or IsPatternExpressionSyntax + } + ) + ) { + return; + } } } diff --git a/Src/CSharpier.Tests/TestFiles/SwitchExpression/SwitchExpressions.cst b/Src/CSharpier.Tests/TestFiles/SwitchExpression/SwitchExpressions.cst index 7382b7fc9..017d06454 100644 --- a/Src/CSharpier.Tests/TestFiles/SwitchExpression/SwitchExpressions.cst +++ b/Src/CSharpier.Tests/TestFiles/SwitchExpression/SwitchExpressions.cst @@ -50,7 +50,28 @@ class ClassName or AnotherObject or OrEvenSomeOtherObject_________________ => CallSomeMethod(someValue), + SomeOtherObject + { + SomeProperty: SomeOtherProject + } + or AnotherObject + => CallSomeMethod(someValue), + AnotherObject + or SomeOtherObject + { + SomeProperty: SomeOtherProject + } + => CallSomeMethod(someValue), _ => CallSomeMethod(someValue) }; + + return someValue switch + { + { IsParameter: true, } => noExtraLineAfterThis, + { + IsParameter: someLongValue____________________________________________, + } + => someOtherValue + }; } } diff --git a/Src/CSharpier/DocTypes/Doc.cs b/Src/CSharpier/DocTypes/Doc.cs index 9e2f743cb..93eaea4d5 100644 --- a/Src/CSharpier/DocTypes/Doc.cs +++ b/Src/CSharpier/DocTypes/Doc.cs @@ -96,6 +96,11 @@ public static IndentDoc Indent(params Doc[] contents) => public static IndentDoc Indent(List contents) => new() { Contents = Concat(contents) }; + public static Doc IndentIf(bool condition, Concat contents) + { + return condition ? Doc.Indent(contents) : contents; + } + public static IfBreak IfBreak( Doc breakContents, Doc flatContents, diff --git a/Src/CSharpier/SyntaxPrinter/SyntaxNodePrinters/BinaryExpression.cs b/Src/CSharpier/SyntaxPrinter/SyntaxNodePrinters/BinaryExpression.cs index 491d40a00..5af465452 100644 --- a/Src/CSharpier/SyntaxPrinter/SyntaxNodePrinters/BinaryExpression.cs +++ b/Src/CSharpier/SyntaxPrinter/SyntaxNodePrinters/BinaryExpression.cs @@ -71,7 +71,8 @@ private static List PrintBinaryExpression(SyntaxNode node) var shouldGroup = binaryExpressionSyntax.Kind() != binaryExpressionSyntax.Parent!.Kind() && binaryExpressionSyntax.Left.GetType() != binaryExpressionSyntax.GetType() - && binaryExpressionSyntax.Right.GetType() != binaryExpressionSyntax.GetType(); + && binaryExpressionSyntax.Right.GetType() != binaryExpressionSyntax.GetType() + && binaryExpressionSyntax.Left is not IsPatternExpressionSyntax; // nested ?? have the next level on the right side, everything else has it on the left var binaryOnTheRight = diff --git a/Src/CSharpier/SyntaxPrinter/SyntaxNodePrinters/BinaryPattern.cs b/Src/CSharpier/SyntaxPrinter/SyntaxNodePrinters/BinaryPattern.cs index dc59b3b52..268180d21 100644 --- a/Src/CSharpier/SyntaxPrinter/SyntaxNodePrinters/BinaryPattern.cs +++ b/Src/CSharpier/SyntaxPrinter/SyntaxNodePrinters/BinaryPattern.cs @@ -1,3 +1,4 @@ +using System.Collections.Generic; using CSharpier.DocTypes; using Microsoft.CodeAnalysis.CSharp.Syntax; @@ -7,12 +8,67 @@ public static class BinaryPattern { public static Doc Print(BinaryPatternSyntax node) { - return Doc.Concat( - Node.Print(node.Left), - Doc.Line, - Token.PrintWithSuffix(node.OperatorToken, " "), - Node.Print(node.Right) + return Doc.IndentIf( + node.Parent is SubpatternSyntax, + Doc.Concat( + Node.Print(node.Left), + Doc.Line, + Token.PrintWithSuffix(node.OperatorToken, " "), + Node.Print(node.Right) + ) ); } } } +/* + +// review this, there are more edge cases +https://github.com/belav/aspnetcore/pull/25/files + +// what should this do? +if ( + someOtherValue_____________ + is (SomeLongType_____________________________________ + or SomeLongType_____________________________________) +) { + return; +} + +// this is uh, ugly, maybe just don't indent the { } ? +// also the new break fore is makes this version uglier, maybe break before is should only be for variable stuff? +if ( + !( + node is PrefixUnaryExpressionSyntax + { + Operand: ParenthesizedExpressionSyntax + { + Expression: IsPatternExpressionSyntax + { + Pattern: DeclarationPatternSyntax, + } isPattern, + }, + } notExpression + ) +) { + return; +} + +// could this be improved?? + return someValue switch + { + OrEvenSomeOtherObject_________________ + => CallSomeMethod(someValue), + SomeOtherObject + { + SomeProperty: SomeOtherProject + } + or AnotherObject + => CallSomeMethod(someValue), + AnotherObject + or SomeOtherObject + { + SomeProperty: SomeOtherProject + } + => CallSomeMethod(someValue) + } +*/ diff --git a/Src/CSharpier/SyntaxPrinter/SyntaxNodePrinters/IsPatternExpression.cs b/Src/CSharpier/SyntaxPrinter/SyntaxNodePrinters/IsPatternExpression.cs index a8ad12c4f..638a0bbe6 100644 --- a/Src/CSharpier/SyntaxPrinter/SyntaxNodePrinters/IsPatternExpression.cs +++ b/Src/CSharpier/SyntaxPrinter/SyntaxNodePrinters/IsPatternExpression.cs @@ -8,12 +8,20 @@ public static class IsPatternExpression { public static Doc Print(IsPatternExpressionSyntax node) { + var useSpace = + node.Parent is IfStatementSyntax or ParenthesizedExpressionSyntax + && node.Pattern is not (ParenthesizedPatternSyntax or UnaryPatternSyntax); + return Doc.Group( Node.Print(node.Expression), - Doc.Indent( - Doc.Line, - Token.PrintWithSuffix(node.IsKeyword, " "), - Doc.Indent(Node.Print(node.Pattern)) + Doc.IndentIf( + node.Parent is not (IfStatementSyntax or ParenthesizedExpressionSyntax), + Doc.Concat( + useSpace ? " " : Doc.Line, + Token.Print(node.IsKeyword), + node.Pattern is RecursivePatternSyntax { Type: null } ? Doc.Null : " ", + Node.Print(node.Pattern) + ) ) ); } diff --git a/Src/CSharpier/SyntaxPrinter/SyntaxNodePrinters/ParenthesizedPattern.cs b/Src/CSharpier/SyntaxPrinter/SyntaxNodePrinters/ParenthesizedPattern.cs index 84a61bff4..73d46897e 100644 --- a/Src/CSharpier/SyntaxPrinter/SyntaxNodePrinters/ParenthesizedPattern.cs +++ b/Src/CSharpier/SyntaxPrinter/SyntaxNodePrinters/ParenthesizedPattern.cs @@ -8,7 +8,7 @@ public static class ParenthesizedPattern { public static Doc Print(ParenthesizedPatternSyntax node) { - return Doc.Concat( + return Doc.Group( Token.Print(node.OpenParenToken), Node.Print(node.Pattern), Token.Print(node.CloseParenToken) diff --git a/Src/CSharpier/SyntaxPrinter/SyntaxNodePrinters/RecursivePattern.cs b/Src/CSharpier/SyntaxPrinter/SyntaxNodePrinters/RecursivePattern.cs index fc56fc732..a2c143559 100644 --- a/Src/CSharpier/SyntaxPrinter/SyntaxNodePrinters/RecursivePattern.cs +++ b/Src/CSharpier/SyntaxPrinter/SyntaxNodePrinters/RecursivePattern.cs @@ -1,6 +1,8 @@ +using System.Collections.Generic; using System.Linq; using CSharpier.DocTypes; using CSharpier.SyntaxPrinter; +using CSharpier.Utilities; using Microsoft.CodeAnalysis.CSharp.Syntax; namespace CSharpier.SyntaxPrinter.SyntaxNodePrinters @@ -9,45 +11,67 @@ public static class RecursivePattern { public static Doc Print(RecursivePatternSyntax node) { - return Doc.Concat( - node.Type != null ? Doc.Concat(Node.Print(node.Type), " ") : Doc.Null, - node.PositionalPatternClause != null - ? Doc.Concat( - Token.Print(node.PositionalPatternClause.OpenParenToken), - SeparatedSyntaxList.Print( - node.PositionalPatternClause.Subpatterns, - subpatternNode => - Doc.Concat( - subpatternNode.NameColon != null - ? NameColon.Print(subpatternNode.NameColon) - : Doc.Null, - Node.Print(subpatternNode.Pattern) - ), - " " - ), - Token.Print(node.PositionalPatternClause.CloseParenToken) - ) - : Doc.Null, - node.PropertyPatternClause != null - ? Doc.Concat( - Token.PrintWithSuffix(node.PropertyPatternClause.OpenBraceToken, " "), - SeparatedSyntaxList.Print( - node.PropertyPatternClause.Subpatterns, - subpatternNode => - Doc.Concat( - subpatternNode.NameColon != null - ? NameColon.Print(subpatternNode.NameColon) - : Doc.Null, - Node.Print(subpatternNode.Pattern) - ), - " " - ), - node.PropertyPatternClause.Subpatterns.Any() ? " " : Doc.Null, - Token.Print(node.PropertyPatternClause.CloseBraceToken) - ) - : Doc.Null, - node.Designation != null ? Doc.Concat(" ", Node.Print(node.Designation)) : Doc.Null - ); + var result = new List(); + if (node.Type != null) + { + result.Add(Node.Print(node.Type)); + } + + if (node.PositionalPatternClause != null) + { + result.Add( + Doc.SoftLine, + Token.Print(node.PositionalPatternClause.OpenParenToken), + SeparatedSyntaxList.Print( + node.PositionalPatternClause.Subpatterns, + subpatternNode => + Doc.Concat( + subpatternNode.NameColon != null + ? NameColon.Print(subpatternNode.NameColon) + : Doc.Null, + Node.Print(subpatternNode.Pattern) + ), + " " + ), + Token.Print(node.PositionalPatternClause.CloseParenToken) + ); + } + + if (node.PropertyPatternClause != null) + { + result.Add( + node.Parent switch + { + IsPatternExpressionSyntax => Doc.Line, + SwitchExpressionArmSyntax => Doc.Null, + _ => Doc.SoftLine + }, + Token.Print(node.PropertyPatternClause.OpenBraceToken), + Doc.Indent( + node.PropertyPatternClause.Subpatterns.Any() ? Doc.Line : Doc.Null, + SeparatedSyntaxList.Print( + node.PropertyPatternClause.Subpatterns, + subpatternNode => + Doc.Group( + subpatternNode.NameColon != null + ? NameColon.Print(subpatternNode.NameColon) + : Doc.Null, + Node.Print(subpatternNode.Pattern) + ), + Doc.Line + ) + ), + Doc.Line, + Token.Print(node.PropertyPatternClause.CloseBraceToken) + ); + } + + if (node.Designation != null) + { + result.Add(" ", Node.Print(node.Designation)); + } + + return Doc.Concat(result); } } }