spoom 1.5.4 → 1.6.1
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 +138 -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 +132 -33
- 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 +3969 -0
- metadata +6 -3
data/lib/spoom/sorbet/lsp.rb
CHANGED
@@ -11,9 +11,7 @@ require_relative "lsp/errors"
|
|
11
11
|
module Spoom
|
12
12
|
module LSP
|
13
13
|
class Client
|
14
|
-
|
15
|
-
|
16
|
-
sig { params(sorbet_bin: String, sorbet_args: String, path: String).void }
|
14
|
+
#: (String sorbet_bin, *String sorbet_args, ?path: String) -> void
|
17
15
|
def initialize(sorbet_bin, *sorbet_args, path: ".")
|
18
16
|
@id = T.let(0, Integer)
|
19
17
|
@open = T.let(false, T::Boolean)
|
@@ -23,23 +21,23 @@ module Spoom
|
|
23
21
|
@err = T.let(io_err, IO)
|
24
22
|
end
|
25
23
|
|
26
|
-
|
24
|
+
#: -> Integer
|
27
25
|
def next_id
|
28
26
|
@id += 1
|
29
27
|
end
|
30
28
|
|
31
|
-
|
29
|
+
#: (String json_string) -> void
|
32
30
|
def send_raw(json_string)
|
33
31
|
@in.puts("Content-Length:#{json_string.length}\r\n\r\n#{json_string}")
|
34
32
|
end
|
35
33
|
|
36
|
-
|
34
|
+
#: (Message message) -> Hash[untyped, untyped]?
|
37
35
|
def send(message)
|
38
36
|
send_raw(message.to_json)
|
39
37
|
read if message.is_a?(Request)
|
40
38
|
end
|
41
39
|
|
42
|
-
|
40
|
+
#: -> String?
|
43
41
|
def read_raw
|
44
42
|
header = @out.gets
|
45
43
|
|
@@ -50,7 +48,7 @@ module Spoom
|
|
50
48
|
@out.read(len + 2) # +2 'cause of the final \r\n
|
51
49
|
end
|
52
50
|
|
53
|
-
|
51
|
+
#: -> Hash[untyped, untyped]?
|
54
52
|
def read
|
55
53
|
raw_string = read_raw
|
56
54
|
return unless raw_string
|
@@ -68,7 +66,7 @@ module Spoom
|
|
68
66
|
|
69
67
|
# LSP requests
|
70
68
|
|
71
|
-
|
69
|
+
#: (String workspace_path) -> void
|
72
70
|
def open(workspace_path)
|
73
71
|
raise Error::AlreadyOpen, "Error: CLI already opened" if @open
|
74
72
|
|
@@ -85,7 +83,7 @@ module Spoom
|
|
85
83
|
@open = true
|
86
84
|
end
|
87
85
|
|
88
|
-
|
86
|
+
#: (String uri, Integer line, Integer column) -> Hover?
|
89
87
|
def hover(uri, line, column)
|
90
88
|
json = send(Request.new(
|
91
89
|
next_id,
|
@@ -106,7 +104,7 @@ module Spoom
|
|
106
104
|
Hover.from_json(json["result"])
|
107
105
|
end
|
108
106
|
|
109
|
-
|
107
|
+
#: (String uri, Integer line, Integer column) -> Array[SignatureHelp]
|
110
108
|
def signatures(uri, line, column)
|
111
109
|
json = send(Request.new(
|
112
110
|
next_id,
|
@@ -127,7 +125,7 @@ module Spoom
|
|
127
125
|
json["result"]["signatures"].map { |loc| SignatureHelp.from_json(loc) }
|
128
126
|
end
|
129
127
|
|
130
|
-
|
128
|
+
#: (String uri, Integer line, Integer column) -> Array[Location]
|
131
129
|
def definitions(uri, line, column)
|
132
130
|
json = send(Request.new(
|
133
131
|
next_id,
|
@@ -148,7 +146,7 @@ module Spoom
|
|
148
146
|
json["result"].map { |loc| Location.from_json(loc) }
|
149
147
|
end
|
150
148
|
|
151
|
-
|
149
|
+
#: (String uri, Integer line, Integer column) -> Array[Location]
|
152
150
|
def type_definitions(uri, line, column)
|
153
151
|
json = send(Request.new(
|
154
152
|
next_id,
|
@@ -169,7 +167,7 @@ module Spoom
|
|
169
167
|
json["result"].map { |loc| Location.from_json(loc) }
|
170
168
|
end
|
171
169
|
|
172
|
-
|
170
|
+
#: (String uri, Integer line, Integer column, ?bool include_decl) -> Array[Location]
|
173
171
|
def references(uri, line, column, include_decl = true)
|
174
172
|
json = send(Request.new(
|
175
173
|
next_id,
|
@@ -193,7 +191,7 @@ module Spoom
|
|
193
191
|
json["result"].map { |loc| Location.from_json(loc) }
|
194
192
|
end
|
195
193
|
|
196
|
-
|
194
|
+
#: (String query) -> Array[DocumentSymbol]
|
197
195
|
def symbols(query)
|
198
196
|
json = send(Request.new(
|
199
197
|
next_id,
|
@@ -208,7 +206,7 @@ module Spoom
|
|
208
206
|
json["result"].map { |loc| DocumentSymbol.from_json(loc) }
|
209
207
|
end
|
210
208
|
|
211
|
-
|
209
|
+
#: (String uri) -> Array[DocumentSymbol]
|
212
210
|
def document_symbols(uri)
|
213
211
|
json = send(Request.new(
|
214
212
|
next_id,
|
@@ -225,7 +223,7 @@ module Spoom
|
|
225
223
|
json["result"].map { |loc| DocumentSymbol.from_json(loc) }
|
226
224
|
end
|
227
225
|
|
228
|
-
|
226
|
+
#: -> void
|
229
227
|
def close
|
230
228
|
send(Request.new(next_id, "shutdown", {}))
|
231
229
|
@in.close
|
data/lib/spoom/sorbet/metrics.rb
CHANGED
@@ -9,19 +9,17 @@ module Spoom
|
|
9
9
|
DEFAULT_PREFIX = "ruby_typer.unknown."
|
10
10
|
|
11
11
|
class << self
|
12
|
-
|
13
|
-
|
14
|
-
sig { params(path: String, prefix: String).returns(T::Hash[String, Integer]) }
|
12
|
+
#: (String path, ?String prefix) -> Hash[String, Integer]
|
15
13
|
def parse_file(path, prefix = DEFAULT_PREFIX)
|
16
14
|
parse_string(File.read(path), prefix)
|
17
15
|
end
|
18
16
|
|
19
|
-
|
17
|
+
#: (String string, ?String prefix) -> Hash[String, Integer]
|
20
18
|
def parse_string(string, prefix = DEFAULT_PREFIX)
|
21
19
|
parse_hash(JSON.parse(string), prefix)
|
22
20
|
end
|
23
21
|
|
24
|
-
|
22
|
+
#: (Hash[String, untyped] obj, ?String prefix) -> Hash[String, Integer]
|
25
23
|
def parse_hash(obj, prefix = DEFAULT_PREFIX)
|
26
24
|
obj["metrics"].each_with_object(Hash.new(0)) do |metric, metrics|
|
27
25
|
name = metric["name"]
|
data/lib/spoom/sorbet/sigils.rb
CHANGED
@@ -7,8 +7,6 @@
|
|
7
7
|
module Spoom
|
8
8
|
module Sorbet
|
9
9
|
module Sigils
|
10
|
-
extend T::Sig
|
11
|
-
|
12
10
|
STRICTNESS_IGNORE = "ignore"
|
13
11
|
STRICTNESS_FALSE = "false"
|
14
12
|
STRICTNESS_TRUE = "true"
|
@@ -31,35 +29,33 @@ module Spoom
|
|
31
29
|
SIGIL_REGEXP = T.let(/^#[[:blank:]]*typed:[[:blank:]]*(\S*)/, Regexp)
|
32
30
|
|
33
31
|
class << self
|
34
|
-
extend T::Sig
|
35
|
-
|
36
32
|
# returns the full sigil comment string for the passed strictness
|
37
|
-
|
33
|
+
#: (String strictness) -> String
|
38
34
|
def sigil_string(strictness)
|
39
35
|
"# typed: #{strictness}"
|
40
36
|
end
|
41
37
|
|
42
38
|
# returns true if the passed string is a valid strictness (else false)
|
43
|
-
|
39
|
+
#: (String strictness) -> bool
|
44
40
|
def valid_strictness?(strictness)
|
45
41
|
VALID_STRICTNESS.include?(strictness.strip)
|
46
42
|
end
|
47
43
|
|
48
44
|
# returns the strictness of a sigil in the passed file content string (nil if no sigil)
|
49
|
-
|
45
|
+
#: (String content) -> String?
|
50
46
|
def strictness_in_content(content)
|
51
47
|
SIGIL_REGEXP.match(content)&.[](1)
|
52
48
|
end
|
53
49
|
|
54
50
|
# returns a string which is the passed content but with the sigil updated to a new strictness
|
55
|
-
|
51
|
+
#: (String content, String new_strictness) -> String
|
56
52
|
def update_sigil(content, new_strictness)
|
57
53
|
content.sub(SIGIL_REGEXP, sigil_string(new_strictness))
|
58
54
|
end
|
59
55
|
|
60
56
|
# returns a string containing the strictness of a sigil in a file at the passed path
|
61
57
|
# * returns nil if no sigil
|
62
|
-
|
58
|
+
#: ((String | Pathname) path) -> String?
|
63
59
|
def file_strictness(path)
|
64
60
|
return unless File.file?(path)
|
65
61
|
|
@@ -68,7 +64,7 @@ module Spoom
|
|
68
64
|
end
|
69
65
|
|
70
66
|
# changes the sigil in the file at the passed path to the specified new strictness
|
71
|
-
|
67
|
+
#: ((String | Pathname) path, String new_strictness) -> bool
|
72
68
|
def change_sigil_in_file(path, new_strictness)
|
73
69
|
content = File.read(path, encoding: Encoding::ASCII_8BIT)
|
74
70
|
new_content = update_sigil(content, new_strictness)
|
@@ -79,7 +75,7 @@ module Spoom
|
|
79
75
|
end
|
80
76
|
|
81
77
|
# changes the sigil to have a new strictness in a list of files
|
82
|
-
|
78
|
+
#: (Array[String] path_list, String new_strictness) -> Array[String]
|
83
79
|
def change_sigil_in_files(path_list, new_strictness)
|
84
80
|
path_list.filter do |path|
|
85
81
|
change_sigil_in_file(path, new_strictness)
|
data/lib/spoom/sorbet/sigs.rb
CHANGED
@@ -6,12 +6,11 @@ require "rbi"
|
|
6
6
|
module Spoom
|
7
7
|
module Sorbet
|
8
8
|
class Sigs
|
9
|
+
class Error < Spoom::Error; end
|
9
10
|
class << self
|
10
|
-
|
11
|
-
|
12
|
-
sig { params(ruby_contents: String).returns(String) }
|
11
|
+
#: (String ruby_contents) -> String
|
13
12
|
def strip(ruby_contents)
|
14
|
-
sigs =
|
13
|
+
sigs = collect_sorbet_sigs(ruby_contents)
|
15
14
|
lines_to_strip = sigs.flat_map { |sig, _| (sig.loc&.begin_line..sig.loc&.end_line).to_a }
|
16
15
|
|
17
16
|
lines = []
|
@@ -21,10 +20,10 @@ module Spoom
|
|
21
20
|
lines.join
|
22
21
|
end
|
23
22
|
|
24
|
-
|
25
|
-
def rbi_to_rbs(ruby_contents)
|
23
|
+
#: (String ruby_contents, positional_names: bool) -> String
|
24
|
+
def rbi_to_rbs(ruby_contents, positional_names: true)
|
26
25
|
ruby_contents = ruby_contents.dup
|
27
|
-
sigs =
|
26
|
+
sigs = collect_sorbet_sigs(ruby_contents)
|
28
27
|
|
29
28
|
sigs.each do |sig, node|
|
30
29
|
scanner = Scanner.new(ruby_contents)
|
@@ -36,7 +35,32 @@ module Spoom
|
|
36
35
|
sig.loc&.end_line&.pred,
|
37
36
|
T.must(sig.loc).end_column,
|
38
37
|
)
|
39
|
-
|
38
|
+
rbs = RBIToRBSTranslator.translate(sig, node, positional_names: positional_names)
|
39
|
+
ruby_contents[start_index...end_index] = rbs
|
40
|
+
end
|
41
|
+
|
42
|
+
ruby_contents
|
43
|
+
end
|
44
|
+
|
45
|
+
#: (String ruby_contents) -> String
|
46
|
+
def rbs_to_rbi(ruby_contents)
|
47
|
+
ruby_contents = ruby_contents.dup
|
48
|
+
rbs_comments = collect_rbs_comments(ruby_contents)
|
49
|
+
|
50
|
+
rbs_comments.each do |rbs_comment, node|
|
51
|
+
scanner = Scanner.new(ruby_contents)
|
52
|
+
start_index = scanner.find_char_position(
|
53
|
+
T.must(rbs_comment.loc&.begin_line&.pred),
|
54
|
+
T.must(rbs_comment.loc).begin_column,
|
55
|
+
)
|
56
|
+
end_index = scanner.find_char_position(
|
57
|
+
rbs_comment.loc&.end_line&.pred,
|
58
|
+
T.must(rbs_comment.loc).end_column,
|
59
|
+
)
|
60
|
+
rbi = RBSToRBITranslator.translate(rbs_comment, node)
|
61
|
+
next unless rbi
|
62
|
+
|
63
|
+
ruby_contents[start_index...end_index] = rbi
|
40
64
|
end
|
41
65
|
|
42
66
|
ruby_contents
|
@@ -44,28 +68,39 @@ module Spoom
|
|
44
68
|
|
45
69
|
private
|
46
70
|
|
47
|
-
|
48
|
-
def
|
71
|
+
#: (String ruby_contents) -> Array[[RBI::Sig, (RBI::Method | RBI::Attr)]]
|
72
|
+
def collect_sorbet_sigs(ruby_contents)
|
49
73
|
tree = RBI::Parser.parse_string(ruby_contents)
|
50
74
|
visitor = SigsLocator.new
|
51
75
|
visitor.visit(tree)
|
52
|
-
visitor.sigs.sort_by { |sig,
|
76
|
+
visitor.sigs.sort_by { |sig, _node| -T.must(sig.loc&.begin_line) }
|
77
|
+
end
|
78
|
+
|
79
|
+
#: (String ruby_contents) -> Array[[RBI::RBSComment, (RBI::Method | RBI::Attr)]]
|
80
|
+
def collect_rbs_comments(ruby_contents)
|
81
|
+
tree = RBI::Parser.parse_string(ruby_contents)
|
82
|
+
visitor = SigsLocator.new
|
83
|
+
visitor.visit(tree)
|
84
|
+
visitor.rbs_comments.sort_by { |comment, _node| -T.must(comment.loc&.begin_line) }
|
53
85
|
end
|
54
86
|
end
|
55
87
|
|
56
88
|
class SigsLocator < RBI::Visitor
|
57
|
-
|
58
|
-
|
59
|
-
sig { returns(T::Array[[RBI::Sig, T.any(RBI::Method, RBI::Attr)]]) }
|
89
|
+
#: Array[[RBI::Sig, (RBI::Method | RBI::Attr)]]
|
60
90
|
attr_reader :sigs
|
61
91
|
|
62
|
-
|
92
|
+
#: Array[[RBI::RBSComment, (RBI::Method | RBI::Attr)]]
|
93
|
+
attr_reader :rbs_comments
|
94
|
+
|
95
|
+
#: -> void
|
63
96
|
def initialize
|
64
97
|
super
|
65
98
|
@sigs = T.let([], T::Array[[RBI::Sig, T.any(RBI::Method, RBI::Attr)]])
|
99
|
+
@rbs_comments = T.let([], T::Array[[RBI::RBSComment, T.any(RBI::Method, RBI::Attr)]])
|
66
100
|
end
|
67
101
|
|
68
|
-
|
102
|
+
# @override
|
103
|
+
#: (RBI::Node? node) -> void
|
69
104
|
def visit(node)
|
70
105
|
return unless node
|
71
106
|
|
@@ -76,32 +111,33 @@ module Spoom
|
|
76
111
|
|
77
112
|
@sigs << [sig, node]
|
78
113
|
end
|
114
|
+
node.comments.grep(RBI::RBSComment).each do |rbs_comment|
|
115
|
+
@rbs_comments << [rbs_comment, node]
|
116
|
+
end
|
79
117
|
when RBI::Tree
|
80
118
|
visit_all(node.nodes)
|
81
119
|
end
|
82
120
|
end
|
83
121
|
end
|
84
122
|
|
85
|
-
class
|
123
|
+
class RBIToRBSTranslator
|
86
124
|
class << self
|
87
|
-
|
88
|
-
|
89
|
-
sig { params(sig: RBI::Sig, node: T.any(RBI::Method, RBI::Attr)).returns(String) }
|
90
|
-
def translate(sig, node)
|
125
|
+
#: (RBI::Sig sig, (RBI::Method | RBI::Attr) node, positional_names: bool) -> String
|
126
|
+
def translate(sig, node, positional_names: true)
|
91
127
|
case node
|
92
128
|
when RBI::Method
|
93
|
-
translate_method_sig(sig, node)
|
129
|
+
translate_method_sig(sig, node, positional_names: positional_names)
|
94
130
|
when RBI::Attr
|
95
|
-
translate_attr_sig(sig, node)
|
131
|
+
translate_attr_sig(sig, node, positional_names: positional_names)
|
96
132
|
end
|
97
133
|
end
|
98
134
|
|
99
135
|
private
|
100
136
|
|
101
|
-
|
102
|
-
def translate_method_sig(sig, node)
|
137
|
+
#: (RBI::Sig sig, RBI::Method node, positional_names: bool) -> String
|
138
|
+
def translate_method_sig(sig, node, positional_names: true)
|
103
139
|
out = StringIO.new
|
104
|
-
p = RBI::RBSPrinter.new(out: out, indent: sig.loc&.begin_column)
|
140
|
+
p = RBI::RBSPrinter.new(out: out, indent: sig.loc&.begin_column, positional_names: positional_names)
|
105
141
|
|
106
142
|
if node.sigs.any?(&:is_final)
|
107
143
|
p.printn("# @final")
|
@@ -133,23 +169,86 @@ module Spoom
|
|
133
169
|
out.string
|
134
170
|
end
|
135
171
|
|
136
|
-
|
137
|
-
def translate_attr_sig(sig, node)
|
172
|
+
#: (RBI::Sig sig, RBI::Attr node, positional_names: bool) -> String
|
173
|
+
def translate_attr_sig(sig, node, positional_names: true)
|
138
174
|
out = StringIO.new
|
139
|
-
p = RBI::RBSPrinter.new(out: out)
|
175
|
+
p = RBI::RBSPrinter.new(out: out, positional_names: positional_names)
|
140
176
|
p.print_attr_sig(node, sig)
|
141
177
|
"#: #{out.string}"
|
142
178
|
end
|
143
179
|
end
|
144
180
|
end
|
145
181
|
|
182
|
+
class RBSToRBITranslator
|
183
|
+
class << self
|
184
|
+
extend T::Sig
|
185
|
+
|
186
|
+
#: (RBI::RBSComment comment, (RBI::Method | RBI::Attr) node) -> String?
|
187
|
+
def translate(comment, node)
|
188
|
+
case node
|
189
|
+
when RBI::Method
|
190
|
+
translate_method_sig(comment, node)
|
191
|
+
when RBI::Attr
|
192
|
+
translate_attr_sig(comment, node)
|
193
|
+
end
|
194
|
+
rescue RBS::ParsingError
|
195
|
+
nil
|
196
|
+
end
|
197
|
+
|
198
|
+
private
|
199
|
+
|
200
|
+
#: (RBI::RBSComment rbs_comment, RBI::Method node) -> String
|
201
|
+
def translate_method_sig(rbs_comment, node)
|
202
|
+
method_type = ::RBS::Parser.parse_method_type(rbs_comment.text)
|
203
|
+
translator = RBI::RBS::MethodTypeTranslator.new(node)
|
204
|
+
translator.visit(method_type)
|
205
|
+
|
206
|
+
# TODO: move this to `rbi`
|
207
|
+
res = translator.result
|
208
|
+
node.comments.each do |comment|
|
209
|
+
case comment.text
|
210
|
+
when "@abstract"
|
211
|
+
res.is_abstract = true
|
212
|
+
when "@final"
|
213
|
+
res.is_final = true
|
214
|
+
when "@override"
|
215
|
+
res.is_override = true
|
216
|
+
when "@override(allow_incompatible: true)"
|
217
|
+
res.is_override = true
|
218
|
+
res.allow_incompatible_override = true
|
219
|
+
when "@overridable"
|
220
|
+
res.is_overridable = true
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
res.string.strip
|
225
|
+
end
|
226
|
+
|
227
|
+
#: (RBI::RBSComment comment, RBI::Attr node) -> String
|
228
|
+
def translate_attr_sig(comment, node)
|
229
|
+
attr_type = ::RBS::Parser.parse_type(comment.text)
|
230
|
+
sig = RBI::Sig.new
|
231
|
+
|
232
|
+
if node.is_a?(RBI::AttrWriter)
|
233
|
+
if node.names.size != 1
|
234
|
+
raise Error, "AttrWriter must have exactly one name"
|
235
|
+
end
|
236
|
+
|
237
|
+
name = T.must(node.names.first)
|
238
|
+
sig.params << RBI::SigParam.new(name.to_s, RBI::RBS::TypeTranslator.translate(attr_type))
|
239
|
+
end
|
240
|
+
|
241
|
+
sig.return_type = RBI::RBS::TypeTranslator.translate(attr_type)
|
242
|
+
sig.string.strip
|
243
|
+
end
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
146
247
|
# From https://github.com/Shopify/ruby-lsp/blob/9154bfc6ef/lib/ruby_lsp/document.rb#L127
|
147
248
|
class Scanner
|
148
|
-
extend T::Sig
|
149
|
-
|
150
249
|
LINE_BREAK = T.let(0x0A, Integer)
|
151
250
|
|
152
|
-
|
251
|
+
#: (String source) -> void
|
153
252
|
def initialize(source)
|
154
253
|
@current_line = T.let(0, Integer)
|
155
254
|
@pos = T.let(0, Integer)
|
@@ -157,7 +256,7 @@ module Spoom
|
|
157
256
|
end
|
158
257
|
|
159
258
|
# Finds the character index inside the source string for a given line and column
|
160
|
-
|
259
|
+
#: (Integer line, Integer character) -> Integer
|
161
260
|
def find_char_position(line, character)
|
162
261
|
# Find the character index for the beginning of the requested line
|
163
262
|
until @current_line == line
|
data/lib/spoom/sorbet.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# typed: strict
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
+
require "spoom/sorbet/assertions"
|
4
5
|
require "spoom/sorbet/config"
|
5
6
|
require "spoom/sorbet/errors"
|
6
7
|
require "spoom/sorbet/lsp"
|
@@ -12,20 +13,13 @@ require "open3"
|
|
12
13
|
module Spoom
|
13
14
|
module Sorbet
|
14
15
|
class Error < Spoom::Error
|
15
|
-
extend T::Sig
|
16
|
-
|
17
16
|
class Killed < Error; end
|
18
17
|
class Segfault < Error; end
|
19
18
|
|
20
|
-
|
19
|
+
#: ExecResult
|
21
20
|
attr_reader :result
|
22
21
|
|
23
|
-
|
24
|
-
params(
|
25
|
-
message: String,
|
26
|
-
result: ExecResult,
|
27
|
-
).void
|
28
|
-
end
|
22
|
+
#: (String message, ExecResult result) -> void
|
29
23
|
def initialize(message, result)
|
30
24
|
super(message)
|
31
25
|
|
data/lib/spoom/timeline.rb
CHANGED
@@ -3,9 +3,7 @@
|
|
3
3
|
|
4
4
|
module Spoom
|
5
5
|
class Timeline
|
6
|
-
|
7
|
-
|
8
|
-
sig { params(context: Context, from: Time, to: Time).void }
|
6
|
+
#: (Context context, Time from, Time to) -> void
|
9
7
|
def initialize(context, from, to)
|
10
8
|
@context = context
|
11
9
|
@from = from
|
@@ -13,13 +11,13 @@ module Spoom
|
|
13
11
|
end
|
14
12
|
|
15
13
|
# Return one commit for each month between `from` and `to`
|
16
|
-
|
14
|
+
#: -> Array[Git::Commit]
|
17
15
|
def ticks
|
18
16
|
commits_for_dates(months)
|
19
17
|
end
|
20
18
|
|
21
19
|
# Return all months between `from` and `to`
|
22
|
-
|
20
|
+
#: -> Array[Time]
|
23
21
|
def months
|
24
22
|
d = Date.new(@from.year, @from.month, 1)
|
25
23
|
to = Date.new(@to.year, @to.month, 1)
|
@@ -32,7 +30,7 @@ module Spoom
|
|
32
30
|
end
|
33
31
|
|
34
32
|
# Return one commit for each date in `dates`
|
35
|
-
|
33
|
+
#: (Array[Time] dates) -> Array[Git::Commit]
|
36
34
|
def commits_for_dates(dates)
|
37
35
|
dates.map do |t|
|
38
36
|
result = @context.git_log(
|
data/lib/spoom/version.rb
CHANGED