AnnotatedLineModificationDetails (@NotNull String beforeContent, @NotNull String afterContent, @NotNull String originalLine) { List<LineFragment> fragments = compareContents(beforeContent, afterContent); LineOffsets afterLineOffsets = LineOffsetsUtil.create(afterContent); int originalLineNumber = findOriginalLine(afterContent, afterLineOffsets, originalLine, fragments); if (originalLineNumber == -1) { return null; // line not found } if (originalLineNumber >= afterLineOffsets.getLineCount()) { return null; // invalid line or content } String lineContentAfter = getLine(afterContent, afterLineOffsets, originalLineNumber); if (StringUtil.isEmptyOrSpaces(lineContentAfter)) { return createNewLineDetails(lineContentAfter); // empty lines are always new, for simplicity } return createFragmentDetails(lineContentAfter, afterLineOffsets, fragments, originalLineNumber); }