1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-06-08 18:26:01 +02:00

Call Hierarchy: Handling of multiple function definitions

This commit is contained in:
Markus Schorn 2006-08-28 15:28:46 +00:00
parent a7e7af7c47
commit 6f04ca7b10
11 changed files with 250 additions and 91 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 824 B

View file

@ -214,6 +214,7 @@ public class CPluginImages {
public static final ImageDescriptor DESC_OVR_VOLATILE= create(T_OVR, "volatile_co.gif"); //$NON-NLS-1$
public static final ImageDescriptor DESC_OVR_TEMPLATE= create(T_OVR, "template_co.gif"); //$NON-NLS-1$
public static final ImageDescriptor DESC_OVR_RELATESTO= create(T_OVR, "relatesto_co.gif"); //$NON-NLS-1$
public static final ImageDescriptor DESC_OVR_RELATESTOMULTIPLE= create(T_OVR, "relatestoMultiple_co.gif"); //$NON-NLS-1$
public static final ImageDescriptor DESC_OVR_REFERENCEDBY= create(T_OVR, "referencedby_co.gif"); //$NON-NLS-1$
public static final ImageDescriptor DESC_OVR_REC_RELATESTO= create(T_OVR, "rec_relatesto_co.gif"); //$NON-NLS-1$
public static final ImageDescriptor DESC_OVR_REC_REFERENCEDBY= create(T_OVR, "rec_referencedby_co.gif"); //$NON-NLS-1$

View file

@ -34,6 +34,7 @@ import org.eclipse.cdt.internal.ui.missingapi.CIndexReference;
import org.eclipse.cdt.internal.ui.missingapi.CalledByResult;
import org.eclipse.cdt.internal.ui.missingapi.CallsToResult;
import org.eclipse.cdt.internal.ui.viewsupport.AsyncTreeContentProvider;
import org.eclipse.cdt.internal.ui.viewsupport.WorkingSetFilterUI;
/**
* This is the content provider for the call hierarchy.
@ -42,6 +43,7 @@ public class CHContentProvider extends AsyncTreeContentProvider {
private static final IProgressMonitor NPM = new NullProgressMonitor();
private boolean fComputeReferencedBy = true;
private WorkingSetFilterUI fFilter;
/**
* Constructs the content provider.
@ -64,6 +66,9 @@ public class CHContentProvider extends AsyncTreeContentProvider {
ITranslationUnit tu= CModelUtil.getTranslationUnit(element);
return new Object[] { new CHNode(null, tu, 0, element) };
}
if (parentElement instanceof CHMultiDefNode) {
return ((CHMultiDefNode) parentElement).getChildNodes();
}
if (parentElement instanceof CHNode) {
CHNode node = (CHNode) parentElement;
if (node.isRecursive() || node.getRepresentedDeclaration() == null) {
@ -103,6 +108,7 @@ public class CHContentProvider extends AsyncTreeContentProvider {
for (int i = 0; i < elements.length; i++) {
ICElement element = elements[i];
if (element != null) {
if (fFilter == null || fFilter.isPartOfWorkingSet(element)) {
CIndexReference[] refs= calledBy.getReferences(element);
if (refs != null && refs.length > 0) {
CHNode node = createRefbyNode(parent, element, refs);
@ -110,6 +116,7 @@ public class CHContentProvider extends AsyncTreeContentProvider {
}
}
}
}
return result.toArray();
} catch (CoreException e) {
CUIPlugin.getDefault().log(e);
@ -130,8 +137,18 @@ public class CHContentProvider extends AsyncTreeContentProvider {
}
private CHNode createReftoNode(CHNode parent, ITranslationUnit tu, ICElement[] elements, CIndexReference[] references) {
CIndexReference firstRef= references[0];
CHNode node= new CHNode(parent, tu, firstRef.getTimestamp(), elements[0]);
assert elements.length > 0;
CHNode node;
long timestamp= references[0].getTimestamp();
if (elements.length == 1) {
node= new CHNode(parent, tu, timestamp, elements[0]);
}
else {
node= new CHMultiDefNode(parent, tu, timestamp, elements);
}
Arrays.sort(references, CIndexReference.COMPARE_OFFSET);
for (int i = 0; i < references.length; i++) {
CIndexReference reference = references[i];
@ -153,10 +170,13 @@ public class CHContentProvider extends AsyncTreeContentProvider {
CElementSet set = elementSets[i];
if (!set.isEmpty()) {
CIndexReference[] refs= callsTo.getReferences(set);
CHNode node = createReftoNode(parent, tu, set.getElements(), refs);
ICElement[] elements= set.getElements(fFilter);
if (elements.length > 0) {
CHNode node = createReftoNode(parent, tu, elements, refs);
result.add(node);
}
}
}
return result.toArray();
}
} catch (CoreException e) {
@ -173,4 +193,9 @@ public class CHContentProvider extends AsyncTreeContentProvider {
public boolean getComputeReferencedBy() {
return fComputeReferencedBy;
}
public void setWorkingSetFilter(WorkingSetFilterUI filterUI) {
fFilter= filterUI;
recompute();
}
}

View file

@ -17,6 +17,7 @@ import java.util.Iterator;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.IColorProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
@ -36,16 +37,17 @@ public class CHLabelProvider extends LabelProvider implements IColorProvider {
private CUILabelProvider fCLabelProvider= new CUILabelProvider(LABEL_OPTIONS_SIMPLE, 0);
private CHContentProvider fContentProvider;
private HashMap fCachedImages= new HashMap();
private Color fColorInactive;
public CHLabelProvider(Display display, CHContentProvider cp) {
// fColorInactive= display.getSystemColor(SWT.COLOR_DARK_GRAY);
fColorInactive= display.getSystemColor(SWT.COLOR_DARK_GRAY);
fContentProvider= cp;
}
public Image getImage(Object element) {
if (element instanceof CHNode) {
CHNode node= (CHNode) element;
ICElement decl= node.getRepresentedDeclaration();
ICElement decl= node.getOneRepresentedDeclaration();
if (decl != null) {
Image image= fCLabelProvider.getImage(decl);
return decorateImage(image, node);
@ -57,8 +59,15 @@ public class CHLabelProvider extends LabelProvider implements IColorProvider {
public String getText(Object element) {
if (element instanceof CHNode) {
CHNode node= (CHNode) element;
ICElement decl= node.getRepresentedDeclaration();
ICElement decl= node.getOneRepresentedDeclaration();
if (decl != null) {
if (node.isMultiDef()) {
int options= fCLabelProvider.getTextFlags();
fCLabelProvider.setTextFlags(LABEL_OPTIONS_SIMPLE);
String result= fCLabelProvider.getText(decl);
fCLabelProvider.setTextFlags(options);
return result;
}
return fCLabelProvider.getText(decl);
}
}
@ -84,10 +93,15 @@ public class CHLabelProvider extends LabelProvider implements IColorProvider {
if (fContentProvider.getComputeReferencedBy()) {
flags |= CElementImageDescriptor.REFERENCED_BY;
}
else {
if (node.isMultiDef()) {
flags |= CElementImageDescriptor.RELATES_TO_MULTIPLE;
}
else {
flags |= CElementImageDescriptor.RELATES_TO;
}
}
}
String key= image.toString()+String.valueOf(flags);
Image result= (Image) fCachedImages.get(key);
@ -105,6 +119,9 @@ public class CHLabelProvider extends LabelProvider implements IColorProvider {
}
public Color getForeground(Object element) {
if (element instanceof CHMultiDefNode) {
return fColorInactive;
}
return null;
}

View file

@ -0,0 +1,53 @@
/*******************************************************************************
* Copyright (c) 2006 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
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Markus Schorn - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.ui.callhierarchy;
import org.eclipse.cdt.core.model.ICElement;
import org.eclipse.cdt.core.model.ITranslationUnit;
public class CHMultiDefNode extends CHNode {
private CHNode[] fChildren;
public CHMultiDefNode(CHNode parent, ITranslationUnit tu, long timestamp, ICElement[] elements) {
super(parent, tu, timestamp, null);
if (elements.length == 0) {
throw new IllegalArgumentException();
}
fChildren= new CHNode[elements.length];
for (int i = 0; i < elements.length; i++) {
ICElement element = elements[i];
fChildren[i]= new CHNode(this, null, 0, element);
}
}
public CHNode[] getChildNodes() {
return fChildren;
}
public boolean isMacro() {
return fChildren[0].isMacro();
}
public boolean isVariable() {
return fChildren[0].isVariable();
}
public ICElement getOneRepresentedDeclaration() {
return fChildren[0].getRepresentedDeclaration();
}
public boolean isMultiDef() {
return true;
}
}

View file

@ -22,6 +22,8 @@ import org.eclipse.cdt.core.model.IMacro;
import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.cdt.core.model.IVariableDeclaration;
import org.eclipse.cdt.internal.ui.util.CoreUtility;
/**
* Represents a node in the include browser
*/
@ -39,7 +41,6 @@ public class CHNode implements IAdaptable {
* Creates a new node for the include browser
*/
public CHNode(CHNode parent, ITranslationUnit fileOfReferences, long timestamp, ICElement decl) {
assert decl != null;
fParent= parent;
fFileOfReferences= fileOfReferences;
fReferences= Collections.EMPTY_LIST;
@ -54,7 +55,9 @@ public class CHNode implements IAdaptable {
if (fParent != null) {
hashCode= fParent.hashCode() * 31;
}
if (fRepresentedDecl != null) {
hashCode+= fRepresentedDecl.hashCode();
}
return hashCode;
}
@ -72,14 +75,14 @@ public class CHNode implements IAdaptable {
return false;
}
return fRepresentedDecl.equals(rhs.fRepresentedDecl);
return CoreUtility.safeEquals(fRepresentedDecl, rhs.fRepresentedDecl);
}
private boolean computeIsRecursive(CHNode parent, ICElement decl) {
if (parent == null || decl == null) {
return false;
}
if (decl.equals(parent.getRepresentedDeclaration())) {
if (decl.equals(parent.fRepresentedDecl)) {
return true;
}
return computeIsRecursive(parent.fParent, decl);
@ -147,4 +150,12 @@ public class CHNode implements IAdaptable {
}
return null;
}
public boolean isMultiDef() {
return false;
}
public ICElement getOneRepresentedDeclaration() {
return getRepresentedDeclaration();
}
}

View file

@ -128,6 +128,7 @@ public class CHViewPart extends ViewPart {
private SelectionSearchGroup fSelectionSearchGroup;
private CRefactoringActionGroup fRefactoringActionGroup;
private Action fOpenElement;
private WorkingSetFilterUI fFilterUI;
public void setFocus() {
@ -203,6 +204,10 @@ public class CHViewPart extends ViewPart {
fRefactoringActionGroup.dispose();
fRefactoringActionGroup= null;
}
if (fFilterUI != null) {
fFilterUI.dispose();
fFilterUI= null;
}
super.dispose();
}
@ -307,7 +312,7 @@ public class CHViewPart extends ViewPart {
fSelectionSearchGroup= new SelectionSearchGroup(getSite());
fRefactoringActionGroup= new CRefactoringActionGroup(this);
WorkingSetFilterUI wsFilterUI= new WorkingSetFilterUI(this, fMemento, KEY_WORKING_SET_FILTER) {
fFilterUI= new WorkingSetFilterUI(this, fMemento, KEY_WORKING_SET_FILTER) {
protected void onWorkingSetChange() {
updateWorkingSetFilter(this);
}
@ -480,7 +485,7 @@ public class CHViewPart extends ViewPart {
// tm.add(fNext);
// tm.add(fPrevious);
// tm.add(new Separator());
wsFilterUI.fillActionBars(actionBars);
fFilterUI.fillActionBars(actionBars);
mm.add(fReferencedByAction);
mm.add(fMakesReferenceToAction);
mm.add(new Separator());
@ -500,7 +505,7 @@ public class CHViewPart extends ViewPart {
if (selectedItem.getData().equals(fNavigationNode)) {
if (forward && fNavigationDetail < fNavigationNode.getReferenceCount()-1) {
if (forward && fNavigationDetail < getReferenceCount(fNavigationNode)-1) {
fNavigationDetail++;
}
else if (!forward && fNavigationDetail > 0) {
@ -509,21 +514,23 @@ public class CHViewPart extends ViewPart {
else {
selectedItem= navigator.getNextSibbling(selectedItem, forward);
fNavigationNode= selectedItem == null ? null : (CHNode) selectedItem.getData();
if (fNavigationNode != null) {
fNavigationDetail= forward ? 0 : fNavigationNode.getReferenceCount()-1;
}
initNavigationDetail(forward);
}
}
else {
fNavigationNode= (CHNode) selectedItem.getData();
initNavigationDetail(forward);
}
}
private void initNavigationDetail(boolean forward) {
if (!forward && fNavigationNode != null) {
fNavigationDetail= Math.max(0, fNavigationNode.getReferenceCount()-1);
fNavigationDetail= Math.max(0, getReferenceCount(fNavigationNode) -1);
}
else {
fNavigationDetail= 0;
}
}
}
protected void onShowSelectedReference(ISelection selection) {
fNavigationDetail= 0;
@ -533,7 +540,11 @@ public class CHViewPart extends ViewPart {
protected void onOpenElement(ISelection selection) {
CHNode node= selectionToNode(selection);
if (node != null) {
openElement(node);
}
private void openElement(CHNode node) {
if (node != null && !node.isMultiDef()) {
ICElement elem= node.getRepresentedDeclaration();
if (elem != null) {
IWorkbenchPage page= getSite().getPage();
@ -622,21 +633,7 @@ public class CHViewPart extends ViewPart {
}
private void updateWorkingSetFilter(WorkingSetFilterUI filterUI) {
if (filterUI.getWorkingSet() == null) {
if (fWorkingSetFilter != null) {
fTreeViewer.removeFilter(fWorkingSetFilter);
fWorkingSetFilter= null;
}
}
else {
if (fWorkingSetFilter != null) {
fTreeViewer.refresh();
}
else {
fWorkingSetFilter= new CHWorkingSetFilter(filterUI);
fTreeViewer.addFilter(fWorkingSetFilter);
}
}
fContentProvider.setWorkingSetFilter(filterUI);
}
protected void onSetShowReferencedBy(boolean showReferencedBy) {
@ -655,11 +652,12 @@ public class CHViewPart extends ViewPart {
CHNode node= selectionToNode(fTreeViewer.getSelection());
if (node != null) {
if (node.getReferenceCount() > 0) {
if (getReferenceCount(node) > 0) {
menu.appendToGroup(IContextMenuConstants.GROUP_OPEN, fShowReference);
}
if (!node.isMultiDef()) {
menu.appendToGroup(IContextMenuConstants.GROUP_OPEN, fOpenElement);
}
if (node.getParent() != null) {
final ICElement element= node.getRepresentedDeclaration();
if (element != null) {
@ -687,26 +685,27 @@ public class CHViewPart extends ViewPart {
}
private void showReference() {
if (fNavigationNode != null) {
ITranslationUnit file= fNavigationNode.getFileOfReferences();
CHNode node= getReferenceNode();
if (node != null) {
ITranslationUnit file= node.getFileOfReferences();
if (file != null) {
IWorkbenchPage page= getSite().getPage();
if (fNavigationNode.getReferenceCount() > 0) {
long timestamp= fNavigationNode.getTimestamp();
if (node.getReferenceCount() > 0) {
long timestamp= node.getTimestamp();
if (fNavigationDetail < 0) {
fNavigationDetail= 0;
}
else if (fNavigationDetail >= fNavigationNode.getReferenceCount()-1) {
fNavigationDetail= fNavigationNode.getReferenceCount()-1;
else if (fNavigationDetail >= node.getReferenceCount()-1) {
fNavigationDetail= node.getReferenceCount()-1;
}
CHReferenceInfo ref= fNavigationNode.getReference(fNavigationDetail);
CHReferenceInfo ref= node.getReference(fNavigationDetail);
Region region= new Region(ref.getOffset(), ref.getLength());
EditorOpener.open(page, file, region, timestamp);
}
else {
try {
EditorOpener.open(page, fNavigationNode.getRepresentedDeclaration());
EditorOpener.open(page, node.getRepresentedDeclaration());
} catch (CModelException e) {
CUIPlugin.getDefault().log(e);
}
@ -715,6 +714,28 @@ public class CHViewPart extends ViewPart {
}
}
private CHNode getReferenceNode() {
if (fNavigationNode != null) {
CHNode parent = fNavigationNode.getParent();
if (parent instanceof CHMultiDefNode) {
return parent;
}
}
return fNavigationNode;
}
private int getReferenceCount(CHNode node) {
if (node != null) {
CHNode parent = node.getParent();
if (parent instanceof CHMultiDefNode) {
return parent.getReferenceCount();
}
return node.getReferenceCount();
}
return 0;
}
private CHNode selectionToNode(ISelection selection) {
if (selection instanceof IStructuredSelection) {
IStructuredSelection ss= (IStructuredSelection) selection;

View file

@ -28,13 +28,24 @@ public class CHWorkingSetFilter extends ViewerFilter {
}
public boolean select(Viewer viewer, Object parentElement, Object element) {
if (parentElement instanceof CHNode && element instanceof CHNode) {
if (parentElement instanceof CHNode) {
if (element instanceof CHMultiDefNode) {
CHNode[] children= ((CHMultiDefNode) element).getChildNodes();
for (int i = 0; i < children.length; i++) {
CHNode node = children[i];
if (fWorkingSetFilter.isPartOfWorkingSet(node.getRepresentedDeclaration())) {
return true;
}
}
return false;
}
else if (element instanceof CHNode) {
CHNode node= (CHNode) element;
ICElement decl= node.getRepresentedDeclaration();
if (decl != null) {
return fWorkingSetFilter.isPartOfWorkingSet(decl);
}
// mstodo in case of an ambigous callees, check the children instead.
}
}
return true;
}

View file

@ -11,6 +11,7 @@
package org.eclipse.cdt.internal.ui.missingapi;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
@ -18,6 +19,8 @@ import java.util.Set;
import org.eclipse.cdt.core.model.ICElement;
import org.eclipse.cdt.internal.ui.viewsupport.WorkingSetFilterUI;
public class CElementSet {
private Set fSet= new HashSet();
private int fHashCode;
@ -70,7 +73,14 @@ public class CElementSet {
return fSet.isEmpty();
}
public ICElement[] getElements() {
return (ICElement[]) fSet.toArray(new ICElement[fSet.size()]);
public ICElement[] getElements(WorkingSetFilterUI filter) {
ArrayList result= new ArrayList(fSet.size());
for (Iterator iter = fSet.iterator(); iter.hasNext(); ) {
ICElement element = (ICElement) iter.next();
if (filter == null || filter.isPartOfWorkingSet(element)) {
result.add(element);
}
}
return (ICElement[]) result.toArray(new ICElement[result.size()]);
}
}

View file

@ -121,6 +121,7 @@ public abstract class AsyncTreeContentProvider implements ITreeContentProvider {
* computations.
*/
public void recompute() {
if (getInput() != null) {
fAutoexpand= new HashSet();
fAutoexpand.addAll(Arrays.asList(fTreeViewer.getVisibleExpandedElements()));
fAutoSelect= null;
@ -128,6 +129,7 @@ public abstract class AsyncTreeContentProvider implements ITreeContentProvider {
clear();
refreshViewer();
}
}
/**
* Refreshes the viewer

View file

@ -67,14 +67,17 @@ public class CElementImageDescriptor extends CompositeImageDescriptor {
/** Flag to render the 'relates to' adornment (for trees, an arrow down) */
public final static int RELATES_TO= 0x200;
/** Flag to render the 'relates to' adornment (for trees, two arrows down) */
public final static int RELATES_TO_MULTIPLE= 0x400;
/** Flag to render the 'referenced by' adornment (for trees, an arrow up) */
public final static int REFERENCED_BY= 0x400;
public final static int REFERENCED_BY= 0x800;
/** Flag to render the 'recursive relation' adornment (for trees, an arrow pointing back) */
public final static int RECURSIVE_RELATION= 0x800;
public final static int RECURSIVE_RELATION= 0x1000;
/** Flag to render the 'system include' adornment */
public final static int SYSTEM_INCLUDE= 0x1000;
public final static int SYSTEM_INCLUDE= 0x2000;
private ImageDescriptor fBaseImage;
private int fFlags;
@ -222,6 +225,11 @@ public class CElementImageDescriptor extends CompositeImageDescriptor {
x-= data.width;
drawImage(data, x, size.y-data.height);
}
else if ((fFlags & RELATES_TO_MULTIPLE) != 0) {
data= CPluginImages.DESC_OVR_RELATESTOMULTIPLE.getImageData();
x-= data.width;
drawImage(data, x, size.y-data.height);
}
else if ((fFlags & REFERENCED_BY) != 0) {
data= CPluginImages.DESC_OVR_REFERENCEDBY.getImageData();
x-= data.width;