{-# LANGUAGE PatternGuards, ScopedTypeVariables, RecordWildCards #-}
{-
    Reduce the number of import declarations.
    Two import declarations can be combined if:
      (note, A[] is A with whatever import list, or none)

    import A[]; import A[] = import A[]
    import A(B); import A(C) = import A(B,C)
    import A; import A(C) = import A
    import A; import A hiding (C) = import A
    import A[]; import A[] as Y = import A[] as Y

<TEST>
import A; import A -- import A
import A; import A; import A -- import A
import A(Foo) ; import A -- import A
import A ;import A(Foo) -- import A
import A(Bar(..)); import {-# SOURCE #-} A
import A; import B
import A(B) ; import A(C) -- import A(B,C)
import A; import A hiding (C) -- import A
import A; import A as Y -- import A as Y
import A; import qualified A as Y
import A as B; import A as C
import A as A -- import A
import qualified A as A -- import qualified A
import A; import B; import A -- import A
import qualified A; import A
import B; import A; import A -- import A
import A hiding(Foo); import A hiding(Bar)
import List -- import Data.List
import qualified List -- import qualified Data.List as List
import Char(foo) -- import Data.Char(foo)
import IO(foo)
import IO as X -- import System.IO as X; import System.IO.Error as X; import Control.Exception  as X (bracket,bracket_)
</TEST>
-}


module Hint.Import(importHint) where

import Control.Applicative
import Data.Tuple.Extra
import Hint.Type
import Refact.Types hiding (ModuleName)
import qualified Refact.Types as R
import Data.List.Extra
import Data.Maybe
import Prelude


importHint :: ModuHint
importHint :: ModuHint
importHint _ x :: Module_
x = (((String, Maybe String), [ImportDecl S]) -> [Idea])
-> [((String, Maybe String), [ImportDecl S])] -> [Idea]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap ([ImportDecl S] -> [Idea]
wrap ([ImportDecl S] -> [Idea])
-> (((String, Maybe String), [ImportDecl S]) -> [ImportDecl S])
-> ((String, Maybe String), [ImportDecl S])
-> [Idea]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((String, Maybe String), [ImportDecl S]) -> [ImportDecl S]
forall a b. (a, b) -> b
snd) ([((String, Maybe String), ImportDecl S)]
-> [((String, Maybe String), [ImportDecl S])]
forall k v. Ord k => [(k, v)] -> [(k, [v])]
groupSort
                 [((ModuleName S -> String
forall a. Named a => a -> String
fromNamed (ModuleName S -> String) -> ModuleName S -> String
forall a b. (a -> b) -> a -> b
$ ImportDecl S -> ModuleName S
forall l. ImportDecl l -> ModuleName l
importModule ImportDecl S
i,ImportDecl S -> Maybe String
forall l. ImportDecl l -> Maybe String
importPkg ImportDecl S
i),ImportDecl S
i) | ImportDecl S
i <- Module_ -> [ImportDecl S]
forall from to. Biplate from to => from -> [to]
universeBi Module_
x, Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ ImportDecl S -> Bool
forall l. ImportDecl l -> Bool
importSrc ImportDecl S
i]) [Idea] -> [Idea] -> [Idea]
forall a. [a] -> [a] -> [a]
++
                 (ImportDecl S -> [Idea]) -> [ImportDecl S] -> [Idea]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (\x :: ImportDecl S
x -> ImportDecl S -> [Idea]
hierarchy ImportDecl S
x [Idea] -> [Idea] -> [Idea]
forall a. [a] -> [a] -> [a]
++ ImportDecl S -> [Idea]
combine1 ImportDecl S
x) (Module_ -> [ImportDecl S]
forall from to. Biplate from to => from -> [to]
universeBi Module_
x)


wrap :: [ImportDecl S] -> [Idea]
wrap :: [ImportDecl S] -> [Idea]
wrap o :: [ImportDecl S]
o = [ Severity
-> String
-> SrcSpan
-> String
-> Maybe String
-> [Note]
-> [Refactoring SrcSpan]
-> Idea
rawIdea Severity
Warning "Use fewer imports" (S -> SrcSpan
srcInfoSpan (S -> SrcSpan) -> S -> SrcSpan
forall a b. (a -> b) -> a -> b
$ ImportDecl S -> S
forall (ast :: * -> *) l. Annotated ast => ast l -> l
ann (ImportDecl S -> S) -> ImportDecl S -> S
forall a b. (a -> b) -> a -> b
$ [ImportDecl S] -> ImportDecl S
forall a. [a] -> a
head [ImportDecl S]
o) ([ImportDecl S] -> String
f [ImportDecl S]
o) (String -> Maybe String
forall a. a -> Maybe a
Just (String -> Maybe String) -> String -> Maybe String
forall a b. (a -> b) -> a -> b
$ [ImportDecl S] -> String
f [ImportDecl S]
x) [] [Refactoring SrcSpan]
rs
         | Just (x :: [ImportDecl S]
x, rs :: [Refactoring SrcSpan]
rs) <- [[ImportDecl S] -> Maybe ([ImportDecl S], [Refactoring SrcSpan])
simplify [ImportDecl S]
o]]
    where f :: [ImportDecl S] -> String
f = [String] -> String
unlines ([String] -> String)
-> ([ImportDecl S] -> [String]) -> [ImportDecl S] -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ImportDecl S -> String) -> [ImportDecl S] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map ImportDecl S -> String
forall a. Pretty a => a -> String
prettyPrint


simplify :: [ImportDecl S] -> Maybe ([ImportDecl S], [Refactoring R.SrcSpan])
simplify :: [ImportDecl S] -> Maybe ([ImportDecl S], [Refactoring SrcSpan])
simplify [] = Maybe ([ImportDecl S], [Refactoring SrcSpan])
forall a. Maybe a
Nothing
simplify (x :: ImportDecl S
x:xs :: [ImportDecl S]
xs) = case ImportDecl S
-> [ImportDecl S] -> Maybe ([ImportDecl S], [Refactoring SrcSpan])
simplifyHead ImportDecl S
x [ImportDecl S]
xs of
    Nothing -> ([ImportDecl S] -> [ImportDecl S])
-> ([ImportDecl S], [Refactoring SrcSpan])
-> ([ImportDecl S], [Refactoring SrcSpan])
forall a a' b. (a -> a') -> (a, b) -> (a', b)
first (ImportDecl S
xImportDecl S -> [ImportDecl S] -> [ImportDecl S]
forall a. a -> [a] -> [a]
:) (([ImportDecl S], [Refactoring SrcSpan])
 -> ([ImportDecl S], [Refactoring SrcSpan]))
-> Maybe ([ImportDecl S], [Refactoring SrcSpan])
-> Maybe ([ImportDecl S], [Refactoring SrcSpan])
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [ImportDecl S] -> Maybe ([ImportDecl S], [Refactoring SrcSpan])
simplify [ImportDecl S]
xs
    Just (xs :: [ImportDecl S]
xs, rs :: [Refactoring SrcSpan]
rs) -> ([ImportDecl S], [Refactoring SrcSpan])
-> Maybe ([ImportDecl S], [Refactoring SrcSpan])
forall a. a -> Maybe a
Just (([ImportDecl S], [Refactoring SrcSpan])
 -> Maybe ([ImportDecl S], [Refactoring SrcSpan]))
-> ([ImportDecl S], [Refactoring SrcSpan])
-> Maybe ([ImportDecl S], [Refactoring SrcSpan])
forall a b. (a -> b) -> a -> b
$ ([ImportDecl S], [Refactoring SrcSpan])
-> (([ImportDecl S], [Refactoring SrcSpan])
    -> ([ImportDecl S], [Refactoring SrcSpan]))
-> Maybe ([ImportDecl S], [Refactoring SrcSpan])
-> ([ImportDecl S], [Refactoring SrcSpan])
forall b a. b -> (a -> b) -> Maybe a -> b
maybe ([ImportDecl S]
xs, [Refactoring SrcSpan]
rs) (([Refactoring SrcSpan] -> [Refactoring SrcSpan])
-> ([ImportDecl S], [Refactoring SrcSpan])
-> ([ImportDecl S], [Refactoring SrcSpan])
forall b b' a. (b -> b') -> (a, b) -> (a, b')
second ([Refactoring SrcSpan]
-> [Refactoring SrcSpan] -> [Refactoring SrcSpan]
forall a. [a] -> [a] -> [a]
++ [Refactoring SrcSpan]
rs)) (Maybe ([ImportDecl S], [Refactoring SrcSpan])
 -> ([ImportDecl S], [Refactoring SrcSpan]))
-> Maybe ([ImportDecl S], [Refactoring SrcSpan])
-> ([ImportDecl S], [Refactoring SrcSpan])
forall a b. (a -> b) -> a -> b
$ [ImportDecl S] -> Maybe ([ImportDecl S], [Refactoring SrcSpan])
simplify [ImportDecl S]
xs


simplifyHead :: ImportDecl S -> [ImportDecl S] -> Maybe ([ImportDecl S], [Refactoring R.SrcSpan])
simplifyHead :: ImportDecl S
-> [ImportDecl S] -> Maybe ([ImportDecl S], [Refactoring SrcSpan])
simplifyHead x :: ImportDecl S
x [] = Maybe ([ImportDecl S], [Refactoring SrcSpan])
forall a. Maybe a
Nothing
simplifyHead x :: ImportDecl S
x (y :: ImportDecl S
y:ys :: [ImportDecl S]
ys) = case ImportDecl S
-> ImportDecl S -> Maybe (ImportDecl S, [Refactoring SrcSpan])
combine ImportDecl S
x ImportDecl S
y of
    Nothing -> ([ImportDecl S] -> [ImportDecl S])
-> ([ImportDecl S], [Refactoring SrcSpan])
-> ([ImportDecl S], [Refactoring SrcSpan])
forall a a' b. (a -> a') -> (a, b) -> (a', b)
first (ImportDecl S
yImportDecl S -> [ImportDecl S] -> [ImportDecl S]
forall a. a -> [a] -> [a]
:) (([ImportDecl S], [Refactoring SrcSpan])
 -> ([ImportDecl S], [Refactoring SrcSpan]))
-> Maybe ([ImportDecl S], [Refactoring SrcSpan])
-> Maybe ([ImportDecl S], [Refactoring SrcSpan])
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ImportDecl S
-> [ImportDecl S] -> Maybe ([ImportDecl S], [Refactoring SrcSpan])
simplifyHead ImportDecl S
x [ImportDecl S]
ys
    Just (xy :: ImportDecl S
xy, rs :: [Refactoring SrcSpan]
rs) -> ([ImportDecl S], [Refactoring SrcSpan])
-> Maybe ([ImportDecl S], [Refactoring SrcSpan])
forall a. a -> Maybe a
Just (ImportDecl S
xy ImportDecl S -> [ImportDecl S] -> [ImportDecl S]
forall a. a -> [a] -> [a]
: [ImportDecl S]
ys, [Refactoring SrcSpan]
rs)


combine :: ImportDecl S -> ImportDecl S -> Maybe (ImportDecl S, [Refactoring R.SrcSpan])
combine :: ImportDecl S
-> ImportDecl S -> Maybe (ImportDecl S, [Refactoring SrcSpan])
combine x :: ImportDecl S
x y :: ImportDecl S
y | Bool
qual, Bool
as, Bool
specs = (ImportDecl S, [Refactoring SrcSpan])
-> Maybe (ImportDecl S, [Refactoring SrcSpan])
forall a. a -> Maybe a
Just (ImportDecl S
x, [RType -> SrcSpan -> Refactoring SrcSpan
forall a. RType -> a -> Refactoring a
Delete RType
Import (ImportDecl S -> SrcSpan
forall (a :: * -> *). Annotated a => a S -> SrcSpan
toSS ImportDecl S
y)])
           | Bool
qual, Bool
as, Just (ImportSpecList _ False xs :: [ImportSpec S]
xs) <- ImportDecl S -> Maybe (ImportSpecList S)
forall l. ImportDecl l -> Maybe (ImportSpecList l)
importSpecs ImportDecl S
x, Just (ImportSpecList _ False ys :: [ImportSpec S]
ys) <- ImportDecl S -> Maybe (ImportSpecList S)
forall l. ImportDecl l -> Maybe (ImportSpecList l)
importSpecs ImportDecl S
y = let newImp :: ImportDecl S
newImp = ImportDecl S
x{importSpecs :: Maybe (ImportSpecList S)
importSpecs = ImportSpecList S -> Maybe (ImportSpecList S)
forall a. a -> Maybe a
Just (ImportSpecList S -> Maybe (ImportSpecList S))
-> ImportSpecList S -> Maybe (ImportSpecList S)
forall a b. (a -> b) -> a -> b
$ S -> Bool -> [ImportSpec S] -> ImportSpecList S
forall l. l -> Bool -> [ImportSpec l] -> ImportSpecList l
ImportSpecList S
an Bool
False ([ImportSpec S] -> ImportSpecList S)
-> [ImportSpec S] -> ImportSpecList S
forall a b. (a -> b) -> a -> b
$ [ImportSpec S] -> [ImportSpec S]
forall (f :: * -> *). (Annotated f, Eq (f ())) => [f S] -> [f S]
nub_ ([ImportSpec S] -> [ImportSpec S])
-> [ImportSpec S] -> [ImportSpec S]
forall a b. (a -> b) -> a -> b
$ [ImportSpec S]
xs [ImportSpec S] -> [ImportSpec S] -> [ImportSpec S]
forall a. [a] -> [a] -> [a]
++ [ImportSpec S]
ys}
            in (ImportDecl S, [Refactoring SrcSpan])
-> Maybe (ImportDecl S, [Refactoring SrcSpan])
forall a. a -> Maybe a
Just (ImportDecl S
newImp, [ RType
-> SrcSpan -> [(String, SrcSpan)] -> String -> Refactoring SrcSpan
forall a. RType -> a -> [(String, a)] -> String -> Refactoring a
Replace RType
Import (ImportDecl S -> SrcSpan
forall (a :: * -> *). Annotated a => a S -> SrcSpan
toSS ImportDecl S
x)  [] (ImportDecl S -> String
forall a. Pretty a => a -> String
prettyPrint ImportDecl S
newImp)
                             , RType -> SrcSpan -> Refactoring SrcSpan
forall a. RType -> a -> Refactoring a
Delete RType
Import (ImportDecl S -> SrcSpan
forall (a :: * -> *). Annotated a => a S -> SrcSpan
toSS ImportDecl S
y) ] )

           | Bool
qual, Bool
as, Maybe (ImportSpecList S) -> Bool
forall a. Maybe a -> Bool
isNothing (ImportDecl S -> Maybe (ImportSpecList S)
forall l. ImportDecl l -> Maybe (ImportSpecList l)
importSpecs ImportDecl S
x) Bool -> Bool -> Bool
|| Maybe (ImportSpecList S) -> Bool
forall a. Maybe a -> Bool
isNothing (ImportDecl S -> Maybe (ImportSpecList S)
forall l. ImportDecl l -> Maybe (ImportSpecList l)
importSpecs ImportDecl S
y) =
             let (newImp :: ImportDecl S
newImp, toDelete :: ImportDecl S
toDelete) = if Maybe (ImportSpecList S) -> Bool
forall a. Maybe a -> Bool
isNothing (ImportDecl S -> Maybe (ImportSpecList S)
forall l. ImportDecl l -> Maybe (ImportSpecList l)
importSpecs ImportDecl S
x) then (ImportDecl S
x, ImportDecl S
y) else (ImportDecl S
y, ImportDecl S
x)
             in (ImportDecl S, [Refactoring SrcSpan])
-> Maybe (ImportDecl S, [Refactoring SrcSpan])
forall a. a -> Maybe a
Just (ImportDecl S
newImp, [RType -> SrcSpan -> Refactoring SrcSpan
forall a. RType -> a -> Refactoring a
Delete RType
Import (ImportDecl S -> SrcSpan
forall (a :: * -> *). Annotated a => a S -> SrcSpan
toSS ImportDecl S
toDelete)])
           | Bool -> Bool
not (ImportDecl S -> Bool
forall l. ImportDecl l -> Bool
importQualified ImportDecl S
x), Bool
qual, Bool
specs, [ModuleName S] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [ModuleName S]
ass Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== 1 =
             let (newImp :: ImportDecl S
newImp, toDelete :: ImportDecl S
toDelete) = if Maybe (ModuleName S) -> Bool
forall a. Maybe a -> Bool
isJust (ImportDecl S -> Maybe (ModuleName S)
forall l. ImportDecl l -> Maybe (ModuleName l)
importAs ImportDecl S
x) then (ImportDecl S
x, ImportDecl S
y) else (ImportDecl S
y, ImportDecl S
x)
             in (ImportDecl S, [Refactoring SrcSpan])
-> Maybe (ImportDecl S, [Refactoring SrcSpan])
forall a. a -> Maybe a
Just (ImportDecl S
newImp, [RType -> SrcSpan -> Refactoring SrcSpan
forall a. RType -> a -> Refactoring a
Delete RType
Import (ImportDecl S -> SrcSpan
forall (a :: * -> *). Annotated a => a S -> SrcSpan
toSS ImportDecl S
toDelete)])

    where
        qual :: Bool
qual = ImportDecl S -> Bool
forall l. ImportDecl l -> Bool
importQualified ImportDecl S
x Bool -> Bool -> Bool
forall a. Eq a => a -> a -> Bool
== ImportDecl S -> Bool
forall l. ImportDecl l -> Bool
importQualified ImportDecl S
y
        as :: Bool
as = ImportDecl S -> Maybe (ModuleName S)
forall l. ImportDecl l -> Maybe (ModuleName l)
importAs ImportDecl S
x Maybe (ModuleName S) -> Maybe (ModuleName S) -> Bool
forall (f :: * -> *).
(Annotated f, Eq (f ())) =>
Maybe (f S) -> Maybe (f S) -> Bool
`eqMaybe` ImportDecl S -> Maybe (ModuleName S)
forall l. ImportDecl l -> Maybe (ModuleName l)
importAs ImportDecl S
y
        ass :: [ModuleName S]
ass = (ImportDecl S -> Maybe (ModuleName S))
-> [ImportDecl S] -> [ModuleName S]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe ImportDecl S -> Maybe (ModuleName S)
forall l. ImportDecl l -> Maybe (ModuleName l)
importAs [ImportDecl S
x,ImportDecl S
y]
        specs :: Bool
specs = ImportDecl S -> Maybe (ImportSpecList S)
forall l. ImportDecl l -> Maybe (ImportSpecList l)
importSpecs ImportDecl S
x Maybe (ImportSpecList S) -> Maybe (ImportSpecList S) -> Bool
forall (f :: * -> *).
(Annotated f, Eq (f ())) =>
Maybe (f S) -> Maybe (f S) -> Bool
`eqMaybe` ImportDecl S -> Maybe (ImportSpecList S)
forall l. ImportDecl l -> Maybe (ImportSpecList l)
importSpecs ImportDecl S
y

combine _ _ = Maybe (ImportDecl S, [Refactoring SrcSpan])
forall a. Maybe a
Nothing

combine1 :: ImportDecl S -> [Idea]
combine1 :: ImportDecl S -> [Idea]
combine1 i :: ImportDecl S
i@ImportDecl{..}
    | ModuleName () -> Maybe (ModuleName ())
forall a. a -> Maybe a
Just (ModuleName S -> ModuleName ()
forall (f :: * -> *). Functor f => f S -> f ()
dropAnn ModuleName S
importModule) Maybe (ModuleName ()) -> Maybe (ModuleName ()) -> Bool
forall a. Eq a => a -> a -> Bool
== (ModuleName S -> ModuleName ())
-> Maybe (ModuleName S) -> Maybe (ModuleName ())
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ModuleName S -> ModuleName ()
forall (f :: * -> *). Functor f => f S -> f ()
dropAnn Maybe (ModuleName S)
importAs
    = [String
-> ImportDecl S -> ImportDecl S -> [Refactoring SrcSpan] -> Idea
forall (ast :: * -> *) a.
(Annotated ast, Pretty a, Pretty (ast S)) =>
String -> ast S -> a -> [Refactoring SrcSpan] -> Idea
suggest "Redundant as" ImportDecl S
i ImportDecl S
i{importAs :: Maybe (ModuleName S)
importAs=Maybe (ModuleName S)
forall a. Maybe a
Nothing} [SrcSpan -> Refactoring SrcSpan
forall a. a -> Refactoring a
RemoveAsKeyword (ImportDecl S -> SrcSpan
forall (a :: * -> *). Annotated a => a S -> SrcSpan
toSS ImportDecl S
i)]]
combine1 _ = []


newNames :: [(String, String)]
newNames = let * :: b -> a -> (a, b)
(*) = (a -> b -> (a, b)) -> b -> a -> (a, b)
forall a b c. (a -> b -> c) -> b -> a -> c
flip (,) in
    ["Control" String -> String -> (String, String)
forall b a. b -> a -> (a, b)
* "Monad"
    ,"Data" String -> String -> (String, String)
forall b a. b -> a -> (a, b)
* "Char"
    ,"Data" String -> String -> (String, String)
forall b a. b -> a -> (a, b)
* "List"
    ,"Data" String -> String -> (String, String)
forall b a. b -> a -> (a, b)
* "Maybe"
    ,"Data" String -> String -> (String, String)
forall b a. b -> a -> (a, b)
* "Ratio"
    ,"System" String -> String -> (String, String)
forall b a. b -> a -> (a, b)
* "Directory"

    -- Special, see bug https://code.google.com/archive/p/ndmitchell/issues/393
    -- ,"System" * "IO"

    -- Do not encourage use of old-locale/old-time over haskell98
    -- ,"System" * "Locale"
    -- ,"System" * "Time"
    ]


hierarchy :: ImportDecl S -> [Idea]
hierarchy :: ImportDecl S -> [Idea]
hierarchy i :: ImportDecl S
i@ImportDecl{importModule :: forall l. ImportDecl l -> ModuleName l
importModule=m :: ModuleName S
m@(ModuleName _ x :: String
x),importPkg :: forall l. ImportDecl l -> Maybe String
importPkg=Maybe String
Nothing} | Just y :: String
y <- String -> [(String, String)] -> Maybe String
forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup String
x [(String, String)]
newNames
    =
    let newModuleName :: String
newModuleName = String
y String -> String -> String
forall a. [a] -> [a] -> [a]
++ "." String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
x
        r :: [Refactoring SrcSpan]
r = [RType
-> SrcSpan -> [(String, SrcSpan)] -> String -> Refactoring SrcSpan
forall a. RType -> a -> [(String, a)] -> String -> Refactoring a
Replace RType
R.ModuleName (ModuleName S -> SrcSpan
forall (a :: * -> *). Annotated a => a S -> SrcSpan
toSS ModuleName S
m) [] String
newModuleName] in
    [String
-> ImportDecl S -> ImportDecl S -> [Refactoring SrcSpan] -> Idea
forall (ast :: * -> *) a.
(Annotated ast, Pretty a, Pretty (ast S)) =>
String -> ast S -> a -> [Refactoring SrcSpan] -> Idea
suggest "Use hierarchical imports" ImportDecl S
i (ImportDecl S -> ImportDecl S
desugarQual ImportDecl S
i){importModule :: ModuleName S
importModule=S -> String -> ModuleName S
forall l. l -> String -> ModuleName l
ModuleName S
an String
newModuleName} [Refactoring SrcSpan]
r]

-- import IO is equivalent to
-- import System.IO, import System.IO.Error, import Control.Exception(bracket, bracket_)
hierarchy i :: ImportDecl S
i@ImportDecl{importModule :: forall l. ImportDecl l -> ModuleName l
importModule=ModuleName _ "IO", importSpecs :: forall l. ImportDecl l -> Maybe (ImportSpecList l)
importSpecs=Maybe (ImportSpecList S)
Nothing,importPkg :: forall l. ImportDecl l -> Maybe String
importPkg=Maybe String
Nothing}
    = [Severity
-> String -> SrcSpan -> String -> Maybe String -> [Note] -> Idea
rawIdeaN Severity
Suggestion "Use hierarchical imports" (S -> SrcSpan
srcInfoSpan (S -> SrcSpan) -> S -> SrcSpan
forall a b. (a -> b) -> a -> b
$ ImportDecl S -> S
forall (ast :: * -> *) l. Annotated ast => ast l -> l
ann ImportDecl S
i) (String -> String
trimStart (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ ImportDecl S -> String
forall a. Pretty a => a -> String
prettyPrint ImportDecl S
i) (
          String -> Maybe String
forall a. a -> Maybe a
Just (String -> Maybe String) -> String -> Maybe String
forall a b. (a -> b) -> a -> b
$ [String] -> String
unlines ([String] -> String) -> [String] -> String
forall a b. (a -> b) -> a -> b
$ (ImportDecl S -> String) -> [ImportDecl S] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map (String -> String
trimStart (String -> String)
-> (ImportDecl S -> String) -> ImportDecl S -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ImportDecl S -> String
forall a. Pretty a => a -> String
prettyPrint)
          [String -> Maybe (ImportSpecList S) -> ImportDecl S
f "System.IO" Maybe (ImportSpecList S)
forall a. Maybe a
Nothing, String -> Maybe (ImportSpecList S) -> ImportDecl S
f "System.IO.Error" Maybe (ImportSpecList S)
forall a. Maybe a
Nothing
          ,String -> Maybe (ImportSpecList S) -> ImportDecl S
f "Control.Exception" (Maybe (ImportSpecList S) -> ImportDecl S)
-> Maybe (ImportSpecList S) -> ImportDecl S
forall a b. (a -> b) -> a -> b
$ ImportSpecList S -> Maybe (ImportSpecList S)
forall a. a -> Maybe a
Just (ImportSpecList S -> Maybe (ImportSpecList S))
-> ImportSpecList S -> Maybe (ImportSpecList S)
forall a b. (a -> b) -> a -> b
$ S -> Bool -> [ImportSpec S] -> ImportSpecList S
forall l. l -> Bool -> [ImportSpec l] -> ImportSpecList l
ImportSpecList S
an Bool
False [S -> Name S -> ImportSpec S
forall l. l -> Name l -> ImportSpec l
IVar S
an (Name S -> ImportSpec S) -> Name S -> ImportSpec S
forall a b. (a -> b) -> a -> b
$ String -> Name S
forall a. Named a => String -> a
toNamed String
x | String
x <- ["bracket","bracket_"]]]) []]
    where f :: String -> Maybe (ImportSpecList S) -> ImportDecl S
f a :: String
a b :: Maybe (ImportSpecList S)
b = (ImportDecl S -> ImportDecl S
desugarQual ImportDecl S
i){importModule :: ModuleName S
importModule=S -> String -> ModuleName S
forall l. l -> String -> ModuleName l
ModuleName S
an String
a, importSpecs :: Maybe (ImportSpecList S)
importSpecs=Maybe (ImportSpecList S)
b}

hierarchy _ = []


-- import qualified X ==> import qualified X as X
desugarQual :: ImportDecl S -> ImportDecl S
desugarQual :: ImportDecl S -> ImportDecl S
desugarQual x :: ImportDecl S
x | ImportDecl S -> Bool
forall l. ImportDecl l -> Bool
importQualified ImportDecl S
x Bool -> Bool -> Bool
&& Maybe (ModuleName S) -> Bool
forall a. Maybe a -> Bool
isNothing (ImportDecl S -> Maybe (ModuleName S)
forall l. ImportDecl l -> Maybe (ModuleName l)
importAs ImportDecl S
x) = ImportDecl S
x{importAs :: Maybe (ModuleName S)
importAs=ModuleName S -> Maybe (ModuleName S)
forall a. a -> Maybe a
Just (ImportDecl S -> ModuleName S
forall l. ImportDecl l -> ModuleName l
importModule ImportDecl S
x)}
              | Bool
otherwise = ImportDecl S
x