-- | 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
(SpanStream -> SpanStream -> Bool)
-> (SpanStream -> SpanStream -> Bool) -> Eq SpanStream
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: SpanStream -> SpanStream -> Bool
== :: SpanStream -> SpanStream -> Bool
$c/= :: SpanStream -> SpanStream -> Bool
/= :: SpanStream -> SpanStream -> Bool
Eq, Int -> SpanStream -> ShowS
[SpanStream] -> ShowS
SpanStream -> String
(Int -> SpanStream -> ShowS)
-> (SpanStream -> String)
-> ([SpanStream] -> ShowS)
-> Show SpanStream
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> SpanStream -> ShowS
showsPrec :: Int -> SpanStream -> ShowS
$cshow :: SpanStream -> String
show :: SpanStream -> String
$cshowList :: [SpanStream] -> ShowS
showList :: [SpanStream] -> ShowS
Show, Typeable SpanStream
Typeable SpanStream =>
(forall (c :: * -> *).
 (forall d b. Data d => c (d -> b) -> d -> c b)
 -> (forall g. g -> c g) -> SpanStream -> c SpanStream)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c SpanStream)
-> (SpanStream -> Constr)
-> (SpanStream -> DataType)
-> (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))
-> ((forall b. Data b => b -> b) -> SpanStream -> SpanStream)
-> (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 u. (forall d. Data d => d -> u) -> SpanStream -> [u])
-> (forall u.
    Int -> (forall d. Data d => d -> u) -> SpanStream -> u)
-> (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 (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> SpanStream -> m SpanStream)
-> Data SpanStream
SpanStream -> Constr
SpanStream -> DataType
(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)
$cgfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> SpanStream -> c SpanStream
gfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> SpanStream -> c SpanStream
$cgunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c SpanStream
gunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c SpanStream
$ctoConstr :: SpanStream -> Constr
toConstr :: SpanStream -> Constr
$cdataTypeOf :: SpanStream -> DataType
dataTypeOf :: SpanStream -> DataType
$cdataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c SpanStream)
dataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c SpanStream)
$cdataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c SpanStream)
dataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c SpanStream)
$cgmapT :: (forall b. Data b => b -> b) -> SpanStream -> SpanStream
gmapT :: (forall b. Data b => b -> b) -> SpanStream -> SpanStream
$cgmapQl :: 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
$cgmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> SpanStream -> r
gmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> SpanStream -> r
$cgmapQ :: forall u. (forall d. Data d => d -> u) -> SpanStream -> [u]
gmapQ :: forall u. (forall d. Data d => d -> u) -> SpanStream -> [u]
$cgmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> SpanStream -> u
gmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> SpanStream -> u
$cgmapM :: forall (m :: * -> *).
Monad 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
$cgmapMp :: 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
$cgmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> SpanStream -> m SpanStream
gmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> SpanStream -> m SpanStream
Data, NonEmpty SpanStream -> SpanStream
SpanStream -> SpanStream -> SpanStream
(SpanStream -> SpanStream -> SpanStream)
-> (NonEmpty SpanStream -> SpanStream)
-> (forall b. Integral b => b -> SpanStream -> SpanStream)
-> Semigroup 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
$c<> :: SpanStream -> SpanStream -> SpanStream
<> :: SpanStream -> SpanStream -> SpanStream
$csconcat :: NonEmpty SpanStream -> SpanStream
sconcat :: NonEmpty SpanStream -> SpanStream
$cstimes :: forall b. Integral b => b -> SpanStream -> SpanStream
stimes :: forall b. Integral b => b -> SpanStream -> SpanStream
Semigroup, Semigroup SpanStream
SpanStream
Semigroup SpanStream =>
SpanStream
-> (SpanStream -> SpanStream -> SpanStream)
-> ([SpanStream] -> SpanStream)
-> Monoid SpanStream
[SpanStream] -> SpanStream
SpanStream -> SpanStream -> SpanStream
forall a.
Semigroup a =>
a -> (a -> a -> a) -> ([a] -> a) -> Monoid a
$cmempty :: SpanStream
mempty :: SpanStream
$cmappend :: SpanStream -> SpanStream -> SpanStream
mappend :: SpanStream -> SpanStream -> SpanStream
$cmconcat :: [SpanStream] -> SpanStream
mconcat :: [SpanStream] -> 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
    ([RealSrcSpan] -> SpanStream)
-> (Seq RealSrcSpan -> [RealSrcSpan])
-> Seq RealSrcSpan
-> SpanStream
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (RealSrcSpan -> RealSrcLoc) -> [RealSrcSpan] -> [RealSrcSpan]
forall b a. Ord b => (a -> b) -> [a] -> [a]
sortOn RealSrcSpan -> RealSrcLoc
realSrcSpanStart
    ([RealSrcSpan] -> [RealSrcSpan])
-> (Seq RealSrcSpan -> [RealSrcSpan])
-> Seq RealSrcSpan
-> [RealSrcSpan]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Seq RealSrcSpan -> [RealSrcSpan]
forall a. Seq a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList
    (Seq RealSrcSpan -> SpanStream) -> Seq RealSrcSpan -> SpanStream
forall a b. (a -> b) -> a -> b
$ (Seq RealSrcSpan -> Seq RealSrcSpan -> Seq RealSrcSpan)
-> GenericQ (Seq RealSrcSpan) -> GenericQ (Seq RealSrcSpan)
forall r. (r -> r -> r) -> GenericQ r -> GenericQ r
everything Seq RealSrcSpan -> Seq RealSrcSpan -> Seq RealSrcSpan
forall a. Monoid a => a -> a -> a
mappend (Seq RealSrcSpan -> a -> Seq RealSrcSpan
forall a b. a -> b -> a
const Seq RealSrcSpan
forall a. Monoid a => a
mempty (a -> Seq RealSrcSpan)
-> (forall d1 d2.
    (Data d1, Data d2) =>
    GenLocated d1 d2 -> Seq RealSrcSpan)
-> a
-> Seq RealSrcSpan
forall d (t :: * -> * -> *) q.
(Data d, Typeable t) =>
(d -> q)
-> (forall d1 d2. (Data d1, Data d2) => t d1 d2 -> q) -> d -> q
`ext2Q` GenLocated d1 d2 -> Seq RealSrcSpan
forall d1 d2.
(Data d1, Data d2) =>
GenLocated d1 d2 -> Seq RealSrcSpan
forall e0 e1. Data e0 => GenLocated e0 e1 -> Seq RealSrcSpan
queryLocated (a -> Seq RealSrcSpan)
-> (forall e. Data e => SrcSpanAnn' e -> Seq RealSrcSpan)
-> a
-> Seq RealSrcSpan
forall d (t :: * -> *) q.
(Data d, Typeable t) =>
(d -> q) -> (forall e. Data e => t e -> q) -> d -> q
`ext1Q` SrcSpanAnn' e -> Seq RealSrcSpan
forall e. Data e => SrcSpanAnn' e -> Seq RealSrcSpan
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
_) =
      Seq RealSrcSpan
-> (SrcSpan -> Seq RealSrcSpan) -> Maybe SrcSpan -> Seq RealSrcSpan
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Seq RealSrcSpan
forall a. Monoid a => a
mempty SrcSpan -> Seq RealSrcSpan
srcSpanToRealSrcSpanSeq (e0 -> Maybe SrcSpan
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 (SrcSpan -> Seq RealSrcSpan)
-> (SrcSpanAnn' a -> SrcSpan) -> SrcSpanAnn' a -> Seq RealSrcSpan
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SrcSpanAnn' a -> SrcSpan
forall a. SrcSpanAnn' a -> SrcSpan
locA
    srcSpanToRealSrcSpanSeq :: SrcSpan -> Seq RealSrcSpan
srcSpanToRealSrcSpanSeq =
      [RealSrcSpan] -> Seq RealSrcSpan
forall a. [a] -> Seq a
Seq.fromList ([RealSrcSpan] -> Seq RealSrcSpan)
-> (SrcSpan -> [RealSrcSpan]) -> SrcSpan -> Seq RealSrcSpan
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe RealSrcSpan -> [RealSrcSpan]
forall a. Maybe a -> [a]
maybeToList (Maybe RealSrcSpan -> [RealSrcSpan])
-> (SrcSpan -> Maybe RealSrcSpan) -> SrcSpan -> [RealSrcSpan]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SrcSpan -> Maybe RealSrcSpan
srcSpanToRealSrcSpan