{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE TemplateHaskell #-}
module Network.Bugsnag.StackFrame
( attachBugsnagCode
, currentStackFrame
) where
import Prelude
import Data.Bugsnag
import Data.HashMap.Strict (HashMap)
import qualified Data.HashMap.Strict as HashMap
import Data.Text (Text, pack, unpack)
import Instances.TH.Lift ()
import Language.Haskell.TH.Syntax
import Network.Bugsnag.CodeIndex
attachBugsnagCode :: CodeIndex -> StackFrame -> StackFrame
attachBugsnagCode :: CodeIndex -> StackFrame -> StackFrame
attachBugsnagCode CodeIndex
index StackFrame
sf = StackFrame
sf
{ stackFrame_code :: Maybe (HashMap Int Text)
stackFrame_code = FilePath -> Int -> CodeIndex -> Maybe (HashMap Int Text)
findBugsnagCode
(Text -> FilePath
unpack (Text -> FilePath) -> Text -> FilePath
forall a b. (a -> b) -> a -> b
$ StackFrame -> Text
stackFrame_file StackFrame
sf)
(StackFrame -> Int
stackFrame_lineNumber StackFrame
sf)
CodeIndex
index
}
findBugsnagCode :: FilePath -> Int -> CodeIndex -> Maybe (HashMap Int Text)
findBugsnagCode :: FilePath -> Int -> CodeIndex -> Maybe (HashMap Int Text)
findBugsnagCode FilePath
path Int
n = ([(Int, Text)] -> HashMap Int Text)
-> Maybe [(Int, Text)] -> Maybe (HashMap Int Text)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [(Int, Text)] -> HashMap Int Text
forall k v. (Eq k, Hashable k) => [(k, v)] -> HashMap k v
HashMap.fromList
(Maybe [(Int, Text)] -> Maybe (HashMap Int Text))
-> (CodeIndex -> Maybe [(Int, Text)])
-> CodeIndex
-> Maybe (HashMap Int Text)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> (Int, Int) -> CodeIndex -> Maybe [(Int, Text)]
findSourceRange FilePath
path (Int
begin, Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
3)
where
begin :: Int
begin
| Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
3 = Int
0
| Bool
otherwise = Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
3
currentStackFrame :: Q Exp
currentStackFrame :: Q Exp
currentStackFrame = [|locStackFrame $(qLocation >>= liftLoc)|]
locStackFrame :: Loc -> Text -> StackFrame
locStackFrame :: Loc -> Text -> StackFrame
locStackFrame (Loc FilePath
path FilePath
_ FilePath
_ (Int
ls, Int
cs) (Int, Int)
_) Text
func =
StackFrame
defaultStackFrame
{ stackFrame_file :: Text
stackFrame_file = FilePath -> Text
pack FilePath
path
, stackFrame_lineNumber :: Int
stackFrame_lineNumber = Int
ls
, stackFrame_columnNumber :: Maybe Int
stackFrame_columnNumber = Int -> Maybe Int
forall a. a -> Maybe a
Just Int
cs
, stackFrame_method :: Text
stackFrame_method = Text
func
, stackFrame_inProject :: Maybe Bool
stackFrame_inProject = Bool -> Maybe Bool
forall a. a -> Maybe a
Just Bool
True
, stackFrame_code :: Maybe (HashMap Int Text)
stackFrame_code = Maybe (HashMap Int Text)
forall a. Maybe a
Nothing
}
liftLoc :: Loc -> Q Exp
liftLoc :: Loc -> Q Exp
liftLoc (Loc FilePath
a FilePath
b FilePath
c (Int
d1, Int
d2) (Int
e1, Int
e2)) = [|Loc
$(lift a)
$(lift b)
$(lift c)
($(lift d1), $(lift d2))
($(lift e1), $(lift e2))
|]