typeprof 0.21.11 → 0.30.1

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 (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,352 @@
1
+ module TypeProf::Core
2
+ class Type
3
+ # This new method does memoize creation of types
4
+ #: (GlobalEnv, *untyped) -> instance
5
+ def self.new(genv, *args)
6
+ genv.type_table[[self] + args] ||= super(genv, *args)
7
+ end
8
+
9
+ def self.strip_parens(s)
10
+ #s =~ /\A\((.*)\)\z/ ? $1 : s
11
+ s.start_with?("(") && s.end_with?(")") ? s[1..-2] || raise : s
12
+ end
13
+
14
+ def self.strip_array(s)
15
+ s.start_with?("Array[") && s.end_with?("]") ? s[6..-2] || raise : s
16
+ end
17
+
18
+ def self.default_param_map(genv, ty)
19
+ ty = ty.base_type(genv)
20
+ instance_ty = ty.is_a?(Type::Instance) ? ty : Type::Instance.new(genv, ty.mod, []) # TODO: type params
21
+ singleton_ty = ty.is_a?(Type::Instance) ? Type::Singleton.new(genv, ty.mod) : ty
22
+ {
23
+ "*self": Source.new(ty),
24
+ "*instance": Source.new(instance_ty),
25
+ "*class": Source.new(singleton_ty),
26
+ }
27
+ end
28
+
29
+ class Singleton < Type
30
+ #: (GlobalEnv, ModuleEntity) -> void
31
+ def initialize(genv, mod)
32
+ raise unless mod.is_a?(ModuleEntity)
33
+ # TODO: type_param
34
+ @mod = mod
35
+ end
36
+
37
+ attr_reader :mod
38
+
39
+ def base_type(_)
40
+ self
41
+ end
42
+
43
+ def check_match(genv, changes, vtx)
44
+ vtx.each_type do |other_ty|
45
+ case other_ty
46
+ when Singleton
47
+ other_mod = other_ty.mod
48
+ if other_mod.module?
49
+ # TODO: implement
50
+ else
51
+ mod = @mod
52
+ while mod
53
+ return true if mod == other_mod
54
+ changes.add_depended_superclass(mod)
55
+ mod = mod.superclass
56
+ end
57
+ end
58
+ when Instance
59
+ base_ty = @mod.module? ? genv.mod_type : genv.cls_type
60
+ return true if base_ty.check_match(genv, changes, Source.new(other_ty))
61
+ end
62
+ end
63
+ return false
64
+ end
65
+
66
+ def show
67
+ "singleton(#{ @mod.show_cpath })"
68
+ end
69
+
70
+ def get_instance_type(genv)
71
+ params = @mod.type_params
72
+ Instance.new(genv, @mod, params ? params.map { Source.new } : [])
73
+ end
74
+ end
75
+
76
+ class Instance < Type
77
+ #: (GlobalEnv, ModuleEntity, ::Array[Vertex]) -> void
78
+ def initialize(genv, mod, args)
79
+ raise mod.class.to_s unless mod.is_a?(ModuleEntity)
80
+ @mod = mod
81
+ @args = args
82
+ raise unless @args.is_a?(::Array)
83
+ end
84
+
85
+ attr_reader :mod, :args
86
+
87
+ def base_type(_)
88
+ self
89
+ end
90
+
91
+ def check_match(genv, changes, vtx)
92
+ vtx.each_type do |other_ty|
93
+ case other_ty
94
+ when Instance
95
+ ty = self
96
+ while ty
97
+ if ty.mod == other_ty.mod
98
+ args_all_match = true
99
+ ty.args.zip(other_ty.args) do |arg, other_arg|
100
+ unless arg.check_match(genv, changes, other_arg)
101
+ args_all_match = false
102
+ break
103
+ end
104
+ end
105
+ return true if args_all_match
106
+ end
107
+ changes.add_depended_superclass(ty.mod)
108
+
109
+ if other_ty.mod.module?
110
+ return true if check_match_included_modules(genv, changes, ty, other_ty)
111
+ end
112
+
113
+ ty = genv.get_superclass_type(ty, changes, {})
114
+ end
115
+ end
116
+ end
117
+ return false
118
+ end
119
+
120
+ def check_match_included_modules(genv, changes, ty, other_ty)
121
+ ty.mod.included_modules.each do |inc_decl, inc_mod|
122
+ if inc_decl.is_a?(AST::SigIncludeNode) && inc_mod.type_params
123
+ inc_ty = genv.get_instance_type(inc_mod, inc_decl.args, changes, {}, ty)
124
+ else
125
+ type_params = inc_mod.type_params.map {|ty_param| Source.new() } # TODO: better support
126
+ inc_ty = Type::Instance.new(genv, inc_mod, type_params)
127
+ end
128
+ if inc_ty.mod == other_ty.mod
129
+ args_all_match = true
130
+ inc_ty.args.zip(other_ty.args) do |arg, other_arg|
131
+ if other_arg && !arg.check_match(genv, changes, other_arg)
132
+ args_all_match = false
133
+ break
134
+ end
135
+ end
136
+ return true if args_all_match
137
+ end
138
+ changes.add_depended_superclass(inc_ty.mod)
139
+
140
+ return true if check_match_included_modules(genv, changes, inc_ty, other_ty)
141
+ end
142
+ return false
143
+ end
144
+
145
+ def show
146
+ case @mod.cpath
147
+ when [:NilClass] then "nil"
148
+ when [:TrueClass] then "true"
149
+ when [:FalseClass] then "false"
150
+ else
151
+ "#{ @mod.show_cpath }#{ @args.empty? ? "" : "[#{ @args.map {|arg| Type.strip_parens(arg.show) }.join(", ") }]" }"
152
+ end
153
+ end
154
+ end
155
+
156
+ class Array < Type
157
+ #: (GlobalEnv, ::Array[Vertex], Instance) -> void
158
+ def initialize(genv, elems, base_type)
159
+ @elems = elems
160
+ @base_type = base_type
161
+ raise unless base_type.is_a?(Instance)
162
+ end
163
+
164
+ attr_reader :elems
165
+
166
+ def get_elem(genv, idx = nil)
167
+ if idx && @elems
168
+ @elems[idx] || Source.new(genv.nil_type)
169
+ else
170
+ @base_type.args.first
171
+ end
172
+ end
173
+
174
+ def splat_assign(genv, lefts, rest_elem, rights)
175
+ edges = []
176
+ state = :left
177
+ j = nil
178
+ @elems.each_with_index do |elem, i|
179
+ case state
180
+ when :left
181
+ if i < lefts.size
182
+ edges << [elem, lefts[i]]
183
+ else
184
+ break unless rest_elem
185
+ state = :rest
186
+ redo
187
+ end
188
+ when :rest
189
+ if @elems.size - i > rights.size
190
+ edges << [elem, rest_elem]
191
+ else
192
+ state = :right
193
+ j = i
194
+ redo
195
+ end
196
+ when :right
197
+ edges << [elem, rights[i - j]]
198
+ end
199
+ end
200
+ edges
201
+ end
202
+
203
+ def base_type(genv)
204
+ @base_type
205
+ end
206
+
207
+ def check_match(genv, changes, vtx)
208
+ vtx.each_type do |other_ty|
209
+ if other_ty.is_a?(Array)
210
+ if @elems.size == other_ty.elems.size
211
+ match = true
212
+ @elems.zip(other_ty.elems) do |elem, other_elem|
213
+ unless elem.check_match(genv, changes, other_elem)
214
+ match = false
215
+ break
216
+ end
217
+ end
218
+ return true if match
219
+ end
220
+ end
221
+ end
222
+ @base_type.check_match(genv, changes, vtx)
223
+ end
224
+
225
+ def show
226
+ if @elems
227
+ "[#{ @elems.map {|e| Type.strip_parens(e.show) }.join(", ") }]"
228
+ else
229
+ "#{ @base_type.mod.show_cpath }[#{ Type.strip_parens(@unified_elem.show) }]"
230
+ end
231
+ end
232
+ end
233
+
234
+ class Hash < Type
235
+ #: (GlobalEnv, ::Array[Vertex], Instance) -> void
236
+ def initialize(genv, literal_pairs, base_type)
237
+ @literal_pairs = literal_pairs
238
+ @base_type = base_type
239
+ raise unless base_type.is_a?(Instance)
240
+ end
241
+
242
+ def get_key
243
+ @base_type.args[0]
244
+ end
245
+
246
+ def get_value(key = nil)
247
+ @literal_pairs[key] || @base_type.args[1]
248
+ end
249
+
250
+ def base_type(genv)
251
+ @base_type
252
+ end
253
+
254
+ def check_match(genv, changes, vtx)
255
+ # TODO: implement
256
+ @base_type.check_match(genv, changes, vtx)
257
+ end
258
+
259
+ def show
260
+ @base_type.show
261
+ end
262
+ end
263
+
264
+ class Proc < Type
265
+ def initialize(genv, block)
266
+ @block = block
267
+ end
268
+
269
+ attr_reader :block
270
+
271
+ def base_type(genv)
272
+ genv.proc_type
273
+ end
274
+
275
+ def check_match(genv, changes, vtx)
276
+ genv.proc_type.check_match(genv, changes, vtx)
277
+ end
278
+
279
+ def show
280
+ "<Proc>"
281
+ end
282
+ end
283
+
284
+ class Symbol < Type
285
+ #: (GlobalEnv, ::Symbol) -> void
286
+ def initialize(genv, sym)
287
+ @sym = sym
288
+ end
289
+
290
+ attr_reader :sym
291
+
292
+ def base_type(genv)
293
+ genv.symbol_type
294
+ end
295
+
296
+ def check_match(genv, changes, vtx)
297
+ vtx.each_type do |other_ty|
298
+ case other_ty
299
+ when Symbol
300
+ return true if @sym == other_ty.sym
301
+ when Instance
302
+ return true if genv.symbol_type.check_match(genv, changes, Source.new(other_ty))
303
+ end
304
+ end
305
+ return false
306
+ end
307
+
308
+ def show
309
+ @sym.inspect
310
+ end
311
+ end
312
+
313
+ class Bot < Type
314
+ def initialize(genv)
315
+ end
316
+
317
+ def base_type(genv)
318
+ genv.obj_type
319
+ end
320
+
321
+ def check_match(genv, changes, vtx)
322
+ return true
323
+ end
324
+
325
+ def show
326
+ "bot"
327
+ end
328
+ end
329
+
330
+ class Var < Type
331
+ #: (GlobalEnv, ::Symbol, Vertex) -> void
332
+ def initialize(genv, name, vtx)
333
+ @name = name
334
+ @vtx = vtx
335
+ end
336
+
337
+ attr_reader :name, :vtx
338
+
339
+ def base_type(genv)
340
+ genv.obj_type # Is this ok?
341
+ end
342
+
343
+ def check_match(genv, changes, vtx)
344
+ true # should implement a better support...
345
+ end
346
+
347
+ def show
348
+ "var[#{ @name }]"
349
+ end
350
+ end
351
+ end
352
+ end
@@ -0,0 +1,81 @@
1
+ module TypeProf::Core
2
+ class Set
3
+ def self.[](*elems)
4
+ h = Hash.new(false)
5
+ elems.each {|elem| h[elem] = true }
6
+ new(h)
7
+ end
8
+
9
+ def initialize(hash)
10
+ @hash = hash
11
+ end
12
+
13
+ def internal_hash = @hash
14
+
15
+ def dup
16
+ Set.new(@hash.dup)
17
+ end
18
+
19
+ def <<(elem)
20
+ raise if @hash.include?(elem)
21
+ @hash[elem] = true
22
+ self
23
+ end
24
+
25
+ def include?(elem)
26
+ @hash[elem]
27
+ end
28
+
29
+ def merge(set)
30
+ raise NotImplementedError
31
+ end
32
+
33
+ def each(&blk)
34
+ @hash.each_key(&blk)
35
+ end
36
+
37
+ def empty?
38
+ @hash.empty?
39
+ end
40
+
41
+ def delete(elem)
42
+ raise unless @hash.include?(elem)
43
+ @hash.delete(elem)
44
+ end
45
+
46
+ def clear
47
+ @hash.clear
48
+ end
49
+
50
+ def to_a
51
+ @hash.keys
52
+ end
53
+
54
+ def size
55
+ @hash.size
56
+ end
57
+
58
+ def -(other)
59
+ h = @hash.dup
60
+ other.each do |elem|
61
+ h.delete(elem)
62
+ end
63
+ Set.new(h)
64
+ end
65
+
66
+ def pretty_print(q)
67
+ q.text "Set["
68
+ q.group do
69
+ q.nest(1) do
70
+ @hash.each_key do |elem|
71
+ q.breakable ""
72
+ q.pp elem
73
+ q.text ","
74
+ end
75
+ end
76
+ q.breakable ""
77
+ end
78
+ q.text "]"
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,31 @@
1
+ require "rbs"
2
+ require "prism"
3
+ require_relative "core/util"
4
+ require_relative "core/ast"
5
+ require_relative "core/ast/base"
6
+ require_relative "core/ast/module"
7
+ require_relative "core/ast/method"
8
+ require_relative "core/ast/call"
9
+ require_relative "core/ast/control"
10
+ require_relative "core/ast/const"
11
+ require_relative "core/ast/variable"
12
+ require_relative "core/ast/value"
13
+ require_relative "core/ast/misc"
14
+ require_relative "core/ast/meta"
15
+ require_relative "core/ast/pattern"
16
+ require_relative "core/ast/sig_decl"
17
+ require_relative "core/ast/sig_type"
18
+ require_relative "core/type"
19
+ require_relative "core/env"
20
+ require_relative "core/env/method_entity"
21
+ require_relative "core/env/module_entity"
22
+ require_relative "core/env/type_alias_entity"
23
+ require_relative "core/env/value_entity"
24
+ require_relative "core/env/method"
25
+ require_relative "core/env/static_read"
26
+ require_relative "core/graph/change_set"
27
+ require_relative "core/graph/vertex"
28
+ require_relative "core/graph/filter"
29
+ require_relative "core/graph/box"
30
+ require_relative "core/builtin"
31
+ require_relative "core/service"
@@ -0,0 +1,35 @@
1
+ module TypeProf
2
+ class Diagnostic
3
+ def initialize(node, meth, msg)
4
+ @node = node
5
+ @meth = meth
6
+ @msg = msg
7
+ @severity = :error # TODO: keyword argument
8
+ @tags = nil # TODO: keyword argument
9
+ end
10
+
11
+ def reuse(new_node)
12
+ @node = new_node
13
+ end
14
+
15
+ attr_reader :msg, :severity
16
+
17
+ def code_range
18
+ @node.send(@meth)
19
+ end
20
+
21
+ SEVERITY = { error: 1, warning: 2, info: 3, hint: 4 }
22
+ TAG = { unnecessary: 1, deprecated: 2 }
23
+
24
+ def to_lsp
25
+ json = {
26
+ range: code_range.to_lsp,
27
+ source: "TypeProf",
28
+ message: @msg,
29
+ }
30
+ json[:severity] = SEVERITY[@severity] if @severity
31
+ json[:tags] = @tags.map {|tag| TAG[tag] } if @tags
32
+ json
33
+ end
34
+ end
35
+ end