on master help sign in
Fixed an idempotence issue in type synonym and data declarations
commit60752a28539c378d81121a1a693b00088fd9b2f6 authorMark Karpov <markkarpov92@gmail.com> dateThu 7 May 2020, 13:06 (6 years ago) parenteb8bccd
17 files changed+72−71
CHANGELOG.md+4 data/examples/declaration/data/gadt/multiline-out.hs+1−1 data/examples/declaration/data/multiline-arg-parens-out.hs+1−1 data/examples/declaration/data/with-weird-haddock-out.hs+4 data/examples/declaration/data/with-weird-haddock.hs+2 data/examples/declaration/type-synonyms/with-weird-haddock-out.hs+3 data/examples/declaration/type-synonyms/with-weird-haddock.hs+1 data/examples/declaration/value/function/arrow/proc-do-complex-out.hs+1−1 data/examples/declaration/value/function/multi-way-if-out.hs+4−2 data/examples/declaration/value/function/operator-comments-2-out.hs+2−2 data/examples/other/comment-two-blocks-out.hs+2−2 expected-failures/Agda.txt+3−15 expected-failures/idris.txt+3−9 src/Ormolu/Printer/Internal.hs+26−35 src/Ormolu/Printer/Meat/Declaration/Data.hs+10−1 src/Ormolu/Printer/Meat/Declaration/Type.hs+3−1 src/Ormolu/Printer/Meat/Declaration/Value.hs+2−1
CHANGELOG.md+4
@@ -17,6 +17,10 @@
1717 separated from the elements they are attached to by the equality sign.
1818 [Issue 340](https://github.com/tweag/ormolu/issues/340).
1919
20+* Fixed an idempotence issue with type synonym and data declarations where
21+ the type has a Haddock. [Issue
22+ 578](https://github.com/tweag/ormolu/issues/578).
23+
2024* Renamed the `--check-idempotency` flag to `--check-idempotence`.
2125 Apparently only the latter is correct.
2226
data/examples/declaration/data/gadt/multiline-out.hs+1−1
@@ -8,7 +8,7 @@ data Foo a where
88 Foo ::
99 forall a b.
1010 (Show a, Eq b) => -- foo
11− -- bar
11+ -- bar
1212 a ->
1313 b ->
1414 Foo 'Int
data/examples/declaration/data/multiline-arg-parens-out.hs+1−1
@@ -5,6 +5,6 @@ data Foo
55 = Foo
66 Bar
77 (Set Baz) -- and here we go
8− -- and that's it
8+ -- and that's it
99 Text
1010 deriving (Eq)
data/examples/declaration/data/with-weird-haddock-out.hsnew file+4
@@ -0,0 +1,4 @@
1+data PlusLevel' t
2+ = -- | @n + ℓ@.
3+ Plus Integer (LevelAtom' t)
4+ deriving (Show, Data)
data/examples/declaration/data/with-weird-haddock.hsnew file+2
@@ -0,0 +1,2 @@
1+data PlusLevel' t = Plus Integer (LevelAtom' t) -- ^ @n + ℓ@.
2+ deriving (Show, Data)
data/examples/declaration/type-synonyms/with-weird-haddock-out.hsnew file+3
@@ -0,0 +1,3 @@
1+type Elims =
2+ -- | eliminations ordered left-to-right.
3+ [Elim]
data/examples/declaration/type-synonyms/with-weird-haddock.hsnew file+1
@@ -0,0 +1 @@
1+type Elims = [Elim] -- ^ eliminations ordered left-to-right.
data/examples/declaration/value/function/arrow/proc-do-complex-out.hs+1−1
@@ -40,7 +40,7 @@ foo
4040 )
4141 else do
4242 let u = x -- Let bindings bind expressions, not commands
43− -- Could pattern match directly on x
43+ -- Could pattern match directly on x
4444 i <- case u of
4545 0 -> (g . h -< u)
4646 n ->
data/examples/declaration/value/function/multi-way-if-out.hs+4−2
@@ -3,12 +3,14 @@
33foo x = if | x == 5 -> 5
44
55bar x y =
6− if | x > y -> x
6+ if
7+ | x > y -> x
78 | x < y ->
89 y
910 | otherwise -> x
1011
1112baz =
12− if | p -> f
13+ if
14+ | p -> f
1315 | otherwise -> g
1416 x
data/examples/declaration/value/function/operator-comments-2-out.hs+2−2
@@ -1,5 +1,5 @@
11x =
22 y
33 ++ f g -- commentA
4− -- commentB
5− -- commentC
4+ -- commentB
5+ -- commentC
data/examples/other/comment-two-blocks-out.hs+2−2
@@ -2,7 +2,7 @@ newNames :: [(String, String)]
22newNames =
33 let (*) = flip (,)
44 in [ "Control" * "Monad"
5− -- Foo
5+ -- Foo
66
7− -- Bar
7+ -- Bar
88 ]
expected-failures/Agda.txt+3−15
@@ -4,25 +4,13 @@ Formatting is not idempotent:
44 after: " =\n "
55Please, consider reporting the bug.
66
7−Formatting is not idempotent:
8− src/full/Agda/Syntax/Internal.hs<rendered>:236:12
9− before: "pe Elims = -- | elim"
10− after: "pe Elims =\n -- | el"
11−Please, consider reporting the bug.
12−
137Parsing of formatted code failed:
148 src/full/Agda/Syntax/Translation/ConcreteToAbstract.hs<rendered>:524:7-13
159 parse error on input `C.QName'
1610Please, consider reporting the bug.
1711
1812Formatting is not idempotent:
19− src/full/Agda/TypeChecking/MetaVars.hs<rendered>:1448:16
20− before: "ubstCand = -- | a po"
21− after: "ubstCand =\n -- | a "
22−Please, consider reporting the bug.
23−
24−Formatting is not idempotent:
25− src/full/Agda/Utils/List.hs<rendered>:186:15
26− before: "Prefix a = -- | The "
27− after: "Prefix a =\n -- | Th"
13+ src/full/Agda/Syntax/Translation/InternalToAbstract.hs<rendered>:745:4
14+ before: " nes\n\n "
15+ after: " nes\n\n -- Andreas"
2816Please, consider reporting the bug.
expected-failures/idris.txt+3−9
@@ -17,15 +17,9 @@ Formatting is not idempotent:
1717Please, consider reporting the bug.
1818
1919Formatting is not idempotent:
20− src/Idris/Delaborate.hs<rendered>:628:6
21− before: "ity\n -- Issue #"
22− after: "ity\n -- Issue"
23−Please, consider reporting the bug.
24−
25−Formatting is not idempotent:
26− src/Idris/Options.hs<rendered>:177:17
27− before: "timisation = PETrans"
28− after: "timisation\n = PETra"
20+ src/Idris/Options.hs<rendered>:178:15
21+ before: "ETransform | -- | pa"
22+ after: "ETransform\n | -- | "
2923Please, consider reporting the bug.
3024
3125The GHC parser (in Haddock mode) failed:
src/Ormolu/Printer/Internal.hs+26−35
@@ -99,6 +99,8 @@ data RC = RC
9999data SC = SC
100100 { -- | Index of the next column to render
101101 scColumn :: !Int,
102+ -- | Indentation level that was used for the current line
103+ scIndent :: !Int,
102104 -- | Rendered source code so far
103105 scBuilder :: Builder,
104106 -- | Span stream
@@ -109,7 +111,7 @@ data SC = SC
109111 scCommentStream :: CommentStream,
110112 -- | Pending comment lines (in reverse order) to be inserted before next
111113 -- newline, 'Int' is the indentation level
112− scPendingComments :: ![(CommentPosition, Int, Text)],
114+ scPendingComments :: ![(CommentPosition, Text)],
113115 -- | Whether to output a space before the next output
114116 scRequestedDelimiter :: !RequestedDelimiter,
115117 -- | An auxiliary marker for keeping track of last output element
@@ -175,6 +177,7 @@ runR (R m) sstream cstream anns recDot =
175177 sc =
176178 SC
177179 { scColumn = 0,
180+ scIndent = 0,
178181 scBuilder = mempty,
179182 scSpanStream = sstream,
180183 scThisLineSpans = [],
@@ -258,15 +261,20 @@ spit stype text = do
258261 i <- asks rcIndent
259262 c <- gets scColumn
260263 closestEnclosing <- listToMaybe <$> asks rcEnclosingSpans
261− let spaces =
262− if c < i
263− then T.replicate (i - c) " "
264− else bool mempty " " (requestedDel == RequestedSpace)
265− indentedTxt = spaces <> text
264+ let indentedTxt = spaces <> text
265+ spaces = T.replicate spacesN " "
266+ spacesN =
267+ if c == 0
268+ then i
269+ else bool 0 1 (requestedDel == RequestedSpace)
266270 modify $ \sc ->
267271 sc
268272 { scBuilder = scBuilder sc <> fromText indentedTxt,
269273 scColumn = scColumn sc + T.length indentedTxt,
274+ scIndent =
275+ if c == 0
276+ then i
277+ else scIndent sc,
270278 scThisLineSpans =
271279 let xs = scThisLineSpans sc
272280 in case stype of
@@ -310,24 +318,15 @@ space = R . modify $ \sc ->
310318-- hard to output more than one blank newline in a row.
311319newline :: R ()
312320newline = do
313− cs <- R (gets scPendingComments)
314− -- Indentation should be the same for the whole series otherwise there
315− -- will be problems with idempotence. Which identation level to use? The
316− -- last. It'll be the level at which the last comment were attached and
317− -- since the all pending comments are necessarily attached to elements on
318− -- the same line, they all will be attached to the very last element on
319− -- the next pass.
320− let indent = case cs of
321− [] -> 0
322− ((_, i, _) : _) -> i
323− csReversed = reverse cs
324− case csReversed of
321+ indent <- R (gets scIndent)
322+ cs <- reverse <$> R (gets scPendingComments)
323+ case cs of
325324 [] -> newlineRaw
326− ((position, _, _) : _) -> do
325+ ((position, _) : _) -> do
327326 case position of
328327 OnTheSameLine -> space
329328 OnNextLine -> newlineRaw
330− R . forM_ csReversed $ \(_, _, text) ->
329+ R . forM_ cs $ \(_, text) ->
331330 let modRC rc =
332331 rc
333332 { rcIndent = indent
@@ -355,6 +354,7 @@ newlineRaw = R . modify $ \sc ->
355354 VeryBeginning -> builderSoFar
356355 _ -> builderSoFar <> "\n",
357356 scColumn = 0,
357+ scIndent = 0,
358358 scThisLineSpans = [],
359359 scRequestedDelimiter = case scRequestedDelimiter sc of
360360 AfterNewline -> RequestedNewline
@@ -365,7 +365,7 @@ newlineRaw = R . modify $ \sc ->
365365
366366-- | Return 'True' if we should print record dot syntax.
367367useRecordDot :: R Bool
368−useRecordDot = R $ asks rcUseRecDot
368+useRecordDot = R (asks rcUseRecDot)
369369
370370-- | Increase indentation level by one indentation step for the inner
371371-- computation. 'inci' should be used when a part of code must be more
@@ -382,8 +382,7 @@ inci (R m) = R (local modRC m)
382382
383383-- | Set indentation level for the inner computation equal to current
384384-- column. This makes sure that the entire inner block is uniformly
385−-- \"shifted\" to the right. Only works (and makes sense) when enclosing
386−-- layout is multi-line.
385+-- \"shifted\" to the right.
387386sitcc :: R () -> R ()
388387sitcc (R m) = do
389388 requestedDel <- R (gets scRequestedDelimiter)
@@ -391,16 +390,9 @@ sitcc (R m) = do
391390 c <- R (gets scColumn)
392391 let modRC rc =
393392 rc
394− { rcIndent = max i c + bool 0 1 (requestedDel == RequestedSpace)
393+ { rcIndent = max i (c + bool 0 1 (requestedDel == RequestedSpace))
395394 }
396− vlayout (R m) . R $ do
397− modify $ \sc ->
398− sc
399− { scRequestedDelimiter = case requestedDel of
400− RequestedSpace -> RequestedNothing
401− other -> other
402− }
403− local modRC m
395+ R (local modRC m)
404396
405397-- | Set 'Layout' for internal computation.
406398enterLayout :: Layout -> R () -> R ()
@@ -442,10 +434,9 @@ registerPendingCommentLine ::
442434 Text ->
443435 R ()
444436registerPendingCommentLine position text = R $ do
445− i <- asks rcIndent
446437 modify $ \sc ->
447438 sc
448− { scPendingComments = (position, i, text) : scPendingComments sc
439+ { scPendingComments = (position, text) : scPendingComments sc
449440 }
450441
451442-- | Drop elements that begin before or at the same place as given
@@ -574,7 +565,7 @@ dontUseBraces (R r) = R (local (\i -> i {rcCanUseBraces = False}) r)
574565
575566-- | Return 'True' if we can use braces in this context.
576567canUseBraces :: R Bool
577−canUseBraces = R $ asks rcCanUseBraces
568+canUseBraces = R (asks rcCanUseBraces)
578569
579570----------------------------------------------------------------------------
580571-- Constants
src/Ormolu/Printer/Meat/Declaration/Data.hs+10−1
@@ -66,7 +66,10 @@ p_dataDecl style name tpats fixity HsDataDefn {..} = do
6666 let singleConstRec = isSingleConstRec dd_cons
6767 if singleConstRec
6868 then space
69− else breakpoint
69+ else
70+ if hasHaddocks dd_cons
71+ then newline
72+ else breakpoint
7073 equals
7174 space
7275 let s =
@@ -256,3 +259,9 @@ isSingleConstRec [(L _ ConDeclH98 {..})] =
256259 RecCon _ -> True
257260 _ -> False
258261isSingleConstRec _ = False
262+
263+hasHaddocks :: [LConDecl GhcPs] -> Bool
264+hasHaddocks = any (f . unLoc)
265+ where
266+ f ConDeclH98 {..} = isJust con_doc
267+ f _ = False
src/Ormolu/Printer/Meat/Declaration/Type.hs+3−1
@@ -33,6 +33,8 @@ p_synDecl name fixity HsQTvs {..} t = do
3333 (map (located' p_hsTyVarBndr) hsq_explicit)
3434 space
3535 equals
36− breakpoint
36+ if hasDocStrings (unLoc t)
37+ then newline
38+ else breakpoint
3739 inci (located t p_hsType)
3840p_synDecl _ _ (XLHsQTyVars x) _ = noExtCon x
src/Ormolu/Printer/Meat/Declaration/Value.hs+2−1
@@ -663,7 +663,8 @@ p_hsExpr' s = \case
663663 HsIf NoExtField _ if' then' else' ->
664664 p_if exprPlacement p_hsExpr if' then' else'
665665 HsMultiIf NoExtField guards -> do
666− txt "if "
666+ txt "if"
667+ breakpoint
667668 inci . inci . sitcc $ sep newline (located' (p_grhs RightArrow)) guards
668669 HsLet NoExtField localBinds e ->
669670 p_let p_hsExpr localBinds e