Skip to content

Commit

Permalink
Fixed AST::Node#updated to always return a copy. (#25)
Browse files Browse the repository at this point in the history
Previously it relied on a call chain #initialize -> #freeze that returns `self`.
However, overriding constructor in a custom subclass and returning something else breaks `updated`.
  • Loading branch information
iliabylich committed Jun 10, 2020
1 parent 05d2321 commit 9a0bfdb
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 1 deletion.
4 changes: 3 additions & 1 deletion lib/ast/node.rb
Expand Up @@ -140,7 +140,9 @@ def updated(type=nil, children=nil, properties=nil)
properties.nil?
self
else
original_dup.send :initialize, new_type, new_children, new_properties
copy = original_dup
copy.send :initialize, new_type, new_children, new_properties
copy
end
end

Expand Down
14 changes: 14 additions & 0 deletions test/test_ast.rb
Expand Up @@ -7,9 +7,17 @@ class MetaNode < AST::Node
attr_reader :meta
end

class SubclassNode < AST::Node
def initialize(*)
super
nil
end
end

before do
@node = AST::Node.new(:node, [ 0, 1 ])
@metanode = MetaNode.new(:node, [ 0, 1 ], :meta => 'value')
@subclass_node = SubclassNode.new(:node, [ 0, 1 ])
end

it 'should have accessors for type and children' do
Expand Down Expand Up @@ -55,6 +63,12 @@ class MetaNode < AST::Node
updated.meta.should.equal 'other_value'
end

it 'returns updated node for subclasses that override constructor' do
updated = @subclass_node.updated(nil, [2])
updated.type.should.equal :node
updated.children.should.equal [2]
end

it 'should format to_sexp correctly' do
AST::Node.new(:a, [ :sym, [ 1, 2 ] ]).to_sexp.should.equal '(a :sym [1, 2])'
AST::Node.new(:a, [ :sym, @node ]).to_sexp.should.equal "(a :sym\n (node 0 1))"
Expand Down

0 comments on commit 9a0bfdb

Please sign in to comment.