    {-# LANGUAGE DeriveDataTypeable #-}
    {-# LANGUAGE DeriveGeneric #-}

    module Distribution.Types.ComponentName (
      ComponentName(..),
      showComponentName,
      componentNameStanza,
      componentNameString,
      ) where

    import Prelude ()
    import Distribution.Compat.Prelude

    import Distribution.Types.UnqualComponentName
    import Distribution.Types.LibraryName
    import Distribution.Pretty
    import Distribution.Parsec

    import qualified Text.PrettyPrint as Disp
    import qualified Distribution.Compat.CharParsing as P

    -- Libraries live in a separate namespace, so must distinguish
    data ComponentName = CLibName   LibraryName
                       | CFLibName  UnqualComponentName
                       | CExeName   UnqualComponentName
                       | CTestName  UnqualComponentName
                       | CBenchName UnqualComponentName
                       deriving (ComponentName -> ComponentName -> Bool
    (ComponentName -> ComponentName -> Bool)
    -> (ComponentName -> ComponentName -> Bool) -> Eq ComponentName
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    /= :: ComponentName -> ComponentName -> Bool
    $c/= :: ComponentName -> ComponentName -> Bool
    == :: ComponentName -> ComponentName -> Bool
    $c== :: ComponentName -> ComponentName -> Bool
    Eq, (forall x. ComponentName -> Rep ComponentName x)
    -> (forall x. Rep ComponentName x -> ComponentName)
    -> Generic ComponentName
    forall x. Rep ComponentName x -> ComponentName
    forall x. ComponentName -> Rep ComponentName x
    forall a.
    (forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
    $cto :: forall x. Rep ComponentName x -> ComponentName
    $cfrom :: forall x. ComponentName -> Rep ComponentName x
    Generic, Eq ComponentName
    Eq ComponentName
    -> (ComponentName -> ComponentName -> Ordering)
    -> (ComponentName -> ComponentName -> Bool)
    -> (ComponentName -> ComponentName -> Bool)
    -> (ComponentName -> ComponentName -> Bool)
    -> (ComponentName -> ComponentName -> Bool)
    -> (ComponentName -> ComponentName -> ComponentName)
    -> (ComponentName -> ComponentName -> ComponentName)
    -> Ord ComponentName
    ComponentName -> ComponentName -> Bool
    ComponentName -> ComponentName -> Ordering
    ComponentName -> ComponentName -> ComponentName
    forall a.
    Eq a
    -> (a -> a -> Ordering)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> a)
    -> (a -> a -> a)
    -> Ord a
    min :: ComponentName -> ComponentName -> ComponentName
    $cmin :: ComponentName -> ComponentName -> ComponentName
    max :: ComponentName -> ComponentName -> ComponentName
    $cmax :: ComponentName -> ComponentName -> ComponentName
    >= :: ComponentName -> ComponentName -> Bool
    $c>= :: ComponentName -> ComponentName -> Bool
    > :: ComponentName -> ComponentName -> Bool
    $c> :: ComponentName -> ComponentName -> Bool
    <= :: ComponentName -> ComponentName -> Bool
    $c<= :: ComponentName -> ComponentName -> Bool
    < :: ComponentName -> ComponentName -> Bool
    $c< :: ComponentName -> ComponentName -> Bool
    compare :: ComponentName -> ComponentName -> Ordering
    $ccompare :: ComponentName -> ComponentName -> Ordering
    Ord, ReadPrec [ComponentName]
    ReadPrec ComponentName
    Int -> ReadS ComponentName
    ReadS [ComponentName]
    (Int -> ReadS ComponentName)
    -> ReadS [ComponentName]
    -> ReadPrec ComponentName
    -> ReadPrec [ComponentName]
    -> Read ComponentName
    forall a.
    (Int -> ReadS a)
    -> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
    readListPrec :: ReadPrec [ComponentName]
    $creadListPrec :: ReadPrec [ComponentName]
    readPrec :: ReadPrec ComponentName
    $creadPrec :: ReadPrec ComponentName
    readList :: ReadS [ComponentName]
    $creadList :: ReadS [ComponentName]
    readsPrec :: Int -> ReadS ComponentName
    $creadsPrec :: Int -> ReadS ComponentName
    Read, Int -> ComponentName -> ShowS
    [ComponentName] -> ShowS
    ComponentName -> String
    (Int -> ComponentName -> ShowS)
    -> (ComponentName -> String)
    -> ([ComponentName] -> ShowS)
    -> Show ComponentName
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    showList :: [ComponentName] -> ShowS
    $cshowList :: [ComponentName] -> ShowS
    show :: ComponentName -> String
    $cshow :: ComponentName -> String
    showsPrec :: Int -> ComponentName -> ShowS
    $cshowsPrec :: Int -> ComponentName -> ShowS
    Show, Typeable)

    instance Binary ComponentName
    instance Structured ComponentName

    -- Build-target-ish syntax
    instance Pretty ComponentName where
        pretty :: ComponentName -> Doc
    pretty (CLibName LibraryName
    lib)    = LibraryName -> Doc
    prettyLibraryNameComponent LibraryName
    lib
        pretty (CFLibName UnqualComponentName
    str)   = String -> Doc
    Disp.text String
    "flib:" Doc -> Doc -> Doc
    <<>> UnqualComponentName -> Doc
    forall a. Pretty a => a -> Doc
    pretty UnqualComponentName
    str
        pretty (CExeName UnqualComponentName
    str)    = String -> Doc
    Disp.text String
    "exe:" Doc -> Doc -> Doc
    <<>> UnqualComponentName -> Doc
    forall a. Pretty a => a -> Doc
    pretty UnqualComponentName
    str
        pretty (CTestName UnqualComponentName
    str)   = String -> Doc
    Disp.text String
    "test:" Doc -> Doc -> Doc
    <<>> UnqualComponentName -> Doc
    forall a. Pretty a => a -> Doc
    pretty UnqualComponentName
    str
        pretty (CBenchName UnqualComponentName
    str)  = String -> Doc
    Disp.text String
    "bench:" Doc -> Doc -> Doc
    <<>> UnqualComponentName -> Doc
    forall a. Pretty a => a -> Doc
    pretty UnqualComponentName
    str

    instance Parsec ComponentName where
        -- note: this works as lib/flib/... all start with different character!
        parsec :: forall (m :: * -> *). CabalParsing m => m ComponentName
    parsec = m ComponentName
    parseComposite m ComponentName -> m ComponentName -> m ComponentName
    forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
    <|> m ComponentName
    parseLib
          where
            parseLib :: m ComponentName
    parseLib = LibraryName -> ComponentName
    CLibName (LibraryName -> ComponentName) -> m LibraryName -> m ComponentName
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> m LibraryName
    forall (m :: * -> *). CabalParsing m => m LibraryName
    parsecLibraryNameComponent
            parseComposite :: m ComponentName
    parseComposite = do
                UnqualComponentName -> ComponentName
    ctor <- [m (UnqualComponentName -> ComponentName)]
    -> m (UnqualComponentName -> ComponentName)
    forall (m :: * -> *) a. Alternative m => [m a] -> m a
    P.choice
                    [ String -> m String
    forall (m :: * -> *). CharParsing m => String -> m String
    P.string String
    "flib:" m String
    -> m (UnqualComponentName -> ComponentName)
    -> m (UnqualComponentName -> ComponentName)
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> (UnqualComponentName -> ComponentName)
    -> m (UnqualComponentName -> ComponentName)
    forall (m :: * -> *) a. Monad m => a -> m a
    return UnqualComponentName -> ComponentName
    CFLibName
                    , String -> m String
    forall (m :: * -> *). CharParsing m => String -> m String
    P.string String
    "exe:" m String
    -> m (UnqualComponentName -> ComponentName)
    -> m (UnqualComponentName -> ComponentName)
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> (UnqualComponentName -> ComponentName)
    -> m (UnqualComponentName -> ComponentName)
    forall (m :: * -> *) a. Monad m => a -> m a
    return UnqualComponentName -> ComponentName
    CExeName
                    , String -> m String
    forall (m :: * -> *). CharParsing m => String -> m String
    P.string String
    "bench:" m String
    -> m (UnqualComponentName -> ComponentName)
    -> m (UnqualComponentName -> ComponentName)
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> (UnqualComponentName -> ComponentName)
    -> m (UnqualComponentName -> ComponentName)
    forall (m :: * -> *) a. Monad m => a -> m a
    return UnqualComponentName -> ComponentName
    CBenchName
                    , String -> m String
    forall (m :: * -> *). CharParsing m => String -> m String
    P.string String
    "test:" m String
    -> m (UnqualComponentName -> ComponentName)
    -> m (UnqualComponentName -> ComponentName)
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> (UnqualComponentName -> ComponentName)
    -> m (UnqualComponentName -> ComponentName)
    forall (m :: * -> *) a. Monad m => a -> m a
    return UnqualComponentName -> ComponentName
    CTestName
                    ]
                UnqualComponentName -> ComponentName
    ctor (UnqualComponentName -> ComponentName)
    -> m UnqualComponentName -> m ComponentName
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> m UnqualComponentName
    forall a (m :: * -> *). (Parsec a, CabalParsing m) => m a
    parsec

    showComponentName :: ComponentName -> String
    showComponentName :: ComponentName -> String
    showComponentName (CLibName LibraryName
    lib)    = LibraryName -> String
    showLibraryName LibraryName
    lib
    showComponentName (CFLibName  UnqualComponentName
    name) = String
    "foreign library '" String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ UnqualComponentName -> String
    forall a. Pretty a => a -> String
    prettyShow UnqualComponentName
    name String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ String
    "'"
    showComponentName (CExeName   UnqualComponentName
    name) = String
    "executable '" String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ UnqualComponentName -> String
    forall a. Pretty a => a -> String
    prettyShow UnqualComponentName
    name String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ String
    "'"
    showComponentName (CTestName  UnqualComponentName
    name) = String
    "test suite '" String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ UnqualComponentName -> String
    forall a. Pretty a => a -> String
    prettyShow UnqualComponentName
    name String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ String
    "'"
    showComponentName (CBenchName UnqualComponentName
    name) = String
    "benchmark '" String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ UnqualComponentName -> String
    forall a. Pretty a => a -> String
    prettyShow UnqualComponentName
    name String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ String
    "'"

    componentNameStanza :: ComponentName -> String
    componentNameStanza :: ComponentName -> String
    componentNameStanza (CLibName LibraryName
    lib)    = LibraryName -> String
    libraryNameStanza LibraryName
    lib
    componentNameStanza (CFLibName  UnqualComponentName
    name) = String
    "foreign-library " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ UnqualComponentName -> String
    forall a. Pretty a => a -> String
    prettyShow UnqualComponentName
    name
    componentNameStanza (CExeName   UnqualComponentName
    name) = String
    "executable " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ UnqualComponentName -> String
    forall a. Pretty a => a -> String
    prettyShow UnqualComponentName
    name
    componentNameStanza (CTestName  UnqualComponentName
    name) = String
    "test-suite " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ UnqualComponentName -> String
    forall a. Pretty a => a -> String
    prettyShow UnqualComponentName
    name
    componentNameStanza (CBenchName UnqualComponentName
    name) = String
    "benchmark " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ UnqualComponentName -> String
    forall a. Pretty a => a -> String
    prettyShow UnqualComponentName
    name

    -- | This gets the underlying unqualified component name. In fact, it is
    -- guaranteed to uniquely identify a component, returning
    -- @Nothing@ if the 'ComponentName' was for the public
    -- library.
    componentNameString :: ComponentName -> Maybe UnqualComponentName
    componentNameString :: ComponentName -> Maybe UnqualComponentName
    componentNameString (CLibName LibraryName
    lib) = LibraryName -> Maybe UnqualComponentName
    libraryNameString LibraryName
    lib
    componentNameString (CFLibName  UnqualComponentName
    n) = UnqualComponentName -> Maybe UnqualComponentName
    forall a. a -> Maybe a
    Just UnqualComponentName
    n
    componentNameString (CExeName   UnqualComponentName
    n) = UnqualComponentName -> Maybe UnqualComponentName
    forall a. a -> Maybe a
    Just UnqualComponentName
    n
    componentNameString (CTestName  UnqualComponentName
    n) = UnqualComponentName -> Maybe UnqualComponentName
    forall a. a -> Maybe a
    Just UnqualComponentName
    n
    componentNameString (CBenchName UnqualComponentName
    n) = UnqualComponentName -> Maybe UnqualComponentName
    forall a. a -> Maybe a
    Just UnqualComponentName
    n