packages feed

hlint 1.6.14 → 1.6.15

raw patch · 36 files changed

+800/−784 lines, 36 filesdep +processdep ~basedep ~haskell-src-extsdep ~uniplate

Dependencies added: process

Dependency ranges changed: base, haskell-src-exts, uniplate

Files

data/Default.hs view
@@ -63,11 +63,6 @@ error = not (elem x y) ==> notElem x y  warn  = foldr f z (map g x) ==> foldr (f . g) z x-warn  = foldl f z (map g x) ==> foldl  (f . g) z x-warn  = foldl' f z (map g x) ==> foldl' (f . g) z x-warn  = foldl1 f (map g x) ==> foldl1  (f . g) x-warn  = foldl1' f (map g x) ==> foldl1' (f . g) x-warn  = foldr1' f (map g x) ==> foldr1' (f . g) x warn  = foldr1 f (map g x) ==> foldr1 (f . g) x  -- FOLDS@@ -196,7 +191,7 @@ error "Evaluate" = foldl f z [] ==> z error "Evaluate" = foldr f z [] ==> z error "Evaluate" = foldr1 f [x] ==> x-error "Evaluate" = scanr f q0 [] ==> [q0]+error "Evaluate" = scanr f z [] ==> [z] error "Evaluate" = scanr1 f [] ==> [] error "Evaluate" = scanr1 f [x] ==> [x] error "Evaluate" = take n [] ==> []
data/Generalise.hs view
@@ -1,7 +1,7 @@  module HLint.Generalise where -warn = concatMap ==> (>>=)+warn = concatMap ==> (=<<) warn = liftM ==> fmap warn = map ==> fmap warn = a ++ b ==> a `Data.Monoid.mappend` b
data/Test.hs view
@@ -6,7 +6,11 @@  error = Prelude.readFile ==> bad +error = (x :: Int) ==> (x :: Int32)+    where _ = notTypeSafe+ {-+<TEST> main = readFile "foo" >>= putStr            \   -- bad @@ -17,5 +21,7 @@ import Prelude as Prelude2                  \ yes = Prelude2.readFile "foo" >>= putStr    \   -- bad++yes = 32 :: Int -- 32 :: Int32 </TEST> -}
+ data/hlint.ghci view
@@ -0,0 +1,10 @@+-- -*- mode: haskell; -*-+-- Begin copied material.+-- <http://www.cs.kent.ac.uk/people/staff/cr3/toolbox/haskell/dot-squashed.ghci641>+let { redir varcmd = case break Data.Char.isSpace varcmd of { (var,_:cmd) -> return $ unlines [":set -fno-print-bind-result","tmp <- System.Directory.getTemporaryDirectory","(f,h) <- System.IO.openTempFile tmp \"ghci\"","sto <- GHC.Handle.hDuplicate System.IO.stdout","GHC.Handle.hDuplicateTo h System.IO.stdout","System.IO.hClose h",cmd,"GHC.Handle.hDuplicateTo sto System.IO.stdout","let readFileNow f = readFile f >>= \\t->length t `seq` return t",var++" <- readFileNow f","System.Directory.removeFile f"]; _ -> return "putStrLn \"usage: :redir <var> <cmd>\"" } }+:def redir redir+-- End copied material++--- Integration with the hlint code style tool+let hlint _ = return $ unlines [":set -w",    ":redir hlintvar1 :show modules", ":cmd return (\":! hlint \" ++ (concat $ Data.List.intersperse \" \" (map (fst . break (==',') . drop 2 . snd . break (== '(')) $ lines hlintvar1)))",    ":set -Wall"]+:def hlint hlint
hlint.cabal view
@@ -1,7 +1,7 @@ cabal-version:      >= 1.6 build-type:         Simple name:               hlint-version:            1.6.14+version:            1.6.15 -- license is GPL v2 only license:            GPL license-file:       LICENSE@@ -24,6 +24,7 @@     report.html     hs-lint.el     hlint.1+    hlint.ghci extra-source-files:     hlint.htm @@ -31,22 +32,23 @@     default: True     description: Build with support for multithreaded execution -executable hlint+library     build-depends:-        base == 4.*, syb, filepath, directory, mtl, containers, hscolour >= 1.15, cpphs >= 1.9,-        haskell-src-exts == 1.5.*, uniplate == 1.2.* && >= 1.2.0.2+        base == 4.*, process, filepath, directory, mtl, containers, syb,+        hscolour >= 1.15,+        cpphs >= 1.9,+        haskell-src-exts == 1.6.*,+        uniplate == 1.4.*      ghc-options:        -fno-warn-overlapping-patterns-    if flag(threaded)-        ghc-options:    -threaded -    -- ViewPatterns not yet supported by Cabal as an extension-    -- extensions:         ViewPatterns, PatternGuards, MultiParamTypeClasses--    main-is:            Main.hs     hs-source-dirs:     src+    exposed-modules:+        Language.Haskell.HLint     other-modules:         CmdLine+        Hint+        HLint         Settings         Report         Type@@ -58,7 +60,6 @@         HSE.Evaluate         HSE.Generics         HSE.Match-        HSE.Operators         HSE.Util         HSE.NameMatch         Hint.All@@ -73,3 +74,14 @@         Hint.Naming         Hint.Pragma         Hint.Structure+++executable hlint+    build-depends:      base+    hs-source-dirs:     src+    main-is:            Main.hs++    ghc-options:        -fno-warn-overlapping-patterns+    if flag(threaded)+        ghc-options:    -threaded+
hlint.htm view
@@ -147,6 +147,12 @@ (add-hook 'haskell-mode-hook 'my-haskell-mode-hook) </pre> +<h3>GHCi Integration</h3>++<p>+	GHCi integration of HLint has been provided by Gwern Branwen. The integration allows running <tt>:hlint</tt> from the GHCi prompt. The script is at <a href="http://community.haskell.org/~ndm/darcs/hlint/data/hlint.ghci">hlint.ghci</a>, and a copy is installed locally in the data directory. To use, add the contents to your <a href="http://www.haskell.org/ghc/docs/latest/html/users_guide/ghci-dot-files.html">GHCi startup file</a>.+</p>+ <h3>Parallel Operation</h3>  <p>
src/CmdLine.hs view
@@ -6,7 +6,6 @@ import Data.Maybe import System.Console.GetOpt import System.Directory-import System.Environment import System.Exit import System.FilePath import Language.Preprocessor.Cpphs@@ -25,6 +24,7 @@     ,cmdShowAll :: Bool              -- ^ display all skipped items     ,cmdColor :: Bool                -- ^ color the result     ,cmdCpphs :: CpphsOptions        -- ^ options for cpphs+    ,cmdDataDir :: FilePath          -- ^ the data directory     }  @@ -36,6 +36,7 @@           | Define String           | Include String           | Ext String+          | DataDir String             deriving Eq  @@ -48,15 +49,15 @@        ,Option "s" ["show"] (NoArg ShowAll) "Show all ignored ideas"        ,Option "e" ["extension"] (ReqArg Ext "ext") "File extensions to search (defaults to hs and lhs)"        ,Option "t" ["test"] (NoArg Test) "Run in test mode"+       ,Option "d" ["datadir"] (ReqArg DataDir "dir") "Override the data directory"        ,Option ""  ["cpp-define"] (ReqArg Define "name[=value]") "CPP #define"        ,Option ""  ["cpp-include"] (ReqArg Include "dir") "CPP include path"        ]   -- | Exit out if you need to display help info-getCmd :: IO Cmd-getCmd = do-    args <- getArgs+getCmd :: [String] -> IO Cmd+getCmd args = do     let (opt,files,err) = getOpt Permute opts args     let test = Test `elem` opt     unless (null err) $@@ -70,11 +71,13 @@         putStr helpText         exitWith ExitSuccess +    dataDir <- last $ getDataDir : [return x | DataDir x <- opt]+     let exts = [x | Ext x <- opt]     files <- concatMapM (getFile $ if null exts then ["hs","lhs"] else exts) files          let hintFiles = [x | Hints x <- opt]-    hints <- mapM getHintFile $ hintFiles ++ ["HLint" | null hintFiles]+    hints <- mapM (getHintFile dataDir) $ hintFiles ++ ["HLint" | null hintFiles]      let cpphs = defaultCpphsOptions             {boolopts=defaultBoolOptions{locations=False}@@ -91,11 +94,12 @@         ,cmdShowAll = ShowAll `elem` opt         ,cmdColor = Color `elem` opt         ,cmdCpphs = cpphs+        ,cmdDataDir = dataDir         }   versionText :: String-versionText = "HLint v" ++ showVersion version ++ ", (C) Neil Mitchell 2006-2009\n"+versionText = "HLint v" ++ showVersion version ++ ", (C) Neil Mitchell 2006-2010\n"  helpText :: String helpText = unlines@@ -121,10 +125,9 @@         return [file]  -getHintFile :: FilePath -> IO FilePath-getHintFile x = do-        dat <- getDataDir-        let poss = nub $ concat [x : [x <.> "hs" | takeExtension x /= ".hs"] | x <- [x,dat </> x]]+getHintFile :: FilePath -> FilePath -> IO FilePath+getHintFile dataDir x = do+        let poss = nub $ concat [x : [x <.> "hs" | takeExtension x /= ".hs"] | x <- [x,dataDir </> x]]         f poss poss     where         f o [] = error $ unlines $ [
+ src/HLint.hs view
@@ -0,0 +1,60 @@+{-# LANGUAGE RecordWildCards #-}++module HLint(hlint) where++import Control.Arrow+import Control.Monad+import Data.List+import Data.Maybe++import CmdLine+import Settings+import Report+import Type+import Hint+import Test+import Util+import Parallel+import Hint.All+import HSE.All+++-- | This function takes the command line arguments, and returns the number+--   of errors reported.+hlint :: [String] -> IO Int+hlint args = do+    Cmd{..} <- getCmd args+    if cmdTest then test cmdDataDir else do+        settings <- readSettings cmdDataDir cmdHintFiles+        let extra = [Classify Ignore x ("","") | x <- cmdIgnore]+        let apply :: FilePath -> IO [Idea]+            apply = fmap (fmap $ classify $ settings ++ extra) . applyHint parseFlags{cpphs=Just cmdCpphs} (allHints settings)+        ideas <- fmap concat $ parallel [listM' =<< apply x | x <- cmdFiles]+        let visideas = filter (\i -> cmdShowAll || rank i /= Ignore) ideas+        showItem <- if cmdColor then showANSI else return show+        mapM_ (putStrLn . showItem) visideas++        -- figure out statistics        +        let counts = map (head &&& length) $ group $ sort $ map rank ideas+        let [ignore,warn,err] = map (fromMaybe 0 . flip lookup counts) [Ignore,Warning,Error]+        let total = ignore + warn + err+        let shown = if cmdShowAll then total else total - ignore++        let ignored = [show i ++ " ignored" | let i = total - shown, i /= 0]+        let errors = [show err ++ " error" ++ ['s'|err/=1] | err /= 0]++        if shown == 0 then do+            when (cmdReports /= []) $ putStrLn "Skipping writing reports"+            printMsg "No relevant suggestions" ignored+         else do+            forM_ cmdReports $ \x -> do+                putStrLn $ "Writing report to " ++ x ++ " ..."+                writeReport cmdDataDir x visideas+            printMsg ("Found " ++ show shown ++ " suggestion" ++ ['s'|shown/=1]) (errors++ignored)+        return err+++printMsg :: String -> [String] -> IO ()+printMsg msg xs =+    putStrLn $ msg ++ if null xs then "" else+        " (" ++ intercalate ", " xs ++ ")"
src/HSE/All.hs view
@@ -1,23 +1,18 @@  module HSE.All(-    module Language.Haskell.Exts,     module HSE.Util, module HSE.Evaluate,     module HSE.Bracket, module HSE.Match,     module HSE.Generics,     module HSE.NameMatch,-    ParseFlags(..), parseFlags, parseFile, parseString, fromParseResult+    ParseFlags(..), parseFlags, parseFile, parseString     ) where -import Language.Haskell.Exts hiding (parse, parseFile, paren, fromParseResult)-import qualified Language.Haskell.Exts as HSE- import HSE.Util import HSE.Evaluate import HSE.Generics import HSE.Bracket import HSE.Match import HSE.NameMatch-import Util import Data.Char import Data.List import Language.Preprocessor.Cpphs@@ -33,7 +28,7 @@   -- | Parse a Haskell module-parseString :: ParseFlags -> FilePath -> String -> ParseResult Module+parseString :: ParseFlags -> FilePath -> String -> ParseResult Module_ parseString flags file = parseFileContentsWithMode mode . maybe id (`runCpphs` file) (cpphs flags)     where         mode = defaultParseMode@@ -43,17 +38,10 @@             }  --- | On failure returns an empty module and prints to the console-parseFile :: ParseFlags -> FilePath -> IO (ParseResult Module)+parseFile :: ParseFlags -> FilePath -> IO (ParseResult Module_) parseFile flags file = do     src <- readFile file     return $ parseString flags file src----- | TODO: Use the fromParseResult in HSE once it gives source location-fromParseResult :: ParseResult Module -> Module-fromParseResult (ParseOk x) = x-fromParseResult (ParseFailed src msg) = error $ showSrcLoc src ++ " Parse failure, " ++ limit 50 msg   extension =
src/HSE/Bracket.hs view
@@ -3,19 +3,19 @@ module HSE.Bracket where  import Control.Monad.State-import Data.Generics.PlateData+import Data.Data+import Data.Generics.Uniplate.Data import Data.Maybe-import Language.Haskell.Exts import HSE.Util  -paren :: Exp -> Exp-paren x = if isAtom x then x else Paren x+paren :: Exp s -> Exp s+paren x = if isAtom x then x else Paren (ann x) x   -- | Is this item lexically requiring no bracketing ever --   i.e. is totally atomic-isAtom :: Exp -> Bool+isAtom :: Exp s -> Bool isAtom x = case x of     Paren{} -> True     Var{} -> True@@ -35,7 +35,7 @@   -- Err on the side of caution, True = don't know-needBracket :: Int -> Exp -> Exp -> Bool+needBracket :: Int -> Exp s -> Exp s -> Bool needBracket i parent child      | isAtom child = False     | InfixApp{} <- parent, isApp child = False@@ -48,16 +48,16 @@   -- True implies I changed this level-descendBracket :: (Exp -> (Bool, Exp)) -> Exp -> Exp+descendBracket :: Data s => (Exp s -> (Bool, Exp s)) -> Exp s -> Exp s descendBracket f x = flip evalState 0 $ flip descendM x $ \y -> do     i <- get     modify (+1)     (b,y) <- return $ f y-    let p = if b && needBracket i x y then Paren else id+    let p = if b && needBracket i x y then (\x -> Paren (ann x) x) else id     return $ p y  -transformBracket :: (Exp -> Maybe Exp) -> Exp -> Exp+transformBracket :: Data s => (Exp s -> Maybe (Exp s)) -> Exp s -> Exp s transformBracket f = snd . g     where         g = f2 . descendBracket g@@ -65,5 +65,5 @@   -- ensure that all the 1-level children are appropriately bracketed-ensureBracket1 :: Exp -> Exp+ensureBracket1 :: Data s => Exp s -> Exp s ensureBracket1 = descendBracket ((,) True)
src/HSE/Evaluate.hs view
@@ -3,23 +3,24 @@ -- Evaluate a HSE Exp as much as possible module HSE.Evaluate(evaluate) where -import Language.Haskell.Exts-import Data.Generics.PlateData+import Data.Generics.Uniplate.Data import HSE.Match import HSE.Util import HSE.Bracket  -evaluate :: Exp -> Exp+evaluate :: Exp_ -> Exp_ evaluate = fromParen . transform evaluate1  -evaluate1 :: Exp -> Exp-evaluate1 (App len (Lit (String xs))) | len ~= "length" = Lit $ Int $ fromIntegral $ length xs-evaluate1 (App len (List xs)) | len ~= "length" = Lit $ Int $ fromIntegral $ length xs-evaluate1 (view -> App2 op (Lit x) (Lit y)) | op ~= "==" = toNamed $ show $ x == y+evaluate1 :: Exp_ -> Exp_+evaluate1 (App s len (Lit _ (String _ xs _))) | len ~= "length" = Lit s $ Int s n (show n)+    where n = fromIntegral $ length xs+evaluate1 (App s len (List _ xs)) | len ~= "length" = Lit s $ Int s n (show n)+    where n = fromIntegral $ length xs+evaluate1 (view -> App2 op (Lit _ x) (Lit _ y)) | op ~= "==" = toNamed $ show $ x =~= y evaluate1 (view -> App2 op x y)     | op ~= "&&" && x ~= "True"  = y     | op ~= "&&" && x ~= "False" = x-evaluate1 (Paren x) | isAtom x = x+evaluate1 (Paren _ x) | isAtom x = x evaluate1 x = x
src/HSE/Generics.hs view
@@ -1,7 +1,7 @@  module HSE.Generics(-    module Data.Generics, module Data.Generics.PlateData+    module Data.Generics, module Data.Generics.Uniplate.Data     ) where  import Data.Generics hiding (Infix, Fixity)-import Data.Generics.PlateData+import Data.Generics.Uniplate.Data
src/HSE/Match.hs view
@@ -1,10 +1,9 @@-{-# LANGUAGE ViewPatterns, MultiParamTypeClasses #-}+{-# LANGUAGE ViewPatterns, MultiParamTypeClasses, FlexibleInstances, TypeSynonymInstances #-}  module HSE.Match where  import Data.Char import Data.List-import Language.Haskell.Exts import HSE.Util  @@ -12,27 +11,39 @@     view :: a -> b  -data App2 = NoApp2 | App2 Exp Exp Exp deriving Show+data App2 = NoApp2 | App2 Exp_ Exp_ Exp_ deriving Show -instance View Exp App2 where-    view (fromParen -> InfixApp lhs op rhs) = view $ opExp op `App` lhs `App` rhs-    view (fromParen -> (fromParen -> f `App` x) `App` y) = App2 f x y+instance View Exp_ App2 where+    view (fromParen -> InfixApp _ lhs op rhs) = App2 (opExp op) lhs rhs+    view (fromParen -> App _ (fromParen -> App _ f x) y) = App2 f x y     view _ = NoApp2  -data App1 = NoApp1 | App1 Exp Exp deriving Show+data App1 = NoApp1 | App1 Exp_ Exp_ deriving Show -instance View Exp App1 where-    view (fromParen -> f `App` x) = App1 f x+instance View Exp_ App1 where+    view (fromParen -> App _ f x) = App1 f x     view _ = NoApp1 +data PVar_ = NoPVar_ | PVar_ String -(~=) :: Exp -> String -> Bool+instance View Pat_ PVar_ where+    view (fromPParen -> PVar _ x) = PVar_ $ fromNamed x+    view _ = NoPVar_++data Var_ = NoVar_ | Var_ String deriving Eq++instance View Exp_ Var_ where+    view (fromParen -> Var _ (UnQual _ x)) = Var_ $ fromNamed x+    view _ = NoVar_+++(~=) :: Exp_ -> String -> Bool (~=) = (==) . fromNamed  --- | fromNamed will return "" when it cannot be represented---   toNamed may crash on ""+-- | fromNamed will return \"\" when it cannot be represented+--   toNamed may crash on \"\" class Named a where     toNamed :: String -> a     fromNamed :: a -> String@@ -45,67 +56,78 @@ isSym _ = False  -instance Named Exp where-    fromNamed (Var x) = fromNamed x-    fromNamed (Con x) = fromNamed x-    fromNamed (List []) = "[]"+instance Named (Exp S) where+    fromNamed (Var _ x) = fromNamed x+    fromNamed (Con _ x) = fromNamed x+    fromNamed (List _ []) = "[]"     fromNamed _ = ""     -    toNamed "[]" = List []-    toNamed x | isCon x = Con $ toNamed x-              | otherwise = Var $ toNamed x+    toNamed "[]" = List an []+    toNamed x | isCon x = Con an $ toNamed x+              | otherwise = Var an $ toNamed x -instance Named QName where-    fromNamed (Special Cons) = ":"-    fromNamed (Special UnitCon) = "()"-    fromNamed (UnQual x) = fromNamed x+instance Named (QName S) where+    fromNamed (Special _ Cons{}) = ":"+    fromNamed (Special _ UnitCon{}) = "()"+    fromNamed (UnQual _ x) = fromNamed x     fromNamed _ = "" -    toNamed ":" = Special Cons-    toNamed x = UnQual $ toNamed x+    toNamed ":" = Special an $ Cons an+    toNamed x = UnQual an $ toNamed x -instance Named Name where-    fromNamed (Ident x) = x-    fromNamed (Symbol x) = x+instance Named (Name S) where+    fromNamed (Ident _ x) = x+    fromNamed (Symbol _ x) = x -    toNamed x | isSym x = Symbol x-              | otherwise = Ident x+    toNamed x | isSym x = Symbol an x+              | otherwise = Ident an x -instance Named ModuleName where-    fromNamed (ModuleName x) = x-    toNamed = ModuleName+instance Named (ModuleName S) where+    fromNamed (ModuleName _ x) = x+    toNamed = ModuleName an  -instance Named Pat where-    fromNamed (PVar x) = fromNamed x-    fromNamed (PApp x []) = fromNamed x+instance Named (Pat S) where+    fromNamed (PVar _ x) = fromNamed x+    fromNamed (PApp _ x []) = fromNamed x     fromNamed _ = "" -    toNamed x | isCon x = PApp (toNamed x) []-              | otherwise = PVar $ toNamed x+    toNamed x | isCon x = PApp an (toNamed x) []+              | otherwise = PVar an $ toNamed x  -instance Named TyVarBind where-    fromNamed (KindedVar x _) = fromNamed x-    fromNamed (UnkindedVar x) = fromNamed x-    toNamed = UnkindedVar . toNamed+instance Named (TyVarBind S) where+    fromNamed (KindedVar _ x _) = fromNamed x+    fromNamed (UnkindedVar _ x) = fromNamed x+    toNamed x = UnkindedVar an (toNamed x)  -instance Named QOp where-    fromNamed (QVarOp x) = fromNamed x-    fromNamed (QConOp x) = fromNamed x-    toNamed x | isCon x = QConOp $ toNamed x-              | otherwise = QVarOp $ toNamed x+instance Named (QOp S) where+    fromNamed (QVarOp _ x) = fromNamed x+    fromNamed (QConOp _ x) = fromNamed x+    toNamed x | isCon x = QConOp an $ toNamed x+              | otherwise = QVarOp an $ toNamed x -instance Named Decl where-    fromNamed (TypeDecl _ name _ _) = fromNamed name-    fromNamed (DataDecl _ _ _ name _ _ _) = fromNamed name-    fromNamed (GDataDecl _ _ _ name _ _ _ _) = fromNamed name-    fromNamed (TypeFamDecl _ name _ _) = fromNamed name-    fromNamed (DataFamDecl _ _ name _ _) = fromNamed name-    fromNamed (ClassDecl _ _ name _ _ _) = fromNamed name-    fromNamed (PatBind _ (PVar name) _ _ _) = fromNamed name-    fromNamed (FunBind (Match _ name _ _ _ _ : _)) = fromNamed name+instance Named (Match S) where+    fromNamed (Match _ x _ _ _) = fromNamed x+    fromNamed (InfixMatch _ _ x _ _ _) = fromNamed x+    toNamed = error "No toNamed for Match"++instance Named (DeclHead S) where+    fromNamed (DHead _ x _) = fromNamed x+    fromNamed (DHInfix _ _ x _) = fromNamed x+    fromNamed (DHParen _ x) = fromNamed x+    toNamed = error "No toNamed for DeclHead"++instance Named (Decl S) where+    fromNamed (TypeDecl _ name _) = fromNamed name+    fromNamed (DataDecl _ _ _ name _ _) = fromNamed name+    fromNamed (GDataDecl _ _ _ name _ _ _) = fromNamed name+    fromNamed (TypeFamDecl _ name _) = fromNamed name+    fromNamed (DataFamDecl _ _ name _) = fromNamed name+    fromNamed (ClassDecl _ _ name _ _) = fromNamed name+    fromNamed (PatBind _ (PVar _ name) _ _ _) = fromNamed name+    fromNamed (FunBind _ (name:_)) = fromNamed name     fromNamed (ForImp _ _ _ _ name _) = fromNamed name     fromNamed (ForExp _ _ _ name _) = fromNamed name     fromNamed _ = ""
src/HSE/NameMatch.hs view
@@ -1,14 +1,15 @@  module HSE.NameMatch(NameMatch, nameMatch) where -import Language.Haskell.Exts+import HSE.Util+import HSE.Match import qualified Data.Map as Map import Data.List import Data.Function import Util  -type NameMatch = QName -> QName -> Bool+type NameMatch = QName S -> QName S -> Bool   -- Given a list of import statements, are the names equal@@ -16,37 +17,38 @@ -- -- If the left is unqualified, then the right is dequalified and checked for match -- If the left is qualified, then the right is wrapped and name resolved-nameMatch :: [ImportDecl] -> NameMatch+nameMatch :: [ImportDecl S] -> NameMatch nameMatch imps = f     where         -- deal with "as" imports-        resolve :: ModuleName -> ModuleName-        resolve = \x -> Map.findWithDefault x x mp-            where mp = Map.fromList [(as, importModule i) | i <- imps, Just as <- [importAs i]]+        resolve :: ModuleName S -> ModuleName S+        resolve = \x -> Map.findWithDefault x (fromNamed x) mp+            where mp = Map.fromList [(fromNamed as, importModule i) | i <- imps, Just as <- [importAs i]]                  -- return True if x is potentially imported by B-        importedFrom :: ModuleName -> Name -> Bool-        importedFrom = \modu x -> any (g x) $ Map.findWithDefault [(True,[]) | modu == ModuleName "Prelude"] modu mp+        importedFrom :: ModuleName S -> Name S -> Bool+        importedFrom = \modu x ->+                any (g x) $ Map.findWithDefault [(True,[]) | fromNamed modu == "Prelude"] (fromNamed modu) mp             where mp = Map.fromList $ groupSortFst-                            [(importModule i, importSpecNames i) | i <- imps, not $ importQualified i]+                       [(fromNamed $ importModule i, importSpecNames i) | i <- imps, not $ importQualified i] -                  g x (hide,y) = hide /= (x `elem` y)+                  g x (hide,y) = hide /= (x `elem_` y)          -        f (Qual xm x) (Qual ym y) = x == y && xm == resolve ym-        f (Qual xm x) (UnQual y) = x == y && importedFrom xm x-        f x y = x == y+        f (Qual _ xm x) (Qual _ ym y) = x =~= y && xm =~= resolve ym+        f (Qual _ xm x) (UnQual _ y) = x =~= y && importedFrom xm x+        f x y = x =~= y  -importSpecNames :: ImportDecl -> (Bool, [Name])+importSpecNames :: ImportDecl S -> (Bool, [Name S]) importSpecNames x = case importSpecs x of     Nothing -> (True, [])-    Just (b, x) -> (b, concatMap f x)+    Just (ImportSpecList _ b x) -> (b, concatMap f x)     where-        f (IVar x) = [x]-        f (IAbs x) = [x]-        f (IThingAll x) = [x]-        f (IThingWith x ys) = x : map g ys-        g (VarName x) = x-        g (ConName x) = x+        f (IVar _ x) = [x]+        f (IAbs _ x) = [x]+        f (IThingAll _ x) = [x]+        f (IThingWith _ x ys) = x : map g ys+        g (VarName _ x) = x+        g (ConName _ x) = x 
− src/HSE/Operators.hs
@@ -1,113 +0,0 @@--module HSE.Operators(-    FixityDecl(..), preludeFixities, baseFixities,-    applyFixities, testFixities,-    infixr_, infixl_, infix_-    ) where--import Data.Generics-import Data.Generics.PlateData-import Data.Char-import Data.List-import Data.Maybe-import Language.Haskell.Exts hiding-    (preludeFixities, baseFixities, applyFixities, Fixity,-    infixr_, infixl_, infix_)-import HSE.Match-import HSE.Util-import HSE.Bracket-import qualified Data.Map as Map---data FixityDecl = Fixity Assoc Int Op---preludeFixities :: [FixityDecl]-preludeFixities = concat-    [infixr_ 9  ["."]-    ,infixl_ 9  ["!!"]-    ,infixr_ 8  ["^","^^","**"]-    ,infixl_ 7  ["*","/","`quot`","`rem`","`div`","`mod`",":%","%"]-    ,infixl_ 6  ["+","-"]-    ,infixr_ 5  [":","++"]-    ,infix_  4  ["==","/=","<","<=",">=",">","`elem`","`notElem`"]-    ,infixr_ 3  ["&&"]-    ,infixr_ 2  ["||"]-    ,infixl_ 1  [">>",">>="]-    ,infixr_ 1  ["=<<"]-    ,infixr_ 0  ["$","$!","`seq`"]-    ]--baseFixities :: [FixityDecl]-baseFixities = preludeFixities ++ concat-    [infixl_ 9 ["!","//","!:"]-    ,infixl_ 8 ["`shift`","`rotate`","`shiftL`","`shiftR`","`rotateL`","`rotateR`"]-    ,infixl_ 7 [".&."]-    ,infixl_ 6 ["`xor`"]-    ,infix_  6 [":+"]-    ,infixl_ 5 [".|."]-    ,infixr_ 5 ["+:+","<++","<+>"] -- fixity conflict for +++ between ReadP and Arrow-    ,infix_  5 ["\\\\"]-    ,infixl_ 4 ["<$>","<$","<*>","<*","*>","<**>"]-    ,infix_  4 ["`elemP`","`notElemP`"]-    ,infixl_ 3 ["<|>"]-    ,infixr_ 3 ["&&&","***"]-    ,infixr_ 2 ["+++","|||"]-    ,infixr_ 1 ["<=<",">=>",">>>","<<<","^<<","<<^","^>>",">>^"]-    ,infixl_ 0 ["`on`"]-    ,infixr_ 0 ["`par`","`pseq`"]-    ]---infixr_ = fixity AssocRight-infixl_ = fixity AssocLeft-infix_  = fixity AssocNone--fixity a p = map (Fixity a p . op)-    where-        op ('`':xs) = (if isUpper (head xs) then ConOp else VarOp) $ Ident $ init xs-        op xs = (if head xs == ':' then ConOp else VarOp) $ Symbol xs----- Inspired by the code at:--- http://hackage.haskell.org/trac/haskell-prime/attachment/wiki/FixityResolution/resolve.hs-applyFixities :: Biplate a Exp => [FixityDecl] -> a -> a-applyFixities fixs = descendBi (transform f)-    where-        ask = askFixity fixs-    -        f o@(InfixApp (InfixApp x op1 y) op2 z)-                | p1 == p2 && (a1 /= a2 || a1 == AssocNone) = o -- Ambiguous infix expression!-                | p1 > p2 || p1 == p2 && (a1 == AssocLeft || a2 == AssocNone) = o-                | otherwise = InfixApp x op1 (f $ InfixApp y op2 z)-            where-                (a1,p1) = ask op1-                (a2,p2) = ask op2-        f x = x---testFixities = let (==) = f in and-    ["f + g + x" == "(f + g) + x"-    ,"f : g : x" == "f : (g : x)"-    ,"f $ g $ x" == "f $ (g $ x)"-    ,"f . g . x" == "f . (g . x)"-    ,"f . g $ x" == "(f . g) $ x"-    ,"f $ g . x" == "f $ (g . x)"-    ,"a && b || c && d" == "(a && b) || (c && d)"-    ]-    where-        f lhs rhs = g lhs == g rhs || error ("Fixity mismatch " ++ lhs ++ " =/= " ++ rhs)-        g = transformBi (const nullSrcLoc) $ transformBi fromParen . applyFixities preludeFixities . fromParseResult . parseFileContents . (++) "foo = "---askFixity :: [FixityDecl] -> QOp -> (Assoc, Int)-askFixity xs = \k -> Map.findWithDefault (AssocLeft, 9) (f k) mp-    where-        mp = Map.fromList [(x,(a,p)) | Fixity a p x <- xs]--        f (QVarOp x) = VarOp (g x)-        f (QConOp x) = ConOp (g x)--        g (Qual _ x) = x-        g (UnQual x) = x-        g (Special Cons) = Symbol ":"
src/HSE/Util.hs view
@@ -1,56 +1,67 @@-{-# LANGUAGE PatternGuards #-} -module HSE.Util where+module HSE.Util(module Language.Haskell.Exts.Annotated, module HSE.Util) where  import Control.Monad import Data.Generics-import Data.Generics.PlateData+import Data.Generics.Uniplate.Data import Data.List import Data.Maybe-import Language.Haskell.Exts-import Util+import Language.Haskell.Exts.Annotated hiding (parse, loc, parseFile, paren)  +type S = SrcSpanInfo+type Module_ = Module S+type Decl_ = Decl S+type Exp_ = Exp S+type Pat_ = Pat S+type Type_ = Type S++ --------------------------------------------------------------------- -- ACCESSOR/TESTER -opExp :: QOp -> Exp-opExp (QVarOp op) = Var op-opExp (QConOp op) = Con op+opExp :: QOp s -> Exp s+opExp (QVarOp s op) = Var s op+opExp (QConOp s op) = Con s op -moduleDecls :: Module -> [Decl]-moduleDecls (Module _ _ _ _ _ _ xs) = xs+moduleDecls :: Module s -> [Decl s]+moduleDecls (Module _ _ _ _ xs) = xs -moduleName :: Module -> String-moduleName (Module _ (ModuleName x) _ _ _ _ _) = x+moduleName :: Module s -> String+moduleName (Module _ Nothing _ _ _) = "Main"+moduleName (Module _ (Just (ModuleHead _ (ModuleName _ x) _ _)) _ _ _) = x -moduleImports :: Module -> [ImportDecl]-moduleImports (Module _ _ _ _ _ x _) = x+moduleImports :: Module s -> [ImportDecl s]+moduleImports (Module _ _ _ x _) = x -modulePragmas :: Module -> [OptionPragma]-modulePragmas (Module _ _ x _ _ _ _) = x+modulePragmas :: Module s -> [OptionPragma s]+modulePragmas (Module _ _ x _ _) = x -isChar :: Exp -> Bool-isChar (Lit (Char _)) = True+isChar :: Exp s -> Bool+isChar (Lit _ Char{}) = True isChar _ = False -fromChar :: Exp -> Char-fromChar (Lit (Char x)) = x+fromChar :: Exp s -> Char+fromChar (Lit _ (Char _ x _)) = x -isString :: Exp -> Bool-isString (Lit (String _)) = True+isString :: Exp s -> Bool+isString (Lit _ String{}) = True isString _ = False -fromString :: Exp -> String-fromString (Lit (String x)) = x+fromString :: Exp s -> String+fromString (Lit _ (String _ x _)) = x -isPString (PLit (String _)) = True; isPString _ = False-fromPString (PLit (String x)) = x+isPString (PLit _ String{}) = True; isPString _ = False+fromPString (PLit _ (String _ x _)) = x -fromParen :: Exp -> Exp-fromParen (Paren x) = fromParen x+fromParen :: Exp s -> Exp s+fromParen (Paren _ x) = fromParen x fromParen x = x +fromPParen :: Pat s -> Pat s+fromPParen (PParen _ x) = fromPParen x+fromPParen x = x+ -- is* :: Exp -> Bool isVar Var{} = True; isVar _ = False isApp App{} = True; isApp _ = False@@ -73,23 +84,18 @@   -- which names are bound by a declaration-declBind :: Decl -> [Name]-declBind (FunBind (Match _ x _ _ _ _ : _)) = [x]-declBind (PatBind _ x _ _ _) = [x | PVar x <- universe x]+declBind :: Decl_ -> [String]+declBind (FunBind _ (Match _ x _ _ _ : _)) = [prettyPrint x]+declBind (PatBind _ x _ _ _) = pvars x declBind _ = []  --------------------------------------------------------------------- -- HSE FUNCTIONS --- pick a variable that is not being used-freeVar :: Data a => a -> String-freeVar x = head $ allVars \\ concat [[y, drop 1 y] | Ident y <- universeBi x]-    where allVars = [letter : number | number <- "" : map show [1..], letter <- ['a'..'z']] --getEquations :: Decl -> [Decl]-getEquations (FunBind xs) = map (FunBind . (:[])) xs-getEquations (PatBind src (PVar name) typ bod bind) = [FunBind [Match src name [] typ bod bind]]+getEquations :: Decl s -> [Decl s]+getEquations (FunBind s xs) = map (FunBind s . (:[])) xs+getEquations (PatBind s (PVar _ name) _ bod bind) = [FunBind s [Match s name [] bod bind]] getEquations x = [x]  @@ -97,76 +103,105 @@ -- VECTOR APPLICATION  -apps :: [Exp] -> Exp-apps = foldl1 App+apps :: [Exp s] -> Exp s+apps xs = foldl1 (App $ ann $ head xs) xs  -fromApps :: Exp -> [Exp]-fromApps (App x y) = fromApps x ++ [y]+fromApps :: Exp s -> [Exp s]+fromApps (App _ x y) = fromApps x ++ [y] fromApps x = [x]   -- Rule for the Uniplate Apps functions -- Given (f a) b, consider the children to be: children f ++ [a,b] -childrenApps :: Exp -> [Exp]-childrenApps (App x@App{} y) = childrenApps x ++ [y]-childrenApps (App x y) = children x ++ [y]+childrenApps :: Data s => Exp s -> [Exp s]+childrenApps (App _ x@App{} y) = childrenApps x ++ [y]+childrenApps (App _ x y) = children x ++ [y] childrenApps x = children x  -descendApps :: (Exp -> Exp) -> Exp -> Exp-descendApps f (App x@App{} y) = App (descendApps f x) (f y)-descendApps f (App x y) = App (descend f x) (f y)+descendApps :: Data s => (Exp s -> Exp s) -> Exp s -> Exp s+descendApps f (App s x@App{} y) = App s (descendApps f x) (f y)+descendApps f (App s x y) = App s (descend f x) (f y) descendApps f x = descend f x  -descendAppsM :: Monad m => (Exp -> m Exp) -> Exp -> m Exp-descendAppsM f (App x@App{} y) = liftM2 App (descendAppsM f x) (f y)-descendAppsM f (App x y) = liftM2 App (descendM f x) (f y)+descendAppsM :: (Data s, Monad m) => (Exp s -> m (Exp s)) -> Exp s -> m (Exp s)+descendAppsM f (App s x@App{} y) = liftM2 (App s) (descendAppsM f x) (f y)+descendAppsM f (App s x y) = liftM2 (App s) (descendM f x) (f y) descendAppsM f x = descendM f x  -universeApps :: Exp -> [Exp]+universeApps :: Data s => Exp s -> [Exp s] universeApps x = x : concatMap universeApps (childrenApps x) -transformApps :: (Exp -> Exp) -> Exp -> Exp+transformApps :: Data s => (Exp s -> Exp s) -> Exp s -> Exp s transformApps f = f . descendApps (transformApps f) -transformAppsM :: Monad m => (Exp -> m Exp) -> Exp -> m Exp+transformAppsM :: (Data s, Monad m) => (Exp s -> m (Exp s)) -> Exp s -> m (Exp s) transformAppsM f x = f =<< descendAppsM (transformAppsM f) x   ------------------------------------------------------------------------ SRCLOC FUNCTIONS+-- UNIPLATE FUNCTIONS -nullSrcLoc :: SrcLoc-nullSrcLoc = SrcLoc "" 0 0+universeS :: (Functor f, Data (f S), Data x) => x -> [f S]+universeS = universeBi +childrenS :: (Functor f, Data (f S), Data x) => x -> [f S]+childrenS = childrenBi+++vars :: Data a => a -> [String]+vars xs = [prettyPrint x | Var _ (UnQual _ x) <- universeS xs]++pvars :: Data a => a -> [String]+pvars xs = [prettyPrint x | PVar _ x <- universeS xs]++---------------------------------------------------------------------+-- SRCLOC FUNCTIONS+ showSrcLoc :: SrcLoc -> String showSrcLoc (SrcLoc file line col) = file ++ ":" ++ show line ++ ":" ++ show col ++ ":" -getSrcLoc :: Data a => a -> Maybe SrcLoc-getSrcLoc = headDef Nothing . gmapQ cast+toSrcLoc :: SrcInfo si => si -> SrcLoc+toSrcLoc = getPointLoc +nullSrcLoc :: SrcLoc+nullSrcLoc = SrcLoc "" 0 0 -declSrcLoc :: Decl -> SrcLoc-declSrcLoc (FunBind (x:xs)) = fromMaybe nullSrcLoc $ getSrcLoc x-declSrcLoc x = fromMaybe nullSrcLoc $ getSrcLoc x+an :: SrcSpanInfo+an = toSrcInfo nullSrcLoc [] nullSrcLoc +dropAnn :: Functor f => f s -> f ()+dropAnn = fmap (const ())++ ------------------------------------------------------------------------ UNIPLATE STYLE FUNCTIONS+-- SRCLOC EQUALITY --- children on Exp, but with SrcLoc's-children1Exp :: Data a => SrcLoc -> a -> [(SrcLoc, Exp)]-children1Exp src x = concat $ gmapQ (children0Exp src2) x-    where src2 = fromMaybe src (getSrcLoc x)+-- enforce all being on S, as otherwise easy to =~= on a Just, and get the wrong functor -children0Exp :: Data a => SrcLoc -> a -> [(SrcLoc, Exp)]-children0Exp src x | Just y <- cast x = [(src, y)]-                   | otherwise = children1Exp src x+x /=~= y = not $ x =~= y -universeExp :: Data a => SrcLoc -> a -> [(SrcLoc, Exp)]-universeExp src x = concatMap f (children0Exp src x)-    where f (src,x) = (src,x) : concatMap f (children1Exp src x)+elem_ :: (Annotated f, Eq (f ())) => f S -> [f S] -> Bool+elem_ x y = any (x =~=) y++nub_ :: (Annotated f, Eq (f ())) => [f S] -> [f S]+nub_ = nubBy (=~=)++intersect_ :: (Annotated f, Eq (f ())) => [f S] -> [f S] -> [f S]+intersect_ = intersectBy (=~=)++eqList, neqList :: (Annotated f, Eq (f ())) => [f S] -> [f S] -> Bool+neqList x y = not $ eqList x y+eqList (x:xs) (y:ys) = x =~= y && eqList xs ys+eqList [] [] = True+eqList _ _ = False++eqMaybe:: (Annotated f, Eq (f ())) => Maybe (f S) -> Maybe (f S) -> Bool+eqMaybe (Just x) (Just y) = x =~= y+eqMaybe Nothing Nothing = True+eqMaybe _ _ = False 
+ src/Hint.hs view
@@ -0,0 +1,36 @@++module Hint where++import HSE.All+import Data.Char+import Data.List+import Data.Ord+import Type+++type DeclHint = NameMatch -> Module_ -> Decl_ -> [Idea]+type ModuHint = NameMatch -> Module_          -> [Idea]++data Hint = DeclHint {declHint :: DeclHint} | ModuHint {moduHint :: ModuHint}+++applyHint :: ParseFlags -> [Hint] -> FilePath -> IO [Idea]+applyHint flags h file = do+    src <- readFile file+    return $ applyHintStr flags h file src+++applyHintStr :: ParseFlags -> [Hint] -> FilePath -> String -> [Idea]+applyHintStr flags h file src =+    case parseString flags file src of+        ParseFailed sl msg ->+            let ticks = ["  ","  ","> ","  ","  "]+                bad = zipWith (++) ticks $ take 5 $ drop (srcLine sl - 3) $ lines src ++ [""]+                bad2 = reverse $ dropWhile (all isSpace) $ reverse $ dropWhile (all isSpace) bad+            in [ParseError Warning "Parse error" sl msg (unlines bad2)]+        ParseOk m ->+            let name = moduleName m+                nm = nameMatch $ moduleImports m+                order n = map (\i -> i{func = (name,n)}) . sortBy (comparing loc)+            in order "" [i | ModuHint h <- h, i <- h nm m] +++               concat [order (fromNamed d) [i | DeclHint h <- h, i <- h nm m d] | d <- moduleDecls m]
src/Hint/All.hs view
@@ -2,6 +2,7 @@ module Hint.All where  import Type+import Hint import Data.List import Data.Maybe 
src/Hint/Bracket.hs view
@@ -25,32 +25,33 @@  import Control.Arrow import Type+import Hint import HSE.All   bracketHint :: DeclHint-bracketHint _ _ = concatMap bracketExp . children0Exp nullSrcLoc+bracketHint _ _ = concatMap bracketExp . childrenBi -bracketExp :: (SrcLoc,Exp) -> [Idea]-bracketExp (loc,x) =-    [g loc x (fromParen x) | isParen x] ++ f loc x+bracketExp :: Exp_ -> [Idea]+bracketExp x =+    [g x (fromParen x) | isParen x] ++ f x     where-        f loc x = testDirect loc x ++ testDollar loc x ++ concatMap (uncurry f) (children1Exp loc x)+        f x = testDirect x ++ testDollar x ++ concatMap f (children x)         g = warn "Redundant brackets" -        testDirect loc x = [g loc x y | let y = descendBracket (isParen &&& fromParen) x, x /= y]+        testDirect x = [g x y | let y = descendBracket (isParen &&& fromParen) x, x /=~= y] -        testDollar loc x =-            [idea Error "Redundant $" loc x y | InfixApp a d b <- [x], opExp d ~= "$"-            ,let y = App a b, not $ needBracket 0 y a, not $ needBracket 1 y b]+        testDollar x =+            [idea Error "Redundant $" x y | InfixApp _ a d b <- [x], opExp d ~= "$"+            ,let y = App an a b, not $ needBracket 0 y a, not $ needBracket 1 y b]             ++-            [idea Error "Redundant $" loc x (t y)-            |(t, Paren (InfixApp a1 op1 a2)) <- infixes x+            [idea Error "Redundant $" x (t y)+            |(t, Paren _ (InfixApp _ a1 op1 a2)) <- infixes x             ,opExp op1 ~= "$", isVar a1 || isApp a1 || isParen a1, not $ isAtom a2-            ,let y = App a1 (Paren a2)]+            ,let y = App an a1 (Paren an a2)]   -- return both sides, and a way to put them together again-infixes :: Exp -> [(Exp -> Exp, Exp)]-infixes (InfixApp a b c) = [(InfixApp a b, c), (\a -> InfixApp a b c, a)]+infixes :: Exp_ -> [(Exp_ -> Exp_, Exp_)]+infixes (InfixApp s a b c) = [(InfixApp s a b, c), (\a -> InfixApp s a b c, a)] infixes _ = []
src/Hint/Extensions.hs view
@@ -31,59 +31,60 @@  import HSE.All import Type+import Hint import Data.List import Data.Maybe import Data.Function   extensionsHint :: ModuHint-extensionsHint _ x = [rawIdea Error "Unused LANGUAGE pragma" sl+extensionsHint _ x = [rawIdea Error "Unused LANGUAGE pragma" (toSrcLoc sl)           (prettyPrint o) (if null new then "" else prettyPrint $ LanguagePragma sl new)-    | let usedTH = used TemplateHaskell x -- if TH is on, can use all other extensions programmatically-    , o@(LanguagePragma sl old) <- modulePragmas x, not usedTH+    | not $ used TemplateHaskell x -- if TH is on, can use all other extensions programmatically+    , 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 = has isMDo-used ParallelListComp = has isParComp-used FunctionalDependencies = has isFunDep-used ImplicitParams = hasT (un :: IPName)-used EmptyDataDecls = has f-    where f (DataDecl _ _ _ _ _ [] _) = True-          f (GDataDecl _ _ _ _ _ _ [] _) = True+used :: Extension -> Module_ -> Bool+used RecursiveDo = hasS isMDo+used ParallelListComp = hasS isParComp+used FunctionalDependencies = hasS isFunDep+used ImplicitParams = hasT (un :: IPName S)+used EmptyDataDecls = hasS f+    where f (DataDecl _ _ _ _ [] _) = True+          f (GDataDecl _ _ _ _ _ [] _) = True           f _ = False-used KindSignatures = hasT (un :: Kind)-used BangPatterns = has isPBangPat-used TemplateHaskell = hasT2 (un :: (Bracket,Splice)) & has f+used KindSignatures = hasT (un :: Kind S)+used BangPatterns = hasS isPBangPat+used TemplateHaskell = hasT2 (un :: (Bracket S, Splice S)) & hasS f     where f VarQuote{} = True           f TypQuote{} = True           f _ = False-used ForeignFunctionInterface = hasT (un :: CallConv)-used Generics = has isPExplTypeArg-used PatternGuards = has f1 & has f2+used ForeignFunctionInterface = hasT (un :: CallConv S)+used Generics = hasS isPExplTypeArg+used PatternGuards = hasS f1 & hasS f2     where f1 (GuardedRhs _ xs _) = g xs           f2 (GuardedAlt _ xs _) = g xs           g [] = False-          g [Qualifier _] = False+          g [Qualifier{}] = False           g _ = True-used StandaloneDeriving = has isDerivDecl-used PatternSignatures = has isPatTypeSig-used RecordWildCards = has isPFieldWildcard-used RecordPuns = has isPFieldPun+used StandaloneDeriving = hasS isDerivDecl+used PatternSignatures = hasS isPatTypeSig+used RecordWildCards = hasS isPFieldWildcard+used RecordPuns = hasS isPFieldPun used UnboxedTuples = has isBoxed-used PackageImports = has (isJust . importPkg)-used QuasiQuotes = has isQuasiQuote-used ViewPatterns = has isPViewPat-used Arrows = has f+used PackageImports = hasS (isJust . importPkg)+used QuasiQuotes = hasS isQuasiQuote+used ViewPatterns = hasS isPViewPat+used Arrows = hasS f     where f Proc{} = True           f LeftArrApp{} = True           f RightArrApp{} = True           f LeftArrHighApp{} = True           f RightArrHighApp{} = True           f _ = False-used TransformListComp = has f+used TransformListComp = hasS f     where f QualStmt{} = False           f _ = True @@ -97,6 +98,9 @@  hasT t x = not $ null (universeBi x `asTypeOf` [t]) hasT2 ~(t1,t2) = hasT t1 & hasT t2++hasS :: (Data (f S), Data x, Functor f) => (f S -> Bool) -> x -> Bool+hasS test = any test . universeBi  has f = any f . universeBi 
src/Hint/Import.hs view
@@ -33,6 +33,7 @@  import HSE.All import Type+import Hint import Util import Data.List import Data.Maybe@@ -40,23 +41,23 @@  importHint :: ModuHint importHint _ x = concatMap (wrap . snd) $ groupSortFst-                 [((importModule i,importPkg i),i) | i <- universeBi x, not $ importSrc i]+                 [((fromNamed $ 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)+wrap :: [ImportDecl S] -> [Idea]+wrap o = [ rawIdea Error "Use fewer imports" (toSrcLoc $ ann $ head o) (f o) (f x)          | Just x <- [simplify o]]     where f = unlines . map prettyPrint  -simplify :: [ImportDecl] -> Maybe [ImportDecl]+simplify :: [ImportDecl S] -> Maybe [ImportDecl S] 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 :: ImportDecl S -> [ImportDecl S] -> Maybe [ImportDecl S] simplifyHead x [] = Nothing simplifyHead x (y:ys) = case reduce x y of     Nothing -> fmap (y:) $ simplifyHead x ys@@ -71,16 +72,16 @@ -- importAs :: Maybe ModuleName -- importSpecs :: Maybe (Bool, [ImportSpec]) -reduce :: ImportDecl -> ImportDecl -> Maybe ImportDecl+reduce :: ImportDecl S -> ImportDecl S -> Maybe (ImportDecl S) 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, Just (ImportSpecList _ False xs) <- importSpecs x, Just (ImportSpecList _ False ys) <- importSpecs y =+                Just x{importSpecs = Just $ ImportSpecList an False $ nub_ $ xs ++ ys}            | qual, as, isNothing (importSpecs x) || isNothing (importSpecs y) = Just x{importSpecs=Nothing}            | not (importQualified x), qual, specs, length ass == 1 = Just x{importAs=Just $ head ass}     where         qual = importQualified x == importQualified y-        as = importAs x == importAs y+        as = importAs x `eqMaybe` importAs y         ass = mapMaybe importAs [x,y]-        specs = importSpecs x == importSpecs y+        specs = importSpecs x `eqMaybe` importSpecs y  reduce _ _ = Nothing
src/Hint/Lambda.hs view
@@ -26,9 +26,6 @@ h a = f ((++) a) a -- (a ++) h a = flip f x (y z) -- f (y z) x h a = flip f x $ y z-type Test a = Foo Char a-type Test a = Foo a Char a-type Test (a :: * -> *) = Foo Char a yes = foo (\x -> sum x) -- sum yes = foo (\x l -> sum x x l) -- \x -> sum x x test = foo (\x -> y == x) -- (y ==)@@ -45,103 +42,80 @@  import HSE.All import Type+import Hint import Control.Monad-import Data.Generics.PlateData import Data.Maybe   lambdaHint :: DeclHint-lambdaHint _ _ x@TypeDecl{} = lambdaType x-lambdaHint _ _ x = concatMap (uncurry lambdaExp) (universeExp nullSrcLoc x) ++ concatMap lambdaDecl (universe x)+lambdaHint _ _ x = concatMap lambdaExp (universeBi x) ++ concatMap lambdaDecl (universe x)  -lambdaExp :: SrcLoc -> Exp -> [Idea]-lambdaExp _ o@(Lambda loc [v] y) | isAtom y, Just x <- f v, x `notElem` universeBi y =-        [warn "Use const" loc o res]+lambdaExp :: Exp_ -> [Idea]+lambdaExp o@(Lambda _ [v] y) | isAtom y, Just x <- f v, x `notElem` universeBi y =+        [warn "Use const" o res]     where-        f (PVar x) = Just x-        f PWildCard = Just $ Ident "_"+        f (view -> PVar_ x) = Just x+        f PWildCard{} = Just "_"         f _ = Nothing-        res = App (toNamed "const") y-lambdaExp _ o@(Lambda loc vs x) | length vs /= length vs2 =-        [warn "Eta reduce" loc o $ if null vs2 then x2 else Lambda loc vs2 x2]+        res = App an (toNamed "const") y+lambdaExp o@(Lambda _ vs x) | length vs /= length vs2 =+        [warn "Eta reduce" o $ if null vs2 then x2 else Lambda an vs2 x2]     where (vs2,x2) = etaReduces vs x-lambdaExp loc o@(Paren (App (Var x@(UnQual (Symbol _))) y)) | isAtom y =-        [warn "Operator rotate" loc o $ LeftSection y (QVarOp x)]-lambdaExp loc o@(App (App (App flp x) y) z) | flp ~= "flip" =-        [idea Error "Redundant flip" loc o $ App (App x z) y]-lambdaExp _ _ = []+lambdaExp o@(Paren _ (App _ (Var _ x@(UnQual _ Symbol{})) y)) | isAtom y =+        [warn "Operator rotate" o $ LeftSection an y (QVarOp an x)]+lambdaExp o@(App _ (App _ (App _ flp x) y) z) | flp ~= "flip" =+        [idea Error "Redundant flip" o $ App an (App an x z) y]+lambdaExp _ = []  -lambdaDecl :: Decl -> [Idea]-lambdaDecl (PatBind loc (PVar x) typ rhs bind) = lambdaDef $ Match loc x [] typ rhs bind-lambdaDecl (FunBind [x]) = lambdaDef x --only apply to 1-def, because arities must be the same+lambdaDecl :: Decl_ -> [Idea]+lambdaDecl (PatBind _ (PVar _ x) typ rhs bind) = lambdaDef $ Match an x [] rhs bind+lambdaDecl (FunBind _ [x]) = lambdaDef x --only apply to 1-def, because arities must be the same lambdaDecl _ = []  -lambdaDef :: Match -> [Idea]-lambdaDef o@(Match loc name pats typ (UnGuardedRhs bod) (BDecls []))-    | Lambda loc vs y <- bod = [warn "Redundant lambda" loc o $ reform (pats++vs) y]-    | [PVar x, PVar y] <- pats, Just (f,g) <- useOn x y bod =-              [warn "Use on" loc o $ reform [] (ensureBracket1 $ InfixApp f (toNamed "on") g)]-    | (p2,y) <- etaReduces pats bod, length p2 /= length pats = [warn "Eta reduce" loc o $ reform p2 y]+lambdaDef :: Match S -> [Idea]+lambdaDef o@(Match _ name pats (UnGuardedRhs _ bod) Nothing)+    | Lambda loc vs y <- bod = [warn "Redundant lambda" o $ reform (pats++vs) y]+    | [PVar _ x, PVar _ y] <- pats, Just (f,g) <- useOn x y bod =+              [warn "Use on" o $ reform [] (ensureBracket1 $ InfixApp an f (toNamed "on") g)]+    | (p2,y) <- etaReduces pats bod, length p2 /= length pats = [warn "Eta reduce" o $ reform p2 y]     | otherwise = []-        where reform pats2 bod2 = Match loc name pats2 typ (UnGuardedRhs bod2) (BDecls [])+        where reform pats2 bod2 = Match an name pats2 (UnGuardedRhs an bod2) Nothing+lambdaDef (InfixMatch an p1 name p2 rhs binds) = lambdaDef $ Match an name [p1,p2] rhs binds lambdaDef _ = []   -- given x y, f (g x) (g y) = Just (f, g)-useOn :: Name -> Name -> Exp -> Maybe (Exp, Exp)+useOn :: Name S -> Name S -> Exp_ -> Maybe (Exp_, Exp_) useOn x1 y1 (view -> App2 f (view -> App1 g1 x2) (view -> App1 g2 y2))-    | fromNamed f `elem` ["==",">=",">","!=","<","<="] && g1 == g2, map (Var . UnQual) [x1,y1] == [x2,y2]+    | fromNamed f `elem` ["==",">=",">","!=","<","<="] && g1 =~= g2, map (Var an . UnQual an) [x1,y1] `eqList` [x2,y2]     = Just (f,g1) useOn _ _ _ = Nothing  -etaReduces :: [Pat] -> Exp -> ([Pat], Exp)-etaReduces ps x | ps /= [], PVar p <- last ps, p /= Ident "mr", Just y <- etaReduce p x = etaReduces (init ps) y+etaReduces :: [Pat S] -> Exp_ -> ([Pat S], Exp_)+etaReduces ps x | ps /= [], PVar_ p <- view $ last ps, p /= "mr", Just y <- etaReduce p x = etaReduces (init ps) y                 | otherwise = (ps,x)  -etaReduce :: Name -> Exp -> Maybe Exp-etaReduce x (App y (Var (UnQual z))) | x == z && x `notElem` universeBi y = Just y-etaReduce x (InfixApp y op z) | f y z = Just $ RightSection op z-                              | f z y = Just $ LeftSection y op-    where f y z = op `notElem` map (toNamed . return) "+-" &&-                  all (not . isInfixApp) [y,z] && var x == y && x `notElem` universeBi z-etaReduce x (App y z) | not (uglyEta y z) && x `notElem` universeBi y = do+etaReduce :: String -> Exp_ -> Maybe Exp_+etaReduce x (App _ y (view -> Var_ z)) | x == z && x `notElem` vars y = Just y+etaReduce x (InfixApp _ y op z) | f y z = Just $ RightSection an op z+                                | f z y = Just $ LeftSection an y op+    where f y z = prettyPrint op `notElem` ["+","-"] &&+                  all (not . isInfixApp) [y,z] && view y == Var_ x && x `notElem` vars z+etaReduce x (App _ y z) | not (uglyEta y z) && x `notElem` vars y = do     z2 <- etaReduce x z-    return $ InfixApp y (toNamed ".") z2-etaReduce x (view -> App2 dollar y z) | dollar ~= "$" = etaReduce x (App y z)-etaReduce x (LeftSection y op) = etaReduce x $ App (opExp op) y+    return $ InfixApp an y (toNamed ".") z2+etaReduce x (view -> App2 dollar y z) | dollar ~= "$" = etaReduce x (App an y z)+etaReduce x (LeftSection _ y op) = etaReduce x $ App an (opExp op) y etaReduce x y | isParen y = etaReduce x (fromParen y) etaReduce x y = Nothing   -- (f (g x)) (h y), ugly if g == h-uglyEta :: Exp -> Exp -> Bool-uglyEta (fromParen -> App f (fromParen -> App g x)) (fromParen -> App h y) = g == h+uglyEta :: Exp_ -> Exp_ -> Bool+uglyEta (fromParen -> App _ f (fromParen -> App _ g x)) (fromParen -> App _ h y) = g =~= h uglyEta _ _ = False------ NOTE: Never perform lambda reduction on types--- > type Foo a = Bar a--- can be reduced for type Foo = Bar, only if Bar is--- a data type, not a type alias - but we can't know--- which it is-lambdaType :: Decl -> [Idea]-lambdaType o@(TypeDecl src name args typ) = []-{--        [warn "Type eta reduce" src o t2 | i /= 0]-    where-        (i,t) = f (reverse args) typ-        t2 = TypeDecl src name (take (length args - i) args) t-    -        -- return the number you managed to delete-        f :: [TyVarBind] -> Type -> (Int, Type)-        f (UnkindedVar x:xs) (TyApp t1 (TyVar v))-            | fromNamed v == fromNamed x && x `notElem` universeBi t1-            = first (+1) $ f xs t1-        f _ t = (0,t)--}
src/Hint/List.hs view
@@ -25,21 +25,22 @@  import HSE.All import Type+import Hint   listHint :: DeclHint listHint _ _ = listDecl -listDecl :: Decl -> [Idea]-listDecl x = concatMap (listExp False) (children0Exp nullSrcLoc x) ++-             concatMap (stringType (declSrcLoc x)) (childrenBi x)+listDecl :: Decl_ -> [Idea]+listDecl x = concatMap (listExp False) (childrenBi x) +++             concatMap stringType (childrenBi x)  -- boolean = are you in a ++ chain-listExp :: Bool -> (SrcLoc,Exp) -> [Idea]-listExp b (loc,x) =-        if null res then concatMap (listExp $ isAppend x) $ children1Exp loc x else [head res]+listExp :: Bool -> Exp_ -> [Idea]+listExp b x =+        if null res then concatMap (listExp $ isAppend x) $ children x else [head res]     where-        res = [warn name loc x x2 | (name,f) <- checks, Just x2 <- [f b x]]+        res = [warn name x x2 | (name,f) <- checks, Just x2 <- [f b x]]   isAppend (view -> App2 op _ _) = op ~= "++"@@ -53,29 +54,30 @@          ]  -useString b (List xs) | xs /= [] && all isChar xs = Just $ Lit $ String $ map fromChar xs+useString b (List _ xs) | xs /= [] && all isChar xs = Just $ Lit an $ String an s (show s)+    where s = map fromChar xs useString b _ = Nothing -useList b = fmap List . f True+useList b = fmap (List an) . f True     where         f first x | x ~= "[]" = if first then Nothing else Just []         f first (view -> App2 c a b) | c ~= ":" = fmap (a:) $ f False b         f first _ = Nothing  useCons False (view -> App2 op x y) | op ~= "++", Just x2 <- f x, not $ isAppend y =-        Just $ InfixApp x2 (QConOp list_cons_name) y+        Just $ InfixApp an x2 (QConOp an $ list_cons_name an) y     where-        f (Lit (String [x])) = Just $ Lit $ Char x-        f (List [x]) = Just $ paren x+        f (Lit _ (String _ [x] _)) = Just $ Lit an $ Char an x (show x)+        f (List _ [x]) = Just $ paren x         f _ = Nothing useCons _ _ = Nothing   -typeListChar = TyList (TyCon (toNamed "Char"))-typeString = TyCon (toNamed "String")+typeListChar = TyList an (TyCon an (toNamed "Char"))+typeString = TyCon an (toNamed "String")  -stringType :: SrcLoc -> Type -> [Idea]-stringType loc x = [warn "Use String" loc x (transform f x) | typeListChar `elem` universe x]-    where f x = if x == typeListChar then typeString else x+stringType :: Type_ -> [Idea]+stringType x = [warn "Use String" x (transform f x) | any (=~= typeListChar) $ universe x]+    where f x = if x =~= typeListChar then typeString else x
src/Hint/ListRec.hs view
@@ -25,6 +25,7 @@ module Hint.ListRec(listRecHint) where  import Type+import Hint import Util import HSE.All import Data.List@@ -32,7 +33,6 @@ import Data.Ord import Data.Either import Control.Monad-import Data.Generics.PlateData   listRecHint :: DeclHint@@ -42,9 +42,7 @@             let x = o             (x, addCase) <- findCase x             (use,rank,x) <- matchListRec x-            let res = addCase x-                loc = headDef nullSrcLoc $ universeBi o-            return $ idea rank ("Use " ++ use) loc o res+            return $ idea rank ("Use " ++ use) o $ addCase x   recursive = toNamed "_recursive_"@@ -52,15 +50,15 @@ -- recursion parameters, nil-case, (x,xs,cons-case) -- for cons-case delete any recursive calls with xs from them -- any recursive calls are marked "_recursive_"-data ListCase = ListCase [Name] Exp (Name,Name,Exp)+data ListCase = ListCase [String] Exp_ (String,String,Exp_)                 deriving Show  -data BList = BNil | BCons Name Name+data BList = BNil | BCons String String              deriving (Eq,Ord,Show)  -- function name, parameters, list-position, list-type, body (unmodified)-data Branch = Branch Name [Name] Int BList Exp+data Branch = Branch String [String] Int BList Exp_               deriving Show  @@ -69,47 +67,47 @@ -- MATCH THE RECURSION  -matchListRec :: ListCase -> Maybe (String,Rank,Exp)-matchListRec o@(ListCase vars nil (x,xs,cons))+matchListRec :: ListCase -> Maybe (String,Rank,Exp_)+matchListRec o@(ListCase vs nil (x,xs,cons))     -    | [] <- vars, nil ~= "[]", InfixApp lhs c rhs <- cons, opExp c ~= ":"-    , fromParen rhs == recursive, Var (UnQual xs) `notElem` universe lhs+    | [] <- vs, nil ~= "[]", InfixApp _ lhs c rhs <- cons, opExp c ~= ":"+    , fromParen rhs =~= recursive, xs `notElem` vars lhs     = Just $ (,,) "map" Error $ appsBracket-        [toNamed "map", lambda [x] lhs, Var $ UnQual xs]+        [toNamed "map", lambda [x] lhs, toNamed xs] -    | [] <- vars, App2 op lhs rhs <- view cons-    , null $ universe op `intersect` [Var (UnQual x), Var (UnQual xs)]-    , fromParen rhs == recursive, Var (UnQual xs) `notElem` universe lhs+    | [] <- vs, App2 op lhs rhs <- view cons+    , null $ vars op `intersect` [x,xs]+    , fromParen rhs == recursive, xs `notElem` vars lhs     = Just $ (,,) "foldr" Warning $ appsBracket-        [toNamed "foldr", lambda [x] $ appsBracket [op,lhs], nil, Var $ UnQual xs]+        [toNamed "foldr", lambda [x] $ appsBracket [op,lhs], nil, toNamed xs] -    | [v] <- vars, Var (UnQual v) == nil, App r lhs <- cons, r == recursive-    , Var (UnQual xs) `notElem` universe lhs+    | [v] <- vs, view nil == Var_ v, App _ r lhs <- cons, r =~= recursive+    , xs `notElem` vars lhs     = Just $ (,,) "foldl" Warning $ appsBracket-        [toNamed "foldl", lambda [v,x] lhs, Var $ UnQual v, Var $ UnQual xs]+        [toNamed "foldl", lambda [v,x] lhs, toNamed v, toNamed xs] -    | [v] <- vars, App ret res <- nil, ret ~= "return", res ~= "()" || res == Var (UnQual v)-    , [Generator _ (PVar b1) e, Qualifier (fromParen -> App r (Var (UnQual b2)))] <- asDo cons-    , b1 == b2, r == recursive, Var (UnQual xs) `notElem` universe e+    | [v] <- vs, App _ ret res <- nil, ret ~= "return", res ~= "()" || view res == Var_ v+    , [Generator _ (view -> PVar_ b1) e, Qualifier _ (fromParen -> App _ r (view -> Var_ b2))] <- asDo cons+    , b1 == b2, r == recursive, xs `notElem` vars e     , name <- "foldM" ++ ['_'|res ~= "()"]     = Just $ (,,) name Warning $ appsBracket-        [toNamed name, lambda [v,x] e, Var $ UnQual v, Var $ UnQual xs]+        [toNamed name, lambda [v,x] e, toNamed v, toNamed xs]      | otherwise = Nothing   -- Very limited attempt to convert >>= to do, only useful for foldM/foldM_-asDo :: Exp -> [Stmt]-asDo (view -> App2 bind lhs (Lambda src [v] rhs)) = [Generator src v lhs, Qualifier rhs]-asDo (Do x) = x-asDo x = [Qualifier x]+asDo :: Exp_ -> [Stmt S]+asDo (view -> App2 bind lhs (Lambda _ [v] rhs)) = [Generator an v lhs, Qualifier an rhs]+asDo (Do _ x) = x+asDo x = [Qualifier an x]  --------------------------------------------------------------------- -- FIND THE CASE ANALYSIS -findCase :: Decl -> Maybe (ListCase, Exp -> Decl)+findCase :: Decl_ -> Maybe (ListCase, Exp_ -> Decl_) findCase x = do-    FunBind [x1,x2] <- return x+    FunBind _ [x1,x2] <- return x     Branch name1 ps1 p1 c1 b1 <- findBranch x1     Branch name2 ps2 p2 c2 b2 <- findBranch x2     guard (name1 == name2 && ps1 == ps2 && p1 == p2)@@ -117,24 +115,24 @@     b2 <- transformAppsM (delCons name1 p1 xs) b2     (ps,b2) <- return $ eliminateArgs ps1 b2 -    let ps12 = let (a,b) = splitAt p1 ps1 in map PVar $ a ++ xs : b+    let ps12 = let (a,b) = splitAt p1 ps1 in map toNamed $ a ++ xs : b     return (ListCase ps b1 (x,xs,b2)-           ,\e -> FunBind [Match nullSrcLoc name1 ps12 Nothing (UnGuardedRhs e) (BDecls [])])+           ,\e -> FunBind an [Match an (toNamed name1) ps12 (UnGuardedRhs an e) Nothing])  -delCons :: Name -> Int -> Name -> Exp -> Maybe Exp-delCons func pos var (fromApps -> Var (UnQual x):xs) | func == x = do-    (pre,Var (UnQual v):post) <- return $ splitAt pos xs+delCons :: String -> Int -> String -> Exp_ -> Maybe Exp_+delCons func pos var (fromApps -> (view -> Var_ x):xs) | func == x = do+    (pre, (view -> Var_ v):post) <- return $ splitAt pos xs     guard $ v == var     return $ apps $ recursive : pre ++ post delCons _ _ _ x = return x  -eliminateArgs :: [Name] -> Exp -> ([Name], Exp)+eliminateArgs :: [String] -> Exp_ -> ([String], Exp_) eliminateArgs ps cons = (remove ps, transform f cons)     where-        args = [zs | z:zs <- map fromApps $ universeApps cons, z == recursive]-        elim = [all (\xs -> length xs > i && xs !! i == Var (UnQual p)) args | (i,p) <- zip [0..] ps] ++ repeat False+        args = [zs | z:zs <- map fromApps $ universeApps cons, z =~= recursive]+        elim = [all (\xs -> length xs > i && view (xs !! i) == Var_ p) args | (i,p) <- zip [0..] ps] ++ repeat False         remove = concat . zipWith (\b x -> [x | not b]) elim          f (fromApps -> x:xs) | x == recursive = apps $ x : remove xs@@ -144,14 +142,14 @@ --------------------------------------------------------------------- -- FIND A BRANCH -findBranch :: Match -> Maybe Branch+findBranch :: Match S -> Maybe Branch findBranch x = do-    Match _ name ps Nothing (UnGuardedRhs bod) (BDecls []) <- return x+    Match _ name ps (UnGuardedRhs _ bod) Nothing <- return x     (a,b,c) <- findPat ps-    return $ Branch name a b c bod+    return $ Branch (fromNamed name) a b c bod  -findPat :: [Pat] -> Maybe ([Name], Int, BList)+findPat :: [Pat_] -> Maybe ([String], Int, BList) findPat ps = do     ps <- mapM readPat ps     [i] <- return $ findIndices isRight ps@@ -159,10 +157,10 @@     return (left, i, right)  -readPat :: Pat -> Maybe (Either Name BList)-readPat (PVar x) = Just $ Left x-readPat (PParen (PInfixApp (PVar x) (Special Cons) (PVar xs))) = Just $ Right $ BCons x xs-readPat (PList []) = Just $ Right BNil+readPat :: Pat_ -> Maybe (Either String BList)+readPat (view -> PVar_ x) = Just $ Left x+readPat (PParen _ (PInfixApp _ (view -> PVar_ x) (Special _ Cons{}) (view -> PVar_ xs))) = Just $ Right $ BCons x xs+readPat (PList _ []) = Just $ Right BNil readPat _ = Nothing  @@ -170,22 +168,22 @@ -- UTILITY FUNCTIONS  -- a list of application, with any necessary brackets-appsBracket :: [Exp] -> Exp-appsBracket = foldl1 (\x -> ensureBracket1 . App x)+appsBracket :: [Exp_] -> Exp_+appsBracket = foldl1 (\x -> ensureBracket1 . App an x)   -- generate a lambda, but prettier (if possible)-lambda :: [Name] -> Exp -> Exp-lambda xs (Paren x) = lambda xs x-lambda xs (Lambda s (PVar v:vs) x) = lambda (xs++[v]) (Lambda s vs x)+lambda :: [String] -> Exp_ -> Exp_+lambda xs (Paren _ x) = lambda xs x+lambda xs (Lambda _ ((view -> PVar_ v):vs) x) = lambda (xs++[v]) (Lambda an vs x) lambda xs (Lambda _ [] x) = lambda xs x-lambda [x] (App a b) | Var (UnQual x) == b = a-lambda [x] (App a (Paren (App b c)))-    | isAtom a && isAtom b && Var (UnQual x) == c = InfixApp a (toNamed ".") b-lambda [x] (InfixApp a op b)-    | a == Var (UnQual x) = RightSection op b-    | b == Var (UnQual x) = LeftSection a op-lambda [x,y] (view -> App2 op x1 y1)-    | x1 == Var (UnQual x) && y1 == Var (UnQual y) = op-    | x1 == Var (UnQual y) && y1 == Var (UnQual x) = App (toNamed "flip") op-lambda ps x = Lambda nullSrcLoc (map PVar ps) x+lambda [x] (App _ a (view -> Var_ b)) | x == b = a+lambda [x] (App _ a (Paren _ (App _ b (view -> Var_ c))))+    | isAtom a && isAtom b && x == c = InfixApp an a (toNamed ".") b+lambda [x] (InfixApp _ a op b)+    | view a == Var_ x = RightSection an op b+    | view b == Var_ x = LeftSection an a op+lambda [x,y] (view -> App2 op (view -> Var_ x1) (view -> Var_ y1))+    | x1 == x && y1 == y = op+    | x1 == y && y1 == x = App an (toNamed "flip") op+lambda ps x = Lambda an (map toNamed ps) x
src/Hint/Match.hs view
@@ -13,6 +13,7 @@ import Data.List import Data.Maybe import Type+import Hint import HSE.All import Control.Monad import Data.Function@@ -27,16 +28,16 @@ readMatch = findIdeas . filter isMatchExp  -findIdeas :: [Setting] -> NameMatch -> Module -> Decl -> [Idea]+findIdeas :: [Setting] -> NameMatch -> Module S -> Decl_ -> [Idea] findIdeas matches nm _ decl =-  [ idea (rankS m) (hintS m) loc x y-  | (loc, x) <- universeExp nullSrcLoc decl, not $ isParen x+  [ idea (rankS m) (hintS m) x y+  | x <- universeBi decl, not $ isParen x   , m <- matches, Just y <- [matchIdea nm m x]]  -matchIdea :: NameMatch -> Setting -> Exp -> Maybe Exp+matchIdea :: NameMatch -> Setting -> Exp_ -> Maybe Exp_ matchIdea nm MatchExp{lhs=lhs,rhs=rhs,side=side} x = do-    u <- unify nm lhs x+    u <- unify nm (fmap (const an) lhs) (fmap (const an) x)     u <- check u     guard $ checkSide side u     let rhs2 = subst u rhs@@ -45,59 +46,57 @@   -- unify a b = c, a[c] = b-unify :: NameMatch -> Exp -> Exp -> Maybe [(String,Exp)]-unify nm (Do xs) (Do ys) | length xs == length ys = concatZipWithM (unifyStmt nm) xs ys+unify :: NameMatch -> Exp_ -> Exp_ -> Maybe [(String,Exp_)]+unify nm (Do _ xs) (Do _ ys) | length xs == length ys = concatZipWithM (unifyStmt nm) xs ys unify nm (Lambda _ xs x) (Lambda _ ys y) | length xs == length ys = liftM2 (++) (unify nm x y) (concatZipWithM unifyPat xs ys) unify nm x y | isParen x || isParen y = unify nm (fromParen x) (fromParen y)-unify nm (Var (fromNamed -> v)) y | isUnifyVar v = Just [(v,y)]-unify nm (Var x) (Var y) | nm x y = Just []+unify nm (Var _ (fromNamed -> v)) y | isUnifyVar v = Just [(v,y)]+unify nm (Var _ x) (Var _ y) | nm x y = Just [] unify nm x y | ((==) `on` descend (const $ toNamed "_")) x y = concatZipWithM (unify nm) (children x) (children y) unify nm x o@(view -> App2 op y1 y2)-  | op ~= "$" = unify nm x $ y1 `App` y2+  | op ~= "$" = unify nm x $ App an y1 y2   | op ~= "." = unify nm x $ dotExpand o-unify nm x (InfixApp lhs op rhs) = unify nm x (opExp op `App` lhs `App` rhs)+unify nm x (InfixApp _ lhs op rhs) = unify nm x $ App an (App an (opExp op) lhs) rhs unify nm _ _ = Nothing  -unifyStmt :: NameMatch -> Stmt -> Stmt -> Maybe [(String,Exp)]+unifyStmt :: NameMatch -> Stmt S -> Stmt S -> Maybe [(String,Exp_)] unifyStmt nm (Generator _ p1 x1) (Generator _ p2 x2) = liftM2 (++) (unifyPat p1 p2) (unify nm x1 x2)-unifyStmt nm x y | ((==) `on` descendBi (const (toNamed "_" :: Exp))) x y = concatZipWithM (unify nm) (childrenBi x) (childrenBi y)+unifyStmt nm x y | ((==) `on` descendBi (const (toNamed "_" :: Exp_))) x y = concatZipWithM (unify nm) (childrenBi x) (childrenBi y) unifyStmt nm _ _ = Nothing  -unifyPat :: Pat -> Pat -> Maybe [(String,Exp)]-unifyPat (PVar x) (PVar y) = Just [(fromNamed x, toNamed $ fromNamed y)]-unifyPat PWildCard (PVar _) = Just []-unifyPat x y | ((==) `on` descend (const PWildCard)) x y = concatZipWithM unifyPat (children x) (children y)+unifyPat :: Pat_ -> Pat_ -> Maybe [(String,Exp_)]+unifyPat (PVar _ x) (PVar _ y) = Just [(fromNamed x, toNamed $ fromNamed y)]+unifyPat PWildCard{} PVar{} = Just []+unifyPat x y | ((==) `on` descend (const $ PWildCard an)) x y = concatZipWithM unifyPat (children x) (children y) unifyPat _ _ = Nothing  -concatZipWithM f xs = liftM concat . zipWithM f xs-- -- check the unification is valid-check :: [(String,Exp)] -> Maybe [(String,Exp)]+check :: [(String,Exp_)] -> Maybe [(String,Exp_)] check = mapM f . groupSortFst     where f (x,ys) = if length (nub ys) == 1 then Just (x,head ys) else Nothing  -checkSide :: Maybe Exp -> [(String,Exp)] -> Bool+checkSide :: Maybe Exp_ -> [(String,Exp_)] -> Bool checkSide Nothing  bind = True checkSide (Just x) bind = f x     where-        f (InfixApp x op y)+        f (InfixApp _ x op y)             | opExp op ~= "&&" = f x && f y             | opExp op ~= "||" = f x || f y-        f (Paren x) = f x-        f (App x (Var y))+        f (Paren _ x) = f x+        f (App _ x (Var _ y))             | 'i':'s':typ <- fromNamed x, Just e <- lookup (fromNamed y) bind             = if typ == "Atom" then isAtom e               else head (words $ show e) == typ-        f (App (App nin xs) ys) | nin ~= "notIn" = and [notIn x y | x <- g xs, y <- g ys]+        f (App _ (App _ nin xs) ys) | nin ~= "notIn" = and [notIn x y | x <- g xs, y <- g ys]+        f x | x ~= "notTypeSafe" = True         f x = error $ "Hint.Match.checkSide, unknown side condition: " ++ prettyPrint x -        g :: Exp -> [Exp]-        g (List xs) = xs+        g :: Exp_ -> [Exp_]+        g (List _ xs) = xs         g x = [x]          notIn x y = fromMaybe False $ do@@ -108,45 +107,45 @@  -- If they have have a lambda in the pattern -- don't allow dot contraction to happen, as it's usually wrong-checkDot :: Exp -> Exp -> Bool-checkDot lhs rhs2 = not $ any isLambda (universeBi lhs) && toNamed "?" `elem` universe rhs2+checkDot :: Exp_ -> Exp_ -> Bool+checkDot lhs rhs2 = not $ any isLambda (universeS lhs) && toNamed "?" `elem` universe rhs2   -- perform a substitution-subst :: [(String,Exp)] -> Exp -> Exp+subst :: [(String,Exp_)] -> Exp_ -> Exp_ subst bind = transform g . transformBracket f     where-        f (Var (fromNamed -> x)) | isUnifyVar x = lookup x bind+        f (Var _ (fromNamed -> x)) | isUnifyVar x = lookup x bind         f _ = Nothing -        g (App np (Paren x)) | np ~= "_noParen_" = x+        g (App _ np (Paren _ x)) | np ~= "_noParen_" = x         g x = x  -dotExpand :: Exp -> Exp-dotExpand (view -> App2 op x1 x2) | op ~= "." = ensureBracket1 $ App x1 (dotExpand x2)-dotExpand x = ensureBracket1 $ App x (toNamed "?")+dotExpand :: Exp_ -> Exp_+dotExpand (view -> App2 op x1 x2) | op ~= "." = ensureBracket1 $ App an x1 (dotExpand x2)+dotExpand x = ensureBracket1 $ App an x (toNamed "?")   -- simplify, removing any introduced ? vars, from expanding (.)-dotContract :: Exp -> Exp+dotContract :: Exp_ -> Exp_ dotContract x = fromMaybe x (f x)     where         f x | isParen x = f $ fromParen x-        f (App x y) | "?" <- fromNamed y = Just x-                    | Just z <- f y = Just $ InfixApp x (toNamed ".") z+        f (App _ x y) | "?" <- fromNamed y = Just x+                      | Just z <- f y = Just $ InfixApp an x (toNamed ".") z         f _ = Nothing  -- if it has _eval_ do evaluation on it-performEval :: Exp -> Exp-performEval (App e x) | e ~= "_eval_" = evaluate x+performEval :: Exp_ -> Exp_+performEval (App _ e x) | e ~= "_eval_" = evaluate x performEval x = x   -- contract Data.List.foo ==> foo, if Data.List is loaded-unqualify :: NameMatch -> Exp -> Exp+unqualify :: NameMatch -> Exp_ -> Exp_ unqualify nm = transformBi f     where-        f (Qual mod x) | nm (Qual mod x) (UnQual x) = UnQual x+        f (Qual _ mod x) | nm (Qual an mod x) (UnQual an x) = UnQual an x         f x = x 
src/Hint/Monad.hs view
@@ -36,59 +36,60 @@ import Data.List import HSE.All import Type+import Hint   badFuncs = ["mapM","foldM","forM","replicateM","sequence","zipWithM"]   monadHint :: DeclHint-monadHint _ _ = concatMap monadExp . universeExp nullSrcLoc+monadHint _ _ = concatMap monadExp . universeBi -monadExp :: (SrcLoc,Exp) -> [Idea]-monadExp (loc,x) = case x of+monadExp :: Exp_ -> [Idea]+monadExp x = case x of         (view -> App2 op x1 x2) | op ~= ">>" -> f x1-        Do xs -> [idea Error "Redundant return" loc x y | Just y <- [monadReturn xs]] ++-                 [idea Error "Use join" loc x (Do y) | Just y <- [monadJoin xs]] ++-                 [idea Error "Redundant do" loc x y | [Qualifier y] <- [xs]] ++-                 [idea Error "Use let" loc x (Do y) | Just y <- [monadLet xs]] ++-                 concat [f x | Qualifier x <- init xs]+        Do _ xs -> [idea Error "Redundant return" x y | Just y <- [monadReturn xs]] +++                   [idea Error "Use join" x (Do an y) | Just y <- [monadJoin xs]] +++                   [idea Error "Redundant do" x y | [Qualifier _ y] <- [xs]] +++                   [idea Error "Use let" x (Do an y) | Just y <- [monadLet xs]] +++                   concat [f x | Qualifier _ x <- init xs]         _ -> []     where-        f x = [idea Error ("Use " ++ name) loc x y+        f x = [idea Error ("Use " ++ name) x y               |Just (name,y) <- [monadCall x]]   -- see through Paren and down if/case etc-monadCall :: Exp -> Maybe (String,Exp)-monadCall (Paren x) = liftM (second Paren) $ monadCall x-monadCall (App x y) = liftM (second (`App` y)) $ monadCall x+monadCall :: Exp_ -> Maybe (String,Exp_)+monadCall (Paren _ x) = fmap (second $ Paren an) $ monadCall x+monadCall (App _ x y) = fmap (second $ \x -> App an x y) $ monadCall x monadCall x | x:_ <- filter (x ~=) badFuncs = let x2 = x ++ "_" in  Just (x2, toNamed x2) monadCall _ = Nothing  -monadReturn (reverse -> Qualifier (App ret (Var v)):Generator _ (PVar p) x:rest)+monadReturn (reverse -> Qualifier _ (App _ ret (Var _ v)):Generator _ (PVar _ p) x:rest)     | ret ~= "return", fromNamed v == fromNamed p-    = Just $ Do $ reverse $ Qualifier x : rest+    = Just $ Do an $ reverse $ Qualifier an x : rest monadReturn _ = Nothing  -monadJoin (Generator _ (PVar p) x:Qualifier (Var v):xs)-    | fromNamed p == fromNamed v && Var v `notElem` universeBi xs-    = Just $ Qualifier (ensureBracket1 $ App (toNamed "join") x) : fromMaybe xs (monadJoin xs)-monadJoin (x:xs) = liftM (x:) $ monadJoin xs+monadJoin (Generator _ (view -> PVar_ p) x:Qualifier _ (view -> Var_ v):xs)+    | p == v && v `notElem` vars xs+    = Just $ Qualifier an (ensureBracket1 $ App an (toNamed "join") x) : fromMaybe xs (monadJoin xs)+monadJoin (x:xs) = fmap (x:) $ monadJoin xs monadJoin [] = Nothing   monadLet xs = if xs == ys then Nothing else Just ys     where         ys = map mkLet xs-        vars = [v | Generator _ p _ <- xs, PVar v <- universe p]-        mkLet (Generator sl (PVar p) (fromRet -> Just y))-            | p `notElem` [v | Var (UnQual v) <- universeBi y], p `notElem` delete p vars-            = LetStmt $ BDecls [PatBind sl (PVar p) Nothing (UnGuardedRhs y) (BDecls [])]+        vs = concatMap pvars [p | Generator _ p _ <- xs]+        mkLet (Generator _ (view -> PVar_ p) (fromRet -> Just y))+            | p `notElem` vars y, p `notElem` delete p vs+            = LetStmt an $ BDecls an [PatBind an (toNamed p) Nothing (UnGuardedRhs an y) Nothing]         mkLet x = x -fromRet (Paren x) = fromRet x-fromRet (InfixApp x y z) | opExp y ~= "$" = fromRet $ App x z-fromRet (App x y) | x ~= "return" = Just y+fromRet (Paren _ x) = fromRet x+fromRet (InfixApp _ x y z) | opExp y ~= "$" = fromRet $ App an x z+fromRet (App _ x y) | x ~= "return" = Just y fromRet _ = Nothing
src/Hint/Naming.hs view
@@ -26,6 +26,7 @@  import HSE.All import Type+import Hint import Data.List import Data.Char import Data.Maybe@@ -33,32 +34,32 @@   namingHint :: DeclHint-namingHint _ modu = naming $ Set.fromList [x | Ident x <- universeBi modu]+namingHint _ modu = naming $ Set.fromList [x | Ident _ x <- universeS modu] -naming :: Set.Set String -> Decl -> [Idea]-naming seen x = [warn "Use camelCase" (declSrcLoc x) x2 (replaceNames res x2) | not $ null res]+naming :: Set.Set String -> Decl_ -> [Idea]+naming seen x = [warn "Use camelCase" x2 (replaceNames res x2) | not $ null res]     where res = [(n,y) | n <- nub $ getNames x, Just y <- [suggestName n], not $ y `Set.member` seen]           x2 = shorten x  -shorten :: Decl -> Decl+shorten :: Decl_ -> Decl_ shorten x = case x of-    FunBind (Match a b c d e _:_) -> FunBind [f (Match a b c d) e]+    FunBind sl (Match a b c d _:_) -> FunBind sl [f (Match a b c) d]     PatBind a b c d _ -> f (PatBind a b c) d     x -> x     where-        dots = Var $ UnQual $ Ident "..." -- Must be an Ident, not a Symbol-        f cont (UnGuardedRhs _) = cont (UnGuardedRhs dots) (BDecls [])-        f cont (GuardedRhss _) = cont (GuardedRhss [GuardedRhs nullSrcLoc [Qualifier dots] dots]) (BDecls [])+        dots = Var an $ UnQual an $ Ident an "..." -- Must be an Ident, not a Symbol+        f cont (UnGuardedRhs _ _) = cont (UnGuardedRhs an dots) Nothing+        f cont (GuardedRhss _ _) = cont (GuardedRhss an [GuardedRhs an [Qualifier an dots] dots]) Nothing  -getNames :: Decl -> [String]+getNames :: Decl_ -> [String] getNames x = case x of     FunBind{} -> name     PatBind{} -> name     TypeDecl{} -> name-    DataDecl _ _ _ _ _ cons _ -> name ++ [fromNamed x | QualConDecl _ _ _ x <- cons, x <- f x]-    GDataDecl _ _ _ _ _ _ cons _ -> name ++ [fromNamed x | GadtDecl _ x _ <- cons]+    DataDecl _ _ _ _ cons _ -> name ++ [fromNamed x | QualConDecl _ _ _ x <- cons, x <- f x]+    GDataDecl _ _ _ _ _ cons _ -> name ++ [fromNamed x | GadtDecl _ x _ <- cons]     TypeFamDecl{} -> name     DataFamDecl{} -> name     ClassDecl{} -> name@@ -66,9 +67,9 @@     where         name = [fromNamed x] -        f (ConDecl x _) = [x]-        f (InfixConDecl _ x _) = [x]-        f (RecDecl x ys) = x : concatMap fst ys+        f (ConDecl _ x _) = [x]+        f (InfixConDecl _ _ x _) = [x]+        f (RecDecl _ x ys) = x : concat [y | FieldDecl _ y _ <- ys]   suggestName :: String -> Maybe String
src/Hint/Pragma.hs view
@@ -28,42 +28,43 @@  import HSE.All import Type+import Hint import Data.List import Data.Maybe import Data.Function   pragmaHint :: ModuHint-pragmaHint _ x = languageDupes lang ++ [pragmaIdea old $ [LanguagePragma nullSrcLoc ns2 | ns2 /= []] ++ catMaybes new | old /= []]+pragmaHint _ x = languageDupes lang ++ [pragmaIdea old $ [LanguagePragma an (map toNamed 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]+        ns2 = nub (concat ns) \\ concat [map fromNamed n | LanguagePragma _ n <- lang]  -pragmaIdea :: [OptionPragma] -> [OptionPragma] -> Idea-pragmaIdea xs ys = rawIdea Error "Use better pragmas" (fromJust $ getSrcLoc $ head xs) (f xs) (f ys)+pragmaIdea :: [OptionPragma S] -> [OptionPragma S] -> Idea+pragmaIdea xs ys = rawIdea Error "Use better pragmas" (toSrcLoc $ ann $ head xs) (f xs) (f ys)     where f = unlines . map prettyPrint  -languageDupes :: [OptionPragma] -> [Idea]+languageDupes :: [OptionPragma S] -> [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 (a@(LanguagePragma _ x):xs) =+    (if nub_ x `neqList` x+        then [pragmaIdea [a] [LanguagePragma an $ nub_ x]]+        else [pragmaIdea [a,b] [LanguagePragma an (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 :: String -> Maybe [String]+strToLanguage "-cpp" = Just ["CPP"]+strToLanguage x | "-X" `isPrefixOf` x = Just [drop 2 x]+strToLanguage "-fglasgow-exts" = Just $ map show glasgowExts strToLanguage _ = Nothing  -optToLanguage :: OptionPragma -> Maybe (Maybe OptionPragma, [Name])+optToLanguage :: OptionPragma S -> Maybe (Maybe (OptionPragma S), [String]) optToLanguage (OptionsPragma sl tool val)     | maybe True (== GHC) tool && any isJust vs = Just (res, concat $ catMaybes vs)     where
src/Hint/Structure.hs view
@@ -23,52 +23,50 @@  import HSE.All import Type+import Hint import Util import Data.List import Data.Maybe   structureHint :: DeclHint-structureHint _ _ x = concat [concatMap useGuards xs | FunBind xs <- [x]] ++-                      concatMap useIf (universeExp nullSrcLoc x)+structureHint _ _ x = concat [concatMap useGuards xs | FunBind _ xs <- [x]] +++                      concatMap useIf (universeBi x)  -useGuards :: Match -> [Idea]-useGuards x@(Match a b c d (UnGuardedRhs bod) e) -    | length guards > 2 = [warn "Use guards" a x x2]+useGuards :: Match S -> [Idea]+useGuards x@(Match a b c (UnGuardedRhs d bod) e) +    | length guards > 2 = [warn "Use guards" x x2]     where         guards = asGuards bod-        x2 = Match a b c d (GuardedRhss guards) e+        x2 = Match a b c (GuardedRhss d guards) e -useGuards o@(Match sl b pats d (GuardedRhss [GuardedRhs _ [Generator _ pat (App op (Var (UnQual p)))] bod]) (BDecls decs))-    | Just i <- findIndex (== PVar p) pats-    , p `notElem` (vr bod ++ vr decs)-    , vr op `disjoint` decsBind, pvr pats `disjoint` vr op, pvr pat `disjoint` pvr pats-    = [warn "Use view patterns" sl o $-       Match sl b (take i pats ++ [PParen $ PViewPat op pat] ++ drop (i+1) pats) d (UnGuardedRhs bod) (BDecls decs)]+useGuards o@(Match sl b pats (GuardedRhss _ [GuardedRhs _ [Generator _ pat (App _ op (view -> Var_ p))] bod]) decs)+    | Just i <- findIndex (=~= (toNamed p :: Pat_)) pats+    , p `notElem` (vars bod ++ vars decs)+    , vars op `disjoint` decsBind, pvars pats `disjoint` vars op, pvars pat `disjoint` pvars pats+    = [warn "Use view patterns" o $+       Match sl b (take i pats ++ [PParen an $ PViewPat an op pat] ++ drop (i+1) pats) (UnGuardedRhs an bod) decs]     where-        decsBind = nub $ concatMap declBind decs--        vr x = [y | Var (UnQual y) <- universeBi x]-        pvr x = [y | PVar y <- universeBi x]+        decsBind = nub $ concatMap declBind $ childrenBi decs  useGuards _ = []  -asGuards :: Exp -> [GuardedRhs]-asGuards (Paren x) = asGuards x-asGuards (If a b c) = GuardedRhs nullSrcLoc [Qualifier a] b : asGuards c-asGuards x = [GuardedRhs nullSrcLoc [Qualifier $ toNamed "otherwise"] x]+asGuards :: Exp_ -> [GuardedRhs S]+asGuards (Paren _ x) = asGuards x+asGuards (If _ a b c) = GuardedRhs an [Qualifier an a] b : asGuards c+asGuards x = [GuardedRhs an [Qualifier an $ toNamed "otherwise"] x]  -useIf :: (SrcLoc,Exp) -> [Idea]-useIf (loc,x@(Case on [simpAlt -> Just (as,av), simpAlt -> Just (bs,bv)]))+useIf :: Exp_ -> [Idea]+useIf x@(Case _ on [simpAlt -> Just (as,av), simpAlt -> Just (bs,bv)])     | as == "True"  && bs `elem` ["False","_"] = iff av bv     | as == "False" && bs `elem` ["True" ,"_"] = iff bv av     where-        iff t f = [warn "Use if" loc x (If on t f)]+        iff t f = [warn "Use if" x (If an on t f)] useIf _ = [] -simpAlt (Alt _ p (UnGuardedAlt x) (BDecls [])) = Just (prettyPrint p, x)+simpAlt (Alt _ p (UnGuardedAlt _ x) Nothing) = Just (prettyPrint p, x) simpAlt _ = Nothing 
+ src/Language/Haskell/HLint.hs view
@@ -0,0 +1,4 @@++module Language.Haskell.HLint(hlint) where++import HLint
src/Main.hs view
@@ -1,6 +1,6 @@ {- HLint, Haskell source code suggestions-Copyright (C) 2006-2009, Neil Mitchell+Copyright (C) 2006-2010, Neil Mitchell  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by@@ -16,62 +16,17 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA -} -{-# LANGUAGE RecordWildCards #-}- module Main where -import Control.Arrow+import Language.Haskell.HLint import Control.Monad-import Data.List-import Data.Maybe+import System.Environment import System.Exit -import CmdLine-import Settings-import Report-import Type-import Test-import Util-import Parallel-import Hint.All-import HSE.All--+main :: IO () main = do-    Cmd{..} <- getCmd-    if cmdTest then test else do-        settings <- readSettings cmdHintFiles-        let extra = [Classify Ignore x ("","") | x <- cmdIgnore]-        let apply :: FilePath -> IO [Idea]-            apply = fmap (fmap $ classify $ settings ++ extra) . applyHint parseFlags{cpphs=Just cmdCpphs} (allHints settings)-        ideas <- liftM concat $ parallel [listM' =<< apply x | x <- cmdFiles]-        let visideas = filter (\i -> cmdShowAll || rank i /= Ignore) ideas-        showItem <- if cmdColor then showANSI else return show-        mapM_ (putStrLn . showItem) visideas--        -- figure out statistics        -        let counts = map (head &&& length) $ group $ sort $ map rank ideas-        let [ignore,warn,err] = map (fromMaybe 0 . flip lookup counts) [Ignore,Warning,Error]-        let total = ignore + warn + err-        let shown = if cmdShowAll then total else total - ignore--        let ignored = [show i ++ " ignored" | let i = total - shown, i /= 0]-        let errors = [show err ++ " error" ++ ['s'|err/=1] | err /= 0]--        if shown == 0 then do-            when (cmdReports /= []) $ putStrLn "Skipping writing reports"-            printMsg "No relevant suggestions" ignored-         else do-            forM_ cmdReports $ \x -> do-                putStrLn $ "Writing report to " ++ x ++ " ..."-                writeReport x visideas-            printMsg ("Found " ++ show shown ++ " suggestion" ++ ['s'|shown/=1]) (errors++ignored)--        when (err > 0) $-            exitWith $ ExitFailure 1-+    args <- getArgs+    errs <- hlint args+    when (errs > 0) $+        exitWith $ ExitFailure 1 -printMsg :: String -> [String] -> IO ()-printMsg msg xs =-    putStrLn $ msg ++ if null xs then "" else-        " (" ++ intercalate ", " xs ++ ")"
src/Report.hs view
@@ -13,18 +13,17 @@ import Language.Haskell.HsColour.CSS  -writeTemplate :: [(String,[String])] -> FilePath -> IO ()-writeTemplate content to = do-    dat <- getDataDir-    src <- readFile $ dat </> "report.html"+writeTemplate :: FilePath -> [(String,[String])] -> FilePath -> IO ()+writeTemplate dataDir content to = do+    src <- readFile $ dataDir </> "report.html"     writeFile to $ unlines $ concatMap f $ lines src     where         f ('$':xs) = fromMaybe ['$':xs] $ lookup xs content         f x = [x]  -writeReport :: FilePath -> [Idea] -> IO ()-writeReport file ideas = writeTemplate inner file+writeReport :: FilePath -> FilePath -> [Idea] -> IO ()+writeReport dataDir file ideas = writeTemplate dataDir inner file     where         generateIds :: [String] -> [(String,Int)] -- sorted by name         generateIds = map (head &&& length) . group . sort
src/Settings.hs view
@@ -1,39 +1,36 @@ {-# LANGUAGE PatternGuards, ViewPatterns #-} -module Settings(readSettings, classify) where+module Settings(readSettings, classify, defaultName) where  import HSE.All-import Paths_hlint import Type import Data.Char import Data.List import System.FilePath import Util-import Data.Generics.PlateData+import Data.Generics.Uniplate.Data   -- Given a list of hint files to start from -- Return the list of settings commands-readSettings :: [FilePath] -> IO [Setting]-readSettings xs = do-    (builtin,mods) <- fmap unzipEither $ concatMapM readHints xs+readSettings :: FilePath -> [FilePath] -> IO [Setting]+readSettings dataDir xs = do+    (builtin,mods) <- fmap unzipEither $ concatMapM (readHints dataDir) xs     return $ map Builtin builtin ++ concatMap (concatMap readSetting . concatMap getEquations . moduleDecls) mods   -- read all the files -- in future this should also do import chasing, but -- currently it doesn't-readHints :: FilePath -> IO [Either String Module]-readHints file = do+readHints :: FilePath -> FilePath -> IO [Either String Module_]+readHints dataDir file = do     y <- fromParseResult `fmap` parseFile parseFlags{implies=True} file     ys <- concatMapM (f . fromNamed . importModule) $ moduleImports y     return $ Right y:ys     where         f x | "HLint.Builtin." `isPrefixOf` x = return [Left $ drop 14 x]-            | "HLint." `isPrefixOf` x = do-                dat <- getDataDir-                readHints $ dat </> drop 6 x <.> "hs"-            | otherwise = readHints $ x <.> "hs"+            | "HLint." `isPrefixOf` x = readHints dataDir $ dataDir </> drop 6 x <.> "hs"+            | otherwise = readHints dataDir $ x <.> "hs"   -- Eta bound variable lifted so the filter only happens once per classify@@ -52,49 +49,50 @@ --------------------------------------------------------------------- -- READ A HINT -readSetting :: Decl -> [Setting]-readSetting (FunBind [Match src (Ident (getRank -> rank)) pats _-           (UnGuardedRhs bod) (BDecls bind)])-    | InfixApp lhs op rhs <- bod, opExp op ~= "==>" =-        [MatchExp rank (head names) (fromParen lhs) (fromParen rhs) (readSide bind)]+defaultName = "Use alternative"++readSetting :: Decl_ -> [Setting]+readSetting (FunBind _ [Match _ (Ident _ (getRank -> rank)) pats (UnGuardedRhs _ bod) bind])+    | InfixApp _ lhs op rhs <- bod, opExp op ~= "==>" =+        [MatchExp rank (if null names then defaultName else head names) (fromParen lhs) (fromParen rhs) (readSide $ childrenBi bind)]     | otherwise = [Classify rank n func | n <- names2, func <- readFuncs bod]     where         names = getNames pats bod         names2 = ["" | null names] ++ names  -readSetting (PatBind src (PVar name) typ bod bind) = readSetting $ FunBind [Match src name [PLit (String "")] typ bod bind]-readSetting (FunBind xs) | length xs /= 1 = concatMap (readSetting . FunBind . (:[])) xs-readSetting x = error $ "Failed to read hint " ++ maybe "" showSrcLoc (getSrcLoc x) ++ "\n" ++ prettyPrint x+readSetting (PatBind _ (PVar _ name) _ bod bind) = readSetting $ FunBind an [Match an name [PLit an (String an "" "")] bod bind]+readSetting (FunBind _ xs) | length xs /= 1 = concatMap (readSetting . FunBind an . (:[])) xs+readSetting x = error $ "Failed to read hint " ++ prettyPrint (getPointLoc $ ann x) ++ "\n" ++ prettyPrint x  -readSide :: [Decl] -> Maybe Exp+readSide :: [Decl_] -> Maybe Exp_ readSide [] = Nothing-readSide [PatBind src PWildCard Nothing (UnGuardedRhs bod) (BDecls [])] = Just bod-readSide (x:_) = error $ "Failed to read side condition " ++ maybe "" showSrcLoc (getSrcLoc x) ++ "\n" ++ prettyPrint x+readSide [PatBind _ PWildCard{} Nothing (UnGuardedRhs _ bod) Nothing] = Just bod+readSide (x:_) = error $ "Failed to read side condition " ++ prettyPrint (getPointLoc $ ann x) ++ "\n" ++ prettyPrint x  -readFuncs :: Exp -> [FuncName]-readFuncs (App x y) = readFuncs x ++ readFuncs y-readFuncs (Lit (String "")) = [("","")]-readFuncs (Var (UnQual name)) = [("",fromNamed name)]-readFuncs (Var (Qual (ModuleName mod) name)) = [(mod, fromNamed name)]-readFuncs (Con (UnQual name)) = [(fromNamed name,"")]-readFuncs (Con (Qual (ModuleName mod) name)) = [(mod ++ "." ++ fromNamed name,"")]+readFuncs :: Exp_ -> [FuncName]+readFuncs (App _ x y) = readFuncs x ++ readFuncs y+readFuncs (Lit _ (String _ "" _)) = [("","")]+readFuncs (Var _ (UnQual _ name)) = [("",fromNamed name)]+readFuncs (Var _ (Qual _ (ModuleName _ mod) name)) = [(mod, fromNamed name)]+readFuncs (Con _ (UnQual _ name)) = [(fromNamed name,"")]+readFuncs (Con _ (Qual _ (ModuleName _ mod) name)) = [(mod ++ "." ++ fromNamed name,"")] readFuncs x = error $ "Failed to read classification rule\n" ++ prettyPrint x   -getNames :: [Pat] -> Exp -> [String]+getNames :: [Pat_] -> Exp_ -> [String] getNames ps _ | ps /= [] && all isPString ps = map fromPString ps-getNames [] (InfixApp lhs op rhs) | opExp op ~= "==>" = ["Use " ++ head (names ++ ["alternative"])]+getNames [] (InfixApp _ lhs op rhs) | opExp op ~= "==>" = map ("Use "++) names     where-        lnames = map f $ childrenBi lhs-        rnames = map f $ childrenBi rhs+        lnames = map f $ childrenS lhs+        rnames = map f $ childrenS rhs         names = filter (not . isUnifyVar) $ (rnames \\ lnames) ++ rnames-        f (Ident x) = x-        f (Symbol x) = x-getNames [] _ = [""]+        f (Ident _ x) = x+        f (Symbol _ x) = x+getNames _ _ = []   getRank :: String -> Rank
src/Test.hs view
@@ -3,6 +3,7 @@ module Test where  import Control.Arrow+import Control.Exception import Control.Monad import Data.Char import Data.List@@ -10,12 +11,15 @@ import Data.Function import System.Directory import System.FilePath+import System.IO+import System.Cmd+import System.Exit  import Settings import Type+import Hint import HSE.All import Hint.All-import Paths_hlint   -- Input, Output@@ -24,27 +28,66 @@ data Test = Test SrcLoc String (Maybe String)  -test :: IO ()-test = do-    dat <- getDataDir-    datDir <- getDirectoryContents dat+test :: FilePath -> IO Int+test dataDir = do+    dataLs <- getDirectoryContents dataDir      src <- doesDirectoryExist "src/Hint"-    (fail,total) <- liftM ((sum *** sum) . unzip) $ sequence $-        [runTestDyn (dat </> h) | h <- datDir, takeExtension h == ".hs"] +++    (fail,total) <- fmap ((sum *** sum) . unzip) $ sequence $+        [runTestDyn dataDir (dataDir </> h) | h <- dataLs, takeExtension h == ".hs", not $ "HLint" `isPrefixOf` takeBaseName h] ++         [runTest h ("src/Hint" </> name <.> "hs") | (name,h) <- staticHints, src]     unless src $ putStrLn "Warning, couldn't find source code, so non-hint tests skipped"     if fail == 0         then putStrLn $ "Tests passed (" ++ show total ++ ")"         else putStrLn $ "Tests failed (" ++ show fail ++ " of " ++ show total ++ ")"+    return fail  -runTestDyn :: FilePath -> IO (Int,Int)-runTestDyn file = do-    settings <- readSettings [file]-    runTest (dynamicHints settings) file+runTestDyn :: FilePath -> FilePath -> IO (Int,Int)+runTestDyn dataDir file = do+    settings <- readSettings dataDir [file]+    let bad = [putStrLn $ "No name for the hint " ++ prettyPrint (lhs x) | x@MatchExp{} <- settings, hintS x == defaultName]+    sequence_ bad +    +    (f1,t1) <- runTestTypes settings+    (f2,t2) <- runTest (dynamicHints settings) file+    return (length bad + f1 + f2, t1 + t2) ++runTestTypes :: [Setting] -> IO (Int,Int)+runTestTypes settings = bracket+    (openTempFile "." "hlinttmp.hs")+    (\(file,h) -> removeFile file)+    $ \(file,h) -> do+        hPutStrLn h $ unlines contents+        hClose h+        res <- system $ "runhaskell " ++ file+        return (if res == ExitSuccess then 0 else 1, 1)+    where+        contents =+            ["{-# LANGUAGE NoMonomorphismRestriction, ExtendedDefaultRules #-}"+            ,"import System.IO"+            ,"import Control.Arrow"+            ,"import Data.Maybe"+            ,"import Control.Monad"+            ,"import Data.List"+            ,"import Data.Int"+            ,"import Data.Ord"+            ,"import Data.Monoid"+            ,"import Data.Function"+            ,"main = return ()"+            ,"(==>) :: a -> a -> a; (==>) = undefined"+            ,"_noParen_ = id"+            ,"_eval_ = id"+            ,"bad = undefined"] +++            [prettyPrint $ PatBind an (toNamed $ "test" ++ show i) Nothing bod Nothing+            | (i, MatchExp _ _ lhs rhs side) <- zip [1..] settings, "notTypeSafe" `notElem` vars side+            , let vs = map toNamed $ nub $ filter isUnifyVar $ vars lhs ++ vars rhs+            , let inner = InfixApp an (Paren an lhs) (toNamed "==>") (Paren an rhs)+            , let bod = UnGuardedRhs an $ if null vs then inner else Lambda an vs inner]++ -- return the number of fails/total runTest :: Hint -> FilePath -> IO (Int,Int) runTest hint file = do@@ -54,7 +97,7 @@     return (length failures, length tests)     where         f (Test loc inp out) =-                ["TEST FAILURE\n" +++                ["TEST FAILURE (" ++ show (length ideas) ++ " hints generated)\n" ++                  "SRC: " ++ showSrcLoc loc ++ "\n" ++                  "INPUT: " ++ inp ++ "\n" ++                  concatMap ((++) "OUTPUT: " . show) ideas ++
src/Type.hs view
@@ -29,7 +29,7 @@ -- Idea are generated by the program data Setting     = Classify {rankS :: Rank, hintS :: String, funcS :: FuncName}-    | MatchExp {rankS :: Rank, hintS :: String, lhs :: Exp, rhs :: Exp, side :: Maybe Exp}+    | MatchExp {rankS :: Rank, hintS :: String, lhs :: Exp_, rhs :: Exp_, side :: Maybe Exp_}     | Builtin String -- use a builtin hint set       deriving Show @@ -62,9 +62,8 @@     [showSrcLoc loc ++ " Parse error","Error message:","  " ++ msg,"Code:"] ++ map ("  "++) (lines $ tt from)  --- The real key will be filled in by applyHint rawIdea = Idea ("","")-idea rank hint loc from to = rawIdea rank hint loc (f from) (f to)+idea rank hint from to = rawIdea rank hint (toSrcLoc $ ann from) (f from) (f to)     where f = dropWhile isSpace . prettyPrint warn mr = idea Warning mr @@ -73,33 +72,3 @@ isUnifyVar :: String -> Bool isUnifyVar [x] = x == '?' || isAlpha x isUnifyVar _ = False-------------------------------------------------------------------------- HINTS--type DeclHint = NameMatch -> Module -> Decl -> [Idea]-type ModuHint = NameMatch -> Module         -> [Idea]--data Hint = DeclHint {declHint :: DeclHint} | ModuHint {moduHint :: ModuHint}---applyHint :: ParseFlags -> [Hint] -> FilePath -> IO [Idea]-applyHint flags h file = do-    src <- readFile file-    return $ applyHintStr flags h file src---applyHintStr :: ParseFlags -> [Hint] -> FilePath -> String -> [Idea]-applyHintStr flags h file src =-    case parseString flags file src of-        ParseFailed sl msg ->-            let ticks = ["  ","  ","> ","  ","  "]-                bad = zipWith (++) ticks $ take 5 $ drop (srcLine sl - 3) $ lines src ++ [""]-                bad2 = reverse $ dropWhile (all isSpace) $ reverse $ dropWhile (all isSpace) bad-            in [ParseError Warning "Parse error" sl msg (unlines bad2)]-        ParseOk m ->-            let name = moduleName m-                nm = nameMatch $ moduleImports m-                order n = map (\i -> i{func = (name,n)}) . sortBy (comparing loc)-            in order "" [i | ModuHint h <- h, i <- h nm m] ++-               concat [order (fromNamed d) [i | DeclHint h <- h, i <- h nm m d] | d <- moduleDecls m]
src/Util.hs view
@@ -32,6 +32,10 @@ concatMapM f = liftM concat . mapM f  +concatZipWithM :: Monad m => (a -> b -> m [c]) -> [a] -> [b] -> m [c]+concatZipWithM f xs ys = liftM concat $ zipWithM f xs ys++ headDef :: a -> [a] -> a headDef x [] = x headDef x (y:ys) = y