Coverage Report - com.puppycrawl.tools.checkstyle.checks.blocks.RightCurlyCheck
 
Classes in this File Line Coverage Branch Coverage Complexity
RightCurlyCheck
93%
55/59
63%
29/46
5.6
 
 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.blocks;
 20  
 
 21  
 import com.puppycrawl.tools.checkstyle.api.DetailAST;
 22  
 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
 23  
 import com.puppycrawl.tools.checkstyle.api.Utils;
 24  
 import com.puppycrawl.tools.checkstyle.checks.AbstractOptionCheck;
 25  
 import com.puppycrawl.tools.checkstyle.checks.CheckUtils;
 26  
 
 27  
 /**
 28  
  * <p>
 29  
  * Checks the placement of right curly braces.
 30  
  * The policy to verify is specified using the {@link RightCurlyOption} class
 31  
  * and defaults to {@link RightCurlyOption#SAME}.
 32  
  * </p>
 33  
  * <p> By default the check will check the following tokens:
 34  
  *  {@link TokenTypes#LITERAL_TRY LITERAL_TRY}.
 35  
  *  {@link TokenTypes#LITERAL_CATCH LITERAL_CATCH},
 36  
  *  {@link TokenTypes#LITERAL_FINALLY LITERAL_FINALLY}.
 37  
  *  {@link TokenTypes#LITERAL_IF LITERAL_IF},
 38  
  *  {@link TokenTypes#LITERAL_ELSE LITERAL_ELSE},
 39  
  * </p>
 40  
  * <p>
 41  
  * An example of how to configure the check is:
 42  
  * </p>
 43  
  * <pre>
 44  
  * &lt;module name="RightCurly"/&gt;
 45  
  * </pre>
 46  
  * <p>
 47  
  * An example of how to configure the check with policy
 48  
  * {@link RightCurlyOption#ALONE} for <code>else</code> tokens is:
 49  
  * </p>
 50  
  * <pre>
 51  
  * &lt;module name="RightCurly"&gt;
 52  
  *     &lt;property name="tokens" value="LITERAL_ELSE"/&gt;
 53  
  *     &lt;property name="option" value="alone"/&gt;
 54  
  * &lt;/module&gt;
 55  
  * </pre>
 56  
  *
 57  
  * @author Oliver Burn
 58  
  * @author lkuehne
 59  
  * @author o_sukhodolsky
 60  
  * @version 2.0
 61  
  */
 62  
 public class RightCurlyCheck extends AbstractOptionCheck<RightCurlyOption>
 63  
 {
 64  
     /** Do we need to check if rculry starts line. */
 65  4
     private boolean mShouldStartLine = true;
 66  
 
 67  
     /**
 68  
      * Sets the right curly option to same.
 69  
      */
 70  
     public RightCurlyCheck()
 71  
     {
 72  4
         super(RightCurlyOption.SAME, RightCurlyOption.class);
 73  4
     }
 74  
 
 75  
     /**
 76  
      * Does the check need to check if rcurly starts line.
 77  
      * @param aFlag new value of this property.
 78  
      */
 79  
     public void setShouldStartLine(boolean aFlag)
 80  
     {
 81  1
         mShouldStartLine = aFlag;
 82  1
     }
 83  
 
 84  
     @Override
 85  
     public int[] getDefaultTokens()
 86  
     {
 87  4
         return new int[] {
 88  
             TokenTypes.LITERAL_TRY,
 89  
             TokenTypes.LITERAL_CATCH,
 90  
             TokenTypes.LITERAL_FINALLY,
 91  
             TokenTypes.LITERAL_IF,
 92  
             TokenTypes.LITERAL_ELSE,
 93  
         };
 94  
     }
 95  
 
 96  
     @Override
 97  
     public void visitToken(DetailAST aAST)
 98  
     {
 99  
         // Attempt to locate the tokens to do the check
 100  
         DetailAST rcurly;
 101  
         DetailAST lcurly;
 102  
         DetailAST nextToken;
 103  44
         boolean shouldCheckLastRcurly = false;
 104  
 
 105  44
         switch (aAST.getType()) {
 106  
         case TokenTypes.LITERAL_TRY:
 107  4
             lcurly = aAST.getFirstChild();
 108  4
             nextToken = lcurly.getNextSibling();
 109  4
             rcurly = lcurly.getLastChild();
 110  4
             break;
 111  
         case TokenTypes.LITERAL_CATCH:
 112  4
             nextToken = aAST.getNextSibling();
 113  4
             lcurly = aAST.getLastChild();
 114  4
             rcurly = lcurly.getLastChild();
 115  4
             if (nextToken == null) {
 116  0
                 shouldCheckLastRcurly = true;
 117  0
                 nextToken = getNextToken(aAST);
 118  
             }
 119  
             break;
 120  
         case TokenTypes.LITERAL_IF:
 121  20
             nextToken = aAST.findFirstToken(TokenTypes.LITERAL_ELSE);
 122  20
             if (nextToken != null) {
 123  12
                 lcurly = nextToken.getPreviousSibling();
 124  12
                 rcurly = lcurly.getLastChild();
 125  
             }
 126  
             else {
 127  8
                 shouldCheckLastRcurly = true;
 128  8
                 nextToken = getNextToken(aAST);
 129  8
                 lcurly = aAST.getLastChild();
 130  8
                 rcurly = lcurly.getLastChild();
 131  
             }
 132  8
             break;
 133  
         case TokenTypes.LITERAL_ELSE:
 134  12
             shouldCheckLastRcurly = true;
 135  12
             nextToken = getNextToken(aAST);
 136  12
             lcurly = aAST.getFirstChild();
 137  12
             rcurly = lcurly.getLastChild();
 138  12
             break;
 139  
         case TokenTypes.LITERAL_FINALLY:
 140  4
             shouldCheckLastRcurly = true;
 141  4
             nextToken = getNextToken(aAST);
 142  4
             lcurly = aAST.getFirstChild();
 143  4
             rcurly = lcurly.getLastChild();
 144  4
             break;
 145  
         default:
 146  0
             throw new RuntimeException("Unexpected token type ("
 147  
                     + TokenTypes.getTokenName(aAST.getType()) + ")");
 148  
         }
 149  
 
 150  44
         if ((rcurly == null) || (rcurly.getType() != TokenTypes.RCURLY)) {
 151  
             // we need to have both tokens to perform the check
 152  12
             return;
 153  
         }
 154  
 
 155  32
         if (shouldCheckLastRcurly) {
 156  16
             if (rcurly.getLineNo() == nextToken.getLineNo()) {
 157  4
                 log(rcurly, "line.alone", "}");
 158  
             }
 159  
         }
 160  16
         else if ((getAbstractOption() == RightCurlyOption.SAME)
 161  
             && (rcurly.getLineNo() != nextToken.getLineNo()))
 162  
         {
 163  8
             log(rcurly, "line.same", "}");
 164  
         }
 165  8
         else if ((getAbstractOption() == RightCurlyOption.ALONE)
 166  
                  && (rcurly.getLineNo() == nextToken.getLineNo()))
 167  
         {
 168  0
             log(rcurly, "line.alone", "}");
 169  
         }
 170  
 
 171  32
         if (!mShouldStartLine) {
 172  8
             return;
 173  
         }
 174  24
         final boolean startsLine =
 175  
             Utils.whitespaceBefore(rcurly.getColumnNo(),
 176  
                                    getLines()[rcurly.getLineNo() - 1]);
 177  
 
 178  24
         if (!startsLine && (lcurly.getLineNo() != rcurly.getLineNo())) {
 179  3
             log(rcurly, "line.new", "}");
 180  
         }
 181  24
     }
 182  
 
 183  
     /**
 184  
      * Finds next token after the given one.
 185  
      * @param aAST the given node.
 186  
      * @return the token which represents next lexical item.
 187  
      */
 188  
     private DetailAST getNextToken(DetailAST aAST)
 189  
     {
 190  24
         DetailAST next = null;
 191  24
         DetailAST parent = aAST;
 192  72
         while ((parent != null) && (next == null)) {
 193  48
             next = parent.getNextSibling();
 194  48
             parent = parent.getParent();
 195  
         }
 196  24
         return CheckUtils.getFirstNode(next);
 197  
     }
 198  
 }