From 8ea6d0d730bc4b74b5d1a9b08e01f0bf0346812c Mon Sep 17 00:00:00 2001 From: Robert Clipsham Date: Thu, 18 Apr 2019 10:36:06 +0100 Subject: [PATCH] Do not output private get/set for interfaces Closes #270 # Conflicts: # ICSharpCode.CodeConverter/CSharp/NodesVisitor.cs --- ICSharpCode.CodeConverter/CSharp/NodesVisitor.cs | 13 ++++++++++--- Tests/CSharp/MemberTests.cs | 16 +++++++++++++++- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/ICSharpCode.CodeConverter/CSharp/NodesVisitor.cs b/ICSharpCode.CodeConverter/CSharp/NodesVisitor.cs index 34632dd4b..6a6ab669a 100644 --- a/ICSharpCode.CodeConverter/CSharp/NodesVisitor.cs +++ b/ICSharpCode.CodeConverter/CSharp/NodesVisitor.cs @@ -455,6 +455,7 @@ public override CSharpSyntaxNode VisitPropertyStatement(VBSyntax.PropertyStateme var modifiers = CommonConversions.ConvertModifiers(convertibleModifiers, GetMemberContext(node)); var isIndexer = node.Modifiers.Any(m => SyntaxTokenExtensions.IsKind(m, VBasic.SyntaxKind.DefaultKeyword)); var accessedThroughMyClass = IsAccessedThroughMyClass(node, node.Identifier, _semanticModel.GetDeclaredSymbol(node)); + bool isInInterface = node.Ancestors().OfType().FirstOrDefault() != null; var initializer = (EqualsValueClauseSyntax)node.Initializer?.Accept(TriviaConvertingVisitor); var rawType = (TypeSyntax)node.AsClause?.TypeSwitch( @@ -476,9 +477,15 @@ public override CSharpSyntaxNode VisitPropertyStatement(VBSyntax.PropertyStateme if (isReadonly) { setAccessor = setAccessor.AddModifiers(SyntaxFactory.Token(SyntaxKind.PrivateKeyword)); } - // In VB, there's a backing field which can always be read and written to even on ReadOnly/WriteOnly properties. - // Our conversion will rewrite usages of that field to use the property accessors which therefore must exist and be private at minimum. - accessors = SyntaxFactory.AccessorList(SyntaxFactory.List(new[] {getAccessor, setAccessor})); + if (isInInterface && isReadonly) { + accessors = SyntaxFactory.AccessorList(SyntaxFactory.List(new[] { getAccessor })); + } else if (isInInterface && isWriteOnly) { + accessors = SyntaxFactory.AccessorList(SyntaxFactory.List(new[] { setAccessor })); + } else { + // In VB, there's a backing field which can always be read and written to even on ReadOnly/WriteOnly properties. + // Our conversion will rewrite usages of that field to use the property accessors which therefore must exist and be private at minimum. + accessors = SyntaxFactory.AccessorList(SyntaxFactory.List(new[] { getAccessor, setAccessor })); + } } else { accessors = SyntaxFactory.AccessorList( SyntaxFactory.List( diff --git a/Tests/CSharp/MemberTests.cs b/Tests/CSharp/MemberTests.cs index b47aa3f87..d0c6cff8a 100644 --- a/Tests/CSharp/MemberTests.cs +++ b/Tests/CSharp/MemberTests.cs @@ -321,6 +321,20 @@ public int Test3 }"); } + [Fact] + public void TestReadWriteOnlyInterfaceProperty() + { + TestConversionVisualBasicToCSharpWithoutComments( +@"Public Interface Foo + ReadOnly Property P1() As String + WriteOnly Property P2() As String +End Interface", @"public interface Foo +{ + string P1 { get; } + string P2 { set; } +}"); + } + [Fact] public void TestConstructor() { @@ -1259,7 +1273,7 @@ public void TestWriteOnlyProperties() WriteOnly Property Items As Integer() End Interface", @"interface TestInterface { - int[] Items { private get; set; } + int[] Items { set; } }"); }