Coverage Report - com.puppycrawl.tools.checkstyle.checks.indentation.MethodCallHandler
 
Classes in this File Line Coverage Branch Coverage Complexity
MethodCallHandler
89%
44/49
73%
22/30
4.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  
 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 method calls.
 26  
  *
 27  
  * @author jrichard
 28  
  */
 29  
 public class MethodCallHandler extends ExpressionHandler
 30  
 {
 31  
     /**
 32  
      * Construct an instance of this handler with the given indentation check,
 33  
      * abstract syntax tree, and parent handler.
 34  
      *
 35  
      * @param aIndentCheck   the indentation check
 36  
      * @param aAST           the abstract syntax tree
 37  
      * @param aParent        the parent handler
 38  
      */
 39  
     public MethodCallHandler(IndentationCheck aIndentCheck,
 40  
         DetailAST aAST, ExpressionHandler aParent)
 41  
     {
 42  278
         super(aIndentCheck,
 43  
             aAST.getType() == TokenTypes.METHOD_CALL
 44  
                 ? "method call" : "ctor call",
 45  
             aAST,
 46  
             aParent);
 47  278
     }
 48  
 
 49  
     @Override
 50  
     protected IndentLevel getLevelImpl()
 51  
     {
 52  
         // if inside a method call's params, this could be part of
 53  
         // an expression, so get the previous line's start
 54  278
         if (getParent() instanceof MethodCallHandler) {
 55  39
             final MethodCallHandler container =
 56  
                 ((MethodCallHandler) getParent());
 57  39
             if (container != null) {
 58  39
                 if (areOnSameLine(container.getMainAst(), getMainAst())) {
 59  9
                     return container.getLevel();
 60  
                 }
 61  
 
 62  
                 // we should increase indentation only if this is the first
 63  
                 // chained method call which was moved to the next line
 64  30
                 final DetailAST main = getMainAst();
 65  30
                 final DetailAST dot = main.getFirstChild();
 66  30
                 final DetailAST target = dot.getFirstChild();
 67  
 
 68  30
                 if ((dot.getType() == TokenTypes.DOT)
 69  
                     && (target.getType() == TokenTypes.METHOD_CALL))
 70  
                 {
 71  16
                     final DetailAST dot1 = target.getFirstChild();
 72  16
                     final DetailAST target1 = dot1.getFirstChild();
 73  
 
 74  16
                     if ((dot1.getType() == TokenTypes.DOT)
 75  
                         && (target1.getType() == TokenTypes.METHOD_CALL))
 76  
                     {
 77  3
                         return container.getLevel();
 78  
                     }
 79  
                 }
 80  27
                 return new IndentLevel(container.getLevel(), getBasicOffset());
 81  
             }
 82  
 
 83  
             // if we get here, we are the child of the left hand side (name
 84  
             //  side) of a method call with no "containing" call, use
 85  
             //  the first non-method call parent
 86  
 
 87  0
             ExpressionHandler p = getParent();
 88  0
             while (p instanceof MethodCallHandler) {
 89  0
                 p = p.getParent();
 90  
             }
 91  0
             return p.suggestedChildLevel(this);
 92  
         }
 93  
 
 94  
         // if our expression isn't first on the line, just use the start
 95  
         // of the line
 96  239
         final LineSet lines = new LineSet();
 97  239
         findSubtreeLines(lines, getMainAst().getFirstChild(), true);
 98  239
         final int firstCol = lines.firstLineCol();
 99  239
         final int lineStart = getLineStart(getFirstAst(getMainAst()));
 100  239
         if (lineStart != firstCol) {
 101  27
             return new IndentLevel(lineStart);
 102  
         }
 103  212
         return super.getLevelImpl();
 104  
     }
 105  
 
 106  
     /**
 107  
      * Get the first AST of the specified method call.
 108  
      *
 109  
      * @param aAst
 110  
      *            the method call
 111  
      *
 112  
      * @return the first AST of the specified method call
 113  
      */
 114  
     private DetailAST getFirstAst(DetailAST aAst)
 115  
     {
 116  
         // walk down the first child part of the dots that make up a method
 117  
         // call name
 118  
 
 119  239
         DetailAST ast = aAst.getFirstChild();
 120  536
         while ((ast != null) && (ast.getType() == TokenTypes.DOT)) {
 121  297
             ast = ast.getFirstChild();
 122  
         }
 123  
 
 124  239
         if (ast == null) {
 125  0
             ast = aAst;
 126  
         }
 127  
 
 128  239
         return ast;
 129  
     }
 130  
 
 131  
     @Override
 132  
     public IndentLevel suggestedChildLevel(ExpressionHandler aChild)
 133  
     {
 134  
         // for whatever reason a method that crosses lines, like asList
 135  
         // here:
 136  
         //            System.out.println("methods are: " + Arrays.asList(
 137  
         //                new String[] {"method"}).toString());
 138  
         // will not have the right line num, so just get the child name
 139  
 
 140  14
         final DetailAST first = getMainAst().getFirstChild();
 141  14
         int indentLevel = getLineStart(first);
 142  14
         if (!areOnSameLine(aChild.getMainAst().getFirstChild(),
 143  
                            getMainAst().getFirstChild()))
 144  
         {
 145  14
             indentLevel += getBasicOffset();
 146  
         }
 147  14
         return new IndentLevel(indentLevel);
 148  
     }
 149  
 
 150  
     @Override
 151  
     public void checkIndentation()
 152  
     {
 153  278
         final DetailAST methodName = getMainAst().getFirstChild();
 154  278
         checkExpressionSubtree(methodName, getLevel(), false, false);
 155  
 
 156  278
         final DetailAST lparen = getMainAst();
 157  278
         final DetailAST rparen = getMainAst().findFirstToken(TokenTypes.RPAREN);
 158  278
         checkLParen(lparen);
 159  
 
 160  278
         if (rparen.getLineNo() == lparen.getLineNo()) {
 161  230
             return;
 162  
         }
 163  
 
 164  
         // if this method name is on the same line as a containing
 165  
         // method, don't indent, this allows expressions like:
 166  
         //    method("my str" + method2(
 167  
         //        "my str2"));
 168  
         // as well as
 169  
         //    method("my str" +
 170  
         //        method2(
 171  
         //            "my str2"));
 172  
         //
 173  
 
 174  48
         checkExpressionSubtree(
 175  
             getMainAst().findFirstToken(TokenTypes.ELIST),
 176  
             new IndentLevel(getLevel(), getBasicOffset()),
 177  
             false, true);
 178  
 
 179  48
         checkRParen(lparen, rparen);
 180  48
     }
 181  
 
 182  
     @Override
 183  
     protected boolean shouldIncreaseIndent()
 184  
     {
 185  15
         return false;
 186  
     }
 187  
 }