{- |
Copyright: (c) 2020 Kowainik
SPDX-License-Identifier: MPL-2.0
Maintainer: Kowainik <xrom.xkov@gmail.com>

Parse Haskell Language Extensions.
-}

module Extensions.Package
       ( -- * Package modules
         getPackageExtentions
       , getPackageExtentionsBySources

         -- * Single module
       , getModuleAndCabalExtentions
       , getModuleExtentions
       , getModuleAndCabalExtentionsBySource
       , getModuleExtentionsBySource
       ) where

import Control.Exception (catch)
import Data.ByteString (ByteString)
import Data.Functor ((<&>))
import Data.Map.Merge.Strict (mapMissing, merge, zipWithMatched)
import Data.Map.Strict (Map)

import Extensions.Cabal (parseCabalFileExtensions)
import Extensions.Module (parseFile, parseSourceWithPath)
import Extensions.Types (CabalAndModuleExtensions (..), CabalException, ExtensionsError (..),
                         ExtensionsResult, ModuleParseError, ParsedExtensions (..),
                         mergeAnyExtensions)

import qualified Data.Map.Strict as Map


{- | By given path to @.cabal@ file, analyse extensions for each Haskell module
and return the corresponding 'Map' with 'ExtensionsResult's.

__Throws__:

* 'CabalException'
-}
getPackageExtentions
    :: FilePath  -- ^ Path to @.cabal@ file.
    -> IO (Map FilePath ExtensionsResult)
getPackageExtentions :: FilePath -> IO (Map FilePath ExtensionsResult)
getPackageExtentions cabalFile :: FilePath
cabalFile = do
    Map FilePath ParsedExtensions
cabalMap <- FilePath -> IO (Map FilePath ParsedExtensions)
parseCabalFileExtensions FilePath
cabalFile
    (FilePath -> ParsedExtensions -> IO ExtensionsResult)
-> Map FilePath ParsedExtensions
-> IO (Map FilePath ExtensionsResult)
forall (t :: * -> *) k a b.
Applicative t =>
(k -> a -> t b) -> Map k a -> t (Map k b)
Map.traverseWithKey FilePath -> ParsedExtensions -> IO ExtensionsResult
perModuleParseMerge Map FilePath ParsedExtensions
cabalMap
  where
    perModuleParseMerge :: FilePath -> ParsedExtensions -> IO ExtensionsResult
    perModuleParseMerge :: FilePath -> ParsedExtensions -> IO ExtensionsResult
perModuleParseMerge path :: FilePath
path cabalExts :: ParsedExtensions
cabalExts = do
        Either ModuleParseError ParsedExtensions
moduleRes <- FilePath -> IO (Either ModuleParseError ParsedExtensions)
parseFile FilePath
path
        ExtensionsResult -> IO ExtensionsResult
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ExtensionsResult -> IO ExtensionsResult)
-> ExtensionsResult -> IO ExtensionsResult
forall a b. (a -> b) -> a -> b
$ ParsedExtensions
-> FilePath
-> Either ModuleParseError ParsedExtensions
-> ExtensionsResult
mergeCabalAndModule ParsedExtensions
cabalExts FilePath
path Either ModuleParseError ParsedExtensions
moduleRes

{- | By given path to @.cabal@ file and 'Map' of sources of all Haskell
modules, analyse extensions for each Haskell module and return the corresponding
'Map' with 'ExtensionsResult's.
-}
getPackageExtentionsBySources
    :: FilePath  -- ^ Path to @.cabal@ file.
    -> Map FilePath ByteString  -- ^ Path to modules with corresponding sources.
    -> IO (Map FilePath ExtensionsResult)
getPackageExtentionsBySources :: FilePath
-> Map FilePath ByteString -> IO (Map FilePath ExtensionsResult)
getPackageExtentionsBySources cabalFile :: FilePath
cabalFile sourcesMap :: Map FilePath ByteString
sourcesMap =
    FilePath
-> IO (Either ExtensionsError (Map FilePath ParsedExtensions))
parseCabalHandleException FilePath
cabalFile IO (Either ExtensionsError (Map FilePath ParsedExtensions))
-> (Either ExtensionsError (Map FilePath ParsedExtensions)
    -> Map FilePath ExtensionsResult)
-> IO (Map FilePath ExtensionsResult)
forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&> \case
        Left err :: ExtensionsError
err -> ExtensionsError -> ExtensionsResult
forall a b. a -> Either a b
Left ExtensionsError
err ExtensionsResult
-> Map FilePath ByteString -> Map FilePath ExtensionsResult
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ Map FilePath ByteString
sourcesMap
        Right cabalMap :: Map FilePath ParsedExtensions
cabalMap -> SimpleWhenMissing FilePath ParsedExtensions ExtensionsResult
-> SimpleWhenMissing FilePath ByteString ExtensionsResult
-> SimpleWhenMatched
     FilePath ParsedExtensions ByteString ExtensionsResult
-> Map FilePath ParsedExtensions
-> Map FilePath ByteString
-> Map FilePath ExtensionsResult
forall k a c b.
Ord k =>
SimpleWhenMissing k a c
-> SimpleWhenMissing k b c
-> SimpleWhenMatched k a b c
-> Map k a
-> Map k b
-> Map k c
merge
            ((FilePath -> ParsedExtensions -> ExtensionsResult)
-> SimpleWhenMissing FilePath ParsedExtensions ExtensionsResult
forall (f :: * -> *) k x y.
Applicative f =>
(k -> x -> y) -> WhenMissing f k x y
mapMissing FilePath -> ParsedExtensions -> ExtensionsResult
cabalNotSource) -- in cabal but not in sources
            ((FilePath -> ByteString -> ExtensionsResult)
-> SimpleWhenMissing FilePath ByteString ExtensionsResult
forall (f :: * -> *) k x y.
Applicative f =>
(k -> x -> y) -> WhenMissing f k x y
mapMissing FilePath -> ByteString -> ExtensionsResult
sourceNotCabal) -- in sources but not in cabal
            ((FilePath -> ParsedExtensions -> ByteString -> ExtensionsResult)
-> SimpleWhenMatched
     FilePath ParsedExtensions ByteString ExtensionsResult
forall (f :: * -> *) k x y z.
Applicative f =>
(k -> x -> y -> z) -> WhenMatched f k x y z
zipWithMatched FilePath -> ParsedExtensions -> ByteString -> ExtensionsResult
cabalAndSource) -- in cabal and sources
            Map FilePath ParsedExtensions
cabalMap
            Map FilePath ByteString
sourcesMap
  where
    cabalNotSource :: FilePath -> ParsedExtensions -> ExtensionsResult
    cabalNotSource :: FilePath -> ParsedExtensions -> ExtensionsResult
cabalNotSource path :: FilePath
path _cabalExts :: ParsedExtensions
_cabalExts = ExtensionsError -> ExtensionsResult
forall a b. a -> Either a b
Left (ExtensionsError -> ExtensionsResult)
-> ExtensionsError -> ExtensionsResult
forall a b. (a -> b) -> a -> b
$ FilePath -> ExtensionsError
SourceNotFound FilePath
path

    sourceNotCabal :: FilePath -> ByteString -> ExtensionsResult
    sourceNotCabal :: FilePath -> ByteString -> ExtensionsResult
sourceNotCabal path :: FilePath
path _source :: ByteString
_source = ExtensionsError -> ExtensionsResult
forall a b. a -> Either a b
Left (ExtensionsError -> ExtensionsResult)
-> ExtensionsError -> ExtensionsResult
forall a b. (a -> b) -> a -> b
$ FilePath -> ExtensionsError
NotCabalModule FilePath
path

    cabalAndSource
        :: FilePath
        -> ParsedExtensions
        -> ByteString
        -> ExtensionsResult
    cabalAndSource :: FilePath -> ParsedExtensions -> ByteString -> ExtensionsResult
cabalAndSource path :: FilePath
path cabalExts :: ParsedExtensions
cabalExts source :: ByteString
source =
        ParsedExtensions
-> FilePath
-> Either ModuleParseError ParsedExtensions
-> ExtensionsResult
mergeCabalAndModule ParsedExtensions
cabalExts FilePath
path (Either ModuleParseError ParsedExtensions -> ExtensionsResult)
-> Either ModuleParseError ParsedExtensions -> ExtensionsResult
forall a b. (a -> b) -> a -> b
$ FilePath -> ByteString -> Either ModuleParseError ParsedExtensions
parseSourceWithPath FilePath
path ByteString
source

{- | By given path to @.cabal@ file and path to Haskell module of the
corresponding package, analyse and return extensions for the
given module separately from .cabal file and from the module itself.
-}
getModuleAndCabalExtentions
    :: FilePath  -- ^ Path to @.cabal@ file.
    -> FilePath  -- ^ Path to Haskell module file.
    -> IO (Either ExtensionsError CabalAndModuleExtensions)
getModuleAndCabalExtentions :: FilePath
-> FilePath -> IO (Either ExtensionsError CabalAndModuleExtensions)
getModuleAndCabalExtentions cabalFile :: FilePath
cabalFile path :: FilePath
path =
    FilePath
-> IO (Either ExtensionsError (Map FilePath ParsedExtensions))
parseCabalHandleException FilePath
cabalFile IO (Either ExtensionsError (Map FilePath ParsedExtensions))
-> (Either ExtensionsError (Map FilePath ParsedExtensions)
    -> IO (Either ExtensionsError CabalAndModuleExtensions))
-> IO (Either ExtensionsError CabalAndModuleExtensions)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
        Left err :: ExtensionsError
err -> Either ExtensionsError CabalAndModuleExtensions
-> IO (Either ExtensionsError CabalAndModuleExtensions)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Either ExtensionsError CabalAndModuleExtensions
 -> IO (Either ExtensionsError CabalAndModuleExtensions))
-> Either ExtensionsError CabalAndModuleExtensions
-> IO (Either ExtensionsError CabalAndModuleExtensions)
forall a b. (a -> b) -> a -> b
$ ExtensionsError -> Either ExtensionsError CabalAndModuleExtensions
forall a b. a -> Either a b
Left ExtensionsError
err
        Right cabalMap :: Map FilePath ParsedExtensions
cabalMap -> case FilePath -> Map FilePath ParsedExtensions -> Maybe ParsedExtensions
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup FilePath
path Map FilePath ParsedExtensions
cabalMap of
            Nothing        -> Either ExtensionsError CabalAndModuleExtensions
-> IO (Either ExtensionsError CabalAndModuleExtensions)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Either ExtensionsError CabalAndModuleExtensions
 -> IO (Either ExtensionsError CabalAndModuleExtensions))
-> Either ExtensionsError CabalAndModuleExtensions
-> IO (Either ExtensionsError CabalAndModuleExtensions)
forall a b. (a -> b) -> a -> b
$ ExtensionsError -> Either ExtensionsError CabalAndModuleExtensions
forall a b. a -> Either a b
Left (ExtensionsError
 -> Either ExtensionsError CabalAndModuleExtensions)
-> ExtensionsError
-> Either ExtensionsError CabalAndModuleExtensions
forall a b. (a -> b) -> a -> b
$ FilePath -> ExtensionsError
NotCabalModule FilePath
path
            Just cabalExts :: ParsedExtensions
cabalExts -> FilePath
-> ParsedExtensions
-> Either ModuleParseError ParsedExtensions
-> Either ExtensionsError CabalAndModuleExtensions
getCabalAndModuleExts FilePath
path ParsedExtensions
cabalExts (Either ModuleParseError ParsedExtensions
 -> Either ExtensionsError CabalAndModuleExtensions)
-> IO (Either ModuleParseError ParsedExtensions)
-> IO (Either ExtensionsError CabalAndModuleExtensions)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> FilePath -> IO (Either ModuleParseError ParsedExtensions)
parseFile FilePath
path

{- | By given path to @.cabal@ file and path to Haskell module of the
corresponding package, analyse and return summary set of extensions for the
given module.
-}
getModuleExtentions
    :: FilePath  -- ^ Path to @.cabal@ file.
    -> FilePath  -- ^ Path to Haskell module file.
    -> IO ExtensionsResult
getModuleExtentions :: FilePath -> FilePath -> IO ExtensionsResult
getModuleExtentions cabalFile :: FilePath
cabalFile path :: FilePath
path =
    FilePath
-> IO (Either ExtensionsError (Map FilePath ParsedExtensions))
parseCabalHandleException FilePath
cabalFile IO (Either ExtensionsError (Map FilePath ParsedExtensions))
-> (Either ExtensionsError (Map FilePath ParsedExtensions)
    -> IO ExtensionsResult)
-> IO ExtensionsResult
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
        Left err :: ExtensionsError
err -> ExtensionsResult -> IO ExtensionsResult
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ExtensionsResult -> IO ExtensionsResult)
-> ExtensionsResult -> IO ExtensionsResult
forall a b. (a -> b) -> a -> b
$ ExtensionsError -> ExtensionsResult
forall a b. a -> Either a b
Left ExtensionsError
err
        Right cabalMap :: Map FilePath ParsedExtensions
cabalMap -> case FilePath -> Map FilePath ParsedExtensions -> Maybe ParsedExtensions
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup FilePath
path Map FilePath ParsedExtensions
cabalMap of
            Nothing -> ExtensionsResult -> IO ExtensionsResult
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ExtensionsResult -> IO ExtensionsResult)
-> ExtensionsResult -> IO ExtensionsResult
forall a b. (a -> b) -> a -> b
$ ExtensionsError -> ExtensionsResult
forall a b. a -> Either a b
Left (ExtensionsError -> ExtensionsResult)
-> ExtensionsError -> ExtensionsResult
forall a b. (a -> b) -> a -> b
$ FilePath -> ExtensionsError
NotCabalModule FilePath
path
            Just cabalExts :: ParsedExtensions
cabalExts -> do
                Either ModuleParseError ParsedExtensions
moduleRes <- FilePath -> IO (Either ModuleParseError ParsedExtensions)
parseFile FilePath
path
                ExtensionsResult -> IO ExtensionsResult
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ExtensionsResult -> IO ExtensionsResult)
-> ExtensionsResult -> IO ExtensionsResult
forall a b. (a -> b) -> a -> b
$ ParsedExtensions
-> FilePath
-> Either ModuleParseError ParsedExtensions
-> ExtensionsResult
mergeCabalAndModule ParsedExtensions
cabalExts FilePath
path Either ModuleParseError ParsedExtensions
moduleRes

{- | By given path to @.cabal@ file and path to Haskell module of the
corresponding package, analyse and return extensions extensions for the
given module separately from .cabal file and from the module itself.
-}
getModuleAndCabalExtentionsBySource
    :: FilePath  -- ^ Maybe path to @.cabal@ file.
    -> FilePath  -- ^ Path to the module's source (needed for matching with cabal file).
    -> ByteString  -- ^ Source of a Haskell module file.
    -> IO (Either ExtensionsError CabalAndModuleExtensions)
getModuleAndCabalExtentionsBySource :: FilePath
-> FilePath
-> ByteString
-> IO (Either ExtensionsError CabalAndModuleExtensions)
getModuleAndCabalExtentionsBySource cabalFile :: FilePath
cabalFile path :: FilePath
path source :: ByteString
source =
    FilePath
-> IO (Either ExtensionsError (Map FilePath ParsedExtensions))
parseCabalHandleException FilePath
cabalFile IO (Either ExtensionsError (Map FilePath ParsedExtensions))
-> (Either ExtensionsError (Map FilePath ParsedExtensions)
    -> Either ExtensionsError CabalAndModuleExtensions)
-> IO (Either ExtensionsError CabalAndModuleExtensions)
forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&> \case
        Left cabalError :: ExtensionsError
cabalError -> ExtensionsError -> Either ExtensionsError CabalAndModuleExtensions
forall a b. a -> Either a b
Left ExtensionsError
cabalError
        Right cabalMap :: Map FilePath ParsedExtensions
cabalMap -> case FilePath -> Map FilePath ParsedExtensions -> Maybe ParsedExtensions
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup FilePath
path Map FilePath ParsedExtensions
cabalMap of
            Nothing        -> ExtensionsError -> Either ExtensionsError CabalAndModuleExtensions
forall a b. a -> Either a b
Left (ExtensionsError
 -> Either ExtensionsError CabalAndModuleExtensions)
-> ExtensionsError
-> Either ExtensionsError CabalAndModuleExtensions
forall a b. (a -> b) -> a -> b
$ FilePath -> ExtensionsError
NotCabalModule FilePath
path
            Just cabalExts :: ParsedExtensions
cabalExts -> FilePath
-> ParsedExtensions
-> Either ModuleParseError ParsedExtensions
-> Either ExtensionsError CabalAndModuleExtensions
getCabalAndModuleExts FilePath
path ParsedExtensions
cabalExts
                (FilePath -> ByteString -> Either ModuleParseError ParsedExtensions
parseSourceWithPath FilePath
path ByteString
source)

{- | By given path to @.cabal@ file and path to Haskell module of the
corresponding package, analyse and return combined set of extensions for the
given module.
-}
getModuleExtentionsBySource
    :: FilePath  -- ^ Maybe path to @.cabal@ file.
    -> FilePath  -- ^ Path to the module's source (needed for matching with cabal file).
    -> ByteString  -- ^ Source of a Haskell module file.
    -> IO ExtensionsResult
getModuleExtentionsBySource :: FilePath -> FilePath -> ByteString -> IO ExtensionsResult
getModuleExtentionsBySource cabalFile :: FilePath
cabalFile path :: FilePath
path source :: ByteString
source =
    FilePath
-> IO (Either ExtensionsError (Map FilePath ParsedExtensions))
parseCabalHandleException FilePath
cabalFile IO (Either ExtensionsError (Map FilePath ParsedExtensions))
-> (Either ExtensionsError (Map FilePath ParsedExtensions)
    -> ExtensionsResult)
-> IO ExtensionsResult
forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&> \case
        Left cabalError :: ExtensionsError
cabalError -> ExtensionsError -> ExtensionsResult
forall a b. a -> Either a b
Left ExtensionsError
cabalError
        Right cabalMap :: Map FilePath ParsedExtensions
cabalMap -> case FilePath -> Map FilePath ParsedExtensions -> Maybe ParsedExtensions
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup FilePath
path Map FilePath ParsedExtensions
cabalMap of
            Nothing        -> ExtensionsError -> ExtensionsResult
forall a b. a -> Either a b
Left (ExtensionsError -> ExtensionsResult)
-> ExtensionsError -> ExtensionsResult
forall a b. (a -> b) -> a -> b
$ FilePath -> ExtensionsError
NotCabalModule FilePath
path
            Just cabalExts :: ParsedExtensions
cabalExts -> ParsedExtensions
-> FilePath
-> Either ModuleParseError ParsedExtensions
-> ExtensionsResult
mergeCabalAndModule ParsedExtensions
cabalExts FilePath
path
                (FilePath -> ByteString -> Either ModuleParseError ParsedExtensions
parseSourceWithPath FilePath
path ByteString
source)

----------------------------------------------------------------------------
-- Internal helpers
----------------------------------------------------------------------------

mergeCabalAndModule
    :: ParsedExtensions
    -> FilePath
    -> Either ModuleParseError ParsedExtensions
    -> ExtensionsResult
mergeCabalAndModule :: ParsedExtensions
-> FilePath
-> Either ModuleParseError ParsedExtensions
-> ExtensionsResult
mergeCabalAndModule cabalExts :: ParsedExtensions
cabalExts path :: FilePath
path moduleRes :: Either ModuleParseError ParsedExtensions
moduleRes = case Either ModuleParseError ParsedExtensions
moduleRes of
    Right moduleExts :: ParsedExtensions
moduleExts -> ParsedExtensions -> ParsedExtensions -> ExtensionsResult
mergeAnyExtensions ParsedExtensions
cabalExts ParsedExtensions
moduleExts
    Left parseErr :: ModuleParseError
parseErr    -> ExtensionsError -> ExtensionsResult
forall a b. a -> Either a b
Left (ExtensionsError -> ExtensionsResult)
-> ExtensionsError -> ExtensionsResult
forall a b. (a -> b) -> a -> b
$ FilePath -> ModuleParseError -> ExtensionsError
ModuleParseError FilePath
path ModuleParseError
parseErr

-- | 'parseCabalFileExtensions' with 'handleCabalException'.
parseCabalHandleException
    :: FilePath
    -> IO (Either ExtensionsError (Map FilePath ParsedExtensions))
parseCabalHandleException :: FilePath
-> IO (Either ExtensionsError (Map FilePath ParsedExtensions))
parseCabalHandleException cabalFile :: FilePath
cabalFile = (Map FilePath ParsedExtensions
-> Either ExtensionsError (Map FilePath ParsedExtensions)
forall a b. b -> Either a b
Right (Map FilePath ParsedExtensions
 -> Either ExtensionsError (Map FilePath ParsedExtensions))
-> IO (Map FilePath ParsedExtensions)
-> IO (Either ExtensionsError (Map FilePath ParsedExtensions))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> FilePath -> IO (Map FilePath ParsedExtensions)
parseCabalFileExtensions FilePath
cabalFile)
    IO (Either ExtensionsError (Map FilePath ParsedExtensions))
-> (CabalException
    -> IO (Either ExtensionsError (Map FilePath ParsedExtensions)))
-> IO (Either ExtensionsError (Map FilePath ParsedExtensions))
forall e a. Exception e => IO a -> (e -> IO a) -> IO a
`catch` CabalException
-> IO (Either ExtensionsError (Map FilePath ParsedExtensions))
handleCabalException

-- | Handle 'CabalException' and return corresponding 'CabalError'.
handleCabalException
    :: CabalException
    -> IO (Either ExtensionsError (Map FilePath ParsedExtensions))
handleCabalException :: CabalException
-> IO (Either ExtensionsError (Map FilePath ParsedExtensions))
handleCabalException = Either ExtensionsError (Map FilePath ParsedExtensions)
-> IO (Either ExtensionsError (Map FilePath ParsedExtensions))
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Either ExtensionsError (Map FilePath ParsedExtensions)
 -> IO (Either ExtensionsError (Map FilePath ParsedExtensions)))
-> (CabalException
    -> Either ExtensionsError (Map FilePath ParsedExtensions))
-> CabalException
-> IO (Either ExtensionsError (Map FilePath ParsedExtensions))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ExtensionsError
-> Either ExtensionsError (Map FilePath ParsedExtensions)
forall a b. a -> Either a b
Left (ExtensionsError
 -> Either ExtensionsError (Map FilePath ParsedExtensions))
-> (CabalException -> ExtensionsError)
-> CabalException
-> Either ExtensionsError (Map FilePath ParsedExtensions)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CabalException -> ExtensionsError
CabalError

getCabalAndModuleExts
    :: FilePath
    -> ParsedExtensions
    -> Either ModuleParseError ParsedExtensions
    -> Either ExtensionsError CabalAndModuleExtensions
getCabalAndModuleExts :: FilePath
-> ParsedExtensions
-> Either ModuleParseError ParsedExtensions
-> Either ExtensionsError CabalAndModuleExtensions
getCabalAndModuleExts path :: FilePath
path cabalExts :: ParsedExtensions
cabalExts moduleRes :: Either ModuleParseError ParsedExtensions
moduleRes = case Either ModuleParseError ParsedExtensions
moduleRes of
    Left err :: ModuleParseError
err -> ExtensionsError -> Either ExtensionsError CabalAndModuleExtensions
forall a b. a -> Either a b
Left (ExtensionsError
 -> Either ExtensionsError CabalAndModuleExtensions)
-> ExtensionsError
-> Either ExtensionsError CabalAndModuleExtensions
forall a b. (a -> b) -> a -> b
$ FilePath -> ModuleParseError -> ExtensionsError
ModuleParseError FilePath
path ModuleParseError
err
    Right moduleExts :: ParsedExtensions
moduleExts -> CabalAndModuleExtensions
-> Either ExtensionsError CabalAndModuleExtensions
forall a b. b -> Either a b
Right (CabalAndModuleExtensions
 -> Either ExtensionsError CabalAndModuleExtensions)
-> CabalAndModuleExtensions
-> Either ExtensionsError CabalAndModuleExtensions
forall a b. (a -> b) -> a -> b
$ $WCabalAndModuleExtensions :: ParsedExtensions -> ParsedExtensions -> CabalAndModuleExtensions
CabalAndModuleExtensions
        { cabalExtensions :: ParsedExtensions
cabalExtensions  = ParsedExtensions
cabalExts
        , moduleExtensions :: ParsedExtensions
moduleExtensions = ParsedExtensions
moduleExts
        }