mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Turn qualifiers of assignment targets into references.
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
a.b = 23
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user