summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosé Valim <jose.valim@plataformatec.com.br>2019-08-20 11:21:14 +0200
committerJosé Valim <jose.valim@plataformatec.com.br>2019-08-20 11:46:17 +0200
commit449c9a5f8b2925ccf135f2220c4689388f38ac60 (patch)
tree13d59e08cfa4d0965ef0598871bcdaef6686b311
parentd44da48ee108de4166d961d5bf94dd4c8584f0f2 (diff)
downloadelixir-449c9a5f8b2925ccf135f2220c4689388f38ac60.tar.gz
Split quoted and value handling in ExUnit.Diff
Closes #9302.
-rw-r--r--lib/ex_unit/lib/ex_unit/diff.ex353
-rw-r--r--lib/ex_unit/test/ex_unit/diff_test.exs13
2 files changed, 178 insertions, 188 deletions
diff --git a/lib/ex_unit/lib/ex_unit/diff.ex b/lib/ex_unit/lib/ex_unit/diff.ex
index dd6077a22..cefe3bc12 100644
--- a/lib/ex_unit/lib/ex_unit/diff.ex
+++ b/lib/ex_unit/lib/ex_unit/diff.ex
@@ -28,118 +28,149 @@ defmodule ExUnit.Diff do
value. The `context` should be `{:match, pins}` for pattern matching and
`expr` for any other case.
"""
- def compute(left, right, :expr) do
- compare_quoted(left, right, %{pins: %{}, context: nil, current_vars: %{}})
+ def compute(left, right, context) do
+ diff(left, right, context_to_env(context))
end
- def compute(left, right, {:match, pins}) do
- compare_quoted(left, right, %{pins: Map.new(pins), context: :match, current_vars: %{}})
- end
+ defp context_to_env(:expr),
+ do: %{pins: %{}, context: nil, current_vars: %{}}
+
+ defp context_to_env({:match, pins}),
+ do: %{pins: Map.new(pins), context: :match, current_vars: %{}}
+
+ # Main entry point for recursive diff
+
+ defp diff(left, right, %{context: :match} = env), do: diff_quoted(left, right, env)
+ defp diff(left, right, env), do: diff_value(left, right, env)
+
+ # diff quoted
- defp compare_quoted({:_, _, context} = left, right, env) when is_atom(context) do
+ defp diff_quoted({:_, _, context} = left, right, env) when is_atom(context) do
diff_right = escape(right)
diff = %__MODULE__{equivalent?: true, left: left, right: diff_right}
{diff, env}
end
- defp compare_quoted({:^, _, [{name, _, context}]} = left, right, env)
+ defp diff_quoted({:^, _, [{name, _, context}]} = left, right, env)
when is_atom(name) and is_atom(context) do
- compare_pin(left, right, env)
+ diff_pin(left, right, env)
end
- defp compare_quoted({name, _, context} = left, right, env)
+ defp diff_quoted({name, _, context} = left, right, env)
when is_atom(name) and is_atom(context) do
- compare_var(left, right, env)
+ diff_var(left, right, env)
end
- defp compare_quoted({:-, _, [number]}, right, env)
- when is_number(number) and is_number(right) do
- compare_quoted(-number, right, env)
+ defp diff_quoted({:-, _, [number]}, right, env) when is_number(number) do
+ diff_quoted(-number, right, env)
end
- defp compare_quoted({:+, _, [number]}, right, env)
- when is_number(number) and is_number(right) do
- compare_quoted(number, right, env)
+ defp diff_quoted({:+, _, [number]}, right, env) when is_number(number) do
+ diff_quoted(number, right, env)
end
- defp compare_quoted(literal, literal, env)
- when is_atom(literal) or is_number(literal) or is_reference(literal) or
- is_pid(literal) or is_function(literal) do
- diff = %__MODULE__{equivalent?: true, left: literal, right: literal}
- {diff, env}
+ defp diff_quoted({:++, _, _} = left, right, env) when is_list(right) do
+ diff_maybe_improper_list(left, right, env)
end
- defp compare_quoted(left, right, env) when is_number(left) and is_number(right) do
- compare_number(left, right, env)
+ defp diff_quoted({:{}, _, left}, right, env) when is_tuple(right) do
+ diff_tuple(left, Tuple.to_list(right), env)
end
- defp compare_quoted({:++, _, _} = left, right, env) when is_list(right) do
- compare_maybe_improper_list(left, right, env)
+ defp diff_quoted({_, _} = left, right, env) when is_tuple(right) do
+ diff_tuple(Tuple.to_list(left), Tuple.to_list(right), env)
end
- defp compare_quoted(left, right, env) when is_list(left) and is_list(right) do
- compare_maybe_list(left, right, env)
+ defp diff_quoted({:%, _, [struct, {:%{}, _, kw}]}, %{} = right, env)
+ when is_atom(struct) and is_list(kw) do
+ diff_quoted_struct(kw, struct, right, env)
end
- defp compare_quoted({:{}, _, _} = left, right, env) when is_tuple(right) do
- compare_tuple(left, right, env)
+ defp diff_quoted({:%{}, _, [{:__struct__, struct} | kw]}, %{} = right, env)
+ when is_atom(struct) do
+ diff_quoted_struct(kw, struct, right, env)
end
- defp compare_quoted({_, _} = left, right, env) when is_tuple(right) do
- compare_tuple(left, right, env)
+ defp diff_quoted({:%{}, _, items} = left, %struct{} = right, env) when is_list(items) do
+ diff_map(left, right, nil, struct, env)
end
- defp compare_quoted(left, right, %{context: nil} = env)
- when is_tuple(left) and is_tuple(right) do
- compare_tuple(left, right, env)
+ defp diff_quoted({:%{}, _, items} = left, %{} = right, env) when is_list(items) do
+ diff_map(left, right, nil, nil, env)
end
- defp compare_quoted({:%, _, [_, {:%{}, _, items}]} = left, %{} = right, env)
- when is_list(items) do
- compare_struct(left, right, env)
+ defp diff_quoted({:<>, _, _} = left, right, env) when is_binary(right) do
+ diff_string_concat(left, right, env)
end
- defp compare_quoted({:%{}, _, [{:__struct__, _} | _]} = left, %{} = right, env) do
- compare_struct(left, right, env)
+ defp diff_quoted({_, [{:expanded, expanded} | _], _} = left, right, env) do
+ macro = Macro.update_meta(left, &Keyword.delete(&1, :expanded))
+ diff_macro(macro, expanded, right, env)
end
- defp compare_quoted({:%{}, _, items} = left, %struct{} = right, env) when is_list(items) do
- compare_map(left, right, nil, struct, env)
+ defp diff_quoted(left, right, env) when is_list(left) and is_list(right) do
+ diff_maybe_list(left, right, env)
end
- defp compare_quoted({:%{}, _, items} = left, %{} = right, env) when is_list(items) do
- compare_map(left, right, nil, nil, env)
+ defp diff_quoted(left, right, env)
+ when is_atom(left) or is_number(left) or is_reference(left) or
+ is_pid(left) or is_function(left) or is_binary(left) do
+ diff_value(left, right, env)
end
- defp compare_quoted(%_{} = left, %{} = right, env) do
- compare_struct(left, right, env)
+ defp diff_quoted(left, right, %{context: :match} = env) do
+ diff_left = update_diff_meta(left, true)
+ diff_right = escape(right) |> update_diff_meta(true)
+ diff = %__MODULE__{equivalent?: false, left: diff_left, right: diff_right}
+ {diff, env}
end
- defp compare_quoted(%{} = left, %{} = right, env) do
- compare_map(left, right, nil, nil, env)
+ ## diff_value
+
+ defp diff_value(literal, literal, env)
+ when is_atom(literal) or is_number(literal) or is_reference(literal) or
+ is_pid(literal) or is_function(literal) do
+ {%__MODULE__{equivalent?: true, left: literal, right: literal}, env}
end
- defp compare_quoted(left, right, env) when is_binary(left) and is_binary(right) do
- compare_string(left, right, ?\", env)
+ defp diff_value(left, right, env) when is_number(left) and is_number(right) do
+ diff_number(left, right, env)
end
- defp compare_quoted({:<>, _, _} = left, right, env) when is_binary(right) do
- compare_string_concat(left, right, env)
+ defp diff_value(left, right, env) when is_list(left) and is_list(right) do
+ diff_maybe_list(left, right, env)
end
- defp compare_quoted({_, [{:expanded, expanded} | _], _} = left, right, env) do
- macro = Macro.update_meta(left, &Keyword.delete(&1, :expanded))
- compare_macro(macro, expanded, right, env)
+ defp diff_value(left, right, env) when is_tuple(left) and is_tuple(right) do
+ diff_tuple(Tuple.to_list(left), Tuple.to_list(right), env)
end
- defp compare_quoted(left, right, %{context: :match} = env) do
- diff_left = update_diff_meta(left, true)
- diff_right = escape(right) |> update_diff_meta(true)
- diff = %__MODULE__{equivalent?: false, left: diff_left, right: diff_right}
- {diff, env}
+ defp diff_value(%left_struct{} = left, %right_struct{} = right, env) do
+ diff_struct(
+ left,
+ Map.from_struct(left),
+ right,
+ left_struct,
+ right_struct,
+ env
+ )
+ end
+
+ defp diff_value(%{} = left, %{} = right, env) do
+ diff_map(
+ Map.delete(left, :__struct__),
+ Map.delete(right, :__struct__),
+ maybe_struct(left),
+ maybe_struct(right),
+ env
+ )
end
- defp compare_quoted(left, right, env) do
+ defp diff_value(left, right, env) when is_binary(left) and is_binary(right) do
+ diff_string(left, right, ?\", env)
+ end
+
+ defp diff_value(left, right, env) do
diff_left = escape(left) |> update_diff_meta(true)
diff_right = escape(right) |> update_diff_meta(true)
diff = %__MODULE__{equivalent?: false, left: diff_left, right: diff_right}
@@ -148,18 +179,17 @@ defmodule ExUnit.Diff do
# Macros
- defp compare_macro(macro, expanded, right, env) do
- {diff, post_env} = compare_quoted(expanded, right, env)
-
+ defp diff_macro(macro, expanded, right, env) do
+ {diff, post_env} = diff(expanded, right, env)
diff_left = update_diff_meta(macro, !diff.equivalent?)
{%{diff | left: diff_left}, post_env}
end
# Pins
- defp compare_pin({:^, _, [{name, _, _}]} = pin, right, %{pins: pins} = env) do
+ defp diff_pin({:^, _, [{name, _, _}]} = pin, right, %{pins: pins} = env) do
%{^name => pin_value} = pins
- {diff, post_env} = compare_quoted(pin_value, right, env)
+ {diff, post_env} = diff(pin_value, right, env)
diff_left = update_diff_meta(pin, !diff.equivalent?)
{%{diff | left: diff_left}, post_env}
@@ -167,7 +197,7 @@ defmodule ExUnit.Diff do
# Vars
- defp compare_var({name, meta, context} = left, right, env) do
+ defp diff_var({name, meta, context} = left, right, env) do
identifier = {name, meta[:counter] || context}
case env.current_vars do
@@ -192,28 +222,19 @@ defmodule ExUnit.Diff do
# Tuples
- defp compare_tuple({:{}, _, left_list}, right, %{context: :match} = env) do
- compare_tuple_items(left_list, Tuple.to_list(right), env)
- end
-
- defp compare_tuple(left, right, env) do
- compare_tuple_items(Tuple.to_list(left), Tuple.to_list(right), env)
- end
-
- defp compare_tuple_items(list_left, list_right, env) do
+ defp diff_tuple(list_left, list_right, env) do
{compared, non_compared_left, non_compared_right, post_env} =
- compare_tuple_items_by_index(list_left, list_right, env)
-
- remaining_diff = compare_tuple_remaining_items(non_compared_left, non_compared_right)
+ diff_tuple_by_index(list_left, list_right, env)
+ remaining_diff = diff_tuple_remaining(non_compared_left, non_compared_right)
{build_tuple_result(compared, remaining_diff), post_env}
end
- defp compare_tuple_items_by_index(list_left, list_right, env) do
+ defp diff_tuple_by_index(list_left, list_right, env) do
{compared, non_compared_left, non_compared_right, post_env} =
Enum.reduce(list_left, {[], [], list_right, env}, fn
item, {compared, non_compared, [next | continue], acc_env} ->
- {diff, diff_post_env} = compare_quoted(item, next, acc_env)
+ {diff, diff_post_env} = diff(item, next, acc_env)
{[diff | compared], non_compared, continue, diff_post_env}
item, {compared, non_compared, [], acc_env} ->
@@ -228,7 +249,7 @@ defmodule ExUnit.Diff do
}
end
- defp compare_tuple_remaining_items([], []) do
+ defp diff_tuple_remaining([], []) do
%__MODULE__{
equivalent?: true,
left: {:{}, [], []},
@@ -236,7 +257,7 @@ defmodule ExUnit.Diff do
}
end
- defp compare_tuple_remaining_items(left, right) do
+ defp diff_tuple_remaining(left, right) do
left = Enum.map(left, &update_diff_meta(&1, true))
right = Enum.map(right, &update_diff_meta(&1, true))
@@ -257,11 +278,11 @@ defmodule ExUnit.Diff do
# Lists
- defp compare_maybe_list(left, right, env) do
+ defp diff_maybe_list(left, right, env) do
if List.ascii_printable?(left) and List.ascii_printable?(right) do
- compare_string(List.to_string(left), List.to_string(right), ?', env)
+ diff_string(List.to_string(left), List.to_string(right), ?', env)
else
- compare_maybe_improper_list(left, right, env)
+ diff_maybe_improper_list(left, right, env)
end
end
@@ -269,9 +290,9 @@ defmodule ExUnit.Diff do
# adding them back in the end. When the `left` contains a improper element
# it will extract forcefully a improper element on the `right` for matching
# purposes.
- defp compare_maybe_improper_list(left, right, env) do
- {parsed_left, improper_left, operators_left, length_left} = parse_list(left, 0)
- {parsed_right, improper_right, operators_right, _} = parse_list(right, 0)
+ defp diff_maybe_improper_list(left, right, env) do
+ {parsed_left, improper_left, operators_left, length_left} = parse_list(left, 0, env.context)
+ {parsed_right, improper_right, operators_right, _} = parse_list(right, 0, nil)
{parsed_right, improper_right, split?} =
split_list(parsed_right, length_left, improper_right, improper_left)
@@ -279,7 +300,7 @@ defmodule ExUnit.Diff do
{parsed_diff, parsed_post_env} = myers_difference_list(parsed_left, parsed_right, env)
{improper_diff, improper_post_env, improper_diff?} =
- compare_improper(improper_left, improper_right, parsed_post_env, split?)
+ diff_improper(improper_left, improper_right, parsed_post_env, split?)
diff =
merge_diff(parsed_diff, improper_diff, fn left1, left2, right1, right2 ->
@@ -298,36 +319,36 @@ defmodule ExUnit.Diff do
{diff, improper_post_env}
end
- defp compare_improper({:element, left}, {:element, right}, env, split?) do
- {diff, post_env} = compare_quoted(left, right, env)
+ defp diff_improper({:element, left}, {:element, right}, env, split?) do
+ {diff, post_env} = diff(left, right, env)
{diff, post_env, split?}
end
- defp compare_improper({:element, left}, :empty, env, _split?) do
+ defp diff_improper({:element, left}, :empty, env, _split?) do
diff_left = update_diff_meta(left, true)
diff = %__MODULE__{equivalent?: false, left: diff_left}
{diff, env, true}
end
- defp compare_improper(:empty, {:element, right}, env, _split?) do
+ defp diff_improper(:empty, {:element, right}, env, _split?) do
diff_right = escape(right) |> update_diff_meta(true)
diff = %__MODULE__{equivalent?: false, right: diff_right}
{diff, env, true}
end
- defp compare_improper(:empty, :empty, env, _split?) do
+ defp diff_improper(:empty, :empty, env, _split?) do
diff = %__MODULE__{equivalent?: true}
{diff, env, false}
end
- defp parse_list([], _index) do
+ defp parse_list([], _index, _context) do
{[], :empty, nil, 0}
end
- defp parse_list({:++, _, [left, right]}, _index) do
- {parsed_left, :empty, operators_left, length_left} = parse_list(left, 0)
+ defp parse_list({:++, _, [left, right]}, _index, :match) do
+ {parsed_left, :empty, operators_left, length_left} = parse_list(left, 0, :match)
- case parse_list(right, 0) do
+ case parse_list(right, 0, :match) do
{:improper, improper} ->
operators = {:++, length_left, [operators_left]}
{parsed_left, {:element, improper}, operators, length_left}
@@ -339,8 +360,8 @@ defmodule ExUnit.Diff do
end
end
- defp parse_list([{:|, _, [head, tail]}], index) do
- case parse_list(tail, 0) do
+ defp parse_list([{:|, _, [head, tail]}], index, :match) do
+ case parse_list(tail, 0, :match) do
{:improper, improper} ->
operator = {:|, index, []}
{[head], {:element, improper}, operator, 1}
@@ -351,8 +372,8 @@ defmodule ExUnit.Diff do
end
end
- defp parse_list([head | tail], index) do
- case parse_list(tail, index + 1) do
+ defp parse_list([head | tail], index, context) do
+ case parse_list(tail, index + 1, context) do
{:improper, improper} ->
operator = {:|, index, []}
{[head], {:element, improper}, operator, 1}
@@ -362,7 +383,7 @@ defmodule ExUnit.Diff do
end
end
- defp parse_list(element, _index) do
+ defp parse_list(element, _index, _) do
{:improper, element}
end
@@ -498,7 +519,7 @@ defmodule ExUnit.Diff do
end
defp follow_snake({y, [elem1 | rest1], [elem2 | rest2], {edit1, edit2, env}} = path) do
- {diff, post_env} = compare_quoted(elem1, elem2, env)
+ {diff, post_env} = diff(elem1, elem2, env)
if diff.equivalent? do
new_edit1 = [{:eq, diff.left} | edit1]
@@ -524,7 +545,7 @@ defmodule ExUnit.Diff do
end
defp list_script_to_result([{:del, elem1} | rest1], [{:ins, elem2} | rest2], env) do
- {elem_diff, elem_post_env} = compare_quoted(elem1, elem2, env)
+ {elem_diff, elem_post_env} = diff(elem1, elem2, env)
{rest_diff, rest_post_env} = list_script_to_result(rest1, rest2, elem_post_env)
{prepend_diff(elem_diff, rest_diff), rest_post_env}
@@ -557,21 +578,21 @@ defmodule ExUnit.Diff do
# Maps
- defp compare_map(%{} = left, right, struct1, struct2, env) do
- compare_map_items(left, right, struct1, struct2, env)
+ defp diff_map(%{} = left, right, struct1, struct2, env) do
+ diff_map_items(left, right, struct1, struct2, env)
end
- defp compare_map({:%{}, _, items}, right, struct1, struct2, env) do
- compare_map_items(items, right, struct1, struct2, env)
+ defp diff_map({:%{}, _, items}, right, struct1, struct2, env) do
+ diff_map_items(items, right, struct1, struct2, env)
end
# Compare items based on the keys of `left_items` and add the `:diff` meta to
# the element that it wasn't able to compare.
- defp compare_map_items(left_items, right, struct1, struct2, env) do
+ defp diff_map_items(left_items, right, struct1, struct2, env) do
{non_comparable_by_key, remaining, compared, struct1, by_key_post_env} =
- compare_map_items_by_key(left_items, right, struct1, env)
+ diff_map_items_by_key(left_items, right, struct1, env)
- remaining_diff = compare_map_remaining_pairs(non_comparable_by_key, remaining, env)
+ remaining_diff = diff_map_remaining_pairs(non_comparable_by_key, remaining, env)
struct_diff = build_struct_result(struct1, struct2)
map_diff = build_map_result(compared, remaining_diff)
@@ -579,7 +600,7 @@ defmodule ExUnit.Diff do
{prepend_diff(struct_diff, map_diff), by_key_post_env}
end
- defp compare_map_items_by_key(items, right, defined_struct, env) do
+ defp diff_map_items_by_key(items, right, defined_struct, env) do
{non_comparable, remaining, compared, items_struct, post_env} =
Enum.reduce(items, {[], right, [], nil, env}, fn
{:__struct__, name}, acc ->
@@ -593,7 +614,7 @@ defmodule ExUnit.Diff do
{[item | non_comparable], remaining, [nil | compared], struct, acc_env}
{popped, new_remaining} ->
- {diff, diff_post_env} = compare_map_pair(item, {literal_key, popped}, acc_env)
+ {diff, diff_post_env} = diff_map_pair(item, {literal_key, popped}, acc_env)
{non_comparable, new_remaining, [diff | compared], struct, diff_post_env}
end
end)
@@ -611,8 +632,8 @@ defmodule ExUnit.Diff do
{non_comparable, remaining, compared, defined_struct, post_env}
end
- defp compare_map_pair({key1, value1}, {key2, value2}, env) do
- {diff, post_env} = compare_quoted(value1, value2, env)
+ defp diff_map_pair({key1, value1}, {key2, value2}, env) do
+ {diff, post_env} = diff(value1, value2, env)
diff_left = {key1, diff.left}
diff_right = {key2, diff.right}
@@ -631,7 +652,7 @@ defmodule ExUnit.Diff do
# Can't compare using `myers_difference_list` because if key and value are
# equivalent, it gives strange results. It just mark them as different
# depending on the context, if `:match` only left side, otherwise both sides.
- defp compare_map_remaining_pairs(remaining, right, env) do
+ defp diff_map_remaining_pairs(remaining, right, env) do
list_left = Enum.map(remaining, &update_diff_meta(&1, true))
list_right =
@@ -671,45 +692,30 @@ defmodule ExUnit.Diff do
# Structs
- defp compare_struct({:%, _, [struct1, left_map]}, right, env) do
- compare_quoted_struct(left_map, struct1, right, env)
- end
-
- defp compare_struct({:%{}, meta, [{:__struct__, struct1} | left_items]}, right, env) do
- compare_quoted_struct({:%{}, meta, left_items}, struct1, right, env)
+ defp diff_quoted_struct(kw, struct1, %struct2{} = right, env) do
+ if Macro.quoted_literal?(kw) do
+ diff_struct(struct(struct1, kw), Map.new(kw), right, struct1, struct2, env)
+ else
+ diff_map(Map.new(kw), right, struct1, struct2, env)
+ end
end
- defp compare_struct(left, right, env) do
- compare_struct(
- left,
- Map.from_struct(left),
- right,
- maybe_struct(left),
- maybe_struct(right),
- env
- )
+ defp diff_quoted_struct(kw, struct1, right, env) do
+ diff_map(Map.new(kw), right, struct1, nil, env)
end
- defp compare_struct(%{} = value, left, right, struct1, struct2, env) do
+ defp diff_struct(%{} = value, left, right, struct1, struct2, env) do
if Inspect.impl_for(value) not in [Inspect.Any, Inspect.Map] do
inspect_left = inspect(value)
inspect_right = inspect(right)
if inspect_left != inspect_right do
- compare_string(inspect_left, inspect_right, ?\", env)
+ diff_string(inspect_left, inspect_right, ?\", env)
else
- compare_map(left, right, struct1, struct2, env)
+ diff_map(left, right, struct1, struct2, env)
end
else
- compare_map(left, right, struct1, struct2, env)
- end
- end
-
- defp compare_quoted_struct({:%{}, _, kw} = map, struct, right, env) do
- if Macro.quoted_literal?(kw) do
- compare_struct(struct(struct, kw), map, right, struct, maybe_struct(right), env)
- else
- compare_map(map, right, struct, maybe_struct(right), env)
+ diff_map(left, right, struct1, struct2, env)
end
end
@@ -738,12 +744,12 @@ defmodule ExUnit.Diff do
defp build_struct_result(struct1, struct2) do
diff_left = update_diff_meta({:__struct__, struct1}, true)
diff_right = update_diff_meta({:__struct__, struct2}, true)
- %__MODULE__{equivalent?: true, left: diff_left, right: diff_right}
+ %__MODULE__{equivalent?: false, left: diff_left, right: diff_right}
end
# Strings
- defp compare_string(left, right, delimiter, env) do
+ defp diff_string(left, right, delimiter, env) do
diff =
cond do
diff_string?(left, right) ->
@@ -767,25 +773,25 @@ defmodule ExUnit.Diff do
# Concat all the literals on `left` and split `right` based on the size of
# that, comparing them and the remaining AST from `left` and the remaining
# string from `right`.
- defp compare_string_concat(left, right, env) do
+ defp diff_string_concat(left, right, env) do
{parsed_left, quoted, indexes, parsed_left_length} = parse_string(left)
- compare_string_concat(parsed_left, quoted, indexes, parsed_left_length, right, env)
+ diff_string_concat(parsed_left, quoted, indexes, parsed_left_length, right, env)
end
- defp compare_string_concat(left, nil, indexes, _left_length, right, env) do
- {parsed_diff, parsed_post_env} = compare_string(left, right, ?\", env)
+ defp diff_string_concat(left, nil, indexes, _left_length, right, env) do
+ {parsed_diff, parsed_post_env} = diff_string(left, right, ?\", env)
left_diff = rebuild_concat_string(parsed_diff.left, nil, indexes)
diff = %__MODULE__{parsed_diff | left: left_diff}
{diff, parsed_post_env}
end
- defp compare_string_concat(left, quoted, indexes, left_length, right, env) do
+ defp diff_string_concat(left, quoted, indexes, left_length, right, env) do
{parsed_right, continue_right} = String.split_at(right, left_length)
- {parsed_diff, parsed_post_env} = compare_string(left, parsed_right, ?\", env)
- {quoted_diff, quoted_post_env} = compare_quoted(quoted, continue_right, parsed_post_env)
+ {parsed_diff, parsed_post_env} = diff_string(left, parsed_right, ?\", env)
+ {quoted_diff, quoted_post_env} = diff(quoted, continue_right, parsed_post_env)
diff =
merge_diff(parsed_diff, quoted_diff, fn left1, left2, right1, right2 ->
@@ -905,8 +911,8 @@ defmodule ExUnit.Diff do
# Numbers
- defp compare_number(left, right, env) do
- {diff, post_env} = compare_string(inspect(left), inspect(right), ?\", env)
+ defp diff_number(left, right, env) do
+ {diff, post_env} = diff_string(inspect(left), inspect(right), ?\", env)
diff_left = remove_diff_container_meta(diff.left)
diff_right = remove_diff_container_meta(diff.right)
{%{diff | left: diff_left, right: diff_right}, post_env}
@@ -1061,13 +1067,11 @@ defmodule ExUnit.Diff do
defp select_list_item_algebra(list) do
short? = Enum.all?(list, &keyword?/1)
-
if short?, do: &keyword_to_algebra/2, else: &to_algebra/2
end
defp select_map_item_to_algebra(list) do
short? = Enum.all?(list, &keyword?/1)
-
if short?, do: &keyword_to_algebra/2, else: &map_item_to_algebra/2
end
@@ -1080,35 +1084,12 @@ defmodule ExUnit.Diff do
# Diff helpers
- defp escape([head | tail]) when is_list(tail) do
- [escape(head) | escape(tail)]
- end
-
- defp escape([head | tail]) do
- [{:|, [], [escape(head), escape(tail)]}]
- end
-
- defp escape({a, b}) do
- {escape(a), escape(b)}
- end
-
- defp escape(tuple) when is_tuple(tuple) do
- list = Tuple.to_list(tuple)
- {:{}, [], escape(list)}
- end
-
- defp escape(%_{} = struct) do
- {:%{}, [], Map.to_list(struct) |> escape()}
- end
-
- defp escape(%{} = map) do
- list = Map.to_list(map)
- {:%{}, [], escape(list)}
- end
-
- defp escape(other) do
- other
- end
+ defp escape([head | tail]) when is_list(tail), do: [escape(head) | escape(tail)]
+ defp escape([head | tail]), do: [{:|, [], [escape(head), escape(tail)]}]
+ defp escape({a, b}), do: {escape(a), escape(b)}
+ defp escape(tuple) when is_tuple(tuple), do: {:{}, [], tuple |> Tuple.to_list() |> escape()}
+ defp escape(%{} = map), do: {:%{}, [], map |> Map.to_list() |> escape()}
+ defp escape(other), do: other
defp merge_diff(%__MODULE__{} = result1, %__MODULE__{} = result2, fun) do
{left, right} = fun.(result1.left, result2.left, result1.right, result2.right)
diff --git a/lib/ex_unit/test/ex_unit/diff_test.exs b/lib/ex_unit/test/ex_unit/diff_test.exs
index 2b35771b9..6a05a10c1 100644
--- a/lib/ex_unit/test/ex_unit/diff_test.exs
+++ b/lib/ex_unit/test/ex_unit/diff_test.exs
@@ -332,6 +332,14 @@ defmodule ExUnit.DiffTest do
)
end
+ test "lists outside of match context" do
+ refute_diff(
+ [:a, {:|, [], [:b, :c]}] == [:a, :b | :c],
+ "[:a, -{:|, [], [:b, :c]}-]",
+ "[:a, +:b+ | +:c+]"
+ )
+ end
+
test "keyword lists" do
assert_diff([file: "nofile", line: 1] = [file: "nofile", line: 1], [])
@@ -371,7 +379,6 @@ defmodule ExUnit.DiffTest do
refute_diff({:a, :b} = {:a}, "{:a, -:b-}", "{:a}")
refute_diff({:ok, value} = {:error, :fatal}, "{-:ok-, value}", "{+:error+, :fatal}")
-
refute_diff({:a, :b} = :a, "-{:a, :b}-", "+:a+")
end
@@ -383,6 +390,7 @@ defmodule ExUnit.DiffTest do
refute_diff({:{}, [], [:a]} == {:a}, "{-:{}-, -[]-, -[:a]-}", "{+:a+}")
refute_diff({:{}, [], [:a]} == :a, "-{:{}, [], [:a]}-", "+:a+")
+ refute_diff({:a, :b, :c} == {:a, :b, :x}, "{:a, :b, -:c-}", "{:a, :b, +:x+}")
end
test "maps" do
@@ -736,6 +744,7 @@ defmodule ExUnit.DiffTest do
defp refute_diff(left, right, expected_left, expected_right, context) do
{diff, _env} = Diff.compute(left, right, context)
+ assert diff.equivalent? == false
diff_left =
diff.left
@@ -758,7 +767,7 @@ defmodule ExUnit.DiffTest do
{diff, env} = Diff.compute(left, right, context)
env_binding = for {{name, _}, value} <- env.current_vars, do: {name, value}
- assert diff.equivalent?
+ assert diff.equivalent? == true
assert env_binding == expected_binding
end