Skip to content

Commit 280e8d9

Browse files
Do all the same mappings that vb -> c# does - fixes #240
1 parent ed09554 commit 280e8d9

3 files changed

Lines changed: 183 additions & 3 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ All notable changes to the code converter will be documented here.
55

66
### C# -> VB
77
* Tuples now converted
8+
* All known operator overloads now converted
89

910
# 6.3.0 05/02/2019
1011
* VS 2019 support

ICSharpCode.CodeConverter/VB/NodesVisitor.cs

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -602,24 +602,57 @@ public override VisualBasicSyntaxNode VisitOperatorDeclaration(CSS.OperatorDecla
602602
ConvertAndSplitAttributes(node.AttributeLists, out var attributes, out var returnAttributes);
603603
var body = _commonConversions.ConvertBody(node.Body, node.ExpressionBody);
604604
var parameterList = (ParameterListSyntax)node.ParameterList?.Accept(TriviaConvertingVisitor);
605+
var firstParam = node.ParameterList?.Parameters.FirstOrDefault()
606+
?? throw new NotSupportedException("Operator overloads with no parameters aren't supported");
607+
var firstParameterIsString = _semanticModel.GetTypeInfo(firstParam.Type).ConvertedType.SpecialType == SpecialType.System_String;
605608
var stmt = SyntaxFactory.OperatorStatement(
606609
attributes, CommonConversions.ConvertModifiers(node.Modifiers, GetMemberContext(node)),
607-
SyntaxFactory.Token(ConvertOperatorDeclarationToken(CS.CSharpExtensions.Kind(node.OperatorToken))),
610+
SyntaxFactory.Token(ConvertOperatorDeclarationToken(CS.CSharpExtensions.Kind(node.OperatorToken), firstParameterIsString)),
608611
parameterList,
609612
SyntaxFactory.SimpleAsClause(returnAttributes, (TypeSyntax)node.ReturnType.Accept(TriviaConvertingVisitor))
610613
);
611614
return SyntaxFactory.OperatorBlock(stmt, body);
612615
}
613616

614-
SyntaxKind ConvertOperatorDeclarationToken(CS.SyntaxKind syntaxKind)
617+
618+
619+
SyntaxKind ConvertOperatorDeclarationToken(CS.SyntaxKind syntaxKind, bool firstParameterIsString)
615620
{
616621
switch (syntaxKind) {
622+
case CS.SyntaxKind.PlusToken:
623+
return firstParameterIsString ? SyntaxKind.AmpersandToken : SyntaxKind.PlusToken;
624+
case CS.SyntaxKind.MinusToken:
625+
return SyntaxKind.MinusToken;
626+
case CS.SyntaxKind.ExclamationToken:
627+
return SyntaxKind.NotKeyword;
628+
case CS.SyntaxKind.AsteriskToken:
629+
return SyntaxKind.AsteriskToken;
630+
case CS.SyntaxKind.SlashToken:
631+
return SyntaxKind.SlashToken;
632+
case CS.SyntaxKind.PercentToken:
633+
return SyntaxKind.ModKeyword;
634+
case CS.SyntaxKind.LessThanLessThanToken:
635+
return SyntaxKind.LessThanLessThanToken;
636+
case CS.SyntaxKind.GreaterThanGreaterThanToken:
637+
return SyntaxKind.GreaterThanGreaterThanToken;
617638
case CS.SyntaxKind.EqualsEqualsToken:
618639
return SyntaxKind.EqualsToken;
619640
case CS.SyntaxKind.ExclamationEqualsToken:
620641
return SyntaxKind.LessThanGreaterThanToken;
642+
case CS.SyntaxKind.GreaterThanToken:
643+
return SyntaxKind.GreaterThanToken;
644+
case CS.SyntaxKind.LessThanToken:
645+
return SyntaxKind.LessThanToken;
646+
case CS.SyntaxKind.GreaterThanEqualsToken:
647+
return SyntaxKind.GreaterThanEqualsToken;
648+
case CS.SyntaxKind.LessThanEqualsToken:
649+
return SyntaxKind.LessThanEqualsToken;
650+
case CS.SyntaxKind.AmpersandToken:
651+
return SyntaxKind.AndKeyword;
652+
case CS.SyntaxKind.BarToken:
653+
return SyntaxKind.OrKeyword;
621654
}
622-
throw new NotSupportedException();
655+
throw new NotSupportedException($"{nameof(syntaxKind)} of {syntaxKind} cannot be converted");
623656
}
624657

625658
public override VisualBasicSyntaxNode VisitConversionOperatorDeclaration(CSS.ConversionOperatorDeclarationSyntax node)

Tests/VB/MemberTests.cs

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,152 @@ End Sub
138138
End Class");
139139
}
140140

141+
142+
[Fact]
143+
public void OperatorOverloads()
144+
{
145+
// 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.
146+
TestConversionCSharpToVisualBasic(@"public class AcmeClass
147+
{
148+
public static AcmeClass operator +(int i, AcmeClass ac)
149+
{
150+
return ac;
151+
}
152+
public static AcmeClass operator +(string s, AcmeClass ac)
153+
{
154+
return ac;
155+
}
156+
public static AcmeClass operator -(int i, AcmeClass ac)
157+
{
158+
return ac;
159+
}
160+
public static AcmeClass operator !(AcmeClass ac)
161+
{
162+
return ac;
163+
}
164+
public static AcmeClass operator *(int i, AcmeClass ac)
165+
{
166+
return ac;
167+
}
168+
public static AcmeClass operator /(int i, AcmeClass ac)
169+
{
170+
return ac;
171+
}
172+
public static AcmeClass operator %(string s, AcmeClass ac)
173+
{
174+
return ac;
175+
}
176+
public static AcmeClass operator <<(AcmeClass ac, int i)
177+
{
178+
return ac;
179+
}
180+
public static AcmeClass operator >>(AcmeClass ac, int i)
181+
{
182+
return ac;
183+
}
184+
public static AcmeClass operator ==(string s, AcmeClass ac)
185+
{
186+
return ac;
187+
}
188+
public static AcmeClass operator !=(string s, AcmeClass ac)
189+
{
190+
return ac;
191+
}
192+
public static AcmeClass operator <(string s, AcmeClass ac)
193+
{
194+
return ac;
195+
}
196+
public static AcmeClass operator >(string s, AcmeClass ac)
197+
{
198+
return ac;
199+
}
200+
public static AcmeClass operator <=(string s, AcmeClass ac)
201+
{
202+
return ac;
203+
}
204+
public static AcmeClass operator >=(string s, AcmeClass ac)
205+
{
206+
return ac;
207+
}
208+
public static AcmeClass operator &(string s, AcmeClass ac)
209+
{
210+
return ac;
211+
}
212+
public static AcmeClass operator |(string s, AcmeClass ac)
213+
{
214+
return ac;
215+
}
216+
}", @"Public Class AcmeClass
217+
Public Shared Operator +(ByVal i As Integer, ByVal ac As AcmeClass) As AcmeClass
218+
Return ac
219+
End Operator
220+
221+
Public Shared Operator &(ByVal s As String, ByVal ac As AcmeClass) As AcmeClass
222+
Return ac
223+
End Operator
224+
225+
Public Shared Operator -(ByVal i As Integer, ByVal ac As AcmeClass) As AcmeClass
226+
Return ac
227+
End Operator
228+
229+
Public Shared Operator Not(ByVal ac As AcmeClass) As AcmeClass
230+
Return ac
231+
End Operator
232+
233+
Public Shared Operator *(ByVal i As Integer, ByVal ac As AcmeClass) As AcmeClass
234+
Return ac
235+
End Operator
236+
237+
Public Shared Operator /(ByVal i As Integer, ByVal ac As AcmeClass) As AcmeClass
238+
Return ac
239+
End Operator
240+
241+
Public Shared Operator Mod(ByVal s As String, ByVal ac As AcmeClass) As AcmeClass
242+
Return ac
243+
End Operator
244+
245+
Public Shared Operator <<(ByVal ac As AcmeClass, ByVal i As Integer) As AcmeClass
246+
Return ac
247+
End Operator
248+
249+
Public Shared Operator >>(ByVal ac As AcmeClass, ByVal i As Integer) As AcmeClass
250+
Return ac
251+
End Operator
252+
253+
Public Shared Operator =(ByVal s As String, ByVal ac As AcmeClass) As AcmeClass
254+
Return ac
255+
End Operator
256+
257+
Public Shared Operator <>(ByVal s As String, ByVal ac As AcmeClass) As AcmeClass
258+
Return ac
259+
End Operator
260+
261+
Public Shared Operator <(ByVal s As String, ByVal ac As AcmeClass) As AcmeClass
262+
Return ac
263+
End Operator
264+
265+
Public Shared Operator >(ByVal s As String, ByVal ac As AcmeClass) As AcmeClass
266+
Return ac
267+
End Operator
268+
269+
Public Shared Operator <=(ByVal s As String, ByVal ac As AcmeClass) As AcmeClass
270+
Return ac
271+
End Operator
272+
273+
Public Shared Operator >=(ByVal s As String, ByVal ac As AcmeClass) As AcmeClass
274+
Return ac
275+
End Operator
276+
277+
Public Shared Operator And(ByVal s As String, ByVal ac As AcmeClass) As AcmeClass
278+
Return ac
279+
End Operator
280+
281+
Public Shared Operator Or(ByVal s As String, ByVal ac As AcmeClass) As AcmeClass
282+
Return ac
283+
End Operator
284+
End Class");
285+
}
286+
141287
[Fact]
142288
public void TestSealedMethod()
143289
{

0 commit comments

Comments
 (0)