From bf1d5b924e8dd9a64a1176540b9e5d12c2f31602 Mon Sep 17 00:00:00 2001 From: Andrey Vlasovskikh Date: Tue, 31 Mar 2015 17:57:41 +0300 Subject: [PATCH] PyTypeProvider can return 'Any' type for parameter and return types Previously there was no way for a type provider to tell that the type is really 'Any'. The 'null' return value was just a sign that the provider doesn't know the return type and we should try other alternatives. --- .../python/psi/impl/PyJavaTypeProvider.java | 10 ++++++++-- .../jetbrains/python/psi/impl/PyTypeProvider.java | 5 +++-- .../python/psi/types/PyTypeProviderBase.java | 5 +++-- .../codeInsight/NumpyDocStringTypeProvider.java | 15 +++++++++++---- .../src/com/jetbrains/pyqt/PyQtTypeProvider.java | 9 ++++++--- .../python/codeInsight/PyTypingTypeProvider.java | 14 +++++++++----- .../PyUserSkeletonsTypeProvider.java | 15 +++++++++++---- .../debugger/PyCallSignatureTypeProvider.java | 8 ++++++-- .../jetbrains/python/psi/impl/PyFunctionImpl.java | 9 ++++++--- .../python/psi/impl/PyNamedParameterImpl.java | 7 +++++-- 10 files changed, 68 insertions(+), 29 deletions(-) diff --git a/python/pluginSrc/com/jetbrains/python/psi/impl/PyJavaTypeProvider.java b/python/pluginSrc/com/jetbrains/python/psi/impl/PyJavaTypeProvider.java index a84919ac8495..50b16502cb9a 100644 --- a/python/pluginSrc/com/jetbrains/python/psi/impl/PyJavaTypeProvider.java +++ b/python/pluginSrc/com/jetbrains/python/psi/impl/PyJavaTypeProvider.java @@ -16,6 +16,7 @@ package com.jetbrains.python.psi.impl; import com.intellij.openapi.module.ModuleUtil; +import com.intellij.openapi.util.Ref; import com.intellij.psi.*; import com.intellij.util.Processor; import com.jetbrains.python.psi.PyFunction; @@ -65,7 +66,9 @@ public class PyJavaTypeProvider extends PyTypeProviderBase { return null; } - public PyType getParameterType(@NotNull final PyNamedParameter param, @NotNull final PyFunction func, @NotNull TypeEvalContext context) { + public Ref getParameterType(@NotNull final PyNamedParameter param, + @NotNull final PyFunction func, + @NotNull TypeEvalContext context) { if (!(param.getParent() instanceof PyParameterList)) return null; List params = ParamHelper.collectNamedParameters((PyParameterList) param.getParent()); final int index = params.indexOf(param); @@ -91,7 +94,10 @@ public class PyJavaTypeProvider extends PyTypeProviderBase { } }); if (superMethodParameterTypes.size() > 0) { - return superMethodParameterTypes.get(0); + final PyType type = superMethodParameterTypes.get(0); + if (type != null) { + return Ref.create(type); + } } return null; } diff --git a/python/psi-api/src/com/jetbrains/python/psi/impl/PyTypeProvider.java b/python/psi-api/src/com/jetbrains/python/psi/impl/PyTypeProvider.java index e60a5ce19c4d..3a74030dcb17 100644 --- a/python/psi-api/src/com/jetbrains/python/psi/impl/PyTypeProvider.java +++ b/python/psi-api/src/com/jetbrains/python/psi/impl/PyTypeProvider.java @@ -16,6 +16,7 @@ package com.jetbrains.python.psi.impl; import com.intellij.openapi.extensions.ExtensionPointName; +import com.intellij.openapi.util.Ref; import com.intellij.psi.PsiElement; import com.jetbrains.python.psi.*; import com.jetbrains.python.psi.types.PyType; @@ -36,10 +37,10 @@ public interface PyTypeProvider { PyType getReferenceType(@NotNull PsiElement referenceTarget, TypeEvalContext context, @Nullable PsiElement anchor); @Nullable - PyType getParameterType(@NotNull PyNamedParameter param, @NotNull PyFunction func, @NotNull TypeEvalContext context); + Ref getParameterType(@NotNull PyNamedParameter param, @NotNull PyFunction func, @NotNull TypeEvalContext context); @Nullable - PyType getReturnType(@NotNull PyCallable callable, @NotNull TypeEvalContext context); + Ref getReturnType(@NotNull PyCallable callable, @NotNull TypeEvalContext context); @Nullable PyType getCallType(@NotNull PyFunction function, @Nullable PyCallSiteExpression callSite, @NotNull TypeEvalContext context); diff --git a/python/psi-api/src/com/jetbrains/python/psi/types/PyTypeProviderBase.java b/python/psi-api/src/com/jetbrains/python/psi/types/PyTypeProviderBase.java index 00768cdd69af..027da13ca2f7 100644 --- a/python/psi-api/src/com/jetbrains/python/psi/types/PyTypeProviderBase.java +++ b/python/psi-api/src/com/jetbrains/python/psi/types/PyTypeProviderBase.java @@ -15,6 +15,7 @@ */ package com.jetbrains.python.psi.types; +import com.intellij.openapi.util.Ref; import com.intellij.psi.PsiElement; import com.intellij.util.containers.FactoryMap; import com.jetbrains.python.psi.*; @@ -92,13 +93,13 @@ public class PyTypeProviderBase implements PyTypeProvider { } @Override - public PyType getParameterType(@NotNull PyNamedParameter param, @NotNull PyFunction func, @NotNull TypeEvalContext context) { + public Ref getParameterType(@NotNull PyNamedParameter param, @NotNull PyFunction func, @NotNull TypeEvalContext context) { return null; } @Nullable @Override - public PyType getReturnType(@NotNull PyCallable callable, @NotNull TypeEvalContext context) { + public Ref getReturnType(@NotNull PyCallable callable, @NotNull TypeEvalContext context) { return null; } diff --git a/python/src/com/jetbrains/numpy/codeInsight/NumpyDocStringTypeProvider.java b/python/src/com/jetbrains/numpy/codeInsight/NumpyDocStringTypeProvider.java index bcd87f4fcb16..0d7c73481048 100644 --- a/python/src/com/jetbrains/numpy/codeInsight/NumpyDocStringTypeProvider.java +++ b/python/src/com/jetbrains/numpy/codeInsight/NumpyDocStringTypeProvider.java @@ -16,6 +16,7 @@ package com.jetbrains.numpy.codeInsight; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.util.Ref; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; @@ -106,11 +107,14 @@ public class NumpyDocStringTypeProvider extends PyTypeProviderBase { @Nullable @Override - public PyType getParameterType(@NotNull PyNamedParameter parameter, @NotNull PyFunction function, @NotNull TypeEvalContext context) { + public Ref getParameterType(@NotNull PyNamedParameter parameter, @NotNull PyFunction function, @NotNull TypeEvalContext context) { if (isInsideNumPy(function)) { final String name = parameter.getName(); if (name != null) { - return getParameterType(function, name); + final PyType type = getParameterType(function, name); + if (type != null) { + return Ref.create(type); + } } } return null; @@ -204,9 +208,12 @@ public class NumpyDocStringTypeProvider extends PyTypeProviderBase { @Nullable @Override - public PyType getReturnType(@NotNull PyCallable callable, @NotNull TypeEvalContext context) { + public Ref getReturnType(@NotNull PyCallable callable, @NotNull TypeEvalContext context) { if (callable instanceof PyFunction) { - return getCallType((PyFunction)callable, null, context); + final PyType type = getCallType((PyFunction)callable, null, context); + if (type != null) { + return Ref.create(type); + } } return null; } diff --git a/python/src/com/jetbrains/pyqt/PyQtTypeProvider.java b/python/src/com/jetbrains/pyqt/PyQtTypeProvider.java index 3ee223aea642..e5a7ffe1bc73 100644 --- a/python/src/com/jetbrains/pyqt/PyQtTypeProvider.java +++ b/python/src/com/jetbrains/pyqt/PyQtTypeProvider.java @@ -15,6 +15,7 @@ */ package com.jetbrains.pyqt; +import com.intellij.openapi.util.Ref; import com.intellij.psi.util.QualifiedName; import com.jetbrains.python.PyNames; import com.jetbrains.python.psi.PyCallable; @@ -36,7 +37,7 @@ public class PyQtTypeProvider extends PyTypeProviderBase { private static final String ourQt4Signal = "pyqtSignal"; @Override - public PyType getReturnType(@NotNull PyCallable callable, @NotNull TypeEvalContext context) { + public Ref getReturnType(@NotNull PyCallable callable, @NotNull TypeEvalContext context) { if (PyNames.INIT.equals(callable.getName()) && callable instanceof PyFunction) { final PyFunction function = (PyFunction)callable; final PyClass containingClass = function.getContainingClass(); @@ -46,8 +47,10 @@ public class PyQtTypeProvider extends PyTypeProviderBase { final QualifiedName name = QualifiedName.fromDottedString(classQName); final String qtVersion = name.getComponents().get(0); final PyClass aClass = PyClassNameIndex.findClass(qtVersion + "." + ourQtBoundSignal, function.getProject()); - if (aClass != null) - return new PyClassTypeImpl(aClass, false); + if (aClass != null) { + final PyType type = new PyClassTypeImpl(aClass, false); + return Ref.create(type); + } } } } diff --git a/python/src/com/jetbrains/python/codeInsight/PyTypingTypeProvider.java b/python/src/com/jetbrains/python/codeInsight/PyTypingTypeProvider.java index f1db260f1ffb..8b979de2c850 100644 --- a/python/src/com/jetbrains/python/codeInsight/PyTypingTypeProvider.java +++ b/python/src/com/jetbrains/python/codeInsight/PyTypingTypeProvider.java @@ -51,13 +51,16 @@ public class PyTypingTypeProvider extends PyTypeProviderBase { .add("typing.Protocol") .build(); - public PyType getParameterType(@NotNull PyNamedParameter param, @NotNull PyFunction func, @NotNull TypeEvalContext context) { + public Ref getParameterType(@NotNull PyNamedParameter param, @NotNull PyFunction func, @NotNull TypeEvalContext context) { final PyAnnotation annotation = param.getAnnotation(); if (annotation != null) { // XXX: Requires switching from stub to AST final PyExpression value = annotation.getValue(); if (value != null) { - return getTypingType(value, context); + final PyType type = getTypingType(value, context); + if (type != null) { + return Ref.create(type); + } } } return null; @@ -65,7 +68,7 @@ public class PyTypingTypeProvider extends PyTypeProviderBase { @Nullable @Override - public PyType getReturnType(@NotNull PyCallable callable, @NotNull TypeEvalContext context) { + public Ref getReturnType(@NotNull PyCallable callable, @NotNull TypeEvalContext context) { if (callable instanceof PyFunction) { final PyFunction function = (PyFunction)callable; final PyAnnotation annotation = function.getAnnotation(); @@ -73,12 +76,13 @@ public class PyTypingTypeProvider extends PyTypeProviderBase { // XXX: Requires switching from stub to AST final PyExpression value = annotation.getValue(); if (value != null) { - return getTypingType(value, context); + final PyType type = getTypingType(value, context); + return type != null ? Ref.create(type) : null; } } final PyType constructorType = getGenericConstructorType(function, context); if (constructorType != null) { - return constructorType; + return Ref.create(constructorType); } } return null; diff --git a/python/src/com/jetbrains/python/codeInsight/userSkeletons/PyUserSkeletonsTypeProvider.java b/python/src/com/jetbrains/python/codeInsight/userSkeletons/PyUserSkeletonsTypeProvider.java index 16f7f59fcb5e..c4409f500781 100644 --- a/python/src/com/jetbrains/python/codeInsight/userSkeletons/PyUserSkeletonsTypeProvider.java +++ b/python/src/com/jetbrains/python/codeInsight/userSkeletons/PyUserSkeletonsTypeProvider.java @@ -15,6 +15,7 @@ */ package com.jetbrains.python.codeInsight.userSkeletons; +import com.intellij.openapi.util.Ref; import com.intellij.psi.PsiElement; import com.jetbrains.python.psi.PyCallable; import com.jetbrains.python.psi.PyFunction; @@ -31,14 +32,17 @@ import org.jetbrains.annotations.Nullable; */ public class PyUserSkeletonsTypeProvider extends PyTypeProviderBase { @Override - public PyType getParameterType(@NotNull PyNamedParameter param, @NotNull PyFunction func, @NotNull TypeEvalContext context) { + public Ref getParameterType(@NotNull PyNamedParameter param, @NotNull PyFunction func, @NotNull TypeEvalContext context) { final String name = param.getName(); if (name != null) { final PyFunction functionSkeleton = PyUserSkeletonsUtil.getUserSkeleton(func); if (functionSkeleton != null) { final PyNamedParameter paramSkeleton = functionSkeleton.getParameterList().findParameterByName(name); if (paramSkeleton != null) { - return context.getType(paramSkeleton); + final PyType type = context.getType(paramSkeleton); + if (type != null) { + return Ref.create(type); + } } } } @@ -47,10 +51,13 @@ public class PyUserSkeletonsTypeProvider extends PyTypeProviderBase { @Nullable @Override - public PyType getReturnType(@NotNull PyCallable callable, @NotNull TypeEvalContext context) { + public Ref getReturnType(@NotNull PyCallable callable, @NotNull TypeEvalContext context) { final PyCallable callableSkeleton = PyUserSkeletonsUtil.getUserSkeleton(callable); if (callableSkeleton != null) { - return context.getReturnType(callableSkeleton); + final PyType type = context.getReturnType(callableSkeleton); + if (type != null) { + return Ref.create(type); + } } return null; } diff --git a/python/src/com/jetbrains/python/debugger/PyCallSignatureTypeProvider.java b/python/src/com/jetbrains/python/debugger/PyCallSignatureTypeProvider.java index 32405fbfa679..57d37479c444 100644 --- a/python/src/com/jetbrains/python/debugger/PyCallSignatureTypeProvider.java +++ b/python/src/com/jetbrains/python/debugger/PyCallSignatureTypeProvider.java @@ -15,6 +15,7 @@ */ package com.jetbrains.python.debugger; +import com.intellij.openapi.util.Ref; import com.jetbrains.python.psi.PyFunction; import com.jetbrains.python.psi.PyNamedParameter; import com.jetbrains.python.psi.types.*; @@ -24,14 +25,17 @@ import org.jetbrains.annotations.NotNull; * @author traff */ public class PyCallSignatureTypeProvider extends PyTypeProviderBase { - public PyType getParameterType(@NotNull final PyNamedParameter param, @NotNull final PyFunction func, @NotNull TypeEvalContext context) { + public Ref getParameterType(@NotNull final PyNamedParameter param, + @NotNull final PyFunction func, + @NotNull TypeEvalContext context) { final String name = param.getName(); if (name != null) { final String typeName = PySignatureCacheManager.getInstance(param.getProject()).findParameterType(func, name); if (typeName != null) { final PyType type = PyTypeParser.getTypeByName(param, typeName); if (type != null) { - return PyDynamicallyEvaluatedType.create(type); + final PyType evaluatedType = PyDynamicallyEvaluatedType.create(type); + return Ref.create(evaluatedType); } } } diff --git a/python/src/com/jetbrains/python/psi/impl/PyFunctionImpl.java b/python/src/com/jetbrains/python/psi/impl/PyFunctionImpl.java index 0996e48e0407..9a2de3224e27 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyFunctionImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyFunctionImpl.java @@ -184,9 +184,12 @@ public class PyFunctionImpl extends PyBaseElementImpl implements @Override public PyType getReturnType(@NotNull TypeEvalContext context, @NotNull TypeEvalContext.Key key) { for (PyTypeProvider typeProvider : Extensions.getExtensions(PyTypeProvider.EP_NAME)) { - final PyType returnType = typeProvider.getReturnType(this, context); - if (returnType != null) { - returnType.assertValid(typeProvider.toString()); + final Ref returnTypeRef = typeProvider.getReturnType(this, context); + if (returnTypeRef != null) { + final PyType returnType = returnTypeRef.get(); + if (returnType != null) { + returnType.assertValid(typeProvider.toString()); + } return returnType; } } diff --git a/python/src/com/jetbrains/python/psi/impl/PyNamedParameterImpl.java b/python/src/com/jetbrains/python/psi/impl/PyNamedParameterImpl.java index dea043f88825..e674a372990a 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyNamedParameterImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyNamedParameterImpl.java @@ -18,6 +18,7 @@ package com.jetbrains.python.psi.impl; import com.intellij.lang.ASTNode; import com.intellij.navigation.ItemPresentation; import com.intellij.openapi.extensions.Extensions; +import com.intellij.openapi.util.Ref; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiReference; @@ -223,8 +224,10 @@ public class PyNamedParameterImpl extends PyBaseElementImpl resultRef = provider.getParameterType(this, func, context); + if (resultRef != null) { + return resultRef.get(); + } } final PyAnnotation annotation = getAnnotation(); if (annotation != null) {