001: ////////////////////////////////////////////////////////////////////////////////
002: // checkstyle: Checks Java source code for adherence to a set of rules.
003: // Copyright (C) 2001-2005 Oliver Burn
004: //
005: // This library is free software; you can redistribute it and/or
006: // modify it under the terms of the GNU Lesser General Public
007: // License as published by the Free Software Foundation; either
008: // version 2.1 of the License, or (at your option) any later version.
009: //
010: // This library is distributed in the hope that it will be useful,
011: // but WITHOUT ANY WARRANTY; without even the implied warranty of
012: // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013: // Lesser General Public License for more details.
014: //
015: // You should have received a copy of the GNU Lesser General Public
016: // License along with this library; if not, write to the Free Software
017: // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
018: ////////////////////////////////////////////////////////////////////////////////
019: package com.puppycrawl.tools.checkstyle.checks.usage;
020:
021: import com.puppycrawl.tools.checkstyle.api.Check;
022: import com.puppycrawl.tools.checkstyle.api.DetailAST;
023: import com.puppycrawl.tools.checkstyle.api.TokenTypes;
024: import com.puppycrawl.tools.checkstyle.api.Utils;
025: import com.puppycrawl.tools.checkstyle.checks.usage.transmogrify.ASTManager;
026: import com.puppycrawl.tools.checkstyle.checks.usage.transmogrify.ClassManager;
027: import com.puppycrawl.tools.checkstyle.checks.usage.transmogrify.Definition;
028: import com.puppycrawl.tools.checkstyle.checks.usage.transmogrify.SymTabAST;
029: import com.puppycrawl.tools.checkstyle.checks.usage.transmogrify.SymbolTableException;
030: import java.util.Iterator;
031: import java.util.Set;
032: import java.util.regex.Pattern;
033: import java.util.regex.PatternSyntaxException;
034:
035: import org.apache.commons.beanutils.ConversionException;
036:
037: /**
038: * Performs a usage check for fields, methods, parameters, variables.
039: * @author Rick Giles
040: */
041: public abstract class AbstractUsageCheck extends Check {
042: /** the regexp to match against */
043: private Pattern mRegexp;
044: /** the format string of the regexp */
045: private String mIgnoreFormat;
046:
047: /**
048: * Constructs an <code>AbstractUsageCheck</code>.
049: */
050: public AbstractUsageCheck() {
051: setIgnoreFormat("^$");
052: }
053:
054: /**
055: * Set the ignore format to the specified regular expression.
056: * @param aFormat a <code>String</code> value
057: * @throws ConversionException unable to parse aFormat
058: */
059: public void setIgnoreFormat(String aFormat)
060: throws ConversionException {
061: try {
062: mRegexp = Utils.getPattern(aFormat);
063: mIgnoreFormat = aFormat;
064: } catch (PatternSyntaxException e) {
065: throw new ConversionException("unable to parse " + aFormat,
066: e);
067: }
068: }
069:
070: /** @return the regexp to match against */
071: public Pattern getRegexp() {
072: return mRegexp;
073: }
074:
075: /** @return the regexp format */
076: public String getIgnoreFormat() {
077: return mIgnoreFormat;
078: }
079:
080: /** @see com.puppycrawl.tools.checkstyle.api.Check */
081: public void beginTree(DetailAST aRootAST) {
082: // use my class loader
083: ClassManager.setClassLoader(getClassLoader());
084:
085: final String fileName = getFileContents().getFilename();
086: getASTManager().addTree(fileName, aRootAST);
087: }
088:
089: /** @see com.puppycrawl.tools.checkstyle.api.Check */
090: public void visitToken(DetailAST aAST) {
091: if (mustCheckReferenceCount(aAST)) {
092: final DetailAST nameAST = aAST
093: .findFirstToken(TokenTypes.IDENT);
094: Pattern regexp = getRegexp();
095: if ((regexp == null)
096: || !regexp.matcher(nameAST.getText()).find()) {
097: getASTManager().registerCheckNode(this , nameAST);
098: }
099: }
100: }
101:
102: /** @see com.puppycrawl.tools.checkstyle.api.Check */
103: public void finishTree(DetailAST aAST) {
104: if (aAST == null) {
105: // we have nothing to check
106: return;
107: }
108: try {
109: final Set nodes = getASTManager().getCheckNodes(this );
110: if (nodes != null) {
111: applyTo(nodes);
112: }
113: } catch (SymbolTableException ste) {
114: logError(ste);
115: }
116: getASTManager().removeCheck(this );
117: }
118:
119: /**
120: * Logs an exception.
121: * @param aException the exception to log.
122: */
123: public void logError(Exception aException) {
124: log(0, "general.exception", new String[] { aException
125: .getMessage() });
126: Utils.getExceptionLogger().debug("An exception occured.",
127: aException);
128: }
129:
130: /**
131: * Determines the reference count for a DetailAST.
132: * @param aAST the DetailAST to count.
133: * @return the number of references to aAST.
134: */
135: private int getReferenceCount(DetailAST aAST) {
136: final SymTabAST ident = getASTManager().get(aAST);
137: if (ident == null) {
138: return 0;
139: }
140: final Definition definition = (Definition) ident
141: .getDefinition();
142: if (definition != null) {
143: return definition.getNumReferences();
144: }
145:
146: return 0;
147: }
148:
149: /**
150: * Returns the key for the Checkstyle error message.
151: * @return the key for the Checkstyle error message.
152: */
153: public abstract String getErrorKey();
154:
155: /**
156: * Determines whether the reference count of an aAST is required.
157: * @param aAST the node to check.
158: * @return true if the reference count of aAST is required.
159: */
160: public abstract boolean mustCheckReferenceCount(DetailAST aAST);
161:
162: /**
163: * Applies this check to a set of nodes.
164: * @param aNodes the nodes to check.
165: */
166: public void applyTo(Set aNodes) {
167: final Iterator it = aNodes.iterator();
168: while (it.hasNext()) {
169: final DetailAST nameAST = (DetailAST) it.next();
170: if (getReferenceCount(nameAST) == 1) {
171: log(nameAST.getLineNo(), nameAST.getColumnNo(),
172: getErrorKey(), nameAST.getText());
173: }
174: }
175: }
176:
177: /**
178: * Gets the manager for AST nodes.
179: * @return the AST manager.
180: */
181: protected ASTManager getASTManager() {
182: return ASTManager.getInstance();
183: }
184: }
|