Skip to content

Commit

Permalink
Fix insertion of space before comment (#62)
Browse files Browse the repository at this point in the history
This patch changes where spaces are inserted before comments so that it
is always added as a sibling to the comment instead of as a "uncle" when
a comment is found as the first leaf of a kid.
  • Loading branch information
fredrikekre authored Sep 10, 2024
1 parent be162ee commit f88195e
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 15 deletions.
15 changes: 15 additions & 0 deletions src/chisels.jl
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,21 @@ function replace_last_leaf(node::Node, kid′::Union{Node, NullNode})
end
end

# Insert a node before the first leaf (at the same level)
# TODO: Currently only works for inserting a space before a comment
function add_before_first_leaf(node::Node, kid′::Union{Node, NullNode})
@assert !is_leaf(node)
kids = verified_kids(node)
@assert length(kids) > 0
kids′ = copy(kids)
if kind(kids′[1]) === K"Comment"
pushfirst!(kids′, kid′)
else
kids′[1] = add_before_first_leaf(kids′[1], kid′)
end
return make_node(node, kids′)
end

function last_leaf(node::Node)
if is_leaf(node)
return node
Expand Down
35 changes: 21 additions & 14 deletions src/runestone.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3372,26 +3372,33 @@ function spaces_around_comments(ctx::Context, node::Node)
prev_kid_ends_with_ws = true
ws = Node(JuliaSyntax.SyntaxHead(K"Whitespace", JuliaSyntax.TRIVIA_FLAG), 1)
for (i, kid) in pairs(kids)
if kind(kid) === K"Comment" ||
(fl = first_leaf(kid); fl !== nothing && kind(fl) === K"Comment")
# TODO: In the case where the comment is found within the kid the whitespace
# should maybe be added right before the comment in the tree (which is how
# JuliaSyntax would have parsed the source if the space was already there). I
# don't know if this really matters though since it is already pretty random
# where whitespace ends up.
if !prev_kid_ends_with_ws
kids′ = kids′ === kids ? kids[1:(i - 1)] : kids′
kid= kid
if !prev_kid_ends_with_ws && (
kind(kid) === K"Comment" ||
(fl = first_leaf(kid); fl !== nothing && kind(fl) === K"Comment")
)
@assert !prev_kid_ends_with_ws
kids′ = kids′ === kids ? kids[1:(i - 1)] : kids′
replace_bytes!(ctx, " ", 0)
if kind(kid) === K"Comment"
push!(kids′, ws)
replace_bytes!(ctx, " ", 0)
accept_node!(ctx, ws)
else
@assert (fl = first_leaf(kid); fl !== nothing && kind(fl) === K"Comment")
# When the comment is found within the kid the whitespace is added right
# before the comment inside of the kid instead of in this outer context.
# This does not necessarily match how JuliaSyntax would have parsed it, but
# seems to work better than the alternative.
kid′ = add_before_first_leaf(kid, ws)
@assert span(kid′) == span(kid) + 1
end
end
if kids′ !== kids
push!(kids′, kid)
push!(kids′, kid)
end
accept_node!(ctx, kid)
prev_kid_ends_with_ws = kind(kid) in KSet"Whitespace NewlineWs" ||
(ll = last_leaf(kid); ll !== nothing && kind(ll) in KSet"Whitespace NewlineWs")
accept_node!(ctx, kid)
prev_kid_ends_with_ws = kind(kid) in KSet"Whitespace NewlineWs" ||
(ll = last_leaf(kid); ll !== nothing && kind(ll) in KSet"Whitespace NewlineWs")
end
# Reset the stream and return
seek(ctx.fmt_io, pos)
Expand Down
3 changes: 2 additions & 1 deletion test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,10 @@ end
@test format_string("1 + 1$(sp)# comment") == "1 + 1$(csp)# comment"
@test format_string("(a,$(sp)# comment\nb)") ==
"(\n a,$(csp)# comment\n b,\n)"
# Edgecase where the comment ends up as the first leaf inside the call
# Edgecases where the comment ends up as the first leaf inside a node
@test format_string("(a,$(sp)# comment\nb + b)") ==
"(\n a,$(csp)# comment\n b + b,\n)"
@test format_string("if c$(sp)# a\n b\nend") == "if c$(csp)# a\n b\nend"
end
let str = "a = 1 # a comment\nab = 2 # ab comment\n"
@test format_string(str) == str
Expand Down

0 comments on commit f88195e

Please sign in to comment.