pmd/rules.xml (343 lines of code) (raw):
<?xml version="1.0"?>
<ruleset name="buck"
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">
<description>Rules for the Buck project.</description>
<!--
Visit https://github.com/pmd/pmd/tree/master/pmd-java/src/main/resources/rulesets/java
for ruleset definitions. Note that Buck is currently built with PMD 5.0.3.
-->
<rule ref="rulesets/java/basic.xml">
<exclude name="CollapsibleIfStatements" />
</rule>
<rule ref="rulesets/java/empty.xml">
<exclude name="EmptyCatchBlock" />
<exclude name="EmptyWhileStmt" />
</rule>
<rule ref="rulesets/java/imports.xml">
<!--
Excluded because tests that use both JUnit and EasyMock tend to
statically import many methods, which we allow.
-->
<exclude name="TooManyStaticImports" />
<!--
google-java-format covers this one; we don't need two messages.
-->
<exclude name="UnusedImports" />
</rule>
<rule ref="rulesets/java/coupling.xml/LooseCoupling" />
<rule ref="rulesets/java/junit.xml">
<!-- This is not practical. -->
<exclude name="JUnitAssertionsShouldIncludeMessage" />
<!-- Unclear what an appropriate upper bound would be. -->
<exclude name="JUnitTestContainsTooManyAsserts" />
<!--
Not practical: pure EasyMock tests or tests that exclusively assert
using MoreAsserts.* should not need to be annotated with this.
-->
<exclude name="JUnitTestsShouldIncludeAssert" />
</rule>
<rule ref="rulesets/java/unusedcode.xml">
<!-- This rule is buggy (http://sourceforge.net/p/pmd/bugs/792/ and others). -->
<exclude name="UnusedPrivateField" />
<exclude name="UnusedPrivateMethod" />
</rule>
<rule ref="rulesets/java/optimizations.xml">
<exclude name="AvoidInstantiatingObjectsInLoops" />
<exclude name="LocalVariableCouldBeFinal" />
<exclude name="MethodArgumentCouldBeFinal" />
<exclude name="RedundantFieldInitializer" />
<exclude name="UseStringBufferForStringAppends" />
<exclude name="SimplifyStartsWith" />
<exclude name="PrematureDeclaration" />
</rule>
<rule name="RuleArgMustBePackagePrivate"
message="@RuleArg value types must be package-private"
class="net.sourceforge.pmd.lang.rule.XPathRule"
language="java">
<description>Value types decorated with @RuleArg must be package-private (i.e., not public or private).
The build will automatically generate a public subclass or implementation of your value type. All clients should use that API, so the parent value type should limit its visibility as much as possible.</description>
<priority>1</priority>
<properties>
<property name="xpath">
<value>
<![CDATA[
//ClassOrInterfaceDeclaration[@PackagePrivate='false']
[ancestor::*/Annotation/MarkerAnnotation/Name
[@Image='RuleArg']]
]]>
</value>
</property>
</properties>
<example>
<![CDATA[
// OK
@RuleArg
interface AbstractFoo {
}
// Bad: uses public visibility
@RuleArg
public class AbstractBar {
}
// Bad: uses public visibility
@RuleArg
public interface AbstractBaz {
}
]]>
</example>
</rule>
<rule name="BuckImmutablesMustNotHaveValueImmutableAnnotation"
message="
Value types decorated with @RuleArg or @ImmutableInfo should not use @Value.Immutable
in any way"
class="net.sourceforge.pmd.lang.rule.XPathRule"
language="java">
<description> Using @Value.Immutable is forbidden when using @RuleArg or @ImmutableInfo.</description>
<priority>1</priority>
<properties>
<property name="xpath">
<value>
<![CDATA[
//Annotation[
following-sibling::ClassOrInterfaceDeclaration[
preceding-sibling::Annotation//Name
[@Image='ImmutableInfo' or @Image='RuleArg']
]
]/*[
Name/@Image='Value.Immutable'
]
]]>
</value>
</property>
</properties>
<example>
<![CDATA[
// OK: No @Value.Immutable
@RuleArg
abstract class AbstractOk1 {
}
// OK: No @Value.Immutable
@ImmutableInfo
abstract class Ok2 {
}
// Bad: using @Value.Immutable
@Value.Immutable
@RuleArg
abstract class AbstractBad1 {
}
// Bad: using @Value.Immutable
@Value.Immutable
@ImmutableInfo
abstract class Bad2 {
}
]]>
</example>
</rule>
<rule name="RuleArgNameMustStartWithAbstract"
message="Name of @RuleArg value types must start with Abstract"
class="net.sourceforge.pmd.lang.rule.XPathRule"
language="java">
<description>Value types decorated with @RuleArg must have a name starting with 'Abstract'
The build will automatically generate a subclass or implementation of your value type without 'Abstract' in the name.</description>
<priority>1</priority>
<properties>
<property name="xpath">
<value>
<![CDATA[
//ClassOrInterfaceDeclaration[not(starts-with(@Image,'Abstract'))]
[ancestor::*/Annotation/MarkerAnnotation/Name
[@Image='RuleArg']]
]]>
</value>
</property>
</properties>
<example>
<![CDATA[
// OK
@RuleArg
interface AbstractFoo {
}
// Bad: name does not start with Abstract
@RuleArg
interface Bar {
}
]]>
</example>
</rule>
<rule name="BuckStyleImmutablesMustNotHaveDefaultsImplicitlyOverridden"
message="
Value types decorated with @BuckStyleValue variants must specify all of 'builder', 'copy', 'prehash'
and 'intern' when overriding defaults"
class="net.sourceforge.pmd.lang.rule.XPathRule"
language="java">
<description>Using @Value.Immutable with @BuckStyleValue variants must specify all of 'builder',
'copy', 'prehash' and 'intern' when overriding defaults</description>
<priority>1</priority>
<properties>
<property name="xpath">
<value>
<![CDATA[
//Annotation[
following-sibling::ClassOrInterfaceDeclaration[
preceding-sibling::Annotation//Name
[@Image='BuckStyleValue' or @Image='BuckStylePrehashedValue' or @Image='BuckStyleValueWithBuilder']
]
]/*[
Name/@Image='Value.Immutable'
and (not(MemberValuePairs/MemberValuePair/@Image="builder")
or not(MemberValuePairs/MemberValuePair/@Image="copy")
or not(MemberValuePairs/MemberValuePair/@Image="prehash")
or not(MemberValuePairs/MemberValuePair/@Image="intern"))
]
]]>
</value>
</property>
</properties>
<example>
<![CDATA[
// OK: No @Value.Immutable
@BuckStyleValue
abstract class Ok1 {
}
// OK: all overriden
@BuckStylePrehashedValue
@Value.Immutable(builder = false, copy = false, prehash = true, intern = true)
abstract class Ok2 {
}
// OK: No @Value.Immutable
@BuckStyleValueWithBuilder
abstract class Ok3 {
}
// Bad: using @Value.Immutable
@Value.Immutable
@BuckStyleValue
abstract class Bad1 {
}
// Bad: using @Value.Immutable
@Value.Immutable
@BuckStylePrehashedValue
abstract class Bad2 {
}
// Bad: using @Value.Immutable partially overriden
@Value.Immutable(intern = true)
@BuckStyleValueWithBuilder
abstract class Bad3 {
}
]]>
</example>
</rule>
<rule name="NoRawUseofValueImmutable"
message="Direct use of @Value.Immutable without being adjacent to a @BuckStyleValue variant is forbidden"
class="net.sourceforge.pmd.lang.rule.XPathRule"
language="java">
<description>Use of @Value.Immutable without overriding defaults 'builder', 'copy',
and 'intern' is forbidden. Either use one of existing BuckStyleValues, or override
these defaults.</description>
<priority>1</priority>
<properties>
<property name="xpath">
<value>
<![CDATA[
//Annotation[
following-sibling::ClassOrInterfaceDeclaration[
not (preceding-sibling::Annotation//Name
[@Image='BuckStyleValue' or @Image='BuckStylePrehashedValue' or @Image='BuckStyleValueWithBuilder'])
]
]/*[
Name/@Image='Value.Immutable'
]
]]>
</value>
</property>
</properties>
<example>
<![CDATA[
// OK
@Value.Immutable(builder = false, copy = false, prehash = true, intern = true)
@BuckStyleValue
interface Foo {
}
// Bad: does not belong beside buck style immutables
@Value.Immutable(copy=false, builder=false, prehash=true)
interface Bar {
}
]]>
</example>
</rule>
<!-- Blacklist docs: http://liveramp.com/engineering/using-pmd-to-blacklist-unsafe-methods/ -->
<rule name="BlacklistedDefaultCharsetMethods"
message="These APIs implicitly use the system default Charset. Use explicit ones instead."
class="com.liveramp.pmd_extensions.BlacklistMethods">
<description>
We blacklist (disallow) use of APIs which implicitly use the system default Charset.
Instead, use APIs which explicitly take a Charset argument.
</description>
<priority>1</priority>
<properties>
<!-- The syntax here is a comma-separated list of pairs in the format:
package.Class:method:num-args;suggested-alternative
...
-->
<property name="BlacklistMethods.BlacklistedMethods" value="
java.lang.String:getBytes:0;String.getBytes(Charset)
"/>
</properties>
</rule>
<rule name="BlacklistedDefaultProcessMethod"
message="All subprocess creation should go through BgProcessKiller."
class="com.liveramp.pmd_extensions.BlacklistMethods">
<description>
We use a process-group-wide signal to kill all our subprocesses
on demand; we need to synchronize this kill operation with
process creation to ensure that no process gets created with
SIG_IGN for SIGHUP.
</description>
<priority>1</priority>
<properties>
<!-- The syntax here is a comma-separated list of pairs in the format:
package.Class:method:num-args;suggested-alternative
...
-->
<property name="BlacklistMethods.BlacklistedMethods" value="
java.lang.ProcessBuilder:start:0;BgProcessKiller.startProcess(ProcessBuilder),com.zaxxer.nuprocess.NuProcessBuilder:start:0;BgProcessKiller.startProcess(NuProcessBuilder)
"/>
</properties>
</rule>
<rule name="BlacklistedJavaUtilLoggerUsage"
message="Use com.facebook.buck.core.util.log.Logger instead of java.util.logging.Logger"
class="com.liveramp.pmd_extensions.BlacklistClassUsages">
<description>
Buck uses a custom Logger which does custom formatting and maybe other things.
java.util.logging.Logger bypasses this.
</description>
<priority>1</priority>
<properties>
<property name="BlacklistClassUsages.BlacklistedClasses" value="java.util.logging.Logger" />
</properties>
<example>
<![CDATA[
// OK
import com.facebook.buck.log.Logger;
private static final Logger LOG = Logger.getLogger(Main.class);
// Bad
import java.util.logging.Logger;
private static final Logger LOG = Logger.getLogger(Main.class.getName());
]]>
</example>
</rule>
<rule name="BlacklistedPrintWriterUsage"
message="Use com.facebook.buck.util.ThrowingPrintWriter instead of java.io.PrintWriter"
class="com.liveramp.pmd_extensions.BlacklistClassUsages">
<description>
java.io.PrintWriter eats IOExceptions. Using it when writing build artifacts and metadata risks
generation of corrupted artifacts when I/O operations fail (such as in low-disk-space situations).
</description>
<priority>1</priority>
<properties>
<property name="BlacklistClassUsages.BlacklistedClasses" value="java.io.PrintWriter" />
<property name="violationSuppressRegex" value=".*/buck/test/.*" />
</properties>
</rule>
<rule name="SimplifyStringReplace"
message="[perf] Use String.replace(char, char) for one-character replacements"
class="net.sourceforge.pmd.lang.rule.XPathRule"
language="java">
<description>Use String.replace('\\', '/') instead of String.replace("\\", "/")
String#replace(char, char) is extremely efficient.
String#replace(String, String) has to compile and execute a regular expression.
Always prefer the former when doing single-character replacements.
</description>
<priority>1</priority>
<properties>
<property name="xpath">
<value>
<!--
Match calls to str.replace("x", "y") or str.replace("\n", "\r")
but not str.replace("foo", "bar")
-->
<![CDATA[
(//PrimaryPrefix/Name[ends-with(@Image, '.replace')]/../..|
//PrimarySuffix[ends-with(@Image, 'replace')]/..)
/PrimarySuffix/Arguments/ArgumentList
[Expression[1]/PrimaryExpression/PrimaryPrefix/Literal[@SingleCharacterStringLiteral='true']]
[Expression[2]/PrimaryExpression/PrimaryPrefix/Literal[@SingleCharacterStringLiteral='true']]
]]>
</value>
</property>
</properties>
<example>
<![CDATA[
// OK
class Foo {
public void bar(String s) {
return s.replace('\r', '\n');
}
}
// Bad: using expensive regular expressions to replace single characters
class Foo {
public void bar(String s) {
return s.replace("\r", "\n");
}
}
]]>
</example>
</rule>
<rule name="BlacklistedSystemGetenv"
message="Use com.facebook.buck.util.environment.EnvVariablesProvider instead of System.getenv()"
class="com.liveramp.pmd_extensions.BlacklistMethods">
<description>
System.getenv() returns environment variables with names that may be case-insensitive on some
OSes (for example, Windows). EnvVariablesProvider.getSystemEnv() returns unified variables
with names converted to upper cases.
</description>
<priority>1</priority>
<properties>
<property name="BlacklistMethods.BlacklistedMethods" value="System:getenv:0;com.facebook.buck.util.environment.EnvVariablesProvider:getSystemEnv"/>
</properties>
</rule>
</ruleset>