Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEugene Tarassov2015-03-10 19:22:52 +0000
committerEugene Tarassov2015-03-10 19:22:52 +0000
commit09d7b0b7c4ba6ae8a83e173f4b13d9af85d1cf34 (patch)
tree925f55f008bef91135907989d2614ac7006f41f0 /plugins/org.eclipse.tcf.cdt.ui/src
parent4904421444e5f3cb06871c5216c2666d82450cff (diff)
downloadorg.eclipse.tcf-09d7b0b7c4ba6ae8a83e173f4b13d9af85d1cf34.tar.gz
org.eclipse.tcf-09d7b0b7c4ba6ae8a83e173f4b13d9af85d1cf34.tar.xz
org.eclipse.tcf-09d7b0b7c4ba6ae8a83e173f4b13d9af85d1cf34.zip
TCF Debugger: fixed: Step Into Selection is disabled in the TCF debugger
Diffstat (limited to 'plugins/org.eclipse.tcf.cdt.ui/src')
-rw-r--r--plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/ui/TCFNodeAdapterFactory.java141
-rw-r--r--plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/ui/commands/StepIntoSelectionLocation.java457
-rw-r--r--plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/ui/commands/TCFStepIntoSelectionHandler.java239
3 files changed, 775 insertions, 62 deletions
diff --git a/plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/ui/TCFNodeAdapterFactory.java b/plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/ui/TCFNodeAdapterFactory.java
index d112ddb86..1c9d6ece9 100644
--- a/plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/ui/TCFNodeAdapterFactory.java
+++ b/plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/ui/TCFNodeAdapterFactory.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2010, 2012 Wind River Systems, Inc. and others.
+ * Copyright (c) 2010, 2015 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
@@ -10,6 +10,8 @@
*******************************************************************************/
package org.eclipse.tcf.internal.cdt.ui;
+import java.util.ArrayList;
+
import org.eclipse.cdt.debug.core.model.IReverseResumeHandler;
import org.eclipse.cdt.debug.core.model.IReverseStepIntoHandler;
import org.eclipse.cdt.debug.core.model.IReverseStepOverHandler;
@@ -29,6 +31,7 @@ import org.eclipse.tcf.internal.cdt.ui.commands.TCFReverseStepIntoCommand;
import org.eclipse.tcf.internal.cdt.ui.commands.TCFReverseStepOverCommand;
import org.eclipse.tcf.internal.cdt.ui.commands.TCFReverseStepReturnCommand;
import org.eclipse.tcf.internal.cdt.ui.commands.TCFReverseToggleCommand;
+import org.eclipse.tcf.internal.cdt.ui.commands.TCFStepIntoSelectionHandler;
import org.eclipse.tcf.internal.cdt.ui.disassembly.TCFDisassemblyBackend;
import org.eclipse.tcf.internal.cdt.ui.hover.TCFDebugTextHover;
import org.eclipse.tcf.internal.cdt.ui.sourcelookup.TCFSourceNotFoundPresentation;
@@ -42,7 +45,11 @@ import org.eclipse.tcf.internal.debug.ui.model.TCFNodeStackFrame;
@SuppressWarnings({ "rawtypes", "restriction" })
public class TCFNodeAdapterFactory implements IAdapterFactory {
- private static final Class<?>[] CLASSES = {
+ // Not available before CDT 8.2
+ private static final String STEP_INTO_SELECTION =
+ "org.eclipse.cdt.debug.core.model.IStepIntoSelectionHandler";
+
+ private static final Object[] class_names = {
IDisassemblyBackend.class,
ISteppingModeTarget.class,
ISuspendResume.class,
@@ -51,85 +58,95 @@ public class TCFNodeAdapterFactory implements IAdapterFactory {
IReverseStepIntoHandler.class,
IReverseStepOverHandler.class,
IReverseResumeHandler.class,
+ STEP_INTO_SELECTION,
IUncallHandler.class,
IPinProvider.class,
ICWatchpointTarget.class,
ISourceNotFoundPresentation.class
};
- private static final TCFSourceNotFoundPresentation fgSourceNotFoundPresentation = new TCFSourceNotFoundPresentation();
+ private static final Class[] class_list;
+
+ static {
+ ArrayList<Class> l = new ArrayList<Class>();
+ for (Object o : class_names) {
+ if (o instanceof Class) {
+ l.add((Class)o);
+ }
+ else {
+ try {
+ l.add(Class.forName((String)o));
+ }
+ catch (ClassNotFoundException e) {
+ }
+ }
+ }
+ class_list = l.toArray(new Class[l.size()]);
+ }
public Object getAdapter(Object obj, Class type) {
if (obj instanceof TCFNode) {
final TCFNode node = (TCFNode)obj;
TCFModel model = node.getModel();
- if (IDisassemblyBackend.class == type) {
- TCFDisassemblyBackend backend = new TCFDisassemblyBackend();
- if (backend.supportsDebugContext((TCFNode)obj)) return backend;
- }
- else if (ISteppingModeTarget.class == type) {
- ISteppingModeTarget target = (ISteppingModeTarget)model.getAdapter(type, node);
- if (target == null) model.setAdapter(type, target = new TCFSteppingModeTarget(model));
- return target;
- }
- else if (ISuspendResume.class == type) {
- TCFNodeExecContext exec = null;
- if (node instanceof TCFNodeExecContext) {
- exec = (TCFNodeExecContext)node;
+ Object handler = model.getAdapter(type, node);
+ if (handler == null) {
+ if (IDisassemblyBackend.class == type) {
+ TCFDisassemblyBackend backend = new TCFDisassemblyBackend();
+ if (backend.supportsDebugContext(node)) return backend;
+ backend.dispose();
}
- else if (node instanceof TCFNodeStackFrame) {
- exec = (TCFNodeExecContext)node.getParent();
+ else if (ISteppingModeTarget.class == type) {
+ model.setAdapter(type, handler = new TCFSteppingModeTarget(model));
}
- if (exec != null) {
- return new TCFSuspendResumeAdapter(exec);
+ else if (ISuspendResume.class == type) {
+ TCFNodeExecContext exec = null;
+ if (node instanceof TCFNodeExecContext) {
+ exec = (TCFNodeExecContext)node;
+ }
+ else if (node instanceof TCFNodeStackFrame) {
+ exec = (TCFNodeExecContext)node.getParent();
+ }
+ if (exec != null) {
+ return new TCFSuspendResumeAdapter(exec);
+ }
+ }
+ else if (ICEditorTextHover.class == type) {
+ model.setAdapter(type, handler = new TCFDebugTextHover());
+ }
+ else if (IReverseToggleHandler.class == type) {
+ model.setAdapter(type, handler = new TCFReverseToggleCommand());
+ }
+ else if (IReverseStepIntoHandler.class == type) {
+ model.setAdapter(type, handler = new TCFReverseStepIntoCommand(model));
+ }
+ else if (IReverseStepOverHandler.class == type) {
+ model.setAdapter(type, handler = new TCFReverseStepOverCommand(model));
+ }
+ else if (IUncallHandler.class == type) {
+ model.setAdapter(type, handler = new TCFReverseStepReturnCommand(model));
+ }
+ else if (IReverseResumeHandler.class == type) {
+ model.setAdapter(type, handler = new TCFReverseResumeCommand(model));
+ }
+ else if (IPinProvider.class == type) {
+ model.setAdapter(type, handler = new TCFPinViewCommand(model));
+ }
+ else if (ICWatchpointTarget.class == type) {
+ if (node instanceof TCFNodeExpression) return new TCFWatchpointTarget((TCFNodeExpression)node);
+ }
+ else if (ISourceNotFoundPresentation.class == type) {
+ model.setAdapter(type, handler = new TCFSourceNotFoundPresentation());
+ }
+ else if (type.getName().equals(STEP_INTO_SELECTION)) {
+ model.setAdapter(type, handler = new TCFStepIntoSelectionHandler());
}
}
- else if (ICEditorTextHover.class == type) {
- ICEditorTextHover hover = (ICEditorTextHover)model.getAdapter(type, node);
- if (hover == null) model.setAdapter(type, hover = new TCFDebugTextHover());
- return hover;
- }
- else if (IReverseToggleHandler.class == type) {
- IReverseToggleHandler handler = (IReverseToggleHandler)model.getAdapter(type, node);
- if (handler == null) model.setAdapter(type, handler = new TCFReverseToggleCommand());
- return handler;
- }
- else if (IReverseStepIntoHandler.class == type) {
- IReverseStepIntoHandler handler = (IReverseStepIntoHandler)model.getAdapter(type, node);
- if (handler == null) model.setAdapter(type, handler = new TCFReverseStepIntoCommand(model));
- return handler;
- }
- else if (IReverseStepOverHandler.class == type) {
- IReverseStepOverHandler handler = (IReverseStepOverHandler)model.getAdapter(type, node);
- if (handler == null) model.setAdapter(type, handler = new TCFReverseStepOverCommand(model));
- return handler;
- }
- else if (IUncallHandler.class == type) {
- IUncallHandler handler = (IUncallHandler)model.getAdapter(type, node);
- if (handler == null) model.setAdapter(type, handler = new TCFReverseStepReturnCommand(model));
- return handler;
- }
- else if (IReverseResumeHandler.class == type) {
- IReverseResumeHandler handler = (IReverseResumeHandler)model.getAdapter(type, node);
- if (handler == null) model.setAdapter(type, handler = new TCFReverseResumeCommand(model));
- return handler;
- }
- else if (IPinProvider.class == type) {
- IPinProvider handler = (IPinProvider)model.getAdapter(type, node);
- if (handler == null) model.setAdapter(type, handler = new TCFPinViewCommand(model));
- return handler;
- }
- else if (ICWatchpointTarget.class == type) {
- if (node instanceof TCFNodeExpression) return new TCFWatchpointTarget((TCFNodeExpression)node);
- }
- else if (ISourceNotFoundPresentation.class == type) {
- return fgSourceNotFoundPresentation;
- }
+ return handler;
}
return null;
}
public Class[] getAdapterList() {
- return CLASSES;
+ return class_list;
}
}
diff --git a/plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/ui/commands/StepIntoSelectionLocation.java b/plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/ui/commands/StepIntoSelectionLocation.java
new file mode 100644
index 000000000..bdda7f2ca
--- /dev/null
+++ b/plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/ui/commands/StepIntoSelectionLocation.java
@@ -0,0 +1,457 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Xilinx, 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Xilinx - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tcf.internal.cdt.ui.commands;
+
+import static java.lang.Math.max;
+import static java.lang.Math.min;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.cdt.core.CCorePlugin;
+import org.eclipse.cdt.core.dom.IName;
+import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
+import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
+import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
+import org.eclipse.cdt.core.dom.ast.IASTImplicitName;
+import org.eclipse.cdt.core.dom.ast.IASTImplicitNameOwner;
+import org.eclipse.cdt.core.dom.ast.IASTName;
+import org.eclipse.cdt.core.dom.ast.IASTNode;
+import org.eclipse.cdt.core.dom.ast.IASTNodeSelector;
+import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
+import org.eclipse.cdt.core.dom.ast.IBinding;
+import org.eclipse.cdt.core.dom.ast.IParameter;
+import org.eclipse.cdt.core.dom.ast.IProblemBinding;
+import org.eclipse.cdt.core.dom.ast.IType;
+import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateDeclaration;
+import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUsingDeclaration;
+import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
+import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization;
+import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter;
+import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDeclaration;
+import org.eclipse.cdt.core.index.IIndex;
+import org.eclipse.cdt.core.index.IIndexManager;
+import org.eclipse.cdt.core.index.IIndexName;
+import org.eclipse.cdt.core.model.ICElement;
+import org.eclipse.cdt.core.model.ICProject;
+import org.eclipse.cdt.core.model.IFunctionDeclaration;
+import org.eclipse.cdt.core.model.ILanguage;
+import org.eclipse.cdt.core.model.ITranslationUnit;
+import org.eclipse.cdt.core.parser.util.ArrayUtil;
+import org.eclipse.cdt.debug.internal.ui.CDebugUIUtils;
+import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
+import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
+import org.eclipse.cdt.internal.core.index.IIndexFragmentName;
+import org.eclipse.cdt.internal.core.model.ASTCache.ASTRunnable;
+import org.eclipse.cdt.internal.core.model.ext.CElementHandleFactory;
+import org.eclipse.cdt.internal.core.model.ext.ICElementHandle;
+import org.eclipse.cdt.internal.ui.editor.ASTProvider;
+import org.eclipse.cdt.internal.ui.editor.CEditor;
+import org.eclipse.cdt.internal.ui.viewsupport.IndexUI;
+import org.eclipse.cdt.ui.CUIPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.debug.core.commands.IDebugCommandRequest;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.text.Region;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.tcf.internal.cdt.ui.Activator;
+import org.eclipse.tcf.internal.debug.ui.model.TCFModel;
+import org.eclipse.tcf.internal.debug.ui.model.TCFNodeExecContext;
+import org.eclipse.tcf.internal.debug.ui.model.TCFNodeStackFrame;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.editors.text.TextEditor;
+
+@SuppressWarnings("restriction")
+class StepIntoSelectionLocation {
+
+ IDebugCommandRequest request;
+ TCFNodeExecContext node;
+ TextEditor editor;
+ ITextSelection text_selection;
+ String text_file;
+ int text_line;
+ ITranslationUnit compilation_unit;
+ IIndex project_index;
+ IFunctionDeclaration[] resolved_functions;
+ IFunctionDeclaration target_function;
+
+ private enum NameKind { REFERENCE, DECLARATION, USING_DECL, DEFINITION }
+
+ void getTextLocation(IDebugCommandRequest request) {
+ this.request = request;
+ Object[] elements = request.getElements();
+ if (elements.length != 1) return;
+
+ if (elements[0] instanceof TCFNodeExecContext) {
+ node = (TCFNodeExecContext)elements[0];
+ }
+ else if (elements[0] instanceof TCFNodeStackFrame) {
+ node = (TCFNodeExecContext)((TCFNodeStackFrame)elements[0]).getParent();
+ }
+ else {
+ return;
+ }
+
+ IWorkbench wb = PlatformUI.getWorkbench();
+ IWorkbenchWindow win = wb.getActiveWorkbenchWindow();
+ if (win != null && win.getActivePage() != null) {
+ IEditorPart part = win.getActivePage().getActiveEditor();
+ if (part instanceof TextEditor) editor = (TextEditor)part;
+ }
+ if (editor != null) {
+ ISelection selection = editor.getEditorSite().getSelectionProvider().getSelection();
+ if (selection instanceof ITextSelection) text_selection = (ITextSelection)selection;
+ try {
+ text_file = CDebugUIUtils.getEditorFilePath(editor.getEditorInput());
+ }
+ catch (CoreException x) {
+ request.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID,
+ IStatus.ERROR, TCFModel.getErrorMessage(x, true), x));
+ return;
+ }
+ }
+ if (text_selection != null) {
+ text_line = text_selection.getStartLine() + 1;
+ }
+ }
+
+ private IName[] findDefinitions(IIndex index, IASTTranslationUnit ast, StepIntoSelectionLocation.NameKind kind, IBinding binding) throws CoreException {
+ List<IASTName> declNames = new ArrayList<IASTName>();
+ declNames.addAll(Arrays.asList(ast.getDefinitionsInAST(binding)));
+ for (Iterator<IASTName> i = declNames.iterator(); i.hasNext();) {
+ IASTName name = i.next();
+ final IBinding b2 = name.resolveBinding();
+ if (b2 instanceof ICPPUsingDeclaration) {
+ i.remove();
+ }
+ if (binding != b2 && binding instanceof ICPPSpecialization) {
+ // Make sure binding specializes b2 so that for instance we do
+ // not navigate from
+ // one partial specialization to another.
+ IBinding spec = binding;
+ while (spec instanceof ICPPSpecialization) {
+ spec = ((ICPPSpecialization) spec).getSpecializedBinding();
+ if (spec == b2)
+ break;
+ }
+ if (!(spec instanceof ICPPSpecialization)) {
+ i.remove();
+ }
+ }
+ }
+ if (!declNames.isEmpty()) {
+ return declNames.toArray(new IASTName[declNames.size()]);
+ }
+
+ // 2. Try definition in index.
+ return index.findNames(binding, IIndex.FIND_DEFINITIONS | IIndex.SEARCH_ACROSS_LANGUAGE_BOUNDARIES);
+ }
+
+ private IName[] findDeclarations(IIndex index, IASTTranslationUnit ast, IBinding binding) throws CoreException {
+ IASTName[] astNames = ast.getDeclarationsInAST(binding);
+ ArrayList<IASTName> usingDeclarations = null;
+ for (int i = 0; i < astNames.length; i++) {
+ IASTName name = astNames[i];
+ if (name.isDefinition()) {
+ astNames[i] = null;
+ } else if (CPPVisitor.findAncestorWithType(name, ICPPASTUsingDeclaration.class) != null) {
+ if (usingDeclarations == null)
+ usingDeclarations = new ArrayList<IASTName>(1);
+ usingDeclarations.add(name);
+ astNames[i] = null;
+ }
+ }
+ IName[] declNames = ArrayUtil.removeNulls(astNames);
+ if (declNames.length == 0) {
+ declNames = index.findNames(binding, IIndex.FIND_DECLARATIONS | IIndex.SEARCH_ACROSS_LANGUAGE_BOUNDARIES);
+ }
+ // 'using' declarations are considered only when there are no other
+ // declarations.
+ if (declNames.length == 0 && usingDeclarations != null) {
+ declNames = usingDeclarations.toArray(new IName[usingDeclarations.size()]);
+ }
+ return declNames;
+ }
+
+ private IName[] findNames(IIndex index, IASTTranslationUnit ast, StepIntoSelectionLocation.NameKind kind, IBinding binding) throws CoreException {
+ IName[] declNames;
+ if (kind == NameKind.DEFINITION) {
+ declNames = findDeclarations(index, ast, binding);
+ }
+ else {
+ declNames = findDefinitions(index, ast, kind, binding);
+ }
+
+ if (declNames.length == 0) {
+ if (kind == NameKind.DEFINITION) {
+ declNames = findDefinitions(index, ast, kind, binding);
+ }
+ else {
+ declNames = findDeclarations(index, ast, binding);
+ }
+ }
+ return declNames;
+ }
+
+ private IName[] findDeclNames(IASTTranslationUnit ast, StepIntoSelectionLocation.NameKind kind, IBinding binding) throws CoreException {
+ IName[] declNames = findNames(project_index, ast, kind, binding);
+ while (declNames.length == 0 && binding instanceof ICPPSpecialization) {
+ binding = ((ICPPSpecialization) binding).getSpecializedBinding();
+ if (binding != null && !(binding instanceof IProblemBinding)) {
+ declNames = findNames(project_index, ast, NameKind.DEFINITION, binding);
+ }
+ }
+ if (declNames.length == 0 && binding instanceof ICPPMethod) {
+ ICPPMethod method = (ICPPMethod) binding;
+ if (method.isImplicit()) {
+ IBinding clsBinding = method.getClassOwner();
+ if (clsBinding != null && !(clsBinding instanceof IProblemBinding)) {
+ declNames = findNames(project_index, ast, NameKind.REFERENCE, clsBinding);
+ }
+ }
+ }
+ return declNames;
+ }
+
+ /*
+ * Returns definitions of bindings referenced by implicit name at the given location.
+ */
+ private IName[] findImplicitTargets(IASTTranslationUnit ast, IASTNodeSelector nodeSelector, int offset, int length) throws CoreException {
+ IName[] definitions = IName.EMPTY_ARRAY;
+ IASTName firstName = nodeSelector.findEnclosingImplicitName(offset, length);
+ if (firstName != null) {
+ IASTImplicitNameOwner owner = (IASTImplicitNameOwner) firstName.getParent();
+ for (IASTImplicitName name : owner.getImplicitNames()) {
+ if (((ASTNode) name).getOffset() == ((ASTNode) firstName).getOffset()) {
+ IBinding binding = name.resolveBinding(); // Guaranteed to
+ // resolve.
+ IName[] declNames = findDeclNames(ast, NameKind.REFERENCE, binding);
+ definitions = ArrayUtil.addAll(definitions, declNames);
+ }
+ }
+ }
+ return ArrayUtil.trim(definitions);
+ }
+
+ private static IBinding getBinding(IName name) {
+ if (name instanceof IASTName) {
+ return ((IASTName) name).resolveBinding();
+ }
+ else if (name instanceof IIndexFragmentName) {
+ try {
+ return ((IIndexFragmentName) name).getBinding();
+ }
+ catch (CoreException e) {
+ // Fall through to return null.
+ }
+ }
+ return null;
+ }
+
+ private static StepIntoSelectionLocation.NameKind getNameKind(IName name) {
+ if (name.isDefinition()) {
+ if (getBinding(name) instanceof ICPPUsingDeclaration) {
+ return NameKind.USING_DECL;
+ }
+ else {
+ return NameKind.DEFINITION;
+ }
+ }
+ else if (name.isDeclaration()) {
+ return NameKind.DECLARATION;
+ }
+ return NameKind.REFERENCE;
+ }
+
+ private boolean areOverlappingNames(IName n1, IName n2) {
+ if (n1 == n2)
+ return true;
+
+ IASTFileLocation loc1 = n1.getFileLocation();
+ IASTFileLocation loc2 = n2.getFileLocation();
+ if (loc1 == null || loc2 == null) return false;
+ return loc1.getFileName().equals(loc2.getFileName())
+ && max(loc1.getNodeOffset(), loc2.getNodeOffset()) < min(loc1.getNodeOffset() + loc1.getNodeLength(), loc2.getNodeOffset() + loc2.getNodeLength());
+ }
+
+ private static IASTDeclaration getEnclosingFunctionDefinition(IASTNode node) {
+ while (node != null && !(node instanceof IASTFunctionDefinition)) {
+ node = node.getParent();
+ }
+ return (IASTDeclaration) node;
+ }
+
+ private static boolean isInSameFunction(IASTName refName, IName funcDeclName) {
+ if (funcDeclName instanceof IASTName) {
+ IASTDeclaration fdef = getEnclosingFunctionDefinition((IASTNode) funcDeclName);
+ return fdef != null && fdef.contains(refName);
+ }
+ return false;
+ }
+
+ private static IASTDeclaration getEnclosingTemplateDeclaration(IASTNode node) {
+ while (node != null && !(node instanceof ICPPASTTemplateDeclaration)) {
+ node = node.getParent();
+ }
+ return (IASTDeclaration) node;
+ }
+
+ private static boolean isInSameTemplate(IASTName refName, IName templateDeclName) {
+ if (templateDeclName instanceof IASTName) {
+ IASTDeclaration template = getEnclosingTemplateDeclaration(refName);
+ return template != null && template.contains(refName);
+ }
+ return false;
+ }
+
+ private ICElementHandle getCElementForName(ICProject project, IIndex index, IName declName) throws CoreException {
+ if (declName instanceof IIndexName) {
+ return IndexUI.getCElementForName(project, index, (IIndexName) declName);
+ }
+ if (declName instanceof IASTName) {
+ IASTName astName = (IASTName) declName;
+ IBinding binding = astName.resolveBinding();
+ if (binding != null) {
+ ITranslationUnit tu = IndexUI.getTranslationUnit(project, astName);
+ if (tu != null) {
+ IASTFileLocation loc = astName.getFileLocation();
+ IRegion region = new Region(loc.getNodeOffset(), loc.getNodeLength());
+ return CElementHandleFactory.create(tu, binding, astName.isDefinition(), region, 0);
+ }
+ }
+ return null;
+ }
+ return null;
+ }
+
+ private void filterToFunctions(ICProject project, IIndex index, IName[] declNames, List<IFunctionDeclaration> functionElements) {
+ for (IName declName : declNames) {
+ try {
+ ICElement elem = getCElementForName(project, index, declName);
+ if (elem instanceof IFunctionDeclaration) {
+ functionElements.add((IFunctionDeclaration) elem);
+ }
+ }
+ catch (CoreException e) {
+ CUIPlugin.log(e);
+ }
+ }
+ }
+
+ void getTargetFunction(IDebugCommandRequest request) {
+ getTextLocation(request);
+ if (text_selection == null) return;
+ text_line = text_selection.getStartLine() + 1;
+ if (editor instanceof CEditor) {
+ compilation_unit = ((CEditor)editor).getInputCElement();
+ if (compilation_unit == null) return;
+ try {
+ project_index = CCorePlugin.getIndexManager().getIndex(compilation_unit.getCProject(),
+ IIndexManager.ADD_DEPENDENCIES | IIndexManager.ADD_DEPENDENT | IIndexManager.ADD_EXTENSION_FRAGMENTS_NAVIGATION);
+ }
+ catch (Exception x) {
+ request.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID,
+ IStatus.ERROR, TCFModel.getErrorMessage(x, true), x));
+ return;
+ }
+ IStatus status = ASTProvider.getASTProvider().runOnAST(compilation_unit, ASTProvider.WAIT_NO, null, new ASTRunnable() {
+ @Override
+ public IStatus runOnAST(ILanguage lang, IASTTranslationUnit ast) throws CoreException {
+ if (ast == null) return Status.OK_STATUS;
+
+ int selection_start = text_selection.getOffset();
+ int selection_length = text_selection.getLength();
+
+ final IASTNodeSelector node_selector = ast.getNodeSelector(null);
+
+ IASTName source_name = node_selector.findEnclosingName(selection_start, selection_length);
+ if (source_name == null) {
+ return new Status(IStatus.ERROR, Activator.PLUGIN_ID,
+ "Unable to resolve the selection to a semantic object");
+ }
+
+ IName[] implicitTargets = findImplicitTargets(ast, node_selector, selection_start, selection_length);
+
+ StepIntoSelectionLocation.NameKind kind = getNameKind(source_name);
+ IBinding b = source_name.resolveBinding();
+ IBinding[] bindings = new IBinding[] { b };
+ if (b instanceof IProblemBinding) {
+ IBinding[] candidateBindings = ((IProblemBinding) b).getCandidateBindings();
+ if (candidateBindings.length != 0) {
+ bindings = candidateBindings;
+ }
+ }
+ else if (kind == NameKind.DEFINITION && b instanceof IType) {
+ // No resolution of type definitions.
+ return Status.OK_STATUS;
+ }
+
+ IName[] targets = IName.EMPTY_ARRAY;
+ String file_path = ast.getFilePath();
+ for (IBinding binding : bindings) {
+ if (binding != null && !(binding instanceof IProblemBinding)) {
+ IName[] names = findDeclNames(ast, kind, binding);
+ for (final IName name : names) {
+ if (name != null) {
+ if (name instanceof IIndexName && file_path.equals(((IIndexName)name).getFileLocation().getFileName())) {
+ // Exclude index names from the current file.
+ }
+ else if (areOverlappingNames(name, source_name)) {
+ // Exclude the current location.
+ }
+ else if (binding instanceof IParameter) {
+ if (isInSameFunction(source_name, name)) {
+ targets = ArrayUtil.append(targets, name);
+ }
+ }
+ else if (binding instanceof ICPPTemplateParameter) {
+ if (isInSameTemplate(source_name, name)) {
+ targets = ArrayUtil.append(targets, name);
+ }
+ }
+ else {
+ targets = ArrayUtil.append(targets, name);
+ }
+ }
+ }
+ }
+ }
+
+ targets = ArrayUtil.trim(ArrayUtil.addAll(targets, implicitTargets));
+
+ final ArrayList<IFunctionDeclaration> functionElements = new ArrayList<IFunctionDeclaration>();
+ filterToFunctions(compilation_unit.getCProject(), project_index, targets, functionElements);
+
+ // save the resolved function declarations
+ resolved_functions = functionElements.toArray(new IFunctionDeclaration[functionElements.size()]);
+
+ return Status.OK_STATUS;
+ }
+ });
+ if (status.getSeverity() != Status.OK) request.setStatus(status);
+ }
+ if (resolved_functions != null && resolved_functions.length == 1 && resolved_functions[0] != null) {
+ target_function = resolved_functions[0];
+ }
+ }
+
+ boolean isValid() {
+ return request != null && request.getStatus() == null && text_file != null && text_line > 0;
+ }
+}
diff --git a/plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/ui/commands/TCFStepIntoSelectionHandler.java b/plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/ui/commands/TCFStepIntoSelectionHandler.java
new file mode 100644
index 000000000..ba39ed595
--- /dev/null
+++ b/plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/ui/commands/TCFStepIntoSelectionHandler.java
@@ -0,0 +1,239 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Xilinx, 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Xilinx - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tcf.internal.cdt.ui.commands;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.debug.core.commands.IDebugCommandHandler;
+import org.eclipse.debug.core.commands.IDebugCommandRequest;
+import org.eclipse.debug.core.commands.IEnabledStateRequest;
+import org.eclipse.tcf.internal.cdt.ui.Activator;
+import org.eclipse.tcf.internal.debug.actions.TCFAction;
+import org.eclipse.tcf.internal.debug.model.TCFContextState;
+import org.eclipse.tcf.internal.debug.ui.model.TCFModel;
+import org.eclipse.tcf.protocol.IChannel;
+import org.eclipse.tcf.protocol.IToken;
+import org.eclipse.tcf.protocol.Protocol;
+import org.eclipse.tcf.services.IBreakpoints;
+import org.eclipse.tcf.services.IRunControl;
+import org.eclipse.tcf.services.IRunControl.RunControlContext;
+import org.eclipse.tcf.services.IRunControl.RunControlListener;
+import org.eclipse.tcf.util.TCFDataCache;
+
+public class TCFStepIntoSelectionHandler implements IDebugCommandHandler {
+
+ @Override
+ public void canExecute(final IEnabledStateRequest request) {
+ final StepIntoSelectionLocation l = new StepIntoSelectionLocation();
+ l.getTextLocation(request);
+
+ if (!l.isValid()) {
+ request.setEnabled(false);
+ request.done();
+ return;
+ }
+
+ Protocol.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ if (l.node.isDisposed()) {
+ done(null, false);
+ return;
+ }
+ TCFDataCache<TCFContextState> cache = l.node.getState();
+ if (!cache.validate(this)) return;
+ if (cache.getError() != null) {
+ done(cache.getError(), false);
+ return;
+ }
+ TCFContextState state = cache.getData();
+ done(null, state != null && state.is_suspended);
+ }
+ private void done(Throwable e, boolean enabled) {
+ if (e != null) {
+ request.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID,
+ IStatus.ERROR, TCFModel.getErrorMessage(e, true), e));
+ }
+ request.setEnabled(enabled);
+ request.done();
+ }
+ });
+ }
+
+ @Override
+ public boolean execute(final IDebugCommandRequest request) {
+ final StepIntoSelectionLocation l = new StepIntoSelectionLocation();
+ l.getTargetFunction(request);
+
+ if (!l.isValid()) {
+ request.done();
+ return true;
+ }
+
+ Protocol.invokeLater(new Runnable() {
+ boolean run_to_line_done;
+ boolean req_done;
+ String bp_id;
+ @Override
+ public void run() {
+ if (l.node.isDisposed()) {
+ done(null);
+ return;
+ }
+ IChannel channel = l.node.getChannel();
+ if (bp_id == null) {
+ IBreakpoints breakpoints = channel.getRemoteService(IBreakpoints.class);
+ if (breakpoints == null) {
+ done(new Exception("Cannot set breakpoint."));
+ return;
+ }
+ Map<String, Object> properties = new HashMap<String, Object>();
+ properties.put(IBreakpoints.PROP_FILE, l.text_file);
+ properties.put(IBreakpoints.PROP_LINE, l.text_line);
+ if (run_to_line_done) {
+ assert l.target_function != null;
+ properties.put(IBreakpoints.PROP_LOCATION, l.target_function.getElementName());
+ properties.put(IBreakpoints.PROP_SKIP_PROLOGUE, true);
+ }
+ properties.put(IBreakpoints.PROP_CONTEXT_IDS, new String[] { l.node.getID() });
+ properties.put(IBreakpoints.PROP_ENABLED, Boolean.TRUE);
+ bp_id = TCFAction.STEP_BREAKPOINT_PREFIX + l.node.getID();
+ properties.put(IBreakpoints.PROP_ID, bp_id);
+ breakpoints.add(properties, new IBreakpoints.DoneCommand() {
+ public void doneCommand(IToken token, Exception error) {
+ if (error != null) {
+ bp_id = null;
+ done(error);
+ }
+ else {
+ run();
+ }
+ }
+ });
+ return;
+ }
+ final IRunControl run_ctrl = channel.getRemoteService(IRunControl.class);
+ if (run_ctrl == null) {
+ done(new Exception("Cannot resume."));
+ return;
+ }
+ TCFDataCache<TCFContextState> state_cache = l.node.getState();
+ if (!state_cache.validate(this)) return;
+ if (state_cache.getError() != null) {
+ done(state_cache.getError());
+ return;
+ }
+ TCFContextState state = state_cache.getData();
+ if (state == null || !state.is_suspended) {
+ done(null);
+ return;
+ }
+ TCFDataCache<IRunControl.RunControlContext> ctx_cache = l.node.getRunContext();
+ if (!ctx_cache.validate(this)) return;
+ if (ctx_cache.getError() != null) {
+ done(ctx_cache.getError());
+ return;
+ }
+ final String node_id = l.node.getID();
+ run_ctrl.addListener(new RunControlListener() {
+ private void suspended() {
+ run_ctrl.removeListener(this);
+ if (!run_to_line_done) {
+ run_to_line_done = true;
+ if (l.target_function != null) {
+ assert bp_id != null;
+ IChannel channel = l.node.getChannel();
+ IBreakpoints breakpoints = channel.getRemoteService(IBreakpoints.class);
+ breakpoints.remove(new String[] { bp_id }, new IBreakpoints.DoneCommand() {
+ public void doneCommand(IToken token, Exception error) {
+ if (error != null) done(error);
+ else run();
+ }
+ });
+ bp_id = null;
+ return;
+ }
+ }
+ done(null);
+ }
+ public void contextSuspended(String context, String pc, String reason, Map<String,Object> params) {
+ if (node_id.equals(context)) {
+ suspended();
+ }
+ }
+ public void contextResumed(String context) {
+ }
+ public void contextRemoved(String[] context_ids) {
+ for (String context : context_ids) {
+ if (node_id.equals(context)) {
+ suspended();
+ return;
+ }
+ }
+ }
+ public void contextException(String context, String msg) {
+ }
+ public void contextChanged(RunControlContext[] contexts) {
+ }
+ public void contextAdded(RunControlContext[] contexts) {
+ }
+ public void containerSuspended(String context, String pc, String reason, Map<String,Object> params, String[] suspended_ids) {
+ for (String context2 : suspended_ids) {
+ if (node_id.equals(context2)) {
+ suspended();
+ return;
+ }
+ }
+ }
+ public void containerResumed(String[] context_ids) {
+ }
+ });
+ IRunControl.RunControlContext ctx = ctx_cache.getData();
+ ctx.resume(IRunControl.RM_RESUME, 1, new IRunControl.DoneCommand() {
+ public void doneCommand(IToken token, Exception error) {
+ if (error != null) {
+ done(error);
+ }
+ else if (!req_done) {
+ req_done = true;
+ request.done();
+ }
+ }
+ });
+ }
+ private void done(Throwable e) {
+ if (bp_id != null) {
+ IChannel channel = l.node.getChannel();
+ IBreakpoints breakpoints = channel.getRemoteService(IBreakpoints.class);
+ breakpoints.remove(new String[] { bp_id }, new IBreakpoints.DoneCommand() {
+ public void doneCommand(IToken token, Exception error) {
+ done(error);
+ }
+ });
+ bp_id = null;
+ return;
+ }
+ if (!req_done) {
+ if (e != null) {
+ request.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID,
+ IStatus.ERROR, TCFModel.getErrorMessage(e, true), e));
+ }
+ req_done = true;
+ request.done();
+ }
+ }
+ });
+ return true;
+ }
+}

Back to the top