    {-# OPTIONS_GHC -cpp #-}
    {-# LANGUAGE RankNTypes #-}
    {-# LANGUAGE OverloadedStrings #-}
    {-# LANGUAGE GADTs #-}
    {-# LANGUAGE NamedFieldPuns #-}
    {-# LANGUAGE GeneralizedNewtypeDeriving #-}
    {-# LANGUAGE FlexibleContexts #-}

    -- | All types.

    module HIndent.Types
      (Printer(..)
      ,PrintState(..)
      ,Config(..)
      ,readExtension
      ,defaultConfig
      ,NodeInfo(..)
      ,NodeComment(..)
      ,SomeComment(..)
      ) where

    import           Control.Applicative
    import           Control.Monad
    import           Control.Monad.State.Strict (MonadState(..),StateT)
    import           Control.Monad.Trans.Maybe
    import           Data.ByteString.Builder
    import           Data.Functor.Identity
    import           Data.Int (Int64)
    import           Data.Maybe
    import           Data.Yaml (FromJSON(..))
    import qualified Data.Yaml as Y
    import           Language.Haskell.Exts hiding (Style, prettyPrint, Pretty, style, parse)

    -- | A pretty printing monad.
    newtype Printer a =
      Printer {forall a. Printer a -> StateT PrintState (MaybeT Identity) a
    runPrinter :: StateT PrintState (MaybeT Identity) a}
      deriving (Functor Printer
    Functor Printer
    -> (forall a. a -> Printer a)
    -> (forall a b. Printer (a -> b) -> Printer a -> Printer b)
    -> (forall a b c.
        (a -> b -> c) -> Printer a -> Printer b -> Printer c)
    -> (forall a b. Printer a -> Printer b -> Printer b)
    -> (forall a b. Printer a -> Printer b -> Printer a)
    -> Applicative Printer
    forall a. a -> Printer a
    forall a b. Printer a -> Printer b -> Printer a
    forall a b. Printer a -> Printer b -> Printer b
    forall a b. Printer (a -> b) -> Printer a -> Printer b
    forall a b c. (a -> b -> c) -> Printer a -> Printer b -> Printer c
    forall (f :: * -> *).
    Functor f
    -> (forall a. a -> f a)
    -> (forall a b. f (a -> b) -> f a -> f b)
    -> (forall a b c. (a -> b -> c) -> f a -> f b -> f c)
    -> (forall a b. f a -> f b -> f b)
    -> (forall a b. f a -> f b -> f a)
    -> Applicative f
    $cpure :: forall a. a -> Printer a
    pure :: forall a. a -> Printer a
    $c<*> :: forall a b. Printer (a -> b) -> Printer a -> Printer b
    <*> :: forall a b. Printer (a -> b) -> Printer a -> Printer b
    $cliftA2 :: forall a b c. (a -> b -> c) -> Printer a -> Printer b -> Printer c
    liftA2 :: forall a b c. (a -> b -> c) -> Printer a -> Printer b -> Printer c
    $c*> :: forall a b. Printer a -> Printer b -> Printer b
    *> :: forall a b. Printer a -> Printer b -> Printer b
    $c<* :: forall a b. Printer a -> Printer b -> Printer a
    <* :: forall a b. Printer a -> Printer b -> Printer a
    Applicative,Applicative Printer
    Applicative Printer
    -> (forall a b. Printer a -> (a -> Printer b) -> Printer b)
    -> (forall a b. Printer a -> Printer b -> Printer b)
    -> (forall a. a -> Printer a)
    -> Monad Printer
    forall a. a -> Printer a
    forall a b. Printer a -> Printer b -> Printer b
    forall a b. Printer a -> (a -> Printer b) -> Printer b
    forall (m :: * -> *).
    Applicative m
    -> (forall a b. m a -> (a -> m b) -> m b)
    -> (forall a b. m a -> m b -> m b)
    -> (forall a. a -> m a)
    -> Monad m
    $c>>= :: forall a b. Printer a -> (a -> Printer b) -> Printer b
    >>= :: forall a b. Printer a -> (a -> Printer b) -> Printer b
    $c>> :: forall a b. Printer a -> Printer b -> Printer b
    >> :: forall a b. Printer a -> Printer b -> Printer b
    $creturn :: forall a. a -> Printer a
    return :: forall a. a -> Printer a
    Monad,(forall a b. (a -> b) -> Printer a -> Printer b)
    -> (forall a b. a -> Printer b -> Printer a) -> Functor Printer
    forall a b. a -> Printer b -> Printer a
    forall a b. (a -> b) -> Printer a -> Printer b
    forall (f :: * -> *).
    (forall a b. (a -> b) -> f a -> f b)
    -> (forall a b. a -> f b -> f a) -> Functor f
    $cfmap :: forall a b. (a -> b) -> Printer a -> Printer b
    fmap :: forall a b. (a -> b) -> Printer a -> Printer b
    $c<$ :: forall a b. a -> Printer b -> Printer a
    <$ :: forall a b. a -> Printer b -> Printer a
    Functor,MonadState PrintState,Monad Printer
    Alternative Printer
    Alternative Printer
    -> Monad Printer
    -> (forall a. Printer a)
    -> (forall a. Printer a -> Printer a -> Printer a)
    -> MonadPlus Printer
    forall a. Printer a
    forall a. Printer a -> Printer a -> Printer a
    forall (m :: * -> *).
    Alternative m
    -> Monad m
    -> (forall a. m a)
    -> (forall a. m a -> m a -> m a)
    -> MonadPlus m
    $cmzero :: forall a. Printer a
    mzero :: forall a. Printer a
    $cmplus :: forall a. Printer a -> Printer a -> Printer a
    mplus :: forall a. Printer a -> Printer a -> Printer a
    MonadPlus,Applicative Printer
    Applicative Printer
    -> (forall a. Printer a)
    -> (forall a. Printer a -> Printer a -> Printer a)
    -> (forall a. Printer a -> Printer [a])
    -> (forall a. Printer a -> Printer [a])
    -> Alternative Printer
    forall a. Printer a
    forall a. Printer a -> Printer [a]
    forall a. Printer a -> Printer a -> Printer a
    forall (f :: * -> *).
    Applicative f
    -> (forall a. f a)
    -> (forall a. f a -> f a -> f a)
    -> (forall a. f a -> f [a])
    -> (forall a. f a -> f [a])
    -> Alternative f
    $cempty :: forall a. Printer a
    empty :: forall a. Printer a
    $c<|> :: forall a. Printer a -> Printer a -> Printer a
    <|> :: forall a. Printer a -> Printer a -> Printer a
    $csome :: forall a. Printer a -> Printer [a]
    some :: forall a. Printer a -> Printer [a]
    $cmany :: forall a. Printer a -> Printer [a]
    many :: forall a. Printer a -> Printer [a]
    Alternative)

    -- | The state of the pretty printer.
    data PrintState = PrintState
      { PrintState -> Int64
    psIndentLevel :: !Int64
        -- ^ Current indentation level, i.e. every time there's a
        -- new-line, output this many spaces.
      , PrintState -> Builder
    psOutput :: !Builder
        -- ^ The current output bytestring builder.
      , PrintState -> Bool
    psNewline :: !Bool
        -- ^ Just outputted a newline?
      , PrintState -> Int64
    psColumn :: !Int64
        -- ^ Current column.
      , PrintState -> Int64
    psLine :: !Int64
        -- ^ Current line number.
      , PrintState -> Config
    psConfig :: !Config
        -- ^ Configuration of max colums and indentation style.
      , PrintState -> Bool
    psInsideCase :: !Bool
        -- ^ Whether we're in a case statement, used for Rhs printing.
      , PrintState -> Bool
    psFitOnOneLine :: !Bool
        -- ^ Bail out if we need to print beyond the current line or
        -- the maximum column.
      , PrintState -> Bool
    psEolComment :: !Bool
      }

    -- | Configurations shared among the different styles. Styles may pay
    -- attention to or completely disregard this configuration.
    data Config = Config
        { Config -> Int64
    configMaxColumns :: !Int64 -- ^ Maximum columns to fit code into ideally.
        , Config -> Int64
    configIndentSpaces :: !Int64 -- ^ How many spaces to indent?
        , Config -> Bool
    configTrailingNewline :: !Bool -- ^ End with a newline.
        , Config -> Bool
    configSortImports :: !Bool -- ^ Sort imports in groups.
        , Config -> [String]
    configLineBreaks :: [String] -- ^ Break line when meets these operators.
        , Config -> [Extension]
    configExtensions :: [Extension]
          -- ^ Extra language extensions enabled by default.
        }

    -- | Parse an extension.

    #if __GLASGOW_HASKELL__ >= 808
    readExtension :: (Monad m, MonadFail m) => String -> m Extension
    #else
    readExtension :: Monad m => String -> m Extension
    #endif
    readExtension :: forall (m :: * -> *).
    (Monad m, MonadFail m) =>
    String -> m Extension
    readExtension String
    x =
      case String -> Extension
    classifyExtension String
    x -- Foo
           of
        UnknownExtension String
    _ -> String -> m Extension
    forall a. String -> m a
    forall (m :: * -> *) a. MonadFail m => String -> m a
    fail (String
    "Unknown extension: " String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ String
    x)
        Extension
    x' -> Extension -> m Extension
    forall a. a -> m a
    forall (m :: * -> *) a. Monad m => a -> m a
    return Extension
    x'

    instance FromJSON Config where
      parseJSON :: Value -> Parser Config
    parseJSON (Y.Object Object
    v) =
        Int64 -> Int64 -> Bool -> Bool -> [String] -> [Extension] -> Config
    Config (Int64
     -> Int64 -> Bool -> Bool -> [String] -> [Extension] -> Config)
    -> Parser Int64
    -> Parser
         (Int64 -> Bool -> Bool -> [String] -> [Extension] -> Config)
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$>
          (Maybe Int64 -> Int64) -> Parser (Maybe Int64) -> Parser Int64
    forall a b. (a -> b) -> Parser a -> Parser b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap
            (Int64 -> Maybe Int64 -> Int64
    forall a. a -> Maybe a -> a
    fromMaybe (Config -> Int64
    configMaxColumns Config
    defaultConfig))
            (Object
    v Object -> Key -> Parser (Maybe Int64)
    forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
    Y..:? Key
    "line-length") Parser (Int64 -> Bool -> Bool -> [String] -> [Extension] -> Config)
    -> Parser Int64
    -> Parser (Bool -> Bool -> [String] -> [Extension] -> Config)
    forall a b. Parser (a -> b) -> Parser a -> Parser b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*>
          (Maybe Int64 -> Int64) -> Parser (Maybe Int64) -> Parser Int64
    forall a b. (a -> b) -> Parser a -> Parser b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap
            (Int64 -> Maybe Int64 -> Int64
    forall a. a -> Maybe a -> a
    fromMaybe (Config -> Int64
    configIndentSpaces Config
    defaultConfig))
            (Object
    v Object -> Key -> Parser (Maybe Int64)
    forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
    Y..:? Key
    "indent-size" Parser (Maybe Int64)
    -> Parser (Maybe Int64) -> Parser (Maybe Int64)
    forall a. Parser a -> Parser a -> Parser a
    forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
    <|> Object
    v Object -> Key -> Parser (Maybe Int64)
    forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
    Y..:? Key
    "tab-size") Parser (Bool -> Bool -> [String] -> [Extension] -> Config)
    -> Parser Bool
    -> Parser (Bool -> [String] -> [Extension] -> Config)
    forall a b. Parser (a -> b) -> Parser a -> Parser b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*>
          (Maybe Bool -> Bool) -> Parser (Maybe Bool) -> Parser Bool
    forall a b. (a -> b) -> Parser a -> Parser b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap
            (Bool -> Maybe Bool -> Bool
    forall a. a -> Maybe a -> a
    fromMaybe (Config -> Bool
    configTrailingNewline Config
    defaultConfig))
            (Object
    v Object -> Key -> Parser (Maybe Bool)
    forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
    Y..:? Key
    "force-trailing-newline") Parser (Bool -> [String] -> [Extension] -> Config)
    -> Parser Bool -> Parser ([String] -> [Extension] -> Config)
    forall a b. Parser (a -> b) -> Parser a -> Parser b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*>
          (Maybe Bool -> Bool) -> Parser (Maybe Bool) -> Parser Bool
    forall a b. (a -> b) -> Parser a -> Parser b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap
            (Bool -> Maybe Bool -> Bool
    forall a. a -> Maybe a -> a
    fromMaybe (Config -> Bool
    configSortImports Config
    defaultConfig))
            (Object
    v Object -> Key -> Parser (Maybe Bool)
    forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
    Y..:? Key
    "sort-imports") Parser ([String] -> [Extension] -> Config)
    -> Parser [String] -> Parser ([Extension] -> Config)
    forall a b. Parser (a -> b) -> Parser a -> Parser b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*>
          (Maybe [String] -> [String])
    -> Parser (Maybe [String]) -> Parser [String]
    forall a b. (a -> b) -> Parser a -> Parser b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap
            ([String] -> Maybe [String] -> [String]
    forall a. a -> Maybe a -> a
    fromMaybe (Config -> [String]
    configLineBreaks Config
    defaultConfig))
            (Object
    v Object -> Key -> Parser (Maybe [String])
    forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
    Y..:? Key
    "line-breaks") Parser ([Extension] -> Config)
    -> Parser [Extension] -> Parser Config
    forall a b. Parser (a -> b) -> Parser a -> Parser b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*>
          ((String -> Parser Extension) -> [String] -> Parser [Extension]
    forall (t :: * -> *) (f :: * -> *) a b.
    (Traversable t, Applicative f) =>
    (a -> f b) -> t a -> f (t b)
    forall (f :: * -> *) a b.
    Applicative f =>
    (a -> f b) -> [a] -> f [b]
    traverse String -> Parser Extension
    forall (m :: * -> *).
    (Monad m, MonadFail m) =>
    String -> m Extension
    readExtension
            ([String] -> Parser [Extension])
    -> Parser [String] -> Parser [Extension]
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
    =<< (Maybe [String] -> [String])
    -> Parser (Maybe [String]) -> Parser [String]
    forall a b. (a -> b) -> Parser a -> Parser b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap ([String] -> Maybe [String] -> [String]
    forall a. a -> Maybe a -> a
    fromMaybe []) (Object
    v Object -> Key -> Parser (Maybe [String])
    forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
    Y..:? Key
    "extensions"))
      parseJSON Value
    _ = String -> Parser Config
    forall a. String -> Parser a
    forall (m :: * -> *) a. MonadFail m => String -> m a
    fail String
    "Expected Object for Config value"

    -- | Default style configuration.
    defaultConfig :: Config
    defaultConfig :: Config
    defaultConfig =
        Config
        { configMaxColumns :: Int64
    configMaxColumns = Int64
    80
        , configIndentSpaces :: Int64
    configIndentSpaces = Int64
    2
        , configTrailingNewline :: Bool
    configTrailingNewline = Bool
    True
        , configSortImports :: Bool
    configSortImports = Bool
    True
        , configLineBreaks :: [String]
    configLineBreaks = []
        , configExtensions :: [Extension]
    configExtensions = []
        }

    -- | Some comment to print.
    data SomeComment
      = EndOfLine String
      | MultiLine String
      deriving (Int -> SomeComment -> String -> String
    [SomeComment] -> String -> String
    SomeComment -> String
    (Int -> SomeComment -> String -> String)
    -> (SomeComment -> String)
    -> ([SomeComment] -> String -> String)
    -> Show SomeComment
    forall a.
    (Int -> a -> String -> String)
    -> (a -> String) -> ([a] -> String -> String) -> Show a
    $cshowsPrec :: Int -> SomeComment -> String -> String
    showsPrec :: Int -> SomeComment -> String -> String
    $cshow :: SomeComment -> String
    show :: SomeComment -> String
    $cshowList :: [SomeComment] -> String -> String
    showList :: [SomeComment] -> String -> String
    Show, Eq SomeComment
    Eq SomeComment
    -> (SomeComment -> SomeComment -> Ordering)
    -> (SomeComment -> SomeComment -> Bool)
    -> (SomeComment -> SomeComment -> Bool)
    -> (SomeComment -> SomeComment -> Bool)
    -> (SomeComment -> SomeComment -> Bool)
    -> (SomeComment -> SomeComment -> SomeComment)
    -> (SomeComment -> SomeComment -> SomeComment)
    -> Ord SomeComment
    SomeComment -> SomeComment -> Bool
    SomeComment -> SomeComment -> Ordering
    SomeComment -> SomeComment -> SomeComment
    forall a.
    Eq a
    -> (a -> a -> Ordering)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> a)
    -> (a -> a -> a)
    -> Ord a
    $ccompare :: SomeComment -> SomeComment -> Ordering
    compare :: SomeComment -> SomeComment -> Ordering
    $c< :: SomeComment -> SomeComment -> Bool
    < :: SomeComment -> SomeComment -> Bool
    $c<= :: SomeComment -> SomeComment -> Bool
    <= :: SomeComment -> SomeComment -> Bool
    $c> :: SomeComment -> SomeComment -> Bool
    > :: SomeComment -> SomeComment -> Bool
    $c>= :: SomeComment -> SomeComment -> Bool
    >= :: SomeComment -> SomeComment -> Bool
    $cmax :: SomeComment -> SomeComment -> SomeComment
    max :: SomeComment -> SomeComment -> SomeComment
    $cmin :: SomeComment -> SomeComment -> SomeComment
    min :: SomeComment -> SomeComment -> SomeComment
    Ord, SomeComment -> SomeComment -> Bool
    (SomeComment -> SomeComment -> Bool)
    -> (SomeComment -> SomeComment -> Bool) -> Eq SomeComment
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: SomeComment -> SomeComment -> Bool
    == :: SomeComment -> SomeComment -> Bool
    $c/= :: SomeComment -> SomeComment -> Bool
    /= :: SomeComment -> SomeComment -> Bool
    Eq)

    -- | Comment associated with a node.
    -- 'SrcSpan' is the original source span of the comment.
    data NodeComment
      = CommentSameLine SrcSpan SomeComment
      | CommentAfterLine SrcSpan SomeComment
      | CommentBeforeLine SrcSpan SomeComment
      deriving (Int -> NodeComment -> String -> String
    [NodeComment] -> String -> String
    NodeComment -> String
    (Int -> NodeComment -> String -> String)
    -> (NodeComment -> String)
    -> ([NodeComment] -> String -> String)
    -> Show NodeComment
    forall a.
    (Int -> a -> String -> String)
    -> (a -> String) -> ([a] -> String -> String) -> Show a
    $cshowsPrec :: Int -> NodeComment -> String -> String
    showsPrec :: Int -> NodeComment -> String -> String
    $cshow :: NodeComment -> String
    show :: NodeComment -> String
    $cshowList :: [NodeComment] -> String -> String
    showList :: [NodeComment] -> String -> String
    Show, Eq NodeComment
    Eq NodeComment
    -> (NodeComment -> NodeComment -> Ordering)
    -> (NodeComment -> NodeComment -> Bool)
    -> (NodeComment -> NodeComment -> Bool)
    -> (NodeComment -> NodeComment -> Bool)
    -> (NodeComment -> NodeComment -> Bool)
    -> (NodeComment -> NodeComment -> NodeComment)
    -> (NodeComment -> NodeComment -> NodeComment)
    -> Ord NodeComment
    NodeComment -> NodeComment -> Bool
    NodeComment -> NodeComment -> Ordering
    NodeComment -> NodeComment -> NodeComment
    forall a.
    Eq a
    -> (a -> a -> Ordering)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> a)
    -> (a -> a -> a)
    -> Ord a
    $ccompare :: NodeComment -> NodeComment -> Ordering
    compare :: NodeComment -> NodeComment -> Ordering
    $c< :: NodeComment -> NodeComment -> Bool
    < :: NodeComment -> NodeComment -> Bool
    $c<= :: NodeComment -> NodeComment -> Bool
    <= :: NodeComment -> NodeComment -> Bool
    $c> :: NodeComment -> NodeComment -> Bool
    > :: NodeComment -> NodeComment -> Bool
    $c>= :: NodeComment -> NodeComment -> Bool
    >= :: NodeComment -> NodeComment -> Bool
    $cmax :: NodeComment -> NodeComment -> NodeComment
    max :: NodeComment -> NodeComment -> NodeComment
    $cmin :: NodeComment -> NodeComment -> NodeComment
    min :: NodeComment -> NodeComment -> NodeComment
    Ord, NodeComment -> NodeComment -> Bool
    (NodeComment -> NodeComment -> Bool)
    -> (NodeComment -> NodeComment -> Bool) -> Eq NodeComment
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: NodeComment -> NodeComment -> Bool
    == :: NodeComment -> NodeComment -> Bool
    $c/= :: NodeComment -> NodeComment -> Bool
    /= :: NodeComment -> NodeComment -> Bool
    Eq)

    -- | Information for each node in the AST.
    data NodeInfo = NodeInfo
      { NodeInfo -> SrcSpanInfo
    nodeInfoSpan :: !SrcSpanInfo -- ^ Location info from the parser.
      , NodeInfo -> [NodeComment]
    nodeInfoComments :: ![NodeComment] -- ^ Comments attached to this node.
      }
    instance Show NodeInfo where
      show :: NodeInfo -> String
    show (NodeInfo SrcSpanInfo
    _ []) = String
    ""
      show (NodeInfo SrcSpanInfo
    _ [NodeComment]
    s) =
        String
    "{- " String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ [NodeComment] -> String
    forall a. Show a => a -> String
    show [NodeComment]
    s String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ String
    " -}"