{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE LambdaCase #-}
module Hpack.Yaml (
-- | /__NOTE:__/ This module is exposed to allow integration of Hpack into
-- other tools.  It is not meant for general use by end users.  The following
-- caveats apply:
--
-- * The API is undocumented, consult the source instead.
--
-- * The exposed types and functions primarily serve Hpack's own needs, not
-- that of a public API.  Breaking changes can happen as Hpack evolves.
--
-- As an Hpack user you either want to use the @hpack@ executable or a build
-- tool that supports Hpack (e.g. @stack@ or @cabal2nix@).

  decodeYaml
, decodeYamlWithParseError
, ParseException
, formatYamlParseError
, formatWarning
, module Data.Aeson.Config.FromValue
) where

import           Imports

import           Data.Yaml hiding (decodeFile, decodeFileWithWarnings)
import           Data.Yaml.Include
import           Data.Yaml.Internal (Warning(..))
import           Data.Aeson.Config.FromValue
import           Data.Aeson.Config.Parser (fromAesonPath, formatPath)

decodeYaml :: FilePath -> IO (Either String ([String], Value))
decodeYaml :: FilePath -> IO (Either FilePath ([FilePath], Value))
decodeYaml FilePath
file = (ParseException -> FilePath)
-> Either ParseException ([FilePath], Value)
-> Either FilePath ([FilePath], Value)
forall a b c. (a -> b) -> Either a c -> Either b c
forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first (FilePath -> ParseException -> FilePath
formatYamlParseError FilePath
file) (Either ParseException ([FilePath], Value)
 -> Either FilePath ([FilePath], Value))
-> IO (Either ParseException ([FilePath], Value))
-> IO (Either FilePath ([FilePath], Value))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> FilePath -> IO (Either ParseException ([FilePath], Value))
decodeYamlWithParseError FilePath
file

decodeYamlWithParseError :: FilePath -> IO (Either ParseException ([String], Value))
decodeYamlWithParseError :: FilePath -> IO (Either ParseException ([FilePath], Value))
decodeYamlWithParseError FilePath
file = do
  Either ParseException ([Warning], Value)
result <- FilePath -> IO (Either ParseException ([Warning], Value))
forall a.
FromJSON a =>
FilePath -> IO (Either ParseException ([Warning], a))
decodeFileWithWarnings FilePath
file
  Either ParseException ([FilePath], Value)
-> IO (Either ParseException ([FilePath], Value))
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Either ParseException ([FilePath], Value)
 -> IO (Either ParseException ([FilePath], Value)))
-> Either ParseException ([FilePath], Value)
-> IO (Either ParseException ([FilePath], Value))
forall a b. (a -> b) -> a -> b
$ (([Warning], Value) -> ([FilePath], Value))
-> Either ParseException ([Warning], Value)
-> Either ParseException ([FilePath], Value)
forall a b.
(a -> b) -> Either ParseException a -> Either ParseException b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (([Warning] -> [FilePath])
-> ([Warning], Value) -> ([FilePath], Value)
forall a b c. (a -> b) -> (a, c) -> (b, c)
forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first ((Warning -> FilePath) -> [Warning] -> [FilePath]
forall a b. (a -> b) -> [a] -> [b]
map ((Warning -> FilePath) -> [Warning] -> [FilePath])
-> (Warning -> FilePath) -> [Warning] -> [FilePath]
forall a b. (a -> b) -> a -> b
$ FilePath -> Warning -> FilePath
formatWarning FilePath
file)) Either ParseException ([Warning], Value)
result

formatYamlParseError :: FilePath -> ParseException -> String
formatYamlParseError :: FilePath -> ParseException -> FilePath
formatYamlParseError FilePath
file ParseException
err = FilePath
file FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ case ParseException
err of
  AesonException FilePath
e -> FilePath
": " FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
e
  InvalidYaml (Just (YamlException FilePath
s)) -> FilePath
": " FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
s
  InvalidYaml (Just (YamlParseException{FilePath
YamlMark
yamlProblem :: FilePath
yamlContext :: FilePath
yamlProblemMark :: YamlMark
yamlProblem :: YamlException -> FilePath
yamlContext :: YamlException -> FilePath
yamlProblemMark :: YamlException -> YamlMark
..})) -> FilePath
":" FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ Int -> FilePath
forall a. Show a => a -> FilePath
show Int
yamlLine FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
":" FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ Int -> FilePath
forall a. Show a => a -> FilePath
show Int
yamlColumn FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
": " FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
yamlProblem FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
" " FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
yamlContext
    where YamlMark{Int
yamlLine :: Int
yamlColumn :: Int
yamlIndex :: Int
yamlIndex :: YamlMark -> Int
yamlLine :: YamlMark -> Int
yamlColumn :: YamlMark -> Int
..} = YamlMark
yamlProblemMark
  ParseException
_ -> FilePath
": " FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ ParseException -> FilePath
forall e. Exception e => e -> FilePath
displayException ParseException
err

formatWarning :: FilePath -> Warning -> String
formatWarning :: FilePath -> Warning -> FilePath
formatWarning FilePath
file = \ case
  DuplicateKey JSONPath
path -> FilePath
file FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
": Duplicate field " FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ JSONPath -> FilePath
formatPath (JSONPath -> JSONPath
fromAesonPath JSONPath
path)