diff --git a/lib/grpc_reflection/service/builder.ex b/lib/grpc_reflection/service/builder.ex index 3278e0a..44ba834 100644 --- a/lib/grpc_reflection/service/builder.ex +++ b/lib/grpc_reflection/service/builder.ex @@ -108,7 +108,7 @@ defmodule GrpcReflection.Service.Builder do when extension_range != [] do unencoded_extension_payload = %Google.Protobuf.FileDescriptorProto{ name: extension_file, - package: Util.package_from_name(symbol), + package: Util.get_package(symbol), dependency: [symbol <> ".proto"], syntax: Util.get_syntax(mod) } @@ -144,7 +144,7 @@ defmodule GrpcReflection.Service.Builder do defp process_extensions(_, _, _, _), do: {:ignore, {nil, nil}} defp process_common(name, module, descriptor) do - package = Util.package_from_name(name) + package = Util.get_package(name) dependencies = descriptor diff --git a/lib/grpc_reflection/service/builder/util.ex b/lib/grpc_reflection/service/builder/util.ex index cac8264..424e412 100644 --- a/lib/grpc_reflection/service/builder/util.ex +++ b/lib/grpc_reflection/service/builder/util.ex @@ -7,13 +7,20 @@ defmodule GrpcReflection.Service.Builder.Util do @type_message Map.fetch!(Google.Protobuf.FieldDescriptorProto.Type.mapping(), :TYPE_MESSAGE) - def package_from_name(service_name) do - service_name - |> String.split(".") - |> Enum.reverse() - |> then(fn [_ | rest] -> rest end) - |> Enum.reverse() - |> Enum.join(".") + def get_package(symbol) do + parent_symbol = symbol |> String.split(".") |> Enum.slice(0..-2) |> Enum.join(".") + + try do + parent_module = convert_symbol_to_module(parent_symbol) + + if function_exported?(parent_module, :descriptor, 0) do + get_package(parent_symbol) + else + parent_symbol + end + rescue + _ -> parent_symbol + end end def upcase_first(<>), do: String.upcase(<>) <> rest @@ -95,14 +102,8 @@ defmodule GrpcReflection.Service.Builder.Util do name -> name end) |> String.split(".") - |> Enum.reverse() - |> then(fn - [m | segments] -> [m | Enum.map(segments, &upcase_first/1)] - end) - |> Enum.reverse() - |> Enum.join(".") - |> then(fn name -> "Elixir." <> name end) - |> String.to_existing_atom() + |> Enum.map(&upcase_first/1) + |> Module.safe_concat() end def is_message_descriptor?(%Google.Protobuf.FieldDescriptorProto{type: @type_message}), diff --git a/test/builder/util_test.exs b/test/builder/util_test.exs index 3115f22..d37ce61 100644 --- a/test/builder/util_test.exs +++ b/test/builder/util_test.exs @@ -10,8 +10,15 @@ defmodule GrpcReflection.Service.Builder.UtilTest do end describe "common utils" do - test "get package from module name" do - assert "a.b" == Util.package_from_name("a.b.CService") + test "get package from module" do + assert "testserviceV3" == + Util.get_package("testserviceV3.TestRequest") + + assert "testserviceV3" == + Util.get_package("testserviceV3.TestRequest.Payload.Location") + + assert "testserviceV3" == + Util.get_package("testserviceV3.TestService") end test "upcase_first" do @@ -21,6 +28,17 @@ defmodule GrpcReflection.Service.Builder.UtilTest do test "downcase_first" do assert "hello" == Util.downcase_first("Hello") end + + test "convert symbol to module succeed" do + assert TestserviceV3.TestRequest == + Util.convert_symbol_to_module("testserviceV3.TestRequest") + end + + test "convert symbol to module fail" do + assert_raise ArgumentError, fn -> + Util.convert_symbol_to_module("testservice.TestRequest.Payload.Location") + end + end end describe "utils for dealing with proto2 only" do