packages feed

hlint 2.2.10 → 2.2.11

raw patch · 12 files changed

+76/−37 lines, 12 filesdep +ghc-bootdep ~ghc-lib-parser-exPVP ok

version bump matches the API change (PVP)

Dependencies added: ghc-boot

Dependency ranges changed: ghc-lib-parser-ex

API changes (from Hackage documentation)

Files

CHANGES.txt view
@@ -1,5 +1,14 @@ Changelog for HLint (* = breaking change) +2.2.11, released 2020-02-09+    #868, fix some brackets in refactoring suggestions+    #865, suggest biList if generalise-for-conciseness is turned on+    #859, suggest regular if instead of a simple multi-way if+    #860, improve the sortBy/sortOn hints+    #862, only suggest TupleSections for 2-tuples once+    #854, add more generalise-for-conciseness hints for Either/Maybe+    #852, change maybe to fromMaybe, when the function is duplicated+    #851, add a rule for maybe Nothing Just 2.2.10, released 2020-02-02     #846, add splitAt warnings     #774, don't warn about 'Redundant compare' in == and /=
data/hlint.yaml view
@@ -99,8 +99,8 @@     - warn: {lhs: head (sortBy f x), rhs: minimumBy f x, side: isCompare f}     - warn: {lhs: last (sortBy f x), rhs: maximumBy f x, side: isCompare f}     - warn: {lhs: reverse (sortBy f x), rhs: sortBy (flip f) x, name: Avoid reverse, side: isCompare f, note: Stabilizes sort order}-    - warn: {lhs: sortBy (comparing (flip f)), rhs: sortOn (Down . f)}-    - warn: {lhs: sortBy (comparing f), rhs: sortOn f}+    - warn: {lhs: sortBy (flip (comparing f)), rhs: sortOn (Down . f)}+    - warn: {lhs: sortBy (comparing f), rhs: sortOn f, side: notEq f fst && notEq f snd}     - warn: {lhs: reverse (sortOn f x), rhs: sortOn (Data.Ord.Down . f) x, name: Avoid reverse, note: Stabilizes sort order}     - warn: {lhs: reverse (sort x), rhs: sortOn Data.Ord.Down x, name: Avoid reverse, note: Stabilizes sort order}     - hint: {lhs: flip (g `on` h), rhs: flip g `on` h, name: Move flip}@@ -303,8 +303,6 @@     - warn: {lhs: x . id, rhs: x, name: Redundant id}     - warn: {lhs: "((,) x)", rhs: "(_noParen_ x,)", name: Use tuple-section, note: RequiresExtension TupleSections}     - warn: {lhs: "flip (,) x", rhs: "(,_noParen_ x)", name: Use tuple-section, note: RequiresExtension TupleSections}-    - warn: {lhs: "\\y -> (x,y)", rhs: "(x,)", name: Use tuple-section, note: RequiresExtension TupleSections}-    - warn: {lhs: "\\y -> (y,x)", rhs: "(,x)", name: Use tuple-section, note: RequiresExtension TupleSections}      # CHAR @@ -332,6 +330,7 @@     - warn: {lhs: if a then (if b then t else f) else f, rhs: if a && b then t else f, name: Redundant if}     - warn: {lhs: if x then True else y, rhs: x || y, side: notEq y False, name: Redundant if}     - warn: {lhs: if x then y else False, rhs: x && y, side: notEq y True, name: Redundant if}+    - warn: {lhs: if | b -> t | otherwise -> f, rhs: if b then t else f, name: Redundant multi-way if}     - hint: {lhs: "case a of {True -> t; False -> f}", rhs: if a then t else f, name: Use if}     - hint: {lhs: "case a of {False -> f; True -> t}", rhs: if a then t else f, name: Use if}     - hint: {lhs: "case a of {True -> t; _ -> f}", rhs: if a then t else f, name: Use if}@@ -516,6 +515,7 @@     # MAYBE      - warn: {lhs: maybe x id, rhs: Data.Maybe.fromMaybe x}+    - warn: {lhs: maybe Nothing Just, rhs: id, name: Redundant maybe}     - warn: {lhs: maybe False (const True), rhs: Data.Maybe.isJust}     - warn: {lhs: maybe True (const False), rhs: Data.Maybe.isNothing}     - warn: {lhs: maybe False (== x), rhs: (== Just x)}@@ -552,6 +552,7 @@     - hint: {lhs: maybe Nothing id, rhs: join}     - hint: {lhs: maybe Nothing f x, rhs: f =<< x}     - hint: {lhs: maybe (f x) (f . g), rhs: f . maybe x g, note: IncreasesLaziness, name: Too strict maybe}+    - hint: {lhs: maybe (f x) f y, rhs: f (Data.Maybe.fromMaybe x y), note: IncreasesLaziness, name: Too strict maybe}     - warn: {lhs: maybe x f (fmap g y), rhs: maybe x (f . g) y, name: Redundant fmap}     - warn: {lhs: isJust (fmap f x), rhs: isJust x}     - warn: {lhs: isNothing (fmap f x), rhs: isNothing x}@@ -812,13 +813,23 @@     - warn: {lhs: Data.Maybe.fromMaybe mempty, rhs: Data.Foldable.fold}     - warn: {lhs: Data.Maybe.fromMaybe False, rhs: or}     - warn: {lhs: Data.Maybe.fromMaybe True, rhs: and}+    - warn: {lhs: Data.Maybe.fromMaybe 0, rhs: sum}+    - warn: {lhs: Data.Maybe.fromMaybe 1, rhs: product}+    - warn: {lhs: Data.Maybe.fromMaybe empty, rhs: Data.Foldable.asum}+    - warn: {lhs: Data.Maybe.fromMaybe mzero, rhs: Data.Foldable.msum}     - warn: {lhs: Data.Either.fromRight mempty, rhs: Data.Foldable.fold}     - warn: {lhs: Data.Either.fromRight False, rhs: or}     - warn: {lhs: Data.Either.fromRight True, rhs: and}+    - warn: {lhs: Data.Either.fromRight 0, rhs: sum}+    - warn: {lhs: Data.Either.fromRight 1, rhs: product}+    - warn: {lhs: Data.Either.fromRight empty, rhs: Data.Foldable.asum}+    - warn: {lhs: Data.Either.fromRight mzero, rhs: Data.Foldable.msum}     - warn: {lhs: if f x then Just x else Nothing, rhs: mfilter f (Just x)}     - hint: {lhs: maybe (pure ()), rhs: traverse_, note: IncreasesLaziness}     - hint: {lhs: fromMaybe (pure ()), rhs: sequenceA_, note: IncreasesLaziness}     - hint: {lhs: fromRight (pure ()), rhs: sequenceA_, note: IncreasesLaziness}+    - hint: {lhs: "[fst x, snd x]", rhs: Data.Bifoldable.biList x}+    - hint: {lhs: "\\(x, y) -> [x, y]", rhs: Data.Bifoldable.biList, note: IncreasesLaziness}  - group:     name: dollar@@ -1029,7 +1040,7 @@ # main = hello .~ Just 12 -- hello ?~ 12 # foo = liftIO $ window `on` deleteEvent $ do a; b # no = sort <$> f input `shouldBe` sort <$> x-# sortBy (comparing snd) -- sortOn snd+# sortBy (comparing length) -- sortOn length # myJoin = on $ child ^. ChildParentId ==. parent ^. ParentId # foo = typeOf (undefined :: Foo Int) -- typeRep (Proxy :: Proxy (Foo Int)) # foo = typeOf (undefined :: a) -- typeRep (Proxy :: Proxy a)
hlint.cabal view
@@ -1,7 +1,7 @@ cabal-version:      >= 1.18 build-type:         Simple name:               hlint-version:            2.2.10+version:            2.2.11 license:            BSD3 license-file:       LICENSE category:           Development@@ -68,11 +68,12 @@         refact >= 0.3,         aeson >= 1.1.2.0,         filepattern >= 0.1.1,-        ghc-lib-parser-ex == 8.8.4.*+        ghc-lib-parser-ex == 8.8.5.*     if !flag(ghc-lib) && impl(ghc >= 8.8.0) && impl(ghc < 8.9.0)         build-depends:           ghc == 8.8.*,-          ghc-boot-th+          ghc-boot-th,+          ghc-boot     else         build-depends:           ghc-lib-parser == 8.8.*
src/GHC/Util/FreeVars.hs view
@@ -30,7 +30,7 @@ ( ^- ) :: Set OccName -> Set OccName -> Set OccName ( ^- ) = Set.difference --- See [Note : Spack leaks lurking here?] below.+-- See [Note : Space leaks lurking here?] below. data Vars' = Vars'{bound' :: Set OccName, free' :: Set OccName}  -- Useful for debugging.
src/GHC/Util/HsExpr.hs view
@@ -35,6 +35,7 @@ import Data.Data import Data.Generics.Uniplate.Data import Data.List.Extra+import Data.Tuple.Extra  import Refact.Types hiding (Match) import qualified Refact.Types as R (SrcSpan)@@ -211,30 +212,40 @@ replaceBranches' x = ([], \[] -> x)  --- Like needBracket, but with a special case for 'a . b . b', which was+-- Like needBracket', but with a special case for 'a . b . b', which was -- removed from haskell-src-exts-util-0.2.2. needBracketOld' :: Int -> LHsExpr GhcPs -> LHsExpr GhcPs -> Bool needBracketOld' i parent child   | isDotApp parent, isDotApp child, i == 2 = False   | otherwise = needBracket' i parent child -transformBracketOld' :: (LHsExpr GhcPs -> Maybe (LHsExpr GhcPs)) -> LHsExpr GhcPs -> LHsExpr GhcPs-transformBracketOld' op = snd . g+transformBracketOld' :: (LHsExpr GhcPs -> Maybe (LHsExpr GhcPs)) -> LHsExpr GhcPs -> (LHsExpr GhcPs, LHsExpr GhcPs)+transformBracketOld' op = first snd . g   where-    g = f . descendBracketOld' g+    g = first f . descendBracketOld' g     f x = maybe (False, x) (True, ) (op x)  -- Descend, and if something changes then add/remove brackets--- appropriately-descendBracketOld' :: (LHsExpr GhcPs -> (Bool, LHsExpr GhcPs)) -> LHsExpr GhcPs -> LHsExpr GhcPs-descendBracketOld' op x = descendIndex' g x+-- appropriately. Returns (suggested replacement, refactor template).+-- Whenever a bracket is added to the suggested replacement, a+-- corresponding bracket is added to the refactor template.+descendBracketOld' :: (LHsExpr GhcPs -> ((Bool, LHsExpr GhcPs), LHsExpr GhcPs))+                   -> LHsExpr GhcPs+                   -> (LHsExpr GhcPs, LHsExpr GhcPs)+descendBracketOld' op x = (descendIndex' g1 x, descendIndex' g2 x)   where-    g i y = if a then f i b else b-      where (a, b) = op y+    g i y = if a then (f1 i b z, f2 i b z) else (b, z)+      where ((a, b), z) = op y -    f i (LL _ (HsPar _ y)) | not $ needBracketOld' i x y = y-    f i y                  | needBracketOld' i x y = addParen' y-    f _ y                  = y+    g1 = (fst .) . g+    g2 = (snd .) . g++    f i (LL _ (HsPar _ y)) z | not $ needBracketOld' i x y = (y, z)+    f i y z                  | needBracketOld' i x y = (addParen' y, addParen' z)+    f _ y z                  = (y, z)++    f1 = ((fst .) .) . f+    f2 = ((snd .) .) . f  reduce' :: LHsExpr GhcPs -> LHsExpr GhcPs reduce' = fromParen' . transform reduce1'
src/GHC/Util/Unify.hs view
@@ -58,7 +58,10 @@           f _ = Nothing  -- Peform a substition.-substitute' :: Subst' (LHsExpr GhcPs) -> LHsExpr GhcPs -> LHsExpr GhcPs+-- Returns (suggested replacement, refactor template), both with brackets added+-- as needed.+-- Example: (traverse foo (bar baz), traverse f (x))+substitute' :: Subst' (LHsExpr GhcPs) -> LHsExpr GhcPs -> (LHsExpr GhcPs, LHsExpr GhcPs) substitute' (Subst' bind) = transformBracketOld' exp . transformBi pat . transformBi typ   where     exp :: LHsExpr GhcPs -> Maybe (LHsExpr GhcPs)
src/HSE/Util.hs view
@@ -395,6 +395,7 @@  -- | (a, bs) means extension a implies all of bs. --   Taken from https://downloads.haskell.org/~ghc/master/users-guide/glasgow_exts.html#language-options+--   In the GHC source at DynFlags.impliedXFlags extensionImplications :: [(Extension, [Extension])] extensionImplications = map (first EnableExtension) $     (RebindableSyntax, [DisableExtension ImplicitPrelude]) :
src/Hint/Import.hs view
@@ -73,8 +73,9 @@   concatMap preferHierarchicalImports ms  reduceImports :: [LImportDecl GhcPs] -> [Idea]-reduceImports ms =-  [rawIdea' Hint.Type.Warning "Use fewer imports" (getLoc $ head ms) (f ms) (Just $ f x) [] rs+reduceImports [] = []+reduceImports ms@(m:_) =+  [rawIdea' Hint.Type.Warning "Use fewer imports" (getLoc m) (f ms) (Just $ f x) [] rs   | Just (x, rs) <- [simplify ms]]   where f = unlines . map unsafePrettyPrint 
src/Hint/Match.hs view
@@ -111,8 +111,8 @@     [ (idea' (hintRuleSeverity m) (hintRuleName m) x y [r]){ideaNote=notes}     | (name, expr) <- findDecls' decl     , (parent,x) <- universeParentExp' expr-    , m <- matches, Just (y, notes, subst) <- [matchIdea' s name m parent x]-    , let r = R.Replace R.Expr (toSS' x) subst (unsafePrettyPrint $ unextendInstances (hintRuleGhcRHS m))+    , m <- matches, Just (y, tpl, notes, subst) <- [matchIdea' s name m parent x]+    , let r = R.Replace R.Expr (toSS' x) subst (unsafePrettyPrint tpl)     ]  -- | A list of root expressions, with their associated names@@ -127,7 +127,7 @@            -> HintRule            -> Maybe (Int, LHsExpr GhcPs)            -> LHsExpr GhcPs-           -> Maybe (LHsExpr GhcPs, [Note], [(String, R.SrcSpan)])+           -> Maybe (LHsExpr GhcPs, LHsExpr GhcPs, [Note], [(String, R.SrcSpan)]) matchIdea' sb declName HintRule{..} parent x = do   let lhs = unextendInstances hintRuleGhcLHS       rhs = unextendInstances hintRuleGhcRHS@@ -138,8 +138,8 @@    -- Need to check free vars before unqualification, but after subst   -- (with 'e') need to unqualify before substitution (with 'res').-  let e = substitute' u rhs-      res = addBracketTy' (addBracket' parent $ performSpecial' $ substitute' u $ unqualify' sa sb rhs)+  let (e, tpl) = substitute' u rhs+      res = addBracketTy' (addBracket' parent $ performSpecial' $ fst $ substitute' u $ unqualify' sa sb rhs)   guard $ (freeVars' e Set.\\ Set.filter (not . isUnifyVar . occNameString) (freeVars' rhs)) `Set.isSubsetOf` freeVars' x       -- Check no unexpected new free variables. @@ -152,7 +152,7 @@   guard $ checkSide' (unextendInstances <$> hintRuleGhcSide) $ ("original", x) : ("result", res) : fromSubst' u   guard $ checkDefine' declName parent res -  return (res, hintRuleNotes, [(s, toSS' pos) | (s, pos) <- fromSubst' u, getLoc pos /= noSrcSpan])+  return (res, tpl, hintRuleNotes, [(s, toSS' pos) | (s, pos) <- fromSubst' u, getLoc pos /= noSrcSpan])  --------------------------------------------------------------------- -- SIDE CONDITIONS
src/Hint/Monad.hs view
@@ -133,8 +133,8 @@            -> [ExprLStmt GhcPs] -> [Idea]  -- Rewrite 'do return x; $2' as 'do $2'.-monadStep wrap o@(LL _ (BodyStmt _ (fromRet -> Just (ret, _)) _ _ ) : x : xs)-  = [warn' ("Redundant " ++ ret) (wrap o) (wrap $ x:xs) [Delete Stmt (toSS' (head o))]]+monadStep wrap os@(o@(LL _ (BodyStmt _ (fromRet -> Just (ret, _)) _ _ )) : xs@(_:_))+  = [warn' ("Redundant " ++ ret) (wrap os) (wrap xs) [Delete Stmt (toSS' o)]]  -- Rewrite 'do a <- $1; return a' as 'do $1'. monadStep wrap o@[ g@(LL _ (BindStmt _ (LL _ (VarPat _ (L _ p))) x _ _ ))
src/Hint/Pragma.hs view
@@ -32,6 +32,7 @@  import Hint.Type(ModuHint,ModuleEx(..),Idea(..),Severity(..),toSS',rawIdea',prettyExtension,glasgowExts) import Data.List.Extra+import qualified Data.List.NonEmpty as NE import Data.Maybe import Refact.Types import qualified Refact.Types as R@@ -52,7 +53,7 @@              -> [(Located AnnotationComment, [String])]              -> [Idea] optToPragma flags langExts =-  [pragmaIdea (OptionsToComment (map fst old) ys rs) | old /= []]+  [pragmaIdea (OptionsToComment (fst <$> old2) ys rs) | Just old2 <- [NE.nonEmpty old]]   where       (old, new, ns, rs) =         unzip4 [(old, new, ns, r)@@ -73,7 +74,7 @@  data PragmaIdea = SingleComment (Located AnnotationComment) (Located AnnotationComment)                  | MultiComment (Located AnnotationComment) (Located AnnotationComment) (Located AnnotationComment)-                 | OptionsToComment [Located AnnotationComment] [Located AnnotationComment] [Refactoring R.SrcSpan]+                 | OptionsToComment (NE.NonEmpty (Located AnnotationComment)) [Located AnnotationComment] [Refactoring R.SrcSpan]  pragmaIdea :: PragmaIdea -> Idea pragmaIdea pidea =@@ -87,8 +88,8 @@         [ ModifyComment (toSS' repl) (comment new)         , ModifyComment (toSS' delete) ""]     OptionsToComment old new r ->-      mkLanguage (getLoc . head $ old)-        (f old) (Just $ f new) []+      mkLanguage (getLoc . NE.head $ old)+        (f $ NE.toList old) (Just $ f new) []         r     where           f = unlines . map comment
src/Report.hs view
@@ -5,6 +5,7 @@ import Idea import Data.Tuple.Extra import Data.List.Extra+import qualified Data.List.NonEmpty as NE import Data.Maybe import Data.Version import HSE.All@@ -26,7 +27,7 @@ writeReport dataDir file ideas = timedIO "Report" file $ writeTemplate dataDir inner file     where         generateIds :: [String] -> [(String,Int)] -- sorted by name-        generateIds = map (head &&& length) . group -- must be already sorted+        generateIds = map (NE.head &&& length) . NE.group -- must be already sorted         files = generateIds $ sort $ map (srcSpanFilename . ideaSpan) ideas         hints = generateIds $ map hintName $ sortOn (negate . fromEnum . ideaSeverity &&& hintName) ideas         hintName x = show (ideaSeverity x) ++ ": " ++ ideaHint x