提交 fa0269b0 编写于 作者: D Dustin Campbell

Make VB Remove Unnecessary Cast a bit smarter in interpolations

There are legitimate cases where removing a cast inside a string
interpolation can case the open brace of the interpolation to touch the
open brace on an array literal, resulting in a broken parse (i.e. `{{`).

This changes the Remove Unnecesary Cast code fix to add parentheses
outside of the cast rather than around the inner expression. Then, the
parenthesis simplifier has been updated to correctly handle the case
where an array literal touches the start of an interpolation:

Dim x = $"{({})}"

Fixes Issue #739.
上级 277a250a
......@@ -2481,6 +2481,7 @@ Class Program
End Sub
End Class
</File>
Test(markup, expected, compareTokens:=False)
End Sub
......@@ -2572,6 +2573,68 @@ End Module
</File>
Test(markup, expected, compareTokens:=False)
End Sub
#End Region
<WorkItem(739, "#739")>
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnnecessaryCast)>
Public Sub RemoveAroundArrayLiteralInInterpolation1()
Dim markup =
<File>
Module M
Dim x = $"{ [|CObj({})|] }" ' Remove unnecessary cast
End Module
</File>
Dim expected =
<File>
Module M
Dim x = $"{ {} }" ' Remove unnecessary cast
End Module
</File>
Test(markup, expected, compareTokens:=False)
End Sub
<WorkItem(739, "#739")>
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnnecessaryCast)>
Public Sub RemoveAroundArrayLiteralInInterpolation2()
Dim markup =
<File>
Module M
Dim x = $"{[|CObj({})|] }" ' Remove unnecessary cast
End Module
</File>
Dim expected =
<File>
Module M
Dim x = $"{({}) }" ' Remove unnecessary cast
End Module
</File>
Test(markup, expected, compareTokens:=False)
End Sub
<WorkItem(739, "#739")>
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnnecessaryCast)>
Public Sub RemoveAroundArrayLiteralInInterpolation3()
Dim markup =
<File>
Module M
Dim x = $"{ [|CObj({})|]}" ' Remove unnecessary cast
End Module
</File>
Dim expected =
<File>
Module M
Dim x = $"{ {}}" ' Remove unnecessary cast
End Module
</File>
Test(markup, expected, compareTokens:=False)
End Sub
End Class
End Namespace
......@@ -19,14 +19,15 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeFixes.RemoveUnnecessaryCast
If TypeOf expression Is ParenthesizedExpressionSyntax Then
Return expression.WithAdditionalAnnotations(Simplifier.Annotation)
Else
Return expression.Parenthesize()
Return expression
End If
End Function
Public Overrides Function VisitCTypeExpression(node As CTypeExpressionSyntax) As SyntaxNode
If node Is _castExpression Then
Return node.WithExpression(GetExpression(node.Expression)) _
.WithAdditionalAnnotations(Simplifier.Annotation)
.WithAdditionalAnnotations(Simplifier.Annotation) _
.Parenthesize()
End If
Return MyBase.VisitCTypeExpression(node)
......@@ -35,7 +36,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeFixes.RemoveUnnecessaryCast
Public Overrides Function VisitDirectCastExpression(node As DirectCastExpressionSyntax) As SyntaxNode
If node Is _castExpression Then
Return node.WithExpression(GetExpression(node.Expression)) _
.WithAdditionalAnnotations(Simplifier.Annotation)
.WithAdditionalAnnotations(Simplifier.Annotation) _
.Parenthesize()
End If
Return MyBase.VisitDirectCastExpression(node)
......@@ -44,7 +46,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeFixes.RemoveUnnecessaryCast
Public Overrides Function VisitTryCastExpression(node As TryCastExpressionSyntax) As SyntaxNode
If node Is _castExpression Then
Return node.WithExpression(GetExpression(node.Expression)) _
.WithAdditionalAnnotations(Simplifier.Annotation)
.WithAdditionalAnnotations(Simplifier.Annotation) _
.Parenthesize()
End If
Return MyBase.VisitTryCastExpression(node)
......@@ -53,7 +56,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeFixes.RemoveUnnecessaryCast
Public Overrides Function VisitPredefinedCastExpression(node As PredefinedCastExpressionSyntax) As SyntaxNode
If node Is _castExpression Then
Return node.WithExpression(GetExpression(node.Expression)) _
.WithAdditionalAnnotations(Simplifier.Annotation)
.WithAdditionalAnnotations(Simplifier.Annotation) _
.Parenthesize()
End If
Return MyBase.VisitPredefinedCastExpression(node)
......
......@@ -117,6 +117,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeFixes.RemoveUnnecessaryCast
' Finally, rewrite the cast expression
Dim exprToRewrite As ExpressionSyntax = Nothing
Dim annotatedNodes = Await FindNodesWithAnnotationAsync(_expressionAnnotation, document, cancellationToken).ConfigureAwait(False)
For Each annotatedNode In annotatedNodes
exprToRewrite = TryCast(annotatedNode.AsNode, ExpressionSyntax)
If exprToRewrite IsNot Nothing AndAlso exprToRewrite.IsKind(originalExpr.Kind) Then
......@@ -138,9 +139,25 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeFixes.RemoveUnnecessaryCast
End If
Dim rewriter = New Rewriter(exprToRewrite)
Dim newExpression = rewriter.Visit(exprToRewrite).WithoutAnnotations(_expressionAnnotation)
Dim newExpression = rewriter.Visit(exprToRewrite)
' Remove the annotation from the expression so that it isn't hanging around later.
If newExpression.HasAnnotation(_expressionAnnotation) Then
newExpression = newExpression.WithoutAnnotations(_expressionAnnotation)
ElseIf newExpression.IsKind(SyntaxKind.ParenthesizedExpression) Then
Dim parenthesizedExpression = DirectCast(newExpression, ParenthesizedExpressionSyntax)
If parenthesizedExpression.Expression.HasAnnotation(_expressionAnnotation) Then
newExpression = parenthesizedExpression _
.WithExpression(parenthesizedExpression.Expression.WithoutAnnotations(_expressionAnnotation))
End If
End If
document = Await document.ReplaceNodeAsync(exprToRewrite, newExpression, cancellationToken).ConfigureAwait(False)
If annotatedNodes.Count > 1 Then
Return Await RewriteCoreAsync(document, originalExpr, cancellationToken).ConfigureAwait(False)
End If
......
......@@ -3,7 +3,6 @@
Imports System.Runtime.CompilerServices
Imports System.Threading
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Imports Microsoft.CodeAnalysis.VisualBasic.Extensions
Namespace Microsoft.CodeAnalysis.VisualBasic.Extensions
Friend Module ParenthesizedExpressionSyntaxExtensions
......@@ -111,9 +110,24 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Extensions
' Cases:
' List(Of Integer()) From {({1})} -to- {({1})}
' List(Of Integer()) From {{({1})}} -to- {{{1}}}
' $"{ ({1}) } - to- $"{ {1} }"
' {({1})} -to- {({1})}
' ({1}) -to- {1}
If expression.IsKind(SyntaxKind.CollectionInitializer) Then
If node.IsParentKind(SyntaxKind.Interpolation) Then
Dim interpolation = DirectCast(node.Parent, InterpolationSyntax)
If interpolation.OpenBraceToken.Span.End = node.OpenParenToken.Span.Start AndAlso
node.OpenParenToken.Span.End = expression.Span.Start Then
' In an interpolation, we need to be careful not to remove a parenthesis if it touches a curly brace
' on the left and the right. Otherwise, code will parse differently.
Return False
End If
End If
If Not node.IsParentKind(SyntaxKind.CollectionInitializer) Then
' Standalone parenthesized array literal.
' Parentheses are insignificant.
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册