hlint 1.6.5 → 1.6.6
raw patch · 26 files changed
+309/−58 lines, 26 filesdep +cpphsdep −paralleldep ~haskell-src-extsdep ~hscolour
Dependencies added: cpphs
Dependencies removed: parallel
Dependency ranges changed: haskell-src-exts, hscolour
Files
- data/Default.hs +7/−0
- hlint.cabal +6/−3
- hlint.htm +12/−0
- src/CmdLine.hs +13/−0
- src/HSE/All.hs +17/−11
- src/HSE/Bracket.hs +1/−1
- src/HSE/Match.hs +1/−1
- src/HSE/Operators.hs +0/−1
- src/HSE/Util.hs +16/−2
- src/Hint/All.hs +17/−11
- src/Hint/Bracket.hs +1/−3
- src/Hint/Extensions.hs +61/−0
- src/Hint/Import.hs +71/−0
- src/Hint/Lambda.hs +1/−1
- src/Hint/List.hs +1/−1
- src/Hint/ListRec.hs +1/−1
- src/Hint/Match.hs +1/−1
- src/Hint/Monad.hs +1/−1
- src/Hint/Naming.hs +1/−3
- src/Hint/Pragma.hs +60/−0
- src/Hint/Structure.hs +2/−2
- src/Main.hs +2/−1
- src/Report.hs +1/−1
- src/Settings.hs +1/−1
- src/Test.hs +2/−2
- src/Type.hs +12/−10
data/Default.hs view
@@ -98,18 +98,25 @@ warn = (\(x,y) -> (f x,y)) ==> first f where _ = notIn [x,y] f warn = (\(x,y) -> (x,f y)) ==> second f where _ = notIn [x,y] f +-- FUNCTOR++error "Functor law" = fmap f (fmap g x) ==> fmap (f . g) x+error "Functor law" = fmap id ==> id+ -- MONAD error "Monad law, left identity" = return a >>= f ==> f a error "Monad law, right identity" = m >>= return ==> m warn = m >>= return . f ==> liftM f m error = (if x then y else return ()) ==> when x $ _noParen_ y+error = (if x then return () else y) ==> unless x $ _noParen_ y error = sequence (map f x) ==> mapM f x error = sequence_ (map f x) ==> mapM_ f x warn = flip mapM ==> forM warn = flip mapM_ ==> forM_ error = when (not x) ==> unless x error = x >>= id ==> join x+error = liftM f (liftM g x) ==> liftM (f . g) x -- MONAD LIST
hlint.cabal view
@@ -1,7 +1,7 @@ cabal-version: >= 1.6 build-type: Simple name: hlint-version: 1.6.5+version: 1.6.6 license: GPL license-file: LICENSE category: Development@@ -29,8 +29,8 @@ executable hlint build-depends:- base == 4.*, syb, filepath, directory, mtl, containers, hscolour >= 1.10,- haskell-src-exts >= 1 && < 1.1, uniplate == 1.2.* && >= 1.2.0.2, parallel+ base == 4.*, syb, filepath, directory, mtl, containers, hscolour >= 1.15, cpphs >= 1.7,+ haskell-src-exts == 1.1.*, uniplate == 1.2.* && >= 1.2.0.2 ghc-options: -fno-warn-overlapping-patterns -threaded @@ -57,10 +57,13 @@ HSE.NameMatch Hint.All Hint.Bracket+ Hint.Extensions+ Hint.Import Hint.Lambda Hint.List Hint.ListRec Hint.Match Hint.Monad Hint.Naming+ Hint.Pragma Hint.Structure
hlint.htm view
@@ -86,6 +86,7 @@ <ul> <li>The presence of <tt>seq</tt> may cause some hints (i.e. eta-reduction) to change the semantics of the program.</li> <li>The monomorphism restriction or uses of rank-2 types may sometimes cause transformed programs to become ill-typed.</li>+ <li>Files using <tt>#include</tt> may have incorrect line numbering.</li> </ul> <h2>Installing and running HLint</h2>@@ -151,6 +152,17 @@ <p> To run HLint on <i>n</i> processors append the flags <tt>+RTS -N<i>n</i></tt>, as described in the <a href="http://www.haskell.org/ghc/docs/latest/html/users_guide/runtime-control.html">GHC user manual</a>. HLint will usually perform fastest if <i>n</i> is equal to the number of physical processors. </p>++<h3>C preprocesor support</h3>++<p>+ HLint always runs the <a href="http://hackage.haskell.org/package/cpphs">cpphs C preprocessor</a> over all input files, by default using the current directory as the include path with no defined macros. These settings can be modified using the flags <tt>--cpp-include</tt> and <tt>--cpp-define</tt>. There are a number of limitations to the C preprocessor support:+</p>+<ul>+ <li>HLint will only check one branch of an <tt>#if</tt>, based on which macros have been defined.</li>+ <li>Any line numbers after a <tt>#include</tt> directive may be wrong.</li>+ <li>Any missing <tt>#include</tt> files will produce a warning on the console, but no information in the reports.</li>+</ul> <h2>FAQ</h2>
src/CmdLine.hs view
@@ -9,6 +9,7 @@ import System.Environment import System.Exit import System.FilePath+import Language.Preprocessor.Cpphs import Util import Paths_hlint@@ -23,6 +24,7 @@ ,cmdIgnore :: [String] -- ^ the hints to ignore ,cmdShowAll :: Bool -- ^ display all skipped items ,cmdColor :: Bool -- ^ color the result+ ,cmdCpphs :: CpphsOptions -- ^ options for cpphs } @@ -31,6 +33,8 @@ | Report FilePath | Skip String | ShowAll | Color+ | Define String+ | Include String deriving Eq @@ -42,6 +46,8 @@ ,Option "i" ["ignore"] (ReqArg Skip "message") "Ignore a particular hint" ,Option "s" ["show"] (NoArg ShowAll) "Show all ignored ideas" ,Option "t" ["test"] (NoArg Test) "Run in test mode"+ ,Option "" ["cpp-define"] (ReqArg Define "name[=value]") "CPP #define"+ ,Option "" ["cpp-include"] (ReqArg Include "dir") "CPP include path" ] @@ -67,6 +73,12 @@ let hintFiles = [x | Hints x <- opt] hints <- mapM getHintFile $ hintFiles ++ ["HLint" | null hintFiles] + let cpphs = defaultCpphsOptions+ {boolopts=defaultBoolOptions{locations=False}+ ,includes = [x | Include x <- opt]+ ,defines = [(a,drop 1 b) | Define x <- opt, let (a,b) = break (== '=') x]+ }+ return Cmd {cmdTest = test ,cmdFiles = files@@ -75,6 +87,7 @@ ,cmdIgnore = [x | Skip x <- opt] ,cmdShowAll = ShowAll `elem` opt ,cmdColor = Color `elem` opt+ ,cmdCpphs = cpphs }
src/HSE/All.hs view
@@ -5,7 +5,7 @@ module HSE.Bracket, module HSE.Match, module HSE.Generics, module HSE.NameMatch,- parseFile, parseString, fromParseResult+ ParseFlags(..), parseFlags, parseFile, parseString, fromParseResult ) where import Language.Haskell.Exts hiding (parse, parseFile, paren, fromParseResult)@@ -20,27 +20,34 @@ import Util import Data.Char import Data.List+import Language.Preprocessor.Cpphs +data ParseFlags = ParseFlags+ {cpphs :: Maybe CpphsOptions+ ,implies :: Bool+ }++parseFlags :: ParseFlags+parseFlags = ParseFlags Nothing False++ -- | Parse a Haskell module-parseString :: Bool -> FilePath -> String -> ParseResult Module-parseString implies file = parseFileContentsWithMode mode . unlines . map f . lines+parseString :: ParseFlags -> FilePath -> String -> ParseResult Module+parseString flags file = parseFileContentsWithMode mode . maybe id (`runCpphs` file) (cpphs flags) where- f x | "#" `isPrefixOf` dropWhile isSpace x = ""- | otherwise = x- mode = defaultParseMode {parseFilename = file ,extensions = extension- ,fixities = concat [infix_ (-1) ["==>"] | implies] ++ baseFixities+ ,fixities = concat [infix_ (-1) ["==>"] | implies flags] ++ baseFixities } -- | On failure returns an empty module and prints to the console-parseFile :: Bool -> FilePath -> IO (ParseResult Module)-parseFile implies file = do+parseFile :: ParseFlags -> FilePath -> IO (ParseResult Module)+parseFile flags file = do src <- readFile file- return $ parseString implies file src+ return $ parseString flags file src -- | TODO: Use the fromParseResult in HSE once it gives source location@@ -67,4 +74,3 @@ -- NOT: TransformListComp - steals the group keyword -- NOT: XmlSyntax, RegularPatterns - steals a-b ]-
src/HSE/Bracket.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE PatternGuards, ViewPatterns, MultiParamTypeClasses #-}+{-# LANGUAGE PatternGuards #-} module HSE.Bracket where
src/HSE/Match.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE PatternGuards, ViewPatterns, MultiParamTypeClasses #-}+{-# LANGUAGE ViewPatterns, MultiParamTypeClasses #-} module HSE.Match where
src/HSE/Operators.hs view
@@ -1,4 +1,3 @@-{-# LANGUAGE PatternGuards, ViewPatterns, MultiParamTypeClasses, FlexibleContexts #-} module HSE.Operators( FixityDecl(..), preludeFixities, baseFixities,
src/HSE/Util.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE PatternGuards, ViewPatterns, MultiParamTypeClasses #-}+{-# LANGUAGE PatternGuards #-} module HSE.Util where @@ -27,6 +27,9 @@ moduleImports :: Module -> [ImportDecl] moduleImports (Module _ _ _ _ _ x _) = x +modulePragmas :: Module -> [OptionPragma]+modulePragmas (Module _ _ x _ _ _ _) = x+ isChar :: Exp -> Bool isChar (Lit (Char _)) = True isChar _ = False@@ -54,7 +57,18 @@ isInfixApp InfixApp{} = True; isInfixApp _ = False isAnyApp x = isApp x || isInfixApp x isParen Paren{} = True; isParen _ = False-+isMDo MDo{} = True; isMDo _ = False+isBoxed Boxed{} = True; isBoxed _ = False+isDerivDecl DerivDecl{} = True; isDerivDecl _ = False+isFunDep FunDep{} = True; isFunDep _ = False+isPBangPat PBangPat{} = True; isPBangPat _ = False+isPExplTypeArg PExplTypeArg{} = True; isPExplTypeArg _ = False+isPFieldPun PFieldPun{} = True; isPFieldPun _ = False+isPFieldWildcard PFieldWildcard{} = True; isPFieldWildcard _ = False+isPViewPat PViewPat{} = True; isPViewPat _ = False+isParComp ParComp{} = True; isParComp _ = False+isPatTypeSig PatTypeSig{} = True; isPatTypeSig _ = False+isQuasiQuote QuasiQuote{} = True; isQuasiQuote _ = False --------------------------------------------------------------------- -- HSE FUNCTIONS
src/Hint/All.hs view
@@ -11,23 +11,29 @@ import Hint.Bracket import Hint.Naming import Hint.Structure+import Hint.Import+import Hint.Pragma+import Hint.Extensions staticHints :: [(String,Hint)] staticHints =- let (*) = (,) in- ["List" * listHint- ,"ListRec" * listRecHint- ,"Monad" * monadHint- ,"Lambda" * lambdaHint- ,"Bracket" * bracketHint- ,"Naming" * namingHint- ,"Structure" * structureHint+ let x*y = (x,DeclHint y) ; x+y = (x,ModuHint y) in+ ["List" * listHint+ ,"ListRec" * listRecHint+ ,"Monad" * monadHint+ ,"Lambda" * lambdaHint+ ,"Bracket" * bracketHint+ ,"Naming" * namingHint+ ,"Structure" * structureHint+ ,"Import" + importHint+ ,"Pragma" + pragmaHint+ ,"Extensions" + extensionsHint ] dynamicHints :: [Setting] -> Hint-dynamicHints = readMatch+dynamicHints = DeclHint . readMatch -allHints :: [Setting] -> Hint-allHints xs = concatHints $ dynamicHints xs : map snd staticHints+allHints :: [Setting] -> [Hint]+allHints xs = dynamicHints xs : map snd staticHints
src/Hint/Bracket.hs view
@@ -1,5 +1,3 @@-{-# LANGUAGE PatternGuards #-}- {- <TEST> yes = (f x) x where res = f x x@@ -28,7 +26,7 @@ import HSE.All -bracketHint :: Hint+bracketHint :: DeclHint bracketHint _ = concatMap bracketExp . children0Exp nullSrcLoc bracketExp :: (SrcLoc,Exp) -> [Idea]
+ src/Hint/Extensions.hs view
@@ -0,0 +1,61 @@+{-+ Suggest removal of unnecessary extensions+ i.e. They have {-# LANGUAGE RecursiveDo #-} but no mdo keywords+<TEST>+</TEST>+-}+++module Hint.Extensions where++import HSE.All+import Type+import Data.List+import Data.Maybe+import Data.Function+++extensionsHint :: ModuHint+extensionsHint _ x = [idea Error "Unused LANGUAGE pragma" sl o (LanguagePragma sl new)+ | o@(LanguagePragma sl old) <- modulePragmas x+ , let new = filter (flip used x . classifyExtension . prettyPrint) old+ , length new /= length old]+++used :: Extension -> Module -> Bool+used RecursiveDo x = any isMDo $ universeBi x+used ParallelListComp x = any isParComp $ universeBi x+used FunctionalDependencies x = any isFunDep $ universeBi x+used ImplicitParams x = not $ null (universeBi x :: [IPName])+used EmptyDataDecls x = any f $ universeBi x+ where f (DataDecl _ _ _ _ _ [] _) = True+ f (GDataDecl _ _ _ _ _ _ [] _) = True+ f _ = False+used KindSignatures x = not $ null (universeBi x :: [Kind])+used BangPatterns x = any isPBangPat $ universeBi x+used TemplateHaskell x = not (null (universeBi x :: [Bracket])) && not (null (universeBi x :: [Splice]))+used ForeignFunctionInterface x = not $ null (universeBi x :: [CallConv])+used Generics x = any isPExplTypeArg $ universeBi x+used PatternGuards x = any f $ universeBi x+ where f (GuardedRhs _ [] _) = False+ f (GuardedRhs _ [Qualifier _] _) = False+ f _ = True+used StandaloneDeriving x = any isDerivDecl $ universeBi x+used PatternSignatures x = any isPatTypeSig $ universeBi x+used RecordWildCards x = any isPFieldWildcard $ universeBi x+used RecordPuns x = any isPFieldPun $ universeBi x+used UnboxedTuples x = any isBoxed $ universeBi x+used PackageImports x = any (isJust . importPkg) $ universeBi x+used QuasiQuotes x = any isQuasiQuote $ universeBi x+used ViewPatterns x = any isPViewPat $ universeBi x+used Arrows x = any f $ universeBi x+ where f Proc{} = True+ f LeftArrApp{} = True+ f RightArrApp{} = True+ f LeftArrHighApp{} = True+ f RightArrHighApp{} = True+used TransformListComp x = any f $ universeBi x+ where f QualStmt{} = False+ f _ = True++used _ _ = True
+ src/Hint/Import.hs view
@@ -0,0 +1,71 @@+{-# LANGUAGE PatternGuards #-}+{-+ Reduce the number of import declarations.+ Two import declarations can be combined if:+ (note, A[] is A with whatever import list, or none)+ + import A[]; import A[] = import A[]+ import A(B); import A(C) = import A(B,C)+ import A; import A(C) = import A+ import A; import A hiding (C) = import A+ import A[]; import A[] as Y = import A[] as Y++<TEST>+</TEST>+-}+++module Hint.Import where++import HSE.All+import Type+import Data.List+import Data.Maybe+import Data.Function+++importHint :: ModuHint+importHint _ x = concatMap (wrap . map snd) $ groupBy ((==) `on` fst) $ sortBy (compare `on` fst)+ [((importModule i,importPkg i),i) | i <- universeBi x, not $ importSrc i]+++wrap :: [ImportDecl] -> [Idea]+wrap o = [ rawIdea Error "Use fewer imports" (importLoc $ head x) (f o) (f x)+ | Just x <- [simplify o]]+ where f = unlines . map prettyPrint+++simplify :: [ImportDecl] -> Maybe [ImportDecl]+simplify [] = Nothing+simplify (x:xs) = case simplifyHead x xs of+ Nothing -> fmap (x:) $ simplify xs+ Just xs -> Just $ fromMaybe xs $ simplify xs+++simplifyHead :: ImportDecl -> [ImportDecl] -> Maybe [ImportDecl]+simplifyHead x [] = Nothing+simplifyHead x (y:ys) = case reduce x y of+ Nothing -> fmap (y:) $ simplifyHead x ys+ Just xy -> Just $ xy : ys+++-- Useful fields in import are:+-- importModule :: ModuleName [same]+-- importPkg :: Maybe String [same]+-- importQualified :: Bool+-- importSrc :: Bool [False]+-- importAs :: Maybe ModuleName+-- importSpecs :: Maybe (Bool, [ImportSpec])++reduce :: ImportDecl -> ImportDecl -> Maybe ImportDecl+reduce x y | qual, as, specs = Just x+ | qual, as, Just (False, xs) <- importSpecs x, Just (False, ys) <- importSpecs y =+ Just x{importSpecs = Just (False, nub $ xs ++ ys)}+ | qual, as, isNothing (importSpecs x) || isNothing (importSpecs y) = Just x{importSpecs=Nothing}+ | not (importQualified x), qual, specs, isNothing (importAs x) || isNothing (importAs y) = Just x{importAs=Nothing}+ where+ qual = importQualified x == importQualified y+ as = importAs x == importAs y+ specs = importSpecs x == importSpecs y++reduce _ _ = Nothing
src/Hint/Lambda.hs view
@@ -40,7 +40,7 @@ import Data.Maybe -lambdaHint :: Hint+lambdaHint :: DeclHint lambdaHint _ x@TypeDecl{} = lambdaType x lambdaHint _ x = concatMap lambdaExp (universeBi x) ++ concatMap lambdaDecl (universe x)
src/Hint/List.hs view
@@ -27,7 +27,7 @@ import Type -listHint :: Hint+listHint :: DeclHint listHint _ = listDecl listDecl :: Decl -> [Idea]
src/Hint/ListRec.hs view
@@ -35,7 +35,7 @@ import Data.Generics.PlateData -listRecHint :: Hint+listRecHint :: DeclHint listRecHint _ = concatMap f . universe where f o = maybeToList $ do
src/Hint/Match.hs view
@@ -22,7 +22,7 @@ --------------------------------------------------------------------- -- PERFORM MATCHING -readMatch :: [Setting] -> Hint+readMatch :: [Setting] -> DeclHint readMatch = findIdeas . filter isMatchExp
src/Hint/Monad.hs view
@@ -33,7 +33,7 @@ badFuncs = ["mapM","foldM","forM","replicateM","sequence","zipWithM"] -monadHint :: Hint+monadHint :: DeclHint monadHint _ = concatMap monadExp . universeExp nullSrcLoc monadExp :: (SrcLoc,Exp) -> [Idea]
src/Hint/Naming.hs view
@@ -1,5 +1,3 @@-{-# LANGUAGE ViewPatterns, PatternGuards #-}- {- Suggest the use of camelCase @@ -31,7 +29,7 @@ import Data.Maybe -namingHint :: Hint+namingHint :: DeclHint namingHint _ x = [warn "Use camelCase" (declSrcLoc x) x2 (replaceNames res x2) | not $ null res] where res = [(n,y) | n <- nub $ getNames x, Just y <- [suggestName n]] x2 = shorten x
+ src/Hint/Pragma.hs view
@@ -0,0 +1,60 @@+{-+ Suggest better pragmas+ OPTIONS_GHC -cpp => LANGUAGE CPP+ OPTIONS_GHC -fglasgow-exts => LANGUAGE ... (in HSE)+ OPTIONS_GHC -XFoo => LANGUAGE Foo+ LANGUAGE A, A => LANGUAGE A+ -- do not do LANGUAGE A, LANGUAGE B to combine+<TEST>+</TEST>+-}+++module Hint.Pragma where++import HSE.All+import Type+import Data.List+import Data.Maybe+import Data.Function+++pragmaHint :: ModuHint+pragmaHint _ x = languageDupes lang ++ [pragmaIdea old $ [LanguagePragma nullSrcLoc ns2 | ns2 /= []] ++ catMaybes new | old /= []]+ where+ lang = [x | x@LanguagePragma{} <- modulePragmas x]+ (old,new,ns) = unzip3 [(old,new,ns) | old <- modulePragmas x, Just (new,ns) <- [optToLanguage old]]+ ns2 = nub (concat ns) \\ concat [n | LanguagePragma _ n <- lang]+++pragmaIdea :: [OptionPragma] -> [OptionPragma] -> Idea+pragmaIdea xs ys = rawIdea Error "Use better pragmas" (fromJust $ getSrcLoc $ head xs) (f xs) (f ys)+ where f = unlines . map prettyPrint+++languageDupes :: [OptionPragma] -> [Idea]+languageDupes [] = []+languageDupes (a@(LanguagePragma sl x):xs) =+ (if nub x /= x+ then [pragmaIdea [a] [LanguagePragma sl $ nub x]]+ else [pragmaIdea [a,b] [LanguagePragma sl (nub $ x ++ y)] | b@(LanguagePragma _ y) <- xs, not $ null $ intersect x y]) +++ languageDupes xs+++-- Given a pragma, can you extract some language features out+strToLanguage :: String -> Maybe [Name]+strToLanguage "-cpp" = Just [Ident "CPP"]+strToLanguage x | "-X" `isPrefixOf` x = Just [Ident $ drop 2 x]+strToLanguage "-fglasgow-exts" = Just $ map (Ident . show) glasgowExts+strToLanguage _ = Nothing+++optToLanguage :: OptionPragma -> Maybe (Maybe OptionPragma, [Name])+optToLanguage (OptionsPragma sl tool val)+ | maybe True (== GHC) tool && any isJust vs = Just (res, concat $ catMaybes vs)+ where+ strs = words val+ vs = map strToLanguage strs+ keep = concat $ zipWith (\v s -> [s | isNothing v]) vs strs+ res = if null keep then Nothing else Just $ OptionsPragma sl tool (unwords keep)+optToLanguage _ = Nothing
src/Hint/Structure.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE ViewPatterns, PatternGuards #-}+{-# LANGUAGE ViewPatterns #-} {- Improve the structure of code@@ -20,7 +20,7 @@ import Data.Maybe -structureHint :: Hint+structureHint :: DeclHint structureHint _ x = concat [concatMap useGuards xs | FunBind xs <- [x]] ++ concatMap useIf (universeExp nullSrcLoc x)
src/Main.hs view
@@ -16,6 +16,7 @@ import Util import Parallel import Hint.All+import HSE.All main = do@@ -24,7 +25,7 @@ settings <- readSettings cmdHintFiles let extra = [Classify Ignore x ("","") | x <- cmdIgnore] let apply :: FilePath -> IO [Idea]- apply = fmap (fmap $ classify $ settings ++ extra) . applyHint (allHints settings)+ apply = fmap (fmap $ classify $ settings ++ extra) . applyHint parseFlags{cpphs=Just cmdCpphs} (allHints settings) ideas <- liftM concat $ parallel [listM' =<< apply x | x <- cmdFiles] showItem <- if cmdColor then showANSI else return show mapM_ putStrLn [showItem i | i <- ideas, cmdShowAll || rank i /= Ignore]
src/Report.hs view
@@ -46,7 +46,7 @@ where id = mode ++ show i -code = hscolour False True ""+code = hscolour False writeIdea :: String -> Idea -> [String]
src/Settings.hs view
@@ -25,7 +25,7 @@ -- currently it doesn't readHints :: FilePath -> IO [Module] readHints file = do- y <- fromParseResult `fmap` parseFile True file+ y <- fromParseResult `fmap` parseFile parseFlags{implies=True} file ys <- concatMapM (f . fromNamed . importModule) $ moduleImports y return $ y:ys where
src/Test.hs view
@@ -59,7 +59,7 @@ concatMap ((++) " | " . show) ideas ++ "\n" ++ prettyPrint inp | not good] where- ideas = hint nm inp+ ideas = declHint hint nm inp good = case out of Nothing -> ideas == [] Just x -> length ideas == 1 && (null x || to (head ideas) == x)@@ -69,7 +69,7 @@ parseTestFile file = do src <- readFile file return [(nm, createTest eqn)- | code <- f $ lines src, let modu = fromParseResult $ parseString False file code+ | code <- f $ lines src, let modu = fromParseResult $ parseString parseFlags file code , let nm = nameMatch $ moduleImports modu , eqn <- concatMap getEquations $ moduleDecls modu] where
src/Type.hs view
@@ -62,7 +62,8 @@ -- The real key will be filled in by applyHint-idea rank hint loc from to = Idea ("","") rank hint loc (f from) (f to)+rawIdea = Idea ("","")+idea rank hint loc from to = rawIdea rank hint loc (f from) (f to) where f = dropWhile isSpace . prettyPrint warn mr = idea Warning mr @@ -75,17 +76,16 @@ --------------------------------------------------------------------- -- HINTS -type Hint = NameMatch -> Decl -> [Idea]-+type DeclHint = NameMatch -> Decl -> [Idea]+type ModuHint = NameMatch -> Module -> [Idea] -concatHints :: [Hint] -> Hint-concatHints hs nm x = concatMap (\h -> h nm x) hs+data Hint = DeclHint {declHint :: DeclHint} | ModuHint {moduHint :: ModuHint} -applyHint :: Hint -> FilePath -> IO [Idea]-applyHint h file = do+applyHint :: ParseFlags -> [Hint] -> FilePath -> IO [Idea]+applyHint flags h file = do src <- readFile file- case parseString False file src of+ case parseString flags file src of ParseFailed sl msg -> do let ticks = [" "," ","> "," "," "] let bad = zipWith (++) ticks $ take 5 $ drop (srcLine sl - 3) $ lines src ++ [""]@@ -94,5 +94,7 @@ ParseOk m -> do let name = moduleName m let nm = nameMatch $ moduleImports m- return [ i{func = (name,fromNamed d)}- | d <- moduleDecls m, i <- sortBy (comparing loc) $ h nm d]+ let order n = map (\i -> i{func = (name,n)}) . sortBy (comparing loc)+ return $+ order "" [i | ModuHint h <- h, i <- h nm m] +++ concat [order (fromNamed d) [i | DeclHint h <- h, i <- h nm d] | d <- moduleDecls m]