typeprof 0.1.4 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +2 -2
- data/README.md +1 -1
- data/doc/doc.ja.md +5 -0
- data/doc/doc.md +9 -5
- data/lib/typeprof/analyzer.rb +97 -69
- data/lib/typeprof/builtin.rb +96 -92
- data/lib/typeprof/cli.rb +42 -4
- data/lib/typeprof/export.rb +36 -20
- data/lib/typeprof/import.rb +406 -365
- data/lib/typeprof/iseq.rb +1 -1
- data/lib/typeprof/method.rb +34 -33
- data/lib/typeprof/type.rb +1 -4
- data/run.sh +1 -1
- data/smoke/block13.rb +9 -0
- data/smoke/block13.rbs +3 -0
- data/smoke/class.rb +2 -0
- data/smoke/constant1.rb +3 -0
- data/smoke/demo5.rb +3 -0
- data/smoke/gvar.rb +1 -1
- data/smoke/gvar2.rb +17 -0
- data/smoke/gvar2.rbs +1 -0
- data/smoke/inheritance2.rb +6 -0
- data/smoke/ivar3.rb +16 -0
- data/smoke/ivar3.rbs +3 -0
- data/smoke/manual-rbs2.rb +1 -1
- data/smoke/manual-rbs3.rb +12 -0
- data/smoke/manual-rbs3.rbs +3 -0
- data/smoke/module4.rb +3 -0
- data/smoke/multiple-superclass.rb +8 -0
- data/smoke/rbs-alias.rb +9 -0
- data/smoke/rbs-alias.rbs +4 -0
- data/smoke/rbs-attr.rb +26 -0
- data/smoke/rbs-attr.rbs +5 -0
- data/smoke/rbs-vars.rb +39 -0
- data/smoke/rbs-vars.rbs +7 -0
- data/smoke/struct.rb +3 -0
- data/smoke/super1.rb +18 -0
- data/smoke/union-recv.rb +6 -0
- data/tools/setup-insns-def.rb +1 -1
- data/tools/stackprof-wrapper.rb +1 -1
- data/typeprof.gemspec +10 -4
- metadata +26 -7
data/lib/typeprof/import.rb
CHANGED
@@ -3,208 +3,125 @@ require "rbs"
|
|
3
3
|
module TypeProf
|
4
4
|
class RBSReader
|
5
5
|
def initialize
|
6
|
-
@env, @
|
6
|
+
@env, @builtin_env_json = RBSReader.get_builtin_env
|
7
7
|
end
|
8
8
|
|
9
|
-
@builtin_env = nil
|
10
|
-
def self.
|
11
|
-
|
9
|
+
@builtin_env = @builtin_env_json = nil
|
10
|
+
def self.get_builtin_env
|
11
|
+
unless @builtin_env
|
12
|
+
@builtin_env = RBS::Environment.new
|
13
|
+
@builtin_env_json = load_rbs(@builtin_env, builtin: true)
|
14
|
+
end
|
12
15
|
|
13
|
-
|
14
|
-
env = RBS::Environment.new
|
15
|
-
decls = loader.load(env: env)
|
16
|
-
@builtin_env = env
|
17
|
-
@builtin_env_dump = RBS2JSON.new(env, decls).dump
|
18
|
-
return env.dup, @builtin_env_dump
|
16
|
+
return @builtin_env.dup, @builtin_env_json
|
19
17
|
end
|
20
18
|
|
21
19
|
def load_builtin
|
22
|
-
@
|
20
|
+
@builtin_env_json
|
23
21
|
end
|
24
22
|
|
25
23
|
def load_library(lib)
|
26
|
-
|
27
|
-
loader.no_builtin!
|
28
|
-
loader.add(library: lib)
|
29
|
-
new_decls = loader.load(env: @env)
|
30
|
-
RBS2JSON.new(@env, new_decls).dump
|
24
|
+
RBSReader.load_rbs(@env, library: lib)
|
31
25
|
end
|
32
26
|
|
33
27
|
def load_path(path)
|
34
|
-
|
35
|
-
loader.no_builtin!
|
36
|
-
loader.add(path: path)
|
37
|
-
new_decls = loader.load(env: @env)
|
38
|
-
RBS2JSON.new(@env, new_decls).dump
|
28
|
+
RBSReader.load_rbs(@env, path: path)
|
39
29
|
end
|
40
|
-
end
|
41
30
|
|
42
|
-
|
43
|
-
|
44
|
-
|
31
|
+
def self.load_rbs(env, builtin: false, **opt)
|
32
|
+
loader = RBS::EnvironmentLoader.new
|
33
|
+
unless builtin
|
34
|
+
loader.no_builtin!
|
35
|
+
loader.add(**opt)
|
36
|
+
end
|
37
|
+
new_decls = loader.load(env: env)
|
45
38
|
|
46
|
-
|
47
|
-
@current_env = RBS::Environment.new()
|
39
|
+
all_env = env.resolve_type_names
|
48
40
|
|
41
|
+
resolver = RBS::TypeNameResolver.from_env(all_env)
|
42
|
+
cur_env = RBS::Environment.new
|
49
43
|
new_decls.each do |decl,|
|
50
|
-
|
44
|
+
cur_env << env.resolve_declaration(resolver, decl, outer: [], prefix: RBS::Namespace.root)
|
51
45
|
end
|
46
|
+
|
47
|
+
RBS2JSON.new(all_env, cur_env).dump_json
|
52
48
|
end
|
49
|
+
end
|
53
50
|
|
54
|
-
|
55
|
-
|
51
|
+
class RBS2JSON
|
52
|
+
def initialize(all_env, cur_env)
|
53
|
+
@all_env, @cur_env = all_env, cur_env
|
54
|
+
end
|
55
|
+
|
56
|
+
def dump_json
|
57
|
+
{
|
58
|
+
classes: conv_classes,
|
59
|
+
constants: conv_constants,
|
60
|
+
globals: conv_globals,
|
61
|
+
}
|
56
62
|
end
|
57
63
|
|
58
64
|
# constant_name = [Symbol]
|
59
65
|
#
|
60
66
|
# { constant_name => type }
|
61
|
-
def
|
67
|
+
def conv_constants
|
62
68
|
constants = {}
|
63
|
-
@
|
64
|
-
|
65
|
-
klass =
|
66
|
-
constants[klass] = convert_type(decl.decl.type)
|
69
|
+
@cur_env.constant_decls.each do |name, decl|
|
70
|
+
klass = conv_type_name(name)
|
71
|
+
constants[klass] = conv_type(decl.decl.type)
|
67
72
|
end
|
68
73
|
constants
|
69
74
|
end
|
70
75
|
|
71
|
-
#
|
72
|
-
# method_name = [singleton: true|false, Symbol}
|
73
|
-
# method_def = [...]
|
76
|
+
# gvar_name = Symbol (:$gvar)
|
74
77
|
#
|
75
|
-
# {
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
def import_rbs_classes
|
82
|
-
class2super = {}
|
83
|
-
# XXX: @env.each_global {|a| p a }
|
84
|
-
@current_env.class_decls.each do |name, decl|
|
85
|
-
decl.decls.each do |decl|
|
86
|
-
decl = decl.decl
|
87
|
-
if decl.is_a?(RBS::AST::Declarations::Class) && name != RBS::Factory.new.type_name("::Object")
|
88
|
-
#next unless decl.super_class
|
89
|
-
class2super[name] ||= decl.super_class&.name || RBS::BuiltinNames::Object.name
|
90
|
-
else
|
91
|
-
class2super[name] ||= nil
|
92
|
-
end
|
93
|
-
end
|
78
|
+
# { gvar_name => type }
|
79
|
+
def conv_globals
|
80
|
+
gvars = {}
|
81
|
+
@cur_env.global_decls.each do |name, decl|
|
82
|
+
decl = decl.decl
|
83
|
+
gvars[name] = conv_type(decl.type)
|
94
84
|
end
|
85
|
+
gvars
|
86
|
+
end
|
95
87
|
|
96
|
-
|
88
|
+
def conv_classes
|
89
|
+
json = {}
|
97
90
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
#p queue.map {|ev, name| [ev, name.to_s] }
|
103
|
-
event, name = queue.pop
|
104
|
-
case event
|
105
|
-
when :visit
|
106
|
-
if !visited[name]
|
107
|
-
visited[name] = true
|
108
|
-
queue << [:new, name]
|
109
|
-
decl = @all_env.class_decls[name]
|
110
|
-
decl.decls.each do |decl|
|
111
|
-
decl = decl.decl
|
112
|
-
next if decl.is_a?(RBS::AST::Declarations::Module)
|
113
|
-
until RBS::BuiltinNames::Object.name == decl.name
|
114
|
-
super_class = decl.super_class
|
115
|
-
break unless super_class
|
116
|
-
decls = @all_env.class_decls[super_class.name].decls
|
117
|
-
raise if decls.size >= 2 # no need to check
|
118
|
-
decl = decls.first.decl
|
119
|
-
queue << [:visit, decl.name]
|
120
|
-
end
|
121
|
-
end
|
122
|
-
if !name.namespace.empty?
|
123
|
-
queue << [:visit, name.namespace.to_type_name]
|
124
|
-
end
|
125
|
-
end
|
126
|
-
when :new
|
127
|
-
super_class_name = class2super[name]
|
128
|
-
klass = name.namespace.path + [name.name]
|
129
|
-
if super_class_name
|
130
|
-
superclass = super_class_name.namespace.path + [super_class_name.name]
|
131
|
-
else
|
132
|
-
superclass = nil
|
133
|
-
end
|
134
|
-
classes << [name, klass, superclass]
|
135
|
-
end
|
136
|
-
end
|
137
|
-
|
138
|
-
result = {}
|
139
|
-
classes.each do |type_name, klass, superclass|
|
140
|
-
next unless @current_env.class_decls[type_name]
|
91
|
+
each_class_decl do |name, decls|
|
92
|
+
super_class_name = get_super_class_name(name)
|
93
|
+
klass = conv_type_name(name)
|
94
|
+
superclass = super_class_name ? conv_type_name(super_class_name) : nil
|
141
95
|
|
96
|
+
type_params = nil
|
142
97
|
included_modules = []
|
143
98
|
methods = {}
|
99
|
+
ivars = {}
|
100
|
+
cvars = {}
|
144
101
|
rbs_sources = {}
|
145
|
-
type_params = nil
|
146
102
|
|
147
|
-
|
103
|
+
decls.each do |decl|
|
148
104
|
decl = decl.decl
|
149
|
-
|
105
|
+
|
106
|
+
raise NotImplementedError if decl.is_a?(RBS::AST::Declarations::Interface) # XXX
|
107
|
+
|
150
108
|
type_params2 = decl.type_params.params.map {|param| [param.name, param.variance] }
|
151
|
-
if type_params
|
152
|
-
|
153
|
-
else
|
154
|
-
type_params = type_params2
|
155
|
-
end
|
109
|
+
raise "inconsistent type parameter declaration" if type_params && type_params != type_params2
|
110
|
+
type_params = type_params2
|
156
111
|
|
157
112
|
decl.members.each do |member|
|
158
113
|
case member
|
159
114
|
when RBS::AST::Members::MethodDefinition
|
160
115
|
name = member.name
|
161
116
|
|
162
|
-
# ad-hoc filter
|
163
|
-
if member.instance?
|
164
|
-
case type_name.name
|
165
|
-
when :Object
|
166
|
-
next if name == :class
|
167
|
-
next if name == :send
|
168
|
-
next if name == :is_a?
|
169
|
-
next if name == :respond_to?
|
170
|
-
when :Array
|
171
|
-
next if name == :[]
|
172
|
-
next if name == :[]=
|
173
|
-
next if name == :pop
|
174
|
-
when :Enumerable
|
175
|
-
when :Enumerator
|
176
|
-
when :Hash
|
177
|
-
next if name == :[]
|
178
|
-
next if name == :[]=
|
179
|
-
next if name == :to_proc
|
180
|
-
#next unless [:empty?, :size].include?(name)
|
181
|
-
when :Struct
|
182
|
-
next if name == :initialize
|
183
|
-
when :Module
|
184
|
-
next if name == :include
|
185
|
-
next if name == :module_function
|
186
|
-
when :Proc
|
187
|
-
next if name == :call || name == :[]
|
188
|
-
when :Kernel
|
189
|
-
next if name == :Array
|
190
|
-
end
|
191
|
-
end
|
192
|
-
if member.singleton?
|
193
|
-
case type_name.name
|
194
|
-
when :Array
|
195
|
-
end
|
196
|
-
end
|
197
|
-
|
198
117
|
method_types = member.types.map do |method_type|
|
199
118
|
case method_type
|
200
|
-
when RBS::MethodType
|
201
|
-
|
202
|
-
when :super
|
203
|
-
raise NotImplementedError
|
119
|
+
when RBS::MethodType then method_type
|
120
|
+
when :super then raise NotImplementedError
|
204
121
|
end
|
205
122
|
end
|
206
123
|
|
207
|
-
method_def =
|
124
|
+
method_def = conv_method_def(method_types)
|
208
125
|
rbs_source = [(member.kind == :singleton ? "self." : "") + member.name.to_s, member.types.map {|type| type.location.source }]
|
209
126
|
if member.instance?
|
210
127
|
methods[[false, name]] = method_def
|
@@ -214,8 +131,16 @@ module TypeProf
|
|
214
131
|
methods[[true, name]] = method_def
|
215
132
|
rbs_sources[[true, name]] = rbs_source
|
216
133
|
end
|
217
|
-
|
218
|
-
|
134
|
+
when RBS::AST::Members::AttrReader
|
135
|
+
ty = conv_type(member.type)
|
136
|
+
methods[[false, member.name]] = attr_reader_def(ty)
|
137
|
+
when RBS::AST::Members::AttrWriter
|
138
|
+
ty = conv_type(member.type)
|
139
|
+
methods[[false, :"#{ member.name }="]] = attr_writer_def(ty)
|
140
|
+
when RBS::AST::Members::AttrAccessor
|
141
|
+
ty = conv_type(member.type)
|
142
|
+
methods[[false, member.name]] = attr_reader_def(ty)
|
143
|
+
methods[[false, :"#{ member.name }="]] = attr_writer_def(ty)
|
219
144
|
when RBS::AST::Members::Alias
|
220
145
|
if member.instance?
|
221
146
|
method_def = methods[[false, member.old_name]]
|
@@ -225,322 +150,438 @@ module TypeProf
|
|
225
150
|
method_def = methods[[true, member.old_name]]
|
226
151
|
methods[[true, member.new_name]] = method_def if method_def
|
227
152
|
end
|
153
|
+
|
228
154
|
when RBS::AST::Members::Include
|
229
155
|
name = member.name
|
230
|
-
|
231
|
-
|
156
|
+
if name.kind == :class
|
157
|
+
mod = conv_type_name(name)
|
158
|
+
included_modules << mod
|
159
|
+
else
|
160
|
+
# including an interface is not supported yet
|
161
|
+
end
|
162
|
+
|
232
163
|
when RBS::AST::Members::InstanceVariable
|
164
|
+
ivars[member.name] = conv_type(member.type)
|
233
165
|
when RBS::AST::Members::ClassVariable
|
234
|
-
|
166
|
+
cvars[member.name] = conv_type(member.type)
|
167
|
+
|
168
|
+
when RBS::AST::Members::Public, RBS::AST::Members::Private # XXX
|
169
|
+
|
170
|
+
# The following declarations are ignoreable because they are handled in other level
|
235
171
|
when RBS::AST::Declarations::Constant
|
236
|
-
when RBS::AST::Declarations::Alias
|
172
|
+
when RBS::AST::Declarations::Alias # type alias
|
173
|
+
when RBS::AST::Declarations::Class, RBS::AST::Declarations::Module
|
174
|
+
when RBS::AST::Declarations::Interface
|
175
|
+
|
237
176
|
else
|
238
177
|
warn "Importing #{ member.class.name } is not supported yet"
|
239
|
-
#p member
|
240
178
|
end
|
241
179
|
end
|
242
180
|
end
|
243
181
|
|
244
|
-
|
245
|
-
|
182
|
+
json[klass] = {
|
183
|
+
type_params: type_params,
|
184
|
+
superclass: superclass,
|
185
|
+
members: {
|
186
|
+
included_modules: included_modules,
|
187
|
+
methods: methods,
|
188
|
+
ivars: ivars,
|
189
|
+
cvars: cvars,
|
190
|
+
rbs_sources: rbs_sources,
|
191
|
+
},
|
192
|
+
}
|
193
|
+
end
|
194
|
+
|
195
|
+
json
|
196
|
+
end
|
197
|
+
|
198
|
+
def each_class_decl
|
199
|
+
classes = []
|
200
|
+
|
201
|
+
# topological sort
|
202
|
+
# * superclasses and modules appear earlier than their subclasses (Object is earlier than String)
|
203
|
+
# * namespace module appers earlier than its children (Process is earlier than Process::Status)
|
204
|
+
visited = {}
|
205
|
+
queue = @cur_env.class_decls.keys.map {|name| [:visit, name] }
|
206
|
+
until queue.empty?
|
207
|
+
event, name = queue.pop
|
208
|
+
case event
|
209
|
+
when :visit
|
210
|
+
if !visited[name]
|
211
|
+
visited[name] = true
|
212
|
+
queue << [:new, name]
|
213
|
+
@all_env.class_decls[name].decls.each do |decl|
|
214
|
+
decl = decl.decl
|
215
|
+
next if decl.is_a?(RBS::AST::Declarations::Module)
|
216
|
+
each_ancestor(decl) {|name| queue << [:visit, name] }
|
217
|
+
end
|
218
|
+
queue << [:visit, name.namespace.to_type_name] if !name.namespace.empty?
|
219
|
+
end
|
220
|
+
when :new
|
221
|
+
decls = @cur_env.class_decls[name]
|
222
|
+
yield name, decls.decls if decls
|
223
|
+
end
|
224
|
+
end
|
246
225
|
|
247
|
-
|
226
|
+
classes
|
248
227
|
end
|
249
228
|
|
250
|
-
def
|
251
|
-
|
252
|
-
|
253
|
-
|
229
|
+
def each_ancestor(decl, &blk)
|
230
|
+
yield decl.name
|
231
|
+
super_class = decl.super_class || RBS::BuiltinNames::Object
|
232
|
+
return if decl.name == RBS::BuiltinNames::BasicObject.name
|
233
|
+
return if decl.name == super_class.name
|
234
|
+
@all_env.class_decls[super_class.name].decls.each do |decl|
|
235
|
+
each_ancestor(decl.decl, &blk)
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
def get_super_class_name(name)
|
240
|
+
return nil if name == RBS::BuiltinNames::BasicObject.name
|
241
|
+
|
242
|
+
@all_env.class_decls[name].decls.each do |decl|
|
243
|
+
decl = decl.decl
|
244
|
+
case decl
|
245
|
+
when RBS::AST::Declarations::Class
|
246
|
+
return decl.super_class.name if decl.super_class
|
247
|
+
when RBS::AST::Declarations::Module
|
248
|
+
return nil
|
254
249
|
else
|
255
|
-
|
250
|
+
raise "unknown declaration: %p" % decl.class
|
256
251
|
end
|
252
|
+
end
|
253
|
+
|
254
|
+
return RBS::BuiltinNames::Object.name
|
255
|
+
end
|
256
|
+
|
257
|
+
def conv_method_def(rbs_method_types)
|
258
|
+
rbs_method_types.map do |type|
|
259
|
+
blk = type.block ? conv_block(type.block) : nil
|
257
260
|
type_params = type.type_params
|
258
261
|
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
262
|
+
lead_tys = type.type.required_positionals.map {|type| conv_type(type.type) }
|
263
|
+
opt_tys = type.type.optional_positionals.map {|type| conv_type(type.type) }
|
264
|
+
rest_ty = type.type.rest_positionals
|
265
|
+
rest_ty = conv_type(rest_ty.type) if rest_ty
|
266
|
+
opt_kw_tys = type.type.optional_keywords.to_h {|key, type| [key, conv_type(type.type)] }
|
267
|
+
req_kw_tys = type.type.required_keywords.to_h {|key, type| [key, conv_type(type.type)] }
|
268
|
+
rest_kw_ty = type.type.rest_keywords
|
269
|
+
raise NotImplementedError if rest_kw_ty # XXX
|
270
|
+
|
271
|
+
ret_ty = conv_type(type.type.return_type)
|
272
|
+
|
273
|
+
{
|
274
|
+
type_params: type_params,
|
275
|
+
lead_tys: lead_tys,
|
276
|
+
opt_tys: opt_tys,
|
277
|
+
rest_ty: rest_ty,
|
278
|
+
req_kw_tys: req_kw_tys,
|
279
|
+
opt_kw_tys: opt_kw_tys,
|
280
|
+
rest_kw_ty: rest_kw_ty,
|
281
|
+
blk: blk,
|
282
|
+
ret_ty: ret_ty,
|
283
|
+
}
|
284
|
+
end
|
285
|
+
end
|
276
286
|
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
287
|
+
def attr_reader_def(ty)
|
288
|
+
[{
|
289
|
+
type_params: [],
|
290
|
+
lead_tys: [],
|
291
|
+
opt_tys: [],
|
292
|
+
rest_ty: nil,
|
293
|
+
req_kw_tys: {},
|
294
|
+
opt_kw_tys: {},
|
295
|
+
rest_kw_ty: nil,
|
296
|
+
blk: nil,
|
297
|
+
ret_ty: ty,
|
298
|
+
}]
|
299
|
+
end
|
300
|
+
|
301
|
+
def attr_writer_def(ty)
|
302
|
+
[{
|
303
|
+
type_params: [],
|
304
|
+
lead_tys: [ty],
|
305
|
+
opt_tys: [],
|
306
|
+
rest_ty: nil,
|
307
|
+
req_kw_tys: {},
|
308
|
+
opt_kw_tys: {},
|
309
|
+
rest_kw_ty: nil,
|
310
|
+
blk: nil,
|
311
|
+
ret_ty: ty,
|
312
|
+
}]
|
283
313
|
end
|
284
314
|
|
285
|
-
def
|
286
|
-
type =
|
315
|
+
def conv_block(rbs_block)
|
316
|
+
type = rbs_block.type
|
317
|
+
|
318
|
+
# XXX
|
287
319
|
raise NotImplementedError unless type.optional_keywords.empty?
|
288
320
|
raise NotImplementedError unless type.required_keywords.empty?
|
289
|
-
raise NotImplementedError unless type.optional_positionals.empty?
|
290
321
|
raise NotImplementedError if type.rest_keywords
|
322
|
+
|
291
323
|
lead_tys = type.required_positionals.map do |type|
|
292
|
-
|
324
|
+
conv_type(type.type)
|
325
|
+
end
|
326
|
+
opt_tys = type.optional_positionals.map do |type|
|
327
|
+
conv_type(type.type)
|
293
328
|
end
|
294
|
-
ret_ty = convert_type(type.return_type)
|
295
|
-
[lead_tys, ret_ty]
|
296
|
-
end
|
297
329
|
|
298
|
-
|
330
|
+
ret_ty = conv_type(type.return_type)
|
331
|
+
|
332
|
+
[lead_tys, opt_tys, ret_ty]
|
299
333
|
end
|
300
334
|
|
301
|
-
def
|
335
|
+
def conv_type(ty)
|
302
336
|
case ty
|
303
337
|
when RBS::Types::ClassSingleton
|
304
|
-
|
305
|
-
[:class, klass]
|
338
|
+
[:class, conv_type_name(ty.name)]
|
306
339
|
when RBS::Types::ClassInstance
|
307
|
-
klass = ty.name
|
340
|
+
klass = conv_type_name(ty.name)
|
308
341
|
case klass
|
309
342
|
when [:Array]
|
310
343
|
raise if ty.args.size != 1
|
311
|
-
[:array, :Array, [],
|
344
|
+
[:array, [:Array], [], conv_type(ty.args.first)]
|
312
345
|
when [:Hash]
|
313
346
|
raise if ty.args.size != 2
|
314
347
|
key, val = ty.args
|
315
|
-
[:hash, :Hash, [
|
348
|
+
[:hash, [:Hash], [conv_type(key), conv_type(val)]]
|
316
349
|
when [:Enumerator]
|
317
350
|
raise if ty.args.size != 2
|
318
|
-
[:array, :Enumerator, [],
|
351
|
+
[:array, [:Enumerator], [], conv_type(ty.args.first)]
|
319
352
|
else
|
320
353
|
[:instance, klass]
|
321
354
|
end
|
322
|
-
when RBS::Types::Bases::Bool
|
323
|
-
|
324
|
-
when RBS::Types::Bases::
|
325
|
-
|
326
|
-
when RBS::Types::Bases::
|
327
|
-
|
328
|
-
when RBS::Types::
|
329
|
-
[:self]
|
330
|
-
when RBS::Types::Bases::Nil
|
331
|
-
[:nil]
|
332
|
-
when RBS::Types::Bases::Bottom
|
333
|
-
[:union, []]
|
334
|
-
when RBS::Types::Variable
|
335
|
-
[:var, ty.name]
|
355
|
+
when RBS::Types::Bases::Bool then [:bool]
|
356
|
+
when RBS::Types::Bases::Any then [:any]
|
357
|
+
when RBS::Types::Bases::Void then [:any]
|
358
|
+
when RBS::Types::Bases::Self then [:self]
|
359
|
+
when RBS::Types::Bases::Nil then [:nil]
|
360
|
+
when RBS::Types::Bases::Bottom then [:union, []]
|
361
|
+
when RBS::Types::Variable then [:var, ty.name]
|
336
362
|
when RBS::Types::Tuple
|
337
|
-
tys = ty.types.map {|ty2|
|
338
|
-
[:array, :Array, tys, [:union, []]]
|
363
|
+
tys = ty.types.map {|ty2| conv_type(ty2) }
|
364
|
+
[:array, [:Array], tys, [:union, []]]
|
339
365
|
when RBS::Types::Literal
|
340
366
|
case ty.literal
|
341
|
-
when Integer
|
342
|
-
|
343
|
-
when
|
344
|
-
|
345
|
-
when
|
346
|
-
[:true]
|
347
|
-
when false
|
348
|
-
[:false]
|
349
|
-
when Symbol
|
350
|
-
[:sym, ty.literal]
|
367
|
+
when Integer then [:int]
|
368
|
+
when String then [:str]
|
369
|
+
when true then [:true]
|
370
|
+
when false then [:false]
|
371
|
+
when Symbol then [:sym, ty.literal]
|
351
372
|
else
|
352
373
|
p ty.literal
|
353
374
|
raise NotImplementedError
|
354
375
|
end
|
355
376
|
when RBS::Types::Alias
|
356
377
|
alias_decl = @all_env.alias_decls[ty.name]
|
357
|
-
alias_decl ?
|
378
|
+
alias_decl ? conv_type(alias_decl.decl.type) : [:any]
|
358
379
|
when RBS::Types::Union
|
359
|
-
[:union, ty.types.map {|ty2|
|
380
|
+
[:union, ty.types.map {|ty2| conv_type(ty2) }.compact]
|
360
381
|
when RBS::Types::Optional
|
361
|
-
[:optional,
|
362
|
-
when RBS::Types::Record
|
363
|
-
[:any]
|
382
|
+
[:optional, conv_type(ty.type)]
|
364
383
|
when RBS::Types::Interface
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
384
|
+
# XXX: Currently, only a few builtin interfaces are supported
|
385
|
+
case ty.to_s
|
386
|
+
when "::_ToStr" then [:str]
|
387
|
+
when "::_ToInt" then [:int]
|
388
|
+
when "::_ToAry[U]" then [:array, [:Array], [], [:var, :U]]
|
389
|
+
else
|
390
|
+
[:any]
|
369
391
|
end
|
370
|
-
|
392
|
+
when RBS::Types::Bases::Instance then [:any] # XXX: not implemented yet
|
393
|
+
when RBS::Types::Record then [:any] # XXX: not implemented yet
|
394
|
+
when RBS::Types::Proc then [:any] # XXX: not implemented yet
|
371
395
|
else
|
372
|
-
|
373
|
-
|
396
|
+
warn "unknown RBS type: %p" % ty.class
|
397
|
+
[:any]
|
374
398
|
end
|
375
399
|
end
|
376
|
-
end
|
377
|
-
|
378
|
-
module RubySignatureImporter
|
379
|
-
module_function
|
380
400
|
|
381
|
-
def
|
382
|
-
|
383
|
-
path.each do |name|
|
384
|
-
klass = scratch.get_constant(klass, name)
|
385
|
-
raise if klass == Type.any
|
386
|
-
end
|
387
|
-
klass
|
401
|
+
def conv_type_name(name)
|
402
|
+
name.namespace.path + [name.name]
|
388
403
|
end
|
404
|
+
end
|
389
405
|
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
import_ruby_signature(scratch, scratch.rbs_reader.load_builtin)
|
406
|
+
class Import
|
407
|
+
def self.import_builtin(scratch)
|
408
|
+
Import.new(scratch, scratch.rbs_reader.load_builtin).import
|
394
409
|
end
|
395
410
|
|
396
|
-
def import_library(scratch, feature)
|
411
|
+
def self.import_library(scratch, feature)
|
412
|
+
begin
|
413
|
+
json = scratch.rbs_reader.load_library(feature)
|
414
|
+
rescue RBS::EnvironmentLoader::UnknownLibraryNameError
|
415
|
+
return nil
|
416
|
+
end
|
397
417
|
# need cache?
|
398
|
-
|
399
|
-
rescue RBS::EnvironmentLoader::UnknownLibraryNameError
|
400
|
-
false
|
418
|
+
Import.new(scratch, json).import
|
401
419
|
end
|
402
420
|
|
403
|
-
def import_rbs_file(scratch, rbs_path)
|
404
|
-
|
421
|
+
def self.import_rbs_file(scratch, rbs_path)
|
422
|
+
Import.new(scratch, scratch.rbs_reader.load_path(Pathname(rbs_path))).import(true)
|
405
423
|
end
|
406
424
|
|
407
|
-
def
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
425
|
+
def initialize(scratch, json)
|
426
|
+
@scratch = scratch
|
427
|
+
@json = json
|
428
|
+
end
|
429
|
+
|
430
|
+
def import(explicit = false)
|
431
|
+
classes = @json[:classes].map do |classpath, cdef|
|
432
|
+
type_params = cdef[:type_params]
|
433
|
+
superclass = cdef[:superclass]
|
434
|
+
members = cdef[:members]
|
435
|
+
|
436
|
+
name = classpath.last
|
437
|
+
superclass = path_to_klass(superclass) if superclass
|
438
|
+
base_klass = path_to_klass(classpath[0..-2])
|
439
|
+
|
440
|
+
klass = @scratch.get_constant(base_klass, name)
|
441
|
+
if klass.is_a?(Type::Any)
|
442
|
+
klass = @scratch.new_class(base_klass, name, type_params, superclass, nil)
|
443
|
+
|
444
|
+
# There builtin classes are needed to interpret RBS declarations
|
445
|
+
case classpath
|
446
|
+
when [:NilClass] then Type::Builtin[:nil] = klass
|
447
|
+
when [:TrueClass] then Type::Builtin[:true] = klass
|
448
|
+
when [:FalseClass] then Type::Builtin[:false] = klass
|
449
|
+
when [:Integer] then Type::Builtin[:int] = klass
|
450
|
+
when [:String] then Type::Builtin[:str] = klass
|
451
|
+
when [:Symbol] then Type::Builtin[:sym] = klass
|
452
|
+
when [:Array] then Type::Builtin[:ary] = klass
|
453
|
+
when [:Hash] then Type::Builtin[:hash] = klass
|
428
454
|
end
|
429
455
|
end
|
430
|
-
|
456
|
+
|
457
|
+
[klass, members]
|
431
458
|
end
|
432
459
|
|
433
|
-
classes.each do |klass,
|
460
|
+
classes.each do |klass, members|
|
461
|
+
included_modules = members[:included_modules]
|
462
|
+
methods = members[:methods]
|
463
|
+
ivars = members[:ivars]
|
464
|
+
cvars = members[:cvars]
|
465
|
+
rbs_sources = members[:rbs_sources]
|
466
|
+
|
434
467
|
included_modules.each do |mod|
|
435
|
-
|
436
|
-
scratch.include_module(klass, mod, false)
|
468
|
+
@scratch.include_module(klass, path_to_klass(mod), nil)
|
437
469
|
end
|
470
|
+
|
438
471
|
methods.each do |(singleton, method_name), mdef|
|
439
|
-
rbs_source = nil
|
440
|
-
|
441
|
-
|
442
|
-
|
472
|
+
rbs_source = explicit ? rbs_sources[[singleton, method_name]] : nil
|
473
|
+
mdef = conv_method_def(method_name, mdef, rbs_source)
|
474
|
+
@scratch.add_method(klass, method_name, singleton, mdef)
|
475
|
+
end
|
476
|
+
|
477
|
+
ivars.each do |ivar_name, ty|
|
478
|
+
ty = conv_type(ty)
|
479
|
+
@scratch.add_ivar_write!(Type::Instance.new(klass), ivar_name, ty, nil)
|
480
|
+
end
|
481
|
+
|
482
|
+
cvars.each do |ivar_name, ty|
|
483
|
+
ty = conv_type(ty)
|
484
|
+
@scratch.add_cvar_write!(klass, ivar_name, ty, nil)
|
443
485
|
end
|
444
486
|
end
|
445
487
|
|
446
|
-
|
447
|
-
base_klass = path_to_klass(
|
448
|
-
value =
|
449
|
-
scratch.add_constant(base_klass, classpath[-1], value)
|
488
|
+
@json[:constants].each do |classpath, value|
|
489
|
+
base_klass = path_to_klass(classpath[0..-2])
|
490
|
+
value = conv_type(value)
|
491
|
+
@scratch.add_constant(base_klass, classpath[-1], value)
|
492
|
+
end
|
493
|
+
|
494
|
+
@json[:globals].each do |name, value|
|
495
|
+
@scratch.add_gvar_write!(name, conv_type(value), nil)
|
450
496
|
end
|
451
497
|
|
452
498
|
true
|
453
499
|
end
|
454
500
|
|
455
|
-
def
|
456
|
-
sig_rets = mdef.map do |
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
501
|
+
def conv_method_def(method_name, mdef, rbs_source)
|
502
|
+
sig_rets = mdef.map do |sig_ret|
|
503
|
+
#type_params = sig_ret[:type_params] # XXX
|
504
|
+
lead_tys = sig_ret[:lead_tys]
|
505
|
+
opt_tys = sig_ret[:opt_tys]
|
506
|
+
rest_ty = sig_ret[:rest_ty]
|
507
|
+
req_kw_tys = sig_ret[:req_kw_tys]
|
508
|
+
opt_kw_tys = sig_ret[:opt_kw_tys]
|
509
|
+
rest_kw_ty = sig_ret[:rest_kw_ty]
|
510
|
+
blk = sig_ret[:blk]
|
511
|
+
ret_ty = sig_ret[:ret_ty]
|
512
|
+
|
513
|
+
lead_tys = lead_tys.map {|ty| conv_type(ty) }
|
514
|
+
opt_tys = opt_tys.map {|ty| conv_type(ty) }
|
515
|
+
rest_ty = conv_type(rest_ty) if rest_ty
|
516
|
+
kw_tys = []
|
517
|
+
req_kw_tys.each {|key, ty| kw_tys << [true, key, conv_type(ty)] }
|
518
|
+
opt_kw_tys.each {|key, ty| kw_tys << [false, key, conv_type(ty)] }
|
519
|
+
kw_rest_ty = conv_type(rest_kw_ty) if rest_kw_ty
|
520
|
+
blk = blk ? conv_block(blk) : Type.nil
|
521
|
+
fargs = FormalArguments.new(lead_tys, opt_tys, rest_ty, [], kw_tys, kw_rest_ty, blk)
|
522
|
+
|
523
|
+
ret_ty = conv_type(ret_ty)
|
524
|
+
|
525
|
+
[fargs, ret_ty]
|
477
526
|
end.compact
|
478
527
|
|
479
528
|
TypedMethodDef.new(sig_rets, rbs_source)
|
480
529
|
end
|
481
530
|
|
482
|
-
def
|
483
|
-
lead_tys, ret_ty = blk
|
484
|
-
lead_tys = lead_tys.map {|ty|
|
485
|
-
|
486
|
-
|
531
|
+
def conv_block(blk)
|
532
|
+
lead_tys, opt_tys, ret_ty = blk
|
533
|
+
lead_tys = lead_tys.map {|ty| conv_type(ty) }
|
534
|
+
opt_tys = opt_tys.map {|ty| conv_type(ty) }
|
535
|
+
fargs = FormalArguments.new(lead_tys, opt_tys, nil, nil, nil, nil, nil)
|
536
|
+
ret_ty = conv_type(ret_ty)
|
537
|
+
Type::TypedProc.new(fargs, ret_ty, Type::Builtin[:proc])
|
487
538
|
end
|
488
539
|
|
489
|
-
|
490
|
-
end
|
491
|
-
|
492
|
-
def convert_type(scratch, ty)
|
540
|
+
def conv_type(ty)
|
493
541
|
case ty.first
|
494
|
-
when :class
|
495
|
-
|
496
|
-
when :
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
when :
|
503
|
-
|
504
|
-
when :
|
505
|
-
|
506
|
-
when :self
|
507
|
-
Type::Var.new(:self)
|
508
|
-
when :int
|
509
|
-
Type::Instance.new(Type::Builtin[:int])
|
510
|
-
when :str
|
511
|
-
Type::Instance.new(Type::Builtin[:str])
|
512
|
-
when :sym
|
513
|
-
Type::Symbol.new(ty.last, Type::Instance.new(Type::Builtin[:sym]))
|
514
|
-
when :nil
|
515
|
-
Type.nil
|
516
|
-
when :true
|
517
|
-
Type::Instance.new(Type::Builtin[:true])
|
518
|
-
when :false
|
519
|
-
Type::Instance.new(Type::Builtin[:false])
|
542
|
+
when :class then path_to_klass(ty[1])
|
543
|
+
when :instance then Type::Instance.new(path_to_klass(ty[1]))
|
544
|
+
when :any then Type.any
|
545
|
+
when :nil then Type.nil
|
546
|
+
when :optional then Type.optional(conv_type(ty[1]))
|
547
|
+
when :bool then Type.bool
|
548
|
+
when :self then Type::Var.new(:self)
|
549
|
+
when :int then Type::Instance.new(Type::Builtin[:int])
|
550
|
+
when :str then Type::Instance.new(Type::Builtin[:str])
|
551
|
+
when :sym then Type::Symbol.new(ty.last, Type::Instance.new(Type::Builtin[:sym]))
|
552
|
+
when :true then Type::Instance.new(Type::Builtin[:true])
|
553
|
+
when :false then Type::Instance.new(Type::Builtin[:false])
|
520
554
|
when :array
|
521
|
-
_,
|
522
|
-
lead_tys = lead_tys.map {|ty|
|
523
|
-
rest_ty =
|
524
|
-
base_type = Type::Instance.new(
|
555
|
+
_, path, lead_tys, rest_ty = ty
|
556
|
+
lead_tys = lead_tys.map {|ty| conv_type(ty) }
|
557
|
+
rest_ty = conv_type(rest_ty)
|
558
|
+
base_type = Type::Instance.new(path_to_klass(path))
|
525
559
|
Type::Array.new(Type::Array::Elements.new(lead_tys, rest_ty), base_type)
|
526
560
|
when :hash
|
527
|
-
_,
|
528
|
-
Type.gen_hash do |h|
|
529
|
-
k_ty =
|
530
|
-
v_ty =
|
561
|
+
_, path, (k, v) = ty
|
562
|
+
Type.gen_hash(Type::Instance.new(path_to_klass(path))) do |h|
|
563
|
+
k_ty = conv_type(k)
|
564
|
+
v_ty = conv_type(v)
|
531
565
|
h[k_ty] = v_ty
|
532
566
|
end
|
533
567
|
when :union
|
534
|
-
tys = ty[1]
|
535
|
-
Type::Union.new(Utils::Set[*tys.map {|ty2|
|
536
|
-
when :optional
|
537
|
-
Type.optional(convert_type(scratch, ty[1]))
|
568
|
+
tys = ty[1]
|
569
|
+
Type::Union.new(Utils::Set[*tys.map {|ty2| conv_type(ty2) }], nil) # XXX: Array and Hash support
|
538
570
|
when :var
|
539
|
-
Type::Var.new(ty[1])
|
571
|
+
Type::Var.new(ty[1])
|
540
572
|
else
|
541
573
|
pp ty
|
542
574
|
raise NotImplementedError
|
543
575
|
end
|
544
576
|
end
|
577
|
+
|
578
|
+
def path_to_klass(path)
|
579
|
+
klass = Type::Builtin[:obj]
|
580
|
+
path.each do |name|
|
581
|
+
klass = @scratch.get_constant(klass, name)
|
582
|
+
raise path.inspect if klass == Type.any
|
583
|
+
end
|
584
|
+
klass
|
585
|
+
end
|
545
586
|
end
|
546
587
|
end
|