module Splint
( plugin
)
where
import qualified Bag as GHC
import qualified Control.Concurrent as Concurrent
import qualified Control.Concurrent.STM as Stm
import qualified Control.Exception as Exception
import qualified Control.Monad.IO.Class as IO
import qualified Data.Map as Map
import qualified ErrUtils as GHC
import qualified GhcPlugins as GHC
import qualified Language.Haskell.HLint as HLint
import qualified Splint.Parser as Splint
import qualified System.IO.Unsafe as Unsafe
plugin :: GHC.Plugin
plugin :: Plugin
plugin = Plugin
GHC.defaultPlugin
{ parsedResultAction :: [CommandLineOption]
-> ModSummary -> HsParsedModule -> Hsc HsParsedModule
GHC.parsedResultAction = [CommandLineOption]
-> ModSummary -> HsParsedModule -> Hsc HsParsedModule
action
, pluginRecompile :: [CommandLineOption] -> IO PluginRecompile
GHC.pluginRecompile = [CommandLineOption] -> IO PluginRecompile
GHC.purePlugin
}
action
:: [GHC.CommandLineOption]
-> GHC.ModSummary
-> GHC.HsParsedModule
-> GHC.Hsc GHC.HsParsedModule
action :: [CommandLineOption]
-> ModSummary -> HsParsedModule -> Hsc HsParsedModule
action [CommandLineOption]
commandLineOptions ModSummary
modSummary HsParsedModule
hsParsedModule = do
(ParseFlags
parseFlags, [Classify]
classifies, Hint
hint) <- [CommandLineOption] -> Hsc (ParseFlags, [Classify], Hint)
getSettings [CommandLineOption]
commandLineOptions
ModuleEx
moduleEx <- ParseFlags -> ModSummary -> HsParsedModule -> Hsc ModuleEx
Splint.parse ParseFlags
parseFlags ModSummary
modSummary HsParsedModule
hsParsedModule
DynFlags
dynFlags <- Hsc DynFlags
forall (m :: * -> *). HasDynFlags m => m DynFlags
GHC.getDynFlags
IO () -> Hsc ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
io
(IO () -> Hsc ()) -> ([Idea] -> IO ()) -> [Idea] -> Hsc ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. DynFlags -> Bag WarnMsg -> IO ()
GHC.printOrThrowWarnings DynFlags
dynFlags
(Bag WarnMsg -> IO ())
-> ([Idea] -> Bag WarnMsg) -> [Idea] -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [WarnMsg] -> Bag WarnMsg
forall a. [a] -> Bag a
GHC.listToBag
([WarnMsg] -> Bag WarnMsg)
-> ([Idea] -> [WarnMsg]) -> [Idea] -> Bag WarnMsg
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Idea -> WarnMsg) -> [Idea] -> [WarnMsg]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (DynFlags -> Idea -> WarnMsg
ideaToWarnMsg DynFlags
dynFlags)
([Idea] -> [WarnMsg]) -> ([Idea] -> [Idea]) -> [Idea] -> [WarnMsg]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Idea -> Bool) -> [Idea] -> [Idea]
forall a. (a -> Bool) -> [a] -> [a]
filter ((Severity -> Severity -> Bool
forall a. Eq a => a -> a -> Bool
/= Severity
HLint.Ignore) (Severity -> Bool) -> (Idea -> Severity) -> Idea -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Idea -> Severity
HLint.ideaSeverity)
([Idea] -> Hsc ()) -> [Idea] -> Hsc ()
forall a b. (a -> b) -> a -> b
$ [Classify] -> Hint -> [ModuleEx] -> [Idea]
HLint.applyHints [Classify]
classifies Hint
hint [ModuleEx
moduleEx]
HsParsedModule -> Hsc HsParsedModule
forall (f :: * -> *) a. Applicative f => a -> f a
pure HsParsedModule
hsParsedModule
type Settings = (HLint.ParseFlags, [HLint.Classify], HLint.Hint)
getSettings :: [String] -> GHC.Hsc Settings
getSettings :: [CommandLineOption] -> Hsc (ParseFlags, [Classify], Hint)
getSettings [CommandLineOption]
options = do
let insert :: RemoteData IOException (ParseFlags, [Classify], Hint) -> STM ()
insert = TVar
(Map
[CommandLineOption]
(RemoteData IOException (ParseFlags, [Classify], Hint)))
-> (Map
[CommandLineOption]
(RemoteData IOException (ParseFlags, [Classify], Hint))
-> Map
[CommandLineOption]
(RemoteData IOException (ParseFlags, [Classify], Hint)))
-> STM ()
forall a. TVar a -> (a -> a) -> STM ()
Stm.modifyTVar TVar
(Map
[CommandLineOption]
(RemoteData IOException (ParseFlags, [Classify], Hint)))
settingsTVar ((Map
[CommandLineOption]
(RemoteData IOException (ParseFlags, [Classify], Hint))
-> Map
[CommandLineOption]
(RemoteData IOException (ParseFlags, [Classify], Hint)))
-> STM ())
-> (RemoteData IOException (ParseFlags, [Classify], Hint)
-> Map
[CommandLineOption]
(RemoteData IOException (ParseFlags, [Classify], Hint))
-> Map
[CommandLineOption]
(RemoteData IOException (ParseFlags, [Classify], Hint)))
-> RemoteData IOException (ParseFlags, [Classify], Hint)
-> STM ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [CommandLineOption]
-> RemoteData IOException (ParseFlags, [Classify], Hint)
-> Map
[CommandLineOption]
(RemoteData IOException (ParseFlags, [Classify], Hint))
-> Map
[CommandLineOption]
(RemoteData IOException (ParseFlags, [Classify], Hint))
forall k a. Ord k => k -> a -> Map k a -> Map k a
Map.insert [CommandLineOption]
options
RemoteData IOException (ParseFlags, [Classify], Hint)
remoteData <- IO (RemoteData IOException (ParseFlags, [Classify], Hint))
-> Hsc (RemoteData IOException (ParseFlags, [Classify], Hint))
forall (m :: * -> *) a. MonadIO m => IO a -> m a
io (IO (RemoteData IOException (ParseFlags, [Classify], Hint))
-> Hsc (RemoteData IOException (ParseFlags, [Classify], Hint)))
-> (STM (RemoteData IOException (ParseFlags, [Classify], Hint))
-> IO (RemoteData IOException (ParseFlags, [Classify], Hint)))
-> STM (RemoteData IOException (ParseFlags, [Classify], Hint))
-> Hsc (RemoteData IOException (ParseFlags, [Classify], Hint))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. STM (RemoteData IOException (ParseFlags, [Classify], Hint))
-> IO (RemoteData IOException (ParseFlags, [Classify], Hint))
forall a. STM a -> IO a
stm (STM (RemoteData IOException (ParseFlags, [Classify], Hint))
-> Hsc (RemoteData IOException (ParseFlags, [Classify], Hint)))
-> STM (RemoteData IOException (ParseFlags, [Classify], Hint))
-> Hsc (RemoteData IOException (ParseFlags, [Classify], Hint))
forall a b. (a -> b) -> a -> b
$ do
Map
[CommandLineOption]
(RemoteData IOException (ParseFlags, [Classify], Hint))
settings <- TVar
(Map
[CommandLineOption]
(RemoteData IOException (ParseFlags, [Classify], Hint)))
-> STM
(Map
[CommandLineOption]
(RemoteData IOException (ParseFlags, [Classify], Hint)))
forall a. TVar a -> STM a
Stm.readTVar TVar
(Map
[CommandLineOption]
(RemoteData IOException (ParseFlags, [Classify], Hint)))
settingsTVar
let remoteData :: RemoteData IOException (ParseFlags, [Classify], Hint)
remoteData = RemoteData IOException (ParseFlags, [Classify], Hint)
-> [CommandLineOption]
-> Map
[CommandLineOption]
(RemoteData IOException (ParseFlags, [Classify], Hint))
-> RemoteData IOException (ParseFlags, [Classify], Hint)
forall k a. Ord k => a -> k -> Map k a -> a
Map.findWithDefault RemoteData IOException (ParseFlags, [Classify], Hint)
forall e a. RemoteData e a
NotAsked [CommandLineOption]
options Map
[CommandLineOption]
(RemoteData IOException (ParseFlags, [Classify], Hint))
settings
case RemoteData IOException (ParseFlags, [Classify], Hint)
remoteData of
RemoteData IOException (ParseFlags, [Classify], Hint)
NotAsked -> RemoteData IOException (ParseFlags, [Classify], Hint) -> STM ()
insert RemoteData IOException (ParseFlags, [Classify], Hint)
forall e a. RemoteData e a
Loading
RemoteData IOException (ParseFlags, [Classify], Hint)
_ -> () -> STM ()
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
RemoteData IOException (ParseFlags, [Classify], Hint)
-> STM (RemoteData IOException (ParseFlags, [Classify], Hint))
forall (f :: * -> *) a. Applicative f => a -> f a
pure RemoteData IOException (ParseFlags, [Classify], Hint)
remoteData
case RemoteData IOException (ParseFlags, [Classify], Hint)
remoteData of
RemoteData IOException (ParseFlags, [Classify], Hint)
NotAsked -> IO (ParseFlags, [Classify], Hint)
-> Hsc (ParseFlags, [Classify], Hint)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
io (IO (ParseFlags, [Classify], Hint)
-> Hsc (ParseFlags, [Classify], Hint))
-> (IO (ParseFlags, [Classify], Hint)
-> IO (ParseFlags, [Classify], Hint))
-> IO (ParseFlags, [Classify], Hint)
-> Hsc (ParseFlags, [Classify], Hint)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TMVar ()
-> (() -> IO (ParseFlags, [Classify], Hint))
-> IO (ParseFlags, [Classify], Hint)
forall a b. TMVar a -> (a -> IO b) -> IO b
withTMVar TMVar ()
settingsTMVar ((() -> IO (ParseFlags, [Classify], Hint))
-> IO (ParseFlags, [Classify], Hint))
-> (IO (ParseFlags, [Classify], Hint)
-> () -> IO (ParseFlags, [Classify], Hint))
-> IO (ParseFlags, [Classify], Hint)
-> IO (ParseFlags, [Classify], Hint)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IO (ParseFlags, [Classify], Hint)
-> () -> IO (ParseFlags, [Classify], Hint)
forall a b. a -> b -> a
const (IO (ParseFlags, [Classify], Hint)
-> Hsc (ParseFlags, [Classify], Hint))
-> IO (ParseFlags, [Classify], Hint)
-> Hsc (ParseFlags, [Classify], Hint)
forall a b. (a -> b) -> a -> b
$ do
Either IOException (ParseFlags, [Classify], Hint)
result <- IO (ParseFlags, [Classify], Hint)
-> IO (Either IOException (ParseFlags, [Classify], Hint))
forall e a. Exception e => IO a -> IO (Either e a)
Exception.try (IO (ParseFlags, [Classify], Hint)
-> IO (Either IOException (ParseFlags, [Classify], Hint)))
-> IO (ParseFlags, [Classify], Hint)
-> IO (Either IOException (ParseFlags, [Classify], Hint))
forall a b. (a -> b) -> a -> b
$ [CommandLineOption] -> IO (ParseFlags, [Classify], Hint)
HLint.argsSettings [CommandLineOption]
options
case Either IOException (ParseFlags, [Classify], Hint)
result of
Left IOException
ioException -> do
STM () -> IO ()
forall a. STM a -> IO a
stm (STM () -> IO ())
-> (RemoteData IOException (ParseFlags, [Classify], Hint)
-> STM ())
-> RemoteData IOException (ParseFlags, [Classify], Hint)
-> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RemoteData IOException (ParseFlags, [Classify], Hint) -> STM ()
insert (RemoteData IOException (ParseFlags, [Classify], Hint) -> IO ())
-> RemoteData IOException (ParseFlags, [Classify], Hint) -> IO ()
forall a b. (a -> b) -> a -> b
$ IOException
-> RemoteData IOException (ParseFlags, [Classify], Hint)
forall e a. e -> RemoteData e a
Failure IOException
ioException
IOException -> IO (ParseFlags, [Classify], Hint)
forall e a. Exception e => e -> IO a
Exception.throwIO IOException
ioException
Right (ParseFlags, [Classify], Hint)
settings -> do
STM () -> IO ()
forall a. STM a -> IO a
stm (STM () -> IO ())
-> (RemoteData IOException (ParseFlags, [Classify], Hint)
-> STM ())
-> RemoteData IOException (ParseFlags, [Classify], Hint)
-> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RemoteData IOException (ParseFlags, [Classify], Hint) -> STM ()
insert (RemoteData IOException (ParseFlags, [Classify], Hint) -> IO ())
-> RemoteData IOException (ParseFlags, [Classify], Hint) -> IO ()
forall a b. (a -> b) -> a -> b
$ (ParseFlags, [Classify], Hint)
-> RemoteData IOException (ParseFlags, [Classify], Hint)
forall e a. a -> RemoteData e a
Success (ParseFlags, [Classify], Hint)
settings
(ParseFlags, [Classify], Hint) -> IO (ParseFlags, [Classify], Hint)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ParseFlags, [Classify], Hint)
settings
RemoteData IOException (ParseFlags, [Classify], Hint)
Loading -> do
IO () -> Hsc ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
io (IO () -> Hsc ()) -> IO () -> Hsc ()
forall a b. (a -> b) -> a -> b
$ Int -> IO ()
Concurrent.threadDelay Int
1000
[CommandLineOption] -> Hsc (ParseFlags, [Classify], Hint)
getSettings [CommandLineOption]
options
Failure IOException
ioException -> IO (ParseFlags, [Classify], Hint)
-> Hsc (ParseFlags, [Classify], Hint)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
io (IO (ParseFlags, [Classify], Hint)
-> Hsc (ParseFlags, [Classify], Hint))
-> IO (ParseFlags, [Classify], Hint)
-> Hsc (ParseFlags, [Classify], Hint)
forall a b. (a -> b) -> a -> b
$ IOException -> IO (ParseFlags, [Classify], Hint)
forall e a. Exception e => e -> IO a
Exception.throwIO IOException
ioException
Success (ParseFlags, [Classify], Hint)
settings -> (ParseFlags, [Classify], Hint)
-> Hsc (ParseFlags, [Classify], Hint)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ParseFlags, [Classify], Hint)
settings
io :: IO.MonadIO m => IO a -> m a
io :: IO a -> m a
io = IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
GHC.liftIO
stm :: Stm.STM a -> IO a
stm :: STM a -> IO a
stm = STM a -> IO a
forall a. STM a -> IO a
Stm.atomically
withTMVar :: Stm.TMVar a -> (a -> IO b) -> IO b
withTMVar :: TMVar a -> (a -> IO b) -> IO b
withTMVar TMVar a
var =
IO a -> (a -> IO ()) -> (a -> IO b) -> IO b
forall a b c. IO a -> (a -> IO b) -> (a -> IO c) -> IO c
Exception.bracket (STM a -> IO a
forall a. STM a -> IO a
stm (STM a -> IO a) -> STM a -> IO a
forall a b. (a -> b) -> a -> b
$ TMVar a -> STM a
forall a. TMVar a -> STM a
Stm.takeTMVar TMVar a
var) (STM () -> IO ()
forall a. STM a -> IO a
stm (STM () -> IO ()) -> (a -> STM ()) -> a -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TMVar a -> a -> STM ()
forall a. TMVar a -> a -> STM ()
Stm.putTMVar TMVar a
var)
settingsTVar
:: Stm.TVar (Map.Map [String] (RemoteData Exception.IOException Settings))
settingsTVar :: TVar
(Map
[CommandLineOption]
(RemoteData IOException (ParseFlags, [Classify], Hint)))
settingsTVar = IO
(TVar
(Map
[CommandLineOption]
(RemoteData IOException (ParseFlags, [Classify], Hint))))
-> TVar
(Map
[CommandLineOption]
(RemoteData IOException (ParseFlags, [Classify], Hint)))
forall a. IO a -> a
Unsafe.unsafePerformIO (IO
(TVar
(Map
[CommandLineOption]
(RemoteData IOException (ParseFlags, [Classify], Hint))))
-> TVar
(Map
[CommandLineOption]
(RemoteData IOException (ParseFlags, [Classify], Hint))))
-> IO
(TVar
(Map
[CommandLineOption]
(RemoteData IOException (ParseFlags, [Classify], Hint))))
-> TVar
(Map
[CommandLineOption]
(RemoteData IOException (ParseFlags, [Classify], Hint)))
forall a b. (a -> b) -> a -> b
$ Map
[CommandLineOption]
(RemoteData IOException (ParseFlags, [Classify], Hint))
-> IO
(TVar
(Map
[CommandLineOption]
(RemoteData IOException (ParseFlags, [Classify], Hint))))
forall a. a -> IO (TVar a)
Stm.newTVarIO Map
[CommandLineOption]
(RemoteData IOException (ParseFlags, [Classify], Hint))
forall k a. Map k a
Map.empty
{-# NOINLINE settingsTVar #-}
settingsTMVar :: Stm.TMVar ()
settingsTMVar :: TMVar ()
settingsTMVar = IO (TMVar ()) -> TMVar ()
forall a. IO a -> a
Unsafe.unsafePerformIO (IO (TMVar ()) -> TMVar ()) -> IO (TMVar ()) -> TMVar ()
forall a b. (a -> b) -> a -> b
$ () -> IO (TMVar ())
forall a. a -> IO (TMVar a)
Stm.newTMVarIO ()
{-# NOINLINE settingsTMVar #-}
data RemoteData e a
= NotAsked
| Loading
| Failure e
| Success a
deriving (RemoteData e a -> RemoteData e a -> Bool
(RemoteData e a -> RemoteData e a -> Bool)
-> (RemoteData e a -> RemoteData e a -> Bool)
-> Eq (RemoteData e a)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall e a.
(Eq e, Eq a) =>
RemoteData e a -> RemoteData e a -> Bool
/= :: RemoteData e a -> RemoteData e a -> Bool
$c/= :: forall e a.
(Eq e, Eq a) =>
RemoteData e a -> RemoteData e a -> Bool
== :: RemoteData e a -> RemoteData e a -> Bool
$c== :: forall e a.
(Eq e, Eq a) =>
RemoteData e a -> RemoteData e a -> Bool
Eq, Int -> RemoteData e a -> ShowS
[RemoteData e a] -> ShowS
RemoteData e a -> CommandLineOption
(Int -> RemoteData e a -> ShowS)
-> (RemoteData e a -> CommandLineOption)
-> ([RemoteData e a] -> ShowS)
-> Show (RemoteData e a)
forall a.
(Int -> a -> ShowS)
-> (a -> CommandLineOption) -> ([a] -> ShowS) -> Show a
forall e a. (Show e, Show a) => Int -> RemoteData e a -> ShowS
forall e a. (Show e, Show a) => [RemoteData e a] -> ShowS
forall e a. (Show e, Show a) => RemoteData e a -> CommandLineOption
showList :: [RemoteData e a] -> ShowS
$cshowList :: forall e a. (Show e, Show a) => [RemoteData e a] -> ShowS
show :: RemoteData e a -> CommandLineOption
$cshow :: forall e a. (Show e, Show a) => RemoteData e a -> CommandLineOption
showsPrec :: Int -> RemoteData e a -> ShowS
$cshowsPrec :: forall e a. (Show e, Show a) => Int -> RemoteData e a -> ShowS
Show)
ideaToWarnMsg :: GHC.DynFlags -> HLint.Idea -> GHC.WarnMsg
ideaToWarnMsg :: DynFlags -> Idea -> WarnMsg
ideaToWarnMsg DynFlags
dynFlags Idea
idea =
let
mkErrMsg :: DynFlags -> SrcSpan -> MsgDoc -> WarnMsg
mkErrMsg = case Idea -> Severity
HLint.ideaSeverity Idea
idea of
Severity
HLint.Error -> DynFlags -> SrcSpan -> MsgDoc -> WarnMsg
GHC.mkPlainErrMsg
Severity
_ -> DynFlags -> SrcSpan -> MsgDoc -> WarnMsg
GHC.mkPlainWarnMsg
srcSpan :: SrcSpan
srcSpan = case SrcSpan -> Maybe (CommandLineOption, (Int, Int), (Int, Int))
HLint.unpackSrcSpan (SrcSpan -> Maybe (CommandLineOption, (Int, Int), (Int, Int)))
-> SrcSpan -> Maybe (CommandLineOption, (Int, Int), (Int, Int))
forall a b. (a -> b) -> a -> b
$ Idea -> SrcSpan
HLint.ideaSpan Idea
idea of
Maybe (CommandLineOption, (Int, Int), (Int, Int))
Nothing -> SrcSpan
GHC.noSrcSpan
Just (CommandLineOption
file, (Int
startLine, Int
startColumn), (Int
endLine, Int
endColumn)) ->
SrcLoc -> SrcLoc -> SrcSpan
GHC.mkSrcSpan
(FastString -> Int -> Int -> SrcLoc
GHC.mkSrcLoc (CommandLineOption -> FastString
GHC.mkFastString CommandLineOption
file) Int
startLine Int
startColumn)
(FastString -> Int -> Int -> SrcLoc
GHC.mkSrcLoc (CommandLineOption -> FastString
GHC.mkFastString CommandLineOption
file) Int
endLine Int
endColumn)
msgDoc :: MsgDoc
msgDoc = Idea -> MsgDoc
ideaToMsgDoc Idea
idea
in DynFlags -> SrcSpan -> MsgDoc -> WarnMsg
mkErrMsg DynFlags
dynFlags SrcSpan
srcSpan MsgDoc
msgDoc
ideaToMsgDoc :: HLint.Idea -> GHC.MsgDoc
ideaToMsgDoc :: Idea -> MsgDoc
ideaToMsgDoc Idea
idea = [MsgDoc] -> MsgDoc
GHC.vcat
[ CommandLineOption -> MsgDoc
GHC.text (CommandLineOption -> MsgDoc) -> CommandLineOption -> MsgDoc
forall a b. (a -> b) -> a -> b
$ Idea -> CommandLineOption
HLint.ideaHint Idea
idea
, case Idea -> Maybe CommandLineOption
HLint.ideaTo Idea
idea of
Just CommandLineOption
to | Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ CommandLineOption -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null CommandLineOption
to -> CommandLineOption -> MsgDoc
GHC.text (CommandLineOption -> MsgDoc) -> CommandLineOption -> MsgDoc
forall a b. (a -> b) -> a -> b
$ CommandLineOption
"Perhaps: " CommandLineOption -> ShowS
forall a. Semigroup a => a -> a -> a
<> CommandLineOption
to
Maybe CommandLineOption
_ -> MsgDoc
GHC.empty
, [MsgDoc] -> MsgDoc
GHC.vcat ([MsgDoc] -> MsgDoc) -> ([Note] -> [MsgDoc]) -> [Note] -> MsgDoc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Note -> MsgDoc) -> [Note] -> [MsgDoc]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (CommandLineOption -> MsgDoc
GHC.text (CommandLineOption -> MsgDoc)
-> (Note -> CommandLineOption) -> Note -> MsgDoc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CommandLineOption -> ShowS
forall a. Monoid a => a -> a -> a
mappend CommandLineOption
"Note: " ShowS -> (Note -> CommandLineOption) -> Note -> CommandLineOption
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Note -> CommandLineOption
forall a. Show a => a -> CommandLineOption
show) ([Note] -> MsgDoc) -> [Note] -> MsgDoc
forall a b. (a -> b) -> a -> b
$ Idea -> [Note]
HLint.ideaNote Idea
idea
]