@@ -70,7 +70,6 @@ import org.sonar.core.component.DefaultResourceTypes; | |||
import org.sonar.core.config.CorePropertyDefinitions; | |||
import org.sonar.core.extension.CoreExtensionRepositoryImpl; | |||
import org.sonar.core.extension.CoreExtensionsLoader; | |||
import org.sonar.core.i18n.RuleI18nManager; | |||
import org.sonar.core.platform.ComponentContainer; | |||
import org.sonar.core.platform.EditionProvider; | |||
import org.sonar.core.platform.Module; | |||
@@ -341,7 +340,6 @@ public class ComputeEngineContainerImpl implements ComputeEngineContainer { | |||
// depends on plugins | |||
ServerI18n.class, // used by RuleI18nManager | |||
RuleI18nManager.class, // used by DebtRulesXMLImporter | |||
Durations.class // used in Web Services and DebtCalculator | |||
); | |||
} |
@@ -123,7 +123,7 @@ public class ComputeEngineContainerImplTest { | |||
assertThat(picoContainer.getParent().getParent().getComponentAdapters()).hasSize( | |||
CONTAINER_ITSELF | |||
+ 6 // MigrationConfigurationModule | |||
+ 16 // level 2 | |||
+ 15 // level 2 | |||
); | |||
assertThat(picoContainer.getParent().getParent().getParent().getComponentAdapters()).hasSize( | |||
COMPONENTS_IN_LEVEL_1_AT_CONSTRUCTION |
@@ -1,216 +0,0 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2019 SonarSource SA | |||
* mailto:info AT sonarsource DOT com | |||
* | |||
* This program is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.server.rule; | |||
import com.google.common.base.Predicate; | |||
import com.google.common.collect.Iterables; | |||
import java.io.Reader; | |||
import java.util.Collection; | |||
import java.util.List; | |||
import javax.annotation.CheckForNull; | |||
import javax.annotation.Nonnull; | |||
import javax.annotation.Nullable; | |||
import org.apache.commons.io.IOUtils; | |||
import org.apache.commons.lang.StringUtils; | |||
import org.sonar.api.rule.RuleKey; | |||
import org.sonar.api.rule.RuleStatus; | |||
import org.sonar.api.rules.RuleParam; | |||
import org.sonar.api.rules.RuleRepository; | |||
import org.sonar.api.server.ServerSide; | |||
import org.sonar.api.server.debt.DebtRemediationFunction; | |||
import org.sonar.api.server.rule.RuleParamType; | |||
import org.sonar.api.server.rule.RulesDefinition; | |||
import org.sonar.api.utils.ValidationMessages; | |||
import org.sonar.api.utils.log.Logger; | |||
import org.sonar.api.utils.log.Loggers; | |||
import org.sonar.core.i18n.RuleI18nManager; | |||
import org.sonar.server.debt.DebtModelPluginRepository; | |||
import org.sonar.server.debt.DebtModelXMLExporter; | |||
import org.sonar.server.debt.DebtModelXMLExporter.RuleDebt; | |||
import org.sonar.server.debt.DebtRulesXMLImporter; | |||
import org.sonar.server.plugins.ServerPluginRepository; | |||
import static com.google.common.collect.Lists.newArrayList; | |||
/** | |||
* Inject deprecated RuleRepository into {@link org.sonar.api.server.rule.RulesDefinition} for backward-compatibility. | |||
*/ | |||
@ServerSide | |||
public class DeprecatedRulesDefinitionLoader { | |||
private static final Logger LOG = Loggers.get(DeprecatedRulesDefinitionLoader.class); | |||
private final RuleI18nManager i18n; | |||
private final RuleRepository[] repositories; | |||
private final DebtModelPluginRepository languageModelFinder; | |||
private final DebtRulesXMLImporter importer; | |||
private final ServerPluginRepository serverPluginRepository; | |||
public DeprecatedRulesDefinitionLoader(RuleI18nManager i18n, DebtModelPluginRepository languageModelFinder, DebtRulesXMLImporter importer, | |||
ServerPluginRepository serverPluginRepository, RuleRepository[] repositories) { | |||
this.i18n = i18n; | |||
this.serverPluginRepository = serverPluginRepository; | |||
this.repositories = repositories; | |||
this.languageModelFinder = languageModelFinder; | |||
this.importer = importer; | |||
} | |||
/** | |||
* Used when no deprecated repositories | |||
*/ | |||
public DeprecatedRulesDefinitionLoader(RuleI18nManager i18n, DebtModelPluginRepository languageModelFinder, DebtRulesXMLImporter importer, | |||
ServerPluginRepository serverPluginRepository) { | |||
this(i18n, languageModelFinder, importer, serverPluginRepository, new RuleRepository[0]); | |||
} | |||
void complete(RulesDefinition.Context context) { | |||
// Load rule debt definitions from xml files provided by plugin | |||
List<RuleDebt> ruleDebts = loadRuleDebtList(); | |||
for (RuleRepository repository : repositories) { | |||
context.setCurrentPluginKey(serverPluginRepository.getPluginKey(repository)); | |||
// RuleRepository API does not handle difference between new and extended repositories, | |||
RulesDefinition.NewRepository newRepository; | |||
if (context.repository(repository.getKey()) == null) { | |||
newRepository = context.createRepository(repository.getKey(), repository.getLanguage()); | |||
newRepository.setName(repository.getName()); | |||
} else { | |||
newRepository = context.extendRepository(repository.getKey(), repository.getLanguage()); | |||
} | |||
for (org.sonar.api.rules.Rule rule : repository.createRules()) { | |||
RulesDefinition.NewRule newRule = newRepository.createRule(rule.getKey()); | |||
newRule.setName(ruleName(repository.getKey(), rule)); | |||
newRule.setHtmlDescription(ruleDescription(repository.getKey(), rule)); | |||
newRule.setInternalKey(rule.getConfigKey()); | |||
newRule.setTemplate(rule.isTemplate()); | |||
newRule.setSeverity(rule.getSeverity().toString()); | |||
newRule.setStatus(rule.getStatus() == null ? RuleStatus.defaultStatus() : RuleStatus.valueOf(rule.getStatus())); | |||
newRule.setTags(rule.getTags()); | |||
for (RuleParam param : rule.getParams()) { | |||
RulesDefinition.NewParam newParam = newRule.createParam(param.getKey()); | |||
newParam.setDefaultValue(param.getDefaultValue()); | |||
newParam.setDescription(paramDescription(repository.getKey(), rule.getKey(), param)); | |||
newParam.setType(RuleParamType.parse(param.getType())); | |||
} | |||
updateRuleDebtDefinitions(newRule, repository.getKey(), rule.getKey(), ruleDebts); | |||
} | |||
newRepository.done(); | |||
} | |||
} | |||
private static void updateRuleDebtDefinitions(RulesDefinition.NewRule newRule, String repoKey, String ruleKey, List<RuleDebt> ruleDebts) { | |||
RuleDebt ruleDebt = findRequirement(ruleDebts, repoKey, ruleKey); | |||
if (ruleDebt != null) { | |||
newRule.setDebtRemediationFunction(remediationFunction(DebtRemediationFunction.Type.valueOf(ruleDebt.function()), | |||
ruleDebt.coefficient(), | |||
ruleDebt.offset(), | |||
newRule.debtRemediationFunctions(), | |||
repoKey, ruleKey)); | |||
} | |||
} | |||
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)); | |||
} | |||
} | |||
@CheckForNull | |||
private String ruleName(String repositoryKey, org.sonar.api.rules.Rule rule) { | |||
String name = i18n.getName(repositoryKey, rule.getKey()); | |||
if (StringUtils.isNotBlank(name)) { | |||
return name; | |||
} | |||
return StringUtils.defaultIfBlank(rule.getName(), null); | |||
} | |||
@CheckForNull | |||
private String ruleDescription(String repositoryKey, org.sonar.api.rules.Rule rule) { | |||
String description = i18n.getDescription(repositoryKey, rule.getKey()); | |||
if (StringUtils.isNotBlank(description)) { | |||
return description; | |||
} | |||
return StringUtils.defaultIfBlank(rule.getDescription(), null); | |||
} | |||
@CheckForNull | |||
private String paramDescription(String repositoryKey, String ruleKey, RuleParam param) { | |||
String desc = StringUtils.defaultIfEmpty( | |||
i18n.getParamDescription(repositoryKey, ruleKey, param.getKey()), | |||
param.getDescription()); | |||
return StringUtils.defaultIfBlank(desc, null); | |||
} | |||
public List<DebtModelXMLExporter.RuleDebt> loadRuleDebtList() { | |||
List<RuleDebt> ruleDebtList = newArrayList(); | |||
for (String pluginKey : getContributingPluginListWithoutSqale()) { | |||
ruleDebtList.addAll(loadRuleDebtsFromXml(pluginKey)); | |||
} | |||
return ruleDebtList; | |||
} | |||
public List<RuleDebt> loadRuleDebtsFromXml(String pluginKey) { | |||
Reader xmlFileReader = null; | |||
try { | |||
xmlFileReader = languageModelFinder.createReaderForXMLFile(pluginKey); | |||
ValidationMessages validationMessages = ValidationMessages.create(); | |||
List<RuleDebt> rules = importer.importXML(xmlFileReader, validationMessages); | |||
validationMessages.log(LOG); | |||
return rules; | |||
} finally { | |||
IOUtils.closeQuietly(xmlFileReader); | |||
} | |||
} | |||
private Collection<String> getContributingPluginListWithoutSqale() { | |||
Collection<String> pluginList = newArrayList(languageModelFinder.getContributingPluginList()); | |||
pluginList.remove(DebtModelPluginRepository.DEFAULT_MODEL); | |||
return pluginList; | |||
} | |||
@CheckForNull | |||
private static RuleDebt findRequirement(List<RuleDebt> requirements, final String repoKey, final String ruleKey) { | |||
return Iterables.find(requirements, new RuleDebtMatchRepoKeyAndRuleKey(repoKey, ruleKey), null); | |||
} | |||
private static class RuleDebtMatchRepoKeyAndRuleKey implements Predicate<RuleDebt> { | |||
private final String repoKey; | |||
private final String ruleKey; | |||
public RuleDebtMatchRepoKeyAndRuleKey(String repoKey, String ruleKey) { | |||
this.repoKey = repoKey; | |||
this.ruleKey = ruleKey; | |||
} | |||
@Override | |||
public boolean apply(@Nonnull RuleDebt input) { | |||
return input.ruleKey().equals(RuleKey.of(repoKey, ruleKey)); | |||
} | |||
} | |||
} |
@@ -29,14 +29,11 @@ import org.sonar.server.plugins.ServerPluginRepository; | |||
*/ | |||
public class RuleDefinitionsLoader { | |||
private final DeprecatedRulesDefinitionLoader deprecatedDefConverter; | |||
private final CommonRuleDefinitions coreCommonDefs; | |||
private final RulesDefinition[] pluginDefs; | |||
private final ServerPluginRepository serverPluginRepository; | |||
public RuleDefinitionsLoader(DeprecatedRulesDefinitionLoader deprecatedDefConverter, | |||
CommonRuleDefinitions coreCommonDefs, ServerPluginRepository serverPluginRepository, RulesDefinition[] pluginDefs) { | |||
this.deprecatedDefConverter = deprecatedDefConverter; | |||
public RuleDefinitionsLoader(CommonRuleDefinitions coreCommonDefs, ServerPluginRepository serverPluginRepository, RulesDefinition[] pluginDefs) { | |||
this.coreCommonDefs = coreCommonDefs; | |||
this.serverPluginRepository = serverPluginRepository; | |||
this.pluginDefs = pluginDefs; | |||
@@ -45,9 +42,8 @@ public class RuleDefinitionsLoader { | |||
/** | |||
* Used when no definitions at all. | |||
*/ | |||
public RuleDefinitionsLoader(DeprecatedRulesDefinitionLoader converter, | |||
CommonRuleDefinitions coreCommonDefs, ServerPluginRepository serverPluginRepository) { | |||
this(converter, coreCommonDefs, serverPluginRepository, new RulesDefinition[0]); | |||
public RuleDefinitionsLoader(CommonRuleDefinitions coreCommonDefs, ServerPluginRepository serverPluginRepository) { | |||
this(coreCommonDefs, serverPluginRepository, new RulesDefinition[0]); | |||
} | |||
public RulesDefinition.Context load() { | |||
@@ -56,7 +52,6 @@ public class RuleDefinitionsLoader { | |||
context.setCurrentPluginKey(serverPluginRepository.getPluginKey(pluginDefinition)); | |||
pluginDefinition.define(context); | |||
} | |||
deprecatedDefConverter.complete(context); | |||
context.setCurrentPluginKey(null); | |||
coreCommonDefs.define(context); | |||
return context; |
@@ -1,219 +0,0 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2019 SonarSource SA | |||
* mailto:info AT sonarsource DOT com | |||
* | |||
* This program is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.server.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; | |||
import org.mockito.runners.MockitoJUnitRunner; | |||
import org.sonar.api.rule.RuleKey; | |||
import org.sonar.api.rule.RuleStatus; | |||
import org.sonar.api.rule.Severity; | |||
import org.sonar.api.rules.Rule; | |||
import org.sonar.api.rules.RulePriority; | |||
import org.sonar.api.rules.RuleRepository; | |||
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; | |||
import org.sonar.api.impl.server.RulesDefinitionContext; | |||
import org.sonar.server.debt.DebtModelPluginRepository; | |||
import org.sonar.server.debt.DebtModelXMLExporter; | |||
import org.sonar.server.debt.DebtRulesXMLImporter; | |||
import org.sonar.server.plugins.ServerPluginRepository; | |||
import static com.google.common.collect.Lists.newArrayList; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
import static org.junit.Assert.fail; | |||
import static org.mockito.ArgumentMatchers.any; | |||
import static org.mockito.ArgumentMatchers.eq; | |||
import static org.mockito.Mockito.mock; | |||
import static org.mockito.Mockito.when; | |||
@RunWith(MockitoJUnitRunner.class) | |||
public class DeprecatedRulesDefinitionLoaderTest { | |||
@Mock | |||
RuleI18nManager i18n; | |||
@Mock | |||
DebtModelPluginRepository debtModelRepository; | |||
@Mock | |||
DebtRulesXMLImporter importer; | |||
@Mock | |||
ServerPluginRepository pluginRepository; | |||
static class CheckstyleRules extends RuleRepository { | |||
public CheckstyleRules() { | |||
super("checkstyle", "java"); | |||
setName("Checkstyle"); | |||
} | |||
@Override | |||
public List<Rule> createRules() { | |||
Rule rule = Rule.create("checkstyle", "ConstantName", "Constant Name"); | |||
rule.setDescription("Checks that constant names conform to the specified format"); | |||
rule.setConfigKey("Checker/TreeWalker/ConstantName"); | |||
rule.setSeverity(RulePriority.BLOCKER); | |||
rule.setStatus(Rule.STATUS_BETA); | |||
rule.setTags(new String[] {"style", "clumsy"}); | |||
rule.createParameter("format").setDescription("Regular expression").setDefaultValue("A-Z").setType("REGULAR_EXPRESSION"); | |||
return Arrays.asList(rule); | |||
} | |||
} | |||
static class UseBundles extends RuleRepository { | |||
public UseBundles() { | |||
super("checkstyle", "java"); | |||
setName("Checkstyle"); | |||
} | |||
@Override | |||
public List<Rule> createRules() { | |||
Rule rule = Rule.create("checkstyle", "ConstantName"); | |||
rule.createParameter("format"); | |||
return Arrays.asList(rule); | |||
} | |||
} | |||
@Test | |||
public void wrap_deprecated_rule_repositories() { | |||
RulesDefinition.Context context = new RulesDefinitionContext(); | |||
CheckstyleRules checkstyleRules = new CheckstyleRules(); | |||
when(pluginRepository.getPluginKey(checkstyleRules)).thenReturn("unittest"); | |||
new DeprecatedRulesDefinitionLoader(i18n, debtModelRepository, importer, pluginRepository, new RuleRepository[] {checkstyleRules}).complete(context); | |||
assertThat(context.repositories()).hasSize(1); | |||
RulesDefinition.Repository checkstyle = context.repository("checkstyle"); | |||
assertThat(checkstyle).isNotNull(); | |||
assertThat(checkstyle.key()).isEqualTo("checkstyle"); | |||
assertThat(checkstyle.name()).isEqualTo("Checkstyle"); | |||
assertThat(checkstyle.language()).isEqualTo("java"); | |||
assertThat(checkstyle.rules()).hasSize(1); | |||
RulesDefinition.Rule rule = checkstyle.rule("ConstantName"); | |||
assertThat(rule).isNotNull(); | |||
assertThat(rule.key()).isEqualTo("ConstantName"); | |||
assertThat(rule.pluginKey()).isEqualTo("unittest"); | |||
assertThat(rule.name()).isEqualTo("Constant Name"); | |||
assertThat(rule.htmlDescription()).isEqualTo("Checks that constant names conform to the specified format"); | |||
assertThat(rule.severity()).isEqualTo(Severity.BLOCKER); | |||
assertThat(rule.internalKey()).isEqualTo("Checker/TreeWalker/ConstantName"); | |||
assertThat(rule.status()).isEqualTo(RuleStatus.BETA); | |||
assertThat(rule.tags()).containsOnly("style", "clumsy"); | |||
assertThat(rule.params()).hasSize(1); | |||
RulesDefinition.Param param = rule.param("format"); | |||
assertThat(param).isNotNull(); | |||
assertThat(param.key()).isEqualTo("format"); | |||
assertThat(param.name()).isEqualTo("format"); | |||
assertThat(param.description()).isEqualTo("Regular expression"); | |||
assertThat(param.defaultValue()).isEqualTo("A-Z"); | |||
} | |||
@Test | |||
public void emulate_the_day_deprecated_api_can_be_dropped() { | |||
RulesDefinition.Context context = new RulesDefinitionContext(); | |||
// no more RuleRepository ! | |||
new DeprecatedRulesDefinitionLoader(i18n, debtModelRepository, importer, pluginRepository); | |||
assertThat(context.repositories()).isEmpty(); | |||
} | |||
@Test | |||
public void use_l10n_bundles() { | |||
RulesDefinition.Context context = new RulesDefinitionContext(); | |||
when(i18n.getName("checkstyle", "ConstantName")).thenReturn("Constant Name"); | |||
when(i18n.getDescription("checkstyle", "ConstantName")).thenReturn("Checks that constant names conform to the specified format"); | |||
when(i18n.getParamDescription("checkstyle", "ConstantName", "format")).thenReturn("Regular expression"); | |||
new DeprecatedRulesDefinitionLoader(i18n, debtModelRepository, importer, pluginRepository, new RuleRepository[] {new UseBundles()}).complete(context); | |||
RulesDefinition.Repository checkstyle = context.repository("checkstyle"); | |||
RulesDefinition.Rule rule = checkstyle.rule("ConstantName"); | |||
assertThat(rule.key()).isEqualTo("ConstantName"); | |||
assertThat(rule.name()).isEqualTo("Constant Name"); | |||
assertThat(rule.htmlDescription()).isEqualTo("Checks that constant names conform to the specified format"); | |||
RulesDefinition.Param param = rule.param("format"); | |||
assertThat(param.key()).isEqualTo("format"); | |||
assertThat(param.name()).isEqualTo("format"); | |||
assertThat(param.description()).isEqualTo("Regular expression"); | |||
} | |||
@Test | |||
public void define_rule_debt() { | |||
RulesDefinition.Context context = new RulesDefinitionContext(); | |||
List<DebtModelXMLExporter.RuleDebt> ruleDebts = newArrayList( | |||
new DebtModelXMLExporter.RuleDebt() | |||
.setRuleKey(RuleKey.of("checkstyle", "ConstantName")) | |||
.setFunction(DebtRemediationFunction.Type.LINEAR_OFFSET.name()) | |||
.setCoefficient("1d") | |||
.setOffset("10min")); | |||
Reader javaModelReader = mock(Reader.class); | |||
when(debtModelRepository.createReaderForXMLFile("java")).thenReturn(javaModelReader); | |||
when(debtModelRepository.getContributingPluginList()).thenReturn(newArrayList("java")); | |||
when(importer.importXML(eq(javaModelReader), any(ValidationMessages.class))).thenReturn(ruleDebts); | |||
new DeprecatedRulesDefinitionLoader(i18n, debtModelRepository, importer, pluginRepository, new RuleRepository[] {new CheckstyleRules()}).complete(context); | |||
assertThat(context.repositories()).hasSize(1); | |||
RulesDefinition.Repository checkstyle = context.repository("checkstyle"); | |||
assertThat(checkstyle.rules()).hasSize(1); | |||
RulesDefinition.Rule rule = checkstyle.rule("ConstantName"); | |||
assertThat(rule).isNotNull(); | |||
assertThat(rule.key()).isEqualTo("ConstantName"); | |||
assertThat(rule.debtRemediationFunction().type()).isEqualTo(DebtRemediationFunction.Type.LINEAR_OFFSET); | |||
assertThat(rule.debtRemediationFunction().gapMultiplier()).isEqualTo("1d"); | |||
assertThat(rule.debtRemediationFunction().baseEffort()).isEqualTo("10min"); | |||
} | |||
@Test | |||
public void fail_on_invalid_rule_debt() { | |||
RulesDefinition.Context context = new RulesDefinitionContext(); | |||
List<DebtModelXMLExporter.RuleDebt> ruleDebts = newArrayList( | |||
new DebtModelXMLExporter.RuleDebt() | |||
.setRuleKey(RuleKey.of("checkstyle", "ConstantName")) | |||
.setFunction(DebtRemediationFunction.Type.LINEAR_OFFSET.name()) | |||
.setCoefficient("1d")); | |||
Reader javaModelReader = mock(Reader.class); | |||
when(debtModelRepository.createReaderForXMLFile("java")).thenReturn(javaModelReader); | |||
when(debtModelRepository.getContributingPluginList()).thenReturn(newArrayList("java")); | |||
when(importer.importXML(eq(javaModelReader), any(ValidationMessages.class))).thenReturn(ruleDebts); | |||
try { | |||
new DeprecatedRulesDefinitionLoader(i18n, debtModelRepository, importer, pluginRepository, new RuleRepository[] {new CheckstyleRules()}).complete(context); | |||
fail(); | |||
} catch (Exception e) { | |||
assertThat(e).isInstanceOf(IllegalArgumentException.class); | |||
} | |||
assertThat(context.repositories()).isEmpty(); | |||
} | |||
} |
@@ -1019,7 +1019,7 @@ public class RegisterRulesTest { | |||
private void execute(RulesDefinition... defs) { | |||
ServerPluginRepository pluginRepository = mock(ServerPluginRepository.class); | |||
when(pluginRepository.getPluginKey(any(RulesDefinition.class))).thenReturn(FAKE_PLUGIN_KEY); | |||
RuleDefinitionsLoader loader = new RuleDefinitionsLoader(mock(DeprecatedRulesDefinitionLoader.class), mock(CommonRuleDefinitionsImpl.class), pluginRepository, | |||
RuleDefinitionsLoader loader = new RuleDefinitionsLoader(mock(CommonRuleDefinitionsImpl.class), pluginRepository, | |||
defs); | |||
Languages languages = mock(Languages.class); | |||
when(languages.get(any())).thenReturn(mock(Language.class)); |
@@ -31,7 +31,7 @@ public class RuleDefinitionsLoaderTest { | |||
@Test | |||
public void no_definitions() { | |||
CommonRuleDefinitions commonRulesDefinitions = mock(CommonRuleDefinitions.class); | |||
RulesDefinition.Context context = new RuleDefinitionsLoader(mock(DeprecatedRulesDefinitionLoader.class), commonRulesDefinitions, mock(ServerPluginRepository.class)).load(); | |||
RulesDefinition.Context context = new RuleDefinitionsLoader(commonRulesDefinitions, mock(ServerPluginRepository.class)).load(); | |||
assertThat(context.repositories()).isEmpty(); | |||
} | |||
@@ -39,7 +39,7 @@ public class RuleDefinitionsLoaderTest { | |||
@Test | |||
public void load_definitions() { | |||
CommonRuleDefinitions commonRulesDefinitions = mock(CommonRuleDefinitions.class); | |||
RulesDefinition.Context context = new RuleDefinitionsLoader(mock(DeprecatedRulesDefinitionLoader.class), commonRulesDefinitions, mock(ServerPluginRepository.class), | |||
RulesDefinition.Context context = new RuleDefinitionsLoader(commonRulesDefinitions, mock(ServerPluginRepository.class), | |||
new RulesDefinition[] { | |||
new FindbugsDefinitions(), new SquidDefinitions() | |||
}).load(); | |||
@@ -52,7 +52,7 @@ public class RuleDefinitionsLoaderTest { | |||
@Test | |||
public void define_common_rules() { | |||
CommonRuleDefinitions commonRulesDefinitions = new FakeCommonRuleDefinitions(); | |||
RulesDefinition.Context context = new RuleDefinitionsLoader(mock(DeprecatedRulesDefinitionLoader.class), commonRulesDefinitions, mock(ServerPluginRepository.class), | |||
RulesDefinition.Context context = new RuleDefinitionsLoader(commonRulesDefinitions, mock(ServerPluginRepository.class), | |||
new RulesDefinition[] { | |||
new SquidDefinitions() | |||
}).load(); | |||
@@ -68,7 +68,7 @@ public class RuleDefinitionsLoaderTest { | |||
@Test | |||
public void plugin_common_rules_are_overridden() { | |||
CommonRuleDefinitions commonRulesDefinitions = new FakeCommonRuleDefinitions(); | |||
RulesDefinition.Context context = new RuleDefinitionsLoader(mock(DeprecatedRulesDefinitionLoader.class), commonRulesDefinitions, mock(ServerPluginRepository.class), | |||
RulesDefinition.Context context = new RuleDefinitionsLoader(commonRulesDefinitions, mock(ServerPluginRepository.class), | |||
new RulesDefinition[] { | |||
new PluginCommonRuleDefinitions() | |||
}).load(); |
@@ -21,7 +21,6 @@ package org.sonar.server.platform.platformlevel; | |||
import org.sonar.api.utils.Durations; | |||
import org.sonar.core.extension.CoreExtensionsInstaller; | |||
import org.sonar.core.i18n.RuleI18nManager; | |||
import org.sonar.core.platform.ComponentContainer; | |||
import org.sonar.core.platform.PluginClassloaderFactory; | |||
import org.sonar.core.platform.PluginLoader; | |||
@@ -81,7 +80,6 @@ public class PlatformLevel2 extends PlatformLevel { | |||
// depends on plugins | |||
ServerI18n.class, | |||
RuleI18nManager.class, | |||
OfficialDistribution.class); | |||
@@ -172,7 +172,6 @@ import org.sonar.server.qualityprofile.index.ActiveRuleIndexer; | |||
import org.sonar.server.qualityprofile.ws.QProfilesWsModule; | |||
import org.sonar.server.root.ws.RootWsModule; | |||
import org.sonar.server.rule.CommonRuleDefinitionsImpl; | |||
import org.sonar.server.rule.DeprecatedRulesDefinitionLoader; | |||
import org.sonar.server.rule.RuleCreator; | |||
import org.sonar.server.rule.RuleDefinitionsLoader; | |||
import org.sonar.server.rule.RuleUpdater; | |||
@@ -303,7 +302,6 @@ public class PlatformLevel4 extends PlatformLevel { | |||
AnnotationRuleParser.class, | |||
XMLRuleParser.class, | |||
WebServerRuleFinderImpl.class, | |||
DeprecatedRulesDefinitionLoader.class, | |||
RuleDefinitionsLoader.class, | |||
CommonRuleDefinitionsImpl.class, | |||
RulesDefinitionXmlLoader.class, |
@@ -1,134 +0,0 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2019 SonarSource SA | |||
* mailto:info AT sonarsource DOT com | |||
* | |||
* This program is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.core.i18n; | |||
import java.util.Locale; | |||
import javax.annotation.CheckForNull; | |||
import org.apache.commons.lang.StringUtils; | |||
import org.sonar.api.ce.ComputeEngineSide; | |||
import org.sonar.api.i18n.RuleI18n; | |||
import org.sonar.api.rules.Rule; | |||
import org.sonar.api.server.ServerSide; | |||
/** | |||
* @deprecated in 4.1. Rules are not localized anymore. See http://jira.sonarsource.com/browse/SONAR-4885 | |||
*/ | |||
@Deprecated | |||
@ServerSide | |||
@ComputeEngineSide | |||
public class RuleI18nManager implements RuleI18n { | |||
private static final String NAME_SUFFIX = ".name"; | |||
private static final String RULE_PREFIX = "rule."; | |||
private DefaultI18n defaultI18n; | |||
public RuleI18nManager(DefaultI18n defaultI18n) { | |||
this.defaultI18n = defaultI18n; | |||
} | |||
/** | |||
* @deprecated in 4.1. Rules are not localized anymore. See http://jira.sonarsource.com/browse/SONAR-4885 | |||
*/ | |||
@Override | |||
@Deprecated | |||
public String getName(String repositoryKey, String ruleKey, Locale locale) { | |||
return getName(repositoryKey, ruleKey); | |||
} | |||
/** | |||
* @deprecated in 4.1. Rules are not localized anymore. See http://jira.sonarsource.com/browse/SONAR-4885 | |||
*/ | |||
@Override | |||
@Deprecated | |||
public String getName(Rule rule, Locale locale) { | |||
return getName(rule); | |||
} | |||
/** | |||
* @deprecated in 4.1. Rules are not localized anymore. See http://jira.sonarsource.com/browse/SONAR-4885 | |||
*/ | |||
@Override | |||
@Deprecated | |||
public String getDescription(String repositoryKey, String ruleKey, Locale locale) { | |||
return getDescription(repositoryKey, ruleKey); | |||
} | |||
/** | |||
* @deprecated in 4.1. Rules are not localized anymore. See http://jira.sonarsource.com/browse/SONAR-4885 | |||
*/ | |||
@Override | |||
@Deprecated | |||
public String getParamDescription(String repositoryKey, String ruleKey, String paramKey, Locale locale) { | |||
return getParamDescription(repositoryKey, ruleKey, paramKey); | |||
} | |||
@Override | |||
@CheckForNull | |||
public String getName(String repositoryKey, String ruleKey) { | |||
return message(repositoryKey, ruleKey, NAME_SUFFIX); | |||
} | |||
@Override | |||
@CheckForNull | |||
public String getName(Rule rule) { | |||
String name = message(rule.getRepositoryKey(), rule.getKey(), NAME_SUFFIX); | |||
return name != null ? name : rule.getName(); | |||
} | |||
@Override | |||
public String getDescription(String repositoryKey, String ruleKey) { | |||
String relatedProperty = new StringBuilder().append(RULE_PREFIX).append(repositoryKey).append(".").append(ruleKey).append(NAME_SUFFIX).toString(); | |||
String ruleDescriptionFilePath = "rules/" + repositoryKey + "/" + ruleKey + ".html"; | |||
String description = defaultI18n.messageFromFile(Locale.ENGLISH, ruleDescriptionFilePath, relatedProperty); | |||
if (description == null) { | |||
// Following line is to ensure backward compatibility (SONAR-3319) | |||
description = lookUpDescriptionInFormerLocation(ruleKey, relatedProperty); | |||
} | |||
return description; | |||
} | |||
/* | |||
* Method used to ensure backward compatibility for language plugins that store HTML rule description files in the former | |||
* location (which was used prior to Sonar 3.0). | |||
* | |||
* See http://jira.sonarsource.com/browse/SONAR-3319 | |||
*/ | |||
private String lookUpDescriptionInFormerLocation(String ruleKey, String relatedProperty) { | |||
return defaultI18n.messageFromFile(Locale.ENGLISH, ruleKey + ".html", relatedProperty); | |||
} | |||
@Override | |||
@CheckForNull | |||
public String getParamDescription(String repositoryKey, String ruleKey, String paramKey) { | |||
return message(repositoryKey, ruleKey, ".param." + paramKey); | |||
} | |||
@CheckForNull | |||
String message(String repositoryKey, String ruleKey, String suffix) { | |||
String propertyKey = new StringBuilder().append(RULE_PREFIX).append(repositoryKey).append(".").append(ruleKey).append(suffix).toString(); | |||
return defaultI18n.message(Locale.ENGLISH, propertyKey, null); | |||
} | |||
static boolean isRuleProperty(String propertyKey) { | |||
return StringUtils.startsWith(propertyKey, RULE_PREFIX) && StringUtils.endsWith(propertyKey, NAME_SUFFIX) && !propertyKey.contains(".param."); | |||
} | |||
} |
@@ -1,113 +0,0 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2019 SonarSource SA | |||
* mailto:info AT sonarsource DOT com | |||
* | |||
* This program is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.core.i18n; | |||
import java.util.Locale; | |||
import org.junit.Test; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
import static org.mockito.Mockito.mock; | |||
import static org.mockito.Mockito.verify; | |||
import static org.mockito.Mockito.verifyNoMoreInteractions; | |||
import static org.mockito.Mockito.when; | |||
public class RuleI18nManagerTest { | |||
@Test | |||
public void shouldGetName() { | |||
DefaultI18n i18n = mock(DefaultI18n.class); | |||
RuleI18nManager ruleI18n = new RuleI18nManager(i18n); | |||
ruleI18n.getName("checkstyle", "com.puppycrawl.tools.checkstyle.checks.annotation.AnnotationUseStyleCheck", Locale.ENGLISH); | |||
String propertyKey = "rule.checkstyle.com.puppycrawl.tools.checkstyle.checks.annotation.AnnotationUseStyleCheck.name"; | |||
verify(i18n).message(Locale.ENGLISH, propertyKey, null /* no default value */); | |||
verifyNoMoreInteractions(i18n); | |||
} | |||
@Test | |||
public void shouldGetParamDescription() { | |||
DefaultI18n i18n = mock(DefaultI18n.class); | |||
RuleI18nManager ruleI18n = new RuleI18nManager(i18n); | |||
ruleI18n.getParamDescription("checkstyle", "com.puppycrawl.tools.checkstyle.checks.annotation.AnnotationUseStyleCheck", "pattern", Locale.ENGLISH); | |||
String propertyKey = "rule.checkstyle.com.puppycrawl.tools.checkstyle.checks.annotation.AnnotationUseStyleCheck.param.pattern"; | |||
verify(i18n).message(Locale.ENGLISH, propertyKey, null /* no default value */); | |||
verifyNoMoreInteractions(i18n); | |||
} | |||
@Test | |||
public void shouldGetDescriptionFromFile() { | |||
String propertyKeyForName = "rule.checkstyle.com.puppycrawl.tools.checkstyle.checks.annotation.AnnotationUseStyleCheck.name"; | |||
DefaultI18n i18n = mock(DefaultI18n.class); | |||
when(i18n.messageFromFile(Locale.ENGLISH, "rules/checkstyle/com.puppycrawl.tools.checkstyle.checks.annotation.AnnotationUseStyleCheck.html", propertyKeyForName)).thenReturn( | |||
"Description"); | |||
RuleI18nManager ruleI18n = new RuleI18nManager(i18n); | |||
String description = ruleI18n.getDescription("checkstyle", "com.puppycrawl.tools.checkstyle.checks.annotation.AnnotationUseStyleCheck", Locale.ENGLISH); | |||
assertThat(description).isEqualTo("Description"); | |||
verify(i18n).messageFromFile(Locale.ENGLISH, "rules/checkstyle/com.puppycrawl.tools.checkstyle.checks.annotation.AnnotationUseStyleCheck.html", propertyKeyForName); | |||
verifyNoMoreInteractions(i18n); | |||
} | |||
// see http://jira.sonarsource.com/browse/SONAR-3319 | |||
@Test | |||
public void shouldGetDescriptionFromFileWithBackwardCompatibility() { | |||
String propertyKeyForName = "rule.checkstyle.com.puppycrawl.tools.checkstyle.checks.annotation.AnnotationUseStyleCheck.name"; | |||
DefaultI18n i18n = mock(DefaultI18n.class); | |||
// this is the "old" way of storing HTML description files for rules (they are not in the "rules/<repo-key>" folder) | |||
when(i18n.messageFromFile(Locale.ENGLISH, "com.puppycrawl.tools.checkstyle.checks.annotation.AnnotationUseStyleCheck.html", propertyKeyForName)).thenReturn("Description"); | |||
RuleI18nManager ruleI18n = new RuleI18nManager(i18n); | |||
String description = ruleI18n.getDescription("checkstyle", "com.puppycrawl.tools.checkstyle.checks.annotation.AnnotationUseStyleCheck", Locale.ENGLISH); | |||
assertThat(description).isEqualTo("Description"); | |||
verify(i18n).messageFromFile(Locale.ENGLISH, "rules/checkstyle/com.puppycrawl.tools.checkstyle.checks.annotation.AnnotationUseStyleCheck.html", propertyKeyForName); | |||
verify(i18n).messageFromFile(Locale.ENGLISH, "com.puppycrawl.tools.checkstyle.checks.annotation.AnnotationUseStyleCheck.html", propertyKeyForName); | |||
verifyNoMoreInteractions(i18n); | |||
} | |||
@Test | |||
public void shoudlReturnNullIfMissingDescription() { | |||
DefaultI18n i18n = mock(DefaultI18n.class); | |||
RuleI18nManager ruleI18n = new RuleI18nManager(i18n); | |||
assertThat(ruleI18n.getDescription("checkstyle", "com.puppycrawl.tools.checkstyle.checks.annotation.AnnotationUseStyleCheck", Locale.ENGLISH)).isNull(); | |||
} | |||
@Test | |||
public void shouldBeRuleKey() { | |||
assertThat(RuleI18nManager.isRuleProperty("rule.checkstyle.com.puppycrawl.tools.checkstyle.checks.annotation.AnnotationUseStyleCheck.name")).isTrue(); | |||
assertThat(RuleI18nManager.isRuleProperty("rule.pmd.Header.name")).isTrue(); | |||
} | |||
@Test | |||
public void shouldNotBeRuleKey() { | |||
// this is the parameter "name" | |||
assertThat(RuleI18nManager.isRuleProperty("rule.checkstyle.com.puppycrawl.tools.checkstyle.checks.annotation.AnnotationUseStyleCheck.param.name")).isFalse(); | |||
assertThat(RuleI18nManager.isRuleProperty("by")).isFalse(); | |||
assertThat(RuleI18nManager.isRuleProperty("something.else")).isFalse(); | |||
assertThat(RuleI18nManager.isRuleProperty("checkstyle.page.name")).isFalse(); | |||
} | |||
} |
@@ -1,152 +0,0 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2019 SonarSource SA | |||
* mailto:info AT sonarsource DOT com | |||
* | |||
* This program is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.api.i18n; | |||
import java.util.Locale; | |||
import javax.annotation.CheckForNull; | |||
import org.sonar.api.ce.ComputeEngineSide; | |||
import org.sonar.api.rules.Rule; | |||
import org.sonar.api.server.ServerSide; | |||
/** | |||
* {@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.sonarsource.com/browse/SONAR-4885 | |||
*/ | |||
@Deprecated | |||
@ServerSide | |||
@ComputeEngineSide | |||
public interface RuleI18n { | |||
/** | |||
* 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.sonarsource.com/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.sonarsource.com/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.sonarsource.com/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.sonarsource.com/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); | |||
} |
@@ -1,83 +0,0 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2019 SonarSource SA | |||
* mailto:info AT sonarsource DOT com | |||
* | |||
* This program is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.api.rules; | |||
import java.util.List; | |||
import org.apache.commons.lang.StringUtils; | |||
import org.apache.commons.lang.builder.ToStringBuilder; | |||
import org.apache.commons.lang.builder.ToStringStyle; | |||
import org.sonar.api.ExtensionPoint; | |||
import org.sonar.api.ce.ComputeEngineSide; | |||
import org.sonar.api.server.ServerSide; | |||
/** | |||
* @since 2.3 | |||
* @deprecated in 4.2. Replaced by org.sonar.api.server.rule.RulesDefinition | |||
*/ | |||
@Deprecated | |||
@ServerSide | |||
@ComputeEngineSide | |||
@ExtensionPoint | |||
public abstract class RuleRepository { | |||
private String key; | |||
private String language; | |||
private String name; | |||
protected RuleRepository(String key, String language) { | |||
this.key = key; | |||
this.language = language; | |||
} | |||
public final String getKey() { | |||
return key; | |||
} | |||
public final String getLanguage() { | |||
return language; | |||
} | |||
public final String getName() { | |||
return name; | |||
} | |||
public final String getName(boolean useKeyIfEmpty) { | |||
if (useKeyIfEmpty) { | |||
return StringUtils.defaultIfEmpty(name, key); | |||
} | |||
return name; | |||
} | |||
public final RuleRepository setName(String s) { | |||
this.name = s; | |||
return this; | |||
} | |||
public abstract List<Rule> createRules(); | |||
@Override | |||
public String toString() { | |||
return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE) | |||
.append("key", key) | |||
.append("language", language) | |||
.append("name", name) | |||
.toString(); | |||
} | |||
} |
@@ -1,69 +0,0 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2019 SonarSource SA | |||
* mailto:info AT sonarsource DOT com | |||
* | |||
* This program is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.api.server.rule; | |||
import org.apache.commons.lang.StringUtils; | |||
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. | |||
* <br> | |||
* This class must be executed after declaring rules on {@link RulesDefinition.NewRepository}. | |||
* <br> | |||
* 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 { | |||
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); | |||
} | |||
} | |||
} | |||
} | |||
} |
@@ -1,100 +0,0 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2019 SonarSource SA | |||
* mailto:info AT sonarsource DOT com | |||
* | |||
* This program is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.api.server.rule; | |||
import org.junit.Test; | |||
import org.sonar.api.i18n.RuleI18n; | |||
import org.sonar.api.impl.server.RulesDefinitionContext; | |||
import static org.assertj.core.api.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() { | |||
when(i18n.getName("squid", "S0001")).thenReturn("SOne"); | |||
when(i18n.getDescription("squid", "S0001")).thenReturn("S One"); | |||
RulesDefinition.Context context = new RulesDefinitionContext(); | |||
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() { | |||
// i18n returns null values | |||
RulesDefinition.Context context = new RulesDefinitionContext(); | |||
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() { | |||
when(i18n.getName("squid", "S0001")).thenReturn("SOne"); | |||
when(i18n.getDescription("squid", "S0001")).thenReturn("S One"); | |||
RulesDefinition.Context context = new RulesDefinitionContext(); | |||
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() { | |||
when(i18n.getParamDescription("squid", "S0001", "max")).thenReturn("Maximum"); | |||
RulesDefinition.Context context = new RulesDefinitionContext(); | |||
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"); | |||
} | |||
} |