Skip to content

Commit

Permalink
Fix an edgecase in operator chains with newlines hidden inside
Browse files Browse the repository at this point in the history
This also removes the limitation of no newline children in a operator
call chain and fixes a bug with trailing comments inside a chain.
  • Loading branch information
fredrikekre committed May 29, 2024
1 parent fac7aa8 commit 6f8c7c7
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 12 deletions.
30 changes: 19 additions & 11 deletions src/runestone.jl
Original file line number Diff line number Diff line change
Expand Up @@ -151,10 +151,6 @@ end
function spaces_around_x(ctx::Context, node::JuliaSyntax.GreenNode, is_x::F) where F
# TODO: So much boilerplate here...
@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′ = children
Expand All @@ -172,12 +168,14 @@ function spaces_around_x(ctx::Context, node::JuliaSyntax.GreenNode, is_x::F) whe

for (i, child) in pairs(children)
span_sum += JuliaSyntax.span(child)
if i == 1 && JuliaSyntax.kind(child) === K"Whitespace"
# If the first child is whitespace it will be accepted as is even if the span is
# larger than one since we don't look behind. The whitespace pass for the parent
# node should trim it later (if not already done).
if JuliaSyntax.kind(child) === K"NewlineWs" ||
(i == 1 && JuliaSyntax.kind(child) === K"Whitespace")
# NewlineWs are accepted as is by this pass.
# 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)
@assert !any_changes
any_changes && push!(children′, child)
looking_for_whitespace = false
elseif looking_for_whitespace
if JuliaSyntax.kind(child) === K"Whitespace" && JuliaSyntax.span(child) == 1
Expand Down Expand Up @@ -225,6 +223,14 @@ function spaces_around_x(ctx::Context, node::JuliaSyntax.GreenNode, is_x::F) whe
end
push!(children′, child′)
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
# Not a whitespace node, insert one
any_changes = true
Expand All @@ -244,7 +250,8 @@ function spaces_around_x(ctx::Context, node::JuliaSyntax.GreenNode, is_x::F) whe
if looking_for_x
@assert is_x(child)::Bool
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
else # !expect_ws
if looking_for_x
Expand All @@ -254,7 +261,8 @@ function spaces_around_x(ctx::Context, node::JuliaSyntax.GreenNode, is_x::F) whe
any_changes && push!(children′, child)
accept_node!(ctx, child)
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
# Reset stream
Expand Down
11 changes: 10 additions & 1 deletion test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ end
("0o" * z(n) * "1" => "0o001" for n in 0:2)...,
"0o377" => "0o377", # typemax(UInt8)
# Octal UInt16
"0o400" => "0o000400", # typemax(UInt8) + 1
"0o400" => "0o000400", # typemax(UInt8) + 1
("0o" * z(n) * "1" => "0o000001" for n in 3:5)...,
"0o177777" => "0o177777", # typemax(UInt16)
# Octal UInt32
Expand Down Expand Up @@ -126,6 +126,12 @@ end
# call() op call() op call()
@test format_string("$(sp)sin(α)$(sp)$(op)$(sp)cos(β)$(sp)$(op)$(sp)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
# Exceptions to the rule: `:` and `^`
# a:b
Expand All @@ -146,6 +152,9 @@ end
# Edgecase when using whitespace from the next leaf but the call chain continues
# after with more children.
@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

Expand Down

0 comments on commit 6f8c7c7

Please sign in to comment.