From edf037a79b41a908a16a90843c491d6d7011f601 Mon Sep 17 00:00:00 2001 From: Ben Price <ben@hackworthltd.com> Date: Wed, 3 Aug 2022 13:54:22 +0100 Subject: [PATCH 1/2] ToSchema + deriving-aeson: it compiles, but is it right...: - the manual instance (look for library?) - my choices around what things are derived via and what are gnd and what are plain (should match ToJSON instances) I would like to brush off the testing work and ensure that catches all possible bugs here! --- primer-service/primer-service.cabal | 1 + primer-service/src/Primer/OpenAPI.hs | 36 ++++++++++++++++++++++------ primer/primer.cabal | 2 +- 3 files changed, 31 insertions(+), 8 deletions(-) diff --git a/primer-service/primer-service.cabal b/primer-service/primer-service.cabal index d7a83a1f1..4877760d8 100644 --- a/primer-service/primer-service.cabal +++ b/primer-service/primer-service.cabal @@ -36,6 +36,7 @@ library build-depends: , aeson >=2.0 && <=2.1 , base >=4.12 && <=4.17 + , deriving-aeson >=0.2 && <=0.3 , exceptions >=0.10.4 && <=0.11 , http-media >=0.8 && <=0.9 , mtl >=2.2.2 && <=2.3 diff --git a/primer-service/src/Primer/OpenAPI.hs b/primer-service/src/Primer/OpenAPI.hs index 2998fa91c..a41d2e524 100644 --- a/primer-service/src/Primer/OpenAPI.hs +++ b/primer-service/src/Primer/OpenAPI.hs @@ -1,3 +1,4 @@ +{-# LANGUAGE UndecidableInstances #-} {-# OPTIONS_GHC -fno-warn-orphans #-} module Primer.OpenAPI ( @@ -5,12 +6,14 @@ module Primer.OpenAPI ( -- $orphanInstances ) where -import Data.OpenApi (ToSchema) -import Data.Text (Text) -import Data.Typeable (Typeable) +import Data.OpenApi (SchemaOptions, fromAesonOptions) +import Data.OpenApi.Internal.Schema +import Deriving.Aeson (AesonOptions (aesonOptions)) +import Foreword import Primer.API (Def, Module, NodeBody, NodeFlavor, Prog, Tree) import Primer.Core (GlobalName, ID (..), LVarName, ModuleName) import Primer.Database (Session, SessionName) +import Primer.JSON (CustomJSON (..), PrimerJSON) import Primer.Name (Name) -- $orphanInstances @@ -20,8 +23,24 @@ import Primer.Name (Name) -- build primer with ghcjs, because openapi3 transitively depends on network, -- which ghcjs currently cannot build. -instance ToSchema SessionName -instance ToSchema Session +-- TODO: this compiles, but is it correct? + +-- Suitable for deriving via, when ToJSON is via the custom json +-- instance (AesonOptions os, ToSchema a, Typeable os, Typeable ks) => ToSchema (CustomJSON (os :: ks) a) where +-- declareNamedSchema = genericDeclareNamedSchemaNewtype opts (declareNamedSchema @a) +instance + (Typeable a, Generic a, GToSchema (Rep a), Typeable os, Typeable ks, AesonOptions os) => + ToSchema (CustomJSON (os :: ks) a) + where + declareNamedSchema _ = genericDeclareNamedSchema opts (Proxy @a) + where + opts :: SchemaOptions + opts = fromAesonOptions (aesonOptions @os) + +-- Technically should GND this, but cannot because of exports... +-- instance ToSchema SessionName +deriving via Text instance ToSchema SessionName -- see comments on instance ToSchema Name +deriving via PrimerJSON Session instance ToSchema Session -- We need to GND the ID instance to match its To/FromJSON instances deriving newtype instance ToSchema ID @@ -33,12 +52,15 @@ deriving via Text instance (ToSchema Name) -- For GlobalName and LVarName, we must derive ToSchema via Name, -- as that is how the To/FromJSON instances are derived -deriving via Name instance Typeable k => ToSchema (GlobalName k) +-- deriving via Name instance Typeable k => ToSchema (GlobalName k) +instance Typeable k => ToSchema (GlobalName k) -- actually, just plain ToJSON here... deriving via Name instance (ToSchema LVarName) + +-- These are just plain ToJSON instance ToSchema Tree instance ToSchema NodeBody instance ToSchema NodeFlavor instance ToSchema Def -instance ToSchema ModuleName +deriving via NonEmpty Name instance ToSchema ModuleName instance ToSchema Module instance ToSchema Prog diff --git a/primer/primer.cabal b/primer/primer.cabal index 8fde82b4b..19db59619 100644 --- a/primer/primer.cabal +++ b/primer/primer.cabal @@ -29,6 +29,7 @@ library Primer.Eval Primer.EvalFull Primer.Examples + Primer.JSON Primer.Module Primer.Name Primer.Name.Fresh @@ -45,7 +46,6 @@ library hs-source-dirs: src other-modules: Control.Monad.NestedError - Primer.JSON default-language: GHC2021 default-extensions: From 40ddb3b75537c3c5f82011bb52882cc8ef18b96e Mon Sep 17 00:00:00 2001 From: Ben Price <ben@hackworthltd.com> Date: Wed, 3 Aug 2022 18:50:58 +0100 Subject: [PATCH 2/2] huh, ToSchema (GlobalName k) generates broken openapi! ... TODO: check what difference this via-custom makes when have non Vanilla (unsure if it currently is applied to any types where it is interesting) TODO: check this via-custom is correct wrt the ToJSON encoding --- primer-service/src/Primer/OpenAPI.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/primer-service/src/Primer/OpenAPI.hs b/primer-service/src/Primer/OpenAPI.hs index a41d2e524..0efbf74dd 100644 --- a/primer-service/src/Primer/OpenAPI.hs +++ b/primer-service/src/Primer/OpenAPI.hs @@ -52,8 +52,8 @@ deriving via Text instance (ToSchema Name) -- For GlobalName and LVarName, we must derive ToSchema via Name, -- as that is how the To/FromJSON instances are derived --- deriving via Name instance Typeable k => ToSchema (GlobalName k) -instance Typeable k => ToSchema (GlobalName k) -- actually, just plain ToJSON here... +deriving via Name instance Typeable k => ToSchema (GlobalName k) +--instance Typeable k => ToSchema (GlobalName k) -- actually, just plain ToJSON here..., but is invalid openapi! deriving via Name instance (ToSchema LVarName) -- These are just plain ToJSON