Skip to content
Merged
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
44 changes: 43 additions & 1 deletion grpc_server/lib/grpc/protoc/cli.ex
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ defmodule GRPC.Protoc.CLI do

alias Protobuf.Protoc.Context

@gen_stubs_disabled_plugin "__grpc_server_gen_stubs_disabled__"

# Entrypoint for the escript (protoc-gen-elixir).
@doc false
def main(args)
Expand Down Expand Up @@ -74,6 +76,11 @@ defmodule GRPC.Protoc.CLI do
Google.Protobuf.Compiler.CodeGeneratorResponse.Feature.value(:FEATURE_PROTO3_OPTIONAL)
end

@doc false
def gen_stubs?(%Context{plugins: plugins}) do
@gen_stubs_disabled_plugin not in plugins
end

# Made public for testing.
@doc false
def parse_params(%Context{} = ctx, params_str) when is_binary(params_str) do
Expand All @@ -83,7 +90,16 @@ defmodule GRPC.Protoc.CLI do
end

defp parse_param("plugins=" <> plugins, %Context{} = ctx) do
%Context{ctx | plugins: String.split(plugins, "+")}
plugins = String.split(plugins, "+")

plugins =
if gen_stubs?(ctx) do
plugins
else
[@gen_stubs_disabled_plugin | plugins]
end

%Context{ctx | plugins: plugins}
end

defp parse_param("gen_descriptors=" <> value, %Context{} = ctx) do
Expand All @@ -96,6 +112,19 @@ defmodule GRPC.Protoc.CLI do
end
end

defp parse_param("gen_stubs=" <> value, %Context{} = ctx) do
case value do
"true" ->
put_gen_stubs(ctx, true)

"false" ->
put_gen_stubs(ctx, false)

other ->
raise "invalid value for gen_stubs option, expected \"true\" or \"false\", got: #{inspect(other)}"
end
end

defp parse_param("package_prefix=" <> package, %Context{} = ctx) do
if package == "" do
raise "package_prefix can't be empty"
Expand Down Expand Up @@ -132,6 +161,19 @@ defmodule GRPC.Protoc.CLI do
ctx
end

defp put_gen_stubs(%Context{} = ctx, true) do
%Context{ctx | plugins: List.delete(ctx.plugins, @gen_stubs_disabled_plugin)}
end

defp put_gen_stubs(%Context{} = ctx, false) do
plugins =
ctx.plugins
|> List.delete(@gen_stubs_disabled_plugin)
|> then(&[@gen_stubs_disabled_plugin | &1])

%Context{ctx | plugins: plugins}
end

# Made public for testing.
@doc false
def find_types(%Context{} = ctx, descs, files_to_generate)
Expand Down
1 change: 1 addition & 0 deletions grpc_server/lib/grpc/protoc/generator/service.ex
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ defmodule GRPC.Protoc.Generator.Service do
methods: methods,
descriptor_fun_body: descriptor_fun_body,
version: Util.version(),
gen_stubs?: GRPC.Protoc.CLI.gen_stubs?(ctx),
module_doc?: false
)
)}
Expand Down
2 changes: 2 additions & 0 deletions grpc_server/priv/templates/service.ex.eex
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,11 @@ defmodule <%= @module %>.Service do
<% end %>
end

<%= if @gen_stubs? do %>
defmodule <%= @module %>.Stub do
<%= unless @module_doc? do %>
@moduledoc false
<% end %>
use GRPC.Stub, service: <%= @module %>.Service
end
<% end %>
67 changes: 67 additions & 0 deletions grpc_server/test/grpc/protoc/generator/service_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
defmodule GRPC.Protoc.Generator.ServiceTest do
use ExUnit.Case, async: true

alias GRPC.Protoc.CLI
alias GRPC.Protoc.Generator.Service
alias Protobuf.Protoc.Context

describe "generate/2" do
test "generates service and stub modules by default" do
{_module, content} = Service.generate(context(), service())

assert content =~ "defmodule Helloworld.Greeter.Service do"
assert content =~ "defmodule Helloworld.Greeter.Stub do"
assert content =~ "use GRPC.Stub, service: Helloworld.Greeter.Service"
end

test "generates service module without stub when gen_stubs=false" do
ctx = CLI.parse_params(context(), "gen_stubs=false")

{_module, content} = Service.generate(ctx, service())

assert content =~ "defmodule Helloworld.Greeter.Service do"
refute content =~ "defmodule Helloworld.Greeter.Stub do"
refute content =~ "use GRPC.Stub"
end
end

describe "parse_params/2" do
test "accepts gen_stubs=true and gen_stubs=false" do
assert CLI.gen_stubs?(CLI.parse_params(context(), "gen_stubs=true"))
refute CLI.gen_stubs?(CLI.parse_params(context(), "gen_stubs=false"))
refute CLI.gen_stubs?(CLI.parse_params(context(), "gen_stubs=false,plugins=grpc"))
end

test "raises on invalid gen_stubs values" do
assert_raise RuntimeError,
~s(invalid value for gen_stubs option, expected "true" or "false", got: "maybe"),
fn ->
CLI.parse_params(context(), "gen_stubs=maybe")
end
end
end

defp context do
%Context{
package: "helloworld",
dep_type_mapping: %{
".helloworld.HelloRequest" => %{type_name: "Helloworld.HelloRequest"},
".helloworld.HelloReply" => %{type_name: "Helloworld.HelloReply"}
}
}
end

defp service do
%Google.Protobuf.ServiceDescriptorProto{
name: "Greeter",
method: [
%Google.Protobuf.MethodDescriptorProto{
name: "SayHello",
input_type: ".helloworld.HelloRequest",
output_type: ".helloworld.HelloReply",
options: %Google.Protobuf.MethodOptions{}
}
]
}
end
end
Loading