src/Importify/ParseException.hs
-- | This module contains data type for parsing exception and pretty
-- formatting of such exceptions.
module Importify.ParseException
( ModuleParseException (..)
, eitherParseResult
, reportErrorsIfAny
, setMpeFile
) where
import Universum
import Fmt (Builder, blockListF, build, indentF, (+|), (|+))
import Language.Haskell.Exts (ParseResult (..), SrcLoc (srcFilename),
prettyPrint)
import Extended.Data.Str (charWrap, wordWrap)
import Extended.System.Wlog (printWarning)
data ModuleParseException = MPE !SrcLoc !String
deriving (Show)
instance Exception ModuleParseException
instance Buildable ModuleParseException where
build (MPE loc reason) = "Location:\n"
+| indentF 4 (build $ charWrap 80 $ prettyPrint loc)
|+ "Reason:\n"
+| indentF 4 (build $ wordWrap 80 reason)
|+ ""
-- | Updates file name of error location. Sometimes error location
-- looks like @- Location: : -1: -1@ which is not very helpful.
setMpeFile :: FilePath -> ModuleParseException -> ModuleParseException
setMpeFile modulePath (MPE loc msg) = MPE (loc {srcFilename = modulePath}) msg
-- | Converts 'ParseResult' into 'Either' making error look pretty.
eitherParseResult :: ParseResult res
-> Either ModuleParseException res
eitherParseResult (ParseOk res) = Right res
eitherParseResult (ParseFailed loc reason) = Left $ MPE loc reason
-- | Pretty printing 'NonEmpty' list of errors in really nice way.
prettyParseErrors :: Text -> NonEmpty ModuleParseException -> Text
prettyParseErrors libName exceptions =
"Next errors occured during caching of package: "+|libName|+"\n"
+| indentF 4 (blockListF exceptions) |+ ""
-- | Prints parse errors if list of errors is not empty.
reportErrorsIfAny :: [ModuleParseException] -> Text -> IO ()
reportErrorsIfAny exceptions libName = whenNotNull exceptions $
printWarning . prettyParseErrors libName