Merge branch 'master' into junit-rule-pmd-test-runner
This commit is contained in:
+408
File diff suppressed because it is too large
Load Diff
@@ -681,7 +681,7 @@ More exceptions can be defined with the property "ignoreMagicNumbers".
|
||||
//IfStatement/Expression/*/PrimaryExpression/PrimaryPrefix/Literal
|
||||
[not(NullLiteral)]
|
||||
[not(BooleanLiteral)]
|
||||
[empty(index-of(tokenize($ignoreMagicNumbers, ','), @Image))]
|
||||
[empty(index-of(tokenize($ignoreMagicNumbers, '\s*,\s*'), @Image))]
|
||||
]]>
|
||||
</value>
|
||||
</property>
|
||||
|
||||
@@ -477,4 +477,34 @@ public class MyTest {
|
||||
</example>
|
||||
</rule>
|
||||
|
||||
</ruleset>
|
||||
<rule name="ForLoopCanBeForeach"
|
||||
language="java"
|
||||
since="6.0"
|
||||
message="This 'for' loop can be replaced by a 'foreach' loop"
|
||||
typeResolution="true"
|
||||
minimumLanguageVersion="1.5"
|
||||
class="net.sourceforge.pmd.lang.java.rule.migrating.ForLoopCanBeForeachRule"
|
||||
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_migrating.html#forloopcanbeforeach">
|
||||
<description><![CDATA[
|
||||
Reports loops that can be safely replaced with the foreach syntax. The rule considers loops over
|
||||
lists, arrays and iterators. A loop is safe to replace if it only uses the index variable to
|
||||
access an element of the list or array, only has one update statement, and loops through *every*
|
||||
element of the list or array left to right.
|
||||
]]></description>
|
||||
<priority>3</priority>
|
||||
<example><![CDATA[
|
||||
public class MyClass {
|
||||
void loop(List<String> l) {
|
||||
for (int i = 0; i < l.size(); i++) { // pre Java 1.5
|
||||
System.out.println(l.get(i));
|
||||
}
|
||||
|
||||
for (String s : l) { // post Java 1.5
|
||||
System.out.println(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
]]></example>
|
||||
</rule>
|
||||
|
||||
</ruleset>
|
||||
|
||||
+1
@@ -15,6 +15,7 @@ public class MigratingRulesTest extends SimpleAggregatorTst {
|
||||
addRule(RULESET, "AvoidAssertAsIdentifier");
|
||||
addRule(RULESET, "AvoidEnumAsIdentifier");
|
||||
addRule(RULESET, "ByteInstantiation");
|
||||
addRule(RULESET, "ForLoopCanBeForeach");
|
||||
addRule(RULESET, "IntegerInstantiation");
|
||||
addRule(RULESET, "JUnit4SuitesShouldUseSuiteAnnotation");
|
||||
addRule(RULESET, "JUnit4TestShouldUseAfterAnnotation");
|
||||
|
||||
+15
@@ -77,4 +77,19 @@ public class Foo {
|
||||
}
|
||||
]]></code>
|
||||
</test-code>
|
||||
<test-code>
|
||||
<description>#388 False positive due to space in property list</description>
|
||||
<expected-problems>0</expected-problems>
|
||||
<rule-property name="ignoreMagicNumbers"><![CDATA[-1,0,1, 0.0]]></rule-property>
|
||||
<code><![CDATA[
|
||||
class Foo {
|
||||
void bar() {
|
||||
if (num == 0.0) {
|
||||
return MathExtItg.sgn0raw(num) == 1 ? IEEEclass.PositiveZero : IEEEclass.NegativeZero;
|
||||
}
|
||||
}
|
||||
}
|
||||
]]></code>
|
||||
</test-code>
|
||||
|
||||
</test-data>
|
||||
|
||||
+267
@@ -0,0 +1,267 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<test-data>
|
||||
|
||||
|
||||
<test-code>
|
||||
<description>Positive with list</description>
|
||||
<expected-problems>1</expected-problems>
|
||||
<code><![CDATA[
|
||||
public class MyClass {
|
||||
void loop(List<String> l) {
|
||||
for (int i = 0; i < l.size(); i++) {
|
||||
System.out.println(l.get(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
]]></code>
|
||||
</test-code>
|
||||
|
||||
<test-code>
|
||||
<description>Positive with lower or equal</description>
|
||||
<expected-problems>1</expected-problems>
|
||||
<code><![CDATA[
|
||||
public class Foo {
|
||||
void loop(List<String> lo) {
|
||||
for (int i = 0; i <= lo.size() - 1; i++) {
|
||||
System.out.println(lo.get(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
]]></code>
|
||||
</test-code>
|
||||
|
||||
<test-code>
|
||||
<description>Usage of index var outside get</description>
|
||||
<expected-problems>0</expected-problems>
|
||||
<code><![CDATA[
|
||||
public class MyClass {
|
||||
void loop(List<String> l) {
|
||||
for (int i = 0; i < l.size(); i++) {
|
||||
System.out.println(i + ": " + l.get(i));
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
]]></code>
|
||||
</test-code>
|
||||
|
||||
<test-code>
|
||||
<description>Subclass of List</description>
|
||||
<expected-problems>1</expected-problems>
|
||||
<code><![CDATA[
|
||||
public class MyClass {
|
||||
void loop(ArrayList<String> l) {
|
||||
for (int i = 0; i < l.size(); i++) {
|
||||
System.out.println(l.get(i));
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
]]></code>
|
||||
</test-code>
|
||||
|
||||
<test-code>
|
||||
<description>Get called on another list</description>
|
||||
<expected-problems>0</expected-problems>
|
||||
<code><![CDATA[
|
||||
public class MyClass {
|
||||
void loop(List<String> l) {
|
||||
List<String> l2 = new ArrayList<>(l);
|
||||
for (int i = 0; i < l.size(); i++) {
|
||||
System.out.println(l2.get(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
]]></code>
|
||||
</test-code>
|
||||
|
||||
<test-code>
|
||||
<description>Backwards iteration</description>
|
||||
<expected-problems>0</expected-problems>
|
||||
<code><![CDATA[
|
||||
public class MyClass {
|
||||
void loop(List<String> l) {
|
||||
for (int i = l.size() - 1; i > 0; i-= 1) {
|
||||
System.out.println(i + ": " + l.get(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
]]></code>
|
||||
</test-code>
|
||||
|
||||
|
||||
<test-code>
|
||||
<description>Index var initialized outside for init</description>
|
||||
<expected-problems>1</expected-problems>
|
||||
<code><![CDATA[
|
||||
public class MyClass {
|
||||
void loop(List<String> l) {
|
||||
int i = 0;
|
||||
for (; i < l.size(); i++) {
|
||||
System.out.println(l.get(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
]]></code>
|
||||
</test-code>
|
||||
|
||||
|
||||
<test-code>
|
||||
<description>Array positives</description>
|
||||
<expected-problems>2</expected-problems>
|
||||
<code><![CDATA[
|
||||
class Foo {
|
||||
protected static final char[] filter(char[] chars, char removeChar) {
|
||||
int count = 0;
|
||||
for (int i = 0; i < chars.length; i++) {
|
||||
if (chars[i] == removeChar) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
char[] results = new char[chars.length - count];
|
||||
|
||||
int index = 0;
|
||||
for (int i = 0; i < chars.length; i++) {
|
||||
if (chars[i] != removeChar) {
|
||||
results[index++] = chars[i];
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
}
|
||||
]]></code>
|
||||
</test-code>
|
||||
|
||||
<test-code>
|
||||
<description>Consider iterators</description>
|
||||
<expected-problems>1</expected-problems>
|
||||
<code><![CDATA[
|
||||
class Foo {
|
||||
void loop() {
|
||||
Iterable<DataFlowNode> path = null;
|
||||
for (Iterator<DataFlowNode> i = path.iterator(); i.hasNext();) {
|
||||
DataFlowNode inode = i.next();
|
||||
if (inode.getVariableAccess() == null) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]]></code>
|
||||
</test-code>
|
||||
|
||||
|
||||
<test-code>
|
||||
<description>Index var starts after zero</description>
|
||||
<expected-problems>0</expected-problems>
|
||||
<code><![CDATA[
|
||||
public class MyClass {
|
||||
void loop(List<String> l) {
|
||||
for (int i = 1; i < filters.size(); i++) {
|
||||
builder.append(' ').append(getOperator()).append(' ');
|
||||
builder.append(filters.get(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
]]></code>
|
||||
</test-code>
|
||||
|
||||
|
||||
<test-code>
|
||||
<description>Prefix increment should work</description>
|
||||
<expected-problems>1</expected-problems>
|
||||
<code><![CDATA[
|
||||
class AbstractApexNode {
|
||||
Node[] children;
|
||||
|
||||
public Object childrenAccept(ApexParserVisitor visitor, Object data) {
|
||||
if (children != null) {
|
||||
for (int i = 0; i < children.length; ++i) {
|
||||
@SuppressWarnings("unchecked")
|
||||
// we know that the children here are all ApexNodes
|
||||
ApexNode<T> apexNode = (ApexNode<T>) children[i];
|
||||
apexNode.jjtAccept(visitor, data);
|
||||
}
|
||||
}
|
||||
return data;
|
||||
}
|
||||
}
|
||||
]]></code>
|
||||
</test-code>
|
||||
|
||||
<test-code>
|
||||
<description>Index inside arithmetic expression should whitelist the loop</description>
|
||||
<expected-problems>0</expected-problems>
|
||||
<code><![CDATA[
|
||||
class BenchMarker {
|
||||
private static String findOptionalStringValue(String[] args, String name, String defaultValue) {
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
if (args[i].equals(name)) {
|
||||
return args[i + 1];
|
||||
}
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
]]></code>
|
||||
</test-code>
|
||||
|
||||
|
||||
<test-code>
|
||||
<description>Array assignment whitelists the loop</description>
|
||||
<expected-problems>0</expected-problems>
|
||||
<code><![CDATA[
|
||||
class StringPropertyTest {
|
||||
private String newString() {
|
||||
int strLength = randomInt(1, MAX_STRING_LENGTH);
|
||||
|
||||
char[] chars = new char[strLength];
|
||||
for (int i = 0; i < chars.length; i++) {
|
||||
chars[i] = randomCharIn(CHARSET);
|
||||
}
|
||||
return new String(chars);
|
||||
}
|
||||
}
|
||||
]]></code>
|
||||
</test-code>
|
||||
|
||||
<test-code>
|
||||
<description>Consider iterators only if safe</description>
|
||||
<expected-problems>0</expected-problems>
|
||||
<code><![CDATA[
|
||||
class Foo {
|
||||
void loop() {
|
||||
Iterable<DataFlowNode> path = null;
|
||||
|
||||
for (Iterator<DataFlowNode> i = path.iterator(); i.hasNext();) {
|
||||
DataFlowNode inode = i.next();
|
||||
path.remove(inode); // throws ConcurrentModificationException if it were a foreach
|
||||
if (inode.getVariableAccess() == null) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]]></code>
|
||||
</test-code>
|
||||
|
||||
<test-code>
|
||||
<description>Do not report iterator loop if we can't find iterator decl</description>
|
||||
<expected-problems>0</expected-problems>
|
||||
<code><![CDATA[
|
||||
class Foo {
|
||||
void loop() {
|
||||
for (Iterator<DataFlowNode> i = path.iterator(); i.hasNext();) {
|
||||
DataFlowNode inode = i.next();
|
||||
if (inode.getVariableAccess() == null) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]]></code>
|
||||
</test-code>
|
||||
|
||||
|
||||
</test-data>
|
||||
Reference in New Issue
Block a user