typeprof 0.9.0 → 0.12.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (182) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/main.yml +1 -1
  3. data/Gemfile.lock +6 -5
  4. data/doc/demo.md +2 -2
  5. data/doc/todo.md +133 -0
  6. data/lib/typeprof/analyzer.rb +89 -37
  7. data/lib/typeprof/block.rb +34 -0
  8. data/lib/typeprof/builtin.rb +169 -66
  9. data/lib/typeprof/cli.rb +7 -0
  10. data/lib/typeprof/config.rb +25 -3
  11. data/lib/typeprof/container-type.rb +24 -0
  12. data/lib/typeprof/export.rb +130 -69
  13. data/lib/typeprof/import.rb +82 -38
  14. data/lib/typeprof/iseq.rb +23 -4
  15. data/lib/typeprof/method.rb +29 -7
  16. data/lib/typeprof/type.rb +75 -13
  17. data/lib/typeprof/version.rb +1 -1
  18. data/smoke/alias.rb +4 -4
  19. data/smoke/alias2.rb +3 -1
  20. data/smoke/arguments.rb +2 -2
  21. data/smoke/arguments2.rb +5 -5
  22. data/smoke/array-each.rb +1 -1
  23. data/smoke/array-each3.rb +1 -1
  24. data/smoke/array-map.rb +1 -1
  25. data/smoke/array-map2.rb +1 -1
  26. data/smoke/array-map3.rb +3 -3
  27. data/smoke/array-mul.rb +2 -2
  28. data/smoke/array-plus1.rb +1 -1
  29. data/smoke/array-plus2.rb +1 -0
  30. data/smoke/array-range-aref.rb +11 -11
  31. data/smoke/array-replace.rb +1 -1
  32. data/smoke/array1.rb +5 -5
  33. data/smoke/array10.rb +1 -1
  34. data/smoke/array11.rb +1 -1
  35. data/smoke/array12.rb +1 -1
  36. data/smoke/array14.rb +1 -1
  37. data/smoke/array15.rb +1 -1
  38. data/smoke/array2.rb +2 -2
  39. data/smoke/array3.rb +1 -0
  40. data/smoke/array6.rb +2 -1
  41. data/smoke/array8.rb +1 -1
  42. data/smoke/array9.rb +1 -1
  43. data/smoke/attr-module.rb +1 -0
  44. data/smoke/attr-vis.rb +43 -0
  45. data/smoke/attr-vis.rbs +4 -0
  46. data/smoke/attr.rb +2 -2
  47. data/smoke/block-ambiguous.rb +4 -4
  48. data/smoke/block-args1-rest.rb +6 -5
  49. data/smoke/block-args1.rb +5 -5
  50. data/smoke/block-args2-rest.rb +6 -5
  51. data/smoke/block-args2.rb +5 -5
  52. data/smoke/block-args3-rest.rb +7 -6
  53. data/smoke/block-args3.rb +6 -6
  54. data/smoke/block-blockarg.rb +3 -3
  55. data/smoke/block-kwarg.rb +4 -4
  56. data/smoke/block1.rb +1 -1
  57. data/smoke/block10.rb +1 -1
  58. data/smoke/block11.rb +2 -2
  59. data/smoke/block2.rb +1 -1
  60. data/smoke/block3.rb +1 -1
  61. data/smoke/block5.rb +1 -0
  62. data/smoke/block_given.rb +37 -0
  63. data/smoke/class_method.rb +2 -2
  64. data/smoke/class_method2.rb +2 -2
  65. data/smoke/constant2.rb +3 -2
  66. data/smoke/context-sensitive1.rb +1 -1
  67. data/smoke/cvar.rb +3 -2
  68. data/smoke/define_method.rb +2 -2
  69. data/smoke/define_method3.rb +1 -0
  70. data/smoke/define_method4.rb +1 -1
  71. data/smoke/define_method6.rb +19 -0
  72. data/smoke/demo.rb +6 -6
  73. data/smoke/demo1.rb +1 -1
  74. data/smoke/demo11.rb +1 -1
  75. data/smoke/demo2.rb +1 -1
  76. data/smoke/demo3.rb +1 -1
  77. data/smoke/demo4.rb +3 -3
  78. data/smoke/demo5.rb +1 -1
  79. data/smoke/demo6.rb +2 -1
  80. data/smoke/demo7.rb +1 -1
  81. data/smoke/demo9.rb +1 -0
  82. data/smoke/dummy-execution1.rb +1 -1
  83. data/smoke/dummy-execution2.rb +1 -1
  84. data/smoke/dummy_element.rb +1 -1
  85. data/smoke/ensure1.rb +1 -1
  86. data/smoke/enum_for.rb +15 -0
  87. data/smoke/enum_for2.rb +17 -0
  88. data/smoke/fib.rb +2 -2
  89. data/smoke/flow1.rb +1 -1
  90. data/smoke/flow10.rb +17 -0
  91. data/smoke/flow2.rb +1 -1
  92. data/smoke/flow3.rb +1 -1
  93. data/smoke/flow5.rb +1 -1
  94. data/smoke/flow6.rb +1 -1
  95. data/smoke/flow7.rb +1 -1
  96. data/smoke/flow8.rb +1 -1
  97. data/smoke/flow9.rb +1 -1
  98. data/smoke/function.rb +1 -1
  99. data/smoke/gvar.rb +1 -1
  100. data/smoke/gvar2.rb +1 -1
  101. data/smoke/hash-fetch.rb +3 -3
  102. data/smoke/inheritance.rb +4 -4
  103. data/smoke/initialize.rb +3 -2
  104. data/smoke/instance_eval.rb +1 -1
  105. data/smoke/int_times.rb +1 -1
  106. data/smoke/integer.rb +1 -1
  107. data/smoke/ivar.rb +3 -2
  108. data/smoke/ivar2.rb +2 -2
  109. data/smoke/ivar3.rb +2 -1
  110. data/smoke/ivar4.rb +21 -0
  111. data/smoke/kernel-class.rb +1 -1
  112. data/smoke/keyword4.rb +1 -1
  113. data/smoke/kwrest.rb +1 -0
  114. data/smoke/kwsplat1.rb +2 -2
  115. data/smoke/kwsplat2.rb +1 -1
  116. data/smoke/manual-rbs.rb +2 -1
  117. data/smoke/manual-rbs3.rb +1 -0
  118. data/smoke/method_in_branch.rb +1 -1
  119. data/smoke/method_missing.rb +4 -3
  120. data/smoke/module3.rb +1 -1
  121. data/smoke/module4.rb +1 -0
  122. data/smoke/module5.rb +1 -1
  123. data/smoke/module_function1.rb +3 -2
  124. data/smoke/module_function2.rb +3 -2
  125. data/smoke/multiple-include.rb +1 -0
  126. data/smoke/next1.rb +1 -1
  127. data/smoke/object-send1.rb +3 -3
  128. data/smoke/optional1.rb +1 -1
  129. data/smoke/optional2.rb +1 -1
  130. data/smoke/optional3.rb +1 -1
  131. data/smoke/parameterizedd-self.rb +2 -1
  132. data/smoke/prepend1.rb +33 -0
  133. data/smoke/prepend2.rb +10 -0
  134. data/smoke/prepend2.rbs +9 -0
  135. data/smoke/primitive_method.rb +19 -0
  136. data/smoke/proc4.rb +1 -1
  137. data/smoke/public.rb +4 -0
  138. data/smoke/range.rb +1 -1
  139. data/smoke/rbs-attr.rb +2 -2
  140. data/smoke/rbs-proc2.rb +1 -1
  141. data/smoke/rbs-proc3.rb +1 -1
  142. data/smoke/rbs-tyvar4.rb +3 -2
  143. data/smoke/rbs-tyvar6.rb +3 -3
  144. data/smoke/redo1.rb +1 -1
  145. data/smoke/redo2.rb +1 -1
  146. data/smoke/rescue1.rb +1 -1
  147. data/smoke/rescue2.rb +1 -1
  148. data/smoke/rescue3.rb +1 -0
  149. data/smoke/rescue4.rb +1 -1
  150. data/smoke/respond_to.rb +1 -1
  151. data/smoke/rest1.rb +2 -2
  152. data/smoke/rest2.rb +1 -1
  153. data/smoke/rest3.rb +6 -6
  154. data/smoke/rest4.rb +2 -2
  155. data/smoke/rest5.rb +1 -1
  156. data/smoke/rest6.rb +1 -1
  157. data/smoke/retry1.rb +2 -2
  158. data/smoke/simple.rb +12 -0
  159. data/smoke/step.rb +3 -3
  160. data/smoke/struct-keyword_init.rb +6 -16
  161. data/smoke/struct.rb +1 -1
  162. data/smoke/struct2.rb +1 -1
  163. data/smoke/struct3.rb +1 -1
  164. data/smoke/struct4.rb +1 -1
  165. data/smoke/struct5.rb +2 -2
  166. data/smoke/struct6.rb +2 -2
  167. data/smoke/struct7.rb +1 -1
  168. data/smoke/super1.rb +4 -4
  169. data/smoke/super3.rb +3 -2
  170. data/smoke/super4.rb +7 -5
  171. data/smoke/super5.rb +6 -4
  172. data/smoke/symbol-proc-attr.rb +1 -1
  173. data/smoke/tap1.rb +2 -2
  174. data/smoke/toplevel.rb +1 -1
  175. data/smoke/type_var.rb +3 -3
  176. data/smoke/user-demo.rb +1 -1
  177. data/smoke/wrong-extend.rb +1 -0
  178. data/smoke/wrong-include.rb +1 -0
  179. data/smoke/wrong-include2.rb +1 -1
  180. data/testbed/goodcheck-Gemfile.lock +1 -1
  181. data/typeprof.gemspec +1 -1
  182. metadata +19 -5
@@ -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
@@ -105,19 +113,20 @@ module TypeProf
105
113
  consts[name] = ty.screen_name(@scratch)
106
114
  end
107
115
 
108
- included_mods = class_def.modules[false].filter_map do |mod_def, _type_args, absolute_paths|
109
- next if absolute_paths.all? {|path| !path || Config.check_dir_filter(path) == :exclude }
110
- Type::Instance.new(mod_def.klass_obj).screen_name(@scratch)
111
- end
112
-
113
- extended_mods = class_def.modules[true].filter_map do |mod_def, _type_args, absolute_paths|
114
- next if absolute_paths.all? {|path| !path || Config.check_dir_filter(path) == :exclude }
115
- Type::Instance.new(mod_def.klass_obj).screen_name(@scratch)
116
+ modules = class_def.modules.to_h do |kind, mods|
117
+ mods = mods.to_h do |singleton, mods|
118
+ mods = mods.filter_map do |mod_def, _type_args, absolute_paths|
119
+ next if absolute_paths.all? {|path| !path || Config.check_dir_filter(path) == :exclude }
120
+ Type::Instance.new(mod_def.klass_obj).screen_name(@scratch)
121
+ end
122
+ [singleton, mods]
123
+ end
124
+ [kind, mods]
116
125
  end
117
126
 
118
- explicit_methods = {}
119
- iseq_methods = {}
120
- attr_methods = {}
127
+ visibilities = {}
128
+ source_locations = {}
129
+ methods = {}
121
130
  ivars = class_def.ivars.dump
122
131
  cvars = class_def.cvars.dump
123
132
 
@@ -135,29 +144,47 @@ module TypeProf
135
144
  method_name = ctx.mid
136
145
  method_name = "self.#{ method_name }" if singleton
137
146
 
138
- iseq_methods[method_name] ||= [true, []]
139
- iseq_methods[method_name][0] &&= mdef.pub_meth
140
- iseq_methods[method_name][1] << @scratch.show_method_signature(ctx)
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)
151
+ end
152
+ when AliasMethodDef
153
+ alias_name, orig_name = mid, mdef.orig_mid
154
+ if singleton
155
+ alias_name = "self.#{ alias_name }"
156
+ orig_name = "self.#{ orig_name }"
141
157
  end
158
+ key = [:alias, alias_name]
159
+ visibilities[key] ||= mdef.pub_meth
160
+ source_locations[key] ||= mdef.def_ep&.source_location
161
+ methods[key] = orig_name
142
162
  when AttrMethodDef
143
- next if !mdef.absolute_path || Config.check_dir_filter(mdef.absolute_path) == :exclude
163
+ next if !mdef.def_ep
164
+ absolute_path = mdef.def_ep.ctx.iseq.absolute_path
165
+ next if !absolute_path || Config.check_dir_filter(absolute_path) == :exclude
144
166
  mid = mid.to_s[0..-2].to_sym if mid.to_s.end_with?("=")
145
167
  method_name = mid
146
168
  method_name = "self.#{ mid }" if singleton
147
169
  method_name = [method_name, :"@#{ mid }" != mdef.ivar]
148
- if attr_methods[method_name]
149
- if attr_methods[method_name][0] != mdef.kind
150
- attr_methods[method_name][0] = :accessor
170
+ key = [:attr, method_name]
171
+ visibilities[key] ||= mdef.pub_meth
172
+ source_locations[key] ||= mdef.def_ep.source_location
173
+ if methods[key]
174
+ if methods[key][0] != mdef.kind
175
+ methods[key][0] = :accessor
151
176
  end
152
177
  else
153
178
  entry = ivars[[singleton, mdef.ivar]]
154
179
  ty = entry ? entry.type : Type.any
155
- attr_methods[method_name] = [mdef.kind, ty.screen_name(@scratch)]
180
+ methods[key] = [mdef.kind, ty.screen_name(@scratch), ty.include_untyped?(@scratch)]
156
181
  end
157
182
  when TypedMethodDef
158
183
  if mdef.rbs_source
159
184
  method_name, sigs = mdef.rbs_source
160
- explicit_methods[method_name] = sigs
185
+ key = [:rbs, method_name]
186
+ methods[key] = sigs
187
+ visibilities[key] ||= mdef.pub_meth
161
188
  end
162
189
  end
163
190
  end
@@ -168,7 +195,7 @@ module TypeProf
168
195
  ty = entry.type
169
196
  next unless var.to_s.start_with?("@")
170
197
  var = "self.#{ var }" if singleton
171
- next if attr_methods[[singleton ? "self.#{ var.to_s[1..] }" : var.to_s[1..].to_sym, false]]
198
+ next if methods[[:attr, [singleton ? "self.#{ var.to_s[1..] }" : var.to_s[1..].to_sym, false]]]
172
199
  next if entry.rbs_declared
173
200
  [var, ty.screen_name(@scratch)]
174
201
  end.compact
@@ -180,7 +207,9 @@ module TypeProf
180
207
  end.compact
181
208
 
182
209
  if !class_def.absolute_path || Config.check_dir_filter(class_def.absolute_path) == :exclude
183
- return nil if consts.empty? && included_mods.empty? && extended_mods.empty? && ivars.empty? && cvars.empty? && iseq_methods.empty? && attr_methods.empty? && inner_classes.empty?
210
+ if methods.keys.all? {|type,| type == :rbs }
211
+ return nil if consts.empty? && modules[:before][true].empty? && modules[:before][false].empty? && modules[:after][true].empty? && modules[:after][false].empty? && ivars.empty? && cvars.empty? && inner_classes.empty?
212
+ end
184
213
  end
185
214
 
186
215
  @scratch.namespace = nil
@@ -190,18 +219,17 @@ module TypeProf
190
219
  name: class_def.name,
191
220
  superclass: superclass,
192
221
  consts: consts,
193
- included_mods: included_mods,
194
- extended_mods: extended_mods,
222
+ modules: modules,
195
223
  ivars: ivars,
196
224
  cvars: cvars,
197
- attr_methods: attr_methods,
198
- explicit_methods: explicit_methods,
199
- iseq_methods: iseq_methods,
225
+ methods: methods,
226
+ visibilities: visibilities,
227
+ source_locations: source_locations,
200
228
  inner_classes: inner_classes,
201
229
  )
202
230
  end
203
231
 
204
- ClassData = Struct.new(:kind, :name, :superclass, :consts, :included_mods, :extended_mods, :ivars, :cvars, :attr_methods, :explicit_methods, :iseq_methods, :inner_classes, keyword_init: true)
232
+ ClassData = Struct.new(:kind, :name, :superclass, :consts, :modules, :ivars, :cvars, :methods, :visibilities, :source_locations, :inner_classes, keyword_init: true)
205
233
 
206
234
  def show(stat_eps, output)
207
235
  # make the class hierarchy
@@ -218,7 +246,16 @@ module TypeProf
218
246
 
219
247
  output.puts "# Classes" # and Modules
220
248
 
221
- show_class_hierarchy(0, hierarchy, output, true)
249
+ prev_nil = true
250
+ show_class_hierarchy(0, hierarchy).each do |line|
251
+ if line == nil
252
+ output.puts line unless prev_nil
253
+ prev_nil = true
254
+ else
255
+ output.puts line
256
+ prev_nil = false
257
+ end
258
+ end
222
259
 
223
260
  if ENV["TP_STAT"]
224
261
  output.puts ""
@@ -246,13 +283,13 @@ module TypeProf
246
283
  end.compact
247
284
  end
248
285
 
249
- def show_class_hierarchy(depth, hierarchy, output, first)
286
+ def show_class_hierarchy(depth, hierarchy)
287
+ lines = []
250
288
  hierarchy.each do |class_data|
251
- output.puts unless first
252
- first = false
253
-
254
- show_class_data(depth, class_data, output)
289
+ lines << nil
290
+ lines.concat show_class_data(depth, class_data)
255
291
  end
292
+ lines
256
293
  end
257
294
 
258
295
  def show_const(namespace, path)
@@ -262,53 +299,77 @@ module TypeProf
262
299
  path[i..].join("::")
263
300
  end
264
301
 
265
- def show_class_data(depth, class_data, output)
302
+ def show_class_data(depth, class_data)
266
303
  indent = " " * depth
267
304
  name = class_data.name.last
268
305
  superclass = " < " + class_data.superclass if class_data.superclass
269
- output.puts indent + "#{ class_data.kind } #{ name }#{ superclass }"
270
- first = true
306
+ first_line = indent + "#{ class_data.kind } #{ name }#{ superclass }"
307
+ lines = []
271
308
  class_data.consts.each do |name, ty|
272
- output.puts indent + " #{ name }: #{ ty }"
273
- first = false
274
- end
275
- class_data.included_mods.sort.each do |mod|
276
- output.puts indent + " include #{ mod }"
277
- first = false
309
+ lines << (indent + " #{ name }: #{ ty }")
278
310
  end
279
- class_data.extended_mods.sort.each do |mod|
280
- output.puts indent + " extend #{ mod }"
281
- first = false
311
+ class_data.modules.each do |kind, mods|
312
+ mods.each do |singleton, mods|
313
+ case
314
+ when kind == :before && singleton then directive = nil
315
+ when kind == :before && !singleton then directive = "prepend"
316
+ when kind == :after && singleton then directive = "extend"
317
+ when kind == :after && !singleton then directive = "include"
318
+ end
319
+ mods.each do |mod|
320
+ lines << (indent + " #{ directive } #{ mod }") if directive
321
+ end
322
+ end
282
323
  end
283
324
  class_data.ivars.each do |var, ty|
284
- output.puts indent + " #{ var }: #{ ty }" unless var.start_with?("_")
285
- first = false
325
+ lines << (indent + " #{ var }: #{ ty }") unless var.start_with?("_")
286
326
  end
287
327
  class_data.cvars.each do |var, ty|
288
- output.puts indent + " #{ var }: #{ ty }"
289
- first = false
328
+ lines << (indent + " #{ var }: #{ ty }")
290
329
  end
291
- class_data.attr_methods.each do |(method_name, hidden), (kind, ty)|
292
- output.puts indent + " attr_#{ kind } #{ method_name }#{ hidden ? "()" : "" }: #{ ty }"
293
- first = false
294
- end
295
- class_data.explicit_methods.each do |method_name, sigs|
296
- sigs = sigs.sort.join("\n" + indent + "#" + " " * (method_name.size + 6) + "| ")
297
- output.puts indent + "# def #{ method_name }: #{ sigs }"
298
- first = false
299
- end
300
- prev_pub_meth = true
301
- class_data.iseq_methods.each do |method_name, (pub_meth, sigs)|
302
- sigs = sigs.sort.join("\n" + indent + " " * (method_name.size + 7) + "| ")
303
- if prev_pub_meth != pub_meth
304
- output.puts indent + " #{ pub_meth ? "public" : "private" }"
305
- prev_pub_meth = pub_meth
330
+ lines << nil
331
+ prev_vis = true
332
+ class_data.methods.each do |key, arg|
333
+ vis = class_data.visibilities[key]
334
+ if prev_vis != vis
335
+ lines << nil
336
+ lines << (indent + " #{ vis ? "public" : "private" }")
337
+ prev_vis = vis
338
+ end
339
+ source_location = class_data.source_locations[key]
340
+ if Config.options[:show_source_locations] && source_location
341
+ lines << nil
342
+ lines << (indent + " # #{ source_location }")
343
+ end
344
+ type, (method_name, hidden) = key
345
+ case type
346
+ when :attr
347
+ kind, ty, untyped = *arg
348
+ exclude = Config.options[:exclude_untyped] && untyped ? "#" : " " # XXX
349
+ lines << (indent + "#{ exclude } attr_#{ kind } #{ method_name }#{ hidden ? "()" : "" }: #{ ty }")
350
+ when :rbs
351
+ sigs = arg.sort.join("\n" + indent + "#" + " " * (method_name.size + 5) + "| ")
352
+ lines << (indent + "# def #{ method_name }: #{ sigs }")
353
+ when :iseq
354
+ sigs = []
355
+ untyped = false
356
+ arg.each do |sig, untyped0|
357
+ sigs << sig
358
+ untyped ||= untyped0
359
+ end
360
+ sigs = sigs.sort.join("\n" + indent + " " * (method_name.size + 6) + "| ")
361
+ exclude = Config.options[:exclude_untyped] && untyped ? "#" : " " # XXX
362
+ lines << (indent + "#{ exclude } def #{ method_name }: #{ sigs }")
363
+ when :alias
364
+ orig_name = arg
365
+ lines << (indent + " alias #{ method_name } #{ orig_name }")
306
366
  end
307
- output.puts indent + " def #{ method_name }: #{ sigs }"
308
- first = false
309
367
  end
310
- show_class_hierarchy(depth + 1, class_data.inner_classes, output, first)
311
- output.puts indent + "end"
368
+ lines.concat show_class_hierarchy(depth + 1, class_data.inner_classes)
369
+ lines.shift until lines.empty? || lines.first
370
+ lines.pop until lines.empty? || lines.last
371
+ lines.unshift first_line
372
+ lines << (indent + "end")
312
373
  end
313
374
  end
314
375
  end
@@ -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
@@ -116,13 +129,13 @@ module TypeProf
116
129
  end
117
130
 
118
131
  type_params = nil
119
- included_modules = []
120
- extended_modules = []
132
+ modules = { include: [], extend: [], prepend: [] }
121
133
  methods = {}
122
134
  attr_methods = {}
123
135
  ivars = {}
124
136
  cvars = {}
125
137
  rbs_sources = {}
138
+ visibility = true
126
139
 
127
140
  decls.each do |decl|
128
141
  decl = decl.decl
@@ -143,7 +156,7 @@ module TypeProf
143
156
  end
144
157
  end
145
158
 
146
- method_def = conv_method_def(method_types)
159
+ method_def = conv_method_def(method_types, visibility)
147
160
  rbs_source = [(member.kind == :singleton ? "self." : "") + member.name.to_s, member.types.map {|type| type.location.source }]
148
161
  if member.instance?
149
162
  methods[[false, name]] = method_def
@@ -155,13 +168,13 @@ module TypeProf
155
168
  end
156
169
  when RBS::AST::Members::AttrReader
157
170
  ty = conv_type(member.type)
158
- attr_methods[[false, member.name]] = attr_method_def(:reader, member.name, ty)
171
+ attr_methods[[false, member.name]] = attr_method_def(:reader, member.name, ty, visibility)
159
172
  when RBS::AST::Members::AttrWriter
160
173
  ty = conv_type(member.type)
161
- attr_methods[[false, member.name]] = attr_method_def(:writer, member.name, ty)
174
+ attr_methods[[false, member.name]] = attr_method_def(:writer, member.name, ty, visibility)
162
175
  when RBS::AST::Members::AttrAccessor
163
176
  ty = conv_type(member.type)
164
- attr_methods[[false, member.name]] = attr_method_def(:accessor, member.name, ty)
177
+ attr_methods[[false, member.name]] = attr_method_def(:accessor, member.name, ty, visibility)
165
178
  when RBS::AST::Members::Alias
166
179
  # XXX: an alias to attr methods?
167
180
  if member.instance?
@@ -178,7 +191,7 @@ module TypeProf
178
191
  if name.kind == :class
179
192
  mod = conv_type_name(name)
180
193
  type_args = member.args.map {|type| conv_type(type) }
181
- included_modules << [mod, type_args]
194
+ modules[:include] << [mod, type_args]
182
195
  else
183
196
  # including an interface is not supported yet
184
197
  end
@@ -188,7 +201,17 @@ module TypeProf
188
201
  if name.kind == :class
189
202
  mod = conv_type_name(name)
190
203
  type_args = member.args.map {|type| conv_type(type) }
191
- extended_modules << [mod, type_args]
204
+ modules[:extend] << [mod, type_args]
205
+ else
206
+ # extending a module with an interface is not supported yet
207
+ end
208
+
209
+ when RBS::AST::Members::Prepend
210
+ name = member.name
211
+ if name.kind == :class
212
+ mod = conv_type_name(name)
213
+ type_args = member.args.map {|type| conv_type(type) }
214
+ modules[:prepend] << [mod, type_args]
192
215
  else
193
216
  # extending a module with an interface is not supported yet
194
217
  end
@@ -198,7 +221,10 @@ module TypeProf
198
221
  when RBS::AST::Members::ClassVariable
199
222
  cvars[member.name] = conv_type(member.type)
200
223
 
201
- when RBS::AST::Members::Public, RBS::AST::Members::Private # XXX
224
+ when RBS::AST::Members::Public
225
+ visibility = true
226
+ when RBS::AST::Members::Private
227
+ visibility = false
202
228
 
203
229
  # The following declarations are ignoreable because they are handled in other level
204
230
  when RBS::AST::Declarations::Constant
@@ -216,8 +242,7 @@ module TypeProf
216
242
  type_params: type_params,
217
243
  superclass: superclass,
218
244
  members: {
219
- included_modules: included_modules,
220
- extended_modules: extended_modules,
245
+ modules: modules,
221
246
  methods: methods,
222
247
  attr_methods: attr_methods,
223
248
  ivars: ivars,
@@ -297,10 +322,14 @@ module TypeProf
297
322
  return RBS::BuiltinNames::Object.name, []
298
323
  end
299
324
 
300
- def conv_method_def(rbs_method_types)
301
- rbs_method_types.map do |method_type|
325
+ def conv_method_def(rbs_method_types, visibility)
326
+ sig_rets = rbs_method_types.map do |method_type|
302
327
  conv_func(method_type.type_params, method_type.type, method_type.block)
303
328
  end
329
+ {
330
+ sig_rets: sig_rets,
331
+ visibility: visibility,
332
+ }
304
333
  end
305
334
 
306
335
  def conv_func(type_params, func, block)
@@ -330,11 +359,12 @@ module TypeProf
330
359
  }
331
360
  end
332
361
 
333
- def attr_method_def(kind, name, ty)
362
+ def attr_method_def(kind, name, ty, visibility)
334
363
  {
335
364
  kind: kind,
336
365
  ivar: name,
337
366
  ty: ty,
367
+ visibility: visibility,
338
368
  }
339
369
  end
340
370
 
@@ -407,8 +437,17 @@ module TypeProf
407
437
  raise NotImplementedError
408
438
  end
409
439
  when RBS::Types::Alias
410
- alias_decl = @all_env.alias_decls[ty.name]
411
- alias_decl ? conv_type(alias_decl.decl.type) : [:any]
440
+ if @alias_resolution_stack[ty.name]
441
+ [:any]
442
+ else
443
+ begin
444
+ @alias_resolution_stack[ty.name] = true
445
+ alias_decl = @all_env.alias_decls[ty.name]
446
+ alias_decl ? conv_type(alias_decl.decl.type) : [:any]
447
+ ensure
448
+ @alias_resolution_stack.delete(ty.name)
449
+ end
450
+ end
412
451
  when RBS::Types::Union
413
452
  [:union, ty.types.map {|ty2| conv_type(ty2) }.compact]
414
453
  when RBS::Types::Optional
@@ -455,9 +494,9 @@ module TypeProf
455
494
  Import.new(scratch, json).import
456
495
  end
457
496
 
458
- def self.import_rbs_file(scratch, rbs_path)
459
- rbs_path = Pathname(rbs_path) unless rbs_path.is_a?(Pathname)
460
- Import.new(scratch, scratch.rbs_reader.load_path(rbs_path)).import(true)
497
+ def self.import_rbs_files(scratch, rbs_paths)
498
+ rbs_paths = rbs_paths.map {|rbs_path| Pathname(rbs_path) }
499
+ Import.new(scratch, scratch.rbs_reader.load_paths(rbs_paths)).import(true)
461
500
  end
462
501
 
463
502
  def self.import_rbs_code(scratch, rbs_name, rbs_code)
@@ -502,22 +541,25 @@ module TypeProf
502
541
 
503
542
  classes.each do |klass, superclass_type_args, members|
504
543
  @scratch.add_superclass_type_args!(klass, superclass_type_args&.map {|ty| conv_type(ty) })
505
- included_modules = members[:included_modules]
506
- extended_modules = members[:extended_modules]
544
+ modules = members[:modules]
507
545
  methods = members[:methods]
508
546
  attr_methods = members[:attr_methods]
509
547
  ivars = members[:ivars]
510
548
  cvars = members[:cvars]
511
549
  rbs_sources = members[:rbs_sources]
512
550
 
513
- included_modules.each do |mod, type_args|
514
- type_args = type_args&.map {|ty| conv_type(ty) }
515
- @scratch.include_module(klass, path_to_klass(mod), type_args, false, nil)
516
- end
517
-
518
- extended_modules.each do |mod, type_args|
519
- type_args = type_args&.map {|ty| conv_type(ty) }
520
- @scratch.include_module(klass, path_to_klass(mod), type_args, true, nil)
551
+ modules.each do |kind, mods|
552
+ mods.each do |mod, type_args|
553
+ type_args = type_args&.map {|ty| conv_type(ty) }
554
+ case kind
555
+ when :include
556
+ @scratch.mix_module(:after, klass, path_to_klass(mod), type_args, false, nil)
557
+ when :extend
558
+ @scratch.mix_module(:after, klass, path_to_klass(mod), type_args, true, nil)
559
+ when :prepend
560
+ @scratch.mix_module(:before, klass, path_to_klass(mod), type_args, false, nil)
561
+ end
562
+ end
521
563
  end
522
564
 
523
565
  methods.each do |(singleton, method_name), mdef|
@@ -530,7 +572,7 @@ module TypeProf
530
572
  kind = mdef[:kind]
531
573
  ivar = mdef[:ivar]
532
574
  ty = conv_type(mdef[:ty]).remove_type_vars
533
- @scratch.add_attr_method(klass, nil, ivar, :"@#{ ivar }", kind)
575
+ @scratch.add_attr_method(klass, ivar, :"@#{ ivar }", kind, mdef[:visibility], nil)
534
576
  @scratch.add_ivar_write!(Type::Instance.new(klass), :"@#{ ivar }", ty, nil)
535
577
  end
536
578
 
@@ -560,11 +602,11 @@ module TypeProf
560
602
  end
561
603
 
562
604
  def conv_method_def(method_name, mdef, rbs_source)
563
- sig_rets = mdef.flat_map do |sig_ret|
605
+ sig_rets = mdef[:sig_rets].flat_map do |sig_ret|
564
606
  conv_func(sig_ret)
565
607
  end
566
608
 
567
- TypedMethodDef.new(sig_rets, rbs_source)
609
+ TypedMethodDef.new(sig_rets, rbs_source, mdef[:visibility])
568
610
  end
569
611
 
570
612
  def conv_func(sig_ret)
@@ -664,7 +706,9 @@ module TypeProf
664
706
  klass = Type::Builtin[:obj]
665
707
  path.each do |name|
666
708
  klass = @scratch.get_constant(klass, name)
667
- raise path.inspect if klass == Type.any
709
+ if klass == Type.any
710
+ raise TypeProfError.new("A constant `#{ path.join("::") }' is used but not defined in RBS")
711
+ end
668
712
  end
669
713
  klass
670
714
  end