LineData (@NotNull Document document, int line, int tabSize) { int start = document.getLineStartOffset(line); int end = document.getLineEndOffset(line); int cacheSize = (end - start) / CACHE_FREQUENCY; int[] cache = ArrayUtil.newIntArray(cacheSize); CharSequence text = document.getImmutableCharSequence(); int column = 0; boolean hasTabsOrSurrogates = false; for (int i = start; i < end; i++) { if (i > start && (i - start) % CACHE_FREQUENCY == 0) { cache[(i - start) / CACHE_FREQUENCY - 1] = column; } char c = text.charAt(i); if (c == '\t') { column = (column / tabSize + 1) * tabSize; hasTabsOrSurrogates = true; } else { if (Character.isHighSurrogate(c)) { hasTabsOrSurrogates = true; if (i + 1 < text.length() && Character.isLowSurrogate(text.charAt(i + 1))) continue; } else { hasTabsOrSurrogates |= Character.isLowSurrogate(c); } column++; } } if (cacheSize > 0 && (end - start) % CACHE_FREQUENCY == 0) cache[cacheSize - 1] = column; return hasTabsOrSurrogates ? new LineData(cache) : TRIVIAL; }