diff --git a/python/pluginSrc/META-INF/plugin.xml b/python/pluginSrc/META-INF/plugin.xml index fd52a7b39285..7b161e73b4e9 100644 --- a/python/pluginSrc/META-INF/plugin.xml +++ b/python/pluginSrc/META-INF/plugin.xml @@ -7,5 +7,6 @@ + \ No newline at end of file diff --git a/python/pluginSrc/com/jetbrains/python/psi/impl/PyJavaSuperMethodsSearchExecutor.java b/python/pluginSrc/com/jetbrains/python/psi/impl/PyJavaSuperMethodsSearchExecutor.java new file mode 100644 index 000000000000..5d627b1bfd8a --- /dev/null +++ b/python/pluginSrc/com/jetbrains/python/psi/impl/PyJavaSuperMethodsSearchExecutor.java @@ -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 { + public boolean execute(final PySuperMethodsSearch.SearchParameters queryParameters, final Processor 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; + } +} diff --git a/python/src/com/jetbrains/python/PyLineMarkerNavigator.java b/python/src/com/jetbrains/python/PyLineMarkerNavigator.java index 2cca4b3fe410..e25f31123074 100644 --- a/python/src/com/jetbrains/python/PyLineMarkerNavigator.java +++ b/python/src/com/jetbrains/python/PyLineMarkerNavigator.java @@ -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 navElements = new ArrayList(); + PySuperMethodsSearch.search(function).forEach(new Processor() { + 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()); } diff --git a/python/src/com/jetbrains/python/PyLineMarkerProvider.java b/python/src/com/jetbrains/python/PyLineMarkerProvider.java index e6cbb8cf7a12..e901bfb2297c 100644 --- a/python/src/com/jetbrains/python/PyLineMarkerProvider.java +++ b/python/src/com/jetbrains/python/PyLineMarkerProvider.java @@ -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; diff --git a/python/src/com/jetbrains/python/psi/PyClass.java b/python/src/com/jetbrains/python/psi/PyClass.java index befbfd99b10f..a503b1fa93d0 100644 --- a/python/src/com/jetbrains/python/psi/PyClass.java +++ b/python/src/com/jetbrains/python/psi/PyClass.java @@ -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(); diff --git a/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java b/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java index dd38697269af..a53808478cec 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java @@ -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 implement return null; } - public PyClass[] getSuperClasses() { + public PsiElement[] getSuperClassElements() { final PyExpression[] superExpressions = getSuperClassExpressions(); if (superExpressions != null) { - List superClasses = new ArrayList(); + List superClasses = new ArrayList(); 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 result = new ArrayList(); + for(PsiElement element: superClassElements) { + if (element instanceof PyClass) { + result.add((PyClass) element); + } + } + return result.toArray(new PyClass[result.size()]); } return null; } diff --git a/python/src/com/jetbrains/python/psi/search/PySuperMethodsSearch.java b/python/src/com/jetbrains/python/psi/search/PySuperMethodsSearch.java index 314c33547ffa..a987d6a4af6d 100644 --- a/python/src/com/jetbrains/python/psi/search/PySuperMethodsSearch.java +++ b/python/src/com/jetbrains/python/psi/search/PySuperMethodsSearch.java @@ -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 { +public class PySuperMethodsSearch extends ExtensibleQueryFactory { public static PySuperMethodsSearch INSTANCE = new PySuperMethodsSearch(); public static class SearchParameters { @@ -26,7 +27,7 @@ public class PySuperMethodsSearch extends ExtensibleQueryFactory search(final PyFunction derivedMethod) { + public static Query search(final PyFunction derivedMethod) { final SearchParameters parameters = new SearchParameters(derivedMethod); return INSTANCE.createUniqueResultsQuery(parameters); } diff --git a/python/src/com/jetbrains/python/psi/search/PySuperMethodsSearchExecutor.java b/python/src/com/jetbrains/python/psi/search/PySuperMethodsSearchExecutor.java index af91dc662917..a651ffa31660 100644 --- a/python/src/com/jetbrains/python/psi/search/PySuperMethodsSearchExecutor.java +++ b/python/src/com/jetbrains/python/psi/search/PySuperMethodsSearchExecutor.java @@ -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 { - public boolean execute(final PySuperMethodsSearch.SearchParameters queryParameters, final Processor consumer) { +public class PySuperMethodsSearchExecutor implements QueryExecutor { + public boolean execute(final PySuperMethodsSearch.SearchParameters queryParameters, final Processor consumer) { PyFunction func = queryParameters.getDerivedMethod(); String name = func.getName(); PyClass containingClass = func.getContainingClass();