spoom 1.6.1 → 1.6.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.
@@ -11,15 +11,12 @@ module Spoom
11
11
 
12
12
  @model = model
13
13
  @file = file
14
- @comments_by_line = T.let(
15
- comments.to_h do |c|
16
- [c.location.start_line, c]
17
- end,
18
- T::Hash[Integer, Prism::Comment],
19
- )
20
- @namespace_nesting = T.let([], T::Array[Namespace])
21
- @visibility_stack = T.let([Visibility::Public], T::Array[Visibility])
22
- @last_sigs = T.let([], T::Array[Sig])
14
+ @comments_by_line = comments.to_h do |c|
15
+ [c.location.start_line, c]
16
+ end #: Hash[Integer, Prism::Comment]
17
+ @namespace_nesting = [] #: Array[Namespace]
18
+ @visibility_stack = [Visibility::Public] #: Array[Visibility]
19
+ @last_sigs = [] #: Array[Sig]
23
20
  end
24
21
 
25
22
  # Classes
@@ -36,7 +36,7 @@ module Spoom
36
36
  #: (String full_name) -> void
37
37
  def initialize(full_name)
38
38
  @full_name = full_name
39
- @definitions = T.let([], T::Array[SymbolDef])
39
+ @definitions = [] #: Array[SymbolDef]
40
40
  end
41
41
 
42
42
  # The short name of this symbol
@@ -122,8 +122,8 @@ module Spoom
122
122
  def initialize(symbol, owner:, location:, comments: [])
123
123
  super(symbol, owner: owner, location: location, comments: comments)
124
124
 
125
- @children = T.let([], T::Array[SymbolDef])
126
- @mixins = T.let([], T::Array[Mixin])
125
+ @children = [] #: Array[SymbolDef]
126
+ @mixins = [] #: Array[Mixin]
127
127
  end
128
128
  end
129
129
 
@@ -233,8 +233,8 @@ module Spoom
233
233
 
234
234
  #: -> void
235
235
  def initialize
236
- @symbols = T.let({}, T::Hash[String, Symbol])
237
- @symbols_hierarchy = T.let(Poset[Symbol].new, Poset[Symbol])
236
+ @symbols = {} #: Hash[String, Symbol]
237
+ @symbols_hierarchy = Poset[Symbol].new #: Poset[Symbol]
238
238
  end
239
239
 
240
240
  # Get a symbol by it's full name
@@ -263,7 +263,7 @@ module Spoom
263
263
  return @symbols[full_name] ||= UnresolvedSymbol.new(full_name)
264
264
  end
265
265
 
266
- target = T.let(@symbols[full_name], T.nilable(Symbol))
266
+ target = @symbols[full_name] #: Symbol?
267
267
  return target if target
268
268
 
269
269
  parts = context.full_name.split("::")
@@ -12,7 +12,7 @@ module Spoom
12
12
  def initialize
13
13
  super()
14
14
 
15
- @names_nesting = T.let([], T::Array[String])
15
+ @names_nesting = [] #: Array[String]
16
16
  end
17
17
 
18
18
  # @override
@@ -13,7 +13,7 @@ module Spoom
13
13
  super()
14
14
 
15
15
  @file = file
16
- @references = T.let([], T::Array[Reference])
16
+ @references = [] #: Array[Reference]
17
17
  end
18
18
 
19
19
  # @override
data/lib/spoom/poset.rb CHANGED
@@ -15,7 +15,7 @@ module Spoom
15
15
 
16
16
  #: -> void
17
17
  def initialize
18
- @elements = T.let({}, T::Hash[E, Element[E]])
18
+ @elements = {} #: Hash[E, Element[E]]
19
19
  end
20
20
 
21
21
  # Get the POSet element for a given value
@@ -149,10 +149,10 @@ module Spoom
149
149
  #: (E value) -> void
150
150
  def initialize(value)
151
151
  @value = value
152
- @dtos = T.let(Set.new, T::Set[Element[E]])
153
- @tos = T.let(Set.new, T::Set[Element[E]])
154
- @dfroms = T.let(Set.new, T::Set[Element[E]])
155
- @froms = T.let(Set.new, T::Set[Element[E]])
152
+ @dtos = Set.new #: Set[Element[E]]
153
+ @tos = Set.new #: Set[Element[E]]
154
+ @dfroms = Set.new #: Set[Element[E]]
155
+ @froms = Set.new #: Set[Element[E]]
156
156
  end
157
157
 
158
158
  #: (untyped other) -> Integer?
@@ -144,7 +144,7 @@ module Spoom
144
144
  end
145
145
 
146
146
  class Locator < Spoom::Visitor
147
- ANNOTATION_METHODS = T.let([:let], T::Array[Symbol])
147
+ ANNOTATION_METHODS = [:let] #: Array[Symbol]
148
148
 
149
149
  #: Array[AssignNode]
150
150
  attr_reader :assigns
@@ -152,7 +152,7 @@ module Spoom
152
152
  #: -> void
153
153
  def initialize
154
154
  super
155
- @assigns = T.let([], T::Array[AssignNode])
155
+ @assigns = [] #: Array[AssignNode]
156
156
  end
157
157
 
158
158
  #: (AssignType) -> void
@@ -254,7 +254,7 @@ module Spoom
254
254
 
255
255
  #: -> void
256
256
  def initialize
257
- @contains_heredoc = T.let(false, T::Boolean)
257
+ @contains_heredoc = false #: bool
258
258
 
259
259
  super
260
260
  end
@@ -24,7 +24,7 @@ module Spoom
24
24
  # puts config.ignore # "c"
25
25
  # ```
26
26
  class Config
27
- DEFAULT_ALLOWED_EXTENSIONS = T.let([".rb", ".rbi"].freeze, T::Array[String])
27
+ DEFAULT_ALLOWED_EXTENSIONS = [".rb", ".rbi"].freeze #: Array[String]
28
28
 
29
29
  #: Array[String]
30
30
  attr_accessor :paths, :ignore, :allowed_extensions
@@ -34,10 +34,10 @@ module Spoom
34
34
 
35
35
  #: -> void
36
36
  def initialize
37
- @paths = T.let([], T::Array[String])
38
- @ignore = T.let([], T::Array[String])
39
- @allowed_extensions = T.let([], T::Array[String])
40
- @no_stdlib = T.let(false, T::Boolean)
37
+ @paths = [] #: Array[String]
38
+ @ignore = [] #: Array[String]
39
+ @allowed_extensions = [] #: Array[String]
40
+ @no_stdlib = false #: bool
41
41
  end
42
42
 
43
43
  #: -> Config
@@ -81,7 +81,7 @@ module Spoom
81
81
  #: (String sorbet_config) -> Spoom::Sorbet::Config
82
82
  def parse_string(sorbet_config)
83
83
  config = Config.new
84
- state = T.let(nil, T.nilable(Symbol))
84
+ state = nil #: Symbol?
85
85
  sorbet_config.each_line do |line|
86
86
  line = line.strip
87
87
  case line
@@ -1,6 +1,8 @@
1
1
  # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
+ require "rexml/document"
5
+
4
6
  module Spoom
5
7
  module Sorbet
6
8
  module Errors
@@ -11,21 +13,47 @@ module Spoom
11
13
  def sort_errors_by_code(errors)
12
14
  errors.sort_by { |e| [e.code, e.file, e.line, e.message] }
13
15
  end
16
+
17
+ #: (Array[Error]) -> REXML::Document
18
+ def to_junit_xml(errors)
19
+ testsuite_element = REXML::Element.new("testsuite")
20
+ testsuite_element.add_attributes(
21
+ "name" => "Sorbet",
22
+ "failures" => errors.size,
23
+ )
24
+
25
+ if errors.empty?
26
+ # Avoid creating an empty report when there are no errors so that
27
+ # reporting tools know that the type checking ran successfully.
28
+ testcase_element = testsuite_element.add_element("testcase")
29
+ testcase_element.add_attributes(
30
+ "name" => "Typecheck",
31
+ "tests" => 1,
32
+ )
33
+ else
34
+ errors.each do |error|
35
+ testsuite_element.add_element(error.to_junit_xml_element)
36
+ end
37
+ end
38
+
39
+ doc = REXML::Document.new
40
+ doc << REXML::XMLDecl.new
41
+ doc.add_element(testsuite_element)
42
+
43
+ doc
44
+ end
14
45
  end
15
46
  # Parse errors from Sorbet output
16
47
  class Parser
17
48
  class ParseError < Spoom::Error; end
18
49
 
19
- HEADER = T.let(
20
- [
21
- "👋 Hey there! Heads up that this is not a release build of sorbet.",
22
- "Release builds are faster and more well-supported by the Sorbet team.",
23
- "Check out the README to learn how to build Sorbet in release mode.",
24
- "To forcibly silence this error, either pass --silence-dev-message,",
25
- "or set SORBET_SILENCE_DEV_MESSAGE=1 in your shell environment.",
26
- ],
27
- T::Array[String],
28
- )
50
+ HEADER = [
51
+ "👋 Hey there! Heads up that this is not a release build of sorbet.",
52
+ "Release builds are faster and more well-supported by the Sorbet team.",
53
+ "Check out the README to learn how to build Sorbet in release mode.",
54
+ "To forcibly silence this error, either pass --silence-dev-message,",
55
+ "or set SORBET_SILENCE_DEV_MESSAGE=1 in your shell environment.",
56
+ ] #: Array[String]
29
57
 
30
58
  class << self
31
59
  #: (String output, ?error_url_base: String) -> Array[Error]
@@ -37,9 +65,9 @@ module Spoom
37
65
 
38
66
  #: (?error_url_base: String) -> void
39
67
  def initialize(error_url_base: DEFAULT_ERROR_URL_BASE)
40
- @errors = T.let([], T::Array[Error])
41
- @error_line_match_regex = T.let(error_line_match_regexp(error_url_base), Regexp)
42
- @current_error = T.let(nil, T.nilable(Error))
68
+ @errors = [] #: Array[Error]
69
+ @error_line_match_regex = error_line_match_regexp(error_url_base) #: Regexp
70
+ @current_error = nil #: Error?
43
71
  end
44
72
 
45
73
  #: (String output) -> Array[Error]
@@ -141,7 +169,7 @@ module Spoom
141
169
  @message = message
142
170
  @code = code
143
171
  @more = more
144
- @files_from_error_sections = T.let(Set.new, T::Set[String])
172
+ @files_from_error_sections = Set.new #: Set[String]
145
173
  end
146
174
 
147
175
  # By default errors are sorted by location
@@ -156,6 +184,35 @@ module Spoom
156
184
  def to_s
157
185
  "#{file}:#{line}: #{message} (#{code})"
158
186
  end
187
+
188
+ #: -> REXML::Element
189
+ def to_junit_xml_element
190
+ testcase_element = REXML::Element.new("testcase")
191
+ # Unlike traditional test suites, we can't report all tests
192
+ # regardless of outcome; we only have errors to report. As a
193
+ # result we reinterpret the definitions of the test properties
194
+ # bit: the error message becomes the test name and the full error
195
+ # info gets plugged into the failure body along with file/line
196
+ # information (displayed in Jenkins as the "Stacktrace" for the
197
+ # error).
198
+ testcase_element.add_attributes(
199
+ "name" => message,
200
+ "file" => file,
201
+ "line" => line,
202
+ )
203
+ failure_element = testcase_element.add_element("failure")
204
+ failure_element.add_attributes(
205
+ "type" => code,
206
+ )
207
+ explanation_text = [
208
+ "In file #{file}:\n",
209
+ *more,
210
+ ].join.chomp
211
+ # Use CDATA so that parsers know the whitespace is significant.
212
+ failure_element.add(REXML::CData.new(explanation_text))
213
+
214
+ testcase_element
215
+ end
159
216
  end
160
217
  end
161
218
  end
@@ -12,7 +12,7 @@ module Spoom
12
12
  class Message
13
13
  #: -> void
14
14
  def initialize
15
- @jsonrpc = T.let("2.0", String)
15
+ @jsonrpc = "2.0" #: String
16
16
  end
17
17
 
18
18
  #: -> Hash[untyped, untyped]
@@ -259,37 +259,34 @@ module Spoom
259
259
  SYMBOL_KINDS[kind] || "<unknown:#{kind}>"
260
260
  end
261
261
 
262
- SYMBOL_KINDS = T.let(
263
- {
264
- 1 => "file",
265
- 2 => "module",
266
- 3 => "namespace",
267
- 4 => "package",
268
- 5 => "class",
269
- 6 => "def",
270
- 7 => "property",
271
- 8 => "field",
272
- 9 => "constructor",
273
- 10 => "enum",
274
- 11 => "interface",
275
- 12 => "function",
276
- 13 => "variable",
277
- 14 => "const",
278
- 15 => "string",
279
- 16 => "number",
280
- 17 => "boolean",
281
- 18 => "array",
282
- 19 => "object",
283
- 20 => "key",
284
- 21 => "null",
285
- 22 => "enum_member",
286
- 23 => "struct",
287
- 24 => "event",
288
- 25 => "operator",
289
- 26 => "type_parameter",
290
- },
291
- T::Hash[Integer, String],
292
- )
262
+ SYMBOL_KINDS = {
263
+ 1 => "file",
264
+ 2 => "module",
265
+ 3 => "namespace",
266
+ 4 => "package",
267
+ 5 => "class",
268
+ 6 => "def",
269
+ 7 => "property",
270
+ 8 => "field",
271
+ 9 => "constructor",
272
+ 10 => "enum",
273
+ 11 => "interface",
274
+ 12 => "function",
275
+ 13 => "variable",
276
+ 14 => "const",
277
+ 15 => "string",
278
+ 16 => "number",
279
+ 17 => "boolean",
280
+ 18 => "array",
281
+ 19 => "object",
282
+ 20 => "key",
283
+ 21 => "null",
284
+ 22 => "enum_member",
285
+ 23 => "struct",
286
+ 24 => "event",
287
+ 25 => "operator",
288
+ 26 => "type_parameter",
289
+ } #: Hash[Integer, String]
293
290
  end
294
291
 
295
292
  class SymbolPrinter < Printer
@@ -302,7 +299,7 @@ module Spoom
302
299
  #: (?out: (IO | StringIO), ?colors: bool, ?indent_level: Integer, ?prefix: String?) -> void
303
300
  def initialize(out: $stdout, colors: true, indent_level: 0, prefix: nil)
304
301
  super(out: out, colors: colors, indent_level: indent_level)
305
- @seen = T.let(Set.new, T::Set[Integer])
302
+ @seen = Set.new #: Set[Integer]
306
303
  @out = out
307
304
  @colors = colors
308
305
  @indent_level = indent_level
@@ -13,12 +13,12 @@ module Spoom
13
13
  class Client
14
14
  #: (String sorbet_bin, *String sorbet_args, ?path: String) -> void
15
15
  def initialize(sorbet_bin, *sorbet_args, path: ".")
16
- @id = T.let(0, Integer)
17
- @open = T.let(false, T::Boolean)
16
+ @id = 0 #: Integer
17
+ @open = false #: bool
18
18
  io_in, io_out, io_err, _status = T.unsafe(Open3).popen3(sorbet_bin, *sorbet_args, chdir: path)
19
- @in = T.let(io_in, IO)
20
- @out = T.let(io_out, IO)
21
- @err = T.let(io_err, IO)
19
+ @in = io_in #: IO
20
+ @out = io_out #: IO
21
+ @err = io_err #: IO
22
22
  end
23
23
 
24
24
  #: -> Integer
@@ -14,19 +14,16 @@ module Spoom
14
14
  STRICTNESS_STRONG = "strong"
15
15
  STRICTNESS_INTERNAL = "__STDLIB_INTERNAL"
16
16
 
17
- VALID_STRICTNESS = T.let(
18
- [
19
- STRICTNESS_IGNORE,
20
- STRICTNESS_FALSE,
21
- STRICTNESS_TRUE,
22
- STRICTNESS_STRICT,
23
- STRICTNESS_STRONG,
24
- STRICTNESS_INTERNAL,
25
- ].freeze,
26
- T::Array[String],
27
- )
17
+ VALID_STRICTNESS = [
18
+ STRICTNESS_IGNORE,
19
+ STRICTNESS_FALSE,
20
+ STRICTNESS_TRUE,
21
+ STRICTNESS_STRICT,
22
+ STRICTNESS_STRONG,
23
+ STRICTNESS_INTERNAL,
24
+ ].freeze #: Array[String]
28
25
 
29
- SIGIL_REGEXP = T.let(/^#[[:blank:]]*typed:[[:blank:]]*(\S*)/, Regexp)
26
+ SIGIL_REGEXP = /^#[[:blank:]]*typed:[[:blank:]]*(\S*)/ #: Regexp
30
27
 
31
28
  class << self
32
29
  # returns the full sigil comment string for the passed strictness
@@ -95,8 +95,8 @@ module Spoom
95
95
  #: -> void
96
96
  def initialize
97
97
  super
98
- @sigs = T.let([], T::Array[[RBI::Sig, T.any(RBI::Method, RBI::Attr)]])
99
- @rbs_comments = T.let([], T::Array[[RBI::RBSComment, T.any(RBI::Method, RBI::Attr)]])
98
+ @sigs = [] #: Array[[RBI::Sig, (RBI::Method | RBI::Attr)]]
99
+ @rbs_comments = [] #: Array[[RBI::RBSComment, (RBI::Method | RBI::Attr)]]
100
100
  end
101
101
 
102
102
  # @override
@@ -246,13 +246,13 @@ module Spoom
246
246
 
247
247
  # From https://github.com/Shopify/ruby-lsp/blob/9154bfc6ef/lib/ruby_lsp/document.rb#L127
248
248
  class Scanner
249
- LINE_BREAK = T.let(0x0A, Integer)
249
+ LINE_BREAK = 0x0A #: Integer
250
250
 
251
251
  #: (String source) -> void
252
252
  def initialize(source)
253
- @current_line = T.let(0, Integer)
254
- @pos = T.let(0, Integer)
255
- @source = T.let(source.codepoints, T::Array[Integer])
253
+ @current_line = 0 #: Integer
254
+ @pos = 0 #: Integer
255
+ @source = source.codepoints #: Array[Integer]
256
256
  end
257
257
 
258
258
  # Finds the character index inside the source string for a given line and column
data/lib/spoom/sorbet.rb CHANGED
@@ -28,9 +28,9 @@ module Spoom
28
28
  end
29
29
 
30
30
  CONFIG_PATH = "sorbet/config"
31
- GEM_PATH = T.let(Gem::Specification.find_by_name("sorbet-static").full_gem_path, String)
32
- GEM_VERSION = T.let(Gem::Specification.find_by_name("sorbet-static-and-runtime").version.to_s, String)
33
- BIN_PATH = T.let((Pathname.new(GEM_PATH) / "libexec" / "sorbet").to_s, String)
31
+ GEM_PATH = Gem::Specification.find_by_name("sorbet-static").full_gem_path #: String
32
+ GEM_VERSION = Gem::Specification.find_by_name("sorbet-static-and-runtime").version.to_s #: String
33
+ BIN_PATH = (Pathname.new(GEM_PATH) / "libexec" / "sorbet").to_s #: String
34
34
 
35
35
  KILLED_CODE = 137
36
36
  SEGFAULT_CODE = 139
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.6.1"
5
+ VERSION = "1.6.2"
6
6
  end
data/lib/spoom.rb CHANGED
@@ -5,7 +5,7 @@ require "sorbet-runtime"
5
5
  require "pathname"
6
6
 
7
7
  module Spoom
8
- SPOOM_PATH = T.let((Pathname.new(__FILE__) / ".." / "..").to_s, String)
8
+ SPOOM_PATH = (Pathname.new(__FILE__) / ".." / "..").to_s #: String
9
9
 
10
10
  class Error < StandardError; end
11
11
  end