KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > puppycrawl > tools > checkstyle > checks > UncommentedMainCheck


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;
20
21 import com.puppycrawl.tools.checkstyle.api.Check;
22 import com.puppycrawl.tools.checkstyle.api.DetailAST;
23 import com.puppycrawl.tools.checkstyle.api.FullIdent;
24 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
25 import com.puppycrawl.tools.checkstyle.api.Utils;
26
27 import java.util.regex.Pattern JavaDoc;
28 import java.util.regex.PatternSyntaxException JavaDoc;
29
30 import org.apache.commons.beanutils.ConversionException;
31
32 /**
33  * Detects uncommented main methods. Basically detects
34  * any main method, since if it is detectable
35  * that means it is uncommented.
36  *
37  * <pre class="body">
38  * &lt;module name=&quot;UncommentedMain&quot;/&gt;
39  * </pre>
40  *
41  * @author Michael Yui
42  * @author o_sukhodolsky
43  */

44 public class UncommentedMainCheck
45     extends Check
46 {
47     /** the pattern to exclude classes from the check */
48     private String JavaDoc mExcludedClasses = "^$";
49     /** compiled regexp to exclude classes from check */
50     private Pattern JavaDoc mExcludedClassesPattern =
51         Utils.createPattern(mExcludedClasses);
52     /** current class name */
53     private String JavaDoc mCurrentClass;
54     /** current package */
55     private FullIdent mPackage;
56     /** class definition depth */
57     private int mClassDepth;
58
59     /**
60      * Set the excluded classes pattern.
61      * @param aExcludedClasses a <code>String</code> value
62      * @throws ConversionException unable to parse aExcludedClasses
63      */

64     public void setExcludedClasses(String JavaDoc aExcludedClasses)
65         throws ConversionException
66     {
67         try {
68             mExcludedClasses = aExcludedClasses;
69             mExcludedClassesPattern = Utils.getPattern(mExcludedClasses);
70         }
71         catch (final PatternSyntaxException JavaDoc e) {
72             throw new ConversionException("unable to parse "
73                                           + mExcludedClasses,
74                                           e);
75         }
76     }
77
78     /** {@inheritDoc} */
79     public int[] getDefaultTokens()
80     {
81         return new int[] {
82             TokenTypes.METHOD_DEF,
83             TokenTypes.CLASS_DEF,
84             TokenTypes.PACKAGE_DEF,
85         };
86     }
87
88     /** {@inheritDoc} */
89     public int[] getRequiredTokens()
90     {
91         return getDefaultTokens();
92     }
93
94     /** {@inheritDoc} */
95     public void beginTree(DetailAST aRootAST)
96     {
97         mPackage = FullIdent.createFullIdent(null);
98         mCurrentClass = null;
99         mClassDepth = 0;
100     }
101
102     /** {@inheritDoc} */
103     public void leaveToken(DetailAST aAst)
104     {
105         if (aAst.getType() == TokenTypes.CLASS_DEF) {
106             if (mClassDepth == 1) {
107                 mCurrentClass = null;
108             }
109             mClassDepth--;
110         }
111     }
112
113     /** {@inheritDoc} */
114     public void visitToken(DetailAST aAst)
115     {
116         switch (aAst.getType()) {
117         case TokenTypes.PACKAGE_DEF:
118             visitPackageDef(aAst);
119             break;
120         case TokenTypes.CLASS_DEF:
121             visitClassDef(aAst);
122             break;
123         case TokenTypes.METHOD_DEF:
124             visitMethodDef(aAst);
125             break;
126         default:
127             throw new IllegalStateException JavaDoc(aAst.toString());
128         }
129     }
130
131     /**
132      * Sets current package.
133      * @param aPackage node for package definition
134      */

135     private void visitPackageDef(DetailAST aPackage)
136     {
137         mPackage = FullIdent.createFullIdent(aPackage.getLastChild()
138                 .getPreviousSibling());
139     }
140
141     /**
142      * If not inner class then change current class name.
143      * @param aClass node for class definition
144      */

145     private void visitClassDef(DetailAST aClass)
146     {
147         // we are not use inner classes because they can not
148
// have static methods
149
if (mClassDepth == 0) {
150             final DetailAST ident = aClass.findFirstToken(TokenTypes.IDENT);
151             mCurrentClass = mPackage.getText() + "." + ident.getText();
152             mClassDepth++;
153         }
154     }
155
156     /**
157      * Checks method definition if this is
158      * <code>public static void main(String[])</code>.
159      * @param aMethod method definition node
160      */

161     private void visitMethodDef(DetailAST aMethod)
162     {
163         if (mClassDepth != 1) {
164             // method in inner class or in interface definition
165
return;
166         }
167
168         if (checkClassName()
169             && checkName(aMethod)
170             && checkModifiers(aMethod)
171             && checkType(aMethod)
172             && checkParams(aMethod))
173         {
174             log(aMethod.getLineNo(), "uncommented.main");
175         }
176     }
177
178     /**
179      * Checks that current class is not excluded
180      * @return true if check passed, false otherwise
181      */

182     private boolean checkClassName()
183     {
184         return !mExcludedClassesPattern.matcher(mCurrentClass).find();
185     }
186
187     /**
188      * Checks that method name is @quot;main@quot;.
189      * @param aMethod the METHOD_DEF node
190      * @return true if check passed, false otherwise
191      */

192     private boolean checkName(DetailAST aMethod)
193     {
194         final DetailAST ident = aMethod.findFirstToken(TokenTypes.IDENT);
195         return "main".equals(ident.getText());
196     }
197
198     /**
199      * Checks that method has final and static modifiers.
200      * @param aMethod the METHOD_DEF node
201      * @return true if check passed, false otherwise
202      */

203     private boolean checkModifiers(DetailAST aMethod)
204     {
205         final DetailAST modifiers =
206             aMethod.findFirstToken(TokenTypes.MODIFIERS);
207
208         return modifiers.branchContains(TokenTypes.LITERAL_PUBLIC)
209             && modifiers.branchContains(TokenTypes.LITERAL_STATIC);
210     }
211
212     /**
213      * Checks that return type is <code>void</code>.
214      * @param aMethod the METHOD_DEF node
215      * @return true if check passed, false otherwise
216      */

217     private boolean checkType(DetailAST aMethod)
218     {
219         final DetailAST type =
220             (DetailAST) aMethod.findFirstToken(TokenTypes.TYPE).getFirstChild();
221         return type.getType() == TokenTypes.LITERAL_VOID;
222     }
223
224     /**
225      * Checks that method has only <code>String[]</code> param
226      * @param aMethod the METHOD_DEF node
227      * @return true if check passed, false otherwise
228      */

229     private boolean checkParams(DetailAST aMethod)
230     {
231         final DetailAST params = aMethod.findFirstToken(TokenTypes.PARAMETERS);
232         if (params.getChildCount() != 1) {
233             return false;
234         }
235         final DetailAST paramType = ((DetailAST) params.getFirstChild())
236             .findFirstToken(TokenTypes.TYPE);
237         final DetailAST arrayDecl =
238             paramType.findFirstToken(TokenTypes.ARRAY_DECLARATOR);
239         if (arrayDecl == null) {
240             return false;
241         }
242
243         final DetailAST arrayType = (DetailAST) arrayDecl.getFirstChild();
244
245         if ((arrayType.getType() == TokenTypes.IDENT)
246             || (arrayType.getType() == TokenTypes.DOT))
247         {
248             final FullIdent type = FullIdent.createFullIdent(arrayType);
249             return ("String".equals(type.getText())
250                     || "java.lang.String".equals(type.getText()));
251         }
252
253         return false;
254     }
255 }
256
Popular Tags