Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/puppycrawl/tools/checkstyle/checks/design/MutableExceptionCheck.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.design;
20  
21  import com.puppycrawl.tools.checkstyle.api.DetailAST;
22  import com.puppycrawl.tools.checkstyle.api.TokenTypes;
23  import com.puppycrawl.tools.checkstyle.checks.AbstractFormatCheck;
24  
25  import java.util.Stack;
26  
27  /**
28   * <p> Ensures that exceptions (defined as any class name conforming
29   * to some regular expression) are immutable. That is, have only final
30   * fields.</p>
31   * <p> Rationale: Exception instances should represent an error
32   * condition. Having non final fields not only allows the state to be
33   * modified by accident and therefore mask the original condition but
34   * also allows developers to accidentally forget to initialise state
35   * thereby leading to code catching the exception to draw incorrect
36   * conclusions based on the state.</p>
37   *
38   * @author <a href="mailto:simon@redhillconsulting.com.au">Simon Harris</a>
39   */
40  public final class MutableExceptionCheck extends AbstractFormatCheck
41  {
42      /** Default value for format property. */
43      private static final String DEFAULT_FORMAT = "^.*Exception$|^.*Error$";
44      /** Stack of checking information for classes. */
45      private final Stack mCheckingStack = new Stack();
46      /** Should we check current class or not. */
47      private boolean mChecking;
48  
49      /** Creates new instance of the check. */
50      public MutableExceptionCheck()
51      {
52          super(DEFAULT_FORMAT);
53      }
54  
55      /** @see com.puppycrawl.tools.checkstyle.api.Check */
56      public int[] getDefaultTokens()
57      {
58          return new int[] {TokenTypes.CLASS_DEF, TokenTypes.VARIABLE_DEF};
59      }
60  
61      /** @see com.puppycrawl.tools.checkstyle.api.Check */
62      public int[] getRequiredTokens()
63      {
64          return getDefaultTokens();
65      }
66  
67      /** @see com.puppycrawl.tools.checkstyle.api.Check */
68      public void visitToken(DetailAST aAST)
69      {
70          switch (aAST.getType()) {
71          case TokenTypes.CLASS_DEF:
72              visitClassDef(aAST);
73              break;
74          case TokenTypes.VARIABLE_DEF:
75              visitVariableDef(aAST);
76              break;
77          default:
78              throw new IllegalStateException(aAST.toString());
79          }
80      }
81  
82      /** @see com.puppycrawl.tools.checkstyle.api.Check */
83      public void leaveToken(DetailAST aAST)
84      {
85          switch (aAST.getType()) {
86          case TokenTypes.CLASS_DEF:
87              leaveClassDef();
88              break;
89          default:
90              // Do nothing
91          }
92      }
93  
94      /**
95       * Called when we start processing class definition.
96       * @param aAST class definition node
97       */
98      private void visitClassDef(DetailAST aAST)
99      {
100         mCheckingStack.push(Boolean.valueOf(mChecking));
101         mChecking =
102             isExceptionClass(aAST.findFirstToken(TokenTypes.IDENT).getText());
103     }
104 
105     /** Called when we leave class definition. */
106     private void leaveClassDef()
107     {
108         mChecking = ((Boolean) mCheckingStack.pop()).booleanValue();
109     }
110 
111     /**
112      * Checks variable definition.
113      * @param aAST variable def node for check.
114      */
115     private void visitVariableDef(DetailAST aAST)
116     {
117         if (mChecking && aAST.getParent().getType() == TokenTypes.OBJBLOCK) {
118             DetailAST modifiersAST = aAST.findFirstToken(TokenTypes.MODIFIERS);
119 
120             if (!(modifiersAST.findFirstToken(TokenTypes.FINAL) != null)) {
121                 log(aAST.getLineNo(),  aAST.getColumnNo(), "mutable.exception",
122                         aAST.findFirstToken(TokenTypes.IDENT).getText());
123             }
124         }
125     }
126 
127     /**
128      * @param aClassName class name to check
129      * @return true if a given class name confirms specified format
130      */
131     private boolean isExceptionClass(String aClassName)
132     {
133         return getRegexp().match(aClassName);
134     }
135 }