mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
a reference in a slice expression in the LHS of an assignment is always a reference expression, not a target expression (PY-6468)
This commit is contained in:
@@ -288,12 +288,12 @@ public class ExpressionParsing extends Parsing {
|
||||
|
||||
public boolean parseMemberExpression(boolean isTargetExpression) {
|
||||
// in sequence a.b.... .c all members but last are always references, and the last may be target.
|
||||
boolean recast_first_identifier = false;
|
||||
boolean recast_qualifier = false;
|
||||
boolean recastFirstIdentifier = false;
|
||||
boolean recastQualifier = false;
|
||||
do {
|
||||
boolean first_identifier_is_target = isTargetExpression && ! recast_first_identifier;
|
||||
boolean firstIdentifierIsTarget = isTargetExpression && ! recastFirstIdentifier;
|
||||
PsiBuilder.Marker expr = myBuilder.mark();
|
||||
if (!parsePrimaryExpression(first_identifier_is_target)) {
|
||||
if (!parsePrimaryExpression(firstIdentifierIsTarget)) {
|
||||
expr.drop();
|
||||
return false;
|
||||
}
|
||||
@@ -301,15 +301,14 @@ public class ExpressionParsing extends Parsing {
|
||||
while (true) {
|
||||
final IElementType tokenType = myBuilder.getTokenType();
|
||||
if (tokenType == PyTokenTypes.DOT) {
|
||||
if (first_identifier_is_target) {
|
||||
recast_first_identifier = true;
|
||||
if (firstIdentifierIsTarget) {
|
||||
recastFirstIdentifier = true;
|
||||
expr.rollbackTo();
|
||||
break;
|
||||
}
|
||||
else recast_first_identifier = false;
|
||||
myBuilder.advanceLexer();
|
||||
checkMatches(PyTokenTypes.IDENTIFIER, message("PARSE.expected.name"));
|
||||
if (isTargetExpression && ! recast_qualifier && !atAnyOfTokens(PyTokenTypes.DOT, PyTokenTypes.LPAR, PyTokenTypes.LBRACKET)) {
|
||||
if (isTargetExpression && ! recastQualifier && !atAnyOfTokens(PyTokenTypes.DOT, PyTokenTypes.LPAR, PyTokenTypes.LBRACKET)) {
|
||||
expr.done(PyElementTypes.TARGET_EXPRESSION);
|
||||
}
|
||||
else {
|
||||
@@ -354,25 +353,25 @@ public class ExpressionParsing extends Parsing {
|
||||
sliceItemStart.drop();
|
||||
checkMatches(PyTokenTypes.RBRACKET, message("PARSE.expected.rbracket"));
|
||||
expr.done(PyElementTypes.SUBSCRIPTION_EXPRESSION);
|
||||
if (isTargetExpression && ! recast_qualifier) {
|
||||
recast_first_identifier = true; // subscription is always a reference
|
||||
recast_qualifier = true; // recast non-first qualifiers too
|
||||
expr.rollbackTo();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isTargetExpression && ! recastQualifier) {
|
||||
recastFirstIdentifier = true; // subscription is always a reference
|
||||
recastQualifier = true; // recast non-first qualifiers too
|
||||
expr.rollbackTo();
|
||||
break;
|
||||
}
|
||||
expr = expr.precede();
|
||||
}
|
||||
else {
|
||||
expr.drop();
|
||||
break;
|
||||
}
|
||||
recast_first_identifier = false; // it is true only after a break; normal flow always unsets it.
|
||||
// recast_qualifier is untouched, it remembers whether qualifiers were already recast
|
||||
recastFirstIdentifier = false; // it is true only after a break; normal flow always unsets it.
|
||||
// recastQualifier is untouched, it remembers whether qualifiers were already recast
|
||||
}
|
||||
}
|
||||
while (recast_first_identifier);
|
||||
while (recastFirstIdentifier);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ PyFile:ExtendedSlices.py
|
||||
PsiWhiteSpace('\n')
|
||||
PyAssignmentStatement
|
||||
PySliceExpression
|
||||
PyTargetExpression: d
|
||||
PyReferenceExpression: d
|
||||
PsiElement(Py:IDENTIFIER)('d')
|
||||
PsiElement(Py:LBRACKET)('[')
|
||||
PySliceItem
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
foo = []
|
||||
foo[:] = []
|
||||
@@ -0,0 +1,29 @@
|
||||
PyFile:RangeAsLHS.py
|
||||
PyAssignmentStatement
|
||||
PyTargetExpression: foo
|
||||
PsiElement(Py:IDENTIFIER)('foo')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:EQ)('=')
|
||||
PsiWhiteSpace(' ')
|
||||
PyListLiteralExpression
|
||||
PsiElement(Py:LBRACKET)('[')
|
||||
PsiElement(Py:RBRACKET)(']')
|
||||
PsiWhiteSpace('\n')
|
||||
PyAssignmentStatement
|
||||
PySliceExpression
|
||||
PyReferenceExpression: foo
|
||||
PsiElement(Py:IDENTIFIER)('foo')
|
||||
PsiElement(Py:LBRACKET)('[')
|
||||
PySliceItem
|
||||
PyEmptyExpression
|
||||
<empty list>
|
||||
PsiElement(Py:COLON)(':')
|
||||
PyEmptyExpression
|
||||
<empty list>
|
||||
PsiElement(Py:RBRACKET)(']')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:EQ)('=')
|
||||
PsiWhiteSpace(' ')
|
||||
PyListLiteralExpression
|
||||
PsiElement(Py:LBRACKET)('[')
|
||||
PsiElement(Py:RBRACKET)(']')
|
||||
@@ -314,6 +314,10 @@ public class PythonParsingTest extends ParsingTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testRangeAsLHS() { // PY-6468
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void doTest() {
|
||||
doTest(LanguageLevel.PYTHON25);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user