Source code: com/puppycrawl/tools/checkstyle/checks/usage/AbstractUsageCheck.java
1 ////////////////////////////////////////////////////////////////////////////////
2 // checkstyle: Checks Java source code for adherence to a set of rules.
3 // Copyright (C) 2001-2003 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.usage;
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 import com.puppycrawl.tools.checkstyle.api.Utils;
25 import com.puppycrawl.tools.checkstyle.checks.usage.transmogrify.ASTManager;
26 import com.puppycrawl.tools.checkstyle.checks.usage.transmogrify.ClassManager;
27 import com.puppycrawl.tools.checkstyle.checks.usage.transmogrify.Definition;
28 import com.puppycrawl.tools.checkstyle.checks.usage.transmogrify.SymTabAST;
29 import com.puppycrawl.tools.checkstyle.checks.usage.transmogrify.
30 SymbolTableException;
31 import java.util.Iterator;
32 import java.util.Set;
33 import org.apache.commons.beanutils.ConversionException;
34 import org.apache.regexp.RE;
35 import org.apache.regexp.RESyntaxException;
36
37 /**
38 * Performs a usage check for fields, methods, parameters, variables.
39 * @author Rick Giles
40 */
41 public abstract class AbstractUsageCheck
42 extends Check
43 {
44 /** the regexp to match against */
45 private RE mRegexp;
46 /** the format string of the regexp */
47 private String mIgnoreFormat;
48
49 /**
50 * Constructs an <code>AbstractUsageCheck</code>.
51 */
52 public AbstractUsageCheck()
53 {
54 setIgnoreFormat("^$");
55 }
56
57 /**
58 * Set the ignore format to the specified regular expression.
59 * @param aFormat a <code>String</code> value
60 * @throws ConversionException unable to parse aFormat
61 */
62 public void setIgnoreFormat(String aFormat)
63 throws ConversionException
64 {
65 try {
66 mRegexp = Utils.getRE(aFormat);
67 mIgnoreFormat = aFormat;
68 }
69 catch (RESyntaxException e) {
70 throw new ConversionException("unable to parse " + aFormat, e);
71 }
72 }
73
74 /** @return the regexp to match against */
75 public RE getRegexp()
76 {
77 return mRegexp;
78 }
79
80 /** @return the regexp format */
81 public String getIgnoreFormat()
82 {
83 return mIgnoreFormat;
84 }
85
86 /** @see com.puppycrawl.tools.checkstyle.api.Check */
87 public void beginTree(DetailAST aRootAST)
88 {
89 // use my class loader
90 ClassManager.setClassLoader(getClassLoader());
91
92 final String fileName = getFileContents().getFilename();
93 ASTManager.getInstance().addTree(fileName, aRootAST);
94 }
95
96 /** @see com.puppycrawl.tools.checkstyle.api.Check */
97 public void visitToken(DetailAST aAST)
98 {
99 if (mustCheckReferenceCount(aAST)) {
100 final DetailAST nameAST = aAST.findFirstToken(TokenTypes.IDENT);
101 RE regexp = getRegexp();
102 if ((regexp == null) || !regexp.match(nameAST.getText())) {
103 ASTManager.getInstance().registerCheckNode(this, nameAST);
104 }
105 }
106 }
107
108 /** @see com.puppycrawl.tools.checkstyle.api.Check */
109 public void finishTree(DetailAST aAST)
110 {
111 try {
112 final Set nodes = getASTManager().getCheckNodes(this);
113 if (nodes != null) {
114 applyTo(nodes);
115 }
116 }
117 catch (SymbolTableException ste) {
118 logError(ste);
119 }
120 ASTManager.getInstance().removeCheck(this);
121 }
122
123 /**
124 * Logs an exception.
125 * @param aException the exception to log.
126 */
127 public void logError(Exception aException)
128 {
129 log(0, "general.exception", new String[] {aException.getMessage()});
130 Utils.getExceptionLogger().debug("An exception occured.", aException);
131 }
132
133 /**
134 * Determines the reference count for a DetailAST.
135 * @param aAST the DetailAST to count.
136 * @return the number of references to aAST.
137 */
138 private int getReferenceCount(DetailAST aAST)
139 {
140 final SymTabAST ident = ASTManager.getInstance().get(aAST);
141 final Definition definition =
142 (Definition) ident.getDefinition();
143 if (definition != null) {
144 return definition.getNumReferences();
145 }
146 else {
147 return 0;
148 }
149 }
150
151 /**
152 * Returns the key for the Checkstyle error message.
153 * @return the key for the Checkstyle error message.
154 */
155 public abstract String getErrorKey();
156
157 /**
158 * Determines whether the reference count of an aAST is required.
159 * @param aAST the node to check.
160 * @return true if the reference count of aAST is required.
161 */
162 public abstract boolean mustCheckReferenceCount(DetailAST aAST);
163
164 /**
165 * Applies this check to a set of nodes.
166 * @param aNodes the nodes to check.
167 */
168 public void applyTo(Set aNodes)
169 {
170 final Iterator it = aNodes.iterator();
171 while (it.hasNext()) {
172 final DetailAST nameAST = (DetailAST) it.next();
173 if (getReferenceCount(nameAST) == 1) {
174 log(
175 nameAST.getLineNo(),
176 nameAST.getColumnNo(),
177 getErrorKey(),
178 nameAST.getText());
179 }
180 }
181 }
182
183 /**
184 * Gets the manager for AST nodes.
185 * @return the AST manager.
186 */
187 protected ASTManager getASTManager()
188 {
189 return ASTManager.getInstance();
190 }
191 }