From d3ec8dac2514dcd7aea3ec7eb1f055b73e9d2780 Mon Sep 17 00:00:00 2001 From: Aldo Torres Date: Wed, 22 Oct 2025 12:14:58 -0500 Subject: [PATCH 1/3] testing yaml --- .../v3/examples/OAR031/without-examples.yaml | 203 +++++++++++++----- 1 file changed, 151 insertions(+), 52 deletions(-) diff --git a/src/test/resources/checks/v3/examples/OAR031/without-examples.yaml b/src/test/resources/checks/v3/examples/OAR031/without-examples.yaml index e1fcaa43..9bd23c30 100644 --- a/src/test/resources/checks/v3/examples/OAR031/without-examples.yaml +++ b/src/test/resources/checks/v3/examples/OAR031/without-examples.yaml @@ -1,73 +1,172 @@ +# openapi: "3.0.0" +# info: +# version: 1.0.0 +# title: Swagger Petstore +# paths: +# /pets: +# get: +# responses: +# 206: # Noncompliant {{OAR031: Responses must have one or more examples defined}} +# description: Pet list +# content: +# application/json: +# schema: +# $ref: '#/components/schemas/pets' +# default: +# $ref: "#/components/responses/server_error_response" +# /pets/{id}: +# parameters: +# - in: query # Noncompliant {{OAR031: Parameters must have one or more examples defined}} +# name: $start +# schema: +# type: integer +# get: +# parameters: +# - $ref: "#/components/parameters/id" +# responses: +# 200: # Noncompliant {{OAR031: Responses must have one or more examples defined}} +# description: One pet +# content: +# application/json: +# schema: +# $ref: "#/components/schemas/pet" +# default: +# $ref: "#/components/responses/server_error_response" + +# components: +# parameters: +# id: +# in: path # Noncompliant {{OAR031: Parameters must have one or more examples defined}} +# name: id +# schema: +# type: integer +# format: int64 +# maxLength: 22 +# description: Identificador del tipo de centro a obtener, actualizar o eliminar. +# required: true +# schemas: +# pet: +# type: object +# properties: +# name: # Noncompliant {{OAR031: Properties must have an example defined}} +# type: string +# type: # Noncompliant {{OAR031: Properties must have an example defined}} +# type: string +# pets: +# type: object +# properties: +# size: # Noncompliant {{OAR031: Properties must have an example defined}} +# type: integer +# pets: # Noncompliant {{OAR031: Properties must have an example defined}} +# type: array +# items: +# $ref: '#/components/schemas/pet' +# responses: +# server_error_response: # Noncompliant {{OAR031: Responses must have one or more examples defined}} +# description: Default error response +# content: +# application/json: +# schema: +# type: object +# properties: +# error: # Noncompliant {{OAR031: Properties must have an example defined}} +# type: string + openapi: "3.0.0" info: + title: API de Migraciones version: 1.0.0 - title: Swagger Petstore + paths: - /pets: - get: - responses: - 206: # Noncompliant {{OAR031: Responses must have one or more examples defined}} - description: Pet list - content: - application/json: - schema: - $ref: '#/components/schemas/pets' - default: - $ref: "#/components/responses/server_error_response" - /pets/{id}: - parameters: - - in: query # Noncompliant {{OAR031: Parameters must have one or more examples defined}} - name: $start - schema: - type: integer + /migraciones: get: - parameters: - - $ref: "#/components/parameters/id" + summary: Obtiene la lista de migraciones + description: Endpoint que devuelve la lista de migraciones existentes. responses: - 200: # Noncompliant {{OAR031: Responses must have one or more examples defined}} - description: One pet - content: - application/json: - schema: - $ref: "#/components/schemas/pet" + 200: + $ref: '#/components/responses/migracion_get_response' default: - $ref: "#/components/responses/server_error_response" + $ref: '#/components/responses/server_error_response' components: - parameters: - id: - in: path # Noncompliant {{OAR031: Parameters must have one or more examples defined}} - name: id - schema: - type: integer - format: int64 - maxLength: 22 - description: Identificador del tipo de centro a obtener, actualizar o eliminar. - required: true schemas: - pet: + id: + type: string + example: "abc123" + + standard_response_with_metadata: type: object properties: - name: # Noncompliant {{OAR031: Properties must have an example defined}} - type: string - type: # Noncompliant {{OAR031: Properties must have an example defined}} - type: string - pets: + metadata: + type: object + properties: + total: + type: integer + example: 1 + page: + type: integer + example: 1 + limit: + type: integer + example: 10 + migracion_get_response: type: object properties: - size: # Noncompliant {{OAR031: Properties must have an example defined}} - type: integer - pets: # Noncompliant {{OAR031: Properties must have an example defined}} - type: array - items: - $ref: '#/components/schemas/pet' + metadata: + type: object + properties: + total: + type: integer + example: 1 + page: + type: integer + example: 1 + limit: + type: integer + example: 10 + + + examples: + migracion_get_response: + summary: Ejemplo de respuesta exitosa + value: + metadata: + total: 1 + page: 1 + limit: 10 + data: + migraciones: + - id: "migracion-001" + nombre: "Migración inicial" + estado: "completada" + responses: server_error_response: # Noncompliant {{OAR031: Responses must have one or more examples defined}} - description: Default error response + description: Respuesta de error genérica del servidor content: application/json: schema: type: object properties: - error: # Noncompliant {{OAR031: Properties must have an example defined}} - type: string \ No newline at end of file + error: + type: string + example: "Error interno del servidor" + migracion_get_response: + description: Datos de la consulta migración obtenidos exitosamente. + content: + application/json: + schema: + allOf: + - $ref: '#/components/schemas/standard_response_with_metadata' + properties: + data: + type: object + properties: + migraciones: + type: array + items: + $ref: '#/components/schemas/migracion_get_response' + example: ['an example'] + examples: + Ejemplo 1: + $ref: '#/components/examples/migracion_get_response' \ No newline at end of file From c3584665dc6ece2011621d5b163a12245d7e0c5a Mon Sep 17 00:00:00 2001 From: Aldo Torres Date: Fri, 14 Nov 2025 17:01:33 -0500 Subject: [PATCH 2/3] fix: delete comments if there are any allOf field --- .../checks/examples/OAR031ExamplesCheck.java | 60 ++++++++++++------- .../checks/v3/examples/OAR031/valid.yaml | 2 +- 2 files changed, 41 insertions(+), 21 deletions(-) diff --git a/src/main/java/apiaddicts/sonar/openapi/checks/examples/OAR031ExamplesCheck.java b/src/main/java/apiaddicts/sonar/openapi/checks/examples/OAR031ExamplesCheck.java index c52e2159..d6e402e6 100644 --- a/src/main/java/apiaddicts/sonar/openapi/checks/examples/OAR031ExamplesCheck.java +++ b/src/main/java/apiaddicts/sonar/openapi/checks/examples/OAR031ExamplesCheck.java @@ -1,20 +1,23 @@ package apiaddicts.sonar.openapi.checks.examples; +import apiaddicts.sonar.openapi.checks.BaseCheck; +import static apiaddicts.sonar.openapi.utils.JsonNodeUtils.getType; +import static apiaddicts.sonar.openapi.utils.JsonNodeUtils.isArrayType; +import static apiaddicts.sonar.openapi.utils.JsonNodeUtils.isExternalRef; +import static apiaddicts.sonar.openapi.utils.JsonNodeUtils.isObjectType; +import static apiaddicts.sonar.openapi.utils.JsonNodeUtils.isOperation; +import static apiaddicts.sonar.openapi.utils.JsonNodeUtils.resolve; import com.google.common.collect.ImmutableSet; import com.sonar.sslr.api.AstNodeType; -import org.sonar.check.Rule; -import org.apiaddicts.apitools.dosonarapi.api.v2.OpenApi2Grammar; -import org.apiaddicts.apitools.dosonarapi.api.v3.OpenApi3Grammar; -import org.apiaddicts.apitools.dosonarapi.api.v31.OpenApi31Grammar; -import apiaddicts.sonar.openapi.checks.BaseCheck; -import org.apiaddicts.apitools.dosonarapi.sslr.yaml.grammar.JsonNode; - import java.util.List; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; - -import static apiaddicts.sonar.openapi.utils.JsonNodeUtils.*; +import org.apiaddicts.apitools.dosonarapi.api.v2.OpenApi2Grammar; +import org.apiaddicts.apitools.dosonarapi.api.v3.OpenApi3Grammar; +import org.apiaddicts.apitools.dosonarapi.api.v31.OpenApi31Grammar; +import org.apiaddicts.apitools.dosonarapi.sslr.yaml.grammar.JsonNode; +import org.sonar.check.Rule; @Rule(key = OAR031ExamplesCheck.KEY) public class OAR031ExamplesCheck extends BaseCheck { @@ -52,7 +55,9 @@ private void visitV2Node(JsonNode node) { } responseNode = resolve(responseNode); visitResponseV2Node(responseNode); - if (externalRefManagement) externalRefNode = null; + if (externalRefManagement) { + externalRefNode = null; + } } } } @@ -80,8 +85,10 @@ private void visitV3Node(JsonNode node) { } responseNode = resolve(responseNode); visitRequestBodyOrResponseV3Node(responseNode); - if (externalRefManagement) externalRefNode = null; - } + if (externalRefManagement) { + externalRefNode = null; + } + } } } else if (type.equals(OpenApi3Grammar.SCHEMA)) { visitSchemaNode(node); @@ -92,7 +99,9 @@ private void visitV3Node(JsonNode node) { private void visitRequestBodyOrResponseV3Node(JsonNode node) { JsonNode content = node.at("/content"); - if (content.isMissing()) return; + if (content.isMissing()) { + return; + } for (JsonNode mediaTypeNode : content.propertyMap().values()) { AstNodeType type = node.getType(); JsonNode schemaNode = mediaTypeNode.get("schema"); @@ -117,8 +126,13 @@ private void visitSchemaNode(JsonNode node) { if (node.get("example").isMissing() && parentNode.get("example").isMissing() && parentNode.get("examples").isMissing()) { addIssue(KEY, translate("OAR031.error-parameter"), parentNode); } - } else if (parentNode.getType().equals(OpenApi3Grammar.SCHEMA_PROPERTIES) || - parentNode.getType().toString().equals("BLOCK_MAPPING") || parentNode.getType().toString().equals("FLOW_MAPPING")) { + } else if (parentNode.getType().equals(OpenApi3Grammar.SCHEMA_PROPERTIES) + || parentNode.getType().toString().equals("BLOCK_MAPPING") || parentNode.getType().toString().equals("FLOW_MAPPING")) { + JsonNode schemaParent = (JsonNode) parentNode.getParent().getParent(); + if (schemaParent != null && !schemaParent.get("allOf").isMissing()) { + return; + } + JsonNode type = getType(node); if (!isObjectType(type) && !type.isMissing() && !isArrayType(type)) { if (node.get("example").isMissing()) { @@ -129,7 +143,7 @@ private void visitSchemaNode(JsonNode node) { } private void visitPathNode(JsonNode node) { - List allResponses = node.properties().stream().filter(propertyNode -> isOperation(propertyNode)) + List allResponses = node.properties().stream().filter(propertyNode -> isOperation(propertyNode)) .map(JsonNode::value) .flatMap(n -> n.properties().stream()) .map(JsonNode::value) @@ -148,15 +162,21 @@ private void visitPathNode(JsonNode node) { } else if (responseNode.getType().equals(OpenApi3Grammar.RESPONSE)) { JsonNode content = responseNode.at("/content"); if (content.isMissing()) { - if (externalRefManagement) externalRefNode = null; + if (externalRefManagement) { + externalRefNode = null; + } continue; } content.propertyMap().forEach((mediaType, mediaTypeNode) -> { // estudiar función lambda - if (!mediaType.toLowerCase().contains("json")) return; - visitSchemaNode2(mediaTypeNode); + if (!mediaType.toLowerCase().contains("json")) { + return; + } + visitSchemaNode(mediaTypeNode); }); } - if (externalRefManagement) externalRefNode = null; + if (externalRefManagement) { + externalRefNode = null; + } } } diff --git a/src/test/resources/checks/v3/examples/OAR031/valid.yaml b/src/test/resources/checks/v3/examples/OAR031/valid.yaml index 2e7ebeac..d0100253 100644 --- a/src/test/resources/checks/v3/examples/OAR031/valid.yaml +++ b/src/test/resources/checks/v3/examples/OAR031/valid.yaml @@ -94,7 +94,7 @@ components: size: type: integer example: 1 - pets: # Noncompliant {{OAR031: Properties must have an example defined}} + pets: type: array items: $ref: '#/components/schemas/pet' From b139b42d04637dc956591005822acdad7a7d0a2e Mon Sep 17 00:00:00 2001 From: Aldo Torres Date: Fri, 14 Nov 2025 17:07:35 -0500 Subject: [PATCH 3/3] modify yaml --- .../v3/examples/OAR031/without-examples.yaml | 203 +++++------------- 1 file changed, 52 insertions(+), 151 deletions(-) diff --git a/src/test/resources/checks/v3/examples/OAR031/without-examples.yaml b/src/test/resources/checks/v3/examples/OAR031/without-examples.yaml index 9bd23c30..ec8cd2a0 100644 --- a/src/test/resources/checks/v3/examples/OAR031/without-examples.yaml +++ b/src/test/resources/checks/v3/examples/OAR031/without-examples.yaml @@ -1,172 +1,73 @@ -# openapi: "3.0.0" -# info: -# version: 1.0.0 -# title: Swagger Petstore -# paths: -# /pets: -# get: -# responses: -# 206: # Noncompliant {{OAR031: Responses must have one or more examples defined}} -# description: Pet list -# content: -# application/json: -# schema: -# $ref: '#/components/schemas/pets' -# default: -# $ref: "#/components/responses/server_error_response" -# /pets/{id}: -# parameters: -# - in: query # Noncompliant {{OAR031: Parameters must have one or more examples defined}} -# name: $start -# schema: -# type: integer -# get: -# parameters: -# - $ref: "#/components/parameters/id" -# responses: -# 200: # Noncompliant {{OAR031: Responses must have one or more examples defined}} -# description: One pet -# content: -# application/json: -# schema: -# $ref: "#/components/schemas/pet" -# default: -# $ref: "#/components/responses/server_error_response" - -# components: -# parameters: -# id: -# in: path # Noncompliant {{OAR031: Parameters must have one or more examples defined}} -# name: id -# schema: -# type: integer -# format: int64 -# maxLength: 22 -# description: Identificador del tipo de centro a obtener, actualizar o eliminar. -# required: true -# schemas: -# pet: -# type: object -# properties: -# name: # Noncompliant {{OAR031: Properties must have an example defined}} -# type: string -# type: # Noncompliant {{OAR031: Properties must have an example defined}} -# type: string -# pets: -# type: object -# properties: -# size: # Noncompliant {{OAR031: Properties must have an example defined}} -# type: integer -# pets: # Noncompliant {{OAR031: Properties must have an example defined}} -# type: array -# items: -# $ref: '#/components/schemas/pet' -# responses: -# server_error_response: # Noncompliant {{OAR031: Responses must have one or more examples defined}} -# description: Default error response -# content: -# application/json: -# schema: -# type: object -# properties: -# error: # Noncompliant {{OAR031: Properties must have an example defined}} -# type: string - openapi: "3.0.0" info: - title: API de Migraciones version: 1.0.0 - + title: Swagger Petstore paths: - /migraciones: + /pets: + get: + responses: + 206: # Noncompliant {{OAR031: Responses must have one or more examples defined}} + description: Pet list + content: + application/json: + schema: + $ref: '#/components/schemas/pets' + default: + $ref: "#/components/responses/server_error_response" + /pets/{id}: + parameters: + - in: query # Noncompliant {{OAR031: Parameters must have one or more examples defined}} + name: $start + schema: + type: integer get: - summary: Obtiene la lista de migraciones - description: Endpoint que devuelve la lista de migraciones existentes. + parameters: + - $ref: "#/components/parameters/id" responses: - 200: - $ref: '#/components/responses/migracion_get_response' + 200: # Noncompliant {{OAR031: Responses must have one or more examples defined}} + description: One pet + content: + application/json: + schema: + $ref: "#/components/schemas/pet" default: - $ref: '#/components/responses/server_error_response' + $ref: "#/components/responses/server_error_response" components: - schemas: + parameters: id: - type: string - example: "abc123" - - standard_response_with_metadata: + in: path # Noncompliant {{OAR031: Parameters must have one or more examples defined}} + name: id + schema: + type: integer + format: int64 + maxLength: 22 + description: Identificador del tipo de centro a obtener, actualizar o eliminar. + required: true + schemas: + pet: type: object properties: - metadata: - type: object - properties: - total: - type: integer - example: 1 - page: - type: integer - example: 1 - limit: - type: integer - example: 10 - migracion_get_response: + name: # Noncompliant {{OAR031: Properties must have an example defined}} + type: string + type: # Noncompliant {{OAR031: Properties must have an example defined}} + type: string + pets: type: object properties: - metadata: - type: object - properties: - total: - type: integer - example: 1 - page: - type: integer - example: 1 - limit: - type: integer - example: 10 - - - examples: - migracion_get_response: - summary: Ejemplo de respuesta exitosa - value: - metadata: - total: 1 - page: 1 - limit: 10 - data: - migraciones: - - id: "migracion-001" - nombre: "Migración inicial" - estado: "completada" - + size: # Noncompliant {{OAR031: Properties must have an example defined}} + type: integer + pets: + type: array + items: + $ref: '#/components/schemas/pet' responses: server_error_response: # Noncompliant {{OAR031: Responses must have one or more examples defined}} - description: Respuesta de error genérica del servidor + description: Default error response content: application/json: schema: type: object properties: - error: - type: string - example: "Error interno del servidor" - migracion_get_response: - description: Datos de la consulta migración obtenidos exitosamente. - content: - application/json: - schema: - allOf: - - $ref: '#/components/schemas/standard_response_with_metadata' - properties: - data: - type: object - properties: - migraciones: - type: array - items: - $ref: '#/components/schemas/migracion_get_response' - example: ['an example'] - examples: - Ejemplo 1: - $ref: '#/components/examples/migracion_get_response' \ No newline at end of file + error: # Noncompliant {{OAR031: Properties must have an example defined}} + type: string \ No newline at end of file