diff --git a/debug/org.eclipse.cdt.debug.core/ChangeLog b/debug/org.eclipse.cdt.debug.core/ChangeLog index cf9fc9acf7a..8472fc4e1fd 100644 --- a/debug/org.eclipse.cdt.debug.core/ChangeLog +++ b/debug/org.eclipse.cdt.debug.core/ChangeLog @@ -1,3 +1,10 @@ +2004-09-01 Mikhail Khodjaiants + Breakpoint filtering by targets (core). + * ICBreakpoint.java + * CBreakpointManager.java + * CBreakpoint.java + * CDebugTarget.java + 2004-08-18 Mikhail Khodjaiants New constant - the default value for the "stop at main" property. * ICDTLaunchConfigurationConstants.java diff --git a/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/model/ICBreakpoint.java b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/model/ICBreakpoint.java index 8fa50c05914..26db29311d7 100644 --- a/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/model/ICBreakpoint.java +++ b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/model/ICBreakpoint.java @@ -177,4 +177,63 @@ public interface ICBreakpoint extends IBreakpoint { * on this breakpoint's underlying marker */ public void resetInstallCount() throws CoreException; + + /** + * Add the given target to the list of this breakpoint's targets. + * Target filters are not persisted across workbench invocations. + * + * @param target the target to add to the list of this breakpoint's targets. + * @throws CoreException if unable to set the target filter + */ + public void setTargetFilter( ICDebugTarget target ) throws CoreException; + + /** + * Removes the given target from the breakpoint's target list. + * The breakpoint has no effect in the given target. + * + * @param target the target filter to be removed + * @exception CoreException if unable to remove the target filter + */ + public void removeTargetFilter( ICDebugTarget target ) throws CoreException; + + /** + * Restricts this breakpoint to suspend only in the given threads + * when encounterd in the given threads' target. + * All threads must be from the same target. + * Thread filters are not persisted across workbench invocations. + * + * @param threads the thread filters to be set + * @exception CoreException if unable to set the thread filters + */ + public void setThreadFilters( ICThread[] threads ) throws CoreException; + + /** + * Returns all target filters set on this breakpoint. + * + * @return the targets that this breakpoint is resticted to + * @exception CoreException if unable to determine this breakpoint's + * target filters + */ + public ICDebugTarget[] getTargetFilters() throws CoreException; + + /** + * Removes this breakpoint's thread filters in the given target, if any. + * Has no effect if this breakpoint does not have filters in the given target. + * All threads must be from the same target. + * + * @param threads the thread filters to be removed + * @exception CoreException if unable to remove the thread filter + */ + public void removeThreadFilters( ICThread[] threads ) throws CoreException; + + /** + * Returns the threads in the given target in which this breakpoint + * is enabled or null if this breakpoint is enabled in + * all threads in the given target. + * + * @return the threads in the given target that this breakpoint is enabled for + * @exception CoreException if unable to determine this breakpoint's thread + * filters + */ + public ICThread[] getThreadFilters( ICDebugTarget target ) throws CoreException; } \ No newline at end of file diff --git a/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/CBreakpointManager.java b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/CBreakpointManager.java index a9aca65bc94..4524a55bf8d 100644 --- a/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/CBreakpointManager.java +++ b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/CBreakpointManager.java @@ -11,10 +11,10 @@ package org.eclipse.cdt.debug.internal.core; import java.text.MessageFormat; +import java.util.Arrays; import java.util.HashMap; import java.util.Map; import java.util.Set; - import org.eclipse.cdt.debug.core.CDIDebugModel; import org.eclipse.cdt.debug.core.CDebugCorePlugin; import org.eclipse.cdt.debug.core.CDebugUtils; @@ -203,6 +203,10 @@ public class CBreakpointManager implements IBreakpointManagerListener, ICDIEvent } public boolean isTargetBreakpoint( ICBreakpoint breakpoint ) { + // Problem: gdb doesn't accept breakpoint if the file is specified by full path (depends on the current directory). + // This prevents us from using gdb as a breakpoint filter. The case when two unrelated projects contain files + // with the same name will cause problems. + // Current solution: the source locator is used as a breakpoint filter. IResource resource = breakpoint.getMarker().getResource(); if ( breakpoint instanceof ICAddressBreakpoint ) return supportsAddressBreakpoint( (ICAddressBreakpoint)breakpoint ); @@ -287,6 +291,7 @@ public class CBreakpointManager implements IBreakpointManagerListener, ICDIEvent } if ( cdiBreakpoint == null ) return; + breakpoint.setTargetFilter( getDebugTarget() ); if ( !breakpoint.isEnabled() ) cdiBreakpoint.setEnabled( false ); setBreakpointCondition( breakpoint ); @@ -312,10 +317,14 @@ public class CBreakpointManager implements IBreakpointManagerListener, ICDIEvent ICDIBreakpointManager bm = getCDIBreakpointManager(); try { bm.deleteBreakpoints( new ICDIBreakpoint[]{ cdiBreakpoint } ); + breakpoint.removeTargetFilter( getDebugTarget() ); } catch( CDIException e ) { targetRequestFailed( MessageFormat.format( InternalDebugCoreMessages.getString( "CBreakpointManager.3" ), new String[] { e.getMessage() } ), e ); //$NON-NLS-1$ } + catch( CoreException e ) { + DebugPlugin.log( e ); + } } } @@ -398,7 +407,16 @@ public class CBreakpointManager implements IBreakpointManagerListener, ICDIEvent ICBreakpoint breakpoint = getBreakpointMap().getCBreakpoint( cdiBreakpoint ); getBreakpointMap().removeCDIBreakpoint( cdiBreakpoint ); if ( breakpoint != null ) { - getBreakpointNotifier().breakpointRemoved( getDebugTarget(), breakpoint ); + if ( isFilteredByTarget( breakpoint, getDebugTarget() ) ) { + getBreakpointNotifier().breakpointRemoved( getDebugTarget(), breakpoint ); + } + else { + try { + breakpoint.decrementInstallCount(); + } + catch( CoreException e ) { + } + } } } @@ -671,4 +689,15 @@ public class CBreakpointManager implements IBreakpointManagerListener, ICDIEvent } } } + + private boolean isFilteredByTarget( ICBreakpoint breakpoint, ICDebugTarget target ) { + boolean result = false; + try { + ICDebugTarget[] tfs = breakpoint.getTargetFilters(); + result = Arrays.asList( tfs ).contains( this ); + } + catch( CoreException e1 ) { + } + return result; + } } diff --git a/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/breakpoints/CBreakpoint.java b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/breakpoints/CBreakpoint.java index cd8b5a7ff7b..a449e4a4f13 100644 --- a/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/breakpoints/CBreakpoint.java +++ b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/breakpoints/CBreakpoint.java @@ -11,10 +11,15 @@ package org.eclipse.cdt.debug.internal.core.breakpoints; import java.text.MessageFormat; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; import java.util.Map; - +import java.util.Set; import org.eclipse.cdt.debug.core.CDIDebugModel; import org.eclipse.cdt.debug.core.model.ICBreakpoint; +import org.eclipse.cdt.debug.core.model.ICDebugTarget; +import org.eclipse.cdt.debug.core.model.ICThread; import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IWorkspaceRunnable; @@ -26,22 +31,27 @@ import org.eclipse.debug.core.DebugException; import org.eclipse.debug.core.DebugPlugin; import org.eclipse.debug.core.IDebugEventSetListener; import org.eclipse.debug.core.model.Breakpoint; +import org.eclipse.debug.core.model.IDebugTarget; /** * The base class for all C/C++ specific breakpoints. */ public abstract class CBreakpoint extends Breakpoint implements ICBreakpoint, IDebugEventSetListener { + private Map fFilteredThreadsByTarget; + /** * Constructor for CBreakpoint. */ public CBreakpoint() { + fFilteredThreadsByTarget = new HashMap( 10 ); } /** * Constructor for CBreakpoint. */ public CBreakpoint( final IResource resource, final String markerType, final Map attributes, final boolean add ) throws CoreException { + this(); IWorkspaceRunnable wr = new IWorkspaceRunnable() { public void run( IProgressMonitor monitor ) throws CoreException { @@ -271,4 +281,76 @@ public abstract class CBreakpoint extends Breakpoint implements ICBreakpoint, ID } return sb.toString(); } + + /* (non-Javadoc) + * @see org.eclipse.cdt.debug.core.model.ICBreakpoint#getTargetFilters() + */ + public ICDebugTarget[] getTargetFilters() throws CoreException { + Set set = fFilteredThreadsByTarget.keySet(); + return (ICDebugTarget[])set.toArray( new ICDebugTarget[set.size()] ); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.debug.core.model.ICBreakpoint#getThreadFilters(org.eclipse.cdt.debug.core.model.ICDebugTarget) + */ + public ICThread[] getThreadFilters( ICDebugTarget target ) throws CoreException { + Set set = (Set)fFilteredThreadsByTarget.get( target ); + return ( set != null ) ? (ICThread[])set.toArray( new ICThread[set.size()] ) : null; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.debug.core.model.ICBreakpoint#removeTargetFilter(org.eclipse.cdt.debug.core.model.ICDebugTarget) + */ + public void removeTargetFilter( ICDebugTarget target ) throws CoreException { + if ( fFilteredThreadsByTarget.containsKey( target ) ) { + fFilteredThreadsByTarget.remove( target ); + fireChanged(); + } + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.debug.core.model.ICBreakpoint#removeThreadFilters(org.eclipse.cdt.debug.core.model.ICThread[]) + */ + public void removeThreadFilters( ICThread[] threads ) throws CoreException { + if ( threads != null && threads.length > 0 ) { + IDebugTarget target = threads[0].getDebugTarget(); + if ( fFilteredThreadsByTarget.containsKey( target ) ) { + Set set = (Set)fFilteredThreadsByTarget.get( target ); + if ( set != null ) { + set.removeAll( Arrays.asList( threads ) ); + if ( set.isEmpty() ) { + fFilteredThreadsByTarget.remove( target ); + } + } + } + } + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.debug.core.model.ICBreakpoint#setTargetFilter(org.eclipse.cdt.debug.core.model.ICDebugTarget) + */ + public void setTargetFilter( ICDebugTarget target ) throws CoreException { + fFilteredThreadsByTarget.put( target, null ); + fireChanged(); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.debug.core.model.ICBreakpoint#setThreadFilters(org.eclipse.cdt.debug.core.model.ICThread[]) + */ + public void setThreadFilters( ICThread[] threads ) throws CoreException { + if ( threads != null && threads.length > 0 ) { + fFilteredThreadsByTarget.put( threads[0].getDebugTarget(), new HashSet( Arrays.asList( threads ) ) ); + } + } + + /** + * Change notification when there are no marker changes. If the marker + * does not exist, do not fire a change notificaiton (the marker may not + * exist if the associated project was closed). + */ + protected void fireChanged() { + if ( markerExists() ) { + DebugPlugin.getDefault().getBreakpointManager().fireBreakpointChanged( this ); + } + } } \ No newline at end of file diff --git a/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/model/CDebugTarget.java b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/model/CDebugTarget.java index e5f93ac0043..152dcd9a301 100644 --- a/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/model/CDebugTarget.java +++ b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/model/CDebugTarget.java @@ -11,6 +11,7 @@ package org.eclipse.cdt.debug.internal.core.model; import java.util.ArrayList; +import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.StringTokenizer; @@ -612,7 +613,7 @@ public class CDebugTarget extends CDebugElement implements ICDebugTarget, ICDIEv * @see org.eclipse.debug.core.IBreakpointListener#breakpointAdded(org.eclipse.debug.core.model.IBreakpoint) */ public void breakpointAdded( IBreakpoint breakpoint ) { - if ( !(breakpoint instanceof ICBreakpoint) || !getBreakpointManager().isTargetBreakpoint( (ICBreakpoint)breakpoint ) || !isAvailable() ) + if ( !(breakpoint instanceof ICBreakpoint) || !isAvailable() || !getBreakpointManager().isTargetBreakpoint( (ICBreakpoint)breakpoint ) ) return; breakpointAdded0( breakpoint ); } @@ -635,7 +636,7 @@ public class CDebugTarget extends CDebugElement implements ICDebugTarget, ICDIEv * @see org.eclipse.debug.core.IBreakpointListener#breakpointRemoved(org.eclipse.debug.core.model.IBreakpoint, org.eclipse.core.resources.IMarkerDelta) */ public void breakpointRemoved( IBreakpoint breakpoint, IMarkerDelta delta ) { - if ( !(breakpoint instanceof ICBreakpoint) || !getBreakpointManager().isTargetBreakpoint( (ICBreakpoint)breakpoint ) || !isAvailable() ) + if ( !(breakpoint instanceof ICBreakpoint) || !isAvailable() || !getBreakpointManager().isCDIRegistered( (ICBreakpoint)breakpoint ) ) return; try { getBreakpointManager().removeBreakpoint( (ICBreakpoint)breakpoint ); @@ -648,12 +649,37 @@ public class CDebugTarget extends CDebugElement implements ICDebugTarget, ICDIEv * @see org.eclipse.debug.core.IBreakpointListener#breakpointChanged(org.eclipse.debug.core.model.IBreakpoint, org.eclipse.core.resources.IMarkerDelta) */ public void breakpointChanged( IBreakpoint breakpoint, IMarkerDelta delta ) { - if ( !(breakpoint instanceof ICBreakpoint) || !getBreakpointManager().isTargetBreakpoint( (ICBreakpoint)breakpoint ) || !isAvailable() || delta == null ) + if ( !(breakpoint instanceof ICBreakpoint) || !isAvailable() ) return; + ICBreakpoint b = (ICBreakpoint)breakpoint; + boolean install = false; try { - getBreakpointManager().changeBreakpointProperties( (ICBreakpoint)breakpoint, delta ); + ICDebugTarget[] tfs = b.getTargetFilters(); + install = Arrays.asList( tfs ).contains( this ); } - catch( DebugException e ) { + catch( CoreException e1 ) { + } + boolean registered = getBreakpointManager().isCDIRegistered( b ); + if ( registered && !install ) { + try { + getBreakpointManager().removeBreakpoint( b ); + } + catch( DebugException e ) { + } + } + if ( !registered && install ) { + try { + getBreakpointManager().setBreakpoint( b ); + } + catch( DebugException e ) { + } + } + if ( delta != null ) { + try { + getBreakpointManager().changeBreakpointProperties( b, delta ); + } + catch( DebugException e ) { + } } } diff --git a/debug/org.eclipse.cdt.debug.ui/ChangeLog b/debug/org.eclipse.cdt.debug.ui/ChangeLog index 9c588ea287f..f0fbc79717d 100644 --- a/debug/org.eclipse.cdt.debug.ui/ChangeLog +++ b/debug/org.eclipse.cdt.debug.ui/ChangeLog @@ -1,3 +1,9 @@ +2004-09-01 Mikhail Khodjaiants + Breakpoint filtering by targets (ui). + * PropertyPageMessages.properties + * CBreakpointFilteringPage.java + * ThreadFilterEditor.java + 2004-08-25 Mikhail Khodjaiants Added the "Filtering" page to the breakpoint properties. * CBreakpointWorkbenchAdapterFactory.java: new diff --git a/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/propertypages/CBreakpointFilteringPage.java b/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/propertypages/CBreakpointFilteringPage.java index 7c0c2195f0b..dd2abdd7694 100644 --- a/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/propertypages/CBreakpointFilteringPage.java +++ b/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/propertypages/CBreakpointFilteringPage.java @@ -47,4 +47,19 @@ public class CBreakpointFilteringPage extends PropertyPage { protected ThreadFilterEditor getThreadFilterEditor() { return fThreadFilterEditor; } + + /* (non-Javadoc) + * @see org.eclipse.jface.preference.IPreferencePage#performOk() + */ + public boolean performOk() { + doStore(); + return super.performOk(); + } + + /** + * Stores the values configured in this page. + */ + protected void doStore() { + fThreadFilterEditor.doStore(); + } } diff --git a/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/propertypages/PropertyPageMessages.properties b/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/propertypages/PropertyPageMessages.properties index 57ea61d278c..f1d4c93d5e4 100644 --- a/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/propertypages/PropertyPageMessages.properties +++ b/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/propertypages/PropertyPageMessages.properties @@ -29,4 +29,4 @@ CBreakpointPropertyPage.16=Invalid condition. CBreakpointPropertyPage.17=&Ignore count: CBreakpointPropertyPage.18=Type: CBreakpointPropertyPage.19=Enabled -ThreadFilterEditor.0=&Restrict to Selected Thread(s): +ThreadFilterEditor.0=&Restrict to Selected Targets and Threads: diff --git a/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/propertypages/ThreadFilterEditor.java b/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/propertypages/ThreadFilterEditor.java index c1d615ddb71..c9fdecf43ef 100644 --- a/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/propertypages/ThreadFilterEditor.java +++ b/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/propertypages/ThreadFilterEditor.java @@ -12,7 +12,10 @@ package org.eclipse.cdt.debug.internal.ui.propertypages; import java.util.ArrayList; import java.util.List; +import org.eclipse.cdt.debug.core.model.ICBreakpoint; import org.eclipse.cdt.debug.core.model.ICDebugTarget; +import org.eclipse.cdt.debug.core.model.ICThread; +import org.eclipse.core.runtime.CoreException; import org.eclipse.debug.core.DebugException; import org.eclipse.debug.core.DebugPlugin; import org.eclipse.debug.core.ILaunch; @@ -279,20 +282,58 @@ public class ThreadFilterEditor { * checked. */ protected void setInitialCheckedState() { -// try { -// IDebugTarget[] targets = getDebugTargets(); -// for( int i = 0, numTargets = targets.length; i < numTargets; i++ ) { -// ICDebugTarget target = (ICDebugTarget)targets[i].getAdapter( ICDebugTarget.class ); -// if ( target != null ) { -// ICThread filteredThread = fPage.getBreakpoint().getThreadFilter( target ); -// if ( filteredThread != null ) { -// fCheckHandler.checkThread( filteredThread, true ); -// } -// } -// } -// } -// catch( CoreException e ) { -// DebugUIPlugin.log( e ); -// } + ICBreakpoint breakpoint = fPage.getBreakpoint(); + try { + ICDebugTarget[] targets = breakpoint.getTargetFilters(); + for( int i = 0; i < targets.length; i++ ) { + ICThread[] filteredThreads = breakpoint.getThreadFilters( targets[i] ); + if ( filteredThreads != null ) { + for ( int j = 0; j < filteredThreads.length; ++j ) + fCheckHandler.checkThread( filteredThreads[j], true ); + } + else { + fCheckHandler.checkTarget( targets[i], true ); + } + } + } + catch( CoreException e ) { + DebugUIPlugin.log( e ); + } + } + + protected void doStore() { + ICBreakpoint breakpoint = fPage.getBreakpoint(); + IDebugTarget[] targets = getDebugTargets(); + for ( int i = 0; i < targets.length; ++i ) { + if ( !(targets[i] instanceof ICDebugTarget) ) + continue; + try { + if ( getThreadViewer().getChecked( targets[i] ) ) { + if ( getThreadViewer().getGrayed( targets[i] ) ) { + ICThread[] threads = getTargetThreadFilters( (ICDebugTarget)targets[i] ); + breakpoint.setThreadFilters( threads ); + } + else { + breakpoint.setTargetFilter( (ICDebugTarget)targets[i] ); + } + } + else { + breakpoint.removeTargetFilter( (ICDebugTarget)targets[i] ); + } + } + catch( CoreException e ) { + DebugUIPlugin.log( e ); + } + } + } + + private ICThread[] getTargetThreadFilters( ICDebugTarget target ) { + Object[] threads = ((ITreeContentProvider)getThreadViewer().getContentProvider()).getChildren( target ); + ArrayList list = new ArrayList( threads.length ); + for ( int i = 0; i < threads.length; ++i ) { + if ( getThreadViewer().getChecked( threads[i] ) ) + list.add( threads[i] ); + } + return (ICThread[])list.toArray( new ICThread[list.size()] ); } }