spoom 1.2.4 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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