stack-3.7.1: src/Stack/Types/NamedComponent.hs
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE OverloadedStrings #-}
{-|
Module : Stack.Types.NamedComponent
Description : Module exporting the 'NamedComponent' type and related functions.
License : BSD-3-Clause
Module exporting the 'NamedComponent' type and related functions.
-}
module Stack.Types.NamedComponent
( NamedComponent (..)
, componentCachePath
, renderComponent
, renderComponentTo
, renderPkgComponents
, renderPkgComponent
, exeComponents
, testComponents
, benchComponents
, subLibComponents
, isCLib
, isCSubLib
, isCExe
, isCTest
, isCBench
, isPotentialDependency
, splitComponents
) where
import qualified Data.Set as Set
import qualified Data.Text as T
import Stack.Prelude
import Stack.Types.ComponentUtils
( StackUnqualCompName, unqualCompToString, unqualCompToText
)
-- | Type representing components of a fully-resolved Cabal package.
data NamedComponent
= CLib
-- The \'main\' unnamed library component.
| CSubLib !StackUnqualCompName
-- A named \'subsidiary\' or \'ancillary\` library component (sub-library).
| CFlib !StackUnqualCompName
-- A foreign library.
| CExe !StackUnqualCompName
-- A named executable component.
| CTest !StackUnqualCompName
-- A named test-suite component.
| CBench !StackUnqualCompName
-- A named benchmark component.
deriving (Eq, Ord, Show)
-- | Render a component to anything with an "IsString" instance. For 'Text'
-- prefer 'renderComponent'.
renderComponentTo :: IsString a => NamedComponent -> a
renderComponentTo = fromString . T.unpack . renderComponent
renderComponent :: NamedComponent -> Text
renderComponent CLib = "lib"
renderComponent (CSubLib x) = "sub-lib:" <> unqualCompToText x
renderComponent (CFlib x) = "flib:" <> unqualCompToText x
renderComponent (CExe x) = "exe:" <> unqualCompToText x
renderComponent (CTest x) = "test:" <> unqualCompToText x
renderComponent (CBench x) = "bench:" <> unqualCompToText x
componentCachePath :: NamedComponent -> String
componentCachePath CLib = "lib"
componentCachePath (CSubLib x) = "sub-lib-" <> unqualCompToString x
componentCachePath (CFlib x) = "flib-" <> unqualCompToString x
componentCachePath (CExe x) = "exe-" <> unqualCompToString x
componentCachePath (CTest x) = "test-" <> unqualCompToString x
componentCachePath (CBench x) = "bench-" <> unqualCompToString x
renderPkgComponents :: [(PackageName, NamedComponent)] -> Text
renderPkgComponents = T.intercalate " " . map renderPkgComponent
renderPkgComponent :: (PackageName, NamedComponent) -> Text
renderPkgComponent (pkg, comp) =
fromPackageName pkg <> ":" <> renderComponent comp
exeComponents :: Set NamedComponent -> Set StackUnqualCompName
exeComponents = Set.fromList . mapMaybe mExeName . Set.toList
where
mExeName (CExe name) = Just name
mExeName _ = Nothing
testComponents :: Set NamedComponent -> Set StackUnqualCompName
testComponents = Set.fromList . mapMaybe mTestName . Set.toList
where
mTestName (CTest name) = Just name
mTestName _ = Nothing
benchComponents :: Set NamedComponent -> Set StackUnqualCompName
benchComponents = Set.fromList . mapMaybe mBenchName . Set.toList
where
mBenchName (CBench name) = Just name
mBenchName _ = Nothing
subLibComponents :: Set NamedComponent -> Set StackUnqualCompName
subLibComponents = Set.fromList . mapMaybe mSubLibName . Set.toList
where
mSubLibName (CSubLib name) = Just name
mSubLibName _ = Nothing
isCLib :: NamedComponent -> Bool
isCLib CLib{} = True
isCLib _ = False
isCSubLib :: NamedComponent -> Bool
isCSubLib CSubLib{} = True
isCSubLib _ = False
isCExe :: NamedComponent -> Bool
isCExe CExe{} = True
isCExe _ = False
isCTest :: NamedComponent -> Bool
isCTest CTest{} = True
isCTest _ = False
isCBench :: NamedComponent -> Bool
isCBench CBench{} = True
isCBench _ = False
isPotentialDependency :: NamedComponent -> Bool
isPotentialDependency v = isCLib v || isCSubLib v || isCExe v
-- | A function to split the given list of components into sets of the names of
-- the named components by the type of component (sub-libraries, executables,
-- test-suites, benchmarks), ignoring any \'main\' unnamed library component or
-- foreign library component. This function should be used very sparingly; more
-- often than not, you can keep/parse the components split from the start.
splitComponents ::
[NamedComponent]
-> ( Set StackUnqualCompName
-- ^ Sub-libraries.
, Set StackUnqualCompName
-- ^ Executables.
, Set StackUnqualCompName
-- ^ Test-suites.
, Set StackUnqualCompName
-- ^ Benchmarks.
)
splitComponents =
go id id id id
where
run c = Set.fromList $ c []
go s e t b [] = (run s, run e, run t, run b)
go s e t b (CLib : xs) = go s e t b xs
go s e t b (CSubLib x : xs) = go (s . (x:)) e t b xs
-- Ignore foreign libraries, for now.
go s e t b (CFlib _ : xs) = go s e t b xs
go s e t b (CExe x : xs) = go s (e . (x:)) t b xs
go s e t b (CTest x : xs) = go s e (t . (x:)) b xs
go s e t b (CBench x : xs) = go s e t (b . (x:)) xs