Completion for classes with non-class expressions in their base class list (PY-4345)

This commit is contained in:
Andrey Vlasovskikh
2013-01-22 18:00:02 +04:00
parent b51445925e
commit bb91645b36
4 changed files with 50 additions and 8 deletions
@@ -11,6 +11,7 @@ import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.UserDataHolderBase;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiInvalidElementAccessException;
import com.intellij.psi.PsiReference;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.ArrayUtil;
import com.intellij.util.ProcessingContext;
@@ -369,16 +370,33 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType {
Set<String> namesAlready,
ProcessingContext context,
List<Object> ret) {
for (PyClass ancestor : myClass.getSuperClasses()) {
Object[] ancestry = (new PyClassTypeImpl(ancestor, myIsDefinition)).getCompletionVariants(name, expressionHook, context);
for (Object ob : ancestry) {
String inheritedName = ob.toString();
if (!namesAlready.contains(inheritedName) && !isClassPrivate(inheritedName)) {
ret.add(ob);
namesAlready.add(inheritedName);
for (PyExpression expression : myClass.getSuperClassExpressions()) {
final PsiReference reference = expression.getReference();
PsiElement element = null;
if (reference != null) {
element = reference.resolve();
}
PyType type;
if (element instanceof PyClass) {
type = new PyClassTypeImpl((PyClass)element, myIsDefinition);
}
else {
type = expression.getType(TypeEvalContext.fastStubOnly(myClass.getContainingFile()));
if (type instanceof PyClassType && !myIsDefinition) {
type = ((PyClassType)type).toInstance();
}
}
ContainerUtil.addAll(ret, ancestry);
if (type != null) {
Object[] ancestry = type.getCompletionVariants(name, expressionHook, context);
for (Object ob : ancestry) {
String inheritedName = ob.toString();
if (!namesAlready.contains(inheritedName) && !isClassPrivate(inheritedName)) {
ret.add(ob);
namesAlready.add(inheritedName);
}
}
ContainerUtil.addAll(ret, ancestry);
}
}
}
@@ -0,0 +1,10 @@
from collections import namedtuple
class C(namedtuple('Coord', 'latitude longitude')):
def foo(self):
return -1
c = C()
c.latitude
@@ -0,0 +1,10 @@
from collections import namedtuple
class C(namedtuple('Coord', 'latitude longitude')):
def foo(self):
return -1
c = C()
c.lat<caret>
@@ -33,6 +33,10 @@ public class Py3CompletionTest extends PyTestCase {
assertTrue(strings.contains("long"));
}
public void testNamedTupleBaseClass() {
doTest();
}
private void doTest() {
CamelHumpMatcher.forceStartMatching(getTestRootDisposable());
final String testName = "completion/" + getTestName(true);