1
1
mirror of https://github.com/google/ormolu.git synced 2024-11-23 14:16:24 +03:00

Make function arguments look more consistent

This change modifies the ‘HsApp’ printer to handle all function parameters
at once instead of following the AST order.

This allows us to consistently put each function argument on separate lines.
Previously, when printing the function f a b c, the AST would look like (((f
a) b) c), which would cause inconsistencies regarding to newlines (imagine f
a\n b).

Otherwise I tried to preserve the same behaviour as the previous printer,
and added a few tests.

This only changes the ‘p_hsExpr’ function, rest of the changes are caused by
the formatting change.
This commit is contained in:
Utku Demir 2019-10-08 12:27:57 +13:00 committed by Mark Karpov
parent 1d3eeba701
commit 3abadaefa5
12 changed files with 89 additions and 26 deletions

View File

@ -10,7 +10,8 @@
{-# RULES
"map/map"
map f
map
f
(map g xs) =
map
(f . g)

View File

@ -1,6 +1,7 @@
{-# RULES
"map/map" [2]
map f
map
f
(map g xs) =
map
(f . g)
@ -9,7 +10,8 @@
{-# RULES
"map/map" [1] forall x y z.
map f
map
f
(map g xs) =
map
(f . g)

View File

@ -0,0 +1,17 @@
foo =
f1
p1
p2
p3
foo' =
f2
p1
p2
p3
foo'' =
f3
p1
p2
p3

View File

@ -0,0 +1,12 @@
foo =
f1
p1
p2 p3
foo' = f2 p1
p2
p3
foo'' =
f3 p1 p2
p3

View File

@ -25,3 +25,5 @@ f7 = foo \x -> y
f8 = foo \x ->
y
f9 = foo do { bar } baz

View File

@ -21,3 +21,5 @@ f7 = foo \x -> y
f8 = foo \x ->
y
f9 = foo do { bar } baz

View File

@ -14,6 +14,7 @@ bar =
baz :: StaticPtr Bool
baz =
static
( fun 1
( fun
1
2
)

View File

@ -51,7 +51,9 @@ instance Exception OrmoluException where
)
++ ["Please, consider reporting the bug."]
OrmoluNonIdempotentOutput loc left right ->
showParsingErr "Formatting is not idempotent:" loc
showParsingErr
"Formatting is not idempotent:"
loc
["before: " ++ show left, "after: " ++ show right]
++ "Please, consider reporting the bug.\n"

View File

@ -62,7 +62,8 @@ mkCommentStream extraComments pstate =
mapMaybe toRealSpan $
extraComments
++ mapMaybe (liftMaybe . fmap unAnnotationComment) (GHC.comment_q pstate)
++ concatMap (mapMaybe (liftMaybe . fmap unAnnotationComment) . snd)
++ concatMap
(mapMaybe (liftMaybe . fmap unAnnotationComment) . snd)
(GHC.annotations_comments pstate)
-- | Test whether a 'Comment' looks like a Haddock following a definition,

View File

@ -21,7 +21,8 @@ printModule ::
-- | Resulting rendition
Text
printModule ParseResult {..} =
runR (p_hsModule prExtensions prParsedSource)
runR
(p_hsModule prExtensions prParsedSource)
(mkSpanStream prParsedSource)
prCommentStream
prAnns

View File

@ -19,7 +19,7 @@ import Data.Bool (bool)
import Data.Char (isPunctuation, isSymbol)
import Data.Data hiding (Infix, Prefix)
import Data.List (intersperse, sortOn)
import Data.List.NonEmpty (NonEmpty ((:|)))
import Data.List.NonEmpty ((<|), NonEmpty ((:|)))
import qualified Data.List.NonEmpty as NE
import Data.Text (Text)
import qualified Data.Text as Text
@ -237,7 +237,8 @@ p_match' placer render style isInfix strictness m_pats m_grhss = do
combineSrcSpans' $
getGRHSSpan . unLoc <$> NE.fromList grhssGRHSs
patGrhssSpan =
maybe grhssSpan
maybe
grhssSpan
(combineSrcSpans grhssSpan . srcLocSpan)
endOfPats
placement =
@ -525,25 +526,44 @@ p_hsExpr' s = \case
breakpoint
inci (p_matchGroup LambdaCase mgroup)
HsApp NoExt f x -> do
-- We hang only the last function argument. In order to do this, we only
-- call 'placeHanging' on the topmost 'HsApp', and then use
-- 'p_withoutHanging' for the descendants.
let p_withoutHanging (HsApp NoExt f' x') = do
let -- In order to format function applications with multiple parameters
-- nicer, traverse the AST to gather the function and all the
-- parameters together.
gatherArgs f' knownArgs =
case f' of
L _ (HsApp _ _ _) -> located f' p_withoutHanging
_ -> located f' (p_hsExpr' s)
breakpoint
inci $ located x' p_hsExpr
p_withoutHanging e = p_hsExpr e
-- Only use the hanging placement if the function spans a single
L _ (HsApp _ l r) -> gatherArgs l (r <| knownArgs)
_ -> (f', knownArgs)
(func, args) = gatherArgs f (x :| [])
-- We need to handle the last argument specially if it is a
-- hanging construct, so separate it from the rest.
(initp, lastp) = (NE.init args, NE.last args)
initSpan = combineSrcSpans' $ getLoc f :| map getLoc initp
-- Hang the last argument only if the initial arguments spans one
-- line.
placement =
if isOneLineSpan (getLoc f)
then exprPlacement (unLoc x)
if isOneLineSpan initSpan
then exprPlacement (unLoc lastp)
else Normal
useBraces (located f p_withoutHanging)
placeHanging placement $
located x p_hsExpr
-- If the last argument is not hanging, just separate every argument as
-- usual. If it is hanging, print the initial arguments and hang the
-- last one. Also, use braces around the every argument except the last
-- one.
case placement of
Normal -> do
useBraces $ do
located func (p_hsExpr' s)
breakpoint
inci $ sep breakpoint (located' p_hsExpr) initp
inci $ do
unless (null initp) breakpoint
located lastp p_hsExpr
Hanging -> do
useBraces . switchLayout [initSpan] $ do
located func (p_hsExpr' s)
breakpoint
sep breakpoint (located' p_hsExpr) initp
placeHanging placement $
located lastp p_hsExpr
HsAppType a e -> do
located e p_hsExpr
breakpoint
@ -1089,7 +1109,8 @@ p_stringLit src =
zipPrevNext :: [a] -> [(Maybe a, a, Maybe a)]
zipPrevNext xs =
let z =
zip (zip (Nothing : map Just xs) xs)
zip
(zip (Nothing : map Just xs) xs)
(map Just (tail xs) ++ repeat Nothing)
in map (\((p, x), n) -> (p, x, n)) z
orig (_, x, _) = x

View File

@ -191,7 +191,8 @@ p_conDeclField :: ConDeclField GhcPs -> R ()
p_conDeclField ConDeclField {..} = do
mapM_ (p_hsDocString Pipe True) cd_fld_doc
sitcc $
sep (comma >> breakpoint)
sep
(comma >> breakpoint)
(located' (p_rdrName . rdrNameFieldOcc))
cd_fld_names
space