blob: 01e70ddb6901799f2de115074a5a705aac0b8730 [file] [log] [blame]
/*=============================================================================#
# Copyright (c) 2010, 2020 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.IdentityHashMap;
import java.util.Map;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Status;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.model.IBreakpoint;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.Position;
import org.eclipse.osgi.util.NLS;
import org.eclipse.ui.statushandlers.StatusManager;
import org.eclipse.ui.texteditor.IMarkerUpdater;
import org.eclipse.ui.texteditor.MarkerUtilities;
import org.eclipse.statet.ltk.core.Ltk;
import org.eclipse.statet.ltk.model.core.LtkModels;
import org.eclipse.statet.ltk.model.core.SourceUnitManager;
import org.eclipse.statet.ltk.model.core.element.SourceUnit;
import org.eclipse.statet.r.core.model.RWorkspaceSourceUnit;
import org.eclipse.statet.r.debug.core.breakpoints.IRLineBreakpoint;
import org.eclipse.statet.r.debug.core.breakpoints.RLineBreakpointValidator;
import org.eclipse.statet.r.ui.RUI;
public class BreakpointMarkerUpdater implements IMarkerUpdater {
private final static String[] ATTRIBUTES= new String[] {
IMarker.LINE_NUMBER,
IMarker.CHAR_START,
IMarker.CHAR_END,
};
public BreakpointMarkerUpdater() {
}
@Override
public String getMarkerType() {
return IBreakpoint.BREAKPOINT_MARKER;
}
@Override
public String[] getAttribute() {
return ATTRIBUTES;
}
@Override
public boolean updateMarker(final IMarker marker, final IDocument document, final Position position) {
if (position == null) {
return true;
}
if (position.isDeleted()) {
return false;
}
final IBreakpoint breakpoint= DebugPlugin.getDefault().getBreakpointManager()
.getBreakpoint(marker);
if (breakpoint == null) {
return false;
}
if (breakpoint instanceof IRLineBreakpoint) {
return update((IRLineBreakpoint) breakpoint, marker, document, position);
}
return updateBasic(marker, document, position);
}
private boolean update(final IRLineBreakpoint breakpoint, final IMarker marker,
final IDocument document, final Position position) {
final IProgressMonitor monitor= new NullProgressMonitor();
final SourceUnitManager suManager= LtkModels.getSourceUnitManager();
SourceUnit su= suManager.getSourceUnit(Ltk.PERSISTENCE_CONTEXT, marker.getResource(),
null, true, monitor );
if (su != null) {
try {
su= suManager.getSourceUnit(Ltk.EDITOR_CONTEXT, su, null, true, monitor);
assert (su.getDocument(null) == document);
if (su instanceof RWorkspaceSourceUnit) {
final RWorkspaceSourceUnit rSourceUnit= (RWorkspaceSourceUnit)su;
final RLineBreakpointValidator validator= new RLineBreakpointValidator(rSourceUnit,
breakpoint.getBreakpointType(), position.getOffset(), monitor );
if (validator.getType() != null) {
validator.updateBreakpoint(breakpoint);
return true;
}
// // TODO search method ?
// if (breakpoint.getElementType() != IRLineBreakpoint.R_TOPLEVEL_COMMAND_ELEMENT_TYPE) {
// }
}
return false;
}
catch (final CoreException e) {
StatusManager.getManager().handle(new Status(IStatus.ERROR, RUI.BUNDLE_ID, 0,
NLS.bind("An error occurred when updating an R line breakpoint in ''{0}''.",
su.getElementName().getDisplayName() ), e ));
return false;
}
finally {
su.disconnect(monitor);
}
}
return false;
}
private boolean updateBasic(final IMarker marker,
final IDocument document, final Position position) {
boolean offsetsInitialized= false;
final int markerStart= MarkerUtilities.getCharStart(marker);
final int markerEnd= MarkerUtilities.getCharEnd(marker);
final Map<String, Object> attributes= new IdentityHashMap<>(4);
if (markerStart != -1 && markerEnd != -1) {
offsetsInitialized= true;
int offset= position.getOffset();
if (markerStart != offset) {
attributes.put(IMarker.CHAR_START, Integer.valueOf(offset));
}
offset+= position.getLength();
if (markerEnd != offset) {
attributes.put(IMarker.CHAR_END, Integer.valueOf(offset));
}
}
if (!offsetsInitialized || (!attributes.isEmpty() && MarkerUtilities.getLineNumber(marker) != -1)) {
try {
// marker line numbers are 1-based
attributes.put(IMarker.LINE_NUMBER, Integer.valueOf(
document.getLineOfOffset(position.getOffset()) + 1 ));
} catch (final BadLocationException x) {}
}
if (!attributes.isEmpty()) {
try {
marker.setAttributes(attributes);
}
catch (final CoreException e) {
StatusManager.getManager().handle(e.getStatus());
}
}
return true;
}
}