Merge branch 'master' of https://github.com/icsharpcode/CodeConverter
This commit is contained in:
Коммит
77c9b81ff7
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
15
README.md
15
README.md
|
@ -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]
|
||||
|
|
Загрузка…
Ссылка в новой задаче