spoom 1.8.7 → 1.8.8

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e5c2341851ed3a30add3601c9ea08a4913b9ecebe17c7da96002de914874d3d8
4
- data.tar.gz: 127b2b8f6771f0f75d09d7d7d1bd269c069f4d5776e4a7bd5e7fdf92db9d8f6e
3
+ metadata.gz: f156e3fd1596713d8fb893ba5e4e0cdc127fc9ee1a21006c751773178e4eb1d3
4
+ data.tar.gz: 84ce5c28958b0fe1b45251336dc283e005738b3c0d280a7f8cb5b643d4b8e8da
5
5
  SHA512:
6
- metadata.gz: 6eaaabb907a1d9e625dc44756b9ddcaae59270b96a080c37331979d2450403e3bc6f6b72c483db782c49983799f4dd7f7ed0cbe114462349ff30e356d6779039
7
- data.tar.gz: 80b4dae7fd1c464b80fdfa4345f57d02512391f0d500cc62b4ea22aac2491074fd32dd471e225e1c5e25fd8d196bcf779e2c561da4c4a0de4332989c133b6a7f
6
+ metadata.gz: 98c8db47ce06755ac7ca5b3426f4f0413d611297240f28d19e767f3c76230c5ed963f54e51b092b6d5361f41b4c7a000423355ef4d4eb445d6ebe334c870c5f5
7
+ data.tar.gz: 4c7a33cef72bc373fe5f7bd9f3230669d301baab006a26f5ce7c0483d627e3dd01e30b5a215282d3c537c77b10b5cc20eff739259bec6bfbb55851b6a654eb39
@@ -106,7 +106,7 @@ module Spoom
106
106
  index.definitions.each do |name, definitions|
107
107
  $stderr.puts " #{blue(name)}"
108
108
  definitions.each do |definition|
109
- $stderr.puts " #{yellow(definition.kind.serialize)} #{gray(definition.location.to_s)}"
109
+ $stderr.puts " #{yellow(definition.kind.to_s)} #{gray(definition.location.to_s)}"
110
110
  end
111
111
  end
112
112
  $stderr.puts
@@ -116,7 +116,7 @@ module Spoom
116
116
  $stderr.puts "\nReferences:"
117
117
  index.references.values.flatten.sort_by(&:name).each do |references|
118
118
  name = references.name
119
- kind = references.kind.serialize
119
+ kind = references.kind.to_s
120
120
  loc = references.location.to_s
121
121
  $stderr.puts " #{blue(name)} #{yellow(kind)} #{gray(loc)}"
122
122
  end
@@ -156,11 +156,11 @@ module Spoom
156
156
  end.filter(&:commit_timestamp).sort_by!(&:commit_timestamp)
157
157
 
158
158
  palette = Spoom::Coverage::D3::ColorPalette.new(
159
- ignore: options[:color_ignore],
160
- false: options[:color_false],
161
- true: options[:color_true],
162
- strict: options[:color_strict],
163
- strong: options[:color_strong],
159
+ ignore_color: options[:color_ignore],
160
+ false_color: options[:color_false],
161
+ true_color: options[:color_true],
162
+ strict_color: options[:color_strict],
163
+ strong_color: options[:color_strong],
164
164
  )
165
165
 
166
166
  report = Spoom::Coverage.report(context, snapshots, palette: palette)
data/lib/spoom/colors.rb CHANGED
@@ -2,34 +2,35 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module Spoom
5
- class Color < T::Enum
6
- enums do
7
- CLEAR = new("\e[0m")
8
- BOLD = new("\e[1m")
5
+ class Color
6
+ #: String
7
+ attr_reader :ansi_code
9
8
 
10
- BLACK = new("\e[30m")
11
- RED = new("\e[31m")
12
- GREEN = new("\e[32m")
13
- YELLOW = new("\e[33m")
14
- BLUE = new("\e[34m")
15
- MAGENTA = new("\e[35m")
16
- CYAN = new("\e[36m")
17
- WHITE = new("\e[37m")
18
-
19
- LIGHT_BLACK = new("\e[90m")
20
- LIGHT_RED = new("\e[91m")
21
- LIGHT_GREEN = new("\e[92m")
22
- LIGHT_YELLOW = new("\e[93m")
23
- LIGHT_BLUE = new("\e[94m")
24
- LIGHT_MAGENTA = new("\e[95m")
25
- LIGHT_CYAN = new("\e[96m")
26
- LIGHT_WHITE = new("\e[97m")
9
+ #: (String) -> void
10
+ def initialize(ansi_code)
11
+ @ansi_code = ansi_code
27
12
  end
28
13
 
29
- #: -> String
30
- def ansi_code
31
- serialize
32
- end
14
+ CLEAR = new("\e[0m") #: Color
15
+ BOLD = new("\e[1m") #: Color
16
+
17
+ BLACK = new("\e[30m") #: Color
18
+ RED = new("\e[31m") #: Color
19
+ GREEN = new("\e[32m") #: Color
20
+ YELLOW = new("\e[33m") #: Color
21
+ BLUE = new("\e[34m") #: Color
22
+ MAGENTA = new("\e[35m") #: Color
23
+ CYAN = new("\e[36m") #: Color
24
+ WHITE = new("\e[37m") #: Color
25
+
26
+ LIGHT_BLACK = new("\e[90m") #: Color
27
+ LIGHT_RED = new("\e[91m") #: Color
28
+ LIGHT_GREEN = new("\e[92m") #: Color
29
+ LIGHT_YELLOW = new("\e[93m") #: Color
30
+ LIGHT_BLUE = new("\e[94m") #: Color
31
+ LIGHT_MAGENTA = new("\e[95m") #: Color
32
+ LIGHT_CYAN = new("\e[96m") #: Color
33
+ LIGHT_WHITE = new("\e[97m") #: Color
33
34
  end
34
35
 
35
36
  module Colorize
@@ -4,11 +4,26 @@
4
4
  require "shellwords"
5
5
 
6
6
  module Spoom
7
- class ExecResult < T::Struct
8
- const :out, String
9
- const :err, T.nilable(String)
10
- const :status, T::Boolean
11
- const :exit_code, Integer
7
+ class ExecResult
8
+ #: String
9
+ attr_reader :out
10
+
11
+ #: String?
12
+ attr_reader :err
13
+
14
+ #: bool
15
+ attr_reader :status
16
+
17
+ #: Integer
18
+ attr_reader :exit_code
19
+
20
+ #: (out: String, status: bool, exit_code: Integer, ?err: String?) -> void
21
+ def initialize(out:, status:, exit_code:, err: nil)
22
+ @out = out
23
+ @err = err
24
+ @status = status
25
+ @exit_code = exit_code
26
+ end
12
27
 
13
28
  #: -> String
14
29
  def to_s
@@ -3,7 +3,7 @@
3
3
 
4
4
  module Spoom
5
5
  module Git
6
- class Commit < T::Struct
6
+ class Commit
7
7
  class << self
8
8
  # Parse a line formatted as `%h %at` into a `Commit`
9
9
  #: (String string) -> Commit?
@@ -16,8 +16,17 @@ module Spoom
16
16
  end
17
17
  end
18
18
 
19
- const :sha, String
20
- const :time, Time
19
+ #: String
20
+ attr_reader :sha
21
+
22
+ #: Time
23
+ attr_reader :time
24
+
25
+ #: (sha: String, time: Time) -> void
26
+ def initialize(sha:, time:)
27
+ @sha = sha
28
+ @time = time
29
+ end
21
30
 
22
31
  #: -> Integer
23
32
  def timestamp
@@ -63,17 +63,17 @@ module Spoom
63
63
  function strictnessColor(strictness) {
64
64
  switch(strictness) {
65
65
  case "ignore":
66
- return "#{palette.ignore}";
66
+ return "#{palette.ignore_color}";
67
67
  case "false":
68
- return "#{palette.false}";
68
+ return "#{palette.false_color}";
69
69
  case "true":
70
- return "#{palette.true}";
70
+ return "#{palette.true_color}";
71
71
  case "strict":
72
- return "#{palette.strict}";
72
+ return "#{palette.strict_color}";
73
73
  case "strong":
74
- return "#{palette.strong}";
74
+ return "#{palette.strong_color}";
75
75
  }
76
- return "#{palette.false}";
76
+ return "#{palette.false_color}";
77
77
  }
78
78
 
79
79
  function toPercent(value, sum) {
@@ -98,12 +98,36 @@ module Spoom
98
98
  end
99
99
  end
100
100
 
101
- class ColorPalette < T::Struct
102
- prop :ignore, String
103
- prop :false, String
104
- prop :true, String
105
- prop :strict, String
106
- prop :strong, String
101
+ class ColorPalette
102
+ #: String
103
+ attr_accessor :ignore_color
104
+
105
+ #: String
106
+ attr_accessor :false_color
107
+
108
+ #: String
109
+ attr_accessor :true_color
110
+
111
+ #: String
112
+ attr_accessor :strict_color
113
+
114
+ #: String
115
+ attr_accessor :strong_color
116
+
117
+ #: (
118
+ #| ignore_color: String,
119
+ #| false_color: String,
120
+ #| true_color: String,
121
+ #| strict_color: String,
122
+ #| strong_color: String
123
+ #| ) -> void
124
+ def initialize(ignore_color:, false_color:, true_color:, strict_color:, strong_color:)
125
+ @ignore_color = ignore_color
126
+ @false_color = false_color
127
+ @true_color = true_color
128
+ @strict_color = strict_color
129
+ @strong_color = strong_color
130
+ end
107
131
  end
108
132
  end
109
133
  end
@@ -3,26 +3,126 @@
3
3
 
4
4
  module Spoom
5
5
  module Coverage
6
- class Snapshot < T::Struct
7
- prop :timestamp, Integer, default: Time.new.getutc.to_i
8
- prop :version_static, T.nilable(String), default: nil
9
- prop :version_runtime, T.nilable(String), default: nil
10
- prop :duration, Integer, default: 0
11
- prop :commit_sha, T.nilable(String), default: nil
12
- prop :commit_timestamp, T.nilable(Integer), default: nil
13
- prop :files, Integer, default: 0
14
- prop :rbi_files, Integer, default: 0
15
- prop :modules, Integer, default: 0
16
- prop :classes, Integer, default: 0
17
- prop :singleton_classes, Integer, default: 0
18
- prop :methods_without_sig, Integer, default: 0
19
- prop :methods_with_sig, Integer, default: 0
20
- prop :calls_untyped, Integer, default: 0
21
- prop :calls_typed, Integer, default: 0
22
- prop :sigils, T::Hash[String, Integer], default: Hash.new(0)
23
- prop :methods_with_sig_excluding_rbis, Integer, default: 0
24
- prop :methods_without_sig_excluding_rbis, Integer, default: 0
25
- prop :sigils_excluding_rbis, T::Hash[String, Integer], default: Hash.new(0)
6
+ class Snapshot
7
+ #: Integer
8
+ attr_accessor :timestamp
9
+
10
+ #: String?
11
+ attr_accessor :version_static
12
+
13
+ #: String?
14
+ attr_accessor :version_runtime
15
+
16
+ #: Integer
17
+ attr_accessor :duration
18
+
19
+ #: String?
20
+ attr_accessor :commit_sha
21
+
22
+ #: Integer?
23
+ attr_accessor :commit_timestamp
24
+
25
+ #: Integer
26
+ attr_accessor :files
27
+
28
+ #: Integer
29
+ attr_accessor :rbi_files
30
+
31
+ #: Integer
32
+ attr_accessor :modules
33
+
34
+ #: Integer
35
+ attr_accessor :classes
36
+
37
+ #: Integer
38
+ attr_accessor :singleton_classes
39
+
40
+ #: Integer
41
+ attr_accessor :methods_without_sig
42
+
43
+ #: Integer
44
+ attr_accessor :methods_with_sig
45
+
46
+ #: Integer
47
+ attr_accessor :calls_untyped
48
+
49
+ #: Integer
50
+ attr_accessor :calls_typed
51
+
52
+ #: Hash[String, Integer]
53
+ attr_accessor :sigils
54
+
55
+ #: Integer
56
+ attr_accessor :methods_with_sig_excluding_rbis
57
+
58
+ #: Integer
59
+ attr_accessor :methods_without_sig_excluding_rbis
60
+
61
+ #: Hash[String, Integer]
62
+ attr_accessor :sigils_excluding_rbis
63
+
64
+ #: (
65
+ #| ?timestamp: Integer,
66
+ #| ?version_static: String?,
67
+ #| ?version_runtime: String?,
68
+ #| ?duration: Integer,
69
+ #| ?commit_sha: String?,
70
+ #| ?commit_timestamp: Integer?,
71
+ #| ?files: Integer,
72
+ #| ?rbi_files: Integer,
73
+ #| ?modules: Integer,
74
+ #| ?classes: Integer,
75
+ #| ?singleton_classes: Integer,
76
+ #| ?methods_without_sig: Integer,
77
+ #| ?methods_with_sig: Integer,
78
+ #| ?calls_untyped: Integer,
79
+ #| ?calls_typed: Integer,
80
+ #| ?sigils: Hash[String, Integer],
81
+ #| ?methods_with_sig_excluding_rbis: Integer,
82
+ #| ?methods_without_sig_excluding_rbis: Integer,
83
+ #| ?sigils_excluding_rbis: Hash[String, Integer],
84
+ #| ) -> void
85
+ def initialize(
86
+ timestamp: Time.new.getutc.to_i,
87
+ version_static: nil,
88
+ version_runtime: nil,
89
+ duration: 0,
90
+ commit_sha: nil,
91
+ commit_timestamp: nil,
92
+ files: 0,
93
+ rbi_files: 0,
94
+ modules: 0,
95
+ classes: 0,
96
+ singleton_classes: 0,
97
+ methods_without_sig: 0,
98
+ methods_with_sig: 0,
99
+ calls_untyped: 0,
100
+ calls_typed: 0,
101
+ sigils: Hash.new(0),
102
+ methods_with_sig_excluding_rbis: 0,
103
+ methods_without_sig_excluding_rbis: 0,
104
+ sigils_excluding_rbis: Hash.new(0)
105
+ )
106
+ @timestamp = timestamp
107
+ @version_static = version_static
108
+ @version_runtime = version_runtime
109
+ @duration = duration
110
+ @commit_sha = commit_sha
111
+ @commit_timestamp = commit_timestamp
112
+ @files = files
113
+ @rbi_files = rbi_files
114
+ @modules = modules
115
+ @classes = classes
116
+ @singleton_classes = singleton_classes
117
+ @methods_without_sig = methods_without_sig
118
+ @methods_with_sig = methods_with_sig
119
+ @calls_untyped = calls_untyped
120
+ @calls_typed = calls_typed
121
+ @sigils = sigils
122
+ @methods_with_sig_excluding_rbis = methods_with_sig_excluding_rbis
123
+ @methods_without_sig_excluding_rbis = methods_without_sig_excluding_rbis
124
+ @sigils_excluding_rbis = sigils_excluding_rbis
125
+ end
26
126
 
27
127
  # The strictness name as found in the Sorbet metrics file
28
128
  STRICTNESSES = ["ignore", "false", "true", "strict", "strong", "stdlib"].freeze #: Array[String]
@@ -35,7 +135,33 @@ module Spoom
35
135
 
36
136
  #: (*untyped arg) -> String
37
137
  def to_json(*arg)
38
- serialize.to_json(*arg)
138
+ to_h #: untyped
139
+ .to_json(*arg)
140
+ end
141
+
142
+ #: -> Hash[String, untyped]
143
+ def to_h
144
+ {
145
+ "timestamp" => timestamp,
146
+ "version_static" => version_static,
147
+ "version_runtime" => version_runtime,
148
+ "duration" => duration,
149
+ "commit_sha" => commit_sha,
150
+ "commit_timestamp" => commit_timestamp,
151
+ "files" => files,
152
+ "rbi_files" => rbi_files,
153
+ "modules" => modules,
154
+ "classes" => classes,
155
+ "singleton_classes" => singleton_classes,
156
+ "methods_with_sig" => methods_with_sig,
157
+ "methods_without_sig" => methods_without_sig,
158
+ "calls_typed" => calls_typed,
159
+ "calls_untyped" => calls_untyped,
160
+ "sigils" => sigils,
161
+ "methods_with_sig_excluding_rbis" => methods_with_sig_excluding_rbis,
162
+ "methods_without_sig_excluding_rbis" => methods_without_sig_excluding_rbis,
163
+ "sigils_excluding_rbis" => sigils_excluding_rbis,
164
+ }
39
165
  end
40
166
 
41
167
  class << self
@@ -4,34 +4,59 @@
4
4
  module Spoom
5
5
  module Deadcode
6
6
  # A definition is a class, module, method, constant, etc. being defined in the code
7
- class Definition < T::Struct
8
- class Kind < T::Enum
9
- enums do
10
- AttrReader = new("attr_reader")
11
- AttrWriter = new("attr_writer")
12
- Class = new("class")
13
- Constant = new("constant")
14
- Method = new("method")
15
- Module = new("module")
7
+ class Definition
8
+ class Kind
9
+ #: (String) -> void
10
+ def initialize(name)
11
+ @name = name
16
12
  end
17
- end
18
13
 
19
- class Status < T::Enum
20
- enums do
21
- # A definition is marked as `ALIVE` if it has at least one reference with the same name
22
- ALIVE = new
23
- # A definition is marked as `DEAD` if it has no reference with the same name
24
- DEAD = new
25
- # A definition can be marked as `IGNORED` if it is not relevant for the analysis
26
- IGNORED = new
14
+ # @override
15
+ #: -> String
16
+ def to_s
17
+ @name
27
18
  end
19
+
20
+ AttrReader = new("attr_reader") #: Kind
21
+ AttrWriter = new("attr_writer") #: Kind
22
+ Class = new("class") #: Kind
23
+ Constant = new("constant") #: Kind
24
+ Method = new("method") #: Kind
25
+ Module = new("module") #: Kind
28
26
  end
29
27
 
30
- const :kind, Kind
31
- const :name, String
32
- const :full_name, String
33
- const :location, Location
34
- const :status, Status, default: Status::DEAD
28
+ class Status
29
+ # A definition is marked as `ALIVE` if it has at least one reference with the same name
30
+ ALIVE = new #: Status
31
+ # A definition is marked as `DEAD` if it has no reference with the same name
32
+ DEAD = new #: Status
33
+ # A definition can be marked as `IGNORED` if it is not relevant for the analysis
34
+ IGNORED = new #: Status
35
+ end
36
+
37
+ #: Kind
38
+ attr_reader :kind
39
+
40
+ #: String
41
+ attr_reader :name
42
+
43
+ #: String
44
+ attr_reader :full_name
45
+
46
+ #: Location
47
+ attr_reader :location
48
+
49
+ #: Status
50
+ attr_reader :status
51
+
52
+ #: (kind: Kind, name: String, full_name: String, location: Location, ?status: Status) -> void
53
+ def initialize(kind:, name:, full_name:, location:, status: Status::DEAD)
54
+ @kind = kind
55
+ @name = name
56
+ @full_name = full_name
57
+ @location = location
58
+ @status = status
59
+ end
35
60
 
36
61
  # Kind
37
62
 
@@ -356,21 +356,9 @@ module Spoom
356
356
 
357
357
  #: (NodeContext context) -> void
358
358
  def delete_node_and_comments_and_sigs(context)
359
- start_line = context.node.location.start_line
360
- end_line = context.node.location.end_line
361
-
362
- # TODO: remove once Prism location are fixed
363
359
  node = context.node
364
- case node
365
- when Prism::ConstantWriteNode, Prism::ConstantOperatorWriteNode,
366
- Prism::ConstantAndWriteNode, Prism::ConstantOrWriteNode,
367
- Prism::ConstantPathWriteNode, Prism::ConstantPathOperatorWriteNode,
368
- Prism::ConstantPathAndWriteNode, Prism::ConstantPathOrWriteNode
369
- value = node.value
370
- if value.is_a?(Prism::StringNode)
371
- end_line = value.closing_loc&.start_line || value.location.end_line
372
- end
373
- end
360
+ start_line = node.location.start_line
361
+ end_line = node_end_line(node)
374
362
 
375
363
  # Adjust the lines to remove to include sigs attached to the node
376
364
  first_node = context.attached_sigs.first || context.node
@@ -388,13 +376,16 @@ module Spoom
388
376
  # if there is, we only want to delete lines up to the last comment found
389
377
  if before
390
378
  to_node = first_comment || node
391
- comment = @node_context.comments_between_lines(before.location.end_line, to_node.location.start_line).last
379
+ comment = @node_context.comments_between_lines(node_end_line(before), to_node.location.start_line).last
392
380
  before = comment if comment
393
381
  end
394
382
 
395
- if before && before.location.end_line < start_line - 1
383
+ # `before` may have been swapped for a comment just above, so resolve its end line after that
384
+ before_end_line = node_end_line(before) if before
385
+
386
+ if before_end_line && before_end_line < start_line - 1
396
387
  # There is a node before and a blank line
397
- start_line = before.location.end_line + 1
388
+ start_line = before_end_line + 1
398
389
  elsif before.nil?
399
390
  # There is no node before, check if there is a blank line
400
391
  parent_context = context.parent_context
@@ -417,6 +408,45 @@ module Spoom
417
408
  delete_lines(start_line, end_line)
418
409
  end
419
410
 
411
+ # Prism reports a node ending in a heredoc as ending on the heredoc's opening line rather than
412
+ # its closing terminator (e.g. `def_node_matcher :foo, <<~PATTERN` spanning several lines).
413
+ # Return the last line the node actually occupies so the heredoc body isn't mistaken for blank
414
+ # filler, either when deleting the node itself or when accounting for the node that follows it.
415
+ # TODO: remove once Prism locations are fixed
416
+ #: ((Prism::Node | Prism::Comment) node) -> Integer
417
+ def node_end_line(node)
418
+ end_line = node.location.end_line
419
+ return end_line unless node.is_a?(Prism::Node)
420
+
421
+ stack = [node] #: Array[Prism::Node]
422
+ until stack.empty?
423
+ child = stack.pop
424
+ next unless child
425
+
426
+ heredoc_end = heredoc_terminator_line(child)
427
+ end_line = heredoc_end if heredoc_end && heredoc_end > end_line
428
+ stack.concat(child.compact_child_nodes)
429
+ end
430
+ end_line
431
+ end
432
+
433
+ # The last line occupied by `node` if it is a heredoc string (its closing terminator), or `nil`
434
+ # otherwise.
435
+ #: (Prism::Node node) -> Integer?
436
+ def heredoc_terminator_line(node)
437
+ case node
438
+ when Prism::StringNode, Prism::InterpolatedStringNode,
439
+ Prism::XStringNode, Prism::InterpolatedXStringNode
440
+ opening = node.opening_loc
441
+ return unless opening&.slice&.start_with?("<<")
442
+
443
+ # The terminator's location runs to the newline (column 0 of the next line), so use its
444
+ # start line rather than its end line.
445
+ closing = node.closing_loc
446
+ closing ? closing.start_line : node.location.end_line
447
+ end
448
+ end
449
+
420
450
  #: (Integer start_line, Integer end_line) -> void
421
451
  def delete_lines(start_line, end_line)
422
452
  lines = @new_source.lines
@@ -688,6 +718,8 @@ module Spoom
688
718
  node.is_a?(Prism::DefNode)
689
719
  when Definition::Kind::Module
690
720
  node.is_a?(Prism::ModuleNode)
721
+ else
722
+ raise Error, "Unsupported node kind: #{node.class}"
691
723
  end
692
724
  end
693
725
  end
@@ -4,13 +4,41 @@
4
4
  module Spoom
5
5
  module Deadcode
6
6
  # An abstraction to simplify handling of Prism::CallNode nodes.
7
- class Send < T::Struct
8
- const :node, Prism::CallNode
9
- const :name, String
10
- const :recv, T.nilable(Prism::Node), default: nil
11
- const :args, T::Array[Prism::Node], default: []
12
- const :block, T.nilable(Prism::Node), default: nil
13
- const :location, Location
7
+ class Send
8
+ #: Prism::CallNode
9
+ attr_reader :node
10
+
11
+ #: String
12
+ attr_reader :name
13
+
14
+ #: Prism::Node?
15
+ attr_reader :recv
16
+
17
+ #: Array[Prism::Node]
18
+ attr_reader :args
19
+
20
+ #: Prism::Node?
21
+ attr_reader :block
22
+
23
+ #: Location
24
+ attr_reader :location
25
+
26
+ #: (
27
+ #| node: Prism::CallNode,
28
+ #| name: String,
29
+ #| location: Location,
30
+ #| ?recv: Prism::Node?,
31
+ #| ?args: Array[Prism::Node],
32
+ #| ?block: Prism::Node?
33
+ #| ) -> void
34
+ def initialize(node:, name:, location:, recv: nil, args: [], block: nil)
35
+ @node = node
36
+ @name = name
37
+ @recv = recv
38
+ @args = args
39
+ @block = block
40
+ @location = location
41
+ end
14
42
 
15
43
  #: [T] (Class[T] arg_type) { (T arg) -> void } -> void
16
44
  def each_arg(arg_type, &block)