001: ////////////////////////////////////////////////////////////////////////////////
002: // checkstyle: Checks Java source code for adherence to a set of rules.
003: // Copyright (C) 2001-2007 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.design;
020:
021: import com.puppycrawl.tools.checkstyle.api.DetailAST;
022: import com.puppycrawl.tools.checkstyle.api.Check;
023: import com.puppycrawl.tools.checkstyle.api.TokenTypes;
024:
025: /**
026: * <p>
027: * Restricts throws statements to a specified count (default = 1).
028: * </p>
029: * <p>
030: * Rationale:
031: * Exceptions form part of a methods interface. Declaring
032: * a method to throw too many differently rooted
033: * exceptions makes exception handling onerous and leads
034: * to poor programming practices such as catch
035: * (Exception). This check forces developers to put
036: * exceptions into a heirachy such that in the simplest
037: * case, only one type of exception need be checked for by
038: * a caller but allows any sub-classes to be caught
039: * specifically if necessary.
040: * </p>
041: * @author <a href="mailto:simon@redhillconsulting.com.au">Simon Harris</a>
042: */
043: public final class ThrowsCountCheck extends Check {
044: /** default value of max property */
045: private static final int DEFAULT_MAX = 1;
046:
047: /** maximum allowed throws statments */
048: private int mMax;
049:
050: /** Creates new instance of the check. */
051: public ThrowsCountCheck() {
052: setMax(DEFAULT_MAX);
053: }
054:
055: /** {@inheritDoc} */
056: public int[] getDefaultTokens() {
057: return new int[] { TokenTypes.LITERAL_THROWS, };
058: }
059:
060: /** {@inheritDoc} */
061: public int[] getRequiredTokens() {
062: return getDefaultTokens();
063: }
064:
065: /**
066: * Getter for max property.
067: * @return maximum allowed throws statements.
068: */
069: public int getMax() {
070: return mMax;
071: }
072:
073: /**
074: * Setter for max property.
075: * @param aMax maximum allowed throws statements.
076: */
077: public void setMax(int aMax) {
078: mMax = aMax;
079: }
080:
081: /** {@inheritDoc} */
082: public void visitToken(DetailAST aAST) {
083: switch (aAST.getType()) {
084: case TokenTypes.LITERAL_THROWS:
085: visitLiteralThrows(aAST);
086: break;
087: default:
088: throw new IllegalStateException(aAST.toString());
089: }
090: }
091:
092: /**
093: * Checks number of throws statments.
094: * @param aAST throws for check.
095: */
096: private void visitLiteralThrows(DetailAST aAST) {
097: // Account for all the commas!
098: final int count = (aAST.getChildCount() + 1) / 2;
099: if (count > getMax()) {
100: log(aAST.getLineNo(), aAST.getColumnNo(), "throws.count",
101: new Integer(count), new Integer(getMax()));
102: }
103: }
104: }
|