From 91f27172ee443abe77dc0e0305bdf1bd421fa6e6 Mon Sep 17 00:00:00 2001 From: Valentina Kiryushkina Date: Tue, 31 May 2016 15:23:41 +0300 Subject: [PATCH] Refactor and cleanup --- .../inspections/PyStringFormatInspection.java | 333 ++++++++++-------- .../inspections/PyStringFormatParser.java | 31 +- ...StyleMappingKeyWithSubscriptionFuncArgs.py | 2 +- .../com/jetbrains/python/PyResolveTest.java | 8 +- .../python/PyStringFormatParserTest.java | 8 +- 5 files changed, 210 insertions(+), 172 deletions(-) diff --git a/python/src/com/jetbrains/python/inspections/PyStringFormatInspection.java b/python/src/com/jetbrains/python/inspections/PyStringFormatInspection.java index 2bd240b3c804..a2be27d5ef7c 100644 --- a/python/src/com/jetbrains/python/inspections/PyStringFormatInspection.java +++ b/python/src/com/jetbrains/python/inspections/PyStringFormatInspection.java @@ -67,8 +67,6 @@ public class PyStringFormatInspection extends PyInspection { public static class Visitor extends PyInspectionVisitor { private static class Inspection { - private static final List CHECKED_TYPES = Arrays.asList("str", "int", "long", "float", "complex", "None"); - private static final List NUMERIC_TYPES = Arrays.asList("int", "long", "float", "complex"); private static final ImmutableMap PERCENT_FORMAT_CONVERSIONS = ImmutableMap.builder() .put('d', "int or long or float") .put('i', "int or long or float") @@ -258,37 +256,6 @@ public class PyStringFormatInspection extends PyInspection { return -1; } - private int inspectCallExpression(@NotNull PyCallExpression callExpression, @NotNull PyResolveContext resolveContext) { - final PyReturnStatement[] returnStatements = getFunctionReturnValues(callExpression, resolveContext); - int expressionsSize = -1; - for (PyReturnStatement returnStatement : returnStatements) { - if (returnStatement.getExpression() instanceof PyCallExpression) { - return -1; - } - final int argumentsSize = Math.max(PyUtil.flattenedParensAndTuples(returnStatement.getExpression()).size(), - PyUtil.flattenedParensAndLists(returnStatement.getExpression()).size()); - if (expressionsSize < 0) { - expressionsSize = argumentsSize; - } - if (expressionsSize != argumentsSize) { - return -1; - } - } - return expressionsSize; - } - - - private PyReturnStatement[] getFunctionReturnValues(@NotNull PyCallExpression callExpression, - @NotNull PyResolveContext resolveContext) { - final PyCallable callable = callExpression.resolveCalleeFunction(resolveContext); - if (callable instanceof PyFunction && myTypeEvalContext.maySwitchToAST(callable)) { - PyStatementList statementList = ((PyFunction)callable).getStatementList(); - return PyUtil.getAllChildrenOfType(statementList, PyReturnStatement.class); - } - return new PyReturnStatement[0]; - } - - private static Map addSubscriptions(PsiFile file, String operand) { Map additionalExpressions = new HashMap(); PySubscriptionExpression[] subscriptionExpressions = PyUtil.getAllChildrenOfType(file, PySubscriptionExpression.class); @@ -464,41 +431,199 @@ public class PyStringFormatInspection extends PyInspection { } } - private void inspectNewStyleValues(@NotNull final PyStringLiteralExpression formatExpression) { - final String value = formatExpression.getStringValue(); + + private static boolean isBytesLiteral(@NotNull PyStringLiteralExpression expr, @NotNull TypeEvalContext context) { + final PyBuiltinCache builtinCache = PyBuiltinCache.getInstance(expr); + final PyClassType bytesType = builtinCache.getBytesType(LanguageLevel.forElement(expr)); + final PyType actualType = context.getType(expr); + return bytesType != null && actualType != null && PyTypeChecker.match(bytesType, actualType, context); + } + + private void inspectWidth(@NotNull final PyStringLiteralExpression formatExpression, String width) { + if ("*".equals(width)) { + ++myExpectedArguments; + if (myUsedMappingKeys.size() > 0) { + registerProblem(formatExpression, "Can't use \'*\' in formats when using a mapping"); + } + } + } + + public boolean isProblem() { + return myProblemRegister; + } + + private void inspectValues(@Nullable final PyExpression rightExpression) { + if (rightExpression == null) { + return; + } + if (rightExpression instanceof PyParenthesizedExpression) { + inspectValues(((PyParenthesizedExpression)rightExpression).getContainedExpression()); + } + else { + final PyClassType type = as(myTypeEvalContext.getType(rightExpression), PyClassType.class); + if (type != null) { + if (myUsedMappingKeys.size() > 0 && !PyABCUtil.isSubclass(type.getPyClass(), PyNames.MAPPING, null)) { + registerProblem(rightExpression, PyBundle.message("INSP.format.requires.mapping")); + return; + } + } + inspectArgumentsNumber(rightExpression); + } + } + + private void inspectArgumentsNumber(@NotNull final PyExpression rightExpression) { + final int arguments = inspectArguments(rightExpression, rightExpression); + if (myUsedMappingKeys.isEmpty() && arguments >= 0) { + if (myExpectedArguments < arguments) { + registerProblem(rightExpression, PyBundle.message("INSP.too.many.args.for.fmt.string")); + } + else if (myExpectedArguments > arguments) { + registerProblem(rightExpression, PyBundle.message("INSP.too.few.args.for.fmt.string")); + } + } + } + } + + private static class NewStyleInspection { + private static final List CHECKED_TYPES = Arrays.asList("str", "int", "long", "float", "complex", "None"); + private static final List NUMERIC_TYPES = Arrays.asList("int", "long", "float", "complex"); + private static final ImmutableMap NEW_STYLE_FORMAT_CONVERSIONS = ImmutableMap.builder() + .put('s', "str or None") + .put('b', "int") + .put('c', "int") + .put('d', "int") + .put('o', "int") + .put('x', "int") + .put('X', "int") + .put('n', "int or long or float or complex") + .put('e', "long or float or complex") + .put('E', "long or float or complex") + .put('f', "long or float or complex") + .put('F', "long or float or complex") + .put('g', "long or float or complex") + .put('G', "long or float or complex") + .put('%', "long or float") + .build(); + + private final PyStringLiteralExpression myFormatExpression; + private boolean myProblemRegister = false; + private final Visitor myVisitor; + private final TypeEvalContext myTypeEvalContext; + + private final Map myFormatSpec = new HashMap(); + + public NewStyleInspection(PyStringLiteralExpression formatExpression, Visitor visitor, TypeEvalContext context) { + myFormatExpression = formatExpression; + myVisitor = visitor; + myTypeEvalContext = context; + } + + public void inspect() { + final String value = myFormatExpression.getStringValue(); final List chunks = filterSubstitutions(PyStringFormatParser.parseNewStyleFormat(value)); - myExpectedArguments = chunks.size(); for (int i = 0; i < chunks.size(); i++) { final PyStringFormatParser.NewStyleSubstitutionChunk chunk = as(chunks.get(i), PyStringFormatParser.NewStyleSubstitutionChunk.class); if (chunk != null) { - String mappingKey = inspectNewStyleChunk(formatExpression, i, chunk); - inspectArgumentsForNewStyleChunk(i, chunk, mappingKey, formatExpression); + chunk.setPosition(i); + String mappingKey = inspectNewStyleChunkAndGetMappingKey(chunk); + if (!isProblem()) { + inspectArguments(chunk, mappingKey); + } } } } - private void inspectArgumentsForNewStyleChunk(int i, - @NotNull PyStringFormatParser.NewStyleSubstitutionChunk chunk, - @NotNull String mappingKey, - @NotNull PyStringLiteralExpression formatExpression) { - final PsiElement target = new PySubstitutionChunkReference(formatExpression, chunk, i).resolve(); + private String inspectNewStyleChunkAndGetMappingKey(@NotNull PyStringFormatParser.NewStyleSubstitutionChunk chunk) { + final HashSet types = new HashSet<>(); + boolean hasTypeOptions = false; + + final String mappingKey = chunk.getMappingKey() != null ? chunk.getMappingKey() : String.valueOf(chunk.getPosition()); + + // inspect options available only for numeric types + if (chunk.hasSignOption() || chunk.useAlternateForm() || chunk.hasZeroPadding() || chunk.hasThousandsSeparator()) { + addTypes(types, NUMERIC_TYPES); + hasTypeOptions = true; + } + + if (chunk.getPrecision() != null) { + // TODO: actually availableTypes doesn't reject int, because int is compatible with float and complex + final List availableTypes = Arrays.asList("str", "float", "complex"); + addTypes(types, availableTypes); + hasTypeOptions = true; + } + + final char conversionType = chunk.getConversionType(); + if (NEW_STYLE_FORMAT_CONVERSIONS.containsKey(conversionType)) { + final String[] s = NEW_STYLE_FORMAT_CONVERSIONS.get(conversionType).split(" or "); + addTypes(types, Arrays.asList(s)); + hasTypeOptions = true; + } + + if (!types.isEmpty()) { + myFormatSpec.put(mappingKey, StringUtil.join(types, " or ")); + } + else if (hasTypeOptions) { + registerProblem(myFormatExpression, PyBundle.message("INSP.incompatible.options", mappingKey)); + } + return mappingKey; + } + + private void inspectArguments(@NotNull PyStringFormatParser.NewStyleSubstitutionChunk chunk, @NotNull String mappingKey) { + // it's true because we set position manually in inspect() + assert chunk.getPosition() != null; + final PsiElement target = new PySubstitutionChunkReference(myFormatExpression, chunk, chunk.getPosition()).resolve(); if (target == null) { final String chunkMapping = chunk.getMappingKey(); - registerProblem(formatExpression, chunkMapping == null ? PyBundle.message("INSP.too.few.keys") : - PyBundle.message("INSP.unused.mapping", chunkMapping)); + registerProblem(myFormatExpression, chunkMapping == null ? PyBundle.message("INSP.too.few.keys") : + PyBundle.message("INSP.unused.mapping", chunkMapping)); } else { if (chunk.getMappingKeyElementIndex() != null) { - inspectIndexElements(chunk, formatExpression, target, target, mappingKey); + inspectIndexElements(chunk, myFormatExpression, target, target, mappingKey); } - checkTypesCompatibleForCheckedTypesOnly(mappingKey, formatExpression, target); + checkTypesCompatibleForCheckedTypesOnly(myFormatExpression, target, mappingKey); } } + private int inspectCallExpression(@NotNull PyCallExpression callExpression, @NotNull PyResolveContext resolveContext) { + final PyReturnStatement[] returnStatements = getFunctionReturnValues(callExpression, resolveContext); + int expressionsSize = -1; + for (PyReturnStatement returnStatement : returnStatements) { + if (returnStatement.getExpression() instanceof PyCallExpression) { + return -1; + } + final int argumentsSize = Math.max(PyUtil.flattenedParensAndTuples(returnStatement.getExpression()).size(), + PyUtil.flattenedParensAndLists(returnStatement.getExpression()).size()); + if (expressionsSize < 0) { + expressionsSize = argumentsSize; + } + if (expressionsSize != argumentsSize) { + return -1; + } + } + return expressionsSize; + } + + + private PyReturnStatement[] getFunctionReturnValues(@NotNull PyCallExpression callExpression, + @NotNull PyResolveContext resolveContext) { + final PyCallable callable = callExpression.resolveCalleeFunction(resolveContext); + if (callable instanceof PyFunction && myTypeEvalContext.maySwitchToAST(callable)) { + PyStatementList statementList = ((PyFunction)callable).getStatementList(); + return PyUtil.getAllChildrenOfType(statementList, PyReturnStatement.class); + } + return new PyReturnStatement[0]; + } + + private void registerProblem(@NotNull PsiElement problemTarget, @NotNull final String message) { + myProblemRegister = true; + myVisitor.registerProblem(problemTarget, message); + } + private void inspectIndexElements(@NotNull PyStringFormatParser.NewStyleSubstitutionChunk chunk, @NotNull PyStringLiteralExpression formatExpression, @NotNull final PsiElement problemElement, @@ -506,6 +631,7 @@ public class PyStringFormatInspection extends PyInspection { @NotNull String mappingKey) { final String indexElement = chunk.getMappingKeyElementIndex(); final PyResolveContext resolveContext = PyResolveContext.noImplicits().withTypeEvalContext(myTypeEvalContext); + if (indexElement != null) { try { final Integer index = Integer.valueOf(indexElement); @@ -525,7 +651,7 @@ public class PyStringFormatInspection extends PyInspection { registerProblem(problemElement, PyBundle.message("INSP.too.few.args.for.fmt.string")); } else { - checkTypesCompatibleForCheckedTypesOnly(indexElement, formatExpression, elements[index]); + checkTypesCompatibleForCheckedTypesOnly(formatExpression, elements[index], indexElement); } } else if (inspectedElement instanceof PyReferenceExpression) { @@ -534,10 +660,7 @@ public class PyStringFormatInspection extends PyInspection { } else if (inspectedElement instanceof PyCallExpression) { final int callResultsArgumentsNumber = inspectCallExpression((PyCallExpression)inspectedElement, resolveContext); - if (index < callResultsArgumentsNumber) { - checkTypesCompatibleForCheckedTypesOnly(mappingKey, formatExpression, inspectedElement); - } - else { + if (callResultsArgumentsNumber <= index) { registerProblem(inspectedElement, PyBundle.message("INSP.too.few.args.for.fmt.string")); } } @@ -561,7 +684,7 @@ public class PyStringFormatInspection extends PyInspection { final PyExpression[] arguments = ((PyCallExpression)valueExpression).getArguments(); for (PyExpression argument : arguments) { if (argument instanceof PyKeywordArgument && indexElement.equals(((PyKeywordArgument)argument).getKeyword())) { - checkTypesCompatibleForCheckedTypesOnly(mappingKey, formatExpression, argument); + checkTypesCompatibleForCheckedTypesOnly(formatExpression, argument, mappingKey); return; } } @@ -626,7 +749,7 @@ public class PyStringFormatInspection extends PyInspection { for (PyKeyValueExpression element : elements) { final PyExpression key = element.getKey(); if (key instanceof PyNumericLiteralExpression && new Long(index).equals(((PyNumericLiteralExpression)key).getLongValue())) { - checkTypesCompatibleForCheckedTypesOnly(mappingKey, formatExpression, key); + checkTypesCompatibleForCheckedTypesOnly(formatExpression, key, mappingKey); return; } } @@ -644,7 +767,7 @@ public class PyStringFormatInspection extends PyInspection { for (PyKeyValueExpression element : elements) { final PyExpression key = element.getKey(); if (key instanceof PyStringLiteralExpression && indexElement.equals(((PyStringLiteralExpression)key).getStringValue())) { - checkTypesCompatibleForCheckedTypesOnly(mappingKey, formatExpression, key); + checkTypesCompatibleForCheckedTypesOnly(formatExpression, key, mappingKey); return; } } @@ -658,16 +781,16 @@ public class PyStringFormatInspection extends PyInspection { @NotNull final PsiElement target) { final PyExpression[] elements = ((PyListLiteralExpression)target).getElements(); if (elements.length > index) { - checkTypesCompatibleForCheckedTypesOnly(String.valueOf(index), formatExpression, elements[index]); + checkTypesCompatibleForCheckedTypesOnly(formatExpression, elements[index], String.valueOf(index)); } else { registerProblem(problemElement, PyBundle.message("INSP.too.few.args.for.fmt.string")); } } - private void checkTypesCompatibleForCheckedTypesOnly(@NotNull String mappingKey, - @NotNull PyStringLiteralExpression anchor, - @NotNull PsiElement target) { + private void checkTypesCompatibleForCheckedTypesOnly(@NotNull PyStringLiteralExpression anchor, + @NotNull PsiElement target, + @NotNull String mappingKey) { final PyTypedElement typedElement = as(target, PyTypedElement.class); if (typedElement != null && myFormatSpec.containsKey(mappingKey)) { final PyType actual = myTypeEvalContext.getType(typedElement); @@ -680,47 +803,6 @@ public class PyStringFormatInspection extends PyInspection { } } - private String inspectNewStyleChunk(@NotNull PyStringLiteralExpression formatExpression, - int i, - PyStringFormatParser.NewStyleSubstitutionChunk chunk) { - String mappingKey = Integer.toString(i + 1); - final HashSet types = new HashSet<>(); - boolean hasTypeOptions = false; - - if (chunk.getMappingKey() != null) { - mappingKey = chunk.getMappingKey(); - myUsedMappingKeys.put(mappingKey, false); - } - - // inspect options available only for numeric types - if (chunk.hasSignOption() || chunk.useAlternateForm() || chunk.hasZeroPadding() || chunk.hasThousandsSeparator()) { - addTypes(types, NUMERIC_TYPES); - hasTypeOptions = true; - } - - if (chunk.getPrecision() != null) { - // TODO: actually availableTypes doesn't reject int, because int is compatible with float and complex - final List availableTypes = Arrays.asList("str", "float", "complex"); - addTypes(types, availableTypes); - hasTypeOptions = true; - } - - final char conversionType = chunk.getConversionType(); - if (NEW_STYLE_FORMAT_CONVERSIONS.containsKey(conversionType)) { - final String[] s = NEW_STYLE_FORMAT_CONVERSIONS.get(conversionType).split(" or "); - addTypes(types, Arrays.asList(s)); - hasTypeOptions = true; - } - - if (!types.isEmpty()) { - myFormatSpec.put(mappingKey, StringUtil.join(types, " or ")); - } - else if (hasTypeOptions) { - registerProblem(formatExpression, PyBundle.message("INSP.incompatible.options", i)); - } - return mappingKey; - } - private static void addTypes(@NotNull final Set types, @NotNull final List availableTypes) { if (!types.isEmpty()) { types.retainAll(availableTypes); @@ -730,56 +812,9 @@ public class PyStringFormatInspection extends PyInspection { } } - private static boolean isBytesLiteral(@NotNull PyStringLiteralExpression expr, @NotNull TypeEvalContext context) { - final PyBuiltinCache builtinCache = PyBuiltinCache.getInstance(expr); - final PyClassType bytesType = builtinCache.getBytesType(LanguageLevel.forElement(expr)); - final PyType actualType = context.getType(expr); - return bytesType != null && actualType != null && PyTypeChecker.match(bytesType, actualType, context); - } - - private void inspectWidth(@NotNull final PyStringLiteralExpression formatExpression, String width) { - if ("*".equals(width)) { - ++myExpectedArguments; - if (myUsedMappingKeys.size() > 0) { - registerProblem(formatExpression, "Can't use \'*\' in formats when using a mapping"); - } - } - } - public boolean isProblem() { return myProblemRegister; } - - private void inspectValues(@Nullable final PyExpression rightExpression) { - if (rightExpression == null) { - return; - } - if (rightExpression instanceof PyParenthesizedExpression) { - inspectValues(((PyParenthesizedExpression)rightExpression).getContainedExpression()); - } - else { - final PyClassType type = as(myTypeEvalContext.getType(rightExpression), PyClassType.class); - if (type != null) { - if (myUsedMappingKeys.size() > 0 && !PyABCUtil.isSubclass(type.getPyClass(), PyNames.MAPPING, myTypeEvalContext)) { - registerProblem(rightExpression, PyBundle.message("INSP.format.requires.mapping")); - return; - } - } - inspectArgumentsNumber(rightExpression); - } - } - - private void inspectArgumentsNumber(@NotNull final PyExpression rightExpression) { - final int arguments = inspectArguments(rightExpression, rightExpression); - if (myUsedMappingKeys.isEmpty() && arguments >= 0) { - if (myExpectedArguments < arguments) { - registerProblem(rightExpression, PyBundle.message("INSP.too.many.args.for.fmt.string")); - } - else if (myExpectedArguments > arguments) { - registerProblem(rightExpression, PyBundle.message("INSP.too.few.args.for.fmt.string")); - } - } - } } public Visitor(final ProblemsHolder holder, LocalInspectionToolSession session) { @@ -805,8 +840,8 @@ public class PyStringFormatInspection extends PyInspection { if (callee != null && callee.getName() != null && callee.getName().equals(PyNames.FORMAT)) { final PyStringLiteralExpression literalExpression = PsiTreeUtil.getChildOfType(callee, PyStringLiteralExpression.class); if (literalExpression != null) { - final Inspection inspection = new Inspection(this, myTypeEvalContext); - inspection.inspectNewStyleValues(literalExpression); + final NewStyleInspection inspection = new NewStyleInspection(literalExpression, this, myTypeEvalContext); + inspection.inspect(); } } } diff --git a/python/src/com/jetbrains/python/inspections/PyStringFormatParser.java b/python/src/com/jetbrains/python/inspections/PyStringFormatParser.java index 15fe786d6a53..19ae0a6834fc 100644 --- a/python/src/com/jetbrains/python/inspections/PyStringFormatParser.java +++ b/python/src/com/jetbrains/python/inspections/PyStringFormatParser.java @@ -179,9 +179,10 @@ public class PyStringFormatParser { myUnclosedMapping = unclosedMapping; } } + public static class NewStyleSubstitutionChunk extends SubstitutionChunk { @Nullable private String myConversion; - @Nullable private String myFieldNameAttribute; + @Nullable private String myMappingKeyAttributeName; @Nullable private String myMappingKeyElementIndex; private char myConversionType; private boolean signOption; @@ -243,12 +244,12 @@ public class PyStringFormatParser { } @Nullable - public String getFieldNameAttribute() { - return myFieldNameAttribute; + public String getMappingKeyAttributeName() { + return myMappingKeyAttributeName; } - public void setFieldNameAttribute(@NotNull String fieldNameAttribute) { - myFieldNameAttribute = fieldNameAttribute; + public void setMappingKeyAttributeName(@NotNull String mappingKeyAttributeName) { + myMappingKeyAttributeName = mappingKeyAttributeName; } @Nullable @@ -298,7 +299,7 @@ public class PyStringFormatParser { @NotNull private List parse() { myPos = 0; - while(myPos < myLiteral.length()) { + while (myPos < myLiteral.length()) { int next = myLiteral.indexOf('%', myPos); while(next >= 0 && next < myLiteral.length()-1 && myLiteral.charAt(next+1) == '%') { next = myLiteral.indexOf('%', next+2); @@ -350,7 +351,8 @@ public class PyStringFormatParser { try { final int number = Integer.parseInt(name); chunk.setPosition(number); - } catch (NumberFormatException e) { + } + catch (NumberFormatException e) { chunk.setMappingKey(name); } myPos = nameEnd; @@ -361,13 +363,13 @@ public class PyStringFormatParser { } // parse field name attribute name - if (isAt('.') ) { + if (isAt('.')) { myPos++; final int attributeEnd = StringUtil.indexOfAny(myLiteral, "!:.[}", myPos, end); if (attributeEnd > 0 && myPos < attributeEnd) { final String attributeName = myLiteral.substring(myPos, attributeEnd); - chunk.setFieldNameAttribute(attributeName); + chunk.setMappingKeyAttributeName(attributeName); myPos = attributeEnd; } } @@ -399,7 +401,7 @@ public class PyStringFormatParser { if (attributeEnd > 0 && myPos < attributeEnd) { myPos = attributeEnd + 1; } - }; + } } // conversion @@ -452,7 +454,8 @@ public class PyStringFormatParser { if (isAtSet(NEW_STYLE_CONVERSION_TYPES)) { chunk.setConversionType(myLiteral.charAt(myPos)); } - } + } + results.add(chunk); return autoPositionedFieldsCount; @@ -464,7 +467,7 @@ public class PyStringFormatParser { myResult.add(chunk); myPos++; if (isAt('(')) { - int mappingEnd = myLiteral.indexOf(')', myPos+1); + int mappingEnd = myLiteral.indexOf(')', myPos + 1); if (mappingEnd < 0) { chunk.setEndIndex(myLiteral.length()); chunk.setMappingKey(myLiteral.substring(myPos + 1)); @@ -473,7 +476,7 @@ public class PyStringFormatParser { return; } chunk.setMappingKey(myLiteral.substring(myPos + 1, mappingEnd)); - myPos = mappingEnd+1; + myPos = mappingEnd + 1; } else { chunk.setAutoPosition(mySubstitutionsCount); @@ -516,7 +519,7 @@ public class PyStringFormatParser { @NotNull private String parseWhileCharacterInSet(@NotNull final String characterSet) { int flagStart = myPos; - while(isAtSet(characterSet)) { + while (isAtSet(characterSet)) { myPos++; } return myLiteral.substring(flagStart, myPos); diff --git a/python/testData/inspections/PyStringFormatInspection/NewStyleMappingKeyWithSubscriptionFuncArgs.py b/python/testData/inspections/PyStringFormatInspection/NewStyleMappingKeyWithSubscriptionFuncArgs.py index 8a2a8b711fc2..44781f7f0647 100644 --- a/python/testData/inspections/PyStringFormatInspection/NewStyleMappingKeyWithSubscriptionFuncArgs.py +++ b/python/testData/inspections/PyStringFormatInspection/NewStyleMappingKeyWithSubscriptionFuncArgs.py @@ -7,7 +7,7 @@ def f(): def g(): return 1, 2, 3 -"{foo[1]}".format(foo=g()) +"{foo[1]:d}".format(foo=g()) "{foo[3]}".format(foo=g()) def ff(): diff --git a/python/testSrc/com/jetbrains/python/PyResolveTest.java b/python/testSrc/com/jetbrains/python/PyResolveTest.java index 9014d1234874..e52d361b4413 100644 --- a/python/testSrc/com/jetbrains/python/PyResolveTest.java +++ b/python/testSrc/com/jetbrains/python/PyResolveTest.java @@ -625,14 +625,14 @@ public class PyResolveTest extends PyResolveTestCase { //PY-2748 public void testFormatPositionalArgs() { PsiElement target = resolve(); - assertTrue(target instanceof PyReferenceExpression); + assertInstanceOf(target, PyReferenceExpression.class); assertEquals("string", target.getText()); } //PY-2748 public void testFormatArgsAndKWargs() { PsiElement target = resolve(); - assertTrue(target instanceof PyStringLiteralExpression); + assertInstanceOf(target, PyStringLiteralExpression.class); } //PY-2748 @@ -652,14 +652,14 @@ public class PyResolveTest extends PyResolveTestCase { //PY-2748 public void testFormatStringWithPackedListAsArgument() { PsiElement target = resolve(); - assertTrue(target instanceof PyNumericLiteralExpression); + assertInstanceOf(target, PyNumericLiteralExpression.class); assertEquals("1", target.getText()); } //PY-2748 public void testFormatStringWithPackedTupleAsArgument() { PsiElement target = resolve(); - assertTrue(target instanceof PyStringLiteralExpression); + assertInstanceOf(target, PyStringLiteralExpression.class); assertEquals("\"snd\"", target.getText()); } diff --git a/python/testSrc/com/jetbrains/python/PyStringFormatParserTest.java b/python/testSrc/com/jetbrains/python/PyStringFormatParserTest.java index d0aacef445c8..681221fa23a7 100644 --- a/python/testSrc/com/jetbrains/python/PyStringFormatParserTest.java +++ b/python/testSrc/com/jetbrains/python/PyStringFormatParserTest.java @@ -506,8 +506,8 @@ public class PyStringFormatParserTest extends TestCase { final NewStyleSubstitutionChunk chunk = (NewStyleSubstitutionChunk)chunks.get(0); assertEquals(TextRange.create(0, 7), chunk.getTextRange()); assertEquals("foo", chunk.getMappingKey()); - assertNotNull(chunk.getFieldNameAttribute()); - assertEquals("a", chunk.getFieldNameAttribute()); + assertNotNull(chunk.getMappingKeyAttributeName()); + assertEquals("a", chunk.getMappingKeyAttributeName()); } public void testNewStyleFiledNameWithElementIndex() { @@ -526,8 +526,8 @@ public class PyStringFormatParserTest extends TestCase { final NewStyleSubstitutionChunk chunk = (NewStyleSubstitutionChunk)chunks.get(0); assertEquals(TextRange.create(0, 9), chunk.getTextRange()); assertEquals("foo", chunk.getMappingKey()); - assertNotNull(chunk.getFieldNameAttribute()); - assertEquals("a", chunk.getFieldNameAttribute()); + assertNotNull(chunk.getMappingKeyAttributeName()); + assertEquals("a", chunk.getMappingKeyAttributeName()); assertEquals('d', chunk.getConversionType()); }