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