Implement Exception.message/1 for exceptions (#242)

We generate Elixir exception structs via defexception for Thrift
exception types. That macro always provides an exception/1
implementation, but message/1 is only generated if the exception is
defined with a :message field. When it doesn't, the generated code
produces a warning because the full Exception behaviour hasn't been
implemented.

This change generates a message/1 implementation for all of our Thrift
exception structs which don't have a natural :message field. It returns
the Kernel.inspect/2 string representation of the exception, which is
both simple and unambiguous.
This commit is contained in:
Jon Parise 2017-02-16 13:58:30 -08:00 committed by GitHub
parent 3b3ce1b501
commit bd4f524bd6
2 changed files with 19 additions and 4 deletions

View File

@ -24,12 +24,17 @@ defmodule Thrift.Generator.StructGenerator do
|> Utils.sort_defs
define_block = case label do
:struct ->
quote do: defstruct unquote(struct_parts)
:union ->
quote do: defstruct unquote(struct_parts)
:exception ->
quote do: defexception unquote(struct_parts)
_ ->
quote do: defstruct unquote(struct_parts)
end
extra_defs = if label == :exception and not Keyword.has_key?(struct_parts, :message) do
quote do
@spec message(Exception.t) :: String.t
def message(exception), do: inspect(exception)
end
end
quote do
@ -43,6 +48,7 @@ defmodule Thrift.Generator.StructGenerator do
unquote(define_block)
@type t :: %__MODULE__{}
def new, do: %__MODULE__{}
unquote_splicing(List.wrap(extra_defs))
defmodule BinaryProtocol do
unquote_splicing(binary_protocol_defs)
end

View File

@ -306,6 +306,9 @@ defmodule Thrift.Generator.BinaryProtocolTest do
1: optional string message,
99: optional byte num;
}
exception Ex2 {
1: optional i16 error_code;
}
struct Exception {
1: optional Ex val;
2: optional map<Ex, Ex> val_map;
@ -327,6 +330,12 @@ defmodule Thrift.Generator.BinaryProtocolTest do
assert_serializes %Exception{val_list: [%Ex{num: 91}]}, <<15, 0, 4, 12, 0, 0, 0, 1, 3, 0, 99, 91, 0, 0>>
end
thrift_test "exceptions always provide message/1" do
assert Ex.message(%Ex{message: "text", num: 1}) == "text"
assert Ex2.message(%Ex2{error_code: 1}) ==
~s(%Thrift.Generator.BinaryProtocolTest.Ex2{error_code: 1})
end
@thrift_file name: "composite.thrift", contents: """
struct Composite {
1: optional map<map<byte, byte>, map<byte, byte>> map_of_maps;