packages feed

hlint 2.0.15 → 2.1

raw patch · 13 files changed

+193/−101 lines, 13 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- Language.Haskell.HLint3: Idea :: String -> String -> Severity -> String -> SrcSpan -> String -> Maybe String -> [Note] -> [Refactoring SrcSpan] -> Idea
+ Language.Haskell.HLint3: Idea :: [String] -> [String] -> Severity -> String -> SrcSpan -> String -> Maybe String -> [Note] -> [Refactoring SrcSpan] -> Idea
- Language.Haskell.HLint3: [ideaDecl] :: Idea -> String
+ Language.Haskell.HLint3: [ideaDecl] :: Idea -> [String]
- Language.Haskell.HLint3: [ideaModule] :: Idea -> String
+ Language.Haskell.HLint3: [ideaModule] :: Idea -> [String]

Files

CHANGES.txt view
@@ -1,5 +1,17 @@-Changelog for HLint+Changelog for HLint (* = breaking change) +2.1, released 2018-02-07+*   #433, make ideas span multiple modules/declarations+    #433, allow ignoring statement-level duplication hint+    #439, add more fixities for new base operators+    #437, --json output should be finite+    #425, avoid misparsing use of Gtk2Hs `on` function+    #353, detect unused results from for/traverse/sequenceA+    #428, add a few rules for the lens package+    #429, spot restricted functions in infix operators+    #427, don't eta reduce variables in the presence of quasi-quotes+    Improve the HTML slightly+    #416, add lens package fixities 2.0.15, released 2018-01-18     #426, don't suggest removing brackets for "x . (x +? x . x)"     #426, better results with haskell-src-exts-util-0.2.2
data/hlint.yaml view
@@ -36,6 +36,13 @@     - import Monad as Control.Monad     - import Char as Data.Char +- package:+    name: lens+    modules:+    - import Control.Lens+    - import Control.Lens.Operators+    - import Control.Monad.Reader+ - group:     name: default     enabled: true@@ -592,6 +599,22 @@     - warn: {lhs: null x  , rhs: "False", side: isTuple x, name: Using null on tuple}     - warn: {lhs: length x, rhs: "1"    , side: isTuple x, name: Using length on tuple} +- group:+    name: lens+    enabled: true+    imports:+    - package base+    - package lens+    rules:+    - warn: {lhs: "(a ^. b) ^. c", rhs: "a ^. (b . c)"}+    - warn: {lhs: "(a ^. b) ^? c", rhs: "a ^? (b . c)"}+    - warn: {lhs: "fromJust (a ^? b)", rhs: "a ^?! b"}+    - warn: {lhs: "a .~ Just b", rhs: "a ?~ b"}+    - warn: {lhs: "a & (mapped %~ b)", rhs: "a <&> b"}+    - warn: {lhs: "a & ((mapped . b) %~ c)", rhs: "a <&> b %~ c"}+    - warn: {lhs: "a & (mapped .~ b)", rhs: "b <$ a"}+    - warn: {lhs: "ask <&> (^. a)", rhs: "view a"}+    - warn: {lhs: "view a <&> (^. b)", rhs: "view (a . b)"}  - group:     name: generalise@@ -778,4 +801,6 @@ # import Prelude((==)) \ # import qualified Prelude as P \ # main = P.length xs == 0 -- P.null xs+# main = hello .~ Just 12 -- hello ?~ 12+# foo = liftIO $ window `on` deleteEvent $ do a; b # </TEST>
data/report_template.html view
@@ -16,15 +16,15 @@  function deleteRules(n) {-	var css = document.styleSheets[0];-	for (var i = 0; i < n; i++)-		css.deleteRule(css.cssRules.length-1);+    var css = document.styleSheets[0];+    for (var i = 0; i < n; i++)+        css.deleteRule(css.cssRules.length-1); }  function insertRule(s) {-	var css = document.styleSheets[0];-	css.insertRule(s, css.cssRules.length);+    var css = document.styleSheets[0];+    css.insertRule(s, css.cssRules.length); }  // SHOW/HIDE LOGIC //@@ -33,28 +33,28 @@  function show(id) {-	if (id == last) return;-	if (id == "")-	{-		deleteRules(3);-		insertRule(".all {font-weight: bold;}");-	}-	else-	{-		if (last == "")-		{-			deleteRules(1);-			insertRule("#content div {display:none;}");-		}-		else-		{-			deleteRules(2);-		}-		insertRule("#content div." + id + " {display:block;}");-		insertRule("#" + id + "{font-weight:bold;}");-	}+    if (id == last) return;+    if (id == "")+    {+        deleteRules(3);+        insertRule(".all {font-weight: bold;}");+    }+    else+    {+        if (last == "")+        {+            deleteRules(1);+            insertRule("#content div {display:none;}");+        }+        else+        {+            deleteRules(2);+        }+        insertRule("#content div." + id + " {display:block;}");+        insertRule("#" + id + "{font-weight:bold;}");+    } -	last = id;+    last = id; }  </script>@@ -70,44 +70,43 @@ <style type="text/css"> /* See http://www.webreference.com/programming/css_frames/ */ body {-	margin:0;-	border:0;-	padding:0;-	height:100%;-	max-height:100%;-	font-family: sans-serif;-	font-size:76%;-	overflow: hidden;+    margin:0;+    border:0;+    padding:0;+    height:100%;+    max-height:100%;+    font-family: sans-serif;+    font-size:76%;+    overflow: hidden; }  #leftbar {-	position:absolute;-	top:0px;-	left:0px;-	width: 215px;-	bottom: 0px;-	overflow:auto;-	background:rgb(202,223,255);-	margin: 10px;-	padding-top: 0;-	padding-left: 7px;-	padding-right: 7px;-	-moz-border-radius: 5px;-	-webkit-border-radius: 5px;+    position:absolute;+    top:0px;+    left:0px;+    width: 215px;+    bottom: 0px;+    overflow:auto;+    background:rgb(202,223,255);+    margin: 10px;+    padding-top: 0;+    padding-left: 7px;+    padding-right: 7px;+    border-radius: 5px; -	display:none; /* Override if script present */+    display:none; /* Override if script present */ }  #content {-	position:absolute;-	top:0;-	bottom:0;-	right:0;-	overflow:auto;-	padding-bottom: 15px;-	padding-right: 7px;+    position:absolute;+    top:0;+    bottom:0;+    right:0;+    overflow:auto;+    padding-bottom: 15px;+    padding-right: 7px; -	left:10px; /* Override if script present */+    left:10px; /* Override if script present */ }  #leftbar ul {margin-top: 0px; padding-left: 15px;}@@ -115,16 +114,16 @@ .note {color: gray; font-size: smaller;}  pre {-	font-family: "lucida console", monospace;-	padding-left: 15px;-	margin: 2px;+    font-family: "lucida console", monospace;+    padding-left: 15px;+    margin: 2px; }  #content div {-	margin-bottom: 10px;-	margin-right: 10px;-	padding-top: 4px;-	border-top: 1px solid #ccc;+    margin-bottom: 10px;+    margin-right: 10px;+    padding-top: 4px;+    border-top: 1px solid #ccc; }  .script #content {left:250px;}@@ -158,9 +157,9 @@ </div> <div id="content" valign="top" width="100%"> <p>-	Report generated by <a href="http://community.haskell.org/~ndm/hlint/">HLint</a>+    Report generated by <a href="http://community.haskell.org/~ndm/hlint/">HLint</a> $VERSION-	- a tool to suggest improvements to your Haskell code.+    - a tool to suggest improvements to your Haskell code. </p>  $CONTENT
hlint.cabal view
@@ -1,7 +1,7 @@ cabal-version:      >= 1.18 build-type:         Simple name:               hlint-version:            2.0.15+version:            2.1 license:            BSD3 license-file:       LICENSE category:           Development@@ -27,7 +27,7 @@ extra-doc-files:     README.md     CHANGES.txt-tested-with:        GHC==8.2.1, GHC==8.0.2, GHC==7.10.3, GHC==7.8.4, GHC==7.6.3, GHC==7.4.2+tested-with:        GHC==8.2.2, GHC==8.0.2, GHC==7.10.3, GHC==7.8.4, GHC==7.6.3, GHC==7.4.2  source-repository head     type:     git
src/Apply.hs view
@@ -45,15 +45,16 @@ applyHintsReal :: [Setting] -> Hint -> [(Module_, [Comment])] -> [Idea] applyHintsReal settings hints_ ms = concat $     [ map (classify $ cls ++ mapMaybe readPragma (universeBi m)) $-        order "" (hintModule hints settings nm m) `merge`-        concat [order (fromNamed d) $ decHints d | d <- moduleDecls m] `merge`-        concat [order "" $ hintComment hints settings c | c <- cs]+        order [] (hintModule hints settings nm m) `merge`+        concat [order [fromNamed d] $ decHints d | d <- moduleDecls m] `merge`+        concat [order [] $ hintComment hints settings c | c <- cs]     | (nm,(m,cs)) <- mns     , let decHints = hintDecl hints settings nm m -- partially apply-    , let order n = map (\i -> i{ideaModule=moduleName m, ideaDecl=n}) . sortBy (comparing ideaSpan)+    , let order n = map (\i -> i{ideaModule= f $ moduleName m : ideaModule i, ideaDecl= f $ n ++ ideaDecl i}) . sortBy (comparing ideaSpan)     , let merge = mergeBy (comparing ideaSpan)] ++     [map (classify cls) (hintModules hints settings $ map (second fst) mns)]     where+        f = nubOrd . filter (/= "")         cls = [x | SettingClassify x <- settings]         mns = map (scopeCreate . fst &&& id) ms         hints = (if length ms <= 1 then noModules else id) hints_@@ -88,6 +89,6 @@     where         -- figure out if we need to change the severity         f :: Idea -> Severity -> Classify -> Severity-        f i r c | classifyHint c ~= ideaHint i && classifyModule c ~= ideaModule i && classifyDecl c ~= ideaDecl i = classifySeverity c+        f i r c | classifyHint c ~= [ideaHint i] && classifyModule c ~= ideaModule i && classifyDecl c ~= ideaDecl i = classifySeverity c                 | otherwise = r-        x ~= y = null x || x == y+        x ~= y = null x || x `elem` y
src/HSE/All.hs view
@@ -48,10 +48,55 @@     ,hseFlags :: ParseMode -- ^ How the file is parsed (defaults to all fixities in the @base@ package and most non-conflicting extensions).     } +lensFixities :: [Fixity]+lensFixities = concat+    -- List as provided at https://github.com/ndmitchell/hlint/issues/416+    [infixr_ 4 ["%%@~","<%@~","%%~","<+~","<*~","<-~","<//~","<^~","<^^~","<**~"]+    ,infix_ 4 ["%%@=","<%@=","%%=","<+=","<*=","<-=","<//=","<^=","<^^=","<**="]+    ,infixr_ 2 ["<<~"]+    ,infixr_ 9 ["#."]+    ,infixl_ 8 [".#"]+    ,infixr_ 8 ["^!","^@!"]+    ,infixl_ 1 ["&","<&>","??"]+    ,infixl_ 8 ["^.","^@."]+    ,infixr_ 9 ["<.>","<.",".>"]+    ,infixr_ 4 ["%@~",".~","+~","*~","-~","//~","^~","^^~","**~","&&~","<>~","||~","%~"]+    ,infix_ 4 ["%@=",".=","+=","*=","-=","//=","^=","^^=","**=","&&=","<>=","||=","%="]+    ,infixr_ 2 ["<~"]+    ,infixr_ 2 ["`zoom`","`magnify`"]+    ,infixl_ 8 ["^..","^?","^?!","^@..","^@?","^@?!"]+    ,infixl_ 8 ["^#"]+    ,infixr_ 4 ["<#~","#~","#%~","<#%~","#%%~"]+    ,infix_ 4 ["<#=","#=","#%=","<#%=","#%%="]+    ,infixl_ 9 [":>"]+    ,infixr_ 4 ["</>~","<</>~","<.>~","<<.>~"]+    ,infix_ 4 ["</>=","<</>=","<.>=","<<.>="]+    ,infixr_ 4 [".|.~",".&.~","<.|.~","<.&.~"]+    ,infix_ 4 [".|.=",".&.=","<.|.=","<.&.="]+    ]++-- Fixites from the `base` package which are currently+-- missing from `haskell-src-exts`'s baseFixities.+-- see https://github.com/haskell-suite/haskell-src-exts/pull/400+baseNotYetInHSE :: [Fixity]+baseNotYetInHSE = concat+    [infixr_ 9 ["`Compose`"]+    ,infixr_ 6 ["<>"]+    ,infixr_ 5 ["<|"]+    ,infixl_ 4 ["<$!>","<$","$>"]+    ,infix_ 4 [":~:", ":~~:"]+    ]++customFixities :: [Fixity]+customFixities =+    infixl_ 1 ["`on`"]+        -- see https://github.com/ndmitchell/hlint/issues/425+        -- otherwise GTK apps using `on` at a different fixity have spurious warnings+ -- | Default value for 'ParseFlags'. defaultParseFlags :: ParseFlags defaultParseFlags = ParseFlags NoCpp-    defaultParseMode{fixities=Just baseFixities, ignoreLinePragmas=False, ignoreFunctionArity=True, extensions=defaultExtensions}+    defaultParseMode{fixities=Just $ customFixities ++ baseFixities ++ baseNotYetInHSE ++ lensFixities, ignoreLinePragmas=False, ignoreFunctionArity=True, extensions=defaultExtensions}  parseFlagsNoLocations :: ParseFlags -> ParseFlags parseFlagsNoLocations x = x{cppFlags = case cppFlags x of Cpphs y -> Cpphs $ f y; y -> y}
src/Hint/All.hs view
@@ -52,7 +52,7 @@     HintExport     -> modu exportHint     HintPragma     -> modu pragmaHint     HintExtensions -> modu extensionsHint-    HintUnsafe     -> modu unsafeHint+    HintUnsafe     -> decl unsafeHint     HintDuplicate  -> mods duplicateHint     HintComment    -> comm commentHint     HintNewType    -> decl newtypeHint
src/Hint/Duplicate.hs view
@@ -12,6 +12,7 @@ main = do a; a; a; b; a; a; a -- ??? main = do a; a; a; b; a; a foo = a where {a = 1; b = 2; c = 3}; bar = a where {a = 1; b = 2; c = 3} -- ???+{-# ANN main "HLint: ignore Reduce duplication" #-}; main = do a; a; a; a; a; a -- @Ignore ??? </TEST> -} @@ -19,6 +20,7 @@ module Hint.Duplicate(duplicateHint) where  import Hint.Type+import Data.Default import Data.Tuple.Extra import Data.List hiding (find) import qualified Data.Map as Map@@ -26,18 +28,22 @@  duplicateHint :: CrossHint duplicateHint ms =-    dupes [y | Do _ y :: Exp S <- universeBi modu] ++-    dupes [y | BDecls l y :: Binds S <- universeBi modu]-    where modu = map snd ms+    dupes [(m,d,y) | (m,d,x) <- ds, Do _ y :: Exp S <- universeBi x] +++    dupes [(m,d,y) | (m,d,x) <- ds, BDecls _ y :: Binds S <- universeBi x]+    where ds = [(moduleName m, fromNamed d, d) | m <- map snd ms, d <- moduleDecls m]  +dupes :: (Pretty (f SrcSpan), Annotated f, Ord (f ())) => [(String, String, [f S])] -> [Idea] dupes ys =-    [rawIdeaN+    [(rawIdeaN         (if length xs >= 5 then Warning else Suggestion)         "Reduce duplication" p1         (unlines $ map (prettyPrint . fmap (const p1)) xs)-        (Just $ "Combine with " ++ showSrcLoc (getPointLoc p2)) []-    | (p1,p2,xs) <- duplicateOrdered 3 $ map (map (srcInfoSpan . ann &&& dropAnn)) ys]+        (Just $ "Combine with " ++ showSrcLoc (getPointLoc p2)) [])+      {ideaModule = [m1,m2], ideaDecl = [d1,d2]}+    | ((m1,d1,p1),(m2,d2,p2),xs) <- duplicateOrdered 3 $ map f ys]+    where+        f (m,d,xs) = [((m,d,srcInfoSpan $ ann x), dropAnn x) | x <- xs]   ---------------------------------------------------------------------@@ -59,7 +65,7 @@     where f new = add pos vs  -duplicateOrdered :: Ord val => Int -> [[(SrcSpan,val)]] -> [(SrcSpan,SrcSpan,[val])]+duplicateOrdered :: (Ord pos, Default pos, Ord val) => Int -> [[(pos,val)]] -> [(pos,pos,[val])] duplicateOrdered threshold xs = concat $ concat $ snd $ mapAccumL f (Dupe def Map.empty) xs     where         f d xs = second overlaps $ mapAccumL (g pos) d $ takeWhile ((>= threshold) . length) $ tails xs
src/Hint/Lambda.hs view
@@ -68,6 +68,8 @@ baz = bar (\x -> (x +)) -- (+) yes = blah (\ x -> case x of A -> a; B -> b) -- \ case A -> a; B -> b no = blah (\ x -> case x of A -> a x; B -> b x)+{-# LANGUAGE QuasiQuotes #-}; authOAuth2 name = authOAuth2Widget [whamlet|Login via #{name}|] name+{-# LANGUAGE QuasiQuotes #-}; authOAuth2 = foo (\name -> authOAuth2Widget [whamlet|Login via #{name}|] name) </TEST> -} @@ -118,6 +120,7 @@ etaReduce :: [Pat_] -> Exp_ -> ([Pat_], Exp_) etaReduce ps (App _ x (Var _ (UnQual _ (Ident _ y))))     | ps /= [], PVar _ (Ident _ p) <- last ps, p == y, p /= "mr", y `notElem` vars x+    , not $ any isQuasiQuote $ universe x     = etaReduce (init ps) x etaReduce ps (InfixApp a x (isDol -> True) y) = etaReduce ps (App a x y) etaReduce ps x = (ps,x)@@ -133,7 +136,7 @@ --      subts = [("a", toSS y), ("*", toSS v)] lambdaExp p o@(Paren _ (App _ (App _ (view -> Var_ "flip") (Var _ x)) y)) | allowRightSection $ fromNamed x =     [suggestN "Use section" o $ RightSection an (QVarOp an x) y]-lambdaExp p o@Lambda{} | maybe True (not . isInfixApp) p, (res, refact) <- niceLambdaR [] o, not $ isLambda res =+lambdaExp p o@Lambda{} | maybe True (not . isInfixApp) p, (res, refact) <- niceLambdaR [] o, not $ isLambda res, not $ any isQuasiQuote $ universe res =     [(if isVar res || isCon res then warn else suggest) "Avoid lambda" o res (refact $ toSS o)] lambdaExp p o@(Lambda _ pats x) | isLambda (fromParen x), null (universeBi pats :: [Exp_]), maybe True (not . isLambda) p =     [suggest "Collapse lambdas" o (Lambda an pats body) [Replace Expr (toSS o) subts template]]
src/Hint/Monad.hs view
@@ -57,7 +57,7 @@ import Prelude  -badFuncs = ["mapM","foldM","forM","replicateM","sequence","zipWithM"]+badFuncs = ["mapM","foldM","forM","replicateM","sequence","zipWithM","traverse","for","sequenceA"]   monadHint :: DeclHint@@ -109,7 +109,7 @@                                       in go -> (ret:f:fs, view -> Var_ v))):g@(Generator _ (view -> PVar_ u) x):rest)     | ret ~= "return", notDol x, u == v, null rest, v `notElem` vars (f:fs)     = Just (reverse (Qualifier an (InfixApp an (foldl' (flip (InfixApp an) (toNamed ".")) f fs) (toNamed "<$>") x):rest),-            [Replace Stmt (toSS g) (("x", toSS x):zip vs (toSS <$> f:fs)) (intercalate " . " vs ++ " <$> x"), Delete Stmt (toSS q)])+            [Replace Stmt (toSS g) (("x", toSS x):zip vs (toSS <$> f:fs)) (intercalate " . " (take (length fs + 1) vs) ++ " <$> x"), Delete Stmt (toSS q)])   where vs = ('f':) . show <$> [0..]         notDol (InfixApp _ _ op _) = not $ isDol op         notDol _ = True
src/Hint/Restrict.hs view
@@ -6,6 +6,7 @@ -- These tests rely on the .hlint.yaml file in the root <TEST> foo = unsafePerformIO --+foo = bar `unsafePerformIO` baz -- module Util where otherFunc = unsafePerformIO $ print 1 -- module Util where exitMessageImpure = unsafePerformIO $ print 1 foo = unsafePerformOI@@ -93,9 +94,9 @@  checkFunctions :: String -> [Decl_] -> (Bool, Map.Map String RestrictItem) -> [Idea] checkFunctions modu decls (def, mp) =-    [ ideaMayBreak $ ideaNoTo $ warn "Avoid restricted function" x x []+    [ (ideaMayBreak $ ideaNoTo $ warn "Avoid restricted function" x x []){ideaDecl = [dname]}     | d <- decls     , let dname = fromNamed d-    , x@Var{} <- universeBi d+    , x <- universeBi d :: [QName S]     , not $ maybe def (within modu dname) $ Map.lookup (fromNamed x) mp     ]
src/Hint/Unsafe.hs view
@@ -23,13 +23,13 @@ import Refact.Types  -unsafeHint :: ModuHint-unsafeHint _ m =+unsafeHint :: DeclHint+unsafeHint _ m = \d ->         [ rawIdea Warning "Missing NOINLINE pragma" (srcInfoSpan $ ann d)             (prettyPrint d)             (Just $ dropWhile isSpace (prettyPrint $ gen x) ++ "\n" ++ prettyPrint d)             [] [InsertComment (toSS d) (prettyPrint $ gen x)]-        | d@(PatBind _ (PVar _ x) _ _) <- moduleDecls m+        | d@(PatBind _ (PVar _ x) _ _) <- [d]         , isUnsafeDecl d, x `notElem_` noinline]     where         gen x = InlineSig an False Nothing $ UnQual an x
src/Idea.hs view
@@ -23,8 +23,8 @@  -- | An idea suggest by a 'Hint'. data Idea = Idea-    {ideaModule :: String -- ^ The module the idea applies to, may be @\"\"@ if the module cannot be determined or is a result of cross-module hints.-    ,ideaDecl :: String -- ^ The declaration the idea applies to, typically the function name, but may be a type name.+    {ideaModule :: [String] -- ^ The modules the idea is for, usually a singleton.+    ,ideaDecl :: [String] -- ^ The declarations the idea is for, usually a singleton, typically the function name, but may be a type name.     ,ideaSeverity :: Severity -- ^ The severity of the idea, e.g. 'Warning'.     ,ideaHint :: String -- ^ The name of the hint that generated the idea, e.g. @\"Use reverse\"@.     ,ideaSpan :: SrcSpan -- ^ The source code the idea relates to.@@ -39,9 +39,9 @@ -- 1) Aeson doesn't esape unicode characters, and I want to (allows me to ignore encoding) -- 2) I want to control the format so it's slightly human readable as well showIdeaJson :: Idea -> String-showIdeaJson idea@Idea{ideaSpan=srcSpan@SrcSpan{..}, ..} = wrap . intercalate "," . map mkPair $-    [("module", str ideaModule)-    ,("decl", str ideaDecl)+showIdeaJson idea@Idea{ideaSpan=srcSpan@SrcSpan{..}, ..} = dict+    [("module", list $ map str ideaModule)+    ,("decl", list $ map str ideaDecl)     ,("severity", str $ show ideaSeverity)     ,("hint", str ideaHint)     ,("file", str srcSpanFilename)@@ -51,7 +51,7 @@     ,("endColumn", show srcSpanEndColumn)     ,("from", str ideaFrom)     ,("to", maybe "null" str ideaTo)-    ,("note", "[" ++ intercalate "," (map (str . show) ideaNote) ++ "]")+    ,("note", list (map (str . show) ideaNote))     ,("refactorings", str $ show ideaRefactoring)     ]   where@@ -62,8 +62,8 @@               f '\r' = "\\r"               f x | isControl x || not (isAscii x) = "\\u" ++ takeEnd 4 ("0000" ++ showHex (ord x) "")               f x = [x]-    mkPair (k, v) = show k ++ ":" ++ v-    wrap x = "{" ++ x ++ "}"+    dict xs = "{" ++ intercalate "," [show k ++ ":" ++ v | (k,v) <- xs] ++ "}"+    list xs = "[" ++ intercalate "," xs ++ "]"  showIdeasJson :: [Idea] -> String showIdeasJson ideas = "[" ++ intercalate "\n," (map showIdeaJson ideas) ++ "]"@@ -87,8 +87,8 @@             where xs = lines $ tt x  -rawIdea = Idea "" ""-rawIdeaN a b c d e f = Idea "" "" a b c d e f []+rawIdea = Idea [] []+rawIdeaN a b c d e f = Idea [] [] a b c d e f []  idea severity hint from to = rawIdea severity hint (srcInfoSpan $ ann from) (f from) (Just $ f to) []     where f = trimStart . prettyPrint