@@ -11,6 +11,7 @@ import Data.Proxy
11
11
import Data.Text (Text )
12
12
import qualified Data.Text as Text
13
13
import Language.Haskell.TH
14
+ import Language.Haskell.TH.Datatype
14
15
15
16
import Servant.TS.Internal (TsTypeable (.. ), TsType (.. ), TsContext (.. ))
16
17
@@ -22,17 +23,19 @@ deriveTsJSON opts name = do
22
23
23
24
deriveTsTypeable :: Options -> Name -> Q [Dec ]
24
25
deriveTsTypeable opts name = do
25
- TyConI (DataD _ _ _ _ cons' _) <- reify name
26
+ DatatypeInfo { datatypeVars = vars
27
+ , datatypeCons = cons } <- reifyDatatype name
26
28
[d |
27
29
instance TsTypeable $(conT name) where
28
- tsTypeRep _ = $(if tagSingleConstructors opts || length cons' > 1
29
- then let mk = if allNullaryToStringTag opts && all isNullaryCons cons' then mkNullaryStringConsE else mkTaggedTypeE
30
- in [| TsUnion <$> sequence $(ListE <$> sequence (mk <$> cons' )) |]
31
- else mkTypeE (head cons' ))
30
+ tsTypeRep _ = $(if tagSingleConstructors opts || length cons > 1
31
+ then let mk = if allNullaryToStringTag opts && all isNullaryCons cons then mkNullaryStringConsE else mkTaggedTypeE
32
+ in [| TsUnion <$> sequence $(ListE <$> sequence (mk <$> cons)) |]
33
+ else mkTypeE (head cons))
32
34
| ]
33
- where mkTypeE :: Con -> Q Exp {- Q (TsContext TsType) -}
34
- mkTypeE (NormalC _ ts) = makeTupleE (mkNormalFieldE <$> ts)
35
- mkTypeE (RecC _ ts) = makeRecordE (mkRecordFieldE <$> ts)
35
+ where mkTypeE :: ConstructorInfo -> Q Exp {- Q (TsContext TsType) -}
36
+ mkTypeE c = case constructorVariant c of
37
+ NormalConstructor -> makeTupleE (mkNormalFieldE <$> constructorFields c)
38
+ RecordConstructor ns -> makeRecordE (mkRecordFieldE <$> zip ns (constructorFields c))
36
39
37
40
makeTupleE :: [Q Exp ] -> Q Exp {- [Q TsContext TsType] -> Q (TsContext TsType) -}
38
41
makeTupleE ts = case ts of
@@ -44,34 +47,29 @@ deriveTsTypeable opts name = do
44
47
then [| snd $ (head ts) | ]
45
48
else [| TsObject <$> mapM (\ (n, TsContext t m) -> TsContext (n, t) m) $ (ListE <$> sequence ts) | ]
46
49
47
- isNullaryCons :: Con -> Bool
48
- isNullaryCons (NormalC _ [] ) = True
49
- isNullaryCons _ = False
50
+ isNullaryCons :: ConstructorInfo -> Bool
51
+ isNullaryCons = (\ x -> length x == 0 ) . constructorFields
50
52
51
- mkNullaryStringConsE :: Con -> Q Exp
52
- mkNullaryStringConsE ( NormalC n [] ) = [| return . TsStringLiteral $ $ (mkConStringE n ) | ]
53
+ mkNullaryStringConsE :: ConstructorInfo -> Q Exp {- Q (TsContext TsType) -}
54
+ mkNullaryStringConsE c = [| return . TsStringLiteral $ $ (mkConStringE . constructorName $ c ) | ]
53
55
54
- mkTaggedTypeE :: Con -> Q Exp {- Q (TsContext TsType) -}
55
- mkTaggedTypeE c = let conE = [| TsStringLiteral $ (mkConStringE $ getConName c) | ]
56
+ mkTaggedTypeE :: ConstructorInfo -> Q Exp {- Q (TsContext TsType) -}
57
+ mkTaggedTypeE c = let conE = [| TsStringLiteral $ (mkConStringE $ constructorName c) | ]
56
58
in case sumEncoding opts of
57
- (TaggedObject tn cn) -> case c of
58
- ( NormalC n ts) -> case ts of
59
+ (TaggedObject tn cn) -> case constructorVariant c of
60
+ NormalConstructor -> case constructorFields c of
59
61
[] -> [| pure $ TsObject [($ (mkTextE tn), $ conE)] | ]
60
62
_ -> [| TsObject <$> sequence [pure ($ (mkTextE tn), $ conE), ((,) $ (mkTextE cn) <$> $ (mkTypeE c))] | ]
61
- ( RecC n ts) -> makeRecordE $ [| ($ (mkTextE tn), return . TsStringLiteral $ $ (mkConStringE n )) | ] : (mkRecordFieldE <$> ts )
63
+ RecordConstructor ns -> makeRecordE $ [| ($ (mkTextE tn), return . TsStringLiteral $ $ (mkConStringE $ constructorName c )) | ] : (mkRecordFieldE <$> zip ns (constructorFields c) )
62
64
UntaggedValue -> mkTypeE c
63
- ObjectWithSingleField -> [| (\ x -> TsObject [($ (mkConStringE $ getConName c), x)]) <$> $ (mkTypeE c) | ]
65
+ ObjectWithSingleField -> [| (\ x -> TsObject [($ (mkConStringE $ constructorName c), x)]) <$> $ (mkTypeE c) | ]
64
66
TwoElemArray -> [| (\ x -> TsTuple [$ conE, x]) <$> $ (mkTypeE c) | ]
65
67
66
- getConName :: Con -> Name
67
- getConName (NormalC n _) = n
68
- getConName (RecC n _) = n
68
+ mkRecordFieldE :: (Name , Type ) -> Q Exp {- Q (Text, TsContext TsType) -}
69
+ mkRecordFieldE (n, t) = [| ($ (mkFieldStringE n), tsTypeRep (Proxy :: Proxy $ (return t ))) | ]
69
70
70
- mkRecordFieldE :: (Name , Bang , Type ) -> Q Exp {- Q (Text, TsContext TsType) -}
71
- mkRecordFieldE (n, _, t) = [| ($ (mkFieldStringE n), tsTypeRep (Proxy :: Proxy $ (return t ))) | ]
72
-
73
- mkNormalFieldE :: (Bang , Type ) -> Q Exp
74
- mkNormalFieldE (_, t) = [| tsTypeRep (Proxy :: Proxy $ (return t )) | ]
71
+ mkNormalFieldE :: Type -> Q Exp {- Q (TsContext TsType) -}
72
+ mkNormalFieldE t = [| tsTypeRep (Proxy :: Proxy $ (return t )) | ]
75
73
76
74
mkFieldStringE :: Name -> Q Exp {- Q String -}
77
75
mkFieldStringE n = mkTextE . (fieldLabelModifier opts) . nameBase $ n
0 commit comments