blob: 994a327786fa797b7d1042ec2a66fb3abd460ad3 [file] [log] [blame]
/*
* (c) Copyright IBM Corp. 2002.
* All Rights Reserved.
*/
package org.eclipse.jdt.internal.debug.eval.ast;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.debug.core.DebugException;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.Message;
import org.eclipse.jdt.debug.core.IJavaDebugTarget;
import org.eclipse.jdt.debug.core.IJavaObject;
import org.eclipse.jdt.debug.core.IJavaStackFrame;
import org.eclipse.jdt.debug.core.IJavaThread;
import org.eclipse.jdt.debug.core.IJavaValue;
import org.eclipse.jdt.debug.eval.IEvaluationEngine;
import org.eclipse.jdt.debug.eval.IEvaluationListener;
import org.eclipse.jdt.debug.eval.ast.model.ICompiledExpression;
import org.eclipse.jdt.debug.eval.ast.model.IRuntimeContext;
import org.eclipse.jdt.debug.eval.ast.model.IValue;
import org.eclipse.jdt.debug.eval.ast.model.IVariable;
import org.eclipse.jdt.internal.debug.eval.ast.engine.ASTAPIVisitor;
import org.eclipse.jdt.internal.debug.eval.ast.engine.InstructionSequence;
import org.eclipse.jdt.internal.debug.core.model.JDIThread;
import org.eclipse.jdt.internal.debug.eval.EvaluationResult;
/**
* @version 1.0
* @author
*/
public class ASTEvaluationEngine implements IEvaluationEngine {
private IJavaProject fProject;
private IJavaDebugTarget fDebugTarget;
private boolean fEvaluationCancelled;
private boolean fEvaluationComplete;
public ASTEvaluationEngine(IJavaProject project, IJavaDebugTarget debugTarget) {
setJavaProject(project);
setDebugTarget(debugTarget);
}
public void setJavaProject(IJavaProject project) {
fProject = project;
}
public void setDebugTarget(IJavaDebugTarget debugTarget) {
fDebugTarget = debugTarget;
}
/*
* @see IEvaluationEngine#evaluate(String, IJavaThread, IEvaluationListener)
*/
public void evaluate(String snippet, IJavaThread thread, IEvaluationListener listener) throws DebugException {
}
/**
* @see IEvaluationEngine#evaluate(String, IJavaStackFrame, IEvaluationListener)
*/
public void evaluate(String snippet, IJavaStackFrame frame, IEvaluationListener listener) throws DebugException {
ICompiledExpression expression= getCompiledExpression(snippet, frame);
evaluate(expression, frame, listener);
}
/**
* @see IEvaluationEngine#evaluate(ICompiledExpression, IJavaStackFrame, IEvaluationListener)
*/
public void evaluate(final ICompiledExpression expression, final IJavaStackFrame frame, final IEvaluationListener listener) {
RuntimeContext context = new RuntimeContext(getJavaProject(), frame);
evaluate(expression, context, (IJavaThread)frame.getThread(), listener);
}
/**
* @see IEvaluationEngine#evaluate(String, IJavaObject, IJavaThread, IEvaluationListener)
*/
public void evaluate(String snippet, IJavaObject thisContext, IJavaThread thread, IEvaluationListener listener) throws DebugException {
ICompiledExpression expression= getCompiledExpression(snippet, thisContext, thread);
evaluate(expression, thisContext, thread, listener);
}
/**
* @see IEvaluationEngine#evaluate(ICompiledExpression, IJavaObject, IJavaThread, IEvaluationListener)
*/
public void evaluate(final ICompiledExpression expression, final IJavaObject thisContext, final IJavaThread thread, final IEvaluationListener listener) {
IRuntimeContext context = new JavaObjectRuntimeContext(thisContext, getJavaProject(), thread);
evaluate(expression, context, thread, listener);
}
/**
* Performs the evaluation.
*/
public void evaluate(final ICompiledExpression expression, final IRuntimeContext context, final IJavaThread thread, final IEvaluationListener listener) {
Thread evaluationThread= new Thread(new Runnable() {
public void run() {
fEvaluationCancelled= false;
fEvaluationComplete= false;
EvaluationResult result = new EvaluationResult(ASTEvaluationEngine.this, expression.getSnippet(), thread);
if (expression.hasErrors()) {
Message[] errors= expression.getErrors();
for (int i= 0, numErrors= errors.length; i < numErrors; i++) {
result.addError(errors[i]);
}
listener.evaluationComplete(result);
return;
}
IValue value = null;
Thread timeoutThread= new Thread(new Runnable() {
public void run() {
while (!fEvaluationComplete && !fEvaluationCancelled) {
try {
Thread.currentThread().sleep(10000); // 10 second timeout for now
} catch(InterruptedException e) {
}
if (!fEvaluationComplete) {
try {
thread.suspend();
if (!listener.evaluationTimedOut(thread)) {
fEvaluationCancelled= true;
} else {
// Keep waiting
thread.resume();
}
} catch(DebugException e) {
}
}
}
}
}, "Evaluation timeout thread");
timeoutThread.start();
value= expression.evaluate(context);
fEvaluationComplete= true;
if (fEvaluationCancelled) {
// Don't notify the listener if the evaluation has been cancelled
return;
}
CoreException exception= expression.getException();
if (value != null) {
IJavaValue jv = ((EvaluationValue)value).getJavaValue();
result.setValue(jv);
}
result.setException(exception);
listener.evaluationComplete(result);
}
}, "Evaluation thread");
evaluationThread.start();
}
/*
* @see IEvaluationEngine#getCompiledExpression(String, IJavaStackFrame)
*/
public ICompiledExpression getCompiledExpression(String snippet, IJavaStackFrame frame) throws DebugException {
IJavaProject javaProject = getJavaProject();
RuntimeContext context = new RuntimeContext(javaProject, frame);
ASTCodeSnippetToCuMapper mapper = null;
CompilationUnit unit = null;
try {
IVariable[] locals = context.getLocals();
int numLocals= locals.length;
int[] localModifiers = new int[locals.length];
String[] localTypesNames= new String[numLocals];
String[] localVariables= new String[numLocals];
for (int i = 0; i < numLocals; i++) {
localVariables[i] = locals[i].getName();
localTypesNames[i] = ((EvaluationValue)locals[i].getValue()).getJavaValue().getReferenceTypeName();
localModifiers[i]= 0;
}
mapper = new ASTCodeSnippetToCuMapper(new String[0], localModifiers, localTypesNames, localVariables, snippet);
unit = AST.parseCompilationUnit(mapper.getSource(frame).toCharArray(), mapper.getCompilationUnitName(), javaProject);
} catch (JavaModelException e) {
throw new DebugException(e.getStatus());
} catch (CoreException e) {
throw new DebugException(e.getStatus());
}
return genExpressionFromAST(snippet, mapper, unit);
}
public ICompiledExpression getCompiledExpression(String snippet, IJavaObject thisContext, IJavaThread thread) throws DebugException {
IJavaProject javaProject = getJavaProject();
ASTCodeSnippetToCuMapper mapper = null;
CompilationUnit unit = null;
try {
mapper = new ASTCodeSnippetToCuMapper(new String[0], new int[0], new String[0], new String[0], snippet);
unit = AST.parseCompilationUnit(mapper.getSource(thisContext, javaProject).toCharArray(), mapper.getCompilationUnitName(), javaProject);
} catch (CoreException e) {
throw new DebugException(e.getStatus());
}
return genExpressionFromAST(snippet, mapper, unit);
}
private ICompiledExpression genExpressionFromAST(String snippet, ASTCodeSnippetToCuMapper mapper, CompilationUnit unit) {
Message[] messages= unit.getMessages();
if (messages.length != 0) {
boolean error= false;
InstructionSequence errorSequence= new InstructionSequence(snippet);
int codeSnippetStartOffset= mapper.getStartPosition();
int codeSnippetEndOffset= codeSnippetStartOffset + snippet.length();
for (int i = 0; i < messages.length; i++) {
Message message= messages[i];
int errorOffset= message.getSourcePosition();
// TO DO: Internationalize "void method..." error message check
if (codeSnippetStartOffset <= errorOffset && errorOffset <= codeSnippetEndOffset && !"Void methods cannot return a value".equals(message.getMessage())) {
errorSequence.addError(message);
error = true;
}
}
if (error) {
return errorSequence;
}
}
ASTAPIVisitor visitor = new ASTAPIVisitor(mapper.getStartPosition(), snippet);
unit.accept(visitor);
return visitor.getInstructions();
}
/*
* @see IEvaluationEngine#getJavaProject()
*/
public IJavaProject getJavaProject() {
return fProject;
}
/*
* @see IEvaluationEngine#getDebugTarget()
*/
public IJavaDebugTarget getDebugTarget() {
return fDebugTarget;
}
/*
* @see IEvaluationEngine#dispose()
*/
public void dispose() {
}
/**
* @see IEvaluationEngine#evaluate(ICompiledExpression, IJavaThread, IEvaluationListener)
*/
public void evaluate(ICompiledExpression expression, IJavaThread thread, IEvaluationListener listener) throws DebugException {
}
/**
* @see IEvaluationEngine#getCompiledExpression(String, IJavaThread)
*/
public ICompiledExpression getCompiledExpression(String snippet, IJavaThread thread) throws DebugException {
return null;
}
}