Coverage Report - com.puppycrawl.tools.checkstyle.checks.whitespace.ParenPadCheck
 
Classes in this File Line Coverage Branch Coverage Complexity
ParenPadCheck
100%
23/23
86%
31/36
5
 
 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  
 
 20  
 package com.puppycrawl.tools.checkstyle.checks.whitespace;
 21  
 
 22  
 import com.puppycrawl.tools.checkstyle.api.DetailAST;
 23  
 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
 24  
 
 25  
 /**
 26  
  * <p>Checks the padding of parentheses; that is whether a space is required
 27  
  * after a left parenthesis and before a right parenthesis, or such spaces are
 28  
  * forbidden, with the exception that it does
 29  
  * not check for padding of the right parenthesis  at an empty for iterator.
 30  
  * Use Check {@link EmptyForIteratorPadCheck EmptyForIteratorPad} to validate
 31  
  * empty for iterators.
 32  
  * <p>
 33  
  * </p>
 34  
  * The policy to verify is specified using the {@link PadOption} class and
 35  
  * defaults to {@link PadOption#NOSPACE}.
 36  
  * </p>
 37  
  * <p> By default the check will check parentheses that occur with the following
 38  
  * tokens:
 39  
  *  {@link TokenTypes#CTOR_CALL CTOR_CALL},
 40  
  *  {@link TokenTypes#LPAREN LPAREN},
 41  
  *  {@link TokenTypes#METHOD_CALL METHOD_CALL},
 42  
  *  {@link TokenTypes#RPAREN RPAREN},
 43  
  *  {@link TokenTypes#SUPER_CTOR_CALL SUPER_CTOR_CALL},
 44  
  * </p>
 45  
  * <p>
 46  
  * An example of how to configure the check is:
 47  
  * </p>
 48  
  * <pre>
 49  
  * &lt;module name="ParenPad"/&gt;
 50  
  * </pre>
 51  
  * <p>
 52  
  * An example of how to configure the check to require spaces for the
 53  
  * parentheses of constructor, method, and super constructor invocations is:
 54  
  * </p>
 55  
  * <pre>
 56  
  * &lt;module name="ParenPad"&gt;
 57  
  *     &lt;property name="tokens"
 58  
  *               value="CTOR_CALL, METHOD_CALL, SUPER_CTOR_CALL"/&gt;
 59  
  *     &lt;property name="option" value="space"/&gt;
 60  
  * &lt;/module&gt;
 61  
  * </pre>
 62  
  * @author Oliver Burn
 63  
  * @version 1.0
 64  
  */
 65  5
 public class ParenPadCheck extends AbstractParenPadCheck
 66  
 {
 67  
     @Override
 68  
     public int[] getDefaultTokens()
 69  
     {
 70  5
         return new int[] {TokenTypes.RPAREN,
 71  
                           TokenTypes.LPAREN,
 72  
                           TokenTypes.CTOR_CALL,
 73  
                           TokenTypes.SUPER_CTOR_CALL,
 74  
                           TokenTypes.METHOD_CALL,
 75  
         };
 76  
     }
 77  
 
 78  
     @Override
 79  
     public void visitToken(DetailAST aAST)
 80  
     {
 81  268
         DetailAST theAst = aAST;
 82  
         // Strange logic in this method to guard against checking RPAREN tokens
 83  
         // that are associated with a TYPECAST token.
 84  268
         if (theAst.getType() != TokenTypes.RPAREN) {
 85  130
             if ((theAst.getType() == TokenTypes.CTOR_CALL)
 86  
                 || (theAst.getType() == TokenTypes.SUPER_CTOR_CALL))
 87  
             {
 88  2
                 theAst = theAst.getFirstChild();
 89  
             }
 90  130
             if (!isPreceedsEmptyForInit(theAst)) {
 91  124
                 processLeft(theAst);
 92  
             }
 93  
         }
 94  138
         else if (((theAst.getParent() == null)
 95  
                  || (theAst.getParent().getType() != TokenTypes.TYPECAST)
 96  
                  || (theAst.getParent().findFirstToken(TokenTypes.RPAREN)
 97  
                      != theAst))
 98  
                  && !isFollowsEmptyForIterator(theAst))
 99  
         {
 100  118
             processRight(theAst);
 101  
         }
 102  268
     }
 103  
 
 104  
     /**
 105  
      * @param aAST the token to check
 106  
      * @return whether a token follows an empty for iterator
 107  
      */
 108  
     private boolean isFollowsEmptyForIterator(DetailAST aAST)
 109  
     {
 110  128
         boolean followsEmptyForIterator = false;
 111  128
         final DetailAST parent = aAST.getParent();
 112  
         //Only traditional for statements are examined, not for-each statements
 113  128
         if ((parent != null)
 114  
             && (parent.getType() == TokenTypes.LITERAL_FOR)
 115  
             && (parent.findFirstToken(TokenTypes.FOR_EACH_CLAUSE) == null))
 116  
         {
 117  28
             final DetailAST forIterator =
 118  
                 parent.findFirstToken(TokenTypes.FOR_ITERATOR);
 119  28
             followsEmptyForIterator = (forIterator.getChildCount() == 0)
 120  
                 && (aAST == forIterator.getNextSibling());
 121  
         }
 122  128
         return followsEmptyForIterator;
 123  
     }
 124  
 
 125  
     /**
 126  
      * @param aAST the token to check
 127  
      * @return whether a token preceeds an empty for initializer
 128  
      */
 129  
     private boolean isPreceedsEmptyForInit(DetailAST aAST)
 130  
     {
 131  130
         boolean preceedsEmptyForInintializer = false;
 132  130
         final DetailAST parent = aAST.getParent();
 133  
         //Only traditional for statements are examined, not for-each statements
 134  130
         if ((parent != null)
 135  
             && (parent.getType() == TokenTypes.LITERAL_FOR)
 136  
             && (parent.findFirstToken(TokenTypes.FOR_EACH_CLAUSE) == null))
 137  
         {
 138  28
             final DetailAST forIterator =
 139  
                     parent.findFirstToken(TokenTypes.FOR_INIT);
 140  28
             preceedsEmptyForInintializer = (forIterator.getChildCount() == 0)
 141  
                     && (aAST == forIterator.getPreviousSibling());
 142  
         }
 143  130
         return preceedsEmptyForInintializer;
 144  
     }
 145  
 }