int (@NotNull Document document, @NotNull PsiFile file, int start, int end) { if (!(file instanceof PyFile)) return CANNOT_JOIN; // step back the probable "\" and space before it. final CharSequence text = document.getCharsSequence(); if (start >= 0 && text.charAt(start) == '\n') start -= 1; if (start >= 0 && text.charAt(start) == '\\') start -= 1; while (start >= 0 && (text.charAt(start) == ' ' || text.charAt(start) == '\t')) { start -= 1; } if (start < 0) { return CANNOT_JOIN; // TODO: join with empty BOF, too } // detect elements around the join final PsiElement leftElement = file.findElementAt(start); final PsiElement rightElement = file.findElementAt(end); if (leftElement != null && rightElement != null) { final PyExpression leftExpr = PsiTreeUtil.getParentOfType(leftElement, PyExpression.class); final PyExpression rightExpr = PsiTreeUtil.getParentOfType(rightElement, PyExpression.class); final Request request = new Request(document, start, end, leftElement, leftExpr, rightElement, rightExpr); for (Joiner joiner : JOINERS) { final Result res = joiner.join(request); if (res != null) { final int cutStart = start + 1 - res.cutFromLeft; document.replaceString(cutStart, end + res.cutIntoRight, res.replacement); return cutStart + res.caretOffset; } } } return CANNOT_JOIN; }