List<Range> (@NotNull List<String> beforeLines, @NotNull List<String> afterLines, boolean beforeNoNewlineAtEOF, boolean afterNoNewlineAtEOF) { // patch treats "X\n" vs "X" as modification of a single line, while we treat it as a deletion of an empty line // so we have to adjust output accordingly if (!beforeNoNewlineAtEOF && !afterNoNewlineAtEOF) return doCompareLines(beforeLines, afterLines); int beforeLastLine = beforeLines.size() - 1; int afterLastLine = afterLines.size() - 1; List<String> beforeComparedLines = beforeNoNewlineAtEOF ? beforeLines.subList(0, beforeLastLine) : beforeLines; List<String> afterComparedLines = afterNoNewlineAtEOF ? afterLines.subList(0, afterLastLine) : afterLines; List<Range> ranges = doCompareLines(beforeComparedLines, afterComparedLines); if (beforeNoNewlineAtEOF && afterNoNewlineAtEOF) { if (beforeLines.get(beforeLastLine).equals(afterLines.get(afterLastLine))) return ranges; Range range = new Range(beforeLastLine, beforeLastLine + 1, afterLastLine, afterLastLine + 1); return appendRange(ranges, range); } else if (beforeNoNewlineAtEOF) { Range range = new Range(beforeLastLine, beforeLastLine + 1, afterLastLine + 1, afterLastLine + 1); return appendRange(ranges, range); } else { Range range = new Range(beforeLastLine + 1, beforeLastLine + 1, afterLastLine, afterLastLine + 1); return appendRange(ranges, range); } }