瀏覽代碼

SONAR-1229 simplify the profiles API

tags/2.6
simonbrandhof 13 年之前
父節點
當前提交
cdd05f32ec
共有 30 個檔案被更改,包括 404 行新增415 行删除
  1. 2
    8
      plugins/sonar-checkstyle-plugin/src/main/java/org/sonar/plugins/checkstyle/CheckstyleProfileExporter.java
  2. 26
    14
      plugins/sonar-checkstyle-plugin/src/main/java/org/sonar/plugins/checkstyle/CheckstyleProfileImporter.java
  3. 3
    2
      plugins/sonar-checkstyle-plugin/src/main/java/org/sonar/plugins/checkstyle/SonarWayProfile.java
  4. 16
    3
      plugins/sonar-checkstyle-plugin/src/main/java/org/sonar/plugins/checkstyle/SonarWayWithFindbugsProfile.java
  5. 3
    2
      plugins/sonar-checkstyle-plugin/src/main/java/org/sonar/plugins/checkstyle/SunConventionsProfile.java
  6. 2
    0
      plugins/sonar-checkstyle-plugin/src/main/resources/org/sonar/plugins/checkstyle/profile-sonar-way.xml
  7. 2
    0
      plugins/sonar-checkstyle-plugin/src/main/resources/org/sonar/plugins/checkstyle/profile-sun-conventions.xml
  8. 60
    21
      plugins/sonar-checkstyle-plugin/src/test/java/org/sonar/plugins/checkstyle/CheckstyleProfileImporterTest.java
  9. 20
    4
      plugins/sonar-checkstyle-plugin/src/test/java/org/sonar/plugins/checkstyle/SonarWayProfileTest.java
  10. 26
    6
      plugins/sonar-checkstyle-plugin/src/test/java/org/sonar/plugins/checkstyle/SonarWayWithFindbugsProfileTest.java
  11. 22
    8
      plugins/sonar-checkstyle-plugin/src/test/java/org/sonar/plugins/checkstyle/SunConventionsProfileTest.java
  12. 2
    2
      plugins/sonar-checkstyle-plugin/src/test/resources/org/sonar/plugins/checkstyle/CheckstyleProfileImporterTest/importingFiltersIsNotSupported.xml
  13. 20
    10
      sonar-plugin-api/src/main/java/org/sonar/api/profiles/AnnotationProfileDefinition.java
  14. 1
    1
      sonar-plugin-api/src/main/java/org/sonar/api/profiles/ProfileDefinition.java
  15. 22
    11
      sonar-plugin-api/src/main/java/org/sonar/api/profiles/ProfileImporter.java
  16. 0
    218
      sonar-plugin-api/src/main/java/org/sonar/api/profiles/ProfilePrototype.java
  17. 6
    10
      sonar-plugin-api/src/main/java/org/sonar/api/profiles/XMLProfileDefinition.java
  18. 11
    7
      sonar-plugin-api/src/main/java/org/sonar/api/profiles/XMLProfileExporter.java
  19. 47
    16
      sonar-plugin-api/src/main/java/org/sonar/api/profiles/XMLProfileImporter.java
  20. 12
    2
      sonar-plugin-api/src/main/java/org/sonar/api/rules/ActiveRule.java
  21. 19
    5
      sonar-plugin-api/src/test/java/org/sonar/api/profiles/AnnotationProfileDefinitionTest.java
  22. 4
    4
      sonar-plugin-api/src/test/java/org/sonar/api/profiles/ProfileImporterTest.java
  23. 0
    55
      sonar-plugin-api/src/test/java/org/sonar/api/profiles/ProfilePrototypeTest.java
  24. 49
    5
      sonar-plugin-api/src/test/java/org/sonar/api/profiles/XMLProfileImporterTest.java
  25. 2
    1
      sonar-plugin-api/src/test/resources/org/sonar/api/profiles/XMLProfileExporterTest/exportEmptyProfile.xml
  26. 2
    0
      sonar-plugin-api/src/test/resources/org/sonar/api/profiles/XMLProfileExporterTest/exportProfile.xml
  27. 2
    0
      sonar-plugin-api/src/test/resources/org/sonar/api/profiles/XMLProfileExporterTest/exportRuleParameters.xml
  28. 2
    0
      sonar-plugin-api/src/test/resources/org/sonar/api/profiles/XMLProfileImporterTest/importProfile.xml
  29. 2
    0
      sonar-plugin-api/src/test/resources/org/sonar/api/profiles/XMLProfileImporterTest/importProfileWithRuleParameters.xml
  30. 19
    0
      sonar-plugin-api/src/test/resources/org/sonar/api/profiles/XMLProfileImporterTest/importProfileWithUnknownRuleParameter.xml

+ 2
- 8
plugins/sonar-checkstyle-plugin/src/main/java/org/sonar/plugins/checkstyle/CheckstyleProfileExporter.java 查看文件

@@ -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);
}
}

+ 26
- 14
plugins/sonar-checkstyle-plugin/src/main/java/org/sonar/plugins/checkstyle/CheckstyleProfileImporter.java 查看文件

@@ -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);
}
}
}

+ 3
- 2
plugins/sonar-checkstyle-plugin/src/main/java/org/sonar/plugins/checkstyle/SonarWayProfile.java 查看文件

@@ -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);
}
}

+ 16
- 3
plugins/sonar-checkstyle-plugin/src/main/java/org/sonar/plugins/checkstyle/SonarWayWithFindbugsProfile.java 查看文件

@@ -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;
}
}


+ 3
- 2
plugins/sonar-checkstyle-plugin/src/main/java/org/sonar/plugins/checkstyle/SunConventionsProfile.java 查看文件

@@ -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);
}
}

+ 2
- 0
plugins/sonar-checkstyle-plugin/src/main/resources/org/sonar/plugins/checkstyle/profile-sonar-way.xml 查看文件

@@ -1,4 +1,6 @@
<profile>
<name>Sonar way</name>
<language>java</language>
<rules>
<rule>
<repositoryKey>checkstyle</repositoryKey>

+ 2
- 0
plugins/sonar-checkstyle-plugin/src/main/resources/org/sonar/plugins/checkstyle/profile-sun-conventions.xml 查看文件

@@ -1,4 +1,6 @@
<profile>
<name>Sun checks</name>
<language>java</language>
<rules>
<rule>
<repositoryKey>checkstyle</repositoryKey>

+ 60
- 21
plugins/sonar-checkstyle-plugin/src/test/java/org/sonar/plugins/checkstyle/CheckstyleProfileImporterTest.java 查看文件

@@ -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
- 4
plugins/sonar-checkstyle-plugin/src/test/java/org/sonar/plugins/checkstyle/SonarWayProfileTest.java 查看文件

@@ -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;
}
}

+ 26
- 6
plugins/sonar-checkstyle-plugin/src/test/java/org/sonar/plugins/checkstyle/SonarWayWithFindbugsProfileTest.java 查看文件

@@ -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;
}

}

+ 22
- 8
plugins/sonar-checkstyle-plugin/src/test/java/org/sonar/plugins/checkstyle/SunConventionsProfileTest.java 查看文件

@@ -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;
}

}

+ 2
- 2
plugins/sonar-checkstyle-plugin/src/test/resources/org/sonar/plugins/checkstyle/CheckstyleProfileImporterTest/importingFiltersIsNotSupported.xml 查看文件

@@ -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>

+ 20
- 10
sonar-plugin-api/src/main/java/org/sonar/api/profiles/AnnotationProfileDefinition.java 查看文件

@@ -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);
}
}
}

+ 1
- 1
sonar-plugin-api/src/main/java/org/sonar/api/profiles/ProfileDefinition.java 查看文件

@@ -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);

}

+ 22
- 11
sonar-plugin-api/src/main/java/org/sonar/api/profiles/ProfileImporter.java 查看文件

@@ -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();
}
}

+ 0
- 218
sonar-plugin-api/src/main/java/org/sonar/api/profiles/ProfilePrototype.java 查看文件

@@ -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();
}
}
}

+ 6
- 10
sonar-plugin-api/src/main/java/org/sonar/api/profiles/XMLProfileDefinition.java 查看文件

@@ -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);

+ 11
- 7
sonar-plugin-api/src/main/java/org/sonar/api/profiles/XMLProfileExporter.java 查看文件

@@ -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());

+ 47
- 16
sonar-plugin-api/src/main/java/org/sonar/api/profiles/XMLProfileImporter.java 查看文件

@@ -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);
}
}
}

+ 12
- 2
sonar-plugin-api/src/main/java/org/sonar/api/rules/ActiveRule.java 查看文件

@@ -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;
}


+ 19
- 5
sonar-plugin-api/src/test/java/org/sonar/api/profiles/AnnotationProfileDefinitionTest.java 查看文件

@@ -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);
}
}

+ 4
- 4
sonar-plugin-api/src/test/java/org/sonar/api/profiles/ProfileImporterTest.java 查看文件

@@ -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;
}
};

+ 0
- 55
sonar-plugin-api/src/test/java/org/sonar/api/profiles/ProfilePrototypeTest.java 查看文件

@@ -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()));
}
}

+ 49
- 5
sonar-plugin-api/src/test/java/org/sonar/api/profiles/XMLProfileImporterTest.java 查看文件

@@ -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;
}
}

+ 2
- 1
sonar-plugin-api/src/test/resources/org/sonar/api/profiles/XMLProfileExporterTest/exportEmptyProfile.xml 查看文件

@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated by Sonar -->
<profile>

<name>sonar way</name>
<language>java</language>
</profile>

+ 2
- 0
sonar-plugin-api/src/test/resources/org/sonar/api/profiles/XMLProfileExporterTest/exportProfile.xml 查看文件

@@ -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>

+ 2
- 0
sonar-plugin-api/src/test/resources/org/sonar/api/profiles/XMLProfileExporterTest/exportRuleParameters.xml 查看文件

@@ -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>

+ 2
- 0
sonar-plugin-api/src/test/resources/org/sonar/api/profiles/XMLProfileImporterTest/importProfile.xml 查看文件

@@ -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>

+ 2
- 0
sonar-plugin-api/src/test/resources/org/sonar/api/profiles/XMLProfileImporterTest/importProfileWithRuleParameters.xml 查看文件

@@ -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>

+ 19
- 0
sonar-plugin-api/src/test/resources/org/sonar/api/profiles/XMLProfileImporterTest/importProfileWithUnknownRuleParameter.xml 查看文件

@@ -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>

Loading…
取消
儲存