/******************************************************************************* * Copyright (c) 2011, 2016 Mentor Graphics 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: * Mentor Graphics - Initial API and implementation * Marc Khouzam (Ericsson) - Don't allow to set two bps at same line (bug 432503) * Teodor Madan (Freescale) - Do not create multiple watchpoints /method breakpoints at same location ( 445375 ) * Jonah Graham (Kichwa Coders) - Create "Add Line Breakpoint (C/C++)" action (Bug 464917) *******************************************************************************/ package org.eclipse.cdt.debug.ui.breakpoints; import java.math.BigInteger; import java.util.Iterator; import java.util.Map; import org.eclipse.cdt.core.model.CModelException; import org.eclipse.cdt.core.model.CoreModel; import org.eclipse.cdt.core.model.ICElement; import org.eclipse.cdt.core.model.IDeclaration; import org.eclipse.cdt.core.model.IFunction; import org.eclipse.cdt.core.model.IFunctionDeclaration; import org.eclipse.cdt.core.model.IMethod; import org.eclipse.cdt.core.model.ISourceRange; import org.eclipse.cdt.core.model.ITranslationUnit; import org.eclipse.cdt.core.model.IVariable; import org.eclipse.cdt.debug.core.ICWatchpointTarget; import org.eclipse.cdt.debug.core.model.ICBreakpoint; import org.eclipse.cdt.debug.core.model.ICFunctionBreakpoint; import org.eclipse.cdt.debug.core.model.ICLineBreakpoint; import org.eclipse.cdt.debug.core.model.ICWatchpoint; import org.eclipse.cdt.debug.internal.core.CRequest; import org.eclipse.cdt.debug.internal.ui.CDebugUIUtils; import org.eclipse.cdt.debug.internal.ui.IInternalCDebugUIConstants; import org.eclipse.cdt.debug.internal.ui.actions.ActionMessages; import org.eclipse.cdt.debug.internal.ui.actions.breakpoints.EnableDisableBreakpointRulerAction; import org.eclipse.cdt.debug.internal.ui.breakpoints.CBreakpointContext; import org.eclipse.cdt.debug.ui.CDebugUIPlugin; import org.eclipse.cdt.internal.ui.util.EditorUtility; import org.eclipse.cdt.internal.ui.util.ExternalEditorInput; import org.eclipse.cdt.ui.CDTUITools; import org.eclipse.core.filesystem.URIUtil; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.debug.core.DebugException; import org.eclipse.debug.core.DebugPlugin; import org.eclipse.debug.core.model.IBreakpoint; import org.eclipse.debug.core.model.IMemoryBlock; import org.eclipse.debug.core.model.IMemoryBlockExtension; import org.eclipse.debug.core.model.MemoryByte; import org.eclipse.debug.ui.DebugUITools; import org.eclipse.debug.ui.actions.IToggleBreakpointsTargetExtension2; import org.eclipse.debug.ui.memory.IRepositionableMemoryRendering; import org.eclipse.jface.preference.PreferenceDialog; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.ITextSelection; import org.eclipse.jface.text.Position; import org.eclipse.jface.text.source.Annotation; import org.eclipse.jface.text.source.IAnnotationModel; import org.eclipse.jface.text.source.IVerticalRulerInfo; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Event; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.IFileEditorInput; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.dialogs.PreferencesUtil; import org.eclipse.ui.editors.text.ILocationProvider; import org.eclipse.ui.progress.WorkbenchJob; import org.eclipse.ui.texteditor.IEditorStatusLine; import org.eclipse.ui.texteditor.ITextEditor; import org.eclipse.ui.texteditor.SimpleMarkerAnnotation; /** * Base class for toggle adapter to create/remove CDT breakpoints. Clients may * extend this class to gather additional data prior to creating the breakpoints. * * @since 7.2 */ abstract public class AbstractToggleBreakpointAdapter implements IToggleBreakpointsTargetExtension2, IToggleBreakpointsTargetCExtension { @Override public boolean canToggleBreakpointsWithEvent(IWorkbenchPart part, ISelection selection, Event event) { return canToggleBreakpoints(part, selection); } @Override public void toggleBreakpointsWithEvent(IWorkbenchPart part, ISelection selection, Event event) throws CoreException { if(event != null && (event.stateMask & SWT.MOD2) > 0) { if (toggleBreakpointEnable(part)) { return; } } else { boolean interactive = event != null && (event.stateMask & SWT.MOD1) > 0; updateBreakpoints(true, interactive, part, selection); } } @Override public void toggleLineBreakpoints( IWorkbenchPart part, ISelection selection ) throws CoreException { updateLineBreakpoints(true, false, part, selection); } @Override public boolean canToggleLineBreakpoints( IWorkbenchPart part, ISelection selection ) { return (selection instanceof ITextSelection); } @Override public void toggleMethodBreakpoints( IWorkbenchPart part, ISelection selection ) throws CoreException { ICElement element = getCElementFromSelection( part, selection ); if ( element instanceof IFunction || element instanceof IMethod) { updateMethodBreakpoints(true, false, part, (IDeclaration)element); } } @Override public boolean canToggleMethodBreakpoints( IWorkbenchPart part, ISelection selection ) { ICElement element = getCElementFromSelection( part, selection ); return (element instanceof IFunction || element instanceof IMethod); } @Override public void toggleWatchpoints( IWorkbenchPart part, ISelection selection ) throws CoreException { IVariable variable = getVariableFromSelection( part, selection ); if ( variable != null ) { updateVariableWatchpoint(true, false, part, variable); } IRepositionableMemoryRendering rendering = getMemoryRendering(part, selection); if (rendering != null) { updateMemoryWatchpoint(true, false, part, rendering); } } @Override public boolean canToggleWatchpoints( IWorkbenchPart part, ISelection selection ) { return getVariableFromSelection( part, selection ) != null || getMemoryRendering(part, selection) != null || getWatchpointTarget(part, selection) != null; } @Override public boolean canToggleBreakpoints( IWorkbenchPart part, ISelection selection ) { return ( canToggleLineBreakpoints( part, selection ) || canToggleWatchpoints( part, selection ) || canToggleMethodBreakpoints( part, selection ) ); } @Override public void toggleBreakpoints( IWorkbenchPart part, ISelection selection ) throws CoreException { updateBreakpoints(true, false, part, selection); } @Override public boolean canCreateLineBreakpointsInteractive(IWorkbenchPart part, ISelection selection) { return canToggleLineBreakpoints( part, selection ) && !hasBreakpoint( part ); } @Override public void createLineBreakpointsInteractive(IWorkbenchPart part, ISelection selection) throws CoreException { updateLineBreakpoints(false, true, part, selection); } @Override public boolean canCreateWatchpointsInteractive(IWorkbenchPart part, ISelection selection) { return canToggleWatchpoints(part, selection) && !hasWatchpoint(part, selection); } @Override public void createWatchpointsInteractive(IWorkbenchPart part, ISelection selection) throws CoreException { ICElement element = getCElementFromSelection( part, selection ); if (element instanceof IVariable) { updateVariableWatchpoint(false, true, part, (IVariable)element); return; } IRepositionableMemoryRendering rendering = getMemoryRendering(part, selection); if (rendering != null) { updateMemoryWatchpoint(false, true, part, rendering); return; } ICWatchpointTarget watchpointTarget = getWatchpointTarget(part, selection); if (watchpointTarget != null) { updateTargetWatchpoint(false, true, part, watchpointTarget); return; } String text = ""; //$NON-NLS-1$ if (selection instanceof ITextSelection) { text = ((ITextSelection)selection).getText(); } createWatchpoint(true, part, null, ResourcesPlugin.getWorkspace().getRoot(), -1, -1, -1, text, null, "0"); //$NON-NLS-1$ } @Override public boolean canCreateEventBreakpointsInteractive(IWorkbenchPart part, ISelection selection) { return true; } @Override public void createEventBreakpointsInteractive(IWorkbenchPart part, ISelection selection) throws CoreException { String type = ""; //$NON-NLS-1$ String arg = ""; //$NON-NLS-1$ createEventBreakpoint( true, part, ResourcesPlugin.getWorkspace().getRoot(), type, arg ); } @Override public boolean canCreateFunctionBreakpointInteractive(IWorkbenchPart part, ISelection selection) { return canToggleMethodBreakpoints(part, selection) && !hasMethodBreakpoints(part, selection); } @Override public void createFunctionBreakpointInteractive(IWorkbenchPart part, ISelection selection) throws CoreException { ICElement element = getCElementFromSelection( part, selection ); if ( element instanceof IFunction || element instanceof IMethod ) { updateMethodBreakpoints(false, true, part, (IDeclaration)element); } else { String text = ""; //$NON-NLS-1$ if (selection instanceof ITextSelection) { text = ((ITextSelection)selection).getText(); } createFunctionBreakpoint(true, part, null, ResourcesPlugin.getWorkspace().getRoot(), text, -1, -1, -1); } } private boolean hasBreakpoint(IWorkbenchPart part) { if (part instanceof ITextEditor) { ITextEditor textEditor = (ITextEditor) part; IVerticalRulerInfo rulerInfo = textEditor.getAdapter(IVerticalRulerInfo.class); IBreakpoint breakpoint = CDebugUIUtils.getBreakpointFromEditor(textEditor, rulerInfo); return breakpoint != null; } return false; } private boolean hasWatchpoint(IWorkbenchPart part, ISelection selection) { ICElement element = getCElementFromSelection( part, selection ); if (element instanceof IVariable) { IVariable variable = (IVariable) element; String sourceHandle = getSourceHandle(variable ); IResource resource = getElementResource(variable); String expression = getVariableName(variable); try { return null != findWatchpoint(sourceHandle, resource, expression); } catch (CoreException e) { DebugPlugin.log(e); } } return false; } private boolean hasMethodBreakpoints(IWorkbenchPart part, ISelection selection) { ICElement element = getCElementFromSelection( part, selection ); if ( element instanceof IFunction || element instanceof IMethod ) { IDeclaration declaration = (IDeclaration) element; String sourceHandle = getSourceHandle(declaration); IResource resource = getElementResource(declaration); String functionName = (declaration instanceof IFunction) ? getFunctionName((IFunction) declaration) : getMethodName((IMethod) declaration); try { return null != findFunctionBreakpoint(sourceHandle, resource, functionName); } catch (CoreException e) { DebugPlugin.log(e); } } return false; } /** * Updates the breakpoint for given part and selection. * Depending on the flags and on whether a breakpoint exists, this method * executes the toggle action. * * @param toggle Whether the toggle action is requested. If * true and the breakpoint currently exists, it will cause the * toggle action to either remove breakpoint or edit its properties. * Otherwise a new breakpoint will be created. * @param interactive If true the toggle adapter should open a dialog before * creating a breakpoint, or open a properties dialog on an existing * breakpoint. * @param part Workbench part where the toggle action is to be executed. * @param selection Current selection on which the toggle action is to be * executed. * @throws CoreException Any error in creating or editing the breakpoint. */ private void updateBreakpoints(boolean toggle, boolean interactive, IWorkbenchPart part, ISelection selection ) throws CoreException { if ( canToggleLineBreakpoints( part, selection ) ) { updateLineBreakpoints(toggle, interactive, part, selection); } else { ICElement element = getCElementFromSelection( part, selection ); if ( element instanceof IFunction || element instanceof IMethod ) { updateMethodBreakpoints(toggle, interactive, part, (IDeclaration)element); } else if ( element instanceof IVariable ) { updateVariableWatchpoint(toggle, interactive, part, (IVariable)element); } } } private void updateLineBreakpoints(boolean toggle, boolean interactive, IWorkbenchPart part, ISelection selection) throws CoreException { String errorMessage = null; if (part instanceof ITextEditor) { ITextEditor textEditor = (ITextEditor) part; IEditorInput input = textEditor.getEditorInput(); if (input == null) { errorMessage = ActionMessages.getString("ToggleBreakpointAdapter.Empty_editor_1"); //$NON-NLS-1$ } else { IDocument document = textEditor.getDocumentProvider().getDocument(input); if (document == null) { errorMessage = ActionMessages.getString("ToggleBreakpointAdapter.Missing_document_1"); //$NON-NLS-1$ } else { IResource resource = getResource(textEditor); if (resource == null) { errorMessage = ActionMessages.getString("ToggleBreakpointAdapter.Missing_resource_1"); //$NON-NLS-1$ } else { int lineNumber = ((ITextSelection) selection).getStartLine() + 1; if (lineNumber == -1) { errorMessage = ActionMessages.getString("ToggleBreakpointAdapter.Invalid_line_1"); //$NON-NLS-1$ } else { String sourceHandle = getSourceHandle(input); if (interactive && !toggle) { createLineBreakpoint(true, part, sourceHandle, resource, lineNumber); } else { ICLineBreakpoint breakpoint = findLineBreakpoint(sourceHandle, resource, lineNumber); if (breakpoint != null) { if (interactive) { CDebugUIUtils.editBreakpointProperties(part, breakpoint); } else { DebugPlugin.getDefault().getBreakpointManager() .removeBreakpoint(breakpoint, true); } } else { createLineBreakpoint(interactive, part, sourceHandle, resource, lineNumber); } } return; } } } } } else if (interactive && !toggle) { createLineBreakpoint(true, part, null, ResourcesPlugin.getWorkspace().getRoot(), -1); return; } else { errorMessage = ActionMessages.getString("RunToLineAdapter.Operation_is_not_supported_1"); //$NON-NLS-1$ } throw new CoreException(new Status(IStatus.ERROR, CDebugUIPlugin.getUniqueIdentifier(), IInternalCDebugUIConstants.INTERNAL_ERROR, errorMessage, null)); } private void updateMethodBreakpoints(boolean toggle, boolean interactive, IWorkbenchPart part, IDeclaration declaration) throws CoreException { String sourceHandle = getSourceHandle(declaration); IResource resource = getElementResource(declaration); String functionName = (declaration instanceof IFunction) ? getFunctionName((IFunction) declaration) : getMethodName((IMethod) declaration); ICFunctionBreakpoint breakpoint = findFunctionBreakpoint(sourceHandle, resource, functionName); if (toggle && breakpoint != null) { if (interactive) { CDebugUIUtils.editBreakpointProperties(part, breakpoint); } else { DebugPlugin.getDefault().getBreakpointManager().removeBreakpoint(breakpoint, true); } } else { int lineNumber = -1; int charStart = -1; int charEnd = -1; try { ISourceRange sourceRange = declaration.getSourceRange(); if (sourceRange != null) { charStart = sourceRange.getStartPos(); charEnd = charStart + sourceRange.getLength(); if (charEnd <= 0) { charStart = -1; charEnd = -1; } lineNumber = sourceRange.getStartLine(); } } catch (CModelException e) { DebugPlugin.log(e); } createFunctionBreakpoint(interactive, part, sourceHandle, resource, functionName, charStart, charEnd, lineNumber); } } /** * Updates a watchpoint. Depending on the flags and on whether a breakpoint * exists, this method executes the toggle action. * * @param toggle * Whether the toggle action is requested. If true and the * breakpoint currently exists, it will cause the toggle action * to either remove breakpoint or edit its properties. Otherwise * a new breakpoint will be created. * @param interactive * If true the toggle adapter should open a dialog before * creating a breakpoint, or open a properties dialog on an * existing breakpoint. * @param part * Workbench part where the toggle action is to be executed. * @param selection * Variable on which to execute the toggle action. * @throws CoreException * Any error in creating or editing the breakpoint. */ private void updateVariableWatchpoint(boolean toggle, boolean interactive, IWorkbenchPart part, IVariable variable) throws CoreException { String sourceHandle = getSourceHandle(variable); IResource resource = getElementResource(variable); String expression = getVariableName(variable); ICWatchpoint watchpoint = findWatchpoint(sourceHandle, resource, expression); if (toggle && watchpoint != null) { if (interactive) { CDebugUIUtils.editBreakpointProperties(part, watchpoint); } else { DebugPlugin.getDefault().getBreakpointManager().removeBreakpoint(watchpoint, true); } } else { int lineNumber = -1; int charStart = -1; int charEnd = -1; try { ISourceRange sourceRange = variable.getSourceRange(); if (sourceRange != null) { charStart = sourceRange.getStartPos(); charEnd = charStart + sourceRange.getLength(); if (charEnd <= 0) { charStart = -1; charEnd = -1; } lineNumber = sourceRange.getStartLine(); } } catch (CModelException e) { CDebugUIPlugin.log(e); } createWatchpoint(interactive, part, sourceHandle, resource, charStart, charEnd, lineNumber, expression, null, "0"); //$NON-NLS-1$ } } private void updateMemoryWatchpoint(boolean toggle, boolean interactive, IWorkbenchPart part, IRepositionableMemoryRendering rendering) throws CoreException { int addressableSize = 1; IMemoryBlock memblock = rendering.getMemoryBlock(); if (memblock instanceof IMemoryBlockExtension) { try { addressableSize = ((IMemoryBlockExtension)memblock).getAddressableSize(); } catch (DebugException e) { CDebugUIPlugin.log(e); } } String memorySpace = getMemorySpace(rendering.getMemoryBlock(), null); String address = getSelectedAddress(rendering.getSelectedAddress(), ""); //$NON-NLS-1$ String range = getRange(rendering.getSelectedAsBytes(), addressableSize, "1"); //$NON-NLS-1$ createWatchpoint(interactive, part, "", ResourcesPlugin.getWorkspace().getRoot(), -1, -1, -1, address, //$NON-NLS-1$ memorySpace, range); } private String getMemorySpace(IMemoryBlock memBlock, String def) { // XXX: In pre-CDI removal this retrieved memory space from CMemoryBlockExtension return def; } private String getSelectedAddress(BigInteger selectedAddress, String def) { if (selectedAddress != null) { return "0x" + selectedAddress.toString(16); //$NON-NLS-1$ } return def; } private String getRange(MemoryByte[] selectedBytes, int addressableSize, String def) { if (selectedBytes != null && selectedBytes.length > 0) { return Integer.toString(selectedBytes.length / addressableSize); } return def; } private void updateTargetWatchpoint(boolean toggle, final boolean interactive, final IWorkbenchPart part, ICWatchpointTarget watchpointTarget) throws CoreException { String _expr = watchpointTarget.getExpression(); if (_expr == null) { _expr = ""; //$NON-NLS-1$ } final String expr = _expr; // Getting the size of the variable/expression is an asynchronous // operation...or at least the API is (the CDI implementation reacts // synchronously) class GetSizeRequest extends CRequest implements ICWatchpointTarget.GetSizeRequest { int fSize = -1; @Override public int getSize() { return fSize; } @Override public void setSize(int size) { fSize = size; } @Override public void done() { int _size = 0; if (isSuccess()) { // Now that we have the size, put up a dialog to create the watchpoint _size = getSize(); assert _size > 0 : "unexpected variale/expression size"; //$NON-NLS-1$ } final int size = _size; WorkbenchJob job = new WorkbenchJob("open watchpoint dialog") { //$NON-NLS-1$ @Override public IStatus runInUIThread(IProgressMonitor monitor) { try { createWatchpoint(interactive, part, "", ResourcesPlugin.getWorkspace().getRoot(), //$NON-NLS-1$ -1, -1, -1, expr, null, Integer.toString(size)); } catch (CoreException e) { return e.getStatus(); } return Status.OK_STATUS; } }; job.setSystem(true); job.schedule(); } }; watchpointTarget.getSize(new GetSizeRequest()); } /** * Returns the C model element at the given selection. * @param part Workbench part where the selection is. * @param selection Selection in part. * @return C model element if found. */ protected ICElement getCElementFromSelection( IWorkbenchPart part, ISelection selection ) { if ( selection instanceof ITextSelection ) { ITextSelection textSelection = (ITextSelection)selection; String text = textSelection.getText(); if ( text != null ) { if ( part instanceof ITextEditor ) { ICElement editorElement = CDTUITools.getEditorInputCElement( ((ITextEditor)part).getEditorInput() ); if ( editorElement instanceof ITranslationUnit ) { ITranslationUnit tu = (ITranslationUnit)editorElement; try { if ( tu.isStructureKnown() && tu.isConsistent() ) { return tu.getElementAtOffset( textSelection.getOffset() ); } } catch( CModelException exc ) { // ignored on purpose } } } else { IResource resource = getResource( part ); if ( resource instanceof IFile ) { ITranslationUnit tu = getTranslationUnit( (IFile)resource ); if ( tu != null ) { try { ICElement element = tu.getElement( text.trim() ); if ( element == null ) { element = tu.getElementAtLine( textSelection.getStartLine() ); } return element; } catch( CModelException e ) { } } } } } } else if ( selection instanceof IStructuredSelection ) { IStructuredSelection ss = (IStructuredSelection)selection; if ( ss.size() == 1 ) { Object object = ss.getFirstElement(); if ( object instanceof ICElement ) { return (ICElement)object; } } } return null; } /** * Returns the variable object at the given selection. * Returns the C model element at the given selection. * @param part Workbench part where the selection is. * @param selection Selection in part. * @return C model variable, if found. */ protected IVariable getVariableFromSelection( IWorkbenchPart part, ISelection selection ) { ICElement element = getCElementFromSelection( part, selection ); if ( element instanceof IVariable ) { return (IVariable)element; } return null; } protected IRepositionableMemoryRendering getMemoryRendering( IWorkbenchPart part, ISelection selection ) { if (selection != null && selection instanceof IStructuredSelection && !selection.isEmpty()) { Object obj = ((IStructuredSelection)selection).getFirstElement(); if (obj != null) { if (obj instanceof IAdaptable) { return ((IAdaptable)obj).getAdapter(IRepositionableMemoryRendering.class); } } } return null; } @SuppressWarnings("deprecation") protected ICWatchpointTarget getWatchpointTarget( IWorkbenchPart part, ISelection selection ) { if (selection != null && selection instanceof IStructuredSelection && !selection.isEmpty()) { Object obj = ((IStructuredSelection)selection).getFirstElement(); if (obj != null) { if (obj instanceof IAdaptable) { ICWatchpointTarget target = ((IAdaptable)obj).getAdapter(ICWatchpointTarget.class); if (target == null) { target = ((IAdaptable)obj).getAdapter( org.eclipse.cdt.debug.internal.core.ICWatchpointTarget.class); } return target; } } } return null; } /** * Reports the given error message to the user. * @param message Message to report. * @param part Workbench part where action was invoked. */ protected void report( String message, IWorkbenchPart part ) { IEditorStatusLine statusLine = part.getAdapter( IEditorStatusLine.class ); if ( statusLine != null ) { if ( message != null ) { statusLine.setMessage( true, message, null ); } else { statusLine.setMessage( true, null, null ); } } if ( message != null && CDebugUIPlugin.getActiveWorkbenchShell() != null ) { CDebugUIPlugin.getActiveWorkbenchShell().getDisplay().beep(); } } /** * Returns the resource being edited in the given workbench part. * @param part Workbench part to check. * @return Resource being edited. */ protected static IResource getResource( IWorkbenchPart part ) { IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); if ( part instanceof IEditorPart ) { IEditorInput editorInput = ((IEditorPart)part).getEditorInput(); return getResource(editorInput); } return root; } private static IResource getResource(IEditorInput editorInput) { IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); IResource resource = null; if ( editorInput instanceof IFileEditorInput ) { resource = ((IFileEditorInput)editorInput).getFile(); } else if ( editorInput instanceof ExternalEditorInput ) { resource = ((ExternalEditorInput)editorInput).getMarkerResource(); } if ( resource != null ) return resource; /* This file is not in a project, let default case handle it */ ILocationProvider provider = editorInput.getAdapter( ILocationProvider.class ); if ( provider != null ) { IPath location = provider.getPath( editorInput ); if ( location != null ) { IFile[] files = root.findFilesForLocationURI( URIUtil.toURI( location ) ); if ( files.length > 0 && files[0].isAccessible()) return files[0]; } } return root; } private String getSourceHandle( IEditorInput input ) throws CoreException { return CDebugUIUtils.getEditorFilePath( input ); } protected String getSourceHandle( IDeclaration declaration ) { ITranslationUnit tu = declaration.getTranslationUnit(); if ( tu != null ) { IPath location = tu.getLocation(); if ( location != null ) { return location.toOSString(); } } return ""; //$NON-NLS-1$ } /** * Returns the resource file containing the C model element. * * @param declaration model element * @return resource for c model element. Cannot be null, will return workspace root when no resource file can be found. */ protected IResource getElementResource( IDeclaration declaration ) { IResource resource = declaration.getUnderlyingResource(); if (resource != null) return resource; try { IEditorInput editorInput = EditorUtility.getEditorInput(declaration); return getResource(editorInput); } catch (CModelException e) { DebugPlugin.log(e); } return ResourcesPlugin.getWorkspace().getRoot(); } private String getFunctionName( IFunction function ) { String functionName = function.getElementName(); StringBuilder name = new StringBuilder( functionName ); ITranslationUnit tu = function.getTranslationUnit(); if ( tu != null && tu.isCXXLanguage() ) { appendParameters( name, function ); } return name.toString(); } private String getMethodName( IMethod method ) { StringBuilder name = new StringBuilder(); String methodName = method.getElementName(); ICElement parent = method.getParent(); while( parent != null && (parent.getElementType() == ICElement.C_NAMESPACE || parent.getElementType() == ICElement.C_CLASS || parent.getElementType() == ICElement.C_STRUCT || parent.getElementType() == ICElement.C_UNION) ) { name.append( parent.getElementName() ).append( "::" ); //$NON-NLS-1$ parent = parent.getParent(); } name.append( methodName ); appendParameters( name, method ); return name.toString(); } private void appendParameters( StringBuilder sb, IFunctionDeclaration fd ) { String[] params = fd.getParameterTypes(); sb.append( '(' ); for( int i = 0; i < params.length; ++i ) { sb.append( params[i] ); if ( i != params.length - 1 ) sb.append( ',' ); } sb.append( ')' ); } private String getVariableName( IVariable variable ) { return variable.getElementName(); } private ITranslationUnit getTranslationUnit( IFile file ) { Object element = CoreModel.getDefault().create( file ); if ( element instanceof ITranslationUnit ) { return (ITranslationUnit)element; } return null; } private boolean toggleBreakpointEnable(IWorkbenchPart part) { ITextEditor textEditor = getTextEditor(part); if(textEditor != null) { IVerticalRulerInfo info = textEditor.getAdapter(IVerticalRulerInfo.class); if(info != null) { EnableDisableBreakpointRulerAction enableAction = new EnableDisableBreakpointRulerAction(part, info); enableAction.update(); enableAction.run(); } } return false; } /** * Returns the text editor associated with the given part or <code>null</code> * if none. In case of a multi-page editor, this method should be used to retrieve * the correct editor to perform the breakpoint operation on. * * @param part workbench part * @return text editor part or <code>null</code> */ protected ITextEditor getTextEditor(IWorkbenchPart part) { if (part instanceof ITextEditor) { return (ITextEditor) part; } return part.getAdapter(ITextEditor.class); } /** * Resolves the {@link IBreakpoint} from the given editor and ruler information. Returns <code>null</code> * if no breakpoint exists or the operation fails. * * @param editor the editor * @param info the current ruler information * @return the {@link IBreakpoint} from the current editor position or <code>null</code> */ protected IBreakpoint getBreakpointFromEditor(ITextEditor editor, IVerticalRulerInfo info) { IAnnotationModel annotationModel = editor.getDocumentProvider().getAnnotationModel(editor.getEditorInput()); IDocument document = editor.getDocumentProvider().getDocument(editor.getEditorInput()); if (annotationModel != null) { Iterator<Annotation> iterator = annotationModel.getAnnotationIterator(); while (iterator.hasNext()) { Object object = iterator.next(); if (object instanceof SimpleMarkerAnnotation) { SimpleMarkerAnnotation markerAnnotation = (SimpleMarkerAnnotation) object; IMarker marker = markerAnnotation.getMarker(); try { if (marker.isSubtypeOf(IBreakpoint.BREAKPOINT_MARKER)) { Position position = annotationModel.getPosition(markerAnnotation); int line = document.getLineOfOffset(position.getOffset()); if (line == info.getLineOfLastMouseButtonActivity()) { IBreakpoint breakpoint = DebugPlugin.getDefault().getBreakpointManager().getBreakpoint(marker); if (breakpoint != null) { return breakpoint; } } } } catch (CoreException e) { } catch (BadLocationException e) { } } } } return null; } /** * Opens the properties dialog for the given breakpoint. This method can be * used on an existing breakpoint or on a blank breakpoint which doesn't * have an associated marker yet. * * @param bp * The breakpoint to edit. This breakpoint may not have an * associated marker yet. * @param part * Workbench part where the action was invoked. * @param resource * Workbench resource to create the breakpoint on. * @param attributes * Breakpoint attributes to show in properties dialog. If the * breakpoint already exists, this attribute map can be used to * override the attributes currently in the breakpoint. Can be * <code>null</code>. */ protected void openBreakpointPropertiesDialog(ICBreakpoint bp, IWorkbenchPart part, IResource resource, Map<String, Object> attributes) { ISelection debugContext = DebugUITools.getDebugContextManager() .getContextService(part.getSite().getWorkbenchWindow()).getActiveContext(part.getSite().getId()); CBreakpointContext bpContext = new CBreakpointContext(bp, debugContext, resource, attributes); String initialPageId = null; if (bp.getMarker() == null) { // Bug 433308 - Always show Common page initially for new breakpoints initialPageId = CBreakpointPropertyDialogAction.PAGE_ID_COMMON; } PreferenceDialog dialog = PreferencesUtil.createPropertyDialogOn(part.getSite().getShell(), bpContext, initialPageId , null, null); if (dialog != null) { dialog.open(); } } /** * Finds the line breakpoint at the given location. * * @param sourceHandle * Source handle for the line breakpoint. * @param resource * Resource of the line breakpoint. * @param lineNumber * Line number. * @return Line breakpoint with given parameters, if found. * @throws CoreException * Exception thrown while reading breakpoints' properties. */ protected abstract ICLineBreakpoint findLineBreakpoint(String sourceHandle, IResource resource, int lineNumber) throws CoreException; /** * Creates a line breakpoint at the given location. * @param interactive true if action should open a dialog to let user edit * breakpoint properties prior to creation. * @param part Workbench part where action was invoked. * @param source Handle Source handle for the new breakpoint. * @param resource Resource to create breakpoint on. * @param lineNumber Line number for new breakpoint. * @throws CoreException Exception while creating breakpoint. */ protected abstract void createLineBreakpoint(boolean interactive, IWorkbenchPart part, String sourceHandle, IResource resource, int lineNumber) throws CoreException; /** * Finds the function breakpoint at the given location. * * @param sourceHandle * Source handle for the line breakpoint. * @param resource * Resource of the line breakpoint. * @param functionName * Function for the breakpoint. * @return Function breakpoint with given parameters, if found. * @throws CoreException * Exception thrown while reading breakpoints' properties. */ protected abstract ICFunctionBreakpoint findFunctionBreakpoint(String sourceHandle, IResource resource, String functionName) throws CoreException; /** * Creates a function breakpoint at the given location. * @param interactive true if action should open a dialog to let user edit * breakpoint properties prior to creation. * @param part Workbench part where action was invoked. * @param source Handle Source handle for the new breakpoint. * @param resource Resource to create breakpoint on. * @param charStart Beginning of range where function is located. Can be * -1 if not known. * @param charStart End of range where function is located. Can be * -1 if not known. * @param lineNumber Line number where the function is located. * @throws CoreException Exception while creating breakpoint. */ protected abstract void createFunctionBreakpoint(boolean interactive, IWorkbenchPart part, String sourceHandle, IResource resource, String functionName, int charStart, int charEnd, int lineNumber) throws CoreException; /** * Finds the watchpoint with given expression. * * @param sourceHandle Source handle for the line breakpoint. * @param resource Resource of the line breakpoint. * @param expression Expression of the breakpoint. * @return Watchpoing with given parameters, if found. * @throws CoreException Exception thrown while reading breakpoints' */ protected abstract ICWatchpoint findWatchpoint( String sourceHandle, IResource resource, String expression ) throws CoreException; /** * Creates a watchpoint at the given location. * @param interactive true if action should open a dialog to let user edit * breakpoint properties prior to creation. * @param part Workbench part where action was invoked. * @param source Handle Source handle for the new breakpoint. * @param resource Resource to create breakpoint on. * @param charStart Beginning of range where variable is located. Can be * -1 if not known. * @param charStart End of range where variable is located. Can be * -1 if not known. * @param lineNumber Line number where the variable is located. * @throws CoreException Exception while creating breakpoint. */ protected abstract void createWatchpoint(boolean interactive, IWorkbenchPart part, String sourceHandle, IResource resource, int charStart, int charEnd, int lineNumber, String expression, String memorySpace, String range) throws CoreException; /** * Creates an event breakpoint of the given type. * @param interactive true if action should open a dialog to let user edit * breakpoint properties prior to creation. * @param part Workbench part where action was invoked. * @param resource Resource to create breakpoint on. * @param type Type of event breakpoint. * @param arg Arugment of event breakpoint. * @throws CoreException Exception while creating breakpoint. */ protected abstract void createEventBreakpoint(boolean interactive, IWorkbenchPart part, IResource resource, String type, String arg) throws CoreException; }