Browse Source

Fix formatting of import/using with `as` renaming

pull/26/head
Fredrik Ekre 1 year ago
parent
commit
d8efd2f05d
No known key found for this signature in database
GPG Key ID: DE82E6D5E364C0A2
  1. 160
      src/runestone.jl
  2. 20
      test/runtests.jl

160
src/runestone.jl

@ -1011,6 +1011,105 @@ function spaces_in_export_public(ctx::Context, node::Node)
return any_changes ? make_node(node, kids′) : nothing return any_changes ? make_node(node, kids′) : nothing
end end
# Used in spaces_in_import_using. Well formatted importpath should have a single leading
# space or a newline.
function format_importpath(ctx::Context, node::Node)
@assert kind(node) === K"importpath"
pos = position(ctx.fmt_io)
spacebar = Node(JuliaSyntax.SyntaxHead(K"Whitespace", JuliaSyntax.TRIVIA_FLAG), 1)
if kind(first_leaf(node)) === K"NewlineWs" ||
(kind(first_leaf(node)) === K"Whitespace" && span(first_leaf(node)) == 1)
# Newline or whitespace with correct span
node′ = nothing
elseif kind(first_leaf(node)) === K"Whitespace"
# Whitespace with incorrect span; replace with a single space
replace_bytes!(ctx, " ", span(first_leaf(node)))
node′ = replace_first_leaf(node, spacebar)
else
# No whitespace, insert
@assert kind(first_leaf(node)) === K"Identifier"
kids′ = copy(verified_kids(node))
pushfirst!(kids′, spacebar)
replace_bytes!(ctx, " ", 0)
node′ = make_node(node, kids′)
end
# Reset stream
seek(ctx.fmt_io, pos)
return node′
end
# Used in spaces_in_import_using.
function format_as(ctx::Context, node::Node)
@assert kind(node) === K"as"
kids = verified_kids(node)
kids′ = kids
any_changes = false
pos = position(ctx.fmt_io)
spacebar = Node(JuliaSyntax.SyntaxHead(K"Whitespace", JuliaSyntax.TRIVIA_FLAG), 1)
# First the importpath (LHS of the `as`)
idx = 1
kid′ = kids[idx]
@assert kind(kid′) === K"importpath"
kid′′ = format_importpath(ctx, kid′)
if kid′′ !== nothing
any_changes = true
kid′ = kid′′
kids′ = [kid′]
end
accept_node!(ctx, kid′)
# space before `as`
idx += 1
kid = kids[idx]
@assert kind(kid) === K"Whitespace"
if span(kid) == 1
# Correct span
accept_node!(ctx, kid)
any_changes && push!(kids′, kid)
else
# Incorrect span
replace_bytes!(ctx, " ", span(kid))
any_changes = true
if kids′ === kids
kids′ = kids[1:(idx - 1)]
end
accept_node!(ctx, spacebar)
push!(kids′, spacebar)
end
# `as`
idx += 1
kid = kids[idx]
@assert kind(kid) === K"as"
accept_node!(ctx, kid)
any_changes && push!(kids′, kid)
# space after `as`
idx += 1
kid = kids[idx]
@assert kind(kid) === K"Whitespace"
if span(kid) == 1
# Correct span
accept_node!(ctx, kid)
any_changes && push!(kids′, kid)
else
# Incorrect span
replace_bytes!(ctx, " ", span(kid))
any_changes = true
if kids′ === kids
kids′ = kids[1:(idx - 1)]
end
accept_node!(ctx, spacebar)
push!(kids′, spacebar)
end
# Alias-identifier
idx += 1
kid = kids[idx]
@assert kind(kid) === K"Identifier"
accept_node!(ctx, kid)
any_changes && push!(kids′, kid)
# Reset stream
seek(ctx.fmt_io, pos)
return any_changes ? make_node(node, kids′) : nothing
end
function spaces_in_import_using(ctx::Context, node::Node) function spaces_in_import_using(ctx::Context, node::Node)
if !(kind(node) in KSet"import using" && !is_leaf(node)) if !(kind(node) in KSet"import using" && !is_leaf(node))
return nothing return nothing
@ -1028,63 +1127,50 @@ function spaces_in_import_using(ctx::Context, node::Node)
kids′ = kids kids′ = kids
end end
spacenode = Node(JuliaSyntax.SyntaxHead(K"Whitespace", JuliaSyntax.TRIVIA_FLAG), 1)
@assert kind(kids[1]) in KSet"import using" @assert kind(kids[1]) in KSet"import using"
accept_node!(ctx, kids[1]) accept_node!(ctx, kids[1])
expect_comma = false state = :expect_item
i = 2
for i in 2:length(kids) while i <= length(kids)
kid = kids[i] kid = kids[i]
if expect_comma if state === :expect_item
if kind(kid) === K"Whitespace" @assert kind(kid) in KSet"importpath as"
# Drop this node if kind(kid) === K"importpath"
kid′ = format_importpath(ctx, kid)
else
@assert kind(kid) === K"as"
kid′ = format_as(ctx, kid)
end
if kid′ !== nothing
any_changes = true any_changes = true
replace_bytes!(ctx, "", span(kid))
if kids′ === kids if kids′ === kids
kids′ = kids[1:(i - 1)] kids′ = kids[1:(i - 1)]
end end
accept_node!(ctx, kid′)
push!(kids′, kid′)
else else
@assert kind(kid) in KSet": ,"
accept_node!(ctx, kid) accept_node!(ctx, kid)
any_changes && push!(kids′, kid) any_changes && push!(kids′, kid)
expect_comma = false
end end
state = :expect_comma
else else
@assert kind(kid) === K"importpath" @assert state === :expect_comma
# Expect a single leading whitespace if kind(kid) === K"Whitespace"
if kind(first_leaf(kid)) === K"NewlineWs" || # Drop this node
(kind(first_leaf(kid)) === K"Whitespace" && span(first_leaf(kid)) == 1)
# Newline or whitespace with correct span
accept_node!(ctx, kid)
any_changes && push!(kids′, kid)
elseif kind(first_leaf(kid)) === K"Whitespace"
# Whitespace with incorrect span; replace with a single space
kid′ = replace_first_leaf(kid, spacenode)
replace_bytes!(ctx, " ", span(first_leaf(kid)))
any_changes = true any_changes = true
replace_bytes!(ctx, "", span(kid))
if kids′ === kids if kids′ === kids
kids′ = kids[1:(i - 1)] kids′ = kids[1:(i - 1)]
end end
accept_node!(ctx, kid′)
push!(kids′, kid′)
else else
# No whitespace, insert @assert kind(kid) in KSet": ,"
@assert kind(first_leaf(kid)) === K"Identifier" accept_node!(ctx, kid)
grandkids′ = copy(verified_kids(kid)) any_changes && push!(kids′, kid)
pushfirst!(grandkids′, spacenode) state = :expect_item
replace_bytes!(ctx, " ", 0)
any_changes = true
if kids′ === kids
kids′ = kids[1:(i - 1)]
end
kid′ = make_node(kid, grandkids′)
accept_node!(ctx, kid′)
push!(kids′, kid′)
end end
expect_comma = true
end end
i += 1
end end
# Reset stream # Reset stream
seek(ctx.fmt_io, pos) seek(ctx.fmt_io, pos)

20
test/runtests.jl

@ -799,6 +799,26 @@ end
@test format_string("$(verb) $(sp)A: $(sp)a$(sp),$(sp)b") == "$(verb) A: a, b" @test format_string("$(verb) $(sp)A: $(sp)a$(sp),$(sp)b") == "$(verb) A: a, b"
@test format_string("$(verb) $(sp)A: $(sp)a$(sp),\nb") == "$(verb) A: a,\n b" @test format_string("$(verb) $(sp)A: $(sp)a$(sp),\nb") == "$(verb) A: a,\n b"
end end
for sp in ("", " ", " ", "\t")
# `import A as a, ...`
@test format_string("import $(sp)A $(sp)as $(sp)a") == "import A as a"
@test format_string("import $(sp)A $(sp)as $(sp)a$(sp),$(sp)B $(sp)as $(sp)b") ==
"import A as a, B as b"
@test format_string("import $(sp)A $(sp)as $(sp)a$(sp),$(sp)B") ==
"import A as a, B"
@test format_string("import $(sp)A$(sp),$(sp)B $(sp)as $(sp)b") ==
"import A, B as b"
# `(import|using) A: a as b, ...`
for verb in ("using", "import")
@test format_string("$(verb) $(sp)A: $(sp)a $(sp)as $(sp)b") == "$(verb) A: a as b"
@test format_string("$(verb) $(sp)A: $(sp)a $(sp)as $(sp)b$(sp),$(sp)c $(sp)as $(sp)d") ==
"$(verb) A: a as b, c as d"
@test format_string("$(verb) $(sp)A: $(sp)a $(sp)as $(sp)b$(sp),$(sp)c") ==
"$(verb) A: a as b, c"
@test format_string("$(verb) $(sp)A: $(sp)a$(sp),$(sp)c $(sp)as $(sp)d") ==
"$(verb) A: a, c as d"
end
end
end end
@testset "spaces in export/public" begin @testset "spaces in export/public" begin

Loading…
Cancel
Save