diff --git a/python/src/com/jetbrains/python/codeInsight/controlflow/PyControlFlowBuilder.java b/python/src/com/jetbrains/python/codeInsight/controlflow/PyControlFlowBuilder.java index 861194de4c32..c7d596c48414 100644 --- a/python/src/com/jetbrains/python/codeInsight/controlflow/PyControlFlowBuilder.java +++ b/python/src/com/jetbrains/python/codeInsight/controlflow/PyControlFlowBuilder.java @@ -9,6 +9,8 @@ import com.intellij.openapi.util.Ref; import com.intellij.psi.PsiElement; import com.intellij.psi.util.PsiTreeUtil; import com.jetbrains.python.psi.*; +import com.jetbrains.python.psi.impl.PyAugAssignmentStatementNavigator; +import com.jetbrains.python.psi.impl.PyImportStatementNavigator; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; @@ -45,6 +47,27 @@ public class PyControlFlowBuilder extends PyRecursiveElementVisitor { super.visitPyStatement(node); } + @Override + public void visitPyReferenceExpression(final PyReferenceExpression node) { + final PyExpression qualifier = node.getQualifier(); + if (qualifier != null){ + qualifier.accept(this); + } + if (PyImportStatementNavigator.getImportStatementByReference(node) != null){ + return; + } + + final ReadInstruction readInstruction = new ReadInstruction(myBuilder, node, node.getName()); + myBuilder.addNode(readInstruction); + myBuilder.checkPending(readInstruction); + + if (PyAugAssignmentStatementNavigator.getStatementByTarget(node) != null){ + final WriteInstruction writeInstruction = new WriteInstruction(myBuilder, node, node.getName()); + myBuilder.addNode(writeInstruction); + myBuilder.checkPending(writeInstruction); + } + } + @Override public void visitPyAssignmentStatement(final PyAssignmentStatement node) { myBuilder.startNode(node); diff --git a/python/src/com/jetbrains/python/codeInsight/controlflow/ReadInstruction.java b/python/src/com/jetbrains/python/codeInsight/controlflow/ReadInstruction.java new file mode 100644 index 000000000000..7209d2b66b99 --- /dev/null +++ b/python/src/com/jetbrains/python/codeInsight/controlflow/ReadInstruction.java @@ -0,0 +1,24 @@ +package com.jetbrains.python.codeInsight.controlflow; + +import com.intellij.codeInsight.controlflow.ControlFlowBuilder; +import com.intellij.codeInsight.controlflow.impl.InstructionImpl; +import com.jetbrains.python.psi.PyElement; +import org.jetbrains.annotations.NonNls; + +public class ReadInstruction extends InstructionImpl { + public String myName; + + public ReadInstruction(final ControlFlowBuilder builder, final PyElement element, final String name) { + super(builder, element); + myName = name; + } + + public String getName() { + return myName; + } + + @NonNls + public String getElementPresentation() { + return "READ ACCESS: " + myName; + } +} \ No newline at end of file diff --git a/python/src/com/jetbrains/python/psi/impl/PyAugAssignmentStatementNavigator.java b/python/src/com/jetbrains/python/psi/impl/PyAugAssignmentStatementNavigator.java new file mode 100644 index 000000000000..76195acb9a3b --- /dev/null +++ b/python/src/com/jetbrains/python/psi/impl/PyAugAssignmentStatementNavigator.java @@ -0,0 +1,20 @@ +package com.jetbrains.python.psi.impl; + +import com.intellij.psi.PsiElement; +import com.intellij.psi.util.PsiTreeUtil; +import com.jetbrains.python.psi.PyAugAssignmentStatement; +import org.jetbrains.annotations.Nullable; + +/** + * @author oleg + */ +public class PyAugAssignmentStatementNavigator { + @Nullable + public static PyAugAssignmentStatement getStatementByTarget(final PsiElement element){ + final PyAugAssignmentStatement statement = PsiTreeUtil.getParentOfType(element, PyAugAssignmentStatement.class); + if (statement == null){ + return null; + } + return statement.getTarget() == element ? statement : null; + } +} diff --git a/python/testData/codeInsight/controlflow/assignment.txt b/python/testData/codeInsight/controlflow/assignment.txt index 9a94af2d9b13..f3175eafa00a 100644 --- a/python/testData/codeInsight/controlflow/assignment.txt +++ b/python/testData/codeInsight/controlflow/assignment.txt @@ -1,4 +1,7 @@ 0(1) element: null 1(2) element: PyAssignmentStatement -2(3) WRITE ACCESS: aaa -3() element: null \ No newline at end of file +2(3) READ ACCESS: aaa +3(4) READ ACCESS: bbb +4(5) READ ACCESS: ccc +5(6) WRITE ACCESS: aaa +6() element: null \ No newline at end of file diff --git a/python/testData/codeInsight/controlflow/augassignment.txt b/python/testData/codeInsight/controlflow/augassignment.txt index e540d9d5f6bc..e35850279534 100644 --- a/python/testData/codeInsight/controlflow/augassignment.txt +++ b/python/testData/codeInsight/controlflow/augassignment.txt @@ -2,4 +2,8 @@ 1(2) element: PyAssignmentStatement 2(3) WRITE ACCESS: aaa 3(4) element: PyAugAssignmentStatement -4() element: null \ No newline at end of file +4(5) READ ACCESS: bbb +5(6) READ ACCESS: ccc +6(7) READ ACCESS: aaa +7(8) WRITE ACCESS: aaa +8() element: null \ No newline at end of file diff --git a/python/testData/codeInsight/controlflow/break.txt b/python/testData/codeInsight/controlflow/break.txt index 205ce227ef59..cc6c179e8e72 100644 --- a/python/testData/codeInsight/controlflow/break.txt +++ b/python/testData/codeInsight/controlflow/break.txt @@ -1,9 +1,12 @@ 0(1) element: null -1(2,8) element: PyWhileStatement -2(3) element: PyStatementList. Condition: foo:true -3(4,6) element: PyIfStatement -4(5) element: PyStatementList. Condition: condition:true -5(8) element: PyBreakStatement -6(7) element: PyExpressionStatement -7(1) element: PyExpressionStatement -8() element: null \ No newline at end of file +1(2) element: PyWhileStatement +2(3,11) READ ACCESS: foo +3(4) element: PyStatementList. Condition: foo:true +4(5) element: PyIfStatement +5(6,8) READ ACCESS: condition +6(7) element: PyStatementList. Condition: condition:true +7(11) element: PyBreakStatement +8(9) element: PyExpressionStatement +9(10) READ ACCESS: puts +10(1) element: PyExpressionStatement +11() element: null \ No newline at end of file diff --git a/python/testData/codeInsight/controlflow/continue.txt b/python/testData/codeInsight/controlflow/continue.txt index 5f64d783a311..9c8561df56c1 100644 --- a/python/testData/codeInsight/controlflow/continue.txt +++ b/python/testData/codeInsight/controlflow/continue.txt @@ -1,9 +1,12 @@ 0(1) element: null -1(2,8) element: PyWhileStatement -2(3) element: PyStatementList. Condition: foo:true -3(4,6) element: PyIfStatement -4(5) element: PyStatementList. Condition: condition:true -5(1) element: PyContinueStatement -6(7) element: PyExpressionStatement -7(1) element: PyExpressionStatement -8() element: null \ No newline at end of file +1(2) element: PyWhileStatement +2(3,11) READ ACCESS: foo +3(4) element: PyStatementList. Condition: foo:true +4(5) element: PyIfStatement +5(6,8) READ ACCESS: condition +6(7) element: PyStatementList. Condition: condition:true +7(1) element: PyContinueStatement +8(9) element: PyExpressionStatement +9(10) READ ACCESS: puts +10(1) element: PyExpressionStatement +11() element: null \ No newline at end of file diff --git a/python/testData/codeInsight/controlflow/file.txt b/python/testData/codeInsight/controlflow/file.txt index b9308de14866..8f2cb77b1ba4 100644 --- a/python/testData/codeInsight/controlflow/file.txt +++ b/python/testData/codeInsight/controlflow/file.txt @@ -2,4 +2,5 @@ 1(2) element: PyAssignmentStatement 2(3) WRITE ACCESS: aaa 3(4) element: PyPrintStatement -4() element: null \ No newline at end of file +4(5) READ ACCESS: aaa +5() element: null \ No newline at end of file diff --git a/python/testData/codeInsight/controlflow/for.txt b/python/testData/codeInsight/controlflow/for.txt index b3cc468479ff..bb3183a2ad67 100644 --- a/python/testData/codeInsight/controlflow/for.txt +++ b/python/testData/codeInsight/controlflow/for.txt @@ -1,7 +1,9 @@ 0(1) element: null -1(2,5) element: PyForStatement -2(3) element: PyStatementList -3(4) WRITE ACCESS: i -4(2,6) element: PyPrintStatement +1(2) element: PyForStatement +2(3,7) READ ACCESS: range +3(4) element: PyStatementList +4(5) WRITE ACCESS: i 5(6) element: PyPrintStatement -6() element: null \ No newline at end of file +6(3,8) READ ACCESS: i +7(8) element: PyPrintStatement +8() element: null \ No newline at end of file diff --git a/python/testData/codeInsight/controlflow/function.txt b/python/testData/codeInsight/controlflow/function.txt index 93d24da4f7bd..8826cc5028ea 100644 --- a/python/testData/codeInsight/controlflow/function.txt +++ b/python/testData/codeInsight/controlflow/function.txt @@ -4,16 +4,39 @@ 3(4) WRITE ACCESS: collapse 4(5) element: PyExpressionStatement 5(6) element: PyAssignmentStatement -6(7,10) element: PyListCompExpression -7(8) element: PyCallExpression: callable -8(9) element: PyCallExpression: dir. Condition: callable(getattr(object, method)):true -9(10) WRITE ACCESS: method -10(11) WRITE ACCESS: methodList -11(12) element: PyAssignmentStatement -12(13) WRITE ACCESS: s -13(14) WRITE ACCESS: s -14(15) WRITE ACCESS: processFunc -15(16) element: PyPrintStatement -16(17) element: PyListCompExpression -17(18) WRITE ACCESS: method -18() element: null \ No newline at end of file +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) WRITE ACCESS: s +21(22) READ ACCESS: join +22(23) READ ACCESS: s +23(24) READ ACCESS: split +24(25) WRITE ACCESS: s +25(26) READ ACCESS: s +26(27) WRITE ACCESS: processFunc +27(28) element: PyPrintStatement +28(29) READ ACCESS: join +29(30) element: PyListCompExpression +30(31) READ ACCESS: methodList +31(32) WRITE ACCESS: method +32(33) READ ACCESS: method +33(34) READ ACCESS: ljust +34(35) READ ACCESS: spacing +35(36) READ ACCESS: processFunc +36(37) READ ACCESS: str +37(38) READ ACCESS: getattr +38(39) READ ACCESS: object +39(40) READ ACCESS: method +40(41) READ ACCESS: __doc__ +41() element: null \ No newline at end of file diff --git a/python/testData/codeInsight/controlflow/ifelsereturn.txt b/python/testData/codeInsight/controlflow/ifelsereturn.txt index 5354aedb6509..0bc243d84f80 100644 --- a/python/testData/codeInsight/controlflow/ifelsereturn.txt +++ b/python/testData/codeInsight/controlflow/ifelsereturn.txt @@ -1,11 +1,15 @@ 0(1) element: null -1(2,8) element: PyIfStatement -2(3) element: PyStatementList. Condition: markup:true -3(4) element: PyTryExceptStatement -4(5) element: PyTryPart -5(10) element: PyReturnStatement -6(7) element: PyExceptPart -7(10) element: PyRaiseStatement -8(9) element: PyElsePart. Condition: markup:false -9(10) element: PyReturnStatement -10() element: null \ No newline at end of file +1(2) element: PyIfStatement +2(3,11) READ ACCESS: markup +3(4) element: PyStatementList. Condition: markup:true +4(5) element: PyTryExceptStatement +5(6) element: PyTryPart +6(7) element: PyReturnStatement +7(14) READ ACCESS: renderer +8(9) element: PyExceptPart +9(10) READ ACCESS: KeyError +10(14) element: PyRaiseStatement +11(12) element: PyElsePart. Condition: markup:false +12(13) element: PyReturnStatement +13(14) READ ACCESS: body +14() element: null \ No newline at end of file diff --git a/python/testData/codeInsight/controlflow/listcomp.txt b/python/testData/codeInsight/controlflow/listcomp.txt index 002df93e0748..f9a206947cf2 100644 --- a/python/testData/codeInsight/controlflow/listcomp.txt +++ b/python/testData/codeInsight/controlflow/listcomp.txt @@ -1,8 +1,12 @@ 0(1) element: null 1(2) element: PyExpressionStatement -2(3,7) element: PyListCompExpression -3(4) element: PyReferenceExpression: foo -4(5) element: PyCallExpression: params.items. Condition: foo:true -5(6) WRITE ACCESS: k -6(7) WRITE ACCESS: v -7() element: null \ No newline at end of file +2(3) element: PyListCompExpression +3(4,11) READ ACCESS: foo +4(5) element: PyReferenceExpression: foo +5(6) element: PyCallExpression: params.items. Condition: foo:true +6(7) READ ACCESS: params +7(8) READ ACCESS: items +8(9) WRITE ACCESS: k +9(10) WRITE ACCESS: v +10(11) READ ACCESS: k +11() element: null \ No newline at end of file diff --git a/python/testData/codeInsight/controlflow/return.txt b/python/testData/codeInsight/controlflow/return.txt index 28c4603c6674..7d7f6c97655f 100644 --- a/python/testData/codeInsight/controlflow/return.txt +++ b/python/testData/codeInsight/controlflow/return.txt @@ -1,9 +1,12 @@ 0(1) element: null -1(2,8) element: PyWhileStatement -2(3) element: PyStatementList. Condition: foo:true -3(4,6) element: PyIfStatement -4(5) element: PyStatementList. Condition: condition:true -5(8) element: PyReturnStatement -6(7) element: PyExpressionStatement -7(1) element: PyExpressionStatement -8() element: null \ No newline at end of file +1(2) element: PyWhileStatement +2(3,11) READ ACCESS: foo +3(4) element: PyStatementList. Condition: foo:true +4(5) element: PyIfStatement +5(6,8) READ ACCESS: condition +6(7) element: PyStatementList. Condition: condition:true +7(11) element: PyReturnStatement +8(9) element: PyExpressionStatement +9(10) READ ACCESS: puts +10(1) element: PyExpressionStatement +11() element: null \ No newline at end of file diff --git a/python/testData/codeInsight/controlflow/try.txt b/python/testData/codeInsight/controlflow/try.txt index c3d74aa09076..a83ad9bc255d 100644 --- a/python/testData/codeInsight/controlflow/try.txt +++ b/python/testData/codeInsight/controlflow/try.txt @@ -4,18 +4,31 @@ 3(4) element: PyTryExceptStatement 4(5) element: PyTryPart 5(6) element: PyAssignmentStatement -6(7) WRITE ACCESS: f -7(8) element: PyAssignmentStatement -8(9) WRITE ACCESS: s -9(10) element: PyAssignmentStatement -10(11,15,17,20) WRITE ACCESS: i -11(12) element: PyExceptPart -12(13) WRITE ACCESS: errno -13(14) WRITE ACCESS: strerror -14(20) element: PyPrintStatement -15(16) element: PyExceptPart -16(20) element: PyPrintStatement +6(7) READ ACCESS: open +7(8) WRITE ACCESS: f +8(9) element: PyAssignmentStatement +9(10) READ ACCESS: f +10(11) READ ACCESS: readline +11(12) WRITE ACCESS: s +12(13) element: PyAssignmentStatement +13(14) READ ACCESS: int +14(15) READ ACCESS: s +15(16) READ ACCESS: strip +16(17,25,28,33) WRITE ACCESS: i 17(18) element: PyExceptPart -18(19) element: PyPrintStatement -19(20) element: PyRaiseStatement -20() element: null \ No newline at end of file +18(19) READ ACCESS: IOError +19(20) WRITE ACCESS: errno +20(21) WRITE ACCESS: strerror +21(22) element: PyPrintStatement +22(23) READ ACCESS: format +23(24) READ ACCESS: errno +24(33) READ ACCESS: strerror +25(26) element: PyExceptPart +26(27) READ ACCESS: ValueError +27(33) element: PyPrintStatement +28(29) element: PyExceptPart +29(30) element: PyPrintStatement +30(31) READ ACCESS: sys +31(32) READ ACCESS: exc_info +32(33) element: PyRaiseStatement +33() element: null \ No newline at end of file diff --git a/python/testData/codeInsight/controlflow/while.txt b/python/testData/codeInsight/controlflow/while.txt index fc68c9ef50a3..f07e285c3bab 100644 --- a/python/testData/codeInsight/controlflow/while.txt +++ b/python/testData/codeInsight/controlflow/while.txt @@ -1,7 +1,8 @@ 0(1) element: null 1(2) element: PyWhileStatement -2(3) element: PyStatementList. Condition: condition:true -3(1,4) element: PyPrintStatement -4(5) element: PyStatementList. Condition: condition:false -5(6) element: PyPrintStatement -6() element: null \ No newline at end of file +2(3) READ ACCESS: condition +3(4) element: PyStatementList. Condition: condition:true +4(1,5) element: PyPrintStatement +5(6) element: PyStatementList. Condition: condition:false +6(7) element: PyPrintStatement +7() element: null \ No newline at end of file