/******************************************************************************* * 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.*; 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.*; import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration; import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; 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; } }