on master help sign in
Implement handling of semicolons
commit16f2c644a7e24bf6ee7b622a53706a275c064062 authorUtku Demir <me@utdemir.com> dateMon 12 Aug 2019, 15:37 (7 years ago) parentc3d69d5
32 files changed+287−138
data/examples/declaration/class/associated-data-out.hs+1−3 data/examples/declaration/class/associated-type-defaults-out.hs+1−3 data/examples/declaration/class/associated-types-out.hs+1−3 data/examples/declaration/class/functional-dependencies-out.hs+1−3 data/examples/declaration/class/multi-parameters-out.hs+1−3 data/examples/declaration/class/single-parameters-out.hs+1−3 data/examples/declaration/instance/associated-data-out.hs+1−3 data/examples/declaration/instance/associated-types-out.hs+1−3 data/examples/declaration/instance/contexts-out.hs+1−3 data/examples/declaration/instance/multi-parameter-out.hs+1−3 data/examples/declaration/instance/overlappable-instances-out.hs+1−3 data/examples/declaration/instance/single-parameter-out.hs+3−3 data/examples/declaration/instance/single-parameter.hs+2 data/examples/declaration/value/function/case-single-line-out.hs+5 data/examples/declaration/value/function/case-single-line.hs+4 data/examples/declaration/value/function/do-out.hs+37−7 data/examples/declaration/value/function/do.hs+32 data/examples/declaration/value/function/lambda-multi-line-out.hs+5 data/examples/declaration/value/function/lambda-multi-line.hs+6 data/examples/declaration/value/function/let-single-line-out.hs+7−1 data/examples/declaration/value/function/let-single-line.hs+5 data/examples/declaration/value/function/operators-out.hs+4−3 data/examples/declaration/value/function/pattern/pattern-bind-out.hs+4−1 data/examples/declaration/value/function/pattern/pattern-bind.hs+4−1 src/Ormolu/Printer/Combinators.hs+35 src/Ormolu/Printer/Internal.hs+25 src/Ormolu/Printer/Meat/Declaration.hs+11−10 src/Ormolu/Printer/Meat/Declaration/Class.hs+2−2 src/Ormolu/Printer/Meat/Declaration/Data.hs+1−1 src/Ormolu/Printer/Meat/Declaration/Instance.hs+12−10 src/Ormolu/Printer/Meat/Declaration/Value.hs+60−55 src/Ormolu/Printer/Meat/Module.hs+12−11
data/examples/declaration/class/associated-data-out.hs+1−3
@@ -1,8 +1,6 @@
11{-# LANGUAGE TypeFamilies #-}
22
3−class Foo a where
4−
5− data FooBar a
3+class Foo a where data FooBar a
64
75-- | Something.
86class Bar a where
data/examples/declaration/class/associated-type-defaults-out.hs+1−3
@@ -1,8 +1,6 @@
11{-# LANGUAGE TypeFamilies #-}
22
3−class Foo a where
4−
5− type FooBar a = Int
3+class Foo a where type FooBar a = Int
64
75-- | Something.
86class Bar a where
data/examples/declaration/class/associated-types-out.hs+1−3
@@ -1,8 +1,6 @@
11{-# LANGUAGE TypeFamilies #-}
22
3−class Foo a where
4−
5− type FooBar a
3+class Foo a where type FooBar a
64
75-- | Something.
86class Bar a where
data/examples/declaration/class/functional-dependencies-out.hs+1−3
@@ -3,9 +3,7 @@
33-- | Something.
44class Foo a b | a -> b
55
6−class Bar a b | a -> b, b -> a where
7−
8− bar :: a
6+class Bar a b | a -> b, b -> a where bar :: a
97
108-- | Something else.
119class
data/examples/declaration/class/multi-parameters-out.hs+1−3
@@ -1,8 +1,6 @@
11{-# LANGUAGE MultiParamTypeClasses #-}
22
3−class Foo a b where
4−
5− foo :: a -> b
3+class Foo a b where foo :: a -> b
64
75-- | Something.
86class Bar a b c d where
data/examples/declaration/class/single-parameters-out.hs+1−3
@@ -1,7 +1,5 @@
11-- | Something.
2−class Foo a where
3−
4− foo :: a
2+class Foo a where foo :: a
53
64-- | Something more.
75class Bar a where
data/examples/declaration/instance/associated-data-out.hs+1−3
@@ -1,8 +1,6 @@
11{-# LANGUAGE TypeFamilies #-}
22
3−instance Foo Int where
4−
5− data Bar Int = IntBar Int Int
3+instance Foo Int where data Bar Int = IntBar Int Int
64
75instance Foo Double where
86
data/examples/declaration/instance/associated-types-out.hs+1−3
@@ -1,8 +1,6 @@
11{-# LANGUAGE TypeFamilies #-}
22
3−instance Foo Int where
4−
5− type Bar Int = Double
3+instance Foo Int where type Bar Int = Double
64
75instance Foo Double where
86
data/examples/declaration/instance/contexts-out.hs+1−3
@@ -1,6 +1,4 @@
1−instance Eq a => Eq [a] where
2−
3− (==) _ _ = False
1+instance Eq a => Eq [a] where (==) _ _ = False
42
53instance
64 ( Ord a,
data/examples/declaration/instance/multi-parameter-out.hs+1−3
@@ -1,6 +1,4 @@
1−instance MonadReader a ((->) a) where
2−
3− ask = id
1+instance MonadReader a ((->) a) where ask = id
42
53instance MonadState s (State s) where
64
data/examples/declaration/instance/overlappable-instances-out.hs+1−3
@@ -1,6 +1,4 @@
1−instance {-# OVERLAPPABLE #-} Eq Int where
2−
3− (==) _ _ = False
1+instance {-# OVERLAPPABLE #-} Eq Int where (==) _ _ = False
42
53instance {-# OVERLAPPING #-} Ord Int where
64
data/examples/declaration/instance/single-parameter-out.hs+3−3
@@ -1,6 +1,4 @@
1−instance Monoid Int where
2−
3− (<>) x y = x + y
1+instance Monoid Int where (<>) x y = x + y
42
53instance Enum Int where
64
@@ -9,3 +7,5 @@ instance Enum Int where
97 toEnum =
108 \x ->
119 x
10+
11+instance Foo Int where foo x = x; bar y = y
data/examples/declaration/instance/single-parameter.hs+2
@@ -6,3 +6,5 @@ instance Enum Int
66 toEnum
77 = \x ->
88 x
9+
10+instance Foo Int where { foo x = x; bar y = y }
data/examples/declaration/value/function/case-single-line-out.hs+5
@@ -1,2 +1,7 @@
11foo :: Int -> Int
22foo x = case x of x -> x
3+
4+foo :: IO ()
5+foo = case [1] of [_] -> "singleton"; _ -> "not singleton"
6+
7+foo = case [1] of { [] -> foo; _ -> bar } `finally` baz
data/examples/declaration/value/function/case-single-line.hs+4
@@ -1,2 +1,6 @@
11foo :: Int -> Int
22foo x = case x of x -> x
3+
4+foo :: IO ()
5+foo = case [1] of [_] -> "singleton"; _ -> "not singleton"
6+foo = case [1] of { [] -> foo; _ -> bar } `finally` baz
data/examples/declaration/value/function/do-out.hs+37−7
@@ -1,8 +1,6 @@
11{-# LANGUAGE RecursiveDo #-}
22
3−bar = do
4− foo
5− bar
3+bar = do foo; bar
64
75baz =
86 mdo
@@ -60,15 +58,22 @@ g = unFoo
6058 . foo
6159 bar
6260 baz
63− 3 $ do
64− act
65− ret
61+ 3
62+ $ do
63+ act
64+ ret
6665
6766main =
6867 do stuff
6968 `finally` do
7069 recover
7170
71+main = do stuff `finally` recover
72+
73+main = do { stuff } `finally` recover
74+
75+foo = do do { foo; bar }; baz
76+
7277foo =
7378 do
7479 1
@@ -77,5 +82,30 @@ foo =
7782-- single line let-where
7883samples n f = do
7984 gen <- newQCGen
80− let rands g = g1 : rands g2 where (g1, g2) = split g
85+ let rands g = g1 : rands g2 where { (g1, g2) = split g }
8186 return $ rands gen
87+
88+main = do bar
89+
90+main = do bar; baz
91+
92+main = do
93+ bar
94+ baz
95+
96+main = do
97+ a <- bar
98+ let a = b; c = d
99+ baz d
100+ let e = f
101+ g = h
102+ return c
103+
104+readInClause = do
105+ do
106+ lookAhead g_Do
107+ parseNote ErrorC 1063 "You need a line feed or semicolon before the 'do'."
108+ <|> do
109+ optional g_Semi
110+ void allspacing
111+ return things
data/examples/declaration/value/function/do.hs+32
@@ -67,6 +67,12 @@ main =
6767 `finally` do
6868 recover
6969
70+main = do stuff `finally` recover
71+
72+main = do { stuff } `finally` recover
73+
74+foo = do { do {foo; bar}; baz }
75+
7076foo = do
7177 1
7278 +
@@ -77,3 +83,29 @@ samples n f = do
7783 gen <- newQCGen
7884 let rands g = g1 : rands g2 where (g1, g2) = split g
7985 return $ rands gen
86+
87+main = do bar
88+main = do { bar; baz }
89+main = do { bar
90+ ; baz
91+ }
92+
93+main = do
94+ a <- bar
95+ let a = b; c = d
96+ baz d
97+ let e = f
98+ g = h
99+ return c
100+
101+readInClause = do
102+ do {
103+ lookAhead g_Do;
104+ parseNote ErrorC 1063 "You need a line feed or semicolon before the 'do'.";
105+ } <|> do {
106+ optional g_Semi;
107+ void allspacing;
108+ }
109+
110+ return things
111+
data/examples/declaration/value/function/lambda-multi-line-out.hs+5
@@ -20,3 +20,8 @@ tricky2 =
2020 flip all (zip ws gs)
2121 $ \(wt, gt) ->
2222 canUnify poly_given_ok wt gt || go False wt gt
23+
24+foo =
25+ prop "is inverse to closure" $ \(f :: StaticPtr (Int -> Int))
26+ (x :: Int) ->
27+ (unclosure . closure) f x == deRefStaticPtr f x
data/examples/declaration/value/function/lambda-multi-line.hs+6
@@ -20,3 +20,9 @@ tricky2 =
2020 flip all (zip ws gs) $
2121 \(wt, gt) ->
2222 canUnify poly_given_ok wt gt || go False wt gt
23+
24+foo =
25+ prop "is inverse to closure" $ \(f :: StaticPtr (Int -> Int))
26+ (x :: Int) ->
27+ (unclosure . closure) f x == deRefStaticPtr f x
28+
data/examples/declaration/value/function/let-single-line-out.hs+7−1
@@ -1,3 +1,9 @@
11foo :: a -> a
22foo x = let x = x in x
3−foo x = let x = z where z = 2 in x
3+foo x = let x = z where { z = 2 } in x
4+foo x = let x = z where { z = 2 }; a = 3 in x
5+foo x = let g :: Int -> Int; g = id in ()
6+
7+let a = b; c = do { foo; bar }; d = baz in b
8+
9+let a = case True of { True -> foo; False -> bar }; b = foo a in b
data/examples/declaration/value/function/let-single-line.hs+5
@@ -1,3 +1,8 @@
11foo :: a -> a
22foo x = let x = x in x
33foo x = let x = z where z = 2 in x
4+foo x = let x = z where { z = 2; }; a = 3 in x
5+foo x = let {g :: Int -> Int; g = id} in ()
6+let a = b; c = do { foo; bar }; d = baz in b
7+let a = case True of { True -> foo; False -> bar }; b = foo a in b
8+
data/examples/declaration/value/function/operators-out.hs+4−3
@@ -38,7 +38,8 @@ lenses =
3838 .= ("user.connection" :: Text)
3939 # "connection"
4040 .= uc
41− # "user" .= case name of
42− Just n -> Just $ object ["name" .= n]
43− Nothing -> Nothing
41+ # "user"
42+ .= case name of
43+ Just n -> Just $ object ["name" .= n]
44+ Nothing -> Nothing
4445 # []
data/examples/declaration/value/function/pattern/pattern-bind-out.hs+4−1
@@ -1,6 +1,9 @@
1−foo :: Int
21foo = bar
32 where
43 Foo bar baz = quux
54 Baz
65 quux = zoo
6+
7+foo = bar
8+ where
9+ Foo bar baz = quux
data/examples/declaration/value/function/pattern/pattern-bind.hs+4−1
@@ -1,6 +1,9 @@
1−foo :: Int
21foo = bar
32 where
43 Foo bar baz = quux
54 Baz
65 quux = zoo
6+
7+foo = bar
8+ where Foo bar baz = quux
9+
src/Ormolu/Printer/Combinators.hs+35
@@ -24,6 +24,9 @@ module Ormolu.Printer.Combinators
2424 , breakpoint'
2525 -- ** Formatting lists
2626 , sep
27+ , sepSemi
28+ , useBraces
29+ , dontUseBraces
2730 -- ** Wrapping
2831 , sitcc
2932 , line
@@ -42,6 +45,7 @@ module Ormolu.Printer.Combinators
4245 )
4346where
4447
48+import Control.Monad
4549import Data.Data (Data)
4650import Data.List (intersperse)
4751import Data.Text (Text)
@@ -156,6 +160,37 @@ sep
156160 -> R ()
157161sep s f xs = sequence_ (intersperse s (f <$> xs))
158162
163+-- | Render a collection of elements layout-sensitively using given printer,
164+-- inserting semicolons if necessary and respecting 'useBraces' and
165+-- 'dontUseBraces' combinators.
166+--
167+-- > useBraces $ sepSemi txt ["foo", "bar"]
168+-- > == vlayout (txt "{ foo; bar }") (txt "foo\nbar")
169+--
170+-- > dontUseBraces $ sepSemi txt ["foo", "bar"]
171+-- > == vlayout (txt "foo; bar") (txt "foo\nbar")
172+
173+sepSemi
174+ :: (a -> R ()) -- ^ How to render an element
175+ -> [a] -- ^ Elements to render
176+ -> R ()
177+sepSemi f xs = vlayout singleLine multiLine
178+ where
179+ singleLine = do
180+ ub <- canUseBraces
181+ case xs of
182+ [] -> when ub $ txt "{}"
183+ xs' ->
184+ if ub
185+ then do
186+ txt "{ "
187+ sep (txt "; ") (dontUseBraces . f) xs'
188+ txt " }"
189+ else
190+ sep (txt "; ") f xs'
191+ multiLine =
192+ sep newline (dontUseBraces . f) xs
193+
159194----------------------------------------------------------------------------
160195-- Wrapping
161196
src/Ormolu/Printer/Internal.hs+25
@@ -23,6 +23,10 @@ module Ormolu.Printer.Internal
2323 , Layout (..)
2424 , enterLayout
2525 , vlayout
26+ -- * Helpers for braces
27+ , useBraces
28+ , dontUseBraces
29+ , canUseBraces
2630 -- * Special helpers for comment placement
2731 , trimSpanStream
2832 , nextEltSpan
@@ -75,6 +79,8 @@ data RC = RC
7579 -- ^ Span of enclosing element of AST
7680 , rcAnns :: Anns
7781 -- ^ Collection of annotations
82+ , rcCanUseBraces :: Bool
83+ -- ^ If the last expression in the layout can use braces
7884 }
7985
8086-- | State context of 'R'.
@@ -117,6 +123,7 @@ runR debug (R m) sstream cstream anns =
117123 , rcDebug = debug
118124 , rcEnclosingSpans = []
119125 , rcAnns = anns
126+ , rcCanUseBraces = False
120127 }
121128 sc = SC
122129 { scColumn = 0
@@ -344,6 +351,24 @@ getAnns
344351 -> R [AnnKeywordId]
345352getAnns spn = lookupAnns spn <$> R (asks rcAnns)
346353
354+----------------------------------------------------------------------------
355+-- Helpers for braces
356+
357+-- | Make the inner computation use braces around single-line layouts.
358+
359+useBraces :: R () -> R ()
360+useBraces (R r) = R (local (\i -> i {rcCanUseBraces = True}) r)
361+
362+-- | Make the inner computation omit braces around single-line layouts.
363+
364+dontUseBraces :: R () -> R ()
365+dontUseBraces (R r) = R (local (\i -> i {rcCanUseBraces = False}) r)
366+
367+-- | Return 'True' if we can use braces in this context.
368+
369+canUseBraces :: R Bool
370+canUseBraces = R $ asks rcCanUseBraces
371+
347372----------------------------------------------------------------------------
348373-- Debug helpers
349374
src/Ormolu/Printer/Meat/Declaration.hs+11−10
@@ -1,4 +1,5 @@
11{-# LANGUAGE LambdaCase #-}
2+{-# LANGUAGE OverloadedStrings #-}
23{-# LANGUAGE PatternSynonyms #-}
34{-# LANGUAGE RecordWildCards #-}
45{-# LANGUAGE ViewPatterns #-}
@@ -10,7 +11,6 @@ module Ormolu.Printer.Meat.Declaration
1011 )
1112where
1213
13−import Control.Monad (forM_)
1414import GHC
1515import OccName (occNameFS)
1616import Ormolu.Printer.Combinators
@@ -34,16 +34,17 @@ import Ormolu.Utils
3434import RdrName (rdrNameOcc)
3535
3636p_hsDecls :: FamilyStyle -> [LHsDecl GhcPs] -> R ()
37−p_hsDecls style decls =
38− forM_ (zip decls ((Just <$> drop 1 decls) ++ [Nothing])) $ \(d, md) ->
39− case md of
40− Nothing -> located d pDecl
41− Just d' ->
42− line $ if separatedDecls (unLoc d) (unLoc d')
43− then line (located d pDecl)
44− else located d pDecl
37+p_hsDecls style decls = do
38+ sepSemi (\(x, r) -> located x pDecl >> r) (separated decls)
4539 where
46− pDecl = p_hsDecl style
40+ pDecl = dontUseBraces . p_hsDecl style
41+
42+ separated [] = []
43+ separated [x] = [(x, return ())]
44+ separated (x:y:xs) =
45+ if separatedDecls (unLoc x) (unLoc y)
46+ then (x, breakpoint') : separated (y:xs)
47+ else (x, return ()) : separated (y:xs)
4748
4849p_hsDecl :: FamilyStyle -> HsDecl GhcPs -> R ()
4950p_hsDecl style = \case
src/Ormolu/Printer/Meat/Declaration/Class.hs+2−2
@@ -66,8 +66,8 @@ p_classDecl ctx name tvars fixity fdeps csigs cdefs cats catdefs = do
6666 snd <$> sortBy (comparing fst) (sigs <> vals <> tyFams <> tyFamDefs)
6767 unless (null allDecls) $ do
6868 txt " where"
69− newline -- Ensure line is added after where clause.
70− newline -- Add newline before first declaration.
69+ breakpoint -- Ensure whitespace is added after where clause.
70+ breakpoint' -- Add newline before first declaration.
7171 inci (p_hsDecls Associated allDecls)
7272
7373p_classContext :: LHsContext GhcPs -> R ()
src/Ormolu/Printer/Meat/Declaration/Data.hs+1−1
@@ -52,7 +52,7 @@ p_dataDecl style name tpats fixity HsDataDefn {..} = do
5252 then do
5353 txt " where"
5454 breakpoint
55− inci . sitcc $ sep newline (sitcc . located' p_conDecl) dd_cons
55+ inci $ sepSemi (located' p_conDecl) dd_cons
5656 else switchLayout (getLoc name : (getLoc <$> dd_cons)) $
5757 inci $ do
5858 breakpoint
src/Ormolu/Printer/Meat/Declaration/Instance.hs+12−10
@@ -67,11 +67,7 @@ p_clsInstDecl = \case
6767 ClsInstDecl {..} -> do
6868 txt "instance"
6969 case cid_poly_ty of
70− HsIB {..} -> located hsib_body $ \x -> do
71− breakpoint
72− inci $ do
73− match_overlap_mode cid_overlap_mode breakpoint
74− p_hsType x
70+ HsIB {..} -> do
7571 -- GHC's AST does not necessarily store each kind of element in source
7672 -- location order. This happens because different declarations are stored in
7773 -- different lists. Consequently, to get all the declarations in proper
@@ -87,13 +83,19 @@ p_clsInstDecl = \case
8783 allDecls =
8884 snd <$>
8985 sortBy (comparing fst) (sigs <> vals <> tyFamInsts <> dataFamInsts)
86+ located hsib_body $ \x -> do
87+ breakpoint
88+ inci $ do
89+ match_overlap_mode cid_overlap_mode breakpoint
90+ p_hsType x
91+ unless (null allDecls) $ do
92+ breakpoint
93+ txt "where"
9094 unless (null allDecls) $ do
91− switchLayout [getLoc hsib_body] breakpoint
9295 inci $ do
93− txt "where"
94− newline -- Ensure line is added after where clause.
95− newline -- Add newline before first declaration.
96− p_hsDecls Associated allDecls
96+ breakpoint -- Ensure whitespace is added after where clause.
97+ breakpoint' -- Add newline before first declaration
98+ dontUseBraces $ p_hsDecls Associated allDecls
9799 XHsImplicitBndrs NoExt -> notImplemented "XHsImplicitBndrs"
98100 XClsInstDecl NoExt -> notImplemented "XClsInstDecl"
99101
src/Ormolu/Printer/Meat/Declaration/Value.hs+60−55
@@ -81,8 +81,15 @@ p_matchGroup'
8181 -> MatchGroupStyle
8282 -> MatchGroup GhcPs (Located body)
8383 -> R ()
84−p_matchGroup' placer pretty style MG {..} =
85− sep newline (located' p_Match) (unLoc mg_alts)
84+p_matchGroup' placer pretty style MG {..} = do
85+ let ob = case style of
86+ Case -> id
87+ LambdaCase -> id
88+ _ -> dontUseBraces
89+ -- NOTE since we are forcing braces on 'sepSemi' based on 'ob', we have to
90+ -- restore the brace state inside the sepsemi.
91+ ub <- bool dontUseBraces useBraces <$> canUseBraces
92+ ob $ sepSemi (located' (ub . p_Match)) (unLoc mg_alts)
8693 where
8794 p_Match m@Match {..} =
8895 p_match'
@@ -179,7 +186,6 @@ p_match' placer pretty style isInfix strictness m_pats m_grhss = do
179186 stdCase
180187 LambdaCase -> stdCase
181188 return inci'
182−
183189 let
184190 -- Calculate position of end of patterns. This is useful when we decide
185191 -- about putting certain constructions in hanging positions.
@@ -192,49 +198,44 @@ p_match' placer pretty style isInfix strictness m_pats m_grhss = do
192198 Case -> True
193199 LambdaCase -> True
194200 _ -> False
201+ let GRHSs {..} = m_grhss
202+ hasGuards = withGuards grhssGRHSs
203+ unless (length grhssGRHSs > 1) $ do
204+ case style of
205+ Function _ | hasGuards -> return ()
206+ Function _ -> txt " ="
207+ PatternBind -> txt " ="
208+ s | isCase s && hasGuards -> return ()
209+ _ -> txt " ->"
210+ let grhssSpan = combineSrcSpans' $
211+ getGRHSSpan . unLoc <$> NE.fromList grhssGRHSs
212+ patGrhssSpan = maybe grhssSpan
213+ (combineSrcSpans grhssSpan . srcLocSpan) endOfPats
214+ placement =
215+ case endOfPats of
216+ Nothing -> blockPlacement placer grhssGRHSs
217+ Just spn ->
218+ if isOneLineSpan
219+ (mkSrcSpan spn (srcSpanStart grhssSpan))
220+ then blockPlacement placer grhssGRHSs
221+ else Normal
222+ p_body = do
223+ let groupStyle =
224+ if isCase style && hasGuards
225+ then RightArrow
226+ else EqualSign
227+ sep newline (located' (p_grhs' pretty groupStyle)) grhssGRHSs
228+ p_where = do
229+ let whereIsEmpty = GHC.isEmptyLocalBindsPR (unLoc grhssLocalBinds)
230+ unless (GHC.eqEmptyLocalBinds (unLoc grhssLocalBinds)) $ do
231+ breakpoint
232+ txt "where"
233+ unless whereIsEmpty breakpoint
234+ inci $ located grhssLocalBinds p_hsLocalBinds
195235 inci' $ do
196− let GRHSs {..} = m_grhss
197− hasGuards = withGuards grhssGRHSs
198− unless (length grhssGRHSs > 1) $ do
199− case style of
200− Function _ | hasGuards -> return ()
201− Function _ -> txt " ="
202− PatternBind -> txt " ="
203− s | isCase s && hasGuards -> return ()
204− _ -> txt " ->"
205− let grhssSpan = combineSrcSpans' $
206− getGRHSSpan . unLoc <$> NE.fromList grhssGRHSs
207− patGrhssSpan = maybe grhssSpan
208− (combineSrcSpans grhssSpan . srcLocSpan) endOfPats
209− placement =
210− case endOfPats of
211− Nothing -> blockPlacement placer grhssGRHSs
212− Just spn ->
213− if isOneLineSpan
214− (mkSrcSpan spn (srcSpanStart grhssSpan))
215− then blockPlacement placer grhssGRHSs
216− else Normal
217− inciLocalBinds = case placement of
218− Normal -> id
219− Hanging -> inci
220− p_body = do
221− let groupStyle =
222− if isCase style && hasGuards
223− then RightArrow
224− else EqualSign
225− sep newline (located' (p_grhs' pretty groupStyle)) grhssGRHSs
226− let whereLocation = combineSrcSpans patGrhssSpan $ getLoc grhssLocalBinds
227− whereIsEmpty = GHC.isEmptyLocalBindsPR (unLoc grhssLocalBinds)
228− unless (GHC.eqEmptyLocalBinds (unLoc grhssLocalBinds))
229− . inciLocalBinds
230− . switchLayout [whereLocation] $ do
231− if whereIsEmpty then newline else breakpoint
232− txt "where"
233− unless whereIsEmpty $ do
234− breakpoint
235− inci (located grhssLocalBinds p_hsLocalBinds)
236236 switchLayout [patGrhssSpan] $
237237 placeHanging placement p_body
238+ inci p_where
238239
239240p_grhs :: GroupStyle -> GRHS GhcPs (LHsExpr GhcPs) -> R ()
240241p_grhs = p_grhs' p_hsExpr
@@ -386,7 +387,7 @@ p_stmt' pretty = \case
386387 inci (p_hsExpr x)
387388 RecStmt {..} -> do
388389 txt "rec "
389− sitcc $ sep newline (located' (p_stmt' pretty)) recS_stmts
390+ sitcc $ sepSemi (located' (p_stmt' pretty)) recS_stmts
390391 XStmtLR {} -> notImplemented "XStmtLR"
391392
392393gatherStmt :: ExprLStmt GhcPs -> [[ExprLStmt GhcPs]]
@@ -411,7 +412,7 @@ p_hsLocalBinds = \case
411412 (Left <$> bagToList bag) ++ (Right <$> lsigs)
412413 p_item (Left x) = located x p_valDecl
413414 p_item (Right x) = located x p_sigDecl
414− sitcc $ sep newline (sitcc . p_item) (sortOn ssStart items)
415+ sitcc $ sepSemi (useBraces . p_item) (sortOn ssStart items)
415416 HsValBinds NoExt _ -> notImplemented "HsValBinds"
416417 HsIPBinds NoExt _ -> notImplemented "HsIPBinds"
417418 EmptyLocalBinds NoExt -> return ()
@@ -468,18 +469,23 @@ p_hsExpr = \case
468469 txt "@"
469470 located (hswc_body a) p_hsType
470471 OpApp NoExt x op y -> do
471− located x p_hsExpr
472− -- NOTE If the end of the first argument and the beginning of the second
473− -- argument are on the same line, and the second argument has a hanging
474− -- form, use hanging placement.
472+ -- NOTE If the beginning of the first argument and the second argument
473+ -- are on the same line, and the second argument has a hanging form, use
474+ -- hanging placement.
475475 let placement =
476476 if isOneLineSpan
477− (mkSrcSpan (srcSpanEnd (getLoc x)) (srcSpanStart (getLoc y)))
477+ (mkSrcSpan (srcSpanStart (getLoc x)) (srcSpanStart (getLoc y)))
478478 then exprPlacement (unLoc y)
479479 else Normal
480480 opWrapper = case unLoc op of
481481 EWildPat NoExt -> backticks
482482 _ -> id
483+ ub <- vlayout
484+ (return useBraces)
485+ (return $ case placement of
486+ Hanging -> useBraces
487+ Normal -> dontUseBraces)
488+ ub $ located x p_hsExpr
483489 placeHanging placement $ do
484490 located op (opWrapper . p_hsExpr)
485491 space
@@ -543,10 +549,9 @@ p_hsExpr = \case
543549 HsDo NoExt ctx es -> do
544550 let doBody header = do
545551 txt header
546− if length (unLoc es) <= 1
547− then breakpoint
548− else newline
549− inci $ located es (sep newline (located' (sitcc . p_stmt)))
552+ breakpoint
553+ ub <- vlayout (return useBraces) (return id)
554+ inci $ sepSemi (located' (ub . p_stmt)) (unLoc es)
550555 compBody = brackets $ located es $ \xs -> do
551556 let p_parBody = sitcc . sep
552557 (breakpoint >> txt "| ")
@@ -864,7 +869,7 @@ p_hsBracket = \case
864869 txt "|"
865870 breakpoint'
866871 inci $ do
867− body
872+ dontUseBraces body
868873 breakpoint'
869874 txt "|]"
870875
src/Ormolu/Printer/Meat/Module.hs+12−11
@@ -57,14 +57,15 @@ p_hsModule pragmas (L moduleSpan HsModule {..}) = do
5757 when (hasImports || hasDecls) newline
5858 forM_ (sortImports hsmodImports) (located' p_hsmodImport)
5959 when (hasImports && hasDecls) newline
60− p_hsDecls Free hsmodDecls
61− trailingComments <- hasMoreComments
62− when hasDecls $ do
63− newlineModified <- isNewlineModified
64− newline
65− -- In this case we need to insert a newline between the comments
66− -- output as a side effect of the previous newline and trailing
67− -- comments to prevent them from merging.
68− when (newlineModified && trailingComments) newline
69− when (trailingComments && hasModuleHeader) newline
70− spitRemainingComments
60+ switchLayout (map getLoc hsmodDecls) $ do
61+ p_hsDecls Free hsmodDecls
62+ trailingComments <- hasMoreComments
63+ when hasDecls $ do
64+ newlineModified <- isNewlineModified
65+ newline
66+ -- In this case we need to insert a newline between the comments
67+ -- output as a side effect of the previous newline and trailing
68+ -- comments to prevent them from merging.
69+ when (newlineModified && trailingComments) newline
70+ when (trailingComments && hasModuleHeader) newline
71+ spitRemainingComments