1 /******************************************************************************* 2 * Copyright (c) 2005, 2015 IBM Corporation and others. 3 * 4 * This program and the accompanying materials 5 * are made available under the terms of the Eclipse Public License 2.0 6 * which accompanies this distribution, and is available at 7 * https://www.eclipse.org/legal/epl-2.0/ 8 * 9 * SPDX-License-Identifier: EPL-2.0 10 * 11 * Contributors: 12 * IBM Corporation - initial API and implementation 13 * Bjorn Freeman-Benson - initial API and implementation 14 * Wind River Systems - added support for IToggleBreakpointsTargetFactory 15 *******************************************************************************/ 16 package org.eclipse.debug.examples.ui.pda.breakpoints; 17 18 import org.eclipse.core.resources.IResource; 19 import org.eclipse.core.runtime.CoreException; 20 import org.eclipse.debug.core.DebugPlugin; 21 import org.eclipse.debug.core.model.IBreakpoint; 22 import org.eclipse.debug.core.model.ILineBreakpoint; 23 import org.eclipse.debug.examples.core.pda.DebugCorePlugin; 24 import org.eclipse.debug.examples.core.pda.breakpoints.PDALineBreakpoint; 25 import org.eclipse.debug.examples.core.pda.breakpoints.PDAWatchpoint; 26 import org.eclipse.debug.ui.actions.IToggleBreakpointsTargetExtension; 27 import org.eclipse.jface.text.BadLocationException; 28 import org.eclipse.jface.text.IDocument; 29 import org.eclipse.jface.text.IRegion; 30 import org.eclipse.jface.text.ITextSelection; 31 import org.eclipse.jface.viewers.ISelection; 32 import org.eclipse.ui.IWorkbenchPart; 33 import org.eclipse.ui.texteditor.IDocumentProvider; 34 import org.eclipse.ui.texteditor.ITextEditor; 35 36 37 /** 38 * Adapter to create breakpoints in PDA files. 39 */ 40 public class PDABreakpointAdapter implements IToggleBreakpointsTargetExtension { 41 @Override toggleLineBreakpoints(IWorkbenchPart part, ISelection selection)42 public void toggleLineBreakpoints(IWorkbenchPart part, ISelection selection) throws CoreException { 43 ITextEditor textEditor = getEditor(part); 44 if (textEditor != null) { 45 IResource resource = textEditor.getEditorInput().getAdapter(IResource.class); 46 ITextSelection textSelection = (ITextSelection) selection; 47 int lineNumber = textSelection.getStartLine(); 48 IBreakpoint[] breakpoints = DebugPlugin.getDefault().getBreakpointManager().getBreakpoints(DebugCorePlugin.ID_PDA_DEBUG_MODEL); 49 for (int i = 0; i < breakpoints.length; i++) { 50 IBreakpoint breakpoint = breakpoints[i]; 51 if (breakpoint instanceof ILineBreakpoint && resource.equals(breakpoint.getMarker().getResource())) { 52 if (((ILineBreakpoint)breakpoint).getLineNumber() == (lineNumber + 1)) { 53 // remove 54 breakpoint.delete(); 55 return; 56 } 57 } 58 } 59 // create line breakpoint (doc line numbers start at 0) 60 PDALineBreakpoint lineBreakpoint = new PDALineBreakpoint(resource, lineNumber + 1); 61 DebugPlugin.getDefault().getBreakpointManager().addBreakpoint(lineBreakpoint); 62 } 63 } 64 65 @Override canToggleLineBreakpoints(IWorkbenchPart part, ISelection selection)66 public boolean canToggleLineBreakpoints(IWorkbenchPart part, ISelection selection) { 67 return getEditor(part) != null; 68 } 69 70 /** 71 * Returns the editor being used to edit a PDA file, associated with the 72 * given part, or <code>null</code> if none. 73 * 74 * @param part workbench part 75 * @return the editor being used to edit a PDA file, associated with the 76 * given part, or <code>null</code> if none 77 */ getEditor(IWorkbenchPart part)78 private ITextEditor getEditor(IWorkbenchPart part) { 79 if (part instanceof ITextEditor) { 80 ITextEditor editorPart = (ITextEditor) part; 81 IResource resource = editorPart.getEditorInput().getAdapter(IResource.class); 82 if (resource != null) { 83 String extension = resource.getFileExtension(); 84 if (extension != null && extension.equals("pda")) { //$NON-NLS-1$ 85 return editorPart; 86 } 87 } 88 } 89 return null; 90 } 91 92 @Override toggleMethodBreakpoints(IWorkbenchPart part, ISelection selection)93 public void toggleMethodBreakpoints(IWorkbenchPart part, ISelection selection) throws CoreException { 94 } 95 96 @Override canToggleMethodBreakpoints(IWorkbenchPart part, ISelection selection)97 public boolean canToggleMethodBreakpoints(IWorkbenchPart part, ISelection selection) { 98 return false; 99 } 100 101 @Override toggleWatchpoints(IWorkbenchPart part, ISelection selection)102 public void toggleWatchpoints(IWorkbenchPart part, ISelection selection) throws CoreException { 103 String[] variableAndFunctionName = getVariableAndFunctionName(part, selection); 104 if (variableAndFunctionName != null && part instanceof ITextEditor && selection instanceof ITextSelection) { 105 ITextEditor editorPart = (ITextEditor)part; 106 int lineNumber = ((ITextSelection)selection).getStartLine(); 107 IResource resource = editorPart.getEditorInput().getAdapter(IResource.class); 108 String var = variableAndFunctionName[0]; 109 String fcn = variableAndFunctionName[1]; 110 toggleWatchpoint(resource, lineNumber, fcn, var, true, true); 111 } 112 } 113 114 @Override canToggleWatchpoints(IWorkbenchPart part, ISelection selection)115 public boolean canToggleWatchpoints(IWorkbenchPart part, ISelection selection) { 116 return getVariableAndFunctionName(part, selection) != null; 117 } 118 toggleWatchpoint(IResource resource, int lineNumber, String fcn, String var, boolean access, boolean modification)119 protected void toggleWatchpoint(IResource resource, int lineNumber, String fcn, String var, boolean access, 120 boolean modification) throws CoreException 121 { 122 // look for existing watchpoint to delete 123 IBreakpoint[] breakpoints = DebugPlugin.getDefault().getBreakpointManager().getBreakpoints(DebugCorePlugin.ID_PDA_DEBUG_MODEL); 124 for (int i = 0; i < breakpoints.length; i++) { 125 IBreakpoint breakpoint = breakpoints[i]; 126 if (breakpoint instanceof PDAWatchpoint && resource.equals(breakpoint.getMarker().getResource())) { 127 PDAWatchpoint watchpoint = (PDAWatchpoint)breakpoint; 128 String otherVar = watchpoint.getVariableName(); 129 String otherFcn = watchpoint.getFunctionName(); 130 if (otherVar.equals(var) && otherFcn.equals(fcn)) { 131 breakpoint.delete(); 132 return; 133 } 134 } 135 } 136 // create watchpoint 137 PDAWatchpoint watchpoint = new PDAWatchpoint(resource, lineNumber + 1, fcn, var, access, modification); 138 DebugPlugin.getDefault().getBreakpointManager().addBreakpoint(watchpoint); 139 } 140 141 /** 142 * Returns the variable and function names at the current line, or <code>null</code> if none. 143 * 144 * @param part text editor 145 * @param selection text selection 146 * @return the variable and function names at the current line, or <code>null</code> if none. 147 * The array has two elements, the first is the variable name, the second is the function name. 148 */ getVariableAndFunctionName(IWorkbenchPart part, ISelection selection)149 protected String[] getVariableAndFunctionName(IWorkbenchPart part, ISelection selection) { 150 ITextEditor editor = getEditor(part); 151 if (editor != null && selection instanceof ITextSelection) { 152 ITextSelection textSelection = (ITextSelection) selection; 153 IDocumentProvider documentProvider = editor.getDocumentProvider(); 154 try { 155 documentProvider.connect(this); 156 IDocument document = documentProvider.getDocument(editor.getEditorInput()); 157 IRegion region = document.getLineInformationOfOffset(textSelection.getOffset()); 158 String string = document.get(region.getOffset(), region.getLength()).trim(); 159 if (string.startsWith("var ")) { //$NON-NLS-1$ 160 String varName = string.substring(4).trim(); 161 String fcnName = getFunctionName(document, varName, document.getLineOfOffset(textSelection.getOffset())); 162 return new String[] {varName, fcnName}; 163 } 164 } catch (CoreException e) { 165 } catch (BadLocationException e) { 166 } finally { 167 documentProvider.disconnect(this); 168 } 169 } 170 return null; 171 } 172 173 /** 174 * Returns the name of the function containing the given variable defined at the given 175 * line number in the specified document. 176 * 177 * @param document PDA source file 178 * @param varName variable name 179 * @param line line numbner at which the variable is defined 180 * @return name of function defining the variable 181 */ getFunctionName(IDocument document, String varName, int line)182 private String getFunctionName(IDocument document, String varName, int line) { 183 // This is a simple guess at the function name - look for the labels preceeding 184 // the variable definition, and then see if there are any 'calls' to that 185 // label. If none, assumet the variable is in the "_main_" function 186 String source = document.get(); 187 int lineIndex = line - 1; 188 while (lineIndex >= 0) { 189 try { 190 IRegion information = document.getLineInformation(lineIndex); 191 String lineText = document.get(information.getOffset(), information.getLength()); 192 if (lineText.startsWith(":")) { //$NON-NLS-1$ 193 String label = lineText.substring(1); 194 if (source.contains("call " + label)) { //$NON-NLS-1$ 195 return label; 196 } 197 } 198 lineIndex--; 199 } catch (BadLocationException e) { 200 } 201 } 202 return "_main_"; //$NON-NLS-1$ 203 } 204 205 @Override toggleBreakpoints(IWorkbenchPart part, ISelection selection)206 public void toggleBreakpoints(IWorkbenchPart part, ISelection selection) throws CoreException { 207 if (canToggleWatchpoints(part, selection)) { 208 toggleWatchpoints(part, selection); 209 } else { 210 toggleLineBreakpoints(part, selection); 211 } 212 } 213 214 @Override canToggleBreakpoints(IWorkbenchPart part, ISelection selection)215 public boolean canToggleBreakpoints(IWorkbenchPart part, ISelection selection) { 216 return canToggleLineBreakpoints(part, selection) || canToggleWatchpoints(part, selection); 217 } 218 } 219