group=org.sonarsource.sonarqube
version=10.8
-
# End Of Life date for the version. MMF-3763. format is yyyy-MM-dd
# 6 months from the release date for non LTA versions
# 30 months from the release date for LTA versions
# No change required for patch versions
versionEOL=2025-05-27
-pluginApiVersion=10.11.0.2468
+pluginApiVersion=10.12.0.2507
description=Open source platform for continuous inspection of code quality
projectTitle=SonarQube
org.gradle.jvmargs=-Xmx2048m
import org.sonar.api.issue.impact.SoftwareQuality;
import org.sonar.api.resources.Qualifiers;
import org.sonar.api.utils.System2;
+import org.sonar.core.rule.ImpactFormatter;
import org.sonar.db.DbTester;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.component.ProjectData;
import org.sonar.server.component.ComponentFinder;
import org.sonar.server.exceptions.ForbiddenException;
import org.sonar.server.exceptions.NotFoundException;
-import org.sonar.server.issue.ImpactFormatter;
import org.sonar.server.issue.TaintChecker;
import org.sonar.server.issue.ws.pull.PullTaintActionProtobufObjectGenerator;
import org.sonar.server.tester.UserSessionRule;
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2024 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.issue;
-
-import org.sonar.api.issue.impact.Severity;
-import org.sonarqube.ws.Common;
-
-public class ImpactFormatter {
- private ImpactFormatter() {
- }
-
- public static Common.ImpactSeverity mapImpactSeverity(Severity severity) {
- return switch (severity) {
- case BLOCKER -> Common.ImpactSeverity.ImpactSeverity_BLOCKER;
- case HIGH -> Common.ImpactSeverity.HIGH;
- case MEDIUM -> Common.ImpactSeverity.MEDIUM;
- case LOW -> Common.ImpactSeverity.LOW;
- case INFO -> Common.ImpactSeverity.ImpactSeverity_INFO;
- };
- }
-}
import org.sonar.api.utils.Duration;
import org.sonar.api.utils.Durations;
import org.sonar.api.utils.Paging;
+import org.sonar.core.rule.ImpactFormatter;
import org.sonar.db.component.BranchDto;
import org.sonar.db.component.BranchType;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.user.UserDto;
import org.sonar.markdown.Markdown;
import org.sonar.server.es.Facets;
-import org.sonar.server.issue.ImpactFormatter;
import org.sonar.server.issue.TextRangeResponseFormatter;
import org.sonar.server.issue.index.IssueScope;
import org.sonar.server.issue.workflow.Transition;
import java.util.stream.Collectors;
import org.sonar.api.rules.CleanCodeAttribute;
import org.sonar.api.server.ServerSide;
+import org.sonar.core.rule.ImpactFormatter;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.issue.IssueDto;
import org.sonar.db.protobuf.DbIssues;
import org.sonar.db.rule.RuleDto;
-import org.sonar.server.issue.ImpactFormatter;
import org.sonar.server.user.UserSession;
import org.sonar.server.ws.MessageFormattingUtils;
import org.sonarqube.ws.Common;
import org.sonar.api.rules.CleanCodeAttribute;
import org.sonar.api.server.debt.DebtRemediationFunction;
import org.sonar.api.server.debt.internal.DefaultDebtRemediationFunction;
+import org.sonar.core.rule.ImpactFormatter;
import org.sonar.db.issue.ImpactDto;
import org.sonar.db.rule.DeprecatedRuleKeyDto;
import org.sonar.db.rule.RuleDescriptionSectionContextDto;
import org.sonar.db.user.UserDto;
import org.sonar.markdown.Markdown;
import org.sonar.server.common.text.MacroInterpreter;
-import org.sonar.server.issue.ImpactFormatter;
import org.sonar.server.rule.RuleDescriptionFormatter;
import org.sonar.server.rule.ws.RulesResponseFormatter.SearchResult;
import org.sonarqube.ws.Common;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.server.ServerSide;
import org.sonar.api.utils.DateUtils;
+import org.sonar.core.rule.ImpactFormatter;
import org.sonar.core.util.stream.MoreCollectors;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.rule.RuleParamDto;
import org.sonar.db.user.UserDto;
import org.sonar.server.es.Facets;
-import org.sonar.server.issue.ImpactFormatter;
import org.sonar.server.qualityprofile.ActiveRuleInheritance;
import org.sonarqube.ws.Common;
import org.sonarqube.ws.Rules;
public static Rules.Impacts mapImpacts(Map<SoftwareQuality, Severity> impacts) {
Rules.Impacts.Builder impactsBuilder = Rules.Impacts.newBuilder();
- impacts.forEach((quality, severity) ->
- impactsBuilder.addImpacts(Common.Impact.newBuilder()
- .setSoftwareQuality(Common.SoftwareQuality.valueOf(quality.name()))
- .setSeverity(ImpactFormatter.mapImpactSeverity(severity))));
+ impacts.forEach((quality, severity) -> impactsBuilder.addImpacts(Common.Impact.newBuilder()
+ .setSoftwareQuality(Common.SoftwareQuality.valueOf(quality.name()))
+ .setSeverity(ImpactFormatter.mapImpactSeverity(severity))));
return impactsBuilder.build();
}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2024 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.issue;
-
-import org.junit.jupiter.api.Test;
-import org.sonar.api.issue.impact.Severity;
-import org.sonarqube.ws.Common;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
-class ImpactFormatterTest {
-
- @Test
- void mapImpactSeverity_shouldReturnExpectedValue() {
- assertEquals(Common.ImpactSeverity.ImpactSeverity_BLOCKER, ImpactFormatter.mapImpactSeverity(Severity.BLOCKER));
- assertEquals(Common.ImpactSeverity.HIGH, ImpactFormatter.mapImpactSeverity(Severity.HIGH));
- assertEquals(Common.ImpactSeverity.MEDIUM, ImpactFormatter.mapImpactSeverity(Severity.MEDIUM));
- assertEquals(Common.ImpactSeverity.LOW, ImpactFormatter.mapImpactSeverity(Severity.LOW));
- assertEquals(Common.ImpactSeverity.ImpactSeverity_INFO, ImpactFormatter.mapImpactSeverity(Severity.INFO));
- }
-}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2024 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.core.rule;
+
+import org.sonar.api.issue.impact.Severity;
+import org.sonarqube.ws.Common;
+
+import static org.sonar.api.issue.impact.Severity.BLOCKER;
+import static org.sonar.api.issue.impact.Severity.HIGH;
+import static org.sonar.api.issue.impact.Severity.INFO;
+import static org.sonar.api.issue.impact.Severity.LOW;
+import static org.sonar.api.issue.impact.Severity.MEDIUM;
+
+public class ImpactFormatter {
+ private ImpactFormatter() {
+ }
+
+ public static Common.ImpactSeverity mapImpactSeverity(Severity severity) {
+ return switch (severity) {
+ case BLOCKER -> Common.ImpactSeverity.ImpactSeverity_BLOCKER;
+ case HIGH -> Common.ImpactSeverity.HIGH;
+ case MEDIUM -> Common.ImpactSeverity.MEDIUM;
+ case LOW -> Common.ImpactSeverity.LOW;
+ case INFO -> Common.ImpactSeverity.ImpactSeverity_INFO;
+ };
+ }
+
+ public static Severity mapImpactSeverity(Common.ImpactSeverity severity) {
+ return switch (severity) {
+ case ImpactSeverity_BLOCKER -> BLOCKER;
+ case HIGH -> HIGH;
+ case MEDIUM -> MEDIUM;
+ case LOW -> LOW;
+ case ImpactSeverity_INFO -> INFO;
+ case UNKNOWN_IMPACT_SEVERITY -> throw new UnsupportedOperationException("Impact severity not supported");
+ };
+ }
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2024 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.core.rule;
+
+import org.junit.jupiter.api.Test;
+import org.sonar.api.issue.impact.Severity;
+import org.sonarqube.ws.Common;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+class ImpactFormatterTest {
+
+ @Test
+ void mapImpactSeverity_whenMappingStandardSeverity_shouldReturnExpectedValue() {
+ assertThat(ImpactFormatter.mapImpactSeverity(Severity.BLOCKER)).isEqualTo(Common.ImpactSeverity.ImpactSeverity_BLOCKER);
+ assertThat(ImpactFormatter.mapImpactSeverity(Severity.HIGH)).isEqualTo(Common.ImpactSeverity.HIGH);
+ assertThat(ImpactFormatter.mapImpactSeverity(Severity.MEDIUM)).isEqualTo(Common.ImpactSeverity.MEDIUM);
+ assertThat(ImpactFormatter.mapImpactSeverity(Severity.LOW)).isEqualTo(Common.ImpactSeverity.LOW);
+ assertThat(ImpactFormatter.mapImpactSeverity(Severity.INFO)).isEqualTo(Common.ImpactSeverity.ImpactSeverity_INFO);
+ }
+
+ @Test
+ void mapImpactSeverity_whenMappingProtobufSeverity_shouldReturnExpectedValue() {
+ assertThat(ImpactFormatter.mapImpactSeverity(Common.ImpactSeverity.ImpactSeverity_BLOCKER)).isEqualTo(Severity.BLOCKER);
+ assertThat(ImpactFormatter.mapImpactSeverity(Common.ImpactSeverity.HIGH)).isEqualTo(Severity.HIGH);
+ assertThat(ImpactFormatter.mapImpactSeverity(Common.ImpactSeverity.MEDIUM)).isEqualTo(Severity.MEDIUM);
+ assertThat(ImpactFormatter.mapImpactSeverity(Common.ImpactSeverity.LOW)).isEqualTo(Severity.LOW);
+ assertThat(ImpactFormatter.mapImpactSeverity(Common.ImpactSeverity.ImpactSeverity_INFO)).isEqualTo(Severity.INFO);
+ assertThatThrownBy(() -> ImpactFormatter.mapImpactSeverity(Common.ImpactSeverity.UNKNOWN_IMPACT_SEVERITY))
+ .isInstanceOf(UnsupportedOperationException.class);
+ }
+}
*/
package org.sonar.api.batch.rule.internal;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.annotation.concurrent.Immutable;
import org.sonar.api.batch.rule.ActiveRule;
+import org.sonar.api.issue.impact.Severity;
+import org.sonar.api.issue.impact.SoftwareQuality;
import org.sonar.api.rule.RuleKey;
@Immutable
private final String language;
private final String templateRuleKey;
private final Map<String, String> params;
+ private final Map<SoftwareQuality, Severity> impacts;
private final long createdAt;
private final long updatedAt;
private final String qProfileKey;
this.internalKey = newActiveRule.internalKey;
this.templateRuleKey = newActiveRule.templateRuleKey;
this.ruleKey = newActiveRule.ruleKey;
- this.params = Collections.unmodifiableMap(new HashMap<>(newActiveRule.params));
+ this.params = Map.copyOf(newActiveRule.params);
+ this.impacts = Map.copyOf(newActiveRule.impacts);
this.language = newActiveRule.language;
this.createdAt = newActiveRule.createdAt;
this.updatedAt = newActiveRule.updatedAt;
this.qProfileKey = newActiveRule.qProfileKey;
- this.deprecatedKeys = Collections.unmodifiableSet(new HashSet<>(newActiveRule.deprecatedKeys));
+ this.deprecatedKeys = Set.copyOf(newActiveRule.deprecatedKeys);
}
@Override
return severity;
}
+ @Override
+ public Map<SoftwareQuality, Severity> impacts() {
+ return impacts;
+ }
+
@Override
public String language() {
return language;
*/
package org.sonar.api.batch.rule.internal;
+import java.util.EnumMap;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
import org.apache.commons.lang3.StringUtils;
+import org.sonar.api.issue.impact.SoftwareQuality;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.rule.Severity;
final RuleKey ruleKey;
final String name;
final String severity;
+ final Map<SoftwareQuality, org.sonar.api.issue.impact.Severity> impacts;
final Map<String, String> params;
final long createdAt;
final long updatedAt;
this.ruleKey = builder.ruleKey;
this.name = builder.name;
this.severity = builder.severity;
+ this.impacts = builder.impacts;
this.params = builder.params;
this.createdAt = builder.createdAt;
this.updatedAt = builder.updatedAt;
private RuleKey ruleKey;
private String name;
private String severity = Severity.defaultSeverity();
+ private final Map<SoftwareQuality, org.sonar.api.issue.impact.Severity> impacts = new EnumMap<>(SoftwareQuality.class);
private Map<String, String> params = new HashMap<>();
private long createdAt;
private long updatedAt;
return this;
}
+ public Builder setImpact(SoftwareQuality softwareQuality, org.sonar.api.issue.impact.Severity severity) {
+ impacts.put(softwareQuality, severity);
+ return this;
+ }
+
public Builder setParam(String key, @Nullable String value) {
// possible improvement : check that the param key exists in rule definition
if (value == null) {
package org.sonar.api.batch.rule.internal;
import com.google.common.collect.ImmutableMap;
+import java.util.Map;
import org.junit.Before;
import org.junit.Test;
-import org.sonar.api.batch.rule.internal.NewActiveRule;
+import org.sonar.api.issue.impact.SoftwareQuality;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.rule.Severity;
.setRuleKey(RuleKey.of("foo", "bar"))
.setName("name")
.setSeverity(org.sonar.api.rule.Severity.CRITICAL)
+ .setImpact(SoftwareQuality.MAINTAINABILITY, org.sonar.api.issue.impact.Severity.MEDIUM)
.setParam("key", "value")
.setCreatedAt(1_000L)
.setUpdatedAt(1_000L)
assertThat(rule.ruleKey).isEqualTo(RuleKey.of("foo", "bar"));
assertThat(rule.name).isEqualTo("name");
assertThat(rule.severity).isEqualTo(org.sonar.api.rule.Severity.CRITICAL);
+ assertThat(rule.impacts).containsExactlyInAnyOrderEntriesOf(Map.of(SoftwareQuality.MAINTAINABILITY, org.sonar.api.issue.impact.Severity.MEDIUM));
assertThat(rule.params).isEqualTo(ImmutableMap.of("key", "value"));
assertThat(rule.createdAt).isEqualTo(1_000L);
assertThat(rule.updatedAt).isEqualTo(1_000L);
import java.util.ArrayList;
import java.util.Collection;
+import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
return false;
}
- ScannerReport.Issue rawIssue = createReportIssue(issue, inputComponent.scannerId(), activeRule.severity());
+ ScannerReport.Issue rawIssue = createReportIssue(issue, inputComponent.scannerId(), activeRule.severity(), activeRule.impacts());
if (filters.accept(inputComponent, rawIssue)) {
write(inputComponent.scannerId(), rawIssue);
return str;
}
- private static ScannerReport.Issue createReportIssue(Issue issue, int componentRef, String activeRuleSeverity) {
+ private static ScannerReport.Issue createReportIssue(Issue issue, int componentRef, String activeRuleSeverity,
+ Map<SoftwareQuality, org.sonar.api.issue.impact.Severity> activeRuleImpacts) {
String primaryMessage = nullToEmpty(issue.primaryLocation().message());
org.sonar.api.batch.rule.Severity overriddenSeverity = issue.overriddenSeverity();
Severity severity = overriddenSeverity != null ? Severity.valueOf(overriddenSeverity.name()) : Severity.valueOf(activeRuleSeverity);
builder.setRuleKey(issue.ruleKey().rule());
builder.setMsg(primaryMessage);
builder.addAllMsgFormatting(toProtobufMessageFormattings(issue.primaryLocation().messageFormattings()));
- builder.addAllOverridenImpacts(toProtobufImpacts(issue.overridenImpacts()));
+ Map<SoftwareQuality, org.sonar.api.issue.impact.Severity> overriddenImpacts = new EnumMap<>(issue.overridenImpacts());
+ activeRuleImpacts.entrySet().forEach(e -> overriddenImpacts.putIfAbsent(e.getKey(), e.getValue()));
+ builder.addAllOverridenImpacts(toProtobufImpacts(overriddenImpacts));
+
locationBuilder.setMsg(primaryMessage);
locationBuilder.addAllMsgFormatting(toProtobufMessageFormattings(issue.primaryLocation().messageFormattings()));
import org.sonar.api.batch.rule.internal.ActiveRulesBuilder;
import org.sonar.api.batch.rule.internal.DefaultActiveRules;
import org.sonar.api.batch.rule.internal.NewActiveRule;
+import org.sonar.api.issue.impact.Severity;
+import org.sonar.api.issue.impact.SoftwareQuality;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
}
}
+ if (activeRule.getImpacts() != null) {
+ for (Map.Entry<SoftwareQuality, Severity> impact : activeRule.getImpacts().entrySet()) {
+ builder.setImpact(impact.getKey(), impact.getValue());
+ }
+ }
+
return builder.build();
}
import java.io.IOException;
import java.io.InputStream;
+import java.util.EnumMap;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import org.apache.commons.io.IOUtils;
import org.sonar.api.batch.rule.LoadedActiveRule;
import org.sonar.api.impl.utils.ScannerUtils;
+import org.sonar.api.issue.impact.Severity;
+import org.sonar.api.issue.impact.SoftwareQuality;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.utils.DateUtils;
+import org.sonar.core.rule.ImpactFormatter;
import org.sonar.scanner.http.ScannerWsClient;
+import org.sonarqube.ws.Common;
import org.sonarqube.ws.Common.Paging;
import org.sonarqube.ws.Rules;
import org.sonarqube.ws.Rules.Active;
loadedRule.setRuleKey(RuleKey.parse(r.getKey()));
loadedRule.setName(r.getName());
loadedRule.setSeverity(active.getSeverity());
+
loadedRule.setCreatedAt(DateUtils.dateToLong(DateUtils.parseDateTime(active.getCreatedAt())));
loadedRule.setUpdatedAt(DateUtils.dateToLong(DateUtils.parseDateTime(active.getUpdatedAt())));
loadedRule.setLanguage(r.getLang());
for (Param param : active.getParamsList()) {
params.put(param.getKey(), param.getValue());
}
+
loadedRule.setParams(params);
+
+ Map<SoftwareQuality, Severity> impacts = new EnumMap<>(SoftwareQuality.class);
+ for (Common.Impact impact : active.getImpacts().getImpactsList()) {
+ impacts.put(SoftwareQuality.valueOf(impact.getSoftwareQuality().name()), ImpactFormatter.mapImpactSeverity(impact.getSeverity()));
+ }
+ loadedRule.setImpacts(impacts);
+
loadedRule.setDeprecatedKeys(r.getDeprecatedKeys().getDeprecatedKeyList()
.stream()
.map(RuleKey::parse)
return loadedRules;
}
+
}
import static org.sonar.api.batch.sensor.issue.MessageFormatting.Type.CODE;
import static org.sonar.api.issue.impact.SoftwareQuality.MAINTAINABILITY;
import static org.sonar.api.issue.impact.SoftwareQuality.RELIABILITY;
+import static org.sonar.api.issue.impact.SoftwareQuality.SECURITY;
@RunWith(MockitoJUnitRunner.class)
public class IssuePublisherTest {
ScannerReport.Impact impact1 = ScannerReport.Impact.newBuilder().setSoftwareQuality(MAINTAINABILITY.name()).setSeverity("HIGH").build();
ScannerReport.Impact impact2 = ScannerReport.Impact.newBuilder().setSoftwareQuality(RELIABILITY.name()).setSeverity("LOW").build();
- assertThat(argument.getValue().getOverridenImpactsList()).containsExactly(impact1, impact2);
+ assertThat(argument.getValue().getOverridenImpactsList()).containsExactlyInAnyOrder(impact1, impact2);
}
@Test
ArgumentCaptor<ScannerReport.Issue> argument = ArgumentCaptor.forClass(ScannerReport.Issue.class);
verify(reportPublisher.getWriter()).appendComponentIssue(eq(file.scannerId()), argument.capture());
assertThat(argument.getValue().getSeverity()).isEqualTo(org.sonar.scanner.protocol.Constants.Severity.INFO);
+ assertThat(argument.getValue().getOverridenImpactsList()).isEmpty();
+ }
+
+ @Test
+ public void initAndAddIssue_whenImpactsOverriddenOnActiveRule_shouldOverrideIssue() {
+ activeRulesBuilder.addRule(new NewActiveRule.Builder()
+ .setRuleKey(NOSONAR_RULE_KEY)
+ .setSeverity(Severity.INFO)
+ .setImpact(MAINTAINABILITY, org.sonar.api.issue.impact.Severity.HIGH)
+ .setQProfileKey("qp-1")
+ .build());
+ initModuleIssues();
+
+ DefaultIssue issue = new DefaultIssue(project)
+ .at(new DefaultIssueLocation().on(file).at(file.selectLine(3)).message("Foo"))
+ .forRule(NOSONAR_RULE_KEY);
+ when(filters.accept(any(InputComponent.class), any(ScannerReport.Issue.class))).thenReturn(true);
+ moduleIssues.initAndAddIssue(issue);
+
+ ArgumentCaptor<ScannerReport.Issue> argument = ArgumentCaptor.forClass(ScannerReport.Issue.class);
+ verify(reportPublisher.getWriter()).appendComponentIssue(eq(file.scannerId()), argument.capture());
+ assertThat(argument.getValue().getSeverity()).isEqualTo(org.sonar.scanner.protocol.Constants.Severity.INFO);
+ assertThat(argument.getValue().getOverridenImpactsList()).extracting(ScannerReport.Impact::getSoftwareQuality, ScannerReport.Impact::getSeverity)
+ .containsExactly(tuple(MAINTAINABILITY.name(), org.sonar.api.issue.impact.Severity.HIGH.name()));
+ }
+
+ @Test
+ public void initAndAddIssue_whenImpactsOverriddenOnActiveRuleAndInIssue_shouldCombineOverriddenImpacts() {
+ activeRulesBuilder.addRule(new NewActiveRule.Builder()
+ .setRuleKey(NOSONAR_RULE_KEY)
+ .setSeverity(Severity.INFO)
+ .setImpact(MAINTAINABILITY, org.sonar.api.issue.impact.Severity.HIGH)
+ .setImpact(SECURITY, org.sonar.api.issue.impact.Severity.INFO)
+ .setQProfileKey("qp-1")
+ .build());
+ initModuleIssues();
+
+ DefaultIssue issue = new DefaultIssue(project)
+ .at(new DefaultIssueLocation().on(file).at(file.selectLine(3)).message("Foo"))
+ .overrideImpact(RELIABILITY, org.sonar.api.issue.impact.Severity.MEDIUM)
+ .overrideImpact(MAINTAINABILITY, org.sonar.api.issue.impact.Severity.LOW)
+ .forRule(NOSONAR_RULE_KEY);
+ when(filters.accept(any(InputComponent.class), any(ScannerReport.Issue.class))).thenReturn(true);
+ moduleIssues.initAndAddIssue(issue);
+
+ ArgumentCaptor<ScannerReport.Issue> argument = ArgumentCaptor.forClass(ScannerReport.Issue.class);
+ verify(reportPublisher.getWriter()).appendComponentIssue(eq(file.scannerId()), argument.capture());
+ assertThat(argument.getValue().getSeverity()).isEqualTo(org.sonar.scanner.protocol.Constants.Severity.INFO);
+ assertThat(argument.getValue().getOverridenImpactsList()).extracting(ScannerReport.Impact::getSoftwareQuality, ScannerReport.Impact::getSeverity)
+ .containsExactlyInAnyOrder(tuple(MAINTAINABILITY.name(), org.sonar.api.issue.impact.Severity.LOW.name()),
+ tuple(RELIABILITY.name(), org.sonar.api.issue.impact.Severity.MEDIUM.name()),
+ tuple(SECURITY.name(), org.sonar.api.issue.impact.Severity.INFO.name()));
}
@Test
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
import org.assertj.core.groups.Tuple;
import org.junit.Test;
+import org.sonar.api.batch.rule.ActiveRule;
import org.sonar.api.batch.rule.ActiveRules;
import org.sonar.api.batch.rule.LoadedActiveRule;
import org.sonar.api.batch.rule.internal.DefaultActiveRules;
+import org.sonar.api.issue.impact.Severity;
+import org.sonar.api.issue.impact.SoftwareQuality;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.utils.DateUtils;
import org.sonarqube.ws.Qualityprofiles.SearchWsResponse.QualityProfile;
LoadedActiveRule r2 = mockRule("rule2");
LoadedActiveRule r3 = mockRule("rule3");
+ r1.setImpacts(Map.of(SoftwareQuality.MAINTAINABILITY, Severity.HIGH));
+
List<LoadedActiveRule> qp1Rules = ImmutableList.of(r1, r2);
List<LoadedActiveRule> qp2Rules = ImmutableList.of(r2, r3);
List<LoadedActiveRule> qp3Rules = ImmutableList.of(r1, r3);
assertThat(activeRules.findAll()).extracting("ruleKey").containsOnly(
RuleKey.of("rule1", "rule1"), RuleKey.of("rule2", "rule2"), RuleKey.of("rule3", "rule3"));
+ Map<String, ActiveRule> activeRuleByKey = activeRules.findAll().stream().collect(Collectors.toMap(e -> e.ruleKey().rule(), e -> e));
+ assertThat(activeRuleByKey.get("rule1").impacts())
+ .containsExactlyInAnyOrderEntriesOf(Map.of(SoftwareQuality.MAINTAINABILITY, Severity.HIGH));
+
+ assertThat(activeRuleByKey.get("rule2").impacts()).isEmpty();
+ assertThat(activeRuleByKey.get("rule3").impacts()).isEmpty();
+
verify(loader).load("qp1");
verify(loader).load("qp2");
verify(loader).load("qp3");
import org.junit.Before;
import org.junit.Test;
import org.sonar.api.batch.rule.LoadedActiveRule;
+import org.sonar.api.issue.impact.SoftwareQuality;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.rule.Severity;
import org.sonar.scanner.WsTestUtil;
.filteredOn(r -> r.getRuleKey().equals(EXAMPLE_KEY))
.extracting(LoadedActiveRule::getSeverity)
.containsExactly(SEVERITY_VALUE);
+ assertThat(activeRules)
+ .filteredOn(r -> r.getRuleKey().equals(EXAMPLE_KEY))
+ .extracting(LoadedActiveRule::getImpacts)
+ .containsExactlyInAnyOrder(Map.of(SoftwareQuality.MAINTAINABILITY, org.sonar.api.issue.impact.Severity.HIGH));
WsTestUtil.verifyCall(wsClient, urlOfPage(1));
WsTestUtil.verifyCall(wsClient, urlOfPage(2));
if (EXAMPLE_KEY.equals(key)) {
activeBuilder.addParams(Rules.Active.Param.newBuilder().setKey(FORMAT_KEY).setValue(FORMAT_VALUE));
activeBuilder.setSeverity(SEVERITY_VALUE);
+ activeBuilder.setImpacts(Rules.Impacts.newBuilder().addImpacts(Common.Impact.newBuilder()
+ .setSoftwareQuality(Common.SoftwareQuality.MAINTAINABILITY)
+ .setSeverity(Common.ImpactSeverity.HIGH).build()).build());
}
ActiveList activeList = Rules.ActiveList.newBuilder().addActiveList(activeBuilder).build();
actives.putAllActives(Map.of(key.toString(), activeList));