@Nullable private PyType getReturnType(@NotNull TypeEvalContext context) { for (PyTypeProvider typeProvider : Extensions.getExtensions(PyTypeProvider.EP_NAME)) { final Ref<PyType> returnTypeRef = typeProvider.getReturnType(this, context); if (returnTypeRef != null) { final PyType returnType = returnTypeRef.get(); if (returnType != null) { returnType.assertValid(typeProvider.toString()); } return returnType; } } final PyType docStringType = getReturnTypeFromDocString(); if (docStringType != null) { docStringType.assertValid("from docstring"); return docStringType; } if (context.allowReturnTypes(this)) { final Ref<? extends PyType> yieldTypeRef = getYieldStatementType(context); if (yieldTypeRef != null) { return yieldTypeRef.get(); } return getReturnStatementType(context); } return null; }
@Nullable @Override public PyType getCallType( @Nullable PyExpression receiver, @NotNull Map<PyExpression, PyNamedParameter> parameters, @NotNull TypeEvalContext context) { return analyzeCallType(context.getReturnType(this), receiver, parameters, context); }
private static boolean isDynamicallyEvaluated( @NotNull Collection<PyNamedParameter> parameters, @NotNull TypeEvalContext context) { for (PyNamedParameter parameter : parameters) { final PyType type = context.getType(parameter); if (type instanceof PyDynamicallyEvaluatedType) { return true; } } return false; }
@Override public void visitPyReturnStatement(PyReturnStatement node) { if (PsiTreeUtil.getParentOfType(node, ScopeOwner.class, true) == myFunction) { final PyExpression expr = node.getExpression(); PyType returnType; returnType = expr == null ? PyNoneType.INSTANCE : myContext.getType(expr); if (!myHasReturns) { myResult = returnType; myHasReturns = true; } else { myResult = PyUnionType.union(myResult, returnType); } } }
@Nullable private PyType getReturnType(@NotNull TypeEvalContext context) { for (PyTypeProvider typeProvider : Extensions.getExtensions(PyTypeProvider.EP_NAME)) { final Ref<PyType> returnTypeRef = typeProvider.getReturnType(this, context); if (returnTypeRef != null) { return derefType(returnTypeRef, typeProvider); } } if (context.allowReturnTypes(this)) { final Ref<? extends PyType> yieldTypeRef = getYieldStatementType(context); if (yieldTypeRef != null) { return yieldTypeRef.get(); } return getReturnStatementType(context); } return null; }
@Nullable private PyType replaceSelf( @Nullable PyType returnType, @Nullable PyExpression receiver, @NotNull TypeEvalContext context) { if (receiver != null) { // TODO: Currently we substitute only simple subclass types, but we could handle union and // collection types as well if (returnType instanceof PyClassType) { final PyClassType returnClassType = (PyClassType) returnType; if (returnClassType.getPyClass() == getContainingClass()) { final PyType receiverType = context.getType(receiver); if (receiverType instanceof PyClassType && PyTypeChecker.match(returnType, receiverType, context)) { return returnClassType.isDefinition() ? receiverType : ((PyClassType) receiverType).toInstance(); } } } } return returnType; }