boolean (@NotNull PsiStatement fromAssignment, @NotNull PsiStatement untilLoop, Function<Predicate<PsiElement>, Predicate<PsiElement>>... predicatesWithSkipOptions) { int fromOffset = fromAssignment.getTextOffset(); int toOffset = untilLoop.getTextOffset(); if (fromOffset >= toOffset) return false; PsiElement context = PsiTreeUtil.findCommonParent(fromAssignment, untilLoop); if (context == null) return false; if (fromAssignment.getParent() != context) return false; //small optimization if (untilLoop.getParent() == context) { PsiStatement nextSibling = PsiTreeUtil.getNextSiblingOfType(fromAssignment, PsiStatement.class); if (nextSibling == untilLoop) { return false; } PsiStatement nextNextSibling = PsiTreeUtil.getNextSiblingOfType(nextSibling, PsiStatement.class); if (nextNextSibling == untilLoop) { context = nextSibling; } } List<Predicate<PsiElement>> predicates = Arrays.stream(predicatesWithSkipOptions) .map(t -> t.apply(element -> !(element.getTextOffset() < toOffset && element.getTextOffset() + element.getTextLength() > fromOffset))) .toList(); PsiElement finalContext = context; return ContainerUtil.exists(predicates, t -> t.test(finalContext)); }