package org.sonar.xoo.rule;
import org.junit.Test;
-import org.sonar.api.server.rule.DebtRemediationFunction;
+import org.sonar.api.server.debt.DebtRemediationFunction;
import org.sonar.api.server.rule.RulesDefinition;
import static org.fest.assertions.Assertions.assertThat;
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.api.i18n;
-
-import org.sonar.api.BatchComponent;
-import org.sonar.api.ServerComponent;
-import org.sonar.api.rules.Rule;
-
-import javax.annotation.CheckForNull;
-
-import java.util.Locale;
-
-/**
- * {@link I18n}-companion component that provides translation facilities for rule names, descriptions and parameter names.
- *
- * @since 3.2
- * @deprecated in 4.1. Rules are not localized anymore. See http://jira.codehaus.org/browse/SONAR-4885
- */
-@Deprecated
-public interface RuleI18n extends ServerComponent, BatchComponent {
-
- /**
- * Returns the localized name of the rule identified by its repository key and rule key.
- * <br>
- * If the name is not found in the given locale, then the default name is returned (the English one).
- * This method could return null if no default name found. This is the cause for instance the copies rules.
- *
- * @param repositoryKey the repository key
- * @param ruleKey the rule key
- * @param locale not used
- * @return the translated name of the rule, or the default English one if the given locale is not supported, or null
- * @deprecated since 4.1. Rules are not localized anymore. See http://jira.codehaus.org/browse/SONAR-4885
- */
- @Deprecated
- @CheckForNull
- String getName(String repositoryKey, String ruleKey, Locale locale);
-
- /**
- * Returns the name of the rule identified by its repository key and rule key.
- * <br>
- * This method could return null if no default name found. This is the cause for instance the copies rules.
- *
- * @param repositoryKey the repository key
- * @param ruleKey the rule key
- * @return the nullable name of the rule
- * @since 4.1
- */
- @CheckForNull
- String getName(String repositoryKey, String ruleKey);
-
- /**
- * Returns the localized name or the name of the rule.
- * <br>
- * If the name is not found in the given locale, then the default name is returned (the English one).
- * It the default name is not found, then the rule name is returned.
- *
- * @param rule the rule
- * @param locale the locale to translate into
- * @return the translated name of the rule, or the default English one if the given locale is not supported, or the rule name.
- * @deprecated since 4.1. Rules are not localized anymore. See http://jira.codehaus.org/browse/SONAR-4885
- */
- @Deprecated
- @CheckForNull
- String getName(Rule rule, Locale locale);
-
- /**
- * Returns the name of the rule.
- * <br>
- * It the default name is not found, then the rule name is returned.
- *
- * @param rule the rule
- * @return the nullable name of the rule
- * @since 4.1
- */
- @CheckForNull
- String getName(Rule rule);
-
- /**
- * Returns the localized description of the rule identified by its repository key and rule key.
- * <br>
- * If the description is not found in the given locale, then the default description is returned (the English one).
- * As a rule must have a description (this is a constraint in Sonar), this method never returns null.
- *
- * @param repositoryKey the repository key
- * @param ruleKey the rule key
- * @param locale the locale to translate into
- * @return the translated description of the rule, or the default English one if the given locale is not supported
- * @deprecated since 4.1. Rules are not localized anymore. See http://jira.codehaus.org/browse/SONAR-4885
- */
- @Deprecated
- String getDescription(String repositoryKey, String ruleKey, Locale locale);
-
- /**
- * Returns the description of the rule identified by its repository key and rule key.
- * <br>
- * As a rule must have a description (this is a constraint in SonarQube), this method never returns null.
- *
- * @param repositoryKey the repository key
- * @param ruleKey the rule key
- * @return the description of the rule
- * @since 4.1
- */
- String getDescription(String repositoryKey, String ruleKey);
-
- /**
- * Returns the localized name of the rule parameter identified by the rules's key and repository key, and by the parameter key.
- * <br>
- * If the name is not found in the given locale, then the English translation is searched and return if found. Otherwise,
- * this method returns null (= if no translation can be found).
- *
- * @param repositoryKey the repository key
- * @param ruleKey the rule key
- * @param paramKey the parameter key
- * @param locale the locale to translate into
- * @return the translated name of the rule parameter, or the default English one if the given locale is not supported, or null if
- * no translation can be found.
- * @deprecated since 4.1. Rules are not localized anymore. See http://jira.codehaus.org/browse/SONAR-4885
- */
- @Deprecated
- @CheckForNull
- String getParamDescription(String repositoryKey, String ruleKey, String paramKey, Locale locale);
-
- /**
- * Returns the name of the rule parameter identified by the rules's key and repository key, and by the parameter key.
- *
- * @param repositoryKey the repository key
- * @param ruleKey the rule key
- * @param paramKey the parameter key
- * @return the nullable name of the rule parameter
- * @since 4.1
- */
- @CheckForNull
- String getParamDescription(String repositoryKey, String ruleKey, String paramKey);
-
-}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.api.i18n;
+
+import org.sonar.api.BatchComponent;
+import org.sonar.api.ServerComponent;
+import org.sonar.api.rules.Rule;
+
+import javax.annotation.CheckForNull;
+
+import java.util.Locale;
+
+/**
+ * {@link I18n}-companion component that provides translation facilities for rule names, descriptions and parameter names.
+ *
+ * @since 3.2
+ * @deprecated in 4.1. Rules are not localized anymore. See http://jira.codehaus.org/browse/SONAR-4885
+ */
+@Deprecated
+public interface RuleI18n extends ServerComponent, BatchComponent {
+
+ /**
+ * Returns the localized name of the rule identified by its repository key and rule key.
+ * <br>
+ * If the name is not found in the given locale, then the default name is returned (the English one).
+ * This method could return null if no default name found. This is the cause for instance the copies rules.
+ *
+ * @param repositoryKey the repository key
+ * @param ruleKey the rule key
+ * @param locale not used
+ * @return the translated name of the rule, or the default English one if the given locale is not supported, or null
+ * @deprecated since 4.1. Rules are not localized anymore. See http://jira.codehaus.org/browse/SONAR-4885
+ */
+ @Deprecated
+ @CheckForNull
+ String getName(String repositoryKey, String ruleKey, Locale locale);
+
+ /**
+ * Returns the name of the rule identified by its repository key and rule key.
+ * <br>
+ * This method could return null if no default name found. This is the cause for instance the copies rules.
+ *
+ * @param repositoryKey the repository key
+ * @param ruleKey the rule key
+ * @return the nullable name of the rule
+ * @since 4.1
+ */
+ @CheckForNull
+ String getName(String repositoryKey, String ruleKey);
+
+ /**
+ * Returns the localized name or the name of the rule.
+ * <br>
+ * If the name is not found in the given locale, then the default name is returned (the English one).
+ * It the default name is not found, then the rule name is returned.
+ *
+ * @param rule the rule
+ * @param locale the locale to translate into
+ * @return the translated name of the rule, or the default English one if the given locale is not supported, or the rule name.
+ * @deprecated since 4.1. Rules are not localized anymore. See http://jira.codehaus.org/browse/SONAR-4885
+ */
+ @Deprecated
+ @CheckForNull
+ String getName(Rule rule, Locale locale);
+
+ /**
+ * Returns the name of the rule.
+ * <br>
+ * It the default name is not found, then the rule name is returned.
+ *
+ * @param rule the rule
+ * @return the nullable name of the rule
+ * @since 4.1
+ */
+ @CheckForNull
+ String getName(Rule rule);
+
+ /**
+ * Returns the localized description of the rule identified by its repository key and rule key.
+ * <br>
+ * If the description is not found in the given locale, then the default description is returned (the English one).
+ * As a rule must have a description (this is a constraint in Sonar), this method never returns null.
+ *
+ * @param repositoryKey the repository key
+ * @param ruleKey the rule key
+ * @param locale the locale to translate into
+ * @return the translated description of the rule, or the default English one if the given locale is not supported
+ * @deprecated since 4.1. Rules are not localized anymore. See http://jira.codehaus.org/browse/SONAR-4885
+ */
+ @Deprecated
+ String getDescription(String repositoryKey, String ruleKey, Locale locale);
+
+ /**
+ * Returns the description of the rule identified by its repository key and rule key.
+ * <br>
+ * As a rule must have a description (this is a constraint in SonarQube), this method never returns null.
+ *
+ * @param repositoryKey the repository key
+ * @param ruleKey the rule key
+ * @return the description of the rule
+ * @since 4.1
+ */
+ String getDescription(String repositoryKey, String ruleKey);
+
+ /**
+ * Returns the localized name of the rule parameter identified by the rules's key and repository key, and by the parameter key.
+ * <br>
+ * If the name is not found in the given locale, then the English translation is searched and return if found. Otherwise,
+ * this method returns null (= if no translation can be found).
+ *
+ * @param repositoryKey the repository key
+ * @param ruleKey the rule key
+ * @param paramKey the parameter key
+ * @param locale the locale to translate into
+ * @return the translated name of the rule parameter, or the default English one if the given locale is not supported, or null if
+ * no translation can be found.
+ * @deprecated since 4.1. Rules are not localized anymore. See http://jira.codehaus.org/browse/SONAR-4885
+ */
+ @Deprecated
+ @CheckForNull
+ String getParamDescription(String repositoryKey, String ruleKey, String paramKey, Locale locale);
+
+ /**
+ * Returns the name of the rule parameter identified by the rules's key and repository key, and by the parameter key.
+ *
+ * @param repositoryKey the repository key
+ * @param ruleKey the rule key
+ * @param paramKey the parameter key
+ * @return the nullable name of the rule parameter
+ * @since 4.1
+ */
+ @CheckForNull
+ String getParamDescription(String repositoryKey, String ruleKey, String paramKey);
+
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.api.server.debt;
+
+import javax.annotation.CheckForNull;
+
+/**
+ * Function used to calculate the remediation cost of an issue. There are three types :
+ * <ul>
+ * <li>
+ * <b>Linear</b> - Each issue of the rule costs the same amount of time (factor) to fix.
+ * </li>
+ * <li>
+ * <b>Linear with offset</b> - It takes a certain amount of time to analyze the issues of such kind on the file (offset).
+ * Then, each issue of the rule costs the same amount of time (factor) to fix. Total remediation cost
+ * by file = offset + (number of issues x factor)
+ * </li>
+ * <li><b>Constant/issue</b> - The cost to fix all the issues of the rule is the same whatever the number of issues
+ * of this rule in the file. Total remediation cost by file = constant
+ * </li>
+ * </ul>
+ *
+ * @since 4.3
+ */
+public interface DebtRemediationFunction {
+
+ static enum Type {
+ LINEAR, LINEAR_OFFSET, CONSTANT_ISSUE
+ }
+
+ Type type();
+
+ /**
+ * Factor is set on types {@link Type#LINEAR} and {@link Type#LINEAR_OFFSET}, else it's null.
+ */
+ @CheckForNull
+ String factor();
+
+ /**
+ * Offset is set on types {@link Type#LINEAR_OFFSET} and {@link Type#CONSTANT_ISSUE}, else it's null.
+ */
+ @CheckForNull
+ String offset();
+
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.api.server.debt.internal;
+
+import com.google.common.base.Objects;
+import org.apache.commons.lang.StringUtils;
+import org.sonar.api.server.debt.DebtRemediationFunction;
+import org.sonar.api.utils.Duration;
+
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+
+public class DefaultDebtRemediationFunction implements DebtRemediationFunction {
+
+ private static final int HOURS_IN_DAY = 24;
+
+ private final Type type;
+ private final String factor;
+ private final String offset;
+
+ public DefaultDebtRemediationFunction(Type type, @Nullable String factor, @Nullable String offset) {
+ this.type = type;
+ // TODO validate factor and offset format
+ this.factor = sanitizeValue("factor", factor);
+ this.offset = sanitizeValue("offset", offset);
+ validate();
+ }
+
+ @CheckForNull
+ private String sanitizeValue(String label, @Nullable String s) {
+ if (StringUtils.isNotBlank(s)) {
+ try {
+ Duration duration = Duration.decode(s, HOURS_IN_DAY);
+ return duration.encode(HOURS_IN_DAY);
+ } catch (Exception e) {
+ throw new IllegalArgumentException(String.format("Invalid %s: %s", label, s), e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public Type type() {
+ return type;
+ }
+
+ @Override
+ @CheckForNull
+ public String factor() {
+ return factor;
+ }
+
+ @Override
+ @CheckForNull
+ public String offset() {
+ return offset;
+ }
+
+ private void validate() {
+ switch (type) {
+ case LINEAR:
+ if (this.factor == null || this.offset != null) {
+ throw new IllegalArgumentException(String.format("Only factor must be set on %s", this));
+ }
+ break;
+ case LINEAR_OFFSET:
+ if (this.factor == null || this.offset == null) {
+ throw new IllegalArgumentException(String.format("Both factor and offset are required on %s", this));
+ }
+ break;
+ case CONSTANT_ISSUE:
+ if (this.factor != null || this.offset == null) {
+ throw new IllegalArgumentException(String.format("Only offset must be set on %s", this));
+ }
+ break;
+ default:
+ throw new IllegalArgumentException(String.format("Unknown type on %s", this));
+ }
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ DefaultDebtRemediationFunction that = (DefaultDebtRemediationFunction) o;
+ if (factor != null ? !factor.equals(that.factor) : that.factor != null) {
+ return false;
+ }
+ if (offset != null ? !offset.equals(that.offset) : that.offset != null) {
+ return false;
+ }
+ return type == that.type;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = type.hashCode();
+ result = 31 * result + (factor != null ? factor.hashCode() : 0);
+ result = 31 * result + (offset != null ? offset.hashCode() : 0);
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return Objects.toStringHelper(DebtRemediationFunction.class)
+ .add("type", type)
+ .add("factor", factor)
+ .add("offset", offset)
+ .toString();
+ }
+}
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.api.server.rule;
-
-import javax.annotation.CheckForNull;
-
-/**
- * @since 4.3
- */
-public interface DebtRemediationFunction {
-
- static class ValidationException extends RuntimeException {
- public ValidationException(String message) {
- super(message);
- }
- }
-
- static enum Type {
- LINEAR, LINEAR_OFFSET, CONSTANT_ISSUE
- }
-
- Type type();
-
- @CheckForNull
- String factor();
-
- @CheckForNull
- String offset();
-
-}
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.api.server.rule;
-
-/**
- * Factory of {@link org.sonar.api.server.rule.DebtRemediationFunction}
- *
- * @since 4.3
- */
-public interface DebtRemediationFunctions {
-
- DebtRemediationFunction linear(String factor);
-
- DebtRemediationFunction linearWithOffset(String factor, String offset);
-
- DebtRemediationFunction constantPerIssue(String offset);
-}
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.api.server.rule;
-
-import org.apache.commons.lang.StringUtils;
-import org.apache.commons.lang.builder.EqualsBuilder;
-import org.apache.commons.lang.builder.HashCodeBuilder;
-import org.apache.commons.lang.builder.ReflectionToStringBuilder;
-import org.apache.commons.lang.builder.ToStringStyle;
-
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-
-class DefaultDebtRemediationFunction implements DebtRemediationFunction {
-
- private Type type;
- private String factor;
- private String offset;
-
- public DefaultDebtRemediationFunction(Type type, @Nullable String factor, @Nullable String offset) {
- this.type = type;
- // TODO validate factor and offset format
- this.factor = StringUtils.deleteWhitespace(factor);
- this.offset = StringUtils.deleteWhitespace(offset);
- validate();
- }
-
- @Override
- public Type type() {
- return type;
- }
-
- @Override
- @CheckForNull
- public String factor() {
- return factor;
- }
-
- @Override
- @CheckForNull
- public String offset() {
- return offset;
- }
-
- private void validate() {
- switch (type) {
- case LINEAR:
- if (this.factor == null || this.offset != null) {
- throw new ValidationException(String.format("%s is invalid, Linear remediation function should only define a factor", this));
- }
- break;
- case LINEAR_OFFSET:
- if (this.factor == null || this.offset == null) {
- throw new ValidationException(String.format("%s is invalid, Linear with offset remediation function should define both factor and offset", this));
- }
- break;
- case CONSTANT_ISSUE:
- if (this.factor != null || this.offset == null) {
- throw new ValidationException(String.format("%s is invalid, Constant/issue remediation function should only define an offset", this));
- }
- break;
- default:
- throw new IllegalStateException(String.format("Remediation function of %s is unknown", this));
- }
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- if (o == null || getClass() != o.getClass()) {
- return false;
- }
-
- DebtRemediationFunction that = (DebtRemediationFunction) o;
- return new EqualsBuilder()
- .append(type, that.type())
- .append(factor, that.factor())
- .append(offset, that.offset())
- .isEquals();
- }
-
- @Override
- public int hashCode() {
- return new HashCodeBuilder(15, 33)
- .append(type)
- .append(factor)
- .append(offset)
- .toHashCode();
- }
-
- @Override
- public String toString() {
- return new ReflectionToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE).toString();
- }
-}
* 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.api.server.rule;
+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;
-class DefaultDebtRemediationFunctions implements DebtRemediationFunctions {
+/**
+ * Factory of {@link org.sonar.api.server.debt.DebtRemediationFunction} that keeps
+ * a context of rule for better error messages. Used only when declaring rules.
+ *
+ * @see org.sonar.api.server.rule.RulesDefinition
+ */
+class DefaultDebtRemediationFunctions implements RulesDefinition.DebtRemediationFunctions {
private final String repoKey, key;
private DebtRemediationFunction create(DefaultDebtRemediationFunction.Type type, @Nullable String factor, @Nullable String offset) {
try {
return new DefaultDebtRemediationFunction(type, factor, offset);
- } catch (DefaultDebtRemediationFunction.ValidationException e) {
+ } catch (Exception e) {
throw MessageException.of(String.format("The rule '%s:%s' is invalid : %s ", this.repoKey, this.key, e.getMessage()));
}
}
public static void validate(String tag) {
if (!isValid(tag)) {
- throw new IllegalArgumentException(String.format("Tag '%s' is invalid. Rule tags accept only the following characters: a-z, 0-9, '+', '-', '#', '.'", tag));
+ throw new IllegalArgumentException(String.format("Tag '%s' is invalid. Rule tags accept only the characters: a-z, 0-9, '+', '-', '#', '.'", tag));
}
}
}
import org.sonar.api.ServerExtension;
import org.sonar.api.rule.RuleStatus;
import org.sonar.api.rule.Severity;
+import org.sonar.api.server.debt.DebtRemediationFunction;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
* this extension point in order to define the rules that it supports.
* <p/>
* This interface replaces the deprecated class org.sonar.api.rules.RuleRepository.
+ * <p/>
+ * <h3>How to use</h3>
+ * <pre>
+ * public class JsSquidRulesDefinition implements RulesDefinition {
+ *
+ * {@literal @}Override
+ * public void define(Context context) {
+ * NewRepository repository = context.createRepository("js_squid", "js").setName("Javascript Squid");
+ *
+ * // define a rule programmatically. Note that rules
+ * // could be loaded from files (JSON, XML, ...)
+ * NewRule x1Rule = repository.createRule("x1")
+ * .setName("No empty line")
+ * .setHtmlDescription("Generate an issue on empty lines")
+ *
+ * // 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
+ * .setDebtCharacteristic("INTEGRATION_TESTABILITY")
+ * .setDebtRemediationFunction(x1Rule.debtRemediationFunctions().linearWithOffset("1h", "30min"));
+ *
+ * x1Rule.createParam("acceptWhitespace")
+ * .setDefaultValue("false")
+ * .setType(RuleParamType.BOOLEAN)
+ * .setDescription("Accept whitespaces on the line");
+ *
+ * // don't forget to call done() to finalize the definition
+ * repository.done();
+ * }
+ * }
+ * </pre>
+ * <p/>
+ * If rules are declared in a XML file with the standard SonarQube format, then it can be loaded by using :
+ *
+ * <pre>
+ * public class JsSquidRulesDefinition implements RulesDefinition {
+ *
+ * private final RulesDefinitionXmlLoader xmlLoader;
+ *
+ * public JsSquidRulesDefinition(RulesDefinitionXmlLoader xmlLoader) {
+ * this.xmlLoader = xmlLoader;
+ * }
+ *
+ * {@literal @}Override
+ * public void define(Context context) {
+ * NewRepository repository = context.createRepository("js_squid", "js").setName("Javascript Squid");
+ * // see javadoc of RulesDefinitionXmlLoader for the format
+ * xmlLoader.load(repository, getClass().getResourceAsStream("/path/to/rules.xml"));
+ * repository.done();
+ * }
+ * }
+ * </pre>
+ *
+ * In the above example, XML file must contain name and description of each rule. If it's not the case, then the
+ * (deprecated) English bundles can be used :
+ *
+ * <pre>
+ * public class JsSquidRulesDefinition implements RulesDefinition {
+ *
+ * private final RulesDefinitionXmlLoader xmlLoader;
+ * private final RulesDefinitionI18nLoader i18nLoader;
+ *
+ * public JsSquidRulesDefinition(RulesDefinitionXmlLoader xmlLoader, RulesDefinitionI18nLoader i18nLoader) {
+ * this.xmlLoader = xmlLoader;
+ * this.i18nLoader = i18nLoader;
+ * }
+ *
+ * {@literal @}Override
+ * public void define(Context context) {
+ * NewRepository repository = context.createRepository("js_squid", "js").setName("Javascript Squid");
+ * xmlLoader.load(repository, getClass().getResourceAsStream("/path/to/rules.xml"));
+ * i18nLoader.load(repository);
+ * repository.done();
+ * }
+ * }
+ * </pre>
*
* @since 4.3
*/
}
}
+ interface DebtRemediationFunctions {
+ DebtRemediationFunction linear(String factor);
+
+ DebtRemediationFunction linearWithOffset(String factor, String offset);
+
+ DebtRemediationFunction constantPerIssue(String offset);
+ }
+
+
class NewRule {
private final String repoKey, key;
private String name, htmlDescription, internalKey, severity = Severity.MAJOR;
private String effortToFixDescription;
private final Set<String> tags = Sets.newTreeSet();
private final Map<String, NewParam> paramsByKey = Maps.newHashMap();
- private final DefaultDebtRemediationFunctions functions;
+ private final DebtRemediationFunctions functions;
private NewRule(String repoKey, String key) {
this.repoKey = repoKey;
return functions;
}
- public NewRule setDebtRemediationFunction(@Nullable DebtRemediationFunction debtRemediationFunction) {
- this.debtRemediationFunction = debtRemediationFunction;
+ /**
+ * @see #debtRemediationFunctions()
+ */
+ public NewRule setDebtRemediationFunction(@Nullable DebtRemediationFunction fn) {
+ this.debtRemediationFunction = fn;
return this;
}
- public NewRule setEffortToFixDescription(@Nullable String effortToFixDescription) {
- this.effortToFixDescription = effortToFixDescription;
+ public NewRule setEffortToFixDescription(@Nullable String s) {
+ this.effortToFixDescription = s;
return this;
}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.api.server.rule;
+
+import org.apache.commons.lang.StringUtils;
+import org.sonar.api.ServerComponent;
+import org.sonar.api.i18n.RuleI18n;
+
+/**
+ * Loads the English bundles of rules (name, description and parameters) that are
+ * deprecated since 4.2. It can be useful when loading existing XML files that
+ * do not contain rule names and descriptions.
+ * <p/>
+ * This class must be executed after declaring rules on {@link RulesDefinition.NewRepository}.
+ * <p/>
+ * Note that localization of rules was dropped in version 4.2. All texts are English.
+ *
+ * @see org.sonar.api.server.rule.RulesDefinition for an example
+ * @since 4.3
+ */
+public class RulesDefinitionI18nLoader implements ServerComponent {
+
+ private final RuleI18n i18n;
+
+ public RulesDefinitionI18nLoader(RuleI18n i18n) {
+ this.i18n = i18n;
+ }
+
+ /**
+ * Loads descriptions of rules and related rule parameters. Existing descriptions
+ * are overridden if English labels exist in bundles.
+ */
+ public void load(RulesDefinition.NewRepository repo) {
+ for (RulesDefinition.NewRule rule : repo.rules()) {
+ String name = i18n.getName(repo.key(), rule.key());
+ if (StringUtils.isNotBlank(name)) {
+ rule.setName(name);
+ }
+
+ String desc = i18n.getDescription(repo.key(), rule.key());
+ if (StringUtils.isNotBlank(desc)) {
+ rule.setHtmlDescription(desc);
+ }
+
+ for (RulesDefinition.NewParam param : rule.params()) {
+ String paramDesc = i18n.getParamDescription(repo.key(), rule.key(), param.key());
+ if (StringUtils.isNotBlank(paramDesc)) {
+ param.setDescription(paramDesc);
+ }
+ }
+ }
+ }
+}
* <p/>
* The classes implementing this extension point must be declared in {@link org.sonar.api.SonarPlugin#getExtensions()}.
*
- * <h2>How to use</h2>
+ * <h3>How to use</h3>
* <pre>
* public class HelloWs implements WebService {
* {@literal @}Override
* }
* }
* </pre>
- * <h2>How to unit test</h2>
+ * <h3>How to test</h3>
* <pre>
* public class HelloWsTest {
* WebService ws = new HelloWs();
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.api.server.debt;
+
+import org.junit.Ignore;
+import org.junit.Test;
+import org.sonar.api.server.debt.internal.DefaultDebtRemediationFunction;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.fest.assertions.Fail.fail;
+
+public class DefaultDebtRemediationFunctionTest {
+
+ @Test
+ public void create_linear() {
+ DebtRemediationFunction function = new DefaultDebtRemediationFunction(DebtRemediationFunction.Type.LINEAR, "10h", null);
+ assertThat(function.type()).isEqualTo(DefaultDebtRemediationFunction.Type.LINEAR);
+ assertThat(function.factor()).isEqualTo("10h");
+ assertThat(function.offset()).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.factor()).isEqualTo("10h");
+ assertThat(function.offset()).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.factor()).isNull();
+ assertThat(function.offset()).isEqualTo("10h");
+ }
+
+ @Test
+ public void sanitize_remediation_factor_and_offset() {
+ DebtRemediationFunction function = new DefaultDebtRemediationFunction(DebtRemediationFunction.Type.LINEAR_OFFSET, " 1 h ", " 10 min");
+
+ assertThat(function.factor()).isEqualTo("1h");
+ assertThat(function.offset()).isEqualTo("10min");
+ }
+
+ @Test
+ public void fail_to_create_linear_when_no_factor() {
+ try {
+ new DefaultDebtRemediationFunction(DebtRemediationFunction.Type.LINEAR, null, "10h");
+ fail();
+ } catch (IllegalArgumentException e) {
+ assertThat(e).hasMessage("Only factor must be set on DebtRemediationFunction{type=LINEAR, factor=null, offset=10h}");
+ }
+ }
+
+ @Test
+ public void fail_to_create_linear_when_offset() {
+ try {
+ new DefaultDebtRemediationFunction(DebtRemediationFunction.Type.LINEAR, "5min", "10h");
+ fail();
+ } catch (IllegalArgumentException e) {
+ assertThat(e).hasMessage("Only factor must be set on DebtRemediationFunction{type=LINEAR, factor=5min, offset=10h}");
+ }
+ }
+
+ @Test
+ public void fail_to_create_constant_per_issue_when_no_offset() {
+ try {
+ new DefaultDebtRemediationFunction(DebtRemediationFunction.Type.CONSTANT_ISSUE, "10h", null);
+ fail();
+ } catch (IllegalArgumentException e) {
+ assertThat(e).hasMessage("Only offset must be set on DebtRemediationFunction{type=CONSTANT_ISSUE, factor=10h, offset=null}");
+ }
+ }
+
+ @Test
+ public void fail_to_create_constant_per_issue_when_factor() {
+ try {
+ new DefaultDebtRemediationFunction(DebtRemediationFunction.Type.CONSTANT_ISSUE, "5min", "10h");
+ fail();
+ } catch (IllegalArgumentException e) {
+ assertThat(e).hasMessage("Only offset must be set on DebtRemediationFunction{type=CONSTANT_ISSUE, factor=5min, offset=10h}");
+ }
+ }
+
+ @Test
+ public void fail_to_create_linear_with_offset_when_no_factor() {
+ try {
+ new DefaultDebtRemediationFunction(DebtRemediationFunction.Type.LINEAR_OFFSET, "", "10h");
+ fail();
+ } catch (IllegalArgumentException e) {
+ assertThat(e).hasMessage("Both factor and offset are required on DebtRemediationFunction{type=LINEAR_OFFSET, factor=null, offset=10h}");
+ }
+ }
+
+ @Test
+ public void fail_to_create_linear_with_offset_when_no_offset() {
+ try {
+ new DefaultDebtRemediationFunction(DebtRemediationFunction.Type.LINEAR_OFFSET, "5min", "");
+ fail();
+ } catch (IllegalArgumentException e) {
+ assertThat(e).hasMessage("Both factor and offset are required on DebtRemediationFunction{type=LINEAR_OFFSET, factor=5min, offset=null}");
+ }
+ }
+
+ @Test
+ public void test_equals_and_hashcode() {
+ DebtRemediationFunction function = new DefaultDebtRemediationFunction(DebtRemediationFunction.Type.LINEAR_OFFSET, "10h", "5min");
+ DebtRemediationFunction functionWithSameValue = new DefaultDebtRemediationFunction(DebtRemediationFunction.Type.LINEAR_OFFSET, "10h", "5min");
+ DebtRemediationFunction functionWithDifferentType = new DefaultDebtRemediationFunction(DebtRemediationFunction.Type.CONSTANT_ISSUE, null, "5min");
+
+ assertThat(function).isEqualTo(function);
+ assertThat(function).isEqualTo(functionWithSameValue);
+ assertThat(function).isNotEqualTo(functionWithDifferentType);
+
+ assertThat(function).isNotEqualTo(new DefaultDebtRemediationFunction(DebtRemediationFunction.Type.LINEAR_OFFSET, "11h", "5min"));
+ assertThat(function).isNotEqualTo(new DefaultDebtRemediationFunction(DebtRemediationFunction.Type.LINEAR_OFFSET, "10h", "6min"));
+ assertThat(function).isNotEqualTo(new DefaultDebtRemediationFunction(DebtRemediationFunction.Type.LINEAR, "10h", null));
+ assertThat(function).isNotEqualTo(new DefaultDebtRemediationFunction(DebtRemediationFunction.Type.CONSTANT_ISSUE, null, "6min"));
+
+ assertThat(function.hashCode()).isEqualTo(function.hashCode());
+ assertThat(function.hashCode()).isEqualTo(functionWithSameValue.hashCode());
+ assertThat(function.hashCode()).isNotEqualTo(functionWithDifferentType.hashCode());
+ }
+
+ @Test
+ public void test_to_string() {
+ assertThat(new DefaultDebtRemediationFunction(DebtRemediationFunction.Type.LINEAR_OFFSET, "10h", "5min").toString())
+ .isEqualTo("DebtRemediationFunction{type=LINEAR_OFFSET, factor=10h, offset=5min}");
+ }
+
+ @Ignore
+ @Test
+ public void fail_if_bad_factor_format() {
+ try {
+ new DefaultDebtRemediationFunction(DebtRemediationFunction.Type.LINEAR, "foo", null);
+ fail();
+ } catch (IllegalArgumentException e) {
+ assertThat(e).hasMessage("TODO");
+ }
+
+ }
+}
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.api.server.rule;
-
-import org.junit.Test;
-
-import static org.fest.assertions.Assertions.assertThat;
-import static org.fest.assertions.Fail.fail;
-
-public class DefaultDebtRemediationFunctionTest {
-
- @Test
- public void create_linear() throws Exception {
- DebtRemediationFunction function = new DefaultDebtRemediationFunction(DebtRemediationFunction.Type.LINEAR, "10h", null);
- assertThat(function.type()).isEqualTo(DefaultDebtRemediationFunction.Type.LINEAR);
- assertThat(function.factor()).isEqualTo("10h");
- assertThat(function.offset()).isNull();
- }
-
- @Test
- public void create_linear_with_offset() throws Exception {
- DebtRemediationFunction function = new DefaultDebtRemediationFunction(DebtRemediationFunction.Type.LINEAR_OFFSET, "10h", "5min");
- assertThat(function.type()).isEqualTo(DefaultDebtRemediationFunction.Type.LINEAR_OFFSET);
- assertThat(function.factor()).isEqualTo("10h");
- assertThat(function.offset()).isEqualTo("5min");
- }
-
- @Test
- public void create_constant_per_issue() throws Exception {
- DebtRemediationFunction function = new DefaultDebtRemediationFunction(DebtRemediationFunction.Type.CONSTANT_ISSUE, null, "10h");
- assertThat(function.type()).isEqualTo(DefaultDebtRemediationFunction.Type.CONSTANT_ISSUE);
- assertThat(function.factor()).isNull();
- assertThat(function.offset()).isEqualTo("10h");
- }
-
- @Test
- public void sanitize_remediation_factor_and_offset() {
- DebtRemediationFunction function = new DefaultDebtRemediationFunction(DebtRemediationFunction.Type.LINEAR_OFFSET, " 1 h ", " 10 mi n");
-
- assertThat(function.factor()).isEqualTo("1h");
- assertThat(function.offset()).isEqualTo("10min");
- }
-
- @Test
- public void fail_to_create_linear_when_no_factor() throws Exception {
- try {
- new DefaultDebtRemediationFunction(DebtRemediationFunction.Type.LINEAR, null, "10h");
- fail();
- } catch (Exception e) {
- assertThat(e).isInstanceOf(DefaultDebtRemediationFunction.ValidationException.class);
- }
- }
-
- @Test
- public void fail_to_create_linear_when_offset() throws Exception {
- try {
- new DefaultDebtRemediationFunction(DebtRemediationFunction.Type.LINEAR, "5min", "10h");
- fail();
- } catch (Exception e) {
- assertThat(e).isInstanceOf(DefaultDebtRemediationFunction.ValidationException.class);
- }
- }
-
- @Test
- public void fail_to_create_constant_per_issue_when_no_offset() throws Exception {
- try {
- new DefaultDebtRemediationFunction(DebtRemediationFunction.Type.CONSTANT_ISSUE, "10h", null);
- fail();
- } catch (Exception e) {
- assertThat(e).isInstanceOf(DefaultDebtRemediationFunction.ValidationException.class);
- }
- }
-
- @Test
- public void fail_to_create_constant_per_issue_when_factor() throws Exception {
- try {
- new DefaultDebtRemediationFunction(DebtRemediationFunction.Type.CONSTANT_ISSUE, "5min", "10h");
- fail();
- } catch (Exception e) {
- assertThat(e).isInstanceOf(DefaultDebtRemediationFunction.ValidationException.class);
- }
- }
-
- @Test
- public void fail_to_create_linear_with_offset_when_no_factor() throws Exception {
- try {
- new DefaultDebtRemediationFunction(DebtRemediationFunction.Type.LINEAR_OFFSET, null, "10h");
- fail();
- } catch (Exception e) {
- assertThat(e).isInstanceOf(DefaultDebtRemediationFunction.ValidationException.class);
- }
- }
-
- @Test
- public void fail_to_create_linear_with_offset_when_no_offset() throws Exception {
- try {
- new DefaultDebtRemediationFunction(DebtRemediationFunction.Type.LINEAR_OFFSET, "5min", null);
- fail();
- } catch (Exception e) {
- assertThat(e).isInstanceOf(DefaultDebtRemediationFunction.ValidationException.class);
- }
- }
-
- @Test
- public void test_equals_and_hashcode() throws Exception {
- DebtRemediationFunction function = new DefaultDebtRemediationFunction(DebtRemediationFunction.Type.LINEAR_OFFSET, "10h", "5min");
- DebtRemediationFunction functionWithSameValue = new DefaultDebtRemediationFunction(DebtRemediationFunction.Type.LINEAR_OFFSET, "10h", "5min");
- DebtRemediationFunction functionWithDifferentType = new DefaultDebtRemediationFunction(DebtRemediationFunction.Type.CONSTANT_ISSUE, null, "5min");
-
- assertThat(function).isEqualTo(function);
- assertThat(function).isEqualTo(functionWithSameValue);
- assertThat(function).isNotEqualTo(functionWithDifferentType);
-
- assertThat(function).isNotEqualTo(new DefaultDebtRemediationFunction(DebtRemediationFunction.Type.LINEAR_OFFSET, "11h", "5min"));
- assertThat(function).isNotEqualTo(new DefaultDebtRemediationFunction(DebtRemediationFunction.Type.LINEAR_OFFSET, "10h", "6min"));
- assertThat(function).isNotEqualTo(new DefaultDebtRemediationFunction(DebtRemediationFunction.Type.LINEAR, "10h", null));
- assertThat(function).isNotEqualTo(new DefaultDebtRemediationFunction(DebtRemediationFunction.Type.CONSTANT_ISSUE, null, "6min"));
-
- assertThat(function.hashCode()).isEqualTo(function.hashCode());
- assertThat(function.hashCode()).isEqualTo(functionWithSameValue.hashCode());
- assertThat(function.hashCode()).isNotEqualTo(functionWithDifferentType.hashCode());
- }
-
- @Test
- public void test_to_string() throws Exception {
- assertThat(new DefaultDebtRemediationFunction(DebtRemediationFunction.Type.LINEAR_OFFSET, "10h", "5min").toString()).isNotNull();
- }
-
-}
RuleTagFormat.validate(" ");
fail();
} catch (IllegalArgumentException e) {
- assertThat(e).hasMessage("Tag ' ' is invalid. Rule tags accept only the following characters: a-z, 0-9, '+', '-', '#', '.'");
+ assertThat(e).hasMessage("Tag ' ' is invalid. Rule tags accept only the characters: a-z, 0-9, '+', '-', '#', '.'");
}
}
}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.api.server.rule;
+
+import org.junit.Test;
+import org.sonar.api.i18n.RuleI18n;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class RulesDefinitionI18nLoaderTest {
+
+ RuleI18n i18n = mock(RuleI18n.class);
+ RulesDefinitionI18nLoader loader = new RulesDefinitionI18nLoader(i18n);
+
+ @Test
+ public void complete_rule_name_and_description() throws Exception {
+ when(i18n.getName("squid", "S0001")).thenReturn("SOne");
+ when(i18n.getDescription("squid", "S0001")).thenReturn("S One");
+
+ RulesDefinition.Context context = new RulesDefinition.Context();
+ RulesDefinition.NewRepository repo = context.createRepository("squid", "java");
+ // rule without description
+ repo.createRule("S0001");
+
+ loader.load(repo);
+ repo.done();
+
+ RulesDefinition.Rule rule = context.repository("squid").rule("S0001");
+ assertThat(rule.name()).isEqualTo("SOne");
+ assertThat(rule.htmlDescription()).isEqualTo("S One");
+ }
+
+ @Test
+ public void do_not_override_if_no_bundle() throws Exception {
+ // i18n returns null values
+
+ RulesDefinition.Context context = new RulesDefinition.Context();
+ RulesDefinition.NewRepository repo = context.createRepository("squid", "java");
+ repo.createRule("S0001").setName("SOne").setHtmlDescription("S One");
+
+ loader.load(repo);
+ repo.done();
+
+ RulesDefinition.Rule rule = context.repository("squid").rule("S0001");
+ assertThat(rule.name()).isEqualTo("SOne");
+ assertThat(rule.htmlDescription()).isEqualTo("S One");
+ }
+
+ @Test
+ public void override_existing() throws Exception {
+ when(i18n.getName("squid", "S0001")).thenReturn("SOne");
+ when(i18n.getDescription("squid", "S0001")).thenReturn("S One");
+
+ RulesDefinition.Context context = new RulesDefinition.Context();
+ RulesDefinition.NewRepository repo = context.createRepository("squid", "java");
+ repo.createRule("S0001").setName("Bad").setHtmlDescription("Bad");
+
+ loader.load(repo);
+ repo.done();
+
+ RulesDefinition.Rule rule = context.repository("squid").rule("S0001");
+ assertThat(rule.name()).isEqualTo("SOne");
+ assertThat(rule.htmlDescription()).isEqualTo("S One");
+ }
+
+ @Test
+ public void complete_param_description() throws Exception {
+ when(i18n.getParamDescription("squid", "S0001", "max")).thenReturn("Maximum");
+
+ RulesDefinition.Context context = new RulesDefinition.Context();
+ RulesDefinition.NewRepository repo = context.createRepository("squid", "java");
+ repo.createRule("S0001").setName("SOne").setHtmlDescription("S One").createParam("max");
+
+ loader.load(repo);
+ repo.done();
+
+ RulesDefinition.Rule rule = context.repository("squid").rule("S0001");
+ assertThat(rule.param("max").description()).isEqualTo("Maximum");
+ }
+}
import org.junit.Test;
import org.sonar.api.rule.RuleStatus;
import org.sonar.api.rule.Severity;
+import org.sonar.api.server.debt.DebtRemediationFunction;
import java.net.URL;
@Test
public void define_rules() {
- RulesDefinition.NewRepository newFindbugs = context.createRepository("findbugs", "java");
- RulesDefinition.NewRule newFindbug = newFindbugs.createRule("NPE")
+ RulesDefinition.NewRepository newRepo = context.createRepository("findbugs", "java");
+ RulesDefinition.NewRule newRule = newRepo.createRule("NPE")
.setName("Detect NPE")
.setHtmlDescription("Detect <code>java.lang.NullPointerException</code>")
.setSeverity(Severity.BLOCKER)
.setEffortToFixDescription("squid.S115.effortToFix")
.setTags("one", "two")
.addTags("two", "three", "four");
- newFindbug.setDebtRemediationFunction(newFindbug.debtRemediationFunctions().linearWithOffset("1h", "10min"));
+ newRule.setDebtRemediationFunction(newRule.debtRemediationFunctions().linearWithOffset("1h", "10min"));
- newFindbugs.createRule("ABC").setName("ABC").setHtmlDescription("ABC");
- newFindbugs.done();
+ newRepo.createRule("ABC").setName("ABC").setHtmlDescription("ABC");
+ newRepo.done();
- RulesDefinition.Repository findbugs = context.repository("findbugs");
- assertThat(findbugs.rules()).hasSize(2);
-
- RulesDefinition.Rule npeRule = findbugs.rule("NPE");
- assertThat(npeRule.key()).isEqualTo("NPE");
- assertThat(npeRule.name()).isEqualTo("Detect NPE");
- assertThat(npeRule.severity()).isEqualTo(Severity.BLOCKER);
- assertThat(npeRule.htmlDescription()).isEqualTo("Detect <code>java.lang.NullPointerException</code>");
- assertThat(npeRule.tags()).containsOnly("one", "two", "three", "four");
- assertThat(npeRule.params()).isEmpty();
- assertThat(npeRule.internalKey()).isEqualTo("/something");
- assertThat(npeRule.template()).isFalse();
- assertThat(npeRule.status()).isEqualTo(RuleStatus.BETA);
- assertThat(npeRule.debtCharacteristic()).isEqualTo("COMPILER");
- assertThat(npeRule.debtRemediationFunction().type()).isEqualTo(DebtRemediationFunction.Type.LINEAR_OFFSET);
- assertThat(npeRule.debtRemediationFunction().factor()).isEqualTo("1h");
- assertThat(npeRule.debtRemediationFunction().offset()).isEqualTo("10min");
- assertThat(npeRule.effortToFixDescription()).isEqualTo("squid.S115.effortToFix");
- assertThat(npeRule.toString()).isEqualTo("[repository=findbugs, key=NPE]");
- assertThat(npeRule.repository()).isSameAs(findbugs);
+ RulesDefinition.Repository repo = context.repository("findbugs");
+ assertThat(repo.rules()).hasSize(2);
+
+ RulesDefinition.Rule rule = repo.rule("NPE");
+ assertThat(rule.key()).isEqualTo("NPE");
+ assertThat(rule.name()).isEqualTo("Detect NPE");
+ assertThat(rule.severity()).isEqualTo(Severity.BLOCKER);
+ assertThat(rule.htmlDescription()).isEqualTo("Detect <code>java.lang.NullPointerException</code>");
+ assertThat(rule.tags()).containsOnly("one", "two", "three", "four");
+ assertThat(rule.params()).isEmpty();
+ assertThat(rule.internalKey()).isEqualTo("/something");
+ assertThat(rule.template()).isFalse();
+ assertThat(rule.status()).isEqualTo(RuleStatus.BETA);
+ assertThat(rule.debtCharacteristic()).isEqualTo("COMPILER");
+ assertThat(rule.debtRemediationFunction().type()).isEqualTo(DebtRemediationFunction.Type.LINEAR_OFFSET);
+ assertThat(rule.debtRemediationFunction().factor()).isEqualTo("1h");
+ assertThat(rule.debtRemediationFunction().offset()).isEqualTo("10min");
+ assertThat(rule.effortToFixDescription()).isEqualTo("squid.S115.effortToFix");
+ assertThat(rule.toString()).isEqualTo("[repository=findbugs, key=NPE]");
+ assertThat(rule.repository()).isSameAs(repo);
// test equals() and hashCode()
- RulesDefinition.Rule otherRule = findbugs.rule("ABC");
- assertThat(npeRule).isEqualTo(npeRule).isNotEqualTo(otherRule).isNotEqualTo("NPE").isNotEqualTo(null);
- assertThat(npeRule.hashCode()).isEqualTo(npeRule.hashCode());
+ RulesDefinition.Rule otherRule = repo.rule("ABC");
+ assertThat(rule).isEqualTo(rule).isNotEqualTo(otherRule).isNotEqualTo("NPE").isNotEqualTo(null);
+ assertThat(rule.hashCode()).isEqualTo(rule.hashCode());
}
@Test
fail();
} catch (Exception e) {
assertThat(e).isInstanceOf(IllegalArgumentException.class)
- .hasMessage("Tag 'coding style' is invalid. Rule tags accept only the following characters: a-z, 0-9, '+', '-', '#', '.'");
+ .hasMessage("Tag 'coding style' is invalid. Rule tags accept only the characters: a-z, 0-9, '+', '-', '#', '.'");
}
}
@Test
public void load_rule_description_from_file() {
RulesDefinition.NewRepository newRepository = context.createRepository("findbugs", "java");
- newRepository.createRule("NPE").setName("NPE").setHtmlDescription(getClass().getResource("/org/sonar/api/server/rule/RuleDefinitionsTest/sample.html"));
+ newRepository.createRule("NPE").setName("NPE").setHtmlDescription(getClass().getResource("/org/sonar/api/server/rule/RulesDefinitionTest/sample.html"));
newRepository.done();
RulesDefinition.Rule rule = context.repository("findbugs").rule("NPE");
+++ /dev/null
-description of rule loaded from file
--- /dev/null
+description of rule loaded from file
import org.sonar.api.rule.RuleKey;
import org.sonar.api.server.debt.DebtCharacteristic;
import org.sonar.api.server.debt.internal.DefaultDebtCharacteristic;
-import org.sonar.api.server.rule.DebtRemediationFunction;
+import org.sonar.api.server.debt.DebtRemediationFunction;
import org.sonar.api.utils.System2;
import org.sonar.api.utils.ValidationMessages;
import org.sonar.core.permission.GlobalPermissions;
import org.sonar.api.ServerComponent;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.server.debt.DebtCharacteristic;
-import org.sonar.api.server.rule.DebtRemediationFunction;
+import org.sonar.api.server.debt.DebtRemediationFunction;
import org.xml.sax.InputSource;
import javax.annotation.CheckForNull;
import org.codehaus.staxmate.in.SMInputCursor;
import org.sonar.api.ServerComponent;
import org.sonar.api.rule.RuleKey;
-import org.sonar.api.server.rule.DebtRemediationFunction;
+import org.sonar.api.server.debt.DebtRemediationFunction;
import org.sonar.api.utils.Duration;
import org.sonar.api.utils.ValidationMessages;
import org.slf4j.LoggerFactory;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.rules.Rule;
-import org.sonar.api.server.rule.DebtRemediationFunction;
+import org.sonar.api.server.debt.DebtRemediationFunction;
import org.sonar.api.server.rule.RulesDefinition;
import org.sonar.api.utils.MessageException;
import org.sonar.api.utils.System2;
import org.mockito.stubbing.Answer;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.server.debt.internal.DefaultDebtCharacteristic;
-import org.sonar.api.server.rule.DebtRemediationFunction;
+import org.sonar.api.server.debt.DebtRemediationFunction;
import org.sonar.api.utils.DateUtils;
import org.sonar.api.utils.System2;
import org.sonar.api.utils.ValidationMessages;
import org.junit.Test;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.server.debt.internal.DefaultDebtCharacteristic;
-import org.sonar.api.server.rule.DebtRemediationFunction;
+import org.sonar.api.server.debt.DebtRemediationFunction;
import org.sonar.test.TestUtils;
import java.io.IOException;
import com.google.common.io.Resources;
import org.junit.Test;
import org.sonar.api.rule.RuleKey;
-import org.sonar.api.server.rule.DebtRemediationFunction;
+import org.sonar.api.server.debt.DebtRemediationFunction;
import org.sonar.api.utils.ValidationMessages;
import java.io.IOException;
RuleDebt ruleDebt = results.get(0);
assertThat(ruleDebt.characteristicKey()).isEqualTo("MEMORY_EFFICIENCY");
assertThat(ruleDebt.ruleKey()).isEqualTo(RuleKey.of("checkstyle", "Regexp"));
- assertThat(ruleDebt.function()).isEqualTo(org.sonar.api.server.rule.DebtRemediationFunction.Type.LINEAR);
+ assertThat(ruleDebt.function()).isEqualTo(DebtRemediationFunction.Type.LINEAR);
assertThat(ruleDebt.factor()).isEqualTo("3h");
assertThat(ruleDebt.offset()).isNull();
}
import org.sonar.api.rules.Rule;
import org.sonar.api.rules.RulePriority;
import org.sonar.api.rules.RuleRepository;
-import org.sonar.api.server.rule.DebtRemediationFunction;
+import org.sonar.api.server.debt.DebtRemediationFunction;
import org.sonar.api.server.rule.RulesDefinition;
import org.sonar.api.utils.ValidationMessages;
import org.sonar.core.i18n.RuleI18nManager;