/*******************************************************************************
* Copyright (c) 2000, 2009 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.jdt.internal.core.util;
import org.eclipse.jdt.core.IField;
import org.eclipse.jdt.core.IInitializer;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.ASTVisitor;
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.Argument;
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
import org.eclipse.jdt.internal.compiler.ast.Initializer;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
import org.eclipse.jdt.internal.core.SourceRefElement;
import org.eclipse.jdt.internal.core.SourceType;
/**
* Finds an ASTNode given an IJavaElement in a CompilationUnitDeclaration
*/
public class ASTNodeFinder {
private CompilationUnitDeclaration unit;
public ASTNodeFinder(CompilationUnitDeclaration unit) {
this.unit= unit;
}
/*
* Finds the FieldDeclaration in the given ast corresponding to the given field handle.
* Returns null if not found.
*/
public FieldDeclaration findField(IField fieldHandle) {
TypeDeclaration typeDecl= findType((IType)fieldHandle.getParent());
if (typeDecl == null)
return null;
FieldDeclaration[] fields= typeDecl.fields;
if (fields != null) {
char[] fieldName= fieldHandle.getElementName().toCharArray();
for (int i= 0, length= fields.length; i < length; i++) {
FieldDeclaration field= fields[i];
if (CharOperation.equals(fieldName, field.name)) {
return field;
}
}
}
return null;
}
/*
* Finds the Initializer in the given ast corresponding to the given initializer handle.
* Returns null if not found.
*/
public Initializer findInitializer(IInitializer initializerHandle) {
TypeDeclaration typeDecl= findType((IType)initializerHandle.getParent());
if (typeDecl == null)
return null;
FieldDeclaration[] fields= typeDecl.fields;
if (fields != null) {
int occurenceCount= ((SourceRefElement)initializerHandle).occurrenceCount;
for (int i= 0, length= fields.length; i < length; i++) {
FieldDeclaration field= fields[i];
if (field instanceof Initializer && --occurenceCount == 0) {
return (Initializer)field;
}
}
}
return null;
}
/*
* Finds the AbstractMethodDeclaration in the given ast corresponding to the given method handle.
* Returns null if not found.
*/
public AbstractMethodDeclaration findMethod(IMethod methodHandle) {
TypeDeclaration typeDecl= findType((IType)methodHandle.getParent());
if (typeDecl == null)
return null;
AbstractMethodDeclaration[] methods= typeDecl.methods;
if (methods != null) {
char[] selector= methodHandle.getElementName().toCharArray();
String[] parameterTypeSignatures= methodHandle.getParameterTypes();
int parameterCount= parameterTypeSignatures.length;
nextMethod: for (int i= 0, length= methods.length; i < length; i++) {
AbstractMethodDeclaration method= methods[i];
if (CharOperation.equals(selector, method.selector)) {
Argument[] args= method.arguments;
int argsLength= args == null ? 0 : args.length;
if (argsLength == parameterCount) {
for (int j= 0; j < parameterCount; j++) {
TypeReference type= args[j].type;
String signature= Util.typeSignature(type);
if (!signature.equals(parameterTypeSignatures[j])) {
continue nextMethod;
}
}
return method;
}
}
}
}
return null;
}
/*
* Finds the TypeDeclaration in the given ast corresponding to the given type handle.
* Returns null if not found.
*/
public TypeDeclaration findType(IType typeHandle) {
IJavaElement parent= typeHandle.getParent();
final char[] typeName= typeHandle.getElementName().toCharArray();
final int occurenceCount= ((SourceType)typeHandle).occurrenceCount;
final boolean findAnonymous= typeName.length == 0;
class Visitor extends ASTVisitor {
TypeDeclaration result;
int count= 0;
public boolean visit(TypeDeclaration typeDeclaration, BlockScope scope) {
if (this.result != null)
return false;
if ((typeDeclaration.bits & ASTNode.IsAnonymousType) != 0) {
if (findAnonymous && ++this.count == occurenceCount) {
this.result= typeDeclaration;
}
} else {
if (!findAnonymous && CharOperation.equals(typeName, typeDeclaration.name)) {
this.result= typeDeclaration;
}
}
return false; // visit only one level
}
}
switch (parent.getElementType()) {
case IJavaElement.COMPILATION_UNIT:
TypeDeclaration[] types= this.unit.types;
if (types != null) {
for (int i= 0, length= types.length; i < length; i++) {
TypeDeclaration type= types[i];
if (CharOperation.equals(typeName, type.name)) {
return type;
}
}
}
break;
case IJavaElement.TYPE:
TypeDeclaration parentDecl= findType((IType)parent);
if (parentDecl == null)
return null;
types= parentDecl.memberTypes;
if (types != null) {
for (int i= 0, length= types.length; i < length; i++) {
TypeDeclaration type= types[i];
if (CharOperation.equals(typeName, type.name)) {
return type;
}
}
}
break;
case IJavaElement.FIELD:
FieldDeclaration fieldDecl= findField((IField)parent);
if (fieldDecl == null)
return null;
Visitor visitor= new Visitor();
fieldDecl.traverse(visitor, null);
return visitor.result;
case IJavaElement.INITIALIZER:
Initializer initializer= findInitializer((IInitializer)parent);
if (initializer == null)
return null;
visitor= new Visitor();
initializer.traverse(visitor, null);
return visitor.result;
case IJavaElement.METHOD:
AbstractMethodDeclaration methodDecl= findMethod((IMethod)parent);
if (methodDecl == null)
return null;
visitor= new Visitor();
methodDecl.traverse(visitor, (ClassScope)null);
return visitor.result;
}
return null;
}
}