We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Bug: Routes with duplicate parameter names are not shown in OpenAPI rendering
### Description

OpenAPI schema fails to generate if there's 2 parameters present with identical name, route is subsequently removed from OpenAPI schema.

### URL to code causing the issue

_No response_

### MCVE

```python
from typing import Annotated

from litestar import Litestar, post
from litestar.params import Parameter


@post("/test")
async def route(
    name: Annotated[str | None, Parameter(cookie="name")] = None,
    name_header: Annotated[str | None, Parameter(header="name")] = None,
) -> str:
    return name or name_header or ""


app = Litestar(
    route_handlers=[route],
)
```


### Steps to reproduce

```bash
1. Launch uvicorn server `uvicorn app:app`
2. Go to http://127.0.0.1:8000/schema/swagger
3. See error
```


### Screenshots

_No response_

### Logs

```bash
$ uvicorn app:app
INFO:     Started server process [8376]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO:     127.0.0.1:54807 - "GET /schema/swagger HTTP/1.1" 500 Internal Server Error
INFO:     127.0.0.1:54807 - "GET /schema/swagger HTTP/1.1" 200 OK
```


### Litestar Version

2.3.2

### Platform

- [ ] Linux
- [ ] Mac
- [X] Windows
- [ ] Other (Please specify in the description above)


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `litestar/_openapi/parameters.py`
Content:
```
1 from __future__ import annotations
2 
3 from typing import TYPE_CHECKING
4 
5 from litestar._openapi.schema_generation.utils import get_formatted_examples
6 from litestar.constants import RESERVED_KWARGS
7 from litestar.enums import ParamType
8 from litestar.exceptions import ImproperlyConfiguredException
9 from litestar.openapi.spec.parameter import Parameter
10 from litestar.openapi.spec.schema import Schema
11 from litestar.params import DependencyKwarg, ParameterKwarg
12 from litestar.types import Empty
13 
14 __all__ = ("create_parameter_for_handler",)
15 
16 from litestar.typing import FieldDefinition
17 
18 if TYPE_CHECKING:
19     from litestar._openapi.schema_generation import SchemaCreator
20     from litestar.di import Provide
21     from litestar.handlers.base import BaseRouteHandler
22     from litestar.openapi.spec import Reference
23     from litestar.types.internal_types import PathParameterDefinition
24 
25 
26 class ParameterCollection:
27     """Facilitates conditional deduplication of parameters.
28 
29     If multiple parameters with the same name are produced for a handler, the condition is ignored if the two
30     ``Parameter`` instances are the same (the first is retained and any duplicates are ignored). If the ``Parameter``
31     instances are not the same, an exception is raised.
32     """
33 
34     def __init__(self, route_handler: BaseRouteHandler) -> None:
35         """Initialize ``ParameterCollection``.
36 
37         Args:
38             route_handler: Associated route handler
39         """
40         self.route_handler = route_handler
41         self._parameters: dict[str, Parameter] = {}
42 
43     def add(self, parameter: Parameter) -> None:
44         """Add a ``Parameter`` to the collection.
45 
46         If an existing parameter with the same name and type already exists, the
47         parameter is ignored.
48 
49         If an existing parameter with the same name but different type exists, raises
50         ``ImproperlyConfiguredException``.
51         """
52 
53         if parameter.name not in self._parameters:
54             # because we are defining routes as unique per path, we have to handle here a situation when there is an optional
55             # path parameter. e.g. get(path=["/", "/{param:str}"]). When parsing the parameter for path, the route handler
56             # would still have a kwarg called param:
57             # def handler(param: str | None) -> ...
58             if parameter.param_in != ParamType.QUERY or all(
59                 "{" + parameter.name + ":" not in path for path in self.route_handler.paths
60             ):
61                 self._parameters[parameter.name] = parameter
62             return
63 
64         pre_existing = self._parameters[parameter.name]
65         if parameter == pre_existing:
66             return
67 
68         raise ImproperlyConfiguredException(
69             f"OpenAPI schema generation for handler `{self.route_handler}` detected multiple parameters named "
70             f"'{parameter.name}' with different types."
71         )
72 
73     def list(self) -> list[Parameter]:
74         """Return a list of all ``Parameter``'s in the collection."""
75         return list(self._parameters.values())
76 
77 
78 def create_parameter(
79     field_definition: FieldDefinition,
80     parameter_name: str,
81     path_parameters: tuple[PathParameterDefinition, ...],
82     schema_creator: SchemaCreator,
83 ) -> Parameter:
84     """Create an OpenAPI Parameter instance."""
85 
86     result: Schema | Reference | None = None
87     kwarg_definition = (
88         field_definition.kwarg_definition if isinstance(field_definition.kwarg_definition, ParameterKwarg) else None
89     )
90 
91     if any(path_param.name == parameter_name for path_param in path_parameters):
92         param_in = ParamType.PATH
93         is_required = True
94         result = schema_creator.for_field_definition(field_definition)
95     elif kwarg_definition and kwarg_definition.header:
96         parameter_name = kwarg_definition.header
97         param_in = ParamType.HEADER
98         is_required = field_definition.is_required
99     elif kwarg_definition and kwarg_definition.cookie:
100         parameter_name = kwarg_definition.cookie
101         param_in = ParamType.COOKIE
102         is_required = field_definition.is_required
103     else:
104         is_required = field_definition.is_required
105         param_in = ParamType.QUERY
106         parameter_name = kwarg_definition.query if kwarg_definition and kwarg_definition.query else parameter_name
107 
108     if not result:
109         result = schema_creator.for_field_definition(field_definition)
110 
111     schema = result if isinstance(result, Schema) else schema_creator.schemas[result.value]
112 
113     examples_list = kwarg_definition.examples or [] if kwarg_definition else []
114     examples = get_formatted_examples(field_definition, examples_list)
115 
116     return Parameter(
117         description=schema.description,
118         name=parameter_name,
119         param_in=param_in,
120         required=is_required,
121         schema=result,
122         examples=examples or None,
123     )
124 
125 
126 def get_recursive_handler_parameters(
127     field_name: str,
128     field_definition: FieldDefinition,
129     dependency_providers: dict[str, Provide],
130     route_handler: BaseRouteHandler,
131     path_parameters: tuple[PathParameterDefinition, ...],
132     schema_creator: SchemaCreator,
133 ) -> list[Parameter]:
134     """Create and return parameters for a handler.
135 
136     If the provided field is not a dependency, a normal parameter is created and returned as a list, otherwise
137     `create_parameter_for_handler()` is called to generate parameters for the dependency.
138     """
139 
140     if field_name not in dependency_providers:
141         return [
142             create_parameter(
143                 field_definition=field_definition,
144                 parameter_name=field_name,
145                 path_parameters=path_parameters,
146                 schema_creator=schema_creator,
147             )
148         ]
149 
150     dependency_fields = dependency_providers[field_name].signature_model._fields
151     return create_parameter_for_handler(
152         route_handler=route_handler,
153         handler_fields=dependency_fields,
154         path_parameters=path_parameters,
155         schema_creator=schema_creator,
156     )
157 
158 
159 def get_layered_parameter(
160     field_name: str,
161     field_definition: FieldDefinition,
162     layered_parameters: dict[str, FieldDefinition],
163     path_parameters: tuple[PathParameterDefinition, ...],
164     schema_creator: SchemaCreator,
165 ) -> Parameter:
166     """Create a layered parameter for a given signature model field.
167 
168     Layer info is extracted from the provided ``layered_parameters`` dict and set as the field's ``field_info`` attribute.
169     """
170     layer_field = layered_parameters[field_name]
171 
172     field = field_definition if field_definition.is_parameter_field else layer_field
173     default = layer_field.default if field_definition.has_default else field_definition.default
174     annotation = field_definition.annotation if field_definition is not Empty else layer_field.annotation
175 
176     parameter_name = field_name
177     if isinstance(field.kwarg_definition, ParameterKwarg):
178         parameter_name = (
179             field.kwarg_definition.query or field.kwarg_definition.header or field.kwarg_definition.cookie or field_name
180         )
181 
182     field_definition = FieldDefinition.from_kwarg(
183         inner_types=field.inner_types,
184         default=default,
185         extra=field.extra,
186         annotation=annotation,
187         kwarg_definition=field.kwarg_definition,
188         name=field_name,
189     )
190     return create_parameter(
191         field_definition=field_definition,
192         parameter_name=parameter_name,
193         path_parameters=path_parameters,
194         schema_creator=schema_creator,
195     )
196 
197 
198 def create_parameter_for_handler(
199     route_handler: BaseRouteHandler,
200     handler_fields: dict[str, FieldDefinition],
201     path_parameters: tuple[PathParameterDefinition, ...],
202     schema_creator: SchemaCreator,
203 ) -> list[Parameter]:
204     """Create a list of path/query/header Parameter models for the given PathHandler."""
205     parameters = ParameterCollection(route_handler=route_handler)
206     dependency_providers = route_handler.resolve_dependencies()
207     layered_parameters = route_handler.resolve_layered_parameters()
208 
209     unique_handler_fields = tuple(
210         (k, v) for k, v in handler_fields.items() if k not in RESERVED_KWARGS and k not in layered_parameters
211     )
212     unique_layered_fields = tuple(
213         (k, v) for k, v in layered_parameters.items() if k not in RESERVED_KWARGS and k not in handler_fields
214     )
215     intersection_fields = tuple(
216         (k, v) for k, v in handler_fields.items() if k not in RESERVED_KWARGS and k in layered_parameters
217     )
218 
219     for field_name, field_definition in unique_handler_fields:
220         if isinstance(field_definition.kwarg_definition, DependencyKwarg) and field_name not in dependency_providers:
221             # never document explicit dependencies
222             continue
223 
224         for parameter in get_recursive_handler_parameters(
225             field_name=field_name,
226             field_definition=field_definition,
227             dependency_providers=dependency_providers,
228             route_handler=route_handler,
229             path_parameters=path_parameters,
230             schema_creator=schema_creator,
231         ):
232             parameters.add(parameter)
233 
234     for field_name, field_definition in unique_layered_fields:
235         parameters.add(
236             create_parameter(
237                 field_definition=field_definition,
238                 parameter_name=field_name,
239                 path_parameters=path_parameters,
240                 schema_creator=schema_creator,
241             )
242         )
243 
244     for field_name, field_definition in intersection_fields:
245         parameters.add(
246             get_layered_parameter(
247                 field_name=field_name,
248                 field_definition=field_definition,
249                 layered_parameters=layered_parameters,
250                 path_parameters=path_parameters,
251                 schema_creator=schema_creator,
252             )
253         )
254 
255     return parameters.list()
256
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/litestar/_openapi/parameters.py b/litestar/_openapi/parameters.py
--- a/litestar/_openapi/parameters.py
+++ b/litestar/_openapi/parameters.py
@@ -38,7 +38,7 @@
             route_handler: Associated route handler
         """
         self.route_handler = route_handler
-        self._parameters: dict[str, Parameter] = {}
+        self._parameters: dict[tuple[str, str], Parameter] = {}
 
     def add(self, parameter: Parameter) -> None:
         """Add a ``Parameter`` to the collection.
@@ -50,18 +50,18 @@
         ``ImproperlyConfiguredException``.
         """
 
-        if parameter.name not in self._parameters:
+        if (parameter.name, parameter.param_in) not in self._parameters:
             # because we are defining routes as unique per path, we have to handle here a situation when there is an optional
             # path parameter. e.g. get(path=["/", "/{param:str}"]). When parsing the parameter for path, the route handler
             # would still have a kwarg called param:
             # def handler(param: str | None) -> ...
             if parameter.param_in != ParamType.QUERY or all(
-                "{" + parameter.name + ":" not in path for path in self.route_handler.paths
+                f"{{{parameter.name}:" not in path for path in self.route_handler.paths
             ):
-                self._parameters[parameter.name] = parameter
+                self._parameters[(parameter.name, parameter.param_in)] = parameter
             return
 
-        pre_existing = self._parameters[parameter.name]
+        pre_existing = self._parameters[(parameter.name, parameter.param_in)]
         if parameter == pre_existing:
             return
 
@@ -206,13 +206,13 @@
     dependency_providers = route_handler.resolve_dependencies()
     layered_parameters = route_handler.resolve_layered_parameters()
 
-    unique_handler_fields = tuple(
+    unique_handler_fields = (
         (k, v) for k, v in handler_fields.items() if k not in RESERVED_KWARGS and k not in layered_parameters
     )
-    unique_layered_fields = tuple(
+    unique_layered_fields = (
         (k, v) for k, v in layered_parameters.items() if k not in RESERVED_KWARGS and k not in handler_fields
     )
-    intersection_fields = tuple(
+    intersection_fields = (
         (k, v) for k, v in handler_fields.items() if k not in RESERVED_KWARGS and k in layered_parameters
     )

{"golden_diff": "diff --git a/litestar/_openapi/parameters.py b/litestar/_openapi/parameters.py\n--- a/litestar/_openapi/parameters.py\n+++ b/litestar/_openapi/parameters.py\n@@ -38,7 +38,7 @@\n             route_handler: Associated route handler\n         \"\"\"\n         self.route_handler = route_handler\n-        self._parameters: dict[str, Parameter] = {}\n+        self._parameters: dict[tuple[str, str], Parameter] = {}\n \n     def add(self, parameter: Parameter) -> None:\n         \"\"\"Add a ``Parameter`` to the collection.\n@@ -50,18 +50,18 @@\n         ``ImproperlyConfiguredException``.\n         \"\"\"\n \n-        if parameter.name not in self._parameters:\n+        if (parameter.name, parameter.param_in) not in self._parameters:\n             # because we are defining routes as unique per path, we have to handle here a situation when there is an optional\n             # path parameter. e.g. get(path=[\"/\", \"/{param:str}\"]). When parsing the parameter for path, the route handler\n             # would still have a kwarg called param:\n             # def handler(param: str | None) -> ...\n             if parameter.param_in != ParamType.QUERY or all(\n-                \"{\" + parameter.name + \":\" not in path for path in self.route_handler.paths\n+                f\"{{{parameter.name}:\" not in path for path in self.route_handler.paths\n             ):\n-                self._parameters[parameter.name] = parameter\n+                self._parameters[(parameter.name, parameter.param_in)] = parameter\n             return\n \n-        pre_existing = self._parameters[parameter.name]\n+        pre_existing = self._parameters[(parameter.name, parameter.param_in)]\n         if parameter == pre_existing:\n             return\n \n@@ -206,13 +206,13 @@\n     dependency_providers = route_handler.resolve_dependencies()\n     layered_parameters = route_handler.resolve_layered_parameters()\n \n-    unique_handler_fields = tuple(\n+    unique_handler_fields = (\n         (k, v) for k, v in handler_fields.items() if k not in RESERVED_KWARGS and k not in layered_parameters\n     )\n-    unique_layered_fields = tuple(\n+    unique_layered_fields = (\n         (k, v) for k, v in layered_parameters.items() if k not in RESERVED_KWARGS and k not in handler_fields\n     )\n-    intersection_fields = tuple(\n+    intersection_fields = (\n         (k, v) for k, v in handler_fields.items() if k not in RESERVED_KWARGS and k in layered_parameters\n     )\n", "issue": "Bug: Routes with duplicate parameter names are not shown in OpenAPI rendering\n### Description\r\n\r\nOpenAPI schema fails to generate if there's 2 parameters present with identical name, route is subsequently removed from OpenAPI schema.\r\n\r\n### URL to code causing the issue\r\n\r\n_No response_\r\n\r\n### MCVE\r\n\r\n```python\r\nfrom typing import Annotated\r\n\r\nfrom litestar import Litestar, post\r\nfrom litestar.params import Parameter\r\n\r\n\r\n@post(\"/test\")\r\nasync def route(\r\n    name: Annotated[str | None, Parameter(cookie=\"name\")] = None,\r\n    name_header: Annotated[str | None, Parameter(header=\"name\")] = None,\r\n) -> str:\r\n    return name or name_header or \"\"\r\n\r\n\r\napp = Litestar(\r\n    route_handlers=[route],\r\n)\r\n```\r\n\r\n\r\n### Steps to reproduce\r\n\r\n```bash\r\n1. Launch uvicorn server `uvicorn app:app`\r\n2. Go to http://127.0.0.1:8000/schema/swagger\r\n3. See error\r\n```\r\n\r\n\r\n### Screenshots\r\n\r\n_No response_\r\n\r\n### Logs\r\n\r\n```bash\r\n$ uvicorn app:app\r\nINFO:     Started server process [8376]\r\nINFO:     Waiting for application startup.\r\nINFO:     Application startup complete.\r\nINFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)\r\nINFO:     127.0.0.1:54807 - \"GET /schema/swagger HTTP/1.1\" 500 Internal Server Error\r\nINFO:     127.0.0.1:54807 - \"GET /schema/swagger HTTP/1.1\" 200 OK\r\n```\r\n\r\n\r\n### Litestar Version\r\n\r\n2.3.2\r\n\r\n### Platform\r\n\r\n- [ ] Linux\r\n- [ ] Mac\r\n- [X] Windows\r\n- [ ] Other (Please specify in the description above)\r\n\n", "before_files": [{"content": "from __future__ import annotations\n\nfrom typing import TYPE_CHECKING\n\nfrom litestar._openapi.schema_generation.utils import get_formatted_examples\nfrom litestar.constants import RESERVED_KWARGS\nfrom litestar.enums import ParamType\nfrom litestar.exceptions import ImproperlyConfiguredException\nfrom litestar.openapi.spec.parameter import Parameter\nfrom litestar.openapi.spec.schema import Schema\nfrom litestar.params import DependencyKwarg, ParameterKwarg\nfrom litestar.types import Empty\n\n__all__ = (\"create_parameter_for_handler\",)\n\nfrom litestar.typing import FieldDefinition\n\nif TYPE_CHECKING:\n    from litestar._openapi.schema_generation import SchemaCreator\n    from litestar.di import Provide\n    from litestar.handlers.base import BaseRouteHandler\n    from litestar.openapi.spec import Reference\n    from litestar.types.internal_types import PathParameterDefinition\n\n\nclass ParameterCollection:\n    \"\"\"Facilitates conditional deduplication of parameters.\n\n    If multiple parameters with the same name are produced for a handler, the condition is ignored if the two\n    ``Parameter`` instances are the same (the first is retained and any duplicates are ignored). If the ``Parameter``\n    instances are not the same, an exception is raised.\n    \"\"\"\n\n    def __init__(self, route_handler: BaseRouteHandler) -> None:\n        \"\"\"Initialize ``ParameterCollection``.\n\n        Args:\n            route_handler: Associated route handler\n        \"\"\"\n        self.route_handler = route_handler\n        self._parameters: dict[str, Parameter] = {}\n\n    def add(self, parameter: Parameter) -> None:\n        \"\"\"Add a ``Parameter`` to the collection.\n\n        If an existing parameter with the same name and type already exists, the\n        parameter is ignored.\n\n        If an existing parameter with the same name but different type exists, raises\n        ``ImproperlyConfiguredException``.\n        \"\"\"\n\n        if parameter.name not in self._parameters:\n            # because we are defining routes as unique per path, we have to handle here a situation when there is an optional\n            # path parameter. e.g. get(path=[\"/\", \"/{param:str}\"]). When parsing the parameter for path, the route handler\n            # would still have a kwarg called param:\n            # def handler(param: str | None) -> ...\n            if parameter.param_in != ParamType.QUERY or all(\n                \"{\" + parameter.name + \":\" not in path for path in self.route_handler.paths\n            ):\n                self._parameters[parameter.name] = parameter\n            return\n\n        pre_existing = self._parameters[parameter.name]\n        if parameter == pre_existing:\n            return\n\n        raise ImproperlyConfiguredException(\n            f\"OpenAPI schema generation for handler `{self.route_handler}` detected multiple parameters named \"\n            f\"'{parameter.name}' with different types.\"\n        )\n\n    def list(self) -> list[Parameter]:\n        \"\"\"Return a list of all ``Parameter``'s in the collection.\"\"\"\n        return list(self._parameters.values())\n\n\ndef create_parameter(\n    field_definition: FieldDefinition,\n    parameter_name: str,\n    path_parameters: tuple[PathParameterDefinition, ...],\n    schema_creator: SchemaCreator,\n) -> Parameter:\n    \"\"\"Create an OpenAPI Parameter instance.\"\"\"\n\n    result: Schema | Reference | None = None\n    kwarg_definition = (\n        field_definition.kwarg_definition if isinstance(field_definition.kwarg_definition, ParameterKwarg) else None\n    )\n\n    if any(path_param.name == parameter_name for path_param in path_parameters):\n        param_in = ParamType.PATH\n        is_required = True\n        result = schema_creator.for_field_definition(field_definition)\n    elif kwarg_definition and kwarg_definition.header:\n        parameter_name = kwarg_definition.header\n        param_in = ParamType.HEADER\n        is_required = field_definition.is_required\n    elif kwarg_definition and kwarg_definition.cookie:\n        parameter_name = kwarg_definition.cookie\n        param_in = ParamType.COOKIE\n        is_required = field_definition.is_required\n    else:\n        is_required = field_definition.is_required\n        param_in = ParamType.QUERY\n        parameter_name = kwarg_definition.query if kwarg_definition and kwarg_definition.query else parameter_name\n\n    if not result:\n        result = schema_creator.for_field_definition(field_definition)\n\n    schema = result if isinstance(result, Schema) else schema_creator.schemas[result.value]\n\n    examples_list = kwarg_definition.examples or [] if kwarg_definition else []\n    examples = get_formatted_examples(field_definition, examples_list)\n\n    return Parameter(\n        description=schema.description,\n        name=parameter_name,\n        param_in=param_in,\n        required=is_required,\n        schema=result,\n        examples=examples or None,\n    )\n\n\ndef get_recursive_handler_parameters(\n    field_name: str,\n    field_definition: FieldDefinition,\n    dependency_providers: dict[str, Provide],\n    route_handler: BaseRouteHandler,\n    path_parameters: tuple[PathParameterDefinition, ...],\n    schema_creator: SchemaCreator,\n) -> list[Parameter]:\n    \"\"\"Create and return parameters for a handler.\n\n    If the provided field is not a dependency, a normal parameter is created and returned as a list, otherwise\n    `create_parameter_for_handler()` is called to generate parameters for the dependency.\n    \"\"\"\n\n    if field_name not in dependency_providers:\n        return [\n            create_parameter(\n                field_definition=field_definition,\n                parameter_name=field_name,\n                path_parameters=path_parameters,\n                schema_creator=schema_creator,\n            )\n        ]\n\n    dependency_fields = dependency_providers[field_name].signature_model._fields\n    return create_parameter_for_handler(\n        route_handler=route_handler,\n        handler_fields=dependency_fields,\n        path_parameters=path_parameters,\n        schema_creator=schema_creator,\n    )\n\n\ndef get_layered_parameter(\n    field_name: str,\n    field_definition: FieldDefinition,\n    layered_parameters: dict[str, FieldDefinition],\n    path_parameters: tuple[PathParameterDefinition, ...],\n    schema_creator: SchemaCreator,\n) -> Parameter:\n    \"\"\"Create a layered parameter for a given signature model field.\n\n    Layer info is extracted from the provided ``layered_parameters`` dict and set as the field's ``field_info`` attribute.\n    \"\"\"\n    layer_field = layered_parameters[field_name]\n\n    field = field_definition if field_definition.is_parameter_field else layer_field\n    default = layer_field.default if field_definition.has_default else field_definition.default\n    annotation = field_definition.annotation if field_definition is not Empty else layer_field.annotation\n\n    parameter_name = field_name\n    if isinstance(field.kwarg_definition, ParameterKwarg):\n        parameter_name = (\n            field.kwarg_definition.query or field.kwarg_definition.header or field.kwarg_definition.cookie or field_name\n        )\n\n    field_definition = FieldDefinition.from_kwarg(\n        inner_types=field.inner_types,\n        default=default,\n        extra=field.extra,\n        annotation=annotation,\n        kwarg_definition=field.kwarg_definition,\n        name=field_name,\n    )\n    return create_parameter(\n        field_definition=field_definition,\n        parameter_name=parameter_name,\n        path_parameters=path_parameters,\n        schema_creator=schema_creator,\n    )\n\n\ndef create_parameter_for_handler(\n    route_handler: BaseRouteHandler,\n    handler_fields: dict[str, FieldDefinition],\n    path_parameters: tuple[PathParameterDefinition, ...],\n    schema_creator: SchemaCreator,\n) -> list[Parameter]:\n    \"\"\"Create a list of path/query/header Parameter models for the given PathHandler.\"\"\"\n    parameters = ParameterCollection(route_handler=route_handler)\n    dependency_providers = route_handler.resolve_dependencies()\n    layered_parameters = route_handler.resolve_layered_parameters()\n\n    unique_handler_fields = tuple(\n        (k, v) for k, v in handler_fields.items() if k not in RESERVED_KWARGS and k not in layered_parameters\n    )\n    unique_layered_fields = tuple(\n        (k, v) for k, v in layered_parameters.items() if k not in RESERVED_KWARGS and k not in handler_fields\n    )\n    intersection_fields = tuple(\n        (k, v) for k, v in handler_fields.items() if k not in RESERVED_KWARGS and k in layered_parameters\n    )\n\n    for field_name, field_definition in unique_handler_fields:\n        if isinstance(field_definition.kwarg_definition, DependencyKwarg) and field_name not in dependency_providers:\n            # never document explicit dependencies\n            continue\n\n        for parameter in get_recursive_handler_parameters(\n            field_name=field_name,\n            field_definition=field_definition,\n            dependency_providers=dependency_providers,\n            route_handler=route_handler,\n            path_parameters=path_parameters,\n            schema_creator=schema_creator,\n        ):\n            parameters.add(parameter)\n\n    for field_name, field_definition in unique_layered_fields:\n        parameters.add(\n            create_parameter(\n                field_definition=field_definition,\n                parameter_name=field_name,\n                path_parameters=path_parameters,\n                schema_creator=schema_creator,\n            )\n        )\n\n    for field_name, field_definition in intersection_fields:\n        parameters.add(\n            get_layered_parameter(\n                field_name=field_name,\n                field_definition=field_definition,\n                layered_parameters=layered_parameters,\n                path_parameters=path_parameters,\n                schema_creator=schema_creator,\n            )\n        )\n\n    return parameters.list()\n", "path": "litestar/_openapi/parameters.py"}], "after_files": [{"content": "from __future__ import annotations\n\nfrom typing import TYPE_CHECKING\n\nfrom litestar._openapi.schema_generation.utils import get_formatted_examples\nfrom litestar.constants import RESERVED_KWARGS\nfrom litestar.enums import ParamType\nfrom litestar.exceptions import ImproperlyConfiguredException\nfrom litestar.openapi.spec.parameter import Parameter\nfrom litestar.openapi.spec.schema import Schema\nfrom litestar.params import DependencyKwarg, ParameterKwarg\nfrom litestar.types import Empty\n\n__all__ = (\"create_parameter_for_handler\",)\n\nfrom litestar.typing import FieldDefinition\n\nif TYPE_CHECKING:\n    from litestar._openapi.schema_generation import SchemaCreator\n    from litestar.di import Provide\n    from litestar.handlers.base import BaseRouteHandler\n    from litestar.openapi.spec import Reference\n    from litestar.types.internal_types import PathParameterDefinition\n\n\nclass ParameterCollection:\n    \"\"\"Facilitates conditional deduplication of parameters.\n\n    If multiple parameters with the same name are produced for a handler, the condition is ignored if the two\n    ``Parameter`` instances are the same (the first is retained and any duplicates are ignored). If the ``Parameter``\n    instances are not the same, an exception is raised.\n    \"\"\"\n\n    def __init__(self, route_handler: BaseRouteHandler) -> None:\n        \"\"\"Initialize ``ParameterCollection``.\n\n        Args:\n            route_handler: Associated route handler\n        \"\"\"\n        self.route_handler = route_handler\n        self._parameters: dict[tuple[str, str], Parameter] = {}\n\n    def add(self, parameter: Parameter) -> None:\n        \"\"\"Add a ``Parameter`` to the collection.\n\n        If an existing parameter with the same name and type already exists, the\n        parameter is ignored.\n\n        If an existing parameter with the same name but different type exists, raises\n        ``ImproperlyConfiguredException``.\n        \"\"\"\n\n        if (parameter.name, parameter.param_in) not in self._parameters:\n            # because we are defining routes as unique per path, we have to handle here a situation when there is an optional\n            # path parameter. e.g. get(path=[\"/\", \"/{param:str}\"]). When parsing the parameter for path, the route handler\n            # would still have a kwarg called param:\n            # def handler(param: str | None) -> ...\n            if parameter.param_in != ParamType.QUERY or all(\n                f\"{{{parameter.name}:\" not in path for path in self.route_handler.paths\n            ):\n                self._parameters[(parameter.name, parameter.param_in)] = parameter\n            return\n\n        pre_existing = self._parameters[(parameter.name, parameter.param_in)]\n        if parameter == pre_existing:\n            return\n\n        raise ImproperlyConfiguredException(\n            f\"OpenAPI schema generation for handler `{self.route_handler}` detected multiple parameters named \"\n            f\"'{parameter.name}' with different types.\"\n        )\n\n    def list(self) -> list[Parameter]:\n        \"\"\"Return a list of all ``Parameter``'s in the collection.\"\"\"\n        return list(self._parameters.values())\n\n\ndef create_parameter(\n    field_definition: FieldDefinition,\n    parameter_name: str,\n    path_parameters: tuple[PathParameterDefinition, ...],\n    schema_creator: SchemaCreator,\n) -> Parameter:\n    \"\"\"Create an OpenAPI Parameter instance.\"\"\"\n\n    result: Schema | Reference | None = None\n    kwarg_definition = (\n        field_definition.kwarg_definition if isinstance(field_definition.kwarg_definition, ParameterKwarg) else None\n    )\n\n    if any(path_param.name == parameter_name for path_param in path_parameters):\n        param_in = ParamType.PATH\n        is_required = True\n        result = schema_creator.for_field_definition(field_definition)\n    elif kwarg_definition and kwarg_definition.header:\n        parameter_name = kwarg_definition.header\n        param_in = ParamType.HEADER\n        is_required = field_definition.is_required\n    elif kwarg_definition and kwarg_definition.cookie:\n        parameter_name = kwarg_definition.cookie\n        param_in = ParamType.COOKIE\n        is_required = field_definition.is_required\n    else:\n        is_required = field_definition.is_required\n        param_in = ParamType.QUERY\n        parameter_name = kwarg_definition.query if kwarg_definition and kwarg_definition.query else parameter_name\n\n    if not result:\n        result = schema_creator.for_field_definition(field_definition)\n\n    schema = result if isinstance(result, Schema) else schema_creator.schemas[result.value]\n\n    examples_list = kwarg_definition.examples or [] if kwarg_definition else []\n    examples = get_formatted_examples(field_definition, examples_list)\n\n    return Parameter(\n        description=schema.description,\n        name=parameter_name,\n        param_in=param_in,\n        required=is_required,\n        schema=result,\n        examples=examples or None,\n    )\n\n\ndef get_recursive_handler_parameters(\n    field_name: str,\n    field_definition: FieldDefinition,\n    dependency_providers: dict[str, Provide],\n    route_handler: BaseRouteHandler,\n    path_parameters: tuple[PathParameterDefinition, ...],\n    schema_creator: SchemaCreator,\n) -> list[Parameter]:\n    \"\"\"Create and return parameters for a handler.\n\n    If the provided field is not a dependency, a normal parameter is created and returned as a list, otherwise\n    `create_parameter_for_handler()` is called to generate parameters for the dependency.\n    \"\"\"\n\n    if field_name not in dependency_providers:\n        return [\n            create_parameter(\n                field_definition=field_definition,\n                parameter_name=field_name,\n                path_parameters=path_parameters,\n                schema_creator=schema_creator,\n            )\n        ]\n\n    dependency_fields = dependency_providers[field_name].signature_model._fields\n    return create_parameter_for_handler(\n        route_handler=route_handler,\n        handler_fields=dependency_fields,\n        path_parameters=path_parameters,\n        schema_creator=schema_creator,\n    )\n\n\ndef get_layered_parameter(\n    field_name: str,\n    field_definition: FieldDefinition,\n    layered_parameters: dict[str, FieldDefinition],\n    path_parameters: tuple[PathParameterDefinition, ...],\n    schema_creator: SchemaCreator,\n) -> Parameter:\n    \"\"\"Create a layered parameter for a given signature model field.\n\n    Layer info is extracted from the provided ``layered_parameters`` dict and set as the field's ``field_info`` attribute.\n    \"\"\"\n    layer_field = layered_parameters[field_name]\n\n    field = field_definition if field_definition.is_parameter_field else layer_field\n    default = layer_field.default if field_definition.has_default else field_definition.default\n    annotation = field_definition.annotation if field_definition is not Empty else layer_field.annotation\n\n    parameter_name = field_name\n    if isinstance(field.kwarg_definition, ParameterKwarg):\n        parameter_name = (\n            field.kwarg_definition.query or field.kwarg_definition.header or field.kwarg_definition.cookie or field_name\n        )\n\n    field_definition = FieldDefinition.from_kwarg(\n        inner_types=field.inner_types,\n        default=default,\n        extra=field.extra,\n        annotation=annotation,\n        kwarg_definition=field.kwarg_definition,\n        name=field_name,\n    )\n    return create_parameter(\n        field_definition=field_definition,\n        parameter_name=parameter_name,\n        path_parameters=path_parameters,\n        schema_creator=schema_creator,\n    )\n\n\ndef create_parameter_for_handler(\n    route_handler: BaseRouteHandler,\n    handler_fields: dict[str, FieldDefinition],\n    path_parameters: tuple[PathParameterDefinition, ...],\n    schema_creator: SchemaCreator,\n) -> list[Parameter]:\n    \"\"\"Create a list of path/query/header Parameter models for the given PathHandler.\"\"\"\n    parameters = ParameterCollection(route_handler=route_handler)\n    dependency_providers = route_handler.resolve_dependencies()\n    layered_parameters = route_handler.resolve_layered_parameters()\n\n    unique_handler_fields = (\n        (k, v) for k, v in handler_fields.items() if k not in RESERVED_KWARGS and k not in layered_parameters\n    )\n    unique_layered_fields = (\n        (k, v) for k, v in layered_parameters.items() if k not in RESERVED_KWARGS and k not in handler_fields\n    )\n    intersection_fields = (\n        (k, v) for k, v in handler_fields.items() if k not in RESERVED_KWARGS and k in layered_parameters\n    )\n\n    for field_name, field_definition in unique_handler_fields:\n        if isinstance(field_definition.kwarg_definition, DependencyKwarg) and field_name not in dependency_providers:\n            # never document explicit dependencies\n            continue\n\n        for parameter in get_recursive_handler_parameters(\n            field_name=field_name,\n            field_definition=field_definition,\n            dependency_providers=dependency_providers,\n            route_handler=route_handler,\n            path_parameters=path_parameters,\n            schema_creator=schema_creator,\n        ):\n            parameters.add(parameter)\n\n    for field_name, field_definition in unique_layered_fields:\n        parameters.add(\n            create_parameter(\n                field_definition=field_definition,\n                parameter_name=field_name,\n                path_parameters=path_parameters,\n                schema_creator=schema_creator,\n            )\n        )\n\n    for field_name, field_definition in intersection_fields:\n        parameters.add(\n            get_layered_parameter(\n                field_name=field_name,\n                field_definition=field_definition,\n                layered_parameters=layered_parameters,\n                path_parameters=path_parameters,\n                schema_creator=schema_creator,\n            )\n        )\n\n    return parameters.list()\n", "path": "litestar/_openapi/parameters.py"}]}