hlint 2.0.2 → 2.0.3
raw patch · 15 files changed
+91/−46 lines, 15 filesdep ~cpphsPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: cpphs
API changes (from Hackage documentation)
Files
- CHANGES.txt +5/−0
- hlint.cabal +1/−5
- src/HSE/Match.hs +1/−1
- src/HSE/Util.hs +0/−4
- src/Hint/Duplicate.hs +1/−1
- src/Hint/Extensions.hs +48/−16
- src/Hint/Import.hs +2/−2
- src/Hint/Lambda.hs +4/−1
- src/Hint/List.hs +19/−3
- src/Hint/Pattern.hs +1/−1
- src/Hint/Pragma.hs +3/−3
- src/Hint/Unsafe.hs +1/−1
- src/Hint/Util.hs +2/−2
- src/Idea.hs +2/−3
- src/Refact.hs +1/−3
CHANGES.txt view
@@ -1,5 +1,10 @@ Changelog for HLint +2.0.3+ #312, suggest removing the DeriveAnyClass extension+ Suggest removing the DeriveLift extension+ Remove redundant parts from list comprehensions, e.g. [a | True]+ #326, fix up the bounds on the eta-reduce hint 2.0.2 #323, try and avoid malformatted JSON #324, use `backticks` in notes
hlint.cabal view
@@ -1,7 +1,7 @@ cabal-version: >= 1.18 build-type: Simple name: hlint-version: 2.0.2+version: 2.0.3 license: BSD3 license-file: LICENSE category: Development@@ -56,10 +56,6 @@ ansi-terminal >= 0.6.2, extra >= 1.4.9, refact >= 0.3-- -- Workaround for https://github.com/malcolmwallace/cpphs/issues/9- if impl(ghc < 7.6)- build-depends: cpphs < 1.20.4 if flag(gpl) build-depends: hscolour >= 1.21
src/HSE/Match.hs view
@@ -3,7 +3,7 @@ module HSE.Match( View(..), Named(..), (~=), isSym,- App2(..), PVar_(..), Var_(..), PApp_(..)+ App2(App2), PVar_(PVar_), Var_(Var_), PApp_(PApp_) ) where import Data.Char
src/HSE/Util.hs view
@@ -87,7 +87,6 @@ isCon Con{} = True; isCon _ = False isApp App{} = True; isApp _ = False isInfixApp InfixApp{} = True; isInfixApp _ = False-isList List{} = True; isList _ = False isAnyApp x = isApp x || isInfixApp x isParen Paren{} = True; isParen _ = False isIf If{} = True; isIf _ = False@@ -283,9 +282,6 @@ where f (x:y:zs) | isPathSeparator x && isPathSeparator y = f $ x:zs f (x:xs) = x : f xs f [] = []--toSrcSpan :: SrcSpanInfo -> SrcSpan-toSrcSpan (SrcSpanInfo x _) = x nullSrcLoc :: SrcLoc nullSrcLoc = SrcLoc "" 0 0
src/Hint/Duplicate.hs view
@@ -37,7 +37,7 @@ "Reduce duplication" p1 (unlines $ map (prettyPrint . fmap (const p1)) xs) (Just $ "Combine with " ++ showSrcLoc (getPointLoc p2)) []- | (p1,p2,xs) <- duplicateOrdered 3 $ map (map (toSrcSpan . ann &&& dropAnn)) ys]+ | (p1,p2,xs) <- duplicateOrdered 3 $ map (map (srcInfoSpan . ann &&& dropAnn)) ys] ---------------------------------------------------------------------
src/Hint/Extensions.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE RecordWildCards #-} {- Suggest removal of unnecessary extensions i.e. They have {-# LANGUAGE RecursiveDo #-} but no mdo keywords@@ -91,6 +92,12 @@ main = "test" {-# LANGUAGE OverloadedStrings #-} \ main = id --+{-# LANGUAGE DeriveAnyClass #-} \+main = id --+{-# LANGUAGE DeriveAnyClass #-} \+data Foo = Foo deriving Bob+{-# LANGUAGE DeriveAnyClass #-} \+data Foo a = Foo a deriving (Eq,Data,Functor) -- </TEST> -} @@ -102,10 +109,12 @@ import Data.List.Extra import Data.Ratio import Refact.Types+import Data.Monoid+import Prelude extensionsHint :: ModuHint-extensionsHint _ x = [rawIdea Warning "Unused LANGUAGE pragma" (toSrcSpan sl)+extensionsHint _ x = [rawIdea Warning "Unused LANGUAGE pragma" (srcInfoSpan sl) (prettyPrint o) (Just newPragma) (warnings old new) [refact] | not $ used TemplateHaskell x -- if TH is on, can use all other extensions programmatically@@ -128,14 +137,26 @@ warnings _ _ = [] --- | Classes that don't work with newtype deriving-noNewtypeDeriving :: [String]-noNewtypeDeriving = ["Read","Show","Data","Typeable","Generic","Generic1"]+deriveHaskell = ["Eq","Ord","Enum","Ix","Bounded","Read","Show"]+deriveGenerics = ["Data","Typeable","Generic","Generic1","Lift"]+deriveCategory = ["Functor","Foldable","Traversable"] +-- | Classes that can't require newtype deriving+noGeneralizedNewtypeDeriving =+ delete "Enum" deriveHaskell ++ -- Enum can't always be derived on a newtype+ deriveGenerics -- Generics stuff can't newtype derive since it has the ctor in it +-- | Classes that can't require DeriveAnyClass+noDeriveAnyClass = deriveHaskell ++ deriveGenerics ++ deriveCategory++ usedExt :: Extension -> Module_ -> Bool usedExt (EnableExtension x) = used x usedExt (UnknownExtension "NumDecimals") = hasS isWholeFrac+usedExt (UnknownExtension "DeriveLift") = hasDerive ["Lift"]+usedExt (UnknownExtension "DeriveAnyClass") =+ any (`notElem` noDeriveAnyClass) .+ (\Derives{..} -> derivesNewType ++ derivesData) . derives usedExt _ = const True @@ -175,7 +196,9 @@ used DeriveFoldable = hasDerive ["Foldable"] used DeriveTraversable = hasDerive ["Traversable"] used DeriveGeneric = hasDerive ["Generic","Generic1"]-used GeneralizedNewtypeDeriving = any (`notElem` noNewtypeDeriving) . fst . derives+used GeneralizedNewtypeDeriving =+ any (`notElem` noGeneralizedNewtypeDeriving) .+ (\Derives{..} -> derivesNewType ++ derivesStandalone) . derives used LambdaCase = hasS isLCase used TupleSections = hasS isTupleSection used OverloadedStrings = hasS isString@@ -195,30 +218,39 @@ hasDerive :: [String] -> Module_ -> Bool-hasDerive want m = any (`elem` want) $ new ++ dat- where (new,dat) = derives m+hasDerive want m = any (`elem` want) $ derivesNewType ++ derivesData ++ derivesStandalone+ where Derives{..} = derives m +data Derives = Derives+ {derivesNewType :: [String]+ ,derivesData :: [String]+ ,derivesStandalone :: [String]+ }+instance Monoid Derives where+ mempty = Derives [] [] []+ mappend (Derives x1 x2 x3) (Derives y1 y2 y3) =+ Derives (x1++y1) (x2++y2) (x3++y3)+ -- | What is derived on newtype, and on data type -- 'deriving' declarations may be on either, so we approximate as both newtype and data-derives :: Module_ -> ([String],[String])-derives m = concatUnzip $ map decl (childrenBi m) ++ map idecl (childrenBi m)+derives :: Module_ -> Derives+derives m = mconcat $ map decl (childrenBi m) ++ map idecl (childrenBi m) where- idecl :: InstDecl S -> ([String], [String])+ idecl :: InstDecl S -> Derives idecl (InsData _ dn _ _ ds) = g dn ds idecl (InsGData _ dn _ _ _ ds) = g dn ds- idecl _ = ([], [])+ idecl _ = mempty - decl :: Decl_ -> ([String], [String])+ decl :: Decl_ -> Derives decl (DataDecl _ dn _ _ _ ds) = g dn ds decl (GDataDecl _ dn _ _ _ _ ds) = g dn ds decl (DataInsDecl _ dn _ _ ds) = g dn ds decl (GDataInsDecl _ dn _ _ _ ds) = g dn ds- decl (DerivDecl _ _ hd) = (xs, xs) -- don't know whether this was on newtype or not- where xs = [ir hd]- decl _ = ([], [])+ decl (DerivDecl _ _ hd) = mempty{derivesStandalone=[ir hd]}+ decl _ = mempty - g dn ds = if isNewType dn then (xs,[]) else ([],xs)+ g dn ds = if isNewType dn then mempty{derivesNewType=xs} else mempty{derivesData=xs} where xs = maybe [] (map ir . fromDeriving) ds ir (IRule _ _ _ x) = ih x
src/Hint/Import.hs view
@@ -56,7 +56,7 @@ wrap :: [ImportDecl S] -> [Idea]-wrap o = [ rawIdea Warning "Use fewer imports" (toSrcSpan $ ann $ head o) (f o) (Just $ f x) [] rs+wrap o = [ rawIdea Warning "Use fewer imports" (srcInfoSpan $ ann $ head o) (f o) (Just $ f x) [] rs | Just (x, rs) <- [simplify o]] where f = unlines . map prettyPrint @@ -131,7 +131,7 @@ -- import IO is equivalent to -- import System.IO, import System.IO.Error, import Control.Exception(bracket, bracket_) hierarchy i@ImportDecl{importModule=ModuleName _ "IO", importSpecs=Nothing,importPkg=Nothing}- = [rawIdeaN Suggestion "Use hierarchical imports" (toSrcSpan $ ann i) (trimStart $ prettyPrint i) (+ = [rawIdeaN Suggestion "Use hierarchical imports" (srcInfoSpan $ ann i) (trimStart $ prettyPrint i) ( Just $ unlines $ map (trimStart . prettyPrint) [f "System.IO" Nothing, f "System.IO.Error" Nothing ,f "Control.Exception" $ Just $ ImportSpecList an False [IVar an $ toNamed x | x <- ["bracket","bracket_"]]]) []]
src/Hint/Lambda.hs view
@@ -85,7 +85,7 @@ lambdaDecl :: Decl_ -> [Idea]-lambdaDecl (toFunBind -> o@(FunBind loc [Match _ name pats (UnGuardedRhs _ bod) bind]))+lambdaDecl (toFunBind -> o@(FunBind loc1 [Match _ name pats (UnGuardedRhs loc2 bod) bind])) | isNothing bind, isLambda $ fromParen bod, null (universeBi pats :: [Exp_]) = [warn "Redundant lambda" o (gen pats bod) [Replace Decl (toSS o) s1 t1]] | length pats2 < length pats, pvars (drop (length pats2) pats) `disjoint` varss bind@@ -94,6 +94,7 @@ -- Replace Decl (toSS $ reform pats bod) s2 t2]] ]] where reform p b = FunBind loc [Match an name p (UnGuardedRhs an b) Nothing]+ loc = setSpanInfoEnd loc1 $ srcSpanEnd $ srcInfoSpan loc2 gen ps = uncurry reform . fromLambda . Lambda an ps (finalpats, body) = fromLambda . Lambda an pats $ bod (pats2, bod2) = etaReduce pats bod@@ -108,6 +109,8 @@ --t2 = template pats2 bod2 lambdaDecl _ = []++setSpanInfoEnd ssi (line, col) = ssi{srcInfoSpan = (srcInfoSpan ssi){srcSpanEndLine=line, srcSpanEndColumn=col}} etaReduce :: [Pat_] -> Exp_ -> ([Pat_], Exp_)
src/Hint/List.hs view
@@ -21,14 +21,16 @@ yes = y :: [Char] -> a -- String -> a instance C [Char] foo = [a b] ++ xs -- a b : xs+foo = [myexpr | True, a] -- [myexpr | a]+foo = [myexpr | False] -- [] </TEST> -} - module Hint.List(listHint) where import Control.Applicative import Hint.Type+import Data.Maybe import Prelude import Refact.Types @@ -37,8 +39,23 @@ listHint _ _ = listDecl listDecl :: Decl_ -> [Idea]-listDecl x = concatMap (listExp False) (childrenBi x) ++ stringType x ++ concatMap listPat (childrenBi x)+listDecl x =+ concatMap (listExp False) (childrenBi x) +++ stringType x +++ concatMap listPat (childrenBi x) +++ concatMap listComp (universeBi x) +listComp :: Exp_ -> [Idea]+listComp o@(ListComp a e xs)+ | "False" `elem` cons = [suggest "Short-circuited list comprehension" o (List an []) []]+ | "True" `elem` cons = [suggest "Redundant True guards" o o2 []]+ where+ o2 = ListComp a e $ filter ((/= Just "True") . qualCon) xs+ cons = mapMaybe qualCon xs+ qualCon (QualStmt _ (Qualifier _ (Con _ x))) = Just $ fromNamed x+ qualCon _ = Nothing+listComp _ = []+ -- boolean = are you in a ++ chain listExp :: Bool -> Exp_ -> [Idea] listExp b (fromParen -> x) =@@ -140,5 +157,4 @@ g e@(fromTyParen -> x) = [suggest "Use String" x (transform f x) rs | not . null $ rs] where f x = if x =~= typeListChar then typeString else x- toSS = toRefactSrcSpan . toSrcSpan . ann rs = [Replace Type (toSS t) [] (prettyPrint typeString) | t <- universe x, t =~= typeListChar]
src/Hint/Pattern.hs view
@@ -102,7 +102,7 @@ template = fromMaybe "" $ ideaTo (gen "" (Pattern l rtype (map toString patSubts) (GuardedRhss d templateGuards) bind) []) f :: [Either a (String, R.SrcSpan)] -> [(String, R.SrcSpan)] f = rights- refactoring = Replace rtype (toRefactSrcSpan . toSrcSpan $ l) (f patSubts ++ f guardSubts ++ f exprSubts) template+ refactoring = Replace rtype (toRefactSrcSpan $ srcInfoSpan l) (f patSubts ++ f guardSubts ++ f exprSubts) template {- -- Do not suggest view patterns, they aren't something everyone likes sufficiently
src/Hint/Pragma.hs view
@@ -68,16 +68,16 @@ pragmaIdea pidea = case pidea of SingleComment old new ->- mkIdea (toSrcSpan . ann $ old)+ mkIdea (srcInfoSpan . ann $ old) (prettyPrint old) (Just $ prettyPrint new) [] [ModifyComment (toSS old) (prettyPrint new)] MultiComment repl delete new ->- mkIdea (toSrcSpan . ann $ repl)+ mkIdea (srcInfoSpan . ann $ repl) (f [repl, delete]) (Just $ prettyPrint new) [] [ ModifyComment (toSS repl) (prettyPrint new) , ModifyComment (toSS delete) ""] OptionsToComment old new r ->- mkIdea (toSrcSpan . ann . head $ old)+ mkIdea (srcInfoSpan . ann . head $ old) (f old) (Just $ f new) [] r where
src/Hint/Unsafe.hs view
@@ -25,7 +25,7 @@ unsafeHint :: ModuHint unsafeHint _ m =- [ rawIdea Warning "Missing NOINLINE pragma" (toSrcSpan $ ann d)+ [ rawIdea Warning "Missing NOINLINE pragma" (srcInfoSpan $ ann d) (prettyPrint d) (Just $ dropWhile isSpace (prettyPrint $ gen x) ++ "\n" ++ prettyPrint d) [] [InsertComment (toSS d) (prettyPrint $ gen x)]
src/Hint/Util.hs view
@@ -37,7 +37,7 @@ (apps e2, \s -> [Replace Expr s [("x", pos)] "x"]) where (e',xs') = splitAt (length e - length xs) e (e2, xs2) = (map fst e', map fst xs')- pos = toRefactSrcSpan . toSrcSpan $ snd (last e')+ pos = toRefactSrcSpan . srcInfoSpan $ snd (last e') -- \x y -> x + y ==> (+) niceLambdaR [x,y] (InfixApp _ (view -> Var_ x1) (opExp -> op) (view -> Var_ y1))@@ -71,7 +71,7 @@ factor _ = Nothing mkRefact :: [S] -> R.SrcSpan -> Refactoring R.SrcSpan mkRefact subts s =- let tempSubts = zipWith (\a b -> ([a], toRefactSrcSpan . toSrcSpan $ b)) ['a' .. 'z'] subts+ let tempSubts = zipWith (\a b -> ([a], toRefactSrcSpan $ srcInfoSpan b)) ['a' .. 'z'] subts template = dotApps (map (toNamed . fst) tempSubts) in Replace Expr s tempSubts (prettyPrint template)
src/Idea.hs view
@@ -3,7 +3,7 @@ module Idea( Idea(..), rawIdea, idea, suggest, warn, ignore,- rawIdeaN, suggestN, warnN,+ rawIdeaN, suggestN, showIdeasJson, showANSI, Note(..), showNotes, Severity(..)@@ -87,7 +87,7 @@ rawIdea = Idea "" "" rawIdeaN a b c d e f = Idea "" "" a b c d e f [] -idea severity hint from to = rawIdea severity hint (toSrcSpan $ ann from) (f from) (Just $ f to) []+idea severity hint from to = rawIdea severity hint (srcInfoSpan $ ann from) (f from) (Just $ f to) [] where f = trimStart . prettyPrint suggest = idea Suggestion@@ -97,4 +97,3 @@ ideaN severity hint from to = idea severity hint from to [] suggestN = ideaN Suggestion-warnN = ideaN Warning
src/Refact.hs view
@@ -10,6 +10,4 @@ (srcSpanEndColumn ss) toSS :: Annotated a => a S -> R.SrcSpan-toSS = toRefactSrcSpan . toSrcSpan . ann--+toSS = toRefactSrcSpan . srcInfoSpan . ann