Fixes #793 [java] Parser error with private method in nested classes in interfaces

This commit is contained in:
Andreas Dangel
2017-12-20 22:37:49 +01:00
parent ef41c71870
commit 64b862eef9
5 changed files with 49 additions and 3 deletions

View File

@ -21,6 +21,9 @@ This is a bug fixing release.
### Fixed Issues
* java
* [#793](https://github.com/pmd/pmd/issues/793): \[java] Parser error with private method in nested classes in interfaces
### API Changes
### External Contributions

View File

@ -1,4 +1,7 @@
/**
* Fixes #793 [java] Parser error with private method in nested classes in interfaces
* Andreas Dangel 12/2017
*====================================================================
* Add support for Java 9 changes:
* Private interface methods are only allowed with java9.
* A single underscore "_" is an invalid identifier in java9.
@ -340,6 +343,7 @@ public class JavaParser {
* Keeps track whether we are dealing with an interface or not. Needed since the tree is
* is not fully constructed yet, when we check for private interface methods.
* The flag is updated, if entering ClassOrInterfaceDeclaration and reset when leaving.
* The flag is also reset, if entering a anonymous inner class.
*/
private boolean inInterface = false;
private void checkForBadPrivateInterfaceMethod(ASTMethodDeclaration node) {
@ -2009,7 +2013,7 @@ void AllocationExpression():
(
ArrayDimsAndInits()
|
Arguments() [ ClassOrInterfaceBody() ]
Arguments() [ {inInterface = false;} ClassOrInterfaceBody() ]
)
)
{ checkForBadAnonymousDiamondUsage(); }

View File

@ -75,8 +75,11 @@ public class ASTMethodDeclaration extends AbstractJavaAccessNode implements DFAG
public boolean isInterfaceMember() {
ASTClassOrInterfaceDeclaration clz = getFirstParentOfType(ASTClassOrInterfaceDeclaration.class);
return clz != null && clz.isInterface();
ASTClassOrInterfaceBody body = getFirstParentOfType(ASTClassOrInterfaceBody.class);
if (body != null && body.jjtGetParent() instanceof ASTClassOrInterfaceDeclaration) {
return ((ASTClassOrInterfaceDeclaration) body.jjtGetParent()).isInterface();
}
return false;
}
public boolean isVoid() {

View File

@ -10,6 +10,7 @@ import static net.sourceforge.pmd.lang.java.ParserTstUtil.parseJava15;
import static net.sourceforge.pmd.lang.java.ParserTstUtil.parseJava17;
import static net.sourceforge.pmd.lang.java.ParserTstUtil.parseJava18;
import static net.sourceforge.pmd.lang.java.ParserTstUtil.parseJava9;
import static org.junit.Assert.assertFalse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
@ -267,4 +268,11 @@ public class JDKVersionTest {
public final void jdk9TryWithResources() {
parseJava9(loadSource("jdk9_try_with_resources.java"));
}
@Test
public final void jdk7PrivateMethodInnerClassInterface() {
ASTCompilationUnit acu = parseJava17(loadSource("private_method_in_inner_class_interface.java"));
ASTMethodDeclaration privateMethod = acu.getFirstDescendantOfType(ASTMethodDeclaration.class);
assertFalse(privateMethod.isInterfaceMember());
}
}

View File

@ -0,0 +1,28 @@
/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.lang.java.ast.testdata;
/**
* With Java9, private methods in interfaces are possible.
* But they must not be confused with private methods in inner classes of interfaces
* when using older java version.
*
* @see https://github.com/pmd/pmd/issues/793
*/
public interface InterfaceWithInnerClass {
Object FOO = new Object() {
private void privateMethod() { }
};
class InnerClass {
private void privateMethod() { }
}
enum InnerEnum {
VALUE;
private void privateMethod() { }
}
}