Java Code Examples for com.intellij.openapi.editor.event.DocumentEvent#getOffset()

The following examples show how to use com.intellij.openapi.editor.event.DocumentEvent#getOffset() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: RangeMarkerImpl.java    From consulo with Apache License 2.0 6 votes vote down vote up
@Nullable
private static TextRange processIfOnePoint(@Nonnull DocumentEvent e, int intervalStart, boolean greedyRight, boolean stickyRight) {
  int offset = e.getOffset();
  int oldLength = e.getOldLength();
  int oldEnd = offset + oldLength;
  if (offset < intervalStart && intervalStart < oldEnd) {
    return null;
  }

  if (offset == intervalStart && oldLength == 0) {
    if (greedyRight) {
      return new UnfairTextRange(intervalStart, intervalStart + e.getNewLength());
    }
    else if (stickyRight) {
      return new UnfairTextRange(intervalStart + e.getNewLength(), intervalStart + e.getNewLength());
    }
  }

  if (intervalStart > oldEnd || intervalStart == oldEnd && oldLength > 0) {
    return new UnfairTextRange(intervalStart + e.getNewLength() - oldLength, intervalStart + e.getNewLength() - oldLength);
  }

  return new UnfairTextRange(intervalStart, intervalStart);
}
 
Example 2
Source File: LineStatusTrackerBase.java    From consulo with Apache License 2.0 6 votes vote down vote up
@Nonnull
private int[] fixRanges(@Nonnull DocumentEvent e, int line1, int line2) {
  CharSequence document = myDocument.getCharsSequence();
  int offset = e.getOffset();

  if (e.getOldLength() == 0 && e.getNewLength() != 0) {
    if (StringUtil.endsWithChar(e.getNewFragment(), '\n') && isNewline(offset - 1, document)) {
      return new int[]{line1, line2 - 1};
    }
    if (StringUtil.startsWithChar(e.getNewFragment(), '\n') && isNewline(offset + e.getNewLength(), document)) {
      return new int[]{line1 + 1, line2};
    }
  }
  if (e.getOldLength() != 0 && e.getNewLength() == 0) {
    if (StringUtil.endsWithChar(e.getOldFragment(), '\n') && isNewline(offset - 1, document)) {
      return new int[]{line1, line2 - 1};
    }
    if (StringUtil.startsWithChar(e.getOldFragment(), '\n') && isNewline(offset + e.getNewLength(), document)) {
      return new int[]{line1 + 1, line2};
    }
  }

  return new int[]{line1, line2};
}
 
Example 3
Source File: DocumentChangesCollector.java    From consulo with Apache License 2.0 6 votes vote down vote up
private void mergeChangesIfNecessary(DocumentEvent event) {
  // There is a possible case that we had more than one scattered change (e.g. (3; 5) and (8; 10)) and current document change affects
  // both of them (e.g. remove all symbols from offset (4; 9)). We have two changes then: (3; 4) and (4; 5) and want to merge them
  // into a single one.
  if (myChanges.size() < 2) {
    return;
  }
  TextChangeImpl next = myChanges.get(myChanges.size() - 1);
  for (int i = myChanges.size() - 2; i >= 0; i--) {
    TextChangeImpl current = myChanges.get(i);
    if (current.getEnd() < event.getOffset()) {
      // Assuming that change ranges are always kept at normalized form.
      break;
    }
    if (current.getEnd() == next.getStart()) {
      myChanges.set(i, next = new TextChangeImpl(current.getText().toString() + next.getText(), current.getStart(), next.getEnd()));
      myChanges.remove(i + 1);
    }
    else {
      next = current;
    }
  }
}
 
Example 4
Source File: EditorComponentImpl.java    From consulo with Apache License 2.0 6 votes vote down vote up
@Override
public void documentChanged(final DocumentEvent event) {
  final Integer pos = event.getOffset();
  if (ApplicationManager.getApplication().isDispatchThread()) {
    firePropertyChange(ACCESSIBLE_TEXT_PROPERTY, null, pos);
    if (SystemInfo.isMac) {
      // For MacOSX we also need to fire a JTextComponent event to anyone listening
      // to our Document, since *that* rather than the accessible property
      // change is the only way to trigger a speech update
      fireJTextComponentDocumentChange(event);
    }
  } else {
    ApplicationManager.getApplication().invokeLater(() -> {
      firePropertyChange(ACCESSIBLE_TEXT_PROPERTY, null, pos);
      fireJTextComponentDocumentChange(event);
    });
  }
}
 
Example 5
Source File: DocumentContentSynchronizer.java    From intellij-quarkus with Eclipse Public License 2.0 5 votes vote down vote up
/**
 * Convert IntelliJ {@link DocumentEvent} to LS according {@link TextDocumentSyncKind}.
 *
 * @param event
 *            IntelliJ {@link DocumentEvent}
 * @return true if change event is ready to be sent
 */
private boolean createChangeEvent(DocumentEvent event) {
    changeParams = new DidChangeTextDocumentParams(new VersionedTextDocumentIdentifier(), Collections.singletonList(new TextDocumentContentChangeEvent()));
    changeParams.getTextDocument().setUri(fileUri.toString());

    Document document = event.getDocument();
    TextDocumentContentChangeEvent changeEvent = null;
    TextDocumentSyncKind syncKind = getTextDocumentSyncKind();
    switch (syncKind) {
        case None:
            return false;
        case Full:
            changeParams.getContentChanges().get(0).setText(event.getDocument().getText());
            break;
        case Incremental:
            changeEvent = changeParams.getContentChanges().get(0);
            CharSequence newText = event.getNewFragment();
            int offset = event.getOffset();
            int length = event.getOldLength();
            try {
                // try to convert the Eclipse start/end offset to LS range.
                Range range = new Range(LSPIJUtils.toPosition(offset, document),
                        LSPIJUtils.toPosition(offset + length, document));
                changeEvent.setRange(range);
                changeEvent.setText(newText.toString());
                changeEvent.setRangeLength(length);
            } finally {
            }
            break;
    }
    return true;
}
 
Example 6
Source File: PersistentRangeMarkerUtil.java    From consulo with Apache License 2.0 5 votes vote down vote up
/**
 * Answers if document region identified by the given range marker should be translated via diff algorithm on document change
 * identified by the given event.
 *
 * @param e             event that describes document change
 * @param rangeStart    target range marker start, for which update strategy should be selected
 * @param rangeEnd      target range marker end
 * @return              {@code true} if target document range referenced by the given range marker should be translated via
 *                      diff algorithm; {@code false} otherwise
 */
static boolean shouldTranslateViaDiff(@Nonnull DocumentEvent e, int rangeStart, int rangeEnd) {
  if (e.isWholeTextReplaced()) {
    // Perform translation if the whole text is replaced.
    return true;
  }

  if (e.getOffset() >= rangeEnd || e.getOffset() + e.getOldLength() <= rangeStart) {
    // Don't perform complex processing if the change doesn't affect target range.
    return false;
  }

  // Perform complex processing only if significant document part is updated.
  return (Math.max(e.getNewLength(), e.getOldLength()) * 1.0) / e.getDocument().getTextLength() >= 0.8;
}
 
Example 7
Source File: FrozenDocument.java    From consulo with Apache License 2.0 5 votes vote down vote up
public FrozenDocument applyEvent(DocumentEvent event, int newStamp) {
  final int offset = event.getOffset();
  final int oldEnd = offset + event.getOldLength();
  ImmutableCharSequence newText = myText.delete(offset, oldEnd).insert(offset, event.getNewFragment());
  LineSet newLineSet = getLineSet().update(myText, offset, oldEnd, event.getNewFragment(), event.isWholeTextReplaced());
  return new FrozenDocument(newText, newLineSet, newStamp, null);
}
 
Example 8
Source File: OffsetTranslator.java    From consulo with Apache License 2.0 5 votes vote down vote up
@Nullable
private static Integer translateOffset(int offset, DocumentEvent event) {
  if (event.getOffset() < offset && offset < event.getOffset() + event.getNewLength()) {
    if (event.getOldLength() == 0) {
      return event.getOffset();
    }

    return null;
  }

  return offset <= event.getOffset() ? offset : offset - event.getNewLength() + event.getOldLength();
}
 
Example 9
Source File: DocumentChangesCollector.java    From consulo with Apache License 2.0 5 votes vote down vote up
/**
 * Updates current object's state on the basis of the given event assuming that there are no stored change ranges that
 * start after offset denoted by the given event.
 *
 * @param event     event for just occurred document change
 * @param oldText   our main idea is to merge all changes in order to have aggregated change against original document. So, there is
 *                  a possible case that subsequent change affects text inserted by the previous one. We don't want to reflect that
 *                  at aggregated change as it didn't appear in initial document. Hence, we have a mutable symbols buffer that holds
 *                  symbols from initial document affected by the given change
 */
private void updateChanges(DocumentEvent event, StringBuilder oldText) {
  int i = findIndex(event.getOffset());
  int endOffset = event.getOffset() + event.getNewLength();
  TextChangeImpl change = new TextChangeImpl(oldText, event.getOffset(), endOffset);
  if (i < 0) {
    myChanges.add(change);
  }
  else {
    myChanges.add(i, change);
  }
}
 
Example 10
Source File: FoldRegionImpl.java    From consulo with Apache License 2.0 5 votes vote down vote up
@Override
protected void changedUpdateImpl(@Nonnull DocumentEvent e) {
  if (isValid()) {
    int oldStart = intervalStart();
    int oldEnd = intervalEnd();
    int changeStart = e.getOffset();
    int changeEnd = e.getOffset() + e.getOldLength();
    if (changeStart < oldEnd && changeEnd > oldStart) myDocumentRegionWasChanged = true;
  }
  super.changedUpdateImpl(e);
  if (isValid()) {
    alignToSurrogateBoundaries();
  }
}
 
Example 11
Source File: InlineInlayImpl.java    From consulo with Apache License 2.0 5 votes vote down vote up
@Override
protected void changedUpdateImpl(@Nonnull DocumentEvent e) {
  myEditor.getInlayModel().myPutMergedIntervalsAtBeginning = intervalStart() == e.getOffset();
  super.changedUpdateImpl(e);
  if (isValid() && DocumentUtil.isInsideSurrogatePair(getDocument(), intervalStart())) {
    invalidate(e);
  }
}
 
Example 12
Source File: EditorSizeManager.java    From consulo with Apache License 2.0 5 votes vote down vote up
@Override
public void beforeDocumentChange(@Nonnull DocumentEvent event) {
  myAfterLineEndInlayUpdated = false;
  myDuringDocumentUpdate = true;
  if (myDocument.isInBulkUpdate()) return;
  myDocumentChangeStartOffset = event.getOffset();
  myDocumentChangeEndOffset = event.getOffset() + event.getNewLength();
}
 
Example 13
Source File: StatisticsUpdate.java    From consulo with Apache License 2.0 5 votes vote down vote up
public void trackStatistics(InsertionContext context) {
  if (ourPendingUpdate != this) {
    return;
  }

  if (!context.getOffsetMap().containsOffset(CompletionInitializationContext.START_OFFSET)) {
    return;
  }

  final Document document = context.getDocument();
  int startOffset = context.getStartOffset();
  int tailOffset = context.getEditor().getCaretModel().getOffset();
  if (startOffset < 0 || tailOffset <= startOffset) {
    return;
  }

  final RangeMarker marker = document.createRangeMarker(startOffset, tailOffset);
  final DocumentAdapter listener = new DocumentAdapter() {
    @Override
    public void beforeDocumentChange(DocumentEvent e) {
      if (!marker.isValid() || e.getOffset() > marker.getStartOffset() && e.getOffset() < marker.getEndOffset()) {
        cancelLastCompletionStatisticsUpdate();
      }
    }
  };

  ourStatsAlarm.addRequest(() -> {
    if (ourPendingUpdate == this) {
      applyLastCompletionStatisticsUpdate();
    }
  }, 20 * 1000);

  document.addDocumentListener(listener);
  Disposer.register(this, () -> {
    document.removeDocumentListener(listener);
    marker.dispose();
    ourStatsAlarm.cancelAllRequests();
  });
}
 
Example 14
Source File: DocumentFragmentContent.java    From consulo with Apache License 2.0 5 votes vote down vote up
@Override
protected void onDocumentChanged2(@Nonnull DocumentEvent event) {
  if (!myRangeMarker.isValid()) return;
  if (!myDocument1.isWritable()) return;

  CharSequence newText = event.getNewFragment();
  int originalOffset = event.getOffset() + myRangeMarker.getStartOffset();
  int originalEnd = originalOffset + event.getOldLength();
  replaceString(myDocument1, originalOffset, originalEnd, newText);
}
 
Example 15
Source File: LocalClosedEditorModificationHandler.java    From saros with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Adjusts the annotations for the resource represented by the changed document if it is not
 * currently open in an editor. If it is currently open in an editor, this will be done
 * automatically by Intellij.
 *
 * @param event the event to react to
 * @see DocumentListener#beforeDocumentChange(DocumentEvent)
 */
private void cleanUpAnnotations(@NotNull DocumentEvent event) {
  Document document = event.getDocument();

  IFile file = getFile(document);

  if (file == null) {
    return;
  }

  int offset = event.getOffset();
  String newText = event.getNewFragment().toString();
  String replacedText = event.getOldFragment().toString();

  if (!ProjectAPI.isOpen(project, document)) {

    int replacedTextLength = replacedText.length();
    if (replacedTextLength > 0) {
      annotationManager.moveAnnotationsAfterDeletion(file, offset, offset + replacedTextLength);
    }

    int newTextLength = newText.length();
    if (newTextLength > 0) {
      annotationManager.moveAnnotationsAfterAddition(file, offset, offset + newTextLength);
    }
  }
}
 
Example 16
Source File: DesktopCaretImpl.java    From consulo with Apache License 2.0 4 votes vote down vote up
private boolean needToShiftWhiteSpaces(final DocumentEvent e) {
  return e.getOffset() > 0 &&
         Character.isWhitespace(e.getDocument().getImmutableCharSequence().charAt(e.getOffset() - 1)) &&
         CharArrayUtil.containsOnlyWhiteSpaces(e.getNewFragment()) &&
         !CharArrayUtil.containLineBreaks(e.getNewFragment());
}
 
Example 17
Source File: DesktopCaretImpl.java    From consulo with Apache License 2.0 4 votes vote down vote up
@Override
protected void changedUpdateImpl(@Nonnull DocumentEvent e) {
  int oldOffset = intervalStart();
  super.changedUpdateImpl(e);
  if (isValid()) {
    // Under certain conditions, when text is inserted at caret position, we position caret at the end of inserted text.
    // Ideally, client code should be responsible for positioning caret after document modification, but in case of
    // postponed formatting (after PSI modifications), this is hard to implement, so a heuristic below is used.
    if (e.getOldLength() == 0 &&
        oldOffset == e.getOffset() &&
        !Boolean.TRUE.equals(myEditor.getUserData(DesktopEditorImpl.DISABLE_CARET_SHIFT_ON_WHITESPACE_INSERTION)) &&
        needToShiftWhiteSpaces(e)) {
      int afterInserted = e.getOffset() + e.getNewLength();
      setIntervalStart(afterInserted);
      setIntervalEnd(afterInserted);
    }
    int offset = intervalStart();
    if (DocumentUtil.isInsideSurrogatePair(getDocument(), offset)) {
      setIntervalStart(offset - 1);
      setIntervalEnd(offset - 1);
    }
  }
  else {
    setValid(true);
    int newOffset = Math.min(intervalStart(), e.getOffset() + e.getNewLength());
    if (!e.getDocument().isInBulkUpdate() && e.isWholeTextReplaced()) {
      try {
        final int line = ((DocumentEventImpl)e).translateLineViaDiff(myLogicalCaret.line);
        newOffset = myEditor.logicalPositionToOffset(new LogicalPosition(line, myLogicalCaret.column));
      }
      catch (FilesTooBigForDiffException ex) {
        LOG.info(ex);
      }
    }
    newOffset = DocumentUtil.alignToCodePointBoundary(getDocument(), newOffset);
    setIntervalStart(newOffset);
    setIntervalEnd(newOffset);
  }
  myLogicalColumnAdjustment = 0;
  myVisualColumnAdjustment = 0;
  if (oldOffset >= e.getOffset() && oldOffset <= e.getOffset() + e.getOldLength() && e.getNewLength() == 0 && e.getOldLength() > 0) {
    int inlaysToTheLeft = myEditor.getInlayModel().getInlineElementsInRange(e.getOffset(), e.getOffset()).size();
    boolean hasInlaysToTheRight = myEditor.getInlayModel().hasInlineElementAt(e.getOffset() + e.getOldLength());
    if (inlaysToTheLeft > 0 || hasInlaysToTheRight) {
      myLeansTowardsLargerOffsets = !hasInlaysToTheRight;
      myVisualColumnAdjustment = hasInlaysToTheRight ? inlaysToTheLeft : 0;
    }
    else if (oldOffset == e.getOffset()) {
      myLeansTowardsLargerOffsets = false;
    }
  }
}
 
Example 18
Source File: RangeMarkerImpl.java    From consulo with Apache License 2.0 4 votes vote down vote up
@Nullable
static TextRange applyChange(@Nonnull DocumentEvent e, int intervalStart, int intervalEnd, boolean isGreedyToLeft, boolean isGreedyToRight, boolean isStickingToRight) {
  if (intervalStart == intervalEnd) {
    return processIfOnePoint(e, intervalStart, isGreedyToRight, isStickingToRight);
  }

  final int offset = e.getOffset();
  final int oldLength = e.getOldLength();
  final int newLength = e.getNewLength();

  // changes after the end.
  if (intervalEnd < offset) {
    return new UnfairTextRange(intervalStart, intervalEnd);
  }
  if (!isGreedyToRight && intervalEnd == offset) {
    // handle replaceString that was minimized and resulted in insertString at the range end
    if (e instanceof DocumentEventImpl && oldLength == 0 && ((DocumentEventImpl)e).getInitialStartOffset() < offset) {
      return new UnfairTextRange(intervalStart, intervalEnd + newLength);
    }
    return new UnfairTextRange(intervalStart, intervalEnd);
  }

  // changes before start
  if (intervalStart > offset + oldLength) {
    return new UnfairTextRange(intervalStart + newLength - oldLength, intervalEnd + newLength - oldLength);
  }
  if (!isGreedyToLeft && intervalStart == offset + oldLength) {
    // handle replaceString that was minimized and resulted in insertString at the range start
    if (e instanceof DocumentEventImpl && oldLength == 0 && ((DocumentEventImpl)e).getInitialStartOffset() + ((DocumentEventImpl)e).getInitialOldLength() > offset) {
      return new UnfairTextRange(intervalStart, intervalEnd + newLength);
    }
    return new UnfairTextRange(intervalStart + newLength - oldLength, intervalEnd + newLength - oldLength);
  }

  // Changes inside marker's area. Expand/collapse.
  if (intervalStart <= offset && intervalEnd >= offset + oldLength) {
    return new ProperTextRange(intervalStart, intervalEnd + newLength - oldLength);
  }

  // At this point we either have (myStart xor myEnd inside changed area) or whole area changed.

  // Replacing prefix or suffix...
  if (intervalStart >= offset && intervalStart <= offset + oldLength && intervalEnd > offset + oldLength) {
    return new ProperTextRange(offset + newLength, intervalEnd + newLength - oldLength);
  }

  if (intervalEnd >= offset && intervalEnd <= offset + oldLength && intervalStart < offset) {
    return new UnfairTextRange(intervalStart, offset);
  }

  return null;
}
 
Example 19
Source File: EditorEventManager.java    From lsp4intellij with Apache License 2.0 4 votes vote down vote up
public void documentChanged(DocumentEvent event) {
    if (editor.isDisposed()) {
        return;
    }
    if (event.getDocument() == editor.getDocument()) {
        //Todo - restore when adding hover support
        // long predTime = System.nanoTime(); //So that there are no hover events while typing
        changesParams.getTextDocument().setVersion(version++);

        if (syncKind == TextDocumentSyncKind.Incremental) {
            TextDocumentContentChangeEvent changeEvent = changesParams.getContentChanges().get(0);
            CharSequence newText = event.getNewFragment();
            int offset = event.getOffset();
            int newTextLength = event.getNewLength();
            Position lspPosition = DocumentUtils.offsetToLSPPos(editor, offset);
            int startLine = lspPosition.getLine();
            int startColumn = lspPosition.getCharacter();
            CharSequence oldText = event.getOldFragment();

            //if text was deleted/replaced, calculate the end position of inserted/deleted text
            int endLine, endColumn;
            if (oldText.length() > 0) {
                endLine = startLine + StringUtil.countNewLines(oldText);
                String[] oldLines = oldText.toString().split("\n");
                int oldTextLength = oldLines.length == 0 ? 0 : oldLines[oldLines.length - 1].length();
                endColumn = oldLines.length == 1 ? startColumn + oldTextLength : oldTextLength;
            } else { //if insert or no text change, the end position is the same
                endLine = startLine;
                endColumn = startColumn;
            }
            Range range = new Range(new Position(startLine, startColumn), new Position(endLine, endColumn));
            changeEvent.setRange(range);
            changeEvent.setRangeLength(newTextLength);
            changeEvent.setText(newText.toString());
        } else if (syncKind == TextDocumentSyncKind.Full) {
            changesParams.getContentChanges().get(0).setText(editor.getDocument().getText());
        }
        requestManager.didChange(changesParams);
    } else {
        LOG.error("Wrong document for the EditorEventManager");
    }
}
 
Example 20
Source File: IncrementalCacheUpdateEvent.java    From consulo with Apache License 2.0 2 votes vote down vote up
/**
 * Creates new {@code IncrementalCacheUpdateEvent} object on the basis on the given event object that describes
 * document change that caused cache update.
 * <p/>
 * This constructor is assumed to be used <b>before</b> the document change.
 *
 * @param event object that describes document change that caused cache update
 */
IncrementalCacheUpdateEvent(@Nonnull DocumentEvent event, @Nonnull DesktopEditorImpl editor) {
  this(event.getOffset(), event.getOffset() + event.getOldLength(), event.getOffset() + event.getNewLength(), editor);
}