mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Fixes wrong mapping of subscribed assignment targets (PY-247); adds tests.
This commit is contained in:
@@ -20,17 +20,14 @@ import com.intellij.lang.ASTNode;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiErrorElement;
|
||||
import com.intellij.psi.PsiWhiteSpace;
|
||||
import com.intellij.psi.ResolveState;
|
||||
import com.intellij.psi.scope.PsiScopeProcessor;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.SmartList;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import com.jetbrains.python.PyElementTypes;
|
||||
import com.jetbrains.python.psi.*;
|
||||
import com.jetbrains.python.toolbox.FP;
|
||||
import com.jetbrains.python.toolbox.RepeatIterable;
|
||||
import com.jetbrains.python.toolbox.RepeatIterator;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -98,21 +95,21 @@ public class PyAssignmentStatementImpl extends PyElementImpl implements PyAssign
|
||||
private static void mapToValues(PyExpression lhs, PyExpression rhs, List<Pair<PyExpression, PyExpression>> map) {
|
||||
// cast for convenience
|
||||
PyTupleExpression lhs_tuple = null;
|
||||
PyTargetExpression lhs_target = null;
|
||||
PyExpression lhs_one = null;
|
||||
if (lhs instanceof PyTupleExpression) lhs_tuple = (PyTupleExpression)lhs;
|
||||
else if (lhs instanceof PyTargetExpression) lhs_target = (PyTargetExpression)lhs;
|
||||
else if (lhs != null) lhs_one = lhs;
|
||||
|
||||
PyTupleExpression rhs_tuple = null;
|
||||
PyTargetExpression rhs_target = null;
|
||||
PyExpression rhs_one = null;
|
||||
if (rhs instanceof PyTupleExpression) rhs_tuple = (PyTupleExpression)rhs;
|
||||
else if (rhs instanceof PyTargetExpression) rhs_target = (PyTargetExpression)rhs;
|
||||
else if (rhs != null) rhs_one = rhs;
|
||||
//
|
||||
if (lhs_target != null) { // single LHS, single RHS (direct mapping) or multiple RHS (packing)
|
||||
map.add(new Pair<PyExpression, PyExpression>(lhs_target, rhs));
|
||||
if (lhs_one != null) { // single LHS, single RHS (direct mapping) or multiple RHS (packing)
|
||||
map.add(new Pair<PyExpression, PyExpression>(lhs_one, rhs));
|
||||
}
|
||||
else if (lhs_tuple != null && rhs_target != null) { // multiple LHS, single RHS: unpacking
|
||||
//for (PyExpression tuple_elt : lhs_tuple.getElements()) map.add(new Pair<PyExpression, PyExpression>(tuple_elt, rhs_target));
|
||||
map.addAll(FP.zipList(lhs_tuple, new RepeatIterable<PyExpression>(rhs_target)));
|
||||
else if (lhs_tuple != null && rhs_one != null) { // multiple LHS, single RHS: unpacking
|
||||
//for (PyExpression tuple_elt : lhs_tuple.getElements()) map.add(new Pair<PyExpression, PyExpression>(tuple_elt, rhs_one));
|
||||
map.addAll(FP.zipList(lhs_tuple, new RepeatIterable<PyExpression>(rhs_one)));
|
||||
}
|
||||
else if (lhs_tuple != null && rhs_tuple != null) { // multiple both sides: piecewise mapping
|
||||
map.addAll(FP.zipList(lhs_tuple, rhs_tuple, null, null));
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
<dst1>a = <dst2>b = <dst3>c = <src>1
|
||||
@@ -0,0 +1 @@
|
||||
<dst>a = <src>"foo"
|
||||
@@ -0,0 +1 @@
|
||||
<dst>a = <src>foo['bar']
|
||||
@@ -0,0 +1 @@
|
||||
<dst>foo['bar'] = <src>1
|
||||
@@ -0,0 +1 @@
|
||||
<dst1>a, <dst2>b = <src1>1, <src2>2
|
||||
@@ -0,0 +1 @@
|
||||
<dst>some_tuple = <src1>1, <src2>2
|
||||
@@ -0,0 +1 @@
|
||||
<dst1>a, <dst2>b = <src>some_tuple
|
||||
@@ -0,0 +1,154 @@
|
||||
package com.jetbrains.python;
|
||||
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.jetbrains.python.psi.PyAssignmentStatement;
|
||||
import com.jetbrains.python.psi.PyExpression;
|
||||
import com.jetbrains.python.psi.PyTargetExpression;
|
||||
import com.jetbrains.python.psi.PySubscriptionExpression;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Tests assignment mapping and tracking.
|
||||
* User: dcheryasov
|
||||
* Date: Dec 11, 2009 2:13:51 AM
|
||||
*/
|
||||
public class PyAssignmentMappingTest extends MarkedTestCase {
|
||||
|
||||
public String getTestDataPath() {
|
||||
return PythonTestUtil.getTestDataPath() + "/psi/assignment/";
|
||||
}
|
||||
|
||||
|
||||
public void testSimple() throws Exception {
|
||||
Map<String, PsiElement> marks = loadTest();
|
||||
assertEquals(2, marks.size());
|
||||
PsiElement src = marks.get("<src>").getParent(); // const -> expr;
|
||||
PsiElement dst = marks.get("<dst>").getParent(); // ident -> target expr
|
||||
assertTrue(dst instanceof PyTargetExpression);
|
||||
PyAssignmentStatement stmt = (PyAssignmentStatement)dst.getParent();
|
||||
List<Pair<PyExpression, PyExpression>> mapping = stmt.getTargetsToValuesMapping();
|
||||
assertEquals(1, mapping.size());
|
||||
Pair<PyExpression, PyExpression> pair = mapping.get(0);
|
||||
assertEquals(dst, pair.getFirst());
|
||||
assertEquals(src, pair.getSecond());
|
||||
}
|
||||
|
||||
public void testSubscribedSource() throws Exception {
|
||||
Map<String, PsiElement> marks = loadTest();
|
||||
assertEquals(2, marks.size());
|
||||
PsiElement src = marks.get("<src>").getParent().getParent(); // const -> ref foo -> subscr expr;
|
||||
PsiElement dst = marks.get("<dst>").getParent(); // ident -> target expr
|
||||
assertTrue(dst instanceof PyTargetExpression);
|
||||
PyAssignmentStatement stmt = (PyAssignmentStatement)dst.getParent();
|
||||
List<Pair<PyExpression, PyExpression>> mapping = stmt.getTargetsToValuesMapping();
|
||||
assertEquals(1, mapping.size());
|
||||
Pair<PyExpression, PyExpression> pair = mapping.get(0);
|
||||
assertEquals(dst, pair.getFirst());
|
||||
assertEquals(src, pair.getSecond());
|
||||
}
|
||||
|
||||
public void testSubscribedTarget() throws Exception {
|
||||
Map<String, PsiElement> marks = loadTest();
|
||||
assertEquals(2, marks.size());
|
||||
PsiElement src = marks.get("<src>").getParent(); // const -> expr;
|
||||
PsiElement dst = marks.get("<dst>").getParent().getParent(); // ident -> target expr
|
||||
assertTrue(dst instanceof PySubscriptionExpression);
|
||||
PyAssignmentStatement stmt = (PyAssignmentStatement)src.getParent();
|
||||
List<Pair<PyExpression, PyExpression>> mapping = stmt.getTargetsToValuesMapping();
|
||||
assertEquals(1, mapping.size());
|
||||
Pair<PyExpression, PyExpression> pair = mapping.get(0);
|
||||
assertEquals(dst, pair.getFirst());
|
||||
assertEquals(src, pair.getSecond());
|
||||
}
|
||||
|
||||
|
||||
public void testMultiple() throws Exception {
|
||||
Map<String, PsiElement> marks = loadTest();
|
||||
final int TARGET_NUM = 3;
|
||||
assertEquals(TARGET_NUM+1, marks.size());
|
||||
PsiElement src = marks.get("<src>").getParent(); // const -> expr;
|
||||
PsiElement[] dsts = new PsiElement[TARGET_NUM];
|
||||
for (int i=0; i<TARGET_NUM; i+=1) {
|
||||
PsiElement dst = marks.get("<dst" + String.valueOf(i+1) +">").getParent(); // ident -> target expr
|
||||
assertTrue(dst instanceof PyTargetExpression);
|
||||
dsts[i] = dst;
|
||||
}
|
||||
PyAssignmentStatement stmt = (PyAssignmentStatement)src.getParent();
|
||||
List<Pair<PyExpression, PyExpression>> mapping = stmt.getTargetsToValuesMapping();
|
||||
assertEquals(TARGET_NUM, mapping.size());
|
||||
for (int i=0; i<TARGET_NUM; i+=1) {
|
||||
Pair<PyExpression, PyExpression> pair = mapping.get(i);
|
||||
assertEquals(dsts[i], pair.getFirst());
|
||||
assertEquals(src, pair.getSecond());
|
||||
}
|
||||
}
|
||||
|
||||
public void testTupleMapped() throws Exception {
|
||||
Map<String, PsiElement> marks = loadTest();
|
||||
final int PAIR_NUM = 2;
|
||||
assertEquals(PAIR_NUM*2, marks.size());
|
||||
PsiElement[] srcs = new PsiElement[PAIR_NUM];
|
||||
PsiElement[] dsts = new PsiElement[PAIR_NUM];
|
||||
for (int i=0; i<PAIR_NUM; i+=1) {
|
||||
PsiElement dst = marks.get("<dst" + String.valueOf(i+1) +">").getParent(); // ident -> target expr
|
||||
assertTrue(dst instanceof PyTargetExpression);
|
||||
dsts[i] = dst;
|
||||
PsiElement src = marks.get("<src" + String.valueOf(i+1) +">").getParent(); // ident -> target expr
|
||||
assertTrue(src instanceof PyExpression);
|
||||
srcs[i] = src;
|
||||
}
|
||||
PyAssignmentStatement stmt = (PyAssignmentStatement)srcs[0].getParent().getParent(); // tuple expr -> assignment
|
||||
List<Pair<PyExpression, PyExpression>> mapping = stmt.getTargetsToValuesMapping();
|
||||
assertEquals(PAIR_NUM, mapping.size());
|
||||
for (int i=0; i<PAIR_NUM; i+=1) {
|
||||
Pair<PyExpression, PyExpression> pair = mapping.get(i);
|
||||
assertEquals(dsts[i], pair.getFirst());
|
||||
assertEquals(srcs[i], pair.getSecond());
|
||||
}
|
||||
}
|
||||
|
||||
public void testTuplePack() throws Exception {
|
||||
Map<String, PsiElement> marks = loadTest();
|
||||
final int SRC_NUM = 2;
|
||||
assertEquals(SRC_NUM+1, marks.size());
|
||||
PsiElement[] srcs = new PsiElement[SRC_NUM];
|
||||
for (int i=0; i<SRC_NUM; i+=1) {
|
||||
PsiElement src = marks.get("<src" + String.valueOf(i+1) +">").getParent(); // ident -> target expr
|
||||
assertTrue(src instanceof PyExpression);
|
||||
srcs[i] = src;
|
||||
}
|
||||
PsiElement dst = marks.get("<dst>").getParent(); // ident -> target expr
|
||||
PyAssignmentStatement stmt = (PyAssignmentStatement)dst.getParent();
|
||||
List<Pair<PyExpression, PyExpression>> mapping = stmt.getTargetsToValuesMapping();
|
||||
assertEquals(1, mapping.size());
|
||||
Pair<PyExpression, PyExpression> pair = mapping.get(0);
|
||||
assertEquals(dst, pair.getFirst());
|
||||
for (PsiElement src : srcs) {
|
||||
assertEquals(src.getParent(), pair.getSecond()); // numeric expr -> tuple
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void testTupleUnpack() throws Exception {
|
||||
Map<String, PsiElement> marks = loadTest();
|
||||
final int DST_NUM = 2;
|
||||
assertEquals(DST_NUM+1, marks.size());
|
||||
PsiElement[] dsts = new PsiElement[DST_NUM];
|
||||
for (int i=0; i<DST_NUM; i+=1) {
|
||||
PsiElement dst = marks.get("<dst" + String.valueOf(i+1) +">").getParent(); // ident -> target expr
|
||||
assertTrue(dst instanceof PyTargetExpression);
|
||||
dsts[i] = dst;
|
||||
}
|
||||
PsiElement src = marks.get("<src>").getParent(); // ident -> target expr
|
||||
PyAssignmentStatement stmt = (PyAssignmentStatement)src.getParent();
|
||||
List<Pair<PyExpression, PyExpression>> mapping = stmt.getTargetsToValuesMapping();
|
||||
assertEquals(DST_NUM, mapping.size());
|
||||
for (int i=0; i<DST_NUM; i+=1) {
|
||||
Pair<PyExpression, PyExpression> pair = mapping.get(i);
|
||||
assertEquals(dsts[i], pair.getFirst());
|
||||
assertEquals(src, pair.getSecond());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -20,6 +20,7 @@ public class PythonAllTestsSuite {
|
||||
PyMultiFileResolveTest.class,
|
||||
PyResolveCalleeTest.class,
|
||||
PyToJavaResolveTest.class,
|
||||
PyAssignmentTrackingTest.class,
|
||||
PythonCompletionTest.class,
|
||||
PyInheritorsSearchTest.class,
|
||||
PyParameterInfoTest.class,
|
||||
|
||||
Reference in New Issue
Block a user