KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > puppycrawl > tools > checkstyle > checks > metrics > BooleanExpressionComplexityCheck


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.metrics;
20
21 import com.puppycrawl.tools.checkstyle.api.Check;
22 import com.puppycrawl.tools.checkstyle.api.DetailAST;
23 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
24
25 import com.puppycrawl.tools.checkstyle.checks.CheckUtils;
26
27 import java.util.Stack JavaDoc;
28
29 /**
30  * Restricts nested boolean operators (&&, || and ^) to
31  * a specified depth (default = 3).
32  *
33  * @author <a HREF="mailto:simon@redhillconsulting.com.au">Simon Harris</a>
34  * @author o_sukhodolsky
35  */

36 public final class BooleanExpressionComplexityCheck extends Check
37 {
38     /** Default allowed complexity. */
39     private static final int DEFAULT_MAX = 3;
40
41     /** Stack of contexts. */
42     private final Stack JavaDoc mContextStack = new Stack JavaDoc();
43     /** Maximum allowed complexity. */
44     private int mMax;
45     /** Current context. */
46     private Context mContext;
47
48     /** Creates new instance of the check. */
49     public BooleanExpressionComplexityCheck()
50     {
51         setMax(DEFAULT_MAX);
52     }
53
54     /** {@inheritDoc} */
55     public int[] getDefaultTokens()
56     {
57         return new int[] {
58             TokenTypes.CTOR_DEF,
59             TokenTypes.METHOD_DEF,
60             TokenTypes.EXPR,
61             TokenTypes.LAND,
62             TokenTypes.BAND,
63             TokenTypes.LOR,
64             TokenTypes.BOR,
65             TokenTypes.BXOR,
66         };
67     }
68
69     /** {@inheritDoc} */
70     public int[] getRequiredTokens()
71     {
72         return getDefaultTokens();
73     }
74
75     /**
76      * Getter for maximum allowed complexity.
77      * @return value of maximum allowed complexity.
78      */

79     public int getMax()
80     {
81         return mMax;
82     }
83
84     /**
85      * Setter for maximum allowed complexity.
86      * @param aMax new maximum allowed complexity.
87      */

88     public void setMax(int aMax)
89     {
90         mMax = aMax;
91     }
92
93     /** {@inheritDoc} */
94     public void visitToken(DetailAST aAST)
95     {
96         switch (aAST.getType()) {
97         case TokenTypes.CTOR_DEF:
98         case TokenTypes.METHOD_DEF:
99             visitMethodDef(aAST);
100             break;
101         case TokenTypes.EXPR:
102             visitExpr();
103             break;
104         case TokenTypes.LAND:
105         case TokenTypes.BAND:
106         case TokenTypes.LOR:
107         case TokenTypes.BOR:
108         case TokenTypes.BXOR:
109             mContext.visitBooleanOperator();
110             break;
111         default:
112             throw new IllegalStateException JavaDoc(aAST.toString());
113         }
114     }
115
116     /** {@inheritDoc} */
117     public void leaveToken(DetailAST aAST)
118     {
119         switch (aAST.getType()) {
120         case TokenTypes.CTOR_DEF:
121         case TokenTypes.METHOD_DEF:
122             leaveMethodDef();
123             break;
124         case TokenTypes.EXPR:
125             leaveExpr(aAST);
126             break;
127         default:
128             // Do nothing
129
}
130     }
131
132     /**
133      * Creates new context for a given method.
134      * @param aAST a method we start to check.
135      */

136     private void visitMethodDef(DetailAST aAST)
137     {
138         mContextStack.push(mContext);
139         mContext = new Context(!CheckUtils.isEqualsMethod(aAST));
140     }
141
142     /** Removes old context. */
143     private void leaveMethodDef()
144     {
145         mContext = (Context) mContextStack.pop();
146     }
147
148     /** Creates and pushes new context. */
149     private void visitExpr()
150     {
151         mContextStack.push(mContext);
152         mContext = new Context((mContext == null) || mContext.isChecking());
153     }
154
155     /**
156      * Restores previous context.
157      * @param aAST expression we leave.
158      */

159     private void leaveExpr(DetailAST aAST)
160     {
161         mContext.checkCount(aAST);
162         mContext = (Context) mContextStack.pop();
163     }
164
165     /**
166      * Represents context (method/expression) in which we check complexity.
167      *
168      * @author <a HREF="mailto:simon@redhillconsulting.com.au">Simon Harris</a>
169      * @author o_sukhodolsky
170      */

171     private class Context
172     {
173         /**
174          * Should we perform check in current context or not.
175          * Usually false if we are inside equals() method.
176          */

177         private final boolean mChecking;
178         /** Count of boolean operators. */
179         private int mCount;
180
181         /**
182          * Creates new instance.
183          * @param aChecking should we check in current context or not.
184          */

185         public Context(boolean aChecking)
186         {
187             mChecking = aChecking;
188             mCount = 0;
189         }
190
191         /**
192          * Getter for checking property.
193          * @return should we check in current context or not.
194          */

195         public boolean isChecking()
196         {
197             return mChecking;
198         }
199
200         /** Increases operator counter. */
201         public void visitBooleanOperator()
202         {
203             ++mCount;
204         }
205
206         /**
207          * Checks if we violates maximum allowed complexity.
208          * @param aAST a node we check now.
209          */

210         public void checkCount(DetailAST aAST)
211         {
212             if (mChecking && (mCount > getMax())) {
213                 final DetailAST parentAST = aAST.getParent();
214
215                 log(parentAST.getLineNo(), parentAST.getColumnNo(),
216                     "booleanExpressionComplexity",
217                     new Integer JavaDoc(mCount),
218                     new Integer JavaDoc(getMax()));
219             }
220         }
221     }
222 }
223
Popular Tags