IndentData (@NotNull CharSequence chars, int startOffset, int endOffset, int tabSize) { assert tabSize > 0 : "Invalid tab size: " + tabSize; int indent = 0; int alignment = 0; boolean hasTabs = false; boolean isInAlignmentArea = false; for (int i = startOffset; i < Math.min(chars.length(), endOffset); i ++) { char c = chars.charAt(i); switch (c) { case ' ' -> { if (hasTabs) { isInAlignmentArea = true; alignment++; } else { indent++; } } case '\t' -> { if (isInAlignmentArea) { alignment = (alignment / tabSize + 1) * tabSize; } else { hasTabs = true; indent += tabSize; } } default -> throw new InvalidDataException("Unexpected indent character: '" + c + "'"); } } return new IndentData(indent, alignment); }