Skip to content

Commit 51a526b

Browse files
committed
#978, do is not redundant with non-decreasing indentation
1 parent 7c38b9c commit 51a526b

File tree

2 files changed

+35
-4
lines changed

2 files changed

+35
-4
lines changed

CHANGES.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
Changelog for HLint (* = breaking change)
22

3+
#978, do is not redundant with non-decreasing indentation
34
#969, wrong redundant bracket suggestion with BlockArguments
45
#970, detect redundant sections, (a +) b ==> a + b
56
* #974, split ParseFlags.extensions into enabled/disabled

src/Hint/Monad.hs

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@ main = do _ <- forM_ f xs; bar -- forM_ f xs
5050
main = do bar; forM_ f xs; return () -- do bar; forM_ f xs
5151
main = do a; when b c; return () -- do a; when b c
5252
bar = 1 * do {\x -> x+x} + y
53+
issue978 = do \
54+
print "x" \
55+
if False then main else do \
56+
return ()
5357
</TEST>
5458
-}
5559

@@ -70,22 +74,37 @@ import Language.Haskell.GhclibParserEx.GHC.Hs.Expr
7074
import Language.Haskell.GhclibParserEx.GHC.Utils.Outputable
7175
import GHC.Util
7276

77+
import Data.Generics.Uniplate.Data
7378
import Data.Tuple.Extra
7479
import Data.Maybe
7580
import Data.List.Extra
7681
import Refact.Types hiding (Match)
7782
import qualified Refact.Types as R
7883

84+
7985
badFuncs :: [String]
8086
badFuncs = ["mapM","foldM","forM","replicateM","sequence","zipWithM","traverse","for","sequenceA"]
8187
unitFuncs :: [String]
8288
unitFuncs = ["when","unless","void"]
8389

8490
monadHint :: DeclHint'
85-
monadHint _ _ d = concatMap (monadExp d) $ universeParentExp' d
91+
monadHint _ _ d = concatMap (f Nothing Nothing) $ childrenBi d
92+
where
93+
decl = declName d
94+
f parentDo parentExpr x =
95+
monadExp decl parentDo parentExpr x ++
96+
concat [f (if isHsDo x then Just x else parentDo) (Just (i, x)) c | (i, c) <- zipFrom 0 $ children x]
97+
98+
isHsDo (L _ HsDo{}) = True
99+
isHsDo _ = False
100+
86101

87-
monadExp :: LHsDecl GhcPs -> (Maybe (Int, LHsExpr GhcPs), LHsExpr GhcPs) -> [Idea]
88-
monadExp (declName -> decl) (parent, x) =
102+
-- | Call with the name of the declaration,
103+
-- the nearest enclosing `do` expression
104+
-- the nearest enclosing expression
105+
-- the expression of interest
106+
monadExp :: Maybe String -> Maybe (LHsExpr GhcPs) -> Maybe (Int, LHsExpr GhcPs) -> LHsExpr GhcPs -> [Idea]
107+
monadExp decl parentDo parentExpr x =
89108
case x of
90109
(view' -> App2' op x1 x2) | isTag ">>" op -> f x1
91110
(view' -> App2' op x1 (view' -> LamConst1' _)) | isTag ">>=" op -> f x1
@@ -94,7 +113,9 @@ monadExp (declName -> decl) (parent, x) =
94113
(L loc (HsDo _ ctx (L loc2 [L loc3 (BodyStmt _ y _ _ )]))) ->
95114
let doOrMDo = case ctx of MDoExpr -> "mdo"; _ -> "do"
96115
in [ warnRemove ("Redundant " ++ doOrMDo) (doSpan doOrMDo loc) doOrMDo [Replace Expr (toSS' x) [("y", toSS' y)] "y"]
97-
| not $ doAsBrackets parent y ]
116+
| not $ doAsBrackets parentExpr y
117+
, not $ doAsAvoidingIndentation parentDo x
118+
]
98119
(L loc (HsDo _ DoExpr (L _ xs))) ->
99120
monadSteps (cL loc . HsDo noExtField DoExpr . noLoc) xs ++
100121
[suggest' "Use let" from to [r] | (from, to, r) <- monadLet xs] ++
@@ -121,6 +142,15 @@ doAsBrackets (Just (i, o)) x = needBracket' i o x
121142
doAsBrackets Nothing x = False
122143

123144

145+
-- Sometimes people write do, to avoid identation, see
146+
-- https://github.com/ndmitchell/hlint/issues/978
147+
-- Return True if they are using do as avoiding identation
148+
doAsAvoidingIndentation :: Maybe (LHsExpr GhcPs) -> LHsExpr GhcPs -> Bool
149+
doAsAvoidingIndentation (Just (L _ (HsDo _ _ (L (RealSrcSpan a) _)))) (L _ (HsDo _ _ (L (RealSrcSpan b) _)))
150+
= srcSpanStartCol a == srcSpanStartCol b
151+
doAsAvoidingIndentation parent self = False
152+
153+
124154
returnsUnit :: LHsExpr GhcPs -> Bool
125155
returnsUnit (L _ (HsPar _ x)) = returnsUnit x
126156
returnsUnit (L _ (HsApp _ x _)) = returnsUnit x

0 commit comments

Comments
 (0)