stylish-cabal 0.2.0.0 → 0.3.0.0
raw patch · 36 files changed
+3193/−779 lines, 36 filesdep +base-compatdep +data-defaultdep +ghc-primdep −hlintdep ~Cabal
Dependencies added: base-compat, data-default, ghc-prim, haddock-library, microlens, microlens-th, mtl, template-haskell
Dependencies removed: hlint
Dependency ranges changed: Cabal
Files
- ChangeLog.md +26/−2
- Main.hs +19/−13
- src/Parse.hs +32/−9
- src/Render.hs +71/−72
- src/Render/Lib.hs +122/−91
- src/Render/Lib/Haddock.hs +166/−0
- src/Render/Options.hs +43/−0
- src/StylishCabal.hs +19/−14
- src/Transform.hs +7/−20
- src/Types/Block.hs +18/−17
- src/Types/Field.hs +8/−3
- stylish-cabal.cabal +73/−55
- tests/cabal-files/BiGUL.txt +68/−0
- tests/cabal-files/Cardinality.txt +105/−0
- tests/cabal-files/ChasingBottoms.txt +185/−0
- tests/cabal-files/OrPatterns.txt +61/−0
- tests/cabal-files/deepseq-bounded.txt +717/−0
- tests/cabal-files/deka-tests.txt +135/−0
- tests/cabal-files/example-out.txt +138/−0
- tests/cabal-files/example.txt +119/−0
- tests/cabal-files/exposed-containers.txt +247/−0
- tests/cabal-files/helics.txt +76/−0
- tests/cabal-files/hpc-coveralls.txt +121/−0
- tests/example.cabal +0/−119
- tests/hlint.hs +0/−6
- tests/roundtrip/Hackage.hs +23/−10
- tests/roundtrip/Main.hs +18/−4
- tests/roundtrip/SortedDesc.hs +0/−269
- tests/roundtrip/Utils.hs +0/−59
- tests/strictness/Instances.hs +10/−2
- tests/strictness/Main.hs +6/−11
- tests/strictness/Pretty.hs +6/−3
- tests/utils/Expectations.hs +58/−0
- tests/utils/MultiSet.hs +10/−0
- tests/utils/SortedPackageDescription.hs +318/−0
- tests/utils/SortedPackageDescription/TH.hs +168/−0
ChangeLog.md view
@@ -1,5 +1,29 @@ # Revision history for stylish-cabal -## 0.1.0.0 -- YYYY-mm-dd+## 0.1.0.0 -- 2018-02-19 -* First version. Released on an unsuspecting world.+* Initial release.++## 0.2.0.0 -- 2018-02-20++0.1.0.0 tarball was broken due to a missing test file.++* Better haddocks for StylishCabal module so it can be imported and used independently of+ the CLI tool (like hindent, hlint, and so on).+* Better readme++## 0.2.1.0 -- 2018-02-27++* Removed support for GHC 8.4. Using a Cabal version older than the built-in version is+ officially not recommended.+* Certain version range expressions no longer incorrectly collapsed to ">="+* `stylish-cabal` executable now checks the correct Handle when determining if it should colorize (previously always checked stdout)+* Code block formatting in descriptions is now preserved (and will not be soft-broken to fit the width limit.)+* haskell-suite in the "tested-with" field can now be rendered+* Roundtrip test now checks an entire `GenericPackageDescription`, rather than just the `packageDescription` field++## 0.3.0.0 -- 2018-03-02++* Description rendering has been rewritten. Rather than naive reformatting, it now uses+ the proper Haddock parser.+* Show1/Eq1 instances for Result
Main.hs view
@@ -1,27 +1,37 @@-{-# Language CPP #-} {-# Language NoMonomorphismRestriction #-} {-# Language OverloadedStrings #-} module Main where import Data.Char+import Data.Monoid.Compat import Options.Applicative hiding (ParserResult(..))+import Prelude.Compat import StylishCabal import System.Exit import System.IO -#if !MIN_VERSION_base(4,11,0)-import Data.Monoid-#endif- data Opts = Opts { file :: Maybe FilePath , inPlace :: Bool , color :: Bool , width :: Int- , indent :: Int+ , renderOpts :: RenderOptions } deriving (Show) +renderopts :: Parser RenderOptions+renderopts =+ RenderOptions <$>+ option+ auto+ (long "indent" <> short 'n' <> help "Indent size in spaces" <> showDefault <>+ value 2 <>+ metavar "INT") <*>+ switch+ (long "simplify-versions" <> short 's' <>+ help "Simplify version ranges present in the Cabal file, if possible" <>+ showDefault)+ opts :: Parser Opts opts = Opts <$> optional (strArgument (metavar "FILE" <> help "Input file")) <*>@@ -38,15 +48,11 @@ showDefault <> value 90 <> metavar "INT") <*>- option- auto- (long "indent" <> short 'n' <> help "Indent size in spaces" <> showDefault <>- value 2 <>- metavar "INT")+ renderopts output :: Opts -> Doc -> Handle -> IO () output o doc h = do- isTerminal <- hIsTerminalDevice stdout+ isTerminal <- hIsTerminalDevice h if color o && isTerminal then displayIO h (f doc) else do@@ -62,7 +68,7 @@ main = do o <- execParser $ info (opts <**> helper) (fullDesc <> progDesc "Format a Cabal file") f <- maybe getContents readFile (file o)- doc <- prettyWithIndent (indent o) <$> readCabalFile (file o) f+ doc <- prettyOpts (renderOpts o) <$> readPackageDescription (file o) f if inPlace o then case file o of Just fname -> withFile fname WriteMode (output o doc)
src/Parse.hs view
@@ -6,8 +6,8 @@ {-# Language DeriveFunctor #-} module Parse- ( parseCabalFile- , readCabalFile+ ( parsePackageDescription+ , readPackageDescription , displayError , printWarnings , Result(..)@@ -17,15 +17,20 @@ import Control.DeepSeq import Data.Data import Data.Maybe-import Distribution.PackageDescription.Parse+import Distribution.PackageDescription.Parse (parseGenericPackageDescription) import Distribution.ParseUtils import Distribution.Simple.Utils import Distribution.Verbosity import GHC.Generics+import Prelude.Compat import System.Environment import System.Exit import System.IO +#if MIN_VERSION_base(4,9,0)+import Data.Functor.Classes+#endif+ -- | Like Cabal's @ParseResult@, but treats warnings as a separate failure -- case. data Result a@@ -35,6 +40,23 @@ | Success a -- ^ The input is a compliant package description. deriving (Show, Eq, Functor, Generic, Typeable, Data) +#if MIN_VERSION_base(4,6,0)+deriving instance Generic1 Result+#endif++#if MIN_VERSION_base(4,9,0)+instance Show1 Result where+ liftShowsPrec sp _ p (Success n) = showsUnaryWith sp "Success" p n+ liftShowsPrec _ _ p (Warn pws) = showsUnaryWith showsPrec "Warn" p pws+ liftShowsPrec _ _ p (Error ml s) = showsBinaryWith showsPrec showsPrec "Error" p ml s++instance Eq1 Result where+ liftEq eq (Success a) (Success b) = eq a b+ liftEq _ (Error ml s) (Error ml2 s2) = (ml,s) == (ml2,s2)+ liftEq _ (Warn pws) (Warn pws2) = pws == pws2+ liftEq _ _ _ = False+#endif+ -- | Case analysis for 'Result'. result :: (Maybe LineNo -> String -> b) -> ([PWarning] -> b) -> (a -> b) -> Result a -> b result e w s p =@@ -49,9 +71,7 @@ deriving instance Data PWarning -#if !MIN_VERSION_base(4,8,0) deriving instance Typeable PWarning-#endif instance NFData PWarning @@ -60,20 +80,23 @@ -- different behaviors accepted by different Cabal parser versions. Parse -- warnings generally indicate a version-related inconsistency, so we play -- it safe here.-parseCabalFile input =+parsePackageDescription input = case parseGenericPackageDescription input of ParseFailed e -> uncurry Error $ locatedErrorMsg e ParseOk warnings x | null warnings -> Success x | otherwise -> Warn $ reverse warnings --- | Shorthand to combine 'parseCabalFile' and one of 'printWarnings' or+-- | Shorthand to combine 'parsePackageDescription' and one of 'printWarnings' or -- 'displayError'. The given 'FilePath' is used only for error messages and -- is not read from.-readCabalFile fpath = result (displayError fpath) printWarnings return . parseCabalFile+readPackageDescription fpath =+ result (displayError fpath) (printWarnings fpath) return . parsePackageDescription -- | Print some warnings to 'stderr' and exit.-printWarnings ps = mapM_ (warn normal . showPWarning "<input>") ps >> exitFailure+printWarnings :: Maybe FilePath -> [PWarning] -> IO a+printWarnings fpath ps =+ mapM_ (warn normal . showPWarning (fromMaybe "<input>" fpath)) ps >> exitFailure -- | Print a parse error to 'stderr', annotated with filepath and line -- number (if available), then exit.
src/Render.hs view
@@ -7,8 +7,7 @@ ( blockBodyToDoc ) where -import Data.List hiding (group)-import Data.List.Split+import Data.List.Compat hiding (group) import Data.Maybe import Data.Ord import Distribution.Types.Dependency@@ -21,16 +20,19 @@ import Distribution.Types.PkgconfigDependency import Distribution.Types.PkgconfigName import Distribution.Version-import Prelude hiding ((<$>))+import Documentation.Haddock.Types+import Prelude.Compat hiding ((<$>))+import qualified Prelude.Compat as P import Text.PrettyPrint.ANSI.Leijen import Render.Lib+import Render.Options import Types.Block import Types.Field deriving instance Ord ModuleReexport -fieldValueToDoc _ k (Field _ f) =+fieldValueToDoc k (Field _ f) = case f of Dependencies ds -> buildDepsToDoc k $ map (\(Dependency pn v) -> (P $ unPackageName pn, v)) ds@@ -44,52 +46,42 @@ RexpModules rms -> buildDepsToDoc k $ map (\rexp -> (P $ show $ rexpModuleDoc rexp, anyVersion)) rms- n -> colon <> indent (k + 1) (align $ val' n)+ n -> val' n <&> \v -> colon <> indent (k + 1) (align v) where- val' (Str x) = string x- val' (File x) = filepath x- val' (Version v) = string $ showVersion v- val' (CabalVersion v)- -- section syntax was introduced in Cabal 1.2. if no cabal-version- -- is specified in the source, we require >=1.2 to be present in- -- the output- | v == mkVersion [0] = renderVersion $ orLaterVersion (mkVersion [1, 2])- -- up until Cabal 1.10, we have to specify '>=' with cabal-version- | withinRange v (orEarlierVersion (mkVersion [1, 10])) =- renderVersion $ orLaterVersion v- | otherwise = string $ showVersion v- val' (License l) = string $ showLicense l+ val' (Str x) = pure $ string x+ val' (File x) = pure $ filepath x+ val' (Version v) = pure $ string $ prettyShow v+ val' (CabalVersion (Left v)) = pure $ string $ prettyShow v+ val' (CabalVersion (Right v))+ | v == anyVersion = showVersionRange (orLaterVersion (mkVersion [1, 10]))+ | otherwise = showVersionRange v+ val' (License l) = pure $ string $ prettyShow l val' (TestedWith ts) = renderTestedWith ts- val' (LongList fs) = vcat $ map filepath fs- val' (Commas fs) = fillSep $ punctuate comma $ map filepath fs- val' (Spaces ls) = fillSep $ map filepath ls- val' (Modules ms) = vcat $ map moduleDoc $ sort ms- val' (Module m) = moduleDoc m- val' (Extensions es) = val' (LongList $ map showExtension es)- val' (FlibType ty) = string $ showFlibType ty- val' (FlibOptions fs) = val' $ Spaces $ map showFlibOpt fs+ val' (LongList fs) = pure $ vcat $ map filepath fs+ val' (Commas fs) = pure $ fillSep $ punctuate comma $ map filepath fs+ val' (Spaces ls) = pure $ fillSep $ map filepath ls+ val' (Modules ms) = pure $ vcat $ map moduleDoc $ sort ms+ val' (Module m) = pure $ moduleDoc m+ val' (Extensions es) = val' (LongList $ map prettyShow $ sort es)+ val' (FlibType ty) = pure $ string $ prettyShow ty+ val' (FlibOptions fs) = val' $ Spaces $ map prettyShow fs val' x = error $ show x-fieldValueToDoc n k (Description s) = descriptionToDoc n k s+fieldValueToDoc k (Description s) = descriptionToDoc k s -descriptionToDoc n k s =- (<>) colon $- nest n $- case paragraphs of- [p]- -- i still don't know what this does- ->- group $- flatAlt- (linebreak <> fillSep (map text $ words p))- (indent (k + 1) (string p))- xs -> line <> vcat (intersperse (green dot) (map paragraph xs))+descriptionToDoc k paras = do+ n <- asks indentSize+ return $+ (<>) colon $+ nest n $+ case paras of+ DocParagraph {} -> indent (k + 1) ds+ _ -> linebreak <> ds where- paragraphs = map (unwords . lines) $ splitOn "\n\n" s- paragraph t = fillSep (map text $ words t)+ ds = renderDescription paras mixinsToDoc k bs- | k == 0 = deps ": "- | otherwise = colon <> indent (k - 1) (deps " ")+ | k == 0 = pure $ deps ": "+ | otherwise = pure $ colon <> indent (k - 1) (deps " ") where deps lsep = encloseSep (string lsep) empty (string ", ") $@@ -128,47 +120,54 @@ renaming (m1, m2) = moduleDoc m1 <+> string "as" <+> moduleDoc m2 align' n doc = column (\ko -> nesting (\i -> nest (ko - i - n) doc)) +buildDepsToDoc :: Int -> [(P, VersionRange)] -> Render Doc buildDepsToDoc k bs | k == 0 = deps ": "- | otherwise = colon <> indent (k - 1) (deps " ")+ | otherwise = fmap (\r -> colon <> indent (k - 1) r) (deps " ") where- deps lsep =- encloseSep- (string lsep)- empty- (string ", ")- (map showField $ sortBy (comparing fst) bs)+ deps lsep = do+ fs <- mapM showField $ sortBy (comparing fst) bs+ return $ encloseSep (string lsep) empty (string ", ") fs longest = maximum $ map (length . unP . fst) bs showField (P fName, fieldVal)- | fieldVal == anyVersion = string fName+ | fieldVal == anyVersion = pure $ string fName | otherwise =- width (string fName) $ \fn ->- let delt n = indent (n + 1) (renderVersion fieldVal)- in flatAlt (delt (longest - fn)) (delt 0)+ widthR (string fName) $ \fn -> do+ shown <- showVersionRange fieldVal+ let delt n = indent (n + 1) shown+ in pure $ flatAlt (delt (longest - fn)) (delt 0) -fieldsToDoc n fs =- vcat $- map (\field ->- width (dullblue $ string (fieldName field)) $ \fn ->- fieldValueToDoc n (longestField - fn) field)+fieldsToDoc :: [Field] -> Render Doc+fieldsToDoc fs =+ vcat P.<$>+ mapM+ (\field ->+ widthR (dullblue $ string (fieldName field)) $ \fn ->+ fieldValueToDoc (longestField - fn) field) fs where longestField = maximum $ map (length . fieldName) fs -renderBlock n (Block t fs blocks) =- (if isElse t- then id- else (<>) line)- (renderBlockHead t) <$$>- indent n (align $ blockBodyToDoc n fs blocks)+renderBlock :: Block -> Render Doc+renderBlock (Block t fs blocks) = do+ blkhead <- renderBlockHead t+ body <- indentM . align =<< blockBodyToDoc fs blocks+ return $+ (if isElse t+ then id+ else (<>) line)+ blkhead <$$>+ body -blockBodyToDoc n fs blocks =- fieldsToDoc- n- (if null fs'- then buildable'- else fs') <>- vcat (empty : map (renderBlock n) blocks)+blockBodyToDoc :: [Maybe Field] -> [Block] -> Render Doc+blockBodyToDoc fs blocks = do+ fields <-+ fieldsToDoc+ (if null fs'+ then buildable'+ else fs')+ subblocks <- mapM renderBlock blocks+ return $ fields <> vcat (empty : subblocks) where fs' = catMaybes fs buildable' = [fromJust $ stringField "buildable" "True"]
src/Render/Lib.hs view
@@ -1,37 +1,49 @@+{-# OPTIONS_GHC -fno-warn-deprecations #-} {-# Language FlexibleContexts #-} {-# Language OverloadedStrings #-} module Render.Lib ( P(..) , renderBlockHead- , renderVersion- , showExtension+ , showVersionRange+ , prettyShow , moduleDoc , rexpModuleDoc- , showFlibType- , showFlibOpt , filepath , renderTestedWith- , showLicense , exeDependencyAsDependency+ , renderDescription ) where import Data.Char-import Data.List+import Data.List.Compat import Distribution.Compiler-import Distribution.License import Distribution.ModuleName import Distribution.PackageDescription+import Distribution.Text import Distribution.Types.ExeDependency-import Distribution.Types.ForeignLibOption-import Distribution.Types.ForeignLibType import Distribution.Types.PackageName import Distribution.Types.UnqualComponentName-import Distribution.Version-import Language.Haskell.Extension-import Text.PrettyPrint.ANSI.Leijen+import Distribution.Version hiding (foldVersionRange)+import Prelude.Compat+import Text.PrettyPrint.ANSI.Leijen hiding ((<$>))++import Render.Lib.Haddock (renderDescription)+import Render.Options import Types.Block +prettyShow = show . disp++wildcardUpperBound =+ alterVersion $ \lowerBound -> init lowerBound ++ [last lowerBound + 1]++majorUpperBound :: Version -> Version+majorUpperBound = alterVersion go+ where+ go [] = [0, 1]+ go [m1] = [m1, 1]+ go (m1:m2:_) = [m1, m2 + 1]+ newtype P = P { unP :: String } deriving (Eq)@@ -42,59 +54,73 @@ compare _ (P "base") = GT compare (P p1) (P p2) = compare p1 p2 -showFlibType ForeignLibNativeShared = "native-shared"-showFlibType f = error $ show f--showFlibOpt ForeignLibStandalone = "standalone"--showLicense :: License -> String-showLicense MIT = "MIT"-showLicense BSD2 = "BSD2"-showLicense BSD3 = "BSD3"-showLicense BSD4 = "BSD4"-showLicense PublicDomain = "PublicDomain"-showLicense ISC = "ISC"-showLicense (MPL v) = showL "MPL" (Just v)-showLicense (LGPL v) = showL "LGPL" v-showLicense (GPL v) = showL "GPL" v-showLicense (AGPL v) = showL "AGPL" v-showLicense (Apache v) = showL "Apache" v-showLicense OtherLicense = "OtherLicense"-showLicense x = error $ show x--showL :: String -> Maybe Version -> String-showL s Nothing = s-showL s (Just v) = s ++ "-" ++ showVersion v--renderTestedWith =- fillSep .- punctuate comma .- map (\(compiler, vers) -> showVersioned (showCompiler compiler, vers))+renderTestedWith ts =+ fillSep . punctuate comma <$>+ mapM (\(compiler, vers) -> showVersioned (showCompiler compiler, vers)) ts where showCompiler (OtherCompiler x) = x- showCompiler HaskellSuite {} =- error "Not sure what to do with HaskellSuite value in tested-with field"+ showCompiler (HaskellSuite x) = x showCompiler x = show x -showVersioned :: (String, VersionRange) -> Doc+showVersioned :: (String, VersionRange) -> Render Doc showVersioned (pn, v')- | v' == anyVersion = string pn- | otherwise = string pn <+> renderVersion v'+ | v' == anyVersion = pure $ string pn+ | otherwise = fmap (string pn <+>) (showVersionRange v') -renderVersion =- foldVersionRange'- empty- (\v -> green "==" <+> dullyellow (string (showVersion v)))- (\v -> green ">" <+> dullyellow (string (showVersion v)))- (\v -> green "<" <+> dullyellow (string (showVersion v)))- (\v -> green ">=" <+> dullyellow (string (showVersion v)))- (\v -> green "<=" <+> dullyellow (string (showVersion v)))- (\v _ -> green "==" <+> dullyellow (string (showVersion v) <> ".*"))- (\v _ -> green "^>=" <+> dullyellow (string (showVersion v)))- (\a b -> a <+> green "||" <+> b)- (\a b -> a <+> green "&&" <+> b)- parens+showVersionRange r = do+ opts <- ask+ return $+ foldVersionRange+ empty+ (\v -> green "==" <+> dullyellow (string (showVersion v)))+ (\v -> green ">" <+> dullyellow (string (showVersion v)))+ (\v -> green "<" <+> dullyellow (string (showVersion v)))+ (\v -> green ">=" <+> dullyellow (string (showVersion v)))+ (\v -> green "<=" <+> dullyellow (string (showVersion v)))+ (\v _ -> green "==" <+> dullyellow (string (showVersion v) <> ".*"))+ (\v _ -> green "^>=" <+> dullyellow (string (showVersion v)))+ (\a b -> a <+> green "||" <+> b)+ (\a b -> a <+> green "&&" <+> b)+ parens .+ (if simplifyVersions opts+ then simplifyVersionRange+ else id) $+ r +{------------ EVIL HACK GOES HERE ---------------+-+- Distribution.Version.foldVersionRange' treats both of the following+- * "(== v) || (> v)"+- * "(> v) || (== v)"+- as "(>= v)"+-+- Makes sense, right? Nope. ">=" is always Union (This ...) (Later ...),+- whereas if Union (Later ...) (This ...) is present in the source file, we+- must preserve it, otherwise roundtrip tests fail because we're switching+- the order of the Union arguments!+-+- The other solution is to wrap VersionRange in a newtype that disregards+- Union argument ordering for the equality test, but I leave that as an+- exercise to the reader.+-+- Arguments renamed to avoid shadowing+-}+foldVersionRange anyv this later earlier orL orE wildcard major both oneof wrap = fold+ where+ fold AnyVersion = anyv+ fold (ThisVersion v) = this v+ fold (LaterVersion v) = later v+ fold (EarlierVersion v) = earlier v+ fold (UnionVersionRanges (ThisVersion v) (LaterVersion v'))+ | v == v' = orL v+ fold (UnionVersionRanges (ThisVersion v) (EarlierVersion v'))+ | v == v' = orE v+ fold (WildcardVersion v) = wildcard v (wildcardUpperBound v)+ fold (MajorBoundVersion v) = major v (majorUpperBound v)+ fold (UnionVersionRanges v1 v2) = both (fold v1) (fold v2)+ fold (IntersectVersionRanges v1 v2) = oneof (fold v1) (fold v2)+ fold (VersionRangeParens v) = wrap (fold v)+ filepath :: String -> Doc filepath x | null x = string "\"\""@@ -109,46 +135,51 @@ then moduleDoc origname else moduleDoc origname <+> "as" <+> moduleDoc name) -showExtension (EnableExtension s) = show s-showExtension (DisableExtension s) = "No" ++ show s-showExtension x = error $ show x- exeDependencyAsDependency (ExeDependency pkg comp vers) = (P $ unPackageName pkg ++ ":" ++ unUnqualComponentName comp, vers) -renderBlockHead CustomSetup = dullgreen "custom-setup"-renderBlockHead (SourceRepo_ k) = dullgreen "source-repository" <+> showKind k+renderBlockHead (If c) = (dullblue "if" <+>) <$> showPredicate c+renderBlockHead x = pure $ r x where- showKind RepoHead = "head"- showKind RepoThis = "this"- showKind (RepoKindUnknown x) = string x-renderBlockHead (Library_ Nothing) = dullgreen "library"-renderBlockHead (Library_ (Just l)) = dullgreen "library" <+> string l-renderBlockHead (ForeignLib_ l) = dullgreen "foreign-library" <+> string l-renderBlockHead (Exe_ e) = dullgreen "executable" <+> string e-renderBlockHead (TestSuite_ t) = dullgreen "test-suite" <+> string t-renderBlockHead (Benchmark_ b) = dullgreen "benchmark" <+> string b-renderBlockHead (Flag_ s) = dullgreen "flag" <+> string s-renderBlockHead (If c) = dullblue "if" <+> showPredicate c-renderBlockHead Else = dullblue "else"+ r CustomSetup = dullgreen "custom-setup"+ r (SourceRepo_ k) = dullgreen "source-repository" <+> showKind k+ where+ showKind RepoHead = "head"+ showKind RepoThis = "this"+ showKind (RepoKindUnknown y) = string y+ r (Library_ Nothing) = dullgreen "library"+ r (Library_ (Just l)) = dullgreen "library" <+> string l+ r (ForeignLib_ l) = dullgreen "foreign-library" <+> string l+ r (Exe_ e) = dullgreen "executable" <+> string e+ r (TestSuite_ t) = dullgreen "test-suite" <+> string t+ r (Benchmark_ b) = dullgreen "benchmark" <+> string b+ r (Flag_ s) = dullgreen "flag" <+> string s+ r Else = dullblue "else"+ r _ = error "unreachable" +showPredicate :: Condition ConfVar -> Render Doc showPredicate (Var x) = showVar x-showPredicate (CNot p) = dullmagenta (string "!") <> maybeParens p-showPredicate (CAnd a b) = maybeParens a <+> dullblue (string "&&") <+> maybeParens b-showPredicate (COr a b) = maybeParens a <+> dullblue (string "||") <+> maybeParens b-showPredicate (Lit b) = string $ show b+showPredicate (CNot p) = fmap (dullmagenta (string "!") <>) (maybeParens p)+showPredicate (CAnd a b) =+ liftM2 (\x y -> x <+> dullblue (string "&&") <+> y) (maybeParens a) (maybeParens b)+showPredicate (COr a b) =+ liftM2 (\x y -> x <+> dullblue (string "||") <+> y) (maybeParens a) (maybeParens b)+showPredicate (Lit b) = pure $ string $ show b -maybeParens p = case p of- Lit {} -> showPredicate p- Var {} -> showPredicate p- CNot {} -> showPredicate p- _ -> parens (showPredicate p)+maybeParens p =+ case p of+ Lit {} -> showPredicate p+ Var {} -> showPredicate p+ CNot {} -> showPredicate p+ _ -> parens <$> showPredicate p -showVar (Impl compiler vers) =- dullgreen $- string "impl" <> parens (dullblue $ showVersioned (map toLower $ show compiler, vers))-showVar (Flag f) = dullgreen $ string "flag" <> parens (dullblue $ string (unFlagName f))+showVar :: ConfVar -> Render Doc+showVar (Impl compiler vers) = do+ v <- showVersioned (prettyShow compiler, vers)+ pure $ dullgreen $ string "impl" <> parens (dullblue v)+showVar (Flag f) =+ pure $ dullgreen $ string "flag" <> parens (dullblue $ string (unFlagName f)) showVar (OS w) =- dullgreen $ string "os" <> parens (dullblue $ string $ map toLower $ show w)+ pure $ dullgreen $ string "os" <> parens (dullblue $ string $ map toLower $ show w) showVar (Arch a) =- dullgreen $ string "arch" <> parens (dullblue $ string $ map toLower $ show a)+ pure $ dullgreen $ string "arch" <> parens (dullblue $ string $ map toLower $ show a)
+ src/Render/Lib/Haddock.hs view
@@ -0,0 +1,166 @@+{-# Language NoMonomorphismRestriction #-}+{-# Language OverloadedStrings #-}+{-# Language RecordWildCards #-}++module Render.Lib.Haddock where++import Control.Monad.Reader+import Data.Char (isSpace)+import Data.List.Compat+import Data.List.Split+import Documentation.Haddock.Parser (Identifier)+import Documentation.Haddock.Types+import Prelude.Compat+import Text.PrettyPrint.ANSI.Leijen hiding ((<$>))++data FlattenBehavior+ = Flatten+ | WordBreak++data TextPosition+ = ParaStart+ | Body+ deriving (Eq)++data DocContext = DocContext+ { flattenBehavior :: FlattenBehavior+ , textPosition :: TextPosition+ , listContext :: Bool+ }++flattenedBody = withReader $ \d -> d {flattenBehavior = Flatten, textPosition = Body}++inPara = withReader $ \d -> d {textPosition = ParaStart}++inBody = withReader $ \d -> d {textPosition = Body}++inList = withReader $ \d -> d {listContext = True}++defaultDocContext = DocContext WordBreak ParaStart False++-- sadly can't use the built-in haddock markup functionality here. we need+-- to change rendering logic entirely inside a code block (i.e. don't+-- fillSep words).+renderDescription =+ vcat . intersperse (green ".") . map ((`runReader` defaultDocContext) . go) . flatten+ where+ flatten (DocAppend d1 d2) = flatten d1 ++ flatten d2+ flatten d = [d]+ -- flatten inline styling which the haddock parser doesn't preserve+ -- across line boundaries+ go :: DocH () Identifier -> Reader DocContext Doc+ go DocEmpty = pure empty+ go (DocEmphasis d) = enclose (green "/") (green "/") <$> flattenedBody (go d)+ go (DocMonospaced d) = enclose (green "@") (green "@") <$> flattenedBody (go d)+ go (DocBold d) = enclose (green "__") (green "__") <$> flattenedBody (go d)+ go (DocHeader (Header l t)) =+ (green (strBody $ replicate l '=') <+>) <$> inBody (go t)+ go (DocAppend a b) = liftM2 (<>) (go a) (inBody $ go b)+ go (DocParagraph d) = inPara $ go d+ go (DocUnorderedList ds) = do+ docs <-+ forM ds $ \item -> do+ doc <- inList $ inPara $ go item+ return $ hang 2 $ string "*" <+> doc+ return $ vcat docs+ go (DocOrderedList ds) = do+ docs <-+ forM (zip [1 ..] ds) $ \(n, item) -> do+ doc <- inList $ inPara $ go item+ return $ hang 3 $ integer n <> "." <+> doc+ return $ vcat docs+ go (DocCodeBlock cb) = do+ DocContext {..} <- ask+ return $+ case cb of+ DocString s+ | all (`notElem` ['{', '}']) s && not listContext ->+ green ">" <+> arrowblock s+ | listContext && notElem '\n' s ->+ cat [green "@", string s, green "@"]+ y -> vcat [green "@", goplain y <> green "@"]+ go (DocString s) = do+ DocContext {..} <- ask+ return $+ case flattenBehavior of+ Flatten ->+ case textPosition of+ Body -> strBody s+ ParaStart -> strPara s+ WordBreak ->+ fillSep $+ (if textPosition == ParaStart+ then map2 strPara strBody+ else map strBody) $+ splitWhen isSpace s+ go (DocDefList ds) = do+ docs <-+ forM ds $ \(hdr, body) -> do+ rhdr <- inBody $ go hdr+ rbdy <- inBody $ go body+ return $ enclose (green "[") (green "]") rhdr <+> rbdy+ return $ vcat docs+ go (DocExamples es) =+ return $+ vcat $+ map+ (\Example {..} ->+ vcat $+ (green ">>>" <+> string exampleExpression) : map string exampleResult)+ es+ go (DocModule x) = return $ enclose (green "\"") (green "\"") (strBody x)+ go (DocIdentifier (c, x, c2)) =+ return $ enclose (green $ char c) (green $ char c2) (string x)+ go (DocMathDisplay x) = return $ enclose (green "\\[") (green "\\]") (strBody x)+ go (DocMathInline x) = return $ enclose (green "\\(") (green "\\)") (strBody x)+ -- go (DocAName x) = return $ enclose (green "#") (green "#") (strBody x)+ go (DocHyperlink (Hyperlink h l)) =+ return $+ enclose (green "<") (green ">") (string $ h ++ maybe "" (" " ++) (unNl <$> l))+ go (DocPic (Picture p t)) =+ return $+ enclose (green "<<") (green ">>") (string $ p ++ maybe "" (" " ++) (unNl <$> t))+ go x = error $ show x+ unNl =+ map+ (\x ->+ if x == '\n'+ then ' '+ else x)+ goplain (DocString s) = strPara $ escapeHtml s+ goplain (DocAppend a b) = goplain a <> goplain b+ goplain (DocIdentifier (a, b, c)) =+ enclose (green (char a)) (green (char c)) (string b)+ goplain (DocEmphasis x) = enclose (green "/") (green "/") (goplain x)+ goplain (DocModule x) = enclose (green "\"") (green "\"") (string x)+ goplain n = error $ "Unhandled in goplain: " ++ show n++map2 f g (x:xs) = f x : map g xs+map2 _ _ [] = []++arrowblock ('\n':ys) = line <> green "> " <> arrowblock ys+arrowblock (x:xs) = char x <> arrowblock xs+arrowblock "" = empty++escapeHtml "" = ""+escapeHtml ('\n':'\n':xs) = '\n' : '.' : '\n' : escapeHtml xs+escapeHtml ('\n':xs)+ | (spcs, '-':chrs) <- span isSpace xs = '\n' : spcs ++ ('\1' : '-' : escapeHtml chrs)+escapeHtml (c:cs) = c : escapeHtml cs++strPara ('>':'>':'>':cs) = text "\\>>>" <> strBody cs+strPara (x:cs)+ -- >, *, and - are mentioned by the haddock docks, but [ is also+ -- a special character b/c it starts a definition list+ | x `elem` ['>', '*', '-', '['] = char '\\' <> char x <> strBody cs+strPara x = strBody x++strBody ('\n':x) = line <> strPara x+strBody ('{':xs) = "{" <> strBody xs+strBody ('}':xs) = "}" <> strBody xs+strBody (x:xs)+ | x `elem` ['\\', '/', '\'', '`', '"', '@', '<', '#'] =+ char '\\' <> char x <> strBody xs+ | x == '\1' = char '\\' <> strBody xs+ | otherwise = char x <> strBody xs+strBody "" = empty
+ src/Render/Options.hs view
@@ -0,0 +1,43 @@+{-# Language FlexibleContexts #-}+{-# Language DeriveDataTypeable #-}+{-# Language DeriveGeneric #-}++module Render.Options+ ( module Render.Options+ , module Control.Monad.Reader+ ) where++import Control.Monad.Reader hiding (mapM)+import Data.Data+import Data.Default+import GHC.Generics+import Prelude.Compat+import Text.PrettyPrint.ANSI.Leijen (Doc, indent, width)++type Render = Reader RenderOptions++data RenderOptions = RenderOptions+ { -- | Number of spaces to use for indentation.+ indentSize :: Int+ -- | If 'True', @stylish-cabal@ will use+ -- 'Distribution.Version.simplifyVersionRange' to simplify every+ -- version range present in the Cabal file. For example, it'll turn+ -- a constraint like @>= 3.0 && <= 3.0@ into just @== 3.0@.+ , simplifyVersions :: Bool+ } deriving (Show, Eq, Generic, Typeable, Data)++instance Default RenderOptions where+ def = RenderOptions {indentSize = 2, simplifyVersions = False}++indentM :: Doc -> Render Doc+indentM k = do+ s <- asks indentSize+ return $ indent s k++(<&>) = flip fmap++widthR :: Doc -> (Int -> Render Doc) -> Render Doc+widthR = liftRender . width++liftRender :: ((a -> b) -> c) -> (a -> Render b) -> Render c+liftRender f g = ask <&> \env -> f $ \fn -> runReader (g fn) env
src/StylishCabal.hs view
@@ -1,44 +1,49 @@-{-# Language CPP #-}- -- | Cabal file formatter. module StylishCabal ( -- * Formatting Cabal files pretty- , prettyWithIndent+ , prettyOpts+ , RenderOptions(..) , render -- * Parsing utilities- , parseCabalFile- , readCabalFile+ , parsePackageDescription+ , readPackageDescription , Result(..) , result , printWarnings , displayError -- * Reexports+ , Default(..) , Doc+ , renderDescription , plain , displayIO , displayS ) where -import Text.PrettyPrint.ANSI.Leijen (Doc, displayIO, displayS, line, plain, renderSmart)+import Data.Default+import Distribution.PackageDescription (GenericPackageDescription)+import Prelude.Compat+import Render.Lib.Haddock+import Text.PrettyPrint.ANSI.Leijen hiding (pretty) import Parse import Render+import Render.Options import Transform -#if !MIN_VERSION_base(4,11,0)-import Data.Monoid-#endif- -- | @pretty pkg@ produces a colorized, formatted textual representation of -- a given 'Distribution.PackageDescription.GenericPackageDescription',--- with a default indent width of 2.+-- using 'Default' options. -- -- To remove syntax highlighting, you can use 'plain'.-pretty = prettyWithIndent 2+pretty :: GenericPackageDescription -> Doc+pretty = prettyOpts def --- | Like 'pretty', but allows you to specify an indent size.-prettyWithIndent i gpd = uncurry (blockBodyToDoc i) (toBlocks gpd) <> line+-- | 'pretty' with specified options.+prettyOpts :: RenderOptions -> GenericPackageDescription -> Doc+prettyOpts opts gpd = runReader (uncurry blockBodyToDoc $ toBlocks gpd) opts <> line -- | Render the given 'Doc' with the given width.+render :: Int -> Doc -> SimpleDoc render = renderSmart 1.0
src/Transform.hs view
@@ -1,4 +1,3 @@-{-# Language CPP #-} {-# Language FlexibleContexts #-} {-# Language RecordWildCards #-} @@ -10,11 +9,9 @@ import Control.DeepSeq import Control.Monad import Data.Char-import Data.Either import Data.Maybe import Distribution.License import Distribution.PackageDescription-import Distribution.Simple.BuildToolDepends import Distribution.Types.CondTree import Distribution.Types.ExecutableScope import Distribution.Types.ForeignLib@@ -23,9 +20,7 @@ import Distribution.Types.PackageName import Distribution.Types.UnqualComponentName import Distribution.Version-#if !MIN_VERSION_base(4,8,0)-import Data.Functor ((<$>))-#endif+import Prelude.Compat import Types.Block import Types.Field@@ -68,7 +63,7 @@ showType x = map toLower $ show x pdToFields pd@PackageDescription {..} =- [ guard newSpec >> cabalVersion "cabal-version" packageVersion+ [ guard newSpec >> cabalVersion "cabal-version" specVersionRaw , stringField "name" (unPackageName $ pkgName package) , version "version" (pkgVersion package) , nonEmpty (stringField "synopsis") synopsis@@ -90,7 +85,7 @@ , nonEmpty (longList "extra-doc-files") extraDocFiles , nonEmpty (longList "data-files") dataFiles , nonEmpty (stringField "data-dir") dataDir- , guard (not newSpec) >> cabalVersion "cabal-version" (specVersion pd)+ , guard (not newSpec) >> cabalVersion "cabal-version" specVersionRaw ] ++ map (uncurry stringField) customFieldsPD where@@ -117,7 +112,7 @@ (nodesToBlocks pkg libBuildInfo libDataToFields condTreeComponents) libDataToFields Library {..} =- libName `seq`+ libName `deepseq` [ ffilter not (stringField "exposed" . show) libExposed , nonEmpty (modules "exposed-modules") exposedModules , nonEmpty (rexpModules "reexported-modules") reexportedModules@@ -125,7 +120,7 @@ ] foreignLibToBlock pkg libname CondNode {..} =- deepseq condTreeConstraints $+ condTreeConstraints `deepseq` Block (ForeignLib_ $ unUnqualComponentName libname) (foreignLibDataToFields condTreeData ++@@ -210,7 +205,7 @@ (nodesToBlocks pkg getBuildInfo extra (condTreeComponents b)) in b1 : maybeToList b2 -buildInfoToFields pkg BuildInfo {..} =+buildInfoToFields _ BuildInfo {..} = [ nonEmpty (commas "other-languages" . map show) otherLanguages , nonEmpty (modules "other-modules") otherModules , nonEmpty (mixins_ "mixins") mixins@@ -244,14 +239,6 @@ map (optionToField "-shared") sharedOptions ++ map (uncurry stringField) customFieldsBI where- (oldTools, newTools) =- partitionEithers $- map Right buildToolDepends ++- map- (\dep ->- case desugarBuildTool pkg dep of- Just k -> Right k- Nothing -> Left dep)- buildTools+ (oldTools, newTools) = (buildTools, buildToolDepends) optionToField pref (f, args) = spaces (map toLower (show f) ++ pref ++ "-options") args
src/Types/Block.hs view
@@ -1,28 +1,29 @@ module Types.Block where import Distribution.PackageDescription+import Prelude.Compat import Types.Field -type File c = ([Maybe Field], [Block c])+type File = ([Maybe Field], [Block]) -data Block c = Block- { title :: BlockHead c+data Block = Block+ { title :: BlockHead , fields :: [Maybe Field]- , subBlocks :: [Block c]- }- deriving Show+ , subBlocks :: [Block]+ } deriving (Show) -data BlockHead c = If (Condition c)- | Else- | Benchmark_ String- | TestSuite_ String- | Exe_ String- | Library_ (Maybe String)- | ForeignLib_ String- | Flag_ String- | SourceRepo_ RepoKind- | CustomSetup- deriving Show+data BlockHead+ = If (Condition ConfVar)+ | Else+ | Benchmark_ String+ | TestSuite_ String+ | Exe_ String+ | Library_ (Maybe String)+ | ForeignLib_ String+ | Flag_ String+ | SourceRepo_ RepoKind+ | CustomSetup+ deriving (Show) isElse Else = True isElse _ = False
src/Types/Field.hs view
@@ -42,12 +42,15 @@ import Distribution.Types.ModuleReexport import Distribution.Types.PkgconfigDependency import Distribution.Version+import Documentation.Haddock.Parser+import Documentation.Haddock.Types (_doc, DocH) import Language.Haskell.Extension+import Prelude.Compat data FieldVal = Dependencies [Dependency] | Version Version- | CabalVersion Version+ | CabalVersion (Either Version VersionRange) | License License | Str String | File String@@ -68,7 +71,7 @@ deriving (Show) data Field- = Description String+ = Description (DocH () Identifier) | Field String FieldVal deriving (Show)@@ -103,6 +106,8 @@ version n a = Just $ Field n (Version a) +cabalVersion _ (Right x)+ | x == anyVersion = Nothing cabalVersion n a = Just $ Field n (CabalVersion a) modules n as = Just $ Field n (Modules as)@@ -121,7 +126,7 @@ fieldName (Description _) = "description" desc [] = Nothing-desc vs = Just (Description vs)+desc vs = Just (Description $ _doc $ parseParas vs) buildDeps [] = Nothing buildDeps vs = dependencies "build-depends" vs
stylish-cabal.cabal view
@@ -1,18 +1,18 @@ name: stylish-cabal-version: 0.2.0.0+version: 0.3.0.0 synopsis: Format Cabal files description: A tool for nicely formatting your Cabal file. license: BSD3 license-file: LICENSE author: Jude Taylor maintainer: me@jude.xyz-tested-with: GHC == 7.8.4, GHC == 7.10.3, GHC == 8.0.2, GHC == 8.2.2,- GHC == 8.4.0.20180204+tested-with: GHC == 7.4.2, GHC == 7.6.3, GHC == 7.8.4, GHC == 7.10.3, GHC == 8.0.2,+ GHC == 8.2.2 category: Language build-type: Simple extra-source-files: ChangeLog.md- tests/example.cabal-cabal-version: >= 1.10+ tests/cabal-files/*.txt+cabal-version: 2.0 source-repository head type: git@@ -31,43 +31,72 @@ flag test-strictness default: False manual: True- description:- Run the strictness testsuite. This requires the StrictCheck package which is not yet- on Hackage, and thus is disabled by default.+ description: Run the strictness testsuite. This requires the StrictCheck package which+ is not yet on Hackage, and thus is disabled by default. library exposed-modules: StylishCabal other-modules: Parse Render Render.Lib+ Render.Lib.Haddock+ Render.Options Transform Types.Block Types.Field hs-source-dirs: src- build-depends: base == 4.*, Cabal == 2.0.*, ansi-wl-pprint, deepseq, split+ build-depends: base == 4.*+ , Cabal == 2.0.*+ , ansi-wl-pprint+ , base-compat+ , data-default+ , deepseq+ , haddock-library+ , mtl+ , split default-language: Haskell2010 default-extensions: NoMonomorphismRestriction+ NoImplicitPrelude ghc-options: -Wall -fno-warn-missing-signatures + if impl(ghc < 7.6)+ build-depends: ghc-prim+ if flag(werror) ghc-options: -Werror -executable stylish-cabal- main-is: Main.hs- build-depends: base, ansi-wl-pprint, optparse-applicative, stylish-cabal- default-language: Haskell2010- ghc-options: -Wall+library test-utils+ exposed-modules: Expectations+ SortedPackageDescription+ other-modules: MultiSet+ SortedPackageDescription.TH+ hs-source-dirs: tests/utils+ build-depends: base+ , Cabal+ , base-compat+ , containers+ , haddock-library+ , hspec+ , hspec-core+ , hspec-expectations-pretty-diff+ , microlens+ , microlens-th+ , split+ , stylish-cabal+ , template-haskell+ default-language: Haskell2010+ default-extensions: NoImplicitPrelude+ ghc-options: -Wall -fno-warn-missing-signatures if flag(werror) ghc-options: -Werror -test-suite hlint- type: exitcode-stdio-1.0- main-is: hlint.hs- hs-source-dirs: tests- build-depends: base, hlint- default-language: Haskell2010- ghc-options: -Wall+executable stylish-cabal+ main-is: Main.hs+ build-depends: base, base-compat, optparse-applicative, stylish-cabal+ default-language: Haskell2010+ default-extensions: NoImplicitPrelude+ ghc-options: -Wall if flag(werror) ghc-options: -Werror@@ -82,6 +111,7 @@ , Cabal , StrictCheck , ansi-wl-pprint+ , base-compat , bytestring , deepseq , generics-sop@@ -89,8 +119,8 @@ , hspec-expectations-pretty-diff , stylish-cabal default-language: Haskell2010- default-extensions: CPP- ghc-options: -freduction-depth=0+ default-extensions: NoImplicitPrelude+ ghc-options: -freduction-depth=0 -Wall if flag(werror) ghc-options: -Werror@@ -101,46 +131,34 @@ test-suite roundtrip type: exitcode-stdio-1.0 main-is: Main.hs- other-modules: SortedDesc- Utils hs-source-dirs: tests/roundtrip- build-depends: base- , Cabal- , ansi-wl-pprint- , containers- , hspec- , hspec-core- , hspec-expectations-pretty-diff- , stylish-cabal+ build-depends: base, base-compat, hspec, test-utils default-language: Haskell2010- default-extensions: CPP+ default-extensions: NoImplicitPrelude ghc-options: -Wall -fno-warn-missing-signatures if flag(werror) ghc-options: -Werror test-suite roundtrip-hackage- type: exitcode-stdio-1.0- main-is: Hackage.hs- other-modules: SortedDesc- Utils- hs-source-dirs: tests/roundtrip- build-depends: base- , Cabal- , aeson- , ansi-wl-pprint- , containers- , hspec- , hspec-core- , hspec-expectations-pretty-diff- , lens- , mwc-random- , stylish-cabal- , utf8-string- , vector- , wreq- default-language: Haskell2010- ghc-options: -threaded -rtsopts -with-rtsopts=-N -Wall -fno-warn-missing-signatures+ type: exitcode-stdio-1.0+ main-is: Hackage.hs+ hs-source-dirs: tests/roundtrip+ build-depends: base+ , aeson+ , base-compat+ , hspec+ , hspec-core+ , lens+ , mwc-random+ , test-utils+ , utf8-string+ , vector+ , wreq+ default-language: Haskell2010+ default-extensions: NoImplicitPrelude+ ghc-options: -threaded -rtsopts -with-rtsopts=-N -Wall+ -fno-warn-missing-signatures if flag(werror) ghc-options: -Werror
+ tests/cabal-files/BiGUL.txt view
@@ -0,0 +1,68 @@+name: BiGUL+version: 1.0.1+synopsis: The Bidirectional Generic Update Language+description:+ Putback-based bidirectional programming allows the programmer to+ write only one putback transformation, from which the unique+ corresponding forward transformation is derived for free. BiGUL,+ short for the Bidirectional Generic Update Language, is designed to+ be a minimalist putback-based bidirectional programming language.+ BiGUL was originally developed in the dependently typed programming+ language Agda, and its well-behavedness has been completely formally+ verified; this package is the Haskell port of BiGUL.+ .+ For more detail, see the following paper:+ .+ * Hsiang-Shang Ko, Tao Zan, and Zhenjiang Hu. BiGUL: A formally+ verified core language for putback-based bidirectional programming.+ In /Partial Evaluation and Program Manipulation/, PEPM’16,+ pages 61–72. ACM, 2016. <http://dx.doi.org/10.1145/2847538.2847544>.++homepage: http://www.prg.nii.ac.jp/project/bigul/+license: PublicDomain+license-file: UNLICENSE+author: Josh Ko, Tao Zan, Li Liu, Zirun Zhu, Jorge Mendes, and Zhenjiang Hu+maintainer: Josh Ko <hsiang-shang@nii.ac.jp> and Zirun Zhu <zhu@nii.ac.jp>+category: Language, Generics, Lenses+build-type: Simple+cabal-version: >=1.22+extra-source-files: CHANGELOG.md++library+ exposed-modules: Generics.BiGUL+ Generics.BiGUL.Error+ Generics.BiGUL.PatternMatching+ Generics.BiGUL.Interpreter+ Generics.BiGUL.Interpreter.Unsafe+ Generics.BiGUL.TH+ Generics.BiGUL.Lib+ Generics.BiGUL.Lib.HuStudies+ Generics.BiGUL.Lib.List+ other-modules: GHC.InOut+ default-extensions: TupleSections,+ ViewPatterns,+ GADTs,+ TypeFamilies,+ TypeOperators,+ EmptyCase,+ ExistentialQuantification,+ TemplateHaskell,+ DeriveDataTypeable,+ FlexibleInstances,+ FlexibleContexts,+ UndecidableInstances,+ CPP+ if impl(ghc >= 7.10) && impl(ghc < 8)+ build-depends: base == 4.8.*,+ mtl >= 2.2,+ containers >= 0.5,+ template-haskell >= 2.10 && < 2.11,+ th-extras >= 0.0.0.4+ else+ build-depends: base == 4.9.*,+ mtl >= 2.2,+ containers >= 0.5,+ template-haskell >= 2.11,+ th-extras >= 0.0.0.4+ hs-source-dirs: src+ default-language: Haskell2010
+ tests/cabal-files/Cardinality.txt view
@@ -0,0 +1,105 @@+Name: Cardinality+Synopsis: Measure container capacity. Use it to safely change container.+Description:+ This module introduces typeclasses+ .+ * @HasCard@ = \"Has cardinality\". In other words, \"it's possible to + measure current count of elements for this container\"+ .+ * @HasCardT@ = \"Has cardinality (for container types of kind + @(* -> *)@)\". In other words, \"it's possible to measure+ current count of elements for this container (for container types of+ kind @(* -> *)@)\"+ .+ * @HasCardConstr@ = \"Has cardinality constraint\". In other words, + \"there is a capacity constraint for this container\".+ .+ * @HasCardConstrT@ = \"Has cardinality constraint (for container types + of kind @(* -> *)@)\".+ In other words, \"there is a capacity constraint for this container type+ of kind @(* -> *)@\".+ .+ * @HasCardUCT@ = \"Has cardinality-unsafe container transform\".+ Define transform that may thow an error, if contents of @from@ don't + fit in @to@ .+ .+ * @HasCardUCT_T@ = \"Has cardinality-unsafe container + transform (for container types of kind @(* -> *)@)\".+ Same thing as @HasCardUCT@, but for containers of kind @(* -> *)@.+ .+ No, it's not about playing cards. It's about cardinalities. + Wikipedia: \"/In mathematics, the cardinality of a set is a measure of + the number of elements of the set. For example, the set A = {2, 4, 6}+ contains 3 elements, and therefore A has a cardinality of 3./\"+ In this package I dare to extend the definition a bit to + \"/C. is a measure of the number of elements in a container/\"+ .+ Usual containers are (together with their cardinality ranges): + .+ * @Identity a@ (1 element)+ .+ * @Maybe a@ (0..1 element)+ .+ * @[a]@ (0..inf elements)+ .+ * @Map k e@ (0..inf elements)+ . + I extended this to the folowing list:+ .+ * @EmptySet a@ (0 elements)+ .+ * @Identity a@ (1 element)+ .+ * @Maybe a@ (0..1 element)+ .+ * @[a]@ (0..inf elements)+ .+ * @NeverEmptyList a@ (1..inf elements)+ .+ * @Map k e@ (0..inf elements)+ .+ Typeclass @HasCardUCT@ together with function @sContTrans@ + (safe container transform) provides a facility to safely change + container from one to another keepeng the content. If content doesn't + fit to target container, @Nothing@ is returned. However, when + transforming from list @[a]@ to @(Maybe a)@ it won't check list length+ further first 2 elements. The complexity and power of this package is + that it provides a facility to /lazily/ evaluate amount of content in+ the container.+ .+ To interface package functions + .+ @import Data.Cardinality@+Version: 0.2+Copyright: Copyright (c) 2010 Andrejs Sisojevs+License: LGPL+License-File: COPYRIGHT+Author: Andrejs Sisojevs <andrejs.sisojevs@nextmail.ru>+Maintainer: Andrejs Sisojevs <andrejs.sisojevs@nextmail.ru>+Stability: experimental+Category: Data+Tested-With: GHC == 6.10.4+Cabal-Version: >= 1.6+Build-Type: Simple++Extra-Source-Files:+ COPYRIGHT+ COPYING+ NEWS+ doinst.sh+ examples/CardinalityRangeCompareTest.hs+ examples/ContainerTransformsTests.hs+ examples/HelloWorld.hs+Library+ Build-Depends:+ base >= 4 && < 5, containers, mtl+ Exposed-Modules:+ Data.Cardinality.Cardinality+ Data.Cardinality.CardinalityRange+ Data.Cardinality.ContTrans+ Data.Cardinality+ Data.EmptySet+ Data.Intersectable+ Data.NeverEmptyList+ Extensions:+ DeriveDataTypeable
+ tests/cabal-files/ChasingBottoms.txt view
@@ -0,0 +1,185 @@+name: ChasingBottoms+version: 1.3.1.3+license: MIT+license-file: LICENCE+copyright: Copyright (c) Nils Anders Danielsson 2004-2017.+author: Nils Anders Danielsson+maintainer: http://www.cse.chalmers.se/~nad/+synopsis: For testing partial and infinite values.+description:+ Do you ever feel the need to test code involving bottoms (e.g. calls to+ the @error@ function), or code involving infinite values? Then this+ library could be useful for you.+ .+ It is usually easy to get a grip on bottoms by showing a value and+ waiting to see how much gets printed before the first exception is+ encountered. However, that quickly gets tiresome and is hard to automate+ using e.g. QuickCheck+ (<http://www.cse.chalmers.se/~rjmh/QuickCheck/>). With this library you+ can do the tests as simply as the following examples show.+ .+ Testing explicitly for bottoms:+ .+ > > isBottom (head [])+ > True+ .+ > > isBottom bottom+ > True+ .+ > > isBottom (\_ -> bottom)+ > False+ .+ > > isBottom (bottom, bottom)+ > False+ .+ Comparing finite, partial values:+ .+ > > ((bottom, 3) :: (Bool, Int)) ==! (bottom, 2+5-4)+ > True+ .+ > > ((bottom, bottom) :: (Bool, Int)) <! (bottom, 8)+ > True+ .+ Showing partial and infinite values (@\\\/!@ is join and @\/\\!@ is meet):+ .+ > > approxShow 4 $ (True, bottom) \/! (bottom, 'b')+ > "Just (True, 'b')"+ .+ > > approxShow 4 $ (True, bottom) /\! (bottom, 'b')+ > "(_|_, _|_)"+ .+ > > approxShow 4 $ ([1..] :: [Int])+ > "[1, 2, 3, _"+ .+ > > approxShow 4 $ (cycle [bottom] :: [Bool])+ > "[_|_, _|_, _|_, _"+ .+ Approximately comparing infinite, partial values:+ .+ > > approx 100 [2,4..] ==! approx 100 (filter even [1..] :: [Int])+ > True+ .+ > > approx 100 [2,4..] /=! approx 100 (filter even [bottom..] :: [Int])+ > True+ .+ The code above relies on the fact that @bottom@, just as @error+ \"...\"@, @undefined@ and pattern match failures, yield+ exceptions. Sometimes we are dealing with properly non-terminating+ computations, such as the following example, and then it can be nice to+ be able to apply a time-out:+ .+ > > timeOut' 1 (reverse [1..5])+ > Value [5,4,3,2,1]+ .+ > > timeOut' 1 (reverse [1..])+ > NonTermination+ .+ The time-out functionality can be used to treat \"slow\" computations as+ bottoms:+ .+ @+ \> let tweak = Tweak { approxDepth = Just 5, timeOutLimit = Just 2 }+ \> semanticEq tweak (reverse [1..], [1..]) (bottom :: [Int], [1..] :: [Int])+ True+ @+ .+ @+ \> let tweak = noTweak { timeOutLimit = Just 2 }+ \> semanticJoin tweak (reverse [1..], True) ([] :: [Int], bottom)+ Just ([],True)+ @+ .+ This can of course be dangerous:+ .+ @+ \> let tweak = noTweak { timeOutLimit = Just 0 }+ \> semanticEq tweak (reverse [1..100000000]) (bottom :: [Integer])+ True+ @+ .+ Timeouts can also be applied to @IO@ computations:+ .+ > > let primes () = unfoldr (\(x:xs) -> Just (x, filter ((/= 0) . (`mod` x)) xs)) [2..]+ > > timeOutMicro 100 (print $ primes ())+ > [2,NonTermination+ > > timeOutMicro 10000 (print $ take 10 $ primes ())+ > [2,3,5,7,11,13,17,19,23,29]+ > Value ()+ .+ For the underlying theory and a larger example involving use of+ QuickCheck, see the article \"Chasing Bottoms, A Case Study in Program+ Verification in the Presence of Partial and Infinite Values\"+ (<http://www.cse.chalmers.se/~nad/publications/danielsson-jansson-mpc2004.html>).+ .+ The code has been tested using GHC. Most parts can probably be+ ported to other Haskell compilers, but this would require some work.+ The @TimeOut@ functions require preemptive scheduling, and most of+ the rest requires @Data.Generics@; @isBottom@ only requires+ exceptions, though.+category: Testing+tested-with: GHC == 6.12.3,+ GHC == 7.0.4,+ GHC == 7.4.2,+ GHC == 7.6.3,+ GHC == 7.8.4,+ GHC == 7.10.3,+ GHC == 8.0.2,+ GHC == 8.2.1+cabal-version: >= 1.9.2+build-type: Simple++source-repository head+ type: darcs+ location: http://www.cse.chalmers.se/~nad/repos/ChasingBottoms/++library+ exposed-modules:+ Test.ChasingBottoms,+ Test.ChasingBottoms.Approx,+ Test.ChasingBottoms.ApproxShow,+ Test.ChasingBottoms.ContinuousFunctions,+ Test.ChasingBottoms.IsBottom,+ Test.ChasingBottoms.Nat,+ Test.ChasingBottoms.SemanticOrd,+ Test.ChasingBottoms.TimeOut++ other-modules: Test.ChasingBottoms.IsType++ build-depends: QuickCheck >= 2.3 && < 2.11,+ mtl >= 2 && < 2.3,+ base >= 4.2 && < 4.11,+ containers >= 0.3 && < 0.6,+ random >= 1.0 && < 1.2,+ syb >= 0.1.0.2 && < 0.8++test-suite ChasingBottomsTestSuite+ type: exitcode-stdio-1.0++ main-is: Test/ChasingBottoms/Tests.hs++ other-modules: Test.ChasingBottoms.Approx,+ Test.ChasingBottoms.Approx.Tests,+ Test.ChasingBottoms.ApproxShow,+ Test.ChasingBottoms.ApproxShow.Tests,+ Test.ChasingBottoms.ContinuousFunctions,+ Test.ChasingBottoms.ContinuousFunctions.Tests,+ Test.ChasingBottoms.IsBottom,+ Test.ChasingBottoms.IsBottom.Tests,+ Test.ChasingBottoms.IsType,+ Test.ChasingBottoms.IsType.Tests,+ Test.ChasingBottoms.Nat,+ Test.ChasingBottoms.Nat.Tests,+ Test.ChasingBottoms.SemanticOrd,+ Test.ChasingBottoms.SemanticOrd.Tests,+ Test.ChasingBottoms.TestUtilities,+ Test.ChasingBottoms.TestUtilities.Generators,+ Test.ChasingBottoms.TimeOut+ Test.ChasingBottoms.TimeOut.Tests++ build-depends: QuickCheck >= 2.3 && < 2.11,+ mtl >= 2 && < 2.3,+ base >= 4.2 && < 4.11,+ containers >= 0.3 && < 0.6,+ random >= 1.0 && < 1.2,+ syb >= 0.1.0.2 && < 0.8,+ array >= 0.3 && < 0.6
+ tests/cabal-files/OrPatterns.txt view
@@ -0,0 +1,61 @@+name: OrPatterns+version: 0.1+synopsis: A quasiquoter for or-patterns+description: A quasiquoter for or-patterns. It allows one additional+ form for patterns:+ .+ > f [o| p1 | p2 | p3 |] = rhs+ .+ Above, @p1@, @p2@ and @p3@ are three arbitrary patterns+ that bind the same variables. These variables are+ available in the expression @rhs@. Nesting of or-patterns+ is not supported yet.+ .+ See also:+ .+ * http://hackage.haskell.org/package/first-class-patterns+ supports @\\\/@ (or). However, variables bound with+ those patterns are not named. This means:+ .+ > g :: Either (x, y) (y, x) -> (x, y)+ > g [o| Left (x,y) | Right (y,x) |] = (x,y)+ .+ > -- ends up slightly longer+ > g = elim $ left (pair var var) \/ right flipped ->> (,)+ > where+ > flipped = (\(a,b) -> (b,a)) --> pair var var+ .+ * http://hackage.haskell.org/trac/ghc/ticket/3919+ is the feature request for or-patterns in ghc++license: BSD3+license-file: LICENSE+author: Adam Vogt <vogt.adam@gmail.com>+maintainer: Adam Vogt <vogt.adam@gmail.com>+category: Development+build-type: Simple+cabal-version: >=1.10+tested-with: GHC == 7.8.2,+ GHC == 7.6.2,+ GHC == 7.4.1++source-repository head+ type: darcs+ location: http://code.haskell.org/~aavogt/OrPatterns+++library+ exposed-modules: OrPatterns+ OrPatterns.Internal+ other-extensions: TemplateHaskell++ build-depends: base >=4.5 && <4.8,+ template-haskell >=2.4 && <2.10,+ mtl >=2.1 && <2.2,+ syb >=0.4 && <0.5,+ split >=0.2 && <0.3,+ haskell-src-meta >=0.6 && <0.7,+ haskell-src-exts >=1.15 && <1.16,+ containers >=0.3 && <0.6++ default-language: Haskell2010
+ tests/cabal-files/deepseq-bounded.txt view
@@ -0,0 +1,717 @@+-------------------------------------------------------------------------------++name: deepseq-bounded+version: 0.8.0.0+x-revision: 1+synopsis: Bounded deepseq, including support for generic deriving+license: BSD3+license-file: LICENSE+author: Andrew G. Seniuk+maintainer: Andrew Seniuk <rasfar@gmail.com>+homepage: http://fremissant.net/deepseq-bounded+bug-reports: http://fremissant.net/deepseq-bounded/trac+---bug-reports: Andrew Seniuk <rasfar@gmail.com>+category: Control+--hackage-tags: leak, space, parallel, strictness, forcing, diagnostic, remedial, bsd3, library+build-type: Simple+stability: provisional+cabal-version: >= 1.10++-- GHC <= 7.4.2 won't work, unless you're also HASKELL98_FRAGMENT+-- (or at least USE_SOP is False).+tested-with: GHC==7.6.3, GHC==7.8.1, GHC==7.8.3, GHC==7.8.4, GHC==7.10.1+--tested-with: GHC==7.6.3, GHC==7.8.*, GHC==7.10.1 -- illegal syntax++description:+ This package provides methods for partially (or fully) evaluating data+ structures (\"bounded deep evaluation\").+ .+ More information is available on the project <http://www.fremissant.net/deepseq-bounded homepage>.+ There may be activity on this <http://www.reddit.com/r/haskell/comments/2pscxh/ann_deepseqbounded_seqaid_leaky/ reddit> discussion, where your comments are invited.+ .+ Quoting from the+ <http://hackage.haskell.org/package/deepseq deepseq> package:+ .+ \"/Artificial forcing is often used for adding strictness to a program, e.g. in order to force pending exceptions, remove space leaks, or force lazy IO to happen. It is also useful in parallel programs, to ensure work does not migrate to the wrong thread./\"+ .+ Sometimes we don't want to, or cannot, force all the way, for instance+ when dealing with potentially infinite values of coinductive types.+ Also, bounded forcing bridges the theoretical axis between shallow seq+ and full deepseq.+ .+ We provide two new classes <http://hackage.haskell.org/package/deepseq-bounded-0.8.0.0/docs/Control-DeepSeq-Bounded-NFDataN.html#t:NFDataN NFDataN> and <http://hackage.haskell.org/package/deepseq-bounded-0.8.0.0/docs/Control-DeepSeq-Bounded-NFDataP.html#t:NFDataP NFDataP>.+ Instances of these provide bounded deep evaluation for arbitrary polytypic terms:+ .+ * <http://hackage.haskell.org/package/deepseq-bounded-0.8.0.0/docs/Control-DeepSeq-Bounded-NFDataN.html#t:NFDataN rnfn> bounds the forced evaluation by depth of recursion.+ .+ * <http://hackage.haskell.org/package/deepseq-bounded-0.8.0.0/docs/Control-DeepSeq-Bounded-NFDataP.html#t:NFDataP rnfp> forces based on patterns (static or dynamic).+ .+ Instances of <http://hackage.haskell.org/package/deepseq-bounded-0.8.0.0/docs/Control-DeepSeq-Bounded-NFDataN.html NFDataN> and <http://hackage.haskell.org/package/deepseq-bounded-0.8.0.0/docs/Control-DeepSeq-Bounded-NFDataP.html NFDataP> can be automatically derived via <http://hackage.haskell.org/package/generics-sop/docs/Generics-SOP.html Generics.SOP>, backed by the <http://hackage.haskell.org/package/deepseq-bounded-0.8.0.0/docs/Control-DeepSeq-Bounded-Generic-GNFDataN.html GNFDataN> and <http://hackage.haskell.org/package/deepseq-bounded-0.8.0.0/docs/Control-DeepSeq-Bounded-Generic-GNFDataP.html GNFDataP> modules.+ <http://hackage.haskell.org/package/deepseq-bounded-0.8.0.0/docs/Control-DeepSeq-Bounded-NFDataN.html NFDataN> can optionally be derived by the standard <http://downloads.haskell.org/~ghc/7.8.3/docs/html/libraries/base-4.7.0.1/GHC-Generics.html GHC.Generics> facility (but not so for <http://hackage.haskell.org/package/deepseq-bounded-0.8.0.0/docs/Control-DeepSeq-Bounded-NFDataP.html NFDataP>).+ .+ Another approach is <http://hackage.haskell.org/package/deepseq-bounded-0.8.0.0/docs/Control-DeepSeq-Bounded-Seqable.html Seqable>, which is similar to <http://hackage.haskell.org/package/deepseq-bounded-0.8.0.0/docs/Control-DeepSeq-Bounded-NFDataN.html NFDataN>,+ but optimised for use as a dynamically-reconfigurable forcing harness+ in the <http://hackage.haskell.org/package/seqaid seqaid> auto-instrumentation tool.+ .+ Recent developments supporting parallelisation control (in <http://hackage.haskell.org/package/deepseq-bounded-0.8.0.0/docs/Control-DeepSeq-Bounded-Pattern.html Pattern>+ and <http://hackage.haskell.org/package/deepseq-bounded-0.8.0.0/docs/Control-DeepSeq-Bounded-Seqable.html Seqable> modules) may justify renaming this library to+ something which encompasses both strictness and parallelism aspects.+ .+ / NOTE: Versions >=0.6 are substantially different from the original (now deprecated) 0.5.* releases, particularly as regards NFDataP. /++extra-source-files:+ README+ , changelog.txt+ , hackage-tags.txt+ , tests/*.hs+ , HTML/*.html+ , HTML/*.css+ , deepseq-bounded-seqaid-leaky.html+ , deepseq-bounded-seqaid-leaky.css+ , cafe-and-glasgow-users-0.6.txt+ , cpphs.sh++-- source-repository head+-- type: git+-- location: https://www.fremissant.com/package/deepseq-bounded.git+-- +-- source-repository this+-- type: git+-- location: https://www.fremissant.com/package/deepseq-bounded.git+-- tag: deepseq-bounded-0.6.0-release++-------------------------------------------------------------------------------++Flag HELLO_HACKAGE_VISITOR+ Description: [Note to those reading on Hackage:] Please ignore these flags, which would be better presented in a collapsed state. The flags are mostly for development purposes.+ Default: False+ Manual: True++Flag HASKELL98_FRAGMENT+ Description: Sacrifice generic deriving, the NFDataPDyn module, and a couple functions from the PatUtil module, in exchange for true Haskell98 conformance (portability). (One non-H98 thing it insists on is PatternGuards, although this could be relieved in the obvious way, at the expense of code clarity.)+--Default: True+ Default: False+ Manual: True++Flag USE_PAR_PATNODE+ Description: On match, spark recursive submatching for parallel evaluation.+ Default: True+--Default: False+ Manual: True++Flag USE_PSEQ_PATNODE+ Description: Use Control.Parallel.pseq to order the evaluation of recursive submatching. This is done by providing a permutation argument; refer to the Control.DeepSeq.Bounded.Pattern.PatNode API for additional documentation. Configurable per PatNode.+ Default: True+--Default: False+ Manual: True++Flag USE_TRACE_PATNODE+ Description: Log a traceline to stderr en passant. Configurable per PatNode. Fires when node is pattern-matched, whether or not the match succeeds.+ Default: True+--Default: False+ Manual: True++Flag USE_PING_PATNODE+ Description: Raise an asynchronous exception en passant. This can be useful for gauging term shape relative to pattern shape, dynamically. Configurable per PatNode. Fires when node is pattern-matched, whether or not the match succeeds.+ Default: True+--Default: False+ Manual: True++Flag USE_DIE_PATNODE+ Description: Kill (just this) thread immediately. To kill the whole program from a pattern node match, use USE_PING_PATNODE, catch the exception in the main thread, and respond from there as you see fit. Configurable per PatNode. Fires when node is pattern-matched, whether or not the match succeeds.+ Default: True+--Default: False+ Manual: True++Flag USE_TIMING_PATNODE+ Description: Get as precise a measurement of the time of matching as possible, and optionally (depending on how you use the API) measuring and reporting (storing?) differential timestamps (relative to parent node already matched). Not sure how useable this will be (the timestamps need to be very high resolution and cheap enough to obtain), but the principle has its place here, and the flag makes it possible to exclude all this code in case it's not working out. Configurable per PatNode. Fires when node is pattern-matched, whether or not the match succeeds.+ Default: True+--Default: False+ Manual: True++Flag OVERLOADED_STRINGS+ Description: Use the OverloadedStrings syntax extension, so never need to call compilePat explicitly. This gives the feeling of "bringing the DSL right into Haskell", and makes ghci experiments a lot less of a headache! Wish I'd had this in since the first release. I guess really nobody is experimenting with this at all, or surely they'd have clamoured for this!+ Default: True+--Default: False+ Manual: True++Flag USE_PAR_SEQABLE+ Description: This flag (now) only affects Seqable. (Refer to USE_PAR_PATNODE for a comparable flag affecting NFDataP.) USE_PAR_SEQABLE = True depends on parallel, and permits (dynamically configurable) sparking of Sequable recursive demand propagation.+ Default: True+--Default: False+ Manual: True++-- Flag DEPTH_USES_INT64+-- Description: This won't be implemented for a while, probably.+-- --Default: True+-- Default: False+-- Manual: True++Flag JUST_ALIAS_GSEQABLE+ Description: The SOP generic function is probably more performant, anyway! (This will be forced False if HASKELL98_FRAGMENT is True.)+ Default: True+--Default: False+ Manual: True++Flag JUST_ALIAS_GNFDATAN+ Description: The SOP generic function is probably more performant, anyway! (This will be forced False if HASKELL98_FRAGMENT is True.)+--Default: True+ Default: False+ Manual: True++Flag JUST_ALIAS_GNFDATAP+ Description: The SOP generic function is probably more performant, anyway! (This will be forced False if HASKELL98_FRAGMENT is True.)+--Default: True+ Default: False+ Manual: True++Flag PROVIDE_DATA_FAMILY+ Description: Provide a data family comprising instances corresponding to the Seqable, NFDataN and NFDataP modules. (This will be forced False if HASKELL98_FRAGMENT is True.)+ Default: True+--Default: False+ Manual: True++Flag USE_CURLY_BRACE_INSTEAD_OF_PAREN_FOR_SUBPATTERNS+ Description: Choose grouping convention (concrete syntax) for pattern strings in the DSL. When True, you have "XX.*Y..Y" instead of the (new) default "((.*)..)". Where X=opening curly brace, and Y=closing curly brace - it seems Cabal makes it impossible to present a curly brace in a flag description, even escaped? Unless Unicode entities? { \u007D } Nope.+--Default: True+ Default: False+ Manual: True++Flag ABBREV_WN_AND_TN_CONCRETE_SYNTAX_TO_NUMBER_ALONE__SAFE_ONLY_TO_DEPTH_19+ Description: So you can write "2(!53)" instead of "*2(!*5*3)". This will be unambiguous up to a depth of 19. (It may still be unambiguous for higher depths, depending on the use case.) This could be convenient if you work a lot manually with the pattern DSL, particularly for vertical alignment of pattern structures, but otherwise it should be False as ambigities can develop, for instance under (showPat . shrinkPat . compilePat) iteration.+---Default: True+ Default: False+ Manual: True++Flag ABBREV_WN_AND_TN_CONCRETE_SYNTAX_TO_SINGLE_DIGIT__CAN_ONLY_EXPRESS_DOWN_TO_DEPTH_9+ Description: Similar to the preceding, but use "1" instead of "!" for depth-1, and moreover, use "0" instead of "." for depth-0. (This is such a niche-case syntax variant, that may as well go all the way!) It makes for very tidy when you're not using a lot of other attributes. This grammar variant is unambiguous; the danger here is only that conventions get mixed in practise...+---Default: True+ Default: False+ Manual: True++Flag USE_WW_DEEPSEQ+ Description: Depend on deepseq and deepseq-generics, to provide conditional deep forcing. This is optional.+ Default: True+--Default: False+ Manual: True++Flag WARN_PATTERN_MATCH_FAILURE+ Description: For NFDataP, if a pattern match fails a warning is output to stderr.+--Default: True+ Default: False+ Manual: True++Flag USE_SOP+ Description: Use the generics-sop package instead of GHC.Generics (in GNFDataN) and instead of SYB (in NFDataPDyn). If USE_SOP is False, then NFDataPDyn, GNFDataP, and GSeqable modules will not be available.+ Default: True+--Default: False+ Manual: True++Flag NFDATA_INSTANCE_PATTERN+ Description: A flag to assist debugging, affecting a few modules.+ Default: True+--Default: False+ Manual: True++Flag USE_CPPHS+ Description: The original intention was to make this a non-manual flag, to allow the build system to try cpphs first, and if that fails, then to try system-wide cpp (typically GNU). Due to path problems, when the build client installs cpphs in the course of installing, it turns out to be better to use a shell script to delegate which cpp runs, jimmy options, etc.+--Default: False+ Default: True+--Manual: False+ Manual: True++-------------------------------------------------------------------------------++library {++-- I feel like declaring this is only asking for more trouble;+-- cpphs installs because it's mentioned as a dependency, and+-- that does install both the library and the executable.+---------+-- build-tools: cpphs +-- -- (This seems /not/ to work, since, when USE_CPPHS is default:false,+-- -- cpphs is still mentioned in the hackage deps.)+-- --if flag(USE_CPPHS)+-- -- build-tools: cpphs++ hs-source-dirs: src++ -- This library is Haskell98 if you exclude the generics bits.+ -- See the comment below (other-extensions) for more specifics.+ if flag(HASKELL98_FRAGMENT)+ default-language: Haskell98+ else+ default-language: Haskell2010++ default-extensions: CPP++-- If you exclude PatUtil.mkPat and PatUtil.growPat (which use SYB),+-- and NFDataPDyn, GNFDataN, and GNFDataP (which use GHC.Generics+-- and/or Generics.SOP), none of the code depends in any essential+-- way on language extensions. I use PatternGuards for convenience,+-- but they could be translated away easily, and we'd have Haskell98.+ if flag(HASKELL98_FRAGMENT)+ other-extensions: PatternGuards+ else+ -- ... and more (see what SOP and SYB actually need)+ other-extensions: PatternGuards, DeriveGeneric+--if impl(ghc >= 7.2)+-- other-extensions: Safe++ if ! flag(HASKELL98_FRAGMENT)+ if flag(OVERLOADED_STRINGS)+ default-extensions: OverloadedStrings++ exposed-modules:+ Control.DeepSeq.Bounded+ , Control.DeepSeq.Bounded.Seqable+ , Control.DeepSeq.Bounded.NFDataN+ , Control.DeepSeq.Bounded.Pattern+ , Control.DeepSeq.Bounded.Compile+ , Control.DeepSeq.Bounded.PatUtil+ , Control.DeepSeq.Bounded.NFDataP+ if ! flag(HASKELL98_FRAGMENT)+ exposed-modules:+ Control.DeepSeq.Bounded.Generic+ , Control.DeepSeq.Bounded.Generic.GNFDataN+ if flag(USE_SOP)+ exposed-modules:+ Control.DeepSeq.Bounded.Generic.GNFDataP+ , Control.DeepSeq.Bounded.Generic.GSeqable+ , Control.DeepSeq.Bounded.NFDataPDyn++--ghc-options: -Wall -fenable-rewrite-rules -ddump-rules -ddump-simpl-stats -ddump-rule-firings+--ghc-options: -Wall -fenable-rewrite-rules+ ghc-options: -fenable-rewrite-rules +--ghc-options: -fenable-rewrite-rules -O2++ ghc-options: -fno-warn-duplicate-exports++ ghc-options: -optP-Wundef -fno-warn-overlapping-patterns++ if flag(USE_CPPHS)+ -- the only reliable way to get equiv. of -pgmP"env PATH=$PATH:blah cpphs"+ ghc-options: -pgmP./cpphs.sh+--else+-- ghc-options: -cpp++ build-depends:++ base == 4.*+--- , base == 4.7.0.1++ , array == 0.5.*+ , random == 1.1++ -- mtl for State so can assign unique IDs to Pattern nodes,+ -- but this could be done without the State monad (I read...).+-- , mtl == 2.1.3.1+ , mtl == 2.1.*++-- We don't really depend on the cpphs /library/, but installing+-- the library also installs the cpphs executable, so in case+-- build-tools doesn't nab it, this ought to!+ if flag(USE_CPPHS)+ build-depends:+ cpphs >= 1.14++ if ! flag(HASKELL98_FRAGMENT)+ build-depends:+ syb < 0.5++ -- deepseq not used for any legitimate reason, unless USE_WW_DEEPSEQ;+ -- but it's used in some debugging and testing code (although probably+ -- shouldn't be), so the dep stays for now:+ build-depends:+ deepseq == 1.3.* || == 1.4.*++ if flag(USE_WW_DEEPSEQ)+ build-depends:+ deepseq == 1.3.* || == 1.4.*+ if ! flag(HASKELL98_FRAGMENT)+ build-depends:+ deepseq-generics == 0.1.*+ cpp-options: -DUSE_WW_DEEPSEQ=1+ else+ cpp-options: -DUSE_WW_DEEPSEQ=0++ if flag(HASKELL98_FRAGMENT)+ cpp-options: -DOVERLOADED_STRINGS=0+ else+ if flag(OVERLOADED_STRINGS)+ cpp-options: -DOVERLOADED_STRINGS=1+ else+ cpp-options: -DOVERLOADED_STRINGS=0++ if flag(USE_CURLY_BRACE_INSTEAD_OF_PAREN_FOR_SUBPATTERNS)+ cpp-options: -DUSE_CURLY_BRACE_INSTEAD_OF_PAREN_FOR_SUBPATTERNS=1+ else+ cpp-options: -DUSE_CURLY_BRACE_INSTEAD_OF_PAREN_FOR_SUBPATTERNS=0++ if flag(ABBREV_WN_AND_TN_CONCRETE_SYNTAX_TO_NUMBER_ALONE__SAFE_ONLY_TO_DEPTH_19)+ cpp-options: -DABBREV_WN_AND_TN_CONCRETE_SYNTAX_TO_NUMBER_ALONE__SAFE_ONLY_TO_DEPTH_19=1+ else+ cpp-options: -DABBREV_WN_AND_TN_CONCRETE_SYNTAX_TO_NUMBER_ALONE__SAFE_ONLY_TO_DEPTH_19=0++ if flag(ABBREV_WN_AND_TN_CONCRETE_SYNTAX_TO_SINGLE_DIGIT__CAN_ONLY_EXPRESS_DOWN_TO_DEPTH_9)+ cpp-options: -DABBREV_WN_AND_TN_CONCRETE_SYNTAX_TO_SINGLE_DIGIT__CAN_ONLY_EXPRESS_DOWN_TO_DEPTH_9=1+ else+ cpp-options: -DABBREV_WN_AND_TN_CONCRETE_SYNTAX_TO_SINGLE_DIGIT__CAN_ONLY_EXPRESS_DOWN_TO_DEPTH_9=0++ if flag(WARN_PATTERN_MATCH_FAILURE)+ cpp-options: -DWARN_PATTERN_MATCH_FAILURE=1+ else+ cpp-options: -DWARN_PATTERN_MATCH_FAILURE=0++ if ! flag(HASKELL98_FRAGMENT)+ if flag(USE_SOP)+ build-depends:+ generics-sop == 0.1.*+ cpp-options: -DUSE_SOP=1+ else+ cpp-options: -DUSE_SOP=0+ else+ cpp-options: -DUSE_SOP=0++ if flag(HASKELL98_FRAGMENT)+ cpp-options: -DHASKELL98_FRAGMENT=1+ else+ cpp-options: -DHASKELL98_FRAGMENT=0++--if flag(DEPTH_USE_INT64)+-- cpp-options: -DDEPTH_USE_INT64=1+--else+-- cpp-options: -DDEPTH_USE_INT64=0++ if flag(NFDATA_INSTANCE_PATTERN)+ cpp-options: -DNFDATA_INSTANCE_PATTERN=1+ else+ cpp-options: -DNFDATA_INSTANCE_PATTERN=0++ if ! flag(HASKELL98_FRAGMENT)+ if flag(USE_PAR_SEQABLE)+ build-depends:+ parallel == 3.2.*+ cpp-options: -DUSE_PAR_SEQABLE=1+ else+ cpp-options: -DUSE_PAR_SEQABLE=0+ else+ cpp-options: -DUSE_PAR_SEQABLE=0++ if ! flag(HASKELL98_FRAGMENT)+ if flag(USE_PAR_PATNODE)+ build-depends:+ parallel == 3.2.*+ cpp-options: -DUSE_PAR_PATNODE=1+ else+ cpp-options: -DUSE_PAR_PATNODE=0+ else+ cpp-options: -DUSE_PAR_PATNODE=0++ if ! flag(HASKELL98_FRAGMENT)+ if flag(USE_PSEQ_PATNODE)+ build-depends:+ parallel == 3.2.*+ cpp-options: -DUSE_PSEQ_PATNODE=1+ else+ cpp-options: -DUSE_PSEQ_PATNODE=0+ else+ cpp-options: -DUSE_PSEQ_PATNODE=0++ if flag(USE_TRACE_PATNODE)+ cpp-options: -DUSE_TRACE_PATNODE=1+ else+ cpp-options: -DUSE_TRACE_PATNODE=0++ -- Not H98 because uses Control.Concurrent which is GHC-specific.+ -- (I'm not sure if Control.Exception is H98 or not, but it uses that too.)+ if ! flag(HASKELL98_FRAGMENT)+ if flag(USE_PING_PATNODE)+ cpp-options: -DUSE_PING_PATNODE=1+ else+ cpp-options: -DUSE_PING_PATNODE=0+ else+ cpp-options: -DUSE_PING_PATNODE=0++ if ! flag(HASKELL98_FRAGMENT)+ if flag(USE_DIE_PATNODE)+ cpp-options: -DUSE_DIE_PATNODE=1+ else+ cpp-options: -DUSE_DIE_PATNODE=0+ else+ cpp-options: -DUSE_DIE_PATNODE=0+ + if flag(USE_TIMING_PATNODE)+ cpp-options: -DUSE_TIMING_PATNODE=1+ else+ cpp-options: -DUSE_TIMING_PATNODE=0++ if flag(HASKELL98_FRAGMENT)+ cpp-options: -DJUST_ALIAS_GSEQABLE=0+ cpp-options: -DJUST_ALIAS_GNFDATAN=0+ cpp-options: -DJUST_ALIAS_GNFDATAP=0+ cpp-options: -DPROVIDE_DATA_FAMILY=0+ else+ if flag(PROVIDE_DATA_FAMILY)+ cpp-options: -DPROVIDE_DATA_FAMILY=1+ else+ cpp-options: -DPROVIDE_DATA_FAMILY=0+ if flag(USE_SOP)+ if flag(JUST_ALIAS_GSEQABLE)+ cpp-options: -DJUST_ALIAS_GSEQABLE=1+ else+ cpp-options: -DJUST_ALIAS_GSEQABLE=0+ if flag(JUST_ALIAS_GNFDATAN)+ cpp-options: -DJUST_ALIAS_GNFDATAN=1+ else+ cpp-options: -DJUST_ALIAS_GNFDATAN=0+ if flag(JUST_ALIAS_GNFDATAP)+ cpp-options: -DJUST_ALIAS_GNFDATAP=1+ else+ cpp-options: -DJUST_ALIAS_GNFDATAP=0+ else+ cpp-options: -DJUST_ALIAS_GSEQABLE=0+ cpp-options: -DJUST_ALIAS_GNFDATAN=0+ cpp-options: -DJUST_ALIAS_GNFDATAP=0++--ghc-options: -O0+--ghc-options: -O2++}++-------------------------------------------------------------------------------++test-suite deepseq-bounded-tests {++-- I feel like declaring this is only asking for more trouble;+-- cpphs installs because it's mentioned as a dependency, and+-- that does install both the library and the executable.+---------+-- build-tools: cpphs +-- -- (This seems /not/ to work, since, when USE_CPPHS is default:false,+-- -- cpphs is still mentioned in the hackage deps.)+-- --if flag(USE_CPPHS)+-- -- build-tools: cpphs++ if flag(HASKELL98_FRAGMENT)+ default-language: Haskell98+ else+ default-language: Haskell2010++ type: exitcode-stdio-1.0++ hs-source-dirs: tests++ main-is: Suite.hs++ other-modules: Tests, Foo+ if flag(HASKELL98_FRAGMENT)+ other-modules: Blah98+ else+ other-modules: Blah, Bottom, FooG++ default-extensions: CPP++ if ! flag(HASKELL98_FRAGMENT)+ if flag(OVERLOADED_STRINGS)+ default-extensions: OverloadedStrings++ ghc-options: -optP-Wundef -fno-warn-overlapping-patterns++--ghc-options: -Wall -fenable-rewrite-rules -O -ddump-rules -ddump-simpl-stats -ddump-rule-firings+--ghc-options: -Wall -fenable-rewrite-rules -O+--ghc-options: -fenable-rewrite-rules -O+--ghc-options: -fenable-rewrite-rules -O2++ if flag(USE_CPPHS)+ -- the only reliable way to get equiv. of -pgmP"env PATH=$PATH:blah cpphs"+ ghc-options: -pgmP./cpphs.sh+--else+-- ghc-options: -cpp++ build-depends:+ base == 4.*++ , deepseq-bounded++ , HUnit == 1.2.*+ , random == 1.1++ , template-haskell >= 2.8 && < 3++---- We don't really depend on the cpphs /library/, but installing+---- the library also installs the cpphs executable, so in case+---- build-tools doesn't nab it, this ought to!+ if flag(USE_CPPHS)+ build-depends:+ cpphs >= 1.14++ if ! flag(HASKELL98_FRAGMENT)+ build-depends:+ ghc-prim+-- ghc-prim <= 0.3.1.0++ if ! flag(HASKELL98_FRAGMENT)+ build-depends:+ syb < 0.5++ -- deepseq not used for any legitimate reason, unless USE_WW_DEEPSEQ;+ -- but it's used in some debugging and testing code (although probably+ -- shouldn't be), so the dep stays for now:+ build-depends:+ deepseq == 1.3.* || == 1.4.*++ if flag(USE_WW_DEEPSEQ)+ build-depends:+ deepseq == 1.3.* || == 1.4.*+ if ! flag(HASKELL98_FRAGMENT)+ build-depends:+ deepseq-generics == 0.1.*+ cpp-options: -DUSE_WW_DEEPSEQ=1+ else+ cpp-options: -DUSE_WW_DEEPSEQ=0++ if ! flag(HASKELL98_FRAGMENT)+ if flag(USE_SOP)+ build-depends:+ generics-sop == 0.1.*+ cpp-options: -DUSE_SOP=1+ else+ cpp-options: -DUSE_SOP=0+ else+ cpp-options: -DUSE_SOP=0++ if flag(HASKELL98_FRAGMENT)+ cpp-options: -DHASKELL98_FRAGMENT=1+ else+ cpp-options: -DHASKELL98_FRAGMENT=0++ if flag(WARN_PATTERN_MATCH_FAILURE)+ cpp-options: -DWARN_PATTERN_MATCH_FAILURE=1+ else+ cpp-options: -DWARN_PATTERN_MATCH_FAILURE=0++ if flag(HASKELL98_FRAGMENT)+ cpp-options: -DOVERLOADED_STRINGS=0+ else+ if flag(OVERLOADED_STRINGS)+ cpp-options: -DOVERLOADED_STRINGS=1+ else+ cpp-options: -DOVERLOADED_STRINGS=0++ if flag(USE_CURLY_BRACE_INSTEAD_OF_PAREN_FOR_SUBPATTERNS)+ cpp-options: -DUSE_CURLY_BRACE_INSTEAD_OF_PAREN_FOR_SUBPATTERNS=1+ else+ cpp-options: -DUSE_CURLY_BRACE_INSTEAD_OF_PAREN_FOR_SUBPATTERNS=0++ -- (Probably not actually referenced in the tests.)+ if flag(ABBREV_WN_AND_TN_CONCRETE_SYNTAX_TO_NUMBER_ALONE__SAFE_ONLY_TO_DEPTH_19)+ cpp-options: -DABBREV_WN_AND_TN_CONCRETE_SYNTAX_TO_NUMBER_ALONE__SAFE_ONLY_TO_DEPTH_19=1+ else+ cpp-options: -DABBREV_WN_AND_TN_CONCRETE_SYNTAX_TO_NUMBER_ALONE__SAFE_ONLY_TO_DEPTH_19=0++ -- (Probably not actually referenced in the tests.)+ if flag(ABBREV_WN_AND_TN_CONCRETE_SYNTAX_TO_SINGLE_DIGIT__CAN_ONLY_EXPRESS_DOWN_TO_DEPTH_9)+ cpp-options: -DABBREV_WN_AND_TN_CONCRETE_SYNTAX_TO_SINGLE_DIGIT__CAN_ONLY_EXPRESS_DOWN_TO_DEPTH_9=1+ else+ cpp-options: -DABBREV_WN_AND_TN_CONCRETE_SYNTAX_TO_SINGLE_DIGIT__CAN_ONLY_EXPRESS_DOWN_TO_DEPTH_9=0++--if flag(DEPTH_USE_INT64)+-- cpp-options: -DDEPTH_USE_INT64=1+--else+-- cpp-options: -DDEPTH_USE_INT64=0++ if ! flag(HASKELL98_FRAGMENT)+ if flag(USE_PAR_SEQABLE)+ build-depends:+ parallel == 3.2.*+ -- I'm not 100% sure where this has to go+ ghc-options: -threaded+ cpp-options: -DUSE_PAR_SEQABLE=1+ else+ cpp-options: -DUSE_PAR_SEQABLE=0+ else+ cpp-options: -DUSE_PAR_SEQABLE=0++ if ! flag(HASKELL98_FRAGMENT)+ if flag(USE_PAR_PATNODE)+ build-depends:+ parallel == 3.2.*+ -- I'm not 100% sure where this has to go+ ghc-options: -threaded+ cpp-options: -DUSE_PAR_PATNODE=1+ else+ cpp-options: -DUSE_PAR_PATNODE=0+ else+ cpp-options: -DUSE_PAR_PATNODE=0++ if ! flag(HASKELL98_FRAGMENT)+ if flag(USE_PSEQ_PATNODE)+ build-depends:+ parallel == 3.2.*+ cpp-options: -DUSE_PSEQ_PATNODE=1+ else+ cpp-options: -DUSE_PSEQ_PATNODE=0+ else+ cpp-options: -DUSE_PSEQ_PATNODE=0++ if flag(USE_TRACE_PATNODE)+ cpp-options: -DUSE_TRACE_PATNODE=1+ else+ cpp-options: -DUSE_TRACE_PATNODE=0++ -- Not H98 because uses Control.Concurrent which is GHC-specific.+ -- (I'm not sure if Control.Exception is H98 or not, but it uses that too.)+ if ! flag(HASKELL98_FRAGMENT)+ if flag(USE_PING_PATNODE)+ cpp-options: -DUSE_PING_PATNODE=1+ else+ cpp-options: -DUSE_PING_PATNODE=0+ else+ cpp-options: -DUSE_PING_PATNODE=0++ if ! flag(HASKELL98_FRAGMENT)+ if flag(USE_DIE_PATNODE)+ cpp-options: -DUSE_DIE_PATNODE=1+ else+ cpp-options: -DUSE_DIE_PATNODE=0+ else+ cpp-options: -DUSE_DIE_PATNODE=0++ if flag(USE_TIMING_PATNODE)+ cpp-options: -DUSE_TIMING_PATNODE=1+ else+ cpp-options: -DUSE_TIMING_PATNODE=0++ if flag(HASKELL98_FRAGMENT)+ cpp-options: -DJUST_ALIAS_GSEQABLE=0+ cpp-options: -DJUST_ALIAS_GNFDATAN=0+ cpp-options: -DJUST_ALIAS_GNFDATAP=0+-- cpp-options: -DPROVIDE_DATA_FAMILY=0+ else+-- if flag(PROVIDE_DATA_FAMILY)+-- cpp-options: -DPROVIDE_DATA_FAMILY=1+-- else+-- cpp-options: -DPROVIDE_DATA_FAMILY=0+ if flag(USE_SOP)+ if flag(JUST_ALIAS_GSEQABLE)+ cpp-options: -DJUST_ALIAS_GSEQABLE=1+ else+ cpp-options: -DJUST_ALIAS_GSEQABLE=0+ if flag(JUST_ALIAS_GNFDATAN)+ cpp-options: -DJUST_ALIAS_GNFDATAN=1+ else+ cpp-options: -DJUST_ALIAS_GNFDATAN=0+ if flag(JUST_ALIAS_GNFDATAP)+ cpp-options: -DJUST_ALIAS_GNFDATAP=1+ else+ cpp-options: -DJUST_ALIAS_GNFDATAP=0+ else+ cpp-options: -DJUST_ALIAS_GSEQABLE=0+ cpp-options: -DJUST_ALIAS_GNFDATAN=0+ cpp-options: -DJUST_ALIAS_GNFDATAP=0++}++-------------------------------------------------------------------------------+
+ tests/cabal-files/deka-tests.txt view
@@ -0,0 +1,135 @@+-- This Cabal file generated using the Cartel library.+-- Cartel is available at:+-- http://www.github.com/massysett/cartel+--+-- Script name used to generate: genCabal.hs+-- Generated on: 2014-07-16 09:29:20.116107 EDT+-- Cartel library version: 0.10.0.2+name: deka-tests+version: 0.6.0.2+cabal-version: >= 1.14+build-type: Simple+license: BSD3+license-file: LICENSE+copyright: Copyright 2014 Omari Norman+author: Omari Norman+maintainer: Omari Norman, omari@smileystation.com+stability: Experimental+homepage: https://github.com/massysett/deka+bug-reports: https://github.com/massysett/deka/issues+synopsis: Tests for deka, decimal floating point arithmetic+description:+ deka provides decimal floating point arithmetic. It is based on+ mpdecimal, the C library used to provide support for the Decimal+ module in Python 3.+ .+ You will need to install mpdecimal to use deka; otherwise your+ executables will not link. It is available at+ .+ <http://www.bytereef.org/mpdecimal/>+ .+ mpdecimal has also been packaged for some Linux distributions,+ such as Debian (libmpdec-dev - available in Jessie and later) and+ Arch (mpdecimal).+ .+ mpdecimal, in turn, implements the General Decimal Arithmetic+ Specification, which is available at+ .+ <http://speleotrove.com/decimal/>+ .+ For more on deka, please see the Github home page at+ .+ <https://github.com/massysett/deka>+ .+ This package contains only tests, so that other packages+ may also use the tests.+category: Math+tested-with: GHC == 7.4.1, GHC == 7.6.3, GHC == 7.8.3+extra-source-files:+ README.md+ , ChangeLog+ , current-versions.txt+ , minimum-versions.txt++source-repository head+ type: git+ location: https://github.com/massysett/deka.git++Library+ exposed-modules:+ Deka.Dec.Coarbitrary+ , Deka.Dec.Generators+ , Deka.Dec.Shrinkers+ , Deka.Native.Abstract.Coarbitrary+ , Deka.Native.Abstract.Generators+ , Deka.Native.Abstract.Shrinkers+ , Deka.Tests.Util+ hs-source-dirs:+ lib+ build-depends:+ base ((> 4.5.0.0 || == 4.5.0.0) && < 4.8)+ , bytestring ((> 0.9.2.1 || == 0.9.2.1) && < 0.11)+ , deka == 0.6.0.2+ , QuickCheck ((> 2.7.3 || == 2.7.3) && < 2.8)+ ghc-options:+ -Wall+ default-language: Haskell2010++Executable deka-dectest+ build-depends:+ base ((> 4.5.0.0 || == 4.5.0.0) && < 4.8)+ , bytestring ((> 0.9.2.1 || == 0.9.2.1) && < 0.11)+ , deka == 0.6.0.2+ , QuickCheck ((> 2.7.3 || == 2.7.3) && < 2.8)+ , transformers ((> 0.3.0.0 || == 0.3.0.0) && < 0.5)+ , parsec ((> 3.1.2 || == 3.1.2) && < 3.2)+ , containers ((> 0.4.2.1 || == 0.4.2.1) && < 0.6)+ , pipes ((> 4.1.1 || == 4.1.1) && < 4.2)+ hs-source-dirs:+ dectest+ other-modules:+ Arity+ , Conditions+ , Directives+ , NumTests+ , Operand+ , Parse+ , Parse.Tokenizer+ , Parse.Tokens+ , Result+ , Runner+ , Specials+ , TestHelpers+ , TestLog+ , Types+ , Util+ main-is: deka-dectest.hs+ default-language: Haskell2010+ ghc-options:+ -Wall++Test-Suite deka-native+ build-depends:+ base ((> 4.5.0.0 || == 4.5.0.0) && < 4.8)+ , bytestring ((> 0.9.2.1 || == 0.9.2.1) && < 0.11)+ , deka == 0.6.0.2+ , QuickCheck ((> 2.7.3 || == 2.7.3) && < 2.8)+ , quickpull ((> 0.2.0.0 || == 0.2.0.0) && < 0.3)+ type: exitcode-stdio-1.0+ main-is: deka-native.hs+ hs-source-dirs:+ native+ , lib+ other-modules:+ Deka.Dec.Coarbitrary+ , Deka.Dec.Generators+ , Deka.Dec.Shrinkers+ , Deka.Native.Abstract.Coarbitrary+ , Deka.Native.Abstract.Generators+ , Deka.Native.Abstract.Shrinkers+ , Deka.Tests.Util+ , Decrees+ , Properties+ default-language: Haskell2010+ ghc-options:+ -Wall
+ tests/cabal-files/example-out.txt view
@@ -0,0 +1,138 @@+-- vi: ft=cabal+name: example-package+version: 1.2.3.4+synopsis: A short synopsis for this package+description:+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam sagittis neque magna, eu+ accumsan velit convallis at. In at odio eu risus facilisis vehicula vel non elit.+ Vestibulum volutpat id tellus ac malesuada.+ .+ Fusce rutrum elit libero, ac malesuada nibh semper ut. Donec commodo viverra felis.+ Quisque tincidunt ultrices turpis. Vestibulum gravida, urna ac pharetra consectetur,+ nulla lacus sollicitudin diam, quis dignissim libero neque at nulla.+license: MIT+license-files: LICENSE1, "license with spaces"+copyright: (c) 2018 John Doe+author: John Doe+maintainer: johndoe@example.com+stability: experimental+tested-with: GHC >= 7.4 && < 8.4+category: Example+homepage: https://example.com/cabal+package-url: https://gituh.bcom/example/Cabal/downloads/1.cabal+bug-reports: https://github.com/example/cabal+build-type: Custom+extra-tmp-files: tmpfile1+ tmpfile2+extra-source-files: extra-file1+ extra-file2+extra-doc-files: docfile1+ docfile2+data-files: "file1 with spaces"+ data/*+data-dir: .+cabal-version: >= 1.8++custom-setup+ setup-depends: base >= 4.5 && < 4.11, Cabal == 1.25++source-repository head+ type: git+ location: https://github.com/pikajude/stylish-cabal.cabal+ subdir: tests+ tag: latest+ branch: master++source-repository this+ type: cvs+ location: anoncvs@cvs.foo.org:/cvs+ module: cvsmodule++flag neat-flag+ default: False+ manual: True+ description: This is a flag with a nice little description++library+ exposed: False+ exposed-modules: Example+ reexported-modules: base:Numeric as MyNumericModule+ signatures: ExampleSig+ other-languages: Haskell98+ other-modules: Example.Module1+ Example.Module2+ mixins: example-mixin2 (Mixin as Foo.Mixin2+ , Mixina as Foo.Mixina2+ , Mixinb as Foo.Mixinb2+ , Mixinc as Foo.Mixinc2+ )+ , example-mixin3 (Mixin as Bar.Mixin)+ requires hiding (Mixin4, Mixin5)+ , example-mixin4+ , short (Mixin as Foo.Mixin) requires (Bar as Foo.Bar)+ autogen-modules: Example.AutogenModule+ hs-source-dirs: src+ build-depends: base == 4.*+ , attoparsec+ , bar == 3.4.*+ , foo >= 1.2.3 && < 1.4+ , somelib >= 1.2.3.4 && < 1.3+ default-extensions: NoMonomorphismRestriction+ other-extensions: OverloadedStrings+ extra-libraries: iconv+ extra-ghci-libraries: webkit+ pkgconfig-depends: cairo >= 1.0, gtk+-2.0 >= 2.10+ frameworks: CoreAudio+ extra-framework-dirs: frameworks+ cpp-options: -DFOO=1+ cc-options: -compat+ ld-options: -static+ c-sources: csource.c+ extra-lib-dirs: lib, lib2+ includes: example.h+ install-includes: output.h+ include-dirs: include+ js-sources: jssource.js+ build-tool-depends: cpphs:cpphs >= 4.0, foo:bar == 1.2.*, hsc2hs:hsc2hs+ build-tools: unknown-build-tool+ ghc-options: -Wall+ ghc-prof-options: -fcaf-all+ ghc-shared-options: -fobject-code+ x-a-custom-field: "Some Custom Value"++ if impl(ghc >= 7.5) && (os(osx) || !arch(i386))+ other-extensions: PolyKinds++library example-internal+ exposed-modules: Example.Internal+ build-depends: base++foreign-library examplelib+ type: native-shared+ lib-version-info: 6:3:2+ lib-version-linux: 4.3.2+ other-modules: ExampleLib.SomeModule+ hs-source-dirs: src+ build-depends: base == 4.*+ default-language: Haskell2010+ c-sources: csrc/ExampleLib.c++ if os(windows)+ options: standalone+ mod-def-file: ExampleLib.def, ExampleLib2.def++executable example+ main-is: example.hs+ scope: private++test-suite testname+ type: exitcode-stdio-1.0+ main-is: test.hs++test-suite detailed+ type: detailed-0.9+ test-module: Example.Test++benchmark bench+ type: exitcode-stdio-1.0+ main-is: benchmark.hs
+ tests/cabal-files/example.txt view
@@ -0,0 +1,119 @@+name: example-package+version: 1.2.3.4+cabal-version: >=1.8+build-type: Custom+license: MIT+license-files: LICENSE1, "license with spaces"+copyright: (c) 2018 John Doe+author: John Doe+maintainer: johndoe@example.com+stability: experimental+homepage: https://example.com/cabal+bug-reports: https://github.com/example/cabal+package-url: https://gituh.bcom/example/Cabal/downloads/1.cabal+synopsis: A short synopsis for this package+description:+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam sagittis neque magna, eu accumsan velit convallis at. In at odio eu risus facilisis vehicula vel non elit. Vestibulum volutpat id tellus ac malesuada.+ .+ Fusce rutrum elit libero, ac malesuada nibh semper ut. Donec commodo viverra felis. Quisque tincidunt ultrices turpis. Vestibulum gravida, urna ac pharetra consectetur, nulla lacus sollicitudin diam, quis dignissim libero neque at nulla.+category: Example+tested-with: GHC >= 7.4 && < 8.4+data-files: "file1 with spaces", data/*+data-dir: .+extra-source-files: extra-file1, extra-file2+extra-doc-files: docfile1, docfile2+extra-tmp-files: tmpfile1, tmpfile2++custom-setup+ setup-depends: base >= 4.5 && < 4.11, Cabal >= 1.25 && <= 1.25++source-repository head+ type: git+ location: https://github.com/pikajude/stylish-cabal.cabal+ tag: latest+ branch: master+ subdir: tests++source-repository this+ type: cvs+ location: anoncvs@cvs.foo.org:/cvs+ module: cvsmodule++flag neat-flag {+ default: False+ manual: True+ description: This is a flag with a nice little description+}++library example-internal+ exposed-modules: Example.Internal+ build-depends: base++library+ exposed-modules: Example+ exposed: False+ reexported-modules: base:Numeric as MyNumericModule+ signatures: ExampleSig+ mixins: short (Mixin as Foo.Mixin) requires (Bar as Foo.Bar), example-mixin2 (Mixin as Foo.Mixin2, Mixina as Foo.Mixina2, Mixinb as Foo.Mixinb2, Mixinc as Foo.Mixinc2), example-mixin3 (Mixin as Bar.Mixin) requires hiding (Mixin4, Mixin5), example-mixin4+ build-depends: base == 4.*, attoparsec, foo >= 1.2.3 && < 1.4, somelib ^>= 1.2.3.4, bar ^>= 3.4+ other-modules: Example.Module1, Example.Module2+ autogen-modules: Example.AutogenModule+ other-languages: Haskell98+ hs-source-dirs: src+ default-extensions: NoMonomorphismRestriction+ other-extensions: OverloadedStrings+ build-tool-depends: cpphs:cpphs >= 4.0, foo:bar == 1.2.*+ ghc-options: -Wall+ ghc-prof-options: -fcaf-all+ ghc-shared-options: -fobject-code+ build-tools: hsc2hs, unknown-build-tool+ includes: example.h+ install-includes: output.h+ include-dirs: include+ c-sources: csource.c+ js-sources: jssource.js+ extra-libraries: iconv+ extra-ghci-libraries: webkit+ extra-lib-dirs: lib, lib2+ cc-options: -compat+ cpp-options: -DFOO=1+ ld-options: -static+ pkgconfig-depends: gtk+-2.0 >= 2.10, cairo >= 1.0+ frameworks: CoreAudio+ extra-framework-dirs: frameworks+ x-a-custom-field: "Some Custom Value"++ if impl(ghc >= 7.5) && (os(darwin) || !arch(i386))+ other-extensions: PolyKinds++executable example {+ main-is: example.hs+ scope: private+}++test-suite testname+ type: exitcode-stdio-1.0+ main-is: test.hs++test-suite detailed+ type: detailed-0.9+ test-module: Example.Test++benchmark bench+ type: exitcode-stdio-1.0+ main-is: benchmark.hs++foreign-library examplelib+ type: native-shared+ lib-version-info: 6:3:2+ lib-version-linux: 4.3.2++ if os(windows)+ options: standalone+ mod-def-file: ExampleLib.def, ExampleLib2.def++ other-modules: ExampleLib.SomeModule+ build-depends: base == 4.*+ hs-source-dirs: src+ c-sources: csrc/ExampleLib.c+ default-language: Haskell2010
+ tests/cabal-files/exposed-containers.txt view
@@ -0,0 +1,247 @@+name: exposed-containers+version: 0.5.5.1+x-revision: 1+license: BSD3+license-file: LICENSE+maintainer: vi@zalora.com+bug-reports: https://github.com/fmap/exposed-containers/issues+synopsis: A distribution of the 'containers' package, with all modules exposed.+category: Data Structures+description:+ The source package contains efficient general-purpose implementations of+ various basic immutable container types. The declared cost of each+ operation is either worst-case or amortized, but remains valid even if+ structures are shared.++ Here we redistribute it, but with hidden modules exposed.+build-type: Simple+cabal-version: >=1.8+extra-source-files:+ include/Typeable.h+ tests/Makefile+ tests/*.hs+ benchmarks/Makefile+ benchmarks/bench-cmp.pl+ benchmarks/bench-cmp.sh+ benchmarks/*.hs+ benchmarks/SetOperations/Makefile+ benchmarks/SetOperations/*.hs+ benchmarks/LookupGE/Makefile+ benchmarks/LookupGE/*.hs++source-repository head+ type: git+ location: http://github.com/fmap/exposed-containers.git++Library+ build-depends: base >= 4.2 && < 5, array, deepseq >= 1.2 && < 1.4+ if impl(ghc>=6.10)+ build-depends: ghc-prim++ ghc-options: -O2 -Wall++ exposed-modules:+ Data.IntMap+ Data.IntMap.Lazy+ Data.IntMap.Strict+ Data.IntSet+ Data.Map+ Data.Map.Lazy+ Data.Map.Strict+ Data.Set+ Data.BitUtil+ Data.IntMap.Base+ Data.IntSet.Base+ Data.Map.Base+ Data.Set.Base+ Data.StrictPair+ if !impl(nhc98)+ exposed-modules:+ Data.Graph+ Data.Sequence+ Data.Tree++ include-dirs: include++ if impl(ghc<7.0)+ extensions: MagicHash, DeriveDataTypeable, StandaloneDeriving, Rank2Types+ if impl(ghc >= 7.8)+ extensions: RoleAnnotations++-------------------+-- T E S T I N G --+-------------------++-- Every test-suite contains the build-depends and options of the library,+-- plus the testing stuff.++-- Because the test-suites cannot contain conditionals in GHC 7.0, the extensions+-- are switched on for every compiler to allow GHC < 7.0 to compile the tests+-- (because GHC < 7.0 cannot handle conditional LANGUAGE pragmas).+-- When testing with GHC < 7.0 is not needed, the extensions should be removed.++Test-suite map-lazy-properties+ hs-source-dirs: tests, .+ main-is: map-properties.hs+ type: exitcode-stdio-1.0+ cpp-options: -DTESTING++ build-depends: base >= 4.2 && < 5, array, deepseq >= 1.2 && < 1.4, ghc-prim+ ghc-options: -O2+ extensions: MagicHash, DeriveDataTypeable, StandaloneDeriving, Rank2Types++ build-depends:+ HUnit,+ QuickCheck,+ test-framework,+ test-framework-hunit,+ test-framework-quickcheck2++Test-suite map-strict-properties+ hs-source-dirs: tests, .+ main-is: map-properties.hs+ type: exitcode-stdio-1.0+ cpp-options: -DTESTING -DSTRICT++ build-depends: base >= 4.2 && < 5, array, deepseq >= 1.2 && < 1.4, ghc-prim+ ghc-options: -O2+ extensions: MagicHash, DeriveDataTypeable, StandaloneDeriving, Rank2Types++ build-depends:+ HUnit,+ QuickCheck,+ test-framework,+ test-framework-hunit,+ test-framework-quickcheck2++Test-suite set-properties+ hs-source-dirs: tests, .+ main-is: set-properties.hs+ type: exitcode-stdio-1.0+ cpp-options: -DTESTING++ build-depends: base >= 4.2 && < 5, array, deepseq >= 1.2 && < 1.4, ghc-prim+ ghc-options: -O2+ extensions: MagicHash, DeriveDataTypeable, StandaloneDeriving, Rank2Types++ build-depends:+ HUnit,+ QuickCheck,+ test-framework,+ test-framework-hunit,+ test-framework-quickcheck2++Test-suite intmap-lazy-properties+ hs-source-dirs: tests, .+ main-is: intmap-properties.hs+ type: exitcode-stdio-1.0+ cpp-options: -DTESTING++ build-depends: base >= 4.2 && < 5, array, deepseq >= 1.2 && < 1.4, ghc-prim+ ghc-options: -O2+ extensions: MagicHash, DeriveDataTypeable, StandaloneDeriving, Rank2Types++ build-depends:+ HUnit,+ QuickCheck,+ test-framework,+ test-framework-hunit,+ test-framework-quickcheck2++Test-suite intmap-strict-properties+ hs-source-dirs: tests, .+ main-is: intmap-properties.hs+ type: exitcode-stdio-1.0+ cpp-options: -DTESTING -DSTRICT++ build-depends: base >= 4.2 && < 5, array, deepseq >= 1.2 && < 1.4, ghc-prim+ ghc-options: -O2+ extensions: MagicHash, DeriveDataTypeable, StandaloneDeriving, Rank2Types++ build-depends:+ HUnit,+ QuickCheck,+ test-framework,+ test-framework-hunit,+ test-framework-quickcheck2++Test-suite intset-properties+ hs-source-dirs: tests, .+ main-is: intset-properties.hs+ type: exitcode-stdio-1.0+ cpp-options: -DTESTING++ build-depends: base >= 4.2 && < 5, array, deepseq >= 1.2 && < 1.4, ghc-prim+ ghc-options: -O2+ extensions: MagicHash, DeriveDataTypeable, StandaloneDeriving, Rank2Types++ build-depends:+ HUnit,+ QuickCheck,+ test-framework,+ test-framework-hunit,+ test-framework-quickcheck2++Test-suite deprecated-properties+ hs-source-dirs: tests, .+ main-is: deprecated-properties.hs+ type: exitcode-stdio-1.0+ cpp-options: -DTESTING++ build-depends: base >= 4.2 && < 5, array, deepseq >= 1.2 && < 1.4, ghc-prim+ ghc-options: -O2+ extensions: MagicHash, DeriveDataTypeable, StandaloneDeriving, Rank2Types++ build-depends:+ QuickCheck,+ test-framework,+ test-framework-quickcheck2++Test-suite seq-properties+ hs-source-dirs: tests, .+ main-is: seq-properties.hs+ type: exitcode-stdio-1.0+ cpp-options: -DTESTING++ build-depends: base >= 4.2 && < 5, array, deepseq >= 1.2 && < 1.4, ghc-prim+ ghc-options: -O2+ extensions: MagicHash, DeriveDataTypeable, StandaloneDeriving, Rank2Types++ build-depends:+ QuickCheck,+ test-framework,+ test-framework-quickcheck2++test-suite map-strictness-properties+ hs-source-dirs: tests, .+ main-is: MapStrictness.hs+ type: exitcode-stdio-1.0++ build-depends:+ array,+ base >= 4.2 && < 5,+ ChasingBottoms,+ deepseq >= 1.2 && < 1.4,+ QuickCheck >= 2.4.0.1,+ ghc-prim,+ test-framework >= 0.3.3,+ test-framework-quickcheck2 >= 0.2.9++ ghc-options: -Wall++test-suite intmap-strictness-properties+ hs-source-dirs: tests, .+ main-is: IntMapStrictness.hs+ type: exitcode-stdio-1.0++ build-depends:+ array,+ base >= 4.2 && < 5,+ ChasingBottoms,+ deepseq >= 1.2 && < 1.4,+ QuickCheck >= 2.4.0.1,+ ghc-prim,+ test-framework >= 0.3.3,+ test-framework-quickcheck2 >= 0.2.9++ ghc-options: -Wall
+ tests/cabal-files/helics.txt view
@@ -0,0 +1,76 @@+name: helics+version: 0.5.1+x-revision: 1+synopsis: New Relic® agent SDK wrapper for Haskell.+description: + New Relic® agent SDK wrapper for Haskell.+ .+ Please get New Relic Agent SDK(<https://docs.newrelic.com/docs/agents/agent-sdk/using-agent-sdk/getting-started-agent-sdk>) before you install this package.+ .+ Copy include\/lib dir of SDK to system include\/lib path, or specify extra include\/lib path when installing this package.+ .+ @+ cabal install helics --extra-lib-dirs=$SDK_LIB_DIR --extra-include-dir=$SDK_INCLUDE_DIR+ @+ .++license: MIT+license-file: LICENSE+author: HirotomoMoriwaki<philopon.dependence@gmail.com>+maintainer: HirotomoMoriwaki<philopon.dependence@gmail.com>+Homepage: https://github.com/philopon/helics+Bug-reports: https://github.com/philopon/helics/issues+copyright: (c) 2014-2015 Hirotomo Moriwaki+category: Network+stability: experimental+build-type: Custom+cabal-version: >=1.10+extra-source-files: src/Network/Helics.hs+ , src/Network/Helics/Sampler.hs+ , dummy/Network/Helics.hs+ , dummy/Network/Helics/Sampler.hs++flag example+ default: False++flag dummy+ description: compile dummy modules on !linux.+ default: True++library+ exposed-modules: Network.Helics+ Network.Helics.Sampler+ Network.Helics.Internal.Types+ ghc-options: -Wall -O2+ default-language: Haskell2010+ build-depends: base >=4.6 && <4.9+ , data-default-class >=0.0 && <0.1+ , bytestring >=0.10 && <0.11++ if flag(dummy) && !os(linux)+ hs-source-dirs: common, dummy+ else+ other-modules: Network.Helics.Foreign.Common+ Network.Helics.Foreign.Client+ Network.Helics.Foreign.Transaction+ Network.Helics.Foreign.System+ build-depends: time >=1.2 && <1.6+ , unix >=2.6 && <2.8+ , bytestring-show >=0.3 && <0.4+ hs-source-dirs: common, src+ build-tools: hsc2hs+ extra-libraries: newrelic-collector-client+ , newrelic-transaction+ , newrelic-common++executable helics-example+ main-is: example.hs+ if flag(example)+ build-depends: base+ , helics+ , bytestring+ buildable: True+ else+ buildable: False+ ghc-options: -Wall -O2 -threaded+ default-language: Haskell2010
+ tests/cabal-files/hpc-coveralls.txt view
@@ -0,0 +1,121 @@+-- vi: ft=cabal+name: hpc-coveralls+version: 1.0.10+synopsis: Coveralls.io support for Haskell.+description:+ This utility converts and sends Haskell projects hpc code coverage to+ <http://coveralls.io/ coverall.io>.+ .+ /Usage/+ .+ Below is the simplest example of .travis.yml configuration to use with Travis CI:+ .+ > language: haskell+ > ghc: 7.8+ > script:+ > - cabal configure --enable-tests --enable-library-coverage && cabal build && cabal test+ > after_script:+ > - cabal install hpc-coveralls+ > - hpc-coveralls [options] [test-suite-names]+ .+ Further information can be found in the <https://github.com/guillaume-nargeot/hpc-coveralls README>.++license: BSD3+license-file: LICENSE+author: Guillaume Nargeot+maintainer: Guillaume Nargeot <guillaume+hackage@nargeot.com>+copyright: (c) 2014-2017 Guillaume Nargeot+category: Control+build-type: Simple+stability: experimental+cabal-version: >= 1.8+tested-with: GHC == 7.6, GHC == 7.8, GHC == 7.10, GHC == 8.0, GHC == 8.2+homepage: https://github.com/guillaume-nargeot/hpc-coveralls+bug-reports: https://github.com/guillaume-nargeot/hpc-coveralls/issues++extra-source-files:+ README.md,+ CHANGELOG.md++source-repository head+ type: git+ location: https://github.com/guillaume-nargeot/hpc-coveralls.git++library+ hs-source-dirs: src+ exposed-modules:+ Trace.Hpc.Coveralls,+ Trace.Hpc.Coveralls.Lix,+ Trace.Hpc.Coveralls.Types,+ Trace.Hpc.Coveralls.Util+ other-modules:+ HpcCoverallsCmdLine,+ Paths_hpc_coveralls,+ Trace.Hpc.Coveralls.Cabal,+ Trace.Hpc.Coveralls.Config,+ Trace.Hpc.Coveralls.Curl,+ Trace.Hpc.Coveralls.GitInfo,+ Trace.Hpc.Coveralls.Paths+ build-depends:+ aeson >= 0.7.1 && <1.3,+ base >= 4 && < 5,+ bytestring >= 0.10 && <0.11,+ Cabal,+ containers >= 0.5 && <0.6,+ cmdargs >= 0.10 && <0.11,+ curl >= 1.3.8 && <1.4,+ directory >= 1.2 && <1.4,+ directory-tree >= 0.12 && <0.13,+ hpc >= 0.6 && <0.7,+ process >= 1.1.0.1 && <1.7,+ pureMD5 >= 2.1 && <2.2,+ retry >= 0.5 && <0.8,+ safe >= 0.3 && <0.4,+ split >= 0.2.2 && <0.3,+ transformers >= 0.4.1 && <0.6++executable hpc-coveralls+ hs-source-dirs: src+ main-is: HpcCoverallsMain.hs+ build-depends:+ aeson >= 0.7.1 && <1.3,+ base >= 4 && < 5,+ bytestring >= 0.10 && <0.11,+ Cabal,+ containers >= 0.5 && <0.6,+ cmdargs >= 0.10 && <0.11,+ curl >= 1.3.8 && <1.4,+ directory >= 1.2 && <1.4,+ directory-tree >= 0.12 && <0.13,+ hpc >= 0.6 && <0.7,+ process >= 1.1.0.1 && <1.7,+ pureMD5 >= 2.1 && <2.2,+ retry >= 0.5 && <0.8,+ safe >= 0.3 && <0.4,+ split >= 0.2.2 && <0.3,+ transformers >= 0.4.1 && <0.6+ ghc-options: -Wall -fwarn-tabs -fwarn-incomplete-uni-patterns++executable run-cabal-test+ hs-source-dirs: src+ main-is: RunCabalTestMain.hs+ build-depends:+ async >= 2.0,+ base >=4 && < 5,+ process,+ regex-posix,+ split+ ghc-options: -Wall -fwarn-tabs -fwarn-incomplete-uni-patterns++test-suite test-all+ hs-source-dirs: test+ type: exitcode-stdio-1.0+ main-is: TestAll.hs+ other-modules:+ TestHpcCoverallsLix,+ TestHpcCoverallsUtil+ build-depends:+ base,+ hpc-coveralls,+ HUnit+ ghc-options: -Wall
− tests/example.cabal
@@ -1,119 +0,0 @@-name: example-package-version: 1.2.3.4-cabal-version: >=1.8-build-type: Custom-license: MIT-license-files: LICENSE1, "license with spaces"-copyright: (c) 2018 John Doe-author: John Doe-maintainer: johndoe@example.com-stability: experimental-homepage: https://example.com/cabal-bug-reports: https://github.com/example/cabal-package-url: https://gituh.bcom/example/Cabal/downloads/1.cabal-synopsis: A short synopsis for this package-description:- Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam sagittis neque magna, eu accumsan velit convallis at. In at odio eu risus facilisis vehicula vel non elit. Vestibulum volutpat id tellus ac malesuada.- .- Fusce rutrum elit libero, ac malesuada nibh semper ut. Donec commodo viverra felis. Quisque tincidunt ultrices turpis. Vestibulum gravida, urna ac pharetra consectetur, nulla lacus sollicitudin diam, quis dignissim libero neque at nulla.-category: Example-tested-with: GHC >= 7.4 && < 8.4-data-files: "file1 with spaces", data/*-data-dir: .-extra-source-files: extra-file1, extra-file2-extra-doc-files: docfile1, docfile2-extra-tmp-files: tmpfile1, tmpfile2--custom-setup- setup-depends: base >= 4.5 && < 4.11, Cabal < 1.25--source-repository head- type: git- location: https://github.com/pikajude/stylish-cabal.cabal- tag: latest- branch: master- subdir: tests--source-repository this- type: cvs- location: anoncvs@cvs.foo.org:/cvs- module: cvsmodule--flag neat-flag {- default: False- manual: True- description: This is a flag with a nice little description-}--library example-internal- exposed-modules: Example.Internal- build-depends: base--library- exposed-modules: Example- exposed: False- reexported-modules: base:Numeric as MyNumericModule- signatures: ExampleSig- mixins: short (Mixin as Foo.Mixin) requires (Bar as Foo.Bar), example-mixin2 (Mixin as Foo.Mixin2, Mixina as Foo.Mixina2, Mixinb as Foo.Mixinb2, Mixinc as Foo.Mixinc2), example-mixin3 (Mixin as Bar.Mixin) requires hiding (Mixin4, Mixin5), example-mixin4- build-depends: base == 4.*, attoparsec, foo >= 1.2.3 && < 1.4, somelib ^>= 1.2.3.4, bar ^>= 3.4- other-modules: Example.Module1, Example.Module2- autogen-modules: Example.AutogenModule- other-languages: Haskell98- hs-source-dirs: src- default-extensions: NoMonomorphismRestriction- other-extensions: OverloadedStrings- build-tool-depends: cpphs:cpphs >= 4.0, foo:bar == 1.2.*- ghc-options: -Wall- ghc-prof-options: -fcaf-all- ghc-shared-options: -fobject-code- build-tools: hsc2hs, unknown-build-tool- includes: example.h- install-includes: output.h- include-dirs: include- c-sources: csource.c- js-sources: jssource.js- extra-libraries: iconv- extra-ghci-libraries: webkit- extra-lib-dirs: lib, lib2- cc-options: -compat- cpp-options: -DFOO=1- ld-options: -static- pkgconfig-depends: gtk+-2.0 >= 2.10, cairo >= 1.0- frameworks: CoreAudio- extra-framework-dirs: frameworks- x-a-custom-field: "Some Custom Value"-- if impl(ghc >= 7.5) && (os(darwin) || !arch(i386))- other-extensions: PolyKinds--executable example {- main-is: example.hs- scope: private-}--test-suite testname- type: exitcode-stdio-1.0- main-is: test.hs--test-suite detailed- type: detailed-0.9- test-module: Example.Test--benchmark bench- type: exitcode-stdio-1.0- main-is: benchmark.hs--foreign-library examplelib- type: native-shared- lib-version-info: 6:3:2- lib-version-linux: 4.3.2-- if os(windows)- options: standalone- mod-def-file: ExampleLib.def, ExampleLib2.def-- other-modules: ExampleLib.SomeModule- build-depends: base == 4.*- hs-source-dirs: src- c-sources: csrc/ExampleLib.c- default-language: Haskell2010
− tests/hlint.hs
@@ -1,6 +0,0 @@-import Control.Monad-import Language.Haskell.HLint-import System.Exit--main :: IO ()-main = hlint [".", "--cpp-define=TEST_HACKAGE=1"] >>= \ hints -> unless (null hints) exitFailure
tests/roundtrip/Hackage.hs view
@@ -1,4 +1,4 @@-{-# OPTIONS_GHC -fno-warn-unused-top-binds #-}+{-# OPTIONS_GHC -fno-warn-unused-binds #-} {-# Language OverloadedStrings #-} {-# Language DeriveGeneric #-} @@ -6,15 +6,19 @@ import Control.Monad import Data.Aeson import Data.ByteString.Lazy.UTF8 (toString)+import Data.Maybe+import qualified Data.Vector as V+import Expectations import GHC.Generics import Network.Wreq+import Prelude.Compat+import System.Environment+import System.IO import System.Random.MWC import System.Random.MWC.Distributions-import System.IO import Test.Hspec-import qualified Data.Vector as V import Test.Hspec.Core.Spec-import Utils+import Text.Read (readMaybe) newtype GetPackage = GetPackage { packageName :: String@@ -35,20 +39,27 @@ fmap (view responseBody) $ asJSON =<< getWith (defaults & header "Accept" .~ ["application/json"]) x +-- if we make a significant change to cabal file rendering, we want to+-- rerun on *all* of hackage, but the normal testsuite shouldn't do that+-- because it takes so long. set SKIP=0 to run on all packages testHackage = do+ skip <- runIO $ (readMaybe =<<) <$> lookupEnv "SKIP" packages <- runIO $ do hSetBuffering stdout NoBuffering putStrLn "getting package list..."- packages <- getJson "http://hackage.haskell.org/packages/"+ packages' <- getJson "http://hackage.haskell.org/packages/"+ let packages = filter (not . isProblematic) packages' putStrLn "done, running tests..."- gen <- createSystemRandom- uniformShuffle (V.fromList packages) gen+ if isNothing skip+ then createSystemRandom >>=+ fmap (V.take 100) . uniformShuffle (V.fromList packages)+ else pure $ V.fromList packages parallel $ describe "for 100 random Hackage packages" $- forM_ (V.take 100 packages) $ \(GetPackage pname) ->+ forM_ (drop (fromMaybe 0 skip) $ zip [0 ..] $ V.toList packages) $ \(n, GetPackage pname) -> mapSpecItem_ applySkips $- it (mkHeader pname) $ do+ it (mkHeader n pname) $ do revs <- getJson $ "http://hackage.haskell.org/package/" ++ pname ++ "/revisions/"@@ -59,5 +70,7 @@ pname ++ "/revision/" ++ show (number recent) ++ ".cabal" expectParse $ toString $ view responseBody cabalFile +isProblematic _ = False+ main :: IO ()-main = hspec $ describe "comprehensive check" testHackage+main = hspecColor $ describe "comprehensive check" testHackage
tests/roundtrip/Main.hs view
@@ -2,11 +2,25 @@ module Main where +import Expectations+import Prelude.Compat import Test.Hspec-import Utils main :: IO () main =- hspec $- describe "comprehensive check" $- it "retains every attribute" $ expectParse =<< readFile "tests/example.cabal"+ hspecColor $+ describe "comprehensive check" $ do+ it "retains every attribute" $+ expectParse =<< readFile "tests/cabal-files/example.txt"+ it "codeblocks" $ do+ expectParse =<< readFile "tests/cabal-files/hpc-coveralls.txt"+ expectParse =<< readFile "tests/cabal-files/helics.txt"+ it "non-ghc compilers" $+ expectParse =<< readFile "tests/cabal-files/exposed-containers.txt"+ it "baffling version constraints" $+ expectParse =<< readFile "tests/cabal-files/deka-tests.txt"+ it "markup" $ do+ expectParse =<< readFile "tests/cabal-files/BiGUL.txt"+ expectParse =<< readFile "tests/cabal-files/ChasingBottoms.txt"+ expectParse =<< readFile "tests/cabal-files/OrPatterns.txt"+ expectParse =<< readFile "tests/cabal-files/Cardinality.txt"
− tests/roundtrip/SortedDesc.hs
@@ -1,269 +0,0 @@-{-# OPTIONS_GHC -fno-warn-orphans #-}-{-# Language CPP #-}-{-# Language NamedFieldPuns #-}-{-# Language RecordWildCards #-}-{-# Language StandaloneDeriving #-}-{-# Language TypeFamilies #-}--module SortedDesc- ( from- , SGenericPackageDescription- ) where--import Data.Set (Set)-import qualified Data.Set as S-import Distribution.Compiler-import Distribution.License-import Distribution.ModuleName-import Distribution.Package-import Distribution.PackageDescription-import Distribution.Types.LegacyExeDependency-import Distribution.Types.Mixin-import Distribution.Types.PkgconfigDependency-import Distribution.Types.UnqualComponentName-import Distribution.Version-import Language.Haskell.Extension-#if !MIN_VERSION_base(4,8,0)-import Data.Functor ((<$>))-#endif--data SGenericPackageDescription = SGenericPackageDescription- { packageDescription :: SPackageDescription- , genPackageFlags :: Set Flag- -- , sCondLibrary :: Maybe (SCondTree SConfVar (Set SDependency) SLibrary)- -- , SCondExecutables :: Set (String, SCondTree SConfVar (Set SDependency) SExecutable)- } deriving (Eq, Show)--data SPackageDescription = SPackageDescription- { package :: PackageIdentifier- , license :: License- , licenseFiles :: Set FilePath- , copyright :: String- , maintainer :: String- , author :: String- , stability :: String- , testedWith :: Set (CompilerFlavor, VersionRange)- , homepage :: String- , pkgUrl :: String- , bugReports :: String- , sourceRepos :: Set SourceRepo- , synopsis :: String- , description :: String- , category :: String- , customFieldsPD :: Set (String, String)- , specVersionRaw :: Either Version VersionRange- , buildType :: Maybe BuildType- , setupBuildInfo :: Maybe SSetupBuildInfo- , library :: Maybe SLibrary- , executables :: Set SExecutable- , testSuites :: Set STestSuite- , benchmarks :: Set SBenchmark- , dataFiles :: Set FilePath- , dataDir :: FilePath- , extraSrcFiles :: Set FilePath- , extraTmpFiles :: Set FilePath- , extraDocFiles :: Set FilePath- } deriving (Show, Eq)--data SLibrary = SLibrary- { exposedModules :: Set ModuleName- , reexportedModules :: Set ModuleReexport- , signatures :: Set ModuleName- , libExposed :: Bool- , libBuildInfo :: SBuildInfo- } deriving (Show, Eq)--data SExecutable = SExecutable- { exeName :: UnqualComponentName- , modulePath :: FilePath- , buildInfo :: SBuildInfo- } deriving (Show, Eq, Ord)--data STestSuite = STestSuite- { testName :: UnqualComponentName- , testInterface :: TestSuiteInterface- , testBuildInfo :: SBuildInfo- } deriving (Show, Eq, Ord)--data SBenchmark = SBenchmark- { benchmarkName :: UnqualComponentName- , benchmarkInterface :: BenchmarkInterface- , benchmarkBuildInfo :: SBuildInfo- } deriving (Show, Eq, Ord)--data SSetupBuildInfo = SSetupBuildInfo- { setupDepends :: Set Dependency- , defaultSetupDepends :: Bool- } deriving (Show, Eq)--data SBuildInfo = SBuildInfo- { buildable :: Bool- , buildTools :: Set LegacyExeDependency- , cppOptions :: Set String- , ccOptions :: Set String- , ldOptions :: Set String- , pkgconfigDepends :: Set PkgconfigDependency- , frameworks :: Set String- , extraFrameworkDirs :: Set String- , cSources :: Set FilePath- , jsSources :: Set FilePath- , hsSourceDirs :: Set FilePath- , otherModules :: Set ModuleName- , defaultLanguage :: Maybe Language- , otherLanguages :: Set Language- , defaultExtensions :: Set Extension- , otherExtensions :: Set Extension- , oldExtensions :: Set Extension- , extraLibs :: Set String- , extraGHCiLibs :: Set String- , extraLibDirs :: Set String- , includeDirs :: Set FilePath- , includes :: Set FilePath- , installIncludes :: Set FilePath- , options :: Set (CompilerFlavor, Set String)- , profOptions :: Set (CompilerFlavor, Set String)- , sharedOptions :: Set (CompilerFlavor, Set String)- , customFieldsBI :: Set (String, String)- , targetBuildDepends :: Set Dependency- , mixins :: Set Mixin- } deriving (Show, Eq, Ord)--class Convert a where- type From a- from :: From a -> a--instance Convert SGenericPackageDescription where- type From SGenericPackageDescription = GenericPackageDescription- from GenericPackageDescription {..} =- SGenericPackageDescription- { packageDescription = from packageDescription- , genPackageFlags =- S.fromList $ map (\f -> f {flagDescription = ""}) genPackageFlags- }--instance Convert SPackageDescription where- type From SPackageDescription = PackageDescription- from PackageDescription {..} =- SPackageDescription- { package- , license- , licenseFiles = S.fromList licenseFiles- , copyright- , maintainer- , author- , stability- , testedWith = S.fromList testedWith- , homepage- , pkgUrl- , bugReports- , sourceRepos = S.fromList sourceRepos- , synopsis- , description = "" -- discard, matching formatting in tests is too much work- , category- , customFieldsPD = S.fromList customFieldsPD- , specVersionRaw = Right anyVersion -- discard, cabal replaces * with >= 0 || <= 0- , buildType- , setupBuildInfo = from <$> setupBuildInfo- , library = from <$> library- , executables = S.fromList $ map from executables- , testSuites = S.fromList $ map from testSuites- , benchmarks = S.fromList $ map from benchmarks- , dataFiles = S.fromList dataFiles- , dataDir- , extraSrcFiles = S.fromList extraSrcFiles- , extraTmpFiles = S.fromList extraTmpFiles- , extraDocFiles = S.fromList extraDocFiles- }--instance Convert SSetupBuildInfo where- type From SSetupBuildInfo = SetupBuildInfo- from SetupBuildInfo {..} =- SSetupBuildInfo {setupDepends = S.fromList setupDepends, defaultSetupDepends}--instance Convert SLibrary where- type From SLibrary = Library- from Library {..} =- SLibrary- { exposedModules = S.fromList exposedModules- , reexportedModules = S.fromList reexportedModules- , signatures = S.fromList signatures- , libExposed- , libBuildInfo = from libBuildInfo- }--instance Convert SExecutable where- type From SExecutable = Executable- from Executable {..} = SExecutable {exeName, modulePath, buildInfo = from buildInfo}--instance Convert STestSuite where- type From STestSuite = TestSuite- from TestSuite {..} =- STestSuite {testName, testInterface, testBuildInfo = from testBuildInfo}--instance Convert SBenchmark where- type From SBenchmark = Benchmark- from Benchmark {..} =- SBenchmark- { benchmarkName- , benchmarkInterface- , benchmarkBuildInfo = from benchmarkBuildInfo- }--instance Convert SBuildInfo where- type From SBuildInfo = BuildInfo- from BuildInfo {..} =- SBuildInfo- { buildable- , buildTools = S.fromList buildTools- , cppOptions = S.fromList cppOptions- , ccOptions = S.fromList ccOptions- , ldOptions = S.fromList ldOptions- , pkgconfigDepends = S.fromList pkgconfigDepends- , frameworks = S.fromList frameworks- , extraFrameworkDirs = S.fromList extraFrameworkDirs- , cSources = S.fromList cSources- , jsSources = S.fromList jsSources- , hsSourceDirs = S.fromList hsSourceDirs- , otherModules = S.fromList otherModules- , defaultLanguage- , otherLanguages = S.fromList otherLanguages- , defaultExtensions = S.fromList defaultExtensions- , otherExtensions = S.fromList otherExtensions- , oldExtensions = S.fromList oldExtensions- , extraLibs = S.fromList extraLibs- , extraGHCiLibs = S.fromList extraGHCiLibs- , extraLibDirs = S.fromList extraLibDirs- , includeDirs = S.fromList includeDirs- , includes = S.fromList includes- , installIncludes = S.fromList installIncludes- , options = S.fromList $ map (fmap S.fromList) options- , profOptions = S.fromList $ map (fmap S.fromList) profOptions- , sharedOptions = S.fromList $ map (fmap S.fromList) sharedOptions- , customFieldsBI = S.fromList customFieldsBI- , targetBuildDepends = S.fromList targetBuildDepends- , mixins = S.fromList mixins- }--deriving instance Ord Flag--deriving instance Ord VersionRange--deriving instance Ord SourceRepo--deriving instance Ord Dependency--deriving instance Ord Language--deriving instance Ord ModuleReexport--deriving instance Ord TestSuiteInterface--deriving instance Ord TestType--deriving instance Ord BenchmarkInterface--deriving instance Ord BenchmarkType--deriving instance Ord PkgconfigDependency--deriving instance Ord LegacyExeDependency
− tests/roundtrip/Utils.hs
@@ -1,59 +0,0 @@-{-# OPTIONS_GHC -fno-warn-orphans #-}-{-# Language CPP #-}-{-# Language StandaloneDeriving #-}--module Utils where--import Control.Monad-import Data.List-import Distribution.PackageDescription.Parse-import Distribution.ParseUtils (PWarning(..))-import SortedDesc-import StylishCabal-import Test.Hspec.Core.Spec-import Test.Hspec.Expectations.Pretty-#if !MIN_VERSION_base(4,8,0)-import Control.Applicative (pure)-import Data.Functor ((<$>))-#endif-deriving instance Eq a => Eq (ParseResult a)--expectParse cabalStr = do- let doc =- (`displayS` "") . render 80 . plain . pretty <$>- parseCabalFile cabalStr- case doc of- StylishCabal.Success rendered -> do- let original =- from <$> parse' cabalStr :: ParseResult SGenericPackageDescription- new = from <$> parse' rendered- case new of- ParseOk pws _ -> skipIfRedFlags pws- _ -> pure ()- shouldBe original new- Warn {} ->- expectationFailure- "SKIP Warnings generated from original file, cannot guarantee consistency of output"- StylishCabal.Error {} ->- expectationFailure "SKIP Original cabal file does not parse"- where- skipIfRedFlags [] = return ()- skipIfRedFlags pws =- when (any (\(PWarning p) -> "must specify at least" `isInfixOf` p) pws) $- expectationFailure- "SKIP Original specified cabal-version is too old for section syntax"- parse' = parseGenericPackageDescription--applySkips i =- i- { itemExample =- \a b c -> do- res <- itemExample i a b c- case res of- Right (Failure _ (Reason r))- | "SKIP " `isPrefixOf` r ->- pure $ Right $ Pending $ Just $ drop 5 r- x -> return x- }--mkHeader p = "parses " ++ p
tests/strictness/Instances.hs view
@@ -1,10 +1,17 @@+{-# OPTIONS_GHC -fno-warn-orphans #-}+{-# Language CPP #-} {-# Language DataKinds #-} {-# Language DeriveAnyClass #-} {-# Language TemplateHaskell #-} {-# Language TypeFamilies #-} {-# Language StandaloneDeriving #-} -#define PRIM(c) instance Shaped c where type Shape c = Prim c; project = projectPrim; embed = embedPrim; match = matchPrim; render = prettyPrim+#define PRIM(c) instance Shaped c where \+ type Shape c = Prim c; \+ project = projectPrim; \+ embed = embedPrim; \+ match = matchPrim; \+ render = prettyPrim #define DERIVE(c) deriveGeneric ''c; instance Shaped c #define DERIVEN(c) DERIVE(c); deriving instance NFData c@@ -54,7 +61,8 @@ import Distribution.Version import Generics.SOP.TH import Language.Haskell.Extension-import Test.StrictCheck.Instances+import Prelude.Compat+import Test.StrictCheck.Instances () import Test.StrictCheck.Instances.Tools import Test.StrictCheck.Shaped
tests/strictness/Main.hs view
@@ -1,25 +1,19 @@+{-# OPTIONS_GHC -fno-warn-missing-signatures #-} {-# Language FlexibleContexts #-} import Control.DeepSeq-import Data.Word-import Distribution.License import Distribution.PackageDescription import qualified Distribution.PackageDescription as C import Distribution.PackageDescription.Parse-import Distribution.Version-import qualified GHC.Generics as GHC-import Generics.SOP-import Generics.SOP.TH-import Instances+import Instances ()+import Prelude.Compat import Pretty import StylishCabal import Test.Hspec hiding (shouldBe) import Test.Hspec.Expectations.Pretty import Test.StrictCheck.Demands-import Test.StrictCheck.Instances-import Test.StrictCheck.Instances.Tools+import Test.StrictCheck.Instances () import Test.StrictCheck.Observe-import Test.StrictCheck.Shaped whnfContext = flip seq () @@ -40,7 +34,8 @@ main = hspec $ do ParseOk _ gpd <-- runIO $ parseGenericPackageDescription <$> readFile "tests/example.cabal"+ runIO $+ parseGenericPackageDescription <$> readFile "tests/cabal-files/example" describe "pretty" $ it "should fully evaluate the package description" $ do let expected = nf gpd
tests/strictness/Pretty.hs view
@@ -4,13 +4,16 @@ module Pretty where import Data.Bifunctor-import Generics.SOP (Associativity(..))+import Generics.SOP (Associativity(..), Fixity)+import Prelude.Compat import Test.StrictCheck.Observe import Test.StrictCheck.Shaped import Text.PrettyPrint.ANSI.Leijen +pprint :: Shaped a => Demand a -> String pprint = showThunk False "_" 10 +showThunk :: Shaped a => Bool -> Doc -> Fixity -> Demand a -> String showThunk a b c d = flip displayS "" $ renderPretty 1.0 90 $ go a b c (renderfold d) where go _ thunk _ (RWrap T) = thunk@@ -33,10 +36,10 @@ string (qualify' fName) <+> char '=' <+> go qualify thunk 11 x) recfields)- CustomD fixity list ->+ CustomD fixity ls -> withParens (prec > fixity) $ hcat $- flip fmap list $+ flip fmap ls $ extractEither . bimap (string . qualifyEither) (uncurry $ go qualify thunk) InfixD name assoc fixity l r ->
+ tests/utils/Expectations.hs view
@@ -0,0 +1,58 @@+{-# OPTIONS_GHC -fno-warn-orphans #-}+{-# Language StandaloneDeriving #-}++module Expectations where++import Control.Monad+import Data.List.Compat+import Distribution.PackageDescription.Parse+import Prelude.Compat+import SortedPackageDescription+import StylishCabal as S+import Test.Hspec+import Test.Hspec.Core.Runner+import Test.Hspec.Core.Spec+-- import Test.Hspec.Expectations.Pretty++deriving instance Eq a => Eq (ParseResult a)++hspecColor = hspecWith (defaultConfig {configColorMode = ColorAlways})++expectParse cabalStr = do+ -- massive width limit is because:+ --+ -- edge case: a line ending in " ." will be word-wrapped to the next+ -- line. unfortunately a "." on its own on a line means paragraph break+ -- to the haddock parser. this case breaks tests on some hackage+ -- packages, but is unlikely to be problematic in practice (because you+ -- should just remove the leading space)+ let proc = (`displayS` "") . render (maxBound `div` 10) . plain+ doc = proc . pretty <$> S.parsePackageDescription cabalStr+ case doc of+ S.Success rendered -> do+ let ParseOk _ (descrs, original) =+ sortGenericPackageDescription <$> parse' cabalStr+ ParseOk _ (descrs2, new) =+ sortGenericPackageDescription <$> parse' rendered+ shouldBe original new+ forM_ (zip descrs descrs2) (uncurry shouldBe)+ Warn {} ->+ expectationFailure+ "SKIP Warnings generated from original file, cannot guarantee consistency of output"+ S.Error {} -> expectationFailure "SKIP Original cabal file does not parse"+ where+ parse' = parseGenericPackageDescription++applySkips i =+ i+ { itemExample =+ \a b c -> do+ res <- itemExample i a b c+ case res of+ Right (Failure _ (Reason r))+ | "SKIP " `isPrefixOf` r ->+ pure $ Right $ Pending $ Just $ drop 5 r+ x -> return x+ }++mkHeader n p = "parses #" ++ show n ++ ": " ++ p
+ tests/utils/MultiSet.hs view
@@ -0,0 +1,10 @@+{-# Language NoMonomorphismRestriction #-}++module MultiSet where++import qualified Data.Map as M+import Prelude.Compat++newtype MultiSet a = MultiSet { unMultiSet :: M.Map a Int } deriving (Eq, Ord, Show)++fromList = MultiSet . foldr (\ v -> M.insertWith (+) v 1) M.empty
+ tests/utils/SortedPackageDescription.hs view
@@ -0,0 +1,318 @@+{-# OPTIONS_GHC+ -fno-warn-orphans -fno-warn-unused-binds -fno-warn-deprecations #-}+{-# Language UndecidableInstances #-}+{-# Language NamedFieldPuns #-}+{-# Language NoMonomorphismRestriction #-}+{-# Language FlexibleContexts #-}+{-# Language TemplateHaskell #-}+{-# Language RecordWildCards #-}+{-# Language StandaloneDeriving #-}+{-# Language TypeFamilies #-}++module SortedPackageDescription+ ( Sortable(..)+ , sortGenericPackageDescription+ , MkSortGenericPackageDescription(..)+ ) where++import Data.Char (isSpace)+import Data.List (sortBy)+import Data.List.Split+import Data.Ord (comparing)+import Data.Word+import Distribution.Compiler+import Distribution.License+import Distribution.ModuleName+import Distribution.PackageDescription+import Distribution.System+import Distribution.Types.CondTree+import Distribution.Types.Dependency+import Distribution.Types.ExeDependency+import Distribution.Types.ExecutableScope+import Distribution.Types.ForeignLib+import Distribution.Types.ForeignLibOption+import Distribution.Types.ForeignLibType+import Distribution.Types.IncludeRenaming+import Distribution.Types.LegacyExeDependency+import Distribution.Types.Mixin+import Distribution.Types.PackageId+import Distribution.Types.PackageName+import Distribution.Types.PkgconfigDependency+import Distribution.Types.PkgconfigName+import Distribution.Types.UnqualComponentName+import Distribution.Utils.ShortText+import Distribution.Version+import Documentation.Haddock.Parser+import Documentation.Haddock.Types+ ( DocH(..)+ , Example(..)+ , Header(..)+ , Hyperlink(..)+ , Picture(..)+ , _doc+ )+import Language.Haskell.Extension+import Lens.Micro+import Lens.Micro.TH+import Prelude.Compat+import SortedPackageDescription.TH++deriving instance (Ord a, Ord b) => Ord (DocH a b)++deriving instance Ord a => Ord (Header a)++deriving instance Ord Hyperlink++deriving instance Ord Picture++deriving instance Ord Example++makeLensesFor+ [ ("packageDescription", "packageDescriptionL")+ , ("genPackageFlags", "genPackageFlagsL")+ ]+ ''GenericPackageDescription++makeLensesFor+ [("description", "descriptionL"), ("synopsis", "synopsisL")]+ ''PackageDescription++sortGenericPackageDescription ::+ GenericPackageDescription+ -> ([DocH () String], MkSortable GenericPackageDescription)+sortGenericPackageDescription gpd = (descriptions, sortable desc)+ where+ (descriptions, desc) = extractDescs gpd+ flagDescriptionL = lens flagDescription (\f d -> f {flagDescription = d})+ extractDescs g =+ let (dsc, gpd1) = g & (packageDescriptionL . descriptionL) <<.~ ""+ (syn, gpd2) = gpd1 & (packageDescriptionL . synopsisL) <<.~ ""+ (fs, gpd3) =+ gpd2 &+ (genPackageFlagsL . traverse) (\x -> ([x], x {flagDescription = ""}))+ sortedFlags = sortBy (comparing flagName) fs+ in ( map (unNl . toRegular . _doc . parseParas) $+ dsc : syn : map flagDescription sortedFlags+ , gpd3)+ unNl :: DocH () String -> DocH () String+ unNl (DocString s) = DocString $ unwords $ wordsBy isSpace s+ unNl (DocEmphasis x) = DocEmphasis $ unNl x+ unNl (DocAppend a b) = DocAppend (unNl a) (unNl b)+ unNl (DocParagraph d) = DocParagraph $ unNl d+ unNl (DocBold d) = DocBold (unNl d)+ unNl (DocCodeBlock d) = DocCodeBlock $ unNl d+ unNl (DocDefList bs) = DocDefList $ map (\(x, y) -> (unNl x, unNl y)) bs+ unNl (DocUnorderedList b) = DocUnorderedList (map unNl b)+ unNl (DocMonospaced d) = DocMonospaced (unNl d)+ unNl (DocOrderedList ds) = DocOrderedList (map unNl ds)+ unNl DocEmpty = DocEmpty+ unNl d@DocHeader {} = d+ unNl d@DocMathDisplay {} = d+ unNl d@DocExamples {} = d+ unNl d@DocPic {} = d+ unNl (DocHyperlink (Hyperlink h l)) =+ DocHyperlink $+ Hyperlink+ h+ (map (\x ->+ if x == '\n'+ then ' '+ else x) <$>+ l)+ unNl d@DocIdentifier {} = d+ unNl d@DocModule {} = d+ unNl d@DocMathInline {} = d+ unNl d@DocAName {} = d+ unNl x = error $ show x++prim [''ModuleName, ''ShortText, ''Char, ''Word64, ''PackageName, ''Int, ''Bool]++deriveSortable+ [ ''BuildType+ , ''Language+ , ''Version+ , ''VersionRange+ , ''ModuleReexport+ , ''Dependency+ , ''SetupBuildInfo+ , ''UnqualComponentName+ , ''LegacyExeDependency+ , ''PkgconfigName+ , ''PkgconfigDependency+ , ''ExeDependency+ , ''KnownExtension+ , ''Extension+ , ''OS+ , ''Arch+ , ''FlagName+ , ''CompilerFlavor+ , ''ModuleRenaming+ , ''IncludeRenaming+ , ''Mixin+ , ''BuildInfo+ , ''Library+ , ''ExecutableScope+ , ''Executable+ , ''License+ , ''ConfVar+ , ''PackageIdentifier+ , ''RepoType+ , ''RepoKind+ , ''SourceRepo+ , ''PackageDescription+ , ''Flag+ , ''ForeignLib+ , ''ForeignLibType+ , ''ForeignLibOption+ , ''LibVersionInfo+ , ''TestSuite+ , ''TestSuiteInterface+ , ''TestType+ , ''Benchmark+ , ''BenchmarkInterface+ , ''BenchmarkType+ ]++deriving instance Ord SourceRepo++deriving instance (Ord a, Ord b, Ord c) => Ord (CondTree a b c)++deriving instance (Ord a, Ord b, Ord c) => Ord (CondBranch a b c)++deriving instance Ord a => Ord (Condition a)++deriving instance Ord Flag++deriving instance Ord Dependency++deriving instance Ord VersionRange++deriving instance Ord ConfVar++deriving instance Ord Library++deriving instance Ord ModuleReexport++deriving instance Ord BuildInfo++deriving instance Ord LegacyExeDependency++deriving instance Ord ExeDependency++deriving instance Ord PkgconfigDependency++deriving instance Ord Language++deriving instance Ord ForeignLib++deriving instance Ord ForeignLibType++deriving instance Ord ForeignLibOption++deriving instance Ord Executable++deriving instance Ord ExecutableScope++deriving instance Ord TestSuite++deriving instance Ord TestSuiteInterface++deriving instance Ord TestType++deriving instance Ord Benchmark++deriving instance Ord BenchmarkInterface++deriving instance Ord BenchmarkType++---------------------------------------------------------------------+-- everything below this line is copy/pasted from TH class generation+-- i am insufficiently intelligent to generate the correct instance heads+-- in TH, so i've done it manually+---------------------------------------------------------------------+data MkSortCondition c+ = MkSortVar (MkSortable c)+ | MkSortLit (MkSortable Bool)+ | MkSortCNot (MkSortable (Condition c))+ | MkSortCOr (MkSortable (Condition c))+ (MkSortable (Condition c))+ | MkSortCAnd (MkSortable (Condition c))+ (MkSortable (Condition c))++instance Sortable a => Sortable (Condition a) where+ type MkSortable (Condition a) = MkSortCondition a+ sortable (Var arg) = MkSortVar (sortable arg)+ sortable (Lit arg) = MkSortLit (sortable arg)+ sortable (CNot arg) = MkSortCNot (sortable arg)+ sortable (COr arg arg2) = MkSortCOr (sortable arg) (sortable arg2)+ sortable (CAnd arg arg2) = MkSortCAnd (sortable arg) (sortable arg2)++data MkSortCondTree v c a = MkSortCondNode+ { mkSortCondTreeData :: MkSortable a+ , mkSortCondTreeConstraints :: MkSortable c+ , mkSortCondTreeComponents :: MkSortable [CondBranch v c a]+ }++deriving instance+ (Show (MkSortable v), Show (MkSortable c), Show (MkSortable a)) =>+ Show (MkSortCondTree v c a)++deriving instance+ (Eq (MkSortable c), Eq (MkSortable v), Eq (MkSortable a)) =>+ Eq (MkSortCondTree v c a)++deriving instance+ (Ord (MkSortable a), Ord (MkSortable v), Sortable c,+ Ord (MkSortable c)) =>+ Ord (MkSortCondTree v c a)++deriving instance Show (MkSortable v) => Show (MkSortCondition v)++deriving instance Eq (MkSortable a) => Eq (MkSortCondition a)++deriving instance Ord (MkSortable a) => Ord (MkSortCondition a)++deriving instance+ (Show (MkSortable v), Show (MkSortable c), Show (MkSortable a)) =>+ Show (MkSortCondBranch v c a)++deriving instance+ (Eq (MkSortable b), Eq (MkSortable a), Eq (MkSortable c)) =>+ Eq (MkSortCondBranch a b c)++deriving instance+ (Ord (MkSortable a), Ord (MkSortable b), Ord (MkSortable c),+ Sortable b) =>+ Ord (MkSortCondBranch a b c)++instance ( Sortable a+ , Sortable b+ , Sortable c+ , Ord (MkSortable a)+ , Ord (MkSortable b)+ , Ord (MkSortable c)+ ) =>+ Sortable (CondTree a b c) where+ type MkSortable (CondTree a b c) = MkSortCondTree a b c+ sortable (CondNode arg arg2 arg3) =+ MkSortCondNode (sortable arg) (sortable arg2) (sortable arg3)++data MkSortCondBranch v c a = MkSortCondBranch+ { mkSortCondBranchCondition :: MkSortable (Condition v)+ , mkSortCondBranchIfTrue :: MkSortable (CondTree v c a)+ , mkSortCondBranchIfFalse :: MkSortable (Maybe (CondTree v c a))+ }++instance ( Sortable a+ , Sortable b+ , Sortable c+ , Ord (MkSortable a)+ , Ord (MkSortable b)+ , Ord (MkSortable c)+ ) =>+ Sortable (CondBranch a b c) where+ type MkSortable (CondBranch a b c) = MkSortCondBranch a b c+ sortable (CondBranch arg arg2 arg3) =+ MkSortCondBranch (sortable arg) (sortable arg2) (sortable arg3)++deriveSortable [''GenericPackageDescription]
+ tests/utils/SortedPackageDescription/TH.hs view
@@ -0,0 +1,168 @@+{-# Language CPP #-}+{-# Language NoMonomorphismRestriction #-}+{-# Language TemplateHaskell #-}+{-# Language UndecidableInstances #-}+{-# Language FlexibleContexts #-}+{-# Language FlexibleInstances #-}+{-# Language TypeSynonymInstances #-}+{-# Language DefaultSignatures #-}+{-# Language TypeFamilies #-}++#if !MIN_VERSION_base(4,6,0)+{-# Language ConstraintKinds #-}+#endif++module SortedPackageDescription.TH where++import Control.Monad.Compat+import Data.Char (toUpper)+import Language.Haskell.TH+import MultiSet+import Prelude.Compat++class Sortable a where+ type MkSortable a :: *+ sortable :: a -> MkSortable a++instance (Sortable a, Sortable b) => Sortable (Either a b) where+ type MkSortable (Either a b) = Either (MkSortable a) (MkSortable b)+ sortable (Left a) = Left (sortable a)+ sortable (Right a) = Right (sortable a)++instance (Sortable a, Sortable b) => Sortable (a, b) where+ type MkSortable (a, b) = (MkSortable a, MkSortable b)+ sortable (a, b) = (sortable a, sortable b)++instance Sortable a => Sortable (Maybe a) where+ type MkSortable (Maybe a) = Maybe (MkSortable a)+ sortable (Just x) = Just (sortable x)+ sortable Nothing = Nothing++instance (Ord (MkSortable a), Sortable a) => Sortable [a] where+ type MkSortable [a] = MultiSet (MkSortable a)+ sortable xs = fromList $ map sortable xs++appsT [] = error "appsT []"+appsT [x] = x+appsT (x:y:zs) = appsT (appT x y : zs)++prim :: [Name] -> DecsQ+prim ns =+ fmap concat $+ forM ns $ \n ->+ sequence+ [ instanceD+ (cxt [])+ [t|Sortable $(conT n)|]+#if MIN_VERSION_template_haskell(2,9,0)+ [ tySynInstD ''MkSortable (tySynEqn [conT n] (conT n))+#else+ [ tySynInstD ''MkSortable [conT n] (conT n)+#endif+ , funD 'sortable [clause [] (normalB [|id|]) []]+ ]+ ]++#if MIN_VERSION_template_haskell(2,11,0)+#define KIND_ARG _k+#else+#define KIND_ARG+#endif++#if MIN_VERSION_template_haskell(2,12,0)+commonDerivClause = [derivClause Nothing [[t|Show|], [t|Ord|], [t|Eq|]]]+#elif MIN_VERSION_template_haskell(2,11,0)+commonDerivClause = cxt [[t|Show|], [t|Ord|], [t|Eq|]]+#else+commonDerivClause = [''Show, ''Ord, ''Eq]+#endif++deriveSortable :: [Name] -> DecsQ+deriveSortable = deriveSortable_ ""++deriveSortable_ :: String -> [Name] -> DecsQ+deriveSortable_ prefix ns =+ fmap concat $+ forM ns $ \n -> do+ TyConI x <- reify n+ (dty, sortableD) <- mkSortableDataD prefix x+ let tyhead = conT n+ sequence+ [ pure sortableD+ , instanceD+ (cxt [])+ [t|Sortable $(tyhead)|]+#if MIN_VERSION_template_haskell(2,9,0)+ [ tySynInstD ''MkSortable (tySynEqn [tyhead] (conT dty))+#else+ [ tySynInstD ''MkSortable [tyhead] (conT dty)+#endif+ , funD 'sortable (mkSortableImpl prefix x)+ ]+ ]++mkSortableDataD prefix (DataD cx tyName [] KIND_ARG cons _) =+ (,) newname <$>+ dataD (pure cx) newname [] KIND_ARG (map (mkSortableCon prefix) cons) commonDerivClause+ where+ newname = sortedTyName prefix tyName+mkSortableDataD prefix (NewtypeD cx tyName [] KIND_ARG con _) =+ (,) newname <$>+ newtypeD (pure cx) newname [] KIND_ARG (mkSortableCon prefix con) commonDerivClause+ where+ newname = sortedTyName prefix tyName+mkSortableDataD _ x = error $ "Unhandled: mkSortableDataD " ++ show x++#if MIN_VERSION_template_haskell(2,11,0)+bangDef = bang noSourceUnpackedness noSourceStrictness+#else+bangDef = pure NotStrict+#endif++mkSortableCon prefix (RecC recName fields) =+ recC (sortedTyName prefix recName) (map mkSortedField fields)+ where+ mkSortedField (varname, _, varty) =+#if MIN_VERSION_template_haskell(2,11,0)+ varBangType+ (sortedValName varname)+ (bangType bangDef [t|MkSortable $(pure varty)|])+#else+ varStrictType+ (sortedValName varname)+ (strictType bangDef [t|MkSortable $(pure varty)|])+#endif+mkSortableCon prefix (NormalC nm tys) =+ normalC (sortedTyName prefix nm) (map mkSortedField tys)+ where+ mkSortedField (_, varty) =+#if MIN_VERSION_template_haskell(2,11,0)+ bangType bangDef [t|MkSortable $(pure varty)|]+#else+ strictType bangDef [t|MkSortable $(pure varty)|]+#endif+mkSortableCon _ x = error $ "Unhandled case in mkSortableCon: " ++ show x++sortedTyName pref = mkName . ("MkSort" ++) . (pref ++) . nameBase++sortedValName = mkName . ("mkSort" ++) . firstToUpper . nameBase+ where+ firstToUpper (x:xs) = toUpper x : xs+ firstToUpper [] = []++mkSortableImpl pref (DataD _ _ _ KIND_ARG cons _) = map (mkSortableImplClause pref) cons+mkSortableImpl pref (NewtypeD _ _ _ KIND_ARG con _) = [mkSortableImplClause pref con]+mkSortableImpl _ x = error $ "Unhandled: mkSortableImpl " ++ show x++mkSortableImplClause pref con = do+ let (n, vars) = extract con+ vs <- replicateM vars (newName "arg")+ clause+ [conP n (map varP vs)]+ (normalB (appsE (conE (sortedTyName pref n) : map (dosort . varE) vs)))+ []+ where+ dosort v = [|sortable $(v)|]+ extract (RecC n vs) = (n, length vs)+ extract (NormalC n vs) = (n, length vs)+ extract x = error $ "Unhandled case in extract: " ++ show x