BaronBodissey 2018-03-14 11:11:17 +01:00
Родитель 2609cd9d20 4f6bcb3ff7
Коммит 77c9b81ff7
12 изменённых файлов: 305 добавлений и 47 удалений

Просмотреть файл

@ -32,7 +32,12 @@ namespace ICSharpCode.CodeConverter.CSharp
public override SyntaxList<StatementSyntax> DefaultVisit(SyntaxNode node)
{
throw new NotImplementedException(node.GetType() + " not implemented!");
var nodeString = node.ToString();
if (nodeString.Length > 15) {
nodeString = nodeString.Substring(0, 12) + "...";
}
throw new NotImplementedException(node.GetType() + $" not implemented - cannot convert {nodeString}");
}
public override SyntaxList<StatementSyntax> VisitStopOrEndStatement(VBSyntax.StopOrEndStatementSyntax node)
@ -169,9 +174,9 @@ namespace ICSharpCode.CodeConverter.CSharp
if (node.ElseClause != null) {
var elseBlock = SyntaxFactory.Block(node.ElseClause.Statements.SelectMany(s => s.Accept(CommentConvertingVisitor)));
elseClause = SyntaxFactory.ElseClause(elseBlock.UnpackBlock());
elseClause = SyntaxFactory.ElseClause(elseBlock.UnpackNonNestedBlock());
}
return SingleStatement(SyntaxFactory.IfStatement(condition, block.UnpackBlock(), elseClause));
return SingleStatement(SyntaxFactory.IfStatement(condition, block.UnpackNonNestedBlock(), elseClause));
}
public override SyntaxList<StatementSyntax> VisitMultiLineIfBlock(VBSyntax.MultiLineIfBlockSyntax node)
@ -182,16 +187,16 @@ namespace ICSharpCode.CodeConverter.CSharp
if (node.ElseBlock != null) {
var elseBlock = SyntaxFactory.Block(node.ElseBlock.Statements.SelectMany(s => s.Accept(CommentConvertingVisitor)));
elseClause = SyntaxFactory.ElseClause(elseBlock.UnpackBlock());
elseClause = SyntaxFactory.ElseClause(elseBlock.UnpackPossiblyNestedBlock());// so that you get a neat "else if" at the end
}
foreach (var elseIf in node.ElseIfBlocks.Reverse()) {
var elseBlock = SyntaxFactory.Block(elseIf.Statements.SelectMany(s => s.Accept(CommentConvertingVisitor)));
var ifStmt = SyntaxFactory.IfStatement((ExpressionSyntax)elseIf.ElseIfStatement.Condition.Accept(nodesVisitor), elseBlock.UnpackBlock(), elseClause);
var ifStmt = SyntaxFactory.IfStatement((ExpressionSyntax)elseIf.ElseIfStatement.Condition.Accept(nodesVisitor), elseBlock.UnpackNonNestedBlock(), elseClause);
elseClause = SyntaxFactory.ElseClause(ifStmt);
}
return SingleStatement(SyntaxFactory.IfStatement(condition, block.UnpackBlock(), elseClause));
return SingleStatement(SyntaxFactory.IfStatement(condition, block.UnpackNonNestedBlock(), elseClause));
}
public override SyntaxList<StatementSyntax> VisitForBlock(VBSyntax.ForBlockSyntax node)
@ -237,7 +242,7 @@ namespace ICSharpCode.CodeConverter.CSharp
declaration != null ? SyntaxFactory.SeparatedList<ExpressionSyntax>() : SyntaxFactory.SingletonSeparatedList(startValue),
condition,
SyntaxFactory.SingletonSeparatedList(step),
block.UnpackBlock()));
block.UnpackNonNestedBlock()));
}
public override SyntaxList<StatementSyntax> VisitForEachBlock(VBSyntax.ForEachBlockSyntax node)
@ -262,7 +267,7 @@ namespace ICSharpCode.CodeConverter.CSharp
type,
id,
(ExpressionSyntax)stmt.Expression.Accept(nodesVisitor),
block.UnpackBlock()
block.UnpackNonNestedBlock()
));
}
@ -351,14 +356,15 @@ namespace ICSharpCode.CodeConverter.CSharp
{
return SingleStatement(SyntaxFactory.LockStatement(
(ExpressionSyntax)node.SyncLockStatement.Expression.Accept(nodesVisitor),
SyntaxFactory.Block(node.Statements.SelectMany(s => s.Accept(CommentConvertingVisitor))).UnpackBlock()
SyntaxFactory.Block(node.Statements.SelectMany(s => s.Accept(CommentConvertingVisitor))).UnpackNonNestedBlock()
));
}
public override SyntaxList<StatementSyntax> VisitUsingBlock(VBSyntax.UsingBlockSyntax node)
{
var statementSyntax = SyntaxFactory.Block(node.Statements.SelectMany(s => s.Accept(CommentConvertingVisitor)));
if (node.UsingStatement.Expression == null) {
StatementSyntax stmt = SyntaxFactory.Block(node.Statements.SelectMany(s => s.Accept(CommentConvertingVisitor)));
StatementSyntax stmt = statementSyntax;
foreach (var v in node.UsingStatement.Variables.Reverse())
foreach (var declaration in SplitVariableDeclarations(v, nodesVisitor, semanticModel).Values.Reverse())
stmt = SyntaxFactory.UsingStatement(declaration, null, stmt);
@ -366,14 +372,15 @@ namespace ICSharpCode.CodeConverter.CSharp
}
var expr = (ExpressionSyntax)node.UsingStatement.Expression.Accept(nodesVisitor);
return SingleStatement(SyntaxFactory.UsingStatement(null, expr, SyntaxFactory.Block(node.Statements.SelectMany(s => s.Accept(CommentConvertingVisitor))).UnpackBlock()));
var unpackPossiblyNestedBlock = statementSyntax.UnpackPossiblyNestedBlock(); // Allow reduced indentation for multiple usings in a row
return SingleStatement(SyntaxFactory.UsingStatement(null, expr, unpackPossiblyNestedBlock));
}
public override SyntaxList<StatementSyntax> VisitWhileBlock(VBSyntax.WhileBlockSyntax node)
{
return SingleStatement(SyntaxFactory.WhileStatement(
(ExpressionSyntax)node.WhileStatement.Condition.Accept(nodesVisitor),
SyntaxFactory.Block(node.Statements.SelectMany(s => s.Accept(CommentConvertingVisitor))).UnpackBlock()
SyntaxFactory.Block(node.Statements.SelectMany(s => s.Accept(CommentConvertingVisitor))).UnpackNonNestedBlock()
));
}
@ -384,22 +391,22 @@ namespace ICSharpCode.CodeConverter.CSharp
if (SyntaxTokenExtensions.IsKind(stmt.WhileOrUntilKeyword, VBasic.SyntaxKind.WhileKeyword))
return SingleStatement(SyntaxFactory.WhileStatement(
(ExpressionSyntax)stmt.Condition.Accept(nodesVisitor),
SyntaxFactory.Block(node.Statements.SelectMany(s => s.Accept(CommentConvertingVisitor))).UnpackBlock()
SyntaxFactory.Block(node.Statements.SelectMany(s => s.Accept(CommentConvertingVisitor))).UnpackNonNestedBlock()
));
return SingleStatement(SyntaxFactory.WhileStatement(
SyntaxFactory.PrefixUnaryExpression(SyntaxKind.LogicalNotExpression, (ExpressionSyntax)stmt.Condition.Accept(nodesVisitor)),
SyntaxFactory.Block(node.Statements.SelectMany(s => s.Accept(CommentConvertingVisitor))).UnpackBlock()
SyntaxFactory.Block(node.Statements.SelectMany(s => s.Accept(CommentConvertingVisitor))).UnpackNonNestedBlock()
));
}
if (node.LoopStatement.WhileOrUntilClause != null) {
var stmt = node.LoopStatement.WhileOrUntilClause;
if (SyntaxTokenExtensions.IsKind(stmt.WhileOrUntilKeyword, VBasic.SyntaxKind.WhileKeyword))
return SingleStatement(SyntaxFactory.DoStatement(
SyntaxFactory.Block(node.Statements.SelectMany(s => s.Accept(CommentConvertingVisitor))).UnpackBlock(),
SyntaxFactory.Block(node.Statements.SelectMany(s => s.Accept(CommentConvertingVisitor))).UnpackNonNestedBlock(),
(ExpressionSyntax)stmt.Condition.Accept(nodesVisitor)
));
return SingleStatement(SyntaxFactory.DoStatement(
SyntaxFactory.Block(node.Statements.SelectMany(s => s.Accept(CommentConvertingVisitor))).UnpackBlock(),
SyntaxFactory.Block(node.Statements.SelectMany(s => s.Accept(CommentConvertingVisitor))).UnpackNonNestedBlock(),
SyntaxFactory.PrefixUnaryExpression(SyntaxKind.LogicalNotExpression, (ExpressionSyntax)stmt.Condition.Accept(nodesVisitor))
));
}
@ -420,9 +427,33 @@ namespace ICSharpCode.CodeConverter.CSharp
static class Extensions
{
public static StatementSyntax UnpackBlock(this BlockSyntax block)
/// <summary>
/// Returns the single statement in a block if it has no nested statements.
/// If it has nested statements, and the surrounding block was removed, it could be ambiguous,
/// e.g. if (...) { if (...) return null; } else return "";
/// Unbundling the middle if statement would bind the else to it, rather than the outer if statement
/// </summary>
public static StatementSyntax UnpackNonNestedBlock(this BlockSyntax block)
{
return block.Statements.Count == 1 && !block.ContainsNestedStatements() ? block.Statements[0] : block;
}
/// <summary>
/// Only use this over <see cref="UnpackNonNestedBlock"/> in special cases where it will display more neatly and where you're sure nested statements don't introduce ambiguity
/// </summary>
public static StatementSyntax UnpackPossiblyNestedBlock(this BlockSyntax block)
{
return block.Statements.Count == 1 ? block.Statements[0] : block;
}
private static bool ContainsNestedStatements(this BlockSyntax block)
{
return block.Statements.Any(HasDescendantCSharpStatement);
}
private static bool HasDescendantCSharpStatement(this StatementSyntax c)
{
return c.DescendantNodes().OfType<StatementSyntax>().Any();
}
}
}

Просмотреть файл

@ -799,13 +799,13 @@ namespace ICSharpCode.CodeConverter.CSharp
if (node.Token.Value == null) {
var type = semanticModel.GetTypeInfo(node).ConvertedType;
if (type == null) {
return Literal(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);
return !type.IsReferenceType ? SyntaxFactory.DefaultExpression(SyntaxFactory.ParseTypeName(type.ToMinimalDisplayString(semanticModel, node.SpanStart))) : Literal("null", null);
}
return Literal(node.Token.Value);
return Literal(node.Token.Text, node.Token.Value);
}
public override CSharpSyntaxNode VisitInterpolatedStringExpression(VBSyntax.InterpolatedStringExpressionSyntax node)
@ -1021,8 +1021,10 @@ namespace ICSharpCode.CodeConverter.CSharp
var vbFromClause = node.Clauses.OfType<VBSyntax.FromClauseSyntax>().Single();
var fromClauseSyntax = ConvertFromClauseSyntax(vbFromClause);
var vbGroupClause = node.Clauses.OfType<VBSyntax.GroupByClauseSyntax>().SingleOrDefault();
var vbSelectClause = node.Clauses.OfType<VBSyntax.SelectClauseSyntax>().Single();
var selectClauseSyntax = ConvertSelectClauseSyntax(vbSelectClause);
var vbSelectClause = node.Clauses.OfType<VBSyntax.SelectClauseSyntax>().SingleOrDefault();
var selectClauseSyntax = vbSelectClause != null
? ConvertSelectClauseSyntax(vbSelectClause)
: CreateDefaultSelectClause(fromClauseSyntax);
var alreadyConverted = new VBSyntax.QueryClauseSyntax[] { vbFromClause, vbGroupClause, vbSelectClause };
var vbBodyClauses = node.Clauses;
SelectOrGroupClauseSyntax selectOrGroup = null;
@ -1058,6 +1060,11 @@ namespace ICSharpCode.CodeConverter.CSharp
);
}
private static SelectClauseSyntax CreateDefaultSelectClause(FromClauseSyntax fromClauseSyntax)
{
return SyntaxFactory.SelectClause(SyntaxFactory.IdentifierName(fromClauseSyntax.Identifier));
}
private QueryClauseSyntax ConvertQueryBodyClause(VBSyntax.QueryClauseSyntax node)
{
return node.TypeSwitch<VBSyntax.QueryClauseSyntax, VBSyntax.JoinClauseSyntax, VBSyntax.LetClauseSyntax, VBSyntax.OrderByClauseSyntax, VBSyntax.WhereClauseSyntax, QueryClauseSyntax>(
@ -1240,13 +1247,30 @@ namespace ICSharpCode.CodeConverter.CSharp
return SyntaxFactory.BinaryExpression(SyntaxKind.NotEqualsExpression, otherArgument, SyntaxFactory.LiteralExpression(SyntaxKind.NullLiteralExpression));
}
}
var kind = ConvertToken(VBasic.VisualBasicExtensions.Kind(node), TokenContext.Local);
return SyntaxFactory.BinaryExpression(
kind,
(ExpressionSyntax)node.Left.Accept(TriviaConvertingVisitor),
SyntaxFactory.Token(CSharpUtil.GetExpressionOperatorTokenKind(kind)),
(ExpressionSyntax)node.Right.Accept(TriviaConvertingVisitor)
);
var lhs = (ExpressionSyntax)node.Left.Accept(TriviaConvertingVisitor);
var op = SyntaxFactory.Token(CSharpUtil.GetExpressionOperatorTokenKind(kind));
var rhs = (ExpressionSyntax)node.Right.Accept(TriviaConvertingVisitor);
// VB DivideExpression "/" is always on doubles unless you use the "\" IntegerDivideExpression, so need to cast in C#
// Need the unconverted type, since the whole point is that it gets converted to a double by the operator
if (node.IsKind(VBasic.SyntaxKind.DivideExpression) && !HasOperandOfUnconvertedType(node, "System.Double")) {
var doubleType = SyntaxFactory.PredefinedType(SyntaxFactory.Token(SyntaxKind.DoubleKeyword));
rhs = SyntaxFactory.CastExpression(doubleType, rhs);
}
return SyntaxFactory.BinaryExpression(kind, lhs, op, rhs);
}
private bool HasOperandOfUnconvertedType(VBSyntax.BinaryExpressionSyntax node, string operandType)
{
return new[] {node.Left, node.Right}.Any(e => UnconvertedIsType(e, operandType));
}
private bool UnconvertedIsType(VBSyntax.ExpressionSyntax e, string fullTypeName)
{
return semanticModel.GetTypeInfo(e).Type?.GetFullMetadataName() == fullTypeName;
}
public override CSharpSyntaxNode VisitInvocationExpression(VBSyntax.InvocationExpressionSyntax node)

Просмотреть файл

@ -80,9 +80,9 @@ namespace ICSharpCode.CodeConverter.CSharp
return newDecls;
}
static ExpressionSyntax Literal(object o) => GetLiteralExpression(o);
static ExpressionSyntax Literal(string valueText, object o) => GetLiteralExpression(valueText, o);
internal static ExpressionSyntax GetLiteralExpression(object value)
internal static ExpressionSyntax GetLiteralExpression(string valueText, object value)
{
if (value is bool)
return SyntaxFactory.LiteralExpression((bool)value ? SyntaxKind.TrueLiteralExpression : SyntaxKind.FalseLiteralExpression);
@ -105,10 +105,14 @@ namespace ICSharpCode.CodeConverter.CSharp
if (value is float)
return SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal((float)value));
if (value is double)
return SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal((double)value));
if (value is decimal)
if (value is double) {
// Important to use value text, otherwise "10.0" gets coerced to and integer literal of 10 which can change semantics
return SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal(valueText, (double)value));
}
if (value is decimal) {
// Don't use value text - it has a "D" in VB, but an "M" in C#
return SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal((decimal)value));
}
if (value is char)
return SyntaxFactory.LiteralExpression(SyntaxKind.CharacterLiteralExpression, SyntaxFactory.Literal((char)value));
@ -367,6 +371,14 @@ namespace ICSharpCode.CodeConverter.CSharp
return SyntaxKind.LessThanExpression;
case VBasic.SyntaxKind.LessThanOrEqualExpression:
return SyntaxKind.LessThanOrEqualExpression;
case VBasic.SyntaxKind.IsExpression:
return SyntaxKind.EqualsExpression;
case VBasic.SyntaxKind.IsNotExpression:
return SyntaxKind.NotEqualsExpression;
case VBasic.SyntaxKind.LeftShiftExpression:
return SyntaxKind.LeftShiftExpression;
case VBasic.SyntaxKind.RightShiftExpression:
return SyntaxKind.RightShiftExpression;
// assignment
case VBasic.SyntaxKind.SimpleAssignmentStatement:
return SyntaxKind.SimpleAssignmentExpression;
@ -377,8 +389,13 @@ namespace ICSharpCode.CodeConverter.CSharp
return SyntaxKind.SubtractAssignmentExpression;
case VBasic.SyntaxKind.MultiplyAssignmentStatement:
return SyntaxKind.MultiplyAssignmentExpression;
case VBasic.SyntaxKind.IntegerDivideAssignmentStatement:
case VBasic.SyntaxKind.DivideAssignmentStatement:
return SyntaxKind.DivideAssignmentExpression;
case VBasic.SyntaxKind.LeftShiftAssignmentStatement:
return SyntaxKind.LeftShiftAssignmentExpression;
case VBasic.SyntaxKind.RightShiftAssignmentStatement:
return SyntaxKind.RightShiftAssignmentExpression;
// Casts
case VBasic.SyntaxKind.CObjKeyword:
return SyntaxKind.ObjectKeyword;

Просмотреть файл

@ -7,7 +7,7 @@
<Company>ICSharpCode</Company>
<Description>This Roslyn-based code converter was previously part of Refactoring Essentials. It has been teased out to be able to evolve separately and faster than the analyzers/refactorings. Conversion from C# to VB.NET, as well as from VB.NET to C# are included.</Description>
<Product>Code Converter for C# to/from VB.NET</Product>
<Copyright>Copyright (c) 2014-2017 AlphaSierraPapa</Copyright>
<Copyright>Copyright (c) 2014-2018 AlphaSierraPapa</Copyright>
<AssemblyVersion>5.6.1.0</AssemblyVersion>
<FileVersion>5.6.1.0</FileVersion>
<Version>5.6.1</Version>

Просмотреть файл

@ -98,6 +98,10 @@ namespace ICSharpCode.CodeConverter.Util
return SyntaxKind.SlashToken;
case SyntaxKind.ModuloExpression:
return SyntaxKind.PercentToken;
case SyntaxKind.LeftShiftExpression:
return SyntaxKind.LessThanLessThanToken;
case SyntaxKind.RightShiftExpression:
return SyntaxKind.GreaterThanGreaterThanToken;
// assignments
case SyntaxKind.SimpleAssignmentExpression:
return SyntaxKind.EqualsToken;
@ -105,6 +109,10 @@ namespace ICSharpCode.CodeConverter.Util
return SyntaxKind.PlusEqualsToken;
case SyntaxKind.SubtractAssignmentExpression:
return SyntaxKind.MinusEqualsToken;
case SyntaxKind.LeftShiftAssignmentExpression:
return SyntaxKind.LessThanLessThanEqualsToken;
case SyntaxKind.RightShiftAssignmentExpression:
return SyntaxKind.GreaterThanGreaterThanEqualsToken;
// unary
case SyntaxKind.UnaryPlusExpression:
return SyntaxKind.PlusToken;
@ -115,7 +123,7 @@ namespace ICSharpCode.CodeConverter.Util
case SyntaxKind.BitwiseNotExpression:
return SyntaxKind.TildeToken;
}
throw new ArgumentOutOfRangeException(nameof(op));
throw new ArgumentOutOfRangeException(nameof(op), op, null);
}
/// <summary>

Просмотреть файл

@ -9,6 +9,7 @@ using Microsoft.CodeAnalysis.Text;
using Microsoft.CodeAnalysis.VisualBasic;
using VbSyntax = Microsoft.CodeAnalysis.VisualBasic.Syntax;
using CsSyntax = Microsoft.CodeAnalysis.CSharp.Syntax;
using SyntaxFactory = Microsoft.CodeAnalysis.VisualBasic.SyntaxFactory;
namespace ICSharpCode.CodeConverter.VB
{
@ -26,5 +27,12 @@ namespace ICSharpCode.CodeConverter.VB
{
return TriviaConverter.PortConvertedTrivia(node, _wrappedVisitor.Visit(node));
}
public override VisualBasicSyntaxNode VisitAttributeList(CsSyntax.AttributeListSyntax node)
{
var convertedNode = _wrappedVisitor.Visit(node)
.WithPrependedLeadingTrivia(SyntaxFactory.EndOfLineTrivia(Environment.NewLine));
return TriviaConverter.PortConvertedTrivia(node, convertedNode);
}
}
}

Просмотреть файл

@ -2,18 +2,23 @@
Convert code from C# to VB.NET and vice versa using Roslyn
NuGet: [https://www.nuget.org/packages/ICSharpCode.CodeConverter/](https://www.nuget.org/packages/ICSharpCode.CodeConverter/)
## Using the code converter
VSIX: [https://marketplace.visualstudio.com/items?itemName=SharpDevelopTeam.CodeConverter](https://marketplace.visualstudio.com/items?itemName=SharpDevelopTeam.CodeConverter)
Visual Studio Extension (recommended): [https://marketplace.visualstudio.com/items?itemName=SharpDevelopTeam.CodeConverter](https://marketplace.visualstudio.com/items?itemName=SharpDevelopTeam.CodeConverter)
Web site: [https://roslyncodeconverter.azurewebsites.net](https://roslyncodeconverter.azurewebsites.net)
Online snippet converter: [https://roslyncodeconverter.azurewebsites.net](https://roslyncodeconverter.azurewebsites.net)
## Using the Code Converter (NuGet)
## Developing against the Code Converter library (NuGet)
NuGet pacakge: [https://www.nuget.org/packages/ICSharpCode.CodeConverter/](https://www.nuget.org/packages/ICSharpCode.CodeConverter/)
Check out the [ConverterController](https://github.com/icsharpcode/CodeConverter/blob/master/Web/Controllers/ConverterController.cs) in the Web project - this is the easiest place to get started.
Alternatively - with a bit of VS glue code - the [CodeConversion class](https://github.com/icsharpcode/CodeConverter/blob/master/Vsix/CodeConversion.cs) in the VSIX project.
## History
It started as part of [Refactoring Essentials](https://github.com/icsharpcode/RefactoringEssentials). However, because of the way analyzers are tied to Visual Studio and Roslyn versions
made it super-hard to co-evolve the code converter bits. That is why we teased the converters out and they are now a self-contained entity.
made it super-hard to co-evolve the code converter bits. That is why we teased the converters out and they are now a self-contained entity.

Просмотреть файл

@ -43,6 +43,89 @@ class TestClass
}");
}
[Fact]
public void BinaryOperatorsIsIsNotLeftShiftRightShift()
{
TestConversionVisualBasicToCSharp(@"Class TestClass
Private bIs as Boolean = New Object Is New Object
Private bIsNot as Boolean = New Object IsNot New Object
Private bLeftShift as Integer = 1 << 3
Private bRightShift as Integer = 8 >> 3
End Class", @"class TestClass
{
private bool bIs = new object() == new object();
private bool bIsNot = new object() != new object();
private int bLeftShift = 1 << 3;
private int bRightShift = 8 >> 3;
}");
}
[Fact]
public void ShiftAssignment()
{
TestConversionVisualBasicToCSharp(@"Class TestClass
Private Sub TestMethod()
Dim x = 1
x <<= 4
x >>= 3
End Sub
End Class", @"class TestClass
{
private void TestMethod()
{
var x = 1;
x <<= 4;
x >>= 3;
}
}");
}
[Fact]
public void IntegerArithmetic()
{
TestConversionVisualBasicToCSharp(@"Class TestClass
Private Sub TestMethod()
Dim x = 6 Mod 5 \ 4 + 3 * 2
x += 1
x -= 2
x *= 3
x \= 4
End Sub
End Class", @"class TestClass
{
private void TestMethod()
{
var x = 6 % 5 / 4 + 3 * 2;
x += 1;
x -= 2;
x *= 3;
x /= 4;
}
}");
}
[Fact]
public void FloatingPointDivisionIsForced()
{
TestConversionVisualBasicToCSharp(@"Class TestClass
Private Sub TestMethod()
Dim x = 10 / 3
x /= 2
Dim y = 10.0 / 3
y /= 2
End Sub
End Class", @"class TestClass
{
private void TestMethod()
{
var x = 10 / (double)3;
x /= 2;
var y = 10.0 / 3;
y /= 2;
}
}");
}
[Fact]
public void FullyTypeInferredEnumerableCreation()
{
@ -421,7 +504,7 @@ class TestClass
var test2 = (a, b) =>
{
if (b > 0)
return a / b;
return a / (double)b;
return 0;
};
@ -592,6 +675,24 @@ End Sub", @"public void Linq103()
}");
}
[Fact]
public void Linq5()
{
TestConversionVisualBasicToCSharp(@"Private Shared Function FindPicFilePath(picId As String) As String
For Each FileInfo As FileInfo In From FileInfo1 In AList Where FileInfo1.Name.Substring(0, 6) = picId
Return FileInfo.FullName
Next
Return String.Empty
End Function", @"private static string FindPicFilePath(string picId)
{
foreach (FileInfo FileInfo in from FileInfo1 in AList
where FileInfo1.Name.Substring(0, 6) == picId
select FileInfo1)
return FileInfo.FullName;
return string.Empty;
}");
}
[Fact]
public void PartiallyQualifiedName()
{

Просмотреть файл

@ -620,6 +620,51 @@ class TestClass
}");
}
[Fact]
public void NestedBlockStatementsKeepSameNesting()
{
TestConversionVisualBasicToCSharpWithoutComments(@"Class TestClass
Shared Function FindTextInCol(w As Worksheet, pTitleRow As Integer, startCol As Integer, needle As String) As Integer
For c As Integer = startCol To w.Cells.MaxDataColumn
If needle = """" Then
If String.IsNullOrWhiteSpace(w.Cells(pTitleRow, c).StringValue) Then
Return c
End If
Else
If w.Cells(pTitleRow, c).StringValue = needle Then
Return c
End If
End If
Next
Return -1
End Function
End Class", @"using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualBasic;
class TestClass
{
public static int FindTextInCol(Worksheet w, int pTitleRow, int startCol, string needle)
{
for (int c = startCol; c <= w.Cells.MaxDataColumn; c++)
{
if (needle == """")
{
if (string.IsNullOrWhiteSpace(w.Cells(pTitleRow, c).StringValue))
return c;
}
else if (w.Cells(pTitleRow, c).StringValue == needle)
return c;
}
return -1;
}
}");
}
[Fact]
public void WhileStatement()
{
@ -891,19 +936,22 @@ class GotoTest1
string[,] array = new string[x - 1 + 1, y - 1 + 1];
for (int i = 0; i <= x - 1; i++)
{
for (int j = 0; j <= y - 1; j++)
array[i, j] = (System.Threading.Interlocked.Increment(ref count)).ToString();
}
Console.Write(""Enter the number to search for: "");
string myNumber = Console.ReadLine();
for (int i = 0; i <= x - 1; i++)
{
for (int j = 0; j <= y - 1; j++)
{
if (array[i, j].Equals(myNumber))
goto Found;
}
}
Console.WriteLine(""The number {0} was not found."", myNumber);
goto Finish;

Просмотреть файл

@ -145,7 +145,7 @@ using Microsoft.VisualBasic;
/// </summary>
private static bool IsTwoLineCsIfStatement(string line, string nextLine)
{
return line.Contains("if") && !nextLine.Trim().Equals("{");
return line.Contains("if ") && !nextLine.Trim().Equals("{");
}
private static bool HasNoTargetLine(string prevLine, string line, string nextLine)
@ -161,7 +161,7 @@ using Microsoft.VisualBasic;
private static bool IsFirstOfMultiLineVbIfStatement(string line)
{
return line.Trim().StartsWith("If") && line.Trim().EndsWith("Then");
return line.Trim().StartsWith("If ") && line.Trim().EndsWith("Then");
}
private static bool IsVbInheritsOrImplements(string line)

Просмотреть файл

@ -187,6 +187,21 @@ End Module");
End Class");
}
[Fact]
public void TestPropertyWithAttribute()
{
TestConversionCSharpToVisualBasic(
@"class TestClass
{
[DatabaseGenerated(DatabaseGeneratedOption.None)]
int value { get; set; }
}", @"Class TestClass
<DatabaseGenerated(DatabaseGeneratedOption.None)>
Private Property value As Integer
End Class
");
}
[Fact]
public void TestConstructor()
{

Просмотреть файл

@ -19,7 +19,8 @@ End Namespace");
{
TestConversionCSharpToVisualBasic(
@"[assembly: CLSCompliant(true)]",
@"<Assembly: CLSCompliant(True)>");
@"
<Assembly: CLSCompliant(True)>");
}
[Fact]