diff --git a/src/Lean/PrettyPrinter/Formatter.lean b/src/Lean/PrettyPrinter/Formatter.lean index 7566236190..0f186bddf6 100644 --- a/src/Lean/PrettyPrinter/Formatter.lean +++ b/src/Lean/PrettyPrinter/Formatter.lean @@ -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 diff --git a/tests/lean/run/4561.lean b/tests/lean/run/4561.lean new file mode 100644 index 0000000000..a95ce5e930 --- /dev/null +++ b/tests/lean/run/4561.lean @@ -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)