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

import Data.Data (Data)
import Data.Foldable (toList)
import Data.Generics (everything, ext1Q, ext2Q)
import Data.List (sortOn)
import Data.Maybe (maybeToList)
import Data.Sequence (Seq)
import Data.Sequence qualified as Seq
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 (t :: * -> *) a. Foldable t => t a -> [a]
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 -> Seq 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 -> Seq RealSrcSpan
querySrcSpanAnn) a
a
  where
    queryLocated ::
      (Data e0) =>
      GenLocated e0 e1 ->
      Seq RealSrcSpan
    queryLocated :: forall e0 e1. Data e0 => GenLocated e0 e1 -> Seq RealSrcSpan
queryLocated (L e0
mspn e1
_) =
      forall b a. b -> (a -> b) -> Maybe a -> b
maybe forall a. Monoid a => a
mempty SrcSpan -> Seq RealSrcSpan
srcSpanToRealSrcSpanSeq (forall a b. (Typeable a, Typeable b) => a -> Maybe b
cast e0
mspn :: Maybe SrcSpan)
    querySrcSpanAnn :: SrcSpanAnn' a -> Seq RealSrcSpan
    querySrcSpanAnn :: forall a. SrcSpanAnn' a -> Seq RealSrcSpan
querySrcSpanAnn = SrcSpan -> Seq RealSrcSpan
srcSpanToRealSrcSpanSeq forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. SrcSpanAnn' a -> SrcSpan
locA
    srcSpanToRealSrcSpanSeq :: SrcSpan -> Seq RealSrcSpan
srcSpanToRealSrcSpanSeq =
      forall a. [a] -> Seq a
Seq.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