{-# LANGUAGE DerivingVia    #-}
{-# LANGUAGE GADTs          #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE RankNTypes     #-}

module Development.IDE.Core.UseStale
  ( Age(..)
  , Tracked
  , unTrack
  , PositionMap
  , TrackedStale (..)
  , untrackedStaleValue
  , unsafeMkStale
  , unsafeMkCurrent
  , unsafeCopyAge
  , MapAge (..)
  , dualPositionMap
  , useWithStale
  , useWithStale_
  ) where

import           Control.Arrow
import           Control.Category (Category)
import qualified Control.Category as C
import           Control.DeepSeq (NFData)
import           Data.Aeson
import           Data.Coerce (coerce)
import           Data.Functor ((<&>))
import           Data.Functor.Identity (Identity(Identity))
import           Data.Kind (Type)
import           Data.String (fromString)
import           Development.IDE (NormalizedFilePath, IdeRule, Action, Range, rangeToRealSrcSpan, realSrcSpanToRange)
import qualified Development.IDE.Core.PositionMapping as P
import qualified Development.IDE.Core.Shake as IDE
import qualified FastString as FS
import           SrcLoc


------------------------------------------------------------------------------
-- | A data kind for 'Tracked'.
data Age = Current | Stale Type


------------------------------------------------------------------------------
-- | Some value, tagged with its age. All 'Current' ages are considered to be
-- the same thing, but 'Stale' values are protected by an untouchable variable
-- to ensure they can't be unified.
newtype Tracked (age :: Age) a  = UnsafeTracked
  { Tracked age a -> a
unTrack :: a
  }
  deriving stock (a -> Tracked age b -> Tracked age a
(a -> b) -> Tracked age a -> Tracked age b
(forall a b. (a -> b) -> Tracked age a -> Tracked age b)
-> (forall a b. a -> Tracked age b -> Tracked age a)
-> Functor (Tracked age)
forall a b. a -> Tracked age b -> Tracked age a
forall a b. (a -> b) -> Tracked age a -> Tracked age b
forall (age :: Age) a b. a -> Tracked age b -> Tracked age a
forall (age :: Age) a b. (a -> b) -> Tracked age a -> Tracked age b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: a -> Tracked age b -> Tracked age a
$c<$ :: forall (age :: Age) a b. a -> Tracked age b -> Tracked age a
fmap :: (a -> b) -> Tracked age a -> Tracked age b
$cfmap :: forall (age :: Age) a b. (a -> b) -> Tracked age a -> Tracked age b
Functor, Tracked age a -> Bool
(a -> m) -> Tracked age a -> m
(a -> b -> b) -> b -> Tracked age a -> b
(forall m. Monoid m => Tracked age m -> m)
-> (forall m a. Monoid m => (a -> m) -> Tracked age a -> m)
-> (forall m a. Monoid m => (a -> m) -> Tracked age a -> m)
-> (forall a b. (a -> b -> b) -> b -> Tracked age a -> b)
-> (forall a b. (a -> b -> b) -> b -> Tracked age a -> b)
-> (forall b a. (b -> a -> b) -> b -> Tracked age a -> b)
-> (forall b a. (b -> a -> b) -> b -> Tracked age a -> b)
-> (forall a. (a -> a -> a) -> Tracked age a -> a)
-> (forall a. (a -> a -> a) -> Tracked age a -> a)
-> (forall a. Tracked age a -> [a])
-> (forall a. Tracked age a -> Bool)
-> (forall a. Tracked age a -> Int)
-> (forall a. Eq a => a -> Tracked age a -> Bool)
-> (forall a. Ord a => Tracked age a -> a)
-> (forall a. Ord a => Tracked age a -> a)
-> (forall a. Num a => Tracked age a -> a)
-> (forall a. Num a => Tracked age a -> a)
-> Foldable (Tracked age)
forall a. Eq a => a -> Tracked age a -> Bool
forall a. Num a => Tracked age a -> a
forall a. Ord a => Tracked age a -> a
forall m. Monoid m => Tracked age m -> m
forall a. Tracked age a -> Bool
forall a. Tracked age a -> Int
forall a. Tracked age a -> [a]
forall a. (a -> a -> a) -> Tracked age a -> a
forall m a. Monoid m => (a -> m) -> Tracked age a -> m
forall b a. (b -> a -> b) -> b -> Tracked age a -> b
forall a b. (a -> b -> b) -> b -> Tracked age a -> b
forall (age :: Age) a. Eq a => a -> Tracked age a -> Bool
forall (age :: Age) a. Num a => Tracked age a -> a
forall (age :: Age) a. Ord a => Tracked age a -> a
forall (age :: Age) m. Monoid m => Tracked age m -> m
forall (age :: Age) a. Tracked age a -> Bool
forall (age :: Age) a. Tracked age a -> Int
forall (age :: Age) a. Tracked age a -> [a]
forall (age :: Age) a. (a -> a -> a) -> Tracked age a -> a
forall (age :: Age) m a. Monoid m => (a -> m) -> Tracked age a -> m
forall (age :: Age) b a. (b -> a -> b) -> b -> Tracked age a -> b
forall (age :: Age) a b. (a -> b -> b) -> b -> Tracked age a -> b
forall (t :: * -> *).
(forall m. Monoid m => t m -> m)
-> (forall m a. Monoid m => (a -> m) -> t a -> m)
-> (forall m a. Monoid m => (a -> m) -> t a -> m)
-> (forall a b. (a -> b -> b) -> b -> t a -> b)
-> (forall a b. (a -> b -> b) -> b -> t a -> b)
-> (forall b a. (b -> a -> b) -> b -> t a -> b)
-> (forall b a. (b -> a -> b) -> b -> t a -> b)
-> (forall a. (a -> a -> a) -> t a -> a)
-> (forall a. (a -> a -> a) -> t a -> a)
-> (forall a. t a -> [a])
-> (forall a. t a -> Bool)
-> (forall a. t a -> Int)
-> (forall a. Eq a => a -> t a -> Bool)
-> (forall a. Ord a => t a -> a)
-> (forall a. Ord a => t a -> a)
-> (forall a. Num a => t a -> a)
-> (forall a. Num a => t a -> a)
-> Foldable t
product :: Tracked age a -> a
$cproduct :: forall (age :: Age) a. Num a => Tracked age a -> a
sum :: Tracked age a -> a
$csum :: forall (age :: Age) a. Num a => Tracked age a -> a
minimum :: Tracked age a -> a
$cminimum :: forall (age :: Age) a. Ord a => Tracked age a -> a
maximum :: Tracked age a -> a
$cmaximum :: forall (age :: Age) a. Ord a => Tracked age a -> a
elem :: a -> Tracked age a -> Bool
$celem :: forall (age :: Age) a. Eq a => a -> Tracked age a -> Bool
length :: Tracked age a -> Int
$clength :: forall (age :: Age) a. Tracked age a -> Int
null :: Tracked age a -> Bool
$cnull :: forall (age :: Age) a. Tracked age a -> Bool
toList :: Tracked age a -> [a]
$ctoList :: forall (age :: Age) a. Tracked age a -> [a]
foldl1 :: (a -> a -> a) -> Tracked age a -> a
$cfoldl1 :: forall (age :: Age) a. (a -> a -> a) -> Tracked age a -> a
foldr1 :: (a -> a -> a) -> Tracked age a -> a
$cfoldr1 :: forall (age :: Age) a. (a -> a -> a) -> Tracked age a -> a
foldl' :: (b -> a -> b) -> b -> Tracked age a -> b
$cfoldl' :: forall (age :: Age) b a. (b -> a -> b) -> b -> Tracked age a -> b
foldl :: (b -> a -> b) -> b -> Tracked age a -> b
$cfoldl :: forall (age :: Age) b a. (b -> a -> b) -> b -> Tracked age a -> b
foldr' :: (a -> b -> b) -> b -> Tracked age a -> b
$cfoldr' :: forall (age :: Age) a b. (a -> b -> b) -> b -> Tracked age a -> b
foldr :: (a -> b -> b) -> b -> Tracked age a -> b
$cfoldr :: forall (age :: Age) a b. (a -> b -> b) -> b -> Tracked age a -> b
foldMap' :: (a -> m) -> Tracked age a -> m
$cfoldMap' :: forall (age :: Age) m a. Monoid m => (a -> m) -> Tracked age a -> m
foldMap :: (a -> m) -> Tracked age a -> m
$cfoldMap :: forall (age :: Age) m a. Monoid m => (a -> m) -> Tracked age a -> m
fold :: Tracked age m -> m
$cfold :: forall (age :: Age) m. Monoid m => Tracked age m -> m
Foldable, Functor (Tracked age)
Foldable (Tracked age)
Functor (Tracked age)
-> Foldable (Tracked age)
-> (forall (f :: * -> *) a b.
    Applicative f =>
    (a -> f b) -> Tracked age a -> f (Tracked age b))
-> (forall (f :: * -> *) a.
    Applicative f =>
    Tracked age (f a) -> f (Tracked age a))
-> (forall (m :: * -> *) a b.
    Monad m =>
    (a -> m b) -> Tracked age a -> m (Tracked age b))
-> (forall (m :: * -> *) a.
    Monad m =>
    Tracked age (m a) -> m (Tracked age a))
-> Traversable (Tracked age)
(a -> f b) -> Tracked age a -> f (Tracked age b)
forall (age :: Age). Functor (Tracked age)
forall (age :: Age). Foldable (Tracked age)
forall (age :: Age) (m :: * -> *) a.
Monad m =>
Tracked age (m a) -> m (Tracked age a)
forall (age :: Age) (f :: * -> *) a.
Applicative f =>
Tracked age (f a) -> f (Tracked age a)
forall (age :: Age) (m :: * -> *) a b.
Monad m =>
(a -> m b) -> Tracked age a -> m (Tracked age b)
forall (age :: Age) (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> Tracked age a -> f (Tracked age b)
forall (t :: * -> *).
Functor t
-> Foldable t
-> (forall (f :: * -> *) a b.
    Applicative f =>
    (a -> f b) -> t a -> f (t b))
-> (forall (f :: * -> *) a. Applicative f => t (f a) -> f (t a))
-> (forall (m :: * -> *) a b.
    Monad m =>
    (a -> m b) -> t a -> m (t b))
-> (forall (m :: * -> *) a. Monad m => t (m a) -> m (t a))
-> Traversable t
forall (m :: * -> *) a.
Monad m =>
Tracked age (m a) -> m (Tracked age a)
forall (f :: * -> *) a.
Applicative f =>
Tracked age (f a) -> f (Tracked age a)
forall (m :: * -> *) a b.
Monad m =>
(a -> m b) -> Tracked age a -> m (Tracked age b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> Tracked age a -> f (Tracked age b)
sequence :: Tracked age (m a) -> m (Tracked age a)
$csequence :: forall (age :: Age) (m :: * -> *) a.
Monad m =>
Tracked age (m a) -> m (Tracked age a)
mapM :: (a -> m b) -> Tracked age a -> m (Tracked age b)
$cmapM :: forall (age :: Age) (m :: * -> *) a b.
Monad m =>
(a -> m b) -> Tracked age a -> m (Tracked age b)
sequenceA :: Tracked age (f a) -> f (Tracked age a)
$csequenceA :: forall (age :: Age) (f :: * -> *) a.
Applicative f =>
Tracked age (f a) -> f (Tracked age a)
traverse :: (a -> f b) -> Tracked age a -> f (Tracked age b)
$ctraverse :: forall (age :: Age) (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> Tracked age a -> f (Tracked age b)
$cp2Traversable :: forall (age :: Age). Foldable (Tracked age)
$cp1Traversable :: forall (age :: Age). Functor (Tracked age)
Traversable)
  deriving newtype (Tracked age a -> Tracked age a -> Bool
(Tracked age a -> Tracked age a -> Bool)
-> (Tracked age a -> Tracked age a -> Bool) -> Eq (Tracked age a)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall (age :: Age) a.
Eq a =>
Tracked age a -> Tracked age a -> Bool
/= :: Tracked age a -> Tracked age a -> Bool
$c/= :: forall (age :: Age) a.
Eq a =>
Tracked age a -> Tracked age a -> Bool
== :: Tracked age a -> Tracked age a -> Bool
$c== :: forall (age :: Age) a.
Eq a =>
Tracked age a -> Tracked age a -> Bool
Eq, Eq (Tracked age a)
Eq (Tracked age a)
-> (Tracked age a -> Tracked age a -> Ordering)
-> (Tracked age a -> Tracked age a -> Bool)
-> (Tracked age a -> Tracked age a -> Bool)
-> (Tracked age a -> Tracked age a -> Bool)
-> (Tracked age a -> Tracked age a -> Bool)
-> (Tracked age a -> Tracked age a -> Tracked age a)
-> (Tracked age a -> Tracked age a -> Tracked age a)
-> Ord (Tracked age a)
Tracked age a -> Tracked age a -> Bool
Tracked age a -> Tracked age a -> Ordering
Tracked age a -> Tracked age a -> Tracked age a
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall (age :: Age) a. Ord a => Eq (Tracked age a)
forall (age :: Age) a.
Ord a =>
Tracked age a -> Tracked age a -> Bool
forall (age :: Age) a.
Ord a =>
Tracked age a -> Tracked age a -> Ordering
forall (age :: Age) a.
Ord a =>
Tracked age a -> Tracked age a -> Tracked age a
min :: Tracked age a -> Tracked age a -> Tracked age a
$cmin :: forall (age :: Age) a.
Ord a =>
Tracked age a -> Tracked age a -> Tracked age a
max :: Tracked age a -> Tracked age a -> Tracked age a
$cmax :: forall (age :: Age) a.
Ord a =>
Tracked age a -> Tracked age a -> Tracked age a
>= :: Tracked age a -> Tracked age a -> Bool
$c>= :: forall (age :: Age) a.
Ord a =>
Tracked age a -> Tracked age a -> Bool
> :: Tracked age a -> Tracked age a -> Bool
$c> :: forall (age :: Age) a.
Ord a =>
Tracked age a -> Tracked age a -> Bool
<= :: Tracked age a -> Tracked age a -> Bool
$c<= :: forall (age :: Age) a.
Ord a =>
Tracked age a -> Tracked age a -> Bool
< :: Tracked age a -> Tracked age a -> Bool
$c< :: forall (age :: Age) a.
Ord a =>
Tracked age a -> Tracked age a -> Bool
compare :: Tracked age a -> Tracked age a -> Ordering
$ccompare :: forall (age :: Age) a.
Ord a =>
Tracked age a -> Tracked age a -> Ordering
$cp1Ord :: forall (age :: Age) a. Ord a => Eq (Tracked age a)
Ord, Int -> Tracked age a -> ShowS
[Tracked age a] -> ShowS
Tracked age a -> String
(Int -> Tracked age a -> ShowS)
-> (Tracked age a -> String)
-> ([Tracked age a] -> ShowS)
-> Show (Tracked age a)
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall (age :: Age) a. Show a => Int -> Tracked age a -> ShowS
forall (age :: Age) a. Show a => [Tracked age a] -> ShowS
forall (age :: Age) a. Show a => Tracked age a -> String
showList :: [Tracked age a] -> ShowS
$cshowList :: forall (age :: Age) a. Show a => [Tracked age a] -> ShowS
show :: Tracked age a -> String
$cshow :: forall (age :: Age) a. Show a => Tracked age a -> String
showsPrec :: Int -> Tracked age a -> ShowS
$cshowsPrec :: forall (age :: Age) a. Show a => Int -> Tracked age a -> ShowS
Show, ReadPrec [Tracked age a]
ReadPrec (Tracked age a)
Int -> ReadS (Tracked age a)
ReadS [Tracked age a]
(Int -> ReadS (Tracked age a))
-> ReadS [Tracked age a]
-> ReadPrec (Tracked age a)
-> ReadPrec [Tracked age a]
-> Read (Tracked age a)
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
forall (age :: Age) a. Read a => ReadPrec [Tracked age a]
forall (age :: Age) a. Read a => ReadPrec (Tracked age a)
forall (age :: Age) a. Read a => Int -> ReadS (Tracked age a)
forall (age :: Age) a. Read a => ReadS [Tracked age a]
readListPrec :: ReadPrec [Tracked age a]
$creadListPrec :: forall (age :: Age) a. Read a => ReadPrec [Tracked age a]
readPrec :: ReadPrec (Tracked age a)
$creadPrec :: forall (age :: Age) a. Read a => ReadPrec (Tracked age a)
readList :: ReadS [Tracked age a]
$creadList :: forall (age :: Age) a. Read a => ReadS [Tracked age a]
readsPrec :: Int -> ReadS (Tracked age a)
$creadsPrec :: forall (age :: Age) a. Read a => Int -> ReadS (Tracked age a)
Read, [Tracked age a] -> Encoding
[Tracked age a] -> Value
Tracked age a -> Encoding
Tracked age a -> Value
(Tracked age a -> Value)
-> (Tracked age a -> Encoding)
-> ([Tracked age a] -> Value)
-> ([Tracked age a] -> Encoding)
-> ToJSON (Tracked age a)
forall a.
(a -> Value)
-> (a -> Encoding)
-> ([a] -> Value)
-> ([a] -> Encoding)
-> ToJSON a
forall (age :: Age) a. ToJSON a => [Tracked age a] -> Encoding
forall (age :: Age) a. ToJSON a => [Tracked age a] -> Value
forall (age :: Age) a. ToJSON a => Tracked age a -> Encoding
forall (age :: Age) a. ToJSON a => Tracked age a -> Value
toEncodingList :: [Tracked age a] -> Encoding
$ctoEncodingList :: forall (age :: Age) a. ToJSON a => [Tracked age a] -> Encoding
toJSONList :: [Tracked age a] -> Value
$ctoJSONList :: forall (age :: Age) a. ToJSON a => [Tracked age a] -> Value
toEncoding :: Tracked age a -> Encoding
$ctoEncoding :: forall (age :: Age) a. ToJSON a => Tracked age a -> Encoding
toJSON :: Tracked age a -> Value
$ctoJSON :: forall (age :: Age) a. ToJSON a => Tracked age a -> Value
ToJSON, Value -> Parser [Tracked age a]
Value -> Parser (Tracked age a)
(Value -> Parser (Tracked age a))
-> (Value -> Parser [Tracked age a]) -> FromJSON (Tracked age a)
forall a.
(Value -> Parser a) -> (Value -> Parser [a]) -> FromJSON a
forall (age :: Age) a.
FromJSON a =>
Value -> Parser [Tracked age a]
forall (age :: Age) a.
FromJSON a =>
Value -> Parser (Tracked age a)
parseJSONList :: Value -> Parser [Tracked age a]
$cparseJSONList :: forall (age :: Age) a.
FromJSON a =>
Value -> Parser [Tracked age a]
parseJSON :: Value -> Parser (Tracked age a)
$cparseJSON :: forall (age :: Age) a.
FromJSON a =>
Value -> Parser (Tracked age a)
FromJSON, Tracked age a -> ()
(Tracked age a -> ()) -> NFData (Tracked age a)
forall a. (a -> ()) -> NFData a
forall (age :: Age) a. NFData a => Tracked age a -> ()
rnf :: Tracked age a -> ()
$crnf :: forall (age :: Age) a. NFData a => Tracked age a -> ()
NFData)
  deriving (Functor (Tracked age)
a -> Tracked age a
Functor (Tracked age)
-> (forall a. a -> Tracked age a)
-> (forall a b.
    Tracked age (a -> b) -> Tracked age a -> Tracked age b)
-> (forall a b c.
    (a -> b -> c) -> Tracked age a -> Tracked age b -> Tracked age c)
-> (forall a b. Tracked age a -> Tracked age b -> Tracked age b)
-> (forall a b. Tracked age a -> Tracked age b -> Tracked age a)
-> Applicative (Tracked age)
Tracked age a -> Tracked age b -> Tracked age b
Tracked age a -> Tracked age b -> Tracked age a
Tracked age (a -> b) -> Tracked age a -> Tracked age b
(a -> b -> c) -> Tracked age a -> Tracked age b -> Tracked age c
forall a. a -> Tracked age a
forall a b. Tracked age a -> Tracked age b -> Tracked age a
forall a b. Tracked age a -> Tracked age b -> Tracked age b
forall a b. Tracked age (a -> b) -> Tracked age a -> Tracked age b
forall a b c.
(a -> b -> c) -> Tracked age a -> Tracked age b -> Tracked age c
forall (age :: Age). Functor (Tracked age)
forall (age :: Age) a. a -> Tracked age a
forall (age :: Age) a b.
Tracked age a -> Tracked age b -> Tracked age a
forall (age :: Age) a b.
Tracked age a -> Tracked age b -> Tracked age b
forall (age :: Age) a b.
Tracked age (a -> b) -> Tracked age a -> Tracked age b
forall (age :: Age) a b c.
(a -> b -> c) -> Tracked age a -> Tracked age b -> Tracked age c
forall (f :: * -> *).
Functor f
-> (forall a. a -> f a)
-> (forall a b. f (a -> b) -> f a -> f b)
-> (forall a b c. (a -> b -> c) -> f a -> f b -> f c)
-> (forall a b. f a -> f b -> f b)
-> (forall a b. f a -> f b -> f a)
-> Applicative f
<* :: Tracked age a -> Tracked age b -> Tracked age a
$c<* :: forall (age :: Age) a b.
Tracked age a -> Tracked age b -> Tracked age a
*> :: Tracked age a -> Tracked age b -> Tracked age b
$c*> :: forall (age :: Age) a b.
Tracked age a -> Tracked age b -> Tracked age b
liftA2 :: (a -> b -> c) -> Tracked age a -> Tracked age b -> Tracked age c
$cliftA2 :: forall (age :: Age) a b c.
(a -> b -> c) -> Tracked age a -> Tracked age b -> Tracked age c
<*> :: Tracked age (a -> b) -> Tracked age a -> Tracked age b
$c<*> :: forall (age :: Age) a b.
Tracked age (a -> b) -> Tracked age a -> Tracked age b
pure :: a -> Tracked age a
$cpure :: forall (age :: Age) a. a -> Tracked age a
$cp1Applicative :: forall (age :: Age). Functor (Tracked age)
Applicative, Applicative (Tracked age)
a -> Tracked age a
Applicative (Tracked age)
-> (forall a b.
    Tracked age a -> (a -> Tracked age b) -> Tracked age b)
-> (forall a b. Tracked age a -> Tracked age b -> Tracked age b)
-> (forall a. a -> Tracked age a)
-> Monad (Tracked age)
Tracked age a -> (a -> Tracked age b) -> Tracked age b
Tracked age a -> Tracked age b -> Tracked age b
forall a. a -> Tracked age a
forall a b. Tracked age a -> Tracked age b -> Tracked age b
forall a b. Tracked age a -> (a -> Tracked age b) -> Tracked age b
forall (age :: Age). Applicative (Tracked age)
forall (age :: Age) a. a -> Tracked age a
forall (age :: Age) a b.
Tracked age a -> Tracked age b -> Tracked age b
forall (age :: Age) a b.
Tracked age a -> (a -> Tracked age b) -> Tracked age b
forall (m :: * -> *).
Applicative m
-> (forall a b. m a -> (a -> m b) -> m b)
-> (forall a b. m a -> m b -> m b)
-> (forall a. a -> m a)
-> Monad m
return :: a -> Tracked age a
$creturn :: forall (age :: Age) a. a -> Tracked age a
>> :: Tracked age a -> Tracked age b -> Tracked age b
$c>> :: forall (age :: Age) a b.
Tracked age a -> Tracked age b -> Tracked age b
>>= :: Tracked age a -> (a -> Tracked age b) -> Tracked age b
$c>>= :: forall (age :: Age) a b.
Tracked age a -> (a -> Tracked age b) -> Tracked age b
$cp1Monad :: forall (age :: Age). Applicative (Tracked age)
Monad) via Identity


------------------------------------------------------------------------------
-- | Like 'P.PositionMapping', but with annotated ages for how 'Tracked' values
-- change. Use the 'Category' instance to compose 'PositionMapping's in order
-- to transform between values of different stale ages.
newtype PositionMap (from :: Age) (to :: Age) = PositionMap
  { PositionMap from to -> PositionMapping
getPositionMapping :: P.PositionMapping
  }

instance Category PositionMap where
  id :: PositionMap a a
id  = PositionMapping -> PositionMap a a
coerce PositionMapping
P.zeroMapping
  . :: PositionMap b c -> PositionMap a b -> PositionMap a c
(.) = (PositionDelta -> PositionDelta -> PositionDelta)
-> PositionMap b c -> PositionMap a b -> PositionMap a c
coerce PositionDelta -> PositionDelta -> PositionDelta
P.composeDelta


------------------------------------------------------------------------------
-- | Get a 'PositionMap' that runs in the opposite direction.
dualPositionMap :: PositionMap from to -> PositionMap to from
dualPositionMap :: PositionMap from to -> PositionMap to from
dualPositionMap (PositionMap (P.PositionMapping (P.PositionDelta Position -> PositionResult Position
from Position -> PositionResult Position
to))) =
  PositionMapping -> PositionMap to from
forall (from :: Age) (to :: Age).
PositionMapping -> PositionMap from to
PositionMap (PositionMapping -> PositionMap to from)
-> PositionMapping -> PositionMap to from
forall a b. (a -> b) -> a -> b
$ PositionDelta -> PositionMapping
P.PositionMapping (PositionDelta -> PositionMapping)
-> PositionDelta -> PositionMapping
forall a b. (a -> b) -> a -> b
$ (Position -> PositionResult Position)
-> (Position -> PositionResult Position) -> PositionDelta
P.PositionDelta Position -> PositionResult Position
to Position -> PositionResult Position
from


------------------------------------------------------------------------------
-- | A pair containing a @'Tracked' 'Stale'@ value, as well as
-- a 'PositionMapping' that will fast-forward values to the current age.
data TrackedStale a where
  TrackedStale
      :: Tracked (Stale s) a
      -> PositionMap (Stale s) Current
      -> TrackedStale a

instance Functor TrackedStale where
  fmap :: (a -> b) -> TrackedStale a -> TrackedStale b
fmap a -> b
f (TrackedStale Tracked ('Stale s) a
t PositionMap ('Stale s) 'Current
pm) = Tracked ('Stale s) b
-> PositionMap ('Stale s) 'Current -> TrackedStale b
forall s a.
Tracked ('Stale s) a
-> PositionMap ('Stale s) 'Current -> TrackedStale a
TrackedStale ((a -> b) -> Tracked ('Stale s) a -> Tracked ('Stale s) b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> b
f Tracked ('Stale s) a
t) PositionMap ('Stale s) 'Current
pm


untrackedStaleValue :: TrackedStale a -> a
untrackedStaleValue :: TrackedStale a -> a
untrackedStaleValue (TrackedStale Tracked ('Stale s) a
ta PositionMap ('Stale s) 'Current
_) = Tracked ('Stale s) a -> a
coerce Tracked ('Stale s) a
ta


------------------------------------------------------------------------------
-- | A class for which 'Tracked' values can be run across a 'PositionMapping'
-- to change their ages.
class MapAge a where
  {-# MINIMAL mapAgeFrom | mapAgeTo #-}
  mapAgeFrom :: PositionMap from to -> Tracked to   a -> Maybe (Tracked from a)
  mapAgeFrom = PositionMap to from -> Tracked to a -> Maybe (Tracked from a)
forall a (from :: Age) (to :: Age).
MapAge a =>
PositionMap from to -> Tracked from a -> Maybe (Tracked to a)
mapAgeTo (PositionMap to from -> Tracked to a -> Maybe (Tracked from a))
-> (PositionMap from to -> PositionMap to from)
-> PositionMap from to
-> Tracked to a
-> Maybe (Tracked from a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PositionMap from to -> PositionMap to from
forall (from :: Age) (to :: Age).
PositionMap from to -> PositionMap to from
dualPositionMap

  mapAgeTo   :: PositionMap from to -> Tracked from a -> Maybe (Tracked to   a)
  mapAgeTo = PositionMap to from -> Tracked from a -> Maybe (Tracked to a)
forall a (from :: Age) (to :: Age).
MapAge a =>
PositionMap from to -> Tracked to a -> Maybe (Tracked from a)
mapAgeFrom (PositionMap to from -> Tracked from a -> Maybe (Tracked to a))
-> (PositionMap from to -> PositionMap to from)
-> PositionMap from to
-> Tracked from a
-> Maybe (Tracked to a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PositionMap from to -> PositionMap to from
forall (from :: Age) (to :: Age).
PositionMap from to -> PositionMap to from
dualPositionMap


instance MapAge Range where
  mapAgeFrom :: PositionMap from to
-> Tracked to Range -> Maybe (Tracked from Range)
mapAgeFrom = (PositionMapping -> Range -> Maybe Range)
-> PositionMap from to
-> Tracked to Range
-> Maybe (Tracked from Range)
coerce PositionMapping -> Range -> Maybe Range
P.fromCurrentRange
  mapAgeTo :: PositionMap from to
-> Tracked from Range -> Maybe (Tracked to Range)
mapAgeTo   = (PositionMapping -> Range -> Maybe Range)
-> PositionMap from to
-> Tracked from Range
-> Maybe (Tracked to Range)
coerce PositionMapping -> Range -> Maybe Range
P.toCurrentRange


instance MapAge RealSrcSpan where
  mapAgeFrom :: PositionMap from to
-> Tracked to RealSrcSpan -> Maybe (Tracked from RealSrcSpan)
mapAgeFrom =
    (FastString -> Range -> RealSrcSpan)
-> (RealSrcSpan -> (FastString, Range))
-> (Tracked to Range -> Maybe (Tracked from Range))
-> Tracked to RealSrcSpan
-> Maybe (Tracked from RealSrcSpan)
forall c a b (from :: Age) (to :: Age).
(c -> a -> b)
-> (b -> (c, a))
-> (Tracked from a -> Maybe (Tracked to a))
-> Tracked from b
-> Maybe (Tracked to b)
invMapAge (\FastString
fs -> NormalizedFilePath -> Range -> RealSrcSpan
rangeToRealSrcSpan (String -> NormalizedFilePath
forall a. IsString a => String -> a
fromString (String -> NormalizedFilePath) -> String -> NormalizedFilePath
forall a b. (a -> b) -> a -> b
$ FastString -> String
FS.unpackFS FastString
fs))
              (RealSrcSpan -> FastString
srcSpanFile (RealSrcSpan -> FastString)
-> (RealSrcSpan -> Range) -> RealSrcSpan -> (FastString, Range)
forall (a :: * -> * -> *) b c c'.
Arrow a =>
a b c -> a b c' -> a b (c, c')
&&& RealSrcSpan -> Range
realSrcSpanToRange)
      ((Tracked to Range -> Maybe (Tracked from Range))
 -> Tracked to RealSrcSpan -> Maybe (Tracked from RealSrcSpan))
-> (PositionMap from to
    -> Tracked to Range -> Maybe (Tracked from Range))
-> PositionMap from to
-> Tracked to RealSrcSpan
-> Maybe (Tracked from RealSrcSpan)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.  PositionMap from to
-> Tracked to Range -> Maybe (Tracked from Range)
forall a (from :: Age) (to :: Age).
MapAge a =>
PositionMap from to -> Tracked to a -> Maybe (Tracked from a)
mapAgeFrom


------------------------------------------------------------------------------
-- | Helper function for deriving 'MapAge' for values in terms of other
-- instances.
invMapAge
    :: (c -> a -> b)
    -> (b -> (c, a))
    -> (Tracked from a -> Maybe (Tracked to a))
    -> Tracked from b
    -> Maybe (Tracked to b)
invMapAge :: (c -> a -> b)
-> (b -> (c, a))
-> (Tracked from a -> Maybe (Tracked to a))
-> Tracked from b
-> Maybe (Tracked to b)
invMapAge c -> a -> b
to b -> (c, a)
from Tracked from a -> Maybe (Tracked to a)
f Tracked from b
t =
  let (c
c, a
t') = Tracked from (c, a) -> (c, a)
forall (age :: Age) a. Tracked age a -> a
unTrack (Tracked from (c, a) -> (c, a)) -> Tracked from (c, a) -> (c, a)
forall a b. (a -> b) -> a -> b
$ (b -> (c, a)) -> Tracked from b -> Tracked from (c, a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap b -> (c, a)
from Tracked from b
t
   in (Tracked to a -> Tracked to b)
-> Maybe (Tracked to a) -> Maybe (Tracked to b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((a -> b) -> Tracked to a -> Tracked to b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((a -> b) -> Tracked to a -> Tracked to b)
-> (a -> b) -> Tracked to a -> Tracked to b
forall a b. (a -> b) -> a -> b
$ c -> a -> b
to c
c) (Maybe (Tracked to a) -> Maybe (Tracked to b))
-> Maybe (Tracked to a) -> Maybe (Tracked to b)
forall a b. (a -> b) -> a -> b
$ Tracked from a -> Maybe (Tracked to a)
f (Tracked from a -> Maybe (Tracked to a))
-> Tracked from a -> Maybe (Tracked to a)
forall a b. (a -> b) -> a -> b
$ a -> Tracked from a
forall (age :: Age) a. a -> Tracked age a
UnsafeTracked a
t'


unsafeMkCurrent :: age ->  Tracked 'Current age
unsafeMkCurrent :: age -> Tracked 'Current age
unsafeMkCurrent = age -> Tracked 'Current age
coerce


unsafeMkStale :: age -> Tracked (Stale s) age
unsafeMkStale :: age -> Tracked ('Stale s) age
unsafeMkStale = age -> Tracked ('Stale s) age
coerce


unsafeCopyAge :: Tracked age a -> b -> Tracked age b
unsafeCopyAge :: Tracked age a -> b -> Tracked age b
unsafeCopyAge Tracked age a
_ = b -> Tracked age b
coerce


-- | Request a Rule result, it not available return the last computed result, if any, which may be stale
useWithStale :: IdeRule k v
    => k -> NormalizedFilePath -> Action (Maybe (TrackedStale v))
useWithStale :: k -> NormalizedFilePath -> Action (Maybe (TrackedStale v))
useWithStale k
key NormalizedFilePath
file = do
  Maybe (v, PositionMapping)
x <- k -> NormalizedFilePath -> Action (Maybe (v, PositionMapping))
forall k v.
IdeRule k v =>
k -> NormalizedFilePath -> Action (Maybe (v, PositionMapping))
IDE.useWithStale k
key NormalizedFilePath
file
  pure $ Maybe (v, PositionMapping)
x Maybe (v, PositionMapping)
-> ((v, PositionMapping) -> TrackedStale v)
-> Maybe (TrackedStale v)
forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&> \(v
v, PositionMapping
pm) ->
    Tracked ('Stale Any) v
-> PositionMap ('Stale Any) 'Current -> TrackedStale v
forall s a.
Tracked ('Stale s) a
-> PositionMap ('Stale s) 'Current -> TrackedStale a
TrackedStale (v -> Tracked ('Stale Any) v
coerce v
v) (PositionMapping -> PositionMap ('Stale Any) 'Current
coerce PositionMapping
pm)

-- | Request a Rule result, it not available return the last computed result which may be stale.
--   Errors out if none available.
useWithStale_ :: IdeRule k v
    => k -> NormalizedFilePath -> Action (TrackedStale v)
useWithStale_ :: k -> NormalizedFilePath -> Action (TrackedStale v)
useWithStale_ k
key NormalizedFilePath
file = do
  (v
v, PositionMapping
pm) <- k -> NormalizedFilePath -> Action (v, PositionMapping)
forall k v.
IdeRule k v =>
k -> NormalizedFilePath -> Action (v, PositionMapping)
IDE.useWithStale_ k
key NormalizedFilePath
file
  TrackedStale v -> Action (TrackedStale v)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (TrackedStale v -> Action (TrackedStale v))
-> TrackedStale v -> Action (TrackedStale v)
forall a b. (a -> b) -> a -> b
$ Tracked ('Stale Any) v
-> PositionMap ('Stale Any) 'Current -> TrackedStale v
forall s a.
Tracked ('Stale s) a
-> PositionMap ('Stale s) 'Current -> TrackedStale a
TrackedStale (v -> Tracked ('Stale Any) v
coerce v
v) (PositionMapping -> PositionMap ('Stale Any) 'Current
coerce PositionMapping
pm)