{-# LANGUAGE Safe #-}
{-# OPTIONS_GHC -Wno-orphans -Wno-missing-methods #-}
-- | The boundary between haskell-src-exts source locations and ReWire's native
--   'Annote'/'Span'. It lives in the HSE layer so the base annotation module
--   (ReWire.Annotation) and the diagnostics renderer (ReWire.Error) carry no
--   haskell-src-exts dependency: only modules that actually manipulate the
--   haskell-src-exts AST import this conversion glue.
module ReWire.HSE.SrcLoc () where

import ReWire.Annotation (Annote, Annotation (..), Span (..), srcAnnote, primSpan)

import Language.Haskell.Exts.SrcLoc
      ( SrcLoc, SrcInfo (..), SrcSpanInfo (..), SrcSpan (..)
      , noLoc, noInfoSpan, mkSrcSpan)

-- | Build an annotation from a haskell-src-exts source span.
instance Annotation SrcSpanInfo where
      toAnnote :: SrcSpanInfo -> Annote
toAnnote = SrcSpanInfo -> Annote
locAnnote

instance Annotation SrcLoc where
      toAnnote :: SrcLoc -> Annote
toAnnote SrcLoc
l = SrcSpanInfo -> Annote
locAnnote (SrcSpanInfo -> Annote) -> SrcSpanInfo -> Annote
forall a b. (a -> b) -> a -> b
$ SrcSpan -> SrcSpanInfo
noInfoSpan (SrcSpan -> SrcSpanInfo) -> SrcSpan -> SrcSpanInfo
forall a b. (a -> b) -> a -> b
$ SrcLoc -> SrcLoc -> SrcSpan
mkSrcSpan SrcLoc
l SrcLoc
l

locAnnote :: SrcSpanInfo -> Annote
locAnnote :: SrcSpanInfo -> Annote
locAnnote SrcSpanInfo
ssi = let Span FilePath
f (Int, Int)
s (Int, Int)
e = SrcSpanInfo -> Span
fromSrcSpanInfo SrcSpanInfo
ssi in FilePath -> (Int, Int) -> (Int, Int) -> Annote
srcAnnote FilePath
f (Int, Int)
s (Int, Int)
e

fromSrcSpanInfo :: SrcSpanInfo -> Span
fromSrcSpanInfo :: SrcSpanInfo -> Span
fromSrcSpanInfo (SrcSpanInfo (SrcSpan FilePath
f Int
sl Int
sc Int
el Int
ec) [SrcSpan]
_) = FilePath -> (Int, Int) -> (Int, Int) -> Span
Span FilePath
f (Int
sl, Int
sc) (Int
el, Int
ec)

spanSrcSpanInfo :: Span -> SrcSpanInfo
spanSrcSpanInfo :: Span -> SrcSpanInfo
spanSrcSpanInfo (Span FilePath
f (Int
sl, Int
sc) (Int
el, Int
ec)) = SrcSpan -> SrcSpanInfo
noInfoSpan (SrcSpan -> SrcSpanInfo) -> SrcSpan -> SrcSpanInfo
forall a b. (a -> b) -> a -> b
$ FilePath -> Int -> Int -> Int -> Int -> SrcSpan
SrcSpan FilePath
f Int
sl Int
sc Int
el Int
ec

noSpanInfo :: SrcSpanInfo
noSpanInfo :: SrcSpanInfo
noSpanInfo = SrcSpan -> SrcSpanInfo
noInfoSpan (SrcSpan -> SrcSpanInfo) -> SrcSpan -> SrcSpanInfo
forall a b. (a -> b) -> a -> b
$ SrcLoc -> SrcLoc -> SrcSpan
mkSrcSpan SrcLoc
noLoc SrcLoc
noLoc

-- | Recover a haskell-src-exts span for the haskell-src-exts machinery.
--   Locationless annotations map to 'noLoc'.
toSrcSpanInfo :: Annote -> SrcSpanInfo
toSrcSpanInfo :: Annote -> SrcSpanInfo
toSrcSpanInfo Annote
an = SrcSpanInfo -> (Span -> SrcSpanInfo) -> Maybe Span -> SrcSpanInfo
forall b a. b -> (a -> b) -> Maybe a -> b
maybe SrcSpanInfo
noSpanInfo Span -> SrcSpanInfo
spanSrcSpanInfo (Maybe Span -> SrcSpanInfo) -> Maybe Span -> SrcSpanInfo
forall a b. (a -> b) -> a -> b
$ Annote -> Maybe Span
primSpan Annote
an

instance SrcInfo Annote where
      toSrcInfo :: SrcLoc -> [SrcSpan] -> SrcLoc -> Annote
toSrcInfo SrcLoc
a [SrcSpan]
b SrcLoc
c = SrcSpanInfo -> Annote
locAnnote (SrcSpanInfo -> Annote) -> SrcSpanInfo -> Annote
forall a b. (a -> b) -> a -> b
$ SrcLoc -> [SrcSpan] -> SrcLoc -> SrcSpanInfo
forall si. SrcInfo si => SrcLoc -> [SrcSpan] -> SrcLoc -> si
toSrcInfo SrcLoc
a [SrcSpan]
b SrcLoc
c
      fromSrcInfo :: SrcSpanInfo -> Annote
fromSrcInfo     = SrcSpanInfo -> Annote
locAnnote (SrcSpanInfo -> Annote)
-> (SrcSpanInfo -> SrcSpanInfo) -> SrcSpanInfo -> Annote
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SrcSpanInfo -> SrcSpanInfo
forall si. SrcInfo si => SrcSpanInfo -> si
fromSrcInfo
      fileName :: Annote -> FilePath
fileName        = SrcSpanInfo -> FilePath
forall si. SrcInfo si => si -> FilePath
fileName (SrcSpanInfo -> FilePath)
-> (Annote -> SrcSpanInfo) -> Annote -> FilePath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Annote -> SrcSpanInfo
toSrcSpanInfo
      startLine :: Annote -> Int
startLine       = SrcSpanInfo -> Int
forall si. SrcInfo si => si -> Int
startLine (SrcSpanInfo -> Int) -> (Annote -> SrcSpanInfo) -> Annote -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Annote -> SrcSpanInfo
toSrcSpanInfo
      startColumn :: Annote -> Int
startColumn     = SrcSpanInfo -> Int
forall si. SrcInfo si => si -> Int
startColumn (SrcSpanInfo -> Int) -> (Annote -> SrcSpanInfo) -> Annote -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Annote -> SrcSpanInfo
toSrcSpanInfo