blob: 0951c4db01d385b64e90015153abd6cf8fe804a7 [file] [log] [blame]
/*=============================================================================#
# Copyright (c) 2015, 2019 Stephan Wahlbrink and others.
#
# This program and the accompanying materials are made available under the
# terms of the Eclipse Public License 2.0 which is available at
# https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
# which is available at https://www.apache.org/licenses/LICENSE-2.0.
#
# SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
#
# Contributors:
# Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
#=============================================================================*/
package org.eclipse.statet.internal.r.debug.ui.breakpoints;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IMarkerDelta;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.IBreakpointsListener;
import org.eclipse.debug.core.model.IBreakpoint;
import org.eclipse.debug.ui.DebugUITools;
import org.eclipse.debug.ui.IDebugModelPresentation;
import org.eclipse.ui.statushandlers.StatusManager;
import org.eclipse.statet.jcommons.lang.Disposable;
import org.eclipse.statet.internal.r.debug.ui.Messages;
import org.eclipse.statet.internal.r.debug.ui.RDebugUIPlugin;
import org.eclipse.statet.r.debug.core.RDebugModel;
import org.eclipse.statet.r.debug.core.breakpoints.IRBreakpoint;
public class BreakpointsHelper implements IBreakpointsListener, Disposable {
class UpdateRunnable implements IWorkspaceRunnable {
private final IBreakpoint[] breakpoints;
private List<IStatus> errors;
public UpdateRunnable(final IBreakpoint[] breakpoints) {
this.breakpoints= breakpoints;
}
public void exec() {
try {
ResourcesPlugin.getWorkspace().run(this, null, 0, null);
log(null);
}
catch (final CoreException e) {
log(e);
}
}
private void log(final CoreException runError) {
IStatus status= null;
if (this.errors != null) {
status= new MultiStatus(RDebugUIPlugin.BUNDLE_ID, 0,
this.errors.toArray(new IStatus[this.errors.size()]),
"An error occurred when updating UI information of R breakpoints.",
runError );
}
else if (runError != null) {
status= new Status(IStatus.ERROR, RDebugUIPlugin.BUNDLE_ID,
"An error occurred when updating UI information of R breakpoints.",
runError );
}
if (status != null) {
StatusManager.getManager().handle(status, StatusManager.LOG);
}
}
private boolean exists(final IBreakpoint breakpoint) {
try {
final IMarker marker= breakpoint.getMarker();
return (marker != null && marker.exists());
}
catch (final Exception e) {
return false;
}
}
@Override
public void run(final IProgressMonitor monitor) throws CoreException {
for (int i= 0; i < this.breakpoints.length; i++) {
if (this.breakpoints[i] instanceof IRBreakpoint) {
try {
updateBreakpoint((IRBreakpoint) this.breakpoints[i]);
}
catch (final CoreException e) {
if (!exists(this.breakpoints[i])) {
continue;
}
if (this.errors == null) {
this.errors= new ArrayList<>();
}
this.errors.add(new Status(IStatus.ERROR, RDebugUIPlugin.BUNDLE_ID,
"An error occurred when updating breakpoint message.", e ));
}
}
}
}
}
private final IDebugModelPresentation labelProvider= DebugUITools.newDebugModelPresentation(RDebugModel.IDENTIFIER);
public BreakpointsHelper() {
DebugPlugin.getDefault().getBreakpointManager().addBreakpointListener(this);
}
@Override
public void dispose() {
final DebugPlugin debugPlugin= DebugPlugin.getDefault();
if (debugPlugin != null) {
debugPlugin.getBreakpointManager().removeBreakpointListener(this);
}
}
@Override
public void breakpointsAdded(final IBreakpoint[] breakpoints) {
if (containsRBreakpoint(breakpoints)) {
new UpdateRunnable(breakpoints).exec();
}
}
@Override
public void breakpointsChanged(final IBreakpoint[] breakpoints, final IMarkerDelta[] deltas) {
if (containsRBreakpoint(breakpoints)) {
new UpdateRunnable(breakpoints).exec();
}
}
@Override
public void breakpointsRemoved(final IBreakpoint[] breakpoints, final IMarkerDelta[] deltas) {
}
private boolean containsRBreakpoint(final IBreakpoint[] breakpoints) {
for (int i= 0; i < breakpoints.length; i++) {
if (breakpoints[i] instanceof IRBreakpoint) {
return true;
}
}
return false;
}
private void updateBreakpoint(final IRBreakpoint breakpoint) throws CoreException {
final String typeLabel;
final String detail= this.labelProvider.getText(breakpoint);
switch (breakpoint.getBreakpointType()) {
case RDebugModel.R_LINE_BREAKPOINT_TYPE_ID:
typeLabel= Messages.LineBreakpoint_name;
break;
case RDebugModel.R_METHOD_BREAKPOINT_TYPE_ID:
typeLabel= Messages.MethodBreakpoint_name;
break;
default:
return;
}
final IMarker marker= breakpoint.getMarker();
if (marker != null && marker.exists()) {
marker.setAttribute(IMarker.MESSAGE, typeLabel + ": " + detail); //$NON-NLS-1$
}
}
}