Skip to content

Commit 569ef85

Browse files
committed
Rewrite the code with pattern matching
1 parent 7900650 commit 569ef85

File tree

1 file changed

+66
-98
lines changed

1 file changed

+66
-98
lines changed

lib/power_assert/parser.rb

Lines changed: 66 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -68,113 +68,81 @@ class Branch < Array
6868
# +--------+
6969
#
7070
def extract_idents(sexp)
71-
tag, * = sexp
72-
case tag
73-
when :arg_paren, :assoc_splat, :fcall, :hash, :method_add_block, :string_literal, :return
74-
extract_idents(sexp[1])
75-
when :assign, :massign
76-
extract_idents(sexp[2])
77-
when :opassign
78-
_, _, (_, op_name, (_, op_column)), s0 = sexp
79-
extract_idents(s0) + [Ident[:method, op_name.sub(/=\z/, ''), op_column]]
80-
when :dyna_symbol
81-
if sexp[1][0].kind_of?(Symbol)
82-
# sexp[1] can be [:string_content, [..]] while parsing { "a": 1 }
83-
extract_idents(sexp[1])
84-
else
85-
sexp[1].flat_map {|s| extract_idents(s) }
86-
end
87-
when :assoclist_from_args, :bare_assoc_hash, :paren, :string_embexpr,
88-
:regexp_literal, :xstring_literal
89-
sexp[1].flat_map {|s| extract_idents(s) }
90-
when :command
91-
[sexp[2], sexp[1]].flat_map {|s| extract_idents(s) }
92-
when :assoc_new, :dot2, :dot3, :string_content
93-
sexp[1..-1].flat_map {|s| extract_idents(s) }
94-
when :unary
95-
handle_columnless_ident([], sexp[1], extract_idents(sexp[2]))
96-
when :binary
97-
op = sexp[2]
98-
if AND_OR_OPS.include?(op)
99-
extract_idents(sexp[1]) + [Branch[extract_idents(sexp[3]), []]]
100-
else
101-
handle_columnless_ident(extract_idents(sexp[1]), op, extract_idents(sexp[3]))
102-
end
103-
when :call
104-
_, recv, (op_sym, op_name, _), method = sexp
71+
case sexp
72+
in [:arg_paren | :assoc_splat | :fcall | :hash | :method_add_block | :string_literal | :return, s, *]
73+
extract_idents(s)
74+
in [:assign | :massign, _, s]
75+
extract_idents(s)
76+
in [:opassign, _, [_, op_name, [_, op_column]], s]
77+
extract_idents(s) + [Ident[:method, op_name.sub(/=\z/, ''), op_column]]
78+
in [:dyna_symbol, [Symbol, *] => s]
79+
# s can be [:string_content, [..]] while parsing an expression like { "a": 1 }
80+
extract_idents(s)
81+
in [:dyna_symbol, ss]
82+
ss.flat_map {|s| extract_idents(s) }
83+
in [:assoclist_from_args | :bare_assoc_hash | :paren | :string_embexpr | :regexp_literal | :xstring_literal, ss, *]
84+
ss.flat_map {|s| extract_idents(s) }
85+
in [:command, s0, s1]
86+
[s1, s0].flat_map {|s| extract_idents(s) }
87+
in [:assoc_new | :dot2 | :dot3 | :string_content, *ss]
88+
ss.flat_map {|s| extract_idents(s) }
89+
in [:unary, mid, s]
90+
handle_columnless_ident([], mid, extract_idents(s))
91+
in [:binary, s0, op, s1] if AND_OR_OPS.include?(op)
92+
extract_idents(s0) + [Branch[extract_idents(s1), []]]
93+
in [:binary, s0, op, s1]
94+
handle_columnless_ident(extract_idents(s0), op, extract_idents(s1))
95+
in [:call, recv, [op_sym, op_name, _], method]
10596
with_safe_op = ((op_sym == :@op and op_name == '&.') or op_sym == :"&.")
10697
if method == :call
10798
handle_columnless_ident(extract_idents(recv), :call, [], with_safe_op)
10899
else
109100
extract_idents(recv) + (with_safe_op ? [Branch[extract_idents(method), []]] : extract_idents(method))
110101
end
111-
when :array
112-
sexp[1] ? sexp[1].flat_map {|s| extract_idents(s) } : []
113-
when :command_call
114-
[sexp[1], sexp[4], sexp[3]].flat_map {|s| extract_idents(s) }
115-
when :aref
116-
handle_columnless_ident(extract_idents(sexp[1]), :[], extract_idents(sexp[2]))
117-
when :method_add_arg
118-
idents = extract_idents(sexp[1])
119-
if idents.empty?
120-
# idents may be empty(e.g. ->{}.())
121-
extract_idents(sexp[2])
122-
else
123-
if idents[-1].kind_of?(Branch) and idents[-1][1].empty?
124-
# Safe navigation operator is used. See :call clause also.
125-
idents[0..-2] + [Branch[extract_idents(sexp[2]) + idents[-1][0], []]]
126-
else
127-
idents[0..-2] + extract_idents(sexp[2]) + [idents[-1]]
128-
end
129-
end
130-
when :args_add_block
131-
_, (tag, ss0, *ss1), _ = sexp
132-
if tag == :args_add_star
133-
(ss0 + ss1).flat_map {|s| extract_idents(s) }
134-
else
135-
sexp[1].flat_map {|s| extract_idents(s) }
102+
in [:array, ss]
103+
ss ? ss.flat_map {|s| extract_idents(s) } : []
104+
in [:command_call, s0, _, s1, s2]
105+
[s0, s2, s1].flat_map {|s| extract_idents(s) }
106+
in [:aref, s0, s1]
107+
handle_columnless_ident(extract_idents(s0), :[], extract_idents(s1))
108+
in [:method_add_arg, s0, s1]
109+
case extract_idents(s0)
110+
in []
111+
# idents(s0) may be empty(e.g. ->{}.())
112+
extract_idents(s1)
113+
in [*is0, Branch[is1, []]]
114+
# Safe navigation operator is used. See :call clause also.
115+
is0 + [Branch[extract_idents(s1) + is1, []]]
116+
in [*is, i]
117+
is + extract_idents(s1) + [i]
136118
end
137-
when :vcall
138-
_, (tag, name, (_, column)) = sexp
139-
if tag == :@ident
140-
[Ident[@proc_local_variables.include?(name) ? :ref : :method, name, column]]
141-
else
142-
[]
143-
end
144-
when :program
145-
_, ((tag0, (tag1, (tag2, (tag3, mname, _)), _), (tag4, _, ss))) = sexp
146-
if tag0 == :method_add_block and tag1 == :method_add_arg and tag2 == :fcall and
147-
(tag3 == :@ident or tag3 == :@const) and mname == @assertion_method_name and (tag4 == :brace_block or tag4 == :do_block)
148-
ss.flat_map {|s| extract_idents(s) }
149-
else
150-
_, (s0, *) = sexp
151-
extract_idents(s0)
152-
end
153-
when :ifop
154-
_, s0, s1, s2 = sexp
119+
in [:args_add_block, [:args_add_star, ss0, *ss1], _]
120+
(ss0 + ss1).flat_map {|s| extract_idents(s) }
121+
in [:args_add_block, ss, _]
122+
ss.flat_map {|s| extract_idents(s) }
123+
in [:vcall, [:@ident, name, [_, column]]]
124+
[Ident[@proc_local_variables.include?(name) ? :ref : :method, name, column]]
125+
in [:vcall, _]
126+
[]
127+
in [:program, [[:method_add_block, [:method_add_arg, [:fcall, [:@ident | :@const, ^@assertion_method_name, _]], _], [:brace_block | :do_block, _, ss]]]]
128+
ss.flat_map {|s| extract_idents(s) }
129+
in [:program, [s, *]]
130+
extract_idents(s)
131+
in [:ifop, s0, s1, s2]
155132
[*extract_idents(s0), Branch[extract_idents(s1), extract_idents(s2)]]
156-
when :if, :unless
157-
_, s0, ss0, (_, ss1) = sexp
158-
[*extract_idents(s0), Branch[ss0.flat_map {|s| extract_idents(s) }, ss1 ? ss1.flat_map {|s| extract_idents(s) } : []]]
159-
when :if_mod, :unless_mod
160-
_, s0, s1 = sexp
133+
in [:if | :unless, s0, ss0, [_, ss1]]
134+
[*extract_idents(s0), Branch[ss0.flat_map {|s| extract_idents(s) }, ss1.flat_map {|s| extract_idents(s) }]]
135+
in [:if | :unless, s0, ss0, _]
136+
[*extract_idents(s0), Branch[ss0.flat_map {|s| extract_idents(s) }, []]]
137+
in [:if_mod | :unless_mod, s0, s1]
161138
[*extract_idents(s0), Branch[extract_idents(s1), []]]
162-
when :var_ref, :var_field
163-
_, (tag, ref_name, (_, column)) = sexp
164-
case tag
165-
when :@kw
166-
if ref_name == 'self'
167-
[Ident[:ref, 'self', column]]
168-
else
169-
[]
170-
end
171-
when :@ident, :@const, :@cvar, :@ivar, :@gvar
172-
[Ident[:ref, ref_name, column]]
173-
else
174-
[]
175-
end
176-
when :@ident, :@const, :@op
177-
_, method_name, (_, column) = sexp
139+
in [:var_ref | :var_field, [:@kw, 'self', [_, column]]]
140+
[Ident[:ref, 'self', column]]
141+
in [:var_ref | :var_field, [:@ident | :@const | :@cvar | :@ivar | :@gvar, ref_name, [_, column]]]
142+
[Ident[:ref, ref_name, column]]
143+
in [:var_ref | :var_field, _]
144+
[]
145+
in [:@ident | :@const | :@op, method_name, [_, column]]
178146
[Ident[:method, method_name, column]]
179147
else
180148
[]

0 commit comments

Comments
 (0)