diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/ClassScope.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/ClassScope.java index 7823895d46..36db91197c 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/ClassScope.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/ClassScope.java @@ -381,6 +381,15 @@ public class ClassScope extends AbstractJavaScope { return qualified; } + // Is it an inner class of an explicit import? + int dotIndex = typeImage.indexOf('.'); + if (dotIndex != -1) { + qualified = findQualifiedName(typeImage.substring(0, dotIndex), fileScope.getExplicitImports()); + if (qualified != null) { + return qualified.concat(typeImage.substring(dotIndex)); + } + } + return typeImage; } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/TypeSet.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/TypeSet.java index fdd1a6db63..b0b1bf8fd8 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/TypeSet.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/TypeSet.java @@ -437,6 +437,18 @@ public class TypeSet { return c; } + + @Override + public boolean couldResolve(String name) { + /* + * We can always try! + * If a file used an explicit import on A.Inner, the class loader will register + * A.Inner can't be resolved even if A$Inner can. + * If a second file used A.Inner without an explicit import, we would end here, + * super.couldResolve("A.Inner") will return false, but we CAN resolve it as A$Inner. + */ + return true; + } } public void setASTCompilationUnitPackage(String pkg) { diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symboltable/ClassScopeTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symboltable/ClassScopeTest.java index 8736c665f1..ae62f018f1 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symboltable/ClassScopeTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symboltable/ClassScopeTest.java @@ -169,6 +169,14 @@ public class ClassScopeTest extends STBBaseTst { assertEquals("(String,String...)", mnd.getParameterDisplaySignature()); } + @Test + public void testNestedClassesOfImportResolution() { + parseCode(NESTED_CLASSES_OF_IMPORT); + final ASTClassOrInterfaceDeclaration n = acu.findDescendantsOfType(ASTClassOrInterfaceDeclaration.class).get(0); + final ClassScope c = (ClassScope) n.getScope(); + assertEquals(EnumTest.class, c.resolveType("TheInnerClass.EnumTest")); + } + @Test public void testNestedClassesResolution() { parseForClass(InnerClass.class); @@ -423,7 +431,9 @@ public class ClassScopeTest extends STBBaseTst { " public EnumTest e;" + PMD.EOL + "}" + PMD.EOL; - public static junit.framework.Test suite() { - return new junit.framework.JUnit4TestAdapter(ClassScopeTest.class); - } + private static final String NESTED_CLASSES_OF_IMPORT = + "import net.sourceforge.pmd.lang.java.symboltable.testdata.InnerClass.TheInnerClass;" + PMD.EOL + + "public class Foo {" + PMD.EOL + + " public TheInnerClass.EnumTest e;" + PMD.EOL + + "}" + PMD.EOL; }