Coverage Report - com.puppycrawl.tools.checkstyle.checks.whitespace.MethodParamPadCheck
 
Classes in this File Line Coverage Branch Coverage Complexity
MethodParamPadCheck
100%
28/28
100%
16/16
2.667
 
 1  
 ////////////////////////////////////////////////////////////////////////////////
 2  
 // checkstyle: Checks Java source code for adherence to a set of rules.
 3  
 // Copyright (C) 2001-2017 the original author or authors.
 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  
 
 20  
 package com.puppycrawl.tools.checkstyle.checks.whitespace;
 21  
 
 22  
 import java.util.Locale;
 23  
 
 24  
 import com.puppycrawl.tools.checkstyle.StatelessCheck;
 25  
 import com.puppycrawl.tools.checkstyle.api.AbstractCheck;
 26  
 import com.puppycrawl.tools.checkstyle.api.DetailAST;
 27  
 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
 28  
 import com.puppycrawl.tools.checkstyle.utils.CommonUtils;
 29  
 
 30  
 /**
 31  
  * <p>
 32  
  * Checks the padding between the identifier of a method definition,
 33  
  * constructor definition, method call, or constructor invocation;
 34  
  * and the left parenthesis of the parameter list.
 35  
  * That is, if the identifier and left parenthesis are on the same line,
 36  
  * checks whether a space is required immediately after the identifier or
 37  
  * such a space is forbidden.
 38  
  * If they are not on the same line, reports an error, unless configured to
 39  
  * allow line breaks.
 40  
  * </p>
 41  
  * <p> By default the check will check the following tokens:
 42  
  *  {@link TokenTypes#CTOR_DEF CTOR_DEF},
 43  
  *  {@link TokenTypes#LITERAL_NEW LITERAL_NEW},
 44  
  *  {@link TokenTypes#METHOD_CALL METHOD_CALL},
 45  
  *  {@link TokenTypes#METHOD_DEF METHOD_DEF},
 46  
  *  {@link TokenTypes#SUPER_CTOR_CALL SUPER_CTOR_CALL}.
 47  
  * </p>
 48  
  * <p>
 49  
  * An example of how to configure the check is:
 50  
  * </p>
 51  
  * <pre>
 52  
  * &lt;module name="MethodParamPad"/&gt;
 53  
  * </pre>
 54  
  * <p> An example of how to configure the check to require a space
 55  
  * after the identifier of a method definition, except if the left
 56  
  * parenthesis occurs on a new line, is:
 57  
  * </p>
 58  
  * <pre>
 59  
  * &lt;module name="MethodParamPad"&gt;
 60  
  *     &lt;property name="tokens" value="METHOD_DEF"/&gt;
 61  
  *     &lt;property name="option" value="space"/&gt;
 62  
  *     &lt;property name="allowLineBreaks" value="true"/&gt;
 63  
  * &lt;/module&gt;
 64  
  * </pre>
 65  
  * @author Rick Giles
 66  
  */
 67  
 
 68  
 @StatelessCheck
 69  17
 public class MethodParamPadCheck
 70  
     extends AbstractCheck {
 71  
 
 72  
     /**
 73  
      * A key is pointing to the warning message text in "messages.properties"
 74  
      * file.
 75  
      */
 76  
     public static final String MSG_LINE_PREVIOUS = "line.previous";
 77  
 
 78  
     /**
 79  
      * A key is pointing to the warning message text in "messages.properties"
 80  
      * file.
 81  
      */
 82  
     public static final String MSG_WS_PRECEDED = "ws.preceded";
 83  
 
 84  
     /**
 85  
      * A key is pointing to the warning message text in "messages.properties"
 86  
      * file.
 87  
      */
 88  
     public static final String MSG_WS_NOT_PRECEDED = "ws.notPreceded";
 89  
 
 90  
     /**
 91  
      * Whether whitespace is allowed if the method identifier is at a
 92  
      * linebreak.
 93  
      */
 94  
     private boolean allowLineBreaks;
 95  
 
 96  
     /** The policy to enforce. */
 97  17
     private PadOption option = PadOption.NOSPACE;
 98  
 
 99  
     @Override
 100  
     public int[] getDefaultTokens() {
 101  13
         return getAcceptableTokens();
 102  
     }
 103  
 
 104  
     @Override
 105  
     public int[] getAcceptableTokens() {
 106  21
         return new int[] {
 107  
             TokenTypes.CTOR_DEF,
 108  
             TokenTypes.LITERAL_NEW,
 109  
             TokenTypes.METHOD_CALL,
 110  
             TokenTypes.METHOD_DEF,
 111  
             TokenTypes.SUPER_CTOR_CALL,
 112  
             TokenTypes.ENUM_CONSTANT_DEF,
 113  
         };
 114  
     }
 115  
 
 116  
     @Override
 117  
     public int[] getRequiredTokens() {
 118  17
         return CommonUtils.EMPTY_INT_ARRAY;
 119  
     }
 120  
 
 121  
     @Override
 122  
     public void visitToken(DetailAST ast) {
 123  
         final DetailAST parenAST;
 124  103
         if (ast.getType() == TokenTypes.METHOD_CALL) {
 125  38
             parenAST = ast;
 126  
         }
 127  
         else {
 128  65
             parenAST = ast.findFirstToken(TokenTypes.LPAREN);
 129  
             // array construction => parenAST == null
 130  
         }
 131  
 
 132  103
         if (parenAST != null) {
 133  99
             final String line = getLines()[parenAST.getLineNo() - 1];
 134  99
             if (CommonUtils.hasWhitespaceBefore(parenAST.getColumnNo(), line)) {
 135  27
                 if (!allowLineBreaks) {
 136  18
                     log(parenAST, MSG_LINE_PREVIOUS, parenAST.getText());
 137  
                 }
 138  
             }
 139  
             else {
 140  72
                 final int before = parenAST.getColumnNo() - 1;
 141  72
                 if (option == PadOption.NOSPACE
 142  44
                     && Character.isWhitespace(line.charAt(before))) {
 143  18
                     log(parenAST, MSG_WS_PRECEDED, parenAST.getText());
 144  
                 }
 145  54
                 else if (option == PadOption.SPACE
 146  28
                          && !Character.isWhitespace(line.charAt(before))) {
 147  13
                     log(parenAST, MSG_WS_NOT_PRECEDED, parenAST.getText());
 148  
                 }
 149  
             }
 150  
         }
 151  103
     }
 152  
 
 153  
     /**
 154  
      * Control whether whitespace is flagged at line breaks.
 155  
      * @param allowLineBreaks whether whitespace should be
 156  
      *     flagged at line breaks.
 157  
      */
 158  
     public void setAllowLineBreaks(boolean allowLineBreaks) {
 159  2
         this.allowLineBreaks = allowLineBreaks;
 160  2
     }
 161  
 
 162  
     /**
 163  
      * Set the option to enforce.
 164  
      * @param optionStr string to decode option from
 165  
      * @throws IllegalArgumentException if unable to decode
 166  
      */
 167  
     public void setOption(String optionStr) {
 168  
         try {
 169  4
             option = PadOption.valueOf(optionStr.trim().toUpperCase(Locale.ENGLISH));
 170  
         }
 171  1
         catch (IllegalArgumentException iae) {
 172  1
             throw new IllegalArgumentException("unable to parse " + optionStr, iae);
 173  3
         }
 174  3
     }
 175  
 }