mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
python subclass navigation
This commit is contained in:
@@ -55,7 +55,7 @@
|
||||
serviceImplementation="com.jetbrains.python.psi.impl.PyBuiltinCache"/>
|
||||
|
||||
<referenceImporter implementation="com.jetbrains.python.validation.PythonReferenceImporter"/>
|
||||
<codeInsight.lineMarkerProvider language="Python" implementationClass="com.jetbrains.python.PyLineMarkerProvider"/>
|
||||
<codeInsight.lineMarkerProvider language="Python" implementationClass="com.jetbrains.python.codeInsight.PyLineMarkerProvider"/>
|
||||
<definitionsSearch implementation="com.jetbrains.python.psi.search.PyDefinitionsSearch"/>
|
||||
<gotoImplementationRendererProvider implementation="com.jetbrains.python.codeInsight.PyGotoImplementationRendererProvider"/>
|
||||
</extensions>
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
package com.jetbrains.python;
|
||||
|
||||
import com.intellij.codeInsight.daemon.impl.GutterIconNavigationHandler;
|
||||
import com.intellij.codeInsight.daemon.impl.PsiElementListNavigator;
|
||||
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
|
||||
*/
|
||||
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 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());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
package com.jetbrains.python;
|
||||
|
||||
import com.intellij.codeHighlighting.Pass;
|
||||
import com.intellij.codeInsight.daemon.impl.LineMarkerInfo;
|
||||
import com.intellij.codeInsight.daemon.impl.LineMarkerProvider;
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.openapi.util.IconLoader;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.jetbrains.python.psi.PyFunction;
|
||||
import com.jetbrains.python.psi.search.PySuperMethodsSearch;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.List;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
*/
|
||||
public class PyLineMarkerProvider implements LineMarkerProvider {
|
||||
private static final Icon OVERRIDING_METHOD_ICON = IconLoader.getIcon("/gutter/overridingMethod.png");
|
||||
|
||||
public LineMarkerInfo getLineMarkerInfo(final PsiElement element) {
|
||||
final ASTNode node = element.getNode();
|
||||
if (node != null && node.getElementType() == PyTokenTypes.IDENTIFIER && element.getParent() instanceof PyFunction) {
|
||||
final PyFunction function = (PyFunction)element.getParent();
|
||||
return getMethodMarker(element, function);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@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;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void collectSlowLineMarkers(final List<PsiElement> elements, final Collection<LineMarkerInfo> result) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.jetbrains.python.codeInsight;
|
||||
|
||||
import com.intellij.codeInsight.daemon.impl.GutterIconNavigationHandler;
|
||||
import com.intellij.codeInsight.daemon.impl.PsiElementListNavigator;
|
||||
import com.intellij.ide.util.DefaultPsiElementCellRenderer;
|
||||
import com.intellij.psi.NavigatablePsiElement;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.Query;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
*/
|
||||
public abstract class PyLineMarkerNavigator<T extends PsiElement> implements GutterIconNavigationHandler {
|
||||
public void navigate(final MouseEvent e, final PsiElement elt) {
|
||||
final List<NavigatablePsiElement> navElements = new ArrayList<NavigatablePsiElement>();
|
||||
Query<T> elementQuery = search(elt);
|
||||
if (elementQuery == null) return;
|
||||
elementQuery.forEach(new Processor<T>() {
|
||||
public boolean process(final T psiElement) {
|
||||
if (psiElement instanceof NavigatablePsiElement) {
|
||||
navElements.add((NavigatablePsiElement)psiElement);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
final NavigatablePsiElement[] methods = navElements.toArray(new NavigatablePsiElement[navElements.size()]);
|
||||
PsiElementListNavigator.openTargets(e, methods, getTitle(elt), new DefaultPsiElementCellRenderer());
|
||||
}
|
||||
|
||||
protected abstract String getTitle(PsiElement elt);
|
||||
|
||||
@Nullable
|
||||
protected abstract Query<T> search(PsiElement elt);
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package com.jetbrains.python.codeInsight;
|
||||
|
||||
import com.intellij.codeHighlighting.Pass;
|
||||
import com.intellij.codeInsight.daemon.impl.LineMarkerInfo;
|
||||
import com.intellij.codeInsight.daemon.impl.LineMarkerProvider;
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.openapi.util.IconLoader;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.util.Query;
|
||||
import com.jetbrains.python.PyTokenTypes;
|
||||
import com.jetbrains.python.psi.PyClass;
|
||||
import com.jetbrains.python.psi.PyFunction;
|
||||
import com.jetbrains.python.psi.search.PyClassInheritorsSearch;
|
||||
import com.jetbrains.python.psi.search.PySuperMethodsSearch;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
*/
|
||||
public class PyLineMarkerProvider implements LineMarkerProvider {
|
||||
private static final Icon OVERRIDING_METHOD_ICON = IconLoader.getIcon("/gutter/overridingMethod.png");
|
||||
private static final Icon OVERRIDDEN_ICON = IconLoader.getIcon("/gutter/overridenMethod.png");
|
||||
|
||||
public LineMarkerInfo getLineMarkerInfo(final PsiElement element) {
|
||||
final ASTNode node = element.getNode();
|
||||
if (node != null && node.getElementType() == PyTokenTypes.IDENTIFIER && element.getParent() instanceof PyFunction) {
|
||||
final PyFunction function = (PyFunction)element.getParent();
|
||||
return getMethodMarker(element, function);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@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
|
||||
PyLineMarkerNavigator markerNavigator = new PyLineMarkerNavigator<PsiElement>() {
|
||||
protected String getTitle(final PsiElement elt) {
|
||||
return "Choose Super Method of " + ((PyFunction)elt.getParent()).getName();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected Query<PsiElement> search(final PsiElement elt) {
|
||||
if (!(elt.getParent() instanceof PyFunction)) return null;
|
||||
return PySuperMethodsSearch.search((PyFunction)elt.getParent());
|
||||
}
|
||||
};
|
||||
return new LineMarkerInfo(element, element.getTextRange().getStartOffset(), OVERRIDING_METHOD_ICON, Pass.UPDATE_ALL,
|
||||
null, markerNavigator);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void collectSlowLineMarkers(final List<PsiElement> elements, final Collection<LineMarkerInfo> result) {
|
||||
for(PsiElement element: elements) {
|
||||
if (element instanceof PyClass) {
|
||||
collectInheritingClasses((PyClass) element, result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void collectInheritingClasses(final PyClass element, final Collection<LineMarkerInfo> result) {
|
||||
if (PyClassInheritorsSearch.search(element, false).findFirst() != null) {
|
||||
PyLineMarkerNavigator navigator = new PyLineMarkerNavigator<PyClass>() {
|
||||
protected String getTitle(final PsiElement elt) {
|
||||
return "Choose Subclass of "+ ((PyClass) elt).getName();
|
||||
}
|
||||
|
||||
protected Query<PyClass> search(final PsiElement elt) {
|
||||
return PyClassInheritorsSearch.search((PyClass) elt, true);
|
||||
}
|
||||
};
|
||||
result.add(new LineMarkerInfo(element, element.getTextOffset(), OVERRIDDEN_ICON, Pass.UPDATE_OVERRIDEN_MARKERS,
|
||||
null, navigator));
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user