From bb755a01befd30c031965681aa8af8575bce52c5 Mon Sep 17 00:00:00 2001 From: aleon Date: Tue, 30 Apr 2013 11:59:16 -0400 Subject: Bug 244865 – Support for Step Into Selection First Implementation: * Non-stop as well as All-stop debugging * Function / Method name validation, arguments size validation (no arguments signature yet) * Ctrl-F5 as short key (consistent with JDT) * Hyper link support with Ctrl-Shift click * Junit Test (Services part) Change-Id: I58903b4b6b7f9fd39a827f5297ad23ac3f96186d Reviewed-on: https://git.eclipse.org/r/11305 Reviewed-by: Marc-Andre Laperle IP-Clean: Marc-Andre Laperle Tested-by: Marc-Andre Laperle --- .../cdt/dsf/debug/internal/ui/Messages.java | 4 +- .../cdt/dsf/debug/internal/ui/Messages.properties | 5 +- .../sourcelookup/DsfSourceSelectionResolver.java | 226 +++++++++++++++++++ .../ui/actions/DsfStepIntoSelectionCommand.java | 195 +++++++++++++++++ .../DsfStepIntoSelectionHyperlinkDetector.java | 239 +++++++++++++++++++++ .../debug/ui/actions/IDsfStepIntoSelection.java | 36 ++++ 6 files changed, 703 insertions(+), 2 deletions(-) create mode 100644 dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/internal/ui/sourcelookup/DsfSourceSelectionResolver.java create mode 100644 dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/actions/DsfStepIntoSelectionCommand.java create mode 100644 dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/actions/DsfStepIntoSelectionHyperlinkDetector.java create mode 100644 dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/actions/IDsfStepIntoSelection.java (limited to 'dsf/org.eclipse.cdt.dsf.ui/src/org') diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/internal/ui/Messages.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/internal/ui/Messages.java index f28a4ab53a5..0761ffcf449 100644 --- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/internal/ui/Messages.java +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/internal/ui/Messages.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009, 2010 Wind River Systems, Inc. and others. + * Copyright (c) 2009, 2013 Wind River Systems, Inc. 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 @@ -8,6 +8,7 @@ * Contributors: * Wind River Systems - initial API and implementation * Patrick Chuong (Texas Instruments) - Bug 315446: Invalid event breakpoint type (group) name + * Alvaro Sanchez-Leon (Ericsson AB) - Support for Step into selection (bug 244865) *******************************************************************************/ package org.eclipse.cdt.dsf.debug.internal.ui; @@ -16,6 +17,7 @@ import org.eclipse.osgi.util.NLS; public class Messages extends NLS { public static String ToggleBreakpointsTargetFactory_description; public static String ToggleBreakpointsTargetFactory_name; + public static String DsfUIStepIntoEditorSelection; static { // initialize resource bundle diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/internal/ui/Messages.properties b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/internal/ui/Messages.properties index 1faea82e179..37451dbd583 100644 --- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/internal/ui/Messages.properties +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/internal/ui/Messages.properties @@ -1,5 +1,5 @@ ############################################################################### -# Copyright (c) 2009, 2010 Wind River Systems and others. +# Copyright (c) 2009, 2013 Wind River Systems 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 @@ -8,7 +8,10 @@ # Contributors: # Wind River Systems - initial API and implementation # Ericsson - added Tracepoint support +# Ericsson - added Step into selection support ############################################################################### ToggleBreakpointsTargetFactory_description=Standard C/C++ breakpoint type. ToggleBreakpointsTargetFactory_name=C/C++ Breakpoints + +DsfUIStepIntoEditorSelection=Step Into diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/internal/ui/sourcelookup/DsfSourceSelectionResolver.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/internal/ui/sourcelookup/DsfSourceSelectionResolver.java new file mode 100644 index 00000000000..aa1f5ab0657 --- /dev/null +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/internal/ui/sourcelookup/DsfSourceSelectionResolver.java @@ -0,0 +1,226 @@ +/******************************************************************************* + * Copyright (c) 2013 Ericsson AB 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: + * Alvaro Sanchez-Leon (Ericsson AB) - Support for Step into selection (bug 244865) + *******************************************************************************/ +package org.eclipse.cdt.dsf.debug.internal.ui.sourcelookup; + +import org.eclipse.cdt.core.model.IFunctionDeclaration; +import org.eclipse.cdt.debug.internal.ui.CDebugUIUtils; +import org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin; +import org.eclipse.cdt.internal.ui.editor.CEditor; +import org.eclipse.cdt.internal.ui.editor.SelectionToDeclarationJob; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.ITextSelection; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.editors.text.TextEditor; +import org.eclipse.ui.texteditor.ITextEditor; + +public class DsfSourceSelectionResolver implements Runnable { + private ITextEditor fEditorPage = null; + private ITextSelection fSelection = null; + private LineLocation fLineLocation = new LineLocation(); + private IFunctionDeclaration fFunction = null; + private boolean fSuccessful = false; + + public class LineLocation { + private String fileName = null; + private int lineNumber = 0; + + public String getFileName() { + return fileName; + } + + public void setFileName(String fileName) { + this.fileName = fileName; + } + + public int getLineNumber() { + return lineNumber; + } + + public void setLineNumber(int lineNumber) { + this.lineNumber = lineNumber; + } + } + + private interface ResolveEditorRunnable extends Runnable { + TextEditor getEditor(); + } + + public DsfSourceSelectionResolver() { + + } + + public DsfSourceSelectionResolver(ITextEditor editor, ITextSelection selection) { + fEditorPage = editor; + fSelection = selection; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.dsf.debug.internal.ui.sourcelookup.IDsfSourceSelectionResolver#run() + */ + @Override + public void run() { + fEditorPage = resolveEditor(); + if (fEditorPage != null) { + ITextSelection selection = resolveSelection(); + if (selection != null) { + IFunctionDeclaration[] selectedFunctions = resolveSelectedFunction(selection); + + IFunctionDeclaration selFunction = null; + if (selectedFunctions == null || selectedFunctions.length != 1 || selectedFunctions[0] == null) { + //Unable to resolve selection to a function + return; + } else { + // Continue as expected + selFunction = selectedFunctions[0]; + } + + LineLocation selectedLine = resolveSelectedLine(); + if (selectedLine == null) { + // Unable to resolve the selected line + return; + } + + fLineLocation = selectedLine; + fFunction = selFunction; + fSuccessful = true; + } + } + } + + public ITextEditor resolveEditor() { + if (fEditorPage != null) { + return fEditorPage; + } + + final IWorkbench wb = DsfUIPlugin.getDefault().getWorkbench(); + // Run in UI thread to access UI resources + ResolveEditorRunnable reditorRunnable = new ResolveEditorRunnable() { + TextEditor result = null; + + @Override + public void run() { + IWorkbenchWindow win = wb.getActiveWorkbenchWindow(); + if (win == null || win.getActivePage() == null || win.getActivePage().getActiveEditor() == null) { + result = null; + } else { + IEditorPart editorPart = win.getActivePage().getActiveEditor(); + if (editorPart instanceof CEditor) { + result = (TextEditor) win.getActivePage().getActiveEditor(); + } + } + } + + @Override + public TextEditor getEditor() { + return result; + } + }; + + Display.getDefault().syncExec(reditorRunnable); + return reditorRunnable.getEditor(); + } + + private LineLocation resolveSelectedLine() { + String errorMessage = ""; //$NON-NLS-1$ + IEditorInput input = fEditorPage.getEditorInput(); + if (input == null) { + errorMessage = "Invalid Editor input on selection"; //$NON-NLS-1$ + } else { + IDocument document = fEditorPage.getDocumentProvider().getDocument(input); + if (document == null) { + errorMessage = "Invalid Editor Document input on selection"; //$NON-NLS-1$ + } else { + ITextSelection selection = resolveSelection(); + if (selection == null) { + errorMessage = "Invalid selection. Only textual selections are supported"; //$NON-NLS-1$ + } else { + String fileName = null; + try { + fileName = CDebugUIUtils.getEditorFilePath(input); + } catch (CoreException e) { + // unable to resolve the path + DsfUIPlugin.log(e); + return null; + } + + if (fileName == null) { + errorMessage = "Unable to resolve fileName from selection"; //$NON-NLS-1$ + DsfUIPlugin.logErrorMessage(errorMessage); + } else { + // Resolve the values + LineLocation lineLocation = new LineLocation(); + + lineLocation.setFileName(fileName); + lineLocation.setLineNumber(selection.getStartLine() + 1); + return lineLocation; + } + } + } + } + + DsfUIPlugin.logErrorMessage(errorMessage); + return null; + } + + public ITextSelection resolveSelection() { + if (fSelection != null) { + //Value received at construction time + return fSelection; + } + + ISelection selection = fEditorPage.getEditorSite().getSelectionProvider().getSelection(); + if (selection instanceof ITextSelection) { + return (ITextSelection) selection; + } + + return null; + } + + private IFunctionDeclaration[] resolveSelectedFunction(ITextSelection textSelection) { + if (textSelection != null) { + SelectionToDeclarationJob job; + try { + job = new SelectionToDeclarationJob(fEditorPage, textSelection); + job.schedule(); + job.join(); + } catch (CoreException e1) { + DsfUIPlugin.log(e1); + return null; + } catch (InterruptedException e) { + DsfUIPlugin.log(e); + return null; + } + + //fetch the result + return job.getSelectedFunctions(); + } + + return null; + } + + public LineLocation getLineLocation() { + return fLineLocation; + } + + public IFunctionDeclaration getFunction() { + return fFunction; + } + + public boolean isSuccessful() { + return fSuccessful; + } +} diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/actions/DsfStepIntoSelectionCommand.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/actions/DsfStepIntoSelectionCommand.java new file mode 100644 index 00000000000..7ec6ce2e0bb --- /dev/null +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/actions/DsfStepIntoSelectionCommand.java @@ -0,0 +1,195 @@ +/******************************************************************************* + * Copyright (c) 2013 Ericsson AB 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: + * Alvaro Sanchez-Leon (Ericsson AB) - Support for Step into selection (bug 244865) + *******************************************************************************/ +package org.eclipse.cdt.dsf.debug.ui.actions; + +import java.util.concurrent.ExecutionException; +import java.util.concurrent.RejectedExecutionException; + +import org.eclipse.cdt.core.model.IFunctionDeclaration; +import org.eclipse.cdt.debug.core.model.IStepIntoSelectionHandler; +import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; +import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants; +import org.eclipse.cdt.dsf.concurrent.Query; +import org.eclipse.cdt.dsf.datamodel.DMContexts; +import org.eclipse.cdt.dsf.debug.internal.ui.sourcelookup.DsfSourceSelectionResolver; +import org.eclipse.cdt.dsf.debug.internal.ui.sourcelookup.DsfSourceSelectionResolver.LineLocation; +import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext; +import org.eclipse.cdt.dsf.debug.service.IRunControl3; +import org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin; +import org.eclipse.cdt.dsf.service.DsfServicesTracker; +import org.eclipse.cdt.dsf.service.DsfSession; +import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.IDMVMContext; +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.debug.core.DebugException; +import org.eclipse.debug.core.IRequest; +import org.eclipse.debug.core.commands.AbstractDebugCommand; +import org.eclipse.debug.core.commands.IDebugCommandRequest; +import org.eclipse.debug.core.commands.IEnabledStateRequest; +import org.eclipse.debug.ui.DebugUITools; +import org.eclipse.debug.ui.IDebugUIConstants; +import org.eclipse.swt.widgets.Display; + +/** + * @since 2.4 + */ +public class DsfStepIntoSelectionCommand extends AbstractDebugCommand implements IStepIntoSelectionHandler, IDsfStepIntoSelection { + private final DsfServicesTracker fTracker; + public DsfStepIntoSelectionCommand(DsfSession session) { + fTracker = new DsfServicesTracker(DsfUIPlugin.getBundleContext(), session.getId()); + } + + public void dispose() { + fTracker.dispose(); + } + + @Override + protected void doExecute(Object[] targets, IProgressMonitor monitor, IRequest request) throws CoreException { + // No multiple selections allowed for Step into selection + if (targets.length != 1) { + return; + } + + final IExecutionDMContext dmc = DMContexts.getAncestorOfType(((IDMVMContext) targets[0]).getDMContext(), IExecutionDMContext.class); + if (dmc == null) { + return; + } + + DsfSourceSelectionResolver resolveSelection = new DsfSourceSelectionResolver(); + // Resolve UI selection from the the UI thread + Display.getDefault().syncExec(resolveSelection); + if (resolveSelection.isSuccessful()) { + LineLocation location = resolveSelection.getLineLocation(); + runToSelection(location.getFileName(), location.getLineNumber(), resolveSelection.getFunction(), dmc); + } else { + DsfUIPlugin.debug("DSfStepIntoSelectionCommand: Unable to resolve a selected function"); //$NON-NLS-1$ + } + } + + @Override + protected boolean isExecutable(Object[] targets, IProgressMonitor monitor, IEnabledStateRequest request) throws CoreException { + // No multiple selections allowed for Step into selection + if (targets.length != 1) { + return false; + } + + final IExecutionDMContext dmc = DMContexts.getAncestorOfType(((IDMVMContext) targets[0]).getDMContext(), IExecutionDMContext.class); + if (dmc == null) { + return false; + } + + return isExecutable(dmc, fTracker); + } + + private boolean isExecutable(final IExecutionDMContext dmc, final DsfServicesTracker tracker) { + final DsfSession session = DsfSession.getSession(dmc.getSessionId()); + if (session != null && session.isActive()) { + try { + Query query = new Query() { + @Override + protected void execute(DataRequestMonitor rm) { + IRunControl3 runControl = tracker.getService(IRunControl3.class); + if (runControl != null) { + // The selection may not be up to date, this is indicated with + // the selectedFunction being set to null + runControl.canStepIntoSelection(dmc, null, 0, null, rm); + } else { + rm.setData(false); + rm.done(); + } + } + }; + + session.getExecutor().execute(query); + return query.get(); + } catch (InterruptedException e) { + } catch (ExecutionException e) { + } + } + + return false; + } + + @Override + protected Object getTarget(Object element) { + if (element instanceof IDMVMContext) { + return element; + } + return null; + } + + @Override + protected boolean isRemainEnabled(IDebugCommandRequest request) { + return true; + } + + @Override + public boolean isExecutable(final IExecutionDMContext dmc) { + if (dmc == null) { + return false; + } + + DsfServicesTracker tracker = new DsfServicesTracker(DsfUIPlugin.getBundleContext(), dmc.getSessionId()); + boolean result = isExecutable(dmc, tracker); + tracker.dispose(); + return result; + } + + @Override + public void runToSelection(final String fileName, final int lineLocation, final IFunctionDeclaration selectedFunction, final IExecutionDMContext dmc) { + final DsfSession session = DsfSession.getSession(dmc.getSessionId()); + if (session != null && session.isActive()) { + Throwable exception = null; + try { + Query query = new Query() { + @Override + protected void execute(final DataRequestMonitor rm) { + DsfServicesTracker tracker = new DsfServicesTracker(DsfUIPlugin.getBundleContext(), session.getId()); + + boolean skipBreakpoints = DebugUITools.getPreferenceStore().getBoolean(IDebugUIConstants.PREF_SKIP_BREAKPOINTS_DURING_RUN_TO_LINE); + + IRunControl3 runControl = tracker.getService(IRunControl3.class); + tracker.dispose(); + StringBuilder eMessage = null; + if (runControl != null) { + runControl.stepIntoSelection(dmc, fileName, lineLocation, skipBreakpoints, selectedFunction, rm); + return; + } else { + eMessage = new StringBuilder("IRunControl3 service not available"); //$NON-NLS-1$ + } + + // Either runControl is null or an Exception has occurred + rm.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfStatusConstants.NOT_SUPPORTED, eMessage.toString(), null)); + rm.done(); + } + }; + + session.getExecutor().execute(query); + query.get(); + } catch (RejectedExecutionException e) { + exception = e; + } catch (InterruptedException e) { + exception = e; + } catch (ExecutionException e) { + exception = e; + } + + if (exception != null) { + DsfUIPlugin.log(new DebugException(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, DebugException.REQUEST_FAILED, "Failed executing Step into Selection", exception)));//$NON-NLS-1$ + } + } else { + DsfUIPlugin.log(new DebugException(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, DebugException.REQUEST_FAILED, "Debug session is not active", null))); //$NON-NLS-1$ + } + } + +} diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/actions/DsfStepIntoSelectionHyperlinkDetector.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/actions/DsfStepIntoSelectionHyperlinkDetector.java new file mode 100644 index 00000000000..5c2a5a09d03 --- /dev/null +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/actions/DsfStepIntoSelectionHyperlinkDetector.java @@ -0,0 +1,239 @@ +/******************************************************************************* + * Copyright (c) 2013 Ericsson AB 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: + * Alvaro Sanchez-Leon (Ericsson AB) - Support for Step into selection (bug 244865) + *******************************************************************************/ +package org.eclipse.cdt.dsf.debug.ui.actions; + +import org.eclipse.cdt.core.model.ICLanguageKeywords; +import org.eclipse.cdt.core.model.ILanguage; +import org.eclipse.cdt.core.model.IWorkingCopy; +import org.eclipse.cdt.dsf.datamodel.DMContexts; +import org.eclipse.cdt.dsf.datamodel.IDMContext; +import org.eclipse.cdt.dsf.debug.internal.ui.Messages; +import org.eclipse.cdt.dsf.debug.internal.ui.sourcelookup.DsfSourceSelectionResolver; +import org.eclipse.cdt.dsf.debug.internal.ui.sourcelookup.DsfSourceSelectionResolver.LineLocation; +import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext; +import org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin; +import org.eclipse.cdt.dsf.service.DsfSession; +import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.IDMVMContext; +import org.eclipse.cdt.internal.ui.editor.CEditor; +import org.eclipse.cdt.internal.ui.text.CWordFinder; +import org.eclipse.cdt.ui.CUIPlugin; +import org.eclipse.cdt.ui.text.ICPartitions; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.debug.ui.DebugUITools; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.ITextSelection; +import org.eclipse.jface.text.ITextViewer; +import org.eclipse.jface.text.Region; +import org.eclipse.jface.text.TextSelection; +import org.eclipse.jface.text.TextUtilities; +import org.eclipse.jface.text.hyperlink.AbstractHyperlinkDetector; +import org.eclipse.jface.text.hyperlink.IHyperlink; +import org.eclipse.ui.texteditor.ITextEditor; + +/** + * @since 2.4 + * + */ +public class DsfStepIntoSelectionHyperlinkDetector extends AbstractHyperlinkDetector { + private class DsfStepIntoSelectionHyperlink implements IHyperlink { + + private ITextSelection fSelection = null; + private IDsfStepIntoSelection fStepIntoSelectionCommand = null; + private DsfSourceSelectionResolver fSelectionResolver = null; + + /** + * Constructor + * + * @param stepIntoSelectionCommand + * @param region + */ + public DsfStepIntoSelectionHyperlink(DsfSourceSelectionResolver selectionResolver, IDsfStepIntoSelection stepIntoSelectionCommand) { + fSelection = selectionResolver.resolveSelection(); + fStepIntoSelectionCommand = stepIntoSelectionCommand; + fSelectionResolver = selectionResolver; + } + + /** + * @see org.eclipse.jface.text.hyperlink.IHyperlink#getHyperlinkRegion() + */ + @Override + public IRegion getHyperlinkRegion() { + return new Region(fSelection.getOffset(), fSelection.getLength()); + } + + /** + * @see org.eclipse.jface.text.hyperlink.IHyperlink#getHyperlinkText() + */ + @Override + public String getHyperlinkText() { + return Messages.DsfUIStepIntoEditorSelection; + } + + /** + * @see org.eclipse.jface.text.hyperlink.IHyperlink#getTypeLabel() + */ + @Override + public String getTypeLabel() { + return null; + } + + /** + * @see org.eclipse.jface.text.hyperlink.IHyperlink#open() + */ + @Override + public void open() { + // Resolve the debug context + final IExecutionDMContext dmc = resolveDebugContext(); + if (fSelectionResolver.isSuccessful() && dmc != null) { + LineLocation location = fSelectionResolver.getLineLocation(); + fStepIntoSelectionCommand.runToSelection(location.getFileName(), location.getLineNumber(), fSelectionResolver.getFunction(), dmc); + } else { + String message = null; + if (dmc == null) { + message = "DSfStepIntoSelection: Unable to resolve the debug context"; //$NON-NLS-1$ + } else { + message = "DSfStepIntoSelection: Unable to resolve a selected function"; //$NON-NLS-1$ + } + DsfUIPlugin.debug(message); + } + } + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.jface.text.hyperlink.IHyperlinkDetector#detectHyperlinks(org.eclipse.jface.text.ITextViewer, org.eclipse.jface.text.IRegion, boolean) + */ + @Override + public IHyperlink[] detectHyperlinks(ITextViewer textViewer, final IRegion region, boolean canShowMultipleHyperlinks) { + // Only valid in the context of a selection within the CEditor + ITextEditor editor = (ITextEditor) getAdapter(ITextEditor.class); + if (editor == null || region == null || !(editor instanceof CEditor)) + return null; + + ITextSelection selection = resolveSelection(editor, region); + if (selection == null) { + return null; + } + + // Shall only enable hyper link step into selection within a cdt debug execution context + IExecutionDMContext dmc = resolveDebugContext(); + if (dmc == null) { + return null; + } + + final DsfSession session = DsfSession.getSession(dmc.getSessionId()); + if (session == null || !session.isActive()) { + return null; + } + + IDsfStepIntoSelection stepIntoSelectionCommand = (IDsfStepIntoSelection) session.getModelAdapter(IDsfStepIntoSelection.class); + if (stepIntoSelectionCommand == null) { + return null; + } + + if (!stepIntoSelectionCommand.isExecutable(dmc)) { + return null; + } + + DsfSourceSelectionResolver functionResolver = new DsfSourceSelectionResolver(editor, selection); + functionResolver.run(); + // Resolve to a selected function + if (!functionResolver.isSuccessful()) { + // We are not pointing to a valid function + return null; + } + + return new IHyperlink[] { new DsfStepIntoSelectionHyperlink(functionResolver, stepIntoSelectionCommand) }; + } + + private ITextSelection resolveSelection(ITextEditor editor, IRegion region) { + ITextSelection selection = null; + if (editor != null) { + IDocument document = editor.getDocumentProvider().getDocument(editor.getEditorInput()); + final IWorkingCopy workingCopy = CUIPlugin.getDefault().getWorkingCopyManager().getWorkingCopy(editor.getEditorInput()); + + if (document != null && workingCopy != null) { + // Check partition type. + String partitionType; + try { + partitionType = TextUtilities.getContentType(document, ICPartitions.C_PARTITIONING, region.getOffset(), false); + if (IDocument.DEFAULT_CONTENT_TYPE.equals(partitionType)) { + // Regular code i.e. Not a Preprocessor directive. + IRegion wregion = getIdentifier(document, region.getOffset(), workingCopy.getLanguage()); + if (wregion != null) { + selection = new TextSelection(document, wregion.getOffset(), wregion.getLength()); + } + } + } catch (BadLocationException e) { + // Ignore to return null + } catch (CoreException e) { + // Ignore to return null + } + } + } + + return selection; + } + + /** + * Returns the identifier at the given offset, or {@code null} if the there is no identifier at the offset. + */ + private static IRegion getIdentifier(IDocument document, int offset, ILanguage language) throws BadLocationException { + @SuppressWarnings("restriction") + IRegion wordRegion = CWordFinder.findWord(document, offset); + if (wordRegion != null && wordRegion.getLength() > 0) { + String word = document.get(wordRegion.getOffset(), wordRegion.getLength()); + if (!Character.isDigit(word.charAt(0)) && !isLanguageKeyword(language, word)) { + return wordRegion; + } + } + return null; + } + + private static boolean isLanguageKeyword(ILanguage lang, String word) { + ICLanguageKeywords keywords = (ICLanguageKeywords) lang.getAdapter(ICLanguageKeywords.class); + if (keywords != null) { + for (String keyword : keywords.getKeywords()) { + if (keyword.equals(word)) + return true; + } + for (String type : keywords.getBuiltinTypes()) { + if (type.equals(word)) + return true; + } + for (String keyword : keywords.getPreprocessorKeywords()) { + if (keyword.charAt(0) == '#' && keyword.length() == word.length() + 1 && keyword.regionMatches(1, word, 0, word.length())) { + return true; + } + } + } + return false; + } + + private IExecutionDMContext resolveDebugContext() { + IExecutionDMContext execContext = null; + IAdaptable adaptableContext = DebugUITools.getDebugContext(); + IDMContext debugContext = null; + if (adaptableContext instanceof IDMVMContext) { + debugContext = ((IDMVMContext) adaptableContext).getDMContext(); + } + + if (debugContext != null) { + execContext = DMContexts.getAncestorOfType(debugContext, IExecutionDMContext.class); + } + + return execContext; + } +} diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/actions/IDsfStepIntoSelection.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/actions/IDsfStepIntoSelection.java new file mode 100644 index 00000000000..43ca6cd11c3 --- /dev/null +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/actions/IDsfStepIntoSelection.java @@ -0,0 +1,36 @@ +/******************************************************************************* + * Copyright (c) 2013 Ericsson AB 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: + * Alvaro Sanchez-Leon (Ericsson AB) - Support for Step into selection (bug 244865) + *******************************************************************************/ +package org.eclipse.cdt.dsf.debug.ui.actions; + +import org.eclipse.cdt.core.model.IFunctionDeclaration; +import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext; + +/** + * @since 2.4 + */ +public interface IDsfStepIntoSelection { + + /** + * Checks if within a state to perform step into selection + * @param dmc + * @return + */ + public boolean isExecutable(final IExecutionDMContext dmc); + + /** + * Carries out the actual step into selection action to the specified function location + * @param fileName + * @param lineLocation + * @param selectedFunction + * @param context + */ + public void runToSelection(final String fileName, final int lineLocation, final IFunctionDeclaration selectedFunction, final IExecutionDMContext context); +} -- cgit v1.2.3