Browse Source

Fix an edgecase in operator chains with newlines hidden inside

This also removes the limitation of no newline children in a operator
call chain and fixes a bug with trailing comments inside a chain.
pull/19/head
Fredrik Ekre 2 years ago
parent
commit
6f8c7c7152
No known key found for this signature in database
GPG Key ID: DE82E6D5E364C0A2
  1. 30
      src/runestone.jl
  2. 9
      test/runtests.jl

30
src/runestone.jl

@ -151,10 +151,6 @@ end
function spaces_around_x(ctx::Context, node::JuliaSyntax.GreenNode, is_x::F) where F function spaces_around_x(ctx::Context, node::JuliaSyntax.GreenNode, is_x::F) where F
# TODO: So much boilerplate here... # TODO: So much boilerplate here...
@assert JuliaSyntax.haschildren(node) @assert JuliaSyntax.haschildren(node)
# TODO: Can't handle NewlineWs here right now
if any(JuliaSyntax.kind(c) === K"NewlineWs" for c in JuliaSyntax.children(node))
return nothing
end
children = verified_children(node) children = verified_children(node)
children′ = children children′ = children
@ -172,12 +168,14 @@ function spaces_around_x(ctx::Context, node::JuliaSyntax.GreenNode, is_x::F) whe
for (i, child) in pairs(children) for (i, child) in pairs(children)
span_sum += JuliaSyntax.span(child) span_sum += JuliaSyntax.span(child)
if i == 1 && JuliaSyntax.kind(child) === K"Whitespace" if JuliaSyntax.kind(child) === K"NewlineWs" ||
# If the first child is whitespace it will be accepted as is even if the span is (i == 1 && JuliaSyntax.kind(child) === K"Whitespace")
# larger than one since we don't look behind. The whitespace pass for the parent # NewlineWs are accepted as is by this pass.
# node should trim it later (if not already done). # Whitespace is accepted as is if this is the first child even if the span is
# larger than we expect since we don't look backwards. It should be cleaned up
# by some other pass.
accept_node!(ctx, child) accept_node!(ctx, child)
@assert !any_changes any_changes && push!(children′, child)
looking_for_whitespace = false looking_for_whitespace = false
elseif looking_for_whitespace elseif looking_for_whitespace
if JuliaSyntax.kind(child) === K"Whitespace" && JuliaSyntax.span(child) == 1 if JuliaSyntax.kind(child) === K"Whitespace" && JuliaSyntax.span(child) == 1
@ -225,6 +223,14 @@ function spaces_around_x(ctx::Context, node::JuliaSyntax.GreenNode, is_x::F) whe
end end
push!(children′, child′) push!(children′, child′)
end end
elseif JuliaSyntax.haschildren(child) &&
JuliaSyntax.kind(first_leaf(child)) === K"NewlineWs"
# NewlineWs have to be accepted as is
accept_node!(ctx, child)
any_changes && push!(children′, child)
looking_for_whitespace = JuliaSyntax.kind(last_leaf(child)) !== K"Whitespace"
@assert !is_x(child)::Bool
looking_for_x = true
else else
# Not a whitespace node, insert one # Not a whitespace node, insert one
any_changes = true any_changes = true
@ -244,7 +250,8 @@ function spaces_around_x(ctx::Context, node::JuliaSyntax.GreenNode, is_x::F) whe
if looking_for_x if looking_for_x
@assert is_x(child)::Bool @assert is_x(child)::Bool
end end
looking_for_x = !looking_for_x # Flip the switch, unless child is a comment
looking_for_x = JuliaSyntax.kind(child) === K"Comment" ? looking_for_x : !looking_for_x
end end
else # !expect_ws else # !expect_ws
if looking_for_x if looking_for_x
@ -254,7 +261,8 @@ function spaces_around_x(ctx::Context, node::JuliaSyntax.GreenNode, is_x::F) whe
any_changes && push!(children′, child) any_changes && push!(children′, child)
accept_node!(ctx, child) accept_node!(ctx, child)
looking_for_whitespace = JuliaSyntax.kind(last_leaf(child)) !== K"Whitespace" looking_for_whitespace = JuliaSyntax.kind(last_leaf(child)) !== K"Whitespace"
looking_for_x = !looking_for_x # Flip the switch, unless child is a comment
looking_for_x = JuliaSyntax.kind(child) === K"Comment" ? looking_for_x : !looking_for_x
end end
end end
# Reset stream # Reset stream

9
test/runtests.jl

@ -126,6 +126,12 @@ end
# call() op call() op call() # call() op call() op call()
@test format_string("$(sp)sin(α)$(sp)$(op)$(sp)cos(β)$(sp)$(op)$(sp)tan(γ)$(sp)") == @test format_string("$(sp)sin(α)$(sp)$(op)$(sp)cos(β)$(sp)$(op)$(sp)tan(γ)$(sp)") ==
"$(sp)sin(α) $(op) cos(β) $(op) tan(γ)$(sp)" "$(sp)sin(α) $(op) cos(β) $(op) tan(γ)$(sp)"
# a op \n b
@test format_string("$(sp)a$(sp)$(op)$(sp)\nb$(sp)") ==
"$(sp)a $(op)\nb$(sp)"
# a op # comment \n b
@test format_string("$(sp)a$(sp)$(op)$(sp)# comment\nb$(sp)") ==
"$(sp)a $(op) # comment\nb$(sp)"
end end
# Exceptions to the rule: `:` and `^` # Exceptions to the rule: `:` and `^`
# a:b # a:b
@ -146,6 +152,9 @@ end
# Edgecase when using whitespace from the next leaf but the call chain continues # Edgecase when using whitespace from the next leaf but the call chain continues
# after with more children. # after with more children.
@test format_string("$(sp)z$(sp)+$(sp)2x$(sp)+$(sp)z$(sp)") == "$(sp)z + 2x + z$(sp)" @test format_string("$(sp)z$(sp)+$(sp)2x$(sp)+$(sp)z$(sp)") == "$(sp)z + 2x + z$(sp)"
# Edgecase where the NewlineWs ends up inside the second call in a chain
@test format_string("$(sp)a$(sp)\\$(sp)b$(sp)$(sp)\n$(sp)c$(sp)\\$(sp)d$(sp)") ==
"$(sp)a \\ b ≈\n$(sp)c \\ d$(sp)"
end end
end end

Loading…
Cancel
Save