]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-20169 Create custom rules with default impacts
authorLéo Geoffroy <leo.geoffroy@sonarsource.com>
Tue, 15 Aug 2023 08:58:11 +0000 (10:58 +0200)
committersonartech <sonartech@sonarsource.com>
Fri, 18 Aug 2023 20:02:49 +0000 (20:02 +0000)
server/sonar-webserver-webapi/src/it/java/org/sonar/server/rule/RuleCreatorIT.java
server/sonar-webserver-webapi/src/it/java/org/sonar/server/rule/RuleUpdaterIT.java
server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/RuleCreator.java
server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/RuleUpdater.java

index 5cc1717306c5341c68cb90db411e2a7e2da20f50..6956212b195a25332a74f737437b847dfcf53542 100644 (file)
@@ -27,12 +27,16 @@ import java.util.Date;
 import java.util.List;
 import java.util.concurrent.atomic.AtomicReference;
 import org.assertj.core.api.Fail;
+import org.assertj.core.groups.Tuple;
 import org.junit.Rule;
 import org.junit.Test;
 import org.sonar.api.impl.utils.TestSystem2;
+import org.sonar.api.issue.impact.SoftwareQuality;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.api.rule.RuleStatus;
 import org.sonar.api.rule.Severity;
+import org.sonar.api.rules.CleanCodeAttribute;
+import org.sonar.api.rules.RuleType;
 import org.sonar.api.server.debt.DebtRemediationFunction;
 import org.sonar.api.utils.System2;
 import org.sonar.core.util.SequenceUuidFactory;
@@ -96,13 +100,13 @@ public class RuleCreatorIT {
     assertThat(rule.getTemplateUuid()).isEqualTo(templateRule.getUuid());
     assertThat(rule.getName()).isEqualTo("My custom");
     assertThat(rule.getDefaultRuleDescriptionSection().getContent()).isEqualTo("Some description");
+    assertThat(rule.getEnumType()).isEqualTo(RuleType.CODE_SMELL);
+    assertCleanCodeInformation(rule);
     assertThat(rule.getSeverityString()).isEqualTo("MAJOR");
     assertThat(rule.getStatus()).isEqualTo(RuleStatus.READY);
     assertThat(rule.getLanguage()).isEqualTo("java");
     assertThat(rule.getConfigKey()).isEqualTo("S001");
-    assertThat(rule.getDefRemediationFunction()).isEqualTo("LINEAR_OFFSET");
-    assertThat(rule.getDefRemediationGapMultiplier()).isEqualTo("1h");
-    assertThat(rule.getDefRemediationBaseEffort()).isEqualTo("5min");
+    assertDefRemediation(rule);
     assertThat(rule.getGapDescription()).isEqualTo("desc");
     assertThat(rule.getTags()).containsOnly("usertag1", "usertag2");
     assertThat(rule.getSystemTags()).containsOnly("tag1", "tag4");
@@ -124,6 +128,18 @@ public class RuleCreatorIT {
     assertThat(ruleIndex.search(new RuleQuery(), new SearchOptions()).getUuids()).containsOnly(rule.getUuid(), templateRule.getUuid());
   }
 
+  private static void assertCleanCodeInformation(RuleDto rule) {
+    assertThat(rule.getCleanCodeAttribute()).isEqualTo(CleanCodeAttribute.CONVENTIONAL);
+    assertThat(rule.getDefaultImpacts()).extracting(i -> i.getSoftwareQuality(), i -> i.getSeverity())
+      .containsExactly(Tuple.tuple(SoftwareQuality.MAINTAINABILITY, org.sonar.api.issue.impact.Severity.MEDIUM));
+  }
+
+  private static void assertDefRemediation(RuleDto rule) {
+    assertThat(rule.getDefRemediationFunction()).isEqualTo("LINEAR_OFFSET");
+    assertThat(rule.getDefRemediationGapMultiplier()).isEqualTo("1h");
+    assertThat(rule.getDefRemediationBaseEffort()).isEqualTo("5min");
+  }
+
   @Test
   public void create_custom_rule_with_empty_parameter_value() {
     // insert template rule
index 587fb83ac2a99effc09520c08d61d0017965a293..46de88eb5309909521e414fca38a0960989923ae 100644 (file)
@@ -29,15 +29,19 @@ import java.util.stream.Collectors;
 import org.junit.Rule;
 import org.junit.Test;
 import org.sonar.api.impl.utils.TestSystem2;
+import org.sonar.api.issue.impact.SoftwareQuality;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.api.rule.RuleStatus;
 import org.sonar.api.rule.Severity;
+import org.sonar.api.rules.RuleType;
 import org.sonar.api.server.debt.DebtRemediationFunction;
 import org.sonar.api.server.debt.internal.DefaultDebtRemediationFunction;
 import org.sonar.api.utils.System2;
 import org.sonar.core.util.UuidFactoryFast;
+import org.sonar.core.util.Uuids;
 import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
+import org.sonar.db.issue.ImpactDto;
 import org.sonar.db.qualityprofile.ActiveRuleDto;
 import org.sonar.db.qualityprofile.ActiveRuleKey;
 import org.sonar.db.qualityprofile.ActiveRuleParamDto;
@@ -56,6 +60,7 @@ import org.sonar.server.tester.UserSessionRule;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.assertj.core.api.Assertions.tuple;
 import static org.sonar.api.rule.Severity.CRITICAL;
 import static org.sonar.db.rule.RuleTesting.newCustomRule;
 import static org.sonar.db.rule.RuleTesting.newRule;
@@ -336,6 +341,10 @@ public class RuleUpdaterIT {
 
     RuleDto customRule = newCustomRule(templateRule, "Old description")
       .setName("Old name")
+      .setType(RuleType.CODE_SMELL)
+      .replaceAllDefaultImpacts(List.of(new ImpactDto().setUuid(Uuids.createFast())
+        .setSoftwareQuality(SoftwareQuality.MAINTAINABILITY)
+        .setSeverity(org.sonar.api.issue.impact.Severity.LOW)))
       .setSeverity(Severity.MINOR)
       .setStatus(RuleStatus.BETA);
     db.rules().insert(customRule);
@@ -358,6 +367,8 @@ public class RuleUpdaterIT {
     assertThat(customRuleReloaded).isNotNull();
     assertThat(customRuleReloaded.getName()).isEqualTo("New name");
     assertThat(customRuleReloaded.getDefaultRuleDescriptionSection().getContent()).isEqualTo("New description");
+    assertThat(customRuleReloaded.getDefaultImpacts()).extracting(ImpactDto::getSoftwareQuality, ImpactDto::getSeverity)
+      .containsExactlyInAnyOrder(tuple(SoftwareQuality.MAINTAINABILITY, org.sonar.api.issue.impact.Severity.MEDIUM));
     assertThat(customRuleReloaded.getSeverityString()).isEqualTo("MAJOR");
     assertThat(customRuleReloaded.getStatus()).isEqualTo(RuleStatus.READY);
 
index cb1150445935cc2724c1bffa8a209f6165263d3b..d0cd5bca426a8025173f39cb66e5ad318c00a4a5 100644 (file)
@@ -29,15 +29,20 @@ import java.util.Set;
 import java.util.function.Function;
 import java.util.stream.Collectors;
 import javax.annotation.Nullable;
+import org.sonar.api.issue.impact.SoftwareQuality;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.api.rule.RuleStatus;
 import org.sonar.api.rule.Severity;
+import org.sonar.api.rules.CleanCodeAttribute;
+import org.sonar.api.rules.RuleType;
 import org.sonar.api.server.ServerSide;
 import org.sonar.api.server.rule.RuleParamType;
+import org.sonar.api.server.rule.internal.ImpactMapper;
 import org.sonar.api.utils.System2;
 import org.sonar.core.util.UuidFactory;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
+import org.sonar.db.issue.ImpactDto;
 import org.sonar.db.rule.RuleDescriptionSectionDto;
 import org.sonar.db.rule.RuleDto;
 import org.sonar.db.rule.RuleDto.Format;
@@ -183,6 +188,11 @@ public class RuleCreator {
 
   private String createCustomRule(RuleKey ruleKey, NewCustomRule newRule, RuleDto templateRuleDto, DbSession dbSession) {
     RuleDescriptionSectionDto ruleDescriptionSectionDto = createDefaultRuleDescriptionSection(uuidFactory.create(), requireNonNull(newRule.markdownDescription()));
+    int type = newRule.type() == null ? templateRuleDto.getType() : newRule.type().getDbConstant();
+    String severity = newRule.severity();
+    SoftwareQuality softwareQuality = ImpactMapper.convertToSoftwareQuality(RuleType.valueOf(type));
+    org.sonar.api.issue.impact.Severity impactSeverity = ImpactMapper.convertToImpactSeverity(severity);
+
     RuleDto ruleDto = new RuleDto()
       .setUuid(uuidFactory.create())
       .setRuleKey(ruleKey)
@@ -190,9 +200,11 @@ public class RuleCreator {
       .setTemplateUuid(templateRuleDto.getUuid())
       .setConfigKey(templateRuleDto.getConfigKey())
       .setName(newRule.name())
-      .setSeverity(newRule.severity())
+      .setSeverity(severity)
       .setStatus(newRule.status())
-      .setType(newRule.type() == null ? templateRuleDto.getType() : newRule.type().getDbConstant())
+      .setType(type)
+      .addDefaultImpact(new ImpactDto().setUuid(uuidFactory.create()).setSoftwareQuality(softwareQuality).setSeverity(impactSeverity))
+      .setCleanCodeAttribute(CleanCodeAttribute.CONVENTIONAL)
       .setLanguage(templateRuleDto.getLanguage())
       .setDefRemediationFunction(templateRuleDto.getDefRemediationFunction())
       .setDefRemediationGapMultiplier(templateRuleDto.getDefRemediationGapMultiplier())
index 98a9eadaa69b7e3644b393511a6d5f698af3f6e2..1d0d4a14464a2b146dd7deb5142eaf13c6270393 100644 (file)
@@ -36,6 +36,7 @@ import org.sonar.api.rule.RuleStatus;
 import org.sonar.api.rule.Severity;
 import org.sonar.api.server.ServerSide;
 import org.sonar.api.server.debt.DebtRemediationFunction;
+import org.sonar.api.server.rule.internal.ImpactMapper;
 import org.sonar.api.utils.System2;
 import org.sonar.core.util.UuidFactory;
 import org.sonar.db.DbClient;
@@ -127,6 +128,14 @@ public class RuleUpdater {
     }
   }
 
+  private static void updateImpactSeverity(RuleDto rule, String severity) {
+    rule.getDefaultImpacts()
+      .stream()
+      .filter(i -> i.getSoftwareQuality().equals(ImpactMapper.convertToSoftwareQuality(rule.getEnumType())))
+      .findFirst()
+      .ifPresent(i -> i.setSeverity(ImpactMapper.convertToImpactSeverity(severity)));
+  }
+
   private static void updateName(RuleUpdate update, RuleDto rule) {
     String name = update.getName();
     if (isNullOrEmpty(name)) {
@@ -151,6 +160,7 @@ public class RuleUpdater {
       throw new IllegalArgumentException("The severity is invalid");
     }
     rule.setSeverity(severity);
+    updateImpactSeverity(rule, severity);
   }
 
   private static void updateStatus(RuleUpdate update, RuleDto rule) {