// ===================================================================== // // Copyright (C) 2012 - 2016, Philip Graf // // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // which accompanies this distribution, and is available at // http://www.eclipse.org/legal/epl-v10.html // // ===================================================================== package ch.acanda.eclipse.pmd.java.resolution; import org.eclipse.jdt.core.dom.ASTNode; import org.eclipse.jdt.core.dom.ASTVisitor; import org.eclipse.jface.text.Position; import com.google.common.base.Optional; /** * Searches an AST for a node that has the provided type and includes the provided position. If more than one node fit * the criteria, the one with the largest distance to the root is returned. */ class PositionWithinNodeNodeFinder<R extends ASTNode, N extends ASTNode> extends ASTVisitor implements NodeFinder<R, N> { private final int start; private final int end; private final Class<? extends N>[] nodeTypes; private N node; @SafeVarargs public PositionWithinNodeNodeFinder(final Position position, final Class<? extends N>... nodeTypes) { start = position.getOffset(); end = start + position.getLength(); this.nodeTypes = nodeTypes; } @Override public boolean preVisit2(final ASTNode node) { final int nodeStart = node.getStartPosition(); final int nodeEnd = nodeStart + node.getLength(); if (nodeStart <= start && end <= nodeEnd) { for (final Class<? extends N> nodeType : nodeTypes) { if (nodeType.isAssignableFrom(node.getClass())) { this.node = nodeType.cast(node); break; } } return true; } return false; } @Override public Optional<N> findNode(final R ast) { node = null; ast.accept(this); return Optional.fromNullable(node); } }