mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-09-10 12:03:16 +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) {
|
public IScope mapToASTScope(IIndexScope scope) {
|
||||||
return fScopeMapper.mapToASTScope(scope);
|
return fScopeMapper.mapToASTScope(scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
// bug 262719: class types from the index have to be mapped back to the AST.
|
// bug 262719: class types from the index have to be mapped back to the AST.
|
||||||
public ICPPClassType mapToAST(ICPPClassType binding) {
|
public ICPPClassType mapToAST(ICPPClassType binding) {
|
||||||
return fScopeMapper.mapToAST(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
|
* @param classType a class
|
||||||
* @return An array of visible base classes in arbitrary order.
|
* @return An array of visible base classes in arbitrary order.
|
||||||
*/
|
*/
|
||||||
|
@ -259,6 +259,27 @@ 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) {
|
public static ICPPMethod[] getAllDeclaredMethods(ICPPClassType ct) {
|
||||||
ICPPMethod[] methods= ct.getDeclaredMethods();
|
ICPPMethod[] methods= ct.getDeclaredMethods();
|
||||||
ICPPClassType[] bases= getAllBases(ct);
|
ICPPClassType[] bases= getAllBases(ct);
|
||||||
|
@ -579,10 +600,19 @@ public class ClassTypeHelper {
|
||||||
if (mcl == null)
|
if (mcl == null)
|
||||||
return ICPPMethod.EMPTY_CPPMETHOD_ARRAY;
|
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 char[] mname= method.getNameCharArray();
|
||||||
final ICPPFunctionType mft= method.getType();
|
final ICPPFunctionType mft= method.getType();
|
||||||
ICPPClassType[] subclasses= getSubClasses(index, mcl);
|
final ArrayList<ICPPMethod> result= new ArrayList<ICPPMethod>();
|
||||||
for (ICPPClassType subClass : subclasses) {
|
for (ICPPClassType subClass : subclasses) {
|
||||||
ICPPMethod[] methods= subClass.getDeclaredMethods();
|
ICPPMethod[] methods= subClass.getDeclaredMethods();
|
||||||
for (ICPPMethod candidate : methods) {
|
for (ICPPMethod candidate : methods) {
|
||||||
|
|
|
@ -6,10 +6,11 @@
|
||||||
* http://www.eclipse.org/legal/epl-v10.html
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
*
|
*
|
||||||
* Contributors:
|
* Contributors:
|
||||||
* IBM - Initial API and implementation
|
* IBM - Initial API and implementation
|
||||||
* Markus Schorn (Wind River Systems)
|
* Markus Schorn (Wind River Systems)
|
||||||
* Bryan Wilkinson (QNX)
|
* Bryan Wilkinson (QNX)
|
||||||
* Andrew Ferguson (Symbian)
|
* Andrew Ferguson (Symbian)
|
||||||
|
* Sergey Prigogin (Google)
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
|
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
|
||||||
|
|
||||||
|
|
|
@ -124,6 +124,33 @@ public class LinkedNamesFinderTest extends AST2BaseTest {
|
||||||
assertTrue(Arrays.equals(regions3, regions));
|
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
|
// #ifndef GUARD //1
|
||||||
// #define GUARD //2
|
// #define GUARD //2
|
||||||
// // This is a GUARD test
|
// // This is a GUARD test
|
||||||
|
|
|
@ -12,11 +12,15 @@ package org.eclipse.cdt.internal.ui.search;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import org.eclipse.jface.text.IRegion;
|
import org.eclipse.jface.text.IRegion;
|
||||||
import org.eclipse.jface.text.Region;
|
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.IASTComment;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
|
import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTName;
|
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.core.dom.ast.cpp.ICPPMethod;
|
||||||
|
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.ASTTranslationUnit;
|
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 {
|
public class LinkedNamesFinder {
|
||||||
private static final IRegion[] EMPTY_LOCATIONS_ARRAY = new IRegion[0];
|
private static final IRegion[] EMPTY_LOCATIONS_ARRAY = new IRegion[0];
|
||||||
|
@ -92,9 +97,38 @@ public class LinkedNamesFinder {
|
||||||
findBinding(method);
|
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() {
|
public IRegion[] getLocations() {
|
||||||
if (locations.isEmpty()) {
|
if (locations.isEmpty()) {
|
||||||
return EMPTY_LOCATIONS_ARRAY;
|
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