Skip to content

Commit

Permalink
Do all the same mappings that vb -> c# does - fixes #240
Browse files Browse the repository at this point in the history
  • Loading branch information
GrahamTheCoder committed Feb 6, 2019
1 parent ed09554 commit 280e8d9
Show file tree
Hide file tree
Showing 3 changed files with 183 additions and 3 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ All notable changes to the code converter will be documented here.

### C# -> VB
* Tuples now converted
* All known operator overloads now converted

# 6.3.0 05/02/2019
* VS 2019 support
Expand Down
39 changes: 36 additions & 3 deletions ICSharpCode.CodeConverter/VB/NodesVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -602,24 +602,57 @@ public override VisualBasicSyntaxNode VisitOperatorDeclaration(CSS.OperatorDecla
ConvertAndSplitAttributes(node.AttributeLists, out var attributes, out var returnAttributes);
var body = _commonConversions.ConvertBody(node.Body, node.ExpressionBody);
var parameterList = (ParameterListSyntax)node.ParameterList?.Accept(TriviaConvertingVisitor);
var firstParam = node.ParameterList?.Parameters.FirstOrDefault()
?? throw new NotSupportedException("Operator overloads with no parameters aren't supported");
var firstParameterIsString = _semanticModel.GetTypeInfo(firstParam.Type).ConvertedType.SpecialType == SpecialType.System_String;
var stmt = SyntaxFactory.OperatorStatement(
attributes, CommonConversions.ConvertModifiers(node.Modifiers, GetMemberContext(node)),
SyntaxFactory.Token(ConvertOperatorDeclarationToken(CS.CSharpExtensions.Kind(node.OperatorToken))),
SyntaxFactory.Token(ConvertOperatorDeclarationToken(CS.CSharpExtensions.Kind(node.OperatorToken), firstParameterIsString)),
parameterList,
SyntaxFactory.SimpleAsClause(returnAttributes, (TypeSyntax)node.ReturnType.Accept(TriviaConvertingVisitor))
);
return SyntaxFactory.OperatorBlock(stmt, body);
}

SyntaxKind ConvertOperatorDeclarationToken(CS.SyntaxKind syntaxKind)


SyntaxKind ConvertOperatorDeclarationToken(CS.SyntaxKind syntaxKind, bool firstParameterIsString)
{
switch (syntaxKind) {
case CS.SyntaxKind.PlusToken:
return firstParameterIsString ? SyntaxKind.AmpersandToken : SyntaxKind.PlusToken;
case CS.SyntaxKind.MinusToken:
return SyntaxKind.MinusToken;
case CS.SyntaxKind.ExclamationToken:
return SyntaxKind.NotKeyword;
case CS.SyntaxKind.AsteriskToken:
return SyntaxKind.AsteriskToken;
case CS.SyntaxKind.SlashToken:
return SyntaxKind.SlashToken;
case CS.SyntaxKind.PercentToken:
return SyntaxKind.ModKeyword;
case CS.SyntaxKind.LessThanLessThanToken:
return SyntaxKind.LessThanLessThanToken;
case CS.SyntaxKind.GreaterThanGreaterThanToken:
return SyntaxKind.GreaterThanGreaterThanToken;
case CS.SyntaxKind.EqualsEqualsToken:
return SyntaxKind.EqualsToken;
case CS.SyntaxKind.ExclamationEqualsToken:
return SyntaxKind.LessThanGreaterThanToken;
case CS.SyntaxKind.GreaterThanToken:
return SyntaxKind.GreaterThanToken;
case CS.SyntaxKind.LessThanToken:
return SyntaxKind.LessThanToken;
case CS.SyntaxKind.GreaterThanEqualsToken:
return SyntaxKind.GreaterThanEqualsToken;
case CS.SyntaxKind.LessThanEqualsToken:
return SyntaxKind.LessThanEqualsToken;
case CS.SyntaxKind.AmpersandToken:
return SyntaxKind.AndKeyword;
case CS.SyntaxKind.BarToken:
return SyntaxKind.OrKeyword;
}
throw new NotSupportedException();
throw new NotSupportedException($"{nameof(syntaxKind)} of {syntaxKind} cannot be converted");
}

public override VisualBasicSyntaxNode VisitConversionOperatorDeclaration(CSS.ConversionOperatorDeclarationSyntax node)
Expand Down
146 changes: 146 additions & 0 deletions Tests/VB/MemberTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,152 @@ End Sub
End Class");
}


[Fact]
public void OperatorOverloads()
{
// Note a couple map to the same thing in C# so occasionally the result won't compile. The user can manually decide what to do in such scenarios.
TestConversionCSharpToVisualBasic(@"public class AcmeClass
{
public static AcmeClass operator +(int i, AcmeClass ac)
{
return ac;
}
public static AcmeClass operator +(string s, AcmeClass ac)
{
return ac;
}
public static AcmeClass operator -(int i, AcmeClass ac)
{
return ac;
}
public static AcmeClass operator !(AcmeClass ac)
{
return ac;
}
public static AcmeClass operator *(int i, AcmeClass ac)
{
return ac;
}
public static AcmeClass operator /(int i, AcmeClass ac)
{
return ac;
}
public static AcmeClass operator %(string s, AcmeClass ac)
{
return ac;
}
public static AcmeClass operator <<(AcmeClass ac, int i)
{
return ac;
}
public static AcmeClass operator >>(AcmeClass ac, int i)
{
return ac;
}
public static AcmeClass operator ==(string s, AcmeClass ac)
{
return ac;
}
public static AcmeClass operator !=(string s, AcmeClass ac)
{
return ac;
}
public static AcmeClass operator <(string s, AcmeClass ac)
{
return ac;
}
public static AcmeClass operator >(string s, AcmeClass ac)
{
return ac;
}
public static AcmeClass operator <=(string s, AcmeClass ac)
{
return ac;
}
public static AcmeClass operator >=(string s, AcmeClass ac)
{
return ac;
}
public static AcmeClass operator &(string s, AcmeClass ac)
{
return ac;
}
public static AcmeClass operator |(string s, AcmeClass ac)
{
return ac;
}
}", @"Public Class AcmeClass
Public Shared Operator +(ByVal i As Integer, ByVal ac As AcmeClass) As AcmeClass
Return ac
End Operator
Public Shared Operator &(ByVal s As String, ByVal ac As AcmeClass) As AcmeClass
Return ac
End Operator
Public Shared Operator -(ByVal i As Integer, ByVal ac As AcmeClass) As AcmeClass
Return ac
End Operator
Public Shared Operator Not(ByVal ac As AcmeClass) As AcmeClass
Return ac
End Operator
Public Shared Operator *(ByVal i As Integer, ByVal ac As AcmeClass) As AcmeClass
Return ac
End Operator
Public Shared Operator /(ByVal i As Integer, ByVal ac As AcmeClass) As AcmeClass
Return ac
End Operator
Public Shared Operator Mod(ByVal s As String, ByVal ac As AcmeClass) As AcmeClass
Return ac
End Operator
Public Shared Operator <<(ByVal ac As AcmeClass, ByVal i As Integer) As AcmeClass
Return ac
End Operator
Public Shared Operator >>(ByVal ac As AcmeClass, ByVal i As Integer) As AcmeClass
Return ac
End Operator
Public Shared Operator =(ByVal s As String, ByVal ac As AcmeClass) As AcmeClass
Return ac
End Operator
Public Shared Operator <>(ByVal s As String, ByVal ac As AcmeClass) As AcmeClass
Return ac
End Operator
Public Shared Operator <(ByVal s As String, ByVal ac As AcmeClass) As AcmeClass
Return ac
End Operator
Public Shared Operator >(ByVal s As String, ByVal ac As AcmeClass) As AcmeClass
Return ac
End Operator
Public Shared Operator <=(ByVal s As String, ByVal ac As AcmeClass) As AcmeClass
Return ac
End Operator
Public Shared Operator >=(ByVal s As String, ByVal ac As AcmeClass) As AcmeClass
Return ac
End Operator
Public Shared Operator And(ByVal s As String, ByVal ac As AcmeClass) As AcmeClass
Return ac
End Operator
Public Shared Operator Or(ByVal s As String, ByVal ac As AcmeClass) As AcmeClass
Return ac
End Operator
End Class");
}

[Fact]
public void TestSealedMethod()
{
Expand Down

0 comments on commit 280e8d9

Please sign in to comment.