Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 30 additions & 9 deletions openapi3-code-generator/src/OpenAPI/Generate/Internal/Operation.hs
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,8 @@ data ParameterCardinality
| MultipleParameters ParameterTypeDefinition

-- | Generates the parameter type for an operation. See 'ParameterCardinality' for further information.
generateParameterTypeFromOperation :: Text -> OAT.OperationObject -> OAM.Generator ParameterCardinality
generateParameterTypeFromOperation operationName = getParametersFromOperationConcrete >=> generateParameterType operationName
generateParameterTypeFromOperation :: [OAT.Referencable OAT.ParameterObject] -> Text -> OAT.OperationObject -> OAM.Generator ParameterCardinality
generateParameterTypeFromOperation pathParams operationName = getParametersFromOperationConcrete pathParams >=> generateParameterType operationName

generateParameterType :: Text -> [(OAT.ParameterObject, [Text])] -> OAM.Generator ParameterCardinality
generateParameterType operationName parameters = OAM.nested "parameters" $ do
Expand Down Expand Up @@ -152,12 +152,24 @@ getParameterLocationPrefix =
)
. OAT.parameterObjectIn

-- | Extracts all parameters of an operation
--
-- Concrete objects are always added. References try to get resolved to a concrete object.
-- If this fails, the parameter is skipped and a warning gets produced.
getParametersFromOperationConcrete :: OAT.OperationObject -> OAM.Generator [(OAT.ParameterObject, [Text])]
getParametersFromOperationConcrete =
-- | Override parameters defined at path level with parameters which are defined at operation level
overrideParameters :: [(OAT.ParameterObject, [Text])] -> [(OAT.ParameterObject, [Text])] -> [(OAT.ParameterObject, [Text])]
overrideParameters pathParams operationParams =
-- According to OpenAPI specification, the unique parameter is identified by a combination of name and location.
-- So, we are using (name, in') as key.
-- We emit all the path parameters that were not overridden, and then all the
-- operation parameters. (Note, we use lists to keep the original parameter
-- order for generating code).
let getKey :: (OAT.ParameterObject, [Text]) -> (Text, OAT.ParameterObjectLocation)
getKey p =
let po = fst p
in (OAT.parameterObjectName po, OAT.parameterObjectIn po)
opKeys = Set.fromList (map getKey operationParams)
pathParamsWithoutOverride = filter (\p -> Set.notMember (getKey p) opKeys) pathParams
in pathParamsWithoutOverride <> operationParams

getConcreteParameters :: [OAT.Referencable OAT.ParameterObject] -> OAM.Generator [(OAT.ParameterObject, [Text])]
getConcreteParameters =
OAM.nested "parameters"
. fmap Maybe.catMaybes
. mapM
Expand All @@ -172,7 +184,16 @@ getParametersFromOperationConcrete =
pure $ (,["components", "parameters", name]) <$> p
)
. zip ([0 ..] :: [Int])
. OAT.operationObjectParameters

-- | Extracts all parameters of an operation
--
-- Concrete objects are always added. References try to get resolved to a concrete object.
-- If this fails, the parameter is skipped and a warning gets produced.
getParametersFromOperationConcrete :: [OAT.Referencable OAT.ParameterObject] -> OAT.OperationObject -> OAM.Generator [(OAT.ParameterObject, [Text])]
getParametersFromOperationConcrete pathParameters operation = do
operationParameters <- getConcreteParameters $ OAT.operationObjectParameters operation
concretePathParameters <- getConcreteParameters pathParameters
pure $ overrideParameters concretePathParameters operationParameters

getSchemaFromParameterObjectSchema :: OAT.ParameterObjectSchema -> OAM.Generator (Maybe OAS.Schema)
getSchemaFromParameterObjectSchema (OAT.SimpleParameterObjectSchema OAT.SimpleParameterSchema {..}) = pure $ Just simpleParameterSchemaSchema
Expand Down
8 changes: 5 additions & 3 deletions openapi3-code-generator/src/OpenAPI/Generate/Operation.hs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ defineOperationsForPath mainModuleName requestPath pathItemObject = OAM.nested r
operationsToGenerate <- OAM.getSetting OAO.settingOperationsToGenerate
fmap (BF.bimap sequence Set.unions)
. mapAndUnzipM
(uncurry (defineModuleForOperation mainModuleName requestPath))
(uncurry (defineModuleForOperation mainModuleName requestPath (OAT.pathItemObjectParameters pathItemObject)))
$ filterEmptyAndOmittedOperations
operationsToGenerate
[ ("GET", OAT.pathItemObjectGet pathItemObject),
Expand Down Expand Up @@ -76,13 +76,15 @@ defineModuleForOperation ::
-- | The path to the request (This is the key from the map of Operations)
-- It may contain placeholder variables in the form of /my/{var}/path/
Text ->
-- | Path parameter definition
[OAT.Referencable OAT.ParameterObject] ->
-- | HTTP Method (GET,POST,etc)
Text ->
-- | The Operation Object
OAT.OperationObject ->
-- | commented function definition and implementation
OAM.Generator (Q Dep.ModuleDefinition, Dep.Models)
defineModuleForOperation mainModuleName requestPath method operation = OAM.nested method $ do
defineModuleForOperation mainModuleName requestPath pathParams method operation = OAM.nested method $ do
operationIdName <- getOperationName requestPath method operation
convertToCamelCase <- OAM.getSetting OAO.settingConvertToCamelCase
let operationIdAsText = T.pack $ show operationIdName
Expand All @@ -92,7 +94,7 @@ defineModuleForOperation mainModuleName requestPath method operation = OAM.neste
(bodySchema, bodyPath) <- getBodySchemaFromOperation operation
(responseTypeName, responseTransformerExp, responseBodyDefinitions, responseBodyDependencies) <- OAR.getResponseDefinitions operation appendToOperationName
(bodyType, (bodyDefinition, bodyDependencies)) <- OAM.resetPath bodyPath $ getBodyType bodySchema appendToOperationName
parameterCardinality <- generateParameterTypeFromOperation operationIdAsText operation
parameterCardinality <- generateParameterTypeFromOperation pathParams operationIdAsText operation
paramDescriptions <-
(<> ["The request body to send" | not $ null bodyType])
<$> ( case parameterCardinality of
Expand Down
2 changes: 1 addition & 1 deletion openapi3-code-generator/src/OpenAPI/Generate/Types.hs
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,7 @@ data ParameterObjectLocation
| HeaderParameterObjectLocation
| PathParameterObjectLocation
| CookieParameterObjectLocation
deriving (Show, Eq, Generic)
deriving (Show, Eq, Ord, Generic)

instance FromJSON ParameterObjectLocation where
parseJSON = withText "ParameterObjectLocation" $ \case
Expand Down
51 changes: 51 additions & 0 deletions specifications/z_complex_self_made_example.yml
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,58 @@ paths:
application/json:
schema:
$ref: "#/components/schemas/Dog"
/pet/multiparam2/{status}:
parameters:
- name: status
in: path
description: Status in path (from path params)
required: true
schema:
type: integer
enum:
- 1
- 3
- 5
get:
description: Operation with multiple parameters (some from path params)
operationId: multiParamPathParam
parameters:
- name: status
in: query
description: Status in query
required: true
schema:
type: string
enum:
- available
- pending
- sold
- name: filter
in: query
description: Filter the entries?
schema:
type: boolean
- name: referenceParameter
in: query
required: true
schema:
$ref: '#/components/schemas/Cat'
responses:
'200':
description: successful operation
content:
application/json:
schema:
$ref: "#/components/schemas/Dog"

/pet/multiparam/{status}:
parameters:
- name: status
in: path
description: Status in path from path params, will be overridden below.
required: true
schema:
type: string
get:
description: Operation with multiple parameters
operationId: multiParam
Expand Down
1 change: 1 addition & 0 deletions testing/golden-output/openapi.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ library
exposed-modules:
OpenAPI
OpenAPI.Operations.MultiParam
OpenAPI.Operations.MultiParamPathParam
OpenAPI.Operations.MultiParamWithFixedEnum
OpenAPI.Operations.NoParam
OpenAPI.Operations.SingleParam
Expand Down
2 changes: 2 additions & 0 deletions testing/golden-output/src/OpenAPI.hs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
-- | The main module which exports all functionality.
module OpenAPI (
module OpenAPI.Operations.MultiParam,
module OpenAPI.Operations.MultiParamPathParam,
module OpenAPI.Operations.MultiParamWithFixedEnum,
module OpenAPI.Operations.NoParam,
module OpenAPI.Operations.SingleParam,
Expand All @@ -28,6 +29,7 @@ module OpenAPI (
) where

import OpenAPI.Operations.MultiParam
import OpenAPI.Operations.MultiParamPathParam
import OpenAPI.Operations.MultiParamWithFixedEnum
import OpenAPI.Operations.NoParam
import OpenAPI.Operations.SingleParam
Expand Down
Loading