Package org.erlide.debug.ui.utils

Source Code of org.erlide.debug.ui.utils.BreakpointMarkerUpdater

/*******************************************************************************
* Copyright (c) 2006, 2008 IBM Corporation 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:
*     IBM Corporation - initial API and implementation
*******************************************************************************/
package org.erlide.debug.ui.utils;

import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.IBreakpointManager;
import org.eclipse.debug.core.model.IBreakpoint;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.Position;
import org.eclipse.ui.texteditor.IMarkerUpdater;
import org.eclipse.ui.texteditor.MarkerUtilities;
import org.erlide.backend.debug.ErlDebugConstants;
import org.erlide.backend.debug.ErlangLineBreakpoint;
import org.erlide.backend.debug.IErlangBreakpoint;
import org.erlide.backend.debug.model.ErlangDebugTarget;
import org.erlide.util.ErlLogger;

/**
* This class provides a mechanism to correct the placement of a breakpoint
* marker when the related document is edited.
*
* This updater is used to cover the line number discrepancy cases that
* <code>BasicMarkerUpdater</code> does not:
* <ul>
* <li>If you insert a blank line at the start of the line of code, the
* breakpoint is moved from the blank line to the next viable line down,
* following the same breakpoint placement rules as creating a breakpoint</li>
*
* <li>If you select the contents of an entire line and delete them (leaving the
* line blank), the breakpoint is moved to the next viable line down, following
* the same breakpoint placement rules as creating a breakpoint</li>
*
* <li>If the breakpoint is on the last viable line of a class file and the line
* is removed via either of the aforementioned deletion cases, the breakpoint is
* removed</li>
*
* <li>If a line breakpoint would be moved to a valid method location with an
* invalid line number it is removed, see {@link https
* ://bugs.eclipse.org/bugs/show_bug.cgi?id=188676} for details</li>
*
* <li>If a line breakpoint will be moved to a line that already has a line
* breakpoint on it, the one being moved is removed, see {@link https
* ://bugs.eclipse.org/bugs/show_bug.cgi?id=129066} for details</li>
*
* <li>In the general deletion case if a valid breakpoint location can not be
* determined, it is removed</li>
* </ul>
*
* @since 3.3
*/
public class BreakpointMarkerUpdater implements IMarkerUpdater {

    public BreakpointMarkerUpdater() {
    }

    @Override
    public String[] getAttribute() {
        return new String[] { IMarker.LINE_NUMBER };
    }

    @Override
    public String getMarkerType() {
        return "org.eclipse.debug.core.breakpointMarker"; //$NON-NLS-1$
    }

    @Override
    public boolean updateMarker(final IMarker marker, final IDocument document,
            final Position position) {
        if (position.isDeleted()) {
            return false;
        }
        try {
            final int line = MarkerUtilities.getLineNumber(marker);
            final int newLine = document.getLineOfOffset(position.getOffset()) + 1;
            if (line == newLine) {
                return true;
            }
            final IBreakpointManager manager = DebugPlugin.getDefault()
                    .getBreakpointManager();
            final IBreakpoint breakpoint = manager.getBreakpoint(marker);
            if (breakpoint == null) {
                return false;
            }
            if (breakpoint instanceof ErlangLineBreakpoint) {
                final ErlangLineBreakpoint erlangLineBreakpoint = (ErlangLineBreakpoint) breakpoint;
                final ErlangDebugTarget target = erlangLineBreakpoint.getTarget();
                erlangLineBreakpoint.remove(target);
                MarkerUtilities.setLineNumber(marker, newLine);
                erlangLineBreakpoint.install(target);
                return true;
            }
            // if there exists a breakpoint on the line remove this one
            if (isLineBreakpointMarker(marker)) {
                ensureRanges(document, marker, line);
                return lineBreakpointExists(marker.getResource(), line, marker) == null;
            }
            // if the line info is a valid location with an invalid line
            // number,
            // a line breakpoint must be removed
            if (isLineBreakpointMarker(marker) && line == -1) {
                return false;
            }
            MarkerUtilities.setLineNumber(marker, line);
            if (isLineBreakpointMarker(marker)) {
                ensureRanges(document, marker, line);
            }
            return true;
        } catch (final BadLocationException e) {
            ErlLogger.error(e);
        } catch (final CoreException e) {
            ErlLogger.error(e);
        }
        return false;
    }

    private static boolean isLineBreakpointMarker(final IMarker marker)
            throws CoreException {
        return marker.getType() == ErlangLineBreakpoint.ERLANG_LINE_BREAKPOINT_MARKER_TYPE;
    }

    /**
     * Updates the charstart and charend ranges if necessary for the given line.
     * Returns immediately if the line is not valid (< 0 or greater than the
     * total line number count)
     *
     * @param document
     * @param marker
     * @param line
     * @throws BadLocationException
     */
    private void ensureRanges(final IDocument document, final IMarker marker,
            final int line) throws BadLocationException {
        if (line < 0 || line > document.getNumberOfLines()) {
            return;
        }
        final IRegion region = document.getLineInformation(line - 1);
        final int charstart = region.getOffset();
        final int charend = charstart + region.getLength();
        MarkerUtilities.setCharStart(marker, charstart);
        MarkerUtilities.setCharEnd(marker, charend);
    }

    /**
     * Searches for an existing line breakpoint on the specified line in the
     * current type that does not match the id of the specified marker
     *
     * @param resource
     *            the resource to care about
     * @param typeName
     *            the name of the type the breakpoint is in
     * @param lineNumber
     *            the number of the line the breakpoint is on
     * @param currentmarker
     *            the current marker we are comparing to see if it will be moved
     *            onto an existing one
     * @return an existing line breakpoint on the current line of the given
     *         resource and type if there is one
     * @throws CoreException
     *
     * @since 3.4
     */
    private IErlangBreakpoint lineBreakpointExists(final IResource resource,
            final int lineNumber, final IMarker currentmarker) throws CoreException {
        final IBreakpointManager manager = DebugPlugin.getDefault()
                .getBreakpointManager();
        final IBreakpoint[] breakpoints = manager
                .getBreakpoints(ErlDebugConstants.ID_ERLANG_DEBUG_MODEL);
        final String markerType = currentmarker.getType();
        for (int i = 0; i < breakpoints.length; i++) {
            if (!(breakpoints[i] instanceof IErlangBreakpoint)) {
                continue;
            }
            final IErlangBreakpoint breakpoint = (IErlangBreakpoint) breakpoints[i];
            final IMarker marker = breakpoint.getMarker();
            if (marker != null && marker.exists() && marker.getType().equals(markerType)
                    && currentmarker.getId() != marker.getId()) {
                if (marker instanceof ErlangLineBreakpoint) {
                    final ErlangLineBreakpoint erlangLineBreakpoint = (ErlangLineBreakpoint) marker;
                    if (erlangLineBreakpoint.getLineNumber() == lineNumber) {
                        return erlangLineBreakpoint;
                    }
                }
            }
        }
        return null;
    }

}
TOP

Related Classes of org.erlide.debug.ui.utils.BreakpointMarkerUpdater

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.