<include>pom.xml</include>
</includes>
</fileSet>
+ <fileSet>
+ <directory>pmd-extensions-plugin</directory>
+ <outputDirectory>pmd-extensions-plugin</outputDirectory>
+ <includes>
+ <include>src/**/*</include>
+ <include>pom.xml</include>
+ </includes>
+ </fileSet>
<fileSet>
<directory>${project.basedir}</directory>
<outputDirectory>/</outputDirectory>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<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>com.mycompany.sonar</groupId>
+ <artifactId>sonar-pmd-extensions-plugin</artifactId>
+ <packaging>sonar-plugin</packaging>
+ <version>2.8-SNAPSHOT</version>
+ <name>Sonar :: Samples :: PMD extensions</name>
+ <description>PMD extensions for Sonar</description>
+
+ <properties>
+ <!-- To be replaced with the minimum required version of Sonar -->
+ <sonar.buildVersion>${project.version}</sonar.buildVersion>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.codehaus.sonar</groupId>
+ <artifactId>sonar-plugin-api</artifactId>
+ <version>${sonar.buildVersion}</version>
+ </dependency>
+ <dependency>
+ <groupId>pmd</groupId>
+ <artifactId>pmd</artifactId>
+ <version>4.2.5</version>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.sonar</groupId>
+ <artifactId>sonar-packaging-maven-plugin</artifactId>
+ <version>1.1</version>
+ <extensions>true</extensions>
+ <configuration>
+ <pluginClass>com.mycompany.sonar.pmd.PmdExtensionsPlugin</pluginClass>
+
+ <!-- This is important. It means that this plugin extends the PMD plugin -->
+ <basePlugin>pmd</basePlugin>
+ </configuration>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>2.3.2</version>
+ <configuration>
+ <source>1.5</source>
+ <target>1.5</target>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
\ No newline at end of file
--- /dev/null
+package com.mycompany.sonar.pmd;
+
+import java.util.ArrayList;
+import java.util.List;
+import net.sourceforge.pmd.AbstractRule;
+import net.sourceforge.pmd.ast.ASTClassOrInterfaceBody;
+import net.sourceforge.pmd.ast.ASTMethodDeclaration;
+import net.sourceforge.pmd.properties.IntegerProperty;
+
+public class MaximumMethodsCountCheck extends AbstractRule {
+
+ private static final IntegerProperty propertyDescriptor = new IntegerProperty(
+ "maxAuthorisedMethodsCount", "Maximum number of methods authorised", 2, 1.0f);
+
+ public Object visit(ASTClassOrInterfaceBody node, Object data) {
+ List<ASTMethodDeclaration> methods = new ArrayList<ASTMethodDeclaration>();
+ methods = (List<ASTMethodDeclaration>)node.findChildrenOfType(ASTMethodDeclaration.class);
+
+ if (methods.size() > getIntProperty(propertyDescriptor)) {
+ addViolation(data, node);
+ }
+ return super.visit(node,data);
+ }
+
+}
--- /dev/null
+package com.mycompany.sonar.pmd;
+
+import org.apache.commons.io.IOUtils;
+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 class PmdExtensionRepository extends RuleRepository {
+
+ // Must be the same than the PMD plugin
+ private static final String REPOSITORY_KEY = "pmd";
+ private XMLRuleParser ruleParser;
+
+ public PmdExtensionRepository(XMLRuleParser ruleParser) {
+ super(REPOSITORY_KEY, Java.KEY);
+ this.ruleParser = ruleParser;
+ }
+
+ @Override
+ public List<Rule> createRules() {
+ // In this example, new rules are declared in a XML file
+ InputStream input = getClass().getResourceAsStream("/com/mycompany/sonar/pmd/extensions.xml");
+ try {
+ return ruleParser.parse(input);
+
+ } finally {
+ IOUtils.closeQuietly(input);
+ }
+ }
+
+}
--- /dev/null
+package com.mycompany.sonar.pmd;
+
+import org.sonar.api.SonarPlugin;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class PmdExtensionsPlugin extends SonarPlugin {
+
+ public List getExtensions() {
+ return Arrays.asList(PmdExtensionRepository.class);
+ }
+
+}
--- /dev/null
+<rules>
+ <!-- Extension written in Java -->
+ <rule>
+ <key>MaximumMethodsCountCheck</key>
+ <name>Maximum Methods Count Check</name>
+ <description>Maximum number of methods authorised</description>
+
+ <!-- path to definition -->
+ <configKey>com/mycompany/sonar/pmd/rulesets.xml/MaximumMethodsCountCheck</configKey>
+
+ <!-- Default priority ("severity"). It can be changed while activating the rule in Quality profile -->
+ <!-- Possible values are: INFO, MINOR, MAJOR, CRITICAL, BLOCKER. Default value is MAJOR -->
+ <!--<priority>MAJOR</priority>-->
+
+ <!-- parameters available in administration console of Quality profiles -->
+ <param>
+ <key>maxAuthorisedMethodsCount</key>
+ <description>Maximum number of methods authorised</description>
+
+ <!-- default value is optional -->
+ <defaultValue>2</defaultValue>
+ </param>
+ </rule>
+
+
+ <!-- Extension written in XPath, first solution -->
+ <rule>
+ <key>AvoidIfWithoutBrace</key>
+ <name>Avoid if without using brace</name>
+ <configKey>com/mycompany/sonar/pmd/rulesets.xml/AvoidIfWithoutBrace</configKey>
+ <priority>CRITICAL</priority>
+ </rule>
+
+
+ <!--
+ Extension written in XPath, second solution.
+ Difference is that the XPath expression can be configured by users from administration console of Quality profiles
+ -->
+ <rule>
+ <key>PreventUseOfEmptyClass</key>
+ <priority>MAJOR</priority>
+ <name><![CDATA[Prevent use of EmptyClass]]></name>
+ <configKey><![CDATA[net.sourceforge.pmd.rules.XPathRule]]></configKey>
+ <priority>MINOR</priority>
+ <param>
+ <key>xpath</key>
+ <description><![CDATA[XPath expressions.]]></description>
+ <defaultValue>//VariableDeclarator[../Type/ReferenceType/ClassOrInterfaceType[@Image='EmptyClass']]</defaultValue>
+ </param>
+ <param>
+ <key>message</key>
+ <description><![CDATA[Message to display when a violation occurs.]]></description>
+ <defaultValue>Prevent use of EmptyClass class</defaultValue>
+ </param>
+ </rule>
+</rules>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0"?>
+<ruleset name="PMD extensions"
+ xmlns="http://pmd.sf.net/ruleset/1.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://pmd.sf.net/ruleset/1.0.0 http://pmd.sf.net/ruleset_xml_schema.xsd"
+ xsi:noNamespaceSchemaLocation="http://pmd.sf.net/ruleset_xml_schema.xsd">
+
+ <rule name="MaximumMethodsCountCheck"
+ message="Avoid too many methods"
+ class="com.mycompany.sonar.pmd.MaximumMethodsCountCheck">
+ <description>
+ Avoid too many methods
+ </description>
+ <priority>3</priority>
+ <properties>
+ <property name="maxAuthorisedMethodsCount" description="Maximum number of methods authorised" value="3"/>
+ </properties>
+ <example>
+ <![CDATA[
+ // too many methods!
+ public void doSomething() {}
+ public void doSomething2() {}
+ public void doSomething3() {}
+ public void doSomething4() {}
+
+ ]]>
+ </example>
+ </rule>
+
+ <rule name="AvoidIfWithoutBrace"
+ message="Avoid if without using brace"
+ class="net.sourceforge.pmd.rules.XPathRule">
+ <description>
+ Avoid if without using brace
+ </description>
+ <properties>
+ <property name="xpath">
+ <value>
+ <![CDATA[
+ //IfStatement[not(Statement/Block)]
+ ]]>
+ </value>
+ </property>
+ </properties>
+ <example>
+ <![CDATA[
+ // don't do this!
+ if (true)
+ test = "test";
+ ]]>
+ </example>
+ </rule>
+</ruleset>
\ No newline at end of file
<module>standard-plugin</module>
<module>gwt-plugin</module>
<module>checkstyle-extensions-plugin</module>
+ <module>pmd-extensions-plugin</module>
</modules>
<build>