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.whitespace;
020:
021: import com.puppycrawl.tools.checkstyle.api.Check;
022: import com.puppycrawl.tools.checkstyle.api.TokenTypes;
023: import com.puppycrawl.tools.checkstyle.api.DetailAST;
024:
025: /**
026: * <p>
027: * Checks that a token is followed by whitespace, with the exception that it
028: * does not check for whitespace after the semicolon of an empty for iterator.
029: * Use Check {@link EmptyForIteratorPadCheck EmptyForIteratorPad} to validate
030: * empty for iterators.
031: * </p>
032: * <p> By default the check will check the following tokens:
033: * {@link TokenTypes#COMMA COMMA},
034: * {@link TokenTypes#SEMI SEMI},
035: * {@link TokenTypes#TYPECAST TYPECAST}.
036: * </p>
037: * <p>
038: * An example of how to configure the check is:
039: * </p>
040: * <pre>
041: * <module name="WhitespaceAfter"/>
042: * </pre>
043: * <p> An example of how to configure the check for whitespace only after
044: * {@link TokenTypes#COMMA COMMA} and {@link TokenTypes#SEMI SEMI} tokens is:
045: * </p>
046: * <pre>
047: * <module name="WhitespaceAfter">
048: * <property name="tokens" value="COMMA, SEMI"/>
049: * </module>
050: * </pre>
051: * @author Oliver Burn
052: * @author Rick Giles
053: * @version 1.0
054: */
055: public class WhitespaceAfterCheck extends Check {
056: /** {@inheritDoc} */
057: public int[] getDefaultTokens() {
058: return new int[] { TokenTypes.COMMA, TokenTypes.SEMI,
059: TokenTypes.TYPECAST, };
060: }
061:
062: /** {@inheritDoc} */
063: public void visitToken(DetailAST aAST) {
064: final Object[] message;
065: final DetailAST targetAST;
066: if (aAST.getType() == TokenTypes.TYPECAST) {
067: targetAST = aAST.findFirstToken(TokenTypes.RPAREN);
068: // TODO: i18n
069: message = new Object[] { "cast" };
070: } else {
071: targetAST = aAST;
072: message = new Object[] { aAST.getText() };
073: }
074: final String line = getLines()[targetAST.getLineNo() - 1];
075: final int after = targetAST.getColumnNo()
076: + targetAST.getText().length();
077:
078: if (after < line.length()) {
079:
080: final char charAfter = line.charAt(after);
081: if ((targetAST.getType() == TokenTypes.SEMI)
082: && ((charAfter == ';') || (charAfter == ')'))) {
083: return;
084: }
085: if (!Character.isWhitespace(charAfter)) {
086: //empty FOR_ITERATOR?
087: if (targetAST.getType() == TokenTypes.SEMI) {
088: final DetailAST sibling = (DetailAST) targetAST
089: .getNextSibling();
090: if ((sibling != null)
091: && (sibling.getType() == TokenTypes.FOR_ITERATOR)
092: && (sibling.getChildCount() == 0)) {
093: return;
094: }
095: }
096: log(targetAST.getLineNo(), targetAST.getColumnNo()
097: + targetAST.getText().length(),
098: "ws.notFollowed", message);
099: }
100: }
101: }
102: }
|