/******************************************************************************* * Copyright (c) 2009 the CHISEL group and contributors. * 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: * Del Myers - initial API and implementation *******************************************************************************/ package ca.uvic.chisel.javasketch.internal.ast; import java.lang.ref.WeakReference; import java.util.HashMap; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.jdt.core.IClassFile; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.IMethod; import org.eclipse.jdt.core.ISourceRange; import org.eclipse.jdt.core.IType; import org.eclipse.jdt.core.ITypeRoot; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.core.dom.AST; import org.eclipse.jdt.core.dom.ASTNode; import org.eclipse.jdt.core.dom.ASTParser; import org.eclipse.jdt.core.dom.IMethodBinding; import org.eclipse.jdt.core.dom.MethodDeclaration; import org.eclipse.jdt.core.dom.MethodInvocation; import org.eclipse.jdt.core.dom.Type; import ca.uvic.chisel.javasketch.SketchPlugin; /** * Static methods for retrieving AST information. * @author Del Myers */ public class ASTUTils { private static ASTParser parser = ASTParser.newParser(AST.JLS3); private static HashMap<IType, WeakReference<ASTNode>> cache = new HashMap<IType, WeakReference<ASTNode>>(); static { parser.setResolveBindings(true); } public static MethodDeclaration findMethodDeclaration(ASTNode rootNode, IMethod method) { if (rootNode != null) { ISourceRange range; try { if (!method.getOpenable().isOpen()) { method.getOpenable().open(new NullProgressMonitor()); } range = method.getSourceRange(); NodeFinder finder = new NodeFinder(rootNode, range.getOffset(), range.getLength()); ASTNode node = finder.getCoveredNode(); if (node instanceof MethodDeclaration) { return (MethodDeclaration) node; } else { return null; } } catch (JavaModelException e) { SketchPlugin.getDefault().log(e); } } return null; } public static ASTNode getASTFor(IType type) { try { synchronized (cache) { if (cache.containsKey(type)) { WeakReference<ASTNode> ref = cache.get(type); if (!(ref.isEnqueued() || ref.get() == null)) { return ref.get(); } else { cache.remove(type); } } ICompilationUnit unit = type.getCompilationUnit(); ASTNode node = null; if (unit != null) { node = getASTFor(unit); } IClassFile classFile = type.getClassFile(); if (classFile != null) { node = getASTFor(classFile); } if (node != null) { cache.put(type, new WeakReference<ASTNode>(node)); } return node; } } catch (Exception e) {} return null; } /** * @param classFile * @return */ public static ASTNode getASTFor(IClassFile unit) { if (!unit.isOpen()) { try { unit.open(new NullProgressMonitor()); } catch (JavaModelException e) { SketchPlugin.getDefault().log(e); } } parser.setSource(unit); parser.setResolveBindings(true); return parser.createAST(new NullProgressMonitor()); } /** * @param unit * @return */ public static ASTNode getASTFor(ICompilationUnit unit) { if (!unit.isOpen()) { try { unit.open(new NullProgressMonitor()); } catch (JavaModelException e) { SketchPlugin.getDefault().log(e); } } parser.setSource(unit); parser.setResolveBindings(true); return parser.createAST(new NullProgressMonitor()); } public static ASTNode getASTFor(ITypeRoot typeRoot) { if (typeRoot instanceof ICompilationUnit) { return getASTFor((ICompilationUnit)typeRoot); } else if (typeRoot instanceof IClassFile) { return getASTFor((IClassFile)typeRoot); } return null; } /** * Returns the corresponding return type for the given method invocation, or * null if it could not be found. * @param unresolved */ public static Type findReturnType(MethodInvocation invocation) { MethodDeclaration declaration = findDeclarationFor(invocation); if (declaration != null) { return declaration.getReturnType2(); } return null; } public static MethodDeclaration findDeclarationFor(MethodInvocation invocation) { IMethodBinding binding = invocation.resolveMethodBinding(); if (binding != null) { IMethod method = (IMethod) binding.getJavaElement(); IType declaringType = method.getDeclaringType(); ASTNode typeNode = getASTFor(declaringType); if (typeNode != null) { return findMethodDeclaration(typeNode, method); } } return null; } }