@@ -19,7 +19,7 @@ import Data.Bool (bool)
1919import Data.Char (isPunctuation, isSymbol)
2020import Data.Data hiding (Infix, Prefix)
2121import Data.List (intersperse, sortOn)
22−import Data.List.NonEmpty (NonEmpty ((:|)))
22+import Data.List.NonEmpty ((<|), NonEmpty ((:|)))
2323import qualified Data.List.NonEmpty as NE
2424import Data.Text (Text)
2525import qualified Data.Text as Text
@@ -237,7 +237,8 @@ p_match' placer render style isInfix strictness m_pats m_grhss = do
237237 combineSrcSpans' $
238238 getGRHSSpan . unLoc <$> NE.fromList grhssGRHSs
239239 patGrhssSpan =
240− maybe grhssSpan
240+ maybe
241+ grhssSpan
241242 (combineSrcSpans grhssSpan . srcLocSpan)
242243 endOfPats
243244 placement =
@@ -525,25 +526,44 @@ p_hsExpr' s = \case
525526 breakpoint
526527 inci (p_matchGroup LambdaCase mgroup)
527528 HsApp NoExt f x -> do
528− -- We hang only the last function argument. In order to do this, we only
529− -- call 'placeHanging' on the topmost 'HsApp', and then use
530− -- 'p_withoutHanging' for the descendants.
531− let p_withoutHanging (HsApp NoExt f' x') = do
529+ let -- In order to format function applications with multiple parameters
530+ -- nicer, traverse the AST to gather the function and all the
531+ -- parameters together.
532+ gatherArgs f' knownArgs =
532533 case f' of
533− L _ (HsApp _ _ _) -> located f' p_withoutHanging
534− _ -> located f' (p_hsExpr' s)
535− breakpoint
536− inci $ located x' p_hsExpr
537− p_withoutHanging e = p_hsExpr e
538− -- Only use the hanging placement if the function spans a single
534+ L _ (HsApp _ l r) -> gatherArgs l (r <| knownArgs)
535+ _ -> (f', knownArgs)
536+ (func, args) = gatherArgs f (x :| [])
537+ -- We need to handle the last argument specially if it is a
538+ -- hanging construct, so separate it from the rest.
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
539542 -- line.
540543 placement =
541− if isOneLineSpan (getLoc f)
542− then exprPlacement (unLoc x)
544+ if isOneLineSpan initSpan
545+ then exprPlacement (unLoc lastp)
543546 else Normal
544− useBraces (located f p_withoutHanging)
545− placeHanging placement $
546− located x p_hsExpr
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
550+ -- one.
551+ case placement of
552+ Normal -> do
553+ useBraces $ do
554+ located func (p_hsExpr' s)
555+ breakpoint
556+ inci $ sep breakpoint (located' p_hsExpr) initp
557+ inci $ do
558+ unless (null initp) breakpoint
559+ located lastp p_hsExpr
560+ Hanging -> do
561+ useBraces . switchLayout [initSpan] $ do
562+ located func (p_hsExpr' s)
563+ breakpoint
564+ sep breakpoint (located' p_hsExpr) initp
565+ placeHanging placement $
566+ located lastp p_hsExpr
547567 HsAppType a e -> do
548568 located e p_hsExpr
549569 breakpoint
@@ -1089,7 +1109,8 @@ p_stringLit src =
10891109 zipPrevNext :: [a] -> [(Maybe a, a, Maybe a)]
10901110 zipPrevNext xs =
10911111 let z =
1092− zip (zip (Nothing : map Just xs) xs)
1112+ zip
1113+ (zip (Nothing : map Just xs) xs)
10931114 (map Just (tail xs) ++ repeat Nothing)
10941115 in map (\((p, x), n) -> (p, x, n)) z
10951116 orig (_, x, _) = x