Coverage Report - com.puppycrawl.tools.checkstyle.checks.imports.UnusedImportsCheck
 
Classes in this File Line Coverage Branch Coverage Complexity
UnusedImportsCheck
98%
54/55
92%
35/38
2.727
 
 1  
 ////////////////////////////////////////////////////////////////////////////////
 2  
 // checkstyle: Checks Java source code for adherence to a set of rules.
 3  
 // Copyright (C) 2001-2014  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.checks.javadoc.JavadocTags;
 22  
 
 23  
 import com.google.common.collect.Sets;
 24  
 import com.puppycrawl.tools.checkstyle.api.Check;
 25  
 import com.puppycrawl.tools.checkstyle.api.DetailAST;
 26  
 import com.puppycrawl.tools.checkstyle.api.FileContents;
 27  
 import com.puppycrawl.tools.checkstyle.api.FullIdent;
 28  
 import com.puppycrawl.tools.checkstyle.api.TextBlock;
 29  
 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
 30  
 import com.puppycrawl.tools.checkstyle.api.Utils;
 31  
 import com.puppycrawl.tools.checkstyle.checks.javadoc.JavadocTag;
 32  
 import com.puppycrawl.tools.checkstyle.checks.javadoc.JavadocUtils;
 33  
 import java.util.Set;
 34  
 import java.util.regex.Matcher;
 35  
 import java.util.regex.Pattern;
 36  
 
 37  
 /**
 38  
  * <p>
 39  
  * Checks for unused import statements.
 40  
  * </p>
 41  
  *  <p>
 42  
  * An example of how to configure the check is:
 43  
  * </p>
 44  
  * <pre>
 45  
  * &lt;module name="UnusedImports"/&gt;
 46  
  * </pre>
 47  
  *
 48  
  * Compatible with Java 1.5 source.
 49  
  *
 50  
  * @author Oliver Burn
 51  
  */
 52  
 public class UnusedImportsCheck extends Check
 53  
 {
 54  
     /** flag to indicate when time to start collecting references */
 55  
     private boolean mCollect;
 56  
     /** flag whether to process Javadoc comments. */
 57  
     private boolean mProcessJavadoc;
 58  
 
 59  
     /** set of the imports */
 60  4
     private final Set<FullIdent> mImports = Sets.newHashSet();
 61  
 
 62  
     /** set of references - possibly to imports or other things */
 63  4
     private final Set<String> mReferenced = Sets.newHashSet();
 64  
 
 65  
     /** Default constructor. */
 66  
     public UnusedImportsCheck()
 67  4
     {
 68  4
     }
 69  
 
 70  
     public void setProcessJavadoc(boolean aValue)
 71  
     {
 72  1
         mProcessJavadoc = aValue;
 73  1
     }
 74  
 
 75  
     @Override
 76  
     public void beginTree(DetailAST aRootAST)
 77  
     {
 78  4
         mCollect = false;
 79  4
         mImports.clear();
 80  4
         mReferenced.clear();
 81  4
     }
 82  
 
 83  
     @Override
 84  
     public void finishTree(DetailAST aRootAST)
 85  
     {
 86  
         // loop over all the imports to see if referenced.
 87  4
         for (final FullIdent imp : mImports) {
 88  46
             if (!mReferenced.contains(Utils.baseClassname(imp.getText()))) {
 89  23
                 log(imp.getLineNo(),
 90  
                     imp.getColumnNo(),
 91  
                     "import.unused", imp.getText());
 92  
             }
 93  
         }
 94  4
     }
 95  
 
 96  
     @Override
 97  
     public int[] getDefaultTokens()
 98  
     {
 99  4
         return new int[] {
 100  
             TokenTypes.IDENT,
 101  
             TokenTypes.IMPORT,
 102  
             TokenTypes.STATIC_IMPORT,
 103  
             // Definitions that may contain Javadoc...
 104  
             TokenTypes.PACKAGE_DEF,
 105  
             TokenTypes.ANNOTATION_DEF,
 106  
             TokenTypes.ANNOTATION_FIELD_DEF,
 107  
             TokenTypes.ENUM_DEF,
 108  
             TokenTypes.ENUM_CONSTANT_DEF,
 109  
             TokenTypes.CLASS_DEF,
 110  
             TokenTypes.INTERFACE_DEF,
 111  
             TokenTypes.METHOD_DEF,
 112  
             TokenTypes.CTOR_DEF,
 113  
             TokenTypes.VARIABLE_DEF,
 114  
         };
 115  
     }
 116  
 
 117  
     @Override
 118  
     public int[] getRequiredTokens()
 119  
     {
 120  0
         return getDefaultTokens();
 121  
     }
 122  
 
 123  
     @Override
 124  
     public void visitToken(DetailAST aAST)
 125  
     {
 126  410
         if (aAST.getType() == TokenTypes.IDENT) {
 127  314
             if (mCollect) {
 128  314
                 processIdent(aAST);
 129  
             }
 130  
         }
 131  96
         else if (aAST.getType() == TokenTypes.IMPORT) {
 132  48
             processImport(aAST);
 133  
         }
 134  48
         else if (aAST.getType() == TokenTypes.STATIC_IMPORT) {
 135  10
             processStaticImport(aAST);
 136  
         }
 137  
         else {
 138  38
             mCollect = true;
 139  38
             if (mProcessJavadoc) {
 140  16
                 processJavadoc(aAST);
 141  
             }
 142  
         }
 143  410
     }
 144  
 
 145  
     /**
 146  
      * Collects references made by IDENT.
 147  
      * @param aAST the IDENT node to process
 148  
      */
 149  
     private void processIdent(DetailAST aAST)
 150  
     {
 151  314
         final DetailAST parent = aAST.getParent();
 152  314
         final int parentType = parent.getType();
 153  314
         if (((parentType != TokenTypes.DOT)
 154  
             && (parentType != TokenTypes.METHOD_DEF))
 155  
             || ((parentType == TokenTypes.DOT)
 156  
                 && (aAST.getNextSibling() != null)))
 157  
         {
 158  137
             mReferenced.add(aAST.getText());
 159  
         }
 160  314
     }
 161  
 
 162  
     /**
 163  
      * Collects the details of imports.
 164  
      * @param aAST node containing the import details
 165  
      */
 166  
     private void processImport(DetailAST aAST)
 167  
     {
 168  48
         final FullIdent name = FullIdent.createFullIdentBelow(aAST);
 169  48
         if ((name != null) && !name.getText().endsWith(".*")) {
 170  42
             mImports.add(name);
 171  
         }
 172  48
     }
 173  
 
 174  
     /**
 175  
      * Collects the details of static imports.
 176  
      * @param aAST node containing the static import details
 177  
      */
 178  
     private void processStaticImport(DetailAST aAST)
 179  
     {
 180  10
         final FullIdent name =
 181  
             FullIdent.createFullIdent(
 182  
                 aAST.getFirstChild().getNextSibling());
 183  10
         if ((name != null) && !name.getText().endsWith(".*")) {
 184  4
             mImports.add(name);
 185  
         }
 186  10
     }
 187  
 
 188  
     /**
 189  
      * Collects references made in JavaDoc comments.
 190  
      * @param aAST node to inspect for JavaDoc
 191  
      */
 192  
     private void processJavadoc(DetailAST aAST)
 193  
     {
 194  16
         final FileContents contents = getFileContents();
 195  16
         final int lineNo = aAST.getLineNo();
 196  16
         final TextBlock cmt = contents.getJavadocBefore(lineNo);
 197  16
         if (cmt != null) {
 198  12
             final JavadocTags tags = JavadocUtils.getJavadocTags(cmt,
 199  
                     JavadocUtils.JavadocTagType.ALL);
 200  12
             for (final JavadocTag tag : tags.getValidTags()) {
 201  10
                 if (tag.canReferenceImports()) {
 202  7
                     String identifier = tag.getArg1();
 203  
                     // Trim off method or link text
 204  7
                     final Pattern pattern =
 205  
                         Utils.getPattern("(.+?)(?:\\s+|#|\\$).*");
 206  7
                     final Matcher matcher = pattern.matcher(identifier);
 207  7
                     if (matcher.find()) {
 208  6
                         identifier = matcher.group(1);
 209  
                     }
 210  7
                     mReferenced.add(identifier);
 211  10
                 }
 212  
             }
 213  
         }
 214  16
     }
 215  
 }