From b669aac1e3848a1e4c945c0ab09591a6171a8b5a Mon Sep 17 00:00:00 2001 From: Julien Lancelot Date: Tue, 8 Mar 2016 21:47:03 +0100 Subject: [PATCH] SONAR-7453 Rename rules remediation function fields in API --- .../sonar/xoo/rule/XooRulesDefinition.java | 6 +- .../xoo/rule/XooRulesDefinitionTest.java | 6 +- .../computation/issue/DebtCalculator.java | 10 ++- .../sonar/server/debt/DebtModelBackup.java | 4 +- .../rule/CommonRuleDefinitionsImpl.java | 12 +-- .../org/sonar/server/rule/RegisterRules.java | 8 +- .../org/sonar/server/rule/RuleOperations.java | 7 +- .../org/sonar/server/rule/RuleUpdater.java | 8 +- .../org/sonar/server/rule/ws/RuleMapper.java | 53 ++++-------- .../DeprecatedRulesDefinitionLoaderTest.java | 11 ++- .../server/rule/RegisterRulesMediumTest.java | 2 +- .../sonar/server/rule/RegisterRulesTest.java | 4 +- .../sonar/server/rule/RuleOperationsTest.java | 2 +- .../server/debt/DebtRemediationFunction.java | 80 ++++++++++++++----- .../DefaultDebtRemediationFunction.java | 53 ++++++++---- .../rule/DefaultDebtRemediationFunctions.java | 19 +++-- .../api/server/rule/RulesDefinition.java | 57 ++++++++----- .../server/rule/RulesDefinitionXmlLoader.java | 59 +++++++------- .../DefaultDebtRemediationFunctionTest.java | 32 ++++---- .../api/server/rule/RulesDefinitionTest.java | 8 +- .../rule/RulesDefinitionXmlLoaderTest.java | 63 ++++++++++----- 21 files changed, 298 insertions(+), 206 deletions(-) diff --git a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/XooRulesDefinition.java b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/XooRulesDefinition.java index f93a5eaba5b..fd0bb0aa9ee 100644 --- a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/XooRulesDefinition.java +++ b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/XooRulesDefinition.java @@ -50,7 +50,7 @@ public class XooRulesDefinition implements RulesDefinition { .setHtmlDescription("Generate an issue on each line of a file. It requires the metric \"lines\"."); oneIssuePerLine .setDebtRemediationFunction(hasTag.debtRemediationFunctions().linear("1min")) - .setEffortToFixDescription("It takes about 1 minute to an experienced software craftsman to remove a line of code"); + .setGapDescription("It takes about 1 minute to an experienced software craftsman to remove a line of code"); repo.done(); } @@ -80,7 +80,7 @@ public class XooRulesDefinition implements RulesDefinition { .setHtmlDescription("Generate an issue on each line of a file. It requires the metric \"lines\"."); oneIssuePerLine .setDebtRemediationFunction(hasTag.debtRemediationFunctions().linear("1min")) - .setEffortToFixDescription("It takes about 1 minute to an experienced software craftsman to remove a line of code"); + .setGapDescription("It takes about 1 minute to an experienced software craftsman to remove a line of code"); repo.createRule(OneIssueOnDirPerFileSensor.RULE_KEY).setName("One Issue On Dir Per File") .setHtmlDescription("Generate issues on directories"); @@ -97,7 +97,7 @@ public class XooRulesDefinition implements RulesDefinition { .setHtmlDescription("Generate an issue on each module"); oneIssuePerModule .setDebtRemediationFunction(hasTag.debtRemediationFunctions().linearWithOffset("25min", "1h")) - .setEffortToFixDescription("A certified architect will need roughly half an hour to start working on removal of modules, " + + .setGapDescription("A certified architect will need roughly half an hour to start working on removal of modules, " + "then it's about one hour per module."); repo.createRule(OneBlockerIssuePerFileSensor.RULE_KEY).setName("One Blocker Issue Per File") diff --git a/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/rule/XooRulesDefinitionTest.java b/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/rule/XooRulesDefinitionTest.java index 985bf936dff..9da06081645 100644 --- a/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/rule/XooRulesDefinitionTest.java +++ b/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/rule/XooRulesDefinitionTest.java @@ -47,9 +47,9 @@ public class XooRulesDefinitionTest { RulesDefinition.Rule rule = repo.rule(OneIssuePerLineSensor.RULE_KEY); assertThat(rule.name()).isNotEmpty(); assertThat(rule.debtRemediationFunction().type()).isEqualTo(DebtRemediationFunction.Type.LINEAR); - assertThat(rule.debtRemediationFunction().coefficient()).isEqualTo("1min"); - assertThat(rule.debtRemediationFunction().offset()).isNull(); - assertThat(rule.effortToFixDescription()).isNotEmpty(); + assertThat(rule.debtRemediationFunction().gapMultiplier()).isEqualTo("1min"); + assertThat(rule.debtRemediationFunction().baseEffort()).isNull(); + assertThat(rule.gapDescription()).isNotEmpty(); } @Test diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/issue/DebtCalculator.java b/server/sonar-server/src/main/java/org/sonar/server/computation/issue/DebtCalculator.java index beb4d1ad875..f1cc57198fe 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/issue/DebtCalculator.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/issue/DebtCalculator.java @@ -46,14 +46,16 @@ public class DebtCalculator { verifyEffortToFix(issue, fn); Duration debt = Duration.create(0); - if (fn.type().usesCoefficient() && !Strings.isNullOrEmpty(fn.coefficient())) { + String gapMultiplier =fn.gapMultiplier(); + if (fn.type().usesGapMultiplier() && !Strings.isNullOrEmpty(gapMultiplier)) { int effortToFixValue = Objects.firstNonNull(issue.effortToFix(), 1).intValue(); // TODO convert to Duration directly in Rule#remediationFunction -> better performance + error handling - debt = durations.decode(fn.coefficient()).multiply(effortToFixValue); + debt = durations.decode(gapMultiplier).multiply(effortToFixValue); } - if (fn.type().usesOffset() && !Strings.isNullOrEmpty(fn.offset())) { + String baseEffort= fn.baseEffort(); + if (fn.type().usesBaseEffort() && !Strings.isNullOrEmpty(baseEffort)) { // TODO convert to Duration directly in Rule#remediationFunction -> better performance + error handling - debt = debt.add(durations.decode(fn.offset())); + debt = debt.add(durations.decode(baseEffort)); } return debt; } diff --git a/server/sonar-server/src/main/java/org/sonar/server/debt/DebtModelBackup.java b/server/sonar-server/src/main/java/org/sonar/server/debt/DebtModelBackup.java index abb8f896c03..3936627a40c 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/debt/DebtModelBackup.java +++ b/server/sonar-server/src/main/java/org/sonar/server/debt/DebtModelBackup.java @@ -150,8 +150,8 @@ public class DebtModelBackup { boolean hasDebtDefinition = remediationFunction != null; rule.setDefaultRemediationFunction(hasDebtDefinition ? remediationFunction.type().name() : null); - rule.setDefaultRemediationGapMultiplier(hasDebtDefinition ? remediationFunction.coefficient() : null); - rule.setDefaultRemediationBaseEffort(hasDebtDefinition ? remediationFunction.offset() : null); + rule.setDefaultRemediationGapMultiplier(hasDebtDefinition ? remediationFunction.gapMultiplier() : null); + rule.setDefaultRemediationBaseEffort(hasDebtDefinition ? remediationFunction.baseEffort() : null); } // Reset overridden debt definitions diff --git a/server/sonar-server/src/main/java/org/sonar/server/rule/CommonRuleDefinitionsImpl.java b/server/sonar-server/src/main/java/org/sonar/server/rule/CommonRuleDefinitionsImpl.java index 5c957918db1..15b2ec68bcf 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/rule/CommonRuleDefinitionsImpl.java +++ b/server/sonar-server/src/main/java/org/sonar/server/rule/CommonRuleDefinitionsImpl.java @@ -63,7 +63,7 @@ public class CommonRuleDefinitionsImpl implements CommonRuleDefinitions { .setHtmlDescription("An issue is created on a file as soon as the branch coverage on this file is less than the required threshold." + "It gives the number of branches to be covered in order to reach the required threshold.") .setDebtRemediationFunction(rule.debtRemediationFunctions().linear("5min")) - .setEffortToFixDescription("number of uncovered conditions") + .setGapDescription("number of uncovered conditions") .setSeverity(Severity.MAJOR); rule.createParam(CommonRuleKeys.INSUFFICIENT_BRANCH_COVERAGE_PROPERTY) .setName("The minimum required branch coverage ratio") @@ -78,7 +78,7 @@ public class CommonRuleDefinitionsImpl implements CommonRuleDefinitions { .setHtmlDescription("An issue is created on a file as soon as the line coverage on this file is less than the required threshold. " + "It gives the number of lines to be covered in order to reach the required threshold.") .setDebtRemediationFunction(rule.debtRemediationFunctions().linear("2min")) - .setEffortToFixDescription("number of lines under the coverage threshold") + .setGapDescription("number of lines under the coverage threshold") .setSeverity(Severity.MAJOR); rule.createParam(CommonRuleKeys.INSUFFICIENT_LINE_COVERAGE_PROPERTY) .setName("The minimum required line coverage ratio") @@ -93,7 +93,7 @@ public class CommonRuleDefinitionsImpl implements CommonRuleDefinitions { .setHtmlDescription("An issue is created on a file as soon as the density of comment lines on this file is less than the required threshold. " + "The number of comment lines to be written in order to reach the required threshold is provided by each issue message.") .setDebtRemediationFunction(rule.debtRemediationFunctions().linear("2min")) - .setEffortToFixDescription("number of lines required to meet minimum density") + .setGapDescription("number of lines required to meet minimum density") .setSeverity(Severity.MAJOR); rule.createParam(CommonRuleKeys.INSUFFICIENT_COMMENT_DENSITY_PROPERTY) .setName("The minimum required comment density") @@ -107,7 +107,7 @@ public class CommonRuleDefinitionsImpl implements CommonRuleDefinitions { .addTags("pitfall") .setHtmlDescription("An issue is created on a file as soon as there is at least one block of duplicated code on this file") .setDebtRemediationFunction(rule.debtRemediationFunctions().linearWithOffset("10min", "10min")) - .setEffortToFixDescription("number of duplicate blocks") + .setGapDescription("number of duplicate blocks") .setSeverity(Severity.MAJOR); } @@ -119,7 +119,7 @@ public class CommonRuleDefinitionsImpl implements CommonRuleDefinitions { .setHtmlDescription( "Test failures or errors generally indicate that regressions have been introduced. Those tests should be handled as soon as possible to reduce the cost to fix the corresponding regressions.") .setDebtRemediationFunction(rule.debtRemediationFunctions().linear("10min")) - .setEffortToFixDescription("number of failed tests") + .setGapDescription("number of failed tests") .setSeverity(Severity.MAJOR); } @@ -129,7 +129,7 @@ public class CommonRuleDefinitionsImpl implements CommonRuleDefinitions { .addTags("pitfall") .setHtmlDescription("Skipped unit tests are considered as dead code. Either they should be activated again (and updated) or they should be removed.") .setDebtRemediationFunction(rule.debtRemediationFunctions().linear("10min")) - .setEffortToFixDescription("number of skipped tests") + .setGapDescription("number of skipped tests") .setSeverity(Severity.MAJOR); } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/rule/RegisterRules.java b/server/sonar-server/src/main/java/org/sonar/server/rule/RegisterRules.java index e9dd263c302..94f0781a01f 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/rule/RegisterRules.java +++ b/server/sonar-server/src/main/java/org/sonar/server/rule/RegisterRules.java @@ -176,7 +176,7 @@ public class RegisterRules implements Startable { .setName(ruleDef.name()) .setSeverity(ruleDef.severity()) .setStatus(ruleDef.status()) - .setGapDescription(ruleDef.effortToFixDescription()) + .setGapDescription(ruleDef.gapDescription()) .setSystemTags(ruleDef.tags()) .setType(RuleType.valueOf(ruleDef.type().name())) .setCreatedAt(system2.now()) @@ -257,9 +257,9 @@ public class RegisterRules implements Startable { if (hasDebt) { return mergeDebtDefinitions(dto, debtRemediationFunction.type().name(), - debtRemediationFunction.coefficient(), - debtRemediationFunction.offset(), - def.effortToFixDescription()); + debtRemediationFunction.gapMultiplier(), + debtRemediationFunction.baseEffort(), + def.gapDescription()); } return mergeDebtDefinitions(dto, null, null, null, null); } diff --git a/server/sonar-server/src/main/java/org/sonar/server/rule/RuleOperations.java b/server/sonar-server/src/main/java/org/sonar/server/rule/RuleOperations.java index 60846a424d2..313cd06811a 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/rule/RuleOperations.java +++ b/server/sonar-server/src/main/java/org/sonar/server/rule/RuleOperations.java @@ -86,8 +86,8 @@ public class RuleOperations { } else if (!isRuleDebtSameAsOverriddenValues(ruleDto, newFunction, newCoefficient, newOffset)) { DefaultDebtRemediationFunction debtRemediationFunction = new DefaultDebtRemediationFunction(DebtRemediationFunction.Type.valueOf(newFunction), newCoefficient, newOffset); ruleDto.setRemediationFunction(debtRemediationFunction.type().name()); - ruleDto.setRemediationGapMultiplier(debtRemediationFunction.coefficient()); - ruleDto.setRemediationBaseEffort(debtRemediationFunction.offset()); + ruleDto.setRemediationGapMultiplier(debtRemediationFunction.gapMultiplier()); + ruleDto.setRemediationBaseEffort(debtRemediationFunction.baseEffort()); needUpdate = true; } @@ -114,7 +114,8 @@ public class RuleOperations { private static boolean isRuleDebtSameAsOverriddenValues(RuleDto ruleDto, @Nullable String newFunction, @Nullable String newCoefficient, @Nullable String newOffset) { - return isSameRemediationFunction(newFunction, newCoefficient, newOffset, ruleDto.getRemediationFunction(), ruleDto.getRemediationGapMultiplier(), ruleDto.getRemediationBaseEffort()); + return isSameRemediationFunction(newFunction, newCoefficient, newOffset, ruleDto.getRemediationFunction(), ruleDto.getRemediationGapMultiplier(), + ruleDto.getRemediationBaseEffort()); } private static boolean isSameRemediationFunction(@Nullable String newFunction, @Nullable String newCoefficient, @Nullable String newOffset, diff --git a/server/sonar-server/src/main/java/org/sonar/server/rule/RuleUpdater.java b/server/sonar-server/src/main/java/org/sonar/server/rule/RuleUpdater.java index ad350b9ecf0..64b7afe59d4 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/rule/RuleUpdater.java +++ b/server/sonar-server/src/main/java/org/sonar/server/rule/RuleUpdater.java @@ -196,8 +196,8 @@ public class RuleUpdater { context.rule.setRemediationBaseEffort(null); } else { context.rule.setRemediationFunction(function.type().name()); - context.rule.setRemediationGapMultiplier(function.coefficient()); - context.rule.setRemediationBaseEffort(function.offset()); + context.rule.setRemediationGapMultiplier(function.gapMultiplier()); + context.rule.setRemediationBaseEffort(function.baseEffort()); } } } @@ -220,8 +220,8 @@ public class RuleUpdater { private static boolean isSameAsDefaultFunction(DebtRemediationFunction fn, RuleDto rule) { return new EqualsBuilder() .append(fn.type().name(), rule.getDefaultRemediationFunction()) - .append(fn.coefficient(), rule.getDefaultRemediationGapMultiplier()) - .append(fn.offset(), rule.getDefaultRemediationBaseEffort()) + .append(fn.gapMultiplier(), rule.getDefaultRemediationGapMultiplier()) + .append(fn.baseEffort(), rule.getDefaultRemediationBaseEffort()) .isEquals(); } diff --git a/server/sonar-server/src/main/java/org/sonar/server/rule/ws/RuleMapper.java b/server/sonar-server/src/main/java/org/sonar/server/rule/ws/RuleMapper.java index a62a20af8d4..a502405ab5c 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/rule/ws/RuleMapper.java +++ b/server/sonar-server/src/main/java/org/sonar/server/rule/ws/RuleMapper.java @@ -23,11 +23,14 @@ package org.sonar.server.rule.ws; import com.google.common.base.Function; import com.google.common.collect.FluentIterable; import java.util.List; +import java.util.Locale; import java.util.Set; +import javax.annotation.CheckForNull; import javax.annotation.Nonnull; import org.sonar.api.resources.Language; import org.sonar.api.resources.Languages; import org.sonar.api.server.debt.DebtRemediationFunction; +import org.sonar.api.server.debt.internal.DefaultDebtRemediationFunction; import org.sonar.db.rule.RuleDto; import org.sonar.db.rule.RuleParamDto; import org.sonar.markdown.Markdown; @@ -130,13 +133,13 @@ public class RuleMapper { if (shouldReturnField(fieldsToReturn, FIELD_DEFAULT_DEBT_REM_FUNCTION)) { DebtRemediationFunction defaultDebtRemediationFunction = defaultDebtRemediationFunction(ruleDto); if (defaultDebtRemediationFunction != null) { - String gapMultiplier = defaultDebtRemediationFunction.coefficient(); + String gapMultiplier = defaultDebtRemediationFunction.gapMultiplier(); if (gapMultiplier != null) { ruleResponse.setDefaultRemFnGapMultiplier(gapMultiplier); // Set deprecated field ruleResponse.setDefaultDebtRemFnCoeff(gapMultiplier); } - String baseEffort = defaultDebtRemediationFunction.offset(); + String baseEffort = defaultDebtRemediationFunction.baseEffort(); if (baseEffort != null) { ruleResponse.setDefaultRemFnBaseEffort(baseEffort); // Set deprecated field @@ -160,13 +163,13 @@ public class RuleMapper { // Set deprecated field ruleResponse.setDebtRemFnType(debtRemediationFunction.type().name()); } - String gapMultiplier = debtRemediationFunction.coefficient(); + String gapMultiplier = debtRemediationFunction.gapMultiplier(); if (gapMultiplier != null) { ruleResponse.setRemFnGapMultiplier(gapMultiplier); // Set deprecated field ruleResponse.setDebtRemFnCoeff(gapMultiplier); } - String baseEffort = debtRemediationFunction.offset(); + String baseEffort = debtRemediationFunction.baseEffort(); if (baseEffort != null) { ruleResponse.setRemFnBaseEffort(baseEffort); // Set deprecated field @@ -298,51 +301,29 @@ public class RuleMapper { return rule.getRemediationFunction() != null; } + @CheckForNull private static DebtRemediationFunction defaultDebtRemediationFunction(final RuleDto ruleDto) { final String function = ruleDto.getDefaultRemediationFunction(); if (function == null || function.isEmpty()) { return null; } else { - return new DebtRemediationFunction() { - @Override - public Type type() { - return Type.valueOf(function.toUpperCase()); - } - - @Override - public String coefficient() { - return ruleDto.getDefaultRemediationGapMultiplier(); - } - - @Override - public String offset() { - return ruleDto.getDefaultRemediationBaseEffort(); - } - }; + return new DefaultDebtRemediationFunction( + DebtRemediationFunction.Type.valueOf(function.toUpperCase(Locale.ENGLISH)), + ruleDto.getDefaultRemediationGapMultiplier(), + ruleDto.getDefaultRemediationBaseEffort()); } } + @CheckForNull private static DebtRemediationFunction debtRemediationFunction(final RuleDto ruleDto) { final String function = ruleDto.getRemediationFunction(); if (function == null || function.isEmpty()) { return defaultDebtRemediationFunction(ruleDto); } else { - return new DebtRemediationFunction() { - @Override - public Type type() { - return Type.valueOf(function.toUpperCase()); - } - - @Override - public String coefficient() { - return ruleDto.getRemediationGapMultiplier(); - } - - @Override - public String offset() { - return ruleDto.getRemediationBaseEffort(); - } - }; + return new DefaultDebtRemediationFunction( + DebtRemediationFunction.Type.valueOf(function.toUpperCase(Locale.ENGLISH)), + ruleDto.getRemediationGapMultiplier(), + ruleDto.getRemediationBaseEffort()); } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/rule/DeprecatedRulesDefinitionLoaderTest.java b/server/sonar-server/src/test/java/org/sonar/server/rule/DeprecatedRulesDefinitionLoaderTest.java index 83610b10433..106ae087e15 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/rule/DeprecatedRulesDefinitionLoaderTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/rule/DeprecatedRulesDefinitionLoaderTest.java @@ -19,6 +19,9 @@ */ package org.sonar.server.rule; +import java.io.Reader; +import java.util.Arrays; +import java.util.List; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; @@ -37,10 +40,6 @@ import org.sonar.server.debt.DebtModelPluginRepository; import org.sonar.server.debt.DebtModelXMLExporter; import org.sonar.server.debt.DebtRulesXMLImporter; -import java.io.Reader; -import java.util.Arrays; -import java.util.List; - import static com.google.common.collect.Lists.newArrayList; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.Assert.fail; @@ -181,8 +180,8 @@ public class DeprecatedRulesDefinitionLoaderTest { assertThat(rule).isNotNull(); assertThat(rule.key()).isEqualTo("ConstantName"); assertThat(rule.debtRemediationFunction().type()).isEqualTo(DebtRemediationFunction.Type.LINEAR_OFFSET); - assertThat(rule.debtRemediationFunction().coefficient()).isEqualTo("1d"); - assertThat(rule.debtRemediationFunction().offset()).isEqualTo("10min"); + assertThat(rule.debtRemediationFunction().gapMultiplier()).isEqualTo("1d"); + assertThat(rule.debtRemediationFunction().baseEffort()).isEqualTo("10min"); } @Test diff --git a/server/sonar-server/src/test/java/org/sonar/server/rule/RegisterRulesMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/rule/RegisterRulesMediumTest.java index db7037386bb..96e6a004063 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/rule/RegisterRulesMediumTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/rule/RegisterRulesMediumTest.java @@ -287,7 +287,7 @@ public class RegisterRulesMediumTest { .setInternalKey("new_internal"); rule .setDebtRemediationFunction(rule.debtRemediationFunctions().linearWithOffset("1h", "30min")) - .setEffortToFixDescription("Effort"); + .setGapDescription("Effort"); } }); diff --git a/server/sonar-server/src/test/java/org/sonar/server/rule/RegisterRulesTest.java b/server/sonar-server/src/test/java/org/sonar/server/rule/RegisterRulesTest.java index 6f46e1d31e8..e506446406d 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/rule/RegisterRulesTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/rule/RegisterRulesTest.java @@ -365,7 +365,7 @@ public class RegisterRulesTest { .setTags("tag1", "tag2", "tag3") .setType(RuleType.CODE_SMELL) .setStatus(RuleStatus.BETA) - .setEffortToFixDescription("squid.S115.effortToFix"); + .setGapDescription("squid.S115.effortToFix"); rule1.setDebtRemediationFunction(rule1.debtRemediationFunctions().linearWithOffset("5d", "10h")); rule1.createParam("param1").setDescription("parameter one").setDefaultValue("default1"); @@ -396,7 +396,7 @@ public class RegisterRulesTest { .setTags("tag1", "tag4") .setType(RuleType.BUG) .setStatus(RuleStatus.READY) - .setEffortToFixDescription("squid.S115.effortToFix.v2"); + .setGapDescription("squid.S115.effortToFix.v2"); rule1.setDebtRemediationFunction(rule1.debtRemediationFunctions().linearWithOffset("6d", "2h")); rule1.createParam("param1").setDescription("parameter one v2").setDefaultValue("default1 v2"); rule1.createParam("param2").setDescription("parameter two v2").setDefaultValue("default2 v2"); diff --git a/server/sonar-server/src/test/java/org/sonar/server/rule/RuleOperationsTest.java b/server/sonar-server/src/test/java/org/sonar/server/rule/RuleOperationsTest.java index 51de3cee65f..ad558c3d5f5 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/rule/RuleOperationsTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/rule/RuleOperationsTest.java @@ -208,7 +208,7 @@ public class RuleOperationsTest { authorizedUserSession ); } catch (Exception e) { - assertThat(e).isInstanceOf(BadRequestException.class).hasMessage("Invalid coefficient: foo (Duration 'foo' is invalid, it should use the following sample format : 2d 10h 15min)"); + assertThat(e).isInstanceOf(BadRequestException.class).hasMessage("Invalid gap multiplier: foo (Duration 'foo' is invalid, it should use the following sample format : 2d 10h 15min)"); } verify(ruleDao, never()).update(eq(session), any(RuleDto.class)); diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/server/debt/DebtRemediationFunction.java b/sonar-plugin-api/src/main/java/org/sonar/api/server/debt/DebtRemediationFunction.java index fa8feda469a..07912bd464a 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/server/debt/DebtRemediationFunction.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/server/debt/DebtRemediationFunction.java @@ -23,7 +23,7 @@ import javax.annotation.CheckForNull; /** * Function used to calculate the remediation cost of an issue. See {@link Type} for details. - *

The coefficient and offset involved in the functions are durations. They are defined in hours, minutes and/or + *

The gap multiplier and base effort involved in the functions are durations. They are defined in hours, minutes and/or * seconds. Examples: "5min", "1h 10min". Supported units are "d" (days), "h" (hour), and "min" (minutes).

* * @since 4.3 @@ -35,23 +35,23 @@ public interface DebtRemediationFunction { /** * The cost to fix an issue of this type depends on the magnitude of the issue. * For instance, an issue related to file size might be linear, with the total cost-to-fix incrementing - * (by the coefficient amount) for each line of code above the allowed threshold. - * The rule must provide the "effort to fix" value when raising an issue. + * (by the gap multiplier amount) for each line of code above the allowed threshold. + * The rule must provide the "gap" value when raising an issue. */ LINEAR(true, false), /** - * It takes a certain amount of time to deal with an issue of this type (this is the offset). + * It takes a certain amount of time to deal with an issue of this type (this is the gap multiplier). * Then, the magnitude of the issue comes in to play. For instance, an issue related to complexity might be linear with offset. - * So the total cost to fix is the time to make the basic analysis (the offset) plus the time required to deal + * So the total cost to fix is the time to make the basic analysis (the base effort) plus the time required to deal * with each complexity point above the allowed value. *

- * Total remediation cost = offset + (number of noncompliance x coefficient) + * Total remediation cost = base effort + (number of noncompliance x gap multiplier) *

- *

The rule must provide the "effort to fix" value when raising an issue. Let’s take as a example the “Paragraphs should not be too complex” rule. + *

The rule must provide the "gap" value when raising an issue. Let’s take as a example the “Paragraphs should not be too complex” rule. * If you set the rule threshold to 20, and you have a paragraph with a complexity of 27, you have 7 points of complexity - * to remove. Internally, this is called the Effort to Fix. In that case, if you use the LINEAR_OFFSET configuration - * with an offset of 4h and a remediation cost of 1mn, the technical debt for this issue related to a + * to remove. Internally, this is called the Gap. In that case, if you use the LINEAR_OFFSET configuration + * with an base effort of 4h and a remediation cost of 1mn, the effort for this issue related to a * too-complex block of code will be: (7 complexity points x 1min) + 4h = 4h and 7mn *

*/ @@ -63,35 +63,79 @@ public interface DebtRemediationFunction { */ CONSTANT_ISSUE(false, true); - private final boolean usesCoefficient; - private final boolean usesOffset; + private final boolean usesGapMultiplier; + private final boolean usesBaseEffort; - Type(boolean usesCoefficient, boolean usesOffset) { - this.usesCoefficient = usesCoefficient; - this.usesOffset = usesOffset; + Type(boolean usesGapMultiplier, boolean usesBaseEffort) { + this.usesGapMultiplier = usesGapMultiplier; + this.usesBaseEffort = usesBaseEffort; } + /** + * @deprecated since 5.5, replaced by {@link #usesGapMultiplier()} + */ + @Deprecated public boolean usesCoefficient() { - return usesCoefficient; + return usesGapMultiplier(); } + /** + * @since 5.5 + */ + public boolean usesGapMultiplier() { + return usesGapMultiplier; + } + + /** + * @deprecated since 5.5, replaced by {@link #usesBaseEffort()} + */ + @Deprecated public boolean usesOffset() { - return usesOffset; + return usesBaseEffort(); } + + /** + * @since 5.5 + */ + public boolean usesBaseEffort() { + return usesBaseEffort; + } + } + /** + * @since 5.5 + */ Type type(); /** - * Non-null value on {@link Type#LINEAR} and {@link Type#LINEAR_OFFSET} functions, else {@code null}. + * @deprecated since 5.5, replaced by {@link #gapMultiplier()} */ + @Deprecated @CheckForNull String coefficient(); /** - * Non-null value on {@link Type#LINEAR_OFFSET} and {@link Type#CONSTANT_ISSUE} functions, else {@code null}. + * Non-null value on {@link Type#LINEAR} and {@link Type#LINEAR_OFFSET} functions, else {@code null}. + * + * @since 5.5 */ @CheckForNull + String gapMultiplier(); + + /** + * @deprecated since 5.5, replaced by {@link #baseEffort()} + */ + @Deprecated + @CheckForNull String offset(); + /** + * Non-null value on {@link Type#LINEAR_OFFSET} and {@link Type#CONSTANT_ISSUE} functions, else {@code null}. + * + * @since 5.5 + */ + @CheckForNull + String baseEffort(); + } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/server/debt/internal/DefaultDebtRemediationFunction.java b/sonar-plugin-api/src/main/java/org/sonar/api/server/debt/internal/DefaultDebtRemediationFunction.java index dad2e2fdfb2..824a7fac706 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/server/debt/internal/DefaultDebtRemediationFunction.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/server/debt/internal/DefaultDebtRemediationFunction.java @@ -34,13 +34,13 @@ public class DefaultDebtRemediationFunction implements DebtRemediationFunction { private static final int HOURS_IN_DAY = 24; private final Type type; - private final String coefficient; - private final String offset; + private final String gapMultiplier; + private final String baseEffort; - public DefaultDebtRemediationFunction(@Nullable Type type, @Nullable String coefficient, @Nullable String offset) { + public DefaultDebtRemediationFunction(@Nullable Type type, @Nullable String gapMultiplier, @Nullable String baseEffort) { this.type = type; - this.coefficient = sanitizeValue("coefficient", coefficient); - this.offset = sanitizeValue("offset", offset); + this.gapMultiplier = sanitizeValue("gap multiplier", gapMultiplier); + this.baseEffort = sanitizeValue("base effort", baseEffort); validate(); } @@ -62,29 +62,50 @@ public class DefaultDebtRemediationFunction implements DebtRemediationFunction { return type; } + /** + * @deprecated since 5.5, replaced by {@link #gapMultiplier} + */ @Override @CheckForNull + @Deprecated public String coefficient() { - return coefficient; + return gapMultiplier(); } + + @Override + @CheckForNull + public String gapMultiplier() { + return gapMultiplier; + } + + /** + * @deprecated since 5.5, replaced by {@link #baseEffort} + */ @Override @CheckForNull + @Deprecated public String offset() { - return offset; + return baseEffort(); } + @Override + public String baseEffort() { + return baseEffort; + } + + private void validate() { checkArgument(type != null, "Remediation function type cannot be null"); switch (type) { case LINEAR: - checkArgument(this.coefficient != null && this.offset == null, "Linear functions must only have a non empty coefficient"); + checkArgument(this.gapMultiplier != null && this.baseEffort == null, "Linear functions must only have a non empty gap multiplier"); break; case LINEAR_OFFSET: - checkArgument(this.coefficient != null && this.offset != null, "Linear with offset functions must have both non null coefficient and offset"); + checkArgument(this.gapMultiplier != null && this.baseEffort != null, "Linear with offset functions must have both non null gap multiplier and base effort"); break; case CONSTANT_ISSUE: - checkArgument(this.coefficient == null && this.offset != null, "Constant/issue functions must only have a non empty offset"); + checkArgument(this.gapMultiplier == null && this.baseEffort != null, "Constant/issue functions must only have a non empty base effort"); break; default: throw new IllegalArgumentException(String.format("Unknown type on %s", this)); @@ -101,8 +122,8 @@ public class DefaultDebtRemediationFunction implements DebtRemediationFunction { } DefaultDebtRemediationFunction other = (DefaultDebtRemediationFunction) o; return new EqualsBuilder() - .append(coefficient, other.coefficient()) - .append(offset, other.offset()) + .append(gapMultiplier, other.gapMultiplier()) + .append(baseEffort, other.baseEffort()) .append(type, other.type()) .isEquals(); } @@ -110,8 +131,8 @@ public class DefaultDebtRemediationFunction implements DebtRemediationFunction { @Override public int hashCode() { int result = type.hashCode(); - result = 31 * result + (coefficient != null ? coefficient.hashCode() : 0); - result = 31 * result + (offset != null ? offset.hashCode() : 0); + result = 31 * result + (gapMultiplier != null ? gapMultiplier.hashCode() : 0); + result = 31 * result + (baseEffort != null ? baseEffort.hashCode() : 0); return result; } @@ -119,8 +140,8 @@ public class DefaultDebtRemediationFunction implements DebtRemediationFunction { public String toString() { return Objects.toStringHelper(DebtRemediationFunction.class) .add("type", type) - .add("coefficient", coefficient) - .add("offset", offset) + .add("gap multiplier", gapMultiplier) + .add("base effort", baseEffort) .toString(); } } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/server/rule/DefaultDebtRemediationFunctions.java b/sonar-plugin-api/src/main/java/org/sonar/api/server/rule/DefaultDebtRemediationFunctions.java index f77d9fdfb41..823ff15fe84 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/server/rule/DefaultDebtRemediationFunctions.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/server/rule/DefaultDebtRemediationFunctions.java @@ -19,12 +19,11 @@ */ package org.sonar.api.server.rule; +import javax.annotation.Nullable; import org.sonar.api.server.debt.DebtRemediationFunction; import org.sonar.api.server.debt.internal.DefaultDebtRemediationFunction; import org.sonar.api.utils.MessageException; -import javax.annotation.Nullable; - /** * Factory of {@link org.sonar.api.server.debt.DebtRemediationFunction} that keeps * a context of rule for better error messages. Used only when declaring rules. @@ -42,24 +41,24 @@ class DefaultDebtRemediationFunctions implements RulesDefinition.DebtRemediation } @Override - public DebtRemediationFunction linear(String coefficient) { - return create(DefaultDebtRemediationFunction.Type.LINEAR, coefficient, null); + public DebtRemediationFunction linear(String gapMultiplier) { + return create(DefaultDebtRemediationFunction.Type.LINEAR, gapMultiplier, null); } @Override - public DebtRemediationFunction linearWithOffset(String coefficient, String offset) { - return create(DefaultDebtRemediationFunction.Type.LINEAR_OFFSET, coefficient, offset); + public DebtRemediationFunction linearWithOffset(String gapMultiplier, String baseEffort) { + return create(DefaultDebtRemediationFunction.Type.LINEAR_OFFSET, gapMultiplier, baseEffort); } @Override - public DebtRemediationFunction constantPerIssue(String offset) { - return create(DefaultDebtRemediationFunction.Type.CONSTANT_ISSUE, null, offset); + public DebtRemediationFunction constantPerIssue(String baseEffort) { + return create(DefaultDebtRemediationFunction.Type.CONSTANT_ISSUE, null, baseEffort); } @Override - public DebtRemediationFunction create(DebtRemediationFunction.Type type, @Nullable String coefficient, @Nullable String offset) { + public DebtRemediationFunction create(DebtRemediationFunction.Type type, @Nullable String gapMultiplier, @Nullable String baseEffort) { try { - return new DefaultDebtRemediationFunction(type, coefficient, offset); + return new DefaultDebtRemediationFunction(type, gapMultiplier, baseEffort); } catch (Exception e) { throw MessageException.of(String.format("The rule '%s:%s' is invalid : %s ", this.repoKey, this.key, e.getMessage())); } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/server/rule/RulesDefinition.java b/sonar-plugin-api/src/main/java/org/sonar/api/server/rule/RulesDefinition.java index 382b29adea5..94d5ef5c065 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/server/rule/RulesDefinition.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/server/rule/RulesDefinition.java @@ -625,33 +625,33 @@ public interface RulesDefinition { interface DebtRemediationFunctions { /** - * Shortcut for {@code create(Type.LINEAR, coefficient, null)}. - * @param coefficient the duration to fix one issue. See {@link DebtRemediationFunction} for details about format. + * Shortcut for {@code create(Type.LINEAR, gap multiplier, null)}. + * @param gapMultiplier the duration to fix one issue. See {@link DebtRemediationFunction} for details about format. * @see org.sonar.api.server.debt.DebtRemediationFunction.Type#LINEAR */ - DebtRemediationFunction linear(String coefficient); + DebtRemediationFunction linear(String gapMultiplier); /** - * Shortcut for {@code create(Type.LINEAR_OFFSET, coefficient, offset)}. - * @param coefficient duration to fix one point of complexity. See {@link DebtRemediationFunction} for details and format. - * @param offset duration to make basic analysis. See {@link DebtRemediationFunction} for details and format. + * Shortcut for {@code create(Type.LINEAR_OFFSET, gap multiplier, base effort)}. + * @param gapMultiplier duration to fix one point of complexity. See {@link DebtRemediationFunction} for details and format. + * @param baseEffort duration to make basic analysis. See {@link DebtRemediationFunction} for details and format. * @see org.sonar.api.server.debt.DebtRemediationFunction.Type#LINEAR_OFFSET */ - DebtRemediationFunction linearWithOffset(String coefficient, String offset); + DebtRemediationFunction linearWithOffset(String gapMultiplier, String baseEffort); /** - * Shortcut for {@code create(Type.CONSTANT_ISSUE, null, constant)}. - * @param constant cost per issue. See {@link DebtRemediationFunction} for details and format. + * Shortcut for {@code create(Type.CONSTANT_ISSUE, null, base effort)}. + * @param baseEffort cost per issue. See {@link DebtRemediationFunction} for details and format. * @see org.sonar.api.server.debt.DebtRemediationFunction.Type#CONSTANT_ISSUE */ - DebtRemediationFunction constantPerIssue(String constant); + DebtRemediationFunction constantPerIssue(String baseEffort); /** * Flexible way to create a {@link DebtRemediationFunction}. An unchecked exception is thrown if * coefficient and/or offset are not valid according to the given @{code type}. * @since 5.3 */ - DebtRemediationFunction create(DebtRemediationFunction.Type type, @Nullable String coefficient, @Nullable String offset); + DebtRemediationFunction create(DebtRemediationFunction.Type type, @Nullable String gapMultiplier, @Nullable String baseEffort); } class NewRule { @@ -666,7 +666,7 @@ public interface RulesDefinition { private boolean template; private RuleStatus status = RuleStatus.defaultStatus(); private DebtRemediationFunction debtRemediationFunction; - private String effortToFixDescription; + private String gapDescription; private final Set tags = Sets.newTreeSet(); private final Map paramsByKey = Maps.newHashMap(); private final DebtRemediationFunctions functions; @@ -810,17 +810,25 @@ public interface RulesDefinition { return this; } + /** + * @deprecated since 5.5, replaced by {@link #setGapDescription(String)} + */ + @Deprecated + public NewRule setEffortToFixDescription(@Nullable String s) { + return setGapDescription(s); + } + /** * For rules that use LINEAR or LINEAR_OFFSET remediation functions, the meaning - * of the function parameter (= "effort to fix") must be set. This description - * explains what 1 point of "effort to fix" represents for the rule. + * of the function parameter (= "gap") must be set. This description + * explains what 1 point of "gap" represents for the rule. *

* Example: for the "Insufficient condition coverage", this description for the - * remediation function coefficient/offset would be something like + * remediation function gap multiplier/base effort would be something like * "Effort to test one uncovered condition". */ - public NewRule setEffortToFixDescription(@Nullable String s) { - this.effortToFixDescription = s; + public NewRule setGapDescription(@Nullable String s) { + this.gapDescription = s; return this; } @@ -901,7 +909,7 @@ public interface RulesDefinition { private final String severity; private final boolean template; private final DebtRemediationFunction debtRemediationFunction; - private final String effortToFixDescription; + private final String gapDescription; private final Set tags; private final Map params; private final RuleStatus status; @@ -918,7 +926,7 @@ public interface RulesDefinition { this.template = newRule.template; this.status = newRule.status; this.debtRemediationFunction = newRule.debtRemediationFunction; - this.effortToFixDescription = newRule.effortToFixDescription; + this.gapDescription = newRule.gapDescription; this.type = newRule.type == null ? RuleTagsToTypeConverter.convert(newRule.tags) : newRule.type; this.tags = ImmutableSortedSet.copyOf(Sets.difference(newRule.tags, RuleTagsToTypeConverter.RESERVED_TAGS)); ImmutableMap.Builder paramsBuilder = ImmutableMap.builder(); @@ -986,9 +994,18 @@ public interface RulesDefinition { return debtRemediationFunction; } + /** + * @deprecated since 5.5, replaced by {@link #gapDescription()} + */ + @Deprecated @CheckForNull public String effortToFixDescription() { - return effortToFixDescription; + return gapDescription(); + } + + @CheckForNull + public String gapDescription() { + return gapDescription; } @CheckForNull diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/server/rule/RulesDefinitionXmlLoader.java b/sonar-plugin-api/src/main/java/org/sonar/api/server/rule/RulesDefinitionXmlLoader.java index 83158579c73..996a044d19b 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/server/rule/RulesDefinitionXmlLoader.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/server/rule/RulesDefinitionXmlLoader.java @@ -121,32 +121,37 @@ import static org.apache.commons.lang.StringUtils.trim; * <param> * <key>another-param</key> * </param> - ** - * <!-- SQALE debt - type of debt remediation function --> + * + * <!-- Quality Model - type of debt remediation function --> * <!-- See enum {@link org.sonar.api.server.debt.DebtRemediationFunction.Type} for supported values --> - * <!-- Since 5.3 --> - * <debtRemediationFunction>LINEAR_OFFSET</debtRemediationFunction> + * <!-- It was previously named 'debtRemediationFunction' which is still supported but deprecated since 5.5 --> + * <!-- Since 5.5 --> + * <remediationFunction>LINEAR_OFFSET</remediationFunction> * - * <!-- SQALE debt - raw description of the "effort to fix", used for some types of remediation functions. --> - * <!-- See {@link org.sonar.api.server.rule.RulesDefinition.NewRule#setEffortToFixDescription(String)} --> - * <!-- Since 5.3 --> - * <effortToFixDescription>Effort to test one uncovered condition</effortToFixDescription> + * <!-- Quality Model - raw description of the "gap", used for some types of remediation functions. --> + * <!-- See {@link org.sonar.api.server.rule.RulesDefinition.NewRule#setGapDescription(String)} --> + * <!-- It was previously named 'effortToFixDescription' which is still supported but deprecated since 5.5 --> + * <!-- Since 5.5 --> + * <gapDescription>Effort to test one uncovered condition</gapFixDescription> * - * <!-- SQALE debt - coefficient of debt remediation function. Must be defined only for some function types. --> + * <!-- Quality Model - gap multiplier of debt remediation function. Must be defined only for some function types. --> * <!-- See {@link org.sonar.api.server.rule.RulesDefinition.DebtRemediationFunctions} --> - * <!-- Since 5.3 --> - * <debtRemediationFunctionCoefficient>10min</debtRemediationFunctionCoefficient> + * <!-- It was previously named 'debtRemediationFunctionCoefficient' which is still supported but deprecated since 5.5 --> + * <!-- Since 5.5 --> + * <remediationFunctionGapMultiplier>10min</remediationFunctionGapMultiplier> * - * <!-- SQALE debt - offset of debt remediation function. Must be defined only for some function types. --> + * <!-- Quality Model - base effort of debt remediation function. Must be defined only for some function types. --> * <!-- See {@link org.sonar.api.server.rule.RulesDefinition.DebtRemediationFunctions} --> - * <!-- Since 5.3 --> - * <debtRemediationFunctionOffset>2min</debtRemediationFunctionOffset> + * <!-- It was previously named 'debtRemediationFunctionOffset' which is still supported but deprecated since 5.5 --> + * <!-- Since 5.5 --> + * <remediationFunctionBaseEffort>2min</remediationFunctionBaseEffort> * * <!-- Deprecated field, replaced by "internalKey" --> * <configKey>Checker/TreeWalker/LocalVariableName</configKey> * * <!-- Deprecated field, replaced by "severity" --> * <priority>BLOCKER</priority> + * * </rule> * </rules> * @@ -162,7 +167,7 @@ import static org.apache.commons.lang.StringUtils.trim; * <tag>security</tag> * <tag>user-experience</tag> * <debtRemediationFunction>CONSTANT_ISSUE</debtRemediationFunction> - * <debtRemediationFunctionOffset>10min</debtRemediationFunctionOffset> + * <debtRemediationFunctionBaseOffset>10min</debtRemediationFunctionBaseOffset> * </rule> * * <!-- another rules... --> @@ -238,10 +243,10 @@ public class RulesDefinitionXmlLoader { String type = null; RuleStatus status = RuleStatus.defaultStatus(); boolean template = false; - String effortToFixDescription = null; + String gapDescription = null; String debtRemediationFunction = null; - String debtRemediationFunctionOffset = null; - String debtRemediationFunctionCoeff = null; + String debtRemediationFunctionGapMultiplier = null; + String debtRemediationFunctionBaseEffort = null; List params = new ArrayList<>(); List tags = new ArrayList<>(); @@ -288,17 +293,17 @@ public class RulesDefinitionXmlLoader { } else if (equalsIgnoreCase("cardinality", nodeName)) { template = Cardinality.MULTIPLE == Cardinality.valueOf(nodeValue(cursor)); - } else if (equalsIgnoreCase("effortToFixDescription", nodeName)) { - effortToFixDescription = nodeValue(cursor); + } else if (equalsIgnoreCase("gapDescription", nodeName) || equalsIgnoreCase("effortToFixDescription", nodeName)) { + gapDescription = nodeValue(cursor); - } else if (equalsIgnoreCase("debtRemediationFunction", nodeName)) { + } else if (equalsIgnoreCase("remediationFunction", nodeName) || equalsIgnoreCase("debtRemediationFunction", nodeName)) { debtRemediationFunction = nodeValue(cursor); - } else if (equalsIgnoreCase("debtRemediationFunctionOffset", nodeName)) { - debtRemediationFunctionOffset = nodeValue(cursor); + } else if (equalsIgnoreCase("remediationFunctionBaseEffort", nodeName) || equalsIgnoreCase("debtRemediationFunctionOffset", nodeName)) { + debtRemediationFunctionGapMultiplier = nodeValue(cursor); - } else if (equalsIgnoreCase("debtRemediationFunctionCoefficient", nodeName)) { - debtRemediationFunctionCoeff = nodeValue(cursor); + } else if (equalsIgnoreCase("remediationFunctionGapMultiplier", nodeName) || equalsIgnoreCase("debtRemediationFunctionCoefficient", nodeName)) { + debtRemediationFunctionBaseEffort = nodeValue(cursor); } else if (equalsIgnoreCase("status", nodeName)) { String s = nodeValue(cursor); @@ -322,12 +327,12 @@ public class RulesDefinitionXmlLoader { .setTags(tags.toArray(new String[tags.size()])) .setTemplate(template) .setStatus(status) - .setEffortToFixDescription(effortToFixDescription); + .setGapDescription(gapDescription); if (type != null) { rule.setType(RuleType.valueOf(type)); } fillDescription(rule, descriptionFormat, description); - fillRemediationFunction(rule, debtRemediationFunction, debtRemediationFunctionOffset, debtRemediationFunctionCoeff); + fillRemediationFunction(rule, debtRemediationFunction, debtRemediationFunctionGapMultiplier, debtRemediationFunctionBaseEffort); fillParams(rule, params); } catch (Exception e) { throw new IllegalArgumentException(format("Fail to load the rule with key [%s:%s]", repo.key(), key), e); diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/server/debt/DefaultDebtRemediationFunctionTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/server/debt/DefaultDebtRemediationFunctionTest.java index c124d362891..4b95faff418 100644 --- a/sonar-plugin-api/src/test/java/org/sonar/api/server/debt/DefaultDebtRemediationFunctionTest.java +++ b/sonar-plugin-api/src/test/java/org/sonar/api/server/debt/DefaultDebtRemediationFunctionTest.java @@ -31,32 +31,32 @@ public class DefaultDebtRemediationFunctionTest { public void create_linear() { DebtRemediationFunction function = new DefaultDebtRemediationFunction(DebtRemediationFunction.Type.LINEAR, "10h", null); assertThat(function.type()).isEqualTo(DefaultDebtRemediationFunction.Type.LINEAR); - assertThat(function.coefficient()).isEqualTo("10h"); - assertThat(function.offset()).isNull(); + assertThat(function.gapMultiplier()).isEqualTo("10h"); + assertThat(function.baseEffort()).isNull(); } @Test public void create_linear_with_offset() { DebtRemediationFunction function = new DefaultDebtRemediationFunction(DebtRemediationFunction.Type.LINEAR_OFFSET, "10h", "5min"); assertThat(function.type()).isEqualTo(DefaultDebtRemediationFunction.Type.LINEAR_OFFSET); - assertThat(function.coefficient()).isEqualTo("10h"); - assertThat(function.offset()).isEqualTo("5min"); + assertThat(function.gapMultiplier()).isEqualTo("10h"); + assertThat(function.baseEffort()).isEqualTo("5min"); } @Test public void create_constant_per_issue() { DebtRemediationFunction function = new DefaultDebtRemediationFunction(DebtRemediationFunction.Type.CONSTANT_ISSUE, null, "10h"); assertThat(function.type()).isEqualTo(DefaultDebtRemediationFunction.Type.CONSTANT_ISSUE); - assertThat(function.coefficient()).isNull(); - assertThat(function.offset()).isEqualTo("10h"); + assertThat(function.gapMultiplier()).isNull(); + assertThat(function.baseEffort()).isEqualTo("10h"); } @Test public void sanitize_remediation_coefficient_and_offset() { DebtRemediationFunction function = new DefaultDebtRemediationFunction(DebtRemediationFunction.Type.LINEAR_OFFSET, " 1 h ", " 10 min"); - assertThat(function.coefficient()).isEqualTo("1h"); - assertThat(function.offset()).isEqualTo("10min"); + assertThat(function.gapMultiplier()).isEqualTo("1h"); + assertThat(function.baseEffort()).isEqualTo("10min"); } @Test @@ -75,7 +75,7 @@ public class DefaultDebtRemediationFunctionTest { new DefaultDebtRemediationFunction(DebtRemediationFunction.Type.LINEAR, null, "10h"); fail(); } catch (IllegalArgumentException e) { - assertThat(e).hasMessage("Linear functions must only have a non empty coefficient"); + assertThat(e).hasMessage("Linear functions must only have a non empty gap multiplier"); } } @@ -85,7 +85,7 @@ public class DefaultDebtRemediationFunctionTest { new DefaultDebtRemediationFunction(DebtRemediationFunction.Type.LINEAR, "5min", "10h"); fail(); } catch (IllegalArgumentException e) { - assertThat(e).hasMessage("Linear functions must only have a non empty coefficient"); + assertThat(e).hasMessage("Linear functions must only have a non empty gap multiplier"); } } @@ -95,7 +95,7 @@ public class DefaultDebtRemediationFunctionTest { new DefaultDebtRemediationFunction(DebtRemediationFunction.Type.CONSTANT_ISSUE, "10h", null); fail(); } catch (IllegalArgumentException e) { - assertThat(e).hasMessage("Constant/issue functions must only have a non empty offset"); + assertThat(e).hasMessage("Constant/issue functions must only have a non empty base effort"); } } @@ -105,7 +105,7 @@ public class DefaultDebtRemediationFunctionTest { new DefaultDebtRemediationFunction(DebtRemediationFunction.Type.CONSTANT_ISSUE, "5min", "10h"); fail(); } catch (IllegalArgumentException e) { - assertThat(e).hasMessage("Constant/issue functions must only have a non empty offset"); + assertThat(e).hasMessage("Constant/issue functions must only have a non empty base effort"); } } @@ -115,7 +115,7 @@ public class DefaultDebtRemediationFunctionTest { new DefaultDebtRemediationFunction(DebtRemediationFunction.Type.LINEAR_OFFSET, "", "10h"); fail(); } catch (IllegalArgumentException e) { - assertThat(e).hasMessage("Linear with offset functions must have both non null coefficient and offset"); + assertThat(e).hasMessage("Linear with offset functions must have both non null gap multiplier and base effort"); } } @@ -125,7 +125,7 @@ public class DefaultDebtRemediationFunctionTest { new DefaultDebtRemediationFunction(DebtRemediationFunction.Type.LINEAR_OFFSET, "5min", ""); fail(); } catch (IllegalArgumentException e) { - assertThat(e).hasMessage("Linear with offset functions must have both non null coefficient and offset"); + assertThat(e).hasMessage("Linear with offset functions must have both non null gap multiplier and base effort"); } } @@ -152,7 +152,7 @@ public class DefaultDebtRemediationFunctionTest { @Test public void test_to_string() { assertThat(new DefaultDebtRemediationFunction(DebtRemediationFunction.Type.LINEAR_OFFSET, "10h", "5min").toString()) - .isEqualTo("DebtRemediationFunction{type=LINEAR_OFFSET, coefficient=10h, offset=5min}"); + .isEqualTo("DebtRemediationFunction{type=LINEAR_OFFSET, gap multiplier=10h, base effort=5min}"); } @Test @@ -161,7 +161,7 @@ public class DefaultDebtRemediationFunctionTest { new DefaultDebtRemediationFunction(DebtRemediationFunction.Type.LINEAR, "foo", null); fail(); } catch (IllegalArgumentException e) { - assertThat(e).hasMessage("Invalid coefficient: foo (Duration 'foo' is invalid, it should use the following sample format : 2d 10h 15min)"); + assertThat(e).hasMessage("Invalid gap multiplier: foo (Duration 'foo' is invalid, it should use the following sample format : 2d 10h 15min)"); } } diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/server/rule/RulesDefinitionTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/server/rule/RulesDefinitionTest.java index 6afed852086..f5c37dbbcd2 100644 --- a/sonar-plugin-api/src/test/java/org/sonar/api/server/rule/RulesDefinitionTest.java +++ b/sonar-plugin-api/src/test/java/org/sonar/api/server/rule/RulesDefinitionTest.java @@ -119,7 +119,7 @@ public class RulesDefinitionTest { .setName("Insufficient condition coverage") .setHtmlDescription("Insufficient condition coverage by unit tests") .setSeverity(Severity.MAJOR) - .setEffortToFixDescription("Effort to test one uncovered branch"); + .setGapDescription("Effort to test one uncovered branch"); newRule.setDebtRemediationFunction(newRule.debtRemediationFunctions().linearWithOffset("1h", "10min")); newRepo.done(); @@ -128,9 +128,9 @@ public class RulesDefinitionTest { RulesDefinition.Rule rule = repo.rule("InsufficientBranchCoverage"); assertThat(rule.debtRemediationFunction().type()).isEqualTo(DebtRemediationFunction.Type.LINEAR_OFFSET); - assertThat(rule.debtRemediationFunction().coefficient()).isEqualTo("1h"); - assertThat(rule.debtRemediationFunction().offset()).isEqualTo("10min"); - assertThat(rule.effortToFixDescription()).isEqualTo("Effort to test one uncovered branch"); + assertThat(rule.debtRemediationFunction().gapMultiplier()).isEqualTo("1h"); + assertThat(rule.debtRemediationFunction().baseEffort()).isEqualTo("10min"); + assertThat(rule.gapDescription()).isEqualTo("Effort to test one uncovered branch"); } @Test diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/server/rule/RulesDefinitionXmlLoaderTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/server/rule/RulesDefinitionXmlLoaderTest.java index 267632aef88..2780f878f94 100644 --- a/sonar-plugin-api/src/test/java/org/sonar/api/server/rule/RulesDefinitionXmlLoaderTest.java +++ b/sonar-plugin-api/src/test/java/org/sonar/api/server/rule/RulesDefinitionXmlLoaderTest.java @@ -139,18 +139,18 @@ public class RulesDefinitionXmlLoaderTest { " One" + " Desc" + - " lines" + - " LINEAR" + - " 2d 3h" + + " lines" + + " LINEAR" + + " 2d 3h" + " " + ""; RulesDefinition.Rule rule = load(xml).rule("1"); - assertThat(rule.effortToFixDescription()).isEqualTo("lines"); + assertThat(rule.gapDescription()).isEqualTo("lines"); DebtRemediationFunction function = rule.debtRemediationFunction(); assertThat(function).isNotNull(); assertThat(function.type()).isEqualTo(DebtRemediationFunction.Type.LINEAR); - assertThat(function.coefficient()).isEqualTo("2d3h"); - assertThat(function.offset()).isNull(); + assertThat(function.gapMultiplier()).isEqualTo("2d3h"); + assertThat(function.baseEffort()).isNull(); } @Test @@ -163,18 +163,18 @@ public class RulesDefinitionXmlLoaderTest { " Desc" + " lines" + - " LINEAR_OFFSET" + - " 2d 3h" + - " 5min" + + " LINEAR_OFFSET" + + " 2d 3h" + + " 5min" + " " + ""; RulesDefinition.Rule rule = load(xml).rule("1"); - assertThat(rule.effortToFixDescription()).isEqualTo("lines"); + assertThat(rule.gapDescription()).isEqualTo("lines"); DebtRemediationFunction function = rule.debtRemediationFunction(); assertThat(function).isNotNull(); assertThat(function.type()).isEqualTo(DebtRemediationFunction.Type.LINEAR_OFFSET); - assertThat(function.coefficient()).isEqualTo("2d3h"); - assertThat(function.offset()).isEqualTo("5min"); + assertThat(function.gapMultiplier()).isEqualTo("2d3h"); + assertThat(function.baseEffort()).isEqualTo("5min"); } @Test @@ -185,16 +185,16 @@ public class RulesDefinitionXmlLoaderTest { " 1" + " One" + " Desc" + - " CONSTANT_ISSUE" + - " 5min" + + " CONSTANT_ISSUE" + + " 5min" + " " + ""; RulesDefinition.Rule rule = load(xml).rule("1"); DebtRemediationFunction function = rule.debtRemediationFunction(); assertThat(function).isNotNull(); assertThat(function.type()).isEqualTo(DebtRemediationFunction.Type.CONSTANT_ISSUE); - assertThat(function.coefficient()).isNull(); - assertThat(function.offset()).isEqualTo("5min"); + assertThat(function.gapMultiplier()).isNull(); + assertThat(function.baseEffort()).isEqualTo("5min"); } @Test @@ -206,7 +206,7 @@ public class RulesDefinitionXmlLoaderTest { " 1" + " One" + " Desc" + - " UNKNOWN" + + " UNKNOWN" + " " + ""); fail(); @@ -226,9 +226,9 @@ public class RulesDefinitionXmlLoaderTest { " Desc" + " lines" + " BUG" + - " LINEAR_OFFSET" + - " 2d 3h" + - " 5min" + + " LINEAR_OFFSET" + + " 2d 3h" + + " 5min" + " " + ""; RulesDefinition.Rule rule = load(xml).rule("1"); @@ -272,6 +272,29 @@ public class RulesDefinitionXmlLoaderTest { } } + @Test + public void test_deprecated_remediation_function() { + String xml = "" + + "" + + " " + + " 1" + + " One" + + " Desc" + + " lines" + + " LINEAR_OFFSET" + + " 2d 3h" + + " 5min" + + " " + + ""; + RulesDefinition.Rule rule = load(xml).rule("1"); + assertThat(rule.gapDescription()).isEqualTo("lines"); + DebtRemediationFunction function = rule.debtRemediationFunction(); + assertThat(function).isNotNull(); + assertThat(function.type()).isEqualTo(DebtRemediationFunction.Type.LINEAR_OFFSET); + assertThat(function.gapMultiplier()).isEqualTo("2d3h"); + assertThat(function.baseEffort()).isEqualTo("5min"); + } + private RulesDefinition.Repository load(InputStream input, String encoding) { RulesDefinition.Context context = new RulesDefinition.Context(); RulesDefinition.NewRepository newRepository = context.createRepository("squid", "java"); -- 2.39.5