Merge branch 'pr-1905'
This commit is contained in:
@ -4,7 +4,9 @@
|
||||
|
||||
package net.sourceforge.pmd.lang.java.dfa;
|
||||
|
||||
import java.util.AbstractMap.SimpleEntry;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@ -14,10 +16,13 @@ import net.sourceforge.pmd.lang.ast.Node;
|
||||
import net.sourceforge.pmd.lang.dfa.DataFlowNode;
|
||||
import net.sourceforge.pmd.lang.dfa.StartOrEndDataFlowNode;
|
||||
import net.sourceforge.pmd.lang.dfa.VariableAccess;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTAssignmentOperator;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceBodyDeclaration;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTConstructorDeclaration;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTExpression;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTFormalParameter;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTStatementExpression;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTVariableInitializer;
|
||||
import net.sourceforge.pmd.lang.java.ast.JavaNode;
|
||||
import net.sourceforge.pmd.lang.java.ast.JavaParserVisitorAdapter;
|
||||
@ -45,6 +50,8 @@ public class VariableAccessVisitor extends JavaParserVisitorAdapter {
|
||||
}
|
||||
|
||||
private void computeNow(Node node) {
|
||||
|
||||
|
||||
DataFlowNode inode = node.getDataFlowNode();
|
||||
|
||||
List<VariableAccess> undefinitions = markUsages(inode);
|
||||
@ -65,7 +72,6 @@ public class VariableAccessVisitor extends JavaParserVisitorAdapter {
|
||||
for (Map<VariableNameDeclaration, List<NameOccurrence>> declarations : variableDeclarations) {
|
||||
for (Map.Entry<VariableNameDeclaration, List<NameOccurrence>> entry : declarations.entrySet()) {
|
||||
VariableNameDeclaration vnd = entry.getKey();
|
||||
|
||||
if (vnd.getAccessNodeParent() instanceof ASTFormalParameter) {
|
||||
// no definition/undefinition/references for parameters
|
||||
continue;
|
||||
@ -76,8 +82,37 @@ public class VariableAccessVisitor extends JavaParserVisitorAdapter {
|
||||
}
|
||||
undefinitions.add(new VariableAccess(VariableAccess.UNDEFINITION, vnd.getImage()));
|
||||
|
||||
//Map the name occurrences to their assignment expressions, if any
|
||||
List<SimpleEntry<Node, NameOccurrence>> occurrencesWithAssignmentExp = new ArrayList<>();
|
||||
for (NameOccurrence occurrence : entry.getValue()) {
|
||||
addAccess((JavaNameOccurrence) occurrence, inode);
|
||||
// find the nearest assignment, if any
|
||||
Node potentialAssignment = occurrence.getLocation().getFirstParentOfAnyType(ASTStatementExpression.class,
|
||||
ASTExpression.class);
|
||||
while (potentialAssignment != null
|
||||
&& (potentialAssignment.jjtGetNumChildren() < 2
|
||||
|| !(potentialAssignment.jjtGetChild(1) instanceof ASTAssignmentOperator))) {
|
||||
potentialAssignment = potentialAssignment.getFirstParentOfAnyType(ASTStatementExpression.class,
|
||||
ASTExpression.class);
|
||||
}
|
||||
// at this point, potentialAssignment is either a assignment or null
|
||||
occurrencesWithAssignmentExp.add(new SimpleEntry<>(potentialAssignment, occurrence));
|
||||
}
|
||||
|
||||
//The name occurrences are in source code order, the means, the left hand side of
|
||||
//the assignment is first. But this is not the order in which the data flows: first the
|
||||
//right hand side is evaluated before the left hand side is assigned.
|
||||
//Therefore move the name occurrences backwards if they belong to the same assignment expression.
|
||||
for (int i = 0; i < occurrencesWithAssignmentExp.size() - 1; i++) {
|
||||
SimpleEntry<Node, NameOccurrence> oc = occurrencesWithAssignmentExp.get(i);
|
||||
SimpleEntry<Node, NameOccurrence> nextOc = occurrencesWithAssignmentExp.get(i + 1);
|
||||
|
||||
if (oc.getKey() != null && oc.getKey().equals(nextOc.getKey())) {
|
||||
Collections.swap(occurrencesWithAssignmentExp, i, i + 1);
|
||||
}
|
||||
}
|
||||
|
||||
for (SimpleEntry<Node, NameOccurrence> oc : occurrencesWithAssignmentExp) {
|
||||
addAccess((JavaNameOccurrence) oc.getValue(), inode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -132,6 +132,248 @@ public class AssertTest {
|
||||
|
||||
System.out.println(k);
|
||||
}
|
||||
}
|
||||
]]></code>
|
||||
</test-code>
|
||||
|
||||
<test-code>
|
||||
<description>#1905 [java] DataflowAnomalyAnalysis Rule in right order : Case 1. DU-Anomaly(b)</description>
|
||||
<expected-problems>1</expected-problems>
|
||||
<expected-linenumbers>6</expected-linenumbers>
|
||||
<expected-messages>
|
||||
<message>Found 'DU'-anomaly for variable 'b' (lines '6'-'7').</message>
|
||||
</expected-messages>
|
||||
<code><![CDATA[
|
||||
class Test{
|
||||
public static void main(String[] args){
|
||||
int a = 0 ;
|
||||
int b = 0 ;
|
||||
a = a + b ;
|
||||
b = a + b ;
|
||||
}
|
||||
}
|
||||
]]></code>
|
||||
</test-code>
|
||||
|
||||
<test-code>
|
||||
<description>#1905 [java] DataflowAnomalyAnalysis Rule in right order : Case 2. DU-Anomaly(a)</description>
|
||||
<expected-problems>2</expected-problems>
|
||||
<expected-linenumbers>3,5</expected-linenumbers>
|
||||
<expected-messages>
|
||||
<message>Found 'DU'-anomaly for variable 'a' (lines '3'-'7').</message>
|
||||
<message>Found 'DU'-anomaly for variable 'a' (lines '5'-'7').</message>
|
||||
</expected-messages>
|
||||
<code><![CDATA[
|
||||
class Test{
|
||||
public static void main(String[] args){
|
||||
int a = 0 ;
|
||||
for(int i = 0 ; i <= 10; i ++){
|
||||
a = a+3;
|
||||
}
|
||||
}
|
||||
}
|
||||
]]></code>
|
||||
</test-code>
|
||||
|
||||
<test-code regressionTest="false">
|
||||
<description>#1905 [java] DataflowAnomalyAnalysis Rule in right order : Case 3. DU-Anomaly(a)</description>
|
||||
<expected-problems>1</expected-problems>
|
||||
<expected-linenumbers>5</expected-linenumbers>
|
||||
<expected-messages>
|
||||
<message>Found 'DU'-anomaly for variable 'a' (lines '5'-'7').</message>
|
||||
</expected-messages>
|
||||
<code><![CDATA[
|
||||
class Test{
|
||||
public static void main(String[] args){
|
||||
int[] b = new int[10];
|
||||
for(int a : b){
|
||||
a = a+3;
|
||||
}
|
||||
}
|
||||
}
|
||||
]]></code>
|
||||
</test-code>
|
||||
|
||||
<test-code>
|
||||
<description>#1905 [java] DataflowAnomalyAnalysis Rule in right order : Case 4. DU-Anomaly(a)</description>
|
||||
<expected-problems>2</expected-problems>
|
||||
<expected-linenumbers>3,6</expected-linenumbers>
|
||||
<expected-messages>
|
||||
<message>Found 'DU'-anomaly for variable 'a' (lines '3'-'9').</message>
|
||||
<message>Found 'DU'-anomaly for variable 'a' (lines '6'-'9').</message>
|
||||
</expected-messages>
|
||||
<code><![CDATA[
|
||||
class Test{
|
||||
public static void main(String[] args){
|
||||
int a = 0 ;
|
||||
int i = 0 ;
|
||||
while(i < 30){
|
||||
a = a+3;
|
||||
i += 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
]]></code>
|
||||
</test-code>
|
||||
|
||||
<test-code>
|
||||
<description>#1905 [java] DataflowAnomalyAnalysis Rule in right order : Case 5. DU-Anomaly(a)</description>
|
||||
<expected-problems>1</expected-problems>
|
||||
<expected-linenumbers>6</expected-linenumbers>
|
||||
<expected-messages>
|
||||
<message>Found 'DU'-anomaly for variable 'a' (lines '6'-'9').</message>
|
||||
</expected-messages>
|
||||
<code><![CDATA[
|
||||
class Test{
|
||||
public static void main(String[] args){
|
||||
int a = 0 ;
|
||||
int i = 0 ;
|
||||
do{
|
||||
a = a+3;
|
||||
i += 3;
|
||||
}while(i < 30);
|
||||
}
|
||||
}
|
||||
]]></code>
|
||||
</test-code>
|
||||
|
||||
<test-code>
|
||||
<description>#1905 [java] DataflowAnomalyAnalysis Rule in right order : Case 6. DU-Anomaly(a)</description>
|
||||
<expected-problems>4</expected-problems>
|
||||
<expected-linenumbers>6,8,10,12</expected-linenumbers>
|
||||
<expected-messages>
|
||||
<message>Found 'DU'-anomaly for variable 'a' (lines '6'-'14').</message>
|
||||
<message>Found 'DU'-anomaly for variable 'a' (lines '8'-'14').</message>
|
||||
<message>Found 'DU'-anomaly for variable 'a' (lines '10'-'14').</message>
|
||||
<message>Found 'DU'-anomaly for variable 'a' (lines '12'-'14').</message>
|
||||
</expected-messages>
|
||||
<code><![CDATA[
|
||||
class Test{
|
||||
public static void main(String[] args){
|
||||
int a = 0 ;
|
||||
int i = 0 ;
|
||||
switch(i){
|
||||
case 1 : a = a+1;
|
||||
break;
|
||||
case 2 : a = a+2;
|
||||
break;
|
||||
case 3 : a = a+3;
|
||||
break;
|
||||
default : a = a + 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
]]></code>
|
||||
</test-code>
|
||||
|
||||
<test-code>
|
||||
<description>#1905 [java] DataflowAnomalyAnalysis Rule in right order : Case 7. DU-Anomaly(a)</description>
|
||||
<expected-problems>1</expected-problems>
|
||||
<expected-linenumbers>9</expected-linenumbers>
|
||||
<expected-messages>
|
||||
<message>Found 'DU'-anomaly for variable 'a' (lines '9'-'11').</message>
|
||||
</expected-messages>
|
||||
<code><![CDATA[
|
||||
class Test{
|
||||
public static void main(String[] args){
|
||||
int a = 0 ;
|
||||
int i = 0 ;
|
||||
switch(i){
|
||||
case 1 : a = a+1;
|
||||
case 2 : a = a+2;
|
||||
case 3 : a = a+3;
|
||||
default : a = a + 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
]]></code>
|
||||
</test-code>
|
||||
|
||||
<test-code>
|
||||
<description>#1905 [java] DataflowAnomalyAnalysis Rule in right order : Case 9. DU-Anomaly(t1)</description>
|
||||
<expected-problems>1</expected-problems>
|
||||
<expected-linenumbers>5</expected-linenumbers>
|
||||
<expected-messages>
|
||||
<message>Found 'DU'-anomaly for variable 't1' (lines '5'-'6').</message>
|
||||
</expected-messages>
|
||||
<code><![CDATA[
|
||||
class Test{
|
||||
public static void main(String[] args){
|
||||
int t1 = 0 ;
|
||||
Test2 test = new Test2() ;
|
||||
t1 = test.simpleTest(t1) ;
|
||||
}
|
||||
}
|
||||
]]></code>
|
||||
</test-code>
|
||||
|
||||
<test-code>
|
||||
<description>#1905 [java] DataflowAnomalyAnalysis Rule in right order : Case 12. DU-Anomaly(t1)</description>
|
||||
<expected-problems>1</expected-problems>
|
||||
<expected-linenumbers>6</expected-linenumbers>
|
||||
<expected-messages>
|
||||
<message>Found 'DU'-anomaly for variable 't1' (lines '6'-'7').</message>
|
||||
</expected-messages>
|
||||
<code><![CDATA[
|
||||
class Test{
|
||||
public static void main(String[] args){
|
||||
int t1 = 0 ;
|
||||
int t2 = 0 ;
|
||||
Test2 test = new Test2();
|
||||
if((t1 = test.simpleTest(t1)) == t2);
|
||||
}
|
||||
}
|
||||
]]></code>
|
||||
</test-code>
|
||||
|
||||
<test-code>
|
||||
<description>#1905 [java] DataflowAnomalyAnalysis Rule in right order : Case 13</description>
|
||||
<expected-problems>0</expected-problems>
|
||||
<code><![CDATA[
|
||||
class Test{
|
||||
public static void main(String[] args){
|
||||
int t1 = 0 ;
|
||||
|
||||
Test2 test = new Test2();
|
||||
if( (t1 = test.simpleTest(t1)) == t1);
|
||||
}
|
||||
}
|
||||
]]></code>
|
||||
</test-code>
|
||||
|
||||
<test-code>
|
||||
<description>#1905 [java] DataflowAnomalyAnalysis Rule in right order : Case 14. DU-Anomaly(t1, t2)</description>
|
||||
<expected-problems>2</expected-problems>
|
||||
<expected-linenumbers>4,6</expected-linenumbers>
|
||||
<expected-messages>
|
||||
<message>Found 'DU'-anomaly for variable 't2' (lines '4'-'7').</message>
|
||||
<message>Found 'DU'-anomaly for variable 't1' (lines '6'-'7').</message>
|
||||
</expected-messages>
|
||||
<code><![CDATA[
|
||||
class Test{
|
||||
public static void main(String[] args){
|
||||
int t1 = 0;
|
||||
int t2 = 0;
|
||||
Test2 test = new Test2() ;
|
||||
if( t1 == (t1 = test.simpleTest(t1))) ;
|
||||
}
|
||||
}
|
||||
]]></code>
|
||||
</test-code>
|
||||
|
||||
<test-code>
|
||||
<description>#1749 DD False Positive in DataflowAnomalyAnalysis</description>
|
||||
<expected-problems>1</expected-problems>
|
||||
<expected-linenumbers>4</expected-linenumbers>
|
||||
<expected-messages>
|
||||
<message>Found 'DU'-anomaly for variable 'a' (lines '4'-'5').</message>
|
||||
</expected-messages>
|
||||
<code><![CDATA[
|
||||
public class Test {
|
||||
public void test(){
|
||||
int a = 0;
|
||||
a = a + 3;
|
||||
}
|
||||
}
|
||||
]]></code>
|
||||
</test-code>
|
||||
|
Reference in New Issue
Block a user