/******************************************************************************* * Copyright (c) 2009, 2016 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 * Zend Technologies *******************************************************************************/ package org.eclipse.php.internal.debug.ui.breakpoint.adapter; import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.*; 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.ui.actions.IRunToLineTarget; import org.eclipse.debug.ui.actions.RunToLineHandler; import org.eclipse.dltk.core.IModelElement; import org.eclipse.dltk.internal.ui.editor.EditorUtility; import org.eclipse.jface.text.*; import org.eclipse.jface.viewers.ISelection; import org.eclipse.php.internal.core.documentModel.partitioner.PHPStructuredTextPartitioner; import org.eclipse.php.internal.debug.core.IPHPDebugConstants; import org.eclipse.php.internal.debug.core.model.PHPDebugElement; import org.eclipse.php.internal.debug.core.model.PHPRunToLineBreakpoint; import org.eclipse.php.internal.debug.core.xdebug.dbgp.model.DBGpElement; import org.eclipse.php.internal.debug.ui.PHPDebugUIMessages; import org.eclipse.php.internal.debug.ui.PHPDebugUIPlugin; import org.eclipse.php.internal.debug.ui.breakpoint.provider.DefaultPHPBreakpointProvider; import org.eclipse.php.internal.ui.util.StatusLineMessageTimerManager; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.texteditor.ITextEditor; /** * Run to line target for the PHP debugger */ public class PHPRunToLineAdapter implements IRunToLineTarget { /* * (non-Javadoc) * * @see * org.eclipse.debug.ui.actions.IRunToLineTarget#runToLine(org.eclipse.ui * .IWorkbenchPart, org.eclipse.jface.viewers.ISelection, * org.eclipse.debug.core.model.ISuspendResume) */ public void runToLine(IWorkbenchPart part, ISelection selection, ISuspendResume target) throws CoreException { IEditorPart editorPart = (IEditorPart) part; IEditorInput input = editorPart.getEditorInput(); String errorMessage = null; if (input == null) { errorMessage = PHPDebugUIMessages.PHPRunToLineAdapter_0; } else { ITextEditor textEditor = (ITextEditor) editorPart; IDocument document = textEditor.getDocumentProvider().getDocument(input); if (document == null) { errorMessage = PHPDebugUIMessages.PHPRunToLineAdapter_1; } else { ITextSelection textSelection = (ITextSelection) selection; int lineNumber = 0; try { lineNumber = document.getLineOfOffset(textSelection.getOffset()) + 1; } catch (BadLocationException e) { } // Figure out if the selected line is a valid line to place a // temporary breakpoint for the run-to-line int validLinePosition = DefaultPHPBreakpointProvider.getValidPosition(document, lineNumber); if (validLinePosition < 0) { StatusLineMessageTimerManager.setErrorMessage(PHPDebugUIMessages.CannotRunToLine, 1000, true); // hide // message // after // 1 // second return; } else { int validLineNumber = 0; try { validLineNumber = document.getLineOfOffset(validLinePosition) + 1; if (validLineNumber != lineNumber) { StatusLineMessageTimerManager.setErrorMessage(PHPDebugUIMessages.CannotRunToLine, 1000, true); // hide message after 1 second return; } } catch (BadLocationException ble) { StatusLineMessageTimerManager.setErrorMessage(PHPDebugUIMessages.CannotRunToLine, 1000, true); // hide // message // after // 1 // second return; } } if (lineNumber > 0) { if (getValidPosition(document, lineNumber) != -1) { if (target instanceof IAdaptable) { IDebugTarget debugTarget = (IDebugTarget) ((IAdaptable) target) .getAdapter(IDebugTarget.class); if (debugTarget != null) { IFile file = getFile(textEditor); IBreakpoint breakpoint = new PHPRunToLineBreakpoint(file, lineNumber); RunToLineHandler handler = new RunToLineHandler(debugTarget, target, breakpoint); handler.run(new NullProgressMonitor()); return; } } } else { errorMessage = PHPDebugUIMessages.PHPRunToLineAdapter_2; } } else { errorMessage = PHPDebugUIMessages.PHPRunToLineAdapter_2; } } } throw new CoreException(new Status(IStatus.ERROR, PHPDebugUIPlugin.getID(), IPHPDebugConstants.INTERNAL_ERROR, errorMessage, null)); } public boolean canRunToLine(IWorkbenchPart part, ISelection selection, ISuspendResume target) { // TODO: PHP Debug elements should have a shared marker and test for // here // This will be an enhancement to the generic debug API. if (target instanceof PHPDebugElement || target instanceof DBGpElement) { // allow running to the line only when the target is suspended. return target.isSuspended(); } return false; } /** * The file input for the TextEditor * * @return the IFile that this strategy is operating on */ protected IFile getFile(ITextEditor textEditor) { if (textEditor != null) { IModelElement modelElement = EditorUtility.getEditorInputModelElement(textEditor, false); if (modelElement != null) { return (IFile) modelElement.getResource(); } } return null; } /** * Finds a valid position somewhere on lineNumber in document, idoc, where a * breakpoint can be set and returns that position. -1 is returned if a * position could not be found. * * @param idoc * @param editorLineNumber * @return position to set breakpoint or -1 if no position could be found */ private int getValidPosition(IDocument idoc, int editorLineNumber) { int result = -1; if (idoc != null) { int startOffset = 0; int endOffset = 0; try { IRegion line = idoc.getLineInformation(editorLineNumber - 1); startOffset = line.getOffset(); endOffset = Math.max(line.getOffset(), line.getOffset() + line.getLength()); String lineText = idoc.get(startOffset, endOffset - startOffset).trim().toLowerCase(); // blank lines or lines with only an open PHP // tags cannot have a breakpoint if (lineText.equals("") //$NON-NLS-1$ || lineText.matches("^(<%|<[?](=|php)?|[?%]>)+$") //$NON-NLS-1$ || lineText.startsWith("//")) { //$NON-NLS-1$ result = -1; } else { // get all partitions for current line ITypedRegion[] partitions = null; partitions = idoc.computePartitioning(startOffset, endOffset - startOffset); for (int i = 0; i < partitions.length; ++i) { String type = partitions[i].getType(); // if found PHP // return that position if (PHPStructuredTextPartitioner.isPHPPartitionType(type)) { result = partitions[i].getOffset(); } } } } catch (BadLocationException e) { result = -1; } } return result; } }