typeprof 0.21.11 → 0.30.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 (73) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +15 -31
  3. data/bin/typeprof +5 -0
  4. data/doc/doc.ja.md +134 -0
  5. data/doc/doc.md +136 -0
  6. data/lib/typeprof/cli/cli.rb +180 -0
  7. data/lib/typeprof/cli.rb +2 -133
  8. data/lib/typeprof/code_range.rb +112 -0
  9. data/lib/typeprof/core/ast/base.rb +263 -0
  10. data/lib/typeprof/core/ast/call.rb +251 -0
  11. data/lib/typeprof/core/ast/const.rb +126 -0
  12. data/lib/typeprof/core/ast/control.rb +432 -0
  13. data/lib/typeprof/core/ast/meta.rb +150 -0
  14. data/lib/typeprof/core/ast/method.rb +335 -0
  15. data/lib/typeprof/core/ast/misc.rb +263 -0
  16. data/lib/typeprof/core/ast/module.rb +123 -0
  17. data/lib/typeprof/core/ast/pattern.rb +140 -0
  18. data/lib/typeprof/core/ast/sig_decl.rb +471 -0
  19. data/lib/typeprof/core/ast/sig_type.rb +663 -0
  20. data/lib/typeprof/core/ast/value.rb +319 -0
  21. data/lib/typeprof/core/ast/variable.rb +315 -0
  22. data/lib/typeprof/core/ast.rb +472 -0
  23. data/lib/typeprof/core/builtin.rb +146 -0
  24. data/lib/typeprof/core/env/method.rb +137 -0
  25. data/lib/typeprof/core/env/method_entity.rb +55 -0
  26. data/lib/typeprof/core/env/module_entity.rb +408 -0
  27. data/lib/typeprof/core/env/static_read.rb +155 -0
  28. data/lib/typeprof/core/env/type_alias_entity.rb +27 -0
  29. data/lib/typeprof/core/env/value_entity.rb +32 -0
  30. data/lib/typeprof/core/env.rb +360 -0
  31. data/lib/typeprof/core/graph/box.rb +991 -0
  32. data/lib/typeprof/core/graph/change_set.rb +224 -0
  33. data/lib/typeprof/core/graph/filter.rb +155 -0
  34. data/lib/typeprof/core/graph/vertex.rb +222 -0
  35. data/lib/typeprof/core/graph.rb +3 -0
  36. data/lib/typeprof/core/service.rb +522 -0
  37. data/lib/typeprof/core/type.rb +348 -0
  38. data/lib/typeprof/core/util.rb +81 -0
  39. data/lib/typeprof/core.rb +32 -0
  40. data/lib/typeprof/diagnostic.rb +35 -0
  41. data/lib/typeprof/lsp/messages.rb +430 -0
  42. data/lib/typeprof/lsp/server.rb +177 -0
  43. data/lib/typeprof/lsp/text.rb +69 -0
  44. data/lib/typeprof/lsp/util.rb +61 -0
  45. data/lib/typeprof/lsp.rb +4 -907
  46. data/lib/typeprof/version.rb +1 -1
  47. data/lib/typeprof.rb +4 -18
  48. data/typeprof.gemspec +5 -7
  49. metadata +48 -35
  50. data/.github/dependabot.yml +0 -6
  51. data/.github/workflows/main.yml +0 -39
  52. data/.gitignore +0 -9
  53. data/Gemfile +0 -17
  54. data/Gemfile.lock +0 -41
  55. data/Rakefile +0 -10
  56. data/exe/typeprof +0 -10
  57. data/lib/typeprof/analyzer.rb +0 -2598
  58. data/lib/typeprof/arguments.rb +0 -414
  59. data/lib/typeprof/block.rb +0 -176
  60. data/lib/typeprof/builtin.rb +0 -893
  61. data/lib/typeprof/code-range.rb +0 -177
  62. data/lib/typeprof/config.rb +0 -158
  63. data/lib/typeprof/container-type.rb +0 -912
  64. data/lib/typeprof/export.rb +0 -589
  65. data/lib/typeprof/import.rb +0 -852
  66. data/lib/typeprof/insns-def.rb +0 -65
  67. data/lib/typeprof/iseq.rb +0 -864
  68. data/lib/typeprof/method.rb +0 -355
  69. data/lib/typeprof/type.rb +0 -1140
  70. data/lib/typeprof/utils.rb +0 -212
  71. data/tools/coverage.rb +0 -14
  72. data/tools/setup-insns-def.rb +0 -30
  73. data/typeprof-lsp +0 -3
@@ -0,0 +1,137 @@
1
+ module TypeProf::Core
2
+ class FormalArguments
3
+ def initialize(req_positionals, opt_positionals, rest_positionals, post_positionals, req_keywords, opt_keywords, rest_keywords, block)
4
+ @req_positionals = req_positionals
5
+ @opt_positionals = opt_positionals
6
+ @rest_positionals = rest_positionals
7
+ @post_positionals = post_positionals
8
+ @req_keywords = req_keywords
9
+ @opt_keywords = opt_keywords
10
+ @rest_keywords = rest_keywords
11
+ @block = block
12
+ end
13
+
14
+ Empty = FormalArguments.new([], [], nil, [], [], [], nil, nil)
15
+
16
+ attr_reader :req_positionals
17
+ attr_reader :opt_positionals
18
+ attr_reader :rest_positionals
19
+ attr_reader :post_positionals
20
+ attr_reader :req_keywords
21
+ attr_reader :opt_keywords
22
+ attr_reader :rest_keywords
23
+ attr_reader :block
24
+ end
25
+
26
+ class ActualArguments
27
+ def initialize(positionals, splat_flags, keywords, block)
28
+ @positionals = positionals
29
+ @splat_flags = splat_flags
30
+ @keywords = keywords
31
+ @block = block
32
+ end
33
+
34
+ attr_reader :positionals, :splat_flags, :keywords, :block
35
+
36
+ def new_vertexes(genv, node)
37
+ positionals = @positionals.map {|arg| arg.new_vertex(genv, node) }
38
+ splat_flags = @splat_flags
39
+ keywords = @keywords ? @keywords.new_vertex(genv, node) : nil
40
+ block = @block ? @block.new_vertex(genv, node) : nil
41
+ ActualArguments.new(positionals, splat_flags, keywords, block)
42
+ end
43
+
44
+ def get_rest_args(genv, start_rest, end_rest)
45
+ vtxs = []
46
+
47
+ start_rest.upto(end_rest - 1) do |i|
48
+ a_arg = @positionals[i]
49
+ if @splat_flags[i]
50
+ a_arg.each_type do |ty|
51
+ ty = ty.base_type(genv)
52
+ if ty.is_a?(Type::Instance) && ty.mod == genv.mod_ary && ty.args[0]
53
+ vtxs << ty.args[0].new_vertex(genv, self)
54
+ else
55
+ "???"
56
+ end
57
+ end
58
+ else
59
+ vtxs << a_arg
60
+ end
61
+ end
62
+
63
+ vtxs.uniq
64
+ end
65
+
66
+ def get_keyword_arg(genv, changes, name)
67
+ vtx = Vertex.new(self)
68
+ @keywords.each_type do |ty|
69
+ case ty
70
+ when Type::Hash
71
+ changes.add_edge(genv, ty.get_value(name), vtx)
72
+ when Type::Instance
73
+ if ty.mod == genv.mod_hash
74
+ changes.add_edge(genv, ty.args[1], vtx)
75
+ end
76
+ else
77
+ # what to do?
78
+ end
79
+ end
80
+ vtx
81
+ end
82
+ end
83
+
84
+ class Block
85
+ def initialize(node, f_ary_arg, f_args, next_boxes)
86
+ @node = node
87
+ @f_ary_arg = f_ary_arg
88
+ @f_args = f_args
89
+ @next_boxes = next_boxes
90
+ end
91
+
92
+ attr_reader :node, :f_args, :ret
93
+
94
+ def accept_args(genv, changes, caller_positionals, caller_ret, ret_check)
95
+ if caller_positionals.size == 1 && @f_args.size >= 2
96
+ # TODO: support splat "do |a, *b, c|"
97
+ changes.add_edge(genv, caller_positionals[0].new_vertex(genv, @node), @f_ary_arg)
98
+ else
99
+ caller_positionals.zip(@f_args) do |a_arg, f_arg|
100
+ changes.add_edge(genv, a_arg, f_arg) if f_arg
101
+ end
102
+ end
103
+ if ret_check
104
+ @next_boxes.each do |box|
105
+ changes.add_edge(genv, caller_ret, box.f_ret)
106
+ end
107
+ else
108
+ @next_boxes.each do |box|
109
+ changes.add_edge(genv, box.a_ret, caller_ret)
110
+ end
111
+ end
112
+ end
113
+ end
114
+
115
+ class RecordBlock
116
+ def initialize(node)
117
+ @node = node
118
+ @used = false
119
+ @f_args = []
120
+ @ret = Vertex.new(node)
121
+ end
122
+
123
+ def get_f_arg(i)
124
+ @f_args[i] ||= Vertex.new(@node)
125
+ end
126
+
127
+ attr_reader :node, :f_args, :ret, :used
128
+
129
+ def accept_args(genv, changes, caller_positionals, caller_ret, ret_check)
130
+ @used = true
131
+ caller_positionals.each_with_index do |a_arg, i|
132
+ changes.add_edge(genv, a_arg.new_vertex(genv, @node), get_f_arg(i))
133
+ end
134
+ changes.add_edge(genv, caller_ret, @ret)
135
+ end
136
+ end
137
+ end
@@ -0,0 +1,55 @@
1
+ module TypeProf::Core
2
+ class MethodEntity
3
+ def initialize
4
+ @builtin = nil
5
+ @decls = Set[]
6
+ @defs = Set[]
7
+ @aliases = {}
8
+ @method_call_boxes = Set[]
9
+ end
10
+
11
+ attr_reader :decls, :defs, :aliases, :method_call_boxes
12
+ attr_accessor :builtin
13
+
14
+ def add_decl(decl)
15
+ @decls << decl
16
+ end
17
+
18
+ def remove_decl(decl)
19
+ @decls.delete(decl) || raise
20
+ end
21
+
22
+ def add_def(mdef)
23
+ @defs << mdef
24
+ self
25
+ end
26
+
27
+ def remove_def(mdef)
28
+ @defs.delete(mdef) || raise
29
+ end
30
+
31
+ def add_alias(node, old_mid)
32
+ @aliases[node] = old_mid
33
+ end
34
+
35
+ def remove_alias(node)
36
+ @aliases.delete(node) || raise
37
+ end
38
+
39
+ def exist?
40
+ @builtin || !@decls.empty? || !@defs.empty?
41
+ end
42
+
43
+ def add_run_all_mdefs(genv)
44
+ @defs.each do |mdef|
45
+ genv.add_run(mdef)
46
+ end
47
+ end
48
+
49
+ def add_run_all_method_call_boxes(genv)
50
+ @method_call_boxes.each do |box|
51
+ genv.add_run(box)
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,408 @@
1
+ module TypeProf::Core
2
+ class ModuleEntity
3
+ def initialize(cpath, outer_module = self)
4
+ @cpath = cpath
5
+
6
+ @module_decls = Set[]
7
+ @module_defs = Set[]
8
+ @include_decls = Set[]
9
+ @include_defs = Set[]
10
+
11
+ @inner_modules = {}
12
+ @outer_module = outer_module
13
+
14
+ # parent modules (superclass and all modules that I include)
15
+ @superclass = nil
16
+ @self_types = {}
17
+ @included_modules = {}
18
+ @basic_object = @cpath == [:BasicObject]
19
+
20
+ # child modules (subclasses and all modules that include me)
21
+ @child_modules = {}
22
+
23
+ # class Foo[X, Y, Z] < Bar[A, B, C]
24
+ @superclass_type_args = nil # A, B, C
25
+ @type_params = [] # X, Y, Z
26
+
27
+ @consts = {}
28
+ @methods = { true => {}, false => {} }
29
+ @ivars = { true => {}, false => {} }
30
+ @cvars = {}
31
+ @type_aliases = {}
32
+
33
+ @static_reads = {}
34
+ @subclass_checks = Set[]
35
+ @ivar_reads = Set[] # should be handled in @ivars ??
36
+ @cvar_reads = Set[]
37
+ end
38
+
39
+ attr_reader :cpath
40
+ attr_reader :module_decls
41
+ attr_reader :module_defs
42
+
43
+ attr_reader :inner_modules
44
+ attr_reader :outer_module
45
+
46
+ attr_reader :superclass
47
+ attr_reader :self_types
48
+ attr_reader :included_modules
49
+ attr_reader :child_modules
50
+
51
+ attr_reader :superclass_type_args
52
+ attr_reader :type_params
53
+
54
+ attr_reader :consts
55
+ attr_reader :methods
56
+ attr_reader :ivars
57
+ attr_reader :cvars
58
+ attr_reader :type_aliases
59
+
60
+ attr_reader :static_reads
61
+ attr_reader :subclass_checks
62
+ attr_reader :ivar_reads
63
+ attr_reader :cvar_reads
64
+
65
+ def module?
66
+ !@superclass && !@basic_object
67
+ end
68
+
69
+ def interface?
70
+ @cpath.last && @cpath.last.start_with?("_")
71
+ end
72
+
73
+ def get_cname
74
+ @cpath.empty? ? :Object : @cpath.last
75
+ end
76
+
77
+ def exist?
78
+ !@module_decls.empty? || !@module_defs.empty?
79
+ end
80
+
81
+ def on_inner_modules_changed(genv, changed_cname)
82
+ @child_modules.each_key do |child_mod|
83
+ child_mod.on_inner_modules_changed(genv, changed_cname)
84
+ end
85
+ if @static_reads[changed_cname]
86
+ @static_reads[changed_cname].each do |static_read|
87
+ genv.add_static_eval_queue(:static_read_changed, static_read)
88
+ end
89
+ end
90
+ end
91
+
92
+ def on_module_added(genv)
93
+ return if @cpath.empty?
94
+ unless exist?
95
+ genv.add_static_eval_queue(:inner_modules_changed, [@outer_module, get_cname])
96
+ end
97
+ genv.add_static_eval_queue(:parent_modules_changed, self)
98
+ end
99
+
100
+ def on_module_removed(genv)
101
+ return if @cpath.empty?
102
+ genv.add_static_eval_queue(:parent_modules_changed, self)
103
+ unless exist?
104
+ genv.add_static_eval_queue(:inner_modules_changed, [@outer_module, get_cname])
105
+ end
106
+ end
107
+
108
+ def add_module_decl(genv, decl)
109
+ on_module_added(genv)
110
+
111
+ @module_decls << decl
112
+
113
+ if @type_params
114
+ update_type_params if @type_params != decl.params
115
+ else
116
+ @type_params = decl.params
117
+ end
118
+
119
+ if decl.is_a?(AST::SigClassNode) && !@superclass_type_args
120
+ @superclass_type_args = decl.superclass_args
121
+ end
122
+
123
+ ce = @outer_module.get_const(get_cname)
124
+ ce.add_decl(decl)
125
+ ce
126
+ end
127
+
128
+ def remove_module_decl(genv, decl)
129
+ @outer_module.get_const(get_cname).remove_decl(decl)
130
+ @module_decls.delete(decl) || raise
131
+
132
+ update_type_params if @type_params == decl.params
133
+ if decl.is_a?(AST::SigClassNode) && @superclass_type_args == decl.superclass_args
134
+ @superclass_type_args = nil
135
+ @module_decls.each do |decl|
136
+ if decl.superclass_args
137
+ @superclass_type_args = decl.superclass_args
138
+ break
139
+ end
140
+ end
141
+ end
142
+
143
+ on_module_removed(genv)
144
+ end
145
+
146
+ def update_type_params
147
+ @type_params = nil
148
+ @module_decls.each do |decl|
149
+ params = decl.params
150
+ next unless params
151
+ if @type_params
152
+ @type_params = params if (@type_params <=> params) > 0
153
+ else
154
+ @type_params = params
155
+ end
156
+ end
157
+ @type_params ||= []
158
+ # TODO: report an error if there are multiple inconsistent declarations
159
+ end
160
+
161
+ def add_module_def(genv, node)
162
+ on_module_added(genv)
163
+ @module_defs << node
164
+ ce = @outer_module.get_const(get_cname)
165
+ ce.add_def(node)
166
+ ce
167
+ end
168
+
169
+ def remove_module_def(genv, node)
170
+ @outer_module.get_const(get_cname).remove_def(node)
171
+ @module_defs.delete(node) || raise
172
+ on_module_removed(genv)
173
+ end
174
+
175
+ def add_include_decl(genv, node)
176
+ @include_decls << node
177
+ genv.add_static_eval_queue(:parent_modules_changed, self)
178
+ end
179
+
180
+ def remove_include_decl(genv, node)
181
+ @include_decls.delete(node) || raise
182
+ genv.add_static_eval_queue(:parent_modules_changed, self)
183
+ end
184
+
185
+ def add_include_def(genv, node)
186
+ @include_defs << node
187
+ genv.add_static_eval_queue(:parent_modules_changed, self)
188
+ end
189
+
190
+ def remove_include_def(genv, node)
191
+ @include_defs.delete(node) || raise
192
+ genv.add_static_eval_queue(:parent_modules_changed, self)
193
+ end
194
+
195
+ def update_parent(genv, origin, old_parent, new_parent_cpath)
196
+ new_parent = new_parent_cpath ? genv.resolve_cpath(new_parent_cpath) : nil
197
+ if old_parent != new_parent
198
+ # check circular inheritance
199
+ mod = new_parent
200
+ while mod
201
+ if mod == self
202
+ # TODO: report an "circular inheritance" error
203
+ new_parent = nil
204
+ break
205
+ end
206
+ mod = mod.superclass
207
+ end
208
+
209
+ if old_parent != new_parent
210
+ if old_parent
211
+ set = old_parent.child_modules[self]
212
+ set.delete(origin)
213
+ old_parent.child_modules.delete(self) if set.empty?
214
+ end
215
+ if new_parent
216
+ set = new_parent.child_modules[self] ||= Set[]
217
+ set << origin
218
+ end
219
+ return [new_parent, true]
220
+ end
221
+ end
222
+ return [new_parent, false]
223
+ end
224
+
225
+ def find_superclass_const_read
226
+ return nil if @basic_object
227
+
228
+ if @module_decls.empty?
229
+ @module_defs.each do |mdef|
230
+ case mdef
231
+ when AST::ClassNode
232
+ if mdef.superclass_cpath
233
+ const_read = mdef.superclass_cpath.static_ret
234
+ return const_read ? const_read.cpath : []
235
+ end
236
+ when AST::SingletonClassNode
237
+ next
238
+ when AST::ModuleNode
239
+ return nil
240
+ else
241
+ raise
242
+ end
243
+ end
244
+ else
245
+ @module_decls.each do |mdecl|
246
+ case mdecl
247
+ when AST::SigClassNode
248
+ if mdecl.superclass_cpath
249
+ const_read = mdecl.static_ret[:superclass_cpath].last
250
+ return const_read ? const_read.cpath : []
251
+ end
252
+ when AST::SigModuleNode, AST::SigInterfaceNode
253
+ return nil
254
+ end
255
+ end
256
+ end
257
+
258
+ return []
259
+ end
260
+
261
+ def on_parent_modules_changed(genv)
262
+ any_updated = false
263
+
264
+ unless @basic_object
265
+ new_superclass_cpath = find_superclass_const_read
266
+
267
+ new_superclass, updated = update_parent(genv, :superclass, @superclass, new_superclass_cpath)
268
+ if updated
269
+ @superclass = new_superclass
270
+ any_updated = true
271
+ end
272
+ end
273
+
274
+ @module_decls.each do |mdecl|
275
+ case mdecl
276
+ when AST::SigModuleNode
277
+ mdecl.static_ret[:self_types].each_with_index do |const_reads, i|
278
+ key = [mdecl, i]
279
+ new_parent_cpath = const_reads.last.cpath
280
+ new_self_type, updated = update_parent(genv, key, @self_types[key], new_parent_cpath)
281
+ if updated
282
+ if new_self_type
283
+ @self_types[key] = new_self_type
284
+ else
285
+ @self_types.delete(key) || raise
286
+ end
287
+ any_updated = true
288
+ end
289
+ end
290
+ end
291
+ end
292
+ @self_types.delete_if do |(origin_mdecl, origin_idx), old_mod|
293
+ if @module_decls.include?(origin_mdecl)
294
+ false
295
+ else
296
+ _new_self_type, updated = update_parent(genv, [origin_mdecl, origin_idx], old_mod, nil)
297
+ any_updated ||= updated
298
+ true
299
+ end
300
+ end
301
+
302
+ @include_decls.each do |idecl|
303
+ new_parent_cpath = idecl.static_ret.last.cpath
304
+ new_parent, updated = update_parent(genv, idecl, @included_modules[idecl], new_parent_cpath)
305
+ if updated
306
+ if new_parent
307
+ @included_modules[idecl] = new_parent
308
+ else
309
+ @included_modules.delete(idecl) || raise
310
+ end
311
+ any_updated = true
312
+ end
313
+ end
314
+ @include_defs.each do |idef|
315
+ new_parent_cpath = idef.static_ret ? idef.static_ret.cpath : nil
316
+ new_parent, updated = update_parent(genv, idef, @included_modules[idef], new_parent_cpath)
317
+ if updated
318
+ if new_parent
319
+ @included_modules[idef] = new_parent
320
+ else
321
+ @included_modules.delete(idef) || raise
322
+ end
323
+ any_updated = true
324
+ end
325
+ end
326
+ @included_modules.delete_if do |origin, old_mod|
327
+ if @include_decls.include?(origin) || @include_defs.include?(origin)
328
+ false
329
+ else
330
+ _new_parent, updated = update_parent(genv, origin, old_mod, nil)
331
+ any_updated ||= updated
332
+ true
333
+ end
334
+ end
335
+
336
+ if any_updated
337
+ @subclass_checks.each do |mcall_box|
338
+ genv.add_run(mcall_box)
339
+ end
340
+ on_ancestors_updated(genv, nil)
341
+ end
342
+ end
343
+
344
+ def on_ancestors_updated(genv, base_mod)
345
+ @child_modules.each_key {|child_mod| child_mod.on_ancestors_updated(genv, base_mod || self) }
346
+ @static_reads.each_value do |static_reads|
347
+ static_reads.each do |static_read|
348
+ genv.add_static_eval_queue(:static_read_changed, static_read)
349
+ end
350
+ end
351
+ @methods.each do |_, methods|
352
+ methods.each_value do |me|
353
+ me.method_call_boxes.each do |box|
354
+ genv.add_run(box)
355
+ end
356
+ end
357
+ end
358
+ @ivar_reads.each {|ivar_read| genv.add_run(ivar_read) }
359
+ @cvar_reads.each {|cvar_read| genv.add_run(cvar_read) }
360
+ end
361
+
362
+ def each_descendant(base_mod = nil, &blk)
363
+ return if base_mod == self
364
+ yield self
365
+ @child_modules.each_key do |child_mod|
366
+ child_mod.each_descendant(base_mod || self, &blk)
367
+ end
368
+ end
369
+
370
+ def get_const(cname)
371
+ @consts[cname] ||= ValueEntity.new
372
+ end
373
+
374
+ def get_method(singleton, mid)
375
+ @methods[singleton][mid] ||= MethodEntity.new
376
+ end
377
+
378
+ def get_ivar(singleton, name)
379
+ @ivars[singleton][name] ||= ValueEntity.new
380
+ end
381
+
382
+ def get_cvar(name)
383
+ @cvars[name] ||= ValueEntity.new
384
+ end
385
+
386
+ def get_type_alias(name)
387
+ @type_aliases[name] ||= TypeAliasEntity.new
388
+ end
389
+
390
+ def get_vertexes(vtxs)
391
+ @inner_modules.each_value do |mod|
392
+ next if self.equal?(mod) # for Object
393
+ mod.get_vertexes(vtxs)
394
+ end
395
+ @consts.each_value do |cdef|
396
+ vtxs << cdef.vtx
397
+ end
398
+ end
399
+
400
+ def show_cpath
401
+ @cpath.empty? ? "Object" : @cpath.join("::" )
402
+ end
403
+
404
+ def pretty_print(q)
405
+ q.text "#<ModuleEntity[::#{ @cpath.empty? ? "Object" : @cpath.join("::") }]>"
406
+ end
407
+ end
408
+ end