{-# 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, ext2Q)
import Data.List (sortOn)
import Data.Typeable (cast)
import 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
/= :: SpanStream -> SpanStream -> Bool
$c/= :: SpanStream -> SpanStream -> Bool
== :: SpanStream -> SpanStream -> Bool
$c== :: 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
showList :: [SpanStream] -> ShowS
$cshowList :: [SpanStream] -> ShowS
show :: SpanStream -> String
$cshow :: SpanStream -> String
showsPrec :: Int -> SpanStream -> ShowS
$cshowsPrec :: Int -> SpanStream -> ShowS
Show, Typeable SpanStream
DataType
Constr
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 -> DataType
SpanStream -> Constr
(forall b. Data b => b -> b) -> SpanStream -> SpanStream
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> SpanStream -> c SpanStream
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c 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)
$cSpanStream :: Constr
$tSpanStream :: DataType
gmapMo :: (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 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 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 :: Int -> (forall d. Data d => d -> u) -> SpanStream -> u
$cgmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> SpanStream -> u
gmapQ :: (forall d. Data d => d -> u) -> SpanStream -> [u]
$cgmapQ :: forall u. (forall d. Data d => d -> u) -> SpanStream -> [u]
gmapQr :: (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 :: (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 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 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 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 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
$cp1Data :: Typeable SpanStream
Data, b -> SpanStream -> SpanStream
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
stimes :: 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
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
mconcat :: [SpanStream] -> SpanStream
$cmconcat :: [SpanStream] -> SpanStream
mappend :: SpanStream -> SpanStream -> SpanStream
$cmappend :: SpanStream -> SpanStream -> SpanStream
mempty :: SpanStream
$cmempty :: SpanStream
$cp1Monoid :: Semigroup SpanStream
Monoid)

-- | Create 'SpanStream' from a data structure containing \"located\"
-- elements.
mkSpanStream ::
  Data a =>
  -- | Data structure to inspect (AST)
  a ->
  SpanStream
mkSpanStream :: a -> SpanStream
mkSpanStream a
a =
  [RealSrcSpan] -> SpanStream
SpanStream
    ([RealSrcSpan] -> SpanStream)
-> (DList RealSrcSpan -> [RealSrcSpan])
-> DList 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])
-> (DList RealSrcSpan -> [RealSrcSpan])
-> DList RealSrcSpan
-> [RealSrcSpan]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. DList RealSrcSpan -> [RealSrcSpan]
forall a. DList a -> [a]
D.toList
    (DList RealSrcSpan -> SpanStream)
-> DList RealSrcSpan -> SpanStream
forall a b. (a -> b) -> a -> b
$ (DList RealSrcSpan -> DList RealSrcSpan -> DList RealSrcSpan)
-> GenericQ (DList RealSrcSpan) -> a -> DList RealSrcSpan
forall r. (r -> r -> r) -> GenericQ r -> GenericQ r
everything DList RealSrcSpan -> DList RealSrcSpan -> DList RealSrcSpan
forall a. Monoid a => a -> a -> a
mappend (DList RealSrcSpan -> a -> DList RealSrcSpan
forall a b. a -> b -> a
const DList RealSrcSpan
forall a. Monoid a => a
mempty (a -> DList RealSrcSpan)
-> (forall d1 d2.
    (Data d1, Data d2) =>
    GenLocated d1 d2 -> DList RealSrcSpan)
-> a
-> DList 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` forall d1 d2.
(Data d1, Data d2) =>
GenLocated d1 d2 -> DList RealSrcSpan
forall e0 e1. Data e0 => GenLocated e0 e1 -> DList RealSrcSpan
queryLocated) a
a
  where
    queryLocated ::
      (Data e0) =>
      GenLocated e0 e1 ->
      DList RealSrcSpan
    queryLocated :: GenLocated e0 e1 -> DList RealSrcSpan
queryLocated (L e0
mspn e1
_) =
      case e0 -> Maybe SrcSpan
forall a b. (Typeable a, Typeable b) => a -> Maybe b
cast e0
mspn :: Maybe SrcSpan of
        Maybe SrcSpan
Nothing -> DList RealSrcSpan
forall a. Monoid a => a
mempty
        Just (UnhelpfulSpan FastString
_) -> DList RealSrcSpan
forall a. Monoid a => a
mempty
        Just (RealSrcSpan RealSrcSpan
spn) -> RealSrcSpan -> DList RealSrcSpan
forall a. a -> DList a
D.singleton RealSrcSpan
spn