module Language.Haskell.Brittany.Internal.Layouters.IE
( layoutIE
, layoutLLIEs
, layoutAnnAndSepLLIEs
)
where
#include "prelude.inc"
import Language.Haskell.Brittany.Internal.Types
import Language.Haskell.Brittany.Internal.LayouterBasics
import Language.Haskell.Brittany.Internal.Config.Types
import GHC ( unLoc
, runGhc
, GenLocated(L)
, moduleNameString
, AnnKeywordId(..)
, Located
)
import HsSyn
import Name
import HsImpExp
import FieldLabel
import qualified FastString
import BasicTypes
import Language.Haskell.Brittany.Internal.Utils
#if MIN_VERSION_ghc(8,2,0)
prepareName :: LIEWrappedName name -> Located name
prepareName = ieLWrappedName
#else
prepareName :: Located name -> Located name
prepareName = id
#endif
layoutIE :: ToBriDoc IE
layoutIE lie@(L _ ie) = docWrapNode lie $ case ie of
#if MIN_VERSION_ghc(8,6,0)
IEVar _ x -> layoutWrapped lie x
#else
IEVar x -> layoutWrapped lie x
#endif
#if MIN_VERSION_ghc(8,6,0)
IEThingAbs _ x -> layoutWrapped lie x
#else
IEThingAbs x -> layoutWrapped lie x
#endif
#if MIN_VERSION_ghc(8,6,0)
IEThingAll _ x -> docSeq [layoutWrapped lie x, docLit $ Text.pack "(..)"]
#else
IEThingAll x -> docSeq [layoutWrapped lie x, docLit $ Text.pack "(..)"]
#endif
#if MIN_VERSION_ghc(8,6,0)
IEThingWith _ x (IEWildcard _) _ _ ->
#else
IEThingWith x (IEWildcard _) _ _ ->
#endif
docSeq [layoutWrapped lie x, docLit $ Text.pack "(..)"]
#if MIN_VERSION_ghc(8,6,0)
IEThingWith _ x _ ns _ -> do
#else
IEThingWith x _ ns _ -> do
#endif
hasComments <- hasAnyCommentsBelow lie
runFilteredAlternative $ do
addAlternativeCond (not hasComments)
$ docSeq
$ [layoutWrapped lie x, docLit $ Text.pack "("]
++ intersperse docCommaSep (map nameDoc ns)
++ [docParenR]
addAlternative $ docAddBaseY BrIndentRegular $ docPar
(layoutWrapped lie x)
(layoutItems (splitFirstLast ns))
where
nameDoc = (docLit =<<) . lrdrNameToTextAnn . prepareName
layoutItem n = docSeq [docCommaSep, docWrapNode n $ nameDoc n]
layoutItems FirstLastEmpty = docSetBaseY $ docLines
[docSeq [docParenLSep, docWrapNodeRest lie docEmpty], docParenR]
layoutItems (FirstLastSingleton n) = docSetBaseY $ docLines
[docSeq [docParenLSep, docWrapNodeRest lie $ nameDoc n], docParenR]
layoutItems (FirstLast n1 nMs nN) =
docSetBaseY
$ docLines
$ [docSeq [docParenLSep, docWrapNode n1 $ nameDoc n1]]
++ map layoutItem nMs
++ [docSeq [docCommaSep, docWrapNodeRest lie $ nameDoc nN], docParenR]
#if MIN_VERSION_ghc(8,6,0)
IEModuleContents _ n -> docSeq
#else
IEModuleContents n -> docSeq
#endif
[ docLit $ Text.pack "module"
, docSeparator
, docLit . Text.pack . moduleNameString $ unLoc n
]
_ -> docEmpty
where
#if MIN_VERSION_ghc(8,2,0) /* ghc-8.2, 8.4, .. */
layoutWrapped _ = \case
L _ (IEName n) -> docLit =<< lrdrNameToTextAnn n
L _ (IEPattern n) -> do
name <- lrdrNameToTextAnn n
docLit $ Text.pack "pattern " <> name
L _ (IEType n) -> do
name <- lrdrNameToTextAnn n
docLit $ Text.pack "type " <> name
#else /* ghc-8.0 */
layoutWrapped outer n = do
name <- lrdrNameToTextAnn n
hasType <- hasAnnKeyword n AnnType
hasPattern <- hasAnnKeyword outer AnnPattern
docLit $ if
| hasType -> Text.pack "type (" <> name <> Text.pack ")"
| hasPattern -> Text.pack "pattern " <> name
| otherwise -> name
#endif
layoutAnnAndSepLLIEs
:: Located [LIE GhcPs] -> ToBriDocM [ToBriDocM BriDocNumbered]
layoutAnnAndSepLLIEs llies@(L _ lies) = do
let makeIENode ie = docSeq [docCommaSep, ie]
let ieDocs = layoutIE <$> lies
ieCommaDocs <-
docWrapNodeRest llies $ sequence $ case splitFirstLast ieDocs of
FirstLastEmpty -> []
FirstLastSingleton ie -> [ie]
FirstLast ie1 ieMs ieN ->
[ie1] ++ map makeIENode ieMs ++ [makeIENode ieN]
pure $ fmap pure ieCommaDocs
layoutLLIEs :: Bool -> Located [LIE GhcPs] -> ToBriDocM BriDocNumbered
layoutLLIEs enableSingleline llies = do
ieDs <- layoutAnnAndSepLLIEs llies
hasComments <- hasAnyCommentsBelow llies
runFilteredAlternative $
case ieDs of
[] -> do
addAlternativeCond (not hasComments) $
docLit $ Text.pack "()"
addAlternativeCond hasComments $
docPar (docSeq [docParenLSep, docWrapNodeRest llies docEmpty])
docParenR
(ieDsH:ieDsT) -> do
addAlternativeCond (not hasComments && enableSingleline)
$ docSeq
$ [docLit (Text.pack "(")]
++ (docForceSingleline <$> ieDs)
++ [docParenR]
addAlternative
$ docPar (docSetBaseY $ docSeq [docParenLSep, ieDsH])
$ docLines
$ ieDsT
++ [docParenR]