Skip to content

Commit 0b2b188

Browse files
ghislainpiotsonartech
authored andcommitted
SONARPY-2894 Ensure custom rules repositories reuse the same PythonCheck instances to avoid a change in behavior (#242)
GitOrigin-RevId: 6973c21af2bdf75010e412e6f6722c3d079b2680
1 parent 4ff6866 commit 0b2b188

2 files changed

Lines changed: 34 additions & 16 deletions

File tree

python-commons/src/main/java/org/sonar/plugins/python/PythonChecks.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ public class PythonChecks {
3636

3737
private final CheckFactory checkFactory;
3838
private final Map<String, RepositoryChecksInfo> sonarPythonRepositoriesChecks;
39-
private final Map<String, RepositoryChecksInfo> noSonarPythonRepositoriesChecks;
39+
private final Map<String, Checks<PythonCheck>> noSonarPythonRepositoriesChecks;
4040
private final Map<Class<? extends PythonCheck>, RuleKey> ruleKeys;
4141

4242
PythonChecks(CheckFactory checkFactory) {
@@ -57,7 +57,7 @@ public PythonChecks addChecks(String repositoryKey, Iterable<Class<?>> checkClas
5757
if (SONAR_PYTHON_REPOSITORIES.contains(repositoryKey)) {
5858
sonarPythonRepositoriesChecks.put(repositoryChecksInfo.repositoryKey, repositoryChecksInfo);
5959
} else {
60-
noSonarPythonRepositoriesChecks.put(repositoryChecksInfo.repositoryKey, repositoryChecksInfo);
60+
noSonarPythonRepositoriesChecks.put(repositoryChecksInfo.repositoryKey, createChecks(repositoryChecksInfo));
6161
}
6262
return this;
6363
}
@@ -78,11 +78,11 @@ public synchronized List<PythonCheck> sonarPythonChecks() {
7878
}
7979

8080
public synchronized Map<String, List<PythonCheck>> noSonarPythonChecks() {
81-
return noSonarPythonRepositoriesChecks.values()
81+
return noSonarPythonRepositoriesChecks.entrySet()
8282
.stream()
83-
.collect(Collectors.toMap(
84-
RepositoryChecksInfo::repositoryKey,
85-
repositoryChecksInfo -> createChecks(repositoryChecksInfo).all().stream().toList()));
83+
.collect(Collectors.toMap(Map.Entry::getKey,
84+
entry -> entry.getValue().all().stream().toList())
85+
);
8686
}
8787

8888
public List<EndOfAnalysis> sonarPythonEndOfAnalyses() {

python-commons/src/test/java/org/sonar/plugins/python/PythonSensorTest.java

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import java.util.Iterator;
3232
import java.util.List;
3333
import java.util.Set;
34+
import java.util.concurrent.atomic.AtomicInteger;
3435
import java.util.function.Function;
3536
import javax.annotation.Nullable;
3637
import org.junit.jupiter.api.BeforeEach;
@@ -141,6 +142,7 @@ class PythonSensorTest {
141142
private static final String CUSTOM_REPOSITORY_KEY = "customKey";
142143
private static final String CUSTOM_RULE_KEY = "key";
143144
private static final String RULE_CRASHING_ON_SCAN_KEY = "key2";
145+
private static final String END_OF_ANALYSIS_KEY = "key3";
144146

145147
private static final Version SONARLINT_DETECTABLE_VERSION = Version.create(6, 0);
146148

@@ -154,7 +156,7 @@ public String repositoryKey() {
154156

155157
@Override
156158
public List<Class<?>> checkClasses() {
157-
return List.of(MyCustomRule.class, RuleCrashingOnRegularScan.class);
159+
return List.of(MyCustomRule.class, RuleCrashingOnRegularScan.class, AccumulatingForEndOfAnalysis.class);
158160
}
159161
}};
160162
private static Path workDir;
@@ -164,9 +166,7 @@ public List<Class<?>> checkClasses() {
164166
name = "name",
165167
description = "desc",
166168
tags = {"bug"})
167-
public static class MyCustomRule implements PythonCheck, EndOfAnalysis {
168-
169-
private static final Logger LOG = LoggerFactory.getLogger(MyCustomRule.class);
169+
public static class MyCustomRule implements PythonCheck {
170170

171171
@RuleProperty(
172172
key = "customParam",
@@ -184,10 +184,6 @@ public boolean scanWithoutParsing(PythonInputFileContext inputFile) {
184184
return false;
185185
}
186186

187-
@Override
188-
public void endOfAnalysis(CacheContext cacheContext) {
189-
LOG.trace("End of analysis called!");
190-
}
191187
}
192188

193189
@Rule(
@@ -208,6 +204,27 @@ public boolean scanWithoutParsing(PythonInputFileContext inputFile) {
208204
}
209205
}
210206

207+
@Rule(key = END_OF_ANALYSIS_KEY)
208+
public static class AccumulatingForEndOfAnalysis implements PythonCheck, EndOfAnalysis {
209+
private static final Logger LOG = LoggerFactory.getLogger(AccumulatingForEndOfAnalysis.class);
210+
private final AtomicInteger scanFileCount = new AtomicInteger(0);
211+
212+
@Override
213+
public void scanFile(PythonVisitorContext visitorContext) {
214+
scanFileCount.incrementAndGet();
215+
}
216+
217+
@Override
218+
public boolean scanWithoutParsing(PythonInputFileContext inputFile) {
219+
return false;
220+
}
221+
222+
@Override
223+
public void endOfAnalysis(CacheContext cacheContext) {
224+
LOG.trace("End of analysis called with {} files", scanFileCount.get());
225+
}
226+
}
227+
211228
private final File baseDir = new File("src/test/resources/org/sonar/plugins/python/sensor").getAbsoluteFile();
212229

213230
private SensorContextTester context;
@@ -506,15 +523,16 @@ void not_relying_on_stubs_for_project_under_analysis_2() {
506523

507524
@Test
508525
void end_of_analysis_called() {
526+
inputFile(FILE_1);
509527
inputFile(FILE_2);
510528
activeRules = new ActiveRulesBuilder()
511529
.addRule(new NewActiveRule.Builder()
512-
.setRuleKey(RuleKey.of(CUSTOM_REPOSITORY_KEY, CUSTOM_RULE_KEY))
530+
.setRuleKey(RuleKey.of(CUSTOM_REPOSITORY_KEY, END_OF_ANALYSIS_KEY))
513531
.build())
514532
.build();
515533
sensor().execute(context);
516534

517-
assertThat(traceLogTester.logs(Level.TRACE)).containsExactly("End of analysis called!");
535+
assertThat(traceLogTester.logs(Level.TRACE)).containsExactly("End of analysis called with 2 files");
518536
}
519537

520538
@Test

0 commit comments

Comments
 (0)