Skip to content

Commit 201ae0c

Browse files
SONARPY-910 Extend AbstractRegexCheck to consider all relevant methods from re package (#959)
* SONARPY-910 Extend AbstractRegexCheck to consider all relevant methods from re package * Further test simplification and improvement
1 parent 8cb734e commit 201ae0c

File tree

4 files changed

+24
-24
lines changed

4 files changed

+24
-24
lines changed

python-checks/src/main/java/org/sonar/python/checks/regex/AbstractRegexCheck.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
*/
2020
package org.sonar.python.checks.regex;
2121

22-
import java.util.Collections;
22+
import java.util.Arrays;
2323
import java.util.HashSet;
2424
import java.util.Optional;
2525
import java.util.Set;
@@ -37,7 +37,8 @@
3737

3838
public abstract class AbstractRegexCheck extends PythonSubscriptionCheck {
3939

40-
private static final Set<String> REGEX_FUNCTIONS = new HashSet<>(Collections.singletonList("re.sub"));
40+
private static final Set<String> REGEX_FUNCTIONS = new HashSet<>(Arrays.asList("re.sub", "re.subn", "re.compile", "re.search", "re.match",
41+
"re.fullmatch", "re.split", "re.findall", "re.finditer"));
4142
protected RegexContext regexContext;
4243

4344
protected Set<String> lookedUpFunctionNames() {

python-checks/src/test/java/org/sonar/python/checks/regex/AbstractRegexCheckTest.java

Lines changed: 9 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,13 @@
2222
import java.io.File;
2323
import java.util.ArrayList;
2424
import java.util.Arrays;
25-
import java.util.Collections;
2625
import java.util.List;
2726
import org.junit.Test;
28-
import org.sonar.plugins.python.api.PythonCheck;
29-
import org.sonar.plugins.python.api.PythonSubscriptionCheck;
3027
import org.sonar.plugins.python.api.PythonVisitorContext;
3128
import org.sonar.plugins.python.api.tree.CallExpression;
3229
import org.sonar.python.SubscriptionVisitor;
3330
import org.sonar.python.TestPythonVisitorRunner;
31+
import org.sonar.python.checks.utils.PythonCheckVerifier;
3432
import org.sonarsource.analyzer.commons.regex.RegexParseResult;
3533

3634
import static org.assertj.core.api.Assertions.assertThat;
@@ -39,33 +37,23 @@ public class AbstractRegexCheckTest {
3937

4038
private static final File FILE = new File("src/test/resources/checks/regex/abstractRegexCheck.py");
4139

42-
private static PythonVisitorContext fileContext(File file) {
43-
return TestPythonVisitorRunner.createContext(file);
44-
}
45-
46-
private static List<PythonCheck.PreciseIssue> scanFileForIssues(PythonVisitorContext fileContext, List<PythonSubscriptionCheck> checks) {
47-
checks.forEach(c -> c.scanFile(fileContext));
48-
SubscriptionVisitor.analyze(checks, fileContext);
49-
return fileContext.getIssues();
50-
}
51-
5240
@Test
5341
public void test_regex_is_visited() {
5442
Check check = new Check();
55-
List<PythonCheck.PreciseIssue> issues = scanFileForIssues(fileContext(FILE), Collections.singletonList(check));
56-
assertThat(check.receivedRegexParseResults).hasSize(1);
57-
assertThat(issues).hasSize(1);
43+
PythonCheckVerifier.verify(FILE.getAbsolutePath(), check);
44+
assertThat(check.receivedRegexParseResults).hasSize(10);
5845
}
5946

6047
@Test
6148
public void test_regex_parse_result_is_retrieved_from_cache_in_context() {
62-
PythonVisitorContext fileContext = fileContext(FILE);
63-
49+
PythonVisitorContext fileContext = TestPythonVisitorRunner.createContext(FILE);
6450
Check checkOne = new Check();
6551
Check checkTwo = new Check();
66-
scanFileForIssues(fileContext, Arrays.asList(checkOne, checkTwo));
67-
68-
assertThat(checkOne.receivedRegexParseResults.get(0)).isSameAs(checkTwo.receivedRegexParseResults.get(0));
52+
SubscriptionVisitor.analyze(Arrays.asList(checkOne, checkTwo), fileContext);
53+
assertThat(checkOne.receivedRegexParseResults).hasSameSizeAs(checkTwo.receivedRegexParseResults);
54+
for (int i = 0; i < checkOne.receivedRegexParseResults.size(); i++) {
55+
assertThat(checkOne.receivedRegexParseResults.get(i)).isSameAs(checkTwo.receivedRegexParseResults.get(i));
56+
}
6957
}
7058

7159
private static class Check extends AbstractRegexCheck {

python-checks/src/test/resources/checks/regex/abstractRegexCheck.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,16 @@
11
import re
22

3-
re.sub(r'.*', "x", "a")
3+
re.sub(r'.*', "x", "a") # Noncompliant {{MESSAGE}}
4+
re.sub(repl='x', pattern=r'.*', string='yyyy') # Noncompliant
5+
re.subn(r'.*', "x", "a") # Noncompliant
6+
re.compile(r'.*') # Noncompliant
7+
re.search(r'.*', "foo") # Noncompliant
8+
re.match(r'.*', "foo") # Noncompliant
9+
re.fullmatch(r'.*', "foo") # Noncompliant
10+
re.split(r'.*', "foo") # Noncompliant
11+
re.findall(r'.*', "foo") # Noncompliant
12+
re.finditer(r'.*', "foo") # Noncompliant
13+
414
re.sub('.*', "x", "a") # We only look at raw strings for now
515
re.sub(r'.*' r'.*', "x", "a") # We do not look at concats for now
616
re.sub() # Required arguments not provided

python-checks/src/test/resources/checks/regex/stringReplaceCheck.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ def compliant():
3636
changed = re.sub(r"x+", "It's", input)
3737
changed = re.sub(r"[\\]", "It's", input)
3838
changed = re.sub(r"", "It's", input)
39+
changed = re.match(r"Bob is", input)
3940

4041
def coverage(input):
4142
re.match(r"Bob is", input)

0 commit comments

Comments
 (0)