Skip to content
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
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