Skip to content

Commit b693c90

Browse files
timholyc42f
andauthored
Support copy for TreeNodes (#210)
Co-authored-by: c42f <[email protected]>
1 parent 9a038af commit b693c90

File tree

2 files changed

+23
-0
lines changed

2 files changed

+23
-0
lines changed

src/syntax_tree.jl

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,21 @@ function Base.push!(node::SN, child::SN) where SN<:AbstractSyntaxNode
244244
push!(args, child)
245245
end
246246

247+
function Base.copy(node::TreeNode)
248+
# copy the container but not the data (ie, deep copy the tree, shallow copy the data). copy(::Expr) is similar
249+
# copy "un-parents" the top-level `node` that you're copying
250+
newnode = typeof(node)(nothing, haschildren(node) ? typeof(node)[] : nothing, copy(node.data))
251+
for child in children(node)
252+
newchild = copy(child)
253+
newchild.parent = newnode
254+
push!(newnode, newchild)
255+
end
256+
return newnode
257+
end
258+
259+
# shallow-copy the data
260+
Base.copy(data::SyntaxData) = SyntaxData(data.source, data.raw, data.position, data.val)
261+
247262
function build_tree(::Type{SyntaxNode}, stream::ParseStream; filename=nothing, first_line=1, kws...)
248263
green_tree = build_tree(GreenNode, stream; kws...)
249264
source = SourceFile(sourcetext(stream), filename=filename, first_line=first_line)

test/syntax_tree.jl

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,14 @@
3636
e = try node.val = :q catch e e end
3737
@test occursin("immutable", e.msg) && occursin("SyntaxData", e.msg)
3838

39+
# copy
40+
t = parse(SyntaxNode, "a*b + c")
41+
ct = copy(t)
42+
ct.data = nothing
43+
@test ct.data === nothing && t.data !== nothing
44+
@test child(ct, 1).parent === ct
45+
@test child(ct, 1) !== child(t, 1)
46+
3947
node = parse(SyntaxNode, "f()")
4048
push!(node, parse(SyntaxNode, "x"))
4149
@test length(children(node)) == 2

0 commit comments

Comments
 (0)