Comply with lint workflow

This commit is contained in:
Alex Biehl 2024-05-28 15:10:13 +02:00 committed by Alexander Biehl
parent 3c169d3ac3
commit cfe90c3aa4
7 changed files with 778 additions and 693 deletions

View File

@ -22,8 +22,8 @@ import qualified Data.Aeson
import qualified Data.Aeson.Types import qualified Data.Aeson.Types
import Data.Attoparsec.ByteString (eitherResult, parseWith) import Data.Attoparsec.ByteString (eitherResult, parseWith)
import Data.ByteString (ByteString) import Data.ByteString (ByteString)
import qualified Data.ByteString.Builder as Builder
import qualified Data.ByteString as ByteString import qualified Data.ByteString as ByteString
import qualified Data.ByteString.Builder as Builder
import qualified Data.ByteString.Lazy as LBS import qualified Data.ByteString.Lazy as LBS
import Data.Coerce (coerce) import Data.Coerce (coerce)
import qualified Data.HashMap.Strict as HashMap import qualified Data.HashMap.Strict as HashMap

View File

@ -48,10 +48,13 @@ codegenOperations resolver operations = do
-- TODO instead of "application" take name from openapi spec -- TODO instead of "application" take name from openapi spec
"application" "application"
<+> "::" <+> "::"
<+> "(" <> "Control.Monad.IO.Class.MonadIO" <+> "("
<+> "m" <> ")" <> "Control.Monad.IO.Class.MonadIO"
<+> "m"
<> ")"
<+> "=>" <+> "=>"
<+> "(" <> "forall" <+> "("
<> "forall"
<+> "a" <+> "a"
<+> "." <+> "."
<+> "Network.Wai.Request" <+> "Network.Wai.Request"
@ -60,7 +63,8 @@ codegenOperations resolver operations = do
<+> "a" <+> "a"
<+> "->" <+> "->"
<+> "IO" <+> "IO"
<+> "a" <> ")" <+> "a"
<> ")"
<+> "->" <+> "->"
<+> "Api" <+> "Api"
<+> "m" <+> "m"
@ -108,10 +112,13 @@ codegenOperations resolver operations = do
<> PP.indent <> PP.indent
4 4
( "respond" ( "respond"
<+> "(" <> "Network.Wai.responseBuilder" <+> "("
<+> "Network.HTTP.Types.status" <> "405" <> "Network.Wai.responseBuilder"
<+> "Network.HTTP.Types.status"
<> "405"
<+> "[]" <+> "[]"
<+> "mempty" <> ")" <+> "mempty"
<> ")"
) )
) )
) )
@ -239,10 +246,14 @@ codegenCallApiMember operationName path queryParams headerParams requestBody =
) )
<> PP.line <> PP.line
<> "Control.Monad.IO.Class.liftIO" <> "Control.Monad.IO.Class.liftIO"
<+> "(" <> "respond" <+> "("
<> "respond"
<+> "$!" <+> "$!"
<+> "(" <> "toResponse" <+> "("
<+> "response" <> ")" <> ")" <> "toResponse"
<+> "response"
<> ")"
<> ")"
) )
<> PP.line <> PP.line
<> ")" <> ")"
@ -314,7 +325,9 @@ codegenRequestBodyGuard requestBody continuation = case requestBody of
"[" <> PP.concatWith (\x y -> x <> "," <+> y) parsers <> "]" "[" <> PP.concatWith (\x y -> x <> "," <+> y) parsers <> "]"
in "parseRequestBody" in "parseRequestBody"
<+> parsersList <+> parsersList
<+> "(" <> "\\" <> "body" <+> "("
<> "\\"
<> "body"
<+> "request" <+> "request"
<+> "respond" <+> "respond"
<+> "->" <+> "->"
@ -343,7 +356,9 @@ codegenPathParamGuard :: Param -> PP.Doc ann -> PP.Doc ann
codegenPathParamGuard Param {name} continuation = codegenPathParamGuard Param {name} continuation =
"pathVariable" "pathVariable"
<+> toParamBinder name <+> toParamBinder name
<+> "(" <> "\\" <> toParamBinder name <+> "("
<> "\\"
<> toParamBinder name
<+> "request" <+> "request"
<+> "respond" <+> "respond"
<+> "->" <+> "->"
@ -369,8 +384,12 @@ codegenQueryParamGuard Param {name, required, style, explode, schema} continuati
Just style <- codegenQueryParamStyle explode style = Just style <- codegenQueryParamStyle explode style =
(if required then "requiredQueryParameters" else "optionalQueryParameters") (if required then "requiredQueryParameters" else "optionalQueryParameters")
<+> style <+> style
<+> "\"" <> toParamName name <> "\"" <+> "\""
<+> "(" <> "\\" <> toParamBinder name <> toParamName name
<> "\""
<+> "("
<> "\\"
<> toParamBinder name
<+> "request" <+> "request"
<+> "respond" <+> "respond"
<+> "->" <+> "->"
@ -381,8 +400,12 @@ codegenQueryParamGuard Param {name, required, style, explode, schema} continuati
<+> "respond" <+> "respond"
| required = | required =
"requiredQueryParameter" "requiredQueryParameter"
<+> "\"" <> toParamName name <> "\"" <+> "\""
<+> "(" <> "\\" <> toParamBinder name <> toParamName name
<> "\""
<+> "("
<> "\\"
<> toParamBinder name
<+> "request" <+> "request"
<+> "respond" <+> "respond"
<+> "->" <+> "->"
@ -393,9 +416,13 @@ codegenQueryParamGuard Param {name, required, style, explode, schema} continuati
<+> "respond" <+> "respond"
| otherwise = | otherwise =
"optionalQueryParameter" "optionalQueryParameter"
<+> "\"" <> toParamName name <> "\"" <+> "\""
<> toParamName name
<> "\""
<+> "False" <+> "False"
<+> "(" <> "\\" <> toParamBinder name <+> "("
<> "\\"
<> toParamBinder name
<+> "request" <+> "request"
<+> "respond" <+> "respond"
<+> "->" <+> "->"
@ -409,8 +436,12 @@ codegenHeaderGuard :: Param -> PP.Doc ann -> PP.Doc ann
codegenHeaderGuard Param {name, required} continuation codegenHeaderGuard Param {name, required} continuation
| required = | required =
"requiredHeader" "requiredHeader"
<+> "\"" <> toParamName name <> "\"" <+> "\""
<+> "(" <> "\\" <> toParamBinder name <> toParamName name
<> "\""
<+> "("
<> "\\"
<> toParamBinder name
<+> "request" <+> "request"
<+> "respond" <+> "respond"
<+> "->" <+> "->"
@ -421,8 +452,12 @@ codegenHeaderGuard Param {name, required} continuation
<+> "respond" <+> "respond"
| otherwise = | otherwise =
"optionalHeader" "optionalHeader"
<+> "\"" <> toParamName name <> "\"" <+> "\""
<+> "(" <> "\\" <> toParamBinder name <> toParamName name
<> "\""
<+> "("
<> "\\"
<> toParamBinder name
<+> "request" <+> "request"
<+> "respond" <+> "respond"
<+> "->" <+> "->"

View File

@ -5,8 +5,8 @@
module Tie.Codegen.Request (codegenRequestAuxFile) where module Tie.Codegen.Request (codegenRequestAuxFile) where
import qualified Data.ByteString as ByteString import qualified Data.ByteString as ByteString
import qualified Data.Text as Text
import Data.FileEmbed (embedStringFile, makeRelativeToProject) import Data.FileEmbed (embedStringFile, makeRelativeToProject)
import qualified Data.Text as Text
import Prettyprinter (Doc, hsep, vsep) import Prettyprinter (Doc, hsep, vsep)
import qualified Prettyprinter.Util as Prettyprinter import qualified Prettyprinter.Util as Prettyprinter
import System.IO.Unsafe (unsafePerformIO) import System.IO.Unsafe (unsafePerformIO)

View File

@ -1,8 +1,8 @@
{-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-} {-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeApplications #-}
module Tie.Codegen.Response module Tie.Codegen.Response
( codegenResponses, ( codegenResponses,
@ -11,10 +11,10 @@ module Tie.Codegen.Response
where where
import qualified Data.ByteString as ByteString import qualified Data.ByteString as ByteString
import Data.FileEmbed (embedStringFile, makeRelativeToProject)
import Data.List (lookup) import Data.List (lookup)
import qualified Data.Text as Text import qualified Data.Text as Text
import Network.HTTP.Media (renderHeader) import Network.HTTP.Media (renderHeader)
import Data.FileEmbed (embedStringFile, makeRelativeToProject)
import Prettyprinter (Doc, (<+>)) import Prettyprinter (Doc, (<+>))
import qualified Prettyprinter as PP import qualified Prettyprinter as PP
import qualified Prettyprinter.Render.Text as PP import qualified Prettyprinter.Render.Text as PP
@ -155,10 +155,13 @@ codegenHasStatusField operationName responses defaultResponse =
4 4
( PP.vsep $ ( PP.vsep $
[ "getField" [ "getField"
<+> "(" <> toApiResponseConstructorName operationName statusCode <+> "("
<+> "{}" <> ")" <> toApiResponseConstructorName operationName statusCode
<+> "{}"
<> ")"
<+> "=" <+> "="
<+> "Network.HTTP.Types.status" <> PP.pretty statusCode <+> "Network.HTTP.Types.status"
<> PP.pretty statusCode
| (statusCode, _response) <- responses | (statusCode, _response) <- responses
] ]
++ [ "getField" ++ [ "getField"
@ -237,14 +240,21 @@ codegenToResponses responseModuleName operationName responses defaultResponse =
] ]
optionalHeaders = optionalHeaders =
[ "[" <> "(\"" <> toParamName name <> "\"," [ "["
<> "(\""
<> toParamName name
<> "\","
<+> "Web.HttpApiData.toHeader" <+> "Web.HttpApiData.toHeader"
<+> toParamBinder name <> ")" <+> toParamBinder name
<> ")"
<+> "|" <+> "|"
<+> "Just" <+> "Just"
<+> toParamBinder name <+> toParamBinder name
<+> "<-" <+> "<-"
<+> "[" <> toParamBinder name <> "]" <> "]" <+> "["
<> toParamBinder name
<> "]"
<> "]"
| Header {name, required = False} <- headers | Header {name, required = False} <- headers
] ]
in "(" in "("
@ -284,7 +294,8 @@ codegenToResponses responseModuleName operationName responses defaultResponse =
<> PP.indent <> PP.indent
4 4
( waiResponse response ( waiResponse response
<+> "Network.HTTP.Types.status" <> PP.pretty statusCode <+> "Network.HTTP.Types.status"
<> PP.pretty statusCode
<+> responseHeaders response <+> responseHeaders response
<+> bodySerialize response <+> bodySerialize response
) )

View File

@ -70,7 +70,7 @@ codegenParamSchema Param {schema, required} =
| Just objectType <- isObjectType typ -> | Just objectType <- isObjectType typ ->
error "Invariant broken: ruled out by pathToPath" error "Invariant broken: ruled out by pathToPath"
| otherwise -> | otherwise ->
undefined error "Impossible"
-- | Generate code for a header -- | Generate code for a header
codegenHeaderSchema :: Header -> Doc ann codegenHeaderSchema :: Header -> Doc ann
@ -88,7 +88,7 @@ codegenHeaderSchema Header {schema, required} =
| Just objectType <- isObjectType typ -> | Just objectType <- isObjectType typ ->
error "Invariant broken: ruled out by pathToPath" error "Invariant broken: ruled out by pathToPath"
| otherwise -> | otherwise ->
undefined error "Impossible"
Nothing -> Nothing ->
error "Header without schema" error "Header without schema"
@ -183,8 +183,10 @@ codegenOneOfType getDiscriminator typName variants = do
4 4
( PP.vsep ( PP.vsep
[ "toJSON" [ "toJSON"
<+> "(" <> variantName <+> "("
<+> "x" <> ")" <> variantName
<+> "x"
<> ")"
<+> "=" <+> "="
<+> "Data.Aeson.toJSON" <+> "Data.Aeson.toJSON"
<+> "x" <+> "x"
@ -194,8 +196,10 @@ codegenOneOfType getDiscriminator typName variants = do
<> PP.line <> PP.line
<> PP.vsep <> PP.vsep
[ "toEncoding" [ "toEncoding"
<+> "(" <> variantName <+> "("
<+> "x" <> ")" <> variantName
<+> "x"
<> ")"
<+> "=" <+> "="
<+> "Data.Aeson.toEncoding" <+> "Data.Aeson.toEncoding"
<+> "x" <+> "x"
@ -206,19 +210,27 @@ codegenOneOfType getDiscriminator typName variants = do
fromJsonVariant :: Name -> PP.Doc ann fromJsonVariant :: Name -> PP.Doc ann
fromJsonVariant variantName fromJsonVariant variantName
| Just (property, value) <- getDiscriminator variantName = | Just (property, value) <- getDiscriminator variantName =
"(" <> "Data.Aeson.Types.withObject" "("
<+> "\"" <> toDataTypeName variantName <> "\"" <> "Data.Aeson.Types.withObject"
<+> "\""
<> toDataTypeName variantName
<> "\""
<+> "$" <+> "$"
<+> "\\" <> "o" <+> "\\"
<> "o"
<+> "->" <+> "->"
<> PP.line <> PP.line
<> PP.indent <> PP.indent
4 4
( "do" ( "do"
<+> PP.align <+> PP.align
( "(" <> "\"" <> PP.pretty value <> "\"" ( "("
<> "\""
<> PP.pretty value
<> "\""
<+> "::" <+> "::"
<+> "Data.Text.Text" <> ")" <+> "Data.Text.Text"
<> ")"
<+> "<-" <+> "<-"
<+> "o" <+> "o"
<+> "Data.Aeson..:" <+> "Data.Aeson..:"
@ -281,7 +293,8 @@ codegenObjectType typName ObjectType {..}
<> PP.line <> PP.line
<> PP.indent <> PP.indent
4 4
( "(" <> "Data.Map.Map" ( "("
<> "Data.Map.Map"
<+> "Data.Text.Text" <+> "Data.Text.Text"
<+> "(" <+> "("
<> codegenFieldType propertyType <> codegenFieldType propertyType
@ -289,7 +302,9 @@ codegenObjectType typName ObjectType {..}
<> ")" <> ")"
<> PP.line <> PP.line
<> "deriving" <> "deriving"
<+> "(" <> "Show" <> ")" <+> "("
<> "Show"
<> ")"
) )
toJson = toJson =
@ -301,8 +316,10 @@ codegenObjectType typName ObjectType {..}
<> PP.indent <> PP.indent
4 4
( "toJSON" ( "toJSON"
<+> "(" <> toConstructorName typName <+> "("
<+> "x" <> ")" <> toConstructorName typName
<+> "x"
<> ")"
<+> "=" <+> "="
<> PP.line <> PP.line
<> PP.indent <> PP.indent
@ -312,8 +329,10 @@ codegenObjectType typName ObjectType {..}
<> PP.line <> PP.line
<> PP.line <> PP.line
<> "toEncoding" <> "toEncoding"
<+> "(" <> toConstructorName typName <+> "("
<+> "x" <> ")" <> toConstructorName typName
<+> "x"
<> ")"
<+> "=" <+> "="
<> PP.line <> PP.line
<> PP.indent <> PP.indent
@ -401,7 +420,8 @@ codegenObjectType typName ObjectType {..}
<> PP.line <> PP.line
<> PP.indent <> PP.indent
4 4
( "(" <> "[" ( "("
<> "["
<+> PP.align <+> PP.align
( PP.concatWith ( PP.concatWith
(\x y -> x <> "," <> PP.line <> y) (\x y -> x <> "," <> PP.line <> y)
@ -419,14 +439,18 @@ codegenObjectType typName ObjectType {..}
(\x y -> x <> PP.line <> y) (\x y -> x <> PP.line <> y)
[ ( "++" [ ( "++"
<+> "[" <+> "["
<+> "\"" <> toJsonFieldName field <> "\"" <+> "\""
<> toJsonFieldName field
<> "\""
<+> "Data.Aeson..=" <+> "Data.Aeson..="
<+> toFieldName haskellField <+> toFieldName haskellField
<+> "|" <+> "|"
<+> "Just" <+> "Just"
<+> toFieldName haskellField <+> toFieldName haskellField
<+> "<-" <+> "<-"
<+> "[" <> toFieldName haskellField <> "]" <+> "["
<> toFieldName haskellField
<> "]"
<+> "]" <+> "]"
) )
| (field, _) <- orderedProperties, | (field, _) <- orderedProperties,
@ -453,17 +477,24 @@ codegenObjectType typName ObjectType {..}
[ if HashSet.member field requiredProperties [ if HashSet.member field requiredProperties
then then
"Data.Aeson.Encoding.pair" "Data.Aeson.Encoding.pair"
<+> "\"" <> toJsonFieldName field <> "\"" <+> "\""
<+> "(" <> "Data.Aeson.toEncoding" <> toJsonFieldName field
<+> toFieldName haskellField <> ")" <> "\""
<+> "("
<> "Data.Aeson.toEncoding"
<+> toFieldName haskellField
<> ")"
else else
"maybe" "maybe"
<+> "mempty" <+> "mempty"
<+> "(" <+> "("
<> "Data.Aeson.Encoding.pair" <> "Data.Aeson.Encoding.pair"
<+> "\"" <> toJsonFieldName field <> "\"" <+> "\""
<> toJsonFieldName field
<> "\""
<+> "." <+> "."
<+> "Data.Aeson.toEncoding" <> ")" <+> "Data.Aeson.toEncoding"
<> ")"
<+> toFieldName haskellField <+> toFieldName haskellField
| (field, _) <- orderedProperties, | (field, _) <- orderedProperties,
let haskellField = let haskellField =
@ -490,9 +521,12 @@ codegenObjectType typName ObjectType {..}
( "parseJSON" ( "parseJSON"
<+> "=" <+> "="
<+> "Data.Aeson.withObject" <+> "Data.Aeson.withObject"
<+> "\"" <> toDataTypeName typName <> "\"" <+> "\""
<> toDataTypeName typName
<> "\""
<+> "$" <+> "$"
<+> "\\" <> "o" <+> "\\"
<> "o"
<+> "->" <+> "->"
<> PP.line <> PP.line
<> PP.indent <> PP.indent
@ -594,8 +628,11 @@ codegenEnumeration typName alternatives _includeNull =
(map (toEnumConstructorName typName) alternatives) (map (toEnumConstructorName typName) alternatives)
<> PP.line <> PP.line
<> "deriving" <> "deriving"
<+> "(" <> "Eq" <> "," <+> "("
<+> "Show" <> ")" <> "Eq"
<> ","
<+> "Show"
<> ")"
) )
toJSON = toJSON =
"instance" "instance"
@ -647,9 +684,12 @@ codegenEnumeration typName alternatives _includeNull =
( "parseJSON" ( "parseJSON"
<+> "=" <+> "="
<+> "Data.Aeson.withText" <+> "Data.Aeson.withText"
<+> "\"" <> toDataTypeName typName <> "\"" <+> "\""
<> toDataTypeName typName
<> "\""
<+> "$" <+> "$"
<+> "\\" <> "s" <+> "\\"
<> "s"
<+> "->" <+> "->"
<> PP.line <> PP.line
<> PP.indent <> PP.indent

View File

@ -103,10 +103,10 @@ data BasicType
| TyInteger (Maybe IntegerFormat) | TyInteger (Maybe IntegerFormat)
| TyBoolean | TyBoolean
| TyHaskellType | TyHaskellType
-- | Haskell modules to import
[Text] [Text]
-- ^ Haskell modules to import -- | Type to insert
Text Text
-- ^ Type to insert
deriving (Eq, Ord, Show) deriving (Eq, Ord, Show)
data FreeFormObject ty data FreeFormObject ty
@ -277,7 +277,7 @@ schemaToType resolver schema
OpenApi.OpenApiItemsObject itemsSchemaRef -> OpenApi.OpenApiItemsObject itemsSchemaRef ->
Array <$> schemaRefToType resolver itemsSchemaRef Array <$> schemaRefToType resolver itemsSchemaRef
OpenApi.OpenApiItemsArray _itemsSchemaRefs -> OpenApi.OpenApiItemsArray _itemsSchemaRefs ->
undefined -- TODO find out what tuple schemas are error "unimplemented" -- TODO find out what tuple schemas are
| otherwise -> | otherwise ->
pure $ pure $
Array Array
@ -293,7 +293,7 @@ schemaToType resolver schema
) )
) )
OpenApi.OpenApiNull -> OpenApi.OpenApiNull ->
undefined -- TODO need a BasicType for that error "unimplemented" -- TODO need a BasicType for OpenApiNull
OpenApi.OpenApiObject -> OpenApi.OpenApiObject ->
Object <$> schemaToObjectType resolver schema Object <$> schemaToObjectType resolver schema
-- Heuristic: if the 'OpenApi.Schema' has properties attached -- Heuristic: if the 'OpenApi.Schema' has properties attached
@ -625,8 +625,7 @@ normalizeObjectType ::
normalizeObjectType assignObjectFieldTypeName assignAdditionaPropertiesTypeName objectType@ObjectType {..} = do normalizeObjectType assignObjectFieldTypeName assignAdditionaPropertiesTypeName objectType@ObjectType {..} = do
(properties, newTypes) <- runWriterT $ (properties, newTypes) <- runWriterT $
flip HashMap.traverseWithKey properties $ \fieldName fieldType -> do flip HashMap.traverseWithKey properties $ \fieldName fieldType -> do
let let haskellFieldName =
haskellFieldName =
HashMap.lookupDefault fieldName fieldName haskellFieldNames HashMap.lookupDefault fieldName fieldName haskellFieldNames
WriterT $ WriterT $
normalizeNamedType normalizeNamedType