mirror of
https://github.com/google/ormolu.git
synced 2024-11-27 13:13:23 +03:00
Implement handling of semicolons
This commit is contained in:
parent
c3d69d5853
commit
16f2c644a7
@ -1,8 +1,6 @@
|
||||
{-# LANGUAGE TypeFamilies #-}
|
||||
|
||||
class Foo a where
|
||||
|
||||
data FooBar a
|
||||
class Foo a where data FooBar a
|
||||
|
||||
-- | Something.
|
||||
class Bar a where
|
||||
|
@ -1,8 +1,6 @@
|
||||
{-# LANGUAGE TypeFamilies #-}
|
||||
|
||||
class Foo a where
|
||||
|
||||
type FooBar a = Int
|
||||
class Foo a where type FooBar a = Int
|
||||
|
||||
-- | Something.
|
||||
class Bar a where
|
||||
|
@ -1,8 +1,6 @@
|
||||
{-# LANGUAGE TypeFamilies #-}
|
||||
|
||||
class Foo a where
|
||||
|
||||
type FooBar a
|
||||
class Foo a where type FooBar a
|
||||
|
||||
-- | Something.
|
||||
class Bar a where
|
||||
|
@ -3,9 +3,7 @@
|
||||
-- | Something.
|
||||
class Foo a b | a -> b
|
||||
|
||||
class Bar a b | a -> b, b -> a where
|
||||
|
||||
bar :: a
|
||||
class Bar a b | a -> b, b -> a where bar :: a
|
||||
|
||||
-- | Something else.
|
||||
class
|
||||
|
@ -1,8 +1,6 @@
|
||||
{-# LANGUAGE MultiParamTypeClasses #-}
|
||||
|
||||
class Foo a b where
|
||||
|
||||
foo :: a -> b
|
||||
class Foo a b where foo :: a -> b
|
||||
|
||||
-- | Something.
|
||||
class Bar a b c d where
|
||||
|
@ -1,7 +1,5 @@
|
||||
-- | Something.
|
||||
class Foo a where
|
||||
|
||||
foo :: a
|
||||
class Foo a where foo :: a
|
||||
|
||||
-- | Something more.
|
||||
class Bar a where
|
||||
|
@ -1,8 +1,6 @@
|
||||
{-# LANGUAGE TypeFamilies #-}
|
||||
|
||||
instance Foo Int where
|
||||
|
||||
data Bar Int = IntBar Int Int
|
||||
instance Foo Int where data Bar Int = IntBar Int Int
|
||||
|
||||
instance Foo Double where
|
||||
|
||||
|
@ -1,8 +1,6 @@
|
||||
{-# LANGUAGE TypeFamilies #-}
|
||||
|
||||
instance Foo Int where
|
||||
|
||||
type Bar Int = Double
|
||||
instance Foo Int where type Bar Int = Double
|
||||
|
||||
instance Foo Double where
|
||||
|
||||
|
@ -1,6 +1,4 @@
|
||||
instance Eq a => Eq [a] where
|
||||
|
||||
(==) _ _ = False
|
||||
instance Eq a => Eq [a] where (==) _ _ = False
|
||||
|
||||
instance
|
||||
( Ord a,
|
||||
|
@ -1,6 +1,4 @@
|
||||
instance MonadReader a ((->) a) where
|
||||
|
||||
ask = id
|
||||
instance MonadReader a ((->) a) where ask = id
|
||||
|
||||
instance MonadState s (State s) where
|
||||
|
||||
|
@ -1,6 +1,4 @@
|
||||
instance {-# OVERLAPPABLE #-} Eq Int where
|
||||
|
||||
(==) _ _ = False
|
||||
instance {-# OVERLAPPABLE #-} Eq Int where (==) _ _ = False
|
||||
|
||||
instance {-# OVERLAPPING #-} Ord Int where
|
||||
|
||||
|
@ -1,6 +1,4 @@
|
||||
instance Monoid Int where
|
||||
|
||||
(<>) x y = x + y
|
||||
instance Monoid Int where (<>) x y = x + y
|
||||
|
||||
instance Enum Int where
|
||||
|
||||
@ -9,3 +7,5 @@ instance Enum Int where
|
||||
toEnum =
|
||||
\x ->
|
||||
x
|
||||
|
||||
instance Foo Int where foo x = x; bar y = y
|
||||
|
@ -6,3 +6,5 @@ instance Enum Int
|
||||
toEnum
|
||||
= \x ->
|
||||
x
|
||||
|
||||
instance Foo Int where { foo x = x; bar y = y }
|
||||
|
@ -1,2 +1,7 @@
|
||||
foo :: Int -> Int
|
||||
foo x = case x of x -> x
|
||||
|
||||
foo :: IO ()
|
||||
foo = case [1] of [_] -> "singleton"; _ -> "not singleton"
|
||||
|
||||
foo = case [1] of { [] -> foo; _ -> bar } `finally` baz
|
||||
|
@ -1,2 +1,6 @@
|
||||
foo :: Int -> Int
|
||||
foo x = case x of x -> x
|
||||
|
||||
foo :: IO ()
|
||||
foo = case [1] of [_] -> "singleton"; _ -> "not singleton"
|
||||
foo = case [1] of { [] -> foo; _ -> bar } `finally` baz
|
||||
|
@ -1,8 +1,6 @@
|
||||
{-# LANGUAGE RecursiveDo #-}
|
||||
|
||||
bar = do
|
||||
foo
|
||||
bar
|
||||
bar = do foo; bar
|
||||
|
||||
baz =
|
||||
mdo
|
||||
@ -60,15 +58,22 @@ g = unFoo
|
||||
. foo
|
||||
bar
|
||||
baz
|
||||
3 $ do
|
||||
act
|
||||
ret
|
||||
3
|
||||
$ do
|
||||
act
|
||||
ret
|
||||
|
||||
main =
|
||||
do stuff
|
||||
`finally` do
|
||||
recover
|
||||
|
||||
main = do stuff `finally` recover
|
||||
|
||||
main = do { stuff } `finally` recover
|
||||
|
||||
foo = do do { foo; bar }; baz
|
||||
|
||||
foo =
|
||||
do
|
||||
1
|
||||
@ -77,5 +82,30 @@ foo =
|
||||
-- single line let-where
|
||||
samples n f = do
|
||||
gen <- newQCGen
|
||||
let rands g = g1 : rands g2 where (g1, g2) = split g
|
||||
let rands g = g1 : rands g2 where { (g1, g2) = split g }
|
||||
return $ rands gen
|
||||
|
||||
main = do bar
|
||||
|
||||
main = do bar; baz
|
||||
|
||||
main = do
|
||||
bar
|
||||
baz
|
||||
|
||||
main = do
|
||||
a <- bar
|
||||
let a = b; c = d
|
||||
baz d
|
||||
let e = f
|
||||
g = h
|
||||
return c
|
||||
|
||||
readInClause = do
|
||||
do
|
||||
lookAhead g_Do
|
||||
parseNote ErrorC 1063 "You need a line feed or semicolon before the 'do'."
|
||||
<|> do
|
||||
optional g_Semi
|
||||
void allspacing
|
||||
return things
|
||||
|
@ -67,6 +67,12 @@ main =
|
||||
`finally` do
|
||||
recover
|
||||
|
||||
main = do stuff `finally` recover
|
||||
|
||||
main = do { stuff } `finally` recover
|
||||
|
||||
foo = do { do {foo; bar}; baz }
|
||||
|
||||
foo = do
|
||||
1
|
||||
+
|
||||
@ -77,3 +83,29 @@ samples n f = do
|
||||
gen <- newQCGen
|
||||
let rands g = g1 : rands g2 where (g1, g2) = split g
|
||||
return $ rands gen
|
||||
|
||||
main = do bar
|
||||
main = do { bar; baz }
|
||||
main = do { bar
|
||||
; baz
|
||||
}
|
||||
|
||||
main = do
|
||||
a <- bar
|
||||
let a = b; c = d
|
||||
baz d
|
||||
let e = f
|
||||
g = h
|
||||
return c
|
||||
|
||||
readInClause = do
|
||||
do {
|
||||
lookAhead g_Do;
|
||||
parseNote ErrorC 1063 "You need a line feed or semicolon before the 'do'.";
|
||||
} <|> do {
|
||||
optional g_Semi;
|
||||
void allspacing;
|
||||
}
|
||||
|
||||
return things
|
||||
|
||||
|
@ -20,3 +20,8 @@ tricky2 =
|
||||
flip all (zip ws gs)
|
||||
$ \(wt, gt) ->
|
||||
canUnify poly_given_ok wt gt || go False wt gt
|
||||
|
||||
foo =
|
||||
prop "is inverse to closure" $ \(f :: StaticPtr (Int -> Int))
|
||||
(x :: Int) ->
|
||||
(unclosure . closure) f x == deRefStaticPtr f x
|
||||
|
@ -20,3 +20,9 @@ tricky2 =
|
||||
flip all (zip ws gs) $
|
||||
\(wt, gt) ->
|
||||
canUnify poly_given_ok wt gt || go False wt gt
|
||||
|
||||
foo =
|
||||
prop "is inverse to closure" $ \(f :: StaticPtr (Int -> Int))
|
||||
(x :: Int) ->
|
||||
(unclosure . closure) f x == deRefStaticPtr f x
|
||||
|
||||
|
@ -1,3 +1,9 @@
|
||||
foo :: a -> a
|
||||
foo x = let x = x in x
|
||||
foo x = let x = z where z = 2 in x
|
||||
foo x = let x = z where { z = 2 } in x
|
||||
foo x = let x = z where { z = 2 }; a = 3 in x
|
||||
foo x = let g :: Int -> Int; g = id in ()
|
||||
|
||||
let a = b; c = do { foo; bar }; d = baz in b
|
||||
|
||||
let a = case True of { True -> foo; False -> bar }; b = foo a in b
|
||||
|
@ -1,3 +1,8 @@
|
||||
foo :: a -> a
|
||||
foo x = let x = x in x
|
||||
foo x = let x = z where z = 2 in x
|
||||
foo x = let x = z where { z = 2; }; a = 3 in x
|
||||
foo x = let {g :: Int -> Int; g = id} in ()
|
||||
let a = b; c = do { foo; bar }; d = baz in b
|
||||
let a = case True of { True -> foo; False -> bar }; b = foo a in b
|
||||
|
||||
|
@ -38,7 +38,8 @@ lenses =
|
||||
.= ("user.connection" :: Text)
|
||||
# "connection"
|
||||
.= uc
|
||||
# "user" .= case name of
|
||||
Just n -> Just $ object ["name" .= n]
|
||||
Nothing -> Nothing
|
||||
# "user"
|
||||
.= case name of
|
||||
Just n -> Just $ object ["name" .= n]
|
||||
Nothing -> Nothing
|
||||
# []
|
||||
|
@ -1,6 +1,9 @@
|
||||
foo :: Int
|
||||
foo = bar
|
||||
where
|
||||
Foo bar baz = quux
|
||||
Baz
|
||||
quux = zoo
|
||||
|
||||
foo = bar
|
||||
where
|
||||
Foo bar baz = quux
|
||||
|
@ -1,6 +1,9 @@
|
||||
foo :: Int
|
||||
foo = bar
|
||||
where
|
||||
Foo bar baz = quux
|
||||
Baz
|
||||
quux = zoo
|
||||
|
||||
foo = bar
|
||||
where Foo bar baz = quux
|
||||
|
||||
|
@ -24,6 +24,9 @@ module Ormolu.Printer.Combinators
|
||||
, breakpoint'
|
||||
-- ** Formatting lists
|
||||
, sep
|
||||
, sepSemi
|
||||
, useBraces
|
||||
, dontUseBraces
|
||||
-- ** Wrapping
|
||||
, sitcc
|
||||
, line
|
||||
@ -42,6 +45,7 @@ module Ormolu.Printer.Combinators
|
||||
)
|
||||
where
|
||||
|
||||
import Control.Monad
|
||||
import Data.Data (Data)
|
||||
import Data.List (intersperse)
|
||||
import Data.Text (Text)
|
||||
@ -156,6 +160,37 @@ sep
|
||||
-> R ()
|
||||
sep s f xs = sequence_ (intersperse s (f <$> xs))
|
||||
|
||||
-- | Render a collection of elements layout-sensitively using given printer,
|
||||
-- inserting semicolons if necessary and respecting 'useBraces' and
|
||||
-- 'dontUseBraces' combinators.
|
||||
--
|
||||
-- > useBraces $ sepSemi txt ["foo", "bar"]
|
||||
-- > == vlayout (txt "{ foo; bar }") (txt "foo\nbar")
|
||||
--
|
||||
-- > dontUseBraces $ sepSemi txt ["foo", "bar"]
|
||||
-- > == vlayout (txt "foo; bar") (txt "foo\nbar")
|
||||
|
||||
sepSemi
|
||||
:: (a -> R ()) -- ^ How to render an element
|
||||
-> [a] -- ^ Elements to render
|
||||
-> R ()
|
||||
sepSemi f xs = vlayout singleLine multiLine
|
||||
where
|
||||
singleLine = do
|
||||
ub <- canUseBraces
|
||||
case xs of
|
||||
[] -> when ub $ txt "{}"
|
||||
xs' ->
|
||||
if ub
|
||||
then do
|
||||
txt "{ "
|
||||
sep (txt "; ") (dontUseBraces . f) xs'
|
||||
txt " }"
|
||||
else
|
||||
sep (txt "; ") f xs'
|
||||
multiLine =
|
||||
sep newline (dontUseBraces . f) xs
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
-- Wrapping
|
||||
|
||||
|
@ -23,6 +23,10 @@ module Ormolu.Printer.Internal
|
||||
, Layout (..)
|
||||
, enterLayout
|
||||
, vlayout
|
||||
-- * Helpers for braces
|
||||
, useBraces
|
||||
, dontUseBraces
|
||||
, canUseBraces
|
||||
-- * Special helpers for comment placement
|
||||
, trimSpanStream
|
||||
, nextEltSpan
|
||||
@ -75,6 +79,8 @@ data RC = RC
|
||||
-- ^ Span of enclosing element of AST
|
||||
, rcAnns :: Anns
|
||||
-- ^ Collection of annotations
|
||||
, rcCanUseBraces :: Bool
|
||||
-- ^ If the last expression in the layout can use braces
|
||||
}
|
||||
|
||||
-- | State context of 'R'.
|
||||
@ -117,6 +123,7 @@ runR debug (R m) sstream cstream anns =
|
||||
, rcDebug = debug
|
||||
, rcEnclosingSpans = []
|
||||
, rcAnns = anns
|
||||
, rcCanUseBraces = False
|
||||
}
|
||||
sc = SC
|
||||
{ scColumn = 0
|
||||
@ -344,6 +351,24 @@ getAnns
|
||||
-> R [AnnKeywordId]
|
||||
getAnns spn = lookupAnns spn <$> R (asks rcAnns)
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
-- Helpers for braces
|
||||
|
||||
-- | Make the inner computation use braces around single-line layouts.
|
||||
|
||||
useBraces :: R () -> R ()
|
||||
useBraces (R r) = R (local (\i -> i {rcCanUseBraces = True}) r)
|
||||
|
||||
-- | Make the inner computation omit braces around single-line layouts.
|
||||
|
||||
dontUseBraces :: R () -> R ()
|
||||
dontUseBraces (R r) = R (local (\i -> i {rcCanUseBraces = False}) r)
|
||||
|
||||
-- | Return 'True' if we can use braces in this context.
|
||||
|
||||
canUseBraces :: R Bool
|
||||
canUseBraces = R $ asks rcCanUseBraces
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
-- Debug helpers
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
{-# LANGUAGE LambdaCase #-}
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
{-# LANGUAGE PatternSynonyms #-}
|
||||
{-# LANGUAGE RecordWildCards #-}
|
||||
{-# LANGUAGE ViewPatterns #-}
|
||||
@ -10,7 +11,6 @@ module Ormolu.Printer.Meat.Declaration
|
||||
)
|
||||
where
|
||||
|
||||
import Control.Monad (forM_)
|
||||
import GHC
|
||||
import OccName (occNameFS)
|
||||
import Ormolu.Printer.Combinators
|
||||
@ -34,16 +34,17 @@ import Ormolu.Utils
|
||||
import RdrName (rdrNameOcc)
|
||||
|
||||
p_hsDecls :: FamilyStyle -> [LHsDecl GhcPs] -> R ()
|
||||
p_hsDecls style decls =
|
||||
forM_ (zip decls ((Just <$> drop 1 decls) ++ [Nothing])) $ \(d, md) ->
|
||||
case md of
|
||||
Nothing -> located d pDecl
|
||||
Just d' ->
|
||||
line $ if separatedDecls (unLoc d) (unLoc d')
|
||||
then line (located d pDecl)
|
||||
else located d pDecl
|
||||
p_hsDecls style decls = do
|
||||
sepSemi (\(x, r) -> located x pDecl >> r) (separated decls)
|
||||
where
|
||||
pDecl = p_hsDecl style
|
||||
pDecl = dontUseBraces . p_hsDecl style
|
||||
|
||||
separated [] = []
|
||||
separated [x] = [(x, return ())]
|
||||
separated (x:y:xs) =
|
||||
if separatedDecls (unLoc x) (unLoc y)
|
||||
then (x, breakpoint') : separated (y:xs)
|
||||
else (x, return ()) : separated (y:xs)
|
||||
|
||||
p_hsDecl :: FamilyStyle -> HsDecl GhcPs -> R ()
|
||||
p_hsDecl style = \case
|
||||
|
@ -66,8 +66,8 @@ p_classDecl ctx name tvars fixity fdeps csigs cdefs cats catdefs = do
|
||||
snd <$> sortBy (comparing fst) (sigs <> vals <> tyFams <> tyFamDefs)
|
||||
unless (null allDecls) $ do
|
||||
txt " where"
|
||||
newline -- Ensure line is added after where clause.
|
||||
newline -- Add newline before first declaration.
|
||||
breakpoint -- Ensure whitespace is added after where clause.
|
||||
breakpoint' -- Add newline before first declaration.
|
||||
inci (p_hsDecls Associated allDecls)
|
||||
|
||||
p_classContext :: LHsContext GhcPs -> R ()
|
||||
|
@ -52,7 +52,7 @@ p_dataDecl style name tpats fixity HsDataDefn {..} = do
|
||||
then do
|
||||
txt " where"
|
||||
breakpoint
|
||||
inci . sitcc $ sep newline (sitcc . located' p_conDecl) dd_cons
|
||||
inci $ sepSemi (located' p_conDecl) dd_cons
|
||||
else switchLayout (getLoc name : (getLoc <$> dd_cons)) $
|
||||
inci $ do
|
||||
breakpoint
|
||||
|
@ -67,11 +67,7 @@ p_clsInstDecl = \case
|
||||
ClsInstDecl {..} -> do
|
||||
txt "instance"
|
||||
case cid_poly_ty of
|
||||
HsIB {..} -> located hsib_body $ \x -> do
|
||||
breakpoint
|
||||
inci $ do
|
||||
match_overlap_mode cid_overlap_mode breakpoint
|
||||
p_hsType x
|
||||
HsIB {..} -> do
|
||||
-- GHC's AST does not necessarily store each kind of element in source
|
||||
-- location order. This happens because different declarations are stored in
|
||||
-- different lists. Consequently, to get all the declarations in proper
|
||||
@ -87,13 +83,19 @@ p_clsInstDecl = \case
|
||||
allDecls =
|
||||
snd <$>
|
||||
sortBy (comparing fst) (sigs <> vals <> tyFamInsts <> dataFamInsts)
|
||||
unless (null allDecls) $ do
|
||||
switchLayout [getLoc hsib_body] breakpoint
|
||||
located hsib_body $ \x -> do
|
||||
breakpoint
|
||||
inci $ do
|
||||
txt "where"
|
||||
newline -- Ensure line is added after where clause.
|
||||
newline -- Add newline before first declaration.
|
||||
p_hsDecls Associated allDecls
|
||||
match_overlap_mode cid_overlap_mode breakpoint
|
||||
p_hsType x
|
||||
unless (null allDecls) $ do
|
||||
breakpoint
|
||||
txt "where"
|
||||
unless (null allDecls) $ do
|
||||
inci $ do
|
||||
breakpoint -- Ensure whitespace is added after where clause.
|
||||
breakpoint' -- Add newline before first declaration
|
||||
dontUseBraces $ p_hsDecls Associated allDecls
|
||||
XHsImplicitBndrs NoExt -> notImplemented "XHsImplicitBndrs"
|
||||
XClsInstDecl NoExt -> notImplemented "XClsInstDecl"
|
||||
|
||||
|
@ -81,8 +81,15 @@ p_matchGroup'
|
||||
-> MatchGroupStyle
|
||||
-> MatchGroup GhcPs (Located body)
|
||||
-> R ()
|
||||
p_matchGroup' placer pretty style MG {..} =
|
||||
sep newline (located' p_Match) (unLoc mg_alts)
|
||||
p_matchGroup' placer pretty style MG {..} = do
|
||||
let ob = case style of
|
||||
Case -> id
|
||||
LambdaCase -> id
|
||||
_ -> dontUseBraces
|
||||
-- NOTE since we are forcing braces on 'sepSemi' based on 'ob', we have to
|
||||
-- restore the brace state inside the sepsemi.
|
||||
ub <- bool dontUseBraces useBraces <$> canUseBraces
|
||||
ob $ sepSemi (located' (ub . p_Match)) (unLoc mg_alts)
|
||||
where
|
||||
p_Match m@Match {..} =
|
||||
p_match'
|
||||
@ -179,7 +186,6 @@ p_match' placer pretty style isInfix strictness m_pats m_grhss = do
|
||||
stdCase
|
||||
LambdaCase -> stdCase
|
||||
return inci'
|
||||
|
||||
let
|
||||
-- Calculate position of end of patterns. This is useful when we decide
|
||||
-- about putting certain constructions in hanging positions.
|
||||
@ -192,49 +198,44 @@ p_match' placer pretty style isInfix strictness m_pats m_grhss = do
|
||||
Case -> True
|
||||
LambdaCase -> True
|
||||
_ -> False
|
||||
let GRHSs {..} = m_grhss
|
||||
hasGuards = withGuards grhssGRHSs
|
||||
unless (length grhssGRHSs > 1) $ do
|
||||
case style of
|
||||
Function _ | hasGuards -> return ()
|
||||
Function _ -> txt " ="
|
||||
PatternBind -> txt " ="
|
||||
s | isCase s && hasGuards -> return ()
|
||||
_ -> txt " ->"
|
||||
let grhssSpan = combineSrcSpans' $
|
||||
getGRHSSpan . unLoc <$> NE.fromList grhssGRHSs
|
||||
patGrhssSpan = maybe grhssSpan
|
||||
(combineSrcSpans grhssSpan . srcLocSpan) endOfPats
|
||||
placement =
|
||||
case endOfPats of
|
||||
Nothing -> blockPlacement placer grhssGRHSs
|
||||
Just spn ->
|
||||
if isOneLineSpan
|
||||
(mkSrcSpan spn (srcSpanStart grhssSpan))
|
||||
then blockPlacement placer grhssGRHSs
|
||||
else Normal
|
||||
p_body = do
|
||||
let groupStyle =
|
||||
if isCase style && hasGuards
|
||||
then RightArrow
|
||||
else EqualSign
|
||||
sep newline (located' (p_grhs' pretty groupStyle)) grhssGRHSs
|
||||
p_where = do
|
||||
let whereIsEmpty = GHC.isEmptyLocalBindsPR (unLoc grhssLocalBinds)
|
||||
unless (GHC.eqEmptyLocalBinds (unLoc grhssLocalBinds)) $ do
|
||||
breakpoint
|
||||
txt "where"
|
||||
unless whereIsEmpty breakpoint
|
||||
inci $ located grhssLocalBinds p_hsLocalBinds
|
||||
inci' $ do
|
||||
let GRHSs {..} = m_grhss
|
||||
hasGuards = withGuards grhssGRHSs
|
||||
unless (length grhssGRHSs > 1) $ do
|
||||
case style of
|
||||
Function _ | hasGuards -> return ()
|
||||
Function _ -> txt " ="
|
||||
PatternBind -> txt " ="
|
||||
s | isCase s && hasGuards -> return ()
|
||||
_ -> txt " ->"
|
||||
let grhssSpan = combineSrcSpans' $
|
||||
getGRHSSpan . unLoc <$> NE.fromList grhssGRHSs
|
||||
patGrhssSpan = maybe grhssSpan
|
||||
(combineSrcSpans grhssSpan . srcLocSpan) endOfPats
|
||||
placement =
|
||||
case endOfPats of
|
||||
Nothing -> blockPlacement placer grhssGRHSs
|
||||
Just spn ->
|
||||
if isOneLineSpan
|
||||
(mkSrcSpan spn (srcSpanStart grhssSpan))
|
||||
then blockPlacement placer grhssGRHSs
|
||||
else Normal
|
||||
inciLocalBinds = case placement of
|
||||
Normal -> id
|
||||
Hanging -> inci
|
||||
p_body = do
|
||||
let groupStyle =
|
||||
if isCase style && hasGuards
|
||||
then RightArrow
|
||||
else EqualSign
|
||||
sep newline (located' (p_grhs' pretty groupStyle)) grhssGRHSs
|
||||
let whereLocation = combineSrcSpans patGrhssSpan $ getLoc grhssLocalBinds
|
||||
whereIsEmpty = GHC.isEmptyLocalBindsPR (unLoc grhssLocalBinds)
|
||||
unless (GHC.eqEmptyLocalBinds (unLoc grhssLocalBinds))
|
||||
. inciLocalBinds
|
||||
. switchLayout [whereLocation] $ do
|
||||
if whereIsEmpty then newline else breakpoint
|
||||
txt "where"
|
||||
unless whereIsEmpty $ do
|
||||
breakpoint
|
||||
inci (located grhssLocalBinds p_hsLocalBinds)
|
||||
switchLayout [patGrhssSpan] $
|
||||
placeHanging placement p_body
|
||||
inci p_where
|
||||
|
||||
p_grhs :: GroupStyle -> GRHS GhcPs (LHsExpr GhcPs) -> R ()
|
||||
p_grhs = p_grhs' p_hsExpr
|
||||
@ -386,7 +387,7 @@ p_stmt' pretty = \case
|
||||
inci (p_hsExpr x)
|
||||
RecStmt {..} -> do
|
||||
txt "rec "
|
||||
sitcc $ sep newline (located' (p_stmt' pretty)) recS_stmts
|
||||
sitcc $ sepSemi (located' (p_stmt' pretty)) recS_stmts
|
||||
XStmtLR {} -> notImplemented "XStmtLR"
|
||||
|
||||
gatherStmt :: ExprLStmt GhcPs -> [[ExprLStmt GhcPs]]
|
||||
@ -411,7 +412,7 @@ p_hsLocalBinds = \case
|
||||
(Left <$> bagToList bag) ++ (Right <$> lsigs)
|
||||
p_item (Left x) = located x p_valDecl
|
||||
p_item (Right x) = located x p_sigDecl
|
||||
sitcc $ sep newline (sitcc . p_item) (sortOn ssStart items)
|
||||
sitcc $ sepSemi (useBraces . p_item) (sortOn ssStart items)
|
||||
HsValBinds NoExt _ -> notImplemented "HsValBinds"
|
||||
HsIPBinds NoExt _ -> notImplemented "HsIPBinds"
|
||||
EmptyLocalBinds NoExt -> return ()
|
||||
@ -468,18 +469,23 @@ p_hsExpr = \case
|
||||
txt "@"
|
||||
located (hswc_body a) p_hsType
|
||||
OpApp NoExt x op y -> do
|
||||
located x p_hsExpr
|
||||
-- NOTE If the end of the first argument and the beginning of the second
|
||||
-- argument are on the same line, and the second argument has a hanging
|
||||
-- form, use hanging placement.
|
||||
-- NOTE If the beginning of the first argument and the second argument
|
||||
-- are on the same line, and the second argument has a hanging form, use
|
||||
-- hanging placement.
|
||||
let placement =
|
||||
if isOneLineSpan
|
||||
(mkSrcSpan (srcSpanEnd (getLoc x)) (srcSpanStart (getLoc y)))
|
||||
(mkSrcSpan (srcSpanStart (getLoc x)) (srcSpanStart (getLoc y)))
|
||||
then exprPlacement (unLoc y)
|
||||
else Normal
|
||||
opWrapper = case unLoc op of
|
||||
EWildPat NoExt -> backticks
|
||||
_ -> id
|
||||
ub <- vlayout
|
||||
(return useBraces)
|
||||
(return $ case placement of
|
||||
Hanging -> useBraces
|
||||
Normal -> dontUseBraces)
|
||||
ub $ located x p_hsExpr
|
||||
placeHanging placement $ do
|
||||
located op (opWrapper . p_hsExpr)
|
||||
space
|
||||
@ -543,10 +549,9 @@ p_hsExpr = \case
|
||||
HsDo NoExt ctx es -> do
|
||||
let doBody header = do
|
||||
txt header
|
||||
if length (unLoc es) <= 1
|
||||
then breakpoint
|
||||
else newline
|
||||
inci $ located es (sep newline (located' (sitcc . p_stmt)))
|
||||
breakpoint
|
||||
ub <- vlayout (return useBraces) (return id)
|
||||
inci $ sepSemi (located' (ub . p_stmt)) (unLoc es)
|
||||
compBody = brackets $ located es $ \xs -> do
|
||||
let p_parBody = sitcc . sep
|
||||
(breakpoint >> txt "| ")
|
||||
@ -864,7 +869,7 @@ p_hsBracket = \case
|
||||
txt "|"
|
||||
breakpoint'
|
||||
inci $ do
|
||||
body
|
||||
dontUseBraces body
|
||||
breakpoint'
|
||||
txt "|]"
|
||||
|
||||
|
@ -57,14 +57,15 @@ p_hsModule pragmas (L moduleSpan HsModule {..}) = do
|
||||
when (hasImports || hasDecls) newline
|
||||
forM_ (sortImports hsmodImports) (located' p_hsmodImport)
|
||||
when (hasImports && hasDecls) newline
|
||||
p_hsDecls Free hsmodDecls
|
||||
trailingComments <- hasMoreComments
|
||||
when hasDecls $ do
|
||||
newlineModified <- isNewlineModified
|
||||
newline
|
||||
-- In this case we need to insert a newline between the comments
|
||||
-- output as a side effect of the previous newline and trailing
|
||||
-- comments to prevent them from merging.
|
||||
when (newlineModified && trailingComments) newline
|
||||
when (trailingComments && hasModuleHeader) newline
|
||||
spitRemainingComments
|
||||
switchLayout (map getLoc hsmodDecls) $ do
|
||||
p_hsDecls Free hsmodDecls
|
||||
trailingComments <- hasMoreComments
|
||||
when hasDecls $ do
|
||||
newlineModified <- isNewlineModified
|
||||
newline
|
||||
-- In this case we need to insert a newline between the comments
|
||||
-- output as a side effect of the previous newline and trailing
|
||||
-- comments to prevent them from merging.
|
||||
when (newlineModified && trailingComments) newline
|
||||
when (trailingComments && hasModuleHeader) newline
|
||||
spitRemainingComments
|
||||
|
Loading…
Reference in New Issue
Block a user