void (@NotNull PyOrPattern orPattern) { List<PyPattern> alternatives = orPattern.getAlternatives(); PyPattern lastAlternative = alternatives.get(alternatives.size() - 1); Map<PyPattern, Set<String>> patternToBoundNames = new HashMap<>(); Set<String> allBoundNames = new HashSet<>(); for (PyPattern alternative : alternatives) { Set<String> boundNames = SyntaxTraverser.psiTraverser(alternative) .filter(PyTargetExpression.class) .map(PyTargetExpression::getName) .toSet(); patternToBoundNames.put(alternative, boundNames); allBoundNames.addAll(boundNames); if (alternative != lastAlternative && alternative.isIrrefutable()) { markError(alternative, PyPsiBundle.message("ANN.patterns.pattern.makes.remaining.alternatives.unreachable")); } } for (Map.Entry<PyPattern, Set<String>> entry : patternToBoundNames.entrySet()) { Set<String> boundNames = entry.getValue(); if (!boundNames.equals(allBoundNames)) { Collection<String> missingNames = ContainerUtil.subtract(allBoundNames, boundNames); String nameList = StringUtil.join(ContainerUtil.sorted(missingNames), ", "); markError(entry.getKey(), PyPsiBundle.message("ANN.patterns.pattern.does.not.bind.names", missingNames.size(), nameList)); } } }