packages feed

sandwich-0.3.1.0: discover/Main.hs

module Main where

import Control.Exception
import Data.Function
import qualified Data.List as L
import qualified Data.Map as M
import Data.String.Interpolate
import qualified Data.Text as T
import qualified Data.Text.IO as T
import System.Directory
import System.Environment
import System.FilePath
import Test.Sandwich.TH


newtype SandwichDiscoverOptions = SandwichDiscoverOptions {
  sandwichDiscoverModulePrefix :: String -- TODO: don't use this, instead detect the module some other way (haskell-src-exts? fancy regex?)
  }

defaultSandwichDiscoverOptions :: SandwichDiscoverOptions
defaultSandwichDiscoverOptions = SandwichDiscoverOptions {
  sandwichDiscoverModulePrefix = ""
  }

tryParseArg :: SandwichDiscoverOptions -> String -> SandwichDiscoverOptions
tryParseArg options x
  | ("--module-prefix=" `L.isPrefixOf` x) = options { sandwichDiscoverModulePrefix = L.drop (L.length ("--module-prefix=" :: String)) x }
  | otherwise = options

main :: IO ()
main = do
  (originalFileName, inputFileName, outputFileName, SandwichDiscoverOptions {..}) <- getArgs >>= \case
    (w:x:y:remainingArgs) -> do
      let sandwichDiscoverOptions = L.foldl' tryParseArg defaultSandwichDiscoverOptions remainingArgs
      return (w, x, y, sandwichDiscoverOptions)
    xs -> throwIO $ userError ([i|sandwich-discover: expected 3+ args but got '#{xs}'|])

  let baseDir' = dropExtension originalFileName
  doesDirectoryExist baseDir' >>= \case
    False -> throwIO $ userError ([i|sandwich-discover: expected directory to exist (#{baseDir'})|])
    True -> return ()
  baseDir <- canonicalizePath baseDir'

  -- Build a map from imported name (possibly dedupped by adding numbers) to full module name
  moduleMap <- buildModuleMap baseDir sandwichDiscoverModulePrefix

  let testImports = [[i|import qualified #{y} as #{x}|] | (x, y) <- M.toList moduleMap]
  let testImportsList = [[i|#{x}.tests|] | (x, _) <- M.toList moduleMap]

  contents <- T.readFile inputFileName
  let finalContents = contents
        & T.replace "#insert_test_imports" (T.unlines testImports)
        & T.replace "#test_imports_list" ("[" <> T.intercalate ", " testImportsList <> "]")

  T.writeFile outputFileName finalContents