-
Notifications
You must be signed in to change notification settings - Fork 13
/
pipe_fun_one.ex
83 lines (61 loc) · 2.13 KB
/
pipe_fun_one.ex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
defmodule Recode.Task.PipeFunOne do
@shortdoc "Add parentheses to one-arity functions."
@moduledoc """
Add parentheses to one-arity functions.
# preferred
some_string |> String.downcase() |> String.trim()
# not preferred
some_string |> String.downcase |> String.trim
This task rewrites the code when `mix recode` runs with `autocorrect: true`.
"""
use Recode.Task, corrector: true, category: :readability
alias Recode.Issue
alias Recode.Task.PipeFunOne
alias Rewrite.Source
alias Sourceror.Zipper
@defs [:def, :defp, :defmacro, :defmacrop, :defdelegate]
@impl Recode.Task
def run(source, opts) do
{zipper, issues} =
source
|> Source.get(:quoted)
|> Zipper.zip()
|> Zipper.traverse([], fn zipper, issues ->
pipe_fun_one(zipper, issues, opts[:autocorrect])
end)
case opts[:autocorrect] do
true -> Source.update(source, PipeFunOne, :quoted, Zipper.root(zipper))
false -> Source.add_issues(source, issues)
end
end
defp pipe_fun_one(%Zipper{node: {def, _meta, _args}} = zipper, issues, _autocorrect)
when def in @defs do
{Zipper.next(zipper), issues}
end
defp pipe_fun_one(%Zipper{node: {:|>, _meta, _tree}} = zipper, issues, true) do
{Zipper.update(zipper, &update/1), issues}
end
defp pipe_fun_one(%Zipper{node: {:|>, meta, _tree} = ast} = zipper, issues, false) do
case issue?(ast) do
true ->
issue = Issue.new(PipeFunOne, "Use parentheses for one-arity functions in pipes.", meta)
{zipper, [issue | issues]}
false ->
{zipper, issues}
end
end
defp pipe_fun_one(zipper, issues, _autocorrect), do: {zipper, issues}
defp issue?({:|>, _meta1, [_a, {_name, _meta2, nil}]}), do: true
defp issue?({:|>, _meta1, [_a, {_name, meta, []}]}), do: Keyword.get(meta, :no_parens, false)
defp issue?(_ast), do: false
defp update({:|>, meta, [a, b]}) do
{:|>, meta, [a, update(b)]}
end
defp update({name, meta, nil}) do
{name, meta, []}
end
defp update({name, meta, []}) do
{name, Keyword.delete(meta, :no_parens), []}
end
defp update(tree), do: tree
end