steep 0.49.1 → 0.50.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/CHANGELOG.md +10 -0
- data/Gemfile +3 -1
- data/Gemfile.lock +2 -2
- data/lib/steep/cli.rb +5 -0
- data/lib/steep/drivers/check.rb +1 -0
- data/lib/steep/drivers/langserver.rb +2 -2
- data/lib/steep/drivers/stats.rb +1 -0
- data/lib/steep/drivers/utils/jobs_count.rb +1 -1
- data/lib/steep/drivers/watch.rb +1 -1
- data/lib/steep/interface/function.rb +5 -0
- data/lib/steep/project.rb +15 -1
- data/lib/steep/server/interaction_worker.rb +2 -2
- data/lib/steep/server/master.rb +9 -4
- data/lib/steep/server/type_check_worker.rb +19 -4
- data/lib/steep/server/worker_process.rb +15 -6
- data/lib/steep/services/goto_service.rb +19 -4
- data/lib/steep/type_construction.rb +31 -14
- data/lib/steep/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6ff552f6d8f112693dc9969f20d851ddbc6d7d2f16cebd45f802a5d703618b58
|
|
4
|
+
data.tar.gz: 723464fe34c81c3e83b66338dfc6fd3e7c3da2aaf30c1fc48116c7de794ca961
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: bf9f83791cfb636c65a26f404fb164fa7fc3906376e36a79a1ca4ae7eeab8020e23c5b9ce5e649a38ed79080d0aa2c00fe53a5cce8a1c76c259237f38880bbf2
|
|
7
|
+
data.tar.gz: 25bd9e11db283acdfc957682860e674d544b82be1b5a68bc87ca96888907966b721301c937cdaa3e06bf0226ec82fa8c78eacfaf4987637a601f75ca8d8e950c
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
## master
|
|
4
4
|
|
|
5
|
+
# 0.50.0 (2022-03-22)
|
|
6
|
+
|
|
7
|
+
* CLI option for override steep command at spawn worker ([\#511](https://github.com/soutaro/steep/pull/511))
|
|
8
|
+
* LSP related improvements for Sublime LSP ([\#513](https://github.com/soutaro/steep/pull/513))
|
|
9
|
+
* Support Windows environment ([\#514](https://github.com/soutaro/steep/pull/514))
|
|
10
|
+
* Let `&:foo` proc work with methods with optional parameters ([\#516](https://github.com/soutaro/steep/pull/516))
|
|
11
|
+
* Fix unexpected error when or-asgn/and-asgn ([\#517](https://github.com/soutaro/steep/pull/517))
|
|
12
|
+
* Fix goto-definition from method call inside block ([\#518](https://github.com/soutaro/steep/pull/518))
|
|
13
|
+
* Better splat in array typing ([\#519](https://github.com/soutaro/steep/pull/519))
|
|
14
|
+
|
|
5
15
|
## 0.49.1 (2022-03-11)
|
|
6
16
|
|
|
7
17
|
* Fix lambda typing ([\#506](https://github.com/soutaro/steep/pull/506))
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
steep (0.
|
|
4
|
+
steep (0.50.0)
|
|
5
5
|
activesupport (>= 5.1)
|
|
6
6
|
language_server-protocol (>= 3.15, < 4.0)
|
|
7
7
|
listen (~> 3.0)
|
|
@@ -41,7 +41,7 @@ GEM
|
|
|
41
41
|
minitest (5.15.0)
|
|
42
42
|
minitest-hooks (1.5.0)
|
|
43
43
|
minitest (> 5.3)
|
|
44
|
-
parallel (1.
|
|
44
|
+
parallel (1.22.0)
|
|
45
45
|
parser (3.1.1.0)
|
|
46
46
|
ast (~> 2.4.1)
|
|
47
47
|
rainbow (3.1.1)
|
data/lib/steep/cli.rb
CHANGED
|
@@ -72,6 +72,11 @@ module Steep
|
|
|
72
72
|
opts.on("-j N", "--jobs=N", "Specify the number of type check workers (defaults: #{default})") do |count|
|
|
73
73
|
command.jobs_count = Integer(count) if Integer(count) > 0
|
|
74
74
|
end
|
|
75
|
+
|
|
76
|
+
command.steep_command = "steep"
|
|
77
|
+
opts.on("--steep-command=COMMAND", "Specify command to exec Steep CLI for worker (defaults: steep)") do |cmd|
|
|
78
|
+
command.steep_command = cmd
|
|
79
|
+
end
|
|
75
80
|
end
|
|
76
81
|
|
|
77
82
|
def process_init
|
data/lib/steep/drivers/check.rb
CHANGED
|
@@ -37,8 +37,8 @@ module Steep
|
|
|
37
37
|
def run
|
|
38
38
|
@project = load_config()
|
|
39
39
|
|
|
40
|
-
interaction_worker = Server::WorkerProcess.spawn_worker(:interaction, name: "interaction", steepfile: project.steepfile_path)
|
|
41
|
-
typecheck_workers = Server::WorkerProcess.spawn_typecheck_workers(steepfile: project.steepfile_path, args: [], count: jobs_count)
|
|
40
|
+
interaction_worker = Server::WorkerProcess.spawn_worker(:interaction, name: "interaction", steepfile: project.steepfile_path, steep_command: steep_command)
|
|
41
|
+
typecheck_workers = Server::WorkerProcess.spawn_typecheck_workers(steepfile: project.steepfile_path, args: [], steep_command: steep_command, count: jobs_count)
|
|
42
42
|
|
|
43
43
|
master = Server::Master.new(
|
|
44
44
|
project: project,
|
data/lib/steep/drivers/stats.rb
CHANGED
data/lib/steep/drivers/watch.rb
CHANGED
|
@@ -41,7 +41,7 @@ module Steep
|
|
|
41
41
|
server_reader = LanguageServer::Protocol::Transport::Io::Reader.new(server_read)
|
|
42
42
|
server_writer = LanguageServer::Protocol::Transport::Io::Writer.new(server_write)
|
|
43
43
|
|
|
44
|
-
typecheck_workers = Server::WorkerProcess.spawn_typecheck_workers(steepfile: project.steepfile_path, args: dirs.map(&:to_s), count: jobs_count)
|
|
44
|
+
typecheck_workers = Server::WorkerProcess.spawn_typecheck_workers(steepfile: project.steepfile_path, args: dirs.map(&:to_s), steep_command: steep_command, count: jobs_count)
|
|
45
45
|
|
|
46
46
|
master = Server::Master.new(
|
|
47
47
|
project: project,
|
|
@@ -879,6 +879,11 @@ module Steep
|
|
|
879
879
|
!has_positional? && !has_keywords?
|
|
880
880
|
end
|
|
881
881
|
|
|
882
|
+
# Returns true if all arguments are non-required.
|
|
883
|
+
def optional?
|
|
884
|
+
required.empty? && required_keywords.empty?
|
|
885
|
+
end
|
|
886
|
+
|
|
882
887
|
# self + params returns a new params for overloading.
|
|
883
888
|
#
|
|
884
889
|
def +(other)
|
data/lib/steep/project.rb
CHANGED
|
@@ -16,7 +16,21 @@ module Steep
|
|
|
16
16
|
steepfile_path.parent
|
|
17
17
|
end
|
|
18
18
|
|
|
19
|
-
def relative_path(
|
|
19
|
+
def relative_path(orig_path)
|
|
20
|
+
path = if Gem.win_platform?
|
|
21
|
+
path_str = URI.decode_www_form_component(
|
|
22
|
+
orig_path.to_s.delete_prefix("/")
|
|
23
|
+
)
|
|
24
|
+
unless path_str.start_with?(%r{[a-z]:/}i)
|
|
25
|
+
# FIXME: Sometimes drive letter is missing, taking from base_dir
|
|
26
|
+
path_str = base_dir.to_s.split("/")[0] + "/" + path_str
|
|
27
|
+
end
|
|
28
|
+
Pathname.new(
|
|
29
|
+
path_str
|
|
30
|
+
)
|
|
31
|
+
else
|
|
32
|
+
orig_path
|
|
33
|
+
end
|
|
20
34
|
path.relative_path_from(base_dir)
|
|
21
35
|
end
|
|
22
36
|
|
|
@@ -89,7 +89,7 @@ module Steep
|
|
|
89
89
|
end
|
|
90
90
|
|
|
91
91
|
LSP::Interface::Hover.new(
|
|
92
|
-
contents: { kind: "markdown", value: format_hover(content) },
|
|
92
|
+
contents: { kind: "markdown", value: format_hover(content)&.gsub(/<!--(?~-->)-->/, "") },
|
|
93
93
|
range: range
|
|
94
94
|
)
|
|
95
95
|
end
|
|
@@ -271,7 +271,7 @@ HOVER
|
|
|
271
271
|
),
|
|
272
272
|
end: LanguageServer::Protocol::Interface::Position.new(
|
|
273
273
|
line: job.line - 1,
|
|
274
|
-
character: job.column
|
|
274
|
+
character: job.column
|
|
275
275
|
)
|
|
276
276
|
)
|
|
277
277
|
|
data/lib/steep/server/master.rb
CHANGED
|
@@ -49,9 +49,14 @@ module Steep
|
|
|
49
49
|
end
|
|
50
50
|
|
|
51
51
|
def checking_path?(path)
|
|
52
|
-
library_paths.
|
|
53
|
-
|
|
54
|
-
|
|
52
|
+
[library_paths, signature_paths, code_paths].any? do |paths|
|
|
53
|
+
if Gem.win_platform?
|
|
54
|
+
# FIXME: Sometimes drive letter is missing, so comparing without drive letter.
|
|
55
|
+
paths.any? {|p| p.to_s.split("/", 2)[1] == path.to_s.split("/", 2)[1]}
|
|
56
|
+
else
|
|
57
|
+
paths.include?(path)
|
|
58
|
+
end
|
|
59
|
+
end
|
|
55
60
|
end
|
|
56
61
|
|
|
57
62
|
def checked(path)
|
|
@@ -739,7 +744,7 @@ module Steep
|
|
|
739
744
|
{ kind: "end" }
|
|
740
745
|
else
|
|
741
746
|
progress_string = ("▮"*(percentage/5)) + ("▯"*(20 - percentage/5))
|
|
742
|
-
{ kind: "report", percentage: percentage, message: "#{progress_string}
|
|
747
|
+
{ kind: "report", percentage: percentage, message: "#{progress_string}" }
|
|
743
748
|
end
|
|
744
749
|
|
|
745
750
|
job_queue << SendMessageJob.to_client(
|
|
@@ -135,6 +135,21 @@ module Steep
|
|
|
135
135
|
end
|
|
136
136
|
|
|
137
137
|
def handle_job(job)
|
|
138
|
+
job_path = if job.respond_to?(:path)
|
|
139
|
+
if Gem.win_platform?
|
|
140
|
+
# FIXME: Sometimes drive letter is missing, using base_dir
|
|
141
|
+
if job.path.to_s.start_with?(%r{/[a-z](:|%3A)/}i)
|
|
142
|
+
job.path.to_s
|
|
143
|
+
else
|
|
144
|
+
"/#{project.base_dir.to_s.split("/").first}/#{job.path}"
|
|
145
|
+
end
|
|
146
|
+
else
|
|
147
|
+
job.path.to_s
|
|
148
|
+
end
|
|
149
|
+
else
|
|
150
|
+
nil
|
|
151
|
+
end
|
|
152
|
+
|
|
138
153
|
case job
|
|
139
154
|
when StartTypeCheckJob
|
|
140
155
|
Steep.logger.info { "Processing StartTypeCheckJob for guid=#{job.guid}" }
|
|
@@ -149,7 +164,7 @@ module Steep
|
|
|
149
164
|
writer.write(
|
|
150
165
|
method: :"textDocument/publishDiagnostics",
|
|
151
166
|
params: LSP::Interface::PublishDiagnosticsParams.new(
|
|
152
|
-
uri: URI.parse(
|
|
167
|
+
uri: URI.parse(job_path).tap {|uri| uri.scheme = "file"},
|
|
153
168
|
diagnostics: diagnostics.map {|diagnostic| formatter.format(diagnostic) }.uniq
|
|
154
169
|
)
|
|
155
170
|
)
|
|
@@ -167,7 +182,7 @@ module Steep
|
|
|
167
182
|
writer.write(
|
|
168
183
|
method: :"textDocument/publishDiagnostics",
|
|
169
184
|
params: LSP::Interface::PublishDiagnosticsParams.new(
|
|
170
|
-
uri: URI.parse(
|
|
185
|
+
uri: URI.parse(job_path).tap {|uri| uri.scheme = "file"},
|
|
171
186
|
diagnostics: diagnostics.map {|diagnostic| formatter.format(diagnostic) }.uniq.compact
|
|
172
187
|
)
|
|
173
188
|
)
|
|
@@ -186,7 +201,7 @@ module Steep
|
|
|
186
201
|
writer.write(
|
|
187
202
|
method: :"textDocument/publishDiagnostics",
|
|
188
203
|
params: LSP::Interface::PublishDiagnosticsParams.new(
|
|
189
|
-
uri: URI.parse(
|
|
204
|
+
uri: URI.parse(job_path).tap {|uri| uri.scheme = "file"},
|
|
190
205
|
diagnostics: diagnostics.map {|diagnostic| formatter.format(diagnostic) }.uniq.compact
|
|
191
206
|
)
|
|
192
207
|
)
|
|
@@ -268,7 +283,7 @@ module Steep
|
|
|
268
283
|
line = job.params[:position][:line] + 1
|
|
269
284
|
column = job.params[:position][:character]
|
|
270
285
|
|
|
271
|
-
goto_service = Services::GotoService.new(type_check: service)
|
|
286
|
+
goto_service = Services::GotoService.new(type_check: service, assignment: assignment)
|
|
272
287
|
locations =
|
|
273
288
|
case
|
|
274
289
|
when job.definition?
|
|
@@ -18,13 +18,17 @@ module Steep
|
|
|
18
18
|
@index = index
|
|
19
19
|
end
|
|
20
20
|
|
|
21
|
-
def self.spawn_worker(type, name:, steepfile:, options: [], delay_shutdown: false, index: nil)
|
|
22
|
-
|
|
21
|
+
def self.spawn_worker(type, name:, steepfile:, steep_command: "steep", options: [], delay_shutdown: false, index: nil)
|
|
22
|
+
args = ["--name=#{name}", "--steepfile=#{steepfile}"]
|
|
23
|
+
args << (%w(debug info warn error fatal unknown)[Steep.logger.level].yield_self {|log_level| "--log-level=#{log_level}" })
|
|
24
|
+
if Steep.log_output.is_a?(String)
|
|
25
|
+
args << "--log-output=#{Steep.log_output}"
|
|
26
|
+
end
|
|
23
27
|
command = case type
|
|
24
28
|
when :interaction
|
|
25
|
-
[
|
|
29
|
+
[steep_command, "worker", "--interaction", *args, *options]
|
|
26
30
|
when :typecheck
|
|
27
|
-
[
|
|
31
|
+
[steep_command, "worker", "--typecheck", *args, *options]
|
|
28
32
|
else
|
|
29
33
|
raise "Unknown type: #{type}"
|
|
30
34
|
end
|
|
@@ -33,7 +37,11 @@ module Steep
|
|
|
33
37
|
command << "--delay-shutdown"
|
|
34
38
|
end
|
|
35
39
|
|
|
36
|
-
stdin, stdout, thread =
|
|
40
|
+
stdin, stdout, thread = if Gem.win_platform?
|
|
41
|
+
Open3.popen2(*command, new_pgroup: true)
|
|
42
|
+
else
|
|
43
|
+
Open3.popen2(*command, pgroup: true)
|
|
44
|
+
end
|
|
37
45
|
stderr = nil
|
|
38
46
|
|
|
39
47
|
writer = LanguageServer::Protocol::Transport::Io::Writer.new(stdin)
|
|
@@ -42,11 +50,12 @@ module Steep
|
|
|
42
50
|
new(reader: reader, writer: writer, stderr: stderr, wait_thread: thread, name: name, index: index)
|
|
43
51
|
end
|
|
44
52
|
|
|
45
|
-
def self.spawn_typecheck_workers(steepfile:, args:, count: [Etc.nprocessors - 1, 1].max, delay_shutdown: false)
|
|
53
|
+
def self.spawn_typecheck_workers(steepfile:, args:, steep_command: "steep", count: [Etc.nprocessors - 1, 1].max, delay_shutdown: false)
|
|
46
54
|
count.times.map do |i|
|
|
47
55
|
spawn_worker(:typecheck,
|
|
48
56
|
name: "typecheck@#{i}",
|
|
49
57
|
steepfile: steepfile,
|
|
58
|
+
steep_command: steep_command,
|
|
50
59
|
options: ["--max-index=#{count}", "--index=#{i}", *args],
|
|
51
60
|
delay_shutdown: delay_shutdown,
|
|
52
61
|
index: i)
|
|
@@ -21,10 +21,11 @@ module Steep
|
|
|
21
21
|
end
|
|
22
22
|
TypeNameQuery = Struct.new(:name, keyword_init: true)
|
|
23
23
|
|
|
24
|
-
attr_reader :type_check
|
|
24
|
+
attr_reader :type_check, :assignment
|
|
25
25
|
|
|
26
|
-
def initialize(type_check:)
|
|
26
|
+
def initialize(type_check:, assignment:)
|
|
27
27
|
@type_check = type_check
|
|
28
|
+
@assignment = assignment
|
|
28
29
|
end
|
|
29
30
|
|
|
30
31
|
def project
|
|
@@ -78,7 +79,17 @@ module Steep
|
|
|
78
79
|
end
|
|
79
80
|
end
|
|
80
81
|
|
|
81
|
-
|
|
82
|
+
# Drop un-assigned paths here.
|
|
83
|
+
# The path assignment makes sense only for `.rbs` files, because un-assigned `.rb` files are already skipped since they are not type checked.
|
|
84
|
+
#
|
|
85
|
+
locations.uniq.select do |loc|
|
|
86
|
+
case loc
|
|
87
|
+
when RBS::Location
|
|
88
|
+
assignment =~ loc.name
|
|
89
|
+
else
|
|
90
|
+
true
|
|
91
|
+
end
|
|
92
|
+
end
|
|
82
93
|
end
|
|
83
94
|
|
|
84
95
|
def test_ast_location(loc, line:, column:)
|
|
@@ -100,6 +111,7 @@ module Steep
|
|
|
100
111
|
typing, signature = type_check_path(target: target, path: relative_path, content: source.content, line: line, column: column)
|
|
101
112
|
if typing
|
|
102
113
|
node, *parents = typing.source.find_nodes(line: line, column: column)
|
|
114
|
+
|
|
103
115
|
if node
|
|
104
116
|
case node.type
|
|
105
117
|
when :const, :casgn
|
|
@@ -125,7 +137,10 @@ module Steep
|
|
|
125
137
|
end
|
|
126
138
|
when :send
|
|
127
139
|
if test_ast_location(node.location.selector, line: line, column: column)
|
|
128
|
-
|
|
140
|
+
if (parent = parents[0]) && parent.type == :block && parent.children[0] == node
|
|
141
|
+
node = parents[0]
|
|
142
|
+
end
|
|
143
|
+
|
|
129
144
|
case call = typing.call_of(node: node)
|
|
130
145
|
when TypeInference::MethodCall::Typed, TypeInference::MethodCall::Error
|
|
131
146
|
call.method_decls.each do |decl|
|
|
@@ -2275,13 +2275,10 @@ module Steep
|
|
|
2275
2275
|
type, constr = synthesize(rhs, hint: hint)
|
|
2276
2276
|
constr.ivasgn(asgn, type)
|
|
2277
2277
|
when :send
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
asgn.children[2],
|
|
2283
|
-
rhs
|
|
2284
|
-
])
|
|
2278
|
+
children = asgn.children.dup
|
|
2279
|
+
children[1] = :"#{children[1]}="
|
|
2280
|
+
send_arg_nodes = [*children, rhs]
|
|
2281
|
+
rhs_ = node.updated(:send, send_arg_nodes)
|
|
2285
2282
|
node_type = case node.type
|
|
2286
2283
|
when :or_asgn
|
|
2287
2284
|
:or
|
|
@@ -2348,11 +2345,11 @@ module Steep
|
|
|
2348
2345
|
interface = calculate_interface(param_type, private: true)
|
|
2349
2346
|
method = interface.methods[value.children[0]]
|
|
2350
2347
|
if method
|
|
2351
|
-
return_types = method.method_types.
|
|
2352
|
-
method_type.type.params.
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2348
|
+
return_types = method.method_types.filter_map do |method_type|
|
|
2349
|
+
if method_type.type.params.optional?
|
|
2350
|
+
method_type.type.return_type
|
|
2351
|
+
end
|
|
2352
|
+
end
|
|
2356
2353
|
|
|
2357
2354
|
unless return_types.empty?
|
|
2358
2355
|
type = AST::Types::Proc.new(
|
|
@@ -2360,7 +2357,7 @@ module Steep
|
|
|
2360
2357
|
params: Interface::Function::Params.empty.with_first_param(
|
|
2361
2358
|
Interface::Function::Params::PositionalParams::Required.new(param_type)
|
|
2362
2359
|
),
|
|
2363
|
-
return_type:
|
|
2360
|
+
return_type: return_types[0],
|
|
2364
2361
|
location: nil
|
|
2365
2362
|
),
|
|
2366
2363
|
block: nil
|
|
@@ -3948,6 +3945,20 @@ module Steep
|
|
|
3948
3945
|
constr.add_typing(node, type: AST::Types::Tuple.new(types: element_types))
|
|
3949
3946
|
end
|
|
3950
3947
|
|
|
3948
|
+
def try_convert(type, method)
|
|
3949
|
+
interface = checker.factory.interface(type, private: false)
|
|
3950
|
+
if entry = interface.methods[method]
|
|
3951
|
+
method_type = entry.method_types.find do |method_type|
|
|
3952
|
+
method_type.type.params.optional?
|
|
3953
|
+
end
|
|
3954
|
+
|
|
3955
|
+
method_type.type.return_type
|
|
3956
|
+
end
|
|
3957
|
+
rescue => exn
|
|
3958
|
+
Steep.log_error(exn, message: "Unexpected error when converting #{type.to_s} with #{method}")
|
|
3959
|
+
nil
|
|
3960
|
+
end
|
|
3961
|
+
|
|
3951
3962
|
def try_array_type(node, hint)
|
|
3952
3963
|
element_hint = hint ? hint.args[0] : nil
|
|
3953
3964
|
|
|
@@ -3958,8 +3969,14 @@ module Steep
|
|
|
3958
3969
|
case child.type
|
|
3959
3970
|
when :splat
|
|
3960
3971
|
type, constr = constr.synthesize(child.children[0], hint: hint)
|
|
3961
|
-
|
|
3972
|
+
|
|
3973
|
+
type = try_convert(type, :to_a) || type
|
|
3974
|
+
|
|
3975
|
+
case
|
|
3976
|
+
when AST::Builtin::Array.instance_type?(type)
|
|
3962
3977
|
element_types << type.args[0]
|
|
3978
|
+
when type.is_a?(AST::Types::Tuple)
|
|
3979
|
+
element_types.push(*type.types)
|
|
3963
3980
|
else
|
|
3964
3981
|
element_types.push(*flatten_array_elements(type))
|
|
3965
3982
|
end
|
data/lib/steep/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: steep
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.50.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Soutaro Matsumoto
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2022-03-
|
|
11
|
+
date: 2022-03-22 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: parser
|