/*******************************************************************************
* Copyright (c) 2005, 2015 Zend Technologies and others.
* 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
*
* Contributors:
* Zend Technologies - initial API and implementation
*******************************************************************************/
package org.eclipse.php.refactoring.core;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.eclipse.php.core.ast.nodes.*;
import org.eclipse.php.core.ast.visitor.AbstractVisitor;
import org.eclipse.php.internal.core.ast.locator.PHPElementConciliator;
import org.eclipse.php.internal.core.search.IOccurrencesFinder;
import org.eclipse.php.internal.core.search.IOccurrencesFinder.OccurrenceLocation;
import org.eclipse.php.internal.core.search.OccurrencesFinderFactory;
/**
* Find all nodes connected to a given binding or node. e.g. Declaration of a
* field and all references. For types this includes also the constructor
* declaration, for methods also overridden methods or methods overriding (if
* existing in the same AST), for constructors also the type and all other
* constructors.
*/
public class LinkedNodeFinder {
private LinkedNodeFinder() {
}
/**
* Find all nodes connected to the given name node. If the node has a
* binding then all nodes connected to this binding are returned. If the
* node has no binding, then all nodes that also miss a binding and have the
* same name are returned.
*
* @param root
* The root of the AST tree to search
* @param name
* The node to find linked nodes for
* @return Return
*/
public static OccurrenceLocation[] findByNode(Program root, ASTNode node) {
ASTNode selectedNode = node;
if (selectedNode != null && selectedNode.getType() == ASTNode.VARIABLE) {
final Expression name = ((Variable) selectedNode).getName();
if (name instanceof Identifier) {
selectedNode = name;
}
}
OccurrenceLocation[] locations = null;
int type = PHPElementConciliator.concile(selectedNode);
IOccurrencesFinder finder = OccurrencesFinderFactory
.getOccurrencesFinder(type);
if (finder != null) {
if (finder.initialize(root, selectedNode) == null) {
locations = finder.getOccurrences();
}
}
return locations;
}
/**
* Find all nodes connected to the given name node. If the node has a
* binding then all nodes connected to this binding are returned. If the
* node has no binding, then all nodes that also miss a binding and have the
* same name are returned.
*
* @param root
* The root of the AST tree to search
* @param name
* The node to find linked nodes for
* @return Return
*/
public static OccurrenceLocation[] findByNode(Program root, ASTNode[] nodes) {
List<OccurrenceLocation> locationList = new ArrayList<OccurrenceLocation>();
for (ASTNode selectedNode : nodes) {
OccurrenceLocation[] locations = findByNode(root, selectedNode);
if (locations != null) {
locationList.addAll(Arrays.asList(locations));
}
}
return locationList
.toArray(new OccurrenceLocation[locationList.size()]);
}
public static Identifier[] findByBinding(ASTNode root,
IVariableBinding binding) {
ArrayList<Identifier> res = new ArrayList<Identifier>();
BindingFinder nodeFinder = new BindingFinder(binding, res);
root.accept(nodeFinder);
return res.toArray(new Identifier[res.size()]);
}
private static class BindingFinder extends AbstractVisitor {
private IBinding fBinding;
private ArrayList<Identifier> fResult;
public BindingFinder(IBinding binding, ArrayList<Identifier> result) {
fBinding = binding;
fResult = result;
}
public boolean visit(Identifier node) {
IBinding binding = node.resolveBinding();
if (binding == null) {
return false;
}
if (fBinding.equals(binding)) {
fResult.add(node);
} else if (binding.getKind() != fBinding.getKind()) {
return false;
} else if (binding.getKind() == IBinding.METHOD) {
IMethodBinding curr = (IMethodBinding) binding;
IMethodBinding methodBinding = (IMethodBinding) fBinding;
if (methodBinding.overrides(curr)
|| curr.overrides(methodBinding)) {
fResult.add(node);
}
}
return false;
}
// private static IBinding getDeclaration(IBinding binding) {
// if (binding instanceof ITypeBinding) {
// return ((ITypeBinding) binding).getTypeDeclaration();
// } else if (binding instanceof IMethodBinding) {
// IMethodBinding methodBinding = (IMethodBinding) binding;
// if (methodBinding.isConstructor()) { // link all constructors with
// their type
// return methodBinding.getDeclaringClass().getTypeDeclaration();
// } else {
// return methodBinding.getMethodDeclaration();
// }
// } else if (binding instanceof IVariableBinding) {
// return ((IVariableBinding) binding).getVariableDeclaration();
// }
// return binding;
// }
}
}