--- debuggercore/api/apichanges.xml:1.6 +++ debuggercore/api/apichanges.xml:1.6 @@ -181,6 +181,25 @@

+ + + Support for stepping over operations. + + + + +

+ Compatile change. +

+
+ +

+ Added fields: + ActionsManager.ACTION_STEP_OPERATION, + This constant is used in action performer which implements an operation step. +

+
+
--- debuggercore/api/manifest.mf:1.13 +++ debuggercore/api/manifest.mf:1.13 @@ -1,5 +1,5 @@ Manifest-Version: 1.0 OpenIDE-Module: org.netbeans.api.debugger/1 OpenIDE-Module-Localizing-Bundle: org/netbeans/api/debugger/Bundle.properties -OpenIDE-Module-Specification-Version: 1.8 +OpenIDE-Module-Specification-Version: 1.9 --- debuggercore/api/src/org/netbeans/api/debugger/ActionsManager.java:1.21 +++ debuggercore/api/src/org/netbeans/api/debugger/ActionsManager.java:1.21 @@ -49,6 +49,9 @@ /** Action constant for Step Out Action. */ public static final Object ACTION_STEP_OUT = "stepOut"; + /** Action constant for Step Operation Action. */ + public static final Object ACTION_STEP_OPERATION = "stepOperation"; + /** Action constant for Continue Action. */ public static final Object ACTION_CONTINUE = "continue"; --- debuggerjpda/api/apichanges.xml:1.17 Wed Aug 30 09:54:18 2006 +++ debuggerjpda/api/apichanges.xml:1.17 Thu Feb 1 10:54:45 2007 @@ -422,6 +422,49 @@ + + + Support for stepping over operations. + + + + + +

+ In order to be able to provide stepping over operations, + we need a representation of an operation and some way how to + retrieve the operation(s) from a Thread and a CallStackFrame. +

+

+ Added fields:
+ JPDAStep.STEP_OPERATION, + EditorContext.CURRENT_LAST_OPERATION_ANNOTATION_TYPE, + EditorContext.CURRENT_EXPRESSION_SECONDARY_LINE_ANNOTATION_TYPE, + EditorContext.CURRENT_EXPRESSION_CURRENT_LINE_ANNOTATION_TYPE +

+

+ Added methods:
+ CallStackFrame.getCurrentOperation(), + JPDAThread.getCurrentOperation(), + JPDAThread.getLastOperations(), + EditorContext.createMethodOperation(), + EditorContext.addNextOperationTo(), + EditorContext.createPosition(), + EditorContext.getOperations() +

+

+ Added classes:
+ EditorContext.BytecodeProvider, + EditorContext.Operation, + EditorContext.Position +

+
+ + + + + +
--- debuggerjpda/api/manifest.mf:1.19 Wed Aug 30 09:51:42 2006 +++ debuggerjpda/api/manifest.mf:1.19 Thu Feb 1 10:54:45 2007 @@ -1,6 +1,6 @@ Manifest-Version: 1.0 OpenIDE-Module: org.netbeans.api.debugger.jpda/2 OpenIDE-Module-Localizing-Bundle: org/netbeans/api/debugger/jpda/Bundle.properties -OpenIDE-Module-Specification-Version: 2.8 +OpenIDE-Module-Specification-Version: 2.9 OpenIDE-Module-Package-Dependencies: com.sun.jdi[VirtualMachineManager] --- debuggerjpda/api/src/org/netbeans/api/debugger/jpda/CallStackFrame.java:1.9 Fri Aug 4 07:18:21 2006 +++ debuggerjpda/api/src/org/netbeans/api/debugger/jpda/CallStackFrame.java:1.9 Thu Jan 18 08:34:29 2007 @@ -22,6 +22,7 @@ import com.sun.jdi.AbsentInformationException; import java.beans.PropertyChangeListener; import java.util.List; +import org.netbeans.spi.debugger.jpda.EditorContext.Operation; /** @@ -43,6 +44,15 @@ * @return line number associated with this this stack frame */ public abstract int getLineNumber (String struts); + + /** + * Returns the current operation (if any) at the location of this call stack frame. + * + * @param struts a language name or null for default language + * @return The operation at the frame location if available and this frame does not + * represent a native method invocation; null otherwise + */ + public abstract Operation getCurrentOperation(String struts); /** * Returns method name associated with this stack frame. --- debuggerjpda/api/src/org/netbeans/api/debugger/jpda/JPDAStep.java:1.3 Fri Jun 30 12:04:47 2006 +++ debuggerjpda/api/src/org/netbeans/api/debugger/jpda/JPDAStep.java:1.3 Fri Jul 21 10:59:11 2006 @@ -44,6 +44,8 @@ public static final int STEP_OUT = StepRequest.STEP_OUT; /** Step to the next location on a different line */ public static final int STEP_LINE = StepRequest.STEP_LINE; + /** Step to the next available operation */ + public static final int STEP_OPERATION = 10; /** Step to the next available location */ public static final int STEP_MIN = StepRequest.STEP_MIN; /** Property fired when the step is executed */ --- debuggerjpda/api/src/org/netbeans/api/debugger/jpda/JPDAThread.java:1.10 Fri Jun 30 12:04:47 2006 +++ debuggerjpda/api/src/org/netbeans/api/debugger/jpda/JPDAThread.java:1.10 Thu Jan 18 08:34:30 2007 @@ -22,6 +22,9 @@ import com.sun.jdi.AbsentInformationException; import com.sun.jdi.ThreadReference; import java.beans.PropertyChangeListener; +import java.util.List; +import org.netbeans.spi.debugger.jpda.EditorContext; +import org.netbeans.spi.debugger.jpda.EditorContext.Operation; /** @@ -82,6 +85,25 @@ * @see CallStackFrame */ public abstract int getLineNumber (String stratum); + + /** + * Returns the operation that is being currently executed on this thread. + * @return The current operation, or null. + * @see {@link CallStackFrame#getCurrentOperation} + */ + public abstract Operation getCurrentOperation(); + + /** + * Returns the list of the last operations, that were performed on this thread. + * Typically just operations from the current expression are stored. + * The thread should be suspended at the moment this method is called. + * + * @return The list of last operations if available, the thread is suspended, + * contains at least one frame and the topmost frame does not + * represent a native method invocation; null otherwise + * @see CallStackFrame + */ + public abstract List getLastOperations(); /** * Returns current state of this thread. --- debuggerjpda/api/src/org/netbeans/spi/debugger/jpda/EditorContext.java:1.9 Fri Jun 30 12:04:49 2006 +++ debuggerjpda/api/src/org/netbeans/spi/debugger/jpda/EditorContext.java:1.9 Thu Jan 18 08:34:30 2007 @@ -19,7 +19,13 @@ package org.netbeans.spi.debugger.jpda; import java.beans.PropertyChangeListener; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; import org.netbeans.api.debugger.jpda.LineBreakpoint; +import org.netbeans.api.debugger.jpda.Variable; /** * Defines bridge to editor and src hierarchy. It allows to use different @@ -41,6 +47,12 @@ public static final String CURRENT_LINE_ANNOTATION_TYPE = "CurrentPC"; /** Annotation type constant. */ public static final String CALL_STACK_FRAME_ANNOTATION_TYPE = "CallSite"; + /** Annotation type constant. */ + public static final String CURRENT_LAST_OPERATION_ANNOTATION_TYPE = "LastOperation"; + /** Annotation type constant. */ + public static final String CURRENT_EXPRESSION_SECONDARY_LINE_ANNOTATION_TYPE = "CurrentExpression"; + /** Annotation type constant. */ + public static final String CURRENT_EXPRESSION_CURRENT_LINE_ANNOTATION_TYPE = "CurrentExpressionLine"; /** Property name constant. */ public static final String PROP_LINE_NUMBER = "lineNumber"; @@ -100,6 +112,27 @@ ); /** + * Adds annotation to given url on given character range. + * + * @param url a url of source annotation should be set into + * @param startPosition the offset of the starting position of the annotation + * @param endPosition the offset of the ending position of the annotation + * @param annotationType a type of annotation to be set + + * @return annotation or null, when the annotation can not be + * created at the given URL or line number. + */ + public Object annotate ( + String url, + int startPosition, + int endPosition, + String annotationType, + Object timeStamp + ) { + return null; + } + + /** * Returns line number given annotation is associated with. * * @param annotation a annotation @@ -207,6 +240,70 @@ public abstract String[] getImports (String url); /** + * Creates an operation which is determined by starting and ending position. + * + protected final Operation createOperation(Position startPosition, + Position endPosition, + int bytecodeIndex) { + return new Operation(startPosition, endPosition, bytecodeIndex); + } + */ + + /** + * Creates a method operation. + * @param startPosition The starting position of the operation + * @param endPosition The ending position of the operation + * @param methodStartPosition The starting position of the method name + * @param methodEndPosition The ending position of the method name + * @param methodName The string representation of the method name + * @param methodClassType The class type, which defines this method + * @param bytecodeIndex The bytecode index of this method call + */ + protected final Operation createMethodOperation(Position startPosition, + Position endPosition, + Position methodStartPosition, + Position methodEndPosition, + String methodName, + String methodClassType, + int bytecodeIndex) { + return new Operation(startPosition, endPosition, + methodStartPosition, methodEndPosition, + methodName, methodClassType, bytecodeIndex); + } + + /** + * Assign a next operation, concatenates operations. + * @param operation The first operation + * @param next The next operation + */ + protected final void addNextOperationTo(Operation operation, Operation next) { + operation.addNextOperation(next); + } + + /** + * Creates a new {@link Position} object. + * @param offset The offset + * @param line The line number + * @param column The column number + */ + protected final Position createPosition( + int offset, int line, int column) { + + return new Position(offset, line, column); + } + + /** + * Get the list of operations that are in expression(s) located at the given line. + * @param url The file's URL + * @param lineNumber The line number + * @param bytecodeProvider The provider of method bytecodes. + */ + public Operation[] getOperations(String url, int lineNumber, + BytecodeProvider bytecodeProvider) { + throw new UnsupportedOperationException("This method is not implemented."); + } + + /** * Adds a property change listener. * * @param l the listener to add @@ -241,5 +338,226 @@ String propertyName, PropertyChangeListener l ); + + /** + * A provider of method bytecode information. + */ + public interface BytecodeProvider { + + /** + * Retrieve the class' constant pool. + */ + byte[] constantPool(); + + /** + * Retrieve the bytecodes of the method. + */ + byte[] byteCodes(); + + /** + * Get an array of bytecode indexes of operations between the starting + * and ending line. + * @param startLine The starting line + * @param endLine The ending line + */ + int[] indexAtLines(int startLine, int endLine); + + } + + /** + * The operation definition. + */ + public static final class Operation { + + private final Position startPosition; + private final Position endPosition; + private final int bytecodeIndex; + + private Position methodStartPosition; + private Position methodEndPosition; + private String methodName; + private String methodClassType; + private Variable returnValue; + + private List nextOperations; + + /* + Operation(Position startPosition, Position endPosition, + int bytecodeIndex) { + this.startPosition = startPosition; + this.endPosition = endPosition; + this.bytecodeIndex = bytecodeIndex; + } + */ + + /** + * Creates a new method operation. + */ + Operation(Position startPosition, Position endPosition, + Position methodStartPosition, Position methodEndPosition, + String methodName, String methodClassType, + int bytecodeIndex) { + this.startPosition = startPosition; + this.endPosition = endPosition; + this.bytecodeIndex = bytecodeIndex; + this.methodStartPosition = methodStartPosition; + this.methodEndPosition = methodEndPosition; + this.methodName = methodName; + this.methodClassType = methodClassType; + } + + synchronized void addNextOperation(Operation next) { + if (nextOperations == null) { + nextOperations = new ArrayList(); + } + nextOperations.add(next); + } + + /** + * Get the starting position of this operation. + */ + public Position getStartPosition() { + return startPosition; + } + + /** + * Get the ending position of this operation. + */ + public Position getEndPosition() { + return endPosition; + } + + /** + * Get the starting position of the method call of this operation. + */ + public Position getMethodStartPosition() { + return methodStartPosition; + } + + /** + * Get the ending position of the method call of this operation. + */ + public Position getMethodEndPosition() { + return methodEndPosition; + } + + /** + * Get the method name. + */ + public String getMethodName() { + return methodName; + } + + /** + * Get the class type declaring the method. + */ + public String getMethodClassType() { + return methodClassType; + } + + /** + * Get the bytecode index of this operation. + */ + public int getBytecodeIndex() { + return bytecodeIndex; + } + + /** + * Set the return value of this operation. + */ + public void setReturnValue(Variable returnValue) { + this.returnValue = returnValue; + } + + /** + * Get the return value of this operation. + */ + public Variable getReturnValue() { + return returnValue; + } + + /** + * Get the list of following operations. + */ + public List getNextOperations() { + if (nextOperations == null) { + return Collections.emptyList(); + } else { + synchronized (this) { + return Collections.unmodifiableList(nextOperations); + } + } + } + + public boolean equals(Object obj) { + if (obj instanceof Operation) { + Operation op2 = (Operation) obj; + return bytecodeIndex == op2.bytecodeIndex && + ((startPosition == null) ? + op2.startPosition == null : + startPosition.equals(op2.startPosition)) && + ((endPosition == null) ? + op2.endPosition == null : + endPosition.equals(op2.endPosition)); + } + return false; + } + + public int hashCode() { + return bytecodeIndex; + } + + } + + /** + * Representation of a position in a source code. + */ + public static final class Position { + + private final int offset; + private final int line; + private final int column; + + Position(int offset, int line, int column) { + this.offset = offset; + this.line = line; + this.column = column; + } + + /** + * Get the offset of this position. + */ + public int getOffset() { + return offset; + } + + /** + * Get the line number of this position. + */ + public int getLine() { + return line; + } + + /** + * Get the column number of this position. + */ + public int getColumn() { + return column; + } + + public boolean equals(Object obj) { + if (obj instanceof Position) { + Position pos = (Position) obj; + return pos.offset == offset; + } + return false; + } + + public int hashCode() { + return offset; + } + + } + }