Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion JavaToCSharp.Tests/CommentTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ public class Foo
[InlineData("Child extends Parent implements IParent", "Child : Parent, IParent")]

[InlineData("Parent<T>", "Parent<T>")]
[InlineData("Child<T extends BoundType<T>>", "Child<T>")] // issue #125, should add: where T : BoundType<T>
[InlineData("Child<T extends BoundType<T>>", "Child<T>\n where T : BoundType<T>")]
[InlineData("Child extends Parent<BoundType>", "Child : Parent<BoundType>")]
public void CommentsInsideClass_ShouldNotBeDuplicated_Fix_88(string javaClass, string csharpClass)
{
Expand Down
31 changes: 31 additions & 0 deletions JavaToCSharp.Tests/ConvertTypeTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -113,4 +113,35 @@ public void ConvertTypeSyntax_GivenMismatchedRank_ShouldThrowException()

Assert.Throws<ArgumentException>(() => TypeHelper.ConvertTypeSyntax(type, 1));
}

[Theory]
[InlineData("GenericClass<T>", "GenericClass<T>")]
[InlineData("GenericClass<T extends BoundType<T>>", "GenericClass<T>\n where T : BoundType<T>")]
[InlineData("GenericClass<T extends BoundType>", "GenericClass<T>\n where T : BoundType")]

[InlineData("GenericClass<T, U>", "GenericClass<T, U>")]
[InlineData("GenericClass<T, U extends BoundType<U>>", "GenericClass<T, U>\n where U : BoundType<U>")]
[InlineData("GenericClass<T extends BoundType1<T>, U extends BoundType2<U>>", "GenericClass<T, U>\n where T : BoundType1<T> where U : BoundType2<U>")]

[InlineData("GenericClass<T extends BoundType1<T> & BoundType2<T>>", "GenericClass<T>\n where T : BoundType1<T>, BoundType2<T>")]
public void ConvertClassTypeBoundedParameters(string javaClass, string csharpClass)
{
string javaCode = $$"""
public class {{javaClass}} { }
""";
var options = new JavaConversionOptions
{
IncludeUsings = false,
IncludeNamespace = false,
};
var parsed = JavaToCSharpConverter.ConvertText(javaCode, options) ?? "";
string expected = $$"""
public class {{csharpClass}}
{
}

""";

Assert.Equal(expected.ReplaceLineEndings(), parsed.ReplaceLineEndings());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ public static ClassDeclarationSyntax VisitClassDeclaration(ConversionContext con
{
classSyntax = classSyntax.AddTypeParameterListParameters(typeParams
.Select(i => SyntaxFactory.TypeParameter(i.getNameAsString())).ToArray());
classSyntax = classSyntax.AddConstraintClauses(TypeHelper.GetTypeParameterListConstraints(typeParams).ToArray());
}

var mods = classDecl.getModifiers().ToModifierKeywordSet();
Expand Down
25 changes: 25 additions & 0 deletions JavaToCSharp/TypeHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,31 @@ private static SeparatedSyntaxList<ArgumentSyntax> GetSeparatedListFromArguments
return SyntaxFactory.SeparatedList(argSyntaxes, separators);
}

/// <summary>
/// Returns the list of C# type parameter constraints that must be added to a class syntax
/// to convert the java bounded type parameters of a class declaration.
/// e.g. to convert <![CDATA[ <T extends Clazz<T>> ]]> into <![CDATA[ <T> where T : Clazz<T> ]]>
/// </summary>
public static IEnumerable<TypeParameterConstraintClauseSyntax> GetTypeParameterListConstraints(List<TypeParameter> typeParams)
{
var typeParameterConstraints = new List<TypeParameterConstraintClauseSyntax>();
foreach (TypeParameter typeParam in typeParams)
{
if (typeParam.getTypeBound().size() > 0)
{
var typeConstraintsSyntax = new SeparatedSyntaxList<TypeParameterConstraintSyntax>();
foreach (ClassOrInterfaceType bound in typeParam.getTypeBound())
typeConstraintsSyntax = typeConstraintsSyntax.Add(SyntaxFactory.TypeConstraint(SyntaxFactory.ParseTypeName(bound.asString())));

var typeIdentifier = SyntaxFactory.IdentifierName(typeParam.getName().asString());
var parameterConstraintClauseSyntax = SyntaxFactory.TypeParameterConstraintClause(typeIdentifier, typeConstraintsSyntax);

typeParameterConstraints.Add(parameterConstraintClauseSyntax);
}
}
return typeParameterConstraints;
}

/// <summary>
/// Transforms method calls into property and indexer accesses where appropriate.
/// </summary>
Expand Down
Loading