@@ -20,8 +20,11 @@ module Language.PureScript.Parser.JS
2020 ) where
2121
2222import Control.Applicative ((*>), (<*))
23−import Control.Monad (msum)
23+import Control.Monad (forM_, when, msum)
2424import Control.Monad.Error.Class (MonadError(..))
25+import Control.Monad.Writer.Class (MonadWriter(..))
26+import Data.Function (on)
27+import Data.List (sortBy, groupBy)
2528import Language.PureScript.Errors
2629import Language.PureScript.Names
2730import Language.PureScript.Parser.Common
@@ -32,13 +35,20 @@ import qualified Text.Parsec as PS
3235
3336type ForeignJS = String
3437
35−parseForeignModulesFromFiles :: (MonadError MultipleErrors m, Functor m) => [(FilePath, ForeignJS)] -> m (M.Map ModuleName (FilePath, ForeignJS))
38+parseForeignModulesFromFiles :: (Functor m, MonadError MultipleErrors m, MonadWriter MultipleErrors m)
39+ => [(FilePath, ForeignJS)]
40+ -> m (M.Map ModuleName (FilePath, ForeignJS))
3641parseForeignModulesFromFiles files = do
37− -- TODO: emit MultipleFFIModules error when duplicates are found
3842 foreigns <- parU files $ \(path, file) ->
3943 case findModuleName (lines file) of
4044 Just name -> return (name, (path, file))
4145 Nothing -> throwError (errorMessage $ ErrorParsingFFIModule path)
46+ let grouped = groupBy ((==) `on` fst) $ sortBy (compare `on` fst) foreigns
47+ forM_ grouped $ \grp ->
48+ when (length grp > 1) $ do
49+ let mn = fst (head grp)
50+ paths = map (fst . snd) grp
51+ tell $ errorMessage $ MultipleFFIModules mn paths
4252 return $ M.fromList foreigns
4353
4454findModuleName :: [String] -> Maybe ModuleName