Skip to content

Commit

Permalink
save extensions from field options in message props
Browse files Browse the repository at this point in the history
  • Loading branch information
artemeff committed Jun 10, 2021
1 parent 4e39ed2 commit c8244e8
Show file tree
Hide file tree
Showing 14 changed files with 100 additions and 9 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,4 @@ gen-protos: protoc-gen-elixir
protoc -I src -I test/protobuf/protoc/proto --elixir_out=test/protobuf/protoc/proto_gen --plugin=./protoc-gen-elixir test/protobuf/protoc/proto/*.proto
protoc -I src --elixir_out=lib --plugin=./protoc-gen-elixir elixirpb.proto

.PHONY: clean gen_google_proto gen_test_protos
.PHONY: clean protoc-gen-elixir gen-google-protos gen-protos
7 changes: 7 additions & 0 deletions lib/mix/tasks/protobuf.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
defmodule Mix.Tasks.Protobuf do
use Mix.Task

def run(args) do
Protobuf.Protoc.CLI.main(args)
end
end
4 changes: 4 additions & 0 deletions lib/protobuf/dsl.ex
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,10 @@ defmodule Protobuf.DSL do
|> cal_encoded_fnum()
end

defp parse_field_opts([{:extensions, map} | t], acc) do
parse_field_opts(t, Map.put(acc, :extensions, map))
end

defp parse_field_opts([{:optional, true} | t], acc) do
parse_field_opts(t, Map.put(acc, :optional?, true))
end
Expand Down
6 changes: 4 additions & 2 deletions lib/protobuf/field_props.ex
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ defmodule Protobuf.FieldProps do
packed?: boolean,
map?: boolean,
deprecated?: boolean,
encoded_fnum: iodata
encoded_fnum: iodata,
extensions: map
}
defstruct fnum: nil,
name: nil,
Expand All @@ -36,5 +37,6 @@ defmodule Protobuf.FieldProps do
packed?: nil,
map?: false,
deprecated?: false,
encoded_fnum: nil
encoded_fnum: nil,
extensions: %{}
end
14 changes: 14 additions & 0 deletions lib/protobuf/protoc/cli.ex
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ defmodule Protobuf.Protoc.CLI do

@doc false
def main(["--version"]) do
Application.ensure_all_started(:protobuf)
{:ok, version} = :application.get_key(:protobuf, :vsn)
IO.puts(to_string(version))
end
Expand All @@ -28,6 +29,9 @@ defmodule Protobuf.Protoc.CLI do
end

def main(_) do
Application.ensure_all_started(:protobuf)
load_custom_extensions()

# https://groups.google.com/forum/#!topic/elixir-lang-talk/T5enez_BBTI
:io.setopts(:standard_io, encoding: :latin1)
bin = IO.binread(:all)
Expand Down Expand Up @@ -135,4 +139,14 @@ defmodule Protobuf.Protoc.CLI do
|> Enum.filter(&(&1 && &1 != ""))
|> Enum.join(".")
end

defp load_custom_extensions do
Application.get_env(:protobuf, :extension_paths, [])
|> Enum.map(&Path.wildcard/1)
|> List.flatten()
|> Enum.map(&Code.require_file/1)
|> List.flatten()
|> Enum.map(fn {module, _} -> module end)
|> Protobuf.Extension.cal_extensions()
end
end
7 changes: 7 additions & 0 deletions lib/protobuf/protoc/generator/message.ex
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,13 @@ defmodule Protobuf.Protoc.Generator.Message do
defp merge_field_options(opts, %{options: nil}), do: opts

defp merge_field_options(opts, f) do
opts =
if map_size(f.options.__pb_extensions__) > 0 do
Map.put(opts, :extensions, inspect(f.options.__pb_extensions__))
else
opts
end

opts
|> Map.put(:packed, f.options.packed)
|> Map.put(:deprecated, f.options.deprecated)
Expand Down
11 changes: 9 additions & 2 deletions test/protobuf/protoc/generator/message_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -150,13 +150,20 @@ defmodule Protobuf.Protoc.Generator.MessageTest do
number: 1,
type: :TYPE_INT32,
label: :LABEL_OPTIONAL,
options: Google.Protobuf.FieldOptions.new(packed: true)
options:
Google.Protobuf.FieldOptions.new(
packed: true,
__pb_extensions__: %{{Mypkg.PbExtension, :myopt_bool} => true}
)
)
]
)

{[], [msg]} = Generator.generate(ctx, desc)
assert msg =~ "field :a, 1, optional: true, type: :int32, packed: true\n"

assert msg =~
"field :a, 1, optional: true, type: :int32, " <>
"extensions: %{{Mypkg.PbExtension, :myopt_bool} => true}, packed: true\n"
end

test "generate/2 supports option :deprecated" do
Expand Down
4 changes: 4 additions & 0 deletions test/protobuf/protoc/integration_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ defmodule Protobuf.Protoc.IntegrationTest do

test "options" do
assert %{deprecated?: true} = My.Test.Options.__message_props__().field_props[1]

assert %{
extensions: %{{Mypkg.PbExtension, :myopt_bool} => true}
} = My.Test.Options.__message_props__().field_props[2]
end

test "extensions" do
Expand Down
3 changes: 3 additions & 0 deletions test/protobuf/protoc/proto/extension.proto
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@ package ext;

// -I src is needed, see Makefile
import "elixirpb.proto";
import "mypkg.proto";

option (elixirpb.file).module_prefix = "Protobuf.Protoc.ExtTest";

message Foo {
optional string a = 1;
optional string b = 2 [(mypkg.myopt_bool)=true];
optional string c = 3 [(mypkg.myopt_string)="test"];
}
10 changes: 10 additions & 0 deletions test/protobuf/protoc/proto/mypkg.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
syntax = "proto2";

package mypkg;

import "google/protobuf/descriptor.proto";

extend google.protobuf.FieldOptions {
optional bool myopt_bool = 100000;
optional string myopt_string = 100001 [default="test"];
}
4 changes: 4 additions & 0 deletions test/protobuf/protoc/proto/test.proto
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ package my.test; // dotted package name
//import "imp.proto";
import "multi/multi1.proto"; // unused import

// extensions
import "mypkg.proto";

enum HatType {
// deliberately skipping 0
FEDORA = 1;
Expand Down Expand Up @@ -125,4 +128,5 @@ message Communique {

message Options {
optional string opt1 = 1 [deprecated=true];
optional string opt2 = 2 [(mypkg.myopt_bool)=true];
}
16 changes: 14 additions & 2 deletions test/protobuf/protoc/proto_gen/extension.pb.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,21 @@ defmodule Protobuf.Protoc.ExtTest.Foo do
use Protobuf, syntax: :proto2

@type t :: %__MODULE__{
a: String.t()
a: String.t(),
b: String.t(),
c: String.t()
}
defstruct [:a]
defstruct [:a, :b, :c]

field :a, 1, optional: true, type: :string

field :b, 2,
optional: true,
type: :string,
extensions: %{{Mypkg.PbExtension, :myopt_bool} => true}

field :c, 3,
optional: true,
type: :string,
extensions: %{{Mypkg.PbExtension, :myopt_string} => "test"}
end
11 changes: 11 additions & 0 deletions test/protobuf/protoc/proto_gen/mypkg.pb.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
defmodule Mypkg.PbExtension do
@moduledoc false
use Protobuf, syntax: :proto2

extend Google.Protobuf.FieldOptions, :myopt_bool, 100_000, optional: true, type: :bool

extend Google.Protobuf.FieldOptions, :myopt_string, 100_001,
optional: true,
type: :string,
default: "test"
end
10 changes: 8 additions & 2 deletions test/protobuf/protoc/proto_gen/test.pb.ex
Original file line number Diff line number Diff line change
Expand Up @@ -246,11 +246,17 @@ defmodule My.Test.Options do
use Protobuf, syntax: :proto2

@type t :: %__MODULE__{
opt1: String.t()
opt1: String.t(),
opt2: String.t()
}
defstruct [:opt1]
defstruct [:opt1, :opt2]

field :opt1, 1, optional: true, type: :string, deprecated: true

field :opt2, 2,
optional: true,
type: :string,
extensions: %{{Mypkg.PbExtension, :myopt_bool} => true}
end

defmodule My.Test.PbExtension do
Expand Down

0 comments on commit c8244e8

Please sign in to comment.