Skip to content

Commit dbf9fb3

Browse files
authored
Ensure single space after for (#187)
1 parent 147403a commit dbf9fb3

2 files changed

Lines changed: 56 additions & 0 deletions

File tree

src/runestone.jl

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1286,6 +1286,57 @@ function space_before_do(ctx::Context, node::Node)
12861286
return nothing
12871287
end
12881288

1289+
function space_after_for(ctx::Context, node::Node)
1290+
@assert kind(node) === K"for" && !is_leaf(node)
1291+
p = position(ctx.fmt_io)
1292+
kids = verified_kids(node)
1293+
for_leaf = kids[1]
1294+
@assert kind(for_leaf) === K"for" && is_leaf(for_leaf)
1295+
ws = Node(JuliaSyntax.SyntaxHead(K"Whitespace", JuliaSyntax.TRIVIA_FLAG), 1)
1296+
if kind(kids[2]) in KSet"Whitespace NewlineWs"
1297+
# In some tree configurations the whitespace after `for` is already a
1298+
# direct child of the K"for" node (e.g. after another pass has
1299+
# restructured it). For a plain K"Whitespace" normalise the span if
1300+
# needed; for K"NewlineWs" leave it alone.
1301+
ws_kid = kids[2]
1302+
if kind(ws_kid) === K"NewlineWs" || span(ws_kid) == 1
1303+
seek(ctx.fmt_io, p)
1304+
return nothing
1305+
end
1306+
accept_node!(ctx, for_leaf)
1307+
replace_bytes!(ctx, " ", span(ws_kid))
1308+
kids′ = copy(kids)
1309+
kids′[2] = ws
1310+
seek(ctx.fmt_io, p)
1311+
return make_node(node, kids′)
1312+
end
1313+
# In JuliaSyntax v1 the space after `for` is the first child of the first
1314+
# in/∈ subnode inside the iteration node (kids[2]).
1315+
iter_idx = 2
1316+
iter_node = kids[iter_idx]
1317+
@assert kind(iter_node) === K"iteration"
1318+
iter_kids = verified_kids(iter_node)
1319+
first_in = iter_kids[1]
1320+
in_kids = verified_kids(first_in)
1321+
ws_kid = in_kids[1]
1322+
if kind(ws_kid) !== K"Whitespace" || span(ws_kid) == 1
1323+
seek(ctx.fmt_io, p)
1324+
return nothing
1325+
end
1326+
accept_node!(ctx, for_leaf)
1327+
replace_bytes!(ctx, " ", span(ws_kid))
1328+
in_kids′ = copy(in_kids)
1329+
in_kids′[1] = ws
1330+
first_in′ = make_node(first_in, in_kids′)
1331+
iter_kids′ = copy(iter_kids)
1332+
iter_kids′[1] = first_in′
1333+
iter_node′ = make_node(iter_node, iter_kids′)
1334+
kids′ = copy(kids)
1335+
kids′[iter_idx] = iter_node′
1336+
seek(ctx.fmt_io, p)
1337+
return make_node(node, kids′)
1338+
end
1339+
12891340
function space_after_let(ctx, node)
12901341
@assert kind(node) === K"let" && !is_leaf(node)
12911342
p = position(ctx.fmt_io)
@@ -1329,6 +1380,9 @@ end
13291380
# global, const
13301381
function spaces_around_keywords(ctx::Context, node::Node)
13311382
is_leaf(node) && return nothing
1383+
if kind(node) === K"for"
1384+
return space_after_for(ctx, node)
1385+
end
13321386
if kind(node) === K"let"
13331387
return space_after_let(ctx, node)
13341388
end

test/runtests.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -601,6 +601,8 @@ end
601601
@test format_string("module$(sp)A\nend") == "module A\nend"
602602
@test format_string("module$(sp)(A)\nend") == "module (A)\nend"
603603
@test format_string("while$(sp)cond\nend") == "while cond\nend"
604+
@test format_string("for$(sp)i in I\nend") == "for i in I\nend"
605+
@test format_string("for$(sp)i in I, j in J\nend") == "for i in I, j in J\nend"
604606
@test format_string("let$(sp)x = 1\nend") == "let x = 1\nend"
605607
@test format_string("let$(sp)\nend") == "let\nend"
606608
for word in ("local", "global"), rhs in ("a", "a, b", "a = 1", "a, b = 1, 2")

0 commit comments

Comments
 (0)