Get rid of unclear isBuiltin check Get elements number for tuples if callType is PyUnionType

This commit is contained in:
Valentina Kiryushkina
2017-05-16 16:15:18 +03:00
parent c8fbaa5ff1
commit 54bde659d8
3 changed files with 84 additions and 8 deletions
@@ -605,19 +605,27 @@ public class PyStringFormatInspection extends PyInspection {
.collect(
Collectors.summarizingInt(
callType -> {
if (callType instanceof PyTupleType) {
return ((PyTupleType)callType).getElementCount();
}
else if (callType instanceof PyNoneType) {
if (callType instanceof PyNoneType) {
return 1;
}
else if (callType instanceof PyClassType) {
if (PyBuiltinCache.getInstance(callExpression).isBuiltin(((PyClassType)callType).getPyClass())) {
return 1;
}
return countElements(evalContext, (PyClassType)callType);
}
else if (callType instanceof PyUnionType) {
if (((PyUnionType)callType).getMembers().stream().allMatch(PyType::isBuiltin)) return 1;
int maxNumber = 1;
boolean allForSure = true;
for (PyType member : ((PyUnionType)callType).getMembers()) {
PyClassType classType = as(member, PyClassType.class);
if (classType != null) {
int elementsCount = countElements(evalContext, classType);
allForSure = allForSure && elementsCount != -1;
maxNumber = Math.max(maxNumber, elementsCount);
}
else {
allForSure = false;
}
}
return allForSure ? maxNumber : -1;
}
return -1;
@@ -633,6 +641,16 @@ public class PyStringFormatInspection extends PyInspection {
}
}
private static int countElements(@NotNull TypeEvalContext evalContext, PyClassType callType) {
if (!callType.getPyClass().isSubclass(PyNames.TUPLE, evalContext)) {
return 1;
}
else if (callType instanceof PyTupleType) {
return ((PyTupleType)callType).getElementCount();
}
return -1;
}
public Visitor(final ProblemsHolder holder, LocalInspectionToolSession session) {
super(holder, session);
}
@@ -0,0 +1,54 @@
from collections import namedtuple
def simple_func(cond):
if cond:
return 1
else:
return 1, 2
Point = namedtuple('Point', ['x', 'y'])
def named_tuple_func(cond):
if cond:
return 1
else:
return Point(1, 1)
def primitive_types_func(cond):
if cond:
return 1
else:
return 2
def collection_func(cond):
if cond:
return [1, 2]
else:
return {1, 2}
def list_tuple(cond):
if cond:
return [1, 2]
else:
return 1, 2
"%s %s" % simple_func(True)
"%s %s" % simple_func(False)
"%s %s %s" % <warning descr="Too few arguments for format string">simple_func(False)</warning>
"%s %s" % named_tuple_func(True)
"%s %s" % named_tuple_func(False)
"%s %s %s" % named_tuple_func(False)
"%s" % primitive_types_func(True)
"%s %s" % <warning descr="Too few arguments for format string">primitive_types_func(True)</warning>
"%s %s" % <warning descr="Too few arguments for format string">primitive_types_func(False)</warning>
"%s %s %s" % <warning descr="Too few arguments for format string">primitive_types_func(False)</warning>
"%s %s" % <warning descr="Too few arguments for format string">collection_func(True)</warning>
"%s %s" % <warning descr="Too few arguments for format string">collection_func(False)</warning>
"%s %s %s" % <warning descr="Too few arguments for format string">collection_func(False)</warning>
"%s %s" % list_tuple(True)
"%s %s" % list_tuple(True)
"%s %s %s" % <warning descr="Too few arguments for format string">list_tuple(True)</warning>
@@ -208,6 +208,10 @@ public class PyStringFormatInspectionTest extends PyTestCase {
doTest();
}
public void testUnionCallType() {
doTest();
}
private void doTest() {
myFixture.configureByFile(TEST_DIRECTORY + getTestName(false) + ".py");
myFixture.enableInspections(PyStringFormatInspection.class);