diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/callhierarchy/CallHierarchyBugs.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/callhierarchy/CallHierarchyBugs.java index 1d2923c900e..4b58c04e568 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/callhierarchy/CallHierarchyBugs.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/callhierarchy/CallHierarchyBugs.java @@ -443,4 +443,39 @@ public class CallHierarchyBugs extends CallHierarchyBaseTest { checkTreeNode(chTree, 0, 1, null); } + + // class Base { + // public: + // virtual void dosomething() {} + // }; + // + // class Derived : public Base { + // public: + // void dosomething() { } + // }; + // + // void test() { + // Base *dbPtr = new Derived(); + // dbPtr->dosomething(); + // delete dbPtr; + // } + public void testCallsToFromVirtualMethod_246064() throws Exception { + final StringBuffer[] contents = getContentsForTest(1); + final String content = contents[0].toString(); + IFile f2= createFile(getProject(), "testCallsToFromVirtualMethod_246064.cpp", content); + waitForIndexer(fIndex, f2, CallHierarchyBaseTest.INDEXER_WAIT_TIME); + + final CHViewPart ch= (CHViewPart) activateView(CUIPlugin.ID_CALL_HIERARCHY); + + // open editor, check outline + CEditor editor= openEditor(f2); + int idx = content.indexOf("dosomething();"); + editor.selectAndReveal(idx, 0); + openCallHierarchy(editor, false); + + Tree chTree= checkTreeNode(ch, 0, "Base::dosomething()").getParent(); + checkTreeNode(chTree, 0, 0, "Base::dosomething()"); + checkTreeNode(chTree, 0, 1, "Derived::dosomething()"); + checkTreeNode(chTree, 0, 2, null); + } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/callhierarchy/CHContentProvider.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/callhierarchy/CHContentProvider.java index d9e8f257e93..2a0e302512e 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/callhierarchy/CHContentProvider.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/callhierarchy/CHContentProvider.java @@ -18,13 +18,16 @@ import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.swt.widgets.Display; import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IEnumerator; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod; import org.eclipse.cdt.core.index.IIndex; import org.eclipse.cdt.core.index.IIndexFile; import org.eclipse.cdt.core.index.IIndexName; import org.eclipse.cdt.core.model.CoreModel; import org.eclipse.cdt.core.model.ICElement; import org.eclipse.cdt.core.model.ICProject; +import org.eclipse.cdt.core.model.IMethod; import org.eclipse.cdt.core.model.ITranslationUnit; import org.eclipse.cdt.core.model.IVariable; import org.eclipse.cdt.ui.CUIPlugin; @@ -130,6 +133,18 @@ public class CHContentProvider extends AsyncTreeContentProvider { }); } ITranslationUnit tu= CModelUtil.getTranslationUnit(element); + if (!fComputeReferencedBy && element instanceof IMethod) { + IIndexName methodName= IndexUI.elementToName(index, element); + if (methodName != null) { + IBinding methodBinding= index.findBinding(methodName); + if (methodBinding instanceof ICPPMethod) { + ICElement[] defs= CHQueries.findOverriders(index, (ICPPMethod) methodBinding); + if (defs != null && defs.length > 0) { + return new Object[] { new CHMultiDefNode(null, tu, 0, defs, methodBinding.getLinkage().getLinkageID()) }; + } + } + } + } return new Object[] { new CHNode(null, tu, 0, element, -1) }; } finally { @@ -177,8 +192,7 @@ public class CHContentProvider extends AsyncTreeContentProvider { CHNode[] createNodes(CHNode node, CalledByResult result) throws CoreException { ArrayList nodes= new ArrayList(); ICElement[] elements= result.getElements(); - for (int i = 0; i < elements.length; i++) { - ICElement element = elements[i]; + for (ICElement element : elements) { if (element != null) { if (fFilter == null || fFilter.isPartOfWorkingSet(element)) { IIndexName[] refs= result.getReferences(element); @@ -201,8 +215,7 @@ public class CHContentProvider extends AsyncTreeContentProvider { } boolean readAccess= false; boolean writeAccess= false; - for (int i = 0; i < refs.length; i++) { - IIndexName reference = refs[i]; + for (IIndexName reference : refs) { node.addReference(new CHReferenceInfo(reference.getNodeOffset(), reference.getNodeLength())); readAccess= (readAccess || reference.isReadAccess()); writeAccess= (writeAccess || reference.isWriteAccess()); @@ -216,8 +229,8 @@ public class CHContentProvider extends AsyncTreeContentProvider { ITranslationUnit tu= CModelUtil.getTranslationUnit(node.getRepresentedDeclaration()); ArrayList result= new ArrayList(); CElementSet[] elementSets= callsTo.getElementSets(); - for (int i = 0; i < elementSets.length; i++) { - CElementSet set = elementSets[i]; + for (CElementSet elementSet : elementSets) { + CElementSet set = elementSet; if (!set.isEmpty()) { IIndexName[] refs= callsTo.getReferences(set); ICElement[] elements= set.getElements(fFilter); @@ -246,8 +259,7 @@ public class CHContentProvider extends AsyncTreeContentProvider { boolean readAccess= false; boolean writeAccess= false; - for (int i = 0; i < references.length; i++) { - IIndexName reference = references[i]; + for (IIndexName reference : references) { node.addReference(new CHReferenceInfo(reference.getNodeOffset(), reference.getNodeLength())); readAccess= (readAccess || reference.isReadAccess()); writeAccess= (writeAccess || reference.isWriteAccess()); diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/callhierarchy/CHQueries.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/callhierarchy/CHQueries.java index deb3e155ffe..3c4850b0d3e 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/callhierarchy/CHQueries.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/callhierarchy/CHQueries.java @@ -120,19 +120,7 @@ public class CHQueries { if (CallHierarchyUI.isRelevantForCallHierarchy(binding)) { ICElement[] defs= null; if (binding instanceof ICPPMethod) { - try { - IBinding[] virtualOverriders= ClassTypeHelper.findOverriders(index, (ICPPMethod) binding); - if (virtualOverriders.length > 0) { - ArrayList list= new ArrayList(); - list.addAll(Arrays.asList(IndexUI.findRepresentative(index, binding))); - for (IBinding overrider : virtualOverriders) { - list.addAll(Arrays.asList(IndexUI.findRepresentative(index, overrider))); - } - defs= list.toArray(new ICElement[list.size()]); - } - } catch (DOMException e) { - // index bindings don't throw DOMExceptions - } + defs = findOverriders(index, (ICPPMethod) binding); } if (defs == null) { defs= IndexUI.findRepresentative(index, binding); @@ -145,4 +133,24 @@ public class CHQueries { } return cp.createNodes(node, result); } + + /** + * Searches for overriders of method and converts them to ICElement, returns null, if there are none. + */ + static ICElement[] findOverriders(IIndex index, ICPPMethod binding) throws CoreException { + try { + IBinding[] virtualOverriders= ClassTypeHelper.findOverriders(index, binding); + if (virtualOverriders.length > 0) { + ArrayList list= new ArrayList(); + list.addAll(Arrays.asList(IndexUI.findRepresentative(index, binding))); + for (IBinding overrider : virtualOverriders) { + list.addAll(Arrays.asList(IndexUI.findRepresentative(index, overrider))); + } + return list.toArray(new ICElement[list.size()]); + } + } catch (DOMException e) { + // index bindings don't throw DOMExceptions + } + return null; + } }