From ce9f894f75727c17b3237c3453dacb91d404b32c Mon Sep 17 00:00:00 2001 From: Michael Williamson Date: Tue, 8 Mar 2016 11:22:53 +0000 Subject: Serialize formal type parameters in C# backend --- .../org/zwobble/couscous/ast/ClassNodeBuilder.java | 12 +++++++++-- .../couscous/ast/FormalTypeParameterNode.java | 4 ++++ .../couscous/backends/csharp/CsharpSerializer.java | 15 ++++++++++++++ .../backends/csharp/CsharpSerializerTests.java | 24 ++++++++++++++++++++++ 4 files changed, 53 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/zwobble/couscous/ast/ClassNodeBuilder.java b/src/main/java/org/zwobble/couscous/ast/ClassNodeBuilder.java index 3a1b81b..db14773 100644 --- a/src/main/java/org/zwobble/couscous/ast/ClassNodeBuilder.java +++ b/src/main/java/org/zwobble/couscous/ast/ClassNodeBuilder.java @@ -10,12 +10,14 @@ import java.util.Optional; import java.util.function.Function; import static org.zwobble.couscous.ast.FormalArgumentNode.formalArg; +import static org.zwobble.couscous.ast.FormalTypeParameterNode.formalTypeParameter; import static org.zwobble.couscous.ast.VariableDeclaration.var; import static org.zwobble.couscous.util.ExtraLists.list; public class ClassNodeBuilder { private final TypeName name; private final ImmutableSet.Builder superTypes; + private final ImmutableList.Builder typeParameters; private final ImmutableList.Builder fields; private List staticConstructor; private Optional constructor; @@ -23,6 +25,7 @@ public class ClassNodeBuilder { public ClassNodeBuilder(TypeName name) { this.name = name; + this.typeParameters = ImmutableList.builder(); this.superTypes = ImmutableSet.builder(); this.fields = ImmutableList.builder(); staticConstructor = list(); @@ -34,6 +37,11 @@ public class ClassNodeBuilder { this(TypeName.of(name)); } + public ClassNodeBuilder addTypeParameter(String name) { + this.typeParameters.add(formalTypeParameter(TypeName.of(name))); + return this; + } + public ClassNodeBuilder addSuperType(String type) { this.superTypes.add(TypeName.of(type)); return this; @@ -104,7 +112,7 @@ public class ClassNodeBuilder { public ClassNode build() { return ClassNode.declareClass( name, - list(), + typeParameters.build(), superTypes.build(), fields.build(), staticConstructor, @@ -115,7 +123,7 @@ public class ClassNodeBuilder { public InterfaceNode buildInterface() { return InterfaceNode.declareInterface( name, - list(), + typeParameters.build(), superTypes.build(), methods.build()); } diff --git a/src/main/java/org/zwobble/couscous/ast/FormalTypeParameterNode.java b/src/main/java/org/zwobble/couscous/ast/FormalTypeParameterNode.java index 9de6e5d..b2d7408 100644 --- a/src/main/java/org/zwobble/couscous/ast/FormalTypeParameterNode.java +++ b/src/main/java/org/zwobble/couscous/ast/FormalTypeParameterNode.java @@ -14,6 +14,10 @@ public class FormalTypeParameterNode implements Node { this.name = name; } + public TypeName getName() { + return name; + } + public FormalTypeParameterNode transform(NodeTransformer transformer) { return new FormalTypeParameterNode(transformer.transform(name)); } diff --git a/src/main/java/org/zwobble/couscous/backends/csharp/CsharpSerializer.java b/src/main/java/org/zwobble/couscous/backends/csharp/CsharpSerializer.java index 036ee39..33187a2 100644 --- a/src/main/java/org/zwobble/couscous/backends/csharp/CsharpSerializer.java +++ b/src/main/java/org/zwobble/couscous/backends/csharp/CsharpSerializer.java @@ -337,6 +337,7 @@ public class CsharpSerializer implements NodeVisitor { writer.writeKeyword(keyword); writer.writeSpace(); writer.writeIdentifier(node.getName().getSimpleName()); + writeTypeParameters(node); writeSuperTypes(node); writer.startBlock(); writeBody.run(); @@ -347,6 +348,20 @@ public class CsharpSerializer implements NodeVisitor { }); } + private void writeTypeParameters(TypeNode node) { + if (!node.getTypeParameters().isEmpty()) { + writer.writeSymbol("<"); + writer.writeWithSeparator( + node.getTypeParameters(), + parameter -> writeTypeReference(parameter.getName()), + () -> { + writer.writeSymbol(","); + writer.writeSpace(); + }); + writer.writeSymbol(">"); + } + } + private void writeSuperTypes(TypeNode node) { if (!node.getSuperTypes().isEmpty()) { writer.writeSpace(); diff --git a/src/test/java/org/zwobble/couscous/tests/backends/csharp/CsharpSerializerTests.java b/src/test/java/org/zwobble/couscous/tests/backends/csharp/CsharpSerializerTests.java index 4964113..493ba2b 100644 --- a/src/test/java/org/zwobble/couscous/tests/backends/csharp/CsharpSerializerTests.java +++ b/src/test/java/org/zwobble/couscous/tests/backends/csharp/CsharpSerializerTests.java @@ -263,6 +263,18 @@ public class CsharpSerializerTests { assertEquals("namespace com.example {\n internal class Example {\n }\n}\n", output); } + @Test + public void classWithTypeParameters() { + ClassNode classNode = ClassNode.builder("com.example.Example") + .addTypeParameter("T") + .addTypeParameter("U") + .build(); + + String output = serialize(classNode); + + assertEquals("namespace com.example {\n internal class Example {\n }\n}\n", output); + } + @Test public void classWithSuperTypes() { ClassNode classNode = ClassNode.builder("com.example.Example") @@ -322,6 +334,18 @@ public class CsharpSerializerTests { assertEquals("namespace com.example {\n internal interface Example {\n }\n}\n", output); } + @Test + public void interfaceWithTypeParameters() { + Node node = new ClassNodeBuilder(TypeName.of("com.example.Example")) + .addTypeParameter("T") + .addTypeParameter("U") + .buildInterface(); + + String output = serialize(node); + + assertEquals("namespace com.example {\n internal interface Example {\n }\n}\n", output); + } + @Test public void interfaceWithSuperTypes() { Node node = new ClassNodeBuilder(TypeName.of("com.example.Example")) -- cgit v1.2.3