BooleanInstantiationRule.java
001 package net.sourceforge.pmd.lang.java.rule.basic;
002 
003 import net.sourceforge.pmd.lang.java.ast.ASTAllocationExpression;
004 import net.sourceforge.pmd.lang.java.ast.ASTArrayDimsAndInits;
005 import net.sourceforge.pmd.lang.java.ast.ASTBooleanLiteral;
006 import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceType;
007 import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit;
008 import net.sourceforge.pmd.lang.java.ast.ASTImportDeclaration;
009 import net.sourceforge.pmd.lang.java.ast.ASTLiteral;
010 import net.sourceforge.pmd.lang.java.ast.ASTName;
011 import net.sourceforge.pmd.lang.java.ast.ASTPrimaryExpression;
012 import net.sourceforge.pmd.lang.java.ast.ASTPrimaryPrefix;
013 import net.sourceforge.pmd.lang.java.ast.ASTPrimarySuffix;
014 import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule;
015 import net.sourceforge.pmd.lang.java.typeresolution.TypeHelper;
016 
017 /**
018  * Avoid instantiating Boolean objects; you can reference Boolean.TRUE,
019  * Boolean.FALSE, or call Boolean.valueOf() instead.
020  *
021  <pre>
022  *  public class Foo {
023  *       Boolean bar = new Boolean("true");    // just do a Boolean
024  *       bar = Boolean.TRUE;                   //ok
025  *       Boolean buz = Boolean.valueOf(false); // just do a Boolean buz = Boolean.FALSE;
026  *  }
027  </pre>
028  */
029 public class BooleanInstantiationRule extends AbstractJavaRule {
030 
031   /*
032    *  see bug 1744065 : If somebody create it owns Boolean, the rule should not be triggered
033    *   Therefore, we use this boolean to flag if the source code contains such an import
034    *
035    */
036   private boolean customBoolean;
037 
038     @Override
039     public Object visit(ASTCompilationUnit decl,Object data) {
040         // customBoolean needs to be reset for each new file
041         customBoolean = false;
042 
043         return super.visit(decl, data);
044     }
045 
046   @Override
047   public Object visit(ASTImportDeclaration decl,Object data) {
048     // If the import actually import a Boolean class that overrides java.lang.Boolean
049     if decl.getImportedName().endsWith("Boolean"&& ! decl.getImportedName().equals("java.lang"))
050     {
051       customBoolean = true;
052     }
053     return super.visit(decl, data);
054   }
055 
056     @Override
057     public Object visit(ASTAllocationExpression node, Object data) {
058 
059       if ! customBoolean ) {
060           if (node.hasDescendantOfType(ASTArrayDimsAndInits.class)) {
061               return super.visit(node, data);
062           }
063           if (TypeHelper.isA((ASTClassOrInterfaceTypenode.jjtGetChild(0), Boolean.class)) {
064                 super.addViolation(data, node);
065                 return data;
066             }
067       }
068         return super.visit(node, data);
069     }
070 
071     @Override
072     public Object visit(ASTPrimaryPrefix node, Object data) {
073 
074       if ! customBoolean )
075       {
076           if (node.jjtGetNumChildren() == || !(node.jjtGetChild(0instanceof ASTName)) {
077               return super.visit(node, data);
078           }
079 
080           if ("Boolean.valueOf".equals(((ASTNamenode.jjtGetChild(0)).getImage())
081                   || "java.lang.Boolean.valueOf".equals(((ASTNamenode.jjtGetChild(0)).getImage())) {
082               ASTPrimaryExpression parent = (ASTPrimaryExpressionnode.jjtGetParent();
083               ASTPrimarySuffix suffix = parent.getFirstDescendantOfType(ASTPrimarySuffix.class);
084               if (suffix == null) {
085                   return super.visit(node, data);
086               }
087               ASTPrimaryPrefix prefix = suffix.getFirstDescendantOfType(ASTPrimaryPrefix.class);
088               if (prefix == null) {
089                   return super.visit(node, data);
090               }
091 
092               if (prefix.hasDescendantOfType(ASTBooleanLiteral.class)) {
093                   super.addViolation(data, node);
094                   return data;
095               }
096               ASTLiteral literal = prefix.getFirstDescendantOfType(ASTLiteral.class);
097               if (literal != null && ("\"true\"".equals(literal.getImage()) || "\"false\"".equals(literal.getImage()))) {
098                   super.addViolation(data, node);
099                   return data;
100               }
101           }
102       }
103         return super.visit(node, data);
104     }
105 }