Skip to content

Commit 332907a

Browse files
authored
Fixed sonar URL generation from rule id (#1038)
Added languages cases for generating sonar url from rule id
1 parent 4cebd9e commit 332907a

File tree

2 files changed

+177
-3
lines changed

2 files changed

+177
-3
lines changed

src/core_codemods/sonar/results.py

+23-3
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,34 @@
1313

1414

1515
def sonar_url_from_id(rule_id: str) -> str:
16-
# convert "python:SXXX" or "pythonsecurity:SXXX" to XXX
16+
language = "python"
1717
try:
18-
rule_id = rule_id.split(":")[1][1:]
18+
# convert "python:SXXX" or "pythonsecurity:SXXX" to python and XXX
19+
prefix, number = rule_id.split(":")
20+
number = number[1:]
21+
match prefix:
22+
case "python" | "pythonsecurity":
23+
language = "python"
24+
case "java" | "javasecurity":
25+
language = "java"
26+
case "javascript" | "jssecurity":
27+
language = "javascript"
28+
case "typescript" | "tssecurity":
29+
language = "typescript"
30+
case "roslyn.sonaranalyzer.security.cs" | "csharpsquid":
31+
language = "dotnet"
32+
case "phpsecurity":
33+
language = "php"
34+
case "xml":
35+
language = "xml"
36+
case _:
37+
logger.debug(f"Unknown language in sonar rule: {prefix}")
38+
1939
except IndexError:
2040
logger.debug("Invalid sonar rule id: %s", rule_id)
2141
raise
2242

23-
return f"https://rules.sonarsource.com/python/RSPEC-{rule_id}/"
43+
return f"https://rules.sonarsource.com/{language}/RSPEC-{number}/"
2444

2545

2646
class SonarLocation(Location):

tests/test_results.py

+154
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,160 @@
55

66

77
class TestResults:
8+
9+
def test_generated_urls(self, tmpdir):
10+
issues = {
11+
"issues": [
12+
{
13+
"rule": "python:S5659",
14+
"status": "OPEN",
15+
"component": "code.py",
16+
"textRange": {
17+
"startLine": 2,
18+
"endLine": 2,
19+
"startOffset": 2,
20+
"endOffset": 2,
21+
},
22+
},
23+
{
24+
"rule": "pythonsecurity:S5147",
25+
"status": "OPEN",
26+
"component": "code.py",
27+
"textRange": {
28+
"startLine": 19,
29+
"endLine": 23,
30+
"startOffset": 4,
31+
"endOffset": 5,
32+
},
33+
},
34+
{
35+
"rule": "javascript:S6535",
36+
"component": "pixee_bad-code:code.js",
37+
"textRange": {
38+
"startLine": 3,
39+
"endLine": 3,
40+
"startOffset": 11,
41+
"endOffset": 12,
42+
},
43+
"status": "OPEN",
44+
},
45+
{
46+
"rule": "jssecurity:S2076",
47+
"component": "pixee_bad-code:code.js",
48+
"textRange": {
49+
"startLine": 11,
50+
"endLine": 11,
51+
"startOffset": 4,
52+
"endOffset": 8,
53+
},
54+
"status": "OPEN",
55+
},
56+
{
57+
"status": "OPEN",
58+
"rule": "typescript:S3504",
59+
"component": "pixee_bad-code:code.ts",
60+
"textRange": {
61+
"startLine": 1,
62+
"endLine": 1,
63+
"startOffset": 0,
64+
"endOffset": 7,
65+
},
66+
},
67+
{
68+
"rule": "tssecurity:S2076",
69+
"component": "pixee_bad-code:code.ts",
70+
"textRange": {
71+
"startLine": 11,
72+
"endLine": 11,
73+
"startOffset": 4,
74+
"endOffset": 8,
75+
},
76+
"status": "OPEN",
77+
},
78+
{
79+
"rule": "csharpsquid:S3878",
80+
"component": "code.cs",
81+
"line": 16,
82+
"textRange": {
83+
"startLine": 16,
84+
"endLine": 16,
85+
"startOffset": 40,
86+
"endOffset": 53,
87+
},
88+
"flows": [],
89+
"status": "OPEN",
90+
},
91+
{
92+
"rule": "roslyn.sonaranalyzer.security.cs:S5131",
93+
"status": "OPEN",
94+
"component": "code.cs",
95+
"textRange": {
96+
"startLine": 10,
97+
"endLine": 10,
98+
"startOffset": 8,
99+
"endOffset": 36,
100+
},
101+
},
102+
{
103+
"status": "OPEN",
104+
"rule": "phpsecurity:S5131",
105+
"component": "pixee_bad-code:code.php",
106+
"textRange": {
107+
"startLine": 3,
108+
"endLine": 3,
109+
"startOffset": 4,
110+
"endOffset": 33,
111+
},
112+
},
113+
]
114+
}
115+
sonar_json = Path(tmpdir) / "sonar_python.json"
116+
sonar_json.write_text(json.dumps(issues))
117+
118+
result = SonarResultSet.from_json(sonar_json)
119+
assert (
120+
result.results_for_rules(["python:S5659"])[0].finding.rule.url
121+
== "https://rules.sonarsource.com/python/RSPEC-5659/"
122+
)
123+
assert (
124+
result.results_for_rules(["pythonsecurity:S5147"])[0].finding.rule.url
125+
== "https://rules.sonarsource.com/python/RSPEC-5147/"
126+
)
127+
128+
assert (
129+
result.results_for_rules(["javascript:S6535"])[0].finding.rule.url
130+
== "https://rules.sonarsource.com/javascript/RSPEC-6535/"
131+
)
132+
assert (
133+
result.results_for_rules(["jssecurity:S2076"])[0].finding.rule.url
134+
== "https://rules.sonarsource.com/javascript/RSPEC-2076/"
135+
)
136+
137+
assert (
138+
result.results_for_rules(["typescript:S3504"])[0].finding.rule.url
139+
== "https://rules.sonarsource.com/typescript/RSPEC-3504/"
140+
)
141+
assert (
142+
result.results_for_rules(["tssecurity:S2076"])[0].finding.rule.url
143+
== "https://rules.sonarsource.com/typescript/RSPEC-2076/"
144+
)
145+
146+
assert (
147+
result.results_for_rules(["csharpsquid:S3878"])[0].finding.rule.url
148+
== "https://rules.sonarsource.com/dotnet/RSPEC-3878/"
149+
)
150+
assert (
151+
result.results_for_rules(["roslyn.sonaranalyzer.security.cs:S5131"])[
152+
0
153+
].finding.rule.url
154+
== "https://rules.sonarsource.com/dotnet/RSPEC-5131/"
155+
)
156+
157+
assert (
158+
result.results_for_rules(["phpsecurity:S5131"])[0].finding.rule.url
159+
== "https://rules.sonarsource.com/php/RSPEC-5131/"
160+
)
161+
8162
def test_or(self, tmpdir):
9163
issues1 = {
10164
"issues": [

0 commit comments

Comments
 (0)