diff --git a/src/core_codemods/sonar/results.py b/src/core_codemods/sonar/results.py index dbbe122a..2c6025ae 100644 --- a/src/core_codemods/sonar/results.py +++ b/src/core_codemods/sonar/results.py @@ -13,14 +13,34 @@ def sonar_url_from_id(rule_id: str) -> str: - # convert "python:SXXX" or "pythonsecurity:SXXX" to XXX + language = "python" try: - rule_id = rule_id.split(":")[1][1:] + # convert "python:SXXX" or "pythonsecurity:SXXX" to python and XXX + prefix, number = rule_id.split(":") + number = number[1:] + match prefix: + case "python" | "pythonsecurity": + language = "python" + case "java" | "javasecurity": + language = "java" + case "javascript" | "jssecurity": + language = "javascript" + case "typescript" | "tssecurity": + language = "typescript" + case "roslyn.sonaranalyzer.security.cs" | "csharpsquid": + language = "dotnet" + case "phpsecurity": + language = "php" + case "xml": + language = "xml" + case _: + logger.debug(f"Unknown language in sonar rule: {prefix}") + except IndexError: logger.debug("Invalid sonar rule id: %s", rule_id) raise - return f"https://rules.sonarsource.com/python/RSPEC-{rule_id}/" + return f"https://rules.sonarsource.com/{language}/RSPEC-{number}/" class SonarLocation(Location): diff --git a/tests/test_results.py b/tests/test_results.py index 7e697765..04a18d8d 100644 --- a/tests/test_results.py +++ b/tests/test_results.py @@ -5,6 +5,160 @@ class TestResults: + + def test_generated_urls(self, tmpdir): + issues = { + "issues": [ + { + "rule": "python:S5659", + "status": "OPEN", + "component": "code.py", + "textRange": { + "startLine": 2, + "endLine": 2, + "startOffset": 2, + "endOffset": 2, + }, + }, + { + "rule": "pythonsecurity:S5147", + "status": "OPEN", + "component": "code.py", + "textRange": { + "startLine": 19, + "endLine": 23, + "startOffset": 4, + "endOffset": 5, + }, + }, + { + "rule": "javascript:S6535", + "component": "pixee_bad-code:code.js", + "textRange": { + "startLine": 3, + "endLine": 3, + "startOffset": 11, + "endOffset": 12, + }, + "status": "OPEN", + }, + { + "rule": "jssecurity:S2076", + "component": "pixee_bad-code:code.js", + "textRange": { + "startLine": 11, + "endLine": 11, + "startOffset": 4, + "endOffset": 8, + }, + "status": "OPEN", + }, + { + "status": "OPEN", + "rule": "typescript:S3504", + "component": "pixee_bad-code:code.ts", + "textRange": { + "startLine": 1, + "endLine": 1, + "startOffset": 0, + "endOffset": 7, + }, + }, + { + "rule": "tssecurity:S2076", + "component": "pixee_bad-code:code.ts", + "textRange": { + "startLine": 11, + "endLine": 11, + "startOffset": 4, + "endOffset": 8, + }, + "status": "OPEN", + }, + { + "rule": "csharpsquid:S3878", + "component": "code.cs", + "line": 16, + "textRange": { + "startLine": 16, + "endLine": 16, + "startOffset": 40, + "endOffset": 53, + }, + "flows": [], + "status": "OPEN", + }, + { + "rule": "roslyn.sonaranalyzer.security.cs:S5131", + "status": "OPEN", + "component": "code.cs", + "textRange": { + "startLine": 10, + "endLine": 10, + "startOffset": 8, + "endOffset": 36, + }, + }, + { + "status": "OPEN", + "rule": "phpsecurity:S5131", + "component": "pixee_bad-code:code.php", + "textRange": { + "startLine": 3, + "endLine": 3, + "startOffset": 4, + "endOffset": 33, + }, + }, + ] + } + sonar_json = Path(tmpdir) / "sonar_python.json" + sonar_json.write_text(json.dumps(issues)) + + result = SonarResultSet.from_json(sonar_json) + assert ( + result.results_for_rules(["python:S5659"])[0].finding.rule.url + == "https://rules.sonarsource.com/python/RSPEC-5659/" + ) + assert ( + result.results_for_rules(["pythonsecurity:S5147"])[0].finding.rule.url + == "https://rules.sonarsource.com/python/RSPEC-5147/" + ) + + assert ( + result.results_for_rules(["javascript:S6535"])[0].finding.rule.url + == "https://rules.sonarsource.com/javascript/RSPEC-6535/" + ) + assert ( + result.results_for_rules(["jssecurity:S2076"])[0].finding.rule.url + == "https://rules.sonarsource.com/javascript/RSPEC-2076/" + ) + + assert ( + result.results_for_rules(["typescript:S3504"])[0].finding.rule.url + == "https://rules.sonarsource.com/typescript/RSPEC-3504/" + ) + assert ( + result.results_for_rules(["tssecurity:S2076"])[0].finding.rule.url + == "https://rules.sonarsource.com/typescript/RSPEC-2076/" + ) + + assert ( + result.results_for_rules(["csharpsquid:S3878"])[0].finding.rule.url + == "https://rules.sonarsource.com/dotnet/RSPEC-3878/" + ) + assert ( + result.results_for_rules(["roslyn.sonaranalyzer.security.cs:S5131"])[ + 0 + ].finding.rule.url + == "https://rules.sonarsource.com/dotnet/RSPEC-5131/" + ) + + assert ( + result.results_for_rules(["phpsecurity:S5131"])[0].finding.rule.url + == "https://rules.sonarsource.com/php/RSPEC-5131/" + ) + def test_or(self, tmpdir): issues1 = { "issues": [