Merge branch 'master' into close-resource-io
This commit is contained in:
@ -398,6 +398,46 @@ public class Foo {
|
||||
</example>
|
||||
</rule>
|
||||
|
||||
<rule name="DoubleBraceInitialization"
|
||||
language="java"
|
||||
since="6.16.0"
|
||||
message="Double-brace initialization should be avoided"
|
||||
class="net.sourceforge.pmd.lang.rule.XPathRule"
|
||||
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_bestpractices.html#doublebraceinitialization">
|
||||
<description>
|
||||
Double brace initialisation is a pattern to initialise eg collections concisely. But it implicitly
|
||||
generates a new .class file, and the object holds a strong reference to the enclosing object. For those
|
||||
reasons, it is preferable to initialize the object normally, even though it's verbose.
|
||||
|
||||
This rule counts any anonymous class which only has a single initializer as an instance of double-brace
|
||||
initialization. There is currently no way to find out whether a method called in the initializer is not
|
||||
accessible from outside the anonymous class, and those legit cases should be suppressed for the time being.
|
||||
</description>
|
||||
<priority>3</priority>
|
||||
<properties>
|
||||
<property name="version" value="2.0"/>
|
||||
<property name="xpath">
|
||||
<value>
|
||||
<![CDATA[
|
||||
//AllocationExpression/ClassOrInterfaceBody[count(*)=1]/*/Initializer[@Static=false()]
|
||||
]]>
|
||||
</value>
|
||||
</property>
|
||||
</properties>
|
||||
<example>
|
||||
<![CDATA[
|
||||
// this is double-brace initialization
|
||||
return new ArrayList<String>(){{addAll("a","b","c");}};
|
||||
|
||||
// the better way is to not create an anonymous class:
|
||||
List<String> a=new ArrayList<>();
|
||||
a.addAll("a","b","c");
|
||||
return a;
|
||||
]]>
|
||||
</example>
|
||||
</rule>
|
||||
|
||||
|
||||
<rule name="ForLoopCanBeForeach"
|
||||
language="java"
|
||||
since="6.0.0"
|
||||
|
@ -2526,10 +2526,11 @@ confusing.
|
||||
</description>
|
||||
<priority>3</priority>
|
||||
<properties>
|
||||
<property name="version" value="2.0" />
|
||||
<property name="xpath">
|
||||
<value>
|
||||
<![CDATA[
|
||||
//Initializer[@Static='false']
|
||||
//Initializer[@Static=false()][not(ancestor::*[3][self::AllocationExpression or self::EnumConstant])]
|
||||
]]>
|
||||
</value>
|
||||
</property>
|
||||
|
@ -17,6 +17,7 @@
|
||||
<rule ref="category/java/bestpractices.xml/CheckResultSet"/>
|
||||
<rule ref="category/java/bestpractices.xml/ConstantsInInterface"/>
|
||||
<rule ref="category/java/bestpractices.xml/DefaultLabelNotLastInSwitchStmt"/>
|
||||
<rule ref="category/java/bestpractices.xml/DoubleBraceInitialization"/>
|
||||
<rule ref="category/java/bestpractices.xml/ForLoopCanBeForeach"/>
|
||||
<!-- <rule ref="category/java/bestpractices.xml/ForLoopVariableCount" /> -->
|
||||
<rule ref="category/java/bestpractices.xml/GuardLogStatement"/>
|
||||
|
@ -0,0 +1,11 @@
|
||||
/*
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
package net.sourceforge.pmd.lang.java.rule.bestpractices;
|
||||
|
||||
import net.sourceforge.pmd.testframework.PmdRuleTst;
|
||||
|
||||
public class DoubleBraceInitializationTest extends PmdRuleTst {
|
||||
// no additional unit tests
|
||||
}
|
@ -0,0 +1,97 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<test-data xmlns="http://pmd.sourceforge.net/rule-tests"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://pmd.sourceforge.net/rule-tests http://pmd.sourceforge.net/rule-tests_1_0_0.xsd">
|
||||
<test-code>
|
||||
<description>Pos in return</description>
|
||||
<expected-problems>1</expected-problems>
|
||||
<expected-linenumbers>4</expected-linenumbers>
|
||||
<code><![CDATA[
|
||||
class Foo {
|
||||
|
||||
List<String> bar() {
|
||||
return new ArrayList<String>(){{addAll("a","b","c");}};
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
]]></code>
|
||||
</test-code>
|
||||
|
||||
<test-code>
|
||||
<description>Neg, override</description>
|
||||
<expected-problems>0</expected-problems>
|
||||
<code><![CDATA[
|
||||
class Foo {
|
||||
|
||||
List<String> bar() {
|
||||
return new ArrayList<String>(){
|
||||
|
||||
{addAll("a","b","c");}
|
||||
|
||||
void add(String x) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
]]></code>
|
||||
</test-code>
|
||||
|
||||
<test-code>
|
||||
<description>Neg, new field</description>
|
||||
<expected-problems>0</expected-problems>
|
||||
<code><![CDATA[
|
||||
class Foo {
|
||||
|
||||
List<String> bar() {
|
||||
return new ArrayList<String>(){
|
||||
|
||||
{addAll("a","b","c");}
|
||||
|
||||
int field;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
]]></code>
|
||||
</test-code>
|
||||
|
||||
<test-code>
|
||||
<description>Neg, enum constant</description>
|
||||
<expected-problems>0</expected-problems>
|
||||
<code><![CDATA[
|
||||
enum Foo {
|
||||
|
||||
A {
|
||||
// neg in enum cons
|
||||
{addAll("a","b","c");}
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
]]></code>
|
||||
</test-code>
|
||||
|
||||
<test-code>
|
||||
<description>Neg, regular class</description>
|
||||
<expected-problems>0</expected-problems>
|
||||
<code><![CDATA[
|
||||
class Foo {
|
||||
|
||||
// neg in regular class
|
||||
{addAll("a","b","c");}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
]]></code>
|
||||
</test-code>
|
||||
|
||||
</test-data>
|
@ -1,28 +1,101 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<test-data
|
||||
xmlns="http://pmd.sourceforge.net/rule-tests"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://pmd.sourceforge.net/rule-tests http://pmd.sourceforge.net/rule-tests_1_0_0.xsd">
|
||||
<test-data xmlns="http://pmd.sourceforge.net/rule-tests"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://pmd.sourceforge.net/rule-tests http://pmd.sourceforge.net/rule-tests_1_0_0.xsd">
|
||||
<test-code>
|
||||
<description><![CDATA[
|
||||
bad
|
||||
]]></description>
|
||||
<description>bad</description>
|
||||
<expected-problems>1</expected-problems>
|
||||
<code><![CDATA[
|
||||
public class Foo {
|
||||
{}
|
||||
}
|
||||
]]></code>
|
||||
]]></code>
|
||||
</test-code>
|
||||
|
||||
<test-code>
|
||||
<description><![CDATA[
|
||||
static initializers are OK
|
||||
]]></description>
|
||||
<description>static initializers are OK</description>
|
||||
<expected-problems>0</expected-problems>
|
||||
<code><![CDATA[
|
||||
public class Foo {
|
||||
static {}
|
||||
}
|
||||
]]></code>
|
||||
]]></code>
|
||||
</test-code>
|
||||
|
||||
<test-code>
|
||||
<description>Allowed in anonymous classes</description>
|
||||
<expected-problems>0</expected-problems>
|
||||
<code><![CDATA[
|
||||
public class Foo {
|
||||
public Animation getStatusTransition() {
|
||||
return new Transition() {
|
||||
|
||||
{
|
||||
setCycleDuration(Duration.millis(1200));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void interpolate(double frac) {
|
||||
// magic
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
]]></code>
|
||||
</test-code>
|
||||
|
||||
<test-code>
|
||||
<description>Flag in local class</description>
|
||||
<expected-problems>1</expected-problems>
|
||||
<expected-linenumbers>3</expected-linenumbers>
|
||||
<code><![CDATA[
|
||||
public class Foo {
|
||||
static {
|
||||
class Local {{}}
|
||||
}
|
||||
}
|
||||
]]></code>
|
||||
</test-code>
|
||||
|
||||
<test-code>
|
||||
<description>Allowed in enum constant</description>
|
||||
<expected-problems>1</expected-problems>
|
||||
<expected-linenumbers>7</expected-linenumbers>
|
||||
<code><![CDATA[
|
||||
public enum Foo {
|
||||
A {
|
||||
{ setCycleDuration(Duration.millis(1200)); }
|
||||
};
|
||||
|
||||
|
||||
{ setCycleDuration(Duration.millis(1200)); }
|
||||
|
||||
}
|
||||
]]></code>
|
||||
</test-code>
|
||||
|
||||
<test-code>
|
||||
<description>Flag in nested local class</description>
|
||||
<expected-problems>1</expected-problems>
|
||||
<expected-linenumbers>7</expected-linenumbers>
|
||||
<code><![CDATA[
|
||||
public class Foo {
|
||||
public Animation getStatusTransition() {
|
||||
return new Transition() {
|
||||
|
||||
{
|
||||
setCycleDuration(Duration.millis(1200));
|
||||
class ImInAnon {{}} // should be flagged
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void interpolate(double frac) {
|
||||
// magic
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
]]></code>
|
||||
</test-code>
|
||||
|
||||
</test-data>
|
||||
|
Reference in New Issue
Block a user