Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: 64a419765c4fa9b20f67dbb0b1aca5fecfaa5e33 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
/*******************************************************************************
 * Copyright (c) 2000, 2008 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.debug.ui.actions;

import org.eclipse.core.resources.IWorkspaceRunnable;
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.DebugEvent;
import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.IBreakpointManager;
import org.eclipse.debug.core.IBreakpointManagerListener;
import org.eclipse.debug.core.IDebugEventSetListener;
import org.eclipse.debug.core.model.IBreakpoint;
import org.eclipse.debug.core.model.IDebugTarget;
import org.eclipse.debug.core.model.ISuspendResume;
import org.eclipse.debug.core.model.IThread;
import org.eclipse.debug.internal.ui.actions.ActionMessages;
import org.eclipse.debug.ui.DebugUITools;
import org.eclipse.debug.ui.IDebugUIConstants;

/**
 * Handles a run to line operation. Clients implementing a run to line action
 * can use this handler to carry out a run to line operation implemented with
 * a breakpoint. Handles the user preference to skip breakpoints while performing
 * a run to line operation, and cancelling the run to line operation if another
 * breakpoint is encountered before the operation is completed.
 * <p>
 * Clients may instantiate this class.
 * </p>
 * @since 3.1
 * @noextend This class is not intended to be subclassed by clients.
 */
public class RunToLineHandler implements IDebugEventSetListener, IBreakpointManagerListener, IWorkspaceRunnable {

    private IDebugTarget fTarget;
    private ISuspendResume fResumee;
    private IBreakpoint fBreakpoint;
    private boolean fAutoSkip = false;

    /**
     * Constructs a handler to perform a run to line operation.
     *
     * @param target the debug target in which the operation is to be performed
     * @param suspendResume the element to be resumed to begin the operation
     * @param breakpoint the run to line breakpoint
     */
    public RunToLineHandler(IDebugTarget target, ISuspendResume suspendResume, IBreakpoint breakpoint) {
        fResumee = suspendResume;
        fTarget = target;
        fBreakpoint = breakpoint;
    }

    @Override
	public void handleDebugEvents(DebugEvent[] events) {
        for (int i = 0; i < events.length; i++) {
            DebugEvent event= events[i];
            Object source= event.getSource();
            if (source instanceof IThread && event.getKind() == DebugEvent.SUSPEND &&
                    event.getDetail() == DebugEvent.BREAKPOINT) {
                IThread thread = (IThread) source;
                IDebugTarget suspendee = thread.getAdapter(IDebugTarget.class);
                if (fTarget.equals(suspendee)) {
                    // cleanup if the breakpoint was hit or not
                    cancel();
                }
            } else if (source instanceof IDebugTarget && event.getKind() == DebugEvent.TERMINATE) {
                if (source.equals(fTarget)) {
                    // Clean up if the debug target terminates without
                    // hitting the breakpoint.
                    cancel();
                }
            }
        }

    }

    @Override
	public void breakpointManagerEnablementChanged(boolean enabled) {
        // if the user changes the breakpoint manager enablement, don't restore it
        fAutoSkip = false;
    }

    private IBreakpointManager getBreakpointManager() {
        return getDebugPlugin().getBreakpointManager();
    }

    private DebugPlugin getDebugPlugin() {
        return DebugPlugin.getDefault();
    }

    /**
     * Cancels the run to line operation.
     */
    public void cancel() {
        IBreakpointManager manager = getBreakpointManager();
        try {
            getDebugPlugin().removeDebugEventListener(this);
            manager.removeBreakpointManagerListener(this);
            fTarget.breakpointRemoved(fBreakpoint, null);
        } finally {
            if (fAutoSkip) {
                manager.setEnabled(true);
            }
        }
    }

    @Override
	public void run(IProgressMonitor monitor) throws CoreException {
        getDebugPlugin().addDebugEventListener(this);
        IBreakpointManager breakpointManager = getBreakpointManager();
        fAutoSkip = DebugUITools.getPreferenceStore().getBoolean(IDebugUIConstants.PREF_SKIP_BREAKPOINTS_DURING_RUN_TO_LINE) && breakpointManager.isEnabled();
        if (fAutoSkip) {
            getBreakpointManager().setEnabled(false);
            breakpointManager.addBreakpointManagerListener(this);
        }
        Job job = new Job(ActionMessages.RunToLineHandler_0) {
            @Override
			protected IStatus run(IProgressMonitor jobMonitor) {
                if (!jobMonitor.isCanceled()) {
                    fTarget.breakpointAdded(fBreakpoint);
                    try {
                        fResumee.resume();
                    } catch (DebugException e) {
                        cancel();
                        return e.getStatus();
                    }
                }
                return Status.OK_STATUS;
            }
        };
        job.schedule();
    }

}

Back to the top