KickJava   Java API By Example, From Geeks To Geeks.

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


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.HashMap JavaDoc;
22 import java.util.Iterator JavaDoc;
23 import java.util.Stack JavaDoc;
24
25 import com.puppycrawl.tools.checkstyle.api.Check;
26 import com.puppycrawl.tools.checkstyle.api.DetailAST;
27 import com.puppycrawl.tools.checkstyle.api.ScopeUtils;
28 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
29
30 /**
31  * <p>
32  * Ensures that local variables that never get their values changed,
33  * must be declared final.
34  * </p>
35  * <p>
36  * An example of how to configure the check is:
37  * </p>
38  * <pre>
39  * &lt;module name="FinalLocalVariable"&gt;
40  * &lt;property name="token" value="VARIABLE_DEF"/&gt;
41  * &lt;/module&gt;
42  * </pre>
43  * @author k_gibbs, r_auckenthaler
44  */

45 public class FinalLocalVariableCheck extends Check
46 {
47     /** Scope Stack */
48     private final Stack JavaDoc mScopeStack = new Stack JavaDoc();
49
50     /**
51      * {@inheritDoc}
52      */

53     public int[] getDefaultTokens()
54     {
55         return new int[] {
56             TokenTypes.IDENT,
57             TokenTypes.CTOR_DEF,
58             TokenTypes.METHOD_DEF,
59             TokenTypes.VARIABLE_DEF,
60             TokenTypes.INSTANCE_INIT,
61             TokenTypes.STATIC_INIT,
62             TokenTypes.LITERAL_FOR,
63             TokenTypes.SLIST,
64             TokenTypes.OBJBLOCK,
65         };
66     }
67
68     /** {@inheritDoc} */
69     public int[] getAcceptableTokens()
70     {
71         return new int[] {
72             TokenTypes.VARIABLE_DEF,
73             TokenTypes.PARAMETER_DEF,
74         };
75     }
76
77     /** {@inheritDoc} */
78     public int[] getRequiredTokens()
79     {
80         return new int[] {
81             TokenTypes.IDENT,
82             TokenTypes.CTOR_DEF,
83             TokenTypes.METHOD_DEF,
84             TokenTypes.INSTANCE_INIT,
85             TokenTypes.STATIC_INIT,
86             TokenTypes.LITERAL_FOR,
87             TokenTypes.SLIST,
88             TokenTypes.OBJBLOCK,
89         };
90     }
91
92     /**
93      * {@inheritDoc}
94      */

95     public void visitToken(DetailAST aAST)
96     {
97         switch(aAST.getType()) {
98         case TokenTypes.OBJBLOCK:
99         case TokenTypes.SLIST:
100         case TokenTypes.LITERAL_FOR:
101         case TokenTypes.METHOD_DEF:
102         case TokenTypes.CTOR_DEF:
103         case TokenTypes.STATIC_INIT:
104         case TokenTypes.INSTANCE_INIT:
105             mScopeStack.push(new HashMap JavaDoc());
106             break;
107
108         case TokenTypes.PARAMETER_DEF:
109             if (ScopeUtils.inInterfaceBlock(aAST)
110                 || inAbstractMethod(aAST))
111             {
112                 break;
113             }
114         case TokenTypes.VARIABLE_DEF:
115             if ((aAST.getParent().getType() != TokenTypes.OBJBLOCK)
116                 && (aAST.getParent().getType() != TokenTypes.FOR_EACH_CLAUSE))
117             {
118                 insertVariable(aAST);
119             }
120             break;
121
122         case TokenTypes.IDENT:
123             final int parentType = aAST.getParent().getType();
124             if ((TokenTypes.POST_DEC == parentType)
125                 || (TokenTypes.DEC == parentType)
126                 || (TokenTypes.POST_INC == parentType)
127                 || (TokenTypes.INC == parentType)
128                 || (TokenTypes.ASSIGN == parentType)
129                 || (TokenTypes.PLUS_ASSIGN == parentType)
130                 || (TokenTypes.MINUS_ASSIGN == parentType)
131                 || (TokenTypes.DIV_ASSIGN == parentType)
132                 || (TokenTypes.STAR_ASSIGN == parentType)
133                 || (TokenTypes.MOD_ASSIGN == parentType)
134                 || (TokenTypes.SR_ASSIGN == parentType)
135                 || (TokenTypes.BSR_ASSIGN == parentType)
136                 || (TokenTypes.SL_ASSIGN == parentType)
137                 || (TokenTypes.BXOR_ASSIGN == parentType)
138                 || (TokenTypes.BOR_ASSIGN == parentType)
139                 || (TokenTypes.BAND_ASSIGN == parentType))
140             {
141                 // TODO: is there better way to check is aAST
142
// in left part of assignment?
143
if (aAST.getParent().getFirstChild() == aAST) {
144                     removeVariable(aAST);
145                 }
146             }
147             break;
148
149         default:
150         }
151     }
152
153     /**
154      * Determines whether an AST is a descentant of an abstract method.
155      * @param aAST the AST to check.
156      * @return true if aAST is a descentant of an abstract method.
157      */

158     private boolean inAbstractMethod(DetailAST aAST)
159     {
160         DetailAST parent = aAST.getParent();
161         while (parent != null) {
162             if (parent.getType() == TokenTypes.METHOD_DEF) {
163                 final DetailAST modifiers =
164                     parent.findFirstToken(TokenTypes.MODIFIERS);
165                 return modifiers.branchContains(TokenTypes.ABSTRACT);
166             }
167             parent = parent.getParent();
168         }
169         return false;
170     }
171
172     /**
173      * Inserts a variable at the topmost scope stack
174      * @param aAST the variable to insert
175      */

176     private void insertVariable(DetailAST aAST)
177     {
178         if (!aAST.branchContains(TokenTypes.FINAL)) {
179             final HashMap JavaDoc state = (HashMap JavaDoc) mScopeStack.peek();
180             final DetailAST ast = aAST.findFirstToken(TokenTypes.IDENT);
181             state.put(ast.getText(), ast);
182         }
183     }
184
185     /**
186      * Removes the variable from the Stacks
187      * @param aAST Variable to remove
188      */

189     private void removeVariable(DetailAST aAST)
190     {
191         for (int i = mScopeStack.size() - 1; i >= 0; i--) {
192             final HashMap JavaDoc state = (HashMap JavaDoc) mScopeStack.get(i);
193             final Object JavaDoc obj = state.remove(aAST.getText());
194             if (obj != null) {
195                 break;
196             }
197         }
198     }
199
200     /**
201      * {@inheritDoc}
202      */

203     public void leaveToken(DetailAST aAST)
204     {
205         super.leaveToken(aAST);
206
207         switch(aAST.getType()) {
208         case TokenTypes.OBJBLOCK:
209         case TokenTypes.SLIST:
210         case TokenTypes.LITERAL_FOR:
211         case TokenTypes.CTOR_DEF:
212         case TokenTypes.STATIC_INIT:
213         case TokenTypes.INSTANCE_INIT:
214         case TokenTypes.METHOD_DEF:
215             final HashMap JavaDoc state = (HashMap JavaDoc) mScopeStack.pop();
216             final Iterator JavaDoc finalVars = state.values().iterator();
217
218             while (finalVars.hasNext()) {
219                 final DetailAST var = (DetailAST) finalVars.next();
220                 log(var.getLineNo(), var.getColumnNo(),
221                     "final.variable", var.getText());
222             }
223             break;
224
225         default:
226         }
227     }
228 }
229
Popular Tags