1
2
3
4 package net.sourceforge.pmd.lang.java.rule.finalizers;
5
6 import java.util.HashSet;
7 import java.util.List;
8 import java.util.Set;
9
10 import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit;
11 import net.sourceforge.pmd.lang.java.ast.ASTName;
12 import net.sourceforge.pmd.lang.java.ast.ASTPrimaryPrefix;
13 import net.sourceforge.pmd.lang.java.ast.ASTPrimarySuffix;
14 import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule;
15 import net.sourceforge.pmd.lang.java.symboltable.MethodScope;
16 import net.sourceforge.pmd.lang.symboltable.ScopedNode;
17
18 public class AvoidCallingFinalizeRule extends AbstractJavaRule {
19
20 private Set<MethodScope> checked = new HashSet<MethodScope>();
21
22 public Object visit(ASTCompilationUnit acu, Object ctx) {
23 checked.clear();
24 return super.visit(acu, ctx);
25 }
26
27 public Object visit(ASTName name, Object ctx) {
28 if (name.getImage() == null || !name.getImage().endsWith("finalize")) {
29 return ctx;
30 }
31 if (!checkForViolation(name)) {
32 return ctx;
33 }
34 addViolation(ctx, name);
35 return ctx;
36 }
37
38 public Object visit(ASTPrimaryPrefix pp, Object ctx) {
39 List<ASTPrimarySuffix> primarySuffixes = pp.jjtGetParent().findChildrenOfType(ASTPrimarySuffix.class);
40 ASTPrimarySuffix firstSuffix = null;
41 if (!primarySuffixes.isEmpty()) {
42 firstSuffix = primarySuffixes.get(0);
43 }
44 if (firstSuffix == null || firstSuffix.getImage() == null || !firstSuffix.getImage().endsWith("finalize")) {
45 return super.visit(pp, ctx);
46 }
47 if (!checkForViolation(pp)) {
48 return super.visit(pp, ctx);
49 }
50 addViolation(ctx, pp);
51 return super.visit(pp, ctx);
52 }
53
54 private boolean checkForViolation(ScopedNode node) {
55 MethodScope meth = node.getScope().getEnclosingScope(MethodScope.class);
56 if (meth != null && "finalize".equals(meth.getName())) {
57 return false;
58 }
59 if (meth != null && checked.contains(meth)) {
60 return false;
61 }
62 if (meth != null) {
63 checked.add(meth);
64 }
65 return true;
66 }
67 }