Merge branch 'master' of https://github.com/pmd/pmd into metrics

This commit is contained in:
oowekyala
2017-06-24 22:01:31 +02:00
41 changed files with 1426 additions and 193 deletions

View File

@ -47,4 +47,8 @@ public class ASTClassOrInterfaceType extends AbstractJavaTypeNode {
}
return false;
}
public boolean isAnonymousClass() {
return jjtGetParent().hasDescendantOfType(ASTClassOrInterfaceBody.class);
}
}

View File

@ -5,7 +5,7 @@
package net.sourceforge.pmd.lang.java.ast;
public class ASTTypeArgument extends AbstractJavaNode {
public class ASTTypeArgument extends AbstractJavaTypeNode {
public ASTTypeArgument(int id) {
super(id);
}

View File

@ -5,7 +5,7 @@
package net.sourceforge.pmd.lang.java.ast;
public class ASTTypeBound extends AbstractJavaNode {
public class ASTTypeBound extends AbstractJavaTypeNode {
public ASTTypeBound(int id) {
super(id);
}

View File

@ -5,7 +5,7 @@
package net.sourceforge.pmd.lang.java.ast;
public class ASTTypeParameter extends AbstractJavaNode {
public class ASTTypeParameter extends AbstractJavaTypeNode {
public ASTTypeParameter(int id) {
super(id);
}

View File

@ -4,9 +4,10 @@
package net.sourceforge.pmd.lang.java.ast;
public abstract class AbstractJavaAccessTypeNode extends AbstractJavaAccessNode implements TypeNode {
import net.sourceforge.pmd.lang.java.typeresolution.typedefinition.JavaTypeDefinition;
private Class<?> type;
public abstract class AbstractJavaAccessTypeNode extends AbstractJavaAccessNode implements TypeNode {
private JavaTypeDefinition typeDefinition;
public AbstractJavaAccessTypeNode(int i) {
super(i);
@ -18,11 +19,25 @@ public abstract class AbstractJavaAccessTypeNode extends AbstractJavaAccessNode
@Override
public Class<?> getType() {
return type;
if (typeDefinition != null) {
return typeDefinition.getType();
}
return null;
}
@Override
public void setType(Class<?> type) {
this.type = type;
typeDefinition = JavaTypeDefinition.build(type);
}
@Override
public JavaTypeDefinition getTypeDefinition() {
return typeDefinition;
}
@Override
public void setTypeDefinition(JavaTypeDefinition typeDefinition) {
this.typeDefinition = typeDefinition;
}
}

View File

@ -4,15 +4,16 @@
package net.sourceforge.pmd.lang.java.ast;
import net.sourceforge.pmd.lang.java.typeresolution.typedefinition.JavaTypeDefinition;
/**
* An extension of the SimpleJavaNode which implements the TypeNode interface.
*
*
* @see AbstractJavaNode
* @see TypeNode
*/
public abstract class AbstractJavaTypeNode extends AbstractJavaNode implements TypeNode {
private Class<?> type;
private JavaTypeDefinition typeDefinition;
public AbstractJavaTypeNode(int i) {
super(i);
@ -24,11 +25,25 @@ public abstract class AbstractJavaTypeNode extends AbstractJavaNode implements T
@Override
public Class<?> getType() {
return type;
if (typeDefinition != null) {
return typeDefinition.getType();
}
return null;
}
@Override
public void setType(Class<?> type) {
this.type = type;
typeDefinition = JavaTypeDefinition.build(type);
}
@Override
public JavaTypeDefinition getTypeDefinition() {
return typeDefinition;
}
@Override
public void setTypeDefinition(JavaTypeDefinition typeDefinition) {
this.typeDefinition = typeDefinition;
}
}

View File

@ -5,6 +5,7 @@
package net.sourceforge.pmd.lang.java.ast;
import net.sourceforge.pmd.lang.ast.Node;
import net.sourceforge.pmd.lang.java.typeresolution.typedefinition.JavaTypeDefinition;
/**
* This interface allows a Java Class to be associated with a node.
@ -13,16 +14,31 @@ public interface TypeNode extends Node {
/**
* Get the Java Class associated with this node.
*
*
* @return The Java Class, may return <code>null</code>.
*/
Class<?> getType();
/**
* Get the TypeDefinition associated with this node. The Class object
* contained in the TypeDefinition will always be equal to that which
* is returned by <code>getType()</code>.
*
* @return The TypeDefinition, may return <code>null</code>
*/
JavaTypeDefinition getTypeDefinition();
/**
* Set the TypeDefinition associated with this node.
*
* @param type A TypeDefinition object
*/
void setTypeDefinition(JavaTypeDefinition type);
/**
* Set the Java Class associated with this node.
*
* @param type
* A Java Class
*
* @param type A Java Class
*/
void setType(Class<?> type);
}

View File

@ -86,7 +86,14 @@ public class UnusedImportsRule extends AbstractJavaRule {
if (s != null) {
String[] params = s.split("\\s*,\\s*");
for (String param : params) {
imports.remove(new ImportWrapper(param, param, new DummyJavaNode(-1)));
final int firstDot = param.indexOf('.');
final String expectedImportName;
if (firstDot == -1) {
expectedImportName = param;
} else {
expectedImportName = param.substring(0, firstDot);
}
imports.remove(new ImportWrapper(param, expectedImportName, new DummyJavaNode(-1)));
}
}
}

View File

@ -9,7 +9,6 @@ import java.util.List;
import java.util.Map;
import net.sourceforge.pmd.lang.ast.Node;
import net.sourceforge.pmd.lang.java.ast.ASTAnnotation;
import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration;
import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration;
import net.sourceforge.pmd.lang.java.ast.ASTMarkerAnnotation;
@ -81,7 +80,7 @@ public class JUnitTestsShouldIncludeAssertRule extends AbstractJUnitRule {
for (NameDeclaration decl : decls.keySet()) {
Node parent = decl.getNode().jjtGetParent().jjtGetParent().jjtGetParent();
if (parent.hasDescendantOfType(ASTAnnotation.class)
if (parent.hasDescendantOfType(ASTMarkerAnnotation.class)
&& parent.getFirstChildOfType(ASTFieldDeclaration.class) != null) {
String annot = parent.getFirstDescendantOfType(ASTMarkerAnnotation.class).jjtGetChild(0).getImage();
if (!"Rule".equals(annot) && !"org.junit.Rule".equals(annot)) {

View File

@ -70,23 +70,9 @@ public class InvalidSlf4jMessageFormatRule extends AbstractJavaRule {
// find the arguments
final List<ASTExpression> argumentList = parentNode.getFirstChildOfType(ASTPrimarySuffix.class)
.getFirstDescendantOfType(ASTArgumentList.class).findChildrenOfType(ASTExpression.class);
final List<ASTPrimaryExpression> params = new ArrayList<ASTPrimaryExpression>(argumentList.size());
for (final ASTExpression astExpression : argumentList) {
ASTPrimaryExpression primaryExpression = astExpression.getFirstChildOfType(ASTPrimaryExpression.class);
if (primaryExpression != null) {
params.add(primaryExpression);
}
}
if (params.isEmpty()) {
// no params we could analyze
return super.visit(node, data);
}
final ASTPrimaryExpression messageParam = params.get(0);
// remove the message parameter
params.remove(0);
final ASTPrimaryExpression messageParam = argumentList.remove(0).getFirstDescendantOfType(ASTPrimaryExpression.class);
final int expectedArguments = expectedArguments(messageParam);
if (expectedArguments == 0) {
@ -97,14 +83,14 @@ public class InvalidSlf4jMessageFormatRule extends AbstractJavaRule {
// Remove throwable param, since it is shown separately.
// But only, if it is not used as a placeholder argument
if (params.size() > expectedArguments) {
removeThrowableParam(params);
if (argumentList.size() > expectedArguments) {
removeThrowableParam(argumentList);
}
if (params.size() < expectedArguments) {
addViolationWithMessage(data, node, "Missing arguments," + getExpectedMessage(params, expectedArguments));
} else if (params.size() > expectedArguments) {
addViolationWithMessage(data, node, "Too many arguments," + getExpectedMessage(params, expectedArguments));
if (argumentList.size() < expectedArguments) {
addViolationWithMessage(data, node, "Missing arguments," + getExpectedMessage(argumentList, expectedArguments));
} else if (argumentList.size() > expectedArguments) {
addViolationWithMessage(data, node, "Too many arguments," + getExpectedMessage(argumentList, expectedArguments));
}
return super.visit(node, data);
@ -146,21 +132,20 @@ public class InvalidSlf4jMessageFormatRule extends AbstractJavaRule {
return false;
}
private void removeThrowableParam(final List<ASTPrimaryExpression> params) {
private void removeThrowableParam(final List<ASTExpression> params) {
// Throwable parameters are the last one in the list, if any.
if (params.isEmpty()) {
return;
}
int lastIndex = params.size() - 1;
ASTPrimaryExpression last = params.get(lastIndex);
ASTPrimaryExpression last = params.get(lastIndex).getFirstDescendantOfType(ASTPrimaryExpression.class);
if (isNewThrowable(last) || hasTypeThrowable(last) || isReferencingThrowable(last)) {
params.remove(lastIndex);
return;
}
}
private String getExpectedMessage(final List<ASTPrimaryExpression> params, final int expectedArguments) {
private String getExpectedMessage(final List<ASTExpression> params, final int expectedArguments) {
return " expected " + expectedArguments + (expectedArguments > 1 ? " arguments " : " argument ") + "but have "
+ params.size();
}

View File

@ -8,6 +8,7 @@ import java.util.Collections;
import java.util.List;
import net.sourceforge.pmd.lang.ast.Node;
import net.sourceforge.pmd.lang.java.ast.ASTAnnotation;
import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit;
import net.sourceforge.pmd.lang.java.ast.ASTConstructorDeclaration;
import net.sourceforge.pmd.lang.java.ast.ASTImportDeclaration;
@ -51,6 +52,15 @@ public class SignatureDeclareThrowsExceptionRule extends AbstractJavaRule {
if (methodDeclaration.getMethodName().startsWith("test")) {
return super.visit(methodDeclaration, o);
}
// Ignore overridden methods, the issue should be marked on the method definition
final List<ASTAnnotation> methodAnnotations = methodDeclaration.jjtGetParent().findChildrenOfType(ASTAnnotation.class);
for (final ASTAnnotation annotation : methodAnnotations) {
final ASTName annotationName = annotation.getFirstDescendantOfType(ASTName.class);
if (annotationName.hasImageEqualTo("Override") || annotationName.hasImageEqualTo("java.lang.Override")) {
return super.visit(methodDeclaration, o);
}
}
List<ASTName> exceptionList = Collections.emptyList();
ASTNameList nameList = methodDeclaration.getFirstChildOfType(ASTNameList.class);

View File

@ -7,6 +7,7 @@ package net.sourceforge.pmd.lang.java.typeresolution.rules;
import java.util.List;
import net.sourceforge.pmd.lang.ast.Node;
import net.sourceforge.pmd.lang.java.ast.ASTAnnotation;
import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration;
import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceType;
import net.sourceforge.pmd.lang.java.ast.ASTConstructorDeclaration;
@ -113,6 +114,15 @@ public class SignatureDeclareThrowsException extends AbstractJavaRule {
if (junitImported && isAllowedMethod(methodDeclaration)) {
return super.visit(methodDeclaration, o);
}
// Ignore overridden methods, the issue should be marked on the method definition
final List<ASTAnnotation> methodAnnotations = methodDeclaration.jjtGetParent().findChildrenOfType(ASTAnnotation.class);
for (final ASTAnnotation annotation : methodAnnotations) {
final ASTName annotationName = annotation.getFirstDescendantOfType(ASTName.class);
if (annotationName.hasImageEqualTo("Override") || annotationName.hasImageEqualTo("java.lang.Override")) {
return super.visit(methodDeclaration, o);
}
}
checkExceptions(methodDeclaration, o);

View File

@ -0,0 +1,74 @@
/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.lang.java.typeresolution.typedefinition;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class JavaTypeDefinition implements TypeDefinition {
private final Class<?> clazz;
private List<JavaTypeDefinition> genericArgs;
// contains TypeDefs where only the clazz field is used
private static Map<Class<?>, JavaTypeDefinition> onlyClassTypeDef = new HashMap<>();
public Class<?> getType() {
return clazz;
}
public List<JavaTypeDefinition> getGenericArgs() {
if (genericArgs == null) {
genericArgs = Collections.unmodifiableList(new ArrayList<JavaTypeDefinition>());
}
return genericArgs;
}
private JavaTypeDefinition(Class<?> clazz, List<JavaTypeDefinition> genericArgs) {
this.clazz = clazz;
if (genericArgs != null) {
this.genericArgs = Collections.unmodifiableList(genericArgs);
}
}
// builder part of the class
public static JavaTypeDefinition build(Class<?> clazz) {
if (onlyClassTypeDef.containsKey(clazz)) {
return onlyClassTypeDef.get(clazz);
}
JavaTypeDefinition typeDef = new JavaTypeDefinition(clazz, null);
onlyClassTypeDef.put(clazz, typeDef);
return typeDef;
}
/**
* @param genericArgs This package private method expects that the genericArgs list has not been leaked,
* meaning the other references have been discarded to ensure immutability.
*/
/* default */ static JavaTypeDefinition build(Class<?> clazz, List<JavaTypeDefinition> genericArgs) {
if (genericArgs == null) {
return build(clazz);
}
return new JavaTypeDefinition(clazz, genericArgs);
}
public static JavaTypeDefinitionBuilder builder(Class<?> clazz) {
return new JavaTypeDefinitionBuilder().setType(clazz);
}
public static JavaTypeDefinitionBuilder builder() {
return new JavaTypeDefinitionBuilder();
}
}

View File

@ -0,0 +1,39 @@
/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.lang.java.typeresolution.typedefinition;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class JavaTypeDefinitionBuilder {
private Class<?> clazz = null;
private List<JavaTypeDefinition> genericArgs = new ArrayList<>();
/* default */ JavaTypeDefinitionBuilder() {}
public JavaTypeDefinitionBuilder addTypeArg(JavaTypeDefinition arg) {
genericArgs.add(arg);
return this;
}
public List<JavaTypeDefinition> getTypeArgs() {
return Collections.unmodifiableList(genericArgs);
}
public JavaTypeDefinitionBuilder getTypeArg(int index) {
genericArgs.get(index);
return this;
}
public JavaTypeDefinitionBuilder setType(Class<?> clazz) {
this.clazz = clazz;
return this;
}
public JavaTypeDefinition build() {
return JavaTypeDefinition.build(clazz, genericArgs);
}
}

View File

@ -0,0 +1,23 @@
/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.lang.java.typeresolution.typedefinition;
import java.util.List;
public interface TypeDefinition {
/**
* Get the raw Class type of the definition.
*
* @return Raw Class type.
*/
Class<?> getType();
/**
* Get the list of type arguments for this TypeDefinition.
*
* @return An ordered and immutable list of type arguments.
*/
List<? extends TypeDefinition> getGenericArgs();
}

View File

@ -148,7 +148,8 @@ public class Foo {
since="1.03"
message = "The {0} ''{1}'' has a Cyclomatic Complexity of {2}."
class="net.sourceforge.pmd.lang.java.rule.codesize.CyclomaticComplexityRule"
externalInfoUrl="${pmd.website.baseurl}/rules/java/codesize.html#CyclomaticComplexity">
externalInfoUrl="${pmd.website.baseurl}/rules/java/codesize.html#CyclomaticComplexity"
deprecated="true">
<description>
<![CDATA[
Complexity directly affects maintenance costs is determined by the number of decision points in a method
@ -204,7 +205,8 @@ public class Foo { // This has a Cyclomatic Complexity = 12
since="5.1.2"
message = "The {0} ''{1}'' has a Standard Cyclomatic Complexity of {2}."
class="net.sourceforge.pmd.lang.java.rule.codesize.StdCyclomaticComplexityRule"
externalInfoUrl="${pmd.website.baseurl}/rules/java/codesize.html#StdCyclomaticComplexity">
externalInfoUrl="${pmd.website.baseurl}/rules/java/codesize.html#StdCyclomaticComplexity"
deprecated="true">
<description>
<![CDATA[
Complexity directly affects maintenance costs is determined by the number of decision points in a method
@ -260,7 +262,8 @@ public class Foo { // This has a Cyclomatic Complexity = 12
since="5.1.2"
message = "The {0} ''{1}'' has a Modified Cyclomatic Complexity of {2}."
class="net.sourceforge.pmd.lang.java.rule.codesize.ModifiedCyclomaticComplexityRule"
externalInfoUrl="${pmd.website.baseurl}/rules/java/codesize.html#ModifiedCyclomaticComplexity">
externalInfoUrl="${pmd.website.baseurl}/rules/java/codesize.html#ModifiedCyclomaticComplexity"
deprecated="true">
<description>
<![CDATA[
Complexity directly affects maintenance costs is determined by the number of decision points in a method

View File

@ -30,10 +30,12 @@ or reported.
[FormalParameter/Type/ReferenceType
/ClassOrInterfaceType[@Image != 'InterruptedException' and @Image != 'CloneNotSupportedException']
]
[FormalParameter/VariableDeclaratorId[not(matches(@Image, $allowExceptionNameRegex))]]
]]>
</value>
</property>
<property name="allowCommentedBlocks" type="Boolean" description="Empty blocks containing comments will be skipped" value="false"/>
<property name="allowExceptionNameRegex" type="String" description="Empty blocks catching exceptions with names matching this regular expression will be skipped" value="^$"/>
</properties>
<example>
<![CDATA[
@ -129,7 +131,7 @@ Avoid empty try blocks - what's the point?
<property name="xpath">
<value>
<![CDATA[
//TryStatement/Block[1][count(*) = 0]
//TryStatement[not(ResourceSpecification)]/Block[1][count(*) = 0]
]]>
</value>
</property>

View File

@ -12,10 +12,13 @@ import net.sourceforge.pmd.typeresolution.testdata.dummytypes.SuperClassA;
/*
* Note: inherited fields of a nested class shadow outer scope variables
* Note: only if they are accessible!
*
* TODO: test static field access, array types, anonymous class (super type access)
*/
public class FieldAccess extends SuperClassA {
public int field;
public FieldAccess f;
public static FieldAccess staticF;
public void foo(FieldAccess param) {
FieldAccess local = null;

View File

@ -0,0 +1,32 @@
/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.typeresolution.testdata;
import net.sourceforge.pmd.typeresolution.testdata.dummytypes.GenericClass;
import net.sourceforge.pmd.typeresolution.testdata.dummytypes.GenericSuperClassA;
public class FieldAccessGenericBounds extends GenericSuperClassA<Long> {
GenericClass<? super String, ?> superGeneric;
GenericClass<? extends Number, Object> upperBound;
public void astPrimaryNameCases() {
// test ?, ? super Something, ? extends Something
// Primary[Prefix[Name[superGeneric.first]]]
superGeneric.first = ""; // Object
superGeneric.second = null; // Object
inheritedSuperGeneric.first = ""; // Object
inheritedSuperGeneric.second = null; // Object
upperBound.first = null; // Number
inheritedUpperBound.first = null; // String
// test static imports
// Primary[Prefix[Name[instanceFields.generic.first]]]
//instanceFields.generic.first = "";
//staticGeneric.first = new Long(0);
}
}

View File

@ -0,0 +1,35 @@
/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.typeresolution.testdata;
import net.sourceforge.pmd.typeresolution.testdata.dummytypes.GenericClass;
public class FieldAccessGenericParameter<T extends GenericClass<String, GenericClass<String, Integer>>,
S extends Double> {
T parameterGeneric;
S classGeneric;
<M extends Character> void foo() {
M localGeneric = null;
// access type dependant on class/method type arguments
// Primary[Prefix[Name[classGeneric]]]
classGeneric = null; // Double
localGeneric = null; // Character
// test type parameters extending generic types
// Primary[Prefix[Name[parameterGeneric.first]]]
parameterGeneric.second.second = new Integer(0);
}
<C extends Number> FieldAccessGenericParameter() {
C constructorGeneric = null;
// access type dependant on constructor type arugments
// Primary[Prefix[Name[localGeneric]]]
constructorGeneric = null; // Number
}
}

View File

@ -0,0 +1,37 @@
/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.typeresolution.testdata;
import net.sourceforge.pmd.typeresolution.testdata.dummytypes.GenericClass2;
import net.sourceforge.pmd.typeresolution.testdata.dummytypes.GenericSuperClassA;
public class FieldAccessGenericRaw<T extends GenericClass2> extends GenericSuperClassA<Long> {
GenericClass2 rawGeneric;
T parameterRawGeneric;
void foo() {
// test raw types
// Primary[Prefix[Name[rawGeneric.first]]]
rawGeneric.first = new Integer(0);
rawGeneric.second = new Integer(0);
rawGeneric.third = new Object();
rawGeneric.fourth.second = "";
rawGeneric.rawGeneric.second = new Integer(0);
// Primary[Prefix[Name[inheritedGeneric.first]]]
inheritedRawGeneric.first = new Integer(0);
inheritedRawGeneric.second = new Integer(0);
inheritedRawGeneric.third = new Object();
inheritedRawGeneric.fourth.second = "";
inheritedRawGeneric.rawGeneric.second = new Integer(0);
// Primary[Prefix[Name[parameterRawGeneric.first]]]
parameterRawGeneric.first = new Integer(0);
parameterRawGeneric.second = new Integer(0);
parameterRawGeneric.third = new Object();
parameterRawGeneric.fourth.second = "";
parameterRawGeneric.rawGeneric.second = new Integer(0);
}
}

View File

@ -0,0 +1,60 @@
/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.typeresolution.testdata;
import net.sourceforge.pmd.typeresolution.testdata.dummytypes.GenericClass;
import net.sourceforge.pmd.typeresolution.testdata.dummytypes.GenericSuperClassA;
/*
* TODO: add anonymous class this (Allocation expression)
* TODO: add primitives, parameterized arrays
* TODO: diamond, type parmeter declarations can shadow Class declarations
*/
public class FieldAccessGenericSimple extends GenericSuperClassA<Long> {
GenericClass<String, Double> genericField;
GenericClass<String, GenericClass<Number, Double>> genericTypeArg;
FieldAccessGenericSimple fieldAcc;
void foo(GenericClass<Integer, Character> param) {
GenericClass<Float, Long> local = null;
// access a generic field through member field
// Primary[Prefix[Name[genericField.first]]]
genericField.first = "";
genericField.second = new Double(0);
// access a generic field whose type depends on a generic type argument
// Primary[Prefix[Name[genericTypeArg.second.second]]]
genericTypeArg.second.second = new Double(0);
// access a generic field through a local or a parameter
// Primary[Prefix[Name[param.first]]]
param.first = new Integer(0);
local.second = new Long(0);
// access a generic field whose type depends on indirect type arguments
// Primary[Prefix[Name[generic.generic.first]]]
param.generic.first = new Character('c');
local.generic.second = new Float(0);
genericField.generic.generic.generic.first = new Double(0);
// test inherited generic
// Primary[Prefix[Name[generic.first]]]
fieldA = new Long(0);
fieldB.generic.second = "";
// test inherited generic
// Primary[Prefix[Name[fieldAcc.fieldA]]]
fieldAcc.fieldA = new Long(0);
}
public class Nested extends GenericSuperClassA<Long> {
void foo() {
fieldA = new Long(0);
}
}
}

View File

@ -29,6 +29,7 @@ public class FieldAccessNested {
a = new SuperClassA();
net.sourceforge.pmd.typeresolution.testdata.FieldAccessNested.Nested.this.a = new SuperClassA();
FieldAccessNested.Nested.this.a = new SuperClassA();
}
}
}

View File

@ -0,0 +1,49 @@
/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.typeresolution.testdata;
import net.sourceforge.pmd.typeresolution.testdata.dummytypes.GenericClass;
import net.sourceforge.pmd.typeresolution.testdata.dummytypes.GenericSuperClassA;
public class FieldAccessPrimaryGenericSimple extends GenericSuperClassA<Long> {
GenericClass<String, Double> genericField;
GenericClass<String, GenericClass<Number, Double>> genericTypeArg;
void foo(GenericClass<Integer, Character> param) {
GenericClass<Float, Long> local = null;
// access a generic field through member field
// Primary[Prefix[this], Suffix[genericField], Suffix[first]]
this.genericField.first = "";
(this).genericField.second = new Double(0);
// access a generic field whose type depends on a generic type argument
// Primary[Prefix[this], Suffix[genericTypeArg], Suffix[second], Suffix[second]]
this.genericTypeArg.second.second = new Double(0);
// access a generic field whose type depends on indirect type arguments
// Primary[Prefix[this], Suffix[genericField], Suffix[generic], Suffix[generic]...]
(this).genericField.generic.generic.generic.first = new Double(0);
// test inherited generic
// Primary[Primary[Prefix[(this)]], Suffix[fieldA]]
(this).fieldA = new Long(0);
this.fieldB.generic.second = "";
// test inherited generic
// Primary[Prefix[super], Suffix[fieldA]]
super.fieldA = new Long(0);
super.fieldB.generic.second = "";
}
class Nested<T extends GenericClass<String, Number>> {
T field;
void foo() {
// Primary[Prefix[this], Suffix[field], Suffix[first]]
this.field.first = "";
}
}
}

View File

@ -16,13 +16,8 @@ import net.sourceforge.pmd.typeresolution.testdata.dummytypes.SuperClassB2;
*/
public class FieldAccessShadow {
Integer field;
String s2;
public void foo() {
String field;

View File

@ -5,6 +5,8 @@
package net.sourceforge.pmd.typeresolution.testdata.dummytypes;
public class GenericClass<T> {
public T a;
public class GenericClass<T, S> {
public T first;
public S second;
public GenericClass<S, T> generic;
}

View File

@ -0,0 +1,19 @@
/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.typeresolution.testdata.dummytypes;
public class GenericClass2<A extends Integer, B extends A, C,
S extends String,
D extends GenericClass<A, S>,
//, E extends GenericClass<E, E>,
F extends GenericClass2> {
public A first;
public B second;
public C third;
public D fourth;
//public E fifth; // recursion
public F sixth; // recursion
public GenericClass2 rawGeneric;
}

View File

@ -0,0 +1,12 @@
/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.typeresolution.testdata.dummytypes;
public class GenericSuperClassA<T> extends GenericSuperClassB<T, GenericClass<String, T>> {
public T fieldA;
public GenericClass2 inheritedRawGeneric;
public GenericClass<? super String, ?> inheritedSuperGeneric;
public GenericClass<? extends String, Object> inheritedUpperBound;
}

Some files were not shown because too many files have changed in this diff Show More