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:
parent
cefc281f9f
commit
f0d7871fea
5 changed files with 138 additions and 10 deletions
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue