Search in sources :

Example 76 with DocumentEx

use of com.intellij.openapi.editor.ex.DocumentEx in project intellij-community by JetBrains.

the class ArrangementEngine method arrange.

/**
   * Arranges given PSI root contents that belong to the given ranges.
   *
   * @param file    target PSI root
   * @param ranges  target ranges to use within the given root
   */
public void arrange(@NotNull PsiFile file, @NotNull Collection<TextRange> ranges, @Nullable final ArrangementCallback callback) {
    myCodeChanged = false;
    final Document document = PsiDocumentManager.getInstance(file.getProject()).getDocument(file);
    if (document == null) {
        return;
    }
    final Rearranger<?> rearranger = Rearranger.EXTENSION.forLanguage(file.getLanguage());
    if (rearranger == null) {
        return;
    }
    final CodeStyleSettings settings = CodeStyleSettingsManager.getInstance(file.getProject()).getCurrentSettings();
    ArrangementSettings arrangementSettings = settings.getCommonSettings(file.getLanguage()).getArrangementSettings();
    if (arrangementSettings == null && rearranger instanceof ArrangementStandardSettingsAware) {
        arrangementSettings = ((ArrangementStandardSettingsAware) rearranger).getDefaultSettings();
    }
    if (arrangementSettings == null) {
        return;
    }
    final DocumentEx documentEx;
    if (document instanceof DocumentEx && !((DocumentEx) document).isInBulkUpdate()) {
        documentEx = (DocumentEx) document;
    } else {
        documentEx = null;
    }
    final Context<? extends ArrangementEntry> context;
    DumbService.getInstance(file.getProject()).setAlternativeResolveEnabled(true);
    try {
        context = Context.from(rearranger, document, file, ranges, arrangementSettings, settings);
    } finally {
        DumbService.getInstance(file.getProject()).setAlternativeResolveEnabled(false);
    }
    ApplicationManager.getApplication().runWriteAction(() -> {
        if (documentEx != null) {
        //documentEx.setInBulkUpdate(true);
        }
        try {
            doArrange(context);
            if (callback != null) {
                callback.afterArrangement(context.moveInfos);
            }
        } finally {
            if (documentEx != null) {
            //documentEx.setInBulkUpdate(false);
            }
        }
    });
}
Also used : DocumentEx(com.intellij.openapi.editor.ex.DocumentEx) CodeStyleSettings(com.intellij.psi.codeStyle.CodeStyleSettings) ArrangementStandardSettingsAware(com.intellij.psi.codeStyle.arrangement.std.ArrangementStandardSettingsAware) Document(com.intellij.openapi.editor.Document)

Example 77 with DocumentEx

use of com.intellij.openapi.editor.ex.DocumentEx in project intellij-community by JetBrains.

the class FileDocumentManagerImpl method reloadFromDisk.

@Override
public void reloadFromDisk(@NotNull final Document document) {
    ApplicationManager.getApplication().assertIsDispatchThread();
    final VirtualFile file = getFile(document);
    assert file != null;
    if (!fireBeforeFileContentReload(file, document)) {
        return;
    }
    final Project project = ProjectLocator.getInstance().guessProjectForFile(file);
    boolean[] isReloadable = { isReloadable(file, document, project) };
    if (isReloadable[0]) {
        CommandProcessor.getInstance().executeCommand(project, () -> ApplicationManager.getApplication().runWriteAction(new ExternalChangeAction.ExternalDocumentChange(document, project) {

            @Override
            public void run() {
                if (!isBinaryWithoutDecompiler(file)) {
                    LoadTextUtil.setCharsetWasDetectedFromBytes(file, null);
                    // reset BOM in case we had one and the external change stripped it away
                    file.setBOM(null);
                    file.setCharset(null, null, false);
                    boolean wasWritable = document.isWritable();
                    document.setReadOnly(false);
                    boolean tooLarge = FileUtilRt.isTooLarge(file.getLength());
                    CharSequence reloaded = tooLarge ? LoadTextUtil.loadText(file, getPreviewCharCount(file)) : LoadTextUtil.loadText(file);
                    isReloadable[0] = isReloadable(file, document, project);
                    if (isReloadable[0]) {
                        DocumentEx documentEx = (DocumentEx) document;
                        documentEx.replaceText(reloaded, file.getModificationStamp());
                    }
                    document.setReadOnly(!wasWritable);
                }
            }
        }), UIBundle.message("file.cache.conflict.action"), null, UndoConfirmationPolicy.REQUEST_CONFIRMATION);
    }
    if (isReloadable[0]) {
        myMultiCaster.fileContentReloaded(file, document);
    } else {
        unbindFileFromDocument(file, document);
        myMultiCaster.fileWithNoDocumentChanged(file);
    }
    myUnsavedDocuments.remove(document);
}
Also used : LightVirtualFile(com.intellij.testFramework.LightVirtualFile) DocumentEx(com.intellij.openapi.editor.ex.DocumentEx)

Example 78 with DocumentEx

use of com.intellij.openapi.editor.ex.DocumentEx in project intellij-community by JetBrains.

the class InlayModelImpl method addInlineElement.

@Nullable
@Override
public Inlay addInlineElement(int offset, @NotNull EditorCustomElementRenderer renderer) {
    ApplicationManager.getApplication().assertIsDispatchThread();
    DocumentEx document = myEditor.getDocument();
    if (DocumentUtil.isInsideSurrogatePair(document, offset))
        return null;
    offset = Math.max(0, Math.min(document.getTextLength(), offset));
    InlayImpl inlay = new InlayImpl(myEditor, offset, renderer);
    notifyAdded(inlay);
    return inlay;
}
Also used : DocumentEx(com.intellij.openapi.editor.ex.DocumentEx) Nullable(org.jetbrains.annotations.Nullable)

Example 79 with DocumentEx

use of com.intellij.openapi.editor.ex.DocumentEx in project intellij-community by JetBrains.

the class SettingsImpl method reinitDocumentIndentOptions.

private void reinitDocumentIndentOptions() {
    if (myEditor == null || myEditor.isViewer())
        return;
    final Project project = myEditor.getProject();
    final DocumentEx document = myEditor.getDocument();
    if (project == null || project.isDisposed())
        return;
    final PsiDocumentManager psiManager = PsiDocumentManager.getInstance(project);
    final PsiFile file = psiManager.getPsiFile(document);
    if (file == null)
        return;
    CodeStyleSettingsManager.updateDocumentIndentOptions(project, document);
}
Also used : DocumentEx(com.intellij.openapi.editor.ex.DocumentEx) Project(com.intellij.openapi.project.Project) PsiFile(com.intellij.psi.PsiFile) PsiDocumentManager(com.intellij.psi.PsiDocumentManager)

Example 80 with DocumentEx

use of com.intellij.openapi.editor.ex.DocumentEx in project intellij-community by JetBrains.

the class LexerEditorHighlighter method documentChanged.

@Override
public synchronized void documentChanged(DocumentEvent e) {
    try {
        final Document document = e.getDocument();
        CharSequence text = document.getImmutableCharSequence();
        if (document instanceof DocumentEx && ((DocumentEx) document).isInBulkUpdate()) {
            myText = null;
            mySegments.removeAll();
            return;
        }
        if (mySegments.getSegmentCount() == 0) {
            setText(text);
            return;
        }
        myText = text;
        int oldStartOffset = e.getOffset();
        final int segmentIndex = mySegments.findSegmentIndex(oldStartOffset) - 2;
        final int oldStartIndex = Math.max(0, segmentIndex);
        int startIndex = oldStartIndex;
        int data;
        do {
            data = mySegments.getSegmentData(startIndex);
            if (isInitialState(data) || startIndex == 0)
                break;
            startIndex--;
        } while (true);
        int startOffset = mySegments.getSegmentStart(startIndex);
        int newEndOffset = e.getOffset() + e.getNewLength();
        myLexer.start(text, startOffset, text.length(), myInitialState);
        int lastTokenStart = -1;
        int lastLexerState = -1;
        IElementType lastTokenType = null;
        while (myLexer.getTokenType() != null) {
            if (startIndex >= oldStartIndex)
                break;
            int tokenStart = myLexer.getTokenStart();
            int lexerState = myLexer.getState();
            if (tokenStart == lastTokenStart && lexerState == lastLexerState && myLexer.getTokenType() == lastTokenType) {
                throw new IllegalStateException("Lexer is not progressing after calling advance()");
            }
            int tokenEnd = myLexer.getTokenEnd();
            data = packData(myLexer.getTokenType(), lexerState);
            if (mySegments.getSegmentStart(startIndex) != tokenStart || mySegments.getSegmentEnd(startIndex) != tokenEnd || mySegments.getSegmentData(startIndex) != data) {
                break;
            }
            startIndex++;
            lastTokenType = myLexer.getTokenType();
            myLexer.advance();
            lastTokenStart = tokenStart;
            lastLexerState = lexerState;
        }
        /*
        Highlighting lexer is expected to periodically return to its "initial state" and
        so to denote valid starting points for incremental highlighting.

        If this requirement is unfulfiled, document has to be always re-analyzed from the beginning
        up to the point of modification,  which can hog CPU and make typing / editing very sluggish,
        especially at large offsets (with at least O(n) time complexity).

        As the faulty lexer implementations otherwise behave normally, it's often hard to spot the problem in the wild.
        Despite additng LexerTestCase.checkCorrectRestart and LexerTestCase.checkZeroState checks and fixing many lexers,
        it's still not so unusual to discover a further broken lexer through pure luck.

        The following runtime check reports cases when document has to be re-analyzed from 0 offset and
        the number of traversed tokens is greater than a predefined threshold.

        Because many highlighting lexers are implemented via the LayeredLexer which forces non-initial state
        (and thus suppresses incrementality) within layers, some false-positivess are probable.
        For example, it's possible to trigger the warning by creating a file with a really large comment
        right at the beginning, and then to modify text at the end of that comment.
        However, this seems to be a rather unusual use case, so that the gain from detecting faulty
        lexers (including third-party ones) justifies the check.

        In a sense, the warning is always righteous, as even with proper layered lexers there really is
        no incrementality within layers, which might lead to performance problem in corresponding cases.
       */
        if (ApplicationManager.getApplication().isInternal() && startOffset == 0 && startIndex > LEXER_INCREMENTALITY_THRESHOLD) {
            Class lexerClass = myLexer.getClass();
            if (!ourNonIncrementalLexers.contains(lexerClass)) {
                LOG.warn(String.format("%s is probably not incremental: no initial state throughout %d tokens", lexerClass.getName(), startIndex));
                ourNonIncrementalLexers.add(lexerClass);
            }
        }
        startOffset = mySegments.getSegmentStart(startIndex);
        int repaintEnd = -1;
        int insertSegmentCount = 0;
        int oldEndIndex = -1;
        lastTokenType = null;
        SegmentArrayWithData insertSegments = new SegmentArrayWithData();
        while (myLexer.getTokenType() != null) {
            int tokenStart = myLexer.getTokenStart();
            int lexerState = myLexer.getState();
            if (tokenStart == lastTokenStart && lexerState == lastLexerState && myLexer.getTokenType() == lastTokenType) {
                throw new IllegalStateException("Lexer is not progressing after calling advance()");
            }
            lastTokenStart = tokenStart;
            lastLexerState = lexerState;
            lastTokenType = myLexer.getTokenType();
            int tokenEnd = myLexer.getTokenEnd();
            data = packData(myLexer.getTokenType(), lexerState);
            if (tokenStart >= newEndOffset && lexerState == myInitialState) {
                int shiftedTokenStart = tokenStart - e.getNewLength() + e.getOldLength();
                int index = mySegments.findSegmentIndex(shiftedTokenStart);
                if (mySegments.getSegmentStart(index) == shiftedTokenStart && mySegments.getSegmentData(index) == data) {
                    repaintEnd = tokenStart;
                    oldEndIndex = index;
                    break;
                }
            }
            insertSegments.setElementAt(insertSegmentCount, tokenStart, tokenEnd, data);
            insertSegmentCount++;
            myLexer.advance();
        }
        final int shift = e.getNewLength() - e.getOldLength();
        if (repaintEnd > 0) {
            while (insertSegmentCount > 0 && oldEndIndex > startIndex) {
                if (!segmentsEqual(mySegments, oldEndIndex - 1, insertSegments, insertSegmentCount - 1, shift)) {
                    break;
                }
                insertSegmentCount--;
                oldEndIndex--;
                repaintEnd = insertSegments.getSegmentStart(insertSegmentCount);
                insertSegments.remove(insertSegmentCount, insertSegmentCount + 1);
            }
        }
        if (repaintEnd == -1) {
            repaintEnd = text.length();
        }
        if (oldEndIndex < 0) {
            oldEndIndex = mySegments.getSegmentCount();
        }
        mySegments.shiftSegments(oldEndIndex, shift);
        mySegments.replace(startIndex, oldEndIndex, insertSegments);
        if (insertSegmentCount == 0 || oldEndIndex == startIndex + 1 && insertSegmentCount == 1 && data == mySegments.getSegmentData(startIndex)) {
            return;
        }
        myEditor.repaint(startOffset, repaintEnd);
    } catch (ProcessCanceledException ex) {
        myText = null;
        mySegments.removeAll();
        throw ex;
    } catch (RuntimeException ex) {
        throw new InvalidStateException(this, "Error updating  after " + e, ex);
    }
}
Also used : DocumentEx(com.intellij.openapi.editor.ex.DocumentEx) IElementType(com.intellij.psi.tree.IElementType) SingleCharSequence(com.intellij.util.text.SingleCharSequence) MergingCharSequence(com.intellij.util.text.MergingCharSequence) ImmutableCharSequence(com.intellij.util.text.ImmutableCharSequence) Document(com.intellij.openapi.editor.Document) ProcessCanceledException(com.intellij.openapi.progress.ProcessCanceledException)

Aggregations

DocumentEx (com.intellij.openapi.editor.ex.DocumentEx)87 Document (com.intellij.openapi.editor.Document)12 NotNull (org.jetbrains.annotations.NotNull)8 RangeMarkerEx (com.intellij.openapi.editor.ex.RangeMarkerEx)7 Project (com.intellij.openapi.project.Project)7 TextRange (com.intellij.openapi.util.TextRange)7 LightVirtualFile (com.intellij.testFramework.LightVirtualFile)7 PsiFile (com.intellij.psi.PsiFile)6 Nullable (org.jetbrains.annotations.Nullable)5 EditorEx (com.intellij.openapi.editor.ex.EditorEx)4 VirtualFile (com.intellij.openapi.vfs.VirtualFile)4 MockVirtualFile (com.intellij.mock.MockVirtualFile)3 FoldRegion (com.intellij.openapi.editor.FoldRegion)3 PsiDocumentManager (com.intellij.psi.PsiDocumentManager)3 DocumentWindow (com.intellij.injected.editor.DocumentWindow)2 DocumentBulkUpdateListener (com.intellij.openapi.editor.ex.DocumentBulkUpdateListener)2 DocumentImpl (com.intellij.openapi.editor.impl.DocumentImpl)2 DocumentMarkupModel (com.intellij.openapi.editor.impl.DocumentMarkupModel)2 RangeHighlighter (com.intellij.openapi.editor.markup.RangeHighlighter)2 FileDocumentManagerAdapter (com.intellij.openapi.fileEditor.FileDocumentManagerAdapter)2