Skip to content

Commit

Permalink
support ScalaPB package/file-level customization
Browse files Browse the repository at this point in the history
  • Loading branch information
github-brice-jaglin committed Feb 1, 2021
1 parent 3dd9873 commit 7c46a20
Show file tree
Hide file tree
Showing 10 changed files with 96 additions and 5 deletions.
11 changes: 9 additions & 2 deletions codegen/src/main/scala/akka/grpc/gen/CodeGenerator.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

package akka.grpc.gen

import com.github.ghik.silencer.silent
import com.google.protobuf.ExtensionRegistry
import com.google.protobuf.compiler.PluginProtos.CodeGeneratorRequest
import com.google.protobuf.compiler.PluginProtos.CodeGeneratorResponse
import protocbridge.Artifact
Expand All @@ -22,8 +24,13 @@ trait CodeGenerator {
/** Takes Scala binary version and returns suggested dependency Seq */
def suggestedDependencies: ScalaBinaryVersion => Seq[Artifact]

final def run(request: Array[Byte], logger: Logger): Array[Byte] =
run(CodeGeneratorRequest.parseFrom(request), logger: Logger).toByteArray
def registerExtensions(@silent("never used") registry: ExtensionRegistry): Unit = {}

final def run(request: Array[Byte], logger: Logger): Array[Byte] = {
val registry = ExtensionRegistry.newInstance
registerExtensions(registry)
run(CodeGeneratorRequest.parseFrom(request, registry), logger: Logger).toByteArray
}
}

object CodeGenerator {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,12 @@ import com.google.protobuf.compiler.PluginProtos.{ CodeGeneratorRequest, CodeGen
import scalapb.compiler.GeneratorParams
import protocbridge.Artifact
import com.github.ghik.silencer.silent
import com.google.protobuf.ExtensionRegistry
import protocgen.CodeGenRequest
import scalapb.options.Scalapb

abstract class ScalaCodeGenerator extends CodeGenerator {

// Override this to add generated files per service
def perServiceContent: Set[(Logger, Service) => immutable.Seq[CodeGeneratorResponse.File]] = Set.empty

Expand All @@ -31,6 +34,12 @@ abstract class ScalaCodeGenerator extends CodeGenerator {
BuildInfo.runtimeArtifactName + "_" + scalaBinaryVersion.prefix,
BuildInfo.version))

override def registerExtensions(registry: ExtensionRegistry): Unit = {
// Allow the embedded ScalaPB compiler helper classes to observe package/file-level options,
// so that properties looked up through DescriptorImplicits are in line with ScalaPB generated stubs
Scalapb.registerAllExtensions(registry)
}

// generate services code here, the data types we want to leave to scalapb
override def run(request: CodeGeneratorRequest, logger: Logger): CodeGeneratorResponse = {
val b = CodeGeneratorResponse.newBuilder
Expand Down
7 changes: 4 additions & 3 deletions docs/src/main/paradox/proto.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ whose name is determined by the `java_outer_classname` setting. By setting the
`java_multiple_files` option, the message classes will be generated in separate files,
but the 'outer' class is still generated with some metadata and utilities.

The Scala code generation uses the mechanism described in the
[ScalaPB documentation](https://scalapb.github.io/customizations.html)
with the `flat_package` option enabled.
The Scala code generation runs with the
[`flat_package` generator option](https://scalapb.github.io/docs/sbt-settings/#additional-options-to-the-generator) enabled by default.
Customizations can be added on a
[per-file and/or per-package basis](https://scalapb.github.io/customizations.html).
6 changes: 6 additions & 0 deletions sbt-plugin/src/main/scala/akka/grpc/sbt/AkkaGrpcPlugin.scala
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,12 @@ object AkkaGrpcPlugin extends AutoPlugin {
akkaGrpcGeneratedSources := Seq(AkkaGrpc.Client, AkkaGrpc.Server),
akkaGrpcGeneratedLanguages := Seq(AkkaGrpc.Scala),
akkaGrpcExtraGenerators := Seq.empty,
libraryDependencies ++= {
if (akkaGrpcGeneratedLanguages.value.contains(AkkaGrpc.Scala))
// Make scalapb.proto available for import in user-defined protos for file and package-level options
Seq("com.thesamet.scalapb" %% "scalapb-runtime" % scalapb.compiler.Version.scalapbVersion % "protobuf")
else Seq()
},
PB.recompile in Compile := {
// hack to get our (dirty) hands on a proper sbt logger before running the generators
generatorLogger.logger = streams.value.log
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
resolvers += Resolver.sonatypeRepo("staging")
resolvers += Resolver.bintrayRepo("akka", "snapshots")

enablePlugins(AkkaGrpcPlugin)

// Don't enable it flat_package globally, but via a package-level option instead (see package.proto)
akkaGrpcCodeGeneratorSettings -= "flat_package"
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
addSbtPlugin("com.lightbend.akka.grpc" % "sbt-akka-grpc" % sys.props("project.version"))
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
syntax = "proto3";

option java_package = "example.myapp.helloworld.grpc";

package helloworld;

// The greeting service definition.
service GreeterService {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {}

rpc ItKeepsTalking (stream HelloRequest) returns (HelloReply) {}

rpc ItKeepsReplying (HelloRequest) returns (stream HelloReply) {}

rpc StreamHellos (stream HelloRequest) returns (stream HelloReply) {}
}

// The request message containing the user's name.
message HelloRequest {
string name = 1;
}

// The response message containing the greetings
message HelloReply {
string message = 1;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
syntax = "proto2";

package helloworld;

import "scalapb/scalapb.proto";

option (scalapb.options) = {
scope: PACKAGE
flat_package: true
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package example.myapp.helloworld

import scala.concurrent.Future

import akka.NotUsed
import akka.stream.scaladsl.Source

import example.myapp.helloworld.grpc._

class GreeterServiceImpl extends GreeterService {
override def sayHello(in: HelloRequest): Future[HelloReply] = ???

override def streamHellos(in: Source[HelloRequest, NotUsed]): Source[HelloReply, NotUsed] = ???

override def itKeepsTalking(in: Source[HelloRequest, NotUsed]): Future[HelloReply] = ???

override def itKeepsReplying(in: HelloRequest): Source[HelloReply, NotUsed] = ???

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
> protocGenerate
$ exists target/scala-2.12/akka-grpc/main/example/myapp/helloworld/grpc/HelloRequest.scala
$ exists target/scala-2.12/akka-grpc/main/example/myapp/helloworld/grpc/HelloworldProto.scala
$ exists target/scala-2.12/akka-grpc/main/example/myapp/helloworld/grpc/GreeterService.scala

0 comments on commit 7c46a20

Please sign in to comment.