KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > puppycrawl > tools > checkstyle > checks > indentation > MethodCallHandler


1 ////////////////////////////////////////////////////////////////////////////////
2
// checkstyle: Checks Java source code for adherence to a set of rules.
3
// Copyright (C) 2001-2005 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         super(aIndentCheck,
43             aAST.getType() == TokenTypes.METHOD_CALL
44                 ? "method call" : "ctor call",
45             aAST,
46             aParent);
47     }
48
49     /**
50      * Compute the indentation amount for this handler.
51      *
52      * @return the expected indentation amount
53      */

54     protected IndentLevel getLevelImpl()
55     {
56         // if inside a method call's params, this could be part of
57
// an expression, so get the previous line's start
58
if (getParent() instanceof MethodCallHandler) {
59             final MethodCallHandler container =
60                 ((MethodCallHandler) getParent());
61             if (container != null) {
62                 if (areOnSameLine(container.getMainAst(), getMainAst())) {
63                     return container.getLevel();
64                 }
65
66                 // we should increase indentation only if this is the first
67
// chained method call which was moved to the next line
68
final DetailAST main = getMainAst();
69                 final DetailAST dot = (DetailAST) main.getFirstChild();
70                 final DetailAST target = (DetailAST) dot.getFirstChild();
71
72                 if ((dot.getType() == TokenTypes.DOT)
73                     && (target.getType() == TokenTypes.METHOD_CALL))
74                 {
75                     final DetailAST dot1 = (DetailAST) target.getFirstChild();
76                     final DetailAST target1 = (DetailAST) dot1.getFirstChild();
77
78                     if ((dot1.getType() == TokenTypes.DOT)
79                         && (target1.getType() == TokenTypes.METHOD_CALL))
80                     {
81                         return container.getLevel();
82                     }
83                 }
84                 return new IndentLevel(container.getLevel(), getBasicOffset());
85             }
86
87             // if we get here, we are the child of the left hand side (name
88
// side) of a method call with no "containing" call, use
89
// the first non-method call parent
90

91             ExpressionHandler p = getParent();
92             while (p instanceof MethodCallHandler) {
93                 p = p.getParent();
94             }
95             return p.suggestedChildLevel(this);
96         }
97
98         // if our expression isn't first on the line, just use the start
99
// of the line
100
final LineSet lines = new LineSet();
101         findSubtreeLines(lines, (DetailAST) getMainAst().getFirstChild(), true);
102         final int firstCol = lines.firstLineCol();
103         final int lineStart = getLineStart(getFirstAst(getMainAst()));
104         if (lineStart != firstCol) {
105             return new IndentLevel(lineStart);
106         }
107         return super.getLevelImpl();
108     }
109
110     /**
111      * Get the first AST of the specified method call.
112      *
113      * @param aAst
114      * the method call
115      *
116      * @return the first AST of the specified method call
117      */

118     private DetailAST getFirstAst(DetailAST aAst)
119     {
120         // walk down the first child part of the dots that make up a method
121
// call name
122

123         DetailAST ast = (DetailAST) aAst.getFirstChild();
124         while ((ast != null) && (ast.getType() == TokenTypes.DOT)) {
125             ast = (DetailAST) ast.getFirstChild();
126         }
127
128         if (ast == null) {
129             ast = aAst;
130         }
131
132         return ast;
133     }
134
135     /**
136      * Indentation level suggested for a child element. Children don't have
137      * to respect this, but most do.
138      *
139      * @param aChild child AST (so suggestion level can differ based on child
140      * type)
141      *
142      * @return suggested indentation for child
143      */

144     public IndentLevel suggestedChildLevel(ExpressionHandler aChild)
145     {
146         // for whatever reason a method that crosses lines, like asList
147
// here:
148
// System.out.println("methods are: " + Arrays.asList(
149
// new String[] {"method"}).toString());
150
// will not have the right line num, so just get the child name
151

152         final DetailAST first = (DetailAST) getMainAst().getFirstChild();
153         int indentLevel = getLineStart(first);
154         if (!areOnSameLine((DetailAST) aChild.getMainAst().getFirstChild(),
155                            (DetailAST) getMainAst().getFirstChild()))
156         {
157             indentLevel += getBasicOffset();
158         }
159         return new IndentLevel(indentLevel);
160     }
161
162     /**
163      * Check the indentation of the expression we are handling.
164      */

165     public void checkIndentation()
166     {
167         final DetailAST methodName = (DetailAST) getMainAst().getFirstChild();
168         checkExpressionSubtree(methodName, getLevel(), false, false);
169
170         final DetailAST lparen = getMainAst();
171         final DetailAST rparen = getMainAst().findFirstToken(TokenTypes.RPAREN);
172         checkLParen(lparen);
173
174         if (rparen.getLineNo() == lparen.getLineNo()) {
175             return;
176         }
177
178         // if this method name is on the same line as a containing
179
// method, don't indent, this allows expressions like:
180
// method("my str" + method2(
181
// "my str2"));
182
// as well as
183
// method("my str" +
184
// method2(
185
// "my str2"));
186
//
187

188         checkExpressionSubtree(
189             getMainAst().findFirstToken(TokenTypes.ELIST),
190             new IndentLevel(getLevel(), getBasicOffset()),
191             false, true);
192
193         checkRParen(lparen, rparen);
194     }
195
196     /**
197      * @return true if indentation should be increased after
198      * fisrt line in checkLinesIndent()
199      * false otherwise
200      */

201     protected boolean shouldIncreaseIndent()
202     {
203         return false;
204     }
205 }
206
Popular Tags