Credence.Syntax.CloseUnclosedFnDelimiter (credence v0.8.0)

Copy Markdown

Repairs an fn closed with ) and a leftover stray end on the next line.

This is the sibling of Credence.Syntax.NoUnclosedFnDelimiter. That rule handles a plain fn args -> body) (an fn whose end is missing entirely). Here the LLM instead writes an inner block's end, then ), then leaves the fn's would-be end dangling on the following line:

Enum.map(row, fn element ->
  if element == 0 do min_value else element end)
end

The end closes the if, the ) closes the Enum.map call, the fn body is never closed, and the next line's end no longer has a block to close. The repair inserts the missing end before the ) and deletes the now-stray end line:

Enum.map(row, fn element ->
  if element == 0 do min_value else element end end)

Detection is driven by the parser itself — Code.string_to_quoted/2 reports the exact fn/) mismatch, and the repair is committed only when removing a stray end makes the whole source parse. So the rule never matches fn/do/ end words inside strings, heredocs, or comments, and a file unparseable for an unrelated reason is left untouched.

This rule deliberately owns only the stray-end variant: when inserting end before ) already yields parseable code (no stray end), that is NoUnclosedFnDelimiter's case and this rule stays silent, so the two never both fire on the same input.