diff --git a/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java b/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java index c27c3c57bfbd..0556b290b23b 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java @@ -579,38 +579,38 @@ public class PyClassImpl extends PyPresentableElementImpl implement return null; } - private Maybe fromPacked(Maybe maybe_name) { - if (maybe_name.isDefined()) { - PyFunction method = findMethodByName(maybe_name.value(), true); + private Maybe fromPacked(Maybe maybeName) { + if (maybeName.isDefined()) { + final String value = maybeName.value(); + if (value == null || PyNames.NONE.equals(value)) { + return NONE; + } + PyFunction method = findMethodByName(value, true); if (method != null) return new Maybe(method); } return UNKNOWN_CALL; } @Nullable - private Property lookInStubProperties(@Nullable String name, @Nullable Processor property_filter) { - Maybe getter = NONE; - Maybe setter = NONE; - Maybe deleter = NONE; - String doc = null; + private Property lookInStubProperties(@Nullable String name, @Nullable Processor propertyProcessor) { final PyClassStub stub = getStub(); if (stub != null) { for (StubElement substub : stub.getChildrenStubs()) { if (substub.getStubType() == PyElementTypes.TARGET_EXPRESSION) { - final PyTargetExpressionStub target_stub = (PyTargetExpressionStub)substub; - PropertyStubStorage prop = target_stub.getCustomStub(PropertyStubStorage.class); - if (prop != null && (name == null || name.equals(target_stub.getName()))) { - getter = fromPacked(prop.getGetter()); - setter = fromPacked(prop.getSetter()); - deleter = fromPacked(prop.getDeleter()); - doc = prop.getDoc(); + final PyTargetExpressionStub targetStub = (PyTargetExpressionStub)substub; + PropertyStubStorage prop = targetStub.getCustomStub(PropertyStubStorage.class); + if (prop != null && (name == null || name.equals(targetStub.getName()))) { + Maybe getter = fromPacked(prop.getGetter()); + Maybe setter = fromPacked(prop.getSetter()); + Maybe deleter = fromPacked(prop.getDeleter()); + String doc = prop.getDoc(); + if (getter != NONE || setter != NONE || deleter != NONE) { + final PropertyImpl property = new PropertyImpl(getter, setter, deleter, doc, targetStub.getPsi()); + if (propertyProcessor == null || propertyProcessor.process(property)) return property; + } } } } - if (getter != NONE || setter != NONE || deleter != NONE) { - final PropertyImpl prop = new PropertyImpl(getter, setter, deleter, doc, null); - if (property_filter == null || property_filter.process(prop)) return prop; - } } return null; } diff --git a/python/src/com/jetbrains/python/psi/stubs/PropertyStubStorage.java b/python/src/com/jetbrains/python/psi/stubs/PropertyStubStorage.java index 11ec9412da0c..69a17b166e73 100644 --- a/python/src/com/jetbrains/python/psi/stubs/PropertyStubStorage.java +++ b/python/src/com/jetbrains/python/psi/stubs/PropertyStubStorage.java @@ -30,28 +30,6 @@ public class PropertyStubStorage extends PropertyBunch implements Custom return name; } - @NotNull - @Override - public Maybe getGetter() { - return myGetter; - } - - @NotNull - @Override - public Maybe getSetter() { - return mySetter; - } - - @NotNull - @Override - public Maybe getDeleter() { - return myDeleter; - } - - public String getDoc() { - return myDoc; - } - private static final String IMPOSSIBLE_NAME = "#"; private static void writeOne(Maybe what, StubOutputStream stream) throws IOException { diff --git a/python/testData/property/Classic.py b/python/testData/property/Classic.py index f2a22d092c27..26c15ae2da42 100644 --- a/python/testData/property/Classic.py +++ b/python/testData/property/Classic.py @@ -15,5 +15,3 @@ class A(object): v2 = property(fset=setter, fdel=deleter, fget=getter, doc="doc of v2") v3 = property(lambda self: self._v, None, (deleter)) v4 = otherworldly # NOTE: not supported yet - -a = A() diff --git a/python/testData/property/Decorated.py b/python/testData/property/Decorated.py index ec162a99493a..45def67d4e61 100644 --- a/python/testData/property/Decorated.py +++ b/python/testData/property/Decorated.py @@ -25,5 +25,3 @@ class A(object): self._v = v # deleter absent - -a = A() diff --git a/python/testSrc/com/jetbrains/python/PyClassicPropertyTest.java b/python/testSrc/com/jetbrains/python/PyClassicPropertyTest.java new file mode 100644 index 000000000000..65347b0531a5 --- /dev/null +++ b/python/testSrc/com/jetbrains/python/PyClassicPropertyTest.java @@ -0,0 +1,111 @@ +package com.jetbrains.python; + +import com.jetbrains.python.fixtures.PyTestCase; +import com.jetbrains.python.psi.*; +import com.jetbrains.python.toolbox.Maybe; + +public class PyClassicPropertyTest extends PyTestCase { + protected PyClass myClass; + + @Override + protected void setUp() throws Exception { + super.setUp(); + final PyFile file = (PyFile)myFixture.configureByFile("property/Classic.py"); + myClass = file.getTopLevelClasses().get(0); + } + + public void testV1() throws Exception { + Property p; + Maybe accessor; + p = myClass.findProperty("v1"); + assertNotNull(p); + assertNull(p.getDoc()); + PyTargetExpression site = p.getDefinitionSite(); + assertEquals("v1", site.getText()); + + accessor = p.getGetter(); + assertTrue(accessor.isDefined()); + assertNotNull(accessor.value()); + assertEquals("getter", accessor.value().getName()); + + accessor = p.getSetter(); + assertTrue(accessor.isDefined()); + assertNotNull(accessor.value()); + assertEquals("setter", accessor.value().getName()); + + accessor = p.getDeleter(); + assertTrue(accessor.isDefined()); + assertNull(accessor.value()); + } + + public void testV2() throws Exception { + Property p; + Maybe accessor; + p = myClass.findProperty("v2"); + assertNotNull(p); + assertEquals("doc of v2", p.getDoc()); + PyTargetExpression site = p.getDefinitionSite(); + assertEquals("v2", site.getText()); + + accessor = p.getGetter(); + assertTrue(accessor.isDefined()); + assertNotNull(accessor.value()); + assertEquals("getter", accessor.value().getName()); + + accessor = p.getSetter(); + assertTrue(accessor.isDefined()); + assertNotNull(accessor.value()); + assertEquals("setter", accessor.value().getName()); + + accessor = p.getDeleter(); + assertTrue(accessor.isDefined()); + assertNotNull(accessor.value()); + assertEquals("deleter", accessor.value().getName()); + } + + public void testV3() throws Exception { + Property p; + Maybe accessor; + p = myClass.findProperty("v3"); + assertNotNull(p); + assertNull(p.getDoc()); + PyTargetExpression site = p.getDefinitionSite(); + assertEquals("v3", site.getText()); + + accessor = p.getGetter(); + assertFalse(accessor.isDefined()); + + accessor = p.getSetter(); + assertTrue(accessor.isDefined()); + assertNull(accessor.value()); + + accessor = p.getDeleter(); + assertTrue(accessor.isDefined()); + assertNotNull(accessor.value()); + assertEquals("deleter", accessor.value().getName()); + } + + /* NOTE: we don't support this yet + public void testV4() throws Exception { + Property p; + Maybe accessor; + p = myClass.findProperty("v4"); + assertNotNull(p); + assertEquals("otherworldly", p.getDoc()); + PyTargetExpression site = p.getDefinitionSite(); + assertEquals("otherworldly", site.getText()); + + accessor = p.getGetter(); + assertFalse(accessor.isDefined()); + + accessor = p.getSetter(); + assertTrue(accessor.isDefined()); + assertNull(accessor.value()); + + accessor = p.getDeleter(); + assertTrue(accessor.isDefined()); + assertNull(accessor.value()); + } + */ + +} diff --git a/python/testSrc/com/jetbrains/python/PyDecoratedPropertyTest.java b/python/testSrc/com/jetbrains/python/PyDecoratedPropertyTest.java new file mode 100644 index 000000000000..f84887e367df --- /dev/null +++ b/python/testSrc/com/jetbrains/python/PyDecoratedPropertyTest.java @@ -0,0 +1,68 @@ +package com.jetbrains.python; + +import com.jetbrains.python.fixtures.PyTestCase; +import com.jetbrains.python.psi.*; +import com.jetbrains.python.psi.impl.PythonLanguageLevelPusher; +import com.jetbrains.python.toolbox.Maybe; + +public class PyDecoratedPropertyTest extends PyTestCase { + protected PyClass myClass; + + @Override + protected void setUp() throws Exception { + super.setUp(); + PythonLanguageLevelPusher.setForcedLanguageLevel(myFixture.getProject(), LanguageLevel.PYTHON26); + final PyFile file = (PyFile)myFixture.configureByFile("property/Decorated.py"); + myClass = file.getTopLevelClasses().get(0); + } + + public void testW1() throws Exception { + Property p; + Maybe accessor; + final String name = "w1"; + p = myClass.findProperty(name); + assertNotNull(p); + assertNull(p.getDoc()); + assertNull(p.getDefinitionSite()); + + accessor = p.getGetter(); + assertTrue(accessor.isDefined()); + assertNotNull(accessor.value()); + assertEquals(name, accessor.value().getName()); + + accessor = p.getSetter(); + assertTrue(accessor.isDefined()); + assertNotNull(accessor.value()); + assertEquals(name, accessor.value().getName()); + + accessor = p.getDeleter(); + assertTrue(accessor.isDefined()); + assertNotNull(accessor.value()); + assertEquals(name, accessor.value().getName()); + } + + public void testW2() throws Exception { + Property p; + Maybe accessor; + final String name = "w2"; + p = myClass.findProperty(name); + assertNotNull(p); + assertNull(p.getDoc()); + assertNull(p.getDefinitionSite()); + + accessor = p.getGetter(); + assertTrue(accessor.isDefined()); + assertNotNull(accessor.value()); + assertEquals("w2", accessor.value().getName()); + assertEquals("doc of "+name, accessor.value().getDocStringExpression().getStringValue()); + + accessor = p.getSetter(); + assertTrue(accessor.isDefined()); + assertNull(accessor.value()); + + accessor = p.getDeleter(); + assertTrue(accessor.isDefined()); + assertNull(accessor.value()); + } + +} diff --git a/python/testSrc/com/jetbrains/python/PyPropertyTestSuite.java b/python/testSrc/com/jetbrains/python/PyPropertyTestSuite.java deleted file mode 100644 index b1d7e5ff8b9b..000000000000 --- a/python/testSrc/com/jetbrains/python/PyPropertyTestSuite.java +++ /dev/null @@ -1,220 +0,0 @@ -package com.jetbrains.python; - -import com.intellij.openapi.project.Project; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiReference; -import com.jetbrains.python.fixtures.PyTestCase; -import com.jetbrains.python.psi.*; -import com.jetbrains.python.psi.impl.PythonLanguageLevelPusher; -import com.jetbrains.python.psi.types.PyClassType; -import com.jetbrains.python.psi.types.PyType; -import com.jetbrains.python.psi.types.TypeEvalContext; -import com.jetbrains.python.toolbox.Maybe; -import junit.framework.TestSuite; - -/** - * Tests property API. - * User: dcheryasov - * Date: Jun 30, 2010 8:09:12 AM - */ -public class PyPropertyTestSuite { - public static TestSuite suite() { - return new TestSuite(PyClassicPropertyTest.class, PyDecoratedPropertyTest.class); - } - - abstract static class PyPropertyTest extends PyTestCase { - protected PyClass myClass; - protected LanguageLevel myLanguageLevel = LanguageLevel.PYTHON26; - - abstract String getFileName(); - - @Override - protected void setUp() throws Exception { - super.setUp(); - PsiReference ref = myFixture.getReferenceAtCaretPosition("property/"+ getFileName()); - final Project project = ref.getElement().getContainingFile().getProject(); - PythonLanguageLevelPusher.setForcedLanguageLevel(project, myLanguageLevel); - PsiElement elt = ref.resolve(); - assertInstanceOf(elt, PyExpression.class); - PyType type = ((PyExpression)elt).getType(TypeEvalContext.slow()); - assertInstanceOf(type, PyClassType.class); - myClass = ((PyClassType)type).getPyClass(); - assertNotNull(myClass); - } - } - - public static class PyClassicPropertyTest extends PyPropertyTest { - - public PyClassicPropertyTest() { - super(); - } - - @Override - String getFileName() { - return "Classic.py"; - } - - public void testV1() throws Exception { - Property p; - Maybe accessor; - p = myClass.findProperty("v1"); - assertNotNull(p); - assertNull(p.getDoc()); - PyTargetExpression site = p.getDefinitionSite(); - assertEquals("v1", site.getText()); - - accessor = p.getGetter(); - assertTrue(accessor.isDefined()); - assertNotNull(accessor.value()); - assertEquals("getter", accessor.value().getName()); - - accessor = p.getSetter(); - assertTrue(accessor.isDefined()); - assertNotNull(accessor.value()); - assertEquals("setter", accessor.value().getName()); - - accessor = p.getDeleter(); - assertTrue(accessor.isDefined()); - assertNull(accessor.value()); - } - - public void testV2() throws Exception { - Property p; - Maybe accessor; - p = myClass.findProperty("v2"); - assertNotNull(p); - assertEquals("doc of v2", p.getDoc()); - PyTargetExpression site = p.getDefinitionSite(); - assertEquals("v2", site.getText()); - - accessor = p.getGetter(); - assertTrue(accessor.isDefined()); - assertNotNull(accessor.value()); - assertEquals("getter", accessor.value().getName()); - - accessor = p.getSetter(); - assertTrue(accessor.isDefined()); - assertNotNull(accessor.value()); - assertEquals("setter", accessor.value().getName()); - - accessor = p.getDeleter(); - assertTrue(accessor.isDefined()); - assertNotNull(accessor.value()); - assertEquals("deleter", accessor.value().getName()); - } - - public void testV3() throws Exception { - Property p; - Maybe accessor; - p = myClass.findProperty("v3"); - assertNotNull(p); - assertNull(p.getDoc()); - PyTargetExpression site = p.getDefinitionSite(); - assertEquals("v3", site.getText()); - - accessor = p.getGetter(); - assertFalse(accessor.isDefined()); - - accessor = p.getSetter(); - assertTrue(accessor.isDefined()); - assertNull(accessor.value()); - - accessor = p.getDeleter(); - assertTrue(accessor.isDefined()); - assertNotNull(accessor.value()); - assertEquals("deleter", accessor.value().getName()); - } - - /* NOTE: we don't support this yet - public void testV4() throws Exception { - Property p; - Maybe accessor; - p = myClass.findProperty("v4"); - assertNotNull(p); - assertEquals("otherworldly", p.getDoc()); - PyTargetExpression site = p.getDefinitionSite(); - assertEquals("otherworldly", site.getText()); - - accessor = p.getGetter(); - assertFalse(accessor.isDefined()); - - accessor = p.getSetter(); - assertTrue(accessor.isDefined()); - assertNull(accessor.value()); - - accessor = p.getDeleter(); - assertTrue(accessor.isDefined()); - assertNull(accessor.value()); - } - */ - - } - - public static class PyDecoratedPropertyTest extends PyPropertyTest { - public PyDecoratedPropertyTest() { - super(); - } - - @Override - String getFileName() { - return "Decorated.py"; - } - - @Override - protected void setUp() throws Exception { - super.setUp(); - myLanguageLevel = LanguageLevel.PYTHON26; - } - - public void testW1() throws Exception { - Property p; - Maybe accessor; - final String name = "w1"; - p = myClass.findProperty(name); - assertNotNull(p); - assertNull(p.getDoc()); - assertNull(p.getDefinitionSite()); - - accessor = p.getGetter(); - assertTrue(accessor.isDefined()); - assertNotNull(accessor.value()); - assertEquals(name, accessor.value().getName()); - - accessor = p.getSetter(); - assertTrue(accessor.isDefined()); - assertNotNull(accessor.value()); - assertEquals(name, accessor.value().getName()); - - accessor = p.getDeleter(); - assertTrue(accessor.isDefined()); - assertNotNull(accessor.value()); - assertEquals(name, accessor.value().getName()); - } - - public void testW2() throws Exception { - Property p; - Maybe accessor; - final String name = "w2"; - p = myClass.findProperty(name); - assertNotNull(p); - assertNull(p.getDoc()); - assertNull(p.getDefinitionSite()); - - accessor = p.getGetter(); - assertTrue(accessor.isDefined()); - assertNotNull(accessor.value()); - assertEquals("w2", accessor.value().getName()); - assertEquals("doc of "+name, accessor.value().getDocStringExpression().getStringValue()); - - accessor = p.getSetter(); - assertTrue(accessor.isDefined()); - assertNull(accessor.value()); - - accessor = p.getDeleter(); - assertTrue(accessor.isDefined()); - assertNull(accessor.value()); - } - - } -} - diff --git a/python/testSrc/com/jetbrains/python/PythonAllTestsSuite.java b/python/testSrc/com/jetbrains/python/PythonAllTestsSuite.java index e3316dbdb0fc..c63805d4e4c6 100644 --- a/python/testSrc/com/jetbrains/python/PythonAllTestsSuite.java +++ b/python/testSrc/com/jetbrains/python/PythonAllTestsSuite.java @@ -73,8 +73,8 @@ public class PythonAllTestsSuite { PyIntroduceConstantTest.class, PyClassNameCompletionTest.class, PySuppressInspectionsTest.class, - PyPropertyTestSuite.PyClassicPropertyTest.class, - PyPropertyTestSuite.PyDecoratedPropertyTest.class, + PyClassicPropertyTest.class, + PyDecoratedPropertyTest.class, PythonRunConfigurationTest.class, PyFoldingTest.class, EpydocStringTest.class,