diff --git a/python/src/META-INF/python-core-common.xml b/python/src/META-INF/python-core-common.xml
index 6cdbf4fa9090..40b3e80d0b29 100644
--- a/python/src/META-INF/python-core-common.xml
+++ b/python/src/META-INF/python-core-common.xml
@@ -452,6 +452,7 @@
+
diff --git a/python/src/com/jetbrains/python/codeInsight/PySubstitutionChunkReference.java b/python/src/com/jetbrains/python/codeInsight/PySubstitutionChunkReference.java
index ddbe2fc3e24d..898c1f9aa335 100644
--- a/python/src/com/jetbrains/python/codeInsight/PySubstitutionChunkReference.java
+++ b/python/src/com/jetbrains/python/codeInsight/PySubstitutionChunkReference.java
@@ -30,6 +30,7 @@ import org.jetbrains.annotations.Nullable;
public class PySubstitutionChunkReference extends PsiReferenceBase implements PsiReferenceEx{
private final int myPosition;
private final PyStringFormatParser.SubstitutionChunk myChunk;
+ private boolean myIgnoreUnresolved = false;
public PySubstitutionChunkReference(@NotNull final PyStringLiteralExpression element,
@NotNull final PyStringFormatParser.SubstitutionChunk chunk, final int position) {
@@ -37,10 +38,11 @@ public class PySubstitutionChunkReference extends PsiReferenceBase 0) {
final PyExpression[] arguments = argumentList.getArguments();
- if (myChunk.getMappingKey() != null) {
+
+ boolean isStarArgument = arguments.length == 1 && arguments[0] instanceof PyStarArgument;
+ if (isStarArgument) return getUnderStarExpression(arguments);
+
+ boolean isKeywordSubstitution = myChunk.getMappingKey() != null;
+ if (isKeywordSubstitution) {
return argumentList.getKeywordArgument(myChunk.getMappingKey());
}
else {
final int position = myChunk.getPosition() == null ? myPosition : myChunk.getPosition();
- if (arguments.length == 1 && arguments[0] instanceof PyStarArgument) {
- return arguments[0];
- }
- else if (position < arguments.length) {
- return arguments[position];
- }
+ if (position < arguments.length) return arguments[position];
+
+ if (arguments[0] instanceof PyBinaryExpression && ((PyBinaryExpression)arguments[0]).isOperator("+")) {
+ return processNotNestedBinaryExpression((PyBinaryExpression)arguments[0]);
}
}
+ }
return null;
}
@@ -94,24 +102,27 @@ public class PySubstitutionChunkReference extends PsiReferenceBase myPosition) {
- result = elements[myPosition];
+ if (expression instanceof PyParenthesizedExpression) {
+ final PyExpression containedExpression = getContainedExpression((PyParenthesizedExpression)expression);
+
+ 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);
+ }
+ else if (containedExpression instanceof PyReferenceExpression) {
+ myIgnoreUnresolved = true;
}
}
- else if (containedExpression instanceof PyBinaryExpression && ((PyBinaryExpression)containedExpression).isOperator("+")) {
- result = processNotNestedBinaryExpression((PyBinaryExpression)containedExpression);
+ else if (expression instanceof PyReferenceExpression) {
+ myIgnoreUnresolved = true;
}
return result;
}
@@ -154,10 +174,10 @@ public class PySubstitutionChunkReference extends PsiReferenceBase myPosition)
- return rigthTupleElements[myPosition - leftTupleLength];
+ return rightTupleElements[myPosition - leftTupleLength];
}
}
}
@@ -180,9 +200,57 @@ public class PySubstitutionChunkReference extends PsiReferenceBase