From d738c9a86c0791ce4ab536eb41742852ba4decfc Mon Sep 17 00:00:00 2001 From: Aldo Torres Date: Fri, 11 Jul 2025 17:33:43 -0500 Subject: [PATCH 1/3] handle patterns in rule --- .../operations/OAR017ResourcePathCheck.java | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/main/java/apiaddicts/sonar/openapi/checks/operations/OAR017ResourcePathCheck.java b/src/main/java/apiaddicts/sonar/openapi/checks/operations/OAR017ResourcePathCheck.java index 95dcedb..94efff9 100644 --- a/src/main/java/apiaddicts/sonar/openapi/checks/operations/OAR017ResourcePathCheck.java +++ b/src/main/java/apiaddicts/sonar/openapi/checks/operations/OAR017ResourcePathCheck.java @@ -1,22 +1,24 @@ package apiaddicts.sonar.openapi.checks.operations; +import apiaddicts.sonar.openapi.checks.BaseCheck; import com.google.common.collect.ImmutableSet; import com.sonar.sslr.api.AstNodeType; -import org.sonar.check.Rule; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; +import java.util.stream.Stream; 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.Set; -import java.util.stream.Stream; +import org.sonar.check.Rule; @Rule(key = OAR017ResourcePathCheck.KEY) public class OAR017ResourcePathCheck extends BaseCheck { public static final String KEY = "OAR017"; private static final String MESSAGE = "OAR017.error"; + public static final Set EXCLUDE_PATTERNS = new HashSet<>(Arrays.asList("get", "me", "search")); @Override public Set subscribedKinds() { @@ -43,6 +45,10 @@ private boolean isCorrect(String path) { for (int i = 0; i < parts.length; i++) { boolean currentIsVariable = isVariable(parts[i]); + if(!currentIsVariable && EXCLUDE_PATTERNS.contains(parts[i])){ + twoOrMoreVariablesInARow = false; + } + if (previousWasVariable && currentIsVariable) { twoOrMoreVariablesInARow = true; break; From ef5f5d8fccc8d86c68fdf51a7a7767f9ae3ea956 Mon Sep 17 00:00:00 2001 From: Aldo Torres Date: Thu, 23 Oct 2025 13:34:07 -0500 Subject: [PATCH 2/3] feat: adding oar017 patterns parameters to ignore --- .../operations/OAR017ResourcePathCheck.java | 25 ++++++++++++++----- src/main/resources/messages/errors.properties | 1 + .../resources/messages/errors_es.properties | 1 + .../OAR017ResourcePathCheckTest.java | 11 +++++--- .../checks/v3/operations/OAR017/plain.json | 2 +- .../checks/v3/operations/OAR017/plain.yaml | 2 +- 6 files changed, 31 insertions(+), 11 deletions(-) diff --git a/src/main/java/apiaddicts/sonar/openapi/checks/operations/OAR017ResourcePathCheck.java b/src/main/java/apiaddicts/sonar/openapi/checks/operations/OAR017ResourcePathCheck.java index 94efff9..42152bc 100644 --- a/src/main/java/apiaddicts/sonar/openapi/checks/operations/OAR017ResourcePathCheck.java +++ b/src/main/java/apiaddicts/sonar/openapi/checks/operations/OAR017ResourcePathCheck.java @@ -4,7 +4,6 @@ import com.google.common.collect.ImmutableSet; import com.sonar.sslr.api.AstNodeType; import java.util.Arrays; -import java.util.HashSet; import java.util.Set; import java.util.stream.Stream; import org.apiaddicts.apitools.dosonarapi.api.v2.OpenApi2Grammar; @@ -12,13 +11,22 @@ import org.apiaddicts.apitools.dosonarapi.api.v31.OpenApi31Grammar; import org.apiaddicts.apitools.dosonarapi.sslr.yaml.grammar.JsonNode; import org.sonar.check.Rule; +import org.sonar.check.RuleProperty; @Rule(key = OAR017ResourcePathCheck.KEY) public class OAR017ResourcePathCheck extends BaseCheck { public static final String KEY = "OAR017"; private static final String MESSAGE = "OAR017.error"; - public static final Set EXCLUDE_PATTERNS = new HashSet<>(Arrays.asList("get", "me", "search")); + private static final String MESSAGE_PATTERN = "OAR017.error-patterns"; + // public static final Set EXCLUDE_PATTERNS = new HashSet<>(Arrays.asList("get", "me", "search")); + public static final String EXCLUDE_PATTERNS = "get,me,search"; + + @RuleProperty( + key = "exclude_patterns", + description = "List of exlude pattenrs separated by coma.", + defaultValue = EXCLUDE_PATTERNS) + public String patternsString = EXCLUDE_PATTERNS; @Override public Set subscribedKinds() { @@ -32,11 +40,12 @@ public void visitNode(JsonNode node) { private void visitV2Node(JsonNode node) { String path = node.key().getTokenValue(); - if (!isCorrect(path)) addIssue(KEY, translate(MESSAGE), node.key()); + if (!isCorrect(path,node)) addIssue(KEY, translate(MESSAGE), node.key()); } - private boolean isCorrect(String path) { + private boolean isCorrect(String path, JsonNode node) { String[] parts = Stream.of(path.split("/")).filter(p -> !p.trim().isEmpty()).toArray(String[]::new); + String[] patterns = Stream.of(patternsString.split(",")).toArray(String[]::new); if (parts.length == 0) return true; boolean previousWasVariable = false; @@ -45,8 +54,8 @@ private boolean isCorrect(String path) { for (int i = 0; i < parts.length; i++) { boolean currentIsVariable = isVariable(parts[i]); - if(!currentIsVariable && EXCLUDE_PATTERNS.contains(parts[i])){ - twoOrMoreVariablesInARow = false; + if(!currentIsVariable && Arrays.asList(patterns).contains(parts[i])){ + issuePatterns(parts[i],node); } if (previousWasVariable && currentIsVariable) { @@ -63,4 +72,8 @@ private boolean isCorrect(String path) { private boolean isVariable(String part) { return '{' == part.charAt(0) && '}' == part.charAt(part.length() - 1); } + + private void issuePatterns(String pattern,JsonNode node){ + addIssue(KEY, translate(MESSAGE_PATTERN,pattern), node.key()); + } } \ No newline at end of file diff --git a/src/main/resources/messages/errors.properties b/src/main/resources/messages/errors.properties index 88e9407..b1294d7 100644 --- a/src/main/resources/messages/errors.properties +++ b/src/main/resources/messages/errors.properties @@ -14,6 +14,7 @@ OAR012.error=Path params names, query params names, object names and property na OAR013.error=Default response is required OAR016.error=Numeric types requires a valid format OAR017.error=Resource path should alternate static and parametrized parts +OAR017.error-patterns=Pattern ''{0}'' not allowed OAR018.error=Operation not recommended for resource path: {0} OAR019.error={0} must be defined as a parameter in this operation OAR020.error={0} must be defined as a parameter in this operation diff --git a/src/main/resources/messages/errors_es.properties b/src/main/resources/messages/errors_es.properties index f79e905..29f1000 100644 --- a/src/main/resources/messages/errors_es.properties +++ b/src/main/resources/messages/errors_es.properties @@ -14,6 +14,7 @@ OAR012.error=Los nombres de parámetros de ruta, parámetros de consulta, objeto OAR013.error=La respuesta por defecto es obligatoria OAR016.error=Tipos numéricos requieren un formato válido OAR017.error=El path del recurso debe de alternar entre partes estáticas y parametrizadas +OAR017.error-patterns=Patrón ''{0}'' no permitido OAR018.error=Acción no recomendada para la ruta de recursos: {0} OAR019.error={0} debe ser definido como un parámetro en esta operación OAR020.error={0} debe ser definido como un parámetro en esta operación diff --git a/src/test/java/apiaddicts/sonar/openapi/checks/operations/OAR017ResourcePathCheckTest.java b/src/test/java/apiaddicts/sonar/openapi/checks/operations/OAR017ResourcePathCheckTest.java index 27b3f32..95db735 100644 --- a/src/test/java/apiaddicts/sonar/openapi/checks/operations/OAR017ResourcePathCheckTest.java +++ b/src/test/java/apiaddicts/sonar/openapi/checks/operations/OAR017ResourcePathCheckTest.java @@ -1,12 +1,11 @@ package apiaddicts.sonar.openapi.checks.operations; +import apiaddicts.sonar.openapi.BaseCheckTest; import org.junit.Before; import org.junit.Test; import org.sonar.api.rule.Severity; import org.sonar.api.rules.RuleType; -import apiaddicts.sonar.openapi.BaseCheckTest; - -import apiaddicts.sonar.openapi.checks.operations.OAR017ResourcePathCheck; +import org.sonar.api.server.rule.RuleParamType; public class OAR017ResourcePathCheckTest extends BaseCheckTest { @@ -33,4 +32,10 @@ public void verifyRule() { assertRuleProperties("OAR017 - ResourcePath - Resource path should alternate static and parametrized parts", RuleType.BUG, Severity.MAJOR, tags("operations")); } + @Override + public void verifyParameters() { + assertNumberOfParameters(1); + assertParameterProperties("exclude_patterns", "get,me,search", RuleParamType.STRING); + } + } \ No newline at end of file diff --git a/src/test/resources/checks/v3/operations/OAR017/plain.json b/src/test/resources/checks/v3/operations/OAR017/plain.json index 23133f7..1c9602c 100644 --- a/src/test/resources/checks/v3/operations/OAR017/plain.json +++ b/src/test/resources/checks/v3/operations/OAR017/plain.json @@ -5,7 +5,7 @@ "title" : "Swagger Petstore" }, "paths" : { - "/one" : { + "/one/me" : { # Noncompliant {{OAR017: Pattern 'me' not allowed}} "get" : { "responses" : { "200" : { diff --git a/src/test/resources/checks/v3/operations/OAR017/plain.yaml b/src/test/resources/checks/v3/operations/OAR017/plain.yaml index c06718b..e1d0c12 100644 --- a/src/test/resources/checks/v3/operations/OAR017/plain.yaml +++ b/src/test/resources/checks/v3/operations/OAR017/plain.yaml @@ -3,7 +3,7 @@ info: version: 1.0.0 title: Swagger Petstore paths: - /one: + /one/me: # Noncompliant {{OAR017: Pattern 'me' not allowed}} get: responses: 200: From acd5f360f090c163e63d952bc0e722afa413d908 Mon Sep 17 00:00:00 2001 From: Aldo Torres Date: Mon, 27 Oct 2025 12:56:56 -0500 Subject: [PATCH 3/3] Delete comments --- .../sonar/openapi/checks/operations/OAR017ResourcePathCheck.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/apiaddicts/sonar/openapi/checks/operations/OAR017ResourcePathCheck.java b/src/main/java/apiaddicts/sonar/openapi/checks/operations/OAR017ResourcePathCheck.java index 42152bc..83db0b9 100644 --- a/src/main/java/apiaddicts/sonar/openapi/checks/operations/OAR017ResourcePathCheck.java +++ b/src/main/java/apiaddicts/sonar/openapi/checks/operations/OAR017ResourcePathCheck.java @@ -19,7 +19,6 @@ public class OAR017ResourcePathCheck extends BaseCheck { public static final String KEY = "OAR017"; private static final String MESSAGE = "OAR017.error"; private static final String MESSAGE_PATTERN = "OAR017.error-patterns"; - // public static final Set EXCLUDE_PATTERNS = new HashSet<>(Arrays.asList("get", "me", "search")); public static final String EXCLUDE_PATTERNS = "get,me,search"; @RuleProperty(