typeprof 0.10.0 → 0.14.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.
@@ -27,7 +27,7 @@ module TypeProf
27
27
  self
28
28
  end
29
29
 
30
- def do_call(aargs, caller_ep, caller_env, scratch, replace_recv_ty:, &ctn)
30
+ def do_call(aargs, caller_ep, caller_env, scratch, replace_recv_ty:, replace_cref:, &ctn)
31
31
  blk_env = scratch.return_envs[@outer_ep]
32
32
  if replace_recv_ty
33
33
  replace_recv_ty = scratch.globalize_type(replace_recv_ty, caller_env, caller_ep)
@@ -46,7 +46,8 @@ module TypeProf
46
46
  return
47
47
  end
48
48
 
49
- nctx = Context.new(@iseq, @outer_ep.ctx.cref, nil)
49
+ cref = replace_cref || @outer_ep.ctx.cref
50
+ nctx = Context.new(@iseq, cref, nil)
50
51
  callee_ep = ExecutionPoint.new(nctx, 0, @outer_ep)
51
52
  nenv = Env.new(blk_env.static_env, locals, [], nil)
52
53
  alloc_site = AllocationSite.new(callee_ep)
@@ -87,7 +88,7 @@ module TypeProf
87
88
  TypedBlock.new(msig, ret_ty)
88
89
  end
89
90
 
90
- def do_call(aargs, caller_ep, caller_env, scratch, replace_recv_ty:, &ctn)
91
+ def do_call(aargs, caller_ep, caller_env, scratch, replace_recv_ty:, replace_cref:, &ctn)
91
92
  aargs = scratch.globalize_type(aargs, caller_env, caller_ep)
92
93
  subst = aargs.consistent_with_method_signature?(@msig)
93
94
  unless subst
@@ -119,7 +120,7 @@ module TypeProf
119
120
  self
120
121
  end
121
122
 
122
- def do_call(aargs, caller_ep, caller_env, scratch, replace_recv_ty:, &ctn)
123
+ def do_call(aargs, caller_ep, caller_env, scratch, replace_recv_ty:, replace_cref:, &ctn)
123
124
  if aargs.lead_tys.size >= 1
124
125
  recv = aargs.lead_tys[0]
125
126
  recv = Type.any if recv == Type.bot
@@ -157,7 +158,7 @@ module TypeProf
157
158
  self
158
159
  end
159
160
 
160
- def do_call(aargs, caller_ep, caller_env, scratch, replace_recv_ty:, &ctn)
161
+ def do_call(aargs, caller_ep, caller_env, scratch, replace_recv_ty:, replace_cref:, &ctn)
161
162
  aargs = scratch.globalize_type(aargs, caller_env, caller_ep)
162
163
 
163
164
  dummy_ctx = TypedContext.new(@caller_ep, @mid)
@@ -165,7 +166,7 @@ module TypeProf
165
166
  scratch.add_block_signature!(self, aargs.to_block_signature)
166
167
  scratch.add_block_to_ctx!(self, dummy_ctx)
167
168
 
168
- @blk.call(aargs, caller_ep, caller_env, scratch, replace_recv_ty: replace_recv_ty) do |ret_ty, ep, env|
169
+ @blk.call(aargs, caller_ep, caller_env, scratch, replace_recv_ty: replace_recv_ty, replace_cref: replace_cref) do |ret_ty, ep, env|
169
170
  scratch.add_return_value!(dummy_ctx, ret_ty)
170
171
  ctn[ret_ty, ep, env]
171
172
  end
@@ -158,7 +158,43 @@ module TypeProf
158
158
  naargs = ActualArguments.new([recv], nil, {}, Type.nil)
159
159
  nrecv = recv
160
160
  nrecv = nrecv.base_type if nrecv.is_a?(Type::ContainerType)
161
- scratch.do_invoke_block(aargs.blk_ty, naargs, ep, env, replace_recv_ty: nrecv) do |_ret_ty, ep|
161
+ scratch.do_invoke_block(aargs.blk_ty, naargs, ep, env, replace_recv_ty: nrecv) do |ret_ty, ep|
162
+ ctn[ret_ty, ep, env]
163
+ end
164
+ end
165
+
166
+ def module_eqq(recv, mid, aargs, ep, env, scratch, &ctn)
167
+ if aargs.lead_tys.size == 1
168
+ aargs.lead_tys[0].each_child do |aarg|
169
+ aarg = aarg.base_type if aarg.is_a?(Type::Symbol) # XXX
170
+ if aarg.is_a?(Type::Instance)
171
+ if aarg.klass == recv # XXX: inheritance
172
+ true_val = Type::Instance.new(Type::Builtin[:true])
173
+ ctn[true_val, ep, env]
174
+ else
175
+ false_val = Type::Instance.new(Type::Builtin[:false])
176
+ ctn[false_val, ep, env]
177
+ end
178
+ else
179
+ ctn[Type.bool, ep, env]
180
+ end
181
+ end
182
+ else
183
+ ctn[Type.bool, ep, env]
184
+ end
185
+ end
186
+
187
+ def object_module_eval(recv, mid, aargs, ep, env, scratch, &ctn)
188
+ if aargs.lead_tys.size >= 1
189
+ scratch.warn(ep, "class_eval with arguments is ignored")
190
+ ctn[Type.any, ep, env]
191
+ return
192
+ end
193
+ naargs = ActualArguments.new([recv], nil, {}, Type.nil)
194
+ nrecv = recv
195
+ nrecv = nrecv.base_type if nrecv.is_a?(Type::ContainerType)
196
+ ncref = ep.ctx.cref.extend(nrecv, true)
197
+ scratch.do_invoke_block(aargs.blk_ty, naargs, ep, env, replace_recv_ty: nrecv, replace_cref: ncref) do |_ret_ty, ep|
162
198
  ctn[recv, ep, env]
163
199
  end
164
200
  end
@@ -176,7 +212,7 @@ module TypeProf
176
212
  end
177
213
 
178
214
  elem_ty = Type.bot
179
- enum_for_blk = CustomBlock.new(ep, mid) do |aargs, caller_ep, caller_env, scratch, replace_recv_ty:, &blk_ctn|
215
+ enum_for_blk = CustomBlock.new(ep, mid) do |aargs, caller_ep, caller_env, scratch, replace_recv_ty:, replace_cref:, &blk_ctn|
180
216
  if aargs.lead_tys.size >= 1
181
217
  elem_ty = elem_ty.union(aargs.lead_tys[0])
182
218
  else
@@ -235,9 +271,12 @@ module TypeProf
235
271
  return ctn[Type.any, ep, env]
236
272
  end
237
273
 
274
+ # support multiple arguments: include M1, M2
238
275
  arg = aargs.lead_tys[0]
239
276
  arg.each_child do |arg|
240
277
  if arg.is_a?(Type::Class)
278
+ aargs = ActualArguments.new([recv], nil, {}, Type.nil)
279
+ scratch.do_send(arg, :included, aargs, ep, env) {|_ret_ty, _ep| }
241
280
  scratch.mix_module(:after, recv, arg, nil, ep.ctx.cref.singleton, ep)
242
281
  end
243
282
  end
@@ -259,6 +298,8 @@ module TypeProf
259
298
  arg = aargs.lead_tys[0]
260
299
  arg.each_child do |arg|
261
300
  if arg.is_a?(Type::Class)
301
+ aargs = ActualArguments.new([recv], nil, {}, Type.nil)
302
+ scratch.do_send(arg, :extended, aargs, ep, env) {|_ret_ty, _ep| }
262
303
  # if ep.ctx.cref.singleton is true, the meta-meta level is ignored. Should we warn?
263
304
  scratch.mix_module(:after, recv, arg, nil, true, ep)
264
305
  end
@@ -557,8 +598,6 @@ module TypeProf
557
598
  end
558
599
 
559
600
  def struct_s_new(recv, mid, aargs, ep, env, scratch, &ctn)
560
- # TODO: keyword_init
561
-
562
601
  keyword_init = false
563
602
  if aargs.kw_tys && aargs.kw_tys[:keyword_init] # XXX: more canonical way to extract keyword...
564
603
  if aargs.kw_tys[:keyword_init] == Type::Instance.new(Type::Builtin[:true])
@@ -806,9 +845,12 @@ module TypeProf
806
845
  scratch.set_custom_method(klass_module, :public, Builtin.method(:module_public), false)
807
846
  scratch.set_custom_method(klass_module, :private, Builtin.method(:module_private), false)
808
847
  scratch.set_custom_method(klass_module, :define_method, Builtin.method(:module_define_method))
809
- scratch.set_custom_method(klass_module, :"attr_accessor", Builtin.method(:module_attr_accessor))
810
- scratch.set_custom_method(klass_module, :"attr_reader", Builtin.method(:module_attr_reader))
811
- scratch.set_custom_method(klass_module, :"attr_writer", Builtin.method(:module_attr_writer))
848
+ scratch.set_custom_method(klass_module, :attr_accessor, Builtin.method(:module_attr_accessor))
849
+ scratch.set_custom_method(klass_module, :attr_reader, Builtin.method(:module_attr_reader))
850
+ scratch.set_custom_method(klass_module, :attr_writer, Builtin.method(:module_attr_writer))
851
+ scratch.set_custom_method(klass_module, :class_eval, Builtin.method(:object_module_eval))
852
+ scratch.set_custom_method(klass_module, :module_eval, Builtin.method(:object_module_eval))
853
+ scratch.set_custom_method(klass_module, :===, Builtin.method(:module_eqq))
812
854
 
813
855
  scratch.set_custom_method(klass_proc, :[], Builtin.method(:proc_call))
814
856
  scratch.set_custom_method(klass_proc, :call, Builtin.method(:proc_call))
data/lib/typeprof/cli.rb CHANGED
@@ -20,6 +20,7 @@ module TypeProf
20
20
  options = {}
21
21
  dir_filter = nil
22
22
  gem_rbs_features = []
23
+ gem_repo_dirs = []
23
24
  show_version = false
24
25
  max_sec = max_iter = nil
25
26
 
@@ -31,6 +32,7 @@ module TypeProf
31
32
  opt.on("--version", "Display typeprof version") { show_version = true }
32
33
  opt.on("-I DIR", "Add DIR to the load/require path") {|v| $LOAD_PATH << v }
33
34
  opt.on("-r FEATURE", "Require RBS of the FEATURE gem") {|v| gem_rbs_features << v }
35
+ opt.on("--repo DIR", "Add DIR to the RBS repository") {|v| gem_repo_dirs << v }
34
36
 
35
37
  opt.separator ""
36
38
  opt.separator "Analysis output options:"
@@ -46,6 +48,8 @@ module TypeProf
46
48
  dir_filter ||= ConfigData::DEFAULT_DIR_FILTER
47
49
  dir_filter << [:exclude, File.expand_path(dir)]
48
50
  end
51
+ opt.on("--exclude-untyped", "Exclude (comment out) all entries including untyped") {|v| options[:exclude_untyped] = v }
52
+ opt.on("--[no-]show-typeprof-version", "Display TypeProf version in a header") {|v| options[:show_typeprof_version] = v }
49
53
  opt.on("--[no-]show-errors", "Display possible errors found during the analysis") {|v| options[:show_errors] = v }
50
54
  opt.on("--[no-]show-untyped", "Display \"Foo | untyped\" instead of \"Foo\"") {|v| options[:show_untyped] = v }
51
55
  opt.on("--[no-]show-parameter-names", "Display parameter names for methods") {|v| options[:show_parameter_names] = v }
@@ -87,6 +91,7 @@ module TypeProf
87
91
  rbs_files: rbs_files,
88
92
  output: output,
89
93
  gem_rbs_features: gem_rbs_features,
94
+ gem_repo_dirs: gem_repo_dirs,
90
95
  verbose: verbose,
91
96
  dir_filter: dir_filter,
92
97
  max_sec: max_sec,
@@ -6,6 +6,7 @@ module TypeProf
6
6
  :rbs_files,
7
7
  :output,
8
8
  :gem_rbs_features,
9
+ :gem_repo_dirs,
9
10
  :verbose,
10
11
  :dir_filter,
11
12
  :max_iter,
@@ -25,10 +26,13 @@ module TypeProf
25
26
  def initialize(**opt)
26
27
  opt[:output] ||= $stdout
27
28
  opt[:gem_rbs_features] ||= []
29
+ opt[:gem_repo_dirs] ||= []
28
30
  opt[:dir_filter] ||= DEFAULT_DIR_FILTER
29
31
  opt[:verbose] ||= 0
30
32
  opt[:options] ||= {}
31
33
  opt[:options] = {
34
+ exclude_untyped: false,
35
+ show_typeprof_version: true,
32
36
  show_indicator: true,
33
37
  show_untyped: false,
34
38
  show_errors: false,
@@ -76,9 +80,19 @@ module TypeProf
76
80
  Import.import_library(scratch, feature)
77
81
  end
78
82
 
79
- prologue_ctx = Context.new(nil, nil, nil)
80
- prologue_ep = ExecutionPoint.new(prologue_ctx, -1, nil)
81
- prologue_env = Env.new(StaticEnv.new(Type.bot, Type.nil, false, true), [], [], Utils::HashWrapper.new({}))
83
+ rbs_files = []
84
+ rbs_codes = []
85
+ Config.rbs_files.each do |rbs|
86
+ if rbs.is_a?(Array) # [String name, String content]
87
+ rbs_codes << rbs
88
+ else
89
+ rbs_files << rbs
90
+ end
91
+ end
92
+ Import.import_rbs_files(scratch, rbs_files)
93
+ rbs_codes.each do |name, content|
94
+ Import.import_rbs_code(scratch, name, content)
95
+ end
82
96
 
83
97
  Config.rb_files.each do |rb|
84
98
  if rb.is_a?(Array) # [String name, String content]
@@ -86,17 +100,7 @@ module TypeProf
86
100
  else
87
101
  iseq = ISeq.compile(rb)
88
102
  end
89
- ep, env = TypeProf.starting_state(iseq)
90
- scratch.merge_env(ep, env)
91
- scratch.add_callsite!(ep.ctx, prologue_ep, prologue_env) {|ty, ep| }
92
- end
93
-
94
- Config.rbs_files.each do |rbs|
95
- if rbs.is_a?(Array) # [String name, String content]
96
- Import.import_rbs_code(scratch, *rbs)
97
- else
98
- Import.import_rbs_file(scratch, rbs)
99
- end
103
+ scratch.add_entrypoint(iseq)
100
104
  end
101
105
 
102
106
  result = scratch.type_profile
@@ -45,6 +45,12 @@ module TypeProf
45
45
  Type::Cell.new(Type::Cell::Elements.new([Type.bot] * klass.type_params.size), base_type)
46
46
  end
47
47
  end
48
+
49
+ def include_untyped?(scratch)
50
+ return true if @base_type.include_untyped?(scratch)
51
+ return true if @elems.include_untyped?(scratch)
52
+ false
53
+ end
48
54
  end
49
55
 
50
56
  # The most basic container type for default type parameter class
@@ -196,6 +202,10 @@ module TypeProf
196
202
  end
197
203
  Elements.new(elems)
198
204
  end
205
+
206
+ def include_untyped?(scratch)
207
+ return @elems.any? {|ty| ty.include_untyped?(scratch) }
208
+ end
199
209
  end
200
210
  end
201
211
 
@@ -531,6 +541,12 @@ module TypeProf
531
541
  return rest_ary_ty, following_tys
532
542
  end
533
543
  end
544
+
545
+ def include_untyped?(scratch)
546
+ return true if @lead_tys.any? {|ty| ty.include_untyped?(scratch) }
547
+ return true if @rest_ty.include_untyped?(scratch)
548
+ false
549
+ end
534
550
  end
535
551
  end
536
552
 
@@ -790,6 +806,14 @@ module TypeProf
790
806
  end
791
807
  kw_tys
792
808
  end
809
+
810
+ def include_untyped?(scratch)
811
+ @map_tys.each do |key, val|
812
+ return true if key.include_untyped?(scratch)
813
+ return true if val.include_untyped?(scratch)
814
+ end
815
+ false
816
+ end
793
817
  end
794
818
  end
795
819
 
@@ -26,6 +26,10 @@ module TypeProf
26
26
  end
27
27
 
28
28
  def show_message(terminated, output)
29
+ if Config.options[:show_typeprof_version]
30
+ output.puts "# TypeProf #{ VERSION }"
31
+ output.puts
32
+ end
29
33
  if terminated
30
34
  output.puts "# CAUTION: Type profiling was terminated prematurely because of the limitation"
31
35
  output.puts
@@ -94,6 +98,10 @@ module TypeProf
94
98
  if class_def.klass_obj.superclass != :__root__ && class_def.klass_obj.superclass
95
99
  omit = class_def.klass_obj.superclass == Type::Builtin[:obj] || class_def.klass_obj == Type::Builtin[:obj]
96
100
  superclass = omit ? nil : @scratch.get_class_name(class_def.klass_obj.superclass)
101
+ type_args = class_def.klass_obj.superclass_type_args
102
+ if type_args && !type_args.empty?
103
+ superclass += "[#{ type_args.map {|ty| ty.screen_name(@scratch) }.join(", ") }]"
104
+ end
97
105
  end
98
106
 
99
107
  @scratch.namespace = class_def.name
@@ -129,18 +137,17 @@ module TypeProf
129
137
  ctxs = @iseq_method_to_ctxs[mdef]
130
138
  next unless ctxs
131
139
 
132
- ctxs.each do |ctx|
133
- next if mid != ctx.mid
134
- next if Config.check_dir_filter(ctx.iseq.absolute_path) == :exclude
140
+ ctx = ctxs.find {|ctx| ctx.mid == mid } || ctxs.first
135
141
 
136
- method_name = ctx.mid
137
- method_name = "self.#{ method_name }" if singleton
142
+ next if Config.check_dir_filter(ctx.iseq.absolute_path) == :exclude
138
143
 
139
- key = [:iseq, method_name]
140
- visibilities[key] ||= mdef.pub_meth
141
- source_locations[key] ||= ctx.iseq.source_location(0)
142
- (methods[key] ||= []) << @scratch.show_method_signature(ctx)
143
- end
144
+ method_name = mid
145
+ method_name = "self.#{ method_name }" if singleton
146
+
147
+ key = [:iseq, method_name]
148
+ visibilities[key] ||= mdef.pub_meth
149
+ source_locations[key] ||= ctx.iseq.source_location(0)
150
+ (methods[key] ||= []) << @scratch.show_method_signature(ctx)
144
151
  when AliasMethodDef
145
152
  alias_name, orig_name = mid, mdef.orig_mid
146
153
  if singleton
@@ -169,7 +176,7 @@ module TypeProf
169
176
  else
170
177
  entry = ivars[[singleton, mdef.ivar]]
171
178
  ty = entry ? entry.type : Type.any
172
- methods[key] = [mdef.kind, ty.screen_name(@scratch)]
179
+ methods[key] = [mdef.kind, ty.screen_name(@scratch), ty.include_untyped?(@scratch)]
173
180
  end
174
181
  when TypedMethodDef
175
182
  if mdef.rbs_source
@@ -336,14 +343,22 @@ module TypeProf
336
343
  type, (method_name, hidden) = key
337
344
  case type
338
345
  when :attr
339
- kind, ty = *arg
340
- lines << (indent + " attr_#{ kind } #{ method_name }#{ hidden ? "()" : "" }: #{ ty }")
346
+ kind, ty, untyped = *arg
347
+ exclude = Config.options[:exclude_untyped] && untyped ? "#" : " " # XXX
348
+ lines << (indent + "#{ exclude } attr_#{ kind } #{ method_name }#{ hidden ? "()" : "" }: #{ ty }")
341
349
  when :rbs
342
350
  sigs = arg.sort.join("\n" + indent + "#" + " " * (method_name.size + 5) + "| ")
343
351
  lines << (indent + "# def #{ method_name }: #{ sigs }")
344
352
  when :iseq
345
- sigs = arg.sort.join("\n" + indent + " " * (method_name.size + 6) + "| ")
346
- lines << (indent + " def #{ method_name }: #{ sigs }")
353
+ sigs = []
354
+ untyped = false
355
+ arg.each do |sig, untyped0|
356
+ sigs << sig
357
+ untyped ||= untyped0
358
+ end
359
+ sigs = sigs.sort.join("\n" + indent + " " * (method_name.size + 6) + "| ")
360
+ exclude = Config.options[:exclude_untyped] && untyped ? "#" : " " # XXX
361
+ lines << (indent + "#{ exclude } def #{ method_name }: #{ sigs }")
347
362
  when :alias
348
363
  orig_name = arg
349
364
  lines << (indent + " alias #{ method_name } #{ orig_name }")
@@ -3,6 +3,10 @@ require "rbs"
3
3
  module TypeProf
4
4
  class RBSReader
5
5
  def initialize
6
+ @repo = RBS::Repository.new
7
+ Config.gem_repo_dirs.each do |dir|
8
+ @repo.add(Pathname(dir))
9
+ end
6
10
  @env, @builtin_env_json = RBSReader.get_builtin_env
7
11
  end
8
12
 
@@ -11,7 +15,7 @@ module TypeProf
11
15
  unless @builtin_env
12
16
  @builtin_env = RBS::Environment.new
13
17
 
14
- loader = RBS::EnvironmentLoader.new
18
+ loader = RBS::EnvironmentLoader.new(repository: @repo)
15
19
  new_decls = loader.load(env: @builtin_env).map {|decl,| decl }
16
20
  @builtin_env_json = load_rbs(@builtin_env, new_decls)
17
21
  end
@@ -24,22 +28,30 @@ module TypeProf
24
28
  end
25
29
 
26
30
  def load_library(lib)
27
- loader = RBS::EnvironmentLoader.new(core_root: nil)
31
+ loader = RBS::EnvironmentLoader.new(core_root: nil, repository: @repo)
28
32
  loader.add(library: lib)
29
33
 
30
34
  case lib
35
+ when 'bigdecimal-math'
36
+ loader.add(library: 'bigdecimal')
31
37
  when "yaml"
32
38
  loader.add(library: "pstore")
33
39
  loader.add(library: "dbm")
40
+ when "logger"
41
+ loader.add(library: "monitor")
42
+ when "csv"
43
+ loader.add(library: "forwardable")
44
+ when "prime"
45
+ loader.add(library: "singleton")
34
46
  end
35
47
 
36
48
  new_decls = loader.load(env: @env).map {|decl,| decl }
37
49
  RBSReader.load_rbs(@env, new_decls)
38
50
  end
39
51
 
40
- def load_path(path)
41
- loader = RBS::EnvironmentLoader.new(core_root: nil)
42
- loader.add(path: path)
52
+ def load_paths(paths)
53
+ loader = RBS::EnvironmentLoader.new(core_root: nil, repository: @repo)
54
+ paths.each {|path| loader.add(path: path) }
43
55
  new_decls = loader.load(env: @env).map {|decl,| decl }
44
56
  RBSReader.load_rbs(@env, new_decls)
45
57
  end
@@ -69,6 +81,7 @@ module TypeProf
69
81
  class RBS2JSON
70
82
  def initialize(all_env, cur_env)
71
83
  @all_env, @cur_env = all_env, cur_env
84
+ @alias_resolution_stack = {}
72
85
  end
73
86
 
74
87
  def dump_json
@@ -176,11 +189,15 @@ module TypeProf
176
189
  when RBS::AST::Members::Include
177
190
  name = member.name
178
191
  if name.kind == :class
192
+ # including a module
179
193
  mod = conv_type_name(name)
180
194
  type_args = member.args.map {|type| conv_type(type) }
181
195
  modules[:include] << [mod, type_args]
182
196
  else
183
- # including an interface is not supported yet
197
+ # including an interface
198
+ mod = conv_type_name(name)
199
+ type_args = member.args.map {|type| conv_type(type) }
200
+ modules[:include] << [mod, type_args]
184
201
  end
185
202
 
186
203
  when RBS::AST::Members::Extend
@@ -424,8 +441,17 @@ module TypeProf
424
441
  raise NotImplementedError
425
442
  end
426
443
  when RBS::Types::Alias
427
- alias_decl = @all_env.alias_decls[ty.name]
428
- alias_decl ? conv_type(alias_decl.decl.type) : [:any]
444
+ if @alias_resolution_stack[ty.name]
445
+ [:any]
446
+ else
447
+ begin
448
+ @alias_resolution_stack[ty.name] = true
449
+ alias_decl = @all_env.alias_decls[ty.name]
450
+ alias_decl ? conv_type(alias_decl.decl.type) : [:any]
451
+ ensure
452
+ @alias_resolution_stack.delete(ty.name)
453
+ end
454
+ end
429
455
  when RBS::Types::Union
430
456
  [:union, ty.types.map {|ty2| conv_type(ty2) }.compact]
431
457
  when RBS::Types::Optional
@@ -472,9 +498,9 @@ module TypeProf
472
498
  Import.new(scratch, json).import
473
499
  end
474
500
 
475
- def self.import_rbs_file(scratch, rbs_path)
476
- rbs_path = Pathname(rbs_path) unless rbs_path.is_a?(Pathname)
477
- Import.new(scratch, scratch.rbs_reader.load_path(rbs_path)).import(true)
501
+ def self.import_rbs_files(scratch, rbs_paths)
502
+ rbs_paths = rbs_paths.map {|rbs_path| Pathname(rbs_path) }
503
+ Import.new(scratch, scratch.rbs_reader.load_paths(rbs_paths)).import(true)
478
504
  end
479
505
 
480
506
  def self.import_rbs_code(scratch, rbs_name, rbs_code)