spoom 1.5.0 → 1.7.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/README.md +14 -0
- data/lib/spoom/backtrace_filter/minitest.rb +3 -4
- data/lib/spoom/cli/deadcode.rb +1 -2
- data/lib/spoom/cli/helper.rb +41 -31
- data/lib/spoom/cli/srb/assertions.rb +48 -0
- data/lib/spoom/cli/srb/bump.rb +1 -2
- data/lib/spoom/cli/srb/coverage.rb +1 -1
- data/lib/spoom/cli/srb/metrics.rb +68 -0
- data/lib/spoom/cli/srb/sigs.rb +209 -0
- data/lib/spoom/cli/srb/tc.rb +16 -1
- data/lib/spoom/cli/srb.rb +16 -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 +3 -6
- data/lib/spoom/context/file_system.rb +12 -19
- data/lib/spoom/context/git.rb +14 -19
- data/lib/spoom/context/sorbet.rb +14 -27
- data/lib/spoom/context.rb +4 -8
- data/lib/spoom/counters.rb +22 -0
- 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 +41 -79
- data/lib/spoom/coverage/snapshot.rb +8 -14
- 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 +21 -25
- 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 +19 -22
- data/lib/spoom/deadcode/plugins/active_model.rb +2 -3
- data/lib/spoom/deadcode/plugins/active_record.rb +62 -53
- data/lib/spoom/deadcode/plugins/active_support.rb +3 -2
- 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 +5 -5
- 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 +23 -31
- data/lib/spoom/deadcode/remover.rb +58 -79
- data/lib/spoom/deadcode/send.rb +2 -8
- data/lib/spoom/file_collector.rb +11 -19
- data/lib/spoom/file_tree.rb +36 -51
- data/lib/spoom/location.rb +9 -20
- data/lib/spoom/model/builder.rb +54 -17
- data/lib/spoom/model/model.rb +71 -74
- data/lib/spoom/model/namespace_visitor.rb +4 -3
- data/lib/spoom/model/reference.rb +4 -8
- data/lib/spoom/model/references_visitor.rb +50 -30
- data/lib/spoom/parse.rb +4 -4
- data/lib/spoom/poset.rb +22 -24
- data/lib/spoom/printer.rb +10 -13
- data/lib/spoom/rbs.rb +77 -0
- data/lib/spoom/sorbet/config.rb +17 -24
- data/lib/spoom/sorbet/errors.rb +87 -45
- data/lib/spoom/sorbet/lsp/base.rb +10 -16
- data/lib/spoom/sorbet/lsp/errors.rb +8 -16
- data/lib/spoom/sorbet/lsp/structures.rb +65 -91
- data/lib/spoom/sorbet/lsp.rb +20 -22
- data/lib/spoom/sorbet/metrics/code_metrics_visitor.rb +236 -0
- data/lib/spoom/sorbet/metrics/metrics_file_parser.rb +34 -0
- data/lib/spoom/sorbet/metrics.rb +2 -32
- data/lib/spoom/sorbet/sigils.rb +16 -23
- data/lib/spoom/sorbet/translate/rbs_comments_to_sorbet_sigs.rb +242 -0
- data/lib/spoom/sorbet/translate/sorbet_assertions_to_rbs_comments.rb +123 -0
- data/lib/spoom/sorbet/translate/sorbet_sigs_to_rbs_comments.rb +293 -0
- data/lib/spoom/sorbet/translate/strip_sorbet_sigs.rb +23 -0
- data/lib/spoom/sorbet/translate/translator.rb +71 -0
- data/lib/spoom/sorbet/translate.rb +49 -0
- data/lib/spoom/sorbet.rb +6 -12
- data/lib/spoom/source/rewriter.rb +167 -0
- data/lib/spoom/source.rb +4 -0
- 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 +4 -3
- data/rbi/spoom.rbi +3567 -0
- metadata +62 -8
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
|
-
@roots =
|
9
|
+
@roots = {} #: 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
|
-
@nodes =
|
126
|
+
@nodes = [] #: 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
|
-
@strictnesses =
|
146
|
+
@strictnesses = {} #: Hash[Node, 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
|
-
@scores =
|
168
|
+
@scores = {} #: 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,23 +202,16 @@ 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
|
225
209
|
@colors = colors
|
226
|
-
@printer =
|
210
|
+
@printer = 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,28 +5,28 @@ 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 }
|
8
|
+
#: (Model model, String file) -> void
|
11
9
|
def initialize(model, file)
|
12
10
|
super()
|
13
11
|
|
14
12
|
@model = model
|
15
13
|
@file = file
|
16
|
-
@namespace_nesting =
|
17
|
-
@visibility_stack =
|
18
|
-
@last_sigs =
|
14
|
+
@namespace_nesting = [] #: Array[Namespace]
|
15
|
+
@visibility_stack = [Visibility::Public] #: Array[Visibility]
|
16
|
+
@last_sigs = [] #: Array[Sig]
|
19
17
|
end
|
20
18
|
|
21
19
|
# Classes
|
22
20
|
|
23
|
-
|
21
|
+
# @override
|
22
|
+
#: (Prism::ClassNode node) -> void
|
24
23
|
def visit_class_node(node)
|
25
24
|
@namespace_nesting << Class.new(
|
26
25
|
@model.register_symbol(@names_nesting.join("::")),
|
27
26
|
owner: @namespace_nesting.last,
|
28
27
|
location: node_location(node),
|
29
28
|
superclass_name: node.superclass&.slice,
|
29
|
+
comments: node_comments(node),
|
30
30
|
)
|
31
31
|
@visibility_stack << Visibility::Public
|
32
32
|
super
|
@@ -35,12 +35,14 @@ module Spoom
|
|
35
35
|
@last_sigs.clear
|
36
36
|
end
|
37
37
|
|
38
|
-
|
38
|
+
# @override
|
39
|
+
#: (Prism::SingletonClassNode node) -> void
|
39
40
|
def visit_singleton_class_node(node)
|
40
41
|
@namespace_nesting << SingletonClass.new(
|
41
42
|
@model.register_symbol(@names_nesting.join("::")),
|
42
43
|
owner: @namespace_nesting.last,
|
43
44
|
location: node_location(node),
|
45
|
+
comments: node_comments(node),
|
44
46
|
)
|
45
47
|
@visibility_stack << Visibility::Public
|
46
48
|
super
|
@@ -51,12 +53,14 @@ module Spoom
|
|
51
53
|
|
52
54
|
# Modules
|
53
55
|
|
54
|
-
|
56
|
+
# @override
|
57
|
+
#: (Prism::ModuleNode node) -> void
|
55
58
|
def visit_module_node(node)
|
56
59
|
@namespace_nesting << Module.new(
|
57
60
|
@model.register_symbol(@names_nesting.join("::")),
|
58
61
|
owner: @namespace_nesting.last,
|
59
62
|
location: node_location(node),
|
63
|
+
comments: node_comments(node),
|
60
64
|
)
|
61
65
|
@visibility_stack << Visibility::Public
|
62
66
|
super
|
@@ -67,7 +71,8 @@ module Spoom
|
|
67
71
|
|
68
72
|
# Constants
|
69
73
|
|
70
|
-
|
74
|
+
# @override
|
75
|
+
#: (Prism::ConstantPathWriteNode node) -> void
|
71
76
|
def visit_constant_path_write_node(node)
|
72
77
|
@last_sigs.clear
|
73
78
|
|
@@ -83,12 +88,14 @@ module Spoom
|
|
83
88
|
owner: @namespace_nesting.last,
|
84
89
|
location: node_location(node),
|
85
90
|
value: node.value.slice,
|
91
|
+
comments: node_comments(node),
|
86
92
|
)
|
87
93
|
|
88
94
|
super
|
89
95
|
end
|
90
96
|
|
91
|
-
|
97
|
+
# @override
|
98
|
+
#: (Prism::ConstantWriteNode node) -> void
|
92
99
|
def visit_constant_write_node(node)
|
93
100
|
@last_sigs.clear
|
94
101
|
|
@@ -97,12 +104,14 @@ module Spoom
|
|
97
104
|
owner: @namespace_nesting.last,
|
98
105
|
location: node_location(node),
|
99
106
|
value: node.value.slice,
|
107
|
+
comments: node_comments(node),
|
100
108
|
)
|
101
109
|
|
102
110
|
super
|
103
111
|
end
|
104
112
|
|
105
|
-
|
113
|
+
# @override
|
114
|
+
#: (Prism::MultiWriteNode node) -> void
|
106
115
|
def visit_multi_write_node(node)
|
107
116
|
@last_sigs.clear
|
108
117
|
|
@@ -114,6 +123,7 @@ module Spoom
|
|
114
123
|
owner: @namespace_nesting.last,
|
115
124
|
location: node_location(const),
|
116
125
|
value: node.value.slice,
|
126
|
+
comments: node_comments(const),
|
117
127
|
)
|
118
128
|
end
|
119
129
|
end
|
@@ -123,7 +133,8 @@ module Spoom
|
|
123
133
|
|
124
134
|
# Methods
|
125
135
|
|
126
|
-
|
136
|
+
# @override
|
137
|
+
#: (Prism::DefNode node) -> void
|
127
138
|
def visit_def_node(node)
|
128
139
|
recv = node.receiver
|
129
140
|
|
@@ -134,6 +145,7 @@ module Spoom
|
|
134
145
|
location: node_location(node),
|
135
146
|
visibility: current_visibility,
|
136
147
|
sigs: collect_sigs,
|
148
|
+
comments: node_comments(node),
|
137
149
|
)
|
138
150
|
end
|
139
151
|
|
@@ -142,7 +154,8 @@ module Spoom
|
|
142
154
|
|
143
155
|
# Accessors
|
144
156
|
|
145
|
-
|
157
|
+
# @override
|
158
|
+
#: (Prism::CallNode node) -> void
|
146
159
|
def visit_call_node(node)
|
147
160
|
return if node.receiver && !node.receiver.is_a?(Prism::SelfNode)
|
148
161
|
|
@@ -160,6 +173,7 @@ module Spoom
|
|
160
173
|
location: node_location(arg),
|
161
174
|
visibility: current_visibility,
|
162
175
|
sigs: sigs,
|
176
|
+
comments: node_comments(node),
|
163
177
|
)
|
164
178
|
end
|
165
179
|
when :attr_reader
|
@@ -173,6 +187,7 @@ module Spoom
|
|
173
187
|
location: node_location(arg),
|
174
188
|
visibility: current_visibility,
|
175
189
|
sigs: sigs,
|
190
|
+
comments: node_comments(node),
|
176
191
|
)
|
177
192
|
end
|
178
193
|
when :attr_writer
|
@@ -186,6 +201,7 @@ module Spoom
|
|
186
201
|
location: node_location(arg),
|
187
202
|
visibility: current_visibility,
|
188
203
|
sigs: sigs,
|
204
|
+
comments: node_comments(node),
|
189
205
|
)
|
190
206
|
end
|
191
207
|
when :include
|
@@ -225,22 +241,43 @@ module Spoom
|
|
225
241
|
|
226
242
|
private
|
227
243
|
|
228
|
-
|
244
|
+
#: -> Visibility
|
229
245
|
def current_visibility
|
230
246
|
T.must(@visibility_stack.last)
|
231
247
|
end
|
232
248
|
|
233
|
-
|
249
|
+
#: -> Array[Sig]
|
234
250
|
def collect_sigs
|
235
251
|
sigs = @last_sigs
|
236
252
|
@last_sigs = []
|
237
253
|
sigs
|
238
254
|
end
|
239
255
|
|
240
|
-
|
256
|
+
#: (Prism::Node node) -> Location
|
241
257
|
def node_location(node)
|
242
258
|
Location.from_prism(@file, node.location)
|
243
259
|
end
|
260
|
+
|
261
|
+
#: (Prism::Node node) -> Array[Comment]
|
262
|
+
def node_comments(node)
|
263
|
+
last_line = node.location.start_line
|
264
|
+
comments = []
|
265
|
+
|
266
|
+
node.location.leading_comments.reverse_each do |comment|
|
267
|
+
if comment.location.start_line < last_line - 1
|
268
|
+
break
|
269
|
+
end
|
270
|
+
|
271
|
+
last_line = comment.location.start_line
|
272
|
+
|
273
|
+
comments.unshift(Comment.new(
|
274
|
+
comment.slice.gsub(/^#\s?/, "").rstrip,
|
275
|
+
Location.from_prism(@file, comment.location),
|
276
|
+
))
|
277
|
+
end
|
278
|
+
|
279
|
+
comments
|
280
|
+
end
|
244
281
|
end
|
245
282
|
end
|
246
283
|
end
|