Fix #PY-18659 ClassCastException in PySubstitutionChunkReference.resolvePercentString

This commit is contained in:
Valentina Kiryushkina
2016-03-09 13:33:27 +03:00
parent baee11599d
commit b6baa97f4d
5 changed files with 45 additions and 21 deletions
@@ -124,13 +124,7 @@ public class PySubstitutionChunkReference extends PsiReferenceBase<PyStringLiter
myIgnoreUnresolved = expression instanceof PyReferenceExpression;
if (expression instanceof PyDictLiteralExpression) {
final PyKeyValueExpression[] keyValueExpressions = ((PyDictLiteralExpression)expression).getElements();
for (PyKeyValueExpression keyValueExpression: keyValueExpressions) {
final PyStringLiteralExpression key = (PyStringLiteralExpression)keyValueExpression.getKey();
if (key.getStringValue().equals(myChunk.getMappingKey())) {
return key;
}
}
return resolveDictLiteralExpression((PyDictLiteralExpression)expression);
}
else if (expression instanceof PyCallExpression) {
return resolveCallExpression((PyCallExpression)expression);
@@ -200,7 +194,7 @@ public class PySubstitutionChunkReference extends PsiReferenceBase<PyStringLiter
}
@Nullable
private PyExpression getUnderStarExpression(@NotNull final PyExpression[] args) {
private PsiElement getUnderStarExpression(@NotNull final PyExpression[] args) {
if (args.length == 1 && args[0] instanceof PyStarArgument) {
PyExpression pyExpression = PsiTreeUtil.getChildOfAnyType(args[0], PyDictLiteralExpression.class,
PyParenthesizedExpression.class,
@@ -209,19 +203,7 @@ public class PySubstitutionChunkReference extends PsiReferenceBase<PyStringLiter
boolean isKeywordSubstitution = myChunk.getMappingKey() != null;
if (isKeywordSubstitution && pyExpression instanceof PyDictLiteralExpression) {
PyDictLiteralExpression dictLiteralExpression = (PyDictLiteralExpression)pyExpression;
for (PyKeyValueExpression keyValueExpression : dictLiteralExpression.getElements()) {
if (keyValueExpression.getKey() instanceof PyStringLiteralExpression) {
PyStringLiteralExpression key = (PyStringLiteralExpression)keyValueExpression.getKey();
if (key.getStringValue().equals(myChunk.getMappingKey())) {
return key;
}
}
else {
myIgnoreUnresolved = true;
break;
}
}
return resolveDictLiteralExpression((PyDictLiteralExpression)pyExpression);
}
else {
int position = myChunk.getPosition() != null ? myChunk.getPosition() : myPosition;
@@ -251,6 +233,25 @@ public class PySubstitutionChunkReference extends PsiReferenceBase<PyStringLiter
return null;
}
@Nullable
private PsiElement resolveDictLiteralExpression(PyDictLiteralExpression expression) {
final PyKeyValueExpression[] keyValueExpressions = expression.getElements();
for (PyKeyValueExpression keyValueExpression: keyValueExpressions) {
PyExpression keyExpression = keyValueExpression.getKey();
if (keyExpression instanceof PyStringLiteralExpression) {
final PyStringLiteralExpression key = (PyStringLiteralExpression)keyExpression;
if (key.getStringValue().equals(myChunk.getMappingKey())) {
return key;
}
}
else {
myIgnoreUnresolved = keyExpression instanceof PyReferenceExpression;
break;
}
}
return null;
}
@Nullable
private PyExpression resolveCallExpression(PyCallExpression pyExpression) {
PyExpression callee = pyExpression.getCallee();
@@ -0,0 +1 @@
print ("first is %(<warning descr="Unresolved reference 'fst'">fst</warning>)s" % {1: "3"})
@@ -0,0 +1,3 @@
f = "fst"
s = "snd"
v = "first {fst}, second {snd}".format(**{s: 221, f: 10})
@@ -0,0 +1,3 @@
f = "fst"
s = "snd"
print ("first is %(fst)s, second is %(snd)s" % {s: "3", f: "1"})
@@ -587,6 +587,22 @@ public class PyUnresolvedReferencesInspectionTest extends PyInspectionTestCase {
doTest();
}
// PY-2748
public void testFormatStringDictLiteralArgumentWithReferenceExprKeys() {
doTest();
}
// PY-2748
public void testPercentStringDictLiteralArgumentWithReferenceExprKeys() {
doTest();
}
// PY-2748
public void testFormatStringDictLiteralArgumentWithNumericExprKeys() {
doTest();
}
// PY-18254
public void testVarargsAnnotatedWithFunctionComment() {
doTest();