TextContent (List<Exclusion> ranges) { ProgressManager.checkCanceled(); if (ranges.isEmpty()) return this; if (ranges.get(0).start < 0 || ranges.get(ranges.size() - 1).end > length()) { throw new IllegalArgumentException("Text ranges " + ranges + " should be between 0 and " + length()); } for (int i = 1; i < ranges.size(); i++) { if (ranges.get(i - 1).end > ranges.get(i).start) { throw new IllegalArgumentException("Ranges should be sorted and non-intersecting: " + ranges); } } int[] offsets = getTokenOffsets(); List<Exclusion>[] affectingExclusions = getAffectingExclusions(ranges, offsets); List<TokenInfo> newTokens = new ArrayList<>(); for (int i = 0; i < tokens.size(); i++) { List<Exclusion> affecting = affectingExclusions[i]; TokenInfo token = tokens.get(i); if (affecting == null) { newTokens.add(token); } else if (token instanceof PsiToken) { newTokens.addAll(((PsiToken)token).splitToken(offsets[i], affecting)); } } if (newTokens.isEmpty()) { PsiToken first = (PsiToken) tokens.get(0); TokenKind kind1 = first.kind; TokenKind kind2 = ((PsiToken)tokens.get(tokens.size() - 1)).kind; TokenKind mostUnknown = kind1.compareTo(kind2) > 0 ? kind1 : kind2; newTokens.add(new PsiToken("", first.psi, TextRange.from(first.rangeInPsi.getStartOffset(), 0), mostUnknown)); } return new TextContentImpl(domain, newTokens); }