BraceHighlightingAndNavigationContext (@NotNull Editor editor, @NotNull PsiFile file, int offset) { EditorHighlighter highlighter = BraceHighlightingHandler.getLazyParsableHighlighterIfAny(file.getProject(), editor, file); CharSequence text = editor.getDocument().getCharsSequence(); HighlighterIterator iterator = highlighter.createIterator(offset); FileType fileType = iterator.atEnd() ? null : getFileType(file, iterator.getStart()); boolean isBeforeOrInsideLeftBrace = fileType != null && isLBraceToken(iterator, text, fileType); boolean isBeforeOrInsideRightBrace = !isBeforeOrInsideLeftBrace && fileType != null && isRBraceToken(iterator, text, fileType); boolean isInsideBrace = (isBeforeOrInsideLeftBrace || isBeforeOrInsideRightBrace) && iterator.getStart() < offset; HighlighterIterator preOffsetIterator = offset > 0 && !isInsideBrace ? highlighter.createIterator(offset - 1) : null; FileType preOffsetFileType = preOffsetIterator != null ? getFileType(file, preOffsetIterator.getStart()) : null; boolean isAfterLeftBrace = preOffsetIterator != null && isLBraceToken(preOffsetIterator, text, preOffsetFileType); boolean isAfterRightBrace = !isAfterLeftBrace && preOffsetIterator != null && isRBraceToken(preOffsetIterator, text, preOffsetFileType); int offsetTokenStart = iterator.atEnd() ? -1 : iterator.getStart(); int preOffsetTokenStart = preOffsetIterator == null || preOffsetIterator.atEnd() ? -1 : preOffsetIterator.getStart(); if (editor.getSettings().isBlockCursor()) { if (isBeforeOrInsideLeftBrace && matchBrace(text, fileType, iterator, true)) { return new BraceHighlightingAndNavigationContext(offsetTokenStart, iterator.getStart(), isInsideBrace); } else if (isBeforeOrInsideRightBrace && matchBrace(text, fileType, iterator, false)) { return new BraceHighlightingAndNavigationContext(offsetTokenStart, iterator.getStart(), isInsideBrace); } else if (isAfterRightBrace && matchBrace(text, preOffsetFileType, preOffsetIterator, false)) { return new BraceHighlightingAndNavigationContext(preOffsetTokenStart, preOffsetIterator.getStart(), true); } else if (isAfterLeftBrace && matchBrace(text, preOffsetFileType, preOffsetIterator, true)) { return new BraceHighlightingAndNavigationContext(preOffsetTokenStart, preOffsetIterator.getStart(), true); } } else { if (isAfterRightBrace && matchBrace(text, preOffsetFileType, preOffsetIterator, false)) { return new BraceHighlightingAndNavigationContext(preOffsetTokenStart, preOffsetIterator.getStart(), true); } else if (isBeforeOrInsideLeftBrace && matchBrace(text, fileType, iterator, true)) { return new BraceHighlightingAndNavigationContext(offsetTokenStart, iterator.getEnd(), isInsideBrace); } else if (isAfterLeftBrace && matchBrace(text, preOffsetFileType, preOffsetIterator, true)) { return new BraceHighlightingAndNavigationContext(preOffsetTokenStart, preOffsetIterator.getEnd(), true); } else if (isBeforeOrInsideRightBrace && matchBrace(text, fileType, iterator, false)) { return new BraceHighlightingAndNavigationContext(offsetTokenStart, iterator.getStart(), isInsideBrace); } } return null; }