Skip to content

Commit c7841fe

Browse files
JAVASE-6 Restrict registration of S2259 to SQ Community Build
Restrict the loading of java:S2259 to SQCB to enable other plugins to provide an implementation S2259 for Java. Because the other plugin might declare java:S2259 as deprecated, the products might not be able to load a set of rules where java:S2259 is both implemented and deprecatd.
1 parent b050a45 commit c7841fe

File tree

4 files changed

+73
-5
lines changed

4 files changed

+73
-5
lines changed

java-symbolic-execution/java-symbolic-execution-plugin/src/main/java/org/sonar/java/se/plugin/JavaSECheckList.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@
1616
*/
1717
package org.sonar.java.se.plugin;
1818

19+
import java.util.ArrayList;
1920
import java.util.List;
21+
import java.util.Set;
22+
import java.util.function.Predicate;
2023
import org.sonar.java.se.checks.AllowXMLInclusionCheck;
2124
import org.sonar.java.se.checks.BooleanGratuitousExpressionsCheck;
2225
import org.sonar.java.se.checks.ConditionalUnreachableCodeCheck;
@@ -43,12 +46,24 @@
4346
import org.sonar.java.se.checks.XxeProcessingCheck;
4447

4548
public class JavaSECheckList {
49+
/**
50+
* A list of checks that can be overridden by other analyzers.
51+
*/
52+
public static final Set<Class<? extends SECheck>> OVERRIDABLE_CHECKS = Set.of(
53+
NullDereferenceCheck.class // S2259
54+
);
4655

4756
private JavaSECheckList(){
4857
// no need to instantiate
4958
}
5059

5160
public static List<Class<? extends SECheck>> getChecks() {
61+
return getStandaloneChecks().stream()
62+
.filter(Predicate.not(OVERRIDABLE_CHECKS::contains))
63+
.toList();
64+
}
65+
66+
public static List<Class<? extends SECheck>> getStandaloneChecks() {
5267
return List.of(
5368
// SEChecks ordered by ExplodedGraphWalker need
5469
NullDereferenceCheck.class,

java-symbolic-execution/java-symbolic-execution-plugin/src/main/java/org/sonar/java/se/plugin/JavaSECheckRegistrar.java

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,18 @@
1717
package org.sonar.java.se.plugin;
1818

1919
import java.util.ArrayList;
20+
import java.util.List;
2021
import java.util.Set;
22+
import org.sonar.api.SonarEdition;
23+
import org.sonar.api.SonarProduct;
2124
import org.sonar.api.SonarRuntime;
2225
import org.sonar.api.batch.rule.CheckFactory;
2326
import org.sonar.api.batch.rule.Checks;
2427
import org.sonar.api.ce.ComputeEngineSide;
2528
import org.sonar.api.scanner.ScannerSide;
2629
import org.sonar.api.server.ServerSide;
2730
import org.sonar.api.server.rule.RulesDefinition;
31+
import org.sonar.java.annotations.VisibleForTesting;
2832
import org.sonar.java.se.SymbolicExecutionVisitor;
2933
import org.sonar.java.se.checks.SECheck;
3034
import org.sonar.plugins.java.api.CheckRegistrar;
@@ -54,7 +58,7 @@ public void register(RegistrarContext registrarContext) {
5458

5559
@Override
5660
public void register(RegistrarContext registrarContext, CheckFactory checkFactory) {
57-
Checks<JavaCheck> checks = checkFactory.<JavaCheck>create(REPOSITORY_KEY).addAnnotatedChecks(JavaSECheckList.getChecks());
61+
Checks<JavaCheck> checks = checkFactory.<JavaCheck>create(REPOSITORY_KEY).addAnnotatedChecks(getChecks(runtime));
5862

5963
var seChecks = checks.all().stream()
6064
.filter(SECheck.class::isInstance)
@@ -71,11 +75,26 @@ public void register(RegistrarContext registrarContext, CheckFactory checkFactor
7175
public void customRulesDefinition(RulesDefinition.Context context, RulesDefinition.NewRepository javaRepository) {
7276
RuleMetadataLoader ruleMetadataLoader = new RuleMetadataLoader(RESOURCE_BASE_PATH, SONAR_WAY_PATH, runtime);
7377

74-
ruleMetadataLoader.addRulesByAnnotatedClass(javaRepository, new ArrayList<>(JavaSECheckList.getChecks()));
78+
ruleMetadataLoader.addRulesByAnnotatedClass(javaRepository, new ArrayList<>(getChecks(runtime)));
7579

7680
setTemplates(javaRepository);
7781
}
7882

83+
@VisibleForTesting
84+
static List<Class<? extends SECheck>> getChecks(SonarRuntime runtime) {
85+
if (isStandaloneSymbolicExecutionPlugin(runtime)) {
86+
return JavaSECheckList.getStandaloneChecks();
87+
}
88+
return JavaSECheckList.getChecks();
89+
}
90+
91+
@VisibleForTesting
92+
static boolean isStandaloneSymbolicExecutionPlugin(SonarRuntime runtime) {
93+
return runtime != null &&
94+
runtime.getProduct() != SonarProduct.SONARLINT &&
95+
runtime.getEdition() == SonarEdition.COMMUNITY;
96+
}
97+
7998
private static void setTemplates(RulesDefinition.NewRepository repository) {
8099
RULE_TEMPLATES_KEY.forEach(ruleKey -> repository.rule(ruleKey).setTemplate(true));
81100
}

java-symbolic-execution/java-symbolic-execution-plugin/src/test/java/org/sonar/java/se/plugin/JavaSECheckListTest.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,16 @@
2323
class JavaSECheckListTest {
2424

2525
@Test
26-
void getChecks() {
27-
assertThat(JavaSECheckList.getChecks()).isNotNull().hasSize(23);
26+
void getChecks_returns_the_list_of_checks_that_cannot_be_overridden_by_other_plugins() {
27+
assertThat(JavaSECheckList.getChecks())
28+
.hasSize(22)
29+
.doesNotContainAnyElementsOf(JavaSECheckList.OVERRIDABLE_CHECKS);
30+
}
31+
32+
@Test
33+
void getStandaloneChecks_returns_the_full_list_of_checks() {
34+
assertThat(JavaSECheckList.getStandaloneChecks())
35+
.hasSize(23);
2836
}
2937

3038
}

java-symbolic-execution/java-symbolic-execution-plugin/src/test/java/org/sonar/java/se/plugin/JavaSECheckRegistrarTest.java

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,32 @@ void register_rules() {
6666
assertThat(context.testRuleKeys).isEmpty();
6767
}
6868

69+
@Test
70+
void is_only_in_standalone_mode_in_sqcb() {
71+
var sonarQubeCloud = SonarRuntimeImpl.forSonarQube(
72+
Version.parse("8.1"),
73+
SonarQubeSide.SERVER,
74+
SonarEdition.SONARCLOUD
75+
);
76+
assertThat(JavaSECheckRegistrar.isStandaloneSymbolicExecutionPlugin(sonarQubeCloud)).isFalse();
77+
var sonarQubeCommunityBuild = SonarRuntimeImpl.forSonarQube(
78+
Version.parse("25.1"),
79+
SonarQubeSide.SERVER,
80+
SonarEdition.COMMUNITY
81+
);
82+
assertThat(JavaSECheckRegistrar.isStandaloneSymbolicExecutionPlugin(sonarQubeCommunityBuild)).isTrue();
83+
var sonarQubeServerDeveloper = SonarRuntimeImpl.forSonarQube(
84+
Version.parse("2025.1"),
85+
SonarQubeSide.SERVER,
86+
SonarEdition.DEVELOPER
87+
);
88+
assertThat(JavaSECheckRegistrar.isStandaloneSymbolicExecutionPlugin(sonarQubeServerDeveloper)).isFalse();
89+
90+
var sonarQubeForIDE = SonarRuntimeImpl.forSonarLint(Version.parse("10.22.0.81232"));
91+
assertThat(JavaSECheckRegistrar.isStandaloneSymbolicExecutionPlugin(sonarQubeForIDE)).isFalse();
92+
}
93+
94+
6995
@Test
7096
void rules_definition() {
7197
SonarRuntime sonarRuntime = SonarRuntimeImpl.forSonarQube(Version.create(10, 2), SonarQubeSide.SERVER, SonarEdition.ENTERPRISE);
@@ -85,7 +111,7 @@ void rules_definition() {
85111
assertThat(repository.name()).isEqualTo("Sonar");
86112
assertThat(repository.language()).isEqualTo("java");
87113
List<RulesDefinition.Rule> rules = repository.rules();
88-
assertThat(rules).hasSize(23);
114+
assertThat(rules).hasSize(22);
89115

90116
var activeByDefault = rules.stream()
91117
.filter(k -> !rulesNotActiveByDefault.contains(k.key()))

0 commit comments

Comments
 (0)