Skip to content

Commit 13cd01b

Browse files
Accessors should always exist on VB auto-properties - fixes #237
Because of the backing field which can always be used
1 parent b19fb82 commit 13cd01b

3 files changed

Lines changed: 34 additions & 10 deletions

File tree

ICSharpCode.CodeConverter/CSharp/NodesVisitor.cs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using Microsoft.CodeAnalysis;
88
using Microsoft.CodeAnalysis.CSharp;
99
using Microsoft.CodeAnalysis.CSharp.Syntax;
10+
using Microsoft.CodeAnalysis.FindSymbols;
1011
using SyntaxFactory = Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
1112
using VBSyntax = Microsoft.CodeAnalysis.VisualBasic.Syntax;
1213
using VBasic = Microsoft.CodeAnalysis.VisualBasic;
@@ -449,15 +450,17 @@ public override CSharpSyntaxNode VisitPropertyStatement(VBSyntax.PropertyStateme
449450

450451
AccessorListSyntax accessors = null;
451452
if (!hasBody) {
452-
var accessorList = new List<AccessorDeclarationSyntax>();
453-
454-
if (!isWriteOnly) {
455-
accessorList.Add(SyntaxFactory.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration).WithSemicolonToken(SemicolonToken));
453+
var getAccessor = SyntaxFactory.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration).WithSemicolonToken(SemicolonToken);
454+
var setAccessor = SyntaxFactory.AccessorDeclaration(SyntaxKind.SetAccessorDeclaration).WithSemicolonToken(SemicolonToken);
455+
if (isWriteOnly) {
456+
getAccessor = getAccessor.AddModifiers(SyntaxFactory.Token(SyntaxKind.PrivateKeyword));
456457
}
457-
if (!isReadonly) {
458-
accessorList.Add(SyntaxFactory.AccessorDeclaration(SyntaxKind.SetAccessorDeclaration).WithSemicolonToken(SemicolonToken));
458+
if (isReadonly) {
459+
setAccessor = setAccessor.AddModifiers(SyntaxFactory.Token(SyntaxKind.PrivateKeyword));
459460
}
460-
accessors = SyntaxFactory.AccessorList(SyntaxFactory.List(accessorList));
461+
// In VB, there's a backing field which can always be read and written to even on ReadOnly/WriteOnly properties.
462+
// Our conversion will rewrite usages of that field to use the property accessors which therefore must exist and be private at minimum.
463+
accessors = SyntaxFactory.AccessorList(SyntaxFactory.List(new[] {getAccessor, setAccessor}));
461464
} else {
462465
accessors = SyntaxFactory.AccessorList(
463466
SyntaxFactory.List(

Tests/CSharp/ExpressionTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -594,7 +594,7 @@ class TestClass3
594594
{
595595
private class Rec
596596
{
597-
public Rec Prop { get; } = new Rec();
597+
public Rec Prop { get; private set; } = new Rec();
598598
}
599599
private Rec TestMethod(string str)
600600
{

Tests/CSharp/MemberTests.cs

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -699,7 +699,7 @@ Private ReadOnly Property First As New List(Of String)
699699
700700
class TestClass
701701
{
702-
private List<string> First { get; } = new List<string>();
702+
private List<string> First { get; private set; } = new List<string>();
703703
private int Second { get; set; } = 0;
704704
}");
705705
}
@@ -1258,7 +1258,28 @@ public void TestWriteOnlyProperties()
12581258
WriteOnly Property Items As Integer()
12591259
End Interface", @"interface TestInterface
12601260
{
1261-
int[] Items { set; }
1261+
int[] Items { private get; set; }
1262+
}");
1263+
}
1264+
1265+
[Fact]
1266+
public void TestImplicitPrivateSetter()
1267+
{
1268+
TestConversionVisualBasicToCSharp(
1269+
@"Public Class SomeClass
1270+
Public ReadOnly Property SomeValue As Integer
1271+
1272+
Public Sub SetValue(value1 As Integer, value2 As Integer)
1273+
_SomeValue = value1 + value2
1274+
End Sub
1275+
End Class", @"public class SomeClass
1276+
{
1277+
public int SomeValue { get; private set; }
1278+
1279+
public void SetValue(int value1, int value2)
1280+
{
1281+
SomeValue = value1 + value2;
1282+
}
12621283
}");
12631284
}
12641285

0 commit comments

Comments
 (0)