Merge branch 'node-api'

This commit is contained in:
Clément Fournier
2020-01-19 13:05:32 +01:00
6 changed files with 34 additions and 28 deletions

View File

@ -357,13 +357,18 @@ public abstract class AbstractNode implements Node {
return list;
}
// TODO : Add to Node interface in 7.0.0
@Override
public <T> List<T> findDescendantsOfType(final Class<T> targetType, final boolean crossBoundaries) {
final List<T> list = new ArrayList<>();
findDescendantsOfType(this, targetType, list, crossBoundaries);
return list;
}
/**
* @deprecated Use {@link #findDescendantsOfType(Class, boolean)} instead, which
* returns a result list.
*/
@Deprecated
@Override
public <T> void findDescendantsOfType(final Class<T> targetType, final List<T> results,
final boolean crossBoundaries) {
@ -373,8 +378,7 @@ public abstract class AbstractNode implements Node {
private static <T> void findDescendantsOfType(final Node node, final Class<T> targetType, final List<T> results,
final boolean crossFindBoundaries) {
for (int i = 0; i < node.getNumChildren(); i++) {
final Node child = node.getChild(i);
for (Node child : node.children()) {
if (targetType.isAssignableFrom(child.getClass())) {
results.add(targetType.cast(child));
}
@ -388,8 +392,7 @@ public abstract class AbstractNode implements Node {
@Override
public <T> List<T> findChildrenOfType(final Class<T> targetType) {
final List<T> list = new ArrayList<>();
for (int i = 0; i < getNumChildren(); i++) {
final Node child = getChild(i);
for (Node child : children()) {
if (targetType.isInstance(child)) {
list.add(targetType.cast(child));
}
@ -443,9 +446,7 @@ public abstract class AbstractNode implements Node {
@Override
public <T> T getFirstChildOfType(final Class<T> childType) {
int n = getNumChildren();
for (int i = 0; i < n; i++) {
final Node child = getChild(i);
for (Node child : children()) {
if (childType.isInstance(child)) {
return childType.cast(child);
}
@ -454,9 +455,7 @@ public abstract class AbstractNode implements Node {
}
private static <T> T getFirstDescendantOfType(final Class<T> descendantType, final Node node) {
final int n = node.getNumChildren();
for (int i = 0; i < n; i++) {
final Node n1 = node.getChild(i);
for (Node n1 : node.children()) {
if (descendantType.isAssignableFrom(n1.getClass())) {
return descendantType.cast(n1);
}

View File

@ -295,9 +295,25 @@ public interface Node {
* @param crossFindBoundaries
* if <code>false</code>, recursion stops for nodes for which
* {@link #isFindBoundary()} is <code>true</code>
* @deprecated Use {@link #findDescendantsOfType(Class, boolean)} instead, which
* returns a result list.
*/
@Deprecated
<T> void findDescendantsOfType(Class<T> targetType, List<T> results, boolean crossFindBoundaries);
/**
* Traverses down the tree to find all the descendant instances of type
* descendantType.
*
* @param targetType
* class which you want to find.
* @param crossFindBoundaries
* if <code>false</code>, recursion stops for nodes for which
* {@link #isFindBoundary()} is <code>true</code>
* @return List of all matching descendants
*/
<T> List<T> findDescendantsOfType(Class<T> targetType, boolean crossFindBoundaries);
/**
* Traverses the children to find the first instance of type childType.
*

View File

@ -8,7 +8,6 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
import java.util.List;
import org.junit.Before;
@ -63,8 +62,7 @@ public class AbstractNodeTransversalTest {
public void testSearchIgnoringBoundary() {
addChild(rootNode, addChild(newDummyNode(true), newDummyNode(false)));
List<DummyNode> descendantsOfType = new ArrayList<>();
rootNode.findDescendantsOfType(DummyNode.class, descendantsOfType, true);
List<DummyNode> descendantsOfType = rootNode.findDescendantsOfType(DummyNode.class, true);
assertEquals(2, descendantsOfType.size());
assertTrue(descendantsOfType.get(0).isFindBoundary());
assertFalse(descendantsOfType.get(1).isFindBoundary());

View File

@ -4,7 +4,6 @@
package net.sourceforge.pmd.lang.java.rule.bestpractices;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@ -140,9 +139,7 @@ public class PreserveStackTraceRule extends AbstractJavaRule {
private boolean checkForTargetUsage(String target, Node baseNode) {
boolean match = false;
if (target != null && baseNode != null) {
// TODO : use Node.findDescendantsOfType(ASTName.class, true) on 7.0.0
List<ASTName> nameNodes = new ArrayList<>();
baseNode.findDescendantsOfType(ASTName.class, nameNodes, true);
List<ASTName> nameNodes = baseNode.findDescendantsOfType(ASTName.class, true);
for (ASTName nameNode : nameNodes) {
if (target.equals(nameNode.getImage())) {
boolean isPartOfStringConcatenation = isStringConcat(nameNode, baseNode);

View File

@ -387,8 +387,7 @@ public class CloseResourceRule extends AbstractJavaRule {
break;
}
List<ASTStatementExpression> exprs = new ArrayList<>();
finallyBody.findDescendantsOfType(ASTStatementExpression.class, exprs, true);
List<ASTStatementExpression> exprs = finallyBody.findDescendantsOfType(ASTStatementExpression.class, true);
for (ASTStatementExpression stmt : exprs) {
ASTPrimaryExpression expr = stmt.getFirstChildOfType(ASTPrimaryExpression.class);
if (expr != null) {
@ -430,8 +429,7 @@ public class CloseResourceRule extends AbstractJavaRule {
// in the other class since there is no way to
// really check it.
if (!closed) {
List<ASTPrimarySuffix> suffixes = new ArrayList<>();
expr.findDescendantsOfType(ASTPrimarySuffix.class, suffixes, true);
List<ASTPrimarySuffix> suffixes = expr.findDescendantsOfType(ASTPrimarySuffix.class, true);
for (ASTPrimarySuffix oSuffix : suffixes) {
String suff = oSuffix.getImage();
if (closeTargets.contains(suff)) {
@ -465,8 +463,7 @@ public class CloseResourceRule extends AbstractJavaRule {
// See if the variable is returned by the method, which means the
// method is a utility for creating the db resource, which means of
// course it can't be closed by the method, so it isn't an error.
List<ASTReturnStatement> returns = new ArrayList<>();
top.findDescendantsOfType(ASTReturnStatement.class, returns, true);
List<ASTReturnStatement> returns = top.findDescendantsOfType(ASTReturnStatement.class, true);
for (ASTReturnStatement returnStatement : returns) {
ASTName name = returnStatement.getFirstDescendantOfType(ASTName.class);
if (name != null && name.getImage().equals(variableToClose)) {
@ -491,8 +488,7 @@ public class CloseResourceRule extends AbstractJavaRule {
}
private boolean variableIsPassedToMethod(ASTPrimaryExpression expr, String variable) {
List<ASTName> methodParams = new ArrayList<>();
expr.findDescendantsOfType(ASTName.class, methodParams, true);
List<ASTName> methodParams = expr.findDescendantsOfType(ASTName.class, true);
for (ASTName pName : methodParams) {
String paramName = pName.getImage();
// also check if we've got the a parameter (i.e if it's an argument

View File

@ -949,8 +949,8 @@ public final class ConstructorCallsOverridableMethodRule extends AbstractJavaRul
* Adds all methods called on this instance from within this Node.
*/
private static void addCalledMethodsOfNode(Node node, List<MethodInvocation> calledMethods, String className) {
List<ASTPrimaryExpression> expressions = new ArrayList<>();
node.findDescendantsOfType(ASTPrimaryExpression.class, expressions, !(node instanceof AccessNode));
List<ASTPrimaryExpression> expressions = node.findDescendantsOfType(ASTPrimaryExpression.class,
!(node instanceof AccessNode));
addCalledMethodsOfNodeImpl(expressions, calledMethods, className);
}