From a1d21dbacda1debad03ba717991656af317d6d61 Mon Sep 17 00:00:00 2001 From: Jacob Bundgaard Date: Mon, 10 Oct 2022 00:46:36 +0200 Subject: [PATCH 1/6] Change operator when negating relational patterns with numeric values --- .../InvertLogical/InvertLogicalTests.cs | 60 +++++++++++++++++++ .../Services/SyntaxFacts/CSharpSyntaxFacts.cs | 7 +++ .../Services/SyntaxFacts/CSharpSyntaxKinds.cs | 1 + .../Core/Services/SyntaxFacts/ISyntaxFacts.cs | 1 + .../SyntaxFacts/ISyntaxFactsExtensions.cs | 3 + .../Core/Services/SyntaxFacts/ISyntaxKinds.cs | 1 + .../SyntaxFacts/VisualBasicSyntaxFacts.vb | 3 + .../SyntaxFacts/VisualBasicSyntaxKinds.vb | 1 + .../CSharpSyntaxGeneratorInternal.cs | 12 ++++ .../SyntaxGeneratorExtensions_Negate.cs | 58 +++++++++++++----- .../SyntaxGeneratorInternal.cs | 4 ++ .../VisualBasicSyntaxGeneratorInternal.vb | 16 +++++ 12 files changed, 153 insertions(+), 14 deletions(-) diff --git a/src/EditorFeatures/CSharpTest/InvertLogical/InvertLogicalTests.cs b/src/EditorFeatures/CSharpTest/InvertLogical/InvertLogicalTests.cs index 96097d8d7d34a..4659362493126 100644 --- a/src/EditorFeatures/CSharpTest/InvertLogical/InvertLogicalTests.cs +++ b/src/EditorFeatures/CSharpTest/InvertLogical/InvertLogicalTests.cs @@ -594,6 +594,66 @@ void M(bool x, int a, object b) }", parseOptions: CSharp9); } + [Fact, WorkItem(64558, "https://github.com/dotnet/roslyn/issues/64558")] + public async Task InvertNumericIsGreaterThanPattern1_CSharp9() + { + await TestInRegularAndScriptAsync( +@"class C +{ + void M(bool x, int a, object b) + { + var c = a > 10 [||]&& a is > 20; + } +}", +@"class C +{ + void M(bool x, int a, object b) + { + var c = !(a <= 10 || a is <= 20); + } +}", parseOptions: CSharp9); + } + + [Fact, WorkItem(64558, "https://github.com/dotnet/roslyn/issues/64558")] + public async Task InvertNullableNumericIsGreaterThanPattern1_CSharp9() + { + await TestInRegularAndScriptAsync( +@"class C +{ + void M(bool x, int? a, object b) + { + var c = x [||]&& a is > 20; + } +}", +@"class C +{ + void M(bool x, int? a, object b) + { + var c = !(!x || a is not > 20); + } +}", parseOptions: CSharp9); + } + + [Fact, WorkItem(64558, "https://github.com/dotnet/roslyn/issues/64558")] + public async Task InvertNonNumericIsGreaterThanPattern1_CSharp9() + { + await TestInRegularAndScriptAsync( +@"class C +{ + void M(bool x, int a, object b) + { + var c = a > 10 [||]&& b is > 20; + } +}", +@"class C +{ + void M(bool x, int a, object b) + { + var c = !(a <= 10 || b is not > 20); + } +}", parseOptions: CSharp9); + } + [Fact, WorkItem(42368, "https://github.com/dotnet/roslyn/issues/42368")] public async Task InvertIsAndPattern1_CSharp8() { diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Services/SyntaxFacts/CSharpSyntaxFacts.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Services/SyntaxFacts/CSharpSyntaxFacts.cs index 518f54a00b65d..ca8cc94433236 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Services/SyntaxFacts/CSharpSyntaxFacts.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Services/SyntaxFacts/CSharpSyntaxFacts.cs @@ -1497,6 +1497,13 @@ public void GetPartsOfUnaryPattern(SyntaxNode node, out SyntaxToken operatorToke pattern = unaryPattern.Pattern; } + public void GetPartsOfRelationalPattern(SyntaxNode node, out SyntaxToken operatorToken, out SyntaxNode expression) + { + var relationalPattern = (RelationalPatternSyntax)node; + operatorToken = relationalPattern.OperatorToken; + expression = relationalPattern.Expression; + } + public SyntaxNode GetTypeOfTypePattern(SyntaxNode node) => ((TypePatternSyntax)node).Type; diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Services/SyntaxFacts/CSharpSyntaxKinds.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Services/SyntaxFacts/CSharpSyntaxKinds.cs index 8a1c40805b0f0..fc4ed1f8eb584 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Services/SyntaxFacts/CSharpSyntaxKinds.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Services/SyntaxFacts/CSharpSyntaxKinds.cs @@ -102,6 +102,7 @@ public TSyntaxKind Convert(int kind) where TSyntaxKind : struct public int? RecursivePattern => (int)SyntaxKind.RecursivePattern; public int? TypePattern => (int)SyntaxKind.TypePattern; public int? VarPattern => (int)SyntaxKind.VarPattern; + public int? RelationalPattern => (int)SyntaxKind.RelationalPattern; public int EndOfFileToken => (int)SyntaxKind.EndOfFileToken; public int AwaitKeyword => (int)SyntaxKind.AwaitKeyword; diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Services/SyntaxFacts/ISyntaxFacts.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Services/SyntaxFacts/ISyntaxFacts.cs index 4dd0019c4f19e..3e09bd1b50300 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Services/SyntaxFacts/ISyntaxFacts.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Services/SyntaxFacts/ISyntaxFacts.cs @@ -466,6 +466,7 @@ void GetPartsOfTupleExpression(SyntaxNode node, void GetPartsOfDeclarationPattern(SyntaxNode node, out SyntaxNode type, out SyntaxNode designation); void GetPartsOfRecursivePattern(SyntaxNode node, out SyntaxNode? type, out SyntaxNode? positionalPart, out SyntaxNode? propertyPart, out SyntaxNode? designation); void GetPartsOfUnaryPattern(SyntaxNode node, out SyntaxToken operatorToken, out SyntaxNode pattern); + void GetPartsOfRelationalPattern(SyntaxNode node, out SyntaxToken operatorToken, out SyntaxNode expression); bool ContainsInterleavedDirective(TextSpan span, SyntaxToken token, CancellationToken cancellationToken); diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Services/SyntaxFacts/ISyntaxFactsExtensions.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Services/SyntaxFacts/ISyntaxFactsExtensions.cs index 6b9228b623e5e..0198fa88a59a2 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Services/SyntaxFacts/ISyntaxFactsExtensions.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Services/SyntaxFacts/ISyntaxFactsExtensions.cs @@ -876,6 +876,9 @@ public static bool IsTypePattern(this ISyntaxFacts syntaxFacts, [NotNullWhen(tru public static bool IsVarPattern(this ISyntaxFacts syntaxFacts, [NotNullWhen(true)] SyntaxNode? node) => node?.RawKind == syntaxFacts.SyntaxKinds.VarPattern; + public static bool IsRelationalPattern(this ISyntaxFacts syntaxFacts, [NotNullWhen(true)] SyntaxNode? node) + => node?.RawKind == syntaxFacts.SyntaxKinds.RelationalPattern; + #endregion #region statements diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Services/SyntaxFacts/ISyntaxKinds.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Services/SyntaxFacts/ISyntaxKinds.cs index b6a15d53c6cb0..8855aa03d071c 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Services/SyntaxFacts/ISyntaxKinds.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Services/SyntaxFacts/ISyntaxKinds.cs @@ -153,6 +153,7 @@ internal interface ISyntaxKinds int? RecursivePattern { get; } int? TypePattern { get; } int? VarPattern { get; } + int? RelationalPattern { get; } #endregion diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Services/SyntaxFacts/VisualBasicSyntaxFacts.vb b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Services/SyntaxFacts/VisualBasicSyntaxFacts.vb index a23875e0724f7..2fcc337ae77c0 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Services/SyntaxFacts/VisualBasicSyntaxFacts.vb +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Services/SyntaxFacts/VisualBasicSyntaxFacts.vb @@ -1689,6 +1689,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.LanguageService Public Sub GetPartsOfUnaryPattern(node As SyntaxNode, ByRef operatorToken As SyntaxToken, ByRef pattern As SyntaxNode) Implements ISyntaxFacts.GetPartsOfUnaryPattern Throw New InvalidOperationException(DoesNotExistInVBErrorMessage) End Sub + Public Sub GetPartsOfRelationalPattern(node As SyntaxNode, ByRef operatorToken As SyntaxToken, ByRef expression As SyntaxNode) Implements ISyntaxFacts.GetPartsOfRelationalPattern + Throw New InvalidOperationException(DoesNotExistInVBErrorMessage) + End Sub Public Sub GetPartsOfDeclarationPattern(node As SyntaxNode, ByRef type As SyntaxNode, ByRef designation As SyntaxNode) Implements ISyntaxFacts.GetPartsOfDeclarationPattern Throw New InvalidOperationException(DoesNotExistInVBErrorMessage) diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Services/SyntaxFacts/VisualBasicSyntaxKinds.vb b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Services/SyntaxFacts/VisualBasicSyntaxKinds.vb index 1ce6a58163ecf..f566ee76e3efe 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Services/SyntaxFacts/VisualBasicSyntaxKinds.vb +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Services/SyntaxFacts/VisualBasicSyntaxKinds.vb @@ -104,6 +104,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.LanguageService Public ReadOnly Property RecursivePattern As Integer? Implements ISyntaxKinds.RecursivePattern Public ReadOnly Property TypePattern As Integer? Implements ISyntaxKinds.TypePattern Public ReadOnly Property VarPattern As Integer? Implements ISyntaxKinds.VarPattern + Public ReadOnly Property RelationalPattern As Integer? Implements ISyntaxKinds.RelationalPattern Public ReadOnly Property IndexerMemberCref As Integer? Implements ISyntaxKinds.IndexerMemberCref Public ReadOnly Property EndOfFileToken As Integer = SyntaxKind.EndOfFileToken Implements ISyntaxKinds.EndOfFileToken diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/LanguageServices/CSharpSyntaxGeneratorInternal.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/LanguageServices/CSharpSyntaxGeneratorInternal.cs index 1486b59a024ba..9ccf135e1252c 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/LanguageServices/CSharpSyntaxGeneratorInternal.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/LanguageServices/CSharpSyntaxGeneratorInternal.cs @@ -182,6 +182,18 @@ public override SyntaxNode TypePattern(SyntaxNode type) public override SyntaxNode UnaryPattern(SyntaxToken operatorToken, SyntaxNode pattern) => SyntaxFactory.UnaryPattern(operatorToken, (PatternSyntax)Parenthesize(pattern)); + public override SyntaxNode LessThanPattern(SyntaxNode expression) + => SyntaxFactory.RelationalPattern(SyntaxFactory.Token(SyntaxKind.LessThanToken), (ExpressionSyntax)expression); + + public override SyntaxNode LessThanEqualsPattern(SyntaxNode expression) + => SyntaxFactory.RelationalPattern(SyntaxFactory.Token(SyntaxKind.LessThanEqualsToken), (ExpressionSyntax)expression); + + public override SyntaxNode GreaterThanPattern(SyntaxNode expression) + => SyntaxFactory.RelationalPattern(SyntaxFactory.Token(SyntaxKind.GreaterThanToken), (ExpressionSyntax)expression); + + public override SyntaxNode GreaterThanEqualsPattern(SyntaxNode expression) + => SyntaxFactory.RelationalPattern(SyntaxFactory.Token(SyntaxKind.GreaterThanEqualsToken), (ExpressionSyntax)expression); + #endregion } } diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Extensions/SyntaxGeneratorExtensions_Negate.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Extensions/SyntaxGeneratorExtensions_Negate.cs index 6565cf220be31..0dca6cd6518ec 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Extensions/SyntaxGeneratorExtensions_Negate.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Extensions/SyntaxGeneratorExtensions_Negate.cs @@ -49,7 +49,7 @@ public static SyntaxNode Negate( bool negateBinary, CancellationToken cancellationToken) { - return Negate(generator, generatorInternal, expressionOrPattern, semanticModel, negateBinary, allowSwappingBooleans: true, cancellationToken); + return Negate(generator, generatorInternal, expressionOrPattern, semanticModel, negateBinary, patternValueType: null, cancellationToken); } public static SyntaxNode Negate( @@ -58,7 +58,7 @@ public static SyntaxNode Negate( SyntaxNode expressionOrPattern, SemanticModel semanticModel, bool negateBinary, - bool allowSwappingBooleans, + SpecialType? patternValueType, CancellationToken cancellationToken) { var options = semanticModel.SyntaxTree.Options; @@ -105,7 +105,7 @@ public static SyntaxNode Negate( return GetNegationOfBinaryPattern(expressionOrPattern, generator, generatorInternal, semanticModel, cancellationToken); if (syntaxFacts.IsConstantPattern(expressionOrPattern)) - return GetNegationOfConstantPattern(expressionOrPattern, generator, generatorInternal, allowSwappingBooleans); + return GetNegationOfConstantPattern(expressionOrPattern, generator, generatorInternal, patternValueType); if (syntaxFacts.IsUnaryPattern(expressionOrPattern)) return GetNegationOfUnaryPattern(expressionOrPattern, generator, generatorInternal, syntaxFacts); @@ -126,9 +126,10 @@ public static SyntaxNode Negate( return generator.IsTypeExpression(expression, type); } - // TODO(cyrusn): We could support negating relational patterns in the future. i.e. - // - // not >= 0 -> < 0 + if (syntaxFacts.IsRelationalPattern(expressionOrPattern)) + { + return GetNegationOfRelationalPattern(expressionOrPattern, generatorInternal, patternValueType); + } return syntaxFacts.IsAnyPattern(expressionOrPattern) ? generatorInternal.NotPattern(expressionOrPattern) @@ -207,7 +208,7 @@ private static SyntaxNode GetNegationOfBinaryPattern( SemanticModel semanticModel, CancellationToken cancellationToken) { - // Apply demorgans's law here. + // Apply De Morgan's laws here. // // not (a and b) -> not a or not b // not (a or b) -> not a and not b @@ -241,11 +242,11 @@ private static SyntaxNode GetNegationOfIsPatternExpression(SyntaxNode isExpressi if (syntaxFacts.SupportsNotPattern(semanticModel.SyntaxTree.Options)) { // We do support 'not' patterns. So attempt to push a 'not' pattern into the current is-pattern RHS. - // If the value isn't a Boolean and the pattern `is true/false`, swapping to `is false/true` is incorrect since non-Booleans match neither. - // As an example, `!(new object() is true)` is equivalent to `new object() is not true` but not `new object() is false`. + // We include the type of the value when negating the pattern, since it allows for nicer negations of + // `is true/false` for Boolean values and relational patterns for numeric values. var operation = semanticModel.GetOperation(isExpression, cancellationToken); - var isValueBoolean = operation is IIsPatternOperation isPatternOperation && isPatternOperation.Value.Type?.SpecialType == SpecialType.System_Boolean; - negatedPattern = generator.Negate(generatorInternal, pattern, semanticModel, negateBinary: true, allowSwappingBooleans: isValueBoolean, cancellationToken); + var valueType = (operation as IIsPatternOperation)?.Value.Type?.SpecialType; + negatedPattern = generator.Negate(generatorInternal, pattern, semanticModel, negateBinary: true, valueType, cancellationToken); } else if (syntaxFacts.IsNotPattern(pattern)) { @@ -272,6 +273,33 @@ private static SyntaxNode GetNegationOfIsPatternExpression(SyntaxNode isExpressi return generator.LogicalNotExpression(isExpression); } + private static SyntaxNode GetNegationOfRelationalPattern( + SyntaxNode expressionNode, + SyntaxGeneratorInternal generatorInternal, + SpecialType? patternValueType) + { + if (patternValueType is SpecialType specialType && specialType.IsNumericType()) + { + // If we know the value is numeric, we can negate the relational operator. + // This is not valid for non-numeric value since they never match a relational pattern. + // Similarly, it's not valid for nullable values, since null never matches a relational pattern. + // As an example, `!(new object() is < 1)` is equivalent to `new object() is not < 1` but not `new object() is >= 1`. + var syntaxFacts = generatorInternal.SyntaxFacts; + syntaxFacts.GetPartsOfRelationalPattern(expressionNode, out var operatorToken, out var expression); + syntaxFacts.TryGetPredefinedOperator(operatorToken, out var predefinedOperator); + return predefinedOperator switch + { + PredefinedOperator.LessThan => generatorInternal.GreaterThanEqualsPattern(expression), + PredefinedOperator.LessThanOrEqual => generatorInternal.GreaterThanPattern(expression), + PredefinedOperator.GreaterThan => generatorInternal.LessThanEqualsPattern(expression), + PredefinedOperator.GreaterThanOrEqual => generatorInternal.LessThanPattern(expression), + _ => throw ExceptionUtilities.UnexpectedValue(predefinedOperator) + }; + } + + return generatorInternal.NotPattern(expressionNode); + } + private static bool IsLegalPattern(ISyntaxFacts syntaxFacts, SyntaxNode pattern, bool designatorsLegal) { // It is illegal to create a pattern that has a designator under a not-pattern or or-pattern @@ -440,12 +468,14 @@ private static SyntaxNode GetNegationOfConstantPattern( SyntaxNode pattern, SyntaxGenerator generator, SyntaxGeneratorInternal generatorInternal, - bool allowSwappingBooleans) + SpecialType? patternValueType) { var syntaxFacts = generatorInternal.SyntaxFacts; - // If we have `is true/false` just swap that to be `is false/true` if allowed. - if (allowSwappingBooleans) + // If we have `is true/false` and a Boolean value, just swap that to be `is false/true`. + // If the value isn't a Boolean, swapping to `is false/true` is incorrect since non-Booleans match neither. + // As an example, `!(new object() is true)` is equivalent to `new object() is not true` but not `new object() is false`. + if (patternValueType == SpecialType.System_Boolean) { var expression = syntaxFacts.GetExpressionOfConstantPattern(pattern); if (syntaxFacts.IsTrueLiteralExpression(expression)) diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/LanguageServices/SyntaxGeneratorInternalExtensions/SyntaxGeneratorInternal.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/LanguageServices/SyntaxGeneratorInternalExtensions/SyntaxGeneratorInternal.cs index 155b3d46b86a9..a0da53a674e5a 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/LanguageServices/SyntaxGeneratorInternalExtensions/SyntaxGeneratorInternal.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/LanguageServices/SyntaxGeneratorInternalExtensions/SyntaxGeneratorInternal.cs @@ -107,6 +107,10 @@ public SyntaxNode LocalDeclarationStatement(SyntaxToken name, SyntaxNode initial public abstract SyntaxNode ParenthesizedPattern(SyntaxNode pattern); public abstract SyntaxNode TypePattern(SyntaxNode type); public abstract SyntaxNode UnaryPattern(SyntaxToken operatorToken, SyntaxNode pattern); + public abstract SyntaxNode LessThanPattern(SyntaxNode expression); + public abstract SyntaxNode LessThanEqualsPattern(SyntaxNode expression); + public abstract SyntaxNode GreaterThanPattern(SyntaxNode expression); + public abstract SyntaxNode GreaterThanEqualsPattern(SyntaxNode expression); #endregion } diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/VisualBasic/LanguageServices/VisualBasicSyntaxGeneratorInternal.vb b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/VisualBasic/LanguageServices/VisualBasicSyntaxGeneratorInternal.vb index 280630681a2e8..f0739356f5344 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/VisualBasic/LanguageServices/VisualBasicSyntaxGeneratorInternal.vb +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/VisualBasic/LanguageServices/VisualBasicSyntaxGeneratorInternal.vb @@ -188,6 +188,22 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeGeneration Throw New NotImplementedException() End Function + Public Overrides Function LessThanPattern(expression As SyntaxNode) As SyntaxNode + Throw New NotImplementedException() + End Function + + Public Overrides Function LessThanEqualsPattern(expression As SyntaxNode) As SyntaxNode + Throw New NotImplementedException() + End Function + + Public Overrides Function GreaterThanPattern(expression As SyntaxNode) As SyntaxNode + Throw New NotImplementedException() + End Function + + Public Overrides Function GreaterThanEqualsPattern(expression As SyntaxNode) As SyntaxNode + Throw New NotImplementedException() + End Function + #End Region End Class End Namespace From 0ce1e62158a9a3f9f4ff05a24de6b103ace86c6a Mon Sep 17 00:00:00 2001 From: Jacob Bundgaard Date: Tue, 11 Oct 2022 00:13:34 +0200 Subject: [PATCH 2/6] Sort members --- .../CSharp/Services/SyntaxFacts/CSharpSyntaxKinds.cs | 2 +- .../Compiler/Core/Services/SyntaxFacts/ISyntaxFacts.cs | 2 +- .../Core/Services/SyntaxFacts/ISyntaxFactsExtensions.cs | 6 +++--- .../Compiler/Core/Services/SyntaxFacts/ISyntaxKinds.cs | 2 +- .../Services/SyntaxFacts/VisualBasicSyntaxFacts.vb | 1 + .../Services/SyntaxFacts/VisualBasicSyntaxKinds.vb | 4 ++-- .../SyntaxGeneratorInternal.cs | 8 ++++---- 7 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Services/SyntaxFacts/CSharpSyntaxKinds.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Services/SyntaxFacts/CSharpSyntaxKinds.cs index fc4ed1f8eb584..fc2ef37626e3b 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Services/SyntaxFacts/CSharpSyntaxKinds.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Services/SyntaxFacts/CSharpSyntaxKinds.cs @@ -100,9 +100,9 @@ public TSyntaxKind Convert(int kind) where TSyntaxKind : struct public int? OrPattern => (int)SyntaxKind.OrPattern; public int? ParenthesizedPattern => (int)SyntaxKind.ParenthesizedPattern; public int? RecursivePattern => (int)SyntaxKind.RecursivePattern; + public int? RelationalPattern => (int)SyntaxKind.RelationalPattern; public int? TypePattern => (int)SyntaxKind.TypePattern; public int? VarPattern => (int)SyntaxKind.VarPattern; - public int? RelationalPattern => (int)SyntaxKind.RelationalPattern; public int EndOfFileToken => (int)SyntaxKind.EndOfFileToken; public int AwaitKeyword => (int)SyntaxKind.AwaitKeyword; diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Services/SyntaxFacts/ISyntaxFacts.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Services/SyntaxFacts/ISyntaxFacts.cs index 3e09bd1b50300..3fc985a3b92fe 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Services/SyntaxFacts/ISyntaxFacts.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Services/SyntaxFacts/ISyntaxFacts.cs @@ -465,8 +465,8 @@ void GetPartsOfTupleExpression(SyntaxNode node, void GetPartsOfBinaryPattern(SyntaxNode node, out SyntaxNode left, out SyntaxToken operatorToken, out SyntaxNode right); void GetPartsOfDeclarationPattern(SyntaxNode node, out SyntaxNode type, out SyntaxNode designation); void GetPartsOfRecursivePattern(SyntaxNode node, out SyntaxNode? type, out SyntaxNode? positionalPart, out SyntaxNode? propertyPart, out SyntaxNode? designation); - void GetPartsOfUnaryPattern(SyntaxNode node, out SyntaxToken operatorToken, out SyntaxNode pattern); void GetPartsOfRelationalPattern(SyntaxNode node, out SyntaxToken operatorToken, out SyntaxNode expression); + void GetPartsOfUnaryPattern(SyntaxNode node, out SyntaxToken operatorToken, out SyntaxNode pattern); bool ContainsInterleavedDirective(TextSpan span, SyntaxToken token, CancellationToken cancellationToken); diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Services/SyntaxFacts/ISyntaxFactsExtensions.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Services/SyntaxFacts/ISyntaxFactsExtensions.cs index 0198fa88a59a2..32e8f01affb50 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Services/SyntaxFacts/ISyntaxFactsExtensions.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Services/SyntaxFacts/ISyntaxFactsExtensions.cs @@ -870,15 +870,15 @@ public static bool IsParenthesizedPattern(this ISyntaxFacts syntaxFacts, [NotNul public static bool IsRecursivePattern(this ISyntaxFacts syntaxFacts, [NotNullWhen(true)] SyntaxNode? node) => node?.RawKind == syntaxFacts.SyntaxKinds.RecursivePattern; + public static bool IsRelationalPattern(this ISyntaxFacts syntaxFacts, [NotNullWhen(true)] SyntaxNode? node) + => node?.RawKind == syntaxFacts.SyntaxKinds.RelationalPattern; + public static bool IsTypePattern(this ISyntaxFacts syntaxFacts, [NotNullWhen(true)] SyntaxNode? node) => node?.RawKind == syntaxFacts.SyntaxKinds.TypePattern; public static bool IsVarPattern(this ISyntaxFacts syntaxFacts, [NotNullWhen(true)] SyntaxNode? node) => node?.RawKind == syntaxFacts.SyntaxKinds.VarPattern; - public static bool IsRelationalPattern(this ISyntaxFacts syntaxFacts, [NotNullWhen(true)] SyntaxNode? node) - => node?.RawKind == syntaxFacts.SyntaxKinds.RelationalPattern; - #endregion #region statements diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Services/SyntaxFacts/ISyntaxKinds.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Services/SyntaxFacts/ISyntaxKinds.cs index 8855aa03d071c..66d199ecc512f 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Services/SyntaxFacts/ISyntaxKinds.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Services/SyntaxFacts/ISyntaxKinds.cs @@ -151,9 +151,9 @@ internal interface ISyntaxKinds int? OrPattern { get; } int? ParenthesizedPattern { get; } int? RecursivePattern { get; } + int? RelationalPattern { get; } int? TypePattern { get; } int? VarPattern { get; } - int? RelationalPattern { get; } #endregion diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Services/SyntaxFacts/VisualBasicSyntaxFacts.vb b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Services/SyntaxFacts/VisualBasicSyntaxFacts.vb index 2fcc337ae77c0..6a6c3e2c613c6 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Services/SyntaxFacts/VisualBasicSyntaxFacts.vb +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Services/SyntaxFacts/VisualBasicSyntaxFacts.vb @@ -1689,6 +1689,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.LanguageService Public Sub GetPartsOfUnaryPattern(node As SyntaxNode, ByRef operatorToken As SyntaxToken, ByRef pattern As SyntaxNode) Implements ISyntaxFacts.GetPartsOfUnaryPattern Throw New InvalidOperationException(DoesNotExistInVBErrorMessage) End Sub + Public Sub GetPartsOfRelationalPattern(node As SyntaxNode, ByRef operatorToken As SyntaxToken, ByRef expression As SyntaxNode) Implements ISyntaxFacts.GetPartsOfRelationalPattern Throw New InvalidOperationException(DoesNotExistInVBErrorMessage) End Sub diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Services/SyntaxFacts/VisualBasicSyntaxKinds.vb b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Services/SyntaxFacts/VisualBasicSyntaxKinds.vb index f566ee76e3efe..9d3a3518c6f3c 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Services/SyntaxFacts/VisualBasicSyntaxKinds.vb +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Services/SyntaxFacts/VisualBasicSyntaxKinds.vb @@ -102,10 +102,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.LanguageService Public ReadOnly Property OrPattern As Integer? Implements ISyntaxKinds.OrPattern Public ReadOnly Property ParenthesizedPattern As Integer? Implements ISyntaxKinds.ParenthesizedPattern Public ReadOnly Property RecursivePattern As Integer? Implements ISyntaxKinds.RecursivePattern + Public ReadOnly Property RelationalPattern As Integer? Implements ISyntaxKinds.RelationalPattern Public ReadOnly Property TypePattern As Integer? Implements ISyntaxKinds.TypePattern Public ReadOnly Property VarPattern As Integer? Implements ISyntaxKinds.VarPattern - Public ReadOnly Property RelationalPattern As Integer? Implements ISyntaxKinds.RelationalPattern - Public ReadOnly Property IndexerMemberCref As Integer? Implements ISyntaxKinds.IndexerMemberCref Public ReadOnly Property EndOfFileToken As Integer = SyntaxKind.EndOfFileToken Implements ISyntaxKinds.EndOfFileToken Public ReadOnly Property AwaitKeyword As Integer = SyntaxKind.AwaitKeyword Implements ISyntaxKinds.AwaitKeyword @@ -147,5 +146,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.LanguageService Public ReadOnly Property Interpolation As Integer = SyntaxKind.Interpolation Implements ISyntaxKinds.Interpolation Public ReadOnly Property InterpolatedStringExpression As Integer = SyntaxKind.InterpolatedStringExpression Implements ISyntaxKinds.InterpolatedStringExpression Public ReadOnly Property InterpolatedStringText As Integer = SyntaxKind.InterpolatedStringText Implements ISyntaxKinds.InterpolatedStringText + Public ReadOnly Property IndexerMemberCref As Integer? Implements ISyntaxKinds.IndexerMemberCref End Class End Namespace diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/LanguageServices/SyntaxGeneratorInternalExtensions/SyntaxGeneratorInternal.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/LanguageServices/SyntaxGeneratorInternalExtensions/SyntaxGeneratorInternal.cs index a0da53a674e5a..a323bdda5aaa1 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/LanguageServices/SyntaxGeneratorInternalExtensions/SyntaxGeneratorInternal.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/LanguageServices/SyntaxGeneratorInternalExtensions/SyntaxGeneratorInternal.cs @@ -102,15 +102,15 @@ public SyntaxNode LocalDeclarationStatement(SyntaxToken name, SyntaxNode initial public abstract SyntaxNode AndPattern(SyntaxNode left, SyntaxNode right); public abstract SyntaxNode DeclarationPattern(INamedTypeSymbol type, string name); public abstract SyntaxNode ConstantPattern(SyntaxNode expression); + public abstract SyntaxNode GreaterThanPattern(SyntaxNode expression); + public abstract SyntaxNode GreaterThanEqualsPattern(SyntaxNode expression); + public abstract SyntaxNode LessThanPattern(SyntaxNode expression); + public abstract SyntaxNode LessThanEqualsPattern(SyntaxNode expression); public abstract SyntaxNode NotPattern(SyntaxNode pattern); public abstract SyntaxNode OrPattern(SyntaxNode left, SyntaxNode right); public abstract SyntaxNode ParenthesizedPattern(SyntaxNode pattern); public abstract SyntaxNode TypePattern(SyntaxNode type); public abstract SyntaxNode UnaryPattern(SyntaxToken operatorToken, SyntaxNode pattern); - public abstract SyntaxNode LessThanPattern(SyntaxNode expression); - public abstract SyntaxNode LessThanEqualsPattern(SyntaxNode expression); - public abstract SyntaxNode GreaterThanPattern(SyntaxNode expression); - public abstract SyntaxNode GreaterThanEqualsPattern(SyntaxNode expression); #endregion } From 7615e85e87f958ddd9f7b74a125a27c60270c5b5 Mon Sep 17 00:00:00 2001 From: Jacob Bundgaard Date: Tue, 11 Oct 2022 00:17:46 +0200 Subject: [PATCH 3/6] Further sorting of members --- .../CSharpSyntaxGeneratorInternal.cs | 28 +++++++++---------- .../SyntaxGeneratorInternal.cs | 2 +- .../VisualBasicSyntaxGeneratorInternal.vb | 24 ++++++++-------- 3 files changed, 27 insertions(+), 27 deletions(-) diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/LanguageServices/CSharpSyntaxGeneratorInternal.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/LanguageServices/CSharpSyntaxGeneratorInternal.cs index 9ccf135e1252c..070bb0cd15c83 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/LanguageServices/CSharpSyntaxGeneratorInternal.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/LanguageServices/CSharpSyntaxGeneratorInternal.cs @@ -156,6 +156,9 @@ public override SyntaxNode IsPatternExpression(SyntaxNode expression, SyntaxToke isKeyword == default ? SyntaxFactory.Token(SyntaxKind.IsKeyword) : isKeyword, (PatternSyntax)pattern); + public override SyntaxNode AndPattern(SyntaxNode left, SyntaxNode right) + => SyntaxFactory.BinaryPattern(SyntaxKind.AndPattern, (PatternSyntax)Parenthesize(left), (PatternSyntax)Parenthesize(right)); + public override SyntaxNode ConstantPattern(SyntaxNode expression) => SyntaxFactory.ConstantPattern((ExpressionSyntax)expression); @@ -164,8 +167,17 @@ public override SyntaxNode DeclarationPattern(INamedTypeSymbol type, string name type.GenerateTypeSyntax(), SyntaxFactory.SingleVariableDesignation(name.ToIdentifierToken())); - public override SyntaxNode AndPattern(SyntaxNode left, SyntaxNode right) - => SyntaxFactory.BinaryPattern(SyntaxKind.AndPattern, (PatternSyntax)Parenthesize(left), (PatternSyntax)Parenthesize(right)); + public override SyntaxNode LessThanPattern(SyntaxNode expression) + => SyntaxFactory.RelationalPattern(SyntaxFactory.Token(SyntaxKind.LessThanToken), (ExpressionSyntax)expression); + + public override SyntaxNode LessThanEqualsPattern(SyntaxNode expression) + => SyntaxFactory.RelationalPattern(SyntaxFactory.Token(SyntaxKind.LessThanEqualsToken), (ExpressionSyntax)expression); + + public override SyntaxNode GreaterThanPattern(SyntaxNode expression) + => SyntaxFactory.RelationalPattern(SyntaxFactory.Token(SyntaxKind.GreaterThanToken), (ExpressionSyntax)expression); + + public override SyntaxNode GreaterThanEqualsPattern(SyntaxNode expression) + => SyntaxFactory.RelationalPattern(SyntaxFactory.Token(SyntaxKind.GreaterThanEqualsToken), (ExpressionSyntax)expression); public override SyntaxNode NotPattern(SyntaxNode pattern) => SyntaxFactory.UnaryPattern(SyntaxFactory.Token(SyntaxKind.NotKeyword), (PatternSyntax)Parenthesize(pattern)); @@ -182,18 +194,6 @@ public override SyntaxNode TypePattern(SyntaxNode type) public override SyntaxNode UnaryPattern(SyntaxToken operatorToken, SyntaxNode pattern) => SyntaxFactory.UnaryPattern(operatorToken, (PatternSyntax)Parenthesize(pattern)); - public override SyntaxNode LessThanPattern(SyntaxNode expression) - => SyntaxFactory.RelationalPattern(SyntaxFactory.Token(SyntaxKind.LessThanToken), (ExpressionSyntax)expression); - - public override SyntaxNode LessThanEqualsPattern(SyntaxNode expression) - => SyntaxFactory.RelationalPattern(SyntaxFactory.Token(SyntaxKind.LessThanEqualsToken), (ExpressionSyntax)expression); - - public override SyntaxNode GreaterThanPattern(SyntaxNode expression) - => SyntaxFactory.RelationalPattern(SyntaxFactory.Token(SyntaxKind.GreaterThanToken), (ExpressionSyntax)expression); - - public override SyntaxNode GreaterThanEqualsPattern(SyntaxNode expression) - => SyntaxFactory.RelationalPattern(SyntaxFactory.Token(SyntaxKind.GreaterThanEqualsToken), (ExpressionSyntax)expression); - #endregion } } diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/LanguageServices/SyntaxGeneratorInternalExtensions/SyntaxGeneratorInternal.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/LanguageServices/SyntaxGeneratorInternalExtensions/SyntaxGeneratorInternal.cs index a323bdda5aaa1..52d71722b3aad 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/LanguageServices/SyntaxGeneratorInternalExtensions/SyntaxGeneratorInternal.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/LanguageServices/SyntaxGeneratorInternalExtensions/SyntaxGeneratorInternal.cs @@ -100,8 +100,8 @@ public SyntaxNode LocalDeclarationStatement(SyntaxToken name, SyntaxNode initial public abstract SyntaxNode IsPatternExpression(SyntaxNode expression, SyntaxToken isToken, SyntaxNode pattern); public abstract SyntaxNode AndPattern(SyntaxNode left, SyntaxNode right); - public abstract SyntaxNode DeclarationPattern(INamedTypeSymbol type, string name); public abstract SyntaxNode ConstantPattern(SyntaxNode expression); + public abstract SyntaxNode DeclarationPattern(INamedTypeSymbol type, string name); public abstract SyntaxNode GreaterThanPattern(SyntaxNode expression); public abstract SyntaxNode GreaterThanEqualsPattern(SyntaxNode expression); public abstract SyntaxNode LessThanPattern(SyntaxNode expression); diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/VisualBasic/LanguageServices/VisualBasicSyntaxGeneratorInternal.vb b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/VisualBasic/LanguageServices/VisualBasicSyntaxGeneratorInternal.vb index f0739356f5344..18d3c61631def 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/VisualBasic/LanguageServices/VisualBasicSyntaxGeneratorInternal.vb +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/VisualBasic/LanguageServices/VisualBasicSyntaxGeneratorInternal.vb @@ -156,51 +156,51 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeGeneration Throw New NotImplementedException() End Function - Public Overrides Function ConstantPattern(expression As SyntaxNode) As SyntaxNode + Public Overrides Function AndPattern(left As SyntaxNode, right As SyntaxNode) As SyntaxNode Throw New NotImplementedException() End Function - Public Overrides Function DeclarationPattern(type As INamedTypeSymbol, name As String) As SyntaxNode + Public Overrides Function ConstantPattern(expression As SyntaxNode) As SyntaxNode Throw New NotImplementedException() End Function - Public Overrides Function AndPattern(left As SyntaxNode, right As SyntaxNode) As SyntaxNode + Public Overrides Function DeclarationPattern(type As INamedTypeSymbol, name As String) As SyntaxNode Throw New NotImplementedException() End Function - Public Overrides Function NotPattern(pattern As SyntaxNode) As SyntaxNode + Public Overrides Function LessThanPattern(expression As SyntaxNode) As SyntaxNode Throw New NotImplementedException() End Function - Public Overrides Function OrPattern(left As SyntaxNode, right As SyntaxNode) As SyntaxNode + Public Overrides Function LessThanEqualsPattern(expression As SyntaxNode) As SyntaxNode Throw New NotImplementedException() End Function - Public Overrides Function ParenthesizedPattern(pattern As SyntaxNode) As SyntaxNode + Public Overrides Function GreaterThanPattern(expression As SyntaxNode) As SyntaxNode Throw New NotImplementedException() End Function - Public Overrides Function TypePattern(type As SyntaxNode) As SyntaxNode + Public Overrides Function GreaterThanEqualsPattern(expression As SyntaxNode) As SyntaxNode Throw New NotImplementedException() End Function - Public Overrides Function UnaryPattern(operatorToken As SyntaxToken, pattern As SyntaxNode) As SyntaxNode + Public Overrides Function NotPattern(pattern As SyntaxNode) As SyntaxNode Throw New NotImplementedException() End Function - Public Overrides Function LessThanPattern(expression As SyntaxNode) As SyntaxNode + Public Overrides Function OrPattern(left As SyntaxNode, right As SyntaxNode) As SyntaxNode Throw New NotImplementedException() End Function - Public Overrides Function LessThanEqualsPattern(expression As SyntaxNode) As SyntaxNode + Public Overrides Function ParenthesizedPattern(pattern As SyntaxNode) As SyntaxNode Throw New NotImplementedException() End Function - Public Overrides Function GreaterThanPattern(expression As SyntaxNode) As SyntaxNode + Public Overrides Function TypePattern(type As SyntaxNode) As SyntaxNode Throw New NotImplementedException() End Function - Public Overrides Function GreaterThanEqualsPattern(expression As SyntaxNode) As SyntaxNode + Public Overrides Function UnaryPattern(operatorToken As SyntaxToken, pattern As SyntaxNode) As SyntaxNode Throw New NotImplementedException() End Function From a645ac1811f57ab697bd6657ea2100b5349a71cc Mon Sep 17 00:00:00 2001 From: Jacob Bundgaard Date: Tue, 11 Oct 2022 00:20:08 +0200 Subject: [PATCH 4/6] Rename syntax generator methods for relational patterns to include Relational in the name --- .../LanguageServices/CSharpSyntaxGeneratorInternal.cs | 8 ++++---- .../Core/Extensions/SyntaxGeneratorExtensions_Negate.cs | 8 ++++---- .../SyntaxGeneratorInternal.cs | 8 ++++---- .../VisualBasicSyntaxGeneratorInternal.vb | 8 ++++---- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/LanguageServices/CSharpSyntaxGeneratorInternal.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/LanguageServices/CSharpSyntaxGeneratorInternal.cs index 070bb0cd15c83..8f87f4b468b20 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/LanguageServices/CSharpSyntaxGeneratorInternal.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/LanguageServices/CSharpSyntaxGeneratorInternal.cs @@ -167,16 +167,16 @@ public override SyntaxNode DeclarationPattern(INamedTypeSymbol type, string name type.GenerateTypeSyntax(), SyntaxFactory.SingleVariableDesignation(name.ToIdentifierToken())); - public override SyntaxNode LessThanPattern(SyntaxNode expression) + public override SyntaxNode LessThanRelationalPattern(SyntaxNode expression) => SyntaxFactory.RelationalPattern(SyntaxFactory.Token(SyntaxKind.LessThanToken), (ExpressionSyntax)expression); - public override SyntaxNode LessThanEqualsPattern(SyntaxNode expression) + public override SyntaxNode LessThanEqualsRelationalPattern(SyntaxNode expression) => SyntaxFactory.RelationalPattern(SyntaxFactory.Token(SyntaxKind.LessThanEqualsToken), (ExpressionSyntax)expression); - public override SyntaxNode GreaterThanPattern(SyntaxNode expression) + public override SyntaxNode GreaterThanRelationalPattern(SyntaxNode expression) => SyntaxFactory.RelationalPattern(SyntaxFactory.Token(SyntaxKind.GreaterThanToken), (ExpressionSyntax)expression); - public override SyntaxNode GreaterThanEqualsPattern(SyntaxNode expression) + public override SyntaxNode GreaterThanEqualsRelationalPattern(SyntaxNode expression) => SyntaxFactory.RelationalPattern(SyntaxFactory.Token(SyntaxKind.GreaterThanEqualsToken), (ExpressionSyntax)expression); public override SyntaxNode NotPattern(SyntaxNode pattern) diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Extensions/SyntaxGeneratorExtensions_Negate.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Extensions/SyntaxGeneratorExtensions_Negate.cs index 0dca6cd6518ec..c2b666b6decf6 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Extensions/SyntaxGeneratorExtensions_Negate.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Extensions/SyntaxGeneratorExtensions_Negate.cs @@ -289,10 +289,10 @@ private static SyntaxNode GetNegationOfRelationalPattern( syntaxFacts.TryGetPredefinedOperator(operatorToken, out var predefinedOperator); return predefinedOperator switch { - PredefinedOperator.LessThan => generatorInternal.GreaterThanEqualsPattern(expression), - PredefinedOperator.LessThanOrEqual => generatorInternal.GreaterThanPattern(expression), - PredefinedOperator.GreaterThan => generatorInternal.LessThanEqualsPattern(expression), - PredefinedOperator.GreaterThanOrEqual => generatorInternal.LessThanPattern(expression), + PredefinedOperator.LessThan => generatorInternal.GreaterThanEqualsRelationalPattern(expression), + PredefinedOperator.LessThanOrEqual => generatorInternal.GreaterThanRelationalPattern(expression), + PredefinedOperator.GreaterThan => generatorInternal.LessThanEqualsRelationalPattern(expression), + PredefinedOperator.GreaterThanOrEqual => generatorInternal.LessThanRelationalPattern(expression), _ => throw ExceptionUtilities.UnexpectedValue(predefinedOperator) }; } diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/LanguageServices/SyntaxGeneratorInternalExtensions/SyntaxGeneratorInternal.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/LanguageServices/SyntaxGeneratorInternalExtensions/SyntaxGeneratorInternal.cs index 52d71722b3aad..f523bd222b5e7 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/LanguageServices/SyntaxGeneratorInternalExtensions/SyntaxGeneratorInternal.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/LanguageServices/SyntaxGeneratorInternalExtensions/SyntaxGeneratorInternal.cs @@ -102,10 +102,10 @@ public SyntaxNode LocalDeclarationStatement(SyntaxToken name, SyntaxNode initial public abstract SyntaxNode AndPattern(SyntaxNode left, SyntaxNode right); public abstract SyntaxNode ConstantPattern(SyntaxNode expression); public abstract SyntaxNode DeclarationPattern(INamedTypeSymbol type, string name); - public abstract SyntaxNode GreaterThanPattern(SyntaxNode expression); - public abstract SyntaxNode GreaterThanEqualsPattern(SyntaxNode expression); - public abstract SyntaxNode LessThanPattern(SyntaxNode expression); - public abstract SyntaxNode LessThanEqualsPattern(SyntaxNode expression); + public abstract SyntaxNode GreaterThanRelationalPattern(SyntaxNode expression); + public abstract SyntaxNode GreaterThanEqualsRelationalPattern(SyntaxNode expression); + public abstract SyntaxNode LessThanRelationalPattern(SyntaxNode expression); + public abstract SyntaxNode LessThanEqualsRelationalPattern(SyntaxNode expression); public abstract SyntaxNode NotPattern(SyntaxNode pattern); public abstract SyntaxNode OrPattern(SyntaxNode left, SyntaxNode right); public abstract SyntaxNode ParenthesizedPattern(SyntaxNode pattern); diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/VisualBasic/LanguageServices/VisualBasicSyntaxGeneratorInternal.vb b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/VisualBasic/LanguageServices/VisualBasicSyntaxGeneratorInternal.vb index 18d3c61631def..de4f014b21889 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/VisualBasic/LanguageServices/VisualBasicSyntaxGeneratorInternal.vb +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/VisualBasic/LanguageServices/VisualBasicSyntaxGeneratorInternal.vb @@ -168,19 +168,19 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeGeneration Throw New NotImplementedException() End Function - Public Overrides Function LessThanPattern(expression As SyntaxNode) As SyntaxNode + Public Overrides Function LessThanRelationalPattern(expression As SyntaxNode) As SyntaxNode Throw New NotImplementedException() End Function - Public Overrides Function LessThanEqualsPattern(expression As SyntaxNode) As SyntaxNode + Public Overrides Function LessThanEqualsRelationalPattern(expression As SyntaxNode) As SyntaxNode Throw New NotImplementedException() End Function - Public Overrides Function GreaterThanPattern(expression As SyntaxNode) As SyntaxNode + Public Overrides Function GreaterThanRelationalPattern(expression As SyntaxNode) As SyntaxNode Throw New NotImplementedException() End Function - Public Overrides Function GreaterThanEqualsPattern(expression As SyntaxNode) As SyntaxNode + Public Overrides Function GreaterThanEqualsRelationalPattern(expression As SyntaxNode) As SyntaxNode Throw New NotImplementedException() End Function From f76fac7b8af775d248ab553376e032ac194f5ab3 Mon Sep 17 00:00:00 2001 From: Jacob Bundgaard Date: Tue, 11 Oct 2022 00:32:45 +0200 Subject: [PATCH 5/6] Gracefully degrade to a not combinator when negating relational patterns with unexpected operators --- .../Core/Extensions/SyntaxGeneratorExtensions_Negate.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Extensions/SyntaxGeneratorExtensions_Negate.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Extensions/SyntaxGeneratorExtensions_Negate.cs index c2b666b6decf6..50e58743e93c9 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Extensions/SyntaxGeneratorExtensions_Negate.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Extensions/SyntaxGeneratorExtensions_Negate.cs @@ -293,7 +293,7 @@ private static SyntaxNode GetNegationOfRelationalPattern( PredefinedOperator.LessThanOrEqual => generatorInternal.GreaterThanRelationalPattern(expression), PredefinedOperator.GreaterThan => generatorInternal.LessThanEqualsRelationalPattern(expression), PredefinedOperator.GreaterThanOrEqual => generatorInternal.LessThanRelationalPattern(expression), - _ => throw ExceptionUtilities.UnexpectedValue(predefinedOperator) + _ => generatorInternal.NotPattern(expressionNode) }; } From b8435928e14c8284c38ac9658d37cda8e7d2aaa2 Mon Sep 17 00:00:00 2001 From: Jacob Bundgaard Date: Tue, 11 Oct 2022 01:07:32 +0200 Subject: [PATCH 6/6] Add test of inverting invalid relational pattern with == operator --- .../InvertLogical/InvertLogicalTests.cs | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/EditorFeatures/CSharpTest/InvertLogical/InvertLogicalTests.cs b/src/EditorFeatures/CSharpTest/InvertLogical/InvertLogicalTests.cs index 4659362493126..982a29b060689 100644 --- a/src/EditorFeatures/CSharpTest/InvertLogical/InvertLogicalTests.cs +++ b/src/EditorFeatures/CSharpTest/InvertLogical/InvertLogicalTests.cs @@ -654,6 +654,26 @@ void M(bool x, int a, object b) }", parseOptions: CSharp9); } + [Fact, WorkItem(64558, "https://github.com/dotnet/roslyn/issues/64558")] + public async Task InvertInvalidEqualsPattern1_CSharp9() + { + await TestInRegularAndScriptAsync( +@"class C +{ + void M(bool x, int a, object b) + { + var c = a > 10 [||]&& a is == 20; + } +}", +@"class C +{ + void M(bool x, int a, object b) + { + var c = !(a <= 10 || a is not == 20); + } +}", parseOptions: CSharp9); + } + [Fact, WorkItem(42368, "https://github.com/dotnet/roslyn/issues/42368")] public async Task InvertIsAndPattern1_CSharp8() {