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/InnerAssignmentCheck.java


1   ////////////////////////////////////////////////////////////////////////////////
2   // checkstyle: Checks Java source code for adherence to a set of rules.
3   // Copyright (C) 2001-2002  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  
20  package com.puppycrawl.tools.checkstyle.checks;
21  
22  import com.puppycrawl.tools.checkstyle.api.Check;
23  import com.puppycrawl.tools.checkstyle.api.TokenTypes;
24  import com.puppycrawl.tools.checkstyle.api.DetailAST;
25  
26  /**
27   * <p>
28   * Checks for assignments in subexpressions, such as in
29   * <code>String s = Integer.toString(i = 2);</code>.
30   * </p>
31   * <p>
32   * Rationale: With the exception of <code>for</code> iterators, all assignments
33   * should occur in their own toplevel statement to increase readability.
34   * With inner assignments like the above it is difficult to see all places
35   * where a variable is set.
36   * </p>
37   * <p>
38   * By default the check will check the following assignment operators:
39   *  {@link TokenTypes#ASSIGN ASSIGN},
40   *  {@link TokenTypes#BAND_ASSIGN BAND_ASSIGN},
41   *  {@link TokenTypes#BOR_ASSIGN BOR_ASSIGN},
42   *  {@link TokenTypes#BSR_ASSIGN BSR_ASSIGN},
43   *  {@link TokenTypes#BXOR_ASSIGN BXOR_ASSIGN},
44   *  {@link TokenTypes#DIV_ASSIGN DIV_ASSIGN},
45   *  {@link TokenTypes#MINUS_ASSIGN MINUS_ASSIGN},
46   *  {@link TokenTypes#MOD_ASSIGN MOD_ASSIGN},
47   *  {@link TokenTypes#PLUS_ASSIGN PLUS_ASSIGN},
48   *  {@link TokenTypes#SL_ASSIGN SL_ASSIGN},
49   *  {@link TokenTypes#SR_ASSIGN SR_ASSIGN},
50   *  {@link TokenTypes#STAR_ASSIGN STAR_ASSIGN}.
51   * </p>
52   * <p> An example of how to configure the check is:
53   * <pre>
54   * &lt;module name="InnerAssignment"/&gt;
55   * </pre>
56   *
57   * <p> An example of how to configure the check for only <code>=</code>,
58   * <code>+=</code>, and <code>-=</code> operators is:
59   * </p>
60   * <pre>
61   * &lt;module name="InnerAssignment"&gt;
62   *    &lt;tokens&gt;ASSIGN, PLUS_ASSIGN, MINUS_ASSIGN&lt;/tokens&gt;
63   * &lt;/module&gt;
64   * </pre>
65  
66   * @author lkuehne
67   */
68  public class InnerAssignmentCheck
69          extends Check
70  {
71      /** @see Check */
72      public int[] getDefaultTokens()
73      {
74          return new int[] {
75              TokenTypes.ASSIGN,            // '='
76              TokenTypes.DIV_ASSIGN,        // "/="
77              TokenTypes.PLUS_ASSIGN,       // "+="
78              TokenTypes.MINUS_ASSIGN,      //"-="
79              TokenTypes.STAR_ASSIGN,       // "*="
80              TokenTypes.MOD_ASSIGN,        // "%="
81              TokenTypes.SR_ASSIGN,         // ">>="
82              TokenTypes.BSR_ASSIGN,        // ">>>="
83              TokenTypes.SL_ASSIGN,         // "<<="
84              TokenTypes.BXOR_ASSIGN,       // "^="
85              TokenTypes.BOR_ASSIGN,        // "|="
86              TokenTypes.BAND_ASSIGN,       // "&="
87          };
88      }
89  
90      /** @see Check */
91      public void visitToken(DetailAST aAST)
92      {
93          final DetailAST parent1 = aAST.getParent();
94          final DetailAST parent2 = parent1.getParent();
95          final DetailAST parent3 = parent2.getParent();
96  
97          final boolean assigment = isAssignment(parent1);
98          final boolean expr = parent1.getType() == TokenTypes.EXPR;
99          final boolean exprList =
100                 expr && parent2.getType() == TokenTypes.ELIST;
101         final boolean methodCall =
102                 exprList && parent3.getType() == TokenTypes.METHOD_CALL;
103         final boolean ctorCall =
104                 exprList && parent3.getType() == TokenTypes.LITERAL_NEW;
105 
106         if (assigment || methodCall || ctorCall) {
107             log(aAST.getLineNo(), aAST.getColumnNo(), "assignment.inner.avoid");
108         }
109     }
110 
111     /**
112      * Checks if an AST is an assignment operator.
113      * @param aAST the AST to check
114      * @return true iff aAST is an assignment operator.
115      */
116     private boolean isAssignment(DetailAST aAST)
117     {
118         // TODO: make actual tokens available to Check and loop over actual
119         // tokens here?
120         final int[] tokens = getDefaultTokens();
121 
122         final int astType = aAST.getType();
123 
124         for (int i = 0; i < tokens.length; i++) {
125             int tokenType = tokens[i];
126             if (astType == tokenType) {
127                 return true;
128             }
129         }
130         return false;
131     }
132 
133 
134 }