PY-22769 Fixed: Wrong inspection "Expected type 'bytes', got 'str' instead" for replacement function of os.path.abspath object

PY-22512 Fixed: False positive: expected Optional[bytes] got str for os.path.realpath(...).rstrip('_')
PY-22475 Fixed: Switch multi-parameters handling to multi-resolved functions API

Use PyCallExpression.multiResolveRatedCalleeFunction in PyTypeChecker and drop PyUtil.getOverloadedParametersSet
This commit is contained in:
Semyon Proshev
2017-03-06 19:43:42 +03:00
committed by Semyon Proshev
parent 96dd05d4d0
commit 77ee34ea5c
5 changed files with 23 additions and 77 deletions
@@ -181,7 +181,7 @@ public class PyTypeCheckerInspection extends PyInspection {
}
}
private void checkCallSite(@Nullable PyCallSiteExpression callSite) {
private void checkCallSite(@NotNull PyCallSiteExpression callSite) {
final List<PyTypeChecker.AnalyzeCallResults> resultsSet = PyTypeChecker.analyzeCallSite(callSite, myTypeEvalContext);
final List<Map<PyExpression, Pair<String, ProblemHighlightType>>> problemsSet =
new ArrayList<>();
@@ -1522,64 +1522,6 @@ public class PyUtil {
return element;
}
@NotNull
public static List<List<PyParameter>> getOverloadedParametersSet(@NotNull PyCallable callable, @NotNull TypeEvalContext context) {
final List<List<PyParameter>> parametersSet = getOverloadedParametersSet(context.getType(callable), context);
return parametersSet != null ? parametersSet : Collections.singletonList(Arrays.asList(callable.getParameterList().getParameters()));
}
@Nullable
private static List<PyParameter> getParametersOfCallableType(@NotNull PyCallableType type, @NotNull TypeEvalContext context) {
final List<PyCallableParameter> callableTypeParameters = type.getParameters(context);
if (callableTypeParameters != null) {
boolean allParametersDefined = true;
final List<PyParameter> parameters = new ArrayList<>();
for (PyCallableParameter callableParameter : callableTypeParameters) {
final PyParameter parameter = callableParameter.getParameter();
if (parameter == null) {
allParametersDefined = false;
break;
}
parameters.add(parameter);
}
if (allParametersDefined) {
return parameters;
}
}
return null;
}
@Nullable
private static List<List<PyParameter>> getOverloadedParametersSet(@Nullable PyType type, @NotNull TypeEvalContext context) {
if (type instanceof PyUnionType) {
type = ((PyUnionType)type).excludeNull(context);
}
if (type instanceof PyCallableType) {
final List<PyParameter> results = getParametersOfCallableType((PyCallableType)type, context);
if (results != null) {
return Collections.singletonList(results);
}
}
else if (type instanceof PyUnionType) {
final List<List<PyParameter>> results = new ArrayList<>();
final Collection<PyType> members = ((PyUnionType)type).getMembers();
for (PyType member : members) {
if (member instanceof PyCallableType) {
final List<PyParameter> parameters = getParametersOfCallableType((PyCallableType)member, context);
if (parameters != null) {
results.add(parameters);
}
}
}
if (!results.isEmpty()) {
return results;
}
}
return null;
}
@NotNull
public static List<PyParameter> getParameters(@NotNull PyCallable callable, @NotNull TypeEvalContext context) {
return Optional
@@ -615,28 +615,22 @@ public class PyTypeChecker {
}
@NotNull
public static List<AnalyzeCallResults> analyzeCallSite(@Nullable PyCallSiteExpression callSite, @NotNull TypeEvalContext context) {
if (callSite != null) {
final List<AnalyzeCallResults> results = new ArrayList<>();
for (PyCallable callable : resolveCallee(callSite, context)) {
final PyExpression receiver = getReceiver(callSite, callable);
for (List<PyParameter> parameters : PyUtil.getOverloadedParametersSet(callable, context)) {
final Map<PyExpression, PyNamedParameter> mapping = PyCallExpressionHelper.mapArguments(callSite, callable, parameters, context);
results.add(new AnalyzeCallResults(callable, receiver, mapping));
}
}
return results;
public static List<AnalyzeCallResults> analyzeCallSite(@NotNull PyCallSiteExpression callSite, @NotNull TypeEvalContext context) {
final List<AnalyzeCallResults> results = new ArrayList<>();
for (PyCallable callable : multiResolveCallee(callSite, context)) {
final PyExpression receiver = getReceiver(callSite, callable);
final Map<PyExpression, PyNamedParameter> mapping = PyCallExpressionHelper.mapArguments(callSite, callable, context);
results.add(new AnalyzeCallResults(callable, receiver, mapping));
}
return Collections.emptyList();
return results;
}
@NotNull
private static List<PyCallable> resolveCallee(@NotNull PyCallSiteExpression callSite, @NotNull TypeEvalContext context) {
private static List<PyCallable> multiResolveCallee(@NotNull PyCallSiteExpression callSite, @NotNull TypeEvalContext context) {
final PyResolveContext resolveContext = PyResolveContext.noImplicits().withTypeEvalContext(context);
if (callSite instanceof PyCallExpression) {
final PyCallExpression callExpr = (PyCallExpression)callSite;
final PyCallExpression.PyMarkedCallee callee = callExpr.resolveCallee(resolveContext);
return callee != null ? Collections.singletonList(callee.getCallable()) : Collections.emptyList();
final List<PyCallExpression.PyRatedCallee> ratedCallees = ((PyCallExpression)callSite).multiResolveRatedCalleeFunction(resolveContext);
return ContainerUtil.map(PyUtil.filterTopPriorityResults(ratedCallees), PyCallExpression.PyRatedCallee::getElement);
}
else if (callSite instanceof PySubscriptionExpression || callSite instanceof PyBinaryExpression) {
final List<PyCallable> results = new ArrayList<>();
@@ -0,0 +1,5 @@
from typing import Union
def foo(path: Union[bytes, str]) -> None:
path.replace("/", "\\")
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
* Copyright 2000-2017 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.
@@ -198,7 +198,7 @@ public class Py3TypeCheckerInspectionTest extends PyTestCase {
public void testBuiltinInputPy3() {
doTest();
}
// PY-200057
public void testClassObjectType() {
doTest();
@@ -218,4 +218,9 @@ public class Py3TypeCheckerInspectionTest extends PyTestCase {
public void testOptionalOfBoundTypeVarInWarnings() {
doTest();
}
// PY-22769
public void testReplaceCalledOnUnionOfStrAndBytesWithStrArguments() {
doTest();
}
}