typeprof 0.21.11 → 0.30.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) 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 +178 -0
  7. data/lib/typeprof/cli.rb +3 -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 +259 -0
  11. data/lib/typeprof/core/ast/const.rb +126 -0
  12. data/lib/typeprof/core/ast/control.rb +433 -0
  13. data/lib/typeprof/core/ast/meta.rb +150 -0
  14. data/lib/typeprof/core/ast/method.rb +339 -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 +366 -0
  31. data/lib/typeprof/core/graph/box.rb +998 -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 +225 -0
  35. data/lib/typeprof/core/service.rb +514 -0
  36. data/lib/typeprof/core/type.rb +352 -0
  37. data/lib/typeprof/core/util.rb +81 -0
  38. data/lib/typeprof/core.rb +31 -0
  39. data/lib/typeprof/diagnostic.rb +35 -0
  40. data/lib/typeprof/lsp/messages.rb +415 -0
  41. data/lib/typeprof/lsp/server.rb +203 -0
  42. data/lib/typeprof/lsp/text.rb +69 -0
  43. data/lib/typeprof/lsp/util.rb +51 -0
  44. data/lib/typeprof/lsp.rb +4 -907
  45. data/lib/typeprof/version.rb +1 -1
  46. data/lib/typeprof.rb +4 -18
  47. data/typeprof.gemspec +5 -7
  48. metadata +47 -33
  49. data/.github/dependabot.yml +0 -6
  50. data/.github/workflows/main.yml +0 -39
  51. data/.gitignore +0 -9
  52. data/Gemfile +0 -17
  53. data/Gemfile.lock +0 -41
  54. data/Rakefile +0 -10
  55. data/exe/typeprof +0 -10
  56. data/lib/typeprof/analyzer.rb +0 -2598
  57. data/lib/typeprof/arguments.rb +0 -414
  58. data/lib/typeprof/block.rb +0 -176
  59. data/lib/typeprof/builtin.rb +0 -893
  60. data/lib/typeprof/code-range.rb +0 -177
  61. data/lib/typeprof/config.rb +0 -158
  62. data/lib/typeprof/container-type.rb +0 -912
  63. data/lib/typeprof/export.rb +0 -589
  64. data/lib/typeprof/import.rb +0 -852
  65. data/lib/typeprof/insns-def.rb +0 -65
  66. data/lib/typeprof/iseq.rb +0 -864
  67. data/lib/typeprof/method.rb +0 -355
  68. data/lib/typeprof/type.rb +0 -1140
  69. data/lib/typeprof/utils.rb +0 -212
  70. data/tools/coverage.rb +0 -14
  71. data/tools/setup-insns-def.rb +0 -30
  72. 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