spoom 1.8.1 → 1.8.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.
- checksums.yaml +4 -4
- data/lib/spoom/deadcode/remover.rb +44 -1
- data/lib/spoom/rbs.rb +6 -1
- data/lib/spoom/sorbet/translate/rbs_comments_to_sorbet_sigs/base_translator.rb +2 -0
- data/lib/spoom/sorbet/translate/rbs_comments_to_sorbet_sigs/options.rb +7 -1
- data/lib/spoom/sorbet/translate/sorbet_assertions_to_rbs_comments.rb +51 -2
- data/lib/spoom/version.rb +1 -1
- data/rbi/spoom.rbi +23 -3
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9bf4851363229baee651a7eba14d9f45464db177f094f3b4da791a8b06b82d39
|
|
4
|
+
data.tar.gz: 6aae091a64fb4cb9a55cea3b82307bd413e544c424bd160599eee48cfeefa1e0
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ac5bbdffd2be7bb1c8c795eff3e8c332212fd19f033805076af2eee3c11d39ac1d614927dda68997498ed2dc96d929b71c865b7b2f5babbf52283085a807f1c9
|
|
7
|
+
data.tar.gz: 86d82cbeb9b56c7d4046c474e1880fb25c3dd32522a88f39fd3c0bb697b81d17641a4a5a7ac1603bcf319f18d513d429bbaea0ad1653cd29433ad51b0c9da195
|
|
@@ -48,8 +48,10 @@ module Spoom
|
|
|
48
48
|
|
|
49
49
|
node = @node_context.node
|
|
50
50
|
case node
|
|
51
|
-
when Prism::ClassNode, Prism::ModuleNode
|
|
51
|
+
when Prism::ClassNode, Prism::ModuleNode
|
|
52
52
|
delete_node_and_comments_and_sigs(@node_context)
|
|
53
|
+
when Prism::DefNode
|
|
54
|
+
delete_node_and_comments_and_sigs(modifier_call_context(node) || @node_context)
|
|
53
55
|
when Prism::ConstantWriteNode, Prism::ConstantOperatorWriteNode,
|
|
54
56
|
Prism::ConstantAndWriteNode, Prism::ConstantOrWriteNode,
|
|
55
57
|
Prism::ConstantPathWriteNode, Prism::ConstantPathOperatorWriteNode,
|
|
@@ -65,6 +67,47 @@ module Spoom
|
|
|
65
67
|
|
|
66
68
|
private
|
|
67
69
|
|
|
70
|
+
# When a method is defined as the argument of a modifier call (e.g. `private def foo; end` or
|
|
71
|
+
# `private_class_method def self.foo; end`), the `def` node's parent is the call rather than the
|
|
72
|
+
# enclosing class or module body, so its sigs and comments are siblings of the call. Return a
|
|
73
|
+
# context targeting the outermost such call so they are removed together with the method.
|
|
74
|
+
#
|
|
75
|
+
# Modifiers are matched structurally rather than from a fixed list, so user-defined ones are
|
|
76
|
+
# handled too. A call only counts as a modifier when the `def` is its sole argument and it takes
|
|
77
|
+
# no block and is a standalone statement, so we never remove a call that does more than wrap
|
|
78
|
+
# the method (e.g. `register(:thing, def foo; end)` or `FOO = register(def foo; end)`).
|
|
79
|
+
#: (Prism::DefNode def_node) -> NodeContext?
|
|
80
|
+
def modifier_call_context(def_node)
|
|
81
|
+
wrapped = def_node #: Prism::Node
|
|
82
|
+
nesting = @node_context.nesting.dup
|
|
83
|
+
outer_call = nil #: Prism::CallNode?
|
|
84
|
+
outer_nesting = nil #: Array[Prism::Node]?
|
|
85
|
+
|
|
86
|
+
while (ancestor = nesting.pop)
|
|
87
|
+
case ancestor
|
|
88
|
+
when Prism::ArgumentsNode
|
|
89
|
+
# An arguments node sits between a call and its arguments, keep climbing
|
|
90
|
+
next
|
|
91
|
+
when Prism::CallNode
|
|
92
|
+
# Stop unless the call wraps the node as its sole argument and takes no block, otherwise
|
|
93
|
+
# it does more than wrap the method and we must not remove it
|
|
94
|
+
args = ancestor.arguments&.arguments
|
|
95
|
+
break if ancestor.block
|
|
96
|
+
break unless args && args.size == 1 && args.first.equal?(wrapped)
|
|
97
|
+
|
|
98
|
+
wrapped = ancestor
|
|
99
|
+
outer_call = ancestor
|
|
100
|
+
outer_nesting = nesting.dup
|
|
101
|
+
else
|
|
102
|
+
break
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
return unless outer_call && outer_nesting
|
|
106
|
+
return unless outer_nesting.last.is_a?(Prism::StatementsNode)
|
|
107
|
+
|
|
108
|
+
NodeContext.new(@old_source, @node_context.comments, outer_call, outer_nesting)
|
|
109
|
+
end
|
|
110
|
+
|
|
68
111
|
#: (NodeContext context) -> void
|
|
69
112
|
def delete_constant_assignment(context)
|
|
70
113
|
case context.node
|
data/lib/spoom/rbs.rb
CHANGED
|
@@ -68,7 +68,12 @@ module Spoom
|
|
|
68
68
|
end
|
|
69
69
|
end
|
|
70
70
|
|
|
71
|
-
class Annotation < Comment
|
|
71
|
+
class Annotation < Comment
|
|
72
|
+
#: () -> bool
|
|
73
|
+
def abstract?
|
|
74
|
+
@string == "@abstract"
|
|
75
|
+
end
|
|
76
|
+
end
|
|
72
77
|
|
|
73
78
|
class Signature < Comment
|
|
74
79
|
# Locations of the `#|` continuation comment lines that make up a multiline signature,
|
|
@@ -25,6 +25,7 @@ module Spoom
|
|
|
25
25
|
end #: Integer?
|
|
26
26
|
|
|
27
27
|
@overloads_strategy = options.overloads_strategy #: Symbol
|
|
28
|
+
@translate_abstract_methods = options.translate_abstract_methods #: bool
|
|
28
29
|
@type_translator = RBI::RBS::TypeTranslator.new #: RBI::RBS::TypeTranslator
|
|
29
30
|
end
|
|
30
31
|
|
|
@@ -141,6 +142,7 @@ module Spoom
|
|
|
141
142
|
def rewrite_def(def_node, comments)
|
|
142
143
|
return if comments.empty?
|
|
143
144
|
return if comments.signatures.empty?
|
|
145
|
+
return if !@translate_abstract_methods && comments.method_annotations.any?(&:abstract?)
|
|
144
146
|
|
|
145
147
|
signatures = apply_overloads_strategy(
|
|
146
148
|
comments.signatures,
|
|
@@ -47,13 +47,18 @@ module Spoom
|
|
|
47
47
|
#: BaseRBIFormat
|
|
48
48
|
attr_reader :output_format
|
|
49
49
|
|
|
50
|
+
#: bool
|
|
51
|
+
attr_reader :translate_abstract_methods
|
|
52
|
+
|
|
50
53
|
#: (
|
|
51
54
|
#| ?overloads_strategy: Symbol,
|
|
52
55
|
#| ?output_format: BaseRBIFormat,
|
|
56
|
+
#| ?translate_abstract_methods: bool,
|
|
53
57
|
#| ) -> void
|
|
54
58
|
def initialize(
|
|
55
59
|
overloads_strategy: :translate_all,
|
|
56
|
-
output_format: HumanReadableRBIFormat.default
|
|
60
|
+
output_format: HumanReadableRBIFormat.default,
|
|
61
|
+
translate_abstract_methods: true
|
|
57
62
|
)
|
|
58
63
|
unless ALLOWED_OVERLOAD_STRATEGIES.include?(overloads_strategy)
|
|
59
64
|
raise ArgumentError, "Unknown overloads_strategy: #{overloads_strategy.inspect}. " \
|
|
@@ -62,6 +67,7 @@ module Spoom
|
|
|
62
67
|
|
|
63
68
|
@overloads_strategy = overloads_strategy
|
|
64
69
|
@output_format = output_format
|
|
70
|
+
@translate_abstract_methods = translate_abstract_methods
|
|
65
71
|
|
|
66
72
|
freeze
|
|
67
73
|
end
|
|
@@ -103,10 +103,12 @@ module Spoom
|
|
|
103
103
|
# Otherwise, replace up to the end of the node
|
|
104
104
|
end_offset = comment_end_offset || node.location.end_offset
|
|
105
105
|
|
|
106
|
+
heredoc_body = heredoc_body_within_range(value, end_offset)
|
|
107
|
+
|
|
106
108
|
replacement = if node.name == :bind
|
|
107
109
|
"#{rbs_annotation}#{trailing_comment}"
|
|
108
110
|
else
|
|
109
|
-
"#{dedent_value(node, value)} #{rbs_annotation}#{trailing_comment}"
|
|
111
|
+
"#{dedent_value(node, value)} #{rbs_annotation}#{trailing_comment}#{heredoc_body}"
|
|
110
112
|
end
|
|
111
113
|
|
|
112
114
|
@rewriter << Source::Replace.new(start_offset, end_offset - 1, replacement)
|
|
@@ -212,6 +214,53 @@ module Spoom
|
|
|
212
214
|
[" #{range.pack("C*")}", end_offset]
|
|
213
215
|
end
|
|
214
216
|
|
|
217
|
+
#: (Prism::Node, Integer) -> String?
|
|
218
|
+
def heredoc_body_within_range(node, replace_end_offset)
|
|
219
|
+
heredoc_end = heredoc_end_offsets(node)
|
|
220
|
+
.select { |offset| offset <= replace_end_offset }
|
|
221
|
+
.max
|
|
222
|
+
return unless heredoc_end
|
|
223
|
+
|
|
224
|
+
opener_line_end = adjust_to_line_end(node.location.end_offset)
|
|
225
|
+
body_bytes = @ruby_bytes[(opener_line_end + 1)...heredoc_end] #: as !nil
|
|
226
|
+
body = body_bytes.pack("C*")
|
|
227
|
+
body.chomp! if @ruby_bytes[replace_end_offset] == LINE_BREAK
|
|
228
|
+
"\n#{body}"
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
#: (Prism::Node) -> Array[Integer]
|
|
232
|
+
def heredoc_end_offsets(node)
|
|
233
|
+
offsets = [] #: Array[Integer]
|
|
234
|
+
|
|
235
|
+
case node
|
|
236
|
+
when Prism::StringNode, Prism::InterpolatedStringNode, Prism::XStringNode, Prism::InterpolatedXStringNode
|
|
237
|
+
opening = node.opening_loc
|
|
238
|
+
closing = node.closing_loc
|
|
239
|
+
if opening && closing && opening.start_line != closing.start_line && opening.slice.start_with?("<<")
|
|
240
|
+
offsets << closing.end_offset
|
|
241
|
+
end
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
node.child_nodes.each do |child|
|
|
245
|
+
next unless child
|
|
246
|
+
|
|
247
|
+
offsets.concat(heredoc_end_offsets(child))
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
offsets
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
#: (Prism::Node) -> bool
|
|
254
|
+
def string_literal?(node)
|
|
255
|
+
case node
|
|
256
|
+
when Prism::StringNode, Prism::InterpolatedStringNode,
|
|
257
|
+
Prism::XStringNode, Prism::InterpolatedXStringNode
|
|
258
|
+
true
|
|
259
|
+
else
|
|
260
|
+
false
|
|
261
|
+
end
|
|
262
|
+
end
|
|
263
|
+
|
|
215
264
|
#: (Prism::Node, Prism::Node) -> String
|
|
216
265
|
def dedent_value(assign, value)
|
|
217
266
|
if value.location.start_line == assign.location.start_line
|
|
@@ -243,7 +292,7 @@ module Spoom
|
|
|
243
292
|
# ```
|
|
244
293
|
indent = value.location.start_line - assign.location.start_line
|
|
245
294
|
lines = value.slice.lines
|
|
246
|
-
if lines.size > 1
|
|
295
|
+
if lines.size > 1 && !string_literal?(value)
|
|
247
296
|
lines[1..]&.each_with_index do |line, i|
|
|
248
297
|
lines[i + 1] = line.delete_prefix(" " * indent)
|
|
249
298
|
end
|
data/lib/spoom/version.rb
CHANGED
data/rbi/spoom.rbi
CHANGED
|
@@ -1519,6 +1519,9 @@ class Spoom::Deadcode::Remover::NodeRemover
|
|
|
1519
1519
|
end
|
|
1520
1520
|
def insert_accessor(node, send_context, was_removed:); end
|
|
1521
1521
|
|
|
1522
|
+
sig { params(def_node: ::Prism::DefNode).returns(T.nilable(::Spoom::Deadcode::Remover::NodeContext)) }
|
|
1523
|
+
def modifier_call_context(def_node); end
|
|
1524
|
+
|
|
1522
1525
|
sig { params(start_char: ::Integer, end_char: ::Integer, replacement: ::String).void }
|
|
1523
1526
|
def replace_chars(start_char, end_char, replacement); end
|
|
1524
1527
|
|
|
@@ -2575,7 +2578,11 @@ end
|
|
|
2575
2578
|
module Spoom::PrismTypes; end
|
|
2576
2579
|
Spoom::PrismTypes::AnyScopeNode = T.type_alias { T.any(::Prism::ClassNode, ::Prism::ModuleNode, ::Prism::SingletonClassNode) }
|
|
2577
2580
|
module Spoom::RBS; end
|
|
2578
|
-
|
|
2581
|
+
|
|
2582
|
+
class Spoom::RBS::Annotation < ::Spoom::RBS::Comment
|
|
2583
|
+
sig { returns(T::Boolean) }
|
|
2584
|
+
def abstract?; end
|
|
2585
|
+
end
|
|
2579
2586
|
|
|
2580
2587
|
class Spoom::RBS::Comment
|
|
2581
2588
|
sig { params(string: ::String, location: ::Prism::Location).void }
|
|
@@ -3206,10 +3213,11 @@ class Spoom::Sorbet::Translate::RBSCommentsToSorbetSigs::Options
|
|
|
3206
3213
|
sig do
|
|
3207
3214
|
params(
|
|
3208
3215
|
overloads_strategy: ::Symbol,
|
|
3209
|
-
output_format: ::Spoom::Sorbet::Translate::RBSCommentsToSorbetSigs::BaseRBIFormat
|
|
3216
|
+
output_format: ::Spoom::Sorbet::Translate::RBSCommentsToSorbetSigs::BaseRBIFormat,
|
|
3217
|
+
translate_abstract_methods: T::Boolean
|
|
3210
3218
|
).void
|
|
3211
3219
|
end
|
|
3212
|
-
def initialize(overloads_strategy: T.unsafe(nil), output_format: T.unsafe(nil)); end
|
|
3220
|
+
def initialize(overloads_strategy: T.unsafe(nil), output_format: T.unsafe(nil), translate_abstract_methods: T.unsafe(nil)); end
|
|
3213
3221
|
|
|
3214
3222
|
sig { returns(::Spoom::Sorbet::Translate::RBSCommentsToSorbetSigs::BaseRBIFormat) }
|
|
3215
3223
|
def output_format; end
|
|
@@ -3217,6 +3225,9 @@ class Spoom::Sorbet::Translate::RBSCommentsToSorbetSigs::Options
|
|
|
3217
3225
|
sig { returns(::Symbol) }
|
|
3218
3226
|
def overloads_strategy; end
|
|
3219
3227
|
|
|
3228
|
+
sig { returns(T::Boolean) }
|
|
3229
|
+
def translate_abstract_methods; end
|
|
3230
|
+
|
|
3220
3231
|
class << self
|
|
3221
3232
|
sig { returns(::Spoom::Sorbet::Translate::RBSCommentsToSorbetSigs::Options) }
|
|
3222
3233
|
def default; end
|
|
@@ -3262,9 +3273,18 @@ class Spoom::Sorbet::Translate::SorbetAssertionsToRBSComments < ::Spoom::Sorbet:
|
|
|
3262
3273
|
sig { params(node: ::Prism::Node).returns(T::Boolean) }
|
|
3263
3274
|
def has_rbs_annotation?(node); end
|
|
3264
3275
|
|
|
3276
|
+
sig { params(node: ::Prism::Node, replace_end_offset: ::Integer).returns(T.nilable(::String)) }
|
|
3277
|
+
def heredoc_body_within_range(node, replace_end_offset); end
|
|
3278
|
+
|
|
3279
|
+
sig { params(node: ::Prism::Node).returns(T::Array[::Integer]) }
|
|
3280
|
+
def heredoc_end_offsets(node); end
|
|
3281
|
+
|
|
3265
3282
|
sig { params(node: ::Prism::Node).returns(T::Boolean) }
|
|
3266
3283
|
def maybe_translate_assertion(node); end
|
|
3267
3284
|
|
|
3285
|
+
sig { params(node: ::Prism::Node).returns(T::Boolean) }
|
|
3286
|
+
def string_literal?(node); end
|
|
3287
|
+
|
|
3268
3288
|
sig { params(node: T.nilable(::Prism::Node)).returns(T::Boolean) }
|
|
3269
3289
|
def t?(node); end
|
|
3270
3290
|
|