Skip to content

Commit 3379c7d

Browse files
authored
Support basic Java 14 switch expressions, #63 (#106)
1 parent 9957153 commit 3379c7d

38 files changed

+331
-160
lines changed

JavaToCSharp.Tests/IntegrationTests.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using Microsoft.CodeAnalysis;
33
using Microsoft.CodeAnalysis.CSharp;
44
using Microsoft.CodeAnalysis.CSharp.Syntax;
5+
using Xunit.Abstractions;
56

67
namespace JavaToCSharp.Tests;
78

@@ -11,7 +12,7 @@ namespace JavaToCSharp.Tests;
1112
/// <remarks>
1213
/// Uses some BSD-2-Clause licensed code from Jaktnat. License: https://github.com/paulirwin/jaktnat/blob/main/LICENSE
1314
/// </remarks>
14-
public class IntegrationTests
15+
public class IntegrationTests(ITestOutputHelper testOutputHelper)
1516
{
1617
[Theory]
1718
[InlineData("Resources/ArrayField.java")]
@@ -36,7 +37,10 @@ public void GeneralSuccessfulConversionTest(string filePath, bool allowWarnings
3637
};
3738

3839
var parsed = JavaToCSharpConverter.ConvertText(File.ReadAllText(filePath), options);
40+
3941
Assert.NotNull(parsed);
42+
43+
testOutputHelper.WriteLine(parsed);
4044
}
4145

4246
[Theory]
@@ -62,6 +66,7 @@ public void GeneralUnsuccessfulConversionTest(string filePath)
6266
[InlineData("Resources/Java9TryWithResources.java")]
6367
[InlineData("Resources/Java9PrivateInterfaceMethods.java")]
6468
[InlineData("Resources/Java10TypeInference.java")]
69+
[InlineData("Resources/Java14SwitchExpressions.java")]
6570
[InlineData("Resources/NewArrayLiteralBug.java")]
6671
[InlineData("Resources/OctalLiteralBug.java")]
6772
[InlineData("Resources/DeprecatedAnnotation.java")]
@@ -81,8 +86,11 @@ public void FullIntegrationTests(string filePath)
8186
var javaText = File.ReadAllText(filePath);
8287

8388
var parsed = JavaToCSharpConverter.ConvertText(javaText, options);
89+
8490
Assert.NotNull(parsed);
8591

92+
testOutputHelper.WriteLine(parsed);
93+
8694
var fileName = Path.GetFileNameWithoutExtension(filePath);
8795
var assembly = CompileAssembly(fileName, parsed);
8896

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/// Expect:
2+
/// - output: "9\n"
3+
package example;
4+
5+
// https://docs.oracle.com/en/java/javase/14/language/switch-expressions.html#GUID-BA4F63E3-4823-43C6-A5F3-BAA4A2EF3ADC
6+
7+
enum Day { SUNDAY, MONDAY, TUESDAY,
8+
WEDNESDAY, THURSDAY, FRIDAY, SATURDAY; }
9+
10+
public class Program {
11+
public static void main(String[] args) {
12+
Day day = Day.WEDNESDAY;
13+
System.out.println(
14+
switch (day) {
15+
case MONDAY, FRIDAY, SUNDAY -> 6;
16+
case TUESDAY -> 7;
17+
case THURSDAY, SATURDAY -> 8;
18+
case WEDNESDAY -> 9;
19+
default -> throw new IllegalStateException("Invalid day: " + day);
20+
}
21+
);
22+
}
23+
}

JavaToCSharp/CommentsHelper.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -475,7 +475,7 @@ private static SyntaxNode AdjustBlockCommentIndentation(SyntaxNode node)
475475
lines[l] = indentString + lines[l].TrimStart();
476476
}
477477

478-
node = node.ReplaceTrivia(t, SyntaxFactory.Comment(String.Join(Environment.NewLine, lines).TrimEnd(' ')));
478+
node = node.ReplaceTrivia(t, SyntaxFactory.Comment(string.Join(Environment.NewLine, lines).TrimEnd(' ')));
479479
}
480480
}
481481

JavaToCSharp/Declarations/ClassOrInterfaceDeclarationVisitor.cs

Lines changed: 39 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,10 @@ public class ClassOrInterfaceDeclarationVisitor : BodyDeclarationVisitor<ClassOr
2828
return VisitClassDeclaration(context, declaration);
2929
}
3030

31-
public static InterfaceDeclarationSyntax? VisitInterfaceDeclaration(ConversionContext context,
32-
ClassOrInterfaceDeclaration javai, bool isNested = false)
31+
public static InterfaceDeclarationSyntax VisitInterfaceDeclaration(ConversionContext context,
32+
ClassOrInterfaceDeclaration interfaceDecl, bool isNested = false)
3333
{
34-
var originalTypeName = javai.getName();
34+
var originalTypeName = interfaceDecl.getName();
3535
var newTypeName = context.Options.StartInterfaceNamesWithI
3636
? $"I{originalTypeName.getIdentifier()}"
3737
: originalTypeName.getIdentifier();
@@ -42,22 +42,23 @@ public class ClassOrInterfaceDeclarationVisitor : BodyDeclarationVisitor<ClassOr
4242
}
4343

4444
if (!isNested)
45+
{
4546
context.RootTypeName = newTypeName;
47+
}
4648

4749
context.LastTypeName = newTypeName;
4850

4951
var classSyntax = SyntaxFactory.InterfaceDeclaration(newTypeName);
5052

51-
var typeParams = javai.getTypeParameters().ToList<TypeParameter>();
53+
var typeParams = interfaceDecl.getTypeParameters().ToList<TypeParameter>();
5254

5355
if (typeParams is { Count: > 0 })
5456
{
55-
classSyntax =
56-
classSyntax.AddTypeParameterListParameters(typeParams
57+
classSyntax = classSyntax.AddTypeParameterListParameters(typeParams
5758
.Select(i => SyntaxFactory.TypeParameter(i.getNameAsString())).ToArray());
5859
}
5960

60-
var mods = javai.getModifiers().ToModifierKeywordSet();
61+
var mods = interfaceDecl.getModifiers().ToModifierKeywordSet();
6162

6263
if (mods.Contains(Modifier.Keyword.PRIVATE))
6364
classSyntax = classSyntax.AddModifiers(SyntaxFactory.Token(SyntaxKind.PrivateKeyword));
@@ -68,64 +69,68 @@ public class ClassOrInterfaceDeclarationVisitor : BodyDeclarationVisitor<ClassOr
6869
if (mods.Contains(Modifier.Keyword.FINAL))
6970
classSyntax = classSyntax.AddModifiers(SyntaxFactory.Token(SyntaxKind.SealedKeyword));
7071

71-
var extends = javai.getExtendedTypes().ToList<ClassOrInterfaceType>();
72+
var extends = interfaceDecl.getExtendedTypes().ToList<ClassOrInterfaceType>();
73+
7274
if (extends != null)
7375
{
7476
foreach (var extend in extends)
7577
{
76-
classSyntax =
77-
classSyntax.AddBaseListTypes(SyntaxFactory.SimpleBaseType(TypeHelper.GetSyntaxFromType(extend)));
78+
classSyntax = classSyntax.AddBaseListTypes(SyntaxFactory.SimpleBaseType(TypeHelper.GetSyntaxFromType(extend)));
7879
}
7980
}
8081

81-
var implements = javai.getImplementedTypes().ToList<ClassOrInterfaceType>();
82+
var implements = interfaceDecl.getImplementedTypes().ToList<ClassOrInterfaceType>();
83+
8284
if (implements != null)
8385
{
8486
foreach (var implement in implements)
8587
{
86-
classSyntax =
87-
classSyntax.AddBaseListTypes(SyntaxFactory.SimpleBaseType(TypeHelper.GetSyntaxFromType(implement)));
88+
classSyntax = classSyntax.AddBaseListTypes(SyntaxFactory.SimpleBaseType(TypeHelper.GetSyntaxFromType(implement)));
8889
}
8990
}
9091

91-
var members = javai.getMembers()?.ToList<BodyDeclaration>();
92+
var members = interfaceDecl.getMembers()?.ToList<BodyDeclaration>();
9293

9394
if (members is not null)
95+
{
9496
foreach (var member in members)
9597
{
9698
var syntax = VisitBodyDeclarationForInterface(context, classSyntax, member);
9799
var memberWithComments = syntax?.WithJavaComments(context, member);
100+
98101
if (memberWithComments != null)
99102
{
100103
classSyntax = classSyntax.AddMembers(memberWithComments);
101104
}
102105
}
106+
}
103107

104-
return classSyntax.WithJavaComments(context, javai);
108+
return classSyntax.WithJavaComments(context, interfaceDecl);
105109
}
106110

107-
public static ClassDeclarationSyntax? VisitClassDeclaration(ConversionContext context,
108-
ClassOrInterfaceDeclaration javac, bool isNested = false)
111+
public static ClassDeclarationSyntax VisitClassDeclaration(ConversionContext context,
112+
ClassOrInterfaceDeclaration classDecl, bool isNested = false)
109113
{
110-
string name = javac.getNameAsString();
114+
string name = classDecl.getNameAsString();
111115

112116
if (!isNested)
117+
{
113118
context.RootTypeName = name;
119+
}
114120

115121
context.LastTypeName = name;
116122

117123
var classSyntax = SyntaxFactory.ClassDeclaration(name);
118124

119-
var typeParams = javac.getTypeParameters().ToList<TypeParameter>();
125+
var typeParams = classDecl.getTypeParameters().ToList<TypeParameter>();
120126

121127
if (typeParams is { Count: > 0 })
122128
{
123-
classSyntax =
124-
classSyntax.AddTypeParameterListParameters(typeParams
129+
classSyntax = classSyntax.AddTypeParameterListParameters(typeParams
125130
.Select(i => SyntaxFactory.TypeParameter(i.getNameAsString())).ToArray());
126131
}
127132

128-
var mods = javac.getModifiers().ToModifierKeywordSet();
133+
var mods = classDecl.getModifiers().ToModifierKeywordSet();
129134

130135
if (mods.Contains(Modifier.Keyword.PRIVATE))
131136
classSyntax = classSyntax.AddModifiers(SyntaxFactory.Token(SyntaxKind.PrivateKeyword));
@@ -138,23 +143,21 @@ public class ClassOrInterfaceDeclarationVisitor : BodyDeclarationVisitor<ClassOr
138143
if (mods.Contains(Modifier.Keyword.FINAL))
139144
classSyntax = classSyntax.AddModifiers(SyntaxFactory.Token(SyntaxKind.SealedKeyword));
140145

141-
var extends = javac.getExtendedTypes().ToList<ClassOrInterfaceType>() ?? new List<ClassOrInterfaceType>();
146+
var extends = classDecl.getExtendedTypes().ToList<ClassOrInterfaceType>() ?? new List<ClassOrInterfaceType>();
142147

143148
foreach (var extend in extends)
144149
{
145-
classSyntax =
146-
classSyntax.AddBaseListTypes(SyntaxFactory.SimpleBaseType(TypeHelper.GetSyntaxFromType(extend)));
150+
classSyntax = classSyntax.AddBaseListTypes(SyntaxFactory.SimpleBaseType(TypeHelper.GetSyntaxFromType(extend)));
147151
}
148152

149-
var implements = javac.getImplementedTypes().ToList<ClassOrInterfaceType>() ?? new List<ClassOrInterfaceType>();
153+
var implements = classDecl.getImplementedTypes().ToList<ClassOrInterfaceType>() ?? new List<ClassOrInterfaceType>();
150154

151155
foreach (var implement in implements)
152156
{
153-
classSyntax =
154-
classSyntax.AddBaseListTypes(SyntaxFactory.SimpleBaseType(TypeHelper.GetSyntaxFromType(implement)));
157+
classSyntax = classSyntax.AddBaseListTypes(SyntaxFactory.SimpleBaseType(TypeHelper.GetSyntaxFromType(implement)));
155158
}
156159

157-
var members = javac.getMembers()?.ToList<BodyDeclaration>();
160+
var members = classDecl.getMembers()?.ToList<BodyDeclaration>();
158161

159162
if (members is not null)
160163
{
@@ -165,24 +168,21 @@ public class ClassOrInterfaceDeclarationVisitor : BodyDeclarationVisitor<ClassOr
165168
if (childType.isInterface())
166169
{
167170
var childInt = VisitInterfaceDeclaration(context, childType, true);
168-
if (childInt is not null)
169-
{
170-
classSyntax = classSyntax.AddMembers(childInt);
171-
}
171+
172+
classSyntax = classSyntax.AddMembers(childInt);
172173
}
173174
else
174175
{
175176
var childClass = VisitClassDeclaration(context, childType, true);
176-
if (childClass is not null)
177-
{
178-
classSyntax = classSyntax.AddMembers(childClass);
179-
}
177+
178+
classSyntax = classSyntax.AddMembers(childClass);
180179
}
181180
}
182181
else
183182
{
184183
var syntax = VisitBodyDeclarationForClass(context, classSyntax, member, extends, implements);
185184
var withJavaComments = syntax?.WithJavaComments(context, member);
185+
186186
if (withJavaComments != null)
187187
{
188188
classSyntax = classSyntax.AddMembers(withJavaComments);
@@ -197,7 +197,7 @@ public class ClassOrInterfaceDeclarationVisitor : BodyDeclarationVisitor<ClassOr
197197
}
198198
}
199199

200-
var annotations = javac.getAnnotations().ToList<AnnotationExpr>();
200+
var annotations = classDecl.getAnnotations().ToList<AnnotationExpr>();
201201

202202
if (annotations is { Count: > 0 })
203203
{
@@ -224,6 +224,6 @@ public class ClassOrInterfaceDeclarationVisitor : BodyDeclarationVisitor<ClassOr
224224
}
225225
}
226226

227-
return classSyntax.WithJavaComments(context, javac);
227+
return classSyntax.WithJavaComments(context, classDecl);
228228
}
229229
}

0 commit comments

Comments
 (0)