spoom 1.5.4 → 1.6.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 (74) hide show
  1. checksums.yaml +4 -4
  2. data/lib/spoom/backtrace_filter/minitest.rb +2 -3
  3. data/lib/spoom/cli/deadcode.rb +1 -2
  4. data/lib/spoom/cli/helper.rb +36 -28
  5. data/lib/spoom/cli/srb/assertions.rb +48 -0
  6. data/lib/spoom/cli/srb/bump.rb +1 -2
  7. data/lib/spoom/cli/srb/sigs.rb +133 -18
  8. data/lib/spoom/cli/srb.rb +8 -4
  9. data/lib/spoom/cli.rb +1 -2
  10. data/lib/spoom/colors.rb +2 -6
  11. data/lib/spoom/context/bundle.rb +8 -9
  12. data/lib/spoom/context/exec.rb +2 -5
  13. data/lib/spoom/context/file_system.rb +12 -19
  14. data/lib/spoom/context/git.rb +14 -19
  15. data/lib/spoom/context/sorbet.rb +13 -26
  16. data/lib/spoom/context.rb +3 -7
  17. data/lib/spoom/coverage/d3/base.rb +6 -8
  18. data/lib/spoom/coverage/d3/circle_map.rb +6 -16
  19. data/lib/spoom/coverage/d3/pie.rb +14 -19
  20. data/lib/spoom/coverage/d3/timeline.rb +46 -47
  21. data/lib/spoom/coverage/d3.rb +2 -4
  22. data/lib/spoom/coverage/report.rb +38 -76
  23. data/lib/spoom/coverage/snapshot.rb +7 -13
  24. data/lib/spoom/coverage.rb +3 -5
  25. data/lib/spoom/deadcode/definition.rb +12 -14
  26. data/lib/spoom/deadcode/erb.rb +10 -8
  27. data/lib/spoom/deadcode/index.rb +19 -23
  28. data/lib/spoom/deadcode/indexer.rb +5 -6
  29. data/lib/spoom/deadcode/plugins/action_mailer.rb +2 -3
  30. data/lib/spoom/deadcode/plugins/action_mailer_preview.rb +2 -3
  31. data/lib/spoom/deadcode/plugins/actionpack.rb +4 -4
  32. data/lib/spoom/deadcode/plugins/active_model.rb +2 -3
  33. data/lib/spoom/deadcode/plugins/active_record.rb +2 -3
  34. data/lib/spoom/deadcode/plugins/active_support.rb +2 -1
  35. data/lib/spoom/deadcode/plugins/base.rb +29 -32
  36. data/lib/spoom/deadcode/plugins/graphql.rb +2 -3
  37. data/lib/spoom/deadcode/plugins/minitest.rb +4 -4
  38. data/lib/spoom/deadcode/plugins/namespaces.rb +5 -5
  39. data/lib/spoom/deadcode/plugins/rails.rb +5 -5
  40. data/lib/spoom/deadcode/plugins/rubocop.rb +4 -4
  41. data/lib/spoom/deadcode/plugins/ruby.rb +3 -4
  42. data/lib/spoom/deadcode/plugins/sorbet.rb +12 -6
  43. data/lib/spoom/deadcode/plugins/thor.rb +2 -3
  44. data/lib/spoom/deadcode/plugins.rb +2 -4
  45. data/lib/spoom/deadcode/remover.rb +37 -59
  46. data/lib/spoom/deadcode/send.rb +2 -8
  47. data/lib/spoom/file_collector.rb +10 -18
  48. data/lib/spoom/file_tree.rb +31 -46
  49. data/lib/spoom/location.rb +9 -20
  50. data/lib/spoom/model/builder.rb +60 -15
  51. data/lib/spoom/model/model.rb +65 -68
  52. data/lib/spoom/model/namespace_visitor.rb +3 -2
  53. data/lib/spoom/model/reference.rb +4 -8
  54. data/lib/spoom/model/references_visitor.rb +49 -29
  55. data/lib/spoom/parse.rb +17 -3
  56. data/lib/spoom/poset.rb +17 -19
  57. data/lib/spoom/printer.rb +10 -13
  58. data/lib/spoom/sorbet/assertions.rb +278 -0
  59. data/lib/spoom/sorbet/config.rb +8 -12
  60. data/lib/spoom/sorbet/errors.rb +16 -31
  61. data/lib/spoom/sorbet/lsp/base.rb +9 -15
  62. data/lib/spoom/sorbet/lsp/errors.rb +8 -16
  63. data/lib/spoom/sorbet/lsp/structures.rb +36 -59
  64. data/lib/spoom/sorbet/lsp.rb +15 -17
  65. data/lib/spoom/sorbet/metrics.rb +3 -5
  66. data/lib/spoom/sorbet/sigils.rb +7 -11
  67. data/lib/spoom/sorbet/sigs.rb +118 -25
  68. data/lib/spoom/sorbet.rb +3 -9
  69. data/lib/spoom/timeline.rb +4 -6
  70. data/lib/spoom/version.rb +1 -1
  71. data/lib/spoom/visitor.rb +298 -151
  72. data/lib/spoom.rb +0 -2
  73. data/rbi/spoom.rbi +3963 -0
  74. metadata +6 -3
@@ -11,9 +11,7 @@ require_relative "lsp/errors"
11
11
  module Spoom
12
12
  module LSP
13
13
  class Client
14
- extend T::Sig
15
-
16
- sig { params(sorbet_bin: String, sorbet_args: String, path: String).void }
14
+ #: (String sorbet_bin, *String sorbet_args, ?path: String) -> void
17
15
  def initialize(sorbet_bin, *sorbet_args, path: ".")
18
16
  @id = T.let(0, Integer)
19
17
  @open = T.let(false, T::Boolean)
@@ -23,23 +21,23 @@ module Spoom
23
21
  @err = T.let(io_err, IO)
24
22
  end
25
23
 
26
- sig { returns(Integer) }
24
+ #: -> Integer
27
25
  def next_id
28
26
  @id += 1
29
27
  end
30
28
 
31
- sig { params(json_string: String).void }
29
+ #: (String json_string) -> void
32
30
  def send_raw(json_string)
33
31
  @in.puts("Content-Length:#{json_string.length}\r\n\r\n#{json_string}")
34
32
  end
35
33
 
36
- sig { params(message: Message).returns(T.nilable(T::Hash[T.untyped, T.untyped])) }
34
+ #: (Message message) -> Hash[untyped, untyped]?
37
35
  def send(message)
38
36
  send_raw(message.to_json)
39
37
  read if message.is_a?(Request)
40
38
  end
41
39
 
42
- sig { returns(T.nilable(String)) }
40
+ #: -> String?
43
41
  def read_raw
44
42
  header = @out.gets
45
43
 
@@ -50,7 +48,7 @@ module Spoom
50
48
  @out.read(len + 2) # +2 'cause of the final \r\n
51
49
  end
52
50
 
53
- sig { returns(T.nilable(T::Hash[T.untyped, T.untyped])) }
51
+ #: -> Hash[untyped, untyped]?
54
52
  def read
55
53
  raw_string = read_raw
56
54
  return unless raw_string
@@ -68,7 +66,7 @@ module Spoom
68
66
 
69
67
  # LSP requests
70
68
 
71
- sig { params(workspace_path: String).void }
69
+ #: (String workspace_path) -> void
72
70
  def open(workspace_path)
73
71
  raise Error::AlreadyOpen, "Error: CLI already opened" if @open
74
72
 
@@ -85,7 +83,7 @@ module Spoom
85
83
  @open = true
86
84
  end
87
85
 
88
- sig { params(uri: String, line: Integer, column: Integer).returns(T.nilable(Hover)) }
86
+ #: (String uri, Integer line, Integer column) -> Hover?
89
87
  def hover(uri, line, column)
90
88
  json = send(Request.new(
91
89
  next_id,
@@ -106,7 +104,7 @@ module Spoom
106
104
  Hover.from_json(json["result"])
107
105
  end
108
106
 
109
- sig { params(uri: String, line: Integer, column: Integer).returns(T::Array[SignatureHelp]) }
107
+ #: (String uri, Integer line, Integer column) -> Array[SignatureHelp]
110
108
  def signatures(uri, line, column)
111
109
  json = send(Request.new(
112
110
  next_id,
@@ -127,7 +125,7 @@ module Spoom
127
125
  json["result"]["signatures"].map { |loc| SignatureHelp.from_json(loc) }
128
126
  end
129
127
 
130
- sig { params(uri: String, line: Integer, column: Integer).returns(T::Array[Location]) }
128
+ #: (String uri, Integer line, Integer column) -> Array[Location]
131
129
  def definitions(uri, line, column)
132
130
  json = send(Request.new(
133
131
  next_id,
@@ -148,7 +146,7 @@ module Spoom
148
146
  json["result"].map { |loc| Location.from_json(loc) }
149
147
  end
150
148
 
151
- sig { params(uri: String, line: Integer, column: Integer).returns(T::Array[Location]) }
149
+ #: (String uri, Integer line, Integer column) -> Array[Location]
152
150
  def type_definitions(uri, line, column)
153
151
  json = send(Request.new(
154
152
  next_id,
@@ -169,7 +167,7 @@ module Spoom
169
167
  json["result"].map { |loc| Location.from_json(loc) }
170
168
  end
171
169
 
172
- sig { params(uri: String, line: Integer, column: Integer, include_decl: T::Boolean).returns(T::Array[Location]) }
170
+ #: (String uri, Integer line, Integer column, ?bool include_decl) -> Array[Location]
173
171
  def references(uri, line, column, include_decl = true)
174
172
  json = send(Request.new(
175
173
  next_id,
@@ -193,7 +191,7 @@ module Spoom
193
191
  json["result"].map { |loc| Location.from_json(loc) }
194
192
  end
195
193
 
196
- sig { params(query: String).returns(T::Array[DocumentSymbol]) }
194
+ #: (String query) -> Array[DocumentSymbol]
197
195
  def symbols(query)
198
196
  json = send(Request.new(
199
197
  next_id,
@@ -208,7 +206,7 @@ module Spoom
208
206
  json["result"].map { |loc| DocumentSymbol.from_json(loc) }
209
207
  end
210
208
 
211
- sig { params(uri: String).returns(T::Array[DocumentSymbol]) }
209
+ #: (String uri) -> Array[DocumentSymbol]
212
210
  def document_symbols(uri)
213
211
  json = send(Request.new(
214
212
  next_id,
@@ -225,7 +223,7 @@ module Spoom
225
223
  json["result"].map { |loc| DocumentSymbol.from_json(loc) }
226
224
  end
227
225
 
228
- sig { void }
226
+ #: -> void
229
227
  def close
230
228
  send(Request.new(next_id, "shutdown", {}))
231
229
  @in.close
@@ -9,19 +9,17 @@ module Spoom
9
9
  DEFAULT_PREFIX = "ruby_typer.unknown."
10
10
 
11
11
  class << self
12
- extend T::Sig
13
-
14
- sig { params(path: String, prefix: String).returns(T::Hash[String, Integer]) }
12
+ #: (String path, ?String prefix) -> Hash[String, Integer]
15
13
  def parse_file(path, prefix = DEFAULT_PREFIX)
16
14
  parse_string(File.read(path), prefix)
17
15
  end
18
16
 
19
- sig { params(string: String, prefix: String).returns(T::Hash[String, Integer]) }
17
+ #: (String string, ?String prefix) -> Hash[String, Integer]
20
18
  def parse_string(string, prefix = DEFAULT_PREFIX)
21
19
  parse_hash(JSON.parse(string), prefix)
22
20
  end
23
21
 
24
- sig { params(obj: T::Hash[String, T.untyped], prefix: String).returns(T::Hash[String, Integer]) }
22
+ #: (Hash[String, untyped] obj, ?String prefix) -> Hash[String, Integer]
25
23
  def parse_hash(obj, prefix = DEFAULT_PREFIX)
26
24
  obj["metrics"].each_with_object(Hash.new(0)) do |metric, metrics|
27
25
  name = metric["name"]
@@ -7,8 +7,6 @@
7
7
  module Spoom
8
8
  module Sorbet
9
9
  module Sigils
10
- extend T::Sig
11
-
12
10
  STRICTNESS_IGNORE = "ignore"
13
11
  STRICTNESS_FALSE = "false"
14
12
  STRICTNESS_TRUE = "true"
@@ -31,35 +29,33 @@ module Spoom
31
29
  SIGIL_REGEXP = T.let(/^#[[:blank:]]*typed:[[:blank:]]*(\S*)/, Regexp)
32
30
 
33
31
  class << self
34
- extend T::Sig
35
-
36
32
  # returns the full sigil comment string for the passed strictness
37
- sig { params(strictness: String).returns(String) }
33
+ #: (String strictness) -> String
38
34
  def sigil_string(strictness)
39
35
  "# typed: #{strictness}"
40
36
  end
41
37
 
42
38
  # returns true if the passed string is a valid strictness (else false)
43
- sig { params(strictness: String).returns(T::Boolean) }
39
+ #: (String strictness) -> bool
44
40
  def valid_strictness?(strictness)
45
41
  VALID_STRICTNESS.include?(strictness.strip)
46
42
  end
47
43
 
48
44
  # returns the strictness of a sigil in the passed file content string (nil if no sigil)
49
- sig { params(content: String).returns(T.nilable(String)) }
45
+ #: (String content) -> String?
50
46
  def strictness_in_content(content)
51
47
  SIGIL_REGEXP.match(content)&.[](1)
52
48
  end
53
49
 
54
50
  # returns a string which is the passed content but with the sigil updated to a new strictness
55
- sig { params(content: String, new_strictness: String).returns(String) }
51
+ #: (String content, String new_strictness) -> String
56
52
  def update_sigil(content, new_strictness)
57
53
  content.sub(SIGIL_REGEXP, sigil_string(new_strictness))
58
54
  end
59
55
 
60
56
  # returns a string containing the strictness of a sigil in a file at the passed path
61
57
  # * returns nil if no sigil
62
- sig { params(path: T.any(String, Pathname)).returns(T.nilable(String)) }
58
+ #: ((String | Pathname) path) -> String?
63
59
  def file_strictness(path)
64
60
  return unless File.file?(path)
65
61
 
@@ -68,7 +64,7 @@ module Spoom
68
64
  end
69
65
 
70
66
  # changes the sigil in the file at the passed path to the specified new strictness
71
- sig { params(path: T.any(String, Pathname), new_strictness: String).returns(T::Boolean) }
67
+ #: ((String | Pathname) path, String new_strictness) -> bool
72
68
  def change_sigil_in_file(path, new_strictness)
73
69
  content = File.read(path, encoding: Encoding::ASCII_8BIT)
74
70
  new_content = update_sigil(content, new_strictness)
@@ -79,7 +75,7 @@ module Spoom
79
75
  end
80
76
 
81
77
  # changes the sigil to have a new strictness in a list of files
82
- sig { params(path_list: T::Array[String], new_strictness: String).returns(T::Array[String]) }
78
+ #: (Array[String] path_list, String new_strictness) -> Array[String]
83
79
  def change_sigil_in_files(path_list, new_strictness)
84
80
  path_list.filter do |path|
85
81
  change_sigil_in_file(path, new_strictness)
@@ -6,12 +6,11 @@ require "rbi"
6
6
  module Spoom
7
7
  module Sorbet
8
8
  class Sigs
9
+ class Error < Spoom::Error; end
9
10
  class << self
10
- extend T::Sig
11
-
12
- sig { params(ruby_contents: String).returns(String) }
11
+ #: (String ruby_contents) -> String
13
12
  def strip(ruby_contents)
14
- sigs = collect_sigs(ruby_contents)
13
+ sigs = collect_sorbet_sigs(ruby_contents)
15
14
  lines_to_strip = sigs.flat_map { |sig, _| (sig.loc&.begin_line..sig.loc&.end_line).to_a }
16
15
 
17
16
  lines = []
@@ -21,10 +20,10 @@ module Spoom
21
20
  lines.join
22
21
  end
23
22
 
24
- sig { params(ruby_contents: String).returns(String) }
23
+ #: (String ruby_contents) -> String
25
24
  def rbi_to_rbs(ruby_contents)
26
25
  ruby_contents = ruby_contents.dup
27
- sigs = collect_sigs(ruby_contents)
26
+ sigs = collect_sorbet_sigs(ruby_contents)
28
27
 
29
28
  sigs.each do |sig, node|
30
29
  scanner = Scanner.new(ruby_contents)
@@ -36,7 +35,28 @@ module Spoom
36
35
  sig.loc&.end_line&.pred,
37
36
  T.must(sig.loc).end_column,
38
37
  )
39
- ruby_contents[start_index...end_index] = SigTranslator.translate(sig, node)
38
+ ruby_contents[start_index...end_index] = RBIToRBSTranslator.translate(sig, node)
39
+ end
40
+
41
+ ruby_contents
42
+ end
43
+
44
+ #: (String ruby_contents) -> String
45
+ def rbs_to_rbi(ruby_contents)
46
+ ruby_contents = ruby_contents.dup
47
+ rbs_comments = collect_rbs_comments(ruby_contents)
48
+
49
+ rbs_comments.each do |rbs_comment, node|
50
+ scanner = Scanner.new(ruby_contents)
51
+ start_index = scanner.find_char_position(
52
+ T.must(rbs_comment.loc&.begin_line&.pred),
53
+ T.must(rbs_comment.loc).begin_column,
54
+ )
55
+ end_index = scanner.find_char_position(
56
+ rbs_comment.loc&.end_line&.pred,
57
+ T.must(rbs_comment.loc).end_column,
58
+ )
59
+ ruby_contents[start_index...end_index] = RBSToRBITranslator.translate(rbs_comment, node)
40
60
  end
41
61
 
42
62
  ruby_contents
@@ -44,28 +64,39 @@ module Spoom
44
64
 
45
65
  private
46
66
 
47
- sig { params(ruby_contents: String).returns(T::Array[[RBI::Sig, T.any(RBI::Method, RBI::Attr)]]) }
48
- def collect_sigs(ruby_contents)
67
+ #: (String ruby_contents) -> Array[[RBI::Sig, (RBI::Method | RBI::Attr)]]
68
+ def collect_sorbet_sigs(ruby_contents)
49
69
  tree = RBI::Parser.parse_string(ruby_contents)
50
70
  visitor = SigsLocator.new
51
71
  visitor.visit(tree)
52
- visitor.sigs.sort_by { |sig, _rbs_string| -T.must(sig.loc&.begin_line) }
72
+ visitor.sigs.sort_by { |sig, _node| -T.must(sig.loc&.begin_line) }
73
+ end
74
+
75
+ #: (String ruby_contents) -> Array[[RBI::RBSComment, (RBI::Method | RBI::Attr)]]
76
+ def collect_rbs_comments(ruby_contents)
77
+ tree = RBI::Parser.parse_string(ruby_contents)
78
+ visitor = SigsLocator.new
79
+ visitor.visit(tree)
80
+ visitor.rbs_comments.sort_by { |comment, _node| -T.must(comment.loc&.begin_line) }
53
81
  end
54
82
  end
55
83
 
56
84
  class SigsLocator < RBI::Visitor
57
- extend T::Sig
58
-
59
- sig { returns(T::Array[[RBI::Sig, T.any(RBI::Method, RBI::Attr)]]) }
85
+ #: Array[[RBI::Sig, (RBI::Method | RBI::Attr)]]
60
86
  attr_reader :sigs
61
87
 
62
- sig { void }
88
+ #: Array[[RBI::RBSComment, (RBI::Method | RBI::Attr)]]
89
+ attr_reader :rbs_comments
90
+
91
+ #: -> void
63
92
  def initialize
64
93
  super
65
94
  @sigs = T.let([], T::Array[[RBI::Sig, T.any(RBI::Method, RBI::Attr)]])
95
+ @rbs_comments = T.let([], T::Array[[RBI::RBSComment, T.any(RBI::Method, RBI::Attr)]])
66
96
  end
67
97
 
68
- sig { override.params(node: T.nilable(RBI::Node)).void }
98
+ # @override
99
+ #: (RBI::Node? node) -> void
69
100
  def visit(node)
70
101
  return unless node
71
102
 
@@ -76,17 +107,18 @@ module Spoom
76
107
 
77
108
  @sigs << [sig, node]
78
109
  end
110
+ node.comments.grep(RBI::RBSComment).each do |rbs_comment|
111
+ @rbs_comments << [rbs_comment, node]
112
+ end
79
113
  when RBI::Tree
80
114
  visit_all(node.nodes)
81
115
  end
82
116
  end
83
117
  end
84
118
 
85
- class SigTranslator
119
+ class RBIToRBSTranslator
86
120
  class << self
87
- extend T::Sig
88
-
89
- sig { params(sig: RBI::Sig, node: T.any(RBI::Method, RBI::Attr)).returns(String) }
121
+ #: (RBI::Sig sig, (RBI::Method | RBI::Attr) node) -> String
90
122
  def translate(sig, node)
91
123
  case node
92
124
  when RBI::Method
@@ -98,7 +130,7 @@ module Spoom
98
130
 
99
131
  private
100
132
 
101
- sig { params(sig: RBI::Sig, node: RBI::Method).returns(String) }
133
+ #: (RBI::Sig sig, RBI::Method node) -> String
102
134
  def translate_method_sig(sig, node)
103
135
  out = StringIO.new
104
136
  p = RBI::RBSPrinter.new(out: out, indent: sig.loc&.begin_column)
@@ -133,7 +165,7 @@ module Spoom
133
165
  out.string
134
166
  end
135
167
 
136
- sig { params(sig: RBI::Sig, node: RBI::Attr).returns(String) }
168
+ #: (RBI::Sig sig, RBI::Attr node) -> String
137
169
  def translate_attr_sig(sig, node)
138
170
  out = StringIO.new
139
171
  p = RBI::RBSPrinter.new(out: out)
@@ -143,13 +175,74 @@ module Spoom
143
175
  end
144
176
  end
145
177
 
178
+ class RBSToRBITranslator
179
+ class << self
180
+ extend T::Sig
181
+
182
+ #: (RBI::RBSComment comment, (RBI::Method | RBI::Attr) node) -> String
183
+ def translate(comment, node)
184
+ case node
185
+ when RBI::Method
186
+ translate_method_sig(comment, node)
187
+ when RBI::Attr
188
+ translate_attr_sig(comment, node)
189
+ end
190
+ end
191
+
192
+ private
193
+
194
+ #: (RBI::RBSComment rbs_comment, RBI::Method node) -> String
195
+ def translate_method_sig(rbs_comment, node)
196
+ method_type = ::RBS::Parser.parse_method_type(rbs_comment.text)
197
+ translator = RBI::RBS::MethodTypeTranslator.new(node)
198
+ translator.visit(method_type)
199
+
200
+ # TODO: move this to `rbi`
201
+ res = translator.result
202
+ node.comments.each do |comment|
203
+ case comment.text
204
+ when "@abstract"
205
+ res.is_abstract = true
206
+ when "@final"
207
+ res.is_final = true
208
+ when "@override"
209
+ res.is_override = true
210
+ when "@override(allow_incompatible: true)"
211
+ res.is_override = true
212
+ res.allow_incompatible_override = true
213
+ when "@overridable"
214
+ res.is_overridable = true
215
+ end
216
+ end
217
+
218
+ res.string.strip
219
+ end
220
+
221
+ #: (RBI::RBSComment comment, RBI::Attr node) -> String
222
+ def translate_attr_sig(comment, node)
223
+ attr_type = ::RBS::Parser.parse_type(comment.text)
224
+ sig = RBI::Sig.new
225
+
226
+ if node.is_a?(RBI::AttrWriter)
227
+ if node.names.size != 1
228
+ raise Error, "AttrWriter must have exactly one name"
229
+ end
230
+
231
+ name = T.must(node.names.first)
232
+ sig.params << RBI::SigParam.new(name.to_s, RBI::RBS::TypeTranslator.translate(attr_type))
233
+ end
234
+
235
+ sig.return_type = RBI::RBS::TypeTranslator.translate(attr_type)
236
+ sig.string.strip
237
+ end
238
+ end
239
+ end
240
+
146
241
  # From https://github.com/Shopify/ruby-lsp/blob/9154bfc6ef/lib/ruby_lsp/document.rb#L127
147
242
  class Scanner
148
- extend T::Sig
149
-
150
243
  LINE_BREAK = T.let(0x0A, Integer)
151
244
 
152
- sig { params(source: String).void }
245
+ #: (String source) -> void
153
246
  def initialize(source)
154
247
  @current_line = T.let(0, Integer)
155
248
  @pos = T.let(0, Integer)
@@ -157,7 +250,7 @@ module Spoom
157
250
  end
158
251
 
159
252
  # Finds the character index inside the source string for a given line and column
160
- sig { params(line: Integer, character: Integer).returns(Integer) }
253
+ #: (Integer line, Integer character) -> Integer
161
254
  def find_char_position(line, character)
162
255
  # Find the character index for the beginning of the requested line
163
256
  until @current_line == line
data/lib/spoom/sorbet.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
+ require "spoom/sorbet/assertions"
4
5
  require "spoom/sorbet/config"
5
6
  require "spoom/sorbet/errors"
6
7
  require "spoom/sorbet/lsp"
@@ -12,20 +13,13 @@ require "open3"
12
13
  module Spoom
13
14
  module Sorbet
14
15
  class Error < Spoom::Error
15
- extend T::Sig
16
-
17
16
  class Killed < Error; end
18
17
  class Segfault < Error; end
19
18
 
20
- sig { returns(ExecResult) }
19
+ #: ExecResult
21
20
  attr_reader :result
22
21
 
23
- sig do
24
- params(
25
- message: String,
26
- result: ExecResult,
27
- ).void
28
- end
22
+ #: (String message, ExecResult result) -> void
29
23
  def initialize(message, result)
30
24
  super(message)
31
25
 
@@ -3,9 +3,7 @@
3
3
 
4
4
  module Spoom
5
5
  class Timeline
6
- extend T::Sig
7
-
8
- sig { params(context: Context, from: Time, to: Time).void }
6
+ #: (Context context, Time from, Time to) -> void
9
7
  def initialize(context, from, to)
10
8
  @context = context
11
9
  @from = from
@@ -13,13 +11,13 @@ module Spoom
13
11
  end
14
12
 
15
13
  # Return one commit for each month between `from` and `to`
16
- sig { returns(T::Array[Git::Commit]) }
14
+ #: -> Array[Git::Commit]
17
15
  def ticks
18
16
  commits_for_dates(months)
19
17
  end
20
18
 
21
19
  # Return all months between `from` and `to`
22
- sig { returns(T::Array[Time]) }
20
+ #: -> Array[Time]
23
21
  def months
24
22
  d = Date.new(@from.year, @from.month, 1)
25
23
  to = Date.new(@to.year, @to.month, 1)
@@ -32,7 +30,7 @@ module Spoom
32
30
  end
33
31
 
34
32
  # Return one commit for each date in `dates`
35
- sig { params(dates: T::Array[Time]).returns(T::Array[Git::Commit]) }
33
+ #: (Array[Time] dates) -> Array[Git::Commit]
36
34
  def commits_for_dates(dates)
37
35
  dates.map do |t|
38
36
  result = @context.git_log(
data/lib/spoom/version.rb CHANGED
@@ -2,5 +2,5 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module Spoom
5
- VERSION = "1.5.4"
5
+ VERSION = "1.6.0"
6
6
  end