Merge branch 'pr-1905'

This commit is contained in:
Andreas Dangel
2019-07-22 20:05:53 +02:00
3 changed files with 281 additions and 2 deletions

View File

@ -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);
}
}
}

View File

@ -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>