diff --git a/python/python-ast/src/com/jetbrains/python/ast/PyAstCapturePattern.kt b/python/python-ast/src/com/jetbrains/python/ast/PyAstCapturePattern.kt index a1f433480cf4..9fab596205b9 100644 --- a/python/python-ast/src/com/jetbrains/python/ast/PyAstCapturePattern.kt +++ b/python/python-ast/src/com/jetbrains/python/ast/PyAstCapturePattern.kt @@ -1,17 +1,19 @@ // Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -package com.jetbrains.python.ast; +package com.jetbrains.python.ast -import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.ApiStatus @ApiStatus.Experimental -public interface PyAstCapturePattern extends PyAstPattern { - @Override - default boolean isIrrefutable() { - return true; +interface PyAstCapturePattern : PyAstPattern { + override fun isIrrefutable(): Boolean { + return true } - @Override - default void acceptPyVisitor(PyAstElementVisitor pyVisitor) { - pyVisitor.visitPyCapturePattern(this); + fun getTarget(): PyAstTargetExpression { + return requireNotNull(findChildByClass(PyAstTargetExpression::class.java)) { "${this}: target cannot be null" } + } + + override fun acceptPyVisitor(pyVisitor: PyAstElementVisitor) { + pyVisitor.visitPyCapturePattern(this) } } diff --git a/python/python-psi-impl/src/com/jetbrains/python/codeInsight/controlflow/PyControlFlowBuilder.java b/python/python-psi-impl/src/com/jetbrains/python/codeInsight/controlflow/PyControlFlowBuilder.java index 6440b2a88217..29e7c260f05c 100644 --- a/python/python-psi-impl/src/com/jetbrains/python/codeInsight/controlflow/PyControlFlowBuilder.java +++ b/python/python-psi-impl/src/com/jetbrains/python/codeInsight/controlflow/PyControlFlowBuilder.java @@ -23,6 +23,7 @@ import com.intellij.codeInsight.controlflow.TransparentInstruction; import com.intellij.codeInsight.controlflow.impl.ConditionalInstructionImpl; import com.intellij.codeInsight.controlflow.impl.TransparentInstructionImpl; import com.intellij.openapi.util.Pair; +import com.intellij.openapi.util.Ref; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiNamedElement; import com.intellij.psi.util.PsiTreeUtil; @@ -32,6 +33,7 @@ import com.jetbrains.python.PyNames; import com.jetbrains.python.PyTokenTypes; import com.jetbrains.python.psi.*; import com.jetbrains.python.psi.impl.*; +import com.jetbrains.python.psi.types.PyNeverType; import one.util.streamex.StreamEx; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -44,6 +46,9 @@ public class PyControlFlowBuilder extends PyRecursiveElementVisitor { private final ControlFlowBuilder myBuilder = new ControlFlowBuilder(); private @Nullable TrueFalseNodes myTrueFalseNodes; + + // see com.jetbrains.python.PyPatternTypeTest.testMatchClassPatternShadowingCapture + private final @NotNull List myPatternBindingNames = new ArrayList<>(); private record TrueFalseNodes(@NotNull Instruction trueNode, @NotNull Instruction falseNode) {} @@ -334,12 +339,46 @@ public class PyControlFlowBuilder extends PyRecursiveElementVisitor { public void visitPyMatchStatement(@NotNull PyMatchStatement matchStatement) { myBuilder.startNode(matchStatement); PyExpression subject = matchStatement.getSubject(); + String subjectName = PyTypeAssertionEvaluator.getAssertionTargetName(subject); if (subject != null) { subject.accept(this); } - for (PyCaseClause caseClause : matchStatement.getCaseClauses()) { - visitPyCaseClause(caseClause); + Instruction nextClause = myBuilder.prevInstruction; + boolean unreachable = false; + for (PyCaseClause clause : matchStatement.getCaseClauses()) { + myBuilder.prevInstruction = nextClause; + nextClause = addTransparentInstruction(); + + myPatternBindingNames.clear(); + + PyPattern pattern = clause.getPattern(); + if (pattern != null) { + pattern.accept(this); + if (!myPatternBindingNames.contains(subjectName)) { + addTypeAssertionNodes(clause, true); + } + } + + PyExpression guard = clause.getGuardCondition(); + if (guard != null) { + TransparentInstruction trueNode = addTransparentInstruction(); + visitCondition(guard, trueNode, nextClause); + myBuilder.prevInstruction = trueNode; + addTypeAssertionNodes(guard, true); + } + + if (unreachable) { + addAssertTypeNever(); + } + if (pattern != null && pattern.isIrrefutable()) { + unreachable = true; + } + myBuilder.startNode(clause.getStatementList()); + clause.getStatementList().accept(this); + myBuilder.addPendingEdge(matchStatement, myBuilder.prevInstruction); + myBuilder.updatePendingElementScope(clause.getStatementList(), matchStatement); } + myBuilder.prevInstruction = nextClause; myBuilder.addNodeAndCheckPending(new TransparentInstructionImpl(myBuilder, matchStatement, "")); if (!myBuilder.prevInstruction.allPred().isEmpty()) { addTypeAssertionNodes(matchStatement, false); @@ -348,53 +387,20 @@ public class PyControlFlowBuilder extends PyRecursiveElementVisitor { myBuilder.prevInstruction = null; } - @Override - public void visitPyCaseClause(@NotNull PyCaseClause clause) { - PyPattern pattern = clause.getPattern(); - if (pattern != null) { - pattern.accept(this); - } - - TransparentInstruction trueNode = addTransparentInstruction(); - TransparentInstruction falseNode = addTransparentInstruction(); - PyExpression guard = clause.getGuardCondition(); - if (guard != null) { - visitCondition(guard, trueNode, falseNode); - addTypeAssertionNodes(guard, true); - myBuilder.addPendingEdge(clause, falseNode); - } - else { - myBuilder.addEdge(myBuilder.prevInstruction, trueNode); - } - myBuilder.prevInstruction = trueNode; - - clause.getStatementList().accept(this); - - if (clause.getParent() instanceof PyMatchStatement matchStatement) { - myBuilder.addPendingEdge(matchStatement, myBuilder.prevInstruction); - myBuilder.updatePendingElementScope(clause.getStatementList(), matchStatement); - } - myBuilder.prevInstruction = null; - } - - @Override - public void visitWildcardPattern(@NotNull PyWildcardPattern node) { - myBuilder.startNode(node); - addTypeAssertionNodes(node, true); - } - @Override public void visitPyPattern(@NotNull PyPattern node) { boolean isRefutable = !node.isIrrefutable(); if (isRefutable) { myBuilder.addNodeAndCheckPending(new RefutablePatternInstruction(myBuilder, node, false)); - myBuilder.addPendingEdge(node.getParent(), myBuilder.prevInstruction); } + else { + myBuilder.startNode(node); + } + myBuilder.addPendingEdge(node.getParent(), myBuilder.prevInstruction); node.acceptChildren(this); myBuilder.updatePendingElementScope(node, node.getParent()); - addTypeAssertionNodes(node, true); if (isRefutable) { myBuilder.addNode(new RefutablePatternInstruction(myBuilder, node, true)); } @@ -429,7 +435,6 @@ public class PyControlFlowBuilder extends PyRecursiveElementVisitor { node.getClassNameReference().accept(this); myBuilder.addPendingEdge(node.getParent(), myBuilder.prevInstruction); - addTypeAssertionNodes(node, true); node.getArgumentList().acceptChildren(this); myBuilder.updatePendingElementScope(node, node.getParent()); @@ -443,7 +448,6 @@ public class PyControlFlowBuilder extends PyRecursiveElementVisitor { node.getValue().accept(this); myBuilder.addPendingEdge(node.getParent(), myBuilder.prevInstruction); - addTypeAssertionNodes(node, true); myBuilder.addNode(new RefutablePatternInstruction(myBuilder, node, true)); } @@ -453,9 +457,20 @@ public class PyControlFlowBuilder extends PyRecursiveElementVisitor { // So no need to create an additional fail edge myBuilder.startNode(node); node.acceptChildren(this); + myPatternBindingNames.add(node.getTarget().getName()); myBuilder.updatePendingElementScope(node, node.getParent()); } + @Override + public void visitPyCapturePattern(@NotNull PyCapturePattern node) { + node.acceptChildren(this); + // Although capture pattern is irrefutable, I add fail edge + // here to add some connection to the next case clause. + // Perhaps this can be reworked and simplified later. + myBuilder.addPendingEdge(node.getParent(), myBuilder.prevInstruction); + myPatternBindingNames.add(node.getTarget().getName()); + } + @Override public void visitPyGroupPattern(@NotNull PyGroupPattern node) { // GroupPattern can't fail by itself – it fails only if its child fails. @@ -478,13 +493,16 @@ public class PyControlFlowBuilder extends PyRecursiveElementVisitor { if (condition != null) { visitCondition(condition, thenNode, elseNode); } + myBuilder.prevInstruction = thenNode; Boolean conditionResult = PyEvaluator.evaluateAsBooleanNoResolve(condition); - myBuilder.prevInstruction = unreachable || Boolean.FALSE.equals(conditionResult) ? null : thenNode; + if (unreachable || Boolean.FALSE.equals(conditionResult)) { + // Condition is always False, or some previous condition is always True. + addAssertTypeNever(); + } if (Boolean.TRUE.equals(conditionResult)) { unreachable = true; } - visitPyStatementPart(ifPart); exitInstructions.add(myBuilder.prevInstruction); @@ -494,7 +512,7 @@ public class PyControlFlowBuilder extends PyRecursiveElementVisitor { final PyElsePart elsePart = node.getElsePart(); if (elsePart != null) { if (unreachable) { - myBuilder.prevInstruction = null; + addAssertTypeNever(); } visitPyStatementPart(elsePart); } @@ -1124,6 +1142,13 @@ public class PyControlFlowBuilder extends PyRecursiveElementVisitor { return instruction; } + /** + * Can be used to mark a branch as unreachable. + */ + private void addAssertTypeNever() { + myBuilder.addNode(ReadWriteInstruction.assertType(myBuilder, null, null, context -> Ref.create(PyNeverType.NEVER))); + } + /** * Can be used to collect all pending edges * that we used to build CFG for `node`, diff --git a/python/python-psi-impl/src/com/jetbrains/python/codeInsight/controlflow/PyDataFlow.kt b/python/python-psi-impl/src/com/jetbrains/python/codeInsight/controlflow/PyDataFlow.kt index 3b19aa6bf85b..7553ae9be3fb 100644 --- a/python/python-psi-impl/src/com/jetbrains/python/codeInsight/controlflow/PyDataFlow.kt +++ b/python/python-psi-impl/src/com/jetbrains/python/codeInsight/controlflow/PyDataFlow.kt @@ -5,6 +5,7 @@ import com.intellij.codeInsight.controlflow.Instruction import com.intellij.openapi.util.Version import com.intellij.psi.PsiElement import com.intellij.psi.util.PsiTreeUtil +import com.intellij.psi.util.findParentOfType import com.jetbrains.python.codeInsight.dataflow.scope.ScopeUtil import com.jetbrains.python.psi.* import com.jetbrains.python.psi.impl.PyEvaluator @@ -88,7 +89,16 @@ class PyDataFlow(scopeOwner: ScopeOwner, controlFlow: ControlFlow, private val c * - calls to functions annotated with `NoReturn` */ fun PsiElement.isUnreachableForInspection(context: TypeEvalContext): Boolean { - return isUnreachableByControlFlow(context) && !isFirstTerminatingStatement(context) + return PyUtil.getParameterizedCachedValue(this, context) { isUnreachableForInspectionNoCache(it) } +} + +private fun PsiElement.isUnreachableForInspectionNoCache(context: TypeEvalContext): Boolean { + if (parent is PyElement && parent.isUnreachableForInspection(context)) return true + return isUnreachableByControlFlow(context) && when (this) { + is PyStatementList -> !(statements.firstOrNull()?.isIgnoredUnreachableStatement(context) ?: true) + is PyStatement -> !this.isIgnoredUnreachableStatement(context) + else -> false + } } /** @@ -128,12 +138,11 @@ fun PsiElement.findInstructionNumber(flow: Array): Int { return -1 } -private fun PsiElement.isFirstTerminatingStatement(context: TypeEvalContext): Boolean { - if (this.isTerminatingStatement(context)) { - val prevSibling = prevSiblingOfType() ?: return true - return !prevSibling.isTerminatingStatement(context) && !prevSibling.isUnreachableByControlFlow(context) - } - return false +private fun PyStatement.isIgnoredUnreachableStatement(context: TypeEvalContext): Boolean { + val parentBlock = this.parent as? PyStatementList ?: return false + if (parentBlock.statements[0] != this) return false + val parentCompoundStatement = parentBlock.findParentOfType() ?: return false + return !parentCompoundStatement.isUnreachableByControlFlow(context) && isTerminatingStatement(context) } private fun PsiElement.isTerminatingStatement(context: TypeEvalContext): Boolean { diff --git a/python/python-psi-impl/src/com/jetbrains/python/codeInsight/controlflow/PyTypeAssertionEvaluator.java b/python/python-psi-impl/src/com/jetbrains/python/codeInsight/controlflow/PyTypeAssertionEvaluator.java index 5a61b20148a8..248b9c437d72 100644 --- a/python/python-psi-impl/src/com/jetbrains/python/codeInsight/controlflow/PyTypeAssertionEvaluator.java +++ b/python/python-psi-impl/src/com/jetbrains/python/codeInsight/controlflow/PyTypeAssertionEvaluator.java @@ -168,10 +168,11 @@ public class PyTypeAssertionEvaluator extends PyRecursiveElementVisitor { } @Override - public void visitPyPattern(@NotNull PyPattern node) { - final PsiElement parent = PsiTreeUtil.skipParentsOfType(node, PyCaseClause.class, PyGroupPattern.class, PyAsPattern.class, PyOrPattern.class); - if (parent instanceof PyMatchStatement matchStatement) { - pushAssertion(matchStatement.getSubject(), myPositive, context -> context.getType(node)); + public void visitPyCaseClause(@NotNull PyCaseClause node) { + var pattern = node.getPattern(); + if (pattern == null) return; + if (node.getParent() instanceof PyMatchStatement matchStatement) { + pushAssertion(matchStatement.getSubject(), myPositive, context -> context.getType(pattern)); } } @@ -189,6 +190,10 @@ public class PyTypeAssertionEvaluator extends PyRecursiveElementVisitor { for (PyCaseClause cs : matchStatement.getCaseClauses()) { if (cs.getPattern() == null) continue; if (cs.getGuardCondition() != null) continue; + if (cs.getPattern().isIrrefutable()) { + subjectType = PyNeverType.NEVER; + break; + } subjectType = Ref.deref(createAssertionType(subjectType, context.getType(cs.getPattern()), false, context)); } @@ -358,6 +363,19 @@ public class PyTypeAssertionEvaluator extends PyRecursiveElementVisitor { } } + public static @Nullable String getAssertionTargetName(@Nullable PyExpression expression) { + PyExpression target = PyPsiUtils.flattenParens(expression); + if (target instanceof PyAssignmentExpression walrus) { + return getAssertionTargetName(walrus.getTarget()); + } + if (target instanceof PyReferenceExpression || target instanceof PyTargetExpression) { + if (!((PyQualifiedExpression)target).isQualified()) { + return target.getName(); + } + } + return null; + } + private static boolean isIfReferenceStatement(@NotNull PyExpression node) { return PsiTreeUtil.skipParentsOfType(node, PyParenthesizedExpression.class) instanceof PyIfPart; } @@ -392,4 +410,4 @@ public class PyTypeAssertionEvaluator extends PyRecursiveElementVisitor { return myFunction; } } -} +} \ No newline at end of file diff --git a/python/python-psi-impl/src/com/jetbrains/python/codeInsight/dataflow/PyReachingDefsDfaInstance.java b/python/python-psi-impl/src/com/jetbrains/python/codeInsight/dataflow/PyReachingDefsDfaInstance.java index 9930e14afacc..e8df30fd36a1 100644 --- a/python/python-psi-impl/src/com/jetbrains/python/codeInsight/dataflow/PyReachingDefsDfaInstance.java +++ b/python/python-psi-impl/src/com/jetbrains/python/codeInsight/dataflow/PyReachingDefsDfaInstance.java @@ -7,7 +7,7 @@ import com.intellij.codeInsight.dataflow.map.DfaMapInstance; import com.intellij.psi.PsiElement; import com.intellij.psi.util.PsiTreeUtil; import com.jetbrains.python.codeInsight.controlflow.CallInstruction; -import com.jetbrains.python.codeInsight.controlflow.ControlFlowCache; +import com.jetbrains.python.codeInsight.controlflow.PyDataFlowKt; import com.jetbrains.python.codeInsight.controlflow.ReadWriteInstruction; import com.jetbrains.python.codeInsight.dataflow.scope.ScopeUtil; import com.jetbrains.python.codeInsight.dataflow.scope.ScopeVariable; @@ -37,11 +37,8 @@ public class PyReachingDefsDfaInstance implements DfaMapInstance if (element == null || ((PyFile) element.getContainingFile()).getLanguageLevel().isPython2()){ return processReducedMap(map, instruction, element); } - var scope = ScopeUtil.getScopeOwner(element); - if (scope != null) { - if (ControlFlowCache.getDataFlow(scope, myContext).isUnreachable(instruction)) { - return UNREACHABLE_MARKER; - } + if (PyDataFlowKt.isUnreachableForInspection(element, myContext)) { + return UNREACHABLE_MARKER; } if (instruction instanceof CallInstruction callInstruction) { if (callInstruction.isNoReturnCall(myContext)) { diff --git a/python/python-psi-impl/src/com/jetbrains/python/inspections/PyUnreachableCodeInspection.kt b/python/python-psi-impl/src/com/jetbrains/python/inspections/PyUnreachableCodeInspection.kt index 1c1fb8ff0733..38de8f9de10f 100644 --- a/python/python-psi-impl/src/com/jetbrains/python/inspections/PyUnreachableCodeInspection.kt +++ b/python/python-psi-impl/src/com/jetbrains/python/inspections/PyUnreachableCodeInspection.kt @@ -5,13 +5,13 @@ import com.intellij.codeInspection.LocalInspectionToolSession import com.intellij.codeInspection.ProblemHighlightType import com.intellij.codeInspection.ProblemsHolder import com.intellij.psi.PsiElementVisitor -import com.intellij.psi.util.findParentInFile import com.jetbrains.python.PyPsiBundle import com.jetbrains.python.codeInsight.controlflow.isUnreachableForInspection -import com.jetbrains.python.psi.PyElement +import com.jetbrains.python.psi.PyStatement +import com.jetbrains.python.psi.PyStatementList /** - * Detects unreachable code using control flow graph + * Detects unreachable code using the control flow graph */ class PyUnreachableCodeInspection : PyInspection() { override fun buildVisitor( @@ -20,12 +20,16 @@ class PyUnreachableCodeInspection : PyInspection() { session: LocalInspectionToolSession ): PsiElementVisitor { return object : PyInspectionVisitor(holder, getContext(session)) { - override fun visitPyElement(node: PyElement) { + override fun visitPyStatementList(node: PyStatementList) { + if (node.parent.isUnreachableForInspection(myTypeEvalContext)) return + if (node.isUnreachableForInspection(myTypeEvalContext)) { + registerProblem(node, PyPsiBundle.message("INSP.unreachable.code"), ProblemHighlightType.LIKE_UNUSED_SYMBOL) + } + } + + override fun visitPyStatement(node: PyStatement) { + if (node.parent.isUnreachableForInspection(myTypeEvalContext)) return if (node.isUnreachableForInspection(myTypeEvalContext)) { - if (node.findParentInFile { it.isUnreachableForInspection(myTypeEvalContext) } != null) { - // We only want to highlight top level unreachable code - return - } registerProblem(node, PyPsiBundle.message("INSP.unreachable.code"), ProblemHighlightType.LIKE_UNUSED_SYMBOL) } } diff --git a/python/testData/codeInsight/controlflow/IfElifFalse.txt b/python/testData/codeInsight/controlflow/IfElifFalse.txt index 6a6ae8065788..0c8887643041 100644 --- a/python/testData/codeInsight/controlflow/IfElifFalse.txt +++ b/python/testData/codeInsight/controlflow/IfElifFalse.txt @@ -5,28 +5,30 @@ 4(5) element: null. Condition: c:true 5(6) ASSERTTYPE ACCESS: c 6(7) element: PyStatementList -7(15) element: PyPassStatement +7(16) element: PyPassStatement 8(9,10) READ ACCESS: False -9(15) element: null. Condition: False:false +9(16) element: null. Condition: False:false 10(11) element: null. Condition: False:true -11() ASSERTTYPE ACCESS: False -12(13) element: PyStatementList -13(14) element: PyAssignmentStatement -14(15) WRITE ACCESS: a -15(16) element: PyIfStatement -16(17,18) READ ACCESS: d -17(22) element: null. Condition: d:false -18(19) element: null. Condition: d:true -19(20) ASSERTTYPE ACCESS: d -20(21) element: PyStatementList -21(31) element: PyPassStatement -22(23,24) READ ACCESS: False -23(29) element: null. Condition: False:false -24(25) element: null. Condition: False:true -25() ASSERTTYPE ACCESS: False -26(27) element: PyStatementList -27(28) element: PyAssignmentStatement -28(31) WRITE ACCESS: b -29(30) element: PyStatementList -30(31) element: PyPassStatement -31() element: null \ No newline at end of file +11(12) ASSERTTYPE ACCESS: False +12(13) ASSERTTYPE ACCESS: null +13(14) element: PyStatementList +14(15) element: PyAssignmentStatement +15(16) WRITE ACCESS: a +16(17) element: PyIfStatement +17(18,19) READ ACCESS: d +18(23) element: null. Condition: d:false +19(20) element: null. Condition: d:true +20(21) ASSERTTYPE ACCESS: d +21(22) element: PyStatementList +22(33) element: PyPassStatement +23(24,25) READ ACCESS: False +24(31) element: null. Condition: False:false +25(26) element: null. Condition: False:true +26(27) ASSERTTYPE ACCESS: False +27(28) ASSERTTYPE ACCESS: null +28(29) element: PyStatementList +29(30) element: PyAssignmentStatement +30(33) WRITE ACCESS: b +31(32) element: PyStatementList +32(33) element: PyPassStatement +33() element: null \ No newline at end of file diff --git a/python/testData/codeInsight/controlflow/IfElifTrue.txt b/python/testData/codeInsight/controlflow/IfElifTrue.txt index dba8ed59f729..583c4fc3df23 100644 --- a/python/testData/codeInsight/controlflow/IfElifTrue.txt +++ b/python/testData/codeInsight/controlflow/IfElifTrue.txt @@ -18,14 +18,15 @@ 17(18) element: null. Condition: d:true 18(19) ASSERTTYPE ACCESS: d 19(20) element: PyStatementList -20(30) element: PyPassStatement +20(31) element: PyPassStatement 21(22,23) READ ACCESS: True -22() element: null. Condition: True:false +22(27) element: null. Condition: True:false 23(24) element: null. Condition: True:true 24(25) ASSERTTYPE ACCESS: True 25(26) element: PyStatementList -26(30) element: PyPassStatement -27(28) element: PyStatementList -28(29) element: PyAssignmentStatement -29(30) WRITE ACCESS: e -30() element: null \ No newline at end of file +26(31) element: PyPassStatement +27(28) ASSERTTYPE ACCESS: null +28(29) element: PyStatementList +29(30) element: PyAssignmentStatement +30(31) WRITE ACCESS: e +31() element: null \ No newline at end of file diff --git a/python/testData/codeInsight/controlflow/IfFalse.txt b/python/testData/codeInsight/controlflow/IfFalse.txt index 3ad7f6618317..a9edc6521b89 100644 --- a/python/testData/codeInsight/controlflow/IfFalse.txt +++ b/python/testData/codeInsight/controlflow/IfFalse.txt @@ -1,36 +1,39 @@ 0(1) element: null 1(2) element: PyIfStatement 2(3,4) READ ACCESS: False -3(9) element: null. Condition: False:false +3(10) element: null. Condition: False:false 4(5) element: null. Condition: False:true -5() ASSERTTYPE ACCESS: False -6(7) element: PyStatementList -7(8) element: PyAssignmentStatement -8(9) WRITE ACCESS: a -9(10) element: PyIfStatement -10(11,12) READ ACCESS: False -11(17) element: null. Condition: False:false -12(13) element: null. Condition: False:true -13() ASSERTTYPE ACCESS: False -14(15) element: PyStatementList -15(16) element: PyAssignmentStatement -16(19) WRITE ACCESS: b -17(18) element: PyStatementList -18(19) element: PyPassStatement -19(20) element: PyIfStatement -20(21,22) READ ACCESS: False -21(27) element: null. Condition: False:false -22(23) element: null. Condition: False:true -23() ASSERTTYPE ACCESS: False -24(25) element: PyStatementList -25(26) element: PyAssignmentStatement -26(35) WRITE ACCESS: c -27(28,29) READ ACCESS: d -28(33) element: null. Condition: d:false -29(30) element: null. Condition: d:true -30(31) ASSERTTYPE ACCESS: d -31(32) element: PyStatementList -32(35) element: PyPassStatement -33(34) element: PyStatementList -34(35) element: PyPassStatement -35() element: null \ No newline at end of file +5(6) ASSERTTYPE ACCESS: False +6(7) ASSERTTYPE ACCESS: null +7(8) element: PyStatementList +8(9) element: PyAssignmentStatement +9(10) WRITE ACCESS: a +10(11) element: PyIfStatement +11(12,13) READ ACCESS: False +12(19) element: null. Condition: False:false +13(14) element: null. Condition: False:true +14(15) ASSERTTYPE ACCESS: False +15(16) ASSERTTYPE ACCESS: null +16(17) element: PyStatementList +17(18) element: PyAssignmentStatement +18(21) WRITE ACCESS: b +19(20) element: PyStatementList +20(21) element: PyPassStatement +21(22) element: PyIfStatement +22(23,24) READ ACCESS: False +23(30) element: null. Condition: False:false +24(25) element: null. Condition: False:true +25(26) ASSERTTYPE ACCESS: False +26(27) ASSERTTYPE ACCESS: null +27(28) element: PyStatementList +28(29) element: PyAssignmentStatement +29(38) WRITE ACCESS: c +30(31,32) READ ACCESS: d +31(36) element: null. Condition: d:false +32(33) element: null. Condition: d:true +33(34) ASSERTTYPE ACCESS: d +34(35) element: PyStatementList +35(38) element: PyPassStatement +36(37) element: PyStatementList +37(38) element: PyPassStatement +38() element: null \ No newline at end of file diff --git a/python/testData/codeInsight/controlflow/IfFor.txt b/python/testData/codeInsight/controlflow/IfFor.txt index 2e40810309b1..6e2e020334ea 100644 --- a/python/testData/codeInsight/controlflow/IfFor.txt +++ b/python/testData/codeInsight/controlflow/IfFor.txt @@ -1,21 +1,22 @@ 0(1) element: null 1(2) element: PyIfStatement 2(3,4) READ ACCESS: True -3() element: null. Condition: True:false +3(13) element: null. Condition: True:false 4(5) element: null. Condition: True:true 5(6) ASSERTTYPE ACCESS: True 6(7) element: PyStatementList 7(8) element: PyForStatement 8(9) READ ACCESS: range -9(10,18) element: PyCallExpression: range +9(10,19) element: PyCallExpression: range 10(11) element: PyTargetExpression: _ 11(12) WRITE ACCESS: _ -12(10,18) element: PyPrintStatement -13(14) element: PyStatementList -14(15) element: PyRaiseStatement -15(16) READ ACCESS: Exception -16(17) element: PyCallExpression: Exception -17(20) raise: PyRaiseStatement -18(19) element: PyReturnStatement -19(20) READ ACCESS: True -20() element: null \ No newline at end of file +12(10,19) element: PyPrintStatement +13(14) ASSERTTYPE ACCESS: null +14(15) element: PyStatementList +15(16) element: PyRaiseStatement +16(17) READ ACCESS: Exception +17(18) element: PyCallExpression: Exception +18(21) raise: PyRaiseStatement +19(20) element: PyReturnStatement +20(21) READ ACCESS: True +21() element: null \ No newline at end of file diff --git a/python/testData/codeInsight/controlflow/IfTrue.txt b/python/testData/codeInsight/controlflow/IfTrue.txt index 646eca81260c..15f53b21f3b2 100644 --- a/python/testData/codeInsight/controlflow/IfTrue.txt +++ b/python/testData/codeInsight/controlflow/IfTrue.txt @@ -8,29 +8,32 @@ 7(8) element: PyPassStatement 8(9) element: PyIfStatement 9(10,11) READ ACCESS: True -10() element: null. Condition: True:false +10(15) element: null. Condition: True:false 11(12) element: null. Condition: True:true 12(13) ASSERTTYPE ACCESS: True 13(14) element: PyStatementList -14(18) element: PyPassStatement -15(16) element: PyStatementList -16(17) element: PyAssignmentStatement -17(18) WRITE ACCESS: b -18(19) element: PyIfStatement -19(20,21) READ ACCESS: True -20(25) element: null. Condition: True:false -21(22) element: null. Condition: True:true -22(23) ASSERTTYPE ACCESS: True -23(24) element: PyStatementList -24(35) element: PyPassStatement -25(26,27) READ ACCESS: c -26() element: null. Condition: c:false -27(28) element: null. Condition: c:true -28() ASSERTTYPE ACCESS: c -29(30) element: PyStatementList -30(31) element: PyAssignmentStatement -31(35) WRITE ACCESS: d -32(33) element: PyStatementList -33(34) element: PyAssignmentStatement -34(35) WRITE ACCESS: e -35() element: null \ No newline at end of file +14(19) element: PyPassStatement +15(16) ASSERTTYPE ACCESS: null +16(17) element: PyStatementList +17(18) element: PyAssignmentStatement +18(19) WRITE ACCESS: b +19(20) element: PyIfStatement +20(21,22) READ ACCESS: True +21(26) element: null. Condition: True:false +22(23) element: null. Condition: True:true +23(24) ASSERTTYPE ACCESS: True +24(25) element: PyStatementList +25(38) element: PyPassStatement +26(27,28) READ ACCESS: c +27(34) element: null. Condition: c:false +28(29) element: null. Condition: c:true +29(30) ASSERTTYPE ACCESS: c +30(31) ASSERTTYPE ACCESS: null +31(32) element: PyStatementList +32(33) element: PyAssignmentStatement +33(38) WRITE ACCESS: d +34(35) ASSERTTYPE ACCESS: null +35(36) element: PyStatementList +36(37) element: PyAssignmentStatement +37(38) WRITE ACCESS: e +38() element: null \ No newline at end of file diff --git a/python/testData/codeInsight/controlflow/MatchStatementClauseWithBreak.txt b/python/testData/codeInsight/controlflow/MatchStatementClauseWithBreak.txt index 42995cc4a96e..60a057dc3e03 100644 --- a/python/testData/codeInsight/controlflow/MatchStatementClauseWithBreak.txt +++ b/python/testData/codeInsight/controlflow/MatchStatementClauseWithBreak.txt @@ -1,18 +1,19 @@ 0(1) element: null 1(2) element: PyWhileStatement 2(3,4) READ ACCESS: x -3(15) element: null. Condition: x:false +3(16) element: null. Condition: x:false 4(5) element: null. Condition: x:true 5(6) element: PyStatementList 6(7) element: PyMatchStatement 7(8) READ ACCESS: x -8(9,12) refutable pattern: 42 -9(10) ASSERTTYPE ACCESS: x -10(11) matched pattern: 42 -11(15) element: PyBreakStatement -12(13) ASSERTTYPE ACCESS: x -13(14) element: PyExpressionStatement -14(1) READ ACCESS: y -15(16) element: PyExpressionStatement -16(17) READ ACCESS: z -17() element: null \ No newline at end of file +8(9,13) refutable pattern: 42 +9(10) matched pattern: 42 +10(11) ASSERTTYPE ACCESS: x +11(12) element: PyStatementList +12(16) element: PyBreakStatement +13(14) ASSERTTYPE ACCESS: x +14(15) element: PyExpressionStatement +15(1) READ ACCESS: y +16(17) element: PyExpressionStatement +17(18) READ ACCESS: z +18() element: null \ No newline at end of file diff --git a/python/testData/codeInsight/controlflow/MatchStatementClauseWithContinue.txt b/python/testData/codeInsight/controlflow/MatchStatementClauseWithContinue.txt index f195519c4260..3b4130587aa7 100644 --- a/python/testData/codeInsight/controlflow/MatchStatementClauseWithContinue.txt +++ b/python/testData/codeInsight/controlflow/MatchStatementClauseWithContinue.txt @@ -1,18 +1,19 @@ 0(1) element: null 1(2) element: PyWhileStatement 2(3,4) READ ACCESS: x -3(15) element: null. Condition: x:false +3(16) element: null. Condition: x:false 4(5) element: null. Condition: x:true 5(6) element: PyStatementList 6(7) element: PyMatchStatement 7(8) READ ACCESS: x -8(9,12) refutable pattern: 42 -9(10) ASSERTTYPE ACCESS: x -10(11) matched pattern: 42 -11(1) element: PyContinueStatement -12(13) ASSERTTYPE ACCESS: x -13(14) element: PyExpressionStatement -14(1) READ ACCESS: y -15(16) element: PyExpressionStatement -16(17) READ ACCESS: z -17() element: null \ No newline at end of file +8(9,13) refutable pattern: 42 +9(10) matched pattern: 42 +10(11) ASSERTTYPE ACCESS: x +11(12) element: PyStatementList +12(1) element: PyContinueStatement +13(14) ASSERTTYPE ACCESS: x +14(15) element: PyExpressionStatement +15(1) READ ACCESS: y +16(17) element: PyExpressionStatement +17(18) READ ACCESS: z +18() element: null \ No newline at end of file diff --git a/python/testData/codeInsight/controlflow/MatchStatementClauseWithReturn.txt b/python/testData/codeInsight/controlflow/MatchStatementClauseWithReturn.txt index de87a950d2ce..1db8a4d75509 100644 --- a/python/testData/codeInsight/controlflow/MatchStatementClauseWithReturn.txt +++ b/python/testData/codeInsight/controlflow/MatchStatementClauseWithReturn.txt @@ -2,11 +2,12 @@ 1(2) WRITE ACCESS: x 2(3) element: PyMatchStatement 3(4) READ ACCESS: x -4(5,8) refutable pattern: 42 -5(6) ASSERTTYPE ACCESS: x -6(7) matched pattern: 42 -7(11) element: PyReturnStatement -8(9) ASSERTTYPE ACCESS: x -9(10) element: PyExpressionStatement -10(11) READ ACCESS: y -11() element: null \ No newline at end of file +4(5,9) refutable pattern: 42 +5(6) matched pattern: 42 +6(7) ASSERTTYPE ACCESS: x +7(8) element: PyStatementList +8(12) element: PyReturnStatement +9(10) ASSERTTYPE ACCESS: x +10(11) element: PyExpressionStatement +11(12) READ ACCESS: y +12() element: null \ No newline at end of file diff --git a/python/testData/codeInsight/controlflow/MatchStatementNestedMatchStatement.txt b/python/testData/codeInsight/controlflow/MatchStatementNestedMatchStatement.txt index 48c128b80443..46b7727a19d6 100644 --- a/python/testData/codeInsight/controlflow/MatchStatementNestedMatchStatement.txt +++ b/python/testData/codeInsight/controlflow/MatchStatementNestedMatchStatement.txt @@ -1,20 +1,23 @@ 0(1) element: null 1(2) element: PyMatchStatement -2(3,12) refutable pattern: 1 +2(3,14) refutable pattern: 1 3(4) matched pattern: 1 -4(5) element: PyMatchStatement -5(6,9) refutable pattern: 11 -6(7) matched pattern: 11 -7(8) element: PyExpressionStatement -8(10) READ ACCESS: y11 -9(10) ASSERTTYPE ACCESS: null -10(11) element: PyExpressionStatement -11(17) READ ACCESS: y1 -12(13,16) refutable pattern: 2 -13(14) matched pattern: 2 -14(15) element: PyExpressionStatement -15(17) READ ACCESS: y2 -16(17) ASSERTTYPE ACCESS: null +4(5) element: PyStatementList +5(6) element: PyMatchStatement +6(7,11) refutable pattern: 11 +7(8) matched pattern: 11 +8(9) element: PyStatementList +9(10) element: PyExpressionStatement +10(12) READ ACCESS: y11 +11(12) ASSERTTYPE ACCESS: null +12(13) element: PyExpressionStatement +13(20) READ ACCESS: y1 +14(15,19) refutable pattern: 2 +15(16) matched pattern: 2 +16(17) element: PyStatementList 17(18) element: PyExpressionStatement -18(19) READ ACCESS: z -19() element: null \ No newline at end of file +18(20) READ ACCESS: y2 +19(20) ASSERTTYPE ACCESS: null +20(21) element: PyExpressionStatement +21(22) READ ACCESS: z +22() element: null \ No newline at end of file diff --git a/python/testData/codeInsight/controlflow/MatchStatementNestedMatchStatementLastInClause.txt b/python/testData/codeInsight/controlflow/MatchStatementNestedMatchStatementLastInClause.txt index 5ee21c066e7d..53cd9943b706 100644 --- a/python/testData/codeInsight/controlflow/MatchStatementNestedMatchStatementLastInClause.txt +++ b/python/testData/codeInsight/controlflow/MatchStatementNestedMatchStatementLastInClause.txt @@ -1,18 +1,21 @@ 0(1) element: null 1(2) element: PyMatchStatement -2(3,10) refutable pattern: 1 +2(3,12) refutable pattern: 1 3(4) matched pattern: 1 -4(5) element: PyMatchStatement -5(6,9) refutable pattern: 11 -6(7) matched pattern: 11 -7(8) element: PyExpressionStatement -8(15) READ ACCESS: y11 -9(15) ASSERTTYPE ACCESS: null -10(11,14) refutable pattern: 2 -11(12) matched pattern: 2 -12(13) element: PyExpressionStatement -13(15) READ ACCESS: y2 -14(15) ASSERTTYPE ACCESS: null +4(5) element: PyStatementList +5(6) element: PyMatchStatement +6(7,11) refutable pattern: 11 +7(8) matched pattern: 11 +8(9) element: PyStatementList +9(10) element: PyExpressionStatement +10(18) READ ACCESS: y11 +11(18) ASSERTTYPE ACCESS: null +12(13,17) refutable pattern: 2 +13(14) matched pattern: 2 +14(15) element: PyStatementList 15(16) element: PyExpressionStatement -16(17) READ ACCESS: z -17() element: null \ No newline at end of file +16(18) READ ACCESS: y2 +17(18) ASSERTTYPE ACCESS: null +18(19) element: PyExpressionStatement +19(20) READ ACCESS: z +20() element: null \ No newline at end of file diff --git a/python/testData/codeInsight/controlflow/MatchStatementSingleClauseAliasedRefutableOrPattern.txt b/python/testData/codeInsight/controlflow/MatchStatementSingleClauseAliasedRefutableOrPattern.txt index 12703b1080d8..3e67a9fdc753 100644 --- a/python/testData/codeInsight/controlflow/MatchStatementSingleClauseAliasedRefutableOrPattern.txt +++ b/python/testData/codeInsight/controlflow/MatchStatementSingleClauseAliasedRefutableOrPattern.txt @@ -7,13 +7,14 @@ 6(7) matched pattern: 42 7(11) matched pattern: [42] 8(9) refutable pattern: foo.bar -9(10,15) READ ACCESS: foo +9(10,16) READ ACCESS: foo 10(11) matched pattern: foo.bar 11(12) matched pattern: [42] | foo.bar 12(13) WRITE ACCESS: x -13(14) element: PyExpressionStatement -14(16) READ ACCESS: y -15(16) ASSERTTYPE ACCESS: null -16(17) element: PyExpressionStatement -17(18) READ ACCESS: z -18() element: null \ No newline at end of file +13(14) element: PyStatementList +14(15) element: PyExpressionStatement +15(17) READ ACCESS: y +16(17) ASSERTTYPE ACCESS: null +17(18) element: PyExpressionStatement +18(19) READ ACCESS: z +19() element: null \ No newline at end of file diff --git a/python/testData/codeInsight/controlflow/MatchStatementSingleClauseBindingSequencePattern.txt b/python/testData/codeInsight/controlflow/MatchStatementSingleClauseBindingSequencePattern.txt index 972b392ce2bc..a7c278494bf1 100644 --- a/python/testData/codeInsight/controlflow/MatchStatementSingleClauseBindingSequencePattern.txt +++ b/python/testData/codeInsight/controlflow/MatchStatementSingleClauseBindingSequencePattern.txt @@ -1,11 +1,12 @@ 0(1) element: null 1(2) element: PyMatchStatement -2(3,7) refutable pattern: [x] -3(4) WRITE ACCESS: x +2(3,8) refutable pattern: [x] +3(4,8) WRITE ACCESS: x 4(5) matched pattern: [x] -5(6) element: PyExpressionStatement -6(8) READ ACCESS: y -7(8) ASSERTTYPE ACCESS: null -8(9) element: PyExpressionStatement -9(10) READ ACCESS: z -10() element: null \ No newline at end of file +5(6) element: PyStatementList +6(7) element: PyExpressionStatement +7(9) READ ACCESS: y +8(9) ASSERTTYPE ACCESS: null +9(10) element: PyExpressionStatement +10(11) READ ACCESS: z +11() element: null \ No newline at end of file diff --git a/python/testData/codeInsight/controlflow/MatchStatementSingleClauseCapturePattern.txt b/python/testData/codeInsight/controlflow/MatchStatementSingleClauseCapturePattern.txt index a637619e16b2..aac2a5b8002b 100644 --- a/python/testData/codeInsight/controlflow/MatchStatementSingleClauseCapturePattern.txt +++ b/python/testData/codeInsight/controlflow/MatchStatementSingleClauseCapturePattern.txt @@ -1,8 +1,10 @@ 0(1) element: null 1(2) element: PyMatchStatement -2(3) WRITE ACCESS: x -3(4) element: PyExpressionStatement -4(5) READ ACCESS: y -5(6) element: PyExpressionStatement -6(7) READ ACCESS: z -7() element: null \ No newline at end of file +2(3,6) WRITE ACCESS: x +3(4) element: PyStatementList +4(5) element: PyExpressionStatement +5(7) READ ACCESS: y +6(7) ASSERTTYPE ACCESS: null +7(8) element: PyExpressionStatement +8(9) READ ACCESS: z +9() element: null \ No newline at end of file diff --git a/python/testData/codeInsight/controlflow/MatchStatementSingleClauseClassPattern.txt b/python/testData/codeInsight/controlflow/MatchStatementSingleClauseClassPattern.txt index 7f9b6964b95f..500f7308ec95 100644 --- a/python/testData/codeInsight/controlflow/MatchStatementSingleClauseClassPattern.txt +++ b/python/testData/codeInsight/controlflow/MatchStatementSingleClauseClassPattern.txt @@ -1,18 +1,19 @@ 0(1) element: null 1(2) element: PyMatchStatement 2(3) refutable pattern: Class(1, attr=foo.bar) -3(4,14) READ ACCESS: Class -4(5,14) refutable pattern: 1 +3(4,15) READ ACCESS: Class +4(5,15) refutable pattern: 1 5(6) matched pattern: 1 -6(7,14) refutable pattern: attr=foo.bar +6(7,15) refutable pattern: attr=foo.bar 7(8) refutable pattern: foo.bar -8(9,14) READ ACCESS: foo +8(9,15) READ ACCESS: foo 9(10) matched pattern: foo.bar 10(11) matched pattern: attr=foo.bar 11(12) matched pattern: Class(1, attr=foo.bar) -12(13) element: PyExpressionStatement -13(15) READ ACCESS: x -14(15) ASSERTTYPE ACCESS: null -15(16) element: PyExpressionStatement -16(17) READ ACCESS: y -17() element: null \ No newline at end of file +12(13) element: PyStatementList +13(14) element: PyExpressionStatement +14(16) READ ACCESS: x +15(16) ASSERTTYPE ACCESS: null +16(17) element: PyExpressionStatement +17(18) READ ACCESS: y +18() element: null \ No newline at end of file diff --git a/python/testData/codeInsight/controlflow/MatchStatementSingleClauseConjunctionGuard.txt b/python/testData/codeInsight/controlflow/MatchStatementSingleClauseConjunctionGuard.txt index 9de7a323d9f6..777c39ebd298 100644 --- a/python/testData/codeInsight/controlflow/MatchStatementSingleClauseConjunctionGuard.txt +++ b/python/testData/codeInsight/controlflow/MatchStatementSingleClauseConjunctionGuard.txt @@ -1,16 +1,17 @@ 0(1) element: null 1(2) element: PyMatchStatement -2(3) WRITE ACCESS: x +2(3,13) WRITE ACCESS: x 3(4) element: PyBinaryExpression 4(5,6) READ ACCESS: x -5(12) element: null. Condition: x > 0:false +5(13) element: null. Condition: x > 0:false 6(7) element: null. Condition: x > 0:true 7(8,9) READ ACCESS: x -8(12) element: null. Condition: x < 10:false +8(13) element: null. Condition: x < 10:false 9(10) element: null. Condition: x < 10:true -10(11) element: PyExpressionStatement -11(13) READ ACCESS: y -12(13) ASSERTTYPE ACCESS: null -13(14) element: PyExpressionStatement -14(15) READ ACCESS: z -15() element: null \ No newline at end of file +10(11) element: PyStatementList +11(12) element: PyExpressionStatement +12(14) READ ACCESS: y +13(14) ASSERTTYPE ACCESS: null +14(15) element: PyExpressionStatement +15(16) READ ACCESS: z +16() element: null \ No newline at end of file diff --git a/python/testData/codeInsight/controlflow/MatchStatementSingleClauseDisjunctionConjunctionGuard.txt b/python/testData/codeInsight/controlflow/MatchStatementSingleClauseDisjunctionConjunctionGuard.txt index 4a2333be4b64..99ba2e70e6f9 100644 --- a/python/testData/codeInsight/controlflow/MatchStatementSingleClauseDisjunctionConjunctionGuard.txt +++ b/python/testData/codeInsight/controlflow/MatchStatementSingleClauseDisjunctionConjunctionGuard.txt @@ -1,20 +1,21 @@ 0(1) element: null 1(2) element: PyMatchStatement -2(3) WRITE ACCESS: x +2(3,17) WRITE ACCESS: x 3(4) element: PyBinaryExpression 4(5,6) READ ACCESS: x -5(16) element: null. Condition: x % 4 == 0:false +5(17) element: null. Condition: x % 4 == 0:false 6(7) element: null. Condition: x % 4 == 0:true 7(8) element: PyBinaryExpression 8(9,10) READ ACCESS: x 9(11) element: null. Condition: x % 400 == 0:false 10(14) element: null. Condition: x % 400 == 0:true 11(12,13) READ ACCESS: x -12(16) element: null. Condition: x % 100 != 0:false +12(17) element: null. Condition: x % 100 != 0:false 13(14) element: null. Condition: x % 100 != 0:true -14(15) element: PyExpressionStatement -15(17) READ ACCESS: y -16(17) ASSERTTYPE ACCESS: null -17(18) element: PyExpressionStatement -18(19) READ ACCESS: z -19() element: null \ No newline at end of file +14(15) element: PyStatementList +15(16) element: PyExpressionStatement +16(18) READ ACCESS: y +17(18) ASSERTTYPE ACCESS: null +18(19) element: PyExpressionStatement +19(20) READ ACCESS: z +20() element: null \ No newline at end of file diff --git a/python/testData/codeInsight/controlflow/MatchStatementSingleClauseDisjunctionGuard.txt b/python/testData/codeInsight/controlflow/MatchStatementSingleClauseDisjunctionGuard.txt index 69e868119e90..52e9eafd4f50 100644 --- a/python/testData/codeInsight/controlflow/MatchStatementSingleClauseDisjunctionGuard.txt +++ b/python/testData/codeInsight/controlflow/MatchStatementSingleClauseDisjunctionGuard.txt @@ -1,16 +1,17 @@ 0(1) element: null 1(2) element: PyMatchStatement -2(3) WRITE ACCESS: x +2(3,13) WRITE ACCESS: x 3(4) element: PyBinaryExpression 4(5,6) READ ACCESS: x 5(7) element: null. Condition: x > 0:false 6(10) element: null. Condition: x > 0:true 7(8,9) READ ACCESS: x -8(12) element: null. Condition: x < 0:false +8(13) element: null. Condition: x < 0:false 9(10) element: null. Condition: x < 0:true -10(11) element: PyExpressionStatement -11(13) READ ACCESS: y -12(13) ASSERTTYPE ACCESS: null -13(14) element: PyExpressionStatement -14(15) READ ACCESS: z -15() element: null \ No newline at end of file +10(11) element: PyStatementList +11(12) element: PyExpressionStatement +12(14) READ ACCESS: y +13(14) ASSERTTYPE ACCESS: null +14(15) element: PyExpressionStatement +15(16) READ ACCESS: z +16() element: null \ No newline at end of file diff --git a/python/testData/codeInsight/controlflow/MatchStatementSingleClauseDoubleStarPatternIsIrrefutable.txt b/python/testData/codeInsight/controlflow/MatchStatementSingleClauseDoubleStarPatternIsIrrefutable.txt index a517d10a6fca..2c79aa1ad5cf 100644 --- a/python/testData/codeInsight/controlflow/MatchStatementSingleClauseDoubleStarPatternIsIrrefutable.txt +++ b/python/testData/codeInsight/controlflow/MatchStatementSingleClauseDoubleStarPatternIsIrrefutable.txt @@ -1,17 +1,19 @@ 0(1) element: null 1(2) element: PyMatchStatement -2(3,13) refutable pattern: {"foo": 1, **x} -3(4,13) refutable pattern: "foo": 1 -4(5,13) refutable pattern: "foo" +2(3,15) refutable pattern: {"foo": 1, **x} +3(4,15) refutable pattern: "foo": 1 +4(5,15) refutable pattern: "foo" 5(6) matched pattern: "foo" -6(7,13) refutable pattern: 1 +6(7,15) refutable pattern: 1 7(8) matched pattern: 1 8(9) matched pattern: "foo": 1 -9(10) WRITE ACCESS: x -10(11) matched pattern: {"foo": 1, **x} -11(12) element: PyExpressionStatement -12(14) READ ACCESS: y -13(14) ASSERTTYPE ACCESS: null -14(15) element: PyExpressionStatement -15(16) READ ACCESS: z -16() element: null \ No newline at end of file +9(10,15) element: PyDoubleStarPattern +10(11,15) WRITE ACCESS: x +11(12) matched pattern: {"foo": 1, **x} +12(13) element: PyStatementList +13(14) element: PyExpressionStatement +14(16) READ ACCESS: y +15(16) ASSERTTYPE ACCESS: null +16(17) element: PyExpressionStatement +17(18) READ ACCESS: z +18() element: null \ No newline at end of file diff --git a/python/testData/codeInsight/controlflow/MatchStatementSingleClauseGuardWithNonTopLevelDisjunction.txt b/python/testData/codeInsight/controlflow/MatchStatementSingleClauseGuardWithNonTopLevelDisjunction.txt index c7040a002d84..6385736f7557 100644 --- a/python/testData/codeInsight/controlflow/MatchStatementSingleClauseGuardWithNonTopLevelDisjunction.txt +++ b/python/testData/codeInsight/controlflow/MatchStatementSingleClauseGuardWithNonTopLevelDisjunction.txt @@ -1,23 +1,24 @@ 0(1) element: null 1(2) element: PyMatchStatement -2(3,19) refutable pattern: [x1, x2, x3] -3(4) WRITE ACCESS: x1 -4(5) WRITE ACCESS: x2 -5(6) WRITE ACCESS: x3 +2(3,20) refutable pattern: [x1, x2, x3] +3(4,20) WRITE ACCESS: x1 +4(5,20) WRITE ACCESS: x2 +5(6,20) WRITE ACCESS: x3 6(7) matched pattern: [x1, x2, x3] 7(8) element: PyBinaryExpression 8(9,10) READ ACCESS: x1 9(11) element: null. Condition: x1:false 10(17) element: null. Condition: x1:true 11(12,13,14) READ ACCESS: x2 -12(19) element: null. Condition: x2:false +12(20) element: null. Condition: x2:false 13(17) element: null. Condition: x2:true 14(15,16) READ ACCESS: x3 -15(19) element: null. Condition: (x1 or x2) > x3:false +15(20) element: null. Condition: (x1 or x2) > x3:false 16(17) element: null. Condition: (x1 or x2) > x3:true -17(18) element: PyExpressionStatement -18(20) READ ACCESS: y -19(20) ASSERTTYPE ACCESS: null -20(21) element: PyExpressionStatement -21(22) READ ACCESS: z -22() element: null \ No newline at end of file +17(18) element: PyStatementList +18(19) element: PyExpressionStatement +19(21) READ ACCESS: y +20(21) ASSERTTYPE ACCESS: null +21(22) element: PyExpressionStatement +22(23) READ ACCESS: z +23() element: null \ No newline at end of file diff --git a/python/testData/codeInsight/controlflow/MatchStatementSingleClauseIrrefutableOrPatternCaptureVariantFirst.txt b/python/testData/codeInsight/controlflow/MatchStatementSingleClauseIrrefutableOrPatternCaptureVariantFirst.txt index f8ceeadbcd08..7d4f18e1d0db 100644 --- a/python/testData/codeInsight/controlflow/MatchStatementSingleClauseIrrefutableOrPatternCaptureVariantFirst.txt +++ b/python/testData/codeInsight/controlflow/MatchStatementSingleClauseIrrefutableOrPatternCaptureVariantFirst.txt @@ -1,14 +1,15 @@ 0(1) element: null 1(2) element: PyMatchStatement 2(3) refutable pattern: x | [x] -3(7) WRITE ACCESS: x -4(5,10) refutable pattern: [x] -5(6) WRITE ACCESS: x +3(4,7) WRITE ACCESS: x +4(5,11) refutable pattern: [x] +5(6,11) WRITE ACCESS: x 6(7) matched pattern: [x] 7(8) matched pattern: x | [x] -8(9) element: PyExpressionStatement -9(11) READ ACCESS: y -10(11) ASSERTTYPE ACCESS: null -11(12) element: PyExpressionStatement -12(13) READ ACCESS: z -13() element: null \ No newline at end of file +8(9) element: PyStatementList +9(10) element: PyExpressionStatement +10(12) READ ACCESS: y +11(12) ASSERTTYPE ACCESS: null +12(13) element: PyExpressionStatement +13(14) READ ACCESS: z +14() element: null \ No newline at end of file diff --git a/python/testData/codeInsight/controlflow/MatchStatementSingleClauseIrrefutableOrPatternCaptureVariantLast.txt b/python/testData/codeInsight/controlflow/MatchStatementSingleClauseIrrefutableOrPatternCaptureVariantLast.txt index 6a1ba7ad2083..fc48fde9b0ab 100644 --- a/python/testData/codeInsight/controlflow/MatchStatementSingleClauseIrrefutableOrPatternCaptureVariantLast.txt +++ b/python/testData/codeInsight/controlflow/MatchStatementSingleClauseIrrefutableOrPatternCaptureVariantLast.txt @@ -2,12 +2,14 @@ 1(2) element: PyMatchStatement 2(3) refutable pattern: [x] | x 3(4,6) refutable pattern: [x] -4(5) WRITE ACCESS: x +4(5,6) WRITE ACCESS: x 5(7) matched pattern: [x] -6(7) WRITE ACCESS: x +6(7,11) WRITE ACCESS: x 7(8) matched pattern: [x] | x -8(9) element: PyExpressionStatement -9(10) READ ACCESS: y -10(11) element: PyExpressionStatement -11(12) READ ACCESS: z -12() element: null \ No newline at end of file +8(9) element: PyStatementList +9(10) element: PyExpressionStatement +10(12) READ ACCESS: y +11(12) ASSERTTYPE ACCESS: null +12(13) element: PyExpressionStatement +13(14) READ ACCESS: z +14() element: null \ No newline at end of file diff --git a/python/testData/codeInsight/controlflow/MatchStatementSingleClauseLiteralPattern.txt b/python/testData/codeInsight/controlflow/MatchStatementSingleClauseLiteralPattern.txt index 97927b8fcdc1..5e17c0a72b2a 100644 --- a/python/testData/codeInsight/controlflow/MatchStatementSingleClauseLiteralPattern.txt +++ b/python/testData/codeInsight/controlflow/MatchStatementSingleClauseLiteralPattern.txt @@ -1,10 +1,11 @@ 0(1) element: null 1(2) element: PyMatchStatement -2(3,6) refutable pattern: 42 +2(3,7) refutable pattern: 42 3(4) matched pattern: 42 -4(5) element: PyExpressionStatement -5(7) READ ACCESS: y -6(7) ASSERTTYPE ACCESS: null -7(8) element: PyExpressionStatement -8(9) READ ACCESS: z -9() element: null \ No newline at end of file +4(5) element: PyStatementList +5(6) element: PyExpressionStatement +6(8) READ ACCESS: y +7(8) ASSERTTYPE ACCESS: null +8(9) element: PyExpressionStatement +9(10) READ ACCESS: z +10() element: null \ No newline at end of file diff --git a/python/testData/codeInsight/controlflow/MatchStatementSingleClauseMappingPattern.txt b/python/testData/codeInsight/controlflow/MatchStatementSingleClauseMappingPattern.txt index ed89c3d3f4e6..0a34eeb04a11 100644 --- a/python/testData/codeInsight/controlflow/MatchStatementSingleClauseMappingPattern.txt +++ b/python/testData/codeInsight/controlflow/MatchStatementSingleClauseMappingPattern.txt @@ -1,23 +1,24 @@ 0(1) element: null 1(2) element: PyMatchStatement -2(3,19) refutable pattern: {'foo': 1, 'bar': foo.bar} -3(4,19) refutable pattern: 'foo': 1 -4(5,19) refutable pattern: 'foo' +2(3,20) refutable pattern: {'foo': 1, 'bar': foo.bar} +3(4,20) refutable pattern: 'foo': 1 +4(5,20) refutable pattern: 'foo' 5(6) matched pattern: 'foo' -6(7,19) refutable pattern: 1 +6(7,20) refutable pattern: 1 7(8) matched pattern: 1 8(9) matched pattern: 'foo': 1 -9(10,19) refutable pattern: 'bar': foo.bar -10(11,19) refutable pattern: 'bar' +9(10,20) refutable pattern: 'bar': foo.bar +10(11,20) refutable pattern: 'bar' 11(12) matched pattern: 'bar' 12(13) refutable pattern: foo.bar -13(14,19) READ ACCESS: foo +13(14,20) READ ACCESS: foo 14(15) matched pattern: foo.bar 15(16) matched pattern: 'bar': foo.bar 16(17) matched pattern: {'foo': 1, 'bar': foo.bar} -17(18) element: PyExpressionStatement -18(20) READ ACCESS: x -19(20) ASSERTTYPE ACCESS: null -20(21) element: PyExpressionStatement -21(22) READ ACCESS: y -22() element: null \ No newline at end of file +17(18) element: PyStatementList +18(19) element: PyExpressionStatement +19(21) READ ACCESS: x +20(21) ASSERTTYPE ACCESS: null +21(22) element: PyExpressionStatement +22(23) READ ACCESS: y +23() element: null \ No newline at end of file diff --git a/python/testData/codeInsight/controlflow/MatchStatementSingleClauseNamedSingleStarPatternIsIrrefutable.txt b/python/testData/codeInsight/controlflow/MatchStatementSingleClauseNamedSingleStarPatternIsIrrefutable.txt index 4de8f4518674..793c8d9dbfd0 100644 --- a/python/testData/codeInsight/controlflow/MatchStatementSingleClauseNamedSingleStarPatternIsIrrefutable.txt +++ b/python/testData/codeInsight/controlflow/MatchStatementSingleClauseNamedSingleStarPatternIsIrrefutable.txt @@ -1,13 +1,15 @@ 0(1) element: null 1(2) element: PyMatchStatement -2(3,9) refutable pattern: [1, *x] -3(4,9) refutable pattern: 1 +2(3,11) refutable pattern: [1, *x] +3(4,11) refutable pattern: 1 4(5) matched pattern: 1 -5(6) WRITE ACCESS: x -6(7) matched pattern: [1, *x] -7(8) element: PyExpressionStatement -8(10) READ ACCESS: y -9(10) ASSERTTYPE ACCESS: null -10(11) element: PyExpressionStatement -11(12) READ ACCESS: z -12() element: null \ No newline at end of file +5(6,11) element: PySingleStarPattern +6(7,11) WRITE ACCESS: x +7(8) matched pattern: [1, *x] +8(9) element: PyStatementList +9(10) element: PyExpressionStatement +10(12) READ ACCESS: y +11(12) ASSERTTYPE ACCESS: null +12(13) element: PyExpressionStatement +13(14) READ ACCESS: z +14() element: null \ No newline at end of file diff --git a/python/testData/codeInsight/controlflow/MatchStatementSingleClauseNestedOrPatterns.txt b/python/testData/codeInsight/controlflow/MatchStatementSingleClauseNestedOrPatterns.txt index a0ebf91193ff..d1195b82dd0a 100644 --- a/python/testData/codeInsight/controlflow/MatchStatementSingleClauseNestedOrPatterns.txt +++ b/python/testData/codeInsight/controlflow/MatchStatementSingleClauseNestedOrPatterns.txt @@ -6,13 +6,14 @@ 5(6) refutable pattern: 2 | 3 6(7,8) refutable pattern: 2 7(10) matched pattern: 2 -8(9,14) refutable pattern: 3 +8(9,15) refutable pattern: 3 9(10) matched pattern: 3 10(11) matched pattern: 2 | 3 11(12) matched pattern: 1 | (2 | 3) -12(13) element: PyExpressionStatement -13(15) READ ACCESS: x -14(15) ASSERTTYPE ACCESS: null -15(16) element: PyExpressionStatement -16(17) READ ACCESS: y -17() element: null \ No newline at end of file +12(13) element: PyStatementList +13(14) element: PyExpressionStatement +14(16) READ ACCESS: x +15(16) ASSERTTYPE ACCESS: null +16(17) element: PyExpressionStatement +17(18) READ ACCESS: y +18() element: null \ No newline at end of file diff --git a/python/testData/codeInsight/controlflow/MatchStatementSingleClauseParenthesizedCapturePattern.txt b/python/testData/codeInsight/controlflow/MatchStatementSingleClauseParenthesizedCapturePattern.txt index a637619e16b2..aac2a5b8002b 100644 --- a/python/testData/codeInsight/controlflow/MatchStatementSingleClauseParenthesizedCapturePattern.txt +++ b/python/testData/codeInsight/controlflow/MatchStatementSingleClauseParenthesizedCapturePattern.txt @@ -1,8 +1,10 @@ 0(1) element: null 1(2) element: PyMatchStatement -2(3) WRITE ACCESS: x -3(4) element: PyExpressionStatement -4(5) READ ACCESS: y -5(6) element: PyExpressionStatement -6(7) READ ACCESS: z -7() element: null \ No newline at end of file +2(3,6) WRITE ACCESS: x +3(4) element: PyStatementList +4(5) element: PyExpressionStatement +5(7) READ ACCESS: y +6(7) ASSERTTYPE ACCESS: null +7(8) element: PyExpressionStatement +8(9) READ ACCESS: z +9() element: null \ No newline at end of file diff --git a/python/testData/codeInsight/controlflow/MatchStatementSingleClauseRefutableOrPattern.txt b/python/testData/codeInsight/controlflow/MatchStatementSingleClauseRefutableOrPattern.txt index a2db65a4ba40..ab93bdbb8fc8 100644 --- a/python/testData/codeInsight/controlflow/MatchStatementSingleClauseRefutableOrPattern.txt +++ b/python/testData/codeInsight/controlflow/MatchStatementSingleClauseRefutableOrPattern.txt @@ -2,17 +2,18 @@ 1(2) element: PyMatchStatement 2(3) refutable pattern: [x] | (foo.bar as x) 3(4,6) refutable pattern: [x] -4(5) WRITE ACCESS: x +4(5,6) WRITE ACCESS: x 5(11) matched pattern: [x] 6(7) element: PyAsPattern 7(8) refutable pattern: foo.bar -8(9,14) READ ACCESS: foo +8(9,15) READ ACCESS: foo 9(10) matched pattern: foo.bar 10(11) WRITE ACCESS: x 11(12) matched pattern: [x] | (foo.bar as x) -12(13) element: PyExpressionStatement -13(15) READ ACCESS: y -14(15) ASSERTTYPE ACCESS: null -15(16) element: PyExpressionStatement -16(17) READ ACCESS: z -17() element: null \ No newline at end of file +12(13) element: PyStatementList +13(14) element: PyExpressionStatement +14(16) READ ACCESS: y +15(16) ASSERTTYPE ACCESS: null +16(17) element: PyExpressionStatement +17(18) READ ACCESS: z +18() element: null \ No newline at end of file diff --git a/python/testData/codeInsight/controlflow/MatchStatementSingleClauseRefutableOrPatternWithNonBindingVariants.txt b/python/testData/codeInsight/controlflow/MatchStatementSingleClauseRefutableOrPatternWithNonBindingVariants.txt index 8d8226e4f0ea..2f2dbd8a5113 100644 --- a/python/testData/codeInsight/controlflow/MatchStatementSingleClauseRefutableOrPatternWithNonBindingVariants.txt +++ b/python/testData/codeInsight/controlflow/MatchStatementSingleClauseRefutableOrPatternWithNonBindingVariants.txt @@ -3,12 +3,13 @@ 2(3) refutable pattern: [] | 42 3(4,5) refutable pattern: [] 4(7) matched pattern: [] -5(6,10) refutable pattern: 42 +5(6,11) refutable pattern: 42 6(7) matched pattern: 42 7(8) matched pattern: [] | 42 -8(9) element: PyExpressionStatement -9(11) READ ACCESS: y -10(11) ASSERTTYPE ACCESS: null -11(12) element: PyExpressionStatement -12(13) READ ACCESS: z -13() element: null \ No newline at end of file +8(9) element: PyStatementList +9(10) element: PyExpressionStatement +10(12) READ ACCESS: y +11(12) ASSERTTYPE ACCESS: null +12(13) element: PyExpressionStatement +13(14) READ ACCESS: z +14() element: null \ No newline at end of file diff --git a/python/testData/codeInsight/controlflow/MatchStatementSingleClauseRefutableOrPatternWithWildcard.txt b/python/testData/codeInsight/controlflow/MatchStatementSingleClauseRefutableOrPatternWithWildcard.txt index f3243c8d7f65..032385a96d21 100644 --- a/python/testData/codeInsight/controlflow/MatchStatementSingleClauseRefutableOrPatternWithWildcard.txt +++ b/python/testData/codeInsight/controlflow/MatchStatementSingleClauseRefutableOrPatternWithWildcard.txt @@ -1,13 +1,14 @@ 0(1) element: null 1(2) element: PyMatchStatement 2(3) refutable pattern: _ | 42 -3(6) element: PyWildcardPattern -4(5,9) refutable pattern: 42 +3(4,6) element: PyWildcardPattern +4(5,10) refutable pattern: 42 5(6) matched pattern: 42 6(7) matched pattern: _ | 42 -7(8) element: PyExpressionStatement -8(10) READ ACCESS: y -9(10) ASSERTTYPE ACCESS: null -10(11) element: PyExpressionStatement -11(12) READ ACCESS: z -12() element: null \ No newline at end of file +7(8) element: PyStatementList +8(9) element: PyExpressionStatement +9(11) READ ACCESS: y +10(11) ASSERTTYPE ACCESS: null +11(12) element: PyExpressionStatement +12(13) READ ACCESS: z +13() element: null \ No newline at end of file diff --git a/python/testData/codeInsight/controlflow/MatchStatementSingleClauseRefutablePatternAndConjunctionGuard.txt b/python/testData/codeInsight/controlflow/MatchStatementSingleClauseRefutablePatternAndConjunctionGuard.txt index f52856307bc1..88cef6451dea 100644 --- a/python/testData/codeInsight/controlflow/MatchStatementSingleClauseRefutablePatternAndConjunctionGuard.txt +++ b/python/testData/codeInsight/controlflow/MatchStatementSingleClauseRefutablePatternAndConjunctionGuard.txt @@ -1,18 +1,19 @@ 0(1) element: null 1(2) element: PyMatchStatement -2(3,14) refutable pattern: [x] -3(4) WRITE ACCESS: x +2(3,15) refutable pattern: [x] +3(4,15) WRITE ACCESS: x 4(5) matched pattern: [x] 5(6) element: PyBinaryExpression 6(7,8) READ ACCESS: x -7(14) element: null. Condition: x > 0:false +7(15) element: null. Condition: x > 0:false 8(9) element: null. Condition: x > 0:true 9(10,11) READ ACCESS: x -10(14) element: null. Condition: x % 2 == 0:false +10(15) element: null. Condition: x % 2 == 0:false 11(12) element: null. Condition: x % 2 == 0:true -12(13) element: PyExpressionStatement -13(15) READ ACCESS: y -14(15) ASSERTTYPE ACCESS: null -15(16) element: PyExpressionStatement -16(17) READ ACCESS: z -17() element: null \ No newline at end of file +12(13) element: PyStatementList +13(14) element: PyExpressionStatement +14(16) READ ACCESS: y +15(16) ASSERTTYPE ACCESS: null +16(17) element: PyExpressionStatement +17(18) READ ACCESS: z +18() element: null \ No newline at end of file diff --git a/python/testData/codeInsight/controlflow/MatchStatementSingleClauseSequencePattern.txt b/python/testData/codeInsight/controlflow/MatchStatementSingleClauseSequencePattern.txt index d5cebf47c1e8..3c15dddfcea2 100644 --- a/python/testData/codeInsight/controlflow/MatchStatementSingleClauseSequencePattern.txt +++ b/python/testData/codeInsight/controlflow/MatchStatementSingleClauseSequencePattern.txt @@ -1,15 +1,16 @@ 0(1) element: null 1(2) element: PyMatchStatement -2(3,11) refutable pattern: [1, foo.bar] -3(4,11) refutable pattern: 1 +2(3,12) refutable pattern: [1, foo.bar] +3(4,12) refutable pattern: 1 4(5) matched pattern: 1 5(6) refutable pattern: foo.bar -6(7,11) READ ACCESS: foo +6(7,12) READ ACCESS: foo 7(8) matched pattern: foo.bar 8(9) matched pattern: [1, foo.bar] -9(10) element: PyExpressionStatement -10(12) READ ACCESS: x -11(12) ASSERTTYPE ACCESS: null -12(13) element: PyExpressionStatement -13(14) READ ACCESS: y -14() element: null \ No newline at end of file +9(10) element: PyStatementList +10(11) element: PyExpressionStatement +11(13) READ ACCESS: x +12(13) ASSERTTYPE ACCESS: null +13(14) element: PyExpressionStatement +14(15) READ ACCESS: y +15() element: null \ No newline at end of file diff --git a/python/testData/codeInsight/controlflow/MatchStatementSingleClauseSequencePatternWithSingleOrPattern.txt b/python/testData/codeInsight/controlflow/MatchStatementSingleClauseSequencePatternWithSingleOrPattern.txt index 07c51ff373a7..9c2d47a51e3f 100644 --- a/python/testData/codeInsight/controlflow/MatchStatementSingleClauseSequencePatternWithSingleOrPattern.txt +++ b/python/testData/codeInsight/controlflow/MatchStatementSingleClauseSequencePatternWithSingleOrPattern.txt @@ -1,15 +1,16 @@ 0(1) element: null 1(2) element: PyMatchStatement -2(3,11) refutable pattern: [1 | x] +2(3,12) refutable pattern: [1 | x] 3(4) refutable pattern: 1 | x 4(5,6) refutable pattern: 1 5(7) matched pattern: 1 -6(7) WRITE ACCESS: x +6(7,12) WRITE ACCESS: x 7(8) matched pattern: 1 | x 8(9) matched pattern: [1 | x] -9(10) element: PyExpressionStatement -10(12) READ ACCESS: y -11(12) ASSERTTYPE ACCESS: null -12(13) element: PyExpressionStatement -13(14) READ ACCESS: z -14() element: null \ No newline at end of file +9(10) element: PyStatementList +10(11) element: PyExpressionStatement +11(13) READ ACCESS: y +12(13) ASSERTTYPE ACCESS: null +13(14) element: PyExpressionStatement +14(15) READ ACCESS: z +15() element: null \ No newline at end of file diff --git a/python/testData/codeInsight/controlflow/MatchStatementSingleClauseTrivialGuard.txt b/python/testData/codeInsight/controlflow/MatchStatementSingleClauseTrivialGuard.txt index ecf5128dd829..3c1a65e41b24 100644 --- a/python/testData/codeInsight/controlflow/MatchStatementSingleClauseTrivialGuard.txt +++ b/python/testData/codeInsight/controlflow/MatchStatementSingleClauseTrivialGuard.txt @@ -1,12 +1,13 @@ 0(1) element: null 1(2) element: PyMatchStatement -2(3) WRITE ACCESS: x +2(3,9) WRITE ACCESS: x 3(4,5) READ ACCESS: x -4(8) element: null. Condition: x > 0:false +4(9) element: null. Condition: x > 0:false 5(6) element: null. Condition: x > 0:true -6(7) element: PyExpressionStatement -7(9) READ ACCESS: y -8(9) ASSERTTYPE ACCESS: null -9(10) element: PyExpressionStatement -10(11) READ ACCESS: z -11() element: null \ No newline at end of file +6(7) element: PyStatementList +7(8) element: PyExpressionStatement +8(10) READ ACCESS: y +9(10) ASSERTTYPE ACCESS: null +10(11) element: PyExpressionStatement +11(12) READ ACCESS: z +12() element: null \ No newline at end of file diff --git a/python/testData/codeInsight/controlflow/MatchStatementSingleClauseWildcardPattern.txt b/python/testData/codeInsight/controlflow/MatchStatementSingleClauseWildcardPattern.txt index 7e15115063fa..35aa3c5fbb9c 100644 --- a/python/testData/codeInsight/controlflow/MatchStatementSingleClauseWildcardPattern.txt +++ b/python/testData/codeInsight/controlflow/MatchStatementSingleClauseWildcardPattern.txt @@ -1,8 +1,10 @@ 0(1) element: null 1(2) element: PyMatchStatement -2(3) element: PyWildcardPattern -3(4) element: PyExpressionStatement -4(5) READ ACCESS: y -5(6) element: PyExpressionStatement -6(7) READ ACCESS: z -7() element: null \ No newline at end of file +2(3,6) element: PyWildcardPattern +3(4) element: PyStatementList +4(5) element: PyExpressionStatement +5(7) READ ACCESS: y +6(7) ASSERTTYPE ACCESS: null +7(8) element: PyExpressionStatement +8(9) READ ACCESS: z +9() element: null \ No newline at end of file diff --git a/python/testData/codeInsight/controlflow/MatchStatementSingleClauseWildcardSingleStarPatternIsIrrefutable.txt b/python/testData/codeInsight/controlflow/MatchStatementSingleClauseWildcardSingleStarPatternIsIrrefutable.txt index f9bb81947cf0..f83030043cca 100644 --- a/python/testData/codeInsight/controlflow/MatchStatementSingleClauseWildcardSingleStarPatternIsIrrefutable.txt +++ b/python/testData/codeInsight/controlflow/MatchStatementSingleClauseWildcardSingleStarPatternIsIrrefutable.txt @@ -1,13 +1,15 @@ 0(1) element: null 1(2) element: PyMatchStatement -2(3,9) refutable pattern: [1, *_] -3(4,9) refutable pattern: 1 +2(3,11) refutable pattern: [1, *_] +3(4,11) refutable pattern: 1 4(5) matched pattern: 1 -5(6) element: PyWildcardPattern -6(7) matched pattern: [1, *_] -7(8) element: PyExpressionStatement -8(10) READ ACCESS: y -9(10) ASSERTTYPE ACCESS: null -10(11) element: PyExpressionStatement -11(12) READ ACCESS: z -12() element: null \ No newline at end of file +5(6,11) element: PySingleStarPattern +6(7,11) element: PyWildcardPattern +7(8) matched pattern: [1, *_] +8(9) element: PyStatementList +9(10) element: PyExpressionStatement +10(12) READ ACCESS: y +11(12) ASSERTTYPE ACCESS: null +12(13) element: PyExpressionStatement +13(14) READ ACCESS: z +14() element: null \ No newline at end of file diff --git a/python/testData/codeInsight/controlflow/MatchStatementTwoClausesCapturePatternFirst.txt b/python/testData/codeInsight/controlflow/MatchStatementTwoClausesCapturePatternFirst.txt index f1106e0d6368..fa8b0adbbae4 100644 --- a/python/testData/codeInsight/controlflow/MatchStatementTwoClausesCapturePatternFirst.txt +++ b/python/testData/codeInsight/controlflow/MatchStatementTwoClausesCapturePatternFirst.txt @@ -1,13 +1,16 @@ 0(1) element: null 1(2) element: PyMatchStatement -2(3) WRITE ACCESS: x -3(4) element: PyExpressionStatement -4(10) READ ACCESS: y -5(6,9) refutable pattern: 42 -6(7) matched pattern: 42 -7(8) element: PyExpressionStatement -8(10) READ ACCESS: y -9(10) ASSERTTYPE ACCESS: null +2(3,6) WRITE ACCESS: x +3(4) element: PyStatementList +4(5) element: PyExpressionStatement +5(13) READ ACCESS: y +6(7,12) refutable pattern: 42 +7(8) matched pattern: 42 +8(9) ASSERTTYPE ACCESS: null +9(10) element: PyStatementList 10(11) element: PyExpressionStatement -11(12) READ ACCESS: z -12() element: null \ No newline at end of file +11(13) READ ACCESS: y +12(13) ASSERTTYPE ACCESS: null +13(14) element: PyExpressionStatement +14(15) READ ACCESS: z +15() element: null \ No newline at end of file diff --git a/python/testData/codeInsight/controlflow/MatchStatementTwoClausesCapturePatternLast.txt b/python/testData/codeInsight/controlflow/MatchStatementTwoClausesCapturePatternLast.txt index f665acbbbfe4..abbc371b0d25 100644 --- a/python/testData/codeInsight/controlflow/MatchStatementTwoClausesCapturePatternLast.txt +++ b/python/testData/codeInsight/controlflow/MatchStatementTwoClausesCapturePatternLast.txt @@ -1,12 +1,15 @@ 0(1) element: null 1(2) element: PyMatchStatement -2(3,6) refutable pattern: 42 +2(3,7) refutable pattern: 42 3(4) matched pattern: 42 -4(5) element: PyExpressionStatement -5(9) READ ACCESS: y -6(7) WRITE ACCESS: x -7(8) element: PyExpressionStatement -8(9) READ ACCESS: y +4(5) element: PyStatementList +5(6) element: PyExpressionStatement +6(12) READ ACCESS: y +7(8,11) WRITE ACCESS: x +8(9) element: PyStatementList 9(10) element: PyExpressionStatement -10(11) READ ACCESS: z -11() element: null \ No newline at end of file +10(12) READ ACCESS: y +11(12) ASSERTTYPE ACCESS: null +12(13) element: PyExpressionStatement +13(14) READ ACCESS: z +14() element: null \ No newline at end of file diff --git a/python/testData/codeInsight/controlflow/WhileInsideIfTrue.txt b/python/testData/codeInsight/controlflow/WhileInsideIfTrue.txt index cf90e225ff88..8f489f25bb8b 100644 --- a/python/testData/codeInsight/controlflow/WhileInsideIfTrue.txt +++ b/python/testData/codeInsight/controlflow/WhileInsideIfTrue.txt @@ -1,16 +1,17 @@ 0(1) element: null 1(2) element: PyIfStatement 2(3,4) READ ACCESS: True -3() element: null. Condition: True:false +3(13) element: null. Condition: True:false 4(5) element: null. Condition: True:true 5(6) ASSERTTYPE ACCESS: True 6(7) element: PyStatementList 7(8) element: PyWhileStatement 8(9,10) READ ACCESS: expr -9(15) element: null. Condition: expr:false +9(16) element: null. Condition: expr:false 10(11) element: null. Condition: expr:true 11(12) element: PyStatementList -12(15) element: PyBreakStatement -13(14) element: PyStatementList -14(15) element: PyPrintStatement -15() element: null \ No newline at end of file +12(16) element: PyBreakStatement +13(14) ASSERTTYPE ACCESS: null +14(15) element: PyStatementList +15(16) element: PyPrintStatement +16() element: null \ No newline at end of file diff --git a/python/testData/inspections/PyUnreachableCodeInspection/UnreachablePatternAfterIrrefutableCaseClause.py b/python/testData/inspections/PyUnreachableCodeInspection/UnreachablePatternAfterIrrefutableCaseClause.py index 8bf2c1817320..022e8c6524dc 100644 --- a/python/testData/inspections/PyUnreachableCodeInspection/UnreachablePatternAfterIrrefutableCaseClause.py +++ b/python/testData/inspections/PyUnreachableCodeInspection/UnreachablePatternAfterIrrefutableCaseClause.py @@ -1,5 +1,5 @@ match 42: case x: pass - case 42: + case 42: pass \ No newline at end of file diff --git a/python/testData/inspections/PyUnreachableCodeInspection/UnreachablePatternAfterIrrefutableOrPatternAlternative.py b/python/testData/inspections/PyUnreachableCodeInspection/UnreachablePatternAfterIrrefutableOrPatternAlternative.py index 327f6c84dca4..50da3b524455 100644 --- a/python/testData/inspections/PyUnreachableCodeInspection/UnreachablePatternAfterIrrefutableOrPatternAlternative.py +++ b/python/testData/inspections/PyUnreachableCodeInspection/UnreachablePatternAfterIrrefutableOrPatternAlternative.py @@ -1,3 +1,3 @@ match 42: - case x | 42: + case x | 42: pass diff --git a/python/testSrc/com/jetbrains/python/inspections/PyUnreachableCodeInspectionTest.java b/python/testSrc/com/jetbrains/python/inspections/PyUnreachableCodeInspectionTest.java index a4b2b4adfd1c..d9a441ebb2bd 100644 --- a/python/testSrc/com/jetbrains/python/inspections/PyUnreachableCodeInspectionTest.java +++ b/python/testSrc/com/jetbrains/python/inspections/PyUnreachableCodeInspectionTest.java @@ -24,7 +24,38 @@ public class PyUnreachableCodeInspectionTest extends PyInspectionTestCase { public void testUnreachable() { runWithLanguageLevel(LanguageLevel.PYTHON26, () -> doTest()); } - + + // PY-81676 + public void testUnreachableBranchesAreStillConnected() { + // This test ensures that the unreachable branch still + // has some edges to and from the main CFG, which allows us + // to make an exception for assert_never or assert False + doTestByText(""" +from typing import assert_never + +if False: + print("actually unreachable") + print("actually unreachable") + +if False: + assert False + print("actually unreachable") + print("actually unreachable") + +def f(obj: int) -> None: + match scalar: + case x: + print("everything") + case _: + print("actually unreachable") + print("actually unreachable") + case _ as unreachable: + assert_never(unreachable) + print("actually unreachable") + print("actually unreachable") + """); + } + // PY-82712 public void testIfInsideTryExcept() { doTestByText(""" @@ -129,6 +160,37 @@ def f(): """); } + // PY-81676 + public void testTerminatingInBranch() { + doTestByText(""" +from enum import Enum +from typing import assert_never + +class Foo(Enum): + A = 0 + B = 1 + +def f1(foo: Foo) -> None: + if foo is Foo.A: + ... + elif foo is Foo.B: + ... + else: + assert_never(foo) + print("unreachable"); + +def f2(foo: Foo) -> None: + match foo: + case Foo.A: + ... + case Foo.B: + ... + case _: + assert_never(foo) + print("unreachable"); + """); + } + // PY-81674 public void testConsecutiveTerminating() { doTestByText(""" @@ -161,7 +223,7 @@ class Foo(Enum): A = 0 B = 1 -print(exit()) +print(exit()) def unreachable(foo: Foo) -> None: if foo is Foo.A: