typeprof 0.8.0 → 0.11.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (298) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +6 -5
  3. data/doc/demo.md +1 -1
  4. data/doc/todo.md +133 -0
  5. data/lib/typeprof/analyzer.rb +177 -76
  6. data/lib/typeprof/arguments.rb +2 -0
  7. data/lib/typeprof/block.rb +40 -2
  8. data/lib/typeprof/builtin.rb +279 -111
  9. data/lib/typeprof/cli.rb +5 -0
  10. data/lib/typeprof/config.rb +15 -1
  11. data/lib/typeprof/container-type.rb +5 -4
  12. data/lib/typeprof/export.rb +115 -70
  13. data/lib/typeprof/import.rb +71 -33
  14. data/lib/typeprof/iseq.rb +46 -11
  15. data/lib/typeprof/method.rb +42 -21
  16. data/lib/typeprof/type.rb +93 -15
  17. data/lib/typeprof/version.rb +1 -1
  18. data/smoke/alias.rb +4 -4
  19. data/smoke/alias2.rb +6 -4
  20. data/smoke/any1.rb +1 -1
  21. data/smoke/any2.rb +2 -2
  22. data/smoke/arguments.rb +2 -2
  23. data/smoke/arguments2.rb +10 -10
  24. data/smoke/array-each.rb +1 -1
  25. data/smoke/array-each2.rb +1 -1
  26. data/smoke/array-each3.rb +1 -1
  27. data/smoke/array-ltlt.rb +1 -1
  28. data/smoke/array-ltlt2.rb +1 -1
  29. data/smoke/array-map.rb +1 -1
  30. data/smoke/array-map2.rb +1 -1
  31. data/smoke/array-map3.rb +3 -3
  32. data/smoke/array-mul.rb +2 -2
  33. data/smoke/array-plus1.rb +1 -1
  34. data/smoke/array-plus2.rb +3 -2
  35. data/smoke/array-pop.rb +1 -1
  36. data/smoke/array-range-aref.rb +11 -11
  37. data/smoke/array-replace.rb +1 -1
  38. data/smoke/array-s-aref.rb +1 -1
  39. data/smoke/array1.rb +5 -5
  40. data/smoke/array10.rb +1 -1
  41. data/smoke/array11.rb +1 -1
  42. data/smoke/array12.rb +3 -3
  43. data/smoke/array13.rb +4 -4
  44. data/smoke/array14.rb +1 -1
  45. data/smoke/array15.rb +16 -0
  46. data/smoke/array2.rb +3 -3
  47. data/smoke/array3.rb +5 -4
  48. data/smoke/array4.rb +1 -1
  49. data/smoke/array5.rb +1 -1
  50. data/smoke/array6.rb +3 -2
  51. data/smoke/array7.rb +1 -1
  52. data/smoke/array8.rb +1 -1
  53. data/smoke/array9.rb +1 -1
  54. data/smoke/attr-module.rb +27 -0
  55. data/smoke/attr-vis.rb +43 -0
  56. data/smoke/attr-vis.rbs +4 -0
  57. data/smoke/attr.rb +5 -5
  58. data/smoke/autoload.rb +1 -1
  59. data/smoke/backtrace.rb +3 -3
  60. data/smoke/block-ambiguous.rb +8 -8
  61. data/smoke/block-args1-rest.rb +12 -11
  62. data/smoke/block-args1.rb +10 -10
  63. data/smoke/block-args2-rest.rb +12 -11
  64. data/smoke/block-args2.rb +10 -10
  65. data/smoke/block-args3-rest.rb +14 -13
  66. data/smoke/block-args3.rb +12 -12
  67. data/smoke/block-blockarg.rb +4 -4
  68. data/smoke/block-kwarg.rb +10 -10
  69. data/smoke/block1.rb +1 -1
  70. data/smoke/block10.rb +1 -1
  71. data/smoke/block11.rb +5 -5
  72. data/smoke/block12.rb +2 -2
  73. data/smoke/block14.rb +2 -2
  74. data/smoke/block2.rb +1 -1
  75. data/smoke/block3.rb +3 -3
  76. data/smoke/block4.rb +2 -2
  77. data/smoke/block5.rb +3 -2
  78. data/smoke/block6.rb +2 -2
  79. data/smoke/block7.rb +1 -1
  80. data/smoke/block8.rb +3 -3
  81. data/smoke/block9.rb +1 -1
  82. data/smoke/block_given.rb +37 -0
  83. data/smoke/blown.rb +1 -1
  84. data/smoke/break1.rb +2 -2
  85. data/smoke/break2.rb +1 -1
  86. data/smoke/break3.rb +13 -0
  87. data/smoke/case.rb +1 -1
  88. data/smoke/case2.rb +1 -1
  89. data/smoke/case3.rb +17 -0
  90. data/smoke/class-hierarchy.rb +5 -5
  91. data/smoke/class-hierarchy2.rb +3 -3
  92. data/smoke/class-new.rb +15 -0
  93. data/smoke/class_instance_var.rb +1 -1
  94. data/smoke/class_method.rb +2 -2
  95. data/smoke/class_method2.rb +2 -2
  96. data/smoke/class_method3.rb +2 -2
  97. data/smoke/constant1.rb +6 -6
  98. data/smoke/constant2.rb +5 -4
  99. data/smoke/constant3.rb +1 -1
  100. data/smoke/constant4.rb +1 -1
  101. data/smoke/context-sensitive1.rb +1 -1
  102. data/smoke/cvar.rb +6 -5
  103. data/smoke/cvar2.rb +2 -2
  104. data/smoke/define_method.rb +2 -2
  105. data/smoke/define_method2.rb +2 -2
  106. data/smoke/define_method3.rb +14 -0
  107. data/smoke/define_method3.rbs +3 -0
  108. data/smoke/define_method4.rb +15 -0
  109. data/smoke/define_method4.rbs +3 -0
  110. data/smoke/define_method5.rb +12 -0
  111. data/smoke/define_method6.rb +19 -0
  112. data/smoke/demo.rb +6 -6
  113. data/smoke/demo1.rb +1 -1
  114. data/smoke/demo10.rb +2 -2
  115. data/smoke/demo11.rb +1 -1
  116. data/smoke/demo2.rb +1 -1
  117. data/smoke/demo3.rb +1 -1
  118. data/smoke/demo4.rb +3 -3
  119. data/smoke/demo5.rb +1 -1
  120. data/smoke/demo6.rb +4 -3
  121. data/smoke/demo7.rb +1 -1
  122. data/smoke/demo8.rb +2 -2
  123. data/smoke/demo9.rb +3 -2
  124. data/smoke/dummy-execution1.rb +2 -2
  125. data/smoke/dummy-execution2.rb +2 -2
  126. data/smoke/dummy_element.rb +14 -0
  127. data/smoke/ensure1.rb +2 -2
  128. data/smoke/enum_for.rb +15 -0
  129. data/smoke/enum_for2.rb +17 -0
  130. data/smoke/enumerator.rb +2 -2
  131. data/smoke/expandarray1.rb +1 -1
  132. data/smoke/expandarray2.rb +1 -1
  133. data/smoke/fib.rb +2 -2
  134. data/smoke/flip-flop.rb +28 -0
  135. data/smoke/flow1.rb +1 -1
  136. data/smoke/flow10.rb +17 -0
  137. data/smoke/flow2.rb +1 -1
  138. data/smoke/flow3.rb +1 -1
  139. data/smoke/flow5.rb +1 -1
  140. data/smoke/flow6.rb +1 -1
  141. data/smoke/flow7.rb +1 -1
  142. data/smoke/flow8.rb +1 -1
  143. data/smoke/flow9.rb +12 -0
  144. data/smoke/freeze.rb +1 -1
  145. data/smoke/function.rb +2 -2
  146. data/smoke/gvar.rb +2 -2
  147. data/smoke/gvar2.rb +3 -3
  148. data/smoke/hash-bot.rb +12 -0
  149. data/smoke/hash-fetch.rb +3 -3
  150. data/smoke/hash-merge-bang.rb +1 -1
  151. data/smoke/hash1.rb +2 -2
  152. data/smoke/hash2.rb +1 -1
  153. data/smoke/hash3.rb +1 -1
  154. data/smoke/hash4.rb +1 -1
  155. data/smoke/hash5.rb +1 -1
  156. data/smoke/inheritance.rb +4 -4
  157. data/smoke/inheritance2.rb +2 -2
  158. data/smoke/initialize.rb +6 -5
  159. data/smoke/instance_eval.rb +2 -2
  160. data/smoke/instance_eval2.rb +10 -0
  161. data/smoke/instance_eval3.rb +25 -0
  162. data/smoke/int_times.rb +1 -1
  163. data/smoke/integer.rb +1 -1
  164. data/smoke/ivar.rb +5 -4
  165. data/smoke/ivar2.rb +4 -4
  166. data/smoke/ivar3.rb +4 -3
  167. data/smoke/ivar4.rb +21 -0
  168. data/smoke/kernel-class.rb +1 -1
  169. data/smoke/keyword1.rb +1 -1
  170. data/smoke/keyword2.rb +1 -1
  171. data/smoke/keyword3.rb +1 -1
  172. data/smoke/keyword4.rb +1 -1
  173. data/smoke/keyword5.rb +1 -1
  174. data/smoke/kwrest.rb +3 -2
  175. data/smoke/kwsplat1.rb +4 -4
  176. data/smoke/kwsplat2.rb +1 -1
  177. data/smoke/lit-complex.rb +10 -0
  178. data/smoke/lit-encoding.rb +10 -0
  179. data/smoke/manual-rbs.rb +5 -4
  180. data/smoke/manual-rbs2.rb +1 -1
  181. data/smoke/manual-rbs3.rb +3 -2
  182. data/smoke/masgn1.rb +1 -1
  183. data/smoke/masgn2.rb +2 -2
  184. data/smoke/masgn3.rb +1 -1
  185. data/smoke/method_in_branch.rb +3 -3
  186. data/smoke/method_missing.rb +5 -4
  187. data/smoke/module1.rb +2 -2
  188. data/smoke/module2.rb +1 -1
  189. data/smoke/module3.rb +3 -3
  190. data/smoke/module4.rb +3 -2
  191. data/smoke/module5.rb +17 -0
  192. data/smoke/module6.rb +40 -0
  193. data/smoke/module_function1.rb +4 -3
  194. data/smoke/module_function2.rb +4 -3
  195. data/smoke/multiple-include.rb +2 -1
  196. data/smoke/multiple-superclass.rb +1 -1
  197. data/smoke/next1.rb +2 -2
  198. data/smoke/next2.rb +1 -1
  199. data/smoke/object-send1.rb +3 -3
  200. data/smoke/object-send2.rb +10 -0
  201. data/smoke/object-send3.rb +18 -0
  202. data/smoke/once.rb +1 -1
  203. data/smoke/optional1.rb +1 -1
  204. data/smoke/optional2.rb +1 -1
  205. data/smoke/optional3.rb +1 -1
  206. data/smoke/parameterizedd-self.rb +3 -2
  207. data/smoke/parameterizedd-self2.rb +1 -1
  208. data/smoke/pathname1.rb +1 -1
  209. data/smoke/pathname2.rb +1 -1
  210. data/smoke/pattern-match1.rb +1 -1
  211. data/smoke/pattern-match2.rb +1 -1
  212. data/smoke/prepend1.rb +33 -0
  213. data/smoke/prepend2.rb +10 -0
  214. data/smoke/prepend2.rbs +9 -0
  215. data/smoke/primitive_method.rb +19 -0
  216. data/smoke/printf.rb +2 -2
  217. data/smoke/proc.rb +2 -2
  218. data/smoke/proc2.rb +1 -1
  219. data/smoke/proc3.rb +1 -1
  220. data/smoke/proc4.rb +1 -1
  221. data/smoke/proc5.rb +19 -0
  222. data/smoke/public.rb +38 -0
  223. data/smoke/range.rb +1 -1
  224. data/smoke/rbs-alias.rb +1 -1
  225. data/smoke/rbs-attr.rb +5 -5
  226. data/smoke/rbs-attr2.rb +1 -1
  227. data/smoke/rbs-extend.rb +1 -1
  228. data/smoke/rbs-interface.rb +4 -4
  229. data/smoke/rbs-module.rb +26 -0
  230. data/smoke/rbs-module.rbs +4 -0
  231. data/smoke/rbs-opt-and-rest.rb +10 -0
  232. data/smoke/rbs-opt-and-rest.rbs +3 -0
  233. data/smoke/rbs-proc1.rb +1 -1
  234. data/smoke/rbs-proc2.rb +2 -2
  235. data/smoke/rbs-proc3.rb +1 -1
  236. data/smoke/rbs-record.rb +2 -2
  237. data/smoke/rbs-tyvar.rb +2 -2
  238. data/smoke/rbs-tyvar2.rb +2 -2
  239. data/smoke/rbs-tyvar3.rb +2 -2
  240. data/smoke/rbs-tyvar4.rb +4 -3
  241. data/smoke/rbs-tyvar5.rb +1 -1
  242. data/smoke/rbs-tyvar6.rb +3 -3
  243. data/smoke/rbs-tyvar7.rb +1 -1
  244. data/smoke/rbs-vars.rb +6 -6
  245. data/smoke/redo1.rb +2 -2
  246. data/smoke/redo2.rb +2 -2
  247. data/smoke/req-keyword.rb +1 -1
  248. data/smoke/rescue1.rb +2 -2
  249. data/smoke/rescue2.rb +2 -2
  250. data/smoke/rescue3.rb +20 -0
  251. data/smoke/rescue4.rb +17 -0
  252. data/smoke/respond_to.rb +1 -1
  253. data/smoke/rest-farg.rb +1 -1
  254. data/smoke/rest1.rb +2 -2
  255. data/smoke/rest2.rb +1 -1
  256. data/smoke/rest3.rb +6 -6
  257. data/smoke/rest4.rb +2 -2
  258. data/smoke/rest5.rb +1 -1
  259. data/smoke/rest6.rb +1 -1
  260. data/smoke/retry1.rb +2 -2
  261. data/smoke/return.rb +1 -1
  262. data/smoke/simple.rb +12 -0
  263. data/smoke/singleton_method.rb +1 -1
  264. data/smoke/step.rb +3 -3
  265. data/smoke/string-split.rb +1 -1
  266. data/smoke/struct-keyword_init.rb +10 -0
  267. data/smoke/struct.rb +1 -1
  268. data/smoke/struct2.rb +4 -4
  269. data/smoke/struct3.rb +2 -2
  270. data/smoke/struct4.rb +7 -0
  271. data/smoke/struct5.rb +16 -0
  272. data/smoke/struct6.rb +15 -0
  273. data/smoke/struct7.rb +17 -0
  274. data/smoke/stub-keyword.rb +10 -0
  275. data/smoke/super1.rb +4 -4
  276. data/smoke/super2.rb +1 -1
  277. data/smoke/super3.rb +4 -3
  278. data/smoke/super4.rb +7 -5
  279. data/smoke/super5.rb +6 -4
  280. data/smoke/svar1.rb +1 -1
  281. data/smoke/symbol-proc-attr.rb +22 -0
  282. data/smoke/symbol-proc-attr2.rb +15 -0
  283. data/smoke/symbol-proc-bot.rb +13 -0
  284. data/smoke/symbol-proc.rb +3 -3
  285. data/smoke/tap1.rb +2 -2
  286. data/smoke/toplevel.rb +1 -1
  287. data/smoke/two-map.rb +2 -2
  288. data/smoke/type_var.rb +3 -3
  289. data/smoke/typed_method.rb +1 -1
  290. data/smoke/uninitialize-var.rb +1 -1
  291. data/smoke/union-recv.rb +2 -2
  292. data/smoke/user-demo.rb +3 -3
  293. data/smoke/wrong-extend.rb +3 -2
  294. data/smoke/wrong-include.rb +3 -2
  295. data/smoke/wrong-include2.rb +17 -0
  296. data/typeprof.gemspec +1 -1
  297. metadata +59 -6
  298. data/tools/stackprof-wrapper.rb +0 -10
@@ -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:"
@@ -48,6 +50,8 @@ module TypeProf
48
50
  end
49
51
  opt.on("--[no-]show-errors", "Display possible errors found during the analysis") {|v| options[:show_errors] = v }
50
52
  opt.on("--[no-]show-untyped", "Display \"Foo | untyped\" instead of \"Foo\"") {|v| options[:show_untyped] = v }
53
+ opt.on("--[no-]show-parameter-names", "Display parameter names for methods") {|v| options[:show_parameter_names] = v }
54
+ opt.on("--[no-]show-source-locations", "Display definition source locations for methods") {|v| options[:show_source_locations] = v }
51
55
 
52
56
  opt.separator ""
53
57
  opt.separator "Analysis limit options:"
@@ -85,6 +89,7 @@ module TypeProf
85
89
  rbs_files: rbs_files,
86
90
  output: output,
87
91
  gem_rbs_features: gem_rbs_features,
92
+ gem_repo_dirs: gem_repo_dirs,
88
93
  verbose: verbose,
89
94
  dir_filter: dir_filter,
90
95
  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,
@@ -14,10 +15,18 @@ module TypeProf
14
15
  keyword_init: true
15
16
  )
16
17
 
18
+ class TypeProfError < StandardError
19
+ def report(output)
20
+ output.puts "# Analysis Error"
21
+ output.puts message
22
+ end
23
+ end
24
+
17
25
  class ConfigData
18
26
  def initialize(**opt)
19
27
  opt[:output] ||= $stdout
20
28
  opt[:gem_rbs_features] ||= []
29
+ opt[:gem_repo_dirs] ||= []
21
30
  opt[:dir_filter] ||= DEFAULT_DIR_FILTER
22
31
  opt[:verbose] ||= 0
23
32
  opt[:options] ||= {}
@@ -25,6 +34,8 @@ module TypeProf
25
34
  show_indicator: true,
26
35
  show_untyped: false,
27
36
  show_errors: false,
37
+ show_parameter_names: true,
38
+ show_source_locations: false,
28
39
  stub_execution: true,
29
40
  type_depth_limit: 5,
30
41
  stackprof: nil,
@@ -69,7 +80,7 @@ module TypeProf
69
80
 
70
81
  prologue_ctx = Context.new(nil, nil, nil)
71
82
  prologue_ep = ExecutionPoint.new(prologue_ctx, -1, nil)
72
- prologue_env = Env.new(StaticEnv.new(:top, Type.nil, false, true), [], [], Utils::HashWrapper.new({}))
83
+ prologue_env = Env.new(StaticEnv.new(Type.bot, Type.nil, false, true), [], [], Utils::HashWrapper.new({}))
73
84
 
74
85
  Config.rb_files.each do |rb|
75
86
  if rb.is_a?(Array) # [String name, String content]
@@ -100,6 +111,9 @@ module TypeProf
100
111
  end
101
112
  end
102
113
 
114
+ rescue TypeProfError => exc
115
+ exc.report(Config.output)
116
+
103
117
  ensure
104
118
  if Config.options[:stackprof] && defined?(StackProf)
105
119
  StackProf.stop
@@ -208,10 +208,6 @@ module TypeProf
208
208
  @base_type = base_type
209
209
  end
210
210
 
211
- def self.dummy_elements
212
- Elements.new([], Type.any)
213
- end
214
-
215
211
  attr_reader :elems, :base_type
216
212
 
217
213
  def inspect
@@ -264,6 +260,10 @@ module TypeProf
264
260
  @lead_tys, @rest_ty = lead_tys, rest_ty
265
261
  end
266
262
 
263
+ def self.dummy_elements
264
+ Elements.new([], Type.any)
265
+ end
266
+
267
267
  attr_reader :lead_tys, :rest_ty
268
268
 
269
269
  def to_local_type(id, base_ty)
@@ -796,6 +796,7 @@ module TypeProf
796
796
  class Local < ContainerType
797
797
  def initialize(kind, id, base_type)
798
798
  @kind = kind
799
+ raise if @kind != Cell && @kind != Array && @kind != Hash
799
800
  @id = id
800
801
  raise unless base_type
801
802
  @base_type = base_type
@@ -72,7 +72,7 @@ module TypeProf
72
72
  gvars.dump.each do |gvar_name, entry|
73
73
  next if entry.type == Type.bot
74
74
  s = entry.rbs_declared ? "#" : ""
75
- output.puts s + "#{ gvar_name } : #{ entry.type.screen_name(scratch) }"
75
+ output.puts s + "#{ gvar_name }: #{ entry.type.screen_name(scratch) }"
76
76
  end
77
77
  output.puts
78
78
  end
@@ -105,19 +105,20 @@ module TypeProf
105
105
  consts[name] = ty.screen_name(@scratch)
106
106
  end
107
107
 
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)
108
+ modules = class_def.modules.to_h do |kind, mods|
109
+ mods = mods.to_h do |singleton, mods|
110
+ mods = mods.filter_map do |mod_def, _type_args, absolute_paths|
111
+ next if absolute_paths.all? {|path| !path || Config.check_dir_filter(path) == :exclude }
112
+ Type::Instance.new(mod_def.klass_obj).screen_name(@scratch)
113
+ end
114
+ [singleton, mods]
115
+ end
116
+ [kind, mods]
116
117
  end
117
118
 
118
- explicit_methods = {}
119
- iseq_methods = {}
120
- attr_methods = {}
119
+ visibilities = {}
120
+ source_locations = {}
121
+ methods = {}
121
122
  ivars = class_def.ivars.dump
122
123
  cvars = class_def.cvars.dump
123
124
 
@@ -135,29 +136,47 @@ module TypeProf
135
136
  method_name = ctx.mid
136
137
  method_name = "self.#{ method_name }" if singleton
137
138
 
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)
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
+ when AliasMethodDef
145
+ alias_name, orig_name = mid, mdef.orig_mid
146
+ if singleton
147
+ alias_name = "self.#{ alias_name }"
148
+ orig_name = "self.#{ orig_name }"
141
149
  end
150
+ key = [:alias, alias_name]
151
+ visibilities[key] ||= mdef.pub_meth
152
+ source_locations[key] ||= mdef.def_ep&.source_location
153
+ methods[key] = orig_name
142
154
  when AttrMethodDef
143
- next if !mdef.absolute_path || Config.check_dir_filter(mdef.absolute_path) == :exclude
155
+ next if !mdef.def_ep
156
+ absolute_path = mdef.def_ep.ctx.iseq.absolute_path
157
+ next if !absolute_path || Config.check_dir_filter(absolute_path) == :exclude
144
158
  mid = mid.to_s[0..-2].to_sym if mid.to_s.end_with?("=")
145
159
  method_name = mid
146
160
  method_name = "self.#{ mid }" if singleton
147
161
  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
162
+ key = [:attr, method_name]
163
+ visibilities[key] ||= mdef.pub_meth
164
+ source_locations[key] ||= mdef.def_ep.source_location
165
+ if methods[key]
166
+ if methods[key][0] != mdef.kind
167
+ methods[key][0] = :accessor
151
168
  end
152
169
  else
153
170
  entry = ivars[[singleton, mdef.ivar]]
154
171
  ty = entry ? entry.type : Type.any
155
- attr_methods[method_name] = [mdef.kind, ty.screen_name(@scratch)]
172
+ methods[key] = [mdef.kind, ty.screen_name(@scratch)]
156
173
  end
157
174
  when TypedMethodDef
158
175
  if mdef.rbs_source
159
176
  method_name, sigs = mdef.rbs_source
160
- explicit_methods[method_name] = sigs
177
+ key = [:rbs, method_name]
178
+ methods[key] = sigs
179
+ visibilities[key] ||= mdef.pub_meth
161
180
  end
162
181
  end
163
182
  end
@@ -168,7 +187,7 @@ module TypeProf
168
187
  ty = entry.type
169
188
  next unless var.to_s.start_with?("@")
170
189
  var = "self.#{ var }" if singleton
171
- next if attr_methods[[singleton ? "self.#{ var.to_s[1..] }" : var.to_s[1..].to_sym, false]]
190
+ next if methods[[:attr, [singleton ? "self.#{ var.to_s[1..] }" : var.to_s[1..].to_sym, false]]]
172
191
  next if entry.rbs_declared
173
192
  [var, ty.screen_name(@scratch)]
174
193
  end.compact
@@ -180,7 +199,9 @@ module TypeProf
180
199
  end.compact
181
200
 
182
201
  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?
202
+ if methods.keys.all? {|type,| type == :rbs }
203
+ 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?
204
+ end
184
205
  end
185
206
 
186
207
  @scratch.namespace = nil
@@ -190,18 +211,17 @@ module TypeProf
190
211
  name: class_def.name,
191
212
  superclass: superclass,
192
213
  consts: consts,
193
- included_mods: included_mods,
194
- extended_mods: extended_mods,
214
+ modules: modules,
195
215
  ivars: ivars,
196
216
  cvars: cvars,
197
- attr_methods: attr_methods,
198
- explicit_methods: explicit_methods,
199
- iseq_methods: iseq_methods,
217
+ methods: methods,
218
+ visibilities: visibilities,
219
+ source_locations: source_locations,
200
220
  inner_classes: inner_classes,
201
221
  )
202
222
  end
203
223
 
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)
224
+ ClassData = Struct.new(:kind, :name, :superclass, :consts, :modules, :ivars, :cvars, :methods, :visibilities, :source_locations, :inner_classes, keyword_init: true)
205
225
 
206
226
  def show(stat_eps, output)
207
227
  # make the class hierarchy
@@ -218,7 +238,16 @@ module TypeProf
218
238
 
219
239
  output.puts "# Classes" # and Modules
220
240
 
221
- show_class_hierarchy(0, hierarchy, output, true)
241
+ prev_nil = true
242
+ show_class_hierarchy(0, hierarchy).each do |line|
243
+ if line == nil
244
+ output.puts line unless prev_nil
245
+ prev_nil = true
246
+ else
247
+ output.puts line
248
+ prev_nil = false
249
+ end
250
+ end
222
251
 
223
252
  if ENV["TP_STAT"]
224
253
  output.puts ""
@@ -246,13 +275,13 @@ module TypeProf
246
275
  end.compact
247
276
  end
248
277
 
249
- def show_class_hierarchy(depth, hierarchy, output, first)
278
+ def show_class_hierarchy(depth, hierarchy)
279
+ lines = []
250
280
  hierarchy.each do |class_data|
251
- output.puts unless first
252
- first = false
253
-
254
- show_class_data(depth, class_data, output)
281
+ lines << nil
282
+ lines.concat show_class_data(depth, class_data)
255
283
  end
284
+ lines
256
285
  end
257
286
 
258
287
  def show_const(namespace, path)
@@ -262,53 +291,69 @@ module TypeProf
262
291
  path[i..].join("::")
263
292
  end
264
293
 
265
- def show_class_data(depth, class_data, output)
294
+ def show_class_data(depth, class_data)
266
295
  indent = " " * depth
267
296
  name = class_data.name.last
268
297
  superclass = " < " + class_data.superclass if class_data.superclass
269
- output.puts indent + "#{ class_data.kind } #{ name }#{ superclass }"
270
- first = true
298
+ first_line = indent + "#{ class_data.kind } #{ name }#{ superclass }"
299
+ lines = []
271
300
  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
301
+ lines << (indent + " #{ name }: #{ ty }")
278
302
  end
279
- class_data.extended_mods.sort.each do |mod|
280
- output.puts indent + " extend #{ mod }"
281
- first = false
303
+ class_data.modules.each do |kind, mods|
304
+ mods.each do |singleton, mods|
305
+ case
306
+ when kind == :before && singleton then directive = nil
307
+ when kind == :before && !singleton then directive = "prepend"
308
+ when kind == :after && singleton then directive = "extend"
309
+ when kind == :after && !singleton then directive = "include"
310
+ end
311
+ mods.each do |mod|
312
+ lines << (indent + " #{ directive } #{ mod }") if directive
313
+ end
314
+ end
282
315
  end
283
316
  class_data.ivars.each do |var, ty|
284
- output.puts indent + " #{ var } : #{ ty }" unless var.start_with?("_")
285
- first = false
317
+ lines << (indent + " #{ var }: #{ ty }") unless var.start_with?("_")
286
318
  end
287
319
  class_data.cvars.each do |var, ty|
288
- output.puts indent + " #{ var } : #{ ty }"
289
- first = false
320
+ lines << (indent + " #{ var }: #{ ty }")
290
321
  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
322
+ lines << nil
323
+ prev_vis = true
324
+ class_data.methods.each do |key, arg|
325
+ vis = class_data.visibilities[key]
326
+ if prev_vis != vis
327
+ lines << nil
328
+ lines << (indent + " #{ vis ? "public" : "private" }")
329
+ prev_vis = vis
330
+ end
331
+ source_location = class_data.source_locations[key]
332
+ if Config.options[:show_source_locations] && source_location
333
+ lines << nil
334
+ lines << (indent + " # #{ source_location }")
335
+ end
336
+ type, (method_name, hidden) = key
337
+ case type
338
+ when :attr
339
+ kind, ty = *arg
340
+ lines << (indent + " attr_#{ kind } #{ method_name }#{ hidden ? "()" : "" }: #{ ty }")
341
+ when :rbs
342
+ sigs = arg.sort.join("\n" + indent + "#" + " " * (method_name.size + 5) + "| ")
343
+ lines << (indent + "# def #{ method_name }: #{ sigs }")
344
+ when :iseq
345
+ sigs = arg.sort.join("\n" + indent + " " * (method_name.size + 6) + "| ")
346
+ lines << (indent + " def #{ method_name }: #{ sigs }")
347
+ when :alias
348
+ orig_name = arg
349
+ lines << (indent + " alias #{ method_name } #{ orig_name }")
306
350
  end
307
- output.puts indent + " def #{ method_name } : #{ sigs }"
308
- first = false
309
351
  end
310
- show_class_hierarchy(depth + 1, class_data.inner_classes, output, first)
311
- output.puts indent + "end"
352
+ lines.concat show_class_hierarchy(depth + 1, class_data.inner_classes)
353
+ lines.shift until lines.empty? || lines.first
354
+ lines.pop until lines.empty? || lines.last
355
+ lines.unshift first_line
356
+ lines << (indent + "end")
312
357
  end
313
358
  end
314
359
  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,14 +28,21 @@ 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)
33
+
34
+ case lib
35
+ when "yaml"
36
+ loader.add(library: "pstore")
37
+ loader.add(library: "dbm")
38
+ end
39
+
29
40
  new_decls = loader.load(env: @env).map {|decl,| decl }
30
41
  RBSReader.load_rbs(@env, new_decls)
31
42
  end
32
43
 
33
44
  def load_path(path)
34
- loader = RBS::EnvironmentLoader.new(core_root: nil)
45
+ loader = RBS::EnvironmentLoader.new(core_root: nil, repository: @repo)
35
46
  loader.add(path: path)
36
47
  new_decls = loader.load(env: @env).map {|decl,| decl }
37
48
  RBSReader.load_rbs(@env, new_decls)
@@ -109,13 +120,13 @@ module TypeProf
109
120
  end
110
121
 
111
122
  type_params = nil
112
- included_modules = []
113
- extended_modules = []
123
+ modules = { include: [], extend: [], prepend: [] }
114
124
  methods = {}
115
125
  attr_methods = {}
116
126
  ivars = {}
117
127
  cvars = {}
118
128
  rbs_sources = {}
129
+ visibility = true
119
130
 
120
131
  decls.each do |decl|
121
132
  decl = decl.decl
@@ -136,7 +147,7 @@ module TypeProf
136
147
  end
137
148
  end
138
149
 
139
- method_def = conv_method_def(method_types)
150
+ method_def = conv_method_def(method_types, visibility)
140
151
  rbs_source = [(member.kind == :singleton ? "self." : "") + member.name.to_s, member.types.map {|type| type.location.source }]
141
152
  if member.instance?
142
153
  methods[[false, name]] = method_def
@@ -148,13 +159,13 @@ module TypeProf
148
159
  end
149
160
  when RBS::AST::Members::AttrReader
150
161
  ty = conv_type(member.type)
151
- attr_methods[[false, member.name]] = attr_method_def(:reader, member.name, ty)
162
+ attr_methods[[false, member.name]] = attr_method_def(:reader, member.name, ty, visibility)
152
163
  when RBS::AST::Members::AttrWriter
153
164
  ty = conv_type(member.type)
154
- attr_methods[[false, member.name]] = attr_method_def(:writer, member.name, ty)
165
+ attr_methods[[false, member.name]] = attr_method_def(:writer, member.name, ty, visibility)
155
166
  when RBS::AST::Members::AttrAccessor
156
167
  ty = conv_type(member.type)
157
- attr_methods[[false, member.name]] = attr_method_def(:accessor, member.name, ty)
168
+ attr_methods[[false, member.name]] = attr_method_def(:accessor, member.name, ty, visibility)
158
169
  when RBS::AST::Members::Alias
159
170
  # XXX: an alias to attr methods?
160
171
  if member.instance?
@@ -171,7 +182,7 @@ module TypeProf
171
182
  if name.kind == :class
172
183
  mod = conv_type_name(name)
173
184
  type_args = member.args.map {|type| conv_type(type) }
174
- included_modules << [mod, type_args]
185
+ modules[:include] << [mod, type_args]
175
186
  else
176
187
  # including an interface is not supported yet
177
188
  end
@@ -181,7 +192,17 @@ module TypeProf
181
192
  if name.kind == :class
182
193
  mod = conv_type_name(name)
183
194
  type_args = member.args.map {|type| conv_type(type) }
184
- extended_modules << [mod, type_args]
195
+ modules[:extend] << [mod, type_args]
196
+ else
197
+ # extending a module with an interface is not supported yet
198
+ end
199
+
200
+ when RBS::AST::Members::Prepend
201
+ name = member.name
202
+ if name.kind == :class
203
+ mod = conv_type_name(name)
204
+ type_args = member.args.map {|type| conv_type(type) }
205
+ modules[:prepend] << [mod, type_args]
185
206
  else
186
207
  # extending a module with an interface is not supported yet
187
208
  end
@@ -191,7 +212,10 @@ module TypeProf
191
212
  when RBS::AST::Members::ClassVariable
192
213
  cvars[member.name] = conv_type(member.type)
193
214
 
194
- when RBS::AST::Members::Public, RBS::AST::Members::Private # XXX
215
+ when RBS::AST::Members::Public
216
+ visibility = true
217
+ when RBS::AST::Members::Private
218
+ visibility = false
195
219
 
196
220
  # The following declarations are ignoreable because they are handled in other level
197
221
  when RBS::AST::Declarations::Constant
@@ -209,8 +233,7 @@ module TypeProf
209
233
  type_params: type_params,
210
234
  superclass: superclass,
211
235
  members: {
212
- included_modules: included_modules,
213
- extended_modules: extended_modules,
236
+ modules: modules,
214
237
  methods: methods,
215
238
  attr_methods: attr_methods,
216
239
  ivars: ivars,
@@ -263,8 +286,11 @@ module TypeProf
263
286
  end
264
287
  return if decl.name == RBS::BuiltinNames::BasicObject.name
265
288
  return if decl.name == name
266
- @all_env.class_decls[name].decls.each do |decl|
267
- each_reference(decl.decl, &blk)
289
+ decls = @all_env.class_decls[name]
290
+ if decls
291
+ decls.decls.each do |decl|
292
+ each_reference(decl.decl, &blk)
293
+ end
268
294
  end
269
295
  end
270
296
 
@@ -287,10 +313,14 @@ module TypeProf
287
313
  return RBS::BuiltinNames::Object.name, []
288
314
  end
289
315
 
290
- def conv_method_def(rbs_method_types)
291
- rbs_method_types.map do |method_type|
316
+ def conv_method_def(rbs_method_types, visibility)
317
+ sig_rets = rbs_method_types.map do |method_type|
292
318
  conv_func(method_type.type_params, method_type.type, method_type.block)
293
319
  end
320
+ {
321
+ sig_rets: sig_rets,
322
+ visibility: visibility,
323
+ }
294
324
  end
295
325
 
296
326
  def conv_func(type_params, func, block)
@@ -320,11 +350,12 @@ module TypeProf
320
350
  }
321
351
  end
322
352
 
323
- def attr_method_def(kind, name, ty)
353
+ def attr_method_def(kind, name, ty, visibility)
324
354
  {
325
355
  kind: kind,
326
356
  ivar: name,
327
357
  ty: ty,
358
+ visibility: visibility,
328
359
  }
329
360
  end
330
361
 
@@ -438,6 +469,8 @@ module TypeProf
438
469
  json = scratch.rbs_reader.load_library(feature)
439
470
  rescue RBS::EnvironmentLoader::UnknownLibraryError
440
471
  return nil
472
+ rescue RBS::DuplicatedDeclarationError
473
+ return true
441
474
  end
442
475
  # need cache?
443
476
  Import.new(scratch, json).import
@@ -490,22 +523,25 @@ module TypeProf
490
523
 
491
524
  classes.each do |klass, superclass_type_args, members|
492
525
  @scratch.add_superclass_type_args!(klass, superclass_type_args&.map {|ty| conv_type(ty) })
493
- included_modules = members[:included_modules]
494
- extended_modules = members[:extended_modules]
526
+ modules = members[:modules]
495
527
  methods = members[:methods]
496
528
  attr_methods = members[:attr_methods]
497
529
  ivars = members[:ivars]
498
530
  cvars = members[:cvars]
499
531
  rbs_sources = members[:rbs_sources]
500
532
 
501
- included_modules.each do |mod, type_args|
502
- type_args = type_args&.map {|ty| conv_type(ty) }
503
- @scratch.include_module(klass, path_to_klass(mod), type_args, false, nil)
504
- end
505
-
506
- extended_modules.each do |mod, type_args|
507
- type_args = type_args&.map {|ty| conv_type(ty) }
508
- @scratch.include_module(klass, path_to_klass(mod), type_args, true, nil)
533
+ modules.each do |kind, mods|
534
+ mods.each do |mod, type_args|
535
+ type_args = type_args&.map {|ty| conv_type(ty) }
536
+ case kind
537
+ when :include
538
+ @scratch.mix_module(:after, klass, path_to_klass(mod), type_args, false, nil)
539
+ when :extend
540
+ @scratch.mix_module(:after, klass, path_to_klass(mod), type_args, true, nil)
541
+ when :prepend
542
+ @scratch.mix_module(:before, klass, path_to_klass(mod), type_args, false, nil)
543
+ end
544
+ end
509
545
  end
510
546
 
511
547
  methods.each do |(singleton, method_name), mdef|
@@ -518,7 +554,7 @@ module TypeProf
518
554
  kind = mdef[:kind]
519
555
  ivar = mdef[:ivar]
520
556
  ty = conv_type(mdef[:ty]).remove_type_vars
521
- @scratch.add_attr_method(klass, nil, ivar, :"@#{ ivar }", kind)
557
+ @scratch.add_attr_method(klass, ivar, :"@#{ ivar }", kind, mdef[:visibility], nil)
522
558
  @scratch.add_ivar_write!(Type::Instance.new(klass), :"@#{ ivar }", ty, nil)
523
559
  end
524
560
 
@@ -548,11 +584,11 @@ module TypeProf
548
584
  end
549
585
 
550
586
  def conv_method_def(method_name, mdef, rbs_source)
551
- sig_rets = mdef.flat_map do |sig_ret|
587
+ sig_rets = mdef[:sig_rets].flat_map do |sig_ret|
552
588
  conv_func(sig_ret)
553
589
  end
554
590
 
555
- TypedMethodDef.new(sig_rets, rbs_source)
591
+ TypedMethodDef.new(sig_rets, rbs_source, mdef[:visibility])
556
592
  end
557
593
 
558
594
  def conv_func(sig_ret)
@@ -652,7 +688,9 @@ module TypeProf
652
688
  klass = Type::Builtin[:obj]
653
689
  path.each do |name|
654
690
  klass = @scratch.get_constant(klass, name)
655
- raise path.inspect if klass == Type.any
691
+ if klass == Type.any
692
+ raise TypeProfError.new("A constant `#{ path.join("::") }' is used but not defined in RBS")
693
+ end
656
694
  end
657
695
  klass
658
696
  end