mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Fixed bugs in control flow for Python list comprehensions (PY-2574)
This commit is contained in:
@@ -506,36 +506,75 @@ public class PyControlFlowBuilder extends PyRecursiveElementVisitor {
|
||||
|
||||
@Override
|
||||
public void visitPyComprehensionElement(final PyComprehensionElement node) {
|
||||
myBuilder.startNode(node);
|
||||
PyExpression prevCondition = null;
|
||||
for (ComprhIfComponent component : node.getIfComponents()) {
|
||||
final PyExpression condition = component.getTest();
|
||||
if (condition != null) {
|
||||
condition.accept(this);
|
||||
final Instruction head = myBuilder.prevInstruction;
|
||||
final Instruction prevInstruction =
|
||||
prevCondition != null ? myBuilder.startConditionalNode(condition, prevCondition, true) : myBuilder.startNode(condition);
|
||||
prevCondition = condition;
|
||||
// restore head
|
||||
myBuilder.prevInstruction = head;
|
||||
myBuilder.addPendingEdge(node, head); // false condition
|
||||
myBuilder.prevInstruction = prevInstruction;
|
||||
}
|
||||
}
|
||||
myBuilder.startNode(node);
|
||||
List<Instruction> iterators = new ArrayList<Instruction>();
|
||||
|
||||
for (ComprhForComponent forComponent : node.getForComponents()) {
|
||||
final PyExpression iteratedList = forComponent.getIteratedList();
|
||||
if (prevCondition != null) {
|
||||
myBuilder.startConditionalNode(iteratedList, prevCondition, true);
|
||||
prevCondition = null;
|
||||
for (ComprehensionComponent component : node.getComponents()) {
|
||||
if (component instanceof ComprhForComponent) {
|
||||
final ComprhForComponent c = (ComprhForComponent) component;
|
||||
final PyExpression iteratedList = c.getIteratedList();
|
||||
final PyExpression iteratorVariable = c.getIteratorVariable();
|
||||
if (prevCondition != null) {
|
||||
myBuilder.startConditionalNode(iteratedList, prevCondition, true);
|
||||
prevCondition = null;
|
||||
}
|
||||
else {
|
||||
myBuilder.startNode(iteratedList);
|
||||
}
|
||||
iteratedList.accept(this);
|
||||
|
||||
// for-loop continue and exit
|
||||
for (Instruction i : iterators) {
|
||||
myBuilder.addEdge(myBuilder.prevInstruction, i);
|
||||
}
|
||||
myBuilder.addPendingEdge(node, myBuilder.prevInstruction);
|
||||
|
||||
final Instruction iterator = myBuilder.startNode(iteratorVariable);
|
||||
iteratorVariable.accept(this);
|
||||
|
||||
// Inner "for" and "if" constructs will be linked to all outer iterators
|
||||
iterators.add(iterator);
|
||||
}
|
||||
else if (component instanceof ComprhIfComponent) {
|
||||
final ComprhIfComponent c = (ComprhIfComponent) component;
|
||||
final PyExpression condition = c.getTest();
|
||||
if (condition == null) {
|
||||
continue;
|
||||
}
|
||||
if (prevCondition != null) {
|
||||
myBuilder.startConditionalNode(condition, prevCondition, true);
|
||||
}
|
||||
else {
|
||||
myBuilder.startNode(condition);
|
||||
}
|
||||
condition.accept(this);
|
||||
|
||||
// Condition is true for nested "for" and "if" constructs, next startNode() should create a conditional node
|
||||
prevCondition = condition;
|
||||
|
||||
// for-loop continue and exit
|
||||
for (Instruction i : iterators) {
|
||||
myBuilder.addEdge(myBuilder.prevInstruction, i);
|
||||
}
|
||||
myBuilder.addPendingEdge(node, myBuilder.prevInstruction);
|
||||
}
|
||||
iteratedList.accept(this);
|
||||
forComponent.getIteratorVariable().accept(this);
|
||||
}
|
||||
|
||||
final PyExpression result = node.getResultExpression();
|
||||
if (result != null) {
|
||||
if (prevCondition != null) {
|
||||
myBuilder.startConditionalNode(result, prevCondition, true);
|
||||
}
|
||||
else {
|
||||
myBuilder.startNode(result);
|
||||
}
|
||||
result.accept(this);
|
||||
|
||||
// for-loop continue
|
||||
for (Instruction i : iterators) {
|
||||
myBuilder.addEdge(myBuilder.prevInstruction, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,35 +5,40 @@
|
||||
4(5) element: PyExpressionStatement
|
||||
5(6) element: PyAssignmentStatement
|
||||
6(7) element: PyListCompExpression
|
||||
7(8) READ ACCESS: callable
|
||||
8(9) READ ACCESS: getattr
|
||||
9(10) READ ACCESS: object
|
||||
10(11,17) READ ACCESS: method
|
||||
11(12) element: PyCallExpression: callable
|
||||
12(13) element: PyCallExpression: dir. Condition: callable(getattr(object, method)):true
|
||||
13(14) READ ACCESS: dir
|
||||
14(15) READ ACCESS: object
|
||||
15(16) WRITE ACCESS: method
|
||||
16(17) READ ACCESS: method
|
||||
17(18) WRITE ACCESS: methodList
|
||||
18(19) element: PyAssignmentStatement
|
||||
19(20) READ ACCESS: collapse
|
||||
20(21) element: PyLambdaExpression
|
||||
21(22) WRITE ACCESS: s
|
||||
22(23) READ ACCESS: s
|
||||
23(24) element: PyLambdaExpression
|
||||
24(25) WRITE ACCESS: s
|
||||
25(26) READ ACCESS: s
|
||||
26(27) WRITE ACCESS: processFunc
|
||||
27(28) element: PyPrintStatement
|
||||
28(29) element: PyListCompExpression
|
||||
29(30) READ ACCESS: methodList
|
||||
30(31) WRITE ACCESS: method
|
||||
31(32) READ ACCESS: method
|
||||
32(33) READ ACCESS: spacing
|
||||
33(34) READ ACCESS: processFunc
|
||||
34(35) READ ACCESS: str
|
||||
35(36) READ ACCESS: getattr
|
||||
36(37) READ ACCESS: object
|
||||
37(38) READ ACCESS: method
|
||||
38() element: null
|
||||
7(8) element: PyCallExpression: dir
|
||||
8(9) READ ACCESS: dir
|
||||
9(10,19) READ ACCESS: object
|
||||
10(11) element: PyTargetExpression: method
|
||||
11(12) WRITE ACCESS: method
|
||||
12(13) element: PyCallExpression: callable
|
||||
13(14) READ ACCESS: callable
|
||||
14(15) READ ACCESS: getattr
|
||||
15(16) READ ACCESS: object
|
||||
16(10,17,19) READ ACCESS: method
|
||||
17(18) element: PyReferenceExpression: method. Condition: callable(getattr(object, method)):true
|
||||
18(10,19) READ ACCESS: method
|
||||
19(20) WRITE ACCESS: methodList
|
||||
20(21) element: PyAssignmentStatement
|
||||
21(22) READ ACCESS: collapse
|
||||
22(23) element: PyLambdaExpression
|
||||
23(24) WRITE ACCESS: s
|
||||
24(25) READ ACCESS: s
|
||||
25(26) element: PyLambdaExpression
|
||||
26(27) WRITE ACCESS: s
|
||||
27(28) READ ACCESS: s
|
||||
28(29) WRITE ACCESS: processFunc
|
||||
29(30) element: PyPrintStatement
|
||||
30(31) element: PyListCompExpression
|
||||
31(32) element: PyReferenceExpression: methodList
|
||||
32(33,43) READ ACCESS: methodList
|
||||
33(34) element: PyTargetExpression: method
|
||||
34(35) WRITE ACCESS: method
|
||||
35(36) element: PyBinaryExpression
|
||||
36(37) READ ACCESS: method
|
||||
37(38) READ ACCESS: spacing
|
||||
38(39) READ ACCESS: processFunc
|
||||
39(40) READ ACCESS: str
|
||||
40(41) READ ACCESS: getattr
|
||||
41(42) READ ACCESS: object
|
||||
42(33,43) READ ACCESS: method
|
||||
43() element: null
|
||||
@@ -1,10 +1,13 @@
|
||||
0(1) element: null
|
||||
1(2) element: PyExpressionStatement
|
||||
2(3) element: PySetCompExpression
|
||||
3(4) READ ACCESS: range
|
||||
4(5) WRITE ACCESS: i
|
||||
5(6) element: PyLambdaExpression
|
||||
6(7) READ ACCESS: i
|
||||
7(8) WRITE ACCESS: i
|
||||
8(9) READ ACCESS: i
|
||||
9() element: null
|
||||
3(4) element: PyCallExpression: range
|
||||
4(5,12) READ ACCESS: range
|
||||
5(6) element: PyTargetExpression: i
|
||||
6(7) WRITE ACCESS: i
|
||||
7(8) element: PyParenthesizedExpression
|
||||
8(9) element: PyLambdaExpression
|
||||
9(10) READ ACCESS: i
|
||||
10(11) WRITE ACCESS: i
|
||||
11(5,12) READ ACCESS: i
|
||||
12() element: null
|
||||
@@ -1 +1,4 @@
|
||||
[k for k, v in params.items() if foo]
|
||||
[(x, y) for k, v in params.items()
|
||||
if k
|
||||
for x, y in v
|
||||
if x > y]
|
||||
|
||||
@@ -1,11 +1,22 @@
|
||||
0(1) element: null
|
||||
1(2) element: PyExpressionStatement
|
||||
2(3) element: PyListCompExpression
|
||||
3(4,10) READ ACCESS: foo
|
||||
4(5) element: PyReferenceExpression: foo
|
||||
5(6) element: PyCallExpression: params.items. Condition: foo:true
|
||||
6(7) READ ACCESS: params
|
||||
7(8) WRITE ACCESS: k
|
||||
8(9) WRITE ACCESS: v
|
||||
9(10) READ ACCESS: k
|
||||
10() element: null
|
||||
3(4) element: PyCallExpression: params.items
|
||||
4(5,21) READ ACCESS: params
|
||||
5(6) element: PyTupleExpression
|
||||
6(7) WRITE ACCESS: k
|
||||
7(8) WRITE ACCESS: v
|
||||
8(9) element: PyReferenceExpression: k
|
||||
9(5,10,21) READ ACCESS: k
|
||||
10(11) element: PyReferenceExpression: v. Condition: k:true
|
||||
11(5,12,21) READ ACCESS: v
|
||||
12(13) element: PyTupleExpression
|
||||
13(14) WRITE ACCESS: x
|
||||
14(15) WRITE ACCESS: y
|
||||
15(16) element: PyBinaryExpression
|
||||
16(17) READ ACCESS: x
|
||||
17(5,12,18,21) READ ACCESS: y
|
||||
18(19) element: PyParenthesizedExpression. Condition: x > y:true
|
||||
19(20) READ ACCESS: x
|
||||
20(5,12,21) READ ACCESS: y
|
||||
21() element: null
|
||||
@@ -2,8 +2,11 @@
|
||||
1(2) element: PyReturnStatement
|
||||
2(3) READ ACCESS: dict
|
||||
3(4) element: PyGeneratorExpression
|
||||
4(5) WRITE ACCESS: name
|
||||
5(6) WRITE ACCESS: val
|
||||
6(7) READ ACCESS: name
|
||||
7(8) READ ACCESS: val
|
||||
8() element: null
|
||||
4(5,11) element: PyDictLiteralExpression
|
||||
5(6) element: PyTupleExpression
|
||||
6(7) WRITE ACCESS: name
|
||||
7(8) WRITE ACCESS: val
|
||||
8(9) element: PyParenthesizedExpression
|
||||
9(10) READ ACCESS: name
|
||||
10(5,11) READ ACCESS: val
|
||||
11() element: null
|
||||
Reference in New Issue
Block a user