spoom 1.7.2 → 1.7.3
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/Gemfile +2 -0
- data/lib/spoom/deadcode/plugins/active_job.rb +19 -0
- data/lib/spoom/rbs.rb +30 -4
- data/lib/spoom/sorbet/metrics/code_metrics_visitor.rb +0 -3
- data/lib/spoom/sorbet/translate/rbs_comments_to_sorbet_sigs.rb +16 -6
- data/lib/spoom/sorbet/translate/sorbet_assertions_to_rbs_comments.rb +67 -8
- data/lib/spoom/sorbet/translate/sorbet_sigs_to_rbs_comments.rb +85 -30
- data/lib/spoom/source/rewriter.rb +4 -1
- data/lib/spoom/version.rb +1 -1
- data/rbi/spoom.rbi +68 -66
- metadata +3 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c8447b66e12a52fef3147761f8331749ba52cebaaba146888a7ca35a253acdf9
|
4
|
+
data.tar.gz: d6a84c3091e71c56d26aceebb40f3a6486589266c0b9b984268bf32036b98a26
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9827d000700721b1e30028eedcaf41c5e5e45811e1b62693dbaa2d859b5adf379c5f5da4acbaac8e0a0a78a8bb4928fbd5d8a395b5527a7c1f3fc0a72f207cc3
|
7
|
+
data.tar.gz: a7c46380dc2e26c622b8b96290964ede0b5f455d060a176d1336db3aa09ca3e7dbccb656d7a6c1451e43406b0e9cf7847b9a985418b905ae8114c20dae294240
|
data/Gemfile
CHANGED
@@ -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
|
data/lib/spoom/rbs.rb
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
module Spoom
|
5
5
|
module RBS
|
6
6
|
class Comments
|
7
|
-
#: Array[
|
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[
|
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
|
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 <<
|
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
|
@@ -48,14 +48,14 @@ module Spoom
|
|
48
48
|
translator = RBI::RBS::MethodTypeTranslator.new(rbi_node)
|
49
49
|
translator.visit(method_type)
|
50
50
|
sig = translator.result
|
51
|
-
apply_member_annotations(comments.
|
51
|
+
apply_member_annotations(comments.method_annotations, sig)
|
52
52
|
|
53
53
|
@rewriter << Source::Replace.new(
|
54
54
|
signature.location.start_offset,
|
55
55
|
signature.location.end_offset,
|
56
56
|
sig.string,
|
57
57
|
)
|
58
|
-
rescue ::RBS::ParsingError
|
58
|
+
rescue ::RBS::ParsingError, ::RBI::Error
|
59
59
|
# Ignore signatures with errors
|
60
60
|
next
|
61
61
|
end
|
@@ -99,13 +99,16 @@ module Spoom
|
|
99
99
|
|
100
100
|
sig.return_type = RBI::RBS::TypeTranslator.translate(attr_type)
|
101
101
|
|
102
|
-
apply_member_annotations(comments.
|
102
|
+
apply_member_annotations(comments.method_annotations, sig)
|
103
103
|
|
104
104
|
@rewriter << Source::Replace.new(
|
105
105
|
signature.location.start_offset,
|
106
106
|
signature.location.end_offset,
|
107
107
|
sig.string,
|
108
108
|
)
|
109
|
+
rescue ::RBS::ParsingError, ::RBI::Error
|
110
|
+
# Ignore signatures with errors
|
111
|
+
next
|
109
112
|
end
|
110
113
|
end
|
111
114
|
|
@@ -124,12 +127,13 @@ module Spoom
|
|
124
127
|
node.expression.location.end_offset
|
125
128
|
end
|
126
129
|
|
127
|
-
|
130
|
+
class_annotations = comments.class_annotations
|
131
|
+
if class_annotations.any?
|
128
132
|
unless already_extends?(node, /^(::)?T::Helpers$/)
|
129
133
|
@rewriter << Source::Insert.new(insert_pos, "\n#{indent}extend T::Helpers\n")
|
130
134
|
end
|
131
135
|
|
132
|
-
|
136
|
+
class_annotations.reverse_each do |annotation|
|
133
137
|
from = adjust_to_line_start(annotation.location.start_offset)
|
134
138
|
to = adjust_to_line_end(annotation.location.end_offset)
|
135
139
|
|
@@ -154,6 +158,9 @@ module Spoom
|
|
154
158
|
|
155
159
|
newline = node.body.nil? ? "" : "\n"
|
156
160
|
@rewriter << Source::Insert.new(insert_pos, "\n#{indent}#{content}#{newline}")
|
161
|
+
rescue ::RBS::ParsingError, ::RBI::Error
|
162
|
+
# Ignore annotations with errors
|
163
|
+
next
|
157
164
|
end
|
158
165
|
end
|
159
166
|
|
@@ -195,12 +202,15 @@ module Spoom
|
|
195
202
|
|
196
203
|
newline = node.body.nil? ? "" : "\n"
|
197
204
|
@rewriter << Source::Insert.new(insert_pos, "\n#{indent}#{type_member}#{newline}")
|
205
|
+
rescue ::RBS::ParsingError, ::RBI::Error
|
206
|
+
# Ignore signatures with errors
|
207
|
+
next
|
198
208
|
end
|
199
209
|
end
|
200
210
|
end
|
201
211
|
end
|
202
212
|
|
203
|
-
#: (Array[RBS::
|
213
|
+
#: (Array[RBS::Annotation], RBI::Sig) -> void
|
204
214
|
def apply_member_annotations(annotations, sig)
|
205
215
|
annotations.each do |annotation|
|
206
216
|
case annotation.string
|
@@ -9,22 +9,75 @@ module Spoom
|
|
9
9
|
LINE_BREAK = "\n".ord #: Integer
|
10
10
|
|
11
11
|
# @override
|
12
|
-
#: (Prism::
|
13
|
-
def
|
14
|
-
|
15
|
-
|
12
|
+
#: (Prism::StatementsNode) -> void
|
13
|
+
def visit_statements_node(node)
|
14
|
+
node.body.each do |statement|
|
15
|
+
translated = maybe_translate_assertion(statement)
|
16
|
+
visit(statement) unless translated
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# @override
|
21
|
+
#: (Prism::IfNode) -> void
|
22
|
+
def visit_if_node(node)
|
23
|
+
if node.if_keyword_loc
|
24
|
+
# We do not translate assertions in ternary expressions to avoid altering the semantic of the code.
|
25
|
+
#
|
26
|
+
# For example:
|
27
|
+
# ```rb
|
28
|
+
# a = T.must(b) ? T.must(c) : T.must(d)
|
29
|
+
# ```
|
30
|
+
#
|
31
|
+
# would become
|
32
|
+
# ```rb
|
33
|
+
# a = T.must(b) ? T.must(c) : d #: !nil
|
34
|
+
# ```
|
35
|
+
#
|
36
|
+
# which does not match the original intent.
|
37
|
+
super
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
#: (Prism::Node) -> bool
|
44
|
+
def maybe_translate_assertion(node)
|
45
|
+
node = case node
|
46
|
+
when Prism::MultiWriteNode,
|
47
|
+
Prism::ClassVariableWriteNode, Prism::ClassVariableAndWriteNode, Prism::ClassVariableOperatorWriteNode, Prism::ClassVariableOrWriteNode,
|
48
|
+
Prism::ConstantWriteNode, Prism::ConstantAndWriteNode, Prism::ConstantOperatorWriteNode, Prism::ConstantOrWriteNode,
|
49
|
+
Prism::ConstantPathWriteNode, Prism::ConstantPathAndWriteNode, Prism::ConstantPathOperatorWriteNode, Prism::ConstantPathOrWriteNode,
|
50
|
+
Prism::GlobalVariableWriteNode, Prism::GlobalVariableAndWriteNode, Prism::GlobalVariableOperatorWriteNode, Prism::GlobalVariableOrWriteNode,
|
51
|
+
Prism::InstanceVariableWriteNode, Prism::InstanceVariableAndWriteNode, Prism::InstanceVariableOperatorWriteNode, Prism::InstanceVariableOrWriteNode,
|
52
|
+
Prism::LocalVariableWriteNode, Prism::LocalVariableAndWriteNode, Prism::LocalVariableOperatorWriteNode, Prism::LocalVariableOrWriteNode,
|
53
|
+
Prism::CallAndWriteNode, Prism::CallOperatorWriteNode, Prism::CallOrWriteNode
|
54
|
+
node.value
|
55
|
+
when Prism::CallNode
|
56
|
+
node
|
57
|
+
else
|
58
|
+
return false
|
59
|
+
end
|
60
|
+
|
61
|
+
return false unless node.is_a?(Prism::CallNode)
|
62
|
+
return false unless t_annotation?(node)
|
63
|
+
return false unless at_end_of_line?(node)
|
16
64
|
|
17
65
|
value = T.must(node.arguments&.arguments&.first)
|
18
66
|
rbs_annotation = build_rbs_annotation(node)
|
19
67
|
|
20
68
|
start_offset = node.location.start_offset
|
21
69
|
end_offset = node.location.end_offset
|
22
|
-
@rewriter << Source::Replace.new(start_offset, end_offset - 1, "#{dedent_value(node, value)} #{rbs_annotation}")
|
23
|
-
end
|
24
70
|
|
25
|
-
|
71
|
+
@rewriter << if node.name == :bind
|
72
|
+
Source::Replace.new(start_offset, end_offset - 1, rbs_annotation)
|
73
|
+
else
|
74
|
+
Source::Replace.new(start_offset, end_offset - 1, "#{dedent_value(node, value)} #{rbs_annotation}")
|
75
|
+
end
|
76
|
+
|
77
|
+
true
|
78
|
+
end
|
26
79
|
|
27
|
-
#: (Prism::CallNode) ->
|
80
|
+
#: (Prism::CallNode) -> String
|
28
81
|
def build_rbs_annotation(call)
|
29
82
|
case call.name
|
30
83
|
when :let
|
@@ -35,6 +88,10 @@ module Spoom
|
|
35
88
|
srb_type = call.arguments&.arguments&.last #: as !nil
|
36
89
|
rbs_type = RBI::Type.parse_node(srb_type).rbs_string
|
37
90
|
"#: as #{rbs_type}"
|
91
|
+
when :bind
|
92
|
+
srb_type = call.arguments&.arguments&.last #: as !nil
|
93
|
+
rbs_type = RBI::Type.parse_node(srb_type).rbs_string
|
94
|
+
"#: self as #{rbs_type}"
|
38
95
|
when :must
|
39
96
|
"#: as !nil"
|
40
97
|
when :unsafe
|
@@ -65,6 +122,8 @@ module Spoom
|
|
65
122
|
case node.name
|
66
123
|
when :let, :cast
|
67
124
|
return node.arguments&.arguments&.size == 2
|
125
|
+
when :bind
|
126
|
+
return node.arguments&.arguments&.size == 2 && node.arguments&.arguments&.first.is_a?(Prism::SelfNode)
|
68
127
|
when :must, :unsafe
|
69
128
|
return node.arguments&.arguments&.size == 1
|
70
129
|
end
|
@@ -12,9 +12,12 @@ module Spoom
|
|
12
12
|
super(ruby_contents, file: file)
|
13
13
|
|
14
14
|
@positional_names = positional_names #: bool
|
15
|
-
@nesting = [] #: Array[Prism::ClassNode | Prism::ModuleNode | Prism::SingletonClassNode]
|
16
15
|
@last_sigs = [] #: Array[[Prism::CallNode, RBI::Sig]]
|
16
|
+
@class_annotations = [] #: Array[Prism::CallNode]
|
17
17
|
@type_members = [] #: Array[String]
|
18
|
+
@extend_t_helpers = [] #: Array[Prism::CallNode]
|
19
|
+
@extend_t_generics = [] #: Array[Prism::CallNode]
|
20
|
+
@seen_mixes_in_class_methods = false #: bool
|
18
21
|
end
|
19
22
|
|
20
23
|
# @override
|
@@ -38,17 +41,18 @@ module Spoom
|
|
38
41
|
# @override
|
39
42
|
#: (Prism::DefNode) -> void
|
40
43
|
def visit_def_node(node)
|
41
|
-
|
42
|
-
return if
|
44
|
+
last_sigs = collect_last_sigs
|
45
|
+
return if last_sigs.empty?
|
46
|
+
return if last_sigs.any? { |_, sig| sig.is_abstract }
|
43
47
|
|
44
|
-
apply_member_annotations(
|
48
|
+
apply_member_annotations(last_sigs)
|
45
49
|
|
46
50
|
# Build the RBI::Method node so we can print the method signature as RBS.
|
47
51
|
builder = RBI::Parser::TreeBuilder.new(@ruby_contents, comments: [], file: @file)
|
48
52
|
builder.visit(node)
|
49
53
|
rbi_node = builder.tree.nodes.first #: as RBI::Method
|
50
54
|
|
51
|
-
|
55
|
+
last_sigs.each do |node, sig|
|
52
56
|
out = StringIO.new
|
53
57
|
p = RBI::RBSPrinter.new(out: out, indent: node.location.start_column, positional_names: @positional_names)
|
54
58
|
p.print("#: ")
|
@@ -56,8 +60,6 @@ module Spoom
|
|
56
60
|
p.print("\n")
|
57
61
|
@rewriter << Source::Replace.new(node.location.start_offset, node.location.end_offset, out.string)
|
58
62
|
end
|
59
|
-
|
60
|
-
@last_sigs.clear
|
61
63
|
end
|
62
64
|
|
63
65
|
# @override
|
@@ -71,7 +73,9 @@ module Spoom
|
|
71
73
|
when "extend"
|
72
74
|
visit_extend(node)
|
73
75
|
when "abstract!", "interface!", "sealed!", "final!", "requires_ancestor"
|
74
|
-
|
76
|
+
@class_annotations << node
|
77
|
+
when "mixes_in_class_methods"
|
78
|
+
@seen_mixes_in_class_methods = true
|
75
79
|
else
|
76
80
|
super
|
77
81
|
end
|
@@ -97,19 +101,39 @@ module Spoom
|
|
97
101
|
|
98
102
|
#: (Prism::ClassNode | Prism::ModuleNode | Prism::SingletonClassNode) { -> void } -> void
|
99
103
|
def visit_scope(node, &block)
|
100
|
-
|
104
|
+
old_class_annotations = @class_annotations
|
105
|
+
@class_annotations = []
|
101
106
|
old_type_members = @type_members
|
102
107
|
@type_members = []
|
108
|
+
old_extend_t_helpers = @extend_t_helpers
|
109
|
+
@extend_t_helpers = []
|
110
|
+
old_extend_t_generics = @extend_t_generics
|
111
|
+
@extend_t_generics = []
|
112
|
+
old_seen_mixes_in_class_methods = @seen_mixes_in_class_methods
|
113
|
+
@seen_mixes_in_class_methods = false
|
103
114
|
|
104
115
|
yield
|
105
116
|
|
117
|
+
delete_extend_t_generics
|
118
|
+
|
106
119
|
if @type_members.any?
|
107
120
|
indent = " " * node.location.start_column
|
108
121
|
@rewriter << Source::Insert.new(node.location.start_offset, "#: [#{@type_members.join(", ")}]\n#{indent}")
|
109
122
|
end
|
110
123
|
|
124
|
+
unless @seen_mixes_in_class_methods
|
125
|
+
delete_extend_t_helpers
|
126
|
+
end
|
127
|
+
|
128
|
+
@class_annotations.each do |call|
|
129
|
+
apply_class_annotation(node, call)
|
130
|
+
end
|
131
|
+
|
132
|
+
@class_annotations = old_class_annotations
|
111
133
|
@type_members = old_type_members
|
112
|
-
@
|
134
|
+
@extend_t_helpers = old_extend_t_helpers
|
135
|
+
@extend_t_generics = old_extend_t_generics
|
136
|
+
@seen_mixes_in_class_methods = old_seen_mixes_in_class_methods
|
113
137
|
end
|
114
138
|
|
115
139
|
#: (Prism::CallNode) -> void
|
@@ -130,16 +154,17 @@ module Spoom
|
|
130
154
|
raise Error, "Expected attr_reader, attr_writer, or attr_accessor"
|
131
155
|
end
|
132
156
|
|
133
|
-
|
134
|
-
return if
|
157
|
+
last_sigs = collect_last_sigs
|
158
|
+
return if last_sigs.empty?
|
159
|
+
return if last_sigs.any? { |_, sig| sig.is_abstract }
|
135
160
|
|
136
|
-
apply_member_annotations(
|
161
|
+
apply_member_annotations(last_sigs)
|
137
162
|
|
138
163
|
builder = RBI::Parser::TreeBuilder.new(@ruby_contents, comments: [], file: @file)
|
139
164
|
builder.visit(node)
|
140
165
|
rbi_node = builder.tree.nodes.first #: as RBI::Attr
|
141
166
|
|
142
|
-
|
167
|
+
last_sigs.each do |node, sig|
|
143
168
|
out = StringIO.new
|
144
169
|
p = RBI::RBSPrinter.new(out: out, indent: node.location.start_column, positional_names: @positional_names)
|
145
170
|
p.print("#: ")
|
@@ -147,8 +172,6 @@ module Spoom
|
|
147
172
|
p.print("\n")
|
148
173
|
@rewriter << Source::Replace.new(node.location.start_offset, node.location.end_offset, out.string)
|
149
174
|
end
|
150
|
-
|
151
|
-
@last_sigs.clear
|
152
175
|
end
|
153
176
|
|
154
177
|
#: (Prism::CallNode node) -> void
|
@@ -160,16 +183,17 @@ module Spoom
|
|
160
183
|
|
161
184
|
arg = node.arguments&.arguments&.first
|
162
185
|
return unless arg.is_a?(Prism::ConstantPathNode)
|
163
|
-
return unless arg.slice.match?(/^(::)?T::Helpers$/) || arg.slice.match?(/^(::)?T::Generic$/)
|
164
186
|
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
187
|
+
case arg.slice
|
188
|
+
when /^(::)?T::Helpers$/
|
189
|
+
@extend_t_helpers << node
|
190
|
+
when /^(::)?T::Generic$/
|
191
|
+
@extend_t_generics << node
|
192
|
+
end
|
169
193
|
end
|
170
194
|
|
171
|
-
#: (Prism::CallNode
|
172
|
-
def
|
195
|
+
#: (Prism::ClassNode | Prism::ModuleNode | Prism::SingletonClassNode, Prism::CallNode) -> void
|
196
|
+
def apply_class_annotation(parent, node)
|
173
197
|
unless node.message == "abstract!" || node.message == "interface!" || node.message == "sealed!" ||
|
174
198
|
node.message == "final!" || node.message == "requires_ancestor"
|
175
199
|
raise Error, "Expected abstract!, interface!, sealed!, final!, or requires_ancestor"
|
@@ -178,18 +202,17 @@ module Spoom
|
|
178
202
|
return unless node.receiver.nil? || node.receiver.is_a?(Prism::SelfNode)
|
179
203
|
return unless node.arguments.nil?
|
180
204
|
|
181
|
-
|
182
|
-
indent = " " * klass.location.start_column
|
205
|
+
indent = " " * parent.location.start_column
|
183
206
|
|
184
207
|
case node.message
|
185
208
|
when "abstract!"
|
186
|
-
@rewriter << Source::Insert.new(
|
209
|
+
@rewriter << Source::Insert.new(parent.location.start_offset, "# @abstract\n#{indent}")
|
187
210
|
when "interface!"
|
188
|
-
@rewriter << Source::Insert.new(
|
211
|
+
@rewriter << Source::Insert.new(parent.location.start_offset, "# @interface\n#{indent}")
|
189
212
|
when "sealed!"
|
190
|
-
@rewriter << Source::Insert.new(
|
213
|
+
@rewriter << Source::Insert.new(parent.location.start_offset, "# @sealed\n#{indent}")
|
191
214
|
when "final!"
|
192
|
-
@rewriter << Source::Insert.new(
|
215
|
+
@rewriter << Source::Insert.new(parent.location.start_offset, "# @final\n#{indent}")
|
193
216
|
when "requires_ancestor"
|
194
217
|
block = node.block
|
195
218
|
return unless block.is_a?(Prism::BlockNode)
|
@@ -200,7 +223,7 @@ module Spoom
|
|
200
223
|
|
201
224
|
arg = body.body.first #: as Prism::Node
|
202
225
|
srb_type = RBI::Type.parse_node(arg)
|
203
|
-
@rewriter << Source::Insert.new(
|
226
|
+
@rewriter << Source::Insert.new(parent.location.start_offset, "# @requires_ancestor: #{srb_type.rbs_string}\n#{indent}")
|
204
227
|
end
|
205
228
|
|
206
229
|
from = adjust_to_line_start(node.location.start_offset)
|
@@ -287,6 +310,38 @@ module Spoom
|
|
287
310
|
|
288
311
|
type_member
|
289
312
|
end
|
313
|
+
|
314
|
+
#: -> void
|
315
|
+
def delete_extend_t_helpers
|
316
|
+
@extend_t_helpers.each do |helper|
|
317
|
+
from = adjust_to_line_start(helper.location.start_offset)
|
318
|
+
to = adjust_to_line_end(helper.location.end_offset)
|
319
|
+
to = adjust_to_new_line(to)
|
320
|
+
@rewriter << Source::Delete.new(from, to)
|
321
|
+
end
|
322
|
+
|
323
|
+
@extend_t_helpers.clear
|
324
|
+
end
|
325
|
+
|
326
|
+
#: -> void
|
327
|
+
def delete_extend_t_generics
|
328
|
+
@extend_t_generics.each do |generic|
|
329
|
+
from = adjust_to_line_start(generic.location.start_offset)
|
330
|
+
to = adjust_to_line_end(generic.location.end_offset)
|
331
|
+
to = adjust_to_new_line(to)
|
332
|
+
@rewriter << Source::Delete.new(from, to)
|
333
|
+
end
|
334
|
+
|
335
|
+
@extend_t_generics.clear
|
336
|
+
end
|
337
|
+
|
338
|
+
# Collects the last signatures visited and clears the current list
|
339
|
+
#: -> Array[[Prism::CallNode, RBI::Sig]]
|
340
|
+
def collect_last_sigs
|
341
|
+
last_sigs = @last_sigs
|
342
|
+
@last_sigs = []
|
343
|
+
last_sigs
|
344
|
+
end
|
290
345
|
end
|
291
346
|
end
|
292
347
|
end
|
@@ -158,7 +158,10 @@ module Spoom
|
|
158
158
|
def rewrite!(bytes)
|
159
159
|
# To avoid remapping positions after each edit,
|
160
160
|
# we sort the changes by position and apply them in reverse order.
|
161
|
-
|
161
|
+
# When ranges are equal, preserve the original order
|
162
|
+
@edits.each_with_index.sort_by do |(edit, idx)|
|
163
|
+
[edit.range, idx]
|
164
|
+
end.reverse_each do |(edit, _)|
|
162
165
|
edit.apply(bytes)
|
163
166
|
end
|
164
167
|
end
|
data/lib/spoom/version.rb
CHANGED
data/rbi/spoom.rbi
CHANGED
@@ -432,6 +432,12 @@ module Spoom::Context::Sorbet
|
|
432
432
|
end
|
433
433
|
|
434
434
|
class Spoom::Counters < ::Hash
|
435
|
+
extend T::Generic
|
436
|
+
|
437
|
+
K = type_member { { fixed: String } }
|
438
|
+
V = type_member { { fixed: Integer } }
|
439
|
+
Elem = type_member { { fixed: [String, Integer] } }
|
440
|
+
|
435
441
|
sig { void }
|
436
442
|
def initialize; end
|
437
443
|
|
@@ -645,10 +651,6 @@ class Spoom::Coverage::D3::ColorPalette < ::T::Struct
|
|
645
651
|
prop :true, ::String
|
646
652
|
prop :strict, ::String
|
647
653
|
prop :strong, ::String
|
648
|
-
|
649
|
-
class << self
|
650
|
-
def inherited(s); end
|
651
|
-
end
|
652
654
|
end
|
653
655
|
|
654
656
|
class Spoom::Coverage::D3::Pie < ::Spoom::Coverage::D3::Base
|
@@ -899,8 +901,6 @@ class Spoom::Coverage::Snapshot < ::T::Struct
|
|
899
901
|
|
900
902
|
sig { params(obj: T::Hash[::String, T.untyped]).returns(::Spoom::Coverage::Snapshot) }
|
901
903
|
def from_obj(obj); end
|
902
|
-
|
903
|
-
def inherited(s); end
|
904
904
|
end
|
905
905
|
end
|
906
906
|
|
@@ -990,10 +990,6 @@ class Spoom::Deadcode::Definition < ::T::Struct
|
|
990
990
|
|
991
991
|
sig { params(args: T.untyped).returns(::String) }
|
992
992
|
def to_json(*args); end
|
993
|
-
|
994
|
-
class << self
|
995
|
-
def inherited(s); end
|
996
|
-
end
|
997
993
|
end
|
998
994
|
|
999
995
|
class Spoom::Deadcode::Definition::Kind < ::T::Enum
|
@@ -1136,7 +1132,13 @@ class Spoom::Deadcode::Plugins::ActionPack < ::Spoom::Deadcode::Plugins::Base
|
|
1136
1132
|
end
|
1137
1133
|
|
1138
1134
|
Spoom::Deadcode::Plugins::ActionPack::CALLBACKS = T.let(T.unsafe(nil), Array)
|
1139
|
-
|
1135
|
+
|
1136
|
+
class Spoom::Deadcode::Plugins::ActiveJob < ::Spoom::Deadcode::Plugins::Base
|
1137
|
+
sig { override.params(send: ::Spoom::Deadcode::Send).void }
|
1138
|
+
def on_send(send); end
|
1139
|
+
end
|
1140
|
+
|
1141
|
+
Spoom::Deadcode::Plugins::ActiveJob::CALLBACKS = T.let(T.unsafe(nil), Array)
|
1140
1142
|
|
1141
1143
|
class Spoom::Deadcode::Plugins::ActiveModel < ::Spoom::Deadcode::Plugins::Base
|
1142
1144
|
sig { override.params(send: ::Spoom::Deadcode::Send).void }
|
@@ -1521,10 +1523,6 @@ class Spoom::Deadcode::Send < ::T::Struct
|
|
1521
1523
|
|
1522
1524
|
sig { params(block: T.proc.params(key: ::Prism::Node, value: T.nilable(::Prism::Node)).void).void }
|
1523
1525
|
def each_arg_assoc(&block); end
|
1524
|
-
|
1525
|
-
class << self
|
1526
|
-
def inherited(s); end
|
1527
|
-
end
|
1528
1526
|
end
|
1529
1527
|
|
1530
1528
|
class Spoom::Error < ::StandardError; end
|
@@ -1537,10 +1535,6 @@ class Spoom::ExecResult < ::T::Struct
|
|
1537
1535
|
|
1538
1536
|
sig { returns(::String) }
|
1539
1537
|
def to_s; end
|
1540
|
-
|
1541
|
-
class << self
|
1542
|
-
def inherited(s); end
|
1543
|
-
end
|
1544
1538
|
end
|
1545
1539
|
|
1546
1540
|
class Spoom::FileCollector
|
@@ -1660,10 +1654,6 @@ class Spoom::FileTree::Node < ::T::Struct
|
|
1660
1654
|
|
1661
1655
|
sig { returns(::String) }
|
1662
1656
|
def path; end
|
1663
|
-
|
1664
|
-
class << self
|
1665
|
-
def inherited(s); end
|
1666
|
-
end
|
1667
1657
|
end
|
1668
1658
|
|
1669
1659
|
class Spoom::FileTree::Printer < ::Spoom::FileTree::Visitor
|
@@ -1708,8 +1698,6 @@ class Spoom::Git::Commit < ::T::Struct
|
|
1708
1698
|
def timestamp; end
|
1709
1699
|
|
1710
1700
|
class << self
|
1711
|
-
def inherited(s); end
|
1712
|
-
|
1713
1701
|
sig { params(string: ::String).returns(T.nilable(::Spoom::Git::Commit)) }
|
1714
1702
|
def parse_line(string); end
|
1715
1703
|
end
|
@@ -1788,8 +1776,6 @@ class Spoom::LSP::Diagnostic < ::T::Struct
|
|
1788
1776
|
class << self
|
1789
1777
|
sig { params(json: T::Hash[T.untyped, T.untyped]).returns(::Spoom::LSP::Diagnostic) }
|
1790
1778
|
def from_json(json); end
|
1791
|
-
|
1792
|
-
def inherited(s); end
|
1793
1779
|
end
|
1794
1780
|
end
|
1795
1781
|
|
@@ -1815,8 +1801,6 @@ class Spoom::LSP::DocumentSymbol < ::T::Struct
|
|
1815
1801
|
class << self
|
1816
1802
|
sig { params(json: T::Hash[T.untyped, T.untyped]).returns(::Spoom::LSP::DocumentSymbol) }
|
1817
1803
|
def from_json(json); end
|
1818
|
-
|
1819
|
-
def inherited(s); end
|
1820
1804
|
end
|
1821
1805
|
end
|
1822
1806
|
|
@@ -1856,8 +1840,6 @@ class Spoom::LSP::Hover < ::T::Struct
|
|
1856
1840
|
class << self
|
1857
1841
|
sig { params(json: T::Hash[T.untyped, T.untyped]).returns(::Spoom::LSP::Hover) }
|
1858
1842
|
def from_json(json); end
|
1859
|
-
|
1860
|
-
def inherited(s); end
|
1861
1843
|
end
|
1862
1844
|
end
|
1863
1845
|
|
@@ -1876,8 +1858,6 @@ class Spoom::LSP::Location < ::T::Struct
|
|
1876
1858
|
class << self
|
1877
1859
|
sig { params(json: T::Hash[T.untyped, T.untyped]).returns(::Spoom::LSP::Location) }
|
1878
1860
|
def from_json(json); end
|
1879
|
-
|
1880
|
-
def inherited(s); end
|
1881
1861
|
end
|
1882
1862
|
end
|
1883
1863
|
|
@@ -1918,8 +1898,6 @@ class Spoom::LSP::Position < ::T::Struct
|
|
1918
1898
|
class << self
|
1919
1899
|
sig { params(json: T::Hash[T.untyped, T.untyped]).returns(::Spoom::LSP::Position) }
|
1920
1900
|
def from_json(json); end
|
1921
|
-
|
1922
|
-
def inherited(s); end
|
1923
1901
|
end
|
1924
1902
|
end
|
1925
1903
|
|
@@ -1945,8 +1923,6 @@ class Spoom::LSP::Range < ::T::Struct
|
|
1945
1923
|
class << self
|
1946
1924
|
sig { params(json: T::Hash[T.untyped, T.untyped]).returns(::Spoom::LSP::Range) }
|
1947
1925
|
def from_json(json); end
|
1948
|
-
|
1949
|
-
def inherited(s); end
|
1950
1926
|
end
|
1951
1927
|
end
|
1952
1928
|
|
@@ -1993,8 +1969,6 @@ class Spoom::LSP::SignatureHelp < ::T::Struct
|
|
1993
1969
|
class << self
|
1994
1970
|
sig { params(json: T::Hash[T.untyped, T.untyped]).returns(::Spoom::LSP::SignatureHelp) }
|
1995
1971
|
def from_json(json); end
|
1996
|
-
|
1997
|
-
def inherited(s); end
|
1998
1972
|
end
|
1999
1973
|
end
|
2000
1974
|
|
@@ -2291,8 +2265,6 @@ class Spoom::Model::Reference < ::T::Struct
|
|
2291
2265
|
sig { params(name: ::String, location: ::Spoom::Location).returns(::Spoom::Model::Reference) }
|
2292
2266
|
def constant(name, location); end
|
2293
2267
|
|
2294
|
-
def inherited(s); end
|
2295
|
-
|
2296
2268
|
sig { params(name: ::String, location: ::Spoom::Location).returns(::Spoom::Model::Reference) }
|
2297
2269
|
def method(name, location); end
|
2298
2270
|
end
|
@@ -2465,25 +2437,29 @@ end
|
|
2465
2437
|
class Spoom::ParseError < ::Spoom::Error; end
|
2466
2438
|
|
2467
2439
|
class Spoom::Poset
|
2440
|
+
extend T::Generic
|
2441
|
+
|
2442
|
+
E = type_member { { upper: Object } }
|
2443
|
+
|
2468
2444
|
sig { void }
|
2469
2445
|
def initialize; end
|
2470
2446
|
|
2471
|
-
sig { params(value:
|
2447
|
+
sig { params(value: E).returns(Spoom::Poset::Element[E]) }
|
2472
2448
|
def [](value); end
|
2473
2449
|
|
2474
|
-
sig { params(from:
|
2450
|
+
sig { params(from: E, to: E).void }
|
2475
2451
|
def add_direct_edge(from, to); end
|
2476
2452
|
|
2477
|
-
sig { params(value:
|
2453
|
+
sig { params(value: E).returns(Spoom::Poset::Element[E]) }
|
2478
2454
|
def add_element(value); end
|
2479
2455
|
|
2480
|
-
sig { params(from:
|
2456
|
+
sig { params(from: E, to: E).returns(T::Boolean) }
|
2481
2457
|
def direct_edge?(from, to); end
|
2482
2458
|
|
2483
|
-
sig { params(from:
|
2459
|
+
sig { params(from: E, to: E).returns(T::Boolean) }
|
2484
2460
|
def edge?(from, to); end
|
2485
2461
|
|
2486
|
-
sig { params(value:
|
2462
|
+
sig { params(value: E).returns(T::Boolean) }
|
2487
2463
|
def element?(value); end
|
2488
2464
|
|
2489
2465
|
sig { params(direct: T::Boolean, transitive: T::Boolean).void }
|
@@ -2494,36 +2470,39 @@ class Spoom::Poset
|
|
2494
2470
|
end
|
2495
2471
|
|
2496
2472
|
class Spoom::Poset::Element
|
2473
|
+
extend T::Generic
|
2497
2474
|
include ::Comparable
|
2498
2475
|
|
2499
|
-
|
2476
|
+
E = type_member { { upper: Object } }
|
2477
|
+
|
2478
|
+
sig { params(value: E).void }
|
2500
2479
|
def initialize(value); end
|
2501
2480
|
|
2502
2481
|
sig { params(other: T.untyped).returns(T.nilable(::Integer)) }
|
2503
2482
|
def <=>(other); end
|
2504
2483
|
|
2505
|
-
sig { returns(T::Array[
|
2484
|
+
sig { returns(T::Array[E]) }
|
2506
2485
|
def ancestors; end
|
2507
2486
|
|
2508
|
-
sig { returns(T::Array[
|
2487
|
+
sig { returns(T::Array[E]) }
|
2509
2488
|
def children; end
|
2510
2489
|
|
2511
|
-
sig { returns(T::Array[
|
2490
|
+
sig { returns(T::Array[E]) }
|
2512
2491
|
def descendants; end
|
2513
2492
|
|
2514
2493
|
def dfroms; end
|
2515
2494
|
|
2516
|
-
sig { returns(T::Set[Spoom::Poset::Element[
|
2495
|
+
sig { returns(T::Set[Spoom::Poset::Element[E]]) }
|
2517
2496
|
def dtos; end
|
2518
2497
|
|
2519
2498
|
def froms; end
|
2520
2499
|
|
2521
|
-
sig { returns(T::Array[
|
2500
|
+
sig { returns(T::Array[E]) }
|
2522
2501
|
def parents; end
|
2523
2502
|
|
2524
2503
|
def tos; end
|
2525
2504
|
|
2526
|
-
sig { returns(
|
2505
|
+
sig { returns(E) }
|
2527
2506
|
def value; end
|
2528
2507
|
end
|
2529
2508
|
|
@@ -2566,7 +2545,7 @@ class Spoom::Printer
|
|
2566
2545
|
end
|
2567
2546
|
|
2568
2547
|
module Spoom::RBS; end
|
2569
|
-
class Spoom::RBS::
|
2548
|
+
class Spoom::RBS::Annotation < ::Spoom::RBS::Comment; end
|
2570
2549
|
|
2571
2550
|
class Spoom::RBS::Comment
|
2572
2551
|
sig { params(string: ::String, location: ::Prism::Location).void }
|
@@ -2583,12 +2562,18 @@ class Spoom::RBS::Comments
|
|
2583
2562
|
sig { void }
|
2584
2563
|
def initialize; end
|
2585
2564
|
|
2586
|
-
sig { returns(T::Array[::Spoom::RBS::
|
2565
|
+
sig { returns(T::Array[::Spoom::RBS::Annotation]) }
|
2587
2566
|
def annotations; end
|
2588
2567
|
|
2568
|
+
sig { returns(T::Array[::Spoom::RBS::Annotation]) }
|
2569
|
+
def class_annotations; end
|
2570
|
+
|
2589
2571
|
sig { returns(T::Boolean) }
|
2590
2572
|
def empty?; end
|
2591
2573
|
|
2574
|
+
sig { returns(T::Array[::Spoom::RBS::Annotation]) }
|
2575
|
+
def method_annotations; end
|
2576
|
+
|
2592
2577
|
sig { returns(T::Array[::Spoom::RBS::Signature]) }
|
2593
2578
|
def signatures; end
|
2594
2579
|
end
|
@@ -2758,9 +2743,6 @@ class Spoom::Sorbet::Metrics::CodeMetricsVisitor < ::Spoom::Visitor
|
|
2758
2743
|
sig { params(counters: Spoom::Counters).void }
|
2759
2744
|
def initialize(counters); end
|
2760
2745
|
|
2761
|
-
sig { returns(Spoom::Counters) }
|
2762
|
-
def counters; end
|
2763
|
-
|
2764
2746
|
sig { override.params(node: T.nilable(::Prism::Node)).void }
|
2765
2747
|
def visit(node); end
|
2766
2748
|
|
@@ -2904,7 +2886,7 @@ class Spoom::Sorbet::Translate::RBSCommentsToSorbetSigs < ::Spoom::Sorbet::Trans
|
|
2904
2886
|
sig { params(node: T.any(::Prism::ClassNode, ::Prism::ModuleNode, ::Prism::SingletonClassNode)).void }
|
2905
2887
|
def apply_class_annotations(node); end
|
2906
2888
|
|
2907
|
-
sig { params(annotations: T::Array[::Spoom::RBS::
|
2889
|
+
sig { params(annotations: T::Array[::Spoom::RBS::Annotation], sig: ::RBI::Sig).void }
|
2908
2890
|
def apply_member_annotations(annotations, sig); end
|
2909
2891
|
|
2910
2892
|
sig { params(node: ::Prism::CallNode).void }
|
@@ -2912,20 +2894,26 @@ class Spoom::Sorbet::Translate::RBSCommentsToSorbetSigs < ::Spoom::Sorbet::Trans
|
|
2912
2894
|
end
|
2913
2895
|
|
2914
2896
|
class Spoom::Sorbet::Translate::SorbetAssertionsToRBSComments < ::Spoom::Sorbet::Translate::Translator
|
2915
|
-
sig { override.params(node: ::Prism::
|
2916
|
-
def
|
2897
|
+
sig { override.params(node: ::Prism::IfNode).void }
|
2898
|
+
def visit_if_node(node); end
|
2899
|
+
|
2900
|
+
sig { override.params(node: ::Prism::StatementsNode).void }
|
2901
|
+
def visit_statements_node(node); end
|
2917
2902
|
|
2918
2903
|
private
|
2919
2904
|
|
2920
2905
|
sig { params(node: ::Prism::Node).returns(T::Boolean) }
|
2921
2906
|
def at_end_of_line?(node); end
|
2922
2907
|
|
2923
|
-
sig { params(call: ::Prism::CallNode).
|
2908
|
+
sig { params(call: ::Prism::CallNode).returns(::String) }
|
2924
2909
|
def build_rbs_annotation(call); end
|
2925
2910
|
|
2926
2911
|
sig { params(assign: ::Prism::Node, value: ::Prism::Node).returns(::String) }
|
2927
2912
|
def dedent_value(assign, value); end
|
2928
2913
|
|
2914
|
+
sig { params(node: ::Prism::Node).returns(T::Boolean) }
|
2915
|
+
def maybe_translate_assertion(node); end
|
2916
|
+
|
2929
2917
|
sig { params(node: T.nilable(::Prism::Node)).returns(T::Boolean) }
|
2930
2918
|
def t?(node); end
|
2931
2919
|
|
@@ -2959,17 +2947,31 @@ class Spoom::Sorbet::Translate::SorbetSigsToRBSComments < ::Spoom::Sorbet::Trans
|
|
2959
2947
|
|
2960
2948
|
private
|
2961
2949
|
|
2950
|
+
sig do
|
2951
|
+
params(
|
2952
|
+
parent: T.any(::Prism::ClassNode, ::Prism::ModuleNode, ::Prism::SingletonClassNode),
|
2953
|
+
node: ::Prism::CallNode
|
2954
|
+
).void
|
2955
|
+
end
|
2956
|
+
def apply_class_annotation(parent, node); end
|
2957
|
+
|
2962
2958
|
sig { params(sigs: T::Array[[::Prism::CallNode, ::RBI::Sig]]).void }
|
2963
2959
|
def apply_member_annotations(sigs); end
|
2964
2960
|
|
2965
2961
|
sig { params(node: ::Prism::ConstantWriteNode).returns(::String) }
|
2966
2962
|
def build_type_member_string(node); end
|
2967
2963
|
|
2968
|
-
sig {
|
2969
|
-
def
|
2964
|
+
sig { returns(T::Array[[::Prism::CallNode, ::RBI::Sig]]) }
|
2965
|
+
def collect_last_sigs; end
|
2966
|
+
|
2967
|
+
sig { void }
|
2968
|
+
def delete_extend_t_generics; end
|
2969
|
+
|
2970
|
+
sig { void }
|
2971
|
+
def delete_extend_t_helpers; end
|
2970
2972
|
|
2971
2973
|
sig { params(node: ::Prism::CallNode).void }
|
2972
|
-
def
|
2974
|
+
def visit_attr(node); end
|
2973
2975
|
|
2974
2976
|
sig { params(node: ::Prism::CallNode).void }
|
2975
2977
|
def visit_extend(node); end
|
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.
|
4
|
+
version: 1.7.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alexandre Terrasa
|
@@ -23,20 +23,6 @@ dependencies:
|
|
23
23
|
- - ">="
|
24
24
|
- !ruby/object:Gem::Version
|
25
25
|
version: 2.2.10
|
26
|
-
- !ruby/object:Gem::Dependency
|
27
|
-
name: minitest
|
28
|
-
requirement: !ruby/object:Gem::Requirement
|
29
|
-
requirements:
|
30
|
-
- - "~>"
|
31
|
-
- !ruby/object:Gem::Version
|
32
|
-
version: '5.0'
|
33
|
-
type: :development
|
34
|
-
prerelease: false
|
35
|
-
version_requirements: !ruby/object:Gem::Requirement
|
36
|
-
requirements:
|
37
|
-
- - "~>"
|
38
|
-
- !ruby/object:Gem::Version
|
39
|
-
version: '5.0'
|
40
26
|
- !ruby/object:Gem::Dependency
|
41
27
|
name: minitest-reporters
|
42
28
|
requirement: !ruby/object:Gem::Requirement
|
@@ -57,14 +43,14 @@ dependencies:
|
|
57
43
|
requirements:
|
58
44
|
- - "~>"
|
59
45
|
- !ruby/object:Gem::Version
|
60
|
-
version: 13.
|
46
|
+
version: 13.3.0
|
61
47
|
type: :development
|
62
48
|
prerelease: false
|
63
49
|
version_requirements: !ruby/object:Gem::Requirement
|
64
50
|
requirements:
|
65
51
|
- - "~>"
|
66
52
|
- !ruby/object:Gem::Version
|
67
|
-
version: 13.
|
53
|
+
version: 13.3.0
|
68
54
|
- !ruby/object:Gem::Dependency
|
69
55
|
name: erubi
|
70
56
|
requirement: !ruby/object:Gem::Requirement
|