-- | Hadolint GNU Format Output
--
-- See https://www.gnu.org/prep/standards/html_node/Errors.html for reference.

module Hadolint.Formatter.Gnu
  ( hWrite )
where


import Data.Text (Text, pack, unpack)
import Hadolint.Formatter.Format
import Hadolint.Rule (CheckFailure (..), RuleCode (..))
import System.IO
import Text.Megaparsec (TraversableStream)
import Text.Megaparsec.Error
import Text.Megaparsec.Stream (VisualStream)
import qualified Data.List.NonEmpty as NonEmpty

hWrite ::
  (VisualStream s, TraversableStream s, ShowErrorComponent e, Foldable f) =>
  Handle -> f (Result s e) -> IO ()
hWrite :: forall s e (f :: * -> *).
(VisualStream s, TraversableStream s, ShowErrorComponent e,
 Foldable f) =>
Handle -> f (Result s e) -> IO ()
hWrite Handle
handle = (Result s e -> IO ()) -> f (Result s e) -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ ( Handle -> Result s e -> IO ()
forall s e.
(VisualStream s, TraversableStream s, ShowErrorComponent e) =>
Handle -> Result s e -> IO ()
printResult Handle
handle )

printResult ::
  (VisualStream s, TraversableStream s, ShowErrorComponent e) =>
  Handle -> Result s e -> IO ()
printResult :: forall s e.
(VisualStream s, TraversableStream s, ShowErrorComponent e) =>
Handle -> Result s e -> IO ()
printResult Handle
handle (Result Text
filename Seq (ParseErrorBundle s e)
errors Failures
checks) =
  Handle -> Seq (ParseErrorBundle s e) -> IO ()
forall s e (f :: * -> *).
(VisualStream s, TraversableStream s, ShowErrorComponent e,
 Foldable f) =>
Handle -> f (ParseErrorBundle s e) -> IO ()
printErrors Handle
handle Seq (ParseErrorBundle s e)
errors IO () -> IO () -> IO ()
forall a b. IO a -> IO b -> IO b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Handle -> Text -> Failures -> IO ()
forall (f :: * -> *).
Foldable f =>
Handle -> Text -> f CheckFailure -> IO ()
printChecks Handle
handle Text
filename Failures
checks

printErrors ::
  (VisualStream s, TraversableStream s, ShowErrorComponent e, Foldable f) =>
  Handle -> f (ParseErrorBundle s e) -> IO ()
printErrors :: forall s e (f :: * -> *).
(VisualStream s, TraversableStream s, ShowErrorComponent e,
 Foldable f) =>
Handle -> f (ParseErrorBundle s e) -> IO ()
printErrors Handle
handle = (ParseErrorBundle s e -> IO ())
-> f (ParseErrorBundle s e) -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ ( Handle -> String -> IO ()
hPutStrLn Handle
handle (String -> IO ())
-> (ParseErrorBundle s e -> String)
-> ParseErrorBundle s e
-> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> String
unpack (Text -> String)
-> (ParseErrorBundle s e -> Text) -> ParseErrorBundle s e -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ParseErrorBundle s e -> Text
forall s e.
(VisualStream s, TraversableStream s, ShowErrorComponent e) =>
ParseErrorBundle s e -> Text
formatError )

printChecks :: (Foldable f) => Handle -> Text -> f CheckFailure -> IO ()
printChecks :: forall (f :: * -> *).
Foldable f =>
Handle -> Text -> f CheckFailure -> IO ()
printChecks Handle
handle Text
filename = (CheckFailure -> IO ()) -> f CheckFailure -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ ( Handle -> String -> IO ()
hPutStrLn Handle
handle (String -> IO ())
-> (CheckFailure -> String) -> CheckFailure -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> String
unpack (Text -> String)
-> (CheckFailure -> Text) -> CheckFailure -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> CheckFailure -> Text
formatCheck Text
filename )


formatError ::
  (VisualStream s, TraversableStream s, ShowErrorComponent e) =>
  ParseErrorBundle s e -> Text
formatError :: forall s e.
(VisualStream s, TraversableStream s, ShowErrorComponent e) =>
ParseErrorBundle s e -> Text
formatError err :: ParseErrorBundle s e
err@(ParseErrorBundle NonEmpty (ParseError s e)
e PosState s
_) =
  String -> Text
pack (String -> Text) -> String -> Text
forall a b. (a -> b) -> a -> b
$
    String
"hadolint:"
      String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String -> String
stripNewlines
          ( ParseErrorBundle s e -> String
forall s e. TraversableStream s => ParseErrorBundle s e -> String
errorPositionPretty ParseErrorBundle s e
err
              String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
": "
              String -> String -> String
forall a. Semigroup a => a -> a -> a
<> ParseError s e -> String
forall s e.
(VisualStream s, ShowErrorComponent e) =>
ParseError s e -> String
parseErrorTextPretty (NonEmpty (ParseError s e) -> ParseError s e
forall a. NonEmpty a -> a
NonEmpty.head NonEmpty (ParseError s e)
e)
          )


formatCheck :: Text -> CheckFailure -> Text
formatCheck :: Text -> CheckFailure -> Text
formatCheck Text
source (CheckFailure RuleCode
code DLSeverity
severity Text
message Linenumber
line) =
  Text
"hadolint:"
    Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
source
    Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
":"
    Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
pack (Linenumber -> String
forall a. Show a => a -> String
show Linenumber
line)
    Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
": "
    Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> RuleCode -> Text
unRuleCode RuleCode
code
    Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" "
    Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> DLSeverity -> Text
severityText DLSeverity
severity
    Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
": "
    Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
message