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 }