git.iko.soy/rowtype-yoga/purescript-native
on golang help sign in
Warn on duplicate imports
ed29a59Gary Burgess
src/Language/PureScript/AST/Declarations.hs+1−1
@@ -109,7 +109,7 @@ data ImportDeclarationType
109 -- An import with a list of references to hide: `import M hiding (foo)`
109 -- An import with a list of references to hide: `import M hiding (foo)`
110 --
110 --
111 | Hiding [DeclarationRef]
111 | Hiding [DeclarationRef]
112− deriving (Show, Read, D.Data, D.Typeable)
112+ deriving (Eq, Show, Read, D.Data, D.Typeable)
113
113
114-- |
114-- |
115-- The data type of declarations
115-- The data type of declarations
src/Language/PureScript/Errors.hs+33−5
@@ -143,6 +143,9 @@ data SimpleErrorMessage
143 | UnusedDctorImport ProperName
143 | UnusedDctorImport ProperName
144 | UnusedDctorExplicitImport ProperName [ProperName]
144 | UnusedDctorExplicitImport ProperName [ProperName]
145 | DeprecatedQualifiedSyntax ModuleName ModuleName
145 | DeprecatedQualifiedSyntax ModuleName ModuleName
146+ | RedundantUnqualifiedImport ModuleName ImportDeclarationType
147+ | DuplicateSelectiveImport ModuleName
148+ | DuplicateImport ModuleName ImportDeclarationType (Maybe ModuleName)
146 deriving (Show)
149 deriving (Show)
147
150
148-- | Error message hints, providing more detailed information about failure.
151-- | Error message hints, providing more detailed information about failure.
@@ -278,6 +281,9 @@ errorCode em = case unwrapErrorMessage em of
278 UnusedDctorImport{} -> "UnusedDctorImport"
281 UnusedDctorImport{} -> "UnusedDctorImport"
279 UnusedDctorExplicitImport{} -> "UnusedDctorExplicitImport"
282 UnusedDctorExplicitImport{} -> "UnusedDctorExplicitImport"
280 DeprecatedQualifiedSyntax{} -> "DeprecatedQualifiedSyntax"
283 DeprecatedQualifiedSyntax{} -> "DeprecatedQualifiedSyntax"
284+ RedundantUnqualifiedImport{} -> "RedundantUnqualifiedImport"
285+ DuplicateSelectiveImport{} -> "DuplicateSelectiveImport"
286+ DuplicateImport{} -> "DuplicateImport"
281
287
282
288
283-- |
289-- |
@@ -718,6 +724,15 @@ prettyPrintSingleError full level e = prettyPrintErrorMessage <$> onTypesInError
718 paras [ line $ "The import of type " ++ runModuleName name ++ " as " ++ runModuleName qualName ++ " uses the deprecated 'import qualified' syntax."
724 paras [ line $ "The import of type " ++ runModuleName name ++ " as " ++ runModuleName qualName ++ " uses the deprecated 'import qualified' syntax."
719 , line $ "This syntax form will be removed in PureScript 0.9." ]
725 , line $ "This syntax form will be removed in PureScript 0.9." ]
720
726
727+ renderSimpleErrorMessage (RedundantUnqualifiedImport name imp) =
728+ line $ "Import of " ++ prettyPrintImport name imp Nothing ++ " is redundant due to a whole-module import"
729+
730+ renderSimpleErrorMessage (DuplicateSelectiveImport name) =
731+ line $ "There is an existing import of " ++ runModuleName name ++ ", consider merging the import lists"
732+
733+ renderSimpleErrorMessage (DuplicateImport name imp qual) =
734+ line $ "Duplicate import of " ++ prettyPrintImport name imp qual
735+
721 renderHint :: ErrorMessageHint -> Box.Box -> Box.Box
736 renderHint :: ErrorMessageHint -> Box.Box -> Box.Box
722 renderHint (ErrorUnifyingTypes t1 t2) detail =
737 renderHint (ErrorUnifyingTypes t1 t2) detail =
723 paras [ detail
738 paras [ detail
@@ -849,11 +864,24 @@ prettyPrintSingleError full level e = prettyPrintErrorMessage <$> onTypesInError
849 -- Pretty print and export declaration
864 -- Pretty print and export declaration
850 prettyPrintExport :: DeclarationRef -> String
865 prettyPrintExport :: DeclarationRef -> String
851 prettyPrintExport (TypeRef pn _) = runProperName pn
866 prettyPrintExport (TypeRef pn _) = runProperName pn
867+ prettyPrintExport ref = prettyPrintRef ref
868+
869+ prettyPrintRef :: DeclarationRef -> String
870+ prettyPrintRef (TypeRef pn Nothing) = runProperName pn ++ "(..)"
871+ prettyPrintRef (TypeRef pn (Just dctors)) = runProperName pn ++ "(" ++ intercalate ", " (map runProperName dctors) ++ ")"
852− prettyPrintExport (ValueRef ident) = showIdent ident
872+ prettyPrintRef (ValueRef ident) = showIdent ident
853− prettyPrintExport (TypeClassRef pn) = runProperName pn
873+ prettyPrintRef (TypeClassRef pn) = runProperName pn
854− prettyPrintExport (TypeInstanceRef ident) = showIdent ident
874+ prettyPrintRef (TypeInstanceRef ident) = showIdent ident
855− prettyPrintExport (ModuleRef name) = "module " ++ runModuleName name
875+ prettyPrintRef (ModuleRef name) = "module " ++ runModuleName name
856− prettyPrintExport (PositionedDeclarationRef _ _ ref) = prettyPrintExport ref
876+ prettyPrintRef (PositionedDeclarationRef _ _ ref) = prettyPrintExport ref
877+
878+ prettyPrintImport :: ModuleName -> ImportDeclarationType -> Maybe ModuleName -> String
879+ prettyPrintImport mn idt qual =
880+ let i = case idt of
881+ Implicit -> runModuleName mn
882+ Explicit refs -> runModuleName mn ++ " (" ++ intercalate ", " (map prettyPrintRef refs) ++ ")"
883+ Hiding refs -> runModuleName mn ++ " hiding (" ++ intercalate "," (map prettyPrintRef refs) ++ ")"
884+ in i ++ maybe "" (\q -> " as " ++ runModuleName q) qual
857
885
858 -- | Simplify an error message
886 -- | Simplify an error message
859 simplifyErrorMessage :: ErrorMessage -> ErrorMessage
887 simplifyErrorMessage :: ErrorMessage -> ErrorMessage
src/Language/PureScript/Sugar/Names/Imports.hs+31−4
@@ -24,9 +24,9 @@ module Language.PureScript.Sugar.Names.Imports
24import Prelude ()
24import Prelude ()
25import Prelude.Compat
25import Prelude.Compat
26
26
27−import Data.List (find)
27+import Data.List (find, delete)
28−import Data.Maybe (fromMaybe, isNothing, fromJust)
28+import Data.Maybe (fromMaybe, isJust, isNothing, fromJust)
29−import Data.Foldable (traverse_)
29+import Data.Foldable (traverse_, for_)
30
30
31import Control.Arrow (first)
31import Control.Arrow (first)
32import Control.Monad
32import Control.Monad
@@ -70,9 +70,36 @@ findImports = foldM (go Nothing) M.empty
70resolveImports :: (Applicative m, MonadError MultipleErrors m, MonadWriter MultipleErrors m) => Env -> Module -> m Imports
70resolveImports :: (Applicative m, MonadError MultipleErrors m, MonadWriter MultipleErrors m) => Env -> Module -> m Imports
71resolveImports env (Module _ _ currentModule decls _) =
71resolveImports env (Module _ _ currentModule decls _) =
72 censor (addHint (ErrorInModule currentModule)) $ do
72 censor (addHint (ErrorInModule currentModule)) $ do
73+ imports <- findImports decls
74+
75+ for_ (M.toList imports) $ \(mn, imps) -> do
76+ let unqual = filter (\(_, _, q) -> isJust q) (reverse imps)
77+
78+ when (length imps > 1) $ for_ (selfCartesianSubset imps) $
79+ \((_, t1, q1), (pos, t2, q2)) ->
80+ when (t1 == t2 && q1 == q2) $
81+ maybe id warnWithPosition pos $
82+ tell . errorMessage $ DuplicateImport mn t2 q2
83+
84+ when (length unqual > 1) $
85+ case find (\(_, typ, _) -> typ == Implicit) unqual of
86+ Just i ->
87+ for_ (delete i unqual) $ \(pos, typ, _) ->
88+ maybe id warnWithPosition pos $
89+ tell $ errorMessage $ RedundantUnqualifiedImport mn typ
90+ Nothing ->
91+ for_ (tail unqual) $ \(pos, _, _) ->
92+ maybe id warnWithPosition pos $
93+ tell $ errorMessage $ DuplicateSelectiveImport mn
94+
73− scope <- M.insert currentModule [(Nothing, Implicit, Nothing)] <$> findImports decls
95+ let scope = M.insert currentModule [(Nothing, Implicit, Nothing)] imports
74 foldM (resolveModuleImport currentModule env) nullImports (M.toList scope)
96 foldM (resolveModuleImport currentModule env) nullImports (M.toList scope)
75
97
98+ where
99+ selfCartesianSubset :: [a] -> [(a, a)]
100+ selfCartesianSubset (x : xs) = [(x, y) | y <- xs] ++ selfCartesianSubset xs
101+ selfCartesianSubset [] = []
102+
76-- | Constructs a set of imports for a single module import.
103-- | Constructs a set of imports for a single module import.
77resolveModuleImport ::
104resolveModuleImport ::
78 forall m. (Applicative m, MonadError MultipleErrors m, MonadWriter MultipleErrors m) =>
105 forall m. (Applicative m, MonadError MultipleErrors m, MonadWriter MultipleErrors m) =>