From aa596d20e0a54e642de8b65d2c95549ab743029e Mon Sep 17 00:00:00 2001 From: Dmitrii Duzhinskii Date: Fri, 29 Sep 2023 13:43:24 +0300 Subject: [PATCH] Better method decomposition for client generator --- .../client/ApiMethodGeneratorBase.java | 78 ++++++++++++------- .../client/StubCallMethodGenerator.java | 39 +++++----- .../OverriddenServiceMethodGenerator.java | 2 +- 3 files changed, 73 insertions(+), 46 deletions(-) diff --git a/generator/src/main/java/org/sudu/protogen/generator/client/ApiMethodGeneratorBase.java b/generator/src/main/java/org/sudu/protogen/generator/client/ApiMethodGeneratorBase.java index 8a51adb..017230d 100644 --- a/generator/src/main/java/org/sudu/protogen/generator/client/ApiMethodGeneratorBase.java +++ b/generator/src/main/java/org/sudu/protogen/generator/client/ApiMethodGeneratorBase.java @@ -1,6 +1,7 @@ package org.sudu.protogen.generator.client; import com.squareup.javapoet.*; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.sudu.protogen.EmptyIfNotFound; import org.sudu.protogen.NullifyIfNotFound; @@ -14,6 +15,7 @@ import protogen.Options; import java.util.List; +import java.util.Objects; public class ApiMethodGeneratorBase { @@ -68,36 +70,58 @@ private List params() { } private CodeBlock body(List params) { - CodeBlock returnExpr = CodeBlock.of(""); - CodeBlock body = CodeBlock.of(""); + CodeBlock returnExpr = CodeBlock.of("$LStubCall(grpcRequest)", method.generatedName()); + if (returnType.getTypeName() != TypeName.VOID) { + returnExpr = CodeBlock.of("return $L", returnExpr); + } + return CodeBlock.builder().add(buildRequest(params)).addStatement(returnExpr).build(); + } + + private CodeBlock buildRequest(List params) { ClassName requestProtoType = method.getInputType().getProtobufTypeName(); - if (requestType != null && !method.doUnfoldRequest()) { - body = CodeBlock.builder().addStatement("$T grpcRequest = $L", requestProtoType, requestType.toGrpcTransformer(CodeBlock.of("request"))).build(); - } else { - if (requestType != null) { - ClassName inputType = method.getInputType().getDomainTypeName(context.configuration().namingManager()); - - List paramsBlocks = params.stream().map(p -> CodeBlock.of("$N", p)).toList(); - CodeBlock paramsAsList = Poem.separatedSequence(paramsBlocks, ",$W"); - body = CodeBlock.builder() - .addStatement("$T grpcRequest = new $T($L).toGrpc()", requestProtoType, inputType, paramsAsList) - .build(); + if (requestType != null) { + if (!method.doUnfoldRequest()) { + return buildDomainRequest(requestProtoType); } else { - List processedFields = method.getInputType().getFields().stream() - .map(field -> new FieldGenerator(context, field).generate()) - .filter(FieldProcessingResult::isNonVoid) - .toList(); - CodeBlock builder = new ToGrpcMethodGenerator(context, requestProtoType, processedFields, false).builder("requestBuilder"); - body = CodeBlock.builder() - .add(builder) - .addStatement("$T grpcRequest = requestBuilder.build()", requestProtoType) - .build(); + return buildUnfoldedDomainRequest(params, requestProtoType); } + } else { + return buildNonDomainRequest(requestProtoType); } - returnExpr = CodeBlock.of("$LStubCall(grpcRequest)", method.generatedName()); - if (returnType.getTypeName() != TypeName.VOID) { - returnExpr = CodeBlock.of("return $L", returnExpr); - } - return CodeBlock.builder().add(body).addStatement(returnExpr).build(); + } + + @NotNull + private CodeBlock buildNonDomainRequest(ClassName requestProtoType) { + List processedFields = method.getInputType().getFields().stream() + .map(field -> new FieldGenerator(context, field).generate()) + .filter(FieldProcessingResult::isNonVoid) + .toList(); + CodeBlock builder = new ToGrpcMethodGenerator(context, requestProtoType, processedFields, false).builder("requestBuilder"); + return CodeBlock.builder() + .add(builder) + .addStatement("$T grpcRequest = requestBuilder.build()", requestProtoType) + .build(); + } + + @NotNull + private CodeBlock buildUnfoldedDomainRequest(List params, ClassName requestProtoType) { + ClassName inputType = method.getInputType().getDomainTypeName(context.configuration().namingManager()); + + List paramsBlocks = params.stream().map(p -> CodeBlock.of("$N", p)).toList(); + CodeBlock paramsAsList = Poem.separatedSequence(paramsBlocks, ",$W"); + return CodeBlock.of("$T grpcRequest = $L;\n", + requestProtoType, + Objects.requireNonNull(requestType).toGrpcTransformer( + CodeBlock.of("new $T($L)", inputType, paramsAsList) + ) + ); + } + + @NotNull + private CodeBlock buildDomainRequest(ClassName requestProtoType) { + return CodeBlock.of("$T grpcRequest = $L;\n", + requestProtoType, + Objects.requireNonNull(requestType).toGrpcTransformer(CodeBlock.of("request")) + ); } } diff --git a/generator/src/main/java/org/sudu/protogen/generator/client/StubCallMethodGenerator.java b/generator/src/main/java/org/sudu/protogen/generator/client/StubCallMethodGenerator.java index 6febbef..3ffb90e 100644 --- a/generator/src/main/java/org/sudu/protogen/generator/client/StubCallMethodGenerator.java +++ b/generator/src/main/java/org/sudu/protogen/generator/client/StubCallMethodGenerator.java @@ -1,6 +1,7 @@ package org.sudu.protogen.generator.client; import com.squareup.javapoet.*; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.sudu.protogen.descriptors.Method; import org.sudu.protogen.descriptors.RepeatedContainer; @@ -36,7 +37,7 @@ public MethodSpec generate() { return MethodSpec.methodBuilder(method.generatedName() + "StubCall") .addModifiers(Modifier.PRIVATE) .addParameters(parameters()) - .addCode(new BodyGenerator().withIfNotFound().get()) + .addCode(new BodyGenerator().get()) .returns(returnType.getTypeName()) .addAnnotation( method.ifNotFoundBehavior() == NULLIFY @@ -50,10 +51,15 @@ private class BodyGenerator implements Supplier { @Override public CodeBlock get() { + return new IfNotFoundDecorator(getStrategy()).get(); + } + + @NotNull + private BodyGenerator getStrategy() { if (method.isOutputStreaming()) { - return new StreamingBodyGenerator().get(); + return new StreamingBodyGenerator(); } else { - return new CommonBodyGenerator().get(); + return new CommonBodyGenerator(); } } @@ -64,7 +70,7 @@ public CodeBlock get() { if (returnType.getTypeName() != TypeName.VOID) { returnExpr = CodeBlock.of("return $L", returnType.fromGrpcTransformer(returnExpr)); } - return CodeBlock.builder().addStatement(returnExpr).build(); + return returnExpr.toBuilder().add(";").build(); } } @@ -73,25 +79,22 @@ private class StreamingBodyGenerator extends BodyGenerator { @Override public CodeBlock get() { if (!(returnType instanceof RepeatedType repType)) throw new IllegalArgumentException(); - CodeBlock body = CodeBlock.of("var iterator = $N.$L(request);\n", stubField, method.getName()); // I write mapping here manually because input is always an Iterator and output is specified by the RepeatedContainer option // So RepeatedType.fromGrpcTransformer is not suitable because it does only T <--> T mappings - CodeBlock mappingExpr = CodeBlock.of("i -> $L", repType.getElementModel().fromGrpcTransformer(CodeBlock.of("i"))); - return CodeBlock.builder() - .add(body) - .addStatement("return $L\n.map($L)$L", - RepeatedContainer.ITERATOR.getToStreamExpr(CodeBlock.of("iterator")), - mappingExpr, - repType.getRepeatedType().getCollectorExpr() - ) - .build(); + return CodeBlock.of(""" + var iterator = $N.$L(request); + return $L + $>.map(i -> $L)$L;$< + """, + stubField, + method.getName(), + RepeatedContainer.ITERATOR.getToStreamExpr(CodeBlock.of("iterator")), + repType.getElementModel().fromGrpcTransformer(CodeBlock.of("i")), + repType.getRepeatedType().getCollectorExpr() + ); } } - private BodyGenerator withIfNotFound() { - return new IfNotFoundDecorator(this); - } - private class IfNotFoundDecorator extends BodyGenerator { private final BodyGenerator generator; diff --git a/generator/src/main/java/org/sudu/protogen/generator/server/OverriddenServiceMethodGenerator.java b/generator/src/main/java/org/sudu/protogen/generator/server/OverriddenServiceMethodGenerator.java index 28c82d6..5a3519a 100644 --- a/generator/src/main/java/org/sudu/protogen/generator/server/OverriddenServiceMethodGenerator.java +++ b/generator/src/main/java/org/sudu/protogen/generator/server/OverriddenServiceMethodGenerator.java @@ -61,7 +61,7 @@ private TypeModel responseTypeModel() { private CodeBlock generateBody() { return CodeBlock.of(""" try { - $L + $>$L$< } catch (Throwable $$t) { responseObserver.onError($$t); } finally { responseObserver.onCompleted(); } """, generateAbstractMethodCall());