From 731a7e6d70530e5edbfce3af8f92e0964dbb927f Mon Sep 17 00:00:00 2001 From: GrahamTheCoder Date: Sat, 31 Mar 2018 02:57:32 +0100 Subject: [PATCH] VB -> C#: Operator overload support - fixes #46 --- .../CSharp/SyntaxKindExtensions.cs | 31 ++++ Tests/CSharp/MemberTests.cs | 159 ++++++++++++++++++ 2 files changed, 190 insertions(+) diff --git a/ICSharpCode.CodeConverter/CSharp/SyntaxKindExtensions.cs b/ICSharpCode.CodeConverter/CSharp/SyntaxKindExtensions.cs index 82d800a7a..7450c1e15 100644 --- a/ICSharpCode.CodeConverter/CSharp/SyntaxKindExtensions.cs +++ b/ICSharpCode.CodeConverter/CSharp/SyntaxKindExtensions.cs @@ -217,6 +217,37 @@ public static SyntaxKind ConvertToken(this Microsoft.CodeAnalysis.VisualBasic.Sy return SyntaxKind.ExplicitKeyword; case Microsoft.CodeAnalysis.VisualBasic.SyntaxKind.WideningKeyword: return SyntaxKind.ImplicitKeyword; + // Operator overloads + case Microsoft.CodeAnalysis.VisualBasic.SyntaxKind.PlusToken: + case Microsoft.CodeAnalysis.VisualBasic.SyntaxKind.AmpersandToken: + return SyntaxKind.PlusToken; //Problematic clash if two operator overloads defined + case Microsoft.CodeAnalysis.VisualBasic.SyntaxKind.MinusToken: + return SyntaxKind.MinusToken; + case Microsoft.CodeAnalysis.VisualBasic.SyntaxKind.NotKeyword: + return SyntaxKind.ExclamationToken; + case Microsoft.CodeAnalysis.VisualBasic.SyntaxKind.AsteriskToken: + return SyntaxKind.AsteriskToken; + case Microsoft.CodeAnalysis.VisualBasic.SyntaxKind.SlashToken: + case Microsoft.CodeAnalysis.VisualBasic.SyntaxKind.BackslashToken: + return SyntaxKind.SlashToken; //Problematic clash if two operator overloads defined + case Microsoft.CodeAnalysis.VisualBasic.SyntaxKind.ModKeyword: + return SyntaxKind.PercentToken; + case Microsoft.CodeAnalysis.VisualBasic.SyntaxKind.LessThanLessThanToken: + return SyntaxKind.LessThanLessThanToken; + case Microsoft.CodeAnalysis.VisualBasic.SyntaxKind.GreaterThanGreaterThanToken: + return SyntaxKind.GreaterThanGreaterThanToken; + case Microsoft.CodeAnalysis.VisualBasic.SyntaxKind.EqualsToken: + return SyntaxKind.EqualsEqualsToken; + case Microsoft.CodeAnalysis.VisualBasic.SyntaxKind.LessThanGreaterThanToken: + return SyntaxKind.ExclamationEqualsToken; + case Microsoft.CodeAnalysis.VisualBasic.SyntaxKind.GreaterThanToken: + return SyntaxKind.GreaterThanToken; + case Microsoft.CodeAnalysis.VisualBasic.SyntaxKind.LessThanToken: + return SyntaxKind.LessThanToken; + case Microsoft.CodeAnalysis.VisualBasic.SyntaxKind.GreaterThanEqualsToken: + return SyntaxKind.GreaterThanEqualsToken; + case Microsoft.CodeAnalysis.VisualBasic.SyntaxKind.LessThanEqualsToken: + return SyntaxKind.LessThanEqualsToken; // case Microsoft.CodeAnalysis.VisualBasic.SyntaxKind.AssemblyKeyword: return SyntaxKind.AssemblyKeyword; diff --git a/Tests/CSharp/MemberTests.cs b/Tests/CSharp/MemberTests.cs index abbeff54f..90eb9f362 100644 --- a/Tests/CSharp/MemberTests.cs +++ b/Tests/CSharp/MemberTests.cs @@ -550,6 +550,165 @@ public static implicit operator int(MyInt myInt) }"); } + [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. + TestConversionVisualBasicToCSharpWithoutComments(@"Public Class AcmeClass + Public Shared Operator +(i As Integer, ac As AcmeClass) As AcmeClass + Return ac + End Operator + Public Shared Operator &(s As String, ac As AcmeClass) As AcmeClass + Return ac + End Operator + Public Shared Operator -(i As Integer, ac As AcmeClass) As AcmeClass + Return ac + End Operator + Public Shared Operator Not(ac As AcmeClass) As AcmeClass + Return ac + End Operator + Public Shared Operator *(i As Integer, ac As AcmeClass) As AcmeClass + Return ac + End Operator + Public Shared Operator /(i As Integer, ac As AcmeClass) As AcmeClass + Return ac + End Operator + Public Shared Operator \(i As Integer, ac As AcmeClass) As AcmeClass + Return ac + End Operator + Public Shared Operator Mod(s As String, ac As AcmeClass) As AcmeClass + Return ac + End Operator + Public Shared Operator <<(ac As AcmeClass, i As Integer) As AcmeClass + Return ac + End Operator + Public Shared Operator >>(ac As AcmeClass, i As Integer) As AcmeClass + Return ac + End Operator + Public Shared Operator =(s As String, ac As AcmeClass) As AcmeClass + Return ac + End Operator + Public Shared Operator <>(s As String, ac As AcmeClass) As AcmeClass + Return ac + End Operator + Public Shared Operator <(s As String, ac As AcmeClass) As AcmeClass + Return ac + End Operator + Public Shared Operator >(s As String, ac As AcmeClass) As AcmeClass + Return ac + End Operator + Public Shared Operator <=(s As String, ac As AcmeClass) As AcmeClass + Return ac + End Operator + Public Shared Operator >=(s As String, ac As AcmeClass) As AcmeClass + Return ac + End Operator +End Class", @"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 /(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; + } +}"); + } + + [Fact(Skip = "No obvious C# equivalent")] + public void OperatorOverloadsWithNoCSharpEquivalent() + { + TestConversionVisualBasicToCSharpWithoutComments(@"Public Class AcmeClass + Public Shared Operator ^(i As Integer, ac As AcmeClass) As AcmeClass + Return ac + End Operator + Public Shared Operator Like(s As String, ac As AcmeClass) As AcmeClass + Return ac + End Operator + Public Shared Operator And(s As String, ac As AcmeClass) As AcmeClass + Return ac + End Operator + Public Shared Operator Or(s As String, ac As AcmeClass) As AcmeClass + Return ac + End Operator +End Class", @"public class AcmeClass" + /* not valid C#, just a starter */ @" +{ + public static AcmeClass operator ^(int i, AcmeClass ac) + { + return ac; + } + public static AcmeClass operator Like(string s, AcmeClass ac) + { + return ac; + } + public static AcmeClass operator And(string s, AcmeClass ac) + { + return ac; + } + public static AcmeClass operator Or(string s, AcmeClass ac) + { + return ac; + } +}"); + } + [Fact] public void ClassWithGloballyQualifiedAttribute() {