@@ -146,14 +146,8 @@ public class CheckstyleProfileExporter extends ProfileExporter { | |||
private void appendRuleParameters(Writer writer, ActiveRule activeRule) throws IOException { | |||
for (RuleParam ruleParam : activeRule.getRule().getParams()) { | |||
ActiveRuleParam activeParam = activeRule.getParameter(ruleParam.getKey()); | |||
String value; | |||
if (activeParam == null) { | |||
value = ruleParam.getDefaultValue(); | |||
} else { | |||
value = activeParam.getValue(true); | |||
} | |||
if (value != null) { | |||
String value = activeRule.getParameter(ruleParam.getKey(), true); | |||
if (StringUtils.isNotBlank(value)) { | |||
appendModuleProperty(writer, ruleParam.getKey(), value); | |||
} | |||
} |
@@ -25,8 +25,12 @@ import org.codehaus.staxmate.SMInputFactory; | |||
import org.codehaus.staxmate.in.SMHierarchicCursor; | |||
import org.codehaus.staxmate.in.SMInputCursor; | |||
import org.sonar.api.profiles.ProfileImporter; | |||
import org.sonar.api.profiles.ProfilePrototype; | |||
import org.sonar.api.profiles.RulesProfile; | |||
import org.sonar.api.resources.Java; | |||
import org.sonar.api.rules.ActiveRule; | |||
import org.sonar.api.rules.Rule; | |||
import org.sonar.api.rules.RuleFinder; | |||
import org.sonar.api.rules.RuleQuery; | |||
import org.sonar.api.utils.ValidationMessages; | |||
import javax.xml.stream.XMLInputFactory; | |||
@@ -38,16 +42,18 @@ public class CheckstyleProfileImporter extends ProfileImporter { | |||
private static final String CHECKER_MODULE = "Checker"; | |||
private static final String TREEWALKER_MODULE = "TreeWalker"; | |||
private static final String MODULE_NODE = "module"; | |||
private final RuleFinder ruleFinder; | |||
public CheckstyleProfileImporter() { | |||
public CheckstyleProfileImporter(RuleFinder ruleFinder) { | |||
super(CheckstyleConstants.REPOSITORY_KEY, CheckstyleConstants.PLUGIN_NAME); | |||
setSupportedLanguages(Java.KEY); | |||
this.ruleFinder = ruleFinder; | |||
} | |||
@Override | |||
public ProfilePrototype importProfile(Reader reader, ValidationMessages messages) { | |||
public RulesProfile importProfile(Reader reader, ValidationMessages messages) { | |||
SMInputFactory inputFactory = initStax(); | |||
ProfilePrototype profile = ProfilePrototype.create(); | |||
RulesProfile profile = RulesProfile.create(); | |||
try { | |||
SMHierarchicCursor rootC = inputFactory.rootElementCursor(reader); | |||
rootC.advance(); // <module name="Checker"> | |||
@@ -79,17 +85,23 @@ public class CheckstyleProfileImporter extends ProfileImporter { | |||
return inputFactory; | |||
} | |||
private void processModule(ProfilePrototype profile, String path, SMInputCursor moduleCursor, ValidationMessages messages) throws XMLStreamException { | |||
private void processModule(RulesProfile profile, String path, SMInputCursor moduleCursor, ValidationMessages messages) throws XMLStreamException { | |||
String configKey = moduleCursor.getAttrValue("name"); | |||
if (isFilter(configKey)) { | |||
messages.addWarningText("Checkstyle filters are not imported: " + configKey); | |||
} else if (isIgnored(configKey)) { | |||
// ignore ! | |||
} else { | |||
ProfilePrototype.RulePrototype rule = ProfilePrototype.RulePrototype.createByConfigKey(CheckstyleConstants.REPOSITORY_KEY, path + configKey); | |||
processProperties(moduleCursor, messages, rule); | |||
profile.activateRule(rule); | |||
Rule rule = ruleFinder.find(RuleQuery.create().withRepositoryKey(CheckstyleConstants.REPOSITORY_KEY).withConfigKey(path + configKey)); | |||
if (rule == null) { | |||
messages.addWarningText("Checkstyle rule not found: " + path + configKey); | |||
} else { | |||
ActiveRule activeRule = profile.activateRule(rule, null); | |||
processProperties(moduleCursor, messages, activeRule); | |||
} | |||
} | |||
} | |||
@@ -104,24 +116,24 @@ public class CheckstyleProfileImporter extends ProfileImporter { | |||
StringUtils.equals(configKey, "SuppressWithNearbyCommentFilter"); | |||
} | |||
private void processProperties(SMInputCursor moduleCursor, ValidationMessages messages, ProfilePrototype.RulePrototype rule) throws XMLStreamException { | |||
private void processProperties(SMInputCursor moduleCursor, ValidationMessages messages, ActiveRule activeRule) throws XMLStreamException { | |||
SMInputCursor propertyCursor = moduleCursor.childElementCursor("property"); | |||
while (propertyCursor.getNext() != null) { | |||
processProperty(rule, propertyCursor, messages); | |||
processProperty(activeRule, propertyCursor, messages); | |||
} | |||
} | |||
private void processProperty(ProfilePrototype.RulePrototype rule, SMInputCursor propertyCursor, ValidationMessages messages) throws XMLStreamException { | |||
private void processProperty(ActiveRule activeRule, SMInputCursor propertyCursor, ValidationMessages messages) throws XMLStreamException { | |||
String key = propertyCursor.getAttrValue("name"); | |||
String value = propertyCursor.getAttrValue("value"); | |||
if (StringUtils.equals("id", key)) { | |||
messages.addWarningText("The checkstyle property 'id' is not supported in the rule: " + rule.getConfigKey()); | |||
messages.addWarningText("The property 'id' is not supported in the Checkstyle rule: " + activeRule.getConfigKey()); | |||
} else if (StringUtils.equals("severity", key)) { | |||
rule.setPriority(CheckstyleSeverityUtils.fromSeverity(value)); | |||
activeRule.setPriority(CheckstyleSeverityUtils.fromSeverity(value)); | |||
} else { | |||
rule.setParameter(key, value); | |||
activeRule.setParameter(key, value); | |||
} | |||
} | |||
} |
@@ -22,10 +22,11 @@ package org.sonar.plugins.checkstyle; | |||
import org.sonar.api.profiles.RulesProfile; | |||
import org.sonar.api.profiles.XMLProfileDefinition; | |||
import org.sonar.api.resources.Java; | |||
import org.sonar.api.rules.RuleFinder; | |||
public final class SonarWayProfile extends XMLProfileDefinition { | |||
public SonarWayProfile() { | |||
super(RulesProfile.SONAR_WAY_NAME, Java.KEY, SunConventionsProfile.class.getClassLoader(), "org/sonar/plugins/checkstyle/profile-sonar-way.xml"); | |||
public SonarWayProfile(RuleFinder ruleFinder) { | |||
super(SunConventionsProfile.class.getClassLoader(), "org/sonar/plugins/checkstyle/profile-sonar-way.xml", ruleFinder); | |||
} | |||
} |
@@ -19,14 +19,27 @@ | |||
*/ | |||
package org.sonar.plugins.checkstyle; | |||
import org.sonar.api.profiles.ProfileDefinition; | |||
import org.sonar.api.profiles.RulesProfile; | |||
import org.sonar.api.profiles.XMLProfileDefinition; | |||
import org.sonar.api.resources.Java; | |||
import org.sonar.api.rules.RuleFinder; | |||
import org.sonar.api.utils.ValidationMessages; | |||
public class SonarWayWithFindbugsProfile extends XMLProfileDefinition { | |||
public class SonarWayWithFindbugsProfile extends ProfileDefinition { | |||
public SonarWayWithFindbugsProfile() { | |||
super(RulesProfile.SONAR_WAY_FINDBUGS_NAME, Java.KEY, SonarWayWithFindbugsProfile.class.getClassLoader(), "org/sonar/plugins/checkstyle/profile-sonar-way.xml"); | |||
private SonarWayProfile sonarWay; | |||
public SonarWayWithFindbugsProfile(SonarWayProfile sonarWay) { | |||
this.sonarWay = sonarWay; | |||
} | |||
@Override | |||
public RulesProfile createProfile(ValidationMessages validationMessages) { | |||
RulesProfile profile = sonarWay.createProfile(validationMessages); | |||
profile.setName(RulesProfile.SONAR_WAY_FINDBUGS_NAME); | |||
return profile; | |||
} | |||
} | |||
@@ -22,10 +22,11 @@ package org.sonar.plugins.checkstyle; | |||
import org.sonar.api.profiles.RulesProfile; | |||
import org.sonar.api.profiles.XMLProfileDefinition; | |||
import org.sonar.api.resources.Java; | |||
import org.sonar.api.rules.RuleFinder; | |||
public final class SunConventionsProfile extends XMLProfileDefinition { | |||
public SunConventionsProfile() { | |||
super(RulesProfile.SUN_CONVENTIONS_NAME, Java.KEY, SunConventionsProfile.class.getClassLoader(), "org/sonar/plugins/checkstyle/profile-sun-conventions.xml"); | |||
public SunConventionsProfile(RuleFinder ruleFinder) { | |||
super(SunConventionsProfile.class.getClassLoader(), "org/sonar/plugins/checkstyle/profile-sun-conventions.xml", ruleFinder); | |||
} | |||
} |
@@ -1,4 +1,6 @@ | |||
<profile> | |||
<name>Sonar way</name> | |||
<language>java</language> | |||
<rules> | |||
<rule> | |||
<repositoryKey>checkstyle</repositoryKey> |
@@ -1,4 +1,6 @@ | |||
<profile> | |||
<name>Sun checks</name> | |||
<language>java</language> | |||
<rules> | |||
<rule> | |||
<repositoryKey>checkstyle</repositoryKey> |
@@ -21,8 +21,10 @@ package org.sonar.plugins.checkstyle; | |||
import org.junit.Before; | |||
import org.junit.Test; | |||
import org.sonar.api.profiles.ProfilePrototype; | |||
import org.sonar.api.rules.RulePriority; | |||
import org.mockito.invocation.InvocationOnMock; | |||
import org.mockito.stubbing.Answer; | |||
import org.sonar.api.profiles.RulesProfile; | |||
import org.sonar.api.rules.*; | |||
import org.sonar.api.utils.ValidationMessages; | |||
import org.sonar.test.TestUtils; | |||
@@ -34,6 +36,10 @@ import static org.hamcrest.core.IsNull.nullValue; | |||
import static org.junit.Assert.assertNotNull; | |||
import static org.junit.Assert.assertNull; | |||
import static org.junit.Assert.assertThat; | |||
import static org.mockito.Matchers.anyObject; | |||
import static org.mockito.Matchers.anyString; | |||
import static org.mockito.Mockito.mock; | |||
import static org.mockito.Mockito.when; | |||
public class CheckstyleProfileImporterTest { | |||
@@ -43,27 +49,36 @@ public class CheckstyleProfileImporterTest { | |||
@Before | |||
public void before() { | |||
messages = ValidationMessages.create(); | |||
importer = new CheckstyleProfileImporter(); | |||
/* | |||
The mocked rule finder defines 2 rules : | |||
- JavadocCheck with 2 paramters format and ignore, default priority is MAJOR | |||
- EqualsHashCodeCheck without parameters, default priority is BLOCKER | |||
*/ | |||
importer = new CheckstyleProfileImporter(newRuleFinder()); | |||
} | |||
@Test | |||
public void importSimpleProfile() { | |||
Reader reader = new StringReader(TestUtils.getResourceContent("/org/sonar/plugins/checkstyle/CheckstyleProfileImporterTest/simple.xml")); | |||
ProfilePrototype profile = importer.importProfile(reader, messages); | |||
RulesProfile profile = importer.importProfile(reader, messages); | |||
assertThat(profile.getRules().size(), is(2)); | |||
assertNotNull(profile.getRuleByConfigKey("checkstyle", "Checker/TreeWalker/EqualsHashCode")); | |||
assertNotNull(profile.getRuleByConfigKey("checkstyle", "Checker/JavadocPackage")); | |||
assertThat(profile.getActiveRules().size(), is(2)); | |||
assertNotNull(profile.getActiveRuleByConfigKey("checkstyle", "Checker/TreeWalker/EqualsHashCode")); | |||
assertNotNull(profile.getActiveRuleByConfigKey("checkstyle", "Checker/JavadocPackage")); | |||
assertThat(messages.hasErrors(), is(false)); | |||
} | |||
@Test | |||
public void importParameters() { | |||
Reader reader = new StringReader(TestUtils.getResourceContent("/org/sonar/plugins/checkstyle/CheckstyleProfileImporterTest/simple.xml")); | |||
ProfilePrototype profile = importer.importProfile(reader, messages); | |||
RulesProfile profile = importer.importProfile(reader, messages); | |||
ProfilePrototype.RulePrototype javadocCheck = profile.getRuleByConfigKey("checkstyle", "Checker/JavadocPackage"); | |||
assertThat(javadocCheck.getParameters().size(), is(2)); | |||
ActiveRule javadocCheck = profile.getActiveRuleByConfigKey("checkstyle", "Checker/JavadocPackage"); | |||
assertThat(javadocCheck.getActiveRuleParams().size(), is(2)); | |||
assertThat(javadocCheck.getParameter("format"), is("abcde")); | |||
assertThat(javadocCheck.getParameter("ignore"), is("true")); | |||
assertThat(javadocCheck.getParameter("severity"), nullValue()); // checkstyle internal parameter | |||
@@ -72,27 +87,27 @@ public class CheckstyleProfileImporterTest { | |||
@Test | |||
public void importPriorities() { | |||
Reader reader = new StringReader(TestUtils.getResourceContent("/org/sonar/plugins/checkstyle/CheckstyleProfileImporterTest/simple.xml")); | |||
ProfilePrototype profile = importer.importProfile(reader, messages); | |||
RulesProfile profile = importer.importProfile(reader, messages); | |||
ProfilePrototype.RulePrototype javadocCheck = profile.getRuleByConfigKey("checkstyle", "Checker/JavadocPackage"); | |||
ActiveRule javadocCheck = profile.getActiveRuleByConfigKey("checkstyle", "Checker/JavadocPackage"); | |||
assertThat(javadocCheck.getPriority(), is(RulePriority.BLOCKER)); | |||
} | |||
@Test | |||
public void priorityIsOptional() { | |||
Reader reader = new StringReader(TestUtils.getResourceContent("/org/sonar/plugins/checkstyle/CheckstyleProfileImporterTest/simple.xml")); | |||
ProfilePrototype profile = importer.importProfile(reader, messages); | |||
RulesProfile profile = importer.importProfile(reader, messages); | |||
ProfilePrototype.RulePrototype check = profile.getRuleByConfigKey("checkstyle", "Checker/TreeWalker/EqualsHashCode"); | |||
assertThat(check.getPriority(), nullValue()); | |||
ActiveRule activeRule= profile.getActiveRuleByConfigKey("checkstyle", "Checker/TreeWalker/EqualsHashCode"); | |||
assertThat(activeRule.getPriority(), is(RulePriority.BLOCKER)); // reuse the rule default priority | |||
} | |||
@Test | |||
public void idPropertyIsNotSupported() { | |||
Reader reader = new StringReader(TestUtils.getResourceContent("/org/sonar/plugins/checkstyle/CheckstyleProfileImporterTest/idProperty.xml")); | |||
ProfilePrototype profile = importer.importProfile(reader, messages); | |||
RulesProfile profile = importer.importProfile(reader, messages); | |||
ProfilePrototype.RulePrototype check = profile.getRuleByConfigKey("checkstyle", "Checker/JavadocPackage"); | |||
ActiveRule check = profile.getActiveRuleByConfigKey("checkstyle", "Checker/JavadocPackage"); | |||
assertThat(check.getParameter("id"), nullValue()); | |||
assertThat(messages.getWarnings().size(), is(1)); | |||
} | |||
@@ -107,12 +122,36 @@ public class CheckstyleProfileImporterTest { | |||
@Test | |||
public void importingFiltersIsNotSupported() { | |||
Reader reader = new StringReader(TestUtils.getResourceContent("/org/sonar/plugins/checkstyle/CheckstyleProfileImporterTest/importingFiltersIsNotSupported.xml")); | |||
ProfilePrototype profile = importer.importProfile(reader, messages); | |||
RulesProfile profile = importer.importProfile(reader, messages); | |||
assertNull(profile.getRuleByConfigKey("checkstyle", "Checker/SuppressionCommentFilter")); | |||
assertNull(profile.getRuleByConfigKey("checkstyle", "Checker/TreeWalker/FileContentsHolder")); | |||
assertThat(profile.getRules().size(), is(2)); | |||
assertNull(profile.getActiveRuleByConfigKey("checkstyle", "Checker/SuppressionCommentFilter")); | |||
assertNull(profile.getActiveRuleByConfigKey("checkstyle", "Checker/TreeWalker/FileContentsHolder")); | |||
assertThat(profile.getActiveRules().size(), is(2)); | |||
assertThat(messages.getWarnings().size(), is(1)); // no warning for FileContentsHolder | |||
} | |||
private RuleFinder newRuleFinder() { | |||
RuleFinder ruleFinder = mock(RuleFinder.class); | |||
when(ruleFinder.find((RuleQuery)anyObject())).thenAnswer(new Answer<Rule>() { | |||
public Rule answer(InvocationOnMock iom) throws Throwable { | |||
RuleQuery query = (RuleQuery)iom.getArguments()[0]; | |||
Rule rule = null; | |||
if (query.getConfigKey().equals("Checker/JavadocPackage")) { | |||
rule = Rule.create(query.getRepositoryKey(), "com.puppycrawl.tools.checkstyle.checks.javadoc.JavadocPackageCheck", "Javadoc Package") | |||
.setConfigKey("Checker/JavadocPackage") | |||
.setPriority(RulePriority.MAJOR); | |||
rule.createParameter("format"); | |||
rule.createParameter("ignore"); | |||
} else if (query.getConfigKey().equals("Checker/TreeWalker/EqualsHashCode")) { | |||
rule = Rule.create(query.getRepositoryKey(), "com.puppycrawl.tools.checkstyle.checks.coding.EqualsHashCodeCheck", "Equals HashCode") | |||
.setConfigKey("Checker/TreeWalker/EqualsHashCode") | |||
.setPriority(RulePriority.BLOCKER); | |||
} | |||
return rule; | |||
} | |||
}); | |||
return ruleFinder; | |||
} | |||
} |
@@ -20,23 +20,39 @@ | |||
package org.sonar.plugins.checkstyle; | |||
import org.junit.Test; | |||
import org.mockito.invocation.InvocationOnMock; | |||
import org.mockito.stubbing.Answer; | |||
import org.sonar.api.profiles.ProfileDefinition; | |||
import org.sonar.api.profiles.ProfilePrototype; | |||
import org.sonar.api.profiles.RulesProfile; | |||
import org.sonar.api.rules.Rule; | |||
import org.sonar.api.rules.RuleFinder; | |||
import org.sonar.api.utils.ValidationMessages; | |||
import static org.hamcrest.core.Is.is; | |||
import static org.hamcrest.number.OrderingComparisons.greaterThan; | |||
import static org.junit.Assert.assertThat; | |||
import static org.mockito.Matchers.anyString; | |||
import static org.mockito.Mockito.mock; | |||
import static org.mockito.Mockito.when; | |||
public class SonarWayProfileTest { | |||
@Test | |||
public void create() { | |||
ProfileDefinition sonarWay = new SonarWayProfile(); | |||
ProfileDefinition sonarWay = new SonarWayProfile(newRuleFinder()); | |||
ValidationMessages validation = ValidationMessages.create(); | |||
ProfilePrototype prototype = sonarWay.createPrototype(validation); | |||
assertThat(prototype.getRulesByRepositoryKey(CheckstyleConstants.REPOSITORY_KEY).size(), greaterThan(1)); | |||
RulesProfile profile = sonarWay.createProfile(validation); | |||
assertThat(profile.getActiveRulesByRepository(CheckstyleConstants.REPOSITORY_KEY).size(), greaterThan(1)); | |||
assertThat(validation.hasErrors(), is(false)); | |||
} | |||
private RuleFinder newRuleFinder() { | |||
RuleFinder ruleFinder = mock(RuleFinder.class); | |||
when(ruleFinder.findByKey(anyString(), anyString())).thenAnswer(new Answer<Rule>(){ | |||
public Rule answer(InvocationOnMock iom) throws Throwable { | |||
return Rule.create((String) iom.getArguments()[0], (String) iom.getArguments()[1], (String) iom.getArguments()[1]); | |||
} | |||
}); | |||
return ruleFinder; | |||
} | |||
} |
@@ -19,20 +19,40 @@ | |||
*/ | |||
package org.sonar.plugins.checkstyle; | |||
import org.hamcrest.core.Is; | |||
import org.junit.Test; | |||
import org.sonar.api.profiles.ProfilePrototype; | |||
import org.mockito.invocation.InvocationOnMock; | |||
import org.mockito.stubbing.Answer; | |||
import org.sonar.api.profiles.RulesProfile; | |||
import org.sonar.api.rules.Rule; | |||
import org.sonar.api.rules.RuleFinder; | |||
import org.sonar.api.utils.ValidationMessages; | |||
import static org.hamcrest.core.Is.is; | |||
import static org.junit.Assert.assertThat; | |||
import static org.hamcrest.CoreMatchers.is; | |||
import static org.mockito.Matchers.anyString; | |||
import static org.mockito.Mockito.mock; | |||
import static org.mockito.Mockito.when; | |||
public class SonarWayWithFindbugsProfileTest { | |||
@Test | |||
public void sameAsSonarWay() { | |||
ProfilePrototype withFindbugs = new SonarWayWithFindbugsProfile().createPrototype(ValidationMessages.create()); | |||
ProfilePrototype withoutFindbugs = new SonarWayProfile().createPrototype(ValidationMessages.create()); | |||
assertThat(withFindbugs.getRules().size(), is(withoutFindbugs.getRules().size())); | |||
RuleFinder ruleFinder = newRuleFinder(); | |||
SonarWayProfile sonarWay = new SonarWayProfile(ruleFinder); | |||
RulesProfile withoutFindbugs = sonarWay.createProfile(ValidationMessages.create()); | |||
RulesProfile withFindbugs = new SonarWayWithFindbugsProfile(sonarWay).createProfile(ValidationMessages.create()); | |||
assertThat(withFindbugs.getActiveRules().size(), is(withoutFindbugs.getActiveRules().size())); | |||
assertThat(withFindbugs.getName(), is(RulesProfile.SONAR_WAY_FINDBUGS_NAME)); | |||
} | |||
private RuleFinder newRuleFinder() { | |||
RuleFinder ruleFinder = mock(RuleFinder.class); | |||
when(ruleFinder.findByKey(anyString(), anyString())).thenAnswer(new Answer<Rule>() { | |||
public Rule answer(InvocationOnMock iom) throws Throwable { | |||
return Rule.create((String) iom.getArguments()[0], (String) iom.getArguments()[1], (String) iom.getArguments()[1]); | |||
} | |||
}); | |||
return ruleFinder; | |||
} | |||
} |
@@ -21,24 +21,38 @@ package org.sonar.plugins.checkstyle; | |||
import org.hamcrest.core.Is; | |||
import org.junit.Test; | |||
import org.mockito.invocation.InvocationOnMock; | |||
import org.mockito.stubbing.Answer; | |||
import org.sonar.api.profiles.ProfileDefinition; | |||
import org.sonar.api.profiles.ProfilePrototype; | |||
import org.sonar.api.profiles.RulesProfile; | |||
import org.sonar.api.rules.Rule; | |||
import org.sonar.api.rules.RuleFinder; | |||
import org.sonar.api.utils.ValidationMessages; | |||
import static org.hamcrest.Matchers.is; | |||
import static org.hamcrest.number.OrderingComparisons.greaterThan; | |||
import static org.junit.Assert.assertThat; | |||
import static org.mockito.Matchers.anyString; | |||
import static org.mockito.Mockito.mock; | |||
import static org.mockito.Mockito.when; | |||
public class SunConventionsProfileTest { | |||
@Test | |||
public void create() { | |||
ProfileDefinition sunConventionsProfile = new SunConventionsProfile(); | |||
ProfileDefinition definition = new SunConventionsProfile(newRuleFinder()); | |||
ValidationMessages validation = ValidationMessages.create(); | |||
ProfilePrototype prototype = sunConventionsProfile.createPrototype(validation); | |||
assertThat(prototype.getRulesByRepositoryKey(CheckstyleConstants.REPOSITORY_KEY).size(), greaterThan(1)); | |||
assertThat( | |||
prototype.getRule(CheckstyleConstants.REPOSITORY_KEY, "com.puppycrawl.tools.checkstyle.checks.NewlineAtEndOfFileCheck").getParameter("lineSeparator"), | |||
is("system")); | |||
RulesProfile sunProfile = definition.createProfile(validation); | |||
assertThat(sunProfile.getActiveRulesByRepository(CheckstyleConstants.REPOSITORY_KEY).size(), greaterThan(1)); | |||
assertThat(validation.hasErrors(), Is.is(false)); | |||
} | |||
private RuleFinder newRuleFinder() { | |||
RuleFinder ruleFinder = mock(RuleFinder.class); | |||
when(ruleFinder.findByKey(anyString(), anyString())).thenAnswer(new Answer<Rule>() { | |||
public Rule answer(InvocationOnMock iom) throws Throwable { | |||
return Rule.create((String) iom.getArguments()[0], (String) iom.getArguments()[1], (String) iom.getArguments()[1]); | |||
} | |||
}); | |||
return ruleFinder; | |||
} | |||
} |
@@ -1,9 +1,9 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<module name="Checker"> | |||
<module name="SuppressionCommentFilter"/> | |||
<module name="NewlineAtEndOfFile"/> | |||
<module name="JavadocPackage"/> | |||
<module name="TreeWalker"> | |||
<module name="FileContentsHolder"/> | |||
<module name="InterfaceIsType"/> | |||
<module name="EqualsHashCode"/> | |||
</module> | |||
</module> |
@@ -19,6 +19,8 @@ | |||
*/ | |||
package org.sonar.api.profiles; | |||
import org.sonar.api.rules.Rule; | |||
import org.sonar.api.rules.RuleFinder; | |||
import org.sonar.api.rules.RulePriority; | |||
import org.sonar.api.utils.ValidationMessages; | |||
import org.sonar.check.AnnotationIntrospector; | |||
@@ -35,34 +37,42 @@ public abstract class AnnotationProfileDefinition extends ProfileDefinition { | |||
private String language; | |||
private String repositoryKey; | |||
private Collection<Class> annotatedClasses; | |||
private RuleFinder ruleFinder; | |||
protected AnnotationProfileDefinition(String repositoryKey, String profileName, String language, Collection<Class> annotatedClasses) { | |||
protected AnnotationProfileDefinition(String repositoryKey, String profileName, String language, Collection<Class> annotatedClasses, RuleFinder ruleFinder) { | |||
this.name = profileName; | |||
this.language = language; | |||
this.repositoryKey = repositoryKey; | |||
this.annotatedClasses = annotatedClasses; | |||
this.ruleFinder = ruleFinder; | |||
} | |||
@Override | |||
public ProfilePrototype createPrototype(ValidationMessages validation) { | |||
ProfilePrototype profile = ProfilePrototype.create(name, language); | |||
public RulesProfile createProfile(ValidationMessages validation) { | |||
RulesProfile profile = RulesProfile.create(name, language); | |||
if (annotatedClasses != null) { | |||
for (Class aClass : annotatedClasses) { | |||
BelongsToProfile belongsToProfile = (BelongsToProfile) aClass.getAnnotation(BelongsToProfile.class); | |||
registerRule(aClass, belongsToProfile, profile); | |||
registerRule(aClass, belongsToProfile, profile, validation); | |||
} | |||
} | |||
return profile; | |||
} | |||
private void registerRule(Class aClass, BelongsToProfile belongsToProfile, ProfilePrototype profile) { | |||
private void registerRule(Class aClass, BelongsToProfile belongsToProfile, RulesProfile profile, ValidationMessages validation) { | |||
if (belongsToProfile != null) { | |||
RulePriority priority = null; | |||
if (belongsToProfile.priority() != null) { | |||
priority = RulePriority.fromCheckPriority(belongsToProfile.priority()); | |||
String ruleKey = AnnotationIntrospector.getCheckKey(aClass); | |||
Rule rule = ruleFinder.findByKey(repositoryKey, ruleKey); | |||
if (rule == null) { | |||
validation.addErrorText("Rule not found: [repository=" + repositoryKey + ", key=" + ruleKey + "]"); | |||
} else { | |||
RulePriority priority = null; | |||
if (belongsToProfile.priority() != null) { | |||
priority = RulePriority.fromCheckPriority(belongsToProfile.priority()); | |||
} | |||
profile.activateRule(rule, priority); | |||
} | |||
profile.activateRule(repositoryKey, AnnotationIntrospector.getCheckKey(aClass), priority); | |||
} | |||
} | |||
} |
@@ -27,6 +27,6 @@ import org.sonar.api.utils.ValidationMessages; | |||
*/ | |||
public abstract class ProfileDefinition implements ServerExtension { | |||
public abstract ProfilePrototype createPrototype(ValidationMessages validation); | |||
public abstract RulesProfile createProfile(ValidationMessages validation); | |||
} |
@@ -19,6 +19,8 @@ | |||
*/ | |||
package org.sonar.api.profiles; | |||
import org.apache.commons.lang.builder.ToStringBuilder; | |||
import org.apache.commons.lang.builder.ToStringStyle; | |||
import org.sonar.api.ServerExtension; | |||
import org.sonar.api.utils.ValidationMessages; | |||
@@ -30,31 +32,31 @@ import java.io.Reader; | |||
public abstract class ProfileImporter implements ServerExtension { | |||
private String[] supportedLanguages = new String[0]; | |||
private String key; | |||
private String name; | |||
private String importerKey; | |||
private String importerName; | |||
protected ProfileImporter(String key, String name) { | |||
this.key = key; | |||
this.name = name; | |||
this.importerKey = key; | |||
this.importerName = name; | |||
} | |||
public abstract ProfilePrototype importProfile(Reader reader, ValidationMessages messages); | |||
public abstract RulesProfile importProfile(Reader reader, ValidationMessages messages); | |||
public final String getKey() { | |||
return key; | |||
return importerKey; | |||
} | |||
public final ProfileImporter setKey(String s) { | |||
this.key = s; | |||
this.importerKey = s; | |||
return this; | |||
} | |||
public final String getName() { | |||
return name; | |||
return importerName; | |||
} | |||
public final ProfileImporter setName(String s) { | |||
this.name = s; | |||
this.importerName = s; | |||
return this; | |||
} | |||
@@ -79,7 +81,7 @@ public abstract class ProfileImporter implements ServerExtension { | |||
return false; | |||
} | |||
ProfileImporter that = (ProfileImporter) o; | |||
if (key != null ? !key.equals(that.key) : that.key != null) { | |||
if (importerKey != null ? !importerKey.equals(that.importerKey) : that.importerKey != null) { | |||
return false; | |||
} | |||
return true; | |||
@@ -87,6 +89,15 @@ public abstract class ProfileImporter implements ServerExtension { | |||
@Override | |||
public final int hashCode() { | |||
return key != null ? key.hashCode() : 0; | |||
return importerKey != null ? importerKey.hashCode() : 0; | |||
} | |||
@Override | |||
public String toString() { | |||
return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE) | |||
.append("key", importerKey) | |||
.append("name", importerName) | |||
.append("languages", supportedLanguages) | |||
.toString(); | |||
} | |||
} |
@@ -1,218 +0,0 @@ | |||
/* | |||
* Sonar, open source software quality management tool. | |||
* Copyright (C) 2009 SonarSource SA | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* Sonar 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. | |||
* | |||
* Sonar 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 Sonar; if not, write to the Free Software | |||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 | |||
*/ | |||
package org.sonar.api.profiles; | |||
import org.apache.commons.lang.StringUtils; | |||
import org.apache.commons.lang.builder.ToStringBuilder; | |||
import org.apache.commons.lang.builder.ToStringStyle; | |||
import org.sonar.api.BatchComponent; | |||
import org.sonar.api.rules.RulePriority; | |||
import java.util.ArrayList; | |||
import java.util.HashMap; | |||
import java.util.List; | |||
import java.util.Map; | |||
/** | |||
* @since 2.3 | |||
*/ | |||
public final class ProfilePrototype implements BatchComponent { | |||
private String name; | |||
private String language; | |||
private List<RulePrototype> rules = new ArrayList<RulePrototype>(); | |||
private ProfilePrototype() { | |||
} | |||
public static ProfilePrototype create() { | |||
return new ProfilePrototype(); | |||
} | |||
public static ProfilePrototype create(String name, String language) { | |||
return new ProfilePrototype().setName(name).setLanguage(language); | |||
} | |||
public final String getName() { | |||
return name; | |||
} | |||
public final ProfilePrototype setName(String s) { | |||
this.name = s; | |||
return this; | |||
} | |||
public final String getLanguage() { | |||
return language; | |||
} | |||
public final ProfilePrototype setLanguage(String s) { | |||
this.language = s; | |||
return this; | |||
} | |||
public List<RulePrototype> getRules() { | |||
return rules; | |||
} | |||
public List<RulePrototype> getRulesByRepositoryKey(String repositoryKey) { | |||
List<RulePrototype> result = new ArrayList<RulePrototype>(); | |||
for (RulePrototype rule : rules) { | |||
if (StringUtils.equals(repositoryKey, rule.getRepositoryKey())) { | |||
result.add(rule); | |||
} | |||
} | |||
return result; | |||
} | |||
public RulePrototype getRule(String repositoryKey, String key) { | |||
for (RulePrototype rule : rules) { | |||
if (StringUtils.equals(repositoryKey, rule.getRepositoryKey()) && | |||
StringUtils.equals(key, rule.getKey())) { | |||
return rule; | |||
} | |||
} | |||
return null; | |||
} | |||
public RulePrototype getRuleByConfigKey(String repositoryKey, String configKey) { | |||
for (RulePrototype rule : rules) { | |||
if (StringUtils.equals(repositoryKey, rule.getRepositoryKey()) && | |||
StringUtils.equals(configKey, rule.getConfigKey())) { | |||
return rule; | |||
} | |||
} | |||
return null; | |||
} | |||
/** | |||
* @param repositoryKey | |||
* @param key | |||
* @param nullablePriority if null, then the default rule priority is used. | |||
* @return the created rule | |||
*/ | |||
public RulePrototype activateRule(String repositoryKey, String key, RulePriority nullablePriority) { | |||
RulePrototype rule = RulePrototype.create(repositoryKey, key); | |||
rule.setPriority(nullablePriority); | |||
rules.add(rule); | |||
return rule; | |||
} | |||
public RulePrototype activateRule(RulePrototype rule) { | |||
rules.add(rule); | |||
return rule; | |||
} | |||
@Override | |||
public String toString() { | |||
return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE) | |||
.append("name", name) | |||
.append("language", language) | |||
.toString(); | |||
} | |||
public static final class RulePrototype { | |||
private String repositoryKey; | |||
private String key; | |||
private String configKey; | |||
private RulePriority priority = null; | |||
private Map<String, String> parameters = new HashMap<String, String>(); | |||
private RulePrototype() { | |||
} | |||
public static RulePrototype create() { | |||
return new RulePrototype(); | |||
} | |||
public static RulePrototype create(String repositoryKey, String key) { | |||
return new RulePrototype().setRepositoryKey(repositoryKey).setKey(key); | |||
} | |||
public static RulePrototype createByConfigKey(String repositoryKey, String configKey) { | |||
return new RulePrototype().setRepositoryKey(repositoryKey).setConfigKey(configKey); | |||
} | |||
public String getRepositoryKey() { | |||
return repositoryKey; | |||
} | |||
public RulePrototype setRepositoryKey(String s) { | |||
this.repositoryKey = s; | |||
return this; | |||
} | |||
public String getKey() { | |||
return key; | |||
} | |||
public RulePrototype setKey(String s) { | |||
this.key = s; | |||
return this; | |||
} | |||
public String getConfigKey() { | |||
return configKey; | |||
} | |||
public RulePrototype setConfigKey(String s) { | |||
this.configKey = s; | |||
return this; | |||
} | |||
public RulePriority getPriority() { | |||
return priority; | |||
} | |||
public RulePrototype setPriority(RulePriority p) { | |||
this.priority = p; | |||
return this; | |||
} | |||
public RulePrototype setParameter(String key, String value) { | |||
parameters.put(key, value); | |||
return this; | |||
} | |||
public Map<String, String> getParameters() { | |||
return parameters; | |||
} | |||
public String getParameter(String key) { | |||
return parameters.get(key); | |||
} | |||
@Override | |||
public String toString() { | |||
StringBuilder sb = new StringBuilder().append("[repository=").append(repositoryKey); | |||
if (StringUtils.isNotBlank(key)) { | |||
sb.append(",key=").append(key); | |||
} | |||
if (StringUtils.isNotBlank(configKey)) { | |||
sb.append(",configKey=").append(configKey); | |||
} | |||
return sb.append("]").toString(); | |||
} | |||
} | |||
} |
@@ -21,6 +21,7 @@ package org.sonar.api.profiles; | |||
import org.apache.commons.io.IOUtils; | |||
import org.apache.commons.lang.CharEncoding; | |||
import org.sonar.api.rules.RuleFinder; | |||
import org.sonar.api.utils.SonarException; | |||
import org.sonar.api.utils.ValidationMessages; | |||
@@ -34,26 +35,21 @@ import java.util.List; | |||
*/ | |||
public abstract class XMLProfileDefinition extends ProfileDefinition { | |||
private String name; | |||
private String language; | |||
private RuleFinder ruleFinder; | |||
private ClassLoader classloader; | |||
private String xmlClassPath; | |||
protected XMLProfileDefinition(String name, String language, ClassLoader classloader, String xmlClassPath) { | |||
this.name = name; | |||
this.language = language; | |||
protected XMLProfileDefinition(ClassLoader classloader, String xmlClassPath, RuleFinder ruleFinder) { | |||
this.ruleFinder = ruleFinder; | |||
this.classloader = classloader; | |||
this.xmlClassPath = xmlClassPath; | |||
} | |||
@Override | |||
public final ProfilePrototype createPrototype(ValidationMessages validation) { | |||
public final RulesProfile createProfile(ValidationMessages validation) { | |||
Reader reader = new InputStreamReader(classloader.getResourceAsStream(xmlClassPath), Charset.forName(CharEncoding.UTF_8)); | |||
try { | |||
ProfilePrototype profile = XMLProfileImporter.create().importProfile(reader, validation); | |||
profile.setName(name); | |||
profile.setLanguage(language); | |||
return profile; | |||
return XMLProfileImporter.create(ruleFinder).importProfile(reader, validation); | |||
} finally { | |||
IOUtils.closeQuietly(reader); |
@@ -39,7 +39,7 @@ public final class XMLProfileExporter { | |||
public void exportProfile(RulesProfile profile, Writer writer) { | |||
try { | |||
appendHeader(writer); | |||
appendHeader(profile, writer); | |||
appendRules(profile, writer); | |||
appendFooter(writer); | |||
@@ -48,6 +48,16 @@ public final class XMLProfileExporter { | |||
} | |||
} | |||
private void appendHeader(RulesProfile profile, Writer writer) throws IOException { | |||
writer.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>" | |||
+ "<!-- Generated by Sonar -->" | |||
+ "<profile><name>"); | |||
StringEscapeUtils.escapeXml(writer, profile.getName()); | |||
writer.append("</name><language>"); | |||
StringEscapeUtils.escapeXml(writer, profile.getLanguage()); | |||
writer.append("</language>"); | |||
} | |||
private void appendRules(RulesProfile profile, Writer writer) throws IOException { | |||
if (!profile.getActiveRules().isEmpty()) { | |||
writer.append("<rules>"); | |||
@@ -58,12 +68,6 @@ public final class XMLProfileExporter { | |||
} | |||
} | |||
private void appendHeader(Writer writer) throws IOException { | |||
writer.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>" | |||
+ "<!-- Generated by Sonar -->" | |||
+ "<profile>"); | |||
} | |||
private void appendRule(ActiveRule activeRule, Writer writer) throws IOException { | |||
writer.append("<rule><repositoryKey>"); | |||
writer.append(activeRule.getRepositoryKey()); |
@@ -24,28 +24,35 @@ import org.codehaus.stax2.XMLInputFactory2; | |||
import org.codehaus.staxmate.SMInputFactory; | |||
import org.codehaus.staxmate.in.SMHierarchicCursor; | |||
import org.codehaus.staxmate.in.SMInputCursor; | |||
import org.sonar.api.rules.ActiveRule; | |||
import org.sonar.api.rules.Rule; | |||
import org.sonar.api.rules.RuleFinder; | |||
import org.sonar.api.rules.RulePriority; | |||
import org.sonar.api.utils.ValidationMessages; | |||
import javax.xml.stream.XMLInputFactory; | |||
import javax.xml.stream.XMLStreamException; | |||
import java.io.Reader; | |||
import java.util.HashMap; | |||
import java.util.Map; | |||
/** | |||
* @since 2.3 | |||
*/ | |||
public final class XMLProfileImporter { | |||
private XMLProfileImporter() { | |||
// support all repositories | |||
private RuleFinder ruleFinder; | |||
private XMLProfileImporter(RuleFinder ruleFinder) { | |||
this.ruleFinder = ruleFinder; | |||
} | |||
public static XMLProfileImporter create() { | |||
return new XMLProfileImporter(); | |||
public static XMLProfileImporter create(RuleFinder ruleFinder) { | |||
return new XMLProfileImporter(ruleFinder); | |||
} | |||
public ProfilePrototype importProfile(Reader reader, ValidationMessages messages) { | |||
ProfilePrototype profile = ProfilePrototype.create(); | |||
public RulesProfile importProfile(Reader reader, ValidationMessages messages) { | |||
RulesProfile profile = RulesProfile.create(); | |||
SMInputFactory inputFactory = initStax(); | |||
try { | |||
SMHierarchicCursor rootC = inputFactory.rootElementCursor(reader); | |||
@@ -55,7 +62,13 @@ public final class XMLProfileImporter { | |||
String nodeName = cursor.getLocalName(); | |||
if (StringUtils.equals("rules", nodeName)) { | |||
SMInputCursor rulesCursor = cursor.childElementCursor("rule"); | |||
processRules(rulesCursor, profile); | |||
processRules(rulesCursor, profile, messages); | |||
} else if (StringUtils.equals("name", nodeName)) { | |||
profile.setName(StringUtils.trim(cursor.collectDescendantText(false))); | |||
} else if (StringUtils.equals("language", nodeName)) { | |||
profile.setLanguage(StringUtils.trim(cursor.collectDescendantText(false))); | |||
} | |||
} | |||
} catch (XMLStreamException e) { | |||
@@ -75,33 +88,51 @@ public final class XMLProfileImporter { | |||
return inputFactory; | |||
} | |||
private void processRules(SMInputCursor rulesCursor, ProfilePrototype profile) throws XMLStreamException { | |||
private void processRules(SMInputCursor rulesCursor, RulesProfile profile, ValidationMessages messages) throws XMLStreamException { | |||
Map<String, String> parameters = new HashMap<String, String>(); | |||
while (rulesCursor.getNext() != null) { | |||
SMInputCursor ruleCursor = rulesCursor.childElementCursor(); | |||
ProfilePrototype.RulePrototype rule = ProfilePrototype.RulePrototype.create(); | |||
profile.activateRule(rule); | |||
String repositoryKey = null, key = null; | |||
RulePriority priority = null; | |||
parameters.clear(); | |||
while (ruleCursor.getNext() != null) { | |||
String nodeName = ruleCursor.getLocalName(); | |||
if (StringUtils.equals("repositoryKey", nodeName)) { | |||
rule.setRepositoryKey(StringUtils.trim(ruleCursor.collectDescendantText(false))); | |||
repositoryKey = StringUtils.trim(ruleCursor.collectDescendantText(false)); | |||
} else if (StringUtils.equals("key", nodeName)) { | |||
rule.setKey(StringUtils.trim(ruleCursor.collectDescendantText(false))); | |||
key = StringUtils.trim(ruleCursor.collectDescendantText(false)); | |||
} else if (StringUtils.equals("priority", nodeName)) { | |||
rule.setPriority(RulePriority.valueOf(StringUtils.trim(ruleCursor.collectDescendantText(false)))); | |||
priority = RulePriority.valueOf(StringUtils.trim(ruleCursor.collectDescendantText(false))); | |||
} else if (StringUtils.equals("parameters", nodeName)) { | |||
SMInputCursor propsCursor = ruleCursor.childElementCursor("parameter"); | |||
processParameters(propsCursor, rule); | |||
processParameters(propsCursor, parameters); | |||
} | |||
} | |||
Rule rule = ruleFinder.findByKey(repositoryKey, key); | |||
if (rule == null) { | |||
messages.addWarningText("Rule not found: [repository=" + repositoryKey + ", key=" + key + "]"); | |||
} else { | |||
ActiveRule activeRule = profile.activateRule(rule, priority); | |||
for (Map.Entry<String, String> entry : parameters.entrySet()) { | |||
if (rule.getParam(entry.getKey()) == null) { | |||
messages.addWarningText("The parameter '" + entry.getKey() + "' does not exist in the rule: [repository=" + repositoryKey + ", key=" + key + "]"); | |||
} else { | |||
activeRule.setParameter(entry.getKey(), entry.getValue()); | |||
} | |||
} | |||
} | |||
} | |||
} | |||
private void processParameters(SMInputCursor propsCursor, ProfilePrototype.RulePrototype rule) throws XMLStreamException { | |||
private void processParameters(SMInputCursor propsCursor, Map<String, String> parameters) throws XMLStreamException { | |||
while (propsCursor.getNext() != null) { | |||
SMInputCursor propCursor = propsCursor.childElementCursor(); | |||
String key = null; | |||
@@ -116,7 +147,7 @@ public final class XMLProfileImporter { | |||
} | |||
} | |||
if (key != null) { | |||
rule.setParameter(key, value); | |||
parameters.put(key, value); | |||
} | |||
} | |||
} |
@@ -142,14 +142,24 @@ public class ActiveRule implements Cloneable { | |||
return this; | |||
} | |||
public ActiveRuleParam getParameter(String key) { | |||
public String getParameter(String key) { | |||
return getParameter(key, false); | |||
} | |||
public String getParameter(String key, boolean useDefaultValueIfNeeded) { | |||
if (activeRuleParams != null) { | |||
for (ActiveRuleParam param : activeRuleParams) { | |||
if (StringUtils.equals(key, param.getKey())) { | |||
return param; | |||
return param.getValue(useDefaultValueIfNeeded); | |||
} | |||
} | |||
} | |||
if (useDefaultValueIfNeeded && rule.getParams()!=null) { | |||
RuleParam param = rule.getParam(key); | |||
if (param != null) { | |||
return param.getDefaultValue(); | |||
} | |||
} | |||
return null; | |||
} | |||
@@ -20,6 +20,10 @@ | |||
package org.sonar.api.profiles; | |||
import org.junit.Test; | |||
import org.mockito.invocation.InvocationOnMock; | |||
import org.mockito.stubbing.Answer; | |||
import org.sonar.api.rules.Rule; | |||
import org.sonar.api.rules.RuleFinder; | |||
import org.sonar.api.rules.RulePriority; | |||
import org.sonar.api.utils.ValidationMessages; | |||
import org.sonar.check.BelongsToProfile; | |||
@@ -32,15 +36,25 @@ import java.util.Collection; | |||
import static org.hamcrest.Matchers.is; | |||
import static org.junit.Assert.assertThat; | |||
import static org.mockito.Matchers.anyString; | |||
import static org.mockito.Mockito.mock; | |||
import static org.mockito.Mockito.when; | |||
public class AnnotationProfileDefinitionTest { | |||
@Test | |||
public void importProfile() { | |||
ProfileDefinition definition = new FakeDefinition(); | |||
RuleFinder ruleFinder = mock(RuleFinder.class); | |||
when(ruleFinder.findByKey(anyString(), anyString())).thenAnswer(new Answer<Rule>(){ | |||
public Rule answer(InvocationOnMock iom) throws Throwable { | |||
return Rule.create((String)iom.getArguments()[0], (String)iom.getArguments()[1], (String)iom.getArguments()[1]); | |||
} | |||
}); | |||
ProfileDefinition definition = new FakeDefinition(ruleFinder); | |||
ValidationMessages validation = ValidationMessages.create(); | |||
ProfilePrototype profile = definition.createPrototype(validation); | |||
assertThat(profile.getRule("squid", "fake").getPriority(), is(RulePriority.BLOCKER)); | |||
RulesProfile profile = definition.createProfile(validation); | |||
assertThat(profile.getActiveRule("squid", "fake").getPriority(), is(RulePriority.BLOCKER)); | |||
assertThat(validation.hasErrors(), is(false)); | |||
} | |||
} | |||
@@ -54,7 +68,7 @@ class FakeRule { | |||
class FakeDefinition extends AnnotationProfileDefinition { | |||
public FakeDefinition() { | |||
super("squid", "sonar way", "java", Arrays.<Class>asList(FakeRule.class)); | |||
public FakeDefinition(RuleFinder ruleFinder) { | |||
super("squid", "sonar way", "java", Arrays.<Class>asList(FakeRule.class), ruleFinder); | |||
} | |||
} |
@@ -30,10 +30,10 @@ import static org.junit.Assert.assertThat; | |||
public class ProfileImporterTest { | |||
@Test | |||
public void testSupportedRepositories() { | |||
public void testSupportedLanguages() { | |||
ProfileImporter inmporter = new ProfileImporter("all", "All") { | |||
@Override | |||
public ProfilePrototype importProfile(Reader reader, ValidationMessages messages) { | |||
public RulesProfile importProfile(Reader reader, ValidationMessages messages) { | |||
return null; | |||
} | |||
}; | |||
@@ -45,10 +45,10 @@ public class ProfileImporterTest { | |||
} | |||
@Test | |||
public void supportAllRepositories() { | |||
public void supportAllLanguages() { | |||
ProfileImporter importer = new ProfileImporter("all", "All") { | |||
@Override | |||
public ProfilePrototype importProfile(Reader reader, ValidationMessages messages) { | |||
public RulesProfile importProfile(Reader reader, ValidationMessages messages) { | |||
return null; | |||
} | |||
}; |
@@ -1,55 +0,0 @@ | |||
/* | |||
* Sonar, open source software quality management tool. | |||
* Copyright (C) 2009 SonarSource SA | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* Sonar 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. | |||
* | |||
* Sonar 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 Sonar; if not, write to the Free Software | |||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 | |||
*/ | |||
package org.sonar.api.profiles; | |||
import org.junit.Test; | |||
import org.sonar.api.rules.RulePriority; | |||
import static org.hamcrest.CoreMatchers.not; | |||
import static org.hamcrest.core.Is.is; | |||
import static org.hamcrest.core.IsNull.nullValue; | |||
import static org.junit.Assert.assertThat; | |||
public class ProfilePrototypeTest { | |||
@Test | |||
public void addRuleByKey() { | |||
ProfilePrototype profile = ProfilePrototype.create(); | |||
profile.activateRule("checkstyle", "JavadocCheck", RulePriority.MINOR); | |||
profile.activateRule("checkstyle", "EqualsHashCodeCheck", RulePriority.BLOCKER); | |||
profile.activateRule("findbugs", "DetectNullPointer", RulePriority.BLOCKER); | |||
assertThat(profile.getRules().size(), is(3)); | |||
assertThat(profile.getRulesByRepositoryKey("checkstyle").size(), is(2)); | |||
assertThat(profile.getRulesByRepositoryKey("pmd").size(), is(0)); | |||
assertThat(profile.getRule("findbugs", "DetectNullPointer"), not(nullValue())); | |||
assertThat(profile.getRule("findbugs", "DetectNullPointer").getPriority(), is(RulePriority.BLOCKER)); | |||
} | |||
@Test | |||
public void addRuleByConfigKey() { | |||
ProfilePrototype profile = ProfilePrototype.create(); | |||
profile.activateRule(ProfilePrototype.RulePrototype.createByConfigKey("checkstyle", "Checker/TreeWalker/EqualsHashCode")); | |||
assertThat(profile.getRules().size(), is(1)); | |||
assertThat(profile.getRule("checkstyle", "Checker/TreeWalker/EqualsHashCode"), nullValue()); | |||
assertThat(profile.getRuleByConfigKey("checkstyle", "Checker/TreeWalker/EqualsHashCode"), not(nullValue())); | |||
} | |||
} |
@@ -22,6 +22,11 @@ package org.sonar.api.profiles; | |||
import org.apache.commons.io.IOUtils; | |||
import org.apache.commons.lang.CharEncoding; | |||
import org.junit.Test; | |||
import org.mockito.invocation.InvocationOnMock; | |||
import org.mockito.stubbing.Answer; | |||
import org.sonar.api.rules.ActiveRule; | |||
import org.sonar.api.rules.Rule; | |||
import org.sonar.api.rules.RuleFinder; | |||
import org.sonar.api.rules.RulePriority; | |||
import org.sonar.api.utils.ValidationMessages; | |||
@@ -29,9 +34,13 @@ import java.io.InputStreamReader; | |||
import java.io.Reader; | |||
import java.io.UnsupportedEncodingException; | |||
import static org.hamcrest.CoreMatchers.nullValue; | |||
import static org.hamcrest.Matchers.is; | |||
import static org.junit.Assert.assertNotNull; | |||
import static org.junit.Assert.assertThat; | |||
import static org.mockito.Matchers.anyString; | |||
import static org.mockito.Mockito.mock; | |||
import static org.mockito.Mockito.when; | |||
public class XMLProfileImporterTest { | |||
@@ -40,11 +49,14 @@ public class XMLProfileImporterTest { | |||
Reader reader = new InputStreamReader(getClass().getResourceAsStream("/org/sonar/api/profiles/XMLProfileImporterTest/importProfile.xml"), CharEncoding.UTF_8); | |||
try { | |||
ValidationMessages validation = ValidationMessages.create(); | |||
ProfilePrototype profile = XMLProfileImporter.create().importProfile(reader, validation); | |||
RuleFinder ruleFinder = newRuleFinder(); | |||
RulesProfile profile = XMLProfileImporter.create(ruleFinder).importProfile(reader, validation); | |||
assertThat(profile.getLanguage(), is("java")); | |||
assertThat(profile.getName(), is("sonar way")); | |||
assertThat(validation.hasErrors(), is(false)); | |||
assertNotNull(profile); | |||
assertThat(profile.getRule("checkstyle", "IllegalRegexp").getPriority(), is(RulePriority.CRITICAL)); | |||
assertThat(profile.getActiveRule("checkstyle", "IllegalRegexp").getPriority(), is(RulePriority.CRITICAL)); | |||
} finally { | |||
IOUtils.closeQuietly(reader); | |||
@@ -56,10 +68,12 @@ public class XMLProfileImporterTest { | |||
Reader reader = new InputStreamReader(getClass().getResourceAsStream("/org/sonar/api/profiles/XMLProfileImporterTest/importProfileWithRuleParameters.xml"), CharEncoding.UTF_8); | |||
try { | |||
ValidationMessages validation = ValidationMessages.create(); | |||
ProfilePrototype profile = XMLProfileImporter.create().importProfile(reader, validation); | |||
RuleFinder ruleFinder = newRuleFinder(); | |||
RulesProfile profile = XMLProfileImporter.create(ruleFinder).importProfile(reader, validation); | |||
assertThat(validation.hasErrors(), is(false)); | |||
ProfilePrototype.RulePrototype rule = profile.getRule("checkstyle", "IllegalRegexp"); | |||
assertThat(validation.hasWarnings(), is(false)); | |||
ActiveRule rule = profile.getActiveRule("checkstyle", "IllegalRegexp"); | |||
assertThat(rule.getParameter("format"), is("foo")); | |||
assertThat(rule.getParameter("message"), is("with special characters < > &")); | |||
@@ -67,4 +81,34 @@ public class XMLProfileImporterTest { | |||
IOUtils.closeQuietly(reader); | |||
} | |||
} | |||
} | |||
@Test | |||
public void importProfileWithUnknownRuleParameter() throws UnsupportedEncodingException { | |||
Reader reader = new InputStreamReader(getClass().getResourceAsStream("/org/sonar/api/profiles/XMLProfileImporterTest/importProfileWithUnknownRuleParameter.xml"), CharEncoding.UTF_8); | |||
try { | |||
ValidationMessages validation = ValidationMessages.create(); | |||
RuleFinder ruleFinder = newRuleFinder(); | |||
RulesProfile profile = XMLProfileImporter.create(ruleFinder).importProfile(reader, validation); | |||
assertThat(validation.getWarnings().size(), is(1)); | |||
ActiveRule rule = profile.getActiveRule("checkstyle", "IllegalRegexp"); | |||
assertThat(rule.getParameter("unknown"), nullValue()); | |||
} finally { | |||
IOUtils.closeQuietly(reader); | |||
} | |||
} | |||
private RuleFinder newRuleFinder() { | |||
RuleFinder ruleFinder = mock(RuleFinder.class); | |||
when(ruleFinder.findByKey(anyString(), anyString())).thenAnswer(new Answer<Rule>(){ | |||
public Rule answer(InvocationOnMock iom) throws Throwable { | |||
Rule rule = Rule.create((String) iom.getArguments()[0], (String) iom.getArguments()[1], (String) iom.getArguments()[1]); | |||
rule.createParameter("format"); | |||
rule.createParameter("message"); | |||
return rule; | |||
} | |||
}); | |||
return ruleFinder; | |||
} | |||
} |
@@ -1,5 +1,6 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<!-- Generated by Sonar --> | |||
<profile> | |||
<name>sonar way</name> | |||
<language>java</language> | |||
</profile> |
@@ -1,6 +1,8 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<!-- Generated by Sonar --> | |||
<profile> | |||
<name>sonar way</name> | |||
<language>java</language> | |||
<rules> | |||
<rule> | |||
<repositoryKey>checkstyle</repositoryKey> |
@@ -1,6 +1,8 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<!-- Generated by Sonar --> | |||
<profile> | |||
<name>sonar way</name> | |||
<language>java</language> | |||
<rules> | |||
<rule> | |||
<repositoryKey>checkstyle</repositoryKey> |
@@ -1,6 +1,8 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<!-- Generated by Sonar --> | |||
<profile> | |||
<name>sonar way</name> | |||
<language>java</language> | |||
<rules> | |||
<rule> | |||
<repositoryKey>checkstyle</repositoryKey> |
@@ -1,6 +1,8 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<!-- Generated by Sonar --> | |||
<profile> | |||
<name>sonar way</name> | |||
<language>java</language> | |||
<rules> | |||
<rule> | |||
<repositoryKey>checkstyle</repositoryKey> |
@@ -0,0 +1,19 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<!-- Generated by Sonar --> | |||
<profile> | |||
<name>sonar way</name> | |||
<language>java</language> | |||
<rules> | |||
<rule> | |||
<repositoryKey>checkstyle</repositoryKey> | |||
<key>IllegalRegexp</key> | |||
<priority>BLOCKER</priority> | |||
<parameters> | |||
<parameter> | |||
<key>unknown</key> | |||
<value>foo</value> | |||
</parameter> | |||
</parameters> | |||
</rule> | |||
</rules> | |||
</profile> |