int (PyExpression rightExpression, PsiElement problemTarget, boolean addSubscriptions) { PsiElement pyElement; Map<PyExpression, PyExpression> additionalExpressions; if (addSubscriptions) { additionalExpressions = addSubscriptions(rightExpression.getContainingFile(), rightExpression.getText()); final var resolveContext = PyResolveContext.defaultContext(myTypeEvalContext); pyElement = ((PyReferenceExpression)rightExpression).followAssignmentsChain(resolveContext).getElement(); } else { additionalExpressions = new HashMap<>(); pyElement = rightExpression; } if (pyElement == null) return 0; final PyKeyValueExpression[] expressions = ((PyDictLiteralExpression)pyElement).getElements(); if (myUsedMappingKeys.isEmpty()) { if (myExpectedArguments > 0) { if (myExpectedArguments > 1 && myExpectedArguments == (expressions.length + additionalExpressions.size())) { // probably "%s %s" % {'a':1, 'b':2}, with names forgotten in template registerProblem(rightExpression, PyPsiBundle.message("INSP.format.requires.no.mapping")); } else { // "braces: %s" % {'foo':1} gives "braces: {'foo':1}", implicit str() kicks in return 1; } } else { // "foo" % {whatever} is just "foo" return 0; } } int referenceKeyNumber = 0; for (PyKeyValueExpression expression : expressions) { final PyExpression key = expression.getKey(); final PyExpression value = expression.getValue(); if (key instanceof PyStringLiteralExpression) { resolveMappingKey(problemTarget, (PyStringLiteralExpression)key, value); } else if (key instanceof PyReferenceExpression) { referenceKeyNumber++; } } for (Map.Entry<PyExpression, PyExpression> expression : additionalExpressions.entrySet()) { final PyExpression key = expression.getKey(); final PyExpression value = expression.getValue(); if (key instanceof PyStringLiteralExpression) { resolveMappingKey(problemTarget, (PyStringLiteralExpression)key, value); } else if (key instanceof PyReferenceExpression) { referenceKeyNumber++; } } int unresolved = 0; for (String key : myUsedMappingKeys.keySet()) { if (!myUsedMappingKeys.get(key).booleanValue()) { unresolved++; if (unresolved > referenceKeyNumber) { registerProblem(problemTarget, PyPsiBundle.message("INSP.str.format.key.has.no.argument", key)); break; } } } return (expressions.length + additionalExpressions.size()); }