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.modifier;
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.ScopeUtils;
025:
026: /**
027: * Checks for redundant modifiers in interface and annotation definitions.
028: * Also checks for redundant final modifiers on methods of final classes.
029: *
030: * @author lkuehne
031: */
032: public class RedundantModifierCheck extends Check {
033: /** {@inheritDoc} */
034: public int[] getDefaultTokens() {
035: return new int[] { TokenTypes.METHOD_DEF,
036: TokenTypes.VARIABLE_DEF,
037: TokenTypes.ANNOTATION_FIELD_DEF, };
038: }
039:
040: /** {@inheritDoc} */
041: public int[] getRequiredTokens() {
042: return new int[] {};
043: }
044:
045: /** {@inheritDoc} */
046: public void visitToken(DetailAST aAST) {
047: if (ScopeUtils.inInterfaceOrAnnotationBlock(aAST)) {
048: final DetailAST modifiers = aAST
049: .findFirstToken(TokenTypes.MODIFIERS);
050:
051: DetailAST modifier = (DetailAST) modifiers.getFirstChild();
052: while (modifier != null) {
053:
054: // javac does not allow final or static in interface methods
055: // order annotation fields hence no need to check that this
056: // is not a method or annotation field
057:
058: final int type = modifier.getType();
059: if ((type == TokenTypes.LITERAL_PUBLIC)
060: || (type == TokenTypes.ABSTRACT)
061: || (type == TokenTypes.LITERAL_STATIC)
062: || (type == TokenTypes.FINAL)) {
063: log(modifier.getLineNo(), modifier.getColumnNo(),
064: "redundantModifier",
065: new String[] { modifier.getText() });
066: break;
067: }
068:
069: modifier = (DetailAST) modifier.getNextSibling();
070: }
071: } else if (aAST.getType() == TokenTypes.METHOD_DEF) {
072: final DetailAST modifiers = aAST
073: .findFirstToken(TokenTypes.MODIFIERS);
074: // private method?
075: boolean checkFinal = modifiers
076: .branchContains(TokenTypes.LITERAL_PRIVATE);
077: // declared in a final class?
078: DetailAST parent = aAST.getParent();
079: while (parent != null) {
080: if (parent.getType() == TokenTypes.CLASS_DEF) {
081: final DetailAST classModifiers = parent
082: .findFirstToken(TokenTypes.MODIFIERS);
083: checkFinal |= classModifiers
084: .branchContains(TokenTypes.FINAL);
085: break;
086: }
087: parent = parent.getParent();
088: }
089: if (checkFinal) {
090: DetailAST modifier = (DetailAST) modifiers
091: .getFirstChild();
092: while (modifier != null) {
093: final int type = modifier.getType();
094: if (type == TokenTypes.FINAL) {
095: log(modifier.getLineNo(), modifier
096: .getColumnNo(), "redundantModifier",
097: new String[] { modifier.getText() });
098: break;
099: }
100: modifier = (DetailAST) modifier.getNextSibling();
101: }
102: }
103: }
104: }
105: }
|