Commit e45b013f authored by Oleg Grenrus's avatar Oleg Grenrus
Browse files

Add Described to IndexState (incl. tests).

- Writing a regex to parse dates is awful.
- Add ShortText conversions to PackageName and UnqualComponentName
- Add mkDependency, which maintains the invariant
- Remove VersionRangeParens - it's not preserved by parsec . pretty
  roundtrip
- Move moree instances into Cabal-quickcheck,
  use the package in cabal-install tests
parent e9b0a715
......@@ -9,8 +9,14 @@ import Test.QuickCheck
import Distribution.SPDX
import Distribution.Version
import Distribution.Types.Dependency
import Distribution.Types.UnqualComponentName
import Distribution.Simple.Flag (Flag (..))
import Distribution.Types.LibraryName
import Distribution.Types.PackageName
import Distribution.Types.VersionRange.Internal
import Distribution.System
import Distribution.Verbosity
#if !MIN_VERSION_base(4,8,0)
import Control.Applicative (pure, (<$>), (<*>))
......@@ -64,7 +70,6 @@ instance Arbitrary VersionRange where
, (1, fmap orEarlierVersion' arbitrary)
, (1, fmap withinVersion arbitrary)
, (1, fmap majorBoundVersion arbitrary)
, (2, fmap VersionRangeParens arbitrary)
] ++ if n == 0 then [] else
[ (2, liftA2 unionVersionRanges verRangeExp2 verRangeExp2)
, (2, liftA2 intersectVersionRanges verRangeExp2 verRangeExp2)
......@@ -85,7 +90,6 @@ instance Arbitrary VersionRange where
shrink (OrEarlierVersion v) = EarlierVersion v : map OrEarlierVersion (shrink v)
shrink (WildcardVersion v) = map WildcardVersion ( shrink v)
shrink (MajorBoundVersion v) = map MajorBoundVersion (shrink v)
shrink (VersionRangeParens vr) = vr : map VersionRangeParens (shrink vr)
shrink (UnionVersionRanges a b) = a : b : map (uncurry UnionVersionRanges) (shrink (a, b))
shrink (IntersectVersionRanges a b) = a : b : map (uncurry IntersectVersionRanges) (shrink (a, b))
......@@ -122,6 +126,71 @@ instance Arbitrary VersionIntervals where
instance Arbitrary Bound where
arbitrary = elements [ExclusiveBound, InclusiveBound]
-------------------------------------------------------------------------------
-- Dependency
-------------------------------------------------------------------------------
instance Arbitrary Dependency where
arbitrary = mkDependency
<$> arbitrary
<*> arbitrary
<*> (arbitrary `suchThat` const True) -- should be (not . null)
shrink (Dependency pn vr lb) =
[ mkDependency pn' vr' lb'
| (pn', vr', lb') <- shrink (pn, vr, lb)
]
-------------------------------------------------------------------------------
-- System
-------------------------------------------------------------------------------
instance Arbitrary OS where
arbitrary = elements knownOSs
instance Arbitrary Arch where
arbitrary = elements knownArches
instance Arbitrary Platform where
arbitrary = Platform <$> arbitrary <*> arbitrary
-------------------------------------------------------------------------------
-- Various names
-------------------------------------------------------------------------------
instance Arbitrary UnqualComponentName where
-- same rules as package names
arbitrary = packageNameToUnqualComponentName <$> arbitrary
instance Arbitrary LibraryName where
arbitrary = oneof
[ LSubLibName <$> arbitrary
, pure LMainLibName
]
shrink (LSubLibName _) = [LMainLibName]
shrink _ = []
instance Arbitrary a => Arbitrary (Flag a) where
arbitrary = arbitrary1
shrink NoFlag = []
shrink (Flag x) = NoFlag : [ Flag x' | x' <- shrink x ]
instance Arbitrary1 Flag where
liftArbitrary genA = sized $ \sz ->
if sz <= 0
then pure NoFlag
else frequency [ (1, pure NoFlag)
, (3, Flag <$> genA) ]
-------------------------------------------------------------------------------
-- Verbosity
-------------------------------------------------------------------------------
instance Arbitrary Verbosity where
arbitrary = elements [minBound..maxBound]
-------------------------------------------------------------------------------
-- SPDX
-------------------------------------------------------------------------------
......
......@@ -2,6 +2,7 @@
{-# LANGUAGE DeriveGeneric #-}
module Distribution.Types.Dependency
( Dependency(..)
, mkDependency
, depPkgName
, depVerRange
, depLibraries
......@@ -33,6 +34,9 @@ import qualified Text.PrettyPrint as PP
-- | Describes a dependency on a source package (API)
--
-- /Invariant:/ package name does not appear as 'LSubLibName' in
-- set of library names.
--
data Dependency = Dependency
PackageName
VersionRange
......@@ -51,35 +55,37 @@ depVerRange (Dependency _ vr _) = vr
depLibraries :: Dependency -> Set LibraryName
depLibraries (Dependency _ _ cs) = cs
-- | Smart constructor of 'Dependency'.
--
-- If 'PackageName' is appears as 'LSubLibName' in a set of sublibraries,
-- it is automatically converted to 'LMainLibName'.
--
-- @since 3.4.0.0
--
mkDependency :: PackageName -> VersionRange -> Set LibraryName -> Dependency
mkDependency pn vr lb = Dependency pn vr (Set.map conv lb)
where
pn' = packageNameToUnqualComponentName pn
conv l@LMainLibName = l
conv l@(LSubLibName ln) | ln == pn' = LMainLibName
| otherwise = l
instance Binary Dependency
instance Structured Dependency
instance NFData Dependency where rnf = genericRnf
instance Pretty Dependency where
pretty (Dependency name ver sublibs) = pretty name
<<>> optionalMonoid
(sublibs /= Set.singleton LMainLibName)
(PP.colon <<>> PP.braces prettySublibs)
<+> pretty ver
pretty (Dependency name ver sublibs) = withSubLibs (pretty name) <+> pretty ver
where
optionalMonoid True x = x
optionalMonoid False _ = mempty
withSubLibs doc
| sublibs == mainLib = doc
| otherwise = doc <<>> PP.colon <<>> PP.braces prettySublibs
prettySublibs = PP.hsep $ PP.punctuate PP.comma $ prettySublib <$> Set.toList sublibs
prettySublib LMainLibName = PP.text $ unPackageName name
prettySublib (LSubLibName un) = PP.text $ unUnqualComponentName un
versionGuardMultilibs :: (Monad m, CabalParsing m) => m a -> m a
versionGuardMultilibs expr = do
csv <- askCabalSpecVersion
if csv < CabalSpecV3_0
then fail $ unwords
[ "Sublibrary dependency syntax used."
, "To use this syntax the package needs to specify at least 'cabal-version: 3.0'."
, "Alternatively, if you are depending on an internal library, you can write"
, "directly the library name as it were a package."
]
else
expr
prettySublib LMainLibName = PP.text $ unPackageName name
prettySublib (LSubLibName un) = PP.text $ unUnqualComponentName un
-- |
--
......@@ -98,58 +104,77 @@ versionGuardMultilibs expr = do
-- >>> simpleParsec "mylib:{ } ^>= 42" :: Maybe Dependency
-- Just (Dependency (PackageName "mylib") (MajorBoundVersion (mkVersion [42])) (fromList []))
--
-- Spaces around colon are not allowed:
-- >>> traverse_ print (map simpleParsec ["mylib:mylib", "mylib:{mylib}", "mylib:{mylib,sublib}" ] :: [Maybe Dependency])
-- Just (Dependency (PackageName "mylib") AnyVersion (fromList [LMainLibName]))
-- Just (Dependency (PackageName "mylib") AnyVersion (fromList [LMainLibName]))
-- Just (Dependency (PackageName "mylib") AnyVersion (fromList [LMainLibName,LSubLibName (UnqualComponentName "sublib")]))
--
-- >>> simpleParsec "mylib: sub" :: Maybe Dependency
-- Nothing
-- Spaces around colon are not allowed:
--
-- >>> simpleParsec "mylib :sub" :: Maybe Dependency
-- Nothing
-- >>> map simpleParsec ["mylib: sub", "mylib :sub", "mylib: {sub1,sub2}", "mylib :{sub1,sub2}"] :: [Maybe Dependency]
-- [Nothing,Nothing,Nothing,Nothing]
--
-- >>> simpleParsec "mylib: {sub1,sub2}" :: Maybe Dependency
-- Nothing
-- Sublibrary syntax is accepted since @cabal-version: 3.0@
--
-- >>> simpleParsec "mylib :{sub1,sub2}" :: Maybe Dependency
-- Nothing
-- >>> map (`simpleParsec'` "mylib:sub") [CabalSpecV2_4, CabalSpecV3_0] :: [Maybe Dependency]
-- [Nothing,Just (Dependency (PackageName "mylib") AnyVersion (fromList [LSubLibName (UnqualComponentName "sub")]))]
--
instance Parsec Dependency where
parsec = do
name <- parsec
libs <- option [LMainLibName]
$ (char ':' *>)
$ versionGuardMultilibs
$ pure <$> parseLib name <|> parseMultipleLibs name
libs <- option mainLib $ do
_ <- char ':'
versionGuardMultilibs
Set.singleton <$> parseLib <|> parseMultipleLibs
spaces -- https://github.com/haskell/cabal/issues/5846
ver <- parsec <|> pure anyVersion
return $ Dependency name ver $ Set.fromList libs
where makeLib pn ln | unPackageName pn == ln = LMainLibName
| otherwise = LSubLibName $ mkUnqualComponentName ln
parseLib pn = makeLib pn <$> parsecUnqualComponentName
parseMultipleLibs pn = between (char '{' *> spaces)
(spaces <* char '}')
$ parsecCommaList $ parseLib pn
return $ mkDependency name ver libs
where
parseLib = LSubLibName <$> parsec
parseMultipleLibs = between
(char '{' *> spaces)
(spaces *> char '}')
(Set.fromList <$> parsecCommaList parseLib)
versionGuardMultilibs :: CabalParsing m => m ()
versionGuardMultilibs = do
csv <- askCabalSpecVersion
when (csv < CabalSpecV3_0) $ fail $ unwords
[ "Sublibrary dependency syntax used."
, "To use this syntax the package needs to specify at least 'cabal-version: 3.0'."
, "Alternatively, if you are depending on an internal library, you can write"
, "directly the library name as it were a package."
]
-- | Library set with main library.
mainLib :: Set LibraryName
mainLib = Set.singleton LMainLibName
instance Described Dependency where
describe _ = REAppend
[ RENamed "pkg-name" (describe (Proxy :: Proxy PackageName))
, REOpt $
RESpaces
<> reChar ':'
<> RESpaces
reChar ':'
<> REUnion
[ reUnqualComponent
, REAppend
[ reChar '{'
, RESpaces
, RECommaList reUnqualComponent
-- no leading or trailing comma
, REMunch reSpacedComma reUnqualComponent
, RESpaces
, reChar '}'
]
]
, REOpt $ RESpaces <> vr
-- TODO: RESpaces1 should be just RESpaces, but we are able
-- to generate non-parseable strings without mandatory space
--
-- https://github.com/haskell/cabal/issues/6589
--
, REOpt $ RESpaces1 <> vr
]
where
vr = RENamed "version-range" (describe (Proxy :: Proxy VersionRange))
......@@ -157,6 +182,9 @@ instance Described Dependency where
-- mempty should never be in a Dependency-as-dependency.
-- This is only here until the Dependency-as-constraint problem is solved #5570.
-- Same for below.
--
-- Note: parser allows for empty set!
--
thisPackageVersion :: PackageIdentifier -> Dependency
thisPackageVersion (PackageIdentifier n v) =
Dependency n (thisVersion v) Set.empty
......
......@@ -2,7 +2,9 @@
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveGeneric #-}
module Distribution.Types.PackageName
( PackageName, unPackageName, mkPackageName
( PackageName
, unPackageName, mkPackageName
, unPackageNameST, mkPackageNameST
) where
import Prelude ()
......@@ -29,6 +31,10 @@ newtype PackageName = PackageName ShortText
unPackageName :: PackageName -> String
unPackageName (PackageName s) = fromShortText s
-- | @since 3.4.0.0
unPackageNameST :: PackageName -> ShortText
unPackageNameST (PackageName s) = s
-- | Construct a 'PackageName' from a 'String'
--
-- 'mkPackageName' is the inverse to 'unPackageName'
......@@ -40,6 +46,15 @@ unPackageName (PackageName s) = fromShortText s
mkPackageName :: String -> PackageName
mkPackageName = PackageName . toShortText
-- | Construct a 'PackageName' from a 'ShortText'
--
-- Note: No validations are performed to ensure that the resulting
-- 'PackageName' is valid
--
-- @since 3.4.0.0
mkPackageNameST :: ShortText -> PackageName
mkPackageNameST = PackageName
-- | 'mkPackageName'
--
-- @since 2.0.0.2
......
......@@ -2,7 +2,7 @@
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module Distribution.Types.UnqualComponentName
( UnqualComponentName, unUnqualComponentName, mkUnqualComponentName
( UnqualComponentName, unUnqualComponentName, unUnqualComponentNameST, mkUnqualComponentName
, packageNameToUnqualComponentName, unqualComponentNameToPackageName
) where
......@@ -32,6 +32,10 @@ newtype UnqualComponentName = UnqualComponentName ShortText
unUnqualComponentName :: UnqualComponentName -> String
unUnqualComponentName (UnqualComponentName s) = fromShortText s
-- | @since 3.4.0.0
unUnqualComponentNameST :: UnqualComponentName -> ShortText
unUnqualComponentNameST (UnqualComponentName s) = s
-- | Construct a 'UnqualComponentName' from a 'String'
--
-- 'mkUnqualComponentName' is the inverse to 'unUnqualComponentName'
......@@ -78,7 +82,7 @@ instance NFData UnqualComponentName where
--
-- @since 2.0.0.2
packageNameToUnqualComponentName :: PackageName -> UnqualComponentName
packageNameToUnqualComponentName = mkUnqualComponentName . unPackageName
packageNameToUnqualComponentName = UnqualComponentName . unPackageNameST
-- | Converts an unqualified component name to a package name
--
......@@ -90,4 +94,4 @@ packageNameToUnqualComponentName = mkUnqualComponentName . unPackageName
--
-- @since 2.0.0.2
unqualComponentNameToPackageName :: UnqualComponentName -> PackageName
unqualComponentNameToPackageName = mkPackageName . unUnqualComponentName
unqualComponentNameToPackageName = mkPackageNameST . unUnqualComponentNameST
......@@ -71,7 +71,6 @@ foldVersionRange anyv this later earlier union intersect = fold
alg (MajorBoundVersionF v) = fold (majorBound v)
alg (UnionVersionRangesF v1 v2) = union v1 v2
alg (IntersectVersionRangesF v1 v2) = intersect v1 v2
alg (VersionRangeParensF v) = v
wildcard v = intersectVersionRanges
(orLaterVersion v)
......@@ -104,12 +103,11 @@ normaliseVersionRange = hyloVersionRange embed projectVersionRange
-- | Remove 'VersionRangeParens' constructors.
--
-- Since version 3.4 this function is 'id', there aren't 'VersionRangeParens' constructor in 'VersionRange' anymore.
--
-- @since 2.2
stripParensVersionRange :: VersionRange -> VersionRange
stripParensVersionRange = hyloVersionRange embed projectVersionRange
where
embed (VersionRangeParensF vr) = vr
embed vr = embedVersionRange vr
stripParensVersionRange = id
-- | Does this version fall within the given range?
--
......
......@@ -58,7 +58,6 @@ data VersionRange
| MajorBoundVersion Version -- @^>= ver@ (same as >= ver && < MAJ(ver)+1)
| UnionVersionRanges VersionRange VersionRange
| IntersectVersionRanges VersionRange VersionRange
| VersionRangeParens VersionRange -- just '(exp)' parentheses syntax
deriving ( Data, Eq, Generic, Read, Show, Typeable )
instance Binary VersionRange
......@@ -180,7 +179,6 @@ data VersionRangeF a
| MajorBoundVersionF Version -- @^>= ver@ (same as >= ver && < MAJ(ver)+1)
| UnionVersionRangesF a a
| IntersectVersionRangesF a a
| VersionRangeParensF a
deriving ( Data, Eq, Generic, Read, Show, Typeable
, Functor, Foldable, Traversable )
......@@ -196,7 +194,6 @@ projectVersionRange (WildcardVersion v) = WildcardVersionF v
projectVersionRange (MajorBoundVersion v) = MajorBoundVersionF v
projectVersionRange (UnionVersionRanges a b) = UnionVersionRangesF a b
projectVersionRange (IntersectVersionRanges a b) = IntersectVersionRangesF a b
projectVersionRange (VersionRangeParens a) = VersionRangeParensF a
-- | Fold 'VersionRange'.
--
......@@ -216,7 +213,6 @@ embedVersionRange (WildcardVersionF v) = WildcardVersion v
embedVersionRange (MajorBoundVersionF v) = MajorBoundVersion v
embedVersionRange (UnionVersionRangesF a b) = UnionVersionRanges a b
embedVersionRange (IntersectVersionRangesF a b) = IntersectVersionRanges a b
embedVersionRange (VersionRangeParensF a) = VersionRangeParens a
-- | Unfold 'VersionRange'.
--
......@@ -251,8 +247,6 @@ instance Pretty VersionRange where
(punct 1 p1 r1 <+> Disp.text "||" <+> punct 2 p2 r2 , 2)
alg (IntersectVersionRangesF (r1, p1) (r2, p2)) =
(punct 0 p1 r1 <+> Disp.text "&&" <+> punct 1 p2 r2 , 1)
alg (VersionRangeParensF (r, _)) =
(Disp.parens r, 0)
dispWild ver =
Disp.hcat (Disp.punctuate (Disp.char '.')
......@@ -492,9 +486,10 @@ versionRangeParser digitParser csv = expr
parens p = P.between
((P.char '(' P.<?> "opening paren") >> P.spaces)
(P.char ')' >> P.spaces)
(do a <- p
$ do
a <- p
P.spaces
return (VersionRangeParens a))
return a
tags :: CabalParsing m => m ()
tags = do
......
......@@ -7,10 +7,9 @@ GenericPackageDescription
{condTreeComponents = [],
condTreeConstraints = [Dependency
`PackageName "base"`
(VersionRangeParens
(UnionVersionRanges
(LaterVersion `mkVersion [4,4]`)
(ThisVersion `mkVersion [4,4]`)))
(UnionVersionRanges
(LaterVersion `mkVersion [4,4]`)
(ThisVersion `mkVersion [4,4]`))
(Set.fromList [LMainLibName])],
condTreeData = Library
{exposedModules = [`ModuleName ["Data","Encoding"]`],
......@@ -64,12 +63,11 @@ GenericPackageDescription
staticOptions = PerCompilerFlavor [] [],
targetBuildDepends = [Dependency
`PackageName "base"`
(VersionRangeParens
(UnionVersionRanges
(LaterVersion
`mkVersion [4,4]`)
(ThisVersion
`mkVersion [4,4]`)))
(UnionVersionRanges
(LaterVersion
`mkVersion [4,4]`)
(ThisVersion
`mkVersion [4,4]`))
(Set.fromList
[LMainLibName])],
virtualModules = []},
......
......@@ -15,4 +15,4 @@ custom-setup
library
exposed-modules: Data.Encoding
ghc-options: -Wall -O2 -threaded -rtsopts "-with-rtsopts=-N1 -A64m"
build-depends: base (>4.4 || ==4.4)
build-depends: base >4.4 || ==4.4
......@@ -17,6 +17,7 @@ import Distribution.Pretty (prettyShow)
import qualified Distribution.Utils.CharSet as CS
import Distribution.Types.Dependency (Dependency)
import Distribution.Types.PackageName (PackageName)
import Distribution.Types.Version (Version)
import Distribution.Types.VersionRange (VersionRange)
......@@ -29,18 +30,24 @@ import Test.QuickCheck.Instances.Cabal ()
tests :: TestTree
tests = testGroup "Described"
[ testDescribed (Proxy :: Proxy PackageName)
[ testDescribed (Proxy :: Proxy Dependency)
, testDescribed (Proxy :: Proxy PackageName)
, testDescribed (Proxy :: Proxy Version)
, testDescribed (Proxy :: Proxy VersionRange)
]
-------------------------------------------------------------------------------
-- Described/Pretty/Parsec tests
-------------------------------------------------------------------------------
testDescribed
:: forall a. (Arbitrary a, Described a, Typeable a, Show a)
:: forall a. (Arbitrary a, Described a, Typeable a, Eq a, Show a)
=> Proxy a
-> TestTree
testDescribed _ = testGroup name
[ testProperty "parsec" propParsec
, testProperty "pretty" propPretty
, testProperty "roundtrip" propRoundtrip
]
where
name = show (typeOf (undefined :: a))
......@@ -61,6 +68,14 @@ testDescribed _ = testGroup name
where
str = prettyShow x
propRoundtrip :: a -> Property
propRoundtrip x = counterexample (show (res, str)) $ case res of
Right y -> x == y
Left _ -> False
where
str = prettyShow x
res = eitherParsec str
newtype Ex a = Example String
deriving (Show)
......@@ -71,6 +86,10 @@ instance Described a => Arbitrary (Ex a) where
$ RE.generate 10 5
$ convert $ describe (Proxy :: Proxy a)
shrink (Example s)
| '\n' `elem` s = [ Example $ map (\c -> if c == '\n' then ' ' else c) s ]
| otherwise = []
genInt :: Int -> Int -> Gen Int
genInt lo hi = choose (lo, hi)
......
......@@ -19,10 +19,10 @@ import UnitTests.Orphans ()
tests :: TestTree
tests = testGroup "Distribution.Utils.Structured"
-- This test also verifies that structureHash doesn't loop.
[ testCase "VersionRange" $ structureHash (Proxy :: Proxy VersionRange) @?= Fingerprint 0x3827faffd22242bf 0xfd0c337e60fc808b
[ testCase "VersionRange" $ structureHash (Proxy :: Proxy VersionRange) @?= Fingerprint 0x6a33c568c9307696 0xe383268b2389a958
, testCase "SPDX.License" $ structureHash (Proxy :: Proxy License) @?= Fingerprint 0xd3d4a09f517f9f75 0xbc3d16370d5a853a
-- The difference is in encoding of newtypes
#if MIN_VERSION_base(4,7,0)
, testCase "LocalBuildInfo" $ structureHash (Proxy :: Proxy LocalBuildInfo) @?= Fingerprint 0xb48ff44b0e5d96ff 0xfc099544337e90ab
, testCase "LocalBuildInfo" $ structureHash (Proxy :: Proxy LocalBuildInfo) @?= Fingerprint 0x57e3e6dcec2cf371 0x00ef351fd0f41443
#endif
]
......@@ -15,7 +15,7 @@ import Distribution.Utils.Generic
import Data.Typeable (typeOf)
import Math.NumberTheory.Logarithms (intLog2)
import Text.PrettyPrint as Disp (text, render, parens, hcat
import Text.PrettyPrint as Disp (text, render, hcat
,punctuate, int, char, (<+>))
import Test.Tasty
import Test.Tasty.QuickCheck
......@@ -284,7 +284,6 @@ prop_foldVersionRange range =
UnionVersionRanges (expandVR v1) (expandVR v2)
expandVR (IntersectVersionRanges v1 v2) =
IntersectVersionRanges (expandVR v1) (expandVR v2)
expandVR (VersionRangeParens v) = expandVR v
expandVR v = v
upper = alterVersion $ \numbers -> case unsnoc numbers of
......@@ -598,15 +597,7 @@ prop_parse_disp vr = counterexample (show (prettyShow vr')) $
prop_parse_disp1 :: VersionRange -> Bool
prop_parse_disp1 vr =
fmap stripParens (simpleParsec (prettyShow vr)) == Just (normaliseVersionRange vr)
where
stripParens :: VersionRange -> VersionRange
stripParens (VersionRangeParens v) = stripParens v
stripParens (UnionVersionRanges v1 v2) =
UnionVersionRanges (stripParens v1) (stripParens v2)
stripParens (IntersectVersionRanges v1 v2) =
IntersectVersionRanges (stripParens v1) (stripParens v2)
stripParens v = v
simpleParsec (prettyShow vr) == Just (normaliseVersionRange vr)
prop_parse_disp2 :: VersionRange -> Property
prop_parse_disp2 vr =
......@@ -662,8 +653,6 @@ displayRaw =
alg (MajorBoundVersionF v) = Disp.text "^>=" <<>> pretty v
alg (UnionVersionRangesF r1 r2) = r1 <+> Disp.text "||" <+> r2
alg (IntersectVersionRangesF r1 r2) = r1 <+> Disp.text "&&" <+> r2
alg (VersionRangeParensF r) = Disp.parens r -- parens
dispWild v =
Disp.hcat (Disp.punctuate (Disp.char '.')
......
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
-----------------------------------------------------------------------------
......@@ -31,6 +32,8 @@ import Data.Time.Clock.POSIX (posixSecondsToUTCTime, utcTimeToPOSIXSeconds)
import Distribution.Parsec (Parsec (..))