diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/UnusedAssignmentRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/UnusedAssignmentRule.java index c4e158b3df..9c21f97fc9 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/UnusedAssignmentRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/UnusedAssignmentRule.java @@ -19,7 +19,6 @@ import java.util.Set; import net.sourceforge.pmd.RuleContext; import net.sourceforge.pmd.lang.ast.Node; -import net.sourceforge.pmd.lang.java.ast.ASTAnnotationTypeDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeBodyDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTAssignmentOperator; @@ -27,12 +26,12 @@ import net.sourceforge.pmd.lang.java.ast.ASTBlock; import net.sourceforge.pmd.lang.java.ast.ASTBlockStatement; import net.sourceforge.pmd.lang.java.ast.ASTBreakStatement; import net.sourceforge.pmd.lang.java.ast.ASTCatchStatement; -import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration; +import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceBody; import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit; import net.sourceforge.pmd.lang.java.ast.ASTConstructorDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTContinueStatement; import net.sourceforge.pmd.lang.java.ast.ASTDoStatement; -import net.sourceforge.pmd.lang.java.ast.ASTEnumDeclaration; +import net.sourceforge.pmd.lang.java.ast.ASTEnumBody; import net.sourceforge.pmd.lang.java.ast.ASTExpression; import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTFinallyStatement; @@ -79,10 +78,10 @@ public class UnusedAssignmentRule extends AbstractJavaRule { /* TODO - * constructors + initializers * labels on arbitrary statements * foreach var should be reassigned from one iter to another * test local class/anonymous class + * test this.field in ctors DONE * conditionals @@ -91,6 +90,8 @@ public class UnusedAssignmentRule extends AbstractJavaRule { * loop labels * try/catch/finally * lambdas + * constructors + initializers + * anon class */ @@ -212,7 +213,7 @@ public class UnusedAssignmentRule extends AbstractJavaRule { } for (VariableNameDeclaration var : localsToKill) { - state.undef(var); + state.del(var); } return state; @@ -302,7 +303,7 @@ public class UnusedAssignmentRule extends AbstractJavaRule { AlgoState exceptionalState = null; for (ASTCatchStatement catchClause : node.getCatchClauses()) { - AlgoState current = acceptOpt(catchClause, before.fork()); + AlgoState current = acceptOpt(catchClause, before.fork().absorb(bodyState)); exceptionalState = current.absorb(exceptionalState); } @@ -580,35 +581,46 @@ public class UnusedAssignmentRule extends AbstractJavaRule { return data; } + /** + * Get the variable accessed from a primary. + */ private VariableNameDeclaration getLhsVar(JavaNode primary, boolean inLhs) { + if (primary instanceof ASTPrimaryExpression) { ASTPrimaryPrefix prefix = (ASTPrimaryPrefix) primary.getChild(0); - // todo - // this.x = 2; - // if (prefix.usesThisModifier()) { - // if (primary.getNumChildren() < 2) { - // return null; - // } - // ASTPrimarySuffix suffix = (ASTPrimarySuffix) primary.getChild(1); - // if (suffix.isArguments() || suffix.isArrayDereference() || suffix.getImage() == null) { - // return null; - // } - // return findVar(primary.getScope(), true, firstIdent(suffix.getImage())); - // } else - { + // this.x = 2; + if (prefix.usesThisModifier() && this.enclosingClassScope != null) { + if (primary.getNumChildren() < 2 || primary.getNumChildren() > 2 && inLhs) { + return null; + } + + ASTPrimarySuffix suffix = (ASTPrimarySuffix) primary.getChild(1); + if (suffix.getImage() == null) { + // catches arrays and such + return null; + } + + return findVar(primary.getScope(), true, suffix.getImage()); + } else { if (prefix.getNumChildren() > 0 && (prefix.getChild(0) instanceof ASTName)) { String prefixImage = prefix.getChild(0).getImage(); String varname = identOf(inLhs, prefixImage); - if (primary.getNumChildren() > 1 && !inLhs) { + if (primary.getNumChildren() > 1) { + if (primary.getNumChildren() > 2 && inLhs) { + // this is for chains like `foo.m().field = 3` + return null; + } ASTPrimarySuffix suffix = (ASTPrimarySuffix) primary.getChild(1); if (suffix.isArguments()) { // then the prefix has the method name varname = methodLhsName(prefixImage); + } else if (suffix.isArrayDereference() && inLhs) { + return null; } } - return findVar(prefix.getScope(), varname); + return findVar(prefix.getScope(), false, varname); } } } @@ -634,20 +646,23 @@ public class UnusedAssignmentRule extends AbstractJavaRule { : name.substring(0, i); } - private VariableNameDeclaration findVar(Scope scope, String name) { + private VariableNameDeclaration findVar(Scope scope, boolean isField, String name) { if (name == null) { return null; } + if (isField) { + return getFromSingleScope(enclosingClassScope, name); + } + while (scope != null) { - for (VariableNameDeclaration decl : scope.getDeclarations(VariableNameDeclaration.class).keySet()) { - if (decl.getImage().equals(name)) { - if (scope instanceof ClassScope && scope != enclosingClassScope) { - // don't handle fields - return null; - } - return decl; + VariableNameDeclaration result = getFromSingleScope(scope, name); + if (result != null) { + if (scope instanceof ClassScope && scope != enclosingClassScope) { + // don't handle fields + return null; } + return result; } scope = scope.getParent(); @@ -656,47 +671,56 @@ public class UnusedAssignmentRule extends AbstractJavaRule { return null; } + private VariableNameDeclaration getFromSingleScope(Scope scope, String name) { + if (scope != null) { + for (VariableNameDeclaration decl : scope.getDeclarations(VariableNameDeclaration.class).keySet()) { + if (decl.getImage().equals(name)) { + return decl; + } + } + } + return null; + } + // ctor/initializer handling - @Override - public Object visit(ASTClassOrInterfaceDeclaration node, Object data) { - return visitType(node, data); - } + // this is the common denominator between anonymous class & astAnyTypeDeclaration on master @Override - public Object visit(ASTEnumDeclaration node, Object data) { - return visitType(node, data); - } - - @Override - public Object visit(ASTAnnotationTypeDeclaration node, Object data) { - return visitType(node, data); - } - - private Object visitType(ASTAnyTypeDeclaration type, Object data) { - AlgoState prev = (AlgoState) data; - processInitializers(type, prev); - - for (ASTAnyTypeBodyDeclaration decl : type.getDeclarations()) { - JavaNode d = decl.getDeclarationNode(); - if (d instanceof ASTMethodDeclaration) { - ONLY_LOCALS.acceptOpt(d, prev.forkCapturingNonLocal()); - } else if (d instanceof ASTAnyTypeDeclaration) { - visitType((ASTAnyTypeDeclaration) d, prev.forkEmptyNonLocal()); - } - } - + public Object visit(ASTClassOrInterfaceBody node, Object data) { + visitTypeBody(node, (AlgoState) data); return data; // type doesn't contribute anything to the enclosing control flow } - // todo anon class + @Override + public Object visit(ASTEnumBody node, Object data) { + visitTypeBody(node, (AlgoState) data); + return data; // type doesn't contribute anything to the enclosing control flow + } - public static void processInitializers(ASTAnyTypeDeclaration klass, - AlgoState beforeLocal) { + public void visitTypeBody(JavaNode typeBody, AlgoState data) { + List declarations = typeBody.findChildrenOfType(ASTAnyTypeBodyDeclaration.class); + processInitializers(declarations, data, (ClassScope) typeBody.getScope()); - ReachingDefsVisitor visitor = new ReachingDefsVisitor((ClassScope) klass.getScope()); + for (ASTAnyTypeBodyDeclaration decl : declarations) { + JavaNode d = decl.getDeclarationNode(); + if (d instanceof ASTMethodDeclaration) { + ONLY_LOCALS.acceptOpt(d, data.forkCapturingNonLocal()); + } else if (d instanceof ASTAnyTypeDeclaration) { + JavaNode body = d.getChild(d.getNumChildren() - 1); + visitTypeBody(body, data.forkEmptyNonLocal()); + } + } + } + + + public static void processInitializers(List declarations, + AlgoState beforeLocal, + ClassScope scope) { + + ReachingDefsVisitor visitor = new ReachingDefsVisitor(scope); // All field initializers + instance initializers AlgoState ctorHeader = beforeLocal.forkCapturingNonLocal(); @@ -705,7 +729,7 @@ public class UnusedAssignmentRule extends AbstractJavaRule { List ctors = new ArrayList<>(); - for (ASTAnyTypeBodyDeclaration declaration : klass.getDeclarations()) { + for (ASTAnyTypeBodyDeclaration declaration : declarations) { JavaNode node = declaration.getDeclarationNode(); final boolean isStatic; @@ -737,6 +761,9 @@ public class UnusedAssignmentRule extends AbstractJavaRule { // assignments that reach the end of any constructor must // be considered used for (VariableNameDeclaration field : visitor.enclosingClassScope.getVariableDeclarations().keySet()) { + if (field.getAccessNodeParent().isStatic()) { + staticInit.use(field); + } ctorEndState.use(field); } } @@ -816,7 +843,7 @@ public class UnusedAssignmentRule extends AbstractJavaRule { } } - void undef(VariableNameDeclaration var) { + void del(VariableNameDeclaration var) { reachingDefs.remove(var); } @@ -858,7 +885,8 @@ public class UnusedAssignmentRule extends AbstractJavaRule { AlgoState absorb(AlgoState sub) { - // Merge reaching des of the other scope into this + // Merge reaching defs of the other scope into this + // This is used to join paths after the control flow has forked if (sub == this || sub == null || sub.reachingDefs.isEmpty()) { return this; } diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/UnusedAssignment.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/UnusedAssignment.xml index ca072e130b..9ede002e1d 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/UnusedAssignment.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/UnusedAssignment.xml @@ -4,1344 +4,1408 @@ 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"> - - ok - 0 - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - DD anomaly - 1 - 3 - - The value assigned to variable 'i' is never used (overwritten on line 4) - - - - - - DU anomaly - 1 - - - - - UR anomaly - 0 - - - - - Conditional flow 0 - 3 - 3,4,6 - - The value assigned to variable 'j' is never used (overwritten on line 6) - The value assigned to variable 'z' is never used (goes out of scope) - The value assigned to variable 'j' is never used (goes out of scope) - - - - - - Conditional flow 1 - 1 - 4 - - The value assigned to variable 'z' is never used (goes out of scope) - - - - - - Conditional flow 2 - 1 - 3 - - The value assigned to variable 'j' is never used (overwritten on lines 6 and 8) - - - - - - Conditional flow with abrupt throw - 2 - 3,6 - - The value assigned to variable 'j' is never used (overwritten on lines 6 and 9) - The value assigned to variable 'j' is never used (goes out of scope) - - - - - - Conditional flow with abrupt return - 2 - 3,6 - - The value assigned to variable 'j' is never used (overwritten on lines 6 and 9) - The value assigned to variable 'j' is never used (goes out of scope) - - - - - - Local variable in loop - 2 - 10,19 - - The value assigned to variable 'fail' is never used (overwritten on line 19) - The value assigned to variable 'fail' is never used (overwritten on line 19) - - - - - - #408 Assert statements causing - 0 - - - - - #1905 [java] DataflowAnomalyAnalysis Rule in right order : Case 1. DU-Anomaly(b) - 1 - 6 - - The value assigned to variable 'b' is never used (goes out of scope) - - - - - - For loop - 0 - - - - - For loop 2 - 2 - 3,5 - - The value assigned to variable 'a' is never used (overwritten on line 5) - - The value assigned to variable 'a' is never used (overwritten on line 5) - - - - - - For loop 3 - 0 - - - - - For loop 4 - 0 - - - - - Foreach - 0 - - - - - While loop 1 - 0 - - - - - While loop 2 - 2 - 4,7 - - The value assigned to variable 'i' is never used (overwritten on line 7) - The value assigned to variable 'i' is never used (overwritten on line 7) - - - - - While loop with break - 1 - 7 - - The value assigned to variable 'i' is never used (goes out of scope) - - = 30) { - i = a + 1; // unused - break; - } - a = a + 3; - i = i + 1; // used by itself - } - } -} - ]]> - - - - While loop without break (control case) - 1 - = 30) { - i += a + 1; // unused by below - // break; // no break here - } - a = a + 3; - i = a + 2; // used by above - } - } -} - ]]> - - - - While loop without break 2 (control case) - 1 - 12 - - The value assigned to variable 'i' is never used (overwritten on line 16) - - = 30) { - i += a + 1; // unused because of i = a + 2 - // break outer; - } - a = a + 3; - i = a + 2; // killed by below - } - - i = 2; // used by print - } - - System.out.println(i); // uses i = i + 1 - } -} - ]]> - - - - While loop without break 2 (control case) - 1 - 12 - - The value assigned to variable 'i' is never used (overwritten on line 19) - - = 30) { - i += a + 1; // unused because of i = 2 - break; - } - a = a + 3; - i = a + 2; // used by i += a + 1 - } - - i = 2; // used by print - } - - System.out.println(i); // uses i = i + 1 - } -} - ]]> - - - - While loop with named break 2 - 0 - = 30) { - i += a + 1; // used by print - break outer; - } - a = a + 3; - i = a + 2; // used by i += a + 1 - } - - i = 2; // used by print - } - - System.out.println(i); // uses i = i + 1 - } -} - ]]> - - - - - While loop with continue - 0 - = 30) { - i = a + 1; // used by below - continue; - } - a = a + 3; - i = i + 1; // used by itself - } - } -} - ]]> - - - - While loop with continue 2 - 0 - = 30) { - a = i + 1; // used by loop condition - continue; - } - i++; // used by itself - } - } -} - ]]> - - - - While loop with break (control for continue test above) - 1 - 7 - - The value assigned to variable 'a' is never used (goes out of scope) - - = 30) { - a = i + 1; // unused - break; - } - i++; // used by itself - } - } -} - ]]> - - - - Do while 0 - 0 - - - - - Do while 1 - 1 - 3 - - The value assigned to variable 'a' is never used (overwritten on line 6) - - - - - - Do while with break - 2 - 7,8 - - The value assigned to variable 'i' is never used (goes out of scope) - The value assigned to variable 'a' is never used (goes out of scope) - - = 20) { - i = 4; - a *= 5; - break; - } - - a = i + 3; - i += 3; - } while (i < 30); - } -} - ]]> - - - - Do while with continue - 0 - = 20) { - i = 4; // used by condition - a *= 5; - continue; - } - - a = i + 3; - i += 3; - } while (i < 30); - } -} - ]]> - - - - Switch statement 0 - 4 - 6,8,10,12 - - The value assigned to variable 'a' is never used (goes out of scope) - The value assigned to variable 'a' is never used (goes out of scope) - The value assigned to variable 'a' is never used (goes out of scope) - The value assigned to variable 'a' is never used (goes out of scope) - - - - - - Switch statement 1 - 0 - - - - - Switch statement 2 - 0 - 0) break; // else fallthrough - case 2 : a = 2; break; - case 3 : a = 3; break; - default : a = a + 1; - } - - System.out.println(a); - } -} - ]]> - - - - Switch fallthrough - 1 - 6 - - The value assigned to variable 'a' is never used (overwritten on line 8) - - - - - - Switch fallthrough 2 - 1 - 9 - - The value assigned to variable 'a' is never used (goes out of scope) - - - - - - Switch non-fallthrough - 0 - a = 1; - case 2 -> a = 2; - case 3 -> a = 3; - default -> a = a + 1; - } - System.out.println(a); - } -} - ]]> - - - - Switch non-fallthrough blocks - 1 - 9 - - The value assigned to variable 'i' is never used (goes out of scope) - - a = 1; - case 2 -> { - if (args.length > 0) { - i = 4; - break; - } - a = 2; - } - case 3 -> a = 3; - default -> a = a + 1; - } - System.out.println(a); - } -} - ]]> - - - - Switch expr non-fallthrough - 4 - 6,7,8,9 - - The value assigned to variable 'a' is never used (overwritten on line 4) - The value assigned to variable 'a' is never used (overwritten on line 4) - The value assigned to variable 'a' is never used (overwritten on line 4) - The value assigned to variable 'a' is never used (overwritten on line 4) - - a = 1; - case 2 -> a = 2; - case 3 -> a = 3; - default -> a = a + 1; - }; - - System.out.println(a); - } -} - ]]> - - - - Switch expr with yield - 4 - 6,9,13,14 - - The value assigned to variable 'a' is never used (overwritten on line 4) - The value assigned to variable 'a' is never used (overwritten on line 4) - The value assigned to variable 'a' is never used (overwritten on line 4) - The value assigned to variable 'a' is never used (overwritten on line 4) - - a = 1; - case 2 -> { - if (a > 0) { - yield a++; - } - yield 4; - } - case 3 -> a = 3; - default -> a = a + 1; - }; - - System.out.println(a); - } -} - ]]> - - - - Usage as LHS of method - 1 - 5 - - The value assigned to variable 't1' is never used (goes out of scope) - - - - - - Assignment in operand - 1 - 6 - - The value assigned to variable 't1' is never used (goes out of scope) - - - - - - Assignment in operand 2 - 1 - 7 - - The value assigned to variable 't1' is never used (goes out of scope) - - - - - - Assignment in operand 3 - 0 - - - - - Assignment in operand 4 - 2 - 4,6 - - The value assigned to variable 't2' is never used (goes out of scope) - The value assigned to variable 't1' is never used (goes out of scope) - - - - - - #1749 DD False Positive in DataflowAnomalyAnalysis - 1 - 4 - - The value assigned to variable 'a' is never used (goes out of scope) - - - - - Compound assignment - 1 - 4 - - The value assigned to variable 'a' is never used (goes out of scope) - - - - - Another case - 2 - 3,5 - - The value assigned to variable 'iter' is never used (overwritten on line 4) - The value assigned to variable 'iter' is never used (goes out of scope) - - - - - - Var usage in lambda (#1304) - 0 - dummySet) { - captured = captured.trim(); - return dummySet.stream().noneMatch(value -> value.equalsIgnoreCase(captured)); - } - -} ]]> - - - - Try/catch - 1 - 4 - - The value assigned to variable 'a' is never used (overwritten on lines 6 and 8) - - - - - - Try with several catches - 0 - - - - - Try/catch finally - 0 - - - - Try/catch finally 3 - 1 - 4 - - The value assigned to variable 'a' is never used (overwritten on lines 6 and 8) - - - - - Try/catch finally in loop - 0 - 10) { - try (Reader r = new StringReader("")) { - r.read(); - } catch (IOException e) { - a = -1; // used in finally even if break - break; - } finally { - a++; - } - } - return a; - } - -} - ]]> - - - Abstract method NPE - 0 - - - - FP in finally - 0 - - - - - Lambda captured var use - 0 - decode() { - Flux> splitEvents = splitEvts(); - - return map(events -> { - return unmarshal(events.append(splitEvents)); - }); - } - -} - ]]> - - - Lambda assignment - 2 - 5,6 - - The value assigned to variable 'k' is never used (overwritten on line 6) - The value assigned to variable 'k' is never used (goes out of scope) - - { - int k = 0; - return k = 2; - }); - } - -} - ]]> - - - Lambda returns 2 - 2 - 4,7 - - The value assigned to variable 'splitEvents' is never used (goes out of scope) - The value assigned to variable 'events' is never used (goes out of scope) - - decode() { - Flux> splitEvents = splitEvts(); - - return map(events -> { - events = events.normalize(); - return dontUseEvents(); - }); - } - -} - ]]> - - - FP in try - 0 - - - - - Field initializers 0 - 0 - - - - - Field initializers 1 - 1 - 3 - - The value assigned to variable 'f1' is never used (overwritten on line 4) - - - - - - Field initializers and ctor + Field initializers and ctor with this, shadowing 1 3 @@ -1353,13 +1417,35 @@ class Foo { int f1 = 0; int f2 = 0; - Foo(int f, int g) { - f1 = f; + Foo(int f1, int g) { + this.f1 = f1; } - Foo(int f, int g) { - f1 = f; - f2 = f + g; + Foo(int f1, int g) { + this.f1 = f1; + this.f2 = f1 + g; + } + +} + ]]> + + + + Field initializers and ctor with this, field access + 0 + + + Static initializer + 0 + ejbRefClass; + + private static Class webServiceRefClass; + + static { + try { + Class clazz = (Class) Class.forName("javax.xml.ws.WebServiceRef"); + webServiceRefClass = clazz; + } catch (ClassNotFoundException ex) { + webServiceRefClass = null; + } + + try { + Class clazz = Class.forName("javax.ejb.EJB"); + ejbRefClass = clazz; + } catch (ClassNotFoundException ex) { + ejbRefClass = null; + } + } + + + private static Class other = webServiceRefClass; + +} + ]]> + + + + + FP with anonymous classes on the way + 0 + OBJECT_METHODS = new ArrayList(); + + static { + Method privateLookupIn; + Method lookupDefineClass; + Method classLoaderDefineClass; + ProtectionDomain protectionDomain; + Throwable throwable = null; + try { + privateLookupIn = (Method) AccessController.doPrivileged(new PrivilegedExceptionAction() { + public Object run() throws Exception { + try { + return MethodHandles.class.getMethod("privateLookupIn", Class.class, MethodHandles.Lookup.class); + } + catch (NoSuchMethodException ex) { + return null; + } + } + }); + lookupDefineClass = (Method) AccessController.doPrivileged(new PrivilegedExceptionAction() { + public Object run() throws Exception { + try { + return MethodHandles.Lookup.class.getMethod("defineClass", byte[].class); + } + catch (NoSuchMethodException ex) { + return null; + } + } + }); + classLoaderDefineClass = (Method) AccessController.doPrivileged(new PrivilegedExceptionAction() { + public Object run() throws Exception { + return ClassLoader.class.getDeclaredMethod("defineClass", + String.class, byte[].class, Integer.TYPE, Integer.TYPE, ProtectionDomain.class); + } + }); + protectionDomain = getProtectionDomain(ReflectUtils.class); + AccessController.doPrivileged(new PrivilegedExceptionAction() { + public Object run() throws Exception { + Method[] methods = Object.class.getDeclaredMethods(); + for (Method method : methods) { + if ("finalize".equals(method.getName()) + || (method.getModifiers() & (Modifier.FINAL | Modifier.STATIC)) > 0) { + continue; + } + OBJECT_METHODS.add(method); + } + return null; + } + }); + } + catch (Throwable t) { + privateLookupIn = null; + lookupDefineClass = null; + classLoaderDefineClass = null; + protectionDomain = null; + throwable = t; + } + privateLookupInMethod = privateLookupIn; + lookupDefineClassMethod = lookupDefineClass; + classLoaderDefineClassMethod = classLoaderDefineClass; + PROTECTION_DOMAIN = protectionDomain; + THROWABLE = throwable; + } + +} + ]]> + + + + FP with array access + 0 + map, String name, int[] arr) { + Integer index = map.get(name); + arr[index] = 4; + } + +} + ]]> + + + + FP with array access + 0 + + + + + FP with long field access + 0 + + + + + FP with long access 2 + 0 + + + + FP with long access 2 + 0 + + + + + FN with casts + 1 + +