下面列出了com.intellij.psi.util.PsiElementFilter#com.intellij.util.DocumentUtil 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
@Nullable
public static LogicalPosition getTabsAwarePosition(Editor editor, Position pos) {
return computableReadAction(() -> {
try {
if (editor.isDisposed()) {
return null;
}
Document doc = editor.getDocument();
int line = Math.max(0, Math.min(pos.getLine(), doc.getLineCount()));
String lineText = doc.getText(DocumentUtil.getLineTextRange(doc, line));
String lineTextForPosition = !lineText.isEmpty() ? lineText.substring(0, min(lineText.length(),
pos.getCharacter())) : "";
int tabs = StringUtil.countChars(lineTextForPosition, '\t');
int tabSize = editor.getSettings().getTabSize(editor.getProject());
int column = tabs * tabSize + lineTextForPosition.length() - tabs;
return new LogicalPosition(line, column);
} catch (IndexOutOfBoundsException e) {
return null;
}
});
}
@NotNull
@Override
public TextRange process(@NotNull ASTNode element, @NotNull TextRange range) {
PsiElement psiElement = element.getPsi();
if (psiElement != null && psiElement.isValid()
&& psiElement.getLanguage().is(CypherLanguage.INSTANCE)) {
FormatterTask converter = new FormatterTask(psiElement, range);
if (converter.getDocument() != null) {
DocumentUtil.executeInBulk(converter.getDocument(), true, converter);
}
return converter.getTextRange();
}
return range;
}
@Nonnull
public List<RangeHighlighter> done() {
// We won't use addLineHighlighter as it will fail to add marker into empty document.
//RangeHighlighter highlighter = editor.getMarkupModel().addLineHighlighter(line, HighlighterLayer.SELECTION - 1, null);
int offset = DocumentUtil.getFirstNonSpaceCharOffset(editor.getDocument(), line);
RangeHighlighter highlighter = editor.getMarkupModel()
.addRangeHighlighter(offset, offset, LINE_MARKER_LAYER, null, HighlighterTargetArea.LINES_IN_RANGE);
highlighter.setLineSeparatorPlacement(placement);
highlighter.setLineSeparatorRenderer(renderer);
highlighter.setLineMarkerRenderer(gutterRenderer);
if (type == null || resolved) return Collections.singletonList(highlighter);
TextAttributes stripeAttributes = getStripeTextAttributes(type, editor);
RangeHighlighter stripeHighlighter = editor.getMarkupModel()
.addRangeHighlighter(offset, offset, STRIPE_LAYER, stripeAttributes, HighlighterTargetArea.LINES_IN_RANGE);
return ContainerUtil.list(highlighter, stripeHighlighter);
}
@RequiredUIAccess
public static void executeWriteCommand(@Nullable Project project,
@Nonnull Document document,
@Nullable String commandName,
@Nullable String commandGroupId,
@Nonnull UndoConfirmationPolicy confirmationPolicy,
boolean underBulkUpdate,
@Nonnull Runnable task) {
if (!makeWritable(project, document)) {
VirtualFile file = FileDocumentManager.getInstance().getFile(document);
LOG.warn("Document is read-only" + (file != null ? ": " + file.getPresentableName() : ""));
return;
}
ApplicationManager.getApplication().runWriteAction(() -> {
CommandProcessor.getInstance().executeCommand(project, () -> {
if (underBulkUpdate) {
DocumentUtil.executeInBulk(document, true, task);
}
else {
task.run();
}
}, commandName, commandGroupId, confirmationPolicy, document);
});
}
@Override
protected void changedUpdateImpl(@Nonnull DocumentEvent e) {
// todo Denis Zhdanov
DocumentEventImpl event = (DocumentEventImpl)e;
final boolean shouldTranslateViaDiff = isValid() && PersistentRangeMarkerUtil.shouldTranslateViaDiff(event, getStartOffset(), getEndOffset());
boolean wasTranslatedViaDiff = shouldTranslateViaDiff;
if (shouldTranslateViaDiff) {
wasTranslatedViaDiff = translatedViaDiff(e, event);
}
if (!wasTranslatedViaDiff) {
super.changedUpdateImpl(e);
if (isValid()) {
myLine = getDocument().getLineNumber(getStartOffset());
int endLine = getDocument().getLineNumber(getEndOffset());
if (endLine != myLine) {
setIntervalEnd(getDocument().getLineEndOffset(myLine));
}
}
}
if (isValid() && getTargetArea() == HighlighterTargetArea.LINES_IN_RANGE) {
setIntervalStart(DocumentUtil.getFirstNonSpaceCharOffset(getDocument(), myLine));
setIntervalEnd(getDocument().getLineEndOffset(myLine));
}
}
@RequiredWriteAction
@Override
public void executeWriteAction(Editor editor, @Nullable Caret caret, DataContext dataContext) {
if (editor.isColumnMode() && caret == null && editor.getCaretModel().getCaretCount() > 1) {
EditorUIUtil.hideCursorInEditor(editor);
CommandProcessor.getInstance().setCurrentCommandGroupId(EditorActionUtil.DELETE_COMMAND_GROUP);
CopyPasteManager.getInstance().stopKillRings();
editor.getCaretModel().runForEachCaret(c -> {
int offset = c.getOffset();
int lineEndOffset = DocumentUtil.getLineEndOffset(offset, editor.getDocument());
if (offset < lineEndOffset) myOriginalHandler.execute(editor, c, dataContext);
});
}
else {
myOriginalHandler.execute(editor, caret, dataContext);
}
}
private int visualLineStartOffset(int offset, boolean leanForward) {
DesktopEditorImpl editor = myView.getEditor();
offset = DocumentUtil.alignToCodePointBoundary(myDocument, offset);
int result = EditorUtil.getNotFoldedLineStartOffset(editor, offset);
SoftWrapModelImpl softWrapModel = editor.getSoftWrapModel();
List<? extends SoftWrap> softWraps = softWrapModel.getRegisteredSoftWraps();
int currentOrPrevWrapIndex = softWrapModel.getSoftWrapIndex(offset);
SoftWrap currentOrPrevWrap;
if (currentOrPrevWrapIndex < 0) {
currentOrPrevWrapIndex = -currentOrPrevWrapIndex - 2;
currentOrPrevWrap = currentOrPrevWrapIndex < 0 || currentOrPrevWrapIndex >= softWraps.size() ? null : softWraps.get(currentOrPrevWrapIndex);
}
else {
currentOrPrevWrap = leanForward ? softWraps.get(currentOrPrevWrapIndex) : null;
}
if (currentOrPrevWrap != null && currentOrPrevWrap.getStart() > result) {
result = currentOrPrevWrap.getStart();
}
return result;
}
@Nullable
@Override
public FoldRegion createFoldRegion(int startOffset, int endOffset, @Nonnull String placeholder, @Nullable FoldingGroup group, boolean neverExpands) {
assertIsDispatchThreadForEditor();
if (!myIsBatchFoldingProcessing) {
LOG.error("Fold regions must be added or removed inside batchFoldProcessing() only.");
return null;
}
if (!isFoldingEnabled() || startOffset >= endOffset ||
DocumentUtil.isInsideSurrogatePair(myEditor.getDocument(), startOffset) ||
DocumentUtil.isInsideSurrogatePair(myEditor.getDocument(), endOffset) ||
!myFoldTree.checkIfValidToCreate(startOffset, endOffset)) return null;
FoldRegionImpl region = new FoldRegionImpl(myEditor, startOffset, endOffset, placeholder, group, neverExpands);
myRegionTree.addInterval(region, startOffset, endOffset, false, false, false, 0);
LOG.assertTrue(region.isValid());
myFoldRegionsProcessed = true;
if (group != null) {
myGroups.putValue(group, region);
}
notifyListenersOnFoldRegionStateChange(region);
LOG.assertTrue(region.isValid());
return region;
}
@Override
protected void changedUpdateImpl(@Nonnull DocumentEvent e) {
super.changedUpdateImpl(e);
if (isValid()) {
int startOffset = intervalStart();
int endOffset = intervalEnd();
if (DocumentUtil.isInsideSurrogatePair(getDocument(), startOffset)) setIntervalStart(startOffset - 1);
if (DocumentUtil.isInsideSurrogatePair(getDocument(), endOffset)) setIntervalStart(endOffset - 1);
}
if (endVirtualOffset > 0 && isValid()) {
Document document = e.getDocument();
int startAfter = intervalStart();
int endAfter = intervalEnd();
if (!DocumentUtil.isAtLineEnd(endAfter, document) || document.getLineNumber(startAfter) != document.getLineNumber(endAfter)) {
resetVirtualSelection();
}
}
}
private int calcSoftWrapOffset(int minOffset, int maxOffset, boolean preferMinOffset) {
if (canBreakBeforeOrAfterCodePoint(Character.codePointAt(myText, maxOffset))) return maxOffset;
for (int i = 0, offset = maxOffset; i < BASIC_LOOK_BACK_LENGTH && offset >= minOffset; i++) {
int prevOffset = Character.offsetByCodePoints(myText, offset, -1);
if (canBreakBeforeOrAfterCodePoint(Character.codePointAt(myText, prevOffset))) return offset;
//noinspection AssignmentToForLoopParameter
offset = prevOffset;
}
if (myLineWrapPositionStrategy == null) {
myLineWrapPositionStrategy = LanguageLineWrapPositionStrategy.INSTANCE.forEditor(myEditor);
}
int wrapOffset = myLineWrapPositionStrategy.calculateWrapPosition(myDocument, myEditor.getProject(), minOffset - 1, maxOffset + 1, maxOffset + 1, false, true);
if (wrapOffset < 0) return preferMinOffset ? minOffset : maxOffset;
if (wrapOffset < minOffset) return minOffset;
if (wrapOffset > maxOffset) return maxOffset;
if (DocumentUtil.isInsideSurrogatePair(myDocument, wrapOffset)) return wrapOffset - 1;
return wrapOffset;
}
@Override
public void onUpdated(@Nonnull Inlay inlay) {
if (myEditor.getDocument().isInBulkUpdate() || inlay.getPlacement() != Inlay.Placement.INLINE && inlay.getPlacement() != Inlay.Placement.AFTER_LINE_END) return;
if (!isSoftWrappingEnabled()) {
myDirty = true;
return;
}
if (!myDirty) {
if (myEditor.getDocument().isInEventsHandling()) {
if (inlay.getPlacement() == Inlay.Placement.AFTER_LINE_END) {
myAfterLineEndInlayUpdated = true;
}
return;
}
int offset = inlay.getOffset();
if (inlay.getPlacement() == Inlay.Placement.AFTER_LINE_END) {
offset = DocumentUtil.getLineEndOffset(offset, myEditor.getDocument());
}
myApplianceManager.recalculate(Collections.singletonList(new TextRange(offset, offset)));
}
}
@TestOnly
void validateState() {
Document document = myEditor.getDocument();
if (myEditor.getDocument().isInBulkUpdate()) return;
FoldingModel foldingModel = myEditor.getFoldingModel();
List<? extends SoftWrap> softWraps = getRegisteredSoftWraps();
int lastSoftWrapOffset = -1;
for (SoftWrap wrap : softWraps) {
int softWrapOffset = wrap.getStart();
LOG.assertTrue(softWrapOffset > lastSoftWrapOffset, "Soft wraps are not ordered");
LOG.assertTrue(softWrapOffset < document.getTextLength(), "Soft wrap is after document's end");
FoldRegion foldRegion = foldingModel.getCollapsedRegionAtOffset(softWrapOffset);
LOG.assertTrue(foldRegion == null || foldRegion.getStartOffset() == softWrapOffset, "Soft wrap is inside fold region");
LOG.assertTrue(softWrapOffset != DocumentUtil.getLineEndOffset(softWrapOffset, document) || foldRegion != null, "Soft wrap before line break");
LOG.assertTrue(softWrapOffset != DocumentUtil.getLineStartOffset(softWrapOffset, document) || foldingModel.isOffsetCollapsed(softWrapOffset - 1), "Soft wrap after line break");
LOG.assertTrue(!DocumentUtil.isInsideSurrogatePair(document, softWrapOffset), "Soft wrap inside a surrogate pair");
lastSoftWrapOffset = softWrapOffset;
}
}
private static void reformatBlock(final Project project, final Editor editor, final int startOffset, final int endOffset) {
PsiDocumentManager.getInstance(project).commitAllDocuments();
Runnable task = new Runnable() {
@Override
public void run() {
PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument());
try {
CodeStyleManager.getInstance(project).reformatRange(file, startOffset, endOffset, true);
}
catch (IncorrectOperationException e) {
LOG.error(e);
}
}
};
if (endOffset - startOffset > 1000) {
DocumentUtil.executeInBulk(editor.getDocument(), true, task);
}
else {
task.run();
}
}
private void doProcess(int lineCount) {
List<RangeMarker> markers = new ArrayList<>();
try {
myIndicator.setText2("Converting end-of-line comments");
convertEndComments(lineCount);
myIndicator.setText2("Removing line-breaks");
int newCount = processRawJoiners(lineCount);
DocumentUtil.executeInBulk(myDoc, newCount > 100, () -> removeLineBreaks(newCount, markers));
myIndicator.setText2("Postprocessing");
List<RangeMarker> unprocessed = processNonRawJoiners(markers);
myIndicator.setText2("Adjusting white-space");
adjustWhiteSpace(unprocessed);
}
finally {
markers.forEach(RangeMarker::dispose);
}
}
private void adjustWhiteSpace(List<RangeMarker> markers) {
int size = markers.size();
if (size == 0) return;
int[] spacesToAdd = getSpacesToAdd(markers);
DocumentUtil.executeInBulk(myDoc, size > 100, () -> {
for (int i = 0; i < size; i++) {
myIndicator.checkCanceled();
myIndicator.setFraction(0.95 + 0.05 * i / size);
RangeMarker marker = markers.get(i);
if (!marker.isValid()) continue;
CharSequence docText = myDoc.getCharsSequence();
int lineEndOffset = marker.getStartOffset();
int start = StringUtil.skipWhitespaceBackward(docText, lineEndOffset) - 1;
int end = StringUtil.skipWhitespaceForward(docText, lineEndOffset);
int replaceStart = start == lineEndOffset ? start : start + 1;
if (myCaretRestoreOffset == CANNOT_JOIN) myCaretRestoreOffset = replaceStart;
int spacesToCreate = spacesToAdd[i];
String spacing = StringUtil.repeatSymbol(' ', spacesToCreate);
myDoc.replaceString(replaceStart, end, spacing);
}
});
myManager.commitDocument(myDoc);
}
private void executeChanges(@Nonnull List<TemplateDocumentChange> changes) {
if (isDisposed() || changes.isEmpty()) {
return;
}
if (changes.size() > 1) {
ContainerUtil.sort(changes, (o1, o2) -> {
int startDiff = o2.startOffset - o1.startOffset;
return startDiff != 0 ? startDiff : o2.endOffset - o1.endOffset;
});
}
DocumentUtil.executeInBulk(myDocument, true, () -> {
for (TemplateDocumentChange change : changes) {
replaceString(change.newValue, change.startOffset, change.endOffset, change.segmentNumber);
}
});
}
private void restoreEmptyVariables(IntArrayList indices) {
List<TextRange> rangesToRemove = ContainerUtil.newArrayList();
for (int i = 0; i < indices.size(); i++) {
int index = indices.get(i);
rangesToRemove.add(TextRange.create(mySegments.getSegmentStart(index), mySegments.getSegmentEnd(index)));
}
Collections.sort(rangesToRemove, (o1, o2) -> {
int startDiff = o2.getStartOffset() - o1.getStartOffset();
return startDiff != 0 ? startDiff : o2.getEndOffset() - o1.getEndOffset();
});
DocumentUtil.executeInBulk(myDocument, true, () -> {
if (isDisposed()) {
return;
}
for (TextRange range : rangesToRemove) {
myDocument.deleteString(range.getStartOffset(), range.getEndOffset());
}
});
}
/**
* Transforms an LSP position to an editor offset
*
* @param editor The editor
* @param pos The LSPPos
* @return The offset
*/
public static int LSPPosToOffset(Editor editor, Position pos) {
return computableReadAction(() -> {
try {
if (editor.isDisposed()) {
return -1;
}
Document doc = editor.getDocument();
int line = Math.max(0, Math.min(pos.getLine(), doc.getLineCount()));
String lineText = doc.getText(DocumentUtil.getLineTextRange(doc, line));
String lineTextForPosition = !lineText.isEmpty() ?
lineText.substring(0, min(lineText.length(), pos.getCharacter())) :
"";
int tabs = StringUtil.countChars(lineTextForPosition, '\t');
int tabSize = editor.getSettings().getTabSize(editor.getProject());
int column = tabs * tabSize + lineTextForPosition.length() - tabs;
int offset = editor.logicalPositionToOffset(new LogicalPosition(line, column));
if (pos.getCharacter() >= lineText.length()) {
LOG.warn(String.format("LSPPOS outofbounds : %s line : %s column : %d offset : %d", pos,
lineText, column, offset));
}
int docLength = doc.getTextLength();
if (offset > docLength) {
LOG.warn(String.format("Offset greater than text length : %d > %d", offset, docLength));
}
return Math.min(Math.max(offset, 0), docLength);
} catch (IndexOutOfBoundsException e) {
return -1;
}
});
}
/**
* Finds the start offset of visual line at which given offset is located, not taking soft wraps into account.
*/
public static int getNotFoldedLineStartOffset(@Nonnull Editor editor, int offset) {
while (true) {
offset = DocumentUtil.getLineStartOffset(offset, editor.getDocument());
FoldRegion foldRegion = editor.getFoldingModel().getCollapsedRegionAtOffset(offset - 1);
if (foldRegion == null || foldRegion.getStartOffset() >= offset) {
break;
}
offset = foldRegion.getStartOffset();
}
return offset;
}
static void doIndent(final int endIndex, final int startIndex, final Document document, final Project project, final Editor editor,
final int blockIndent) {
final int[] caretOffset = {editor.getCaretModel().getOffset()};
boolean bulkMode = endIndex - startIndex > 50;
DocumentUtil.executeInBulk(document, bulkMode, ()-> {
List<Integer> nonModifiableLines = new ArrayList<>();
if (project != null) {
PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(document);
IndentStrategy indentStrategy = LanguageIndentStrategy.getIndentStrategy(file);
if (!LanguageIndentStrategy.isDefault(indentStrategy)) {
for (int i = startIndex; i <= endIndex; i++) {
if (!canIndent(document, file, i, indentStrategy)) {
nonModifiableLines.add(i);
}
}
}
}
for(int i=startIndex; i<=endIndex; i++) {
if (!nonModifiableLines.contains(i)) {
caretOffset[0] = EditorActionUtil.indentLine(project, editor, i, blockIndent, caretOffset[0]);
}
}
});
editor.getCaretModel().moveToOffset(caretOffset[0]);
}
private static int processIndents(Document document, int tabSize, TextRange textRange, IndentBuilder indentBuilder) {
int[] changedLines = {0};
DocumentUtil.executeInBulk(document, true, () -> {
int startLine = document.getLineNumber(textRange.getStartOffset());
int endLine = document.getLineNumber(textRange.getEndOffset());
for (int line = startLine; line <= endLine; line++) {
int indent = 0;
final int lineStart = document.getLineStartOffset(line);
final int lineEnd = document.getLineEndOffset(line);
int indentEnd = lineEnd;
for(int offset = Math.max(lineStart, textRange.getStartOffset()); offset < lineEnd; offset++) {
char c = document.getCharsSequence().charAt(offset);
if (c == ' ') {
indent++;
}
else if (c == '\t') {
indent = ((indent / tabSize) + 1) * tabSize;
}
else {
indentEnd = offset;
break;
}
}
if (indent > 0) {
String oldIndent = document.getCharsSequence().subSequence(lineStart, indentEnd).toString();
String newIndent = indentBuilder.buildIndent(indent, tabSize);
if (!oldIndent.equals(newIndent)) {
document.replaceString(lineStart, indentEnd, newIndent);
changedLines[0]++;
}
}
}
});
return changedLines[0];
}
public static void deleteCharAtCaret(Editor editor) {
int lineNumber = editor.getCaretModel().getLogicalPosition().line;
int afterLineEnd = EditorModificationUtil.calcAfterLineEnd(editor);
Document document = editor.getDocument();
int offset = editor.getCaretModel().getOffset();
if (afterLineEnd < 0
// There is a possible case that caret is located right before the soft wrap position at the last logical line
// (popular use case with the soft wraps at the commit message dialog).
|| (offset < document.getTextLength() - 1 && editor.getSoftWrapModel().getSoftWrap(offset) != null)) {
FoldRegion region = editor.getFoldingModel().getCollapsedRegionAtOffset(offset);
if (region != null && region.shouldNeverExpand()) {
document.deleteString(region.getStartOffset(), region.getEndOffset());
editor.getCaretModel().moveToOffset(region.getStartOffset());
}
else {
document.deleteString(offset, DocumentUtil.getNextCodePointOffset(document, offset));
}
return;
}
if (lineNumber + 1 >= document.getLineCount()) return;
// Do not group delete newline and other deletions.
CommandProcessor commandProcessor = CommandProcessor.getInstance();
commandProcessor.setCurrentCommandGroupId(null);
int nextLineStart = document.getLineStartOffset(lineNumber + 1);
int nextLineEnd = document.getLineEndOffset(lineNumber + 1);
if (nextLineEnd - nextLineStart > 0) {
StringBuilder buf = new StringBuilder();
StringUtil.repeatSymbol(buf, ' ', afterLineEnd);
document.insertString(getCaretLineStart(editor) + getCaretLineLength(editor), buf.toString());
nextLineStart = document.getLineStartOffset(lineNumber + 1);
}
int thisLineEnd = document.getLineEndOffset(lineNumber);
document.deleteString(thisLineEnd, nextLineStart);
}
@Nullable
@Override
public Rectangle getBounds() {
int targetOffset = DocumentUtil.getLineEndOffset(getOffset(), myEditor.getDocument());
if (myEditor.getFoldingModel().isOffsetCollapsed(targetOffset)) return null;
Point pos = getPosition();
return new Rectangle(pos.x, pos.y, getWidthInPixels(), getHeightInPixels());
}
@Nonnull
Point2D offsetToXY(int offset, boolean leanTowardsLargerOffsets, boolean beforeSoftWrap) {
offset = Math.max(0, Math.min(myDocument.getTextLength(), offset));
offset = DocumentUtil.alignToCodePointBoundary(myDocument, offset);
int logicalLine = myDocument.getLineNumber(offset);
int visualLine = offsetToVisualLine(offset, beforeSoftWrap);
int visualLineStartOffset = visualLineToOffset(visualLine);
int y = visualLineToY(visualLine);
float x = getStartX(logicalLine);
if (myDocument.getTextLength() > 0) {
boolean firstFragment = true;
for (VisualLineFragmentsIterator.Fragment fragment : VisualLineFragmentsIterator.create(myView, offset, beforeSoftWrap, true)) {
if (firstFragment && offset == visualLineStartOffset && !leanTowardsLargerOffsets) {
x = fragment.getStartX();
break;
}
firstFragment = false;
int minOffset = fragment.getMinOffset();
int maxOffset = fragment.getMaxOffset();
if (fragment.getCurrentInlay() == null && (offset > minOffset && offset < maxOffset || offset == minOffset && leanTowardsLargerOffsets || offset == maxOffset && !leanTowardsLargerOffsets)) {
x = fragment.offsetToX(offset);
break;
}
else {
x = fragment.getEndX();
}
}
}
return new Point2D.Double(x, y);
}
public WrapElementMeasuringIterator(@Nonnull EditorView view, int startOffset, int endOffset) {
super(view.getEditor(), startOffset, endOffset);
myView = view;
myDocument = view.getEditor().getDocument();
inlineInlays = view.getEditor().getInlayModel().getInlineElementsInRange(startOffset, endOffset);
afterLineEndInlays = view.getEditor().getInlayModel().getAfterLineEndElementsInRange(DocumentUtil.getLineStartOffset(startOffset, myDocument), endOffset);
}
@Override
public void documentChanged(@Nonnull DocumentEvent event) {
myDuringDocumentUpdate = false;
if (myDocument.isInBulkUpdate()) return;
doInvalidateRange(myDocumentChangeStartOffset, myDocumentChangeEndOffset);
if (myAfterLineEndInlayUpdated) {
int lineEndOffset = DocumentUtil.getLineEndOffset(myDocumentChangeEndOffset, myDocument);
doInvalidateRange(lineEndOffset, lineEndOffset);
}
assertValidState();
}
private void onLineInlayUpdate(@Nonnull Inlay inlay) {
if (myDuringDocumentUpdate) {
if (inlay.getPlacement() == Inlay.Placement.AFTER_LINE_END) {
myAfterLineEndInlayUpdated = true;
}
return;
}
int offset = inlay.getOffset();
if (inlay.getPlacement() == Inlay.Placement.AFTER_LINE_END) {
offset = DocumentUtil.getLineEndOffset(offset, myDocument);
}
doInvalidateRange(offset, offset);
}
@Override
protected void changedUpdateImpl(@Nonnull DocumentEvent e) {
myEditor.getInlayModel().myPutMergedIntervalsAtBeginning = intervalStart() == e.getOffset();
super.changedUpdateImpl(e);
if (isValid() && DocumentUtil.isInsideSurrogatePair(getDocument(), intervalStart())) {
invalidate(e);
}
}
@Override
protected void onReTarget(int startOffset, int endOffset, int destOffset) {
InlayModelImpl inlayModel = myEditor.getInlayModel();
inlayModel.myPutMergedIntervalsAtBeginning = intervalStart() == endOffset;
if (DocumentUtil.isInsideSurrogatePair(getDocument(), getOffset())) {
inlayModel.myMoveInProgress = true;
try {
invalidate("moved inside surrogate pair on retarget");
}
finally {
inlayModel.myMoveInProgress = false;
}
}
}
@Override
protected void onReTarget(int startOffset, int endOffset, int destOffset) {
int offset = intervalStart();
if (DocumentUtil.isInsideSurrogatePair(getDocument(), offset)) {
setIntervalStart(offset - 1);
setIntervalEnd(offset - 1);
}
}