From 787dfc916ab44515d2982f53ed5cbdef8dbae9a2 Mon Sep 17 00:00:00 2001 From: Oleg Grenrus Date: Sun, 10 Feb 2019 20:09:52 +0200 Subject: [PATCH] Format setup-depends and tested-with --- cabal-fmt.cabal | 1 + fixtures/simple-example.cabal | 51 +++++++++++++++++++++++++++++ fixtures/simple-example.format | 48 +++++++++++++++++++++++++++ src/CabalFmt.hs | 3 ++ src/CabalFmt/Fields/BuildDepends.hs | 27 ++++++++------- src/CabalFmt/Fields/TestedWith.hs | 33 +++++++++++++++++++ tests/Golden.hs | 1 + 7 files changed, 153 insertions(+), 11 deletions(-) create mode 100644 fixtures/simple-example.cabal create mode 100644 fixtures/simple-example.format create mode 100644 src/CabalFmt/Fields/TestedWith.hs diff --git a/cabal-fmt.cabal b/cabal-fmt.cabal index 068a02d..6b84303 100644 --- a/cabal-fmt.cabal +++ b/cabal-fmt.cabal @@ -39,6 +39,7 @@ library CabalFmt.Fields.BuildDepends CabalFmt.Fields.Extensions CabalFmt.Fields.Modules + CabalFmt.Fields.TestedWith CabalFmt.Monad CabalFmt.Options CabalFmt.Parser diff --git a/fixtures/simple-example.cabal b/fixtures/simple-example.cabal new file mode 100644 index 0000000..de86776 --- /dev/null +++ b/fixtures/simple-example.cabal @@ -0,0 +1,51 @@ +name: simple-example +version: 1 +synopsis: Simple example of cabal-doctest demonstrating a library + with doctests +description: A package skeleton, to demostrate the use of cabal-doctest +homepage: https://github.com/phadej/cabal-doctest +license: BSD3 +license-file: LICENSE +author: Oleg Grenrus +maintainer: Oleg Grenrus +copyright: (c) 2017 Oleg Grenrus +category: Example +build-type: Custom +cabal-version: 1.12 + +tested-with: + GHC==7.0.4, + GHC==7.2.2, + GHC==7.4.2, + GHC==7.6.3, + GHC==7.8.4, + GHC==7.10.3, + GHC==8.0.2, + GHC==8.2.2, + GHC==8.4.4, + GHC==8.6.3 + +custom-setup + setup-depends: + base, Cabal, cabal-doctest >=1.0.6 && <1.1 + +library + exposed-modules: Example + default-extensions: ScopedTypeVariables RankNTypes + build-depends: base >=4.3 && <4.13 + hs-source-dirs: src + default-language: Haskell2010 + +test-suite doctests + type: exitcode-stdio-1.0 + main-is: doctests.hs + build-depends: + base, + doctest >= 0.15 && <0.17, + QuickCheck ==2.12.*, + simple-example, + template-haskell + + ghc-options: -Wall -threaded + hs-source-dirs: tests + default-language: Haskell2010 diff --git a/fixtures/simple-example.format b/fixtures/simple-example.format new file mode 100644 index 0000000..0f89a8e --- /dev/null +++ b/fixtures/simple-example.format @@ -0,0 +1,48 @@ +name: simple-example +version: 1 +synopsis: + Simple example of cabal-doctest demonstrating a library + with doctests + +description: A package skeleton, to demostrate the use of cabal-doctest +homepage: https://github.com/phadej/cabal-doctest +license: BSD3 +license-file: LICENSE +author: Oleg Grenrus +maintainer: Oleg Grenrus +copyright: (c) 2017 Oleg Grenrus +category: Example +build-type: Custom +cabal-version: 1.12 +tested-with: + GHC ==8.6.3 || ==8.4.4 || ==8.2.2 || ==8.0.2 || ==7.10.3 || ==7.8.4 || ==7.6.3 || ==7.4.2 || ==7.2.2 || ==7.0.4 + +custom-setup + setup-depends: + base + , Cabal + , cabal-doctest >=1.0.6 && <1.1 + +library + exposed-modules: Example + default-extensions: + RankNTypes + ScopedTypeVariables + + build-depends: base >=4.3 && <4.13 + hs-source-dirs: src + default-language: Haskell2010 + +test-suite doctests + type: exitcode-stdio-1.0 + main-is: doctests.hs + build-depends: + base + , doctest >=0.15 && <0.17 + , QuickCheck >=2.12 && <2.13 + , simple-example + , template-haskell + + ghc-options: -Wall -threaded + hs-source-dirs: tests + default-language: Haskell2010 diff --git a/src/CabalFmt.hs b/src/CabalFmt.hs index e3b5147..119c3a1 100644 --- a/src/CabalFmt.hs +++ b/src/CabalFmt.hs @@ -31,6 +31,7 @@ import CabalFmt.Fields import CabalFmt.Fields.BuildDepends import CabalFmt.Fields.Extensions import CabalFmt.Fields.Modules +import CabalFmt.Fields.TestedWith import CabalFmt.Monad import CabalFmt.Options import CabalFmt.Parser @@ -83,10 +84,12 @@ knownField fn fls = do fieldDescrs :: C.CabalSpecVersion -> FieldDescrs () () fieldDescrs v = buildDependsF v + <> setupDependsF v <> defaultExtensionsF <> otherExtensionsF <> exposedModulesF <> otherModulesF + <> testedWithF <> coerceFieldDescrs C.packageDescriptionFieldGrammar <> coerceFieldDescrs C.buildInfoFieldGrammar diff --git a/src/CabalFmt/Fields/BuildDepends.hs b/src/CabalFmt/Fields/BuildDepends.hs index 039b0b9..fda3639 100644 --- a/src/CabalFmt/Fields/BuildDepends.hs +++ b/src/CabalFmt/Fields/BuildDepends.hs @@ -1,6 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} module CabalFmt.Fields.BuildDepends ( buildDependsF, + setupDependsF, ) where import Control.Arrow ((&&&)) @@ -22,22 +23,26 @@ import qualified Text.PrettyPrint as PP import CabalFmt.Fields +setupDependsF :: C.CabalSpecVersion -> FieldDescrs () () +setupDependsF v = singletonF "setup-depends" (pretty v) parse + buildDependsF :: C.CabalSpecVersion -> FieldDescrs () () -buildDependsF v = singletonF "build-depends" pretty parse where - parse :: C.CabalParsing m => m [C.Dependency] - parse = unpack' (C.alaList C.CommaVCat) <$> C.parsec - - pretty :: [C.Dependency] -> PP.Doc - pretty [] = PP.empty - pretty [dep] = - C.pretty (C.depPkgName dep) PP.<+> - prettyVR vr' +buildDependsF v = singletonF "build-depends" (pretty v) parse + +parse :: C.CabalParsing m => m [C.Dependency] +parse = unpack' (C.alaList C.CommaVCat) <$> C.parsec + +pretty :: C.CabalSpecVersion -> [C.Dependency] -> PP.Doc +pretty v deps = case deps of + [] -> PP.empty + [dep] -> C.pretty (C.depPkgName dep) PP.<+> prettyVR vr' where vr' = either (C.fromVersionIntervals . C.mkVersionIntervals) id $ norm (C.asVersionIntervals $ C.depVerRange dep) prettyVR vr | vr == C.anyVersion = PP.empty | otherwise = C.pretty vr - pretty deps = PP.vcat (zipWith pretty' (True : repeat False) deps') where + _ -> PP.vcat (zipWith pretty' (True : repeat False) deps') + where deps' = sortOn (map toLower . fst) $ map (C.unPackageName . C.depPkgName &&& C.asVersionIntervals . C.depVerRange) $ C.fromDepMap . C.toDepMap -- this combines duplicate packages @@ -94,7 +99,7 @@ buildDependsF v = singletonF "build-depends" pretty parse where prettyUpperBound :: C.Bound -> PP.Doc prettyUpperBound C.InclusiveBound = PP.text "<=" prettyUpperBound C.ExclusiveBound = PP.text "<" - + where empty :: [C.VersionInterval] -> Bool empty [] = True empty [(C.LowerBound l C.InclusiveBound, C.NoUpperBound)] = l == C.mkVersion [0] diff --git a/src/CabalFmt/Fields/TestedWith.hs b/src/CabalFmt/Fields/TestedWith.hs new file mode 100644 index 0000000..6e9f4ad --- /dev/null +++ b/src/CabalFmt/Fields/TestedWith.hs @@ -0,0 +1,33 @@ +{-# LANGUAGE OverloadedStrings #-} +module CabalFmt.Fields.TestedWith ( + testedWithF, + ) where + +import Distribution.Compat.Newtype + +import qualified Distribution.Parsec as C +import qualified Distribution.Compiler as C +import qualified Distribution.Parsec.Newtypes as C +import qualified Distribution.Pretty as C +import qualified Distribution.Types.VersionRange as C +import qualified Text.PrettyPrint as PP +import qualified Data.Map.Strict as Map + +import CabalFmt.Fields + +testedWithF :: FieldDescrs () () +testedWithF = singletonF "tested-with" pretty parse where + parse :: C.CabalParsing m => m [(C.CompilerFlavor, C.VersionRange)] + parse = unpack' (C.alaList' C.FSep C.TestedWith) <$> C.parsec + + pretty :: [(C.CompilerFlavor, C.VersionRange)] -> PP.Doc + pretty tw0 = PP.fsep $ PP.punctuate PP.comma + [ prettyC c PP.<+> C.pretty vr + | (c, vr) <- Map.toList tw1 + ] + where + tw1 :: Map.Map C.CompilerFlavor C.VersionRange + tw1 = Map.fromListWith C.unionVersionRanges tw0 + + prettyC C.GHC = PP.text "GHC" + prettyC c = C.pretty c diff --git a/tests/Golden.hs b/tests/Golden.hs index b5488fd..d60b647 100644 --- a/tests/Golden.hs +++ b/tests/Golden.hs @@ -16,6 +16,7 @@ main :: IO () main = defaultMain $ testGroup "tests" [ goldenTest' "cabal-fmt" , goldenTest' "Cabal" + , goldenTest' "simple-example" ] goldenTest' :: String -> TestTree