diff --git a/src/EditorFeatures/Test2/Simplification/CastSimplificationTests.vb b/src/EditorFeatures/Test2/Simplification/CastSimplificationTests.vb index 0cf6227f8e20d318a0120feaa722b571344f7475..fa80e3db1cadf8c8fada73bfa70cdc29c4608780 100644 --- a/src/EditorFeatures/Test2/Simplification/CastSimplificationTests.vb +++ b/src/EditorFeatures/Test2/Simplification/CastSimplificationTests.vb @@ -4125,9 +4125,10 @@ class Program Test(input, expected) - End SUb + End Sub + - + Public Sub CSharp_Remove_UnncessaryCastInExpressionBody_Method() Dim input = @@ -4149,6 +4150,52 @@ class Program public int X() => 0; } ]]> + + + Test(input, expected) + End Sub + + + + Public Sub CSharp_DoNotRemove_NecessaryCastInConditionAccess() + Dim input = + + + + + + + + Dim expected = + Test(input, expected) @@ -7115,6 +7162,50 @@ Class Program End Sub End Class ]]> + + + Test(input, expected) + End Sub + + + + Public Sub VisualBasic_DoNotRemove_NecessaryCastInConditionAccess() + Dim input = + + + + + + + + Dim expected = + Test(input, expected) diff --git a/src/Workspaces/CSharp/Portable/Utilities/SpeculationAnalyzer.cs b/src/Workspaces/CSharp/Portable/Utilities/SpeculationAnalyzer.cs index 5a494cc97528d6e38af96167e4523bf5f522a241..a17a8da2393a1adb7bb076b1275a549b3437f21c 100644 --- a/src/Workspaces/CSharp/Portable/Utilities/SpeculationAnalyzer.cs +++ b/src/Workspaces/CSharp/Portable/Utilities/SpeculationAnalyzer.cs @@ -279,6 +279,10 @@ protected override bool ReplacementChangesSemanticsForNodeLanguageSpecific(Synta // If replacing the node will result in a broken binary expression, we won't remove it. return ReplacementBreaksBinaryExpression((BinaryExpressionSyntax)currentOriginalNode, (BinaryExpressionSyntax)currentReplacedNode); } + else if (currentOriginalNode.Kind() == SyntaxKind.ConditionalAccessExpression) + { + return ReplacementBreaksConditionalAccessExpression((ConditionalAccessExpressionSyntax)currentOriginalNode, (ConditionalAccessExpressionSyntax)currentReplacedNode); + } else if (currentOriginalNode is AssignmentExpressionSyntax) { // If replacing the node will result in a broken assignment expression, we won't remove it. @@ -561,6 +565,14 @@ private bool ReplacementBreaksBinaryExpression(BinaryExpressionSyntax binaryExpr !ImplicitConversionsAreCompatible(binaryExpression, newBinaryExpression); } + private bool ReplacementBreaksConditionalAccessExpression(ConditionalAccessExpressionSyntax conditionalAccessExpression, ConditionalAccessExpressionSyntax newConditionalAccessExpression) + { + return !SymbolsAreCompatible(conditionalAccessExpression, newConditionalAccessExpression) || + !TypesAreCompatible(conditionalAccessExpression, newConditionalAccessExpression) || + !SymbolsAreCompatible(conditionalAccessExpression.WhenNotNull, newConditionalAccessExpression.WhenNotNull) || + !TypesAreCompatible(conditionalAccessExpression.WhenNotNull, newConditionalAccessExpression.WhenNotNull); + } + private bool ReplacementBreaksIsOrAsExpression(BinaryExpressionSyntax originalIsOrAsExpression, BinaryExpressionSyntax newIsOrAsExpression) { // Special case: Lambda expressions and anonymous delegates cannot appear diff --git a/src/Workspaces/VisualBasic/Portable/Utilities/SpeculationAnalyzer.vb b/src/Workspaces/VisualBasic/Portable/Utilities/SpeculationAnalyzer.vb index 2e6fad58afb38525ad57e1dc278d17385fd32121..dd12c59038598fa091d3bb10db9b1dd71b5804db 100644 --- a/src/Workspaces/VisualBasic/Portable/Utilities/SpeculationAnalyzer.vb +++ b/src/Workspaces/VisualBasic/Portable/Utilities/SpeculationAnalyzer.vb @@ -328,6 +328,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Utilities End If Return Not ImplicitConversionsAreCompatible(originalExpression, newExpression) + ElseIf currentOriginalNode.Kind = SyntaxKind.ConditionalAccessExpression + Dim originalExpression = DirectCast(currentOriginalNode, ConditionalAccessExpressionSyntax) + Dim newExpression = DirectCast(currentReplacedNode, ConditionalAccessExpressionSyntax) + Return ReplacementBreaksConditionalAccessExpression(originalExpression, newExpression) ElseIf currentOriginalNode.Kind = SyntaxKind.VariableDeclarator Then ' Heuristic: If replacing the node will result in changing the type of a local variable ' that is type-inferred, we won't remove it. It's possible to do this analysis, but it's @@ -470,6 +474,13 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Utilities Not TypesAreCompatible(binaryExpression, newBinaryExpression) End Function + Private Function ReplacementBreaksConditionalAccessExpression(conditionalAccessExpression As ConditionalAccessExpressionSyntax, newConditionalAccessExpression As ConditionalAccessExpressionSyntax) As Boolean + Return Not SymbolsAreCompatible(conditionalAccessExpression, newConditionalAccessExpression) OrElse + Not TypesAreCompatible(conditionalAccessExpression, newConditionalAccessExpression) OrElse + Not SymbolsAreCompatible(conditionalAccessExpression.WhenNotNull, newConditionalAccessExpression.WhenNotNull) OrElse + Not TypesAreCompatible(conditionalAccessExpression.WhenNotNull, newConditionalAccessExpression.WhenNotNull) + End Function + Protected Overrides Function GetForEachStatementExpression(forEachStatement As ForEachStatementSyntax) As ExpressionSyntax Return forEachStatement.Expression End Function