View Javadoc
1   /**
2    * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
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<>();
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  }