Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support protoc Kotlin code generation #44552

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
7 changes: 7 additions & 0 deletions docs/src/main/asciidoc/grpc-generation-reference.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,13 @@ quarkus.generate-code.grpc.scan-for-proto-exclude."<groupId>:<artifactId>"=foo/p

Note that `:` characters in the property keys must be escaped.

== Kotlin code generation

`protoc` also supports https://protobuf.dev/reference/kotlin/kotlin-generated/[generating Kotlin code] in addition to the generated Java code.

By default, the Kotlin code generation is enabled if the dependency `io.quarkus:quarkus-kotlin` is present.
To explicitly en-/disable this feature, set the `quarkus.generate-code.grpc.kotlin.generate` property in your `application.properties` file to `true` or `false`.

== Skipping code generation

You can skip gRPC code generation using:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;

Expand Down Expand Up @@ -66,8 +67,11 @@ public class GrpcCodeGen implements CodeGenProvider {

private static final String USE_ARG_FILE = "quarkus.generate-code.grpc.use-arg-file";

private static final String GENERATE_KOTLIN = "quarkus.generate-code.grpc.kotlin.generate";

private Executables executables;
private String input;
private boolean hasQuarkusKotlinDependency;

@Override
public String providerId() {
Expand Down Expand Up @@ -95,6 +99,7 @@ public Path getInputDirectory() {
@Override
public void init(ApplicationModel model, Map<String, String> properties) {
this.input = properties.get("quarkus.grpc.codegen.proto-directory");
this.hasQuarkusKotlinDependency = containsQuarkusKotlin(model.getDependencies());
}

@Override
Expand Down Expand Up @@ -162,6 +167,10 @@ public boolean trigger(CodeGenContext context) throws CodeGenException {
"--grpc_out=" + outDir,
"--java_out=" + outDir));

if (shouldGenerateKotlin(context.config())) {
command.add("--kotlin_out=" + outDir);
}

if (shouldGenerateDescriptorSet(context.config())) {
command.add(String.format("--descriptor_set_out=%s", getDescriptorSetOutputFile(context)));
}
Expand Down Expand Up @@ -296,6 +305,11 @@ private boolean isGeneratingFromAppDependenciesEnabled(Config config) {
.filter(value -> !"none".equals(value)).isPresent();
}

private boolean shouldGenerateKotlin(Config config) {
return config.getOptionalValue(GENERATE_KOTLIN, Boolean.class).orElse(
hasQuarkusKotlinDependency);
}

private boolean shouldGenerateDescriptorSet(Config config) {
return config.getOptionalValue(GENERATE_DESCRIPTOR_SET, Boolean.class).orElse(FALSE);
}
Expand Down Expand Up @@ -526,6 +540,16 @@ private static void writePluginExeCmd(Path pluginPath, BufferedWriter writer) th
writer.newLine();
}

private static boolean containsQuarkusKotlin(Collection<ResolvedDependency> dependencies) {
return dependencies.stream().anyMatch(new Predicate<ResolvedDependency>() {
@Override
public boolean test(ResolvedDependency rd) {
return rd.getGroupId().equalsIgnoreCase("io.quarkus")
&& rd.getArtifactId().equalsIgnoreCase("quarkus-kotlin");
}
});
}

private static class Executables {

final Path protoc;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@ import jakarta.ws.rs.Produces
import jakarta.ws.rs.core.MediaType

import io.quarkus.example.HelloMsg
import io.quarkus.example.helloMsg

@Path("/hello")
class ExampleResource {

@GET
@Produces(MediaType.TEXT_PLAIN)
fun hello() = "hello" + HelloMsg.Status.TEST_ONE.getNumber()
fun hello() = "hello" + helloMsg { status = HelloMsg.Status.TEST_ONE }.statusValue
}
Loading