From c1251a34252de09e46f98135f30a6fd90327a234 Mon Sep 17 00:00:00 2001 From: Dorgan Date: Thu, 4 Jan 2024 20:45:47 -0300 Subject: [PATCH] Fix incorrect ranges for `fn` and `->` (#117) Fixes #116 --- lib/sourceror/range.ex | 35 ++++++++++++++++++++++++++++++++++- test/range_test.exs | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+), 1 deletion(-) diff --git a/lib/sourceror/range.ex b/lib/sourceror/range.ex index f6e1fc6..285dc1d 100644 --- a/lib/sourceror/range.ex +++ b/lib/sourceror/range.ex @@ -199,7 +199,31 @@ defmodule Sourceror.Range do get_range(first) end - # Stabs without args + # Stabs without right args + # a -> + defp do_get_range({:->, stab_meta, [left, {:__block__, right_meta, [nil]} = right]}) do + end_pos = + if right_meta[:column] == stab_meta[:column] do + right_meta + |> Keyword.take([:line, :column]) + |> Keyword.update!(:column, &(&1 + 2)) + else + get_range(right).end + end + + start_pos = + case left do + [] -> + Keyword.take(stab_meta, [:line, :column]) + + _ -> + get_range(left).start + end + + %{start: start_pos, end: end_pos} + end + + # Stabs without left args # -> b defp do_get_range({:->, meta, [[], right]}) do start_pos = Keyword.take(meta, [:line, :column]) @@ -425,6 +449,15 @@ defmodule Sourceror.Range do end end + defp get_range_for_node_with_closing_line({:fn, _, _} = quoted) do + start_position = Sourceror.get_start_position(quoted) + end_position = Sourceror.get_end_position(quoted) + + end_position = Keyword.update!(end_position, :column, &(&1 + 3)) + + %{start: start_position, end: end_position} + end + defp get_range_for_node_with_closing_line({_, meta, _} = quoted) do start_position = Sourceror.get_start_position(quoted) end_position = Sourceror.get_end_position(quoted) diff --git a/test/range_test.exs b/test/range_test.exs index e1b867d..6943eeb 100644 --- a/test/range_test.exs +++ b/test/range_test.exs @@ -336,6 +336,48 @@ defmodule SourcerorTest.RangeTest do } end + test "stab without body" do + {:fn, _, [stab]} = Sourceror.parse_string!(~S"fn -> end") + + assert Sourceror.Range.get_range(stab) == %{ + start: [line: 1, column: 4], + end: [line: 1, column: 6] + } + + {:fn, _, [stab]} = + Sourceror.parse_string!(~S""" + fn a -> + end + """) + + assert Sourceror.Range.get_range(stab) == %{ + start: [line: 1, column: 4], + end: [line: 1, column: 8] + } + end + + test "anonymous functions" do + assert to_range(~S"fn -> :ok end") == %{ + start: [line: 1, column: 1], + end: [line: 1, column: 14] + } + + assert to_range(~S""" + fn -> + :ok + end + """) == %{start: [line: 1, column: 1], end: [line: 3, column: 4]} + + assert to_range(~S""" + fn -> end + """) == %{start: [line: 1, column: 1], end: [line: 1, column: 10]} + + assert to_range(~S""" + fn -> + end + """) == %{start: [line: 1, column: 1], end: [line: 2, column: 4]} + end + test "qualified tuples" do assert to_range(~S/Foo.{Bar, Baz}/) == %{ start: [line: 1, column: 1],