From 6ca70dc68b38fb680530d4f0bf613ab4b59b4d5b Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Tue, 3 Apr 2012 18:52:51 +0200 Subject: [PATCH] provide type also for functions annotated as setter or deleter (PY-5951 take 2) --- python/src/com/jetbrains/python/PyNames.java | 2 ++ .../inspections/PyPropertyDefinitionInspection.java | 2 +- .../com/jetbrains/python/psi/impl/PyClassImpl.java | 4 ++-- .../python/psi/impl/PyReferenceExpressionImpl.java | 10 ++++++++-- .../completion/propertyAfterAccessor.after.py | 13 +++++++++++++ python/testData/completion/propertyAfterAccessor.py | 13 +++++++++++++ .../com/jetbrains/python/Py3CompletionTest.java | 4 ++++ 7 files changed, 43 insertions(+), 5 deletions(-) create mode 100644 python/testData/completion/propertyAfterAccessor.after.py create mode 100644 python/testData/completion/propertyAfterAccessor.py diff --git a/python/src/com/jetbrains/python/PyNames.java b/python/src/com/jetbrains/python/PyNames.java index cbb6811dc4e8..b15baf0f7df1 100644 --- a/python/src/com/jetbrains/python/PyNames.java +++ b/python/src/com/jetbrains/python/PyNames.java @@ -42,6 +42,8 @@ public class PyNames { public static final String STATICMETHOD = "staticmethod"; public static final String PROPERTY = "property"; + public static final String SETTER = "setter"; + public static final String DELETER = "deleter"; public static final String ALL = "__all__"; public static final String SLOTS = "__slots__"; diff --git a/python/src/com/jetbrains/python/inspections/PyPropertyDefinitionInspection.java b/python/src/com/jetbrains/python/inspections/PyPropertyDefinitionInspection.java index 47bc56738dd0..5e174b23caff 100644 --- a/python/src/com/jetbrains/python/inspections/PyPropertyDefinitionInspection.java +++ b/python/src/com/jetbrains/python/inspections/PyPropertyDefinitionInspection.java @@ -44,7 +44,7 @@ public class PyPropertyDefinitionInspection extends PyInspection { return PyBundle.message("INSP.NAME.property.definition"); } - private static final ImmutableList SUFFIXES = ImmutableList.of("setter", "deleter"); + private static final ImmutableList SUFFIXES = ImmutableList.of(PyNames.SETTER, PyNames.DELETER); @NotNull @Override diff --git a/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java b/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java index 3c6961501d60..81af6004eb3f 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java @@ -559,10 +559,10 @@ public class PyClassImpl extends PyPresentableElementImpl implement if (qname.matches(PyNames.PROPERTY)) { getter = new Maybe(method); } - else if (useAdvancedSyntax && qname.matches(decoratorName, "setter")) { + else if (useAdvancedSyntax && qname.matches(decoratorName, PyNames.SETTER)) { setter = new Maybe(method); } - else if (useAdvancedSyntax && qname.matches(decoratorName, "deleter")) { + else if (useAdvancedSyntax && qname.matches(decoratorName, PyNames.DELETER)) { deleter = new Maybe(method); } } diff --git a/python/src/com/jetbrains/python/psi/impl/PyReferenceExpressionImpl.java b/python/src/com/jetbrains/python/psi/impl/PyReferenceExpressionImpl.java index 1980ef1eb285..d08b1d56b694 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyReferenceExpressionImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyReferenceExpressionImpl.java @@ -313,10 +313,16 @@ public class PyReferenceExpressionImpl extends PyElementImpl implements PyRefere if (target instanceof PyFunction) { final PyDecoratorList decoratorList = ((PyFunction)target).getDecoratorList(); if (decoratorList != null) { - final PyDecorator decorator = decoratorList.findDecorator(PyNames.PROPERTY); - if (decorator != null) { + final PyDecorator propertyDecorator = decoratorList.findDecorator(PyNames.PROPERTY); + if (propertyDecorator != null) { return PyBuiltinCache.getInstance(target).getObjectType(PyNames.PROPERTY); } + for (PyDecorator decorator: decoratorList.getDecorators()) { + final PyQualifiedName qName = decorator.getQualifiedName(); + if (qName != null && (qName.endsWith(PyNames.SETTER) || qName.endsWith(PyNames.DELETER))) { + return PyBuiltinCache.getInstance(target).getObjectType(PyNames.PROPERTY); + } + } } } return null; diff --git a/python/testData/completion/propertyAfterAccessor.after.py b/python/testData/completion/propertyAfterAccessor.after.py new file mode 100644 index 000000000000..f01541d6d155 --- /dev/null +++ b/python/testData/completion/propertyAfterAccessor.after.py @@ -0,0 +1,13 @@ +class C(object): + def __init__(self): + self._x = None + + @property + def x(self): + return self._x + + @x.setter + def x(self, value): + self._x = value + + @x.deleter \ No newline at end of file diff --git a/python/testData/completion/propertyAfterAccessor.py b/python/testData/completion/propertyAfterAccessor.py new file mode 100644 index 000000000000..95f719795adb --- /dev/null +++ b/python/testData/completion/propertyAfterAccessor.py @@ -0,0 +1,13 @@ +class C(object): + def __init__(self): + self._x = None + + @property + def x(self): + return self._x + + @x.setter + def x(self, value): + self._x = value + + @x.d \ No newline at end of file diff --git a/python/testSrc/com/jetbrains/python/Py3CompletionTest.java b/python/testSrc/com/jetbrains/python/Py3CompletionTest.java index d4b88bc6dbab..7a26337b5444 100644 --- a/python/testSrc/com/jetbrains/python/Py3CompletionTest.java +++ b/python/testSrc/com/jetbrains/python/Py3CompletionTest.java @@ -16,6 +16,10 @@ public class Py3CompletionTest extends PyTestCase { doTest(); } + public void testPropertyAfterAccessor() { // PY-5951 + doTest(); + } + private void doTest() { final String testName = "completion/" + getTestName(true); myFixture.configureByFile(testName + ".py");