cabal2json (empty) → 0.0.0.0
raw patch · 5 files changed
+966/−0 lines, 5 filesdep +Cabaldep +aesondep +autodocodec
Dependencies added: Cabal, aeson, autodocodec, autodocodec-yaml, base, bytestring, cabal2json, hashable, pretty, pretty-show, sydtest, sydtest-aeson, text, unordered-containers, utf8-string
Files
- app/Main.hs +6/−0
- cabal2json.cabal +74/−0
- src/Cabal2JSON.hs +788/−0
- test/Cabal2JSONSpec.hs +97/−0
- test/Spec.hs +1/−0
+ app/Main.hs view
@@ -0,0 +1,6 @@+module Main where++import Cabal2JSON++main :: IO ()+main = cabal2JSON
+ cabal2json.cabal view
@@ -0,0 +1,74 @@+cabal-version: 1.12++-- This file has been generated from package.yaml by hpack version 0.34.7.+--+-- see: https://github.com/sol/hpack++name: cabal2json+version: 0.0.0.0+synopsis: Turn a .cabal file into a .json file+homepage: https://github.com/NorfairKing/cabal2json#readme+bug-reports: https://github.com/NorfairKing/cabal2json/issues+author: Tom Sydney Kerckhove+maintainer: syd@cs-syd.eu+copyright: Copyright (c) 2022 Tom Sydney Kerckhove+license: MIT+build-type: Simple++source-repository head+ type: git+ location: https://github.com/NorfairKing/cabal2json++library+ exposed-modules:+ Cabal2JSON+ other-modules:+ Paths_cabal2json+ hs-source-dirs:+ src+ build-depends:+ Cabal+ , aeson+ , autodocodec+ , base >=4.7 && <5+ , bytestring+ , hashable+ , pretty+ , pretty-show+ , text+ , unordered-containers+ default-language: Haskell2010++executable cabal2json+ main-is: Main.hs+ other-modules:+ Paths_cabal2json+ hs-source-dirs:+ app+ ghc-options: -threaded -rtsopts -with-rtsopts=-N+ build-depends:+ base >=4.7 && <5+ , cabal2json+ default-language: Haskell2010++test-suite cabal2json-test+ type: exitcode-stdio-1.0+ main-is: Spec.hs+ other-modules:+ Cabal2JSONSpec+ Paths_cabal2json+ hs-source-dirs:+ test+ ghc-options: -threaded -rtsopts -with-rtsopts=-N+ build-tool-depends:+ sydtest-discover:sydtest-discover+ build-depends:+ Cabal+ , autodocodec+ , autodocodec-yaml+ , base >=4.7 && <5+ , cabal2json+ , sydtest+ , sydtest-aeson+ , utf8-string+ default-language: Haskell2010
+ src/Cabal2JSON.hs view
@@ -0,0 +1,788 @@+{-# LANGUAGE DerivingVia #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE OverloadedLists #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE StandaloneDeriving #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}++module Cabal2JSON+ ( cabal2JSON,+ )+where++import Autodocodec+import Control.Arrow (first)+import Data.Aeson (FromJSON, ToJSON)+import qualified Data.ByteString.Char8 as SB8+import qualified Data.ByteString.Lazy as LB+import qualified Data.HashMap.Strict as HM+import Data.Hashable+import qualified Data.List.NonEmpty as NE+import qualified Data.Text as T+import Data.Text.Encoding+import Distribution.Compiler as Cabal+import Distribution.License as Cabal+import Distribution.ModuleName as Cabal+import Distribution.PackageDescription+import Distribution.PackageDescription.Parsec as Cabal+import Distribution.Parsec (eitherParsec)+import Distribution.Pretty as Pretty+import Distribution.SPDX (LicenseExpression (..), SimpleLicenseExpression (..))+import qualified Distribution.SPDX as SPDX+import Distribution.SPDX.License as SPDX+import Distribution.System+import Distribution.Types.CondTree as Cabal+import Distribution.Types.Dependency as Cabal+import Distribution.Types.ExeDependency as Cabal+import Distribution.Types.ExecutableScope as Cabal+import Distribution.Types.ForeignLib as Cabal+import Distribution.Types.ForeignLibOption as Cabal+import Distribution.Types.ForeignLibType as Cabal+import Distribution.Types.IncludeRenaming as Cabal+import Distribution.Types.LegacyExeDependency as Cabal+import Distribution.Types.LibraryVisibility as Cabal+import Distribution.Types.Mixin as Cabal+import Distribution.Types.PackageId as Cabal+import Distribution.Types.PackageName as Cabal+import Distribution.Types.PkgconfigDependency as Cabal+import Distribution.Types.PkgconfigName+import Distribution.Types.PkgconfigVersion+import Distribution.Types.PkgconfigVersionRange+import Distribution.Types.UnqualComponentName as Cabal+import Distribution.Types.Version as Cabal+import Distribution.Types.VersionRange as Cabal+import Distribution.Utils.ShortText as Cabal+import Distribution.Verbosity as Cabal+import Language.Haskell.Extension+import System.Environment++cabal2JSON :: IO ()+cabal2JSON = do+ args <- getArgs+ case args of+ [] -> error "Please provide path to cabal file as CLI argument"+ arg -> do+ genericPackageDescription <- Cabal.readGenericPackageDescription Cabal.deafening (head arg)+ SB8.putStrLn $ LB.toStrict $ encodeJSONViaCodec genericPackageDescription++instance HasCodec GenericPackageDescription where+ codec =+ object "GenericPackageDescription" $+ GenericPackageDescription+ <$> requiredField' "description" .= packageDescription+ <*> optionalFieldWithOmittedDefault' "package-flags" [] .= genPackageFlags+ <*> optionalField' "library" .= condLibrary+ <*> optionalFieldWithOmittedDefaultWith' "sublibraries" unqualComponentNameCodec [] .= condSubLibraries+ <*> optionalFieldWithOmittedDefaultWith' "foreign-libs" unqualComponentNameCodec [] .= condForeignLibs+ <*> optionalFieldWithOmittedDefaultWith' "executables" unqualComponentNameCodec [] .= condExecutables+ <*> optionalFieldWithOmittedDefaultWith' "test-suites" unqualComponentNameCodec [] .= condTestSuites+ <*> optionalFieldWithOmittedDefaultWith' "benchmarks" unqualComponentNameCodec [] .= condBenchmarks++deriving via (Autodocodec GenericPackageDescription) instance (FromJSON GenericPackageDescription)++deriving via (Autodocodec GenericPackageDescription) instance (ToJSON GenericPackageDescription)++unqualComponentNameCodec :: HasCodec b => JSONCodec [(UnqualComponentName, b)]+unqualComponentNameCodec = mapInListForCodec mkUnqualComponentName unUnqualComponentName++instance HasCodec UnqualComponentName where+ codec = dimapCodec mkUnqualComponentName unUnqualComponentName codec++mapInListForCodec ::+ HasCodec b =>+ (String -> a) ->+ (a -> String) ->+ JSONCodec [(a, b)]+mapInListForCodec fromText toText =+ dimapCodec+ (f . HM.toList)+ (HM.fromList . g)+ codec+ where+ f = map (first fromText)+ g = map (first toText)++instance Hashable UnqualComponentName where+ hashWithSalt s = hashWithSalt s . unUnqualComponentName++instance HasCodec VersionRange where+ codec = bimapCodec f g codec+ where+ f = \s -> case eitherParsec s of+ Left pe -> Left $ show pe+ Right a -> Right a+ g = prettyShow++instance HasCodec CompilerFlavor where+ codec =+ stringConstCodec+ [ (GHC, "GHC"),+ (GHCJS, "GHCJS"),+ (NHC, "NHC"),+ (YHC, "YHC"),+ (HBC, "HBC"),+ (Helium, "Helium"),+ (JHC, "JHC"),+ (LHC, "LHC"),+ (UHC, "UHC"),+ (Eta, "Eta")+ ]++instance HasCodec PackageDescription where+ codec =+ object "PackageDescription" $+ PackageDescription+ <$> requiredField' "spec-version" .= specVersionRaw+ <*> requiredField' "package" .= package+ <*> requiredField' "license" .= licenseRaw+ <*> requiredField' "license-files" .= licenseFiles+ <*> requiredField' "copyright" .= copyright+ <*> requiredField' "maintainer" .= maintainer+ <*> requiredField' "author" .= author+ <*> requiredField' "stability" .= stability+ <*> requiredField' "tested-with" .= testedWith+ <*> requiredField' "homepage" .= homepage+ <*> requiredField' "pkg-url" .= pkgUrl+ <*> requiredField' "bug-reports" .= bugReports+ <*> requiredField' "source-repos" .= sourceRepos+ <*> requiredField' "synopsis" .= synopsis+ <*> requiredField' "description" .= description+ <*> requiredField' "category" .= category+ <*> requiredField' "custom-fields" .= customFieldsPD+ <*> requiredField' "build-type-raw" .= buildTypeRaw+ <*> requiredField' "custom-setup" .= setupBuildInfo+ <*> requiredField' "library" .= library+ <*> requiredField' "sublibraries" .= subLibraries+ <*> requiredField' "executables" .= executables+ <*> requiredField' "foreign-libs" .= foreignLibs+ <*> requiredField' "test-suites" .= testSuites+ <*> requiredField' "benchmarks" .= benchmarks+ <*> requiredField' "data-files" .= dataFiles+ <*> requiredField' "data-dir" .= dataDir+ <*> requiredField' "extra-source-files" .= extraSrcFiles+ <*> requiredField' "extra-tmp-files" .= extraTmpFiles+ <*> requiredField' "extra-doc-files" .= extraDocFiles++instance HasCodec (PerCompilerFlavor [String]) where+ codec = dimapCodec (uncurry PerCompilerFlavor) (\(PerCompilerFlavor a b) -> (a, b)) codec++instance (HasCodec a) => HasCodec (a, a) where+ codec = dimapCodec (\(a : [b]) -> (a, b)) (\(a, b) -> [a, b]) codec++instance HasCodec (CompilerFlavor, VersionRange) where+ codec =+ object "(CompilerFlavor, VersionRange)" $+ (,)+ <$> requiredField' "compiler" .= fst+ <*> requiredField' "versionRange" .= snd++instance (HasCodec a) => HasCodec (a, a, a) where+ codec = dimapCodec (\(a : b : [c]) -> (a, b, c)) (\(a, b, c) -> [a, b, c]) codec++instance HasCodec (Maybe String, String) where+ codec =+ dimapCodec+ ( \case+ ("", s) -> (Nothing, s)+ (s1, s2) -> (Just s1, s2)+ )+ ( \case+ (Nothing, s) -> ("", s)+ (Just s1, s2) -> (s1, s2)+ )+ codec++instance HasCodec PackageName where+ codec = dimapCodec mkPackageName unPackageName codec++instance HasCodec PackageIdentifier where+ codec =+ object "PackgeIdentifier" $+ PackageIdentifier+ <$> requiredField' "name" .= pkgName+ <*> requiredField' "version" .= pkgVersion++instance HasCodec RepoKind where+ codec =+ object "RepoKind" $+ dimapCodec f g $+ eitherCodec (pure RepoHead) $+ eitherCodec (pure RepoThis) $+ requiredField' "repo-kind"+ where+ f = \case+ Left _ -> RepoHead+ Right (Left _) -> RepoThis+ Right (Right s) -> RepoKindUnknown s+ g = \case+ RepoHead -> Left ()+ RepoThis -> Right $ Left ()+ RepoKindUnknown s -> Right $ Right s++instance HasCodec RepoType where+ -- TODO add OtherRepoType+ codec =+ stringConstCodec+ [ (Darcs, "Darcs"),+ (Git, "Git"),+ (SVN, "SVN"),+ (CVS, "CVS"),+ (Mercurial, "Mercurial"),+ (GnuArch, "GnuArch"),+ (Bazaar, "Bazaar"),+ (Monotone, "Monotone")+ ]++instance HasCodec Dependency where+ codec =+ object "Dependency" $+ Dependency+ <$> requiredField' "package-name" .= (\(Dependency name _ _) -> name)+ <*> requiredField' "version-range" .= (\(Dependency _ version _) -> version)+ <*> requiredField' "library" .= (\(Dependency _ _ lib) -> lib)++instance HasCodec SourceRepo where+ codec =+ object "SourceRepo" $+ SourceRepo+ <$> requiredField' "kind" .= repoKind+ <*> requiredField' "type" .= repoType+ <*> requiredField' "location" .= repoLocation+ <*> requiredField' "module" .= repoModule+ <*> requiredField' "branch" .= repoBranch+ <*> requiredField' "tag" .= repoTag+ <*> requiredField' "subdir" .= repoSubdir++instance HasCodec ShortText where+ codec = dimapCodec toShortText fromShortText codec++instance HasCodec Cabal.License where+ -- TODO add others+ codec =+ named "Cabal.License" $+ stringConstCodec+ [ (BSD2, "BSD2"),+ (BSD3, "BSD3"),+ (BSD4, "BSD4"),+ (MIT, "MIT"),+ (ISC, "ISC"),+ (PublicDomain, "PublicDomain"),+ (AllRightsReserved, "AllRightsReserved"),+ (UnspecifiedLicense, "UnspecifiedLicense"),+ (OtherLicense, "OtherLicense")+ ]++instance HasCodec SPDX.License where+ codec =+ named "SPDX.License" $+ object "spdx-license" $+ dimapCodec f g $+ eitherCodec (pure NONE) $+ requiredField' "license-expression"+ where+ f = \case+ Left _ -> NONE+ Right e -> License e+ g = \case+ NONE -> Left ("None" :: String)+ License e -> Right e++instance HasCodec SPDX.LicenseExpression where+ codec =+ named "LicenseExpression" $+ dimapCodec f g $+ eitherCodec (object "ELicense" $ (,) <$> requiredField' "expression" .= fst <*> requiredField' "exception-id" .= snd) $+ eitherCodec (object "EAnd" $ (,) <$> requiredField' "expression-1" .= fst <*> requiredField' "expression-2" .= snd) $+ object "EOr" $ (,) <$> requiredField' "expression-11" .= fst <*> requiredField' "expression-22" .= snd+ where+ f = \case+ Left (e, c) -> ELicense e c+ Right (Left (exp1, exp2)) -> EAnd exp1 exp2+ Right (Right (exp1, exp2)) -> EOr exp1 exp2+ g = \case+ ELicense e c -> Left (e, c)+ EAnd exp1 exp2 -> Right $ Left (exp1, exp2)+ EOr exp1 exp2 -> Right $ Right (exp1, exp2)++instance HasCodec SPDX.SimpleLicenseExpression where+ codec =+ object "SimpleLicenseExpression" $+ dimapCodec f g $+ eitherCodec (requiredField' "id") $+ eitherCodec (requiredField' "id-plus") $+ requiredField' "license-ref"+ where+ f = \case+ Left i -> ELicenseId i+ Right (Left i) -> ELicenseIdPlus i+ Right (Right ref) -> ELicenseRef ref+ g = \case+ ELicenseId i -> Left i+ ELicenseIdPlus i -> Right $ Left i+ ELicenseRef ref -> Right $ Right ref++instance HasCodec SPDX.LicenseId where+ codec = named "SPDX.LicenseId" shownBoundedEnumCodec++instance HasCodec SPDX.LicenseRef where+ codec = dimapCodec f g codec+ where+ f = uncurry SPDX.mkLicenseRef'+ g = \l -> (SPDX.licenseDocumentRef l, SPDX.licenseRef l)++instance HasCodec SPDX.LicenseExceptionId where+ codec = shownBoundedEnumCodec++instance HasCodec BuildType where+ codec = stringConstCodec [(Simple, "Simple"), (Configure, "Configure"), (Make, "Make"), (Custom, "Custom")]++instance HasCodec SetupBuildInfo where+ codec =+ object "SetupBuildInfo" $+ SetupBuildInfo+ <$> requiredField' "setup-depends" .= setupDepends+ -- TODO: not needed+ <*> requiredField' "__defaultSetupDepends" .= defaultSetupDepends++instance HasCodec Flag where+ codec =+ object "Flag" $+ MkFlag+ <$> requiredField' "name" .= flagName+ <*> requiredField' "description" .= flagDescription+ <*> requiredField' "default" .= flagDefault+ <*> requiredField' "manual" .= flagManual++instance HasCodec FlagName where+ codec = dimapCodec mkFlagName unFlagName codec++instance HasCodec a => HasCodec (CondTree ConfVar [Dependency] a) where+ codec =+ named "ConditionalTree" $+ object "CondTree" $+ CondNode+ <$> requiredField' "condTreeData" .= condTreeData+ <*> requiredField' "condTreeConstraints" .= condTreeConstraints+ <*> requiredField' "condTreeComponents" .= condTreeComponents++instance (HasCodec a) => HasCodec (CondBranch ConfVar [Dependency] a) where+ codec =+ object "CondBranch" $+ CondBranch+ <$> requiredField' "condBranchCondition" .= condBranchCondition+ <*> requiredField' "condBranchIfTrue" .= condBranchIfTrue+ <*> optionalField' "condBranchIfFalse" .= condBranchIfFalse++instance HasCodec (Condition ConfVar) where+ codec =+ named "Condition" $+ dimapCodec f g $+ eitherCodec (object "var" $ requiredField' "v") $+ eitherCodec (object "lit" $ requiredField' "bool") $+ eitherCodec (object "cnot" $ requiredField' "cond") $+ eitherCodec (object "cor" $ (,) <$> requiredField' "cond1" .= fst <*> requiredField' "cond2" .= snd) $+ object "cand" $ (,) <$> requiredField' "cond12" .= fst <*> requiredField' "cond22" .= snd+ where+ f = \case+ Left c -> Var c+ Right (Left b) -> Lit b+ Right (Right (Left cond)) -> CNot cond+ Right (Right (Right (Left (cond1, cond2)))) -> COr cond1 cond2+ Right (Right (Right (Right (cond1, cond2)))) -> CAnd cond1 cond2+ g = \case+ Var c -> Left c+ Lit b -> Right $ Left b+ CNot cond -> Right $ Right $ Left cond+ COr cond1 cond2 -> Right $ Right $ Right $ Left (cond1, cond2)+ CAnd cond1 cond2 -> Right $ Right $ Right $ Right (cond1, cond2)++instance HasCodec ConfVar where+ codec =+ object "ConfVar" $+ dimapCodec f g $+ eitherCodec (requiredField' "os") $+ eitherCodec (requiredField' "arch") $+ eitherCodec (requiredField' "flag") $+ (,) <$> requiredField' "compiler" .= fst <*> requiredField' "version" .= snd+ where+ f = \case+ Left o -> OS o+ Right (Left a) -> Arch a+ Right (Right (Left name)) -> Flag name+ Right (Right (Right (compiler, version))) -> Impl compiler version+ g = \case+ OS o -> Left o+ Arch a -> Right $ Left a+ Flag name -> Right $ Right $ Left name+ Impl compiler version -> Right $ Right $ Right (compiler, version)++instance HasCodec Arch where+ -- TODO add OtherArch+ codec =+ stringConstCodec+ [ (I386, "I386"),+ (X86_64, "X86_64"),+ (PPC, "PPC"),+ (PPC64, "PPC64"),+ (Sparc, "Sparc"),+ (Arm, "Arm"),+ (AArch64, "AArch64"),+ (Mips, "Mips"),+ (SH, "SH"),+ (IA64, "IA64"),+ (S390, "S390"),+ (Alpha, "Alpha"),+ (Hppa, "Hppa"),+ (Rs6000, "Rs6000"),+ (M68k, "M68k"),+ (Vax, "Vax"),+ (JavaScript, "JavaScript")+ ]++instance HasCodec OS where+ -- TODO add OtherOS+ codec =+ stringConstCodec+ [ (Linux, "Linux"),+ (Windows, "Windows"),+ (OSX, "OSX"),+ (FreeBSD, "FreeBSD"),+ (OpenBSD, "OpenBSD"),+ (NetBSD, "NetBSD"),+ (DragonFly, "DragonFly"),+ (Solaris, "Solaris"),+ (AIX, "AIX"),+ (HPUX, "HPUX"),+ (IRIX, "IRIX"),+ (HaLVM, "HaLVM"),+ (Hurd, "Hurd"),+ (IOS, "IOS"),+ (Android, "Android"),+ (Ghcjs, "Ghcjs")+ ]++instance HasCodec Library where+ codec =+ object "Library" $+ Library+ <$> requiredField' "name" .= libName+ <*> requiredField' "exposed-modules" .= exposedModules+ <*> requiredField' "re-exported-modules" .= reexportedModules+ <*> requiredField' "signatures" .= signatures+ <*> requiredField' "exposed" .= libExposed+ <*> requiredField' "visibility" .= libVisibility+ <*> requiredField' "build-info" .= libBuildInfo++instance HasCodec LibraryName where+ codec =+ object "LibraryName" $+ dimapCodec f g $+ eitherCodec (pure LMainLibName) $+ requiredField' "sub-lib-name"+ where+ f = \case+ Left _ -> LMainLibName+ Right s -> LSubLibName s+ g = \case+ LMainLibName -> Left ()+ LSubLibName s -> Right s++instance HasCodec ModuleName where+ codec = dimapCodec fromComponents components codec++instance HasCodec ModuleReexport where+ codec =+ object "ModuleReexport" $+ ModuleReexport+ <$> requiredField' "moduleReexportOriginalPackage" .= moduleReexportOriginalPackage+ <*> requiredField' "moduleReexportOriginalName" .= moduleReexportOriginalName+ <*> requiredField' "moduleReexportName" .= moduleReexportName++instance HasCodec LibraryVisibility where+ codec = stringConstCodec [(LibraryVisibilityPublic, "LibraryVisibilityPublic"), (LibraryVisibilityPrivate, "LibraryVisibilityPrivate")]++instance HasCodec ForeignLib where+ codec =+ object "ForeignLib" $+ ForeignLib+ <$> requiredField' "name" .= foreignLibName+ <*> requiredField' "type" .= foreignLibType+ <*> requiredField' "options" .= foreignLibOptions+ <*> requiredField' "build-info" .= foreignLibBuildInfo+ <*> requiredField' "version-info" .= foreignLibVersionInfo+ <*> requiredField' "linux-version" .= foreignLibVersionLinux+ <*> requiredField' "mod-def-files" .= foreignLibModDefFile++instance HasCodec ForeignLibType where+ codec = stringConstCodec [(ForeignLibNativeShared, "ForeignLibNativeShared"), (ForeignLibNativeStatic, "ForeignLibNativeStatic"), (ForeignLibTypeUnknown, "ForeignLibTypeUnknown")]++instance HasCodec ForeignLibOption where+ codec = literalTextValueCodec ForeignLibStandalone "ForeignLibStandalone"++instance HasCodec LibVersionInfo where+ codec = dimapCodec mkLibVersionInfo libVersionInfoCRA codec++instance HasCodec Version where+ codec = dimapCodec mkVersion versionNumbers codec++instance HasCodec Executable where+ codec =+ object "Executable" $+ Executable+ <$> requiredField' "name" .= exeName+ <*> requiredField' "module-path" .= modulePath+ <*> requiredField' "scope" .= exeScope+ <*> requiredField' "build-info" .= buildInfo++instance HasCodec ExecutableScope where+ codec =+ stringConstCodec $+ NE.fromList+ [ (ExecutablePublic, "public"),+ (ExecutablePrivate, "private")+ ]++instance HasCodec TestSuite where+ codec =+ object "TestSuite" $+ TestSuite+ <$> requiredField' "name" .= testName+ <*> requiredField' "interface" .= testInterface+ <*> requiredField' "build-info" .= testBuildInfo++instance HasCodec TestSuiteInterface where+ codec =+ object "TestSuiteInterface" $+ dimapCodec f g $+ eitherCodec ((,) <$> requiredField' "version" .= fst <*> requiredField' "filepath" .= snd) $+ eitherCodec ((,) <$> requiredField' "version" .= fst <*> requiredField' "module-name" .= snd) $+ requiredField' "type"+ where+ f = \case+ Left (v, fp) -> TestSuiteExeV10 v fp+ Right (Left (v, mn)) -> TestSuiteLibV09 v mn+ Right (Right tt) -> TestSuiteUnsupported tt+ g = \case+ TestSuiteExeV10 v fp -> Left (v, fp)+ TestSuiteLibV09 v mn -> Right $ Left (v, mn)+ TestSuiteUnsupported tt -> Right $ Right tt++instance HasCodec TestType where+ codec =+ object "TestType" $+ dimapCodec f g $+ eitherCodec (requiredField' "version") $+ eitherCodec (requiredField' "version") $+ (,) <$> requiredField' "name" .= fst <*> requiredField' "version" .= snd+ where+ f = \case+ Left v -> TestTypeExe v+ Right (Left v) -> TestTypeLib v+ Right (Right (s, v)) -> TestTypeUnknown s v+ g = \case+ TestTypeExe v -> Left v+ TestTypeLib v -> Right $ Left v+ TestTypeUnknown s v -> Right $ Right (s, v)++instance HasCodec Benchmark where+ codec =+ object "Benchmark" $+ Benchmark+ <$> requiredField' "name" .= benchmarkName+ <*> requiredField' "interface" .= benchmarkInterface+ <*> requiredField' "build-info" .= benchmarkBuildInfo++instance HasCodec BenchmarkType where+ codec =+ object "BenchmarkType" $+ dimapCodec f g $+ eitherCodec (requiredField' "benchmark-type") $+ (,)+ <$> requiredField' "type" .= fst+ <*> requiredField' "version" .= snd+ where+ f = \case+ Left v -> BenchmarkTypeExe v+ Right (s, v) -> BenchmarkTypeUnknown s v+ g = \case+ BenchmarkTypeExe v -> Left v+ BenchmarkTypeUnknown s v -> Right (s, v)++instance HasCodec BenchmarkInterface where+ codec =+ dimapCodec f g $+ eitherCodec+ ( object "BenchmarkExeV10" $+ (,)+ <$> requiredField' "version" .= fst+ <*> requiredField' "filepath" .= snd+ )+ $ object "BenchmarkUnsupported" $ requiredField' "benchmark-type"+ where+ f = \case+ Left (version, file) -> BenchmarkExeV10 version file+ Right t -> BenchmarkUnsupported t+ g = \case+ BenchmarkExeV10 version file -> Left (version, file)+ BenchmarkUnsupported t -> Right t++instance HasCodec ModuleRenaming where+ codec =+ object "ModuleRenaming" $+ dimapCodec f g $+ eitherCodec (pure DefaultRenaming) $+ eitherCodec (requiredField' "name") (requiredField' "name")+ where+ f = \case+ Left _ -> DefaultRenaming+ Right (Left m) -> ModuleRenaming m+ Right (Right m) -> HidingRenaming m+ g = \case+ DefaultRenaming -> Left ()+ ModuleRenaming m -> Right $ Left m+ HidingRenaming m -> Right $ Right m++instance HasCodec IncludeRenaming where+ codec =+ object "IncludeRenaming" $+ IncludeRenaming+ <$> requiredField' "includeProvidesRn" .= includeProvidesRn+ <*> requiredField' "includeRequiresRn" .= includeRequiresRn++instance HasCodec Mixin where+ codec =+ object "Mixin" $+ Mixin+ <$> requiredField' "package-name" .= mixinPackageName+ <*> requiredField' "include-renaming" .= mixinIncludeRenaming++instance HasCodec LegacyExeDependency where+ codec =+ object "LegacyExeDependency" $+ LegacyExeDependency+ <$> requiredField' "package-name" .= (\(LegacyExeDependency s _) -> s)+ <*> requiredField' "include-renaming" .= (\(LegacyExeDependency _ vr) -> vr)++instance HasCodec ExeDependency where+ codec =+ object "ExeDependency" $+ ExeDependency+ <$> requiredField' "package-name" .= (\(ExeDependency a _ _) -> a)+ <*> requiredField' "executable-component-name" .= (\(ExeDependency _ b _) -> b)+ <*> requiredField' "version-range" .= (\(ExeDependency _ _ c) -> c)++instance HasCodec PkgconfigDependency where+ codec =+ object "PkgconfigDependency" $+ PkgconfigDependency+ <$> requiredField' "pkgconfigName" .= (\(PkgconfigDependency name _) -> name)+ <*> requiredField' "pkgconfigVersionRange" .= (\(PkgconfigDependency _ version) -> version)++instance HasCodec PkgconfigName where+ codec = dimapCodec mkPkgconfigName unPkgconfigName codec++instance HasCodec PkgconfigVersionRange where+ codec = bimapCodec f g codec+ where+ f = \s -> case eitherParsec s of+ Left pe -> Left $ show pe+ Right a -> Right a+ g = prettyShow++instance HasCodec PkgconfigVersion where+ codec =+ bimapCodec+ (Right . PkgconfigVersion . encodeUtf8)+ ( \(PkgconfigVersion v) -> case decodeUtf8' v of+ Left ex -> T.pack $ show ex+ Right txt -> txt+ )+ codec++instance HasCodec Language where+ codec =+ dimapCodec f g $+ eitherCodec (literalTextValueCodec Haskell98 "Haskell98") $+ eitherCodec+ (literalTextValueCodec Haskell2010 "Haskell2010")+ codec+ where+ f = \case+ Left l -> l+ Right (Left l) -> l+ Right (Right s) -> UnknownLanguage s+ g = \case+ Haskell98 -> Left Haskell98+ Haskell2010 -> Right $ Left Haskell2010+ UnknownLanguage s -> Right $ Right s++instance HasCodec Extension where+ codec =+ named "Extension" $+ object "Extension" $+ dimapCodec f g $+ eitherCodec (requiredField' "enable-extension") $+ eitherCodec+ (requiredField' "disable-extension")+ (requiredField' "unknown-extension")+ where+ f = \case+ Left e -> EnableExtension e+ Right (Left e) -> DisableExtension e+ Right (Right s) -> UnknownExtension s+ g = \case+ EnableExtension e -> Left e+ DisableExtension e -> Right $ Left e+ UnknownExtension e -> Right $ Right e++instance HasCodec KnownExtension where+ codec = named "KnownExtension" shownBoundedEnumCodec++instance HasCodec BuildInfo where+ codec =+ object "BuildInfo" $+ BuildInfo+ <$> requiredField' "buildable" .= buildable+ <*> requiredField' "buildTools" .= buildTools+ <*> requiredField' "buildToolDepends" .= buildToolDepends+ <*> requiredField' "cppOptions" .= cppOptions+ <*> requiredField' "asmOptions" .= asmOptions+ <*> requiredField' "cmmOptions" .= cmmOptions+ <*> requiredField' "ccOptions" .= ccOptions+ <*> requiredField' "cxxOptions" .= cxxOptions+ <*> requiredField' "ldOptions" .= ldOptions+ <*> requiredField' "pkgconfigDepends" .= pkgconfigDepends+ <*> requiredField' "frameworks" .= frameworks+ <*> requiredField' "extraFrameworkDirs" .= extraFrameworkDirs+ <*> requiredField' "asmSources" .= asmSources+ <*> requiredField' "cmmSources" .= cmmSources+ <*> requiredField' "cSources" .= cSources+ <*> requiredField' "cxxSources" .= cxxSources+ <*> requiredField' "jsSources" .= jsSources+ <*> requiredField' "hsSourceDirs" .= hsSourceDirs+ <*> requiredField' "otherModules" .= otherModules+ <*> requiredField' "virtualModules" .= virtualModules+ <*> requiredField' "autogenModules" .= autogenModules+ <*> requiredField' "defaultLanguage" .= defaultLanguage+ <*> requiredField' "otherLanguages" .= otherLanguages+ <*> requiredField' "defaultExtensions" .= defaultExtensions+ <*> requiredField' "otherExtensions" .= otherExtensions+ <*> requiredField' "oldExtensions" .= oldExtensions+ <*> requiredField' "extraLibs" .= extraLibs+ <*> requiredField' "extraGHCiLibs" .= extraGHCiLibs+ <*> requiredField' "extraBundledLibs" .= extraBundledLibs+ <*> requiredField' "extraLibFlavours" .= extraLibFlavours+ <*> requiredField' "extraDynLibFlavours" .= extraDynLibFlavours+ <*> requiredField' "extraLibDirs" .= extraLibDirs+ <*> requiredField' "includeDirs" .= includeDirs+ <*> requiredField' "includes" .= includes+ <*> requiredField' "autogenIncludes" .= autogenIncludes+ <*> requiredField' "installIncludes" .= installIncludes+ <*> requiredField' "options" .= options+ <*> requiredField' "profOptions" .= profOptions+ <*> requiredField' "sharedOptions" .= sharedOptions+ <*> requiredField' "staticOptions" .= staticOptions+ <*> requiredField' "customFieldsBI" .= customFieldsBI+ <*> requiredField' "targetBuildDepends" .= targetBuildDepends+ <*> requiredField' "mixins" .= mixins
+ test/Cabal2JSONSpec.hs view
@@ -0,0 +1,97 @@+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}++module Cabal2JSONSpec (spec) where++import Autodocodec+import Autodocodec.Yaml+import Cabal2JSON ()+import qualified Distribution.Make as Cabal+import Distribution.ModuleName as Cabal+import Distribution.PackageDescription.Parsec as Cabal+import qualified Distribution.SPDX as SPDX+import Distribution.Types.Benchmark as Cabal+import Distribution.Types.BenchmarkInterface as Cabal+import Distribution.Types.BenchmarkType as Cabal+import Distribution.Types.BuildInfo as Cabal+import Distribution.Types.BuildType as Cabal+import Distribution.Types.Executable as Cabal+import Distribution.Types.ExecutableScope as Cabal+import Distribution.Types.Flag as Cabal+import Distribution.Types.ForeignLib as Cabal+import Distribution.Types.ForeignLibOption as Cabal+import Distribution.Types.ForeignLibType as Cabal+import Distribution.Types.GenericPackageDescription as Cabal+import Distribution.Types.Library as Cabal+import Distribution.Types.LibraryName as Cabal+import Distribution.Types.LibraryVisibility as Cabal+import Distribution.Types.ModuleReexport as Cabal+import Distribution.Types.PackageDescription as Cabal+import Distribution.Types.PkgconfigVersion as Cabal+import Distribution.Types.PkgconfigVersionRange as Cabal+import Distribution.Types.SourceRepo as Cabal+import Distribution.Types.TestSuite as Cabal+import Distribution.Types.TestSuiteInterface as Cabal+import Distribution.Types.UnqualComponentName as Cabal+import Distribution.Types.VersionRange as Cabal+import Distribution.Utils.ShortText as Cabal+import Distribution.Verbosity as Cabal+import Language.Haskell.Extension as Cabal+import Test.Syd+import Test.Syd.Aeson++spec :: Spec+spec = do+ it "outputs the same json for the cabal2json cabal file" $+ goldenJSONValueFile+ "test_resources/json/cabal2json.cabal.json"+ (Cabal.readGenericPackageDescription Cabal.silent "cabal2json.cabal")++ schemaSpec @Cabal.GenericPackageDescription "generic-package-description"+ schemaSpec @Cabal.PackageDescription "package-description"+ schemaSpec @Cabal.PackageIdentifier "package-identified"+ schemaSpec @Cabal.BenchmarkType "benchmark-type"+ schemaSpec @Cabal.BenchmarkInterface "benchmark-interface"+ schemaSpec @Cabal.Benchmark "benchmark"+ schemaSpec @Cabal.BuildInfo "build-info"+ schemaSpec @Cabal.BuildType "build-type"+ schemaSpec @Cabal.Executable "executable"+ schemaSpec @Cabal.ExecutableScope "executable-scope"+ schemaSpec @Cabal.Extension "extension"+ schemaSpec @Cabal.Flag "flag"+ schemaSpec @Cabal.FlagName "flag-name"+ schemaSpec @Cabal.ForeignLibType "foreign-lib-type"+ schemaSpec @Cabal.ForeignLibOption "foreign-lib-option"+ schemaSpec @Cabal.ForeignLib "foreign-lib"+ schemaSpec @Cabal.KnownExtension "KnownExtension"+ schemaSpec @Cabal.Language "language"+ schemaSpec @Cabal.Library "library"+ schemaSpec @Cabal.LibraryName "library-name"+ schemaSpec @Cabal.LibraryVisibility "library-visibility"+ schemaSpec @Cabal.License "license"+ schemaSpec @Cabal.ModuleName "module-name"+ schemaSpec @Cabal.ModuleReexport "module-reexport"+ schemaSpec @Cabal.PackageIdentifier "package-identifier"+ schemaSpec @Cabal.PkgconfigVersion "pkgconfig-version"+ schemaSpec @Cabal.PkgconfigVersionRange "pkgconfig-version-range"+ schemaSpec @Cabal.ShortText "short-text"+ schemaSpec @Cabal.SourceRepo "source-repo"+ schemaSpec @Cabal.TestSuiteInterface "test-suite-interface"+ schemaSpec @Cabal.TestSuite "test-suite"+ schemaSpec @Cabal.UnqualComponentName "unqual-component-name"+ schemaSpec @Cabal.Version "version"+ schemaSpec @Cabal.VersionRange "version-range"+ schemaSpec @SPDX.License "spdx-license"+ schemaSpec @SPDX.LicenseExpression "spdx-license-expression"+ schemaSpec @SPDX.SimpleLicenseExpression "spdx-simple-license-expression"+ schemaSpec @SPDX.LicenseExceptionId "spdx-license-exception-id"+ schemaSpec @SPDX.LicenseRef "spdx-license-ref"+ schemaSpec @SPDX.LicenseId "spdx-license-id"++schemaSpec :: forall a. HasCodec a => String -> Spec+schemaSpec name =+ it ("outputs the same yaml file for " <> name) $+ pureGoldenByteStringFile+ ("test_resources/schemas/" <> name <> ".txt")+ (renderColouredSchemaViaCodec @a)
+ test/Spec.hs view
@@ -0,0 +1,1 @@+{-# OPTIONS_GHC -F -pgmF sydtest-discover #-}