Skip to content

Commit 6dae086

Browse files
mameclaude
andcommitted
Add attr_writer support
Implement AttrWriterMetaNode to handle attr_writer declarations, generating setter methods that write to instance variables. Previously attr_writer was silently ignored. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 5bfa9ff commit 6dae086

3 files changed

Lines changed: 75 additions & 0 deletions

File tree

lib/typeprof/core/ast.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,8 @@ def self.create_node(raw_node, lenv, use_result = true, allow_meta = false)
278278
return IncludeMetaNode.new(raw_node, lenv)
279279
when :attr_reader
280280
return AttrReaderMetaNode.new(raw_node, lenv)
281+
when :attr_writer
282+
return AttrWriterMetaNode.new(raw_node, lenv)
281283
when :attr_accessor
282284
return AttrAccessorMetaNode.new(raw_node, lenv)
283285
when :module_function

lib/typeprof/core/ast/meta.rb

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,62 @@ def install0(genv)
8686
end
8787
end
8888

89+
class AttrWriterMetaNode < Node
90+
def initialize(raw_node, lenv)
91+
super(raw_node, lenv)
92+
@args = []
93+
raw_node.arguments.arguments.each do |raw_arg|
94+
@args << raw_arg.value.to_sym if raw_arg.type == :symbol_node
95+
end
96+
end
97+
98+
attr_reader :args
99+
100+
def attrs = { args: }
101+
102+
def mname_code_range(name)
103+
idx = @args.index(name.to_sym)
104+
node = @raw_node.arguments.arguments[idx].location
105+
@lenv.code_range_from_node(node)
106+
end
107+
108+
def define0(genv)
109+
@args.map do |arg|
110+
mod = genv.resolve_ivar(lenv.cref.cpath, false, :"@#{ arg }")
111+
mod.add_def(self)
112+
mod
113+
end
114+
end
115+
116+
def define_copy(genv)
117+
@args.map do |arg|
118+
mod = genv.resolve_ivar(lenv.cref.cpath, false, :"@#{ arg }")
119+
mod.add_def(self)
120+
mod.remove_def(@prev_node)
121+
mod
122+
end
123+
super(genv)
124+
end
125+
126+
def undefine0(genv)
127+
@args.each do |arg|
128+
mod = genv.resolve_ivar(lenv.cref.cpath, false, :"@#{ arg }")
129+
mod.remove_def(self)
130+
end
131+
end
132+
133+
def install0(genv)
134+
@args.zip(@static_ret) do |arg, ive|
135+
vtx = Vertex.new(self)
136+
@changes.add_edge(genv, vtx, ive.vtx)
137+
ret_box = @changes.add_escape_box(genv, vtx)
138+
f_args = FormalArguments.new([vtx], [], nil, [], [], [], nil, nil)
139+
@changes.add_method_def_box(genv, @lenv.cref.cpath, false, :"#{ arg }=", f_args, [ret_box])
140+
end
141+
Source.new
142+
end
143+
end
144+
89145
class AttrAccessorMetaNode < Node
90146
def initialize(raw_node, lenv)
91147
super(raw_node, lenv)

scenario/misc/attr_writer.rb

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
## update
2+
class Foo
3+
attr_writer :x
4+
5+
def get_x
6+
@x
7+
end
8+
end
9+
10+
Foo.new.x = 1
11+
Foo.new.get_x
12+
13+
## assert
14+
class Foo
15+
def x=: (Integer) -> Integer
16+
def get_x: -> Integer
17+
end

0 commit comments

Comments
 (0)