From 709ed7a3547acbc30e7ff2c8ae2aca2630c87905 Mon Sep 17 00:00:00 2001 From: Semyon Proshev Date: Mon, 9 Jan 2017 15:30:42 +0300 Subject: [PATCH] PY-22037 Fixed: Code completion on property that returns self declared in base class only shows options for base class Pass receiver to Property.getType --- .../src/com/jetbrains/python/psi/Property.java | 4 ++-- .../com/jetbrains/python/psi/impl/PyClassImpl.java | 6 +++--- .../python/psi/impl/PyReferenceExpressionImpl.java | 6 +++--- .../com/jetbrains/python/PyClassicPropertyTest.java | 4 ++-- python/testSrc/com/jetbrains/python/PyTypeTest.java | 13 +++++++++++++ 5 files changed, 23 insertions(+), 10 deletions(-) diff --git a/python/psi-api/src/com/jetbrains/python/psi/Property.java b/python/psi-api/src/com/jetbrains/python/psi/Property.java index 1d3084dc02ef..dcba8ecd2af2 100644 --- a/python/psi-api/src/com/jetbrains/python/psi/Property.java +++ b/python/psi-api/src/com/jetbrains/python/psi/Property.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2017 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -72,5 +72,5 @@ public interface Property { * Get the return type of the property getter. */ @Nullable - PyType getType(@NotNull TypeEvalContext context); + PyType getType(@Nullable PyExpression receiver, @NotNull TypeEvalContext context); } diff --git a/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java b/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java index 8fd6b672f542..fe1867516cfc 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2016 JetBrains s.r.o. + * Copyright 2000-2017 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -926,7 +926,7 @@ public class PyClassImpl extends PyBaseElementImpl implements PyCla @Nullable @Override - public PyType getType(@NotNull TypeEvalContext context) { + public PyType getType(@Nullable PyExpression receiver, @NotNull TypeEvalContext context) { if (mySite instanceof PyTargetExpressionImpl) { final PyType targetDocStringType = ((PyTargetExpressionImpl)mySite).getTypeFromDocString(); if (targetDocStringType != null) { @@ -939,7 +939,7 @@ public class PyClassImpl extends PyBaseElementImpl implements PyCla if (!(callable instanceof StubBasedPsiElement) && !context.maySwitchToAST(callable)) { return null; } - return context.getReturnType(callable); + return callable.getCallType(receiver, Collections.emptyMap(), context); } return null; } diff --git a/python/src/com/jetbrains/python/psi/impl/PyReferenceExpressionImpl.java b/python/src/com/jetbrains/python/psi/impl/PyReferenceExpressionImpl.java index 5915ff454435..664f08e0c56a 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyReferenceExpressionImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyReferenceExpressionImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2017 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -289,10 +289,10 @@ public class PyReferenceExpressionImpl extends PyElementImpl implements PyRefere Property property = pyClass.findProperty(name, true, context); if (property != null) { if (classType.isDefinition()) { - return Ref.create(PyBuiltinCache.getInstance(pyClass).getObjectType(PyNames.PROPERTY)); + return Ref.create(PyBuiltinCache.getInstance(pyClass).getObjectType(PyNames.PROPERTY)); } if (AccessDirection.of(this) == AccessDirection.READ) { - final PyType type = property.getType(context); + final PyType type = property.getType(getQualifier(), context); if (type != null) { return Ref.create(type); } diff --git a/python/testSrc/com/jetbrains/python/PyClassicPropertyTest.java b/python/testSrc/com/jetbrains/python/PyClassicPropertyTest.java index 4733134eee6b..7c4dd51ae6c1 100644 --- a/python/testSrc/com/jetbrains/python/PyClassicPropertyTest.java +++ b/python/testSrc/com/jetbrains/python/PyClassicPropertyTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2017 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -95,7 +95,7 @@ public class PyClassicPropertyTest extends PyTestCase { accessor = p.getGetter(); assertFalse(accessor.isDefined()); - final PyType codeInsightType = p.getType(TypeEvalContext.codeInsightFallback(myClass.getProject())); + final PyType codeInsightType = p.getType(null, TypeEvalContext.codeInsightFallback(myClass.getProject())); assertNull(codeInsightType); accessor = p.getSetter(); diff --git a/python/testSrc/com/jetbrains/python/PyTypeTest.java b/python/testSrc/com/jetbrains/python/PyTypeTest.java index fb5991ef601e..6703a7775b36 100644 --- a/python/testSrc/com/jetbrains/python/PyTypeTest.java +++ b/python/testSrc/com/jetbrains/python/PyTypeTest.java @@ -1621,6 +1621,19 @@ public class PyTypeTest extends PyTestCase { " expr = foo"); } + // PY-22037 + public void testAncestorPropertyReturnsSelf() { + doTest("Child", + "class Master(object):\n" + + " @property\n" + + " def me(self):\n" + + " return self\n" + + "class Child(Master):\n" + + " pass\n" + + "child = Child()\n" + + "expr = child.me"); + } + private static List getTypeEvalContexts(@NotNull PyExpression element) { return ImmutableList.of(TypeEvalContext.codeAnalysis(element.getProject(), element.getContainingFile()).withTracing(), TypeEvalContext.userInitiated(element.getProject(), element.getContainingFile()).withTracing());