Moved annotation-based type inference to PyTypingTypeProvider

We couldn't do check for 'typing.Any' inside PyTypingTypeProvider, so
we had to put some 'typing' knowlegde into PyFunctionImpl and
PyParameterImpl which wasn't elegant. Also we couldn't combine
type information from annotations and default arguments that was
required for Optional[T] for 'x: T = None'. Now we can implement it.
This commit is contained in:
Andrey Vlasovskikh
2015-03-31 22:25:34 +03:00
parent bf1d5b924e
commit ba7d99f478
5 changed files with 24 additions and 49 deletions
@@ -22,7 +22,7 @@ import org.jetbrains.annotations.Nullable;
/**
* @author yole
*/
public interface PyAnnotation extends PyTypedElement, StubBasedPsiElement<PyAnnotationStub> {
public interface PyAnnotation extends PyElement, StubBasedPsiElement<PyAnnotationStub> {
@Nullable
PyExpression getValue();
}
@@ -172,6 +172,10 @@ public class PyTypingTypeProvider extends PyTypeProviderBase {
if (genericType != null) {
return genericType;
}
final Ref<PyType> classType = getClassType(expression, context);
if (classType != null) {
return classType.get();
}
final PyType stringBasedType = getStringBasedType(expression, context);
if (stringBasedType != null) {
return stringBasedType;
@@ -179,6 +183,25 @@ public class PyTypingTypeProvider extends PyTypeProviderBase {
return null;
}
@Nullable
private static Ref<PyType> getClassType(@NotNull PyExpression expression, @NotNull TypeEvalContext context) {
final PyType type = context.getType(expression);
if (type != null && isAny(type)) {
return Ref.create();
}
if (type instanceof PyClassLikeType) {
final PyClassLikeType classType = (PyClassLikeType)type;
if (classType.isDefinition()) {
final PyType instanceType = classType.toInstance();
return Ref.create(instanceType);
}
}
else if (type instanceof PyNoneType) {
return Ref.create(type);
}
return null;
}
@Nullable
private static Ref<PyType> getOptionalType(@NotNull PyExpression expression, @NotNull TypeEvalContext context) {
if (expression instanceof PySubscriptionExpression) {
@@ -20,11 +20,6 @@ import com.jetbrains.python.PyElementTypes;
import com.jetbrains.python.psi.PyAnnotation;
import com.jetbrains.python.psi.PyExpression;
import com.jetbrains.python.psi.stubs.PyAnnotationStub;
import com.jetbrains.python.psi.types.PyClassLikeType;
import com.jetbrains.python.psi.types.PyNoneType;
import com.jetbrains.python.psi.types.PyType;
import com.jetbrains.python.psi.types.TypeEvalContext;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
@@ -44,23 +39,4 @@ public class PyAnnotationImpl extends PyBaseElementImpl<PyAnnotationStub> implem
public PyExpression getValue() {
return findChildByClass(PyExpression.class);
}
@Nullable
@Override
public PyType getType(@NotNull TypeEvalContext context, @NotNull TypeEvalContext.Key key) {
final PyExpression value = getValue();
if (value != null) {
final PyType type = context.getType(value);
if (type instanceof PyClassLikeType) {
final PyClassLikeType classType = (PyClassLikeType)type;
if (classType.isDefinition()) {
return classType.toInstance();
}
}
else if (type instanceof PyNoneType) {
return type;
}
}
return null;
}
}
@@ -38,7 +38,6 @@ import com.intellij.util.PlatformIcons;
import com.jetbrains.python.PyElementTypes;
import com.jetbrains.python.PyNames;
import com.jetbrains.python.PyTokenTypes;
import com.jetbrains.python.codeInsight.PyTypingTypeProvider;
import com.jetbrains.python.codeInsight.controlflow.ControlFlowCache;
import com.jetbrains.python.codeInsight.controlflow.ScopeOwner;
import com.jetbrains.python.codeInsight.dataflow.scope.ScopeUtil;
@@ -193,18 +192,6 @@ public class PyFunctionImpl extends PyBaseElementImpl<PyFunctionStub> implements
return returnType;
}
}
if (context.maySwitchToAST(this) && LanguageLevel.forElement(this).isAtLeast(LanguageLevel.PYTHON30)) {
final PyAnnotation annotation = getAnnotation();
if (annotation != null) {
final PyType type = context.getType(annotation);
if (type != null) {
if (PyTypingTypeProvider.isAny(type)) {
return null;
}
return type;
}
}
}
final PyType docStringType = getReturnTypeFromDocString();
if (docStringType != null) {
docStringType.assertValid("from docstring");
@@ -33,7 +33,6 @@ import com.jetbrains.python.PyElementTypes;
import com.jetbrains.python.PyNames;
import com.jetbrains.python.PyTokenTypes;
import com.jetbrains.python.PythonDialectsTokenSetProvider;
import com.jetbrains.python.codeInsight.PyTypingTypeProvider;
import com.jetbrains.python.codeInsight.controlflow.ScopeOwner;
import com.jetbrains.python.codeInsight.dataflow.scope.ScopeUtil;
import com.jetbrains.python.psi.*;
@@ -229,16 +228,6 @@ public class PyNamedParameterImpl extends PyBaseElementImpl<PyNamedParameterStub
return resultRef.get();
}
}
final PyAnnotation annotation = getAnnotation();
if (annotation != null) {
final PyType type = context.getType(annotation);
if (type != null) {
if (PyTypingTypeProvider.isAny(type)) {
return null;
}
return type;
}
}
if (context.maySwitchToAST(this)) {
final PyExpression defaultValue = getDefaultValue();
if (defaultValue != null) {