Turn qualifiers of assignment targets into references.

This commit is contained in:
Dmitry Cheryasov
2008-10-25 07:17:55 +04:00
parent 6a7cc502e1
commit 910bac9cd8
6 changed files with 89 additions and 37 deletions
@@ -207,54 +207,66 @@ public class ExpressionParsing extends Parsing {
}
public boolean parseMemberExpression(PsiBuilder builder, boolean isTargetExpression) {
PsiBuilder.Marker expr = builder.mark();
if (!parsePrimaryExpression(builder, isTargetExpression)) {
expr.drop();
return false;
}
// in sequence a.b.... .c all members but last are always references, and the last may be target.
boolean recast_first_identifier = false;
do {
boolean first_identifier_is_target = isTargetExpression && ! recast_first_identifier;
PsiBuilder.Marker expr = builder.mark();
if (!parsePrimaryExpression(builder, first_identifier_is_target)) {
expr.drop();
return false;
}
while (true) {
final IElementType tokenType = builder.getTokenType();
if (tokenType == PyTokenTypes.DOT) {
builder.advanceLexer();
checkMatches(PyTokenTypes.IDENTIFIER, "name expected");
if (isTargetExpression && builder.getTokenType() != PyTokenTypes.DOT) {
expr.done(PyElementTypes.TARGET_EXPRESSION);
while (true) {
final IElementType tokenType = builder.getTokenType();
if (tokenType == PyTokenTypes.DOT) {
if (first_identifier_is_target) {
recast_first_identifier = true;
expr.rollbackTo();
break;
}
else recast_first_identifier = false;
builder.advanceLexer();
checkMatches(PyTokenTypes.IDENTIFIER, "name expected");
if (isTargetExpression && builder.getTokenType() != PyTokenTypes.DOT) {
expr.done(PyElementTypes.TARGET_EXPRESSION);
}
else {
expr.done(PyElementTypes.REFERENCE_EXPRESSION);
}
expr = expr.precede();
}
else {
expr.done(PyElementTypes.REFERENCE_EXPRESSION);
else if (tokenType == PyTokenTypes.LPAR) {
parseArgumentList(builder);
expr.done(PyElementTypes.CALL_EXPRESSION);
expr = expr.precede();
}
expr = expr.precede();
}
else if (tokenType == PyTokenTypes.LPAR) {
parseArgumentList(builder);
expr.done(PyElementTypes.CALL_EXPRESSION);
expr = expr.precede();
}
else if (tokenType == PyTokenTypes.LBRACKET) {
builder.advanceLexer();
if (builder.getTokenType() == PyTokenTypes.COLON) {
PsiBuilder.Marker sliceMarker = builder.mark();
sliceMarker.done(PyElementTypes.EMPTY_EXPRESSION);
parseSliceEnd(builder, expr);
}
else {
parseExpressionOptional();
else if (tokenType == PyTokenTypes.LBRACKET) {
builder.advanceLexer();
if (builder.getTokenType() == PyTokenTypes.COLON) {
PsiBuilder.Marker sliceMarker = builder.mark();
sliceMarker.done(PyElementTypes.EMPTY_EXPRESSION);
parseSliceEnd(builder, expr);
}
else {
checkMatches(PyTokenTypes.RBRACKET, "] expected");
expr.done(PyElementTypes.SUBSCRIPTION_EXPRESSION);
parseExpressionOptional();
if (builder.getTokenType() == PyTokenTypes.COLON) {
parseSliceEnd(builder, expr);
}
else {
checkMatches(PyTokenTypes.RBRACKET, "] expected");
expr.done(PyElementTypes.SUBSCRIPTION_EXPRESSION);
}
}
expr = expr.precede();
}
else {
expr.drop();
break;
}
expr = expr.precede();
}
else {
expr.drop();
break;
}
}
while (recast_first_identifier);
return true;
}
@@ -255,6 +255,22 @@ public class PyResolveUtil {
return path;
}
public static String toPath(PyQualifiedExpression expr, String separator) {
if (expr == null) return "";
List<PyQualifiedExpression> path = unwindQualifiers(expr);
if (path != null) {
StringBuilder buf = new StringBuilder();
boolean is_not_first = false;
for (PyQualifiedExpression ex : path) {
if (is_not_first) buf.append(separator);
else is_not_first = true;
buf.append(ex.getName());
}
return buf.toString();
}
else return expr.getName();
}
public static class CollectProcessor<T extends PsiElement> implements PsiScopeProcessor {
Class<T>[] my_collectables;
+1
View File
@@ -0,0 +1 @@
a.b = 23
+13
View File
@@ -0,0 +1,13 @@
PyFile:QualifiedTarget.py
PyAssignmentStatement
PyTargetExpression: b
PyReferenceExpression: a
PsiElement(Py:IDENTIFIER)('a')
PsiElement(Py:DOT)('.')
PsiElement(Py:IDENTIFIER)('b')
PsiWhiteSpace(' ')
PsiElement(Py:EQ)('=')
PsiWhiteSpace(' ')
PyNumericLiteralExpression
PsiElement(Py:INTEGER_LITERAL)('23')
@@ -0,0 +1,5 @@
class Foo: pass
foo = Foo();
f<ref>oo.bar = 1
@@ -51,6 +51,11 @@ public class PyResolveTest extends ResolveTestCase {
assertTrue(targetElement instanceof PyTargetExpression);
}
public void testQualifiedTarget() throws Exception {
PsiElement targetElement = resolve();
assertTrue(targetElement instanceof PyTargetExpression);
}
public void testInnerFuncVar() throws Exception {
PsiElement targetElement = resolve();
assertTrue(targetElement instanceof PyTargetExpression);