diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/ImportWrapper.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/ImportWrapper.java index e6f42841e4..c5e721663f 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/ImportWrapper.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/ImportWrapper.java @@ -3,17 +3,45 @@ */ package net.sourceforge.pmd.lang.rule; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.HashSet; +import java.util.Set; + import net.sourceforge.pmd.lang.ast.Node; public class ImportWrapper { private Node node; private String name; private String fullname; + private boolean isStaticDemand; + private Set allDemands = new HashSet(); + + public ImportWrapper(String fullname, String name) { + this(fullname, name, null); + } public ImportWrapper(String fullname, String name, Node node) { + this(fullname, name, node, false); + } + + public ImportWrapper(String fullname, String name, Node node, Class type, boolean isStaticDemand) { + this(fullname, name, node, isStaticDemand); + if (type != null) { + for (Method m : type.getMethods()) { + allDemands.add(m.getName()); + } + for (Field f : type.getFields()) { + allDemands.add(f.getName()); + } + } + } + + public ImportWrapper(String fullname, String name, Node node, boolean isStaticDemand) { this.fullname = fullname; this.name = name; this.node = node; + this.isStaticDemand = isStaticDemand; } public boolean equals(Object other) { @@ -33,6 +61,18 @@ public class ImportWrapper { return false; } + public boolean matches(ImportWrapper i) { + if (isStaticDemand) { + if (allDemands.contains(i.fullname)) { + return true; + } + } + if (name == null && i.getName() == null) { + return i.getFullName().equals(fullname); + } + return i.getName().equals(name); + } + public int hashCode() { if(name == null){ return fullname.hashCode(); @@ -51,5 +91,10 @@ public class ImportWrapper { public Node getNode() { return node; } + + @Override + public String toString() { + return "Import[name=" + name + ",fullname=" + fullname + ",static*=" + isStaticDemand + "]"; + } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/imports/UnusedImportsRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/imports/UnusedImportsRule.java index c50374dfb2..295ae9f364 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/imports/UnusedImportsRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/imports/UnusedImportsRule.java @@ -144,7 +144,7 @@ public class UnusedImportsRule extends AbstractJavaRule { } else { name = node.getImage().substring(0, node.getImage().indexOf('.')); } - ImportWrapper candidate = new ImportWrapper(node.getImage(), name, new DummyJavaNode(-1)); + ImportWrapper candidate = new ImportWrapper(node.getImage(), name); return candidate; } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/rules/imports/UnusedImports.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/rules/imports/UnusedImports.java index c89ad5dc2d..029d1cbcf1 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/rules/imports/UnusedImports.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/rules/imports/UnusedImports.java @@ -3,10 +3,11 @@ */ package net.sourceforge.pmd.lang.java.typeresolution.rules.imports; +import java.util.Iterator; + import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.lang.java.ast.ASTImportDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTName; -import net.sourceforge.pmd.lang.java.ast.DummyJavaNode; import net.sourceforge.pmd.lang.java.ast.TypeNode; import net.sourceforge.pmd.lang.java.rule.imports.UnusedImportsRule; import net.sourceforge.pmd.lang.rule.ImportWrapper; @@ -17,7 +18,7 @@ public class UnusedImports extends UnusedImportsRule { public Object visit(ASTImportDeclaration node, Object data) { if (node.isImportOnDemand()) { ASTName importedType = (ASTName) node.jjtGetChild(0); - imports.add(new ImportWrapper(importedType.getImage(), null, node)); + imports.add(new ImportWrapper(importedType.getImage(), null, node, node.getType(), node.isStatic())); } else { super.visit(node, data); } @@ -30,14 +31,18 @@ public class UnusedImports extends UnusedImportsRule { return; } ImportWrapper candidate = getImportWrapper(node); - if (imports.contains(candidate)) { - imports.remove(candidate); - return; + Iterator it = imports.iterator(); + while (it.hasNext()) { + ImportWrapper i = it.next(); + if (i.matches(candidate)) { + it.remove(); + return; + } } if (TypeNode.class.isAssignableFrom(node.getClass()) && ((TypeNode) node).getType() != null) { Class c = ((TypeNode) node).getType(); if (c.getPackage() != null) { - candidate = new ImportWrapper(c.getPackage().getName(), null, new DummyJavaNode(-1)); + candidate = new ImportWrapper(c.getPackage().getName(), null); if (imports.contains(candidate)) { imports.remove(candidate); } diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/imports/xml/UnusedImports.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/imports/xml/UnusedImports.xml index da77893ade..d2a38009f3 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/imports/xml/UnusedImports.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/imports/xml/UnusedImports.xml @@ -268,6 +268,28 @@ public class Foo { */ public void someMethod() { } +} + ]]> + + + #914 False +ve from UnusedImports with wildcard static imports + 0 + diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/typeresolution/xml/UnusedImports.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/typeresolution/xml/UnusedImports.xml index cd1f5746b5..b456944e64 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/typeresolution/xml/UnusedImports.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/typeresolution/xml/UnusedImports.xml @@ -190,6 +190,28 @@ public class Foo { */ public void someMethod() { } +} + ]]> + + + #914 False +ve from UnusedImports with wildcard static imports + 0 + diff --git a/src/site/markdown/overview/changelog.md b/src/site/markdown/overview/changelog.md index d6df04d060..1c8bc4cc7b 100644 --- a/src/site/markdown/overview/changelog.md +++ b/src/site/markdown/overview/changelog.md @@ -27,6 +27,7 @@ **Bugfixes:** +* [#914](https://sourceforge.net/p/pmd/bugs/914/): False +ve from UnusedImports with wildcard static imports * [#1296](https://sourceforge.net/p/pmd/bugs/1296/): PMD UnusedPrivateMethod invalid detection of 'private void method(int,boolean,Integer...)' * [#1298](https://sourceforge.net/p/pmd/bugs/1298/): Member variable int type with value 0xff000000 causes processing error * [#1299](https://sourceforge.net/p/pmd/bugs/1299/): MethodReturnsInternalArray false positive