spoom 1.2.4 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +54 -55
  3. data/lib/spoom/cli/deadcode.rb +172 -0
  4. data/lib/spoom/cli/helper.rb +20 -0
  5. data/lib/spoom/cli/srb/bump.rb +200 -0
  6. data/lib/spoom/cli/srb/coverage.rb +224 -0
  7. data/lib/spoom/cli/srb/lsp.rb +159 -0
  8. data/lib/spoom/cli/srb/tc.rb +150 -0
  9. data/lib/spoom/cli/srb.rb +27 -0
  10. data/lib/spoom/cli.rb +72 -32
  11. data/lib/spoom/context/git.rb +2 -2
  12. data/lib/spoom/context/sorbet.rb +2 -2
  13. data/lib/spoom/deadcode/definition.rb +11 -0
  14. data/lib/spoom/deadcode/indexer.rb +222 -224
  15. data/lib/spoom/deadcode/location.rb +2 -2
  16. data/lib/spoom/deadcode/plugins/action_mailer.rb +2 -2
  17. data/lib/spoom/deadcode/plugins/action_mailer_preview.rb +19 -0
  18. data/lib/spoom/deadcode/plugins/actionpack.rb +4 -6
  19. data/lib/spoom/deadcode/plugins/active_model.rb +8 -8
  20. data/lib/spoom/deadcode/plugins/active_record.rb +9 -12
  21. data/lib/spoom/deadcode/plugins/active_support.rb +11 -0
  22. data/lib/spoom/deadcode/plugins/base.rb +1 -1
  23. data/lib/spoom/deadcode/plugins/graphql.rb +4 -4
  24. data/lib/spoom/deadcode/plugins/namespaces.rb +2 -4
  25. data/lib/spoom/deadcode/plugins/ruby.rb +8 -17
  26. data/lib/spoom/deadcode/plugins/sorbet.rb +4 -10
  27. data/lib/spoom/deadcode/plugins.rb +1 -0
  28. data/lib/spoom/deadcode/remover.rb +209 -174
  29. data/lib/spoom/deadcode/send.rb +9 -10
  30. data/lib/spoom/deadcode/visitor.rb +755 -0
  31. data/lib/spoom/deadcode.rb +40 -10
  32. data/lib/spoom/file_tree.rb +0 -16
  33. data/lib/spoom/sorbet/errors.rb +1 -1
  34. data/lib/spoom/sorbet/lsp/structures.rb +2 -2
  35. data/lib/spoom/version.rb +1 -1
  36. metadata +19 -15
  37. data/lib/spoom/cli/bump.rb +0 -198
  38. data/lib/spoom/cli/coverage.rb +0 -222
  39. data/lib/spoom/cli/lsp.rb +0 -168
  40. data/lib/spoom/cli/run.rb +0 -148
@@ -3,11 +3,11 @@
3
3
 
4
4
  module Spoom
5
5
  module Deadcode
6
- class Indexer < SyntaxTree::Visitor
6
+ class Indexer < Visitor
7
7
  extend T::Sig
8
8
 
9
9
  sig { returns(String) }
10
- attr_reader :path, :file_name
10
+ attr_reader :path
11
11
 
12
12
  sig { returns(Index) }
13
13
  attr_reader :index
@@ -21,9 +21,9 @@ module Spoom
21
21
  @source = source
22
22
  @index = index
23
23
  @plugins = plugins
24
- @previous_node = T.let(nil, T.nilable(SyntaxTree::Node))
24
+ @previous_node = T.let(nil, T.nilable(Prism::Node))
25
25
  @names_nesting = T.let([], T::Array[String])
26
- @nodes_nesting = T.let([], T::Array[SyntaxTree::Node])
26
+ @nodes_nesting = T.let([], T::Array[Prism::Node])
27
27
  @in_const_field = T.let(false, T::Boolean)
28
28
  @in_opassign = T.let(false, T::Boolean)
29
29
  @in_symbol_literal = T.let(false, T::Boolean)
@@ -31,7 +31,7 @@ module Spoom
31
31
 
32
32
  # Visit
33
33
 
34
- sig { override.params(node: T.nilable(SyntaxTree::Node)).void }
34
+ sig { override.params(node: T.nilable(Prism::Node)).void }
35
35
  def visit(node)
36
36
  return unless node
37
37
 
@@ -41,163 +41,233 @@ module Spoom
41
41
  @previous_node = node
42
42
  end
43
43
 
44
- sig { override.params(node: SyntaxTree::AliasNode).void }
45
- def visit_alias(node)
46
- reference_method(node_string(node.right), node)
44
+ sig { override.params(node: Prism::AliasMethodNode).void }
45
+ def visit_alias_method_node(node)
46
+ reference_method(node.old_name.slice, node)
47
47
  end
48
48
 
49
- sig { override.params(node: SyntaxTree::ARef).void }
50
- def visit_aref(node)
49
+ sig { override.params(node: Prism::AndNode).void }
50
+ def visit_and_node(node)
51
+ reference_method(node.operator_loc.slice, node)
51
52
  super
52
-
53
- reference_method("[]", node)
54
- end
55
-
56
- sig { override.params(node: SyntaxTree::ARefField).void }
57
- def visit_aref_field(node)
58
- super
59
-
60
- reference_method("[]=", node)
61
53
  end
62
54
 
63
- sig { override.params(node: SyntaxTree::ArgBlock).void }
64
- def visit_arg_block(node)
65
- value = node.value
66
-
67
- case value
68
- when SyntaxTree::SymbolLiteral
69
- # If the block call is something like `x.select(&:foo)`, we need to reference the `foo` method
70
- reference_method(symbol_string(value), node)
71
- when SyntaxTree::VCall
72
- # If the block call is something like `x.select { ... }`, we need to visit the block
73
- super
55
+ sig { override.params(node: Prism::BlockArgumentNode).void }
56
+ def visit_block_argument_node(node)
57
+ expression = node.expression
58
+ case expression
59
+ when Prism::SymbolNode
60
+ reference_method(expression.unescaped, expression)
61
+ else
62
+ visit(expression)
74
63
  end
75
64
  end
76
65
 
77
- sig { override.params(node: SyntaxTree::Binary).void }
78
- def visit_binary(node)
79
- super
80
-
81
- op = node.operator
66
+ sig { override.params(node: Prism::CallAndWriteNode).void }
67
+ def visit_call_and_write_node(node)
68
+ visit(node.receiver)
69
+ reference_method(node.read_name.to_s, node)
70
+ reference_method(node.write_name.to_s, node)
71
+ visit(node.value)
72
+ end
82
73
 
83
- # Reference the operator itself
84
- reference_method(op.to_s, node)
74
+ sig { override.params(node: Prism::CallOperatorWriteNode).void }
75
+ def visit_call_operator_write_node(node)
76
+ visit(node.receiver)
77
+ reference_method(node.read_name.to_s, node)
78
+ reference_method(node.write_name.to_s, node)
79
+ visit(node.value)
80
+ end
85
81
 
86
- case op
87
- when :<, :>, :<=, :>=
88
- # For comparison operators, we also reference the `<=>` method
89
- reference_method("<=>", node)
90
- end
82
+ sig { override.params(node: Prism::CallOrWriteNode).void }
83
+ def visit_call_or_write_node(node)
84
+ visit(node.receiver)
85
+ reference_method(node.read_name.to_s, node)
86
+ reference_method(node.write_name.to_s, node)
87
+ visit(node.value)
91
88
  end
92
89
 
93
- sig { override.params(node: SyntaxTree::CallNode).void }
94
- def visit_call(node)
90
+ sig { override.params(node: Prism::CallNode).void }
91
+ def visit_call_node(node)
95
92
  visit_send(
96
93
  Send.new(
97
94
  node: node,
98
- name: node_string(node.message),
95
+ name: node.name.to_s,
99
96
  recv: node.receiver,
100
- args: call_args(node.arguments),
97
+ args: node.arguments&.arguments || [],
98
+ block: node.block,
101
99
  ),
102
100
  )
103
101
  end
104
102
 
105
- sig { override.params(node: SyntaxTree::ClassDeclaration).void }
106
- def visit_class(node)
107
- const_name = node_string(node.constant)
108
- @names_nesting << const_name
109
- define_class(T.must(const_name.split("::").last), @names_nesting.join("::"), node)
103
+ sig { override.params(node: Prism::ClassNode).void }
104
+ def visit_class_node(node)
105
+ constant_path = node.constant_path.slice
106
+
107
+ if constant_path.start_with?("::")
108
+ full_name = constant_path.delete_prefix("::")
109
+
110
+ # We found a top level definition such as `class ::A; end`, we need to reset the name nesting
111
+ old_nesting = @names_nesting.dup
112
+ @names_nesting.clear
113
+ @names_nesting << full_name
110
114
 
111
- # We do not call `super` here because we don't want to visit the `constant` again
112
- visit(node.superclass) if node.superclass
113
- visit(node.bodystmt)
115
+ define_class(T.must(constant_path.split("::").last), full_name, node)
116
+
117
+ # We do not call `super` here because we don't want to visit the `constant` again
118
+ visit(node.superclass) if node.superclass
119
+ visit(node.body)
120
+
121
+ # Restore the name nesting once we finished visited the class
122
+ @names_nesting.clear
123
+ @names_nesting = old_nesting
124
+ else
125
+ @names_nesting << constant_path
126
+ define_class(T.must(constant_path.split("::").last), @names_nesting.join("::"), node)
114
127
 
115
- @names_nesting.pop
128
+ # We do not call `super` here because we don't want to visit the `constant` again
129
+ visit(node.superclass) if node.superclass
130
+ visit(node.body)
131
+
132
+ @names_nesting.pop
133
+ end
116
134
  end
117
135
 
118
- sig { override.params(node: SyntaxTree::Command).void }
119
- def visit_command(node)
120
- visit_send(
121
- Send.new(
122
- node: node,
123
- name: node_string(node.message),
124
- args: call_args(node.arguments),
125
- block: node.block,
126
- ),
127
- )
136
+ sig { override.params(node: Prism::ConstantAndWriteNode).void }
137
+ def visit_constant_and_write_node(node)
138
+ reference_constant(node.name.to_s, node)
139
+ visit(node.value)
128
140
  end
129
141
 
130
- sig { override.params(node: SyntaxTree::CommandCall).void }
131
- def visit_command_call(node)
132
- visit_send(
133
- Send.new(
134
- node: node,
135
- name: node_string(node.message),
136
- recv: node.receiver,
137
- args: call_args(node.arguments),
138
- block: node.block,
139
- ),
140
- )
142
+ sig { override.params(node: Prism::ConstantOperatorWriteNode).void }
143
+ def visit_constant_operator_write_node(node)
144
+ reference_constant(node.name.to_s, node)
145
+ visit(node.value)
146
+ end
147
+
148
+ sig { override.params(node: Prism::ConstantOrWriteNode).void }
149
+ def visit_constant_or_write_node(node)
150
+ reference_constant(node.name.to_s, node)
151
+ visit(node.value)
141
152
  end
142
153
 
143
- sig { override.params(node: SyntaxTree::Const).void }
144
- def visit_const(node)
145
- reference_constant(node.value, node) unless @in_symbol_literal
154
+ sig { override.params(node: Prism::ConstantPathWriteNode).void }
155
+ def visit_constant_path_write_node(node)
156
+ parent = node.target.parent
157
+ name = node.target.child.slice
158
+
159
+ if parent
160
+ visit(parent)
161
+
162
+ parent_name = parent.slice
163
+ full_name = [*@names_nesting, parent_name, name].compact.join("::")
164
+ define_constant(name, full_name, node)
165
+ else
166
+ define_constant(name, name, node)
167
+ end
168
+
169
+ visit(node.value)
146
170
  end
147
171
 
148
- sig { override.params(node: SyntaxTree::ConstPathField).void }
149
- def visit_const_path_field(node)
150
- # We do not call `super` here because we don't want to visit the `constant` again
151
- visit(node.parent)
172
+ sig { override.params(node: Prism::ConstantReadNode).void }
173
+ def visit_constant_read_node(node)
174
+ reference_constant(node.name.to_s, node)
175
+ end
152
176
 
153
- name = node.constant.value
154
- full_name = [*@names_nesting, node_string(node.parent), name].join("::")
177
+ sig { override.params(node: Prism::ConstantWriteNode).void }
178
+ def visit_constant_write_node(node)
179
+ name = node.name.to_s
180
+ full_name = [*@names_nesting, name].join("::")
155
181
  define_constant(name, full_name, node)
182
+ visit(node.value)
156
183
  end
157
184
 
158
- sig { override.params(node: SyntaxTree::DefNode).void }
159
- def visit_def(node)
160
- name = node_string(node.name)
185
+ sig { override.params(node: Prism::DefNode).void }
186
+ def visit_def_node(node)
187
+ name = node.name.to_s
161
188
  define_method(name, [*@names_nesting, name].join("::"), node)
162
189
 
163
190
  super
164
191
  end
165
192
 
166
- sig { override.params(node: SyntaxTree::Field).void }
167
- def visit_field(node)
168
- visit(node.parent)
193
+ sig { override.params(node: Prism::LocalVariableAndWriteNode).void }
194
+ def visit_local_variable_and_write_node(node)
195
+ name = node.name.to_s
196
+ reference_method(name, node)
197
+ reference_method("#{name}=", node)
198
+ visit(node.value)
199
+ end
169
200
 
170
- name = node.name
171
- case name
172
- when SyntaxTree::Const
173
- name = name.value
174
- full_name = [*@names_nesting, node_string(node.parent), name].join("::")
175
- define_constant(name, full_name, node)
176
- when SyntaxTree::Ident
177
- reference_method(name.value, node) if @in_opassign
178
- reference_method("#{name.value}=", node)
179
- end
201
+ sig { override.params(node: Prism::LocalVariableOperatorWriteNode).void }
202
+ def visit_local_variable_operator_write_node(node)
203
+ name = node.name.to_s
204
+ reference_method(name, node)
205
+ reference_method("#{name}=", node)
206
+ visit(node.value)
180
207
  end
181
208
 
182
- sig { override.params(node: SyntaxTree::ModuleDeclaration).void }
183
- def visit_module(node)
184
- const_name = node_string(node.constant)
185
- @names_nesting << const_name
186
- define_module(T.must(const_name.split("::").last), @names_nesting.join("::"), node)
209
+ sig { override.params(node: Prism::LocalVariableOrWriteNode).void }
210
+ def visit_local_variable_or_write_node(node)
211
+ name = node.name.to_s
212
+ reference_method(name, node)
213
+ reference_method("#{name}=", node)
214
+ visit(node.value)
215
+ end
216
+
217
+ sig { override.params(node: Prism::LocalVariableWriteNode).void }
218
+ def visit_local_variable_write_node(node)
219
+ visit(node.value)
220
+ reference_method("#{node.name}=", node)
221
+ end
222
+
223
+ sig { override.params(node: Prism::ModuleNode).void }
224
+ def visit_module_node(node)
225
+ constant_path = node.constant_path.slice
226
+
227
+ if constant_path.start_with?("::")
228
+ full_name = constant_path.delete_prefix("::")
229
+
230
+ # We found a top level definition such as `class ::A; end`, we need to reset the name nesting
231
+ old_nesting = @names_nesting.dup
232
+ @names_nesting.clear
233
+ @names_nesting << full_name
234
+
235
+ define_module(T.must(constant_path.split("::").last), full_name, node)
236
+
237
+ visit(node.body)
238
+
239
+ # Restore the name nesting once we finished visited the class
240
+ @names_nesting.clear
241
+ @names_nesting = old_nesting
242
+ else
243
+ @names_nesting << constant_path
244
+ define_module(T.must(constant_path.split("::").last), @names_nesting.join("::"), node)
245
+
246
+ # We do not call `super` here because we don't want to visit the `constant` again
247
+ visit(node.body)
187
248
 
188
- # We do not call `super` here because we don't want to visit the `constant` again
189
- visit(node.bodystmt)
249
+ @names_nesting.pop
250
+ end
251
+ end
190
252
 
191
- @names_nesting.pop
253
+ sig { override.params(node: Prism::MultiWriteNode).void }
254
+ def visit_multi_write_node(node)
255
+ node.lefts.each do |const|
256
+ case const
257
+ when Prism::ConstantTargetNode, Prism::ConstantPathTargetNode
258
+ name = const.slice
259
+ define_constant(T.must(name.split("::").last), [*@names_nesting, name].join("::"), const)
260
+ when Prism::LocalVariableTargetNode
261
+ reference_method("#{const.name}=", node)
262
+ end
263
+ end
264
+ visit(node.value)
192
265
  end
193
266
 
194
- sig { override.params(node: SyntaxTree::OpAssign).void }
195
- def visit_opassign(node)
196
- # Both `FOO = x` and `FOO += x` yield a VarField node, but the former is a constant definition and the latter is
197
- # a constant reference. We need to distinguish between the two cases.
198
- @in_opassign = true
267
+ sig { override.params(node: Prism::OrNode).void }
268
+ def visit_or_node(node)
269
+ reference_method(node.operator_loc.slice, node)
199
270
  super
200
- @in_opassign = false
201
271
  end
202
272
 
203
273
  sig { params(send: Send).void }
@@ -207,23 +277,23 @@ module Spoom
207
277
  case send.name
208
278
  when "attr_reader"
209
279
  send.args.each do |arg|
210
- next unless arg.is_a?(SyntaxTree::SymbolLiteral)
280
+ next unless arg.is_a?(Prism::SymbolNode)
211
281
 
212
- name = symbol_string(arg)
282
+ name = arg.unescaped
213
283
  define_attr_reader(name, [*@names_nesting, name].join("::"), arg)
214
284
  end
215
285
  when "attr_writer"
216
286
  send.args.each do |arg|
217
- next unless arg.is_a?(SyntaxTree::SymbolLiteral)
287
+ next unless arg.is_a?(Prism::SymbolNode)
218
288
 
219
- name = symbol_string(arg)
289
+ name = arg.unescaped
220
290
  define_attr_writer("#{name}=", "#{[*@names_nesting, name].join("::")}=", arg)
221
291
  end
222
292
  when "attr_accessor"
223
293
  send.args.each do |arg|
224
- next unless arg.is_a?(SyntaxTree::SymbolLiteral)
294
+ next unless arg.is_a?(Prism::SymbolNode)
225
295
 
226
- name = symbol_string(arg)
296
+ name = arg.unescaped
227
297
  full_name = [*@names_nesting, name].join("::")
228
298
  define_attr_reader(name, full_name, arg)
229
299
  define_attr_writer("#{name}=", "#{full_name}=", arg)
@@ -234,50 +304,21 @@ module Spoom
234
304
  end
235
305
 
236
306
  reference_method(send.name, send.node)
237
- visit_all(send.args)
238
- visit(send.block)
239
- end
240
- end
241
-
242
- sig { override.params(node: SyntaxTree::SymbolLiteral).void }
243
- def visit_symbol_literal(node)
244
- # Something like `:FOO` will yield a Const node but we do not want to treat it as a constant reference.
245
- # So we need to distinguish between the two cases.
246
- @in_symbol_literal = true
247
- super
248
- @in_symbol_literal = false
249
- end
250
307
 
251
- sig { override.params(node: SyntaxTree::TopConstField).void }
252
- def visit_top_const_field(node)
253
- define_constant(node.constant.value, node.constant.value, node)
254
- end
255
-
256
- sig { override.params(node: SyntaxTree::VarField).void }
257
- def visit_var_field(node)
258
- value = node.value
259
- case value
260
- when SyntaxTree::Const
261
- if @in_opassign
262
- reference_constant(value.value, node)
263
- else
264
- name = value.value
265
- define_constant(name, [*@names_nesting, name].join("::"), node)
308
+ case send.name
309
+ when "<", ">", "<=", ">="
310
+ # For comparison operators, we also reference the `<=>` method
311
+ reference_method("<=>", send.node)
266
312
  end
267
- when SyntaxTree::Ident
268
- reference_method(value.value, node) if @in_opassign
269
- reference_method("#{value.value}=", node)
270
- end
271
- end
272
313
 
273
- sig { override.params(node: SyntaxTree::VCall).void }
274
- def visit_vcall(node)
275
- visit_send(Send.new(node: node, name: node_string(node.value)))
314
+ visit_all(send.args)
315
+ visit(send.block)
316
+ end
276
317
  end
277
318
 
278
319
  # Definition indexing
279
320
 
280
- sig { params(name: String, full_name: String, node: SyntaxTree::Node).void }
321
+ sig { params(name: String, full_name: String, node: Prism::Node).void }
281
322
  def define_attr_reader(name, full_name, node)
282
323
  definition = Definition.new(
283
324
  kind: Definition::Kind::AttrReader,
@@ -289,7 +330,7 @@ module Spoom
289
330
  @plugins.each { |plugin| plugin.internal_on_define_accessor(self, definition) }
290
331
  end
291
332
 
292
- sig { params(name: String, full_name: String, node: SyntaxTree::Node).void }
333
+ sig { params(name: String, full_name: String, node: Prism::Node).void }
293
334
  def define_attr_writer(name, full_name, node)
294
335
  definition = Definition.new(
295
336
  kind: Definition::Kind::AttrWriter,
@@ -301,7 +342,7 @@ module Spoom
301
342
  @plugins.each { |plugin| plugin.internal_on_define_accessor(self, definition) }
302
343
  end
303
344
 
304
- sig { params(name: String, full_name: String, node: SyntaxTree::Node).void }
345
+ sig { params(name: String, full_name: String, node: Prism::Node).void }
305
346
  def define_class(name, full_name, node)
306
347
  definition = Definition.new(
307
348
  kind: Definition::Kind::Class,
@@ -313,7 +354,7 @@ module Spoom
313
354
  @plugins.each { |plugin| plugin.internal_on_define_class(self, definition) }
314
355
  end
315
356
 
316
- sig { params(name: String, full_name: String, node: SyntaxTree::Node).void }
357
+ sig { params(name: String, full_name: String, node: Prism::Node).void }
317
358
  def define_constant(name, full_name, node)
318
359
  definition = Definition.new(
319
360
  kind: Definition::Kind::Constant,
@@ -325,7 +366,7 @@ module Spoom
325
366
  @plugins.each { |plugin| plugin.internal_on_define_constant(self, definition) }
326
367
  end
327
368
 
328
- sig { params(name: String, full_name: String, node: SyntaxTree::Node).void }
369
+ sig { params(name: String, full_name: String, node: Prism::Node).void }
329
370
  def define_method(name, full_name, node)
330
371
  definition = Definition.new(
331
372
  kind: Definition::Kind::Method,
@@ -337,7 +378,7 @@ module Spoom
337
378
  @plugins.each { |plugin| plugin.internal_on_define_method(self, definition) }
338
379
  end
339
380
 
340
- sig { params(name: String, full_name: String, node: SyntaxTree::Node).void }
381
+ sig { params(name: String, full_name: String, node: Prism::Node).void }
341
382
  def define_module(name, full_name, node)
342
383
  definition = Definition.new(
343
384
  kind: Definition::Kind::Module,
@@ -351,19 +392,19 @@ module Spoom
351
392
 
352
393
  # Reference indexing
353
394
 
354
- sig { params(name: String, node: SyntaxTree::Node).void }
395
+ sig { params(name: String, node: Prism::Node).void }
355
396
  def reference_constant(name, node)
356
397
  @index.reference(Reference.new(name: name, kind: Reference::Kind::Constant, location: node_location(node)))
357
398
  end
358
399
 
359
- sig { params(name: String, node: SyntaxTree::Node).void }
400
+ sig { params(name: String, node: Prism::Node).void }
360
401
  def reference_method(name, node)
361
402
  @index.reference(Reference.new(name: name, kind: Reference::Kind::Method, location: node_location(node)))
362
403
  end
363
404
 
364
405
  # Context
365
406
 
366
- sig { returns(SyntaxTree::Node) }
407
+ sig { returns(Prism::Node) }
367
408
  def current_node
368
409
  T.must(@nodes_nesting.last)
369
410
  end
@@ -377,33 +418,19 @@ module Spoom
377
418
  nil
378
419
  end
379
420
 
380
- sig { returns(T.nilable(SyntaxTree::ClassDeclaration)) }
421
+ sig { returns(T.nilable(Prism::ClassNode)) }
381
422
  def nesting_class
382
- nesting_node(SyntaxTree::ClassDeclaration)
423
+ nesting_node(Prism::ClassNode)
383
424
  end
384
425
 
385
- sig { returns(T.nilable(SyntaxTree::BlockNode)) }
426
+ sig { returns(T.nilable(Prism::BlockNode)) }
386
427
  def nesting_block
387
- nesting_node(SyntaxTree::BlockNode)
388
- end
389
-
390
- sig { returns(T.nilable(SyntaxTree::MethodAddBlock)) }
391
- def nesting_block_call
392
- nesting_node(SyntaxTree::MethodAddBlock)
428
+ nesting_node(Prism::BlockNode)
393
429
  end
394
430
 
395
- sig { returns(T.nilable(String)) }
396
- def nesting_block_call_name
397
- block = nesting_block_call
398
- return unless block.is_a?(SyntaxTree::MethodAddBlock)
399
-
400
- call = block.call
401
- case call
402
- when SyntaxTree::ARef
403
- node_string(call.collection)
404
- when SyntaxTree::CallNode, SyntaxTree::Command, SyntaxTree::CommandCall
405
- node_string(call.message)
406
- end
431
+ sig { returns(T.nilable(Prism::CallNode)) }
432
+ def nesting_call
433
+ nesting_node(Prism::CallNode)
407
434
  end
408
435
 
409
436
  sig { returns(T.nilable(String)) }
@@ -411,7 +438,7 @@ module Spoom
411
438
  nesting_class = self.nesting_class
412
439
  return unless nesting_class
413
440
 
414
- node_string(nesting_class.constant)
441
+ nesting_class.name.to_s
415
442
  end
416
443
 
417
444
  sig { returns(T.nilable(String)) }
@@ -419,52 +446,23 @@ module Spoom
419
446
  nesting_class_superclass = nesting_class&.superclass
420
447
  return unless nesting_class_superclass
421
448
 
422
- node_string(nesting_class_superclass).delete_prefix("::")
449
+ nesting_class_superclass.slice.delete_prefix("::")
423
450
  end
424
451
 
425
452
  sig { returns(T.nilable(String)) }
426
453
  def last_sig
427
- return unless @previous_node.is_a?(SyntaxTree::MethodAddBlock)
454
+ previous_call = @previous_node
455
+ return unless previous_call.is_a?(Prism::CallNode)
456
+ return unless previous_call.name == :sig
428
457
 
429
- node_string(@previous_node)
458
+ previous_call.slice
430
459
  end
431
460
 
432
461
  # Node utils
433
462
 
434
- sig { params(node: T.any(Symbol, SyntaxTree::Node)).returns(String) }
435
- def node_string(node)
436
- case node
437
- when Symbol
438
- node.to_s
439
- else
440
- T.must(@source[node.location.start_char...node.location.end_char])
441
- end
442
- end
443
-
444
- sig { params(node: SyntaxTree::Node).returns(Location) }
463
+ sig { params(node: Prism::Node).returns(Location) }
445
464
  def node_location(node)
446
- Location.from_syntax_tree(@path, node.location)
447
- end
448
-
449
- sig { params(node: SyntaxTree::Node).returns(String) }
450
- def symbol_string(node)
451
- node_string(node).delete_prefix(":")
452
- end
453
-
454
- sig do
455
- params(
456
- node: T.any(SyntaxTree::Args, SyntaxTree::ArgParen, SyntaxTree::ArgsForward, NilClass),
457
- ).returns(T::Array[SyntaxTree::Node])
458
- end
459
- def call_args(node)
460
- case node
461
- when SyntaxTree::ArgParen
462
- call_args(node.arguments)
463
- when SyntaxTree::Args
464
- node.parts
465
- else
466
- []
467
- end
465
+ Location.from_prism(@path, node.location)
468
466
  end
469
467
  end
470
468
  end
@@ -30,8 +30,8 @@ module Spoom
30
30
  new(file, start_line.to_i, start_column.to_i, end_line.to_i, end_column.to_i)
31
31
  end
32
32
 
33
- sig { params(file: String, location: SyntaxTree::Location).returns(Location) }
34
- def from_syntax_tree(file, location)
33
+ sig { params(file: String, location: Prism::Location).returns(Location) }
34
+ def from_prism(file, location)
35
35
  new(file, location.start_line, location.start_column, location.end_line, location.end_column)
36
36
  end
37
37
  end
@@ -11,8 +11,8 @@ module Spoom
11
11
  def on_send(indexer, send)
12
12
  return unless send.recv.nil? && ActionPack::CALLBACKS.include?(send.name)
13
13
 
14
- send.each_arg(SyntaxTree::SymbolLiteral) do |arg|
15
- indexer.reference_method(indexer.node_string(arg.value), send.node)
14
+ send.each_arg(Prism::SymbolNode) do |arg|
15
+ indexer.reference_method(arg.unescaped, send.node)
16
16
  end
17
17
  end
18
18
  end