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
50 lines
1.1 KiB
Text
50 lines
1.1 KiB
Text
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)
|