Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSergey Prigogin2010-09-19 23:09:50 -0400
committerSergey Prigogin2010-09-19 23:09:50 -0400
commitf0d7871fea71199c318bf85e505a5bfdc7b93140 (patch)
tree23d25713339f98c9bf7960c6093325aa6403b83c
parentcefc281f9f3bada13c754be45dffaa27342aaf77 (diff)
downloadorg.eclipse.cdt-f0d7871fea71199c318bf85e505a5bfdc7b93140.tar.gz
org.eclipse.cdt-f0d7871fea71199c318bf85e505a5bfdc7b93140.tar.xz
org.eclipse.cdt-f0d7871fea71199c318bf85e505a5bfdc7b93140.zip
Support for overridden virtual methods in LinkedNamesFinder.
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTranslationUnit.java1
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ClassTypeHelper.java40
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/SemanticUtil.java9
-rw-r--r--core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/search/LinkedNamesFinderTest.java27
-rw-r--r--core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/LinkedNamesFinder.java71
5 files changed, 138 insertions, 10 deletions
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTranslationUnit.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTranslationUnit.java
index 94ee1d1f2b..57dd28b901 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTranslationUnit.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTranslationUnit.java
@@ -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);
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ClassTypeHelper.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ClassTypeHelper.java
index 7e91d3e025..2333153491 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ClassTypeHelper.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ClassTypeHelper.java
@@ -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) {
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/SemanticUtil.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/SemanticUtil.java
index ccb899a822..ec49fbce93 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/SemanticUtil.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/SemanticUtil.java
@@ -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;
diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/search/LinkedNamesFinderTest.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/search/LinkedNamesFinderTest.java
index 2970cd2a84..68e20027ad 100644
--- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/search/LinkedNamesFinderTest.java
+++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/search/LinkedNamesFinderTest.java
@@ -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
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/LinkedNamesFinder.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/LinkedNamesFinder.java
index 70a7e9248a..cd4ddfcf4f 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/LinkedNamesFinder.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/LinkedNamesFinder.java
@@ -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()]);
+ }
+ }
}

Back to the top