elm-bridge 0.4.3 → 0.5.0
raw patch · 12 files changed
+311/−125 lines, 12 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- Elm.TyRep: [es_options] :: ESum -> [(String, Either [(String, EType)] [EType])]
+ Elm.Json: jsonParserForType :: EType -> String
+ Elm.Json: jsonSerForType :: EType -> String
+ Elm.Module: defaultTypeAlterations :: EType -> EType
+ Elm.TyRep: Anonymous :: [EType] -> SumTypeFields
+ Elm.TyRep: Named :: [(String, EType)] -> SumTypeFields
+ Elm.TyRep: STC :: String -> String -> SumTypeFields -> SumTypeConstructor
+ Elm.TyRep: [_stcEncoded] :: SumTypeConstructor -> String
+ Elm.TyRep: [_stcFields] :: SumTypeConstructor -> SumTypeFields
+ Elm.TyRep: [_stcName] :: SumTypeConstructor -> String
+ Elm.TyRep: [es_constructors] :: ESum -> [SumTypeConstructor]
+ Elm.TyRep: data SumTypeConstructor
+ Elm.TyRep: data SumTypeFields
+ Elm.TyRep: instance GHC.Classes.Eq Elm.TyRep.SumTypeConstructor
+ Elm.TyRep: instance GHC.Classes.Eq Elm.TyRep.SumTypeFields
+ Elm.TyRep: instance GHC.Classes.Ord Elm.TyRep.SumTypeConstructor
+ Elm.TyRep: instance GHC.Classes.Ord Elm.TyRep.SumTypeFields
+ Elm.TyRep: instance GHC.Show.Show Elm.TyRep.SumTypeConstructor
+ Elm.TyRep: instance GHC.Show.Show Elm.TyRep.SumTypeFields
+ Elm.TyRep: isNamed :: SumTypeFields -> Bool
+ Elm.TyRep: toElmType :: (Typeable a) => Proxy a -> EType
- Elm.Derive: data Options :: *
+ Elm.Derive: data Options
- Elm.Derive: data SumEncoding :: *
+ Elm.Derive: data SumEncoding
- Elm.TyRep: ESum :: ETypeName -> [(String, Either [(String, EType)] [EType])] -> SumEncoding' -> Bool -> Bool -> ESum
+ Elm.TyRep: ESum :: ETypeName -> [SumTypeConstructor] -> SumEncoding' -> Bool -> Bool -> ESum
Files
- CHANGELOG.md +4/−0
- elm-bridge.cabal +1/−1
- src/Elm/Derive.hs +11/−5
- src/Elm/Json.hs +35/−34
- src/Elm/Module.hs +29/−18
- src/Elm/TyRender.hs +3/−3
- src/Elm/TyRep.hs +65/−7
- test/Elm/DeriveSpec.hs +25/−10
- test/Elm/JsonSpec.hs +65/−20
- test/Elm/ModuleSpec.hs +15/−16
- test/Elm/TyRenderSpec.hs +51/−0
- test/EndToEnd.hs +7/−11
CHANGELOG.md view
@@ -1,3 +1,7 @@+# v0.5.0++ * Large change for sum types that used `constructorTagModifier`. The generated types are now unaffected! This is a breaking change for those who used this feature.+ # v0.4.2 Drop support for `aeson < 1.`
elm-bridge.cabal view
@@ -1,5 +1,5 @@ name: elm-bridge-version: 0.4.3+version: 0.5.0 synopsis: Derive Elm types and Json code from Haskell types, using aeson's options description: Building the bridge from Haskell to Elm and back. Define types once, and derive the aeson and elm functions at the same time, using any aeson
src/Elm/Derive.hs view
@@ -151,17 +151,17 @@ sumOpts = listE $ map mkOpt constrs mkOpt :: Con -> Q Exp mkOpt c =- let modifyName = A.constructorTagModifier opts . nameBase+ let modifyName n = (nameBase n, A.constructorTagModifier opts (nameBase n)) in case c of NormalC name' args ->- let n = modifyName name'+ let (b, n) = modifyName name' tyArgs = listE $ map (\(_, ty) -> compileType ty) args- in [|(n, Right $tyArgs)|]+ in [|STC b n (Anonymous $tyArgs)|] RecC name' args ->- let n = modifyName name'+ let (b, n) = modifyName name' tyArgs = listE $ map (\(nm, _, ty) -> let nm' = A.fieldLabelModifier opts $ nameBase nm in [|(nm', $(compileType ty))|]) args- in [|(n, Left $tyArgs)|]+ in [|STC b n (Named $tyArgs)|] _ -> fail ("Can't derive this sum: " ++ show c) deriveSynonym :: A.Options -> Name -> [TyVarBndr] -> Type -> Q [Dec]@@ -197,4 +197,10 @@ else deriveAlias True opts name [] conFields TySynD _ vars otherTy -> deriveSynonym opts name vars otherTy+ NewtypeD _ _ tyvars Nothing (NormalC _ [(Bang NoSourceUnpackedness NoSourceStrictness, otherTy)]) [] ->+ deriveSynonym opts name tyvars otherTy+ NewtypeD _ _ tyvars Nothing (RecC _ conFields@[(Name (OccName _) _, Bang NoSourceUnpackedness NoSourceStrictness, otherTy)]) [] ->+ if A.unwrapUnaryRecords opts+ then deriveSynonym opts name tyvars otherTy+ else deriveAlias True opts name tyvars conFields _ -> fail ("Oops, can only derive data and newtype, not this: " ++ show tyCon)
src/Elm/Json.hs view
@@ -9,11 +9,12 @@ module Elm.Json ( jsonParserForDef , jsonSerForDef+ , jsonParserForType+ , jsonSerForType ) where import Data.List-import Data.Either (isLeft) import Data.Aeson.Types (SumEncoding(..)) import Elm.TyRep@@ -22,6 +23,7 @@ data MaybeHandling = Root | Leaf deriving Eq +-- | Compile a JSON parser for an Elm type jsonParserForType :: EType -> String jsonParserForType = jsonParserForType' Leaf @@ -29,7 +31,6 @@ isOption (ETyApp (ETyCon (ETCon "Maybe")) _) = True isOption _ = False --- | Compile a JSON parser for an Elm type jsonParserForType' :: MaybeHandling -> EType -> String jsonParserForType' mh ty = case ty of@@ -57,32 +58,33 @@ _ -> error $ "Do suitable json parser found for " ++ show ty xs -> let tupleLen = length xs- commas = replicate (tupleLen - 1) ','- in "Json.Decode.map" ++ show tupleLen ++ " (" ++ commas ++ ") "+ in "Json.Decode.map" ++ show tupleLen ++ " tuple" ++ show tupleLen ++ " " ++ unwords (zipWith (\i t' -> "(Json.Decode.index " ++ show (i :: Int) ++ " (" ++ jsonParserForType t' ++ "))") [0..] xs) parseRecords :: Maybe ETypeName -> Bool -> [(String, EType)] -> [String]-parseRecords newtyped unwrap fields = map (mkField doUnwrap) fields ++ [" Json.Decode.succeed " ++ mkNewtype ("{" ++ intercalate ", " (map (\(fldName, _) -> fixReserved fldName ++ " = p" ++ fldName) fields) ++ "}")]+parseRecords newtyped unwrap fields =+ case fields of+ [(_, ftype)] | unwrap -> [ succeed ++ " |> custom (" ++ jsonParserForType' (o ftype) ftype ++ ")" ]+ _ -> succeed : map mkField fields where- doUnwrap = length fields == 1 && unwrap+ succeed = " Json.Decode.succeed (\\" ++ unwords (map ( ('p':) . fst ) fields) ++ " -> " ++ mkNewtype ("{" ++ intercalate ", " (map (\(fldName, _) -> fixReserved fldName ++ " = p" ++ fldName) fields) ++ "}") ++ ")" mkNewtype x = case newtyped of Nothing -> x Just nm -> "(" ++ et_name nm ++ " " ++ x ++ ")"- mkField u (fldName, fldType) =- let (fldStart, fldEnd, mh) = if isOption fldType- then ("(Json.Decode.maybe ", ")", Root)- else ("", "", Leaf)- in " " ++ fldStart ++ "(" ++ (if u then "" else "\"" ++ fldName ++ "\" := ")- ++ jsonParserForType' mh fldType- ++ fldEnd- ++ ") >>= \\p" ++ fldName ++ " ->"+ o fldType = if isOption fldType+ then Root+ else Leaf+ mkField (fldName, fldType) =+ " |> " ++ (if isOption fldType then "fnullable " else "required ")+ ++ show fldName+ ++ " (" ++ jsonParserForType' (o fldType) fldType ++ ")" -- | Checks that all the arguments to the ESum are unary values-allUnaries :: Bool -> [(String, Either [(String, EType)] [EType])] -> Maybe [String]+allUnaries :: Bool -> [SumTypeConstructor] -> Maybe [(String, String)] allUnaries False = const Nothing allUnaries True = mapM isUnary where- isUnary (x, Right args) = if null args then Just x else Nothing+ isUnary (STC o c (Anonymous args)) = if null args then Just (o,c) else Nothing isUnary _ = Nothing -- | Compile a JSON parser for an Elm type definition@@ -118,24 +120,24 @@ isObjectSetName = "jsonDecObjectSet" ++ typename deriveUnaries strs = unlines [ ""- , " let " ++ dictName ++ " = Dict.fromList [" ++ intercalate ", " (map (\s -> "(" ++ show s ++ ", " ++ cap s ++ ")") strs ) ++ "]"+ , " let " ++ dictName ++ " = Dict.fromList [" ++ intercalate ", " (map (\(o, s) -> "(" ++ show s ++ ", " ++ o ++ ")") strs ) ++ "]" , " in decodeSumUnaries " ++ show typename ++ " " ++ dictName ]- encodingDictionary [(oname, args)] = " " ++ mkDecoder oname args+ encodingDictionary [STC cname _ args] = " " ++ mkDecoder cname args encodingDictionary os = tab 4 "let " ++ dictName ++ " = Dict.fromList\n" ++ tab 12 "[ " ++ intercalate ("\n" ++ replicate 12 ' ' ++ ", ") (map dictEntry os) ++ "\n" ++ tab 12 "]" isObjectSet = case encodingType of TaggedObject _ _- | length opts > 1 -> "\n" ++ tab 8 (isObjectSetName ++ " = " ++ "Set.fromList [" ++ intercalate ", " (map (show . fst) $ filter (isLeft . snd) opts) ++ "]")+ | length opts > 1 -> "\n" ++ tab 8 (isObjectSetName ++ " = " ++ "Set.fromList [" ++ intercalate ", " (map (show . _stcName) $ filter (isNamed . _stcFields) opts) ++ "]") _ -> ""- dictEntry (oname, args) = "(" ++ show oname ++ ", " ++ mkDecoder oname args ++ ")"- mkDecoder oname (Left args) = lazy $ "Json.Decode.map "- ++ cap oname+ dictEntry (STC cname oname args) = "(" ++ show oname ++ ", " ++ mkDecoder cname args ++ ")"+ mkDecoder cname (Named args) = lazy $ "Json.Decode.map "+ ++ cname ++ " (" ++ unwords (parseRecords Nothing False args) ++ ")" - mkDecoder oname (Right args) = lazy $ unwords ( decodeFunction- : cap oname+ mkDecoder cname (Anonymous args) = lazy $ unwords ( decodeFunction+ : cname : zipWith (\t' i -> "(" ++ jsonParserForIndexedType t' i ++ ")") args [0..] ) where decodeFunction = case length args of@@ -169,7 +171,7 @@ ETyCon (ETCon "String") -> "Json.Encode.string" ETyCon (ETCon "Bool") -> "Json.Encode.bool" ETyCon (ETCon c) -> "jsonEnc" ++ c- ETyApp (ETyCon (ETCon "List")) t' -> "(Json.Encode.list << List.map " ++ jsonSerForType t' ++ ")"+ ETyApp (ETyCon (ETCon "List")) t' -> "(Json.Encode.list " ++ jsonSerForType t' ++ ")" ETyApp (ETyCon (ETCon "Maybe")) t' -> if omitnull then jsonSerForType t' else "(maybeEncode (" ++ jsonSerForType t' ++ "))"@@ -189,11 +191,10 @@ let tupleArgsV = zip xs ([1..] :: [Int]) tupleArgs = intercalate "," $ map (\(_, v) -> "v" ++ show v) tupleArgsV- in "(\\(" ++ tupleArgs ++ ") -> Json.Encode.list [" ++ intercalate "," (map (\(t', idx) -> "(" ++ jsonSerForType t' ++ ") v" ++ show idx) tupleArgsV) ++ "])"+ in "(\\(" ++ tupleArgs ++ ") -> Json.Encode.list identity [" ++ intercalate "," (map (\(t', idx) -> "(" ++ jsonSerForType t' ++ ") v" ++ show idx) tupleArgsV) ++ "])" -- | Compile a JSON serializer for an Elm type definition--- TODO: handle the omit null case jsonSerForDef :: ETypeDef -> String jsonSerForDef etd = case etd of@@ -215,7 +216,7 @@ TwoElemArray -> "encodeSumTwoElementArray" TaggedObject k c -> unwords ["encodeSumTaggedObject", show k, show c] UntaggedValue -> "encodeSumUntagged"- defaultEncoding [(oname, Right args)] = unlines $+ defaultEncoding [STC _ oname (Anonymous args)] = unlines [ makeType name , fname name ++ " " ++ unwords (map (\tv -> "localEncoder_" ++ tv_name tv) $ et_args name)@@ -225,23 +226,23 @@ defaultEncoding os = unlines ( ( makeName name False ++ " =") : " let keyval v = case v of"- : (map (replicate 12 ' ' ++) (map mkcase os))+ : map ((replicate 12 ' ' ++) . mkcase) os ++ [ " " ++ unwords ["in", encodeFunction, "keyval", "val"] ] ) unaryEncoding names = unlines ( [ makeName name False ++ " =" , " case val of"- ] ++ map (\n -> replicate 8 ' ' ++ cap n ++ " -> Json.Encode.string " ++ show n) names+ ] ++ map (\(o, n) -> replicate 8 ' ' ++ o ++ " -> Json.Encode.string " ++ show n) names )- mkcase :: (String, Either [(String, EType)] [EType]) -> String- mkcase (oname, Right args) = replicate 8 ' ' ++ cap oname ++ " " ++ argList args ++ " -> (" ++ show oname ++ ", encodeValue (" ++ mkEncodeList args ++ "))"- mkcase (oname, Left args) = replicate 8 ' ' ++ cap oname ++ " vs -> (" ++ show oname ++ ", " ++ mkEncodeObject args ++ ")"+ mkcase :: SumTypeConstructor -> String+ mkcase (STC cname oname (Anonymous args)) = replicate 8 ' ' ++ cap cname ++ " " ++ argList args ++ " -> (" ++ show oname ++ ", encodeValue (" ++ mkEncodeList args ++ "))"+ mkcase (STC cname oname (Named args)) = replicate 8 ' ' ++ cap cname ++ " vs -> (" ++ show oname ++ ", " ++ mkEncodeObject args ++ ")" argList a = unwords $ map (\i -> "v" ++ show i ) [1 .. length a] numargs :: (a -> String) -> [a] -> String numargs f = intercalate ", " . zipWith (\n a -> f a ++ " v" ++ show n) ([1..] :: [Int]) mkEncodeObject args = "encodeObject [" ++ intercalate ", " (map (\(n,t) -> "(" ++ show n ++ ", " ++ jsonSerForType t ++ " vs." ++ fixReserved n ++ ")") args) ++ "]" mkEncodeList [arg] = jsonSerForType arg ++ " v1"- mkEncodeList args = "Json.Encode.list [" ++ numargs jsonSerForType args ++ "]"+ mkEncodeList args = "Json.Encode.list identity [" ++ numargs jsonSerForType args ++ "]" where fname name = "jsonEnc" ++ et_name name makeType name = fname name ++ " : " ++ intercalate " -> " (map (mkLocalEncoder . tv_name) (et_args name) ++ [unwords (et_name name : map tv_name (et_args name)) , "Value"])
src/Elm/Module.hs view
@@ -8,7 +8,7 @@ import Data.Proxy import Data.List-import Control.Arrow (second, (+++))+import Control.Arrow (second) import Elm.TyRep import Elm.TyRender@@ -39,8 +39,8 @@ , "import Json.Encode exposing (Value)" , "-- The following module comes from bartavelle/json-helpers" , "import Json.Helpers exposing (..)"- , "import Dict"- , "import Set"+ , "import Dict exposing (Dict)"+ , "import Set exposing (Set)" , "" , "" ]) ++ makeModuleContent defs@@ -79,10 +79,14 @@ recAlterType f td = case td of ETypeAlias a -> ETypeAlias (a { ea_fields = map (second f') (ea_fields a) }) ETypePrimAlias (EPrimAlias n t) -> ETypePrimAlias (EPrimAlias n (f' t))- ETypeSum s -> ETypeSum (s { es_options = map (second (map (second f') +++ map f')) (es_options s) })+ ETypeSum s -> ETypeSum (s { es_constructors = map alterTypes (es_constructors s) }) where- f' (ETyApp a b) = f (ETyApp (f' a) (f' b))- f' x = f x+ alterTypes :: SumTypeConstructor -> SumTypeConstructor+ alterTypes (STC cn dn s) = STC cn dn $ case s of+ Anonymous flds -> Anonymous (map f' flds)+ Named flds -> Named (map (second f') flds)+ f' (ETyApp a b) = f (ETyApp (f' a) (f' b))+ f' x = f x -- | Given a list of type names, will @newtype@ all the matching type -- definitions.@@ -101,20 +105,27 @@ * @Text@ -> @String@ * @Vector@ -> @List@ * @Double@ -> @Float@+ * @Tagged t v@ -> @v@ -} defaultAlterations :: ETypeDef -> ETypeDef-defaultAlterations = recAlterType $ \t -> case t of- ETyApp (ETyCon (ETCon "HashSet")) s -> checkSet s- ETyApp (ETyCon (ETCon "Set")) s -> checkSet s- ETyApp (ETyApp (ETyCon (ETCon "HashMap")) k) v -> checkMap k v- ETyApp (ETyApp (ETyCon (ETCon "THashMap")) k) v -> checkMap k v- ETyApp (ETyApp (ETyCon (ETCon "Map")) k) v -> checkMap k v- ETyCon (ETCon "Integer") -> ETyCon (ETCon "Int")- ETyCon (ETCon "Natural") -> ETyCon (ETCon "Int")- ETyCon (ETCon "Text") -> ETyCon (ETCon "String")- ETyCon (ETCon "Vector") -> ETyCon (ETCon "List")- ETyCon (ETCon "Double") -> ETyCon (ETCon "Float")- _ -> t+defaultAlterations = recAlterType defaultTypeAlterations++defaultTypeAlterations :: EType -> EType+defaultTypeAlterations t = case t of+ ETyApp (ETyCon (ETCon "HashSet")) s -> checkSet $ defaultTypeAlterations s+ ETyApp (ETyCon (ETCon "Set")) s -> checkSet $ defaultTypeAlterations s+ ETyApp (ETyApp (ETyCon (ETCon "HashMap")) k) v -> checkMap (defaultTypeAlterations k) (defaultTypeAlterations v)+ ETyApp (ETyApp (ETyCon (ETCon "THashMap")) k) v -> checkMap (defaultTypeAlterations k) (defaultTypeAlterations v)+ ETyApp (ETyApp (ETyCon (ETCon "Map")) k) v -> checkMap (defaultTypeAlterations k) (defaultTypeAlterations v)+ ETyApp (ETyApp (ETyCon (ETCon "Tagged")) _) v -> defaultTypeAlterations v+ ETyApp x y -> ETyApp (defaultTypeAlterations x) (defaultTypeAlterations y)+ ETyCon (ETCon "Integer") -> ETyCon (ETCon "Int")+ ETyCon (ETCon "Natural") -> ETyCon (ETCon "Int")+ ETyCon (ETCon "Text") -> ETyCon (ETCon "String")+ ETyCon (ETCon "Vector") -> ETyCon (ETCon "List")+ ETyCon (ETCon "Double") -> ETyCon (ETCon "Float")+ ETyCon (ETCon "UTCTime") -> ETyCon (ETCon "Posix")+ _ -> t where isString (ETyCon (ETCon "String")) = True isString _ = False
src/Elm/TyRender.hs view
@@ -53,11 +53,11 @@ instance ElmRenderable ESum where renderElm s = "type " ++ renderElm (es_name s) ++ " =\n "- ++ intercalate "\n | " (map mkOpt (es_options s))+ ++ intercalate "\n | " (map mkOpt (es_constructors s)) ++ "\n" where- mkOpt (name, Left types) = cap name ++ " {" ++ intercalate ", " (map (\(fld, ty) -> fixReserved fld ++ ": " ++ renderElm ty) types) ++ "}"- mkOpt (name, Right types) =+ mkOpt (STC name _ (Named types)) = cap name ++ " {" ++ intercalate ", " (map (\(fld, ty) -> fixReserved fld ++ ": " ++ renderElm ty) types) ++ "}"+ mkOpt (STC name _ (Anonymous types)) = cap name ++ " " ++ unwords (map renderElm types) instance ElmRenderable EPrimAlias where
src/Elm/TyRep.hs view
@@ -5,6 +5,7 @@ import Data.List import Data.Proxy+import Data.Typeable (Typeable, TyCon, TypeRep, splitTyConApp, tyConName, typeRep, typeRepTyCon) import Data.Aeson.Types (SumEncoding(..)) import Data.Monoid ((<>))@@ -70,14 +71,32 @@ , ea_unwrap_unary :: Bool } deriving (Show, Eq, Ord) +data SumTypeFields+ = Anonymous [EType]+ | Named [(String, EType)]+ deriving (Show, Eq, Ord)++isNamed :: SumTypeFields -> Bool+isNamed s =+ case s of+ Named _ -> True+ _ -> False++data SumTypeConstructor+ = STC+ { _stcName :: String+ , _stcEncoded :: String+ , _stcFields :: SumTypeFields+ } deriving (Show, Eq, Ord)+ data ESum- = ESum- { es_name :: ETypeName- , es_options :: [(String, Either [(String, EType)] [EType])]- , es_type :: SumEncoding'- , es_omit_null :: Bool- , es_unary_strings :: Bool- } deriving (Show, Eq, Ord)+ = ESum+ { es_name :: ETypeName+ , es_constructors :: [SumTypeConstructor]+ , es_type :: SumEncoding'+ , es_omit_null :: Bool+ , es_unary_strings :: Bool+ } deriving (Show, Eq, Ord) -- | Transforms tuple types in a list of types. Otherwise returns -- a singleton list with the original type.@@ -86,6 +105,7 @@ where extract :: EType -> Maybe [EType] extract ty = case ty of+ ETyTuple 0 -> return [] ETyApp (ETyTuple _) t -> return [t] ETyApp app@(ETyApp _ _) t -> fmap (++ [t]) (extract app) _ -> Nothing@@ -140,3 +160,41 @@ defSumEncoding :: SumEncoding' defSumEncoding = SumEncoding' ObjectWithSingleField +-- | Get an @elm-bridge@ type representation for a Haskell type.+-- This can be used to render the type declaration via+-- 'Elm.TyRender.ElmRenderable' or the the JSON serializer/parser names via+-- 'Elm.Json.jsonSerForType' and 'Elm.Json.jsonParserForType'.+toElmType :: (Typeable a) => Proxy a -> EType+toElmType ty = toElmType' $ typeRep ty+ where+ toElmType' :: TypeRep -> EType+ toElmType' rep+ -- String (A list of Char)+ | con == (typeRepTyCon $ typeRep (Proxy :: Proxy [])) &&+ args == [typeRep (Proxy :: Proxy Char)] = ETyCon (ETCon "String")+ -- List is special because the constructor name is [] in Haskell and List in elm+ | con == (typeRepTyCon $ typeRep (Proxy :: Proxy [])) = ETyApp (ETyCon $ ETCon $ "List") (toElmType' (head args))+ -- The unit type '()' is a 0-ary tuple.+ | isTuple $ tyConName con = ETyTuple $ length args+ | otherwise = typeApplication con args+ where+ (con, args) = splitTyConApp rep++ isTuple :: String -> Bool+ isTuple ('(':xs) = isTuple' $ reverse xs+ where+ isTuple' :: String -> Bool+ isTuple' (')':xs') = all (== ',') xs'+ isTuple' _ = False+ isTuple _ = False++ typeApplication :: TyCon -> [TypeRep] -> EType+ typeApplication con args = typeApplication' (reverse args)+ where+ typeApplication' [] = ETyCon (ETCon $ tyConName con)+ typeApplication' [x] =+ ETyApp+ (ETyCon $ ETCon $ tyConName con)+ (toElmType' x)+ typeApplication' (x:xs) =+ ETyApp (typeApplication' xs) (toElmType' x)
test/Elm/DeriveSpec.hs view
@@ -39,12 +39,17 @@ = Okay Int | NotOkay a +data Simple+ = SimpleA+ | SimpleB+ deriveElmDef defaultOptions ''Foo deriveElmDef defaultOptions ''Bar deriveElmDef defaultOptions ''SomeOpts deriveElmDef defaultOptions { fieldLabelModifier = drop 1 . map toLower } ''Baz deriveElmDef defaultOptions { fieldLabelModifier = drop 1 . map toLower } ''Test deriveElmDef defaultOptions { fieldLabelModifier = drop 4 . map toLower, sumEncoding = TaggedObject "key" "value" } ''Qux+deriveElmDef defaultOptions { constructorTagModifier = drop 6 . map toLower} ''Simple testElm :: ETypeDef testElm = ETypeAlias $ EAlias@@ -101,10 +106,10 @@ bazElm :: ETypeDef bazElm = ETypeSum $ ESum { es_name = ETypeName {et_name = "Baz", et_args = [ETVar {tv_name = "a"}]}- , es_options =- [ ("Baz1",Left [("foo",ETyCon (ETCon {tc_name = "Int"})), ("qux",ETyVar (ETVar {tv_name = "a"}))])- , ("Baz2",Left [("bar",ETyCon (ETCon {tc_name = "Int"})), ("str",ETyCon (ETCon {tc_name = "String"}))])- , ("Zob",Right [ETyVar (ETVar {tv_name = "a"})])+ , es_constructors =+ [ STC "Baz1" "Baz1" (Named [("foo",ETyCon (ETCon {tc_name = "Int"})), ("qux",ETyVar (ETVar {tv_name = "a"}))])+ , STC "Baz2" "Baz2" (Named [("bar",ETyCon (ETCon {tc_name = "Int"})), ("str",ETyCon (ETCon {tc_name = "String"}))])+ , STC "Zob" "Zob" (Anonymous [ETyVar (ETVar {tv_name = "a"})]) ] , es_type = SumEncoding' ObjectWithSingleField , es_omit_null = False@@ -114,9 +119,9 @@ quxElm :: ETypeDef quxElm = ETypeSum $ ESum { es_name = ETypeName {et_name = "Qux", et_args = [ETVar {tv_name = "a"}]}- , es_options =- [ ("Qux1",Left [("foo",ETyCon (ETCon {tc_name = "Int"})), ("qux",ETyVar (ETVar {tv_name = "a"}))])- , ("Qux2",Left [("bar",ETyCon (ETCon {tc_name = "Int"})), ("str",ETyCon (ETCon {tc_name = "String"}))])+ , es_constructors =+ [ STC "Qux1" "Qux1" (Named [("foo",ETyCon (ETCon {tc_name = "Int"})), ("qux",ETyVar (ETVar {tv_name = "a"}))])+ , STC "Qux2" "Qux2" (Named [("bar",ETyCon (ETCon {tc_name = "Int"})), ("str",ETyCon (ETCon {tc_name = "String"}))]) ] , es_type = SumEncoding' $ TaggedObject "key" "value" , es_omit_null = False@@ -132,15 +137,24 @@ { et_name = "SomeOpts" , et_args = [ETVar {tv_name = "a"}] }- , es_options =- [ ("Okay", Right [ETyCon (ETCon {tc_name = "Int"})])- , ("NotOkay", Right [ETyVar (ETVar {tv_name = "a"})])+ , es_constructors =+ [ STC "Okay" "Okay" (Anonymous [ETyCon (ETCon {tc_name = "Int"})])+ , STC "NotOkay" "NotOkay" (Anonymous [ETyVar (ETVar {tv_name = "a"})]) ] , es_type = defSumEncoding , es_omit_null = False , es_unary_strings = True } +simpleElm :: ETypeDef+simpleElm = ETypeSum $+ ESum+ { es_name = ETypeName {et_name = "Simple", et_args = []}, es_constructors = [STC "SimpleA" "a" (Anonymous []),STC "SimpleB" "b" (Anonymous [])]+ , es_type = SumEncoding' ObjectWithSingleField+ , es_omit_null = False+ , es_unary_strings = True+ }+ spec :: Spec spec = describe "deriveElmRep" $@@ -151,3 +165,4 @@ compileElmDef (Proxy :: Proxy (Baz a)) `shouldBe` bazElm compileElmDef (Proxy :: Proxy (Qux a)) `shouldBe` quxElm compileElmDef (Proxy :: Proxy (Test a)) `shouldBe` testElm+ compileElmDef (Proxy :: Proxy Simple) `shouldBe` simpleElm
test/Elm/JsonSpec.hs view
@@ -2,13 +2,14 @@ module Elm.JsonSpec (spec) where import Elm.Derive+import Elm.TyRender import Elm.TyRep import Elm.Json import Data.Proxy import Test.Hspec import Data.Char (toLower)-import Data.Aeson.Types (SumEncoding(..),defaultTaggedObject)+import Data.Aeson.Types (defaultTaggedObject) import qualified Data.Map.Strict as M import qualified Data.Aeson.TH as TH @@ -53,6 +54,11 @@ newtype NTC = NTC Int newtype NTD = NTD { getNtd :: Int } +newtype PhantomA a = PhantomA Int+newtype PhantomB a = PhantomB { getPhantomB :: Int }+newtype PhantomC a = PhantomC Int+newtype PhantomD a = PhantomD { getPhantomD :: Int }+ $(deriveElmDef (defaultOptionsDropLower 2) ''Foo) $(deriveElmDef (defaultOptionsDropLower 2) ''Bar) $(deriveElmDef (defaultOptionsDropLower 1) ''TestComp)@@ -67,6 +73,10 @@ $(deriveElmDef defaultOptions ''NTB) $(deriveElmDef defaultOptions { unwrapUnaryRecords = False } ''NTC) $(deriveElmDef defaultOptions { unwrapUnaryRecords = False } ''NTD)+$(deriveElmDef defaultOptions ''PhantomA)+$(deriveElmDef defaultOptions ''PhantomB)+$(deriveElmDef defaultOptions { unwrapUnaryRecords = False } ''PhantomC)+$(deriveElmDef defaultOptions { unwrapUnaryRecords = False } ''PhantomD) fooSer :: String fooSer = "jsonEncFoo : Foo -> Value\njsonEncFoo val =\n Json.Encode.object\n [ (\"name\", Json.Encode.string val.name)\n , (\"blablub\", Json.Encode.int val.blablub)\n ]\n"@@ -75,9 +85,9 @@ fooParse = unlines [ "jsonDecFoo : Json.Decode.Decoder ( Foo )" , "jsonDecFoo ="- , " (\"name\" := Json.Decode.string) >>= \\pname ->"- , " (\"blablub\" := Json.Decode.int) >>= \\pblablub ->"- , " Json.Decode.succeed {name = pname, blablub = pblablub}"+ , " Json.Decode.succeed (\\pname pblablub -> {name = pname, blablub = pblablub})"+ , " |> required \"name\" (Json.Decode.string)"+ , " |> required \"blablub\" (Json.Decode.int)" ] barSer :: String@@ -87,8 +97,8 @@ , " Json.Encode.object" , " [ (\"name\", localEncoder_a val.name)" , " , (\"blablub\", Json.Encode.int val.blablub)"- , " , (\"tuple\", (\\(v1,v2) -> Json.Encode.list [(Json.Encode.int) v1,(Json.Encode.string) v2]) val.tuple)"- , " , (\"list\", (Json.Encode.list << List.map Json.Encode.bool) val.list)"+ , " , (\"tuple\", (\\(v1,v2) -> Json.Encode.list identity [(Json.Encode.int) v1,(Json.Encode.string) v2]) val.tuple)"+ , " , (\"list\", (Json.Encode.list Json.Encode.bool) val.list)" , " ]" ] @@ -107,11 +117,11 @@ barParse = unlines [ "jsonDecBar : Json.Decode.Decoder a -> Json.Decode.Decoder ( Bar a )" , "jsonDecBar localDecoder_a ="- , " (\"name\" := localDecoder_a) >>= \\pname ->"- , " (\"blablub\" := Json.Decode.int) >>= \\pblablub ->"- , " (\"tuple\" := Json.Decode.map2 (,) (Json.Decode.index 0 (Json.Decode.int)) (Json.Decode.index 1 (Json.Decode.string))) >>= \\ptuple ->"- , " (\"list\" := Json.Decode.list (Json.Decode.bool)) >>= \\plist ->"- , " Json.Decode.succeed {name = pname, blablub = pblablub, tuple = ptuple, list = plist}"+ , " Json.Decode.succeed (\\pname pblablub ptuple plist -> {name = pname, blablub = pblablub, tuple = ptuple, list = plist})"+ , " |> required \"name\" (localDecoder_a)"+ , " |> required \"blablub\" (Json.Decode.int)"+ , " |> required \"tuple\" (Json.Decode.map2 tuple2 (Json.Decode.index 0 (Json.Decode.int)) (Json.Decode.index 1 (Json.Decode.string)))"+ , " |> required \"list\" (Json.Decode.list (Json.Decode.bool))" ] bazParse :: String@@ -119,8 +129,8 @@ [ "jsonDecBaz : Json.Decode.Decoder a -> Json.Decode.Decoder ( Baz a )" , "jsonDecBaz localDecoder_a =" , " let jsonDecDictBaz = Dict.fromList"- , " [ (\"Baz1\", Json.Decode.lazy (\\_ -> Json.Decode.map Baz1 ( (\"foo\" := Json.Decode.int) >>= \\pfoo -> (\"qux\" := jsonDecMap (Json.Decode.int) (localDecoder_a)) >>= \\pqux -> Json.Decode.succeed {foo = pfoo, qux = pqux})))"- , " , (\"Baz2\", Json.Decode.lazy (\\_ -> Json.Decode.map Baz2 ( (Json.Decode.maybe (\"bar\" := Json.Decode.int)) >>= \\pbar -> (\"str\" := Json.Decode.string) >>= \\pstr -> Json.Decode.succeed {bar = pbar, str = pstr})))"+ , " [ (\"Baz1\", Json.Decode.lazy (\\_ -> Json.Decode.map Baz1 ( Json.Decode.succeed (\\pfoo pqux -> {foo = pfoo, qux = pqux}) |> required \"foo\" (Json.Decode.int) |> required \"qux\" (jsonDecMap (Json.Decode.int) (localDecoder_a)))))"+ , " , (\"Baz2\", Json.Decode.lazy (\\_ -> Json.Decode.map Baz2 ( Json.Decode.succeed (\\pbar pstr -> {bar = pbar, str = pstr}) |> fnullable \"bar\" (Json.Decode.int) |> required \"str\" (Json.Decode.string))))" , " , (\"Testing\", Json.Decode.lazy (\\_ -> Json.Decode.map Testing (jsonDecBaz (localDecoder_a))))" , " ]" , " in decodeSumObjectWithSingleField \"Baz\" jsonDecDictBaz"@@ -151,9 +161,9 @@ test1Parse = unlines [ "jsonDecTestComp : Json.Decode.Decoder a -> Json.Decode.Decoder ( TestComp a )" , "jsonDecTestComp localDecoder_a ="- , " (\"t1\" := jsonDecChange (Json.Decode.int)) >>= \\pt1 ->"- , " (\"t2\" := jsonDecChange (localDecoder_a)) >>= \\pt2 ->"- , " Json.Decode.succeed {t1 = pt1, t2 = pt2}"+ , " Json.Decode.succeed (\\pt1 pt2 -> {t1 = pt1, t2 = pt2})"+ , " |> required \"t1\" (jsonDecChange (Json.Decode.int))"+ , " |> required \"t2\" (jsonDecChange (localDecoder_a))" ] unaryAParse :: String@@ -180,8 +190,8 @@ [ "jsonEncUnaryA : UnaryA -> Value" , "jsonEncUnaryA val =" , " let keyval v = case v of"- , " UnaryA1 -> (\"UnaryA1\", encodeValue (Json.Encode.list []))"- , " UnaryA2 -> (\"UnaryA2\", encodeValue (Json.Encode.list []))"+ , " UnaryA1 -> (\"UnaryA1\", encodeValue (Json.Encode.list identity []))"+ , " UnaryA2 -> (\"UnaryA2\", encodeValue (Json.Encode.list identity []))" , " in encodeSumObjectWithSingleField keyval val" ] @@ -243,10 +253,36 @@ ntdParse = unlines [ "jsonDecNTD : Json.Decode.Decoder ( NTD )" , "jsonDecNTD ="- , " (\"getNtd\" := Json.Decode.int) >>= \\pgetNtd ->"- , " Json.Decode.succeed (NTD {getNtd = pgetNtd})"+ , " Json.Decode.succeed (\\pgetNtd -> (NTD {getNtd = pgetNtd}))"+ , " |> required \"getNtd\" (Json.Decode.int)" ] +phantomAParse :: String+phantomAParse = unlines+ [ "jsonDecPhantomA : Json.Decode.Decoder a -> Json.Decode.Decoder ( PhantomA a )"+ , "jsonDecPhantomA localDecoder_a ="+ , " Json.Decode.int"+ ]+phantomBParse :: String+phantomBParse = unlines+ [ "jsonDecPhantomB : Json.Decode.Decoder a -> Json.Decode.Decoder ( PhantomB a )"+ , "jsonDecPhantomB localDecoder_a ="+ , " Json.Decode.int"+ ]+phantomCParse :: String+phantomCParse = unlines+ [ "jsonDecPhantomC : Json.Decode.Decoder a -> Json.Decode.Decoder ( PhantomC a )"+ , "jsonDecPhantomC localDecoder_a ="+ , " Json.Decode.int"+ ]+phantomDParse :: String+phantomDParse = unlines+ [ "jsonDecPhantomD : Json.Decode.Decoder a -> Json.Decode.Decoder ( PhantomD a )"+ , "jsonDecPhantomD localDecoder_a ="+ , " Json.Decode.succeed (\\pgetPhantomD -> (PhantomD {getPhantomD = pgetPhantomD}))"+ , " |> required \"getPhantomD\" (Json.Decode.int)"+ ]+ spec :: Spec spec = describe "json serialisation" $@@ -264,6 +300,10 @@ rNTB = compileElmDef (Proxy :: Proxy NTB) rNTC = compileElmDef (Proxy :: Proxy NTC) rNTD = compileElmDef (Proxy :: Proxy NTD)+ rPhantomA = compileElmDef (Proxy :: Proxy (PhantomA a))+ rPhantomB = compileElmDef (Proxy :: Proxy (PhantomB a))+ rPhantomC = compileElmDef (Proxy :: Proxy (PhantomC a))+ rPhantomD = compileElmDef (Proxy :: Proxy (PhantomD a)) it "should produce the correct ser code" $ do jsonSerForDef rFoo `shouldBe` fooSer jsonSerForDef rBar `shouldBe` barSer@@ -292,3 +332,8 @@ it "should produce the correct parse code for newtypes with unwrapUnaryRecords=False" $ do jsonParserForDef rNTC `shouldBe` ntcParse jsonParserForDef rNTD `shouldBe` ntdParse+ it "should produce the correct parse code for phantom newtypes" $ do+ jsonParserForDef rPhantomA `shouldBe` phantomAParse+ jsonParserForDef rPhantomB `shouldBe` phantomBParse+ jsonParserForDef rPhantomC `shouldBe` phantomCParse+ jsonParserForDef rPhantomD `shouldBe` phantomDParse
test/Elm/ModuleSpec.hs view
@@ -5,7 +5,6 @@ import Elm.Module import Elm.Versions - import Data.Map (Map) import Data.Proxy import Test.Hspec@@ -37,8 +36,8 @@ , "import Json.Encode exposing (Value)" , "-- The following module comes from bartavelle/json-helpers" , "import Json.Helpers exposing (..)"- , "import Dict"- , "import Set"+ , "import Dict exposing (Dict)"+ , "import Set exposing (Set)" , "" , "" , "type alias Bar a ="@@ -51,21 +50,21 @@ , "" , "jsonDecBar : Json.Decode.Decoder a -> Json.Decode.Decoder ( Bar a )" , "jsonDecBar localDecoder_a ="- , " (\"name\" := localDecoder_a) >>= \\pname ->"- , " (\"blablub\" := Json.Decode.int) >>= \\pblablub ->"- , " (\"tuple\" := Json.Decode.map2 (,) (Json.Decode.index 0 (Json.Decode.int)) (Json.Decode.index 1 (Json.Decode.string))) >>= \\ptuple ->"- , " (\"list\" := Json.Decode.list (Json.Decode.bool)) >>= \\plist ->"- , " (\"list_map\" := Json.Decode.list (Json.Decode.dict (Json.Decode.bool))) >>= \\plist_map ->"- , " Json.Decode.succeed {name = pname, blablub = pblablub, tuple = ptuple, list = plist, list_map = plist_map}"+ , " Json.Decode.succeed (\\pname pblablub ptuple plist plist_map -> {name = pname, blablub = pblablub, tuple = ptuple, list = plist, list_map = plist_map})"+ , " |> required \"name\" (localDecoder_a)"+ , " |> required \"blablub\" (Json.Decode.int)"+ , " |> required \"tuple\" (Json.Decode.map2 tuple2 (Json.Decode.index 0 (Json.Decode.int)) (Json.Decode.index 1 (Json.Decode.string)))"+ , " |> required \"list\" (Json.Decode.list (Json.Decode.bool))"+ , " |> required \"list_map\" (Json.Decode.list (Json.Decode.dict (Json.Decode.bool)))" , "" , "jsonEncBar : (a -> Value) -> Bar a -> Value" , "jsonEncBar localEncoder_a val =" , " Json.Encode.object" , " [ (\"name\", localEncoder_a val.name)" , " , (\"blablub\", Json.Encode.int val.blablub)"- , " , (\"tuple\", (\\(v1,v2) -> Json.Encode.list [(Json.Encode.int) v1,(Json.Encode.string) v2]) val.tuple)"- , " , (\"list\", (Json.Encode.list << List.map Json.Encode.bool) val.list)"- , " , (\"list_map\", (Json.Encode.list << List.map (encodeMap (Json.Encode.string) (Json.Encode.bool))) val.list_map)"+ , " , (\"tuple\", (\\(v1,v2) -> Json.Encode.list identity [(Json.Encode.int) v1,(Json.Encode.string) v2]) val.tuple)"+ , " , (\"list\", (Json.Encode.list Json.Encode.bool) val.list)"+ , " , (\"list_map\", (Json.Encode.list (encodeMap (Json.Encode.string) (Json.Encode.bool))) val.list_map)" , " ]" , "" ]@@ -78,8 +77,8 @@ , "import Json.Encode exposing (Value)" , "-- The following module comes from bartavelle/json-helpers" , "import Json.Helpers exposing (..)"- , "import Dict"- , "import Set"+ , "import Dict exposing (Dict)"+ , "import Set exposing (Set)" , "" , "" , "type Qux a ="@@ -90,14 +89,14 @@ , "jsonDecQux localDecoder_a =" , " let jsonDecDictQux = Dict.fromList" , " [ (\"Qux1\", Json.Decode.lazy (\\_ -> Json.Decode.map2 Qux1 (Json.Decode.index 0 (Json.Decode.int)) (Json.Decode.index 1 (Json.Decode.string))))"- , " , (\"Qux2\", Json.Decode.lazy (\\_ -> Json.Decode.map Qux2 ( (\"a\" := Json.Decode.int) >>= \\pa -> (\"test\" := localDecoder_a) >>= \\ptest -> Json.Decode.succeed {a = pa, test = ptest})))"+ , " , (\"Qux2\", Json.Decode.lazy (\\_ -> Json.Decode.map Qux2 ( Json.Decode.succeed (\\pa ptest -> {a = pa, test = ptest}) |> required \"a\" (Json.Decode.int) |> required \"test\" (localDecoder_a))))" , " ]" , " in decodeSumObjectWithSingleField \"Qux\" jsonDecDictQux" , "" , "jsonEncQux : (a -> Value) -> Qux a -> Value" , "jsonEncQux localEncoder_a val =" , " let keyval v = case v of"- , " Qux1 v1 v2 -> (\"Qux1\", encodeValue (Json.Encode.list [Json.Encode.int v1, Json.Encode.string v2]))"+ , " Qux1 v1 v2 -> (\"Qux1\", encodeValue (Json.Encode.list identity [Json.Encode.int v1, Json.Encode.string v2]))" , " Qux2 vs -> (\"Qux2\", encodeObject [(\"a\", Json.Encode.int vs.a), (\"test\", localEncoder_a vs.test)])" , " in encodeSumObjectWithSingleField keyval val" , ""
test/Elm/TyRenderSpec.hs view
@@ -26,9 +26,29 @@ = Okay Int | NotOkay a +data Unit+ = Unit+ { u_unit :: ()+ }++data Paa+ = PA1+ | PA2++newtype PhantomA a = PhantomA Int+newtype PhantomB a = PhantomB { getPhantomB :: Int }+newtype PhantomC a = PhantomC Int+newtype PhantomD a = PhantomD { getPhantomD :: Int }+ $(deriveElmDef (defaultOptionsDropLower 2) ''Foo) $(deriveElmDef (defaultOptionsDropLower 2) ''Bar) $(deriveElmDef defaultOptions ''SomeOpts)+$(deriveElmDef defaultOptions ''Unit)+$(deriveElmDef defaultOptions{allNullaryToStringTag = True, constructorTagModifier = drop 1} ''Paa)+$(deriveElmDef defaultOptions ''PhantomA)+$(deriveElmDef defaultOptions ''PhantomB)+$(deriveElmDef defaultOptions { unwrapUnaryRecords = False } ''PhantomC)+$(deriveElmDef defaultOptions { unwrapUnaryRecords = False } ''PhantomD) fooCode :: String fooCode = "type alias Foo =\n { name: String\n , blablub: Int\n }\n"@@ -39,13 +59,44 @@ someOptsCode :: String someOptsCode = "type SomeOpts a =\n Okay Int\n | NotOkay a\n" +unitCode :: String+unitCode = "type alias Unit =\n { u_unit: ()\n }\n"++paaCode :: String+paaCode = unlines+ [ "type Paa ="+ , " PA1 "+ , " | PA2 "+ ]++phantomATy :: String+phantomATy = "type alias PhantomA a = Int\n"+phantomBTy :: String+phantomBTy = "type alias PhantomB a = Int\n"+phantomCTy :: String+phantomCTy = "type alias PhantomC a = Int\n"+phantomDTy :: String+phantomDTy = "type PhantomD a = PhantomD\n { getPhantomD: Int\n }\n"+ spec :: Spec spec = describe "deriveElmRep" $ do let rFoo = compileElmDef (Proxy :: Proxy Foo) rBar = compileElmDef (Proxy :: Proxy (Bar a)) rSomeOpts = compileElmDef (Proxy :: Proxy (SomeOpts a))+ rUnit = compileElmDef (Proxy :: Proxy Unit)+ rPaa = compileElmDef (Proxy :: Proxy Paa)+ rPhA = compileElmDef (Proxy :: Proxy (PhantomA a))+ rPhB = compileElmDef (Proxy :: Proxy (PhantomB a))+ rPhC = compileElmDef (Proxy :: Proxy (PhantomC a))+ rPhD = compileElmDef (Proxy :: Proxy (PhantomD a)) it "should produce the correct code" $ do renderElm rFoo `shouldBe` fooCode renderElm rBar `shouldBe` barCode renderElm rSomeOpts `shouldBe` someOptsCode+ renderElm rUnit `shouldBe` unitCode+ renderElm rPaa `shouldBe` paaCode+ renderElm rPhA `shouldBe` phantomATy+ renderElm rPhB `shouldBe` phantomBTy+ renderElm rPhC `shouldBe` phantomCTy+ renderElm rPhD `shouldBe` phantomDTy
test/EndToEnd.hs view
@@ -110,7 +110,7 @@ ++ [" ]"] ) where- mktest (n,e) = pfix ++ "test \"" ++ show n ++ "\" (\\_ -> equalHack " ++ encoded ++ "(Json.Encode.encode 0 (jsonEnc" ++ pred ++ num ++ "(Json.Encode.list << List.map Json.Encode.int) (" ++ pretty ++ "))))"+ mktest (n,e) = pfix ++ "test \"" ++ show n ++ "\" (\\_ -> equalHack " ++ encoded ++ "(Json.Encode.encode 0 (jsonEnc" ++ pred ++ num ++ "(Json.Encode.list Json.Encode.int) (" ++ pretty ++ "))))" where pretty = T.unpack $ T.replace (T.pack (prefix ++ num)) T.empty $ T.pack $ show e encoded = show (encode e)@@ -230,21 +230,19 @@ elmModuleContent :: String elmModuleContent = unlines- [ "-- This module requires the following packages:"- , "-- * elm-community/elm-test"- , "-- * elm-community/html-test-runner"+ [ "module MyTests exposing (..)"+ , "-- This module requires the following packages:" , "-- * bartavelle/json-helpers"- , "module MyTests exposing (..)"+ , "-- * NoRedInk/elm-json-decode-pipeline" , "" , "import Dict exposing (Dict)"+ , "import Expect exposing (Expectation, equal)" , "import Set exposing (Set)" , "import Json.Decode exposing (field, Value)" , "import Json.Encode" , "import Json.Helpers exposing (..)"- , "import Test exposing (..)"- , "import Expect exposing (..)" , "import String"- , "import Test.Runner.Html"+ , "import Test exposing (Test, describe, test)" , "" , "newtypeDecode : Test" , "newtypeDecode = describe \"Newtype decoding checks\""@@ -338,8 +336,6 @@ , " let remix = Json.Decode.decodeString Json.Decode.value" , " in equal (remix a) (remix b)" , ""- , "main : Test.Runner.Html.TestProgram"- , "main = concat [newtypeDecode, newtypeEncode, recordDecode, recordEncode, sumDecode, sumEncode, simpleDecode, simpleEncode ] |> Test.Runner.Html.run" , "" , makeModuleContentWithAlterations (newtypeAliases ["Record1", "Record2", "SimpleRecord01", "SimpleRecord02", "SimpleRecord03", "SimpleRecord04"] . defaultAlterations) [ DefineElm (Proxy :: Proxy (Record1 a))@@ -460,6 +456,6 @@ , mkDecodeTestNT "NT" "_nt" "3" extractNT3 nt3 , mkEncodeTestNT "NT" "_nt" "3" extractNT3 nt3 , dropAll "(Json.Decode.list Json.Decode.int)" (mkDecodeTest "NT" "_nt" "4" nt4)- , dropAll "(Json.Encode.list << List.map Json.Encode.int)" (mkEncodeTest "NT" "_nt" "4" nt4)+ , dropAll "(Json.Encode.list Json.Encode.int)" (mkEncodeTest "NT" "_nt" "4" nt4) ]