mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge branch 'python-fixes'
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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());
|
||||
|
||||
Reference in New Issue
Block a user