All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.walkmod.checkstyle.treewalkers.RedundantImport Maven / Gradle / Ivy

package org.walkmod.checkstyle.treewalkers;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.walkmod.javalang.ast.CompilationUnit;
import org.walkmod.javalang.ast.ImportDeclaration;
import org.walkmod.javalang.ast.PackageDeclaration;
import org.walkmod.javalang.ast.SymbolDataAware;
import org.walkmod.javalang.ast.SymbolReference;
import org.walkmod.javalang.compiler.symbols.RequiresSemanticAnalysis;
import org.walkmod.javalang.visitors.VoidVisitorAdapter;

/**
 * Checks for redundant import statements. An import statement is considered redundant if:
 *
 * - It is a duplicate of another import. This is, when a class is imported more than once.
 * - The class non-statically imported is from the java.lang package, e.g. importing java.lang.String.
 * - The class non-statically imported is from the same package as the current package.
 * @param  context
 */
@RequiresSemanticAnalysis
public class RedundantImport extends VoidVisitorAdapter {

   private Map nonAsteriskImports;

   private String package_ = null;

   private Map> asteriskImports = new HashMap>();

   private void setPackage(CompilationUnit cu) {
      PackageDeclaration pkg = cu.getPackage();
      if (pkg != null) {
         package_ = pkg.getName().toString();
      }
   }

   private void setAsteriskImports(CompilationUnit cu) {
      Iterator it = cu.getImports().iterator();
      while (it.hasNext()) {
         ImportDeclaration id = it.next();
         if (id.isAsterisk()) {
            asteriskImports.put(id.getName().toString(), new HashSet());
         }
      }
   }

   private void setNonAsteriskImports(CompilationUnit cu) {
      nonAsteriskImports = new HashMap();
      Iterator it = cu.getImports().iterator();
      while (it.hasNext()) {
         ImportDeclaration id = it.next();
         String name = id.getName().toString();
         if (!id.isAsterisk()) {
            nonAsteriskImports.put(name, id);
         }
      }
   }

   private void setRedundantImportsForAsterisk(CompilationUnit cu) {
      Iterator it = cu.getImports().iterator();
      while (it.hasNext()) {
         ImportDeclaration id = it.next();
         String name = id.getName().toString();
         if (!id.isAsterisk()) {
            int index = name.lastIndexOf(".");
            if (index != -1) {
               String pkgName = name.substring(0, index);
               if (asteriskImports.containsKey(pkgName)) {
                  Set relatedImports = asteriskImports.get(pkgName);
                  relatedImports.add(name);
               }
            }
         }
      }
   }

   @Override
   public void visit(CompilationUnit cu, A ctx) {
      List imports = cu.getImports();
      if (imports != null) {
         setPackage(cu);
         setAsteriskImports(cu);
         setNonAsteriskImports(cu);
         setRedundantImportsForAsterisk(cu);

         ImportsCleaner ic = new ImportsCleaner();
         Iterator it = imports.iterator();
         while (it.hasNext()) {
            it.next().accept(ic, ctx);
         }
         cu.setImports(ic.getImports());
      }
   }

   private class ImportsCleaner extends VoidVisitorAdapter {

      private List correctImports = new LinkedList();

      public List getImports() {
         return correctImports;
      }

      private boolean isInTheSamePackage(String importName) {

         if (package_ == null) {
            return false;
         }
         if (!importName.startsWith(package_)) {
            return false;
         }

         String[] packageTokens = package_.split("\\.");
         String[] tokens = importName.split("\\.");
         return (tokens.length == packageTokens.length);
      }

      private boolean isRedundantJavaLangImport(String importedName) {
         return importedName.startsWith("java.lang") && importedName.split("\\.").length == 3;
      }

      private boolean requiresAsteriskImport(ImportDeclaration importDeclaration) {

         String importedName = importDeclaration.getName().toString();

         if(asteriskImports.get(importedName).isEmpty()) {
            return true;
         }

         List usages = importDeclaration.getUsages();
         Set usedImports = new HashSet();

         if (usages != null) {
            Iterator it = usages.iterator();
            while (it.hasNext()) {
               SymbolReference current = it.next();
               if (current instanceof SymbolDataAware) {
                  SymbolDataAware sda = (SymbolDataAware) current;
                  String typeName = sda.getSymbolData().getName();
                  usedImports.add(typeName);
               }
            }
         }

         return !nonAsteriskImports.keySet().containsAll(usedImports);
      }


      @Override
      public void visit(ImportDeclaration importDeclaration, A ctx) {
         String importedName = importDeclaration.getName().toString();
         if (nonAsteriskImports.containsKey(importedName)) {

            if (isRedundantJavaLangImport(importedName)) {
               return;
            }

            if (importDeclaration.isStatic() || !isInTheSamePackage(importedName)) {
               correctImports.add(importDeclaration);
            }
         } else {
            if (!isInTheSamePackage(importedName)) {
               if (importDeclaration.getUsages() == null && importDeclaration.isNewNode()) {
                  correctImports.add(importDeclaration);
               } else  if (requiresAsteriskImport(importDeclaration)){
                  correctImports.add(importDeclaration);
               }
            }
         }
      }
   }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy