json-autotype 3.1.1 → 3.1.2
raw patch · 4 files changed
+62/−36 lines, 4 files
Files
- changelog.md +5/−0
- json-autotype.cabal +2/−2
- src/Data/Aeson/AutoType/CodeGen/Haskell.hs +16/−1
- src/Data/Aeson/AutoType/Nested.hs +39/−33
changelog.md view
@@ -1,5 +1,10 @@ Changelog =========+ 3.1.2 Apr 2020+ * Future-proof nested code gen interface+ with parametric `CodeFrag`ment that can+ refer to thing that is not a type.+ 3.1.1 Apr 2020 * Expose Data.Aeson.AutoType.Nested
json-autotype.cabal view
@@ -4,10 +4,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: 1f3b5938078282c1d5d432d27afdc61b719195bd936f167412da2cc5cca230d3+-- hash: 284ee102820ec2e6f94fe118266cdb759c0049a5e95f88fd6c42a73e39aeff04 name: json-autotype-version: 3.1.1+version: 3.1.2 synopsis: Automatic type declaration for JSON input data description: Generates datatype declarations with Aeson''s ''Data.Aeson.FromJSON'' .
src/Data/Aeson/AutoType/CodeGen/Haskell.hs view
@@ -11,6 +11,7 @@ , importedModules , requiredPackages , generateModuleImports+ , ModuleImport ) where import qualified Data.Text as Text@@ -40,6 +41,7 @@ defaultHaskellFilename :: FilePath defaultHaskellFilename = "JSONTypes.hs" +-- | Generate module header header :: Text -> Text header moduleName = [src| {-# LANGUAGE TemplateHaskell #-}@@ -50,12 +52,13 @@ {-# LANGUAGE DeriveGeneric #-} -- | DO NOT EDIT THIS FILE MANUALLY! -- It was automatically generated by `json-autotype`.- module |] <> capitalize moduleName <> [src| where |] <> generateModuleImports importedModules +-- | Alias for indicating that this is item in module imports list. type ModuleImport = Text +-- | Given a list of imports, generate source code. generateModuleImports :: [ModuleImport] -> Text generateModuleImports = Text.unlines . fmap ("import " <>)@@ -81,8 +84,14 @@ , "qualified GHC.Generics" ] +-- | Epilogue for generated code:+--+-- * function to use parser to get data from `Text`+-- * main function in case we use `runghc` for testing parser immediately epilogue :: Text -> Text epilogue toplevelName = [src|++-- | Use parser to get |] <> toplevelName <> [src| object parse :: FilePath -> IO |] <> toplevelName <> [src| parse filename = do input <- BSL.readFile filename@@ -97,6 +106,7 @@ fatal msg = do hPutStrLn stderr msg exitFailure +-- | For quick testing main :: IO () main = do filenames <- getArgs@@ -122,13 +132,18 @@ else outputFilename normalizeTypeName' = Text.unpack . normalizeTypeName . Text.pack +-- | Function to run Haskell module+--+-- FIXME: just rely on `run-haskell-module` exports runHaskellModule :: FilePath -> [String] -> IO ExitCode runHaskellModule = Run.runHaskellModule +-- | Options to be used when running Haskell module defaultHaskellOpts :: Run.RunOptions defaultHaskellOpts = def { Run.additionalPackages = ["json-alt", "aeson"] } +-- | Run Haskell module with strict warning options (each warning is an error) runHaskellModuleStrict :: FilePath -> [String] -> IO ExitCode runHaskellModuleStrict = Run.runHaskellModule' opts where
src/Data/Aeson/AutoType/Nested.hs view
@@ -1,5 +1,7 @@-{-# language DeriveGeneric #-}-{-# language OverloadedStrings #-}+{-# language DeriveGeneric #-}+{-# language OverloadedStrings #-}+{-# language TypeSynonymInstances #-}+{-# language FlexibleInstances #-} -- | Simple interface for using AutoType inference -- in other code generators. --@@ -12,17 +14,21 @@ -- Note that while we can put more code in the module, -- it is recommended to avoid multiple automatically -- generated types in order to avoid name conflicts.+--+-- NOTE: this interface is yet unstable module Data.Aeson.AutoType.Nested( defaultImportedModules , generateModuleImports , inferType- , CodeFragment+ , CodeFrag(..) , TypeName- , DeclaredType(..)+ , TypeFrag+ , ModuleImport+ , PackageName ) where import Data.Aeson-import Data.Aeson.AutoType.CodeGen.Haskell(generateModuleImports, requiredPackages, importedModules)+import Data.Aeson.AutoType.CodeGen.Haskell(generateModuleImports, requiredPackages, importedModules, ModuleImport) import Data.Aeson.AutoType.CodeGen.HaskellFormat(displaySplitTypes) import Data.Aeson.AutoType.Extract(extractType, unifyTypes) import Data.Aeson.AutoType.Split(splitTypeByLabel)@@ -34,43 +40,43 @@ -- FIXME: general type to compose generated types -- move to JSON Autotype as library interface? -- * API Response Structures-type CodeFragment = Text+type Code = Text type TypeName = Text-type ImportedModule = Text type PackageName = Text --- | Type declaration and its requirements+-- | Generated code reference and its requirements -- Content to embed in an autogenerated module:--- * name of the type to reference+--+-- * name of the reference -- * declarations to describe it -- * module imports necessary for declarations -- to work-data DeclaredType = DeclaredType+data CodeFrag a = CodeFrag { -- | Code fragment to be inserted in generated module- typeCodeFragment :: CodeFragment+ codeFragCode :: Code -- | Toplevel type name to refer to- , typeName :: TypeName+ , codeFragName :: a -- | List of clauses to add to imports list- , typeImportedModules :: [ImportedModule]+ , codeFragImports :: [ModuleImport] -- | List of packages to add to generated package dependencies- , typePackages :: [PackageName]- }- deriving- ( Eq- , Show- , Generic- , Typeable- )+ , codeFragPackages :: [PackageName]+ } deriving+ ( Eq+ , Show+ , Generic+ , Typeable+ ) +type TypeFrag = CodeFrag TypeName -instance Default DeclaredType where+instance Default TypeFrag where -- Minimal placeholder to use in case we cannot infer proper type- def = DeclaredType {- typeCodeFragment = ""- , typeName = "Data.Aeson.Value"- , typeImportedModules = ["qualified Data.Aeson"]- , typePackages = ["aeson"]+ def = CodeFrag {+ codeFragCode = ""+ , codeFragName = "Data.Aeson.Value"+ , codeFragImports = ["qualified Data.Aeson"]+ , codeFragPackages = ["aeson"] } -- | List of modules imported for Autotyped declarations@@ -81,14 +87,14 @@ -- either an error, or an `EndpointResponse` -- that allows to declare and use this type -- in generated module.-inferType :: Text -> [Value] -> DeclaredType+inferType :: Text -> [Value] -> TypeFrag inferType typeName [] = def inferType typeName jsonValues =- DeclaredType {- typeImportedModules = defaultImportedModules- , typeCodeFragment = displaySplitTypes splitTypeDescriptors- , typeName = typeName- , typePackages = requiredPackages+ CodeFrag {+ codeFragImports = defaultImportedModules+ , codeFragCode = displaySplitTypes splitTypeDescriptors+ , codeFragName = typeName+ , codeFragPackages = requiredPackages } where valueTypes = map extractType jsonValues