View Javadoc

1   package net.sourceforge.pmd.lang.java.rule.basic;
2   
3   import net.sourceforge.pmd.lang.java.ast.ASTAllocationExpression;
4   import net.sourceforge.pmd.lang.java.ast.ASTArrayDimsAndInits;
5   import net.sourceforge.pmd.lang.java.ast.ASTBooleanLiteral;
6   import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceType;
7   import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit;
8   import net.sourceforge.pmd.lang.java.ast.ASTImportDeclaration;
9   import net.sourceforge.pmd.lang.java.ast.ASTLiteral;
10  import net.sourceforge.pmd.lang.java.ast.ASTName;
11  import net.sourceforge.pmd.lang.java.ast.ASTPrimaryExpression;
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.typeresolution.TypeHelper;
16  
17  /**
18   * Avoid instantiating Boolean objects; you can reference Boolean.TRUE,
19   * Boolean.FALSE, or call Boolean.valueOf() instead.
20   *
21   * <pre>
22   *  public class Foo {
23   *       Boolean bar = new Boolean("true");    // just do a Boolean
24   *       bar = Boolean.TRUE;                   //ok
25   *       Boolean buz = Boolean.valueOf(false); // just do a Boolean buz = Boolean.FALSE;
26   *  }
27   * </pre>
28   */
29  public class BooleanInstantiationRule extends AbstractJavaRule {
30  
31  	/*
32  	 *  see bug 1744065 : If somebody create it owns Boolean, the rule should not be triggered
33  	 *   Therefore, we use this boolean to flag if the source code contains such an import
34  	 *
35  	 */
36  	private boolean customBoolean;
37  
38      @Override
39      public Object visit(ASTCompilationUnit decl,Object data) {
40          // customBoolean needs to be reset for each new file
41          customBoolean = false;
42  
43          return super.visit(decl, data);
44      }
45  
46  	@Override
47  	public Object visit(ASTImportDeclaration decl,Object data) {
48  		// If the import actually import a Boolean class that overrides java.lang.Boolean
49  		if ( decl.getImportedName().endsWith("Boolean") && ! decl.getImportedName().equals("java.lang"))
50  		{
51  			customBoolean = true;
52  		}
53  		return super.visit(decl, data);
54  	}
55  
56      @Override
57      public Object visit(ASTAllocationExpression node, Object data) {
58  
59      	if ( ! customBoolean ) {
60  	        if (node.hasDescendantOfType(ASTArrayDimsAndInits.class)) {
61  	            return super.visit(node, data);
62  	        }
63  	        if (TypeHelper.isA((ASTClassOrInterfaceType) node.jjtGetChild(0), Boolean.class)) {
64                  super.addViolation(data, node);
65                  return data;
66              }
67      	}
68          return super.visit(node, data);
69      }
70  
71      @Override
72      public Object visit(ASTPrimaryPrefix node, Object data) {
73  
74      	if ( ! customBoolean )
75      	{
76  	        if (node.jjtGetNumChildren() == 0 || !(node.jjtGetChild(0) instanceof ASTName)) {
77  	            return super.visit(node, data);
78  	        }
79  
80  	        if ("Boolean.valueOf".equals(((ASTName) node.jjtGetChild(0)).getImage())
81  	                || "java.lang.Boolean.valueOf".equals(((ASTName) node.jjtGetChild(0)).getImage())) {
82  	            ASTPrimaryExpression parent = (ASTPrimaryExpression) node.jjtGetParent();
83  	            ASTPrimarySuffix suffix = parent.getFirstDescendantOfType(ASTPrimarySuffix.class);
84  	            if (suffix == null) {
85  	                return super.visit(node, data);
86  	            }
87  	            ASTPrimaryPrefix prefix = suffix.getFirstDescendantOfType(ASTPrimaryPrefix.class);
88  	            if (prefix == null) {
89  	                return super.visit(node, data);
90  	            }
91  
92  	            if (prefix.hasDescendantOfType(ASTBooleanLiteral.class)) {
93  	                super.addViolation(data, node);
94  	                return data;
95  	            }
96  	            ASTLiteral literal = prefix.getFirstDescendantOfType(ASTLiteral.class);
97  	            if (literal != null && ("\"true\"".equals(literal.getImage()) || "\"false\"".equals(literal.getImage()))) {
98  	                super.addViolation(data, node);
99  	                return data;
100 	            }
101 	        }
102     	}
103         return super.visit(node, data);
104     }
105 }