hlint-1.8.58: src/HLint.hs
{-# LANGUAGE RecordWildCards #-}
module HLint(hlint, Suggestion, suggestionLocation, suggestionSeverity, Severity(..)) where
import Control.Applicative
import Control.Monad
import System.Console.CmdArgs.Verbosity
import Data.List
import System.Exit
import CmdLine
import Settings
import Report
import Idea
import Apply
import Test
import Proof
import Util
import Parallel
import HSE.All
-- | A suggestion - the @Show@ instance is of particular use.
newtype Suggestion = Suggestion {fromSuggestion :: Idea}
deriving (Eq,Ord)
instance Show Suggestion where
show = show . fromSuggestion
-- | From a suggestion, extract the file location it refers to.
suggestionLocation :: Suggestion -> SrcLoc
suggestionLocation = getPointLoc . ideaSpan . fromSuggestion
-- | From a suggestion, determine how severe it is.
suggestionSeverity :: Suggestion -> Severity
suggestionSeverity = ideaSeverity . fromSuggestion
-- | This function takes a list of command line arguments, and returns the given suggestions.
-- To see a list of arguments type @hlint --help@ at the console.
-- This function writes to the stdout/stderr streams, unless @--quiet@ is specified.
--
-- As an example:
--
-- > do hints <- hlint ["src", "--ignore=Use map","--quiet"]
-- > when (length hints > 3) $ error "Too many hints!"
hlint :: [String] -> IO [Suggestion]
hlint args = do
cmd@Cmd{..} <- getCmd args
encoding <- readEncoding cmdEncoding
let flags = parseFlagsSetExtensions (cmdExtensions cmd) $ defaultParseFlags{cppFlags=cmdCpp cmd, encoding=encoding}
if cmdTest then do
failed <- test (void . hlint) cmdDataDir cmdGivenHints
when (failed > 0) exitFailure
return []
else if notNull cmdProof then do
s <- readAllSettings cmd flags
let reps = if cmdReports == ["report.html"] then ["report.txt"] else cmdReports
mapM_ (proof reps s) cmdProof
return []
else if null cmdFiles && notNull cmdFindHints then do
hints <- concatMapM (resolveFile cmd) cmdFindHints
mapM_ (\x -> putStrLn . fst =<< findSettings2 flags x) hints >> return []
else if null cmdFiles then
exitWithHelp
else do
files <- concatMapM (resolveFile cmd) cmdFiles
if null files then
error "No files found"
else
runHints cmd{cmdFiles=files} flags
readAllSettings :: Cmd -> ParseFlags -> IO [Setting]
readAllSettings cmd@Cmd{..} flags = do
files <- cmdHintFiles cmd
settings1 <- readSettings2 cmdDataDir files cmdWithHints
settings2 <- concatMapM (fmap snd . findSettings2 flags) cmdFindHints
settings3 <- return [SettingClassify $ Classify Ignore x "" "" | x <- cmdIgnore]
return $ settings1 ++ settings2 ++ settings3
runHints :: Cmd -> ParseFlags -> IO [Suggestion]
runHints cmd@Cmd{..} flags = do
let outStrLn = whenNormal . putStrLn
settings <- readAllSettings cmd flags
ideas <- if cmdCross
then applyHintFiles flags settings cmdFiles
else concat <$> parallel [listM' =<< applyHintFile flags settings x Nothing | x <- cmdFiles]
let (showideas,hideideas) = partition (\i -> cmdShowAll || ideaSeverity i /= Ignore) ideas
showItem <- if cmdColor then showANSI else return show
mapM_ (outStrLn . showItem) showideas
if null showideas then
when (cmdReports /= []) $ outStrLn "Skipping writing reports"
else
forM_ cmdReports $ \x -> do
outStrLn $ "Writing report to " ++ x ++ " ..."
writeReport cmdDataDir x showideas
outStrLn $
(let i = length showideas in if i == 0 then "No suggestions" else show i ++ " suggestion" ++ ['s'|i/=1]) ++
(let i = length hideideas in if i == 0 then "" else " (" ++ show i ++ " ignored)")
return $ map Suggestion showideas