spoom 1.7.7 → 1.7.9

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: dee74aa6f300c648be7b9c74808c1f24507e3c806a9fb80565f6bad3a84ca724
4
- data.tar.gz: a6202c46d255610003479c753cd209a8511b5bc7511bcfe9d092e7619ed7d68a
3
+ metadata.gz: 24a0283b0a0b16cef6e3547725768b9d3d63673efec428dee7859e6bb398add0
4
+ data.tar.gz: 2e3037e4cf693ac776412e9817d2a1309a39b50bc58bff639dccce5fc9790a9e
5
5
  SHA512:
6
- metadata.gz: ed6f6fb93669b54ce54010fb657d8f3264e29e7c825382b49dbbc718aad8d48177392cc3ab89c9a2c669bf183c87653cb5c2682c222c311991cfaaca3f7e5088
7
- data.tar.gz: b763bdbc1480b4e6290cd152190726855bd0c0347cfd582ba12d79e3d106703cf3117a471ff4493c7f579d1713260e3c7b423d2de633fafaacb3945b26ae37d4
6
+ metadata.gz: 1168d181aa2f2d7512dfae7f01b8845a247bfecc5b8ea85441c9377a7bd33e51ab288d4078f3b86bbceef129c81721ba68a386095dd8feb215d0afea93bb1788
7
+ data.tar.gz: f9e7e65da944d81186ca772535b84befff429ce4c0cb9406ce2d0f6b9f0b5b46ba2efc67ab942782e635dd339139f9d902e71092a86c1ea28f221a0e219af0be
@@ -39,7 +39,11 @@ module Spoom
39
39
  glob("*")
40
40
  end
41
41
 
42
- #: (?allow_extensions: Array[String], ?allow_mime_types: Array[String], ?exclude_patterns: Array[String]) -> Array[String]
42
+ #: (
43
+ #| ?allow_extensions: Array[String],
44
+ #| ?allow_mime_types: Array[String],
45
+ #| ?exclude_patterns: Array[String]
46
+ #| ) -> Array[String]
43
47
  def collect_files(allow_extensions: [], allow_mime_types: [], exclude_patterns: [])
44
48
  collector = FileCollector.new(
45
49
  allow_extensions: allow_extensions,
@@ -145,7 +145,12 @@ module Spoom
145
145
  end
146
146
 
147
147
  class Sigils < CircleMap
148
- #: (String id, FileTree file_tree, Hash[FileTree::Node, String?] nodes_strictnesses, Hash[FileTree::Node, Float] nodes_scores) -> void
148
+ #: (
149
+ #| String id,
150
+ #| FileTree file_tree,
151
+ #| Hash[FileTree::Node, String?] nodes_strictnesses,
152
+ #| Hash[FileTree::Node, Float] nodes_scores
153
+ #| ) -> void
149
154
  def initialize(id, file_tree, nodes_strictnesses, nodes_scores)
150
155
  @nodes_strictnesses = nodes_strictnesses
151
156
  @nodes_scores = nodes_scores
@@ -138,7 +138,12 @@ module Spoom
138
138
  end
139
139
 
140
140
  class Map < Card
141
- #: (file_tree: FileTree, nodes_strictnesses: Hash[FileTree::Node, String?], nodes_strictness_scores: Hash[FileTree::Node, Float], ?title: String) -> void
141
+ #: (
142
+ #| file_tree: FileTree,
143
+ #| nodes_strictnesses: Hash[FileTree::Node, String?],
144
+ #| nodes_strictness_scores: Hash[FileTree::Node, Float],
145
+ #| ?title: String
146
+ #| ) -> void
142
147
  def initialize(file_tree:, nodes_strictnesses:, nodes_strictness_scores:, title: "Strictness Map")
143
148
  super(
144
149
  title: title,
@@ -222,7 +227,16 @@ module Spoom
222
227
  end
223
228
 
224
229
  class Report < Page
225
- #: (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
230
+ #: (
231
+ #| project_name: String,
232
+ #| palette: D3::ColorPalette,
233
+ #| snapshots: Array[Snapshot],
234
+ #| file_tree: FileTree,
235
+ #| nodes_strictnesses: Hash[FileTree::Node, String?],
236
+ #| nodes_strictness_scores: Hash[FileTree::Node, Float],
237
+ #| ?sorbet_intro_commit: String?,
238
+ #| ?sorbet_intro_date: Time?
239
+ #| ) -> void
226
240
  def initialize(
227
241
  project_name:,
228
242
  palette:,
@@ -49,7 +49,7 @@ module Spoom
49
49
 
50
50
  #: (String rb, file: String, ?plugins: Array[Plugins::Base]) -> void
51
51
  def index_ruby(rb, file:, plugins: [])
52
- node = Spoom.parse_ruby(rb, file: file, comments: true)
52
+ node, _ = Spoom.parse_ruby(rb, file: file)
53
53
 
54
54
  # Index definitions
55
55
  model_builder = Model::Builder.new(@model, file)
@@ -129,7 +129,13 @@ module Spoom
129
129
  #: String?
130
130
  attr_accessor :superclass_name
131
131
 
132
- #: (Symbol symbol, owner: Namespace?, location: Location, ?superclass_name: String?, ?comments: Array[Comment]) -> void
132
+ #: (
133
+ #| Symbol symbol,
134
+ #| owner: Namespace?,
135
+ #| location: Location,
136
+ #| ?superclass_name: String?,
137
+ #| ?comments: Array[Comment]
138
+ #| ) -> void
133
139
  def initialize(symbol, owner:, location:, superclass_name: nil, comments: [])
134
140
  super(symbol, owner: owner, location: location, comments: comments)
135
141
 
@@ -160,7 +166,14 @@ module Spoom
160
166
  #: Array[Sig]
161
167
  attr_reader :sigs
162
168
 
163
- #: (Symbol symbol, owner: Namespace?, location: Location, visibility: Visibility, ?sigs: Array[Sig], ?comments: Array[Comment]) -> void
169
+ #: (
170
+ #| Symbol symbol,
171
+ #| owner: Namespace?,
172
+ #| location: Location,
173
+ #| visibility: Visibility,
174
+ #| ?sigs: Array[Sig],
175
+ #| ?comments: Array[Comment]
176
+ #| ) -> void
164
177
  def initialize(symbol, owner:, location:, visibility:, sigs: [], comments: [])
165
178
  super(symbol, owner: owner, location: location, comments: comments)
166
179
 
data/lib/spoom/parse.rb CHANGED
@@ -7,22 +7,21 @@ module Spoom
7
7
  class ParseError < Error; end
8
8
 
9
9
  class << self
10
- #: (String ruby, file: String, ?comments: bool) -> Prism::Node
11
- def parse_ruby(ruby, file:, comments: false)
10
+ #: (String ruby, file: String) -> [Prism::Node, Array[Prism::Comment]]
11
+ def parse_ruby(ruby, file:)
12
12
  result = Prism.parse(ruby)
13
+
13
14
  unless result.success?
14
15
  message = +"Error while parsing #{file}:\n"
15
-
16
16
  result.errors.each do |e|
17
17
  message << "- #{e.message} (at #{e.location.start_line}:#{e.location.start_column})\n"
18
18
  end
19
-
20
19
  raise ParseError, message
21
20
  end
22
21
 
23
- result.attach_comments! if comments
22
+ result.attach_comments!
24
23
 
25
- result.value
24
+ [result.value, result.comments]
26
25
  end
27
26
  end
28
27
  end
data/lib/spoom/rbs.rb CHANGED
@@ -39,7 +39,13 @@ module Spoom
39
39
  def method_annotations
40
40
  @annotations.select do |annotation|
41
41
  case annotation.string
42
- when "@abstract", "@final", "@override", "@override(allow_incompatible: true)", "@overridable", "@without_runtime"
42
+ when "@abstract",
43
+ "@final",
44
+ "@override",
45
+ "@override(allow_incompatible: true)",
46
+ "@override(allow_incompatible: :visibility)",
47
+ "@overridable",
48
+ "@without_runtime"
43
49
  true
44
50
  else
45
51
  false
@@ -64,6 +70,7 @@ module Spoom
64
70
 
65
71
  class Annotation < Comment; end
66
72
  class Signature < Comment; end
73
+ class TypeAlias < Comment; end
67
74
 
68
75
  module ExtractRBSComments
69
76
  #: (Prism::Node) -> Comments
@@ -13,7 +13,7 @@ module Spoom
13
13
  counters.increment("files")
14
14
 
15
15
  content = File.read(file)
16
- node = Spoom.parse_ruby(content, file: file, comments: true)
16
+ node, _ = Spoom.parse_ruby(content, file: file)
17
17
  visitor = CodeMetricsVisitor.new(counters)
18
18
  visitor.visit(node)
19
19
  end
@@ -14,6 +14,16 @@ module Spoom
14
14
  @max_line_length = max_line_length
15
15
  end
16
16
 
17
+ # @override
18
+ #: (Prism::ProgramNode node) -> void
19
+ def visit_program_node(node)
20
+ # Process all type aliases from the entire file first
21
+ apply_type_aliases(@comments)
22
+
23
+ # Now process the rest of the file with type aliases available
24
+ super
25
+ end
26
+
17
27
  # @override
18
28
  #: (Prism::ClassNode node) -> void
19
29
  def visit_class_node(node)
@@ -248,6 +258,9 @@ module Spoom
248
258
  when "@override(allow_incompatible: true)"
249
259
  sig.is_override = true
250
260
  sig.allow_incompatible_override = true
261
+ when "@override(allow_incompatible: :visibility)"
262
+ sig.is_override = true
263
+ sig.allow_incompatible_override_visibility = true
251
264
  when "@overridable"
252
265
  sig.is_overridable = true
253
266
  when "@without_runtime"
@@ -271,6 +284,78 @@ module Spoom
271
284
  true
272
285
  end
273
286
  end
287
+
288
+ #: (Array[Prism::Comment]) -> Array[RBS::TypeAlias]
289
+ def collect_type_aliases(comments)
290
+ type_aliases = [] #: Array[RBS::TypeAlias]
291
+
292
+ return type_aliases if comments.empty?
293
+
294
+ continuation_comments = [] #: Array[Prism::Comment]
295
+
296
+ comments.reverse_each do |comment|
297
+ string = comment.slice
298
+
299
+ if string.start_with?("#:")
300
+ string = string.delete_prefix("#:").strip
301
+ location = comment.location
302
+
303
+ if string.start_with?("type ")
304
+ continuation_comments.reverse_each do |continuation_comment|
305
+ string = "#{string}#{continuation_comment.slice.delete_prefix("#|")}"
306
+ location = location.join(continuation_comment.location)
307
+ end
308
+
309
+ type_aliases << Spoom::RBS::TypeAlias.new(string, location)
310
+ end
311
+
312
+ # Clear the continuation comments regardless of whether we found a type alias or not
313
+ continuation_comments.clear
314
+ elsif string.start_with?("#|")
315
+ continuation_comments << comment
316
+ else
317
+ continuation_comments.clear
318
+ end
319
+ end
320
+
321
+ type_aliases
322
+ end
323
+
324
+ #: (Array[Prism::Comment]) -> void
325
+ def apply_type_aliases(comments)
326
+ type_aliases = collect_type_aliases(comments)
327
+
328
+ type_aliases.each do |type_alias|
329
+ indent = " " * type_alias.location.start_column
330
+ insert_pos = adjust_to_line_start(type_alias.location.start_offset)
331
+
332
+ from = insert_pos
333
+ to = adjust_to_line_end(type_alias.location.end_offset)
334
+
335
+ *, decls = ::RBS::Parser.parse_signature(type_alias.string)
336
+
337
+ # We only expect there to be a single type alias declaration
338
+ next unless decls.size == 1 && decls.first.is_a?(::RBS::AST::Declarations::TypeAlias)
339
+
340
+ rbs_type = decls.first
341
+ sorbet_type = RBI::RBS::TypeTranslator.translate(rbs_type.type)
342
+
343
+ alias_name = ::RBS::TypeName.new(
344
+ namespace: rbs_type.name.namespace,
345
+ name: rbs_type.name.name.to_s.gsub(/(?:^|_)([a-z\d]*)/i) do |match|
346
+ match = match.delete_prefix("_")
347
+ !match.empty? ? match[0].upcase.concat(match[1..-1]) : +""
348
+ end,
349
+ )
350
+
351
+ @rewriter << Source::Delete.new(from, to)
352
+ content = "#{indent}#{alias_name} = T.type_alias { #{sorbet_type.to_rbi} }\n"
353
+ @rewriter << Source::Insert.new(insert_pos, content)
354
+ rescue ::RBS::ParsingError, ::RBI::Error
355
+ # Ignore type aliases with errors
356
+ next
357
+ end
358
+ end
274
359
  end
275
360
  end
276
361
  end
@@ -74,8 +74,10 @@ module Spoom
74
74
  Prism::ClassVariableWriteNode, Prism::ClassVariableAndWriteNode, Prism::ClassVariableOperatorWriteNode, Prism::ClassVariableOrWriteNode,
75
75
  Prism::ConstantWriteNode, Prism::ConstantAndWriteNode, Prism::ConstantOperatorWriteNode, Prism::ConstantOrWriteNode,
76
76
  Prism::ConstantPathWriteNode, Prism::ConstantPathAndWriteNode, Prism::ConstantPathOperatorWriteNode, Prism::ConstantPathOrWriteNode,
77
- Prism::GlobalVariableWriteNode, Prism::GlobalVariableAndWriteNode, Prism::GlobalVariableOperatorWriteNode, Prism::GlobalVariableOrWriteNode,
78
- Prism::InstanceVariableWriteNode, Prism::InstanceVariableAndWriteNode, Prism::InstanceVariableOperatorWriteNode, Prism::InstanceVariableOrWriteNode,
77
+ Prism::GlobalVariableWriteNode, Prism::GlobalVariableAndWriteNode,
78
+ Prism::GlobalVariableOperatorWriteNode, Prism::GlobalVariableOrWriteNode,
79
+ Prism::InstanceVariableWriteNode, Prism::InstanceVariableAndWriteNode,
80
+ Prism::InstanceVariableOperatorWriteNode, Prism::InstanceVariableOrWriteNode,
79
81
  Prism::LocalVariableWriteNode, Prism::LocalVariableAndWriteNode, Prism::LocalVariableOperatorWriteNode, Prism::LocalVariableOrWriteNode,
80
82
  Prism::CallAndWriteNode, Prism::CallOperatorWriteNode, Prism::CallOrWriteNode
81
83
  node.value
@@ -260,7 +260,10 @@ module Spoom
260
260
 
261
261
  arg = body.body.first #: as Prism::Node
262
262
  srb_type = RBI::Type.parse_node(arg)
263
- @rewriter << Source::Insert.new(parent.location.start_offset, "# @requires_ancestor: #{srb_type.rbs_string}\n#{indent}")
263
+ @rewriter << Source::Insert.new(
264
+ parent.location.start_offset,
265
+ "# @requires_ancestor: #{srb_type.rbs_string}\n#{indent}",
266
+ )
264
267
  end
265
268
 
266
269
  from = adjust_to_line_start(node.location.start_offset)
@@ -294,6 +297,8 @@ module Spoom
294
297
  if sigs.any? { |_, sig| sig.is_override }
295
298
  @rewriter << if sigs.any? { |_, sig| sig.allow_incompatible_override }
296
299
  Source::Insert.new(insert_pos, "# @override(allow_incompatible: true)\n#{indent}")
300
+ elsif sigs.any? { |_, sig| sig.allow_incompatible_override_visibility }
301
+ Source::Insert.new(insert_pos, "# @override(allow_incompatible: :visibility)\n#{indent}")
297
302
  else
298
303
  Source::Insert.new(insert_pos, "# @override\n#{indent}")
299
304
  end
@@ -19,8 +19,9 @@ module Spoom
19
19
  ruby_contents.encode("UTF-8")
20
20
  end #: String
21
21
 
22
- node = Spoom.parse_ruby(ruby_contents, file: file, comments: true)
22
+ node, comments = Spoom.parse_ruby(ruby_contents, file: file)
23
23
  @node = node #: Prism::Node
24
+ @comments = comments #: Array[Prism::Comment]
24
25
  @ruby_bytes = ruby_contents.bytes #: Array[Integer]
25
26
  @rewriter = Spoom::Source::Rewriter.new #: Source::Rewriter
26
27
  end
@@ -92,7 +92,8 @@ module Spoom
92
92
  # @override
93
93
  #: (Array[Integer]) -> void
94
94
  def apply(bytes)
95
- raise PositionError, "Position is out of bounds" if from < 0 || to < 0 || from > bytes.size || to > bytes.size || from > to
95
+ raise PositionError,
96
+ "Position is out of bounds" if from < 0 || to < 0 || from > bytes.size || to > bytes.size || from > to
96
97
 
97
98
  bytes[from..to] = *text.bytes
98
99
  end
@@ -125,7 +126,8 @@ module Spoom
125
126
  # @override
126
127
  #: (Array[untyped]) -> void
127
128
  def apply(bytes)
128
- raise PositionError, "Position is out of bounds" if from < 0 || to < 0 || from > bytes.size || to > bytes.size || from > to
129
+ raise PositionError,
130
+ "Position is out of bounds" if from < 0 || to < 0 || from > bytes.size || to > bytes.size || from > to
129
131
 
130
132
  bytes[from..to] = "".bytes
131
133
  end
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.7.7"
5
+ VERSION = "1.7.9"
6
6
  end
data/rbi/spoom.rbi CHANGED
@@ -6,8 +6,8 @@
6
6
 
7
7
  module Spoom
8
8
  class << self
9
- sig { params(ruby: ::String, file: ::String, comments: T::Boolean).returns(::Prism::Node) }
10
- def parse_ruby(ruby, file:, comments: T.unsafe(nil)); end
9
+ sig { params(ruby: ::String, file: ::String).returns([::Prism::Node, T::Array[::Prism::Comment]]) }
10
+ def parse_ruby(ruby, file:); end
11
11
  end
12
12
  end
13
13
 
@@ -2584,6 +2584,7 @@ module Spoom::RBS::ExtractRBSComments
2584
2584
  end
2585
2585
 
2586
2586
  class Spoom::RBS::Signature < ::Spoom::RBS::Comment; end
2587
+ class Spoom::RBS::TypeAlias < ::Spoom::RBS::Comment; end
2587
2588
  Spoom::SPOOM_PATH = T.let(T.unsafe(nil), String)
2588
2589
  module Spoom::Sorbet; end
2589
2590
  Spoom::Sorbet::BIN_PATH = T.let(T.unsafe(nil), String)
@@ -2893,6 +2894,9 @@ class Spoom::Sorbet::Translate::RBSCommentsToSorbetSigs < ::Spoom::Sorbet::Trans
2893
2894
  sig { override.params(node: ::Prism::ModuleNode).void }
2894
2895
  def visit_module_node(node); end
2895
2896
 
2897
+ sig { override.params(node: ::Prism::ProgramNode).void }
2898
+ def visit_program_node(node); end
2899
+
2896
2900
  sig { override.params(node: ::Prism::SingletonClassNode).void }
2897
2901
  def visit_singleton_class_node(node); end
2898
2902
 
@@ -2912,6 +2916,12 @@ class Spoom::Sorbet::Translate::RBSCommentsToSorbetSigs < ::Spoom::Sorbet::Trans
2912
2916
  sig { params(annotations: T::Array[::Spoom::RBS::Annotation], sig: ::RBI::Sig).void }
2913
2917
  def apply_member_annotations(annotations, sig); end
2914
2918
 
2919
+ sig { params(comments: T::Array[::Prism::Comment]).void }
2920
+ def apply_type_aliases(comments); end
2921
+
2922
+ sig { params(comments: T::Array[::Prism::Comment]).returns(T::Array[::Spoom::RBS::TypeAlias]) }
2923
+ def collect_type_aliases(comments); end
2924
+
2915
2925
  sig { params(def_node: ::Prism::DefNode, comments: ::Spoom::RBS::Comments).void }
2916
2926
  def rewrite_def(def_node, comments); end
2917
2927
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spoom
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.7.7
4
+ version: 1.7.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexandre Terrasa