IDEA-71293 (Inspections / Imports / Redundant Import: no warning for type import redundant due to static import)

This commit is contained in:
Bas Leijdekkers
2012-10-09 22:28:43 +02:00
parent 8dd16279c1
commit f541ed314a
5 changed files with 93 additions and 190 deletions
@@ -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<PsiImportStatement> importStatements;
private final List<PsiImportStatementBase> importStatements;
private final List<PsiImportStatementBase> 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<PsiImportStatement> 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<PsiImportStatementBase> 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()]);
}
}
@@ -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<PsiImportStaticStatement> 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()]);
}
}
}
@@ -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);
}
}
@@ -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;
}
}
@@ -1,4 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<problems>
<problem>
<file>UnusedImport.java</file>
<line>3</line>
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Unused import</problem_class>
<description>Unused import &lt;code&gt;import java.util.Map.*;&lt;/code&gt; #loc</description>
</problem>
</problems>