Merge branch 'master' into metrics
This commit is contained in:
@ -5,7 +5,7 @@
|
||||
|
||||
package net.sourceforge.pmd.lang.java.ast;
|
||||
|
||||
public class ASTPrimarySuffix extends AbstractJavaNode {
|
||||
public class ASTPrimarySuffix extends AbstractJavaTypeNode {
|
||||
|
||||
private boolean isArguments;
|
||||
private boolean isArrayDereference;
|
||||
|
@ -61,6 +61,7 @@ import net.sourceforge.pmd.lang.java.ast.ASTUnaryExpression;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTUnaryExpressionNotPlusMinus;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclarator;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId;
|
||||
import net.sourceforge.pmd.lang.java.ast.AbstractJavaTypeNode;
|
||||
import net.sourceforge.pmd.lang.java.ast.JavaParserVisitorAdapter;
|
||||
import net.sourceforge.pmd.lang.java.ast.TypeNode;
|
||||
|
||||
@ -442,34 +443,65 @@ public class ClassTypeResolver extends JavaParserVisitorAdapter {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visit(ASTPrimaryExpression node, Object data) {
|
||||
super.visit(node, data);
|
||||
if (node.jjtGetNumChildren() == 1) {
|
||||
rollupTypeUnary(node);
|
||||
} else {
|
||||
// TODO OMG, this is complicated. PrimaryExpression, PrimaryPrefix
|
||||
// and PrimarySuffix are all related.
|
||||
public Object visit(ASTPrimaryExpression primaryNode, Object data) {
|
||||
super.visit(primaryNode, data);
|
||||
|
||||
Class<?> primaryNodeType = null;
|
||||
AbstractJavaTypeNode previousChild = null;
|
||||
|
||||
for (int childIndex = 0; childIndex < primaryNode.jjtGetNumChildren(); ++childIndex) {
|
||||
AbstractJavaTypeNode currentChild = (AbstractJavaTypeNode) primaryNode.jjtGetChild(childIndex);
|
||||
|
||||
// skip children which already have their type assigned
|
||||
if (currentChild.getType() == null) {
|
||||
// Last token, because if 'this' is a Suffix, it'll have tokens '.' and 'this'
|
||||
if (currentChild.jjtGetLastToken().toString().equals("this")) {
|
||||
if (previousChild != null) { // Qualified 'this' expression
|
||||
currentChild.setType(previousChild.getType());
|
||||
} else { // simple 'this' expression
|
||||
ASTClassOrInterfaceDeclaration typeDeclaration
|
||||
= currentChild.getFirstParentOfType(ASTClassOrInterfaceDeclaration.class);
|
||||
if (typeDeclaration != null) {
|
||||
currentChild.setType(typeDeclaration.getType());
|
||||
}
|
||||
}
|
||||
|
||||
// Last token, because if 'super' is a Suffix, it'll have tokens '.' and 'super'
|
||||
} else if (currentChild.jjtGetLastToken().toString().equals("super")) {
|
||||
if (previousChild != null) { // Qualified 'super' expression
|
||||
currentChild.setType(previousChild.getType().getSuperclass());
|
||||
} else { // simple 'super' expression
|
||||
ASTClassOrInterfaceDeclaration typeDeclaration
|
||||
= currentChild.getFirstParentOfType(ASTClassOrInterfaceDeclaration.class);
|
||||
if (typeDeclaration != null && typeDeclaration.getType() != null) {
|
||||
currentChild.setType(typeDeclaration.getType().getSuperclass());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//if (currentChild.getType() != null)
|
||||
primaryNodeType = currentChild.getType();
|
||||
|
||||
previousChild = currentChild;
|
||||
}
|
||||
|
||||
primaryNode.setType(primaryNodeType);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visit(ASTPrimaryPrefix node, Object data) {
|
||||
super.visit(node, data);
|
||||
if (node.getImage() == null) {
|
||||
rollupTypeUnary(node);
|
||||
} else {
|
||||
// TODO OMG, this is complicated. PrimaryExpression, PrimaryPrefix
|
||||
// and PrimarySuffix are all related.
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visit(ASTPrimarySuffix node, Object data) {
|
||||
super.visit(node, data);
|
||||
// TODO OMG, this is complicated. PrimaryExpression, PrimaryPrefix and
|
||||
// PrimarySuffix are all related.
|
||||
return data;
|
||||
}
|
||||
|
||||
|
@ -14,11 +14,13 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.jaxen.JaxenException;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
|
||||
import net.sourceforge.pmd.lang.LanguageRegistry;
|
||||
import net.sourceforge.pmd.lang.LanguageVersionHandler;
|
||||
import net.sourceforge.pmd.lang.ast.Node;
|
||||
@ -35,13 +37,17 @@ import net.sourceforge.pmd.lang.java.ast.ASTImportDeclaration;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTLiteral;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTName;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTNullLiteral;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTPrimaryExpression;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTPrimaryPrefix;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTReferenceType;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTStatementExpression;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTType;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTTypeDeclaration;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclarator;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId;
|
||||
import net.sourceforge.pmd.lang.java.ast.AbstractJavaTypeNode;
|
||||
import net.sourceforge.pmd.lang.java.ast.TypeNode;
|
||||
|
||||
import net.sourceforge.pmd.lang.java.symboltable.VariableNameDeclaration;
|
||||
import net.sourceforge.pmd.lang.java.typeresolution.ClassTypeResolver;
|
||||
import net.sourceforge.pmd.typeresolution.testdata.AnonymousInnerClass;
|
||||
@ -53,6 +59,10 @@ import net.sourceforge.pmd.typeresolution.testdata.InnerClass;
|
||||
import net.sourceforge.pmd.typeresolution.testdata.Literals;
|
||||
import net.sourceforge.pmd.typeresolution.testdata.Operators;
|
||||
import net.sourceforge.pmd.typeresolution.testdata.Promotion;
|
||||
import net.sourceforge.pmd.typeresolution.testdata.SuperClass;
|
||||
import net.sourceforge.pmd.typeresolution.testdata.SuperExpression;
|
||||
import net.sourceforge.pmd.typeresolution.testdata.ThisExpression;
|
||||
|
||||
|
||||
public class ClassTypeResolverTest {
|
||||
|
||||
@ -584,6 +594,73 @@ public class ClassTypeResolverTest {
|
||||
Assert.assertSame(StringTokenizer.class, id.getType());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testThisExpression() throws JaxenException {
|
||||
ASTCompilationUnit acu = parseAndTypeResolveForClass15(ThisExpression.class);
|
||||
|
||||
List<ASTPrimaryExpression> expressions = convertList(
|
||||
acu.findChildNodesWithXPath("//PrimaryExpression"),
|
||||
ASTPrimaryExpression.class);
|
||||
List<ASTPrimaryPrefix> prefixes = convertList(
|
||||
acu.findChildNodesWithXPath("//PrimaryPrefix"),
|
||||
ASTPrimaryPrefix.class);
|
||||
|
||||
int index = 0;
|
||||
|
||||
|
||||
assertEquals(ThisExpression.class, expressions.get(index).getType());
|
||||
assertEquals(ThisExpression.class, prefixes.get(index++).getType());
|
||||
assertEquals(ThisExpression.class, expressions.get(index).getType());
|
||||
assertEquals(ThisExpression.class, prefixes.get(index++).getType());
|
||||
assertEquals(ThisExpression.class, expressions.get(index).getType());
|
||||
assertEquals(ThisExpression.class, prefixes.get(index++).getType());
|
||||
assertEquals(ThisExpression.class, expressions.get(index).getType());
|
||||
assertEquals(ThisExpression.class, prefixes.get(index++).getType());
|
||||
|
||||
assertEquals(ThisExpression.ThisExprNested.class, expressions.get(index).getType());
|
||||
assertEquals(ThisExpression.ThisExprNested.class, prefixes.get(index++).getType());
|
||||
|
||||
// Qualified this
|
||||
assertEquals(ThisExpression.class, expressions.get(index).getType());
|
||||
assertEquals(ThisExpression.class, prefixes.get(index).getType());
|
||||
assertEquals(ThisExpression.class, ((TypeNode) expressions.get(index++).jjtGetChild(1)).getType());
|
||||
|
||||
assertEquals(ThisExpression.ThisExprStaticNested.class, expressions.get(index).getType());
|
||||
assertEquals(ThisExpression.ThisExprStaticNested.class, prefixes.get(index++).getType());
|
||||
|
||||
// Make sure we got them all
|
||||
assertEquals("All expressions not tested", index, expressions.size());
|
||||
assertEquals("All expressions not tested", index, prefixes.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuperExpression() throws JaxenException {
|
||||
ASTCompilationUnit acu = parseAndTypeResolveForClass15(SuperExpression.class);
|
||||
|
||||
List<AbstractJavaTypeNode> expressions = convertList(
|
||||
acu.findChildNodesWithXPath("//VariableInitializer/Expression/PrimaryExpression/PrimaryPrefix"),
|
||||
AbstractJavaTypeNode.class);
|
||||
|
||||
int index = 0;
|
||||
|
||||
assertEquals(SuperClass.class, expressions.get(index++).getType());
|
||||
assertEquals(SuperClass.class, expressions.get(index++).getType());
|
||||
assertEquals(SuperClass.class, expressions.get(index++).getType());
|
||||
assertEquals(SuperClass.class, expressions.get(index++).getType());
|
||||
assertEquals(SuperExpression.class, ((TypeNode) expressions.get(index).jjtGetParent().jjtGetChild(0)).getType());
|
||||
assertEquals(SuperClass.class, ((TypeNode) expressions.get(index++).jjtGetParent().jjtGetChild(1)).getType());
|
||||
|
||||
assertEquals(SuperExpression.class, expressions.get(index++).getType());
|
||||
assertEquals(SuperExpression.class, expressions.get(index++).getType());
|
||||
|
||||
|
||||
// Make sure we got them all
|
||||
assertEquals("All expressions not tested", index, expressions.size());
|
||||
}
|
||||
|
||||
|
||||
|
||||
private ASTCompilationUnit parseAndTypeResolveForClass15(Class<?> clazz) {
|
||||
return parseAndTypeResolveForClass(clazz, "1.5");
|
||||
}
|
||||
|
10
pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/testdata/SuperClass.java
vendored
Normal file
10
pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/testdata/SuperClass.java
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
/**
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
|
||||
package net.sourceforge.pmd.typeresolution.testdata;
|
||||
|
||||
public class SuperClass {
|
||||
protected SuperClass s;
|
||||
}
|
32
pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/testdata/SuperExpression.java
vendored
Normal file
32
pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/testdata/SuperExpression.java
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
/**
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
|
||||
package net.sourceforge.pmd.typeresolution.testdata;
|
||||
|
||||
public class SuperExpression extends SuperClass {
|
||||
public SuperExpression() {
|
||||
SuperClass a = super.s;
|
||||
}
|
||||
|
||||
protected SuperExpression b;
|
||||
|
||||
{ SuperClass s = super.s; }
|
||||
|
||||
public void foo() {
|
||||
SuperClass a = super.s;
|
||||
}
|
||||
|
||||
SuperClass a = super.s;
|
||||
|
||||
public class SuperExprNested extends SuperExpression {
|
||||
SuperClass a = SuperExpression.super.s;
|
||||
SuperExpression b = super.b;
|
||||
}
|
||||
|
||||
public static class ThisExprStaticNested extends SuperExpression {
|
||||
SuperExpression a = super.b;
|
||||
}
|
||||
}
|
||||
|
32
pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/testdata/ThisExpression.java
vendored
Normal file
32
pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/testdata/ThisExpression.java
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
/**
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
|
||||
package net.sourceforge.pmd.typeresolution.testdata;
|
||||
|
||||
public class ThisExpression {
|
||||
public ThisExpression() {
|
||||
ThisExpression a = this;
|
||||
}
|
||||
|
||||
{
|
||||
ThisExpression a = this;
|
||||
}
|
||||
|
||||
public void foo() {
|
||||
ThisExpression a = this;
|
||||
}
|
||||
|
||||
ThisExpression a = this;
|
||||
|
||||
public class ThisExprNested {
|
||||
ThisExprNested a = this;
|
||||
ThisExpression b = ThisExpression.this;
|
||||
}
|
||||
|
||||
public static class ThisExprStaticNested {
|
||||
ThisExprStaticNested a = this;
|
||||
}
|
||||
}
|
||||
|
@ -4,18 +4,32 @@
|
||||
|
||||
package net.sourceforge.pmd.typeresolution;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.jaxen.JaxenException;
|
||||
import org.junit.Test;
|
||||
|
||||
import net.sourceforge.pmd.lang.LanguageRegistry;
|
||||
import net.sourceforge.pmd.lang.LanguageVersionHandler;
|
||||
import net.sourceforge.pmd.lang.ast.Node;
|
||||
import net.sourceforge.pmd.lang.java.JavaLanguageModule;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTPrimaryExpression;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTPrimaryPrefix;
|
||||
import net.sourceforge.pmd.lang.java.ast.AbstractJavaTypeNode;
|
||||
import net.sourceforge.pmd.typeresolution.testdata.SuperClass;
|
||||
import net.sourceforge.pmd.typeresolution.testdata.SuperExpression;
|
||||
import net.sourceforge.pmd.typeresolution.testdata.ThisExpression;
|
||||
import net.sourceforge.pmd.typeresolution.testdata.UsesJavaStreams;
|
||||
import net.sourceforge.pmd.typeresolution.testdata.UsesRepeatableAnnotations;
|
||||
|
||||
|
||||
|
||||
public class ClassTypeResolverJava8Test {
|
||||
|
||||
@Test
|
||||
@ -28,6 +42,53 @@ public class ClassTypeResolverJava8Test {
|
||||
ASTCompilationUnit acu = parseAndTypeResolveForClass18(UsesRepeatableAnnotations.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThisExpression() throws JaxenException {
|
||||
ASTCompilationUnit acu = parseAndTypeResolveForClass18(ThisExpression.class);
|
||||
|
||||
List<ASTPrimaryExpression> expressions = convertList(
|
||||
acu.findChildNodesWithXPath("//VariableInitializer/Expression/PrimaryExpression"),
|
||||
ASTPrimaryExpression.class);
|
||||
List<ASTPrimaryPrefix> prefixes = convertList(
|
||||
acu.findChildNodesWithXPath("//VariableInitializer/Expression/PrimaryExpression/PrimaryPrefix"),
|
||||
ASTPrimaryPrefix.class);
|
||||
|
||||
int index = 0;
|
||||
|
||||
assertEquals(ThisExpression.class, expressions.get(index).getType());
|
||||
assertEquals(ThisExpression.class, prefixes.get(index++).getType());
|
||||
assertEquals(ThisExpression.PrimaryThisInterface.class, expressions.get(index).getType());
|
||||
assertEquals(ThisExpression.PrimaryThisInterface.class, prefixes.get(index++).getType());
|
||||
|
||||
// Make sure we got them all
|
||||
assertEquals("All expressions not tested", index, expressions.size());
|
||||
assertEquals("All expressions not tested", index, prefixes.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuperExpression() throws JaxenException {
|
||||
ASTCompilationUnit acu = parseAndTypeResolveForClass18(SuperExpression.class);
|
||||
|
||||
List<AbstractJavaTypeNode> expressions = convertList(
|
||||
acu.findChildNodesWithXPath("//VariableInitializer/Expression/PrimaryExpression/PrimaryPrefix"),
|
||||
AbstractJavaTypeNode.class);
|
||||
|
||||
int index = 0;
|
||||
|
||||
assertEquals(SuperClass.class, expressions.get(index++).getType());
|
||||
|
||||
// Make sure we got them all
|
||||
assertEquals("All expressions not tested", index, expressions.size());
|
||||
}
|
||||
|
||||
private static <T> List<T> convertList(List<Node> nodes, Class<T> target) {
|
||||
List<T> converted = new ArrayList<>();
|
||||
for (Node n : nodes) {
|
||||
converted.add(target.cast(n));
|
||||
}
|
||||
return converted;
|
||||
}
|
||||
|
||||
private ASTCompilationUnit parseAndTypeResolveForClass18(Class<?> clazz) {
|
||||
return parseAndTypeResolveForClass(clazz, "1.8");
|
||||
}
|
||||
|
10
pmd-java8/src/test/java/net/sourceforge/pmd/typeresolution/testdata/SuperClass.java
vendored
Normal file
10
pmd-java8/src/test/java/net/sourceforge/pmd/typeresolution/testdata/SuperClass.java
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
/**
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
|
||||
package net.sourceforge.pmd.typeresolution.testdata;
|
||||
|
||||
public class SuperClass {
|
||||
protected SuperClass s;
|
||||
}
|
15
pmd-java8/src/test/java/net/sourceforge/pmd/typeresolution/testdata/SuperExpression.java
vendored
Normal file
15
pmd-java8/src/test/java/net/sourceforge/pmd/typeresolution/testdata/SuperExpression.java
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
/**
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
|
||||
package net.sourceforge.pmd.typeresolution.testdata;
|
||||
|
||||
public class SuperExpression extends SuperClass {
|
||||
public void foo() {
|
||||
((Runnable) (() -> {
|
||||
SuperClass a = super.s; }))
|
||||
.run();
|
||||
}
|
||||
}
|
||||
|
22
pmd-java8/src/test/java/net/sourceforge/pmd/typeresolution/testdata/ThisExpression.java
vendored
Normal file
22
pmd-java8/src/test/java/net/sourceforge/pmd/typeresolution/testdata/ThisExpression.java
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
/**
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
|
||||
package net.sourceforge.pmd.typeresolution.testdata;
|
||||
|
||||
public class ThisExpression {
|
||||
|
||||
public void foo() {
|
||||
((Runnable) (() -> {
|
||||
ThisExpression b = this; }))
|
||||
.run();
|
||||
}
|
||||
|
||||
public interface PrimaryThisInterface {
|
||||
default void foo() {
|
||||
PrimaryThisInterface a = this;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -33,4 +33,5 @@ This is a minor release.
|
||||
* [#406](https://github.com/pmd/pmd/pull/406): \[java] False positive with lambda in java-design/ConstructorCallsOverridableMethod
|
||||
* [#409](https://github.com/pmd/pmd/pull/409): \[java] Groundwork for the upcoming metrics framework
|
||||
* [#416](https://github.com/pmd/pmd/pull/416): \[java] FIXED: Java 8 parsing problem with annotations for wildcards
|
||||
* [#418](https://github.com/pmd/pmd/pull/418): \[java] Type resolution: super and this keywords
|
||||
|
||||
|
Reference in New Issue
Block a user