Merge branch 'python-fixes'

This commit is contained in:
Andrey Vlasovskikh
2013-08-14 21:50:32 +04:00
6 changed files with 68 additions and 12 deletions
@@ -1,5 +1,7 @@
package com.jetbrains.python.psi;
import com.jetbrains.python.psi.types.PyType;
import com.jetbrains.python.psi.types.TypeEvalContext;
import com.jetbrains.python.toolbox.Maybe;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -51,4 +53,9 @@ public interface Property {
@NotNull
Maybe<Callable> getByDirection(@NotNull AccessDirection direction);
/**
* Get the return type of the property getter.
*/
@Nullable
PyType getType(@NotNull TypeEvalContext context);
}
@@ -3,7 +3,6 @@ package com.jetbrains.python.psi.types;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.StubBasedPsiElement;
import com.jetbrains.python.psi.PyTypedElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -158,8 +157,8 @@ public class TypeEvalContext {
}
}
public boolean maySwitchToAST(@NotNull StubBasedPsiElement element) {
return myAllowStubToAST || (element.getStub() == null && (myOrigin == null || myOrigin == element.getContainingFile()));
public boolean maySwitchToAST(@NotNull PsiElement element) {
return myAllowStubToAST || myOrigin == element.getContainingFile();
}
@Nullable
@@ -691,6 +691,24 @@ public class PyClassImpl extends PyPresentableElementImpl<PyClassStub> implement
mySite = site;
}
@NotNull
@Override
public Maybe<Callable> getGetter() {
return filterNonStubExpression(myGetter);
}
@NotNull
@Override
public Maybe<Callable> getSetter() {
return filterNonStubExpression(mySetter);
}
@NotNull
@Override
public Maybe<Callable> getDeleter() {
return filterNonStubExpression(myDeleter);
}
public String getName() {
return myName;
}
@@ -704,15 +722,29 @@ public class PyClassImpl extends PyPresentableElementImpl<PyClassStub> implement
public Maybe<Callable> getByDirection(@NotNull AccessDirection direction) {
switch (direction) {
case READ:
return myGetter;
return getGetter();
case WRITE:
return mySetter;
return getSetter();
case DELETE:
return myDeleter;
return getDeleter();
}
throw new IllegalArgumentException("Unknown direction " + PyUtil.nvl(direction));
}
@Nullable
@Override
public PyType getType(@NotNull TypeEvalContext context) {
final Callable callable = myGetter.valueOrNull();
if (callable != null) {
// Ignore return types of non stub-based elements if we are not allowed to use AST
if (!(callable instanceof StubBasedPsiElement) && !context.maySwitchToAST(callable)) {
return null;
}
return callable.getReturnType(context, null);
}
return null;
}
@NotNull
@Override
protected Maybe<Callable> translate(@Nullable PyExpression expr) {
@@ -733,6 +765,17 @@ public class PyClassImpl extends PyPresentableElementImpl<PyClassStub> implement
return NONE;
}
@NotNull
private static Maybe<Callable> filterNonStubExpression(@NotNull Maybe<Callable> maybeCallable) {
final Callable callable = maybeCallable.valueOrNull();
if (callable != null) {
if (!(callable instanceof StubBasedPsiElement)) {
return UNKNOWN_CALL;
}
}
return maybeCallable;
}
public String toString() {
return "property(" + myGetter + ", " + mySetter + ", " + myDeleter + ", " + myDoc + ")";
}
@@ -27,7 +27,6 @@ import com.jetbrains.python.psi.impl.references.PyReferenceImpl;
import com.jetbrains.python.psi.resolve.*;
import com.jetbrains.python.psi.types.*;
import com.jetbrains.python.refactoring.PyDefUseUtil;
import com.jetbrains.python.toolbox.Maybe;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -269,10 +268,13 @@ public class PyReferenceExpressionImpl extends PyElementImpl implements PyRefere
if (classType.isDefinition()) {
return Ref.<PyType>create(PyBuiltinCache.getInstance(pyClass).getObjectType(PyNames.PROPERTY));
}
final Maybe<Callable> accessor = property.getByDirection(AccessDirection.of(this));
final Callable callable = accessor.valueOrNull();
final PyType type = (callable != null) ? callable.getReturnType(context, this) : null;
return Ref.create(type);
if (AccessDirection.of(this) == AccessDirection.READ) {
final PyType type = property.getType(context);
if (type != null) {
return Ref.create(type);
}
}
return Ref.create();
}
}
else if (qualifierType instanceof PyUnionType) {
+1 -1
View File
@@ -19,6 +19,6 @@ class A(object):
v1 = property(getter, setter)
v2 = property(fset=setter, fdel=deleter, fget=getter, doc="doc of v2")
v3 = property(lambda self: self._v, None, (deleter))
v3 = property(lambda self: 0, None, (deleter))
v4 = otherworldly # NOTE: not supported yet
v5 = property(v5getter, v5setter)
@@ -2,6 +2,8 @@ package com.jetbrains.python;
import com.jetbrains.python.fixtures.PyTestCase;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.types.PyType;
import com.jetbrains.python.psi.types.TypeEvalContext;
import com.jetbrains.python.toolbox.Maybe;
public class PyClassicPropertyTest extends PyTestCase {
@@ -78,6 +80,9 @@ public class PyClassicPropertyTest extends PyTestCase {
accessor = p.getGetter();
assertFalse(accessor.isDefined());
final PyType codeInsightType = p.getType(TypeEvalContext.codeInsightFallback());
assertNull(codeInsightType);
accessor = p.getSetter();
assertTrue(accessor.isDefined());
assertNull(accessor.value());