blob: fb4a0fadd6bfcf5e860a68a17f6852ddefea7562 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2016 xored software, Inc. 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:
* xored software, Inc. - initial API and implementation
*******************************************************************************/
package org.eclipse.dltk.tcl.internal.debug.ui;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.model.IBreakpoint;
import org.eclipse.dltk.core.IField;
import org.eclipse.dltk.core.ISourceRange;
import org.eclipse.dltk.debug.core.model.IScriptVariable;
import org.eclipse.dltk.debug.core.model.IScriptWatchpoint;
import org.eclipse.dltk.debug.ui.DLTKDebugUIPlugin;
import org.eclipse.dltk.debug.ui.actions.ActionMessages;
import org.eclipse.dltk.debug.ui.breakpoints.BreakpointUtils;
import org.eclipse.dltk.debug.ui.breakpoints.IScriptBreakpointLineValidator;
import org.eclipse.dltk.debug.ui.breakpoints.Messages;
import org.eclipse.dltk.debug.ui.breakpoints.ScriptBreakpointLineValidatorFactory;
import org.eclipse.dltk.debug.ui.breakpoints.ScriptToggleBreakpointAdapter;
import org.eclipse.dltk.internal.debug.core.model.ScriptWatchpoint;
import org.eclipse.dltk.internal.ui.text.ScriptWordFinder;
import org.eclipse.dltk.tcl.internal.debug.TclDebugConstants;
import org.eclipse.dltk.tcl.internal.debug.ui.actions.IToggleSpawnpointsTarget;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.window.Window;
import org.eclipse.osgi.util.NLS;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.texteditor.IDocumentProvider;
import org.eclipse.ui.texteditor.ITextEditor;
public class TclToggleBreakpointAdapter extends ScriptToggleBreakpointAdapter
implements IToggleSpawnpointsTarget {
private static final IScriptBreakpointLineValidator validator = ScriptBreakpointLineValidatorFactory
.createNonEmptyNoCommentValidator("#"); //$NON-NLS-1$
@Override
protected String getDebugModelId() {
return TclDebugConstants.DEBUG_MODEL_ID;
}
@Override
protected IScriptBreakpointLineValidator getValidator() {
return validator;
}
public void toggleMethodBreakpoints(IWorkbenchPart part,
ISelection selection) throws CoreException {
// Not implemented for TCL yet
}
public boolean canToggleMethodBreakpoints(IWorkbenchPart part,
ISelection selection) {
return false;
}
public boolean canToggleWatchpoints(IWorkbenchPart part,
ISelection selection) {
if (isRemote(part, selection)) {
return false;
}
if (selection instanceof IStructuredSelection) {
IStructuredSelection ss = (IStructuredSelection) selection;
return isFields(ss);
}
return selection instanceof ITextSelection;
}
public void toggleWatchpoints(final IWorkbenchPart part,
final ISelection finalSelection) throws CoreException {
report(null, part);
ISelection selection = finalSelection;
int lineNumber = -1;
IResource resource = ResourcesPlugin.getWorkspace().getRoot();
IBreakpoint[] breakpoints = DebugPlugin.getDefault()
.getBreakpointManager().getBreakpoints(getDebugModelId());
if (selection instanceof ITextSelection && part instanceof ITextEditor) {
// one based line number
lineNumber = ((ITextSelection) selection).getStartLine() + 1;
resource = BreakpointUtils
.getBreakpointResource((ITextEditor) part);
}
List<?> fields;
if (selection instanceof IStructuredSelection) {
fields = getFields((IStructuredSelection) selection);
} else {
ISelection newSelection = translateToMembers(part, selection);
if (newSelection instanceof IStructuredSelection) {
fields = getFields((IStructuredSelection) newSelection);
} else {
fields = Collections.EMPTY_LIST;
}
}
if (fields.isEmpty() && selection instanceof ITextSelection) {
ITextEditor textEditor = getTextEditor(part);
if (textEditor != null) {
IEditorInput editorInput = textEditor.getEditorInput();
IDocumentProvider documentProvider = textEditor
.getDocumentProvider();
if (documentProvider != null) {
IDocument document = documentProvider
.getDocument(editorInput);
IRegion reg = ScriptWordFinder.findWord(document,
((ITextSelection) selection).getOffset());
final TclAddWatchpointDialog dialog = new TclAddWatchpointDialog(
part.getSite().getShell());
try {
dialog.setExpression(document.get(reg.getOffset(), reg
.getLength()));
} catch (BadLocationException e) {
// ignore
}
if (dialog.open() != Window.OK) {
return;
}
fields = Collections.singletonList(dialog.getExpression());
}
}
}
if (fields.isEmpty()) {
report(ActionMessages.ToggleBreakpointAdapter_10, part);
return;
}
for (Iterator<?> i = fields.iterator(); i.hasNext();) {
final Object element = i.next();
int start = -1;
int end = -1;
final String watchExpression;
if (element instanceof IField) {
final IField field = (IField) element;
final ISourceRange range = field.getNameRange();
start = range.getOffset();
end = range.getOffset() + range.getLength();
watchExpression = field.getElementName();
} else if (element instanceof IScriptVariable) {
watchExpression = ((IScriptVariable) element).getName();
} else if (element instanceof String) {
watchExpression = element.toString();
} else {
continue;
}
boolean found = false;
for (int j = 0; j < breakpoints.length; j++) {
final IBreakpoint breakpoint = breakpoints[j];
if (breakpoint instanceof IScriptWatchpoint
&& breakpoint.getMarker() != null
&& resource
.equals(breakpoint.getMarker().getResource())) {
IScriptWatchpoint wp = (IScriptWatchpoint) breakpoint;
if (wp.getLineNumber() == lineNumber
&& watchExpression.equals(wp.getFieldName())) {
// delete existing breakpoint
breakpoint.delete();
found = true;
}
}
}
if (!found) {
new ScriptWatchpoint(getDebugModelId(), resource, resource
.getType() == IResource.FILE ? resource.getLocation()
: null, lineNumber, start, end, watchExpression);
}
}
}
public void toggleBreakpoints(IWorkbenchPart part, ISelection selection)
throws CoreException {
toggleLineBreakpoints(part, selection);
}
public boolean canToggleBreakpoints(IWorkbenchPart part,
ISelection selection) {
return canToggleLineBreakpoints(part, selection);
}
public boolean canToggleSpawnpoints(IWorkbenchPart part,
ITextSelection selection) {
if (isRemote(part, selection)) {
return false;
}
return true;
}
public void toggleSpawnpoints(final IWorkbenchPart part,
final ITextSelection selection) throws CoreException {
Job job = new Job("Script Toggle Spawnpoint") { //$NON-NLS-1$
@Override
protected IStatus run(IProgressMonitor monitor) {
final ITextEditor editor = getTextEditor(part);
if (editor != null) {
if (monitor.isCanceled()) {
return Status.CANCEL_STATUS;
}
try {
report(null, part);
int lineNumber = selection.getStartLine() + 1;
final IBreakpoint breakpoint = BreakpointUtils
.findLineBreakpoint(editor, lineNumber);
if (breakpoint != null) {
// if breakpoint already exists, delete it
breakpoint.delete();
} else {
final IDocumentProvider documentProvider = editor
.getDocumentProvider();
if (documentProvider == null) {
return Status.CANCEL_STATUS;
}
final IDocument document = documentProvider
.getDocument(editor.getEditorInput());
lineNumber = findBreakpointLine(document,
lineNumber - 1, getValidator()) + 1;
if (lineNumber != BREAKPOINT_LINE_NOT_FOUND) {
// Check if already breakpoint set to the same
// location
if (BreakpointUtils.findLineBreakpoint(editor,
lineNumber) == null) {
BreakpointUtils.addSpawnpoint(editor,
lineNumber);
} else {
final String template = Messages.ScriptToggleBreakpointAdapter_breakpointAlreadySetAtLine;
report(NLS.bind(template, Integer
.toString(lineNumber)), part);
}
} else {
report(
Messages.ScriptToggleBreakpointAdapter_invalidBreakpointPosition,
part);
}
}
} catch (CoreException e) {
DLTKDebugUIPlugin.log(e);
}
}
return Status.OK_STATUS;
}
};
job.setSystem(true);
job.schedule();
}
}