module Language.Haskell.Brittany.Internal.Layouters.Module (layoutModule) where

#include "prelude.inc"

import           Language.Haskell.Brittany.Internal.Types
import           Language.Haskell.Brittany.Internal.LayouterBasics
import           Language.Haskell.Brittany.Internal.Layouters.IE
import           Language.Haskell.Brittany.Internal.Layouters.Import
import           Language.Haskell.Brittany.Internal.Config.Types

import GHC (unLoc, runGhc, GenLocated(L), moduleNameString, AnnKeywordId(..))
#if MIN_VERSION_ghc(8,10,1)   /* ghc-8.10.1 */
import           GHC.Hs
import           GHC.Hs.ImpExp
#else
import           HsSyn
import           HsImpExp
#endif
import           Name
import           FieldLabel
import qualified FastString
import           BasicTypes
import           Language.Haskell.GHC.ExactPrint as ExactPrint
import           Language.Haskell.GHC.ExactPrint.Types as ExactPrint.Types

import           Language.Haskell.Brittany.Internal.Utils



layoutModule :: ToBriDoc HsModule
layoutModule :: ToBriDoc HsModule
layoutModule lmod :: Located (HsModule GhcPs)
lmod@(L SrcSpan
_ HsModule GhcPs
mod') = case HsModule GhcPs
mod' of
    -- Implicit module Main
  HsModule Maybe (Located ModuleName)
Nothing  Maybe (Located [LIE GhcPs])
_   [LImportDecl GhcPs]
imports [LHsDecl GhcPs]
_ Maybe (Located WarningTxt)
_ Maybe LHsDocString
_ -> [ToBriDocM BriDocNumbered] -> ToBriDocM BriDocNumbered
docLines ([ToBriDocM BriDocNumbered] -> ToBriDocM BriDocNumbered)
-> [ToBriDocM BriDocNumbered] -> ToBriDocM BriDocNumbered
forall a b. (a -> b) -> a -> b
$ (LImportDecl GhcPs -> ToBriDocM BriDocNumbered)
-> [LImportDecl GhcPs] -> [ToBriDocM BriDocNumbered]
forall a b. (a -> b) -> [a] -> [b]
map LImportDecl GhcPs -> ToBriDocM BriDocNumbered
layoutImport [LImportDecl GhcPs]
imports
  HsModule (Just Located ModuleName
n) Maybe (Located [LIE GhcPs])
les [LImportDecl GhcPs]
imports [LHsDecl GhcPs]
_ Maybe (Located WarningTxt)
_ Maybe LHsDocString
_ -> do
    let tn :: Text
tn = String -> Text
Text.pack (String -> Text) -> String -> Text
forall a b. (a -> b) -> a -> b
$ ModuleName -> String
moduleNameString (ModuleName -> String) -> ModuleName -> String
forall a b. (a -> b) -> a -> b
$ Located ModuleName -> SrcSpanLess (Located ModuleName)
forall a. HasSrcSpan a => a -> SrcSpanLess a
unLoc Located ModuleName
n
    Bool
allowSingleLineExportList <- MultiRWST
  '[Config, Anns]
  '[[BrittanyError], Seq String]
  '[NodeAllocIndex]
  Identity
  Config
forall a (m :: * -> *). MonadMultiReader a m => m a
mAsk
      MultiRWST
  '[Config, Anns]
  '[[BrittanyError], Seq String]
  '[NodeAllocIndex]
  Identity
  Config
-> (Config -> Bool)
-> MultiRWST
     '[Config, Anns]
     '[[BrittanyError], Seq String]
     '[NodeAllocIndex]
     Identity
     Bool
forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&> Config -> CLayoutConfig Identity
forall (f :: * -> *). CConfig f -> CLayoutConfig f
_conf_layout
      (Config -> CLayoutConfig Identity)
-> (CLayoutConfig Identity -> Identity (Last Bool))
-> Config
-> Identity (Last Bool)
forall a b c. (a -> b) -> (b -> c) -> a -> c
.>  CLayoutConfig Identity -> Identity (Last Bool)
forall (f :: * -> *). CLayoutConfig f -> f (Last Bool)
_lconfig_allowSingleLineExportList
      (Config -> Identity (Last Bool))
-> (Identity (Last Bool) -> Bool) -> Config -> Bool
forall a b c. (a -> b) -> (b -> c) -> a -> c
.>  Identity (Last Bool) -> Bool
forall a b. Coercible a b => Identity a -> b
confUnpack
    -- the config should not prevent single-line layout when there is no
    -- export list
    let allowSingleLine :: Bool
allowSingleLine = Bool
allowSingleLineExportList Bool -> Bool -> Bool
|| Maybe (Located [LIE GhcPs]) -> Bool
forall a. Maybe a -> Bool
Data.Maybe.isNothing Maybe (Located [LIE GhcPs])
les
    [ToBriDocM BriDocNumbered] -> ToBriDocM BriDocNumbered
docLines
      ([ToBriDocM BriDocNumbered] -> ToBriDocM BriDocNumbered)
-> [ToBriDocM BriDocNumbered] -> ToBriDocM BriDocNumbered
forall a b. (a -> b) -> a -> b
$ [ToBriDocM BriDocNumbered] -> ToBriDocM BriDocNumbered
docSeq
          [ Located (HsModule GhcPs)
-> Maybe AnnKeywordId
-> ToBriDocM BriDocNumbered
-> ToBriDocM BriDocNumbered
forall ast.
Data ast =>
Located ast
-> Maybe AnnKeywordId
-> ToBriDocM BriDocNumbered
-> ToBriDocM BriDocNumbered
docNodeAnnKW Located (HsModule GhcPs)
lmod Maybe AnnKeywordId
forall a. Maybe a
Nothing ToBriDocM BriDocNumbered
docEmpty
             -- A pseudo node that serves merely to force documentation
             -- before the node
          , Located (HsModule GhcPs)
-> AnnKeywordId
-> Bool
-> ToBriDocM BriDocNumbered
-> ToBriDocM BriDocNumbered
forall ast.
Data ast =>
Located ast
-> AnnKeywordId
-> Bool
-> ToBriDocM BriDocNumbered
-> ToBriDocM BriDocNumbered
docNodeMoveToKWDP Located (HsModule GhcPs)
lmod AnnKeywordId
AnnModule Bool
True (ToBriDocM BriDocNumbered -> ToBriDocM BriDocNumbered)
-> ToBriDocM BriDocNumbered -> ToBriDocM BriDocNumbered
forall a b. (a -> b) -> a -> b
$ CollectAltM () -> ToBriDocM BriDocNumbered
runFilteredAlternative (CollectAltM () -> ToBriDocM BriDocNumbered)
-> CollectAltM () -> ToBriDocM BriDocNumbered
forall a b. (a -> b) -> a -> b
$ do
            Bool -> ToBriDocM BriDocNumbered -> CollectAltM ()
addAlternativeCond Bool
allowSingleLine (ToBriDocM BriDocNumbered -> CollectAltM ())
-> ToBriDocM BriDocNumbered -> CollectAltM ()
forall a b. (a -> b) -> a -> b
$
              ToBriDocM BriDocNumbered -> ToBriDocM BriDocNumbered
docForceSingleline
                (ToBriDocM BriDocNumbered -> ToBriDocM BriDocNumbered)
-> ToBriDocM BriDocNumbered -> ToBriDocM BriDocNumbered
forall a b. (a -> b) -> a -> b
$ [ToBriDocM BriDocNumbered] -> ToBriDocM BriDocNumbered
docSeq
                [ ToBriDocM BriDocNumbered -> ToBriDocM BriDocNumbered
appSep (ToBriDocM BriDocNumbered -> ToBriDocM BriDocNumbered)
-> ToBriDocM BriDocNumbered -> ToBriDocM BriDocNumbered
forall a b. (a -> b) -> a -> b
$ Text -> ToBriDocM BriDocNumbered
docLit (Text -> ToBriDocM BriDocNumbered)
-> Text -> ToBriDocM BriDocNumbered
forall a b. (a -> b) -> a -> b
$ String -> Text
Text.pack String
"module"
                , ToBriDocM BriDocNumbered -> ToBriDocM BriDocNumbered
appSep (ToBriDocM BriDocNumbered -> ToBriDocM BriDocNumbered)
-> ToBriDocM BriDocNumbered -> ToBriDocM BriDocNumbered
forall a b. (a -> b) -> a -> b
$ Text -> ToBriDocM BriDocNumbered
docLit Text
tn
                , Located (HsModule GhcPs)
-> ToBriDocM BriDocNumbered -> ToBriDocM BriDocNumbered
forall a ast. (DocWrapable a, Data ast) => Located ast -> a -> a
docWrapNode Located (HsModule GhcPs)
lmod (ToBriDocM BriDocNumbered -> ToBriDocM BriDocNumbered)
-> ToBriDocM BriDocNumbered -> ToBriDocM BriDocNumbered
forall a b. (a -> b) -> a -> b
$ ToBriDocM BriDocNumbered -> ToBriDocM BriDocNumbered
appSep (ToBriDocM BriDocNumbered -> ToBriDocM BriDocNumbered)
-> ToBriDocM BriDocNumbered -> ToBriDocM BriDocNumbered
forall a b. (a -> b) -> a -> b
$ case Maybe (Located [LIE GhcPs])
les of
                  Maybe (Located [LIE GhcPs])
Nothing -> ToBriDocM BriDocNumbered
docEmpty
                  Just Located [LIE GhcPs]
x  -> Bool -> Located [LIE GhcPs] -> ToBriDocM BriDocNumbered
layoutLLIEs Bool
True Located [LIE GhcPs]
x
                , ToBriDocM BriDocNumbered
docSeparator
                , Text -> ToBriDocM BriDocNumbered
docLit (Text -> ToBriDocM BriDocNumbered)
-> Text -> ToBriDocM BriDocNumbered
forall a b. (a -> b) -> a -> b
$ String -> Text
Text.pack String
"where"
                ]
            ToBriDocM BriDocNumbered -> CollectAltM ()
addAlternative
              (ToBriDocM BriDocNumbered -> CollectAltM ())
-> ToBriDocM BriDocNumbered -> CollectAltM ()
forall a b. (a -> b) -> a -> b
$ [ToBriDocM BriDocNumbered] -> ToBriDocM BriDocNumbered
docLines
              [ BrIndent -> ToBriDocM BriDocNumbered -> ToBriDocM BriDocNumbered
docAddBaseY BrIndent
BrIndentRegular (ToBriDocM BriDocNumbered -> ToBriDocM BriDocNumbered)
-> ToBriDocM BriDocNumbered -> ToBriDocM BriDocNumbered
forall a b. (a -> b) -> a -> b
$ ToBriDocM BriDocNumbered
-> ToBriDocM BriDocNumbered -> ToBriDocM BriDocNumbered
docPar
                ([ToBriDocM BriDocNumbered] -> ToBriDocM BriDocNumbered
docSeq [ToBriDocM BriDocNumbered -> ToBriDocM BriDocNumbered
appSep (ToBriDocM BriDocNumbered -> ToBriDocM BriDocNumbered)
-> ToBriDocM BriDocNumbered -> ToBriDocM BriDocNumbered
forall a b. (a -> b) -> a -> b
$ Text -> ToBriDocM BriDocNumbered
docLit (Text -> ToBriDocM BriDocNumbered)
-> Text -> ToBriDocM BriDocNumbered
forall a b. (a -> b) -> a -> b
$ String -> Text
Text.pack String
"module", Text -> ToBriDocM BriDocNumbered
docLit Text
tn]
                )
                ([ToBriDocM BriDocNumbered] -> ToBriDocM BriDocNumbered
docSeq [ Located (HsModule GhcPs)
-> ToBriDocM BriDocNumbered -> ToBriDocM BriDocNumbered
forall a ast. (DocWrapable a, Data ast) => Located ast -> a -> a
docWrapNode Located (HsModule GhcPs)
lmod (ToBriDocM BriDocNumbered -> ToBriDocM BriDocNumbered)
-> ToBriDocM BriDocNumbered -> ToBriDocM BriDocNumbered
forall a b. (a -> b) -> a -> b
$ case Maybe (Located [LIE GhcPs])
les of
                            Maybe (Located [LIE GhcPs])
Nothing -> ToBriDocM BriDocNumbered
docEmpty
                            Just Located [LIE GhcPs]
x  -> Bool -> Located [LIE GhcPs] -> ToBriDocM BriDocNumbered
layoutLLIEs Bool
False Located [LIE GhcPs]
x
                        , ToBriDocM BriDocNumbered
docSeparator
                        , Text -> ToBriDocM BriDocNumbered
docLit (Text -> ToBriDocM BriDocNumbered)
-> Text -> ToBriDocM BriDocNumbered
forall a b. (a -> b) -> a -> b
$ String -> Text
Text.pack String
"where"
                        ]
                )
              ]
          ]
      ToBriDocM BriDocNumbered
-> [ToBriDocM BriDocNumbered] -> [ToBriDocM BriDocNumbered]
forall a. a -> [a] -> [a]
: (LImportDecl GhcPs -> ToBriDocM BriDocNumbered)
-> [LImportDecl GhcPs] -> [ToBriDocM BriDocNumbered]
forall a b. (a -> b) -> [a] -> [b]
map LImportDecl GhcPs -> ToBriDocM BriDocNumbered
layoutImport [LImportDecl GhcPs]
imports