package org.zwobble.couscous.ast; import java.util.Optional; import java.util.function.Function; import com.google.common.collect.ImmutableList; public class ClassNodeBuilder { private final TypeName name; private final ImmutableList.Builder fields; private Optional constructor; private final ImmutableList.Builder methods; public ClassNodeBuilder(String name) { this.name = TypeName.of(name); this.fields = ImmutableList.builder(); this.constructor = Optional.empty(); this.methods = ImmutableList.builder(); } public ClassNodeBuilder field(String name, TypeName type) { this.fields.add(FieldDeclarationNode.field(name, type)); return this; } public ClassNodeBuilder constructor(Function build) { this.constructor = Optional.of(build.apply(new ConstructorBuilder()).build()); return this; } public ClassNodeBuilder method(MethodNode method) { this.methods.add(method); return this; } public ClassNodeBuilder method(String name, Function build) { this.methods.add(build.apply(new MethodBuilder(name)).build()); return this; } public ClassNode build() { return new ClassNode( name, constructor.orElse(new ConstructorBuilder().build()), methods.build()); } public class ConstructorBuilder { private final ImmutableList.Builder arguments; private final ImmutableList.Builder statements; public ConstructorBuilder() { this.arguments = ImmutableList.builder(); this.statements = ImmutableList.builder(); } public ThisReferenceNode thisReference() { return ThisReferenceNode.thisReference(name); } public ConstructorBuilder argument(FormalArgumentNode argument) { arguments.add(argument); return this; } public ConstructorBuilder statement(StatementNode statement) { statements.add(statement); return this; } public ConstructorNode build() { return ConstructorNode.constructor( arguments.build(), statements.build()); } } public class MethodBuilder { private final String methodName; private final ImmutableList.Builder statements; public MethodBuilder(String name) { this.methodName = name; this.statements = ImmutableList.builder(); } public ThisReferenceNode thisReference() { return ThisReferenceNode.thisReference(name); } public MethodBuilder statement(StatementNode statement) { statements.add(statement); return this; } public MethodNode build() { return MethodNode.builder() .name(methodName) .body(statements.build()) .build(); } } }