1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-09-08 11:03:28 +02:00

Support for overridden virtual methods in LinkedNamesFinder.

This commit is contained in:
Sergey Prigogin 2010-09-20 03:09:50 +00:00
parent cefc281f9f
commit f0d7871fea
5 changed files with 138 additions and 10 deletions

View file

@ -156,6 +156,7 @@ public class CPPASTTranslationUnit extends ASTTranslationUnit implements ICPPAST
public IScope mapToASTScope(IIndexScope scope) {
return fScopeMapper.mapToASTScope(scope);
}
// bug 262719: class types from the index have to be mapped back to the AST.
public ICPPClassType mapToAST(ICPPClassType binding) {
return fScopeMapper.mapToAST(binding);

View file

@ -234,7 +234,7 @@ public class ClassTypeHelper {
}
/**
* Returns all direct and indirect base classes that have at least a given visibility level.
* Returns all direct and indirect base classes.
* @param classType a class
* @return An array of visible base classes in arbitrary order.
*/
@ -258,7 +258,28 @@ public class ClassTypeHelper {
}
}
}
/**
* Checks inheritance relationship between two classes.
* @return <code>true</code> if {@code subclass} is a subclass of {@code superclass}.
*/
public static boolean isSubclass(ICPPClassType subclass, ICPPClassType superclass) {
ICPPBase[] bases= subclass.getBases();
for (ICPPBase base : bases) {
IBinding b= base.getBaseClass();
if (b instanceof ICPPClassType) {
ICPPClassType baseClass = (ICPPClassType) b;
if (baseClass.isSameType(superclass)) {
return true;
}
if (isSubclass(baseClass, superclass)) {
return true;
}
}
}
return false;
}
public static ICPPMethod[] getAllDeclaredMethods(ICPPClassType ct) {
ICPPMethod[] methods= ct.getDeclaredMethods();
ICPPClassType[] bases= getAllBases(ct);
@ -572,17 +593,26 @@ public class ClassTypeHelper {
* @throws CoreException
*/
public static ICPPMethod[] findOverriders(IIndex index, ICPPMethod method) throws DOMException, CoreException {
if (!isVirtual(method))
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>();
ICPPClassType[] subclasses= getSubClasses(index, mcl);
return findOverriders(subclasses, method);
}
/**
* Returns all methods belonging to the given set of classes that override the given {@code method}.
* @throws DOMException
*/
public static ICPPMethod[] findOverriders(ICPPClassType[] subclasses, ICPPMethod method)
throws DOMException {
final char[] mname= method.getNameCharArray();
final ICPPFunctionType mft= method.getType();
ICPPClassType[] subclasses= getSubClasses(index, mcl);
final ArrayList<ICPPMethod> result= new ArrayList<ICPPMethod>();
for (ICPPClassType subClass : subclasses) {
ICPPMethod[] methods= subClass.getDeclaredMethods();
for (ICPPMethod candidate : methods) {

View file

@ -6,10 +6,11 @@
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM - Initial API and implementation
* Markus Schorn (Wind River Systems)
* Bryan Wilkinson (QNX)
* Andrew Ferguson (Symbian)
* IBM - Initial API and implementation
* Markus Schorn (Wind River Systems)
* Bryan Wilkinson (QNX)
* Andrew Ferguson (Symbian)
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;

View file

@ -124,6 +124,33 @@ public class LinkedNamesFinderTest extends AST2BaseTest {
assertTrue(Arrays.equals(regions3, regions));
}
// class A {
// public:
// virtual void m(int a);
// virtual void m();
// };
//
// class B : public A {
// public:
// void m();
// };
//
// class C : public B {
// public:
// void m(int c);
// };
public void testVirtualMethod() throws Exception {
String code = getAboveComment();
IRegion[] regions = getLinkedRegions(code, "m(int c)", 1, true);
assertEquals(2, regions.length);
assertContents(code, regions[0].getOffset(), "m(int a)");
assertContents(code, regions[1].getOffset(), "m(int c)");
regions = getLinkedRegions(code, "m(int a)", 1, true);
assertEquals(2, regions.length);
assertContents(code, regions[0].getOffset(), "m(int a)");
assertContents(code, regions[1].getOffset(), "m(int c)");
}
// #ifndef GUARD //1
// #define GUARD //2
// // This is a GUARD test

View file

@ -12,11 +12,15 @@ package org.eclipse.cdt.internal.ui.search;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.Region;
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
import org.eclipse.cdt.core.dom.ast.DOMException;
import org.eclipse.cdt.core.dom.ast.IASTComment;
import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
import org.eclipse.cdt.core.dom.ast.IASTName;
@ -37,9 +41,10 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
import org.eclipse.cdt.internal.core.dom.parser.ASTTranslationUnit;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper;
/**
* Finds locations of linked names. Used by Rename in File.
* Finds locations of linked names. Used by Rename in File and Rename in Workspace.
*/
public class LinkedNamesFinder {
private static final IRegion[] EMPTY_LOCATIONS_ARRAY = new IRegion[0];
@ -92,9 +97,38 @@ public class LinkedNamesFinder {
findBinding(method);
}
}
} else if (target instanceof ICPPMethod) {
ICPPMethod method= (ICPPMethod) target;
try {
for (ICPPMethod m : ClassTypeHelper.findOverridden(method)) {
findBinding(m);
}
} catch (DOMException e) {
// Ignore.
}
try {
for (ICPPMethod m : findOverridersInAST(method)) {
findBinding(m);
}
} catch (DOMException e) {
// Ignore.
}
}
}
private ICPPMethod[] findOverridersInAST(ICPPMethod method) throws DOMException {
if (!ClassTypeHelper.isVirtual(method))
return ICPPMethod.EMPTY_CPPMETHOD_ARRAY;
final ICPPClassType ownerClass = method.getClassOwner();
if (ownerClass == null)
return ICPPMethod.EMPTY_CPPMETHOD_ARRAY;
SubclassFinder subclassFinder = new SubclassFinder(ownerClass);
root.accept(subclassFinder);
return ClassTypeHelper.findOverriders(subclassFinder.getSubclasses(), method);
}
public IRegion[] getLocations() {
if (locations.isEmpty()) {
return EMPTY_LOCATIONS_ARRAY;
@ -261,4 +295,39 @@ public class LinkedNamesFinder {
}
}
}
/**
* Finds subclasses of the given class referenced by the AST.
*/
static class SubclassFinder extends ASTVisitor {
{
shouldVisitNames= true;
}
private final ICPPClassType baseClass;
private Set<ICPPClassType> subclasses = new HashSet<ICPPClassType>();
private Set<IBinding> seenClasses = new HashSet<IBinding>();
SubclassFinder(ICPPClassType baseClass) {
this.baseClass = baseClass;
}
@Override
public int visit(IASTName name) {
IBinding binding = name.resolveBinding();
if (binding instanceof ICPPClassType) {
if (seenClasses.add(binding)) {
ICPPClassType candidate = (ICPPClassType) binding;
if (ClassTypeHelper.isSubclass(candidate, baseClass)) {
subclasses.add(candidate);
}
}
}
return PROCESS_CONTINUE;
}
public ICPPClassType[] getSubclasses() {
return subclasses.toArray(new ICPPClassType[subclasses.size()]);
}
}
}