Drop DeriveDataTypeable extension
[ghc.git] / src / Package.hs
1 {-# LANGUAGE DeriveGeneric, GeneralizedNewtypeDeriving #-}
2
3 module Package (
4 Package (..), PackageName (..), PackageType (..),
5 -- * Queries
6 pkgNameString,
7 pkgCabalFile,
8 matchPackageNames,
9 -- * Helpers for constructing and using 'Package's
10 setPath, topLevel, library, utility, setType, isLibrary, isProgram
11 ) where
12
13 import Base
14 import GHC.Generics (Generic)
15 import Data.String
16
17 -- | The name of a Cabal package
18 newtype PackageName = PackageName { fromPackageName :: String }
19 deriving (Eq, Ord, IsString, Generic, Binary, Hashable, Typeable, NFData)
20
21 -- TODO: Make PackageType more precise, #12
22 -- TODO: Turn Program to Program FilePath thereby getting rid of programPath
23 -- | We regard packages as either being libraries or programs. This is
24 -- bit of a convenient lie as Cabal packages can be both, but it works
25 -- for now.
26 data PackageType = Program | Library deriving Generic
27
28 data Package = Package
29 { pkgName :: PackageName -- ^ Examples: "ghc", "Cabal"
30 , pkgPath :: FilePath -- ^ pkgPath is the path to the source code relative to the root.
31 -- e.g. "compiler", "libraries/Cabal/Cabal"
32 , pkgType :: PackageType
33 } deriving Generic
34
35 -- | Prettyprint Package name.
36 pkgNameString :: Package -> String
37 pkgNameString = fromPackageName . pkgName
38
39 -- | Relative path to cabal file, e.g.: "libraries/Cabal/Cabal/Cabal.cabal"
40 pkgCabalFile :: Package -> FilePath
41 pkgCabalFile pkg = pkgPath pkg -/- pkgNameString pkg <.> "cabal"
42
43 -- | Smart constructor for a top-level package, e.g. 'compiler'.
44 topLevel :: PackageName -> Package
45 topLevel name = Package name (fromPackageName name) Library
46
47 -- | Smart constructor for a library package, e.g. 'array'.
48 library :: PackageName -> Package
49 library name = Package name ("libraries" -/- fromPackageName name) Library
50
51 -- | Smart constructor for a utility package, e.g. 'haddock'.
52 utility :: PackageName -> Package
53 utility name = Package name ("utils" -/- fromPackageName name) Program
54
55 -- | Amend package path. Useful when a package name doesn't match its path.
56 setPath :: Package -> FilePath -> Package
57 setPath pkg path = pkg { pkgPath = path }
58
59 -- | Amend package type.
60 setType :: Package -> PackageType -> Package
61 setType pkg ty = pkg { pkgType = ty }
62
63 -- | Check whether a package is a library.
64 isLibrary :: Package -> Bool
65 isLibrary (Package _ _ Library) = True
66 isLibrary _ = False
67
68 -- | Check whether a package is a program.
69 isProgram :: Package -> Bool
70 isProgram (Package _ _ Program) = True
71 isProgram _ = False
72
73 -- TODO: Get rid of non-derived Show instances.
74 instance Show Package where
75 show = pkgNameString
76
77 instance Eq Package where
78 (==) = (==) `on` pkgName
79
80 instance Ord Package where
81 compare = compare `on` pkgName
82
83 -- | Given a sorted list of packages and a sorted list of package names, returns
84 -- packages whose names appear in the list of names.
85 matchPackageNames :: [Package] -> [PackageName] -> [Package]
86 matchPackageNames = intersectOrd (\pkg name -> compare (pkgName pkg) name)
87
88 -- Instances for storing in the Shake database
89 instance Binary Package
90 instance Hashable Package where
91 hashWithSalt salt = hashWithSalt salt . show
92 instance NFData Package
93
94 instance Binary PackageType
95 instance Hashable PackageType
96 instance NFData PackageType