For #PY-2748 Resolve to argument with redundant parentheses and to binary expression argument in percent string

This commit is contained in:
Valentina Kiryushkina
2016-03-09 13:33:25 +03:00
parent d1d5dc8580
commit bd395499ed
4 changed files with 84 additions and 16 deletions
@@ -91,29 +91,73 @@ public class PySubstitutionChunkReference extends PsiReferenceBase<PyStringLiter
return null;
}
@Nullable
private PsiElement resolvePercentString() {
final PyBinaryExpression binaryExpression = PsiTreeUtil.getParentOfType(getElement(), PyBinaryExpression.class);
PsiElement result = null;
final PyBinaryExpression binaryExpression = PsiTreeUtil.getParentOfType(getElement(), PyBinaryExpression.class);
if (binaryExpression != null) {
final PyExpression rightExpression = binaryExpression.getRightExpression();
if (rightExpression instanceof PyParenthesizedExpression) {
final PyParenthesizedExpression expression = (PyParenthesizedExpression)rightExpression;
final PyExpression containedExpression = expression.getContainedExpression();
if (containedExpression instanceof PyTupleExpression ) {
final PyExpression[] elements = ((PySequenceExpression)containedExpression).getElements();
if (elements.length > myPosition) {
return elements[myPosition];
}
}
result = resolvePositional((PyParenthesizedExpression)rightExpression);
}
else if (rightExpression instanceof PyDictLiteralExpression) {
if (myChunk.getMappingKey() != null) {
final PyKeyValueExpression[] keyValueExpressions = ((PyDictLiteralExpression)rightExpression).getElements();
for (PyKeyValueExpression keyValueExpression: keyValueExpressions) {
final PyStringLiteralExpression key = (PyStringLiteralExpression)keyValueExpression.getKey();
if (key.getStringValue().equals(myChunk.getMappingKey())) {
return key;
}
result = resolveKeyword((PyDictLiteralExpression)rightExpression);
}
}
return result == null ? getElement() : result;
}
@Nullable
private PsiElement resolveKeyword(PyDictLiteralExpression rightExpression) {
if (myChunk.getMappingKey() != null) {
final PyKeyValueExpression[] keyValueExpressions = rightExpression.getElements();
for (PyKeyValueExpression keyValueExpression: keyValueExpressions) {
final PyStringLiteralExpression key = (PyStringLiteralExpression)keyValueExpression.getKey();
if (key.getStringValue().equals(myChunk.getMappingKey())) {
return key;
}
}
}
return null;
}
@Nullable
private PsiElement resolvePositional(PyParenthesizedExpression rightExpression) {
PsiElement result = null;
final PyExpression containedExpression = getContainedExpression(rightExpression);
if (containedExpression instanceof PyTupleExpression) {
final PyExpression[] elements = ((PySequenceExpression)containedExpression).getElements();
if (elements.length > myPosition) {
result = elements[myPosition];
}
}
else if (containedExpression instanceof PyBinaryExpression && ((PyBinaryExpression)containedExpression).isOperator("+")) {
result = processNotNestedBinaryExpression((PyBinaryExpression)containedExpression);
}
return result;
}
@Nullable
private PsiElement processNotNestedBinaryExpression(PyBinaryExpression containedExpression) {
PyExpression left = containedExpression.getLeftExpression();
PyExpression right = containedExpression.getRightExpression();
if (left instanceof PyParenthesizedExpression) {
PyExpression leftTuple = getContainedExpression((PyParenthesizedExpression)left);
if (leftTuple instanceof PyTupleExpression) {
PyExpression[] leftTupleElements = ((PyTupleExpression)leftTuple).getElements();
int leftTupleLength = leftTupleElements.length;
if (leftTupleLength > myPosition) {
return leftTupleElements[myPosition];
}
if (right instanceof PyParenthesizedExpression) {
PyExpression rightTuple = ((PyParenthesizedExpression)right).getContainedExpression();
if (rightTuple instanceof PyTupleExpression) {
PyExpression[] rigthTupleElements = ((PyTupleExpression)rightTuple).getElements();
int rightLength = rigthTupleElements.length;
if (leftTupleLength + rightLength > myPosition)
return rigthTupleElements[myPosition - leftTupleLength];
}
}
}
@@ -121,6 +165,15 @@ public class PySubstitutionChunkReference extends PsiReferenceBase<PyStringLiter
return null;
}
@Nullable
private static PyExpression getContainedExpression(@NotNull final PyParenthesizedExpression parenthesizedExpression) {
PyExpression containedExpression = parenthesizedExpression.getContainedExpression();
while (containedExpression instanceof PyParenthesizedExpression) {
containedExpression = ((PyParenthesizedExpression)containedExpression).getContainedExpression();
}
return containedExpression;
}
@Nullable
private static PyArgumentList getArgumentList(final PsiElement original) {
final PsiElement pyReferenceExpression = PsiTreeUtil.getParentOfType(original, PyReferenceExpression.class);
@@ -0,0 +1 @@
print("<ref>%d%s" % ((("1", " "))))
@@ -0,0 +1 @@
print("<ref>%d%s" % (("1",) + (" ")))
@@ -659,4 +659,17 @@ public class PyResolveTest extends PyResolveTestCase {
public void testGlobalNotDefinedAtTopLevel() {
assertResolvesTo(PyTargetExpression.class, "foo");
}
//PY-2478
public void testPercentStringBinaryStatementArg() {
PsiElement target = resolve();
assertTrue(target instanceof PyStringLiteralExpression);
assertTrue(((PyStringLiteralExpression)target).getStringValue().equals("1"));
}
public void testPercentStringArgWithRedundantParentheses() {
PsiElement target = resolve();
assertTrue(target instanceof PyStringLiteralExpression);
assertTrue(((PyStringLiteralExpression)target).getStringValue().equals("1"));
}
}