use of net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration in project pmd by pmd.
the class ClassTypeResolver method visit.
@Override
public Object visit(ASTPrimaryExpression primaryNode, Object data) {
// visit method arguments in reverse
for (int i = primaryNode.jjtGetNumChildren() - 1; i >= 0; --i) {
((JavaNode) primaryNode.jjtGetChild(i)).jjtAccept(this, data);
}
JavaTypeDefinition primaryNodeType = null;
AbstractJavaTypeNode previousChild = null;
AbstractJavaTypeNode nextChild;
Class<?> accessingClass = getEnclosingTypeDeclarationClass(primaryNode);
for (int childIndex = 0; childIndex < primaryNode.jjtGetNumChildren(); ++childIndex) {
AbstractJavaTypeNode currentChild = (AbstractJavaTypeNode) primaryNode.jjtGetChild(childIndex);
nextChild = childIndex + 1 < primaryNode.jjtGetNumChildren() ? (AbstractJavaTypeNode) primaryNode.jjtGetChild(childIndex + 1) : null;
// 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.setTypeDefinition(previousChild.getTypeDefinition());
} else {
// simple 'this' expression
ASTClassOrInterfaceDeclaration typeDeclaration = currentChild.getFirstParentOfType(ASTClassOrInterfaceDeclaration.class);
if (typeDeclaration != null) {
currentChild.setTypeDefinition(typeDeclaration.getTypeDefinition());
}
}
// 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
// anonymous classes can't have qualified super expression, thus
// getSuperClassTypeDefinition's second argumet isn't null, but we are not
// looking for enclosing super types
currentChild.setTypeDefinition(getSuperClassTypeDefinition(currentChild, previousChild.getType()));
} else {
// simple 'super' expression
currentChild.setTypeDefinition(getSuperClassTypeDefinition(currentChild, null));
}
} else if (currentChild.getFirstChildOfType(ASTArguments.class) != null) {
currentChild.setTypeDefinition(previousChild.getTypeDefinition());
} else if (previousChild != null && previousChild.getType() != null) {
String currentChildImage = currentChild.getImage();
if (currentChildImage == null) {
// this.<Something>foo(); <Something>foo would be in a Suffix and would have a null image
currentChildImage = currentChild.jjtGetLastToken().toString();
}
ASTArguments astArguments = nextChild != null ? nextChild.getFirstChildOfType(ASTArguments.class) : null;
if (astArguments != null) {
// method
ASTArgumentList astArgumentList = getArgumentList(astArguments);
int methodArgsArity = getArgumentListArity(astArgumentList);
List<JavaTypeDefinition> typeArguments = getMethodExplicitTypeArugments(currentChild);
List<MethodType> methods = getApplicableMethods(previousChild.getTypeDefinition(), currentChildImage, typeArguments, methodArgsArity, accessingClass);
currentChild.setTypeDefinition(getBestMethodReturnType(previousChild.getTypeDefinition(), methods, astArgumentList));
} else {
// field
currentChild.setTypeDefinition(getFieldType(previousChild.getTypeDefinition(), currentChildImage, accessingClass));
}
}
}
if (currentChild.getType() != null) {
primaryNodeType = currentChild.getTypeDefinition();
} else {
// avoid falsely passing tests
primaryNodeType = null;
break;
}
previousChild = currentChild;
}
primaryNode.setTypeDefinition(primaryNodeType);
return data;
}
use of net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration in project pmd by pmd.
the class ClassTypeResolver method visit.
@Override
public Object visit(ASTTypeParameters node, Object data) {
super.visit(node, data);
if (node.jjtGetParent() instanceof ASTClassOrInterfaceDeclaration) {
TypeNode parent = (TypeNode) node.jjtGetParent();
final JavaTypeDefinition[] boundGenerics = new JavaTypeDefinition[node.jjtGetNumChildren()];
for (int i = 0; i < node.jjtGetNumChildren(); ++i) {
boundGenerics[i] = ((TypeNode) node.jjtGetChild(i)).getTypeDefinition();
}
parent.setTypeDefinition(JavaTypeDefinition.forClass(parent.getType(), boundGenerics));
}
return data;
}
use of net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration in project pmd by pmd.
the class ClassScope method determineSuper.
private SimpleTypedNameDeclaration determineSuper(Node declaringNode) {
SimpleTypedNameDeclaration result = null;
if (declaringNode instanceof ASTClassOrInterfaceDeclaration) {
ASTClassOrInterfaceDeclaration classDeclaration = (ASTClassOrInterfaceDeclaration) declaringNode;
ASTImplementsList implementsList = classDeclaration.getFirstChildOfType(ASTImplementsList.class);
if (implementsList != null) {
List<ASTClassOrInterfaceType> types = implementsList.findChildrenOfType(ASTClassOrInterfaceType.class);
SimpleTypedNameDeclaration type = convertToSimpleType(types);
result = type;
}
ASTExtendsList extendsList = classDeclaration.getFirstChildOfType(ASTExtendsList.class);
if (extendsList != null) {
List<ASTClassOrInterfaceType> types = extendsList.findChildrenOfType(ASTClassOrInterfaceType.class);
SimpleTypedNameDeclaration type = convertToSimpleType(types);
if (result == null) {
result = type;
} else {
result.addNext(type);
}
}
}
return result;
}
use of net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration in project pmd by pmd.
the class SingularFieldRule method visit.
@SuppressWarnings("PMD.CompareObjectsWithEquals")
@Override
public Object visit(ASTFieldDeclaration node, Object data) {
boolean checkInnerClasses = getProperty(CHECK_INNER_CLASSES);
boolean disallowNotAssignment = getProperty(DISALLOW_NOT_ASSIGNMENT);
if (node.isPrivate() && !node.isStatic() && !hasClassLombokAnnotation() && !hasLombokAnnotation(node)) {
for (ASTVariableDeclarator declarator : node.findChildrenOfType(ASTVariableDeclarator.class)) {
ASTVariableDeclaratorId declaration = (ASTVariableDeclaratorId) declarator.jjtGetChild(0);
List<NameOccurrence> usages = declaration.getUsages();
Node decl = null;
boolean violation = true;
for (int ix = 0; ix < usages.size(); ix++) {
NameOccurrence no = usages.get(ix);
Node location = no.getLocation();
ASTPrimaryExpression primaryExpressionParent = location.getFirstParentOfType(ASTPrimaryExpression.class);
if (ix == 0 && !disallowNotAssignment) {
if (primaryExpressionParent.getFirstParentOfType(ASTIfStatement.class) != null) {
// the first usage is in an if, so it may be skipped
// on
// later calls to the method. So this might be legit
// code
// that simply stores an object for later use.
violation = false;
// Optimization
break;
}
// Is the first usage in an assignment?
Node potentialStatement = primaryExpressionParent.jjtGetParent();
// Check that the assignment is not to a field inside
// the field object
boolean assignmentToField = no.getImage().equals(location.getImage());
if (!assignmentToField || !isInAssignment(potentialStatement)) {
violation = false;
// Optimization
break;
} else {
if (usages.size() > ix + 1) {
Node secondUsageLocation = usages.get(ix + 1).getLocation();
List<ASTStatementExpression> parentStatements = secondUsageLocation.getParentsOfType(ASTStatementExpression.class);
for (ASTStatementExpression statementExpression : parentStatements) {
if (statementExpression != null && statementExpression.equals(potentialStatement)) {
// The second usage is in the assignment
// of the first usage, which is allowed
violation = false;
// Optimization
break;
}
}
}
}
}
if (!checkInnerClasses) {
// Skip inner classes because the field can be used in
// the outer class and checking this is too difficult
ASTClassOrInterfaceDeclaration clazz = location.getFirstParentOfType(ASTClassOrInterfaceDeclaration.class);
if (clazz != null && clazz.getFirstParentOfType(ASTClassOrInterfaceDeclaration.class) != null) {
violation = false;
// Optimization
break;
}
}
if (primaryExpressionParent.jjtGetParent() instanceof ASTSynchronizedStatement) {
// This usage is directly in an expression of a
// synchronized block
violation = false;
// Optimization
break;
}
if (location.getFirstParentOfType(ASTLambdaExpression.class) != null) {
// This usage is inside a lambda expression
violation = false;
// Optimization
break;
}
Node method = location.getFirstParentOfType(ASTMethodDeclaration.class);
if (method == null) {
method = location.getFirstParentOfType(ASTConstructorDeclaration.class);
if (method == null) {
method = location.getFirstParentOfType(ASTInitializer.class);
if (method == null) {
continue;
}
}
}
if (decl == null) {
decl = method;
continue;
} else if (decl != method && // handle inner classes
decl.getFirstParentOfType(ASTClassOrInterfaceDeclaration.class) == method.getFirstParentOfType(ASTClassOrInterfaceDeclaration.class)) {
violation = false;
// Optimization
break;
}
}
if (violation && !usages.isEmpty()) {
addViolation(data, node, new Object[] { declaration.getImage() });
}
}
}
return data;
}
use of net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration in project pmd by pmd.
the class UseUtilityClassRule method visit.
@Override
public Object visit(ASTClassOrInterfaceBody decl, Object data) {
if (decl.jjtGetParent() instanceof ASTClassOrInterfaceDeclaration) {
ASTClassOrInterfaceDeclaration parent = (ASTClassOrInterfaceDeclaration) decl.jjtGetParent();
if (parent.isAbstract() || parent.isInterface() || isExceptionType(parent)) {
return super.visit(decl, data);
}
if (isOkUsingLombok(parent)) {
return super.visit(decl, data);
}
int i = decl.jjtGetNumChildren();
int methodCount = 0;
boolean isOK = false;
while (i > 0) {
Node p = decl.jjtGetChild(--i);
if (p.jjtGetNumChildren() == 0) {
continue;
}
Node n = skipAnnotations(p);
if (n instanceof ASTFieldDeclaration) {
if (!((ASTFieldDeclaration) n).isStatic()) {
isOK = true;
break;
}
} else if (n instanceof ASTConstructorDeclaration) {
if (((ASTConstructorDeclaration) n).isPrivate()) {
isOK = true;
break;
}
} else if (n instanceof ASTMethodDeclaration) {
ASTMethodDeclaration m = (ASTMethodDeclaration) n;
if (!m.isPrivate()) {
methodCount++;
}
if (!m.isStatic()) {
isOK = true;
break;
}
// TODO use symbol table
if (m.getMethodName().equals("suite")) {
ASTResultType res = m.getResultType();
ASTClassOrInterfaceType c = res.getFirstDescendantOfType(ASTClassOrInterfaceType.class);
if (c != null && c.hasImageEqualTo("Test")) {
isOK = true;
break;
}
}
}
}
if (!isOK && methodCount > 0) {
addViolation(data, decl);
}
}
return super.visit(decl, data);
}
Aggregations