spoom 1.7.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/lib/spoom/cli/srb/metrics.rb +68 -0
- data/lib/spoom/cli/srb.rb +4 -0
- data/lib/spoom/context/sorbet.rb +1 -1
- data/lib/spoom/counters.rb +22 -0
- 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 -30
- data/lib/spoom/sorbet/translate/rbs_comments_to_sorbet_sigs.rb +4 -1
- data/lib/spoom/version.rb +1 -1
- data/lib/spoom.rb +1 -0
- data/rbi/spoom.rbi +96 -23
- metadata +5 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 59987238a3b2bae115f02d1da2a7e2a4cd6b3532d816bbe80d9153fa7819f989
|
4
|
+
data.tar.gz: d7e6bccfa046b7c457cb3e5d3d4383141243949021bd584b22cde0db0cc165ef
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b2f53478b7fdee59bfa7c579c3686b6d6c388db8737584c02f613daa2c4d42c0be2c1baaa39c50e90137697f62d7b8bb04e9fdbb458defdfa7813be3b6cbbd36
|
7
|
+
data.tar.gz: 57b26d457d2235bedaff15c832accc34a9c5ffcb89876306394f12b74a87ce03964d0309cd62e213e9954607150968607227436ebeb522a84f27782f7cc8cac8
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# typed: true
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Spoom
|
5
|
+
module Cli
|
6
|
+
module Srb
|
7
|
+
class Metrics < Thor
|
8
|
+
include Helper
|
9
|
+
|
10
|
+
default_task :show
|
11
|
+
|
12
|
+
desc "show", "Show metrics about Sorbet usage"
|
13
|
+
option :dump, type: :boolean, default: false
|
14
|
+
def show(*paths)
|
15
|
+
files = collect_files(paths)
|
16
|
+
metrics = Spoom::Sorbet::Metrics.collect_code_metrics(files)
|
17
|
+
|
18
|
+
if options[:dump]
|
19
|
+
metrics.sort_by { |key, _value| key }.each do |key, value|
|
20
|
+
puts "#{key} #{value}"
|
21
|
+
end
|
22
|
+
|
23
|
+
return
|
24
|
+
end
|
25
|
+
|
26
|
+
say("Files: `#{files.size}`")
|
27
|
+
|
28
|
+
["classes", "modules", "singleton_classes"].each do |key|
|
29
|
+
value = metrics[key]
|
30
|
+
next if value == 0
|
31
|
+
|
32
|
+
say("\n#{key.capitalize}: `#{value}`")
|
33
|
+
["with_srb_type_params", "with_rbs_type_params"].each do |subkey|
|
34
|
+
say(" * #{subkey.gsub("_", " ")}: `#{metrics["#{key}_#{subkey}"]}`")
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
["methods", "accessors"].each do |key|
|
39
|
+
value = metrics[key]
|
40
|
+
next if value == 0
|
41
|
+
|
42
|
+
say("\n#{key.capitalize}: `#{value}`")
|
43
|
+
["without_sig", "with_srb_sig", "with_rbs_sig"].each do |subkey|
|
44
|
+
say(" * #{subkey.gsub("_", " ")}: `#{metrics["#{key}_#{subkey}"]}`")
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
say("\nT. calls: `#{metrics["T_calls"]}`")
|
49
|
+
metrics
|
50
|
+
.select { |key, _value| key.start_with?("T.") }
|
51
|
+
.sort_by { |_key, value| -value }
|
52
|
+
.each do |key, value|
|
53
|
+
say(" * #{key}: `#{value}`")
|
54
|
+
end
|
55
|
+
|
56
|
+
say("\nRBS Assertions: `#{metrics["rbs_assertions"]}`")
|
57
|
+
metrics
|
58
|
+
.reject { |key, _value| key == "rbs_assertions" }
|
59
|
+
.select { |key, _value| key.start_with?("rbs_") }
|
60
|
+
.sort_by { |_key, value| -value }
|
61
|
+
.each do |key, value|
|
62
|
+
say(" * #{key}: `#{value}`")
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
data/lib/spoom/cli/srb.rb
CHANGED
@@ -5,6 +5,7 @@ require_relative "srb/assertions"
|
|
5
5
|
require_relative "srb/bump"
|
6
6
|
require_relative "srb/coverage"
|
7
7
|
require_relative "srb/lsp"
|
8
|
+
require_relative "srb/metrics"
|
8
9
|
require_relative "srb/sigs"
|
9
10
|
require_relative "srb/tc"
|
10
11
|
|
@@ -24,6 +25,9 @@ module Spoom
|
|
24
25
|
desc "lsp", "Send LSP requests to Sorbet"
|
25
26
|
subcommand "lsp", Spoom::Cli::Srb::LSP
|
26
27
|
|
28
|
+
desc "metrics", "Collect metrics about Sorbet usage"
|
29
|
+
subcommand "metrics", Spoom::Cli::Srb::Metrics
|
30
|
+
|
27
31
|
desc "sigs", "Translate signatures from/to RBI and RBS"
|
28
32
|
subcommand "sigs", Spoom::Cli::Srb::Sigs
|
29
33
|
|
data/lib/spoom/context/sorbet.rb
CHANGED
@@ -48,7 +48,7 @@ module Spoom
|
|
48
48
|
return unless file?(metrics_file)
|
49
49
|
|
50
50
|
metrics_path = absolute_path_to(metrics_file)
|
51
|
-
metrics = Spoom::Sorbet::
|
51
|
+
metrics = Spoom::Sorbet::Metrics::MetricsFileParser.parse_file(metrics_path)
|
52
52
|
remove!(metrics_file)
|
53
53
|
metrics
|
54
54
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Spoom
|
5
|
+
#: [K = String, V = Integer, Elem = [String, Integer]]
|
6
|
+
class Counters < Hash
|
7
|
+
#: -> void
|
8
|
+
def initialize
|
9
|
+
super(0)
|
10
|
+
end
|
11
|
+
|
12
|
+
#: (String) -> void
|
13
|
+
def increment(key)
|
14
|
+
self[key] += 1
|
15
|
+
end
|
16
|
+
|
17
|
+
#: (String) -> Integer
|
18
|
+
def [](key)
|
19
|
+
super(key) #: as Integer
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,236 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Spoom
|
5
|
+
module Sorbet
|
6
|
+
module Metrics
|
7
|
+
class << self
|
8
|
+
#: (Array[String]) -> Spoom::Counters
|
9
|
+
def collect_code_metrics(files)
|
10
|
+
counters = Counters.new
|
11
|
+
|
12
|
+
files.each do |file|
|
13
|
+
counters.increment("files")
|
14
|
+
|
15
|
+
content = File.read(file)
|
16
|
+
node = Spoom.parse_ruby(content, file: file, comments: true)
|
17
|
+
visitor = CodeMetricsVisitor.new(counters)
|
18
|
+
visitor.visit(node)
|
19
|
+
end
|
20
|
+
|
21
|
+
counters
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# Collects metrics about how Sorbet is used in the codebase.
|
26
|
+
#
|
27
|
+
# This approach is different from the metrics file we get directly from Sorbet.
|
28
|
+
#
|
29
|
+
# This visitor actually visits the codebase and collects metrics about the amount of signatures, `T.` calls,
|
30
|
+
# and other metrics. It also knows about RBS comments.
|
31
|
+
#
|
32
|
+
# On the other hand, the metrics file is a snapshot of the metrics at type checking time and knows about
|
33
|
+
# is calls are typed, how many assertions are done, etc.
|
34
|
+
class CodeMetricsVisitor < Spoom::Visitor
|
35
|
+
include RBS::ExtractRBSComments
|
36
|
+
|
37
|
+
#: Counters
|
38
|
+
attr_reader :counters
|
39
|
+
|
40
|
+
#: (Spoom::Counters) -> void
|
41
|
+
def initialize(counters)
|
42
|
+
super()
|
43
|
+
|
44
|
+
@counters = counters
|
45
|
+
|
46
|
+
@last_sigs = [] #: Array[Prism::CallNode]
|
47
|
+
@type_params = [] #: Array[Prism::CallNode]
|
48
|
+
end
|
49
|
+
|
50
|
+
# @override
|
51
|
+
#: (Prism::Node?) -> void
|
52
|
+
def visit(node)
|
53
|
+
return if node.nil?
|
54
|
+
|
55
|
+
node.location.trailing_comments.each do |comment|
|
56
|
+
text = comment.slice.strip
|
57
|
+
next unless text.start_with?("#:")
|
58
|
+
|
59
|
+
@counters.increment("rbs_assertions")
|
60
|
+
|
61
|
+
case text
|
62
|
+
when /^#: as !nil/
|
63
|
+
@counters.increment("rbs_must")
|
64
|
+
when /^#: as untyped/
|
65
|
+
@counters.increment("rbs_unsafe")
|
66
|
+
when /^#: as/
|
67
|
+
@counters.increment("rbs_cast")
|
68
|
+
when /^#:/
|
69
|
+
@counters.increment("rbs_let")
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
super
|
74
|
+
end
|
75
|
+
|
76
|
+
# @override
|
77
|
+
#: (Prism::ClassNode) -> void
|
78
|
+
def visit_class_node(node)
|
79
|
+
visit_scope(node) do
|
80
|
+
super
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# @override
|
85
|
+
#: (Prism::ModuleNode) -> void
|
86
|
+
def visit_module_node(node)
|
87
|
+
visit_scope(node) do
|
88
|
+
super
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
# @override
|
93
|
+
#: (Prism::SingletonClassNode) -> void
|
94
|
+
def visit_singleton_class_node(node)
|
95
|
+
visit_scope(node) do
|
96
|
+
super
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
# @override
|
101
|
+
#: (Prism::DefNode) -> void
|
102
|
+
def visit_def_node(node)
|
103
|
+
unless node.name.to_s.start_with?("test_")
|
104
|
+
@counters.increment("methods")
|
105
|
+
|
106
|
+
rbs_sigs = node_rbs_comments(node).signatures
|
107
|
+
srb_sigs = collect_last_srb_sigs
|
108
|
+
|
109
|
+
if rbs_sigs.any?
|
110
|
+
@counters.increment("methods_with_rbs_sig")
|
111
|
+
end
|
112
|
+
|
113
|
+
if srb_sigs.any?
|
114
|
+
@counters.increment("methods_with_srb_sig")
|
115
|
+
end
|
116
|
+
|
117
|
+
if rbs_sigs.empty? && srb_sigs.empty?
|
118
|
+
@counters.increment("methods_without_sig")
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
super
|
123
|
+
end
|
124
|
+
|
125
|
+
# @override
|
126
|
+
#: (Prism::CallNode) -> void
|
127
|
+
def visit_call_node(node)
|
128
|
+
@counters.increment("calls")
|
129
|
+
|
130
|
+
case node.name
|
131
|
+
when :attr_accessor, :attr_reader, :attr_writer
|
132
|
+
visit_attr_accessor(node)
|
133
|
+
return
|
134
|
+
when :sig
|
135
|
+
visit_sig(node)
|
136
|
+
return
|
137
|
+
when :type_member, :type_template
|
138
|
+
visit_type_member(node)
|
139
|
+
return
|
140
|
+
end
|
141
|
+
|
142
|
+
case node.receiver&.slice
|
143
|
+
when /^(::)?T$/
|
144
|
+
@counters.increment("T_calls")
|
145
|
+
@counters.increment("T.#{node.name}")
|
146
|
+
end
|
147
|
+
|
148
|
+
super
|
149
|
+
end
|
150
|
+
|
151
|
+
private
|
152
|
+
|
153
|
+
#: (Prism::ClassNode | Prism::ModuleNode | Prism::SingletonClassNode) { -> void } -> void
|
154
|
+
def visit_scope(node, &block)
|
155
|
+
key = node_key(node)
|
156
|
+
@counters.increment(key)
|
157
|
+
@counters.increment("#{key}_with_rbs_type_params") if node_rbs_comments(node).signatures.any?
|
158
|
+
|
159
|
+
old_type_params = @type_params
|
160
|
+
@type_params = []
|
161
|
+
|
162
|
+
yield
|
163
|
+
|
164
|
+
@counters.increment("#{key}_with_srb_type_params") if @type_params.any?
|
165
|
+
|
166
|
+
@type_params = old_type_params
|
167
|
+
end
|
168
|
+
|
169
|
+
#: (Prism::CallNode) -> void
|
170
|
+
def visit_attr_accessor(node)
|
171
|
+
@counters.increment("accessors")
|
172
|
+
|
173
|
+
rbs_sigs = node_rbs_comments(node).signatures
|
174
|
+
srb_sigs = collect_last_srb_sigs
|
175
|
+
|
176
|
+
if rbs_sigs.any?
|
177
|
+
@counters.increment("accessors_with_rbs_sig")
|
178
|
+
end
|
179
|
+
|
180
|
+
if srb_sigs.any?
|
181
|
+
@counters.increment("accessors_with_srb_sig")
|
182
|
+
end
|
183
|
+
|
184
|
+
if rbs_sigs.empty? && srb_sigs.empty?
|
185
|
+
@counters.increment("accessors_without_sig")
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
#: (Prism::CallNode) -> void
|
190
|
+
def visit_sig(node)
|
191
|
+
@last_sigs << node
|
192
|
+
@counters.increment("srb_sigs")
|
193
|
+
|
194
|
+
if node.slice =~ /abstract/
|
195
|
+
@counters.increment("srb_sigs_abstract")
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
#: (Prism::CallNode) -> void
|
200
|
+
def visit_type_member(node)
|
201
|
+
key = case node.name
|
202
|
+
when :type_member
|
203
|
+
"type_members"
|
204
|
+
when :type_template
|
205
|
+
"type_templates"
|
206
|
+
else
|
207
|
+
return
|
208
|
+
end
|
209
|
+
|
210
|
+
@counters.increment(key)
|
211
|
+
|
212
|
+
@type_params << node
|
213
|
+
end
|
214
|
+
|
215
|
+
#: -> Array[Prism::CallNode]
|
216
|
+
def collect_last_srb_sigs
|
217
|
+
sigs = @last_sigs.dup
|
218
|
+
@last_sigs.clear
|
219
|
+
sigs
|
220
|
+
end
|
221
|
+
|
222
|
+
#: (Prism::ClassNode | Prism::ModuleNode | Prism::SingletonClassNode) -> String
|
223
|
+
def node_key(node)
|
224
|
+
case node
|
225
|
+
when Prism::ClassNode
|
226
|
+
"classes"
|
227
|
+
when Prism::ModuleNode
|
228
|
+
"modules"
|
229
|
+
when Prism::SingletonClassNode
|
230
|
+
"singleton_classes"
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|
235
|
+
end
|
236
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "spoom/sorbet/sigils"
|
5
|
+
|
6
|
+
module Spoom
|
7
|
+
module Sorbet
|
8
|
+
module Metrics
|
9
|
+
module MetricsFileParser
|
10
|
+
DEFAULT_PREFIX = "ruby_typer.unknown."
|
11
|
+
|
12
|
+
class << self
|
13
|
+
#: (String path, ?String prefix) -> Hash[String, Integer]
|
14
|
+
def parse_file(path, prefix = DEFAULT_PREFIX)
|
15
|
+
parse_string(File.read(path), prefix)
|
16
|
+
end
|
17
|
+
|
18
|
+
#: (String string, ?String prefix) -> Hash[String, Integer]
|
19
|
+
def parse_string(string, prefix = DEFAULT_PREFIX)
|
20
|
+
parse_hash(JSON.parse(string), prefix)
|
21
|
+
end
|
22
|
+
|
23
|
+
#: (Hash[String, untyped] obj, ?String prefix) -> Counters
|
24
|
+
def parse_hash(obj, prefix = DEFAULT_PREFIX)
|
25
|
+
obj["metrics"].each_with_object(Counters.new) do |metric, metrics|
|
26
|
+
name = metric["name"].sub(prefix, "")
|
27
|
+
metrics[name] = metric["value"] || 0
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/lib/spoom/sorbet/metrics.rb
CHANGED
@@ -1,33 +1,5 @@
|
|
1
1
|
# typed: strict
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
module Spoom
|
7
|
-
module Sorbet
|
8
|
-
module MetricsParser
|
9
|
-
DEFAULT_PREFIX = "ruby_typer.unknown."
|
10
|
-
|
11
|
-
class << self
|
12
|
-
#: (String path, ?String prefix) -> Hash[String, Integer]
|
13
|
-
def parse_file(path, prefix = DEFAULT_PREFIX)
|
14
|
-
parse_string(File.read(path), prefix)
|
15
|
-
end
|
16
|
-
|
17
|
-
#: (String string, ?String prefix) -> Hash[String, Integer]
|
18
|
-
def parse_string(string, prefix = DEFAULT_PREFIX)
|
19
|
-
parse_hash(JSON.parse(string), prefix)
|
20
|
-
end
|
21
|
-
|
22
|
-
#: (Hash[String, untyped] obj, ?String prefix) -> Hash[String, Integer]
|
23
|
-
def parse_hash(obj, prefix = DEFAULT_PREFIX)
|
24
|
-
obj["metrics"].each_with_object(Hash.new(0)) do |metric, metrics|
|
25
|
-
name = metric["name"]
|
26
|
-
name = name.sub(prefix, "")
|
27
|
-
metrics[name] = metric["value"] || 0
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
4
|
+
require "spoom/sorbet/metrics/code_metrics_visitor"
|
5
|
+
require "spoom/sorbet/metrics/metrics_file_parser"
|
@@ -132,7 +132,6 @@ module Spoom
|
|
132
132
|
comments.annotations.reverse_each do |annotation|
|
133
133
|
from = adjust_to_line_start(annotation.location.start_offset)
|
134
134
|
to = adjust_to_line_end(annotation.location.end_offset)
|
135
|
-
@rewriter << Source::Delete.new(from, to)
|
136
135
|
|
137
136
|
content = case annotation.string
|
138
137
|
when "@abstract"
|
@@ -147,8 +146,12 @@ module Spoom
|
|
147
146
|
srb_type = ::RBS::Parser.parse_type(annotation.string.delete_prefix("@requires_ancestor: "))
|
148
147
|
rbs_type = RBI::RBS::TypeTranslator.translate(srb_type)
|
149
148
|
"requires_ancestor { #{rbs_type} }"
|
149
|
+
else
|
150
|
+
next
|
150
151
|
end
|
151
152
|
|
153
|
+
@rewriter << Source::Delete.new(from, to)
|
154
|
+
|
152
155
|
newline = node.body.nil? ? "" : "\n"
|
153
156
|
@rewriter << Source::Insert.new(insert_pos, "\n#{indent}#{content}#{newline}")
|
154
157
|
end
|
data/lib/spoom/version.rb
CHANGED
data/lib/spoom.rb
CHANGED
data/rbi/spoom.rbi
CHANGED
@@ -165,10 +165,19 @@ class Spoom::Cli::Srb::Main < ::Thor
|
|
165
165
|
def coverage(*args); end
|
166
166
|
def help(command = T.unsafe(nil), subcommand = T.unsafe(nil)); end
|
167
167
|
def lsp(*args); end
|
168
|
+
def metrics(*args); end
|
168
169
|
def sigs(*args); end
|
169
170
|
def tc(*args); end
|
170
171
|
end
|
171
172
|
|
173
|
+
class Spoom::Cli::Srb::Metrics < ::Thor
|
174
|
+
include ::Spoom::Colorize
|
175
|
+
include ::Spoom::Cli::Helper
|
176
|
+
|
177
|
+
def help(command = T.unsafe(nil), subcommand = T.unsafe(nil)); end
|
178
|
+
def show(*paths); end
|
179
|
+
end
|
180
|
+
|
172
181
|
class Spoom::Cli::Srb::Sigs < ::Thor
|
173
182
|
include ::Spoom::Colorize
|
174
183
|
include ::Spoom::Cli::Helper
|
@@ -422,6 +431,17 @@ module Spoom::Context::Sorbet
|
|
422
431
|
def write_sorbet_config!(contents, append: T.unsafe(nil)); end
|
423
432
|
end
|
424
433
|
|
434
|
+
class Spoom::Counters < ::Hash
|
435
|
+
sig { void }
|
436
|
+
def initialize; end
|
437
|
+
|
438
|
+
sig { params(key: ::String).returns(::Integer) }
|
439
|
+
def [](key); end
|
440
|
+
|
441
|
+
sig { params(key: ::String).void }
|
442
|
+
def increment(key); end
|
443
|
+
end
|
444
|
+
|
425
445
|
module Spoom::Coverage
|
426
446
|
class << self
|
427
447
|
sig { params(context: ::Spoom::Context).returns(::Spoom::FileTree) }
|
@@ -2445,29 +2465,25 @@ end
|
|
2445
2465
|
class Spoom::ParseError < ::Spoom::Error; end
|
2446
2466
|
|
2447
2467
|
class Spoom::Poset
|
2448
|
-
extend T::Generic
|
2449
|
-
|
2450
|
-
E = type_member { { upper: Object } }
|
2451
|
-
|
2452
2468
|
sig { void }
|
2453
2469
|
def initialize; end
|
2454
2470
|
|
2455
|
-
sig { params(value:
|
2471
|
+
sig { params(value: T.untyped).returns(Spoom::Poset::Element[T.untyped]) }
|
2456
2472
|
def [](value); end
|
2457
2473
|
|
2458
|
-
sig { params(from:
|
2474
|
+
sig { params(from: T.untyped, to: T.untyped).void }
|
2459
2475
|
def add_direct_edge(from, to); end
|
2460
2476
|
|
2461
|
-
sig { params(value:
|
2477
|
+
sig { params(value: T.untyped).returns(Spoom::Poset::Element[T.untyped]) }
|
2462
2478
|
def add_element(value); end
|
2463
2479
|
|
2464
|
-
sig { params(from:
|
2480
|
+
sig { params(from: T.untyped, to: T.untyped).returns(T::Boolean) }
|
2465
2481
|
def direct_edge?(from, to); end
|
2466
2482
|
|
2467
|
-
sig { params(from:
|
2483
|
+
sig { params(from: T.untyped, to: T.untyped).returns(T::Boolean) }
|
2468
2484
|
def edge?(from, to); end
|
2469
2485
|
|
2470
|
-
sig { params(value:
|
2486
|
+
sig { params(value: T.untyped).returns(T::Boolean) }
|
2471
2487
|
def element?(value); end
|
2472
2488
|
|
2473
2489
|
sig { params(direct: T::Boolean, transitive: T::Boolean).void }
|
@@ -2478,39 +2494,36 @@ class Spoom::Poset
|
|
2478
2494
|
end
|
2479
2495
|
|
2480
2496
|
class Spoom::Poset::Element
|
2481
|
-
extend T::Generic
|
2482
2497
|
include ::Comparable
|
2483
2498
|
|
2484
|
-
|
2485
|
-
|
2486
|
-
sig { params(value: E).void }
|
2499
|
+
sig { params(value: T.untyped).void }
|
2487
2500
|
def initialize(value); end
|
2488
2501
|
|
2489
2502
|
sig { params(other: T.untyped).returns(T.nilable(::Integer)) }
|
2490
2503
|
def <=>(other); end
|
2491
2504
|
|
2492
|
-
sig { returns(T::Array[
|
2505
|
+
sig { returns(T::Array[T.untyped]) }
|
2493
2506
|
def ancestors; end
|
2494
2507
|
|
2495
|
-
sig { returns(T::Array[
|
2508
|
+
sig { returns(T::Array[T.untyped]) }
|
2496
2509
|
def children; end
|
2497
2510
|
|
2498
|
-
sig { returns(T::Array[
|
2511
|
+
sig { returns(T::Array[T.untyped]) }
|
2499
2512
|
def descendants; end
|
2500
2513
|
|
2501
2514
|
def dfroms; end
|
2502
2515
|
|
2503
|
-
sig { returns(T::Set[Spoom::Poset::Element[
|
2516
|
+
sig { returns(T::Set[Spoom::Poset::Element[T.untyped]]) }
|
2504
2517
|
def dtos; end
|
2505
2518
|
|
2506
2519
|
def froms; end
|
2507
2520
|
|
2508
|
-
sig { returns(T::Array[
|
2521
|
+
sig { returns(T::Array[T.untyped]) }
|
2509
2522
|
def parents; end
|
2510
2523
|
|
2511
2524
|
def tos; end
|
2512
2525
|
|
2513
|
-
sig { returns(
|
2526
|
+
sig { returns(T.untyped) }
|
2514
2527
|
def value; end
|
2515
2528
|
end
|
2516
2529
|
|
@@ -2732,12 +2745,72 @@ Spoom::Sorbet::GEM_PATH = T.let(T.unsafe(nil), String)
|
|
2732
2745
|
Spoom::Sorbet::GEM_VERSION = T.let(T.unsafe(nil), String)
|
2733
2746
|
Spoom::Sorbet::KILLED_CODE = T.let(T.unsafe(nil), Integer)
|
2734
2747
|
|
2735
|
-
module Spoom::Sorbet::
|
2748
|
+
module Spoom::Sorbet::Metrics
|
2749
|
+
class << self
|
2750
|
+
sig { params(files: T::Array[::String]).returns(Spoom::Counters) }
|
2751
|
+
def collect_code_metrics(files); end
|
2752
|
+
end
|
2753
|
+
end
|
2754
|
+
|
2755
|
+
class Spoom::Sorbet::Metrics::CodeMetricsVisitor < ::Spoom::Visitor
|
2756
|
+
include ::Spoom::RBS::ExtractRBSComments
|
2757
|
+
|
2758
|
+
sig { params(counters: Spoom::Counters).void }
|
2759
|
+
def initialize(counters); end
|
2760
|
+
|
2761
|
+
sig { returns(Spoom::Counters) }
|
2762
|
+
def counters; end
|
2763
|
+
|
2764
|
+
sig { override.params(node: T.nilable(::Prism::Node)).void }
|
2765
|
+
def visit(node); end
|
2766
|
+
|
2767
|
+
sig { override.params(node: ::Prism::CallNode).void }
|
2768
|
+
def visit_call_node(node); end
|
2769
|
+
|
2770
|
+
sig { override.params(node: ::Prism::ClassNode).void }
|
2771
|
+
def visit_class_node(node); end
|
2772
|
+
|
2773
|
+
sig { override.params(node: ::Prism::DefNode).void }
|
2774
|
+
def visit_def_node(node); end
|
2775
|
+
|
2776
|
+
sig { override.params(node: ::Prism::ModuleNode).void }
|
2777
|
+
def visit_module_node(node); end
|
2778
|
+
|
2779
|
+
sig { override.params(node: ::Prism::SingletonClassNode).void }
|
2780
|
+
def visit_singleton_class_node(node); end
|
2781
|
+
|
2782
|
+
private
|
2783
|
+
|
2784
|
+
sig { returns(T::Array[::Prism::CallNode]) }
|
2785
|
+
def collect_last_srb_sigs; end
|
2786
|
+
|
2787
|
+
sig { params(node: T.any(::Prism::ClassNode, ::Prism::ModuleNode, ::Prism::SingletonClassNode)).returns(::String) }
|
2788
|
+
def node_key(node); end
|
2789
|
+
|
2790
|
+
sig { params(node: ::Prism::CallNode).void }
|
2791
|
+
def visit_attr_accessor(node); end
|
2792
|
+
|
2793
|
+
sig do
|
2794
|
+
params(
|
2795
|
+
node: T.any(::Prism::ClassNode, ::Prism::ModuleNode, ::Prism::SingletonClassNode),
|
2796
|
+
block: T.proc.void
|
2797
|
+
).void
|
2798
|
+
end
|
2799
|
+
def visit_scope(node, &block); end
|
2800
|
+
|
2801
|
+
sig { params(node: ::Prism::CallNode).void }
|
2802
|
+
def visit_sig(node); end
|
2803
|
+
|
2804
|
+
sig { params(node: ::Prism::CallNode).void }
|
2805
|
+
def visit_type_member(node); end
|
2806
|
+
end
|
2807
|
+
|
2808
|
+
module Spoom::Sorbet::Metrics::MetricsFileParser
|
2736
2809
|
class << self
|
2737
2810
|
sig { params(path: ::String, prefix: ::String).returns(T::Hash[::String, ::Integer]) }
|
2738
2811
|
def parse_file(path, prefix = T.unsafe(nil)); end
|
2739
2812
|
|
2740
|
-
sig { params(obj: T::Hash[::String, T.untyped], prefix: ::String).returns(
|
2813
|
+
sig { params(obj: T::Hash[::String, T.untyped], prefix: ::String).returns(Spoom::Counters) }
|
2741
2814
|
def parse_hash(obj, prefix = T.unsafe(nil)); end
|
2742
2815
|
|
2743
2816
|
sig { params(string: ::String, prefix: ::String).returns(T::Hash[::String, ::Integer]) }
|
@@ -2745,7 +2818,7 @@ module Spoom::Sorbet::MetricsParser
|
|
2745
2818
|
end
|
2746
2819
|
end
|
2747
2820
|
|
2748
|
-
Spoom::Sorbet::
|
2821
|
+
Spoom::Sorbet::Metrics::MetricsFileParser::DEFAULT_PREFIX = T.let(T.unsafe(nil), String)
|
2749
2822
|
Spoom::Sorbet::SEGFAULT_CODE = T.let(T.unsafe(nil), Integer)
|
2750
2823
|
|
2751
2824
|
module Spoom::Sorbet::Sigils
|
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.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alexandre Terrasa
|
@@ -185,6 +185,7 @@ files:
|
|
185
185
|
- lib/spoom/cli/srb/bump.rb
|
186
186
|
- lib/spoom/cli/srb/coverage.rb
|
187
187
|
- lib/spoom/cli/srb/lsp.rb
|
188
|
+
- lib/spoom/cli/srb/metrics.rb
|
188
189
|
- lib/spoom/cli/srb/sigs.rb
|
189
190
|
- lib/spoom/cli/srb/tc.rb
|
190
191
|
- lib/spoom/colors.rb
|
@@ -194,6 +195,7 @@ files:
|
|
194
195
|
- lib/spoom/context/file_system.rb
|
195
196
|
- lib/spoom/context/git.rb
|
196
197
|
- lib/spoom/context/sorbet.rb
|
198
|
+
- lib/spoom/counters.rb
|
197
199
|
- lib/spoom/coverage.rb
|
198
200
|
- lib/spoom/coverage/d3.rb
|
199
201
|
- lib/spoom/coverage/d3/base.rb
|
@@ -249,6 +251,8 @@ files:
|
|
249
251
|
- lib/spoom/sorbet/lsp/errors.rb
|
250
252
|
- lib/spoom/sorbet/lsp/structures.rb
|
251
253
|
- lib/spoom/sorbet/metrics.rb
|
254
|
+
- lib/spoom/sorbet/metrics/code_metrics_visitor.rb
|
255
|
+
- lib/spoom/sorbet/metrics/metrics_file_parser.rb
|
252
256
|
- lib/spoom/sorbet/sigils.rb
|
253
257
|
- lib/spoom/sorbet/translate.rb
|
254
258
|
- lib/spoom/sorbet/translate/rbs_comments_to_sorbet_sigs.rb
|