[java] Prepare for Java 11

This commit is contained in:
Andreas Dangel
2018-07-19 22:00:34 +02:00
parent 0f9bc63bfc
commit c362f5a77f
12 changed files with 221 additions and 60 deletions

View File

@ -2206,10 +2206,38 @@ void LambdaExpression() :
{ checkForBadLambdaUsage(); }
{
VariableDeclaratorId() "->" ( Expression() | Block() )
| LOOKAHEAD(3) FormalParameters() "->" ( Expression() | Block() )
| LOOKAHEAD(3) LambdaParameters() "->" ( Expression() | Block() )
| LOOKAHEAD(3) "(" VariableDeclaratorId() ( "," VariableDeclaratorId() )* ")" "->" ( Expression() | Block() )
}
void LambdaParameters() #FormalParameters :
{}
{
"(" [ LambdaParameterList() ] ")"
}
void LambdaParameterList() #void :
{}
{
LambdaParameter() ( "," LambdaParameter() )*
}
void LambdaParameter() #FormalParameter :
{}
{
( "final" {jjtThis.setFinal(true);} | Annotation() )*
LambdaParameterType()
[ "..." {checkForBadVariableArgumentsUsage();} {jjtThis.setVarargs();} ]
VariableDeclaratorId()
}
void LambdaParameterType() #void :
{}
{
LOOKAHEAD( { jdkVersion >= 11 && isKeyword("var") } ) <IDENTIFIER>
| Type()
}
void PrimarySuffix() :
{Token t;}
{ LOOKAHEAD(2) "." "this"

View File

@ -24,7 +24,8 @@ public class JavaLanguageModule extends BaseLanguageModule {
addVersion("1.7", new JavaLanguageHandler(7), false);
addVersion("1.8", new JavaLanguageHandler(8), false);
addVersion("9", new JavaLanguageHandler(9), false);
addVersion("10", new JavaLanguageHandler(10), true);
addVersion("10", new JavaLanguageHandler(10), false);
addVersion("11", new JavaLanguageHandler(11), true);
}
}

View File

@ -14,6 +14,7 @@ import net.sourceforge.pmd.lang.java.typeresolution.typedefinition.JavaTypeDefin
* production of {@link ASTMethodDeclarator} to represent a
* method's formal parameter. Also used in the {@link ASTCatchStatement}
* production to represent the declared exception variable.
* Also used in LambdaExpressions for the LambdaParameters.
* <pre>
* ( "final" | Annotation )* Type ( "|" Type )* [ "..." ] VariableDeclaratorId
* </pre>
@ -93,7 +94,9 @@ public class ASTFormalParameter extends AbstractJavaAccessTypeNode implements Di
*/
@Override
public boolean isArray() {
return isVarargs() || getTypeNode().isArray() || getVariableDeclaratorId().isArray();
return isVarargs()
|| getTypeNode() != null && getTypeNode().isArray()
|| getVariableDeclaratorId().isArray();
}
@Override

View File

@ -206,7 +206,7 @@ public class ASTVariableDeclaratorId extends AbstractJavaTypeNode implements Dim
*/
public boolean isTypeInferred() {
// TODO think about supporting var for lambda parameters
return isLambdaParamWithNoType() || isLocalVariableTypeInferred();
return isLambdaParamWithNoType() || isLocalVariableTypeInferred() || isLambdaTypeInferred();
}
@ -222,6 +222,11 @@ public class ASTVariableDeclaratorId extends AbstractJavaTypeNode implements Dim
return false;
}
private boolean isLambdaTypeInferred() {
return getNthParent(3) instanceof ASTLambdaExpression
&& jjtGetParent().getFirstChildOfType(ASTType.class) == null;
}
/**
* Returns the first child of the node returned by {@link #getTypeNode()}.
* The image of that node can usually be interpreted as the image of the

View File

@ -49,6 +49,7 @@ public abstract class Foo {
<rule name="AccessorClassGeneration"
since="1.04"
maximumLanguageVersion="10"
message="Avoid instantiation through private constructors from outside of the constructor's class."
class="net.sourceforge.pmd.lang.java.rule.bestpractices.AccessorClassGenerationRule"
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_bestpractices.html#accessorclassgeneration">
@ -77,6 +78,7 @@ public class Outer {
<rule name="AccessorMethodGeneration"
language="java"
since="5.5.4"
maximumLanguageVersion="10"
message="Avoid autogenerated methods to access private fields and methods of inner / outer classes"
class="net.sourceforge.pmd.lang.java.rule.bestpractices.AccessorMethodGenerationRule"
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_bestpractices.html#accessormethodgeneration">

View File

@ -26,8 +26,8 @@ public class LanguageVersionDiscovererTest {
File javaFile = new File("/path/to/MyClass.java");
LanguageVersion languageVersion = discoverer.getDefaultLanguageVersionForFile(javaFile);
assertEquals("LanguageVersion must be Java 10 !",
LanguageRegistry.getLanguage(JavaLanguageModule.NAME).getVersion("10"), languageVersion);
assertEquals("LanguageVersion must be Java 11 !",
LanguageRegistry.getLanguage(JavaLanguageModule.NAME).getVersion("11"), languageVersion);
}
/**
@ -48,7 +48,7 @@ public class LanguageVersionDiscovererTest {
public void testLanguageVersionDiscoverer() {
PMDConfiguration configuration = new PMDConfiguration();
LanguageVersionDiscoverer languageVersionDiscoverer = configuration.getLanguageVersionDiscoverer();
assertEquals("Default Java version", LanguageRegistry.getLanguage(JavaLanguageModule.NAME).getVersion("10"),
assertEquals("Default Java version", LanguageRegistry.getLanguage(JavaLanguageModule.NAME).getVersion("11"),
languageVersionDiscoverer
.getDefaultLanguageVersion(LanguageRegistry.getLanguage(JavaLanguageModule.NAME)));
configuration

View File

@ -34,6 +34,12 @@ public class LanguageVersionTest extends AbstractLanguageVersionTest {
LanguageRegistry.getLanguage(JavaLanguageModule.NAME).getVersion("1.7"), },
{ JavaLanguageModule.NAME, JavaLanguageModule.TERSE_NAME, "1.8",
LanguageRegistry.getLanguage(JavaLanguageModule.NAME).getVersion("1.8"), },
{ JavaLanguageModule.NAME, JavaLanguageModule.TERSE_NAME, "9",
LanguageRegistry.getLanguage(JavaLanguageModule.NAME).getVersion("9"), },
{ JavaLanguageModule.NAME, JavaLanguageModule.TERSE_NAME, "10",
LanguageRegistry.getLanguage(JavaLanguageModule.NAME).getVersion("10"), },
{ JavaLanguageModule.NAME, JavaLanguageModule.TERSE_NAME, "11",
LanguageRegistry.getLanguage(JavaLanguageModule.NAME).getVersion("11"), },
// this one won't be found: case sensitive!
{ "JAVA", "JAVA", "1.7", null, }, });

View File

@ -0,0 +1,89 @@
/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.lang.java.ast;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.List;
import org.apache.commons.io.IOUtils;
import org.junit.Assert;
import org.junit.Test;
import net.sourceforge.pmd.lang.ast.Node;
import net.sourceforge.pmd.lang.java.ParserTstUtil;
public class Java11Test {
private static String loadSource(String name) {
try {
return IOUtils.toString(Java10Test.class.getResourceAsStream("jdkversiontests/java11/" + name),
StandardCharsets.UTF_8);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Test
public void testLocalVariableSyntaxForLambdaParametersWithJava10() {
ASTCompilationUnit compilationUnit = ParserTstUtil.parseAndTypeResolveJava("10",
loadSource("LocalVariableSyntaxForLambdaParameters.java"));
List<ASTLambdaExpression> lambdas = compilationUnit.findDescendantsOfType(ASTLambdaExpression.class);
Assert.assertEquals(4, lambdas.size());
// (var x) -> String.valueOf(x);
List<ASTFormalParameter> formalParameters = lambdas.get(0).findDescendantsOfType(ASTFormalParameter.class);
Assert.assertEquals(1, formalParameters.size());
ASTType type = formalParameters.get(0).getFirstChildOfType(ASTType.class);
assertEquals("var", type.getTypeImage());
assertEquals(1, type.jjtGetNumChildren());
ASTReferenceType referenceType = type.getFirstChildOfType(ASTReferenceType.class);
assertNotNull(referenceType);
assertEquals(1, referenceType.jjtGetNumChildren());
ASTClassOrInterfaceType classType = referenceType.getFirstChildOfType(ASTClassOrInterfaceType.class);
assertNotNull(classType);
assertEquals("var", classType.getImage());
// (var x, var y) -> x + y;
formalParameters = lambdas.get(1).findDescendantsOfType(ASTFormalParameter.class);
Assert.assertEquals(2, formalParameters.size());
type = formalParameters.get(0).getFirstChildOfType(ASTType.class);
assertEquals("var", type.getTypeImage());
assertEquals(1, type.jjtGetNumChildren());
referenceType = type.getFirstChildOfType(ASTReferenceType.class);
assertNotNull(referenceType);
assertEquals(1, referenceType.jjtGetNumChildren());
classType = referenceType.getFirstChildOfType(ASTClassOrInterfaceType.class);
assertNotNull(classType);
assertEquals("var", classType.getImage());
type = formalParameters.get(1).getFirstChildOfType(ASTType.class);
assertEquals("var", type.getTypeImage());
assertEquals(1, type.jjtGetNumChildren());
// (@Nonnull var x) -> String.valueOf(x);
formalParameters = lambdas.get(2).findDescendantsOfType(ASTFormalParameter.class);
Assert.assertEquals(1, formalParameters.size());
Node firstChild = formalParameters.get(0).jjtGetChild(0);
Assert.assertTrue(firstChild instanceof ASTAnnotation);
}
@Test
public void testLocalVariableSyntaxForLambdaParametersWithJava11() {
ASTCompilationUnit compilationUnit = ParserTstUtil.parseAndTypeResolveJava("11",
loadSource("LocalVariableSyntaxForLambdaParameters.java"));
List<ASTLambdaExpression> lambdas = compilationUnit.findDescendantsOfType(ASTLambdaExpression.class);
Assert.assertEquals(4, lambdas.size());
// (var x) -> String.valueOf(x);
List<ASTFormalParameter> formalParameters = lambdas.get(0).findDescendantsOfType(ASTFormalParameter.class);
Assert.assertEquals(1, formalParameters.size());
assertNull(formalParameters.get(0).getTypeNode());
}
}

View File

@ -0,0 +1,28 @@
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.function.BiFunction;
import java.util.function.Function;
public class LocalVariableSyntaxForLambdaParameters {
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface Nonnull { }
public void createLambdas() {
//var lambda = (var x, var y) -> x.process(y);
Function<Integer, String> lambda1 = (var x) -> String.valueOf(x);
BiFunction<Integer, Integer, Integer> lambda2 = (var x, var y) -> x + y;
}
public void createAnnotatedLambdaParameters() {
//@Nonnull var x = new Foo();
//(@Nonnull var x, @Nullable var y) -> x.process(y)
Function<Integer, String> lambda1 = (@Nonnull var x) -> String.valueOf(x);
BiFunction<Integer, Integer, Integer> lambda2 = (@Nonnull var x, @Nonnull var y) -> x + y;
}
}

View File

@ -4,9 +4,7 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sourceforge.net/rule-tests http://pmd.sourceforge.net/rule-tests_1_0_0.xsd">
<test-code>
<description><![CDATA[
inner class has private constructor
]]></description>
<description>inner class has private constructor</description>
<expected-problems>1</expected-problems>
<code><![CDATA[
public class Foo1 {
@ -19,11 +17,11 @@ public class Foo1 {
}
}
]]></code>
<source-type>java 10</source-type>
</test-code>
<test-code>
<description><![CDATA[
inner class has public constructor
]]></description>
<description>inner class has public constructor</description>
<expected-problems>0</expected-problems>
<code><![CDATA[
public class Foo2 {
@ -36,11 +34,11 @@ public class Foo2 {
}
}
]]></code>
<source-type>java 10</source-type>
</test-code>
<test-code>
<description><![CDATA[
outer class has public constructor
]]></description>
<description>outer class has public constructor</description>
<expected-problems>1</expected-problems>
<code><![CDATA[
public class Foo3 {
@ -53,11 +51,11 @@ public class Foo3 {
}
}
]]></code>
<source-type>java 10</source-type>
</test-code>
<test-code>
<description><![CDATA[
final inner class
]]></description>
<description>final inner class</description>
<expected-problems>0</expected-problems>
<code><![CDATA[
public class Foo {
@ -67,11 +65,11 @@ public class Foo {
}
}
]]></code>
<source-type>java 10</source-type>
</test-code>
<test-code>
<description><![CDATA[
interface inner class has private constructor
]]></description>
<description>interface inner class has private constructor</description>
<expected-problems>1</expected-problems>
<code><![CDATA[
package foo;
@ -85,11 +83,11 @@ public interface Foo1 {
}
}
]]></code>
<source-type>java 10</source-type>
</test-code>
<test-code>
<description><![CDATA[
there's a check for int declaration - not sure right now why
]]></description>
<description>there's a check for int declaration - not sure right now why</description>
<expected-problems>1</expected-problems>
<code><![CDATA[
public class Foo1 {
@ -102,18 +100,20 @@ public class Foo1 {
}
}
]]></code>
<source-type>java 10</source-type>
</test-code>
<test-code>
<description>#1452 ArrayIndexOutOfBoundsException with Annotations for AccessorClassGenerationRule</description>
<expected-problems>0</expected-problems>
<code><![CDATA[
public @interface Something { public interface SomthingElse{}; }
]]></code>
<source-type>java 10</source-type>
</test-code>
<test-code>
<description><![CDATA[
#291 - Private constructor called from anonymous class
]]></description>
<description>#291 - Private constructor called from anonymous class</description>
<expected-problems>1</expected-problems>
<code><![CDATA[
public class Example extends View {
@ -133,11 +133,11 @@ public class Example extends View {
}
}
]]></code>
<source-type>java 10</source-type>
</test-code>
<test-code>
<description><![CDATA[
Array initializer is not a class body
]]></description>
<description>Array initializer is not a class body</description>
<expected-problems>0</expected-problems>
<code><![CDATA[
public class Foo {
@ -153,5 +153,6 @@ public class Foo {
}
}
]]></code>
<source-type>java 10</source-type>
</test-code>
</test-data>

View File

@ -4,9 +4,7 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sourceforge.net/rule-tests http://pmd.sourceforge.net/rule-tests_1_0_0.xsd">
<test-code>
<description><![CDATA[
inner class accesses private field from outer class
]]></description>
<description>inner class accesses private field from outer class</description>
<expected-problems>1</expected-problems>
<expected-linenumbers>8</expected-linenumbers>
<code><![CDATA[
@ -22,11 +20,11 @@ public class Foo {
}
}
]]></code>
<source-type>java 10</source-type>
</test-code>
<test-code>
<description><![CDATA[
inner class accesses private field from outer class unqualified
]]></description>
<description>inner class accesses private field from outer class unqualified</description>
<expected-problems>1</expected-problems>
<expected-linenumbers>8</expected-linenumbers>
<code><![CDATA[
@ -42,11 +40,11 @@ public class Foo {
}
}
]]></code>
<source-type>java 10</source-type>
</test-code>
<test-code>
<description><![CDATA[
outer class accesses private field from inner class
]]></description>
<description>outer class accesses private field from inner class</description>
<expected-problems>1</expected-problems>
<expected-linenumbers>9</expected-linenumbers>
<code><![CDATA[
@ -62,11 +60,11 @@ public class Foo {
}
}
]]></code>
<source-type>java 10</source-type>
</test-code>
<test-code>
<description><![CDATA[
non private fields are ok
]]></description>
<test-code>
<description>non private fields are ok</description>
<expected-problems>0</expected-problems>
<code><![CDATA[
public class Foo {
@ -85,11 +83,11 @@ public class Foo {
}
}
]]></code>
<source-type>java 10</source-type>
</test-code>
<test-code>
<description><![CDATA[
inner class accesses private method of outer class, unqualified
]]></description>
<description>inner class accesses private method of outer class, unqualified</description>
<expected-problems>1</expected-problems>
<expected-linenumbers>4</expected-linenumbers>
<code><![CDATA[
@ -104,11 +102,11 @@ public class Foo {
}
}
]]></code>
<source-type>java 10</source-type>
</test-code>
<test-code>
<description><![CDATA[
inner class accesses private method of outer class, qualified
]]></description>
<description>inner class accesses private method of outer class, qualified</description>
<expected-problems>1</expected-problems>
<expected-linenumbers>4</expected-linenumbers>
<code><![CDATA[
@ -123,11 +121,11 @@ public class Foo {
}
}
]]></code>
<source-type>java 10</source-type>
</test-code>
<test-code>
<description><![CDATA[
outer class accesses private method of inner class
]]></description>
<description>outer class accesses private method of inner class</description>
<expected-problems>1</expected-problems>
<expected-linenumbers>8</expected-linenumbers>
<code><![CDATA[
@ -142,11 +140,10 @@ public class Foo {
}
}
]]></code>
<source-type>java 10</source-type>
</test-code>
<test-code>
<description><![CDATA[
inner class accesses non-private methods of outer class
]]></description>
<description>inner class accesses non-private methods of outer class</description>
<expected-problems>0</expected-problems>
<code><![CDATA[
public class Foo {
@ -168,11 +165,11 @@ public class Foo {
}
}
]]></code>
<source-type>java 10</source-type>
</test-code>
<test-code>
<description><![CDATA[
#274 - Method inside static inner class incorrectly reported as generating accessor methods
]]></description>
<description>#274 - Method inside static inner class incorrectly reported as generating accessor methods</description>
<expected-problems>0</expected-problems>
<code><![CDATA[
public class Foo implements Parcelable {
@ -195,5 +192,6 @@ public class Foo implements Parcelable {
};
}
]]></code>
<source-type>java 10</source-type>
</test-code>
</test-data>

View File

@ -764,7 +764,7 @@ Additionally it includes CPD, the copy-paste-detector. CPD finds duplicated code
<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm</artifactId>
<version>6.1.1</version>
<version>6.2</version>
</dependency>
<dependency>
<groupId>net.sourceforge.pmd</groupId>