1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-29 19:45:01 +02:00

Utility methods to work with virtual methods, bug 248846.

This commit is contained in:
Markus Schorn 2008-10-09 14:06:00 +00:00
parent 04fa1f9ff5
commit 37c141ceab
3 changed files with 343 additions and 162 deletions

View file

@ -112,6 +112,7 @@ import org.eclipse.cdt.core.dom.ast.gnu.cpp.IGPPPointerType;
import org.eclipse.cdt.core.parser.ParserLanguage;
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTName;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper;
import org.eclipse.cdt.internal.core.dom.parser.cpp.OverloadableOperator;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
@ -6046,4 +6047,77 @@ public class AST2CPPTests extends AST2BaseTest {
ICPPFunction func2= helper.assertNonProblem("func(y[0])", 4, ICPPFunction.class);
assertNotSame(func1, func2);
}
// class NonVirt {
// void m();//0
// };
// class C1 : NonVirt {
// virtual void m();//1
// };
// class C2 : C1 {
// void m();//2
// };
// class C3 : C2 {
// void m(int);
// };
// class C4 : C3 {
// void m();//4
// };
// class C5 : C1 {
// void m();//5
// };
public void testOverridden_248846() throws Exception {
BindingAssertionHelper helper= new BindingAssertionHelper(getAboveComment(), true);
ICPPMethod m0= helper.assertNonProblem("m();//0", 1, ICPPMethod.class);
ICPPMethod m1= helper.assertNonProblem("m();//1", 1, ICPPMethod.class);
ICPPMethod m2= helper.assertNonProblem("m();//2", 1, ICPPMethod.class);
ICPPMethod m3= helper.assertNonProblem("m(int);", 1, ICPPMethod.class);
ICPPMethod m4= helper.assertNonProblem("m();//4", 1, ICPPMethod.class);
ICPPMethod m5= helper.assertNonProblem("m();//5", 1, ICPPMethod.class);
assertFalse(ClassTypeHelper.isVirtual(m0));
assertFalse(ClassTypeHelper.isVirtual(m3));
assertTrue(ClassTypeHelper.isVirtual(m1));
assertTrue(ClassTypeHelper.isVirtual(m2));
assertTrue(ClassTypeHelper.isVirtual(m4));
assertTrue(ClassTypeHelper.isVirtual(m5));
assertFalse(ClassTypeHelper.isOverrider(m0, m0));
assertFalse(ClassTypeHelper.isOverrider(m1, m0));
assertFalse(ClassTypeHelper.isOverrider(m2, m0));
assertFalse(ClassTypeHelper.isOverrider(m3, m0));
assertFalse(ClassTypeHelper.isOverrider(m4, m0));
assertFalse(ClassTypeHelper.isOverrider(m5, m0));
assertFalse(ClassTypeHelper.isOverrider(m0, m1));
assertFalse(ClassTypeHelper.isOverrider(m1, m1));
assertFalse(ClassTypeHelper.isOverrider(m3, m1));
assertTrue(ClassTypeHelper.isOverrider(m2, m1));
assertTrue(ClassTypeHelper.isOverrider(m4, m1));
assertTrue(ClassTypeHelper.isOverrider(m5, m1));
assertFalse(ClassTypeHelper.isOverrider(m0, m2));
assertFalse(ClassTypeHelper.isOverrider(m1, m2));
assertFalse(ClassTypeHelper.isOverrider(m2, m2));
assertFalse(ClassTypeHelper.isOverrider(m3, m2));
assertFalse(ClassTypeHelper.isOverrider(m5, m2));
assertTrue(ClassTypeHelper.isOverrider(m4, m2));
ICPPMethod[] ors= ClassTypeHelper.findOverridden(m0);
assertEquals(0, ors.length);
ors= ClassTypeHelper.findOverridden(m1);
assertEquals(0, ors.length);
ors= ClassTypeHelper.findOverridden(m2);
assertEquals(1, ors.length);
assertSame(ors[0], m1);
ors= ClassTypeHelper.findOverridden(m3);
assertEquals(0, ors.length);
ors= ClassTypeHelper.findOverridden(m4);
assertEquals(2, ors.length);
assertSame(ors[0], m2);
assertSame(ors[1], m1);
ors= ClassTypeHelper.findOverridden(m5);
assertEquals(1, ors.length);
assertSame(ors[0], m1);
}
}

View file

@ -14,6 +14,13 @@
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import org.eclipse.cdt.core.dom.ast.DOMException;
import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
@ -24,6 +31,7 @@ import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IField;
import org.eclipse.cdt.core.dom.ast.IFunctionType;
import org.eclipse.cdt.core.dom.ast.IProblemBinding;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclSpecifier;
@ -31,6 +39,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTElaboratedTypeSpecifier;
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.ICPPBase;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBinding;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor;
@ -38,13 +47,17 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPField;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDeclaration;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier;
import org.eclipse.cdt.core.index.IIndex;
import org.eclipse.cdt.core.index.IIndexName;
import org.eclipse.cdt.core.parser.util.ArrayUtil;
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
import org.eclipse.cdt.core.parser.util.ObjectSet;
import org.eclipse.cdt.internal.core.dom.parser.ASTInternal;
import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClassType.CPPClassTypeProblem;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
import org.eclipse.core.runtime.CoreException;
/**
* Holds common implementation of methods for ICPPClassType implementations that have
@ -155,27 +168,47 @@ public class ClassTypeHelper {
return (ICPPField[]) ArrayUtil.trim( ICPPField.class, result );
}
public static ICPPMethod[] getAllDeclaredMethods(ICPPClassType ct) throws DOMException {
ICPPMethod[] methods = ct.getDeclaredMethods();
ICPPBase [] bases = ct.getBases();
public static ICPPClassType[] getAllBases(ICPPClassType ct) throws DOMException {
HashSet<ICPPClassType> result= new HashSet<ICPPClassType>();
result.add(ct);
getAllBases(ct, result);
result.remove(ct);
return result.toArray(new ICPPClassType[result.size()]);
}
private static void getAllBases(ICPPClassType ct, HashSet<ICPPClassType> result) throws DOMException {
ICPPBase [] bases= ct.getBases();
for (ICPPBase base : bases) {
IBinding b = base.getBaseClass();
if( b instanceof ICPPClassType )
methods = (ICPPMethod[]) ArrayUtil.addAll( ICPPMethod.class, methods, ((ICPPClassType)b).getAllDeclaredMethods() );
IBinding b= base.getBaseClass();
if (b instanceof ICPPClassType) {
final ICPPClassType ctbase = (ICPPClassType) b;
if (result.add(ctbase)) {
getAllBases(ctbase, result);
}
}
}
}
public static ICPPMethod[] getAllDeclaredMethods(ICPPClassType ct) throws DOMException {
ICPPMethod[] methods= ct.getDeclaredMethods();
ICPPClassType[] bases= getAllBases(ct);
for (ICPPClassType base : bases) {
methods = (ICPPMethod[]) ArrayUtil.addAll(ICPPMethod.class, methods, base.getDeclaredMethods());
}
return (ICPPMethod[]) ArrayUtil.trim( ICPPMethod.class, methods );
}
public static ICPPMethod[] getMethods(ICPPClassType ct) throws DOMException {
ObjectSet<ICPPMethod> set = new ObjectSet<ICPPMethod>(4);
ObjectSet<ICPPMethod> set= new ObjectSet<ICPPMethod>(4);
set.addAll(ct.getDeclaredMethods());
ICPPClassScope scope = (ICPPClassScope) ct.getCompositeScope();
ICPPClassScope scope= (ICPPClassScope) ct.getCompositeScope();
set.addAll(scope.getImplicitMethods());
ICPPBase[] bases = ct.getBases();
for (ICPPBase base : bases) {
IBinding b = base.getBaseClass();
if (b instanceof ICPPClassType)
set.addAll(((ICPPClassType) b).getMethods());
ICPPClassType[] bases= getAllBases(ct);
for (ICPPClassType base : bases) {
set.addAll(base.getDeclaredMethods());
scope= (ICPPClassScope) base.getCompositeScope();
set.addAll(scope.getImplicitMethods());
}
return set.keyArray(ICPPMethod.class);
}
@ -300,13 +333,11 @@ public class ClassTypeHelper {
public static IField[] getFields(ICPPClassType ct) throws DOMException {
IField[] fields = ct.getDeclaredFields();
ICPPBase [] bases = ct.getBases();
for (ICPPBase base : bases) {
IBinding b = base.getBaseClass();
if( b instanceof ICPPClassType )
fields = (IField[]) ArrayUtil.addAll( IField.class, fields, ((ICPPClassType)b).getFields() );
ICPPClassType[] bases = getAllBases(ct);
for (ICPPClassType base : bases) {
fields = (IField[]) ArrayUtil.addAll(IField.class, fields, base.getFields());
}
return (IField[]) ArrayUtil.trim( IField.class, fields );
return (IField[]) ArrayUtil.trim(IField.class, fields);
}
public static IField findField(ICPPClassType ct, String name) throws DOMException {
@ -325,4 +356,196 @@ public class ClassTypeHelper {
}
return field;
}
/**
* Returns whether {@code method} is virtual. This is the case if it is declared to be virtual or
* overrides another virtual method.
*/
public static boolean isVirtual(ICPPMethod m) throws DOMException {
if (m instanceof ICPPConstructor)
return false;
if (m.isVirtual())
return true;
final char[] mname= m.getNameCharArray();
final ICPPClassType mcl= m.getClassOwner();
if (mcl != null) {
final IFunctionType mft= m.getType();
ICPPMethod[] allMethods= mcl.getMethods();
for (ICPPMethod method : allMethods) {
if (CharArrayUtils.equals(mname, method.getNameCharArray()) && mft.isSameType(method.getType())) {
if (method.isVirtual()) {
return true;
}
}
}
}
return false;
}
/**
* Returns {@code true} if {@code source} overrides {@code target}.
* @throws DOMException
*/
public static boolean isOverrider(ICPPMethod source, ICPPMethod target) throws DOMException {
if (source instanceof ICPPConstructor || target instanceof ICPPConstructor)
return false;
if (!isVirtual(target))
return false;
if (!source.getType().isSameType(target.getType()))
return false;
final ICPPClassType sourceClass= source.getClassOwner();
final ICPPClassType targetClass= target.getClassOwner();
if (sourceClass == null || targetClass == null)
return false;
ICPPClassType[] bases= getAllBases(sourceClass);
for (ICPPClassType base : bases) {
if (base.isSameType(targetClass))
return true;
}
return false;
}
/**
* Returns all methods that are overridden by the given {@code method}.
* @throws DOMException
*/
public static ICPPMethod[] findOverridden(ICPPMethod method) throws DOMException {
if (method instanceof ICPPConstructor)
return ICPPMethod.EMPTY_CPPMETHOD_ARRAY;
final char[] mname= method.getNameCharArray();
final ICPPClassType mcl= method.getClassOwner();
if (mcl == null)
return ICPPMethod.EMPTY_CPPMETHOD_ARRAY;
final ArrayList<ICPPMethod> result= new ArrayList<ICPPMethod>();
final HashMap<ICPPClassType, Boolean> virtualInClass= new HashMap<ICPPClassType, Boolean>();
final IFunctionType mft= method.getType();
virtualInClass.put(mcl, method.isVirtual());
ICPPBase[] bases= mcl.getBases();
for (ICPPBase base : bases) {
IBinding b= base.getBaseClass();
if (b instanceof ICPPClassType) {
findOverridden((ICPPClassType) b, mname, mft, virtualInClass, result);
}
}
// list is filled from most derived up to here, reverse it
Collections.reverse(result);
return result.toArray(new ICPPMethod[result.size()]);
}
/**
* Searches for overridden methods starting in {@code cl}. The map {@code virtualInClass} contains a mapping
* of classes that have been visited to the information whether they (or a base-class) contain an overridden
* method.
* Returns whether {@code cl} contains an overridden method.
*/
private static boolean findOverridden(ICPPClassType cl, char[] mname, IFunctionType mft,
HashMap<ICPPClassType, Boolean> virtualInClass, ArrayList<ICPPMethod> result) throws DOMException {
Boolean visitedBefore= virtualInClass.get(cl);
if (visitedBefore != null)
return visitedBefore;
ICPPMethod[] methods= cl.getDeclaredMethods();
ICPPMethod candidate= null;
boolean hasOverridden= false;
for (ICPPMethod method : methods) {
if (CharArrayUtils.equals(mname, method.getNameCharArray()) && mft.isSameType(method.getType())) {
candidate= method;
hasOverridden= method.isVirtual();
break;
}
}
// prevent recursion
virtualInClass.put(cl, hasOverridden);
ICPPBase[] bases= cl.getBases();
for (ICPPBase base : bases) {
IBinding b= base.getBaseClass();
if (b instanceof ICPPClassType) {
if (findOverridden((ICPPClassType) b, mname, mft, virtualInClass, result)) {
hasOverridden= true;
}
}
}
if (hasOverridden) {
// the candidate is virtual
if (candidate != null)
result.add(candidate);
virtualInClass.put(cl, hasOverridden);
}
return hasOverridden;
}
/**
* Returns all methods found in the index, that override the given {@code method}.
* @throws DOMException
* @throws CoreException
*/
public static ICPPMethod[] findOverriders(IIndex index, ICPPMethod method) throws DOMException, CoreException {
if (!isVirtual(method))
return ICPPMethod.EMPTY_CPPMETHOD_ARRAY;
final ICPPClassType mcl= method.getClassOwner();
if (mcl == null)
return ICPPMethod.EMPTY_CPPMETHOD_ARRAY;
final ArrayList<ICPPMethod> result= new ArrayList<ICPPMethod>();
final char[] mname= method.getNameCharArray();
final IFunctionType mft= method.getType();
ICPPClassType[] subclasses= getSubClasses(index, mcl);
for (ICPPClassType subClass : subclasses) {
ICPPMethod[] methods= subClass.getDeclaredMethods();
for (ICPPMethod candidate : methods) {
if (CharArrayUtils.equals(mname, candidate.getNameCharArray()) &&
mft.isSameType(candidate.getType())) {
result.add(candidate);
}
}
}
return result.toArray(new ICPPMethod[result.size()]);
}
private static ICPPClassType[] getSubClasses(IIndex index, ICPPClassType mcl) throws CoreException {
List<ICPPBinding> result= new LinkedList<ICPPBinding>();
HashSet<String> handled= new HashSet<String>();
getSubClasses(index, mcl, result, handled);
result.remove(0);
return result.toArray(new ICPPClassType[result.size()]);
}
private static void getSubClasses(IIndex index, ICPPBinding classOrTypedef, List<ICPPBinding> result, HashSet<String> handled) throws CoreException {
try {
final String key = CPPVisitor.renderQualifiedName(classOrTypedef.getQualifiedName());
if (!handled.add(key)) {
return;
}
} catch (DOMException e) {
return;
}
if (classOrTypedef instanceof ICPPClassType) {
result.add(classOrTypedef);
}
IIndexName[] names= index.findNames(classOrTypedef, IIndex.FIND_REFERENCES | IIndex.FIND_DEFINITIONS);
for (IIndexName indexName : names) {
if (indexName.isBaseSpecifier()) {
IIndexName subClassDef= indexName.getEnclosingDefinition();
if (subClassDef != null) {
IBinding subClass= index.findBinding(subClassDef);
if (subClass instanceof ICPPBinding) {
getSubClasses(index, (ICPPBinding) subClass, result, handled);
}
}
}
}
}
}

View file

@ -12,19 +12,12 @@ package org.eclipse.cdt.internal.ui.callhierarchy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.cdt.core.dom.ast.DOMException;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IFunctionType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBinding;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
import org.eclipse.cdt.core.index.IIndex;
import org.eclipse.cdt.core.index.IIndexBinding;
@ -32,9 +25,8 @@ 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.ISourceReference;
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper;
import org.eclipse.cdt.internal.core.model.ext.ICElementHandle;
import org.eclipse.cdt.internal.ui.viewsupport.IndexUI;
@ -63,134 +55,20 @@ public class CHQueries {
IIndexBinding calleeBinding= IndexUI.elementToBinding(index, callee);
if (calleeBinding != null) {
findCalledBy(index, calleeBinding, true, project, result);
IBinding[] overriddenBindings= getOverriddenBindings(index, calleeBinding);
for (IBinding overriddenBinding : overriddenBindings) {
findCalledBy(index, overriddenBinding, false, project, result);
if (calleeBinding instanceof ICPPMethod) {
try {
IBinding[] overriddenBindings= ClassTypeHelper.findOverridden((ICPPMethod) calleeBinding);
for (IBinding overriddenBinding : overriddenBindings) {
findCalledBy(index, overriddenBinding, false, project, result);
}
} catch (DOMException e) {
// index bindings don't throw DOMExceptions
}
}
}
return cp.createNodes(node, result);
}
private static IBinding[] getOverriddenBindings(IIndex index, IIndexBinding binding) {
if (binding instanceof ICPPMethod && !(binding instanceof ICPPConstructor)) {
try {
final ArrayList<ICPPMethod> result= new ArrayList<ICPPMethod>();
final ICPPMethod m= (ICPPMethod) binding;
final char[] mname= m.getNameCharArray();
final ICPPClassType mcl= m.getClassOwner();
if (mcl != null) {
final IFunctionType mft= m.getType();
boolean isVirtual= m.isVirtual();
ICPPMethod[] allMethods= mcl.getMethods();
for (ICPPMethod method : allMethods) {
if (CharArrayUtils.equals(mname, method.getNameCharArray()) && !mcl.isSameType(method.getClassOwner())) {
if (mft.isSameType(method.getType())) {
isVirtual= isVirtual || method.isVirtual();
result.add(method);
}
}
}
if (isVirtual) {
return result.toArray(new IBinding[result.size()]);
}
}
} catch (DOMException e) {
// index bindings don't throw DOMExceptions
}
}
return IBinding.EMPTY_BINDING_ARRAY;
}
private static IBinding[] getOverridingBindings(IIndex index, IBinding binding) throws CoreException {
if (binding instanceof ICPPMethod && !(binding instanceof ICPPConstructor)) {
try {
final ICPPMethod m= (ICPPMethod) binding;
if (isVirtual(m)) {
final ArrayList<ICPPMethod> result= new ArrayList<ICPPMethod>();
final char[] mname= m.getNameCharArray();
final ICPPClassType mcl= m.getClassOwner();
if (mcl != null) {
final IFunctionType mft= m.getType();
ICPPClassType[] subclasses= getSubClasses(index, mcl);
for (ICPPClassType subClass : subclasses) {
ICPPMethod[] methods= subClass.getDeclaredMethods();
for (ICPPMethod method : methods) {
if (CharArrayUtils.equals(mname, method.getNameCharArray()) &&
mft.isSameType(method.getType())) {
result.add(method);
}
}
}
return result.toArray(new IBinding[result.size()]);
}
}
} catch (DOMException e) {
// index bindings don't throw DOMExceptions
}
}
return IBinding.EMPTY_BINDING_ARRAY;
}
private static ICPPClassType[] getSubClasses(IIndex index, ICPPClassType mcl) throws CoreException {
List<ICPPBinding> result= new LinkedList<ICPPBinding>();
HashSet<String> handled= new HashSet<String>();
getSubClasses(index, mcl, result, handled);
result.remove(0);
return result.toArray(new ICPPClassType[result.size()]);
}
private static void getSubClasses(IIndex index, ICPPBinding classOrTypedef, List<ICPPBinding> result, HashSet<String> handled) throws CoreException {
try {
final String key = CPPVisitor.renderQualifiedName(classOrTypedef.getQualifiedName());
if (!handled.add(key)) {
return;
}
} catch (DOMException e) {
return;
}
if (classOrTypedef instanceof ICPPClassType) {
result.add(classOrTypedef);
}
IIndexName[] names= index.findNames(classOrTypedef, IIndex.FIND_REFERENCES | IIndex.FIND_DEFINITIONS);
for (IIndexName indexName : names) {
if (indexName.isBaseSpecifier()) {
IIndexName subClassDef= indexName.getEnclosingDefinition();
if (subClassDef != null) {
IBinding subClass= index.findBinding(subClassDef);
if (subClass instanceof ICPPBinding) {
getSubClasses(index, (ICPPBinding) subClass, result, handled);
}
}
}
}
}
private static boolean isVirtual(ICPPMethod m) {
try {
if (m.isVirtual()) {
return true;
}
final char[] mname= m.getNameCharArray();
final ICPPClassType mcl= m.getClassOwner();
if (mcl != null) {
final IFunctionType mft= m.getType();
ICPPMethod[] allMethods= mcl.getMethods();
for (ICPPMethod method : allMethods) {
if (CharArrayUtils.equals(mname, method.getNameCharArray()) && mft.isSameType(method.getType())) {
if (method.isVirtual()) {
return true;
}
}
}
}
} catch (DOMException e) {
// index bindings don't throw DOMExceptions
}
return false;
}
private static void findCalledBy(IIndex index, IBinding callee, boolean includeOrdinaryCalls, ICProject project, CalledByResult result)
throws CoreException {
IIndexName[] names= index.findNames(callee, IIndex.FIND_REFERENCES | IIndex.SEARCH_ACROSS_LANGUAGE_BOUNDARIES);
@ -220,18 +98,24 @@ public class CHQueries {
for (IIndexName name : refs) {
IBinding binding= index.findBinding(name);
if (CallHierarchyUI.isRelevantForCallHierarchy(binding)) {
IBinding[] virtualOverriders= getOverridingBindings(index, binding);
ICElement[] defs;
if (virtualOverriders.length == 0) {
defs = IndexUI.findRepresentative(index, binding);
}
else {
ArrayList<ICElementHandle> list= new ArrayList<ICElementHandle>();
list.addAll(Arrays.asList(IndexUI.findRepresentative(index, binding)));
for (IBinding overrider : virtualOverriders) {
list.addAll(Arrays.asList(IndexUI.findRepresentative(index, overrider)));
ICElement[] defs= null;
if (binding instanceof ICPPMethod) {
try {
IBinding[] virtualOverriders= ClassTypeHelper.findOverriders(index, (ICPPMethod) binding);
if (virtualOverriders.length > 0) {
ArrayList<ICElementHandle> list= new ArrayList<ICElementHandle>();
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= list.toArray(new ICElement[list.size()]);
}
if (defs == null) {
defs= IndexUI.findRepresentative(index, binding);
}
if (defs != null && defs.length > 0) {
result.add(defs, name);