Skip to content

Commit a5eaa16

Browse files
committed
fix: preserve leading nil in stab clause body
A -> clause body can begin with a semicolon token after optional newlines, and that semicolon represents an implicit leading nil expression in the clause rhs. The previous detection logic did not recognize the `-> \n;expr` shape reliably, so the resulting AST dropped that leading nil and diverged from Code.string_to_quoted/2 output in with ... else clauses. This change detects the leading semicolon by peeking past end-of-line trivia before consuming clause eoe tokens, preserving the expected rhs shape. A regression assertion was added to `property test regression cases` for `with x <- 1 do :ok else _ -> \n;a end` to prevent this AST mismatch from returning. fix #113
1 parent 19f2c88 commit a5eaa16

2 files changed

Lines changed: 7 additions & 22 deletions

File tree

lib/spitfire.ex

Lines changed: 3 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1195,28 +1195,9 @@ defmodule Spitfire do
11951195
nl -> [newlines: nl]
11961196
end
11971197

1198-
# Check if we have a semicolon right after -> (possibly after eol)
1199-
# Check if there's a leading semicolon right after ->
1200-
# Handles both ";expr" and "\n;expr" patterns
1201-
has_leading_semicolon =
1202-
case peek_token(parser) do
1203-
:";" ->
1204-
true
1205-
1206-
:eol ->
1207-
# Peek at the next token after eol without consuming
1208-
# We need to manually check the token sequence
1209-
with {:eol, _} <- parser.current_token,
1210-
# Look at the tokens list to find what comes after eol
1211-
[{:";", _} | _] <- parser.tokens do
1212-
true
1213-
else
1214-
_ -> false
1215-
end
1216-
1217-
_ ->
1218-
false
1219-
end
1198+
# A semicolon immediately after `->` (with optional newlines in between)
1199+
# starts the clause body with an implicit nil expression.
1200+
has_leading_semicolon = peek_token_skip_eol(parser) == :";"
12201201

12211202
parser = eat_eoe_at(parser, 1)
12221203

test/spitfire_test.exs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2301,6 +2301,10 @@ defmodule SpitfireTest do
23012301
assert Spitfire.parse("%e.(){}") == s2q("%e.(){}")
23022302
assert Spitfire.parse("%e.(1){}") == s2q("%e.(1){}")
23032303
assert Spitfire.parse("%e.(a, b){}") == s2q("%e.(a, b){}")
2304+
2305+
# with/else stab body with leading semicolon after newline
2306+
assert Spitfire.parse("with x <- 1 do :ok else _ -> \n;a end") ==
2307+
s2q("with x <- 1 do :ok else _ -> \n;a end")
23042308
end
23052309
end
23062310

0 commit comments

Comments
 (0)