    {-# LANGUAGE DeriveDataTypeable #-}

    -- | A module for dealing with shebangs.
    module Ormolu.Parser.Shebang
      ( Shebang (..),
        extractShebangs,
        isShebang,
      )
    where

    import Data.Data (Data)
    import qualified Data.List as L
    import SrcLoc

    -- | A wrapper for a shebang.
    newtype Shebang = Shebang (Located String)
      deriving (Shebang -> Shebang -> Bool
    (Shebang -> Shebang -> Bool)
    -> (Shebang -> Shebang -> Bool) -> Eq Shebang
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    /= :: Shebang -> Shebang -> Bool
    $c/= :: Shebang -> Shebang -> Bool
    == :: Shebang -> Shebang -> Bool
    $c== :: Shebang -> Shebang -> Bool
    Eq, Typeable Shebang
    DataType
    Constr
    Typeable Shebang =>
    (forall (c :: * -> *).
     (forall d b. Data d => c (d -> b) -> d -> c b)
     -> (forall g. g -> c g) -> Shebang -> c Shebang)
    -> (forall (c :: * -> *).
        (forall b r. Data b => c (b -> r) -> c r)
        -> (forall r. r -> c r) -> Constr -> c Shebang)
    -> (Shebang -> Constr)
    -> (Shebang -> DataType)
    -> (forall (t :: * -> *) (c :: * -> *).
        Typeable t =>
        (forall d. Data d => c (t d)) -> Maybe (c Shebang))
    -> (forall (t :: * -> * -> *) (c :: * -> *).
        Typeable t =>
        (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Shebang))
    -> ((forall b. Data b => b -> b) -> Shebang -> Shebang)
    -> (forall r r'.
        (r -> r' -> r)
        -> r -> (forall d. Data d => d -> r') -> Shebang -> r)
    -> (forall r r'.
        (r' -> r -> r)
        -> r -> (forall d. Data d => d -> r') -> Shebang -> r)
    -> (forall u. (forall d. Data d => d -> u) -> Shebang -> [u])
    -> (forall u. Int -> (forall d. Data d => d -> u) -> Shebang -> u)
    -> (forall (m :: * -> *).
        Monad m =>
        (forall d. Data d => d -> m d) -> Shebang -> m Shebang)
    -> (forall (m :: * -> *).
        MonadPlus m =>
        (forall d. Data d => d -> m d) -> Shebang -> m Shebang)
    -> (forall (m :: * -> *).
        MonadPlus m =>
        (forall d. Data d => d -> m d) -> Shebang -> m Shebang)
    -> Data Shebang
    Shebang -> DataType
    Shebang -> Constr
    (forall b. Data b => b -> b) -> Shebang -> Shebang
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> Shebang -> c Shebang
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c Shebang
    forall a.
    Typeable a =>
    (forall (c :: * -> *).
     (forall d b. Data d => c (d -> b) -> d -> c b)
     -> (forall g. g -> c g) -> a -> c a)
    -> (forall (c :: * -> *).
        (forall b r. Data b => c (b -> r) -> c r)
        -> (forall r. r -> c r) -> Constr -> c a)
    -> (a -> Constr)
    -> (a -> DataType)
    -> (forall (t :: * -> *) (c :: * -> *).
        Typeable t =>
        (forall d. Data d => c (t d)) -> Maybe (c a))
    -> (forall (t :: * -> * -> *) (c :: * -> *).
        Typeable t =>
        (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
    -> ((forall b. Data b => b -> b) -> a -> a)
    -> (forall r r'.
        (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
    -> (forall r r'.
        (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
    -> (forall u. (forall d. Data d => d -> u) -> a -> [u])
    -> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
    -> (forall (m :: * -> *).
        Monad m =>
        (forall d. Data d => d -> m d) -> a -> m a)
    -> (forall (m :: * -> *).
        MonadPlus m =>
        (forall d. Data d => d -> m d) -> a -> m a)
    -> (forall (m :: * -> *).
        MonadPlus m =>
        (forall d. Data d => d -> m d) -> a -> m a)
    -> Data a
    forall u. Int -> (forall d. Data d => d -> u) -> Shebang -> u
    forall u. (forall d. Data d => d -> u) -> Shebang -> [u]
    forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> Shebang -> r
    forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> Shebang -> r
    forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> Shebang -> m Shebang
    forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> Shebang -> m Shebang
    forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c Shebang
    forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> Shebang -> c Shebang
    forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c Shebang)
    forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Shebang)
    $cShebang :: Constr
    $tShebang :: DataType
    gmapMo :: (forall d. Data d => d -> m d) -> Shebang -> m Shebang
    $cgmapMo :: forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> Shebang -> m Shebang
    gmapMp :: (forall d. Data d => d -> m d) -> Shebang -> m Shebang
    $cgmapMp :: forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> Shebang -> m Shebang
    gmapM :: (forall d. Data d => d -> m d) -> Shebang -> m Shebang
    $cgmapM :: forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> Shebang -> m Shebang
    gmapQi :: Int -> (forall d. Data d => d -> u) -> Shebang -> u
    $cgmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> Shebang -> u
    gmapQ :: (forall d. Data d => d -> u) -> Shebang -> [u]
    $cgmapQ :: forall u. (forall d. Data d => d -> u) -> Shebang -> [u]
    gmapQr :: (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> Shebang -> r
    $cgmapQr :: forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> Shebang -> r
    gmapQl :: (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> Shebang -> r
    $cgmapQl :: forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> Shebang -> r
    gmapT :: (forall b. Data b => b -> b) -> Shebang -> Shebang
    $cgmapT :: (forall b. Data b => b -> b) -> Shebang -> Shebang
    dataCast2 :: (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Shebang)
    $cdataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Shebang)
    dataCast1 :: (forall d. Data d => c (t d)) -> Maybe (c Shebang)
    $cdataCast1 :: forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c Shebang)
    dataTypeOf :: Shebang -> DataType
    $cdataTypeOf :: Shebang -> DataType
    toConstr :: Shebang -> Constr
    $ctoConstr :: Shebang -> Constr
    gunfold :: (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c Shebang
    $cgunfold :: forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c Shebang
    gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> Shebang -> c Shebang
    $cgfoldl :: forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> Shebang -> c Shebang
    $cp1Data :: Typeable Shebang
    Data)

    -- | Extract shebangs from the beginning of a comment stream.
    extractShebangs :: [Located String] -> ([Shebang], [Located String])
    extractShebangs :: [Located String] -> ([Shebang], [Located String])
    extractShebangs comments :: [Located String]
    comments = (Located String -> Shebang
    Shebang (Located String -> Shebang) -> [Located String] -> [Shebang]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> [Located String]
    shebangs, [Located String]
    rest)
      where
        (shebangs :: [Located String]
    shebangs, rest :: [Located String]
    rest) = (Located String -> Bool)
    -> [Located String] -> ([Located String], [Located String])
    forall a. (a -> Bool) -> [a] -> ([a], [a])
    span (String -> Bool
    isShebang (String -> Bool)
    -> (Located String -> String) -> Located String -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Located String -> String
    forall a. HasSrcSpan a => a -> SrcSpanLess a
    unLoc) [Located String]
    comments

    -- | Return 'True' if given 'String' is a shebang.
    isShebang :: String -> Bool
    isShebang :: String -> Bool
    isShebang str :: String
    str = "#!" String -> String -> Bool
    forall a. Eq a => [a] -> [a] -> Bool
    `L.isPrefixOf` String
    str