typeprof 0.9.0 → 0.12.0

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.
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