find Java super methods for Python methods

This commit is contained in:
Dmitry Jemerov
2008-03-19 17:16:09 +03:00
parent be773340d5
commit 7d8c03e24b
8 changed files with 83 additions and 12 deletions

View File

@@ -7,5 +7,6 @@
<importResolver implementation="com.jetbrains.python.psi.impl.PyJavaImportResolver"/>
<typeProvider implementation="com.jetbrains.python.psi.impl.PyJavaTypeProvider"/>
<pySuperMethodsSearch implementation="com.jetbrains.python.psi.search.PySuperMethodsSearchExecutor"/>
<pySuperMethodsSearch implementation="com.jetbrains.python.psi.impl.PyJavaSuperMethodsSearchExecutor"/>
</extensions>
</idea-plugin>

View File

@@ -0,0 +1,36 @@
package com.jetbrains.python.psi.impl;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiMethod;
import com.intellij.util.Processor;
import com.intellij.util.QueryExecutor;
import com.jetbrains.python.psi.PyClass;
import com.jetbrains.python.psi.PyFunction;
import com.jetbrains.python.psi.search.PySuperMethodsSearch;
/**
* @author yole
*/
public class PyJavaSuperMethodsSearchExecutor implements QueryExecutor<PsiElement, PySuperMethodsSearch.SearchParameters> {
public boolean execute(final PySuperMethodsSearch.SearchParameters queryParameters, final Processor<PsiElement> consumer) {
PyFunction func = queryParameters.getDerivedMethod();
PyClass containingClass = func.getContainingClass();
if (containingClass != null) {
PsiElement[] superClassElements = containingClass.getSuperClassElements();
if (superClassElements != null) {
for(PsiElement element: superClassElements) {
if (element instanceof PsiClass) {
PsiClass psiClass = (PsiClass) element;
PsiMethod[] methods = psiClass.findMethodsByName(func.getName(), true);
// the Python method actually does override/implement all of Java super methods with the same name
for(PsiMethod method: methods) {
if (!consumer.process(method)) return false;
}
}
}
}
}
return true;
}
}

View File

@@ -2,12 +2,16 @@ package com.jetbrains.python;
import com.intellij.codeInsight.daemon.impl.GutterIconNavigationHandler;
import com.intellij.codeInsight.daemon.impl.PsiElementListNavigator;
import com.intellij.psi.PsiElement;
import com.intellij.ide.util.DefaultPsiElementCellRenderer;
import com.intellij.psi.NavigatablePsiElement;
import com.intellij.psi.PsiElement;
import com.intellij.util.Processor;
import com.jetbrains.python.psi.PyFunction;
import com.jetbrains.python.psi.search.PySuperMethodsSearch;
import java.awt.event.MouseEvent;
import java.util.List;
import java.util.ArrayList;
/**
* @author yole
@@ -16,7 +20,16 @@ public class PyLineMarkerNavigator implements GutterIconNavigationHandler {
public void navigate(final MouseEvent e, final PsiElement elt) {
if (elt.getParent() instanceof PyFunction) {
final PyFunction function = (PyFunction)elt.getParent();
final PyFunction[] methods = PySuperMethodsSearch.search(function).toArray(new PyFunction[0]);
final List<NavigatablePsiElement> navElements = new ArrayList<NavigatablePsiElement>();
PySuperMethodsSearch.search(function).forEach(new Processor<PsiElement>() {
public boolean process(final PsiElement psiElement) {
if (psiElement instanceof NavigatablePsiElement) {
navElements.add((NavigatablePsiElement) psiElement);
}
return true;
}
});
final NavigatablePsiElement[] methods = navElements.toArray(new NavigatablePsiElement[navElements.size()]);
PsiElementListNavigator.openTargets(e, methods, "Choose Super Method of " + function.getName(),
new DefaultPsiElementCellRenderer());
}

View File

@@ -30,6 +30,7 @@ public class PyLineMarkerProvider implements LineMarkerProvider {
@Nullable
private static LineMarkerInfo getMethodMarker(final PsiElement element, final PyFunction function) {
if (PySuperMethodsSearch.search(function).findFirst() != null) {
// TODO: show "implementing" instead of "overriding" icon for Python implementations of Java interface methods
LineMarkerInfo info = new LineMarkerInfo(element, element.getTextRange().getStartOffset(),
OVERRIDING_METHOD_ICON, Pass.UPDATE_ALL, null, new PyLineMarkerNavigator());
return info;

View File

@@ -16,6 +16,7 @@
package com.jetbrains.python.psi;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiNamedElement;
import com.intellij.psi.StubBasedPsiElement;
import com.intellij.psi.stubs.MayHaveStubsInside;
@@ -38,6 +39,9 @@ public interface PyClass extends PsiNamedElement, PyElement, PyDocStringOwner, S
@Nullable
PyExpression[] getSuperClassExpressions();
@Nullable
PsiElement[] getSuperClassElements();
@Nullable
PyClass[] getSuperClasses();

View File

@@ -32,8 +32,8 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.util.List;
import java.util.ArrayList;
import java.util.List;
/**
* Created by IntelliJ IDEA.
@@ -104,20 +104,34 @@ public class PyClassImpl extends PyPresentableElementImpl<PyClassStub> implement
return null;
}
public PyClass[] getSuperClasses() {
public PsiElement[] getSuperClassElements() {
final PyExpression[] superExpressions = getSuperClassExpressions();
if (superExpressions != null) {
List<PyClass> superClasses = new ArrayList<PyClass>();
List<PsiElement> superClasses = new ArrayList<PsiElement>();
for(PyExpression expr: superExpressions) {
if (expr instanceof PyReferenceExpression && !"object".equals(expr.getText())) {
PyReferenceExpression ref = (PyReferenceExpression) expr;
final PsiElement result = ref.resolve();
if (result instanceof PyClass) {
superClasses.add((PyClass) result);
if (result != null) {
superClasses.add(result);
}
}
}
return superClasses.toArray(new PyClass[superClasses.size()]);
return superClasses.toArray(new PsiElement[superClasses.size()]);
}
return null;
}
public PyClass[] getSuperClasses() {
PsiElement[] superClassElements = getSuperClassElements();
if (superClassElements != null) {
List<PyClass> result = new ArrayList<PyClass>();
for(PsiElement element: superClassElements) {
if (element instanceof PyClass) {
result.add((PyClass) element);
}
}
return result.toArray(new PyClass[result.size()]);
}
return null;
}

View File

@@ -1,5 +1,6 @@
package com.jetbrains.python.psi.search;
import com.intellij.psi.PsiElement;
import com.intellij.psi.search.searches.ExtensibleQueryFactory;
import com.intellij.util.Query;
import com.jetbrains.python.psi.PyFunction;
@@ -7,7 +8,7 @@ import com.jetbrains.python.psi.PyFunction;
/**
* @author yole
*/
public class PySuperMethodsSearch extends ExtensibleQueryFactory<PyFunction, PySuperMethodsSearch.SearchParameters> {
public class PySuperMethodsSearch extends ExtensibleQueryFactory<PsiElement, PySuperMethodsSearch.SearchParameters> {
public static PySuperMethodsSearch INSTANCE = new PySuperMethodsSearch();
public static class SearchParameters {
@@ -26,7 +27,7 @@ public class PySuperMethodsSearch extends ExtensibleQueryFactory<PyFunction, PyS
super("Pythonid");
}
public static Query<PyFunction> search(final PyFunction derivedMethod) {
public static Query<PsiElement> search(final PyFunction derivedMethod) {
final SearchParameters parameters = new SearchParameters(derivedMethod);
return INSTANCE.createUniqueResultsQuery(parameters);
}

View File

@@ -1,5 +1,6 @@
package com.jetbrains.python.psi.search;
import com.intellij.psi.PsiElement;
import com.intellij.util.Processor;
import com.intellij.util.QueryExecutor;
import com.jetbrains.python.psi.PyClass;
@@ -8,8 +9,8 @@ import com.jetbrains.python.psi.PyFunction;
/**
* @author yole
*/
public class PySuperMethodsSearchExecutor implements QueryExecutor<PyFunction, PySuperMethodsSearch.SearchParameters> {
public boolean execute(final PySuperMethodsSearch.SearchParameters queryParameters, final Processor<PyFunction> consumer) {
public class PySuperMethodsSearchExecutor implements QueryExecutor<PsiElement, PySuperMethodsSearch.SearchParameters> {
public boolean execute(final PySuperMethodsSearch.SearchParameters queryParameters, final Processor<PsiElement> consumer) {
PyFunction func = queryParameters.getDerivedMethod();
String name = func.getName();
PyClass containingClass = func.getContainingClass();