provide type, and therefore completion, for function decorated with @property (PY-5951)

This commit is contained in:
Dmitry Jemerov
2012-03-06 18:14:48 +01:00
parent 1d6f4838be
commit f00c0ad5fc
6 changed files with 62 additions and 5 deletions
@@ -306,14 +306,18 @@ public class PyReferenceExpressionImpl extends PyElementImpl implements PyRefere
PsiFile file = ((PsiDirectory)target).findFile(PyNames.INIT_DOT_PY);
if (file != null) return getTypeFromTarget(file, context, anchor);
}
if (target instanceof PyFunction) {
final PyDecoratorList decoratorList = ((PyFunction)target).getDecoratorList();
if (decoratorList != null) {
final PyDecorator decorator = decoratorList.findDecorator(PyNames.PROPERTY);
if (decorator != null) {
return PyBuiltinCache.getInstance(target).getObjectType(PyNames.PROPERTY);
}
}
}
return null;
}
@Nullable
private static PyType getTypeIfExpr(PyElement def, TypeEvalContext context) {
return def instanceof PyExpression ? context.getType((PyExpression)def) : null;
}
@Nullable
public static PyType getReferenceTypeFromProviders(@NotNull final PsiElement target,
TypeEvalContext context,
@@ -8,9 +8,11 @@ import com.intellij.psi.PsiElement;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.Function;
import com.intellij.util.PlatformIcons;
import com.jetbrains.python.PyNames;
import com.jetbrains.python.codeInsight.completion.PyClassInsertHandler;
import com.jetbrains.python.codeInsight.completion.PyFunctionInsertHandler;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.impl.PyBuiltinCache;
import com.jetbrains.python.psi.types.PyType;
import com.jetbrains.python.psi.types.TypeEvalContext;
import org.jetbrains.annotations.Nullable;
@@ -65,6 +67,13 @@ public class CompletionVariantsProcessor extends VariantsProcessor {
}
private static boolean isSingleArgDecoratorCall(PsiElement elementInCall, PyFunction callee) {
// special case hack to avoid the need of patching generator3.py
PyClass containingClass = callee.getContainingClass();
if (containingClass != null && PyNames.PROPERTY.equals(containingClass.getName()) &&
PyBuiltinCache.getInstance(elementInCall).hasInBuiltins(containingClass)) {
return true;
}
if (callee.getParameterList().getParameters().length > 1) {
return false;
}
@@ -0,0 +1,9 @@
class C(object):
def __init__(self):
self._x = None
@property
def x(self):
return self._x
@x.setter
@@ -0,0 +1,9 @@
class C(object):
def __init__(self):
self._x = None
@property
def x(self):
return self._x
@x.set<caret>
@@ -0,0 +1,25 @@
package com.jetbrains.python;
import com.intellij.testFramework.LightProjectDescriptor;
import com.jetbrains.python.fixtures.PyTestCase;
/**
* @author yole
*/
public class Py3CompletionTest extends PyTestCase {
@Override
protected LightProjectDescriptor getProjectDescriptor() {
return ourPy3Descriptor;
}
public void testPropertyDecorator() {
doTest();
}
private void doTest() {
final String testName = "completion/" + getTestName(true);
myFixture.configureByFile(testName + ".py");
myFixture.completeBasic();
myFixture.checkResultByFile(testName + ".after.py");
}
}
@@ -39,6 +39,7 @@ public class PythonAllTestsSuite {
CythonResolveTest.class,
PyAssignmentMappingTest.class,
PythonCompletionTest.class,
Py3CompletionTest.class,
PyInheritorsSearchTest.class,
PyParameterInfoTest.class,
PyDecoratorTest.class,