/******************************************************************************* * Copyright (c) 2011, 2014 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) *******************************************************************************/ package org.eclipse.cdt.dsf.debug.ui.actions; import java.net.URI; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; import org.eclipse.cdt.core.IAddress; import org.eclipse.cdt.debug.core.model.ICBreakpoint; import org.eclipse.cdt.debug.internal.ui.CDebugUIUtils; import org.eclipse.cdt.debug.internal.ui.breakpoints.CBreakpointContext; import org.eclipse.cdt.debug.ui.CDebugUIPlugin; import org.eclipse.cdt.debug.ui.breakpoints.IToggleBreakpointsTargetCExtension; import org.eclipse.cdt.dsf.debug.internal.ui.disassembly.provisional.DisassemblySelection; import org.eclipse.cdt.dsf.debug.internal.ui.disassembly.provisional.IDisassemblyPart; import org.eclipse.cdt.dsf.debug.internal.ui.disassembly.provisional.IDisassemblySelection; import org.eclipse.core.filesystem.URIUtil; import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.debug.core.DebugPlugin; import org.eclipse.debug.core.model.IBreakpoint; import org.eclipse.debug.ui.DebugUITools; import org.eclipse.debug.ui.actions.IToggleBreakpointsTargetExtension2; 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.IAnnotationModel; import org.eclipse.jface.viewers.ISelection; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Event; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.dialogs.PreferencesUtil; import org.eclipse.ui.texteditor.SimpleMarkerAnnotation; /** * Base class for toggle breakpoint targets for the disassembly part. * @since 2.2 */ public abstract class AbstractDisassemblyBreakpointsTarget implements IToggleBreakpointsTargetExtension2, IToggleBreakpointsTargetCExtension { /* (non-Javadoc) * @see org.eclipse.debug.ui.actions.IToggleBreakpointsTarget#toggleLineBreakpoints(org.eclipse.ui.IWorkbenchPart, org.eclipse.jface.viewers.ISelection) */ @Override public void toggleLineBreakpoints( IWorkbenchPart part, ISelection selection ) throws CoreException { assert part instanceof IDisassemblyPart && selection instanceof ITextSelection; if ( !(selection instanceof IDisassemblySelection) ) { selection = new DisassemblySelection( (ITextSelection)selection, (IDisassemblyPart)part ); } IDisassemblySelection disassemblySelection = (IDisassemblySelection)selection; int line = disassemblySelection.getStartLine(); IBreakpoint[] bp = getBreakpointsAtLine( (IDisassemblyPart)part, line ); if ( bp == null || bp.length == 0 ) { insertBreakpoint(part, disassemblySelection, false); } else { for( int i = 0; i < bp.length; i++ ) { bp[i].delete(); } } } /* (non-Javadoc) * @see org.eclipse.debug.ui.actions.IToggleBreakpointsTarget#canToggleLineBreakpoints(org.eclipse.ui.IWorkbenchPart, org.eclipse.jface.viewers.ISelection) */ @Override public boolean canToggleLineBreakpoints( IWorkbenchPart part, ISelection selection ) { return part instanceof IDisassemblyPart && selection instanceof ITextSelection; } /* (non-Javadoc) * @see org.eclipse.debug.ui.actions.IToggleBreakpointsTarget#toggleMethodBreakpoints(org.eclipse.ui.IWorkbenchPart, org.eclipse.jface.viewers.ISelection) */ @Override public void toggleMethodBreakpoints( IWorkbenchPart part, ISelection selection ) throws CoreException { } /* (non-Javadoc) * @see org.eclipse.debug.ui.actions.IToggleBreakpointsTarget#canToggleMethodBreakpoints(org.eclipse.ui.IWorkbenchPart, org.eclipse.jface.viewers.ISelection) */ @Override public boolean canToggleMethodBreakpoints( IWorkbenchPart part, ISelection selection ) { return false; } /* (non-Javadoc) * @see org.eclipse.debug.ui.actions.IToggleBreakpointsTarget#toggleWatchpoints(org.eclipse.ui.IWorkbenchPart, org.eclipse.jface.viewers.ISelection) */ @Override public void toggleWatchpoints( IWorkbenchPart part, ISelection selection ) throws CoreException { } /* (non-Javadoc) * @see org.eclipse.debug.ui.actions.IToggleBreakpointsTarget#canToggleWatchpoints(org.eclipse.ui.IWorkbenchPart, org.eclipse.jface.viewers.ISelection) */ @Override public boolean canToggleWatchpoints( IWorkbenchPart part, ISelection selection ) { return false; } /* (non-Javadoc) * @see org.eclipse.debug.ui.actions.IToggleBreakpointsTargetExtension#toggleBreakpoints(org.eclipse.ui.IWorkbenchPart, org.eclipse.jface.viewers.ISelection) */ @Override public void toggleBreakpoints( IWorkbenchPart part, ISelection selection ) throws CoreException { toggleLineBreakpoints( part, selection ); } /* (non-Javadoc) * @see org.eclipse.debug.ui.actions.IToggleBreakpointsTargetExtension#canToggleBreakpoints(org.eclipse.ui.IWorkbenchPart, org.eclipse.jface.viewers.ISelection) */ @Override public boolean canToggleBreakpoints( IWorkbenchPart part, ISelection selection ) { return canToggleLineBreakpoints( part, selection ); } /** * @since 2.3 */ @Override public boolean canToggleBreakpointsWithEvent(IWorkbenchPart part, ISelection selection, Event event) { return canToggleBreakpoints(part, selection); } /** * @since 2.3 */ @Override public void toggleBreakpointsWithEvent(IWorkbenchPart part, ISelection selection, Event event) throws CoreException { assert part instanceof IDisassemblyPart && selection instanceof ITextSelection; boolean mod1 = event != null && (event.stateMask & SWT.MOD1) > 0; boolean mod2 = event != null && (event.stateMask & SWT.MOD2) > 0; if ( !(selection instanceof IDisassemblySelection) ) { selection = new DisassemblySelection( (ITextSelection)selection, (IDisassemblyPart)part ); } IDisassemblySelection disassemblySelection = (IDisassemblySelection)selection; int line = disassemblySelection.getStartLine(); IBreakpoint[] bp = getBreakpointsAtLine( (IDisassemblyPart)part, line ); if ( bp == null || bp.length == 0 ) { insertBreakpoint(part, disassemblySelection, mod1); } else { if(mod2) { toggleBreakpointEnabled(bp[0]); return; } else if (mod1 && bp[0] instanceof ICBreakpoint) { CDebugUIUtils.editBreakpointProperties(part, (ICBreakpoint)bp[0]); return; } for( int i = 0; i < bp.length; i++ ) { bp[i].delete(); } } } /** * @since 2.3 */ @Override public boolean canCreateLineBreakpointsInteractive(IWorkbenchPart part, ISelection selection) { return canToggleLineBreakpoints(part, selection) && !hasBreakpoint(part, selection); } /** * @since 2.3 */ @Override public void createLineBreakpointsInteractive(IWorkbenchPart part, ISelection selection) throws CoreException { assert part instanceof IDisassemblyPart && selection instanceof ITextSelection; if ( !(selection instanceof IDisassemblySelection) ) { selection = new DisassemblySelection( (ITextSelection)selection, (IDisassemblyPart)part ); } IDisassemblySelection disassemblySelection = (IDisassemblySelection)selection; insertBreakpoint(part, disassemblySelection, true); } /** * @since 2.3 */ @Override public boolean canCreateFunctionBreakpointInteractive(IWorkbenchPart part, ISelection selection) { return false; } /** * @since 2.3 */ @Override public void createFunctionBreakpointInteractive(IWorkbenchPart part, ISelection selection) throws CoreException { } /** * @since 2.3 */ @Override public boolean canCreateWatchpointsInteractive(IWorkbenchPart part, ISelection selection) { return false; } /** * @since 2.3 */ @Override public void createWatchpointsInteractive(IWorkbenchPart part, ISelection selection) throws CoreException { } /** * @since 2.3 */ @Override public boolean canCreateEventBreakpointsInteractive(IWorkbenchPart part, ISelection selection) { return false; } /** * @since 2.3 */ @Override public void createEventBreakpointsInteractive(IWorkbenchPart part, ISelection selection) throws CoreException { } private void toggleBreakpointEnabled(IBreakpoint bp) { try { bp.setEnabled(!bp.isEnabled()); } catch (CoreException e) { CDebugUIPlugin.log(e.getStatus()); } } protected abstract void createLineBreakpoint( String sourceHandle, IResource resource, int lineNumber ) throws CoreException; /** * @since 2.3 */ protected void createLineBreakpointInteractive(IWorkbenchPart part, String sourceHandle, IResource resource, int lineNumber ) throws CoreException { createLineBreakpoint(sourceHandle, resource, lineNumber); } protected abstract void createAddressBreakpoint( IResource resource, IAddress address ) throws CoreException; /** * @since 2.3 */ protected void createAddressBreakpointInteractive(IWorkbenchPart part, IResource resource, IAddress address ) throws CoreException { createAddressBreakpoint(resource, address); } private boolean hasBreakpoint(IWorkbenchPart part, ISelection selection) { assert part instanceof IDisassemblyPart && selection instanceof ITextSelection; if ( !(selection instanceof IDisassemblySelection) ) { selection = new DisassemblySelection( (ITextSelection)selection, (IDisassemblyPart)part ); } IDisassemblySelection disassemblySelection = (IDisassemblySelection)selection; int line = disassemblySelection.getStartLine(); IBreakpoint[] bp = getBreakpointsAtLine( (IDisassemblyPart)part, line ); return bp != null && bp.length > 0; } private IBreakpoint[] getBreakpointsAtLine( IDisassemblyPart part, int line ) { List<IBreakpoint> breakpoints = new ArrayList<IBreakpoint>(); IAnnotationModel annotationModel = part.getTextViewer().getAnnotationModel(); IDocument document = part.getTextViewer().getDocument(); if ( annotationModel != null ) { Iterator<?> 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 bpLine = document.getLineOfOffset( position.getOffset() ); if ( line == bpLine ) { IBreakpoint breakpoint = DebugPlugin.getDefault().getBreakpointManager().getBreakpoint( marker ); if ( breakpoint != null ) { breakpoints.add( breakpoint ); } } } } catch( CoreException e ) { } catch( BadLocationException e ) { } } } } IBreakpoint[] breakpointsArray = new IBreakpoint[breakpoints.size()]; return breakpoints.toArray( breakpointsArray ); } private void insertBreakpoint(IWorkbenchPart part, IDisassemblySelection selection, boolean interactive) throws CoreException { IAddress address = selection.getStartAddress(); if ( address == null ) { return; } URI fileUri = selection.getSourceLocationURI(); if ( fileUri != null ) { String filePath = null; IResource resource = selection.getSourceFile(); if ( resource != null ) { final IPath location = resource.getLocation(); if ( location == null ) { return; } filePath = location.toOSString(); } else { resource = ResourcesPlugin.getWorkspace().getRoot(); filePath = URIUtil.toPath( fileUri ).toOSString(); } int srcLine = selection.getSourceLine(); if (interactive) { createLineBreakpointInteractive(part, filePath, resource, srcLine + 1 ); } else { createLineBreakpoint( filePath, resource, srcLine + 1 ); } } else { IResource resource = ResourcesPlugin.getWorkspace().getRoot(); if (interactive) { createAddressBreakpointInteractive(part, resource, address ); } else { createAddressBreakpoint( resource, address ); } } } /** * 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>. * @since 2.3 */ 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); PreferenceDialog dialog = PreferencesUtil.createPropertyDialogOn(part.getSite().getShell(), bpContext, null, null, null); if (dialog != null) { dialog.open(); } } }