{-# LANGUAGE ApplicativeDo #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}

module OptEnvConf.Lint
  ( LintError (..),
    LintErrorMessage (..),
    renderLintErrors,
    renderLintError,
    lintParser,
  )
where

import Control.Monad
import Control.Monad.Reader
import Data.Either
import Data.Foldable
import Data.List.NonEmpty (NonEmpty (..))
import qualified Data.List.NonEmpty as NE
import Data.Maybe
import qualified Data.Text as T
import GHC.Stack (SrcLoc, prettySrcLoc)
import OptEnvConf.Args
import OptEnvConf.Output
import OptEnvConf.Parser
import qualified OptEnvConf.Reader as OptEnvConf
import OptEnvConf.Setting
import OptEnvConf.Validation
import Text.Colour

data LintError = LintError
  { LintError -> Maybe SrcLoc
lintErrorSrcLoc :: !(Maybe SrcLoc),
    LintError -> LintErrorMessage
lintErrorMessage :: !LintErrorMessage
  }

data LintErrorMessage
  = LintErrorUndocumented
  | LintErrorEmptySetting
  | LintErrorDashInShort
  | LintErrorDashInLong !(NonEmpty Char)
  | LintErrorNoReaderForArgument
  | LintErrorNoMetavarForArgument
  | LintErrorNoReaderForOption
  | LintErrorNoDashedForOption
  | LintErrorNoMetavarForOption
  | LintErrorNoDashedForSwitch
  | LintErrorNoOptionOrSwitchForDashed
  | LintErrorNoReaderForEnvVar
  | LintErrorNoMetavarForEnvVar
  | LintErrorNoCommands
  | LintErrorUnknownDefaultCommand !String
  | LintErrorUnreadableExample !String
  | LintErrorConfigWithoutLoad
  | LintErrorManyInfinite

renderLintErrors :: NonEmpty LintError -> [Chunk]
renderLintErrors :: NonEmpty LintError -> [Chunk]
renderLintErrors =
  [[Chunk]] -> [Chunk]
unlinesChunks
    ([[Chunk]] -> [Chunk])
-> (NonEmpty LintError -> [[Chunk]])
-> NonEmpty LintError
-> [Chunk]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([Colour -> Chunk -> Chunk
fore Colour
red Chunk
"Setting parser is invalid:"] [Chunk] -> [[Chunk]] -> [[Chunk]]
forall a. a -> [a] -> [a]
:)
    ([[Chunk]] -> [[Chunk]])
-> (NonEmpty LintError -> [[Chunk]])
-> NonEmpty LintError
-> [[Chunk]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([Chunk] -> [Chunk]) -> [[Chunk]] -> [[Chunk]]
forall a b. (a -> b) -> [a] -> [b]
map (Chunk
"  " Chunk -> [Chunk] -> [Chunk]
forall a. a -> [a] -> [a]
:)
    ([[Chunk]] -> [[Chunk]])
-> (NonEmpty LintError -> [[Chunk]])
-> NonEmpty LintError
-> [[Chunk]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (LintError -> [[Chunk]]) -> NonEmpty LintError -> [[Chunk]]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (([] [Chunk] -> [[Chunk]] -> [[Chunk]]
forall a. a -> [a] -> [a]
:) ([[Chunk]] -> [[Chunk]])
-> (LintError -> [[Chunk]]) -> LintError -> [[Chunk]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LintError -> [[Chunk]]
renderLintError)

renderLintError :: LintError -> [[Chunk]]
renderLintError :: LintError -> [[Chunk]]
renderLintError LintError {Maybe SrcLoc
LintErrorMessage
lintErrorSrcLoc :: LintError -> Maybe SrcLoc
lintErrorMessage :: LintError -> LintErrorMessage
lintErrorSrcLoc :: Maybe SrcLoc
lintErrorMessage :: LintErrorMessage
..} =
  [[[Chunk]]] -> [[Chunk]]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
    [ [[Colour -> Chunk -> Chunk
fore Colour
red Chunk
"Invalid Setting:"]],
      case LintErrorMessage
lintErrorMessage of
        LintErrorMessage
LintErrorUndocumented ->
          [[Chunk
"missing ", Text -> Chunk
functionChunk Text
"help", Chunk
"."]]
        LintErrorMessage
LintErrorEmptySetting ->
          [[[Chunk]]] -> [[Chunk]]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
            [ [ [ Chunk
"This ",
                  Text -> Chunk
functionChunk Text
"setting",
                  Chunk
" parses nothing."
                ]
              ],
              [ [ Chunk
"Add an ",
                  Text -> Chunk
functionChunk Text
"argument",
                  Chunk
", ",
                  Text -> Chunk
functionChunk Text
"switch",
                  Chunk
", ",
                  Text -> Chunk
functionChunk Text
"option",
                  Chunk
", ",
                  Text -> Chunk
functionChunk Text
"env",
                  Chunk
", ",
                  Text -> Chunk
functionChunk Text
"conf",
                  Chunk
", or ",
                  Text -> Chunk
functionChunk Text
"value",
                  Chunk
"."
                ]
              ]
            ]
        LintErrorMessage
LintErrorDashInShort ->
          [ [Text -> Chunk
functionChunk Text
"short", Chunk
" may not contain a '-'."],
            [Chunk
"Found ", Text -> Chunk
functionChunk Text
"short", Chunk
" '-'."]
          ]
        LintErrorDashInLong NonEmpty Char
s ->
          [ [Text -> Chunk
functionChunk Text
"long", Chunk
" may not start with a '-'."],
            [Chunk
"Found ", Text -> Chunk
functionChunk Text
"long", Chunk
" ", Text -> Chunk
chunk (Text -> Chunk) -> Text -> Chunk
forall a b. (a -> b) -> a -> b
$ [Char] -> Text
T.pack ([Char] -> Text) -> [Char] -> Text
forall a b. (a -> b) -> a -> b
$ [Char] -> [Char]
forall a. Show a => a -> [Char]
show ([Char] -> [Char]) -> [Char] -> [Char]
forall a b. (a -> b) -> a -> b
$ NonEmpty Char -> [Char]
forall a. NonEmpty a -> [a]
NE.toList NonEmpty Char
s, Chunk
"."],
            [ Chunk
"Try ",
              Text -> Chunk
functionChunk Text
"long",
              Chunk
" ",
              Text -> Chunk
chunk (Text -> Chunk) -> Text -> Chunk
forall a b. (a -> b) -> a -> b
$
                [Char] -> Text
T.pack ([Char] -> Text) -> [Char] -> Text
forall a b. (a -> b) -> a -> b
$
                  [Char] -> [Char]
forall a. Show a => a -> [Char]
show ([Char] -> [Char]) -> [Char] -> [Char]
forall a b. (a -> b) -> a -> b
$
                    let go :: [Char] -> [Char]
go = \case
                          [] -> []
                          Char
'-' : [Char]
cs -> [Char] -> [Char]
go [Char]
cs
                          Char
c : [Char]
cs -> Char
c Char -> [Char] -> [Char]
forall a. a -> [a] -> [a]
: [Char]
cs
                     in [Char] -> [Char]
go ([Char] -> [Char]) -> [Char] -> [Char]
forall a b. (a -> b) -> a -> b
$ NonEmpty Char -> [Char]
forall a. NonEmpty a -> [a]
NE.toList NonEmpty Char
s,
              Chunk
" instead."
            ]
          ]
        LintErrorMessage
LintErrorNoReaderForArgument ->
          [ [ Text -> Chunk
functionChunk Text
"argument",
              Chunk
" has no ",
              Text -> Chunk
functionChunk Text
"reader",
              Chunk
"."
            ]
          ]
        LintErrorMessage
LintErrorNoMetavarForArgument ->
          [ [ Text -> Chunk
functionChunk Text
"argument",
              Chunk
" has no ",
              Text -> Chunk
functionChunk Text
"metavar",
              Chunk
"."
            ]
          ]
        LintErrorMessage
LintErrorNoReaderForOption ->
          [ [ Text -> Chunk
functionChunk Text
"option",
              Chunk
" or ",
              Text -> Chunk
functionChunk Text
"name",
              Chunk
" has no ",
              Text -> Chunk
functionChunk Text
"reader",
              Chunk
"."
            ]
          ]
        LintErrorMessage
LintErrorNoDashedForOption ->
          [ [ Text -> Chunk
functionChunk Text
"option",
              Chunk
" has no ",
              Text -> Chunk
functionChunk Text
"long",
              Chunk
" or ",
              Text -> Chunk
functionChunk Text
"short",
              Chunk
"."
            ]
          ]
        LintErrorMessage
LintErrorNoMetavarForOption ->
          [ [ Text -> Chunk
functionChunk Text
"option",
              Chunk
" or ",
              Text -> Chunk
functionChunk Text
"name",
              Chunk
" has no ",
              Text -> Chunk
functionChunk Text
"metavar",
              Chunk
"."
            ]
          ]
        LintErrorMessage
LintErrorNoDashedForSwitch ->
          [ [ Text -> Chunk
functionChunk Text
"switch",
              Chunk
" has no ",
              Text -> Chunk
functionChunk Text
"long",
              Chunk
" or ",
              Text -> Chunk
functionChunk Text
"short",
              Chunk
"."
            ]
          ]
        LintErrorMessage
LintErrorNoOptionOrSwitchForDashed ->
          [ [ Text -> Chunk
functionChunk Text
"long",
              Chunk
" or ",
              Text -> Chunk
functionChunk Text
"short",
              Chunk
" has no ",
              Text -> Chunk
functionChunk Text
"option",
              Chunk
" or ",
              Text -> Chunk
functionChunk Text
"switch",
              Chunk
"."
            ]
          ]
        LintErrorMessage
LintErrorNoReaderForEnvVar ->
          [ [ Text -> Chunk
functionChunk Text
"env",
              Chunk
" or ",
              Text -> Chunk
functionChunk Text
"name",
              Chunk
" has no ",
              Text -> Chunk
functionChunk Text
"reader",
              Chunk
"."
            ]
          ]
        LintErrorMessage
LintErrorNoMetavarForEnvVar ->
          [ [ Text -> Chunk
functionChunk Text
"env",
              Chunk
" or ",
              Text -> Chunk
functionChunk Text
"name",
              Chunk
" has no ",
              Text -> Chunk
functionChunk Text
"metavar",
              Chunk
"."
            ]
          ]
        LintErrorMessage
LintErrorNoCommands ->
          [ [ Text -> Chunk
functionChunk Text
"commands",
              Chunk
" was called with an empty list."
            ]
          ]
        LintErrorUnknownDefaultCommand [Char]
c ->
          [ [ Text -> Chunk
functionChunk Text
"defaultCommand",
              Chunk
" was called with an unknown command: ",
              [Char] -> Chunk
commandChunk [Char]
c
            ]
          ]
        LintErrorUnreadableExample [Char]
e ->
          [ [Text -> Chunk
functionChunk Text
"example", Chunk
" was called with an example that none of the ", Text -> Chunk
functionChunk Text
"reader", Chunk
"s succeed in reading."],
            [Chunk
"Example: ", Text -> Chunk
chunk (Text -> Chunk) -> Text -> Chunk
forall a b. (a -> b) -> a -> b
$ [Char] -> Text
T.pack [Char]
e]
          ]
        LintErrorMessage
LintErrorConfigWithoutLoad ->
          [ [ Text -> Chunk
functionChunk Text
"conf",
              Chunk
" or ",
              Text -> Chunk
functionChunk Text
"name",
              Chunk
" was called with no way to load configuration."
            ],
            [ Chunk
"You can load configuration with ",
              Text -> Chunk
functionChunk Text
"withConfig",
              Chunk
", or explicitly not load any configuration with ",
              Text -> Chunk
functionChunk Text
"withoutConfig",
              Chunk
"."
            ]
          ]
        LintErrorMessage
LintErrorManyInfinite ->
          [ [ Text -> Chunk
functionChunk Text
"many",
              Chunk
" or ",
              Text -> Chunk
functionChunk Text
"some",
              Chunk
" was called with a parser that may succeed without consuming anything."
            ],
            [Chunk
"This is not allowed because the parser would run infinitely."]
          ],
      [[Chunk]] -> (SrcLoc -> [[Chunk]]) -> Maybe SrcLoc -> [[Chunk]]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [] ([Chunk] -> [[Chunk]]
forall a. a -> [a]
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([Chunk] -> [[Chunk]])
-> (SrcLoc -> [Chunk]) -> SrcLoc -> [[Chunk]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Chunk
"Defined at: " Chunk -> [Chunk] -> [Chunk]
forall a. a -> [a] -> [a]
:) ([Chunk] -> [Chunk]) -> (SrcLoc -> [Chunk]) -> SrcLoc -> [Chunk]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Chunk -> [Chunk]
forall a. a -> [a]
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Chunk -> [Chunk]) -> (SrcLoc -> Chunk) -> SrcLoc -> [Chunk]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Colour -> Chunk -> Chunk
fore Colour
cyan (Chunk -> Chunk) -> (SrcLoc -> Chunk) -> SrcLoc -> Chunk
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Chunk
chunk (Text -> Chunk) -> (SrcLoc -> Text) -> SrcLoc -> Chunk
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> Text
T.pack ([Char] -> Text) -> (SrcLoc -> [Char]) -> SrcLoc -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SrcLoc -> [Char]
prettySrcLoc) Maybe SrcLoc
lintErrorSrcLoc
    ]

lintParser :: Parser a -> Maybe (NonEmpty LintError)
lintParser :: forall a. Parser a -> Maybe (NonEmpty LintError)
lintParser =
  (NonEmpty LintError -> Maybe (NonEmpty LintError))
-> (Bool -> Maybe (NonEmpty LintError))
-> Either (NonEmpty LintError) Bool
-> Maybe (NonEmpty LintError)
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either NonEmpty LintError -> Maybe (NonEmpty LintError)
forall a. a -> Maybe a
Just (Maybe (NonEmpty LintError) -> Bool -> Maybe (NonEmpty LintError)
forall a b. a -> b -> a
const Maybe (NonEmpty LintError)
forall a. Maybe a
Nothing)
    (Either (NonEmpty LintError) Bool -> Maybe (NonEmpty LintError))
-> (Parser a -> Either (NonEmpty LintError) Bool)
-> Parser a
-> Maybe (NonEmpty LintError)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Validation LintError Bool -> Either (NonEmpty LintError) Bool
forall e a. Validation e a -> Either (NonEmpty e) a
validationToEither
    (Validation LintError Bool -> Either (NonEmpty LintError) Bool)
-> (Parser a -> Validation LintError Bool)
-> Parser a
-> Either (NonEmpty LintError) Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Reader Bool (Validation LintError Bool)
-> Bool -> Validation LintError Bool
forall r a. Reader r a -> r -> a
`runReader` Bool
False) -- Set to true for parsers that have a way to load conf
    (Reader Bool (Validation LintError Bool)
 -> Validation LintError Bool)
-> (Parser a -> Reader Bool (Validation LintError Bool))
-> Parser a
-> Validation LintError Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ValidationT LintError (ReaderT Bool Identity) Bool
-> Reader Bool (Validation LintError Bool)
forall e (m :: * -> *) a. ValidationT e m a -> m (Validation e a)
runValidationT
    (ValidationT LintError (ReaderT Bool Identity) Bool
 -> Reader Bool (Validation LintError Bool))
-> (Parser a -> ValidationT LintError (ReaderT Bool Identity) Bool)
-> Parser a
-> Reader Bool (Validation LintError Bool)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Parser a -> ValidationT LintError (ReaderT Bool Identity) Bool
forall a.
Parser a -> ValidationT LintError (ReaderT Bool Identity) Bool
go
  where
    -- Returns whether 'many' is allowed.
    -- 'many' is allowed only when every parse below consumes something.
    go :: Parser a -> ValidationT LintError (Reader Bool) Bool
    go :: forall a.
Parser a -> ValidationT LintError (ReaderT Bool Identity) Bool
go = \case
      ParserPure a
_ -> Bool -> ValidationT LintError (ReaderT Bool Identity) Bool
forall a. a -> ValidationT LintError (ReaderT Bool Identity) a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
False
      ParserAp Parser (a1 -> a)
p1 Parser a1
p2 -> do
        Bool
c1 <- Parser (a1 -> a)
-> ValidationT LintError (ReaderT Bool Identity) Bool
forall a.
Parser a -> ValidationT LintError (ReaderT Bool Identity) Bool
go Parser (a1 -> a)
p1
        Bool
c2 <- Parser a1 -> ValidationT LintError (ReaderT Bool Identity) Bool
forall a.
Parser a -> ValidationT LintError (ReaderT Bool Identity) Bool
go Parser a1
p2
        pure (Bool
c1 Bool -> Bool -> Bool
|| Bool
c2)
      ParserSelect Parser (Either a1 a)
p1 Parser (a1 -> a)
p2 -> do
        Bool
c1 <- Parser (Either a1 a)
-> ValidationT LintError (ReaderT Bool Identity) Bool
forall a.
Parser a -> ValidationT LintError (ReaderT Bool Identity) Bool
go Parser (Either a1 a)
p1
        Bool
c2 <- Parser (a1 -> a)
-> ValidationT LintError (ReaderT Bool Identity) Bool
forall a.
Parser a -> ValidationT LintError (ReaderT Bool Identity) Bool
go Parser (a1 -> a)
p2
        pure (Bool
c1 Bool -> Bool -> Bool
|| Bool
c2) -- TODO: is this right?
      ParserEmpty Maybe SrcLoc
_ -> Bool -> ValidationT LintError (ReaderT Bool Identity) Bool
forall a. a -> ValidationT LintError (ReaderT Bool Identity) a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
True
      ParserAlt Parser a
p1 Parser a
p2 -> do
        Bool
c1 <- Parser a -> ValidationT LintError (ReaderT Bool Identity) Bool
forall a.
Parser a -> ValidationT LintError (ReaderT Bool Identity) Bool
go Parser a
p1
        Bool
c2 <- Parser a -> ValidationT LintError (ReaderT Bool Identity) Bool
forall a.
Parser a -> ValidationT LintError (ReaderT Bool Identity) Bool
go Parser a
p2
        pure (Bool
c1 Bool -> Bool -> Bool
&& Bool
c2) -- TODO: is this right?
        -- TODO lint if we don't try to parse anything consuming under many.
      ParserMany Parser a1
p -> do
        Bool
c <- Parser a1 -> ValidationT LintError (ReaderT Bool Identity) Bool
forall a.
Parser a -> ValidationT LintError (ReaderT Bool Identity) Bool
go Parser a1
p
        Bool
-> ValidationT LintError (ReaderT Bool Identity) ()
-> ValidationT LintError (ReaderT Bool Identity) ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Bool -> Bool
not Bool
c) (ValidationT LintError (ReaderT Bool Identity) ()
 -> ValidationT LintError (ReaderT Bool Identity) ())
-> ValidationT LintError (ReaderT Bool Identity) ()
-> ValidationT LintError (ReaderT Bool Identity) ()
forall a b. (a -> b) -> a -> b
$
          (LintErrorMessage -> LintError)
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
-> ValidationT LintError (ReaderT Bool Identity) ()
forall (m :: * -> *) e1 e2 a.
Functor m =>
(e1 -> e2) -> ValidationT e1 m a -> ValidationT e2 m a
mapValidationTFailure (Maybe SrcLoc -> LintErrorMessage -> LintError
LintError Maybe SrcLoc
forall a. Maybe a
Nothing) (ValidationT LintErrorMessage (ReaderT Bool Identity) ()
 -> ValidationT LintError (ReaderT Bool Identity) ())
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
-> ValidationT LintError (ReaderT Bool Identity) ()
forall a b. (a -> b) -> a -> b
$
            LintErrorMessage
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
forall (m :: * -> *) e a. Applicative m => e -> ValidationT e m a
validationTFailure LintErrorMessage
LintErrorManyInfinite
        pure Bool
c
      ParserSome Parser a1
p -> do
        Bool
c <- Parser a1 -> ValidationT LintError (ReaderT Bool Identity) Bool
forall a.
Parser a -> ValidationT LintError (ReaderT Bool Identity) Bool
go Parser a1
p
        Bool
-> ValidationT LintError (ReaderT Bool Identity) ()
-> ValidationT LintError (ReaderT Bool Identity) ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Bool -> Bool
not Bool
c) (ValidationT LintError (ReaderT Bool Identity) ()
 -> ValidationT LintError (ReaderT Bool Identity) ())
-> ValidationT LintError (ReaderT Bool Identity) ()
-> ValidationT LintError (ReaderT Bool Identity) ()
forall a b. (a -> b) -> a -> b
$
          (LintErrorMessage -> LintError)
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
-> ValidationT LintError (ReaderT Bool Identity) ()
forall (m :: * -> *) e1 e2 a.
Functor m =>
(e1 -> e2) -> ValidationT e1 m a -> ValidationT e2 m a
mapValidationTFailure (Maybe SrcLoc -> LintErrorMessage -> LintError
LintError Maybe SrcLoc
forall a. Maybe a
Nothing) (ValidationT LintErrorMessage (ReaderT Bool Identity) ()
 -> ValidationT LintError (ReaderT Bool Identity) ())
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
-> ValidationT LintError (ReaderT Bool Identity) ()
forall a b. (a -> b) -> a -> b
$
            LintErrorMessage
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
forall (m :: * -> *) e a. Applicative m => e -> ValidationT e m a
validationTFailure LintErrorMessage
LintErrorManyInfinite
        pure Bool
c
      ParserAllOrNothing Maybe SrcLoc
_ Parser a
p -> Parser a -> ValidationT LintError (ReaderT Bool Identity) Bool
forall a.
Parser a -> ValidationT LintError (ReaderT Bool Identity) Bool
go Parser a
p
      ParserCheck Maybe SrcLoc
_ Bool
_ a1 -> IO (Either [Char] a)
_ Parser a1
p -> Parser a1 -> ValidationT LintError (ReaderT Bool Identity) Bool
forall a.
Parser a -> ValidationT LintError (ReaderT Bool Identity) Bool
go Parser a1
p
      ParserCommands Maybe SrcLoc
mLoc Maybe [Char]
mDefault [Command a]
cs -> do
        if [Command a] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Command a]
cs
          then LintError -> ValidationT LintError (ReaderT Bool Identity) Bool
forall (m :: * -> *) e a. Applicative m => e -> ValidationT e m a
validationTFailure (LintError -> ValidationT LintError (ReaderT Bool Identity) Bool)
-> LintError -> ValidationT LintError (ReaderT Bool Identity) Bool
forall a b. (a -> b) -> a -> b
$ Maybe SrcLoc -> LintErrorMessage -> LintError
LintError Maybe SrcLoc
mLoc LintErrorMessage
LintErrorNoCommands
          else do
            Maybe [Char]
-> ([Char] -> ValidationT LintError (ReaderT Bool Identity) ())
-> ValidationT LintError (ReaderT Bool Identity) ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ Maybe [Char]
mDefault (([Char] -> ValidationT LintError (ReaderT Bool Identity) ())
 -> ValidationT LintError (ReaderT Bool Identity) ())
-> ([Char] -> ValidationT LintError (ReaderT Bool Identity) ())
-> ValidationT LintError (ReaderT Bool Identity) ()
forall a b. (a -> b) -> a -> b
$ \[Char]
d ->
              Bool
-> ValidationT LintError (ReaderT Bool Identity) ()
-> ValidationT LintError (ReaderT Bool Identity) ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Maybe (Command a) -> Bool
forall a. Maybe a -> Bool
isNothing ((Command a -> Bool) -> [Command a] -> Maybe (Command a)
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Maybe a
find (([Char] -> [Char] -> Bool
forall a. Eq a => a -> a -> Bool
== [Char]
d) ([Char] -> Bool) -> (Command a -> [Char]) -> Command a -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Command a -> [Char]
forall a. Command a -> [Char]
commandArg) [Command a]
cs)) (ValidationT LintError (ReaderT Bool Identity) ()
 -> ValidationT LintError (ReaderT Bool Identity) ())
-> ValidationT LintError (ReaderT Bool Identity) ()
-> ValidationT LintError (ReaderT Bool Identity) ()
forall a b. (a -> b) -> a -> b
$
                LintError -> ValidationT LintError (ReaderT Bool Identity) ()
forall (m :: * -> *) e a. Applicative m => e -> ValidationT e m a
validationTFailure (LintError -> ValidationT LintError (ReaderT Bool Identity) ())
-> LintError -> ValidationT LintError (ReaderT Bool Identity) ()
forall a b. (a -> b) -> a -> b
$
                  Maybe SrcLoc -> LintErrorMessage -> LintError
LintError Maybe SrcLoc
mLoc (LintErrorMessage -> LintError) -> LintErrorMessage -> LintError
forall a b. (a -> b) -> a -> b
$
                    [Char] -> LintErrorMessage
LintErrorUnknownDefaultCommand [Char]
d
            [Bool] -> Bool
forall (t :: * -> *). Foldable t => t Bool -> Bool
and ([Bool] -> Bool)
-> ValidationT LintError (ReaderT Bool Identity) [Bool]
-> ValidationT LintError (ReaderT Bool Identity) Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Command a -> ValidationT LintError (ReaderT Bool Identity) Bool)
-> [Command a]
-> ValidationT LintError (ReaderT Bool Identity) [Bool]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> [a] -> f [b]
traverse (Parser a -> ValidationT LintError (ReaderT Bool Identity) Bool
forall a.
Parser a -> ValidationT LintError (ReaderT Bool Identity) Bool
go (Parser a -> ValidationT LintError (ReaderT Bool Identity) Bool)
-> (Command a -> Parser a)
-> Command a
-> ValidationT LintError (ReaderT Bool Identity) Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Command a -> Parser a
forall a. Command a -> Parser a
commandParser) [Command a]
cs -- TODO is this right?
      ParserWithConfig Maybe SrcLoc
_ Parser (Maybe Object)
p1 Parser a
p2 -> do
        Bool
c1 <- Parser (Maybe Object)
-> ValidationT LintError (ReaderT Bool Identity) Bool
forall a.
Parser a -> ValidationT LintError (ReaderT Bool Identity) Bool
go Parser (Maybe Object)
p1
        Bool
c2 <- (Bool -> Bool)
-> ValidationT LintError (ReaderT Bool Identity) Bool
-> ValidationT LintError (ReaderT Bool Identity) Bool
forall a.
(Bool -> Bool)
-> ValidationT LintError (ReaderT Bool Identity) a
-> ValidationT LintError (ReaderT Bool Identity) a
forall r (m :: * -> *) a. MonadReader r m => (r -> r) -> m a -> m a
local (Bool -> Bool -> Bool
forall a b. a -> b -> a
const Bool
True) (Parser a -> ValidationT LintError (ReaderT Bool Identity) Bool
forall a.
Parser a -> ValidationT LintError (ReaderT Bool Identity) Bool
go Parser a
p2)
        pure $ Bool
c1 Bool -> Bool -> Bool
|| Bool
c2
      ParserSetting Maybe SrcLoc
mLoc Setting {Bool
[[Char]]
[Dashed]
[Reader a]
Maybe a
Maybe [Char]
Maybe (NonEmpty [Char])
Maybe (NonEmpty (ConfigValSetting a))
Maybe (a, [Char])
settingDasheds :: [Dashed]
settingReaders :: [Reader a]
settingTryArgument :: Bool
settingSwitchValue :: Maybe a
settingTryOption :: Bool
settingEnvVars :: Maybe (NonEmpty [Char])
settingConfigVals :: Maybe (NonEmpty (ConfigValSetting a))
settingDefaultValue :: Maybe (a, [Char])
settingExamples :: [[Char]]
settingHidden :: Bool
settingMetavar :: Maybe [Char]
settingHelp :: Maybe [Char]
settingDasheds :: forall a. Setting a -> [Dashed]
settingReaders :: forall a. Setting a -> [Reader a]
settingTryArgument :: forall a. Setting a -> Bool
settingSwitchValue :: forall a. Setting a -> Maybe a
settingTryOption :: forall a. Setting a -> Bool
settingEnvVars :: forall a. Setting a -> Maybe (NonEmpty [Char])
settingConfigVals :: forall a. Setting a -> Maybe (NonEmpty (ConfigValSetting a))
settingDefaultValue :: forall a. Setting a -> Maybe (a, [Char])
settingExamples :: forall a. Setting a -> [[Char]]
settingHidden :: forall a. Setting a -> Bool
settingMetavar :: forall a. Setting a -> Maybe [Char]
settingHelp :: forall a. Setting a -> Maybe [Char]
..} -> (LintErrorMessage -> LintError)
-> ValidationT LintErrorMessage (ReaderT Bool Identity) Bool
-> ValidationT LintError (ReaderT Bool Identity) Bool
forall (m :: * -> *) e1 e2 a.
Functor m =>
(e1 -> e2) -> ValidationT e1 m a -> ValidationT e2 m a
mapValidationTFailure (Maybe SrcLoc -> LintErrorMessage -> LintError
LintError Maybe SrcLoc
mLoc) (ValidationT LintErrorMessage (ReaderT Bool Identity) Bool
 -> ValidationT LintError (ReaderT Bool Identity) Bool)
-> ValidationT LintErrorMessage (ReaderT Bool Identity) Bool
-> ValidationT LintError (ReaderT Bool Identity) Bool
forall a b. (a -> b) -> a -> b
$ do
        case Maybe [Char]
settingHelp of
          Maybe [Char]
Nothing ->
            -- Hidden values may be undocumented
            Bool
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Bool -> Bool
not Bool
settingHidden) (ValidationT LintErrorMessage (ReaderT Bool Identity) ()
 -> ValidationT LintErrorMessage (ReaderT Bool Identity) ())
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
forall a b. (a -> b) -> a -> b
$ LintErrorMessage
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
forall (m :: * -> *) e a. Applicative m => e -> ValidationT e m a
validationTFailure LintErrorMessage
LintErrorUndocumented
          Just [Char]
_ -> () -> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
forall a.
a -> ValidationT LintErrorMessage (ReaderT Bool Identity) a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
        Bool
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when
          ( [Bool] -> Bool
forall (t :: * -> *). Foldable t => t Bool -> Bool
and
              [ Bool -> Bool
not Bool
settingTryArgument,
                Maybe a -> Bool
forall a. Maybe a -> Bool
isNothing Maybe a
settingSwitchValue,
                Bool -> Bool
not Bool
settingTryOption,
                Maybe (NonEmpty [Char]) -> Bool
forall a. Maybe a -> Bool
isNothing Maybe (NonEmpty [Char])
settingEnvVars,
                Maybe (NonEmpty (ConfigValSetting a)) -> Bool
forall a. Maybe a -> Bool
isNothing Maybe (NonEmpty (ConfigValSetting a))
settingConfigVals,
                Maybe (a, [Char]) -> Bool
forall a. Maybe a -> Bool
isNothing Maybe (a, [Char])
settingDefaultValue
              ]
          )
          (ValidationT LintErrorMessage (ReaderT Bool Identity) ()
 -> ValidationT LintErrorMessage (ReaderT Bool Identity) ())
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
forall a b. (a -> b) -> a -> b
$ LintErrorMessage
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
forall (m :: * -> *) e a. Applicative m => e -> ValidationT e m a
validationTFailure LintErrorMessage
LintErrorEmptySetting
        [Dashed]
-> (Dashed
    -> ValidationT LintErrorMessage (ReaderT Bool Identity) ())
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ [Dashed]
settingDasheds ((Dashed
  -> ValidationT LintErrorMessage (ReaderT Bool Identity) ())
 -> ValidationT LintErrorMessage (ReaderT Bool Identity) ())
-> (Dashed
    -> ValidationT LintErrorMessage (ReaderT Bool Identity) ())
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
forall a b. (a -> b) -> a -> b
$ \case
          DashedLong cs :: NonEmpty Char
cs@(Char
'-' :| [Char]
_) -> LintErrorMessage
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
forall (m :: * -> *) e a. Applicative m => e -> ValidationT e m a
validationTFailure (LintErrorMessage
 -> ValidationT LintErrorMessage (ReaderT Bool Identity) ())
-> LintErrorMessage
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
forall a b. (a -> b) -> a -> b
$ NonEmpty Char -> LintErrorMessage
LintErrorDashInLong NonEmpty Char
cs
          DashedShort Char
'-' -> LintErrorMessage
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
forall (m :: * -> *) e a. Applicative m => e -> ValidationT e m a
validationTFailure LintErrorMessage
LintErrorDashInShort
          Dashed
_ -> () -> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
forall a.
a -> ValidationT LintErrorMessage (ReaderT Bool Identity) a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
        Bool
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Bool
settingTryArgument Bool -> Bool -> Bool
&& [Reader a] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Reader a]
settingReaders) (ValidationT LintErrorMessage (ReaderT Bool Identity) ()
 -> ValidationT LintErrorMessage (ReaderT Bool Identity) ())
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
forall a b. (a -> b) -> a -> b
$
          LintErrorMessage
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
forall (m :: * -> *) e a. Applicative m => e -> ValidationT e m a
validationTFailure LintErrorMessage
LintErrorNoReaderForArgument
        Bool
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Bool
settingTryArgument Bool -> Bool -> Bool
&& Bool -> Bool
not Bool
settingHidden Bool -> Bool -> Bool
&& Maybe [Char] -> Bool
forall a. Maybe a -> Bool
isNothing Maybe [Char]
settingMetavar) (ValidationT LintErrorMessage (ReaderT Bool Identity) ()
 -> ValidationT LintErrorMessage (ReaderT Bool Identity) ())
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
forall a b. (a -> b) -> a -> b
$
          LintErrorMessage
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
forall (m :: * -> *) e a. Applicative m => e -> ValidationT e m a
validationTFailure LintErrorMessage
LintErrorNoMetavarForArgument
        Bool
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Bool
settingTryOption Bool -> Bool -> Bool
&& [Reader a] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Reader a]
settingReaders) (ValidationT LintErrorMessage (ReaderT Bool Identity) ()
 -> ValidationT LintErrorMessage (ReaderT Bool Identity) ())
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
forall a b. (a -> b) -> a -> b
$
          LintErrorMessage
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
forall (m :: * -> *) e a. Applicative m => e -> ValidationT e m a
validationTFailure LintErrorMessage
LintErrorNoReaderForOption
        Bool
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Bool
settingTryOption Bool -> Bool -> Bool
&& [Dashed] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Dashed]
settingDasheds) (ValidationT LintErrorMessage (ReaderT Bool Identity) ()
 -> ValidationT LintErrorMessage (ReaderT Bool Identity) ())
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
forall a b. (a -> b) -> a -> b
$
          LintErrorMessage
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
forall (m :: * -> *) e a. Applicative m => e -> ValidationT e m a
validationTFailure LintErrorMessage
LintErrorNoDashedForOption
        Bool
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Bool
settingTryOption Bool -> Bool -> Bool
&& Bool -> Bool
not Bool
settingHidden Bool -> Bool -> Bool
&& Maybe [Char] -> Bool
forall a. Maybe a -> Bool
isNothing Maybe [Char]
settingMetavar) (ValidationT LintErrorMessage (ReaderT Bool Identity) ()
 -> ValidationT LintErrorMessage (ReaderT Bool Identity) ())
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
forall a b. (a -> b) -> a -> b
$
          LintErrorMessage
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
forall (m :: * -> *) e a. Applicative m => e -> ValidationT e m a
validationTFailure LintErrorMessage
LintErrorNoMetavarForOption
        Bool
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Maybe a -> Bool
forall a. Maybe a -> Bool
isJust Maybe a
settingSwitchValue Bool -> Bool -> Bool
&& [Dashed] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Dashed]
settingDasheds) (ValidationT LintErrorMessage (ReaderT Bool Identity) ()
 -> ValidationT LintErrorMessage (ReaderT Bool Identity) ())
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
forall a b. (a -> b) -> a -> b
$
          LintErrorMessage
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
forall (m :: * -> *) e a. Applicative m => e -> ValidationT e m a
validationTFailure LintErrorMessage
LintErrorNoDashedForSwitch
        Bool
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Bool -> Bool
not Bool
settingTryOption Bool -> Bool -> Bool
&& Maybe a -> Bool
forall a. Maybe a -> Bool
isNothing Maybe a
settingSwitchValue Bool -> Bool -> Bool
&& Bool -> Bool
not ([Dashed] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Dashed]
settingDasheds)) (ValidationT LintErrorMessage (ReaderT Bool Identity) ()
 -> ValidationT LintErrorMessage (ReaderT Bool Identity) ())
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
forall a b. (a -> b) -> a -> b
$
          LintErrorMessage
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
forall (m :: * -> *) e a. Applicative m => e -> ValidationT e m a
validationTFailure LintErrorMessage
LintErrorNoOptionOrSwitchForDashed
        Bool
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Maybe (NonEmpty [Char]) -> Bool
forall a. Maybe a -> Bool
isJust Maybe (NonEmpty [Char])
settingEnvVars Bool -> Bool -> Bool
&& [Reader a] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Reader a]
settingReaders) (ValidationT LintErrorMessage (ReaderT Bool Identity) ()
 -> ValidationT LintErrorMessage (ReaderT Bool Identity) ())
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
forall a b. (a -> b) -> a -> b
$
          LintErrorMessage
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
forall (m :: * -> *) e a. Applicative m => e -> ValidationT e m a
validationTFailure LintErrorMessage
LintErrorNoReaderForEnvVar
        Bool
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Maybe (NonEmpty [Char]) -> Bool
forall a. Maybe a -> Bool
isJust Maybe (NonEmpty [Char])
settingEnvVars Bool -> Bool -> Bool
&& Bool -> Bool
not Bool
settingHidden Bool -> Bool -> Bool
&& Maybe [Char] -> Bool
forall a. Maybe a -> Bool
isNothing Maybe [Char]
settingMetavar) (ValidationT LintErrorMessage (ReaderT Bool Identity) ()
 -> ValidationT LintErrorMessage (ReaderT Bool Identity) ())
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
forall a b. (a -> b) -> a -> b
$
          LintErrorMessage
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
forall (m :: * -> *) e a. Applicative m => e -> ValidationT e m a
validationTFailure LintErrorMessage
LintErrorNoMetavarForEnvVar
        [[Char]]
-> ([Char]
    -> ValidationT LintErrorMessage (ReaderT Bool Identity) ())
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ [[Char]]
settingExamples (([Char]
  -> ValidationT LintErrorMessage (ReaderT Bool Identity) ())
 -> ValidationT LintErrorMessage (ReaderT Bool Identity) ())
-> ([Char]
    -> ValidationT LintErrorMessage (ReaderT Bool Identity) ())
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
forall a b. (a -> b) -> a -> b
$ \[Char]
e ->
          let canRead :: Reader a -> Bool
canRead Reader a
r = Either [Char] a -> Bool
forall a b. Either a b -> Bool
isRight (Either [Char] a -> Bool) -> Either [Char] a -> Bool
forall a b. (a -> b) -> a -> b
$ Reader a -> [Char] -> Either [Char] a
forall a. Reader a -> [Char] -> Either [Char] a
OptEnvConf.runReader Reader a
r [Char]
e
           in Bool
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when ((Bool
settingTryArgument Bool -> Bool -> Bool
|| Bool
settingTryOption) Bool -> Bool -> Bool
&& Bool -> Bool
not ((Reader a -> Bool) -> [Reader a] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any Reader a -> Bool
canRead [Reader a]
settingReaders)) (ValidationT LintErrorMessage (ReaderT Bool Identity) ()
 -> ValidationT LintErrorMessage (ReaderT Bool Identity) ())
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
forall a b. (a -> b) -> a -> b
$
                LintErrorMessage
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
forall (m :: * -> *) e a. Applicative m => e -> ValidationT e m a
validationTFailure (LintErrorMessage
 -> ValidationT LintErrorMessage (ReaderT Bool Identity) ())
-> LintErrorMessage
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
forall a b. (a -> b) -> a -> b
$
                  [Char] -> LintErrorMessage
LintErrorUnreadableExample [Char]
e
        Bool
hasConfig <- ValidationT LintErrorMessage (ReaderT Bool Identity) Bool
forall r (m :: * -> *). MonadReader r m => m r
ask
        Bool
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Maybe (NonEmpty (ConfigValSetting a)) -> Bool
forall a. Maybe a -> Bool
isJust Maybe (NonEmpty (ConfigValSetting a))
settingConfigVals Bool -> Bool -> Bool
&& Bool -> Bool
not Bool
hasConfig) (ValidationT LintErrorMessage (ReaderT Bool Identity) ()
 -> ValidationT LintErrorMessage (ReaderT Bool Identity) ())
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
forall a b. (a -> b) -> a -> b
$
          LintErrorMessage
-> ValidationT LintErrorMessage (ReaderT Bool Identity) ()
forall (m :: * -> *) e a. Applicative m => e -> ValidationT e m a
validationTFailure LintErrorMessage
LintErrorConfigWithoutLoad
        pure $
          -- 'many' is only allowed if something is being consumed and it's
          -- impossible for nothing to be consumed.
          [Bool] -> Bool
forall (t :: * -> *). Foldable t => t Bool -> Bool
and
            [ Bool
settingTryArgument Bool -> Bool -> Bool
|| Bool
settingTryOption Bool -> Bool -> Bool
|| Maybe a -> Bool
forall a. Maybe a -> Bool
isJust Maybe a
settingSwitchValue,
              Maybe (NonEmpty [Char]) -> Bool
forall a. Maybe a -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null Maybe (NonEmpty [Char])
settingEnvVars,
              Maybe (NonEmpty (ConfigValSetting a)) -> Bool
forall a. Maybe a -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null Maybe (NonEmpty (ConfigValSetting a))
settingConfigVals
            ]