Merge branch 'pr-2771' into master
[java] Fix #2756, NPE in TypeTestUtil #2771
This commit is contained in:
@ -19,6 +19,7 @@ This is a {{ site.pmd.release_type }} release.
|
||||
* pmd-java
|
||||
* [#2708](https://github.com/pmd/pmd/issues/2708): \[java] False positive FinalFieldCouldBeStatic when using lombok Builder.Default
|
||||
* [#2738](https://github.com/pmd/pmd/issues/2738): \[java] Custom rule with @ExhaustiveEnumSwitch throws NPE
|
||||
* [#2756](https://github.com/pmd/pmd/issues/2756): \[java] TypeTestUtil fails with NPE for anonymous class
|
||||
|
||||
|
||||
### API Changes
|
||||
|
@ -106,7 +106,11 @@ public final class TypeTestUtil {
|
||||
|
||||
final Class<?> clazz = loadClassWithNodeClassloader(node, canonicalName);
|
||||
|
||||
|
||||
if (clazz != null) {
|
||||
if (clazz.getCanonicalName() == null) {
|
||||
return false; // no canonical name, give up: we shouldn't be able to access them
|
||||
}
|
||||
return clazz.isAssignableFrom(nodeType);
|
||||
} else {
|
||||
return fallbackIsA(node, canonicalName, true);
|
||||
@ -174,8 +178,16 @@ public final class TypeTestUtil {
|
||||
}
|
||||
|
||||
|
||||
return node.getType() == null ? fallbackIsA(node, canonicalName, false)
|
||||
: node.getType().getCanonicalName().equals(canonicalName);
|
||||
if (node.getType() == null) {
|
||||
return fallbackIsA(node, canonicalName, false);
|
||||
}
|
||||
|
||||
String canoname = node.getType().getCanonicalName();
|
||||
if (canoname == null) {
|
||||
// anonymous/local class, or class nested within one of those
|
||||
return false;
|
||||
}
|
||||
return canoname.equals(canonicalName);
|
||||
}
|
||||
|
||||
|
||||
|
@ -6,6 +6,7 @@ package net.sourceforge.pmd.lang.java.types;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Rule;
|
||||
@ -13,6 +14,7 @@ import org.junit.Test;
|
||||
import org.junit.function.ThrowingRunnable;
|
||||
import org.junit.rules.ExpectedException;
|
||||
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTAllocationExpression;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTAnnotationTypeDeclaration;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTEnumDeclaration;
|
||||
@ -20,6 +22,7 @@ import net.sourceforge.pmd.lang.java.ast.ASTMarkerAnnotation;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTName;
|
||||
import net.sourceforge.pmd.lang.java.ast.TypeNode;
|
||||
import net.sourceforge.pmd.lang.java.symboltable.BaseNonParserTest;
|
||||
import net.sourceforge.pmd.lang.java.types.testdata.SomeClassWithAnon;
|
||||
|
||||
public class TypeTestUtilTest extends BaseNonParserTest {
|
||||
|
||||
@ -74,6 +77,31 @@ public class TypeTestUtilTest extends BaseNonParserTest {
|
||||
assertIsA(klass, Object.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAnonClassTypeNPE() {
|
||||
// #2756
|
||||
|
||||
ASTAllocationExpression anon =
|
||||
java.parseClass(SomeClassWithAnon.class)
|
||||
.getFirstDescendantOfType(ASTAllocationExpression.class);
|
||||
|
||||
|
||||
Assert.assertNotNull("Type should be resolved", anon.getType());
|
||||
Assert.assertTrue("Anon class", anon.isAnonymousClass());
|
||||
Assert.assertTrue("Anon class", anon.getType().isAnonymousClass());
|
||||
Assert.assertTrue("Should be a Runnable", TypeTestUtil.isA(Runnable.class, anon));
|
||||
|
||||
// This is not a canonical name, so we give up early
|
||||
Assert.assertFalse(TypeTestUtil.isA(SomeClassWithAnon.class.getName() + "$1", anon));
|
||||
Assert.assertFalse(TypeTestUtil.isExactlyA(SomeClassWithAnon.class.getName() + "$1", anon));
|
||||
|
||||
// this is the failure case: if the binary name doesn't match, we test the canoname, which was null
|
||||
Assert.assertFalse(TypeTestUtil.isA(Callable.class, anon));
|
||||
Assert.assertFalse(TypeTestUtil.isA(Callable.class.getCanonicalName(), anon));
|
||||
Assert.assertFalse(TypeTestUtil.isExactlyA(Callable.class, anon));
|
||||
Assert.assertFalse(TypeTestUtil.isExactlyA(Callable.class.getCanonicalName(), anon));
|
||||
}
|
||||
|
||||
/**
|
||||
* If we don't have the annotation on the classpath,
|
||||
* we should resolve the full name via the import, if possible
|
||||
|
25
pmd-java/src/test/java/net/sourceforge/pmd/lang/java/types/testdata/SomeClassWithAnon.java
vendored
Normal file
25
pmd-java/src/test/java/net/sourceforge/pmd/lang/java/types/testdata/SomeClassWithAnon.java
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
package net.sourceforge.pmd.lang.java.types.testdata;
|
||||
|
||||
/**
|
||||
* #2756
|
||||
*/
|
||||
public class SomeClassWithAnon {
|
||||
|
||||
{
|
||||
new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
Reference in New Issue
Block a user