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