module Patrol.Type.Frame
  ( Frame(..)
  , fromSrcLoc
  ) where

import qualified Data.Aeson as Aeson
import qualified Data.Maybe as Maybe
import qualified Data.Text as Text
import qualified GHC.Stack as Stack
import qualified Patrol.Utility.Json as Json

-- | <https://develop.sentry.dev/sdk/event-payloads/stacktrace/#frame-attributes>
data Frame = Frame
  { Frame -> Maybe Int
colno :: Maybe Int
  , Frame -> Maybe Text
filename :: Maybe Text.Text
  , Frame -> Text
function :: Text.Text
  , Frame -> Maybe Int
lineno :: Maybe Int
  , Frame -> Maybe Text
module_ :: Maybe Text.Text
  , Frame -> Maybe Text
package :: Maybe Text.Text
  } deriving (Frame -> Frame -> Bool
(Frame -> Frame -> Bool) -> (Frame -> Frame -> Bool) -> Eq Frame
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Frame -> Frame -> Bool
$c/= :: Frame -> Frame -> Bool
== :: Frame -> Frame -> Bool
$c== :: Frame -> Frame -> Bool
Eq, Int -> Frame -> ShowS
[Frame] -> ShowS
Frame -> String
(Int -> Frame -> ShowS)
-> (Frame -> String) -> ([Frame] -> ShowS) -> Show Frame
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Frame] -> ShowS
$cshowList :: [Frame] -> ShowS
show :: Frame -> String
$cshow :: Frame -> String
showsPrec :: Int -> Frame -> ShowS
$cshowsPrec :: Int -> Frame -> ShowS
Show)

instance Aeson.ToJSON Frame where
  toJSON :: Frame -> Value
toJSON Frame
frame = [Pair] -> Value
Aeson.object ([Pair] -> Value) -> [Pair] -> Value
forall a b. (a -> b) -> a -> b
$ [Maybe Pair] -> [Pair]
forall a. [Maybe a] -> [a]
Maybe.catMaybes
    [ String -> Int -> Pair
forall value pair.
(ToJSON value, KeyValue pair) =>
String -> value -> pair
Json.pair String
"colno" (Int -> Pair) -> Maybe Int -> Maybe Pair
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Frame -> Maybe Int
colno Frame
frame
    , String -> Text -> Pair
forall value pair.
(ToJSON value, KeyValue pair) =>
String -> value -> pair
Json.pair String
"filename" (Text -> Pair) -> Maybe Text -> Maybe Pair
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Frame -> Maybe Text
filename Frame
frame
    , Pair -> Maybe Pair
forall a. a -> Maybe a
Just (Pair -> Maybe Pair) -> (Text -> Pair) -> Text -> Maybe Pair
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Text -> Pair
forall value pair.
(ToJSON value, KeyValue pair) =>
String -> value -> pair
Json.pair String
"function" (Text -> Maybe Pair) -> Text -> Maybe Pair
forall a b. (a -> b) -> a -> b
$ Frame -> Text
function Frame
frame
    , String -> Int -> Pair
forall value pair.
(ToJSON value, KeyValue pair) =>
String -> value -> pair
Json.pair String
"lineno" (Int -> Pair) -> Maybe Int -> Maybe Pair
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Frame -> Maybe Int
lineno Frame
frame
    , String -> Text -> Pair
forall value pair.
(ToJSON value, KeyValue pair) =>
String -> value -> pair
Json.pair String
"module" (Text -> Pair) -> Maybe Text -> Maybe Pair
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Frame -> Maybe Text
module_ Frame
frame
    , String -> Text -> Pair
forall value pair.
(ToJSON value, KeyValue pair) =>
String -> value -> pair
Json.pair String
"package" (Text -> Pair) -> Maybe Text -> Maybe Pair
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Frame -> Maybe Text
package Frame
frame
    ]

fromSrcLoc :: String -> Stack.SrcLoc -> Frame
fromSrcLoc :: String -> SrcLoc -> Frame
fromSrcLoc String
function SrcLoc
srcLoc = Frame :: Maybe Int
-> Maybe Text
-> Text
-> Maybe Int
-> Maybe Text
-> Maybe Text
-> Frame
Frame
  { colno :: Maybe Int
colno = Int -> Maybe Int
forall a. a -> Maybe a
Just (Int -> Maybe Int) -> Int -> Maybe Int
forall a b. (a -> b) -> a -> b
$ SrcLoc -> Int
Stack.srcLocStartCol SrcLoc
srcLoc
  , filename :: Maybe Text
filename = Text -> Maybe Text
forall a. a -> Maybe a
Just (Text -> Maybe Text) -> (String -> Text) -> String -> Maybe Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Text
Text.pack (String -> Maybe Text) -> String -> Maybe Text
forall a b. (a -> b) -> a -> b
$ SrcLoc -> String
Stack.srcLocFile SrcLoc
srcLoc
  , function :: Text
function = String -> Text
Text.pack String
function
  , lineno :: Maybe Int
lineno = Int -> Maybe Int
forall a. a -> Maybe a
Just (Int -> Maybe Int) -> Int -> Maybe Int
forall a b. (a -> b) -> a -> b
$ SrcLoc -> Int
Stack.srcLocStartLine SrcLoc
srcLoc
  , module_ :: Maybe Text
module_ = Text -> Maybe Text
forall a. a -> Maybe a
Just (Text -> Maybe Text) -> (String -> Text) -> String -> Maybe Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Text
Text.pack (String -> Maybe Text) -> String -> Maybe Text
forall a b. (a -> b) -> a -> b
$ SrcLoc -> String
Stack.srcLocModule SrcLoc
srcLoc
  , package :: Maybe Text
package = Text -> Maybe Text
forall a. a -> Maybe a
Just (Text -> Maybe Text) -> (String -> Text) -> String -> Maybe Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Text
Text.pack (String -> Maybe Text) -> String -> Maybe Text
forall a b. (a -> b) -> a -> b
$ SrcLoc -> String
Stack.srcLocPackage SrcLoc
srcLoc
  }