@@ -74,6 +74,7 @@ module Moat
74
74
omitFields ,
75
75
omitCases ,
76
76
fieldsRequiredByClients ,
77
+ deprecatedFields ,
77
78
strictCases ,
78
79
makeBase ,
79
80
sumOfProductEncodingOptions ,
@@ -509,6 +510,10 @@ data MoatError
509
510
}
510
511
| MissingRequiredFields
511
512
{ _missingFields :: [String ]
513
+ , _missingDeprecatedFields :: [String ]
514
+ }
515
+ | MissingDeprecatedRequiredFields
516
+ { _missingDeprecatedRequiredFields :: [String ]
512
517
}
513
518
| MissingStrictCases
514
519
{ _missingCases :: [String ]
@@ -577,8 +582,10 @@ prettyMoatError = \case
577
582
ImproperNewtypeConstructorInfo conInfo ->
578
583
" Expected `ConstructorInfo` with single field, but got "
579
584
++ show conInfo
580
- MissingRequiredFields missingFields ->
581
- " These fields are required by clients: " ++ L. unwords missingFields
585
+ MissingRequiredFields missingFields missingDeprecatedFields ->
586
+ " These fields are required by clients: " ++ L. unwords missingFields ++ " " ++ L. unwords missingDeprecatedFields
587
+ MissingDeprecatedRequiredFields missingDeprecatedFields ->
588
+ " These fields need to be added to the required field list due to being necessary on older clients: " ++ L. unwords missingDeprecatedFields
582
589
MissingStrictCases missingCases ->
583
590
" Removing these cases will break clients: " ++ L. unwords missingCases
584
591
@@ -975,7 +982,8 @@ mkNewtype o@Options {..} typName doc instTys ts = \case
975
982
} -> do
976
983
fieldDocs <- lift $ mapM (getDocWith o) fieldNames
977
984
fields <- zipFields o fieldNames constructorFields fieldDocs
978
- matchProxy =<< lift (structExp typName doc instTys dataInterfaces dataProtocols dataAnnotations fields ts makeBase)
985
+ deprecatedFieldExps <- lift [e |deprecatedFields|]
986
+ matchProxy =<< lift (structExp typName doc instTys dataInterfaces dataProtocols dataAnnotations fields deprecatedFieldExps ts makeBase)
979
987
ConstructorInfo
980
988
{ constructorFields = [field]
981
989
} -> do
@@ -1004,7 +1012,8 @@ mkProd o@Options {..} typName parentDoc instTys ts = \case
1004
1012
{ constructorVariant = NormalConstructor
1005
1013
, constructorFields = []
1006
1014
} -> do
1007
- matchProxy =<< lift (structExp typName parentDoc instTys dataInterfaces dataProtocols dataAnnotations [] ts makeBase)
1015
+ emptyDeprecatedFieldsExp <- lift [e |[]|]
1016
+ matchProxy =<< lift (structExp typName parentDoc instTys dataInterfaces dataProtocols dataAnnotations [] emptyDeprecatedFieldsExp ts makeBase)
1008
1017
-- single constructor, non-record (Normal)
1009
1018
ConstructorInfo
1010
1019
{ constructorVariant = NormalConstructor
@@ -1026,17 +1035,30 @@ mkProd o@Options {..} typName parentDoc instTys ts = \case
1026
1035
} -> do
1027
1036
fieldDocs <- lift $ mapM (getDocWith o) fieldNames
1028
1037
fields <- zipFields o fieldNames constructorFields fieldDocs
1029
- matchProxy =<< lift (structExp typName parentDoc instTys dataInterfaces dataProtocols dataAnnotations fields ts makeBase)
1038
+ deprecatedFieldExp <- lift [e |deprecatedFields|]
1039
+ matchProxy =<< lift (structExp typName parentDoc instTys dataInterfaces dataProtocols dataAnnotations fields deprecatedFieldExp ts makeBase)
1030
1040
1031
1041
-- | 'strictFields' are required to exist in the record and are always included.
1032
1042
-- 'omitFields' will remove any remaining fields if they are 'Discard'ed.
1033
1043
zipFields :: Options -> [Name ] -> [Type ] -> [Maybe String ] -> MoatM [Exp ]
1034
1044
zipFields o ns ts ds = do
1035
1045
let fields = nameStr <$> ns
1036
- missingFields = fieldsRequiredByClients o L. \\ fields
1037
- if null missingFields
1038
- then pure $ catMaybes $ zipWith3 mkField ns ts ds
1039
- else throwError $ MissingRequiredFields missingFields
1046
+ requiredFieldNames = fieldsRequiredByClients o
1047
+ deprecatedFieldNames = fst <$> deprecatedFields o
1048
+ missingFields = requiredFieldNames L. \\ fields
1049
+ missingDeprecatedFields = deprecatedFieldNames L. \\ fields
1050
+ deprecatedNonRequiredFields = deprecatedFieldNames L. \\ requiredFieldNames
1051
+ checkMissingFields =
1052
+ if null missingFields
1053
+ then pure $ catMaybes $ zipWith3 mkField ns ts ds
1054
+ else throwError $ MissingRequiredFields missingFields missingDeprecatedFields
1055
+ case requiredFieldNames of
1056
+ [] -> checkMissingFields
1057
+ _requiredFields ->
1058
+ -- Throw an error if required fields are available but a deprecated field is not included in them
1059
+ case deprecatedNonRequiredFields of
1060
+ [] -> checkMissingFields
1061
+ _xs -> throwError $ MissingDeprecatedRequiredFields deprecatedNonRequiredFields
1040
1062
where
1041
1063
mkField :: Name -> Type -> Maybe String -> Maybe Exp
1042
1064
mkField n t d =
@@ -1650,12 +1672,14 @@ structExp ::
1650
1672
[Annotation ] ->
1651
1673
-- | fields
1652
1674
[Exp ] ->
1675
+ -- | deprecated fields
1676
+ Exp ->
1653
1677
-- | tags
1654
1678
[Exp ] ->
1655
1679
-- | Make base?
1656
1680
(Bool , Maybe MoatType , [Protocol ]) ->
1657
1681
Q Exp
1658
- structExp name doc tyVars ifaces protos anns fields tags bs = do
1682
+ structExp name doc tyVars ifaces protos anns fields deprecatedFields tags bs = do
1659
1683
structInterfaces_ <- Syntax. lift ifaces
1660
1684
structAnnotations_ <- Syntax. lift anns
1661
1685
structProtocols_ <- Syntax. lift protos
@@ -1669,6 +1693,7 @@ structExp name doc tyVars ifaces protos anns fields tags bs = do
1669
1693
, ('structProtocols, structProtocols_)
1670
1694
, ('structAnnotations, structAnnotations_)
1671
1695
, ('structFields, ListE fields)
1696
+ , ('structDeprecatedFields, deprecatedFields)
1672
1697
, ('structPrivateTypes, ListE [] )
1673
1698
, ('structTags, ListE tags)
1674
1699
]
0 commit comments