Skip to content

Commit 01a4ddb

Browse files
Merge pull request #21 from GrahamTheCoder/fix-1174-vb-with-block-null-conditional-12294486853097276888
Fix VB With block conversion with null-conditional operator
2 parents cace870 + 63806cf commit 01a4ddb

File tree

2 files changed

+54
-9
lines changed

2 files changed

+54
-9
lines changed

CodeConverter/CSharp/NameExpressionNodeVisitor.cs

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using System.Data;
1+
using System.Data;
22
using System.Globalization;
33
using ICSharpCode.CodeConverter.CSharp.Replacements;
44
using ICSharpCode.CodeConverter.Util.FromRoslyn;
@@ -688,14 +688,19 @@ private static QualifiedNameSyntax Qualify(string qualification, ExpressionSynta
688688

689689
private static bool IsSubPartOfConditionalAccess(VBasic.Syntax.MemberAccessExpressionSyntax node)
690690
{
691-
var firstPossiblyConditionalAncestor = node.Parent;
692-
while (firstPossiblyConditionalAncestor != null &&
693-
firstPossiblyConditionalAncestor.IsKind(VBasic.SyntaxKind.InvocationExpression,
694-
VBasic.SyntaxKind.SimpleMemberAccessExpression)) {
695-
firstPossiblyConditionalAncestor = firstPossiblyConditionalAncestor.Parent;
691+
static bool IsMemberAccessChain(SyntaxNode exp) =>
692+
exp?.IsKind(VBasic.SyntaxKind.InvocationExpression,
693+
VBasic.SyntaxKind.SimpleMemberAccessExpression,
694+
VBasic.SyntaxKind.ParenthesizedExpression,
695+
VBasic.SyntaxKind.ConditionalAccessExpression) == true;
696+
697+
for (SyntaxNode child = node, parent = node.Parent; IsMemberAccessChain(parent); child = parent, parent = parent.Parent) {
698+
if (parent is VBSyntax.ConditionalAccessExpressionSyntax cae && cae.WhenNotNull == child) {
699+
return true; // On right hand side of a ?. conditional access
700+
}
696701
}
697702

698-
return firstPossiblyConditionalAncestor?.IsKind(VBasic.SyntaxKind.ConditionalAccessExpression) == true;
703+
return false;
699704
}
700705

701706
private static CSharpSyntaxNode ReplaceRightmostIdentifierText(CSharpSyntaxNode expr, SyntaxToken idToken, string overrideIdentifier)

Tests/CSharp/StatementTests/MethodStatementTests.cs

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using System.Threading.Tasks;
1+
using System.Threading.Tasks;
22
using ICSharpCode.CodeConverter.Tests.TestRunners;
33
using Xunit;
44

@@ -1673,4 +1673,44 @@ public object Func()
16731673
}
16741674
}");
16751675
}
1676-
}
1676+
1677+
[Fact]
1678+
public async Task WithBlockWithNullConditionalAccessAsync()
1679+
{
1680+
await TestConversionVisualBasicToCSharpAsync(@"
1681+
Public Class Class1
1682+
Public Property x As Class1
1683+
Public Property Name As String
1684+
End Class
1685+
1686+
Public Class TestClass
1687+
Private _Data As Class1
1688+
Private x As String
1689+
1690+
Public Sub TestMethod()
1691+
With _Data
1692+
x = .x?.Name
1693+
End With
1694+
End Sub
1695+
End Class", @"
1696+
public partial class Class1
1697+
{
1698+
public Class1 x { get; set; }
1699+
public string Name { get; set; }
1700+
}
1701+
1702+
public partial class TestClass
1703+
{
1704+
private Class1 _Data;
1705+
private string x;
1706+
1707+
public void TestMethod()
1708+
{
1709+
{
1710+
ref var withBlock = ref _Data;
1711+
x = withBlock.x?.Name;
1712+
}
1713+
}
1714+
}");
1715+
}
1716+
}

0 commit comments

Comments
 (0)