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 * <module name="usage.OneMethodPrivateField"/>
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 }