mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
PyClass.iterateAncestors() split into iterateAncestors() (returning class refs, which can be not classes or unresolved classes) and iterateAncestorClasses() (returning actual resolved classes); fix PY-817
This commit is contained in:
@@ -426,7 +426,7 @@ public class PythonDocumentationProvider extends QuickDocumentationProvider {
|
||||
if (cls != null && meth_name != null) {
|
||||
final boolean is_constructor = PyNames.INIT.equals(meth_name);
|
||||
// look for inherited and its doc
|
||||
Iterable<PyClass> classes = cls.iterateAncestors();
|
||||
Iterable<PyClass> classes = cls.iterateAncestorClasses();
|
||||
if (is_constructor) {
|
||||
// look at our own class again and maybe inherit class's doc
|
||||
classes = new ChainIterable<PyClass>(cls).add(classes);
|
||||
@@ -496,9 +496,9 @@ public class PythonDocumentationProvider extends QuickDocumentationProvider {
|
||||
PyClass cls = inferContainingClassOf(context);
|
||||
if (cls != null) {
|
||||
String desired_name = link.substring(LINK_TYPE_PARENT.length());
|
||||
for (PyClass parent : cls.iterateAncestors()) {
|
||||
final String parent_name = parent.getName();
|
||||
if (parent_name != null && parent_name.equals(desired_name)) return parent;
|
||||
for (PyClassRef parent : cls.iterateAncestors()) {
|
||||
final String parent_name = parent.getClassName();
|
||||
if (parent_name != null && parent_name.equals(desired_name)) return parent.getPyClass();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@ public class AddFieldQuickFix implements LocalQuickFix {
|
||||
return appendToInit(init, callback);
|
||||
}
|
||||
else { // no init! boldly copy ancestor's.
|
||||
for (PyClass ancestor : cls.iterateAncestors()) {
|
||||
for (PyClass ancestor : cls.iterateAncestorClasses()) {
|
||||
init = ancestor.findMethodByName(PyNames.INIT, false);
|
||||
if (init != null) break;
|
||||
}
|
||||
|
||||
@@ -45,13 +45,13 @@ public class PyGotoSuperHandler implements CodeInsightActionHandler {
|
||||
else {
|
||||
PyClass pyClass = PsiTreeUtil.getParentOfType(element, PyClass.class);
|
||||
if (pyClass != null) {
|
||||
PyClass[] superClasses = PyUtil.getAllSuperClasses(pyClass);
|
||||
if (superClasses.length != 0) {
|
||||
if (superClasses.length == 1) {
|
||||
superClasses[0].navigate(true);
|
||||
List<PyClass> superClasses = PyUtil.getAllSuperClasses(pyClass);
|
||||
if (superClasses.size() != 0) {
|
||||
if (superClasses.size() == 1) {
|
||||
superClasses.get(0).navigate(true);
|
||||
}
|
||||
else {
|
||||
NavigationUtil.getPsiElementPopup(superClasses, CodeInsightBundle.message("goto.super.class.chooser.title"))
|
||||
NavigationUtil.getPsiElementPopup(superClasses.toArray(new PyClass[superClasses.size()]), CodeInsightBundle.message("goto.super.class.chooser.title"))
|
||||
.showInBestPositionFor(editor);
|
||||
}
|
||||
}
|
||||
@@ -66,7 +66,7 @@ public class PyGotoSuperHandler implements CodeInsightActionHandler {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
final List<PyFunction> result = new ArrayList<PyFunction>();
|
||||
for (PyClass aClass: pyClass.iterateAncestors()) {
|
||||
for (PyClass aClass: pyClass.iterateAncestorClasses()) {
|
||||
final PyFunction byName = aClass.findMethodByName(name, false);
|
||||
if (byName != null) {
|
||||
result.add(byName);
|
||||
|
||||
+5
-2
@@ -8,7 +8,10 @@ import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiWhiteSpace;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.ProcessingContext;
|
||||
import com.jetbrains.python.psi.*;
|
||||
import com.jetbrains.python.psi.PyClass;
|
||||
import com.jetbrains.python.psi.PyFunction;
|
||||
import com.jetbrains.python.psi.PyReferenceExpression;
|
||||
import com.jetbrains.python.psi.PyTargetExpression;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
@@ -42,7 +45,7 @@ public class PySuperAttributesCompletionContributor extends CompletionContributo
|
||||
for (PyTargetExpression expr : containingClass.getClassAttributes()) {
|
||||
seenNames.add(expr.getName());
|
||||
}
|
||||
for (PyClass ancestor : containingClass.iterateAncestors()) {
|
||||
for (PyClass ancestor : containingClass.iterateAncestorClasses()) {
|
||||
for (PyTargetExpression expr : ancestor.getClassAttributes()) {
|
||||
if (!seenNames.contains(expr.getName())) {
|
||||
result.addElement(LookupElementBuilder.create(expr, expr.getName() + " = "));
|
||||
|
||||
@@ -41,7 +41,7 @@ public class PySuperMethodCompletionContributor extends CompletionContributor {
|
||||
for (PyFunction function : containingClass.getMethods()) {
|
||||
seenNames.add(function.getName());
|
||||
}
|
||||
for (PyClass ancestor : containingClass.iterateAncestors()) {
|
||||
for (PyClass ancestor : containingClass.iterateAncestorClasses()) {
|
||||
for (PyFunction superMethod : ancestor.getMethods()) {
|
||||
if (!seenNames.contains(superMethod.getName())) {
|
||||
result.addElement(LookupElementBuilder.create(superMethod.getName() + superMethod.getParameterList().getText() + ":"));
|
||||
|
||||
@@ -219,7 +219,7 @@ public class PyOverrideImplementUtil {
|
||||
@NotNull
|
||||
private static Collection<PyFunction> getAllSuperFunctions(@NotNull final PyClass pyClass) {
|
||||
final Map<String, PyFunction> superFunctions = new HashMap<String, PyFunction>();
|
||||
for (PyClass aClass : pyClass.iterateAncestors()) {
|
||||
for (PyClass aClass : pyClass.iterateAncestorClasses()) {
|
||||
for (PyFunction function : aClass.getMethods()) {
|
||||
if (!superFunctions.containsKey(function.getName())) {
|
||||
superFunctions.put(function.getName(), function);
|
||||
|
||||
+5
-3
@@ -7,15 +7,17 @@ import com.jetbrains.python.psi.PyClass;
|
||||
import com.jetbrains.python.psi.PyUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Alexey.Ivanov
|
||||
*/
|
||||
public class PyTypeHierarchyTreeStructure extends PySubTypesHierarchyTreeStructure {
|
||||
private static PyTypeHierarchyNodeDescriptor buildHierarchyElement(@NotNull final PyClass cl) {
|
||||
PyTypeHierarchyNodeDescriptor descriptor = null;
|
||||
PyClass[] superClasses = PyUtil.getAllSuperClasses(cl);
|
||||
for (int i = superClasses.length - 1; i >= 0; --i) {
|
||||
final PyClass superClass = superClasses[i];
|
||||
List<PyClass> superClasses = PyUtil.getAllSuperClasses(cl);
|
||||
for (int i = superClasses.size() - 1; i >= 0; --i) {
|
||||
final PyClass superClass = superClasses.get(i);
|
||||
final PyTypeHierarchyNodeDescriptor newDescriptor = new PyTypeHierarchyNodeDescriptor(descriptor, superClass, false);
|
||||
if (descriptor != null) {
|
||||
descriptor.setCachedChildren(new PyTypeHierarchyNodeDescriptor[]{newDescriptor});
|
||||
|
||||
@@ -44,8 +44,8 @@ public class PyExceptionInheritInspection extends PyInspection {
|
||||
PsiElement psiElement = ((PyReferenceExpression)callee).getReference().resolve();
|
||||
if (psiElement instanceof PyClass) {
|
||||
PyClass aClass = (PyClass) psiElement;
|
||||
for (PyClass pyClass : aClass.iterateAncestors()) {
|
||||
if ("Exception".equals(pyClass.getName())) {
|
||||
for (PyClassRef pyClass : aClass.iterateAncestors()) {
|
||||
if ("Exception".equals(pyClass.getClassName())) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,7 +104,9 @@ public interface PyClass extends
|
||||
* A lazy way to list ancestor classes width first, in method-resolution order (MRO).
|
||||
* @return an iterable of ancestor classes.
|
||||
*/
|
||||
Iterable<PyClass> iterateAncestors();
|
||||
Iterable<PyClassRef> iterateAncestors();
|
||||
|
||||
Iterable<PyClass> iterateAncestorClasses();
|
||||
|
||||
/**
|
||||
* Scan properties in order of definition, until processor returns true for one of them.
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
package com.jetbrains.python.psi;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
*/
|
||||
public class PyClassRef {
|
||||
@Nullable
|
||||
private final PsiElement myElement;
|
||||
|
||||
public PyClassRef(PsiElement element) {
|
||||
myElement = element;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PyClass getPyClass() {
|
||||
return myElement instanceof PyClass ? (PyClass) myElement : null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getClassName() {
|
||||
return myElement instanceof PyClass ? ((PyClass) myElement).getName() : null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getQualifiedName() {
|
||||
return myElement instanceof PyClass ? ((PyClass) myElement).getQualifiedName() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
PyClassRef that = (PyClassRef)o;
|
||||
|
||||
if (myElement != null ? !myElement.equals(that.myElement) : that.myElement != null) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return myElement != null ? myElement.hashCode() : 0;
|
||||
}
|
||||
}
|
||||
@@ -342,15 +342,9 @@ public class PyUtil {
|
||||
* Collects superclasses of a class all the way up the inheritance chain. The order is <i>not</i> necessarily the MRO.
|
||||
*/
|
||||
@NotNull
|
||||
public static PyClass[] getAllSuperClasses(@NotNull PyClass pyClass) {
|
||||
Set<PyClass> superClasses = getAllSuperClassesSet(pyClass);
|
||||
return superClasses.toArray(new PyClass[superClasses.size()]);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Set<PyClass> getAllSuperClassesSet(PyClass pyClass) {
|
||||
Set<PyClass> superClasses = new HashSet<PyClass>();
|
||||
for (PyClass ancestor : pyClass.iterateAncestors()) superClasses.add(ancestor);
|
||||
public static List<PyClass> getAllSuperClasses(@NotNull PyClass pyClass) {
|
||||
List<PyClass> superClasses = new ArrayList<PyClass>();
|
||||
for (PyClass ancestor : pyClass.iterateAncestorClasses()) superClasses.add(ancestor);
|
||||
return superClasses;
|
||||
}
|
||||
|
||||
@@ -721,7 +715,7 @@ public class PyUtil {
|
||||
}
|
||||
|
||||
public static boolean isExceptionClass(PyClass pyClass) {
|
||||
for (PyClass c: pyClass.iterateAncestors()) {
|
||||
for (PyClassRef c: pyClass.iterateAncestors()) {
|
||||
if ("BaseException".equals(c.getQualifiedName())) {
|
||||
return true;
|
||||
}
|
||||
@@ -776,7 +770,7 @@ public class PyUtil {
|
||||
Set<PyFunction.Flag> flags = detectDecorationsAndWrappersOf(node);
|
||||
boolean isMetaclassMethod = false;
|
||||
PyClass type_cls = PyBuiltinCache.getInstance(node).getClass("type");
|
||||
for (PyClass ancestor_cls : cls.iterateAncestors()) {
|
||||
for (PyClass ancestor_cls : cls.iterateAncestorClasses()) {
|
||||
if (ancestor_cls == type_cls) {
|
||||
isMetaclassMethod = true;
|
||||
break;
|
||||
|
||||
@@ -143,13 +143,18 @@ public class PyClassImpl extends PyPresentableElementImpl<PyClassStub> implement
|
||||
/* The implementation is manifestly lazy wrt psi scanning and uses stack rather sparingly.
|
||||
It must be more efficient on deep and wide hierarchies, but it was more fun than efficiency that produced it.
|
||||
*/
|
||||
public Iterable<PyClass> iterateAncestors() {
|
||||
public Iterable<PyClassRef> iterateAncestors() {
|
||||
return new AncestorsIterable(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<PyClass> iterateAncestorClasses() {
|
||||
return new AncestorClassesIterable(this);
|
||||
}
|
||||
|
||||
public boolean isSubclass(PyClass parent) {
|
||||
if (this == parent) return true;
|
||||
for (PyClass superclass : iterateAncestors()) {
|
||||
for (PyClass superclass : iterateAncestorClasses()) {
|
||||
if (parent == superclass) return true;
|
||||
}
|
||||
return false;
|
||||
@@ -193,7 +198,7 @@ public class PyClassImpl extends PyPresentableElementImpl<PyClassStub> implement
|
||||
if (slots != null) {
|
||||
return slots;
|
||||
}
|
||||
for(PyClass cls: iterateAncestors()) {
|
||||
for(PyClass cls: iterateAncestorClasses()) {
|
||||
slots = ((PyClassImpl) cls).getOwnSlots();
|
||||
if (slots != null) {
|
||||
return slots;
|
||||
@@ -211,31 +216,34 @@ public class PyClassImpl extends PyPresentableElementImpl<PyClassStub> implement
|
||||
return PyFileImpl.getStringListFromTargetExpression(PyNames.SLOTS, getClassAttributes());
|
||||
}
|
||||
|
||||
protected List<PyClass> getSuperClassesList() {
|
||||
protected List<PyClassRef> getSuperClassesList() {
|
||||
if (PyNames.FAKE_OLD_BASE.equals(getName())) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
List<PyClassRef> result = new ArrayList<PyClassRef>();
|
||||
List<PyClass> superClasses = resolveSuperClassesFromStub();
|
||||
if (superClasses == null) {
|
||||
superClasses = new ArrayList<PyClass>();
|
||||
if (superClasses != null) {
|
||||
for (PyClass superClass : superClasses) {
|
||||
result.add(new PyClassRef(superClass));
|
||||
}
|
||||
}
|
||||
else {
|
||||
PsiElement[] superClassElements = getSuperClassElements();
|
||||
for (PsiElement element : superClassElements) {
|
||||
if (element instanceof PyClass) {
|
||||
superClasses.add((PyClass)element);
|
||||
}
|
||||
result.add(new PyClassRef(element));
|
||||
}
|
||||
}
|
||||
|
||||
if (superClasses.size() == 0 && !PyBuiltinCache.getInstance(this).hasInBuiltins(this)) {
|
||||
if (result.size() == 0 && !PyBuiltinCache.getInstance(this).hasInBuiltins(this)) {
|
||||
String implicitSuperclassName = LanguageLevel.forElement(this).isPy3K() ? PyNames.OBJECT : PyNames.FAKE_OLD_BASE;
|
||||
PyClass implicitSuperclass = PyBuiltinCache.getInstance(this).getClass(implicitSuperclassName);
|
||||
if (implicitSuperclass != null) {
|
||||
superClasses.add(implicitSuperclass);
|
||||
result.add(new PyClassRef(implicitSuperclass));
|
||||
}
|
||||
}
|
||||
|
||||
return superClasses;
|
||||
return result;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -508,7 +516,7 @@ public class PyClassImpl extends PyPresentableElementImpl<PyClassStub> implement
|
||||
};
|
||||
Property prop = findPropertyLocally(name_filer, null, use_advanced_syntax);
|
||||
if (prop != null) return prop;
|
||||
for (PyClass cls : iterateAncestors()) {
|
||||
for (PyClass cls : iterateAncestorClasses()) {
|
||||
prop = ((PyClassImpl)cls).findPropertyLocally(name_filer, null, use_advanced_syntax);
|
||||
if (prop != null) return prop;
|
||||
}
|
||||
@@ -529,7 +537,7 @@ public class PyClassImpl extends PyPresentableElementImpl<PyClassStub> implement
|
||||
Property property = findPropertyLocally(null, processor, use_advanced_syntax);
|
||||
if (property != null) return property;
|
||||
if (inherited) {
|
||||
for (PyClass cls : iterateAncestors()) {
|
||||
for (PyClass cls : iterateAncestorClasses()) {
|
||||
property = ((PyClassImpl)cls).findPropertyLocally(null, processor, use_advanced_syntax);
|
||||
if (property != null) return property;
|
||||
}
|
||||
@@ -624,7 +632,7 @@ public class PyClassImpl extends PyPresentableElementImpl<PyClassStub> implement
|
||||
if (! processor.process(method)) return false;
|
||||
}
|
||||
if (inherited) {
|
||||
for (PyClass ancestor : iterateAncestors()) {
|
||||
for (PyClass ancestor : iterateAncestorClasses()) {
|
||||
if (!ancestor.visitMethods(processor, false)) {
|
||||
return false;
|
||||
}
|
||||
@@ -639,7 +647,7 @@ public class PyClassImpl extends PyPresentableElementImpl<PyClassStub> implement
|
||||
if (!processor.process(nestedClass)) return false;
|
||||
}
|
||||
if (inherited) {
|
||||
for (PyClass ancestor : iterateAncestors()) {
|
||||
for (PyClass ancestor : iterateAncestorClasses()) {
|
||||
if (!((PyClassImpl) ancestor).visitNestedClasses(processor, false)) {
|
||||
return false;
|
||||
}
|
||||
@@ -654,7 +662,7 @@ public class PyClassImpl extends PyPresentableElementImpl<PyClassStub> implement
|
||||
if (! processor.process(attribute)) return false;
|
||||
}
|
||||
if (inherited) {
|
||||
for (PyClass ancestor : iterateAncestors()) {
|
||||
for (PyClass ancestor : iterateAncestorClasses()) {
|
||||
if (!ancestor.visitClassAttributes(processor, false)) {
|
||||
return false;
|
||||
}
|
||||
@@ -767,9 +775,14 @@ public class PyClassImpl extends PyPresentableElementImpl<PyClassStub> implement
|
||||
PyClass objclass = PyBuiltinCache.getInstance(this).getClass("object");
|
||||
if (this == objclass) return true; // a rare but possible case
|
||||
if (hasNewStyleMetaClass(this)) return true;
|
||||
for (PyClass ancestor : iterateAncestors()) {
|
||||
if (ancestor == objclass) return true;
|
||||
if (hasNewStyleMetaClass(ancestor)) {
|
||||
for (PyClassRef ancestor : iterateAncestors()) {
|
||||
PyClass pyClass = ancestor.getPyClass();
|
||||
if (pyClass == null) {
|
||||
// unknown, assume new-style class
|
||||
return true;
|
||||
}
|
||||
if (pyClass == objclass) return true;
|
||||
if (hasNewStyleMetaClass(pyClass)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -906,32 +919,32 @@ public class PyClassImpl extends PyPresentableElementImpl<PyClassStub> implement
|
||||
return reference != null ? reference.get() : null;
|
||||
}
|
||||
|
||||
private static class AncestorsIterable implements Iterable<PyClass> {
|
||||
private static class AncestorsIterable implements Iterable<PyClassRef> {
|
||||
private final PyClassImpl myClass;
|
||||
|
||||
public AncestorsIterable(final PyClassImpl pyClass) {
|
||||
myClass = pyClass;
|
||||
}
|
||||
|
||||
public Iterator<PyClass> iterator() {
|
||||
public Iterator<PyClassRef> iterator() {
|
||||
return new AncestorsIterator(myClass);
|
||||
}
|
||||
}
|
||||
|
||||
private static class AncestorsIterator implements Iterator<PyClass> {
|
||||
List<PyClassImpl> pending = new LinkedList<PyClassImpl>();
|
||||
Set<PyClass> seen;
|
||||
Iterator<PyClass> percolator;
|
||||
PyClass prefetch = null;
|
||||
private static class AncestorsIterator implements Iterator<PyClassRef> {
|
||||
List<PyClassRef> pending = new LinkedList<PyClassRef>();
|
||||
private final Set<PyClassRef> seen;
|
||||
Iterator<PyClassRef> percolator;
|
||||
PyClassRef prefetch = null;
|
||||
private final PyClassImpl myAClass;
|
||||
|
||||
public AncestorsIterator(PyClassImpl aClass) {
|
||||
myAClass = aClass;
|
||||
percolator = myAClass.getSuperClassesList().iterator();
|
||||
seen = new HashSet<PyClass>();
|
||||
seen = new HashSet<PyClassRef>();
|
||||
}
|
||||
|
||||
private AncestorsIterator(PyClassImpl AClass, Set<PyClass> seen) {
|
||||
private AncestorsIterator(PyClassImpl AClass, Set<PyClassRef> seen) {
|
||||
myAClass = AClass;
|
||||
this.seen = seen;
|
||||
percolator = myAClass.getSuperClassesList().iterator();
|
||||
@@ -944,23 +957,23 @@ public class PyClassImpl extends PyPresentableElementImpl<PyClassStub> implement
|
||||
return prefetch != null;
|
||||
}
|
||||
|
||||
public PyClass next() {
|
||||
final PyClass nextClass = getNext();
|
||||
public PyClassRef next() {
|
||||
final PyClassRef nextClass = getNext();
|
||||
if (nextClass == null) throw new NoSuchElementException();
|
||||
return nextClass;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private PyClass getNext() {
|
||||
private PyClassRef getNext() {
|
||||
iterations:
|
||||
while (true) {
|
||||
if (prefetch != null) {
|
||||
PyClass ret = prefetch;
|
||||
PyClassRef ret = prefetch;
|
||||
prefetch = null;
|
||||
return ret;
|
||||
}
|
||||
if (percolator.hasNext()) {
|
||||
PyClassImpl it = (PyClassImpl)percolator.next();
|
||||
PyClassRef it = percolator.next();
|
||||
if (seen.contains(it)) {
|
||||
continue iterations; // loop back is equivalent to return next();
|
||||
}
|
||||
@@ -968,13 +981,18 @@ public class PyClassImpl extends PyPresentableElementImpl<PyClassStub> implement
|
||||
seen.add(it);
|
||||
return it;
|
||||
}
|
||||
else if (pending.size() > 0) {
|
||||
PyClassImpl it = pending.get(0);
|
||||
pending.remove(0); // t, ts* = pending
|
||||
percolator = new AncestorsIterator(it, new HashSet<PyClass>(seen));
|
||||
// loop back is equivalent to return next();
|
||||
else {
|
||||
while (pending.size() > 0) {
|
||||
PyClassRef it = pending.get(0);
|
||||
pending.remove(0);
|
||||
PyClass pyClass = it.getPyClass();
|
||||
if (pyClass != null) {
|
||||
percolator = new AncestorsIterator((PyClassImpl)pyClass, new HashSet<PyClassRef>(seen));
|
||||
continue iterations;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
else return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -983,5 +1001,59 @@ public class PyClassImpl extends PyPresentableElementImpl<PyClassStub> implement
|
||||
}
|
||||
}
|
||||
|
||||
private static class AncestorClassesIterable implements Iterable<PyClass> {
|
||||
private final PyClassImpl myClass;
|
||||
|
||||
public AncestorClassesIterable(final PyClassImpl pyClass) {
|
||||
myClass = pyClass;
|
||||
}
|
||||
|
||||
public Iterator<PyClass> iterator() {
|
||||
return new AncestorClassesIterator(new AncestorsIterator(myClass));
|
||||
}
|
||||
}
|
||||
|
||||
private static class AncestorClassesIterator implements Iterator<PyClass> {
|
||||
private final AncestorsIterator myAncestorsIterator;
|
||||
private PyClass myNext;
|
||||
|
||||
public AncestorClassesIterator(AncestorsIterator ancestorsIterator) {
|
||||
myAncestorsIterator = ancestorsIterator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
if (myNext != null) {
|
||||
return true;
|
||||
}
|
||||
while (myAncestorsIterator.hasNext()) {
|
||||
PyClassRef clsRef = myAncestorsIterator.getNext();
|
||||
if (clsRef == null) {
|
||||
return false;
|
||||
}
|
||||
myNext = clsRef.getPyClass();
|
||||
if (myNext != null) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PyClass next() {
|
||||
if (myNext == null) {
|
||||
if (!hasNext()) return null;
|
||||
}
|
||||
PyClass next = myNext;
|
||||
myNext = null;
|
||||
return next;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -114,7 +114,7 @@ public class PyReferenceImpl implements PsiReferenceEx, PsiPolyVariantReference
|
||||
it.set(rrr.replace(init));
|
||||
}
|
||||
else { // init not found; maybe it's ancestor's
|
||||
for (PyClass ancestor : cls.iterateAncestors()) {
|
||||
for (PyClass ancestor : cls.iterateAncestorClasses()) {
|
||||
init = ancestor.findMethodByName(PyNames.INIT, false);
|
||||
if (init != null) {
|
||||
// add to resuls as low priority
|
||||
|
||||
@@ -20,7 +20,7 @@ public class PySuperMethodsSearchExecutor implements QueryExecutor<PsiElement, P
|
||||
PyClass containingClass = func.getContainingClass();
|
||||
Set<PyClass> foundMethodContainingClasses = new HashSet<PyClass>();
|
||||
if (name != null && containingClass != null) {
|
||||
for (PyClass superClass : containingClass.iterateAncestors()) {
|
||||
for (PyClass superClass : containingClass.iterateAncestorClasses()) {
|
||||
if (!queryParameters.isDeepSearch()) {
|
||||
boolean isAlreadyFound = false;
|
||||
for (PyClass alreadyFound : foundMethodContainingClasses) {
|
||||
|
||||
@@ -128,7 +128,7 @@ public class PyClassType extends UserDataHolderBase implements PyType {
|
||||
return new SmartList<PsiElement>(classMember);
|
||||
}
|
||||
|
||||
for (PyClass superClass : myClass.iterateAncestors()) {
|
||||
for (PyClass superClass : myClass.iterateAncestorClasses()) {
|
||||
PsiElement superMember = resolveClassMember(superClass, name, null);
|
||||
if (superMember != null) {
|
||||
return new SmartList<PsiElement>(superMember);
|
||||
|
||||
@@ -103,7 +103,7 @@ public class PyStructureViewElement implements StructureViewTreeElement {
|
||||
if (element instanceof PyClass) {
|
||||
PyClass the_exception = PyBuiltinCache.getInstance(element).getClass("Exception");
|
||||
final PyClass cls = (PyClass)element;
|
||||
for (PyClass anc : cls.iterateAncestors()) {
|
||||
for (PyClass anc : cls.iterateAncestorClasses()) {
|
||||
if (anc == the_exception) {
|
||||
((PyStructureViewElement)(children[i])).setIcon(Icons.EXCEPTION_CLASS_ICON);
|
||||
break;
|
||||
|
||||
@@ -8,7 +8,6 @@ import org.jetbrains.annotations.NotNull;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
|
||||
@@ -80,10 +79,9 @@ public class PythonUnitTestUtil {
|
||||
}
|
||||
|
||||
public static boolean isTestCaseClass(@NotNull PyClass cls, Set<String> testQualifiedNames) {
|
||||
for (PyClass ancestor : cls.iterateAncestors()) {
|
||||
if (ancestor == null) continue;
|
||||
|
||||
for (PyClassRef ancestor : cls.iterateAncestors()) {
|
||||
String qName = ancestor.getQualifiedName();
|
||||
if (qName == null) continue;
|
||||
if (testQualifiedNames.contains(qName)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2,10 +2,7 @@ package com.jetbrains.python.testing.pytest;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.jetbrains.python.psi.PyClass;
|
||||
import com.jetbrains.python.psi.PyFile;
|
||||
import com.jetbrains.python.psi.PyFunction;
|
||||
import com.jetbrains.python.psi.PyStatement;
|
||||
import com.jetbrains.python.psi.*;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
@@ -40,26 +37,21 @@ public class PyTestUtil {
|
||||
}
|
||||
|
||||
public static boolean isPyTestClass(PyClass pyClass) {
|
||||
for (PyClass ancestor : pyClass.iterateAncestors()) {
|
||||
if (ancestor == null) continue;
|
||||
|
||||
for (PyClassRef ancestor : pyClass.iterateAncestors()) {
|
||||
String qName = ancestor.getQualifiedName();
|
||||
if (PYTHON_TEST_QUALIFIED_CLASSES.contains(qName)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
String name = pyClass.getName().toLowerCase();
|
||||
if (name != null && name.startsWith("test")) {
|
||||
List<PyStatement> result = Lists.newArrayList();
|
||||
for (PyFunction cls : pyClass.getMethods()) {
|
||||
if (isPyTestFunction(cls)) {
|
||||
result.add(cls);
|
||||
}
|
||||
}
|
||||
|
||||
String name = pyClass.getName().toLowerCase();
|
||||
if (name != null && name.startsWith("test")) {
|
||||
for (PyFunction cls : pyClass.getMethods()) {
|
||||
if (isPyTestFunction(cls)) {
|
||||
return true;
|
||||
}
|
||||
if (!result.isEmpty()) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -13,3 +13,12 @@ class D(C):
|
||||
|
||||
class E:
|
||||
__metaclass__ = None
|
||||
|
||||
|
||||
def create_meta():
|
||||
return type
|
||||
|
||||
Meta = create_meta()
|
||||
|
||||
class Something(Meta):
|
||||
pass
|
||||
|
||||
Reference in New Issue
Block a user