fixes #1455 PMD doesn't handle Java 8 explicit receiver parameters

Those parameters are correctly parsed now and can be found
with "//FormalParameter[@ExplicitReceiverParameter='true']"
This commit is contained in:
Andreas Dangel
2016-01-25 10:29:00 +01:00
parent 44a8c0defe
commit e6f5380719
6 changed files with 66 additions and 9 deletions

View File

@ -1,4 +1,9 @@
/**
* Added support for explicit receiver parameters.
* Bug #1455
*
* Andreas Dangel 01/2016
*====================================================================
* Added capability for Tracking Tokens.
*
* Amit Kumar Prasad 10/2015
@ -248,6 +253,11 @@ public class JavaParser {
throwParseException("Cannot use type annotations when running in JDK inferior to 1.8 mode!");
}
}
private void checkforBadExplicitReceiverParameter() {
if (jdkVersion < 8) {
throwParseException("Cannot use explicit receiver parameters when running in JDK inferior to 1.8 mode!");
}
}
// This is a semantic LOOKAHEAD to determine if we're dealing with an assert
// Note that this can't be replaced with a syntactic lookahead
@ -1390,14 +1400,20 @@ void VariableDeclarator() :
}
void VariableDeclaratorId() :
{Token t;}
{
t=<IDENTIFIER>
Token t;
String image;
}
{
(LOOKAHEAD(2) t=<IDENTIFIER> "." <THIS> { checkforBadExplicitReceiverParameter(); jjtThis.setExplicitReceiverParameter(); image=t.image + ".this"; }
| t=<THIS> { checkforBadExplicitReceiverParameter(); jjtThis.setExplicitReceiverParameter(); image = t.image;}
| t=<IDENTIFIER> { image = t.image; }
)
( "[" "]" { jjtThis.bumpArrayDepth(); })*
{
checkForBadAssertUsage(t.image, "a variable name");
checkForBadEnumUsage(t.image, "a variable name");
jjtThis.setImage( t.image );
checkForBadAssertUsage(image, "a variable name");
checkForBadEnumUsage(image, "a variable name");
jjtThis.setImage( image );
}
}
@ -1778,7 +1794,7 @@ void PrimaryPrefix() :
{Token t;}
{
Literal()
| "this" {jjtThis.setUsesThisModifier();}
| LOOKAHEAD(2) "this" {jjtThis.setUsesThisModifier();}
| "super" {jjtThis.setUsesSuperModifier();}
| LOOKAHEAD( "(" ")" "->" ) LambdaExpression()
| LOOKAHEAD( <IDENTIFIER> "->" ) LambdaExpression()

View File

@ -19,7 +19,11 @@ public class ASTFormalParameter extends AbstractJavaAccessNode implements Dimens
public boolean isVarargs() {
return isVarargs;
}
public boolean isExplicitReceiverParameter() {
return getDecl().isExplicitReceiverParameter();
}
public ASTFormalParameter(int id) {
super(id);
}

View File

@ -31,6 +31,7 @@ public class ASTVariableDeclaratorId extends AbstractJavaTypeNode {
private int arrayDepth;
private VariableNameDeclaration nameDeclaration;
private boolean explicitReceiverParameter = false;
public VariableNameDeclaration getNameDeclaration() {
return nameDeclaration;
@ -60,6 +61,13 @@ public class ASTVariableDeclaratorId extends AbstractJavaTypeNode {
return jjtGetParent().jjtGetParent() instanceof ASTTryStatement;
}
public void setExplicitReceiverParameter() {
explicitReceiverParameter = true;
}
public boolean isExplicitReceiverParameter() {
return explicitReceiverParameter;
}
public Node getTypeNameNode() {
if (jjtGetParent() instanceof ASTFormalParameter) {
return findTypeNameNode(jjtGetParent());

View File

@ -13,6 +13,7 @@ import net.sourceforge.pmd.PMD;
import net.sourceforge.pmd.lang.java.ParserTst;
import org.apache.commons.io.IOUtils;
import org.junit.Assert;
import org.junit.Test;
public class ParserCornersTest extends ParserTst {
@ -54,15 +55,25 @@ public class ParserCornersTest extends ParserTst {
}
@Test
public void testParsersCases() {
public void testParsersCases15() {
String test15 = readAsString("/net/sourceforge/pmd/ast/ParserCornerCases.java");
parseJava15(test15);
}
@Test
public void testParsersCases17() {
String test17 = readAsString("/net/sourceforge/pmd/ast/ParserCornerCases17.java");
parseJava17(test17);
}
@Test
public void testParsersCases18() throws Exception {
String test18 = readAsString("/net/sourceforge/pmd/ast/ParserCornerCases18.java");
parseJava18(test18);
ASTCompilationUnit cu = parseJava18(test18);
Assert.assertEquals(13, cu.findChildNodesWithXPath("//FormalParameter").size());
Assert.assertEquals(4, cu.findChildNodesWithXPath("//FormalParameter[@ExplicitReceiverParameter='true']").size());
Assert.assertEquals(9, cu.findChildNodesWithXPath("//FormalParameter[@ExplicitReceiverParameter='false']").size());
}
/**

View File

@ -153,6 +153,22 @@ public class ParserCornerCases18 {
};
}
}
/**
* Explicit receiver Parameters
* see: http://blog.joda.org/2015/12/explicit-receiver-parameters.html
* and: https://sourceforge.net/p/pmd/bugs/1455/
*/
public void methodWithReceiverParameter(ParserCornerCases18 this) { }
public void methodWithReceiverAndOtherParameters(ParserCornerCases18 this, String other) { }
public void methodWithReceiverParameterWithAnnotation(@AnnotatedUsage ParserCornerCases18 this, String other) { }
@Target(ElementType.TYPE_USE)
public @interface AnnotatedUsage {}
class Inner {
Inner(ParserCornerCases18 ParserCornerCases18.this) {}
}
}
interface DefaultIterator<E> {

View File

@ -29,6 +29,8 @@
* [#1449](https://sourceforge.net/p/pmd/bugs/1449/): false positive when casting a variable to short
* java-design/AccessorClassGeneration:
* [#1452](https://sourceforge.net/p/pmd/bugs/1452/): ArrayIndexOutOfBoundsException with Annotations for AccessorClassGenerationRule
* General
* [#1455](https://sourceforge.net/p/pmd/bugs/1455/): PMD doesn't handle Java 8 explicit receiver parameters
**API Changes:**