Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions data/import_explicit_limit.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
- smell:
type: many explicit imports
limit: 2
3 changes: 2 additions & 1 deletion src/Config/Type.hs
Original file line number Diff line number Diff line change
Expand Up @@ -166,14 +166,15 @@ data Restrict = Restrict
,restrictMessage :: Maybe String
} deriving Show

data SmellType = SmellLongFunctions | SmellLongTypeLists | SmellManyArgFunctions | SmellManyImports
data SmellType = SmellLongFunctions | SmellLongTypeLists | SmellManyArgFunctions | SmellManyImports | SmellManyExplicitImports
deriving (Show,Eq,Ord)

getSmellType :: String -> Maybe SmellType
getSmellType "long functions" = Just SmellLongFunctions
getSmellType "long type lists" = Just SmellLongTypeLists
getSmellType "many arg functions" = Just SmellManyArgFunctions
getSmellType "many imports" = Just SmellManyImports
getSmellType "many explicit imports" = Just SmellManyExplicitImports
getSmellType _ = Nothing

data Setting
Expand Down
37 changes: 34 additions & 3 deletions src/Hint/Smell.hs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,20 @@ import A
import A; import B
import A
</TEST>

<TEST> [{smell: { type: many explicit imports, limit: 2}}]
import A (x, y, z) --
import A (x, y)
import A
import A hiding (x, y, z)
</TEST>

<TEST>
import A (x, y, z)
import A (x, y)
import A
import A hiding (x, y, z)
</TEST>
-}

import Hint.Type(ModuHint,ModuleEx(..),DeclHint,Idea(..),rawIdea,warn)
Expand All @@ -93,17 +107,34 @@ import Language.Haskell.GhclibParserEx.GHC.Utils.Outputable
smellModuleHint :: [Setting] -> ModuHint
smellModuleHint settings scope m =
let (L _ mod) = ghcModule m
imports = hsmodImports mod in
case Map.lookup SmellManyImports (smells settings) of
imports = hsmodImports mod
sm = smells settings in
manyImportsHint sm imports ++
concatMap (explicitImportLengthHint sm) imports

manyImportsHint :: Map.Map SmellType Int -> [LImportDecl GhcPs] -> [Idea]
manyImportsHint sm imports =
case Map.lookup SmellManyImports sm of
Just n | length imports >= n ->
let span = foldl1 combineSrcSpans $ locA . getLoc <$> imports
displayImports = unlines $ f <$> imports
in [rawIdea Config.Type.Warning "Many imports" span displayImports Nothing [] [] ]
in [rawIdea Config.Type.Warning "Many imports" span displayImports Nothing [] []]
where
f :: LImportDecl GhcPs -> String
f = trimStart . unsafePrettyPrint
_ -> []

explicitImportLengthHint :: Map.Map SmellType Int -> LImportDecl GhcPs -> [Idea]
explicitImportLengthHint sm imp@(L _ decl) =
case Map.lookup SmellManyExplicitImports sm of
Just limit ->
case ideclImportList decl of
Just (Exactly, L _ names) | length names > limit ->
[rawIdea Config.Type.Warning "Too many explicit imports" (locA $ getLoc imp)
(trimStart $ unsafePrettyPrint imp) Nothing [] []]
_ -> []
Nothing -> []

smellHint :: [Setting] -> DeclHint
smellHint settings scope m d =
sniff smellLongFunctions SmellLongFunctions ++
Expand Down
35 changes: 35 additions & 0 deletions tests/import_explicit_limit.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
---------------------------------------------------------------------
RUN tests/import_explicit_limit_pos.hs --hint=data/import_explicit_limit.yaml
FILE tests/import_explicit_limit_pos.hs
import A (sort, nub, group)
import B (Map, lookup, insert)
OUTPUT
tests/import_explicit_limit_pos.hs:1:1-27: Warning: Too many explicit imports
Found:
import A ( sort, nub, group )

tests/import_explicit_limit_pos.hs:2:1-30: Warning: Too many explicit imports
Found:
import B ( Map, lookup, insert )

2 hints

---------------------------------------------------------------------
RUN tests/import_explicit_limit_default.hs
FILE tests/import_explicit_limit_default.hs
import A (sort, nub, group)
import B (Map, lookup, insert)
OUTPUT
No hints

---------------------------------------------------------------------
RUN tests/import_explicit_limit_neg.hs --hint=data/import_explicit_limit.yaml
FILE tests/import_explicit_limit_neg.hs
import A (sort, nub)
import B (sort)
import C
import D hiding (sort, nub, group)
OUTPUT
No hints

---------------------------------------------------------------------
Loading