Fixes #52 - NRE for arbitrary expressions in With Block

Flip the conditional to target the elvis expression instead which is the more specific case. Basically any statement can appear inside a with block
Also catch an obvious case of a missing argument list - would be good to look for more subtle ones of these
This commit is contained in:
GrahamTheCoder 2018-03-17 11:42:24 +00:00
Родитель e422c8c7d6
Коммит 12d050f431
2 изменённых файлов: 51 добавлений и 6 удалений

Просмотреть файл

@ -853,10 +853,9 @@ namespace ICSharpCode.CodeConverter.CSharp
var left = (ExpressionSyntax)node.Expression?.Accept(TriviaConvertingVisitor);
if (left == null) {
if (!node.Parent.Parent.IsKind(VBasic.SyntaxKind.WithBlock)) {
if (IsSubPartOfConditionalAccess(node)) {
return SyntaxFactory.MemberBindingExpression(simpleNameSyntax);
}
left = SyntaxFactory.IdentifierName(withBlockTempVariableNames.Peek());
}
@ -873,9 +872,23 @@ namespace ICSharpCode.CodeConverter.CSharp
return memberAccessExpressionSyntax;
}
private static bool IsSubPartOfConditionalAccess(VBSyntax.MemberAccessExpressionSyntax node)
{
var firstPossiblyConditionalAncestor = node.Parent;
while (firstPossiblyConditionalAncestor != null &&
firstPossiblyConditionalAncestor.IsKind(VBasic.SyntaxKind.InvocationExpression,
VBasic.SyntaxKind.SimpleMemberAccessExpression))
{
firstPossiblyConditionalAncestor = firstPossiblyConditionalAncestor.Parent;
}
return firstPossiblyConditionalAncestor?.IsKind(VBasic.SyntaxKind.ConditionalAccessExpression) == true;
}
public override CSharpSyntaxNode VisitConditionalAccessExpression(VBSyntax.ConditionalAccessExpressionSyntax node)
{
return SyntaxFactory.ConditionalAccessExpression((ExpressionSyntax)node.Expression.Accept(TriviaConvertingVisitor), (ExpressionSyntax)node.WhenNotNull.Accept(TriviaConvertingVisitor));
var leftExpression = (ExpressionSyntax)node.Expression?.Accept(TriviaConvertingVisitor) ?? SyntaxFactory.IdentifierName(withBlockTempVariableNames.Peek());
return SyntaxFactory.ConditionalAccessExpression(leftExpression, (ExpressionSyntax)node.WhenNotNull.Accept(TriviaConvertingVisitor));
}
public override CSharpSyntaxNode VisitArgumentList(VBSyntax.ArgumentListSyntax node)
@ -1290,7 +1303,7 @@ namespace ICSharpCode.CodeConverter.CSharp
return SyntaxFactory.InvocationExpression(
(ExpressionSyntax)node.Expression.Accept(TriviaConvertingVisitor),
(ArgumentListSyntax)node.ArgumentList.Accept(TriviaConvertingVisitor)
(ArgumentListSyntax)node.ArgumentList?.Accept(TriviaConvertingVisitor) ?? SyntaxFactory.ArgumentList()
);
}

Просмотреть файл

@ -243,7 +243,7 @@ class TestClass
Private Sub TestMethod()
With New System.Text.StringBuilder
.Capacity = 20
.Length = 0
?.Length = 0
End With
End Sub
End Class", @"using System;
@ -258,7 +258,39 @@ class TestClass
{
var withBlock = new System.Text.StringBuilder();
withBlock.Capacity = 20;
withBlock.Length = 0;
withBlock?.Length = 0;
}
}
}");
}
[Fact]
public void WithBlock2()
{
TestConversionVisualBasicToCSharpWithoutComments(@"Class TestClass
Private Sub Save()
Using cmd As SqlCommand = new SqlCommand()
With cmd
.ExecuteNonQuery()
?.ExecuteNonQuery()
.ExecuteNonQuery
?.ExecuteNonQuery
End With
End Using
End Sub
End Class", @"class TestClass
{
private void Save()
{
using (SqlCommand cmd = new SqlCommand())
{
{
var withBlock = cmd;
withBlock.ExecuteNonQuery();
withBlock?.ExecuteNonQuery();
withBlock.ExecuteNonQuery();
withBlock?.ExecuteNonQuery();
}
}
}
}");