From 8c3352f703a7f53248fede1e8cdb13ee590bd867 Mon Sep 17 00:00:00 2001 From: GrahamTheCoder Date: Tue, 8 May 2018 00:07:49 +0100 Subject: [PATCH] Deal with accesorless properties fixes #119 --- ICSharpCode.CodeConverter/VB/NodesVisitor.cs | 78 +++++++++++--------- Tests/VB/MemberTests.cs | 24 ++++++ 2 files changed, 67 insertions(+), 35 deletions(-) diff --git a/ICSharpCode.CodeConverter/VB/NodesVisitor.cs b/ICSharpCode.CodeConverter/VB/NodesVisitor.cs index 4c288eb..e8d9a21 100644 --- a/ICSharpCode.CodeConverter/VB/NodesVisitor.cs +++ b/ICSharpCode.CodeConverter/VB/NodesVisitor.cs @@ -447,54 +447,62 @@ namespace ICSharpCode.CodeConverter.VB public override VisualBasicSyntaxNode VisitPropertyDeclaration(CSS.PropertyDeclarationSyntax node) { var id = CommonConversions.ConvertIdentifier(node.Identifier); - ConvertAndSplitAttributes(node.AttributeLists, out var attributes, out var returnAttributes); - bool isIterator = false; - List accessors = new List(); - var csAccessors = node.AccessorList.Accessors; - foreach (var a in csAccessors) { - accessors.Add(_commonConversions.ConvertAccessor(a, out var isAIterator)); - isIterator |= isAIterator; - } var modifiers = CommonConversions.ConvertModifiers(node.Modifiers, TokenContext.Member); - if (isIterator) modifiers = modifiers.Add(SyntaxFactory.Token(SyntaxKind.IteratorKeyword)); - var accessLimitationTokens = GetAccessLimitationTokens(csAccessors); - modifiers = modifiers.AddRange(accessLimitationTokens); - var stmt = SyntaxFactory.PropertyStatement( - attributes, - modifiers, - id, null, - SyntaxFactory.SimpleAsClause(returnAttributes, (TypeSyntax)node.Type.Accept(TriviaConvertingVisitor)), - node.Initializer == null ? null : SyntaxFactory.EqualsValue((ExpressionSyntax) _commonConversions.ConvertTopLevelExpression(node.Initializer.Value)), null - ); - - if (HasNoAccessorBody(node.AccessorList)) - return stmt; - return SyntaxFactory.PropertyBlock(stmt, SyntaxFactory.List(accessors)); + var initializer = node.Initializer == null ? null + : SyntaxFactory.EqualsValue((ExpressionSyntax)_commonConversions.ConvertTopLevelExpression(node.Initializer.Value)); + return ConvertPropertyBlock(node, id, modifiers, null, node.ExpressionBody, initializer); } public override VisualBasicSyntaxNode VisitIndexerDeclaration(CSS.IndexerDeclarationSyntax node) { var id = SyntaxFactory.Identifier("Item"); + var modifiers = CommonConversions.ConvertModifiers(node.Modifiers, TokenContext.Member).Insert(0, SyntaxFactory.Token(SyntaxKind.DefaultKeyword)); + var parameterListSyntax = (ParameterListSyntax) node.ParameterList?.Accept(TriviaConvertingVisitor); + return ConvertPropertyBlock(node, id, modifiers, parameterListSyntax, node.ExpressionBody, null); + } + + private VisualBasicSyntaxNode ConvertPropertyBlock(CSS.BasePropertyDeclarationSyntax node, + SyntaxToken id, SyntaxTokenList modifiers, + ParameterListSyntax parameterListSyntax, CSS.ArrowExpressionClauseSyntax arrowExpressionClauseSyntax, + EqualsValueSyntax initializerOrNull) + { ConvertAndSplitAttributes(node.AttributeLists, out SyntaxList attributes, out SyntaxList returnAttributes); + bool isIterator = false; List accessors = new List(); - var csAccessors = node.AccessorList.Accessors; - foreach (var a in csAccessors) { - accessors.Add(_commonConversions.ConvertAccessor(a, out var isAIterator)); - isIterator |= isAIterator; + var hasAccessors = node.AccessorList != null; + if (hasAccessors) { + var csAccessors = node.AccessorList.Accessors; + foreach (var a in csAccessors) + { + accessors.Add(_commonConversions.ConvertAccessor(a, out var isAIterator)); + isIterator |= isAIterator; + } + + var accessLimitationTokens = GetAccessLimitationTokens(csAccessors); + modifiers = modifiers.AddRange(accessLimitationTokens); + if (isIterator) modifiers = modifiers.Add(SyntaxFactory.Token(SyntaxKind.IteratorKeyword)); } - var modifiers = CommonConversions.ConvertModifiers(node.Modifiers, TokenContext.Member).Insert(0, SyntaxFactory.Token(SyntaxKind.DefaultKeyword)); - if (isIterator) modifiers = modifiers.Add(SyntaxFactory.Token(SyntaxKind.IteratorKeyword)); - var accessLimitationTokens = GetAccessLimitationTokens(csAccessors); - modifiers = modifiers.AddRange(accessLimitationTokens); - var parameterList = (ParameterListSyntax)node.ParameterList?.Accept(TriviaConvertingVisitor); + else { + StatementSyntax expressionStatementSyntax = + SyntaxFactory.ReturnStatement( + (ExpressionSyntax) arrowExpressionClauseSyntax.Expression.Accept(TriviaConvertingVisitor)); + var accessorStatementSyntax = SyntaxFactory.AccessorStatement(SyntaxKind.GetAccessorStatement, + SyntaxFactory.Token(SyntaxKind.GetKeyword)); + accessors.Add(SyntaxFactory.GetAccessorBlock(accessorStatementSyntax, + SyntaxFactory.SingletonList(expressionStatementSyntax), SyntaxFactory.EndGetStatement())); + modifiers = modifiers.Add(SyntaxFactory.Token(SyntaxKind.ReadOnlyKeyword)); + } + var stmt = SyntaxFactory.PropertyStatement( attributes, modifiers, - id, parameterList, - SyntaxFactory.SimpleAsClause(returnAttributes, (TypeSyntax)node.Type.Accept(TriviaConvertingVisitor)), null, null + id, parameterListSyntax, + SyntaxFactory.SimpleAsClause(returnAttributes, (TypeSyntax) node.Type.Accept(TriviaConvertingVisitor)), + initializerOrNull, + null ); - if (HasNoAccessorBody(node.AccessorList)) + if (hasAccessors && HasNoAccessorBody(node.AccessorList)) return stmt; return SyntaxFactory.PropertyBlock(stmt, SyntaxFactory.List(accessors)); } @@ -511,7 +519,7 @@ namespace ICSharpCode.CodeConverter.VB private static bool HasNoAccessorBody(CSS.AccessorListSyntax accessorListSyntaxOrNull) { - return accessorListSyntaxOrNull?.Accessors.All(a => a.Body == null && a.ExpressionBody == null) == true; + return accessorListSyntaxOrNull.Accessors.All(a => a.Body == null && a.ExpressionBody == null); } public override VisualBasicSyntaxNode VisitEventDeclaration(CSS.EventDeclarationSyntax node) diff --git a/Tests/VB/MemberTests.cs b/Tests/VB/MemberTests.cs index ce65158..ad6ada4 100644 --- a/Tests/VB/MemberTests.cs +++ b/Tests/VB/MemberTests.cs @@ -269,6 +269,30 @@ End Class"); End Class"); } + [Fact] + public void TestOmmittedAccessorsReplacedWithExpressionBody() + { + TestConversionCSharpToVisualBasic( + @"class MyFavColor +{ + private string[] favColor => new string[] {""Red"", ""Green""}; + public string this[int index] => favColor[index]; +} +", @"Class MyFavColor + Private ReadOnly Property favColor As String() + Get + Return New String() {""Red"", ""Green""} + End Get + End Property + + Default Public ReadOnly Property Item(ByVal index As Integer) As String + Get + Return favColor(index) + End Get + End Property +End Class"); + } + [Fact] public void TestPropertyWithExpressionBodyThatCanBeStatement() {