Parcourir la source

SONAR 1076 - Run PMD on Unit Tests

tags/3.1
David Gageot il y a 12 ans
Parent
révision
1a6a18a5c4
56 fichiers modifiés avec 1289 ajouts et 1338 suppressions
  1. 1
    2
      plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/ViolationsDecorator.java
  2. 1
    2
      plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/NewViolationsDecorator.java
  3. 10
    0
      plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/pmd.properties
  4. 8
    0
      plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/pmd/rules/pmd-unit-tests/JUnitAssertionsShouldIncludeMessage.html
  5. 9
    0
      plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/pmd/rules/pmd-unit-tests/JUnitSpelling.html
  6. 9
    0
      plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/pmd/rules/pmd-unit-tests/JUnitStaticSuite.html
  7. 10
    0
      plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/pmd/rules/pmd-unit-tests/JUnitTestsShouldIncludeAssert.html
  8. 9
    0
      plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/pmd/rules/pmd-unit-tests/SimplifyBooleanAssertion.html
  9. 9
    0
      plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/pmd/rules/pmd-unit-tests/TestClassWithoutTestCases.html
  10. 7
    0
      plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/pmd/rules/pmd-unit-tests/UnnecessaryBooleanAssertion.html
  11. 10
    0
      plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/pmd/rules/pmd-unit-tests/UseAssertEqualsInsteadOfAssertTrue.html
  12. 13
    0
      plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/pmd/rules/pmd-unit-tests/UseAssertNullInsteadOfAssertTrue.html
  13. 11
    0
      plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/pmd/rules/pmd-unit-tests/UseAssertSameInsteadOfAssertTrue.html
  14. 7
    0
      plugins/sonar-pmd-plugin/pom.xml
  15. 13
    14
      plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/JavaCpdMapping.java
  16. 49
    22
      plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdConfiguration.java
  17. 2
    0
      plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdConstants.java
  18. 57
    118
      plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdExecutor.java
  19. 12
    32
      plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdLevelUtils.java
  20. 4
    3
      plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdPlugin.java
  21. 19
    14
      plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdProfileExporter.java
  22. 2
    4
      plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdRuleRepository.java
  23. 18
    36
      plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdSensor.java
  24. 98
    0
      plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdTemplate.java
  25. 44
    0
      plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdUnitTestsRuleRepository.java
  26. 12
    8
      plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdVersion.java
  27. 82
    0
      plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdViolationToRuleViolation.java
  28. 17
    10
      plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/SonarWayProfile.java
  29. 5
    6
      plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/SonarWayWithFindbugsProfile.java
  30. 17
    11
      plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/SunConventionsProfile.java
  31. 42
    0
      plugins/sonar-pmd-plugin/src/main/resources/org/sonar/plugins/pmd/rules-unit-tests.xml
  32. 63
    24
      plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdConfigurationTest.java
  33. 82
    63
      plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdExecutorTest.java
  34. 47
    0
      plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdLevelUtilsTest.java
  35. 10
    7
      plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdPluginTest.java
  36. 62
    100
      plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdProfileExporterTest.java
  37. 70
    58
      plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdProfileImporterTest.java
  38. 37
    22
      plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdProfilesTest.java
  39. 43
    16
      plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdRuleRepositoryTest.java
  40. 126
    0
      plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdSensorTest.java
  41. 59
    0
      plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdTemplateTest.java
  42. 71
    0
      plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdUnitTestsRuleRepositoryTest.java
  43. 3
    7
      plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdVersionTest.java
  44. 0
    66
      plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/SonarWayProfileTest.java
  45. 0
    65
      plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/SonarWayWithFindbugsProfileTest.java
  46. 0
    22
      plugins/sonar-pmd-plugin/src/test/resources/org/sonar/plugins/pmd/PmdConfigurationTest/failIfConfigurationToReuseDoesNotExist/pom.xml
  47. 0
    27
      plugins/sonar-pmd-plugin/src/test/resources/org/sonar/plugins/pmd/PmdConfigurationTest/findConfigurationToReuse/pom.xml
  48. 0
    8
      plugins/sonar-pmd-plugin/src/test/resources/org/sonar/plugins/pmd/PmdConfigurationTest/writeConfigurationToWorkingDir/pom.xml
  49. 0
    263
      plugins/sonar-pmd-plugin/src/test/resources/org/sonar/plugins/pmd/PmdExecutorTest/executeOnManySourceDirs/pmd.xml
  50. 0
    9
      plugins/sonar-pmd-plugin/src/test/resources/org/sonar/plugins/pmd/PmdExecutorTest/executeOnManySourceDirs/src1/FirstClass.java
  51. 0
    9
      plugins/sonar-pmd-plugin/src/test/resources/org/sonar/plugins/pmd/PmdExecutorTest/executeOnManySourceDirs/src2/SecondClass.java
  52. 7
    0
      plugins/sonar-pmd-plugin/src/test/resources/org/sonar/plugins/pmd/junit.xml
  53. 0
    20
      plugins/sonar-pmd-plugin/src/test/resources/org/sonar/plugins/pmd/test_xml_complete.xml
  54. 0
    5
      plugins/sonar-pmd-plugin/test-resources/ignorePmdFailures/DoesNotCompile.java
  55. 0
    263
      plugins/sonar-pmd-plugin/test-resources/ignorePmdFailures/pmd.xml
  56. 2
    2
      sonar-server/src/main/java/org/sonar/server/ui/DefaultPages.java

+ 1
- 2
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/ViolationsDecorator.java Voir le fichier

@@ -26,7 +26,6 @@ import org.sonar.api.batch.*;
import org.sonar.api.measures.*;
import org.sonar.api.resources.Project;
import org.sonar.api.resources.Resource;
import org.sonar.api.resources.ResourceUtils;
import org.sonar.api.rules.Rule;
import org.sonar.api.rules.RulePriority;
import org.sonar.api.rules.Violation;
@@ -44,7 +43,7 @@ public class ViolationsDecorator implements Decorator {
}

private boolean shouldDecorateResource(Resource resource) {
return !ResourceUtils.isUnitTestClass(resource);
return true;
}

@DependedUpon

+ 1
- 2
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/NewViolationsDecorator.java Voir le fichier

@@ -96,8 +96,7 @@ public class NewViolationsDecorator implements Decorator {
private boolean shouldDecorateResource(Resource<?> resource, DecoratorContext context) {
return (StringUtils.equals(Scopes.PROJECT, resource.getScope()) || StringUtils.equals(Scopes.DIRECTORY, resource.getScope()) || StringUtils
.equals(Scopes.FILE, resource.getScope()))
&& !ResourceUtils.isUnitTestClass(resource)
&& context.getMeasure(CoreMetrics.NEW_VIOLATIONS) == null;
&& (context.getMeasure(CoreMetrics.NEW_VIOLATIONS) == null);
}

private void computeNewViolations(DecoratorContext context) {

+ 10
- 0
plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/pmd.properties Voir le fichier

@@ -275,3 +275,13 @@ rule.pmd.UseConcurrentHashMap.name=Use ConcurrentHashMap
rule.pmd.DoNotHardCodeSDCard.name=Android - Do Not Hard Code SD Card
rule.pmd.DontCallThreadRun.name=Dont Call Thread Run
rule.pmd.GuardDebugLogging.name=Guard Debug Logging
rule.pmd-unit-tests.JUnitStaticSuite.name=JUnit static suite
rule.pmd-unit-tests.JUnitSpelling.name= JUnit spelling
rule.pmd-unit-tests.JUnitAssertionsShouldIncludeMessage.name=JUnit assertions should include a message
rule.pmd-unit-tests.JUnitTestsShouldIncludeAssert.name=JUnit tests should include an assert
rule.pmd-unit-tests.TestClassWithoutTestCases.name=Test class without test cases
rule.pmd-unit-tests.UnnecessaryBooleanAssertion.name=Unnecessary boolean assertion
rule.pmd-unit-tests.UseAssertEqualsInsteadOfAssertTrue.name=Use assertEquals instead of assertTrue
rule.pmd-unit-tests.UseAssertSameInsteadOfAssertTrue.name=Use assertSame instead of assertTrue
rule.pmd-unit-tests.UseAssertNullInsteadOfAssertTrue.name=Use assertNull instead of assertTrue
rule.pmd-unit-tests.SimplifyBooleanAssertion.name=Simplify boolean assertion

+ 8
- 0
plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/pmd/rules/pmd-unit-tests/JUnitAssertionsShouldIncludeMessage.html Voir le fichier

@@ -0,0 +1,8 @@
JUnit assertions should include a message - i.e., use the three argument version of assertEquals(), not the two argument version.
<pre>
public class Foo extends TestCase {
public void testSomething() {
assertEquals("foo", "bar"); // violation, should be assertEquals("Foo does not equals bar", "foo", "bar");
}
}
</pre>

+ 9
- 0
plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/pmd/rules/pmd-unit-tests/JUnitSpelling.html Voir le fichier

@@ -0,0 +1,9 @@
Some JUnit framework methods are easy to misspell.
<pre>
import junit.framework.*;

public class Foo extends TestCase {
public void setup() {} // violation, should be setUp()
public void TearDown() {} // violation, should be tearDown()
}
</pre>

+ 9
- 0
plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/pmd/rules/pmd-unit-tests/JUnitStaticSuite.html Voir le fichier

@@ -0,0 +1,9 @@
The suite() method in a JUnit test needs to be both public and static.
<pre>
import junit.framework.*;

public class Foo extends TestCase {
public void suite() {} // violation, should be static
private static void suite() {} // violation, should be public
}
</pre>

+ 10
- 0
plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/pmd/rules/pmd-unit-tests/JUnitTestsShouldIncludeAssert.html Voir le fichier

@@ -0,0 +1,10 @@
JUnit tests should include at least one assertion. This makes the tests more robust, and using assert with messages provide the developer a clearer idea of what the test does.
<pre>
public class Foo extends TestCase {
public void testSomething() {
Bar b = findBar();
b.work();
// violation, we could use assertNotNull("bar not found", b);
}
}
</pre>

+ 9
- 0
plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/pmd/rules/pmd-unit-tests/SimplifyBooleanAssertion.html Voir le fichier

@@ -0,0 +1,9 @@
Avoid negation in an assertTrue or assertFalse test. For example, rephrase: assertTrue(!expr); as: assertFalse(expr);
<pre>
public class SimpleTest extends TestCase {
public void testX() {
assertTrue("not empty", !r.isEmpty()); // violation, replace with assertFalse("not empty", r.isEmpty())
assertFalse(!r.isEmpty()); // violation, replace with assertTrue("empty", r.isEmpty())
}
}
</pre>

+ 9
- 0
plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/pmd/rules/pmd-unit-tests/TestClassWithoutTestCases.html Voir le fichier

@@ -0,0 +1,9 @@
Test classes end with the suffix Test. Having a non-test class with that name is not a good practice, since most people will assume it is a test case. Test classes have test methods named testXXX.
<pre>
public class CarTest { // violation, consider changing the name of the class if it is not a test
// consider adding test methods if it is a test
public static void main(String[] args) {
// do something
}
}
</pre>

+ 7
- 0
plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/pmd/rules/pmd-unit-tests/UnnecessaryBooleanAssertion.html Voir le fichier

@@ -0,0 +1,7 @@
A JUnit test assertion with a boolean literal is unnecessary since it always will eval to the same thing. Consider using flow control (in case of assertTrue(false) or similar) or simply removing statements like assertTrue(true) and assertFalse(false). If you just want a test to halt, use the fail method.
<pre>
public class SimpleTest extends TestCase {
public void testX() {
assertTrue(true); // violation
}
}</pre>

+ 10
- 0
plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/pmd/rules/pmd-unit-tests/UseAssertEqualsInsteadOfAssertTrue.html Voir le fichier

@@ -0,0 +1,10 @@
This rule detects JUnit assertions in object equality. These assertions should be made by more specific methods, like assertEquals.
<pre>
public class FooTest extends TestCase {
void testCode() {
Object a, b;

assertTrue(a.equals(b)); // violation
assertEquals("a should equals b", a, b); // good usage
}
}</pre>

+ 13
- 0
plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/pmd/rules/pmd-unit-tests/UseAssertNullInsteadOfAssertTrue.html Voir le fichier

@@ -0,0 +1,13 @@
This rule detects JUnit assertions in object references equality. These assertions should be made by more specific methods, like assertNull, assertNotNull.
<pre>
public class FooTest extends TestCase {
void testCode() {
Object a = doSomething();

assertTrue(a==null); // violation
assertNull(a); // good usage
assertTrue(a != null); // violation
assertNotNull(a); // good usage
}
}
</pre>

+ 11
- 0
plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/pmd/rules/pmd-unit-tests/UseAssertSameInsteadOfAssertTrue.html Voir le fichier

@@ -0,0 +1,11 @@
This rule detects JUnit assertions in object references equality. These assertions should be made by more specific methods, like assertSame, assertNotSame.
<pre>
public class FooTest extends TestCase {
void testCode() {
Object a, b;

assertTrue(a==b); // violation
assertSame(a, b); // good usage
}
}
</pre>

+ 7
- 0
plugins/sonar-pmd-plugin/pom.xml Voir le fichier

@@ -65,6 +65,13 @@
<artifactId>sonar-testing-harness</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.codehaus.sonar.plugins</groupId>
<artifactId>sonar-l10n-en-plugin</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
</dependencies>

<build>

+ 13
- 14
plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/JavaCpdMapping.java Voir le fichier

@@ -19,37 +19,36 @@
*/
package org.sonar.plugins.pmd;

import java.io.File;
import java.util.List;
import java.util.Properties;

import net.sourceforge.pmd.cpd.JavaTokenizer;
import net.sourceforge.pmd.cpd.Tokenizer;

import org.sonar.api.CoreProperties;
import org.sonar.api.batch.CpdMapping;
import org.sonar.api.config.Settings;
import org.sonar.api.resources.Java;
import org.sonar.api.resources.JavaFile;
import org.sonar.api.resources.Language;
import org.sonar.api.resources.Project;
import org.sonar.api.resources.Resource;

public class JavaCpdMapping implements CpdMapping {
import java.io.File;
import java.util.List;
import java.util.Properties;

private String ignore_literals;
private String ignore_identifiers;
import static com.google.common.base.Objects.firstNonNull;

public JavaCpdMapping(Project project) {
ignore_literals = project.getConfiguration().getString(CoreProperties.CPD_IGNORE_LITERALS_PROPERTY,
CoreProperties.CPD_IGNORE_LITERALS_DEFAULT_VALUE);
ignore_identifiers = project.getConfiguration().getString(CoreProperties.CPD_IGNORE_IDENTIFIERS_PROPERTY,
CoreProperties.CPD_IGNORE_IDENTIFIERS_DEFAULT_VALUE);
public class JavaCpdMapping implements CpdMapping {
private final String ignore_literals;
private final String ignore_identifiers;

public JavaCpdMapping(Settings settings) {
ignore_literals = firstNonNull(settings.getString(CoreProperties.CPD_IGNORE_LITERALS_PROPERTY), CoreProperties.CPD_IGNORE_LITERALS_DEFAULT_VALUE);
ignore_identifiers = firstNonNull(settings.getString(CoreProperties.CPD_IGNORE_IDENTIFIERS_PROPERTY), CoreProperties.CPD_IGNORE_IDENTIFIERS_DEFAULT_VALUE);
}

public Tokenizer getTokenizer() {
Properties props = new Properties();
props.setProperty(JavaTokenizer.IGNORE_LITERALS, ignore_literals);
props.setProperty(JavaTokenizer.IGNORE_IDENTIFIERS, ignore_identifiers);

JavaTokenizer tokenizer = new JavaTokenizer();
tokenizer.setProperties(props);
return tokenizer;

+ 49
- 22
plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdConfiguration.java Voir le fichier

@@ -19,18 +19,20 @@
*/
package org.sonar.plugins.pmd;

import net.sourceforge.pmd.Report;
import net.sourceforge.pmd.renderers.Renderer;
import net.sourceforge.pmd.renderers.XMLRenderer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.api.BatchExtension;
import org.sonar.api.Property;
import org.sonar.api.config.Settings;
import org.sonar.api.profiles.RulesProfile;
import org.sonar.api.resources.Project;
import org.sonar.api.resources.ProjectFileSystem;
import org.sonar.api.utils.SonarException;

import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.util.Arrays;
import java.util.List;

@org.sonar.api.Properties({
@Property(
@@ -42,40 +44,65 @@ import java.util.List;
)
})
public class PmdConfiguration implements BatchExtension {
private static final Logger LOG = LoggerFactory.getLogger(PmdConfiguration.class);

public static final String PROPERTY_GENERATE_XML = "sonar.pmd.generateXml";
public static final String PMD_RESULT_XML = "pmd-result.xml";

private PmdProfileExporter pmdProfileExporter;
private RulesProfile rulesProfile;
private Project project;
private Settings settings;
private final ProjectFileSystem projectFileSystem;
private final Settings settings;

public PmdConfiguration(PmdProfileExporter pmdRulesRepository, RulesProfile rulesProfile, Project project, Settings settings) {
this.pmdProfileExporter = pmdRulesRepository;
this.rulesProfile = rulesProfile;
this.project = project;
public PmdConfiguration(ProjectFileSystem projectFileSystem, Settings settings) {
this.projectFileSystem = projectFileSystem;
this.settings = settings;
}

public List<String> getRulesets() {
return Arrays.asList(saveXmlFile().getAbsolutePath());
public File getTargetXMLReport() {
if (settings.getBoolean(PROPERTY_GENERATE_XML)) {
return projectFileSystem.resolvePath(PMD_RESULT_XML);
}
return null;
}

private File saveXmlFile() {
public File dumpXmlRuleSet(String repositoryKey, String rulesXml) {
try {
StringWriter pmdConfiguration = new StringWriter();
pmdProfileExporter.exportProfile(rulesProfile, pmdConfiguration);
return project.getFileSystem().writeToWorkingDirectory(pmdConfiguration.toString(), "pmd.xml");
File configurationFile = projectFileSystem.writeToWorkingDirectory(rulesXml, repositoryKey + ".xml");
LOG.info("PMD configuration: " + configurationFile.getAbsolutePath());

return configurationFile;
} catch (IOException e) {
throw new SonarException("Fail to save the PMD configuration", e);
}
}

public File getTargetXMLReport() {
if (settings.getBoolean(PROPERTY_GENERATE_XML)) {
return new File(project.getFileSystem().getSonarWorkingDirectory(), "pmd-result.xml");
public File dumpXmlReport(Report report) {
if (!settings.getBoolean(PROPERTY_GENERATE_XML)) {
return null;
}
return null;

try {
String reportAsString = reportToString(report);

File reportFile = projectFileSystem.writeToWorkingDirectory(reportAsString, PMD_RESULT_XML);

LOG.info("PMD output report: " + reportFile.getAbsolutePath());

return reportFile;
} catch (IOException e) {
throw new SonarException("Fail to save the PMD report", e);
}
}

private static String reportToString(Report report) throws IOException {
StringWriter output = new StringWriter();

Renderer xmlRenderer = new XMLRenderer();
xmlRenderer.setWriter(output);
xmlRenderer.start();
xmlRenderer.renderFileReport(report);
xmlRenderer.end();

return output.toString();
}
}

+ 2
- 0
plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdConstants.java Voir le fichier

@@ -24,6 +24,8 @@ import org.sonar.api.CoreProperties;
public final class PmdConstants {
public static final String REPOSITORY_KEY = CoreProperties.PMD_PLUGIN;
public static final String REPOSITORY_NAME = "PMD";
public static final String TEST_REPOSITORY_KEY = "pmd-unit-tests";
public static final String TEST_REPOSITORY_NAME = "PMD Unit Tests";
public static final String PLUGIN_NAME = "PMD";
public static final String PLUGIN_KEY = CoreProperties.PMD_PLUGIN;
public static final String XPATH_CLASS = "net.sourceforge.pmd.rules.XPathRule";

+ 57
- 118
plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdExecutor.java Voir le fichier

@@ -19,166 +19,105 @@
*/
package org.sonar.plugins.pmd;

import net.sourceforge.pmd.PMD;
import net.sourceforge.pmd.PMDException;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.io.Closeables;
import net.sourceforge.pmd.Report;
import net.sourceforge.pmd.RuleContext;
import net.sourceforge.pmd.RuleSet;
import net.sourceforge.pmd.RuleSetFactory;
import net.sourceforge.pmd.RuleSets;
import net.sourceforge.pmd.SourceType;
import net.sourceforge.pmd.renderers.Renderer;
import net.sourceforge.pmd.renderers.XMLRenderer;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.api.BatchExtension;
import org.sonar.api.profiles.RulesProfile;
import org.sonar.api.resources.InputFile;
import org.sonar.api.resources.Java;
import org.sonar.api.resources.Project;
import org.sonar.api.utils.SonarException;
import org.sonar.api.resources.ProjectFileSystem;
import org.sonar.api.utils.TimeProfiler;
import org.sonar.java.api.JavaUtils;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringWriter;
import java.io.Writer;
import java.nio.charset.Charset;
import java.util.List;

public class PmdExecutor implements BatchExtension {

private static final Logger LOG = LoggerFactory.getLogger(PmdExecutor.class);

private final PmdConfiguration configuration;
private final Project project;
private final ProjectFileSystem projectFileSystem;
private final RulesProfile rulesProfile;
private final PmdProfileExporter pmdProfileExporter;
private final PmdConfiguration pmdConfiguration;

public PmdExecutor(Project project, PmdConfiguration configuration) {
public PmdExecutor(Project project, ProjectFileSystem projectFileSystem, RulesProfile rulesProfile, PmdProfileExporter pmdProfileExporter, PmdConfiguration pmdConfiguration) {
this.project = project;
this.configuration = configuration;
this.projectFileSystem = projectFileSystem;
this.rulesProfile = rulesProfile;
this.pmdProfileExporter = pmdProfileExporter;
this.pmdConfiguration = pmdConfiguration;
}

public Report execute() throws IOException {
public Report execute() {
TimeProfiler profiler = new TimeProfiler().start("Execute PMD " + PmdVersion.getVersion());

ClassLoader initialClassLoader = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
try {
PMD pmd = new PMD();
setJavaVersion(pmd, project);
RuleContext ruleContext = new RuleContext();
Report report = new Report();
ruleContext.setReport(report);
Thread.currentThread().setContextClassLoader(getClass().getClassLoader());

RuleSets rulesets = createRulesets();
return executePmd();
} finally {
Thread.currentThread().setContextClassLoader(initialClassLoader);
profiler.stop();
}
}

for (File file : project.getFileSystem().getSourceFiles(Java.INSTANCE)) {
ruleContext.setSourceCodeFilename(file.getAbsolutePath());
Reader fileReader = new InputStreamReader(new FileInputStream(file), project.getFileSystem().getSourceCharset());
try {
pmd.processFile(fileReader, rulesets, ruleContext);
private Report executePmd() {
Report report = new Report();

} catch (PMDException e) {
LOG.error("Fail to execute PMD. Following file is ignored: " + file, e.getCause());
RuleContext context = new RuleContext();
context.setReport(report);

} catch (Exception e) {
LOG.error("Fail to execute PMD. Following file is ignored: " + file, e);
PmdTemplate pmdFactory = createPmdTemplate();
executeRules(pmdFactory, context, projectFileSystem.mainFiles(Java.KEY), PmdConstants.REPOSITORY_KEY);
executeRules(pmdFactory, context, projectFileSystem.testFiles(Java.KEY), PmdConstants.TEST_REPOSITORY_KEY);

} finally {
IOUtils.closeQuietly(fileReader);
}
}
pmdConfiguration.dumpXmlReport(report);

writeXmlReport(report);
return report;
}

return report;
public void executeRules(PmdTemplate pmdFactory, RuleContext ruleContext, List<InputFile> files, String repositoryKey) {
if (files.isEmpty()) {
return; // Nothing to analyse
}

} finally {
profiler.stop();
Thread.currentThread().setContextClassLoader(initialClassLoader);
Charset encoding = projectFileSystem.getSourceCharset();
RuleSets rulesets = createRulesets(repositoryKey);

for (InputFile file : files) {
pmdFactory.process(file.getFile(), encoding, rulesets, ruleContext);
}
}

private RuleSets createRulesets() {
RuleSets rulesets = new RuleSets();
RuleSetFactory ruleSetFactory = new RuleSetFactory();
private RuleSets createRulesets(String repositoryKey) {
String rulesXml = pmdProfileExporter.exportProfile(repositoryKey, rulesProfile);

List<String> rulesetPaths = configuration.getRulesets();
LOG.info("PMD configuration: " + StringUtils.join(rulesetPaths, ", "));
pmdConfiguration.dumpXmlRuleSet(repositoryKey, rulesXml);

for (String rulesetPath : rulesetPaths) {
InputStream rulesInput = openRuleset(rulesetPath);
rulesets.addRuleSet(ruleSetFactory.createRuleSet(rulesInput));
IOUtils.closeQuietly(rulesInput);
}
return rulesets;
return new RuleSets(readRuleSet(rulesXml));
}

private InputStream openRuleset(String rulesetPath) {
private static RuleSet readRuleSet(String rulesXml) {
InputStream rulesInput = null;
try {
File file = new File(rulesetPath);
boolean found;
if (file.exists()) {
found = true;
} else {
file = new File(project.getFileSystem().getBasedir(), rulesetPath);
found = file.exists();
}
if (found) {
return new FileInputStream(file);
}
InputStream stream = PmdExecutor.class.getResourceAsStream(rulesetPath);
if (stream == null) {
throw new SonarException("The PMD ruleset can not be found: " + rulesetPath);
}
return stream;

} catch (FileNotFoundException e) {
throw new SonarException("The PMD ruleset can not be found: " + rulesetPath, e);
}
}
rulesInput = new ByteArrayInputStream(rulesXml.getBytes());

private void writeXmlReport(Report report) throws IOException {
File xmlReport = configuration.getTargetXMLReport();
if (xmlReport != null) {
Renderer xmlRenderer = new XMLRenderer();
Writer stringwriter = new StringWriter();
xmlRenderer.setWriter(stringwriter);
xmlRenderer.start();
xmlRenderer.renderFileReport(report);
xmlRenderer.end();

LOG.info("PMD output report: " + xmlReport.getAbsolutePath());
FileUtils.write(xmlReport, stringwriter.toString());
}
}

static String getNormalizedJavaVersion(String javaVersion) {
if (StringUtils.equals("1.1", javaVersion) || StringUtils.equals("1.2", javaVersion)) {
javaVersion = "1.3";
} else if (StringUtils.equals("5", javaVersion)) {
javaVersion = "1.5";
} else if (StringUtils.equals("6", javaVersion)) {
javaVersion = "1.6";
return new RuleSetFactory().createRuleSet(rulesInput);
} finally {
Closeables.closeQuietly(rulesInput);
}
return javaVersion;
}

private void setJavaVersion(PMD pmd, Project project) {
String javaVersion = getNormalizedJavaVersion(JavaUtils.getSourceVersion(project));
if (javaVersion != null) {
SourceType sourceType = SourceType.getSourceTypeForId("java " + javaVersion);
if (sourceType != null) {
LOG.info("Java version: " + javaVersion);
pmd.setJavaVersion(sourceType);
} else {
throw new SonarException("Unsupported Java version for PMD: " + javaVersion);
}
}
@VisibleForTesting
PmdTemplate createPmdTemplate() {
return new PmdTemplate(JavaUtils.getSourceVersion(project));
}
}

+ 12
- 32
plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdLevelUtils.java Voir le fichier

@@ -19,49 +19,29 @@
*/
package org.sonar.plugins.pmd;

import com.google.common.collect.BiMap;
import com.google.common.collect.EnumHashBiMap;
import org.sonar.api.rules.RulePriority;

import static com.google.common.collect.ImmutableMap.of;

public final class PmdLevelUtils {
private static final BiMap<RulePriority, String> LEVELS_PER_PRIORITY = EnumHashBiMap.create(of(
RulePriority.BLOCKER, "1",
RulePriority.CRITICAL, "2",
RulePriority.MAJOR, "3",
RulePriority.MINOR, "4",
RulePriority.INFO, "5"));

private PmdLevelUtils() {
// only static methods
}

public static RulePriority fromLevel(String level) {
if ("1".equals(level)) {
return RulePriority.BLOCKER;
}
if ("2".equals(level)) {
return RulePriority.CRITICAL;
}
if ("3".equals(level)) {
return RulePriority.MAJOR;
}
if ("4".equals(level)) {
return RulePriority.MINOR;
}
if ("5".equals(level)) {
return RulePriority.INFO;
}
return null;
return LEVELS_PER_PRIORITY.inverse().get(level);
}

public static String toLevel(RulePriority priority) {
if (priority.equals(RulePriority.BLOCKER)) {
return "1";
}
if (priority.equals(RulePriority.CRITICAL)) {
return "2";
}
if (priority.equals(RulePriority.MAJOR)) {
return "3";
}
if (priority.equals(RulePriority.MINOR)) {
return "4";
}
if (priority.equals(RulePriority.INFO)) {
return "5";
}
throw new IllegalArgumentException("Level not supported: " + priority);
return LEVELS_PER_PRIORITY.get(priority);
}
}

+ 4
- 3
plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdPlugin.java Voir le fichier

@@ -26,19 +26,20 @@ import org.sonar.api.SonarPlugin;
import java.util.List;

public class PmdPlugin extends SonarPlugin {
@SuppressWarnings("unchecked")
public List<Class<? extends Extension>> getExtensions() {
return ImmutableList.of(
PmdSensor.class,
PmdConfiguration.class,
PmdExecutor.class,
PmdRuleRepository.class,
PmdUnitTestsRuleRepository.class,
PmdProfileExporter.class,
PmdProfileImporter.class,
SonarWayProfile.class,
SonarWayWithFindbugsProfile.class,
SunConventionsProfile.class,
JavaCpdMapping.class
);
JavaCpdMapping.class,
PmdViolationToRuleViolation.class);
}
}

+ 19
- 14
plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdProfileExporter.java Voir le fichier

@@ -19,12 +19,7 @@
*/
package org.sonar.plugins.pmd;

import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.List;

import com.google.common.annotations.VisibleForTesting;
import org.jdom.CDATA;
import org.jdom.Document;
import org.jdom.Element;
@@ -40,8 +35,13 @@ import org.sonar.plugins.pmd.xml.PmdProperty;
import org.sonar.plugins.pmd.xml.PmdRule;
import org.sonar.plugins.pmd.xml.PmdRuleset;

public class PmdProfileExporter extends ProfileExporter {
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.List;

public class PmdProfileExporter extends ProfileExporter {
public PmdProfileExporter() {
super(PmdConstants.REPOSITORY_KEY, PmdConstants.PLUGIN_NAME);
setSupportedLanguages(Java.KEY);
@@ -51,21 +51,25 @@ public class PmdProfileExporter extends ProfileExporter {
@Override
public void exportProfile(RulesProfile profile, Writer writer) {
try {
PmdRuleset tree = createPmdRuleset(profile.getActiveRulesByRepository(PmdConstants.REPOSITORY_KEY), profile.getName());
String xmlModules = exportPmdRulesetToXml(tree);
String xmlModules = exportProfile(PmdConstants.REPOSITORY_KEY, profile);
writer.append(xmlModules);
} catch (IOException e) {
throw new SonarException("Fail to export the profile " + profile, e);
}
}

protected PmdRuleset createPmdRuleset(List<ActiveRule> activeRules, String profileName) {
public String exportProfile(String repositoryKey, RulesProfile profile) {
PmdRuleset tree = createPmdRuleset(repositoryKey, profile.getActiveRulesByRepository(repositoryKey), profile.getName());
return exportPmdRulesetToXml(tree);
}

private PmdRuleset createPmdRuleset(String repositoryKey, List<ActiveRule> activeRules, String profileName) {
PmdRuleset ruleset = new PmdRuleset(profileName);
for (ActiveRule activeRule : activeRules) {
if (activeRule.getRule().getRepositoryKey().equals(PmdConstants.REPOSITORY_KEY)) {
if (activeRule.getRule().getRepositoryKey().equals(repositoryKey)) {
String configKey = activeRule.getRule().getConfigKey();
PmdRule rule = new PmdRule(configKey, PmdLevelUtils.toLevel(activeRule.getSeverity()));
if (activeRule.getActiveRuleParams() != null && !activeRule.getActiveRuleParams().isEmpty()) {
if ((activeRule.getActiveRuleParams() != null) && !activeRule.getActiveRuleParams().isEmpty()) {
List<PmdProperty> properties = new ArrayList<PmdProperty>();
for (ActiveRuleParam activeRuleParam : activeRule.getActiveRuleParams()) {
properties.add(new PmdProperty(activeRuleParam.getRuleParam().getKey(), activeRuleParam.getValue()));
@@ -79,7 +83,8 @@ public class PmdProfileExporter extends ProfileExporter {
return ruleset;
}

protected void processXPathRule(String sonarRuleKey, PmdRule rule) {
@VisibleForTesting
void processXPathRule(String sonarRuleKey, PmdRule rule) {
if (PmdConstants.XPATH_CLASS.equals(rule.getRef())) {
rule.setRef(null);
PmdProperty xpathMessage = rule.getProperty(PmdConstants.XPATH_MESSAGE_PARAM);
@@ -98,7 +103,7 @@ public class PmdProfileExporter extends ProfileExporter {
}
}

protected String exportPmdRulesetToXml(PmdRuleset pmdRuleset) {
private String exportPmdRulesetToXml(PmdRuleset pmdRuleset) {
Element eltRuleset = new Element("ruleset");
for (PmdRule pmdRule : pmdRuleset.getPmdRules()) {
Element eltRule = new Element("rule");

+ 2
- 4
plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdRuleRepository.java Voir le fichier

@@ -30,10 +30,8 @@ import java.io.File;
import java.util.List;

public final class PmdRuleRepository extends RuleRepository {

// for user extensions
private ServerFileSystem fileSystem;
private XMLRuleParser xmlRuleParser;
private final ServerFileSystem fileSystem;
private final XMLRuleParser xmlRuleParser;

public PmdRuleRepository(ServerFileSystem fileSystem, XMLRuleParser xmlRuleParser) {
super(PmdConstants.REPOSITORY_KEY, Java.KEY);

+ 18
- 36
plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdSensor.java Voir le fichier

@@ -21,70 +21,52 @@ package org.sonar.plugins.pmd;

import net.sourceforge.pmd.IRuleViolation;
import net.sourceforge.pmd.Report;
import org.sonar.api.CoreProperties;
import org.sonar.api.batch.Sensor;
import org.sonar.api.batch.SensorContext;
import org.sonar.api.profiles.RulesProfile;
import org.sonar.api.resources.Java;
import org.sonar.api.resources.JavaFile;
import org.sonar.api.resources.Project;
import org.sonar.api.resources.Resource;
import org.sonar.api.rules.Rule;
import org.sonar.api.rules.RuleFinder;
import org.sonar.api.rules.Violation;
import org.sonar.api.utils.XmlParserException;

import java.util.Iterator;

public class PmdSensor implements Sensor {
private final RulesProfile profile;
private final PmdExecutor executor;
private final PmdViolationToRuleViolation pmdViolationToRuleViolation;

private RulesProfile profile;
private RuleFinder rulesFinder;
private PmdExecutor executor;

public PmdSensor(RulesProfile profile, RuleFinder rulesFinder, PmdExecutor executor) {
public PmdSensor(RulesProfile profile, PmdExecutor executor, PmdViolationToRuleViolation pmdViolationToRuleViolation) {
this.profile = profile;
this.rulesFinder = rulesFinder;
this.executor = executor;
this.pmdViolationToRuleViolation = pmdViolationToRuleViolation;
}

public boolean shouldExecuteOnProject(Project project) {
return (!project.getFileSystem().mainFiles(Java.KEY).isEmpty() && !profile.getActiveRulesByRepository(PmdConstants.REPOSITORY_KEY).isEmpty())
|| (!project.getFileSystem().testFiles(Java.KEY).isEmpty() && !profile.getActiveRulesByRepository(PmdConstants.TEST_REPOSITORY_KEY).isEmpty());
}

public void analyse(Project project, SensorContext context) {
try {
Report report = executor.execute();
analyseReport(report, project, context);

reportViolations(report.iterator(), context);
} catch (Exception e) {
// TOFIX
throw new XmlParserException(e);
}
}

private void analyseReport(Report report, Project project, SensorContext context) {
Iterator<IRuleViolation> pmdViolationIter = report.iterator();
while (pmdViolationIter.hasNext()) {
IRuleViolation pmdViolation = pmdViolationIter.next();
int lineId = pmdViolation.getBeginLine();
String ruleKey = pmdViolation.getRule().getName();
String message = pmdViolation.getDescription();
String filename = pmdViolation.getFilename();
Resource resource = JavaFile.fromAbsolutePath(filename, project.getFileSystem().getSourceDirs(), false);
// Save violations only for existing resources
if (context.getResource(resource) != null) {
Rule rule = rulesFinder.findByKey(CoreProperties.PMD_PLUGIN, ruleKey);
// Save violations only for enabled rules
if (rule != null) {
Violation violation = Violation.create(rule, resource).setLineId(lineId).setMessage(message);
context.saveViolation(violation);
}
private void reportViolations(Iterator<IRuleViolation> violations, SensorContext context) {
while (violations.hasNext()) {
IRuleViolation pmdViolation = violations.next();

Violation violation = pmdViolationToRuleViolation.toViolation(pmdViolation, context);
if (null != violation) {
context.saveViolation(violation);
}
}
}

public boolean shouldExecuteOnProject(Project project) {
return !project.getFileSystem().mainFiles(Java.KEY).isEmpty() &&
!profile.getActiveRulesByRepository(PmdConstants.REPOSITORY_KEY).isEmpty();
}

@Override
public String toString() {
return getClass().getSimpleName();

+ 98
- 0
plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdTemplate.java Voir le fichier

@@ -0,0 +1,98 @@
/*
* Sonar, open source software quality management tool.
* Copyright (C) 2008-2012 SonarSource
* 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.plugins.pmd;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Functions;
import com.google.common.collect.ImmutableMap;
import com.google.common.io.Closeables;
import net.sourceforge.pmd.PMD;
import net.sourceforge.pmd.PMDException;
import net.sourceforge.pmd.RuleContext;
import net.sourceforge.pmd.RuleSets;
import net.sourceforge.pmd.SourceType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.api.utils.SonarException;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.Map;

public class PmdTemplate {
private static final Logger LOG = LoggerFactory.getLogger(PmdTemplate.class);

private static final Map<String, String> JAVA_VERSIONS = ImmutableMap.of(
"1.1", "1.3",
"1.2", "1.3",
"5", "1.5",
"6", "1.6");

private final PMD pmd;

public PmdTemplate(String javaVersion) {
pmd = new PMD();
setJavaVersion(pmd, javaVersion);
}

public void process(File file, Charset encoding, RuleSets rulesets, RuleContext ruleContext) {
ruleContext.setSourceCodeFilename(file.getAbsolutePath());

InputStream inputStream = null;
try {
inputStream = new FileInputStream(file);

pmd.processFile(inputStream, encoding.displayName(), rulesets, ruleContext);
} catch (PMDException e) {
LOG.error("Fail to execute PMD. Following file is ignored: " + file, e.getCause());
} catch (Exception e) {
LOG.error("Fail to execute PMD. Following file is ignored: " + file, e);
} finally {
Closeables.closeQuietly(inputStream);
}
}

@VisibleForTesting
static void setJavaVersion(PMD pmd, String javaVersion) {
String version = normalize(javaVersion);
if (version == null) {
return; // Do nothing
}

SourceType sourceType = SourceType.getSourceTypeForId("java " + version);
if (sourceType == null) {
throw new SonarException("Unsupported Java version for PMD: " + version);
}

LOG.info("Java version: " + version);
pmd.setJavaVersion(sourceType);
}

private static String normalize(String version) {
return Functions.forMap(JAVA_VERSIONS, version).apply(version);
}

@Override
public String toString() {
return getClass().getSimpleName();
}
}

+ 44
- 0
plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdUnitTestsRuleRepository.java Voir le fichier

@@ -0,0 +1,44 @@
/*
* Sonar, open source software quality management tool.
* Copyright (C) 2008-2012 SonarSource
* 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.plugins.pmd;

import org.sonar.api.resources.Java;
import org.sonar.api.rules.Rule;
import org.sonar.api.rules.RuleRepository;
import org.sonar.api.rules.XMLRuleParser;

import java.io.InputStream;
import java.util.List;

public final class PmdUnitTestsRuleRepository extends RuleRepository {
private final XMLRuleParser xmlRuleParser;

public PmdUnitTestsRuleRepository(XMLRuleParser xmlRuleParser) {
super(PmdConstants.TEST_REPOSITORY_KEY, Java.KEY);
setName(PmdConstants.TEST_REPOSITORY_NAME);
this.xmlRuleParser = xmlRuleParser;
}

@Override
public List<Rule> createRules() {
InputStream input = getClass().getResourceAsStream("/org/sonar/plugins/pmd/rules-unit-tests.xml");
return xmlRuleParser.parse(input);
}
}

+ 12
- 8
plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdVersion.java Voir le fichier

@@ -19,7 +19,7 @@
*/
package org.sonar.plugins.pmd;

import org.apache.commons.io.IOUtils;
import com.google.common.io.Closeables;
import org.slf4j.LoggerFactory;

import java.io.IOException;
@@ -37,18 +37,22 @@ public enum PmdVersion {
}

private PmdVersion() {
InputStream input = getClass().getResourceAsStream(PROPERTIES_PATH);
version = readVersion();
}

public String readVersion() {
Properties properties = new Properties();

InputStream input = null;
try {
Properties properties = new Properties();
input = getClass().getResourceAsStream(PROPERTIES_PATH);
properties.load(input);
this.version = properties.getProperty("pmd.version");

} catch (IOException e) {
LoggerFactory.getLogger(getClass()).warn("Can not load the PMD version from the file " + PROPERTIES_PATH);
this.version = "";

} finally {
IOUtils.closeQuietly(input);
Closeables.closeQuietly(input);
}

return properties.getProperty("pmd.version", "");
}
}

+ 82
- 0
plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdViolationToRuleViolation.java Voir le fichier

@@ -0,0 +1,82 @@
/*
* Sonar, open source software quality management tool.
* Copyright (C) 2008-2012 SonarSource
* 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.plugins.pmd;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import net.sourceforge.pmd.IRuleViolation;
import org.sonar.api.BatchExtension;
import org.sonar.api.batch.SensorContext;
import org.sonar.api.resources.JavaFile;
import org.sonar.api.resources.ProjectFileSystem;
import org.sonar.api.resources.Resource;
import org.sonar.api.rules.Rule;
import org.sonar.api.rules.RuleFinder;
import org.sonar.api.rules.Violation;

import java.io.File;
import java.util.List;

public class PmdViolationToRuleViolation implements BatchExtension {
private final ProjectFileSystem projectFileSystem;
private final RuleFinder ruleFinder;

public PmdViolationToRuleViolation(ProjectFileSystem projectFileSystem, RuleFinder ruleFinder) {
this.projectFileSystem = projectFileSystem;
this.ruleFinder = ruleFinder;
}

public Violation toViolation(IRuleViolation pmdViolation, SensorContext context) {
Resource resource = findResourceFor(pmdViolation);
if (context.getResource(resource) == null) {
return null; // Save violations only for existing resources
}

Rule rule = findRuleFor(pmdViolation);
if (rule == null) {
return null; // Save violations only for enabled rules
}

int lineId = pmdViolation.getBeginLine();
String message = pmdViolation.getDescription();

return Violation.create(rule, resource).setLineId(lineId).setMessage(message);
}

private Resource findResourceFor(IRuleViolation violation) {
List<File> allSources = ImmutableList.copyOf(Iterables.concat(projectFileSystem.getSourceDirs(), projectFileSystem.getTestDirs()));

return JavaFile.fromAbsolutePath(violation.getFilename(), allSources, true);
}

private Rule findRuleFor(IRuleViolation violation) {
String ruleKey = violation.getRule().getName();
Rule rule = ruleFinder.findByKey(PmdConstants.REPOSITORY_KEY, ruleKey);
if (rule != null) {
return rule;
}
return ruleFinder.findByKey(PmdConstants.TEST_REPOSITORY_KEY, ruleKey);
}

@Override
public String toString() {
return getClass().getSimpleName();
}
}

+ 17
- 10
plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/SonarWayProfile.java Voir le fichier

@@ -19,16 +19,16 @@
*/
package org.sonar.plugins.pmd;

import java.io.InputStreamReader;
import java.io.Reader;

import com.google.common.io.Closeables;
import org.sonar.api.profiles.ProfileDefinition;
import org.sonar.api.profiles.RulesProfile;
import org.sonar.api.resources.Java;
import org.sonar.api.utils.ValidationMessages;

public final class SonarWayProfile extends ProfileDefinition {
import java.io.InputStreamReader;
import java.io.Reader;

public final class SonarWayProfile extends ProfileDefinition {
private final PmdProfileImporter importer;

public SonarWayProfile(PmdProfileImporter importer) {
@@ -36,11 +36,18 @@ public final class SonarWayProfile extends ProfileDefinition {
}

@Override
public RulesProfile createProfile(ValidationMessages messages) {
Reader pmdSonarWayProfile = new InputStreamReader(this.getClass().getResourceAsStream("/org/sonar/plugins/pmd/profile-sonar-way.xml"));
RulesProfile profile = importer.importProfile(pmdSonarWayProfile, messages);
profile.setLanguage(Java.KEY);
profile.setName(RulesProfile.SONAR_WAY_NAME);
return profile;
public RulesProfile createProfile(ValidationMessages validation) {
Reader config = null;
try {
config = new InputStreamReader(this.getClass().getResourceAsStream("/org/sonar/plugins/pmd/profile-sonar-way.xml"));

RulesProfile profile = importer.importProfile(config, validation);
profile.setLanguage(Java.KEY);
profile.setName(RulesProfile.SONAR_WAY_NAME);

return profile;
} finally {
Closeables.closeQuietly(config);
}
}
}

+ 5
- 6
plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/SonarWayWithFindbugsProfile.java Voir le fichier

@@ -25,20 +25,19 @@ import org.sonar.api.resources.Java;
import org.sonar.api.utils.ValidationMessages;

public class SonarWayWithFindbugsProfile extends ProfileDefinition {

private SonarWayProfile sonarWay;
private final SonarWayProfile sonarWay;

public SonarWayWithFindbugsProfile(SonarWayProfile sonarWay) {
this.sonarWay = sonarWay;
}


@Override
public RulesProfile createProfile(ValidationMessages validationMessages) {
RulesProfile profile = sonarWay.createProfile(validationMessages);
public RulesProfile createProfile(ValidationMessages validation) {
RulesProfile profile = sonarWay.createProfile(validation);

profile.setName(RulesProfile.SONAR_WAY_FINDBUGS_NAME);
profile.setLanguage(Java.KEY);

return profile;
}
}


+ 17
- 11
plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/SunConventionsProfile.java Voir le fichier

@@ -19,16 +19,16 @@
*/
package org.sonar.plugins.pmd;

import java.io.InputStreamReader;
import java.io.Reader;

import com.google.common.io.Closeables;
import org.sonar.api.profiles.ProfileDefinition;
import org.sonar.api.profiles.RulesProfile;
import org.sonar.api.resources.Java;
import org.sonar.api.utils.ValidationMessages;

public final class SunConventionsProfile extends ProfileDefinition {
import java.io.InputStreamReader;
import java.io.Reader;

public final class SunConventionsProfile extends ProfileDefinition {
private final PmdProfileImporter importer;

public SunConventionsProfile(PmdProfileImporter importer) {
@@ -36,12 +36,18 @@ public final class SunConventionsProfile extends ProfileDefinition {
}

@Override
public RulesProfile createProfile(ValidationMessages messages) {
Reader pmdSonarWayProfile = new InputStreamReader(this.getClass().getResourceAsStream(
"/org/sonar/plugins/pmd/profile-sun-conventions.xml"));
RulesProfile profile = importer.importProfile(pmdSonarWayProfile, messages);
profile.setName(RulesProfile.SUN_CONVENTIONS_NAME);
profile.setLanguage(Java.KEY);
return profile;
public RulesProfile createProfile(ValidationMessages validation) {
Reader config = null;
try {
config = new InputStreamReader(this.getClass().getResourceAsStream("/org/sonar/plugins/pmd/profile-sun-conventions.xml"));

RulesProfile profile = importer.importProfile(config, validation);
profile.setLanguage(Java.KEY);
profile.setName(RulesProfile.SUN_CONVENTIONS_NAME);

return profile;
} finally {
Closeables.closeQuietly(config);
}
}
}

+ 42
- 0
plugins/sonar-pmd-plugin/src/main/resources/org/sonar/plugins/pmd/rules-unit-tests.xml Voir le fichier

@@ -0,0 +1,42 @@
<rules>
<rule key="JUnitStaticSuite">
<priority>MAJOR</priority>
<configKey><![CDATA[rulesets/junit.xml/JUnitStaticSuite]]></configKey>
</rule>
<rule key="JUnitSpelling">
<priority>MAJOR</priority>
<configKey><![CDATA[rulesets/junit.xml/JUnitSpelling]]></configKey>
</rule>
<rule key="JUnitAssertionsShouldIncludeMessage">
<priority>MINOR</priority>
<configKey><![CDATA[rulesets/junit.xml/JUnitAssertionsShouldIncludeMessage]]></configKey>
</rule>
<rule key="JUnitTestsShouldIncludeAssert">
<priority>MAJOR</priority>
<configKey><![CDATA[rulesets/junit.xml/JUnitTestsShouldIncludeAssert]]></configKey>
</rule>
<rule key="TestClassWithoutTestCases">
<priority>MAJOR</priority>
<configKey><![CDATA[rulesets/junit.xml/TestClassWithoutTestCases]]></configKey>
</rule>
<rule key="UnnecessaryBooleanAssertion">
<priority>MINOR</priority>
<configKey><![CDATA[rulesets/junit.xml/UnnecessaryBooleanAssertion]]></configKey>
</rule>
<rule key="UseAssertEqualsInsteadOfAssertTrue">
<priority>MINOR</priority>
<configKey><![CDATA[rulesets/junit.xml/UseAssertEqualsInsteadOfAssertTrue]]></configKey>
</rule>
<rule key="UseAssertSameInsteadOfAssertTrue">
<priority>MINOR</priority>
<configKey><![CDATA[rulesets/junit.xml/UseAssertSameInsteadOfAssertTrue]]></configKey>
</rule>
<rule key="UseAssertNullInsteadOfAssertTrue">
<priority>MINOR</priority>
<configKey><![CDATA[rulesets/junit.xml/UseAssertNullInsteadOfAssertTrue]]></configKey>
</rule>
<rule key="SimplifyBooleanAssertion">
<priority>MINOR</priority>
<configKey><![CDATA[rulesets/junit.xml/SimplifyBooleanAssertion]]></configKey>
</rule>
</rules>

+ 63
- 24
plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdConfigurationTest.java Voir le fichier

@@ -19,51 +19,90 @@
*/
package org.sonar.plugins.pmd;

import org.apache.commons.io.FileUtils;
import net.sourceforge.pmd.Report;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.sonar.api.config.Settings;
import org.sonar.api.profiles.RulesProfile;
import org.sonar.api.resources.Project;
import org.sonar.api.resources.ProjectFileSystem;
import org.sonar.api.test.MavenTestUtils;
import org.sonar.api.utils.SonarException;

import java.io.File;
import java.io.IOException;
import java.util.List;

import static org.hamcrest.Matchers.*;
import static org.junit.Assert.assertThat;
import static org.fest.assertions.Assertions.assertThat;
import static org.mockito.Matchers.eq;
import static org.mockito.Matchers.matches;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;

public class PmdConfigurationTest {
PmdConfiguration configuration;

Settings settings = new Settings();
ProjectFileSystem fs = mock(ProjectFileSystem.class);

@Rule
public ExpectedException expectedException = ExpectedException.none();

@Before
public void setUpPmdConfiguration() {
configuration = new PmdConfiguration(fs, settings);
}

@Test
public void should_return_default_target_xml_report_when_property_is_not_set() {
File targetXMLReport = configuration.getTargetXMLReport();

assertThat(targetXMLReport).isNull();
}

@Test
public void should_set_target_xml_report() {
when(fs.resolvePath("pmd-result.xml")).thenReturn(new File("/workingDir/pmd-result.xml"));

settings.setProperty(PmdConfiguration.PROPERTY_GENERATE_XML, true);
File targetXMLReport = configuration.getTargetXMLReport();

assertThat(targetXMLReport).isEqualTo(new File("/workingDir/pmd-result.xml"));
}

@Test
public void writeConfigurationToWorkingDir() throws IOException {
Project project = MavenTestUtils.loadProjectFromPom(getClass(), "writeConfigurationToWorkingDir/pom.xml");
public void should_dump_xml_rule_set() throws IOException {
when(fs.writeToWorkingDirectory("<rules>", "pmd.xml")).thenReturn(new File("/workingDir/pmd.xml"));

PmdConfiguration configuration = new PmdConfiguration(new PmdProfileExporter(), RulesProfile.create(), project, null);
List<String> rulesets = configuration.getRulesets();
File rulesFile = configuration.dumpXmlRuleSet("pmd", "<rules>");

assertThat(rulesets.size(), is(1));
File xmlFile = new File(rulesets.get(0));
assertThat(xmlFile.exists(), is(true));
assertThat(FileUtils.readFileToString(xmlFile), is("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<ruleset />\r\n\r\n"));
assertThat(rulesFile).isEqualTo(new File("/workingDir/pmd.xml"));
}

@Test
public void shouldReturnTargetXMLReport() {
Project project = new Project("key");
ProjectFileSystem fs = mock(ProjectFileSystem.class);
when(fs.getSonarWorkingDirectory()).thenReturn(new File("/tmp"));
project.setFileSystem(fs);
Settings settings = new Settings();
PmdConfiguration configuration = new PmdConfiguration(null, null, project, settings);
public void should_fail_to_dump_xml_rule_set() throws IOException {
when(fs.writeToWorkingDirectory("<xml>", "pmd.xml")).thenThrow(new IOException("BUG"));

assertThat(configuration.getTargetXMLReport(), nullValue());
expectedException.expect(SonarException.class);
expectedException.expectMessage("Fail to save the PMD configuration");

configuration.dumpXmlRuleSet("pmd", "<xml>");
}

@Test
public void should_dump_xml_report() throws IOException {
when(fs.writeToWorkingDirectory(matches(".*[\r\n]*<pmd.*[\r\n].*</pmd>"), eq("pmd-result.xml"))).thenReturn(new File("/workingDir/pmd-result.xml"));

settings.setProperty(PmdConfiguration.PROPERTY_GENERATE_XML, true);
assertThat(configuration.getTargetXMLReport(), equalTo(new File("/tmp/pmd-result.xml")));
File reportFile = configuration.dumpXmlReport(new Report());

assertThat(reportFile).isEqualTo(new File("/workingDir/pmd-result.xml"));
}

@Test
public void should_ignore_xml_report_when_property_is_not_set() {
File reportFile = configuration.dumpXmlReport(new Report());

assertThat(reportFile).isNull();
verifyZeroInteractions(fs);
}
}

+ 82
- 63
plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdExecutorTest.java Voir le fichier

@@ -20,90 +20,109 @@
package org.sonar.plugins.pmd;

import com.google.common.base.Charsets;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.junit.Rule;
import net.sourceforge.pmd.Report;
import net.sourceforge.pmd.RuleContext;
import net.sourceforge.pmd.RuleSets;
import org.junit.Before;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.mockito.Mockito;
import org.sonar.api.profiles.RulesProfile;
import org.sonar.api.resources.InputFile;
import org.sonar.api.resources.Java;
import org.sonar.api.resources.Project;
import org.sonar.api.resources.ProjectFileSystem;
import org.sonar.test.TestUtils;

import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;

import static org.hamcrest.Matchers.nullValue;
import static org.hamcrest.core.Is.is;
import static org.hamcrest.number.OrderingComparisons.greaterThan;
import static org.junit.Assert.assertThat;
import static org.fest.assertions.Assertions.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;

public class PmdExecutorTest {
PmdExecutor pmdExecutor;

@Rule
public TemporaryFolder temp = new TemporaryFolder();
Project project = mock(Project.class);
ProjectFileSystem projectFileSystem = mock(ProjectFileSystem.class);
RulesProfile rulesProfile = mock(RulesProfile.class);
PmdProfileExporter pmdProfileExporter = mock(PmdProfileExporter.class);
PmdConfiguration pmdConfiguration = mock(PmdConfiguration.class);
PmdTemplate pmdTemplate = mock(PmdTemplate.class);

@Before
public void setUpPmdExecutor() {
pmdExecutor = Mockito.spy(new PmdExecutor(project, projectFileSystem, rulesProfile, pmdProfileExporter, pmdConfiguration));

doReturn(pmdTemplate).when(pmdExecutor).createPmdTemplate();
}

@Test
public void executeOnManySourceDirs() throws IOException {
File workDir = temp.getRoot();
Project project = new Project("two-source-dirs");

ProjectFileSystem fs = mock(ProjectFileSystem.class);
File root = new File(getClass().getResource("/org/sonar/plugins/pmd/PmdExecutorTest/executeOnManySourceDirs/").toURI());
when(fs.getSourceFiles(Java.INSTANCE)).thenReturn(Arrays.asList(new File(root, "src1/FirstClass.java"), new File(root, "src2/SecondClass.java")));
when(fs.getSourceCharset()).thenReturn(Charsets.UTF_8);
when(fs.getSonarWorkingDirectory()).thenReturn(workDir);
project.setFileSystem(fs);

PmdConfiguration conf = mock(PmdConfiguration.class);
File file = FileUtils.toFile(getClass().getResource("/org/sonar/plugins/pmd/PmdExecutorTest/executeOnManySourceDirs/pmd.xml").toURI().toURL());
when(conf.getRulesets()).thenReturn(Arrays.asList(file.getAbsolutePath()));
File xmlReport = new File(workDir, "pmd-result.xml");
when(conf.getTargetXMLReport()).thenReturn(xmlReport);

PmdExecutor executor = new PmdExecutor(project, conf);
executor.execute();
assertThat(xmlReport.exists(), is(true));

String xml = FileUtils.readFileToString(xmlReport);

// errors on the two source files
assertThat(StringUtils.countMatches(xml, "<file"), is(2));
assertThat(StringUtils.countMatches(xml, "<violation"), greaterThan(2));
public void should_execute_pmd_on_source_files_and_test_files() {
InputFile srcFile = file("src/Class.java");
InputFile tstFile = file("test/ClassTest.java");
when(pmdProfileExporter.exportProfile(PmdConstants.REPOSITORY_KEY, rulesProfile)).thenReturn(TestUtils.getResourceContent("/org/sonar/plugins/pmd/simple.xml"));
when(pmdProfileExporter.exportProfile(PmdConstants.TEST_REPOSITORY_KEY, rulesProfile)).thenReturn(TestUtils.getResourceContent("/org/sonar/plugins/pmd/junit.xml"));
when(projectFileSystem.getSourceCharset()).thenReturn(Charsets.UTF_8);
when(projectFileSystem.mainFiles(Java.KEY)).thenReturn(Arrays.asList(srcFile));
when(projectFileSystem.testFiles(Java.KEY)).thenReturn(Arrays.asList(tstFile));

Report report = pmdExecutor.execute();

verify(pmdTemplate).process(eq(new File("src/Class.java")), eq(Charsets.UTF_8), any(RuleSets.class), any(RuleContext.class));
verify(pmdTemplate).process(eq(new File("test/ClassTest.java")), eq(Charsets.UTF_8), any(RuleSets.class), any(RuleContext.class));
assertThat(report).isNotNull();
}

@Test
public void ignorePmdFailures() throws IOException {
final File workDir = temp.getRoot();
Project project = new Project("ignorePmdFailures");

ProjectFileSystem fs = mock(ProjectFileSystem.class);
when(fs.getSourceFiles(Java.INSTANCE)).thenReturn(Arrays.asList(new File("test-resources/ignorePmdFailures/DoesNotCompile.java")));
when(fs.getSourceCharset()).thenReturn(Charsets.UTF_8);
when(fs.getSonarWorkingDirectory()).thenReturn(workDir);
project.setFileSystem(fs);

PmdConfiguration conf = mock(PmdConfiguration.class);
when(conf.getRulesets()).thenReturn(Arrays.asList(new File("test-resources/ignorePmdFailures/pmd.xml").getAbsolutePath()));
File xmlReport = new File(workDir, "pmd-result.xml");
when(conf.getTargetXMLReport()).thenReturn(xmlReport);
PmdExecutor executor = new PmdExecutor(project, conf);

executor.execute();
assertThat(xmlReport.exists(), is(true));
public void should_dump_configuration_as_xml() {
when(pmdProfileExporter.exportProfile(PmdConstants.REPOSITORY_KEY, rulesProfile)).thenReturn(TestUtils.getResourceContent("/org/sonar/plugins/pmd/simple.xml"));
when(pmdProfileExporter.exportProfile(PmdConstants.TEST_REPOSITORY_KEY, rulesProfile)).thenReturn(TestUtils.getResourceContent("/org/sonar/plugins/pmd/junit.xml"));

Report report = pmdExecutor.execute();

verify(pmdConfiguration).dumpXmlReport(report);
}

@Test
public void shouldNormalizeJavaVersion() {
assertThat(PmdExecutor.getNormalizedJavaVersion(null), nullValue());
assertThat(PmdExecutor.getNormalizedJavaVersion(""), is(""));
assertThat(PmdExecutor.getNormalizedJavaVersion("1.1"), is("1.3"));
assertThat(PmdExecutor.getNormalizedJavaVersion("1.2"), is("1.3"));
assertThat(PmdExecutor.getNormalizedJavaVersion("1.4"), is("1.4"));
assertThat(PmdExecutor.getNormalizedJavaVersion("5"), is("1.5"));
assertThat(PmdExecutor.getNormalizedJavaVersion("6"), is("1.6"));
public void should_dump_ruleset_as_xml() {
InputFile srcFile = file("src/Class.java");
InputFile tstFile = file("test/ClassTest.java");
when(pmdProfileExporter.exportProfile(PmdConstants.REPOSITORY_KEY, rulesProfile)).thenReturn(TestUtils.getResourceContent("/org/sonar/plugins/pmd/simple.xml"));
when(pmdProfileExporter.exportProfile(PmdConstants.TEST_REPOSITORY_KEY, rulesProfile)).thenReturn(TestUtils.getResourceContent("/org/sonar/plugins/pmd/junit.xml"));
when(projectFileSystem.mainFiles(Java.KEY)).thenReturn(Arrays.asList(srcFile));
when(projectFileSystem.testFiles(Java.KEY)).thenReturn(Arrays.asList(tstFile));

pmdExecutor.execute();

verify(pmdConfiguration).dumpXmlRuleSet(PmdConstants.REPOSITORY_KEY, TestUtils.getResourceContent("/org/sonar/plugins/pmd/simple.xml"));
verify(pmdConfiguration).dumpXmlRuleSet(PmdConstants.TEST_REPOSITORY_KEY, TestUtils.getResourceContent("/org/sonar/plugins/pmd/junit.xml"));
}

@Test
public void should_ignore_empty_test_dir() {
InputFile srcFile = file("src/Class.java");
doReturn(pmdTemplate).when(pmdExecutor).createPmdTemplate();
when(pmdProfileExporter.exportProfile(PmdConstants.REPOSITORY_KEY, rulesProfile)).thenReturn(TestUtils.getResourceContent("/org/sonar/plugins/pmd/simple.xml"));
when(projectFileSystem.getSourceCharset()).thenReturn(Charsets.UTF_8);
when(projectFileSystem.mainFiles(Java.KEY)).thenReturn(Arrays.asList(srcFile));
when(projectFileSystem.testFiles(Java.KEY)).thenReturn(Collections.<InputFile> emptyList());

pmdExecutor.execute();

verify(pmdTemplate).process(eq(new File("src/Class.java")), eq(Charsets.UTF_8), any(RuleSets.class), any(RuleContext.class));
verifyNoMoreInteractions(pmdTemplate);
}

static InputFile file(String path) {
InputFile inputFile = mock(InputFile.class);
when(inputFile.getFile()).thenReturn(new File(path));
return inputFile;
}
}

+ 47
- 0
plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdLevelUtilsTest.java Voir le fichier

@@ -0,0 +1,47 @@
/*
* Sonar, open source software quality management tool.
* Copyright (C) 2008-2012 SonarSource
* 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.plugins.pmd;

import org.junit.Test;
import org.sonar.api.rules.RulePriority;

import static org.fest.assertions.Assertions.assertThat;

public class PmdLevelUtilsTest {
@Test
public void should_get_priority_from_level() {
assertThat(PmdLevelUtils.fromLevel("1")).isSameAs(RulePriority.BLOCKER);
assertThat(PmdLevelUtils.fromLevel("2")).isSameAs(RulePriority.CRITICAL);
assertThat(PmdLevelUtils.fromLevel("3")).isSameAs(RulePriority.MAJOR);
assertThat(PmdLevelUtils.fromLevel("4")).isSameAs(RulePriority.MINOR);
assertThat(PmdLevelUtils.fromLevel("5")).isSameAs(RulePriority.INFO);
assertThat(PmdLevelUtils.fromLevel("?")).isNull();
assertThat(PmdLevelUtils.fromLevel(null)).isNull();
}

@Test
public void should_get_level_from_priority() {
assertThat(PmdLevelUtils.toLevel(RulePriority.BLOCKER)).isEqualTo("1");
assertThat(PmdLevelUtils.toLevel(RulePriority.CRITICAL)).isEqualTo("2");
assertThat(PmdLevelUtils.toLevel(RulePriority.MAJOR)).isEqualTo("3");
assertThat(PmdLevelUtils.toLevel(RulePriority.MINOR)).isEqualTo("4");
assertThat(PmdLevelUtils.toLevel(RulePriority.INFO)).isEqualTo("5");
}
}

+ 10
- 7
plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdPluginTest.java Voir le fichier

@@ -19,17 +19,20 @@
*/
package org.sonar.plugins.pmd;

import static org.hamcrest.number.OrderingComparisons.greaterThan;
import static org.junit.Assert.assertThat;

import org.junit.Test;
import org.sonar.api.Extension;

import java.util.List;

import static org.fest.assertions.Assertions.assertThat;

public class PmdPluginTest {
PmdPlugin plugin = new PmdPlugin();

@Test
public void testGetExtensions() {
PmdPlugin plugin = new PmdPlugin();
assertThat(plugin.getExtensions().size(), greaterThan(1));
}
public void should_contain_both_rule_repositories() {
List<Class<? extends Extension>> extensions = plugin.getExtensions();

assertThat(extensions).contains(PmdRuleRepository.class, PmdUnitTestsRuleRepository.class);
}
}

+ 62
- 100
plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdProfileExporterTest.java Voir le fichier

@@ -19,12 +19,9 @@
*/
package org.sonar.plugins.pmd;

import org.apache.commons.io.IOUtils;
import org.apache.commons.io.input.CharSequenceReader;
import org.apache.commons.lang.StringUtils;
import org.hamcrest.Description;
import org.hamcrest.TypeSafeMatcher;
import org.junit.Test;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.sonar.api.platform.ServerFileSystem;
import org.sonar.api.profiles.RulesProfile;
import org.sonar.api.rules.ActiveRule;
@@ -38,144 +35,109 @@ import org.sonar.plugins.pmd.xml.PmdProperty;
import org.sonar.plugins.pmd.xml.PmdRule;
import org.sonar.test.TestUtils;

import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.Collection;
import java.util.List;

import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.nullValue;
import static org.junit.Assert.assertThat;
import static org.fest.assertions.Assertions.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.sonar.test.MoreConditions.equalsIgnoreEOL;

public class PmdProfileExporterTest {

private final PmdProfileExporter exporter = new PmdProfileExporter();
PmdProfileExporter exporter = new PmdProfileExporter();

@Test
public void testExportProfile() {
ServerFileSystem fileSystem = mock(ServerFileSystem.class);
PmdRuleRepository repository = new PmdRuleRepository(fileSystem, new XMLRuleParser());
List<Rule> rules = repository.createRules();
public void should_export_pmd_profile() {
String importedXml = TestUtils.getResourceContent("/org/sonar/plugins/pmd/export_simple.xml");

RuleFinder ruleFinder = new FakeRuleFinder(rules);
PmdProfileImporter importer = new PmdProfileImporter(ruleFinder);
Reader reader = new StringReader(TestUtils.getResourceContent("/org/sonar/plugins/pmd/simple.xml"));
RulesProfile rulesProfile = importer.importProfile(reader, ValidationMessages.create());
String exportedXml = exporter.exportProfile(PmdConstants.REPOSITORY_KEY, importProfile(importedXml));

StringWriter xmlOutput = new StringWriter();
exporter.exportProfile(rulesProfile, xmlOutput);
assertThat(exportedXml).satisfies(equalsIgnoreEOL(importedXml));
}

assertThat(xmlOutput.toString(), new IsEqualIgnoringEOL(TestUtils.getResourceContent("/org/sonar/plugins/pmd/export_simple.xml")));
@Test
public void should_export_empty_configuration_as_xml() {
String exportedXml = exporter.exportProfile(PmdConstants.REPOSITORY_KEY, RulesProfile.create());

assertThat(exportedXml).satisfies(equalsIgnoreEOL("<?xml version=\"1.0\" encoding=\"UTF-8\"?><ruleset />"));
}

@Test
public void testExportXPathRule() {
StringWriter xmlOutput = new StringWriter();
public void should_export_xPath_rule() {
Rule rule = Rule.create(PmdConstants.REPOSITORY_KEY, "MyOwnRule", "This is my own xpath rule.")
.setConfigKey(PmdConstants.XPATH_CLASS)
.setRepositoryKey(PmdConstants.REPOSITORY_KEY);
rule.createParameter(PmdConstants.XPATH_EXPRESSION_PARAM);
rule.createParameter(PmdConstants.XPATH_MESSAGE_PARAM);

RulesProfile profile = RulesProfile.create();
Rule xpathTemplate = Rule.create(PmdConstants.REPOSITORY_KEY, "MyOwnRule", "This is my own xpath rule.")
.setConfigKey(PmdConstants.XPATH_CLASS).setRepositoryKey(PmdConstants.REPOSITORY_KEY);
xpathTemplate.createParameter(PmdConstants.XPATH_EXPRESSION_PARAM);
xpathTemplate.createParameter(PmdConstants.XPATH_MESSAGE_PARAM);
ActiveRule xpath = profile.activateRule(xpathTemplate, null);
ActiveRule xpath = profile.activateRule(rule, null);
xpath.setParameter(PmdConstants.XPATH_EXPRESSION_PARAM, "//FieldDeclaration");
xpath.setParameter(PmdConstants.XPATH_MESSAGE_PARAM, "This is bad");
exporter.exportProfile(profile, xmlOutput);
assertThat(xmlOutput.toString(), new IsEqualIgnoringEOL(TestUtils.getResourceContent("/org/sonar/plugins/pmd/export_xpath_rules.xml")));
}

private static class IsEqualIgnoringEOL extends TypeSafeMatcher<CharSequence> {
private final String expected;
String exportedXml = exporter.exportProfile(PmdConstants.REPOSITORY_KEY, profile);

public IsEqualIgnoringEOL(CharSequence expected) {
this.expected = normalize(expected);
}

public void describeTo(Description description) {
description.appendText("string equal ").appendText(expected);
}

@Override
public boolean matchesSafely(CharSequence item) {
return StringUtils.equals(expected, normalize(item));
}

private static String normalize(CharSequence charSequence) {
return StringUtils.join(IOUtils.lineIterator(new CharSequenceReader(charSequence)), IOUtils.LINE_SEPARATOR_UNIX);
}
assertThat(exportedXml).satisfies(equalsIgnoreEOL(TestUtils.getResourceContent("/org/sonar/plugins/pmd/export_xpath_rules.xml")));
}

@Test(expected = SonarException.class)
public void shouldFailIfMessageNotProvidedForXPathRule() {
String xpathExpression = "xpathExpression";

public void should_fail_if_message_not_provided_for_xPath_rule() {
PmdRule rule = new PmdRule(PmdConstants.XPATH_CLASS);
rule.addProperty(new PmdProperty(PmdConstants.XPATH_EXPRESSION_PARAM, xpathExpression));

rule.addProperty(new PmdProperty(PmdConstants.XPATH_EXPRESSION_PARAM, "xpathExpression"));
rule.setName("MyOwnRule");

exporter.processXPathRule("xpathKey", rule);
}

@Test(expected = SonarException.class)
public void shouldFailIfXPathNotProvidedForXPathRule() {
String message = "This is bad";

@Test
public void should_process_xPath_rule() {
PmdRule rule = new PmdRule(PmdConstants.XPATH_CLASS);
rule.addProperty(new PmdProperty(PmdConstants.XPATH_MESSAGE_PARAM, message));
rule.setName("MyOwnRule");
rule.addProperty(new PmdProperty(PmdConstants.XPATH_EXPRESSION_PARAM, "xpathExpression"));
rule.addProperty(new PmdProperty(PmdConstants.XPATH_MESSAGE_PARAM, "message"));

exporter.processXPathRule("xpathKey", rule);
}

@Test
public void testProcessingXPathRule() {
String message = "This is bad";
String xpathExpression = "xpathExpression";
assertThat(rule.getMessage()).isEqualTo("message");
assertThat(rule.getRef()).isNull();
assertThat(rule.getClazz()).isEqualTo(PmdConstants.XPATH_CLASS);
assertThat(rule.getProperty(PmdConstants.XPATH_MESSAGE_PARAM)).isNull();
assertThat(rule.getName()).isEqualTo("xpathKey");
assertThat(rule.getProperty(PmdConstants.XPATH_EXPRESSION_PARAM).getValue()).isEqualTo("xpathExpression");
}

@Test(expected = SonarException.class)
public void should_fail_if_xPath_not_provided() {
PmdRule rule = new PmdRule(PmdConstants.XPATH_CLASS);
rule.addProperty(new PmdProperty(PmdConstants.XPATH_EXPRESSION_PARAM, xpathExpression));
rule.addProperty(new PmdProperty(PmdConstants.XPATH_MESSAGE_PARAM, message));
rule.setName("MyOwnRule");
rule.addProperty(new PmdProperty(PmdConstants.XPATH_MESSAGE_PARAM, "This is bad"));

exporter.processXPathRule("xpathKey", rule);

assertThat(rule.getMessage(), is(message));
assertThat(rule.getRef(), is(nullValue()));
assertThat(rule.getClazz(), is(PmdConstants.XPATH_CLASS));
assertThat(rule.getProperty(PmdConstants.XPATH_MESSAGE_PARAM), is(nullValue()));
assertThat(rule.getName(), is("xpathKey"));
assertThat(rule.getProperty(PmdConstants.XPATH_EXPRESSION_PARAM).getValue(), is(xpathExpression));
}

private static class FakeRuleFinder implements RuleFinder {

private final List<Rule> rules;

public FakeRuleFinder(List<Rule> rules) {
this.rules = rules;
}

public Rule findById(int ruleId) {
throw new UnsupportedOperationException();
}

public Rule findByKey(String repositoryKey, String key) {
throw new UnsupportedOperationException();
}
static RulesProfile importProfile(String configuration) {
PmdRuleRepository pmdRuleRepository = new PmdRuleRepository(mock(ServerFileSystem.class), new XMLRuleParser());
RuleFinder ruleFinder = createRuleFinder(pmdRuleRepository.createRules());
PmdProfileImporter importer = new PmdProfileImporter(ruleFinder);

public Collection<Rule> findAll(RuleQuery query) {
throw new UnsupportedOperationException();
}
return importer.importProfile(new StringReader(configuration), ValidationMessages.create());
}

public Rule find(RuleQuery query) {
for (Rule rule : rules) {
if (query.getConfigKey().equals(rule.getConfigKey())) {
rule.setRepositoryKey(PmdConstants.REPOSITORY_KEY);
return rule;
static RuleFinder createRuleFinder(final List<Rule> rules) {
RuleFinder ruleFinder = mock(RuleFinder.class);
when(ruleFinder.find(any(RuleQuery.class))).then(new Answer<Rule>() {
public Rule answer(InvocationOnMock invocation) {
RuleQuery query = (RuleQuery) invocation.getArguments()[0];
for (Rule rule : rules) {
if (query.getConfigKey().equals(rule.getConfigKey())) {
return rule.setRepositoryKey(PmdConstants.REPOSITORY_KEY);
}
}
return null;
}
return null;
}
});
return ruleFinder;
}
}

+ 70
- 58
plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdProfileImporterTest.java Voir le fichier

@@ -24,7 +24,11 @@ import org.junit.Test;
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.rules.ActiveRule;
import org.sonar.api.rules.Rule;
import org.sonar.api.rules.RuleFinder;
import org.sonar.api.rules.RulePriority;
import org.sonar.api.rules.RuleQuery;
import org.sonar.api.utils.ValidationMessages;
import org.sonar.plugins.pmd.xml.PmdRuleset;
import org.sonar.test.TestUtils;
@@ -32,127 +36,135 @@ import org.sonar.test.TestUtils;
import java.io.Reader;
import java.io.StringReader;

import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.nullValue;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.fest.assertions.Assertions.assertThat;
import static org.mockito.Matchers.anyObject;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

public class PmdProfileImporterTest {

private PmdProfileImporter importer;
private ValidationMessages messages;
PmdProfileImporter importer;
ValidationMessages messages;

@Before
public void before() {
public void setUpImporter() {
messages = ValidationMessages.create();
RuleFinder finder = createRuleFinder();
importer = new PmdProfileImporter(finder);
importer = new PmdProfileImporter(createRuleFinder());
}

@Test
public void testBuildPmdRuleset() {
Reader reader = new StringReader(TestUtils.getResourceContent("/org/sonar/plugins/pmd/simple.xml"));
public void should_import_pmd_ruleset() {
Reader reader = read("/org/sonar/plugins/pmd/simple.xml");

PmdRuleset pmdRuleset = importer.parsePmdRuleset(reader, messages);
assertThat(pmdRuleset.getPmdRules().size(), is(3));

assertThat(pmdRuleset.getPmdRules()).hasSize(3);
}

@Test
public void testImportingSimpleProfile() {
Reader reader = new StringReader(TestUtils.getResourceContent("/org/sonar/plugins/pmd/simple.xml"));
public void should_import_simple_profile() {
Reader reader = read("/org/sonar/plugins/pmd/simple.xml");

RulesProfile profile = importer.importProfile(reader, messages);

assertThat(profile.getActiveRules().size(), is(3));
assertNotNull(profile.getActiveRuleByConfigKey("pmd", "rulesets/coupling.xml/ExcessiveImports"));
assertNotNull(profile.getActiveRuleByConfigKey("pmd", "rulesets/design.xml/UseNotifyAllInsteadOfNotify"));
assertThat(messages.hasErrors(), is(false));
assertThat(profile.getActiveRules()).hasSize(3);
assertThat(profile.getActiveRuleByConfigKey("pmd", "rulesets/coupling.xml/ExcessiveImports")).isNotNull();
assertThat(profile.getActiveRuleByConfigKey("pmd", "rulesets/design.xml/UseNotifyAllInsteadOfNotify")).isNotNull();
assertThat(messages.hasErrors()).isFalse();
}

@Test
public void testImportingProfileWithXPathRule() {
Reader reader = new StringReader(TestUtils.getResourceContent("/org/sonar/plugins/pmd/export_xpath_rules.xml"));
public void should_import_profile_with_xpath_rule() {
Reader reader = read("/org/sonar/plugins/pmd/export_xpath_rules.xml");

RulesProfile profile = importer.importProfile(reader, messages);

assertThat(profile.getActiveRules().size(), is(0));
assertThat(messages.hasWarnings(), is(true));
assertThat(profile.getActiveRules()).isEmpty();
assertThat(messages.hasWarnings()).isTrue();
}

@Test
public void testImportingParameters() {
Reader reader = new StringReader(TestUtils.getResourceContent("/org/sonar/plugins/pmd/simple.xml"));
RulesProfile profile = importer.importProfile(reader, messages);
public void should_import_parameter() {
Reader reader = read("/org/sonar/plugins/pmd/simple.xml");

RulesProfile profile = importer.importProfile(reader, messages);
ActiveRule activeRule = profile.getActiveRuleByConfigKey("pmd", "rulesets/coupling.xml/ExcessiveImports");
assertThat(activeRule.getActiveRuleParams().size(), is(1));
assertThat(activeRule.getParameter("max"), is("30"));
assertThat(activeRule.getParameter("max")).isEqualTo("30");
}

@Test
public void testImportingDefaultPriority() {
Reader reader = new StringReader(TestUtils.getResourceContent("/org/sonar/plugins/pmd/simple.xml"));
RulesProfile profile = importer.importProfile(reader, messages);
public void should_import_default_priority() {
Reader reader = read("/org/sonar/plugins/pmd/simple.xml");

RulesProfile profile = importer.importProfile(reader, messages);
ActiveRule activeRule = profile.getActiveRuleByConfigKey("pmd", "rulesets/coupling.xml/ExcessiveImports");
assertThat(activeRule.getSeverity(), is(RulePriority.BLOCKER)); // reuse the rule default priority

assertThat(activeRule.getSeverity()).isSameAs(RulePriority.BLOCKER);
}

@Test
public void testImportingPriority() {
Reader reader = new StringReader(TestUtils.getResourceContent("/org/sonar/plugins/pmd/simple.xml"));
public void should_import_priority() {
Reader reader = read("/org/sonar/plugins/pmd/simple.xml");

RulesProfile profile = importer.importProfile(reader, messages);

ActiveRule activeRule = profile.getActiveRuleByConfigKey("pmd", "rulesets/design.xml/UseNotifyAllInsteadOfNotify");
assertThat(activeRule.getSeverity(), is(RulePriority.MINOR));
assertThat(activeRule.getSeverity()).isSameAs(RulePriority.MINOR);

activeRule = profile.getActiveRuleByConfigKey("pmd", "rulesets/coupling.xml/CouplingBetweenObjects");
assertThat(activeRule.getSeverity(), is(RulePriority.CRITICAL));
assertThat(activeRule.getSeverity()).isSameAs(RulePriority.CRITICAL);
}

@Test
public void testImportingPmdConfigurationWithUnknownNodes() {
Reader reader = new StringReader(TestUtils.getResourceContent("/org/sonar/plugins/pmd/complex-with-unknown-nodes.xml"));
public void should_import_pmd_configuration_with_unknown_nodes() {
Reader reader = read("/org/sonar/plugins/pmd/complex-with-unknown-nodes.xml");

RulesProfile profile = importer.importProfile(reader, messages);

assertThat(profile.getActiveRules().size(), is(3));
assertThat(profile.getActiveRules()).hasSize(3);
}

@Test
public void testUnsupportedProperty() {
Reader reader = new StringReader(TestUtils.getResourceContent("/org/sonar/plugins/pmd/simple.xml"));
RulesProfile profile = importer.importProfile(reader, messages);
public void should_deal_with_unsupported_property() {
Reader reader = read("/org/sonar/plugins/pmd/simple.xml");

RulesProfile profile = importer.importProfile(reader, messages);
ActiveRule check = profile.getActiveRuleByConfigKey("pmd", "rulesets/coupling.xml/CouplingBetweenObjects");
assertThat(check.getParameter("threshold"), nullValue());
assertThat(messages.getWarnings().size(), is(1));

assertThat(check.getParameter("threshold")).isNull();
assertThat(messages.getWarnings()).hasSize(1);
}

@Test
public void testUnvalidXML() {
public void should_fail_on_invalid_xml() {
Reader reader = new StringReader("not xml");

importer.importProfile(reader, messages);
assertThat(messages.getErrors().size(), is(1));

assertThat(messages.getErrors()).hasSize(1);
}

@Test
public void testImportingUnknownRules() {
Reader reader = new StringReader(TestUtils.getResourceContent("/org/sonar/plugins/pmd/simple.xml"));
public void should_warn_on_unknown_rule() {
Reader reader = read("/org/sonar/plugins/pmd/simple.xml");

importer = new PmdProfileImporter(mock(RuleFinder.class));
RulesProfile profile = importer.importProfile(reader, messages);

assertThat(profile.getActiveRules().size(), is(0));
assertThat(messages.getWarnings().size(), is(3));
assertThat(profile.getActiveRules()).isEmpty();
assertThat(messages.getWarnings()).hasSize(3);
}

private RuleFinder createRuleFinder() {
RuleFinder ruleFinder = mock(RuleFinder.class);
when(ruleFinder.find((RuleQuery) anyObject())).thenAnswer(new Answer<Rule>() {
static Reader read(String path) {
return new StringReader(TestUtils.getResourceContent(path));
}

public Rule answer(InvocationOnMock iom) throws Throwable {
RuleQuery query = (RuleQuery) iom.getArguments()[0];
Rule rule = Rule.create(query.getRepositoryKey(), query.getConfigKey(), "Rule name - " + query.getConfigKey())
.setConfigKey(query.getConfigKey()).setSeverity(RulePriority.BLOCKER);
static RuleFinder createRuleFinder() {
RuleFinder ruleFinder = mock(RuleFinder.class);
when(ruleFinder.find((RuleQuery) anyObject())).then(new Answer<Rule>() {
public Rule answer(InvocationOnMock invocation) {
RuleQuery query = (RuleQuery) invocation.getArguments()[0];
Rule rule = Rule.create(query.getRepositoryKey(), "", "").setConfigKey(query.getConfigKey()).setSeverity(RulePriority.BLOCKER);
if (rule.getConfigKey().equals("rulesets/coupling.xml/ExcessiveImports")) {
rule.createParameter("max");
}

plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/SunConventionsProfileTest.java → plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdProfilesTest.java Voir le fichier

@@ -22,44 +22,59 @@ package org.sonar.plugins.pmd;
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.RulesProfile;
import org.sonar.api.rules.Rule;
import org.sonar.api.rules.RuleFinder;
import org.sonar.api.rules.RulePriority;
import org.sonar.api.rules.RuleQuery;
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.anyObject;
import static org.fest.assertions.Assertions.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

public class SunConventionsProfileTest {
public class PmdProfilesTest {
ValidationMessages validation = ValidationMessages.create();

@Test
public void shouldCreateProfile() {
SunConventionsProfile sunConvention = new SunConventionsProfile(createPmdProfileImporter());
ValidationMessages validation = ValidationMessages.create();
public void should_create_sun_convention_profile() {
SunConventionsProfile sunConvention = new SunConventionsProfile(new PmdProfileImporter(ruleFinder()));
RulesProfile profile = sunConvention.createProfile(validation);
assertThat(profile.getActiveRulesByRepository(PmdConstants.REPOSITORY_KEY).size(), greaterThan(1));
assertThat(validation.hasErrors(), is(false));

assertThat(profile.getActiveRulesByRepository(PmdConstants.REPOSITORY_KEY)).isNotEmpty();
assertThat(validation.hasErrors()).isFalse();
}

private PmdProfileImporter createPmdProfileImporter() {
@Test
public void should_create_sonar_way_profile() {
ProfileDefinition sonarWay = new SonarWayProfile(new PmdProfileImporter(ruleFinder()));

RuleFinder ruleFinder = mock(RuleFinder.class);
when(ruleFinder.find((RuleQuery) anyObject())).thenAnswer(new Answer<Rule>() {
RulesProfile profile = sonarWay.createProfile(validation);

assertThat(profile.getActiveRulesByRepository(PmdConstants.REPOSITORY_KEY)).isNotEmpty();
assertThat(validation.hasErrors()).isFalse();
}

public Rule answer(InvocationOnMock iom) throws Throwable {
RuleQuery query = (RuleQuery) iom.getArguments()[0];
Rule rule = Rule.create(query.getRepositoryKey(), query.getConfigKey(), "Rule name - " + query.getConfigKey())
.setConfigKey(query.getConfigKey()).setSeverity(RulePriority.BLOCKER);
return rule;
@Test
public void should_create_sonar_way_with_findbugs_profile() {
ProfileDefinition sonarWayWithFindbugs = new SonarWayWithFindbugsProfile(new SonarWayProfile(new PmdProfileImporter(ruleFinder())));

RulesProfile profile = sonarWayWithFindbugs.createProfile(validation);

assertThat(profile.getActiveRulesByRepository(PmdConstants.REPOSITORY_KEY)).isNotEmpty();
assertThat(validation.hasErrors()).isFalse();
}

static RuleFinder ruleFinder() {
RuleFinder ruleFinder = mock(RuleFinder.class);
when(ruleFinder.find(any(RuleQuery.class))).then(new Answer<Rule>() {
public Rule answer(InvocationOnMock invocation) {
RuleQuery query = (RuleQuery) invocation.getArguments()[0];
return Rule.create(query.getRepositoryKey(), "", "");
}
});
PmdProfileImporter importer = new PmdProfileImporter(ruleFinder);
return importer;
return ruleFinder;
}

}

+ 43
- 16
plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdRuleRepositoryTest.java Voir le fichier

@@ -19,41 +19,68 @@
*/
package org.sonar.plugins.pmd;

import org.apache.commons.io.FileUtils;
import org.junit.Before;
import org.junit.Test;
import org.sonar.api.platform.ServerFileSystem;
import org.sonar.api.rules.Rule;
import org.sonar.api.rules.XMLRuleParser;
import org.sonar.test.TestUtils;
import org.sonar.test.i18n.RuleRepositoryTestHelper;

import java.io.File;
import java.util.Collections;
import java.util.Arrays;
import java.util.List;

import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
import static org.fest.assertions.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

public class PmdRuleRepositoryTest {
PmdRuleRepository repository;

ServerFileSystem fileSystem = mock(ServerFileSystem.class);

@Before
public void setUpRuleRepository() {
repository = new PmdRuleRepository(fileSystem, new XMLRuleParser());
}

@Test
public void testLoadRepositoryFromXml() {
ServerFileSystem fileSystem = mock(ServerFileSystem.class);
PmdRuleRepository repository = new PmdRuleRepository(fileSystem, new XMLRuleParser());
public void should_have_correct_name_and_key() {
assertThat(repository.getKey()).isEqualTo("pmd");
assertThat(repository.getLanguage()).isEqualTo("java");
assertThat(repository.getName()).isEqualTo("PMD");
}

@Test
public void should_load_repository_from_xml() {
List<Rule> rules = repository.createRules();
assertThat(rules.size(), greaterThan(100));

assertThat(rules.size()).isGreaterThan(100);
}

@Test
public void shouldLoadExtensions() {
ServerFileSystem fileSystem = mock(ServerFileSystem.class);
File file = FileUtils.toFile(getClass().getResource("/org/sonar/plugins/pmd/rules-extension.xml"));
when(fileSystem.getExtensions("pmd", "xml")).thenReturn(Collections.singletonList(file));
PmdRuleRepository repository = new PmdRuleRepository(fileSystem, new XMLRuleParser());
public void should_load_extensions() {
File file = TestUtils.getResource("/org/sonar/plugins/pmd/rules-extension.xml");
when(fileSystem.getExtensions("pmd", "xml")).thenReturn(Arrays.asList(file));

List<Rule> rules = repository.createRules();
assertThat(rules.size(), greaterThan(100));
assertThat(rules.get(rules.size() - 1).getKey(), is("Extension"));
assertThat(rules).onProperty("key").contains("Extension");
}

@Test
public void should_exclude_junit_rules() {
List<Rule> rules = repository.createRules();

assertThat(rules).onProperty("key").excludes("JUnitStaticSuite");
}

@Test
public void should_provide_a_name_and_description_for_each_rule() {
List<Rule> rules = RuleRepositoryTestHelper.createRulesWithNameAndDescription("pmd", repository);

assertThat(rules).onProperty("name").excludes(null, "");
assertThat(rules).onProperty("description").excludes(null, "");
}
}

+ 126
- 0
plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdSensorTest.java Voir le fichier

@@ -0,0 +1,126 @@
/*
* Sonar, open source software quality management tool.
* Copyright (C) 2008-2012 SonarSource
* 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.plugins.pmd;

import com.google.common.collect.Iterators;
import net.sourceforge.pmd.IRuleViolation;
import net.sourceforge.pmd.Report;
import org.junit.Before;
import org.junit.Test;
import org.sonar.api.batch.SensorContext;
import org.sonar.api.profiles.RulesProfile;
import org.sonar.api.resources.Java;
import org.sonar.api.resources.Project;
import org.sonar.api.rules.Violation;

import static org.fest.assertions.Assertions.assertThat;
import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;

public class PmdSensorTest {
PmdSensor pmdSensor;

Project project = mock(Project.class, RETURNS_DEEP_STUBS);
RulesProfile profile = mock(RulesProfile.class, RETURNS_DEEP_STUBS);
PmdExecutor executor = mock(PmdExecutor.class);
PmdViolationToRuleViolation pmdViolationToRuleViolation = mock(PmdViolationToRuleViolation.class);
SensorContext sensorContext = mock(SensorContext.class);
Violation violation = mock(Violation.class);

@Before
public void setUpPmdSensor() {
pmdSensor = new PmdSensor(profile, executor, pmdViolationToRuleViolation);
}

@Test
public void should_execute_on_project_with_main_files_and_active_rules() {
boolean shouldExecute = pmdSensor.shouldExecuteOnProject(project);

assertThat(shouldExecute).isTrue();
}

@Test
public void should_not_execute_on_project_without_files() {
when(project.getFileSystem().mainFiles(Java.KEY).isEmpty()).thenReturn(true);
when(project.getFileSystem().testFiles(Java.KEY).isEmpty()).thenReturn(true);

boolean shouldExecute = pmdSensor.shouldExecuteOnProject(project);

assertThat(shouldExecute).isFalse();
}

@Test
public void should_not_execute_on_project_without_active_rules() {
when(profile.getActiveRulesByRepository(PmdConstants.REPOSITORY_KEY).isEmpty()).thenReturn(true);
when(profile.getActiveRulesByRepository(PmdConstants.TEST_REPOSITORY_KEY).isEmpty()).thenReturn(true);

boolean shouldExecute = pmdSensor.shouldExecuteOnProject(project);

assertThat(shouldExecute).isFalse();
}

@Test
public void should_report_violations() {
IRuleViolation pmdViolation = violation();
Report report = report(pmdViolation);
when(executor.execute()).thenReturn(report);
when(pmdViolationToRuleViolation.toViolation(pmdViolation, sensorContext)).thenReturn(violation);

pmdSensor.analyse(project, sensorContext);

verify(sensorContext).saveViolation(violation);
}

@Test
public void shouldnt_report_zero_violation() {
Report report = report();
when(executor.execute()).thenReturn(report);

pmdSensor.analyse(project, sensorContext);

verifyZeroInteractions(sensorContext);
}

@Test
public void shouldnt_report_invalid_violation() {
IRuleViolation pmdViolation = violation();
Report report = report(pmdViolation);
when(executor.execute()).thenReturn(report);
when(report.iterator()).thenReturn(Iterators.forArray(pmdViolation));
when(pmdViolationToRuleViolation.toViolation(pmdViolation, sensorContext)).thenReturn(null);

pmdSensor.analyse(project, sensorContext);

verifyZeroInteractions(sensorContext);
}

static IRuleViolation violation() {
return mock(IRuleViolation.class);
}

static Report report(IRuleViolation... violations) {
Report report = mock(Report.class);
when(report.iterator()).thenReturn(Iterators.forArray(violations));
return report;
}
}

+ 59
- 0
plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdTemplateTest.java Voir le fichier

@@ -0,0 +1,59 @@
/*
* Sonar, open source software quality management tool.
* Copyright (C) 2008-2012 SonarSource
* 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.plugins.pmd;

import net.sourceforge.pmd.PMD;
import net.sourceforge.pmd.SourceType;
import org.junit.Test;

import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;

public class PmdTemplateTest {
PMD pmd = mock(PMD.class);

@Test
public void should_set_java11_version() {
PmdTemplate.setJavaVersion(pmd, "1.1");

verify(pmd).setJavaVersion(SourceType.JAVA_13);
}

@Test
public void should_set_java12_version() {
PmdTemplate.setJavaVersion(pmd, "1.2");

verify(pmd).setJavaVersion(SourceType.JAVA_13);
}

@Test
public void should_set_java5_version() {
PmdTemplate.setJavaVersion(pmd, "5");

verify(pmd).setJavaVersion(SourceType.JAVA_15);
}

@Test
public void should_set_java6_version() {
PmdTemplate.setJavaVersion(pmd, "6");

verify(pmd).setJavaVersion(SourceType.JAVA_16);
}
}

+ 71
- 0
plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdUnitTestsRuleRepositoryTest.java Voir le fichier

@@ -0,0 +1,71 @@
/*
* Sonar, open source software quality management tool.
* Copyright (C) 2008-2012 SonarSource
* 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.plugins.pmd;

import org.junit.Before;
import org.junit.Test;
import org.sonar.api.rules.Rule;
import org.sonar.api.rules.XMLRuleParser;
import org.sonar.test.i18n.RuleRepositoryTestHelper;

import java.util.List;

import static org.fest.assertions.Assertions.assertThat;

public class PmdUnitTestsRuleRepositoryTest {
PmdUnitTestsRuleRepository repository;

@Before
public void setUpRuleRepository() {
repository = new PmdUnitTestsRuleRepository(new XMLRuleParser());
}

@Test
public void should_have_correct_name_and_key() {
assertThat(repository.getKey()).isEqualTo("pmd-unit-tests");
assertThat(repository.getLanguage()).isEqualTo("java");
assertThat(repository.getName()).isEqualTo("PMD Unit Tests");
}

@Test
public void should_load_repository_from_xml() {
List<Rule> rules = repository.createRules();

assertThat(rules).onProperty("key").containsOnly(
"JUnitStaticSuite",
"JUnitSpelling",
"JUnitAssertionsShouldIncludeMessage",
"JUnitTestsShouldIncludeAssert",
"TestClassWithoutTestCases",
"UnnecessaryBooleanAssertion",
"UseAssertEqualsInsteadOfAssertTrue",
"UseAssertSameInsteadOfAssertTrue",
"UseAssertNullInsteadOfAssertTrue",
"SimplifyBooleanAssertion");
}

@Test
public void should_provide_a_name_and_description_for_each_rule() {
List<Rule> rules = RuleRepositoryTestHelper.createRulesWithNameAndDescription("pmd", repository);

assertThat(rules).onProperty("name").excludes(null, "");
assertThat(rules).onProperty("description").excludes(null, "");
}
}

+ 3
- 7
plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdVersionTest.java Voir le fichier

@@ -21,15 +21,11 @@ package org.sonar.plugins.pmd;

import org.junit.Test;

import static junit.framework.Assert.assertEquals;
import static org.hamcrest.number.OrderingComparisons.greaterThan;
import static org.junit.Assert.assertThat;
import static org.fest.assertions.Assertions.assertThat;

public class PmdVersionTest {
@Test
public void getCheckstyleVersion() {
assertThat(PmdVersion.getVersion().length(), greaterThan(1));
assertEquals(PmdVersion.getVersion(), PmdVersion.getVersion());
public void should_get_pmd_version() {
assertThat(PmdVersion.getVersion()).isNotEmpty().isSameAs(PmdVersion.getVersion());
}

}

+ 0
- 66
plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/SonarWayProfileTest.java Voir le fichier

@@ -1,66 +0,0 @@
/*
* Sonar, open source software quality management tool.
* Copyright (C) 2008-2012 SonarSource
* 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.plugins.pmd;

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.RulesProfile;
import org.sonar.api.rules.Rule;
import org.sonar.api.rules.RuleFinder;
import org.sonar.api.rules.RulePriority;
import org.sonar.api.rules.RuleQuery;
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.anyObject;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

public class SonarWayProfileTest {

@Test
public void shouldCreateProfile() {
ProfileDefinition sonarWay = new SonarWayProfile(createPmdProfileImporter());
ValidationMessages validation = ValidationMessages.create();
RulesProfile profile = sonarWay.createProfile(validation);
assertThat(profile.getActiveRulesByRepository(PmdConstants.REPOSITORY_KEY).size(), greaterThan(1));
assertThat(validation.hasErrors(), is(false));
}

private PmdProfileImporter createPmdProfileImporter() {

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 = Rule.create(query.getRepositoryKey(), query.getConfigKey(), "Rule name - " + query.getConfigKey())
.setConfigKey(query.getConfigKey()).setSeverity(RulePriority.BLOCKER);
return rule;
}
});
PmdProfileImporter importer = new PmdProfileImporter(ruleFinder);
return importer;
}
}

+ 0
- 65
plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/SonarWayWithFindbugsProfileTest.java Voir le fichier

@@ -1,65 +0,0 @@
/*
* Sonar, open source software quality management tool.
* Copyright (C) 2008-2012 SonarSource
* 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.plugins.pmd;

import org.junit.Test;
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.rules.RulePriority;
import org.sonar.api.rules.RuleQuery;
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.anyObject;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

public class SonarWayWithFindbugsProfileTest {

@Test
public void shouldCreateProfile() {
SonarWayWithFindbugsProfile sonarWayWithFindbugs = new SonarWayWithFindbugsProfile(new SonarWayProfile(createPmdProfileImporter()));
ValidationMessages validation = ValidationMessages.create();
RulesProfile profile = sonarWayWithFindbugs.createProfile(validation);
assertThat(profile.getActiveRulesByRepository(PmdConstants.REPOSITORY_KEY).size(), greaterThan(1));
assertThat(validation.hasErrors(), is(false));
}

private PmdProfileImporter createPmdProfileImporter() {

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 = Rule.create(query.getRepositoryKey(), query.getConfigKey(), "Rule name - " + query.getConfigKey())
.setConfigKey(query.getConfigKey()).setSeverity(RulePriority.BLOCKER);
return rule;
}
});
PmdProfileImporter importer = new PmdProfileImporter(ruleFinder);
return importer;
}
}

+ 0
- 22
plugins/sonar-pmd-plugin/src/test/resources/org/sonar/plugins/pmd/PmdConfigurationTest/failIfConfigurationToReuseDoesNotExist/pom.xml Voir le fichier

@@ -1,22 +0,0 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>fake.group</groupId>
<artifactId>fake.artifactId</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>

<properties>
<sonar.reuseExistingRulesConfiguration>true</sonar.reuseExistingRulesConfiguration>
</properties>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-pmd-plugin</artifactId>
<!-- rulesets are not set in <configuration> -->
</plugin>
</plugins>
</build>
</project>

+ 0
- 27
plugins/sonar-pmd-plugin/src/test/resources/org/sonar/plugins/pmd/PmdConfigurationTest/findConfigurationToReuse/pom.xml Voir le fichier

@@ -1,27 +0,0 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>fake.group</groupId>
<artifactId>fake.artifactId</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>

<properties>
<sonar.reuseExistingRulesConfiguration>true</sonar.reuseExistingRulesConfiguration>
</properties>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-pmd-plugin</artifactId>
<configuration>
<rulesets>
<ruleset>ruleset/maven.xml</ruleset>
<ruleset>ruleset/basic.xml</ruleset>
</rulesets>
</configuration>
</plugin>
</plugins>
</build>
</project>

+ 0
- 8
plugins/sonar-pmd-plugin/src/test/resources/org/sonar/plugins/pmd/PmdConfigurationTest/writeConfigurationToWorkingDir/pom.xml Voir le fichier

@@ -1,8 +0,0 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>fake.group</groupId>
<artifactId>fake.artifactId</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
</project>

+ 0
- 263
plugins/sonar-pmd-plugin/src/test/resources/org/sonar/plugins/pmd/PmdExecutorTest/executeOnManySourceDirs/pmd.xml Voir le fichier

@@ -1,263 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- generated by Sonar -->
<ruleset>
<description>Sonar way</description>
<rule ref="rulesets/unusedcode.xml/UnusedLocalVariable">
<priority>3</priority>
</rule>
<rule ref="rulesets/finalizers.xml/AvoidCallingFinalize">
<priority>3</priority>
</rule>
<rule ref="rulesets/unusedcode.xml/UnusedPrivateField">
<priority>3</priority>
</rule>
<rule ref="rulesets/finalizers.xml/FinalizeOverloaded">
<priority>3</priority>
</rule>
<rule ref="rulesets/finalizers.xml/FinalizeDoesNotCallSuperFinalize">
<priority>3</priority>
</rule>
<rule ref="rulesets/finalizers.xml/EmptyFinalizer">
<priority>3</priority>
</rule>
<rule ref="rulesets/unusedcode.xml/UnusedPrivateMethod">
<priority>3</priority>
</rule>
<rule ref="rulesets/unusedcode.xml/UnusedFormalParameter">
<priority>3</priority>
</rule>
<rule ref="rulesets/controversial.xml/UnusedModifier">
<priority>5</priority>
</rule>
<rule ref="rulesets/controversial.xml/DontImportSun">
<priority>4</priority>
</rule>
<rule ref="rulesets/design.xml/SingularField">
<priority>4</priority>
</rule>
<rule ref="rulesets/coupling.xml/LooseCoupling">
<priority>3</priority>
</rule>
<rule ref="rulesets/optimizations.xml/UseArrayListInsteadOfVector">
<priority>3</priority>
</rule>
<rule ref="rulesets/optimizations.xml/UseArraysAsList">
<priority>3</priority>
</rule>
<rule ref="rulesets/optimizations.xml/AvoidArrayLoops">
<priority>3</priority>
</rule>
<rule ref="rulesets/basic.xml/EmptyIfStmt">
<priority>2</priority>
</rule>
<rule ref="rulesets/basic.xml/EmptyWhileStmt">
<priority>2</priority>
</rule>
<rule ref="rulesets/basic.xml/EmptyTryBlock">
<priority>3</priority>
</rule>
<rule ref="rulesets/basic.xml/EmptyFinallyBlock">
<priority>2</priority>
</rule>
<rule ref="rulesets/basic.xml/EmptySwitchStatements">
<priority>3</priority>
</rule>
<rule ref="rulesets/basic.xml/EmptySynchronizedBlock">
<priority>2</priority>
</rule>
<rule ref="rulesets/basic.xml/EmptyStaticInitializer">
<priority>3</priority>
</rule>
<rule ref="rulesets/basic.xml/UnconditionalIfStatement">
<priority>2</priority>
</rule>
<rule ref="rulesets/basic.xml/BooleanInstantiation">
<priority>3</priority>
</rule>
<rule ref="rulesets/basic.xml/CollapsibleIfStatements">
<priority>4</priority>
</rule>
<rule ref="rulesets/basic.xml/UselessOverridingMethod">
<priority>3</priority>
</rule>
<rule ref="rulesets/basic.xml/ClassCastExceptionWithToArray">
<priority>3</priority>
</rule>
<rule ref="rulesets/basic.xml/AvoidDecimalLiteralsInBigDecimalConstructor">
<priority>3</priority>
</rule>
<rule ref="rulesets/basic.xml/UselessOperationOnImmutable">
<priority>2</priority>
</rule>
<rule ref="rulesets/basic.xml/UnusedNullCheckInEquals">
<priority>3</priority>
</rule>
<rule ref="rulesets/basic.xml/BrokenNullCheck">
<priority>2</priority>
</rule>
<rule ref="rulesets/basic.xml/BigIntegerInstantiation">
<priority>3</priority>
</rule>
<rule ref="rulesets/design.xml/ConstructorCallsOverridableMethod">
<priority>3</priority>
</rule>
<rule ref="rulesets/design.xml/FinalFieldCouldBeStatic">
<priority>4</priority>
</rule>
<rule ref="rulesets/design.xml/CloseResource">
<priority>3</priority>
</rule>
<rule ref="rulesets/design.xml/EqualsNull">
<priority>2</priority>
</rule>
<rule ref="rulesets/design.xml/InstantiationToGetClass">
<priority>3</priority>
</rule>
<rule ref="rulesets/design.xml/IdempotentOperations">
<priority>3</priority>
</rule>
<rule ref="rulesets/design.xml/MissingStaticMethodInNonInstantiatableClass">
<priority>3</priority>
</rule>
<rule ref="rulesets/design.xml/AvoidInstanceofChecksInCatchClause">
<priority>4</priority>
</rule>
<rule ref="rulesets/design.xml/SimplifyConditional">
<priority>3</priority>
</rule>
<rule ref="rulesets/design.xml/CompareObjectsWithEquals">
<priority>3</priority>
</rule>
<rule ref="rulesets/design.xml/UnnecessaryLocalBeforeReturn">
<priority>3</priority>
</rule>
<rule ref="rulesets/design.xml/PreserveStackTrace">
<priority>3</priority>
</rule>
<rule ref="rulesets/sunsecure.xml/ArrayIsStoredDirectly">
<priority>2</priority>
</rule>
<rule ref="rulesets/strictexception.xml/AvoidCatchingThrowable">
<priority>2</priority>
</rule>
<rule ref="rulesets/strictexception.xml/SignatureDeclareThrowsException">
<priority>3</priority>
</rule>
<rule ref="rulesets/strictexception.xml/ExceptionAsFlowControl">
<priority>3</priority>
</rule>
<rule ref="rulesets/strictexception.xml/AvoidCatchingNPE">
<priority>3</priority>
</rule>
<rule ref="rulesets/strictexception.xml/AvoidThrowingRawExceptionTypes">
<priority>3</priority>
</rule>
<rule ref="rulesets/strictexception.xml/AvoidThrowingNullPointerException">
<priority>3</priority>
</rule>
<rule ref="rulesets/strictexception.xml/AvoidRethrowingException">
<priority>3</priority>
</rule>
<rule ref="rulesets/strings.xml/AvoidDuplicateLiterals">
<priority>3</priority>
</rule>
<rule ref="rulesets/strings.xml/StringInstantiation">
<priority>3</priority>
</rule>
<rule ref="rulesets/strings.xml/StringToString">
<priority>3</priority>
</rule>
<rule ref="rulesets/strings.xml/InefficientStringBuffering">
<priority>3</priority>
</rule>
<rule ref="rulesets/strings.xml/UnnecessaryCaseChange">
<priority>4</priority>
</rule>
<rule ref="rulesets/strings.xml/UseStringBufferLength">
<priority>4</priority>
</rule>
<rule ref="rulesets/strings.xml/UseIndexOfChar">
<priority>3</priority>
</rule>
<rule ref="rulesets/strings.xml/UselessStringValueOf">
<priority>4</priority>
</rule>
<rule ref="rulesets/strings.xml/StringBufferInstantiationWithChar">
<priority>3</priority>
</rule>
<rule ref="rulesets/codesize.xml/NcssMethodCount">
<priority>3</priority>
<properties>
<property name="minimum" value="50"/>
</properties>
</rule>
<rule ref="rulesets/codesize.xml/NcssTypeCount">
<priority>3</priority>
<properties>
<property name="minimum" value="800"/>
</properties>
</rule>
<rule ref="rulesets/imports.xml/DontImportJavaLang">
<priority>4</priority>
</rule>
<rule ref="rulesets/clone.xml/CloneThrowsCloneNotSupportedException">
<priority>3</priority>
</rule>
<rule ref="rulesets/logging-jakarta-commons.xml/UseCorrectExceptionLogging">
<priority>3</priority>
</rule>
<rule ref="rulesets/naming.xml/ClassNamingConventions">
<priority>3</priority>
</rule>
<rule ref="rulesets/naming.xml/AvoidDollarSigns">
<priority>4</priority>
</rule>
<rule ref="rulesets/naming.xml/MethodWithSameNameAsEnclosingClass">
<priority>3</priority>
</rule>
<rule ref="rulesets/naming.xml/SuspiciousHashcodeMethodName">
<priority>3</priority>
</rule>
<rule ref="rulesets/naming.xml/SuspiciousConstantFieldName">
<priority>3</priority>
</rule>
<rule ref="rulesets/naming.xml/SuspiciousEqualsMethodName">
<priority>2</priority>
</rule>
<rule ref="rulesets/migrating.xml/ReplaceVectorWithList">
<priority>3</priority>
</rule>
<rule ref="rulesets/migrating.xml/ReplaceHashtableWithMap">
<priority>3</priority>
</rule>
<rule ref="rulesets/migrating.xml/ReplaceEnumerationWithIterator">
<priority>3</priority>
</rule>
<rule ref="rulesets/migrating.xml/AvoidEnumAsIdentifier">
<priority>3</priority>
</rule>
<rule ref="rulesets/migrating.xml/AvoidAssertAsIdentifier">
<priority>3</priority>
</rule>
<rule ref="rulesets/migrating.xml/IntegerInstantiation">
<priority>3</priority>
</rule>
<rule ref="rulesets/logging-java.xml/SystemPrintln">
<priority>3</priority>
</rule>
<rule ref="rulesets/logging-java.xml/AvoidPrintStackTrace">
<priority>3</priority>
</rule>
<rule ref="rulesets/braces.xml/IfStmtsMustUseBraces">
<priority>3</priority>
</rule>
<rule ref="rulesets/braces.xml/WhileLoopsMustUseBraces">
<priority>3</priority>
</rule>
<rule ref="rulesets/braces.xml/IfElseStmtsMustUseBraces">
<priority>3</priority>
</rule>
<rule ref="rulesets/braces.xml/ForLoopsMustUseBraces">
<priority>3</priority>
</rule>
</ruleset>

+ 0
- 9
plugins/sonar-pmd-plugin/src/test/resources/org/sonar/plugins/pmd/PmdExecutorTest/executeOnManySourceDirs/src1/FirstClass.java Voir le fichier

@@ -1,9 +0,0 @@
public class FirstClass {

private FirstClass() {
int unused= new Integer(0);
if (true) {
unused += new Integer(12345);
}
}
}

+ 0
- 9
plugins/sonar-pmd-plugin/src/test/resources/org/sonar/plugins/pmd/PmdExecutorTest/executeOnManySourceDirs/src2/SecondClass.java Voir le fichier

@@ -1,9 +0,0 @@
public class SecondClass {

private SecondClass() {
int unused= 0;
if (true) {
unused += 12345;
}
}
}

+ 7
- 0
plugins/sonar-pmd-plugin/src/test/resources/org/sonar/plugins/pmd/junit.xml Voir le fichier

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ruleset>
<description>Sonar PMD Unit Tests rules</description>
<rule ref="rulesets/junit.xml/SimplifyBooleanAssertion">
<priority>2</priority>
</rule>
</ruleset>

+ 0
- 20
plugins/sonar-pmd-plugin/src/test/resources/org/sonar/plugins/pmd/test_xml_complete.xml Voir le fichier

@@ -1,20 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Sonar PMD rules generated configuration -->
<ruleset>
<description>A test profile</description>
<rule ref="rulesets/coupling.xml/CouplingBetweenObjects">
<priority>2</priority>
<properties>
<property name="threshold" value="20"/>
</properties>
</rule>
<rule ref="rulesets/coupling.xml/ExcessiveImports">
<priority>3</priority>
<properties>
<property name="max" value="30"/>
</properties>
</rule>
<rule ref="rulesets/design.xml/UseNotifyAllInsteadOfNotify">
<priority>4</priority>
</rule>
</ruleset>

+ 0
- 5
plugins/sonar-pmd-plugin/test-resources/ignorePmdFailures/DoesNotCompile.java Voir le fichier

@@ -1,5 +0,0 @@
public class DoesNotCompile {

/ not java /
Yeeaah !
}

+ 0
- 263
plugins/sonar-pmd-plugin/test-resources/ignorePmdFailures/pmd.xml Voir le fichier

@@ -1,263 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- generated by Sonar -->
<ruleset>
<description>Sonar way</description>
<rule ref="rulesets/unusedcode.xml/UnusedLocalVariable">
<priority>3</priority>
</rule>
<rule ref="rulesets/finalizers.xml/AvoidCallingFinalize">
<priority>3</priority>
</rule>
<rule ref="rulesets/unusedcode.xml/UnusedPrivateField">
<priority>3</priority>
</rule>
<rule ref="rulesets/finalizers.xml/FinalizeOverloaded">
<priority>3</priority>
</rule>
<rule ref="rulesets/finalizers.xml/FinalizeDoesNotCallSuperFinalize">
<priority>3</priority>
</rule>
<rule ref="rulesets/finalizers.xml/EmptyFinalizer">
<priority>3</priority>
</rule>
<rule ref="rulesets/unusedcode.xml/UnusedPrivateMethod">
<priority>3</priority>
</rule>
<rule ref="rulesets/unusedcode.xml/UnusedFormalParameter">
<priority>3</priority>
</rule>
<rule ref="rulesets/controversial.xml/UnusedModifier">
<priority>5</priority>
</rule>
<rule ref="rulesets/controversial.xml/DontImportSun">
<priority>4</priority>
</rule>
<rule ref="rulesets/design.xml/SingularField">
<priority>4</priority>
</rule>
<rule ref="rulesets/coupling.xml/LooseCoupling">
<priority>3</priority>
</rule>
<rule ref="rulesets/optimizations.xml/UseArrayListInsteadOfVector">
<priority>3</priority>
</rule>
<rule ref="rulesets/optimizations.xml/UseArraysAsList">
<priority>3</priority>
</rule>
<rule ref="rulesets/optimizations.xml/AvoidArrayLoops">
<priority>3</priority>
</rule>
<rule ref="rulesets/basic.xml/EmptyIfStmt">
<priority>2</priority>
</rule>
<rule ref="rulesets/basic.xml/EmptyWhileStmt">
<priority>2</priority>
</rule>
<rule ref="rulesets/basic.xml/EmptyTryBlock">
<priority>3</priority>
</rule>
<rule ref="rulesets/basic.xml/EmptyFinallyBlock">
<priority>2</priority>
</rule>
<rule ref="rulesets/basic.xml/EmptySwitchStatements">
<priority>3</priority>
</rule>
<rule ref="rulesets/basic.xml/EmptySynchronizedBlock">
<priority>2</priority>
</rule>
<rule ref="rulesets/basic.xml/EmptyStaticInitializer">
<priority>3</priority>
</rule>
<rule ref="rulesets/basic.xml/UnconditionalIfStatement">
<priority>2</priority>
</rule>
<rule ref="rulesets/basic.xml/BooleanInstantiation">
<priority>3</priority>
</rule>
<rule ref="rulesets/basic.xml/CollapsibleIfStatements">
<priority>4</priority>
</rule>
<rule ref="rulesets/basic.xml/UselessOverridingMethod">
<priority>3</priority>
</rule>
<rule ref="rulesets/basic.xml/ClassCastExceptionWithToArray">
<priority>3</priority>
</rule>
<rule ref="rulesets/basic.xml/AvoidDecimalLiteralsInBigDecimalConstructor">
<priority>3</priority>
</rule>
<rule ref="rulesets/basic.xml/UselessOperationOnImmutable">
<priority>2</priority>
</rule>
<rule ref="rulesets/basic.xml/UnusedNullCheckInEquals">
<priority>3</priority>
</rule>
<rule ref="rulesets/basic.xml/BrokenNullCheck">
<priority>2</priority>
</rule>
<rule ref="rulesets/basic.xml/BigIntegerInstantiation">
<priority>3</priority>
</rule>
<rule ref="rulesets/design.xml/ConstructorCallsOverridableMethod">
<priority>3</priority>
</rule>
<rule ref="rulesets/design.xml/FinalFieldCouldBeStatic">
<priority>4</priority>
</rule>
<rule ref="rulesets/design.xml/CloseResource">
<priority>3</priority>
</rule>
<rule ref="rulesets/design.xml/EqualsNull">
<priority>2</priority>
</rule>
<rule ref="rulesets/design.xml/InstantiationToGetClass">
<priority>3</priority>
</rule>
<rule ref="rulesets/design.xml/IdempotentOperations">
<priority>3</priority>
</rule>
<rule ref="rulesets/design.xml/MissingStaticMethodInNonInstantiatableClass">
<priority>3</priority>
</rule>
<rule ref="rulesets/design.xml/AvoidInstanceofChecksInCatchClause">
<priority>4</priority>
</rule>
<rule ref="rulesets/design.xml/SimplifyConditional">
<priority>3</priority>
</rule>
<rule ref="rulesets/design.xml/CompareObjectsWithEquals">
<priority>3</priority>
</rule>
<rule ref="rulesets/design.xml/UnnecessaryLocalBeforeReturn">
<priority>3</priority>
</rule>
<rule ref="rulesets/design.xml/PreserveStackTrace">
<priority>3</priority>
</rule>
<rule ref="rulesets/sunsecure.xml/ArrayIsStoredDirectly">
<priority>2</priority>
</rule>
<rule ref="rulesets/strictexception.xml/AvoidCatchingThrowable">
<priority>2</priority>
</rule>
<rule ref="rulesets/strictexception.xml/SignatureDeclareThrowsException">
<priority>3</priority>
</rule>
<rule ref="rulesets/strictexception.xml/ExceptionAsFlowControl">
<priority>3</priority>
</rule>
<rule ref="rulesets/strictexception.xml/AvoidCatchingNPE">
<priority>3</priority>
</rule>
<rule ref="rulesets/strictexception.xml/AvoidThrowingRawExceptionTypes">
<priority>3</priority>
</rule>
<rule ref="rulesets/strictexception.xml/AvoidThrowingNullPointerException">
<priority>3</priority>
</rule>
<rule ref="rulesets/strictexception.xml/AvoidRethrowingException">
<priority>3</priority>
</rule>
<rule ref="rulesets/strings.xml/AvoidDuplicateLiterals">
<priority>3</priority>
</rule>
<rule ref="rulesets/strings.xml/StringInstantiation">
<priority>3</priority>
</rule>
<rule ref="rulesets/strings.xml/StringToString">
<priority>3</priority>
</rule>
<rule ref="rulesets/strings.xml/InefficientStringBuffering">
<priority>3</priority>
</rule>
<rule ref="rulesets/strings.xml/UnnecessaryCaseChange">
<priority>4</priority>
</rule>
<rule ref="rulesets/strings.xml/UseStringBufferLength">
<priority>4</priority>
</rule>
<rule ref="rulesets/strings.xml/UseIndexOfChar">
<priority>3</priority>
</rule>
<rule ref="rulesets/strings.xml/UselessStringValueOf">
<priority>4</priority>
</rule>
<rule ref="rulesets/strings.xml/StringBufferInstantiationWithChar">
<priority>3</priority>
</rule>
<rule ref="rulesets/codesize.xml/NcssMethodCount">
<priority>3</priority>
<properties>
<property name="minimum" value="50"/>
</properties>
</rule>
<rule ref="rulesets/codesize.xml/NcssTypeCount">
<priority>3</priority>
<properties>
<property name="minimum" value="800"/>
</properties>
</rule>
<rule ref="rulesets/imports.xml/DontImportJavaLang">
<priority>4</priority>
</rule>
<rule ref="rulesets/clone.xml/CloneThrowsCloneNotSupportedException">
<priority>3</priority>
</rule>
<rule ref="rulesets/logging-jakarta-commons.xml/UseCorrectExceptionLogging">
<priority>3</priority>
</rule>
<rule ref="rulesets/naming.xml/ClassNamingConventions">
<priority>3</priority>
</rule>
<rule ref="rulesets/naming.xml/AvoidDollarSigns">
<priority>4</priority>
</rule>
<rule ref="rulesets/naming.xml/MethodWithSameNameAsEnclosingClass">
<priority>3</priority>
</rule>
<rule ref="rulesets/naming.xml/SuspiciousHashcodeMethodName">
<priority>3</priority>
</rule>
<rule ref="rulesets/naming.xml/SuspiciousConstantFieldName">
<priority>3</priority>
</rule>
<rule ref="rulesets/naming.xml/SuspiciousEqualsMethodName">
<priority>2</priority>
</rule>
<rule ref="rulesets/migrating.xml/ReplaceVectorWithList">
<priority>3</priority>
</rule>
<rule ref="rulesets/migrating.xml/ReplaceHashtableWithMap">
<priority>3</priority>
</rule>
<rule ref="rulesets/migrating.xml/ReplaceEnumerationWithIterator">
<priority>3</priority>
</rule>
<rule ref="rulesets/migrating.xml/AvoidEnumAsIdentifier">
<priority>3</priority>
</rule>
<rule ref="rulesets/migrating.xml/AvoidAssertAsIdentifier">
<priority>3</priority>
</rule>
<rule ref="rulesets/migrating.xml/IntegerInstantiation">
<priority>3</priority>
</rule>
<rule ref="rulesets/logging-java.xml/SystemPrintln">
<priority>3</priority>
</rule>
<rule ref="rulesets/logging-java.xml/AvoidPrintStackTrace">
<priority>3</priority>
</rule>
<rule ref="rulesets/braces.xml/IfStmtsMustUseBraces">
<priority>3</priority>
</rule>
<rule ref="rulesets/braces.xml/WhileLoopsMustUseBraces">
<priority>3</priority>
</rule>
<rule ref="rulesets/braces.xml/IfElseStmtsMustUseBraces">
<priority>3</priority>
</rule>
<rule ref="rulesets/braces.xml/ForLoopsMustUseBraces">
<priority>3</priority>
</rule>
</ruleset>

+ 2
- 2
sonar-server/src/main/java/org/sonar/server/ui/DefaultPages.java Voir le fichier

@@ -96,8 +96,8 @@ public final class DefaultPages {
CoreMetrics.NEW_VIOLATIONS_KEY, CoreMetrics.NEW_BLOCKER_VIOLATIONS_KEY, CoreMetrics.NEW_CRITICAL_VIOLATIONS_KEY, CoreMetrics.NEW_MAJOR_VIOLATIONS_KEY,
CoreMetrics.NEW_MINOR_VIOLATIONS_KEY, CoreMetrics.NEW_INFO_VIOLATIONS_KEY, CoreMetrics.ACTIVE_REVIEWS_KEY, CoreMetrics.UNASSIGNED_REVIEWS_KEY,
CoreMetrics.UNPLANNED_REVIEWS_KEY, CoreMetrics.FALSE_POSITIVE_REVIEWS_KEY, CoreMetrics.UNREVIEWED_VIOLATIONS_KEY, CoreMetrics.NEW_UNREVIEWED_VIOLATIONS_KEY})
@ResourceQualifier({Qualifiers.VIEW, Qualifiers.SUBVIEW, Qualifiers.PROJECT, Qualifiers.MODULE, Qualifiers.PACKAGE, Qualifiers.DIRECTORY, Qualifiers.FILE, Qualifiers.CLASS})
/* all exept unit tests...*/
@ResourceQualifier({Qualifiers.VIEW, Qualifiers.SUBVIEW, Qualifiers.PROJECT, Qualifiers.MODULE, Qualifiers.PACKAGE, Qualifiers.DIRECTORY, Qualifiers.FILE, Qualifiers.CLASS,
Qualifiers.UNIT_TEST_FILE})
@UserRole(UserRole.CODEVIEWER)
private static final class ViolationsTab implements RubyRailsPage {
public String getTemplate() {

Chargement…
Annuler
Enregistrer