Skip to content

Commit

Permalink
Add support for creating watchpoints from Groovy Editor's vertical ruler
Browse files Browse the repository at this point in the history
  • Loading branch information
eric-milles committed Apr 13, 2018
1 parent b9cd2e7 commit f6e50db
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 65 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package org.codehaus.groovy.eclipse.test.debug

import org.codehaus.groovy.ast.ASTNode
import org.codehaus.groovy.ast.ConstructorNode
import org.codehaus.groovy.ast.FieldNode
import org.codehaus.groovy.ast.MethodNode
import org.codehaus.groovy.eclipse.debug.ui.BreakpointLocationFinder
import org.codehaus.groovy.eclipse.test.GroovyEclipseTestSuite
Expand Down Expand Up @@ -301,15 +302,16 @@ final class BreakpointLocationTests extends GroovyEclipseTestSuite {
assert node?.lineNumber == 3
}

@Test
@Test // TODO: Should line breakpoint be created for closure body instead of watchpoint for field?
void testBreakpointInClass8() {
def node = findBreakpointLocation 'here()', '''\
class Class {
def t = { here() }
}
'''.stripIndent()

assert node?.lineNumber == 2
assert node instanceof FieldNode
assert node.lineNumber == 2
}

@Test
Expand All @@ -320,7 +322,21 @@ final class BreakpointLocationTests extends GroovyEclipseTestSuite {
}
'''.stripIndent()

assert node == null
assert node instanceof FieldNode
assert node.lineNumber == 2
}

@Test
void testBreakpointInClass9a() {
def node = findBreakpointLocation 'field', '''\
import groovy.transform.PackageScope
class Class {
@PackageScope String field
}
'''.stripIndent()

assert node instanceof FieldNode
assert node.lineNumber == 3
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@

import org.codehaus.groovy.antlr.LocationSupport;
import org.codehaus.groovy.ast.ASTNode;
import org.codehaus.groovy.ast.AnnotatedNode;
import org.codehaus.groovy.ast.AnnotationNode;
import org.codehaus.groovy.ast.FieldNode;
import org.codehaus.groovy.ast.MethodNode;
import org.codehaus.groovy.ast.ModuleNode;
import org.codehaus.groovy.ast.expr.ClosureExpression;
Expand Down Expand Up @@ -61,6 +63,14 @@ public void visitMethod(MethodNode method) {
super.visitMethod(method);
}

@Override
public void visitField(FieldNode field) {
if (field.getLineNumber() > 0) {
nodes.add(field);
}
super.visitField(field);
}

}.visitModule(module);

this.nodes = Collections.unmodifiableSet(nodes);
Expand Down Expand Up @@ -88,9 +98,9 @@ public ASTNode findBreakpointLocation(int lineNumber) {
}

protected int lineNumber(ASTNode node) {
if (locator != null && node instanceof MethodNode) {
if (locator != null && (node instanceof MethodNode || node instanceof FieldNode)) {
// annotations, modifiers and generics may be on separate line(s)
int[] row_col = locator.getRowCol(((MethodNode) node).getNameStart());
int[] row_col = locator.getRowCol(((AnnotatedNode) node).getNameStart());
if (row_col != null && row_col.length > 0) {
return row_col[0];
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@
import java.util.HashMap;
import java.util.Map;

import org.codehaus.groovy.antlr.LocationSupport;
import org.codehaus.groovy.ast.ASTNode;
import org.codehaus.groovy.ast.ClassNode;
import org.codehaus.groovy.ast.FieldNode;
import org.codehaus.groovy.ast.MethodNode;
import org.codehaus.groovy.ast.ModuleNode;
import org.eclipse.core.resources.IResource;
Expand All @@ -31,12 +32,11 @@
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.debug.core.IJavaLineBreakpoint;
import org.eclipse.jdt.debug.core.JDIDebugModel;
import org.eclipse.jdt.groovy.search.VariableScope;
import org.eclipse.jdt.groovy.core.util.GroovyUtils;
import org.eclipse.jdt.internal.debug.ui.BreakpointUtils;
import org.eclipse.jdt.internal.debug.ui.JDIDebugUIPlugin;
import org.eclipse.jdt.internal.debug.ui.actions.ActionMessages;
Expand Down Expand Up @@ -92,6 +92,11 @@ public BreakpointLocationVerifierJob(IJavaLineBreakpoint breakpoint, int lineNum
fEditorPart = editorPart;
}

@Override
public boolean belongsTo(Object family) {
return (family == FAMILY);
}

@Override
public IStatus run(IProgressMonitor monitor) {
try {
Expand All @@ -102,11 +107,14 @@ public IStatus run(IProgressMonitor monitor) {
ModuleNode module = Adapters.adapt(fEditorPart, ModuleNode.class);
if (module != null) {
ASTNode found = new BreakpointLocationFinder(module).findBreakpointLocation(fLineNumber);
if (found instanceof MethodNode && ((MethodNode) found).getNameEnd() > 0) {
createNewMethodBreakpoint((MethodNode) found, fTypeName);
return new Status(IStatus.OK, JDIDebugUIPlugin.getUniqueIdentifier(), ActionMessages.BreakpointLocationVerifierJob_breakpoint_set);
if (found instanceof FieldNode && ((FieldNode) found).getNameEnd() > 0) {
createNewFieldBreakpoint((FieldNode) found, module.getNodeMetaData(LocationSupport.class));
} else if (found instanceof MethodNode && ((MethodNode) found).getNameEnd() > 0) {
createNewMethodBreakpoint((MethodNode) found, module.getNodeMetaData(LocationSupport.class));
} else if (found != null) {
createNewLineBreakpoint(found, fTypeName);
createNewLineBreakpoint(found);
}
if (found != null) {
return new Status(IStatus.OK, JDIDebugUIPlugin.getUniqueIdentifier(), ActionMessages.BreakpointLocationVerifierJob_breakpoint_set);
}
}
Expand All @@ -119,49 +127,47 @@ public IStatus run(IProgressMonitor monitor) {
return new Status(IStatus.OK, JDIDebugUIPlugin.getUniqueIdentifier(), ActionMessages.BreakpointLocationVerifierJob_not_valid_location);
}

private void createNewMethodBreakpoint(MethodNode node, String typeName) throws CoreException {
Map<String, Object> newAttributes = new HashMap<>(10);
int start = node.getNameStart();
int end = node.getNameEnd();
private void createNewFieldBreakpoint(FieldNode node, LocationSupport locator) throws CoreException {
if (fType != null) {
IJavaElement elt = fType.getTypeRoot().getElementAt(start);
if (elt != null) {
IMethod method = (IMethod) elt;
BreakpointUtils.addJavaBreakpointAttributesWithMemberDetails(newAttributes, fType, start, end);
BreakpointUtils.addJavaBreakpointAttributes(newAttributes, method);
JDIDebugModel.createMethodBreakpoint(fResource, typeName, node.getName(), createMethodSignature(node), true, false, false, node.getLineNumber(), start, end, 0, true, newAttributes);
int start = node.getNameStart(), end = node.getNameEnd();
IJavaElement elem = fType.getTypeRoot().getElementAt(start);
if (elem != null) {
int lineNumber = locator.getRowCol(start)[0];
Map<String, Object> attributes = new HashMap<>();
BreakpointUtils.addJavaBreakpointAttributes(attributes, elem);
BreakpointUtils.addJavaBreakpointAttributesWithMemberDetails(attributes, fType, start, end);
JDIDebugModel.createWatchpoint(fResource, fTypeName, node.getName(), lineNumber, start, end, 0, true, attributes);
}
}
}

private String createMethodSignature(MethodNode node) {
String returnType = createTypeSignatureStr(node.getReturnType());
String[] parameterTypes = new String[node.getParameters().length];
for (int i = 0, n = parameterTypes.length; i < n; i += 1) {
parameterTypes[i] = createTypeSignatureStr(node.getParameters()[i].getType());
private void createNewMethodBreakpoint(MethodNode node, LocationSupport locator) throws CoreException {
if (fType != null) {
int start = node.getNameStart(), end = node.getNameEnd();
IJavaElement elem = fType.getTypeRoot().getElementAt(start);
if (elem != null) {
int lineNumber = locator.getRowCol(start)[0];
Map<String, Object> attributes = new HashMap<>();
BreakpointUtils.addJavaBreakpointAttributes(attributes, elem);
BreakpointUtils.addJavaBreakpointAttributesWithMemberDetails(attributes, fType, start, end);
JDIDebugModel.createMethodBreakpoint(fResource, fTypeName, node.getName(), createMethodSignature(node), true, false, false, lineNumber, start, end, 0, true, attributes);
}
}
return Signature.createMethodSignature(parameterTypes, returnType).replace('.', '/');
}

private String createTypeSignatureStr(ClassNode node) {
if (node == null) {
node = VariableScope.OBJECT_CLASS_NODE;
}
String name = node.getName();
if (name.startsWith("[")) {
return name;
} else {
return Signature.createTypeSignature(name, true);
}
private String createMethodSignature(MethodNode node) {
String[] parameterTypes = GroovyUtils.getParameterTypeSignatures(node, true);
String returnType = GroovyUtils.getTypeSignature(node.getReturnType(), true, true);
return Signature.createMethodSignature(parameterTypes, returnType).replace('.', '/');
}

/**
* Create a new breakpoint at the right position.
*/
private void createNewLineBreakpoint(ASTNode node, String typeName) throws CoreException {
private void createNewLineBreakpoint(ASTNode node) throws CoreException {
// check to make sure that breakpoint doesn't exist on this line
// line may have moved by the validator
if (JDIDebugModel.lineBreakpointExists(typeName, node.getLineNumber()) != null) {
if (JDIDebugModel.lineBreakpointExists(fTypeName, node.getLineNumber()) != null) {
return;
}
Map<String, Object> newAttributes = new HashMap<>(10);
Expand All @@ -170,10 +176,10 @@ private void createNewLineBreakpoint(ASTNode node, String typeName) throws CoreE
if (fType != null) {
BreakpointUtils.addJavaBreakpointAttributesWithMemberDetails(newAttributes, fType, start, end);
}
JDIDebugModel.createLineBreakpoint(fResource, typeName, node.getLineNumber(), start, end, 0, true, newAttributes);
JDIDebugModel.createLineBreakpoint(fResource, fTypeName, node.getLineNumber(), start, end, 0, true, newAttributes);
}

protected void report(final String message) {
private void report(final String message) {
JDIDebugUIPlugin.getStandardDisplay().asyncExec(() -> {
IEditorStatusLine statusLine = Adapters.adapt(fEditorPart, IEditorStatusLine.class);
if (statusLine != null) {
Expand All @@ -184,9 +190,4 @@ protected void report(final String message) {
}
});
}

@Override
public boolean belongsTo(Object family) {
return family == FAMILY;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -91,39 +91,30 @@ public ToggleBreakpointAdapter() {

@Override
public boolean canToggleBreakpoints(IWorkbenchPart part, ISelection selection) {
return canToggleLineBreakpoints(part, selection);
return (selection instanceof ITextSelection);
}

@Override
public boolean canToggleLineBreakpoints(IWorkbenchPart part, ISelection selection) {
return selection instanceof ITextSelection;
return canToggleBreakpoints(part, selection);
}

@Override
public boolean canToggleMethodBreakpoints(IWorkbenchPart part, ISelection selection) {
return false;
return canToggleBreakpoints(part, selection);
}

@Override
public boolean canToggleWatchpoints(IWorkbenchPart part, ISelection selection) {
return false;
return canToggleBreakpoints(part, selection);
}

@Override
public void toggleBreakpoints(IWorkbenchPart part, ISelection selection) throws CoreException {
toggleLineBreakpoints(part, selection, true);
}

@Override
public void toggleLineBreakpoints(IWorkbenchPart part, ISelection selection) throws CoreException {
toggleLineBreakpoints(part, selection, false);
}

public void toggleLineBreakpoints(IWorkbenchPart part, ISelection selection, boolean bestMatch) {
Job job = new Job("Toggle Line Breakpoint") {
public void toggleBreakpoints(IWorkbenchPart part, ISelection selection) {
Job job = new Job("Toggle Breakpoint") {
@Override
public boolean belongsTo(Object family) {
return family == TOGGLE_BREAKPOINT_FAMILY;
return (family == TOGGLE_BREAKPOINT_FAMILY);
}
@Override
protected IStatus run(IProgressMonitor monitor) {
Expand Down Expand Up @@ -235,11 +226,22 @@ protected IStatus run(IProgressMonitor monitor) {
}

@Override
public void toggleMethodBreakpoints(IWorkbenchPart part, ISelection finalSelection) {
public void toggleLineBreakpoints(IWorkbenchPart part, ISelection selection) {
toggleBreakpoints(part, selection);
}

public void toggleLineBreakpoints(IWorkbenchPart part, ISelection selection, boolean bestMatch) {
toggleBreakpoints(part, selection);
}

@Override
public void toggleMethodBreakpoints(IWorkbenchPart part, ISelection selection) {
toggleBreakpoints(part, selection);
}

@Override
public void toggleWatchpoints(IWorkbenchPart part, ISelection finalSelection) {
public void toggleWatchpoints(IWorkbenchPart part, ISelection selection) {
toggleBreakpoints(part, selection);
}

//--------------------------------------------------------------------------
Expand Down

0 comments on commit f6e50db

Please sign in to comment.