VB -> C#: Convert erase, and a crude conversion for Redim
This commit is contained in:
Родитель
49261e640b
Коммит
17da71e4f1
|
@ -6,6 +6,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 +102,91 @@ namespace ICSharpCode.CodeConverter.CSharp
|
|||
return SingleStatement(SyntaxFactory.AssignmentExpression(kind, (ExpressionSyntax)node.Left.Accept(nodesVisitor), (ExpressionSyntax)node.Right.Accept(nodesVisitor)));
|
||||
}
|
||||
|
||||
public override SyntaxList<StatementSyntax> VisitEraseStatement(VBSyntax.EraseStatementSyntax node)
|
||||
{
|
||||
var eraseStatements = node.Expressions.Select<VBSyntax.ExpressionSyntax, StatementSyntax>(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<StatementSyntax> VisitReDimStatement(VBSyntax.ReDimStatementSyntax node)
|
||||
{
|
||||
return SyntaxFactory.List(node.Clauses.SelectMany(arrayExpression => arrayExpression.Accept(CommentConvertingVisitor)));
|
||||
}
|
||||
|
||||
public override SyntaxList<StatementSyntax> 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 = CreateVariableDeclarationAndAssignment(oldTargetName, csTargetArrayExpression);
|
||||
|
||||
var oldTargetExpression = SyntaxFactory.IdentifierName(oldTargetName);
|
||||
var arrayCopyIfNotNull = CreateConditionalRankOneArrayCopy(oldTargetExpression, csTargetArrayExpression, convertedBounds);
|
||||
|
||||
return SyntaxFactory.List(new StatementSyntax[] {oldArrayAssignment, newArrayAssignment, arrayCopyIfNotNull});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cut down version of Microsoft.VisualBasic.CompilerServices.Utils.CopyArray
|
||||
/// </summary>
|
||||
private static IfStatementSyntax CreateConditionalRankOneArrayCopy(IdentifierNameSyntax oldTargetExpression,
|
||||
ExpressionSyntax csTargetArrayExpression,
|
||||
List<ExpressionSyntax> convertedBounds)
|
||||
{
|
||||
var expressionSyntax = convertedBounds.Count != 1 ? throw new NotSupportedException("ReDim not supported with Preserve for multi-dimensional arrays")
|
||||
: convertedBounds.Single();
|
||||
var oldTargetLength = SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
|
||||
oldTargetExpression, SyntaxFactory.IdentifierName("Length"));
|
||||
var minLength = SyntaxFactory.InvocationExpression(SyntaxFactory.ParseExpression("Math.Min"),
|
||||
CreateArgList(expressionSyntax, oldTargetLength));
|
||||
var oldTargetNotEqualToNull = SyntaxFactory.BinaryExpression(SyntaxKind.NotEqualsExpression, oldTargetExpression,
|
||||
SyntaxFactory.LiteralExpression(SyntaxKind.NullLiteralExpression));
|
||||
var copyArgList = CreateArgList(oldTargetExpression, csTargetArrayExpression, minLength);
|
||||
var arrayCopy = SyntaxFactory.InvocationExpression(SyntaxFactory.ParseExpression("Array.Copy"), copyArgList);
|
||||
return SyntaxFactory.IfStatement(oldTargetNotEqualToNull, SyntaxFactory.ExpressionStatement(arrayCopy));
|
||||
}
|
||||
|
||||
private ExpressionStatementSyntax CreateNewArrayAssignment(VBSyntax.ExpressionSyntax vbArrayExpression,
|
||||
ExpressionSyntax csArrayExpression, List<ExpressionSyntax> 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<StatementSyntax> VisitThrowStatement(VBSyntax.ThrowStatementSyntax node)
|
||||
{
|
||||
return SingleStatement(SyntaxFactory.ThrowStatement((ExpressionSyntax)node.Expression?.Accept(nodesVisitor)));
|
||||
|
@ -327,12 +413,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 = CreateVariableDeclarationAndAssignment(withBlockTempVariableNames.Peek(), withExpression);
|
||||
var statements = node.Statements.SelectMany(s => s.Accept(CommentConvertingVisitor));
|
||||
|
||||
return SingleStatement(SyntaxFactory.Block(new[] { declaration }.Concat(statements).ToArray()));
|
||||
|
@ -341,6 +422,16 @@ namespace ICSharpCode.CodeConverter.CSharp
|
|||
}
|
||||
}
|
||||
|
||||
private LocalDeclarationStatementSyntax CreateVariableDeclarationAndAssignment(string variableName, ExpressionSyntax initValue)
|
||||
{
|
||||
var variableDeclaratorSyntax = SyntaxFactory.VariableDeclarator(
|
||||
SyntaxFactory.Identifier(variableName), null,
|
||||
SyntaxFactory.EqualsValueClause(initValue));
|
||||
return SyntaxFactory.LocalDeclarationStatement(SyntaxFactory.VariableDeclaration(
|
||||
SyntaxFactory.IdentifierName("var"),
|
||||
SyntaxFactory.SingletonSeparatedList(variableDeclaratorSyntax)));
|
||||
}
|
||||
|
||||
private string GetUniqueVariableNameInScope(SyntaxNode node, string variableNameBase)
|
||||
{
|
||||
var reservedNames = withBlockTempVariableNames.Concat(node.DescendantNodesAndSelf()
|
||||
|
|
|
@ -1971,7 +1971,7 @@ namespace ICSharpCode.CodeConverter.Util
|
|||
/// </summary>
|
||||
/// <param name="specialType">The specialtype of this type.</param>
|
||||
/// <returns>The keyword kind for a given special type, or SyntaxKind.None if the type name is not a predefined type.</returns>
|
||||
public static SyntaxKind GetPredefinedKeywordKind(SpecialType specialType)
|
||||
public static SyntaxKind GetPredefinedKeywordKind(this SpecialType specialType)
|
||||
{
|
||||
switch (specialType) {
|
||||
case SpecialType.System_Boolean:
|
||||
|
|
|
@ -194,6 +194,38 @@ 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)
|
||||
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));
|
||||
return numArray2;
|
||||
}
|
||||
}");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EndStatement()
|
||||
{
|
||||
|
|
Загрузка…
Ссылка в новой задаче