/** * Tries to calculate given line's indent column assuming that there might be a comment at the * given indent offset (see {@link #getCommentPrefix(IElementType)}). * * @param line target line * @param indentOffset start indent offset to use for the given line * @param lineEndOffset given line's end offset * @param fallbackColumn column to return if it's not possible to apply comment-specific indent * calculation rules * @return given line's indent column to use */ private int calcIndent(int line, int indentOffset, int lineEndOffset, int fallbackColumn) { final HighlighterIterator it = myEditor.getHighlighter().createIterator(indentOffset); IElementType tokenType = it.getTokenType(); Language language = tokenType.getLanguage(); TokenSet comments = myComments.get(language); if (comments == null) { ParserDefinition definition = LanguageParserDefinitions.INSTANCE.forLanguage(language); if (definition != null) { comments = definition.getCommentTokens(); } if (comments == null) { return fallbackColumn; } else { myComments.put(language, comments); } } if (comments.contains(tokenType) && indentOffset == it.getStart()) { String prefix = COMMENT_PREFIXES.get(tokenType); if (prefix == null) { prefix = getCommentPrefix(tokenType); } if (!NO_COMMENT_INFO_MARKER.equals(prefix)) { final int indentInsideCommentOffset = CharArrayUtil.shiftForward( myChars, indentOffset + prefix.length(), lineEndOffset, " \t"); if (indentInsideCommentOffset < lineEndOffset) { int indent = myEditor.calcColumnNumber(indentInsideCommentOffset, line); indentAfterUncomment.put(line, indent - prefix.length()); return indent; } } } return fallbackColumn; }
@Override public void advance() { myCurrentStart = getCurrentStart(); myCurrentEnd = getCurrentEnd(); myCurrentAttributes = myIterator.getTextAttributes(); myIterator.advance(); skipBadCharacters(); }
public static List<IElementType> getAllTokens(EditorHighlighter highlighter) { List<IElementType> tokens = new ArrayList<IElementType>(); HighlighterIterator iterator = highlighter.createIterator(0); while (!iterator.atEnd()) { tokens.add(iterator.getTokenType()); iterator.advance(); } return tokens; }
private static List<BidiRun> createRuns(EditorImpl editor, char[] text, int startOffsetInEditor) { int textLength = text.length; if (editor.myDisableRtl) return Collections.singletonList(new BidiRun((byte) 0, 0, textLength)); List<BidiRun> runs = new ArrayList<BidiRun>(); if (startOffsetInEditor >= 0) { // running bidi algorithm separately for text fragments corresponding to different lexer // tokens int lastOffset = startOffsetInEditor; IElementType lastToken = null; HighlighterIterator iterator = editor.getHighlighter().createIterator(startOffsetInEditor); int endOffsetInEditor = startOffsetInEditor + textLength; while (!iterator.atEnd() && iterator.getStart() < endOffsetInEditor) { IElementType currentToken = iterator.getTokenType(); if (distinctTokens(lastToken, currentToken)) { int tokenStart = Math.max(iterator.getStart(), startOffsetInEditor); addRuns(runs, text, lastOffset - startOffsetInEditor, tokenStart - startOffsetInEditor); lastToken = currentToken; lastOffset = tokenStart; } iterator.advance(); } addRuns( runs, text, lastOffset - startOffsetInEditor, endOffsetInEditor - startOffsetInEditor); } else { addRuns(runs, text, 0, textLength); } return runs; }
private static boolean isAtTokenNeeded(InsertionContext myContext) { HighlighterIterator iterator = ((EditorEx) myContext.getEditor()) .getHighlighter() .createIterator(myContext.getStartOffset()); LOG.assertTrue(iterator.getTokenType() == JavaTokenType.IDENTIFIER); iterator.retreat(); if (iterator.getTokenType() == TokenType.WHITE_SPACE) iterator.retreat(); return iterator.getTokenType() != JavaTokenType.AT && iterator.getTokenType() != JavaTokenType.DOT; }
private void paintBorderEffect( Graphics2D g, ClipDetector clipDetector, EditorHighlighter highlighter, int clipStartOffset, int clipEndOffset) { HighlighterIterator it = highlighter.createIterator(clipStartOffset); while (!it.atEnd() && it.getStart() < clipEndOffset) { TextAttributes attributes = it.getTextAttributes(); if (isBorder(attributes)) { paintBorderEffect(g, clipDetector, it.getStart(), it.getEnd(), attributes); } it.advance(); } }
/** * Calculates number of unmatched left braces before the given offset. * * @param editor target editor * @param offset target offset * @param fileType target file type * @return number of unmatched braces before the given offset; negative value if it's not possible * to perform the calculation or if there are no unmatched left braces before the given offset */ protected static int getUnmatchedLBracesNumberBefore( Editor editor, int offset, FileType fileType) { if (offset == 0) { return -1; } CharSequence chars = editor.getDocument().getCharsSequence(); if (chars.charAt(offset - 1) != '{') { return -1; } EditorHighlighter highlighter = ((EditorEx) editor).getHighlighter(); HighlighterIterator iterator = highlighter.createIterator(offset - 1); BraceMatcher braceMatcher = BraceMatchingUtil.getBraceMatcher(fileType, iterator); if (!braceMatcher.isLBraceToken(iterator, chars, fileType) || !braceMatcher.isStructuralBrace(iterator, chars, fileType)) { return -1; } Language language = iterator.getTokenType().getLanguage(); iterator = highlighter.createIterator(0); int lBracesBeforeOffset = 0; int lBracesAfterOffset = 0; int rBracesBeforeOffset = 0; int rBracesAfterOffset = 0; for (; !iterator.atEnd(); iterator.advance()) { IElementType tokenType = iterator.getTokenType(); if (!tokenType.getLanguage().equals(language) || !braceMatcher.isStructuralBrace(iterator, chars, fileType)) { continue; } boolean beforeOffset = iterator.getStart() < offset; if (braceMatcher.isLBraceToken(iterator, chars, fileType)) { if (beforeOffset) { lBracesBeforeOffset++; } else { lBracesAfterOffset++; } } else if (braceMatcher.isRBraceToken(iterator, chars, fileType)) { if (beforeOffset) { rBracesBeforeOffset++; } else { rBracesAfterOffset++; } } } return lBracesBeforeOffset - rBracesBeforeOffset - (rBracesAfterOffset - lBracesAfterOffset); }
@Override @NotNull public Map<TodoIndexEntry, Integer> map(@NotNull final FileContent inputData) { if (IndexPatternUtil.getIndexPatternCount() > 0) { final CharSequence chars = inputData.getContentAsText(); final OccurrenceConsumer occurrenceConsumer = new OccurrenceConsumer(null, true); EditorHighlighter highlighter; final EditorHighlighter editorHighlighter = inputData.getUserData(EDITOR_HIGHLIGHTER); if (editorHighlighter != null && checkCanUseCachedEditorHighlighter(chars, editorHighlighter)) { highlighter = editorHighlighter; } else { highlighter = HighlighterFactory.createHighlighter(inputData.getProject(), myFile); highlighter.setText(chars); } final int documentLength = chars.length(); BaseFilterLexer.TodoScanningState todoScanningState = null; final HighlighterIterator iterator = highlighter.createIterator(0); while (!iterator.atEnd()) { final IElementType token = iterator.getTokenType(); if (myCommentTokens.contains(token) || CacheUtil.isInComments(token)) { int start = iterator.getStart(); if (start >= documentLength) break; int end = iterator.getEnd(); todoScanningState = BaseFilterLexer.advanceTodoItemsCount( chars.subSequence(start, Math.min(end, documentLength)), occurrenceConsumer, todoScanningState); if (end > documentLength) break; } iterator.advance(); } final Map<TodoIndexEntry, Integer> map = new HashMap<>(); for (IndexPattern pattern : IndexPatternUtil.getIndexPatterns()) { final int count = occurrenceConsumer.getOccurrenceCount(pattern); if (count > 0) { map.put( new TodoIndexEntry(pattern.getPatternString(), pattern.isCaseSensitive()), count); } } return map; } return Collections.emptyMap(); }
protected boolean handleBackspace( Editor editor, Caret caret, DataContext dataContext, boolean toWordStart) { Project project = CommonDataKeys.PROJECT.getData(dataContext); if (project == null) return false; PsiFile file = PsiUtilBase.getPsiFileInEditor(editor, project); if (file == null) return false; if (editor.getSelectionModel().hasSelection()) return false; int offset = editor.getCaretModel().getOffset() - 1; if (offset < 0) return false; CharSequence chars = editor.getDocument().getCharsSequence(); char c = chars.charAt(offset); final Editor injectedEditor = TypedHandler.injectedEditorIfCharTypedIsSignificant(c, editor, file); final Editor originalEditor = editor; if (injectedEditor != editor) { int injectedOffset = injectedEditor.getCaretModel().getOffset(); if (isOffsetInsideInjected(injectedEditor, injectedOffset)) { file = PsiDocumentManager.getInstance(project).getPsiFile(injectedEditor.getDocument()); editor = injectedEditor; offset = injectedOffset - 1; } } final BackspaceHandlerDelegate[] delegates = Extensions.getExtensions(BackspaceHandlerDelegate.EP_NAME); if (!toWordStart) { for (BackspaceHandlerDelegate delegate : delegates) { delegate.beforeCharDeleted(c, file, editor); } } FileType fileType = file.getFileType(); final QuoteHandler quoteHandler = TypedHandler.getQuoteHandler(file, editor); HighlighterIterator hiterator = ((EditorEx) editor).getHighlighter().createIterator(offset); boolean wasClosingQuote = quoteHandler != null && quoteHandler.isClosingQuote(hiterator, offset); myOriginalHandler.execute(originalEditor, caret, dataContext); if (!toWordStart) { for (BackspaceHandlerDelegate delegate : delegates) { if (delegate.charDeleted(c, file, editor)) { return true; } } } if (offset >= editor.getDocument().getTextLength()) return true; chars = editor.getDocument().getCharsSequence(); if ((c == '(' || c == '[' || c == '{') && CodeInsightSettings.getInstance().AUTOINSERT_PAIR_BRACKET) { char c1 = chars.charAt(offset); if (c1 != getRightChar(c)) return true; HighlighterIterator iterator = ((EditorEx) editor).getHighlighter().createIterator(offset); BraceMatcher braceMatcher = BraceMatchingUtil.getBraceMatcher(fileType, iterator); if (!braceMatcher.isLBraceToken(iterator, chars, fileType) && !braceMatcher.isRBraceToken(iterator, chars, fileType)) { return true; } int rparenOffset = BraceMatchingUtil.findRightmostRParen(iterator, iterator.getTokenType(), chars, fileType); if (rparenOffset >= 0) { iterator = ((EditorEx) editor).getHighlighter().createIterator(rparenOffset); boolean matched = BraceMatchingUtil.matchBrace(chars, fileType, iterator, false); if (matched) return true; } editor.getDocument().deleteString(offset, offset + 1); } else if ((c == '"' || c == '\'' || c == '`') && CodeInsightSettings.getInstance().AUTOINSERT_PAIR_QUOTE) { char c1 = chars.charAt(offset); if (c1 != c) return true; if (wasClosingQuote) return true; HighlighterIterator iterator = ((EditorEx) editor).getHighlighter().createIterator(offset); if (quoteHandler == null || !quoteHandler.isOpeningQuote(iterator, offset)) return true; editor.getDocument().deleteString(offset, offset + 1); } return true; }
public static boolean semicolonNeeded(final Editor editor, PsiFile file, final int startOffset) { final PsiJavaCodeReferenceElement ref = PsiTreeUtil.findElementOfClassAtOffset( file, startOffset, PsiJavaCodeReferenceElement.class, false); if (ref != null && !(ref instanceof PsiReferenceExpression)) { if (ref.getParent() instanceof PsiTypeElement) { return true; } } HighlighterIterator iterator = ((EditorEx) editor).getHighlighter().createIterator(startOffset); if (iterator.atEnd()) return false; if (iterator.getTokenType() == JavaTokenType.IDENTIFIER) { iterator.advance(); } while (!iterator.atEnd() && ElementType.JAVA_COMMENT_OR_WHITESPACE_BIT_SET.contains(iterator.getTokenType())) { iterator.advance(); } if (!iterator.atEnd() && (iterator.getTokenType() == JavaTokenType.LPARENTH || iterator.getTokenType() == JavaTokenType.COLON)) { return true; } while (!iterator.atEnd() && ElementType.JAVA_COMMENT_OR_WHITESPACE_BIT_SET.contains(iterator.getTokenType())) { iterator.advance(); } if (iterator.atEnd() || iterator.getTokenType() != JavaTokenType.IDENTIFIER) return false; iterator.advance(); while (!iterator.atEnd() && ElementType.JAVA_COMMENT_OR_WHITESPACE_BIT_SET.contains(iterator.getTokenType())) { iterator.advance(); } if (iterator.atEnd()) return false; return iterator.getTokenType() == JavaTokenType.EQ || iterator.getTokenType() == JavaTokenType.LPARENTH; }
private void skipBadCharacters() { while (!myIterator.atEnd() && myIterator.getTokenType() == TokenType.BAD_CHARACTER) { myIterator.advance(); } }
private int getCurrentEnd() { return Math.min(myIterator.getEnd(), myEndOffset); }
private int getCurrentStart() { return Math.max(myIterator.getStart(), myStartOffset); }
@Override public boolean atEnd() { return myIterator.atEnd() || getCurrentStart() >= myEndOffset; }
protected String addTextRangeToHistory( TextRange textRange, final EditorEx consoleEditor, boolean preserveMarkup) { final Document history = myHistoryViewer.getDocument(); final MarkupModel markupModel = DocumentMarkupModel.forDocument(history, myProject, true); if (myPrompt != null) { appendToHistoryDocument(history, myPrompt); } markupModel.addRangeHighlighter( history.getTextLength() - StringUtil.length(myPrompt), history.getTextLength(), HighlighterLayer.SYNTAX, ConsoleViewContentType.USER_INPUT.getAttributes(), HighlighterTargetArea.EXACT_RANGE); final int localStartOffset = textRange.getStartOffset(); String text; EditorHighlighter highlighter; if (consoleEditor instanceof EditorWindow) { EditorWindow editorWindow = (EditorWindow) consoleEditor; EditorColorsScheme scheme = EditorColorsManager.getInstance().getGlobalScheme(); PsiFile file = editorWindow.getInjectedFile(); final VirtualFile virtualFile = file.getVirtualFile(); assert virtualFile != null; highlighter = HighlighterFactory.createHighlighter(virtualFile, scheme, getProject()); String fullText = InjectedLanguageUtil.getUnescapedText(file, null, null); highlighter.setText(fullText); text = textRange.substring(fullText); } else { text = consoleEditor.getDocument().getText(textRange); highlighter = consoleEditor.getHighlighter(); } // offset can be changed after text trimming after insert due to buffer constraints appendToHistoryDocument(history, text); int offset = history.getTextLength() - text.length(); final HighlighterIterator iterator = highlighter.createIterator(localStartOffset); final int localEndOffset = textRange.getEndOffset(); while (!iterator.atEnd()) { final int itStart = iterator.getStart(); if (itStart > localEndOffset) break; final int itEnd = iterator.getEnd(); if (itEnd >= localStartOffset) { final int start = Math.max(itStart, localStartOffset) - localStartOffset + offset; final int end = Math.min(itEnd, localEndOffset) - localStartOffset + offset; markupModel.addRangeHighlighter( start, end, HighlighterLayer.SYNTAX, iterator.getTextAttributes(), HighlighterTargetArea.EXACT_RANGE); } iterator.advance(); } if (preserveMarkup) { duplicateHighlighters( markupModel, DocumentMarkupModel.forDocument(consoleEditor.getDocument(), myProject, true), offset, textRange); duplicateHighlighters(markupModel, consoleEditor.getMarkupModel(), offset, textRange); } if (!text.endsWith("\n")) { appendToHistoryDocument(history, "\n"); } return text; }
public boolean isOpeningQuote(HighlighterIterator iterator, int offset) { return iterator.getTokenType() == XmlTokenType.XML_ATTRIBUTE_VALUE_START_DELIMITER; }