void (@NotNull PyPattern pattern) { boolean isRefutable = !pattern.isIrrefutable(); if (isRefutable) { RefutablePatternInstruction instruction = new RefutablePatternInstruction(myBuilder, pattern, false); myBuilder.addNodeAndCheckPending(instruction); myBuilder.addPendingEdge(pattern, instruction); } if (pattern instanceof PyWildcardPattern) { myBuilder.startNode(pattern); } else if (pattern instanceof PyOrPattern) { List<PyPattern> alternatives = ((PyOrPattern)pattern).getAlternatives(); PyPattern lastAlternative = ContainerUtil.getLastItem(alternatives); for (PyPattern alternative : alternatives) { processPattern(alternative); if (alternative != lastAlternative) { myBuilder.addPendingEdge(alternative, myBuilder.prevInstruction); myBuilder.prevInstruction = null; } retargetOutgoingEdges(alternative, (pendingScope, instruction) -> { if (instruction instanceof RefutablePatternInstruction && !((RefutablePatternInstruction)instruction).isMatched()) { // Pattern has failed, jump to the next alternative if any return alternative; } // Pattern succeeded, jump out of OR-pattern. It can be either a refutable pattern or a capture/wildcard node. else { return pattern; } }); } } else { pattern.acceptChildren(new PyElementVisitor() { @Override public void visitPyReferenceExpression(@NotNull PyReferenceExpression node) { myBaseVisitor.visitPyReferenceExpression(node); } @Override public void visitPyTargetExpression(@NotNull PyTargetExpression node) { myBaseVisitor.visitPyTargetExpression(node); } @Override public void visitPyPattern(@NotNull PyPattern node) { processPattern(node); retargetOutgoingPatternEdges(pattern, (oldScope, instr) -> { // Mismatch in a non-OR pattern means mismatch of the containing pattern as well return instr.isMatched() ? oldScope : pattern; }); } @Override public void visitPyPatternArgumentList(@NotNull PyPatternArgumentList node) { node.acceptChildren(this); } }); } if (isRefutable) { myBuilder.addNode(new RefutablePatternInstruction(myBuilder, pattern, true)); } }