{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedStrings #-}

module Skeletest.Internal.Error (
  SkeletestError (..),
  skeletestPluginError,
  invariantViolation,
) where

import Data.List (dropWhileEnd)
import Data.Text (Text)
import Data.Text qualified as Text
import GHC.Utils.Panic (pgmError)
import UnliftIO.Exception (Exception (..))

data SkeletestError
  = TestInfoNotFound
  | CliFlagNotFound Text
  | FixtureCircularDependency [Text]
  | SnapshotFileCorrupted FilePath
  deriving (Int -> SkeletestError -> ShowS
[SkeletestError] -> ShowS
SkeletestError -> String
(Int -> SkeletestError -> ShowS)
-> (SkeletestError -> String)
-> ([SkeletestError] -> ShowS)
-> Show SkeletestError
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> SkeletestError -> ShowS
showsPrec :: Int -> SkeletestError -> ShowS
$cshow :: SkeletestError -> String
show :: SkeletestError -> String
$cshowList :: [SkeletestError] -> ShowS
showList :: [SkeletestError] -> ShowS
Show)

instance Exception SkeletestError where
  displayException :: SkeletestError -> String
displayException =
    Text -> String
Text.unpack (Text -> String)
-> (SkeletestError -> Text) -> SkeletestError -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. \case
      SkeletestError
TestInfoNotFound ->
        Text
"Could not find test info"
      CliFlagNotFound Text
name ->
        Text
"CLI flag '" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
name Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"' was not registered. Did you add it to cliFlags in Main.hs?"
      FixtureCircularDependency [Text]
fixtures ->
        Text
"Found circular dependency when resolving fixtures: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> [Text] -> Text
Text.intercalate Text
" -> " [Text]
fixtures
      SnapshotFileCorrupted String
fp ->
        Text
"Snapshot file was corrupted: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
Text.pack String
fp

-- | Throw a user error during compilation, e.g. during the preprocessor or plugin phases.
skeletestPluginError :: String -> a
skeletestPluginError :: forall a. String -> a
skeletestPluginError String
msg =
  String -> a
forall a. HasCallStack => String -> a
pgmError (String -> a) -> ([String] -> String) -> [String] -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Char -> Bool) -> ShowS
forall a. (a -> Bool) -> [a] -> [a]
dropWhileEnd (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'\n') ShowS -> ([String] -> String) -> [String] -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [String] -> String
unlines ([String] -> a) -> [String] -> a
forall a b. (a -> b) -> a -> b
$
    [ String
""
    , String
"******************** skeletest failure ********************"
    , String
msg
    ]

-- | Throw an error in a situation that should never happen, and indicates a bug.
invariantViolation :: String -> a
invariantViolation :: forall a. String -> a
invariantViolation String
msg =
  String -> a
forall a. HasCallStack => String -> a
error (String -> a) -> ([String] -> String) -> [String] -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [String] -> String
unlines ([String] -> a) -> [String] -> a
forall a b. (a -> b) -> a -> b
$
    [ String
"Invariant violation: " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
msg
    , String
"**** This is a skeletest bug. Please report it at https://github.com/brandonchinn178/skeletest/issues"
    ]