spoom 1.5.4 → 1.6.0
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/backtrace_filter/minitest.rb +2 -3
- data/lib/spoom/cli/deadcode.rb +1 -2
- data/lib/spoom/cli/helper.rb +36 -28
- data/lib/spoom/cli/srb/assertions.rb +48 -0
- data/lib/spoom/cli/srb/bump.rb +1 -2
- data/lib/spoom/cli/srb/sigs.rb +133 -18
- data/lib/spoom/cli/srb.rb +8 -4
- data/lib/spoom/cli.rb +1 -2
- data/lib/spoom/colors.rb +2 -6
- data/lib/spoom/context/bundle.rb +8 -9
- data/lib/spoom/context/exec.rb +2 -5
- data/lib/spoom/context/file_system.rb +12 -19
- data/lib/spoom/context/git.rb +14 -19
- data/lib/spoom/context/sorbet.rb +13 -26
- data/lib/spoom/context.rb +3 -7
- data/lib/spoom/coverage/d3/base.rb +6 -8
- data/lib/spoom/coverage/d3/circle_map.rb +6 -16
- data/lib/spoom/coverage/d3/pie.rb +14 -19
- data/lib/spoom/coverage/d3/timeline.rb +46 -47
- data/lib/spoom/coverage/d3.rb +2 -4
- data/lib/spoom/coverage/report.rb +38 -76
- data/lib/spoom/coverage/snapshot.rb +7 -13
- data/lib/spoom/coverage.rb +3 -5
- data/lib/spoom/deadcode/definition.rb +12 -14
- data/lib/spoom/deadcode/erb.rb +10 -8
- data/lib/spoom/deadcode/index.rb +19 -23
- data/lib/spoom/deadcode/indexer.rb +5 -6
- data/lib/spoom/deadcode/plugins/action_mailer.rb +2 -3
- data/lib/spoom/deadcode/plugins/action_mailer_preview.rb +2 -3
- data/lib/spoom/deadcode/plugins/actionpack.rb +4 -4
- data/lib/spoom/deadcode/plugins/active_model.rb +2 -3
- data/lib/spoom/deadcode/plugins/active_record.rb +2 -3
- data/lib/spoom/deadcode/plugins/active_support.rb +2 -1
- data/lib/spoom/deadcode/plugins/base.rb +29 -32
- data/lib/spoom/deadcode/plugins/graphql.rb +2 -3
- data/lib/spoom/deadcode/plugins/minitest.rb +4 -4
- data/lib/spoom/deadcode/plugins/namespaces.rb +5 -5
- data/lib/spoom/deadcode/plugins/rails.rb +5 -5
- data/lib/spoom/deadcode/plugins/rubocop.rb +4 -4
- data/lib/spoom/deadcode/plugins/ruby.rb +3 -4
- data/lib/spoom/deadcode/plugins/sorbet.rb +12 -6
- data/lib/spoom/deadcode/plugins/thor.rb +2 -3
- data/lib/spoom/deadcode/plugins.rb +2 -4
- data/lib/spoom/deadcode/remover.rb +37 -59
- data/lib/spoom/deadcode/send.rb +2 -8
- data/lib/spoom/file_collector.rb +10 -18
- data/lib/spoom/file_tree.rb +31 -46
- data/lib/spoom/location.rb +9 -20
- data/lib/spoom/model/builder.rb +60 -15
- data/lib/spoom/model/model.rb +65 -68
- data/lib/spoom/model/namespace_visitor.rb +3 -2
- data/lib/spoom/model/reference.rb +4 -8
- data/lib/spoom/model/references_visitor.rb +49 -29
- data/lib/spoom/parse.rb +17 -3
- data/lib/spoom/poset.rb +17 -19
- data/lib/spoom/printer.rb +10 -13
- data/lib/spoom/sorbet/assertions.rb +278 -0
- data/lib/spoom/sorbet/config.rb +8 -12
- data/lib/spoom/sorbet/errors.rb +16 -31
- data/lib/spoom/sorbet/lsp/base.rb +9 -15
- data/lib/spoom/sorbet/lsp/errors.rb +8 -16
- data/lib/spoom/sorbet/lsp/structures.rb +36 -59
- data/lib/spoom/sorbet/lsp.rb +15 -17
- data/lib/spoom/sorbet/metrics.rb +3 -5
- data/lib/spoom/sorbet/sigils.rb +7 -11
- data/lib/spoom/sorbet/sigs.rb +118 -25
- data/lib/spoom/sorbet.rb +3 -9
- data/lib/spoom/timeline.rb +4 -6
- data/lib/spoom/version.rb +1 -1
- data/lib/spoom/visitor.rb +298 -151
- data/lib/spoom.rb +0 -2
- data/rbi/spoom.rbi +3963 -0
- metadata +6 -3
data/lib/spoom/file_tree.rb
CHANGED
@@ -4,16 +4,14 @@
|
|
4
4
|
module Spoom
|
5
5
|
# Build a file hierarchy from a set of file paths.
|
6
6
|
class FileTree
|
7
|
-
|
8
|
-
|
9
|
-
sig { params(paths: T::Enumerable[String]).void }
|
7
|
+
#: (?T::Enumerable[String] paths) -> void
|
10
8
|
def initialize(paths = [])
|
11
9
|
@roots = T.let({}, T::Hash[String, Node])
|
12
10
|
add_paths(paths)
|
13
11
|
end
|
14
12
|
|
15
13
|
# Add all `paths` to the tree
|
16
|
-
|
14
|
+
#: (T::Enumerable[String] paths) -> void
|
17
15
|
def add_paths(paths)
|
18
16
|
paths.each { |path| add_path(path) }
|
19
17
|
end
|
@@ -21,7 +19,7 @@ module Spoom
|
|
21
19
|
# Add a `path` to the tree
|
22
20
|
#
|
23
21
|
# This will create all nodes until the root of `path`.
|
24
|
-
|
22
|
+
#: (String path) -> Node
|
25
23
|
def add_path(path)
|
26
24
|
parts = path.split("/")
|
27
25
|
if path.empty? || parts.size == 1
|
@@ -35,13 +33,13 @@ module Spoom
|
|
35
33
|
end
|
36
34
|
|
37
35
|
# All root nodes
|
38
|
-
|
36
|
+
#: -> Array[Node]
|
39
37
|
def roots
|
40
38
|
@roots.values
|
41
39
|
end
|
42
40
|
|
43
41
|
# All the nodes in this tree
|
44
|
-
|
42
|
+
#: -> Array[Node]
|
45
43
|
def nodes
|
46
44
|
v = CollectNodes.new
|
47
45
|
v.visit_tree(self)
|
@@ -49,13 +47,13 @@ module Spoom
|
|
49
47
|
end
|
50
48
|
|
51
49
|
# All the paths in this tree
|
52
|
-
|
50
|
+
#: -> Array[String]
|
53
51
|
def paths
|
54
52
|
nodes.map(&:path)
|
55
53
|
end
|
56
54
|
|
57
55
|
# Return a map of typing scores for each node in the tree
|
58
|
-
|
56
|
+
#: (Context context) -> Hash[Node, Float]
|
59
57
|
def nodes_strictness_scores(context)
|
60
58
|
v = CollectScores.new(context)
|
61
59
|
v.visit_tree(self)
|
@@ -63,12 +61,12 @@ module Spoom
|
|
63
61
|
end
|
64
62
|
|
65
63
|
# Return a map of typing scores for each path in the tree
|
66
|
-
|
64
|
+
#: (Context context) -> Hash[String, Float]
|
67
65
|
def paths_strictness_scores(context)
|
68
66
|
nodes_strictness_scores(context).map { |node, score| [node.path, score] }.to_h
|
69
67
|
end
|
70
68
|
|
71
|
-
|
69
|
+
#: (?out: (IO | StringIO), ?colors: bool) -> void
|
72
70
|
def print(out: $stdout, colors: true)
|
73
71
|
printer = Printer.new({}, out: out, colors: colors)
|
74
72
|
printer.visit_tree(self)
|
@@ -76,8 +74,6 @@ module Spoom
|
|
76
74
|
|
77
75
|
# A node representing either a file or a directory inside a FileTree
|
78
76
|
class Node < T::Struct
|
79
|
-
extend T::Sig
|
80
|
-
|
81
77
|
# Node parent or `nil` if the node is a root one
|
82
78
|
const :parent, T.nilable(Node)
|
83
79
|
|
@@ -88,7 +84,7 @@ module Spoom
|
|
88
84
|
const :children, T::Hash[String, Node], default: {}
|
89
85
|
|
90
86
|
# Full path to this node from root
|
91
|
-
|
87
|
+
#: -> String
|
92
88
|
def path
|
93
89
|
parent = self.parent
|
94
90
|
return name unless parent
|
@@ -99,22 +95,21 @@ module Spoom
|
|
99
95
|
|
100
96
|
# An abstract visitor for FileTree
|
101
97
|
class Visitor
|
102
|
-
extend T::Sig
|
103
98
|
extend T::Helpers
|
104
99
|
|
105
100
|
abstract!
|
106
101
|
|
107
|
-
|
102
|
+
#: (FileTree tree) -> void
|
108
103
|
def visit_tree(tree)
|
109
104
|
visit_nodes(tree.roots)
|
110
105
|
end
|
111
106
|
|
112
|
-
|
107
|
+
#: (FileTree::Node node) -> void
|
113
108
|
def visit_node(node)
|
114
109
|
visit_nodes(node.children.values)
|
115
110
|
end
|
116
111
|
|
117
|
-
|
112
|
+
#: (Array[FileTree::Node] nodes) -> void
|
118
113
|
def visit_nodes(nodes)
|
119
114
|
nodes.each { |node| visit_node(node) }
|
120
115
|
end
|
@@ -122,18 +117,17 @@ module Spoom
|
|
122
117
|
|
123
118
|
# A visitor that collects all the nodes in a tree
|
124
119
|
class CollectNodes < Visitor
|
125
|
-
|
126
|
-
|
127
|
-
sig { returns(T::Array[FileTree::Node]) }
|
120
|
+
#: Array[FileTree::Node]
|
128
121
|
attr_reader :nodes
|
129
122
|
|
130
|
-
|
123
|
+
#: -> void
|
131
124
|
def initialize
|
132
125
|
super()
|
133
126
|
@nodes = T.let([], T::Array[FileTree::Node])
|
134
127
|
end
|
135
128
|
|
136
|
-
|
129
|
+
# @override
|
130
|
+
#: (FileTree::Node node) -> void
|
137
131
|
def visit_node(node)
|
138
132
|
@nodes << node
|
139
133
|
super
|
@@ -142,19 +136,18 @@ module Spoom
|
|
142
136
|
|
143
137
|
# A visitor that collects the strictness of each node in a tree
|
144
138
|
class CollectStrictnesses < Visitor
|
145
|
-
|
146
|
-
|
147
|
-
sig { returns(T::Hash[Node, T.nilable(String)]) }
|
139
|
+
#: Hash[Node, String?]
|
148
140
|
attr_reader :strictnesses
|
149
141
|
|
150
|
-
|
142
|
+
#: (Context context) -> void
|
151
143
|
def initialize(context)
|
152
144
|
super()
|
153
145
|
@context = context
|
154
146
|
@strictnesses = T.let({}, T::Hash[Node, T.nilable(String)])
|
155
147
|
end
|
156
148
|
|
157
|
-
|
149
|
+
# @override
|
150
|
+
#: (FileTree::Node node) -> void
|
158
151
|
def visit_node(node)
|
159
152
|
path = node.path
|
160
153
|
@strictnesses[node] = @context.read_file_strictness(path) if @context.file?(path)
|
@@ -165,19 +158,18 @@ module Spoom
|
|
165
158
|
|
166
159
|
# A visitor that collects the typing score of each node in a tree
|
167
160
|
class CollectScores < CollectStrictnesses
|
168
|
-
|
169
|
-
|
170
|
-
sig { returns(T::Hash[Node, Float]) }
|
161
|
+
#: Hash[Node, Float]
|
171
162
|
attr_reader :scores
|
172
163
|
|
173
|
-
|
164
|
+
#: (Context context) -> void
|
174
165
|
def initialize(context)
|
175
166
|
super
|
176
167
|
@context = context
|
177
168
|
@scores = T.let({}, T::Hash[Node, Float])
|
178
169
|
end
|
179
170
|
|
180
|
-
|
171
|
+
# @override
|
172
|
+
#: (FileTree::Node node) -> void
|
181
173
|
def visit_node(node)
|
182
174
|
super
|
183
175
|
|
@@ -186,7 +178,7 @@ module Spoom
|
|
186
178
|
|
187
179
|
private
|
188
180
|
|
189
|
-
|
181
|
+
#: (Node node) -> Float
|
190
182
|
def node_score(node)
|
191
183
|
if @context.file?(node.path)
|
192
184
|
strictness_score(@strictnesses[node])
|
@@ -195,7 +187,7 @@ module Spoom
|
|
195
187
|
end
|
196
188
|
end
|
197
189
|
|
198
|
-
|
190
|
+
#: (String? strictness) -> Float
|
199
191
|
def strictness_score(strictness)
|
200
192
|
case strictness
|
201
193
|
when "true", "strict", "strong"
|
@@ -210,15 +202,7 @@ module Spoom
|
|
210
202
|
#
|
211
203
|
# See `FileTree#print`
|
212
204
|
class Printer < Visitor
|
213
|
-
|
214
|
-
|
215
|
-
sig do
|
216
|
-
params(
|
217
|
-
strictnesses: T::Hash[FileTree::Node, T.nilable(String)],
|
218
|
-
out: T.any(IO, StringIO),
|
219
|
-
colors: T::Boolean,
|
220
|
-
).void
|
221
|
-
end
|
205
|
+
#: (Hash[FileTree::Node, String?] strictnesses, ?out: (IO | StringIO), ?colors: bool) -> void
|
222
206
|
def initialize(strictnesses, out: $stdout, colors: true)
|
223
207
|
super()
|
224
208
|
@strictnesses = strictnesses
|
@@ -226,7 +210,8 @@ module Spoom
|
|
226
210
|
@printer = T.let(Spoom::Printer.new(out: out, colors: colors), Spoom::Printer)
|
227
211
|
end
|
228
212
|
|
229
|
-
|
213
|
+
# @override
|
214
|
+
#: (FileTree::Node node) -> void
|
230
215
|
def visit_node(node)
|
231
216
|
@printer.printt
|
232
217
|
if node.children.empty?
|
@@ -251,7 +236,7 @@ module Spoom
|
|
251
236
|
|
252
237
|
private
|
253
238
|
|
254
|
-
|
239
|
+
#: (String? strictness) -> Color
|
255
240
|
def strictness_color(strictness)
|
256
241
|
case strictness
|
257
242
|
when "false"
|
data/lib/spoom/location.rb
CHANGED
@@ -3,16 +3,12 @@
|
|
3
3
|
|
4
4
|
module Spoom
|
5
5
|
class Location
|
6
|
-
extend T::Sig
|
7
|
-
|
8
6
|
include Comparable
|
9
7
|
|
10
8
|
class LocationError < Spoom::Error; end
|
11
9
|
|
12
10
|
class << self
|
13
|
-
|
14
|
-
|
15
|
-
sig { params(location_string: String).returns(Location) }
|
11
|
+
#: (String location_string) -> Location
|
16
12
|
def from_string(location_string)
|
17
13
|
file, rest = location_string.split(":", 2)
|
18
14
|
raise LocationError, "Invalid location string `#{location_string}`: missing file name" unless file
|
@@ -43,7 +39,7 @@ module Spoom
|
|
43
39
|
)
|
44
40
|
end
|
45
41
|
|
46
|
-
|
42
|
+
#: (String file, Prism::Location location) -> Location
|
47
43
|
def from_prism(file, location)
|
48
44
|
new(
|
49
45
|
file,
|
@@ -55,21 +51,13 @@ module Spoom
|
|
55
51
|
end
|
56
52
|
end
|
57
53
|
|
58
|
-
|
54
|
+
#: String
|
59
55
|
attr_reader :file
|
60
56
|
|
61
|
-
|
57
|
+
#: Integer?
|
62
58
|
attr_reader :start_line, :start_column, :end_line, :end_column
|
63
59
|
|
64
|
-
|
65
|
-
params(
|
66
|
-
file: String,
|
67
|
-
start_line: T.nilable(Integer),
|
68
|
-
start_column: T.nilable(Integer),
|
69
|
-
end_line: T.nilable(Integer),
|
70
|
-
end_column: T.nilable(Integer),
|
71
|
-
).void
|
72
|
-
end
|
60
|
+
#: (String file, ?start_line: Integer?, ?start_column: Integer?, ?end_line: Integer?, ?end_column: Integer?) -> void
|
73
61
|
def initialize(file, start_line: nil, start_column: nil, end_line: nil, end_column: nil)
|
74
62
|
raise LocationError,
|
75
63
|
"Invalid location: end line is required if start line is provided" if start_line && !end_line
|
@@ -89,7 +77,7 @@ module Spoom
|
|
89
77
|
@end_column = end_column
|
90
78
|
end
|
91
79
|
|
92
|
-
|
80
|
+
#: (Location other) -> bool
|
93
81
|
def include?(other)
|
94
82
|
return false unless @file == other.file
|
95
83
|
return false if (@start_line || -Float::INFINITY) > (other.start_line || -Float::INFINITY)
|
@@ -102,7 +90,8 @@ module Spoom
|
|
102
90
|
true
|
103
91
|
end
|
104
92
|
|
105
|
-
|
93
|
+
# @override
|
94
|
+
#: (BasicObject other) -> Integer?
|
106
95
|
def <=>(other)
|
107
96
|
return unless Location === other
|
108
97
|
|
@@ -125,7 +114,7 @@ module Spoom
|
|
125
114
|
comparison_array_self <=> comparison_array_other
|
126
115
|
end
|
127
116
|
|
128
|
-
|
117
|
+
#: -> String
|
129
118
|
def to_s
|
130
119
|
if @start_line && @start_column
|
131
120
|
"#{@file}:#{@start_line}:#{@start_column}-#{@end_line}:#{@end_column}"
|
data/lib/spoom/model/builder.rb
CHANGED
@@ -5,14 +5,18 @@ module Spoom
|
|
5
5
|
class Model
|
6
6
|
# Populate a Model by visiting the nodes from a Ruby file
|
7
7
|
class Builder < NamespaceVisitor
|
8
|
-
|
9
|
-
|
10
|
-
sig { params(model: Model, file: String).void }
|
11
|
-
def initialize(model, file)
|
8
|
+
#: (Model model, String file, ?comments: Array[Prism::Comment]) -> void
|
9
|
+
def initialize(model, file, comments:)
|
12
10
|
super()
|
13
11
|
|
14
12
|
@model = model
|
15
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
|
+
)
|
16
20
|
@namespace_nesting = T.let([], T::Array[Namespace])
|
17
21
|
@visibility_stack = T.let([Visibility::Public], T::Array[Visibility])
|
18
22
|
@last_sigs = T.let([], T::Array[Sig])
|
@@ -20,13 +24,15 @@ module Spoom
|
|
20
24
|
|
21
25
|
# Classes
|
22
26
|
|
23
|
-
|
27
|
+
# @override
|
28
|
+
#: (Prism::ClassNode node) -> void
|
24
29
|
def visit_class_node(node)
|
25
30
|
@namespace_nesting << Class.new(
|
26
31
|
@model.register_symbol(@names_nesting.join("::")),
|
27
32
|
owner: @namespace_nesting.last,
|
28
33
|
location: node_location(node),
|
29
34
|
superclass_name: node.superclass&.slice,
|
35
|
+
comments: node_comments(node),
|
30
36
|
)
|
31
37
|
@visibility_stack << Visibility::Public
|
32
38
|
super
|
@@ -35,12 +41,14 @@ module Spoom
|
|
35
41
|
@last_sigs.clear
|
36
42
|
end
|
37
43
|
|
38
|
-
|
44
|
+
# @override
|
45
|
+
#: (Prism::SingletonClassNode node) -> void
|
39
46
|
def visit_singleton_class_node(node)
|
40
47
|
@namespace_nesting << SingletonClass.new(
|
41
48
|
@model.register_symbol(@names_nesting.join("::")),
|
42
49
|
owner: @namespace_nesting.last,
|
43
50
|
location: node_location(node),
|
51
|
+
comments: node_comments(node),
|
44
52
|
)
|
45
53
|
@visibility_stack << Visibility::Public
|
46
54
|
super
|
@@ -51,12 +59,14 @@ module Spoom
|
|
51
59
|
|
52
60
|
# Modules
|
53
61
|
|
54
|
-
|
62
|
+
# @override
|
63
|
+
#: (Prism::ModuleNode node) -> void
|
55
64
|
def visit_module_node(node)
|
56
65
|
@namespace_nesting << Module.new(
|
57
66
|
@model.register_symbol(@names_nesting.join("::")),
|
58
67
|
owner: @namespace_nesting.last,
|
59
68
|
location: node_location(node),
|
69
|
+
comments: node_comments(node),
|
60
70
|
)
|
61
71
|
@visibility_stack << Visibility::Public
|
62
72
|
super
|
@@ -67,7 +77,8 @@ module Spoom
|
|
67
77
|
|
68
78
|
# Constants
|
69
79
|
|
70
|
-
|
80
|
+
# @override
|
81
|
+
#: (Prism::ConstantPathWriteNode node) -> void
|
71
82
|
def visit_constant_path_write_node(node)
|
72
83
|
@last_sigs.clear
|
73
84
|
|
@@ -83,12 +94,14 @@ module Spoom
|
|
83
94
|
owner: @namespace_nesting.last,
|
84
95
|
location: node_location(node),
|
85
96
|
value: node.value.slice,
|
97
|
+
comments: node_comments(node),
|
86
98
|
)
|
87
99
|
|
88
100
|
super
|
89
101
|
end
|
90
102
|
|
91
|
-
|
103
|
+
# @override
|
104
|
+
#: (Prism::ConstantWriteNode node) -> void
|
92
105
|
def visit_constant_write_node(node)
|
93
106
|
@last_sigs.clear
|
94
107
|
|
@@ -97,12 +110,14 @@ module Spoom
|
|
97
110
|
owner: @namespace_nesting.last,
|
98
111
|
location: node_location(node),
|
99
112
|
value: node.value.slice,
|
113
|
+
comments: node_comments(node),
|
100
114
|
)
|
101
115
|
|
102
116
|
super
|
103
117
|
end
|
104
118
|
|
105
|
-
|
119
|
+
# @override
|
120
|
+
#: (Prism::MultiWriteNode node) -> void
|
106
121
|
def visit_multi_write_node(node)
|
107
122
|
@last_sigs.clear
|
108
123
|
|
@@ -114,6 +129,7 @@ module Spoom
|
|
114
129
|
owner: @namespace_nesting.last,
|
115
130
|
location: node_location(const),
|
116
131
|
value: node.value.slice,
|
132
|
+
comments: node_comments(const),
|
117
133
|
)
|
118
134
|
end
|
119
135
|
end
|
@@ -123,7 +139,8 @@ module Spoom
|
|
123
139
|
|
124
140
|
# Methods
|
125
141
|
|
126
|
-
|
142
|
+
# @override
|
143
|
+
#: (Prism::DefNode node) -> void
|
127
144
|
def visit_def_node(node)
|
128
145
|
recv = node.receiver
|
129
146
|
|
@@ -134,6 +151,7 @@ module Spoom
|
|
134
151
|
location: node_location(node),
|
135
152
|
visibility: current_visibility,
|
136
153
|
sigs: collect_sigs,
|
154
|
+
comments: node_comments(node),
|
137
155
|
)
|
138
156
|
end
|
139
157
|
|
@@ -142,7 +160,8 @@ module Spoom
|
|
142
160
|
|
143
161
|
# Accessors
|
144
162
|
|
145
|
-
|
163
|
+
# @override
|
164
|
+
#: (Prism::CallNode node) -> void
|
146
165
|
def visit_call_node(node)
|
147
166
|
return if node.receiver && !node.receiver.is_a?(Prism::SelfNode)
|
148
167
|
|
@@ -160,6 +179,7 @@ module Spoom
|
|
160
179
|
location: node_location(arg),
|
161
180
|
visibility: current_visibility,
|
162
181
|
sigs: sigs,
|
182
|
+
comments: node_comments(node),
|
163
183
|
)
|
164
184
|
end
|
165
185
|
when :attr_reader
|
@@ -173,6 +193,7 @@ module Spoom
|
|
173
193
|
location: node_location(arg),
|
174
194
|
visibility: current_visibility,
|
175
195
|
sigs: sigs,
|
196
|
+
comments: node_comments(node),
|
176
197
|
)
|
177
198
|
end
|
178
199
|
when :attr_writer
|
@@ -186,6 +207,7 @@ module Spoom
|
|
186
207
|
location: node_location(arg),
|
187
208
|
visibility: current_visibility,
|
188
209
|
sigs: sigs,
|
210
|
+
comments: node_comments(node),
|
189
211
|
)
|
190
212
|
end
|
191
213
|
when :include
|
@@ -225,22 +247,45 @@ module Spoom
|
|
225
247
|
|
226
248
|
private
|
227
249
|
|
228
|
-
|
250
|
+
#: -> Visibility
|
229
251
|
def current_visibility
|
230
252
|
T.must(@visibility_stack.last)
|
231
253
|
end
|
232
254
|
|
233
|
-
|
255
|
+
#: -> Array[Sig]
|
234
256
|
def collect_sigs
|
235
257
|
sigs = @last_sigs
|
236
258
|
@last_sigs = []
|
237
259
|
sigs
|
238
260
|
end
|
239
261
|
|
240
|
-
|
262
|
+
#: (Prism::Node node) -> Location
|
241
263
|
def node_location(node)
|
242
264
|
Location.from_prism(@file, node.location)
|
243
265
|
end
|
266
|
+
|
267
|
+
#: (Prism::Node node) -> Array[Comment]
|
268
|
+
def node_comments(node)
|
269
|
+
comments = []
|
270
|
+
|
271
|
+
start_line = node.location.start_line
|
272
|
+
start_line -= 1 unless @comments_by_line.key?(start_line)
|
273
|
+
|
274
|
+
start_line.downto(1) do |line|
|
275
|
+
comment = @comments_by_line[line]
|
276
|
+
break unless comment
|
277
|
+
|
278
|
+
spoom_comment = Comment.new(
|
279
|
+
comment.slice.gsub(/^#\s?/, "").rstrip,
|
280
|
+
Location.from_prism(@file, comment.location),
|
281
|
+
)
|
282
|
+
|
283
|
+
comments.unshift(spoom_comment)
|
284
|
+
@comments_by_line.delete(line)
|
285
|
+
end
|
286
|
+
|
287
|
+
comments
|
288
|
+
end
|
244
289
|
end
|
245
290
|
end
|
246
291
|
end
|