KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > puppycrawl > tools > checkstyle > checks > coding > ModifiedControlVariableCheck


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.coding;
20
21 import java.util.Stack JavaDoc;
22
23 import com.puppycrawl.tools.checkstyle.api.Check;
24 import com.puppycrawl.tools.checkstyle.api.DetailAST;
25 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
26 /**
27  * Check for ensuring that for loop control variables are not modified
28  * inside the for block.
29  *
30  * @author Daniel Grenner
31  */

32 public final class ModifiedControlVariableCheck extends Check
33 {
34     /** Current set of parameters. */
35     private Stack JavaDoc mCurrentVariables = new Stack JavaDoc();
36     /** Stack of block parameters. */
37     private final Stack JavaDoc mVariableStack = new Stack JavaDoc();
38
39     /** {@inheritDoc} */
40     public int[] getDefaultTokens()
41     {
42         return new int[] {
43             TokenTypes.OBJBLOCK,
44             TokenTypes.LITERAL_FOR,
45             TokenTypes.FOR_ITERATOR,
46             TokenTypes.FOR_EACH_CLAUSE,
47             TokenTypes.ASSIGN,
48             TokenTypes.PLUS_ASSIGN,
49             TokenTypes.MINUS_ASSIGN,
50             TokenTypes.STAR_ASSIGN,
51             TokenTypes.DIV_ASSIGN,
52             TokenTypes.MOD_ASSIGN,
53             TokenTypes.SR_ASSIGN,
54             TokenTypes.BSR_ASSIGN,
55             TokenTypes.SL_ASSIGN,
56             TokenTypes.BAND_ASSIGN,
57             TokenTypes.BXOR_ASSIGN,
58             TokenTypes.BOR_ASSIGN,
59             TokenTypes.INC,
60             TokenTypes.POST_INC,
61             TokenTypes.DEC,
62             TokenTypes.POST_DEC,
63         };
64     }
65
66     /** {@inheritDoc} */
67     public int[] getRequiredTokens()
68     {
69         return getDefaultTokens();
70     }
71
72     /** {@inheritDoc} */
73     public void beginTree(DetailAST aRootAST)
74     {
75         // clear data
76
mCurrentVariables.clear();
77         mVariableStack.clear();
78     }
79
80     /** {@inheritDoc} */
81     public void visitToken(DetailAST aAST)
82     {
83         switch (aAST.getType()) {
84         case TokenTypes.OBJBLOCK:
85             enterBlock();
86             break;
87         case TokenTypes.LITERAL_FOR:
88         case TokenTypes.FOR_ITERATOR:
89         case TokenTypes.FOR_EACH_CLAUSE:
90             break;
91         case TokenTypes.ASSIGN:
92         case TokenTypes.PLUS_ASSIGN:
93         case TokenTypes.MINUS_ASSIGN:
94         case TokenTypes.STAR_ASSIGN:
95         case TokenTypes.DIV_ASSIGN:
96         case TokenTypes.MOD_ASSIGN:
97         case TokenTypes.SR_ASSIGN:
98         case TokenTypes.BSR_ASSIGN:
99         case TokenTypes.SL_ASSIGN:
100         case TokenTypes.BAND_ASSIGN:
101         case TokenTypes.BXOR_ASSIGN:
102         case TokenTypes.BOR_ASSIGN:
103         case TokenTypes.INC:
104         case TokenTypes.POST_INC:
105         case TokenTypes.DEC:
106         case TokenTypes.POST_DEC:
107             checkIdent(aAST);
108             break;
109         default:
110             throw new IllegalStateException JavaDoc(aAST.toString());
111         }
112     }
113
114
115     /** {@inheritDoc} */
116     public void leaveToken(DetailAST aAST)
117     {
118         switch (aAST.getType()) {
119         case TokenTypes.FOR_ITERATOR:
120             leaveForIter(aAST.getParent());
121             break;
122         case TokenTypes.FOR_EACH_CLAUSE:
123             leaveForEach(aAST);
124             break;
125         case TokenTypes.LITERAL_FOR:
126             leaveForDef(aAST);
127             break;
128         case TokenTypes.OBJBLOCK:
129             exitBlock();
130             break;
131         case TokenTypes.ASSIGN:
132         case TokenTypes.PLUS_ASSIGN:
133         case TokenTypes.MINUS_ASSIGN:
134         case TokenTypes.STAR_ASSIGN:
135         case TokenTypes.DIV_ASSIGN:
136         case TokenTypes.MOD_ASSIGN:
137         case TokenTypes.SR_ASSIGN:
138         case TokenTypes.BSR_ASSIGN:
139         case TokenTypes.SL_ASSIGN:
140         case TokenTypes.BAND_ASSIGN:
141         case TokenTypes.BXOR_ASSIGN:
142         case TokenTypes.BOR_ASSIGN:
143         case TokenTypes.INC:
144         case TokenTypes.POST_INC:
145         case TokenTypes.DEC:
146         case TokenTypes.POST_DEC:
147             // Do nothing
148
break;
149         default:
150             throw new IllegalStateException JavaDoc(aAST.toString());
151         }
152     }
153
154     /**
155      * Enters an inner class, which requires a new variable set.
156      */

157     private void enterBlock()
158     {
159         mVariableStack.push(mCurrentVariables);
160         mCurrentVariables = new Stack JavaDoc();
161
162     }
163     /**
164      * Leave an inner class, so restore variable set.
165      */

166     private void exitBlock()
167     {
168         mCurrentVariables = (Stack JavaDoc) mVariableStack.pop();
169     }
170
171     /**
172      * Check if ident is parameter.
173      * @param aAST ident to check.
174      */

175     private void checkIdent(DetailAST aAST)
176     {
177         if ((mCurrentVariables != null) && !mCurrentVariables.isEmpty()) {
178             final DetailAST identAST = (DetailAST) aAST.getFirstChild();
179
180             if ((identAST != null)
181                 && (identAST.getType() == TokenTypes.IDENT)
182                 && mCurrentVariables.contains(identAST.getText()))
183             {
184                 log(aAST.getLineNo(), aAST.getColumnNo(),
185                     "modified.control.variable", identAST.getText());
186             }
187         }
188     }
189
190     /**
191      * Push current variables to the stack.
192      * @param aAST a for definition.
193      */

194     private void leaveForIter(DetailAST aAST)
195     {
196         final DetailAST forInitAST = aAST.findFirstToken(TokenTypes.FOR_INIT);
197         DetailAST parameterDefAST =
198             forInitAST.findFirstToken(TokenTypes.VARIABLE_DEF);
199
200         for (; parameterDefAST != null;
201              parameterDefAST = (DetailAST) parameterDefAST.getNextSibling())
202         {
203             if (parameterDefAST.getType() == TokenTypes.VARIABLE_DEF) {
204                 final DetailAST param =
205                     parameterDefAST.findFirstToken(TokenTypes.IDENT);
206                 mCurrentVariables.push(param.getText());
207             }
208         }
209     }
210
211     /**
212      * Push current variables to the stack.
213      * @param aForEach a for-each clause
214      */

215     private void leaveForEach(DetailAST aForEach)
216     {
217         final DetailAST paramDef =
218             aForEach.findFirstToken(TokenTypes.VARIABLE_DEF);
219         final DetailAST paramName = paramDef.findFirstToken(TokenTypes.IDENT);
220         mCurrentVariables.push(paramName.getText());
221     }
222
223     /**
224      * Pops the variables from the stack.
225      * @param aAST a for definition.
226      */

227     private void leaveForDef(DetailAST aAST)
228     {
229         final DetailAST forInitAST = aAST.findFirstToken(TokenTypes.FOR_INIT);
230         if (forInitAST != null) {
231             DetailAST parameterDefAST =
232                 forInitAST.findFirstToken(TokenTypes.VARIABLE_DEF);
233
234             for (; parameterDefAST != null;
235                  parameterDefAST = (DetailAST) parameterDefAST.getNextSibling())
236             {
237                 if (parameterDefAST.getType() == TokenTypes.VARIABLE_DEF) {
238                     mCurrentVariables.pop();
239                 }
240             }
241         }
242         else {
243             // this is for-each loop, just pop veriables
244
mCurrentVariables.pop();
245         }
246     }
247 }
248
Popular Tags