typeprof 0.15.1 → 0.20.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (365) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/main.yml +1 -1
  3. data/Gemfile.lock +4 -4
  4. data/doc/ide.md +81 -0
  5. data/doc/typeprof-for-ide-log.png +0 -0
  6. data/doc/typeprof-for-ide.png +0 -0
  7. data/exe/typeprof +5 -1
  8. data/lib/typeprof/analyzer.rb +234 -55
  9. data/lib/typeprof/arguments.rb +1 -0
  10. data/lib/typeprof/builtin.rb +23 -23
  11. data/lib/typeprof/cli.rb +23 -5
  12. data/lib/typeprof/code-range.rb +177 -0
  13. data/lib/typeprof/config.rb +41 -20
  14. data/lib/typeprof/container-type.rb +10 -1
  15. data/lib/typeprof/export.rb +199 -20
  16. data/lib/typeprof/import.rb +38 -9
  17. data/lib/typeprof/iseq.rb +223 -16
  18. data/lib/typeprof/lsp.rb +884 -0
  19. data/lib/typeprof/method.rb +15 -11
  20. data/lib/typeprof/type.rb +46 -38
  21. data/lib/typeprof/utils.rb +18 -1
  22. data/lib/typeprof/version.rb +1 -1
  23. data/lib/typeprof.rb +3 -5
  24. data/typeprof-lsp +3 -0
  25. data/typeprof.gemspec +2 -2
  26. data/vscode/.gitignore +5 -0
  27. data/vscode/.vscode/launch.json +16 -0
  28. data/vscode/.vscodeignore +7 -0
  29. data/vscode/README.md +22 -0
  30. data/vscode/development.md +31 -0
  31. data/vscode/package-lock.json +2211 -0
  32. data/vscode/package.json +71 -0
  33. data/vscode/sandbox/test.rb +24 -0
  34. data/vscode/src/extension.ts +285 -0
  35. data/vscode/tsconfig.json +15 -0
  36. metadata +21 -334
  37. data/smoke/alias.rb +0 -31
  38. data/smoke/alias2.rb +0 -21
  39. data/smoke/any-cbase.rb +0 -5
  40. data/smoke/any1.rb +0 -16
  41. data/smoke/any2.rb +0 -18
  42. data/smoke/arguments.rb +0 -17
  43. data/smoke/arguments2.rb +0 -56
  44. data/smoke/array-each.rb +0 -15
  45. data/smoke/array-each2.rb +0 -16
  46. data/smoke/array-each3.rb +0 -13
  47. data/smoke/array-ltlt.rb +0 -14
  48. data/smoke/array-ltlt2.rb +0 -17
  49. data/smoke/array-map.rb +0 -12
  50. data/smoke/array-map2.rb +0 -11
  51. data/smoke/array-map3.rb +0 -23
  52. data/smoke/array-mul.rb +0 -18
  53. data/smoke/array-plus1.rb +0 -11
  54. data/smoke/array-plus2.rb +0 -16
  55. data/smoke/array-pop.rb +0 -12
  56. data/smoke/array-range-aref.rb +0 -71
  57. data/smoke/array-replace.rb +0 -13
  58. data/smoke/array-s-aref.rb +0 -12
  59. data/smoke/array1.rb +0 -27
  60. data/smoke/array10.rb +0 -15
  61. data/smoke/array11.rb +0 -14
  62. data/smoke/array12.rb +0 -25
  63. data/smoke/array13.rb +0 -31
  64. data/smoke/array14.rb +0 -14
  65. data/smoke/array15.rb +0 -16
  66. data/smoke/array2.rb +0 -28
  67. data/smoke/array3.rb +0 -26
  68. data/smoke/array4.rb +0 -15
  69. data/smoke/array5.rb +0 -14
  70. data/smoke/array6.rb +0 -17
  71. data/smoke/array7.rb +0 -14
  72. data/smoke/array8.rb +0 -13
  73. data/smoke/array9.rb +0 -13
  74. data/smoke/attr-module.rb +0 -24
  75. data/smoke/attr-vis.rb +0 -43
  76. data/smoke/attr-vis.rbs +0 -4
  77. data/smoke/attr.rb +0 -28
  78. data/smoke/autoload.rb +0 -14
  79. data/smoke/backtrace.rb +0 -33
  80. data/smoke/block-ambiguous.rb +0 -37
  81. data/smoke/block-args1-rest.rb +0 -64
  82. data/smoke/block-args1.rb +0 -60
  83. data/smoke/block-args2-rest.rb +0 -64
  84. data/smoke/block-args2.rb +0 -60
  85. data/smoke/block-args3-rest.rb +0 -75
  86. data/smoke/block-args3.rb +0 -71
  87. data/smoke/block-blockarg.rb +0 -28
  88. data/smoke/block-kwarg.rb +0 -53
  89. data/smoke/block1.rb +0 -23
  90. data/smoke/block10.rb +0 -15
  91. data/smoke/block11.rb +0 -40
  92. data/smoke/block12.rb +0 -23
  93. data/smoke/block13.rb +0 -9
  94. data/smoke/block13.rbs +0 -3
  95. data/smoke/block14.rb +0 -18
  96. data/smoke/block2.rb +0 -15
  97. data/smoke/block3.rb +0 -38
  98. data/smoke/block4.rb +0 -19
  99. data/smoke/block5.rb +0 -21
  100. data/smoke/block6.rb +0 -21
  101. data/smoke/block7.rb +0 -19
  102. data/smoke/block8.rb +0 -28
  103. data/smoke/block9.rb +0 -13
  104. data/smoke/block_given.rb +0 -37
  105. data/smoke/blown.rb +0 -13
  106. data/smoke/break1.rb +0 -19
  107. data/smoke/break2.rb +0 -16
  108. data/smoke/break3.rb +0 -13
  109. data/smoke/break4.rb +0 -17
  110. data/smoke/case.rb +0 -17
  111. data/smoke/case2.rb +0 -18
  112. data/smoke/case3.rb +0 -17
  113. data/smoke/class-hierarchy.rb +0 -54
  114. data/smoke/class-hierarchy2.rb +0 -27
  115. data/smoke/class-new.rb +0 -15
  116. data/smoke/class.rb +0 -7
  117. data/smoke/class_eval.rb +0 -22
  118. data/smoke/class_instance_var.rb +0 -9
  119. data/smoke/class_method.rb +0 -25
  120. data/smoke/class_method2.rb +0 -21
  121. data/smoke/class_method3.rb +0 -29
  122. data/smoke/constant1.rb +0 -46
  123. data/smoke/constant2.rb +0 -36
  124. data/smoke/constant3.rb +0 -10
  125. data/smoke/constant4.rb +0 -12
  126. data/smoke/context-sensitive1.rb +0 -13
  127. data/smoke/cvar.rb +0 -31
  128. data/smoke/cvar2.rb +0 -17
  129. data/smoke/define_method.rb +0 -16
  130. data/smoke/define_method2.rb +0 -18
  131. data/smoke/define_method3.rb +0 -14
  132. data/smoke/define_method3.rbs +0 -3
  133. data/smoke/define_method4.rb +0 -15
  134. data/smoke/define_method4.rbs +0 -3
  135. data/smoke/define_method5.rb +0 -12
  136. data/smoke/define_method6.rb +0 -19
  137. data/smoke/define_method7.rb +0 -18
  138. data/smoke/demo.rb +0 -81
  139. data/smoke/demo1.rb +0 -17
  140. data/smoke/demo10.rb +0 -21
  141. data/smoke/demo11.rb +0 -12
  142. data/smoke/demo2.rb +0 -15
  143. data/smoke/demo3.rb +0 -17
  144. data/smoke/demo4.rb +0 -27
  145. data/smoke/demo5.rb +0 -16
  146. data/smoke/demo6.rb +0 -22
  147. data/smoke/demo7.rb +0 -15
  148. data/smoke/demo8.rb +0 -19
  149. data/smoke/demo9.rb +0 -18
  150. data/smoke/dummy-execution1.rb +0 -15
  151. data/smoke/dummy-execution2.rb +0 -16
  152. data/smoke/dummy_element.rb +0 -14
  153. data/smoke/ensure1.rb +0 -21
  154. data/smoke/enum_for.rb +0 -15
  155. data/smoke/enum_for2.rb +0 -17
  156. data/smoke/enumerator.rb +0 -16
  157. data/smoke/expandarray1.rb +0 -23
  158. data/smoke/expandarray2.rb +0 -24
  159. data/smoke/extended.rb +0 -38
  160. data/smoke/fib.rb +0 -28
  161. data/smoke/flip-flop.rb +0 -28
  162. data/smoke/flow1.rb +0 -17
  163. data/smoke/flow10.rb +0 -17
  164. data/smoke/flow11.rb +0 -17
  165. data/smoke/flow2.rb +0 -15
  166. data/smoke/flow3.rb +0 -15
  167. data/smoke/flow4.rb +0 -5
  168. data/smoke/flow5.rb +0 -20
  169. data/smoke/flow6.rb +0 -20
  170. data/smoke/flow7.rb +0 -21
  171. data/smoke/flow8.rb +0 -14
  172. data/smoke/flow9.rb +0 -12
  173. data/smoke/for.rb +0 -9
  174. data/smoke/freeze.rb +0 -12
  175. data/smoke/function.rb +0 -17
  176. data/smoke/gvar.rb +0 -14
  177. data/smoke/gvar2.rb +0 -18
  178. data/smoke/gvar2.rbs +0 -1
  179. data/smoke/hash-bot.rb +0 -12
  180. data/smoke/hash-fetch.rb +0 -28
  181. data/smoke/hash-merge-bang.rb +0 -12
  182. data/smoke/hash1.rb +0 -20
  183. data/smoke/hash2.rb +0 -13
  184. data/smoke/hash3.rb +0 -14
  185. data/smoke/hash4.rb +0 -11
  186. data/smoke/hash5.rb +0 -14
  187. data/smoke/huge_union.rb +0 -86
  188. data/smoke/identifier_keywords.rb +0 -17
  189. data/smoke/included.rb +0 -38
  190. data/smoke/inheritance.rb +0 -34
  191. data/smoke/inheritance2.rb +0 -35
  192. data/smoke/inherited.rb +0 -26
  193. data/smoke/initialize.rb +0 -28
  194. data/smoke/instance_eval.rb +0 -18
  195. data/smoke/instance_eval2.rb +0 -10
  196. data/smoke/instance_eval3.rb +0 -25
  197. data/smoke/instance_eval4.rb +0 -12
  198. data/smoke/int_times.rb +0 -15
  199. data/smoke/integer.rb +0 -11
  200. data/smoke/ivar.rb +0 -31
  201. data/smoke/ivar2.rb +0 -30
  202. data/smoke/ivar3.rb +0 -17
  203. data/smoke/ivar3.rbs +0 -3
  204. data/smoke/ivar4.rb +0 -21
  205. data/smoke/kernel-class.rb +0 -13
  206. data/smoke/keyword1.rb +0 -12
  207. data/smoke/keyword2.rb +0 -12
  208. data/smoke/keyword3.rb +0 -12
  209. data/smoke/keyword4.rb +0 -12
  210. data/smoke/keyword5.rb +0 -16
  211. data/smoke/kwrest.rb +0 -13
  212. data/smoke/kwrest.rbs +0 -3
  213. data/smoke/kwsplat1.rb +0 -43
  214. data/smoke/kwsplat2.rb +0 -13
  215. data/smoke/lit-complex.rb +0 -10
  216. data/smoke/lit-encoding.rb +0 -10
  217. data/smoke/manual-rbs.rb +0 -29
  218. data/smoke/manual-rbs.rbs +0 -3
  219. data/smoke/manual-rbs2.rb +0 -21
  220. data/smoke/manual-rbs2.rbs +0 -8
  221. data/smoke/manual-rbs3.rb +0 -13
  222. data/smoke/manual-rbs3.rbs +0 -3
  223. data/smoke/masgn1.rb +0 -14
  224. data/smoke/masgn2.rb +0 -18
  225. data/smoke/masgn3.rb +0 -13
  226. data/smoke/method_in_branch.rb +0 -23
  227. data/smoke/method_missing.rb +0 -29
  228. data/smoke/module1.rb +0 -29
  229. data/smoke/module2.rb +0 -28
  230. data/smoke/module3.rb +0 -33
  231. data/smoke/module4.rb +0 -35
  232. data/smoke/module5.rb +0 -17
  233. data/smoke/module6.rb +0 -40
  234. data/smoke/module_function1.rb +0 -29
  235. data/smoke/module_function2.rb +0 -29
  236. data/smoke/multiple-include.rb +0 -15
  237. data/smoke/multiple-superclass.rb +0 -28
  238. data/smoke/next1.rb +0 -21
  239. data/smoke/next2.rb +0 -17
  240. data/smoke/noname.rb +0 -9
  241. data/smoke/object-send1.rb +0 -23
  242. data/smoke/object-send2.rb +0 -10
  243. data/smoke/object-send3.rb +0 -18
  244. data/smoke/once.rb +0 -13
  245. data/smoke/optional1.rb +0 -14
  246. data/smoke/optional2.rb +0 -16
  247. data/smoke/optional3.rb +0 -11
  248. data/smoke/or_raise.rb +0 -18
  249. data/smoke/parameterizedd-self.rb +0 -20
  250. data/smoke/parameterizedd-self2.rb +0 -15
  251. data/smoke/pathname1.rb +0 -14
  252. data/smoke/pathname2.rb +0 -14
  253. data/smoke/pattern-match1.rb +0 -19
  254. data/smoke/pattern-match2.rb +0 -16
  255. data/smoke/prepend1.rb +0 -33
  256. data/smoke/prepend2.rb +0 -10
  257. data/smoke/prepend2.rbs +0 -9
  258. data/smoke/primitive_method.rb +0 -19
  259. data/smoke/printf.rb +0 -20
  260. data/smoke/proc.rb +0 -20
  261. data/smoke/proc2.rb +0 -17
  262. data/smoke/proc3.rb +0 -15
  263. data/smoke/proc4.rb +0 -12
  264. data/smoke/proc5.rb +0 -19
  265. data/smoke/proc6.rb +0 -13
  266. data/smoke/proc7.rb +0 -32
  267. data/smoke/public.rb +0 -38
  268. data/smoke/range.rb +0 -14
  269. data/smoke/rbs-alias.rb +0 -10
  270. data/smoke/rbs-alias.rbs +0 -4
  271. data/smoke/rbs-attr.rb +0 -27
  272. data/smoke/rbs-attr.rbs +0 -5
  273. data/smoke/rbs-attr2.rb +0 -11
  274. data/smoke/rbs-attr2.rbs +0 -3
  275. data/smoke/rbs-extend.rb +0 -10
  276. data/smoke/rbs-extend.rbs +0 -7
  277. data/smoke/rbs-interface.rb +0 -25
  278. data/smoke/rbs-interface.rbs +0 -12
  279. data/smoke/rbs-module.rb +0 -26
  280. data/smoke/rbs-module.rbs +0 -4
  281. data/smoke/rbs-opt-and-rest.rb +0 -10
  282. data/smoke/rbs-opt-and-rest.rbs +0 -3
  283. data/smoke/rbs-proc1.rb +0 -10
  284. data/smoke/rbs-proc1.rbs +0 -3
  285. data/smoke/rbs-proc2.rb +0 -21
  286. data/smoke/rbs-proc2.rbs +0 -3
  287. data/smoke/rbs-proc3.rb +0 -14
  288. data/smoke/rbs-proc3.rbs +0 -4
  289. data/smoke/rbs-record.rb +0 -18
  290. data/smoke/rbs-record.rbs +0 -4
  291. data/smoke/rbs-tyvar.rb +0 -19
  292. data/smoke/rbs-tyvar.rbs +0 -5
  293. data/smoke/rbs-tyvar2.rb +0 -21
  294. data/smoke/rbs-tyvar2.rbs +0 -9
  295. data/smoke/rbs-tyvar3.rb +0 -18
  296. data/smoke/rbs-tyvar3.rbs +0 -5
  297. data/smoke/rbs-tyvar4.rb +0 -37
  298. data/smoke/rbs-tyvar5.rb +0 -13
  299. data/smoke/rbs-tyvar5.rbs +0 -8
  300. data/smoke/rbs-tyvar6.rb +0 -18
  301. data/smoke/rbs-tyvar6.rbs +0 -12
  302. data/smoke/rbs-tyvar7.rb +0 -12
  303. data/smoke/rbs-tyvar7.rbs +0 -7
  304. data/smoke/rbs-vars.rb +0 -38
  305. data/smoke/rbs-vars.rbs +0 -7
  306. data/smoke/redo1.rb +0 -22
  307. data/smoke/redo2.rb +0 -23
  308. data/smoke/req-keyword.rb +0 -13
  309. data/smoke/require1.rb +0 -13
  310. data/smoke/require2.rb +0 -13
  311. data/smoke/rescue1.rb +0 -21
  312. data/smoke/rescue2.rb +0 -23
  313. data/smoke/rescue3.rb +0 -20
  314. data/smoke/rescue4.rb +0 -17
  315. data/smoke/respond_to.rb +0 -23
  316. data/smoke/rest-farg.rb +0 -11
  317. data/smoke/rest1.rb +0 -26
  318. data/smoke/rest2.rb +0 -31
  319. data/smoke/rest3.rb +0 -37
  320. data/smoke/rest4.rb +0 -19
  321. data/smoke/rest5.rb +0 -11
  322. data/smoke/rest6.rb +0 -12
  323. data/smoke/retry1.rb +0 -21
  324. data/smoke/return.rb +0 -14
  325. data/smoke/reveal.rb +0 -13
  326. data/smoke/simple.rb +0 -12
  327. data/smoke/singleton_class.rb +0 -8
  328. data/smoke/singleton_method.rb +0 -12
  329. data/smoke/step.rb +0 -18
  330. data/smoke/string-split.rb +0 -12
  331. data/smoke/struct-keyword_init.rb +0 -10
  332. data/smoke/struct.rb +0 -13
  333. data/smoke/struct2.rb +0 -25
  334. data/smoke/struct3.rb +0 -14
  335. data/smoke/struct4.rb +0 -7
  336. data/smoke/struct5.rb +0 -16
  337. data/smoke/struct6.rb +0 -15
  338. data/smoke/struct7.rb +0 -17
  339. data/smoke/stub-keyword.rb +0 -10
  340. data/smoke/super1.rb +0 -69
  341. data/smoke/super2.rb +0 -16
  342. data/smoke/super3.rb +0 -20
  343. data/smoke/super4.rb +0 -45
  344. data/smoke/super5.rb +0 -38
  345. data/smoke/svar1.rb +0 -13
  346. data/smoke/symbol-proc-attr.rb +0 -22
  347. data/smoke/symbol-proc-attr2.rb +0 -15
  348. data/smoke/symbol-proc-bot.rb +0 -13
  349. data/smoke/symbol-proc.rb +0 -25
  350. data/smoke/tap1.rb +0 -18
  351. data/smoke/toplevel.rb +0 -13
  352. data/smoke/two-map.rb +0 -18
  353. data/smoke/type_var.rb +0 -11
  354. data/smoke/typed_method.rb +0 -16
  355. data/smoke/uninitialize-var.rb +0 -13
  356. data/smoke/union-recv.rb +0 -35
  357. data/smoke/user-demo.rb +0 -15
  358. data/smoke/wrong-extend.rb +0 -27
  359. data/smoke/wrong-include.rb +0 -27
  360. data/smoke/wrong-include2.rb +0 -17
  361. data/smoke/wrong-rbs.rb +0 -15
  362. data/smoke/wrong-rbs.rbs +0 -7
  363. data/testbed/ao.rb +0 -297
  364. data/testbed/diff-lcs-entrypoint.rb +0 -4
  365. data/testbed/goodcheck-Gemfile.lock +0 -51
@@ -43,6 +43,14 @@ module TypeProf
43
43
  end
44
44
  end
45
45
 
46
+ def detailed_source_location(pc)
47
+ if @iseq
48
+ @iseq.detailed_source_location(pc)
49
+ else
50
+ nil
51
+ end
52
+ end
53
+
46
54
  def replace_cref(cref)
47
55
  Context.new(@iseq, cref, @mid)
48
56
  end
@@ -66,6 +74,14 @@ module TypeProf
66
74
  end
67
75
  end
68
76
 
77
+ def detailed_source_location(_pc)
78
+ if @caller_ep
79
+ @caller_ep.source_location
80
+ else
81
+ nil
82
+ end
83
+ end
84
+
69
85
  def replace_cref(cref)
70
86
  # What to do?
71
87
  end
@@ -101,6 +117,14 @@ module TypeProf
101
117
  def source_location
102
118
  @ctx.source_location(@pc)
103
119
  end
120
+
121
+ def detailed_source_location
122
+ @ctx.detailed_source_location(@pc)
123
+ end
124
+
125
+ def absolute_path
126
+ @ctx.iseq.absolute_path
127
+ end
104
128
  end
105
129
 
106
130
  class StaticEnv
@@ -287,6 +311,9 @@ module TypeProf
287
311
 
288
312
  @types_being_shown = []
289
313
  @namespace = nil
314
+
315
+ @lsp_completion = nil
316
+ @lsp_signature_help = CodeRangeTable.new
290
317
  end
291
318
 
292
319
  def add_entrypoint(iseq)
@@ -335,7 +362,7 @@ module TypeProf
335
362
  @subclasses = []
336
363
  end
337
364
 
338
- attr_reader :kind, :modules, :consts, :methods, :ivars, :cvars, :absolute_path, :subclasses
365
+ attr_reader :kind, :modules, :methods, :ivars, :cvars, :absolute_path, :subclasses
339
366
  attr_accessor :name, :klass_obj
340
367
 
341
368
  def mix_module(kind, mod, type_args, singleton, absolute_path)
@@ -350,24 +377,43 @@ module TypeProf
350
377
  end
351
378
 
352
379
  def get_constant(name)
353
- ty, = @consts[name]
354
- ty || Type.any # XXX: warn?
380
+ ty, locs = @consts[name]
381
+ ty = ty || Type.any # XXX: warn?
382
+ return ty, locs
355
383
  end
356
384
 
357
- def add_constant(name, ty, absolute_path)
385
+ def add_constant(name, ty, def_ep)
358
386
  if @consts[name]
359
387
  # XXX: warn!
388
+ _, eps = @consts[name]
389
+ @consts[name] = [ty, eps + [def_ep&.detailed_source_location]]
390
+ return
391
+ end
392
+ @consts[name] = [ty, [def_ep&.detailed_source_location]]
393
+ end
394
+
395
+ def consts
396
+ @consts.lazy.flat_map do |name, (ty, eps)|
397
+ eps.map do |ep|
398
+ [name, [ty, ep]]
399
+ end
360
400
  end
361
- @consts[name] = [ty, absolute_path]
362
401
  end
363
402
 
403
+ def add_class_open(name, open_ep)
404
+ ty, eps = @consts[name]
405
+ raise "call this only if the class is opened more than once" if ty.nil?
406
+ @consts[name] = [ty, eps + [open_ep&.detailed_source_location]]
407
+ end
408
+
409
+
364
410
  def adjust_substitution_for_module(mods, mid, mthd, subst, &blk)
365
411
  mods.each do |mod_def, type_args,|
366
412
  if mod_def.klass_obj.type_params && type_args
367
413
  subst2 = {}
368
414
  mod_def.klass_obj.type_params.zip(type_args) do |(tyvar, *), tyarg|
369
415
  tyvar = Type::Var.new(tyvar)
370
- subst2[tyvar] = tyarg.substitute(subst, Config.options[:type_depth_limit])
416
+ subst2[tyvar] = tyarg.substitute(subst, Config.current.options[:type_depth_limit])
371
417
  end
372
418
  mod_def.adjust_substitution(false, mid, mthd, subst2, false, &blk)
373
419
  end
@@ -444,23 +490,23 @@ module TypeProf
444
490
  cbase && cbase.idx != 1 ? @class_defs[cbase.idx].name : []
445
491
  end
446
492
 
447
- def new_class(cbase, name, type_params, superclass, absolute_path)
493
+ def new_class(cbase, name, type_params, superclass, def_ep)
448
494
  show_name = cbase_path(cbase) + [name]
449
495
  idx = @class_defs.size
450
496
  if superclass
451
- @class_defs[idx] = ClassDef.new(:class, show_name, absolute_path)
497
+ @class_defs[idx] = ClassDef.new(:class, show_name, def_ep&.absolute_path)
452
498
  @class_defs[superclass.idx].subclasses << idx unless superclass == :__root__
453
499
  klass = Type::Class.new(:class, idx, type_params, superclass, show_name)
454
500
  @class_defs[idx].klass_obj = klass
455
501
  cbase ||= klass # for bootstrap
456
- add_constant(cbase, name, klass, absolute_path)
502
+ add_constant(cbase, name, klass, def_ep)
457
503
  return klass
458
504
  else
459
505
  # module
460
- @class_defs[idx] = ClassDef.new(:module, show_name, absolute_path)
506
+ @class_defs[idx] = ClassDef.new(:module, show_name, def_ep&.absolute_path)
461
507
  mod = Type::Class.new(:module, idx, type_params, nil, show_name)
462
508
  @class_defs[idx].klass_obj = mod
463
- add_constant(cbase, name, mod, absolute_path)
509
+ add_constant(cbase, name, mod, def_ep)
464
510
  return mod
465
511
  end
466
512
  end
@@ -519,7 +565,7 @@ module TypeProf
519
565
  subst2 = {}
520
566
  klass.superclass.type_params.zip(klass.superclass_type_args) do |(tyvar, *), tyarg|
521
567
  tyvar = Type::Var.new(tyvar)
522
- subst2[tyvar] = tyarg.substitute(subst, Config.options[:type_depth_limit])
568
+ subst2[tyvar] = tyarg.substitute(subst, Config.current.options[:type_depth_limit])
523
569
  end
524
570
  subst = subst2
525
571
  end
@@ -601,29 +647,53 @@ module TypeProf
601
647
  nil
602
648
  end
603
649
 
650
+ def get_all_methods(klass, singleton, _include_subclasses)
651
+ names = {}
652
+
653
+ if klass.kind == :class
654
+ while klass != :__root__
655
+ # TODO: module
656
+ @class_defs[klass.idx].methods.each_key do |singleton0, name|
657
+ if singleton == singleton0
658
+ names[name] = true
659
+ end
660
+ end
661
+ klass = klass.superclass
662
+ end
663
+ else
664
+ @class_defs[klass.idx].methods.each_key do |singleton0, name|
665
+ if singleton == singleton0
666
+ names[name] = true
667
+ end
668
+ end
669
+ end
670
+
671
+ names
672
+ end
673
+
604
674
  def get_constant(klass, name)
605
675
  if klass == Type.any
606
- Type.any
676
+ [Type.any, nil]
607
677
  elsif klass.is_a?(Type::Class)
608
678
  @class_defs[klass.idx].get_constant(name)
609
679
  else
610
- Type.any
680
+ [Type.any, nil]
611
681
  end
612
682
  end
613
683
 
614
684
  def search_constant(cref, name)
615
685
  while cref != :bottom
616
- val = get_constant(cref.klass, name)
617
- return val if val != Type.any
686
+ ty, locs = get_constant(cref.klass, name)
687
+ return ty, locs if ty != Type.any
618
688
  cref = cref.outer
619
689
  end
620
690
 
621
- Type.any
691
+ return Type.any, nil
622
692
  end
623
693
 
624
- def add_constant(klass, name, value, user_defined)
694
+ def add_constant(klass, name, value, def_ep)
625
695
  if klass.is_a?(Type::Class)
626
- @class_defs[klass.idx].add_constant(name, value, user_defined)
696
+ @class_defs[klass.idx].add_constant(name, value, def_ep)
627
697
  end
628
698
  end
629
699
 
@@ -694,7 +764,13 @@ module TypeProf
694
764
  end
695
765
 
696
766
  def add_callsite!(callee_ctx, caller_ep, caller_env, &ctn)
697
- @executed_iseqs << callee_ctx.iseq if callee_ctx.is_a?(Context)
767
+ if callee_ctx.is_a?(Context)
768
+ @executed_iseqs << callee_ctx.iseq
769
+ callee_type = callee_ctx.iseq.type
770
+ if caller_ep.ctx.is_a?(Context) && (callee_type == :method || callee_type == :block)
771
+ caller_ep.ctx.iseq&.add_called_iseq(caller_ep.pc, callee_ctx.iseq)
772
+ end
773
+ end
698
774
 
699
775
  @callsites[callee_ctx] ||= {}
700
776
  @callsites[callee_ctx][caller_ep] = ctn
@@ -743,23 +819,23 @@ module TypeProf
743
819
  end
744
820
 
745
821
  class VarTable
746
- Entry = Struct.new(:rbs_declared, :read_continuations, :type, :absolute_paths)
822
+ Entry = Struct.new(:rbs_declared, :read_continuations, :type, :absolute_paths, :write_eps)
747
823
 
748
824
  def initialize
749
825
  @tbl = {}
750
826
  end
751
827
 
752
828
  def add_read!(site, ep, &ctn)
753
- entry = @tbl[site] ||= Entry.new(false, {}, Type.bot, Utils::MutableSet.new)
829
+ entry = @tbl[site] ||= Entry.new(false, {}, Type.bot, Utils::MutableSet.new, Utils::MutableSet.new)
754
830
  entry.read_continuations[ep] = ctn
755
831
  entry.absolute_paths << ep.ctx.iseq.absolute_path if ep.ctx.is_a?(Context)
756
832
  ty = entry.type
757
833
  ty = Type.nil if ty == Type.bot
758
- ctn[ty, ep]
834
+ ctn[ty, ep, entry.write_eps]
759
835
  end
760
836
 
761
837
  def add_write!(site, ty, ep, scratch)
762
- entry = @tbl[site] ||= Entry.new(!ep, {}, Type.bot, Utils::MutableSet.new)
838
+ entry = @tbl[site] ||= Entry.new(!ep, {}, Type.bot, Utils::MutableSet.new, Utils::MutableSet.new)
763
839
  if ep
764
840
  if entry.rbs_declared
765
841
  unless Type.match?(ty, entry.type)
@@ -768,10 +844,11 @@ module TypeProf
768
844
  end
769
845
  end
770
846
  entry.absolute_paths << ep.ctx.iseq.absolute_path
847
+ entry.write_eps << ep
771
848
  end
772
849
  entry.type = entry.type.union(ty)
773
- entry.read_continuations.each do |ep, ctn|
774
- ctn[ty, ep]
850
+ entry.read_continuations.each do |read_ep, ctn|
851
+ ctn[ty, read_ep, [ep]]
775
852
  end
776
853
  end
777
854
 
@@ -815,7 +892,8 @@ module TypeProf
815
892
  recv.each_child do |recv|
816
893
  class_def, singleton = get_ivar(recv, var)
817
894
  next unless class_def
818
- class_def.ivars.add_write!([singleton, var], ty, ep, self)
895
+ site = [singleton, var]
896
+ class_def.ivars.add_write!(site, ty, ep, self)
819
897
  end
820
898
  end
821
899
 
@@ -846,18 +924,18 @@ module TypeProf
846
924
  end
847
925
 
848
926
  def error(ep, msg)
849
- p [ep.source_location, "[error] " + msg] if Config.verbose >= 2
927
+ p [ep.source_location, "[error] " + msg] if Config.current.verbose >= 2
850
928
  @errors << [ep, "[error] " + msg]
851
929
  end
852
930
 
853
931
  def warn(ep, msg)
854
- p [ep.source_location, "[warning] " + msg] if Config.verbose >= 2
932
+ p [ep.source_location, "[warning] " + msg] if Config.current.verbose >= 2
855
933
  @errors << [ep, "[warning] " + msg]
856
934
  end
857
935
 
858
936
  def reveal_type(ep, ty)
859
937
  key = ep.source_location
860
- puts "reveal:#{ ep.source_location }:#{ ty.screen_name(self) }" if Config.verbose >= 2
938
+ puts "reveal:#{ ep.source_location }:#{ ty.screen_name(self) }" if Config.current.verbose >= 2
861
939
  if @reveal_types[key]
862
940
  @reveal_types[key] = @reveal_types[key].union(ty)
863
941
  else
@@ -924,8 +1002,9 @@ module TypeProf
924
1002
  end
925
1003
  end
926
1004
 
927
- def type_profile
928
- start_time = tick = Time.now
1005
+ def type_profile(cancel_token = nil)
1006
+ cancel_token ||= Utils::TimerCancelToken.new(Config.current.max_sec)
1007
+ tick = Time.now
929
1008
  iter_counter = 0
930
1009
  stat_eps = Utils::MutableSet.new
931
1010
 
@@ -938,7 +1017,7 @@ module TypeProf
938
1017
  if entrypoint.is_a?(String)
939
1018
  file = entrypoint
940
1019
  next if @loaded_files[File.expand_path(file)]
941
- iseq = ISeq.compile(file)
1020
+ iseq, = ISeq.compile(file)
942
1021
  else
943
1022
  iseq = entrypoint
944
1023
  end
@@ -953,7 +1032,7 @@ module TypeProf
953
1032
  ep = @worklist.deletemin
954
1033
 
955
1034
  iter_counter += 1
956
- if Config.options[:show_indicator]
1035
+ if Config.current.options[:show_indicator]
957
1036
  tick2 = Time.now
958
1037
  if tick2 - tick >= 1
959
1038
  tick = tick2
@@ -962,7 +1041,7 @@ module TypeProf
962
1041
  end
963
1042
  end
964
1043
 
965
- if (Config.max_sec && Time.now - start_time >= Config.max_sec) || (Config.max_iter && Config.max_iter <= iter_counter)
1044
+ if (Config.current.max_iter && Config.current.max_iter <= iter_counter) || cancel_token.cancelled?
966
1045
  @terminated = true
967
1046
  break
968
1047
  end
@@ -973,7 +1052,7 @@ module TypeProf
973
1052
 
974
1053
  break if @terminated
975
1054
 
976
- break unless Config.options[:stub_execution]
1055
+ break unless Config.current.options[:stub_execution]
977
1056
 
978
1057
  begin
979
1058
  iseq, (kind, dummy_continuation) = @pending_execution.first
@@ -981,7 +1060,7 @@ module TypeProf
981
1060
  @pending_execution.delete(iseq)
982
1061
  end while @executed_iseqs.include?(iseq)
983
1062
 
984
- puts "DEBUG: trigger stub execution (#{ iseq&.name || "(nil)" }): rest #{ @pending_execution.size }" if Config.verbose >= 2
1063
+ puts "DEBUG: trigger stub execution (#{ iseq&.name || "(nil)" }): rest #{ @pending_execution.size }" if Config.current.verbose >= 2
985
1064
 
986
1065
  break if !iseq
987
1066
  case kind
@@ -1000,7 +1079,7 @@ module TypeProf
1000
1079
  end
1001
1080
  end
1002
1081
 
1003
- $stderr.print "\r\e[K" if Config.options[:show_indicator]
1082
+ $stderr.print "\r\e[K" if Config.current.options[:show_indicator]
1004
1083
 
1005
1084
  stat_eps
1006
1085
  end
@@ -1017,13 +1096,70 @@ module TypeProf
1017
1096
  RubySignatureExporter.new(self, @class_defs, @iseq_method_to_ctxs).show(stat_eps, output)
1018
1097
  end
1019
1098
 
1099
+ def report_lsp
1100
+ errs = @errors.map do |ep, msg|
1101
+ [ep&.detailed_source_location, msg]
1102
+ end
1103
+
1104
+ res = RubySignatureExporter.new(self, @class_defs, @iseq_method_to_ctxs).show_lsp
1105
+
1106
+ path, loc = Config.current.options[:signature_help_loc]
1107
+ if path
1108
+ sig_help_res = []
1109
+ sig_help = @lsp_signature_help[loc]
1110
+ if sig_help
1111
+ recv = sig_help[:recv]
1112
+ mid = sig_help[:mid]
1113
+ singleton = sig_help[:singleton]
1114
+ mdefs = sig_help[:mdefs]
1115
+ node_id = sig_help[:node_id]
1116
+ mdefs.each do |mdef|
1117
+ case mdef
1118
+ when ISeqMethodDef
1119
+ ctxs = @iseq_method_to_ctxs[mdef]
1120
+ next unless ctxs
1121
+
1122
+ ctx = ctxs.find {|ctx| ctx.mid == mid } || ctxs.first
1123
+
1124
+ method_name = mid
1125
+ method_name = "self.#{ method_name }" if singleton
1126
+
1127
+ str = recv.screen_name(self)
1128
+ str += singleton ? "." : "#"
1129
+ str += method_name.to_s
1130
+ str += ": "
1131
+ sig, _, sig_help = show_method_signature(ctx)
1132
+ offset = str.size
1133
+ sig_help = sig_help.transform_values {|r| (r.begin + offset ... r.end + offset) }
1134
+ str += sig
1135
+ sig_help_res << [str, sig_help, node_id]
1136
+ when AliasMethodDef
1137
+ # TODO
1138
+ when TypedMethodDef
1139
+ mdef.rbs_source&.[](1)&.each do |rbs|
1140
+ # TODO: sig_help
1141
+ sig_help_res << [rbs, {}, node_id]
1142
+ end
1143
+ end
1144
+ end
1145
+ end
1146
+ end
1147
+
1148
+ {
1149
+ sigs: res,
1150
+ errors: errs,
1151
+ completion: @lsp_completion,
1152
+ signature_help: sig_help_res,
1153
+ }
1154
+ end
1155
+
1020
1156
  def globalize_type(ty, env, ep)
1021
1157
  if ep.outer
1022
1158
  tmp_ep = ep
1023
1159
  tmp_ep = tmp_ep.outer while tmp_ep.outer
1024
1160
  env = @return_envs[tmp_ep]
1025
1161
  end
1026
- ty.globalize(env, {}, Config.options[:type_depth_limit])
1162
+ ty.globalize(env, {}, Config.current.options[:type_depth_limit])
1027
1163
  end
1028
1164
 
1029
1165
  def localize_type(ty, env, ep, alloc_site = AllocationSite.new(ep))
@@ -1031,13 +1167,13 @@ module TypeProf
1031
1167
  tmp_ep = ep
1032
1168
  tmp_ep = tmp_ep.outer while tmp_ep.outer
1033
1169
  target_env = @return_envs[tmp_ep]
1034
- target_env, ty = ty.localize(target_env, alloc_site, Config.options[:type_depth_limit])
1170
+ target_env, ty = ty.localize(target_env, alloc_site, Config.current.options[:type_depth_limit])
1035
1171
  merge_return_env(tmp_ep) do |env|
1036
1172
  env ? env.merge(target_env) : target_env
1037
1173
  end
1038
1174
  return env, ty
1039
1175
  else
1040
- return ty.localize(env, alloc_site, Config.options[:type_depth_limit])
1176
+ return ty.localize(env, alloc_site, Config.current.options[:type_depth_limit])
1041
1177
  end
1042
1178
  end
1043
1179
 
@@ -1099,13 +1235,16 @@ module TypeProf
1099
1235
  end
1100
1236
 
1101
1237
  def get_instance_variable(recv, var, ep, env)
1102
- add_ivar_read!(recv, var, ep) do |ty, ep|
1238
+ add_ivar_read!(recv, var, ep) do |ty, ep, write_eps|
1103
1239
  alloc_site = AllocationSite.new(ep)
1104
1240
  nenv, ty = localize_type(ty, env, ep, alloc_site)
1105
1241
  case ty
1106
1242
  when Type::Local
1107
1243
  @alloc_site_to_global_id[ty.id] = [recv, var] # need overwrite check??
1108
1244
  end
1245
+ write_eps.each do |write_ep|
1246
+ ep.ctx.iseq.add_def_loc(ep.pc, write_ep.detailed_source_location)
1247
+ end
1109
1248
  yield ty, nenv
1110
1249
  end
1111
1250
  end
@@ -1122,7 +1261,7 @@ module TypeProf
1122
1261
  insn = ep.ctx.iseq.insns[ep.pc]
1123
1262
  operands = insn.operands
1124
1263
 
1125
- if Config.verbose >= 2
1264
+ if Config.current.verbose >= 2
1126
1265
  # XXX: more dedicated output
1127
1266
  puts "DEBUG: stack=%p" % [env.stack]
1128
1267
  puts "DEBUG: %s (%s) PC=%d insn=%s sp=%d" % [ep.source_location, ep.ctx.iseq.name, ep.pc, insn.insn, env.stack.size]
@@ -1291,8 +1430,10 @@ module TypeProf
1291
1430
  case flags & 7
1292
1431
  when 0, 2 # CLASS / MODULE
1293
1432
  type = (flags & 7) == 2 ? :module : :class
1294
- existing_klass = get_constant(cbase, id) # TODO: multiple return values
1433
+ existing_klass, = get_constant(cbase, id) # TODO: multiple return values
1295
1434
  if existing_klass.is_a?(Type::Class)
1435
+ # record re-opening location
1436
+ @class_defs[cbase.idx].add_class_open(id, ep)
1296
1437
  klass = existing_klass
1297
1438
  else
1298
1439
  if existing_klass != Type.any
@@ -1317,7 +1458,7 @@ module TypeProf
1317
1458
  superclass = nil
1318
1459
  end
1319
1460
  if cbase.is_a?(Type::Class)
1320
- klass = new_class(cbase, id, [], superclass, ep.ctx.iseq.absolute_path)
1461
+ klass = new_class(cbase, id, [], superclass, ep)
1321
1462
  if superclass
1322
1463
  add_superclass_type_args!(klass, superclass.type_params.map { Type.any })
1323
1464
 
@@ -1631,7 +1772,7 @@ module TypeProf
1631
1772
  var, = operands
1632
1773
  ty = Type.builtin_global_variable_type(var)
1633
1774
  if ty
1634
- ty = get_constant(Type::Builtin[:obj], ty) if ty.is_a?(Symbol)
1775
+ ty, locs = get_constant(Type::Builtin[:obj], ty) if ty.is_a?(Symbol)
1635
1776
  env, ty = localize_type(ty, env, ep)
1636
1777
  env = env.push(ty)
1637
1778
  else
@@ -1776,21 +1917,29 @@ module TypeProf
1776
1917
  name, = operands
1777
1918
  env, (cbase, _allow_nil,) = env.pop(2)
1778
1919
  if cbase == Type.nil
1779
- ty = search_constant(ep.ctx.cref, name)
1920
+ ty, locs = search_constant(ep.ctx.cref, name)
1780
1921
  env, ty = localize_type(ty, env, ep)
1781
1922
  env = env.push(ty)
1782
1923
  elsif cbase == Type.any
1783
1924
  env = env.push(Type.any) # XXX: warning needed?
1784
1925
  else
1785
- ty = get_constant(cbase, name)
1926
+ ty, locs = get_constant(cbase, name)
1786
1927
  env, ty = localize_type(ty, env, ep)
1787
1928
  env = env.push(ty)
1788
1929
  end
1930
+ locs&.each do |loc|
1931
+ ep.ctx.iseq.add_def_loc(ep.pc, loc)
1932
+ end
1789
1933
  when :setconstant
1790
1934
  name, = operands
1791
1935
  env, (ty, cbase) = env.pop(2)
1792
- old_ty = get_constant(cbase, name)
1793
- if old_ty != Type.any # XXX???
1936
+ old_ty, old_locs = get_constant(cbase, name)
1937
+ if old_locs == [nil] # RBS defined
1938
+ # TODO: it would be better to check if ty is consistent with old_ty (defined in RBS)
1939
+ # instead of extending the type
1940
+ env, old_ty = localize_type(globalize_type(old_ty, env, ep), env, ep)
1941
+ ty = ty.union(old_ty)
1942
+ elsif old_ty != Type.any # XXX???
1794
1943
  warn(ep, "already initialized constant #{ Type::Instance.new(cbase).screen_name(self) }::#{ name }")
1795
1944
  end
1796
1945
  ty.each_child do |ty|
@@ -1798,7 +1947,7 @@ module TypeProf
1798
1947
  @class_defs[ty.idx].name = cbase_path(cbase) + [name]
1799
1948
  end
1800
1949
  end
1801
- add_constant(cbase, name, globalize_type(ty, env, ep), ep.ctx.iseq.absolute_path)
1950
+ add_constant(cbase, name, globalize_type(ty, env, ep), ep)
1802
1951
 
1803
1952
  when :getspecial
1804
1953
  key, type = operands
@@ -2186,10 +2335,26 @@ module TypeProf
2186
2335
  merge_return_env(ep) {|tenv| tenv ? tenv.merge(env) : env }
2187
2336
  end
2188
2337
 
2338
+ aargs.node_id = opt[:node_id]
2339
+
2189
2340
  return env, recv, mid, aargs
2190
2341
  end
2191
2342
 
2192
2343
  def do_send(recvs, mid, aargs, ep, env, &ctn)
2344
+ if mid == :__typeprof_lsp_completion
2345
+ names = {}
2346
+ recvs.each_child do |recv|
2347
+ case recv
2348
+ when Type::Void, Type::Any
2349
+ else
2350
+ klass, singleton, include_subclasses = recv.method_dispatch_info
2351
+ names.merge!(get_all_methods(klass, singleton, include_subclasses)) if klass
2352
+ end
2353
+ end
2354
+ @lsp_completion = names
2355
+ return ctn[Type.any, ep, env]
2356
+ end
2357
+
2193
2358
  recvs.each_child do |recv|
2194
2359
  case recv
2195
2360
  when Type::Void
@@ -2201,6 +2366,19 @@ module TypeProf
2201
2366
  klass, singleton, include_subclasses = recv.method_dispatch_info
2202
2367
  meths = get_method(klass, singleton, include_subclasses, mid) if klass
2203
2368
  if meths
2369
+ path, loc = Config.current.options[:signature_help_loc]
2370
+ if path && path == ep.ctx.iseq.path && mid != :inherited # XXX: too ad-hoc!!!
2371
+ path, code_range = ep&.detailed_source_location
2372
+ if path && code_range&.contain_loc?(loc)
2373
+ @lsp_signature_help[code_range] = {
2374
+ recv: recv,
2375
+ mid: mid,
2376
+ singleton: singleton,
2377
+ mdefs: meths,
2378
+ node_id: aargs.node_id,
2379
+ }
2380
+ end
2381
+ end
2204
2382
  meths.each do |meth|
2205
2383
  meth.do_send(recv, mid, aargs, ep, env, self, &ctn)
2206
2384
  end
@@ -2282,7 +2460,7 @@ module TypeProf
2282
2460
 
2283
2461
  bsig ||= BlockSignature.new([], [], nil, Type.nil)
2284
2462
 
2285
- bsig = bsig.screen_name(nil, self)
2463
+ bsig, = bsig.screen_name(nil, self)
2286
2464
  ret_ty = ret_ty.screen_name(self)
2287
2465
  ret_ty = (ret_ty.include?("|") ? "(#{ ret_ty })" : ret_ty) # XXX?
2288
2466
 
@@ -2317,7 +2495,7 @@ module TypeProf
2317
2495
 
2318
2496
  begin
2319
2497
  @types_being_shown << farg_tys << ret_ty
2320
- farg_tys = farg_tys ? farg_tys.screen_name(nil, self) : "(unknown)"
2498
+ farg_tys, = farg_tys ? farg_tys.screen_name(nil, self) : ["(unknown)"]
2321
2499
  ret_ty = ret_ty.screen_name(self)
2322
2500
  ret_ty = (ret_ty.include?("|") ? "(#{ ret_ty })" : ret_ty) # XXX?
2323
2501
 
@@ -2330,15 +2508,16 @@ module TypeProf
2330
2508
 
2331
2509
  def show_method_signature(ctx)
2332
2510
  farg_tys = @method_signatures[ctx]
2511
+ return nil unless farg_tys
2333
2512
  ret_ty = ctx.mid == :initialize ? Type::Void.new : @return_values[ctx] || Type.bot
2334
2513
 
2335
2514
  untyped = farg_tys.include_untyped?(self) || ret_ty.include_untyped?(self)
2336
2515
 
2337
- farg_tys = farg_tys.screen_name(ctx.iseq, self)
2516
+ farg_tys, ranges = farg_tys.screen_name(ctx.iseq, self)
2338
2517
  ret_ty = ret_ty.screen_name(self)
2339
2518
  ret_ty = (ret_ty.include?("|") ? "(#{ ret_ty })" : ret_ty) # XXX?
2340
2519
 
2341
- ["#{ (farg_tys.empty? ? "" : "#{ farg_tys } ") }-> #{ ret_ty }", untyped]
2520
+ return "#{ (farg_tys.empty? ? "" : "#{ farg_tys } ") }-> #{ ret_ty }", untyped, ranges
2342
2521
  end
2343
2522
  end
2344
2523
  end
@@ -16,6 +16,7 @@ module TypeProf
16
16
  end
17
17
 
18
18
  attr_reader :lead_tys, :rest_ty, :kw_tys, :blk_ty
19
+ attr_accessor :node_id
19
20
 
20
21
  def globalize(caller_env, visited, depth)
21
22
  lead_tys = @lead_tys.map {|ty| ty.globalize(caller_env, visited, depth) }