typeprof 0.8.0 → 0.11.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 (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