/*******************************************************************************
* Copyright (c) 2000, 2012 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:
* Jesper Kamstrup Linnet (eclipse@kamstrup-linnet.dk) - initial API and implementation
* (report 36180: Callers/Callees view)
* eBay Inc. Modifications
*******************************************************************************/
package org.eclipse.vjet.eclipse.internal.core;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.vjet.dsf.jst.IJstType;
import org.eclipse.vjet.dsf.jst.JstSource;
import org.eclipse.vjet.dsf.jst.expr.MtdInvocationExpr;
import org.eclipse.vjet.eclipse.codeassist.CodeassistUtils;
import org.eclipse.vjet.eclipse.core.IVjoSourceModule;
import org.eclipse.vjet.eclipse.core.VjetPlugin;
import org.eclipse.vjet.eclipse.core.ts.GenericVisitor;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.dltk.mod.ast.references.SimpleReference;
import org.eclipse.dltk.mod.core.IMethod;
import org.eclipse.dltk.mod.core.IModelElement;
import org.eclipse.dltk.mod.core.ISourceRange;
import org.eclipse.dltk.mod.core.ModelException;
class VjoCalleeAnalyzerVisitor extends GenericVisitor {
private Map fSearchResults;
private IMethod fMethod;
private IJstType fCompilationUnit;
private IProgressMonitor fProgressMonitor;
private int fMethodEndPosition;
private int fMethodStartPosition;
VjoCalleeAnalyzerVisitor(IMethod method, IJstType jstType, IProgressMonitor progressMonitor) {
fSearchResults = new HashMap();
this.fMethod = method;
this.fCompilationUnit = jstType;
this.fProgressMonitor = progressMonitor;
try {
ISourceRange sourceRange = method.getSourceRange();
this.fMethodStartPosition = sourceRange.getOffset();
this.fMethodEndPosition = fMethodStartPosition + sourceRange.getLength();
} catch (ModelException jme) {
VjetPlugin.error("Model exception occurs when getting source range", jme);
}
}
/**
* Method getCallees.
*
* @return CallerElement
*/
public Map getCallees() {
return fSearchResults;
}
// /* (non-Javadoc)
// * @see
// org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.ClassInstanceCreation)
// */
// public boolean visit(ClassInstanceCreation node) {
// progressMonitorWorked(1);
// if (!isFurtherTraversalNecessary(node)) {
// return false;
// }
//
// if (isNodeWithinMethod(node)) {
// addMethodCall(node.resolveConstructorBinding(), node);
// }
//
// return true;
// }
//
// /**
// * Find all constructor invocations (<code>this(...)</code>) from the
// called method.
// * Since we only traverse into the AST on the wanted method declaration,
// this method
// * should not hit on more constructor invocations than those in the wanted
// method.
// *
// * @see
// org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.ConstructorInvocation)
// */
// public boolean visit(ConstructorInvocation node) {
// progressMonitorWorked(1);
// if (!isFurtherTraversalNecessary(node)) {
// return false;
// }
//
// if (isNodeWithinMethod(node)) {
// addMethodCall(node.resolveConstructorBinding(), node);
// }
//
// return true;
// }
//
// /**
// * @see
// org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.MethodDeclaration)
// */
// public boolean visit(MethodDeclaration node) {
// progressMonitorWorked(1);
// return isFurtherTraversalNecessary(node);
// }
//
// /**
// * Find all method invocations from the called method. Since we only
// traverse into
// * the AST on the wanted method declaration, this method should not hit on
// more
// * method invocations than those in the wanted method.
// *
// * @see
// org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.MethodInvocation)
// */
// public boolean visit(MethodInvocation node) {
// progressMonitorWorked(1);
// if (!isFurtherTraversalNecessary(node)) {
// return false;
// }
//
// if (isNodeWithinMethod(node)) {
// addMethodCall(node.resolveMethodBinding(), node);
// }
//
// return true;
// }
//
// /**
// * Find invocations of the supertype's constructor from the called method
// * (=constructor). Since we only traverse into the AST on the wanted
// method
// * declaration, this method should not hit on more method invocations than
// those in
// * the wanted method.
// *
// * @see
// org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.SuperConstructorInvocation)
// */
// public boolean visit(SuperConstructorInvocation node) {
// progressMonitorWorked(1);
// if (!isFurtherTraversalNecessary(node)) {
// return false;
// }
//
// if (isNodeWithinMethod(node)) {
// addMethodCall(node.resolveConstructorBinding(), node);
// }
//
// return true;
// }
//
// /**
// * Find all method invocations from the called method. Since we only
// traverse into
// * the AST on the wanted method declaration, this method should not hit on
// more
// * method invocations than those in the wanted method.
// *
// * @see
// org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.MethodInvocation)
// */
// public boolean visit(SuperMethodInvocation node) {
// progressMonitorWorked(1);
// if (!isFurtherTraversalNecessary(node)) {
// return false;
// }
//
// if (isNodeWithinMethod(node)) {
// addMethodCall(node.resolveMethodBinding(), node);
// }
//
// return true;
// }
//
// /**
// * When an anonymous class declaration is reached, the traversal should
// not go further since it's not
// * supposed to consider calls inside the anonymous inner class as calls
// from the outer method.
// *
// * @see
// org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.AnonymousClassDeclaration)
// */
// public boolean visit(AnonymousClassDeclaration node) {
// return isNodeEnclosingMethod(node);
// }
private void progressMonitorWorked(int work) {
if (fProgressMonitor != null) {
fProgressMonitor.worked(work);
if (fProgressMonitor.isCanceled()) {
throw new OperationCanceledException();
}
}
}
@Override
public void visit(MtdInvocationExpr expr) {
progressMonitorWorked(1);
//what we've put here should be different than CodeAssistUtils.
IModelElement[] modelElement=CodeassistUtils.getModelElementByMtdInvoExpr(expr, (IVjoSourceModule)this.fMethod.getSourceModule());
if (modelElement != null&&modelElement instanceof IMethod[])
addMethodCall( (IMethod[])modelElement, expr);
}
protected void addMethodCall(IMethod[] calledMethod, MtdInvocationExpr node) {
JstSource jstSource = node.getMethodIdentifier().getSource();
String methodName = node.getMethodIdentifier().toString();
SimpleReference ref = null;
if (jstSource != null) {
ref = new SimpleReference(jstSource.getStartOffSet(), jstSource.getStartOffSet() + methodName.length(), node.toExprText());
} else {
ref = new SimpleReference(-1, 0, node.toExprText());
}
fSearchResults.put(ref, calledMethod );
}
// protected void addMethodCall(IMethodBinding calledMethodBinding, ASTNode node) {
// try {
// if (calledMethodBinding != null) {
// fProgressMonitor.worked(1);
//
// ITypeBinding calledTypeBinding = calledMethodBinding.getDeclaringClass();
// IType calledType = null;
//
// if (!calledTypeBinding.isAnonymous()) {
// calledType = (IType) calledTypeBinding.getJavaElement();
// } else {
// if (!"java.lang.Object".equals(calledTypeBinding.getSuperclass().getQualifiedName())) { //$NON-NLS-1$
// calledType = (IType) calledTypeBinding.getSuperclass().getJavaElement();
// } else {
// calledType = (IType) calledTypeBinding.getInterfaces()[0].getJavaElement();
// }
// }
//
// IMethod calledMethod = findIncludingSupertypes(calledMethodBinding, calledType, fProgressMonitor);
//
// IMember referencedMember = null;
// if (calledMethod == null) {
// if (calledMethodBinding.isConstructor() && calledMethodBinding.getParameterTypes().length == 0) {
// referencedMember = calledType;
// }
// } else {
// if (calledType.isInterface()) {
// calledMethod = findImplementingMethods(calledMethod);
// }
//
// if (!isIgnoredBySearchScope(calledMethod)) {
// referencedMember = calledMethod;
// }
// }
// final int position = node.getStartPosition();
// final int number = fCompilationUnit.getLineNumber(position);
// fSearchResults.addMember(fMethod, referencedMember, position, position + node.getLength(), number < 1 ? 1 : number);
// }
// } catch (JavaModelException jme) {
// JavaPlugin.log(jme);
// }
// }
}