Coverage Report - com.puppycrawl.tools.checkstyle.checks.naming.AbstractClassNameCheck
 
Classes in this File Line Coverage Branch Coverage Complexity
AbstractClassNameCheck
95%
20/21
92%
13/14
1.667
 
 1  
 ////////////////////////////////////////////////////////////////////////////////
 2  
 // checkstyle: Checks Java source code for adherence to a set of rules.
 3  
 // Copyright (C) 2001-2014  Oliver Burn
 4  
 //
 5  
 // This library is free software; you can redistribute it and/or
 6  
 // modify it under the terms of the GNU Lesser General Public
 7  
 // License as published by the Free Software Foundation; either
 8  
 // version 2.1 of the License, or (at your option) any later version.
 9  
 //
 10  
 // This library is distributed in the hope that it will be useful,
 11  
 // but WITHOUT ANY WARRANTY; without even the implied warranty of
 12  
 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 13  
 // Lesser General Public License for more details.
 14  
 //
 15  
 // You should have received a copy of the GNU Lesser General Public
 16  
 // License along with this library; if not, write to the Free Software
 17  
 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 18  
 ////////////////////////////////////////////////////////////////////////////////
 19  
 package com.puppycrawl.tools.checkstyle.checks.naming;
 20  
 
 21  
 import com.puppycrawl.tools.checkstyle.api.DetailAST;
 22  
 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
 23  
 import com.puppycrawl.tools.checkstyle.checks.AbstractFormatCheck;
 24  
 
 25  
 /**
 26  
  * <p>
 27  
  * Ensures that the names of abstract classes conforming to some
 28  
  * regular expression and check that <code>abstract</code> modifier exists.
 29  
  * </p>
 30  
  * <p>
 31  
  * Rationale: Abstract classes are convenience base class
 32  
  * implementations of interfaces, not types as such. As such
 33  
  * they should be named to indicate this. Also if names of classes
 34  
  * starts with 'Abstract' it's very convenient that they will
 35  
  * have abstract modifier.
 36  
  * </p>
 37  
  *
 38  
  * @author <a href="mailto:simon@redhillconsulting.com.au">Simon Harris</a>
 39  
  * @author <a href="mailto:solid.danil@gmail.com">Danil Lopatin</a>
 40  
  */
 41  
 public final class AbstractClassNameCheck extends AbstractFormatCheck
 42  
 {
 43  
     /** Default format for abstract class names */
 44  
     private static final String DEFAULT_FORMAT = "^Abstract.*$|^.*Factory$";
 45  
 
 46  
     /** whether to ignore checking the modifier */
 47  
     private boolean mIgnoreModifier;
 48  
 
 49  
     /** whether to ignore checking the name */
 50  
     private boolean mIgnoreName;
 51  
 
 52  
     /** Creates new instance of the check. */
 53  
     public AbstractClassNameCheck()
 54  
     {
 55  3
         super(DEFAULT_FORMAT);
 56  3
     }
 57  
 
 58  
     /**
 59  
      * Whether to ignore checking for the <code>abstract</code> modifier.
 60  
      * @param aValue new value
 61  
      */
 62  
     public void setIgnoreModifier(boolean aValue)
 63  
     {
 64  3
         mIgnoreModifier = aValue;
 65  3
     }
 66  
 
 67  
     /**
 68  
      * Whether to ignore checking the name.
 69  
      * @param aValue new value.
 70  
      */
 71  
     public void setIgnoreName(boolean aValue)
 72  
     {
 73  3
         mIgnoreName = aValue;
 74  3
     }
 75  
 
 76  
     @Override
 77  
     public int[] getDefaultTokens()
 78  
     {
 79  3
         return new int[]{TokenTypes.CLASS_DEF};
 80  
     }
 81  
 
 82  
     @Override
 83  
     public int[] getRequiredTokens()
 84  
     {
 85  0
         return getDefaultTokens();
 86  
     }
 87  
 
 88  
     @Override
 89  
     public void visitToken(DetailAST aAST)
 90  
     {
 91  42
         if (TokenTypes.CLASS_DEF == aAST.getType()) {
 92  42
             visitClassDef(aAST);
 93  
         }
 94  42
     }
 95  
 
 96  
     /**
 97  
      * Checks class definition.
 98  
      * @param aAST class definition for check.
 99  
      */
 100  
     private void visitClassDef(DetailAST aAST)
 101  
     {
 102  42
         final String className =
 103  
             aAST.findFirstToken(TokenTypes.IDENT).getText();
 104  42
         if (isAbstract(aAST)) {
 105  
             // if class has abstract modifier
 106  27
             if (!mIgnoreName && !isMatchingClassName(className)) {
 107  8
                 log(aAST.getLineNo(), aAST.getColumnNo(),
 108  
                     "illegal.abstract.class.name", className, getFormat());
 109  
             }
 110  
         }
 111  15
         else if (!mIgnoreModifier && isMatchingClassName(className)) {
 112  8
             log(aAST.getLineNo(), aAST.getColumnNo(),
 113  
                 "no.abstract.class.modifier", className);
 114  
         }
 115  42
     }
 116  
 
 117  
     /**
 118  
      * @param aAST class definition for check.
 119  
      * @return true if a given class declared as abstract.
 120  
      */
 121  
     private boolean isAbstract(DetailAST aAST)
 122  
     {
 123  42
         final DetailAST abstractAST = aAST.findFirstToken(TokenTypes.MODIFIERS)
 124  
             .findFirstToken(TokenTypes.ABSTRACT);
 125  
 
 126  42
         return abstractAST != null;
 127  
     }
 128  
 
 129  
     /**
 130  
      * @param aClassName class name for check.
 131  
      * @return true if class name matches format of abstract class names.
 132  
      */
 133  
     private boolean isMatchingClassName(String aClassName)
 134  
     {
 135  28
         return getRegexp().matcher(aClassName).find();
 136  
     }
 137  
 }