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,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,251 @@
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
+ box.ret
128
+ end
129
+
130
+ def block_last_stmt_code_range
131
+ if @block_body
132
+ if @block_body.is_a?(AST::StatementsNode)
133
+ @block_body.stmts.last.code_range
134
+ else
135
+ @block_body.code_range
136
+ end
137
+ else
138
+ nil
139
+ end
140
+ end
141
+
142
+ def retrieve_at(pos, &blk)
143
+ yield self if @mid_code_range && @mid_code_range.include?(pos)
144
+ each_subnode do |subnode|
145
+ next unless subnode
146
+ subnode.retrieve_at(pos, &blk)
147
+ end
148
+ end
149
+
150
+ def modified_vars(tbl, vars)
151
+ subnodes.each do |key, subnode|
152
+ next unless subnode
153
+ if key == :block_body
154
+ subnode.modified_vars(tbl - self.block_tbl, vars)
155
+ elsif subnode.is_a?(AST::Node)
156
+ subnode.modified_vars(tbl, vars)
157
+ else
158
+ subnode.each {|n| n.modified_vars(tbl, vars) }
159
+ end
160
+ end
161
+ end
162
+ end
163
+
164
+ class CallNode < CallBaseNode
165
+ def initialize(raw_node, lenv)
166
+ recv = raw_node.receiver ? AST.create_node(raw_node.receiver, lenv) : nil
167
+ mid = raw_node.name
168
+ mid_code_range = TypeProf::CodeRange.from_node(raw_node.message_loc) if raw_node.message_loc
169
+ raw_args = raw_node.arguments
170
+ raw_block = raw_node.block
171
+ super(raw_node, recv, mid, mid_code_range, raw_args, nil, raw_block, lenv)
172
+ end
173
+ end
174
+
175
+ class SuperNode < CallBaseNode
176
+ def initialize(raw_node, lenv)
177
+ raw_args = raw_node.arguments
178
+ raw_block = raw_node.block
179
+ super(raw_node, nil, :"*super", nil, raw_args, nil, raw_block, lenv)
180
+ end
181
+ end
182
+
183
+ class ForwardingSuperNode < CallBaseNode
184
+ def initialize(raw_node, lenv)
185
+ raw_args = nil # TODO: forward args properly
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 YieldNode < CallBaseNode
192
+ def initialize(raw_node, lenv)
193
+ raw_args = raw_node.arguments
194
+ super(raw_node, nil, :call, nil, raw_args, nil, nil, lenv)
195
+ end
196
+ end
197
+
198
+ class OperatorNode < CallBaseNode
199
+ def initialize(raw_node, recv, lenv)
200
+ mid = raw_node.binary_operator
201
+ mid_code_range = TypeProf::CodeRange.from_node(raw_node.binary_operator_loc)
202
+ last_arg = AST.create_node(raw_node.value, lenv)
203
+ super(raw_node, recv, mid, mid_code_range, nil, last_arg, nil, lenv)
204
+ end
205
+ end
206
+
207
+ class IndexReadNode < CallBaseNode
208
+ def initialize(raw_node, lenv)
209
+ recv = AST.create_node(raw_node.receiver, lenv)
210
+ mid = :[]
211
+ mid_code_range = nil
212
+ raw_args = raw_node.arguments
213
+ super(raw_node, recv, mid, mid_code_range, raw_args, nil, nil, lenv)
214
+ end
215
+ end
216
+
217
+ class IndexWriteNode < CallBaseNode
218
+ def initialize(raw_node, rhs, lenv)
219
+ recv = AST.create_node(raw_node.receiver, lenv)
220
+ mid = :[]=
221
+ mid_code_range = nil
222
+ raw_args = raw_node.arguments
223
+ @rhs = rhs
224
+ super(raw_node, recv, mid, mid_code_range, raw_args, rhs, nil, lenv)
225
+ end
226
+
227
+ attr_reader :rhs
228
+ end
229
+
230
+ class CallReadNode < CallBaseNode
231
+ def initialize(raw_node, lenv)
232
+ recv = AST.create_node(raw_node.receiver, lenv)
233
+ mid = raw_node.read_name
234
+ mid_code_range = TypeProf::CodeRange.from_node(raw_node.message_loc)
235
+ super(raw_node, recv, mid, mid_code_range, nil, nil, nil, lenv)
236
+ end
237
+ end
238
+
239
+ class CallWriteNode < CallBaseNode
240
+ def initialize(raw_node, rhs, lenv)
241
+ recv = AST.create_node(raw_node.receiver, lenv)
242
+ mid = raw_node.is_a?(Prism::CallTargetNode) ? raw_node.name : raw_node.write_name
243
+ mid_code_range = TypeProf::CodeRange.from_node(raw_node.message_loc)
244
+ @rhs = rhs
245
+ super(raw_node, recv, mid, mid_code_range, nil, rhs, nil, lenv)
246
+ end
247
+
248
+ attr_reader :rhs
249
+ end
250
+ end
251
+ end