fix: make sure syntax nodes always run their formatters (#4631)
Now syntax nodes have their formatters run even if the parsers they wrap are all arity zero. This fixes an issue where if `ppSpace` appears in a `macro`/`elab` then it does not format with a space due to the fact that macro argument processing wraps this as `group(ppSpace)`, and `ppSpace` has arity zero. Implementation note: the fix is to make the `visitArgs` formatter combinator always visit the last child, even if it does not exist (in which case the visited node will be `Syntax.missing`). To compensate, parser combinators like many and optional need to be sure to keep track of whether there any children. Only optional's needed to be modified. Closes #4561
This commit is contained in:
parent
7ef95cd30b
commit
c2edae92c8
2 changed files with 59 additions and 5 deletions
|
|
@ -129,11 +129,13 @@ def pushLine : FormatterM Unit :=
|
|||
def pushAlign (force : Bool) : FormatterM Unit :=
|
||||
pushWhitespace (.align force)
|
||||
|
||||
/-- Execute `x` at the right-most child of the current node, if any, then advance to the left. -/
|
||||
/--
|
||||
Execute `x` at the right-most child of the current node, if any, then advance to the left.
|
||||
Runs `x` even if there are no children, in which case the current syntax node will be `.missing`.
|
||||
-/
|
||||
def visitArgs (x : FormatterM Unit) : FormatterM Unit := do
|
||||
let stx ← getCur
|
||||
if stx.getArgs.size > 0 then
|
||||
goDown (stx.getArgs.size - 1) *> x <* goUp
|
||||
goDown (stx.getArgs.size - 1) *> x <* goUp
|
||||
goLeft
|
||||
|
||||
/-- Execute `x`, pass array of generated Format objects to `fn`, and push result. -/
|
||||
|
|
@ -454,7 +456,9 @@ def manyNoAntiquot.formatter (p : Formatter) : Formatter := do
|
|||
@[combinator_formatter many1NoAntiquot] def many1NoAntiquot.formatter (p : Formatter) : Formatter := manyNoAntiquot.formatter p
|
||||
|
||||
@[combinator_formatter optionalNoAntiquot]
|
||||
def optionalNoAntiquot.formatter (p : Formatter) : Formatter := visitArgs p
|
||||
def optionalNoAntiquot.formatter (p : Formatter) : Formatter := do
|
||||
let stx ← getCur
|
||||
visitArgs <| unless stx.getArgs.isEmpty do p
|
||||
|
||||
@[combinator_formatter many1Unbox]
|
||||
def many1Unbox.formatter (p : Formatter) : Formatter := do
|
||||
|
|
@ -467,7 +471,7 @@ def many1Unbox.formatter (p : Formatter) : Formatter := do
|
|||
@[combinator_formatter sepByNoAntiquot]
|
||||
def sepByNoAntiquot.formatter (p pSep : Formatter) : Formatter := do
|
||||
let stx ← getCur
|
||||
visitArgs <| (List.range stx.getArgs.size).reverse.forM fun i => if i % 2 == 0 then p else pSep
|
||||
visitArgs <| stx.getArgs.size.forRevM fun i => if i % 2 == 0 then p else pSep
|
||||
|
||||
@[combinator_formatter sepBy1NoAntiquot] def sepBy1NoAntiquot.formatter := sepByNoAntiquot.formatter
|
||||
|
||||
|
|
|
|||
50
tests/lean/run/4561.lean
Normal file
50
tests/lean/run/4561.lean
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
import Lean.Elab.Command
|
||||
/-!
|
||||
# 4561: group(ppSpace) was not pretty printing with a space
|
||||
-/
|
||||
|
||||
/-!
|
||||
Example from the issue. Here, ppSpace is wrapped in a group due to macro argument handling.
|
||||
-/
|
||||
macro (name := useSyntax) "use0" ppSpace arg:term : tactic => `(tactic| sorry)
|
||||
|
||||
/-- info: use0 .succ✝ 0 -/
|
||||
#guard_msgs in
|
||||
run_cmd do
|
||||
Lean.logInfo <| ← `(tactic| use0 .succ 0)
|
||||
|
||||
/-!
|
||||
Version of this using `syntax` to test it without macro argument handling.
|
||||
-/
|
||||
|
||||
syntax "use1" ppSpace term,+ : tactic
|
||||
syntax "use2" group(ppSpace) term,+ : tactic
|
||||
|
||||
/--
|
||||
info: use1 .succ✝ 0
|
||||
---
|
||||
info: use2 .succ✝ 0
|
||||
-/
|
||||
#guard_msgs in
|
||||
run_cmd Lean.Elab.Command.liftTermElabM do
|
||||
Lean.logInfo <| ← `(tactic| use1 .succ 0)
|
||||
Lean.logInfo <| ← `(tactic| use2 .succ 0)
|
||||
|
||||
/-!
|
||||
Check that fix even works inside other nodes.
|
||||
-/
|
||||
|
||||
syntax myPPSpace := ppSpace
|
||||
|
||||
syntax "use3" myPPSpace term,+ : tactic
|
||||
syntax "use4" group(myPPSpace) term,+ : tactic
|
||||
|
||||
/--
|
||||
info: use3 .succ✝ 0
|
||||
---
|
||||
info: use4 .succ✝ 0
|
||||
-/
|
||||
#guard_msgs in
|
||||
run_cmd Lean.Elab.Command.liftTermElabM do
|
||||
Lean.logInfo <| ← `(tactic| use3 .succ 0)
|
||||
Lean.logInfo <| ← `(tactic| use4 .succ 0)
|
||||
Loading…
Add table
Reference in a new issue