Make PyTypeProvider.getCallType returns Ref<PyType> instead of PyType. Attempt to make related methods more readable

This commit is contained in:
Semyon Proshev
2016-08-10 17:00:20 +03:00
parent fa7cd10e94
commit d438a0737b
7 changed files with 162 additions and 140 deletions
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -43,7 +43,7 @@ public interface PyTypeProvider {
Ref<PyType> getReturnType(@NotNull PyCallable callable, @NotNull TypeEvalContext context);
@Nullable
PyType getCallType(@NotNull PyFunction function, @Nullable PyCallSiteExpression callSite, @NotNull TypeEvalContext context);
Ref<PyType> getCallType(@NotNull PyFunction function, @Nullable PyCallSiteExpression callSite, @NotNull TypeEvalContext context);
@Nullable
PyType getContextManagerVariableType(PyClass contextManager, PyExpression withExpression, TypeEvalContext context);
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,6 +17,7 @@ package com.jetbrains.python.psi.types;
import com.intellij.openapi.util.Ref;
import com.intellij.psi.PsiElement;
import com.intellij.util.ObjectUtils;
import com.intellij.util.containers.FactoryMap;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.impl.PyTypeProvider;
@@ -26,52 +27,18 @@ import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
/**
* @author yole
*/
public class PyTypeProviderBase implements PyTypeProvider {
public PyTypeProviderBase() {
}
protected interface ReturnTypeCallback {
@Nullable
PyType getType(@Nullable PyCallSiteExpression callSite, @Nullable PyType qualifierType, TypeEvalContext context);
}
private static class ReturnTypeDescriptor {
private final Map<String, ReturnTypeCallback> myStringToReturnTypeMap = new HashMap<>();
void put(String className, ReturnTypeCallback callback) {
myStringToReturnTypeMap.put(className, callback);
}
@Nullable
public PyType get(PyFunction function, @Nullable PyCallSiteExpression callSite, TypeEvalContext context) {
PyClass containingClass = function.getContainingClass();
if (containingClass != null) {
final ReturnTypeCallback typeCallback = myStringToReturnTypeMap.get(containingClass.getQualifiedName());
if (typeCallback != null) {
final PyExpression callee = callSite instanceof PyCallExpression ? ((PyCallExpression)callSite).getCallee() : null;
final PyExpression qualifier = callee instanceof PyQualifiedExpression ? ((PyQualifiedExpression)callee).getQualifier() : null;
PyType qualifierType = qualifier != null ? context.getType(qualifier) : null;
return typeCallback.getType(callSite, qualifierType, context);
}
}
return null;
}
}
private final ReturnTypeCallback mySelfTypeCallback = new ReturnTypeCallback() {
@Override
public PyType getType(@Nullable PyCallSiteExpression callSite, @Nullable PyType qualifierType, TypeEvalContext context) {
if (qualifierType instanceof PyClassType) {
PyClass aClass = ((PyClassType)qualifierType).getPyClass();
return PyPsiFacade.getInstance(aClass.getProject()).createClassType(aClass, false);
}
return null;
}
};
private final ReturnTypeCallback mySelfTypeCallback = (callSite, qualifierType, context) -> Optional
.ofNullable(ObjectUtils.tryCast(qualifierType, PyClassType.class))
.map(PyClassType::getPyClass)
.map(pyClass -> PyPsiFacade.getInstance(pyClass.getProject()).createClassType(pyClass, false))
.orElse(null);
@SuppressWarnings({"MismatchedQueryAndUpdateOfCollection"})
private final Map<String, ReturnTypeDescriptor> myMethodToReturnTypeMap = new FactoryMap<String, ReturnTypeDescriptor>() {
@@ -105,8 +72,8 @@ public class PyTypeProviderBase implements PyTypeProvider {
@Nullable
@Override
public PyType getCallType(@NotNull PyFunction function, @Nullable PyCallSiteExpression callSite, @NotNull TypeEvalContext context) {
ReturnTypeDescriptor descriptor;
public Ref<PyType> getCallType(@NotNull PyFunction function, @Nullable PyCallSiteExpression callSite, @NotNull TypeEvalContext context) {
final ReturnTypeDescriptor descriptor;
synchronized (myMethodToReturnTypeMap) {
descriptor = myMethodToReturnTypeMap.get(function.getName());
}
@@ -128,17 +95,50 @@ public class PyTypeProviderBase implements PyTypeProvider {
return null;
}
protected void registerSelfReturnType(String classQualifiedName, Collection<String> methods) {
protected void registerSelfReturnType(@NotNull String classQualifiedName, @NotNull Collection<String> methods) {
registerReturnType(classQualifiedName, methods, mySelfTypeCallback);
}
protected void registerReturnType(String classQualifiedName,
Collection<String> methods,
final ReturnTypeCallback callback) {
protected void registerReturnType(@NotNull String classQualifiedName,
@NotNull Collection<String> methods,
@NotNull ReturnTypeCallback callback) {
synchronized (myMethodToReturnTypeMap) {
for (String method : methods) {
myMethodToReturnTypeMap.get(method).put(classQualifiedName, callback);
}
}
}
protected interface ReturnTypeCallback {
@Nullable
PyType getType(@Nullable PyCallSiteExpression callSite, @Nullable PyType qualifierType, @NotNull TypeEvalContext context);
}
private static class ReturnTypeDescriptor {
private final Map<String, ReturnTypeCallback> myStringToReturnTypeMap = new HashMap<>();
public void put(@NotNull String classQualifiedName, @NotNull ReturnTypeCallback callback) {
myStringToReturnTypeMap.put(classQualifiedName, callback);
}
@Nullable
public Ref<PyType> get(@NotNull PyFunction function, @Nullable PyCallSiteExpression callSite, @NotNull TypeEvalContext context) {
return Optional
.ofNullable(function.getContainingClass())
.map(pyClass -> myStringToReturnTypeMap.get(pyClass.getQualifiedName()))
.map(typeCallback -> typeCallback.getType(callSite, getQualifierType(callSite, context), context))
.map(Ref::create)
.orElse(null);
}
@Nullable
private static PyType getQualifierType(@Nullable PyCallSiteExpression callSite, @NotNull TypeEvalContext context) {
final PyExpression callee = callSite instanceof PyCallExpression ? ((PyCallExpression)callSite).getCallee() : null;
final PyExpression qualifier = callee instanceof PyQualifiedExpression ? ((PyQualifiedExpression)callee).getQualifier() : null;
return qualifier != null ? context.getType(qualifier) : null;
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -205,34 +205,34 @@ public class NumpyDocStringTypeProvider extends PyTypeProviderBase {
@Nullable
@Override
public PyType getCallType(@NotNull PyFunction function, @Nullable PyCallSiteExpression callSite, @NotNull TypeEvalContext context) {
public Ref<PyType> getCallType(@NotNull PyFunction function, @Nullable PyCallSiteExpression callSite, @NotNull TypeEvalContext context) {
if (isApplicable(function)) {
final PyExpression callee = callSite instanceof PyCallExpression ? ((PyCallExpression)callSite).getCallee() : null;
final NumpyDocString docString = forFunction(function, callee);
if (docString != null) {
final List<SectionField> returns = docString.getReturnFields();
final PyPsiFacade facade = getPsiFacade(function);
switch (returns.size()) {
case 0:
return null;
case 1:
// Function returns single value
final String typeName = returns.get(0).getType();
if (StringUtil.isNotEmpty(typeName)) {
final PyType genericType = getPsiFacade(function).parseTypeAnnotation("T", function);
if (isUfuncType(function, typeName)) return genericType;
return parseNumpyDocType(function, typeName);
}
return null;
return Optional
.ofNullable(returns.get(0).getType())
.filter(StringUtil::isNotEmpty)
.map(typeName -> isUfuncType(function, typeName)
? facade.parseTypeAnnotation("T", function)
: parseNumpyDocType(function, typeName))
.map(Ref::create)
.orElse(null);
default:
// Function returns a tuple
final ArrayList<PyType> unionMembers = new ArrayList<>();
final List<PyType> unionMembers = new ArrayList<>();
final List<PyType> members = new ArrayList<>();
for (int i = 0; i < returns.size(); i++) {
SectionField ret = returns.get(i);
final String memberTypeName = ret.getType();
final String memberTypeName = returns.get(i).getType();
final PyType returnType = StringUtil.isNotEmpty(memberTypeName) ? parseNumpyDocType(function, memberTypeName) : null;
final boolean isOptional = StringUtil.isNotEmpty(memberTypeName) && memberTypeName.contains("optional");
@@ -250,13 +250,13 @@ public class NumpyDocStringTypeProvider extends PyTypeProviderBase {
unionMembers.add(facade.createTupleType(members, function));
}
}
if (unionMembers.isEmpty()) {
return facade.createTupleType(members, function);
}
return facade.createUnionType(unionMembers);
final PyType type = unionMembers.isEmpty() ? facade.createTupleType(members, function) : facade.createUnionType(unionMembers);
return Ref.create(type);
}
}
}
return null;
}
@@ -414,12 +414,9 @@ public class NumpyDocStringTypeProvider extends PyTypeProviderBase {
@Nullable
@Override
public Ref<PyType> getReturnType(@NotNull PyCallable callable, @NotNull TypeEvalContext context) {
if (callable instanceof PyFunction) {
final PyType type = getCallType((PyFunction)callable, null, context);
if (type != null) {
return Ref.create(type);
}
}
return null;
return Optional
.ofNullable(PyUtil.as(callable, PyFunction.class))
.map(function -> getCallType(function, null, context))
.orElse(null);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -158,15 +158,17 @@ public class PyTypingTypeProvider extends PyTypeProviderBase {
@Nullable
@Override
public PyType getCallType(@NotNull PyFunction function, @Nullable PyCallSiteExpression callSite, @NotNull TypeEvalContext context) {
if ("typing.cast".equals(function.getQualifiedName()) && callSite instanceof PyCallExpression) {
final PyCallExpression callExpr = (PyCallExpression)callSite;
final PyExpression[] args = callExpr.getArguments();
if (args.length > 0) {
final PyExpression typeExpr = args[0];
return getType(typeExpr, new Context(context));
}
public Ref<PyType> getCallType(@NotNull PyFunction function, @Nullable PyCallSiteExpression callSite, @NotNull TypeEvalContext context) {
if ("typing.cast".equals(function.getQualifiedName())) {
return Optional
.ofNullable(as(callSite, PyCallExpression.class))
.map(PyCallExpression::getArguments)
.filter(args -> args.length > 0)
.map(args -> getType(args[0], new Context(context)))
.map(Ref::create)
.orElse(null);
}
return null;
}
@@ -17,6 +17,7 @@ package com.jetbrains.python.codeInsight.stdlib;
import com.google.common.collect.ImmutableSet;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.psi.util.QualifiedName;
@@ -144,7 +145,16 @@ public class PyStdlibTypeProvider extends PyTypeProviderBase {
@Nullable
@Override
public PyType getCallType(@NotNull PyFunction function, @Nullable PyCallSiteExpression callSite, @NotNull TypeEvalContext context) {
public Ref<PyType> getCallType(@NotNull PyFunction function, @Nullable PyCallSiteExpression callSite, @NotNull TypeEvalContext context) {
if (callSite != null && isListGetItem(function)) {
final PyExpression receiver = PyTypeChecker.getReceiver(callSite, function);
final Map<PyExpression, PyNamedParameter> mapping = PyCallExpressionHelper.mapArguments(callSite, function, context);
final Map<PyGenericType, PyType> substitutions = PyTypeChecker.unifyGenericCall(receiver, mapping, context);
if (substitutions != null) {
return analyzeListGetItemCallType(receiver, mapping, substitutions, context);
}
}
final String qname = getQualifiedName(function, callSite);
if (qname != null) {
if (OPEN_FUNCTIONS.contains(qname) && callSite instanceof PyCallExpression) {
@@ -152,10 +162,7 @@ public class PyStdlibTypeProvider extends PyTypeProviderBase {
final PyResolveContext resolveContext = PyResolveContext.noImplicits().withTypeEvalContext(context);
final PyCallExpression.PyArgumentsMapping mapping = callExpr.mapArguments(resolveContext);
if (mapping.getMarkedCallee() != null) {
final PyType type = getOpenFunctionType(qname, mapping.getMappedParameters(), callSite);
if (type != null) {
return type;
}
return getOpenFunctionType(qname, mapping.getMappedParameters(), callSite);
}
}
else if ("__builtin__.tuple.__add__".equals(qname) && callSite instanceof PyBinaryExpression) {
@@ -164,15 +171,8 @@ public class PyStdlibTypeProvider extends PyTypeProviderBase {
else if ("__builtin__.tuple.__mul__".equals(qname) && callSite instanceof PyBinaryExpression) {
return getTupleMultiplicationResultType((PyBinaryExpression)callSite, context);
}
else if (callSite != null && isListGetItem(function)) {
final PyExpression receiver = PyTypeChecker.getReceiver(callSite, function);
final Map<PyExpression, PyNamedParameter> mapping = PyCallExpressionHelper.mapArguments(callSite, function, context);
final Map<PyGenericType, PyType> substitutions = PyTypeChecker.unifyGenericCall(receiver, mapping, context);
if (substitutions != null) {
return analyzeListGetItemCallType(receiver, mapping, substitutions, context);
}
}
}
return null;
}
@@ -186,10 +186,10 @@ public class PyStdlibTypeProvider extends PyTypeProviderBase {
}
@Nullable
private static PyType analyzeListGetItemCallType(@Nullable PyExpression receiver,
@NotNull Map<PyExpression, PyNamedParameter> parameters,
@NotNull Map<PyGenericType, PyType> substitutions,
@NotNull TypeEvalContext context) {
private static Ref<PyType> analyzeListGetItemCallType(@Nullable PyExpression receiver,
@NotNull Map<PyExpression, PyNamedParameter> parameters,
@NotNull Map<PyGenericType, PyType> substitutions,
@NotNull TypeEvalContext context) {
if (parameters.size() != 1 || substitutions.size() != 1) {
return null;
}
@@ -204,25 +204,28 @@ public class PyStdlibTypeProvider extends PyTypeProviderBase {
}
if (PyABCUtil.isSubtype(firstArgumentType, PyNames.ABC_INTEGRAL, context)) {
return substitutions.values().iterator().next();
return Ref.create(substitutions.values().iterator().next());
}
if (PyNames.SLICE.equals(firstArgumentType.getName()) && firstArgumentType.isBuiltin()) {
return Optional
.ofNullable(receiver)
.map(context::getType)
.orElseGet(() -> PyTypeChecker.substitute(PyBuiltinCache.getInstance(receiver).getListType(), substitutions, context));
return Ref.create(
Optional
.ofNullable(receiver)
.map(context::getType)
.orElseGet(() -> PyTypeChecker.substitute(PyBuiltinCache.getInstance(receiver).getListType(), substitutions, context))
);
}
return null;
}
@Nullable
private static PyType getTupleMultiplicationResultType(@NotNull PyBinaryExpression multiplication, @NotNull TypeEvalContext context) {
private static Ref<PyType> getTupleMultiplicationResultType(@NotNull PyBinaryExpression multiplication, @NotNull TypeEvalContext context) {
final PyTupleType leftTupleType = as(context.getType(multiplication.getLeftExpression()), PyTupleType.class);
if (leftTupleType == null) {
return null;
}
PyExpression rightExpression = multiplication.getRightExpression();
if (rightExpression instanceof PyReferenceExpression) {
final PsiElement target = ((PyReferenceExpression)rightExpression).getReference().resolve();
@@ -230,10 +233,12 @@ public class PyStdlibTypeProvider extends PyTypeProviderBase {
rightExpression = ((PyTargetExpression)target).findAssignedValue();
}
}
if (rightExpression instanceof PyNumericLiteralExpression && ((PyNumericLiteralExpression)rightExpression).isIntegerLiteral()) {
if (leftTupleType.isHomogeneous()) {
return leftTupleType;
return Ref.create(leftTupleType);
}
final int multiplier = ((PyNumericLiteralExpression)rightExpression).getBigIntegerValue().intValue();
final int originalSize = leftTupleType.getElementCount();
// Heuristic
@@ -244,17 +249,19 @@ public class PyStdlibTypeProvider extends PyTypeProviderBase {
elementTypes[i * originalSize + j] = leftTupleType.getElementType(j);
}
}
return PyTupleType.create(multiplication, elementTypes);
return Ref.create(PyTupleType.create(multiplication, elementTypes));
}
}
return null;
}
@Nullable
private static PyType getTupleConcatenationResultType(@NotNull PyBinaryExpression addition, @NotNull TypeEvalContext context) {
final PyTupleType leftTupleType = as(context.getType(addition.getLeftExpression()), PyTupleType.class);
private static Ref<PyType> getTupleConcatenationResultType(@NotNull PyBinaryExpression addition, @NotNull TypeEvalContext context) {
if (addition.getRightExpression() != null) {
final PyTupleType leftTupleType = as(context.getType(addition.getLeftExpression()), PyTupleType.class);
final PyTupleType rightTupleType = as(context.getType(addition.getRightExpression()), PyTupleType.class);
if (leftTupleType != null && rightTupleType != null) {
if (leftTupleType.isHomogeneous() || rightTupleType.isHomogeneous()) {
// We may try to find the common type of elements of two homogeneous tuple as an alternative
@@ -268,9 +275,11 @@ public class PyStdlibTypeProvider extends PyTypeProviderBase {
for (int i = 0; i < rightTupleType.getElementCount(); i++) {
elementTypes[i + leftTupleType.getElementCount()] = rightTupleType.getElementType(i);
}
return PyTupleType.create(addition, elementTypes);
return Ref.create(PyTupleType.create(addition, elementTypes));
}
}
return null;
}
@@ -310,10 +319,10 @@ public class PyStdlibTypeProvider extends PyTypeProviderBase {
return null;
}
@Nullable
private static PyType getOpenFunctionType(@NotNull String callQName,
@NotNull Map<PyExpression, PyNamedParameter> arguments,
@NotNull PsiElement anchor) {
@NotNull
private static Ref<PyType> getOpenFunctionType(@NotNull String callQName,
@NotNull Map<PyExpression, PyNamedParameter> arguments,
@NotNull PsiElement anchor) {
String mode = "r";
for (Map.Entry<PyExpression, PyNamedParameter> entry : arguments.entrySet()) {
final PyNamedParameter parameter = entry.getValue();
@@ -328,17 +337,17 @@ public class PyStdlibTypeProvider extends PyTypeProviderBase {
}
}
}
final LanguageLevel level = LanguageLevel.forElement(anchor);
if (level.isPy3K() || "io.open".equals(callQName)) {
if (LanguageLevel.forElement(anchor).isAtLeast(LanguageLevel.PYTHON30) || "io.open".equals(callQName)) {
if (mode.contains("b")) {
return PyTypeParser.getTypeByName(anchor, PY3K_BINARY_FILE_TYPE);
} else {
return PyTypeParser.getTypeByName(anchor, PY3K_TEXT_FILE_TYPE);
return Ref.create(PyTypeParser.getTypeByName(anchor, PY3K_BINARY_FILE_TYPE));
}
else {
return Ref.create(PyTypeParser.getTypeByName(anchor, PY3K_TEXT_FILE_TYPE));
}
}
return PyTypeParser.getTypeByName(anchor, PY2K_FILE_TYPE);
return Ref.create(PyTypeParser.getTypeByName(anchor, PY2K_FILE_TYPE));
}
@Nullable
@@ -194,13 +194,10 @@ public class PyFunctionImpl extends PyBaseElementImpl<PyFunctionStub> implements
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;
return derefType(returnTypeRef, typeProvider);
}
}
if (context.allowReturnTypes(this)) {
final Ref<? extends PyType> yieldTypeRef = getYieldStatementType(context);
if (yieldTypeRef != null) {
@@ -208,6 +205,7 @@ public class PyFunctionImpl extends PyBaseElementImpl<PyFunctionStub> implements
}
return getReturnStatementType(context);
}
return null;
}
@@ -215,17 +213,26 @@ public class PyFunctionImpl extends PyBaseElementImpl<PyFunctionStub> implements
@Override
public PyType getCallType(@NotNull TypeEvalContext context, @NotNull PyCallSiteExpression callSite) {
for (PyTypeProvider typeProvider : Extensions.getExtensions(PyTypeProvider.EP_NAME)) {
final PyType type = typeProvider.getCallType(this, callSite, context);
if (type != null) {
type.assertValid(typeProvider.toString());
return type;
final Ref<PyType> typeRef = typeProvider.getCallType(this, callSite, context);
if (typeRef != null) {
return derefType(typeRef, typeProvider);
}
}
final PyExpression receiver = PyTypeChecker.getReceiver(callSite, this);
final Map<PyExpression, PyNamedParameter> mapping = PyCallExpressionHelper.mapArguments(callSite, this, context);
return getCallType(receiver, mapping, context);
}
@Nullable
private static PyType derefType(@NotNull Ref<PyType> typeRef, @NotNull PyTypeProvider typeProvider) {
final PyType type = typeRef.get();
if (type != null) {
type.assertValid(typeProvider.toString());
}
return type;
}
@Nullable
@Override
public PyType getCallType(@Nullable PyExpression receiver,
@@ -91,42 +91,49 @@ public class PyiTypeProvider extends PyTypeProviderBase {
@Nullable
@Override
public PyType getCallType(@NotNull PyFunction function, @Nullable PyCallSiteExpression callSite, @NotNull TypeEvalContext context) {
public Ref<PyType> getCallType(@NotNull PyFunction function, @Nullable PyCallSiteExpression callSite, @NotNull TypeEvalContext context) {
if (callSite != null) {
final PsiElement pythonStub = PyiUtil.getPythonStub(function);
if (pythonStub instanceof PyFunction) {
final PyFunction functionStub = (PyFunction)pythonStub;
return getOverloadedCallType(functionStub, callSite, context);
return getOverloadedCallType((PyFunction)pythonStub, callSite, context);
}
else if (function.getContainingFile() instanceof PyiFile) {
return getOverloadedCallType(function, callSite, context);
}
}
return null;
}
@Nullable
private static PyType getOverloadedCallType(@NotNull PyFunction function, @NotNull PyCallSiteExpression callSite,
@NotNull TypeEvalContext context) {
private static Ref<PyType> getOverloadedCallType(@NotNull PyFunction function,
@NotNull PyCallSiteExpression callSite,
@NotNull TypeEvalContext context) {
if (isOverload(function, context)) {
final List<PyType> matchedReturnTypes = new ArrayList<>();
final List<PyType> allReturnTypes = new ArrayList<>();
final List<PyFunction> overloads = getOverloads(function, context);
final List<PyType> allReturnTypes = new ArrayList<>();
final List<PyType> matchedReturnTypes = new ArrayList<>();
for (PyFunction overload : overloads) {
final Map<PyExpression, PyNamedParameter> mapping = mapArguments(callSite, overload, context);
final PyExpression receiver = PyTypeChecker.getReceiver(callSite, overload);
final Map<PyGenericType, PyType> substitutions = PyTypeChecker.unifyGenericCall(receiver, mapping, context);
final PyType returnType = context.getReturnType(overload);
if (!PyTypeChecker.hasGenerics(returnType, context)) {
allReturnTypes.add(returnType);
}
final PyExpression receiver = PyTypeChecker.getReceiver(callSite, overload);
final Map<PyExpression, PyNamedParameter> mapping = mapArguments(callSite, overload, context);
final Map<PyGenericType, PyType> substitutions = PyTypeChecker.unifyGenericCall(receiver, mapping, context);
final PyType unifiedType = substitutions != null ? PyTypeChecker.substitute(returnType, substitutions, context) : null;
if (unifiedType != null) {
matchedReturnTypes.add(unifiedType);
}
}
return PyUnionType.union(matchedReturnTypes.isEmpty() ? allReturnTypes : matchedReturnTypes);
return Ref.create(PyUnionType.union(matchedReturnTypes.isEmpty() ? allReturnTypes : matchedReturnTypes));
}
return null;
}