Context (@NotNull CharSequence text, int startOffset, int endOffset, int offset) { int asteriskOffset = StringUtil.indexOf(text, '*', startOffset, endOffset); if (asteriskOffset < 0) { return NOT_MATCHED_CONTEXT; } startOffset = asteriskOffset + 1; int startTagStartOffset = -1; int startTagEndOffset = -1; Set<CharSequence> closedTags = new HashSet<>(); CharSequence startTag = null; // Try to find start tag to the left of the given offset. for (int i = offset - 1; i >= startOffset; i--) { char c = text.charAt(i); if (c == ' ' || c == '\t') { continue; } if (c == '>' && (startTagEndOffset < 0)) { if (i > startOffset && text.charAt(i - 1) == '/') { // Handle situation like '<p/>[offset]' break; } else { startTagEndOffset = i; continue; } } if (c == '<') { if (startTagEndOffset < 0 || i >= endOffset) { // We are inside the tag. break; } if (text.charAt(i + 1) == '/') { CharSequence tag = text.subSequence(i + 2, startTagEndOffset); closedTags.add(tag); startTagEndOffset = -1; } else { CharSequence tag = text.subSequence(i + 1, startTagEndOffset); if (closedTags.remove(tag)) { startTagEndOffset = -1; continue; } startTagStartOffset = i; startTag = text.subSequence(i + 1, startTagEndOffset + 1); break; } } } if (startTagStartOffset < 0) { return NOT_MATCHED_CONTEXT; } int endTagStartOffset = -1; // Try to find closing tag at or after the given offset. for (int i = offset; i < endOffset; i++) { char c = text.charAt(i); if (c == '<' && i < endOffset - 2 && text.charAt(i + 1) == '/' && CharArrayUtil.regionMatches(text, i + 2, endOffset, startTag)) { endTagStartOffset = i; break; } } return new Context(text, startTagEndOffset, endTagStartOffset, startTag, offset); }