KickJava   Java API By Example, From Geeks To Geeks.

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


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

20 package com.puppycrawl.tools.checkstyle.checks.coding;
21
22 import java.util.LinkedList JavaDoc;
23
24 import antlr.collections.AST;
25
26 import com.puppycrawl.tools.checkstyle.api.Check;
27 import com.puppycrawl.tools.checkstyle.api.DetailAST;
28 import com.puppycrawl.tools.checkstyle.api.ScopeUtils;
29 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
30
31 /**
32  * <p>
33  * Abstract class for checking that an overriding method with no parameters
34  * invokes the super method.
35  * </p>
36  * @author Rick Giles
37  */

38 public abstract class AbstractSuperCheck
39         extends Check
40 {
41     /**
42      * Stack node for a method definition and a record of
43      * whether the method has a call to the super method.
44      * @author Rick Giles
45      */

46     private class MethodNode
47     {
48         /** method definition */
49         private DetailAST mMethod;
50
51         /** true if the overriding method calls the super method */
52         private boolean mCallsSuper;
53
54         /**
55          * Constructs a stack node for a method definition.
56          * @param aAST AST for the method definition.
57          */

58         public MethodNode(DetailAST aAST)
59         {
60             mMethod = aAST;
61             mCallsSuper = false;
62         }
63
64         /**
65          * Records that the overriding method has a call to the super method.
66          */

67         public void setCallsSuper()
68         {
69             mCallsSuper = true;
70         }
71
72         /**
73          * Determines whether the overriding method has a call to the super
74          * method.
75          * @return true if the overriding method has a call to the super
76          * method.
77          */

78         public boolean getCallsSuper()
79         {
80             return mCallsSuper;
81         }
82
83         /**
84          * Returns the overriding method definition AST.
85          * @return the overriding method definition AST.
86          */

87         public DetailAST getMethod()
88         {
89             return mMethod;
90         }
91     }
92
93     /** stack of methods */
94     private final LinkedList JavaDoc mMethodStack = new LinkedList JavaDoc();
95
96     /** {@inheritDoc} */
97     public int[] getDefaultTokens()
98     {
99         return new int[] {
100             TokenTypes.METHOD_DEF,
101             TokenTypes.LITERAL_SUPER,
102         };
103     }
104
105     /**
106      * Returns the name of the overriding method.
107      * @return the name of the overriding method.
108      */

109     protected abstract String JavaDoc getMethodName();
110
111     /**
112      * {@inheritDoc}
113      */

114     public void beginTree(DetailAST aRootAST)
115     {
116         mMethodStack.clear();
117     }
118
119     /**
120      *
121      * {@inheritDoc}
122      */

123     public void visitToken(DetailAST aAST)
124     {
125         if (isOverridingMethod(aAST)) {
126             mMethodStack.add(new MethodNode(aAST));
127         }
128         else if (isSuperCall(aAST)) {
129             final MethodNode methodNode = (MethodNode) mMethodStack.getLast();
130             methodNode.setCallsSuper();
131         }
132     }
133
134     /**
135      * Determines whether a 'super' literal is a call to the super method
136      * for this check.
137      * @param aAST the AST node of a 'super' literal.
138      * @return true if aAST is a call to the super method
139      * for this check.
140      */

141     private boolean isSuperCall(DetailAST aAST)
142     {
143         if (aAST.getType() != TokenTypes.LITERAL_SUPER) {
144             return false;
145         }
146         // dot operator?
147
DetailAST parent = aAST.getParent();
148         if ((parent == null) || (parent.getType() != TokenTypes.DOT)) {
149             return false;
150         }
151
152         // same name of method
153
AST sibling = aAST.getNextSibling();
154         // ignore type parameters
155
if ((sibling != null)
156             && (sibling.getType() == TokenTypes.TYPE_ARGUMENTS))
157         {
158             sibling = sibling.getNextSibling();
159         }
160         if ((sibling == null) || (sibling.getType() != TokenTypes.IDENT)) {
161             return false;
162         }
163         final String JavaDoc name = sibling.getText();
164         if (!getMethodName().equals(name)) {
165             return false;
166         }
167
168         // 0 parameters?
169
final DetailAST args = (DetailAST) parent.getNextSibling();
170         if ((args == null) || (args.getType() != TokenTypes.ELIST)) {
171             return false;
172         }
173         if (args.getChildCount() != 0) {
174             return false;
175         }
176
177         // in an overriding method for this check?
178
while (parent != null) {
179             if (parent.getType() == TokenTypes.METHOD_DEF) {
180                 return isOverridingMethod(parent);
181             }
182             else if ((parent.getType() == TokenTypes.CTOR_DEF)
183                 || (parent.getType() == TokenTypes.INSTANCE_INIT))
184             {
185                 return false;
186             }
187             parent = parent.getParent();
188         }
189         return false;
190     }
191
192     /**
193      * {@inheritDoc}
194      */

195     public void leaveToken(DetailAST aAST)
196     {
197         if (isOverridingMethod(aAST)) {
198             final MethodNode methodNode =
199                 (MethodNode) mMethodStack.removeLast();
200             if (!methodNode.getCallsSuper()) {
201                 final DetailAST methodAST = methodNode.getMethod();
202                 final DetailAST nameAST =
203                     methodAST.findFirstToken(TokenTypes.IDENT);
204                 log(nameAST.getLineNo(), nameAST.getColumnNo(),
205                     "missing.super.call",
206                     new Object JavaDoc[] {nameAST.getText()});
207             }
208         }
209     }
210
211     /**
212      * Determines whether an AST is a method definition for this check,
213      * with 0 parameters.
214      * @param aAST the method definition AST.
215      * @return true if the method of aAST is a method for this check.
216      */

217     private boolean isOverridingMethod(DetailAST aAST)
218     {
219         if ((aAST.getType() != TokenTypes.METHOD_DEF)
220             || ScopeUtils.inInterfaceOrAnnotationBlock(aAST))
221         {
222             return false;
223         }
224         final DetailAST nameAST = aAST.findFirstToken(TokenTypes.IDENT);
225         final String JavaDoc name = nameAST.getText();
226         if (!getMethodName().equals(name)) {
227             return false;
228         }
229         final DetailAST params = aAST.findFirstToken(TokenTypes.PARAMETERS);
230         return (params.getChildCount() == 0);
231     }
232 }
233
Popular Tags