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/usage/OneMethodPrivateFieldCheck.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.usage;
20  
21  import java.util.HashSet;
22  import java.util.Iterator;
23  import java.util.Set;
24  
25  import com.puppycrawl.tools.checkstyle.api.DetailAST;
26  import com.puppycrawl.tools.checkstyle.api.Scope;
27  import com.puppycrawl.tools.checkstyle.api.ScopeUtils;
28  import com.puppycrawl.tools.checkstyle.api.TokenTypes;
29  import com.puppycrawl.tools.checkstyle.checks.usage.transmogrify.ASTManager;
30  import com.puppycrawl.tools.checkstyle.checks.usage.transmogrify.Definition;
31  import com.puppycrawl.tools.checkstyle.checks.usage.transmogrify.Reference;
32  import com.puppycrawl.tools.checkstyle.checks.usage.transmogrify.SymTabAST;
33  
34  
35  /**
36   * <p>Checks that a private field is used in more than one method,
37   * constructor, or initializer.
38   * </p>
39   * <p>
40   * Rationale: a private field used in only one method, constructor, or
41   * initializer should be replaced by a local variable.
42   * </p>
43   * <p>
44   * An example of how to configure the check is:
45   * </p>
46   * <pre>
47   * &lt;module name="usage.OneMethodPrivateField"/&gt;
48   * </pre>
49   * <p>
50   * @author Rick Giles
51   */
52  public class OneMethodPrivateFieldCheck
53      extends AbstractUsageCheck
54  {
55      /** @see com.puppycrawl.tools.checkstyle.api.Check */
56      public int[] getDefaultTokens()
57      {
58          return new int[] {
59              TokenTypes.VARIABLE_DEF,
60          };
61      }
62  
63      /** @see com.puppycrawl.tools.checkstyle.checks.usage.AbstractUsageCheck */
64      public String getErrorKey()
65      {
66          return "one.method.private.field";
67      }
68  
69      /** @see com.puppycrawl.tools.checkstyle.checks.usage.AbstractUsageCheck */
70      public boolean mustCheckReferenceCount(DetailAST aAST)
71      {
72          final DetailAST mods = aAST.findFirstToken(TokenTypes.MODIFIERS);
73          return ((mods != null)
74              && (ScopeUtils.getScopeFromMods(mods) == Scope.PRIVATE));
75      }
76  
77      /** @see com.puppycrawl.tools.checkstyle.checks.usage.AbstractUsageCheck */
78      public void applyTo(Set aNodes)
79      {
80          // apply the check to each private field
81          final Set methods = new HashSet();
82          final Iterator it = aNodes.iterator();
83          while (it.hasNext()) {
84              methods.clear();
85              final DetailAST nameAST = (DetailAST) it.next();
86              // find methods using the field
87              final Iterator refIt = getReferences(nameAST);
88              while (refIt.hasNext()) {
89                  final Reference ref = (Reference) refIt.next();
90                  final SymTabAST refNode = ref.getTreeNode();
91                  final DetailAST refDetail = refNode.getDetailNode();
92                  // don't need to check a self-reference
93                  if (refDetail == nameAST) {
94                      continue;
95                  }
96                  DetailAST parent = refDetail.getParent();
97                  while (parent != null) {
98                      final int type = parent.getType();
99                      if ((type == TokenTypes.METHOD_DEF)
100                         || (type == TokenTypes.CTOR_DEF)
101                         || (type == TokenTypes.INSTANCE_INIT)
102                         || (type == TokenTypes.STATIC_INIT))
103                     {
104                         methods.add(parent);
105                         break;
106                     }
107                     // initializer for inner class?
108                     else if (type == TokenTypes.CLASS_DEF) {
109                         break;
110                     }
111                     parent = parent.getParent();
112                 }
113             }
114             if (methods.size() == 1) {
115                 log(
116                     nameAST.getLineNo(),
117                     nameAST.getColumnNo(),
118                     getErrorKey(),
119                     nameAST.getText());
120             }
121         }
122     }
123 
124     /**
125      * Returns the references to an AST.
126      * @param aAST the AST for the references.
127      * @return an iterator for the references to aAST.
128      */
129     private Iterator getReferences(DetailAST aAST)
130     {
131         final SymTabAST ident = ASTManager.getInstance().get(aAST);
132         final Definition definition =
133             (Definition) ident.getDefinition();
134         if (definition != null) {
135             return definition.getReferences();
136         }
137         else {
138             final Set dummy = new HashSet();
139             return dummy.iterator();
140         }
141     }
142 }