001: /*******************************************************************************
002: * Copyright (c) 2000, 2007 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.jdt.internal.debug.eval.ast.engine;
011:
012: import java.util.Map;
013: import java.util.StringTokenizer;
014: import java.util.regex.Matcher;
015: import java.util.regex.Pattern;
016:
017: import org.eclipse.core.runtime.CoreException;
018: import org.eclipse.core.runtime.IProgressMonitor;
019: import org.eclipse.core.runtime.IStatus;
020: import org.eclipse.core.runtime.Status;
021: import org.eclipse.debug.core.DebugEvent;
022: import org.eclipse.debug.core.DebugException;
023: import org.eclipse.debug.core.DebugPlugin;
024: import org.eclipse.debug.core.IDebugEventFilter;
025: import org.eclipse.debug.core.model.ITerminate;
026: import org.eclipse.jdt.core.IJavaProject;
027: import org.eclipse.jdt.core.JavaCore;
028: import org.eclipse.jdt.core.Signature;
029: import org.eclipse.jdt.core.compiler.IProblem;
030: import org.eclipse.jdt.core.dom.AST;
031: import org.eclipse.jdt.core.dom.ASTParser;
032: import org.eclipse.jdt.core.dom.CompilationUnit;
033: import org.eclipse.jdt.debug.core.IEvaluationRunnable;
034: import org.eclipse.jdt.debug.core.IJavaArray;
035: import org.eclipse.jdt.debug.core.IJavaArrayType;
036: import org.eclipse.jdt.debug.core.IJavaDebugTarget;
037: import org.eclipse.jdt.debug.core.IJavaInterfaceType;
038: import org.eclipse.jdt.debug.core.IJavaObject;
039: import org.eclipse.jdt.debug.core.IJavaReferenceType;
040: import org.eclipse.jdt.debug.core.IJavaStackFrame;
041: import org.eclipse.jdt.debug.core.IJavaThread;
042: import org.eclipse.jdt.debug.core.IJavaType;
043: import org.eclipse.jdt.debug.core.IJavaValue;
044: import org.eclipse.jdt.debug.core.IJavaVariable;
045: import org.eclipse.jdt.debug.core.JDIDebugModel;
046: import org.eclipse.jdt.debug.eval.IAstEvaluationEngine;
047: import org.eclipse.jdt.debug.eval.ICompiledExpression;
048: import org.eclipse.jdt.debug.eval.IEvaluationListener;
049: import org.eclipse.jdt.debug.eval.IEvaluationResult;
050: import org.eclipse.jdt.internal.debug.core.JDIDebugPlugin;
051: import org.eclipse.jdt.internal.debug.core.model.JDIDebugTarget;
052: import org.eclipse.jdt.internal.debug.core.model.JDIThread;
053: import org.eclipse.jdt.internal.debug.core.model.JDIValue;
054: import org.eclipse.jdt.internal.debug.eval.EvaluationResult;
055: import org.eclipse.jdt.internal.debug.eval.ast.instructions.InstructionSequence;
056:
057: import com.sun.jdi.InvocationException;
058: import com.sun.jdi.ObjectReference;
059:
060: public class ASTEvaluationEngine implements IAstEvaluationEngine {
061:
062: private IJavaProject fProject;
063:
064: private IJavaDebugTarget fDebugTarget;
065:
066: /**
067: * Regex to find occurrences of 'this' in a code snippet
068: */
069: private static Pattern fgThisPattern = Pattern
070: .compile("(.*[^a-zA-Z0-9]+|^)(this)([^a-zA-Z0-9]+|$).*"); //$NON-NLS-1$
071:
072: /**
073: * Filters variable change events during an evaluation to avoid refreshing the variables
074: * view until done.
075: */
076: class EventFilter implements IDebugEventFilter {
077:
078: /* (non-Javadoc)
079: * @see org.eclipse.debug.core.IDebugEventFilter#filterDebugEvents(org.eclipse.debug.core.DebugEvent[])
080: */
081: public DebugEvent[] filterDebugEvents(DebugEvent[] events) {
082: if (events.length == 1) {
083: DebugEvent event = events[0];
084: if (event.getSource() instanceof IJavaVariable
085: && event.getKind() == DebugEvent.CHANGE) {
086: if (((IJavaVariable) event.getSource())
087: .getDebugTarget().equals(getDebugTarget())) {
088: return null;
089: }
090: }
091: }
092: return events;
093: }
094:
095: }
096:
097: public ASTEvaluationEngine(IJavaProject project,
098: IJavaDebugTarget debugTarget) {
099: setJavaProject(project);
100: setDebugTarget(debugTarget);
101: }
102:
103: public void setJavaProject(IJavaProject project) {
104: fProject = project;
105: }
106:
107: public void setDebugTarget(IJavaDebugTarget debugTarget) {
108: fDebugTarget = debugTarget;
109: }
110:
111: /* (non-Javadoc)
112: * @see org.eclipse.jdt.debug.eval.IEvaluationEngine#evaluate(java.lang.String, org.eclipse.jdt.debug.core.IJavaStackFrame, org.eclipse.jdt.debug.eval.IEvaluationListener, int, boolean)
113: */
114: public void evaluate(String snippet, IJavaStackFrame frame,
115: IEvaluationListener listener, int evaluationDetail,
116: boolean hitBreakpoints) throws DebugException {
117: checkInterface(frame);
118: ICompiledExpression expression = getCompiledExpression(snippet,
119: frame);
120: evaluateExpression(expression, frame, listener,
121: evaluationDetail, hitBreakpoints);
122: }
123:
124: /* (non-Javadoc)
125: * @see org.eclipse.jdt.debug.eval.IEvaluationEngine#evaluate(java.lang.String, org.eclipse.jdt.debug.core.IJavaObject, org.eclipse.jdt.debug.core.IJavaThread, org.eclipse.jdt.debug.eval.IEvaluationListener, int, boolean)
126: */
127: public void evaluate(String snippet, IJavaObject this Context,
128: IJavaThread thread, IEvaluationListener listener,
129: int evaluationDetail, boolean hitBreakpoints)
130: throws DebugException {
131: ICompiledExpression expression = getCompiledExpression(snippet,
132: this Context);
133: evaluateExpression(expression, this Context, thread, listener,
134: evaluationDetail, hitBreakpoints);
135: }
136:
137: /**
138: * Checks if the stack frame is declared in an interface an aborts
139: * if so.
140: *
141: * @param frame stack frame
142: * @throws DebugException if declaring type is an interface
143: */
144: private void checkInterface(IJavaStackFrame frame)
145: throws DebugException {
146: if (frame.getReferenceType() instanceof IJavaInterfaceType) {
147: IStatus status = new Status(IStatus.ERROR, JDIDebugModel
148: .getPluginIdentifier(),
149: DebugException.REQUEST_FAILED,
150: EvaluationEngineMessages.ASTEvaluationEngine_0,
151: null);
152: throw new DebugException(status);
153: }
154: }
155:
156: /* (non-Javadoc)
157: * @see org.eclipse.jdt.debug.eval.IAstEvaluationEngine#evaluateExpression(org.eclipse.jdt.debug.eval.ICompiledExpression, org.eclipse.jdt.debug.core.IJavaStackFrame, org.eclipse.jdt.debug.eval.IEvaluationListener, int, boolean)
158: */
159: public void evaluateExpression(ICompiledExpression expression,
160: IJavaStackFrame frame, IEvaluationListener listener,
161: int evaluationDetail, boolean hitBreakpoints)
162: throws DebugException {
163: RuntimeContext context = new RuntimeContext(getJavaProject(),
164: frame);
165: doEvaluation(expression, context, (IJavaThread) frame
166: .getThread(), listener, evaluationDetail,
167: hitBreakpoints);
168: }
169:
170: /* (non-Javadoc)
171: * @see org.eclipse.jdt.debug.eval.IAstEvaluationEngine#evaluateExpression(org.eclipse.jdt.debug.eval.ICompiledExpression, org.eclipse.jdt.debug.core.IJavaObject, org.eclipse.jdt.debug.core.IJavaThread, org.eclipse.jdt.debug.eval.IEvaluationListener, int, boolean)
172: */
173: public void evaluateExpression(ICompiledExpression expression,
174: IJavaObject this Context, IJavaThread thread,
175: IEvaluationListener listener, int evaluationDetail,
176: boolean hitBreakpoints) throws DebugException {
177: IRuntimeContext context = null;
178: if (this Context instanceof IJavaArray) {
179: context = new ArrayRuntimeContext((IJavaArray) this Context,
180: thread, getJavaProject());
181: } else {
182: context = new JavaObjectRuntimeContext(this Context,
183: getJavaProject(), thread);
184: }
185: doEvaluation(expression, context, thread, listener,
186: evaluationDetail, hitBreakpoints);
187: }
188:
189: /**
190: * Evaluates the given expression in the given thread and the given runtime context.
191: */
192: private void doEvaluation(ICompiledExpression expression,
193: IRuntimeContext context, IJavaThread thread,
194: IEvaluationListener listener, int evaluationDetail,
195: boolean hitBreakpoints) throws DebugException {
196: if (expression instanceof InstructionSequence) {
197: // don't queue explicit evaluation if the thread is all ready performing an evaluation.
198: if (thread.isSuspended()
199: && ((JDIThread) thread).isInvokingMethod()
200: || thread.isPerformingEvaluation()
201: && evaluationDetail == DebugEvent.EVALUATION) {
202: EvaluationResult result = new EvaluationResult(this ,
203: expression.getSnippet(), thread);
204: result
205: .addError(EvaluationEngineMessages.ASTEvaluationEngine_Cannot_perform_nested_evaluations);
206: listener.evaluationComplete(result);
207: return;
208: }
209: thread.queueRunnable(new EvalRunnable(
210: (InstructionSequence) expression, thread, context,
211: listener, evaluationDetail, hitBreakpoints));
212: } else {
213: throw new DebugException(
214: new Status(
215: IStatus.ERROR,
216: JDIDebugPlugin.getUniqueIdentifier(),
217: IStatus.OK,
218: EvaluationEngineMessages.ASTEvaluationEngine_AST_evaluation_engine_cannot_evaluate_expression,
219: null));
220: }
221: }
222:
223: /* (non-Javadoc)
224: * @see org.eclipse.jdt.debug.eval.IAstEvaluationEngine#getCompiledExpression(java.lang.String, org.eclipse.jdt.debug.core.IJavaStackFrame)
225: */
226: public ICompiledExpression getCompiledExpression(String snippet,
227: IJavaStackFrame frame) {
228: IJavaProject javaProject = getJavaProject();
229: RuntimeContext context = new RuntimeContext(javaProject, frame);
230:
231: EvaluationSourceGenerator mapper = null;
232: CompilationUnit unit = null;
233: try {
234: IJavaVariable[] localsVar = context.getLocals();
235: int numLocalsVar = localsVar.length;
236: // ******
237: // to hide problems with local variable declare as instance of Local Types
238: IJavaVariable[] locals = new IJavaVariable[numLocalsVar];
239: int numLocals = 0;
240: for (int i = 0; i < numLocalsVar; i++) {
241: if (!isLocalType(localsVar[i].getSignature())) {
242: locals[numLocals++] = localsVar[i];
243: }
244: }
245: // to solve and remove
246: // ******
247: String[] localTypesNames = new String[numLocals];
248: String[] localVariables = new String[numLocals];
249: for (int i = 0; i < numLocals; i++) {
250: localVariables[i] = locals[i].getName();
251: localTypesNames[i] = Signature.toString(
252: locals[i].getGenericSignature()).replace('/',
253: '.');
254: }
255: mapper = new EvaluationSourceGenerator(localTypesNames,
256: localVariables, snippet);
257: // Compile in context of declaring type to get proper visibility of locals and members.
258: // Compiling in context of receiving type potentially provides access to more members,
259: // but does not allow access to privates members in declaring type
260: IJavaReferenceType receivingType = frame.getReferenceType();
261:
262: // currently disabled - see bugs 99416 and 106492
263: // if (frame.isStatic()) {
264: // receivingType= frame.getReferenceType();
265: // } else {
266: // receivingType= (IJavaReferenceType) frame.getThis().getJavaType();
267: // }
268:
269: unit = parseCompilationUnit(mapper.getSource(receivingType,
270: javaProject, frame.isStatic()).toCharArray(),
271: mapper.getCompilationUnitName(), javaProject);
272: } catch (CoreException e) {
273: InstructionSequence expression = new InstructionSequence(
274: snippet);
275: expression.addError(e.getStatus().getMessage());
276: return expression;
277: }
278:
279: return createExpressionFromAST(snippet, mapper, unit);
280: }
281:
282: private CompilationUnit parseCompilationUnit(char[] source,
283: String unitName, IJavaProject project) {
284: ASTParser parser = ASTParser.newParser(AST.JLS3);
285: String compilerCompliance = project.getOption(
286: JavaCore.COMPILER_COMPLIANCE, true);
287: parser.setSource(source);
288: parser.setUnitName(unitName);
289: parser.setProject(project);
290: parser.setResolveBindings(true);
291: Map options = JavaCore.getDefaultOptions();
292: options.put(JavaCore.COMPILER_COMPLIANCE, compilerCompliance);
293: options.put(JavaCore.COMPILER_SOURCE, project.getOption(
294: JavaCore.COMPILER_SOURCE, true));
295: parser.setCompilerOptions(options);
296: return (CompilationUnit) parser.createAST(null);
297: }
298:
299: // ******
300: // to hide problems with local variable declare as instance of Local Types
301: private boolean isLocalType(String typeName) {
302: StringTokenizer strTok = new StringTokenizer(typeName, "$"); //$NON-NLS-1$
303: strTok.nextToken();
304: while (strTok.hasMoreTokens()) {
305: char char0 = strTok.nextToken().charAt(0);
306: if ('0' <= char0 && char0 <= '9') {
307: return true;
308: }
309: }
310: return false;
311: }
312:
313: // ******
314:
315: /**
316: * Returns a compiled expression for an evaluation in the context of an array
317: * as a receiver.
318: */
319: private ICompiledExpression getCompiledExpression(String snippet,
320: IJavaArrayType arrayType) {
321: EvaluationSourceGenerator mapper = null;
322: CompilationUnit unit = null;
323: try {
324: IJavaProject javaProject = getJavaProject();
325: // replace all occurrences of 'this' with '_a_t'
326: String newSnippet = replaceThisReferences(snippet);
327:
328: int dimension = 1;
329: IJavaType componentType = arrayType.getComponentType();
330: while (componentType instanceof IJavaArrayType) {
331: componentType = ((IJavaArrayType) componentType)
332: .getComponentType();
333: dimension++;
334: }
335:
336: // Primitive arrays are evaluated in the context of Object.
337: // Arrays with a base component type of a class or interface are treated
338: // as Object arrays and evaluated in Object.
339: String recTypeName = "java.lang.Object"; //$NON-NLS-1$
340: String typeName = arrayType.getName();
341: if (componentType instanceof IJavaReferenceType) {
342: StringBuffer buf = new StringBuffer();
343: buf.append("java.lang.Object"); //$NON-NLS-1$
344: for (int i = 0; i < dimension; i++) {
345: buf.append("[]"); //$NON-NLS-1$
346: }
347: typeName = buf.toString();
348: }
349:
350: String[] localTypesNames = new String[] { typeName };
351: String[] localVariables = new String[] { ArrayRuntimeContext.ARRAY_THIS_VARIABLE };
352: mapper = new EvaluationSourceGenerator(localTypesNames,
353: localVariables, newSnippet);
354:
355: int index = typeName.indexOf('$');
356: // if the argument is an inner type, compile in context of outer type so type is visible
357: if (index >= 0) {
358: recTypeName = typeName.substring(0, index);
359: }
360: IJavaType[] javaTypes = getDebugTarget().getJavaTypes(
361: recTypeName);
362: if (javaTypes.length > 0) {
363: IJavaReferenceType recType = (IJavaReferenceType) javaTypes[0];
364: unit = parseCompilationUnit(mapper.getSource(recType,
365: getJavaProject(), false).toCharArray(), mapper
366: .getCompilationUnitName(), javaProject);
367: } else {
368: IStatus status = new Status(IStatus.ERROR,
369: JDIDebugPlugin.getUniqueIdentifier(),
370: JDIDebugPlugin.ERROR,
371: EvaluationEngineMessages.ASTEvaluationEngine_1,
372: null);
373: throw new CoreException(status);
374: }
375: } catch (CoreException e) {
376: InstructionSequence expression = new InstructionSequence(
377: snippet);
378: expression.addError(e.getStatus().getMessage());
379: return expression;
380: }
381:
382: return createExpressionFromAST(snippet, mapper, unit);
383: }
384:
385: /* (non-Javadoc)
386: * @see org.eclipse.jdt.debug.eval.IAstEvaluationEngine#getCompiledExpression(java.lang.String, org.eclipse.jdt.debug.core.IJavaObject)
387: */
388: public ICompiledExpression getCompiledExpression(String snippet,
389: IJavaObject this Context) {
390: try {
391: if (this Context instanceof IJavaArray) {
392: return getCompiledExpression(snippet,
393: (IJavaArrayType) this Context.getJavaType());
394: }
395: return getCompiledExpression(snippet,
396: (IJavaReferenceType) this Context.getJavaType());
397: } catch (DebugException e) {
398: InstructionSequence expression = new InstructionSequence(
399: snippet);
400: expression.addError(e.getStatus().getMessage());
401: return expression;
402: }
403:
404: }
405:
406: /* (non-Javadoc)
407: * @see org.eclipse.jdt.debug.eval.IAstEvaluationEngine#getCompiledExpression(java.lang.String, org.eclipse.jdt.debug.core.IJavaType)
408: */
409: public ICompiledExpression getCompiledExpression(String snippet,
410: IJavaReferenceType type) {
411: if (type instanceof IJavaArrayType) {
412: return getCompiledExpression(snippet, (IJavaArrayType) type);
413: }
414: IJavaProject javaProject = getJavaProject();
415:
416: EvaluationSourceGenerator mapper = null;
417: CompilationUnit unit = null;
418:
419: mapper = new EvaluationSourceGenerator(new String[0],
420: new String[0], snippet);
421:
422: try {
423: unit = parseCompilationUnit(mapper.getSource(type,
424: javaProject, false).toCharArray(), mapper
425: .getCompilationUnitName(), javaProject);
426: } catch (CoreException e) {
427: InstructionSequence expression = new InstructionSequence(
428: snippet);
429: expression.addError(e.getStatus().getMessage());
430: return expression;
431: }
432: return createExpressionFromAST(snippet, mapper, unit);
433: }
434:
435: /**
436: * Creates a compiled expression for the given snippet using the given mapper and
437: * compilation unit (AST).
438: * @param snippet the code snippet to be compiled
439: * @param mapper the object which will be used to create the expression
440: * @param unit the compilation unit (AST) generated for the snippet
441: */
442: private ICompiledExpression createExpressionFromAST(String snippet,
443: EvaluationSourceGenerator mapper, CompilationUnit unit) {
444: IProblem[] problems = unit.getProblems();
445: if (problems.length != 0) {
446: boolean snippetError = false;
447: boolean runMethodError = false;
448: InstructionSequence errorSequence = new InstructionSequence(
449: snippet);
450: int codeSnippetStart = mapper.getSnippetStart();
451: int codeSnippetEnd = codeSnippetStart
452: + mapper.getSnippet().length();
453: int runMethodStart = mapper.getRunMethodStart();
454: int runMethodEnd = runMethodStart
455: + mapper.getRunMethodLength();
456: for (int i = 0; i < problems.length; i++) {
457: IProblem problem = problems[i];
458: int errorOffset = problem.getSourceStart();
459: int problemId = problem.getID();
460: if (problemId == IProblem.IsClassPathCorrect) {
461: errorSequence.addError(problem.getMessage());
462: snippetError = true;
463: }
464: if (problemId == IProblem.VoidMethodReturnsValue
465: || problemId == IProblem.NotVisibleMethod
466: || problemId == IProblem.NotVisibleConstructor
467: || problemId == IProblem.NotVisibleField
468: || problemId == IProblem.NotVisibleType) {
469: continue;
470: }
471: if (problem.isError()) {
472: if (codeSnippetStart <= errorOffset
473: && errorOffset <= codeSnippetEnd) {
474: errorSequence.addError(problem.getMessage());
475: snippetError = true;
476: } else if (runMethodStart <= errorOffset
477: && errorOffset <= runMethodEnd) {
478: runMethodError = true;
479: }
480: }
481: }
482: if (snippetError || runMethodError) {
483: if (runMethodError) {
484: errorSequence
485: .addError(EvaluationEngineMessages.ASTEvaluationEngine_Evaluations_must_contain_either_an_expression_or_a_block_of_well_formed_statements_1);
486: }
487: return errorSequence;
488: }
489: }
490:
491: ASTInstructionCompiler visitor = new ASTInstructionCompiler(
492: mapper.getSnippetStart(), snippet);
493: unit.accept(visitor);
494:
495: return visitor.getInstructions();
496: }
497:
498: /* (non-Javadoc)
499: * @see org.eclipse.jdt.debug.eval.IEvaluationEngine#getJavaProject()
500: */
501: public IJavaProject getJavaProject() {
502: return fProject;
503: }
504:
505: /* (non-Javadoc)
506: * @see org.eclipse.jdt.debug.eval.IEvaluationEngine#getDebugTarget()
507: */
508: public IJavaDebugTarget getDebugTarget() {
509: return fDebugTarget;
510: }
511:
512: /* (non-Javadoc)
513: * @see org.eclipse.jdt.debug.eval.IEvaluationEngine#dispose()
514: */
515: public void dispose() {
516: }
517:
518: class EvalRunnable implements Runnable {
519:
520: private InstructionSequence fExpression;
521:
522: private IJavaThread fThread;
523:
524: private int fEvaluationDetail;
525:
526: private boolean fHitBreakpoints;
527:
528: private IRuntimeContext fContext;
529:
530: private IEvaluationListener fListener;
531:
532: public EvalRunnable(InstructionSequence expression,
533: IJavaThread thread, IRuntimeContext context,
534: IEvaluationListener listener, int evaluationDetail,
535: boolean hitBreakpoints) {
536: fExpression = expression;
537: fThread = thread;
538: fContext = context;
539: fListener = listener;
540: fEvaluationDetail = evaluationDetail;
541: fHitBreakpoints = hitBreakpoints;
542: }
543:
544: public void run() {
545: EvaluationResult result = new EvaluationResult(
546: ASTEvaluationEngine.this , fExpression.getSnippet(),
547: fThread);
548: if (fExpression.hasErrors()) {
549: String[] errors = fExpression.getErrorMessages();
550: for (int i = 0, numErrors = errors.length; i < numErrors; i++) {
551: result.addError(errors[i]);
552: }
553: evaluationFinished(result);
554: return;
555: }
556: final Interpreter interpreter = new Interpreter(
557: fExpression, fContext);
558:
559: class EvaluationRunnable implements IEvaluationRunnable,
560: ITerminate {
561:
562: CoreException fException;
563:
564: public void run(IJavaThread jt, IProgressMonitor pm) {
565: EventFilter filter = new EventFilter();
566: try {
567: DebugPlugin.getDefault().addDebugEventFilter(
568: filter);
569: interpreter.execute();
570: } catch (CoreException exception) {
571: fException = exception;
572: if (fEvaluationDetail == DebugEvent.EVALUATION
573: && exception.getStatus().getException() instanceof InvocationException) {
574: // print the stack trace for the exception if an *explicit* evaluation
575: InvocationException invocationException = (InvocationException) exception
576: .getStatus().getException();
577: ObjectReference exObject = invocationException
578: .exception();
579: IJavaObject modelObject = (IJavaObject) JDIValue
580: .createValue(
581: (JDIDebugTarget) getDebugTarget(),
582: exObject);
583: try {
584: modelObject
585: .sendMessage(
586: "printStackTrace", "()V", null, jt, false); //$NON-NLS-1$ //$NON-NLS-2$
587: } catch (DebugException e) {
588: // unable to print stack trace
589: }
590: }
591: } finally {
592: DebugPlugin.getDefault()
593: .removeDebugEventFilter(filter);
594: }
595: }
596:
597: public void terminate() {
598: interpreter.stop();
599: }
600:
601: public boolean canTerminate() {
602: return true;
603: }
604:
605: public boolean isTerminated() {
606: return false;
607: }
608:
609: public CoreException getException() {
610: return fException;
611: }
612: }
613:
614: EvaluationRunnable er = new EvaluationRunnable();
615: CoreException exception = null;
616: try {
617: fThread.runEvaluation(er, null, fEvaluationDetail,
618: fHitBreakpoints);
619: } catch (DebugException e) {
620: exception = e;
621: }
622:
623: IJavaValue value = interpreter.getResult();
624:
625: if (exception == null) {
626: exception = er.getException();
627: }
628:
629: if (exception != null) {
630: if (exception instanceof DebugException) {
631: result.setException((DebugException) exception);
632: } else {
633: result.setException(new DebugException(exception
634: .getStatus()));
635: }
636: } else {
637: if (value != null) {
638: result.setValue(value);
639: } else {
640: result
641: .addError(EvaluationEngineMessages.ASTEvaluationEngine_An_unknown_error_occurred_during_evaluation);
642: }
643: }
644:
645: evaluationFinished(result);
646: }
647:
648: private void evaluationFinished(IEvaluationResult result) {
649: // only notify if plug-in not yet shutdown - bug# 8693
650: if (JDIDebugPlugin.getDefault() != null) {
651: fListener.evaluationComplete(result);
652: }
653: }
654:
655: }
656:
657: /**
658: * Replaces references to 'this' with the 'array_this' variable.
659: *
660: * @param snippet code snippet
661: * @return snippet with 'this' references replaced
662: */
663: public static String replaceThisReferences(String snippet) {
664: // replace all occurrences of 'this' with 'array_this'
665: StringBuffer updatedSnippet = new StringBuffer();
666: Matcher matcher = fgThisPattern.matcher(snippet);
667: int start = 0;
668: while (matcher.find()) {
669: int end = matcher.start(2);
670: updatedSnippet.append(snippet.substring(start, end));
671: updatedSnippet
672: .append(ArrayRuntimeContext.ARRAY_THIS_VARIABLE);
673: start = end + 4;
674: }
675: if (start < snippet.length()) {
676: updatedSnippet.append(snippet.substring(start, snippet
677: .length()));
678: }
679: return updatedSnippet.toString();
680: }
681: }
|