Skip to content

Commit

Permalink
Add utility function to extract children::Vector in a type stable way.
Browse files Browse the repository at this point in the history
  • Loading branch information
fredrikekre committed May 29, 2024
1 parent b2b3e90 commit a0b7eb2
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 13 deletions.
6 changes: 2 additions & 4 deletions src/Runic.jl
Original file line number Diff line number Diff line change
Expand Up @@ -115,11 +115,9 @@ function format_node_with_children!(ctx::Context, node::JuliaSyntax.GreenNode)
span_sum = 0

# The new node parts. `children′` aliases `children` and only copied below if any of the
# nodes change ("copy-on-write"). Since we return directly if the node don't have
# children we can assert that `JuliaSyntax.children` returns a vector (and not the
# empty tuple) to help the compiler.
# nodes change ("copy-on-write").
head′ = JuliaSyntax.head(node)
children = JuliaSyntax.children(node)::AbstractVector
children = verified_children(node)
children′ = children
any_child_changed = false

Expand Down
19 changes: 14 additions & 5 deletions src/chisels.jl
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,23 @@ function first_leaf(node::JuliaSyntax.GreenNode)
if is_leaf(node)
return node
else
return first_leaf(first(JuliaSyntax.children(node)::AbstractVector))
return first_leaf(first(verified_children(node)))
end
end

# This function exist so that we can type-assert the return value to narrow it down from
# `Union{Tuple{}, Vector{JuliaSyntax.GreenNode}}` to `Vector{JuliaSyntax.GreenNode}`. Must
# only be called after verifying that the node has children.
function verified_children(node::JuliaSyntax.GreenNode)
@assert JuliaSyntax.haschildren(node)
return JuliaSyntax.children(node)::AbstractVector
end

function replace_first_leaf(node::JuliaSyntax.GreenNode, child′::JuliaSyntax.GreenNode)
if is_leaf(node)
return child′
else
children′ = copy(JuliaSyntax.children(node)::AbstractVector)
children′ = copy(verified_children(node))
children′[1] = replace_first_leaf(children′[1], child′)
@assert length(children′) > 0
span′ = mapreduce(JuliaSyntax.span, +, children′; init = 0)
Expand All @@ -65,12 +73,13 @@ function last_leaf(node::JuliaSyntax.GreenNode)
if is_leaf(node)
return node
else
return last_leaf(last(JuliaSyntax.children(node)::AbstractVector))
return last_leaf(last(verified_children(node)))
end
end

function is_assignment(node::JuliaSyntax.GreenNode)
return JuliaSyntax.is_prec_assignment(node)
return !is_leaf(node) && JuliaSyntax.is_prec_assignment(node)
end

# Just like `JuliaSyntax.is_infix_op_call`, but also check that the node is K"call"
Expand All @@ -81,7 +90,7 @@ end

function infix_op_call_op(node::JuliaSyntax.GreenNode)
@assert is_infix_op_call(node)
children = JuliaSyntax.children(node)::AbstractVector
children = verified_children(node)
first_operand_index = findfirst(!JuliaSyntax.is_whitespace, children)
op_index = findnext(JuliaSyntax.is_operator, children, first_operand_index + 1)
return children[op_index]
Expand All @@ -97,7 +106,7 @@ end

function first_non_whitespace_child(node::JuliaSyntax.GreenNode)
@assert !is_leaf(node)
children = JuliaSyntax.children(node)::AbstractVector
children = verified_children(node)
idx = findfirst(!JuliaSyntax.is_whitespace, children)::Int
return children[idx]
end
4 changes: 2 additions & 2 deletions src/runestone.jl
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ function spaces_around_x(ctx::Context, node::JuliaSyntax.GreenNode, is_x::F) whe
return nothing
end

children = JuliaSyntax.children(node)::AbstractVector
children = verified_children(node)
children′ = children
any_changes = false
original_bytes = node_bytes(ctx, node)
Expand Down Expand Up @@ -299,7 +299,7 @@ function no_spaces_around_x(ctx::Context, node::JuliaSyntax.GreenNode, is_x::F)
return nothing
end

children = JuliaSyntax.children(node)::AbstractVector
children = verified_children(node)
children′ = children
any_changes = false
original_bytes = node_bytes(ctx, node)
Expand Down
12 changes: 10 additions & 2 deletions test/runtests.jl
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
# SPDX-License-Identifier: MIT

using Runic:
format_string
Runic, format_string
using Test:
@test, @testset, @test_broken
@test, @testset, @test_broken, @inferred
using JuliaSyntax:
JuliaSyntax

@testset "Chisels" begin
# Type stability of verified_children
node = JuliaSyntax.parseall(JuliaSyntax.GreenNode, "a = 1 + b\n")
@test typeof(@inferred Runic.verified_children(node)) <: Vector{<:JuliaSyntax.GreenNode}
end

@testset "Trailing whitespace" begin
io = IOBuffer()
Expand Down

0 comments on commit a0b7eb2

Please sign in to comment.