typeprof 0.21.11 → 0.30.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/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 +178 -0
- data/lib/typeprof/cli.rb +3 -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 +259 -0
- data/lib/typeprof/core/ast/const.rb +126 -0
- data/lib/typeprof/core/ast/control.rb +433 -0
- data/lib/typeprof/core/ast/meta.rb +150 -0
- data/lib/typeprof/core/ast/method.rb +339 -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 +366 -0
- data/lib/typeprof/core/graph/box.rb +998 -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 +225 -0
- data/lib/typeprof/core/service.rb +514 -0
- data/lib/typeprof/core/type.rb +352 -0
- data/lib/typeprof/core/util.rb +81 -0
- data/lib/typeprof/core.rb +31 -0
- data/lib/typeprof/diagnostic.rb +35 -0
- data/lib/typeprof/lsp/messages.rb +415 -0
- data/lib/typeprof/lsp/server.rb +203 -0
- data/lib/typeprof/lsp/text.rb +69 -0
- data/lib/typeprof/lsp/util.rb +51 -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 +47 -33
- 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
|