make LTS branch pre-releases
[cabal.git] / Cabal-syntax / src / Distribution / Types / Mixin.hs
blob63fa6e30fd5f043fd8ec86292ea70259171ecb3b
1 {-# LANGUAGE DeriveDataTypeable #-}
2 {-# LANGUAGE DeriveGeneric #-}
4 module Distribution.Types.Mixin
5 ( Mixin (..)
6 , mkMixin
7 , normaliseMixin
8 ) where
10 import Distribution.Compat.Prelude
11 import Prelude ()
13 import Distribution.CabalSpecVersion
14 import Distribution.Parsec
15 import Distribution.Pretty
16 import Distribution.Types.IncludeRenaming
17 import Distribution.Types.LibraryName
18 import Distribution.Types.PackageName
19 import Distribution.Types.UnqualComponentName
21 import qualified Distribution.Compat.CharParsing as P
22 import qualified Text.PrettyPrint as PP
24 -- |
26 -- /Invariant:/ if 'mixinLibraryName' is 'LSubLibName', it's not
27 -- the same as 'mixinPackageName'. In other words,
28 -- the same invariant as 'Dependency' has.
29 data Mixin = Mixin
30 { mixinPackageName :: PackageName
31 , mixinLibraryName :: LibraryName
32 , mixinIncludeRenaming :: IncludeRenaming
34 deriving (Show, Read, Eq, Ord, Typeable, Data, Generic)
36 instance Binary Mixin
37 instance Structured Mixin
39 instance NFData Mixin where rnf = genericRnf
41 instance Pretty Mixin where
42 pretty (Mixin pn LMainLibName incl) = pretty pn <+> pretty incl
43 pretty (Mixin pn (LSubLibName ln) incl) = pretty pn <<>> PP.colon <<>> pretty ln <+> pretty incl
45 -- |
47 -- >>> simpleParsec "mylib" :: Maybe Mixin
48 -- Just (Mixin {mixinPackageName = PackageName "mylib", mixinLibraryName = LMainLibName, mixinIncludeRenaming = IncludeRenaming {includeProvidesRn = DefaultRenaming, includeRequiresRn = DefaultRenaming}})
50 -- >>> simpleParsec "thatlib:sublib" :: Maybe Mixin
51 -- Just (Mixin {mixinPackageName = PackageName "thatlib", mixinLibraryName = LSubLibName (UnqualComponentName "sublib"), mixinIncludeRenaming = IncludeRenaming {includeProvidesRn = DefaultRenaming, includeRequiresRn = DefaultRenaming}})
53 -- >>> simpleParsec "thatlib:thatlib" :: Maybe Mixin
54 -- Just (Mixin {mixinPackageName = PackageName "thatlib", mixinLibraryName = LMainLibName, mixinIncludeRenaming = IncludeRenaming {includeProvidesRn = DefaultRenaming, includeRequiresRn = DefaultRenaming}})
56 -- Sublibrary syntax is accepted since @cabal-version: 3.4@.
58 -- >>> map (`simpleParsec'` "mylib:sub") [CabalSpecV3_0, CabalSpecV3_4] :: [Maybe Mixin]
59 -- [Nothing,Just (Mixin {mixinPackageName = PackageName "mylib", mixinLibraryName = LSubLibName (UnqualComponentName "sub"), mixinIncludeRenaming = IncludeRenaming {includeProvidesRn = DefaultRenaming, includeRequiresRn = DefaultRenaming}})]
60 instance Parsec Mixin where
61 parsec = do
62 pn <- parsec
63 ln <- P.option LMainLibName $ do
64 _ <- P.char ':'
65 versionGuardMultilibs
66 LSubLibName <$> parsec
67 P.spaces
68 incl <- parsec
69 return (mkMixin pn ln incl)
71 versionGuardMultilibs :: CabalParsing m => m ()
72 versionGuardMultilibs = do
73 csv <- askCabalSpecVersion
74 when (csv < CabalSpecV3_4) $
75 fail $
76 unwords
77 [ "Sublibrary mixin syntax used."
78 , "To use this syntax the package needs to specify at least 'cabal-version: 3.4'."
81 -- | Smart constructor of 'Mixin', enforces invariant.
83 -- @since 3.4.0.0
84 mkMixin :: PackageName -> LibraryName -> IncludeRenaming -> Mixin
85 mkMixin pn (LSubLibName uqn) incl
86 | packageNameToUnqualComponentName pn == uqn =
87 Mixin pn LMainLibName incl
88 mkMixin pn ln incl =
89 Mixin pn ln incl
91 -- | Restore invariant
92 normaliseMixin :: Mixin -> Mixin
93 normaliseMixin (Mixin pn ln incl) = mkMixin pn ln incl