ocaml-export 0.2.0.0 → 0.3.0.0
raw patch · 13 files changed
+165/−296 lines, 13 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ OCaml.BuckleScript.Internal.Module: instance (OCaml.BuckleScript.Internal.Module.HasEmbeddedFile' a, OCaml.BuckleScript.Internal.Module.HasEmbeddedFile' b) => OCaml.BuckleScript.Internal.Module.HasEmbeddedFile' (a Servant.API.Alternative.:<|> b)
+ OCaml.BuckleScript.Internal.Module: instance GHC.Show.Show OCaml.BuckleScript.Internal.Module.EmbeddedOCamlFiles
+ OCaml.BuckleScript.Types: oCamlValueIsFloat :: OCamlValue -> Bool
Files
- ocaml-export.cabal +3/−3
- src/OCaml/BuckleScript/Decode.hs +46/−44
- src/OCaml/BuckleScript/Encode.hs +9/−9
- src/OCaml/BuckleScript/Internal/Module.hs +6/−6
- src/OCaml/BuckleScript/Types.hs +7/−0
- test/Dependency.hs +0/−37
- test/File.hs +1/−12
- test/FileApp.hs +1/−5
- test/Product.hs +42/−69
- test/ProductApp.hs +37/−0
- test/Spec.hs +6/−61
- test/Sum.hs +5/−5
- test/Util.hs +2/−45
ocaml-export.cabal view
@@ -3,7 +3,7 @@ -- see: https://github.com/sol/hpack name: ocaml-export-version: 0.2.0.0+version: 0.3.0.0 synopsis: Convert Haskell types in OCaml types description: README.md category: Web@@ -24,7 +24,7 @@ library hs-source-dirs: src- ghc-options: -Wall -Wredundant-constraints -fprint-potential-instances+ ghc-options: -Wall build-depends: base >= 4.7 && < 5 , aeson@@ -66,7 +66,7 @@ main-is: Spec.hs hs-source-dirs: test- ghc-options: -fprint-potential-instances+ ghc-options: -Wall build-depends: base , aeson
src/OCaml/BuckleScript/Decode.hs view
@@ -235,7 +235,7 @@ case Map.lookup typeRef ds of Just parOCamlTypeMetaData -> do let prefix = stext $ mkModulePrefix decOCamlTypeMetaData parOCamlTypeMetaData- pure $ "(fun a -> unwrapResult (" <> prefix <> "decode" <> (stext . textUppercaseFirst $ name) <+> "a))" + pure $ "(fun a -> unwrapResult (" <> prefix <> "decode" <> (stext . textUppercaseFirst $ name) <+> "a))" -- in case of a Haskell sum of products, ocaml-export creates a definition for each product -- within the same file as the sum. These products will not be in the dependencies map.@@ -267,81 +267,83 @@ instance HasDecoder EnumeratorConstructor where render (EnumeratorConstructor name) = pure $ "| Some \"" <> stext name <> "\" -> Js_result.Ok" <+> stext name- + instance HasDecoderRef OCamlPrimitive where renderRef OUnit = pure $ parens "()" renderRef ODate = pure "date" renderRef OInt = pure "int" renderRef OBool = pure "bool" renderRef OChar = pure "char"- renderRef OFloat = pure "float"+ renderRef OFloat = pure "Aeson.Decode.float" -- this is to prevent overshadowing warning renderRef OString = pure "string"- renderRef (OList (OCamlPrimitive OChar)) = pure "string" - renderRef (OList datatype@(OCamlDatatype typeRef name _)) =- if isTypeParameterRef datatype- then- pure . parens $ "list" <+> (parens $ "fun a -> unwrapResult (decode" <> (stext . textUppercaseFirst $ name) <+> "a)")- else do- mOCamlTypeMetaData <- asks topLevelOCamlTypeMetaData- case mOCamlTypeMetaData of- Nothing -> fail $ "OCaml.BuckleScript.Decode (HasDecoderRef (OList (OCamlDatatype typeRep name _))) mOCamlTypeMetaData is Nothing:\n\n" ++ (show datatype)- Just decOCamlTypeMetaData -> do- ds <- asks (dependencies . userOptions)- case Map.lookup typeRef ds of- Just parOCamlTypeMetaData -> do- let prefix = stext $ mkModulePrefix decOCamlTypeMetaData parOCamlTypeMetaData- pure . parens $ "list" <+> (parens $ "fun a -> unwrapResult (" <> prefix <> "decode" <> (stext . textUppercaseFirst $ name) <+> "a)")- Nothing -> fail ("OCaml.BuckleScript.Decode (HasDecoderRef (OList (OCamlDatatype typeRep name _))) expected to find dependency:\n\n" ++ show typeRef ++ "\n\nin\n\n" ++ show ds)- renderRef (OList datatype) = do- dt <- renderRef datatype+ dt <- renderRefWithUnwrapResult datatype pure . parens $ "list" <+> dt renderRef (OOption _) = pure "" renderRef (OEither v0 v1) = do- dv0 <- renderRef v0- dv1 <- renderRef v1+ dv0 <- renderRefWithUnwrapResult v0+ dv1 <- renderRefWithUnwrapResult v1 pure $ parens $ "either" <+> dv0 <+> dv1 renderRef (OTuple2 v0 v1) = do- dv0 <- renderRef v0- dv1 <- renderRef v1+ dv0 <- renderRefWithUnwrapResult v0+ dv1 <- renderRefWithUnwrapResult v1 pure $ parens $ "pair" <+> dv0 <+> dv1 renderRef (OTuple3 v0 v1 v2) = do- dv0 <- renderRef v0- dv1 <- renderRef v1- dv2 <- renderRef v2+ dv0 <- renderRefWithUnwrapResult v0+ dv1 <- renderRefWithUnwrapResult v1+ dv2 <- renderRefWithUnwrapResult v2 pure $ parens $ "tuple3" <+> dv0 <+> dv1 <+> dv2 renderRef (OTuple4 v0 v1 v2 v3) = do- dv0 <- renderRef v0- dv1 <- renderRef v1- dv2 <- renderRef v2- dv3 <- renderRef v3+ dv0 <- renderRefWithUnwrapResult v0+ dv1 <- renderRefWithUnwrapResult v1+ dv2 <- renderRefWithUnwrapResult v2+ dv3 <- renderRefWithUnwrapResult v3 pure $ parens $ "tuple4" <+> dv0 <+> dv1 <+> dv2 <+> dv3 renderRef (OTuple5 v0 v1 v2 v3 v4) = do- dv0 <- renderRef v0- dv1 <- renderRef v1- dv2 <- renderRef v2- dv3 <- renderRef v3- dv4 <- renderRef v4+ dv0 <- renderRefWithUnwrapResult v0+ dv1 <- renderRefWithUnwrapResult v1+ dv2 <- renderRefWithUnwrapResult v2+ dv3 <- renderRefWithUnwrapResult v3+ dv4 <- renderRefWithUnwrapResult v4 pure $ parens $ "tuple5" <+> dv0 <+> dv1 <+> dv2 <+> dv3 <+> dv4 renderRef (OTuple6 v0 v1 v2 v3 v4 v5) = do- dv0 <- renderRef v0- dv1 <- renderRef v1- dv2 <- renderRef v2- dv3 <- renderRef v3- dv4 <- renderRef v4- dv5 <- renderRef v5+ dv0 <- renderRefWithUnwrapResult v0+ dv1 <- renderRefWithUnwrapResult v1+ dv2 <- renderRefWithUnwrapResult v2+ dv3 <- renderRefWithUnwrapResult v3+ dv4 <- renderRefWithUnwrapResult v4+ dv5 <- renderRefWithUnwrapResult v5 pure $ parens $ "tuple6" <+> dv0 <+> dv1 <+> dv2 <+> dv3 <+> dv4 <+> dv5 -- Util++renderRefWithUnwrapResult :: OCamlDatatype -> Reader TypeMetaData Doc+renderRefWithUnwrapResult datatype@(OCamlDatatype typeRef name _) = do+ if isTypeParameterRef datatype+ then+ pure . parens $ "fun a -> unwrapResult (decode" <> (stext . textUppercaseFirst $ name) <+> "a)"+ else do+ mOCamlTypeMetaData <- asks topLevelOCamlTypeMetaData+ case mOCamlTypeMetaData of+ Nothing -> fail $ "OCaml.BuckleScript.Decode.renderRefWithUnwrapResult mOCamlTypeMetaData is Nothing:\n\n" ++ (show datatype)+ Just decOCamlTypeMetaData -> do+ ds <- asks (dependencies . userOptions)+ case Map.lookup typeRef ds of+ Just parOCamlTypeMetaData -> do+ let prefix = stext $ mkModulePrefix decOCamlTypeMetaData parOCamlTypeMetaData+ pure . parens $ "fun a -> unwrapResult (" <> prefix <> "decode" <> (stext . textUppercaseFirst $ name) <+> "a)"+ Nothing -> fail ("OCaml.BuckleScript.Decode.renderRefWithUnwrapResult expected to find dependency:\n\n" ++ show typeRef ++ "\n\nin\n\n" ++ show ds)+renderRefWithUnwrapResult ref = renderRef ref+ -- | "<name>" -> decode <name> renderSumCondition :: T.Text -> Doc -> Reader TypeMetaData Doc@@ -428,7 +430,7 @@ renderedVal <- render x' renderedInternal <- mk name (i+1) xs let iDoc = (stext . T.pack . show $ i)- pure $ indent 1 $ "(match Aeson.Decode." <> renderedVal <+> ("v." <> parens iDoc) <+> "with"+ pure $ indent 1 $ "(match" <+> (if oCamlValueIsFloat x' then "" else "Aeson.Decode.") <> renderedVal <+> ("v." <> parens iDoc) <+> "with" <$$> indent 1 ("| v" <> iDoc <+> "->" <$$> (indent 2 renderedInternal)
src/OCaml/BuckleScript/Encode.hs view
@@ -13,7 +13,7 @@ {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ScopedTypeVariables #-} -module OCaml.BuckleScript.Encode +module OCaml.BuckleScript.Encode ( toOCamlEncoderSourceWith , toOCamlEncoderInterfaceWith ) where@@ -339,34 +339,34 @@ renderRef (OList datatype) = do dd <- renderRef datatype- return . parens $ "Aeson.Encode.list" <+> dd+ pure . parens $ "Aeson.Encode.list" <+> dd renderRef (OOption datatype) = do dd <- renderRef datatype- return $ "Aeson.Encode.optional" <+> dd+ pure . parens $ "Aeson.Encode.optional" <+> dd renderRef (OEither t0 t1) = do dt0 <- renderRef t0 dt1 <- renderRef t1- return $ "Aeson.Encode.either" <+> dt0 <+> dt1+ pure . parens $ "Aeson.Encode.either" <+> dt0 <+> dt1 renderRef (OTuple2 t0 t1) = do dt0 <- renderRef t0 dt1 <- renderRef t1- return $ "Aeson.Encode.pair" <+> dt0 <+> dt1+ pure . parens $ "Aeson.Encode.pair" <+> dt0 <+> dt1 renderRef (OTuple3 t0 t1 t2) = do dt0 <- renderRef t0 dt1 <- renderRef t1 dt2 <- renderRef t2- return $ "Aeson.Encode.tuple3" <+> dt0 <+> dt1 <+> dt2+ pure . parens $ "Aeson.Encode.tuple3" <+> dt0 <+> dt1 <+> dt2 renderRef (OTuple4 t0 t1 t2 t3) = do dt0 <- renderRef t0 dt1 <- renderRef t1 dt2 <- renderRef t2 dt3 <- renderRef t3- return $ "Aeson.Encode.tuple4" <+> dt0 <+> dt1 <+> dt2 <+> dt3+ pure . parens $ "Aeson.Encode.tuple4" <+> dt0 <+> dt1 <+> dt2 <+> dt3 renderRef (OTuple5 t0 t1 t2 t3 t4) = do dt0 <- renderRef t0@@ -374,7 +374,7 @@ dt2 <- renderRef t2 dt3 <- renderRef t3 dt4 <- renderRef t4- return $ "Aeson.Encode.tuple5" <+> dt0 <+> dt1 <+> dt2 <+> dt3 <+> dt4+ pure . parens $ "Aeson.Encode.tuple5" <+> dt0 <+> dt1 <+> dt2 <+> dt3 <+> dt4 renderRef (OTuple6 t0 t1 t2 t3 t4 t5) = do dt0 <- renderRef t0@@ -383,7 +383,7 @@ dt3 <- renderRef t3 dt4 <- renderRef t4 dt5 <- renderRef t5- return $ "Aeson.Encode.tuple6" <+> dt0 <+> dt1 <+> dt2 <+> dt3 <+> dt4 <+> dt5+ pure . parens $ "Aeson.Encode.tuple6" <+> dt0 <+> dt1 <+> dt2 <+> dt3 <+> dt4 <+> dt5 -- | Variable names for the members of constructors -- Used in pattern matches
src/OCaml/BuckleScript/Internal/Module.hs view
@@ -65,7 +65,7 @@ import OCaml.BuckleScript.Types -- servant-import Servant.API ((:>))+import Servant.API ((:>), (:<|>)) -- template-haskell import Language.Haskell.TH@@ -106,11 +106,8 @@ { eocDeclaration :: ByteString , eocInterface :: Maybe ByteString , eocSpec :: Maybe ByteString- }----+ } deriving (Show)+ -- ============================================== -- Type Level Functions@@ -215,6 +212,9 @@ -- | Help function for HasEmbeddedFile. class HasEmbeddedFile' api where mkFiles' :: Bool -> Bool -> Proxy api -> Q [Exp]++instance (HasEmbeddedFile' a, HasEmbeddedFile' b) => HasEmbeddedFile' (a :<|> b) where+ mkFiles' includeInterface includeSpec Proxy = (<>) <$> mkFiles' includeInterface includeSpec (Proxy :: Proxy a) <*> mkFiles' includeInterface includeSpec (Proxy :: Proxy b) instance (HasEmbeddedFile' a, HasEmbeddedFile' b) => HasEmbeddedFile' (a :> b) where mkFiles' includeInterface includeSpec Proxy = (<>) <$> mkFiles' includeInterface includeSpec (Proxy :: Proxy a) <*> mkFiles' includeInterface includeSpec (Proxy :: Proxy b)
src/OCaml/BuckleScript/Types.hs view
@@ -50,6 +50,7 @@ , getTypeParameters , isTypeParameterRef , mkModulePrefix+ , oCamlValueIsFloat ) where -- base@@ -562,3 +563,9 @@ zipWithRightRemainder [] bs = ([], bs) zipWithRightRemainder _ab [] = ([], []) zipWithRightRemainder (a:as) (b:bs) = ([(a,b)], []) <> zipWithRightRemainder as bs++-- | BuckleScript has a 'float' type that conflicts when you do 'open Aeson.Decode'+-- float must be appended with 'Aeson.Decode'. +oCamlValueIsFloat :: OCamlValue -> Bool+oCamlValueIsFloat (OCamlPrimitiveRef OFloat) = True+oCamlValueIsFloat _ = False
test/Dependency.hs view
@@ -5,48 +5,22 @@ {-# LANGUAGE TypeOperators #-} module Dependency where- -- base-import Data.Monoid ((<>)) import GHC.Generics (Generic)- -- aeson import Data.Aeson (FromJSON, ToJSON)- -- containers import Data.Map as Map- -- hspec import Test.Hspec---- hspec-aeson-golden-import Test.Aeson.Internal.ADT.GoldenSpecs- -- QuickCheck import Test.QuickCheck- -- quickcheck-arbitrary-adt import Test.QuickCheck.Arbitrary.ADT---- text-import Data.Text (Text)---- time-import Data.Time-import Data.Time.Clock.POSIX- -- ocaml-export import OCaml.Export import Product (ProductPackage, Person)-import Util ---mkGolden :: forall a. (ToADTArbitrary a, ToJSON a) => Proxy a -> IO ()---mkGolden Proxy = mkGoldenFileForType 10 (Proxy :: Proxy a) "test/interface/golden/golden/dependency"----mkGoldenFiles :: IO ()---mkGoldenFiles = do--- mkGolden (Proxy :: Proxy Class)- type DependencyPackage = OCamlPackage "dependency" '[ProductPackage] :> ( OCamlModule '["Class"] :> Class)@@ -58,17 +32,7 @@ type SchoolPackage = OCamlPackage "school" '[DependencyPackage] :> ( OCamlModule '["School"] :> School)-{--data Person = Person- { id :: Int- , name :: Maybe String- } deriving (Show, Eq, Generic, OCamlType, FromJSON, ToJSON) -instance Arbitrary Person where- arbitrary = Person <$> arbitrary <*> arbitrary--instance ToADTArbitrary Person--} data Class = Class { subject :: String , students :: [Person] -- from another package@@ -139,7 +103,6 @@ type SubsPackage = OCamlPackage "subs" NoDependency :> (OCamlModule '["AtoE"] :> A :> (OCamlSubModule "One" :> B :> (OCamlSubModule "Two" :> C) :> D) :> E)--- (OCamlModule '["AtoE"] :> OCamlSubModule '["One"] :> A) spec :: Spec spec = do
test/File.hs view
@@ -7,26 +7,15 @@ {-# LANGUAGE TypeOperators #-} module File where- -- base import Data.Proxy import GHC.Generics (Generic)- -- aeson import Data.Aeson---- hspec-import Test.Hspec---- hspec-golden-aeson-import Test.Aeson.Internal.ADT.GoldenSpecs- -- QuickCheck import Test.QuickCheck- -- quickcheck-arbitrary-adt import Test.QuickCheck.Arbitrary.ADT- -- ocaml-export import OCaml.Export @@ -89,7 +78,7 @@ instance (Arbitrary a, Arbitrary b) => Arbitrary (Wrapper a b) where arbitrary = Wrapper <$> arbitrary <*> arbitrary <*> arbitrary -instance (ToADTArbitrary a, ToADTArbitrary b) => ToADTArbitrary (Wrapper a b)+instance (Arbitrary a, ToADTArbitrary a, Arbitrary b, ToADTArbitrary b) => ToADTArbitrary (Wrapper a b) instance OCamlType (Wrapper TypeParameterRef0 TypeParameterRef1) where toOCamlType _ = typeableToOCamlType (Proxy :: Proxy (Wrapper TypeParameterRef0 TypeParameterRef1))
test/FileApp.hs view
@@ -1,18 +1,13 @@ {-# LANGUAGE DataKinds #-}- {-# LANGUAGE TemplateHaskell #-} module FileApp where- -- containers import qualified Data.Map as Map- -- hspec import Test.Hspec- -- servant-server import Servant- -- ocaml-export import OCaml.Export import File@@ -23,6 +18,7 @@ fileMap :: Map.Map String EmbeddedOCamlFiles fileMap = Map.fromList $(mkFiles True False (Proxy :: Proxy FilePackage)) +compareInterfaceFiles :: FilePath -> SpecWith () compareInterfaceFiles = compareFiles "test/interface" "file" True spec :: Spec
test/Product.hs view
@@ -1,42 +1,25 @@+{-# LANGUAGE DataKinds #-} {-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ScopedTypeVariables #-}--{-# LANGUAGE FlexibleInstances #-}----- for OCaml Module-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE TypeOperators #-}- {-# LANGUAGE TemplateHaskell #-}-+{-# LANGUAGE TypeOperators #-} module Product where- -- base-import Data.Monoid ((<>)) import GHC.Generics--- text-import Data.Text (Text) -- time import Data.Time-import Data.Time.Clock.POSIX--- containers-import qualified Data.Map as Map- -- aeson import Data.Aeson (FromJSON, ToJSON)- -- hspec-import Test.Hspec+import Test.Hspec (SpecWith) -- QuickCheck import Test.QuickCheck -- quickcheck-arbitrary-adt import Test.QuickCheck.Arbitrary.ADT--- hspec-golden-aeson-import Test.Aeson.Internal.ADT.GoldenSpecs -- ocaml-export import OCaml.Export hiding (mkGoldenFiles) import Util@@ -52,59 +35,15 @@ :<|> OCamlModule '["TwoTypeParameters"] :> TwoTypeParameters TypeParameterRef0 TypeParameterRef1 :<|> OCamlModule '["ThreeTypeParameters"] :> Three TypeParameterRef0 TypeParameterRef1 TypeParameterRef2 :<|> OCamlModule '["SubTypeParameter"] :> SubTypeParameter TypeParameterRef0 TypeParameterRef1 TypeParameterRef2- :<|> OCamlModule '["UnnamedProduct"] :> UnnamedProduct)--mkGolden :: forall a. (ToADTArbitrary a, ToJSON a) => Proxy a -> IO ()-mkGolden Proxy = mkGoldenFileForType 10 (Proxy :: Proxy a) "test/interface/golden/golden/product"+ :<|> OCamlModule '["UnnamedProduct"] :> UnnamedProduct+ :<|> OCamlModule '["ComplexProduct"] :> OCamlTypeInFile Simple "test/ocaml/Simple" :> ComplexProduct) -mkGoldenFiles :: IO ()-mkGoldenFiles = do- mkGolden (Proxy :: Proxy SimpleChoice)- mkGolden (Proxy :: Proxy Person)- mkGolden (Proxy :: Proxy Company)- mkGolden (Proxy :: Proxy Suit)- mkGolden (Proxy :: Proxy Card)- mkGolden (Proxy :: Proxy Company2)- mkGolden (Proxy :: Proxy (OneTypeParameter TypeParameterRef0))- mkGolden (Proxy :: Proxy (TwoTypeParameters TypeParameterRef0 TypeParameterRef1))- mkGolden (Proxy :: Proxy (Three TypeParameterRef0 TypeParameterRef1 TypeParameterRef2))- mkGolden (Proxy :: Proxy (SubTypeParameter TypeParameterRef0 TypeParameterRef1 TypeParameterRef2))- mkGolden (Proxy :: Proxy UnnamedProduct)- +compareInterfaceFiles :: FilePath -> SpecWith () compareInterfaceFiles = compareFiles "test/interface" "product" True +compareNoInterfaceFiles :: FilePath -> SpecWith () compareNoInterfaceFiles = compareFiles "test/nointerface" "product" False --spec :: Spec-spec = do- runIO $ mkGoldenFiles- - let dir = "test/interface/temp"- runIO $ mkPackage (Proxy :: Proxy ProductPackage) (PackageOptions dir "product" Map.empty True $ Just $ SpecOptions "__tests__/product" "golden/product" "http://localhost:8081")- - describe "OCaml Declaration with Interface: Product Types" $ do- compareInterfaceFiles "Person"- compareInterfaceFiles "Company"- compareInterfaceFiles "Card"- compareInterfaceFiles "OneTypeParameter"- compareInterfaceFiles "TwoTypeParameters"- compareInterfaceFiles "ThreeTypeParameters"- compareInterfaceFiles "SubTypeParameter"- compareInterfaceFiles "UnnamedProduct"- - let dir2 = "test/nointerface/temp"- runIO $ mkPackage (Proxy :: Proxy ProductPackage) (PackageOptions dir2 "product" Map.empty False Nothing)-- describe "OCaml Declaration without Interface: Product Types" $ do- compareNoInterfaceFiles "Person"- compareNoInterfaceFiles "Company"- compareNoInterfaceFiles "Card"- compareNoInterfaceFiles "OneTypeParameter"- compareNoInterfaceFiles "TwoTypeParameters"- compareNoInterfaceFiles "ThreeTypeParameters"- compareNoInterfaceFiles "SubTypeParameter"- data SimpleChoice = SimpleChoice { choice :: Either String Int@@ -231,3 +170,37 @@ arbitrary = UnnamedProduct <$> arbitrary <*> arbitrary instance ToADTArbitrary UnnamedProduct++data Simple =+ Simple+ { sa :: Int+ , sb :: String+ } deriving (Eq,Show,Generic,FromJSON,ToJSON)++instance OCamlType Simple where+ toOCamlType _ = typeableToOCamlType (Proxy :: Proxy Simple)++instance ToADTArbitrary Simple+instance Arbitrary Simple where+ arbitrary = Simple <$> arbitrary <*> arbitrary++data ComplexProduct =+ ComplexProduct+ { cp0 :: Either Person [Int]+ , cp1 :: [(Int, Either String Double)]+ , cp2 :: [[Int]]+ , cp3 :: Maybe [Int]+ , cp4 :: Either Simple Int+ } deriving (Eq,Show,Generic,OCamlType,FromJSON,ToJSON)++instance Arbitrary ComplexProduct where+ arbitrary = do+ k0 <- choose (1,3)+ v0 <- vector k0++ k1 <- choose (1,3)+ v1 <- vector k1+ + ComplexProduct <$> arbitrary <*> pure v0 <*> pure v1 <*> arbitrary <*> arbitrary++instance ToADTArbitrary ComplexProduct
test/ProductApp.hs view
@@ -4,5 +4,42 @@ import OCaml.Export import Product+-- containers+import qualified Data.Map as Map+-- hspec+import Test.Hspec +fileMap :: Map.Map String EmbeddedOCamlFiles+fileMap = Map.fromList $(mkFiles True False (Proxy :: Proxy ProductPackage))+ $(mkOCamlSpecServer "ProductPackage" (Proxy :: Proxy ProductPackage))++spec :: Spec+spec = do+ runIO $ mkGoldenFiles (Proxy :: Proxy ProductPackage) 10 "test/interface/golden/golden/product" ++ let dir = "test/interface/temp"+ runIO $ mkPackage (Proxy :: Proxy ProductPackage) (PackageOptions dir "product" fileMap True $ Just $ SpecOptions "__tests__/product" "golden/product" "http://localhost:8081")+ + describe "OCaml Declaration with Interface: Product Types" $ do+ compareInterfaceFiles "Person"+ compareInterfaceFiles "Company"+ compareInterfaceFiles "Card"+ compareInterfaceFiles "OneTypeParameter"+ compareInterfaceFiles "TwoTypeParameters"+ compareInterfaceFiles "ThreeTypeParameters"+ compareInterfaceFiles "SubTypeParameter"+ compareInterfaceFiles "UnnamedProduct"+ compareInterfaceFiles "ComplexProduct"+ + let dir2 = "test/nointerface/temp"+ runIO $ mkPackage (Proxy :: Proxy ProductPackage) (PackageOptions dir2 "product" fileMap False Nothing)++ describe "OCaml Declaration without Interface: Product Types" $ do+ compareNoInterfaceFiles "Person"+ compareNoInterfaceFiles "Company"+ compareNoInterfaceFiles "Card"+ compareNoInterfaceFiles "OneTypeParameter"+ compareNoInterfaceFiles "TwoTypeParameters"+ compareNoInterfaceFiles "ThreeTypeParameters"+ compareNoInterfaceFiles "SubTypeParameter"
test/Spec.hs view
@@ -6,76 +6,27 @@ {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TypeOperators #-} --{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveFunctor #-}-{-# LANGUAGE DeriveFoldable #-}-{-# LANGUAGE DeriveTraversable #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE KindSignatures #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE PolyKinds #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE TypeOperators #-}-{-# LANGUAGE UndecidableInstances #-}--import Network.Wai.Handler.Warp-import Network.Wai-import Network.Wai.Middleware.RequestLogger (logStdout)-import System.Process- -- base import Control.Concurrent (forkIO) import Data.Monoid ((<>))-import GHC.TypeLits---- ByteString-import Data.ByteString (unpack)- -- hspec-import Test.Hspec---- hspec-aeson-golden-import Test.Aeson.GenericSpecs----- servant-import Servant---- servant-server-import Servant.API---- text-import Data.Text (Text)-+import Test.Hspec -- ocaml-export-import OCaml.Export import qualified Dependency as D-import qualified File as File import qualified FileApp as File-import qualified Options as Options import qualified Product as Product-import ProductApp+import qualified ProductApp as Product import qualified Sum as Sum import SumApp--logAllMiddleware :: Application -> Request -> (Response -> IO ResponseReceived) -> IO ResponseReceived-logAllMiddleware app req respond = do- d <- requestBody req- print $ requestHeaders req- print $ d- app req respond---- npm start --prefix path/to/your/app+import OCaml.Export+-- warp+import Network.Wai.Handler.Warp main :: IO () main = do hspec Product.spec hspec Sum.spec hspec File.spec--- hspec Options.spec hspec D.spec hspec $@@ -84,14 +35,8 @@ (mkOCamlTypeMetaData (Proxy :: Proxy Product.ProductPackage)) <> (mkOCamlTypeMetaData (Proxy :: Proxy D.DependencyPackageWithoutProduct)) `shouldBe` mkOCamlTypeMetaData (Proxy :: Proxy D.DependencyPackage) --- print $ ocamlPackageTypeCount (Proxy :: Proxy Product.ProductPackage)---- print $ mkOCamlTypeMetaData (Proxy :: Proxy Product.ProductPackage) print $ mkOCamlTypeMetaData (Proxy :: Proxy D.SubsPackage) - _ <- forkIO $ run 8081 productPackageApp+ _ <- forkIO $ run 8081 Product.productPackageApp _ <- forkIO $ run 8082 sumPackageApp run 8083 File.filePackageApp---- curl -i -d '"hi"' -H 'Content-type: application/json' -X POST http://localhost:8081/x/y-
test/Sum.hs view
@@ -1,12 +1,10 @@+{-# LANGUAGE DataKinds #-} {-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE OverloadedStrings #-}--{-# LANGUAGE DataKinds #-}-{-# LANGUAGE TypeOperators #-}- {-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeOperators #-} module Sum where @@ -50,8 +48,10 @@ :<|> OCamlModule '["Result"] :> Result TypeParameterRef0 TypeParameterRef1 :<|> OCamlModule '["NewType"] :> NewType) +compareInterfaceFiles :: FilePath -> SpecWith () compareInterfaceFiles = compareFiles "test/interface" "sum" True +compareNoInterfaceFiles :: FilePath -> SpecWith () compareNoInterfaceFiles = compareFiles "test/nointerface" "sum" False mkGolden :: forall a. (ToADTArbitrary a, ToJSON a) => Proxy a -> IO ()
test/Util.hs view
@@ -1,31 +1,18 @@-module Util where+{-# OPTIONS_GHC -fno-warn-orphans #-} +module Util where -- base import Data.Monoid ((<>)) import Data.Time- -- text import qualified Data.Text.IO as T---- ocaml-export-import OCaml.Export hiding (Options)---import System.Directory (doesFileExist)- -- filepath import System.FilePath.Posix ((</>))- -- hspec import Test.Hspec- -- QuickCheck import Test.QuickCheck --- quickcheck-arbitrary-adt-import Test.QuickCheck.Arbitrary.ADT-import Test.Aeson.Internal.ADT.GoldenSpecs- instance Arbitrary UTCTime where arbitrary = UTCTime <$> (ModifiedJulianDay <$> (2000 +) <$> arbitrary)@@ -38,7 +25,6 @@ adtToPath :: ADT -> FilePath adtToPath Options = "options" - compareFiles :: FilePath -> FilePath -> Bool -> FilePath -> SpecWith () compareFiles rootDir categoryDir compareInterfaceAndSpecFiles typeName = it typeName $ do@@ -60,32 +46,3 @@ goldenPath = rootDir </> "golden" </> categoryDir testSpecPath = rootDir </> "temp" </> "__tests__" </> categoryDir goldenSpecPath = rootDir </> "golden" </> "__tests__" </> categoryDir--{--testOCamlTypeWithInterface :: ADT -> FilePath -> OCamlInterface -> SpecWith ()-testOCamlTypeWithInterface adt typeName ocamlFile =- it typeName $ do- createOCamlFileWithInterface testPath specPath typeName ocamlFile- automated <- T.readFile (testPath <> "/" <> typeName <> ".ml")- handWritten <- T.readFile (goldenPath <> "/" <> typeName <> ".ml")-- automated2 <- T.readFile (testPath <> "/" <> typeName <> ".mli")- handWritten2 <- T.readFile (goldenPath <> "/" <> typeName <> ".mli")-- automated `shouldBe` handWritten- automated2 `shouldBe` handWritten2-- fe <- doesFileExist (specGoldenPath <> "/" <> typeName <> "_spec.ml")- if fe- then do- automated3 <- T.readFile (specPath <> "/" <> typeName <> "_spec.ml")- handWritten3 <- T.readFile (specGoldenPath <> "/" <> typeName <> "_spec.ml")- automated3 `shouldBe` handWritten3- else pure ()- where- adtPath = adtToPath adt- testPath = "test/interface/temp/" <> adtPath- goldenPath = "test/interface/golden/" <> adtPath- specPath = "test/interface/temp/__tests__/" <> adtPath- specGoldenPath = "test/interface/golden/__tests__/" <> adtPath--}