From c1c24c724112752367d977d07172e955fdd82d85 Mon Sep 17 00:00:00 2001 From: Patrick Boos Date: Thu, 10 Oct 2024 09:54:36 +0200 Subject: [PATCH 01/12] [bugfix] component-name-unique: correctly report location in problem --- .../__tests__/component-name-unique.test.ts | 22 ++++----- .../src/rules/oas3/component-name-unique.ts | 49 +++++++++++-------- 2 files changed, 40 insertions(+), 31 deletions(-) diff --git a/packages/core/src/rules/oas3/__tests__/component-name-unique.test.ts b/packages/core/src/rules/oas3/__tests__/component-name-unique.test.ts index c79591a9d1..1c6885cc57 100644 --- a/packages/core/src/rules/oas3/__tests__/component-name-unique.test.ts +++ b/packages/core/src/rules/oas3/__tests__/component-name-unique.test.ts @@ -44,7 +44,7 @@ describe('Oas3 component-name-unique', () => { { "location": [ { - "pointer": "#/", + "pointer": "#/components/schemas/SomeSchema", "reportOnKey": false, "source": "/foobar.yaml", }, @@ -99,7 +99,7 @@ describe('Oas3 component-name-unique', () => { { "location": [ { - "pointer": "#/", + "pointer": "#/components/schemas/SomeSchema", "reportOnKey": false, "source": "/foobar.yaml", }, @@ -202,7 +202,7 @@ describe('Oas3 component-name-unique', () => { { "location": [ { - "pointer": "#/", + "pointer": "#/components/parameters/ParameterOne", "reportOnKey": false, "source": "/foobar.yaml", }, @@ -261,7 +261,7 @@ describe('Oas3 component-name-unique', () => { { "location": [ { - "pointer": "#/", + "pointer": "#/components/parameters/ParameterOne", "reportOnKey": false, "source": "/foobar.yaml", }, @@ -378,7 +378,7 @@ describe('Oas3 component-name-unique', () => { { "location": [ { - "pointer": "#/", + "pointer": "#/components/responses/SuccessResponse", "reportOnKey": false, "source": "/foobar.yaml", }, @@ -444,7 +444,7 @@ describe('Oas3 component-name-unique', () => { { "location": [ { - "pointer": "#/", + "pointer": "#/components/responses/SuccessResponse", "reportOnKey": false, "source": "/foobar.yaml", }, @@ -565,7 +565,7 @@ describe('Oas3 component-name-unique', () => { { "location": [ { - "pointer": "#/", + "pointer": "#/components/requestBodies/MyRequestBody", "reportOnKey": false, "source": "/foobar.yaml", }, @@ -632,7 +632,7 @@ describe('Oas3 component-name-unique', () => { { "location": [ { - "pointer": "#/", + "pointer": "#/components/requestBodies/MyRequestBody", "reportOnKey": false, "source": "/foobar.yaml", }, @@ -761,7 +761,7 @@ describe('Oas3 component-name-unique', () => { { "location": [ { - "pointer": "#/", + "pointer": "#/components/requestBodies/MyRequestBody", "reportOnKey": false, "source": "/foobar.yaml", }, @@ -776,7 +776,7 @@ describe('Oas3 component-name-unique', () => { { "location": [ { - "pointer": "#/", + "pointer": "#/components/schemas/SomeSchema", "reportOnKey": false, "source": "/foobar.yaml", }, @@ -804,7 +804,7 @@ describe('Oas3 component-name-unique', () => { { "location": [ { - "pointer": "#/", + "pointer": "#/components/requestBodies/MyRequestBody", "reportOnKey": false, "source": "/foobar.yaml", }, diff --git a/packages/core/src/rules/oas3/component-name-unique.ts b/packages/core/src/rules/oas3/component-name-unique.ts index caad601796..f325a72bc3 100644 --- a/packages/core/src/rules/oas3/component-name-unique.ts +++ b/packages/core/src/rules/oas3/component-name-unique.ts @@ -1,3 +1,4 @@ +import type { Location } from "../../ref-utils"; import type { Problem, UserContext } from '../../walk'; import type { Oas2Rule, Oas3Rule, Oas3Visitor } from '../../visitors'; import type { @@ -21,8 +22,10 @@ const TYPE_NAME_TO_OPTION_COMPONENT_NAME: { [key: string]: string } = { [TYPE_NAME_REQUEST_BODY]: 'requestBodies', }; +type ComponentsMapValue = { absolutePointers: Set, locations: Location[] }; + export const ComponentNameUnique: Oas3Rule | Oas2Rule = (options) => { - const components = new Map>(); + const components = new Map(); const typeNames: string[] = []; if (options.schemas !== 'off') { @@ -46,17 +49,14 @@ export const ComponentNameUnique: Oas3Rule | Oas2Rule = (options) => { const resolvedRef = resolve(ref); if (!resolvedRef.location) return; - addComponentFromAbsoluteLocation( - typeName, - resolvedRef.location.absolutePointer.toString() - ); + addComponentFromAbsoluteLocation(typeName, resolvedRef.location); } }, }, Root: { leave(root: Oas3Definition, ctx: UserContext) { components.forEach((value, key, _) => { - if (value.size > 1) { + if (value.absolutePointers.size > 1) { const component = getComponentFromKey(key); const optionComponentName = getOptionComponentNameForTypeName(component.typeName); const definitions = Array.from(value) @@ -66,6 +66,11 @@ export const ComponentNameUnique: Oas3Rule | Oas2Rule = (options) => { const problem: Problem = { message: `Component '${optionComponentName}/${component.componentName}' is not unique. It is defined at:\n${definitions}`, }; + problem.location = { + ...value.locations[0], + // reportOnKey: + // error.keyword === 'unevaluatedProperties' || error.keyword === 'additionalProperties', + }; const componentSeverity = optionComponentName ? options[optionComponentName] : null; if (componentSeverity) { @@ -81,7 +86,7 @@ export const ComponentNameUnique: Oas3Rule | Oas2Rule = (options) => { if (options.schemas != 'off') { rule.NamedSchemas = { Schema(_: Oas3Schema, { location }: UserContext) { - addComponentFromAbsoluteLocation(TYPE_NAME_SCHEMA, location.absolutePointer.toString()); + addComponentFromAbsoluteLocation(TYPE_NAME_SCHEMA, location); }, }; } @@ -89,7 +94,7 @@ export const ComponentNameUnique: Oas3Rule | Oas2Rule = (options) => { if (options.responses != 'off') { rule.NamedResponses = { Response(_: Oas3Response, { location }: UserContext) { - addComponentFromAbsoluteLocation(TYPE_NAME_RESPONSE, location.absolutePointer.toString()); + addComponentFromAbsoluteLocation(TYPE_NAME_RESPONSE, location); }, }; } @@ -97,7 +102,7 @@ export const ComponentNameUnique: Oas3Rule | Oas2Rule = (options) => { if (options.parameters != 'off') { rule.NamedParameters = { Parameter(_: Oas3Parameter, { location }: UserContext) { - addComponentFromAbsoluteLocation(TYPE_NAME_PARAMETER, location.absolutePointer.toString()); + addComponentFromAbsoluteLocation(TYPE_NAME_PARAMETER, location); }, }; } @@ -105,10 +110,7 @@ export const ComponentNameUnique: Oas3Rule | Oas2Rule = (options) => { if (options.requestBodies != 'off') { rule.NamedRequestBodies = { RequestBody(_: Oas3RequestBody, { location }: UserContext) { - addComponentFromAbsoluteLocation( - TYPE_NAME_REQUEST_BODY, - location.absolutePointer.toString() - ); + addComponentFromAbsoluteLocation(TYPE_NAME_REQUEST_BODY, location); }, }; } @@ -130,17 +132,24 @@ export const ComponentNameUnique: Oas3Rule | Oas2Rule = (options) => { function addFoundComponent( typeName: string, componentName: string, - absoluteLocation: string + location: Location ): void { const key = getKeyForComponent(typeName, componentName); - const locations = components.get(key) ?? new Set(); - locations.add(absoluteLocation); - components.set(key, locations); + const entry: ComponentsMapValue = components.get(key) ?? { + absolutePointers: new Set(), + locations: [] + } satisfies ComponentsMapValue; + const absoluteLocation = location.absolutePointer.toString(); + if (!entry.absolutePointers.has(absoluteLocation)) { + entry.absolutePointers.add(absoluteLocation); + entry.locations.push(location); + } + components.set(key, entry); } - function addComponentFromAbsoluteLocation(typeName: string, absoluteLocation: string): void { - const componentName = getComponentNameFromAbsoluteLocation(absoluteLocation); - addFoundComponent(typeName, componentName, absoluteLocation); + function addComponentFromAbsoluteLocation(typeName: string, location: Location): void { + const componentName = getComponentNameFromAbsoluteLocation(location.absolutePointer.toString()); + addFoundComponent(typeName, componentName, location); } }; From 2ba16ff070e471d86a4fe4518cce3535a544aa07 Mon Sep 17 00:00:00 2001 From: Patrick Boos Date: Thu, 10 Oct 2024 09:55:01 +0200 Subject: [PATCH 02/12] [bugfix] component-name-unique: message to be in single line --- .../__tests__/component-name-unique.test.ts | 44 +++++-------------- .../src/rules/oas3/component-name-unique.ts | 6 +-- 2 files changed, 13 insertions(+), 37 deletions(-) diff --git a/packages/core/src/rules/oas3/__tests__/component-name-unique.test.ts b/packages/core/src/rules/oas3/__tests__/component-name-unique.test.ts index 1c6885cc57..33c060204b 100644 --- a/packages/core/src/rules/oas3/__tests__/component-name-unique.test.ts +++ b/packages/core/src/rules/oas3/__tests__/component-name-unique.test.ts @@ -49,9 +49,7 @@ describe('Oas3 component-name-unique', () => { "source": "/foobar.yaml", }, ], - "message": "Component 'schemas/SomeSchema' is not unique. It is defined at: - - /foobar.yaml#/components/schemas/SomeSchema - - /test.yaml#/components/schemas/SomeSchema", + "message": "Component 'schemas/SomeSchema' is not unique. It is defined at: /foobar.yaml#/components/schemas/SomeSchema, /test.yaml#/components/schemas/SomeSchema", "ruleId": "component-name-unique", "severity": "error", "suggest": [], @@ -104,9 +102,7 @@ describe('Oas3 component-name-unique', () => { "source": "/foobar.yaml", }, ], - "message": "Component 'schemas/SomeSchema' is not unique. It is defined at: - - /foobar.yaml#/components/schemas/SomeSchema - - /SomeSchema.yaml", + "message": "Component 'schemas/SomeSchema' is not unique. It is defined at: /foobar.yaml#/components/schemas/SomeSchema, /SomeSchema.yaml", "ruleId": "component-name-unique", "severity": "error", "suggest": [], @@ -207,9 +203,7 @@ describe('Oas3 component-name-unique', () => { "source": "/foobar.yaml", }, ], - "message": "Component 'parameters/ParameterOne' is not unique. It is defined at: - - /foobar.yaml#/components/parameters/ParameterOne - - /test.yaml#/components/parameters/ParameterOne", + "message": "Component 'parameters/ParameterOne' is not unique. It is defined at: /foobar.yaml#/components/parameters/ParameterOne, /test.yaml#/components/parameters/ParameterOne", "ruleId": "component-name-unique", "severity": "error", "suggest": [], @@ -266,9 +260,7 @@ describe('Oas3 component-name-unique', () => { "source": "/foobar.yaml", }, ], - "message": "Component 'parameters/ParameterOne' is not unique. It is defined at: - - /foobar.yaml#/components/parameters/ParameterOne - - /ParameterOne.yaml", + "message": "Component 'parameters/ParameterOne' is not unique. It is defined at: /foobar.yaml#/components/parameters/ParameterOne, /ParameterOne.yaml", "ruleId": "component-name-unique", "severity": "error", "suggest": [], @@ -383,9 +375,7 @@ describe('Oas3 component-name-unique', () => { "source": "/foobar.yaml", }, ], - "message": "Component 'responses/SuccessResponse' is not unique. It is defined at: - - /foobar.yaml#/components/responses/SuccessResponse - - /test.yaml#/components/responses/SuccessResponse", + "message": "Component 'responses/SuccessResponse' is not unique. It is defined at: /foobar.yaml#/components/responses/SuccessResponse, /test.yaml#/components/responses/SuccessResponse", "ruleId": "component-name-unique", "severity": "error", "suggest": [], @@ -449,9 +439,7 @@ describe('Oas3 component-name-unique', () => { "source": "/foobar.yaml", }, ], - "message": "Component 'responses/SuccessResponse' is not unique. It is defined at: - - /foobar.yaml#/components/responses/SuccessResponse - - /SuccessResponse.yaml", + "message": "Component 'responses/SuccessResponse' is not unique. It is defined at: /foobar.yaml#/components/responses/SuccessResponse, /SuccessResponse.yaml", "ruleId": "component-name-unique", "severity": "error", "suggest": [], @@ -570,9 +558,7 @@ describe('Oas3 component-name-unique', () => { "source": "/foobar.yaml", }, ], - "message": "Component 'requestBodies/MyRequestBody' is not unique. It is defined at: - - /foobar.yaml#/components/requestBodies/MyRequestBody - - /test.yaml#/components/requestBodies/MyRequestBody", + "message": "Component 'requestBodies/MyRequestBody' is not unique. It is defined at: /foobar.yaml#/components/requestBodies/MyRequestBody, /test.yaml#/components/requestBodies/MyRequestBody", "ruleId": "component-name-unique", "severity": "error", "suggest": [], @@ -637,9 +623,7 @@ describe('Oas3 component-name-unique', () => { "source": "/foobar.yaml", }, ], - "message": "Component 'requestBodies/MyRequestBody' is not unique. It is defined at: - - /foobar.yaml#/components/requestBodies/MyRequestBody - - /MyRequestBody.yaml", + "message": "Component 'requestBodies/MyRequestBody' is not unique. It is defined at: /foobar.yaml#/components/requestBodies/MyRequestBody, /MyRequestBody.yaml", "ruleId": "component-name-unique", "severity": "error", "suggest": [], @@ -766,9 +750,7 @@ describe('Oas3 component-name-unique', () => { "source": "/foobar.yaml", }, ], - "message": "Component 'requestBodies/MyRequestBody' is not unique. It is defined at: - - /foobar.yaml#/components/requestBodies/MyRequestBody - - /test.yaml#/components/requestBodies/MyRequestBody", + "message": "Component 'requestBodies/MyRequestBody' is not unique. It is defined at: /foobar.yaml#/components/requestBodies/MyRequestBody, /test.yaml#/components/requestBodies/MyRequestBody", "ruleId": "component-name-unique", "severity": "error", "suggest": [], @@ -781,9 +763,7 @@ describe('Oas3 component-name-unique', () => { "source": "/foobar.yaml", }, ], - "message": "Component 'schemas/SomeSchema' is not unique. It is defined at: - - /foobar.yaml#/components/schemas/SomeSchema - - /test.yaml#/components/schemas/SomeSchema", + "message": "Component 'schemas/SomeSchema' is not unique. It is defined at: /foobar.yaml#/components/schemas/SomeSchema, /test.yaml#/components/schemas/SomeSchema", "ruleId": "component-name-unique", "severity": "error", "suggest": [], @@ -809,9 +789,7 @@ describe('Oas3 component-name-unique', () => { "source": "/foobar.yaml", }, ], - "message": "Component 'requestBodies/MyRequestBody' is not unique. It is defined at: - - /foobar.yaml#/components/requestBodies/MyRequestBody - - /test.yaml#/components/requestBodies/MyRequestBody", + "message": "Component 'requestBodies/MyRequestBody' is not unique. It is defined at: /foobar.yaml#/components/requestBodies/MyRequestBody, /test.yaml#/components/requestBodies/MyRequestBody", "ruleId": "component-name-unique", "severity": "error", "suggest": [], diff --git a/packages/core/src/rules/oas3/component-name-unique.ts b/packages/core/src/rules/oas3/component-name-unique.ts index f325a72bc3..b0043b4696 100644 --- a/packages/core/src/rules/oas3/component-name-unique.ts +++ b/packages/core/src/rules/oas3/component-name-unique.ts @@ -59,12 +59,10 @@ export const ComponentNameUnique: Oas3Rule | Oas2Rule = (options) => { if (value.absolutePointers.size > 1) { const component = getComponentFromKey(key); const optionComponentName = getOptionComponentNameForTypeName(component.typeName); - const definitions = Array.from(value) - .map((v) => `- ${v}`) - .join('\n'); + const definitions = Array.from(value.absolutePointers).join(', '); const problem: Problem = { - message: `Component '${optionComponentName}/${component.componentName}' is not unique. It is defined at:\n${definitions}`, + message: `Component '${optionComponentName}/${component.componentName}' is not unique. It is defined at: ${definitions}`, }; problem.location = { ...value.locations[0], From 59e1dd112dde9f94c6479d80cef234f4b6fbe258 Mon Sep 17 00:00:00 2001 From: Patrick Boos Date: Thu, 10 Oct 2024 10:57:08 +0200 Subject: [PATCH 03/12] [bugfix] component-name-unique: sort locations for the problem --- packages/core/src/rules/oas3/component-name-unique.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/packages/core/src/rules/oas3/component-name-unique.ts b/packages/core/src/rules/oas3/component-name-unique.ts index b0043b4696..ccbe9e1840 100644 --- a/packages/core/src/rules/oas3/component-name-unique.ts +++ b/packages/core/src/rules/oas3/component-name-unique.ts @@ -60,14 +60,11 @@ export const ComponentNameUnique: Oas3Rule | Oas2Rule = (options) => { const component = getComponentFromKey(key); const optionComponentName = getOptionComponentNameForTypeName(component.typeName); const definitions = Array.from(value.absolutePointers).join(', '); - const problem: Problem = { message: `Component '${optionComponentName}/${component.componentName}' is not unique. It is defined at: ${definitions}`, }; problem.location = { - ...value.locations[0], - // reportOnKey: - // error.keyword === 'unevaluatedProperties' || error.keyword === 'additionalProperties', + ...value.locations.sort((a, b)=> a.absolutePointer.localeCompare(b.absolutePointer))[0], }; const componentSeverity = optionComponentName ? options[optionComponentName] : null; From bccb138782faa727a94ab1ea0dc00ba258542d04 Mon Sep 17 00:00:00 2001 From: Patrick Boos Date: Thu, 10 Oct 2024 10:57:27 +0200 Subject: [PATCH 04/12] formatting --- packages/core/src/rules/oas3/component-name-unique.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/src/rules/oas3/component-name-unique.ts b/packages/core/src/rules/oas3/component-name-unique.ts index ccbe9e1840..69bffa3f87 100644 --- a/packages/core/src/rules/oas3/component-name-unique.ts +++ b/packages/core/src/rules/oas3/component-name-unique.ts @@ -64,7 +64,7 @@ export const ComponentNameUnique: Oas3Rule | Oas2Rule = (options) => { message: `Component '${optionComponentName}/${component.componentName}' is not unique. It is defined at: ${definitions}`, }; problem.location = { - ...value.locations.sort((a, b)=> a.absolutePointer.localeCompare(b.absolutePointer))[0], + ...value.locations.sort((a, b) => a.absolutePointer.localeCompare(b.absolutePointer))[0], }; const componentSeverity = optionComponentName ? options[optionComponentName] : null; From d695eded1c2aa5da6f10b3c141ebabe6604e514a Mon Sep 17 00:00:00 2001 From: Patrick Boos Date: Thu, 10 Oct 2024 11:03:17 +0200 Subject: [PATCH 05/12] remove `satisfies` --- packages/core/src/rules/oas3/component-name-unique.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/src/rules/oas3/component-name-unique.ts b/packages/core/src/rules/oas3/component-name-unique.ts index 69bffa3f87..f3f0fe1223 100644 --- a/packages/core/src/rules/oas3/component-name-unique.ts +++ b/packages/core/src/rules/oas3/component-name-unique.ts @@ -133,7 +133,7 @@ export const ComponentNameUnique: Oas3Rule | Oas2Rule = (options) => { const entry: ComponentsMapValue = components.get(key) ?? { absolutePointers: new Set(), locations: [] - } satisfies ComponentsMapValue; + }; const absoluteLocation = location.absolutePointer.toString(); if (!entry.absolutePointers.has(absoluteLocation)) { entry.absolutePointers.add(absoluteLocation); From b1aa0e206ab544cba9adfa0eece235ad873ae0a8 Mon Sep 17 00:00:00 2001 From: Patrick Boos Date: Thu, 10 Oct 2024 11:23:49 +0200 Subject: [PATCH 06/12] formatting --- .../core/src/rules/oas3/component-name-unique.ts | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/packages/core/src/rules/oas3/component-name-unique.ts b/packages/core/src/rules/oas3/component-name-unique.ts index f3f0fe1223..bc8bcac9cd 100644 --- a/packages/core/src/rules/oas3/component-name-unique.ts +++ b/packages/core/src/rules/oas3/component-name-unique.ts @@ -1,4 +1,4 @@ -import type { Location } from "../../ref-utils"; +import type { Location } from '../../ref-utils'; import type { Problem, UserContext } from '../../walk'; import type { Oas2Rule, Oas3Rule, Oas3Visitor } from '../../visitors'; import type { @@ -22,7 +22,7 @@ const TYPE_NAME_TO_OPTION_COMPONENT_NAME: { [key: string]: string } = { [TYPE_NAME_REQUEST_BODY]: 'requestBodies', }; -type ComponentsMapValue = { absolutePointers: Set, locations: Location[] }; +type ComponentsMapValue = { absolutePointers: Set; locations: Location[] }; export const ComponentNameUnique: Oas3Rule | Oas2Rule = (options) => { const components = new Map(); @@ -64,7 +64,9 @@ export const ComponentNameUnique: Oas3Rule | Oas2Rule = (options) => { message: `Component '${optionComponentName}/${component.componentName}' is not unique. It is defined at: ${definitions}`, }; problem.location = { - ...value.locations.sort((a, b) => a.absolutePointer.localeCompare(b.absolutePointer))[0], + ...value.locations.sort((a, b) => + a.absolutePointer.localeCompare(b.absolutePointer) + )[0], }; const componentSeverity = optionComponentName ? options[optionComponentName] : null; @@ -124,15 +126,11 @@ export const ComponentNameUnique: Oas3Rule | Oas2Rule = (options) => { return componentName; } - function addFoundComponent( - typeName: string, - componentName: string, - location: Location - ): void { + function addFoundComponent(typeName: string, componentName: string, location: Location): void { const key = getKeyForComponent(typeName, componentName); const entry: ComponentsMapValue = components.get(key) ?? { absolutePointers: new Set(), - locations: [] + locations: [], }; const absoluteLocation = location.absolutePointer.toString(); if (!entry.absolutePointers.has(absoluteLocation)) { From f32798d5967b81a34ea3604b24aa3038cf389c34 Mon Sep 17 00:00:00 2001 From: Patrick Boos Date: Thu, 10 Oct 2024 11:43:32 +0200 Subject: [PATCH 07/12] Add changeset --- .changeset/real-chicken-cheat.md | 5 +++++ .../core/src/rules/oas3/component-name-unique.ts | 16 ++++++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 .changeset/real-chicken-cheat.md diff --git a/.changeset/real-chicken-cheat.md b/.changeset/real-chicken-cheat.md new file mode 100644 index 0000000000..56959ad161 --- /dev/null +++ b/.changeset/real-chicken-cheat.md @@ -0,0 +1,5 @@ +--- +"@redocly/openapi-core": minor +--- + +Fixed `component-name-unique` problems to include correct location diff --git a/packages/core/src/rules/oas3/component-name-unique.ts b/packages/core/src/rules/oas3/component-name-unique.ts index bc8bcac9cd..724409ac40 100644 --- a/packages/core/src/rules/oas3/component-name-unique.ts +++ b/packages/core/src/rules/oas3/component-name-unique.ts @@ -74,6 +74,22 @@ export const ComponentNameUnique: Oas3Rule | Oas2Rule = (options) => { problem.forceSeverity = componentSeverity; } ctx.report(problem); + // value.locations.forEach((location) => { + // const problem: Problem = { + // message: `Component '${optionComponentName}/${component.componentName}' is not unique. It is defined at: ${definitions}`, + // }; + // problem.location = { + // ...location, + // // reportOnKey: + // // error.keyword === 'unevaluatedProperties' || error.keyword === 'additionalProperties', + // }; + // + // const componentSeverity = optionComponentName ? options[optionComponentName] : null; + // if (componentSeverity) { + // problem.forceSeverity = componentSeverity; + // } + // ctx.report(problem); + // }); } }); }, From 3193bbc6a9e125cd348cc73f8886420b0750480e Mon Sep 17 00:00:00 2001 From: Patrick Boos Date: Fri, 25 Oct 2024 16:46:14 +0200 Subject: [PATCH 08/12] Remove comments --- .../core/src/rules/oas3/component-name-unique.ts | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/packages/core/src/rules/oas3/component-name-unique.ts b/packages/core/src/rules/oas3/component-name-unique.ts index 724409ac40..bc8bcac9cd 100644 --- a/packages/core/src/rules/oas3/component-name-unique.ts +++ b/packages/core/src/rules/oas3/component-name-unique.ts @@ -74,22 +74,6 @@ export const ComponentNameUnique: Oas3Rule | Oas2Rule = (options) => { problem.forceSeverity = componentSeverity; } ctx.report(problem); - // value.locations.forEach((location) => { - // const problem: Problem = { - // message: `Component '${optionComponentName}/${component.componentName}' is not unique. It is defined at: ${definitions}`, - // }; - // problem.location = { - // ...location, - // // reportOnKey: - // // error.keyword === 'unevaluatedProperties' || error.keyword === 'additionalProperties', - // }; - // - // const componentSeverity = optionComponentName ? options[optionComponentName] : null; - // if (componentSeverity) { - // problem.forceSeverity = componentSeverity; - // } - // ctx.report(problem); - // }); } }); }, From 2a0368f7b24e8d94feb52254b826b62d4fd55c2d Mon Sep 17 00:00:00 2001 From: Patrick Boos Date: Fri, 25 Oct 2024 16:46:33 +0200 Subject: [PATCH 09/12] Revert output formatting --- .../__tests__/component-name-unique.test.ts | 44 ++++++++++++++----- .../src/rules/oas3/component-name-unique.ts | 6 ++- 2 files changed, 37 insertions(+), 13 deletions(-) diff --git a/packages/core/src/rules/oas3/__tests__/component-name-unique.test.ts b/packages/core/src/rules/oas3/__tests__/component-name-unique.test.ts index 33c060204b..1c6885cc57 100644 --- a/packages/core/src/rules/oas3/__tests__/component-name-unique.test.ts +++ b/packages/core/src/rules/oas3/__tests__/component-name-unique.test.ts @@ -49,7 +49,9 @@ describe('Oas3 component-name-unique', () => { "source": "/foobar.yaml", }, ], - "message": "Component 'schemas/SomeSchema' is not unique. It is defined at: /foobar.yaml#/components/schemas/SomeSchema, /test.yaml#/components/schemas/SomeSchema", + "message": "Component 'schemas/SomeSchema' is not unique. It is defined at: + - /foobar.yaml#/components/schemas/SomeSchema + - /test.yaml#/components/schemas/SomeSchema", "ruleId": "component-name-unique", "severity": "error", "suggest": [], @@ -102,7 +104,9 @@ describe('Oas3 component-name-unique', () => { "source": "/foobar.yaml", }, ], - "message": "Component 'schemas/SomeSchema' is not unique. It is defined at: /foobar.yaml#/components/schemas/SomeSchema, /SomeSchema.yaml", + "message": "Component 'schemas/SomeSchema' is not unique. It is defined at: + - /foobar.yaml#/components/schemas/SomeSchema + - /SomeSchema.yaml", "ruleId": "component-name-unique", "severity": "error", "suggest": [], @@ -203,7 +207,9 @@ describe('Oas3 component-name-unique', () => { "source": "/foobar.yaml", }, ], - "message": "Component 'parameters/ParameterOne' is not unique. It is defined at: /foobar.yaml#/components/parameters/ParameterOne, /test.yaml#/components/parameters/ParameterOne", + "message": "Component 'parameters/ParameterOne' is not unique. It is defined at: + - /foobar.yaml#/components/parameters/ParameterOne + - /test.yaml#/components/parameters/ParameterOne", "ruleId": "component-name-unique", "severity": "error", "suggest": [], @@ -260,7 +266,9 @@ describe('Oas3 component-name-unique', () => { "source": "/foobar.yaml", }, ], - "message": "Component 'parameters/ParameterOne' is not unique. It is defined at: /foobar.yaml#/components/parameters/ParameterOne, /ParameterOne.yaml", + "message": "Component 'parameters/ParameterOne' is not unique. It is defined at: + - /foobar.yaml#/components/parameters/ParameterOne + - /ParameterOne.yaml", "ruleId": "component-name-unique", "severity": "error", "suggest": [], @@ -375,7 +383,9 @@ describe('Oas3 component-name-unique', () => { "source": "/foobar.yaml", }, ], - "message": "Component 'responses/SuccessResponse' is not unique. It is defined at: /foobar.yaml#/components/responses/SuccessResponse, /test.yaml#/components/responses/SuccessResponse", + "message": "Component 'responses/SuccessResponse' is not unique. It is defined at: + - /foobar.yaml#/components/responses/SuccessResponse + - /test.yaml#/components/responses/SuccessResponse", "ruleId": "component-name-unique", "severity": "error", "suggest": [], @@ -439,7 +449,9 @@ describe('Oas3 component-name-unique', () => { "source": "/foobar.yaml", }, ], - "message": "Component 'responses/SuccessResponse' is not unique. It is defined at: /foobar.yaml#/components/responses/SuccessResponse, /SuccessResponse.yaml", + "message": "Component 'responses/SuccessResponse' is not unique. It is defined at: + - /foobar.yaml#/components/responses/SuccessResponse + - /SuccessResponse.yaml", "ruleId": "component-name-unique", "severity": "error", "suggest": [], @@ -558,7 +570,9 @@ describe('Oas3 component-name-unique', () => { "source": "/foobar.yaml", }, ], - "message": "Component 'requestBodies/MyRequestBody' is not unique. It is defined at: /foobar.yaml#/components/requestBodies/MyRequestBody, /test.yaml#/components/requestBodies/MyRequestBody", + "message": "Component 'requestBodies/MyRequestBody' is not unique. It is defined at: + - /foobar.yaml#/components/requestBodies/MyRequestBody + - /test.yaml#/components/requestBodies/MyRequestBody", "ruleId": "component-name-unique", "severity": "error", "suggest": [], @@ -623,7 +637,9 @@ describe('Oas3 component-name-unique', () => { "source": "/foobar.yaml", }, ], - "message": "Component 'requestBodies/MyRequestBody' is not unique. It is defined at: /foobar.yaml#/components/requestBodies/MyRequestBody, /MyRequestBody.yaml", + "message": "Component 'requestBodies/MyRequestBody' is not unique. It is defined at: + - /foobar.yaml#/components/requestBodies/MyRequestBody + - /MyRequestBody.yaml", "ruleId": "component-name-unique", "severity": "error", "suggest": [], @@ -750,7 +766,9 @@ describe('Oas3 component-name-unique', () => { "source": "/foobar.yaml", }, ], - "message": "Component 'requestBodies/MyRequestBody' is not unique. It is defined at: /foobar.yaml#/components/requestBodies/MyRequestBody, /test.yaml#/components/requestBodies/MyRequestBody", + "message": "Component 'requestBodies/MyRequestBody' is not unique. It is defined at: + - /foobar.yaml#/components/requestBodies/MyRequestBody + - /test.yaml#/components/requestBodies/MyRequestBody", "ruleId": "component-name-unique", "severity": "error", "suggest": [], @@ -763,7 +781,9 @@ describe('Oas3 component-name-unique', () => { "source": "/foobar.yaml", }, ], - "message": "Component 'schemas/SomeSchema' is not unique. It is defined at: /foobar.yaml#/components/schemas/SomeSchema, /test.yaml#/components/schemas/SomeSchema", + "message": "Component 'schemas/SomeSchema' is not unique. It is defined at: + - /foobar.yaml#/components/schemas/SomeSchema + - /test.yaml#/components/schemas/SomeSchema", "ruleId": "component-name-unique", "severity": "error", "suggest": [], @@ -789,7 +809,9 @@ describe('Oas3 component-name-unique', () => { "source": "/foobar.yaml", }, ], - "message": "Component 'requestBodies/MyRequestBody' is not unique. It is defined at: /foobar.yaml#/components/requestBodies/MyRequestBody, /test.yaml#/components/requestBodies/MyRequestBody", + "message": "Component 'requestBodies/MyRequestBody' is not unique. It is defined at: + - /foobar.yaml#/components/requestBodies/MyRequestBody + - /test.yaml#/components/requestBodies/MyRequestBody", "ruleId": "component-name-unique", "severity": "error", "suggest": [], diff --git a/packages/core/src/rules/oas3/component-name-unique.ts b/packages/core/src/rules/oas3/component-name-unique.ts index bc8bcac9cd..848591b653 100644 --- a/packages/core/src/rules/oas3/component-name-unique.ts +++ b/packages/core/src/rules/oas3/component-name-unique.ts @@ -59,9 +59,11 @@ export const ComponentNameUnique: Oas3Rule | Oas2Rule = (options) => { if (value.absolutePointers.size > 1) { const component = getComponentFromKey(key); const optionComponentName = getOptionComponentNameForTypeName(component.typeName); - const definitions = Array.from(value.absolutePointers).join(', '); + const definitions = Array.from(value.absolutePointers) + .map((v) => `- ${v}`) + .join('\n'); const problem: Problem = { - message: `Component '${optionComponentName}/${component.componentName}' is not unique. It is defined at: ${definitions}`, + message: `Component '${optionComponentName}/${component.componentName}' is not unique. It is defined at:\n${definitions}`, }; problem.location = { ...value.locations.sort((a, b) => From 13a9741f1b2e36e3f459b6c02a870e2fb34fc5a6 Mon Sep 17 00:00:00 2001 From: Patrick Boos Date: Mon, 28 Oct 2024 09:46:21 +0100 Subject: [PATCH 10/12] Update .changeset/real-chicken-cheat.md Co-authored-by: Andrew Tatomyr --- .changeset/real-chicken-cheat.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/real-chicken-cheat.md b/.changeset/real-chicken-cheat.md index 56959ad161..d69583ddff 100644 --- a/.changeset/real-chicken-cheat.md +++ b/.changeset/real-chicken-cheat.md @@ -2,4 +2,4 @@ "@redocly/openapi-core": minor --- -Fixed `component-name-unique` problems to include correct location +Fixed `component-name-unique` problems to include correct location. From bf980a6ada2e46f848842529e75148ff9e603266 Mon Sep 17 00:00:00 2001 From: Patrick Boos Date: Mon, 28 Oct 2024 15:37:14 +0100 Subject: [PATCH 11/12] Report for each location --- .../__tests__/component-name-unique.test.ts | 187 +++++++++++++++--- .../src/rules/oas3/component-name-unique.ts | 31 ++- 2 files changed, 180 insertions(+), 38 deletions(-) diff --git a/packages/core/src/rules/oas3/__tests__/component-name-unique.test.ts b/packages/core/src/rules/oas3/__tests__/component-name-unique.test.ts index 1c6885cc57..442379a9e9 100644 --- a/packages/core/src/rules/oas3/__tests__/component-name-unique.test.ts +++ b/packages/core/src/rules/oas3/__tests__/component-name-unique.test.ts @@ -49,13 +49,26 @@ describe('Oas3 component-name-unique', () => { "source": "/foobar.yaml", }, ], - "message": "Component 'schemas/SomeSchema' is not unique. It is defined at: - - /foobar.yaml#/components/schemas/SomeSchema + "message": "Component 'schemas/SomeSchema' is not unique. It is also defined at: - /test.yaml#/components/schemas/SomeSchema", "ruleId": "component-name-unique", "severity": "error", "suggest": [], }, + { + "location": [ + { + "pointer": "#/components/schemas/SomeSchema", + "reportOnKey": false, + "source": "/test.yaml", + }, + ], + "message": "Component 'schemas/SomeSchema' is not unique. It is also defined at: + - /foobar.yaml#/components/schemas/SomeSchema", + "ruleId": "component-name-unique", + "severity": "error", + "suggest": [], + }, ] `); }); @@ -104,13 +117,26 @@ describe('Oas3 component-name-unique', () => { "source": "/foobar.yaml", }, ], - "message": "Component 'schemas/SomeSchema' is not unique. It is defined at: - - /foobar.yaml#/components/schemas/SomeSchema + "message": "Component 'schemas/SomeSchema' is not unique. It is also defined at: - /SomeSchema.yaml", "ruleId": "component-name-unique", "severity": "error", "suggest": [], }, + { + "location": [ + { + "pointer": "#/", + "reportOnKey": false, + "source": "/SomeSchema.yaml", + }, + ], + "message": "Component 'schemas/SomeSchema' is not unique. It is also defined at: + - /foobar.yaml#/components/schemas/SomeSchema", + "ruleId": "component-name-unique", + "severity": "error", + "suggest": [], + }, ] `); }); @@ -207,13 +233,26 @@ describe('Oas3 component-name-unique', () => { "source": "/foobar.yaml", }, ], - "message": "Component 'parameters/ParameterOne' is not unique. It is defined at: - - /foobar.yaml#/components/parameters/ParameterOne + "message": "Component 'parameters/ParameterOne' is not unique. It is also defined at: - /test.yaml#/components/parameters/ParameterOne", "ruleId": "component-name-unique", "severity": "error", "suggest": [], }, + { + "location": [ + { + "pointer": "#/components/parameters/ParameterOne", + "reportOnKey": false, + "source": "/test.yaml", + }, + ], + "message": "Component 'parameters/ParameterOne' is not unique. It is also defined at: + - /foobar.yaml#/components/parameters/ParameterOne", + "ruleId": "component-name-unique", + "severity": "error", + "suggest": [], + }, ] `); }); @@ -266,13 +305,26 @@ describe('Oas3 component-name-unique', () => { "source": "/foobar.yaml", }, ], - "message": "Component 'parameters/ParameterOne' is not unique. It is defined at: - - /foobar.yaml#/components/parameters/ParameterOne + "message": "Component 'parameters/ParameterOne' is not unique. It is also defined at: - /ParameterOne.yaml", "ruleId": "component-name-unique", "severity": "error", "suggest": [], }, + { + "location": [ + { + "pointer": "#/", + "reportOnKey": false, + "source": "/ParameterOne.yaml", + }, + ], + "message": "Component 'parameters/ParameterOne' is not unique. It is also defined at: + - /foobar.yaml#/components/parameters/ParameterOne", + "ruleId": "component-name-unique", + "severity": "error", + "suggest": [], + }, ] `); }); @@ -383,13 +435,26 @@ describe('Oas3 component-name-unique', () => { "source": "/foobar.yaml", }, ], - "message": "Component 'responses/SuccessResponse' is not unique. It is defined at: - - /foobar.yaml#/components/responses/SuccessResponse + "message": "Component 'responses/SuccessResponse' is not unique. It is also defined at: - /test.yaml#/components/responses/SuccessResponse", "ruleId": "component-name-unique", "severity": "error", "suggest": [], }, + { + "location": [ + { + "pointer": "#/components/responses/SuccessResponse", + "reportOnKey": false, + "source": "/test.yaml", + }, + ], + "message": "Component 'responses/SuccessResponse' is not unique. It is also defined at: + - /foobar.yaml#/components/responses/SuccessResponse", + "ruleId": "component-name-unique", + "severity": "error", + "suggest": [], + }, ] `); }); @@ -449,13 +514,26 @@ describe('Oas3 component-name-unique', () => { "source": "/foobar.yaml", }, ], - "message": "Component 'responses/SuccessResponse' is not unique. It is defined at: - - /foobar.yaml#/components/responses/SuccessResponse + "message": "Component 'responses/SuccessResponse' is not unique. It is also defined at: - /SuccessResponse.yaml", "ruleId": "component-name-unique", "severity": "error", "suggest": [], }, + { + "location": [ + { + "pointer": "#/", + "reportOnKey": false, + "source": "/SuccessResponse.yaml", + }, + ], + "message": "Component 'responses/SuccessResponse' is not unique. It is also defined at: + - /foobar.yaml#/components/responses/SuccessResponse", + "ruleId": "component-name-unique", + "severity": "error", + "suggest": [], + }, ] `); }); @@ -570,13 +648,26 @@ describe('Oas3 component-name-unique', () => { "source": "/foobar.yaml", }, ], - "message": "Component 'requestBodies/MyRequestBody' is not unique. It is defined at: - - /foobar.yaml#/components/requestBodies/MyRequestBody + "message": "Component 'requestBodies/MyRequestBody' is not unique. It is also defined at: - /test.yaml#/components/requestBodies/MyRequestBody", "ruleId": "component-name-unique", "severity": "error", "suggest": [], }, + { + "location": [ + { + "pointer": "#/components/requestBodies/MyRequestBody", + "reportOnKey": false, + "source": "/test.yaml", + }, + ], + "message": "Component 'requestBodies/MyRequestBody' is not unique. It is also defined at: + - /foobar.yaml#/components/requestBodies/MyRequestBody", + "ruleId": "component-name-unique", + "severity": "error", + "suggest": [], + }, ] `); }); @@ -637,13 +728,26 @@ describe('Oas3 component-name-unique', () => { "source": "/foobar.yaml", }, ], - "message": "Component 'requestBodies/MyRequestBody' is not unique. It is defined at: - - /foobar.yaml#/components/requestBodies/MyRequestBody + "message": "Component 'requestBodies/MyRequestBody' is not unique. It is also defined at: - /MyRequestBody.yaml", "ruleId": "component-name-unique", "severity": "error", "suggest": [], }, + { + "location": [ + { + "pointer": "#/", + "reportOnKey": false, + "source": "/MyRequestBody.yaml", + }, + ], + "message": "Component 'requestBodies/MyRequestBody' is not unique. It is also defined at: + - /foobar.yaml#/components/requestBodies/MyRequestBody", + "ruleId": "component-name-unique", + "severity": "error", + "suggest": [], + }, ] `); }); @@ -766,13 +870,26 @@ describe('Oas3 component-name-unique', () => { "source": "/foobar.yaml", }, ], - "message": "Component 'requestBodies/MyRequestBody' is not unique. It is defined at: - - /foobar.yaml#/components/requestBodies/MyRequestBody + "message": "Component 'requestBodies/MyRequestBody' is not unique. It is also defined at: - /test.yaml#/components/requestBodies/MyRequestBody", "ruleId": "component-name-unique", "severity": "error", "suggest": [], }, + { + "location": [ + { + "pointer": "#/components/requestBodies/MyRequestBody", + "reportOnKey": false, + "source": "/test.yaml", + }, + ], + "message": "Component 'requestBodies/MyRequestBody' is not unique. It is also defined at: + - /foobar.yaml#/components/requestBodies/MyRequestBody", + "ruleId": "component-name-unique", + "severity": "error", + "suggest": [], + }, { "location": [ { @@ -781,13 +898,26 @@ describe('Oas3 component-name-unique', () => { "source": "/foobar.yaml", }, ], - "message": "Component 'schemas/SomeSchema' is not unique. It is defined at: - - /foobar.yaml#/components/schemas/SomeSchema + "message": "Component 'schemas/SomeSchema' is not unique. It is also defined at: - /test.yaml#/components/schemas/SomeSchema", "ruleId": "component-name-unique", "severity": "error", "suggest": [], }, + { + "location": [ + { + "pointer": "#/components/schemas/SomeSchema", + "reportOnKey": false, + "source": "/test.yaml", + }, + ], + "message": "Component 'schemas/SomeSchema' is not unique. It is also defined at: + - /foobar.yaml#/components/schemas/SomeSchema", + "ruleId": "component-name-unique", + "severity": "error", + "suggest": [], + }, ] `); }); @@ -809,13 +939,26 @@ describe('Oas3 component-name-unique', () => { "source": "/foobar.yaml", }, ], - "message": "Component 'requestBodies/MyRequestBody' is not unique. It is defined at: - - /foobar.yaml#/components/requestBodies/MyRequestBody + "message": "Component 'requestBodies/MyRequestBody' is not unique. It is also defined at: - /test.yaml#/components/requestBodies/MyRequestBody", "ruleId": "component-name-unique", "severity": "error", "suggest": [], }, + { + "location": [ + { + "pointer": "#/components/requestBodies/MyRequestBody", + "reportOnKey": false, + "source": "/test.yaml", + }, + ], + "message": "Component 'requestBodies/MyRequestBody' is not unique. It is also defined at: + - /foobar.yaml#/components/requestBodies/MyRequestBody", + "ruleId": "component-name-unique", + "severity": "error", + "suggest": [], + }, ] `); }); diff --git a/packages/core/src/rules/oas3/component-name-unique.ts b/packages/core/src/rules/oas3/component-name-unique.ts index 848591b653..c4594abbe8 100644 --- a/packages/core/src/rules/oas3/component-name-unique.ts +++ b/packages/core/src/rules/oas3/component-name-unique.ts @@ -59,23 +59,22 @@ export const ComponentNameUnique: Oas3Rule | Oas2Rule = (options) => { if (value.absolutePointers.size > 1) { const component = getComponentFromKey(key); const optionComponentName = getOptionComponentNameForTypeName(component.typeName); - const definitions = Array.from(value.absolutePointers) - .map((v) => `- ${v}`) - .join('\n'); - const problem: Problem = { - message: `Component '${optionComponentName}/${component.componentName}' is not unique. It is defined at:\n${definitions}`, - }; - problem.location = { - ...value.locations.sort((a, b) => - a.absolutePointer.localeCompare(b.absolutePointer) - )[0], - }; - const componentSeverity = optionComponentName ? options[optionComponentName] : null; - if (componentSeverity) { - problem.forceSeverity = componentSeverity; - } - ctx.report(problem); + value.locations.forEach((location) => { + const definitions = Array.from(value.absolutePointers) + .filter((v) => v !== location.absolutePointer.toString()) + .map((v) => `- ${v}`) + .join('\n'); + const problem: Problem = { + message: `Component '${optionComponentName}/${component.componentName}' is not unique. It is also defined at:\n${definitions}`, + location: location, + }; + if (componentSeverity) { + problem.forceSeverity = componentSeverity; + } + ctx.report(problem); + }); + } }); }, From a774fda6e36efcc4c34edf151c9acd7d131fdcdb Mon Sep 17 00:00:00 2001 From: Patrick Boos Date: Mon, 28 Oct 2024 15:48:56 +0100 Subject: [PATCH 12/12] forEach -> for...of --- packages/core/src/rules/oas3/component-name-unique.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/core/src/rules/oas3/component-name-unique.ts b/packages/core/src/rules/oas3/component-name-unique.ts index c4594abbe8..cbf21fd555 100644 --- a/packages/core/src/rules/oas3/component-name-unique.ts +++ b/packages/core/src/rules/oas3/component-name-unique.ts @@ -60,7 +60,7 @@ export const ComponentNameUnique: Oas3Rule | Oas2Rule = (options) => { const component = getComponentFromKey(key); const optionComponentName = getOptionComponentNameForTypeName(component.typeName); const componentSeverity = optionComponentName ? options[optionComponentName] : null; - value.locations.forEach((location) => { + for (const location of value.locations) { const definitions = Array.from(value.absolutePointers) .filter((v) => v !== location.absolutePointer.toString()) .map((v) => `- ${v}`) @@ -73,8 +73,7 @@ export const ComponentNameUnique: Oas3Rule | Oas2Rule = (options) => { problem.forceSeverity = componentSeverity; } ctx.report(problem); - }); - + } } }); },