@@ -19,7 +19,7 @@ import Data.Bool (bool)
19import Data.Char (isPunctuation, isSymbol)
19import Data.Char (isPunctuation, isSymbol)
20import Data.Data hiding (Infix, Prefix)
20import Data.Data hiding (Infix, Prefix)
21import Data.List (intersperse, sortOn)
21import Data.List (intersperse, sortOn)
22−import Data.List.NonEmpty (NonEmpty ((:|)))
22+import Data.List.NonEmpty ((<|), NonEmpty ((:|)))
23import qualified Data.List.NonEmpty as NE
23import qualified Data.List.NonEmpty as NE
24import Data.Text (Text)
24import Data.Text (Text)
25import qualified Data.Text as Text
25import qualified Data.Text as Text
@@ -237,7 +237,8 @@ p_match' placer render style isInfix strictness m_pats m_grhss = do
237 combineSrcSpans' $
237 combineSrcSpans' $
238 getGRHSSpan . unLoc <$> NE.fromList grhssGRHSs
238 getGRHSSpan . unLoc <$> NE.fromList grhssGRHSs
239 patGrhssSpan =
239 patGrhssSpan =
240− maybe grhssSpan
241+ grhssSpan
241 (combineSrcSpans grhssSpan . srcLocSpan)
242 (combineSrcSpans grhssSpan . srcLocSpan)
242 endOfPats
243 endOfPats
243 placement =
244 placement =
@@ -525,25 +526,44 @@ p_hsExpr' s = \case
525 breakpoint
526 breakpoint
526 inci (p_matchGroup LambdaCase mgroup)
527 inci (p_matchGroup LambdaCase mgroup)
527 HsApp NoExt f x -> do
528 HsApp NoExt f x -> do
528− -- We hang only the last function argument. In order to do this, we only
529+ let -- In order to format function applications with multiple parameters
529− -- call 'placeHanging' on the topmost 'HsApp', and then use
530+ -- nicer, traverse the AST to gather the function and all the
530− -- 'p_withoutHanging' for the descendants.
531+ -- parameters together.
531− let p_withoutHanging (HsApp NoExt f' x') = do
532+ gatherArgs f' knownArgs =
532 case f' of
533 case f' of
533− L _ (HsApp _ _ _) -> located f' p_withoutHanging
534+ L _ (HsApp _ l r) -> gatherArgs l (r <| knownArgs)
534− _ -> located f' (p_hsExpr' s)
535+ _ -> (f', knownArgs)
535− breakpoint
536+ (func, args) = gatherArgs f (x :| [])
536− inci $ located x' p_hsExpr
537+ -- We need to handle the last argument specially if it is a
537− p_withoutHanging e = p_hsExpr e
538+ -- hanging construct, so separate it from the rest.
538− -- Only use the hanging placement if the function spans a single
539+ (initp, lastp) = (NE.init args, NE.last args)
540+ initSpan = combineSrcSpans' $ getLoc f :| map getLoc initp
541+ -- Hang the last argument only if the initial arguments spans one
540 placement =
543 placement =
541− if isOneLineSpan (getLoc f)
544+ if isOneLineSpan initSpan
542− then exprPlacement (unLoc x)
545+ then exprPlacement (unLoc lastp)
543 else Normal
546 else Normal
547+ -- If the last argument is not hanging, just separate every argument as
548+ -- usual. If it is hanging, print the initial arguments and hang the
549+ -- last one. Also, use braces around the every argument except the last
544− useBraces (located f p_withoutHanging)
553+ useBraces $ do
554+ located func (p_hsExpr' s)
556+ inci $ sep breakpoint (located' p_hsExpr) initp
558+ unless (null initp) breakpoint
559+ located lastp p_hsExpr
561+ useBraces . switchLayout [initSpan] $ do
562+ located func (p_hsExpr' s)
564+ sep breakpoint (located' p_hsExpr) initp
545− placeHanging placement $
565+ placeHanging placement $
546− located x p_hsExpr
566+ located lastp p_hsExpr
547 HsAppType a e -> do
567 HsAppType a e -> do
548 located e p_hsExpr
568 located e p_hsExpr
549 breakpoint
569 breakpoint
@@ -1089,7 +1109,8 @@ p_stringLit src =
1089 zipPrevNext :: [a] -> [(Maybe a, a, Maybe a)]
1109 zipPrevNext :: [a] -> [(Maybe a, a, Maybe a)]
1090 zipPrevNext xs =
1110 zipPrevNext xs =
1092− zip (zip (Nothing : map Just xs) xs)
1113+ (zip (Nothing : map Just xs) xs)
1093 (map Just (tail xs) ++ repeat Nothing)
1114 (map Just (tail xs) ++ repeat Nothing)
1094 in map (\((p, x), n) -> (p, x, n)) z
1115 in map (\((p, x), n) -> (p, x, n)) z
1095 orig (_, x, _) = x
1116 orig (_, x, _) = x