module Hint.All(
    Hint(..), ModuHint,
    resolveHints, hintRules, builtinHints
    ) where

import Data.Monoid
import Config.Type
import Data.Either
import Data.List.Extra
import Hint.Type
import Timing
import Util
import Prelude

import Hint.Match
import Hint.List
import Hint.ListRec
import Hint.Monad
import Hint.Lambda
import Hint.Bracket
import Hint.Fixities
import Hint.Naming
import Hint.Pattern
import Hint.Import
import Hint.Export
import Hint.Pragma
import Hint.Restrict
import Hint.Extensions
import Hint.Duplicate
import Hint.Comment
import Hint.Unsafe
import Hint.NewType
import Hint.Smell
import Hint.NumLiteral

-- | A list of the builtin hints wired into HLint.
--   This list is likely to grow over time.
data HintBuiltin =
    HintList | HintListRec | HintMonad | HintLambda | HintFixities |
    HintBracket | HintNaming | HintPattern | HintImport | HintExport |
    HintPragma | HintExtensions | HintUnsafe | HintDuplicate | HintRestrict |
    HintComment | HintNewType | HintSmell | HintNumLiteral
    deriving (Int -> HintBuiltin -> ShowS
[HintBuiltin] -> ShowS
HintBuiltin -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [HintBuiltin] -> ShowS
$cshowList :: [HintBuiltin] -> ShowS
show :: HintBuiltin -> String
$cshow :: HintBuiltin -> String
showsPrec :: Int -> HintBuiltin -> ShowS
$cshowsPrec :: Int -> HintBuiltin -> ShowS
Show,HintBuiltin -> HintBuiltin -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: HintBuiltin -> HintBuiltin -> Bool
$c/= :: HintBuiltin -> HintBuiltin -> Bool
== :: HintBuiltin -> HintBuiltin -> Bool
$c== :: HintBuiltin -> HintBuiltin -> Bool
Eq,Eq HintBuiltin
HintBuiltin -> HintBuiltin -> Bool
HintBuiltin -> HintBuiltin -> Ordering
HintBuiltin -> HintBuiltin -> HintBuiltin
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: HintBuiltin -> HintBuiltin -> HintBuiltin
$cmin :: HintBuiltin -> HintBuiltin -> HintBuiltin
max :: HintBuiltin -> HintBuiltin -> HintBuiltin
$cmax :: HintBuiltin -> HintBuiltin -> HintBuiltin
>= :: HintBuiltin -> HintBuiltin -> Bool
$c>= :: HintBuiltin -> HintBuiltin -> Bool
> :: HintBuiltin -> HintBuiltin -> Bool
$c> :: HintBuiltin -> HintBuiltin -> Bool
<= :: HintBuiltin -> HintBuiltin -> Bool
$c<= :: HintBuiltin -> HintBuiltin -> Bool
< :: HintBuiltin -> HintBuiltin -> Bool
$c< :: HintBuiltin -> HintBuiltin -> Bool
compare :: HintBuiltin -> HintBuiltin -> Ordering
$ccompare :: HintBuiltin -> HintBuiltin -> Ordering
Ord,HintBuiltin
forall a. a -> a -> Bounded a
maxBound :: HintBuiltin
$cmaxBound :: HintBuiltin
minBound :: HintBuiltin
$cminBound :: HintBuiltin
Bounded,Int -> HintBuiltin
HintBuiltin -> Int
HintBuiltin -> [HintBuiltin]
HintBuiltin -> HintBuiltin
HintBuiltin -> HintBuiltin -> [HintBuiltin]
HintBuiltin -> HintBuiltin -> HintBuiltin -> [HintBuiltin]
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: HintBuiltin -> HintBuiltin -> HintBuiltin -> [HintBuiltin]
$cenumFromThenTo :: HintBuiltin -> HintBuiltin -> HintBuiltin -> [HintBuiltin]
enumFromTo :: HintBuiltin -> HintBuiltin -> [HintBuiltin]
$cenumFromTo :: HintBuiltin -> HintBuiltin -> [HintBuiltin]
enumFromThen :: HintBuiltin -> HintBuiltin -> [HintBuiltin]
$cenumFromThen :: HintBuiltin -> HintBuiltin -> [HintBuiltin]
enumFrom :: HintBuiltin -> [HintBuiltin]
$cenumFrom :: HintBuiltin -> [HintBuiltin]
fromEnum :: HintBuiltin -> Int
$cfromEnum :: HintBuiltin -> Int
toEnum :: Int -> HintBuiltin
$ctoEnum :: Int -> HintBuiltin
pred :: HintBuiltin -> HintBuiltin
$cpred :: HintBuiltin -> HintBuiltin
succ :: HintBuiltin -> HintBuiltin
$csucc :: HintBuiltin -> HintBuiltin
Enum)

-- See https://github.com/ndmitchell/hlint/issues/1150 - Duplicate is too slow
-- and doesn't provide much value anyway.
issue1150 :: Bool
issue1150 = Bool
True

builtin :: HintBuiltin -> Hint
builtin :: HintBuiltin -> Hint
builtin HintBuiltin
x = case HintBuiltin
x of
    HintBuiltin
HintLambda     -> (Scope
 -> ModuleEx -> GenLocated SrcSpanAnnA (HsDecl GhcPs) -> [Idea])
-> Hint
decl DeclHint
lambdaHint
    HintBuiltin
HintImport     -> (Scope -> ModuleEx -> [Idea]) -> Hint
modu Scope -> ModuleEx -> [Idea]
importHint
    HintBuiltin
HintExport     -> (Scope -> ModuleEx -> [Idea]) -> Hint
modu Scope -> ModuleEx -> [Idea]
exportHint
    HintBuiltin
HintComment    -> (Scope -> ModuleEx -> [Idea]) -> Hint
modu Scope -> ModuleEx -> [Idea]
commentHint
    HintBuiltin
HintPragma     -> (Scope -> ModuleEx -> [Idea]) -> Hint
modu Scope -> ModuleEx -> [Idea]
pragmaHint
    HintBuiltin
HintDuplicate  -> if Bool
issue1150 then forall a. Monoid a => a
mempty else ([(Scope, ModuleEx)] -> [Idea]) -> Hint
mods [(Scope, ModuleEx)] -> [Idea]
duplicateHint
    HintBuiltin
HintRestrict   -> forall a. Monoid a => a
mempty{hintModule :: [Setting] -> Scope -> ModuleEx -> [Idea]
hintModule=[Setting] -> Scope -> ModuleEx -> [Idea]
restrictHint}
    HintBuiltin
HintList       -> (Scope
 -> ModuleEx -> GenLocated SrcSpanAnnA (HsDecl GhcPs) -> [Idea])
-> Hint
decl DeclHint
listHint
    HintBuiltin
HintNewType    -> (Scope
 -> ModuleEx -> GenLocated SrcSpanAnnA (HsDecl GhcPs) -> [Idea])
-> Hint
decl DeclHint
newtypeHint
    HintBuiltin
HintUnsafe     -> (Scope
 -> ModuleEx -> GenLocated SrcSpanAnnA (HsDecl GhcPs) -> [Idea])
-> Hint
decl DeclHint
unsafeHint
    HintBuiltin
HintListRec    -> (Scope
 -> ModuleEx -> GenLocated SrcSpanAnnA (HsDecl GhcPs) -> [Idea])
-> Hint
decl DeclHint
listRecHint
    HintBuiltin
HintNaming     -> (Scope
 -> ModuleEx -> GenLocated SrcSpanAnnA (HsDecl GhcPs) -> [Idea])
-> Hint
decl DeclHint
namingHint
    HintBuiltin
HintBracket    -> (Scope
 -> ModuleEx -> GenLocated SrcSpanAnnA (HsDecl GhcPs) -> [Idea])
-> Hint
decl DeclHint
bracketHint
    HintBuiltin
HintFixities   -> forall a. Monoid a => a
mempty{hintDecl :: [Setting] -> DeclHint
hintDecl=[Setting] -> DeclHint
fixitiesHint}
    HintBuiltin
HintSmell      -> forall a. Monoid a => a
mempty{hintDecl :: [Setting] -> DeclHint
hintDecl=[Setting] -> DeclHint
smellHint,hintModule :: [Setting] -> Scope -> ModuleEx -> [Idea]
hintModule=[Setting] -> Scope -> ModuleEx -> [Idea]
smellModuleHint}
    HintBuiltin
HintPattern    -> (Scope
 -> ModuleEx -> GenLocated SrcSpanAnnA (HsDecl GhcPs) -> [Idea])
-> Hint
decl DeclHint
patternHint
    HintBuiltin
HintMonad      -> (Scope
 -> ModuleEx -> GenLocated SrcSpanAnnA (HsDecl GhcPs) -> [Idea])
-> Hint
decl DeclHint
monadHint
    HintBuiltin
HintExtensions -> (Scope -> ModuleEx -> [Idea]) -> Hint
modu Scope -> ModuleEx -> [Idea]
extensionsHint
    HintBuiltin
HintNumLiteral -> (Scope
 -> ModuleEx -> GenLocated SrcSpanAnnA (HsDecl GhcPs) -> [Idea])
-> Hint
decl DeclHint
numLiteralHint
    where
        wrap :: [a] -> [a]
wrap = forall a. String -> String -> a -> a
timed String
"Hint" (forall a. Int -> [a] -> [a]
drop Int
4 forall a b. (a -> b) -> a -> b
$ forall a. Show a => a -> String
show HintBuiltin
x) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. [a] -> [a]
forceList
        decl :: (Scope
 -> ModuleEx -> GenLocated SrcSpanAnnA (HsDecl GhcPs) -> [Idea])
-> Hint
decl Scope
-> ModuleEx -> GenLocated SrcSpanAnnA (HsDecl GhcPs) -> [Idea]
f = forall a. Monoid a => a
mempty{hintDecl :: [Setting] -> DeclHint
hintDecl=forall a b. a -> b -> a
const forall a b. (a -> b) -> a -> b
$ \Scope
a ModuleEx
b LHsDecl GhcPs
c -> forall a. [a] -> [a]
wrap forall a b. (a -> b) -> a -> b
$ Scope
-> ModuleEx -> GenLocated SrcSpanAnnA (HsDecl GhcPs) -> [Idea]
f Scope
a ModuleEx
b LHsDecl GhcPs
c}
        modu :: (Scope -> ModuleEx -> [Idea]) -> Hint
modu Scope -> ModuleEx -> [Idea]
f = forall a. Monoid a => a
mempty{hintModule :: [Setting] -> Scope -> ModuleEx -> [Idea]
hintModule=forall a b. a -> b -> a
const forall a b. (a -> b) -> a -> b
$ \Scope
a ModuleEx
b -> forall a. [a] -> [a]
wrap forall a b. (a -> b) -> a -> b
$ Scope -> ModuleEx -> [Idea]
f Scope
a ModuleEx
b}
        mods :: ([(Scope, ModuleEx)] -> [Idea]) -> Hint
mods [(Scope, ModuleEx)] -> [Idea]
f = forall a. Monoid a => a
mempty{hintModules :: [Setting] -> [(Scope, ModuleEx)] -> [Idea]
hintModules=forall a b. a -> b -> a
const forall a b. (a -> b) -> a -> b
$ \[(Scope, ModuleEx)]
a -> forall a. [a] -> [a]
wrap forall a b. (a -> b) -> a -> b
$ [(Scope, ModuleEx)] -> [Idea]
f [(Scope, ModuleEx)]
a}

-- | A list of builtin hints, currently including entries such as @\"List\"@ and @\"Bracket\"@.
builtinHints :: [(String, Hint)]
builtinHints :: [(String, Hint)]
builtinHints = [(forall a. Int -> [a] -> [a]
drop Int
4 forall a b. (a -> b) -> a -> b
$ forall a. Show a => a -> String
show HintBuiltin
h, HintBuiltin -> Hint
builtin HintBuiltin
h) | HintBuiltin
h <- forall a. (Enum a, Bounded a) => [a]
enumerate]

-- | Transform a list of 'HintBuiltin' or 'HintRule' into a 'Hint'.
resolveHints :: [Either HintBuiltin HintRule] -> Hint
resolveHints :: [Either HintBuiltin HintRule] -> Hint
resolveHints [Either HintBuiltin HintRule]
xs =
  forall a. Monoid a => [a] -> a
mconcat forall a b. (a -> b) -> a -> b
$ forall a. Monoid a => a
mempty{hintDecl :: [Setting] -> DeclHint
hintDecl=forall a b. a -> b -> a
const forall a b. (a -> b) -> a -> b
$ [HintRule] -> DeclHint
readMatch [HintRule]
rights} forall a. a -> [a] -> [a]
: forall a b. (a -> b) -> [a] -> [b]
map HintBuiltin -> Hint
builtin (forall a. Ord a => [a] -> [a]
nubOrd [HintBuiltin]
lefts)
  where ([HintBuiltin]
lefts,[HintRule]
rights) = forall a b. [Either a b] -> ([a], [b])
partitionEithers [Either HintBuiltin HintRule]
xs

-- | Transform a list of 'HintRule' into a 'Hint'.
hintRules :: [HintRule] -> Hint
hintRules :: [HintRule] -> Hint
hintRules = [Either HintBuiltin HintRule] -> Hint
resolveHints forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map forall a b. b -> Either a b
Right