diff --git a/ICSharpCode.CodeConverter/CSharp/MethodBodyVisitor.cs b/ICSharpCode.CodeConverter/CSharp/MethodBodyVisitor.cs index 62a3ae4..a3d12dc 100644 --- a/ICSharpCode.CodeConverter/CSharp/MethodBodyVisitor.cs +++ b/ICSharpCode.CodeConverter/CSharp/MethodBodyVisitor.cs @@ -1,4 +1,5 @@ using System; +using System.Collections; using System.Collections.Generic; using System.Linq; using ICSharpCode.CodeConverter.Shared; @@ -6,6 +7,7 @@ using ICSharpCode.CodeConverter.Util; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; +using SyntaxFactory = Microsoft.CodeAnalysis.CSharp.SyntaxFactory; using VBasic = Microsoft.CodeAnalysis.VisualBasic; using VBSyntax = Microsoft.CodeAnalysis.VisualBasic.Syntax; @@ -101,6 +103,159 @@ namespace ICSharpCode.CodeConverter.CSharp return SingleStatement(SyntaxFactory.AssignmentExpression(kind, (ExpressionSyntax)node.Left.Accept(nodesVisitor), (ExpressionSyntax)node.Right.Accept(nodesVisitor))); } + public override SyntaxList VisitEraseStatement(VBSyntax.EraseStatementSyntax node) + { + var eraseStatements = node.Expressions.Select(arrayExpression => { + var lhs = arrayExpression.Accept(nodesVisitor); + var rhs = SyntaxFactory.LiteralExpression(SyntaxKind.NullLiteralExpression); + var assignmentExpressionSyntax = + SyntaxFactory.AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, (ExpressionSyntax)lhs, + rhs); + return SyntaxFactory.ExpressionStatement(assignmentExpressionSyntax); + }); + return SyntaxFactory.List(eraseStatements); + } + + public override SyntaxList VisitReDimStatement(VBSyntax.ReDimStatementSyntax node) + { + return SyntaxFactory.List(node.Clauses.SelectMany(arrayExpression => arrayExpression.Accept(CommentConvertingVisitor))); + } + + public override SyntaxList VisitRedimClause(VBSyntax.RedimClauseSyntax node) + { + bool preserve = node.Parent is VBSyntax.ReDimStatementSyntax rdss && rdss.PreserveKeyword.IsKind(VBasic.SyntaxKind.PreserveKeyword); + + var csTargetArrayExpression = (ExpressionSyntax) node.Expression.Accept(nodesVisitor); + var convertedBounds = ConvertArrayBounds(node.ArrayBounds, semanticModel, nodesVisitor).ToList(); + + var newArrayAssignment = CreateNewArrayAssignment(node.Expression, csTargetArrayExpression, convertedBounds, node.SpanStart); + if (!preserve) return SingleStatement(newArrayAssignment); + + var oldTargetName = GetUniqueVariableNameInScope(node, "old" + csTargetArrayExpression.ToString().ToPascalCase()); + var oldArrayAssignment = CreateLocalVariableDeclarationAndAssignment(oldTargetName, csTargetArrayExpression); + + var oldTargetExpression = SyntaxFactory.IdentifierName(oldTargetName); + var arrayCopyIfNotNull = CreateConditionalArrayCopy(oldTargetExpression, csTargetArrayExpression, convertedBounds); + + return SyntaxFactory.List(new StatementSyntax[] {oldArrayAssignment, newArrayAssignment, arrayCopyIfNotNull}); + } + + /// + /// Cut down version of Microsoft.VisualBasic.CompilerServices.Utils.CopyArray + /// + private IfStatementSyntax CreateConditionalArrayCopy(IdentifierNameSyntax sourceArrayExpression, + ExpressionSyntax targetArrayExpression, + List convertedBounds) + { + var sourceLength = SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, sourceArrayExpression, SyntaxFactory.IdentifierName("Length")); + var arrayCopyStatement = convertedBounds.Count == 1 + ? CreateArrayCopyWithMinOfLengths(sourceArrayExpression, sourceLength, targetArrayExpression, convertedBounds.Single()) + : CreateArrayCopy(sourceArrayExpression, sourceLength, targetArrayExpression, convertedBounds); + + var oldTargetNotEqualToNull = SyntaxFactory.BinaryExpression(SyntaxKind.NotEqualsExpression, sourceArrayExpression, + SyntaxFactory.LiteralExpression(SyntaxKind.NullLiteralExpression)); + return SyntaxFactory.IfStatement(oldTargetNotEqualToNull, arrayCopyStatement); + } + + /// + /// Array copy for multiple array dimensions represented by + /// + /// + /// Exception cases will sometimes silently succeed in the converted code, + /// but existing VB code relying on the exception thrown from a multidimensional redim preserve on + /// different rank arrays is hopefully rare enough that it's worth saving a few lines of code + /// + private StatementSyntax CreateArrayCopy(IdentifierNameSyntax sourceArrayExpression, + MemberAccessExpressionSyntax sourceLength, + ExpressionSyntax targetArrayExpression, ICollection convertedBounds) + { + var lastSourceLengthArgs = CreateArgList(Literal(convertedBounds.Count - 1)); + var sourceLastRankLength = SyntaxFactory.InvocationExpression( + SyntaxFactory.ParseExpression($"{sourceArrayExpression.Identifier}.GetLength"), lastSourceLengthArgs); + var targetLastRankLength = + SyntaxFactory.InvocationExpression(SyntaxFactory.ParseExpression($"{targetArrayExpression}.GetLength"), + lastSourceLengthArgs); + var length = SyntaxFactory.InvocationExpression(SyntaxFactory.ParseExpression("Math.Min"), + CreateArgList(sourceLastRankLength, targetLastRankLength)); + + var loopVariableName = GetUniqueVariableNameInScope(sourceArrayExpression, "i"); + var loopVariableIdentifier = SyntaxFactory.IdentifierName(loopVariableName); + var sourceStartForThisIteration = + SyntaxFactory.BinaryExpression(SyntaxKind.MultiplyExpression, loopVariableIdentifier, sourceLastRankLength); + var targetStartForThisIteration = + SyntaxFactory.BinaryExpression(SyntaxKind.MultiplyExpression, loopVariableIdentifier, targetLastRankLength); + + var arrayCopy = CreateArrayCopyWithStartingPoints(sourceArrayExpression, sourceStartForThisIteration, targetArrayExpression, + targetStartForThisIteration, length); + + var sourceArrayCount = SyntaxFactory.BinaryExpression(SyntaxKind.SubtractExpression, + SyntaxFactory.BinaryExpression(SyntaxKind.DivideExpression, sourceLength, sourceLastRankLength), + Literal(1)); + + return CreateForZeroToValueLoop(loopVariableIdentifier, arrayCopy, sourceArrayCount); + } + + private static ForStatementSyntax CreateForZeroToValueLoop(SimpleNameSyntax loopVariableIdentifier, StatementSyntax loopStatement, ExpressionSyntax inclusiveLoopUpperBound) + { + var loopVariableAssignment = CreateVariableDeclarationAndAssignment(loopVariableIdentifier.Identifier.Text, Literal(0)); + var lessThanSourceBounds = SyntaxFactory.BinaryExpression(SyntaxKind.LessThanOrEqualExpression, + loopVariableIdentifier, inclusiveLoopUpperBound); + var incrementors = SyntaxFactory.SingletonSeparatedList( + SyntaxFactory.PrefixUnaryExpression(SyntaxKind.PreIncrementExpression, loopVariableIdentifier)); + var forStatementSyntax = SyntaxFactory.ForStatement(loopVariableAssignment, + SyntaxFactory.SeparatedList(), + lessThanSourceBounds, incrementors, loopStatement); + return forStatementSyntax; + } + + private static ExpressionStatementSyntax CreateArrayCopyWithMinOfLengths( + IdentifierNameSyntax sourceExpression, ExpressionSyntax sourceLength, + ExpressionSyntax targetExpression, ExpressionSyntax targetLength) + { + var minLength = SyntaxFactory.InvocationExpression(SyntaxFactory.ParseExpression("Math.Min"), + CreateArgList(targetLength, sourceLength)); + var copyArgList = CreateArgList(sourceExpression, targetExpression, minLength); + var arrayCopy = SyntaxFactory.InvocationExpression(SyntaxFactory.ParseExpression("Array.Copy"), copyArgList); + return SyntaxFactory.ExpressionStatement(arrayCopy); + } + + private static ExpressionStatementSyntax CreateArrayCopyWithStartingPoints( + IdentifierNameSyntax sourceExpression, ExpressionSyntax sourceStart, + ExpressionSyntax targetExpression, ExpressionSyntax targetStart, ExpressionSyntax length) + { + var copyArgList = CreateArgList(sourceExpression, sourceStart, targetExpression, targetStart, length); + var arrayCopy = SyntaxFactory.InvocationExpression(SyntaxFactory.ParseExpression("Array.Copy"), copyArgList); + return SyntaxFactory.ExpressionStatement(arrayCopy); + } + + private ExpressionStatementSyntax CreateNewArrayAssignment(VBSyntax.ExpressionSyntax vbArrayExpression, + ExpressionSyntax csArrayExpression, List convertedBounds, + int nodeSpanStart) + { + var arrayRankSpecifierSyntax = SyntaxFactory.ArrayRankSpecifier(SyntaxFactory.SeparatedList(convertedBounds)); + var convertedType = (IArrayTypeSymbol) semanticModel.GetTypeInfo(vbArrayExpression).ConvertedType; + var typeSyntax = GetTypeSyntaxFromTypeSymbol(convertedType.ElementType, nodeSpanStart); + var arrayCreation = + SyntaxFactory.ArrayCreationExpression(SyntaxFactory.ArrayType(typeSyntax, + SyntaxFactory.SingletonList(arrayRankSpecifierSyntax))); + var assignmentExpressionSyntax = + SyntaxFactory.AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, csArrayExpression, arrayCreation); + var newArrayAssignment = SyntaxFactory.ExpressionStatement(assignmentExpressionSyntax); + return newArrayAssignment; + } + + private static ArgumentListSyntax CreateArgList(params ExpressionSyntax[] copyArgs) + { + return SyntaxFactory.ArgumentList(SyntaxFactory.SeparatedList(copyArgs.Select(SyntaxFactory.Argument))); + } + + private TypeSyntax GetTypeSyntaxFromTypeSymbol(ITypeSymbol convertedType, int nodeSpanStart) + { + var predefinedKeywordKind = convertedType.SpecialType.GetPredefinedKeywordKind(); + if (predefinedKeywordKind != SyntaxKind.None) return SyntaxFactory.PredefinedType(SyntaxFactory.Token(predefinedKeywordKind)); + return SyntaxFactory.ParseTypeName(convertedType.ToMinimalDisplayString(semanticModel, nodeSpanStart)); + } + public override SyntaxList VisitThrowStatement(VBSyntax.ThrowStatementSyntax node) { return SingleStatement(SyntaxFactory.ThrowStatement((ExpressionSyntax)node.Expression?.Accept(nodesVisitor))); @@ -327,12 +482,7 @@ namespace ICSharpCode.CodeConverter.CSharp var withExpression = (ExpressionSyntax)node.WithStatement.Expression.Accept(nodesVisitor); withBlockTempVariableNames.Push(GetUniqueVariableNameInScope(node, "withBlock")); try { - var variableDeclaratorSyntax = SyntaxFactory.VariableDeclarator( - SyntaxFactory.Identifier(withBlockTempVariableNames.Peek()), null, - SyntaxFactory.EqualsValueClause(withExpression)); - var declaration = SyntaxFactory.LocalDeclarationStatement(SyntaxFactory.VariableDeclaration( - SyntaxFactory.IdentifierName("var"), - SyntaxFactory.SingletonSeparatedList(variableDeclaratorSyntax))); + var declaration = CreateLocalVariableDeclarationAndAssignment(withBlockTempVariableNames.Peek(), withExpression); var statements = node.Statements.SelectMany(s => s.Accept(CommentConvertingVisitor)); return SingleStatement(SyntaxFactory.Block(new[] { declaration }.Concat(statements).ToArray())); @@ -341,6 +491,23 @@ namespace ICSharpCode.CodeConverter.CSharp } } + private LocalDeclarationStatementSyntax CreateLocalVariableDeclarationAndAssignment(string variableName, ExpressionSyntax initValue) + { + return SyntaxFactory.LocalDeclarationStatement(CreateVariableDeclarationAndAssignment(variableName, initValue)); + } + + private static VariableDeclarationSyntax CreateVariableDeclarationAndAssignment(string variableName, + ExpressionSyntax initValue) + { + var variableDeclaratorSyntax = SyntaxFactory.VariableDeclarator( + SyntaxFactory.Identifier(variableName), null, + SyntaxFactory.EqualsValueClause(initValue)); + var variableDeclarationSyntax = SyntaxFactory.VariableDeclaration( + SyntaxFactory.IdentifierName("var"), + SyntaxFactory.SingletonSeparatedList(variableDeclaratorSyntax)); + return variableDeclarationSyntax; + } + private string GetUniqueVariableNameInScope(SyntaxNode node, string variableNameBase) { var reservedNames = withBlockTempVariableNames.Concat(node.DescendantNodesAndSelf() @@ -435,6 +602,22 @@ namespace ICSharpCode.CodeConverter.CSharp { return SyntaxFactory.SingletonList(SyntaxFactory.ExpressionStatement(expression)); } + + public static IEnumerable ConvertArrayBounds(VBSyntax.ArgumentListSyntax argumentListSyntax, SemanticModel model, VBasic.VisualBasicSyntaxVisitor commentConvertingNodesVisitor) + { + return argumentListSyntax.Arguments.Select(a => IncreaseArrayUpperBoundExpression(((VBSyntax.SimpleArgumentSyntax)a).Expression, model, commentConvertingNodesVisitor)); + } + + private static ExpressionSyntax IncreaseArrayUpperBoundExpression(VBSyntax.ExpressionSyntax expr, SemanticModel model, VBasic.VisualBasicSyntaxVisitor commentConvertingNodesVisitor) + { + var constant = model.GetConstantValue(expr); + if (constant.HasValue && constant.Value is int) + return SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal((int)constant.Value + 1)); + + return SyntaxFactory.BinaryExpression( + SyntaxKind.SubtractExpression, + (ExpressionSyntax)expr.Accept(commentConvertingNodesVisitor), SyntaxFactory.Token(SyntaxKind.PlusToken), SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal(1))); + } } } diff --git a/ICSharpCode.CodeConverter/CSharp/NodesVisitor.cs b/ICSharpCode.CodeConverter/CSharp/NodesVisitor.cs index f8880e2..b2f2311 100644 --- a/ICSharpCode.CodeConverter/CSharp/NodesVisitor.cs +++ b/ICSharpCode.CodeConverter/CSharp/NodesVisitor.cs @@ -654,7 +654,7 @@ namespace ICSharpCode.CodeConverter.CSharp returnType = returnType ?? SyntaxFactory.ParseTypeName("object"); } - var rankSpecifiers = ConvertArrayRankSpecifierSyntaxes(node.Identifier.ArrayRankSpecifiers); + var rankSpecifiers = ConvertArrayRankSpecifierSyntaxes(node.Identifier.ArrayRankSpecifiers, node.Identifier.ArrayBounds, TriviaConvertingVisitor, semanticModel, false); if (rankSpecifiers.Any() && returnType != null) { returnType = SyntaxFactory.ArrayType(returnType, rankSpecifiers); } @@ -804,13 +804,13 @@ namespace ICSharpCode.CodeConverter.CSharp if (node.Token.Value == null) { var type = semanticModel.GetTypeInfo(node).ConvertedType; if (type == null) { - return Literal("null", null) + return Literal(null, "null") .WithTrailingTrivia( SyntaxFactory.Comment("/* TODO Change to default(_) if this is not a reference type */")); } - return !type.IsReferenceType ? SyntaxFactory.DefaultExpression(SyntaxFactory.ParseTypeName(type.ToMinimalDisplayString(semanticModel, node.SpanStart))) : Literal("null", null); + return !type.IsReferenceType ? SyntaxFactory.DefaultExpression(SyntaxFactory.ParseTypeName(type.ToMinimalDisplayString(semanticModel, node.SpanStart))) : Literal(null, "null"); } - return Literal(node.Token.Text, node.Token.Value); + return Literal(node.Token.Value, node.Token.Text); } public override CSharpSyntaxNode VisitInterpolatedStringExpression(VBSyntax.InterpolatedStringExpressionSyntax node) @@ -1002,25 +1002,31 @@ namespace ICSharpCode.CodeConverter.CSharp public override CSharpSyntaxNode VisitArrayCreationExpression(VBSyntax.ArrayCreationExpressionSyntax node) { - var bounds = ConvertArrayRankSpecifierSyntaxes(node.RankSpecifiers); - if (node.ArrayBounds != null) { - var arrayRankSpecifierSyntax = SyntaxFactory.ArrayRankSpecifier(SyntaxFactory.SeparatedList(ConvertArrayBounds(node.ArrayBounds))); - bounds = bounds.Insert(0, arrayRankSpecifierSyntax); - } + var bounds = ConvertArrayRankSpecifierSyntaxes(node.RankSpecifiers, node.ArrayBounds, TriviaConvertingVisitor, semanticModel); return SyntaxFactory.ArrayCreationExpression( SyntaxFactory.ArrayType((TypeSyntax)node.Type.Accept(TriviaConvertingVisitor), bounds), (InitializerExpressionSyntax)node.Initializer?.Accept(TriviaConvertingVisitor) ); } - private SyntaxList ConvertArrayRankSpecifierSyntaxes(SyntaxList arrayRankSpecifierSyntaxs) + internal static SyntaxList ConvertArrayRankSpecifierSyntaxes( + SyntaxList arrayRankSpecifierSyntaxs, + VBSyntax.ArgumentListSyntax nodeArrayBounds, VBasic.VisualBasicSyntaxVisitor commentConvertingNodesVisitor, SemanticModel semanticModel, bool withSizes = true) { - return SyntaxFactory.List(arrayRankSpecifierSyntaxs.Select(r => (ArrayRankSpecifierSyntax)r.Accept(TriviaConvertingVisitor))); - } + var bounds = SyntaxFactory.List(arrayRankSpecifierSyntaxs.Select(r => (ArrayRankSpecifierSyntax)r.Accept(commentConvertingNodesVisitor))); - private IEnumerable ConvertArrayBounds(VBSyntax.ArgumentListSyntax argumentListSyntax) - { - return argumentListSyntax.Arguments.Select(a => IncreaseArrayUpperBoundExpression(((VBSyntax.SimpleArgumentSyntax)a).Expression)); + if (nodeArrayBounds != null) + { + var convertedArrayBounds = withSizes ? + MethodBodyVisitor.ConvertArrayBounds(nodeArrayBounds, semanticModel, commentConvertingNodesVisitor) + : nodeArrayBounds.Arguments.Select(s => SyntaxFactory.OmittedArraySizeExpression()); + var arrayRankSpecifierSyntax = SyntaxFactory.ArrayRankSpecifier( + SyntaxFactory.SeparatedList( + convertedArrayBounds)); + bounds = bounds.Insert(0, arrayRankSpecifierSyntax); + } + + return bounds; } public override CSharpSyntaxNode VisitCollectionInitializer(VBSyntax.CollectionInitializerSyntax node) @@ -1185,17 +1191,6 @@ namespace ICSharpCode.CodeConverter.CSharp return node.Initializer.Accept(TriviaConvertingVisitor); //Dictionary initializer comes through here despite the FROM keyword not being in the source code } - ExpressionSyntax IncreaseArrayUpperBoundExpression(VBSyntax.ExpressionSyntax expr) - { - var constant = semanticModel.GetConstantValue(expr); - if (constant.HasValue && constant.Value is int) - return SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal((int)constant.Value + 1)); - - return SyntaxFactory.BinaryExpression( - SyntaxKind.SubtractExpression, - (ExpressionSyntax)expr.Accept(TriviaConvertingVisitor), SyntaxFactory.Token(SyntaxKind.PlusToken), SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal(1))); - } - public override CSharpSyntaxNode VisitBinaryConditionalExpression(VBSyntax.BinaryConditionalExpressionSyntax node) { return SyntaxFactory.BinaryExpression( diff --git a/ICSharpCode.CodeConverter/CSharp/VisualBasicConverter.cs b/ICSharpCode.CodeConverter/CSharp/VisualBasicConverter.cs index 0a37121..9c22f61 100644 --- a/ICSharpCode.CodeConverter/CSharp/VisualBasicConverter.cs +++ b/ICSharpCode.CodeConverter/CSharp/VisualBasicConverter.cs @@ -61,13 +61,26 @@ namespace ICSharpCode.CodeConverter.CSharp foreach (var name in declarator.Names) { var type = rawType; if (!SyntaxTokenExtensions.IsKind(name.Nullable, VBasic.SyntaxKind.None)) { - if (type is ArrayTypeSyntax) - type = ((ArrayTypeSyntax)type).WithElementType(SyntaxFactory.NullableType(((ArrayTypeSyntax)type).ElementType)); - else + if (type is ArrayTypeSyntax) { + type = ((ArrayTypeSyntax)type).WithElementType( + SyntaxFactory.NullableType(((ArrayTypeSyntax)type).ElementType)); + initializer = null; + } else type = SyntaxFactory.NullableType(type); } - if (name.ArrayRankSpecifiers.Count > 0) - type = SyntaxFactory.ArrayType(type, SyntaxFactory.List(name.ArrayRankSpecifiers.Select(a => (ArrayRankSpecifierSyntax)a.Accept(nodesVisitor)))); + + var rankSpecifiers = NodesVisitor.ConvertArrayRankSpecifierSyntaxes(name.ArrayRankSpecifiers, name.ArrayBounds, nodesVisitor, semanticModel, false); + if (rankSpecifiers.Count > 0) { + var rankSpecifiersWithSizes = NodesVisitor.ConvertArrayRankSpecifierSyntaxes(name.ArrayRankSpecifiers, name.ArrayBounds, nodesVisitor, semanticModel); + if (!rankSpecifiersWithSizes.SelectMany(ars => ars.Sizes).OfType().Any()) + { + initializer = + SyntaxFactory.ArrayCreationExpression( + SyntaxFactory.ArrayType(type, rankSpecifiersWithSizes)); + } + type = SyntaxFactory.ArrayType(type, rankSpecifiers); + } + VariableDeclarationSyntax decl; var v = SyntaxFactory.VariableDeclarator(ConvertIdentifier(name.Identifier, semanticModel), null, initializer == null ? null : SyntaxFactory.EqualsValueClause(initializer)); string k = type.ToString(); @@ -80,7 +93,7 @@ namespace ICSharpCode.CodeConverter.CSharp return newDecls; } - static ExpressionSyntax Literal(string valueText, object o) => GetLiteralExpression(valueText, o); + static ExpressionSyntax Literal(object o, string valueText = null) => GetLiteralExpression(valueText ?? o.ToString(), o); internal static ExpressionSyntax GetLiteralExpression(string valueText, object value) { diff --git a/ICSharpCode.CodeConverter/Util/ExpressionSyntaxExtensions.cs b/ICSharpCode.CodeConverter/Util/ExpressionSyntaxExtensions.cs index 0e8ea46..66dcf4d 100644 --- a/ICSharpCode.CodeConverter/Util/ExpressionSyntaxExtensions.cs +++ b/ICSharpCode.CodeConverter/Util/ExpressionSyntaxExtensions.cs @@ -1971,7 +1971,7 @@ namespace ICSharpCode.CodeConverter.Util /// /// The specialtype of this type. /// The keyword kind for a given special type, or SyntaxKind.None if the type name is not a predefined type. - public static SyntaxKind GetPredefinedKeywordKind(SpecialType specialType) + public static SyntaxKind GetPredefinedKeywordKind(this SpecialType specialType) { switch (specialType) { case SpecialType.System_Boolean: diff --git a/Tests/CSharp/StatementTests.cs b/Tests/CSharp/StatementTests.cs index c6d6fd4..e2193a6 100644 --- a/Tests/CSharp/StatementTests.cs +++ b/Tests/CSharp/StatementTests.cs @@ -194,6 +194,48 @@ class TestClass }"); } + [Fact] + public void ArrayEraseAndRedimStatement() + { + // One statement turns into two, so can't auto-test comments + TestConversionVisualBasicToCSharpWithoutComments(@"Public Class TestClass + Shared Function TestMethod(numArray As Integer(), numArray2 As Integer()) As Integer() + ReDim numArray(3) + Erase numArray + numArray2(1) = 1 + ReDim Preserve numArray(5), numArray2(5) + Dim y(6, 5) As Integer + y(2,3) = 1 + ReDim Preserve y(6,8) + Return numArray2 + End Function +End Class", @"public class TestClass +{ + public static int[] TestMethod(int[] numArray, int[] numArray2) + { + numArray = new int[4]; + numArray = null; + numArray2[1] = 1; + var oldNumArray = numArray; + numArray = new int[6]; + if (oldNumArray != null) + Array.Copy(oldNumArray, numArray, Math.Min(6, oldNumArray.Length)); + var oldNumArray2 = numArray2; + numArray2 = new int[6]; + if (oldNumArray2 != null) + Array.Copy(oldNumArray2, numArray2, Math.Min(6, oldNumArray2.Length)); + int[,] y = new int[7, 6]; + y[2, 3] = 1; + var oldY = y; + y = new int[7, 9]; + if (oldY != null) + for (var i = 0; i <= oldY.Length / oldY.GetLength(1) - 1; ++i) + Array.Copy(oldY, i * oldY.GetLength(1), y, i * y.GetLength(1), Math.Min(oldY.GetLength(1), y.GetLength(1))); + return numArray2; + } +}"); + } + [Fact] public void EndStatement() {