typeprof 0.21.11 → 0.30.0

Sign up to get free protection for your applications and to get access to all the features.
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