Skip to content

Commit faa5d3c

Browse files
fix: parameters defined as a reference in the path-params-defined rule (#2458)
1 parent 0c96e48 commit faa5d3c

File tree

3 files changed

+42
-9
lines changed

3 files changed

+42
-9
lines changed

.changeset/evil-states-fold.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@redocly/openapi-core": patch
3+
---
4+
5+
Fixed `path-params-defined` rule to correctly skip parameters defined through `$ref`.

packages/core/src/rules/common/__tests__/path-params-defined.test.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,4 +402,30 @@ describe('Oas3 path-params-defined', () => {
402402
]
403403
`);
404404
});
405+
406+
it('should not report on undefined params in case of reference', async () => {
407+
const document = parseYamlToDocument(
408+
outdent`
409+
openapi: 3.0.0
410+
paths:
411+
/test-endpoint:
412+
get:
413+
operationId: testEndpoint
414+
tags:
415+
- Test
416+
summary: Test endpoint to reproduce bug
417+
parameters:
418+
- $ref: ./test_params.yaml
419+
`,
420+
'foobar.yaml'
421+
);
422+
423+
const results = await lintDocument({
424+
externalRefResolver: new BaseResolver(),
425+
document,
426+
config: await createConfig({ rules: { 'path-params-defined': 'error' } }),
427+
});
428+
429+
expect(replaceSourceWithRef(results)).toMatchInlineSnapshot(`[]`);
430+
});
405431
});

packages/core/src/rules/common/path-params-defined.ts

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -112,11 +112,9 @@ const createOperationHandlers = (
112112
enter() {
113113
currentOperationParams = new Set();
114114
},
115-
leave(_op: unknown, { report, location }: UserContext) {
115+
leave(_operation: unknown, { report, location }: UserContext) {
116116
if (!pathContext.current || !currentOperationParams) return;
117117

118-
collectPathParamsFromOperation(_op, currentOperationParams);
119-
120118
validateRequiredPathParams(
121119
pathContext.current.templateParams,
122120
currentOperationParams,
@@ -127,6 +125,8 @@ const createOperationHandlers = (
127125
);
128126
},
129127
Parameter(parameter: Oas2Parameter | Oas3Parameter, { report, location }: UserContext) {
128+
collectPathParamsFromOperation(parameter, currentOperationParams);
129+
130130
if (parameter.in === 'path' && parameter.name && pathContext.current) {
131131
currentOperationParams.add(parameter.name);
132132
validatePathParameter(
@@ -150,13 +150,15 @@ const extractTemplateParams = (path: string): Set<string> => {
150150
return new Set(Array.from(path.matchAll(pathRegex)).map((m) => m[1]));
151151
};
152152

153-
const collectPathParamsFromOperation = (operation: unknown, targetSet: Set<string>): void => {
154-
const op = operation as { parameters?: Array<{ in?: string; name?: string }> };
155-
op?.parameters?.forEach((param) => {
156-
if (param?.in === 'path' && param?.name) {
157-
targetSet.add(param.name);
153+
const collectPathParamsFromOperation = (
154+
parameter: Oas2Parameter | Oas3Parameter,
155+
targetSet: Set<string>
156+
): void => {
157+
if (parameter && typeof parameter === 'object' && 'in' in parameter && 'name' in parameter) {
158+
if (parameter.in === 'path' && parameter.name) {
159+
targetSet.add(parameter.name);
158160
}
159-
});
161+
}
160162
};
161163

162164
const validatePathParameter = (

0 commit comments

Comments
 (0)