{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}

-- | Build span stream from AST.
module Ormolu.Printer.SpanStream
  ( SpanStream (..),
    mkSpanStream,
  )
where

import Data.DList (DList)
import qualified Data.DList as D
import Data.Data (Data)
import Data.Generics (everything, ext1Q, ext2Q)
import Data.List (sortOn)
import Data.Maybe (maybeToList)
import Data.Typeable (cast)
import GHC.Parser.Annotation
import GHC.Types.SrcLoc

-- | A stream of 'RealSrcSpan's in ascending order. This allows us to tell
-- e.g. whether there is another \"located\" element of AST between current
-- element and comment we're considering for printing.
newtype SpanStream = SpanStream [RealSrcSpan]
  deriving (SpanStream -> SpanStream -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: SpanStream -> SpanStream -> Bool
$c/= :: SpanStream -> SpanStream -> Bool
== :: SpanStream -> SpanStream -> Bool
$c== :: SpanStream -> SpanStream -> Bool
Eq, Int -> SpanStream -> ShowS
[SpanStream] -> ShowS
SpanStream -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [SpanStream] -> ShowS
$cshowList :: [SpanStream] -> ShowS
show :: SpanStream -> String
$cshow :: SpanStream -> String
showsPrec :: Int -> SpanStream -> ShowS
$cshowsPrec :: Int -> SpanStream -> ShowS
Show, Typeable SpanStream
SpanStream -> DataType
SpanStream -> Constr
(forall b. Data b => b -> b) -> SpanStream -> SpanStream
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) -> SpanStream -> u
forall u. (forall d. Data d => d -> u) -> SpanStream -> [u]
forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> SpanStream -> r
forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> SpanStream -> r
forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> SpanStream -> m SpanStream
forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> SpanStream -> m SpanStream
forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c SpanStream
forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> SpanStream -> c SpanStream
forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c SpanStream)
forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c SpanStream)
gmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> SpanStream -> m SpanStream
$cgmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> SpanStream -> m SpanStream
gmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> SpanStream -> m SpanStream
$cgmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> SpanStream -> m SpanStream
gmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> SpanStream -> m SpanStream
$cgmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> SpanStream -> m SpanStream
gmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> SpanStream -> u
$cgmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> SpanStream -> u
gmapQ :: forall u. (forall d. Data d => d -> u) -> SpanStream -> [u]
$cgmapQ :: forall u. (forall d. Data d => d -> u) -> SpanStream -> [u]
gmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> SpanStream -> r
$cgmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> SpanStream -> r
gmapQl :: forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> SpanStream -> r
$cgmapQl :: forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> SpanStream -> r
gmapT :: (forall b. Data b => b -> b) -> SpanStream -> SpanStream
$cgmapT :: (forall b. Data b => b -> b) -> SpanStream -> SpanStream
dataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c SpanStream)
$cdataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c SpanStream)
dataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c SpanStream)
$cdataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c SpanStream)
dataTypeOf :: SpanStream -> DataType
$cdataTypeOf :: SpanStream -> DataType
toConstr :: SpanStream -> Constr
$ctoConstr :: SpanStream -> Constr
gunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c SpanStream
$cgunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c SpanStream
gfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> SpanStream -> c SpanStream
$cgfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> SpanStream -> c SpanStream
Data, NonEmpty SpanStream -> SpanStream
SpanStream -> SpanStream -> SpanStream
forall b. Integral b => b -> SpanStream -> SpanStream
forall a.
(a -> a -> a)
-> (NonEmpty a -> a)
-> (forall b. Integral b => b -> a -> a)
-> Semigroup a
stimes :: forall b. Integral b => b -> SpanStream -> SpanStream
$cstimes :: forall b. Integral b => b -> SpanStream -> SpanStream
sconcat :: NonEmpty SpanStream -> SpanStream
$csconcat :: NonEmpty SpanStream -> SpanStream
<> :: SpanStream -> SpanStream -> SpanStream
$c<> :: SpanStream -> SpanStream -> SpanStream
Semigroup, Semigroup SpanStream
SpanStream
[SpanStream] -> SpanStream
SpanStream -> SpanStream -> SpanStream
forall a.
Semigroup a -> a -> (a -> a -> a) -> ([a] -> a) -> Monoid a
mconcat :: [SpanStream] -> SpanStream
$cmconcat :: [SpanStream] -> SpanStream
mappend :: SpanStream -> SpanStream -> SpanStream
$cmappend :: SpanStream -> SpanStream -> SpanStream
mempty :: SpanStream
$cmempty :: SpanStream
Monoid)

-- | Create 'SpanStream' from a data structure containing \"located\"
-- elements.
mkSpanStream ::
  (Data a) =>
  -- | Data structure to inspect (AST)
  a ->
  SpanStream
mkSpanStream :: forall a. Data a => a -> SpanStream
mkSpanStream a
a =
  [RealSrcSpan] -> SpanStream
SpanStream
    forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall b a. Ord b => (a -> b) -> [a] -> [a]
sortOn RealSrcSpan -> RealSrcLoc
realSrcSpanStart
    forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. DList a -> [a]
D.toList
    forall a b. (a -> b) -> a -> b
$ forall r. (r -> r -> r) -> GenericQ r -> GenericQ r
everything forall a. Monoid a => a -> a -> a
mappend (forall a b. a -> b -> a
const forall a. Monoid a => a
mempty forall d (t :: * -> * -> *) q.
(Data d, Typeable t) =>
(d -> q)
-> (forall d1 d2. (Data d1, Data d2) => t d1 d2 -> q) -> d -> q
`ext2Q` forall e0 e1. Data e0 => GenLocated e0 e1 -> DList RealSrcSpan
queryLocated forall d (t :: * -> *) q.
(Data d, Typeable t) =>
(d -> q) -> (forall e. Data e => t e -> q) -> d -> q
`ext1Q` forall a. SrcSpanAnn' a -> DList RealSrcSpan
querySrcSpanAnn) a
a
  where
    queryLocated ::
      (Data e0) =>
      GenLocated e0 e1 ->
      DList RealSrcSpan
    queryLocated :: forall e0 e1. Data e0 => GenLocated e0 e1 -> DList RealSrcSpan
queryLocated (L e0
mspn e1
_) =
      forall b a. b -> (a -> b) -> Maybe a -> b
maybe forall a. Monoid a => a
mempty SrcSpan -> DList RealSrcSpan
srcSpanToRealSrcSpanDList (forall a b. (Typeable a, Typeable b) => a -> Maybe b
cast e0
mspn :: Maybe SrcSpan)
    querySrcSpanAnn :: SrcSpanAnn' a -> DList RealSrcSpan
    querySrcSpanAnn :: forall a. SrcSpanAnn' a -> DList RealSrcSpan
querySrcSpanAnn = SrcSpan -> DList RealSrcSpan
srcSpanToRealSrcSpanDList forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. SrcSpanAnn' a -> SrcSpan
locA
    srcSpanToRealSrcSpanDList :: SrcSpan -> DList RealSrcSpan
srcSpanToRealSrcSpanDList =
      forall a. [a] -> DList a
D.fromList forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Maybe a -> [a]
maybeToList forall b c a. (b -> c) -> (a -> b) -> a -> c
. SrcSpan -> Maybe RealSrcSpan
srcSpanToRealSrcSpan