Browse Source

Add utility function to extract children::Vector in a type stable way.

pull/19/head
Fredrik Ekre 2 years ago
parent
commit
a0b7eb2c2c
No known key found for this signature in database
GPG Key ID: DE82E6D5E364C0A2
  1. 6
      src/Runic.jl
  2. 19
      src/chisels.jl
  3. 4
      src/runestone.jl
  4. 12
      test/runtests.jl

6
src/Runic.jl

@ -115,11 +115,9 @@ function format_node_with_children!(ctx::Context, node::JuliaSyntax.GreenNode)
span_sum = 0 span_sum = 0
# The new node parts. `children′` aliases `children` and only copied below if any of the # 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 # nodes change ("copy-on-write").
# children we can assert that `JuliaSyntax.children` returns a vector (and not the
# empty tuple) to help the compiler.
head′ = JuliaSyntax.head(node) head′ = JuliaSyntax.head(node)
children = JuliaSyntax.children(node)::AbstractVector children = verified_children(node)
children′ = children children′ = children
any_child_changed = false any_child_changed = false

19
src/chisels.jl

@ -45,15 +45,23 @@ function first_leaf(node::JuliaSyntax.GreenNode)
if is_leaf(node) if is_leaf(node)
return node return node
else else
return first_leaf(first(JuliaSyntax.children(node)::AbstractVector)) return first_leaf(first(verified_children(node)))
end end
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) function replace_first_leaf(node::JuliaSyntax.GreenNode, child′::JuliaSyntax.GreenNode)
if is_leaf(node) if is_leaf(node)
return child′ return child′
else else
children′ = copy(JuliaSyntax.children(node)::AbstractVector) children′ = copy(verified_children(node))
children′[1] = replace_first_leaf(children′[1], child′) children′[1] = replace_first_leaf(children′[1], child′)
@assert length(children′) > 0 @assert length(children′) > 0
span′ = mapreduce(JuliaSyntax.span, +, children′; init = 0) span′ = mapreduce(JuliaSyntax.span, +, children′; init = 0)
@ -65,12 +73,13 @@ function last_leaf(node::JuliaSyntax.GreenNode)
if is_leaf(node) if is_leaf(node)
return node return node
else else
return last_leaf(last(JuliaSyntax.children(node)::AbstractVector)) return last_leaf(last(verified_children(node)))
end end
end end
function is_assignment(node::JuliaSyntax.GreenNode) function is_assignment(node::JuliaSyntax.GreenNode)
return JuliaSyntax.is_prec_assignment(node) return JuliaSyntax.is_prec_assignment(node)
return !is_leaf(node) && JuliaSyntax.is_prec_assignment(node)
end end
# Just like `JuliaSyntax.is_infix_op_call`, but also check that the node is K"call" # Just like `JuliaSyntax.is_infix_op_call`, but also check that the node is K"call"
@ -81,7 +90,7 @@ end
function infix_op_call_op(node::JuliaSyntax.GreenNode) function infix_op_call_op(node::JuliaSyntax.GreenNode)
@assert is_infix_op_call(node) @assert is_infix_op_call(node)
children = JuliaSyntax.children(node)::AbstractVector children = verified_children(node)
first_operand_index = findfirst(!JuliaSyntax.is_whitespace, children) first_operand_index = findfirst(!JuliaSyntax.is_whitespace, children)
op_index = findnext(JuliaSyntax.is_operator, children, first_operand_index + 1) op_index = findnext(JuliaSyntax.is_operator, children, first_operand_index + 1)
return children[op_index] return children[op_index]
@ -97,7 +106,7 @@ end
function first_non_whitespace_child(node::JuliaSyntax.GreenNode) function first_non_whitespace_child(node::JuliaSyntax.GreenNode)
@assert !is_leaf(node) @assert !is_leaf(node)
children = JuliaSyntax.children(node)::AbstractVector children = verified_children(node)
idx = findfirst(!JuliaSyntax.is_whitespace, children)::Int idx = findfirst(!JuliaSyntax.is_whitespace, children)::Int
return children[idx] return children[idx]
end end

4
src/runestone.jl

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

12
test/runtests.jl

@ -1,9 +1,17 @@
# SPDX-License-Identifier: MIT # SPDX-License-Identifier: MIT
using Runic: using Runic:
format_string Runic, format_string
using Test: 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 @testset "Trailing whitespace" begin
io = IOBuffer() io = IOBuffer()

Loading…
Cancel
Save