{-# LANGUAGE PatternGuards, DeriveDataTypeable, TupleSections #-}
{-# OPTIONS_GHC -fno-warn-missing-fields -fno-cse -O0 #-}

module CmdLine(
    Cmd(..), getCmd,
    CppFlags(..), cmdCpp, cmdExtensions, cmdHintFiles, cmdUseColour,
    exitWithHelp, resolveFile
    ) where

import Control.Monad.Extra
import qualified Data.ByteString as BS
import Data.Char
import Data.List
import Data.Maybe
import Data.Functor
import HSE.All(CppFlags(..))
import Language.Haskell.Exts(defaultParseMode, baseLanguage)
import Language.Haskell.Exts.Extension
import Language.Preprocessor.Cpphs
import System.Console.ANSI(hSupportsANSI)
import System.Console.CmdArgs.Explicit(helpText, HelpFormat(..))
import System.Console.CmdArgs.Implicit
import System.Directory.Extra
import System.Environment.Extra
import System.Exit
import System.FilePath
import System.IO
import System.IO.Error
import System.Info.Extra
import System.Process
import System.FilePattern

import EmbedData
import Util
import Paths_hlint
import Data.Version
import Prelude


getCmd :: [String] -> IO Cmd
getCmd :: [String] -> IO Cmd
getCmd args :: [String]
args = [String] -> IO Cmd -> IO Cmd
forall a. [String] -> IO a -> IO a
withArgs ((String -> String) -> [String] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map String -> String
f [String]
args) (IO Cmd -> IO Cmd) -> IO Cmd -> IO Cmd
forall a b. (a -> b) -> a -> b
$ Cmd -> IO Cmd
automatic (Cmd -> IO Cmd) -> IO Cmd -> IO Cmd
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Mode (CmdArgs Cmd) -> IO Cmd
forall a. Mode (CmdArgs a) -> IO a
cmdArgsRun Mode (CmdArgs Cmd)
mode
    where f :: String -> String
f x :: String
x = if String
x String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== "-?" Bool -> Bool -> Bool
|| String
x String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== "--help" then "--help=all" else String
x


automatic :: Cmd -> IO Cmd
automatic :: Cmd -> IO Cmd
automatic cmd :: Cmd
cmd = case Cmd
cmd of
    CmdMain{} -> Cmd -> IO Cmd
dataDir (Cmd -> IO Cmd) -> IO Cmd -> IO Cmd
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Cmd -> IO Cmd
forall (m :: * -> *). Monad m => Cmd -> m Cmd
path (Cmd -> IO Cmd) -> IO Cmd -> IO Cmd
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Cmd -> IO Cmd
git (Cmd -> IO Cmd) -> IO Cmd -> IO Cmd
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Cmd -> IO Cmd
forall (m :: * -> *). Monad m => Cmd -> m Cmd
extension Cmd
cmd
    CmdGrep{} -> Cmd -> IO Cmd
forall (m :: * -> *). Monad m => Cmd -> m Cmd
path (Cmd -> IO Cmd) -> IO Cmd -> IO Cmd
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Cmd -> IO Cmd
forall (m :: * -> *). Monad m => Cmd -> m Cmd
extension Cmd
cmd
    CmdTest{} -> Cmd -> IO Cmd
dataDir Cmd
cmd
    _ -> Cmd -> IO Cmd
forall (m :: * -> *) a. Monad m => a -> m a
return Cmd
cmd
    where
        path :: Cmd -> m Cmd
path cmd :: Cmd
cmd = Cmd -> m Cmd
forall (m :: * -> *) a. Monad m => a -> m a
return (Cmd -> m Cmd) -> Cmd -> m Cmd
forall a b. (a -> b) -> a -> b
$ if [String] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null ([String] -> Bool) -> [String] -> Bool
forall a b. (a -> b) -> a -> b
$ Cmd -> [String]
cmdPath Cmd
cmd then Cmd
cmd{cmdPath :: [String]
cmdPath=["."]} else Cmd
cmd
        extension :: Cmd -> m Cmd
extension cmd :: Cmd
cmd = Cmd -> m Cmd
forall (m :: * -> *) a. Monad m => a -> m a
return (Cmd -> m Cmd) -> Cmd -> m Cmd
forall a b. (a -> b) -> a -> b
$ if [String] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null ([String] -> Bool) -> [String] -> Bool
forall a b. (a -> b) -> a -> b
$ Cmd -> [String]
cmdExtension Cmd
cmd then Cmd
cmd{cmdExtension :: [String]
cmdExtension=["hs","lhs"]} else Cmd
cmd
        dataDir :: Cmd -> IO Cmd
dataDir cmd :: Cmd
cmd
            | Cmd -> String
cmdDataDir Cmd
cmd  String -> String -> Bool
forall a. Eq a => a -> a -> Bool
/= "" = Cmd -> IO Cmd
forall (m :: * -> *) a. Monad m => a -> m a
return Cmd
cmd
            | Bool
otherwise = do
                String
x <- IO String
getDataDir
                Bool
b <- String -> IO Bool
doesDirectoryExist String
x
                if Bool
b then Cmd -> IO Cmd
forall (m :: * -> *) a. Monad m => a -> m a
return Cmd
cmd{cmdDataDir :: String
cmdDataDir=String
x} else do
                    String
exe <- IO String
getExecutablePath
                    Cmd -> IO Cmd
forall (m :: * -> *) a. Monad m => a -> m a
return Cmd
cmd{cmdDataDir :: String
cmdDataDir = String -> String
takeDirectory String
exe String -> String -> String
</> "data"}
        git :: Cmd -> IO Cmd
git cmd :: Cmd
cmd
            | Cmd -> Bool
cmdGit Cmd
cmd = do
                Maybe String
mgit <- String -> IO (Maybe String)
findExecutable "git"
                case Maybe String
mgit of
                    Nothing -> String -> IO Cmd
forall a. HasCallStack => String -> a
error "Could not find git"
                    Just git :: String
git -> do
                        let args :: [String]
args = ["ls-files", "--cached", "--others", "--exclude-standard"] [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++
                                   (String -> String) -> [String] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map ("*." String -> String -> String
forall a. [a] -> [a] -> [a]
++) (Cmd -> [String]
cmdExtension Cmd
cmd)
                        String
files <- String -> [String] -> String -> IO String
readProcess String
git [String]
args ""
                        Cmd -> IO Cmd
forall (m :: * -> *) a. Monad m => a -> m a
return Cmd
cmd{cmdFiles :: [String]
cmdFiles = Cmd -> [String]
cmdFiles Cmd
cmd [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++ String -> [String]
lines String
files}
            | Bool
otherwise = Cmd -> IO Cmd
forall (m :: * -> *) a. Monad m => a -> m a
return Cmd
cmd


exitWithHelp :: IO a
exitWithHelp :: IO a
exitWithHelp = do
    String -> IO ()
putStr (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ [Text] -> String
forall a. Show a => a -> String
show ([Text] -> String) -> [Text] -> String
forall a b. (a -> b) -> a -> b
$ [String] -> HelpFormat -> Mode (CmdArgs Cmd) -> [Text]
forall a. [String] -> HelpFormat -> Mode a -> [Text]
helpText [] HelpFormat
HelpFormatAll Mode (CmdArgs Cmd)
mode
    IO a
forall a. IO a
exitSuccess


-- | When to colour terminal output.
data ColorMode
    = Never  -- ^ Terminal output will never be coloured.
    | Always -- ^ Terminal output will always be coloured.
    | Auto   -- ^ Terminal output will be coloured if $TERM and stdout appear to support it.
      deriving (Int -> ColorMode -> String -> String
[ColorMode] -> String -> String
ColorMode -> String
(Int -> ColorMode -> String -> String)
-> (ColorMode -> String)
-> ([ColorMode] -> String -> String)
-> Show ColorMode
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
showList :: [ColorMode] -> String -> String
$cshowList :: [ColorMode] -> String -> String
show :: ColorMode -> String
$cshow :: ColorMode -> String
showsPrec :: Int -> ColorMode -> String -> String
$cshowsPrec :: Int -> ColorMode -> String -> String
Show, Typeable, Typeable ColorMode
Constr
DataType
Typeable ColorMode =>
(forall (c :: * -> *).
 (forall d b. Data d => c (d -> b) -> d -> c b)
 -> (forall g. g -> c g) -> ColorMode -> c ColorMode)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c ColorMode)
-> (ColorMode -> Constr)
-> (ColorMode -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c ColorMode))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c ColorMode))
-> ((forall b. Data b => b -> b) -> ColorMode -> ColorMode)
-> (forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> ColorMode -> r)
-> (forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> ColorMode -> r)
-> (forall u. (forall d. Data d => d -> u) -> ColorMode -> [u])
-> (forall u.
    Int -> (forall d. Data d => d -> u) -> ColorMode -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> ColorMode -> m ColorMode)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> ColorMode -> m ColorMode)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> ColorMode -> m ColorMode)
-> Data ColorMode
ColorMode -> Constr
ColorMode -> DataType
(forall b. Data b => b -> b) -> ColorMode -> ColorMode
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> ColorMode -> c ColorMode
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c ColorMode
forall a.
Typeable a =>
(forall (c :: * -> *).
 (forall d b. Data d => c (d -> b) -> d -> c b)
 -> (forall g. g -> c g) -> a -> c a)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c a)
-> (a -> Constr)
-> (a -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c a))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
-> ((forall b. Data b => b -> b) -> a -> a)
-> (forall r r'.
    (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall r r'.
    (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall u. (forall d. Data d => d -> u) -> a -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> Data a
forall u. Int -> (forall d. Data d => d -> u) -> ColorMode -> u
forall u. (forall d. Data d => d -> u) -> ColorMode -> [u]
forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> ColorMode -> r
forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> ColorMode -> r
forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> ColorMode -> m ColorMode
forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> ColorMode -> m ColorMode
forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c ColorMode
forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> ColorMode -> c ColorMode
forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c ColorMode)
forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c ColorMode)
$cAuto :: Constr
$cAlways :: Constr
$cNever :: Constr
$tColorMode :: DataType
gmapMo :: (forall d. Data d => d -> m d) -> ColorMode -> m ColorMode
$cgmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> ColorMode -> m ColorMode
gmapMp :: (forall d. Data d => d -> m d) -> ColorMode -> m ColorMode
$cgmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> ColorMode -> m ColorMode
gmapM :: (forall d. Data d => d -> m d) -> ColorMode -> m ColorMode
$cgmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> ColorMode -> m ColorMode
gmapQi :: Int -> (forall d. Data d => d -> u) -> ColorMode -> u
$cgmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> ColorMode -> u
gmapQ :: (forall d. Data d => d -> u) -> ColorMode -> [u]
$cgmapQ :: forall u. (forall d. Data d => d -> u) -> ColorMode -> [u]
gmapQr :: (r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> ColorMode -> r
$cgmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> ColorMode -> r
gmapQl :: (r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> ColorMode -> r
$cgmapQl :: forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> ColorMode -> r
gmapT :: (forall b. Data b => b -> b) -> ColorMode -> ColorMode
$cgmapT :: (forall b. Data b => b -> b) -> ColorMode -> ColorMode
dataCast2 :: (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c ColorMode)
$cdataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c ColorMode)
dataCast1 :: (forall d. Data d => c (t d)) -> Maybe (c ColorMode)
$cdataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c ColorMode)
dataTypeOf :: ColorMode -> DataType
$cdataTypeOf :: ColorMode -> DataType
toConstr :: ColorMode -> Constr
$ctoConstr :: ColorMode -> Constr
gunfold :: (forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c ColorMode
$cgunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c ColorMode
gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> ColorMode -> c ColorMode
$cgfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> ColorMode -> c ColorMode
$cp1Data :: Typeable ColorMode
Data)


instance Default ColorMode where
  def :: ColorMode
def = if Bool
isWindows then ColorMode
Never else ColorMode
Auto


data Cmd
    = CmdMain
        {Cmd -> [String]
cmdFiles :: [FilePath]    -- ^ which files to run it on, nothing = none given
        ,Cmd -> [String]
cmdReports :: [FilePath]        -- ^ where to generate reports
        ,Cmd -> [String]
cmdGivenHints :: [FilePath]     -- ^ which settignsfiles were explicitly given
        ,Cmd -> [String]
cmdWithHints :: [String]        -- ^ hints that are given on the command line
        ,Cmd -> [String]
cmdWithGroups :: [String]       -- ^ groups that are given on the command line
        ,Cmd -> Bool
cmdGit :: Bool                  -- ^ use git ls-files to find files
        ,Cmd -> ColorMode
cmdColor :: ColorMode           -- ^ color the result
        ,Cmd -> Int
cmdThreads :: Int              -- ^ Numbmer of threads to use, 0 = whatever GHC has
        ,Cmd -> [String]
cmdIgnore :: [String]           -- ^ the hints to ignore
        ,Cmd -> Bool
cmdShowAll :: Bool              -- ^ display all skipped items
        ,Cmd -> [String]
cmdExtension :: [String]        -- ^ extensions
        ,Cmd -> [String]
cmdLanguage :: [String]      -- ^ the extensions (may be prefixed by "No")
        ,Cmd -> Bool
cmdCross :: Bool                -- ^ work between source files, applies to hints such as duplicate code between modules
        ,Cmd -> [String]
cmdFindHints :: [FilePath]      -- ^ source files to look for hints in
        ,Cmd -> String
cmdDataDir :: FilePath          -- ^ the data directory
        ,Cmd -> Bool
cmdDefault :: Bool              -- ^ Print a default file to stdout
        ,Cmd -> [String]
cmdPath :: [String]
        ,Cmd -> [String]
cmdCppDefine :: [String]
        ,Cmd -> [String]
cmdCppInclude :: [FilePath]
        ,Cmd -> [String]
cmdCppFile :: [FilePath]
        ,Cmd -> Bool
cmdCppSimple :: Bool
        ,Cmd -> Bool
cmdCppAnsi :: Bool
        ,Cmd -> Bool
cmdJson :: Bool                -- ^ display hint data as JSON
        ,Cmd -> Bool
cmdCC :: Bool                  -- ^ display hint data as Code Climate Issues
        ,Cmd -> Bool
cmdNoSummary :: Bool           -- ^ do not show the summary info
        ,Cmd -> [String]
cmdOnly :: [String]            -- ^ specify which hints explicitly
        ,Cmd -> Bool
cmdNoExitCode :: Bool
        ,Cmd -> Bool
cmdTiming :: Bool
        ,Cmd -> Bool
cmdSerialise :: Bool           -- ^ Display hints in serialisation format
        ,Cmd -> Bool
cmdRefactor :: Bool            -- ^ Run the `refactor` executable to automatically perform hints
        ,Cmd -> String
cmdRefactorOptions :: String   -- ^ Options to pass to the `refactor` executable.
        ,Cmd -> String
cmdWithRefactor :: FilePath    -- ^ Path to refactor tool
        ,Cmd -> [String]
cmdIgnoreGlob :: [FilePattern]
        }
    | CmdGrep
        {cmdFiles :: [FilePath]    -- ^ which files to run it on, nothing = none given
        ,Cmd -> String
cmdPattern :: String
        ,cmdExtension :: [String]        -- ^ extensions
        ,cmdLanguage :: [String]      -- ^ the extensions (may be prefixed by "No")
        ,cmdPath :: [String]
        ,cmdCppDefine :: [String]
        ,cmdCppInclude :: [FilePath]
        ,cmdCppFile :: [FilePath]
        ,cmdCppSimple :: Bool
        ,cmdCppAnsi :: Bool
        }
    | CmdTest
        {Cmd -> [String]
cmdProof :: [FilePath]          -- ^ a proof script to check against
        ,cmdGivenHints :: [FilePath]     -- ^ which settings files were explicitly given
        ,cmdDataDir :: FilePath          -- ^ the data directory
        ,cmdReports :: [FilePath]        -- ^ where to generate reports
        ,cmdWithHints :: [String]        -- ^ hints that are given on the command line
        ,Cmd -> String
cmdTempDir :: FilePath          -- ^ temporary directory to put the files in
        ,Cmd -> Bool
cmdQuickCheck :: Bool
        ,Cmd -> Bool
cmdTypeCheck :: Bool
        }
    | CmdHSE
        {cmdFiles :: [FilePath]
        ,cmdLanguage :: [String]      -- ^ the extensions (may be prefixed by "No")
        }
    deriving (Typeable Cmd
Constr
DataType
Typeable Cmd =>
(forall (c :: * -> *).
 (forall d b. Data d => c (d -> b) -> d -> c b)
 -> (forall g. g -> c g) -> Cmd -> c Cmd)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c Cmd)
-> (Cmd -> Constr)
-> (Cmd -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c Cmd))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Cmd))
-> ((forall b. Data b => b -> b) -> Cmd -> Cmd)
-> (forall r r'.
    (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Cmd -> r)
-> (forall r r'.
    (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Cmd -> r)
-> (forall u. (forall d. Data d => d -> u) -> Cmd -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> Cmd -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> Cmd -> m Cmd)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> Cmd -> m Cmd)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> Cmd -> m Cmd)
-> Data Cmd
Cmd -> Constr
Cmd -> DataType
(forall b. Data b => b -> b) -> Cmd -> Cmd
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Cmd -> c Cmd
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Cmd
forall a.
Typeable a =>
(forall (c :: * -> *).
 (forall d b. Data d => c (d -> b) -> d -> c b)
 -> (forall g. g -> c g) -> a -> c a)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c a)
-> (a -> Constr)
-> (a -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c a))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
-> ((forall b. Data b => b -> b) -> a -> a)
-> (forall r r'.
    (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall r r'.
    (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall u. (forall d. Data d => d -> u) -> a -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> Data a
forall u. Int -> (forall d. Data d => d -> u) -> Cmd -> u
forall u. (forall d. Data d => d -> u) -> Cmd -> [u]
forall r r'.
(r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Cmd -> r
forall r r'.
(r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Cmd -> r
forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> Cmd -> m Cmd
forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Cmd -> m Cmd
forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Cmd
forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Cmd -> c Cmd
forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c Cmd)
forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Cmd)
$cCmdHSE :: Constr
$cCmdTest :: Constr
$cCmdGrep :: Constr
$cCmdMain :: Constr
$tCmd :: DataType
gmapMo :: (forall d. Data d => d -> m d) -> Cmd -> m Cmd
$cgmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Cmd -> m Cmd
gmapMp :: (forall d. Data d => d -> m d) -> Cmd -> m Cmd
$cgmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Cmd -> m Cmd
gmapM :: (forall d. Data d => d -> m d) -> Cmd -> m Cmd
$cgmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> Cmd -> m Cmd
gmapQi :: Int -> (forall d. Data d => d -> u) -> Cmd -> u
$cgmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> Cmd -> u
gmapQ :: (forall d. Data d => d -> u) -> Cmd -> [u]
$cgmapQ :: forall u. (forall d. Data d => d -> u) -> Cmd -> [u]
gmapQr :: (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Cmd -> r
$cgmapQr :: forall r r'.
(r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Cmd -> r
gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Cmd -> r
$cgmapQl :: forall r r'.
(r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Cmd -> r
gmapT :: (forall b. Data b => b -> b) -> Cmd -> Cmd
$cgmapT :: (forall b. Data b => b -> b) -> Cmd -> Cmd
dataCast2 :: (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Cmd)
$cdataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Cmd)
dataCast1 :: (forall d. Data d => c (t d)) -> Maybe (c Cmd)
$cdataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c Cmd)
dataTypeOf :: Cmd -> DataType
$cdataTypeOf :: Cmd -> DataType
toConstr :: Cmd -> Constr
$ctoConstr :: Cmd -> Constr
gunfold :: (forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Cmd
$cgunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Cmd
gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Cmd -> c Cmd
$cgfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Cmd -> c Cmd
$cp1Data :: Typeable Cmd
Data,Typeable,Int -> Cmd -> String -> String
[Cmd] -> String -> String
Cmd -> String
(Int -> Cmd -> String -> String)
-> (Cmd -> String) -> ([Cmd] -> String -> String) -> Show Cmd
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
showList :: [Cmd] -> String -> String
$cshowList :: [Cmd] -> String -> String
show :: Cmd -> String
$cshow :: Cmd -> String
showsPrec :: Int -> Cmd -> String -> String
$cshowsPrec :: Int -> Cmd -> String -> String
Show)

mode :: Mode (CmdArgs Cmd)
mode = Cmd -> Mode (CmdArgs Cmd)
forall a. Data a => a -> Mode (CmdArgs a)
cmdArgsMode (Cmd -> Mode (CmdArgs Cmd)) -> Cmd -> Mode (CmdArgs Cmd)
forall a b. (a -> b) -> a -> b
$ [Cmd] -> Cmd
forall val. Data val => [val] -> val
modes
    [CmdMain :: [String]
-> [String]
-> [String]
-> [String]
-> [String]
-> Bool
-> ColorMode
-> Int
-> [String]
-> Bool
-> [String]
-> [String]
-> Bool
-> [String]
-> String
-> Bool
-> [String]
-> [String]
-> [String]
-> [String]
-> Bool
-> Bool
-> Bool
-> Bool
-> Bool
-> [String]
-> Bool
-> Bool
-> Bool
-> Bool
-> String
-> String
-> [String]
-> Cmd
CmdMain
        {cmdFiles :: [String]
cmdFiles = [String]
forall a. Default a => a
def [String] -> Ann -> [String]
forall val. Data val => val -> Ann -> val
&= Ann
args [String] -> Ann -> [String]
forall val. Data val => val -> Ann -> val
&= String -> Ann
typ "FILE/DIR"
        ,cmdReports :: [String]
cmdReports = String -> [String]
forall val. (Data val, Default val) => String -> val
nam "report" [String] -> Ann -> [String]
forall val. Data val => val -> Ann -> val
&= String -> Ann
forall a. (Show a, Typeable a) => a -> Ann
opt "report.html" [String] -> Ann -> [String]
forall val. Data val => val -> Ann -> val
&= Ann
typFile [String] -> Ann -> [String]
forall val. Data val => val -> Ann -> val
&= String -> Ann
help "Generate a report in HTML"
        ,cmdGivenHints :: [String]
cmdGivenHints = String -> [String]
forall val. (Data val, Default val) => String -> val
nam "hint" [String] -> Ann -> [String]
forall val. Data val => val -> Ann -> val
&= Ann
typFile [String] -> Ann -> [String]
forall val. Data val => val -> Ann -> val
&= String -> Ann
help "Hint/ignore file to use"
        ,cmdWithHints :: [String]
cmdWithHints = String -> [String]
forall val. (Data val, Default val) => String -> val
nam "with" [String] -> Ann -> [String]
forall val. Data val => val -> Ann -> val
&= String -> Ann
typ "HINT" [String] -> Ann -> [String]
forall val. Data val => val -> Ann -> val
&= String -> Ann
help "Extra hints to use"
        ,cmdWithGroups :: [String]
cmdWithGroups = String -> [String]
forall val. (Data val, Default val) => String -> val
nam_ "with-group" [String] -> Ann -> [String]
forall val. Data val => val -> Ann -> val
&= String -> Ann
typ "GROUP" [String] -> Ann -> [String]
forall val. Data val => val -> Ann -> val
&= String -> Ann
help "Extra hint groups to use"
        ,cmdGit :: Bool
cmdGit = String -> Bool
forall val. (Data val, Default val) => String -> val
nam "git" Bool -> Ann -> Bool
forall val. Data val => val -> Ann -> val
&= String -> Ann
help "Run on files tracked by git"
        ,cmdColor :: ColorMode
cmdColor = String -> ColorMode
forall val. (Data val, Default val) => String -> val
nam "colour" ColorMode -> Ann -> ColorMode
forall val. Data val => val -> Ann -> val
&= String -> Ann
name "color" ColorMode -> Ann -> ColorMode
forall val. Data val => val -> Ann -> val
&= ColorMode -> Ann
forall a. (Show a, Typeable a) => a -> Ann
opt ColorMode
Always ColorMode -> Ann -> ColorMode
forall val. Data val => val -> Ann -> val
&= String -> Ann
typ "always/never/auto" ColorMode -> Ann -> ColorMode
forall val. Data val => val -> Ann -> val
&= String -> Ann
help "Color output (requires ANSI terminal; auto means on when $TERM is supported; by itself, selects always)"
        ,cmdThreads :: Int
cmdThreads = 1 Int -> Ann -> Int
forall val. Data val => val -> Ann -> val
&= String -> Ann
name "threads" Int -> Ann -> Int
forall val. Data val => val -> Ann -> val
&= String -> Ann
name "j" Int -> Ann -> Int
forall val. Data val => val -> Ann -> val
&= Int -> Ann
forall a. (Show a, Typeable a) => a -> Ann
opt (0 :: Int) Int -> Ann -> Int
forall val. Data val => val -> Ann -> val
&= String -> Ann
help "Number of threads to use (-j for all)"
        ,cmdIgnore :: [String]
cmdIgnore = String -> [String]
forall val. (Data val, Default val) => String -> val
nam "ignore" [String] -> Ann -> [String]
forall val. Data val => val -> Ann -> val
&= String -> Ann
typ "HINT" [String] -> Ann -> [String]
forall val. Data val => val -> Ann -> val
&= String -> Ann
help "Ignore a particular hint"
        ,cmdShowAll :: Bool
cmdShowAll = String -> Bool
forall val. (Data val, Default val) => String -> val
nam "show" Bool -> Ann -> Bool
forall val. Data val => val -> Ann -> val
&= String -> Ann
help "Show all ignored ideas"
        ,cmdExtension :: [String]
cmdExtension = String -> [String]
forall val. (Data val, Default val) => String -> val
nam "extension" [String] -> Ann -> [String]
forall val. Data val => val -> Ann -> val
&= String -> Ann
typ "EXT" [String] -> Ann -> [String]
forall val. Data val => val -> Ann -> val
&= String -> Ann
help "File extensions to search (default hs/lhs)"
        ,cmdLanguage :: [String]
cmdLanguage = String -> [String]
forall val. (Data val, Default val) => String -> val
nam_ "language" [String] -> Ann -> [String]
forall val. Data val => val -> Ann -> val
&= String -> Ann
name "X" [String] -> Ann -> [String]
forall val. Data val => val -> Ann -> val
&= String -> Ann
typ "EXTENSION" [String] -> Ann -> [String]
forall val. Data val => val -> Ann -> val
&= String -> Ann
help "Language extensions (Arrows, NoCPP)"
        ,cmdCross :: Bool
cmdCross = String -> Bool
forall val. (Data val, Default val) => String -> val
nam_ "cross" Bool -> Ann -> Bool
forall val. Data val => val -> Ann -> val
&= String -> Ann
help "Work between modules"
        ,cmdFindHints :: [String]
cmdFindHints = String -> [String]
forall val. (Data val, Default val) => String -> val
nam "find" [String] -> Ann -> [String]
forall val. Data val => val -> Ann -> val
&= Ann
typFile [String] -> Ann -> [String]
forall val. Data val => val -> Ann -> val
&= String -> Ann
help "Find hints in a Haskell file"
        ,cmdDataDir :: String
cmdDataDir = String -> String
forall val. (Data val, Default val) => String -> val
nam_ "datadir" String -> Ann -> String
forall val. Data val => val -> Ann -> val
&= Ann
typDir String -> Ann -> String
forall val. Data val => val -> Ann -> val
&= String -> Ann
help "Override the data directory"
        ,cmdDefault :: Bool
cmdDefault = String -> Bool
forall val. (Data val, Default val) => String -> val
nam "default" Bool -> Ann -> Bool
forall val. Data val => val -> Ann -> val
&= String -> Ann
help "Print a default file to stdout"
        ,cmdPath :: [String]
cmdPath = String -> [String]
forall val. (Data val, Default val) => String -> val
nam "path" [String] -> Ann -> [String]
forall val. Data val => val -> Ann -> val
&= String -> Ann
help "Directory in which to search for files"
        ,cmdCppDefine :: [String]
cmdCppDefine = String -> [String]
forall val. (Data val, Default val) => String -> val
nam_ "cpp-define" [String] -> Ann -> [String]
forall val. Data val => val -> Ann -> val
&= String -> Ann
typ "NAME[=VALUE]" [String] -> Ann -> [String]
forall val. Data val => val -> Ann -> val
&= String -> Ann
help "CPP #define"
        ,cmdCppInclude :: [String]
cmdCppInclude = String -> [String]
forall val. (Data val, Default val) => String -> val
nam_ "cpp-include" [String] -> Ann -> [String]
forall val. Data val => val -> Ann -> val
&= Ann
typDir [String] -> Ann -> [String]
forall val. Data val => val -> Ann -> val
&= String -> Ann
help "CPP include path"
        ,cmdCppFile :: [String]
cmdCppFile = String -> [String]
forall val. (Data val, Default val) => String -> val
nam_ "cpp-file" [String] -> Ann -> [String]
forall val. Data val => val -> Ann -> val
&= Ann
typFile [String] -> Ann -> [String]
forall val. Data val => val -> Ann -> val
&= String -> Ann
help "CPP pre-include file"
        ,cmdCppSimple :: Bool
cmdCppSimple = String -> Bool
forall val. (Data val, Default val) => String -> val
nam_ "cpp-simple" Bool -> Ann -> Bool
forall val. Data val => val -> Ann -> val
&= String -> Ann
help "Use a simple CPP (strip # lines)"
        ,cmdCppAnsi :: Bool
cmdCppAnsi = String -> Bool
forall val. (Data val, Default val) => String -> val
nam_ "cpp-ansi" Bool -> Ann -> Bool
forall val. Data val => val -> Ann -> val
&= String -> Ann
help "Use CPP in ANSI compatibility mode"
        ,cmdJson :: Bool
cmdJson = String -> Bool
forall val. (Data val, Default val) => String -> val
nam_ "json" Bool -> Ann -> Bool
forall val. Data val => val -> Ann -> val
&= String -> Ann
help "Display hint data as JSON"
        ,cmdCC :: Bool
cmdCC = String -> Bool
forall val. (Data val, Default val) => String -> val
nam_ "cc" Bool -> Ann -> Bool
forall val. Data val => val -> Ann -> val
&= String -> Ann
help "Display hint data as Code Climate Issues"
        ,cmdNoSummary :: Bool
cmdNoSummary = String -> Bool
forall val. (Data val, Default val) => String -> val
nam_ "no-summary" Bool -> Ann -> Bool
forall val. Data val => val -> Ann -> val
&= String -> Ann
help "Do not show summary information"
        ,cmdOnly :: [String]
cmdOnly = String -> [String]
forall val. (Data val, Default val) => String -> val
nam "only" [String] -> Ann -> [String]
forall val. Data val => val -> Ann -> val
&= String -> Ann
typ "HINT" [String] -> Ann -> [String]
forall val. Data val => val -> Ann -> val
&= String -> Ann
help "Specify which hints explicitly"
        ,cmdNoExitCode :: Bool
cmdNoExitCode = String -> Bool
forall val. (Data val, Default val) => String -> val
nam_ "no-exit-code" Bool -> Ann -> Bool
forall val. Data val => val -> Ann -> val
&= String -> Ann
help "Do not give a negative exit if hints"
        ,cmdTiming :: Bool
cmdTiming = String -> Bool
forall val. (Data val, Default val) => String -> val
nam_ "timing" Bool -> Ann -> Bool
forall val. Data val => val -> Ann -> val
&= String -> Ann
help "Display timing information"
        ,cmdSerialise :: Bool
cmdSerialise = String -> Bool
forall val. (Data val, Default val) => String -> val
nam_ "serialise" Bool -> Ann -> Bool
forall val. Data val => val -> Ann -> val
&= String -> Ann
help "Serialise hint data for consumption by apply-refact"
        ,cmdRefactor :: Bool
cmdRefactor = String -> Bool
forall val. (Data val, Default val) => String -> val
nam_ "refactor" Bool -> Ann -> Bool
forall val. Data val => val -> Ann -> val
&= String -> Ann
help "Automatically invoke `refactor` to apply hints"
        ,cmdRefactorOptions :: String
cmdRefactorOptions = String -> String
forall val. (Data val, Default val) => String -> val
nam_ "refactor-options" String -> Ann -> String
forall val. Data val => val -> Ann -> val
&= String -> Ann
typ "OPTIONS" String -> Ann -> String
forall val. Data val => val -> Ann -> val
&= String -> Ann
help "Options to pass to the `refactor` executable"
        ,cmdWithRefactor :: String
cmdWithRefactor = String -> String
forall val. (Data val, Default val) => String -> val
nam_ "with-refactor" String -> Ann -> String
forall val. Data val => val -> Ann -> val
&= String -> Ann
help "Give the path to refactor"
        ,cmdIgnoreGlob :: [String]
cmdIgnoreGlob = String -> [String]
forall val. (Data val, Default val) => String -> val
nam_ "ignore-glob" [String] -> Ann -> [String]
forall val. Data val => val -> Ann -> val
&= String -> Ann
help "Ignore paths matching glob pattern"
        } Cmd -> Ann -> Cmd
forall val. Data val => val -> Ann -> val
&= Ann
auto Cmd -> Ann -> Cmd
forall val. Data val => val -> Ann -> val
&= Ann
explicit Cmd -> Ann -> Cmd
forall val. Data val => val -> Ann -> val
&= String -> Ann
name "lint"
    ,CmdGrep :: [String]
-> String
-> [String]
-> [String]
-> [String]
-> [String]
-> [String]
-> [String]
-> Bool
-> Bool
-> Cmd
CmdGrep
        {cmdFiles :: [String]
cmdFiles = [String]
forall a. Default a => a
def [String] -> Ann -> [String]
forall val. Data val => val -> Ann -> val
&= Ann
args [String] -> Ann -> [String]
forall val. Data val => val -> Ann -> val
&= String -> Ann
typ "FILE/DIR"
        ,cmdPattern :: String
cmdPattern = String
forall a. Default a => a
def String -> Ann -> String
forall val. Data val => val -> Ann -> val
&= Int -> Ann
argPos 0 String -> Ann -> String
forall val. Data val => val -> Ann -> val
&= String -> Ann
typ "PATTERN"
        } Cmd -> Ann -> Cmd
forall val. Data val => val -> Ann -> val
&= Ann
explicit Cmd -> Ann -> Cmd
forall val. Data val => val -> Ann -> val
&= String -> Ann
name "grep"
    ,CmdTest :: [String]
-> [String]
-> String
-> [String]
-> [String]
-> String
-> Bool
-> Bool
-> Cmd
CmdTest
        {cmdProof :: [String]
cmdProof = String -> [String]
forall val. (Data val, Default val) => String -> val
nam_ "proof" [String] -> Ann -> [String]
forall val. Data val => val -> Ann -> val
&= Ann
typFile [String] -> Ann -> [String]
forall val. Data val => val -> Ann -> val
&= String -> Ann
help "Isabelle/HOLCF theory file"
        ,cmdTypeCheck :: Bool
cmdTypeCheck = String -> Bool
forall val. (Data val, Default val) => String -> val
nam_ "typecheck" Bool -> Ann -> Bool
forall val. Data val => val -> Ann -> val
&= String -> Ann
help "Use GHC to type check the hints"
        ,cmdQuickCheck :: Bool
cmdQuickCheck = String -> Bool
forall val. (Data val, Default val) => String -> val
nam_ "quickcheck" Bool -> Ann -> Bool
forall val. Data val => val -> Ann -> val
&= String -> Ann
help "Use QuickCheck to check the hints"
        ,cmdTempDir :: String
cmdTempDir = String -> String
forall val. (Data val, Default val) => String -> val
nam_ "tempdir" String -> Ann -> String
forall val. Data val => val -> Ann -> val
&= String -> Ann
help "Where to put temporary files (not cleaned up)"
        } Cmd -> Ann -> Cmd
forall val. Data val => val -> Ann -> val
&= Ann
explicit Cmd -> Ann -> Cmd
forall val. Data val => val -> Ann -> val
&= String -> Ann
name "test"
        Cmd -> Ann -> Cmd
forall val. Data val => val -> Ann -> val
&= [String] -> Ann
details ["HLint gives hints on how to improve Haskell code."
                   ,""
                   ,"To check all Haskell files in 'src' and generate a report type:"
                   ,"  hlint src --report"]
    ,CmdHSE :: [String] -> [String] -> Cmd
CmdHSE
        {} Cmd -> Ann -> Cmd
forall val. Data val => val -> Ann -> val
&= Ann
explicit Cmd -> Ann -> Cmd
forall val. Data val => val -> Ann -> val
&= String -> Ann
name "hse"
    ] Cmd -> Ann -> Cmd
forall val. Data val => val -> Ann -> val
&= String -> Ann
program "hlint" Cmd -> Ann -> Cmd
forall val. Data val => val -> Ann -> val
&= Ann
verbosity
    Cmd -> Ann -> Cmd
forall val. Data val => val -> Ann -> val
&=  String -> Ann
summary ("HLint v" String -> String -> String
forall a. [a] -> [a] -> [a]
++ Version -> String
showVersion Version
version String -> String -> String
forall a. [a] -> [a] -> [a]
++ ", (C) Neil Mitchell 2006-2020")
    where
        nam :: String -> val
nam xs :: String
xs = String -> val
forall val. (Data val, Default val) => String -> val
nam_ String
xs val -> Ann -> val
forall val. Data val => val -> Ann -> val
&= String -> Ann
name [String -> Char
forall a. [a] -> a
head String
xs]
        nam_ :: String -> val
nam_ xs :: String
xs = val
forall a. Default a => a
def val -> Ann -> val
forall val. Data val => val -> Ann -> val
&= Ann
explicit val -> Ann -> val
forall val. Data val => val -> Ann -> val
&= String -> Ann
name String
xs

-- | Where should we find the configuration files?
--   * If someone passes cmdWithHints, only look at files they explicitly request
--   * If someone passes an explicit hint name, automatically merge in data/hlint.yaml
--   We want more important hints to go last, since they override
cmdHintFiles :: Cmd -> IO [(FilePath, Maybe String)]
cmdHintFiles :: Cmd -> IO [(String, Maybe String)]
cmdHintFiles cmd :: Cmd
cmd = do
    let explicit1 :: [(String, Maybe String)]
explicit1 = [(String, Maybe String)
hlintYaml | [String] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null ([String] -> Bool) -> [String] -> Bool
forall a b. (a -> b) -> a -> b
$ Cmd -> [String]
cmdWithHints Cmd
cmd]
    let explicit2 :: [String]
explicit2 = Cmd -> [String]
cmdGivenHints Cmd
cmd
    [String]
bad <- (String -> IO Bool) -> [String] -> IO [String]
forall (m :: * -> *) a.
Applicative m =>
(a -> m Bool) -> [a] -> m [a]
filterM (IO Bool -> IO Bool
forall (m :: * -> *). Functor m => m Bool -> m Bool
notM (IO Bool -> IO Bool) -> (String -> IO Bool) -> String -> IO Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> IO Bool
doesFileExist) [String]
explicit2
    let explicit2' :: [(String, Maybe a)]
explicit2' = (String -> (String, Maybe a)) -> [String] -> [(String, Maybe a)]
forall a b. (a -> b) -> [a] -> [b]
map (,Maybe a
forall a. Maybe a
Nothing) [String]
explicit2
    Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when ([String]
bad [String] -> [String] -> Bool
forall a. Eq a => a -> a -> Bool
/= []) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$
        String -> IO ()
forall (m :: * -> *) a. MonadFail m => String -> m a
fail (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ [String] -> String
unlines ([String] -> String) -> [String] -> String
forall a b. (a -> b) -> a -> b
$ "Failed to find requested hint files:" String -> [String] -> [String]
forall a. a -> [a] -> [a]
: (String -> String) -> [String] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map ("  "String -> String -> String
forall a. [a] -> [a] -> [a]
++) [String]
bad
    if Cmd -> [String]
cmdWithHints Cmd
cmd [String] -> [String] -> Bool
forall a. Eq a => a -> a -> Bool
/= [] then [(String, Maybe String)] -> IO [(String, Maybe String)]
forall (m :: * -> *) a. Monad m => a -> m a
return ([(String, Maybe String)] -> IO [(String, Maybe String)])
-> [(String, Maybe String)] -> IO [(String, Maybe String)]
forall a b. (a -> b) -> a -> b
$ [(String, Maybe String)]
explicit1 [(String, Maybe String)]
-> [(String, Maybe String)] -> [(String, Maybe String)]
forall a. [a] -> [a] -> [a]
++ [(String, Maybe String)]
forall a. [(String, Maybe a)]
explicit2' else do
        -- we follow the stylish-haskell config file search policy
        -- 1) current directory or its ancestors; 2) home directory
        String
curdir <- IO String
getCurrentDirectory
        -- Ignores home directory when it isn't present.
        [String]
home <- IO [String] -> (IOError -> IO [String]) -> IO [String]
forall a. IO a -> (IOError -> IO a) -> IO a
catchIOError ((String -> [String] -> [String]
forall a. a -> [a] -> [a]
:[]) (String -> [String]) -> IO String -> IO [String]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO String
getHomeDirectory) (IO [String] -> IOError -> IO [String]
forall a b. a -> b -> a
const (IO [String] -> IOError -> IO [String])
-> IO [String] -> IOError -> IO [String]
forall a b. (a -> b) -> a -> b
$ [String] -> IO [String]
forall (m :: * -> *) a. Monad m => a -> m a
return [])
        Maybe String
implicit <- (String -> IO Bool) -> [String] -> IO (Maybe String)
forall (m :: * -> *) a.
Monad m =>
(a -> m Bool) -> [a] -> m (Maybe a)
findM String -> IO Bool
doesFileExist ([String] -> IO (Maybe String)) -> [String] -> IO (Maybe String)
forall a b. (a -> b) -> a -> b
$
            (String -> String) -> [String] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map (String -> String -> String
</> ".hlint.yaml") (String -> [String]
ancestors String
curdir [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++ [String]
home) -- to match Stylish Haskell
            [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++ ["HLint.hs"] -- the default in HLint 1.*
        [(String, Maybe String)] -> IO [(String, Maybe String)]
forall (m :: * -> *) a. Monad m => a -> m a
return ([(String, Maybe String)] -> IO [(String, Maybe String)])
-> [(String, Maybe String)] -> IO [(String, Maybe String)]
forall a b. (a -> b) -> a -> b
$ [(String, Maybe String)]
explicit1 [(String, Maybe String)]
-> [(String, Maybe String)] -> [(String, Maybe String)]
forall a. [a] -> [a] -> [a]
++ (String -> (String, Maybe String))
-> [String] -> [(String, Maybe String)]
forall a b. (a -> b) -> [a] -> [b]
map (,Maybe String
forall a. Maybe a
Nothing) (Maybe String -> [String]
forall a. Maybe a -> [a]
maybeToList Maybe String
implicit) [(String, Maybe String)]
-> [(String, Maybe String)] -> [(String, Maybe String)]
forall a. [a] -> [a] -> [a]
++ [(String, Maybe String)]
forall a. [(String, Maybe a)]
explicit2'
    where
        ancestors :: String -> [String]
ancestors = [String] -> [String]
forall a. [a] -> [a]
init ([String] -> [String])
-> (String -> [String]) -> String -> [String]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([String] -> String) -> [[String]] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map [String] -> String
joinPath ([[String]] -> [String])
-> (String -> [[String]]) -> String -> [String]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [[String]] -> [[String]]
forall a. [a] -> [a]
reverse ([[String]] -> [[String]])
-> (String -> [[String]]) -> String -> [[String]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [String] -> [[String]]
forall a. [a] -> [[a]]
inits ([String] -> [[String]])
-> (String -> [String]) -> String -> [[String]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> [String]
splitPath

cmdExtensions :: Cmd -> (Language, [Extension])
cmdExtensions :: Cmd -> (Language, [Extension])
cmdExtensions = [String] -> (Language, [Extension])
getExtensions ([String] -> (Language, [Extension]))
-> (Cmd -> [String]) -> Cmd -> (Language, [Extension])
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Cmd -> [String]
cmdLanguage


cmdCpp :: Cmd -> CppFlags
cmdCpp :: Cmd -> CppFlags
cmdCpp cmd :: Cmd
cmd
    | Cmd -> Bool
cmdCppSimple Cmd
cmd = CppFlags
CppSimple
    | KnownExtension -> Extension
EnableExtension KnownExtension
CPP Extension -> [Extension] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` (Language, [Extension]) -> [Extension]
forall a b. (a, b) -> b
snd (Cmd -> (Language, [Extension])
cmdExtensions Cmd
cmd) = CpphsOptions -> CppFlags
Cpphs CpphsOptions
defaultCpphsOptions
        {boolopts :: BoolOptions
boolopts=BoolOptions
defaultBoolOptions{hashline :: Bool
hashline=Bool
False, stripC89 :: Bool
stripC89=Bool
True, ansi :: Bool
ansi=Cmd -> Bool
cmdCppAnsi Cmd
cmd}
        ,includes :: [String]
includes = Cmd -> [String]
cmdCppInclude Cmd
cmd
        ,preInclude :: [String]
preInclude = Cmd -> [String]
cmdCppFile Cmd
cmd
        ,defines :: [(String, String)]
defines = ("__HLINT__","1") (String, String) -> [(String, String)] -> [(String, String)]
forall a. a -> [a] -> [a]
: [(String
a,Int -> String -> String
forall a. Int -> [a] -> [a]
drop 1 String
b) | String
x <- Cmd -> [String]
cmdCppDefine Cmd
cmd, let (a :: String
a,b :: String
b) = (Char -> Bool) -> String -> (String, String)
forall a. (a -> Bool) -> [a] -> ([a], [a])
break (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== '=') String
x]
        }
    | Bool
otherwise = CppFlags
NoCpp


-- | Determines whether to use colour or not.
cmdUseColour :: Cmd -> IO Bool
cmdUseColour :: Cmd -> IO Bool
cmdUseColour cmd :: Cmd
cmd = case Cmd -> ColorMode
cmdColor Cmd
cmd of
  Always -> Bool -> IO Bool
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
True
  Never  -> Bool -> IO Bool
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
  Auto   -> Handle -> IO Bool
hSupportsANSI Handle
stdout


"." <\> :: String -> String -> String
<\> x :: String
x = String
x
x :: String
x <\> y :: String
y = String
x String -> String -> String
</> String
y


resolveFile
    :: Cmd
    -> Maybe FilePath -- ^ Temporary file
    -> FilePath       -- ^ File to resolve, may be "-" for stdin
    -> IO [FilePath]
resolveFile :: Cmd -> Maybe String -> String -> IO [String]
resolveFile cmd :: Cmd
cmd = (String -> Bool)
-> [String] -> [String] -> Maybe String -> String -> IO [String]
getFile ([String] -> String -> Bool
toPredicate ([String] -> String -> Bool) -> [String] -> String -> Bool
forall a b. (a -> b) -> a -> b
$ Cmd -> [String]
cmdIgnoreGlob Cmd
cmd) (Cmd -> [String]
cmdPath Cmd
cmd) (Cmd -> [String]
cmdExtension Cmd
cmd)
    where
        toPredicate :: [FilePattern] -> FilePath -> Bool
        toPredicate :: [String] -> String -> Bool
toPredicate [] = Bool -> String -> Bool
forall a b. a -> b -> a
const Bool
False
        toPredicate globs :: [String]
globs = \x :: String
x -> Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ [((), (), [String])] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null ([((), (), [String])] -> Bool) -> [((), (), [String])] -> Bool
forall a b. (a -> b) -> a -> b
$ [((), String)] -> [((), (), [String])]
forall b. [(b, String)] -> [((), b, [String])]
m [((), String -> String
cleanup String
x)]
            where m :: [(b, String)] -> [((), b, [String])]
m = [((), String)] -> [(b, String)] -> [((), b, [String])]
forall a b. [(a, String)] -> [(b, String)] -> [(a, b, [String])]
matchMany ((String -> ((), String)) -> [String] -> [((), String)]
forall a b. (a -> b) -> [a] -> [b]
map ((),) [String]
globs)

        cleanup :: FilePath -> FilePath
        cleanup :: String -> String
cleanup ('.':x :: Char
x:xs :: String
xs) | Char -> Bool
isPathSeparator Char
x, Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ String -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null String
xs = String
xs
        cleanup x :: String
x = String
x


getFile :: (FilePath -> Bool) -> [FilePath] -> [String] -> Maybe FilePath -> FilePath -> IO [FilePath]
getFile :: (String -> Bool)
-> [String] -> [String] -> Maybe String -> String -> IO [String]
getFile _ path :: [String]
path _ (Just tmpfile :: String
tmpfile) "-" =
    -- make sure we don't reencode any Unicode
    IO ByteString
BS.getContents IO ByteString -> (ByteString -> IO ()) -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= String -> ByteString -> IO ()
BS.writeFile String
tmpfile IO () -> IO [String] -> IO [String]
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> [String] -> IO [String]
forall (m :: * -> *) a. Monad m => a -> m a
return [String
tmpfile]
getFile _ path :: [String]
path _ Nothing "-" = [String] -> IO [String]
forall (m :: * -> *) a. Monad m => a -> m a
return ["-"]
getFile _ [] exts :: [String]
exts _ file :: String
file = String -> IO [String]
forall a. String -> IO a
exitMessage (String -> IO [String]) -> String -> IO [String]
forall a b. (a -> b) -> a -> b
$ "Couldn't find file: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
file
getFile ignore :: String -> Bool
ignore (p :: String
p:ath :: [String]
ath) exts :: [String]
exts t :: Maybe String
t file :: String
file = do
    Bool
isDir <- String -> IO Bool
doesDirectoryExist (String -> IO Bool) -> String -> IO Bool
forall a b. (a -> b) -> a -> b
$ String
p String -> String -> String
<\> String
file
    if Bool
isDir then do
        let avoidDir :: String -> Bool
avoidDir x :: String
x = let y :: String
y = String -> String
takeFileName String
x in "_" String -> String -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`isPrefixOf` String
y Bool -> Bool -> Bool
|| ("." String -> String -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`isPrefixOf` String
y Bool -> Bool -> Bool
&& Bool -> Bool
not ((Char -> Bool) -> String -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== '.') String
y))
            avoidFile :: String -> Bool
avoidFile x :: String
x = let y :: String
y = String -> String
takeFileName String
x in "." String -> String -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`isPrefixOf` String
y Bool -> Bool -> Bool
|| String -> Bool
ignore String
x
        [String]
xs <- (String -> IO Bool) -> String -> IO [String]
listFilesInside (Bool -> IO Bool
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool -> IO Bool) -> (String -> Bool) -> String -> IO Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Bool -> Bool
not (Bool -> Bool) -> (String -> Bool) -> String -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Bool
avoidDir) (String -> IO [String]) -> String -> IO [String]
forall a b. (a -> b) -> a -> b
$ String
p String -> String -> String
<\> String
file
        [String] -> IO [String]
forall (m :: * -> *) a. Monad m => a -> m a
return [String
x | String
x <- [String]
xs, Int -> String -> String
forall a. Int -> [a] -> [a]
drop 1 (String -> String
takeExtension String
x) String -> [String] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [String]
exts, Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ String -> Bool
avoidFile String
x]
     else do
        Bool
isFil <- String -> IO Bool
doesFileExist (String -> IO Bool) -> String -> IO Bool
forall a b. (a -> b) -> a -> b
$ String
p String -> String -> String
<\> String
file
        if Bool
isFil then [String] -> IO [String]
forall (m :: * -> *) a. Monad m => a -> m a
return [String
p String -> String -> String
<\> String
file]
         else do
            Maybe String
res <- String -> [String] -> String -> IO (Maybe String)
getModule String
p [String]
exts String
file
            case Maybe String
res of
                Just x :: String
x -> [String] -> IO [String]
forall (m :: * -> *) a. Monad m => a -> m a
return [String
x]
                Nothing -> (String -> Bool)
-> [String] -> [String] -> Maybe String -> String -> IO [String]
getFile String -> Bool
ignore [String]
ath [String]
exts Maybe String
t String
file


getModule :: FilePath -> [String] -> FilePath -> IO (Maybe FilePath)
getModule :: String -> [String] -> String -> IO (Maybe String)
getModule path :: String
path exts :: [String]
exts x :: String
x | Bool -> Bool
not ((Char -> Bool) -> String -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any Char -> Bool
isSpace String
x) Bool -> Bool -> Bool
&& (String -> Bool) -> [String] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all String -> Bool
isMod [String]
xs = [String] -> IO (Maybe String)
f [String]
exts
    where
        xs :: [String]
xs = String -> [String]
words (String -> [String]) -> String -> [String]
forall a b. (a -> b) -> a -> b
$ (Char -> Char) -> String -> String
forall a b. (a -> b) -> [a] -> [b]
map (\x :: Char
x -> if Char
x Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== '.' then ' ' else Char
x) String
x
        isMod :: String -> Bool
isMod (x :: Char
x:xs :: String
xs) = Char -> Bool
isUpper Char
x Bool -> Bool -> Bool
&& (Char -> Bool) -> String -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (\x :: Char
x -> Char -> Bool
isAlphaNum Char
x Bool -> Bool -> Bool
|| Char
x Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== '_') String
xs
        isMod _ = Bool
False
        pre :: String
pre = String
path String -> String -> String
<\> [String] -> String
joinPath [String]
xs

        f :: [String] -> IO (Maybe String)
f [] = Maybe String -> IO (Maybe String)
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe String
forall a. Maybe a
Nothing
        f (x :: String
x:xs :: [String]
xs) = do
            let s :: String
s = String
pre String -> String -> String
<.> String
x
            Bool
b <- String -> IO Bool
doesFileExist String
s
            if Bool
b then Maybe String -> IO (Maybe String)
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe String -> IO (Maybe String))
-> Maybe String -> IO (Maybe String)
forall a b. (a -> b) -> a -> b
$ String -> Maybe String
forall a. a -> Maybe a
Just String
s else [String] -> IO (Maybe String)
f [String]
xs
getModule _ _ _ = Maybe String -> IO (Maybe String)
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe String
forall a. Maybe a
Nothing


getExtensions :: [String] -> (Language, [Extension])
getExtensions :: [String] -> (Language, [Extension])
getExtensions args :: [String]
args = (Language
lang, ([Extension] -> String -> [Extension])
-> [Extension] -> [String] -> [Extension]
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl [Extension] -> String -> [Extension]
f (if [String] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [String]
langs then [Extension]
parseExtensions else []) [String]
exts)
    where
        lang :: Language
lang = if [String] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [String]
langs then ParseMode -> Language
baseLanguage ParseMode
defaultParseMode else Maybe Language -> Language
forall a. HasCallStack => Maybe a -> a
fromJust (Maybe Language -> Language) -> Maybe Language -> Language
forall a b. (a -> b) -> a -> b
$ String -> [(String, Language)] -> Maybe Language
forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup ([String] -> String
forall a. [a] -> a
last [String]
langs) [(String, Language)]
ls
        (langs :: [String]
langs, exts :: [String]
exts) = (String -> Bool) -> [String] -> ([String], [String])
forall a. (a -> Bool) -> [a] -> ([a], [a])
partition (Maybe Language -> Bool
forall a. Maybe a -> Bool
isJust (Maybe Language -> Bool)
-> (String -> Maybe Language) -> String -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String -> [(String, Language)] -> Maybe Language)
-> [(String, Language)] -> String -> Maybe Language
forall a b c. (a -> b -> c) -> b -> a -> c
flip String -> [(String, Language)] -> Maybe Language
forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup [(String, Language)]
ls) [String]
args
        ls :: [(String, Language)]
ls = [(Language -> String
forall a. Show a => a -> String
show Language
x, Language
x) | Language
x <- [Language]
knownLanguages]

        f :: [Extension] -> String -> [Extension]
f a :: [Extension]
a "Haskell98" = []
        f a :: [Extension]
a ('N':'o':x :: String
x) | Just x :: Extension
x <- String -> Maybe Extension
readExtension String
x = Extension -> [Extension] -> [Extension]
forall a. Eq a => a -> [a] -> [a]
delete Extension
x [Extension]
a
        f a :: [Extension]
a x :: String
x | Just x :: Extension
x <- String -> Maybe Extension
readExtension String
x = Extension
x Extension -> [Extension] -> [Extension]
forall a. a -> [a] -> [a]
: Extension -> [Extension] -> [Extension]
forall a. Eq a => a -> [a] -> [a]
delete Extension
x [Extension]
a
        f a :: [Extension]
a x :: String
x = String -> Extension
UnknownExtension String
x Extension -> [Extension] -> [Extension]
forall a. a -> [a] -> [a]
: Extension -> [Extension] -> [Extension]
forall a. Eq a => a -> [a] -> [a]
delete (String -> Extension
UnknownExtension String
x) [Extension]
a


readExtension :: String -> Maybe Extension
readExtension :: String -> Maybe Extension
readExtension x :: String
x = case String -> Extension
classifyExtension String
x of
    UnknownExtension _ -> Maybe Extension
forall a. Maybe a
Nothing
    x :: Extension
x -> Extension -> Maybe Extension
forall a. a -> Maybe a
Just Extension
x