Skip to content

Commit ee8dccf

Browse files
committed
Convert class bounded type parameters, close #125
1 parent ebc6002 commit ee8dccf

File tree

3 files changed

+57
-0
lines changed

3 files changed

+57
-0
lines changed

JavaToCSharp.Tests/ConvertTypeTests.cs

+31
Original file line numberDiff line numberDiff line change
@@ -113,4 +113,35 @@ public void ConvertTypeSyntax_GivenMismatchedRank_ShouldThrowException()
113113

114114
Assert.Throws<ArgumentException>(() => TypeHelper.ConvertTypeSyntax(type, 1));
115115
}
116+
117+
[Theory]
118+
[InlineData("GenericClass<T>", "GenericClass<T>")]
119+
[InlineData("GenericClass<T extends BoundType<T>>", "GenericClass<T>\n where T : BoundType<T>")]
120+
[InlineData("GenericClass<T extends BoundType>", "GenericClass<T>\n where T : BoundType")]
121+
122+
[InlineData("GenericClass<T, U>", "GenericClass<T, U>")]
123+
[InlineData("GenericClass<T, U extends BoundType<U>>", "GenericClass<T, U>\n where U : BoundType<U>")]
124+
[InlineData("GenericClass<T extends BoundType1<T>, U extends BoundType2<U>>", "GenericClass<T, U>\n where T : BoundType1<T> where U : BoundType2<U>")]
125+
126+
[InlineData("GenericClass<T extends BoundType1<T> & BoundType2<T>>", "GenericClass<T>\n where T : BoundType1<T>, BoundType2<T>")]
127+
public void ConvertClassTypeBoundedParameters(string javaClass, string csharpClass)
128+
{
129+
string javaCode = $$"""
130+
public class {{javaClass}} { }
131+
""";
132+
var options = new JavaConversionOptions
133+
{
134+
IncludeUsings = false,
135+
IncludeNamespace = false,
136+
};
137+
var parsed = JavaToCSharpConverter.ConvertText(javaCode, options) ?? "";
138+
string expected = $$"""
139+
public class {{csharpClass}}
140+
{
141+
}
142+
143+
""";
144+
145+
Assert.Equal(expected.ReplaceLineEndings(), parsed.ReplaceLineEndings());
146+
}
116147
}

JavaToCSharp/Declarations/ClassOrInterfaceDeclarationVisitor.cs

+1
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ public static ClassDeclarationSyntax VisitClassDeclaration(ConversionContext con
128128
{
129129
classSyntax = classSyntax.AddTypeParameterListParameters(typeParams
130130
.Select(i => SyntaxFactory.TypeParameter(i.getNameAsString())).ToArray());
131+
classSyntax = classSyntax.AddConstraintClauses(TypeHelper.GetTypeParameterListConstraints(typeParams).ToArray());
131132
}
132133

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

JavaToCSharp/TypeHelper.cs

+25
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,31 @@ private static SeparatedSyntaxList<ArgumentSyntax> GetSeparatedListFromArguments
194194
return SyntaxFactory.SeparatedList(argSyntaxes, separators);
195195
}
196196

197+
/// <summary>
198+
/// Returns the list of C# type parameter constraints that must be added to a class syntax
199+
/// to convert the java bounded type parameters of a class declaration.
200+
/// e.g. to convert <![CDATA[ <T extends Clazz<T>> ]]> into <![CDATA[ <T> where T : Clazz<T> ]]>
201+
/// </summary>
202+
public static IEnumerable<TypeParameterConstraintClauseSyntax> GetTypeParameterListConstraints(List<TypeParameter> typeParams)
203+
{
204+
var typeParameterConstraints = new List<TypeParameterConstraintClauseSyntax>();
205+
foreach (TypeParameter typeParam in typeParams)
206+
{
207+
if (typeParam.getTypeBound().size() > 0)
208+
{
209+
var typeConstraintsSyntax = new SeparatedSyntaxList<TypeParameterConstraintSyntax>();
210+
foreach (ClassOrInterfaceType bound in typeParam.getTypeBound())
211+
typeConstraintsSyntax = typeConstraintsSyntax.Add(SyntaxFactory.TypeConstraint(SyntaxFactory.ParseTypeName(bound.asString())));
212+
213+
var typeIdentifier = SyntaxFactory.IdentifierName(typeParam.getName().asString());
214+
var parameterConstraintClauseSyntax = SyntaxFactory.TypeParameterConstraintClause(typeIdentifier, typeConstraintsSyntax);
215+
216+
typeParameterConstraints.Add(parameterConstraintClauseSyntax);
217+
}
218+
}
219+
return typeParameterConstraints;
220+
}
221+
197222
/// <summary>
198223
/// Transforms method calls into property and indexer accesses where appropriate.
199224
/// </summary>

0 commit comments

Comments
 (0)