private static DebtRemediationFunction remediationFunction(DebtRemediationFunction.Type function, @Nullable String coefficient, @Nullable String offset, RulesDefinition.DebtRemediationFunctions functions, String repoKey, String ruleKey) { if (DebtRemediationFunction.Type.LINEAR.equals(function) && coefficient != null) { return functions.linear(coefficient); } else if (DebtRemediationFunction.Type.CONSTANT_ISSUE.equals(function) && offset != null) { return functions.constantPerIssue(offset); } else if (DebtRemediationFunction.Type.LINEAR_OFFSET.equals(function) && coefficient != null && offset != null) { return functions.linearWithOffset(coefficient, offset); } else { throw new IllegalArgumentException(String.format("Debt definition on rule '%s:%s' is invalid", repoKey, ruleKey)); } }
@Test public void define_rules_with_remediation_function() { RulesDefinition.NewRepository newRepo = context.createRepository("common-java", "java"); RulesDefinition.NewRule newRule = newRepo.createRule("InsufficientBranchCoverage") .setName("Insufficient condition coverage") .setHtmlDescription("Insufficient condition coverage by unit tests") .setSeverity(Severity.MAJOR) .setGapDescription("Effort to test one uncovered branch"); newRule.setDebtRemediationFunction(newRule.debtRemediationFunctions().linearWithOffset("1h", "10min")); newRepo.done(); RulesDefinition.Repository repo = context.repository("common-java"); assertThat(repo.rules()).hasSize(1); RulesDefinition.Rule rule = repo.rule("InsufficientBranchCoverage"); assertThat(rule.debtRemediationFunction().type()).isEqualTo(DebtRemediationFunction.Type.LINEAR_OFFSET); assertThat(rule.debtRemediationFunction().gapMultiplier()).isEqualTo("1h"); assertThat(rule.debtRemediationFunction().baseEffort()).isEqualTo("10min"); assertThat(rule.gapDescription()).isEqualTo("Effort to test one uncovered branch"); }
private DebtRemediationFunction remediationFunction(DebtRemediationFunctions drf) { if (func.startsWith("Constant")) { return drf.constantPerIssue(constantCost.replace("mn", "min")); } if ("Linear".equals(func)) { return drf.linear(linearFactor.replace("mn", "min")); } return drf.linearWithOffset(linearFactor.replace("mn", "min"), linearOffset.replace("mn", "min")); } }
private void setupSqaleModel(NewRule rule, Class<?> ruleClass) { SqaleConstantRemediation constant = AnnotationUtils.getAnnotation(ruleClass, SqaleConstantRemediation.class); SqaleLinearRemediation linear = AnnotationUtils.getAnnotation(ruleClass, SqaleLinearRemediation.class); SqaleLinearWithOffsetRemediation linearWithOffset = AnnotationUtils.getAnnotation(ruleClass, SqaleLinearWithOffsetRemediation.class); Set<Annotation> remediations = Sets.newHashSet(constant, linear, linearWithOffset); if (Iterables.size(Iterables.filter(remediations, Predicates.notNull())) > 1) { throw new IllegalArgumentException("Found more than one SQALE remediation annotations on " + ruleClass); } if (constant != null) { rule.setDebtRemediationFunction(rule.debtRemediationFunctions().constantPerIssue(constant.value())); } if (linear != null) { rule.setDebtRemediationFunction(rule.debtRemediationFunctions().linear(linear.coeff())); rule.setGapDescription(linear.effortToFixDescription()); } if (linearWithOffset != null) { rule.setDebtRemediationFunction( rule.debtRemediationFunctions().linearWithOffset(linearWithOffset.coeff(), linearWithOffset.offset())); rule.setGapDescription(linearWithOffset.effortToFixDescription()); } }
private static void setRemediationFromJson(NewRule rule, Map<String, Object> remediation) { String func = getString(remediation, "func"); DebtRemediationFunctions remediationBuilder = rule.debtRemediationFunctions(); if (func.startsWith("Constant")) { String constantCost = getString(remediation, "constantCost"); rule.setDebtRemediationFunction(remediationBuilder.constantPerIssue(constantCost.replace("mn", "min"))); } else if ("Linear".equals(func)) { String linearFactor = getString(remediation, "linearFactor"); rule.setDebtRemediationFunction(remediationBuilder.linear(linearFactor.replace("mn", "min"))); } else { String linearFactor = getString(remediation, "linearFactor"); String linearOffset = getString(remediation, "linearOffset"); rule.setDebtRemediationFunction(remediationBuilder.linearWithOffset( linearFactor.replace("mn", "min"), linearOffset.replace("mn", "min"))); } if (remediation.get("linearDesc") != null) { rule.setGapDescription(getString(remediation, "linearDesc")); } }
private void setupSqaleModel(NewRule rule, Class<?> ruleClass) { SqaleConstantRemediation constant = AnnotationUtils.getAnnotation(ruleClass, SqaleConstantRemediation.class); SqaleLinearRemediation linear = AnnotationUtils.getAnnotation(ruleClass, SqaleLinearRemediation.class); SqaleLinearWithOffsetRemediation linearWithOffset = AnnotationUtils.getAnnotation(ruleClass, SqaleLinearWithOffsetRemediation.class); Set<Annotation> remediations = Sets.newHashSet(constant, linear, linearWithOffset); if (Iterables.size(Iterables.filter(remediations, Predicates.notNull())) > 1) { throw new IllegalArgumentException("Found more than one SQALE remediation annotations on " + ruleClass); } if (constant != null) { rule.setDebtRemediationFunction(rule.debtRemediationFunctions().constantPerIssue(constant.value())); } if (linear != null) { rule.setDebtRemediationFunction(rule.debtRemediationFunctions().linear(linear.coeff())); rule.setGapDescription(linear.effortToFixDescription()); } if (linearWithOffset != null) { rule.setDebtRemediationFunction( rule.debtRemediationFunctions().linearWithOffset(linearWithOffset.coeff(), linearWithOffset.offset())); rule.setGapDescription(linearWithOffset.effortToFixDescription()); } }
@Override public void define(Context context) { NewRepository repository = context.createRepository(REPOSITORY, JAVA_LANGUAGE).setName("My Custom Java Analyzer"); NewRule x1Rule = repository.createRule(RULE_ON_LINE_1.rule()) .setName("Stupid rule") .setHtmlDescription("Generates an issue on every line 1 of Java files") // optional tags .setTags("style", "stupid") // optional status. Default value is READY. .setStatus(RuleStatus.BETA) // default severity when the rule is activated on a Quality profile. Default value is MAJOR. .setSeverity(Severity.MINOR); x1Rule.setDebtRemediationFunction(x1Rule.debtRemediationFunctions().linearWithOffset("1h", "30min")); // don't forget to call done() to finalize the definition repository.done(); } }
private DebtRemediationFunction remediationFunction(final DebtRemediationFunctions drf) { if (this.func.startsWith("Constant")) { return drf.constantPerIssue(this.constantCost.replace("mn", "min")); } if ("Linear".equals(this.func)) { return drf.linear(this.coeff.replace("mn", "min")); } return drf.linearWithOffset(this.coeff.replace("mn", "min"), this.linearOffset.replace("mn", "min")); } }
public DebtRemediationFunction remediationFunction(DebtRemediationFunctions drf) { if (func.startsWith("Constant")) { return drf.constantPerIssue(constantCost.replace("mn", "min")); } if ("Linear".equals(func)) { return drf.linear(linearFactor.replace("mn", "min")); } return drf.linearWithOffset(linearFactor.replace("mn", "min"), linearOffset.replace("mn", "min")); } }
public DebtRemediationFunction remediationFunction(DebtRemediationFunctions debt) { if (func.startsWith("Constant")) { return debt.constantPerIssue(constantCost.replace("mn", "min")); } if ("Linear".equals(func)) { return debt.linear(linearFactor.replace("mn", "min")); } return debt.linearWithOffset(linearFactor.replace("mn", "min"), linearOffset.replace("mn", "min")); } }
public DebtRemediationFunction remediationFunction(DebtRemediationFunctions drf) { if (func.startsWith("Constant")) { return drf.constantPerIssue(constantCost.replace("mn", "min")); } if ("Linear".equals(func)) { return drf.linear(linearFactor.replace("mn", "min")); } return drf.linearWithOffset(linearFactor.replace("mn", "min"), linearOffset.replace("mn", "min")); } }
private static DebtRemediationFunction remediationFunction(DebtRemediationFunction.Type function, @Nullable String coefficient, @Nullable String offset, RulesDefinition.DebtRemediationFunctions functions, String repoKey, String ruleKey) { if (DebtRemediationFunction.Type.LINEAR.equals(function) && coefficient != null) { return functions.linear(coefficient); } else if (DebtRemediationFunction.Type.CONSTANT_ISSUE.equals(function) && offset != null) { return functions.constantPerIssue(offset); } else if (DebtRemediationFunction.Type.LINEAR_OFFSET.equals(function) && coefficient != null && offset != null) { return functions.linearWithOffset(coefficient, offset); } else { throw new IllegalArgumentException(String.format("Debt definition on rule '%s:%s' is invalid", repoKey, ruleKey)); } }
private static void defineDuplicatedBlocksRule(RulesDefinition.NewRepository repo) { RulesDefinition.NewRule rule = repo.createRule(CommonRuleKeys.DUPLICATED_BLOCKS); rule.setName("Source files should not have any duplicated blocks") .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")) .setGapDescription("number of duplicate blocks") .setSeverity(Severity.MAJOR); }
public DebtRemediationFunction remediationFunction(DebtRemediationFunctions drf) { if(func.startsWith("Constant")) { return drf.constantPerIssue(constantCost.replace("mn", "min")); } if("Linear".equals(func)) { return drf.linear(linearFactor.replace("mn", "min")); } return drf.linearWithOffset(linearFactor.replace("mn", "min"), linearOffset.replace("mn", "min")); } }
@Override public boolean setRemediation(NewRule sonarRule, SqaleRemediation remediation) { if(remediation instanceof SqaleLinearWithOffsetRemediation) { SqaleLinearWithOffsetRemediation linearWithOffsetRemediation = (SqaleLinearWithOffsetRemediation) remediation; sonarRule.setDebtRemediationFunction(sonarRule.debtRemediationFunctions().linearWithOffset(linearWithOffsetRemediation.getCoeff(), linearWithOffsetRemediation.getOffset())); sonarRule.setEffortToFixDescription(linearWithOffsetRemediation.getEffortToFixDescription()); return true; } else { return false; } }
private DebtRemediationFunction remediationFunction(DebtRemediationFunctions functions, String remediationFunction, String offset, String remediationFactor) { if ("CONSTANT_ISSUE".equalsIgnoreCase(remediationFunction)) { return functions.constantPerIssue(offset); } else if ("LINEAR".equalsIgnoreCase(remediationFunction)) { return functions.linear(remediationFactor); } else if ("LINEAR_OFFSET".equalsIgnoreCase(remediationFunction)) { return functions.linearWithOffset(remediationFactor, offset); } return null; }
.setHtmlDescription("Generate an issue on each module"); oneIssuePerModule .setDebtRemediationFunction(oneIssuePerModule.debtRemediationFunctions().linearWithOffset("25min", "1h")) .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."); .setType(RuleType.VULNERABILITY); oneVulnerabilityIssuePerModule .setDebtRemediationFunction(oneVulnerabilityIssuePerModule.debtRemediationFunctions().linearWithOffset("25min", "1h")) .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.");
@Override public void define(Context context) { NewRepository repo = context.createRepository("fake", "java"); NewRule rule1 = repo.createRule(RULE_KEY1.rule()) .setName("One") .setHtmlDescription("Description of One") .setSeverity(BLOCKER) .setInternalKey("config1") .setTags("tag1", "tag2", "tag3") .setScope(RuleScope.ALL) .setType(RuleType.CODE_SMELL) .setStatus(RuleStatus.BETA) .setGapDescription("squid.S115.effortToFix"); rule1.setDebtRemediationFunction(rule1.debtRemediationFunctions().linearWithOffset("5d", "10h")); rule1.createParam("param1").setDescription("parameter one").setDefaultValue("default1"); rule1.createParam("param2").setDescription("parameter two").setDefaultValue("default2"); repo.createRule(HOTSPOT_RULE_KEY.rule()) .setName("Hotspot") .setHtmlDescription("Minimal hotspot") .setType(RuleType.SECURITY_HOTSPOT) .addOwaspTop10(OwaspTop10.A1, OwaspTop10.A3) .addCwe(1, 123, 863); repo.createRule(RULE_KEY2.rule()) .setName("Two") .setHtmlDescription("Minimal rule"); repo.done(); } }
@Override public void define(Context context) { NewRepository repo = context.createRepository("fake", "java"); // almost all the attributes of rule1 are changed NewRule rule1 = repo.createRule(RULE_KEY1.rule()) .setName("One v2") .setHtmlDescription("Description of One v2") .setSeverity(INFO) .setInternalKey("config1 v2") // tag2 and tag3 removed, tag4 added .setTags("tag1", "tag4") .setType(RuleType.BUG) .setStatus(READY) .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"); // rule2 is dropped, rule3 is new repo.createRule(RULE_KEY3.rule()) .setName("Three") .setHtmlDescription("Rule Three"); repo.done(); } }
private static void defineDuplicatedBlocksRule(RulesDefinition.NewRepository repo) { RulesDefinition.NewRule rule = repo.createRule(CommonRuleKeys.DUPLICATED_BLOCKS); rule.setName("Source files should not have any duplicated blocks") .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")) .setGapDescription("number of duplicate blocks") .setSeverity(Severity.MAJOR); }