hlint 3.6.1 → 3.10
raw patch · 45 files changed
Files
- CHANGES.txt +16/−0
- LICENSE +1/−1
- README.md +2/−2
- data/hlint.yaml +77/−35
- data/import_style.yaml +2/−0
- hlint.cabal +8/−7
- src/Apply.hs +1/−1
- src/CmdLine.hs +8/−4
- src/Config/Compute.hs +7/−8
- src/Config/Haskell.hs +2/−2
- src/Config/Yaml.hs +4/−3
- src/Fixity.hs +4/−6
- src/GHC/All.hs +26/−7
- src/GHC/Util/ApiAnnotation.hs +18/−8
- src/GHC/Util/Brackets.hs +5/−7
- src/GHC/Util/FreeVars.hs +17/−25
- src/GHC/Util/HsExpr.hs +22/−23
- src/GHC/Util/Scope.hs +5/−5
- src/GHC/Util/SrcLoc.hs +4/−4
- src/GHC/Util/Unify.hs +23/−15
- src/GHC/Util/View.hs +3/−3
- src/Hint/All.hs +3/−1
- src/Hint/Bracket.hs +10/−10
- src/Hint/Comment.hs +1/−1
- src/Hint/Duplicate.hs +1/−2
- src/Hint/Export.hs +2/−2
- src/Hint/Extensions.hs +8/−5
- src/Hint/Fixities.hs +0/−1
- src/Hint/Lambda.hs +19/−20
- src/Hint/List.hs +23/−21
- src/Hint/ListRec.hs +9/−9
- src/Hint/Match.hs +7/−8
- src/Hint/Monad.hs +24/−25
- src/Hint/Naming.hs +2/−2
- src/Hint/Negation.hs +62/−0
- src/Hint/NewType.hs +1/−1
- src/Hint/NumLiteral.hs +9/−8
- src/Hint/Pattern.hs +18/−19
- src/Hint/Pragma.hs +1/−1
- src/Hint/Restrict.hs +29/−16
- src/Hint/Smell.hs +3/−3
- src/Hint/Unsafe.hs +7/−4
- src/Refact.hs +4/−3
- src/Summary.hs +3/−2
- tests/import_style.test +61/−0
CHANGES.txt view
@@ -1,5 +1,21 @@ Changelog for HLint (* = breaking change) +3.10, released 2024-02-02+ #1617, hints for when x <*> y could be y, e.g. []+* #1594, upgrade to GHC 9.12+ #1568, add mapMaybe f (reverse x) ==> reverse (mapMaybe f x)+ #1569, avoid redundant Foldable.toList calls in Foldable operations+ #1571, rename a few hints to make them clearer+ #1599, add translated 0 0 hint for CodeWorld project+ #1600, add sum [x, y] ==> x + y+ #1549, downgrade a few of the error severities to warn+3.8, released 2024-01-15+ #1552, make --git and --ignore-glob work nicely together+ #1502, fix incorrect free variable calculation in some cases+ #1555, slightly more efficient concatMap usages (e.g. pull filter out)+ #1500, suggest avoiding NonEmpty.unzip (use Functor.unzip)+* #1544, upgrade to GHC 9.8+ #1540, correct Functor law hint, was missing brackets 3.6.1, released 2023-07-03 Attempt to make a binary release 3.6, released 2023-06-26
LICENSE view
@@ -1,4 +1,4 @@-Copyright Neil Mitchell 2006-2023.+Copyright Neil Mitchell 2006-2025. All rights reserved. Redistribution and use in source and binary forms, with or without
README.md view
@@ -1,4 +1,4 @@-# HLint [](https://hackage.haskell.org/package/hlint) [](https://www.stackage.org/package/hlint) [](https://github.com/ndmitchell/hlint/actions)+# HLint [](https://hackage.haskell.org/package/hlint) [](https://www.stackage.org/package/hlint) [](https://github.com/ndmitchell/hlint/actions) HLint is a tool for suggesting possible improvements to Haskell code. These suggestions include ideas such as using alternative functions, simplifying code and spotting redundancies. This document is structured as follows: @@ -447,7 +447,7 @@ - modules: - {name: [Data.Map, Data.Map.*], as: Map} - {name: Test.Hspec, within: **.*Spec }- - {name: '**', importStyle: post}+ - {name: '**', qualifiedStyle: post} ``` ## Hacking HLint
data/hlint.yaml view
@@ -120,7 +120,7 @@ - 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: sortBy (comparing 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}- - hint: {lhs: (f `on` g) `on` h, rhs: f `on` (g . h), name: Fuse on/on}+ - hint: {lhs: (f `on` g) `on` h, rhs: f `on` (g . h), name: Use on once} - warn: {lhs: if a >= b then a else b, rhs: max a b} - warn: {lhs: if a >= b then b else a, rhs: min a b} - warn: {lhs: if a > b then a else b, rhs: max a b}@@ -149,6 +149,7 @@ - warn: {lhs: concat (x <&> f), rhs: concatMap f x} - warn: {lhs: concat (fmap f x), rhs: concatMap f x} - hint: {lhs: "concat [a, b]", rhs: a ++ b}+ - hint: {lhs: "sum [a, b]", rhs: a + b, name: "Use + directly"} - hint: {lhs: map f (map g x), rhs: map (f . g) x, name: Use map once} - hint: {lhs: concatMap f (map g x), rhs: concatMap (f . g) x, name: Fuse concatMap/map} - hint: {lhs: x !! 0, rhs: head x}@@ -164,7 +165,7 @@ - warn: {lhs: head (drop n x), rhs: x !! max 0 n, side: not (isNat n) && not (isNeg n)} - warn: {lhs: reverse (init x), rhs: tail (reverse x)} - warn: {lhs: reverse (tail (reverse x)), rhs: init x, note: IncreasesLaziness}- - warn: {lhs: reverse (reverse x), rhs: x, note: IncreasesLaziness, name: Avoid reverse}+ - warn: {lhs: reverse (reverse x), rhs: x, note: IncreasesLaziness, name: Redundant reverse} - warn: {lhs: isPrefixOf (reverse x) (reverse y), rhs: isSuffixOf x y} - warn: {lhs: "foldr (++) []", rhs: concat} - warn: {lhs: foldr (++) "", rhs: concat}@@ -214,6 +215,7 @@ - hint: {lhs: map f (zip x y), rhs: zipWith (curry f) x y, side: not (isApp f)} - hint: {lhs: "map f (fromMaybe [] x)", rhs: "maybe [] (map f) x"} - hint: {lhs: "concatMap f (fromMaybe [] x)", rhs: "maybe [] (concatMap f) x"}+ - hint: {lhs: "concat (fromMaybe [] x)", rhs: "maybe [] concat x"} - warn: {lhs: not (elem x y), rhs: notElem x y} - warn: {lhs: not (notElem x y), rhs: elem x y} - hint: {lhs: foldr f z (map g x), rhs: foldr (f . g) z x, name: Fuse foldr/map}@@ -365,8 +367,8 @@ - warn: {lhs: f (fst p) (snd p), rhs: uncurry f p} - warn: {lhs: "uncurry (\\x y -> z)", rhs: "\\(x,y) -> z"} - warn: {lhs: "curry (\\(x,y) -> z)", rhs: "\\x y -> z"}- - warn: {lhs: uncurry (curry f), rhs: f}- - warn: {lhs: curry (uncurry f), rhs: f}+ - warn: {lhs: uncurry (curry f), rhs: f, name: Redundant curry/uncurry}+ - warn: {lhs: curry (uncurry f), rhs: f, name: Redundant curry/uncurry} - warn: {lhs: "uncurry f (a, b)", rhs: f a b} - warn: {lhs: ($) (f x), rhs: f x, name: Redundant $} - warn: {lhs: (f $), rhs: f, name: Redundant $}@@ -384,6 +386,7 @@ - warn: {lhs: g <**> flip f, rhs: g >>= f, name: Redundant flip} - warn: {lhs: flip f =<< g, rhs: f <*> g, name: Redundant flip} - warn: {lhs: g >>= flip f, rhs: g Control.Applicative.<**> f, name: Redundant flip}+ - warn: {lhs: ($ x) . f, rhs: flip f x} # CHAR @@ -472,11 +475,12 @@ # FUNCTOR - warn: {lhs: fmap f (fmap g x), rhs: fmap (f . g) x, name: Functor law}- - warn: {lhs: f <$> g <$> x, rhs: f . g <$> x, name: Functor law}+ - warn: {lhs: f <$> (g <$> x), rhs: f . g <$> x, name: Functor law} - warn: {lhs: x <&> g <&> f, rhs: x <&> f . g, name: Functor law} - warn: {lhs: fmap id, rhs: id, name: Functor law} - warn: {lhs: id <$> x, rhs: x, name: Functor law} - warn: {lhs: x <&> id, rhs: x, name: Functor law}+ - warn: {lhs: f <$> g <$> x, rhs: f . g <$> x} - hint: {lhs: fmap f $ x, rhs: f <$> x, side: isApp x || isAtom x} - hint: {lhs: \x -> a <$> b x, rhs: fmap a . b} - hint: {lhs: \x -> b x <&> a, rhs: fmap a . b}@@ -503,8 +507,14 @@ - hint: {lhs: return x <*> y, rhs: x <$> y} - warn: {lhs: x <* pure y, rhs: x} - warn: {lhs: x <* return y, rhs: x}- - warn: {lhs: pure x *> y, rhs: "y"}- - warn: {lhs: return x *> y, rhs: "y"}+ - warn: {lhs: pure x *> y, rhs: "y", name: Redundant *>}+ - warn: {lhs: return x *> y, rhs: "y", name: Redundant *>}+ - warn: {lhs: "x <*> Nothing", rhs: "Nothing" }+ - warn: {lhs: "x <*> First Nothing", rhs: "First Nothing" }+ - warn: {lhs: "x <*> Last Nothing", rhs: "Last Nothing" }+ - warn: {lhs: "x <*> Left a", rhs: "Left a" }+ - warn: {lhs: "x <*> Ap []", rhs: "Ap []" }+ - warn: {lhs: "x <*> []", rhs: "[]" } # MONAD @@ -589,10 +599,10 @@ - warn: {lhs: a >>= \_ -> b, rhs: a >> b} - warn: {lhs: m <* pure x, rhs: m} - warn: {lhs: m <* return x, rhs: m}- - warn: {lhs: pure x *> m, rhs: m}- - warn: {lhs: return x *> m, rhs: m}- - warn: {lhs: pure x >> m, rhs: m}- - warn: {lhs: return x >> m, rhs: m}+ - warn: {lhs: pure x *> m, rhs: m, name: Redundant *>}+ - warn: {lhs: return x *> m, rhs: m, name: Redundant *>}+ - warn: {lhs: pure x >> m, rhs: m, name: Redundant >>}+ - warn: {lhs: return x >> m, rhs: m, name: Redundant >>} - warn: {lhs: "forM [1..n] (const f)", rhs: replicateM n f} - warn: {lhs: "for [1..n] (const f)", rhs: replicateM n f} - warn: {lhs: "forM [1..n] (\\_ -> x)", rhs: replicateM n x}@@ -670,6 +680,7 @@ - hint: {lhs: "\\x y z -> (x, y, z)", rhs: "(,,)"} - hint: {lhs: "(,b) a", rhs: "(a,b)", side: isAtom a, name: Evaluate} - hint: {lhs: "(a,) b", rhs: "(a,b)", side: isAtom b, name: Evaluate}+ - warn: {lhs: "Data.List.NonEmpty.unzip", rhs: "Data.Functor.unzip", name: "Avoid NonEmpty.unzip", note: "The function is being deprecated"} # MAYBE @@ -677,14 +688,14 @@ - 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 ==)}- - warn: {lhs: maybe True (x /=), rhs: (Just x /=)}- - warn: {lhs: maybe False (== x), rhs: (Just x ==), note: ValidInstance Eq x}- - warn: {lhs: maybe True (/= x), rhs: (Just x /=), note: ValidInstance Eq x}+ - warn: {lhs: maybe False (x ==), rhs: (Just x ==), name: Redundant maybe}+ - warn: {lhs: maybe True (x /=), rhs: (Just x /=), name: Redundant maybe}+ - warn: {lhs: maybe False (== x), rhs: (Just x ==), note: ValidInstance Eq x, name: Redundant maybe}+ - warn: {lhs: maybe True (/= x), rhs: (Just x /=), note: ValidInstance Eq x, name: Redundant maybe} # The following two hints seem to be somewhat unwelcome, e.g. # https://github.com/ndmitchell/hlint/issues/1177- - ignore: {lhs: fromMaybe False x, rhs: Just True == x} # Eta expanded, see https://github.com/ndmitchell/hlint/issues/970#issuecomment-643645053- - ignore: {lhs: fromMaybe True x, rhs: Just False /= x}+ - ignore: {lhs: fromMaybe False x, rhs: Just True == x, name: Redundant fromMaybe} # Eta expanded, see https://github.com/ndmitchell/hlint/issues/970#issuecomment-643645053+ - ignore: {lhs: fromMaybe True x, rhs: Just False /= x, name: Redundant fromMaybe} - warn: {lhs: not (isNothing x), rhs: isJust x} - warn: {lhs: not (isJust x), rhs: isNothing x} - warn: {lhs: "maybe [] (:[])", rhs: maybeToList}@@ -752,6 +763,7 @@ - warn: {lhs: lefts (nubOrd x), rhs: nubOrd (lefts x), name: Move nubOrd out} - warn: {lhs: rights (nubOrd x), rhs: nubOrd (rights x), name: Move nubOrd out} - warn: {lhs: filter f (reverse x), rhs: reverse (filter f x), name: Move reverse out}+ - warn: {lhs: mapMaybe f (reverse x), rhs: reverse (mapMaybe f x), name: Move reverse out} # EITHER @@ -813,10 +825,10 @@ # CONCURRENT - hint: {lhs: mapM_ (writeChan a), rhs: writeList2Chan a}- - error: {lhs: atomically (readTVar x), rhs: readTVarIO x}- - error: {lhs: atomically (newTVar x), rhs: newTVarIO x}- - error: {lhs: atomically (newTMVar x), rhs: newTMVarIO x}- - error: {lhs: atomically newEmptyTMVar, rhs: newEmptyTMVarIO}+ - warn: {lhs: atomically (readTVar x), rhs: readTVarIO x}+ - warn: {lhs: atomically (newTVar x), rhs: newTVarIO x}+ - warn: {lhs: atomically (newTMVar x), rhs: newTMVarIO x}+ - warn: {lhs: atomically newEmptyTMVar, rhs: newEmptyTMVarIO} # TYPEABLE @@ -872,15 +884,18 @@ - warn: {lhs: or (concatMap f x), rhs: any (or . f) x} - warn: {lhs: and (concat x), rhs: all and x} - warn: {lhs: and (concatMap f x), rhs: all (and . f) x}- - warn: {lhs: any f (concat x), rhs: any (any f) x}- - warn: {lhs: any f (concatMap g x), rhs: any (any f . g) x}- - warn: {lhs: all f (concat x), rhs: all (all f) x}- - warn: {lhs: all f (concatMap g x), rhs: all (all f . g) x}+ - warn: {lhs: any f (concat x), rhs: any (any f) x, name: Use any nested}+ - warn: {lhs: any f (concatMap g x), rhs: any (any f . g) x, name: Use any nested}+ - warn: {lhs: all f (concat x), rhs: all (all f) x, name: Use all nested}+ - warn: {lhs: all f (concatMap g x), rhs: all (all f . g) x, name: Use all nested} - warn: {lhs: fold (concatMap f x), rhs: foldMap (fold . f) x}- - warn: {lhs: foldMap f (concatMap g x), rhs: foldMap (foldMap f . g) x}- - warn: {lhs: catMaybes (concatMap f x), rhs: concatMap (catMaybes . f) x, name: Move concatMap out}- - hint: {lhs: filter f (concatMap g x), rhs: concatMap (filter f . g) x, name: Move concatMap out}- - warn: {lhs: mapMaybe f (concatMap g x), rhs: concatMap (mapMaybe f . g) x, name: Move concatMap out}+ - warn: {lhs: foldMap f (concatMap g x), rhs: foldMap (foldMap f . g) x, name: Use foldMap nested}+ - warn: {lhs: catMaybes (concatMap f x), rhs: concatMap (catMaybes . f) x, name: Move catMaybes}+ - warn: {lhs: catMaybes (concat x), rhs: concatMap catMaybes x, name: Move catMaybes}+ - hint: {lhs: filter f (concatMap g x), rhs: concatMap (filter f . g) x, name: Move filter}+ - hint: {lhs: filter f (concat x), rhs: concatMap (filter f) x, name: Move filter}+ - warn: {lhs: mapMaybe f (concatMap g x), rhs: concatMap (mapMaybe f . g) x, name: Move mapMaybe}+ - warn: {lhs: mapMaybe f (concat x), rhs: concatMap (mapMaybe f) x, name: Move mapMaybe} - warn: {lhs: or (fmap p x), rhs: any p x} - warn: {lhs: or (p <$> x), rhs: any p x} - warn: {lhs: or (x <&> p), rhs: any p x}@@ -896,6 +911,32 @@ - hint: {lhs: foldr f z (fmap g x), rhs: foldr (f . g) z x, name: Fuse foldr/fmap} - hint: {lhs: foldr f z (g <$> x), rhs: foldr (f . g) z x, name: Fuse foldr/<$>} - hint: {lhs: foldr f z (x <&> g), rhs: foldr (f . g) z x, name: Fuse foldr/<&>}+ - warn: {lhs: fold (Data.Foldable.toList x), rhs: fold x}+ - warn: {lhs: foldMap f (Data.Foldable.toList x), rhs: foldMap f x}+ - warn: {lhs: foldMap' f (Data.Foldable.toList x), rhs: foldMap' f x}+ - warn: {lhs: foldr f z (Data.Foldable.toList x), rhs: foldr f z x}+ - warn: {lhs: foldr' f z (Data.Foldable.toList x), rhs: foldr' f z x}+ - warn: {lhs: foldl f z (Data.Foldable.toList x), rhs: foldl f z x}+ - warn: {lhs: foldl' f z (Data.Foldable.toList x), rhs: foldl' f z x}+ - warn: {lhs: foldr1 f (Data.Foldable.toList x), rhs: foldr1 f x}+ - warn: {lhs: foldl1 f (Data.Foldable.toList x), rhs: foldl1 f x}+ - warn: {lhs: null (Data.Foldable.toList x), rhs: null x}+ - warn: {lhs: length (Data.Foldable.toList x), rhs: length x}+ - warn: {lhs: elem y (Data.Foldable.toList x), rhs: elem y x}+ - warn: {lhs: notElem y (Data.Foldable.toList x), rhs: notElem y x}+ - warn: {lhs: maximum (Data.Foldable.toList x), rhs: maximum x}+ - warn: {lhs: minimum (Data.Foldable.toList x), rhs: minimum x}+ - warn: {lhs: maximumBy f (Data.Foldable.toList x), rhs: maximumBy f x}+ - warn: {lhs: minimumBy f (Data.Foldable.toList x), rhs: minimumBy f x}+ - warn: {lhs: sum (Data.Foldable.toList x), rhs: sum x}+ - warn: {lhs: product (Data.Foldable.toList x), rhs: product x}+ - warn: {lhs: and (Data.Foldable.toList x), rhs: and x}+ - warn: {lhs: or (Data.Foldable.toList x), rhs: or x}+ - warn: {lhs: all f (Data.Foldable.toList x), rhs: all f x}+ - warn: {lhs: any f (Data.Foldable.toList x), rhs: any f x}+ - warn: {lhs: find f (Data.Foldable.toList x), rhs: find f x}+ - warn: {lhs: concat (Data.Foldable.toList x), rhs: concat x}+ - warn: {lhs: concatMap f (Data.Foldable.toList x), rhs: concatMap f x} # STATE MONAD @@ -1060,9 +1101,9 @@ - warn: {lhs: "Control.Lens.at a . Control.Lens._Just", rhs: "Control.Lens.ix a"} - error: {lhs: "Control.Lens.has (Control.Lens.at a)", rhs: "True"}- - error: {lhs: "Control.Lens.has (a . Control.Lens.at b)", rhs: "Control.Lens.has a"}+ - warn: {lhs: "Control.Lens.has (a . Control.Lens.at b)", rhs: "Control.Lens.has a"} - error: {lhs: "Control.Lens.nullOf (Control.Lens.at a)", rhs: "False"}- - error: {lhs: "Control.Lens.nullOf (a . Control.Lens.at b)", rhs: "Control.Lens.nullOf a"}+ - warn: {lhs: "Control.Lens.nullOf (a . Control.Lens.at b)", rhs: "Control.Lens.nullOf a"} - group: name: use-lens@@ -1202,10 +1243,10 @@ # Data.List - - warn: {lhs: head l, rhs: "case l of x:_ -> x; [] -> error _", side: not (isNonEmpty l), name: Avoid partial function}- - warn: {lhs: last l, rhs: "case reverse l of x:_ -> x; [] -> error _", side: not (isNonEmpty l), name: Avoid partial function}- - warn: {lhs: tail l, rhs: "case l of _:xs -> xs; [] -> error _", side: not (isNonEmpty x), name: Avoid partial function}- - warn: {lhs: init l, rhs: "case reverse l of _:xs -> reverse xs; [] -> error _", side: not (isNonEmpty x), name: Avoid partial function}+ - warn: {lhs: head l, rhs: "case l of x:_ -> x; [] -> error _", name: Avoid partial function}+ - warn: {lhs: last l, rhs: "case reverse l of x:_ -> x; [] -> error _", name: Avoid partial function}+ - warn: {lhs: tail l, rhs: "case l of _:xs -> xs; [] -> error _", name: Avoid partial function}+ - warn: {lhs: init l, rhs: "case reverse l of _:xs -> reverse xs; [] -> error _", name: Avoid partial function} - warn: {lhs: l !! n, rhs: "case drop n l of x:_ -> x; [] -> error _", name: Avoid partial function} # Data.List.NonEmpty@@ -1402,6 +1443,7 @@ - warn: {lhs: "duller (- a)", rhs: "brighter a"} - warn: {lhs: "darker (- a)", rhs: "lighter a"} - warn: {lhs: translated x y (translated u v p), rhs: translated (x + u) (y + v) p, name: Use translated once}+ - warn: {lhs: translated 0 0 p, rhs: p} - group: name: teaching
data/import_style.yaml view
@@ -4,3 +4,5 @@ - {name: HypotheticalModule3, importStyle: qualified} - {name: 'HypotheticalModule3.*', importStyle: unqualified} - {name: 'HypotheticalModule3.OtherSubModule', importStyle: unrestricted, qualifiedStyle: post}+ - {name: HypotheticalModule4, importStyle: qualified, as: HM4, asRequired: true}+ - {name: HypotheticalModule5, importStyle: qualified, qualifiedStyle: post}
hlint.cabal view
@@ -1,13 +1,13 @@ cabal-version: 1.18 build-type: Simple name: hlint-version: 3.6.1+version: 3.10 license: BSD3 license-file: LICENSE category: Development author: Neil Mitchell <ndmitchell@gmail.com> maintainer: Neil Mitchell <ndmitchell@gmail.com>-copyright: Neil Mitchell 2006-2023+copyright: Neil Mitchell 2006-2025 synopsis: Source code suggestions description: HLint gives suggestions on how to improve your source code.@@ -36,7 +36,7 @@ extra-doc-files: README.md CHANGES.txt-tested-with: GHC==9.6, GHC==9.4, GHC==9.2+tested-with: GHC==9.12, GHC==9.10, GHC==9.8 source-repository head type: git@@ -81,16 +81,16 @@ deriving-aeson >= 0.2, filepattern >= 0.1.1 - if !flag(ghc-lib) && impl(ghc >= 9.6.1) && impl(ghc < 9.7.0)+ if !flag(ghc-lib) && impl(ghc >= 9.12.1) && impl(ghc < 9.13.0) build-depends:- ghc == 9.6.*,+ ghc == 9.12.*, ghc-boot-th, ghc-boot else build-depends:- ghc-lib-parser == 9.6.*+ ghc-lib-parser == 9.12.* build-depends:- ghc-lib-parser-ex >= 9.6.0.0 && < 9.6.1+ ghc-lib-parser-ex >= 9.12.0.0 && < 9.13.0 if flag(gpl) build-depends: hscolour >= 1.21@@ -159,6 +159,7 @@ Hint.Match Hint.Monad Hint.Naming+ Hint.Negation Hint.NewType Hint.Pattern Hint.Pragma
src/Apply.hs view
@@ -17,7 +17,7 @@ import Config.Type import Config.Haskell import GHC.Types.SrcLoc-import GHC.Hs+import GHC.Hs hiding (comments) import Language.Haskell.GhclibParserEx.GHC.Hs import Data.HashSet qualified as Set import Prelude
src/CmdLine.hs view
@@ -12,6 +12,7 @@ import Control.Exception.Extra import Data.ByteString qualified as BS import Data.Char+import Data.List.NonEmpty qualified as NE import Data.List.Extra import Data.Maybe import Data.Functor@@ -182,9 +183,9 @@ ,"To check all Haskell files in 'src' and generate a report type:" ," hlint src --report"] ] &= program "hlint" &= verbosity- &= summary ("HLint v" ++ showVersion version ++ ", (C) Neil Mitchell 2006-2023")+ &= summary ("HLint v" ++ showVersion version ++ ", (C) Neil Mitchell 2006-2025") where- nam xs = nam_ xs &= name [head xs]+ nam xs = nam_ xs &= name [NE.head $ NE.fromList xs] nam_ xs = def &= explicit &= name xs -- | Where should we find the configuration files?@@ -278,7 +279,8 @@ pure [x | x <- xs, drop1 (takeExtension x) `elem` exts, not $ avoidFile x] else do isFil <- doesFileExist $ p <\> file- if isFil then pure [p <\> file]+ if isFil then+ pure [p <\> file | not $ ignore $ p <\> file] else do res <- getModule p exts file case res of@@ -325,7 +327,9 @@ langs, exts :: [String] (langs, exts) = partition (isJust . flip lookup ls) args- ls = [ (show x, x) | x <- [Haskell98, Haskell2010 , GHC2021] ]++ ls :: [(String, Language)]+ ls = [(show x, x) | x <- enumerate] f :: ([Extension], [Extension]) -> String -> ([Extension], [Extension]) f (a, e) ('N':'o':x) | Just x <- GhclibParserEx.readExtension x, let xs = expandDisable x = (deletes xs a, xs ++ deletes xs e)
src/Config/Compute.hs view
@@ -12,7 +12,6 @@ import GHC.Hs hiding (Warning) import GHC.Types.Name.Reader import GHC.Types.Name-import GHC.Data.Bag import GHC.Types.SrcLoc import Language.Haskell.GhclibParserEx.GHC.Hs.ExtendInstances import Language.Haskell.GhclibParserEx.GHC.Hs.Expr@@ -46,24 +45,24 @@ findSetting :: LocatedA (HsDecl GhcPs) -> [Setting] findSetting (L _ (ValD _ x)) = findBind x findSetting (L _ (InstD _ (ClsInstD _ ClsInstDecl{cid_binds}))) =- concatMap (findBind . unLoc) $ bagToList cid_binds+ concatMap (findBind . unLoc) cid_binds findSetting (L _ (SigD _ (FixSig _ x))) = map Infix $ fromFixitySig x findSetting x = [] findBind :: HsBind GhcPs -> [Setting] findBind VarBind{var_id, var_rhs} = findExp var_id [] $ unLoc var_rhs-findBind FunBind{fun_id, fun_matches} = findExp (unLoc fun_id) [] $ HsLam noExtField fun_matches+findBind FunBind{fun_id, fun_matches} = findExp (unLoc fun_id) [] $ HsLam noAnn LamSingle fun_matches findBind _ = [] findExp :: IdP GhcPs -> [String] -> HsExpr GhcPs -> [Setting]-findExp name vs (HsLam _ MG{mg_alts=L _ [L _ Match{m_pats, m_grhss=GRHSs{grhssGRHSs=[L _ (GRHS _ [] x)], grhssLocalBinds=(EmptyLocalBinds _)}}]})- = if length m_pats == length ps then findExp name (vs++ps) $ unLoc x else []- where ps = [rdrNameStr x | L _ (VarPat _ x) <- m_pats]+findExp name vs (HsLam _ LamSingle MG{mg_alts=L _ [L _ Match{m_pats=L _ pats, m_grhss=GRHSs{grhssGRHSs=[L _ (GRHS _ [] x)], grhssLocalBinds=(EmptyLocalBinds _)}}]})+ = if length pats == length ps then findExp name (vs++ps) $ unLoc x else []+ where ps = [rdrNameStr x | L _ (VarPat _ x) <- pats] findExp name vs HsLam{} = [] findExp name vs HsVar{} = [] findExp name vs (OpApp _ x dot y) | isDot dot = findExp name (vs++["_hlint"]) $- HsApp EpAnnNotUsed x $ nlHsPar $ noLocA $ HsApp EpAnnNotUsed y $ noLocA $ mkVar "_hlint"+ HsApp noExtField x $ nlHsPar $ noLocA $ HsApp noExtField y $ noLocA $ mkVar "_hlint" findExp name vs bod = [SettingMatchExp $ HintRule Warning defaultHintName []@@ -74,7 +73,7 @@ rep = zip vs $ map (mkVar . pure) ['a'..] f (HsVar _ x) | Just y <- lookup (rdrNameStr x) rep = y- f (OpApp _ x dol y) | isDol dol = HsApp EpAnnNotUsed x $ nlHsPar y+ f (OpApp _ x dol y) | isDol dol = HsApp noExtField x $ nlHsPar y f x = x
src/Config/Haskell.hs view
@@ -45,7 +45,7 @@ Nothing -> errorOn expr "bad classify pragma" Just severity -> Just $ Classify severity (trimStart b) "" name where (a,b) = break isSpace $ trimStart $ drop 6 s- f (L _ (HsPar _ _ x _)) = f x+ f (L _ (HsPar _ x)) = f x f (L _ (ExprWithTySig _ x _)) = f x f _ = Nothing @@ -85,6 +85,6 @@ errorOnComment :: LEpaComment -> String -> b errorOnComment c@(L s _) msg = exitMessageImpure $ let isMultiline = isCommentMultiline c in- showSrcSpan (RealSrcSpan (anchor s) GHC.Data.Strict.Nothing) +++ showSrcSpan (RealSrcSpan (epaLocationRealSrcSpan s) GHC.Data.Strict.Nothing) ++ ": Error while reading hint file, " ++ msg ++ "\n" ++ (if isMultiline then "{-" else "--") ++ commentText c ++ (if isMultiline then "-}" else "")
src/Config/Yaml.hs view
@@ -29,6 +29,7 @@ import Config.Type import Data.Either.Extra import Data.Maybe+import Data.List.NonEmpty qualified as NE import Data.List.Extra import Data.Tuple.Extra import Control.Monad.Extra@@ -163,7 +164,7 @@ -- aim to show a smallish but relevant context dotDot (fromMaybe (encode focus) $ listToMaybe $ dropWhile (\x -> BS.length x > 250) $ map encode contexts) where- (steps, contexts) = unzip $ reverse path+ (steps, contexts) = Prelude.unzip $ reverse path dotDot x = let (a,b) = BS.splitAt 250 x in BS.unpack a ++ (if BS.null b then "" else "...") parseArray :: Val -> Parser [Val]@@ -235,7 +236,7 @@ case parser defaultParseFlags{enabledExtensions=configExtensions, disabledExtensions=[]} x of POk _ x -> pure x PFailed ps ->- let errMsg = head . bagToList . getMessages $ GhcPsMessage <$> snd (getPsMessages ps)+ let errMsg = NE.head . NE.fromList . bagToList . getMessages $ GhcPsMessage <$> snd (getPsMessages ps) msg = showSDoc baseDynFlags $ pprLocMsgEnvelopeDefault errMsg in parseFail v $ "Failed to parse " ++ msg ++ ", when parsing:\n " ++ x @@ -441,7 +442,7 @@ scope'= asScope' packageMap' (map (fmap unextendInstances) groupImports) asScope' :: Map.HashMap String [LocatedA (ImportDecl GhcPs)] -> [Either String (LocatedA (ImportDecl GhcPs))] -> Scope-asScope' packages xs = scopeCreate (HsModule (XModulePs EpAnnNotUsed NoLayoutInfo Nothing Nothing) Nothing Nothing (concatMap f xs) [])+asScope' packages xs = scopeCreate (HsModule (XModulePs noAnn EpNoLayout Nothing Nothing) Nothing Nothing (concatMap f xs) []) where f (Right x) = [x] f (Left x) | Just pkg <- Map.lookup x packages = pkg
src/Fixity.hs view
@@ -12,9 +12,7 @@ import GHC.Types.Name.Occurrence import GHC.Types.Name.Reader import GHC.Types.Fixity-import GHC.Types.SourceText import GHC.Parser.Annotation-import Language.Haskell.Syntax.Extension import Language.Haskell.GhclibParserEx.GHC.Types.Name.Reader import Language.Haskell.GhclibParserEx.Fixity @@ -29,7 +27,7 @@ type FixityInfo = (String, Associativity, Int) fromFixitySig :: FixitySig GhcPs -> [FixityInfo]-fromFixitySig (FixitySig _ names (Fixity _ i dir)) =+fromFixitySig (FixitySig _ names (Fixity i dir)) = [(rdrNameStr name, f dir, i) | name <- names] where f InfixL = LeftAssociative@@ -37,14 +35,14 @@ f InfixN = NotAssociative toFixity :: FixityInfo -> (String, Fixity)-toFixity (name, dir, i) = (name, Fixity NoSourceText i $ f dir)+toFixity (name, dir, i) = (name, Fixity i $ f dir) where f LeftAssociative = InfixL f RightAssociative = InfixR f NotAssociative = InfixN fromFixity :: (String, Fixity) -> FixityInfo-fromFixity (name, Fixity _ i dir) = (name, assoc dir, i)+fromFixity (name, Fixity i dir) = (name, assoc dir, i) where assoc dir = case dir of InfixL -> LeftAssociative@@ -52,7 +50,7 @@ InfixN -> NotAssociative toFixitySig :: FixityInfo -> FixitySig GhcPs-toFixitySig (toFixity -> (name, x)) = FixitySig noExtField [noLocA $ mkRdrUnqual (mkVarOcc name)] x+toFixitySig (toFixity -> (name, x)) = FixitySig NoNamespaceSpecifier [noLocA $ mkRdrUnqual (mkVarOcc name)] x defaultFixities :: [FixityInfo] defaultFixities = map fromFixity $ customFixities ++ baseFixities ++ lensFixities ++ otherFixities
src/GHC/All.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE ImportQualifiedPost #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE ViewPatterns #-} @@ -14,6 +15,8 @@ import Control.Monad.IO.Class import Util import Data.Char+import Data.List+import Data.List.NonEmpty qualified as NE import Data.List.Extra import Timing import Language.Preprocessor.Cpphs@@ -22,7 +25,7 @@ import Extension import GHC.Data.FastString -import GHC.Hs+import GHC.Hs hiding (comments) import GHC.Types.SrcLoc import GHC.Types.Fixity import GHC.Types.Error@@ -37,6 +40,8 @@ import Language.Haskell.GhclibParserEx.GHC.Parser import Language.Haskell.GhclibParserEx.Fixity+import Language.Haskell.GhclibParserEx.GHC.Driver.Session+ import GHC.Util -- | What C pre processor should be used.@@ -101,7 +106,7 @@ firstDeclComments m = case hsmodDecls . unLoc . ghcModule $ m of [] -> EpaCommentsBalanced [] []- L (SrcSpanAnn ann _) _ : _ -> comments ann+ L ann _ : _ -> comments ann -- | The error handler invoked when GHC parsing has failed. ghcFailOpParseModuleEx :: String@@ -129,7 +134,7 @@ parseModeToFlags :: ParseFlags -> DynFlags parseModeToFlags parseMode =- flip lang_set (baseLanguage parseMode) $ foldl' xopt_unset (foldl' xopt_set baseDynFlags enable) disable+ flip lang_set (baseLanguage parseMode) $ foldl xopt_unset (foldl' xopt_set baseDynFlags enable) disable where (enable, disable) = ghcExtensionsFromParseFlags parseMode @@ -161,6 +166,16 @@ createModuleExWithFixities fixities ast = ModuleEx (applyFixities (fixitiesFromModule ast ++ fixities) ast) +impliedEnables :: Extension -> [Extension]+impliedEnables ext = case Data.List.lookup ext extensionImplications of+ Just exts -> ext : fst exts+ Nothing -> [ext]++impliedDisables :: Extension -> [Extension]+impliedDisables ext = case Data.List.lookup ext extensionImplications of+ Just exts -> ext : snd exts+ Nothing -> []+ -- | Parse a Haskell module. Applies the C pre processor, and uses -- best-guess fixity resolution if there are ambiguities. The -- filename @-@ is treated as @stdin@. Requires some flags (often@@ -177,7 +192,11 @@ Nothing | file == "-" -> liftIO getContentsUTF8 | otherwise -> liftIO $ readFileUTF8' file str <- pure $ dropPrefix "\65279" str -- Remove the BOM if it exists, see #130.- let enableDisableExts = ghcExtensionsFromParseFlags flags+ let (enable, disable) = ghcExtensionsFromParseFlags flags+ -- Enable/disable extensions and the extensions they imply.+ impliedEnabled = concatMap impliedEnables enable+ impliedDisabled = concatMap impliedDisables disable+ enableDisableExts = (impliedEnabled, impliedDisabled) -- Read pragmas for the first time. dynFlags <- withExceptT (parsePragmasErr str) $ ExceptT (parsePragmasIntoDynFlags baseDynFlags enableDisableExts file str) dynFlags <- pure $ lang_set dynFlags $ baseLanguage flags@@ -192,12 +211,12 @@ POk s a -> do let errs = bagToList . getMessages $ GhcPsMessage <$> snd (getPsMessages s) if not $ null errs then- ExceptT $ parseFailureErr dynFlags str file str errs+ ExceptT $ parseFailureErr dynFlags str file str $ NE.fromList errs else do let fixes = fixitiesFromModule a ++ ghcFixitiesFromParseFlags flags pure $ ModuleEx (applyFixities fixes a) PFailed s ->- ExceptT $ parseFailureErr dynFlags str file str $ bagToList . getMessages $ GhcPsMessage <$> snd (getPsMessages s)+ ExceptT $ parseFailureErr dynFlags str file str $ NE.fromList . bagToList . getMessages $ GhcPsMessage <$> snd (getPsMessages s) where -- If parsing pragmas fails, synthesize a parse error from the -- error message.@@ -206,7 +225,7 @@ in ParseError (mkSrcSpan loc loc) msg src parseFailureErr dynFlags ppstr file str errs =- let errMsg = head errs+ let errMsg = NE.head errs loc = errMsgSpan errMsg doc = pprLocMsgEnvelopeDefault errMsg in ghcFailOpParseModuleEx ppstr file str (loc, doc)
src/GHC/Util/ApiAnnotation.hs view
@@ -1,9 +1,15 @@ {-# LANGUAGE ImportQualifiedPost #-} module GHC.Util.ApiAnnotation (- comment_, commentText, isCommentMultiline- , pragmas, flags, languagePragmas- , mkFlags, mkLanguagePragmas+ comment_+ , commentText+ , GHC.Util.ApiAnnotation.comments+ , isCommentMultiline+ , pragmas+ , flags+ , languagePragmas+ , mkFlags+ , mkLanguagePragmas , extensions ) where @@ -39,12 +45,16 @@ comment_ (L _ (EpaComment (EpaDocOptions s) _)) = s comment_ (L _ (EpaComment (EpaLineComment s) _)) = s comment_ (L _ (EpaComment (EpaBlockComment s) _)) = s-comment_ (L _ (EpaComment EpaEofComment _)) = "" -- | The comment string with delimiters removed. commentText :: LEpaComment -> String commentText = trimCommentDelims . comment_ +-- | Total replacement for the partial `GHC.Parser.Annotation.comments` field of+-- `EpAnn`+comments :: EpAnn ann -> EpAnnComments+comments EpAnn{ GHC.Parser.Annotation.comments = result } = result+ isCommentMultiline :: LEpaComment -> Bool isCommentMultiline (L _ (EpaComment (EpaBlockComment _) _)) = True isCommentMultiline _ = False@@ -95,10 +105,10 @@ , let exts = map trim (splitOn "," rest)] -- Given a list of flags, make a GHC options pragma.-mkFlags :: Anchor -> [String] -> LEpaComment+mkFlags :: NoCommentsLocation -> [String] -> LEpaComment mkFlags anc flags =- L anc $ EpaComment (EpaBlockComment ("{-# " ++ "OPTIONS_GHC " ++ unwords flags ++ " #-}")) (anchor anc)+ L anc $ EpaComment (EpaBlockComment ("{-# " ++ "OPTIONS_GHC " ++ unwords flags ++ " #-}")) (epaLocationRealSrcSpan anc) -mkLanguagePragmas :: Anchor -> [String] -> LEpaComment+mkLanguagePragmas :: NoCommentsLocation -> [String] -> LEpaComment mkLanguagePragmas anc exts =- L anc $ EpaComment (EpaBlockComment ("{-# " ++ "LANGUAGE " ++ intercalate ", " exts ++ " #-}")) (anchor anc)+ L anc $ EpaComment (EpaBlockComment ("{-# " ++ "LANGUAGE " ++ intercalate ", " exts ++ " #-}")) (epaLocationRealSrcSpan anc)
src/GHC/Util/Brackets.hs view
@@ -26,9 +26,9 @@ -- result in a "naked" section. Consequently, given an expression, -- when stripping brackets (c.f. 'Hint.Brackets), don't remove the -- paren's surrounding a section - they are required.- remParen (L _ (HsPar _ _ (L _ SectionL{}) _)) = Nothing- remParen (L _ (HsPar _ _ (L _ SectionR{}) _)) = Nothing- remParen (L _ (HsPar _ _ x _)) = Just x+ remParen (L _ (HsPar _ (L _ SectionL{}))) = Nothing+ remParen (L _ (HsPar _ (L _ SectionR{}))) = Nothing+ remParen (L _ (HsPar _ x)) = Just x remParen _ = Nothing addParen = nlHsPar@@ -36,8 +36,6 @@ isAtom (L _ x) = case x of HsVar{} -> True HsUnboundVar{} -> True- -- Technically atomic, but lots of people think it shouldn't be- HsRecSel{} -> False -- Only relevant for OverloadedRecordDot extension HsGetField{} -> True HsOverLabel{} -> True@@ -108,7 +106,7 @@ isAtomOrApp _ = False instance Brackets (LocatedA (Pat GhcPs)) where- remParen (L _ (ParPat _ _ x _)) = Just x+ remParen (L _ (ParPat _ x)) = Just x remParen _ = Nothing addParen = nlParPat@@ -151,7 +149,7 @@ instance Brackets (LocatedA (HsType GhcPs)) where remParen (L _ (HsParTy _ x)) = Just x remParen _ = Nothing- addParen e = noLocA $ HsParTy EpAnnNotUsed e+ addParen e = noLocA $ HsParTy noAnn e isAtom (L _ x) = case x of HsParTy{} -> True
src/GHC/Util/FreeVars.hs view
@@ -13,7 +13,6 @@ import GHC.Types.Name import GHC.Hs import GHC.Types.SrcLoc-import GHC.Data.Bag (bagToList) import Data.Generics.Uniplate.DataOnly import Data.Monoid@@ -99,10 +98,10 @@ instance FreeVars (LocatedA (HsExpr GhcPs)) where freeVars (L _ (HsVar _ x)) = Set.fromList $ unqualNames x -- Variable. freeVars (L _ (HsUnboundVar _ x)) = Set.fromList [rdrNameOcc x] -- Unbound variable; also used for "holes".- freeVars (L _ (HsLam _ mg)) = free (allVars mg) -- Lambda abstraction. Currently always a single match.- freeVars (L _ (HsLamCase _ _ MG{mg_alts=(L _ ms)})) = free (allVars ms) -- Lambda case+ freeVars (L _ (HsLam _ LamSingle mg)) = free (allVars mg) -- Lambda abstraction. Currently always a single match.+ freeVars (L _ (HsLam _ _ MG{mg_alts=(L _ ms)})) = free (allVars ms) -- Lambda case freeVars (L _ (HsCase _ of_ MG{mg_alts=(L _ ms)})) = freeVars of_ ^+ free (allVars ms) -- Case expr.- freeVars (L _ (HsLet _ _ binds _ e)) = inFree binds e -- Let (rec).+ freeVars (L _ (HsLet _ binds e)) = inFree binds e -- Let (rec). freeVars (L _ (HsDo _ ctxt (L _ stmts))) = snd $ foldl' alg mempty stmts -- Do block. where alg ::@@ -119,17 +118,16 @@ _ -> mempty ) accFree = accFree0 ^+ (free (allVars stmt) ^- accBound0)- freeVars (L _ (RecordCon _ _ (HsRecFields flds _))) = Set.unions $ map freeVars flds -- Record construction.+ freeVars (L _ (RecordCon _ _ (HsRecFields _ flds _))) = Set.unions $ map freeVars flds -- Record construction. freeVars (L _ (RecordUpd _ e flds)) = case flds of- Left fs -> Set.unions $ freeVars e : map freeVars fs- Right ps -> Set.unions $ freeVars e : map freeVars ps+ RegularRecUpdFields _ fs -> Set.unions $ freeVars e : map freeVars fs+ OverloadedRecUpdFields _ ps -> Set.unions $ freeVars e : map freeVars ps freeVars (L _ (HsMultiIf _ grhss)) = free (allVars grhss) -- Multi-way if. freeVars (L _ (HsTypedBracket _ e)) = freeVars e freeVars (L _ (HsUntypedBracket _ (ExpBr _ e))) = freeVars e freeVars (L _ (HsUntypedBracket _ (VarBr _ _ v))) = Set.fromList [occName (unLoc v)] - freeVars (L _ HsRecSel{}) = mempty -- Variable pointing to a record selector. freeVars (L _ HsOverLabel{}) = mempty -- Overloaded label. The id of the in-scope fromLabel. freeVars (L _ HsIPVar{}) = mempty -- Implicit parameter. freeVars (L _ HsOverLit{}) = mempty -- Overloaded literal.@@ -169,27 +167,23 @@ freeVars (Present _ args) = freeVars args freeVars _ = mempty -instance FreeVars (LocatedA (HsFieldBind (LocatedAn NoEpAnns (FieldOcc GhcPs)) (LocatedA (HsExpr GhcPs)))) where+instance FreeVars (LocatedA (HsFieldBind (LocatedA (FieldOcc GhcPs)) (LocatedA (HsExpr GhcPs)))) where freeVars o@(L _ (HsFieldBind _ x _ True)) = Set.singleton $ occName $ unLoc $ foLabel $ unLoc x -- a pun freeVars o@(L _ (HsFieldBind _ _ x _)) = freeVars x -instance FreeVars (LocatedA (HsFieldBind (LocatedAn NoEpAnns (AmbiguousFieldOcc GhcPs)) (LocatedA (HsExpr GhcPs)))) where- freeVars (L _ (HsFieldBind _ x _ True)) = Set.singleton $ rdrNameOcc $ rdrNameAmbiguousFieldOcc $ unLoc x -- a pun- freeVars (L _ (HsFieldBind _ _ x _)) = freeVars x- instance FreeVars (LocatedA (HsFieldBind (LocatedAn NoEpAnns (FieldLabelStrings GhcPs)) (LocatedA (HsExpr GhcPs)))) where freeVars (L _ (HsFieldBind _ _ x _)) = freeVars x instance AllVars (LocatedA (Pat GhcPs)) where allVars (L _ (VarPat _ (L _ x))) = Vars (Set.singleton $ rdrNameOcc x) Set.empty -- Variable pattern.- allVars (L _ (AsPat _ n _ x)) = allVars (noLocA $ VarPat noExtField n :: LocatedA (Pat GhcPs)) <> allVars x -- As pattern.- allVars (L _ (ConPat _ _ (RecCon (HsRecFields flds _)))) = allVars flds+ allVars (L _ (AsPat _ n x)) = allVars (noLocA $ VarPat noExtField n :: LocatedA (Pat GhcPs)) <> allVars x -- As pattern.+ allVars (L _ (ConPat _ _ (RecCon (HsRecFields _ flds _)))) = allVars flds allVars (L _ (NPlusKPat _ n _ _ _ _)) = allVars (noLocA $ VarPat noExtField n :: LocatedA (Pat GhcPs)) -- n+k pattern. allVars (L _ (ViewPat _ e p)) = freeVars_ e <> allVars p -- View pattern.- allVars (L _ WildPat{}) = mempty -- Wildcard pattern. allVars (L _ LitPat{}) = mempty -- Literal pattern. allVars (L _ NPat{}) = mempty -- Natural pattern.+ allVars (L _ InvisPat {}) = mempty -- since ghc-9.10.1 -- allVars p@SplicePat{} = allVars $ children p -- Splice pattern (includes quasi-quotes). -- allVars p@SigPat{} = allVars $ children p -- Pattern with a type signature.@@ -203,7 +197,7 @@ allVars p = allVars $ children p -instance AllVars (LocatedA (HsFieldBind (LocatedAn NoEpAnns (FieldOcc GhcPs)) (LocatedA (Pat GhcPs)))) where+instance AllVars (LocatedA (HsFieldBind (LocatedA (FieldOcc GhcPs)) (LocatedA (Pat GhcPs)))) where allVars (L _ (HsFieldBind _ _ x _)) = allVars x instance AllVars (LocatedA (StmtLR GhcPs GhcPs (LocatedA (HsExpr GhcPs)))) where@@ -213,12 +207,10 @@ allVars (L _ (LetStmt _ binds)) = allVars binds -- A local declaration e.g. let y = x + 1 allVars (L _ (TransStmt _ _ stmts _ using by _ _ fmap_)) = allVars stmts <> freeVars_ using <> maybe mempty freeVars_ by <> freeVars_ (noLocA fmap_ :: LocatedA (HsExpr GhcPs)) -- Apply a function to a list of statements in order. allVars (L _ (RecStmt _ stmts _ _ _ _ _)) = allVars (unLoc stmts) -- A recursive binding for a group of arrows.-- allVars (L _ ApplicativeStmt{}) = mempty -- Generated by the renamer. allVars (L _ ParStmt{}) = mempty -- Parallel list thing. Come back to it. instance AllVars (HsLocalBinds GhcPs) where- allVars (HsValBinds _ (ValBinds _ binds _)) = allVars (bagToList binds) -- Value bindings.+ allVars (HsValBinds _ (ValBinds _ binds _)) = allVars binds -- Value bindings. allVars (HsIPBinds _ (IPBinds _ binds)) = allVars binds -- Implicit parameter bindings. allVars EmptyLocalBinds{} = mempty -- The case of no local bindings (signals the empty `let` or `where` clause). allVars _ = mempty -- extension points@@ -233,15 +225,15 @@ allVars (L _ (PatSynBind _ PSB{})) = mempty -- Come back to it. instance AllVars (MatchGroup GhcPs (LocatedA (HsExpr GhcPs))) where- allVars (MG _ _alts@(L _ alts)) = inVars (foldMap (allVars . m_pats) ms) (allVars (map m_grhss ms))+ allVars (MG _ _alts@(L _ alts)) = foldMap (\m -> inVars (allVars ((unLoc . m_pats) m)) (allVars (m_grhss m))) ms where ms = map unLoc alts instance AllVars (LocatedA (Match GhcPs (LocatedA (HsExpr GhcPs)))) where- allVars (L _ (Match _ FunRhs {mc_fun=name} pats grhss)) = allVars (noLocA $ VarPat noExtField name :: LocatedA (Pat GhcPs)) <> allVars pats <> allVars grhss -- A pattern matching on an argument of a function binding.- allVars (L _ (Match _ (StmtCtxt ctxt) pats grhss)) = allVars ctxt <> allVars pats <> allVars grhss -- Pattern of a do-stmt, list comprehension, pattern guard etc.- allVars (L _ (Match _ _ pats grhss)) = inVars (allVars pats) (allVars grhss) -- Everything else.+ allVars (L _ (Match _ FunRhs {mc_fun=name} pats grhss)) = allVars (noLocA $ VarPat noExtField name :: LocatedA (Pat GhcPs)) <> (allVars . unLoc) pats <> allVars grhss -- A pattern matching on an argument of a function binding.+ allVars (L _ (Match _ (StmtCtxt ctxt) pats grhss)) = allVars ctxt <> (allVars . unLoc) pats <> allVars grhss -- Pattern of a do-stmt, list comprehension, pattern guard etc.+ allVars (L _ (Match _ _ pats grhss)) = inVars ((allVars . unLoc) pats) (allVars grhss) -- Everything else. -instance AllVars (HsStmtContext GhcPs) where+instance AllVars (HsStmtContext (GenLocated SrcSpanAnnN RdrName)) where allVars (PatGuard FunRhs{mc_fun=n}) = allVars (noLocA $ VarPat noExtField n :: LocatedA (Pat GhcPs)) allVars ParStmtCtxt{} = mempty -- Come back to it. allVars TransStmtCtxt{} = mempty -- Come back to it.
src/GHC/Util/HsExpr.hs view
@@ -21,7 +21,6 @@ import GHC.Data.FastString import GHC.Types.Name.Reader import GHC.Types.Name.Occurrence-import GHC.Data.Bag(bagToList) import GHC.Util.Brackets import GHC.Util.FreeVars@@ -49,7 +48,7 @@ -- | 'dotApp a b' makes 'a . b'. dotApp :: LHsExpr GhcPs -> LHsExpr GhcPs -> LHsExpr GhcPs-dotApp x y = noLocA $ OpApp EpAnnNotUsed x (noLocA $ HsVar noExtField (noLocA $ mkVarUnqual (fsLit "."))) y+dotApp x y = noLocA $ OpApp noExtField x (noLocA $ HsVar noExtField (noLocA $ mkVarUnqual (fsLit "."))) y dotApps :: [LHsExpr GhcPs] -> LHsExpr GhcPs dotApps [] = error "GHC.Util.HsExpr.dotApps', does not work on an empty list"@@ -58,7 +57,7 @@ -- | @lambda [p0, p1..pn] body@ makes @\p1 p1 .. pn -> body@ lambda :: [LPat GhcPs] -> LHsExpr GhcPs -> LHsExpr GhcPs-lambda vs body = noLocA $ HsLam noExtField (MG Generated (noLocA [noLocA $ Match EpAnnNotUsed LambdaExpr vs (GRHSs emptyComments [noLocA $ GRHS EpAnnNotUsed [] body] (EmptyLocalBinds noExtField))]))+lambda vs body = noLocA $ HsLam noAnn LamSingle (MG (Generated OtherExpansion DoPmc) (noLocA [noLocA $ Match noExtField (LamAlt LamSingle) (L noSpanAnchor vs) (GRHSs emptyComments [noLocA $ GRHS noAnn [] body] (EmptyLocalBinds noExtField))])) -- | 'paren e' wraps 'e' in parens if 'e' is non-atomic. paren :: LHsExpr GhcPs -> LHsExpr GhcPs@@ -72,7 +71,7 @@ apps :: [LHsExpr GhcPs] -> LHsExpr GhcPs-apps = foldl1' mkApp where mkApp x y = noLocA (HsApp EpAnnNotUsed x y)+apps = foldl1' mkApp where mkApp x y = noLocA (HsApp noExtField x y) fromApps :: LHsExpr GhcPs -> [LHsExpr GhcPs] fromApps (L _ (HsApp _ x y)) = fromApps x ++ [y]@@ -86,7 +85,7 @@ universeApps x = x : concatMap universeApps (childrenApps x) descendAppsM :: Monad m => (LHsExpr GhcPs -> m (LHsExpr GhcPs)) -> LHsExpr GhcPs -> m (LHsExpr GhcPs)-descendAppsM f (L l (HsApp _ x y)) = (\x y -> L l $ HsApp EpAnnNotUsed x y) <$> descendAppsM f x <*> f y+descendAppsM f (L l (HsApp _ x y)) = (\x y -> L l $ HsApp noExtField x y) <$> descendAppsM f x <*> f y descendAppsM f x = descendM f x transformAppsM :: Monad m => (LHsExpr GhcPs -> m (LHsExpr GhcPs)) -> LHsExpr GhcPs -> m (LHsExpr GhcPs)@@ -117,15 +116,15 @@ -- A list of application, with any necessary brackets. appsBracket :: [LHsExpr GhcPs] -> LHsExpr GhcPs appsBracket = foldl1 mkApp- where mkApp x y = rebracket1 (noLocA $ HsApp EpAnnNotUsed x y)+ where mkApp x y = rebracket1 (noLocA $ HsApp noExtField x y) simplifyExp :: LHsExpr GhcPs -> LHsExpr GhcPs -- Replace appliciations 'f $ x' with 'f (x)'.-simplifyExp (L l (OpApp _ x op y)) | isDol op = L l (HsApp EpAnnNotUsed x (nlHsPar y))-simplifyExp e@(L _ (HsLet _ _ ((HsValBinds _ (ValBinds _ binds []))) _ z)) =+simplifyExp (L l (OpApp _ x op y)) | isDol op = L l (HsApp noExtField x (nlHsPar y))+simplifyExp e@(L _ (HsLet _ ((HsValBinds _ (ValBinds _ binds []))) z)) = -- An expression of the form, 'let x = y in z'.- case bagToList binds of- [L _ (FunBind _ _ (MG _ (L _ [L _ (Match _(FunRhs (L _ x) _ _) [] (GRHSs _[L _ (GRHS _ [] y)] ((EmptyLocalBinds _))))])))]+ case binds of+ [L _ (FunBind _ _ (MG _ (L _ [L _ (Match _(FunRhs (L _ x) _ _ _) (L _ []) (GRHSs _ [L _ (GRHS _ [] y)] ((EmptyLocalBinds _))))])))] -- If 'x' is not in the free variables of 'y', beta-reduce to -- 'z[(y)/x]'. | occNameStr x `notElem` vars y && length [() | Unqual a <- universeBi z, a == rdrNameOcc x] <= 1 ->@@ -159,7 +158,7 @@ niceLambdaR xs (SimpleLambda [] x) = niceLambdaR xs x -- Rewrite @\xs -> (e)@ as @\xs -> e@.-niceLambdaR xs (L _ (HsPar _ _ x _)) = niceLambdaR xs x+niceLambdaR xs (L _ (HsPar _ x)) = niceLambdaR xs x -- @\vs v -> ($) e v@ ==> @\vs -> e@ -- @\vs v -> e $ v@ ==> @\vs -> e@@@ -177,7 +176,7 @@ , vars e `disjoint` [v] , L _ (HsVar _ (L _ fname)) <- f , isSymOcc $ rdrNameOcc fname- = let res = nlHsPar $ noLocA $ SectionL EpAnnNotUsed e f+ = let res = nlHsPar $ noLocA $ SectionL noExtField e f in (res, \s -> [Replace Expr s [] (unsafePrettyPrint res)]) -- @\vs v -> f x v@ ==> @\vs -> f x@@@ -198,7 +197,7 @@ -- lexeme, or it all gets too complex). niceLambdaR [x] (view -> App2 op@(L _ (HsVar _ (L _ tag))) l r) | isLexeme r, view l == Var_ x, x `notElem` vars r, allowRightSection (occNameStr tag) =- let e = rebracket1 $ addParen (noLocA $ SectionR EpAnnNotUsed op r)+ let e = rebracket1 $ addParen (noLocA $ SectionR noExtField op r) in (e, \s -> [Replace Expr s [] (unsafePrettyPrint e)]) -- Rewrite (1) @\x -> f (b x)@ as @f . b@, (2) @\x -> f $ b x@ as @f . b@. niceLambdaR [x] y@@ -213,7 +212,7 @@ factor (L _ (OpApp _ y op (factor -> Just (z, ss))))| isDol op = let r = niceDotApp y z in if astEq r z then Just (r, ss) else Just (r, y : ss)- factor (L _ (HsPar _ _ y@(L _ HsApp{}) _)) = factor y+ factor (L _ (HsPar _ y@(L _ HsApp{}))) = factor y factor _ = Nothing mkRefact :: [LHsExpr GhcPs] -> R.SrcSpan -> Refactoring R.SrcSpan mkRefact subts s =@@ -231,7 +230,7 @@ ) where gen :: LHsExpr GhcPs -> LHsExpr GhcPs- gen = noLocA . HsApp EpAnnNotUsed (strToVar "flip")+ gen = noLocA . HsApp noExtField (strToVar "flip") . if isAtom op then id else addParen -- We're done factoring, but have no variables left, so we shouldn't make a lambda.@@ -239,20 +238,20 @@ niceLambdaR [] e = (e, \s -> [Replace Expr s [("a", toSSA e)] "a"]) -- Base case. Just a good old fashioned lambda. niceLambdaR ss e =- let grhs = noLocA $ GRHS EpAnnNotUsed [] e :: LGRHS GhcPs (LHsExpr GhcPs)+ let grhs = noLocA $ GRHS noAnn [] e :: LGRHS GhcPs (LHsExpr GhcPs) grhss = GRHSs {grhssExt = emptyComments, grhssGRHSs=[grhs], grhssLocalBinds=EmptyLocalBinds noExtField}- match = noLocA $ Match {m_ext=EpAnnNotUsed, m_ctxt=LambdaExpr, m_pats=map strToPat ss, m_grhss=grhss} :: LMatch GhcPs (LHsExpr GhcPs)- matchGroup = MG {mg_ext=Generated, mg_alts=noLocA [match]}- in (noLocA $ HsLam noExtField matchGroup, const [])+ match = noLocA $ Match {m_ext=noExtField, m_ctxt=LamAlt LamSingle, m_pats=noLocA $ map strToPat ss, m_grhss=grhss} :: LMatch GhcPs (LHsExpr GhcPs)+ matchGroup = MG {mg_ext=Generated OtherExpansion SkipPmc, mg_alts=noLocA [match]}+ in (noLocA $ HsLam noAnn LamSingle matchGroup, const []) -- 'case' and 'if' expressions have branches, nothing else does (this -- doesn't consider 'HsMultiIf' perhaps it should?). replaceBranches :: LHsExpr GhcPs -> ([LHsExpr GhcPs], [LHsExpr GhcPs] -> LHsExpr GhcPs)-replaceBranches (L l (HsIf _ a b c)) = ([b, c], \[b, c] -> L l (HsIf EpAnnNotUsed a b c))+replaceBranches (L l (HsIf _ a b c)) = ([b, c], \[b, c] -> L l (HsIf noAnn a b c)) replaceBranches (L s (HsCase _ a (MG FromSource (L l bs)))) =- (concatMap f bs, L s . HsCase EpAnnNotUsed a . MG Generated . L l . g bs)+ (concatMap f bs, L s . HsCase noAnn a . MG (Generated OtherExpansion SkipPmc). L l . g bs) where f :: LMatch GhcPs (LHsExpr GhcPs) -> [LHsExpr GhcPs] f (L _ (Match _ CaseAlt _ (GRHSs _ xs _))) = [x | (L _ (GRHS _ _ x)) <- xs]@@ -260,7 +259,7 @@ g :: [LMatch GhcPs (LHsExpr GhcPs)] -> [LHsExpr GhcPs] -> [LMatch GhcPs (LHsExpr GhcPs)] g (L s1 (Match _ CaseAlt a (GRHSs _ ns b)) : rest) xs =- L s1 (Match EpAnnNotUsed CaseAlt a (GRHSs emptyComments [L a (GRHS EpAnnNotUsed gs x) | (L a (GRHS _ gs _), x) <- zip ns as] b)) : g rest bs+ L s1 (Match noExtField CaseAlt a (GRHSs emptyComments [L a (GRHS noAnn gs x) | (L a (GRHS _ gs _), x) <- zip ns as] b)) : g rest bs where (as, bs) = splitAt (length ns) xs g [] [] = [] g _ _ = error "GHC.Util.HsExpr.replaceBranches': internal invariant failed, lists are of differing lengths"@@ -298,7 +297,7 @@ g1 a b = fst (g a b) g2 a b = writer $ snd (g a b) - f i (L _ (HsPar _ _ y _)) z w+ f i (L _ (HsPar _ y)) z w | not $ needBracketOld i x y = (y, removeBracket z) where -- If the template expr is a Var, record it so that we can remove the brackets
src/GHC/Util/Scope.hs view
@@ -119,7 +119,7 @@ then maybe PossiblyImported (f . first (== EverythingBut)) (ideclImportList i) else NotImported where- f :: (Bool, LocatedL [LIE GhcPs]) -> IsImported+ f :: (Bool, LocatedLI [LocatedA (IE GhcPs)]) -> IsImported f (hide, L _ xs) | hide = if Just True `elem` ms then NotImported else PossiblyImported | Just True `elem` ms = Imported@@ -131,10 +131,10 @@ tag = occNameString x g :: LIE GhcPs -> Maybe Bool -- Does this import cover the name 'x'?- g (L _ (IEVar _ y)) = Just $ tag == unwrapName y- g (L _ (IEThingAbs _ y)) = Just $ tag == unwrapName y- g (L _ (IEThingAll _ y)) = if tag == unwrapName y then Just True else Nothing- g (L _ (IEThingWith _ y _wildcard ys)) = Just $ tag `elem` unwrapName y : map unwrapName ys+ g (L _ (IEVar _ y _)) = Just $ tag == unwrapName y+ g (L _ (IEThingAbs _ y _)) = Just $ tag == unwrapName y+ g (L _ (IEThingAll _ y _)) = if tag == unwrapName y then Just True else Nothing+ g (L _ (IEThingWith _ y _ ys _)) = Just $ tag `elem` unwrapName y : map unwrapName ys g _ = Just False unwrapName :: LIEWrappedName GhcPs -> String
src/GHC/Util/SrcLoc.hs view
@@ -17,10 +17,10 @@ import Data.Data import Data.Generics.Uniplate.DataOnly --- Get the 'SrcSpan' out of a value located by an 'Anchor' (e.g.--- comments).-getAncLoc :: GenLocated Anchor a -> SrcSpan-getAncLoc o = RealSrcSpan (anchor (getLoc o)) GHC.Data.Strict.Nothing+-- Get the 'SrcSpan' out of a value located by an 'NoCommentsLocation'+-- (e.g. comments).+getAncLoc :: GenLocated NoCommentsLocation a -> SrcSpan+getAncLoc o = RealSrcSpan (GHC.Parser.Annotation.epaLocationRealSrcSpan (GHC.Types.SrcLoc.getLoc o)) GHC.Data.Strict.Nothing -- 'stripLocs x' is 'x' with all contained source locs replaced by -- 'noSrcSpan'.
src/GHC/Util/Unify.hs view
@@ -1,5 +1,6 @@ {-# LANGUAGE PatternGuards, ViewPatterns, FlexibleContexts, ScopedTypeVariables, TupleSections #-} {-# LANGUAGE GeneralizedNewtypeDeriving, DeriveFunctor #-}+{-# LANGUAGE DataKinds #-} module GHC.Util.Unify( Subst(..), fromSubst,@@ -77,13 +78,13 @@ exp (L _ (HsVar _ x)) = lookup (rdrNameStr x) bind -- Operator applications. exp (L loc (OpApp _ lhs (L _ (HsVar _ x)) rhs))- | Just y <- lookup (rdrNameStr x) bind = Just (L loc (OpApp EpAnnNotUsed lhs y rhs))+ | Just y <- lookup (rdrNameStr x) bind = Just (L loc (OpApp noExtField lhs y rhs)) -- Left sections. exp (L loc (SectionL _ exp (L _ (HsVar _ x))))- | Just y <- lookup (rdrNameStr x) bind = Just (L loc (SectionL EpAnnNotUsed exp y))+ | Just y <- lookup (rdrNameStr x) bind = Just (L loc (SectionL noExtField exp y)) -- Right sections. exp (L loc (SectionR _ (L _ (HsVar _ x)) exp))- | Just y <- lookup (rdrNameStr x) bind = Just (L loc (SectionR EpAnnNotUsed y exp))+ | Just y <- lookup (rdrNameStr x) bind = Just (L loc (SectionR noExtField y exp)) exp _ = Nothing pat :: LPat GhcPs -> LPat GhcPs@@ -95,7 +96,7 @@ typ :: LHsType GhcPs -> LHsType GhcPs -- Type variables. typ (L _ (HsTyVar _ _ x))- | Just (L _ (HsAppType _ _ _ (HsWC _ y))) <- lookup (rdrNameStr x) bind = y+ | Just (L _ (HsAppType _ _ (HsWC _ y))) <- lookup (rdrNameStr x) bind = y typ x = x :: LHsType GhcPs @@ -114,11 +115,11 @@ | Just (x, y) <- cast (x, y) = if (x :: FastString) == y then Just mempty else Nothing -- We need some type magic to reduce this.- | Just (x :: EpAnn Anchor) <- cast x = Just mempty+ | Just (x :: EpAnn EpaLocation) <- cast x = Just mempty | Just (x :: EpAnn AnnContext) <- cast x = Just mempty | Just (x :: EpAnn AnnExplicitSum) <- cast x = Just mempty | Just (x :: EpAnn AnnFieldLabel) <- cast x = Just mempty- | Just (x :: EpAnn AnnList) <- cast x = Just mempty+ | Just (x :: EpAnn (AnnList [EpToken ","])) <- cast x = Just mempty | Just (x :: EpAnn AnnListItem) <- cast x = Just mempty | Just (x :: EpAnn AnnParen) <- cast x = Just mempty | Just (x :: EpAnn AnnPragma) <- cast x = Just mempty@@ -126,7 +127,6 @@ | Just (x :: EpAnn AnnsIf) <- cast x = Just mempty | Just (x :: EpAnn AnnSig) <- cast x = Just mempty | Just (x :: EpAnn AnnsModule) <- cast x = Just mempty- | Just (x :: EpAnn EpaLocation) <- cast x = Just mempty | Just (x :: EpAnn EpAnnHsCase) <- cast x = Just mempty | Just (x :: EpAnn EpAnnImportDecl) <- cast x = Just mempty | Just (x :: EpAnn EpAnnSumPat) <- cast x = Just mempty@@ -135,8 +135,16 @@ | Just (x :: EpAnn HsRuleAnn) <- cast x = Just mempty | Just (x :: EpAnn NameAnn) <- cast x = Just mempty | Just (x :: EpAnn NoEpAnns) <- cast x = Just mempty- | Just (x :: EpAnn [AddEpAnn]) <- cast x = Just mempty- | Just (x :: EpAnn (AddEpAnn, AddEpAnn)) <- cast x = Just mempty+ | Just (x :: EpToken "let") <- cast x = Just mempty+ | Just (x :: EpToken "in") <- cast x = Just mempty+ | Just (x :: EpToken "@") <- cast x = Just mempty+ | Just (x :: EpToken "(") <- cast x = Just mempty+ | Just (x :: EpToken ")") <- cast x = Just mempty+ | Just (x :: EpToken "type") <- cast x = Just mempty+ | Just (x :: EpToken "%") <- cast x = Just mempty+ | Just (x :: EpToken "%1") <- cast x = Just mempty+ | Just (x :: EpToken "⊸") <- cast x = Just mempty+ | Just (x :: EpUniToken "->" "→") <- cast x = Just mempty | Just (x :: TokenLocation) <- cast y = Just mempty | Just (y :: SrcSpan) <- cast y = Just mempty @@ -154,7 +162,7 @@ ((, Just y11) <$> unifyExp' nm False x1 y12) <|> case y12 of (L _ (OpApp _ y121 dot' y122)) | isDot dot' ->- unifyComposed' nm x1 (noLocA (OpApp EpAnnNotUsed y11 dot y121)) dot' y122+ unifyComposed' nm x1 (noLocA (OpApp noExtField y11 dot y121)) dot' y122 _ -> Nothing -- unifyExp handles the cases where both x and y are HsApp, or y is OpApp. Otherwise,@@ -188,7 +196,7 @@ -- Attempt #1: rewrite '(fun1 . fun2) arg' as 'fun1 (fun2 arg)', and unify it with 'x'. -- The guard ensures that you don't get duplicate matches because the matching engine -- auto-generates hints in dot-form.- (, Nothing) <$> unifyExp' nm root x (noLocA (HsApp EpAnnNotUsed y11 (noLocA (HsApp EpAnnNotUsed y12 y2))))+ (, Nothing) <$> unifyExp' nm root x (noLocA (HsApp noExtField y11 (noLocA (HsApp noExtField y12 y2)))) else do -- Attempt #2: rewrite '(fun1 . fun2 ... funn) arg' as 'fun1 $ (fun2 ... funn) arg', -- 'fun1 . fun2 $ (fun3 ... funn) arg', 'fun1 . fun2 . fun3 $ (fun4 ... funn) arg',@@ -203,9 +211,9 @@ unifyExp nm root x (L _ (OpApp _ lhs2 op2@(L _ (HsVar _ op2')) rhs2)) | (L _ (OpApp _ lhs1 op1@(L _ (HsVar _ op1')) rhs1)) <- x = guard (nm op1' op2') >> (, Nothing) <$> liftA2 (<>) (unifyExp' nm False lhs1 lhs2) (unifyExp' nm False rhs1 rhs2)- | isDol op2 = unifyExp nm root x $ noLocA (HsApp EpAnnNotUsed lhs2 rhs2)- | isAmp op2 = unifyExp nm root x $ noLocA (HsApp EpAnnNotUsed rhs2 lhs2)- | otherwise = unifyExp nm root x $ noLocA (HsApp EpAnnNotUsed (noLocA (HsApp EpAnnNotUsed op2 (addPar lhs2))) (addPar rhs2))+ | isDol op2 = unifyExp nm root x $ noLocA (HsApp noExtField lhs2 rhs2)+ | isAmp op2 = unifyExp nm root x $ noLocA (HsApp noExtField rhs2 lhs2)+ | otherwise = unifyExp nm root x $ noLocA (HsApp noExtField (noLocA (HsApp noExtField op2 (addPar lhs2))) (addPar rhs2)) where -- add parens around when desugaring the expression, if necessary addPar :: LHsExpr GhcPs -> LHsExpr GhcPs@@ -288,6 +296,6 @@ unifyType' nm (L loc (HsTyVar _ _ x)) y = let wc = HsWC noExtField y :: LHsWcType (NoGhcTc GhcPs) unused = strToVar "__unused__"- appType = L loc (HsAppType noExtField unused noHsTok wc)+ appType = L loc (HsAppType noAnn unused wc) in Just $ Subst [(rdrNameStr x, appType)] unifyType' nm x y = unifyDef' nm x y
src/GHC/Util/View.hs view
@@ -18,7 +18,7 @@ fromParen x = maybe x fromParen $ remParen x fromPParen :: LocatedA (Pat GhcPs) -> LocatedA (Pat GhcPs)-fromPParen (L _ (ParPat _ _ x _ )) = fromPParen x+fromPParen (L _ (ParPat _ x)) = fromPParen x fromPParen x = x class View a b where@@ -32,7 +32,7 @@ data LamConst1 = NoLamConst1 | LamConst1 (LocatedA (HsExpr GhcPs)) instance View (LocatedA (HsExpr GhcPs)) LamConst1 where- view (fromParen -> (L _ (HsLam _ (MG FromSource (L _ [L _ (Match _ LambdaExpr [L _ WildPat {}]+ view (fromParen -> (L _ (HsLam _ _ (MG FromSource (L _ [L _ (Match _ (LamAlt _) (L _ [L _ WildPat {}]) (GRHSs _ [L _ (GRHS _ [] x)] ((EmptyLocalBinds _))))]))))) = LamConst1 x view _ = NoLamConst1 @@ -62,4 +62,4 @@ -- A lambda with no guards and no where clauses pattern SimpleLambda :: [LocatedA (Pat GhcPs)] -> LocatedA (HsExpr GhcPs) -> LocatedA (HsExpr GhcPs)-pattern SimpleLambda vs body <- L _ (HsLam _ (MG _ (L _ [L _ (Match _ _ vs (GRHSs _ [L _ (GRHS _ [] body)] ((EmptyLocalBinds _))))])))+pattern SimpleLambda vs body <- L _ (HsLam _ LamSingle (MG _ (L _ [L _ (Match _ _ (L _ vs) (GRHSs _ [L _ (GRHS _ [] body)] ((EmptyLocalBinds _))))])))
src/Hint/All.hs view
@@ -21,6 +21,7 @@ import Hint.Bracket import Hint.Fixities import Hint.Naming+import Hint.Negation import Hint.Pattern import Hint.Import import Hint.Export@@ -37,7 +38,7 @@ -- | A list of the builtin hints wired into HLint. -- This list is likely to grow over time. data HintBuiltin =- HintList | HintListRec | HintMonad | HintLambda | HintFixities |+ HintList | HintListRec | HintMonad | HintLambda | HintFixities | HintNegation | HintBracket | HintNaming | HintPattern | HintImport | HintExport | HintPragma | HintExtensions | HintUnsafe | HintDuplicate | HintRestrict | HintComment | HintNewType | HintSmell | HintNumLiteral@@ -63,6 +64,7 @@ HintNaming -> decl namingHint HintBracket -> decl bracketHint HintFixities -> mempty{hintDecl=fixitiesHint}+ HintNegation -> decl negationParensHint HintSmell -> mempty{hintDecl=smellHint,hintModule=smellModuleHint} HintPattern -> decl patternHint HintMonad -> decl monadHint
src/Hint/Bracket.hs view
@@ -160,13 +160,13 @@ -- Brackets the roots of annotations are fine, so we strip them. annotations :: AnnDecl GhcPs -> AnnDecl GhcPs annotations= descendBi $ \x -> case (x :: LHsExpr GhcPs) of- L _ (HsPar _ _ x _) -> x+ L _ (HsPar _ x) -> x x -> x -- Brackets at the root of splices used to be required, but now they aren't splices :: HsDecl GhcPs -> HsDecl GhcPs splices (SpliceD a x) = SpliceD a $ flip descendBi x $ \x -> case (x :: LHsExpr GhcPs) of- L _ (HsPar _ _ x _) -> x+ L _ (HsPar _ x) -> x x -> x splices x = x @@ -271,32 +271,32 @@ dollar = concatMap f . universe where f x = [ (suggest "Redundant $" (reLoc x) (reLoc y) [r]){ideaSpan = locA (getLoc d)} | L _ (OpApp _ a d b) <- [x], isDol d- , let y = noLocA (HsApp EpAnnNotUsed a b) :: LHsExpr GhcPs+ , let y = noLocA (HsApp noExtField a b) :: LHsExpr GhcPs , not $ needBracket 0 y a , not $ needBracket 1 y b , not $ isPartialAtom (Just x) b , let r = Replace Expr (toSSA x) [("a", toSSA a), ("b", toSSA b)] "a b"] ++ [ suggest "Move brackets to avoid $" (reLoc x) (reLoc (t y)) [r]- |(t, e@(L _ (HsPar _ _ (L _ (OpApp _ a1 op1 a2)) _))) <- splitInfix x+ |(t, e@(L _ (HsPar _ (L _ (OpApp _ a1 op1 a2))))) <- splitInfix x , isDol op1 , isVar a1 || isApp a1 || isPar a1, not $ isAtom a2 , varToStr a1 /= "select" -- special case for esqueleto, see #224- , let y = noLocA $ HsApp EpAnnNotUsed a1 (nlHsPar a2)+ , let y = noLocA $ HsApp noExtField a1 (nlHsPar a2) , let r = Replace Expr (toSSA e) [("a", toSSA a1), ("b", toSSA a2)] "a (b)" ] ++ -- Special case of (v1 . v2) <$> v3 [ (suggest "Redundant bracket" (reLoc x) (reLoc y) [r]){ideaSpan = locA locPar}- | L _ (OpApp _ (L locPar (HsPar _ _ o1@(L locNoPar (OpApp _ _ (isDot -> True) _)) _)) o2 v3) <- [x], varToStr o2 == "<$>"- , let y = noLocA (OpApp EpAnnNotUsed o1 o2 v3) :: LHsExpr GhcPs+ | L _ (OpApp _ (L locPar (HsPar _ o1@(L locNoPar (OpApp _ _ (isDot -> True) _)))) o2 v3) <- [x], varToStr o2 == "<$>"+ , let y = noLocA (OpApp noExtField o1 o2 v3) :: LHsExpr GhcPs , let r = Replace Expr (toRefactSrcSpan (locA locPar)) [("a", toRefactSrcSpan (locA locNoPar))] "a"] ++ [ suggest "Redundant section" (reLoc x) (reLoc y) [r]- | L _ (HsApp _ (L _ (HsPar _ _ (L _ (SectionL _ a b)) _)) c) <- [x]+ | L _ (HsApp _ (L _ (HsPar _ (L _ (SectionL _ a b)))) c) <- [x] -- , error $ show (unsafePrettyPrint a, gshow b, unsafePrettyPrint c)- , let y = noLocA $ OpApp EpAnnNotUsed a b c :: LHsExpr GhcPs+ , let y = noLocA $ OpApp noExtField a b c :: LHsExpr GhcPs , let r = Replace Expr (toSSA x) [("x", toSSA a), ("op", toSSA b), ("y", toSSA c)] "x op y"] splitInfix :: LHsExpr GhcPs -> [(LHsExpr GhcPs -> LHsExpr GhcPs, LHsExpr GhcPs)] splitInfix (L l (OpApp _ lhs op rhs)) =- [(L l . OpApp EpAnnNotUsed lhs op, rhs), (\lhs -> L l (OpApp EpAnnNotUsed lhs op rhs), lhs)]+ [(L l . OpApp noExtField lhs op, rhs), (\lhs -> L l (OpApp noExtField lhs op rhs), lhs)] splitInfix _ = []
src/Hint/Comment.hs view
@@ -46,7 +46,7 @@ grab :: String -> LEpaComment -> String -> Idea grab msg o@(L pos _) s2 = let s1 = commentText o- loc = RealSrcSpan (anchor pos) GHC.Data.Strict.Nothing+ loc = RealSrcSpan (epaLocationRealSrcSpan pos) GHC.Data.Strict.Nothing in rawIdea Suggestion msg loc (f s1) (Just $ f s2) [] (refact loc) where f s = if isCommentMultiline o then "{-" ++ s ++ "-}" else "--" ++ s
src/Hint/Duplicate.hs view
@@ -37,7 +37,6 @@ import GHC.Types.SrcLoc import GHC.Hs import GHC.Utils.Outputable-import GHC.Data.Bag import GHC.Util import Language.Haskell.GhclibParserEx.GHC.Hs import Language.Haskell.GhclibParserEx.GHC.Hs.ExtendInstances@@ -54,7 +53,7 @@ dupes [ (m, d, y) | (m, d, x) <- ds , HsValBinds _ (ValBinds _ b _ ) :: HsLocalBinds GhcPs <- universeBi x- , let y = bagToList b+ , let y = b ] where ds = [(modName m, fromMaybe "" (declName d), unLoc d)
src/Hint/Export.hs view
@@ -23,7 +23,7 @@ exportHint :: ModuHint exportHint _ (ModuleEx (L s m@HsModule {hsmodName = Just name, hsmodExports = exports}) ) | Nothing <- exports =- let r = o{ hsmodExports = Just (noLocA [noLocA (IEModuleContents EpAnnNotUsed name)] )} in+ let r = o{ hsmodExports = Just (noLocA [noLocA (IEModuleContents (Nothing, noAnn) name)] )} in [(ignore "Use module export list" (L s o) (noLoc r) []){ideaNote = [Note "an explicit list is usually better"]}] | Just (L _ xs) <- exports , mods <- [x | x <- xs, isMod x]@@ -32,7 +32,7 @@ , exports' <- [x | x <- xs, not (matchesModName modName x)] , modName `elem` names = let dots = mkRdrUnqual (mkVarOcc " ... ")- r = o{ hsmodExports = Just (noLocA (noLocA (IEVar noExtField (noLocA (IEName noExtField (noLocA dots)))) : exports') )}+ r = o{ hsmodExports = Just (noLocA (noLocA (IEVar Nothing (noLocA (IEName noExtField (noLocA dots))) Nothing) : exports') )} in [ignore "Use explicit module export list" (L s o) (noLoc r) []] where
src/Hint/Extensions.hs view
@@ -249,6 +249,8 @@ foo = [|| x ||] {-# LANGUAGE TemplateHaskell #-} \ foo = $bar+{-# LANGUAGE TemplateHaskell #-} \+foo = $$typedExpressionSplice {-# LANGUAGE TypeData # -} \ type data Nat = Zero | Succ Nat -- @NoRefactor: refactor requires GHC >= 9.6.1 {-# LANGUAGE TypeData #-} \@@ -272,6 +274,7 @@ import Data.Set qualified as Set import Data.Map qualified as Map +import GHC.Data.FastString import GHC.Types.SrcLoc import GHC.Types.SourceText import GHC.Hs@@ -298,7 +301,7 @@ extensionsHint _ x = [ rawIdea Hint.Type.Warning "Unused LANGUAGE pragma"- (RealSrcSpan (anchor sl) GHC.Data.Strict.Nothing)+ (RealSrcSpan (epaLocationRealSrcSpan sl) GHC.Data.Strict.Nothing) (comment_ (mkLanguagePragmas sl exts)) (Just newPragma) ( [RequiresExtension (show gone) | (_, Just x) <- before \\ after, gone <- Map.findWithDefault [] x disappear] ++@@ -421,11 +424,11 @@ where f :: HsExpr GhcPs -> Bool f (HsCase _ _ (MG _ (L _ []))) = True- f (HsLamCase _ _ (MG _ (L _ []))) = True+ f (HsLam _ LamCase (MG _ (L _ []))) = True f _ = False used KindSignatures = hasT (un :: HsKind GhcPs) used BangPatterns = hasS isPBangPat ||^ hasS isStrictMatch-used TemplateHaskell = hasS $ not . isQuasiQuoteSplice+used TemplateHaskell = hasS (not . isQuasiQuoteSplice) ||^ hasS isTypedSplice used TemplateHaskellQuotes = hasS f where f :: HsExpr GhcPs -> Bool@@ -490,8 +493,8 @@ used NumericUnderscores = hasS f where f :: OverLitVal -> Bool- f (HsIntegral (IL (SourceText t) _ _)) = '_' `elem` t- f (HsFractional (FL (SourceText t) _ _ _ _)) = '_' `elem` t+ f (HsIntegral (IL (SourceText t) _ _)) = '_' `elem` unpackFS t+ f (HsFractional (FL (SourceText t) _ _ _ _)) = '_' `elem` unpackFS t f _ = False used LambdaCase = hasS isLCase
src/Hint/Fixities.hs view
@@ -73,7 +73,6 @@ needParenAsChild HsLet{} = True needParenAsChild HsDo{} = True needParenAsChild HsLam{} = True-needParenAsChild HsLamCase{} = True needParenAsChild HsCase{} = True needParenAsChild HsIf{} = True needParenAsChild _ = False
src/Hint/Lambda.hs view
@@ -87,6 +87,7 @@ yes = blah (\ x -> case x of A -> a; B -> b) -- \ case A -> a; B -> b yes = blah (\ x -> case x of A -> a; B -> b) -- @Note may require `{-# LANGUAGE LambdaCase #-}` adding to the top of the file no = blah (\ x -> case x of A -> a x; B -> b x)+no = blah (\ x -> case x of A -> a x; x -> b x) foo = bar (\x -> case x of Y z | z > 0 -> z) -- \case Y z | z > 0 -> z yes = blah (\ x -> (y, x)) -- (y,) yes = blah (\ x -> (y, x, z+q)) -- (y, , z+q)@@ -122,6 +123,7 @@ import GHC.Types.Name.Reader import GHC.Types.SrcLoc import Language.Haskell.GhclibParserEx.GHC.Hs.Expr (isTypeApp, isOpApp, isLambda, isQuasiQuoteExpr, isVar, isDol, strToVar)+import Language.Haskell.GhclibParserEx.GHC.Hs.Pat (isWildPat) import Language.Haskell.GhclibParserEx.GHC.Utils.Outputable import Language.Haskell.GhclibParserEx.GHC.Types.Name.Reader import GHC.Util.Brackets (isAtom)@@ -147,7 +149,7 @@ lambdaBind o@(L _ origBind@FunBind {fun_id = funName@(L loc1 _), fun_matches = MG {mg_alts =- L _ [L _ (Match _ ctxt@(FunRhs _ Prefix _) pats (GRHSs _ [L _ (GRHS _ [] origBody@(L loc2 _))] bind))]}}) rtype+ L _ [L _ (Match _ ctxt@(FunRhs _ Prefix _ _) (L _ pats) (GRHSs _ [L _ (GRHS _ [] origBody@(L loc2 _))] bind))]}}) rtype | EmptyLocalBinds _ <- bind , isLambda $ fromParen origBody , null (universeBi pats :: [HsExpr GhcPs])@@ -170,7 +172,7 @@ where reform :: [LPat GhcPs] -> LHsExpr GhcPs -> Located (HsDecl GhcPs) reform ps b = L (combineSrcSpans (locA loc1) (locA loc2)) $ ValD noExtField $- origBind {fun_matches = MG Generated (noLocA [noLocA $ Match EpAnnNotUsed ctxt ps $ GRHSs emptyComments [noLocA $ GRHS EpAnnNotUsed [] b] $ EmptyLocalBinds noExtField])}+ origBind {fun_matches = MG (Generated OtherExpansion SkipPmc) (noLocA [noLocA $ Match noExtField ctxt (L noSpanAnchor ps) $ GRHSs emptyComments [noLocA $ GRHS noAnn [] b] $ EmptyLocalBinds noExtField])} mkSubtsAndTpl newPats newBody = (sub, tpl) where@@ -186,11 +188,11 @@ , y `notElem` vars x , not $ any isQuasiQuoteExpr $ universe x = etaReduce ps x-etaReduce ps (L loc (OpApp _ x (isDol -> True) y)) = etaReduce ps (L loc (HsApp EpAnnNotUsed x y))+etaReduce ps (L loc (OpApp _ x (isDol -> True) y)) = etaReduce ps (L loc (HsApp noExtField x y)) etaReduce ps x = (ps, x) lambdaExp :: Maybe (LHsExpr GhcPs) -> LHsExpr GhcPs -> [Idea]-lambdaExp _ o@(L _ (HsPar _ _ (L _ (HsApp _ oper@(L _ (HsVar _ origf@(L _ (rdrNameOcc -> f)))) y)) _))+lambdaExp _ o@(L _ (HsPar _ (L _ (HsApp _ oper@(L _ (HsVar _ origf@(L _ (rdrNameOcc -> f)))) y)))) | isSymOcc f -- is this an operator? , isAtom y , allowLeftSection $ occNameString f@@ -198,22 +200,22 @@ = [suggest "Use section" (reLoc o) (reLoc to) [r]] where to :: LHsExpr GhcPs- to = nlHsPar $ noLocA $ SectionL EpAnnNotUsed y oper+ to = nlHsPar $ noLocA $ SectionL noExtField y oper r = Replace Expr (toSSA o) [("x", toSSA y)] ("(x " ++ unsafePrettyPrint origf ++ ")") -lambdaExp _ o@(L _ (HsPar _ _ (view -> App2 (view -> Var_ "flip") origf@(view -> RdrName_ f) y) _))+lambdaExp _ o@(L _ (HsPar _ (view -> App2 (view -> Var_ "flip") origf@(view -> RdrName_ f) y))) | allowRightSection (rdrNameStr f), not $ "(" `isPrefixOf` rdrNameStr f = [suggest "Use section" (reLoc o) (reLoc to) [r]] where to :: LHsExpr GhcPs- to = nlHsPar $ noLocA $ SectionR EpAnnNotUsed origf y+ to = nlHsPar $ noLocA $ SectionR noExtField origf y op = if isSymbolRdrName (unLoc f) then unsafePrettyPrint f else "`" ++ unsafePrettyPrint f ++ "`" var = if rdrNameStr f == "x" then "y" else "x" r = Replace Expr (toSSA o) [(var, toSSA y)] ("(" ++ op ++ " " ++ var ++ ")") -lambdaExp p o@(L _ HsLam{})+lambdaExp p o@(L _ (HsLam _ LamSingle _)) | not $ any isOpApp p , (res, refact) <- niceLambdaR [] o , not $ isLambda res@@ -223,7 +225,7 @@ -- If the lambda's parent is an HsPar, and the result is also an HsPar, the span should include the parentheses. , let from = case p of -- Avoid creating redundant bracket.- Just p@(L _ (HsPar _ _ (L _ HsLam{}) _))+ Just p@(L _ (HsPar _ (L _ HsLam{}))) | L _ HsPar{} <- res -> p | L _ (HsVar _ (L _ name)) <- res, not (isSymbolRdrName name) -> p _ -> o@@ -252,7 +254,7 @@ | ([_x], ys) <- partition ((==Just x) . tupArgVar) args -- the other arguments must not have a nested x somewhere in them , Set.notMember x $ Set.map occNameString $ freeVars ys- -> [(suggestN "Use tuple-section" (reLoc o) $ noLoc $ ExplicitTuple EpAnnNotUsed (map removeX args) boxity)+ -> [(suggestN "Use tuple-section" (reLoc o) $ noLoc $ ExplicitTuple noAnn (map removeX args) boxity) {ideaNote = [RequiresExtension "TupleSections"]}] -- suggest @LambdaCase@/directly matching in a lambda instead of doing @\x -> case x of ...@ HsCase _ (view -> Var_ x') matchGroup@@ -268,7 +270,7 @@ -- * mark match as being in a lambda context so that it's printed properly oldMG@(MG _ (L _ [L _ oldmatch])) | all (\(L _ (GRHS _ stmts _)) -> null stmts) (grhssGRHSs (m_grhss oldmatch)) ->- let patLocs = fmap (locA . getLoc) (m_pats oldmatch)+ let patLocs = fmap (locA . getLoc) ((unLoc . m_pats) oldmatch) bodyLocs = concatMap (\case L _ (GRHS _ _ body) -> [locA (getLoc body)]) $ grhssGRHSs (m_grhss oldmatch) r | notNull patLocs && notNull bodyLocs =@@ -278,13 +280,13 @@ ((if needParens then "\\(x)" else "\\x") ++ " -> y") ] | otherwise = []- needParens = any (patNeedsParens appPrec . unLoc) (m_pats oldmatch)+ needParens = any (patNeedsParens appPrec . unLoc) ((unLoc . m_pats) oldmatch) in [ suggest "Use lambda" (reLoc o)- ( noLoc $ HsLam noExtField oldMG+ ( noLoc $ HsLam noAnn LamSingle oldMG { mg_alts = noLocA [ noLocA oldmatch- { m_pats = map mkParPat $ m_pats oldmatch- , m_ctxt = LambdaExpr+ { m_pats = L noSpanAnchor (map mkParPat $ (unLoc . m_pats) oldmatch)+ , m_ctxt = LamAlt LamSingle } ] }@@ -295,7 +297,7 @@ -- otherwise we should use @LambdaCase@ MG _ (L _ _) ->- [(suggestN "Use lambda-case" (reLoc o) $ noLoc $ HsLamCase EpAnnNotUsed LamCase matchGroup)+ [(suggestN "Use lambda-case" (reLoc o) $ noLoc $ HsLam noAnn LamCase matchGroup) {ideaNote=[RequiresExtension "LambdaCase"]}] _ -> [] where@@ -303,7 +305,7 @@ -- to a missing argument, so that we get the proper section. removeX :: HsTupArg GhcPs -> HsTupArg GhcPs removeX (Present _ (view -> Var_ x'))- | x == x' = Missing EpAnnNotUsed+ | x == x' = Missing noAnn removeX y = y -- | Extract the name of an argument of a tuple if it's present and a variable. tupArgVar :: HsTupArg GhcPs -> Maybe String@@ -344,9 +346,6 @@ let used = Set.fromList [rdrNameStr name | (L _ (VarPat _ name)) <- universe p] in (used, (True, p)) | otherwise = (mempty, (False, p))-- isWildPat :: LPat GhcPs -> Bool- isWildPat = \case (L _ (WildPat _)) -> True; _ -> False -- Replace the pattern with a variable pattern if the pattern doesn't contain wildcards. munge :: String -> (Bool, LPat GhcPs) -> LPat GhcPs
src/Hint/List.hs view
@@ -44,6 +44,7 @@ import Control.Applicative import Data.Generics.Uniplate.DataOnly+import Data.List.NonEmpty qualified as NE import Data.List.Extra import Data.Maybe import Prelude@@ -103,9 +104,9 @@ listCompCheckGuards :: LHsExpr GhcPs -> HsDoFlavour -> [ExprLStmt GhcPs] -> [Idea] listCompCheckGuards o ctx stmts =- let revs = reverse stmts- e@(L _ LastStmt{}) = head revs -- In a ListComp, this is always last.- xs = reverse (tail revs) in+ let revs = NE.reverse $ NE.fromList stmts+ e@(L _ LastStmt{}) = NE.head revs -- In a ListComp, this is always last.+ xs = reverse (NE.tail revs) in list_comp_aux e xs where list_comp_aux e xs@@ -115,9 +116,9 @@ | otherwise = [] where ys = moveGuardsForward xs- o' = noLocA $ ExplicitList EpAnnNotUsed []- o2 = noLocA $ HsDo EpAnnNotUsed ctx (noLocA (filter ((/= Just "True") . qualCon) xs ++ [e]))- o3 = noLocA $ HsDo EpAnnNotUsed ctx (noLocA $ ys ++ [e])+ o' = noLocA $ ExplicitList noAnn []+ o2 = noLocA $ HsDo noAnn ctx (noLocA (filter ((/= Just "True") . qualCon) xs ++ [e]))+ o3 = noLocA $ HsDo noAnn ctx (noLocA $ ys ++ [e]) cons = mapMaybe qualCon xs qualCon :: ExprLStmt GhcPs -> Maybe String qualCon (L _ (BodyStmt _ (L _ (HsVar _ (L _ x))) _ _)) = Just (occNameStr x)@@ -128,10 +129,11 @@ listCompCheckMap o mp f ctx stmts | varToStr mp == "map" = [suggest "Move map inside list comprehension" (reLoc o) (reLoc o2) (suggestExpr o o2)] where- revs = reverse stmts- L _ (LastStmt _ body b s) = head revs -- In a ListComp, this is always last.- last = noLocA $ LastStmt noExtField (noLocA $ HsApp EpAnnNotUsed (paren f) (paren body)) b s- o2 =noLocA $ HsDo EpAnnNotUsed ctx (noLocA $ reverse (tail revs) ++ [last])+ revs = NE.reverse $ NE.fromList stmts+ L _ (LastStmt _ body b s) = NE.head revs -- In a ListComp, this is always last.+ last = noLocA $ LastStmt noExtField (noLocA $ HsApp noExtField (paren f) (paren body)) b s+ o2 =noLocA $ HsDo noAnn ctx (noLocA $ reverse (NE.tail revs) ++ [last])+ listCompCheckMap _ _ _ _ _ = [] suggestExpr :: LHsExpr GhcPs -> LHsExpr GhcPs -> [Refactoring R.SrcSpan]@@ -162,7 +164,7 @@ listExp overloadedListsOn b (fromParen -> x) = if null res then concatMap (listExp overloadedListsOn $ isAppend x) $ children x- else [head res]+ else [NE.head $ NE.fromList res] where res = [suggest name (reLoc x) (reLoc x2) [r] | (name, f) <- checks overloadedListsOn@@ -170,7 +172,7 @@ , let r = Replace Expr (toSSA x) subts temp ] listPat :: LPat GhcPs -> [Idea]-listPat x = if null res then concatMap listPat $ children x else [head res]+listPat x = if null res then concatMap listPat $ children x else [NE.head $ NE.fromList res] where res = [suggest name (reLoc x) (reLoc x2) [r] | (name, f) <- pchecks , Just (x2, subts, temp) <- [f x]@@ -202,9 +204,9 @@ usePList :: LPat GhcPs -> Maybe (LPat GhcPs, [(String, R.SrcSpan)], String) usePList = fmap ( (\(e, s) ->- (noLocA (ListPat EpAnnNotUsed e)+ (noLocA (ListPat noAnn e) , map (fmap toRefactSrcSpan . fst) s- , unsafePrettyPrint (noLocA $ ListPat EpAnnNotUsed (map snd s) :: LPat GhcPs))+ , unsafePrettyPrint (noLocA $ ListPat noAnn (map snd s) :: LPat GhcPs)) ) . unzip )@@ -219,16 +221,16 @@ useString :: p -> LHsExpr GhcPs -> Maybe (LHsExpr GhcPs, [a], String) useString b (L _ (ExplicitList _ xs)) | not $ null xs, Just s <- mapM fromChar xs =- let literal = noLocA (HsLit EpAnnNotUsed (HsString NoSourceText (fsLit (show s)))) :: LHsExpr GhcPs+ let literal = noLocA (HsLit noExtField (HsString NoSourceText (fsLit (show s)))) :: LHsExpr GhcPs in Just (literal, [], unsafePrettyPrint literal) useString _ _ = Nothing useList :: p -> LHsExpr GhcPs -> Maybe (LHsExpr GhcPs, [(String, R.SrcSpan)], String) useList b = fmap ( (\(e, s) ->- (noLocA (ExplicitList EpAnnNotUsed e)+ (noLocA (ExplicitList noAnn e) , map (fmap toSSA) s- , unsafePrettyPrint (noLocA $ ExplicitList EpAnnNotUsed (map snd s) :: LHsExpr GhcPs))+ , unsafePrettyPrint (noLocA $ ExplicitList noAnn (map snd s) :: LHsExpr GhcPs)) ) . unzip )@@ -258,17 +260,17 @@ f _ = Nothing gen :: LHsExpr GhcPs -> LHsExpr GhcPs -> LHsExpr GhcPs- gen x = noLocA . OpApp EpAnnNotUsed x (noLocA (HsVar noExtField (noLocA consDataCon_RDR)))+ gen x = noLocA . OpApp noExtField x (noLocA (HsVar noExtField (noLocA consDataCon_RDR))) useCons _ _ = Nothing typeListChar :: LHsType GhcPs typeListChar =- noLocA $ HsListTy EpAnnNotUsed- (noLocA (HsTyVar EpAnnNotUsed NotPromoted (noLocA (mkVarUnqual (fsLit "Char")))))+ noLocA $ HsListTy noAnn+ (noLocA (HsTyVar noAnn NotPromoted (noLocA (mkVarUnqual (fsLit "Char"))))) typeString :: LHsType GhcPs typeString =- noLocA $ HsTyVar EpAnnNotUsed NotPromoted (noLocA (mkVarUnqual (fsLit "String")))+ noLocA $ HsTyVar noAnn NotPromoted (noLocA (mkVarUnqual (fsLit "String"))) stringType :: LHsDecl GhcPs -> [Idea] stringType (L _ x) = case x of
src/Hint/ListRec.hs view
@@ -134,16 +134,16 @@ asDo :: LHsExpr GhcPs -> [LStmt GhcPs (LHsExpr GhcPs)] asDo (view -> App2 bind lhs- (L _ (HsLam _ MG {+ (L _ (HsLam _ LamSingle MG { mg_ext=FromSource , mg_alts=L _ [- L _ Match { m_ctxt=LambdaExpr- , m_pats=[v@(L _ VarPat{})]+ L _ Match { m_ctxt=(LamAlt LamSingle)+ , m_pats=L _ [v@(L _ VarPat{})] , m_grhss=GRHSs _ [L _ (GRHS _ [] rhs)] (EmptyLocalBinds _)}]})) ) =- [ noLocA $ BindStmt EpAnnNotUsed v lhs+ [ noLocA $ BindStmt noAnn v lhs , noLocA $ BodyStmt noExtField rhs noSyntaxExpr noSyntaxExpr ] asDo (L _ (HsDo _ (DoExpr _) (L _ stmts))) = stmts asDo x = [noLocA $ BodyStmt noExtField x noSyntaxExpr noSyntaxExpr]@@ -173,10 +173,10 @@ let ps12 = let (a, b) = splitAt p1 ps1 in map strToPat (a ++ xs : b) -- Function arguments. emptyLocalBinds = EmptyLocalBinds noExtField :: HsLocalBindsLR GhcPs GhcPs -- Empty where clause.- gRHS e = noLocA $ GRHS EpAnnNotUsed [] e :: LGRHS GhcPs (LHsExpr GhcPs) -- Guarded rhs.+ gRHS e = noLocA $ GRHS noAnn [] e :: LGRHS GhcPs (LHsExpr GhcPs) -- Guarded rhs. gRHSSs e = GRHSs emptyComments [gRHS e] emptyLocalBinds -- Guarded rhs set.- match e = Match{m_ext=EpAnnNotUsed,m_pats=ps12, m_grhss=gRHSSs e, ..} -- Match.- matchGroup e = MG{mg_alts=noLocA [noLocA $ match e], mg_ext=Generated, ..} -- Match group.+ match e = Match{m_ext=noExtField,m_pats=noLocA ps12, m_grhss=gRHSSs e, ..} -- Match.+ matchGroup e = MG{mg_alts=noLocA [noLocA $ match e], mg_ext=Generated OtherExpansion SkipPmc, ..} -- Match group. funBind e = FunBind {fun_matches=matchGroup e, ..} :: HsBindLR GhcPs GhcPs -- Fun bind. pure (ListCase ps b1 (x, xs, b2), noLocA . ValD noExtField . funBind)@@ -212,7 +212,7 @@ , grhssLocalBinds=EmptyLocalBinds _ } } <- pure x- (a, b, c) <- findPat ps+ (a, b, c) <- findPat (unLoc ps) pure $ Branch (occNameStr name) a b c $ simplifyExp body findPat :: [LPat GhcPs] -> Maybe ([String], Int, BList)@@ -225,7 +225,7 @@ readPat :: LPat GhcPs -> Maybe (Either String BList) readPat (view -> PVar_ x) = Just $ Left x-readPat (L _ (ParPat _ _ (L _ (ConPat _ (L _ n) (InfixCon (view -> PVar_ x) (view -> PVar_ xs)))) _))+readPat (L _ (ParPat _ (L _ (ConPat _ (L _ n) (InfixCon (view -> PVar_ x) (view -> PVar_ xs)))))) | n == consDataCon_RDR = Just $ Right $ BCons x xs readPat (L _ (ConPat _ (L _ n) (PrefixCon [] []))) | n == nameRdrName nilDataConName = Just $ Right BNil
src/Hint/Match.hs view
@@ -53,7 +53,6 @@ import Config.Type import Data.Generics.Uniplate.DataOnly -import GHC.Data.Bag import GHC.Hs import GHC.Types.SrcLoc import GHC.Types.SourceText@@ -101,8 +100,8 @@ -- If a == b then -- x is 'a', op is '==' and y is 'b' and,- let lSec = addParen (L l (SectionL EpAnnNotUsed x op)) -- (a == )- rSec = addParen (L l (SectionR EpAnnNotUsed op y)) -- ( == b)+ let lSec = addParen (L l (SectionL noExtField x op)) -- (a == )+ rSec = addParen (L l (SectionR noExtField op y)) -- ( == b) in (first (lSec :) <$> dotVersion y) ++ (first (rSec :) <$> dotVersion x) -- [([(a ==)], b), ([(b == )], a])]. dotVersion _ = [] @@ -121,7 +120,7 @@ -- | A list of root expressions, with their associated names findDecls :: LHsDecl GhcPs -> [(String, LHsExpr GhcPs)] findDecls x@(L _ (InstD _ (ClsInstD _ ClsInstDecl{cid_binds}))) =- [(fromMaybe "" $ bindName xs, x) | xs <- bagToList cid_binds, x <- childrenBi xs]+ [(fromMaybe "" $ bindName xs, x) | xs <- cid_binds, x <- childrenBi xs] findDecls (L _ RuleD{}) = [] -- Often rules contain things that HLint would rewrite. findDecls x = map (fromMaybe "" $ declName x,) $ childrenBi x @@ -142,7 +141,7 @@ -- Need to check free vars before unqualification, but after subst -- (with 'e') need to unqualify before substitution (with 'res').- let rhs' | Just fun <- extra = rebracket1 $ noLocA (HsApp EpAnnNotUsed fun rhs)+ let rhs' | Just fun <- extra = rebracket1 $ noLocA (HsApp noExtField fun rhs) | otherwise = rhs (e, (tpl, substNoParens)) = substitute u rhs' noParens = [varToStr $ fromParen x | L _ (HsApp _ (varToStr -> "_noParen_") x) <- universe tpl]@@ -183,7 +182,7 @@ | varToStr op == "||" = bool x || bool y | varToStr op == "==" = expr (fromParen1 x) `astEq` expr (fromParen1 y) bool (L _ (HsApp _ x y)) | varToStr x == "not" = not $ bool y- bool (L _ (HsPar _ _ x _)) = bool x+ bool (L _ (HsPar _ x)) = bool x bool (L _ (HsApp _ cond (sub -> y))) | 'i' : 's' : typ <- varToStr cond = isType typ y@@ -220,7 +219,7 @@ typ == top asInt :: LHsExpr GhcPs -> Maybe Integer- asInt (L _ (HsPar _ _ x _)) = asInt x+ asInt (L _ (HsPar _ x)) = asInt x asInt (L _ (NegApp _ x _)) = negate <$> asInt x asInt (L _ (HsLit _ (HsInt _ (IL _ _ x)) )) = Just x asInt (L _ (HsOverLit _ (OverLit _ (HsIntegral (IL _ _ x))))) = Just x@@ -276,5 +275,5 @@ where f :: LHsType GhcPs -> LHsType GhcPs f (L _ (HsAppTy _ t x@(L _ HsAppTy{}))) =- noLocA (HsAppTy noExtField t (noLocA (HsParTy EpAnnNotUsed x)))+ noLocA (HsAppTy noExtField t (noLocA (HsParTy noAnn x))) f x = x
src/Hint/Monad.hs view
@@ -77,7 +77,6 @@ import GHC.Types.Basic import GHC.Types.Name.Reader import GHC.Types.Name.Occurrence-import GHC.Data.Bag import GHC.Data.Strict qualified import Language.Haskell.GhclibParserEx.GHC.Hs.Pat@@ -120,8 +119,8 @@ case x of (view -> App2 op x1 x2) | isTag ">>" op -> f x1 (view -> App2 op x1 (view -> LamConst1 _)) | isTag ">>=" op -> f x1- (L l (HsApp _ op x)) | isTag "void" op -> seenVoid (L l . HsApp EpAnnNotUsed op) x- (L l (OpApp _ op dol x)) | isTag "void" op, isDol dol -> seenVoid (L l . OpApp EpAnnNotUsed op dol) x+ (L l (HsApp _ op x)) | isTag "void" op -> seenVoid (L l . HsApp noExtField op) x+ (L l (OpApp _ op dol x)) | isTag "void" op, isDol dol -> seenVoid (L l . OpApp noExtField op dol) x (L loc (HsDo _ ctx (L loc2 [L loc3 (BodyStmt _ y _ _ )]))) -> let doOrMDo = case ctx of MDoExpr _ -> "mdo"; _ -> "do" in [ ideaRemove Ignore ("Redundant " ++ doOrMDo) (doSpan doOrMDo (locA loc)) doOrMDo [Replace Expr (toSSA x) [("y", toSSA y)] "y"]@@ -129,14 +128,14 @@ , not $ doAsAvoidingIndentation parentDo x ] (L loc (HsDo _ (DoExpr mm) (L _ xs))) ->- monadSteps (L loc . HsDo EpAnnNotUsed (DoExpr mm) . noLocA) xs +++ monadSteps (L loc . HsDo noAnn (DoExpr mm) . noLocA) xs ++ [suggest "Use let" (reLoc from) (reLoc to) [r] | (from, to, r) <- monadLet xs] ++ concat [f x | (L _ (BodyStmt _ x _ _)) <- dropEnd1 xs] ++ concat [f x | (L _ (BindStmt _ (L _ WildPat{}) x)) <- dropEnd1 xs] _ -> [] where f = monadNoResult (fromMaybe "" decl) id- seenVoid wrap (L l (HsPar x p y q)) = seenVoid (wrap . L l . \y -> HsPar x p y q) y+ seenVoid wrap (L l (HsPar x y)) = seenVoid (wrap . L l . \y -> HsPar x y) y seenVoid wrap x = -- Suggest `traverse_ f x` given `void $ traverse_ f x` [warn "Redundant void" (reLoc (wrap x)) (reLoc x) [Replace Expr (toSSA (wrap x)) [("a", toSSA x)] "a"] | returnsUnit x]@@ -179,9 +178,9 @@ -- Return True if they are using do as avoiding indentation doAsAvoidingIndentation :: Maybe (LHsExpr GhcPs) -> LHsExpr GhcPs -> Bool doAsAvoidingIndentation (Just (L _ (HsDo _ _ (L anna _)))) (L _ (HsDo _ _ (L annb _)))- | SrcSpanAnn _ (RealSrcSpan a _) <- anna- , SrcSpanAnn _ (RealSrcSpan b _) <- annb- = srcSpanStartCol a == srcSpanStartCol b+ | EpAnn (EpaSpan (RealSrcSpan a _)) _ _ <- anna+ , EpAnn (EpaSpan (RealSrcSpan b _)) _ _ <- annb+ = srcSpanStartCol a == srcSpanStartCol b doAsAvoidingIndentation parent self = False -- Apply a function to the application head, including `head arg` and `head $ arg`, which modifies@@ -190,9 +189,9 @@ modifyAppHead f = go id where go :: (LHsExpr GhcPs -> LHsExpr GhcPs) -> LHsExpr GhcPs -> (LHsExpr GhcPs, Maybe a)- go wrap (L l (HsPar _ p x q)) = go (wrap . L l . \y -> HsPar EpAnnNotUsed p y q) x- go wrap (L l (HsApp _ x y)) = go (\x -> wrap $ L l (HsApp EpAnnNotUsed x y)) x- go wrap (L l (OpApp _ x op y)) | isDol op = go (\x -> wrap $ L l (OpApp EpAnnNotUsed x op y)) x+ go wrap (L l (HsPar _ x)) = go (wrap . L l . \y -> HsPar noAnn y) x+ go wrap (L l (HsApp _ x y)) = go (\x -> wrap $ L l (HsApp noExtField x y)) x+ go wrap (L l (OpApp _ x op y)) | isDol op = go (\x -> wrap $ L l (OpApp noExtField x op y)) x go wrap (L l (HsVar _ x)) = (wrap (L l (HsVar NoExtField x')), Just a) where (x', a) = f x go _ expr = (expr, Nothing)@@ -205,11 +204,11 @@ -- See through HsPar, and down HsIf/HsCase, return the name to use in -- the hint, and the revised expression. monadNoResult :: String -> (LHsExpr GhcPs -> LHsExpr GhcPs) -> LHsExpr GhcPs -> [Idea]-monadNoResult inside wrap (L l (HsPar _ _ x _)) = monadNoResult inside (wrap . nlHsPar) x-monadNoResult inside wrap (L l (HsApp _ x y)) = monadNoResult inside (\x -> wrap $ L l (HsApp EpAnnNotUsed x y)) x+monadNoResult inside wrap (L l (HsPar _ x)) = monadNoResult inside (wrap . nlHsPar) x+monadNoResult inside wrap (L l (HsApp _ x y)) = monadNoResult inside (\x -> wrap $ L l (HsApp noExtField x y)) x monadNoResult inside wrap (L l (OpApp _ x tag@(L _ (HsVar _ (L _ op))) y))- | isDol tag = monadNoResult inside (\x -> wrap $ L l (OpApp EpAnnNotUsed x tag y)) x- | occNameStr op == ">>=" = monadNoResult inside (wrap . L l . OpApp EpAnnNotUsed x tag) y+ | isDol tag = monadNoResult inside (\x -> wrap $ L l (OpApp noExtField x tag y)) x+ | occNameStr op == ">>=" = monadNoResult inside (wrap . L l . OpApp noExtField x tag) y monadNoResult inside wrap x | x2 : _ <- filter (`isTag` x) badFuncs , let x3 = x2 ++ "_"@@ -235,7 +234,7 @@ -- Suggest to use join. Rewrite 'do x <- $1; x; $2' as 'do join $1; $2'. monadStep wrap o@(g@(L _ (BindStmt _ (view -> PVar_ p) x)):q@(L _ (BodyStmt _ (view -> Var_ v) _ _)):xs) | p == v && v `notElem` varss xs- = let app = noLocA $ HsApp EpAnnNotUsed (strToVar "join") x+ = let app = noLocA $ HsApp noExtField (strToVar "join") x body = noLocA $ BodyStmt noExtField (rebracket1 app) noSyntaxExpr noSyntaxExpr stmts = body : xs in [warn "Use join" (reLoc (wrap o)) (reLoc (wrap stmts)) r]@@ -261,7 +260,7 @@ , q@(L _ (BodyStmt _ (fromApplies -> (ret:f:fs, view -> Var_ v)) _ _))] | isReturn ret, notDol x, u == v, length fs < 3, all isSimple (f : fs), v `notElem` vars (f : fs) =- [warn "Use <$>" (reLoc (wrap o)) (reLoc (wrap [noLocA $ BodyStmt noExtField (noLocA $ OpApp EpAnnNotUsed (foldl' (\acc e -> noLocA $ OpApp EpAnnNotUsed acc (strToVar ".") e) f fs) (strToVar "<$>") x) noSyntaxExpr noSyntaxExpr]))+ [warn "Use <$>" (reLoc (wrap o)) (reLoc (wrap [noLocA $ BodyStmt noExtField (noLocA $ OpApp noExtField (foldl' (\acc e -> noLocA $ OpApp noExtField acc (strToVar ".") e) f fs) (strToVar "<$>") x) noSyntaxExpr noSyntaxExpr])) [Replace Stmt (toSSA g) (("x", toSSA x):zip vs (toSSA <$> f:fs)) (intercalate " . " (take (length fs + 1) vs) ++ " <$> x"), Delete Stmt (toSSA q)]] where isSimple (fromApps -> xs) = all isAtom (x : xs)@@ -295,14 +294,14 @@ template :: String -> LHsExpr GhcPs -> ExprLStmt GhcPs template lhs rhs = let p = noLocA $ mkRdrUnqual (mkVarOcc lhs)- grhs = noLocA (GRHS EpAnnNotUsed [] rhs)+ grhs = noLocA (GRHS noAnn [] rhs) grhss = GRHSs emptyComments [grhs] (EmptyLocalBinds noExtField)- match = noLocA $ Match EpAnnNotUsed (FunRhs p Prefix NoSrcStrict) [] grhss- fb = noLocA $ FunBind noExtField p (MG Generated (noLocA [match]))- binds = unitBag fb+ match = noLocA $ Match noExtField (FunRhs p Prefix NoSrcStrict noAnn) (noLocA []) grhss+ fb = noLocA $ FunBind noExtField p (MG (Generated OtherExpansion SkipPmc) (noLocA [match]))+ binds = [fb] valBinds = ValBinds NoAnnSortKey binds []- localBinds = HsValBinds EpAnnNotUsed valBinds- in noLocA $ LetStmt EpAnnNotUsed localBinds+ localBinds = HsValBinds noAnn valBinds+ in noLocA $ LetStmt noAnn localBinds fromApplies :: LHsExpr GhcPs -> ([LHsExpr GhcPs], LHsExpr GhcPs) fromApplies (L _ (HsApp _ f x)) = first (f:) $ fromApplies (fromParen x)@@ -310,7 +309,7 @@ fromApplies x = ([], x) fromRet :: LHsExpr GhcPs -> Maybe (String, LHsExpr GhcPs)-fromRet (L _ (HsPar _ _ x _)) = fromRet x-fromRet (L _ (OpApp _ x (L _ (HsVar _ (L _ y))) z)) | occNameStr y == "$" = fromRet $ noLocA (HsApp EpAnnNotUsed x z)+fromRet (L _ (HsPar _ x)) = fromRet x+fromRet (L _ (OpApp _ x (L _ (HsVar _ (L _ y))) z)) | occNameStr y == "$" = fromRet $ noLocA (HsApp noExtField x z) fromRet (L _ (HsApp _ x y)) | isReturn x = Just (unsafePrettyPrint x, y) fromRet _ = Nothing
src/Hint/Naming.hs view
@@ -89,7 +89,7 @@ shorten :: LHsDecl GhcPs -> LHsDecl GhcPs shorten (L locDecl (ValD ttg0 bind@(FunBind _ _ matchGroup@(MG FromSource (L locMatches matches))))) = L locDecl (ValD ttg0 bind {fun_matches = matchGroup {mg_alts = L locMatches $ map shortenMatch matches}})-shorten (L locDecl (ValD ttg0 bind@(PatBind _ _ grhss@(GRHSs _ rhss _)))) =+shorten (L locDecl (ValD ttg0 bind@(PatBind _ _ _ grhss@(GRHSs _ rhss _)))) = L locDecl (ValD ttg0 bind {pat_rhs = grhss {grhssGRHSs = map shortenLGRHS rhss}}) shorten x = x @@ -102,7 +102,7 @@ L locGRHS (GRHS ttg0 guards (L locExpr dots)) where dots :: HsExpr GhcPs- dots = HsLit EpAnnNotUsed (HsString (SourceText "...") (mkFastString "..."))+ dots = HsLit noExtField (HsString (SourceText (fsLit "...")) (fsLit "...")) getNames :: LHsDecl GhcPs -> [String] getNames decl = maybeToList (declName decl) ++ getConstructorNames (unLoc decl)
+ src/Hint/Negation.hs view
@@ -0,0 +1,62 @@+{-++Raise a warning if negation precedence may appear ambiguous to human readers.++<TEST>+yes = -1 ^ 2 -- @Suggestion -(1 ^ 2)+yes = -x ^ y -- @Suggestion -(x ^ y)+yes = -5 `plus` 3 -- @Suggestion -(5 `plus` 3)+yes = -f x `mod` y -- @Suggestion -(f x `mod` y)+yes = -x `mod` y -- @Suggestion -(x `mod` y)+no = -(5 + 3)+no = -5 + 3+no = -(f x)+no = -x+</TEST>+-}++module Hint.Negation(negationParensHint) where++import Hint.Type(DeclHint,Idea(..),rawIdea,toSSA)+import Config.Type+import Data.Generics.Uniplate.DataOnly+import Refact.Types+import GHC.Hs+import GHC.Util+import Language.Haskell.GhclibParserEx.GHC.Utils.Outputable+import GHC.Types.SrcLoc++-- | See [motivating issue #1484](https://github.com/ndmitchell/hlint/issues/1484).+--+-- == Implementation note+--+-- The original intention was to compare fixities so as+-- to only fire the rule when the operand of prefix negation+-- has higher fixity than the negation itself (fixity 6).+--+-- However, since there do not exist any numerically-valued+-- operators with lower fixity than 6+-- (see [table](https://www.haskell.org/onlinereport/decls.html#sect4.4.2)),+-- we do not have to worry about fixity comparisons.+negationParensHint :: DeclHint+negationParensHint _ _ x =+ concatMap negatedOp (universeBi x :: [LHsExpr GhcPs])++negatedOp :: LHsExpr GhcPs -> [Idea]+negatedOp e =+ case e of+ L b1 (NegApp a1 inner@(L _ OpApp {}) a2) ->+ pure $+ rawIdea+ Suggestion+ "Parenthesize unary negation"+ (locA (getLoc e))+ (unsafePrettyPrint e)+ (Just renderedNewExpr)+ []+ [Replace (findType e) (toSSA e) [] renderedNewExpr]+ where+ renderedNewExpr = unsafePrettyPrint newExpr+ parenthesizedOperand = addParen inner+ newExpr = L b1 $ NegApp a1 parenthesizedOperand a2+ _ -> []
src/Hint/NewType.hs view
@@ -151,7 +151,7 @@ isHashy x = or ["#" `isSuffixOf` unsafePrettyPrint v | v@HsTyVar{} <- universe x] warnBang :: HsType GhcPs -> Bool-warnBang (HsBangTy _ (HsSrcBang _ _ SrcStrict) _) = False+warnBang (HsBangTy _ (HsBang _ SrcStrict) _) = False warnBang _ = True emptyOrNoContext :: Maybe (LHsContext GhcPs) -> Bool
src/Hint/NumLiteral.hs view
@@ -22,6 +22,7 @@ module Hint.NumLiteral (numLiteralHint) where import GHC.Hs+import GHC.Data.FastString import GHC.LanguageExtensions.Type (Extension (..)) import GHC.Types.SrcLoc import GHC.Types.SourceText@@ -49,18 +50,18 @@ suggestUnderscore :: LHsExpr GhcPs -> [Idea] suggestUnderscore x@(L _ (HsOverLit _ ol@(OverLit _ (HsIntegral intLit@(IL (SourceText srcTxt) _ _))))) =- [ suggest "Use underscore" (reLoc x) (reLoc y) [r] | '_' `notElem` srcTxt, srcTxt /= underscoredSrcTxt ]+ [ suggest "Use underscore" (reLoc x) (reLoc y) [r] | '_' `notElem` unpackFS srcTxt, unpackFS srcTxt /= underscoredSrcTxt ] where- underscoredSrcTxt = addUnderscore srcTxt- y :: LocatedAn an (HsExpr GhcPs)- y = noLocA $ HsOverLit EpAnnNotUsed $ ol{ol_val = HsIntegral intLit{il_text = SourceText underscoredSrcTxt}}+ underscoredSrcTxt = addUnderscore (unpackFS srcTxt)+ y :: LocatedAn NoEpAnns (HsExpr GhcPs)+ y = noLocA $ HsOverLit noExtField $ ol{ol_val = HsIntegral intLit{il_text = SourceText (fsLit underscoredSrcTxt)}} r = Replace Expr (toSSA x) [("a", toSSA y)] "a" suggestUnderscore x@(L _ (HsOverLit _ ol@(OverLit _ (HsFractional fracLit@(FL (SourceText srcTxt) _ _ _ _))))) =- [ suggest "Use underscore" (reLoc x) (reLoc y) [r] | '_' `notElem` srcTxt, srcTxt /= underscoredSrcTxt ]+ [ suggest "Use underscore" (reLoc x) (reLoc y) [r] | '_' `notElem` unpackFS srcTxt, unpackFS srcTxt /= underscoredSrcTxt ] where- underscoredSrcTxt = addUnderscore srcTxt- y :: LocatedAn an (HsExpr GhcPs)- y = noLocA $ HsOverLit EpAnnNotUsed $ ol{ol_val = HsFractional fracLit{fl_text = SourceText underscoredSrcTxt}}+ underscoredSrcTxt = addUnderscore (unpackFS srcTxt)+ y :: LocatedAn NoEpAnns (HsExpr GhcPs)+ y = noLocA $ HsOverLit noExtField $ ol{ol_val = HsFractional fracLit{fl_text = SourceText (fsLit underscoredSrcTxt)}} r = Replace Expr (toSSA x) [("a", toSSA y)] "a" suggestUnderscore _ = mempty
src/Hint/Pattern.hs view
@@ -69,11 +69,10 @@ import Refact.Types hiding (RType(Pattern, Match), SrcSpan) import Refact.Types qualified as R (RType(Pattern, Match), SrcSpan) -import GHC.Hs+import GHC.Hs hiding(asPattern) import GHC.Types.SrcLoc import GHC.Types.Name.Reader import GHC.Types.Name.Occurrence-import GHC.Data.Bag import GHC.Types.Basic hiding (Pattern) import GHC.Data.Strict qualified @@ -88,7 +87,7 @@ concatMap (uncurry hints . swap) (asPattern x) ++ -- PatBind (used in 'let' and 'where') contains lazy-by-default -- patterns, everything else is strict.- concatMap (patHint strict False) [p | PatBind _ p _ <- universeBi x :: [HsBind GhcPs]] +++ concatMap (patHint strict False) [p | PatBind _ p _ _ <- universeBi x :: [HsBind GhcPs]] ++ concatMap (patHint strict True) (universeBi $ transformBi noPatBind x) ++ concatMap expHint (universeBi x) where@@ -124,7 +123,7 @@ rawGuards = asGuards bod mkGuard :: LHsExpr GhcPs -> (LHsExpr GhcPs -> GRHS GhcPs (LHsExpr GhcPs))- mkGuard a = GRHS EpAnnNotUsed [noLocA $ BodyStmt noExtField a noSyntaxExpr noSyntaxExpr]+ mkGuard a = GRHS noAnn [noLocA $ BodyStmt noExtField a noSyntaxExpr noSyntaxExpr] guards :: [LGRHS GhcPs (LHsExpr GhcPs)] guards = map (noLocA . uncurry mkGuard) rawGuards@@ -158,12 +157,12 @@ refactoring = Replace rtype (toRefactSrcSpan l) (f patSubts ++ f guardSubts ++ f exprSubts) template hints gen (Pattern l t pats o@(GRHSs _ [L _ (GRHS _ [test] bod)] bind)) | unsafePrettyPrint test `elem` ["otherwise", "True"]- = [gen "Redundant guard" (Pattern l t pats o{grhssGRHSs=[noLocA (GRHS EpAnnNotUsed [] bod)]}) [Delete Stmt (toSSA test)]]+ = [gen "Redundant guard" (Pattern l t pats o{grhssGRHSs=[noLocA (GRHS noAnn [] bod)]}) [Delete Stmt (toSSA test)]] hints _ (Pattern l t pats bod@(GRHSs _ _ binds)) | f binds = [suggestRemove "Redundant where" whereSpan "where" [ {- TODO refactoring for redundant where -} ]] where f :: HsLocalBinds GhcPs -> Bool- f (HsValBinds _ (ValBinds _ bag _)) = isEmptyBag bag+ f (HsValBinds _ (ValBinds _ l _)) = null l f (HsIPBinds _ (IPBinds _ l)) = null l f _ = False whereSpan = case l of@@ -175,11 +174,11 @@ hints gen (Pattern l t pats o@(GRHSs _ (unsnoc -> Just (gs, L _ (GRHS _ [test] bod))) binds)) | unsafePrettyPrint test == "True" = let otherwise_ = noLocA $ BodyStmt noExtField (strToVar "otherwise") noSyntaxExpr noSyntaxExpr in- [gen "Use otherwise" (Pattern l t pats o{grhssGRHSs = gs ++ [noLocA (GRHS EpAnnNotUsed [otherwise_] bod)]}) [Replace Expr (toSSA test) [] "otherwise"]]+ [gen "Use otherwise" (Pattern l t pats o{grhssGRHSs = gs ++ [noLocA (GRHS noAnn [otherwise_] bod)]}) [Replace Expr (toSSA test) [] "otherwise"]] hints _ _ = [] asGuards :: LHsExpr GhcPs -> [(LHsExpr GhcPs, LHsExpr GhcPs)]-asGuards (L _ (HsPar _ _ x _)) = asGuards x+asGuards (L _ (HsPar _ x)) = asGuards x asGuards (L _ (HsIf _ a b c)) = (a, b) : asGuards c asGuards x = [(strToVar "otherwise", x)] @@ -190,20 +189,20 @@ asPattern (L loc x) = concatMap decl (universeBi x) where decl :: HsBind GhcPs -> [(Pattern, String -> Pattern -> [Refactoring R.SrcSpan] -> Idea)]- decl o@(PatBind _ pat rhs) = [(Pattern (locA loc) Bind [pat] rhs, \msg (Pattern _ _ [pat] rhs) rs -> suggest msg (noLoc o :: Located (HsBind GhcPs)) (noLoc (PatBind EpAnnNotUsed pat rhs) :: Located (HsBind GhcPs)) rs)]+ decl o@(PatBind _ pat mult rhs) = [(Pattern (locA loc) Bind [pat] rhs, \msg (Pattern _ _ [pat] rhs) rs -> suggest msg (noLoc o :: Located (HsBind GhcPs)) (noLoc (PatBind noExtField pat mult rhs) :: Located (HsBind GhcPs)) rs)] decl (FunBind _ _ (MG _ (L _ xs))) = map match xs decl _ = [] match :: LMatch GhcPs (LHsExpr GhcPs) -> (Pattern, String -> Pattern -> [Refactoring R.SrcSpan] -> Idea)- match o@(L loc (Match _ ctx pats grhss)) = (Pattern (locA loc) R.Match pats grhss, \msg (Pattern _ _ pats grhss) rs -> suggest msg (reLoc o) (noLoc (Match EpAnnNotUsed ctx pats grhss) :: Located (Match GhcPs (LHsExpr GhcPs))) rs)+ match o@(L loc (Match _ ctx (L lpats pats) grhss)) = (Pattern (locA loc) R.Match pats grhss, \msg (Pattern _ _ pats grhss) rs -> suggest msg (reLoc o) (noLoc (Match noExtField ctx (L lpats pats) grhss) :: Located (Match GhcPs (LHsExpr GhcPs))) rs) -- First Bool is if 'Strict' is a language extension. Second Bool is -- if this pattern in this context is going to be evaluated strictly. patHint :: Bool -> Bool -> LPat GhcPs -> [Idea] patHint _ _ o@(L _ (ConPat _ name (PrefixCon _ args))) | length args >= 3 && all isPWildcard args =- let rec_fields = HsRecFields [] Nothing :: HsRecFields GhcPs (LPat GhcPs)- new = noLocA $ ConPat EpAnnNotUsed name (RecCon rec_fields) :: LPat GhcPs+ let rec_fields = HsRecFields noExtField [] Nothing :: HsRecFields GhcPs (LPat GhcPs)+ new = noLocA $ ConPat noAnn name (RecCon rec_fields) :: LPat GhcPs in [suggest "Use record patterns" (reLoc o) (reLoc new) [Replace R.Pattern (toSSA o) [] (unsafePrettyPrint new)]] patHint _ _ o@(L _ (VarPat _ (L _ name)))@@ -213,8 +212,8 @@ | strict, f x = [warn "Redundant bang pattern" (reLoc o) (noLoc x :: Located (Pat GhcPs)) [r]] where f :: Pat GhcPs -> Bool- f (ParPat _ _ (L _ x) _) = f x- f (AsPat _ _ _ (L _ x)) = f x+ f (ParPat _ (L _ x)) = f x+ f (AsPat _ _ (L _ x)) = f x f LitPat {} = True f NPat {} = True f ConPat {} = True@@ -227,23 +226,23 @@ | f x = [warn "Redundant irrefutable pattern" (reLoc o) (noLoc x :: Located (Pat GhcPs)) [r]] where f :: Pat GhcPs -> Bool- f (ParPat _ _ (L _ x) _) = f x- f (AsPat _ _ _ (L _ x)) = f x+ f (ParPat _ (L _ x)) = f x+ f (AsPat _ _ (L _ x)) = f x f WildPat{} = True f VarPat{} = True f _ = False r = Replace R.Pattern (toSSA o) [("x", toSSA pat)] "x"-patHint _ _ o@(L _ (AsPat _ v _ (L _ (WildPat _)))) =+patHint _ _ o@(L _ (AsPat _ v (L _ (WildPat _)))) = [warn "Redundant as-pattern" (reLoc o) (reLoc v) [Replace R.Pattern (toSSA o) [] (rdrNameStr v)]] patHint _ _ _ = [] expHint :: LHsExpr GhcPs -> [Idea] -- Note the 'FromSource' in these equations (don't warn on generated match groups).-expHint o@(L _ (HsCase _ _ (MG FromSource (L _ [L _ (Match _ CaseAlt [L _ (WildPat _)] (GRHSs _ [L _ (GRHS _ [] e)] (EmptyLocalBinds _))) ])))) =+expHint o@(L _ (HsCase _ _ (MG FromSource (L _ [L _ (Match _ CaseAlt (L _ [L _ (WildPat _)]) (GRHSs _ [L _ (GRHS _ [] e)] (EmptyLocalBinds _))) ])))) = [suggest "Redundant case" (reLoc o) (reLoc e) [r]] where r = Replace Expr (toSSA o) [("x", toSSA e)] "x"-expHint o@(L _ (HsCase _ (L _ (HsVar _ (L _ x))) (MG FromSource (L _ [L _ (Match _ CaseAlt [L _ (VarPat _ (L _ y))] (GRHSs _ [L _ (GRHS _ [] e)] (EmptyLocalBinds _))) ]))))+expHint o@(L _ (HsCase _ (L _ (HsVar _ (L _ x))) (MG FromSource (L _ [L _ (Match _ CaseAlt (L _ [L _ (VarPat _ (L _ y))]) (GRHSs _ [L _ (GRHS _ [] e)] (EmptyLocalBinds _))) ])))) | occNameStr x == occNameStr y = [suggest "Redundant case" (reLoc o) (reLoc e) [r]] where
src/Hint/Pragma.hs view
@@ -144,7 +144,7 @@ -- 'ls' is a list of language features enabled by this -- OPTIONS_GHC pragma that are not enabled by LANGUAGE pragmas -- in this module.- let ls = filter (not . (`elem` languagePragmas)) (concat $ catMaybes vs) in+ let ls = concatMap (filter (`notElem` languagePragmas)) $ catMaybes vs in Just (res, ls) where -- Try reinterpreting each flag as a list of language features
src/Hint/Restrict.hs view
@@ -31,6 +31,7 @@ import Data.Map qualified as Map import Data.List.Extra import Data.List.NonEmpty (nonEmpty)+import Data.Either import Data.Maybe import Data.Monoid import Data.Semigroup@@ -157,6 +158,11 @@ , not $ null bad] isGood def mp x = maybe def (within modu "" . riWithin) $ Map.lookup x mp ++-- | Extension to GHC's 'ImportDeclQualifiedStyle', expressing @qualifiedStyle: unrestricted@,+-- i.e. the preference of "either pre- or post-, but qualified" in a rule.+data QualifiedPostOrPre = QualifiedPostOrPre deriving Eq+ checkImports :: String -> [LImportDecl GhcPs] -> (Bool, Map.Map String RestrictItem) -> [Idea] checkImports modu lImportDecls (def, mp) = mapMaybe getImportHint lImportDecls where@@ -190,30 +196,37 @@ case fromMaybe ImportStyleUnrestricted $ getAlt riImportStyle of ImportStyleUnrestricted | NotQualified <- ideclQualified -> (Nothing, Nothing)- | otherwise -> (second (<> " or unqualified") <$> expectedQualStyle, Nothing)- ImportStyleQualified -> (expectedQualStyleDef, Nothing)+ | otherwise -> (Just $ second (<> " or unqualified") expectedQualStyle, Nothing)+ ImportStyleQualified -> (Just expectedQualStyle, Nothing) ImportStyleExplicitOrQualified | Just (False, _) <- first (== EverythingBut) <$> ideclImportList -> (Nothing, Nothing) | otherwise ->- ( second (<> " or with an explicit import list") <$> expectedQualStyleDef+ ( Just $ second (<> " or with an explicit import list") expectedQualStyle , Nothing ) ImportStyleExplicit | Just (False, _) <- first (== EverythingBut) <$> ideclImportList -> (Nothing, Nothing) | otherwise ->- ( Just (NotQualified, "unqualified")+ ( Just (Right NotQualified, "unqualified") , Just $ Just (Exactly, noLocA []) )- ImportStyleUnqualified -> (Just (NotQualified, "unqualified"), Nothing)- expectedQualStyleDef = expectedQualStyle <|> Just (QualifiedPre, "qualified")+ ImportStyleUnqualified -> (Just (Right NotQualified, "unqualified"), Nothing) expectedQualStyle = case fromMaybe QualifiedStyleUnrestricted $ getAlt riQualifiedStyle of- QualifiedStyleUnrestricted -> Nothing- QualifiedStylePost -> Just (QualifiedPost, "post-qualified")- QualifiedStylePre -> Just (QualifiedPre, "pre-qualified")+ QualifiedStyleUnrestricted -> (Left QualifiedPostOrPre, "qualified")+ QualifiedStylePost -> (Right QualifiedPost, "post-qualified")+ QualifiedStylePre -> (Right QualifiedPre, "pre-qualified")+ -- unless expectedQual is Nothing, it holds the Idea (hint) to ultimately emit,+ -- except in these cases when the rule's requirements are fulfilled in-source: qualIdea- | Just ideclQualified == (fst <$> expectedQual) = Nothing+ -- the rule demands a particular importStyle, and the decl obeys exactly+ | Just (Right ideclQualified) == (fst <$> expectedQual) = Nothing+ -- the rule demands a QualifiedPostOrPre import, and the decl does either+ | Just (Left QualifiedPostOrPre) == (fst <$> expectedQual)+ && ideclQualified `elem` [QualifiedPost, QualifiedPre] = Nothing+ -- otherwise, expectedQual gets converted into a warning below (or is Nothing) | otherwise = expectedQual whenJust qualIdea $ \(qual, hint) -> do- let i' = noLoc $ (unLoc i){ ideclQualified = qual+ -- convert non-Nothing qualIdea into hlint's refactoring Idea+ let i' = noLoc $ (unLoc i){ ideclQualified = fromRight QualifiedPre qual , ideclImportList = fromMaybe ideclImportList expectedHiding } msg = moduleNameString (unLoc ideclName) <> " should be imported " <> hint Left $ warn msg (reLoc i) i' []@@ -237,10 +250,10 @@ importListToIdents :: IE GhcPs -> [String] importListToIdents = catMaybes .- \case (IEVar _ n) -> [fromName n]- (IEThingAbs _ n) -> [fromName n]- (IEThingAll _ n) -> [fromName n]- (IEThingWith _ n _ ns) -> fromName n : map fromName ns+ \case (IEVar _ n _) -> [fromName n]+ (IEThingAbs _ n _) -> [fromName n]+ (IEThingAll _ n _) -> [fromName n]+ (IEThingWith _ n _ ns _) -> fromName n : map fromName ns _ -> [] where fromName :: LIEWrappedName GhcPs -> Maybe String@@ -258,7 +271,7 @@ checkFunctions :: Scope -> String -> [LHsDecl GhcPs] -> RestrictFunctions -> [Idea] checkFunctions scope modu decls (def, mp) =- [ (ideaMessage message $ ideaNoTo $ warn "Avoid restricted function" (reLocN x) (reLocN x) []){ideaDecl = [dname]}+ [ (ideaMessage message $ ideaNoTo $ warn "Avoid restricted function" (reLoc x) (reLoc x) []){ideaDecl = [dname]} | d <- decls , let dname = fromMaybe "" (declName d) , x <- universeBi d :: [LocatedN RdrName]
src/Hint/Smell.hs view
@@ -86,8 +86,8 @@ import GHC.Utils.Outputable import GHC.Types.Basic import GHC.Hs-import GHC.Data.Bag import GHC.Types.SrcLoc+import GHC.Types.Name.Reader import Language.Haskell.GhclibParserEx.GHC.Utils.Outputable smellModuleHint :: [Setting] -> ModuHint@@ -142,7 +142,7 @@ declSpans _ = [] -- The span of a guarded right hand side.-rhsSpans :: HsMatchContext GhcPs -> LGRHS GhcPs (LHsExpr GhcPs) -> [(SrcSpan, Idea)]+rhsSpans :: HsMatchContext (GenLocated SrcSpanAnnN RdrName) -> LGRHS GhcPs (LHsExpr GhcPs) -> [(SrcSpan, Idea)] rhsSpans _ (L _ (GRHS _ _ (L _ RecordCon {}))) = [] -- record constructors get a pass rhsSpans ctx (L _ r@(GRHS _ _ (L l _))) = [(locA l, rawIdea Config.Type.Warning "Long function" (locA l) (showSDocUnsafe (pprGRHS ctx r)) Nothing [] [])]@@ -150,7 +150,7 @@ -- The spans of a 'where' clause are the spans of its bindings. whereSpans :: HsLocalBinds GhcPs -> [(SrcSpan, Idea)] whereSpans (HsValBinds _ (ValBinds _ bs _)) =- concatMap (declSpans . (\(L loc bind) -> L loc (ValD noExtField bind))) (bagToList bs)+ concatMap (declSpans . (\(L loc bind) -> L loc (ValD noExtField bind))) bs whereSpans _ = [] spanLength :: SrcSpan -> Int
src/Hint/Unsafe.hs view
@@ -54,19 +54,22 @@ -- 'x' does not declare a new function. | d@(ValD _ FunBind {fun_id=L _ (Unqual x)- , fun_matches=MG{mg_ext=FromSource,mg_alts=L _ [L _ Match {m_pats=[]}]}}) <- [d]+ , fun_matches=MG{mg_ext=FromSource,mg_alts=L _ [L _ Match {m_pats=L _ []}]}}) <- [d] -- 'x' is a synonym for an application involving 'unsafePerformIO' , isUnsafeDecl d -- 'x' is not marked 'NOINLINE'. , x `notElem` noinline] where+ noInline :: FastString+ noInline = fsLit $ '{' : '-' : '#' : " NOINLINE"+ gen :: OccName -> LHsDecl GhcPs gen x = noLocA $- SigD noExtField (InlineSig EpAnnNotUsed (noLocA (mkRdrUnqual x))- (InlinePragma (SourceText "{-# NOINLINE") (NoInline (SourceText "{-# NOINLINE")) Nothing NeverActive FunLike))+ SigD noExtField (InlineSig noAnn (noLocA (mkRdrUnqual x))+ (InlinePragma (SourceText noInline) (NoInline (SourceText noInline)) Nothing NeverActive FunLike)) noinline :: [OccName] noinline = [q | L _(SigD _ (InlineSig _ (L _ (Unqual q))- (InlinePragma _ (NoInline (SourceText "{-# NOINLINE")) Nothing NeverActive FunLike))+ (InlinePragma _ (NoInline (SourceText noInline)) Nothing NeverActive FunLike)) ) <- hsmodDecls m] isUnsafeDecl :: HsDecl GhcPs -> Bool
src/Refact.hs view
@@ -10,6 +10,7 @@ import Control.Exception.Extra import Control.Monad+import Data.List.NonEmpty qualified as NE import Data.Maybe import Data.Version.Extra import GHC.LanguageExtensions.Type@@ -43,10 +44,10 @@ toSS :: GHC.Located a -> R.SrcSpan toSS = toRefactSrcSpan . GHC.getLoc -toSSA :: GHC.GenLocated (GHC.SrcSpanAnn' a) e -> R.SrcSpan+toSSA :: GHC.GenLocated (GHC.EpAnn a) e -> R.SrcSpan toSSA = toRefactSrcSpan . GHC.getLocA -toSSAnc :: GHC.GenLocated GHC.Anchor e -> R.SrcSpan+toSSAnc :: GHC.GenLocated GHC.NoCommentsLocation e -> R.SrcSpan toSSAnc = toRefactSrcSpan . getAncLoc checkRefactor :: Maybe FilePath -> IO FilePath@@ -58,7 +59,7 @@ mexc <- findExecutable excPath case mexc of Just exc -> do- ver <- readVersion . tail <$> readProcess exc ["--version"] ""+ ver <- readVersion . NE.tail . NE.fromList <$> readProcess exc ["--version"] "" pure $ if ver >= minRefactorVersion then Right exc else Left $ "Your version of refactor is too old, please install apply-refact "
src/Summary.hs view
@@ -9,6 +9,7 @@ import Data.Map qualified as Map import Control.Monad.Extra import System.FilePath+import Data.List.NonEmpty qualified as NE import Data.List.Extra import System.Directory @@ -121,7 +122,7 @@ ++ ["", "# All LHS/RHS hints"] ++ (mkLine <$> sortDedup (hintRuleName <$> sLhsRhsRules)) where- sortDedup = fmap head . group . sort+ sortDedup = fmap (NE.head . NE.fromList) . group . sort mkLine name = "- " <> show severity <> ": {name: " <> jsonToString name <> "}" genSummaryMd :: Summary -> String@@ -161,7 +162,7 @@ where row1 = row $ [ "<td>" ++ hName ++ "</td>", "<td>"]- ++ showExample (head hExamples)+ ++ showExample (NE.head (NE.fromList hExamples)) ++ ["Does not support refactoring." | not hRefactoring] ++ ["</td>"] ++ [ "<td>" ++ show hSeverity ++ "</td>"
tests/import_style.test view
@@ -66,3 +66,64 @@ No hints ---------------------------------------------------------------------+RUN tests/importStyle-postqual-pos.hs --hint=data/import_style.yaml -XImportQualifiedPost+FILE tests/importStyle-postqual-pos.hs+import HypotheticalModule1 qualified as HM1+import HypotheticalModule2 qualified+import HypotheticalModule2 qualified as Arbitrary+import HypotheticalModule3 qualified+import HypotheticalModule3 qualified as Arbitrary+import HypotheticalModule4 qualified as HM4+import HypotheticalModule5 qualified+import HypotheticalModule5 qualified as HM5+OUTPUT+No hints++---------------------------------------------------------------------+RUN tests/importStyle-postqual-neg.hs --hint=data/import_style.yaml -XImportQualifiedPost+FILE tests/importStyle-postqual-neg.hs+import HypotheticalModule1 qualified+import qualified HypotheticalModule4+import qualified HypotheticalModule4 as Verbotten+import qualified HypotheticalModule4 as HM4+import HypotheticalModule5 as HM5+import qualified HypotheticalModule5++OUTPUT+tests/importStyle-postqual-neg.hs:1:1-36: Warning: Avoid restricted alias+Found:+ import HypotheticalModule1 qualified+Perhaps:+ import HypotheticalModule1 qualified as HM1+Note: may break the code++tests/importStyle-postqual-neg.hs:2:1-36: Warning: Avoid restricted alias+Found:+ import qualified HypotheticalModule4+Perhaps:+ import qualified HypotheticalModule4 as HM4+Note: may break the code++tests/importStyle-postqual-neg.hs:3:1-49: Warning: Avoid restricted alias+Found:+ import qualified HypotheticalModule4 as Verbotten+Perhaps:+ import qualified HypotheticalModule4 as HM4+Note: may break the code++tests/importStyle-postqual-neg.hs:5:1-33: Warning: HypotheticalModule5 should be imported post-qualified+Found:+ import HypotheticalModule5 as HM5+Perhaps:+ import HypotheticalModule5 qualified as HM5+Note: may break the code++tests/importStyle-postqual-neg.hs:6:1-36: Warning: HypotheticalModule5 should be imported post-qualified+Found:+ import qualified HypotheticalModule5+Perhaps:+ import HypotheticalModule5 qualified+Note: may break the code++5 hints+---------------------------------------------------------------------