Copyright (c) 2000, 2009 IBM Corporation and others. This program and the accompanying materials are made available under the terms of the Eclipse Public License 2.0 which accompanies this distribution, and is available at https://www.eclipse.org/legal/epl-2.0/ SPDX-License-Identifier: EPL-2.0 Contributors: IBM Corporation - initial API and implementation
/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 * which accompanies this distribution, and is available at * https://www.eclipse.org/legal/epl-2.0/ * * SPDX-License-Identifier: EPL-2.0 * * 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
/** * 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; @Override 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; } }