spoom 1.5.0 → 1.7.2

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 (88) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +14 -0
  3. data/lib/spoom/backtrace_filter/minitest.rb +3 -4
  4. data/lib/spoom/cli/deadcode.rb +1 -2
  5. data/lib/spoom/cli/helper.rb +41 -31
  6. data/lib/spoom/cli/srb/assertions.rb +48 -0
  7. data/lib/spoom/cli/srb/bump.rb +1 -2
  8. data/lib/spoom/cli/srb/coverage.rb +1 -1
  9. data/lib/spoom/cli/srb/metrics.rb +68 -0
  10. data/lib/spoom/cli/srb/sigs.rb +209 -0
  11. data/lib/spoom/cli/srb/tc.rb +16 -1
  12. data/lib/spoom/cli/srb.rb +16 -4
  13. data/lib/spoom/cli.rb +1 -2
  14. data/lib/spoom/colors.rb +2 -6
  15. data/lib/spoom/context/bundle.rb +8 -9
  16. data/lib/spoom/context/exec.rb +3 -6
  17. data/lib/spoom/context/file_system.rb +12 -19
  18. data/lib/spoom/context/git.rb +14 -19
  19. data/lib/spoom/context/sorbet.rb +14 -27
  20. data/lib/spoom/context.rb +4 -8
  21. data/lib/spoom/counters.rb +22 -0
  22. data/lib/spoom/coverage/d3/base.rb +6 -8
  23. data/lib/spoom/coverage/d3/circle_map.rb +6 -16
  24. data/lib/spoom/coverage/d3/pie.rb +14 -19
  25. data/lib/spoom/coverage/d3/timeline.rb +46 -47
  26. data/lib/spoom/coverage/d3.rb +2 -4
  27. data/lib/spoom/coverage/report.rb +41 -79
  28. data/lib/spoom/coverage/snapshot.rb +8 -14
  29. data/lib/spoom/coverage.rb +3 -5
  30. data/lib/spoom/deadcode/definition.rb +12 -14
  31. data/lib/spoom/deadcode/erb.rb +10 -8
  32. data/lib/spoom/deadcode/index.rb +21 -25
  33. data/lib/spoom/deadcode/indexer.rb +5 -6
  34. data/lib/spoom/deadcode/plugins/action_mailer.rb +2 -3
  35. data/lib/spoom/deadcode/plugins/action_mailer_preview.rb +2 -3
  36. data/lib/spoom/deadcode/plugins/actionpack.rb +19 -22
  37. data/lib/spoom/deadcode/plugins/active_model.rb +2 -3
  38. data/lib/spoom/deadcode/plugins/active_record.rb +62 -53
  39. data/lib/spoom/deadcode/plugins/active_support.rb +3 -2
  40. data/lib/spoom/deadcode/plugins/base.rb +29 -32
  41. data/lib/spoom/deadcode/plugins/graphql.rb +2 -3
  42. data/lib/spoom/deadcode/plugins/minitest.rb +4 -4
  43. data/lib/spoom/deadcode/plugins/namespaces.rb +5 -5
  44. data/lib/spoom/deadcode/plugins/rails.rb +5 -5
  45. data/lib/spoom/deadcode/plugins/rubocop.rb +5 -5
  46. data/lib/spoom/deadcode/plugins/ruby.rb +3 -4
  47. data/lib/spoom/deadcode/plugins/sorbet.rb +12 -6
  48. data/lib/spoom/deadcode/plugins/thor.rb +2 -3
  49. data/lib/spoom/deadcode/plugins.rb +23 -31
  50. data/lib/spoom/deadcode/remover.rb +58 -79
  51. data/lib/spoom/deadcode/send.rb +2 -8
  52. data/lib/spoom/file_collector.rb +11 -19
  53. data/lib/spoom/file_tree.rb +36 -51
  54. data/lib/spoom/location.rb +9 -20
  55. data/lib/spoom/model/builder.rb +54 -17
  56. data/lib/spoom/model/model.rb +71 -74
  57. data/lib/spoom/model/namespace_visitor.rb +4 -3
  58. data/lib/spoom/model/reference.rb +4 -8
  59. data/lib/spoom/model/references_visitor.rb +50 -30
  60. data/lib/spoom/parse.rb +4 -4
  61. data/lib/spoom/poset.rb +22 -24
  62. data/lib/spoom/printer.rb +10 -13
  63. data/lib/spoom/rbs.rb +77 -0
  64. data/lib/spoom/sorbet/config.rb +17 -24
  65. data/lib/spoom/sorbet/errors.rb +87 -45
  66. data/lib/spoom/sorbet/lsp/base.rb +10 -16
  67. data/lib/spoom/sorbet/lsp/errors.rb +8 -16
  68. data/lib/spoom/sorbet/lsp/structures.rb +65 -91
  69. data/lib/spoom/sorbet/lsp.rb +20 -22
  70. data/lib/spoom/sorbet/metrics/code_metrics_visitor.rb +236 -0
  71. data/lib/spoom/sorbet/metrics/metrics_file_parser.rb +34 -0
  72. data/lib/spoom/sorbet/metrics.rb +2 -32
  73. data/lib/spoom/sorbet/sigils.rb +16 -23
  74. data/lib/spoom/sorbet/translate/rbs_comments_to_sorbet_sigs.rb +242 -0
  75. data/lib/spoom/sorbet/translate/sorbet_assertions_to_rbs_comments.rb +123 -0
  76. data/lib/spoom/sorbet/translate/sorbet_sigs_to_rbs_comments.rb +293 -0
  77. data/lib/spoom/sorbet/translate/strip_sorbet_sigs.rb +23 -0
  78. data/lib/spoom/sorbet/translate/translator.rb +71 -0
  79. data/lib/spoom/sorbet/translate.rb +49 -0
  80. data/lib/spoom/sorbet.rb +6 -12
  81. data/lib/spoom/source/rewriter.rb +167 -0
  82. data/lib/spoom/source.rb +4 -0
  83. data/lib/spoom/timeline.rb +4 -6
  84. data/lib/spoom/version.rb +1 -1
  85. data/lib/spoom/visitor.rb +298 -151
  86. data/lib/spoom.rb +4 -3
  87. data/rbi/spoom.rbi +3567 -0
  88. metadata +62 -8
@@ -8,28 +8,27 @@ require "erb"
8
8
  module Spoom
9
9
  module Coverage
10
10
  class Template
11
- extend T::Sig
12
11
  extend T::Helpers
13
12
 
14
13
  abstract!
15
14
 
16
15
  # Create a new template from an Erb file path
17
- sig { params(template: String).void }
16
+ #: (template: String) -> void
18
17
  def initialize(template:)
19
18
  @template = template
20
19
  end
21
20
 
22
- sig { returns(String) }
21
+ #: -> String
23
22
  def erb
24
23
  File.read(@template)
25
24
  end
26
25
 
27
- sig { returns(String) }
26
+ #: -> String
28
27
  def html
29
28
  ERB.new(erb).result(get_binding)
30
29
  end
31
30
 
32
- sig { returns(Binding) }
31
+ #: -> Binding
33
32
  def get_binding # rubocop:disable Naming/AccessorMethodName
34
33
  binding
35
34
  end
@@ -41,37 +40,37 @@ module Spoom
41
40
 
42
41
  abstract!
43
42
 
44
- TEMPLATE = T.let("#{Spoom::SPOOM_PATH}/templates/page.erb", String)
43
+ TEMPLATE = "#{Spoom::SPOOM_PATH}/templates/page.erb" #: String
45
44
 
46
- sig { returns(String) }
45
+ #: String
47
46
  attr_reader :title
48
47
 
49
- sig { returns(D3::ColorPalette) }
48
+ #: D3::ColorPalette
50
49
  attr_reader :palette
51
50
 
52
- sig { params(title: String, palette: D3::ColorPalette, template: String).void }
51
+ #: (title: String, palette: D3::ColorPalette, ?template: String) -> void
53
52
  def initialize(title:, palette:, template: TEMPLATE)
54
53
  super(template: template)
55
54
  @title = title
56
55
  @palette = palette
57
56
  end
58
57
 
59
- sig { returns(String) }
58
+ #: -> String
60
59
  def header_style
61
60
  D3.header_style
62
61
  end
63
62
 
64
- sig { returns(String) }
63
+ #: -> String
65
64
  def header_script
66
65
  D3.header_script(palette)
67
66
  end
68
67
 
69
- sig { returns(String) }
68
+ #: -> String
70
69
  def header_html
71
70
  "<h1 class='display-3'>#{title}</h1>"
72
71
  end
73
72
 
74
- sig { returns(String) }
73
+ #: -> String
75
74
  def body_html
76
75
  cards.map(&:html).join("\n")
77
76
  end
@@ -79,7 +78,7 @@ module Spoom
79
78
  sig { abstract.returns(T::Array[Cards::Card]) }
80
79
  def cards; end
81
80
 
82
- sig { returns(String) }
81
+ #: -> String
83
82
  def footer_html
84
83
  "Generated by <a href='https://github.com/Shopify/spoom'>spoom</a> on #{Time.now.utc}."
85
84
  end
@@ -89,12 +88,12 @@ module Spoom
89
88
  class Card < Template
90
89
  extend T::Sig
91
90
 
92
- TEMPLATE = T.let("#{Spoom::SPOOM_PATH}/templates/card.erb", String)
91
+ TEMPLATE = "#{Spoom::SPOOM_PATH}/templates/card.erb" #: String
93
92
 
94
- sig { returns(T.nilable(String)) }
93
+ #: String?
95
94
  attr_reader :title, :body
96
95
 
97
- sig { params(template: String, title: T.nilable(String), body: T.nilable(String)).void }
96
+ #: (?template: String, ?title: String?, ?body: String?) -> void
98
97
  def initialize(template: TEMPLATE, title: nil, body: nil)
99
98
  super(template: template)
100
99
  @title = title
@@ -103,15 +102,15 @@ module Spoom
103
102
  end
104
103
 
105
104
  class Erb < Card
106
- extend T::Sig
107
105
  extend T::Helpers
108
106
 
109
107
  abstract!
110
108
 
111
- sig { void }
109
+ #: -> void
112
110
  def initialize; end # rubocop:disable Lint/MissingSuper
113
111
 
114
- sig { override.returns(String) }
112
+ # @override
113
+ #: -> String
115
114
  def html
116
115
  ERB.new(erb).result(get_binding)
117
116
  end
@@ -121,46 +120,35 @@ module Spoom
121
120
  end
122
121
 
123
122
  class Snapshot < Card
124
- extend T::Sig
123
+ TEMPLATE = "#{Spoom::SPOOM_PATH}/templates/card_snapshot.erb" #: String
125
124
 
126
- TEMPLATE = T.let("#{Spoom::SPOOM_PATH}/templates/card_snapshot.erb", String)
127
-
128
- sig { returns(Coverage::Snapshot) }
125
+ #: Coverage::Snapshot
129
126
  attr_reader :snapshot
130
127
 
131
- sig { params(snapshot: Coverage::Snapshot, title: String).void }
128
+ #: (snapshot: Coverage::Snapshot, ?title: String) -> void
132
129
  def initialize(snapshot:, title: "Snapshot")
133
130
  super(template: TEMPLATE, title: title)
134
131
  @snapshot = snapshot
135
132
  end
136
133
 
137
- sig { returns(D3::Pie::Sigils) }
134
+ #: -> D3::Pie::Sigils
138
135
  def pie_sigils
139
136
  D3::Pie::Sigils.new("pie_sigils", "Sigils", snapshot)
140
137
  end
141
138
 
142
- sig { returns(D3::Pie::Calls) }
139
+ #: -> D3::Pie::Calls
143
140
  def pie_calls
144
141
  D3::Pie::Calls.new("pie_calls", "Calls", snapshot)
145
142
  end
146
143
 
147
- sig { returns(D3::Pie::Sigs) }
144
+ #: -> D3::Pie::Sigs
148
145
  def pie_sigs
149
146
  D3::Pie::Sigs.new("pie_sigs", "Sigs", snapshot)
150
147
  end
151
148
  end
152
149
 
153
150
  class Map < Card
154
- extend T::Sig
155
-
156
- sig do
157
- params(
158
- file_tree: FileTree,
159
- nodes_strictnesses: T::Hash[FileTree::Node, T.nilable(String)],
160
- nodes_strictness_scores: T::Hash[FileTree::Node, Float],
161
- title: String,
162
- ).void
163
- end
151
+ #: (file_tree: FileTree, nodes_strictnesses: Hash[FileTree::Node, String?], nodes_strictness_scores: Hash[FileTree::Node, Float], ?title: String) -> void
164
152
  def initialize(file_tree:, nodes_strictnesses:, nodes_strictness_scores:, title: "Strictness Map")
165
153
  super(
166
154
  title: title,
@@ -175,62 +163,48 @@ module Spoom
175
163
  end
176
164
 
177
165
  class Timeline < Card
178
- extend T::Sig
179
-
180
- sig { params(title: String, timeline: D3::Timeline).void }
166
+ #: (title: String, timeline: D3::Timeline) -> void
181
167
  def initialize(title:, timeline:)
182
168
  super(title: title, body: timeline.html)
183
169
  end
184
170
 
185
171
  class Sigils < Timeline
186
- extend T::Sig
187
-
188
- sig { params(snapshots: T::Array[Coverage::Snapshot], title: String).void }
172
+ #: (snapshots: Array[Coverage::Snapshot], ?title: String) -> void
189
173
  def initialize(snapshots:, title: "Sigils Timeline")
190
174
  super(title: title, timeline: D3::Timeline::Sigils.new("timeline_sigils", snapshots))
191
175
  end
192
176
  end
193
177
 
194
178
  class Calls < Timeline
195
- extend T::Sig
196
-
197
- sig { params(snapshots: T::Array[Coverage::Snapshot], title: String).void }
179
+ #: (snapshots: Array[Coverage::Snapshot], ?title: String) -> void
198
180
  def initialize(snapshots:, title: "Calls Timeline")
199
181
  super(title: title, timeline: D3::Timeline::Calls.new("timeline_calls", snapshots))
200
182
  end
201
183
  end
202
184
 
203
185
  class Sigs < Timeline
204
- extend T::Sig
205
-
206
- sig { params(snapshots: T::Array[Coverage::Snapshot], title: String).void }
186
+ #: (snapshots: Array[Coverage::Snapshot], ?title: String) -> void
207
187
  def initialize(snapshots:, title: "Signatures Timeline")
208
188
  super(title: title, timeline: D3::Timeline::Sigs.new("timeline_sigs", snapshots))
209
189
  end
210
190
  end
211
191
 
212
192
  class RBIs < Timeline
213
- extend T::Sig
214
-
215
- sig { params(snapshots: T::Array[Coverage::Snapshot], title: String).void }
193
+ #: (snapshots: Array[Coverage::Snapshot], ?title: String) -> void
216
194
  def initialize(snapshots:, title: "RBIs Timeline")
217
195
  super(title: title, timeline: D3::Timeline::RBIs.new("timeline_rbis", snapshots))
218
196
  end
219
197
  end
220
198
 
221
199
  class Versions < Timeline
222
- extend T::Sig
223
-
224
- sig { params(snapshots: T::Array[Coverage::Snapshot], title: String).void }
200
+ #: (snapshots: Array[Coverage::Snapshot], ?title: String) -> void
225
201
  def initialize(snapshots:, title: "Sorbet Versions Timeline")
226
202
  super(title: title, timeline: D3::Timeline::Versions.new("timeline_versions", snapshots))
227
203
  end
228
204
  end
229
205
 
230
206
  class Runtimes < Timeline
231
- extend T::Sig
232
-
233
- sig { params(snapshots: T::Array[Coverage::Snapshot], title: String).void }
207
+ #: (snapshots: Array[Coverage::Snapshot], ?title: String) -> void
234
208
  def initialize(snapshots:, title: "Sorbet Typechecking Time")
235
209
  super(title: title, timeline: D3::Timeline::Runtimes.new("timeline_runtimes", snapshots))
236
210
  end
@@ -238,15 +212,14 @@ module Spoom
238
212
  end
239
213
 
240
214
  class SorbetIntro < Erb
241
- extend T::Sig
242
-
243
- sig { params(sorbet_intro_commit: T.nilable(String), sorbet_intro_date: T.nilable(Time)).void }
215
+ #: (?sorbet_intro_commit: String?, ?sorbet_intro_date: Time?) -> void
244
216
  def initialize(sorbet_intro_commit: nil, sorbet_intro_date: nil) # rubocop:disable Lint/MissingSuper
245
217
  @sorbet_intro_commit = sorbet_intro_commit
246
218
  @sorbet_intro_date = sorbet_intro_date
247
219
  end
248
220
 
249
- sig { override.returns(String) }
221
+ # @override
222
+ #: -> String
250
223
  def erb
251
224
  <<~ERB
252
225
  <div class="text-center" style="margin-top: 30px">
@@ -259,20 +232,7 @@ module Spoom
259
232
  end
260
233
 
261
234
  class Report < Page
262
- extend T::Sig
263
-
264
- sig do
265
- params(
266
- project_name: String,
267
- palette: D3::ColorPalette,
268
- snapshots: T::Array[Snapshot],
269
- file_tree: FileTree,
270
- nodes_strictnesses: T::Hash[FileTree::Node, T.nilable(String)],
271
- nodes_strictness_scores: T::Hash[FileTree::Node, Float],
272
- sorbet_intro_commit: T.nilable(String),
273
- sorbet_intro_date: T.nilable(Time),
274
- ).void
275
- end
235
+ #: (project_name: String, palette: D3::ColorPalette, snapshots: Array[Snapshot], file_tree: FileTree, nodes_strictnesses: Hash[FileTree::Node, String?], nodes_strictness_scores: Hash[FileTree::Node, Float], ?sorbet_intro_commit: String?, ?sorbet_intro_date: Time?) -> void
276
236
  def initialize(
277
237
  project_name:,
278
238
  palette:,
@@ -293,7 +253,8 @@ module Spoom
293
253
  @sorbet_intro_date = sorbet_intro_date
294
254
  end
295
255
 
296
- sig { override.returns(String) }
256
+ # @override
257
+ #: -> String
297
258
  def header_html
298
259
  last = T.must(@snapshots.last)
299
260
  <<~ERB
@@ -304,7 +265,8 @@ module Spoom
304
265
  ERB
305
266
  end
306
267
 
307
- sig { override.returns(T::Array[Cards::Card]) }
268
+ # @override
269
+ #: -> Array[Cards::Card]
308
270
  def cards
309
271
  last = T.must(@snapshots.last)
310
272
  cards = []
@@ -4,8 +4,6 @@
4
4
  module Spoom
5
5
  module Coverage
6
6
  class Snapshot < T::Struct
7
- extend T::Sig
8
-
9
7
  prop :timestamp, Integer, default: Time.new.getutc.to_i
10
8
  prop :version_static, T.nilable(String), default: nil
11
9
  prop :version_runtime, T.nilable(String), default: nil
@@ -27,28 +25,26 @@ module Spoom
27
25
  prop :sigils_excluding_rbis, T::Hash[String, Integer], default: Hash.new(0)
28
26
 
29
27
  # The strictness name as found in the Sorbet metrics file
30
- STRICTNESSES = T.let(["ignore", "false", "true", "strict", "strong", "stdlib"].freeze, T::Array[String])
28
+ STRICTNESSES = ["ignore", "false", "true", "strict", "strong", "stdlib"].freeze #: Array[String]
31
29
 
32
- sig { params(out: T.any(IO, StringIO), colors: T::Boolean, indent_level: Integer).void }
30
+ #: (?out: (IO | StringIO), ?colors: bool, ?indent_level: Integer) -> void
33
31
  def print(out: $stdout, colors: true, indent_level: 0)
34
32
  printer = SnapshotPrinter.new(out: out, colors: colors, indent_level: indent_level)
35
33
  printer.print_snapshot(self)
36
34
  end
37
35
 
38
- sig { params(arg: T.untyped).returns(String) }
36
+ #: (*untyped arg) -> String
39
37
  def to_json(*arg)
40
38
  serialize.to_json(*arg)
41
39
  end
42
40
 
43
41
  class << self
44
- extend T::Sig
45
-
46
- sig { params(json: String).returns(Snapshot) }
42
+ #: (String json) -> Snapshot
47
43
  def from_json(json)
48
44
  from_obj(JSON.parse(json))
49
45
  end
50
46
 
51
- sig { params(obj: T::Hash[String, T.untyped]).returns(Snapshot) }
47
+ #: (Hash[String, untyped] obj) -> Snapshot
52
48
  def from_obj(obj)
53
49
  snapshot = Snapshot.new
54
50
  snapshot.timestamp = obj.fetch("timestamp", 0)
@@ -93,9 +89,7 @@ module Spoom
93
89
  end
94
90
 
95
91
  class SnapshotPrinter < Spoom::Printer
96
- extend T::Sig
97
-
98
- sig { params(snapshot: Snapshot).void }
92
+ #: (Snapshot snapshot) -> void
99
93
  def print_snapshot(snapshot)
100
94
  methods = snapshot.methods_with_sig + snapshot.methods_without_sig
101
95
  methods_excluding_rbis = snapshot.methods_with_sig_excluding_rbis + snapshot.methods_without_sig_excluding_rbis
@@ -143,7 +137,7 @@ module Spoom
143
137
 
144
138
  private
145
139
 
146
- sig { params(hash: T::Hash[String, Integer], total: Integer).void }
140
+ #: (Hash[String, Integer] hash, Integer total) -> void
147
141
  def print_map(hash, total)
148
142
  indent
149
143
  hash.each do |key, value|
@@ -154,7 +148,7 @@ module Spoom
154
148
  dedent
155
149
  end
156
150
 
157
- sig { params(value: T.nilable(Integer), total: T.nilable(Integer)).returns(String) }
151
+ #: (Integer? value, Integer? total) -> String
158
152
  def percent(value, total)
159
153
  return "" if value.nil? || total.nil? || total == 0
160
154
 
@@ -10,9 +10,7 @@ require "date"
10
10
  module Spoom
11
11
  module Coverage
12
12
  class << self
13
- extend T::Sig
14
-
15
- sig { params(context: Context, rbi: T::Boolean, sorbet_bin: T.nilable(String)).returns(Snapshot) }
13
+ #: (Context context, ?rbi: bool, ?sorbet_bin: String?) -> Snapshot
16
14
  def snapshot(context, rbi: true, sorbet_bin: nil)
17
15
  config = context.sorbet_config
18
16
  config.allowed_extensions.push(".rb", ".rbi") if config.allowed_extensions.empty?
@@ -79,7 +77,7 @@ module Spoom
79
77
  snapshot
80
78
  end
81
79
 
82
- sig { params(context: Context, snapshots: T::Array[Snapshot], palette: D3::ColorPalette).returns(Report) }
80
+ #: (Context context, Array[Snapshot] snapshots, palette: D3::ColorPalette) -> Report
83
81
  def report(context, snapshots, palette:)
84
82
  intro_commit = context.sorbet_intro_commit
85
83
 
@@ -99,7 +97,7 @@ module Spoom
99
97
  )
100
98
  end
101
99
 
102
- sig { params(context: Context).returns(FileTree) }
100
+ #: (Context context) -> FileTree
103
101
  def file_tree(context)
104
102
  config = context.sorbet_config
105
103
  config.ignore += ["test"]
@@ -5,8 +5,6 @@ module Spoom
5
5
  module Deadcode
6
6
  # A definition is a class, module, method, constant, etc. being defined in the code
7
7
  class Definition < T::Struct
8
- extend T::Sig
9
-
10
8
  class Kind < T::Enum
11
9
  enums do
12
10
  AttrReader = new("attr_reader")
@@ -37,66 +35,66 @@ module Spoom
37
35
 
38
36
  # Kind
39
37
 
40
- sig { returns(T::Boolean) }
38
+ #: -> bool
41
39
  def attr_reader?
42
40
  kind == Kind::AttrReader
43
41
  end
44
42
 
45
- sig { returns(T::Boolean) }
43
+ #: -> bool
46
44
  def attr_writer?
47
45
  kind == Kind::AttrWriter
48
46
  end
49
47
 
50
- sig { returns(T::Boolean) }
48
+ #: -> bool
51
49
  def class?
52
50
  kind == Kind::Class
53
51
  end
54
52
 
55
- sig { returns(T::Boolean) }
53
+ #: -> bool
56
54
  def constant?
57
55
  kind == Kind::Constant
58
56
  end
59
57
 
60
- sig { returns(T::Boolean) }
58
+ #: -> bool
61
59
  def method?
62
60
  kind == Kind::Method
63
61
  end
64
62
 
65
- sig { returns(T::Boolean) }
63
+ #: -> bool
66
64
  def module?
67
65
  kind == Kind::Module
68
66
  end
69
67
 
70
68
  # Status
71
69
 
72
- sig { returns(T::Boolean) }
70
+ #: -> bool
73
71
  def alive?
74
72
  status == Status::ALIVE
75
73
  end
76
74
 
77
- sig { void }
75
+ #: -> void
78
76
  def alive!
79
77
  @status = Status::ALIVE
80
78
  end
81
79
 
82
- sig { returns(T::Boolean) }
80
+ #: -> bool
83
81
  def dead?
84
82
  status == Status::DEAD
85
83
  end
86
84
 
87
- sig { returns(T::Boolean) }
85
+ #: -> bool
88
86
  def ignored?
89
87
  status == Status::IGNORED
90
88
  end
91
89
 
92
- sig { void }
90
+ #: -> void
93
91
  def ignored!
94
92
  @status = Status::IGNORED
95
93
  end
96
94
 
97
95
  # Utils
98
96
 
99
- sig { params(args: T.untyped).returns(String) }
97
+ #: (*untyped args) -> String
100
98
  def to_json(*args)
101
99
  {
102
100
  kind: kind,
@@ -27,9 +27,7 @@ module Spoom
27
27
  module Deadcode
28
28
  # Custom engine to handle ERB templates as used by Rails
29
29
  class ERB < ::Erubi::Engine
30
- extend T::Sig
31
-
32
- sig { params(input: T.untyped, properties: T.untyped).void }
30
+ #: (untyped input, ?untyped properties) -> void
33
31
  def initialize(input, properties = {})
34
32
  @newline_pending = 0
35
33
 
@@ -44,7 +42,8 @@ module Spoom
44
42
 
45
43
  private
46
44
 
47
- sig { override.params(text: T.untyped).void }
45
+ # @override
46
+ #: (untyped text) -> void
48
47
  def add_text(text)
49
48
  return if text.empty?
50
49
 
@@ -62,7 +61,8 @@ module Spoom
62
61
 
63
62
  BLOCK_EXPR = /\s*((\s+|\))do|\{)(\s*\|[^|]*\|)?\s*\Z/
64
63
 
65
- sig { override.params(indicator: T.untyped, code: T.untyped).void }
64
+ # @override
65
+ #: (untyped indicator, untyped code) -> void
66
66
  def add_expression(indicator, code)
67
67
  flush_newline_if_pending(src)
68
68
 
@@ -79,19 +79,21 @@ module Spoom
79
79
  end
80
80
  end
81
81
 
82
- sig { override.params(code: T.untyped).void }
82
+ # @override
83
+ #: (untyped code) -> void
83
84
  def add_code(code)
84
85
  flush_newline_if_pending(src)
85
86
  super
86
87
  end
87
88
 
88
- sig { override.params(_: T.untyped).void }
89
+ # @override
90
+ #: (untyped _) -> void
89
91
  def add_postamble(_)
90
92
  flush_newline_if_pending(src)
91
93
  super
92
94
  end
93
95
 
94
- sig { params(src: T.untyped).void }
96
+ #: (untyped src) -> void
95
97
  def flush_newline_if_pending(src)
96
98
  if @newline_pending > 0
97
99
  src << bufvar << ".safe_append='#{"\n" * @newline_pending}'.freeze;"
@@ -4,38 +4,34 @@
4
4
  module Spoom
5
5
  module Deadcode
6
6
  class Index
7
- extend T::Sig
8
-
9
7
  class Error < Spoom::Error
10
- extend T::Sig
11
-
12
- sig { params(message: String, parent: Exception).void }
8
+ #: (String message, parent: Exception) -> void
13
9
  def initialize(message, parent:)
14
10
  super(message)
15
11
  set_backtrace(parent.backtrace)
16
12
  end
17
13
  end
18
14
 
19
- sig { returns(Model) }
15
+ #: Model
20
16
  attr_reader :model
21
17
 
22
- sig { returns(T::Hash[String, T::Array[Definition]]) }
18
+ #: Hash[String, Array[Definition]]
23
19
  attr_reader :definitions
24
20
 
25
- sig { returns(T::Hash[String, T::Array[Model::Reference]]) }
21
+ #: Hash[String, Array[Model::Reference]]
26
22
  attr_reader :references
27
23
 
28
- sig { params(model: Model).void }
24
+ #: (Model model) -> void
29
25
  def initialize(model)
30
26
  @model = model
31
- @definitions = T.let({}, T::Hash[String, T::Array[Definition]])
32
- @references = T.let({}, T::Hash[String, T::Array[Model::Reference]])
33
- @ignored = T.let(Set.new, T::Set[Model::SymbolDef])
27
+ @definitions = {} #: Hash[String, Array[Definition]]
28
+ @references = {} #: Hash[String, Array[Model::Reference]]
29
+ @ignored = Set.new #: Set[Model::SymbolDef]
34
30
  end
35
31
 
36
32
  # Indexing
37
33
 
38
- sig { params(file: String, plugins: T::Array[Plugins::Base]).void }
34
+ #: (String file, ?plugins: Array[Plugins::Base]) -> void
39
35
  def index_file(file, plugins: [])
40
36
  if file.end_with?(".erb")
41
37
  erb = File.read(file)
@@ -46,14 +42,14 @@ module Spoom
46
42
  end
47
43
  end
48
44
 
49
- sig { params(erb: String, file: String, plugins: T::Array[Plugins::Base]).void }
45
+ #: (String erb, file: String, ?plugins: Array[Plugins::Base]) -> void
50
46
  def index_erb(erb, file:, plugins: [])
51
47
  index_ruby(Deadcode::ERB.new(erb).src, file: file, plugins: plugins)
52
48
  end
53
49
 
54
- sig { params(rb: String, file: String, plugins: T::Array[Plugins::Base]).void }
50
+ #: (String rb, file: String, ?plugins: Array[Plugins::Base]) -> void
55
51
  def index_ruby(rb, file:, plugins: [])
56
- node = Spoom.parse_ruby(rb, file: file)
52
+ node = Spoom.parse_ruby(rb, file: file, comments: true)
57
53
 
58
54
  # Index definitions
59
55
  model_builder = Model::Builder.new(@model, file)
@@ -75,27 +71,27 @@ module Spoom
75
71
  raise Error.new("Error while indexing #{file} (#{e.message})", parent: e)
76
72
  end
77
73
 
78
- sig { params(definition: Definition).void }
74
+ #: (Definition definition) -> void
79
75
  def define(definition)
80
76
  (@definitions[definition.name] ||= []) << definition
81
77
  end
82
78
 
83
- sig { params(name: String, location: Location).void }
79
+ #: (String name, Location location) -> void
84
80
  def reference_constant(name, location)
85
81
  (@references[name] ||= []) << Model::Reference.constant(name, location)
86
82
  end
87
83
 
88
- sig { params(name: String, location: Location).void }
84
+ #: (String name, Location location) -> void
89
85
  def reference_method(name, location)
90
86
  (@references[name] ||= []) << Model::Reference.method(name, location)
91
87
  end
92
88
 
93
- sig { params(symbol_def: Model::SymbolDef).void }
89
+ #: (Model::SymbolDef symbol_def) -> void
94
90
  def ignore(symbol_def)
95
91
  @ignored << symbol_def
96
92
  end
97
93
 
98
- sig { params(plugins: T::Array[Plugins::Base]).void }
94
+ #: (Array[Plugins::Base] plugins) -> void
99
95
  def apply_plugins!(plugins)
100
96
  @model.symbols.each do |_full_name, symbol|
101
97
  symbol.definitions.each do |symbol_def|
@@ -118,7 +114,7 @@ module Spoom
118
114
  # Mark all definitions having a reference of the same name as `alive`
119
115
  #
120
116
  # To be called once all the files have been indexed and all the definitions and references discovered.
121
- sig { void }
117
+ #: -> void
122
118
  def finalize!
123
119
  @model.symbols.each do |_full_name, symbol|
124
120
  symbol.definitions.each do |symbol_def|
@@ -210,17 +206,17 @@ module Spoom
210
206
 
211
207
  # Utils
212
208
 
213
- sig { params(name: String).returns(T::Array[Definition]) }
209
+ #: (String name) -> Array[Definition]
214
210
  def definitions_for_name(name)
215
211
  @definitions[name] || []
216
212
  end
217
213
 
218
- sig { returns(T::Array[Definition]) }
214
+ #: -> Array[Definition]
219
215
  def all_definitions
220
216
  @definitions.values.flatten
221
217
  end
222
218
 
223
- sig { returns(T::Array[Model::Reference]) }
219
+ #: -> Array[Model::Reference]
224
220
  def all_references
225
221
  @references.values.flatten
226
222
  end