Source code: com/puppycrawl/tools/checkstyle/checks/imports/UnusedImportsCheck.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.imports;
20
21 import com.puppycrawl.tools.checkstyle.api.Check;
22 import com.puppycrawl.tools.checkstyle.api.DetailAST;
23 import com.puppycrawl.tools.checkstyle.api.FullIdent;
24 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
25 import com.puppycrawl.tools.checkstyle.api.Utils;
26 import java.util.HashSet;
27 import java.util.Iterator;
28 import java.util.Set;
29
30 /**
31 * <p>
32 * Checks for unused import statements.
33 * </p>
34 * <p>
35 * An example of how to configure the check is:
36 * </p>
37 * <pre>
38 * <module name="UnusedImports"/>
39 * </pre>
40 * @author Oliver Burn
41 * @version 1.0
42 */
43 public class UnusedImportsCheck
44 extends Check
45 {
46 /** flag to indicate when time to start collecting references */
47 private boolean mCollect;
48 /** set of the imports */
49 private final Set mImports = new HashSet();
50 /** set of references - possibly to imports or other things */
51 private final Set mReferenced = new HashSet();
52
53 /** @see com.puppycrawl.tools.checkstyle.api.Check */
54 public void beginTree(DetailAST aRootAST)
55 {
56 mCollect = false;
57 mImports.clear();
58 mReferenced.clear();
59 }
60
61 /** @see com.puppycrawl.tools.checkstyle.api.Check */
62 public void finishTree(DetailAST aRootAST)
63 {
64 // loop over all the imports to see if referenced.
65 final Iterator it = mImports.iterator();
66 while (it.hasNext()) {
67 final FullIdent imp = (FullIdent) it.next();
68
69 if (!mReferenced.contains(Utils.baseClassname(imp.getText()))) {
70 log(imp.getLineNo(),
71 imp.getColumnNo(),
72 "import.unused", imp.getText());
73 }
74 }
75 }
76
77 /** @see com.puppycrawl.tools.checkstyle.api.Check */
78 public int[] getDefaultTokens()
79 {
80 return new int[] {
81 TokenTypes.IMPORT,
82 TokenTypes.CLASS_DEF,
83 TokenTypes.INTERFACE_DEF,
84 TokenTypes.IDENT,
85 };
86 }
87
88 /** @see com.puppycrawl.tools.checkstyle.api.Check */
89 public void visitToken(DetailAST aAST)
90 {
91 if (aAST.getType() == TokenTypes.IDENT) {
92 if (mCollect) {
93 processIdent(aAST);
94 }
95 }
96 else if (aAST.getType() == TokenTypes.IMPORT) {
97 processImport(aAST);
98 }
99 else if ((aAST.getType() == TokenTypes.CLASS_DEF)
100 || (aAST.getType() == TokenTypes.INTERFACE_DEF))
101 {
102 mCollect = true;
103 }
104 }
105
106 /**
107 * Collects references made by IDENT.
108 * @param aAST the IDENT node to process
109 */
110 private void processIdent(DetailAST aAST)
111 {
112 // TODO: should be a lot smarter in selection. Currently use
113 // same algorithm as real checkstyle
114 final DetailAST parent = aAST.getParent();
115 if (parent.getType() == TokenTypes.DOT) {
116 if (aAST.getNextSibling() != null) {
117 mReferenced.add(aAST.getText());
118 }
119 }
120 else {
121 mReferenced.add(aAST.getText());
122 }
123 }
124
125 /**
126 * Collects the details of imports.
127 * @param aAST node containing the import details
128 */
129 private void processImport(DetailAST aAST)
130 {
131 final FullIdent name = FullIdent.createFullIdentBelow(aAST);
132 if ((name != null) && !name.getText().endsWith(".*")) {
133 mImports.add(name);
134 }
135 }
136 }