Skip to content

Commit 5183369

Browse files
authored
Fix issues with array type conversion, #98 (#101)
1 parent 167623f commit 5183369

12 files changed

+288
-92
lines changed

JavaToCSharp.Tests/ConvertTypeTests.cs

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
using com.github.javaparser.ast.type;
2+
13
namespace JavaToCSharp.Tests;
24

35
public class ConvertTypeTests
@@ -43,4 +45,72 @@ public void ConvertType_WithGenericWildcard_ShouldReplaceToken()
4345
{
4446
Assert.Equal("MyType<TWildcardTodo>", TypeHelper.ConvertType("MyType<?>"));
4547
}
48+
49+
[Fact]
50+
public void ConvertTypeSyntax_GivenNonArrayType_ShouldReturnCorrectSyntax()
51+
{
52+
var type = new PrimitiveType(PrimitiveType.Primitive.INT);
53+
54+
var syntax = TypeHelper.ConvertTypeSyntax(type, 0);
55+
56+
Assert.Equal("int", syntax.ToString());
57+
}
58+
59+
[Fact]
60+
public void ConvertTypeSyntax_GivenNonArrayTypeWithRank_ShouldReturnCorrectSyntax()
61+
{
62+
var type = new PrimitiveType(PrimitiveType.Primitive.INT);
63+
64+
var syntax = TypeHelper.ConvertTypeSyntax(type, 1);
65+
66+
Assert.Equal("int[]", syntax.ToString());
67+
}
68+
69+
[Fact]
70+
public void ConvertTypeSyntax_GivenNonArrayTypeWithMultidimensionalRank_ShouldReturnCorrectSyntax()
71+
{
72+
var type = new PrimitiveType(PrimitiveType.Primitive.INT);
73+
74+
var syntax = TypeHelper.ConvertTypeSyntax(type, 2);
75+
76+
Assert.Equal("int[,]", syntax.ToString());
77+
}
78+
79+
[Fact]
80+
public void ConvertTypeSyntax_GivenArrayTypeWithoutRank_ShouldReturnCorrectSyntax()
81+
{
82+
var type = new ArrayType(new PrimitiveType(PrimitiveType.Primitive.INT));
83+
84+
var syntax = TypeHelper.ConvertTypeSyntax(type, 0);
85+
86+
Assert.Equal("int[]", syntax.ToString());
87+
}
88+
89+
[Fact]
90+
public void ConvertTypeSyntax_GivenArrayTypeWithRank_ShouldReturnCorrectSyntax()
91+
{
92+
var type = new ArrayType(new PrimitiveType(PrimitiveType.Primitive.INT));
93+
94+
var syntax = TypeHelper.ConvertTypeSyntax(type, 1);
95+
96+
Assert.Equal("int[]", syntax.ToString());
97+
}
98+
99+
[Fact]
100+
public void ConvertTypeSyntax_GivenArrayTypeWithMultidimensionalRank_ShouldReturnCorrectSyntax()
101+
{
102+
var type = new ArrayType(new ArrayType(new PrimitiveType(PrimitiveType.Primitive.INT)));
103+
104+
var syntax = TypeHelper.ConvertTypeSyntax(type, 2);
105+
106+
Assert.Equal("int[,]", syntax.ToString());
107+
}
108+
109+
[Fact]
110+
public void ConvertTypeSyntax_GivenMismatchedRank_ShouldThrowException()
111+
{
112+
var type = new ArrayType(new ArrayType(new PrimitiveType(PrimitiveType.Primitive.INT)));
113+
114+
Assert.Throws<ArgumentException>(() => TypeHelper.ConvertTypeSyntax(type, 1));
115+
}
46116
}

JavaToCSharp.Tests/IntegrationTests.cs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,21 @@ public class IntegrationTests
1919
[InlineData("Resources/TestNumericDocValuesUpdates.java")]
2020
[InlineData("Resources/Java9DiamondOperatorInnerClass.java")]
2121
[InlineData("Resources/Java11LambdaInference.java")]
22-
public void GeneralSuccessfulConversionTest(string filePath)
22+
[InlineData("Resources/MultidimensionalArrays.java", true)]
23+
public void GeneralSuccessfulConversionTest(string filePath, bool allowWarnings = false)
2324
{
2425
var options = new JavaConversionOptions
2526
{
2627
IncludeComments = false,
2728
};
2829

29-
options.WarningEncountered += (_, eventArgs)
30-
=> throw new InvalidOperationException($"Encountered a warning in conversion: {eventArgs.Message}");
30+
options.WarningEncountered += (_, eventArgs) =>
31+
{
32+
if (!allowWarnings)
33+
{
34+
throw new InvalidOperationException($"Encountered a warning in conversion: {eventArgs.Message}");
35+
}
36+
};
3137

3238
var parsed = JavaToCSharpConverter.ConvertText(File.ReadAllText(filePath), options);
3339
Assert.NotNull(parsed);
@@ -59,6 +65,7 @@ public void GeneralUnsuccessfulConversionTest(string filePath)
5965
[InlineData("Resources/NewArrayLiteralBug.java")]
6066
[InlineData("Resources/OctalLiteralBug.java")]
6167
[InlineData("Resources/DeprecatedAnnotation.java")]
68+
[InlineData("Resources/BooleanArrays.java")]
6269
public void FullIntegrationTests(string filePath)
6370
{
6471
var options = new JavaConversionOptions
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/// Expect:
2+
/// - output: "2\n"
3+
package example;
4+
5+
// see issue #98
6+
public class Program {
7+
static boolean[] myBooleans = new boolean[] { true, false, true, false };
8+
public static void main(String[] args) {
9+
int trueCount = 0;
10+
for (boolean b : myBooleans) {
11+
if (b) {
12+
trueCount++;
13+
}
14+
}
15+
System.out.println(trueCount);
16+
}
17+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// NOTE: this test case only parses and converts successfully, it does not yet work.
2+
// The multidimensional array indexers do not translate to the correct syntax.
3+
package example;
4+
5+
public class Program {
6+
private static int[][] multiField = new int[2][2];
7+
private static int[] singleField = new int[2];
8+
9+
static {
10+
multiField[0][0] = 10;
11+
multiField[0][1] = 20;
12+
multiField[1][0] = 30;
13+
multiField[1][1] = 40;
14+
15+
singleField[0] = 11;
16+
singleField[1] = 21;
17+
}
18+
19+
public static void main(String[] args) {
20+
int multi[][] = new int[2][2];
21+
int single[] = new int[2];
22+
23+
multi[0][0] = 1;
24+
multi[0][1] = 2;
25+
multi[1][0] = 3;
26+
multi[1][1] = 4;
27+
28+
System.out.println(multi[0][0]);
29+
System.out.println(multi[0][1]);
30+
System.out.println(multi[1][0]);
31+
System.out.println(multi[1][1]);
32+
33+
single[0] = 1;
34+
single[1] = 2;
35+
36+
System.out.println(single[0]);
37+
System.out.println(single[1]);
38+
39+
System.out.println(multiField[0][0]);
40+
System.out.println(multiField[0][1]);
41+
System.out.println(multiField[1][0]);
42+
System.out.println(multiField[1][1]);
43+
44+
System.out.println(singleField[0]);
45+
System.out.println(singleField[1]);
46+
}
47+
}

JavaToCSharp.sln

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
2121
EndProject
2222
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JavaToCSharp.Tests", "JavaToCSharp.Tests\JavaToCSharp.Tests.csproj", "{0CBBEF05-FD79-474A-A5F0-25B341B8B77D}"
2323
EndProject
24-
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{DE56E074-10C7-47BA-8E8A-DAB0F3F92181}"
25-
EndProject
2624
Global
2725
GlobalSection(SolutionConfigurationPlatforms) = preSolution
2826
Debug|Any CPU = Debug|Any CPU
@@ -50,7 +48,6 @@ Global
5048
HideSolutionNode = FALSE
5149
EndGlobalSection
5250
GlobalSection(NestedProjects) = preSolution
53-
{0CBBEF05-FD79-474A-A5F0-25B341B8B77D} = {DE56E074-10C7-47BA-8E8A-DAB0F3F92181}
5451
EndGlobalSection
5552
GlobalSection(ExtensibilityGlobals) = postSolution
5653
SolutionGuid = {EB538484-5025-4753-B0A5-2C66A6C06193}

JavaToCSharp/Declarations/ConstructorDeclarationVisitor.cs

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
1-
using System;
2-
using System.Collections.Generic;
3-
using System.Linq;
4-
using com.github.javaparser.ast;
1+
using com.github.javaparser.ast;
52
using com.github.javaparser.ast.body;
63
using com.github.javaparser.ast.stmt;
74
using com.github.javaparser.ast.type;
@@ -26,7 +23,7 @@ public class ConstructorDeclarationVisitor : BodyDeclarationVisitor<ConstructorD
2623
{
2724
return null;
2825
}
29-
26+
3027
var ctorSyntax = SyntaxFactory.ConstructorDeclaration(identifier)
3128
.WithLeadingTrivia(SyntaxFactory.CarriageReturnLineFeed);
3229

@@ -52,7 +49,7 @@ public class ConstructorDeclarationVisitor : BodyDeclarationVisitor<ConstructorD
5249

5350
if (param.isVarArgs())
5451
{
55-
paramSyntax = paramSyntax.WithType(SyntaxFactory.ParseTypeName(TypeHelper.ConvertTypeOf(param) + "[]"))
52+
paramSyntax = paramSyntax.WithType(TypeHelper.ConvertArrayTypeSyntax(param.getType(), 1))
5653
.WithModifiers(SyntaxFactory.TokenList(SyntaxFactory.Token(SyntaxKind.ParamsKeyword)));
5754
}
5855
else
@@ -65,7 +62,7 @@ public class ConstructorDeclarationVisitor : BodyDeclarationVisitor<ConstructorD
6562

6663
ctorSyntax = ctorSyntax.AddParameterListParameters(paramSyntaxes.ToArray());
6764
}
68-
65+
6966
var block = ctorDecl.getBody();
7067
var statements = block.getStatements().ToList<Statement>();
7168

@@ -82,8 +79,8 @@ public class ConstructorDeclarationVisitor : BodyDeclarationVisitor<ConstructorD
8279
argsSyntax = TypeHelper.GetSyntaxFromArguments(context, initArgs);
8380
}
8481

85-
var constructorInitSyntax = SyntaxFactory.ConstructorInitializer(ctorInvStmt.isThis()
86-
? SyntaxKind.ThisConstructorInitializer
82+
var constructorInitSyntax = SyntaxFactory.ConstructorInitializer(ctorInvStmt.isThis()
83+
? SyntaxKind.ThisConstructorInitializer
8784
: SyntaxKind.BaseConstructorInitializer, argsSyntax);
8885

8986
ctorSyntax = ctorSyntax.WithInitializer(constructorInitSyntax);

JavaToCSharp/Declarations/FieldDeclarationVisitor.cs

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
1-
using System.Collections.Generic;
2-
using System.Linq;
3-
using com.github.javaparser.ast;
1+
using com.github.javaparser.ast;
42
using com.github.javaparser.ast.body;
53
using com.github.javaparser.ast.expr;
64
using com.github.javaparser.ast.type;
7-
using com.sun.org.apache.bcel.@internal.classfile;
85
using JavaToCSharp.Expressions;
96
using Microsoft.CodeAnalysis.CSharp;
107
using Microsoft.CodeAnalysis.CSharp.Syntax;
@@ -14,35 +11,46 @@ namespace JavaToCSharp.Declarations;
1411
public class FieldDeclarationVisitor : BodyDeclarationVisitor<FieldDeclaration>
1512
{
1613
public override MemberDeclarationSyntax VisitForClass(
17-
ConversionContext context,
18-
ClassDeclarationSyntax? classSyntax,
14+
ConversionContext context,
15+
ClassDeclarationSyntax? classSyntax,
1916
FieldDeclaration fieldDecl,
2017
IReadOnlyList<ClassOrInterfaceType> extends,
2118
IReadOnlyList<ClassOrInterfaceType> implements)
2219
{
2320
var variables = new List<VariableDeclaratorSyntax>();
2421

25-
string typeName = fieldDecl.getCommonType().toString();
22+
var commonType = fieldDecl.getCommonType();
23+
int? arrayRank = null;
24+
25+
var variableDeclarators = fieldDecl.getVariables()?.ToList<VariableDeclarator>() ?? [];
2626

27-
var variableDeclarators = fieldDecl.getVariables()?.ToList<VariableDeclarator>() ?? new List<VariableDeclarator>();
2827
foreach (var item in variableDeclarators)
2928
{
3029
var type = item.getType();
30+
31+
if (arrayRank is not null && type.getArrayLevel() != arrayRank)
32+
{
33+
throw new InvalidOperationException("Different array levels in the same field declaration are not yet supported");
34+
}
35+
36+
arrayRank ??= type.getArrayLevel();
37+
3138
string name = item.getNameAsString();
3239

3340
if (type.getArrayLevel() > 0)
3441
{
35-
if (!typeName.EndsWith("[]"))
36-
typeName += "[]";
37-
if (name.EndsWith("[]"))
42+
while (name.EndsWith("[]"))
43+
{
3844
name = name[..^2];
45+
}
3946
}
4047

4148
var initExpr = item.getInitializer().FromOptional<Expression>();
4249

4350
if (initExpr != null)
4451
{
4552
var initSyntax = ExpressionVisitor.VisitExpression(context, initExpr);
53+
4654
if (initSyntax is not null)
4755
{
4856
var varDeclarationSyntax = SyntaxFactory.VariableDeclarator(name).WithInitializer(SyntaxFactory.EqualsValueClause(initSyntax));
@@ -53,11 +61,11 @@ public override MemberDeclarationSyntax VisitForClass(
5361
variables.Add(SyntaxFactory.VariableDeclarator(name));
5462
}
5563

56-
typeName = TypeHelper.ConvertType(typeName);
64+
var typeSyntax = TypeHelper.ConvertTypeSyntax(commonType, arrayRank ?? 0);
5765

5866
var fieldSyntax = SyntaxFactory.FieldDeclaration(
5967
SyntaxFactory.VariableDeclaration(
60-
SyntaxFactory.ParseTypeName(typeName),
68+
typeSyntax,
6169
SyntaxFactory.SeparatedList(variables, Enumerable.Repeat(SyntaxFactory.Token(SyntaxKind.CommaToken), variables.Count - 1))));
6270

6371
var mods = fieldDecl.getModifiers().ToModifierKeywordSet();

0 commit comments

Comments
 (0)