Skip to content

Commit

Permalink
Fix spaces in comparison chains
Browse files Browse the repository at this point in the history
  • Loading branch information
fredrikekre committed May 26, 2024
1 parent c489dfc commit 0db3c54
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 19 deletions.
6 changes: 6 additions & 0 deletions src/chisel.jl
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,9 @@ end
function is_assignment(node::JuliaSyntax.GreenNode)
return JuliaSyntax.is_prec_assignment(node)
end
function is_comparison_leaf(node::JuliaSyntax.GreenNode)
return is_leaf(node) && JuliaSyntax.is_prec_comparison(node)
end
function is_operator_leaf(node::JuliaSyntax.GreenNode)
return is_leaf(node) && JuliaSyntax.is_operator(node)
end
25 changes: 12 additions & 13 deletions src/runestone.jl
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ end
# Insert space around `x`, where `x` can be operators, assignments, etc. with the pattern:
# `<something><space><x><space><something>`, for example the spaces around `+` and `=` in
# `a = x + y`.
function spaces_around_x(ctx::Context, node::JuliaSyntax.GreenNode, x::JuliaSyntax.Kind)
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
Expand Down Expand Up @@ -239,13 +239,13 @@ function spaces_around_x(ctx::Context, node::JuliaSyntax.GreenNode, x::JuliaSynt
accept_node!(ctx, child)
looking_for_whitespace = JuliaSyntax.kind(last_leaf(child)) !== K"Whitespace"
if looking_for_x
@assert JuliaSyntax.kind(child) === x
@assert is_x(child)::Bool
end
looking_for_x = !looking_for_x
end
else # !expect_ws
if looking_for_x
@assert JuliaSyntax.kind(child) === x
@assert is_x(child)::Bool
end
@assert JuliaSyntax.kind(child) !== K"Whitespace" # This would be weird, I think?
any_changes && push!(children′, child)
Expand All @@ -266,23 +266,22 @@ function spaces_around_x(ctx::Context, node::JuliaSyntax.GreenNode, x::JuliaSynt
end
end

# This pass handles spaces around infix operator calls and comparison chains
function spaces_around_operators(ctx::Context, node::JuliaSyntax.GreenNode)
if !(JuliaSyntax.is_infix_op_call(node))
if !(
JuliaSyntax.is_infix_op_call(node) ||
(JuliaSyntax.kind(node) === K"comparison" && !JuliaSyntax.is_trivia(node))
)
return nothing
end
@assert JuliaSyntax.kind(node) === K"call"
# Find the specific operator
children = JuliaSyntax.children(node)::AbstractVector
start_idx = JuliaSyntax.is_whitespace(first_leaf(node)) ? 3 : 2
i = findnext(!JuliaSyntax.is_whitespace, children, start_idx)::Int
op = JuliaSyntax.kind(children[i])
@assert JuliaSyntax.is_operator(op)
return spaces_around_x(ctx, node, op)
@assert JuliaSyntax.kind(node) in KSet"call comparison"
is_x = x -> is_operator_leaf(x) || is_comparison_leaf(x)
return spaces_around_x(ctx, node, is_x)
end

function spaces_around_assignments(ctx::Context, node::JuliaSyntax.GreenNode)
if !(is_assignment(node) && !JuliaSyntax.is_trivia(node))
return nothing
end
return spaces_around_x(ctx, node, JuliaSyntax.kind(node))
return spaces_around_x(ctx, node, is_assignment)
end
18 changes: 12 additions & 6 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -99,18 +99,24 @@ end
@test format_string(" a$(op) b ") == " a $(op) b "
@test format_string("x=a$(op) b ") == "x = a $(op) b "
@test format_string("a$(op) b") == "a $(op) b"
if op in ("==", "!=", "===", "!==", "<", "<=")
# TODO: Broken when chaining these operators
@test_broken format_string("a$(op) b $(op) x") == "a $(op) b $(op) x"
else
@test format_string("a$(op) b $(op) x") == "a $(op) b $(op) x"
end
@test format_string("a$(op) b $(op) x") == "a $(op) b $(op) x"
@test format_string("a$(op) b * x") == "a $(op) b * x"
@test format_string("a$(op)( b * x)") == "a $(op) ( b * x)"
@test format_string("sin(π)$(op)cos(pi)") == "sin(π) $(op) cos(pi)"
end
end

@testset "whitespace in comparison chains" begin
for sp in ("", " ", " ")
@test format_string("a$(sp)==$(sp)b") == "a == b"
@test format_string("a$(sp)==$(sp)b$(sp)==$(sp)c") == "a == b == c"
@test format_string("a$(sp)<=$(sp)b$(sp)==$(sp)c") == "a <= b == c"
@test format_string("a$(sp)<=$(sp)b$(sp)>=$(sp)c") == "a <= b >= c"
@test format_string("a$(sp)<$(sp)b$(sp)>=$(sp)c") == "a < b >= c"
@test format_string("a$(sp)<$(sp)b$(sp)<$(sp)c") == "a < b < c"
end
end

@testset "whitespace around assignments" begin
# Regular assignments and dot-assignments
for a in ("=", "+=", "-=", ".=", ".+=", ".-=")
Expand Down

0 comments on commit 0db3c54

Please sign in to comment.