Skip to content

Commit

Permalink
Support basic Java 14 switch expressions, #63 (#106)
Browse files Browse the repository at this point in the history
  • Loading branch information
paulirwin authored Feb 14, 2024
1 parent 9957153 commit 3379c7d
Show file tree
Hide file tree
Showing 38 changed files with 331 additions and 160 deletions.
10 changes: 9 additions & 1 deletion JavaToCSharp.Tests/IntegrationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Xunit.Abstractions;

namespace JavaToCSharp.Tests;

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

var parsed = JavaToCSharpConverter.ConvertText(File.ReadAllText(filePath), options);

Assert.NotNull(parsed);

testOutputHelper.WriteLine(parsed);
}

[Theory]
Expand All @@ -62,6 +66,7 @@ public void GeneralUnsuccessfulConversionTest(string filePath)
[InlineData("Resources/Java9TryWithResources.java")]
[InlineData("Resources/Java9PrivateInterfaceMethods.java")]
[InlineData("Resources/Java10TypeInference.java")]
[InlineData("Resources/Java14SwitchExpressions.java")]
[InlineData("Resources/NewArrayLiteralBug.java")]
[InlineData("Resources/OctalLiteralBug.java")]
[InlineData("Resources/DeprecatedAnnotation.java")]
Expand All @@ -81,8 +86,11 @@ public void FullIntegrationTests(string filePath)
var javaText = File.ReadAllText(filePath);

var parsed = JavaToCSharpConverter.ConvertText(javaText, options);

Assert.NotNull(parsed);

testOutputHelper.WriteLine(parsed);

var fileName = Path.GetFileNameWithoutExtension(filePath);
var assembly = CompileAssembly(fileName, parsed);

Expand Down
23 changes: 23 additions & 0 deletions JavaToCSharp.Tests/Resources/Java14SwitchExpressions.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/// Expect:
/// - output: "9\n"
package example;

// https://docs.oracle.com/en/java/javase/14/language/switch-expressions.html#GUID-BA4F63E3-4823-43C6-A5F3-BAA4A2EF3ADC

enum Day { SUNDAY, MONDAY, TUESDAY,
WEDNESDAY, THURSDAY, FRIDAY, SATURDAY; }

public class Program {
public static void main(String[] args) {
Day day = Day.WEDNESDAY;
System.out.println(
switch (day) {
case MONDAY, FRIDAY, SUNDAY -> 6;
case TUESDAY -> 7;
case THURSDAY, SATURDAY -> 8;
case WEDNESDAY -> 9;
default -> throw new IllegalStateException("Invalid day: " + day);
}
);
}
}
2 changes: 1 addition & 1 deletion JavaToCSharp/CommentsHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -475,7 +475,7 @@ private static SyntaxNode AdjustBlockCommentIndentation(SyntaxNode node)
lines[l] = indentString + lines[l].TrimStart();
}

node = node.ReplaceTrivia(t, SyntaxFactory.Comment(String.Join(Environment.NewLine, lines).TrimEnd(' ')));
node = node.ReplaceTrivia(t, SyntaxFactory.Comment(string.Join(Environment.NewLine, lines).TrimEnd(' ')));
}
}

Expand Down
78 changes: 39 additions & 39 deletions JavaToCSharp/Declarations/ClassOrInterfaceDeclarationVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,10 @@ public class ClassOrInterfaceDeclarationVisitor : BodyDeclarationVisitor<ClassOr
return VisitClassDeclaration(context, declaration);
}

public static InterfaceDeclarationSyntax? VisitInterfaceDeclaration(ConversionContext context,
ClassOrInterfaceDeclaration javai, bool isNested = false)
public static InterfaceDeclarationSyntax VisitInterfaceDeclaration(ConversionContext context,
ClassOrInterfaceDeclaration interfaceDecl, bool isNested = false)
{
var originalTypeName = javai.getName();
var originalTypeName = interfaceDecl.getName();
var newTypeName = context.Options.StartInterfaceNamesWithI
? $"I{originalTypeName.getIdentifier()}"
: originalTypeName.getIdentifier();
Expand All @@ -42,22 +42,23 @@ public class ClassOrInterfaceDeclarationVisitor : BodyDeclarationVisitor<ClassOr
}

if (!isNested)
{
context.RootTypeName = newTypeName;
}

context.LastTypeName = newTypeName;

var classSyntax = SyntaxFactory.InterfaceDeclaration(newTypeName);

var typeParams = javai.getTypeParameters().ToList<TypeParameter>();
var typeParams = interfaceDecl.getTypeParameters().ToList<TypeParameter>();

if (typeParams is { Count: > 0 })
{
classSyntax =
classSyntax.AddTypeParameterListParameters(typeParams
classSyntax = classSyntax.AddTypeParameterListParameters(typeParams
.Select(i => SyntaxFactory.TypeParameter(i.getNameAsString())).ToArray());
}

var mods = javai.getModifiers().ToModifierKeywordSet();
var mods = interfaceDecl.getModifiers().ToModifierKeywordSet();

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

var extends = javai.getExtendedTypes().ToList<ClassOrInterfaceType>();
var extends = interfaceDecl.getExtendedTypes().ToList<ClassOrInterfaceType>();

if (extends != null)
{
foreach (var extend in extends)
{
classSyntax =
classSyntax.AddBaseListTypes(SyntaxFactory.SimpleBaseType(TypeHelper.GetSyntaxFromType(extend)));
classSyntax = classSyntax.AddBaseListTypes(SyntaxFactory.SimpleBaseType(TypeHelper.GetSyntaxFromType(extend)));
}
}

var implements = javai.getImplementedTypes().ToList<ClassOrInterfaceType>();
var implements = interfaceDecl.getImplementedTypes().ToList<ClassOrInterfaceType>();

if (implements != null)
{
foreach (var implement in implements)
{
classSyntax =
classSyntax.AddBaseListTypes(SyntaxFactory.SimpleBaseType(TypeHelper.GetSyntaxFromType(implement)));
classSyntax = classSyntax.AddBaseListTypes(SyntaxFactory.SimpleBaseType(TypeHelper.GetSyntaxFromType(implement)));
}
}

var members = javai.getMembers()?.ToList<BodyDeclaration>();
var members = interfaceDecl.getMembers()?.ToList<BodyDeclaration>();

if (members is not null)
{
foreach (var member in members)
{
var syntax = VisitBodyDeclarationForInterface(context, classSyntax, member);
var memberWithComments = syntax?.WithJavaComments(context, member);

if (memberWithComments != null)
{
classSyntax = classSyntax.AddMembers(memberWithComments);
}
}
}

return classSyntax.WithJavaComments(context, javai);
return classSyntax.WithJavaComments(context, interfaceDecl);
}

public static ClassDeclarationSyntax? VisitClassDeclaration(ConversionContext context,
ClassOrInterfaceDeclaration javac, bool isNested = false)
public static ClassDeclarationSyntax VisitClassDeclaration(ConversionContext context,
ClassOrInterfaceDeclaration classDecl, bool isNested = false)
{
string name = javac.getNameAsString();
string name = classDecl.getNameAsString();

if (!isNested)
{
context.RootTypeName = name;
}

context.LastTypeName = name;

var classSyntax = SyntaxFactory.ClassDeclaration(name);

var typeParams = javac.getTypeParameters().ToList<TypeParameter>();
var typeParams = classDecl.getTypeParameters().ToList<TypeParameter>();

if (typeParams is { Count: > 0 })
{
classSyntax =
classSyntax.AddTypeParameterListParameters(typeParams
classSyntax = classSyntax.AddTypeParameterListParameters(typeParams
.Select(i => SyntaxFactory.TypeParameter(i.getNameAsString())).ToArray());
}

var mods = javac.getModifiers().ToModifierKeywordSet();
var mods = classDecl.getModifiers().ToModifierKeywordSet();

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

var extends = javac.getExtendedTypes().ToList<ClassOrInterfaceType>() ?? new List<ClassOrInterfaceType>();
var extends = classDecl.getExtendedTypes().ToList<ClassOrInterfaceType>() ?? new List<ClassOrInterfaceType>();

foreach (var extend in extends)
{
classSyntax =
classSyntax.AddBaseListTypes(SyntaxFactory.SimpleBaseType(TypeHelper.GetSyntaxFromType(extend)));
classSyntax = classSyntax.AddBaseListTypes(SyntaxFactory.SimpleBaseType(TypeHelper.GetSyntaxFromType(extend)));
}

var implements = javac.getImplementedTypes().ToList<ClassOrInterfaceType>() ?? new List<ClassOrInterfaceType>();
var implements = classDecl.getImplementedTypes().ToList<ClassOrInterfaceType>() ?? new List<ClassOrInterfaceType>();

foreach (var implement in implements)
{
classSyntax =
classSyntax.AddBaseListTypes(SyntaxFactory.SimpleBaseType(TypeHelper.GetSyntaxFromType(implement)));
classSyntax = classSyntax.AddBaseListTypes(SyntaxFactory.SimpleBaseType(TypeHelper.GetSyntaxFromType(implement)));
}

var members = javac.getMembers()?.ToList<BodyDeclaration>();
var members = classDecl.getMembers()?.ToList<BodyDeclaration>();

if (members is not null)
{
Expand All @@ -165,24 +168,21 @@ public class ClassOrInterfaceDeclarationVisitor : BodyDeclarationVisitor<ClassOr
if (childType.isInterface())
{
var childInt = VisitInterfaceDeclaration(context, childType, true);
if (childInt is not null)
{
classSyntax = classSyntax.AddMembers(childInt);
}

classSyntax = classSyntax.AddMembers(childInt);
}
else
{
var childClass = VisitClassDeclaration(context, childType, true);
if (childClass is not null)
{
classSyntax = classSyntax.AddMembers(childClass);
}

classSyntax = classSyntax.AddMembers(childClass);
}
}
else
{
var syntax = VisitBodyDeclarationForClass(context, classSyntax, member, extends, implements);
var withJavaComments = syntax?.WithJavaComments(context, member);

if (withJavaComments != null)
{
classSyntax = classSyntax.AddMembers(withJavaComments);
Expand All @@ -197,7 +197,7 @@ public class ClassOrInterfaceDeclarationVisitor : BodyDeclarationVisitor<ClassOr
}
}

var annotations = javac.getAnnotations().ToList<AnnotationExpr>();
var annotations = classDecl.getAnnotations().ToList<AnnotationExpr>();

if (annotations is { Count: > 0 })
{
Expand All @@ -224,6 +224,6 @@ public class ClassOrInterfaceDeclarationVisitor : BodyDeclarationVisitor<ClassOr
}
}

return classSyntax.WithJavaComments(context, javac);
return classSyntax.WithJavaComments(context, classDecl);
}
}
Loading

0 comments on commit 3379c7d

Please sign in to comment.