spoom 1.7.2 → 1.7.4

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: 59987238a3b2bae115f02d1da2a7e2a4cd6b3532d816bbe80d9153fa7819f989
4
- data.tar.gz: d7e6bccfa046b7c457cb3e5d3d4383141243949021bd584b22cde0db0cc165ef
3
+ metadata.gz: e63e36fda1906fc8f047e6c4abab3ab8c887035f9e7b6c4c1d2c07d55ae3adaf
4
+ data.tar.gz: bf63f0df57b0c6dbed78a6a10021a6e94cdbbddbb8e072d145805829dae78cf2
5
5
  SHA512:
6
- metadata.gz: b2f53478b7fdee59bfa7c579c3686b6d6c388db8737584c02f613daa2c4d42c0be2c1baaa39c50e90137697f62d7b8bb04e9fdbb458defdfa7813be3b6cbbd36
7
- data.tar.gz: 57b26d457d2235bedaff15c832accc34a9c5ffcb89876306394f12b74a87ce03964d0309cd62e213e9954607150968607227436ebeb522a84f27782f7cc8cac8
6
+ metadata.gz: 51d63f6ef122e99b679f317fe2082df8956c7f0e25cf11afd612395101edf67e025698ef2e9a4deac795c0d49077e18cbf9e46771313536deb79f3aec5e31d21
7
+ data.tar.gz: bb0a342c5c8ac4bfd0a5310d2ced6541b13d0980fdab309124fca657192fcb8fefe34bde16a347d3974563989f38713a1519a389f803a7c1ace4b18e17fe1438
data/Gemfile CHANGED
@@ -5,6 +5,8 @@ source "https://rubygems.org"
5
5
 
6
6
  gemspec
7
7
 
8
+ gem "minitest"
9
+
8
10
  group :development do
9
11
  gem "debug"
10
12
  gem "rubocop-shopify", require: false
@@ -7,13 +7,10 @@ require "stringio"
7
7
 
8
8
  module Spoom
9
9
  module Cli
10
+ # @requires_ancestor: Thor
10
11
  module Helper
11
- extend T::Helpers
12
-
13
12
  include Colorize
14
13
 
15
- requires_ancestor { Thor }
16
-
17
14
  # Print `message` on `$stdout`
18
15
  #: (String message) -> void
19
16
  def say(message)
@@ -16,15 +16,26 @@ module Spoom
16
16
  desc: "Use positional names when translating from RBI to RBS",
17
17
  default: true
18
18
  option :include_rbi_files, type: :boolean, desc: "Include RBI files", default: false
19
+ option :max_line_length, type: :numeric, desc: "Max line length (pass 0 to disable)", default: 120
19
20
  def translate(*paths)
20
21
  from = options[:from]
21
22
  to = options[:to]
23
+ max_line_length = options[:max_line_length]
22
24
 
23
25
  if from == to
24
26
  say_error("Can't translate signatures from `#{from}` to `#{to}`")
25
27
  exit(1)
26
28
  end
27
29
 
30
+ if max_line_length.nil? || max_line_length.zero?
31
+ max_line_length = nil
32
+ elsif max_line_length.negative?
33
+ say_error("--max-line-length can't be negative")
34
+ exit(1)
35
+ else
36
+ max_line_length = max_line_length.to_i
37
+ end
38
+
28
39
  files = collect_files(paths, include_rbi_files: options[:include_rbi_files])
29
40
 
30
41
  say("Translating signatures from `#{from}` to `#{to}` " \
@@ -33,11 +44,20 @@ module Spoom
33
44
  case from
34
45
  when "rbi"
35
46
  transformed_files = transform_files(files) do |file, contents|
36
- Spoom::Sorbet::Translate.sorbet_sigs_to_rbs_comments(contents, file: file, positional_names: options[:positional_names])
47
+ Spoom::Sorbet::Translate.sorbet_sigs_to_rbs_comments(
48
+ contents,
49
+ file: file,
50
+ positional_names: options[:positional_names],
51
+ max_line_length: max_line_length,
52
+ )
37
53
  end
38
54
  when "rbs"
39
55
  transformed_files = transform_files(files) do |file, contents|
40
- Spoom::Sorbet::Translate.rbs_comments_to_sorbet_sigs(contents, file: file)
56
+ Spoom::Sorbet::Translate.rbs_comments_to_sorbet_sigs(
57
+ contents,
58
+ file: file,
59
+ max_line_length: max_line_length,
60
+ )
41
61
  end
42
62
  end
43
63
 
@@ -4,11 +4,8 @@
4
4
  module Spoom
5
5
  class Context
6
6
  # Bundle features for a context
7
+ # @requires_ancestor: Context
7
8
  module Bundle
8
- extend T::Helpers
9
-
10
- requires_ancestor { Context }
11
-
12
9
  # Read the contents of the Gemfile in this context directory
13
10
  #: -> String?
14
11
  def read_gemfile
@@ -22,11 +22,8 @@ module Spoom
22
22
 
23
23
  class Context
24
24
  # Execution features for a context
25
+ # @requires_ancestor: Context
25
26
  module Exec
26
- extend T::Helpers
27
-
28
- requires_ancestor { Context }
29
-
30
27
  # Run a command in this context directory
31
28
  #: (String command, ?capture_err: bool) -> ExecResult
32
29
  def exec(command, capture_err: true)
@@ -4,11 +4,8 @@
4
4
  module Spoom
5
5
  class Context
6
6
  # File System features for a context
7
+ # @requires_ancestor: Context
7
8
  module FileSystem
8
- extend T::Helpers
9
-
10
- requires_ancestor { Context }
11
-
12
9
  # Returns the absolute path to `relative_path` in the context's directory
13
10
  #: (String relative_path) -> String
14
11
  def absolute_path_to(relative_path)
@@ -28,11 +28,8 @@ module Spoom
28
28
 
29
29
  class Context
30
30
  # Git features for a context
31
+ # @requires_ancestor: Context
31
32
  module Git
32
- extend T::Helpers
33
-
34
- requires_ancestor { Context }
35
-
36
33
  # Run a command prefixed by `git` in this context directory
37
34
  #: (String command) -> ExecResult
38
35
  def git(command)
@@ -4,11 +4,8 @@
4
4
  module Spoom
5
5
  class Context
6
6
  # Sorbet features for a context
7
+ # @requires_ancestor: Context
7
8
  module Sorbet
8
- extend T::Helpers
9
-
10
- requires_ancestor { Context }
11
-
12
9
  # Run `bundle exec srb` in this context directory
13
10
  #: (*String arg, ?sorbet_bin: String?, ?capture_err: bool) -> ExecResult
14
11
  def srb(*arg, sorbet_bin: nil, capture_err: true)
@@ -4,12 +4,8 @@
4
4
  module Spoom
5
5
  module Coverage
6
6
  module D3
7
+ # @abstract
7
8
  class Base
8
- extend T::Sig
9
- extend T::Helpers
10
-
11
- abstract!
12
-
13
9
  #: String
14
10
  attr_reader :id
15
11
 
@@ -44,7 +40,8 @@ module Spoom
44
40
  ""
45
41
  end
46
42
 
47
- sig { abstract.returns(String) }
43
+ # @abstract
44
+ #: -> String
48
45
  def script; end
49
46
  end
50
47
  end
@@ -6,11 +6,8 @@ require_relative "base"
6
6
  module Spoom
7
7
  module Coverage
8
8
  module D3
9
+ # @abstract
9
10
  class Pie < Base
10
- extend T::Helpers
11
-
12
- abstract!
13
-
14
11
  #: (String id, String title, untyped data) -> void
15
12
  def initialize(id, title, data)
16
13
  super(id, data)
@@ -6,11 +6,8 @@ require_relative "base"
6
6
  module Spoom
7
7
  module Coverage
8
8
  module D3
9
+ # @abstract
9
10
  class Timeline < Base
10
- extend T::Helpers
11
-
12
- abstract!
13
-
14
11
  #: (String id, untyped data, Array[String] keys) -> void
15
12
  def initialize(id, data, keys)
16
13
  super(id, data)
@@ -120,7 +117,8 @@ module Spoom
120
117
  HTML
121
118
  end
122
119
 
123
- sig { abstract.returns(String) }
120
+ # @abstract
121
+ #: -> String
124
122
  def plot; end
125
123
 
126
124
  #: -> String
@@ -324,11 +322,8 @@ module Spoom
324
322
  end
325
323
  end
326
324
 
325
+ # @abstract
327
326
  class Stacked < Timeline
328
- extend T::Helpers
329
-
330
- abstract!
331
-
332
327
  # @override
333
328
  #: -> String
334
329
  def script
@@ -7,11 +7,8 @@ require "erb"
7
7
 
8
8
  module Spoom
9
9
  module Coverage
10
+ # @abstract
10
11
  class Template
11
- extend T::Helpers
12
-
13
- abstract!
14
-
15
12
  # Create a new template from an Erb file path
16
13
  #: (template: String) -> void
17
14
  def initialize(template:)
@@ -34,12 +31,8 @@ module Spoom
34
31
  end
35
32
  end
36
33
 
34
+ # @abstract
37
35
  class Page < Template
38
- extend T::Sig
39
- extend T::Helpers
40
-
41
- abstract!
42
-
43
36
  TEMPLATE = "#{Spoom::SPOOM_PATH}/templates/page.erb" #: String
44
37
 
45
38
  #: String
@@ -75,7 +68,8 @@ module Spoom
75
68
  cards.map(&:html).join("\n")
76
69
  end
77
70
 
78
- sig { abstract.returns(T::Array[Cards::Card]) }
71
+ # @abstract
72
+ #: -> Array[Cards::Card]
79
73
  def cards; end
80
74
 
81
75
  #: -> String
@@ -86,8 +80,6 @@ module Spoom
86
80
 
87
81
  module Cards
88
82
  class Card < Template
89
- extend T::Sig
90
-
91
83
  TEMPLATE = "#{Spoom::SPOOM_PATH}/templates/card.erb" #: String
92
84
 
93
85
  #: String?
@@ -101,11 +93,8 @@ module Spoom
101
93
  end
102
94
  end
103
95
 
96
+ # @abstract
104
97
  class Erb < Card
105
- extend T::Helpers
106
-
107
- abstract!
108
-
109
98
  #: -> void
110
99
  def initialize; end # rubocop:disable Lint/MissingSuper
111
100
 
@@ -115,7 +104,8 @@ module Spoom
115
104
  ERB.new(erb).result(get_binding)
116
105
  end
117
106
 
118
- sig { abstract.returns(String) }
107
+ # @abstract
108
+ #: -> String
119
109
  def erb; end
120
110
  end
121
111
 
@@ -7,6 +7,25 @@ module Spoom
7
7
  class ActiveJob < Base
8
8
  ignore_classes_named("ApplicationJob")
9
9
  ignore_methods_named("perform", "build_enumerator", "each_iteration")
10
+
11
+ CALLBACKS = [
12
+ "after_enqueue",
13
+ "after_perform",
14
+ "around_enqueue",
15
+ "around_perform",
16
+ "before_enqueue",
17
+ "before_perform",
18
+ ].freeze
19
+
20
+ # @override
21
+ #: (Send send) -> void
22
+ def on_send(send)
23
+ return unless send.recv.nil? && CALLBACKS.include?(send.name)
24
+
25
+ send.each_arg(Prism::SymbolNode) do |arg|
26
+ @index.reference_method(arg.unescaped, send.location)
27
+ end
28
+ end
10
29
  end
11
30
  end
12
31
  end
@@ -6,11 +6,8 @@ require "set"
6
6
  module Spoom
7
7
  module Deadcode
8
8
  module Plugins
9
+ # @abstract
9
10
  class Base
10
- extend T::Helpers
11
-
12
- abstract!
13
-
14
11
  class << self
15
12
  # Plugins DSL
16
13
 
@@ -94,11 +94,8 @@ module Spoom
94
94
  end
95
95
 
96
96
  # An abstract visitor for FileTree
97
+ # @abstract
97
98
  class Visitor
98
- extend T::Helpers
99
-
100
- abstract!
101
-
102
99
  #: (FileTree tree) -> void
103
100
  def visit_tree(tree)
104
101
  visit_nodes(tree.roots)
@@ -63,11 +63,8 @@ module Spoom
63
63
  #
64
64
  # It can be a class, module, constant, method, etc.
65
65
  # A SymbolDef has a location pointing to the actual code that defines the symbol.
66
+ # @abstract
66
67
  class SymbolDef
67
- extend T::Helpers
68
-
69
- abstract!
70
-
71
68
  # The symbol this definition belongs to
72
69
  #: Symbol
73
70
  attr_reader :symbol
@@ -109,9 +106,8 @@ module Spoom
109
106
  end
110
107
 
111
108
  # A class or module
109
+ # @abstract
112
110
  class Namespace < SymbolDef
113
- abstract!
114
-
115
111
  #: Array[SymbolDef]
116
112
  attr_reader :children
117
113
 
@@ -156,9 +152,8 @@ module Spoom
156
152
  end
157
153
 
158
154
  # A method or an attribute accessor
155
+ # @abstract
159
156
  class Property < SymbolDef
160
- abstract!
161
-
162
157
  #: Visibility
163
158
  attr_reader :visibility
164
159
 
@@ -176,8 +171,8 @@ module Spoom
176
171
 
177
172
  class Method < Property; end
178
173
 
174
+ # @abstract
179
175
  class Attr < Property
180
- abstract!
181
176
  end
182
177
 
183
178
  class AttrReader < Attr; end
@@ -193,11 +188,8 @@ module Spoom
193
188
  end
194
189
 
195
190
  # A mixin (include, prepend, extend) to a namespace
191
+ # @abstract
196
192
  class Mixin
197
- extend T::Helpers
198
-
199
- abstract!
200
-
201
193
  #: String
202
194
  attr_reader :name
203
195
 
@@ -234,7 +226,7 @@ module Spoom
234
226
  #: -> void
235
227
  def initialize
236
228
  @symbols = {} #: Hash[String, Symbol]
237
- @symbols_hierarchy = Poset[Symbol].new #: Poset[Symbol]
229
+ @symbols_hierarchy = Poset.new #: Poset[Symbol]
238
230
  end
239
231
 
240
232
  # Get a symbol by it's full name
@@ -3,11 +3,8 @@
3
3
 
4
4
  module Spoom
5
5
  class Model
6
+ # @abstract
6
7
  class NamespaceVisitor < Visitor
7
- extend T::Helpers
8
-
9
- abstract!
10
-
11
8
  #: -> void
12
9
  def initialize
13
10
  super()
data/lib/spoom/poset.rb CHANGED
@@ -6,13 +6,10 @@ module Spoom
6
6
  #
7
7
  # The partial order relation is a binary relation that is reflexive, antisymmetric, and transitive.
8
8
  # It can be used to represent a hierarchy of classes or modules, the dependencies between gems, etc.
9
+ #: [E < Object]
9
10
  class Poset
10
- extend T::Generic
11
-
12
11
  class Error < Spoom::Error; end
13
12
 
14
- E = type_member { { upper: Object } }
15
-
16
13
  #: -> void
17
14
  def initialize
18
15
  @elements = {} #: Hash[E, Element[E]]
@@ -35,7 +32,7 @@ module Spoom
35
32
  element = @elements[value]
36
33
  return element if element
37
34
 
38
- @elements[value] = Element[E].new(value)
35
+ @elements[value] = Element.new(value) #: Element[E]
39
36
  end
40
37
 
41
38
  # Is the given value a element in the POSet?
@@ -132,12 +129,10 @@ module Spoom
132
129
  end
133
130
 
134
131
  # An element in a POSet
132
+ #: [E < Object]
135
133
  class Element
136
- extend T::Generic
137
134
  include Comparable
138
135
 
139
- E = type_member { { upper: Object } }
140
-
141
136
  # The value held by this element
142
137
  #: E
143
138
  attr_reader :value
data/lib/spoom/rbs.rb CHANGED
@@ -4,7 +4,7 @@
4
4
  module Spoom
5
5
  module RBS
6
6
  class Comments
7
- #: Array[Annotations]
7
+ #: Array[Annotation]
8
8
  attr_reader :annotations
9
9
 
10
10
  #: Array[Signature]
@@ -12,7 +12,7 @@ module Spoom
12
12
 
13
13
  #: -> void
14
14
  def initialize
15
- @annotations = [] #: Array[Annotations]
15
+ @annotations = [] #: Array[Annotation]
16
16
  @signatures = [] #: Array[Signature]
17
17
  end
18
18
 
@@ -20,6 +20,32 @@ module Spoom
20
20
  def empty?
21
21
  @annotations.empty? && @signatures.empty?
22
22
  end
23
+
24
+ #: -> Array[Annotation]
25
+ def class_annotations
26
+ @annotations.select do |annotation|
27
+ case annotation.string
28
+ when "@abstract", "@interface", "@sealed", "@final"
29
+ true
30
+ when /^@requires_ancestor: /
31
+ true
32
+ else
33
+ false
34
+ end
35
+ end
36
+ end
37
+
38
+ #: -> Array[Annotation]
39
+ def method_annotations
40
+ @annotations.select do |annotation|
41
+ case annotation.string
42
+ when "@abstract", "@final", "@override", "@override(allow_incompatible: true)", "@overridable", "@without_runtime"
43
+ true
44
+ else
45
+ false
46
+ end
47
+ end
48
+ end
23
49
  end
24
50
 
25
51
  class Comment
@@ -36,7 +62,7 @@ module Spoom
36
62
  end
37
63
  end
38
64
 
39
- class Annotations < Comment; end
65
+ class Annotation < Comment; end
40
66
  class Signature < Comment; end
41
67
 
42
68
  module ExtractRBSComments
@@ -54,7 +80,7 @@ module Spoom
54
80
 
55
81
  if string.start_with?("# @")
56
82
  string = string.delete_prefix("#").strip
57
- res.annotations << Annotations.new(string, comment.location)
83
+ res.annotations << Annotation.new(string, comment.location)
58
84
  elsif string.start_with?("#: ")
59
85
  string = string.delete_prefix("#:").strip
60
86
  location = comment.location
@@ -6,13 +6,10 @@ require "set"
6
6
 
7
7
  module Spoom
8
8
  module LSP
9
+ # @interface
9
10
  module PrintableSymbol
10
- extend T::Sig
11
- extend T::Helpers
12
-
13
- interface!
14
-
15
- sig { abstract.params(printer: SymbolPrinter).void }
11
+ # @abstract
12
+ #: (SymbolPrinter printer) -> void
16
13
  def accept_printer(printer); end
17
14
  end
18
15
 
@@ -34,9 +34,6 @@ module Spoom
34
34
  class CodeMetricsVisitor < Spoom::Visitor
35
35
  include RBS::ExtractRBSComments
36
36
 
37
- #: Counters
38
- attr_reader :counters
39
-
40
37
  #: (Spoom::Counters) -> void
41
38
  def initialize(counters)
42
39
  super()
@@ -7,6 +7,13 @@ module Spoom
7
7
  class RBSCommentsToSorbetSigs < Translator
8
8
  include Spoom::RBS::ExtractRBSComments
9
9
 
10
+ #: (String, file: String, ?max_line_length: Integer?) -> void
11
+ def initialize(ruby_contents, file:, max_line_length: nil)
12
+ super(ruby_contents, file: file)
13
+
14
+ @max_line_length = max_line_length
15
+ end
16
+
10
17
  # @override
11
18
  #: (Prism::ClassNode node) -> void
12
19
  def visit_class_node(node)
@@ -48,14 +55,14 @@ module Spoom
48
55
  translator = RBI::RBS::MethodTypeTranslator.new(rbi_node)
49
56
  translator.visit(method_type)
50
57
  sig = translator.result
51
- apply_member_annotations(comments.annotations, sig)
58
+ apply_member_annotations(comments.method_annotations, sig)
52
59
 
53
60
  @rewriter << Source::Replace.new(
54
61
  signature.location.start_offset,
55
62
  signature.location.end_offset,
56
- sig.string,
63
+ sig.string(max_line_length: @max_line_length),
57
64
  )
58
- rescue ::RBS::ParsingError
65
+ rescue ::RBS::ParsingError, ::RBI::Error
59
66
  # Ignore signatures with errors
60
67
  next
61
68
  end
@@ -99,13 +106,16 @@ module Spoom
99
106
 
100
107
  sig.return_type = RBI::RBS::TypeTranslator.translate(attr_type)
101
108
 
102
- apply_member_annotations(comments.annotations, sig)
109
+ apply_member_annotations(comments.method_annotations, sig)
103
110
 
104
111
  @rewriter << Source::Replace.new(
105
112
  signature.location.start_offset,
106
113
  signature.location.end_offset,
107
- sig.string,
114
+ sig.string(max_line_length: @max_line_length),
108
115
  )
116
+ rescue ::RBS::ParsingError, ::RBI::Error
117
+ # Ignore signatures with errors
118
+ next
109
119
  end
110
120
  end
111
121
 
@@ -124,12 +134,13 @@ module Spoom
124
134
  node.expression.location.end_offset
125
135
  end
126
136
 
127
- if comments.annotations.any?
137
+ class_annotations = comments.class_annotations
138
+ if class_annotations.any?
128
139
  unless already_extends?(node, /^(::)?T::Helpers$/)
129
140
  @rewriter << Source::Insert.new(insert_pos, "\n#{indent}extend T::Helpers\n")
130
141
  end
131
142
 
132
- comments.annotations.reverse_each do |annotation|
143
+ class_annotations.reverse_each do |annotation|
133
144
  from = adjust_to_line_start(annotation.location.start_offset)
134
145
  to = adjust_to_line_end(annotation.location.end_offset)
135
146
 
@@ -154,6 +165,9 @@ module Spoom
154
165
 
155
166
  newline = node.body.nil? ? "" : "\n"
156
167
  @rewriter << Source::Insert.new(insert_pos, "\n#{indent}#{content}#{newline}")
168
+ rescue ::RBS::ParsingError, ::RBI::Error
169
+ # Ignore annotations with errors
170
+ next
157
171
  end
158
172
  end
159
173
 
@@ -195,12 +209,15 @@ module Spoom
195
209
 
196
210
  newline = node.body.nil? ? "" : "\n"
197
211
  @rewriter << Source::Insert.new(insert_pos, "\n#{indent}#{type_member}#{newline}")
212
+ rescue ::RBS::ParsingError, ::RBI::Error
213
+ # Ignore signatures with errors
214
+ next
198
215
  end
199
216
  end
200
217
  end
201
218
  end
202
219
 
203
- #: (Array[RBS::Annotations], RBI::Sig) -> void
220
+ #: (Array[RBS::Annotation], RBI::Sig) -> void
204
221
  def apply_member_annotations(annotations, sig)
205
222
  annotations.each do |annotation|
206
223
  case annotation.string