Coverage Report - com.puppycrawl.tools.checkstyle.checks.indentation.BlockParentHandler
 
Classes in this File Line Coverage Branch Coverage Complexity
BlockParentHandler
98%
63/64
88%
44/50
2.524
 
 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.indentation;
 20  
 
 21  
 import com.puppycrawl.tools.checkstyle.api.DetailAST;
 22  
 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
 23  
 
 24  
 /**
 25  
  * Handler for parents of blocks ('if', 'else', 'while', etc).
 26  
  * <P>
 27  
  * The "block" handler classes use a common superclass BlockParentHandler,
 28  
  * employing the Template Method pattern.
 29  
  * <P>
 30  
  * <UL>
 31  
  *   <LI>template method to get the lcurly</LI>
 32  
  *   <LI>template method to get the rcurly</LI>
 33  
  *   <LI>if curlys aren't present, then template method to get expressions
 34  
  *       is called</LI>
 35  
  *   <LI>now all the repetitous code which checks for BOL, if curlys are on
 36  
  *       same line, etc. can be collapsed into  the superclass</LI>
 37  
  * </UL>
 38  
  *
 39  
  * @author jrichard
 40  
  */
 41  
 public class BlockParentHandler extends ExpressionHandler
 42  
 {
 43  
     /**
 44  
      * Children checked by parent handlers.
 45  
      */
 46  1
     private static final int[] CHECKED_CHILDREN = new int[] {
 47  
         TokenTypes.VARIABLE_DEF,
 48  
         TokenTypes.EXPR,
 49  
         TokenTypes.OBJBLOCK,
 50  
         TokenTypes.LITERAL_BREAK,
 51  
         TokenTypes.LITERAL_RETURN,
 52  
         TokenTypes.LITERAL_THROW,
 53  
         TokenTypes.LITERAL_CONTINUE,
 54  
     };
 55  
 
 56  
     /**
 57  
      * Returns array of token types which should be checked among childrens.
 58  
      * @return array of token types to check.
 59  
      */
 60  
     protected int[] getCheckedChildren()
 61  
     {
 62  451
         return CHECKED_CHILDREN;
 63  
     }
 64  
 
 65  
     /**
 66  
      * Construct an instance of this handler with the given indentation check,
 67  
      * name, abstract syntax tree, and parent handler.
 68  
      *
 69  
      * @param aIndentCheck   the indentation check
 70  
      * @param aName          the name of the handler
 71  
      * @param aAst           the abstract syntax tree
 72  
      * @param aParent        the parent handler
 73  
      */
 74  
     public BlockParentHandler(IndentationCheck aIndentCheck,
 75  
         String aName, DetailAST aAst, ExpressionHandler aParent)
 76  
     {
 77  1277
         super(aIndentCheck, aName, aAst, aParent);
 78  1277
     }
 79  
 
 80  
     /**
 81  
      * Get the top level expression being managed by this handler.
 82  
      *
 83  
      * @return the top level expression
 84  
      */
 85  
     protected DetailAST getToplevelAST()
 86  
     {
 87  245
         return getMainAst();
 88  
     }
 89  
 
 90  
     /**
 91  
      * Check the indent of the top level token.
 92  
      */
 93  
     protected void checkToplevelToken()
 94  
     {
 95  603
         final DetailAST toplevel = getToplevelAST();
 96  
 
 97  603
         if ((toplevel == null)
 98  
             || getLevel().accept(expandedTabsColumnNo(toplevel)))
 99  
         {
 100  552
             return;
 101  
         }
 102  51
         if (!toplevelMustStartLine() && !startsLine(toplevel)) {
 103  16
             return;
 104  
         }
 105  35
         logError(toplevel, "", expandedTabsColumnNo(toplevel));
 106  35
     }
 107  
 
 108  
     /**
 109  
      * Determines if the top level token must start the line.
 110  
      *
 111  
      * @return true
 112  
      */
 113  
     protected boolean toplevelMustStartLine()
 114  
     {
 115  29
         return true;
 116  
     }
 117  
 
 118  
     /**
 119  
      * Determines if this block expression has curly braces.
 120  
      *
 121  
      * @return true if curly braces are present, false otherwise
 122  
      */
 123  
     protected boolean hasCurlys()
 124  
     {
 125  1288
         return (getLCurly() != null) && (getRCurly() != null);
 126  
     }
 127  
 
 128  
     /**
 129  
      * Get the left curly brace portion of the expression we are handling.
 130  
      *
 131  
      * @return the left curly brace expression
 132  
      */
 133  
     protected DetailAST getLCurly()
 134  
     {
 135  1953
         return getMainAst().findFirstToken(TokenTypes.SLIST);
 136  
     }
 137  
 
 138  
     /**
 139  
      * Get the right curly brace portion of the expression we are handling.
 140  
      *
 141  
      * @return the right curly brace expression
 142  
      */
 143  
     protected DetailAST getRCurly()
 144  
     {
 145  1416
         final DetailAST slist = getMainAst().findFirstToken(TokenTypes.SLIST);
 146  1416
         if (slist == null) {
 147  0
             return null;
 148  
         }
 149  
 
 150  1416
         return slist.findFirstToken(TokenTypes.RCURLY);
 151  
     }
 152  
 
 153  
     /**
 154  
      * Check the indentation of the left curly brace.
 155  
      */
 156  
     protected void checkLCurly()
 157  
     {
 158  
         // the lcurly can either be at the correct indentation, or nested
 159  
         // with a previous expression
 160  559
         final DetailAST lcurly = getLCurly();
 161  559
         final int lcurlyPos = expandedTabsColumnNo(lcurly);
 162  
 
 163  559
         if ((lcurly == null)
 164  
             || curlyLevel().accept(lcurlyPos)
 165  
             || !startsLine(lcurly))
 166  
         {
 167  517
             return;
 168  
         }
 169  
 
 170  42
         logError(lcurly, "lcurly", lcurlyPos);
 171  42
     }
 172  
 
 173  
     /**
 174  
      * Get the expected indentation level for the curly braces.
 175  
      *
 176  
      * @return the curly brace indentation level
 177  
      */
 178  
     private IndentLevel curlyLevel()
 179  
     {
 180  1195
         return new IndentLevel(getLevel(), getBraceAdjustement());
 181  
     }
 182  
 
 183  
     /**
 184  
      * Determines if the right curly brace must be at the start of the line.
 185  
      *
 186  
      * @return true
 187  
      */
 188  
     protected boolean rcurlyMustStart()
 189  
     {
 190  95
         return true;
 191  
     }
 192  
 
 193  
     /**
 194  
      * Determines if child elements within the expression may be nested.
 195  
      *
 196  
      * @return false
 197  
      */
 198  
     protected boolean childrenMayNest()
 199  
     {
 200  497
         return false;
 201  
     }
 202  
 
 203  
     /**
 204  
      * Check the indentation of the right curly brace.
 205  
      */
 206  
     protected void checkRCurly()
 207  
     {
 208  
         // the rcurly can either be at the correct indentation, or
 209  
         // on the same line as the lcurly
 210  559
         final DetailAST lcurly = getLCurly();
 211  559
         final DetailAST rcurly = getRCurly();
 212  559
         final int rcurlyPos = expandedTabsColumnNo(rcurly);
 213  
 
 214  559
         if ((rcurly == null)
 215  
             || curlyLevel().accept(rcurlyPos)
 216  
             || (!rcurlyMustStart() && !startsLine(rcurly))
 217  
             || areOnSameLine(rcurly, lcurly))
 218  
         {
 219  482
             return;
 220  
         }
 221  77
         logError(rcurly, "rcurly", rcurlyPos, curlyLevel());
 222  77
     }
 223  
 
 224  
     /**
 225  
      * Get the child element that is not a list of statements.
 226  
      *
 227  
      * @return the non-list child element
 228  
      */
 229  
     protected DetailAST getNonlistChild()
 230  
     {
 231  26
         return getMainAst().findFirstToken(
 232  
             TokenTypes.RPAREN).getNextSibling();
 233  
     }
 234  
 
 235  
     /**
 236  
      * Check the indentation level of a child that is not a list of statements.
 237  
      */
 238  
     private void checkNonlistChild()
 239  
     {
 240  
         // TODO: look for SEMI and check for it here?
 241  59
         final DetailAST nonlist = getNonlistChild();
 242  59
         if (nonlist == null) {
 243  12
             return;
 244  
         }
 245  
 
 246  47
         final IndentLevel expected =
 247  
             new IndentLevel(getLevel(), getBasicOffset());
 248  47
         checkExpressionSubtree(nonlist, expected, false, false);
 249  47
     }
 250  
 
 251  
     /**
 252  
      * Get the child element representing the list of statements.
 253  
      *
 254  
      * @return the statement list child
 255  
      */
 256  
     protected DetailAST getListChild()
 257  
     {
 258  401
         return getMainAst().findFirstToken(TokenTypes.SLIST);
 259  
     }
 260  
 
 261  
     /**
 262  
      * Get the right parenthesis portion of the expression we are handling.
 263  
      *
 264  
      * @return the right parenthis expression
 265  
      */
 266  
     protected DetailAST getRParen()
 267  
     {
 268  640
         return getMainAst().findFirstToken(TokenTypes.RPAREN);
 269  
     }
 270  
 
 271  
     /**
 272  
      * Get the left parenthesis portion of the expression we are handling.
 273  
      *
 274  
      * @return the left parenthis expression
 275  
      */
 276  
     protected DetailAST getLParen()
 277  
     {
 278  1280
         return getMainAst().findFirstToken(TokenTypes.LPAREN);
 279  
     }
 280  
 
 281  
     @Override
 282  
     public void checkIndentation()
 283  
     {
 284  640
         checkToplevelToken();
 285  
         // seperate to allow for eventual configuration
 286  640
         checkLParen(getLParen());
 287  640
         checkRParen(getLParen(), getRParen());
 288  640
         if (hasCurlys()) {
 289  559
             checkLCurly();
 290  559
             checkRCurly();
 291  
         }
 292  640
         final DetailAST listChild = getListChild();
 293  640
         if (listChild != null) {
 294  
             // NOTE: switch statements usually don't have curlys
 295  581
             if (!hasCurlys() || !areOnSameLine(getLCurly(), getRCurly())) {
 296  527
                 checkChildren(listChild,
 297  
                               getCheckedChildren(),
 298  
                               getChildrenExpectedLevel(),
 299  
                               true,
 300  
                               childrenMayNest());
 301  
             }
 302  
         }
 303  
         else {
 304  59
             checkNonlistChild();
 305  
         }
 306  640
     }
 307  
 
 308  
     /**
 309  
      * @return indentation level expected for children
 310  
      */
 311  
     protected IndentLevel getChildrenExpectedLevel()
 312  
     {
 313  
         // if we have multileveled expected level then we should
 314  
         // try to suggest single level to children using curlies'
 315  
         // levels.
 316  1555
         if (getLevel().isMultiLevel() && hasCurlys()
 317  
             && !areOnSameLine(getLCurly(), getRCurly()))
 318  
         {
 319  27
             if (startsLine(getLCurly())) {
 320  17
                 return new IndentLevel(expandedTabsColumnNo(getLCurly())
 321  
                                        + getBasicOffset());
 322  
             }
 323  10
             else if (startsLine(getRCurly())) {
 324  10
                 return new IndentLevel(expandedTabsColumnNo(getRCurly())
 325  
                                        + getBasicOffset());
 326  
             }
 327  
         }
 328  1528
         return new IndentLevel(getLevel(), getBasicOffset());
 329  
     }
 330  
 
 331  
     @Override
 332  
     public IndentLevel suggestedChildLevel(ExpressionHandler aChild)
 333  
     {
 334  833
         return getChildrenExpectedLevel();
 335  
     }
 336  
 
 337  
 }