typeprof 0.21.11 → 0.30.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +15 -31
- data/bin/typeprof +5 -0
- data/doc/doc.ja.md +134 -0
- data/doc/doc.md +136 -0
- data/lib/typeprof/cli/cli.rb +180 -0
- data/lib/typeprof/cli.rb +2 -133
- data/lib/typeprof/code_range.rb +112 -0
- data/lib/typeprof/core/ast/base.rb +263 -0
- data/lib/typeprof/core/ast/call.rb +251 -0
- data/lib/typeprof/core/ast/const.rb +126 -0
- data/lib/typeprof/core/ast/control.rb +432 -0
- data/lib/typeprof/core/ast/meta.rb +150 -0
- data/lib/typeprof/core/ast/method.rb +335 -0
- data/lib/typeprof/core/ast/misc.rb +263 -0
- data/lib/typeprof/core/ast/module.rb +123 -0
- data/lib/typeprof/core/ast/pattern.rb +140 -0
- data/lib/typeprof/core/ast/sig_decl.rb +471 -0
- data/lib/typeprof/core/ast/sig_type.rb +663 -0
- data/lib/typeprof/core/ast/value.rb +319 -0
- data/lib/typeprof/core/ast/variable.rb +315 -0
- data/lib/typeprof/core/ast.rb +472 -0
- data/lib/typeprof/core/builtin.rb +146 -0
- data/lib/typeprof/core/env/method.rb +137 -0
- data/lib/typeprof/core/env/method_entity.rb +55 -0
- data/lib/typeprof/core/env/module_entity.rb +408 -0
- data/lib/typeprof/core/env/static_read.rb +155 -0
- data/lib/typeprof/core/env/type_alias_entity.rb +27 -0
- data/lib/typeprof/core/env/value_entity.rb +32 -0
- data/lib/typeprof/core/env.rb +360 -0
- data/lib/typeprof/core/graph/box.rb +991 -0
- data/lib/typeprof/core/graph/change_set.rb +224 -0
- data/lib/typeprof/core/graph/filter.rb +155 -0
- data/lib/typeprof/core/graph/vertex.rb +222 -0
- data/lib/typeprof/core/graph.rb +3 -0
- data/lib/typeprof/core/service.rb +522 -0
- data/lib/typeprof/core/type.rb +348 -0
- data/lib/typeprof/core/util.rb +81 -0
- data/lib/typeprof/core.rb +32 -0
- data/lib/typeprof/diagnostic.rb +35 -0
- data/lib/typeprof/lsp/messages.rb +430 -0
- data/lib/typeprof/lsp/server.rb +177 -0
- data/lib/typeprof/lsp/text.rb +69 -0
- data/lib/typeprof/lsp/util.rb +61 -0
- data/lib/typeprof/lsp.rb +4 -907
- data/lib/typeprof/version.rb +1 -1
- data/lib/typeprof.rb +4 -18
- data/typeprof.gemspec +5 -7
- metadata +48 -35
- data/.github/dependabot.yml +0 -6
- data/.github/workflows/main.yml +0 -39
- data/.gitignore +0 -9
- data/Gemfile +0 -17
- data/Gemfile.lock +0 -41
- data/Rakefile +0 -10
- data/exe/typeprof +0 -10
- data/lib/typeprof/analyzer.rb +0 -2598
- data/lib/typeprof/arguments.rb +0 -414
- data/lib/typeprof/block.rb +0 -176
- data/lib/typeprof/builtin.rb +0 -893
- data/lib/typeprof/code-range.rb +0 -177
- data/lib/typeprof/config.rb +0 -158
- data/lib/typeprof/container-type.rb +0 -912
- data/lib/typeprof/export.rb +0 -589
- data/lib/typeprof/import.rb +0 -852
- data/lib/typeprof/insns-def.rb +0 -65
- data/lib/typeprof/iseq.rb +0 -864
- data/lib/typeprof/method.rb +0 -355
- data/lib/typeprof/type.rb +0 -1140
- data/lib/typeprof/utils.rb +0 -212
- data/tools/coverage.rb +0 -14
- data/tools/setup-insns-def.rb +0 -30
- data/typeprof-lsp +0 -3
data/lib/typeprof/import.rb
DELETED
@@ -1,852 +0,0 @@
|
|
1
|
-
require "rbs"
|
2
|
-
|
3
|
-
module TypeProf
|
4
|
-
class RBSReader
|
5
|
-
def initialize
|
6
|
-
@repo = RBS::Repository.new
|
7
|
-
collection_path = Config.current.collection_path
|
8
|
-
if collection_path&.exist?
|
9
|
-
lock_path = RBS::Collection::Config.to_lockfile_path(collection_path)
|
10
|
-
if lock_path.exist?
|
11
|
-
collection_lock = RBS::Collection::Config.from_path(lock_path)
|
12
|
-
@repo.add(collection_lock.repo_path)
|
13
|
-
else
|
14
|
-
raise "Please execute 'rbs collection install'"
|
15
|
-
end
|
16
|
-
end
|
17
|
-
@env, @loaded_gems, @builtin_env_json = RBSReader.get_builtin_env
|
18
|
-
end
|
19
|
-
|
20
|
-
@builtin_env = @builtin_env_json = nil
|
21
|
-
def self.get_builtin_env
|
22
|
-
@loaded_gems = []
|
23
|
-
unless @builtin_env
|
24
|
-
@builtin_env = RBS::Environment.new
|
25
|
-
|
26
|
-
loader = RBS::EnvironmentLoader.new
|
27
|
-
|
28
|
-
# TODO: invalidate this cache when rbs_collection.yml was changed
|
29
|
-
collection_path = Config.current.collection_path
|
30
|
-
if collection_path&.exist?
|
31
|
-
lock_path = RBS::Collection::Config.to_lockfile_path(collection_path)
|
32
|
-
if lock_path.exist?
|
33
|
-
collection_lock = RBS::Collection::Config::Lockfile.from_lockfile(lockfile_path: lock_path, data: YAML.load_file(lock_path.to_s))
|
34
|
-
collection_lock.gems.each_value {|gem| @loaded_gems << gem[:name] }
|
35
|
-
loader.add_collection(collection_lock)
|
36
|
-
else
|
37
|
-
raise "Please execute 'rbs collection install'"
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
new_decls = loader.load(env: @builtin_env).map {|decl,| decl }
|
42
|
-
@builtin_env_json = load_rbs(@builtin_env, new_decls)
|
43
|
-
end
|
44
|
-
|
45
|
-
return @builtin_env.dup, @loaded_gems.dup, @builtin_env_json
|
46
|
-
end
|
47
|
-
|
48
|
-
def load_builtin
|
49
|
-
@builtin_env_json
|
50
|
-
end
|
51
|
-
|
52
|
-
class RBSCollectionDefined < StandardError; end
|
53
|
-
|
54
|
-
def load_library(lib)
|
55
|
-
loader = RBS::EnvironmentLoader.new(core_root: nil, repository: @repo)
|
56
|
-
if @loaded_gems.include?(lib)
|
57
|
-
raise RBSCollectionDefined
|
58
|
-
end
|
59
|
-
@loaded_gems << lib
|
60
|
-
loader.add(library: lib)
|
61
|
-
|
62
|
-
case lib
|
63
|
-
when 'bigdecimal-math'
|
64
|
-
loader.add(library: 'bigdecimal')
|
65
|
-
when "yaml"
|
66
|
-
loader.add(library: "pstore")
|
67
|
-
loader.add(library: "dbm")
|
68
|
-
when "logger"
|
69
|
-
loader.add(library: "monitor")
|
70
|
-
when "csv"
|
71
|
-
loader.add(library: "forwardable")
|
72
|
-
when "prime"
|
73
|
-
loader.add(library: "singleton")
|
74
|
-
end
|
75
|
-
|
76
|
-
new_decls = loader.load(env: @env).map {|decl,| decl }
|
77
|
-
RBSReader.load_rbs(@env, new_decls)
|
78
|
-
end
|
79
|
-
|
80
|
-
def load_paths(paths)
|
81
|
-
loader = RBS::EnvironmentLoader.new(core_root: nil, repository: @repo)
|
82
|
-
paths.each {|path| loader.add(path: path) }
|
83
|
-
new_decls = loader.load(env: @env).map {|decl,| decl }
|
84
|
-
RBSReader.load_rbs(@env, new_decls)
|
85
|
-
end
|
86
|
-
|
87
|
-
def load_rbs_string(name, content)
|
88
|
-
buffer = RBS::Buffer.new(name: name, content: content)
|
89
|
-
new_decls = []
|
90
|
-
ret = RBS::Parser.parse_signature(buffer)
|
91
|
-
if ret[0].is_a?(RBS::Buffer)
|
92
|
-
# rbs 3.0
|
93
|
-
buffer, directives, decls = ret
|
94
|
-
@env.add_signature(buffer: buffer, directives: directives, decls: decls)
|
95
|
-
new_decls.concat(decls)
|
96
|
-
else
|
97
|
-
ret.each do |decl|
|
98
|
-
@env << decl
|
99
|
-
new_decls << decl
|
100
|
-
end
|
101
|
-
end
|
102
|
-
RBSReader.load_rbs(@env, new_decls)
|
103
|
-
end
|
104
|
-
|
105
|
-
def self.load_rbs(env, new_decls)
|
106
|
-
all_env = env.resolve_type_names
|
107
|
-
cur_env = RBS::Environment.new
|
108
|
-
if defined?(RBS::TypeNameResolver)
|
109
|
-
resolver = RBS::TypeNameResolver.from_env(all_env)
|
110
|
-
new_decls.each do |decl|
|
111
|
-
cur_env << env.resolve_declaration(resolver, decl, outer: [], prefix: RBS::Namespace.root)
|
112
|
-
end
|
113
|
-
else
|
114
|
-
resolver = RBS::Resolver::TypeNameResolver.new(all_env)
|
115
|
-
table = RBS::Environment::UseMap::Table.new()
|
116
|
-
table.compute_children
|
117
|
-
map = RBS::Environment::UseMap.new(table: table)
|
118
|
-
new_decls.each do |decl|
|
119
|
-
cur_env << s = env.resolve_declaration(resolver, map, decl, outer: [], prefix: RBS::Namespace.root)
|
120
|
-
end
|
121
|
-
end
|
122
|
-
|
123
|
-
RBS2JSON.new(all_env, cur_env).dump_json
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
|
-
class RBS2JSON
|
128
|
-
def initialize(all_env, cur_env)
|
129
|
-
@all_env, @cur_env = all_env, cur_env
|
130
|
-
@alias_resolution_stack = {}
|
131
|
-
end
|
132
|
-
|
133
|
-
def dump_json
|
134
|
-
{
|
135
|
-
classes: conv_classes,
|
136
|
-
constants: conv_constants,
|
137
|
-
globals: conv_globals,
|
138
|
-
}
|
139
|
-
end
|
140
|
-
|
141
|
-
# constant_name = [Symbol]
|
142
|
-
#
|
143
|
-
# { constant_name => type }
|
144
|
-
def conv_constants
|
145
|
-
constants = {}
|
146
|
-
@cur_env.constant_decls.each do |name, decl|
|
147
|
-
klass = conv_type_name(name)
|
148
|
-
constants[klass] = conv_type(decl.decl.type)
|
149
|
-
end
|
150
|
-
constants
|
151
|
-
end
|
152
|
-
|
153
|
-
# gvar_name = Symbol (:$gvar)
|
154
|
-
#
|
155
|
-
# { gvar_name => type }
|
156
|
-
def conv_globals
|
157
|
-
gvars = {}
|
158
|
-
@cur_env.global_decls.each do |name, decl|
|
159
|
-
decl = decl.decl
|
160
|
-
gvars[name] = conv_type(decl.type)
|
161
|
-
end
|
162
|
-
gvars
|
163
|
-
end
|
164
|
-
|
165
|
-
AliasDecl = defined?(RBS::AST::Declarations::Alias) ? RBS::AST::Declarations::Alias : RBS::AST::Declarations::AliasDecl
|
166
|
-
TypeAlias = defined?(RBS::AST::Declarations::TypeAlias) ? RBS::AST::Declarations::TypeAlias : nil
|
167
|
-
|
168
|
-
def conv_classes
|
169
|
-
json = {}
|
170
|
-
|
171
|
-
each_class_decl do |name, decls|
|
172
|
-
klass = conv_type_name(name)
|
173
|
-
super_class_name, super_class_args = get_super_class(name, decls)
|
174
|
-
if super_class_name
|
175
|
-
name = conv_type_name(super_class_name)
|
176
|
-
type_args = super_class_args.map {|type| conv_type(type) }
|
177
|
-
superclass = [name, type_args]
|
178
|
-
end
|
179
|
-
|
180
|
-
type_params = nil
|
181
|
-
modules = { include: [], extend: [], prepend: [] }
|
182
|
-
methods = {}
|
183
|
-
attr_methods = {}
|
184
|
-
ivars = {}
|
185
|
-
cvars = {}
|
186
|
-
rbs_sources = {}
|
187
|
-
visibility = true
|
188
|
-
|
189
|
-
decls.each do |decl|
|
190
|
-
decl = decl.decl
|
191
|
-
|
192
|
-
type_params2 = decl.type_params
|
193
|
-
# A hack to deal with the imcompatibility between rbs 1.8 and 2.0
|
194
|
-
type_params2 = type_params2.params if type_params2.respond_to?(:params)
|
195
|
-
type_params2 = type_params2.map {|param| [param.name, param.variance] }
|
196
|
-
raise "inconsistent type parameter declaration" if type_params && type_params != type_params2
|
197
|
-
type_params = type_params2
|
198
|
-
|
199
|
-
decl.members.each do |member|
|
200
|
-
case member
|
201
|
-
when RBS::AST::Members::MethodDefinition
|
202
|
-
name = member.name
|
203
|
-
|
204
|
-
if member.respond_to?(:overloads)
|
205
|
-
types = member.overloads.map {|overload| overload.method_type }
|
206
|
-
else
|
207
|
-
types = member.types
|
208
|
-
end
|
209
|
-
method_types = types.map do |method_type|
|
210
|
-
case method_type
|
211
|
-
when RBS::MethodType then method_type
|
212
|
-
when :super then raise NotImplementedError
|
213
|
-
end
|
214
|
-
end
|
215
|
-
|
216
|
-
method_def = conv_method_def(method_types, visibility)
|
217
|
-
rbs_source = [
|
218
|
-
(member.kind == :singleton ? "self." : "") + member.name.to_s,
|
219
|
-
types.map {|type| type.location.source },
|
220
|
-
[member.location.name, CodeRange.from_rbs(member.location)],
|
221
|
-
]
|
222
|
-
if member.instance?
|
223
|
-
methods[[false, name]] = method_def
|
224
|
-
rbs_sources[[false, name]] = rbs_source
|
225
|
-
end
|
226
|
-
if member.singleton?
|
227
|
-
methods[[true, name]] = method_def
|
228
|
-
rbs_sources[[true, name]] = rbs_source
|
229
|
-
end
|
230
|
-
when RBS::AST::Members::AttrReader
|
231
|
-
ty = conv_type(member.type)
|
232
|
-
attr_methods[[false, member.name]] = attr_method_def(:reader, member.name, ty, visibility)
|
233
|
-
rbs_sources[[false, member.name]] = attr_rbs_source(member)
|
234
|
-
when RBS::AST::Members::AttrWriter
|
235
|
-
ty = conv_type(member.type)
|
236
|
-
attr_methods[[false, member.name]] = attr_method_def(:writer, member.name, ty, visibility)
|
237
|
-
rbs_sources[[false, member.name]] = attr_rbs_source(member)
|
238
|
-
when RBS::AST::Members::AttrAccessor
|
239
|
-
ty = conv_type(member.type)
|
240
|
-
attr_methods[[false, member.name]] = attr_method_def(:accessor, member.name, ty, visibility)
|
241
|
-
rbs_sources[[false, member.name]] = attr_rbs_source(member)
|
242
|
-
when RBS::AST::Members::Alias
|
243
|
-
# XXX: an alias to attr methods?
|
244
|
-
if member.instance?
|
245
|
-
method_def = methods[[false, member.old_name]]
|
246
|
-
methods[[false, member.new_name]] = method_def if method_def
|
247
|
-
end
|
248
|
-
if member.singleton?
|
249
|
-
method_def = methods[[true, member.old_name]]
|
250
|
-
methods[[true, member.new_name]] = method_def if method_def
|
251
|
-
end
|
252
|
-
|
253
|
-
when RBS::AST::Members::Include
|
254
|
-
name = member.name
|
255
|
-
if name.kind == :class
|
256
|
-
# including a module
|
257
|
-
mod = conv_type_name(name)
|
258
|
-
type_args = member.args.map {|type| conv_type(type) }
|
259
|
-
modules[:include] << [mod, type_args]
|
260
|
-
else
|
261
|
-
# including an interface
|
262
|
-
mod = conv_type_name(name)
|
263
|
-
type_args = member.args.map {|type| conv_type(type) }
|
264
|
-
modules[:include] << [mod, type_args]
|
265
|
-
end
|
266
|
-
|
267
|
-
when RBS::AST::Members::Extend
|
268
|
-
name = member.name
|
269
|
-
if name.kind == :class
|
270
|
-
mod = conv_type_name(name)
|
271
|
-
type_args = member.args.map {|type| conv_type(type) }
|
272
|
-
modules[:extend] << [mod, type_args]
|
273
|
-
else
|
274
|
-
# extending a module with an interface is not supported yet
|
275
|
-
end
|
276
|
-
|
277
|
-
when RBS::AST::Members::Prepend
|
278
|
-
name = member.name
|
279
|
-
if name.kind == :class
|
280
|
-
mod = conv_type_name(name)
|
281
|
-
type_args = member.args.map {|type| conv_type(type) }
|
282
|
-
modules[:prepend] << [mod, type_args]
|
283
|
-
else
|
284
|
-
# extending a module with an interface is not supported yet
|
285
|
-
end
|
286
|
-
|
287
|
-
when RBS::AST::Members::InstanceVariable
|
288
|
-
ivars[member.name] = conv_type(member.type)
|
289
|
-
when RBS::AST::Members::ClassVariable
|
290
|
-
cvars[member.name] = conv_type(member.type)
|
291
|
-
|
292
|
-
when RBS::AST::Members::Public
|
293
|
-
visibility = true
|
294
|
-
when RBS::AST::Members::Private
|
295
|
-
visibility = false
|
296
|
-
|
297
|
-
# The following declarations are ignoreable because they are handled in other level
|
298
|
-
when RBS::AST::Declarations::Constant
|
299
|
-
when AliasDecl # type alias
|
300
|
-
when RBS::AST::Declarations::Class, RBS::AST::Declarations::Module
|
301
|
-
when RBS::AST::Declarations::Interface
|
302
|
-
when TypeAlias
|
303
|
-
|
304
|
-
else
|
305
|
-
warn "Importing #{ member.class.name } is not supported yet"
|
306
|
-
end
|
307
|
-
end
|
308
|
-
end
|
309
|
-
|
310
|
-
json[klass] = {
|
311
|
-
type_params: type_params,
|
312
|
-
superclass: superclass,
|
313
|
-
members: {
|
314
|
-
modules: modules,
|
315
|
-
methods: methods,
|
316
|
-
attr_methods: attr_methods,
|
317
|
-
ivars: ivars,
|
318
|
-
cvars: cvars,
|
319
|
-
rbs_sources: rbs_sources,
|
320
|
-
},
|
321
|
-
}
|
322
|
-
end
|
323
|
-
|
324
|
-
json
|
325
|
-
end
|
326
|
-
|
327
|
-
def each_class_decl
|
328
|
-
# topological sort
|
329
|
-
# * superclasses and modules appear earlier than their subclasses (Object is earlier than String)
|
330
|
-
# * namespace module appers earlier than its children (Process is earlier than Process::Status)
|
331
|
-
visited = {}
|
332
|
-
queue = @cur_env.class_decls.keys.map {|name| [:visit, name] }.reverse
|
333
|
-
until queue.empty?
|
334
|
-
event, name = queue.pop
|
335
|
-
case event
|
336
|
-
when :visit
|
337
|
-
if !visited[name]
|
338
|
-
visited[name] = true
|
339
|
-
queue << [:new, name]
|
340
|
-
@all_env.class_decls[name].decls.each do |decl|
|
341
|
-
decl = decl.decl
|
342
|
-
next if decl.is_a?(RBS::AST::Declarations::Module)
|
343
|
-
each_reference(decl) {|name| queue << [:visit, name] }
|
344
|
-
end
|
345
|
-
queue << [:visit, name.namespace.to_type_name] if !name.namespace.empty?
|
346
|
-
end
|
347
|
-
when :new
|
348
|
-
decls = @cur_env.class_decls[name]
|
349
|
-
yield name, decls.decls if decls
|
350
|
-
end
|
351
|
-
end
|
352
|
-
|
353
|
-
@cur_env.interface_decls.each do |name, decl|
|
354
|
-
yield name, [decl]
|
355
|
-
end
|
356
|
-
end
|
357
|
-
|
358
|
-
def each_reference(decl, &blk)
|
359
|
-
yield decl.name
|
360
|
-
if decl.super_class
|
361
|
-
name = decl.super_class.name
|
362
|
-
else
|
363
|
-
name = RBS::BuiltinNames::Object.name
|
364
|
-
end
|
365
|
-
return if decl.name == RBS::BuiltinNames::BasicObject.name
|
366
|
-
return if decl.name == name
|
367
|
-
decls = @all_env.class_decls[name]
|
368
|
-
if decls
|
369
|
-
decls.decls.each do |decl|
|
370
|
-
each_reference(decl.decl, &blk)
|
371
|
-
end
|
372
|
-
end
|
373
|
-
end
|
374
|
-
|
375
|
-
def get_super_class(name, decls)
|
376
|
-
return nil if name == RBS::BuiltinNames::BasicObject.name
|
377
|
-
|
378
|
-
decls.each do |decl|
|
379
|
-
decl = decl.decl
|
380
|
-
case decl
|
381
|
-
when RBS::AST::Declarations::Class
|
382
|
-
super_class = decl.super_class
|
383
|
-
return super_class.name, super_class.args if super_class
|
384
|
-
when RBS::AST::Declarations::Module, RBS::AST::Declarations::Interface
|
385
|
-
return nil
|
386
|
-
else
|
387
|
-
raise "unknown declaration: %p" % decl.class
|
388
|
-
end
|
389
|
-
end
|
390
|
-
|
391
|
-
return RBS::BuiltinNames::Object.name, []
|
392
|
-
end
|
393
|
-
|
394
|
-
def conv_method_def(rbs_method_types, visibility)
|
395
|
-
sig_rets = rbs_method_types.map do |method_type|
|
396
|
-
conv_func(method_type.type_params, method_type.type, method_type.block)
|
397
|
-
end
|
398
|
-
{
|
399
|
-
sig_rets: sig_rets,
|
400
|
-
visibility: visibility,
|
401
|
-
}
|
402
|
-
end
|
403
|
-
|
404
|
-
def conv_func(type_params, func, block)
|
405
|
-
blk = block ? conv_block(block) : nil
|
406
|
-
|
407
|
-
lead_tys = func.required_positionals.map {|type| conv_type(type.type) }
|
408
|
-
opt_tys = func.optional_positionals.map {|type| conv_type(type.type) }
|
409
|
-
rest_ty = func.rest_positionals
|
410
|
-
rest_ty = conv_type(rest_ty.type) if rest_ty
|
411
|
-
opt_kw_tys = func.optional_keywords.to_h {|key, type| [key, conv_type(type.type)] }
|
412
|
-
req_kw_tys = func.required_keywords.to_h {|key, type| [key, conv_type(type.type)] }
|
413
|
-
rest_kw_ty = func.rest_keywords
|
414
|
-
rest_kw_ty = conv_type(rest_kw_ty.type) if rest_kw_ty
|
415
|
-
|
416
|
-
ret_ty = conv_type(func.return_type)
|
417
|
-
|
418
|
-
{
|
419
|
-
type_params: type_params,
|
420
|
-
lead_tys: lead_tys,
|
421
|
-
opt_tys: opt_tys,
|
422
|
-
rest_ty: rest_ty,
|
423
|
-
req_kw_tys: req_kw_tys,
|
424
|
-
opt_kw_tys: opt_kw_tys,
|
425
|
-
rest_kw_ty: rest_kw_ty,
|
426
|
-
blk: blk,
|
427
|
-
ret_ty: ret_ty,
|
428
|
-
}
|
429
|
-
end
|
430
|
-
|
431
|
-
def attr_method_def(kind, name, ty, visibility)
|
432
|
-
{
|
433
|
-
kind: kind,
|
434
|
-
ivar: name,
|
435
|
-
ty: ty,
|
436
|
-
visibility: visibility,
|
437
|
-
}
|
438
|
-
end
|
439
|
-
|
440
|
-
def attr_rbs_source(member)
|
441
|
-
[
|
442
|
-
member.name.to_s,
|
443
|
-
member.type.location.source,
|
444
|
-
[member.location.name, CodeRange.from_rbs(member.location)],
|
445
|
-
]
|
446
|
-
end
|
447
|
-
|
448
|
-
def conv_block(rbs_block)
|
449
|
-
blk = rbs_block.type
|
450
|
-
|
451
|
-
lead_tys = blk.required_positionals.map {|type| conv_type(type.type) }
|
452
|
-
opt_tys = blk.optional_positionals.map {|type| conv_type(type.type) }
|
453
|
-
rest_ty = blk.rest_positionals
|
454
|
-
rest_ty = conv_type(rest_ty.type) if rest_ty
|
455
|
-
opt_kw_tys = blk.optional_keywords.to_h {|key, type| [key, conv_type(type.type)] }
|
456
|
-
req_kw_tys = blk.required_keywords.to_h {|key, type| [key, conv_type(type.type)] }
|
457
|
-
rest_kw_ty = blk.rest_keywords
|
458
|
-
rest_kw_ty = conv_type(rest_kw_ty.type) if rest_kw_ty
|
459
|
-
|
460
|
-
ret_ty = conv_type(blk.return_type)
|
461
|
-
|
462
|
-
{
|
463
|
-
required_block: rbs_block.required,
|
464
|
-
lead_tys: lead_tys,
|
465
|
-
opt_tys: opt_tys,
|
466
|
-
rest_ty: rest_ty,
|
467
|
-
req_kw_tys: req_kw_tys,
|
468
|
-
opt_kw_tys: opt_kw_tys,
|
469
|
-
rest_kw_ty: rest_kw_ty,
|
470
|
-
blk: blk,
|
471
|
-
ret_ty: ret_ty,
|
472
|
-
}
|
473
|
-
end
|
474
|
-
|
475
|
-
def conv_type(ty)
|
476
|
-
case ty
|
477
|
-
when RBS::Types::ClassSingleton
|
478
|
-
[:class, conv_type_name(ty.name)]
|
479
|
-
when RBS::Types::ClassInstance
|
480
|
-
klass = conv_type_name(ty.name)
|
481
|
-
case klass
|
482
|
-
when [:Array]
|
483
|
-
raise if ty.args.size != 1
|
484
|
-
[:array, [:Array], [], conv_type(ty.args.first)]
|
485
|
-
when [:Hash]
|
486
|
-
raise if ty.args.size != 2
|
487
|
-
key, val = ty.args
|
488
|
-
[:hash, [:Hash], [conv_type(key), conv_type(val)]]
|
489
|
-
when [:Enumerator]
|
490
|
-
raise if ty.args.size != 2
|
491
|
-
[:array, [:Enumerator], [], conv_type(ty.args.first)]
|
492
|
-
else
|
493
|
-
if ty.args.empty?
|
494
|
-
[:instance, klass]
|
495
|
-
else
|
496
|
-
[:cell, [:instance, klass], ty.args.map {|ty| conv_type(ty) }]
|
497
|
-
end
|
498
|
-
end
|
499
|
-
when RBS::Types::Bases::Bool then [:bool]
|
500
|
-
when RBS::Types::Bases::Any then [:any]
|
501
|
-
when RBS::Types::Bases::Top then [:any]
|
502
|
-
when RBS::Types::Bases::Void then [:void]
|
503
|
-
when RBS::Types::Bases::Self then [:self]
|
504
|
-
when RBS::Types::Bases::Nil then [:nil]
|
505
|
-
when RBS::Types::Bases::Bottom then [:union, []]
|
506
|
-
when RBS::Types::Variable then [:var, ty.name]
|
507
|
-
when RBS::Types::Tuple
|
508
|
-
tys = ty.types.map {|ty2| conv_type(ty2) }
|
509
|
-
[:array, [:Array], tys, [:union, []]]
|
510
|
-
when RBS::Types::Literal
|
511
|
-
case ty.literal
|
512
|
-
when Integer then [:int]
|
513
|
-
when String then [:str]
|
514
|
-
when true then [:true]
|
515
|
-
when false then [:false]
|
516
|
-
when Symbol then [:sym, ty.literal]
|
517
|
-
else
|
518
|
-
p ty.literal
|
519
|
-
raise NotImplementedError
|
520
|
-
end
|
521
|
-
when RBS::Types::Alias
|
522
|
-
if @alias_resolution_stack[ty.name]
|
523
|
-
[:any]
|
524
|
-
else
|
525
|
-
begin
|
526
|
-
@alias_resolution_stack[ty.name] = true
|
527
|
-
alias_decl = (@all_env.respond_to?(:alias_decls) ? @all_env.alias_decls : @all_env.type_alias_decls)[ty.name]
|
528
|
-
alias_decl ? conv_type(alias_decl.decl.type) : [:any]
|
529
|
-
ensure
|
530
|
-
@alias_resolution_stack.delete(ty.name)
|
531
|
-
end
|
532
|
-
end
|
533
|
-
when RBS::Types::Union
|
534
|
-
[:union, ty.types.map {|ty2| conv_type(ty2) }.compact]
|
535
|
-
when RBS::Types::Intersection
|
536
|
-
[:intersection, ty.types.map {|ty2| conv_type(ty2) }.compact]
|
537
|
-
when RBS::Types::Optional
|
538
|
-
[:optional, conv_type(ty.type)]
|
539
|
-
when RBS::Types::Interface
|
540
|
-
# XXX: Currently, only a few builtin interfaces are supported
|
541
|
-
case ty.to_s
|
542
|
-
when "::_ToS" then [:str]
|
543
|
-
when "::_ToStr" then [:str]
|
544
|
-
when "::_ToInt" then [:int]
|
545
|
-
when "::_ToAry[U]" then [:array, [:Array], [], [:var, :U]]
|
546
|
-
else
|
547
|
-
[:instance, conv_type_name(ty.name)]
|
548
|
-
end
|
549
|
-
when RBS::Types::Bases::Instance then [:any] # XXX: not implemented yet
|
550
|
-
when RBS::Types::Bases::Class then [:any] # XXX: not implemented yet
|
551
|
-
when RBS::Types::Record
|
552
|
-
[:hash_record, [:Hash], ty.fields.map {|key, ty| [key, conv_type(ty)] }]
|
553
|
-
when RBS::Types::Proc
|
554
|
-
[:proc, conv_func(nil, ty.type, nil)]
|
555
|
-
else
|
556
|
-
warn "unknown RBS type: %p" % ty.class
|
557
|
-
[:any]
|
558
|
-
end
|
559
|
-
end
|
560
|
-
|
561
|
-
def conv_type_name(name)
|
562
|
-
name.namespace.path + [name.name]
|
563
|
-
end
|
564
|
-
end
|
565
|
-
|
566
|
-
class Import
|
567
|
-
def self.import_builtin(scratch)
|
568
|
-
Import.new(scratch, scratch.rbs_reader.load_builtin).import
|
569
|
-
end
|
570
|
-
|
571
|
-
def self.import_library(scratch, feature)
|
572
|
-
begin
|
573
|
-
json = scratch.rbs_reader.load_library(feature)
|
574
|
-
rescue RBS::EnvironmentLoader::UnknownLibraryError
|
575
|
-
return nil
|
576
|
-
rescue RBS::DuplicatedDeclarationError, RBSReader::RBSCollectionDefined
|
577
|
-
return true
|
578
|
-
end
|
579
|
-
# need cache?
|
580
|
-
Import.new(scratch, json).import
|
581
|
-
end
|
582
|
-
|
583
|
-
def self.import_rbs_files(scratch, rbs_paths)
|
584
|
-
rbs_paths = rbs_paths.map {|rbs_path| Pathname(rbs_path) }
|
585
|
-
Import.new(scratch, scratch.rbs_reader.load_paths(rbs_paths)).import(true)
|
586
|
-
end
|
587
|
-
|
588
|
-
def self.import_rbs_code(scratch, rbs_name, rbs_code)
|
589
|
-
Import.new(scratch, scratch.rbs_reader.load_rbs_string(rbs_name, rbs_code)).import(true)
|
590
|
-
end
|
591
|
-
|
592
|
-
def initialize(scratch, json)
|
593
|
-
@scratch = scratch
|
594
|
-
@json = json
|
595
|
-
end
|
596
|
-
|
597
|
-
def import(explicit = false)
|
598
|
-
classes = @json[:classes].map do |classpath, cdef|
|
599
|
-
type_params = cdef[:type_params]
|
600
|
-
superclass, superclass_type_args = cdef[:superclass]
|
601
|
-
members = cdef[:members]
|
602
|
-
|
603
|
-
name = classpath.last
|
604
|
-
superclass = path_to_klass(superclass) if superclass
|
605
|
-
base_klass = path_to_klass(classpath[0..-2])
|
606
|
-
|
607
|
-
klass, = @scratch.get_constant(base_klass, name)
|
608
|
-
if klass.is_a?(Type::Any)
|
609
|
-
klass = @scratch.new_class(base_klass, name, type_params, superclass, nil)
|
610
|
-
|
611
|
-
# There builtin classes are needed to interpret RBS declarations
|
612
|
-
case classpath
|
613
|
-
when [:NilClass] then Type::Builtin[:nil] = klass
|
614
|
-
when [:TrueClass] then Type::Builtin[:true] = klass
|
615
|
-
when [:FalseClass] then Type::Builtin[:false] = klass
|
616
|
-
when [:Integer] then Type::Builtin[:int] = klass
|
617
|
-
when [:String] then Type::Builtin[:str] = klass
|
618
|
-
when [:Symbol] then Type::Builtin[:sym] = klass
|
619
|
-
when [:Array] then Type::Builtin[:ary] = klass
|
620
|
-
when [:Hash] then Type::Builtin[:hash] = klass
|
621
|
-
when [:Proc] then Type::Builtin[:proc] = klass
|
622
|
-
end
|
623
|
-
end
|
624
|
-
|
625
|
-
[klass, superclass_type_args, members]
|
626
|
-
end
|
627
|
-
|
628
|
-
classes.each do |klass, superclass_type_args, members|
|
629
|
-
@scratch.add_superclass_type_args!(klass, superclass_type_args&.map {|ty| conv_type(ty) })
|
630
|
-
modules = members[:modules]
|
631
|
-
methods = members[:methods]
|
632
|
-
attr_methods = members[:attr_methods]
|
633
|
-
ivars = members[:ivars]
|
634
|
-
cvars = members[:cvars]
|
635
|
-
rbs_sources = members[:rbs_sources]
|
636
|
-
|
637
|
-
modules.each do |kind, mods|
|
638
|
-
mods.each do |mod, type_args|
|
639
|
-
type_args = type_args&.map {|ty| conv_type(ty) }
|
640
|
-
case kind
|
641
|
-
when :include
|
642
|
-
@scratch.mix_module(:after, klass, path_to_klass(mod), type_args, false, nil)
|
643
|
-
when :extend
|
644
|
-
@scratch.mix_module(:after, klass, path_to_klass(mod), type_args, true, nil)
|
645
|
-
when :prepend
|
646
|
-
@scratch.mix_module(:before, klass, path_to_klass(mod), type_args, false, nil)
|
647
|
-
end
|
648
|
-
end
|
649
|
-
end
|
650
|
-
|
651
|
-
methods.each do |(singleton, method_name), mdef|
|
652
|
-
rbs_source = explicit ? rbs_sources[[singleton, method_name]] : nil
|
653
|
-
mdef = conv_method_def(method_name, mdef, rbs_source)
|
654
|
-
@scratch.add_method(klass, method_name, singleton, mdef)
|
655
|
-
end
|
656
|
-
|
657
|
-
attr_methods.each do |(singleton, method_name), mdef|
|
658
|
-
rbs_source = explicit ? rbs_sources[[singleton, method_name]] : nil
|
659
|
-
ty = conv_type(mdef[:ty]).remove_type_vars
|
660
|
-
mdefs = conv_attr_defs(mdef, rbs_source)
|
661
|
-
mdefs.each do |mdef|
|
662
|
-
@scratch.add_typed_attr_method(klass, mdef)
|
663
|
-
end
|
664
|
-
@scratch.add_ivar_write!(Type::Instance.new(klass), :"@#{ mdef[:ivar] }", ty, nil)
|
665
|
-
end
|
666
|
-
|
667
|
-
ivars.each do |ivar_name, ty|
|
668
|
-
ty = conv_type(ty).remove_type_vars
|
669
|
-
@scratch.add_ivar_write!(Type::Instance.new(klass), ivar_name, ty, nil)
|
670
|
-
end
|
671
|
-
|
672
|
-
cvars.each do |ivar_name, ty|
|
673
|
-
ty = conv_type(ty).remove_type_vars
|
674
|
-
@scratch.add_cvar_write!(klass, ivar_name, ty, nil)
|
675
|
-
end
|
676
|
-
end
|
677
|
-
|
678
|
-
@json[:constants].each do |classpath, value|
|
679
|
-
base_klass = path_to_klass(classpath[0..-2])
|
680
|
-
value = conv_type(value).remove_type_vars
|
681
|
-
@scratch.add_constant(base_klass, classpath[-1], value, nil)
|
682
|
-
end
|
683
|
-
|
684
|
-
@json[:globals].each do |name, ty|
|
685
|
-
ty = conv_type(ty).remove_type_vars
|
686
|
-
@scratch.add_gvar_write!(name, ty, nil)
|
687
|
-
end
|
688
|
-
|
689
|
-
true
|
690
|
-
end
|
691
|
-
|
692
|
-
def conv_method_def(method_name, mdef, rbs_source)
|
693
|
-
sig_rets = mdef[:sig_rets].flat_map do |sig_ret|
|
694
|
-
conv_func(sig_ret)
|
695
|
-
end
|
696
|
-
|
697
|
-
TypedMethodDef.new(sig_rets, rbs_source, mdef[:visibility])
|
698
|
-
end
|
699
|
-
|
700
|
-
def conv_attr_defs(mdef, rbs_source)
|
701
|
-
ivar = :"@#{ mdef[:ivar] }"
|
702
|
-
kind = mdef[:kind]
|
703
|
-
pub_meth = mdef[:visibility]
|
704
|
-
|
705
|
-
defs = []
|
706
|
-
if kind == :reader || kind == :accessor
|
707
|
-
defs << TypedAttrMethodDef.new(ivar, :reader, pub_meth, rbs_source)
|
708
|
-
end
|
709
|
-
if kind == :writer || kind == :accessor
|
710
|
-
defs << TypedAttrMethodDef.new(ivar, :writer, pub_meth, rbs_source)
|
711
|
-
end
|
712
|
-
raise if defs.empty?
|
713
|
-
defs
|
714
|
-
end
|
715
|
-
|
716
|
-
def conv_func(sig_ret)
|
717
|
-
#type_params = sig_ret[:type_params] # XXX
|
718
|
-
lead_tys = sig_ret[:lead_tys]
|
719
|
-
opt_tys = sig_ret[:opt_tys]
|
720
|
-
rest_ty = sig_ret[:rest_ty]
|
721
|
-
req_kw_tys = sig_ret[:req_kw_tys]
|
722
|
-
opt_kw_tys = sig_ret[:opt_kw_tys]
|
723
|
-
rest_kw_ty = sig_ret[:rest_kw_ty]
|
724
|
-
blk = sig_ret[:blk]
|
725
|
-
ret_ty = sig_ret[:ret_ty]
|
726
|
-
|
727
|
-
lead_tys = lead_tys.map {|ty| conv_type(ty) }
|
728
|
-
opt_tys = opt_tys.map {|ty| conv_type(ty) }
|
729
|
-
rest_ty = conv_type(rest_ty) if rest_ty
|
730
|
-
kw_tys = []
|
731
|
-
req_kw_tys.each {|key, ty| kw_tys << [true, key, conv_type(ty)] }
|
732
|
-
opt_kw_tys.each {|key, ty| kw_tys << [false, key, conv_type(ty)] }
|
733
|
-
if rest_kw_ty
|
734
|
-
ty = conv_type(rest_kw_ty)
|
735
|
-
kw_rest_ty = Type.gen_hash do |h|
|
736
|
-
k_ty = Type::Instance.new(Type::Builtin[:sym])
|
737
|
-
h[k_ty] = ty
|
738
|
-
end
|
739
|
-
end
|
740
|
-
|
741
|
-
blks = conv_block(blk)
|
742
|
-
|
743
|
-
ret_ty = conv_type(ret_ty)
|
744
|
-
|
745
|
-
blks.map do |blk|
|
746
|
-
[MethodSignature.new(lead_tys, opt_tys, rest_ty, [], kw_tys, kw_rest_ty, blk), ret_ty]
|
747
|
-
end
|
748
|
-
end
|
749
|
-
|
750
|
-
def conv_block(blk)
|
751
|
-
return [Type.nil] unless blk
|
752
|
-
|
753
|
-
required_block = blk[:required_block]
|
754
|
-
lead_tys = blk[:lead_tys]
|
755
|
-
opt_tys = blk[:opt_tys]
|
756
|
-
rest_ty = blk[:rest_ty]
|
757
|
-
req_kw_tys = blk[:req_kw_tys]
|
758
|
-
opt_kw_tys = blk[:opt_kw_tys]
|
759
|
-
rest_kw_ty = blk[:rest_kw_ty]
|
760
|
-
ret_ty = blk[:ret_ty]
|
761
|
-
|
762
|
-
lead_tys = lead_tys.map {|ty| conv_type(ty) }
|
763
|
-
opt_tys = opt_tys.map {|ty| conv_type(ty) }
|
764
|
-
rest_ty = conv_type(rest_ty) if rest_ty
|
765
|
-
kw_tys = []
|
766
|
-
req_kw_tys.each {|key, ty| kw_tys << [true, key, conv_type(ty)] }
|
767
|
-
opt_kw_tys.each {|key, ty| kw_tys << [false, key, conv_type(ty)] }
|
768
|
-
if rest_kw_ty
|
769
|
-
ty = conv_type(rest_kw_ty)
|
770
|
-
kw_rest_ty = Type.gen_hash do |h|
|
771
|
-
k_ty = Type::Instance.new(Type::Builtin[:sym])
|
772
|
-
h[k_ty] = ty
|
773
|
-
end
|
774
|
-
end
|
775
|
-
|
776
|
-
msig = MethodSignature.new(lead_tys, opt_tys, rest_ty, [], kw_tys, kw_rest_ty, Type.nil)
|
777
|
-
|
778
|
-
ret_ty = conv_type(ret_ty)
|
779
|
-
|
780
|
-
ret = [Type::Proc.new(TypedBlock.new(msig, ret_ty), Type::Builtin[:proc])]
|
781
|
-
ret << Type.nil unless required_block
|
782
|
-
ret
|
783
|
-
end
|
784
|
-
|
785
|
-
def conv_type(ty)
|
786
|
-
case ty.first
|
787
|
-
when :class then path_to_klass(ty[1])
|
788
|
-
when :instance then Type::Instance.new(path_to_klass(ty[1]))
|
789
|
-
when :cell
|
790
|
-
Type::Cell.new(Type::Cell::Elements.new(ty[2].map {|ty| conv_type(ty) }), conv_type(ty[1]))
|
791
|
-
when :any then Type.any
|
792
|
-
when :void then Type::Void.new
|
793
|
-
when :nil then Type.nil
|
794
|
-
when :optional then Type.optional(conv_type(ty[1]))
|
795
|
-
when :bool then Type.bool
|
796
|
-
when :self then Type::Var.new(:self)
|
797
|
-
when :int then Type::Instance.new(Type::Builtin[:int])
|
798
|
-
when :str then Type::Instance.new(Type::Builtin[:str])
|
799
|
-
when :sym then Type::Symbol.new(ty.last, Type::Instance.new(Type::Builtin[:sym]))
|
800
|
-
when :true then Type::Instance.new(Type::Builtin[:true])
|
801
|
-
when :false then Type::Instance.new(Type::Builtin[:false])
|
802
|
-
when :array
|
803
|
-
_, path, lead_tys, rest_ty = ty
|
804
|
-
lead_tys = lead_tys.map {|ty| conv_type(ty) }
|
805
|
-
rest_ty = conv_type(rest_ty)
|
806
|
-
base_type = Type::Instance.new(path_to_klass(path))
|
807
|
-
Type::Array.new(Type::Array::Elements.new(lead_tys, rest_ty), base_type)
|
808
|
-
when :hash
|
809
|
-
_, path, (k, v) = ty
|
810
|
-
Type.gen_hash(Type::Instance.new(path_to_klass(path))) do |h|
|
811
|
-
k_ty = conv_type(k)
|
812
|
-
v_ty = conv_type(v)
|
813
|
-
h[k_ty] = v_ty
|
814
|
-
end
|
815
|
-
when :hash_record
|
816
|
-
_, path, key_tys = ty
|
817
|
-
Type.gen_hash(Type::Instance.new(path_to_klass(path))) do |h|
|
818
|
-
key_tys.each do |key, ty|
|
819
|
-
k_ty = Type::Symbol.new(key, Type::Instance.new(Type::Builtin[:sym]))
|
820
|
-
v_ty = conv_type(ty)
|
821
|
-
h[k_ty] = v_ty
|
822
|
-
end
|
823
|
-
end
|
824
|
-
when :union
|
825
|
-
tys = ty[1]
|
826
|
-
Type::Union.create(Utils::Set[*tys.map {|ty2| conv_type(ty2) }], nil) # XXX: Array and Hash support
|
827
|
-
when :intersection
|
828
|
-
tys = ty[1]
|
829
|
-
conv_type(tys.first) # XXX: This is wrong! We need to support intersection type
|
830
|
-
when :var
|
831
|
-
Type::Var.new(ty[1])
|
832
|
-
when :proc
|
833
|
-
msig, ret_ty = conv_func(ty[1]).first # Currently, RBS Proc does not accept a block, so the size should be always one
|
834
|
-
Type::Proc.new(TypedBlock.new(msig, ret_ty), Type::Instance.new(Type::Builtin[:proc]))
|
835
|
-
else
|
836
|
-
pp ty
|
837
|
-
raise NotImplementedError
|
838
|
-
end
|
839
|
-
end
|
840
|
-
|
841
|
-
def path_to_klass(path)
|
842
|
-
klass = Type::Builtin[:obj]
|
843
|
-
path.each do |name|
|
844
|
-
klass, = @scratch.get_constant(klass, name)
|
845
|
-
if klass == Type.any
|
846
|
-
raise TypeProfError.new("A constant `#{ path.join("::") }' is used but not defined in RBS")
|
847
|
-
end
|
848
|
-
end
|
849
|
-
klass
|
850
|
-
end
|
851
|
-
end
|
852
|
-
end
|