Coverage Report - com.puppycrawl.tools.checkstyle.checks.coding.ParameterAssignmentCheck
 
Classes in this File Line Coverage Branch Coverage Complexity
ParameterAssignmentCheck
93%
41/44
32%
17/52
5.091
 
 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.coding;
 20  
 
 21  
 import com.google.common.collect.Sets;
 22  
 import com.puppycrawl.tools.checkstyle.api.Check;
 23  
 import com.puppycrawl.tools.checkstyle.api.DetailAST;
 24  
 import com.puppycrawl.tools.checkstyle.api.FastStack;
 25  
 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
 26  
 import java.util.Set;
 27  
 
 28  
 /**
 29  
  * <p>
 30  
  * Disallow assignment of parameters.
 31  
  * </p>
 32  
  * <p>
 33  
  * Rationale:
 34  
  * Parameter assignment is often considered poor
 35  
  * programming practice. Forcing developers to declare
 36  
  * parameters as final is often onerous. Having a check
 37  
  * ensure that parameters are never assigned would give
 38  
  * the best of both worlds.
 39  
  * </p>
 40  
  * @author <a href="mailto:simon@redhillconsulting.com.au">Simon Harris</a>
 41  
  */
 42  1
 public final class ParameterAssignmentCheck extends Check
 43  
 {
 44  
     /** Stack of methods' parameters. */
 45  1
     private final FastStack<Set<String>> mParameterNamesStack =
 46  
         FastStack.newInstance();
 47  
     /** Current set of perameters. */
 48  
     private Set<String> mParameterNames;
 49  
 
 50  
     @Override
 51  
     public int[] getDefaultTokens()
 52  
     {
 53  1
         return new int[] {
 54  
             TokenTypes.CTOR_DEF,
 55  
             TokenTypes.METHOD_DEF,
 56  
             TokenTypes.ASSIGN,
 57  
             TokenTypes.PLUS_ASSIGN,
 58  
             TokenTypes.MINUS_ASSIGN,
 59  
             TokenTypes.STAR_ASSIGN,
 60  
             TokenTypes.DIV_ASSIGN,
 61  
             TokenTypes.MOD_ASSIGN,
 62  
             TokenTypes.SR_ASSIGN,
 63  
             TokenTypes.BSR_ASSIGN,
 64  
             TokenTypes.SL_ASSIGN,
 65  
             TokenTypes.BAND_ASSIGN,
 66  
             TokenTypes.BXOR_ASSIGN,
 67  
             TokenTypes.BOR_ASSIGN,
 68  
             TokenTypes.INC,
 69  
             TokenTypes.POST_INC,
 70  
             TokenTypes.DEC,
 71  
             TokenTypes.POST_DEC,
 72  
         };
 73  
     }
 74  
 
 75  
     @Override
 76  
     public int[] getRequiredTokens()
 77  
     {
 78  0
         return getDefaultTokens();
 79  
     }
 80  
 
 81  
     @Override
 82  
     public void beginTree(DetailAST aRootAST)
 83  
     {
 84  
         // clear data
 85  1
         mParameterNamesStack.clear();
 86  1
         mParameterNames = null;
 87  1
     }
 88  
 
 89  
     @Override
 90  
     public void visitToken(DetailAST aAST)
 91  
     {
 92  13
         switch (aAST.getType()) {
 93  
         case TokenTypes.CTOR_DEF:
 94  
         case TokenTypes.METHOD_DEF:
 95  3
             visitMethodDef(aAST);
 96  3
             break;
 97  
         case TokenTypes.ASSIGN:
 98  
         case TokenTypes.PLUS_ASSIGN:
 99  
         case TokenTypes.MINUS_ASSIGN:
 100  
         case TokenTypes.STAR_ASSIGN:
 101  
         case TokenTypes.DIV_ASSIGN:
 102  
         case TokenTypes.MOD_ASSIGN:
 103  
         case TokenTypes.SR_ASSIGN:
 104  
         case TokenTypes.BSR_ASSIGN:
 105  
         case TokenTypes.SL_ASSIGN:
 106  
         case TokenTypes.BAND_ASSIGN:
 107  
         case TokenTypes.BXOR_ASSIGN:
 108  
         case TokenTypes.BOR_ASSIGN:
 109  7
             visitAssign(aAST);
 110  7
             break;
 111  
         case TokenTypes.INC:
 112  
         case TokenTypes.POST_INC:
 113  
         case TokenTypes.DEC:
 114  
         case TokenTypes.POST_DEC:
 115  3
             visitIncDec(aAST);
 116  3
             break;
 117  
         default:
 118  0
             throw new IllegalStateException(aAST.toString());
 119  
         }
 120  13
     }
 121  
 
 122  
     @Override
 123  
     public void leaveToken(DetailAST aAST)
 124  
     {
 125  13
         switch (aAST.getType()) {
 126  
         case TokenTypes.CTOR_DEF:
 127  
         case TokenTypes.METHOD_DEF:
 128  3
             leaveMethodDef();
 129  3
             break;
 130  
         case TokenTypes.ASSIGN:
 131  
         case TokenTypes.PLUS_ASSIGN:
 132  
         case TokenTypes.MINUS_ASSIGN:
 133  
         case TokenTypes.STAR_ASSIGN:
 134  
         case TokenTypes.DIV_ASSIGN:
 135  
         case TokenTypes.MOD_ASSIGN:
 136  
         case TokenTypes.SR_ASSIGN:
 137  
         case TokenTypes.BSR_ASSIGN:
 138  
         case TokenTypes.SL_ASSIGN:
 139  
         case TokenTypes.BAND_ASSIGN:
 140  
         case TokenTypes.BXOR_ASSIGN:
 141  
         case TokenTypes.BOR_ASSIGN:
 142  
         case TokenTypes.INC:
 143  
         case TokenTypes.POST_INC:
 144  
         case TokenTypes.DEC:
 145  
         case TokenTypes.POST_DEC:
 146  
             // Do nothing
 147  10
             break;
 148  
         default:
 149  0
             throw new IllegalStateException(aAST.toString());
 150  
         }
 151  13
     }
 152  
 
 153  
     /**
 154  
      * Ckecks if this is assignments of parameter.
 155  
      * @param aAST assignment to check.
 156  
      */
 157  
     private void visitAssign(DetailAST aAST)
 158  
     {
 159  7
         checkIdent(aAST);
 160  7
     }
 161  
 
 162  
     /**
 163  
      * Checks if this is increment/decrement of parameter.
 164  
      * @param aAST dec/inc to check.
 165  
      */
 166  
     private void visitIncDec(DetailAST aAST)
 167  
     {
 168  3
         checkIdent(aAST);
 169  3
     }
 170  
 
 171  
     /**
 172  
      * Check if ident is parameter.
 173  
      * @param aAST ident to check.
 174  
      */
 175  
     private void checkIdent(DetailAST aAST)
 176  
     {
 177  10
         if ((mParameterNames != null) && !mParameterNames.isEmpty()) {
 178  9
             final DetailAST identAST = aAST.getFirstChild();
 179  
 
 180  9
             if ((identAST != null)
 181  
                 && (identAST.getType() == TokenTypes.IDENT)
 182  
                 && mParameterNames.contains(identAST.getText()))
 183  
             {
 184  4
                 log(aAST.getLineNo(), aAST.getColumnNo(),
 185  
                     "parameter.assignment", identAST.getText());
 186  
             }
 187  
         }
 188  10
     }
 189  
 
 190  
     /**
 191  
      * Creates new set of parameters and store old one in stack.
 192  
      * @param aAST a method to process.
 193  
      */
 194  
     private void visitMethodDef(DetailAST aAST)
 195  
     {
 196  3
         mParameterNamesStack.push(mParameterNames);
 197  3
         mParameterNames = Sets.newHashSet();
 198  
 
 199  3
         visitMethodParameters(aAST.findFirstToken(TokenTypes.PARAMETERS));
 200  3
     }
 201  
 
 202  
     /** Restores old set of parameters. */
 203  
     private void leaveMethodDef()
 204  
     {
 205  3
         mParameterNames = mParameterNamesStack.pop();
 206  3
     }
 207  
 
 208  
     /**
 209  
      * Creates new parameter set for given method.
 210  
      * @param aAST a method for process.
 211  
      */
 212  
     private void visitMethodParameters(DetailAST aAST)
 213  
     {
 214  3
         DetailAST parameterDefAST =
 215  
             aAST.findFirstToken(TokenTypes.PARAMETER_DEF);
 216  
 
 217  7
         for (; parameterDefAST != null;
 218  4
              parameterDefAST = parameterDefAST.getNextSibling())
 219  
         {
 220  4
             if (parameterDefAST.getType() == TokenTypes.PARAMETER_DEF) {
 221  3
                 final DetailAST param =
 222  
                     parameterDefAST.findFirstToken(TokenTypes.IDENT);
 223  3
                 mParameterNames.add(param.getText());
 224  
             }
 225  
         }
 226  3
     }
 227  
 }