{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeSynonymInstances #-}
{-# LANGUAGE ViewPatterns #-}

module Test.Tasty.AutoCollect.Config (
  AutoCollectConfig' (..),
  AutoCollectConfig,
  AutoCollectConfigPartial,
  AutoCollectGroupType (..),
  parseConfig,
  resolveConfig,
) where

import Control.Applicative ((<|>))
import Control.Monad (forM)
import Data.Functor.Identity (Identity)
import Data.Maybe (fromMaybe)
import Data.Text (Text)
import Data.Text qualified as Text
import Data.Text.IO qualified as Text
import System.FilePath (takeDirectory, (</>))

{----- Configuration -----}

type family Apply f a where
  Apply Maybe a = Maybe a
  Apply Identity a = a

-- | Configuration for generating the Main module, specified as a block comment.
data AutoCollectConfig' f = AutoCollectConfig
  { forall (f :: * -> *). AutoCollectConfig' f -> Apply f [FilePath]
cfgImports :: Apply f [FilePath]
  -- ^ Files to import
  , forall (f :: * -> *). AutoCollectConfig' f -> Apply f (Maybe Text)
cfgSuiteName :: Apply f (Maybe Text)
  -- ^ The name of the entire test suite
  , forall (f :: * -> *).
AutoCollectConfig' f -> Apply f AutoCollectGroupType
cfgGroupType :: Apply f AutoCollectGroupType
  -- ^ How tests should be grouped (defaults to "modules")
  , forall (f :: * -> *). AutoCollectConfig' f -> Apply f Text
cfgStripSuffix :: Apply f Text
  -- ^ The suffix to strip from a test, e.g. @strip_suffix = Test@ will relabel
  -- a module @Foo.BarTest@ to @Foo.Bar@.
  , forall (f :: * -> *). AutoCollectConfig' f -> Apply f [Text]
cfgIngredients :: Apply f [Text]
  -- ^ A comma-separated list of extra tasty ingredients to include
  , forall (f :: * -> *). AutoCollectConfig' f -> Apply f Bool
cfgIngredientsOverride :: Apply f Bool
  -- ^ If true, 'cfgIngredients' overrides the default tasty ingredients;
  -- otherwise, they're prepended to the list of default ingredients (defaults to false)
  , forall (f :: * -> *). AutoCollectConfig' f -> Apply f Bool
cfgCustomMain :: Apply f Bool
  }

type AutoCollectConfigPartial = AutoCollectConfig' Maybe
deriving instance Show AutoCollectConfigPartial
deriving instance Eq AutoCollectConfigPartial

type AutoCollectConfig = AutoCollectConfig' Identity
deriving instance Show AutoCollectConfig
deriving instance Eq AutoCollectConfig

data AutoCollectGroupType
  = -- | All tests will be flattened like
    --
    -- @
    -- test1
    -- test2
    -- test3
    -- @
    AutoCollectGroupFlat
  | -- | Tests will be grouped by module
    --
    -- @
    -- MyModule.MyTest1
    --   test1
    --   test2
    -- MyModule.MyTest2
    --   test3
    -- @
    AutoCollectGroupModules
  | -- | Test modules will be grouped as a tree
    --
    -- @
    -- MyModule
    --   MyTest1
    --     test1
    --     test2
    --   MyTest2
    --     test3
    -- @
    AutoCollectGroupTree
  deriving (Int -> AutoCollectGroupType -> ShowS
[AutoCollectGroupType] -> ShowS
AutoCollectGroupType -> FilePath
(Int -> AutoCollectGroupType -> ShowS)
-> (AutoCollectGroupType -> FilePath)
-> ([AutoCollectGroupType] -> ShowS)
-> Show AutoCollectGroupType
forall a.
(Int -> a -> ShowS) -> (a -> FilePath) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> AutoCollectGroupType -> ShowS
showsPrec :: Int -> AutoCollectGroupType -> ShowS
$cshow :: AutoCollectGroupType -> FilePath
show :: AutoCollectGroupType -> FilePath
$cshowList :: [AutoCollectGroupType] -> ShowS
showList :: [AutoCollectGroupType] -> ShowS
Show, AutoCollectGroupType -> AutoCollectGroupType -> Bool
(AutoCollectGroupType -> AutoCollectGroupType -> Bool)
-> (AutoCollectGroupType -> AutoCollectGroupType -> Bool)
-> Eq AutoCollectGroupType
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: AutoCollectGroupType -> AutoCollectGroupType -> Bool
== :: AutoCollectGroupType -> AutoCollectGroupType -> Bool
$c/= :: AutoCollectGroupType -> AutoCollectGroupType -> Bool
/= :: AutoCollectGroupType -> AutoCollectGroupType -> Bool
Eq)

-- | Config on RHS overrides config on LHS.
instance Semigroup AutoCollectConfigPartial where
  AutoCollectConfigPartial
cfg1 <> :: AutoCollectConfigPartial
-> AutoCollectConfigPartial -> AutoCollectConfigPartial
<> AutoCollectConfigPartial
cfg2 =
    AutoCollectConfig
      { cfgImports :: Apply Maybe [FilePath]
cfgImports = AutoCollectConfigPartial -> Apply Maybe [FilePath]
forall (f :: * -> *). AutoCollectConfig' f -> Apply f [FilePath]
cfgImports AutoCollectConfigPartial
cfg2 Maybe [FilePath] -> Maybe [FilePath] -> Maybe [FilePath]
forall a. Maybe a -> Maybe a -> Maybe a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> AutoCollectConfigPartial -> Apply Maybe [FilePath]
forall (f :: * -> *). AutoCollectConfig' f -> Apply f [FilePath]
cfgImports AutoCollectConfigPartial
cfg1
      , cfgSuiteName :: Apply Maybe (Maybe Text)
cfgSuiteName = AutoCollectConfigPartial -> Apply Maybe (Maybe Text)
forall (f :: * -> *). AutoCollectConfig' f -> Apply f (Maybe Text)
cfgSuiteName AutoCollectConfigPartial
cfg2 Maybe (Maybe Text) -> Maybe (Maybe Text) -> Maybe (Maybe Text)
forall a. Maybe a -> Maybe a -> Maybe a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> AutoCollectConfigPartial -> Apply Maybe (Maybe Text)
forall (f :: * -> *). AutoCollectConfig' f -> Apply f (Maybe Text)
cfgSuiteName AutoCollectConfigPartial
cfg1
      , cfgGroupType :: Apply Maybe AutoCollectGroupType
cfgGroupType = AutoCollectConfigPartial -> Apply Maybe AutoCollectGroupType
forall (f :: * -> *).
AutoCollectConfig' f -> Apply f AutoCollectGroupType
cfgGroupType AutoCollectConfigPartial
cfg2 Maybe AutoCollectGroupType
-> Maybe AutoCollectGroupType -> Maybe AutoCollectGroupType
forall a. Maybe a -> Maybe a -> Maybe a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> AutoCollectConfigPartial -> Apply Maybe AutoCollectGroupType
forall (f :: * -> *).
AutoCollectConfig' f -> Apply f AutoCollectGroupType
cfgGroupType AutoCollectConfigPartial
cfg1
      , cfgIngredients :: Apply Maybe [Text]
cfgIngredients = AutoCollectConfigPartial -> Apply Maybe [Text]
forall (f :: * -> *). AutoCollectConfig' f -> Apply f [Text]
cfgIngredients AutoCollectConfigPartial
cfg2 Maybe [Text] -> Maybe [Text] -> Maybe [Text]
forall a. Maybe a -> Maybe a -> Maybe a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> AutoCollectConfigPartial -> Apply Maybe [Text]
forall (f :: * -> *). AutoCollectConfig' f -> Apply f [Text]
cfgIngredients AutoCollectConfigPartial
cfg1
      , cfgIngredientsOverride :: Apply Maybe Bool
cfgIngredientsOverride = AutoCollectConfigPartial -> Apply Maybe Bool
forall (f :: * -> *). AutoCollectConfig' f -> Apply f Bool
cfgIngredientsOverride AutoCollectConfigPartial
cfg2 Maybe Bool -> Maybe Bool -> Maybe Bool
forall a. Maybe a -> Maybe a -> Maybe a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> AutoCollectConfigPartial -> Apply Maybe Bool
forall (f :: * -> *). AutoCollectConfig' f -> Apply f Bool
cfgIngredientsOverride AutoCollectConfigPartial
cfg1
      , cfgStripSuffix :: Apply Maybe Text
cfgStripSuffix = AutoCollectConfigPartial -> Apply Maybe Text
forall (f :: * -> *). AutoCollectConfig' f -> Apply f Text
cfgStripSuffix AutoCollectConfigPartial
cfg2 Maybe Text -> Maybe Text -> Maybe Text
forall a. Maybe a -> Maybe a -> Maybe a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> AutoCollectConfigPartial -> Apply Maybe Text
forall (f :: * -> *). AutoCollectConfig' f -> Apply f Text
cfgStripSuffix AutoCollectConfigPartial
cfg1
      , cfgCustomMain :: Apply Maybe Bool
cfgCustomMain = AutoCollectConfigPartial -> Apply Maybe Bool
forall (f :: * -> *). AutoCollectConfig' f -> Apply f Bool
cfgCustomMain AutoCollectConfigPartial
cfg2 Maybe Bool -> Maybe Bool -> Maybe Bool
forall a. Maybe a -> Maybe a -> Maybe a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> AutoCollectConfigPartial -> Apply Maybe Bool
forall (f :: * -> *). AutoCollectConfig' f -> Apply f Bool
cfgCustomMain AutoCollectConfigPartial
cfg1
      }

instance Monoid AutoCollectConfigPartial where
  mempty :: AutoCollectConfigPartial
mempty =
    Apply Maybe [FilePath]
-> Apply Maybe (Maybe Text)
-> Apply Maybe AutoCollectGroupType
-> Apply Maybe Text
-> Apply Maybe [Text]
-> Apply Maybe Bool
-> Apply Maybe Bool
-> AutoCollectConfigPartial
forall (f :: * -> *).
Apply f [FilePath]
-> Apply f (Maybe Text)
-> Apply f AutoCollectGroupType
-> Apply f Text
-> Apply f [Text]
-> Apply f Bool
-> Apply f Bool
-> AutoCollectConfig' f
AutoCollectConfig
      Maybe [FilePath]
Apply Maybe [FilePath]
forall a. Maybe a
Nothing
      Maybe (Maybe Text)
Apply Maybe (Maybe Text)
forall a. Maybe a
Nothing
      Maybe AutoCollectGroupType
Apply Maybe AutoCollectGroupType
forall a. Maybe a
Nothing
      Maybe Text
Apply Maybe Text
forall a. Maybe a
Nothing
      Maybe [Text]
Apply Maybe [Text]
forall a. Maybe a
Nothing
      Maybe Bool
Apply Maybe Bool
forall a. Maybe a
Nothing
      Maybe Bool
Apply Maybe Bool
forall a. Maybe a
Nothing

{----- Parsing -----}

parseConfig :: Text -> Either Text AutoCollectConfigPartial
parseConfig :: Text -> Either Text AutoCollectConfigPartial
parseConfig = ([AutoCollectConfigPartial] -> AutoCollectConfigPartial)
-> Either Text [AutoCollectConfigPartial]
-> Either Text AutoCollectConfigPartial
forall a b. (a -> b) -> Either Text a -> Either Text b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [AutoCollectConfigPartial] -> AutoCollectConfigPartial
forall a. Monoid a => [a] -> a
mconcat (Either Text [AutoCollectConfigPartial]
 -> Either Text AutoCollectConfigPartial)
-> (Text -> Either Text [AutoCollectConfigPartial])
-> Text
-> Either Text AutoCollectConfigPartial
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Text -> Either Text AutoCollectConfigPartial)
-> [Text] -> Either Text [AutoCollectConfigPartial]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM Text -> Either Text AutoCollectConfigPartial
parseLine ([Text] -> Either Text [AutoCollectConfigPartial])
-> (Text -> [Text])
-> Text
-> Either Text [AutoCollectConfigPartial]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Text -> Bool) -> [Text] -> [Text]
forall a. (a -> Bool) -> [a] -> [a]
filter (Bool -> Bool
not (Bool -> Bool) -> (Text -> Bool) -> Text -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Bool
isIgnoredLine) ([Text] -> [Text]) -> (Text -> [Text]) -> Text -> [Text]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> [Text]
Text.lines
  where
    isIgnoredLine :: Text -> Bool
isIgnoredLine Text
s = Text -> Bool
Text.null (Text -> Text
Text.strip Text
s) Bool -> Bool -> Bool
|| (Text
"#" Text -> Text -> Bool
`Text.isPrefixOf` Text
s)

    parseLine :: Text -> Either Text AutoCollectConfigPartial
    parseLine :: Text -> Either Text AutoCollectConfigPartial
parseLine Text
s = do
      (Text
k, Text
v) <-
        case HasCallStack => Text -> Text -> [Text]
Text -> Text -> [Text]
Text.splitOn Text
"=" Text
s of
          [Text -> Text
Text.strip -> Text
k, Text -> Text
Text.strip -> Text
v]
            | Bool -> Bool
not (Text -> Bool
Text.null Text
k)
            , Bool -> Bool
not (Text -> Bool
Text.null Text
v) ->
                (Text, Text) -> Either Text (Text, Text)
forall a. a -> Either Text a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text
k, Text
v)
          [Text]
_ -> Text -> Either Text (Text, Text)
forall a b. a -> Either a b
Left (Text -> Either Text (Text, Text))
-> Text -> Either Text (Text, Text)
forall a b. (a -> b) -> a -> b
$ Text
"Invalid configuration line: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> FilePath -> Text
Text.pack (Text -> FilePath
forall a. Show a => a -> FilePath
show Text
s)

      case Text
k of
        Text
"import" ->
          AutoCollectConfigPartial -> Either Text AutoCollectConfigPartial
forall a. a -> Either Text a
forall (f :: * -> *) a. Applicative f => a -> f a
pure AutoCollectConfigPartial
emptyConfig{cfgImports = Just $ map Text.unpack $ parseCSV v}
        Text
"suite_name" ->
          AutoCollectConfigPartial -> Either Text AutoCollectConfigPartial
forall a. a -> Either Text a
forall (f :: * -> *) a. Applicative f => a -> f a
pure AutoCollectConfigPartial
emptyConfig{cfgSuiteName = Just (Just v)}
        Text
"group_type" -> do
          AutoCollectGroupType
groupType <- Text -> Either Text AutoCollectGroupType
parseGroupType Text
v
          AutoCollectConfigPartial -> Either Text AutoCollectConfigPartial
forall a. a -> Either Text a
forall (f :: * -> *) a. Applicative f => a -> f a
pure AutoCollectConfigPartial
emptyConfig{cfgGroupType = Just groupType}
        Text
"strip_suffix" ->
          AutoCollectConfigPartial -> Either Text AutoCollectConfigPartial
forall a. a -> Either Text a
forall (f :: * -> *) a. Applicative f => a -> f a
pure AutoCollectConfigPartial
emptyConfig{cfgStripSuffix = Just v}
        Text
"ingredients" ->
          AutoCollectConfigPartial -> Either Text AutoCollectConfigPartial
forall a. a -> Either Text a
forall (f :: * -> *) a. Applicative f => a -> f a
pure AutoCollectConfigPartial
emptyConfig{cfgIngredients = Just $ parseCSV v}
        Text
"ingredients_override" -> do
          Bool
override <- Text -> Either Text Bool
parseBool Text
v
          AutoCollectConfigPartial -> Either Text AutoCollectConfigPartial
forall a. a -> Either Text a
forall (f :: * -> *) a. Applicative f => a -> f a
pure AutoCollectConfigPartial
emptyConfig{cfgIngredientsOverride = Just override}
        Text
"custom_main" -> do
          Bool
customMain <- Text -> Either Text Bool
parseBool Text
v
          AutoCollectConfigPartial -> Either Text AutoCollectConfigPartial
forall a. a -> Either Text a
forall (f :: * -> *) a. Applicative f => a -> f a
pure AutoCollectConfigPartial
emptyConfig{cfgCustomMain = Just customMain}
        Text
_ -> Text -> Either Text AutoCollectConfigPartial
forall a b. a -> Either a b
Left (Text -> Either Text AutoCollectConfigPartial)
-> Text -> Either Text AutoCollectConfigPartial
forall a b. (a -> b) -> a -> b
$ Text
"Invalid configuration key: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> FilePath -> Text
Text.pack (Text -> FilePath
forall a. Show a => a -> FilePath
show Text
k)
    emptyConfig :: AutoCollectConfigPartial
emptyConfig = AutoCollectConfigPartial
forall a. Monoid a => a
mempty :: AutoCollectConfigPartial

parseGroupType :: Text -> Either Text AutoCollectGroupType
parseGroupType :: Text -> Either Text AutoCollectGroupType
parseGroupType = \case
  Text
"flat" -> AutoCollectGroupType -> Either Text AutoCollectGroupType
forall a. a -> Either Text a
forall (f :: * -> *) a. Applicative f => a -> f a
pure AutoCollectGroupType
AutoCollectGroupFlat
  Text
"modules" -> AutoCollectGroupType -> Either Text AutoCollectGroupType
forall a. a -> Either Text a
forall (f :: * -> *) a. Applicative f => a -> f a
pure AutoCollectGroupType
AutoCollectGroupModules
  Text
"tree" -> AutoCollectGroupType -> Either Text AutoCollectGroupType
forall a. a -> Either Text a
forall (f :: * -> *) a. Applicative f => a -> f a
pure AutoCollectGroupType
AutoCollectGroupTree
  Text
ty -> Text -> Either Text AutoCollectGroupType
forall a b. a -> Either a b
Left (Text -> Either Text AutoCollectGroupType)
-> Text -> Either Text AutoCollectGroupType
forall a b. (a -> b) -> a -> b
$ Text
"Invalid group_type: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> FilePath -> Text
Text.pack (Text -> FilePath
forall a. Show a => a -> FilePath
show Text
ty)

parseCSV :: Text -> [Text]
parseCSV :: Text -> [Text]
parseCSV = (Text -> Text) -> [Text] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map Text -> Text
Text.strip ([Text] -> [Text]) -> (Text -> [Text]) -> Text -> [Text]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. HasCallStack => Text -> Text -> [Text]
Text -> Text -> [Text]
Text.splitOn Text
","

parseBool :: Text -> Either Text Bool
parseBool :: Text -> Either Text Bool
parseBool Text
s =
  case Text -> Text
Text.toLower Text
s of
    Text
"true" -> Bool -> Either Text Bool
forall a. a -> Either Text a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
True
    Text
"false" -> Bool -> Either Text Bool
forall a. a -> Either Text a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
False
    Text
_ -> Text -> Either Text Bool
forall a b. a -> Either a b
Left (Text -> Either Text Bool) -> Text -> Either Text Bool
forall a b. (a -> b) -> a -> b
$ Text
"Invalid bool: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> FilePath -> Text
Text.pack (Text -> FilePath
forall a. Show a => a -> FilePath
show Text
s)

{----- Resolving -----}

resolveConfig :: FilePath -> AutoCollectConfigPartial -> IO AutoCollectConfig
resolveConfig :: FilePath -> AutoCollectConfigPartial -> IO AutoCollectConfig
resolveConfig FilePath
path0 AutoCollectConfigPartial
cfg0 = AutoCollectConfigPartial -> AutoCollectConfig
resolve (AutoCollectConfigPartial -> AutoCollectConfig)
-> IO AutoCollectConfigPartial -> IO AutoCollectConfig
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> FilePath -> AutoCollectConfigPartial -> IO AutoCollectConfigPartial
resolveImports FilePath
path0 AutoCollectConfigPartial
cfg0
  where
    resolveImports :: FilePath -> AutoCollectConfigPartial -> IO AutoCollectConfigPartial
resolveImports FilePath
path AutoCollectConfigPartial
cfg = do
      let imports :: [FilePath]
imports = [FilePath] -> Maybe [FilePath] -> [FilePath]
forall a. a -> Maybe a -> a
fromMaybe [] (Maybe [FilePath] -> [FilePath]) -> Maybe [FilePath] -> [FilePath]
forall a b. (a -> b) -> a -> b
$ AutoCollectConfigPartial -> Apply Maybe [FilePath]
forall (f :: * -> *). AutoCollectConfig' f -> Apply f [FilePath]
cfgImports AutoCollectConfigPartial
cfg
      ([AutoCollectConfigPartial] -> AutoCollectConfigPartial)
-> IO [AutoCollectConfigPartial] -> IO AutoCollectConfigPartial
forall a b. (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (AutoCollectConfigPartial
-> [AutoCollectConfigPartial] -> AutoCollectConfigPartial
forall {a}. Monoid a => a -> [a] -> a
mergeConfigs AutoCollectConfigPartial
cfg) (IO [AutoCollectConfigPartial] -> IO AutoCollectConfigPartial)
-> ((FilePath -> IO AutoCollectConfigPartial)
    -> IO [AutoCollectConfigPartial])
-> (FilePath -> IO AutoCollectConfigPartial)
-> IO AutoCollectConfigPartial
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [FilePath]
-> (FilePath -> IO AutoCollectConfigPartial)
-> IO [AutoCollectConfigPartial]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
t a -> (a -> m b) -> m (t b)
forM [FilePath]
imports ((FilePath -> IO AutoCollectConfigPartial)
 -> IO AutoCollectConfigPartial)
-> (FilePath -> IO AutoCollectConfigPartial)
-> IO AutoCollectConfigPartial
forall a b. (a -> b) -> a -> b
$ \FilePath
imp -> do
        let fp :: FilePath
fp = ShowS
takeDirectory FilePath
path FilePath -> ShowS
</> FilePath
imp
        Text
file <- FilePath -> IO Text
Text.readFile FilePath
fp
        case Text -> Either Text AutoCollectConfigPartial
parseConfig Text
file of
          Right AutoCollectConfigPartial
cfg' -> FilePath -> AutoCollectConfigPartial -> IO AutoCollectConfigPartial
resolveImports FilePath
fp AutoCollectConfigPartial
cfg'
          Left Text
e -> FilePath -> IO AutoCollectConfigPartial
forall a. FilePath -> a
errorWithoutStackTrace (FilePath -> IO AutoCollectConfigPartial)
-> FilePath -> IO AutoCollectConfigPartial
forall a b. (a -> b) -> a -> b
$ FilePath
"Could not parse imported config (" FilePath -> ShowS
forall a. Semigroup a => a -> a -> a
<> FilePath
fp FilePath -> ShowS
forall a. Semigroup a => a -> a -> a
<> FilePath
"): " FilePath -> ShowS
forall a. Semigroup a => a -> a -> a
<> Text -> FilePath
Text.unpack Text
e

    mergeConfigs :: a -> [a] -> a
mergeConfigs a
cfg [a]
importedCfgs = [a] -> a
forall a. Monoid a => [a] -> a
mconcat [a]
importedCfgs a -> a -> a
forall a. Semigroup a => a -> a -> a
<> a
cfg

    resolve :: AutoCollectConfigPartial -> AutoCollectConfig
    resolve :: AutoCollectConfigPartial -> AutoCollectConfig
resolve AutoCollectConfig{Apply Maybe Bool
Apply Maybe [FilePath]
Apply Maybe [Text]
Apply Maybe (Maybe Text)
Apply Maybe Text
Apply Maybe AutoCollectGroupType
cfgImports :: forall (f :: * -> *). AutoCollectConfig' f -> Apply f [FilePath]
cfgSuiteName :: forall (f :: * -> *). AutoCollectConfig' f -> Apply f (Maybe Text)
cfgGroupType :: forall (f :: * -> *).
AutoCollectConfig' f -> Apply f AutoCollectGroupType
cfgStripSuffix :: forall (f :: * -> *). AutoCollectConfig' f -> Apply f Text
cfgIngredients :: forall (f :: * -> *). AutoCollectConfig' f -> Apply f [Text]
cfgIngredientsOverride :: forall (f :: * -> *). AutoCollectConfig' f -> Apply f Bool
cfgCustomMain :: forall (f :: * -> *). AutoCollectConfig' f -> Apply f Bool
cfgImports :: Apply Maybe [FilePath]
cfgSuiteName :: Apply Maybe (Maybe Text)
cfgGroupType :: Apply Maybe AutoCollectGroupType
cfgStripSuffix :: Apply Maybe Text
cfgIngredients :: Apply Maybe [Text]
cfgIngredientsOverride :: Apply Maybe Bool
cfgCustomMain :: Apply Maybe Bool
..} =
      AutoCollectConfig
        { cfgImports :: Apply Identity [FilePath]
cfgImports = []
        , cfgSuiteName :: Apply Identity (Maybe Text)
cfgSuiteName = Maybe Text -> Maybe (Maybe Text) -> Maybe Text
forall a. a -> Maybe a -> a
fromMaybe Maybe Text
forall a. Maybe a
Nothing Maybe (Maybe Text)
Apply Maybe (Maybe Text)
cfgSuiteName
        , cfgGroupType :: Apply Identity AutoCollectGroupType
cfgGroupType = AutoCollectGroupType
-> Maybe AutoCollectGroupType -> AutoCollectGroupType
forall a. a -> Maybe a -> a
fromMaybe AutoCollectGroupType
AutoCollectGroupModules Maybe AutoCollectGroupType
Apply Maybe AutoCollectGroupType
cfgGroupType
        , cfgIngredients :: Apply Identity [Text]
cfgIngredients = [Text] -> Maybe [Text] -> [Text]
forall a. a -> Maybe a -> a
fromMaybe [] Maybe [Text]
Apply Maybe [Text]
cfgIngredients
        , cfgIngredientsOverride :: Apply Identity Bool
cfgIngredientsOverride = Bool -> Maybe Bool -> Bool
forall a. a -> Maybe a -> a
fromMaybe Bool
False Maybe Bool
Apply Maybe Bool
cfgIngredientsOverride
        , cfgStripSuffix :: Apply Identity Text
cfgStripSuffix = Text -> Maybe Text -> Text
forall a. a -> Maybe a -> a
fromMaybe Text
"" Maybe Text
Apply Maybe Text
cfgStripSuffix
        , cfgCustomMain :: Apply Identity Bool
cfgCustomMain = Bool -> Maybe Bool -> Bool
forall a. a -> Maybe a -> a
fromMaybe Bool
False Maybe Bool
Apply Maybe Bool
cfgCustomMain
        }