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,112 @@
1
+ module TypeProf
2
+ class CodePosition
3
+ def initialize(lineno, column)
4
+ @lineno = lineno
5
+ @column = column
6
+ end
7
+
8
+ def self.from_lsp(pos)
9
+ new(pos[:line] + 1, pos[:character])
10
+ end
11
+
12
+ def to_lsp
13
+ { line: @lineno - 1, character: @column }
14
+ end
15
+
16
+ attr_reader :lineno, :column
17
+
18
+ def <=>(other)
19
+ cmp = @lineno <=> other.lineno
20
+ cmp == 0 ? @column <=> other.column : cmp
21
+ end
22
+
23
+ include Comparable
24
+
25
+ def ==(other)
26
+ @lineno == other.lineno && @column == other.column
27
+ end
28
+
29
+ alias eql? ==
30
+
31
+ def hash
32
+ [@lineno, @column].hash
33
+ end
34
+
35
+ def to_s
36
+ "(%d,%d)" % [@lineno, @column]
37
+ end
38
+
39
+ alias inspect to_s
40
+
41
+ def left
42
+ raise if @column == 0
43
+ CodePosition.new(@lineno, @column - 1)
44
+ end
45
+
46
+ def right
47
+ CodePosition.new(@lineno, @column + 1)
48
+ end
49
+ end
50
+
51
+ class CodeRange
52
+ def initialize(first, last)
53
+ @first = first
54
+ @last = last
55
+ raise unless first
56
+ end
57
+
58
+ def self.from_node(node, encoding = Encoding::UTF_16LE)
59
+ node = node.location if node.is_a?(Prism::Node)
60
+ if node.is_a?(Prism::Location)
61
+ pos1 = CodePosition.new(node.start_line, node.start_code_units_column(encoding))
62
+ pos2 = CodePosition.new(node.end_line, node.end_code_units_column(encoding))
63
+ elsif node.respond_to?(:location)
64
+ loc = node.location
65
+ row, col = loc.start_loc
66
+ pos1 = CodePosition.new(row, col) # TODO: use SPLAT
67
+ row, col = loc.end_loc
68
+ pos2 = CodePosition.new(row, col)
69
+ else
70
+ p node.class.ancestors
71
+ raise "unknown type: #{ node.class }"
72
+ end
73
+ new(pos1, pos2)
74
+ end
75
+
76
+ def self.[](a, b, c, d)
77
+ pos1 = CodePosition.new(a, b)
78
+ pos2 = CodePosition.new(c, d)
79
+ new(pos1, pos2)
80
+ end
81
+
82
+ def to_lsp
83
+ { start: @first.to_lsp, end: @last.to_lsp }
84
+ end
85
+
86
+ attr_reader :first, :last
87
+
88
+ def include?(pos)
89
+ @first <= pos && pos < @last
90
+ end
91
+
92
+ def ==(other)
93
+ @first == other.first && @last == other.last
94
+ end
95
+
96
+ alias eql? ==
97
+
98
+ def hash
99
+ [@first, @last].hash
100
+ end
101
+
102
+ def to_s
103
+ "%p-%p" % [@first, @last]
104
+ end
105
+
106
+ alias inspect to_s
107
+
108
+ def ==(other)
109
+ @first == other.first && @last == other.last
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,263 @@
1
+ module TypeProf::Core
2
+ class AST
3
+ class Node
4
+ def initialize(raw_node, lenv)
5
+ @raw_node = raw_node
6
+ @lenv = lenv
7
+ @prev_node = nil
8
+ @static_ret = nil
9
+ @ret = nil
10
+
11
+ @changes = ChangeSet.new(self, nil)
12
+ end
13
+
14
+ attr_reader :lenv
15
+ attr_reader :prev_node
16
+ attr_reader :static_ret
17
+ attr_reader :ret
18
+ attr_reader :changes
19
+
20
+ def subnodes = {}
21
+ def attrs = {}
22
+
23
+ #: { (TypeProf::Core::AST::Node) -> void } -> nil
24
+ def each_subnode
25
+ queue = subnodes.values
26
+
27
+ until queue.empty?
28
+ subnode = queue.shift
29
+ next unless subnode
30
+
31
+ case subnode
32
+ when AST::Node
33
+ yield subnode
34
+ when Array
35
+ queue.unshift(*subnode)
36
+ when Hash
37
+ queue.unshift(*subnode.values)
38
+ else
39
+ raise subnode.class.to_s
40
+ end
41
+ end
42
+ end
43
+
44
+ def traverse(&blk)
45
+ yield :enter, self
46
+ each_subnode do |subnode|
47
+ subnode.traverse(&blk)
48
+ end
49
+ yield :leave, self
50
+ end
51
+
52
+ def code_range
53
+ if @raw_node
54
+ TypeProf::CodeRange.from_node(@raw_node)
55
+ else
56
+ pp self
57
+ raise
58
+ end
59
+ end
60
+
61
+ def define(genv)
62
+ @static_ret = define0(genv)
63
+ end
64
+
65
+ def define_copy(genv)
66
+ @lenv = @prev_node.lenv
67
+ each_subnode do |subnode|
68
+ subnode.define_copy(genv)
69
+ end
70
+ @prev_node.instance_variable_set(:@reused, true)
71
+ @static_ret = @prev_node.static_ret
72
+ end
73
+
74
+ def define0(genv)
75
+ each_subnode do |subnode|
76
+ subnode.define(genv)
77
+ end
78
+ return nil
79
+ end
80
+
81
+ def undefine(genv)
82
+ unless @reused
83
+ undefine0(genv)
84
+ end
85
+ end
86
+
87
+ def undefine0(genv)
88
+ each_subnode do |subnode|
89
+ subnode.undefine(genv)
90
+ end
91
+ end
92
+
93
+ def install(genv)
94
+ @ret = install0(genv)
95
+ @changes.reinstall(genv)
96
+ @ret
97
+ end
98
+
99
+ def install_copy(genv)
100
+ @changes.copy_from(@prev_node.changes)
101
+ @changes.reuse(self)
102
+ each_subnode do |subnode|
103
+ subnode.install_copy(genv)
104
+ end
105
+ @ret = @prev_node.ret
106
+ end
107
+
108
+ def install0(_)
109
+ raise "should override"
110
+ end
111
+
112
+ def uninstall(genv)
113
+ @changes.reinstall(genv)
114
+ each_subnode do |subnode|
115
+ subnode.uninstall(genv)
116
+ end
117
+ end
118
+
119
+ def diff(prev_node)
120
+ if prev_node.is_a?(self.class) && attrs.all? {|key, attr| attr == prev_node.send(key) }
121
+ raise unless prev_node # annotation
122
+ s1 = subnodes
123
+ s2 = prev_node.subnodes
124
+ return if s1.keys != s2.keys
125
+ s1.each do |key, subnode|
126
+ prev_subnode = s2[key]
127
+ if subnode && prev_subnode
128
+ subnode = [subnode] if subnode.is_a?(AST::Node)
129
+ prev_subnode = [prev_subnode] if prev_subnode.is_a?(AST::Node)
130
+ subnode.zip(prev_subnode) do |subnode0, prev_subnode0|
131
+ next if subnode0 == nil && prev_subnode0 == nil
132
+ subnode0.diff(prev_subnode0)
133
+ return unless subnode0.prev_node
134
+ end
135
+ else
136
+ return if subnode != prev_subnode
137
+ end
138
+ end
139
+ @prev_node = prev_node
140
+ end
141
+ end
142
+
143
+ def retrieve_at(pos, &blk)
144
+ if code_range.include?(pos)
145
+ each_subnode do |subnode|
146
+ subnode.retrieve_at(pos, &blk)
147
+ end
148
+ yield self
149
+ end
150
+ end
151
+
152
+ def boxes(key)
153
+ @changes.boxes.each do |(k, *), box|
154
+ # TODO: make it recursive
155
+ box.changes.boxes.each do |(k, *), box|
156
+ yield box if k == key
157
+ end
158
+ yield box if k == key
159
+ end
160
+ end
161
+
162
+ def diagnostics(genv, &blk)
163
+ @changes.diagnostics.each(&blk)
164
+ @changes.boxes.each_value do |box|
165
+ box.diagnostics(genv, &blk)
166
+ end
167
+ each_subnode do |subnode|
168
+ subnode.diagnostics(genv, &blk)
169
+ end
170
+ end
171
+
172
+ def get_vertexes(vtxs)
173
+ return if @reused
174
+ @changes.boxes.each_value do |box|
175
+ vtxs << box.ret
176
+ end
177
+ vtxs << @ret
178
+ each_subnode do |subnode|
179
+ subnode.get_vertexes(vtxs)
180
+ end
181
+ end
182
+
183
+ def modified_vars(tbl, vars)
184
+ each_subnode do |subnode|
185
+ subnode.modified_vars(tbl, vars)
186
+ end
187
+ end
188
+
189
+ def pretty_print_instance_variables
190
+ super() - [:@raw_node, :@lenv, :@prev_node, :@static_ret, :@changes]
191
+ end
192
+ end
193
+
194
+ class ProgramNode < Node
195
+ def initialize(raw_node, lenv)
196
+ super(raw_node, lenv)
197
+
198
+ @tbl = raw_node.locals
199
+ raw_body = raw_node.statements
200
+
201
+ @body = AST.create_node(raw_body, lenv, false)
202
+ end
203
+
204
+ attr_reader :tbl, :body
205
+
206
+ def subnodes = { body: }
207
+ def attrs = { tbl: }
208
+
209
+ def install0(genv)
210
+ @tbl.each {|var| @lenv.locals[var] = Source.new(genv.nil_type) }
211
+ @lenv.locals[:"*self"] = lenv.cref.get_self(genv)
212
+
213
+ # for toplevel return
214
+ @body.lenv.locals[:"*expected_method_ret"] = Vertex.new(self)
215
+ @body.install(genv)
216
+ end
217
+ end
218
+
219
+ class DummyNilNode < Node
220
+ def initialize(code_range, lenv)
221
+ @code_range = code_range
222
+ super(nil, lenv)
223
+ end
224
+
225
+ def code_range
226
+ @code_range
227
+ end
228
+
229
+ def install0(genv)
230
+ Source.new(genv.nil_type)
231
+ end
232
+ end
233
+
234
+ class DummyRHSNode < Node
235
+ def initialize(code_range, lenv)
236
+ @code_range = code_range
237
+ super(nil, lenv)
238
+ end
239
+
240
+ def code_range
241
+ @code_range
242
+ end
243
+
244
+ def install0(_)
245
+ Vertex.new(self)
246
+ end
247
+ end
248
+
249
+ class DummySymbolNode
250
+ def initialize(sym, code_range, ret)
251
+ @sym = sym
252
+ @code_range = code_range
253
+ @ret = ret
254
+ end
255
+
256
+ attr_reader :lenv, :prev_node, :ret
257
+
258
+ def boxes(_)
259
+ []
260
+ end
261
+ end
262
+ end
263
+ end
@@ -0,0 +1,259 @@
1
+ module TypeProf::Core
2
+ class AST
3
+ class CallBaseNode < Node
4
+ def initialize(raw_node, recv, mid, mid_code_range, raw_args, last_arg, raw_block, lenv)
5
+ super(raw_node, lenv)
6
+
7
+ @recv = recv
8
+ @mid = mid
9
+ @mid_code_range = mid_code_range
10
+
11
+ # args
12
+ @positional_args = []
13
+ @splat_flags = []
14
+ @keyword_args = nil
15
+
16
+ @block_pass = nil
17
+ @block_tbl = nil
18
+ @block_f_args = nil
19
+ @block_body = nil
20
+
21
+ if raw_args
22
+ args = []
23
+ @splat_flags = []
24
+ raw_args.arguments.each do |raw_arg|
25
+ if raw_arg.is_a?(Prism::SplatNode)
26
+ args << raw_arg.expression
27
+ @splat_flags << true
28
+ else
29
+ args << raw_arg
30
+ @splat_flags << false
31
+ end
32
+ end
33
+ @positional_args = args.map {|arg| AST.create_node(arg, lenv) }
34
+
35
+ if @positional_args.last.is_a?(TypeProf::Core::AST::HashNode) && @positional_args.last.keywords
36
+ @keyword_args = @positional_args.pop
37
+ end
38
+ end
39
+
40
+ @positional_args << last_arg if last_arg
41
+
42
+ if raw_block
43
+ if raw_block.type == :block_argument_node
44
+ @block_pass = AST.create_node(raw_block.expression, lenv)
45
+ else
46
+ @block_pass = nil
47
+ @block_tbl = raw_block.locals
48
+ # TODO: optional args, etc.
49
+ @block_f_args = case raw_block.parameters
50
+ when Prism::BlockParametersNode
51
+ raw_block.parameters.parameters.requireds.map {|n| n.is_a?(Prism::MultiTargetNode) ? nil : n.name }
52
+ when Prism::NumberedParametersNode
53
+ 1.upto(raw_block.parameters.maximum).map { |n| :"_#{n}" }
54
+ when nil
55
+ []
56
+ else
57
+ raise "not supported yet: #{ raw_block.parameters.class }"
58
+ end
59
+ ncref = CRef.new(lenv.cref.cpath, :instance, @mid, lenv.cref)
60
+ nlenv = LocalEnv.new(@lenv.path, ncref, {}, @lenv.return_boxes)
61
+ @block_body = raw_block.body ? AST.create_node(raw_block.body, nlenv) : DummyNilNode.new(code_range, lenv)
62
+ end
63
+ end
64
+
65
+ @yield = raw_node.type == :yield_node
66
+ end
67
+
68
+ attr_reader :recv, :mid, :mid_code_range, :yield
69
+ attr_reader :positional_args, :splat_flags, :keyword_args
70
+ attr_reader :block_tbl, :block_f_args, :block_body, :block_pass
71
+
72
+ def subnodes = { recv:, positional_args:, keyword_args:, block_body:, block_pass: }
73
+ def attrs = { mid:, splat_flags:, block_tbl:, block_f_args:, yield: }
74
+
75
+ def install0(genv)
76
+ recv = @recv ? @recv.install(genv) : @yield ? @lenv.get_var(:"*given_block") : @lenv.get_var(:"*self")
77
+
78
+ positional_args = @positional_args.map do |arg|
79
+ arg.install(genv)
80
+ end
81
+
82
+ keyword_args = @keyword_args ? @keyword_args.install(genv) : nil
83
+
84
+ if @block_body
85
+ @lenv.locals.each {|var, vtx| @block_body.lenv.locals[var] = vtx }
86
+ @block_tbl.each {|var| @block_body.lenv.locals[var] = Source.new(genv.nil_type) }
87
+ @block_body.lenv.locals[:"*self"] = @block_body.lenv.cref.get_self(genv)
88
+
89
+ blk_f_args = []
90
+ if @block_f_args
91
+ @block_f_args.each do |arg|
92
+ blk_f_args << @block_body.lenv.new_var(arg, self)
93
+ end
94
+ end
95
+
96
+ @lenv.locals.each do |var, vtx|
97
+ @block_body.lenv.set_var(var, vtx)
98
+ end
99
+ vars = []
100
+ @block_body.modified_vars(@lenv.locals.keys - @block_tbl, vars)
101
+ vars.uniq!
102
+ vars.each do |var|
103
+ vtx = @lenv.get_var(var)
104
+ nvtx = vtx.new_vertex(genv, self)
105
+ @lenv.set_var(var, nvtx)
106
+ @block_body.lenv.set_var(var, nvtx)
107
+ end
108
+
109
+ e_ret = @block_body.lenv.locals[:"*expected_block_ret"] = Vertex.new(self)
110
+ @block_body.install(genv)
111
+ @block_body.lenv.add_next_box(@changes.add_escape_box(genv, @block_body.ret, e_ret))
112
+
113
+ vars.each do |var|
114
+ @changes.add_edge(genv, @block_body.lenv.get_var(var), @lenv.get_var(var))
115
+ end
116
+
117
+ blk_f_ary_arg = Vertex.new(self)
118
+ @changes.add_masgn_box(genv, blk_f_ary_arg, blk_f_args, nil, nil) # TODO: support splat "do |a, *b, c|"
119
+ block = Block.new(self, blk_f_ary_arg, blk_f_args, @block_body.lenv.next_boxes)
120
+ blk_ty = Source.new(Type::Proc.new(genv, block))
121
+ elsif @block_pass
122
+ blk_ty = @block_pass.install(genv)
123
+ end
124
+
125
+ a_args = ActualArguments.new(positional_args, @splat_flags, keyword_args, blk_ty)
126
+ box = @changes.add_method_call_box(genv, recv, @mid, a_args, !@recv)
127
+
128
+ if @block_body && @block_body.lenv.break_vtx
129
+ ret = Vertex.new(self)
130
+ @changes.add_edge(genv, box.ret, ret)
131
+ @changes.add_edge(genv, @block_body.lenv.break_vtx, ret)
132
+ ret
133
+ else
134
+ box.ret
135
+ end
136
+ end
137
+
138
+ def block_last_stmt_code_range
139
+ if @block_body
140
+ if @block_body.is_a?(AST::StatementsNode)
141
+ @block_body.stmts.last.code_range
142
+ else
143
+ @block_body.code_range
144
+ end
145
+ else
146
+ nil
147
+ end
148
+ end
149
+
150
+ def retrieve_at(pos, &blk)
151
+ yield self if @mid_code_range && @mid_code_range.include?(pos)
152
+ each_subnode do |subnode|
153
+ next unless subnode
154
+ subnode.retrieve_at(pos, &blk)
155
+ end
156
+ end
157
+
158
+ def modified_vars(tbl, vars)
159
+ subnodes.each do |key, subnode|
160
+ next unless subnode
161
+ if key == :block_body
162
+ subnode.modified_vars(tbl - self.block_tbl, vars)
163
+ elsif subnode.is_a?(AST::Node)
164
+ subnode.modified_vars(tbl, vars)
165
+ else
166
+ subnode.each {|n| n.modified_vars(tbl, vars) }
167
+ end
168
+ end
169
+ end
170
+ end
171
+
172
+ class CallNode < CallBaseNode
173
+ def initialize(raw_node, lenv)
174
+ recv = raw_node.receiver ? AST.create_node(raw_node.receiver, lenv) : nil
175
+ mid = raw_node.name
176
+ mid_code_range = TypeProf::CodeRange.from_node(raw_node.message_loc) if raw_node.message_loc
177
+ raw_args = raw_node.arguments
178
+ raw_block = raw_node.block
179
+ super(raw_node, recv, mid, mid_code_range, raw_args, nil, raw_block, lenv)
180
+ end
181
+ end
182
+
183
+ class SuperNode < CallBaseNode
184
+ def initialize(raw_node, lenv)
185
+ raw_args = raw_node.arguments
186
+ raw_block = raw_node.block
187
+ super(raw_node, nil, :"*super", nil, raw_args, nil, raw_block, lenv)
188
+ end
189
+ end
190
+
191
+ class ForwardingSuperNode < CallBaseNode
192
+ def initialize(raw_node, lenv)
193
+ raw_args = nil # TODO: forward args properly
194
+ raw_block = raw_node.block
195
+ super(raw_node, nil, :"*super", nil, raw_args, nil, raw_block, lenv)
196
+ end
197
+ end
198
+
199
+ class YieldNode < CallBaseNode
200
+ def initialize(raw_node, lenv)
201
+ raw_args = raw_node.arguments
202
+ super(raw_node, nil, :call, nil, raw_args, nil, nil, lenv)
203
+ end
204
+ end
205
+
206
+ class OperatorNode < CallBaseNode
207
+ def initialize(raw_node, recv, lenv)
208
+ mid = raw_node.binary_operator
209
+ mid_code_range = TypeProf::CodeRange.from_node(raw_node.binary_operator_loc)
210
+ last_arg = AST.create_node(raw_node.value, lenv)
211
+ super(raw_node, recv, mid, mid_code_range, nil, last_arg, nil, lenv)
212
+ end
213
+ end
214
+
215
+ class IndexReadNode < CallBaseNode
216
+ def initialize(raw_node, lenv)
217
+ recv = AST.create_node(raw_node.receiver, lenv)
218
+ mid = :[]
219
+ mid_code_range = nil
220
+ raw_args = raw_node.arguments
221
+ super(raw_node, recv, mid, mid_code_range, raw_args, nil, nil, lenv)
222
+ end
223
+ end
224
+
225
+ class IndexWriteNode < CallBaseNode
226
+ def initialize(raw_node, rhs, lenv)
227
+ recv = AST.create_node(raw_node.receiver, lenv)
228
+ mid = :[]=
229
+ mid_code_range = nil
230
+ raw_args = raw_node.arguments
231
+ @rhs = rhs
232
+ super(raw_node, recv, mid, mid_code_range, raw_args, rhs, nil, lenv)
233
+ end
234
+
235
+ attr_reader :rhs
236
+ end
237
+
238
+ class CallReadNode < CallBaseNode
239
+ def initialize(raw_node, lenv)
240
+ recv = AST.create_node(raw_node.receiver, lenv)
241
+ mid = raw_node.read_name
242
+ mid_code_range = TypeProf::CodeRange.from_node(raw_node.message_loc)
243
+ super(raw_node, recv, mid, mid_code_range, nil, nil, nil, lenv)
244
+ end
245
+ end
246
+
247
+ class CallWriteNode < CallBaseNode
248
+ def initialize(raw_node, rhs, lenv)
249
+ recv = AST.create_node(raw_node.receiver, lenv)
250
+ mid = raw_node.is_a?(Prism::CallTargetNode) ? raw_node.name : raw_node.write_name
251
+ mid_code_range = TypeProf::CodeRange.from_node(raw_node.message_loc)
252
+ @rhs = rhs
253
+ super(raw_node, recv, mid, mid_code_range, nil, rhs, nil, lenv)
254
+ end
255
+
256
+ attr_reader :rhs
257
+ end
258
+ end
259
+ end