blob: 3f11a94b2b27ac9fb0761137d34e241109f547fc [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2008 IBM Corporation 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:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.wst.jsdt.internal.corext.refactoring.structure;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.runtime.Assert;
import org.eclipse.wst.jsdt.core.IField;
import org.eclipse.wst.jsdt.core.IFunction;
import org.eclipse.wst.jsdt.core.IImportContainer;
import org.eclipse.wst.jsdt.core.IImportDeclaration;
import org.eclipse.wst.jsdt.core.IInitializer;
import org.eclipse.wst.jsdt.core.IJavaScriptElement;
import org.eclipse.wst.jsdt.core.IMember;
import org.eclipse.wst.jsdt.core.IPackageDeclaration;
import org.eclipse.wst.jsdt.core.ISourceRange;
import org.eclipse.wst.jsdt.core.IType;
import org.eclipse.wst.jsdt.core.JavaScriptModelException;
import org.eclipse.wst.jsdt.core.dom.ASTNode;
import org.eclipse.wst.jsdt.core.dom.AbstractTypeDeclaration;
import org.eclipse.wst.jsdt.core.dom.Block;
import org.eclipse.wst.jsdt.core.dom.BodyDeclaration;
import org.eclipse.wst.jsdt.core.dom.ClassInstanceCreation;
import org.eclipse.wst.jsdt.core.dom.ConstructorInvocation;
import org.eclipse.wst.jsdt.core.dom.FieldDeclaration;
import org.eclipse.wst.jsdt.core.dom.FunctionDeclaration;
import org.eclipse.wst.jsdt.core.dom.ImportDeclaration;
import org.eclipse.wst.jsdt.core.dom.Initializer;
import org.eclipse.wst.jsdt.core.dom.JavaScriptUnit;
import org.eclipse.wst.jsdt.core.dom.PackageDeclaration;
import org.eclipse.wst.jsdt.core.dom.SimpleName;
import org.eclipse.wst.jsdt.core.dom.SuperConstructorInvocation;
import org.eclipse.wst.jsdt.core.dom.TypeDeclaration;
import org.eclipse.wst.jsdt.core.dom.VariableDeclarationFragment;
import org.eclipse.wst.jsdt.core.search.SearchMatch;
import org.eclipse.wst.jsdt.internal.corext.dom.ASTNodes;
import org.eclipse.wst.jsdt.internal.corext.dom.NodeFinder;
import org.eclipse.wst.jsdt.internal.corext.dom.Selection;
import org.eclipse.wst.jsdt.internal.corext.dom.SelectionAnalyzer;
public class ASTNodeSearchUtil {
private ASTNodeSearchUtil() {
//no instance
}
public static ASTNode[] getAstNodes(SearchMatch[] searchResults, JavaScriptUnit cuNode) {
List result= new ArrayList(searchResults.length);
for (int i= 0; i < searchResults.length; i++) {
ASTNode node= getAstNode(searchResults[i], cuNode);
if (node != null)
result.add(node);
}
return (ASTNode[]) result.toArray(new ASTNode[result.size()]);
}
public static ASTNode getAstNode(SearchMatch searchResult, JavaScriptUnit cuNode) {
ASTNode selectedNode= getAstNode(cuNode, searchResult.getOffset(), searchResult.getLength());
if (selectedNode == null)
return null;
if (selectedNode.getParent() == null)
return null;
return selectedNode;
}
public static ASTNode getAstNode(JavaScriptUnit cuNode, int start, int length){
SelectionAnalyzer analyzer= new SelectionAnalyzer(Selection.createFromStartLength(start, length), true);
cuNode.accept(analyzer);
//XXX workaround for jdt core feature 23527
ASTNode node= analyzer.getFirstSelectedNode();
if (node == null && analyzer.getLastCoveringNode() instanceof SuperConstructorInvocation)
node= analyzer.getLastCoveringNode().getParent();
else if (node == null && analyzer.getLastCoveringNode() instanceof ConstructorInvocation)
node= analyzer.getLastCoveringNode().getParent();
if (node == null)
return null;
ASTNode parentNode= node.getParent();
if (parentNode instanceof FunctionDeclaration){
FunctionDeclaration md= (FunctionDeclaration)parentNode;
if (!(node instanceof SimpleName)
&& md.isConstructor()
&& md.getBody() != null
&& md.getBody().statements().size() > 0
&&(md.getBody().statements().get(0) instanceof ConstructorInvocation || md.getBody().statements().get(0) instanceof SuperConstructorInvocation)
&&((ASTNode)md.getBody().statements().get(0)).getLength() == length + 1)
return (ASTNode)md.getBody().statements().get(0);
}
if (parentNode instanceof SuperConstructorInvocation){
if (parentNode.getLength() == length + 1)
return parentNode;
}
if (parentNode instanceof ConstructorInvocation){
if (parentNode.getLength() == length + 1)
return parentNode;
}
return node;
}
public static FunctionDeclaration getMethodDeclarationNode(IFunction iMethod, JavaScriptUnit cuNode) throws JavaScriptModelException {
return (FunctionDeclaration)ASTNodes.getParent(getNameNode(iMethod, cuNode), FunctionDeclaration.class);
}
public static BodyDeclaration getMethodOrAnnotationTypeMemberDeclarationNode(IFunction iMethod, JavaScriptUnit cuNode) throws JavaScriptModelException {
// if (JdtFlags.isAnnotation(iMethod.getDeclaringType()))
// return getAnnotationTypeMemberDeclarationNode(iMethod, cuNode);
// else
return getMethodDeclarationNode(iMethod, cuNode);
}
public static VariableDeclarationFragment getFieldDeclarationFragmentNode(IField iField, JavaScriptUnit cuNode) throws JavaScriptModelException {
ASTNode node= getNameNode(iField, cuNode);
if (node instanceof VariableDeclarationFragment)
return (VariableDeclarationFragment)node;
return (VariableDeclarationFragment)ASTNodes.getParent(node, VariableDeclarationFragment.class);
}
public static FieldDeclaration getFieldDeclarationNode(IField iField, JavaScriptUnit cuNode) throws JavaScriptModelException {
return (FieldDeclaration) ASTNodes.getParent(getNameNode(iField, cuNode), FieldDeclaration.class);
}
public static BodyDeclaration getFieldOrEnumConstantDeclaration(IField iField, JavaScriptUnit cuNode) throws JavaScriptModelException {
return getFieldDeclarationNode(iField, cuNode);
}
public static BodyDeclaration getBodyDeclarationNode(IMember iMember, JavaScriptUnit cuNode) throws JavaScriptModelException {
return (BodyDeclaration) ASTNodes.getParent(getNameNode(iMember, cuNode), BodyDeclaration.class);
}
public static AbstractTypeDeclaration getAbstractTypeDeclarationNode(IType iType, JavaScriptUnit cuNode) throws JavaScriptModelException {
return (AbstractTypeDeclaration) ASTNodes.getParent(getNameNode(iType, cuNode), AbstractTypeDeclaration.class);
}
public static TypeDeclaration getTypeDeclarationNode(IType iType, JavaScriptUnit cuNode) throws JavaScriptModelException {
return (TypeDeclaration) ASTNodes.getParent(getNameNode(iType, cuNode), TypeDeclaration.class);
}
public static ClassInstanceCreation getClassInstanceCreationNode(IType iType, JavaScriptUnit cuNode) throws JavaScriptModelException {
return (ClassInstanceCreation) ASTNodes.getParent(getNameNode(iType, cuNode), ClassInstanceCreation.class);
}
public static List getBodyDeclarationList(IType iType, JavaScriptUnit cuNode) throws JavaScriptModelException {
if (iType.isAnonymous())
return getClassInstanceCreationNode(iType, cuNode).getAnonymousClassDeclaration().bodyDeclarations();
else
return getAbstractTypeDeclarationNode(iType, cuNode).bodyDeclarations();
}
//returns an array because of the import container, which does not represent 1 node but many
//for fields, it returns the whole declaration node
public static ASTNode[] getDeclarationNodes(IJavaScriptElement element, JavaScriptUnit cuNode) throws JavaScriptModelException {
switch(element.getElementType()){
case IJavaScriptElement.FIELD:
return new ASTNode[]{getFieldOrEnumConstantDeclaration((IField) element, cuNode)};
case IJavaScriptElement.IMPORT_CONTAINER:
return getImportNodes((IImportContainer)element, cuNode);
case IJavaScriptElement.IMPORT_DECLARATION:
return new ASTNode[]{getImportDeclarationNode((IImportDeclaration)element, cuNode)};
case IJavaScriptElement.INITIALIZER:
return new ASTNode[]{getInitializerNode((IInitializer)element, cuNode)};
case IJavaScriptElement.METHOD:
return new ASTNode[]{getMethodOrAnnotationTypeMemberDeclarationNode((IFunction) element, cuNode)};
case IJavaScriptElement.PACKAGE_DECLARATION:
return new ASTNode[]{getPackageDeclarationNode((IPackageDeclaration)element, cuNode)};
case IJavaScriptElement.TYPE:
return new ASTNode[]{getAbstractTypeDeclarationNode((IType) element, cuNode)};
default:
Assert.isTrue(false, String.valueOf(element.getElementType()));
return null;
}
}
private static ASTNode getNameNode(IMember iMember, JavaScriptUnit cuNode) throws JavaScriptModelException {
return NodeFinder.perform(cuNode, iMember.getNameRange());
}
public static PackageDeclaration getPackageDeclarationNode(IPackageDeclaration reference, JavaScriptUnit cuNode) throws JavaScriptModelException {
return (PackageDeclaration) findNode(reference.getSourceRange(), cuNode);
}
public static ImportDeclaration getImportDeclarationNode(IImportDeclaration reference, JavaScriptUnit cuNode) throws JavaScriptModelException {
return (ImportDeclaration) findNode(reference.getSourceRange(), cuNode);
}
public static ASTNode[] getImportNodes(IImportContainer reference, JavaScriptUnit cuNode) throws JavaScriptModelException {
IJavaScriptElement[] imps= reference.getChildren();
ASTNode[] result= new ASTNode[imps.length];
for (int i= 0; i < imps.length; i++) {
result[i]= getImportDeclarationNode((IImportDeclaration)imps[i], cuNode);
}
return result;
}
public static Initializer getInitializerNode(IInitializer initializer, JavaScriptUnit cuNode) throws JavaScriptModelException {
ASTNode node= findNode(initializer.getSourceRange(), cuNode);
if (node instanceof Initializer)
return (Initializer) node;
if (node instanceof Block && node.getParent() instanceof Initializer)
return (Initializer) node.getParent();
return null;
}
private static ASTNode findNode(ISourceRange range, JavaScriptUnit cuNode){
NodeFinder nodeFinder= new NodeFinder(range.getOffset(), range.getLength());
cuNode.accept(nodeFinder);
ASTNode coveredNode= nodeFinder.getCoveredNode();
if (coveredNode != null)
return coveredNode;
else
return nodeFinder.getCoveringNode();
}
public static ASTNode[] findNodes(SearchMatch[] searchResults, JavaScriptUnit cuNode) {
List result= new ArrayList(searchResults.length);
for (int i= 0; i < searchResults.length; i++) {
ASTNode node= findNode(searchResults[i], cuNode);
if (node != null)
result.add(node);
}
return (ASTNode[]) result.toArray(new ASTNode[result.size()]);
}
public static ASTNode findNode(SearchMatch searchResult, JavaScriptUnit cuNode) {
ASTNode selectedNode= NodeFinder.perform(cuNode, searchResult.getOffset(), searchResult.getLength());
if (selectedNode == null)
return null;
if (selectedNode.getParent() == null)
return null;
return selectedNode;
}
}