From f541ed314a866c12f6148af90db54b3e98bf06ab Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Tue, 9 Oct 2012 22:28:43 +0200 Subject: [PATCH] IDEA-71293 (Inspections / Imports / Redundant Import: no warning for type import redundant due to static import) --- .../ig/imports/ImportsAreUsedVisitor.java | 112 +++++++++++------ .../imports/StaticImportsAreUsedVisitor.java | 115 ------------------ .../ig/imports/UnusedImportInspection.java | 46 ++----- .../igtest/imports/unused/UnusedImport.java | 3 + .../siyeh/igtest/imports/unused/expected.xml | 7 +- 5 files changed, 93 insertions(+), 190 deletions(-) delete mode 100644 plugins/InspectionGadgets/src/com/siyeh/ig/imports/StaticImportsAreUsedVisitor.java diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/imports/ImportsAreUsedVisitor.java b/plugins/InspectionGadgets/src/com/siyeh/ig/imports/ImportsAreUsedVisitor.java index bb97ed202bc2..6753839eb83d 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/imports/ImportsAreUsedVisitor.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/imports/ImportsAreUsedVisitor.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2007 Dave Griffith, Bas Leijdekkers + * Copyright 2003-2012 Dave Griffith, Bas Leijdekkers * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,7 +15,9 @@ */ package com.siyeh.ig.imports; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; +import com.intellij.psi.util.InheritanceUtil; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; @@ -25,9 +27,10 @@ import java.util.List; class ImportsAreUsedVisitor extends JavaRecursiveElementVisitor { - private final List importStatements; + private final List importStatements; + private final List usedImportStatements = new ArrayList(); - ImportsAreUsedVisitor(PsiImportStatement[] importStatements) { + ImportsAreUsedVisitor(PsiImportStatementBase[] importStatements) { this.importStatements = new ArrayList(Arrays.asList(importStatements)); Collections.reverse(this.importStatements); } @@ -57,43 +60,81 @@ class ImportsAreUsedVisitor extends JavaRecursiveElementVisitor { // during typing there can be incomplete code final JavaResolveResult resolveResult = reference.advancedResolve(true); final PsiElement element = resolveResult.getElement(); - if (!(element instanceof PsiClass)) { + if (element == null) { return; } - final PsiClass referencedClass = (PsiClass)element; - final String qualifiedName = referencedClass.getQualifiedName(); - if (qualifiedName == null) { + if (findImport(element, usedImportStatements) != null) { return; } - final List importStatementsCopy = - new ArrayList(importStatements); - for (PsiImportStatement importStatement : importStatementsCopy) { - final String importName = importStatement.getQualifiedName(); - if (importName == null) { - return; - } - if (importStatement.isOnDemand()) { - final int lastComponentIndex = - qualifiedName.lastIndexOf((int)'.'); - if (lastComponentIndex > 0) { - final String packageName = qualifiedName.substring(0, - lastComponentIndex); - if (importName.equals(packageName)) { - removeAll(importStatement); - break; - } - } - } - else if (importName.equals(qualifiedName)) { - removeAll(importStatement); - break; - } + final PsiImportStatementBase foundImport = findImport(element, importStatements); + if (foundImport != null) { + removeAll(foundImport); + usedImportStatements.add(foundImport); } } - private void removeAll(@NotNull PsiImportStatement importStatement) { + private static PsiImportStatementBase findImport(PsiElement element, List importStatements) { + final String qualifiedName; + final String packageName; + if (element instanceof PsiClass) { + final PsiClass referencedClass = (PsiClass)element; + qualifiedName = referencedClass.getQualifiedName(); + packageName = qualifiedName != null ? StringUtil.getPackageName(qualifiedName) : null; + } + else { + qualifiedName = null; + packageName = null; + } + final PsiClass referenceClass; + final String referenceName; + if (element instanceof PsiMember) { + final PsiMember member = (PsiMember)element; + referenceClass = member.getContainingClass(); + referenceName = member.getName(); + } + else { + referenceClass = null; + referenceName = null; + } + for (PsiImportStatementBase importStatementBase : importStatements) { + if (importStatementBase instanceof PsiImportStatement && qualifiedName != null && packageName != null) { + final PsiImportStatement importStatement = (PsiImportStatement)importStatementBase; + final String importName = importStatement.getQualifiedName(); + if (importName != null) { + if (importStatement.isOnDemand()) { + if (importName.equals(packageName)) { + return importStatement; + } + } + else if (importName.equals(qualifiedName)) { + return importStatement; + } + } + } + if (importStatementBase instanceof PsiImportStaticStatement && referenceClass != null && referenceName != null) { + final PsiImportStaticStatement importStaticStatement = (PsiImportStaticStatement)importStatementBase; + if (importStaticStatement.isOnDemand()) { + final PsiClass targetClass = importStaticStatement.resolveTargetClass(); + if (InheritanceUtil.isInheritorOrSelf(targetClass, referenceClass, true)) { + return importStaticStatement; + } + } + else { + final String importReferenceName = importStaticStatement.getReferenceName(); + if (importReferenceName != null) { + if (importReferenceName.equals(referenceName)) { + return importStaticStatement; + } + } + } + } + } + return null; + } + + private void removeAll(@NotNull PsiImportStatementBase importStatement) { for (int i = importStatements.size() - 1; i >= 0; i--) { - final PsiImportStatement statement = importStatements.get(i); + final PsiImportStatementBase statement = importStatements.get(i); final String statementText = statement.getText(); final String importText = importStatement.getText(); if (importText.equals(statementText)) { @@ -102,11 +143,10 @@ class ImportsAreUsedVisitor extends JavaRecursiveElementVisitor { } } - public PsiImportStatement[] getUnusedImportStatements() { + public PsiImportStatementBase[] getUnusedImportStatements() { if (importStatements.isEmpty()) { - return PsiImportStatement.EMPTY_ARRAY; + return PsiImportStatementBase.EMPTY_ARRAY; } - return importStatements.toArray( - new PsiImportStatement[importStatements.size()]); + return importStatements.toArray(new PsiImportStatementBase[importStatements.size()]); } } \ No newline at end of file diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/imports/StaticImportsAreUsedVisitor.java b/plugins/InspectionGadgets/src/com/siyeh/ig/imports/StaticImportsAreUsedVisitor.java deleted file mode 100644 index 7f791e4eff0a..000000000000 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/imports/StaticImportsAreUsedVisitor.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright 2005-2008 Bas Leijdekkers - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.siyeh.ig.imports; - -import com.intellij.psi.*; -import com.intellij.psi.util.InheritanceUtil; -import org.jetbrains.annotations.NotNull; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -class StaticImportsAreUsedVisitor extends JavaRecursiveElementVisitor { - - private final List importStatements; - - StaticImportsAreUsedVisitor(PsiImportStaticStatement[] importStatements) { - this.importStatements = new ArrayList(Arrays.asList(importStatements)); - Collections.reverse(this.importStatements); - } - - @Override - public void visitElement(PsiElement element) { - if (importStatements.isEmpty()) { - return; - } - super.visitElement(element); - } - - @Override - public void visitReferenceElement( - @NotNull PsiJavaCodeReferenceElement reference) { - followReferenceToImport(reference); - super.visitReferenceElement(reference); - } - - private void followReferenceToImport( - PsiJavaCodeReferenceElement reference) { - if (reference.getQualifier() != null) { - //it's already qualified, so the import statement wasn't - // responsible - return; - } - final String referenceName = reference.getReferenceName(); - if (referenceName == null) { - return; - } - final PsiElement element = reference.resolve(); - if (!(element instanceof PsiMember)) { - return; - } - final PsiMember member = (PsiMember)element; - final PsiClass containingClass = member.getContainingClass(); - if (containingClass == null) { - return; - } - for (PsiImportStaticStatement importStatement : importStatements) { - if (importStatement.isOnDemand()) { - final PsiClass targetClass = - importStatement.resolveTargetClass(); - if (InheritanceUtil.isInheritorOrSelf(targetClass, - containingClass, true)) { - removeAll(importStatement); - break; - } - } - else { - final String importReferenceName = - importStatement.getReferenceName(); - if (importReferenceName == null) { - continue; - } - if (importReferenceName.equals(referenceName)) { - removeAll(importStatement); - break; - } - } - } - } - - private void removeAll( - @NotNull PsiImportStaticStatement importStaticStatement) { - for (int i = importStatements.size() - 1; i >= 0; i--) { - final PsiImportStaticStatement statement = importStatements.get(i); - final String text = statement.getText(); - if (importStaticStatement.getText().equals(text)) { - importStatements.remove(i); - } - } - } - - public PsiImportStaticStatement[] getUnusedImportStaticStatements() { - if (importStatements.isEmpty()) { - return PsiImportStaticStatement.EMPTY_ARRAY; - } - else { - return importStatements.toArray( - new PsiImportStaticStatement[importStatements.size()]); - } - } -} diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/imports/UnusedImportInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/imports/UnusedImportInspection.java index 932186fb99ed..d745f3927339 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/imports/UnusedImportInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/imports/UnusedImportInspection.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2008 Dave Griffith, Bas Leijdekkers + * Copyright 2003-2012 Dave Griffith, Bas Leijdekkers * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -35,8 +35,7 @@ public class UnusedImportInspection extends BaseInspection { @Override @NotNull public String buildErrorString(Object... infos) { - return InspectionGadgetsBundle.message( - "unused.import.problem.descriptor"); + return InspectionGadgetsBundle.message("unused.import.problem.descriptor"); } @Override @@ -66,8 +65,7 @@ public class UnusedImportInspection extends BaseInspection { return; } final PsiClass[] classes = file.getClasses(); - final PsiPackageStatement packageStatement = - file.getPackageStatement(); + final PsiPackageStatement packageStatement = file.getPackageStatement(); final PsiModifierList annotationList; if (packageStatement != null) { annotationList = packageStatement.getAnnotationList(); @@ -75,51 +73,23 @@ public class UnusedImportInspection extends BaseInspection { else { annotationList = null; } - final PsiImportStatement[] importStatements = - importList.getImportStatements(); + final PsiImportStatementBase[] importStatements = importList.getAllImportStatements(); checkImports(importStatements, classes, annotationList); - final PsiImportStaticStatement[] importStaticStatements = - importList.getImportStaticStatements(); - checkStaticImports(importStaticStatements, classes); } - private void checkStaticImports( - PsiImportStaticStatement[] importStaticStatements, - PsiClass[] classes) { - if (importStaticStatements.length == 0) { - return; - } - final StaticImportsAreUsedVisitor visitor = - new StaticImportsAreUsedVisitor(importStaticStatements); - for (PsiClass aClass : classes) { - aClass.accept(visitor); - } - final PsiImportStaticStatement[] unusedImportStaticStatements = - visitor.getUnusedImportStaticStatements(); - for (PsiImportStaticStatement importStaticStatement : - unusedImportStaticStatements) { - registerError(importStaticStatement); - } - } - - private void checkImports(PsiImportStatement[] importStatements, - PsiClass[] classes, - @Nullable PsiModifierList annotationList) { + private void checkImports(PsiImportStatementBase[] importStatements, PsiClass[] classes, @Nullable PsiModifierList annotationList) { if (importStatements.length == 0) { return; } - final ImportsAreUsedVisitor visitor = - new ImportsAreUsedVisitor(importStatements); + final ImportsAreUsedVisitor visitor = new ImportsAreUsedVisitor(importStatements); for (PsiClass aClass : classes) { aClass.accept(visitor); } if (annotationList != null) { annotationList.accept(visitor); } - final PsiImportStatement[] unusedImportStatements = - visitor.getUnusedImportStatements(); - for (PsiImportStatement unusedImportStatement : - unusedImportStatements) { + final PsiImportStatementBase[] unusedImportStatements = visitor.getUnusedImportStatements(); + for (PsiImportStatementBase unusedImportStatement : unusedImportStatements) { registerError(unusedImportStatement); } } diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/imports/unused/UnusedImport.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/imports/unused/UnusedImport.java index 4c6d3d0a263a..adab39f11837 100644 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/imports/unused/UnusedImport.java +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/imports/unused/UnusedImport.java @@ -1,5 +1,7 @@ package com.siyeh.igtest.imports.unused; +import java.util.Map.*; +import static java.util.Map.*; import static java.lang.Math.*; import static java.lang.Integer.SIZE; import java.util.List; @@ -18,5 +20,6 @@ public class UnusedImport { public void add(int i) { list.add(i); + Entry entry; } } \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/imports/unused/expected.xml b/plugins/InspectionGadgets/test/com/siyeh/igtest/imports/unused/expected.xml index b89ca9b58144..50ba5aa23f0f 100644 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/imports/unused/expected.xml +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/imports/unused/expected.xml @@ -1,4 +1,9 @@ - + + UnusedImport.java + 3 + Unused import + Unused import <code>import java.util.Map.*;</code> #loc + \ No newline at end of file